Hi there, and thanks for the reply. Here’s the script. Like I said, I’ve shamelessly borrowed this. Not a habit, but it initially seemed to do everything I wanted it to. Happy with all it does, and happy with my mods, but just can’t nail this final issue.
Here’s a screenshot of the hierarchy:
The code (localscript):
game:GetService('StarterGui'):SetCoreGuiEnabled(Enum.CoreGuiType.Backpack, false)
local uis = game:GetService("UserInputService")
local player = game.Players.LocalPlayer
local char = workspace:WaitForChild(player.Name) -- added WaitForChild
local bp = player.Backpack
local hum = char:WaitForChild("Humanoid")
local mouse = player:GetMouse()
local frame = script.Parent.Hotbar
local template = frame.Template
local equipped = 0 -- icon transparencies
local unequipped = 0.7
local Inventory = script.Parent.Inventory
local Template = Inventory.Items.Template
local InventoryButton = script.Parent.InventoryButton
local HotbarItems = {}
local previousInput
local inventoryOpen = false
-- Hotbar stuff
local iconSize = template.Size
local iconBorder = {x = 15, y = 5} -- pixel space between icons
local inputKeys = { -- dictionary for effective referencing
["One"] = {txt = "1"},
["Two"] = {txt = "2"},
["Three"] = {txt = "3"},
["Four"] = {txt = "4"},
["Five"] = {txt = "5"},
["Six"] = {txt = "6"},
["Seven"] = {txt = "7"},
["Eight"] = {txt = "8"},
["Nine"] = {txt = "9"},
}
local inputOrder = { -- array for storing the order of the keys
inputKeys["One"],inputKeys["Two"],inputKeys["Three"],inputKeys["Four"],inputKeys["Five"],inputKeys["Six"],inputKeys["Seven"],inputKeys["Eight"],inputKeys["Nine"]
}
-- So tool doesn't instasntly equip on pickup
local Tools = {}
for I, v in pairs(player.Backpack:GetChildren()) do
Tools[v] = true
end
char.ChildAdded:connect(function(Obj)
if Obj:IsA("Tool") then
if not Tools[Obj.Name] then
wait()
Obj.Parent = player.Backpack
if previousInput and previousInput["tool"] then
handleEquip(previousInput["tool"])
end
end
end
end)
--< functions >--
function getToolAmount(tool) -- Gets the total amount of a certain tool
local toolAmount = 0
for i,v in pairs(bp:GetChildren()) do
if v.Name == tool.Name then
toolAmount += 1
end
end
if char:FindFirstChild(tool.Name) then
toolAmount += 1
end
return toolAmount
end
function adjust() -- adjusts all icons in the hotbar
for key, value in pairs(inputKeys) do
local tool = value["tool"]
local icon = frame:FindFirstChild(value["txt"])
if tool then
icon.Image = tool.TextureId
icon.BackgroundTransparency = 0
wait(0.2)
local toolAmount = getToolAmount(tool)
if toolAmount > 1 then
icon.Label.Visible = true
icon.ImageLabel.Visible = true
else
icon.Label.Visible = false
icon.ImageLabel.Visible = false
end
icon.Label.Text = toolAmount
if char:FindFirstChild(tool.Name) then -- if the tool is equipped...
icon.BackgroundTransparency = equipped
end
else
icon.Label.Text = 0
icon.Label.Visible = false
icon.ImageLabel.Visible = false
icon.BackgroundTransparency = unequipped
icon.Image = ""
end
end
end
function handleEquip(tool) -- Equips and unequips the tools
if tool then
if tool.Parent ~= bp then
Tools[tool.Name] = false
hum:UnequipTools()
else
Tools[tool.Name] = true
hum:EquipTool(tool)
end
adjust()
end
end
function onKeyPress(inputObject) -- press keys to equip/unequip
local key = inputObject.KeyCode.Name
local value = inputKeys[key]
if value and uis:GetFocusedTextBox() == nil then -- don't equip/unequip while typing in text box
previousInput = value
handleEquip(value["tool"])
if value["tool"].Parent == char then
previousInput = value
else
previousInput = nil
end
end
end
function handleAddition(adding) -- Fires when a tool is added to the backpack
if adding:IsA("Tool") then
local new = true
for key, value in pairs(inputKeys) do
local tool = value["tool"]
if tool then -- if there is a tool...
if tool.Name == adding.Name then -- and the tool has the same name as the tool being added...
new = false -- then the tool being added is not new
end
end
end
if new then
for i = 1, #inputOrder do
local tool = inputOrder[i]["tool"]
if not tool and table.find(HotbarItems, adding.Name) then -- if the tool slot is free...
inputOrder[i]["tool"] = adding
break
end
end
end
adjust()
end
end
function handleRemoval(removing) -- Fires when a tool is removed from the player's character
if removing and removing:IsA("Tool") then
for i = 1, #inputOrder do
if removing.Parent ~= bp then
if inputOrder[i]["tool"] and inputOrder[i]["tool"].Name == removing.Name then
Tools[removing.Name] = false
if getToolAmount(removing) <= 0 then
-- If there is no more of the tool in the player backpack or on their character,
-- it is safe to assume it has been dropped into the workspace
inputOrder[i]["tool"] = nil
previousInput = nil
table.remove(HotbarItems, table.find(HotbarItems, removing.Name))
else
wait() -- added a wait because, without it, it would cause some timing issues
local tool = bp:FindFirstChild(removing.Name)
inputOrder[i]["tool"] = tool
handleEquip(tool)
end
break
end
end
end
end
adjust()
end
function create() -- creates all the icons at once (and will only run once)
local toShow = #inputOrder -- # operator can only be used with an array, not a dictionary
local totalX = (toShow*iconSize.X.Offset)+((toShow+1)*iconBorder.x)
local totalY = iconSize.Y.Offset + (2*iconBorder.y)
frame.Size = UDim2.new(0, totalX, 0, totalY)
frame.Position = UDim2.new(0.5, -(totalX/2), 1, -(totalY+(iconBorder.y*2)))
frame.Visible = true -- just in case!
for i = 1, #inputOrder do
local value = inputOrder[i]
local clone = template:Clone()
clone.Parent = frame
clone.Label.Text = value["txt"]
clone.Name = value["txt"]
clone.Visible = true
clone.Position = UDim2.new(0, (i-1)*(iconSize.X.Offset)+(iconBorder.x*i), 0, iconBorder.y)
clone.ImageTransparency = 0
local tool = value["tool"]
-- Creates a display label to show the tool's name
local label
clone.MouseEnter:Connect(function()
if value["tool"] then
local labelClone = script.Parent.ItemLabel:Clone()
labelClone.Text = "Test"
labelClone.Position = UDim2.new(0, mouse.X, 0, mouse.Y + 10)
labelClone.Visible = true
label = labelClone
labelClone.Parent = script.Parent
end
end)
clone.MouseLeave:Connect(function()
if label then
label:Destroy()
end
end)
clone.Tool.Activated:Connect(function() -- click icon to equip/unequip
for key, value in pairs(inputKeys) do
if value["txt"] == clone.Name and value["tool"] then
if inventoryOpen == true then
-- If the inventory is open, then the player is taking the tool off of their hotbar
if label then
label:Destroy()
end
previousInput = nil
table.remove(HotbarItems, table.find(HotbarItems, value["tool"].Name))
createInventorySlot(inputOrder[i]["tool"])
if char:FindFirstChild(value["tool"].Name) then
handleEquip(char:FindFirstChild(value["tool"].Name))
end
inputOrder[i]["tool"] = nil
handleRemoval(value["tool"])
clone.Parent.Image = ""
else -- If it is closed then they are trying to equip/unequip it
if char:FindFirstChild(value["tool"].Name) then
previousInput = nil
handleEquip(char:FindFirstChild(value["tool"].Name))
else
previousInput = value
handleEquip(bp:FindFirstChild(value["tool"].Name))
end
end
end
end
end)
end
template:Destroy()
end
function setup() -- sets up all the tools already in the backpack (and will only run once)
local tools = bp:GetChildren()
for i = 1, #tools do
if tools[i]:IsA("Tool") then -- does not assume that all objects in the backpack will be a tool (2.11.18)
for i = 1, #inputOrder do
local value = inputOrder[i]
if not value["tool"] then -- if the tool slot is free...
--value["tool"] = tools[i]
break -- stop searching for a free slot
end
end
end
end
create()
end
--< events >--
uis.InputBegan:Connect(onKeyPress)
--< start >--
setup()
bp.ChildAdded:Connect(handleAddition)
char.ChildRemoved:Connect(handleRemoval)
-- Inventory stuff
function hotbarAddition(tool) -- Adds a tool into the hotbar
table.insert(HotbarItems, tool.Name)
handleAddition(tool)
end
function createInventorySlot(tool) -- creates an item slot for a tool
local clone = Template:Clone() -- creates a clone of the item to display it
clone.Name = tool.Name
clone.Parent = Inventory.Items
local toolAmount = getToolAmount(tool)
if toolAmount > 1 then
clone.Label.Visible = true
end
clone.Label.Text = tostring(toolAmount)
local object = tool:Clone()
object.Parent = clone
object.Handle.Orientation = Vector3.new(0,0,0)
object.Handle.Position = Vector3.new(0,0,0)
clone.Image = object.TextureId
local label -- creates a label to display the name
clone.MouseEnter:Connect(function()
local labelClone = script.Parent.ItemLabel:Clone()
labelClone.Text = object.Name
labelClone.Position = UDim2.new(0, mouse.X, 0, mouse.Y + 10)
labelClone.Visible = true
label = labelClone
labelClone.Parent = script.Parent
end)
clone.MouseLeave:Connect(function()
if label then
label:Destroy()
end
end)
clone.Activated:Connect(function()
local FilledInputs = 0
for i = 1, #inputOrder do -- counts how many spot on the hotbar are full
if inputOrder[i]["tool"] then
FilledInputs += 1
end
end
if FilledInputs < #inputOrder then -- if the hotbar has an open space
clone:Destroy()
if label then
label:Destroy()
end
hotbarAddition(tool)
end
end)
clone.Visible = true
clone.Parent = Inventory.Items
end
function adjustInventory(child,tool)
if Inventory.Items:FindFirstChild(child.Name) then
local toolAmount = getToolAmount(child)
if toolAmount <= 0 then
Inventory.Items:FindFirstChild(child.Name):Destroy()
else
if toolAmount == 1 then
Inventory.Items:FindFirstChild(child.Name).Label.Text = toolAmount
Inventory.Items:FindFirstChild(child.Name).Label.Visible = false
Inventory.Items:FindFirstChild(child.Name).ImageLabel.Visible = false
else
Inventory.Items:FindFirstChild(child.Name).Label.Text = toolAmount
Inventory.Items:FindFirstChild(child.Name).Label.Visible = true
Inventory.Items:FindFirstChild(child.Name).ImageLabel.Visible = true
end
end
else if not table.find(HotbarItems, child.Name) then
createInventorySlot(child)
end
end
end
function createInventory() -- setups the entire initial inventory
for _,tool in pairs(bp:GetChildren()) do
local toolAmount = getToolAmount(tool)
if not Inventory.Items:FindFirstChild(tool) then
if toolAmount < 2 then
createInventorySlot(tool)
end
end
adjustInventory(tool)
end
end
InventoryButton.Activated:Connect(function() -- toggles the inventory
if Inventory.Visible == true then
Inventory.Visible = false
inventoryOpen = false
else
Inventory.Visible = true
inventoryOpen = true
end
end)
bp.ChildAdded:Connect(adjustInventory)
bp.ChildRemoved:Connect(adjustInventory)
char.ChildAdded:Connect(adjustInventory)
char.ChildRemoved:Connect(adjustInventory)
createInventory()