The "fastattack" problem; high hit pause in multiplayer is nearly unplayable.

NickyP

Active member
Per the manual,
fastattack {bi}

- Normally, in order for an attack to hit entities multiple times, the attack boxes must be separated by at least one frame with an empty attack box (one set to all 0) and must also be separated by a brief delay.
- If this is set to 1, this animation's attack boxes are not restricted by the delay (it will still need an empty attack box between frames, though).

"Fastattack 1" does two things, really: first, it allows multiple players to hit the same enemy at the same time; and second, it greatly enables multihit moves in a single animation. Unfortunately, a well known consequence of this function is that if two or more players hit an enemy, both players attack boxes will continue to do damage until the animation renders an empty attackbox. IE, if Player 1 and Player 2's attack1 animation has a 12 centisecond active attackbox, and both players attack the enemy at the same time, the engine will constantly cycle between and register hits from both attackboxes until the 12 centiseconds are over.

This is already an annoying problem if both attackboxes have zero hit pause. However, with hit pauses, it becomes unplayable. I'm currently working on a project that relies on larger hit pauses (between 15-40 centiseconds) for attacks, and fastattack 1 for multihit attacks and supers. The fastattack bug unfortunately makes multiplayer nearly unplayable, as observed in my test video below:

https://www.youtube.com/watch?v=PZlPFaRE6O4

Is there any way around this, that at least maintains the fast multihit-per-animation feature? Attacks with high hit pause are a necessary part of this project of mine, so I can't compromise on that.
 
Yep. Stop using legacy attack box commands.  ;)

All fastattack really does is reduce the invincibility time conferred onto the target. I posted the math somewhere here but I'm on phone now. Basically by using fastattack (or not) you're choosing between one of two hard coded invincibility times. Those work for most setups, but as you can see, not all.

The up to date attack box has a setting that lets you specifically control amount of invincibility time the hit recipient gets. Then you can tailor it precisely to your needs.

DC
 
Damon Caskey said:
Stop using legacy attack box commands.  ;)

You can't tell me what to do, dad!

In all seriousness though, I've found the command you're referring to. From the manual:
attack.reaction.invincible.time - Time to remain invincible after hit.

I've been using it as a supplemental command to the legacy attackbox (much like dropv or stun), and it seems to be doing the trick for the most part. So far in my testing, I can maintain multiplayer attacking and multi-hit moves when invincibility time is set to (hit pause) - 2.

For example, here's Ryu's attack1 animation, with the important parts bolded:
anim attack1
fastattack 1
cancel 0 20 1 a2 freespecial2
cancel 0 20 1 a3 freespecial10
delay 5
offset 24 99
bbox  17  5  37  96
frame data/chars/cvsryu/161.gif
attack1  33  3  64  33  12  0  0  0  20
dropv 1.5 1 0
attack.reaction.invincible.time 18
frame data/chars/cvsryu/162.gif
frame data/chars/cvsryu/163.gif
delay 4
Attack1  0
idle 1
frame data/chars/cvsryu/164.gif
offset 25 99
bbox  11  4  37  95
frame data/chars/cvsryu/165.gif

There's still the slight problem of at least one player gaining an additional hit, but this is much better than before. Thanks for the tip, Damon Caskey!
 
Hey NickyP

Please, take a look in this post: http://www.chronocrash.com/forum/index.php?topic=5488.0

This is the multihit bug I'm talking about in this post, I found where the problem is.
It happens when two characters are hitting the same opponent and both atboxes will reset each other.

I fixed this issue by making the engine memorize the last atboxes and will avoid repeating them. After all tests are finished in the test build 6392 and if it has the DC approval, it will be officially launched.

In fact the "fastattack" will temporarily hide the problem, but will not fix it. This is because sometimes you may need to enable it to perform fast combos in some characters and it can only be made by activating the "fastattack", but will bring back the multihit issue.
 
Kratus,

Kratus said:
Hey NickyP This is because sometimes you may need to enable it to perform fast combos in some characters and it can only be made by activating the "fastattack", but will bring back the multihit issue.

That last part isn't strictly correct. See my post above: Fastattack just uses a slightly shorter value for the hard coded mercy invincibility.

It doesn't have anything to do with combos or hit pauses.

DC
 
Damon Caskey

Sorry buddy, maybe I can explain better with the video below:
https://www.youtube.com/watch?v=ruwAeVvBb-Y

In this case, I want the Blaze Orb to have the same effect as the Chun-Li's Kikou-shou. It performs very fast combos and the "fastattack 1" is needed in this case.
So, an invincibility time between each hit will totally break the move, as the video shows. It's true that the "fastattack 0" will avoid the multihit, but I want a way to disable the multihit and use the "fastattack 1" at the same time.

I could fix the multihit problem by using scripts in the "ondoattack" event, it's slight better than manage the fastattack function or change the legacy attack box commands, but I need to do a small sacrifice of the "damage on landing" function.
The source code change is the best way to fix this issue, but I'm holding this script as a second option in case the source code changes are not approved.

Code:
void multihits()
{//Script to avoid "multihits" bug, same as the original SOR2
 //However, to a nostalgic purpose it can be enabled in the Extra Menu
	
	if(getglobalvar("multiHit") == "off"){
		void self	= getlocalvar("self");
		void other	= getlocalvar("other");
		int atkid	= getentityproperty(self, "attackid");
		int land	= getentityproperty(other, "damage_on_landing");

		if(land <= 0){ //USED TO AVOID "DAMAGE ON LANDING" SITUATIONS AND BROKE SOME "THROW" MOVES
			if(atkid == getglobalvar("atkid"+self+other)){ //THE CURRENT ATTACKBOX ID IS SAME AS THE PREVIOUS USED ONE??
				changeopenborvariant("lasthitc", 0); //DISABLE THE ENGINE HIT HANDLING
			}
			else //THE CURRENT ATTACKBOX ID IS NOT SAME AS THE PREVIOUS USED ONE??
			{
				changeopenborvariant("lasthitc", 1); //ENABLE THE ENGINE HIT HANDLING
			}
			setglobalvar("atkid"+self+other, atkid); //SAVE THE "LAST ATTACKBOX ID" + "CURRENT PLAYER" + "DAMAGED ENTITY"
		}
	}
}

I hope it can explain better  :)
 
Kratus

Does that ondoattackscript need to be declared in enemy text files, or players too? Additionally, shouldn't the void be "main" in order for it to execute immediately?
 
NickyP said:
Kratus

Does that ondoattackscript need to be declared in enemy text files, or players too? Additionally, shouldn't the void be "main" in order for it to execute immediately?

NickyP

Yeah, you will need to declare this "ondoattackscript" at the header of all entities that have attack moves (players, enemies, npcs, obstacles, etc).
And you're right, if you don't have any other script inside your ondoattack event, the "void" can be "main" in order for it to execute immediately.
 
Kratus

It didn't work. Maybe I did something wrong.

First, I commented out all references to the attack.reaction setting I posted previously. Then, I created a file in the Scripts folder called multihit.c. It contains the following:
Code:
void main()
{//Script to avoid "multihits" bug, same as the original SOR2
 //However, to a nostalgic purpose it can be enabled in the Extra Menu
	
	if(getglobalvar("multiHit") == "off"){
		void self	= getlocalvar("self");
		void other	= getlocalvar("other");
		int atkid	= getentityproperty(self, "attackid");
		int land	= getentityproperty(other, "damage_on_landing");

		if(land <= 0){ //USED TO AVOID "DAMAGE ON LANDING" SITUATIONS AND BROKE SOME "THROW" MOVES
			if(atkid == getglobalvar("atkid"+self+other)){ //THE CURRENT ATTACKBOX ID IS SAME AS THE PREVIOUS USED ONE??
				changeopenborvariant("lasthitc", 0); //DISABLE THE ENGINE HIT HANDLING
			}
			else //THE CURRENT ATTACKBOX ID IS NOT SAME AS THE PREVIOUS USED ONE??
			{
				changeopenborvariant("lasthitc", 1); //ENABLE THE ENGINE HIT HANDLING
			}
			setglobalvar("atkid"+self+other, atkid); //SAVE THE "LAST ATTACKBOX ID" + "CURRENT PLAYER" + "DAMAGED ENTITY"
		}
	}
}

Then, I put the following line in Ryu, Ken, and a test dummy enemy:
Code:
ondoattackscript data/scripts/multihit.c

The result is identical to the video I posted in the first post. EDIT: This is still in 3.0 6391.
 
NickyP

Sorry, I forgot to mention that this script uses some variables that exists only in my game. To work properly you need to remove these variables:

Code:
void main()
{//Script to avoid "multihits" bug, same as the original SOR2
 //However, to a nostalgic purpose it can be enabled in the Extra Menu
	
	void self	= getlocalvar("self");
	void other	= getlocalvar("other");
	int atkid	= getentityproperty(self, "attackid");
	int land	= getentityproperty(other, "damage_on_landing");

	if(land <= 0){ //USED TO AVOID DAMAGE ON LANDING SITUATIONS
		if(atkid == getglobalvar("atkid"+self+other)){ //THE CURRENT ATTACKBOX ID IS SAME AS THE PREVIOUS USED ONE??
			changeopenborvariant("lasthitc", 0); //DISABLE THE ENGINE HIT HANDLING
		}
		else //THE CURRENT ATTACKBOX ID IS NOT SAME AS THE PREVIOUS USED ONE??
		{
			changeopenborvariant("lasthitc", 1); //ENABLE THE ENGINE HIT HANDLING
		}
		setglobalvar("atkid"+self+other, atkid); //SAVE THE "LAST ATTACKBOX ID" + "CURRENT PLAYER" + "DAMAGED ENTITY"
	}
}

I removed the following line, because in my game you can enable/disable this feature in a custom menu.

Code:
if(getglobalvar("multiHit") == "off"){
 
Back
Top Bottom