Here is my script
local Players = game:GetService('Players')
local RunService = game:GetService('RunService')
local StarterGui = game:GetService('StarterGui')
local UserInputService = game:GetService('UserInputService')
-- disable our core gui
repeat
local Success, Error = pcall(function()
StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.Backpack, false)
end)
wait()
until Success
--[!] const
-- max tool slot size
local TOOL_MAX_SLOTS = 10
-- i.e. GUI-related tool slot settings
local TOOL_SIZE = 50 -- tool icon size
local TOOL_BORDER_OFFSET = 15 -- gap between icons
local TOOL_BOTTOM_OFFSET = 20 -- offset from bottom of screen
-- keycode values, see here: https://create.roblox.com/docs/reference/engine/enums/KeyCode
--
-- where:
-- 48 = Zero
-- 49 = One
-- n = ...
-- 57 = Nine
--
local NUMERIC_KEYCODE_ZRO = 48
local NUMERIC_KEYCODE_MIN = 49
local NUMERIC_KEYCODE_MAX = 57
-- i.e. the range of Enum.KeyCode[name].Value that represents numeric keycodes
local NUMERIC_KEYCODE_RANGE = NumberRange.new(NUMERIC_KEYCODE_MIN, NUMERIC_KEYCODE_MAX)
-- i.e. set up a dictionary that maps the value to a specific keycode
local KEYCODE_VALUES = { }
for _, keycode in next, Enum.KeyCode:GetEnumItems() do
KEYCODE_VALUES[keycode.Value] = keycode
end
--[!] utils
-- checks whether a character is alive, and has valid character instances e.g. humanoid + rootpart
local function tryGetCharacterInstances(character)
if typeof(character) ~= 'Instance' or not character:IsA('Model') or not character:IsDescendantOf(workspace) then
return false
end
local humanoid = character:FindFirstChildOfClass('Humanoid')
local humanoidState = humanoid and humanoid:GetState() or Enum.HumanoidStateType.Dead
local humanoidRootPart = humanoid and humanoid.RootPart or nil
if humanoidState == Enum.HumanoidStateType.Dead or not humanoidRootPart then
return false
end
return true, humanoid, humanoidRootPart
end
-- wait until we find a valid character
local function awaitCharacter(player)
if typeof(player) ~= 'Instance' or not player:IsA('Player') then
return nil
end
local character
while not character do
if not player or not player:IsDescendantOf(Players) then
break
end
local char = player.Character
if not char then
player.CharacterAdded:Wait()
continue
end
local valid = tryGetCharacterInstances(char)
if not valid then
RunService.Stepped:Wait()
continue
end
character = char
end
return character
end
--[!] methods
local function createToolSlot(parent, index, keyCode)
local position = index - math.ceil(TOOL_MAX_SLOTS*0.5)
local frame = Instance.new('ImageButton')
frame.Name = 'Toolslot' .. index
frame.Size = UDim2.fromOffset(TOOL_SIZE, TOOL_SIZE)
frame.Position = UDim2.new(0.5, position*(TOOL_SIZE + TOOL_BORDER_OFFSET*0.5), 1, -TOOL_BOTTOM_OFFSET)
frame.AnchorPoint = Vector2.new(0.5, 1)
frame.BorderSizePixel = 1
frame.BackgroundTransparency = 0
frame.Image = ''
frame.ImageTransparency = 1
local posLabel = Instance.new('TextLabel')
posLabel.Name = 'PositionLabel'
posLabel.Size = UDim2.fromOffset(13, 13)
posLabel.Position = UDim2.fromScale(0, 0)
posLabel.AnchorPoint = Vector2.new(0, 0)
posLabel.BorderSizePixel = 1
posLabel.BackgroundTransparency = 1
posLabel.Text = tostring(index)
posLabel.Parent = frame
local StackLabel = Instance.new('TextLabel')
StackLabel.Name = 'StackLabel'
StackLabel.Size = UDim2.fromOffset(13, 13)
StackLabel.Position = UDim2.fromScale(0.8, 0.8)
StackLabel.AnchorPoint = Vector2.new(0, 0)
StackLabel.BorderSizePixel = 1
StackLabel.BackgroundTransparency = 1
StackLabel.Transparency = 1
StackLabel.Text = 0
StackLabel.Parent = frame
local toolLabel = Instance.new('TextLabel')
toolLabel.Name = 'ToolLabel'
toolLabel.Size = UDim2.new(1, 0, 0, 25)
toolLabel.Position = UDim2.fromScale(0.5, 0.5)
toolLabel.AnchorPoint = Vector2.new(0.5, 0.5)
toolLabel.BorderSizePixel = 1
toolLabel.TextColor3 = Color3.fromHSV(0.98, 0.7, 0.75)
toolLabel.BackgroundTransparency = 1
toolLabel.Text = ''
toolLabel.Parent = frame
toolLabel.TextScaled = true
frame.Parent = parent
return frame, toolLabel
end
-- used to check whether the tool is still within the
-- player's backpack / their character; and if not, will remove
-- it from the slots e.g. in cases where they pressed backspace to drop the tool
--
local function handleToolRemoval(player, toolSlots, object, connection)
-- make sure we've not just equipped the tool
local character = player.Character
if object:IsDescendantOf(player) or (character and object:IsDescendantOf(character)) then
return
end
-- find the tool slot so we can remove it
local toolSlot
for i = 1, TOOL_MAX_SLOTS, 1 do
local slot = toolSlots[i]
if slot.Tool == object then
toolSlot = slot
break
end
end
-- stop listening to this tool's ancestry since it's been not related to our player now
if connection and connection.Connected then
connection:Disconnect()
end
end
local function RemoveToolSlot(toolSlot)
if toolSlot then
toolSlot.Tool = nil
toolSlot.Label.Text = ''
end
end
-- used to add the tool to the next best slot
-- if not already present
--
local function handleToolAdded(player, toolSlots, object, FromCharacter)
if not object:IsA('Tool') then
return
end
-- make sure we don't already exist
-- otherwise select next best empty slot
local CreateNewSlot = true
local NewItem = object.NewItem
if FromCharacter == true then
if NewItem.Value == true then
NewItem.Value = false
for i,item in pairs(Players.LocalPlayer.Character:GetChildren()) do
if item:IsA("Tool") then
for i, S in pairs(script.Parent:GetChildren()) do
if S:IsA("ImageButton") then
if S.ToolLabel.Text == item.Name then
S.StackLabel.Transparency = true
if S.StackLabel.Text == "0" then
S.StackLabel.Text = tonumber(S.StackLabel.Text) + 2
CreateNewSlot = false
else
S.StackLabel.Text = tonumber(S.StackLabel.Text) + 1
CreateNewSlot = false
end
else
end
end
end
end
end
if CreateNewSlot == true then
local bestSlot
for i = 1, TOOL_MAX_SLOTS, 1 do
local slot = toolSlots[i]
if slot.Tool == object then
return
elseif not bestSlot and not slot.Tool then
bestSlot = i
end
end
if bestSlot then
-- i.e. we're a new tool
bestSlot = toolSlots[bestSlot]
bestSlot.Tool = object
bestSlot.Label.Text = object.Name
end
end
end
end
-- watch the ancestry of the object (i.e. it's parent)
-- to check when the player removes the tool from its backpack
-- and/or its character
local watchdog
watchdog = object.AncestryChanged:Connect(function ()
handleToolRemoval(player, toolSlots, object, watchdog)
end)
end
--[!] setup
local player = Players.LocalPlayer
local backpack = player:WaitForChild('Backpack')
local character = awaitCharacter(player)
local screenGui = script.Parent
-- states
local toolSlots = table.create(TOOL_MAX_SLOTS) -- i.e. all of the tool slots
local toolSlotMap = { } -- i.e. a map between a keycode and a tool slot
local selectedToolSlot -- the tool slot we're trying to swap
local isChangingKeybinds = false -- whether we're trying to change our keybinds
-- set up our keybind slots
for i = 1, TOOL_MAX_SLOTS, 1 do
-- get the KeyCode from the slot number
local keyCode
if i == TOOL_MAX_SLOTS then
keyCode = KEYCODE_VALUES[NUMERIC_KEYCODE_ZRO]
else
keyCode = KEYCODE_VALUES[NUMERIC_KEYCODE_MIN + (i - 1)]
end
-- set up the slot
local slot, toolLabel = createToolSlot(screenGui, i, keyCode)
-- append to our list
toolSlots[i] = {
Tool = nil,
Slot = slot,
Label = toolLabel,
ScreenGui = screenGui,
Index = i,
KeyCode = keyCode,
}
toolSlotMap[keyCode] = i
-- set up the listener
slot.MouseButton1Click:Connect(function ()
-- set the selected one to our current slot
-- if we aren't already trying to change it
if not isChangingKeybinds then
isChangingKeybinds = true
selectedToolSlot = i
return
end
local StackLabels = {screenGui.Toolslot1.StackLabel, screenGui.Toolslot2.StackLabel, screenGui.Toolslot3.StackLabel, screenGui.Toolslot4.StackLabel,screenGui.Toolslot5.StackLabel,
screenGui.Toolslot6.StackLabel, screenGui.Toolslot7.StackLabel, screenGui.Toolslot8.StackLabel,screenGui.Toolslot9.StackLabel, screenGui.Toolslot10.StackLabel}
-- swap our slots around
local swapSlot = toolSlots[selectedToolSlot]
local thisSlot = toolSlots[i]
-- swap our tool reference around
thisSlot.Tool, swapSlot.Tool = swapSlot.Tool, thisSlot.Tool
-- swap the label text around
thisSlot.Label.Text, swapSlot.Label.Text = swapSlot.Label.Text, thisSlot.Label.Text
-- swap the transparency around
StackLabels[i].Transparency, StackLabels[selectedToolSlot].Transparency = StackLabels[selectedToolSlot].Transparency, StackLabels[i].Transparency
-- swap the stack nums around
StackLabels[i].Text, StackLabels[selectedToolSlot].Text = StackLabels[selectedToolSlot].Text, StackLabels[i].Text
isChangingKeybinds, selectedToolSlot = false, nil
end)
end
-- set up our input action(s)
UserInputService.InputBegan:Connect(function (input, gameProcessed)
-- ignore if not keyboard input and/or it's used by something else e.g. a textbox
local inputType = input.UserInputType
if gameProcessed or inputType ~= Enum.UserInputType.Keyboard then
return
end
-- ignore if we're dead
local isValid, humanoid = tryGetCharacterInstances(character)
if not isValid then
return
end
-- try to get the slot from the keycode and ignore if it doesn't exist
local keyCode = input.KeyCode
local slotIndex = toolSlotMap[keyCode]
local toolSlot = slotIndex and toolSlots[slotIndex] or nil
if keyCode == Enum.KeyCode.Q then
for i, Item in pairs(Players.LocalPlayer.Character:GetChildren()) do
if Item:IsA("Tool") then
for i, ItemSlot in pairs(script.Parent:GetChildren()) do
if ItemSlot:IsA("ImageButton") then
if ItemSlot.ToolLabel.Text == Item.Name then
if tonumber(ItemSlot.StackLabel.Text) == 0 then
print(tonumber(ItemSlot.StackLabel.Text))
print("deeds")
ItemSlot.StackLabel.Text = 0
for i, Item in pairs(Players.LocalPlayer.Character:GetChildren() and Players.LocalPlayer.Backpack:GetChildren()) do
if Item:IsA("Tool") then
if Item.Name == ItemSlot.ToolLabel.Text then
toolSlots[tonumber(ItemSlot.PositionLabel.Text)].Label.Text = ""
toolSlots[tonumber(ItemSlot.PositionLabel.Text)].Tool = nil
Item:Destroy()
humanoid:UnequipTools()
end
end
end
elseif tonumber(ItemSlot.StackLabel.Text) == 2 then
print("2")
ItemSlot.StackLabel.Text = 0
ItemSlot.StackLabel.Transparency = 1
elseif tonumber(ItemSlot.StackLabel.Text) >= 2 then
ItemSlot.StackLabel.Text = tonumber(ItemSlot.StackLabel.Text) - 1
end
end
end
end
end
end
end
if not toolSlot then
return
end
-- if we haven't got a tool for this slot we can ignore it
local tool = toolSlot.Tool
if not tool then
return
end
-- equip it if we're not using it;
-- otherwise unequip it
if tool.Parent ~= character then
humanoid:EquipTool(tool)
else
humanoid:UnequipTools()
end
end)
-- set up our listener(s)
-- - we need to make sure we look at those already
-- in the backback too
--
-- - we also need to make sure any tools added to the char
-- via pickup get added
--
for _, object in next, backpack:GetChildren() do
handleToolAdded(player, toolSlots, object)
end
backpack.ChildAdded:Connect(function (object)
handleToolAdded(player, toolSlots, object, false)
end)
character.ChildAdded:Connect(function (object)
handleToolAdded(player, toolSlots, object, true)
end)
Ive took a little bit to work on simplifying and learning tables here is my script from 2 weeks ago