Combostyle 1 for A2

Galaxcius

New member
Good morning friends!
I am using the second attack button (A2) to execute kick combos.
I used the cancel and follow commands but unfortunately I can not satisfy this dynamic.
The Combostyle 1 command allows the first attack, move and walk with character to any direction and make the second attack giving continuity to the combo.
I would like a "Combostyle 1" for the A2 because of this dynamics.
Can someone help me?
 
Are you saying combo style executes in between walk animations because this does not sound right to me it should reset if you move!

This sounds like it could be done using keyscripts are you familiar with them ?  Please clarify the desired results!
 
msmalik681 said:
Are you saying combo style executes in between walk animations because this does not sound right to me it should reset if you move!

This is not correct. Auto combos are based on an adjustable time delay that resets the combo if it expires between hits. Movement plays no part at all - it just appears that way because the default delay is very short.

DC

 
msmalik681 said:
Are you saying combo style executes in between walk animations because this does not sound right to me it should reset if you move!

This sounds like it could be done using keyscripts are you familiar with them ?  Please clarify the desired results!

Combostyle 1 allows me to move without interrupting the combo, I can
turn and attack other enemies without breaking the combo chain.

Yes I am familiar, but I do not know how to work with keyscript to satisfy this function using A2.
 
Damon Caskey said:
msmalik681 said:
Are you saying combo style executes in between walk animations because this does not sound right to me it should reset if you move!

This is not correct. Auto combos are based on an adjustable time delay that resets the combo if it expires between hits. Movement plays no part at all - it just appears that way because the default delay is very short.

DC

Perfectly, this is how Combostyle 1 works. It just does not apply to cancel and follow. The animation needs to be in progress which does not allow me to turn around and attack another opponent without the combo restarting in case command cancel and follow.

I still do not know a way to make the cancel or follow work with the same dynamism equal or similar to combostyle 1 for A2
 
What you need to do is have a keyscript activate when you press a2 at this point you will capture the current time and set a counter to increment.  within this if statement have another if statement so on the next a2 the counter should be on 2 and use the current time to work out the difference from the last stored time if it is all ok then use performattack to push to the second attack and so on. Remember to have a else statement to reset the time and counter. Make sure you can only use this either from walking animation or idle or any of the a2 attack animations.

Disable a2 as a button in the mod and let keyscripts handle it.
 
msmalik681 said:
What you need to do is have a keyscript activate when you press a2 at this point you will capture the current time and set a counter to increment.  within this if statement have another if statement so on the next a2 the counter should be on 2 and use the current time to work out the difference from the last stored time if it is all ok then use performattack to push to the second attack and so on. Remember to have a else statement to reset the time and counter. Make sure you can only use this either from walking animation or idle or any of the a2 attack animations.

Disable a2 as a button in the mod and let keyscripts handle it.

An interesting logic. But I do not have enough knowledge to implement logic in a satisfactory way, I need more help to create this function. If one feels in the heart, it is not much, but I will remember the name. Does anyone know how to create this code?
 
Remember my name MSMALIK681  :P

Code:
void main()//keyscripts
{//msmalik681 combo attack with a2
 if (openborvariant("in_level")){
    int playerIndex = getlocalvar("player"); //Get calling player
    void self = getplayerproperty(playerIndex ,"entity"); //Get calling entity
    void exists = getentityproperty(self, "exists"); // Is caller alive
    char name = getentityproperty(self, "name"); // Get callers name
    void vAniID = getentityproperty(self,"animationID"); //Get current animation ID
    void vAniPos = getentityproperty(self, "animpos"); //Get current animation frame
    int iDir = getentityproperty(self, "direction");  //Get current facing direction
    float x = getentityproperty(self, "x");
    float y = getentityproperty(self, "y");
    float z = getentityproperty(self, "z");
    float base = getentityproperty(self, "base");
    void iStart = playerkeys(playerIndex, 1, "start"); //New key status of "Start"
    void iUp = playerkeys(playerIndex, 1, "moveup"); // New key status of "Up"
    void iDown = playerkeys(playerIndex, 1, "movedown"); // New key status of "Down"
    void iLeft = playerkeys(playerIndex, 1, "moveleft"); // New key status of "Left"
    void iRight = playerkeys(playerIndex, 1, "moveright"); // New key status of "Right"
    void iJump = playerkeys(playerIndex, 1, "jump"); //New key status of "Jump"
    void iSpecial = playerkeys(playerIndex, 1, "Special"); //New key status of "Special"
    void iAttack = playerkeys(playerIndex, 1, "attack"); //New key status of "Attack"
    void iAttack2 = playerkeys(playerIndex, 1, "attack2"); // New key of "Attack 2"
    void iAttack3 = playerkeys(playerIndex, 1, "attack3"); // New key of "Attack 3"
    void iAttackR = playerkeys(playerIndex, 2, "attack"); //New key status of release "Attack"
    void iSpecialR = playerkeys(playerIndex, 2, "Special"); //New key status of release "Special"
    void iJumpR = playerkeys(playerIndex, 2, "jump"); //New key status of "Jump"
    void iRightR = playerkeys(playerIndex, 2, "moveright"); // New key status of "Right"

	
	int counter, time; //placeholder for time and counter check
	int timeplus = 150; //set minimum time to press button before reset
	if(counter==NULL()){counter=0;} //set counter to zero just on first run
	if(iAttack2) //if you press attack2
	{
		if(counter==0 && (vAniID==openborconstant("ANI_IDLE") || vAniID==openborconstant("ANI_WALK"))) //if counter is 0 and you are in one of these animations.
		{
			time = openborvariant("elapsed_time")+timeplus; //set time to current time + timeplus
			performattack(self, openborconstant("ANI_ATTACK1"),0); //perform attack
			changeentityproperty(self, "velocity", 0, 0, 0); //stop player from keeping walk velocity
			counter++; //increment counter
		} else if(counter==1 && time > openborvariant("elapsed_time") && (vAniID==openborconstant("ANI_IDLE") || vAniID==openborconstant("ANI_WALK") || vAniID==openborconstant("ANI_ATTACK1")))
		{
			time = openborvariant("elapsed_time")+timeplus;
			performattack(self, openborconstant("ANI_ATTACK2"),0);
			changeentityproperty(self, "velocity", 0, 0, 0);
			counter++;
		} else if(counter==2 && time > openborvariant("elapsed_time") && (vAniID==openborconstant("ANI_IDLE") || vAniID==openborconstant("ANI_WALK") || vAniID==openborconstant("ANI_ATTACK2")))
		{
			time = openborvariant("elapsed_time")+timeplus;
			performattack(self, openborconstant("ANI_ATTACK3"),0);
			changeentityproperty(self, "velocity", 0, 0, 0);
			counter++;
		} else if(vAniID==openborconstant("ANI_IDLE") || vAniID==openborconstant("ANI_WALK")) //this is the reset animation if they did not hit the next button in time
		{
			time = openborvariant("elapsed_time")+timeplus;
			performattack(self, openborconstant("ANI_ATTACK1"),0);
			changeentityproperty(self, "velocity", 0, 0, 0);
			counter=1;
		}
	


	}
	
	}
 }

to help you understand it better here is a tech demo the file you need to copy is keyall.c and remember to change the names of the attacks to match your character attack animations.  It was a bit more complicated then I originally thought lol enjoy
 
msmalik681 said:
Remember my name MSMALIK681  :P

Code:
void main()//keyscripts
{//msmalik681 combo attack with a2
 if (openborvariant("in_level")){
    int playerIndex = getlocalvar("player"); //Get calling player
    void self = getplayerproperty(playerIndex ,"entity"); //Get calling entity
    void exists = getentityproperty(self, "exists"); // Is caller alive
    char name = getentityproperty(self, "name"); // Get callers name
    void vAniID = getentityproperty(self,"animationID"); //Get current animation ID
    void vAniPos = getentityproperty(self, "animpos"); //Get current animation frame
    int iDir = getentityproperty(self, "direction");  //Get current facing direction
    float x = getentityproperty(self, "x");
    float y = getentityproperty(self, "y");
    float z = getentityproperty(self, "z");
    float base = getentityproperty(self, "base");
    void iStart = playerkeys(playerIndex, 1, "start"); //New key status of "Start"
    void iUp = playerkeys(playerIndex, 1, "moveup"); // New key status of "Up"
    void iDown = playerkeys(playerIndex, 1, "movedown"); // New key status of "Down"
    void iLeft = playerkeys(playerIndex, 1, "moveleft"); // New key status of "Left"
    void iRight = playerkeys(playerIndex, 1, "moveright"); // New key status of "Right"
    void iJump = playerkeys(playerIndex, 1, "jump"); //New key status of "Jump"
    void iSpecial = playerkeys(playerIndex, 1, "Special"); //New key status of "Special"
    void iAttack = playerkeys(playerIndex, 1, "attack"); //New key status of "Attack"
    void iAttack2 = playerkeys(playerIndex, 1, "attack2"); // New key of "Attack 2"
    void iAttack3 = playerkeys(playerIndex, 1, "attack3"); // New key of "Attack 3"
    void iAttackR = playerkeys(playerIndex, 2, "attack"); //New key status of release "Attack"
    void iSpecialR = playerkeys(playerIndex, 2, "Special"); //New key status of release "Special"
    void iJumpR = playerkeys(playerIndex, 2, "jump"); //New key status of "Jump"
    void iRightR = playerkeys(playerIndex, 2, "moveright"); // New key status of "Right"

	
	int counter, time; //placeholder for time and counter check
	int timeplus = 150; //set minimum time to press button before reset
	if(counter==NULL()){counter=0;} //set counter to zero just on first run
	if(iAttack2) //if you press attack2
	{
		if(counter==0 && (vAniID==openborconstant("ANI_IDLE") || vAniID==openborconstant("ANI_WALK"))) //if counter is 0 and you are in one of these animations.
		{
			time = openborvariant("elapsed_time")+timeplus; //set time to current time + timeplus
			performattack(self, openborconstant("ANI_ATTACK1"),0); //perform attack
			changeentityproperty(self, "velocity", 0, 0, 0); //stop player from keeping walk velocity
			counter++; //increment counter
		} else if(counter==1 && time > openborvariant("elapsed_time") && (vAniID==openborconstant("ANI_IDLE") || vAniID==openborconstant("ANI_WALK") || vAniID==openborconstant("ANI_ATTACK1")))
		{
			time = openborvariant("elapsed_time")+timeplus;
			performattack(self, openborconstant("ANI_ATTACK2"),0);
			changeentityproperty(self, "velocity", 0, 0, 0);
			counter++;
		} else if(counter==2 && time > openborvariant("elapsed_time") && (vAniID==openborconstant("ANI_IDLE") || vAniID==openborconstant("ANI_WALK") || vAniID==openborconstant("ANI_ATTACK2")))
		{
			time = openborvariant("elapsed_time")+timeplus;
			performattack(self, openborconstant("ANI_ATTACK3"),0);
			changeentityproperty(self, "velocity", 0, 0, 0);
			counter++;
		} else if(vAniID==openborconstant("ANI_IDLE") || vAniID==openborconstant("ANI_WALK")) //this is the reset animation if they did not hit the next button in time
		{
			time = openborvariant("elapsed_time")+timeplus;
			performattack(self, openborconstant("ANI_ATTACK1"),0);
			changeentityproperty(self, "velocity", 0, 0, 0);
			counter=1;
		}
	


	}
	
	}
 }

to help you understand it better here is a tech demo the file you need to copy is keyall.c and remember to change the names of the attacks to match your character attack animations.  It was a bit more complicated then I originally thought lol enjoy

Excellent job! It works better than I imagined. Can I ask for a small adjustment?

By pressing a2 quickly, the animation skips the current frames, it would be interesting in the combo string to end the animation from one attack to the next, so the animation can flow through without being interrupted by pressing a2 again.

Some current frame query, I have no idea. Is it possible to add this to the code?
 
msmalik681, if you're going to use old copies of my stuff... which I can tell you based your script from, you need to actually analyze and fully understand them. Especially when you pass them along in tutorials!

Most (almost all actually) of the initialized variables are not being used in any way. They should be removed or disabled.

DC
 
@DC
Sorry I did not know that keyscript was originally made by you I found it in some mod.  And I thought about taking all the extra stuff out but thought Galaxcius may find use for them as I did in my mod.  This was more of a example then a tutorial (but I hope to make a tutorial and I will add you to the credits for that)

@Galaxcius
Here is a cut down version of the script with the ability to cancel other attacks removed.
Code:
void main()//keyscripts
{//msmalik681 combo attack with a2. credit to DC for script base.
 if (openborvariant("in_level")){
    void self = getplayerproperty(getlocalvar("player") ,"entity"); //Get calling entity
    void vAniID = getentityproperty(self,"animationID"); //Get current animation ID
    void iAttack2 = playerkeys(playerIndex, 1, "attack2"); // New key of "Attack 2"
	
	int counter, time; //placeholder for time and counter check
	int timeplus = 150; //set minimum time to press button before reset
	if(counter==NULL()){counter=0;} //set counter to zero just on first run
	if(iAttack2) //if you press attack2
	{
		if(counter==0 && (vAniID==openborconstant("ANI_IDLE") || vAniID==openborconstant("ANI_WALK"))) //if counter is 0 and you are in one of these animations.
		{
			time = openborvariant("elapsed_time")+timeplus; //set time to current time + timeplus
			performattack(self, openborconstant("ANI_ATTACK1"),0); //perform attack
			changeentityproperty(self, "velocity", 0, 0, 0); //stop player from keeping walk velocity
			counter++; //increment counter
		} else if(counter==1 && time > openborvariant("elapsed_time") && (vAniID==openborconstant("ANI_IDLE") || vAniID==openborconstant("ANI_WALK")))
		{
			time = openborvariant("elapsed_time")+timeplus;
			performattack(self, openborconstant("ANI_ATTACK2"),0);
			changeentityproperty(self, "velocity", 0, 0, 0);
			counter++;
		} else if(counter==2 && time > openborvariant("elapsed_time") && (vAniID==openborconstant("ANI_IDLE") || vAniID==openborconstant("ANI_WALK")))
		{
			time = openborvariant("elapsed_time")+timeplus;
			performattack(self, openborconstant("ANI_ATTACK3"),0);
			changeentityproperty(self, "velocity", 0, 0, 0);
			counter++;
		} else if(vAniID==openborconstant("ANI_IDLE") || vAniID==openborconstant("ANI_WALK")) //this is the reset animation if they did not hit the next button in time
		{
			time = openborvariant("elapsed_time")+timeplus;
			performattack(self, openborconstant("ANI_ATTACK1"),0);
			changeentityproperty(self, "velocity", 0, 0, 0);
			counter=1;
		}
	}
	}
 }
 
I am with Damon on this one, no offense.

First, if your code is based on DC's code, you really should credit him.
Second, there are not used variables which were initiliazed. This is wasting memory for nothing.

Third, I have some questions about the scriipt itself:
int playerIndex = getlocalvar("player"); //Get calling player
void self = getplayerproperty(playerIndex ,"entity"); //Get calling entity
void exists = getentityproperty(self, "exists"); // Is caller alive

1- "exists", as the name and manual says, tells if the caller is valid (IOW exists), not if its alive, as far as I know. The entity can exist and be not alive at the same time. Dead entities are still valid, killed entities not.

2- If you get the self at the second line and it returns a valid value, why you need to check if it exists again?

3- You should change the code to check it the entity is valid as the main condition, right in the start. Then ONLY if its valid (IOW, using it inside a IF), you continue with all those variable initialization.

And why I am saying this? For optmization sake.
if (openborvariant("in_level")){
    int playerIndex = getlocalvar("player"); //Get calling player
    void self = getplayerproperty(playerIndex ,"entity"); //Get calling entity
    void exists = getentityproperty(self, "exists"); // Is caller alive
  if (exists){
  *continue your logic*
    }

Because the way it is know, the engine will initialize all those variables even if the caller is not valid, wasting resources. If you check it the caller is valid, the engine will skip it.

 
I don't really care about credit, I just don't want bad practices passed around to new users.

It's also fine if you don't fully understand a script... or do but know some of its contents are superfluous. But in either case you need to say so as a disclaimer.

DC
 
@O Ilusionista
I did not have any way to know DC wrote the base to that code (that is everything before "int counter") or I would have no issue leaving his name on there.  And I have to admit I was being lazy leaving all the variables initialised and thanks for the info about "exists"

@DC
Sure thing no problem.
 
It worked perfectly, I'm very grateful. I'll remember the name of all of you, MSMALIK681, Damon Caskey, O Ilusionista. I want to reciprocate in some way. Thank you all for your help!
 
Back
Top Bottom