Issue with setting character attribute

Now this is probably going to be a very niche and specific post, but I have a combat system and Im tyring to make two types of attacks using mousebutton1 and mousebutton2. Mousebutton1 works fine but once i press mousebutton2, it turns sets a character attribute named “canSwing” to false and whenever its false, the player cannot do M1/M2 inputs nor walk or jump. The heavy attack portion, for some reason, just sets it to false and doesnt re-enable it. The animation has the keyframes required as well I seriously dont know whats going on (no errors pop up in the output)

“Light Attack”

if Args.Event == "LightAttack" then
		if not Character:GetAttribute("canSwing") then return end
		
		local Combo = Character:GetAttribute("Combo")
		if Combo == 1 then
			Character:SetAttribute("canSwing", false)
			Player:SetAttribute("canSwing", false)
			Character:SetAttribute("Combo", Character:GetAttribute("Combo") + 1)
			Character:SetAttribute("LastSwing", DateTime.now().UnixTimestampMillis)
			local Swing = Humanoid:LoadAnimation(WeaponSettings.Swing1)
			Swing:Play()
			
			Swing.KeyframeReached:Connect(function(Keyframe)
				if Keyframe == "Hit" then
					CombatManager.CreateHitbox(Player, Character.HumanoidRootPart.CFrame * CFrame.new(0, 0, -3), WeaponSettings.HitboxSize)
				end
				if Keyframe == "End" then
					task.delay(WeaponSettings.SwingCD, function()
						Character:SetAttribute("canSwing", true)
						Player:SetAttribute("canSwing", true)
					end)
				end
			end)
		elseif Combo == 2 then
			Character:SetAttribute("canSwing", false)
			Player:SetAttribute("canSwing", false)
			Character:SetAttribute("Combo", Character:GetAttribute("Combo") + 1)
			Character:SetAttribute("LastSwing", DateTime.now().UnixTimestampMillis)
			local Swing = Humanoid:LoadAnimation(WeaponSettings.Swing2)
			Swing:Play()

			end)
		elseif Combo == 3 then
			Character:SetAttribute("canSwing", false)
			Player:SetAttribute("canSwing", false)
			Character:SetAttribute("Combo", 1)
			Character:SetAttribute("LastSwing", DateTime.now().UnixTimestampMillis)
			local Swing = Humanoid:LoadAnimation(WeaponSettings.Swing3)
			Swing:Play()
			
			Swing.KeyframeReached:Connect(function(Keyframe)
				if Keyframe == "Hit" then
					CombatManager.CreateHitbox(Player, Character.HumanoidRootPart.CFrame * CFrame.new(0, 0, -3), WeaponSettings.HitboxSize)
				end
				if Keyframe == "End" then
					task.delay(WeaponSettings.SwingCD, function()
						Character:SetAttribute("canSwing", true)
						Player:SetAttribute("canSwing", true)
					end)
				end
			end)
		end
	end

“Heavy Attack”

if Args.Event == "HeavyAttack" then
		if not Character:GetAttribute("canSwing") then return end

		local Combo = Character:GetAttribute("Combo")
		if Combo == 1 then
			Character:SetAttribute("canSwing", false)
			Player:SetAttribute("canSwing", false)
			Character:SetAttribute("Combo", Character:GetAttribute("Combo") + 1)
			Character:SetAttribute("LastSwing", DateTime.now().UnixTimestampMillis)
			local Swing = Humanoid:LoadAnimation(WeaponSettings.HeavySwing)
			Swing:Play()

			Swing.KeyframeReached:Connect(function(Keyframe)
				if Keyframe == "Hit" then
					CombatManager.CreateHitbox(Player, Character.HumanoidRootPart.CFrame * CFrame.new(0, 0, -3), WeaponSettings.HitboxSize)
				end
				if Keyframe == "End" then
					task.delay(WeaponSettings.HeavyCD, function()
						Character:SetAttribute("canSwing", true)
						Player:SetAttribute("canSwing", true)
					end)
				end
			end)
		elseif Combo == 2 then
			Character:SetAttribute("canSwing", false)
			Player:SetAttribute("canSwing", false)
			Character:SetAttribute("Combo", Character:GetAttribute("Combo") + 1)
			Character:SetAttribute("LastSwing", DateTime.now().UnixTimestampMillis)
			local Swing = Humanoid:LoadAnimation(WeaponSettings.HeavySwing)
			Swing:Play()

			Swing.KeyframeReached:Connect(function(Keyframe)
				if Keyframe == "Hit" then
					CombatManager.CreateHitbox(Player, Character.HumanoidRootPart.CFrame * CFrame.new(0, 0, -3), WeaponSettings.HitboxSize)
				end
				if Keyframe == "End" then
					task.delay(WeaponSettings.HeavyCD, function()
						Character:SetAttribute("canSwing", true)
						Player:SetAttribute("canSwing", true)
					end)
				end
			end)
		elseif Combo == 3 then
			Character:SetAttribute("canSwing", false)
			Player:SetAttribute("canSwing", false)
			Character:SetAttribute("Combo", 1)
			Character:SetAttribute("LastSwing", DateTime.now().UnixTimestampMillis)
			local Swing = Humanoid:LoadAnimation(WeaponSettings.HeavySwing)
			Swing:Play()

			Swing.KeyframeReached:Connect(function(Keyframe)
				if Keyframe == "Hit" then
					CombatManager.CreateHitbox(Player, Character.HumanoidRootPart.CFrame * CFrame.new(0, 0, -3), WeaponSettings.HitboxSize)
				end
				if Keyframe == "End" then
					task.delay(WeaponSettings.HeavyCD, function()
						Character:SetAttribute("canSwing", true)
						Player:SetAttribute("canSwing", true)
					end)
				end
			end)
		end
	end

If you need me to post the other scripts that comply with the code then let me know.

Oh and another thing I noticed is that it seems to play the animation but it doesnt do the keyframe function. so it has to be something wrong with that section

This part only needs to be called once, not per stack, and Humanoid:LoadAnimation(animation) returns a AnimationTrack that can be reused, so loading the animation as the player loads in once and playing it here is much more convenient and saves memory.

For the issue with KeyframeReached not firing, try the method Swing:GetMarkerReachedSignal(“Hit”):Connect(onAnimHit), and since the Swing AnimationTrack persists until the humanoid dies, you only need to connect this signal once.

1 Like

Thank you so much I appreciate it

Cleaning this up:
If you have a script for when the player’s character loads in, load every animation and parent them to somewhere accessible, like under the humanoid.

For those times you set the attributes, they are incredibly similar, you can shorten it to this:

local Swing = Humanoid:LoadAnimation(WeaponSettings.HeavySwing)

Swing:GetMarkerReachedSignal("Hit"):Connect(function()
	CombatManager.CreateHitbox(Player, Character.HumanoidRootPart.CFrame * CFrame.new(0, 0, -3), WeaponSettings.HitboxSize)
end)
Swing:GetMarkerReachedSignal("End"):Connect(function()
	task.delay(WeaponSettings.HeavyCD, function()
	Character:SetAttribute("canSwing", true)
	Player:SetAttribute("canSwing", true)
end)

if Args.Event == "HeavyAttack" then
		if not Character:GetAttribute("canSwing") then return end

		local Combo = Character:GetAttribute("Combo")
		Character:SetAttribute("canSwing", false)
		Player:SetAttribute("canSwing", false)
		Character:SetAttribute("Combo", Combo)
		Character:SetAttribute("LastSwing", tick())
		Swing:Play()
end

@90xiao I replied to myself by accident so hopefully you’ll see this :pray:.

Yeah I realized that I actually put markers instead of renamed keyframes. Using GetMarkerReachedSignal still helped though, and Ill optimize the code as well.

1 Like

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