Магазин ускорений через единый контроллер
Купите временное ускорение за монеты, не сбрасывая другие бонусы.
За 10 монет игрок получает ускорение на 20 секунд. Другие бонусы продолжают работать.
1. Подготовьте объект
Где разместить: ServerScriptService: StatsController и SpeedShopServer; Workspace: SpeedShop (Part) с ProximityPrompt.
ServerScriptService
StatsController (ModuleScript из практики 91)
SpeedShopServer (Script)
Workspace
SpeedShop (Part)
ProximityPrompt- Сначала установите StatsController из практики 91, но не копируйте его второй раз.
- Создайте Part SpeedShop в Workspace, добавьте ProximityPrompt, задайте ActionText «Купить ускорение», ObjectText «Магазин», HoldDuration 0.5.
- В ServerScriptService создайте Script SpeedShopServer и вставьте код.
- Используйте только одну систему leaderstats.Coins. Этот урок НЕ создаёт и НЕ сохраняет валюту.
- Дайте тестовому игроку 20 Coins в своей системе монет. Подойдите к магазину и нажмите E.
- Проверьте недостаток монет, покупку с бонусом SpeedPad, истечение 20 секунд и двух игроков.
- При отсутствии Coins покупка не происходит; сообщения о покупке видны в Output сервера.
2. Вставьте код
-- Script: ServerScriptService/SpeedShopServer
local Players = game:GetService("Players")
local Controller = require(script.Parent:WaitForChild("StatsController"))
local prompt = workspace:WaitForChild("SpeedShop"):WaitForChild("ProximityPrompt")
local PRICE = 10
local DURATION = 20
local busy = {}
-- Не берём повторную плату, пока действует купленный бонус.
local paidUntil = {}
local paidCharacter = {}
prompt.Triggered:Connect(function(player)
if busy[player] then return end
busy[player] = true
local character = player.Character
local now = os.clock()
if paidCharacter[player] == character and now < (paidUntil[player] or 0) then
busy[player] = nil
return
end
local humanoid = character and character:FindFirstChildOfClass("Humanoid")
local root = character and character:FindFirstChild("HumanoidRootPart")
local shop = prompt.Parent
local stats = player:FindFirstChild("leaderstats")
local coins = stats and stats:FindFirstChild("Coins")
if not humanoid or humanoid.Health <= 0 or not root
or not shop:IsA("BasePart") or (root.Position - shop.Position).Magnitude > 15
or not coins or not coins:IsA("IntValue") or coins.Value < PRICE then
busy[player] = nil
return
end
if Controller.Apply(player, "ShopSpeed", {speed = 1.5}, DURATION) then
coins.Value -= PRICE
paidUntil[player] = now + DURATION
paidCharacter[player] = character
print(player.Name .. " купил ускорение за " .. PRICE .. " монет")
end
busy[player] = nil
end)
Players.PlayerRemoving:Connect(function(player)
busy[player] = nil
paidUntil[player] = nil
paidCharacter[player] = nil
end)3. Проверьте в игре
Нажмите Play в Roblox Studio и проверьте действие механики. Если механика не работает, откройте окно Output и проверьте тип скрипта, его расположение и названия объектов.
Когда проверите механику в Roblox Studio, отметьте практику как выполненную. Отметка хранится только в этом браузере, не в личном кабинете.
Добавляйте механики по одной и проверяйте окно Output. Не создавайте несколько одинаковых систем монет или интерфейсов; скрипты, меняющие WalkSpeed, прыжок или освещение, могут влиять друг на друга.
Измените цену на 5 монет.
Добавьте второй магазин с другим множителем скорости и названием эффекта.
Соберите магазин с несколькими улучшениями и протестируйте баланс цен.
4. Проверьте себя
Кто должен проверять количество монет перед покупкой?
Если покупка не происходит, проверьте leaderstats.Coins (IntValue), ProximityPrompt и названия объектов. В одной игре должен быть только один скрипт создания и сохранения Coins. При недостатке монет сервер ничего не списывает.