Playing an action right after another by holding down its key during the previous action

  1. What do you want to achieve? Keep it simple and clear!
    I am a newish scripter and I am making a combat script and I’m trying to make it so that if I hold down the block button during the middle of an m1 or dash it will play and set the block state only after the other actions have finished. Similar to how JJs or Type Soul have it.

  2. What is the issue? Include screenshots / videos if possible!
    The code I have right now uses an Input manager to send inputs to the replicated storage to play animations and effects and then fires a server script to set states for each action and create hitboxes. The issue I’m having is I don’t know a good way to detect when the block button is being held down since I am using Enum.UserInputState.Begin and when the other actions end.

  3. What solutions have you tried so far? Did you look for solutions on the Creator Hub?
    I have tried to use humanoid.StateChanged to wait for the Previous states to be removed ,but I couldn’t get it to work. I have also tried to create a queue system for my inputs but I also couldn’t get it to work properly. And lastly I tried to use a while loop to constantly fire the server if the key is being pressed ,but I’m trying to avoid using as many while loops as I can.

After that, you should include more details if you have any. Try to make your topic as descriptive as possible, so that it’s easier for people to help you!

Heres a snippet of the code
– Note I am also using a bunch of handlers but I believe they are irrelevant for this problem.

Input Handler

local function onInput(actionName, inputState, inputObject) -- fired when a input is made
	if inputState == Enum.UserInputState.Begin then -- if key is pressed
		if actionName == "M1Input" then
			callClientFunction("Combat", "M1", "OnM1Activated")   -- Checks in LocalHandler, first is Folder Name, Second is Module Name, Third is name of Function in the Module
		elseif actionName == "BlockInput" then
			callClientFunction("Combat", "Block", "Block")

	elseif inputState == Enum.UserInputState.End then
		if actionName == "BlockInput" then
			callClientFunction("Combat", "Block", "unBlock")
		end

Block modulescript in Replicated Storage

function module.Block()
	local char = plr.Character
	if char:GetAttribute("CantAnything") then return end
	if char:GetAttribute("Stunned") then return end
	if char:GetAttribute("Equip") == false then return end
	

	AnimationHandler.LoadAnim(char, "Blocking", animId, nil, false)
	ServerRemote:FireServer({Type = "Combat",Action = "Block",Func = "Activated",})
	AnimationHandler.StopAnim(char, "Running", RunanimId, nil, false)
	
end

function module.unBlock ()
	AnimationHandler.StopAnim(char,"Blocking",animId)
	ServerRemote:FireServer({Type = "Combat",Action = "Block",Func = "Deactivated",})
end

return module

Block modulescript in ServerScriptService

module.Activated = function(plr)
	local char = plr.Character
	local hum = char:FindFirstChildOfClass("Humanoid")
	
	if StateHandler.GetState(char, "CantAnything") then return end
	if StateHandler.GetState(char, "Stunned") then return end
	if StateHandler.GetState(char, "M1") then return end
	if StateHandler.GetState(char,"Equip") == false then return end
	
	Helper.SetSpeed(char,3,nil)
	StateHandler.SetState(char,"Blocking",true,9999999)
	
	--Activate perfect block window
	StateHandler.SetState(char,"PerfectBlocking",true,PB_Window)
end

module.Deactivated = function(plr)
	local char = plr.Character
	if StateHandler.GetState(char, "Blocking") then
		Helper.ResetSpeed(char)
		if StateHandler.GetState(char, "PerfectBlocking") then
			StateHandler.RemoveStates(char,"PerfectBlocking")
		end
		StateHandler.RemoveStates(char,"Blocking")
	end
end

return module

If anyone could just point me in the right direction that would be great!

Generally how I’ve done this is I have a queued action variable that is globally accessible and if something couldn’t happen right then (like the next attack in the combo, or a block) it keeps it queued (until something removes it from the queue like a changed input or a timeout though you have to be careful not to accidentally invalidate the wrong queued item).

Then when the attack ends I have it automatically call the queued input through the system if there is one.

2 Likes

Hey man this worked perfectly tysm

1 Like

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