How do I make M1 Cancelling like deepwoken

I’m making a combat oriented game and I realised that in alot of combat games today they involve m1 cancelling and move cancelling in general. I already have a basic move system that sends the input and finds the corresponding function to then be called, but I want to be able to implement the cancelling of the function and i dont know whether or not i would do that from the moment of input or when it gets to the function. I’d assume it is when it gets to the function as the m1 can still take place and be cancelled after. Does anyone have an idea or an example of how to make this?

here’s a pseudocode:

local cancelAttack = false
local isAttacking = false

local function activateHitbox()
	if cancelAttack then return end
	-- sum code here
end

local function attack()
	attackAnim:Play()
	task.wait(0.25)
	activateHitbox()
end

attack()
task.wait(0.15)
cancelAttack = true

how would i do move cancelling like this tho

client:

UserInputService.InputBegan:Connect(function(Input,GameProcessed)
   Move:FireServer(Input)
end)

Server:

Move.OnServerEvent:Connect(function(Player,Input)
    local Moves = require(script.Moves)
    local function = Moves[Input] 
    Player.Attacking = true
    local succ,fail = pcall(function()
       function(Player)
    end)
    Player.Attacking = false
end)

How would I control it as this is a basic rundown of how my current system works

You’d have to use newproxies (or increment a number by 1, if you’re lame.) A newproxy is a value that is empty, but unique, so overwriting a newproxy with another will signal a change. This can be used to have a function check if a newproxy has changed, and if it has, terminate itself.

CheckProxy = newproxy()

function AttackThingy()
	local CurrentP = newproxy()
	CheckProxy = CurrentP 

	task.wait(3)
	if CheckProxy ~= CurrentP then return end --//Make sure to clean up whatever your attacks do.
end

and then for the cancelling would i just set a newproxy?

Precisely. The function itself overwrites the old proxy, so calling it again will interrupt the last one.

would this not happen everytime i use a keybind though? if so how would i bind this to mousebutton2 and still cancel any other move

As long as CheckProxy is the same value used for other attacks, any attack can cancel any attack. You could add further conditional logic to prevent unwanted behavior, such as attacks cancelling themselves.

i did this as a test and it didnt work what did i do wrong?
client:

game.UserInputService.InputBegan:Connect(function(Input,GameProcessed)
	if GameProcessed then
		return
	end
	if Input.UserInputType == Enum.UserInputType.MouseButton1 then
		game.ReplicatedStorage.RemoteEvent:FireServer("hi")
	elseif Input.UserInputType == Enum.UserInputType.MouseButton2 then
		game.ReplicatedStorage.RemoteEvent:FireServer("hey")
	end
end)

server:

local CheckProxy = newproxy()

game.ReplicatedStorage.RemoteEvent.OnServerEvent:Connect(function(Player,strin : string)
	local NewProxy = CheckProxy
	if strin == "hi" then
		wait(1)
		if CheckProxy ~= NewProxy then
			return
		end	
		print(strin)
	elseif strin == "hey" then
		NewProxy = newproxy()
	end
end)
for i,v in humanoid:GetPlayingAnimationTracks() do 
       v:Stop()
end

so just use this to stop the animations and then delete the move hitboxes

why are you using newproxy? newproxy isn’t necessary here. when the player joins just create a new value inside of them to store their current move and update it whenever they use a new move and when they’re hit just change the value and take the value in account when scripting your abilities.

1 Like

@TheCraftNCreator This is not what newproxy() should be used for and this is horrible advice. Please read what these actually do before you recommend them to other people.


@Hierophant_Bean, I would have a bool value for whether or not the player is swinging. This bool turns true when the player starts an M1. This bool turns false when the M1 prepare ends, and he swings the sword.

A better way to visualize this:

Client: Clicks and fires server to start an M1.
Server: Sees this request and sets PreparingM1 to true.
Client: Presses Right Click to cancel their M1 (feinting in deepwoken).
Server: If PreparingM1 is still true by the time the players hits M2, they will feint.


-- Server Sided Code for when the Player requests to start an M1
Remotes.Swing.OnServerEvent:Connect(function(Player)
       PreparingM1 = true
       CanSwing = true
end)

-- Server Sided Code for when the Player requests to cancel an M1
if PreparingM1 then
      -- Feint Weapon and Cancel M1
      -- Stop playing animations, don't create a hitbox etc

     SwingAnimation:Stop()
     CanSwing = false
end

You could use an Animation Event to determine whether or not to swing.

-- Server Sided Code
-- MAKE SURE YOUR ANIMATION HAS AN EVENT NAMED "DealDamage"!!!

-- This event should be after the player finishes preparing their swing. 
-- Preferably right as they begin to swipe their sword.
SwingAnimation:GetMarkerReachedSignal("DealDamage"):Connect(function()
       -- The M1 can no longer be cancelled.
       PreparingM1 = false

       -- Create damage dealing hitbox
end)

Example of where to place the animation event:

I’m not an animator don’t judge me :joy:

1 Like

Thanks I used this for the m1 cancelling and it works perfectly

2 Likes

@Hierophant_Bean Your code in comment 9 does not work because you set local value “NewProxy” to a newproxy() instead of CheckProxy.

@synical4 What’s so horrible about newproxy()? I’ve seen it used as an identifier in other scripts and it doesn’t seem to have any kind of impact on preformance. Either way, even if it’s bad, you can increment a number by one for the same effect.

Anyways, there are some flaws with your methods:

  • Animations played on the server cause lots of lag since it needs to replicate everything. It is a far better idea to simply send a remote event telling each client what animation to play on what character.
  • Compared to my code, this system cannot be adjusted to work with other attacks.
  • Animation Events are near-useless and are difficult to work with. Every time you want to adjust when the hitbox appears, you have to go into an animation editor, move the event, then publish that to roblox.
  • Lastly, server-sided hitboxes are less than ideal.

he’s telling him to use newproxy because half of the people on here are professionals at trying to act smart

1 Like

First of all you’re trying to help a beginner why are you telling him to use newproxy and metatables and what not just for something as basic as this? You’re just overcomplicating it for him and wasting time. Second of all quit yapping. Third of all its code to just show him what to do its almost like he’s not meant to copy and paste it like ur code no wonder why it doesn’t work well for other attacks :moyai: And finally if you give someone the code and still have to go out of your way to explain after they use it then you’re clearly doing something wrong.

1 Like

It appears you have failed to read the part where I mention that incrementing a number (translation: add 1 every time you need to change it) could suffice as well. newproxy() is also not being used as a metatable, it’s an identifier. It should be simple enough that even a beginner scripter such as you could understand that.

Also, the other person gave way more lines of code compared to what I gave. I showed a very basic example of how my system would work. Again, the only reason the code doesn’t work in comment 9 is because OP misassigned a variable, which can be fixed in a couple seconds.

If it’s so easy for them to mess up newproxy then why would you recommend it over just using a stringvalue to store the player’s move or literally anything else

He would’ve made the same mistake regardless. Do you even know what he did wrong?

Yes, I know. I’m helping a beginner. This solution DOES work just fine. It’s not perfect, and I’m fully aware it can be improved. I personally always do client animations. This doesn’t mean that server animations don’t work.

The logic behind cancelling an M1 that I provided can easily be expanded into other systems with a bit of intuition. I provided help code; not a full system for him to copy and paste.

Disagree strongly.

Again, I provided a simple example that is easy to understand. I wouldn’t do hitboxes this way at all. But for a beginner, this is a great place to begin.

Same reasoning for everything else above.


It provides no benefit to use newproxy() in this scenario other than for the sake of making yourself seem smarter. There’s nothing wrong with using simple code to achieve results.

1 Like