Roblox · Королевская битва · урок 3

Лут: оружие и снаряжение

Оружие, гранаты и аптечки появляются в случайных местах на полах домов. Подобрали — через 10 секунд появится новый предмет где-то ещё.

Структура

Синим — что добавляем на этом уроке.

Workspace
├─ LootSpawns (Folder)
│  └─ Tile (Part) — плитки на полах; невидимые, Anchored, CanCollide выкл.
└─ Loot (Folder) — сюда скрипт кладёт лут
ServerStorage
└─ Loot (Folder) — образцы: Pistol, Rifle, Shotgun, Medkit…
   └─ Medkit (Tool) — Handle → Heal (Sound); MedkitScript
ServerScriptService
├─ LootSpawn (Script)
└─ WeaponEffects (ModuleScript) — из раздела «Оружие» — нужен пушкам

Шаги

  1. Лут появляется только там, куда можно дойти: полы домов, базы, тайники — не крыши и не заборы.
  2. Построй несколько домов. На полу каждого — плоская деталь-плитка (Tile): невидимая, Anchored, CanCollide выкл. Все плитки — в папку Workspace → «LootSpawns». Workspace → пустая папка «Loot».
  3. Оружие — из раздела «Оружие» этой базы: пистолет, автомат, дробовик (собираются одной командой) и модуль WeaponEffects в ServerScriptService. Положи оружие в ServerStorage → папку «Loot».
  4. Аптечка: Tool «Medkit», Handle (красный кубик) со звуком «Heal», Script «MedkitScript» — лечит 50 и исчезает.
  5. LootSpawn: случайная плитка → случайная точка на ней → копия случайного предмета чуть выше пола. Следит, когда предмет подобрали (у него сменился родитель), и через 10 секунд кладёт новый.
  6. В методичке новый предмет создавался рекурсивно с ожиданием внутри Touched, двигалась только Handle и использовался устаревший Whitelist — исправлено.

Скрипты

LootSpawn

Где: ServerScriptService · Script
Зачем: Случайный лут.

-- образцы лута
local SS = game:GetService("ServerStorage")
-- оружие, гранаты, аптечки (Tool)
local loot = SS:WaitForChild("Loot")
-- невидимые плитки на полах домов
local spawns = workspace:WaitForChild("LootSpawns")
-- сюда кладём появившийся лут
local folder = workspace:WaitForChild("Loot")
-- сколько предметов лежит одновременно
local MAX_ACTIVE = 10
-- через сколько секунд после подбора появится новый
local RESPAWN_DELAY = 10
-- сколько лежит сейчас
local active = 0

-- случайная точка на случайной плитке
local function RandomPoint()
    -- все плитки
    local tiles = spawns:GetChildren()
    -- случайная
    local tile = tiles[math.random(1, #tiles)]
    -- по ширине плитки
    local x = (math.random() - 0.5) * tile.Size.X
    -- по длине
    local z = (math.random() - 0.5) * tile.Size.Z
    -- чуть выше плитки — предмет упадёт на пол
    return (tile.CFrame * CFrame.new(x, tile.Size.Y / 2 + 1.5, z)).Position
-- конец функции
end

-- положить один предмет
local function SpawnItem()
    -- образцы
    local items = loot:GetChildren()
    -- нечего, некуда или хватит
    if #items == 0 or #spawns:GetChildren() == 0 or active >= MAX_ACTIVE then return end
    -- случайный предмет
    local item = items[math.random(1, #items)]:Clone()
    -- за неё двигаем — приваренные детали едут следом
    local handle = item:FindFirstChild("Handle")
    -- предмет без Handle
    if not handle then return end
    -- место и случайный поворот
    handle.CFrame = CFrame.new(RandomPoint()) * CFrame.Angles(0, math.rad(math.random(0, 359)), 0)
    -- в мир
    item.Parent = folder
    -- лежит на один больше
    active += 1
    -- подписка на подбор
    local connection
    -- предмет куда-то переложили
    connection = item:GetPropertyChangedSignal("Parent"):Connect(function()
        -- всё ещё лежит
        if item.Parent == folder then return end
        -- больше не следим
        connection:Disconnect()
        -- подобрали
        active -= 1
        -- через 10 секунд — новый где-то ещё
        task.delay(RESPAWN_DELAY, SpawnItem)
    -- конец функции
    end)
-- конец функции
end

-- сразу раскладываем лут по карте
for i = 1, MAX_ACTIVE do SpawnItem() end

MedkitScript

Где: ServerStorage → Loot → Medkit · Script
Зачем: Аптечка.

-- аптечка
local tool = script.Parent
-- звук
local healSound = tool:WaitForChild("Handle"):WaitForChild("Heal")
-- сколько лечит
local HEAL = 50
-- уже использована
local used = false

-- клик
tool.Activated:Connect(function()
    -- кто держит
    local humanoid = tool.Parent:FindFirstChildOfClass("Humanoid")
    -- уже, или погиб
    if used or not humanoid or humanoid.Health <= 0 then return end
    -- одна аптечка — одно лечение
    used = true
    -- звук
    healSound:Play()
    -- лечим, не выше максимума
    humanoid.Health = math.min(humanoid.Health + HEAL, humanoid.MaxHealth)
    -- звук доиграет
    task.wait(0.5)
    -- аптечки больше нет
    tool:Destroy()
-- конец функции
end)

Проверка

Запусти Play (или Run) и убедись: