Jump to content

[Quick Tutorial] How to Punch Things Really Fast


Wonderlarr
 Share

Recommended Posts

Hello Modders, here's a quick guide on how to make your character punch things really quickly.

We'll be using AddStategraphPostInit here, so you'll want to throw these into your modmain.lua. Make sure to read the comments in the code, to adjust the things you'll need to adjust! I used Wilba from Hamlet to test here, but unless you're ripping off hamlet, you'll need to change it.

AddStategraphPostInit("wilson", function(sg) -- This will add some code to the server side stategraph
	local _attack = sg.states["attack"]
	local _onenter = _attack.onenter
	_attack.onenter = function(inst,...)
		_onenter(inst,...)
		if inst.prefab == "wilba" then -- You'll want to change wilba to your own character's prefab
			local speed = 2 -- Change this to whatever yoy want your speed multiplier to go to, careful when going over 5 though, it gets buggy.
			inst.sg:SetTimeout(inst.sg.timeout/speed)
      	    inst.components.combat:SetAttackPeriod(TUNING.WILSON_ATTACK_PERIOD / speed) -- Attack period is essentially like an attack cooldown, so we divide it by the speed. 
			inst.AnimState:SetDeltaTimeMultiplier(speed) -- This is the time multiplier for animations, we multiply it by our speed to make the character punch fast and not have animation desyncs.
			for k, v in pairs(_attack.timeline) do
				v.time = v.time/speed
			end
		end
		return
	end
	local _onexit = _attack.onexit
	_attack.onexit = function(inst,...)
		if inst.prefab == "wilba" then -- Make sure to change your prefab here too!
			inst.AnimState:SetDeltaTimeMultiplier(1) -- Here we'll only return out animation speed back to normal, since Attack Period being increased doesn't matter otherwise, and it might break things if we did return it after every attack.
		end
		return _onexit(inst,...)
	end
end)

AddStategraphPostInit("wilson_client", function(sg) -- This adds code to the client side stategraph, but it's only used if the client has Movement Prediction enabled.
	local _attack = sg.states["attack"]
	local _onenter = _attack.onenter
	_attack.onenter = function(inst,...)
		_onenter(inst,...)
		if inst.prefab == "wilba" then --Change it here again!
			local speed = 2 -- Make sure to set your speed here as well, so the client knows.
			inst.sg:SetTimeout(inst.sg.timeout/speed)
			inst.AnimState:SetDeltaTimeMultiplier(speed)
			for k, v in pairs(_attack.timeline) do
				v.time = v.time/speed
			end
		end
		return
	end
	local _onexit = _attack.onexit
	_attack.onexit = function(inst,...)
		if inst.prefab == "wilba" then  -- Final change here, to your characters prefab again.
			inst.AnimState:SetDeltaTimeMultiplier(1)
		end
		return _onexit(inst,...)
	end
end)

Thing to keep in mind

If you want your character to ALWAYS punch fast, you should probably comment out or remove the lines that mess with AttackPeriod, and instead put that in your characters master_postinit.

Edited by TheSkylarr
Changed title
  • Like 2
  • Thanks 1
Link to comment
Share on other sites

I'm not sure if this is entirely correct, as when I tried something like this for my mod to get a faster attack, my character started to attack faster and faster after each attack. To understand the cause, I added some print, like this:

for k, v in pairs(_attack.timeline) do--"overide the timeline"
		print("v.time onenter before:"..tostring(v.time))
		v.time = v.time/speed
		print("v.time onenter after:"..tostring(v.time))
end

in the onenter and onexit function. The result can be seen in the first spoiler.

Spoiler

[00:07:04]: v.time onenter before:0.16666666666667    
[00:07:04]: v.time onenter after:0.095238095238095    
[00:07:04]: v.time onenter before:0.2    
[00:07:04]: v.time onenter after:0.11428571428571    
[00:07:04]: v.time onenter before:0.23333333333333    
[00:07:04]: v.time onenter after:0.13333333333333    
[00:07:04]: v.time onenter before:0.26666666666667    
[00:07:04]: v.time onenter after:0.15238095238095    
[00:07:04]: v.time onenter before:0.33333333333333    
[00:07:04]: v.time onenter after:0.19047619047619    
[00:07:05]: v.time onexit before:0.095238095238095    
[00:07:05]: v.time onexit after:0.095238095238095    
[00:07:05]: v.time onexit before:0.11428571428571    
[00:07:05]: v.time onexit after:0.11428571428571    
[00:07:05]: v.time onexit before:0.13333333333333    
[00:07:05]: v.time onexit after:0.13333333333333    
[00:07:05]: v.time onexit before:0.15238095238095    
[00:07:05]: v.time onexit after:0.15238095238095    
[00:07:05]: v.time onexit before:0.19047619047619    
[00:07:05]: v.time onexit after:0.19047619047619    
[00:07:05]: v.time onenter before:0.095238095238095    
[00:07:05]: v.time onenter after:0.054421768707483    
[00:07:05]: v.time onenter before:0.11428571428571    
[00:07:05]: v.time onenter after:0.06530612244898    
[00:07:05]: v.time onenter before:0.13333333333333    
[00:07:05]: v.time onenter after:0.076190476190476    
[00:07:05]: v.time onenter before:0.15238095238095    
[00:07:05]: v.time onenter after:0.087074829931973    
[00:07:05]: v.time onenter before:0.19047619047619    
[00:07:05]: v.time onenter after:0.10884353741497    
[00:07:05]: v.time onexit before:0.054421768707483    
[00:07:05]: v.time onexit after:0.054421768707483    
[00:07:05]: v.time onexit before:0.06530612244898    
[00:07:05]: v.time onexit after:0.06530612244898    
[00:07:05]: v.time onexit before:0.076190476190476    
[00:07:05]: v.time onexit after:0.076190476190476    
[00:07:05]: v.time onexit before:0.087074829931973    
[00:07:05]: v.time onexit after:0.087074829931973    
[00:07:05]: v.time onexit before:0.10884353741497    
[00:07:05]: v.time onexit after:0.10884353741497    
[00:07:05]: v.time onenter before:0.054421768707483    
[00:07:05]: v.time onenter after:0.031098153547133    
[00:07:05]: v.time onenter before:0.06530612244898    
[00:07:05]: v.time onenter after:0.03731778425656    
[00:07:05]: v.time onenter before:0.076190476190476    
[00:07:05]: v.time onenter after:0.043537414965986    
[00:07:05]: v.time onenter before:0.087074829931973    
[00:07:05]: v.time onenter after:0.049757045675413    
[00:07:05]: v.time onenter before:0.10884353741497    
[00:07:05]: v.time onenter after:0.062196307094266    
[00:07:05]: v.time onexit before:0.031098153547133    
[00:07:05]: v.time onexit after:0.031098153547133    
[00:07:05]: v.time onexit before:0.03731778425656    
[00:07:05]: v.time onexit after:0.03731778425656    
[00:07:05]: v.time onexit before:0.043537414965986    
[00:07:05]: v.time onexit after:0.043537414965986    
[00:07:05]: v.time onexit before:0.049757045675413    
[00:07:05]: v.time onexit after:0.049757045675413    
[00:07:05]: v.time onexit before:0.062196307094266    
[00:07:05]: v.time onexit after:0.062196307094266    
[00:07:05]: v.time onenter before:0.031098153547133    
[00:07:05]: v.time onenter after:0.017770373455505    
[00:07:05]: v.time onenter before:0.03731778425656    
[00:07:05]: v.time onenter after:0.021324448146606    
[00:07:05]: v.time onenter before:0.043537414965986    
[00:07:05]: v.time onenter after:0.024878522837707    
[00:07:05]: v.time onenter before:0.049757045675413    
[00:07:05]: v.time onenter after:0.028432597528807    
[00:07:05]: v.time onenter before:0.062196307094266    
[00:07:05]: v.time onenter after:0.035540746911009    
[00:07:06]: v.time onexit before:0.017770373455505    
[00:07:06]: v.time onexit after:0.017770373455505    
[00:07:06]: v.time onexit before:0.021324448146606    
[00:07:06]: v.time onexit after:0.021324448146606    
[00:07:06]: v.time onexit before:0.024878522837707    
[00:07:06]: v.time onexit after:0.024878522837707    
[00:07:06]: v.time onexit before:0.028432597528807    
[00:07:06]: v.time onexit after:0.028432597528807    
[00:07:06]: v.time onexit before:0.035540746911009    
[00:07:06]: v.time onexit after:0.035540746911009    
[00:07:06]: v.time onenter before:0.017770373455505    
[00:07:06]: v.time onenter after:0.010154499117431    
[00:07:06]: v.time onenter before:0.021324448146606    
[00:07:06]: v.time onenter after:0.012185398940917    
[00:07:06]: v.time onenter before:0.024878522837707    
[00:07:06]: v.time onenter after:0.014216298764404    
[00:07:06]: v.time onenter before:0.028432597528807    
[00:07:06]: v.time onenter after:0.01624719858789    
[00:07:06]: v.time onenter before:0.035540746911009    
[00:07:06]: v.time onenter after:0.020308998234862    
[00:07:06]: v.time onexit before:0.010154499117431    
[00:07:06]: v.time onexit after:0.010154499117431    
[00:07:06]: v.time onexit before:0.012185398940917    
[00:07:06]: v.time onexit after:0.012185398940917    
[00:07:06]: v.time onexit before:0.014216298764404    
[00:07:06]: v.time onexit after:0.014216298764404    
[00:07:06]: v.time onexit before:0.01624719858789    
[00:07:06]: v.time onexit after:0.01624719858789    
[00:07:06]: v.time onexit before:0.020308998234862    
[00:07:06]: v.time onexit after:0.020308998234862    
[00:07:06]: v.time onenter before:0.010154499117431    
[00:07:06]: v.time onenter after:0.0058025709242464    
[00:07:06]: v.time onenter before:0.012185398940917    
[00:07:06]: v.time onenter after:0.0069630851090957    
[00:07:06]: v.time onenter before:0.014216298764404    
[00:07:06]: v.time onenter after:0.008123599293945    
[00:07:06]: v.time onenter before:0.01624719858789    
[00:07:06]: v.time onenter after:0.0092841134787943    
[00:07:06]: v.time onenter before:0.020308998234862    
[00:07:06]: v.time onenter after:0.011605141848493    
[00:07:07]: v.time onexit before:0.0058025709242464    
[00:07:07]: v.time onexit after:0.0058025709242464    
[00:07:07]: v.time onexit before:0.0069630851090957    
[00:07:07]: v.time onexit after:0.0069630851090957    
[00:07:07]: v.time onexit before:0.008123599293945    
[00:07:07]: v.time onexit after:0.008123599293945    
[00:07:07]: v.time onexit before:0.0092841134787943    
[00:07:07]: v.time onexit after:0.0092841134787943    
[00:07:07]: v.time onexit before:0.011605141848493    
[00:07:07]: v.time onexit after:0.011605141848493    
[00:07:07]: v.time onenter before:0.0058025709242464    
[00:07:07]: v.time onenter after:0.0033157548138551    
[00:07:07]: v.time onenter before:0.0069630851090957    
[00:07:07]: v.time onenter after:0.0039789057766261    
[00:07:07]: v.time onenter before:0.008123599293945    
[00:07:07]: v.time onenter after:0.0046420567393971    
[00:07:07]: v.time onenter before:0.0092841134787943    
[00:07:07]: v.time onenter after:0.0053052077021682    
[00:07:07]: v.time onenter before:0.011605141848493    
[00:07:07]: v.time onenter after:0.0066315096277102    
[00:07:07]: v.time onexit before:0.0033157548138551    
[00:07:07]: v.time onexit after:0.0033157548138551    
[00:07:07]: v.time onexit before:0.0039789057766261    
[00:07:07]: v.time onexit after:0.0039789057766261    
[00:07:07]: v.time onexit before:0.0046420567393971    
[00:07:07]: v.time onexit after:0.0046420567393971    
[00:07:07]: v.time onexit before:0.0053052077021682    
[00:07:07]: v.time onexit after:0.0053052077021682    
[00:07:07]: v.time onexit before:0.0066315096277102    
[00:07:07]: v.time onexit after:0.0066315096277102    
[00:07:07]: v.time onenter before:0.0033157548138551    
[00:07:07]: v.time onenter after:0.0018947170364886    
[00:07:07]: v.time onenter before:0.0039789057766261    
[00:07:07]: v.time onenter after:0.0022736604437864    
[00:07:07]: v.time onenter before:0.0046420567393971    
[00:07:07]: v.time onenter after:0.0026526038510841    
[00:07:07]: v.time onenter before:0.0053052077021682    
[00:07:07]: v.time onenter after:0.0030315472583818    
[00:07:07]: v.time onenter before:0.0066315096277102    
[00:07:07]: v.time onenter after:0.0037894340729773    
[00:07:08]: v.time onexit before:0.0018947170364886    
[00:07:08]: v.time onexit after:0.0018947170364886    
[00:07:08]: v.time onexit before:0.0022736604437864    
[00:07:08]: v.time onexit after:0.0022736604437864    
[00:07:08]: v.time onexit before:0.0026526038510841    
[00:07:08]: v.time onexit after:0.0026526038510841    
[00:07:08]: v.time onexit before:0.0030315472583818    
[00:07:08]: v.time onexit after:0.0030315472583818    
[00:07:08]: v.time onexit before:0.0037894340729773    
[00:07:08]: v.time onexit after:0.0037894340729773    
[00:07:08]: v.time onenter before:0.0018947170364886    
[00:07:08]: v.time onenter after:0.0010826954494221    
[00:07:08]: v.time onenter before:0.0022736604437864    
[00:07:08]: v.time onenter after:0.0012992345393065    
[00:07:08]: v.time onenter before:0.0026526038510841    
[00:07:08]: v.time onenter after:0.0015157736291909    
[00:07:08]: v.time onenter before:0.0030315472583818    
[00:07:08]: v.time onenter after:0.0017323127190753    
[00:07:08]: v.time onenter before:0.0037894340729773    
[00:07:08]: v.time onenter after:0.0021653908988441    

As you can see, the timelines of the attacks are always getting smaller and smaller.

That's why I thought of adding to the onexit function this:

local _onexit = _attack.onexit
	_attack.onexit = function(inst,...)
	if inst.prefab == "wilba" then  -- Final change here, to your characters prefab again.
	local speed = 2 
		inst.AnimState:SetDeltaTimeMultiplier(1)
		for k, v in pairs(_attack.timeline) do--"overide the timeline"
			v.time = v.time*speed
		end
	end
	return _onexit(inst,...)
end

After adding this to the onexit function, the prints can be seen in the second spoiler:

Spoiler

[00:02:29]: v.time onenter before:0.16666666666667    
[00:02:29]: v.time onenter after:0.095238095238095    
[00:02:29]: v.time onenter before:0.2    
[00:02:29]: v.time onenter after:0.11428571428571    
[00:02:29]: v.time onenter before:0.23333333333333    
[00:02:29]: v.time onenter after:0.13333333333333    
[00:02:29]: v.time onenter before:0.26666666666667    
[00:02:29]: v.time onenter after:0.15238095238095    
[00:02:29]: v.time onenter before:0.33333333333333    
[00:02:29]: v.time onenter after:0.19047619047619    
[00:02:29]: v.time onexit before:0.095238095238095    
[00:02:29]: v.time onexit after:0.16666666666667    
[00:02:29]: v.time onexit before:0.11428571428571    
[00:02:29]: v.time onexit after:0.2    
[00:02:29]: v.time onexit before:0.13333333333333    
[00:02:29]: v.time onexit after:0.23333333333333    
[00:02:29]: v.time onexit before:0.15238095238095    
[00:02:29]: v.time onexit after:0.26666666666667    
[00:02:29]: v.time onexit before:0.19047619047619    
[00:02:29]: v.time onexit after:0.33333333333333    
[00:02:29]: v.time onenter before:0.16666666666667    
[00:02:29]: v.time onenter after:0.095238095238095    
[00:02:29]: v.time onenter before:0.2    
[00:02:29]: v.time onenter after:0.11428571428571    
[00:02:29]: v.time onenter before:0.23333333333333    
[00:02:29]: v.time onenter after:0.13333333333333    
[00:02:29]: v.time onenter before:0.26666666666667    
[00:02:29]: v.time onenter after:0.15238095238095    
[00:02:29]: v.time onenter before:0.33333333333333    
[00:02:29]: v.time onenter after:0.19047619047619    
[00:02:30]: v.time onexit before:0.095238095238095    
[00:02:30]: v.time onexit after:0.16666666666667    
[00:02:30]: v.time onexit before:0.11428571428571    
[00:02:30]: v.time onexit after:0.2    
[00:02:30]: v.time onexit before:0.13333333333333    
[00:02:30]: v.time onexit after:0.23333333333333    
[00:02:30]: v.time onexit before:0.15238095238095    
[00:02:30]: v.time onexit after:0.26666666666667    
[00:02:30]: v.time onexit before:0.19047619047619    
[00:02:30]: v.time onexit after:0.33333333333333    

As you can see, the timelines stay at the same numbers.

To be honest, I'm not sure sure if this is correct, as I only had a feeling that I was attacking faster than I should, but at least these numbers say so.

  • Like 1
Link to comment
Share on other sites

I made some tests (see in the spoiler) where you can see that the times between the attacks stays the same, so it doesn't seem to change the attackspeed after time, it was probably only my imagination :D

Spoiler

[00:24:48]: time attackenter:2.3000001199543    
[00:24:48]: time since last attack:2.3000001199543    
[00:24:48]: time attackexit:2.5666668005288    
[00:24:48]: v.time onexit before:0.083333333333333    
[00:24:48]: v.time onexit before:0.1    
[00:24:48]: v.time onexit before:0.11666666666667    
[00:24:48]: v.time onexit before:0.13333333333333    
[00:24:48]: v.time onexit before:0.16666666666667    
[00:24:48]: time attackenter:2.5666668005288    
[00:24:48]: time since last attack:0.26666668057442    
[00:24:48]: time attackexit:2.8333334811032    
[00:24:48]: v.time onexit before:0.041666666666667    
[00:24:48]: v.time onexit before:0.05    
[00:24:48]: v.time onexit before:0.058333333333333    
[00:24:48]: v.time onexit before:0.066666666666667    
[00:24:48]: v.time onexit before:0.083333333333333    
[00:24:48]: time attackenter:2.8333334811032    
[00:24:48]: time since last attack:0.26666668057442    
[00:24:49]: time attackexit:3.1000001616776    
[00:24:49]: v.time onexit before:0.020833333333333    
[00:24:49]: v.time onexit before:0.025    
[00:24:49]: v.time onexit before:0.029166666666667    
[00:24:49]: v.time onexit before:0.033333333333333    
[00:24:49]: v.time onexit before:0.041666666666667    
[00:24:49]: time attackenter:3.1000001616776    
[00:24:49]: time since last attack:0.26666668057442    
[00:24:49]: time attackexit:3.366666842252    
[00:24:49]: v.time onexit before:0.010416666666667    
[00:24:49]: v.time onexit before:0.0125    
[00:24:49]: v.time onexit before:0.014583333333333    
[00:24:49]: v.time onexit before:0.016666666666667    
[00:24:49]: v.time onexit before:0.020833333333333    
[00:24:49]: time attackenter:3.366666842252    
[00:24:49]: time since last attack:0.26666668057442    
[00:24:49]: time attackexit:3.6333335228264    
[00:24:49]: v.time onexit before:0.0052083333333333    
[00:24:49]: v.time onexit before:0.00625    
[00:24:49]: v.time onexit before:0.0072916666666667    
[00:24:49]: v.time onexit before:0.0083333333333333    
[00:24:49]: v.time onexit before:0.010416666666667    
[00:24:49]: time attackenter:3.6333335228264    
[00:24:49]: time since last attack:0.26666668057442    
[00:24:49]: time attackexit:3.9000002034009    
[00:24:49]: v.time onexit before:0.0026041666666667    
[00:24:49]: v.time onexit before:0.003125    
[00:24:49]: v.time onexit before:0.0036458333333333    
[00:24:49]: v.time onexit before:0.0041666666666667    
[00:24:49]: v.time onexit before:0.0052083333333333    
[00:24:49]: time attackenter:3.9000002034009    
[00:24:49]: time since last attack:0.26666668057442    
[00:24:50]: time attackexit:4.1666668839753    
[00:24:50]: v.time onexit before:0.0013020833333333    
[00:24:50]: v.time onexit before:0.0015625    
[00:24:50]: v.time onexit before:0.0018229166666667    
[00:24:50]: v.time onexit before:0.0020833333333333    
[00:24:50]: v.time onexit before:0.0026041666666667    
[00:24:50]: time attackenter:4.1666668839753    
[00:24:50]: time since last attack:0.26666668057442    
[00:24:50]: time attackexit:4.4333335645497    
[00:24:50]: v.time onexit before:0.00065104166666667    
[00:24:50]: v.time onexit before:0.00078125    
[00:24:50]: v.time onexit before:0.00091145833333333    
[00:24:50]: v.time onexit before:0.0010416666666667    
[00:24:50]: v.time onexit before:0.0013020833333333    
[00:24:50]: time attackenter:4.4333335645497    
[00:24:50]: time since last attack:0.26666668057442    
[00:24:50]: time attackexit:4.7000002451241    
[00:24:50]: v.time onexit before:0.00032552083333333    
[00:24:50]: v.time onexit before:0.000390625    
[00:24:50]: v.time onexit before:0.00045572916666667    
[00:24:50]: v.time onexit before:0.00052083333333333    
[00:24:50]: v.time onexit before:0.00065104166666667    

As for the timeline values that are changing, I'm not sure if this has implications for other things in the game, so perhaps it would be the best to get them back to their original values. Even without changing the timelines, you attack faster with this guide, just a frame slower than with the timeline change except for some frames where attack onenter and attack onexit overlap.

Edit: This seems to only happen if you are not changing the timelines in the wilson stategraph and changing the timelines in the wilson_client stategraph. So its seems the timelines are probably mostly important for the clients.

Edited by Monti18
  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
  • Create New...