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

Рюкзак: иконки, колесо мыши, лимит

У каждого предмета своя иконка, колесо мыши листает оружие, а нести можно только 4 предмета — подобрал пятый, и то, что было в руках, падает на землю.

Структура

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

ServerStorage → Loot
└─ Pistol, Rifle, … (Tool) — TextureId — иконка
StarterPlayer → StarterCharacterScripts
└─ ScrollSwitch (LocalScript) — Click (Sound) — по желанию
ServerScriptService
└─ BackpackLimit (Script)

Шаги

  1. Иконка: найди картинку (Toolbox → Images или загрузи свою), ПКМ → Copy Asset ID. Выдели Tool → свойство TextureId → вставь ID. В панели предметов вместо названия появится картинка.
  2. ScrollSwitch: колесо мыши — следующий или предыдущий предмет по кругу. Список собирается заново при каждом повороте колеса (в методичке — один раз при входе, новые предметы не листались).
  3. Колесо больше не приближает камеру — расстояние камеры фиксировано (12). Звук щелчка — Sound «Click» внутри скрипта.
  4. BackpackLimit: при каждом подборе считает предметы в рюкзаке и в руках. Больше 4 — то, что было в руках, падает позади тебя (обмен, как в настоящих королевских битвах). В методичке функция вызывалась без игрока и не работала.
  5. Менять родителя предмета прямо в момент подбора нельзя — поэтому выброс в task.defer, чуть позже.

Скрипты

ScrollSwitch

Где: StarterPlayer → StarterCharacterScripts · LocalScript
Зачем: Колесо мыши.

-- игроки
local Players = game:GetService("Players")
-- этот игрок
local player = Players.LocalPlayer
-- персонаж
local character = script.Parent
-- Humanoid
local humanoid = character:WaitForChild("Humanoid")
-- рюкзак
local backpack = player:WaitForChild("Backpack")
-- колёсико мыши
local mouse = player:GetMouse()
-- звук переключения (Sound внутри скрипта — по желанию)
local click = script:FindFirstChild("Click")
-- колесо теперь переключает оружие…
player.CameraMinZoomDistance = 12
-- …поэтому камеру фиксируем на одном расстоянии
player.CameraMaxZoomDistance = 12

-- инструменты по порядку — каждый раз заново (в методичке список был один при входе)
local function Tools()
    -- список
    local list = {}
    -- рюкзак
    for _, tool in ipairs(backpack:GetChildren()) do
        -- только инструменты
        if tool:IsA("Tool") then table.insert(list, tool) end
    -- конец перебора
    end
    -- что в руках
    local equipped = character:FindFirstChildOfClass("Tool")
    -- тоже в списке
    if equipped then table.insert(list, equipped) end
    -- по имени — порядок не прыгает
    table.sort(list, function(a, b) return a.Name < b.Name end)
    -- список и что в руках
    return list, equipped
-- конец функции
end
-- следующий (1) или предыдущий (-1)
local function Switch(step)
    -- погиб
    if humanoid.Health <= 0 then return end
    -- что есть
    local list, equipped = Tools()
    -- рюкзак пуст
    if #list == 0 then return end
    -- номер того, что в руках
    local index = table.find(list, equipped)
    -- что-то в руках
    if index then
        -- по кругу: после последнего — первый
        index = (index - 1 + step) % #list + 1
    -- руки пусты
    else
        -- первый или последний
        index = step > 0 and 1 or #list
    -- конец проверки
    end
    -- берём в руки
    humanoid:EquipTool(list[index])
    -- щелчок
    if click then click:Play() end
-- конец функции
end
-- колесо от себя — назад
mouse.WheelForward:Connect(function() Switch(-1) end)
-- колесо на себя — вперёд
mouse.WheelBackward:Connect(function() Switch(1) end)

BackpackLimit

Где: ServerScriptService · Script
Зачем: Не больше 4 предметов.

-- игроки
local Players = game:GetService("Players")
-- сколько предметов можно нести
local LIMIT = 4

-- все предметы: рюкзак и руки
local function Tools(player, character)
    -- список
    local list = {}
    -- рюкзак
    for _, tool in ipairs(player.Backpack:GetChildren()) do
        -- только инструменты
        if tool:IsA("Tool") then table.insert(list, tool) end
    -- конец перебора
    end
    -- руки
    for _, tool in ipairs(character:GetChildren()) do
        -- в руках
        if tool:IsA("Tool") then table.insert(list, tool) end
    -- конец перебора
    end
    -- список
    return list
-- конец функции
end
-- подобрал предмет — не много ли?
local function Check(player, character, newTool)
    -- влезает
    if not newTool:IsA("Tool") or #Tools(player, character) <= LIMIT then return end
    -- центр
    local root = character:FindFirstChild("HumanoidRootPart")
    -- персонажа нет
    if not root then return end
    -- что в руках
    local held = character:FindFirstChildOfClass("Tool")
    -- меняем: выбрасываем то, что в руках, иначе новое
    local drop = (held and held ~= newTool) and held or newTool
    -- сразу во время подбора менять родителя нельзя — чуть позже
    task.defer(function()
        -- за что двигать
        local handle = drop:FindFirstChild("Handle")
        -- на землю
        drop.Parent = workspace:FindFirstChild("Loot") or workspace
        -- в 6 studs позади
        if handle then handle.CFrame = root.CFrame * CFrame.new(0, 0, 6) end
    -- конец функции
    end)
-- конец функции
end

-- игрок зашёл
local function Setup(player)
    -- каждый новый персонаж (рюкзак тоже новый)
    player.CharacterAdded:Connect(function(character)
        -- рюкзак
        local backpack = player:WaitForChild("Backpack")
        -- что-то попало в рюкзак
        backpack.ChildAdded:Connect(function(tool) Check(player, character, tool) end)
        -- или сразу в руки (в методичке Check вызывался без игрока)
        character.ChildAdded:Connect(function(tool) Check(player, character, tool) end)
    -- конец функции
    end)
-- конец функции
end
-- новые игроки
Players.PlayerAdded:Connect(Setup)
-- кто зашёл раньше скрипта
for _, player in ipairs(Players:GetPlayers()) do Setup(player) end

Проверка

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