Trying to use a single script for multiple weapons

when switching weapons, something related to the equipping and unequipping functions breaks
if i equip one weapon, and then the other, the first weapon works fine, and the other one breaks
i tried printing the “equipped” variable and on the first weapon it works fine, but on the second the values are flipped, equipping returns false, and unequipping returns true

Character.ChildAdded:Connect(function(Child)
        
        if Child:IsA("Tool") then
        
            local Weapon = Child
            local Weapon_Barrel = Weapon:WaitForChild("Barrel")
    
            local Equipped = false

            Weapon.Equipped:Connect(function()

                Equipped = true

            end)

            Weapon.Unequipped:Connect(function()

                Equipped = false

            end)

Here’s the problem with your setup:

Character.ChildAdded is already acting like a Tool.Equipped event. That event runs when the tool is added to your character, which only happens when they equip a tool.

In addition to that, you’re connecting events every single time they equip (ChildAdded gets run and it’s a tool). You never disconnect those events, so re-equipping the same tool connects a new set of events.

What you should do is get rid of the Character.ChildAdded event, and just do something like this:

function InitTool(tool, isEquipped)
    -- use the isEquipped parameter as your "Equipped" variable
    tool.Equipped etc
    tool.Unequipped etc
end

for _, tool in backpack:GetChildren() do
    task.spawn(InitTool, tool, false)
end
local heldTool = character:FindFirstChildWhichIsA("Tool")
if heldTool then
    task.spawn(InitTool, heldTool, true)
end
1 Like

i removed the .equipped function, and the script works mostly as intended, the only issue now is, any weapon i had equipped beforehand will fire even if they arent equipped, for example if i equip 3 weapons on separate occassions, 3 rays will fire despite only 1 weapon being equipped? does your code snippet counter that? im not entirely sure whats different in the setup you have, in comparison to mine

Post your code as you have it now

local Equipped = false
    
    Character.ChildAdded:Connect(function(Child)
        
        if Child:IsA("Tool") then
            
            local Weapon = Child
            local Weapon_Barrel = Weapon:WaitForChild("Barrel")
            
            Equipped = true
            Weapon.Enabled = true

            Weapon.Unequipped:Connect(function()

                Equipped = false
                Weapon.Enabled = false

            end)
        
            Mouse.Button1Down:Connect(function()
        
                if Equipped == true and Weapon.Enabled == true then

                    local Bullet_Raycast =    WorkSpace:Raycast(Weapon.Barrel.Position,Weapon_Barrel.CFrame.LookVector*5000,RaycastParams)
            
                    if Bullet_Raycast then
-- stuff --

i have found out that when equipping a tool it gets taken out of the backpack and tried enabling and disabling tools if they are in the players backpack/character
but that hasnt helped at all

i printed the current weapon equipped, the equipped variable, and the enabled variable after the mouse.button1down function and it shows the wrong tools being equipped and the wrong values being true/false

Let me try to walk you through the event sequence here:

  1. Character.ChildAdded fires and Child:IsA(“Tool”), which means that the player just equipped a tool.
  2. Listen for unequip and mouse button 1 events.
  3. Player unequips the tool.
  4. Player clicks, and the still-connected mouse button 1 event hears this.
  5. Player re-equips the tool, and another set of Unequipped and Mouse Button1Down events get connected.

This is terribly inefficient, as every time you take out the same weapon, a new set of events get connected. It also causes some undefined behavior which is probably what is mixing up your Equipped variable.

Follow the code I wrote before, and only one equipped event per tool will ever be connected, rather than stacking on top of each other.

local Players = game:GetService("Players") 

Players.LocalPlayer.CharacterAdded:Wait()
Players.LocalPlayer.CharacterAppearanceLoaded:Connect(function(Character)
    
-- Variables --
    
-- Player -- 
    
    local Backpack = Players.LocalPlayer.Backpack
    
-- WeaponInitialization --
    
    local function InitializedWeapon(Weapon,IsEquipped) -- what is the point of IsEquipped here? its not used in any other part of the code

        IsEquipped = false

        Weapon.Equipped -- what does this even do??? all 3 of these functions arent mentioned anywhere alse
        Weapon.Unequipped
        Weapon.Activated
                    
    end

    for _,Weapon in(Backpack:GetChildren()) do
        
        task.spawn(InitializedWeapon(),Weapon,false)
        
    end

    local EquippedTool = Character:FindFirstChildWhichIsA("Tool")
    
    if EquippedTool then
        
        task.spawn(InitializedWeapon(),EquippedTool,true)
            
    end        
end)

tried implementing your code, but i dont really understand it?
like i see what youre getting at but i dont understand how this helps

The point of IsEquipped is for you to use it as you want in that tool’s function, though I guess if you’re wanting to have 1 variable in the whole script that always tells whether you have a tool equipped, then it doesnt fit that purpose.

Here’s an alternative to that:

function IsPlayerHoldingTool()
    return Character:FindFirstChildWhichIsA("Tool") ~= nil
end

Then, wherever it is you need to check whether you have a tool equipped, do this:
local IsEquipped = IsPlayerHoldingTool()

When I typed “weapon.Equipped etc” i meant you would fill those in with like Weapon.Equipped:Connect(function etc. The code was meant to be barebones just to show you an alternative