Будь ласка, використовуйте цей ідентифікатор, щоб цитувати або посилатися на цей матеріал: https://er.chdtu.edu.ua/handle/ChSTU/6189
Повний запис метаданих
Поле DCЗначенняМова
dc.contributor.advisorПідгорний, Микола Володимирович-
dc.contributor.authorКолісник, Максим Володимирович-
dc.date.accessioned2025-11-25T07:30:35Z-
dc.date.available2025-11-25T07:30:35Z-
dc.date.issued2024-06-12-
dc.identifier.urihttps://er.chdtu.edu.ua/handle/ChSTU/6189-
dc.description.abstractОнлайн-ігрові платформи набули великої популярності в останні роки, забезпечуючи доступ до безлічі ігор різного жанру та стилю. Однією з найпопулярніших серед них є платформа Roblox, яка дозволяє користувачам створювати та розгортати власні ігри. У цій роботі досліджується процес розробки 3-D гри на платформі Roblox. Метою кваліфікаційної роботи є розробка та реалізація повноцінної 3-D гри на платформі Roblox з використанням доступних інструментів та технологій. Об’єкт дослідження: програмування гри на онлайн платформі Roblox Предмет дослідження: гра «PLS DONATE X» Методи дослідження. Для вирішення поставлених завдань були застосовані наступні методи дослідження: теоретичний (аналіз літератури з проблеми дослідження); порівняльний – для здійснення порівнянь існуючих аналогів для гри.uk_UA
dc.language.isoukuk_UA
dc.subjectПРЕДМЕТНА ОБЛАСТЬuk_UA
dc.subjectГРАuk_UA
dc.subjectROBLOXuk_UA
dc.subjectROBLOX STUDIO.uk_UA
dc.titleКомп’ютерна 3-D гра “PLS DONATE X” на онлайн-платформі Robloxuk_UA
dc.typeBachelor Thesisuk_UA
Розташовується у зібраннях:122 Комп’ютерні науки (Комп’ютерні науки та прикладне програмування)

Файли цього матеріалу:
Файл Опис РозмірФормат 
Пояснювальна записка_Колісник Максим_КНС-2201_2023-2024.pdf
  Restricted Access
4.29 MBAdobe PDFПереглянути/Відкрити    Запит копії


Усі матеріали в архіві електронних ресурсів захищено авторським правом, усі права збережено.

Extracted text
 
МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ 
ЧЕРКАСЬКИЙ ДЕРЖАВНИЙ ТЕХНОЛОГІЧНИЙ УНІВЕРСИТЕТ 
 
Факультет інформаційних технологій і систем 
 
Кафедра комп’ютерних наук та системного аналізу 
 
 
 
 
 
 
Пояснювальна записка 
до кваліфікаційної роботи 
бакалавра 
(освітньо-кваліфікаційний рівень) 
 
на тему: «Комп’ютерна 3-D гра “PLS DONATE X” на онлайн-платформі Roblox» 
 
 
 
 
 
    Виконав: студент 4 курсу, групи КНС-2201 
                                                              
спеціальності  122  «Комп’ютерні науки» 
                                                                         (шифр і назва спеціальності) 
  
освітня програма «Комп’ютерні науки та                                                                                   
прикладне програмування 
                                                                      (назва освітньої програми)                                                                                         
 
Колісник Максим Володимирович 
 
Керівник __________   Підгорний М.В.     
                                                                          (прізвище та ініціали) 
 
Рецензент __________  Мельник В.П.       
                                                                          (прізвище та ініціали) 
    
 
 
 
 
 
 
 
 
Черкаси 2024 року 
  
 
Бланк завдання на кваліфікаційну роботу бакалавра студенту 
 
Черкаський державний технологічний університет 
Факультет Інформаційних технологій і систем 
Кафедра Комп’ютерних наук та системного аналізу 
Освітньо-кваліфікаційний рівень Бакалавр 
Спеціальність 122  – Комп’ютерні науки 
Освітня програма Комп’ютерні науки та прикладне програмування 
 
 
 
ЗАТВЕРДЖУЮ 
Завідувач кафедри КНСА  
_______________ Юрій ТРИУС 
«____» _____________ 2024 р. 
 
 
 
ЗАВДАННЯ 
на кваліфікаційну роботу бакалавра студенту 
Коліснику Максиму Володимировичу 
(прізвище, ім’я, по батькові) 
1. Тема роботи  Комп’ютерна 3-D гра “PLS DONATE X” на онлайн-платформі Roblox 
                                  
 
Керівник роботи     Підгорний М.В., к.т.н., доцент                    
(прізвище, ім’я, по батькові, науковий ступінь, вчене звання) 
затверджені наказом університету від «26» лютого 2024 р. №60/04. 
 
2. Строк подання студентом роботи до 10 червня 2024 року 
3. Вихідні дані до роботи:  
Практичні навики роботи з інформаційними ресурсами. 
Звіт з виробничої практики. Звіт з переддипломної практики. 
4. Зміст пояснювальної записки (перелік питань, що їх належить розробити): 
Вступ 
4.1. Дослідження предметної області. 
4.2. Проектування та розробка гри «PLS DONATE X»  
 
4.3. Тестування гри 
Висновки.  
 5. Перелік додатків (з точним зазначенням назв додатків): 
5.1. Додаток А. Специфікація 482.ЧДТУ. 42285-01. 
 5.2. Додаток Б. Текст програми. 
5.3. Додаток В. Інструкція користувача. 
5 .4. Презентація у вигляді 15 слайдів. 
 
 
 
6. Консультанти розділів роботи 
Прізвище, ініціали та Підпис, дата 
Розділ посада 
завдання видав завдання прийняв 
консультанта 
    
    
 
7. Дата видачі завдання 15.01.2024 
  
 
КАЛЕНДАРНИЙ ПЛАН 
Строк виконання 
№ з/п Назва етапів кваліфікаційної роботи бакалавра Примітка 
етапів роботи 
1 Видача завдання на кваліфікаційну роботу 
до 15.01.2024 Виконано 
бакалавра. 
2 Аналіз літературних джерел, об’єкту та 
до 12.02.2024 Виконано 
предмету дослідження. 
3 Написання теоретичного розділу 
до 18.03.2024 Виконано 
кваліфікаційної роботи бакалавра. 
4 Написання аналітичного розділу кваліфікаційної 
до 01.04.2024 Виконано 
роботи бакалавра. 
5 Написання практичних розділів й висновків до 
до 01.05.2024 Виконано 
кваліфікаційної роботи бакалавра. 
6 Передзахист кваліфікаційної роботи бакалавра 
до 03.06.2024 Виконано 
на засіданні кафедри КНСА. 
7 Подання роботи завідувачу кафедри КНСА. до 10.06.2024 Виконано 
8 Захист кваліфікаційної роботи бакалавра. 12.06.2024 Виконано 
    
    
    
 
 
Студент                                   _____________________________     Максим КОЛІСНИК 
(підпис)      
 
Керівник роботи                     ____________________________       Микола ПІДГОРНИЙ 
                                           (підпис) 
 
 
                                                               
  
 
РЕФЕРАТ 
Кваліфікаційна робота бакалавра містить: 41 с., 40 рис., 1 таблицю, 3 
використаних джерел, 2 додатки. 
Актуальність теми. Онлайн-ігрові платформи набули великої популярності в 
останні роки, забезпечуючи доступ до безлічі ігор різного жанру та стилю. Однією з 
найпопулярніших серед них є платформа Roblox, яка дозволяє користувачам 
створювати та розгортати власні ігри. У цій роботі досліджується процес розробки 
3-D гри на платформі Roblox. 
 
Мета роботи і задачі дослідження. Метою кваліфікаційної роботи є розробка 
та реалізація повноцінної 3-D гри на платформі Roblox з використанням доступних 
інструментів та технологій. 
 
Для досягнення поставленої мети були поставлені такі завдання: 
 дослідити предметну область; 
 виконати порівняльний аналіз існуючих ігор на онлайн платформі Roblox; 
 обрати програмно-технічні засоби для реалізації гри; 
 розробити гру «PLS DONATE X» та виконати її тестування. 
Об’єкт дослідження: програмування гри на онлайн платформі Roblox 
Предмет дослідження: гра «PLS DONATE X» 
Методи дослідження. Для вирішення поставлених завдань були застосовані 
наступні методи дослідження: теоретичний (аналіз літератури з проблеми 
дослідження); порівняльний – для здійснення порівнянь існуючих аналогів для гри. 
Перелік ключових слів: ПРЕДМЕТНА ОБЛАСТЬ, ГРА, ROBLOX, ROBLOX 
STUDIO. 
 
 
 
 
 
ABSTRACT 
Bachelor's qualification work contains: 41 pages, 40 figures, 1 table, 3 references, 
2 appendices. 
Relevance of the topic. Online gaming platforms have become very popular in 
recent years, providing access to many games of different genres and styles. One of the 
most popular among them is the roblox platform, which allows users to create and deploy 
their own games. This paper investigates the process of developing a 3-d game on the 
roblox platform. 
 
Purpose and objectives of the study. The purpose of the qualification work is to 
develop and implement a full-fledged 3-d game on the roblox platform using available 
tools and technologies. 
 
To achieve this goal, the following tasks were set: 
− research the subject area; 
− perform a comparative analysis of existing mobile applications for ordering 
food; 
− to select software and hardware for the game implementation; 
− develop the pls donate x game and test it; 
− Object of research: roblox online platform. 
Subject of research: the game "PLS DONATE X" 
Research methods. To solve the tasks, the following research methods were used: 
theoretical (analysis of the literature on the research problem); comparative - to compare 
existing analogues for game. 
List of keywords: SUBJECT AREA, GAME, ROBLOX, ROBLOX STUDIO. 
 
 7 
ЗМІСТ 
ПЕРЕЛІК УМОВНИХ ПОЗНАЧЕНЬ, СИМВОЛІВ, СКОРОЧЕНЬ І ТЕРМІНІВ ........ 8 
ВСТУП .................................................................................................................................. 9 
1 ДОСЛІДЖЕННЯ ПРЕДМЕТНОЇ ОБЛАСТІ ............................................................... 10 
1.1 Опис предметної області…………………… ......................................................... 10 
1.2 Огляд існуючих аналогів ......................................................................................... 12 
1.3 Аналіз порівнянь існуючих рішень розглянутих реалізацій та постановка 
завдання……………….. ................................................................................................ 15 
Висновки до розділу 1 ................................................................................................... 16 
2 ПРОЄКТУВАННЯ ГРИ ................................................................................................. 17 
2.1 Опис функціонального програмного середовища для розробки ........................ 17 
2.2 Опис процесу проєктування гри ............................................................................. 21 
Висновки до розділу 2 ................................................................................................... 37 
3 ТЕСТУВАННЯ ГРИ ....................................................................................................... 38 
3.1 Особливості тестування ігор ................................................................................... 38 
3.2 Тестування гри ......................................................................................................... 40 
Висновки до розділу 3 ................................................................................................... 41 
ВИСНОВКИ ....................................................................................................................... 42 
СПИСОК ВИКОРИСТАНИХ ДЖЕРЕЛ ......................................................................... 43 
Додаток А. Специфікація 482.ЧДТУ. 42285-01 ……………………………………… 44 
Додаток Б. Текст програми............................................................................................... 46 
Додаток В. Інструкція користувача ................................................................................. 81 
 
 
 
  
 8 
ПЕРЕЛІК УМОВНИХ ПОЗНАЧЕНЬ, СИМВОЛІВ, СКОРОЧЕНЬ І ТЕРМІНІВ 
 
MSC – MacNeal-Schwendler Corporation 
ПЗ – Програмне забезпеченя  
 9 
ВСТУП 
Початком розвивання індустрії відеоігор є друга половина двадцятого століття. 
Вона зародилась на території США та Японії у 1970-х роках [1]. 
Індустрія відеоігор – це сектор економіки, який пов’язаний із розробкою, 
просуванням та реалізацією відеоігор. Підтвердженням актуальності і своєчасності 
обраної для дослідження тематики є постійне зростання загального доходу ігрової 
продукції у світі [1]. 
Поява та розвиток сучасних персональних комп’ютерів, консолей та мобільних 
платформ призвели до еволюції продукції ігрових студій. Також з’явились нові способи 
розповсюдження ігор, а саме через онлайн платформи такі, як: Steam, GOG, Epic Games 
тощо. Через це ринок почав зростати швидше. У 2023 році ігрова індустрія згенерувала 
$184 мільярди доходу, що на 0,6% більше, ніж у 2022-му. Ріст забезпечили проєкти для 
консолей та ПК. 
Лиш одна Roblox має дохід у 2023 році: $2,79 млрд. Згідно з останніми 
фінансовими звітами Roblox, поточний дохід компанії становить 2,79 мільярда доларів 
США. У 2022 році дохід компанії склав 2,22 мільярда доларів США, збільшившись у 
порівнянні з доходом у 2021 році, який становив 1,91 мільярда доларів США. Також 
Roblox посів 5 місце мобільного геймінг маркету в номінації «worldwide consumer 
spending». Та 3 місце в номінації «worldwide downloads», адже його завантажили понад 
200 мільйонів разів. 
Roblox - це чистий успіх, і ці цифри свідчать про його величезну популярність. У 
цій платформі існує безліч ігор різних жанрів, і саме це робить його таким унікальним. 
Гравці можуть знаходити нові ігри з різноманітними геймплеями, персонажами, світами 
та можливостями. Ці ігри привносять у світ Roblox свіжі ідеї та дозволяють гравцям 
насолоджуватися новими пригодами безмежної віртуальної всесвіту. 
 
 
 
 
 10 
1 ДОСЛІДЖЕННЯ ПРЕДМЕТНОЇ ОБЛАСТІ 
1.1 Опис предметної області 
Roblox — безплатна онлайн-платформа для створення ігор. Користувачі 
можуть створювати власні ігри в Roblox Studio, грати в ігри, створені іншими 
користувачами, а також створювати та вигадувати одяг для свого персонажа. Деякі 
товари в каталозі можна купити за ігрову валюту — Robux [2]. 
Сага про Roblox (Рисунок 1.1) розпочалася наприкінці 80-х років, коли Девід 
Башукі розпочав проєкт під назвою Knowledge Revolution. Це підприємство мало на 
меті поєднати освіту з технологіями, спеціалізуючись на програмному забезпеченні 
для фізики та механічного моделювання. Одним із важливих творінь Башукі стала 
інтерактивна фізика, яка заклала основу для більш інтерактивних цифрових сфер. Ці 
зусилля призвели до випадкової зустрічі з Еріком Касселем, інноватором-
однодумцем. Їхнє спільне бачення та взаємодоповнюючі навички створили міцне 
партнерство, підготувавши основу для того, що згодом перетворилося на 
новаторську платформу Roblox Corporation, яка принесла свіжий погляд на онлайн-
ігри та взаємодію. 
У 1999 році відбувся перехід, коли MSC Software Corporation придбала 
Knowledge Revolution за значні 20 мільйонів доларів, а Башукі обійняв посаду віце-
президента. 2004 рік став знаменним, оскільки він ознаменував відхід Башукі та 
Касселя з MSC, що призвело до народження корпорації Roblox. Дует разом з 
деякими колишніми співробітниками MSC почав розробку Roblox, спочатку 
розглядаючи такі назви, як "GoBlocks" і "DynaBlocks". Офіційний запуск Roblox 
відбувся 1 вересня 2006 року, після виходу з бета-версії.  
2007 рік став роком еволюції Roblox з появою нових функцій, таких як 
пошуковий рядок, приватний чат з безпечним чатом для молодших користувачів, 
розробники квитків, клуби та можливості налаштування персонажів. Цього ж року 
з'явилися "Roblox Points" - щоденні бонуси за вхід в систему, які згодом, у травні 
2007 року, були замінені на "Robux". Інша валюта, "Tix", була введена, але 
 11 
припинила своє існування в березні 2016 року. Roblox продовжував розширювати 
можливості свого сервера і запустив преміум-членство, відоме як "Клуб 
будівельників", яке у вересні 2019 року було перейменовано на "Roblox Premium", 
що демонструє постійне прагнення Roblox до вдосконалення та розвитку. 
У холодному фіналі 2011 року всесвіт Roblox став свідком світанку свого 
першого Тижня Хака, що ознаменував зародження традиції, яка процвітатиме 
щороку. Це свято зібрало найкращих розробників Roblox, запалило горнило 
інновацій, де ідеї перетворилися на абсолютно нові проєкти ігрової системи, які 
згодом були продемонстровані великим шишкам Roblox. З настанням першого 
жовтневого дня 2013 року було запущено " Developer Exchange program"(Рисунок 
1.2), що відкрила портал для віртуозів гри, які могли перетворити своїх Robux на 
реальні скарби. Історія Roblox перейшла в більш інтригуючу главу 31 травня 2015 
року, коли відбулося урочисте відкриття функції "Згладжування рельєфу". Це 
нововведення покращило візуальну привабливість і достовірність гри, 
перетворивши місцевість на більш автентичну, позбувшись її колишньої блокової 
подоби. У тандемі з цим еволюціонував і фізичний рушій гри, що ще більше 
покращило ігровий досвід. 
 
Рисунок 1.1 – Логотип Roblox 
 12 
 
Рисунок 1.2 – Приклад тарифу Robux’ів 
 
1.2 Огляд існуючих аналогів 
 
Для огляду існуючих рішень розробки гри доцільно виконати порівняльний 
аналіз інших ігор в Roblox. 
PLS DONATE BUT GOOD – гра є прямим конкурентои, недоліками якої є: 
– некоректне відображення моделі гравця (Рисунок 1.3); 
– під час першого візиту в гру гравцям видають предмети, які повинні 
з’являтись після певних виконаних досягнень (Рисунок 1.3); 
– відсутність редагування тексту на кіоску; 
 13 
– накладання тексту на чат в грі (Рисунок 1.3). 
 
Рисунок 1.3 –Демонстрація недоліків гри PLS DONATE BUT GOOD 
 
PLS DONATE S – гра є прямим конкурентом, недоліками якої є: 
– відсутність редагування тексту на кіоску; 
– застраріла мапа гри; 
– відустність міні-ігор для довшого утримання гравців в грі. 
 
Рисунок 1.4 – Головна сторінка «PLS DONATE S» 
 14 
1.3 Аналіз порівнянь існуючих рішень розглянутих реалізацій та 
постановка завдання 
Проаналізувавши існуючі рішення розглянутих реалізацій, в кваліфікаційній 
роботі бакалавра є кілька пропозицій щодо усунення обмежень існуючих сервісів:  
1. Необхідно, щоб моделі гравців коректно відображались в грі. 
2. Видавати предмети лиш при виконанні певних досягнень. 
3. Потрібно додати можливість редагування тексту (стиль, прозорість, тощо) 
4. Варто мати актуальну мапу та своєчасно оновлювати гру. 
5. Додати міні-ігри для довшого утримання гравців в грі. 
У таблиці 1.1 представлено порівняльний аналіз розглянутих ігор, а саме: 
«PLS DONATE BUT GOOD»,  «PLS DONATE S».  
Таблиця 1.1 – Таблиця порівнянь існуючих рішень розглянутих реалізацій 
Критерії Назва гри 
порівняння «PLS DONATE 
«PLS DONATE S» 
сервісів BUT GOOD» 
Дизайн 
3 3 
(0-5) 
Швидкість 
завантаження 1 5 
(0-5) 
Оптимізація 
2 4 
(0-5) 
 
Як видно із табл. 1.1, що у якості критеріїв для порівняння було обрано: 
дизайн; швидкість завантаження; оптимізація. 
Підсумовуючи перегляд та оцінку приведених вище ігор, варто зазначити, що 
кожній з них притаманні такі характеристики, як зрозумілий дизайн. 
Проаналізувавши існуючі рішення розглянутих реалізацій, в кваліфікаційній 
роботі бакалавра при розробці гри варто звернути увагу на такі моменти: 
− гра повинна мати зручний, зрозумілий та приємний інтерфейс; 
 15 
− гра повинна мати швидкість завантаження серед оцінок (0-5), а саме: 5; 
− гра повинна мати оптимізацію серед оцінок (0-5), а саме: 5; 
Постановка завдання  
1. Аналіз роботи гри, функціональних вимог та використаних засобів 
користувацьких інтерфейсів існуючих ігор.  
2. Дослідження та вибір найактуальніших технологій розробки для створення 
гри в Roblox.  
3. Розробка гри, що задовольняє таким функціональним вимогам:  
− система промо-кодів; 
− функція офлайн донатів; 
− система налаштування кіоску;  
− придбання в магазині речей;  
− система налаштувань гри; 
− рейтинг гравців який відображає суму донатів, які вони отримали протягом 
всього часу; 
− глобальна таблиця всіх донатів в реальному часі; 
− міні-гра футбол; 
− функція донатів; 
− можливість виганяти гравців з приватного серверу; 
− система репортів; 
− можливість переглядати історію донатів користувача; 
− можливість переглядати найбільших донатерів користувача; 
− можливість переглянути рейтинг сум донатів за весь час користувача, які він 
надсилав іншим користувачам; 
− адміністраторська панель; 
− система досягнень; 
− додати предмети з різним функціоналом для користувачів; 
− рейтинг найбільших донатерів. 
 16 
Висновки до розділу 1 
В даному розділі досліджено предметну область, а саме: Roblox; огляд 
існуючих аналогів. 
Виконано порівняльний аналіз існуючих ігор: «PLS DONATE BUT GOOD», 
«PLS DONATE S». 
Представлено таблицю порівнянь існуючих рішень розглянутих реалізацій та 
визначено постановку завдання. 
  
 17 
2 ПРОЄКТУВАННЯ ГРИ 
2.1  Опис функціонального програмного середовища для розробки  
Розглянемо детальніше програмне середовище та його особливості для 
розробки гри «PLS DONATE X». 
Для розробки гри використано ігровий рушій «Roblox Studio». 
Roblox Studio – це інтегроване середовище для створення і редагування ігор на 
платформі Roblox. Roblox – це веб-платформа для масових онлайн-ігор, яка 
дозволяє користувачам створювати власні ігри та долучатися до ігор, розроблених 
іншими користувачами. Roblox Studio надає інструменти, щоб допомогти 
розробникам створювати різноманітні ігри, від простих до складних, з 
використанням 3D-графіки, анімації та багатьох інших функцій. 
Roblox Studio надає можливості такі як: 
− створення світу (Рисунок 2.1): Roblox Studio дозволяє розробникам 
створювати унікальні ігрові світи, які можуть бути складними або 
простими залежно від креативності користувача. Деякі з основних 
можливостей цієї функції включають: 
1) ландшафт: Roblox Studio має інструменти для створення 
різноманітних ландшафтів, включаючи гори, долини, річки тощо; 
2) зміщення об'єктів: Розробники можуть додавати об'єкти, такі як 
будівлі, рослини, тварини та інше, для створення реалістичних 
ігрових світів; 
3) конфігурація параметрів: Roblox Studio дозволяє налаштовувати 
параметри світу, такі як текстури, освітлення, погодні умови, щоб 
створити певну атмосферу в грі. 
− Скриптування (Рисунок 2.2): скриптування в Roblox Studio дозволяє 
розробникам програмувати поведінку об'єктів та персонажів у грі. 
Основні можливості цієї функції включають: 
1) мова програмування Lua: Roblox Studio використовує мову 
програмування Lua для створення скриптів; 
 18 
2) керування рухом: розробники можуть програмувати рух 
персонажів, об'єктів та інших елементів у грі; 
3) взаємодія об'єктів: скрипти дозволяють розробникам створювати 
взаємодію між різними об'єктами у грі, таку як взаємодія зі 
світлом, рухомі елементи тощо. 
− персонажі та анімація: Roblox Studio надає інструменти для створення 
персонажів та їх анімації. Основні можливості цієї функції включають: 
1) створення персонажів: розробники можуть створювати унікальних 
персонажів з різними виглядами та характеристиками; 
2) анімація (Рисунок 2.3): Roblox Studio надає можливості для 
створення анімацій персонажів, включаючи рухи, взаємодію з 
об'єктами тощо. 
− соціальні можливості: спільнота і взаємодія між гравцями грає важливу 
роль у платформі Roblox. Деякі з соціальних можливостей включають: 
1) чат та взаємодія (Рисунок 2.4): гравці можуть спілкуватися один з 
одним за допомогою вбудованого чату, обмінюватися 
повідомленнями, дружити та взаємодіяти; 
2) публікація та обмін: розробники можуть публікувати свої ігри, 
щоб інші гравці могли їх грати, а також обмінюватися власними 
творіннями з іншими користувачами. 
− тестування та публікація: Roblox Studio надає зручні інструменти для 
тестування ігор та їх подальшої публікації на платформі Roblox. 
Основною можливістю цієї функції є тестування у реальному часі 
(Рисунок 2.5): розробники можуть тестувати свої ігри безпосередньо у 
середовищі розробки, щоб виявити помилки або недоліки. 
Також в Roblox Studio є плагіни (Рисунок 2.6) користувачі мають можливість 
придбати різноманітні плагіни, які розширюють функціональність середовища 
розробки та полегшують процес створення ігор. 
 
 19 
 
Рисунок 2.1 – Приклад створеного світу 
 
Рисунок 2.2 – Приклад скрипту 
 20 
 
Рисунок 2.3 – Приклад анімації в роботі 
 
Рисунок 2.4 – Відображення чату 
 21 
 
Рисунок 2.5 – Приклад cross-platform testing 
 
Рисунок 2.6 – Зображення панелі плагінів 
 
2.2 Опис процесу проєктування гри 
 
Створено елементи гри, а саме: 
− ігрова мапа; 
− система промо-кодів – Можливість введення промокодів знайдених підчас гри 
задля отримання бонусів; 
− функція офлайн донатів – Можливість відправки донатного подарунку людині 
яка є офлайн; 
− система налаштування кіоску – Меню налаштування кіоску;  
− придбання в магазині речей; 
− система налаштувань гри – Меню налаштування гри (гучність музики, звукові 
ефекти, тощо); 
− рейтинг гравців який відображає суму донатів, які вони отримали протягом 
всього часу; 
− глобальна таблиця всіх донатів в реальному часі; 
 22 
− міні-гра футбол; 
− функція донатів; 
− можливість виганяти гравців з приватного серверу; 
− система репортів – Можливість поскаржитись на гравця, та можливість 
переглянути скарги поза грою адміністатору; 
− можливість переглядати історію донатів користувача; 
− можливість переглядати найбільших донатерів користувача; 
− можливість переглянути рейтинг сум донатів за весь час користувача, які він 
надсилав іншим користувачам; 
− адміністраторська панель; 
− система досягнень – система яка винагороджує гравця за досягнення певних 
цілей в грі; 
− предмети з різним функціоналом для користувачів; 
− рейтинг найбільших донатерів. 
 
Для того, щоб створити гру для початку необхідно створити проєкт 
використовуючи довільний шаблон. Проєкт – це набір ресурсів, налаштувань та 
інших ресурсів, які разом представляють гру. 
Далі заповнюємо ігрову мапу об’єктами (Рисунок 2.7). 
 
Рисунок 2.7 – Приклад ігрової мапи з об’єктами 
 23 
Наповнивши ігрову мапу далі її необхідно зберегти. Для цього необхідно в 
верхній панелі інструментів натиснути на «File» та обрати у випадаючому меню 
функцію «Save to file». 
 
Рисунок 2.8 – Ілюстрація випадаючого меню 
 
Для того, щоб створити систему промокодів, адміністраторську панель, 
функцію офлайн донатів, придбання речей в магазині, меню налаштування кіоску, 
меню налаштування гри. Необхідно створити в інтерфейсі користувача навігаційну 
панель. 
Для цього необхідно в вікні «Explorer» необхідно навести курсор миші на 
папку «StarterGui». Після цього з'явиться «Плюсик» натиснувши на нього в полі 
пошуку ввести «ScreenGui» (Рисунок 2.9). 
 24 
 
Рисунок 2.9 – Приклад пошуку «ScreenGui» 
 
Додавши «ScreenGui» в «StarterGui» необхідно в нього додати елементи, а 
саме: 
– LocalScript – Локальний скрипт для написання скриптів; 
– Frame – Окреме вікно в графічному інтерфейся користувача для 
відображення навігаційної панелі; 
 
Рисунок 2.10 Приклад доданих елементів 
 
Після цього потрібно заповнити фрейм кнопками задля формування 
навігаційної панелі. 
Для того, щоб додати кнопки в фрейм потрібно навести курсор миші на фрейм 
та натиснути на «Плюсик». Після цього в пошуковому полі ввести «ImageButton». 
 25 
 
Рисунок 2.11 Приклад пошуку «ImageButton» 
 
Після цього буде сформована навігаційна панель (Рисунок 2.12) в якій 
розміщено більшість ігрових функцій. 
 
Рисунок 2.12 Приклад створеної навігаційної панелі 
 
Для того, щоб навігаційна панель працювала потрібно прописати скрипти в 
створеному «LocalScript». 
Після цього необхідно створити вікна для кожної кнопки адже ці кнопки в 
навігаційній панелі і є тими елементами гри, як: меню налаштування гри, 
промокоди, офлайн донати, магазин, меню налаштування кіоску, панель 
адміністратора. Для того, щоб створити вікна для даних елементів потрібно навести 
курсор миші на «ScreenGui» та натиснути на «Плюсик». Після цього в пошуковому 
полі ввести «CanvasGroup». 
 26 
 
Рисунок 2.13 Приклад пошуку «CanvasGroup» 
 
Кожні дані елементи створені, а саме: «LocalScript», «ScreenGui», 
«CanvasGroup», «ImageButton» та інші можна налаштовувати у вікні «Properties». 
 
Рисунок 2.14 – Приклад вікна «Properties» для «ScreenGui» 
 
Завдяки вікну «Properties» для вікон елементів навігаційної панелі можна 
вимкнути їх видимість для того, щоб дані вікна з’являлись на екрані після 
натискання на потрібну кнопку в навігаційній панелі. 
 27 
 
Рисунок 2.15 – Приклад вимкнутої видимості та увімкнутої видимості вікна 
елементу промокодів 
 
Для того, щоб створити кіоски, необхідно створити їх модель з «MeshPart» та 
завантажити її в «Model». Також потрібно додати «PrimaryPart» для того, щоб 
позиціонування в просторі стало коректне. Далі необхідно для коректного 
позиціонування в просторі тексту на вивісці та малюнку предмета додати 
«SignPart», «ItemsPart» (Рисунок 2.16). 
 
Рисунок 2.16 – Приклад створеного кіоску 
 
Також для кіосків потрібно прописати скрипти які завантажуватимуть кіоски 
на серверах ігрової мапи. Для цього потрібно створити «Script» в 
«ServerScriptService». 
 28 
 
Рисунок 2.17 – Приклад створеного «Script» з назвою «BoothLoader» для 
завантаження кіосків 
 
Створені кіоски надають можливість реалізувати систему донатів. Дана 
система поділена на два скрипти. Один з яких відповідає за основну частину 
системи донатів, а інший демонструє великі донати на всіх серверах одночасно в 
реальному часі (Рисунок 2.18). 
 
Рисунок 2.18 – Приклад створених двох скриптів для системи донатів 
 
Для донатів також мати валюту а саме несправжні «Robux», тому необхідно 
створити скрипт який нараховуватиме певну кількість валюти підчас проведенння 
часу в грі, та елемент інтерфейсу для відображення накопиченої суми несправжній 
«Robux». Елемент інтерфейсу потрібно розмістити в «ScreenGui». 
 29 
 
Рисунок 2.19 – Приклад створеного скрипта для накопичення гравцями валюти 
 
 
Рисунок 2.20 – Приклад створеного елементу інтерфейсу для відображення 
валюти 
 
Також потрібно створити міні гру «Футбол». Для цього потрібно розмістити 
об’єкти даної міні гри на мапі: футбольне поле, ворота, м’яч (Рисунок 2.21). Та 
додати скрипт пов’язаний з футбольним полем завдяки якому м’яч не вилітатиме за 
кордони футбольного поля, лічильник забитих у ворота м’ячів та переміщення м’яча 
на центр футбольного поля після забиття у ворота (Рисунок 2.22). 
 30 
 
Рисунок 2.21 – Приклад доданого на ігрову мапу футбольного поля та м’яча 
 
 
Рисунок 2.22 – Приклад написаного скрипту для міні гри футбол 
 31 
Для розробки стендів «Top Donated», та «Top Raised» необхідно створити та 
завантажити їх моделі на ігрову мапу (Рисунок 2.23). Дані стенди відображають 
рейтинг найбільших донатерів та рейтинг гравців який відображає суму донатів, які 
вони отримали протягом всього часу. 
 
Рисунок 2.23 – Приклад доданих стендів на ігрову мапу 
 
Для роботи даних стендів потрібно написати скрипти (Рисунок 2.24), які 
відображатимуть на стендах рейтинг топ гравців на стенді «TopDonated» та рейтинг 
гравців який відображає суму донатів, які вони отримали протягом всього часу для 
стенду «TopRaised». 
 
Рисунок 2.24 – Приклад створених скриптів для стенду «TopDonated» та 
«TopRaised» 
 
Результатом створення даних стендів є рейтинги гравців які оновлюються 
кожні 60 секунд (Рисунок 2.25). 
 32 
 
Рисунок 2.25 – Результат роботи стендів «TopDonated» та «TopRaised» 
 
Для створення стенду «LiveDonations» потрібно зробити аналогічні кроки як з 
стендами «TopDonated» та «TopRaised», окрім скрипту. Адже, даний стенд 
відображатиме донати гравців в реальному часі. 
 
Рисунок 2.26 – Приклад створеного скрипту для стенду «LiveDonations» 
 
Для системи репортів потрібно створити вікно для репорту в «ScreenGui», та 
написати скрипт для даного вікна. Система репортів працюватиме так, що якщо 
гравець вирішив поскаржитись на іншого гравця то даний репорт завдяки 
«webhook» потрапляє в текстовий канал, на сервері гри в додатку «Discord». Завдяки 
цьому адміністратору та модераторам не потрібно перебувати весь час в грі для 
фіксації репортів. 
 33 
 
Рисунок 2.27 – Приклад створеного вікна репортів 
 
Рисунок 2.28 – Приклад створеного скрипту системи репортів 
 34 
 
Рисунок 2.29 – Результат роботи системи репортів 
 
Для того, щоб створити досягнення в грі необхідно зайти на офіційну сторінку 
Roblox та перейти в навігаційному меню на сторінку «Create». Далі обрати створену 
гру та перейти в «Badges». Після цього з’явиться вікно створення досягнень 
(Рисунок 2.30). 
 
Рисунок 2.30 – Приклад вікна створення досягнень 
 35 
Настиснувши лівою кнопкою миші по кнопці «Create A Badge» з’явиться вікно 
створення досягнення (Рисунок 2.31). 
 
Рисунок 2.31 – Приклад вікна створення досягнення 
 
Дане вікно має такі елементи, а саме: 
− кнопка «Upload Image» для завантаження зображення досянення; 
− текстове поле «Name» для введення назви досягнення; 
− текстове поле «Description» для опису даного досягнення; 
− кнопка «Cancel»; 
− кнопка «Create Badge». 
Заповнивши всі необхідні поля та завантаживши зображення потрібно 
натиснути на кнопку «Create Badge». 
 36 
 
Рисунок 2.32 – Приклад заповнених полів створення досягнення 
 
Після того як досягнення створилось необхідно зачекати деякий час для 
затвердження даного досягнення модерацією Roblox. Далі це досягнення потрібно 
додати в гру задля того, щоб користувач міг його отримати виконавши певну умову. 
Наприклад гравець задонатив вперше будь яку суму, для цього потрібно створити 
скрипт в якому потрібно мати «Asset ID» (Рисунок 2.23). Дане ID береться з 
досягнення натиснувши по ньому правою кнопкою миші та обравши пункт «Copy 
Asset ID» в меню яке з’явилось (Рисунок 2.34). 
 
Рисунок 2.33 – Приклад створеного скрипта з застосуванням «Asset ID» 
досягнення 
 37 
 
Рисунок 2.34 – Приклад меню з пунктом«Copy Asset ID» досягнення 
 
Отримавши досягнення його можна переглянути в профілі на сторінці Roblox 
(Рисунок 2.35). 
 
Рисунок 2.35 – Приклад отриманого досягнення 
Висновки до розділу 2 
В даному розділі представлено опис функціонального програмного 
середовища для розробки гри «PLS DONATE X», а також досліджено основні 
принципи створення ігор в Roblox Studio. 
За допомогою Roblox Studio була розроблена гра «PLS DONATE X» 
 38 
3 ТЕСТУВАННЯ ГРИ 
3.1 Особливості тестування ігор 
Тестування гри це процес тестування програмного забезпечення для 
тестування ігор для контролю якості. Основна мета тестування ігор — визначити та 
виявити дефекти та помилки у відеогрі та покращити стабільність і продуктивність. 
Тестування ігор — це компонент розробки ігор, який допомагає забезпечити 
розгортання відеоігри не містить помилок. 
Робота тестувальника ігор передбачає: 
− класифікування вимог, виходячи з цільової мети та цільової аудиторії; 
− визначте вимоги користувача та системи, та їх слід класифікувати на 
функціональні, нефункціональні вимоги; 
− визначити предмети, що підлягають перевірці, елементи, що не 
підлягають тестуванню, цілі та заходи щодо функціональних і 
нефункціональних вимог; 
− перевіряти, чи функціональні вимоги повні, послідовні та зрозумілі; 
− визначте настроювані вимоги, суперечливі вимоги; 
− визначення взаємозалежних вимог є одним із завдань тестування гри; 
− пріоритезація вимог на основі унікальності, комплексність, критичність; 
− визначити тему гри, персонажів, анімації, штучного інтелекту, 
кінематографії, перегляду камери, ігрового процесу. 
Види тестування гри: 
Функціональне тестування. 
Тестувальники перевірки функціональності шукають загальні проблеми в грі 
або її користувальницькому інтерфейсі та графіці, як-от проблеми з ігровою 
механікою, проблеми зі стабільністю та цілісністю ігрових ресурсів. Тестування 
інтерфейсу користувача забезпечує зручність гри. 
Тестування продуктивності. 
 39 
Перевіряється загальна продуктивність гри. Налаштування продуктивності 
виконується для оптимізації швидкості гри. 
Час відповіді на клієнті та серверах, час завершення транзакцій, 
продуктивність при піковому навантаженні, довговічність, покриття мережі, витік 
пам’яті, низький рівень пам’яті, низький заряд акумулятора, час, витрачений на 
завантаження програм, одночасно (кілька користувачів) доступ до сервера 
програми, швидкість, пропускна здатність, надійність, масштабованість тощо. 
Споживання батареї та продуктивність графіки: Виміряйте споживання 
батареї мобільної гри. Споживання батареї має бути оптимальним протягом 
тривалого часу, і реакція гри має бути задовільною за різних великих навантажень 
на різних пристроях. 
Обмеження процесора та пам'яті: Лічильники продуктивності 
використовуються для вимірювання споживання процесора та пам’яті програмою. 
Мережеве підключення: Вимірює час відгуку мобільних ігор у різних типах 
мереж (Wi-Fi, 2G, 3G, 4G). Це дає загальне уявлення про те, наскільки добре гра 
працюватиме в ненадійних мережах. Він також перевіряє з’єднання між мобільними 
пристроями, центрами обробки даних або хмарою. Відстежуються всі часи піку, 
нестабільні з’єднання, дублювання даних, втрата пакетів, фрагментація даних. 
Тестування локалізації. 
Тестування локалізації стає надзвичайно важливим, коли гра орієнтована на 
глобальні ринки. Назви ігор, вміст і тексти потрібно перекладати та тестувати на 
пристроях кількома мовами. Ці типи тестів можна виконати швидко (за допомогою 
хмарного доступу до пристрою та автоматизації тестування). 
Тестування безпеки. 
Це робиться для того, щоб перевірити, наскільки захищено програмне 
забезпечення від зовнішніх загроз. Захист даних від зовнішніх загроз, 
неконтрольованих обмежень доступу до системи, порушення даних, помилки 
системи зв'язку та слабке шифрування коду [3]. 
 40 
3.2 Тестування гри 
Для перевірки належного функціонування додатку з точки зору користувача 
використано тестування програмного забезпечення, що виконується вручну без 
використання автоматичних тестів або скриптів. Цей процес включає запуск гри, 
введення різних даних та перевірку результатів, з метою забезпечення належного 
функціонування програмного забезпечення та виявлення можливих помилок та 
дефектів. 
Тестування продуктивності розробленої гри показало найвищі результати, що 
означає про його швидкісну та ефективну роботу. В процесі тестування було 
проведено перевірку використання оперативної пам’яті, обробки великого обсягу 
даних та інших вимог продуктивності. Отримані результати свідчать про те, що він 
може забезпечити швидку та зручну роботу для користувачів. 
Це позитивний результат, який підтверджує відповідність функціональних 
вимог гри та її здатність працювати з оптимальною продуктивністю. Такі результати 
тестування дозволяють зробити висновок про успішну розробку та належну роботу 
розробленої гри (Рисунок 3.1). 
Проте варто зазначити, що тестування продуктивності є одним з багатьох 
аспектів тестування, і необхідно проводити й інші види тестів, такі як: 
функціональне тестування, тестування безпеки та інші, щоб забезпечити повну 
перевірку функціональності та якості гри. 
 
Рисунок 3.1 – Результати тестування «PLS DONATE X» 
 41 
Проведено кросплатформне тестування гри на різних пристроях, включаючи 
комп'ютери, планшети та мобільні телефони. В результаті тестування було 
виявлено, що на малих екранах телефонів виникають помилки розміщення 
елементів інтерфейсу. Зокрема, кнопки та текстові блоки відображаються 
некоректно або перекривають один одного, що суттєво ускладнює взаємодію 
користувачів з грою (Рисунок 3.2). Це вказує на необхідність додаткової оптимізації 
інтерфейсу для забезпечення повної сумісності з мобільними пристроями. 
 
Рисунок 3.2 – Результат кросплатформного тестування 
Висновки до розділу 3 
В даному розділі описано технології тестування ігор. 
Виконано тестування розробленої гри «PLS DONATE X» на онлайн-платформі 
Roblox. Результати тестування дозволяють зробити висновок про успішну розробку 
гри та її належну роботу. 
  
 42 
ВИСНОВКИ 
Мета кваліфікаційної роботи бакалавра досягнута. В ході її виконання 
спроєктовано та розроблено гру «PLS DONATE X». 
Для досягнення поставленої мети в роботі розв’язувалися наступні завдання: 
 досліджено предметну область; 
 виконано порівняльний аналіз існуючих ігор, а саме: «PLS DONATE BUT 
GOOD», «PLS DONATE S»; 
 обрано програмно-технічні засоби для реалізації задачі дослідження; 
 розроблено гру «PLS DONATE X»та виконано її тестування. 
Кросплатформна гра «PLS DONATE X» розроблена на мові Lua. Створення та 
робота з базою даних відбувалась із застосуванням Roblox Studio. Контроль проєкту 
та написання коду здійснювалось у середовищі Roblox Studio. 
Обрані технології задовольняють всім функціональним і не функціональним 
вимогам до такого типу програмного забезпечення. 
Розроблений розроблена гра має зручний, зрозумілий та приємний інтерфейс. 
Користується попитом в багатьох гравців. 
 
 
 
 
 
 
 
 
 
 43 
СПИСОК ВИКОРИСТАНИХ ДЖЕРЕЛ 
1. GamesIndustry.biz presents… The Year in Numbers 2020 URL: 
https://www.gamesindustry.biz/articles/2020-12-21-gamesindustry-biz-presents-the-
year-in-numbers-2020 (дата звернення: 10.03.2024) 
2. Roblox URL: https://uk.wikipedia.org/wiki/Roblox (дата звернення: 10.03.2024). 
3. Тестування ігор: типи та способи тестування мобільних/настільних програм 
URL: https://www.guru99.com/uk/game-testing-mobile-desktop-apps.html (дата 
звернення: 10.03.2024) 
  
 44 
ДОДАТОК А 
 
 
 
        Затверджую               
Зав. кафедри КНСА, 
______________ Юрій ТРИУС 
«____»____________2023 р.                                                                                                                                                                              
 
 
 
 
 
 
 
КОМП’ЮТЕРНА 3-D ГРА “PLS DONATE X” НА ОНЛАЙН-ПЛАТФОРМІ 
ROBLOX 
 
Специфікація  
482.ЧДТУ. 42285-01  
 
Листів 2 
 
 
 
 
 
 
Розробник                          ____________________                 Колісник М.В. 
 
Керівник                             ____________________                Підгорний М.В. 
 
 
 
 
 
 
 
 
 
 
Черкаси – 2024  
 45 
482.ЧДТУ. 42285-01 
Позначення Найменування Примітка 
   
   
 Документація  
   
   
482.ЧДТУ. 42285-01    12 01 Текст програми  
482.ЧДТУ. 42285-01    34 01 Інструкція користувача  
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
 46 
ДОДАТОК Б 
 
 
 
 
 
КОМП’ЮТЕРНА 3-D ГРА “PLS DONATE X” НА ОНЛАЙН-ПЛАТФОРМІ 
ROBLOX 
 
 
 
Текст програми 
482.ЧДТУ. 42285-01 12 01 
 
Листів 23 
 
 
 
 
 
 
Розробник    _____________                   Колісник М.В. 
 
 
 
 
 
 
 
Черкаси – 2024  
 47 
Фрагмент програми 
 
BoothLoader 
-- SERVICES -- 
 
local ServerStorage = game:GetService('ServerStorage') 
local ReplicatedStorage = game:GetService('ReplicatedStorage') 
local CollectionService = game:GetService('CollectionService') 
 
-- MODULES -- 
 
local BoothService = require(game.ServerScriptService.Services.BoothService) 
 
-- INSTANCES -- 
 
local Templates = ReplicatedStorage.Templates 
local Booths = ServerStorage:WaitForChild('BoothModels') 
 
-- MAIN SCRIPT -- 
 
local BoothsPositions = { 
 Booth1 = {Position = Vector3.new(241.8, 0.98, 279.223), Orientation = 120}, 
 Booth2 = {Position = Vector3.new(235.268, 0.98, 347.292), Orientation = 60}, 
 Booth3 = {Position = Vector3.new(245.8, 0.98, 323.223), Orientation = 90}, 
 Booth4 = {Position = Vector3.new(115.69, 0.98, 245.387), Orientation = -150}, 
 Booth5 = {Position = Vector3.new(126.948, 0.98, 238.886), Orientation = -150}, 
 Booth6 = {Position = Vector3.new(206.275, 0.98, 238.918), Orientation = 150}, 
 Booth7 = {Position = Vector3.new(241.768, 0.98, 336.034), Orientation = 60}, 
 Booth8 = {Position = Vector3.new(104.37, 0.98, 358.496), Orientation = -60}, 
 Booth9 = {Position = Vector3.new(217.534, 0.98, 245.418), Orientation = 150}, 
 Booth10 = {Position = Vector3.new(228.8, 0.98, 256.707), Orientation = 120}, 
 Booth11 = {Position = Vector3.new(115.636, 0.98, 369.785), Orientation = -30}, 
 Booth12 = {Position = Vector3.new(126.894, 0.98, 376.285), Orientation = -30}, 
 Booth13 = {Position = Vector3.new(245.8, 0.98, 291.223), Orientation = 90}, 
 Booth14 = {Position = Vector3.new(91.37, 0.98, 335.98), Orientation = -60}, 
 Booth15 = {Position = Vector3.new(217.48, 0.98, 369.816), Orientation = 30}, 
 Booth16 = {Position = Vector3.new(91.401, 0.98, 279.169), Orientation = -120}, 
 Booth17 = {Position = Vector3.new(138.207, 0.98, 232.387), Orientation = -150}, 
 Booth18 = {Position = Vector3.new(235.3, 0.98, 267.965), Orientation = 120}, 
 Booth19 = {Position = Vector3.new(195.017, 0.98, 232.418), Orientation = 150}, 
 Booth20 = {Position = Vector3.new(126.517, 0.98, 519.711), Orientation = -75}, 
 Booth21 = {Position = Vector3.new(97.901, 0.98, 267.911), Orientation = -120}, 
 Booth22 = {Position = Vector3.new(194.963, 0.98, 382.816), Orientation = 30}, 
 Booth23 = {Position = Vector3.new(97.87, 0.98, 347.238), Orientation = -60}, 
 Booth24 = {Position = Vector3.new(87.293, 0.98, 291.161), Orientation = -90}, 
 Booth25 = {Position = Vector3.new(126.533, 0.98, 498.202), Orientation = -105}, 
 48 
 Booth26 = {Position = Vector3.new(206.804, 0.98, 498.263), Orientation = 105}, 
 Booth27 = {Position = Vector3.new(104.401, 0.98, 256.652), Orientation = -120}, 
 Booth28 = {Position = Vector3.new(206.221, 0.98, 376.316), Orientation = 30}, 
 Booth29 = {Position = Vector3.new(206.788, 0.98, 519.771), Orientation = 75}, 
 Booth30 = {Position = Vector3.new(196.064, 0.98, 479.628), Orientation = 135}, 
 Booth31 = {Position = Vector3.new(87.293, 0.98, 323.161), Orientation = -90}, 
 Booth32 = {Position = Vector3.new(228.768, 0.98, 358.55), Orientation = 60}, 
 Booth33 = {Position = Vector3.new(181.026, 0.552, 123.042), Orientation = 94}, 
 Booth34 = {Position = Vector3.new(137.257, 0.98, 538.346), Orientation = -45}, 
 Booth35 = {Position = Vector3.new(152.947, 0.524, 143.891), Orientation = -107}, 
 Booth36 = {Position = Vector3.new(137.301, 0.98, 479.583), Orientation = -135}, 
 Booth37 = {Position = Vector3.new(138.152, 0.98, 382.785), Orientation = -30}, 
 Booth38 = {Position = Vector3.new(196.02, 0.98, 538.39), Orientation = 45}, 
} 
 
local BoothInteraction = { 
 Interaction1 = {Position = Vector3.new(240.959, 4.973, 279.766), Orientation = 120}, 
 Interaction2 = {Position = Vector3.new(234.378, 4.973, 346.836), Orientation = 60}, 
 Interaction3 = {Position = Vector3.new(244.801, 4.973, 323.273), Orientation = 90}, 
 Interaction4 = {Position = Vector3.new(116.233, 4.973, 246.227), Orientation = 30}, 
 Interaction5 = {Position = Vector3.new(127.491, 4.973, 239.727), Orientation = 30}, 
 Interaction6 = {Position = Vector3.new(205.819, 4.973, 239.808), Orientation = -30}, 
 Interaction7 = {Position = Vector3.new(240.878, 4.973, 335.578), Orientation = 165}, 
 Interaction8 = {Position = Vector3.new(105.21, 4.973, 357.953), Orientation = 165}, 
 Interaction9 = {Position = Vector3.new(217.077, 4.973, 246.308), Orientation = -165}, 
 Interaction10 = {Position = Vector3.new(227.959, 4.973, 257.249), Orientation = -165}, 
 Interaction11 = {Position = Vector3.new(116.092, 4.973, 368.895), Orientation = -165}, 
 Interaction12 = {Position = Vector3.new(127.35, 4.973, 375.395), Orientation = -135}, 
 Interaction13 = {Position = Vector3.new(244.801, 4.973, 291.273), Orientation = -90}, 
 Interaction14 = {Position = Vector3.new(92.21, 4.973, 335.437), Orientation = -135}, 
 Interaction15 = {Position = Vector3.new(216.937, 4.973, 368.976), Orientation = -45}, 
 Interaction16 = {Position = Vector3.new(92.291, 4.973, 279.625), Orientation = -45}, 
 Interaction17 = {Position = Vector3.new(138.749, 4.973, 233.227), Orientation = -45}, 
 Interaction18 = {Position = Vector3.new(234.46, 4.973, 268.508), Orientation = -15}, 
 Interaction19 = {Position = Vector3.new(194.561, 4.973, 233.308), Orientation = -15}, 
 Interaction20 = {Position = Vector3.new(127.469, 4.973, 519.404), Orientation = -15}, 
 Interaction21 = {Position = Vector3.new(98.791, 4.973, 268.367), Orientation = 15}, 
 Interaction22 = {Position = Vector3.new(194.42, 4.973, 381.976), Orientation = 15}, 
 Interaction23 = {Position = Vector3.new(98.71, 4.973, 346.695), Orientation = 45}, 
 Interaction24 = {Position = Vector3.new(88.292, 4.973, 291.111), Orientation = 45}, 
 Interaction25 = {Position = Vector3.new(127.511, 4.973, 498.413), Orientation = 45}, 
 Interaction26 = {Position = Vector3.new(205.852, 4.973, 498.569), Orientation = 75}, 
 Interaction27 = {Position = Vector3.new(105.291, 4.973, 257.109), Orientation = 75}, 
 Interaction28 = {Position = Vector3.new(205.678, 4.973, 375.476), Orientation = 75}, 
 Interaction29 = {Position = Vector3.new(205.81, 4.973, 519.561), Orientation = 75}, 
 Interaction30 = {Position = Vector3.new(195.393, 4.973, 480.369), Orientation = 75}, 
 Interaction31 = {Position = Vector3.new(88.292, 4.973, 323.111), Orientation = 75}, 
 49 
 Interaction32 = {Position = Vector3.new(227.878, 4.973, 358.094), Orientation = -120}, 
 Interaction33 = {Position = Vector3.new(180.033, 4.545, 123.161), Orientation = 75}, 
 Interaction34 = {Position = Vector3.new(137.928, 4.973, 537.604), Orientation = 75}, 
 Interaction35 = {Position = Vector3.new(153.917, 4.517, 144.135), Orientation = 75}, 
 Interaction36 = {Position = Vector3.new(138.043, 4.973, 480.254), Orientation = 75}, 
 Interaction37 = {Position = Vector3.new(138.609, 4.973, 381.895), Orientation = 75}, 
 Interaction38 = {Position = Vector3.new(195.278, 4.973, 537.719), Orientation = 75}, 
} 
 
local BoothModels = {} 
 
for Name, Booth in pairs(BoothsPositions) do 
 local BoothClone = Booths.BasicBooth:Clone() 
 BoothClone:SetPrimaryPartCFrame(CFrame.new(Booth.Position)) 
 BoothClone:SetPrimaryPartCFrame(BoothClone.PrimaryPart.CFrame * CFrame.Angles(0, 
math.rad(Booth.Orientation), 0)) 
 BoothClone.Name = 'BasicBooth' 
 BoothClone:SetAttribute('BoothID', Name:sub(6, #Name)) 
 BoothClone.Parent = workspace:WaitForChild('BoothModels') 
 local BoothUI = Templates.BoothUI:Clone() 
 BoothUI.Parent = workspace:WaitForChild('MapUI'):WaitForChild('BoothUI') 
 BoothUI.Details.Adornee = BoothClone:WaitForChild('Base') 
 BoothUI.Items.Adornee = BoothClone:WaitForChild('ItemsPart') 
 BoothUI.Sign.Adornee = BoothClone:WaitForChild('SignPart') 
 BoothUI.Name = 'BoothUI'..Name:sub(6, #Name) 
 rawset(BoothModels, Name:sub(6, #Name), BoothClone) 
 --CreateBoothStore(Name) 
end 
 
local function findBoothByBoothID(boothID) 
 for _, boothModel in pairs(BoothModels) do 
  if boothModel:GetAttribute('BoothID') == boothID then 
   return boothModel 
  end 
 end 
 return nil 
end 
 
local BoothInteractions = {} 
 
for Name, Interaction in pairs(BoothInteraction) do 
 local InteractionClone = script.BoothInteraction:Clone() 
 InteractionClone.Position = Interaction.Position 
 InteractionClone.Orientation = Vector3.new(0, Interaction.Orientation, 0) 
 InteractionClone.Name = 'BoothInteraction' 
 CollectionService:AddTag(InteractionClone, 'BoothInteraction') 
 InteractionClone:SetAttribute('BoothSlot', Name:sub(12, #Name)) 
 50 
 InteractionClone:SetAttribute('BoothOwner', nil) 
 local BoothID = InteractionClone:GetAttribute('BoothSlot') 
 local Booth = findBoothByBoothID(BoothID) 
 InteractionClone.Parent = workspace:WaitForChild('BoothInteractions') 
 InteractionClone.BoothModel.Value = Booth 
 rawset(BoothInteractions, Name:sub(12, #Name), InteractionClone) 
end 
 
wait(0.15) 
 
BoothService:UpdateTables(BoothInteractions, BoothModels) 
 
wait(1) 
 
script:Destroy() 
 
Admin 
Local remotes = require(game.replicatedstorage.remotes) 
Local dataservice = require(game.serverscriptservice.services.dataservice) 
Local logservice = require(game.serverscriptservice.services.logservice) 
Local messagingservice = game:getservice("messagingservice") 
Local function checkplayer(player) 
 if player:getrankingroup(16756900) < 4 then 
  logservice:logexploit(player, 'trying to use admin panel without permissions') 
  player:kick('xuataun\n exploiting') 
  return 
 end 
End 
Remotes.function("checkifbanned").onserverinvoke = function(player, userdata) 
 checkplayer(player) 
 local bandata = dataservice:isplayerbanned(userdata) 
 if bandata == nil then 
  bandata = {isbanned = false, reason = ""} 
 end 
 return bandata 
End 
Remotes.event("ban").onserverevent:connect(function(player, userid, reason) 
 checkplayer(player) 
 dataservice:banplayer(userid, reason) 
 local target = game.players:getplayerbyuserid(userid) 
 if target then 
  target:kick(string.format("you've been banned for reason %s", reason)) 
 end 
End) 
Remotes.event("unban").onserverevent:connect(function(player, userid) 
 checkplayer(player) 
 51 
 dataservice:unbanplayer(userid) 
End) 
Remotes.event("kick").onserverevent:connect(function(player, userid) 
 checkplayer(player) 
 local player = game.players:getplayerbyuserid(userid) 
 player:kick("you've been kicked from this server") 
End) 
Remotes.function("checkuseringame").onserverinvoke = function(player, userid) 
 checkplayer(player) 
 local userdata = {ingame = false, placeid = 17114655272} 
 local success, errormessage, placeid, jobid = pcall(function() 
 return game["teleport service"]:getplayerplaceinstanceasync(userid) 
 end) 
 if success then 
  if placeid == game.placeid then 
   userdata.ingame = true 
  end 
 end 
 return userdata 
End 
Remotes.event("joinuserserver").onserverevent:connect(function(player, userid) 
 checkplayer(player) 
 local success, errormessage, placeid, jobid = pcall(function() 
  return game["teleport service"]:getplayerplaceinstanceasync(userid) 
 end) 
 if success then 
  game["teleport service"]:teleporttoplaceinstance(placeid, jobid, player) 
 end 
End)  
 
Chat commands 
-- Services --  
 
Local players = game:getservice('players') 
Local serverstorage = game:getservice('serverstorage') 
Local replicatedstorage = game:getservice('replicatedstorage') 
Local messagingservice = game:getservice("messagingservice") 
 
-- modules -- 
 
Local remotes = require(replicatedstorage.remotes) 
Local playersservice = require(game.serverscriptservice.services.playersservice) 
 
-- stuff -- 
 
 52 
Local validcmds = {'headless', 'purplevalk', 'blackvalk', 'pinkvalk', 'bluevalk', 'icevalk', 
'greenvalk', 'redvalk', 'car'} 
Local foundercommands = 
require(game:getservice('serverscriptservice'):waitforchild('services'):waitforchild('founderc
mds')) 
 
-- main script -- 
 
Remotes.function('getplayerrank').onserverinvoke = function(player) 
  
 local playerrank = player:getrankingroup(16756900) 
 
 return playerrank 
  
End 
 
Players.playeradded:connect(function(plr) 
  
 plr.chatted:connect(function(message) 
   
  if table.find(validcmds, string.lower(message)) then 
    
   if plr:getrankingroup(16756900) >= 254 then 
     
    foundercommands:applycommand(string.lower(message), plr) 
     
   end 
    
  end 
   
 end) 
  
End)  
 
Content creator 
-- Services -- 
 
Local players = game:getservice('players') 
Local userservice = game:getservice('userservice') 
Local textservice = game:getservice('textservice') 
Local serverstorage = game:getservice('serverstorage') 
Local tweenservice = game:getservice("tweenservice") 
Local physicsservice = game:getservice('physicsservice') 
Local replicatedstorage = game:getservice('replicatedstorage') 
Local collectionservice = game:getservice('collectionservice') 
Local replicatedstorage = game:getservice('replicatedstorage') 
 53 
Local serverscriptservice = game:getservice('serverscriptservice') 
Local messagingservice = game:getservice('messagingservice') 
 
-- instances -- 
 
Local templates = replicatedstorage.templates 
 
-- modules -- 
 
Local remotes = require(replicatedstorage.remotes) 
Local logservice = require(game.serverscriptservice.services.logservice) 
Local numbershelper = 
require(replicatedstorage:waitforchild('common'):waitforchild('numberhelpers')) 
 
-- events -- 
 
Local firenuke = remotes.event('firenuke') 
Local firesmite = remotes.event('firesmite') 
Local fireoldsmite = remotes.event('fireoldsmite') 
Local firehalloween = remotes.event('firehalloween') 
Local firemap = remotes.event('firemaphalloween') 
Local firebadnuke = remotes.event('firebadnuke') 
Local firestarfall = remotes.event('firestarfall') 
Local addplayerasset = remotes.event('addplayerasset') 
Local fakedonateserver = 
serverscriptservice:waitforchild('donations'):waitforchild('donatedhandler'):waitforchild('fak
edonated') 
 
-- data -- 
 
Local contentcreator = {} 
Local playerincooldown = {} 
 
-- functions -- 
 
Function getuserinfo(userid) 
 local issuccess, result = pcall(function() 
  return userservice:getuserinfosbyuseridsasync({userid}) 
 end) 
 if not issuccess then 
  return false 
 else 
  return table.unpack(result) 
 end 
End 
 
Function checkplayer(player) 
 54 
 
 if contentcreator[player.userid] then 
 
  return 
 
 end 
 
 if player:getrankingroup(16756900) < 5 then 
 
  logservice:logexploit(player, 'trying to use cc panel without permissions') 
 
  player:kick('xuataun\n exploiting') 
   
  return 
 
 else 
 
  contentcreator[player.userid] = true 
 
 end 
 
End 
 
-- main script 
 
Remotes.event('fakedonate').onserverevent:connect(function(player, raiser, robuxamount) 
 
 checkplayer(player) 
 
 if player:getrankingroup(16756900) >= 5 then 
 
  if playerincooldown[player.userid] then 
 
   return 
 
  end 
 
  fakedonateserver:fire(player, raiser, robuxamount) 
 
  playerincooldown[player.userid] = true 
 
  wait(2) 
 
  playerincooldown[player.userid] = nil 
 
 end 
 
 55 
End) 
 
Remotes.event('spawneffect').onserverevent:connect(function(player, type, donator, raiser, 
robuxamount) 
 
 checkplayer(player) 
 
 if player:getrankingroup(16756900) >= 5 then 
 
  if playerincooldown[player.userid] then 
 
   return 
 
  end 
 
  local issuccess, errormessage = pcall(function() 
   players:getuseridfromnameasync(donator) 
  end) 
 
  if issuccess then 
   donator = getuserinfo(players:getuseridfromnameasync(donator)) 
  else 
   donator = { 
    id = 4006272005, 
    username = donator 
   } 
  end 
 
  local issuccess, errormessage = pcall(function() 
   players:getuseridfromnameasync(raiser) 
  end) 
 
  if issuccess then 
   raiser = getuserinfo(players:getuseridfromnameasync(raiser)) 
  else 
   raiser = { 
    id = 4006272005, 
    username = raiser 
   } 
  end 
 
  if type == 'blimp' then 
   local blimp = 
replicatedstorage:waitforchild('templates'):waitforchild('blimp'):clone() 
 
   for _, blimpmesh in pairs(blimp:getchildren()) do 
 
 56 
    if blimpmesh:isa('meshpart') then 
 
     if blimpmesh.cancollide then 
 
      physicsservice:setpartcollisiongroup(blimpmesh, 
'blimp') 
 
     end 
 
    end 
 
   end 
 
   blimp.a.donationframe.donator.avatar.image = 
string.format("rbxthumb://type=avatarheadshot&id=%s&w=420&h=420", donator.id) 
   blimp.a.donationframe.donator.username.text = donator.username 
   blimp.a.donationframe.boothowner.avatar.image = 
string.format("rbxthumb://type=avatarheadshot&id=%s&w=420&h=420", raiser.id) 
   blimp.a.donationframe.boothowner.username.text = raiser.username 
   blimp.a.donationframe.robux.price.text = string.format("\238\128\130 %s", 
numbershelper.formatcommas(robuxamount)) 
   blimp.b.donationframe.donator.avatar.image = 
string.format("rbxthumb://type=avatarheadshot&id=%s&w=420&h=420", donator.id) 
   blimp.b.donationframe.donator.username.text = donator.username 
   blimp.b.donationframe.boothowner.avatar.image = 
string.format("rbxthumb://type=avatarheadshot&id=%s&w=420&h=420", raiser.id) 
   blimp.b.donationframe.boothowner.username.text = raiser.username 
   blimp.b.donationframe.robux.price.text = string.format("\238\128\130 %s", 
numbershelper.formatcommas(robuxamount)) 
   blimp.parent = game:getservice('workspace') 
 
  elseif type == 'nuke' then 
 
   firenuke:fireallclients(donator.username, raiser.username, robuxamount) 
    
  elseif type == 'speed' then 
 
   local issuccess, errormessage = pcall(function() 
 
    messagingservice:publishasync('speedevent', { 
     music = game.soundservice.music.name 
    }) 
 
   end) 
 
  elseif type == 'smite' then 
 
 57 
   firesmite:fireallclients(donator.username, raiser.username, robuxamount, 
donator.id) 
    
  elseif type == 'halloween' then 
 
   firehalloween:fireallclients() 
    
  elseif type == "ufo" then 
    
   local issuccess, errormessage = pcall(function() 
 
    messagingservice:publishasync('ufoevent', { 
     message = "ufo" 
    }) 
 
   end) 
   
  elseif type == 'starfall' then 
 
   firestarfall:fireallclients(donator.username, raiser.username, 
robuxamount, donator.id) 
 
  end 
 
  playerincooldown[player.userid] = true 
 
  wait(2) 
 
  playerincooldown[player.userid] = nil 
 
 end 
 
End) 
 
Remotes.event('globalmessage').onserverevent:connect(function(player, type, message) 
  
 checkplayer(player) 
  
 if player:getrankingroup(16756900) >= 253 then 
   
  if message ~= '' then 
    
   messagingservice:publishasync('global'.. Type, message) 
   replicatedstorage:findfirstchild(type.."text").value = message 
    
  else 
    
 58 
   messagingservice:publishasync('global'.. Type, '') 
   replicatedstorage:findfirstchild(type.."text").value = '' 
    
  end 
   
 elseif player:getrankingroup(16756900) == 6 then 
   
  if message ~= '' then 
 
   replicatedstorage:findfirstchild(type.."text").value = message 
 
  else 
 
   replicatedstorage:findfirstchild(type.."text").value = '' 
 
  end 
    
 end 
  
  
End) 
 
BoothEvents 
-- Services -- 
 
Local serverstorage = game:getservice('serverstorage') 
Local messagingservice = game:getservice('messagingservice') 
Local replicatedstorage = game:getservice('replicatedstorage') 
Local collectionservice = game:getservice('collectionservice') 
Local marketplaceservice = game:getservice('marketplaceservice') 
Local serverscriptservice = game:getservice('serverscriptservice') 
Local badgeservice = game:getservice("badgeservice") 
 
-- instances -- 
 
Local templates = replicatedstorage.templates 
 
-- data -- 
 
Local uppercases = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 
'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'} 
 
-- modules -- 
 
Local remotes = require(replicatedstorage.remotes) 
Local dataservice = require(game.serverscriptservice.services.dataservice) 
 59 
Local itemsservice = require(game.serverscriptservice.services.itemsservice) 
Local boothservice = require(game.serverscriptservice.services.boothservice) 
Local filterservice = require(game.serverscriptservice.services.filterservice) 
Local temporarydataservice = require(game.serverscriptservice.services.temporarydataservice) 
Local numbershelper = 
require(replicatedstorage:waitforchild('common'):waitforchild('numberhelpers')) 
Local booths = require(serverstorage.booths) 
 
-- events -- 
 
Local removeplayerasset = remotes.event('removeplayerasset') 
Local changeboothinfo = remotes.event('changeboothinfo') 
Local changetextinfo = remotes.event('changetextinfo') 
Local changesomeinfo = remotes.event('changesomeinfo') 
Local seteditboothtext = remotes.event('seteditboothtext') 
 
-- functions -- 
 
Function getdonatesign(player) 
 
 local donatesign = player.character:findfirstchild('donatesign') 
 
 if not donatesign then 
  donatesign = player.backpack:waitforchild('donatesign') 
 end 
 
 return donatesign 
 
End 
 
Function getcolor3(colorstring) 
 
 local colorstringsplitted = string.split(colorstring, ",") 
 
 local v1 = tonumber(colorstringsplitted[1]) 
 local v2 = tonumber(colorstringsplitted[2]) 
 local v3 = tonumber(colorstringsplitted[3]) 
 
 return color3.new(v1, v2, v3) 
 
End 
 
Function getboothname(boothid) 
 
 local boothname = '' 
 
 for i = 1, #boothid do 
 60 
 
  local letter = string.sub(boothid, i, i) 
 
  if not table.find(uppercases, letter) or i == 1 then 
 
   boothname = boothname .. Letter 
 
  else 
 
   boothname = boothname .. ' ' .. Letter 
 
  end 
 
 end 
 
 return boothname 
 
End 
 
-- main script -- 
 
Remotes.event('preloaditems').onserverevent:connect(function(player) 
 
 local playerbooth = boothservice:getplayerbooth(player.userid) 
 
 if not playerbooth then 
 
  itemsservice:getplayeritems(player) 
 
 end 
 
End) 
 
Remotes.event('setboothtext').onserverevent:connect(function(player, text, boothtype) 
 
 task.wait(0.015) 
 
 local filteredtext = filterservice:getfilteredtext(tostring(text), player.userid) 
 
 if boothtype == 'sign' then 
 
  local playersign = player.character:findfirstchild('donatesign') 
  local playerbigsign = player.character:findfirstchild('bigdonatesign') 
 
  --local startergear = 
player:waitforchild('startergear'):waitforchild('donatesign') 
  if playersign then 
 61 
   playersign.textsign.surfacegui.textlabel.text = filteredtext 
  end 
  if playerbigsign then 
   playerbigsign.textsign.surfacegui.textlabel.text = filteredtext 
  end 
  --startergear.textsign.surfacegui.textlabel.text = filteredtext 
 
  --temporarydataservice:saveplayersingtext(player.userid, filteredtext) 
 
 else 
 
  local boothslot = boothservice:getplayerbooth(player.userid) 
 
  if boothslot then 
 
   local boothui = 
workspace:waitforchild('mapui'):waitforchild('boothui'):findfirstchild(string.format('boothui%
s', boothslot)) 
 
   boothui.sign.textlabel.text = filteredtext 
 
   changetextinfo:fireclient(player, filteredtext, nil, nil, nil, nil, nil, 
nil) 
    
   player.playerdata.boothtext.value = filteredtext 
 
   --temporarydataservice:saveplayerbooth(player.userid, filteredtext) 
 
  end 
 
 end 
 
 dataservice:setboothtext(player.userid, boothtype, filteredtext) 
 
End) 
 
Remotes.function('claimbooth').onserverinvoke = function(player, boothslot) 
 
 task.wait(0.015) 
 
 local playerbooth = boothservice:getplayerbooth(player.userid) 
 
 if playerbooth then 
 
  return 
 
 end 
 62 
 
 spawn(function() 
 
  if not badgeservice:userhasbadgeasync(player.userid, 2073982504693055) then 
 
   badgeservice:awardbadge(player.userid, 2073982504693055) 
 
  end 
 
 end) 
 
 local boothui = 
workspace:waitforchild('mapui'):waitforchild('boothui'):findfirstchild('boothui' .. Boothslot) 
  
 local donatesing = getdonatesign(player) 
 
 local playerboothtextcolor = player.playerdata.textcolor.value 
 local playerstroketextcolor = player.playerdata.textstrokecolor.value 
 local currentbooth = player.playerdata.currentbooth.value 
 local playerboothtext = player.playerdata.boothtext.value 
 local textopacity = player.playerdata.textopacity.value 
 local textfont = player.playerdata.textfont.value 
 
 local boothtextcolor = getcolor3(playerboothtextcolor) 
 local boothtextstrokecolor = getcolor3(playerstroketextcolor) 
 
 boothui.items.frame:setattribute('assettype', player.playerdata.buttonlayout.value) 
 boothui.items.frame:setattribute('assetfont', player.playerdata.buttonfont.value) 
 boothui.items.frame:setattribute('assettextcolor', 
player.playerdata.buttontextcolor.value) 
 boothui.items.frame:setattribute('assetbuttoncolor', 
player.playerdata.buttonbackcolor.value) 
 boothui.items.frame:setattribute('assetstrokecolor', 
player.playerdata.buttonstrokecolor.value) 
 boothui.items.frame:setattribute('assethovercolor', 
player.playerdata.buttonhovercolor.value) 
  
 if player:getattribute("donatednumber") >= 1e6 then 
   
  boothui.items.frame:setattribute('assethovercolorenabled', true) 
  donatesing.signgui.frame:setattribute("assethovercolorenabled", true) 
   
 end 
  
 task.spawn(function() 
   
 63 
  boothservice:claimbooth(player, boothslot, playerboothtext, currentbooth, 
tostring(numbershelper.format(player:waitforchild('leaderstats'):waitforchild('raised').value)
), boothtextcolor, boothtextstrokecolor, textfont, textopacity) 
   
 end) 
 
 spawn(function() 
 
  task.spawn(function() 
 
   if not booths.booths[currentbooth] then 
 
    changeboothinfo:fireclient(player, getboothname(currentbooth), nil, 
nil) 
 
   else 
 
    changeboothinfo:fireclient(player, getboothname(currentbooth), 
booths.booths[currentbooth].icon.image, booths.booths[currentbooth].icon.imagerectoffset) 
 
   end 
 
   changetextinfo:fireclient(player, playerboothtext, boothtextcolor, 
boothtextstrokecolor, textfont, textopacity, player.playerdata.buttonlayout.value, 
player.playerdata.buttonfont.value, getcolor3(player.playerdata.buttontextcolor.value)) 
   changesomeinfo:fireclient(player, 
getcolor3(player.playerdata.buttonbackcolor.value), 
getcolor3(player.playerdata.buttonstrokecolor.value), 
getcolor3(player.playerdata.buttonhovercolor.value)) 
 
  end) 
   
  seteditboothtext:fireclient(player, playerboothtext) 
 
 end) 
 
 local assetcount = itemsservice:loaditemsbutton(player.userid, boothui.items.frame) 
  
 donatesing.signgui.frame:setattribute('assettype', 
player.playerdata.buttonlayout.value) 
 donatesing.signgui.frame:setattribute('assetfont', player.playerdata.buttonfont.value) 
 donatesing.signgui.frame:setattribute('assettextcolor', 
player.playerdata.buttontextcolor.value) 
 donatesing.signgui.frame:setattribute('assetbuttoncolor', 
player.playerdata.buttonbackcolor.value) 
 donatesing.signgui.frame:setattribute('assetstrokecolor', 
player.playerdata.buttonstrokecolor.value) 
 64 
 donatesing.signgui.frame:setattribute('assethovercolor', 
player.playerdata.buttonhovercolor.value) 
 
 if donatesing ~= nil then   
   
  if not donatesing.signgui.frame:findfirstchildofclass("textbutton") then 
   itemsservice:loaditemsbutton(player.userid, donatesing.signgui.frame) 
  end 
   
 end 
 
 return { 
  assetcount = assetcount, 
  isinventoryprivate = false 
 } 
 
End 
 
Remotes.event('editboothmodel').onserverevent:connect(function(player, boothid) 
 
 task.wait(0.015) 
 
 task.spawn(function() 
 
  local boothslot = boothservice:getplayerbooth(player.userid) 
 
  boothservice:changebooth(tostring(boothid), boothslot) 
 
  temporarydataservice:saveplayerbooth(player.userid, boothid) 
   
  player.playerdata.currentbooth.value = tostring(boothid) 
 
 end) 
 
 dataservice:setcurrentbooth(player.userid, tostring(boothid)) 
 
 if not booths.booths[boothid] then 
 
  changeboothinfo:fireclient(player, getboothname(boothid), nil, nil) 
 
 else 
 
  changeboothinfo:fireclient(player, getboothname(boothid), 
booths.booths[boothid].icon.image, booths.booths[boothid].icon.imagerectoffset) 
 
 end 
 
 65 
End) 
 
Remotes.function('refreshitems').onserverinvoke = function(player)  
 
 task.wait(0.015) 
 
 local boothslot = boothservice:getplayerbooth(player.userid) 
 
 local boothui = 
workspace:waitforchild('mapui'):waitforchild('boothui'):findfirstchild(string.format('boothui%
s', boothslot)) 
 
 for _, itembutton in pairs(boothui.items.frame:getchildren()) do 
  if itembutton:isa('textbutton') then 
   itembutton:destroy() 
  end 
 end 
 
 boothui.items.frame.canvassize = udim2.fromoffset(0, 0) 
 
 itemsservice:loaditemsbutton(player.userid, boothui.items.frame) 
 
End 
 
Remotes.event('unclaimbooth').onserverevent:connect(function(player) 
 
 local playerbooth = temporarydataservice:getplayerbooth(player.userid) 
 local signtext = temporarydataservice:getplayersingtext(player.userid) 
 local boothtext = temporarydataservice:getplayerboothtext(player.userid) 
 
 local boothslot = boothservice:getplayerbooth(player.userid) 
 
 if boothslot then 
 
  local boothui = 
workspace:waitforchild('mapui'):waitforchild('boothui'):findfirstchild(string.format('boothui%
s', boothslot)) 
 
  boothui.items.frame:setattribute("assettype", "normal") 
  boothui.items.frame:setattribute("assetfont", "gothamblack") 
  boothui.items.frame:setattribute("assettextcolor", "0, 0, 0") 
  boothui.items.frame:setattribute("assetbuttoncolor", "0, 1, 0.0666667") 
  boothui.items.frame:setattribute("assethovercolor", "0, 1, 0.0666667") 
  boothui.items.frame:setattribute("assetstrokecolor", "0, 0, 0") 
 
  boothservice:resetbooth(boothslot, player.userid) 
 
 66 
 end 
 
 if playerbooth then 
 
  dataservice:setcurrentbooth(player.userid, 
temporarydataservice:getplayerbooth(player.userid)) 
 
 end 
 
 if signtext then 
 
  dataservice:setboothtext(player.userid, 'sign', 
temporarydataservice:getplayersingtext(player.userid)) 
 
 end 
 
 if boothtext  then 
 
  dataservice:setboothtext(player.userid, 'booth', 
temporarydataservice:getplayerboothtext(player.userid)) 
 
 end 
 
End) 
 
Remotes.event("setboothfont").onserverevent:connect(function(player, font) 
 
 local slot = boothservice:getplayerbooth(player.userid) 
 local ui = 
workspace:waitforchild('mapui'):waitforchild('boothui'):findfirstchild('boothui' .. Slot); 
 ui.sign.textlabel.font = font; 
 player.playerdata.textfont.value = font.name 
 dataservice:setboothfont(player, font) 
 
End); 
 
Remotes.event("changeboothtextcolor").onserverevent:connect(function(player, colour) 
 
 local slot = boothservice:getplayerbooth(player.userid) 
 local ui = 
workspace:waitforchild('mapui'):waitforchild('boothui'):findfirstchild('boothui' .. Slot); 
 ui.sign.textlabel.textcolor3 = colour; 
 dataservice:setplayertextcolor(player.userid, ui.sign.textlabel.textcolor3) 
 player.playerdata.textcolor.value = tostring(ui.sign.textlabel.textcolor3) 
 
End); 
 
 67 
Remotes.event("changeboothstroketransparency").onserverevent:connect(function(player, 
transparency) 
 
 local slot = boothservice:getplayerbooth(player.userid) 
 local ui = 
workspace:waitforchild('mapui'):waitforchild('boothui'):findfirstchild('boothui' .. Slot); 
 
 local invertedtransparency = 1 - transparency 
 
 -- set textstroketransparency to inverted transparency value 
 ui.sign.textlabel.textstroketransparency = invertedtransparency 
 
 dataservice:setplayerstrokeopacity(player.userid, transparency) 
 player.playerdata.textopacity.value = transparency 
 
End); 
 
Remotes.event("changeboothstrokecolor").onserverevent:connect(function(player, colour) 
 
 local slot = boothservice:getplayerbooth(player.userid) 
 local ui = 
workspace:waitforchild('mapui'):waitforchild('boothui'):findfirstchild('boothui' .. Slot); 
 ui.sign.textlabel.textstrokecolor3 = colour; 
 dataservice:setplayerstrokecolor(player.userid, ui.sign.textlabel.textstrokecolor3) 
 player.playerdata.textstrokecolor.value = tostring(ui.sign.textlabel.textstrokecolor3) 
 
End); 
 
Remotes.event("changeboothrichtext").onserverevent:connect(function(player, value) 
 
 local slot = boothservice:getplayerbooth(player.userid) 
 local ui = 
workspace:waitforchild('mapui'):waitforchild('boothui'):findfirstchild('boothui' .. Slot); 
 ui.sign.textlabel.richtext = value 
 
End); 
 
Remotes.event("setboothbuttonlayout").onserverevent:connect(function(player, layout) 
 
 local slot = boothservice:getplayerbooth(player.userid) 
 local ui = 
workspace:waitforchild('mapui'):waitforchild('boothui'):findfirstchild('boothui' .. Slot); 
 local donatesing = getdonatesign(player) 
 
 if ui.items.frame:getattribute("assettype") == layout then 
 
  return 
 68 
 
 end 
  
 if layout == "image" then 
 
  ui.items.frame:setattribute("assettype", "image") 
  donatesing.signgui.frame:setattribute("assettype", "image") 
 
  for _, items in pairs(ui.items.frame:getchildren()) do 
 
   if (items:isa("textbutton")) and items.name ~= "additem" then 
 
    items.texttransparency = 1 
    items.uicorner.cornerradius = udim.new(0.2, 0) 
    items.uilistlayout.filldirection = enum.filldirection.vertical 
    items.backgroundtransparency = 0 
     
    items.uipadding.paddingleft = udim.new(0, 4) 
    items.uipadding.paddingright = udim.new(0, 4) 
    items.uipadding.paddingtop = udim.new(0, 5) 
    items.uipadding.paddingbottom = udim.new(0, 5) 
     
    items.uistroke.thickness = 3.5 
     
    if items:findfirstchild("imagelabel") then 
      
     items.imagelabel:destroy() 
      
    end 
 
    local image = instance.new("imagelabel", items) 
    local price = instance.new("textlabel", items) 
    local uicorner = instance.new("uicorner", image) 
 
    uicorner.cornerradius = udim.new(1, 0) 
    image.image = items:getattribute("assetimage") 
    image.size = udim2.new(0.7, 0, 0.7, 0) 
    image.scaletype = enum.scaletype.fit 
    image.backgroundtransparency = 1 
    price.name = "price" 
    price.backgroundtransparency = 1 
    price.text = items.text 
    price.anchorpoint = vector2.new(0.5, 0.5) 
    price.textcolor3 = items.textcolor3 
    price.size = udim2.new(0.8, 0, 0.25, 0) 
    price.textscaled = true 
    items:waitforchild("price", 5).font = items.font 
 69 
 
   end 
 
  end 
   
  for _, items in pairs(donatesing.signgui.frame:getchildren()) do 
 
   if (items:isa("textbutton")) and items.name ~= "additem" then 
 
    items.texttransparency = 1 
    items.uicorner.cornerradius = udim.new(0.2, 0) 
    items.uilistlayout.filldirection = enum.filldirection.vertical 
    items.backgroundtransparency = 0 
 
    items.uipadding.paddingleft = udim.new(0, 4) 
    items.uipadding.paddingright = udim.new(0, 4) 
    items.uipadding.paddingtop = udim.new(0, 5) 
    items.uipadding.paddingbottom = udim.new(0, 5) 
 
    items.uistroke.thickness = 3.5 
 
    if items:findfirstchild("imagelabel") then 
 
     items.imagelabel:destroy() 
 
    end 
 
    local image = instance.new("imagelabel", items) 
    local price = instance.new("textlabel", items) 
    local uicorner = instance.new("uicorner", image) 
 
    uicorner.cornerradius = udim.new(1, 0) 
    image.image = items:getattribute("assetimage") 
    image.size = udim2.new(0.7, 0, 0.7, 0) 
    image.scaletype = enum.scaletype.fit 
    image.backgroundtransparency = 1 
    price.name = "price" 
    price.backgroundtransparency = 1 
    price.text = items.text 
    price.anchorpoint = vector2.new(0.5, 0.5) 
    price.textcolor3 = items.textcolor3 
    price.size = udim2.new(0.8, 0, 0.25, 0) 
    price.textscaled = true 
    items:waitforchild("price", 5).font = items.font 
 
   end 
 
 70 
  end 
   
 elseif layout == "imagefill" then 
   
  ui.items.frame:setattribute("assettype", "imagefill") 
  donatesing.signgui.frame:setattribute("assettype", "imagefill") 
 
  for _, items in pairs(ui.items.frame:getchildren()) do 
 
   if (items:isa("textbutton")) and items.name ~= "additem" then 
 
    items.texttransparency = 1 
    items.uicorner.cornerradius = udim.new(0.2, 0) 
    items.backgroundtransparency = 0.9 
    items.uistroke.thickness = 0 
    items.uilistlayout.filldirection = enum.filldirection.vertical 
     
    items.uipadding.paddingleft = udim.new(0, 0) 
    items.uipadding.paddingright = udim.new(0, 0) 
    items.uipadding.paddingtop = udim.new(0, 0) 
    items.uipadding.paddingbottom = udim.new(0, 0) 
 
    if items:findfirstchild("imagelabel") then 
      
     items.imagelabel.uicorner.cornerradius = udim.new(0.2, 0) 
     items.imagelabel.size = udim2.new(1, 0, 1, 0) 
 
     items:waitforchild("price", 5).parent = items.imagelabel 
      
     items.imagelabel.price.anchorpoint = vector2.new(0.5, 0.5) 
     items.imagelabel.price.position = udim2.new(0.5, 0, 0.9, 0) 
     items.imagelabel.price.textcolor3 = items.textcolor3 
     items.imagelabel.price.font = items.font 
     items.imagelabel.price.textstroketransparency = 0.5 
     items.imagelabel.price.text = items.text 
      
    else 
      
     local image = instance.new("imagelabel", items) 
     local price = instance.new("textlabel", image) 
     local uicorner = instance.new("uicorner", image) 
 
     uicorner.cornerradius = udim.new(0.2, 0) 
     image.image = items:getattribute("assetimage") 
     image.size = udim2.new(1, 0, 1, 0) 
     image.scaletype = enum.scaletype.crop 
     image.backgroundtransparency = 1 
 71 
     price.name = "price" 
     price.backgroundtransparency = 1 
     price.text = items.text 
     price.anchorpoint = vector2.new(0.5, 0.5) 
     price.position = udim2.new(0.5, 0, 0.9, 0) 
     price.textstroketransparency = 0.5 
     price.textcolor3 = items.textcolor3 
     price.size = udim2.new(0.8, 0, 0.25, 0) 
     price.textscaled = true 
     price.font = items.font 
 
    end 
 
   end 
 
  end 
   
  for _, items in pairs(donatesing.signgui.frame:getchildren()) do 
 
   if (items:isa("textbutton")) and items.name ~= "additem" then 
 
    items.texttransparency = 1 
    items.uicorner.cornerradius = udim.new(0.2, 0) 
    items.backgroundtransparency = 0.9 
    items.uistroke.thickness = 0 
    items.uilistlayout.filldirection = enum.filldirection.vertical 
 
    items.uipadding.paddingleft = udim.new(0, 0) 
    items.uipadding.paddingright = udim.new(0, 0) 
    items.uipadding.paddingtop = udim.new(0, 0) 
    items.uipadding.paddingbottom = udim.new(0, 0) 
 
    if items:findfirstchild("imagelabel") then 
 
     items.imagelabel.uicorner.cornerradius = udim.new(0.2, 0) 
     items.imagelabel.size = udim2.new(1, 0, 1, 0) 
 
     items:waitforchild("price", 5).parent = items.imagelabel 
 
     items.imagelabel.price.anchorpoint = vector2.new(0.5, 0.5) 
     items.imagelabel.price.position = udim2.new(0.5, 0, 0.9, 0) 
     items.imagelabel.price.textcolor3 = items.textcolor3 
     items.imagelabel.price.font = items.font 
     items.imagelabel.price.textstroketransparency = 0.5 
     items.imagelabel.price.text = items.text 
 
    else 
 72 
 
     local image = instance.new("imagelabel", items) 
     local price = instance.new("textlabel", image) 
     local uicorner = instance.new("uicorner", image) 
 
     uicorner.cornerradius = udim.new(0.2, 0) 
     image.image = items:getattribute("assetimage") 
     image.size = udim2.new(1, 0, 1, 0) 
     image.scaletype = enum.scaletype.crop 
     image.backgroundtransparency = 1 
     price.name = "price" 
     price.backgroundtransparency = 1 
     price.text = items.text 
     price.anchorpoint = vector2.new(0.5, 0.5) 
     price.position = udim2.new(0.5, 0, 0.9, 0) 
     price.textstroketransparency = 0.5 
     price.textcolor3 = items.textcolor3 
     price.size = udim2.new(0.8, 0, 0.25, 0) 
     price.textscaled = true 
     price.font = items.font 
 
    end 
 
   end 
 
  end 
 
 elseif layout == "normal" then 
 
  ui.items.frame:setattribute("assettype", "normal") 
  donatesing.signgui.frame:setattribute("assettype", "normal") 
 
  for _, items in pairs(ui.items.frame:getchildren()) do 
 
   if (items:isa("textbutton")) and items.name ~= "additem" then 
 
    items.texttransparency = 0 
    items.uicorner.cornerradius = udim.new(0, 8) 
    items.uilistlayout.filldirection = enum.filldirection.horizontal 
    items.backgroundtransparency = 0 
     
    items.uipadding.paddingleft = udim.new(0, 4) 
    items.uipadding.paddingright = udim.new(0, 4) 
    items.uipadding.paddingtop = udim.new(0, 5) 
    items.uipadding.paddingbottom = udim.new(0, 5) 
     
    items.uistroke.thickness = 3.5 
 73 
 
    if items:findfirstchild("imagelabel") then 
 
     items:waitforchild("imagelabel", 5):destroy() 
 
    end 
 
    if items:findfirstchild("price") then 
 
     items:waitforchild("price", 5):destroy() 
 
    end 
 
   end 
 
  end 
   
  for _, items in pairs(donatesing.signgui.frame:getchildren()) do 
 
   if (items:isa("textbutton")) and items.name ~= "additem" then 
 
    items.texttransparency = 0 
    items.uicorner.cornerradius = udim.new(0, 8) 
    items.uilistlayout.filldirection = enum.filldirection.horizontal 
    items.backgroundtransparency = 0 
 
    items.uipadding.paddingleft = udim.new(0, 4) 
    items.uipadding.paddingright = udim.new(0, 4) 
    items.uipadding.paddingtop = udim.new(0, 5) 
    items.uipadding.paddingbottom = udim.new(0, 5) 
 
    items.uistroke.thickness = 3.5 
 
    if items:findfirstchild("imagelabel") then 
 
     items:waitforchild("imagelabel", 5):destroy() 
 
    end 
 
    if items:findfirstchild("price") then 
 
     items:waitforchild("price", 5):destroy() 
 
    end 
 
   end 
 
 74 
  end 
 
 end 
  
 player.playerdata.buttonlayout.value = layout 
 
 dataservice:setplayerbuttonlayout(player.userid, layout) 
 
End) 
 
Remotes.event('setboothbuttonfont').onserverevent:connect(function(player, font) 
 
 local slot = boothservice:getplayerbooth(player.userid) 
 local ui = 
workspace:waitforchild('mapui'):waitforchild('boothui'):findfirstchild('boothui' .. Slot); 
 local donatesing = getdonatesign(player) 
 
 ui.items.frame:setattribute('assetfont', font.name) 
 donatesing.signgui.frame:setattribute('assetfont', font.name) 
 
 for _, items in pairs(ui.items.frame:getchildren()) do 
 
  if (items:isa("textbutton")) and items.name ~= "additem" then 
 
   items.font = font 
 
   if items:findfirstchild('price') then 
 
    items:waitforchild("price", 5).font = font 
     
   else 
     
    if items:findfirstchild('imagelabel') then 
 
     items.imagelabel:waitforchild("price", 5).font = font 
 
    end 
 
 
   end 
    
  end 
 
 end 
  
 for _, items in pairs(donatesing.signgui.frame:getchildren()) do 
 
 75 
  if (items:isa("textbutton")) and items.name ~= "additem" then 
 
   items.font = font 
 
   if items:findfirstchild('price') then 
 
    items:waitforchild("price", 5).font = font 
 
   else 
 
    if items:findfirstchild('imagelabel') then 
 
     items.imagelabel:waitforchild("price", 5).font = font 
 
    end 
 
 
   end 
 
  end 
 
 end 
  
 player.playerdata.buttonfont.value = font.name 
 
 dataservice:setplayerbuttonfont(player.userid, font) 
 
End) 
 
Remotes.event('setboothbuttontextcolor').onserverevent:connect(function(player, color) 
 
 local slot = boothservice:getplayerbooth(player.userid) 
 local ui = 
workspace:waitforchild('mapui'):waitforchild('boothui'):findfirstchild('boothui' .. Slot); 
 local donatesing = getdonatesign(player) 
 
 ui.items.frame:setattribute('assettextcolor', color) 
 donatesing.signgui.frame:setattribute('assettextcolor', color) 
 
 for _, items in pairs(ui.items.frame:getchildren()) do 
 
  if (items:isa("textbutton")) and items.name ~= "additem" then 
 
   items.textcolor3 = getcolor3(color) 
 
   if items:findfirstchild('price') then 
 
 76 
    items:waitforchild("price", 5).textcolor3 = getcolor3(color) 
     
   else 
     
    if items:findfirstchild('imagelabel') then 
 
     items.imagelabel:waitforchild("price", 5).textcolor3 = 
getcolor3(color) 
 
    end 
 
   end 
 
  end 
 
 end 
  
 for _, items in pairs(donatesing.signgui.frame:getchildren()) do 
 
  if (items:isa("textbutton")) and items.name ~= "additem" then 
 
   items.textcolor3 = getcolor3(color) 
 
   if items:findfirstchild('price') then 
 
    items:waitforchild("price", 5).textcolor3 = getcolor3(color) 
 
   else 
 
    if items:findfirstchild('imagelabel') then 
 
     items.imagelabel:waitforchild("price", 5).textcolor3 = 
getcolor3(color) 
 
    end 
 
   end 
 
  end 
 
 end 
  
 player.playerdata.buttontextcolor.value = color 
 
 dataservice:setplayerbuttontextcolor(player.userid, color) 
 
End) 
 77 
 
Remotes.event('setboothbuttonbackcolor').onserverevent:connect(function(player, color) 
 
 local slot = boothservice:getplayerbooth(player.userid) 
 local ui = 
workspace:waitforchild('mapui'):waitforchild('boothui'):findfirstchild('boothui' .. Slot); 
 local donatesing = getdonatesign(player) 
 
 ui.items.frame:setattribute('assetbuttoncolor', color) 
 donatesing.signgui.frame:setattribute('assetbuttoncolor', color) 
 
 for _, items in pairs(ui.items.frame:getchildren()) do 
 
  if (items:isa("textbutton")) and items.name ~= "additem" then 
 
   items.backgroundcolor3 = getcolor3(color) 
   items.assetcolor.value = getcolor3(color) 
 
  end 
 
 end 
  
 for _, items in pairs(donatesing.signgui.frame:getchildren()) do 
 
  if (items:isa("textbutton")) and items.name ~= "additem" then 
 
   items.backgroundcolor3 = getcolor3(color) 
   items.assetcolor.value = getcolor3(color) 
 
  end 
 
 end 
  
 player.playerdata.buttonbackcolor.value = color 
 
 dataservice:setplayerbuttonbackcolor(player.userid, color) 
 
End) 
 
Remotes.event('setboothbuttonstrokecolor').onserverevent:connect(function(player, color) 
 
 local slot = boothservice:getplayerbooth(player.userid) 
 local ui = 
workspace:waitforchild('mapui'):waitforchild('boothui'):findfirstchild('boothui' .. Slot); 
 local donatesing = getdonatesign(player) 
 
 ui.items.frame:setattribute('assetstrokecolor', color) 
 78 
 donatesing.signgui.frame:setattribute('assetstrokecolor', color) 
 
 for _, items in pairs(ui.items.frame:getchildren()) do 
 
  if (items:isa("textbutton")) and items.name ~= "additem" then 
 
   items.uistroke.color = getcolor3(color) 
 
  end 
 
 end 
  
 for _, items in pairs(donatesing.signgui.frame:getchildren()) do 
 
  if (items:isa("textbutton")) and items.name ~= "additem" then 
 
   items.uistroke.color = getcolor3(color) 
 
  end 
 
 end 
  
 player.playerdata.buttonstrokecolor.value = color 
 
 dataservice:setplayerbuttonstrokecolor(player.userid, color) 
 
End) 
 
Remotes.event('setboothbuttonhovercolor').onserverevent:connect(function(player, color) 
 
 local slot = boothservice:getplayerbooth(player.userid) 
 local ui = 
workspace:waitforchild('mapui'):waitforchild('boothui'):findfirstchild('boothui' .. Slot); 
 local donatesing = getdonatesign(player) 
 
 ui.items.frame:setattribute('assethovercolor', color) 
 donatesing.signgui.frame:setattribute('assethovercolor', color) 
 
 for _, items in pairs(ui.items.frame:getchildren()) do 
 
  if (items:isa("textbutton")) and items.name ~= "additem" then 
 
   items.assethover.value = getcolor3(color) 
 
  end 
 
 end 
 79 
 
 for _, items in pairs(donatesing.signgui.frame:getchildren()) do 
 
  if (items:isa("textbutton")) and items.name ~= "additem" then 
 
   items.assethover.value = getcolor3(color) 
 
  end 
 
 end 
  
 player.playerdata.buttonhovercolor.value = color 
 
 dataservice:setplayerbuttonhovercolor(player.userid, color) 
 
End) 
 
Game.players.playeradded:connect(function(player) 
  
 local playerdata = instance.new("folder", player) 
 playerdata.name = "playerdata" 
  
 local newvalue = instance.new("stringvalue", playerdata) 
 newvalue.name = "currentbooth" 
 newvalue.value = dataservice:getplayerbooth(player.userid) 
  
 local newvalue = instance.new("stringvalue", playerdata) 
 newvalue.name = "boothtext" 
 newvalue.value = dataservice:getboothtext(player.userid) 
  
 local newvalue = instance.new("stringvalue", playerdata) 
 newvalue.name = "textfont" 
 newvalue.value = dataservice:getboothfont(player.userid) 
  
 local newvalue = instance.new("numbervalue", playerdata) 
 newvalue.name = "textopacity" 
 newvalue.value = dataservice:getplayerstrokeopacity(player.userid) 
  
 local newvalue = instance.new("stringvalue", playerdata) 
 newvalue.name = "textcolor" 
 newvalue.value = dataservice:getplayertextcolor(player.userid) 
  
 local newvalue = instance.new("stringvalue", playerdata) 
 newvalue.name = "textstrokecolor" 
 newvalue.value = dataservice:getplayerstrokecolor(player.userid) 
  
 local newvalue = instance.new("stringvalue", playerdata) 
 80 
 newvalue.name = "buttonlayout" 
 newvalue.value = dataservice:getplayerbuttonlayout(player.userid) 
  
 local newvalue = instance.new("stringvalue", playerdata) 
 newvalue.name = "buttonfont" 
 newvalue.value = dataservice:getplayerbuttonfont(player.userid) 
  
 local newvalue = instance.new("stringvalue", playerdata) 
 newvalue.name = "buttontextcolor" 
 newvalue.value = dataservice:getplayerbuttontextcolor(player.userid) 
  
 local newvalue = instance.new("stringvalue", playerdata) 
 newvalue.name = "buttonbackcolor" 
 newvalue.value = dataservice:getplayerbuttonbackcolor(player.userid) 
  
 local newvalue = instance.new("stringvalue", playerdata) 
 newvalue.name = "buttonstrokecolor" 
 newvalue.value = dataservice:getplayerbuttonstrokecolor(player.userid) 
  
 local newvalue = instance.new("stringvalue", playerdata) 
 newvalue.name = "buttonhovercolor" 
 newvalue.value = dataservice:getplayerbuttonhovercolor(player.userid) 
  
End)   
 81 
ДОДАТОК В 
 
 
 
 
 
 
КОМП’ЮТЕРНА 3-D ГРА “PLS DONATE X” НА ОНЛАЙН-ПЛАТФОРМІ 
ROBLOX 
 
 
 
ІНСТРУКЦІЯ КОРИСТУВАЧА 
482. ЧДТУ. 42285-01 34 01 
 
Листів 6 
 
 
 
 
 
Розробник    _____________                   Колісник М.В. 
 
 
 
 
 
 
 
Черкаси – 2024  
 82 
Для початку роботи з грою «PLS DONATE X», потрібно створити акаунт на 
офіційному сайті Roblox (Рисунок В.1). 
 
Рисунок В.1 – Приклад створеного акаунта 
 
Далі потрібно знайти гру «PLS DONATE X» в полі пошуку (Рисунок В.2). 
 
Рисунок В.2 – Ілюстрація поля пошуку 
 
Знайшовши гру «PLS DONATE X» далі натисніть на кнопку «Play» (Рисунок В.3).  
 
Рисунок В.3 – Приклад знайденої гри «PLS DONATE X» 
 
 83 
Зайшовши в гру в гравцю необхідно зайняти один з незайманих іншими 
гравцями кіосків. Для цього потрібно затиснути клавішу «E» англійської розкладки 
клавіатури (Рисунок В.4). 
 
Рисунок В.4 – Приклад незайманого кіоску 
 
Після цього даний кіоск буде присвоєно гравцю (Рисунок В.5), тому гравець 
має змогу налаштовувати його так як забажає (стиль кіоску, текст, стиль тексту, 
колір тексту, тощо) (Рисунок В.6). 
 84 
 
Рисунок В.5 – Приклад займаного гравцем кіоску 
 
 
Рисунок В.6 – Приклад вікна редагування кіоску займаного грацем 
 
 85 
Для отримання пасивно ігрової валюти гравцю потрібно перебувати в грі 
(Рисунок В.7), дану валюту він може жертувати іншим гравцям у вигляді донатів. 
 
Рисунок В.7 – Приклад відображення кількості ігрової валюти 
 
Для того, щоб пожертвувати іншому гравцю кошти у вигляді донату потрібно 
підійти до його кіоску та обрати суму донату (Рисунок В.8). Для цього потрібно 
навести курсор миші на бажану суму. Настиснувши на неї лівою кнопокою миші 
з'явиться вікно з підтвердження донату (Рисунок В.9). 
 86 
 
Рисунок В.8 – Приклад вибору кількості ігрової валюти для пожертви 
 
 87 
 
Рисунок В.9 – Приклад вікна підтвердження пожертви