Help regarding animations and attributes

The script works fine with one person, but as soon as there are two it starts bugging out. Once the person unequips the weapon, it immediately makes the equipped attribute true, bugging it out, with addition to not playing the animation in reverse.

Code with one person:

Code with two:

Script (Placed in StarterCharacterScripts) :

local equipEvent = game.ReplicatedStorage.EquipEvent

-- Dictionary to store animations for each player
local playerAnimations = {}

local function equipWeapon(player)
	local humanoid = player.Character:FindFirstChild("Humanoid")

	-- Check if animations are already loaded, if not, load them for this player
	if not playerAnimations[player] then
		playerAnimations[player] = {}
		playerAnimations[player].stowAnim = humanoid:LoadAnimation(game.StarterPlayer.StarterCharacterScripts.Animate.Animations.MinigunStow)
		playerAnimations[player].stowAnimEnd = humanoid:LoadAnimation(game.StarterPlayer.StarterCharacterScripts.Animate.Animations.MinigunStowEnd)
	end

	local stowAnim = playerAnimations[player].stowAnim
	local stowAnimEnd = playerAnimations[player].stowAnimEnd

	-- Stop previous animations if they're playing
	stowAnim:Stop()
	stowAnimEnd:Stop()

	if player.Character:GetAttribute("Equipped") == nil or player.Character:GetAttribute("Equipped") == false then
		if player.Character:FindFirstChild("WeaponPart") == nil then
			local weapon = game.Workspace.WeaponPart:Clone()

			weapon.Parent = player.Character

			local motor = Instance.new("Motor6D")

			motor.Parent = player.Character.HumanoidRootPart
			motor.Part0 = player.Character.HumanoidRootPart
			motor.Part1 = weapon
		end

		stowAnim:Play(0.1, 1, -1) -- Adjust the speed, loop count, etc., as needed

		-- Wait for the animation to finish
		stowAnim.Stopped:Wait()

		print("Equip: ", player)

		player.Character:SetAttribute("Equipped", true)
		player.Character:SetAttribute("WeaponType", "Minigun")
	else
		player.Character:SetAttribute("Equipped", false)
		player.Character:SetAttribute("WeaponType", nil)

		stowAnim:Play()
		stowAnim:AdjustSpeed(1)

		-- Wait for the animation to finish
		stowAnim.Stopped:Wait()

		stowAnimEnd:Play()

		-- Wait for the animation to finish
		stowAnimEnd.Stopped:Wait()

		-- Cleanup, if needed
		-- player.Character.HumanoidRootPart:FindFirstChild("Motor6D"):Destroy()
		-- player.Character:FindFirstChild("WeaponPart"):Destroy()
	end
end

equipEvent.OnServerEvent:Connect(equipWeapon)
1 Like

The issue is the equipEvent.

When you fire equipEvent, every client will receive that event, running the function associated.

I would recommend placing this event inside of the tool the player is using, that way there is no confusion around who’s the event for.

Alternatively, you could send a player value in the event which specifies who the equip event is meant for.

That’s not true, it only listens for one client’s onServerEvent call, getting that player.

And OP @Ld7620 I need more info, such as the client sided code for this script to have full context into potential issues.

Ah I see. This is the code that triggers the event:

Specific Function:

local function onInput(input)
	local player = game.Players.LocalPlayer
	local character = player.Character or player.CharacterAdded:Wait()
	
	if input.KeyCode == Enum.KeyCode.R and character:GetAttribute("Reloading") == false then
		reloadEvent:FireServer()
	end
	if input.KeyCode == Enum.KeyCode.One then
		equipEvent:FireServer()
	end
end

Entire script:

local replicatedStorage = game:GetService("ReplicatedStorage")
local shootEvent = replicatedStorage:WaitForChild("ShootEvent")
local UIS = game:GetService("UserInputService")
local runService = game:GetService("RunService")
local CAS = game:GetService("ContextActionService")
local reloadEvent = replicatedStorage:WaitForChild("ReloadEvent")
local equipEvent = replicatedStorage:WaitForChild("EquipEvent")
local aimEvent = replicatedStorage:WaitForChild("AimInEvent")
local gunData = require(replicatedStorage:WaitForChild("gunData"))
local player = game.Players.LocalPlayer
local mouse = player:GetMouse()
local character = player.Character or player.CharacterAdded:Wait()
local gunStats

runService.Stepped:Connect(function() 
	local player = game.Players.LocalPlayer
	local mouse = player:GetMouse()
	local character = player.Character or player.CharacterAdded:Wait()
	
	if character:GetAttribute("Equipped") == true then
		gunStats = gunData.getData(player.Character:GetAttribute("WeaponType"))
		if gunStats then
			if gunStats.firingMode == "fullAuto" then
				if UIS:IsMouseButtonPressed(Enum.UserInputType.MouseButton1) then
					local shootPos = character.WeaponPart.ShootAtt.WorldPosition
					local direction = character.WeaponPart.ShootAtt.WorldCFrame.LookVector
					
					shootEvent:FireServer(shootPos, direction)
				end
			end
		else
			gunStats = gunData.getData(player.Character:GetAttribute("WeaponType"))
		end
	end
end)

local function onInput(input)
	local player = game.Players.LocalPlayer
	local character = player.Character or player.CharacterAdded:Wait()
	
	if input.KeyCode == Enum.KeyCode.R and character:GetAttribute("Reloading") == false then
		reloadEvent:FireServer()
	end
	if input.KeyCode == Enum.KeyCode.One then
		equipEvent:FireServer()
	end
end

local function button2Down()
	--player:SetAttribute("Spread", 0.025)
	aimEvent:FireServer("button2Down")
end

local function button2Up()
	--player:SetAttribute("Spread", 0.05)
	aimEvent:FireServer("button2Up")
end



local function shoot()
	local player = game.Players.LocalPlayer
	local mouse = player:GetMouse()
	local character = player.Character or player.CharacterAdded:Wait()
	
	if character:GetAttribute("Equipped") == true then
		local gunStats = gunData.getData(player.Character:GetAttribute("WeaponType"))
		if gunStats.firingMode == "semiAuto" then
			local shootPos = character.WeaponPart.ShootAtt.WorldPosition
			local direction = character.WeaponPart.ShootAtt.WorldCFrame.LookVector

			shootEvent:FireServer(shootPos, direction, player, mouse)
		end
	end
end

mouse.Button1Down:Connect(shoot)
mouse.Button2Down:Connect(button2Down)
mouse.Button2Up:Connect(button2Up)
UIS.InputBegan:Connect(onInput)

You said this:

And you mean this script?:

local equipEvent = game.ReplicatedStorage.EquipEvent

-- Dictionary to store animations for each player
local playerAnimations = {}

local function equipWeapon(player)
	local humanoid = player.Character:FindFirstChild("Humanoid")

	-- Check if animations are already loaded, if not, load them for this player
	if not playerAnimations[player] then
		playerAnimations[player] = {}
		playerAnimations[player].stowAnim = humanoid:LoadAnimation(game.StarterPlayer.StarterCharacterScripts.Animate.Animations.MinigunStow)
		playerAnimations[player].stowAnimEnd = humanoid:LoadAnimation(game.StarterPlayer.StarterCharacterScripts.Animate.Animations.MinigunStowEnd)
	end

	local stowAnim = playerAnimations[player].stowAnim
	local stowAnimEnd = playerAnimations[player].stowAnimEnd

	-- Stop previous animations if they're playing
	stowAnim:Stop()
	stowAnimEnd:Stop()

	if player.Character:GetAttribute("Equipped") == nil or player.Character:GetAttribute("Equipped") == false then
		if player.Character:FindFirstChild("WeaponPart") == nil then
			local weapon = game.Workspace.WeaponPart:Clone()

			weapon.Parent = player.Character

			local motor = Instance.new("Motor6D")

			motor.Parent = player.Character.HumanoidRootPart
			motor.Part0 = player.Character.HumanoidRootPart
			motor.Part1 = weapon
		end

		stowAnim:Play(0.1, 1, -1) -- Adjust the speed, loop count, etc., as needed

		-- Wait for the animation to finish
		stowAnim.Stopped:Wait()

		print("Equip: ", player)

		player.Character:SetAttribute("Equipped", true)
		player.Character:SetAttribute("WeaponType", "Minigun")
	else
		player.Character:SetAttribute("Equipped", false)
		player.Character:SetAttribute("WeaponType", nil)

		stowAnim:Play()
		stowAnim:AdjustSpeed(1)

		-- Wait for the animation to finish
		stowAnim.Stopped:Wait()

		stowAnimEnd:Play()

		-- Wait for the animation to finish
		stowAnimEnd.Stopped:Wait()

		-- Cleanup, if needed
		-- player.Character.HumanoidRootPart:FindFirstChild("Motor6D"):Destroy()
		-- player.Character:FindFirstChild("WeaponPart"):Destroy()
	end
end

equipEvent.OnServerEvent:Connect(equipWeapon)

That script seems like it works like a Server Script…

So… You are giving a Server Script to each player that joins the game?
A script that contains a equipEvent.OnServerEvent:Connect(equipWeapon) ?
Causing that multiple connections to that Remote exist.

So… Client fires the Remote, and ALL Server Scripts in players will get the Remote signal.
I think you only need 1 of that script, not one per player, otherwise unexpected behavior will occur cause any player can call all scripts that supposedly owns different players, unless you put somekind of “lock” to verify that only the owner of that server script can run it, or change the approach and use only 1 server script in ServerScriptService that is able to handle all player’s actions related.

Since you have tables like this:

-- Dictionary to store animations for each player
local playerAnimations = {}

Seems the approach is using one single script. So remove it from StarterCharacterScripts and place it in ServerScriptService

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.