Escaping "grabbed" anim

NED

Well-known member
Hello,

I would like to make possible some custom escape from grabbed anim (when enemy grabs you)

There is already the possibility to use "anim  special" A+J, it drains life.
But I'm looking for a way to use another custom move to "override" special ONLY if you're in grabbed anim.

How can I do it ?
Thanks
 
here it is...
I was going to try to and make one of this later after finishing my mod...

however there is a really big problem here...
the player keys are not released this means if the player holds left/right/attack/jump
the gaunge will keep increasing the point was to make it increase only when he presses the key...
Bloodbayne needs to check this !!! I think I once saw him make a release key script....
also when player escapes the slam if a wall is there puff bye bye...
see the attachment below to get the full grab escape entity
http://www.mediafire.com/download/v9oyng1njfaxysn/grab.rar


stick.jpg


this is the grab1 entity
Code:
name	grab1
type			obstacle
scroll			1
health			300
speed			0
nomove			1 1
facing			1 
noquake			1
shadow			0
falldie			1
antigrab		10
offscreenkill 	        30000
subject_to_wall		0
subject_to_platform 	0
subject_to_obstacle 	0
subject_to_hole 	0
subject_to_gravity 	0
diesound        data/sounds/empty.wav
setlayer	999999998

lifebarstatus 150 20 0 1 0 2 5 
lifeposition 120  240
nolife 1



anim	idle
	@script
    	void self = getlocalvar("self");
	void attacker = getentityproperty(self,"parent");
   	void victim2 = getentityproperty(attacker, "opponent");
  	void victim = getentityproperty(victim2, "playerindex");
	int HP = getentityproperty(self,"health");
	int HPmax = getentityproperty(self,"maxhealth");

    	int escape = getentityvar(self, "madjon");


	if(HP>=HPmax && escape == 1){
     	performattack(victim2, openborconstant("ANI_FOLLOW15"));
    	setidle(attacker, openborconstant("ANI_IDLE"));
     	bindentity(victim2, NULL());
	setentityvar(self, "madjon", NULL());
	killentity(self);

	} else if(HP>=HPmax && escape == 2){
     	performattack(victim2, openborconstant("ANI_FOLLOW16"));
    	setidle(attacker, openborconstant("ANI_IDLE"));
     	bindentity(victim2, NULL());
	setentityvar(self, "madjon", NULL());
	killentity(self);

	} else if(HP>=HPmax && escape == 3){
     	performattack(victim2, openborconstant("ANI_FOLLOW17"));
    	setidle(attacker, openborconstant("ANI_IDLE"));
     	bindentity(victim2, NULL());
	setentityvar(self, "madjon", NULL());
	killentity(self);


      	} else if(playerkeys(victim, 0, "moveleft")){// Left is pressed?
    	changeentityproperty(self, "health", HP+1);
	} else if(playerkeys(victim, 0, "moveright")){// Right is pressed?
    	changeentityproperty(self, "health", HP+1);
	} else if(playerkeys(victim, 0, "attack")){// Right is pressed?
    	changeentityproperty(self, "health", HP+1);
	} else if(playerkeys(victim, 0, "jump")){// Right is pressed?
    	changeentityproperty(self, "health", HP+1);
      }
@end_script
	loop	1
	delay	5
	offset	125 130
	bbox	0 0 0 0
	#quakeframe	0 10 5
	platform	1 1 1 1 1 1 1 1
	frame     data/chars/misc/grab/grab01.gif
	frame     data/chars/misc/grab/grab02.gif
	frame     data/chars/misc/grab/grab03.gif
	frame     data/chars/misc/grab/grab02.gif
	frame     data/chars/misc/grab/grab01.gif
	frame     data/chars/misc/grab/grab02.gif
	frame     data/chars/misc/grab/grab03.gif
	frame     data/chars/misc/grab/grab02.gif
	frame     data/chars/misc/grab/grab01.gif
	frame     data/chars/misc/grab/grab02.gif
	frame     data/chars/misc/grab/grab03.gif
	frame     data/chars/misc/grab/grab02.gif

anim	spawn
@script
    void self = getlocalvar("self");
    	changeentityproperty(self, "health",-5);
@end_script
	loop	0
	delay	5
	offset	125 130
	bbox	0 0 0 0
	platform	1 1 1 1 1 1 1 1
	frame     data/chars/misc/grab/empty.gif
	frame     data/chars/misc/grab/empty.gif

the enemy will use a special spawn01 to spawn the grab1 in its slamst animation
anim follow1
loop 0
delay 30
offset 125 215
bbox 0 0 0 0
@cmd stop
@cmd slamstart2
@cmd position 11 45 30 -1 -1
frame data/chars/badguy/grab20.gif
delay 14
        @cmd         spawngrab "grab1" 200 200 450 50 3  #------- escape
@cmd position 7 30 55 -1 -1
frame data/chars/badguy/grab21.gif
@cmd position 11 30 65 -1 -1
frame data/chars/badguy/grab22.gif
@cmd position 11 30 75 -1 -1
frame data/chars/badguy/grab23.gif
frame.....
frame.....

you need to add the spawngrab script in the enemy animations script
animations script.c
void spawngrab(void vName, float fX, float fY, float fZ,int HPgv, int Num2)
{ //Spawns.a.grab---set.it.as.child--with.HP.MAX--opponent.plays.follow
//opponent.follow.Num=1jumpback
//   Num=2dashlow
//           Num=3countergrab

void self = getlocalvar("self");
void vSpawn;
vSpawn = spawn02(vName, fX, fY, fZ);

        setentityvar(vSpawn, "madjon", Num2);

    changeentityproperty(vSpawn, "maxhealth", HPgv);
changeentityproperty(vSpawn, "parent", self); //Set caller as parent.
return vSpawn; //Return spawn.
}

it spawns the grab1 entity on the camera panel coordinates not enemy coordinates
so add spawn02 in animations script
Code:
void spawn02(void vName, float fX, float fY, float fZ)
{	//Spawns entity based on left screen edge
	//vName: Model name of entity to be spawned in.
	//fX: X distance relative to left edge
	//fY: Y height from ground
        //fZ: Z location adjustment

	void self = getlocalvar("self"); //Get calling entity.
	void vSpawn; //Spawn object.
        int XPos = openborvariant("xpos"); //Get screen edge's x position
        int YPos = openborvariant("ypos"); //Get screen edge's y position

	clearspawnentry(); //Clear current spawn entry.
        setspawnentry("name", vName); //Acquire spawn entity by name.

	vSpawn = spawn(); //Spawn in entity.
	changeentityproperty(vSpawn, "position", fX + XPos, fZ + YPos, fY); //Set spawn location.
	return vSpawn; //Return spawn.
}




it works very easly
void spawngrab(void vName, float fX, float fY, float fZ,int HPgv, int Num2) 
vName - entity (grab1)
coords - X 
coords - y - it scrolls with panel so set an altitude of 200
coords - Z - give it a z 400 to bring it 200 down
HPgv  - its the grab1 health 
Num2 - its the player release animation ive only made 3 more can be added (follow15/16/17)

-----release options-----
follow15 - player jumps back
follow16 - player dashes back
follow17 - player makes a counter grab

you need to set Num2 (1/2 or 3)  in enemy @cmd spawngrab for the player to make the escape type depending on the slam...

important !!!
HPgv  - its the grab1 health

in enemy @cmd spawngrab (HPgv) is the gauge release value
entity grab1 sets its health to 1 in its spawn animation when the player presses the keys entity grab1 health wil increase +1 once its reaches 100% the player makes an escape....
so if you give the entity grab1 a health of 1000 the player wil be there pressing the keys for a long time...
this is to make enemies harder and some slams harder to escape than others...

P.S. THE SLAM WORKS FOR ALL PLAYERS ON SCREEN PLAYER0/1/2/3/1000...ETC...
at frist player1 keys were controlling the escape of player 2 but I manadge to get the current player... also entity works better has type obstacle wrong type in media fire grab.rar

I was going to post a neo edit pack with this but I still have to make the slams animations for players and enemy

I will post a video later on... then maybe the neo edit pack 

 
The only script I have in Crime Buster is script which checks current state in SPECIAL animation. If player is NOT in grabbed state change animation to other animation which is the true special
I did that cause I was still using energycost that time. Now that I can replicate energycost with script, I can use inverted version of the script above

I set this script in GRABBED animation
anim grabbed
@script
    void self = getlocalvar("self");

    setlocalvar("GSign" + self, 1);
@end_script
...

This local variable is checked in SPECIAL animation to decide whether to change animation or not

This is example from Athena's SPECIAL:
anim special
@script
    if(frame == 0){
      void self = getlocalvar("self");
      if(getlocalvar("GSign" + self) != 1){
        changeentityproperty(self, "animation", openborconstant("ANI_FREESPECIAL4"));
      }
    }
@end_script
...

The script will change her animation to freespecial4 is she's not grabbed
 
I can use inverted version of the script above
inverted version how ? using the script on player.txt

The only script I have in Crime Buster
I meant the player keys... it needs to make the action only if the key is released otherwise the player can just hold the attack button and the release gauge will increase at maximum velocity... but maybe theres something wrong with the script or player keys...

ive checked GI joe Skyhawk keyscript fly.c and this seems to be what I was forgetting...
    void iLeftR = playerkeys(iPlIndex, 2, "moveleft"); // Release status of "Left"
    void iRightR = playerkeys(iPlIndex, 2, "moveright"); // Release status of "Right"

when I use 2 instead fo 0 it works the release gauge increases by pressing one key at the time...
but theres something wrong with it... its lagging a lot... delays of 50/30 maybe 20 beteween the inputs...
maybe the problem its from playerkeys itself...
playerkeys(playerindex, newkey?, key1, key2, key3, ...)

*NOTE* This method call is a bit buggy as of 8/8/2007. If not used in "key#.c" it will always return 0 unless newkey? = 0. If used to detect multiple keys, 1 will be returned if ANY of the specified keys are pressed.
 
Hello, jonsilva. I am testing your grab release system and it works well. Only 2 issues i cant solve.
1st is grab1 entity do not disappears if player dont press any keys and enemy performs grab attack.
2nd is when player releases from grab 1st time, grab1 entity disappears but when enemy perform this attack second and next times it is just regular attack, even followcond not work and follow anim not starts.

Ok, 2nd one is solved. The thing was in followcond 4. I set it to 3 and now enemy grabs player every time he perform attack

Do you has those problems?
Thank you.
 
I just released I never replied to your message guys.
I think my head was somewhere because of my professional contest.

Anyway, thanks.
I finally took off this feature for the moment, since there is more priority making other system parts.

I'm still interested on it.
Mtrain, if you finally fix it, I'll be pleased to look how you do it.
Good luck
 
nedflandeurse, I solve this, but without pressing left, right, attack, jump event.
But in my method you still need rapidly press attack button to escape grab. So how it looks:

Enemy grab anim
Code:
anim 	follow1
	hitfx	data/sounds/none.wav
	offset	165 170
        bbox	154 21 129 146
	sound data/sounds/punch.wav
	delay	10
		offset  160  170
	@cmd	slamstart2
	@cmd    position 8 100 1 -1 0
	frame	data/chars/donovan/x/108.gif
#------------------------------------------------start of grappling
	delay	20
	@cmd    position 8 150 1 -1 0
	frame   data/chars/donovan/x/106.gif
	@cmd    position 9 150 1 -1 0
	frame   data/chars/donovan/x/120.gif
	@cmd    position 8 150 1 -1 0
	frame   data/chars/donovan/x/106.gif
	@cmd    position 9 150 1 -1 0
	frame   data/chars/donovan/x/120.gif
	@cmd    position 8 150 1 -1 0
	frame   data/chars/donovan/x/106.gif
	@cmd    position 9 150 1 -1 0
	frame   data/chars/donovan/x/120.gif
	@cmd    position 8 150 1 -1 0
	frame   data/chars/donovan/x/106.gif
	@cmd    position 9 150 1 -1 0
	frame   data/chars/donovan/x/120.gif
#------------------------------------------------end of grappling
	@cmd    depost 	0
	@cmd    finish 	40 3 2 7 0 0
	frame   data/chars/donovan/x/120.gif

Player anim
Code:
anim fall7
	loop	0
	offset	257 98
	delay	200
	frame	data/chars/axel/q/1210.gif
	frame	data/chars/axel/q/1210.gif
		offset  280  297
	frame	data/chars/axel/q/1063.gif
	frame  data/chars/axel/q/1210.gif
	frame  data/chars/axel/q/g2.gif
		offset  310  166
	frame  data/chars/axel/q/g1.gif
		offset  301  166
	frame  data/chars/axel/q/1209.gif
		offset  280  297
	frame  data/chars/axel/q/1210.gif
	@cmd	bigcounter2  <-------------------------frame8
	frame	data/chars/axel/q/pj.gif
	@cmd	bigcounter2  <-------------------------frame9
	frame	data/chars/axel/q/g1.gif

Code:
void bigcounter2()
{// counterattack from big grab while slamstarter
   void self = getlocalvar("self");
   void attacker = getentityproperty(self, "opponent");
   int player = getlocalvar("player");
   int frame = getentityproperty(self, "animpos");

	if(playerkeys(player, 0, "attack") && (frame == 8 || frame == 9)){
     	bindentity(self, NULL());
    	setidle(attacker, openborconstant("ANI_IDLE"));
    	performattack(self, openborconstant("ANI_FREESPECIAL8"));
	}
}

When enemy attacks player with follow1, he grabs player in grapple and they start to struggle during 8 frames (8 and 9 frame of players fall7). Player need to press attack, then enemy instantly release player, goes to idle and player perform FREESPECIAL8. I dont know is it bug, but you need to rapidly press attack to perform release move. But this plays on our side :D
 
Thanks guys,
both method seems very interesting.

Anyway, Magggas method seems easier to me since it involves using player control to "emulate being grabbed".

But for both, I still struggle to understand since I can't see what each anim does actually as pictures/screenshots...
 
i think this method works if you just hold attack, which isnt fun, you dont have to mash the button , does anyone know how to make it harder ? So you have to mash the button and cant just hold it to escape ?
Heres mine
Code:
					@script
                void self = getlocalvar("self");
                int iPIndex = getentityproperty(self,"playerindex"); //Get player index
                    void oppo = getentityproperty(self, "opponent");
                    void p1 = playerkeys(iPIndex, 0, "attack");
                 if ( p1 && frame == 18 ){
	  damageentity(oppo, self, 50, 1, openborconstant("ATK_NORMAL2"));
   	    performattack(self, openborconstant("ANI_FOLLOW6"));
		}
	@end_script
For this :
 
yeah but if player 1 and player 3 will be wrestling with giant arm, the same variable will be updated, any ideas how to differentiate p1 and p3 variable in most efficient way?
Also when i hold attack it updates variable like on autofire
---
This does the trick, i guess id have to do separate variable for each player,  but how ? iPIndex takes care of it but im still using one variable for all players.
Code:
					@script
                void self = getlocalvar("self");
                int iPIndex = getentityproperty(self,"playerindex"); //Get player index
                    void oppo = getentityproperty(self, "opponent");
                    void p2 = playerkeys(iPIndex, 1, "attack");
					void p1 = playerkeys(iPIndex, 2, "attack");
                 if ( getglobalvar("P1ES") >= 3 && frame == 22 ){
	  damageentity(oppo, self, 50, 1, openborconstant("ATK_NORMAL2"));
   	    performattack(self, openborconstant("ANI_FOLLOW6"));
		}
		                 if (( p1 )|| ( p2 )){
	setglobalvar("P1ES", getglobalvar("P1ES")+1 );  
 settextobj(1, 250 , 280 , 0, -1, getglobalvar("P1ES") , openborvariant("elapsed_time")+200);
		}
	@end_script
---
Ive got this, it doesnt work all the time, sometimes i cant get even 1 var point when i tap attack, but it kinda works
Code:
					@script
                void self = getlocalvar("self");
                int iPIndex = getentityproperty(self,"playerindex"); //Get player index
                    void oppo = getentityproperty(self, "opponent");
                    void p1 = playerkeys(iPIndex, 1, "attack");
					void p1b = playerkeys(iPIndex, 2, "attack");
							                 if (frame == 1){
settextobj(1, getentityproperty(self,"x")-50-openborvariant("xpos") , getentityproperty(self,"z")-260-openborvariant("ypos") , 1, -1, " TAP ATTACK !!!" , openborvariant("elapsed_time")+250);
  setglobalvar(iPIndex +"P1ES", 0 );	
		}

		                 if (( p1 )|| ( p1b )){
  setglobalvar(iPIndex +"P1ES", getglobalvar(iPIndex+"P1ES")+1 );	
 settextobj(1, 250 , 280 , 0, -1, getglobalvar(iPIndex +"P1ES") , openborvariant("elapsed_time")+200);
		}
		                 if ( getglobalvar(iPIndex +"P1ES") >= 3 && frame == 22 ){
				   setglobalvar(iPIndex +"P1ES", 0 );	
	  damageentity(oppo, self, 50, 1, openborconstant("ATK_NORMAL2"));
   	    performattack(self, openborconstant("ANI_FOLLOW6"));
		}
	@end_script
If theres some other way that works all the time let me know.
 
Are you triggering the key press, right? Why don't you trigger the key release instead? It will give you more time to detect it.

About the variable, I saw that you added an index to it. But you can use a entity variable instead of a global one.
 
I tried different values 1 means pressed and 2 means released and 0 means held, but its not as reliable.  void p2 = playerkeys(iPIndex, 1, "attack");
Did you seen something similar somewhere? Manual also says its better to use keyscript cause its often returning 0 if you dont.

  void iUpR = playerkeys(iPlIndex, 2, "moveup"); // Release status of "Up"
  void iUp = playerkeys(iPlIndex, 1, "moveup"); // New key status of "Up"
void iUpH = playerkeys(iPlIndex, 0, "moveup"); // Held key status of "Up"
Id have to experiment more.
Also i read DC wrote something about entity vars that theyre there but its better not to use them , globalvars are the best.
 
Keyscript would be more reliable for sure.
About the global variables, I think you misunderstood what Damon Caskey said.

Globalvar is very useful, but it's not for every case and it will turn against you in no time if you don't handle it well. Because they are persistent and get even saved in save games as well.

Btw, search for a topic called Charge like MegaMan. White dragon did something with charge buttons, maybe you can adapt from there
 
nedflandeurse said:
Hello,

I would like to make possible some custom escape from grabbed anim (when enemy grabs you)

There is already the possibility to use "anim  special" A+J, it drains life.
But I'm looking for a way to use another custom move to "override" special ONLY if you're in grabbed anim.

How can I do it ?
Thanks

Hi nedflandeurse! SOR2X already has a "grabbed escape" move with simple script. In my case I use guardpoints to escape instead of consuming life or mp. And used damageentity to reset opponent "grabbing" status. You can see an example in this video at 0:14.

https://www.youtube.com/watch?v=31Zl_HPUXkU&feature=youtu.be

ENTITY KEYSCRIPT.C
Code:
void grabEscape()
{//Escape when grabbed
        void self       = getlocalvar("self");
	void target     = getentityproperty(self,"opponent");
	void vAniID     = getentityproperty(self,"animationID");
	int iPIndex     = getentityproperty(self,"playerindex");
	int dir		= getentityproperty(self,"direction");
	int maxGP	= getentityproperty(self,"maxguardpoints");
	int gp 		= getentityproperty(self,"guardpoints");
	int costGp	= maxGP/5*4;
	int xVel	= 2;
	
	if(dir == 0){
		xVel = -xVel;
	}
	
	if(playerkeys(iPIndex, 1, "attack")){
		if(vAniID == openborconstant("ANI_GRABBED") && gp == maxGP){
			gpCost(costGp);
			damageentity(target, self, 0, 0, openborconstant("ATK_NORMAL"));
			tossentity(target, 0.2, xVel, 0);
			performattack(self, openborconstant("ANI_FOLLOW6"), 0);
		}
	}
}

ANIMATION
Code:
anim follow6 #GRAB ESCAPE
	loop	0
	delay	16
	offset	62 126
	sound	data/sounds/Throw.wav
	@cmd dasher -1.2 0 0
	@cmd spawn01 "escape" 25 50 1
	frame	data/chars/axel/grabatk00.gif
		delay	8
	sound	data/sounds/Slide.wav
	@cmd dasher -0.8 0 0
	@cmd spawn01 "dust" 0 0 1
	frame	data/chars/axel/block00.gif
	@cmd dasher -0.2 0 0
	frame	data/chars/axel/block00.gif
 
Kratus said:
nedflandeurse said:
Hello,

I would like to make possible some custom escape from grabbed anim (when enemy grabs you)

There is already the possibility to use "anim  special" A+J, it drains life.
But I'm looking for a way to use another custom move to "override" special ONLY if you're in grabbed anim.

How can I do it ?
Thanks

Hi nedflandeurse! SOR2X already has a "grabbed escape" move with simple script. In my case I use guardpoints to escape instead of consuming life or mp. And used damageentity to reset opponent "grabbing" status. You can see an example in this video at 0:14.

https://www.youtube.com/watch?v=31Zl_HPUXkU&feature=youtu.be

ENTITY KEYSCRIPT.C
Code:
void grabEscape()
{//Escape when grabbed
        void self       = getlocalvar("self");
	void target     = getentityproperty(self,"opponent");
	void vAniID     = getentityproperty(self,"animationID");
	int iPIndex     = getentityproperty(self,"playerindex");
	int dir		= getentityproperty(self,"direction");
	int maxGP	= getentityproperty(self,"maxguardpoints");
	int gp 		= getentityproperty(self,"guardpoints");
	int costGp	= maxGP/5*4;
	int xVel	= 2;
	
	if(dir == 0){
		xVel = -xVel;
	}
	
	if(playerkeys(iPIndex, 1, "attack")){
		if(vAniID == openborconstant("ANI_GRABBED") && gp == maxGP){
			gpCost(costGp);
			damageentity(target, self, 0, 0, openborconstant("ATK_NORMAL"));
			tossentity(target, 0.2, xVel, 0);
			performattack(self, openborconstant("ANI_FOLLOW6"), 0);
		}
	}
}

ANIMATION
Code:
anim follow6 #GRAB ESCAPE
	loop	0
	delay	16
	offset	62 126
	sound	data/sounds/Throw.wav
	@cmd dasher -1.2 0 0
	@cmd spawn01 "escape" 25 50 1
	frame	data/chars/axel/grabatk00.gif
		delay	8
	sound	data/sounds/Slide.wav
	@cmd dasher -0.8 0 0
	@cmd spawn01 "dust" 0 0 1
	frame	data/chars/axel/block00.gif
	@cmd dasher -0.2 0 0
	frame	data/chars/axel/block00.gif

Kratus
Thanks for sharing your help.
Right now I'm not anymore in a sittuation to work in any game project.
Openbor took all my motivation.

And I need motivation for real life projects.
Now, I just have the energy to support and comment other people's project. Because I still like this engine and community.

I might give it a try in some months if the sittuation evoluate.
 
Back
Top Bottom