Roblox · Тайкун · урок 5
Деньги в кошельке, деньги в кассе и всё купленное сохраняются в DataStore и возвращаются при следующем входе.
Синим — что добавляем на этом уроке.
ServerScriptService └─ Stats (Script) — переписан Workspace └─ IndustryModel (Model) └─ Buttons (Folder) ├─ BuyButtons (Folder) │ └─ CandyDropper (Part) — бывший CandyDropperButton └─ GainButtons (Folder) └─ … CollectGainScript (Script) — обновлён Player (во время игры) — создаёт Stats ├─ leaderstats → Money — кошелёк ├─ GainIndustry (NumberValue) — копия кассы └─ ItemsFolder (Folder) — список покупок
Где: ServerScriptService · Script
Зачем: Создаёт кошелёк и список покупок; при входе загружает сохранение, при выходе и остановке сервера — записывает.
-- сервис сохранений
local DSS = game:GetService("DataStoreService")
-- наше хранилище
local store = DSS:GetDataStore("TycoonData")
-- серверное хранилище
local SS = game:GetService("ServerStorage")
-- производство
local tycoon = workspace.IndustryModel
-- купленное оборудование
local ownedItems = tycoon.Owned_Items
-- кнопки покупки
local buttons = tycoon.Buttons.BuyButtons
-- сохраняет данные игрока
local function Save(player)
-- данные не загрузились — не затираем сохранение нулями
if not player:GetAttribute("DataLoaded") then return end
-- список купленного
local items = {}
-- всё, что игрок купил
for _, item in pairs(player.ItemsFolder:GetChildren()) do
-- запоминаем имя
table.insert(items, item.Name)
-- конец перебора
end
-- кошелёк, касса, покупки
local data = {Money = player.leaderstats.Money.Value, Gain = player.GainIndustry.Value, Items = items}
-- защищённый вызов: сеть может подвести
local success, err = pcall(function()
-- записываем по ID игрока
store:SetAsync(player.UserId, data)
-- конец защищённого вызова
end)
-- не получилось — пишем причину в Output
if not success then warn(err) end
-- конец функции
end
-- игрок зашёл
game.Players.PlayerAdded:Connect(function(player)
-- папка для таблицы лидеров
local leaderstats = Instance.new("Folder", player)
-- имя, которое понимает Roblox
leaderstats.Name = "leaderstats"
-- кошелёк
local money = Instance.new("NumberValue", leaderstats)
-- называем Money
money.Name = "Money"
-- копия кассы — чтобы сохранить её при выходе
local gainIndustry = Instance.new("NumberValue", player)
-- называем GainIndustry
gainIndustry.Name = "GainIndustry"
-- список покупок игрока
local itemsFolder = Instance.new("Folder", player)
-- называем ItemsFolder
itemsFolder.Name = "ItemsFolder"
-- что-то куплено
ownedItems.ChildAdded:Connect(function(child)
-- записываем в список покупок
local item = Instance.new("StringValue", itemsFolder)
-- по имени предмета
item.Name = child.Name
-- конец обработчика
end)
-- защищённый вызов
local success, data = pcall(function()
-- читаем сохранение
return store:GetAsync(player.UserId)
-- конец защищённого вызова
end)
-- прочитали — при выходе можно сохранять
if success then player:SetAttribute("DataLoaded", true) end
-- прочитали, и сохранение есть (у нового игрока его нет)
if success and data then
-- кошелёк
money.Value = data.Money or 0
-- касса
gainIndustry.Value = data.Gain or 0
-- возвращаем деньги в кассу производства
tycoon.Values.Gain.Value = gainIndustry.Value
-- все покупки
for _, name in pairs(data.Items or {}) do
-- образец в ServerStorage
local sample = SS.Conveyors:FindFirstChild(name)
-- образец есть и ещё не стоит
if sample and not ownedItems:FindFirstChild(name) then
-- копия
local item = sample:Clone()
-- ставим в производство
item.Parent = ownedItems
-- кнопка с тем же именем
local button = buttons:FindFirstChild(name)
-- уже куплено — кнопку убираем
if button then button:Destroy() end
-- конец проверки
end
-- конец перебора
end
-- сервис недоступен
elseif not success then
-- причина — в Output
warn(data)
-- конец проверки
end
-- конец обработчика
end)
-- игрок вышел — сохраняем
game.Players.PlayerRemoving:Connect(Save)
-- сервер выключается (и Stop в Studio)
game:BindToClose(function()
-- всех, кто ещё в игре
for _, player in pairs(game.Players:GetPlayers()) do
-- сохраняем
Save(player)
-- конец перебора
end
-- конец функции
end)Где: … → GainButtons → CollectGainButton → GainButton → ClickDetector · Script
Зачем: Дополнительно держит копию кассы у владельца — её сохраняет Stats.
-- ClickDetector кнопки кассы
local clicker = script.Parent
-- экран: ClickDetector → GainButton → CollectGainButton
local screen = clicker.Parent.Parent.GainScreen
-- Values: CollectGainButton → GainButtons → Buttons → IndustryModel
local valuesFolder = screen.Parent.Parent.Parent.Parent.Values
-- нажали на кнопку кассы
clicker.MouseClick:Connect(function(player)
-- нажал владелец
if valuesFolder.Owner.Value == player then
-- сколько в кассе
local gain = valuesFolder.Gain.Value
-- сначала обнуляем — двойной клик не удвоит деньги
valuesFolder.Gain.Value = 0
-- переводим деньги в кошелёк
player.leaderstats.Money.Value += gain
-- конец проверки
end
-- конец обработчика нажатия
end)
-- сумма в кассе изменилась
valuesFolder.Gain.Changed:Connect(function(newGain)
-- показываем её на экране
screen.GainScreenGui.GainText.Text = newGain .. " $"
-- владелец
local owner = valuesFolder.Owner.Value
-- владелец есть и у него есть копия кассы
if owner and owner:FindFirstChild("GainIndustry") then
-- обновляем копию — её сохранит Stats
owner.GainIndustry.Value = newGain
-- конец проверки
end
-- конец обработчика
end)Запусти Play (или Run) и убедись: