Walking throw

danno

Moderator
Staff member
I currently have a walking throw set up like this, player entity can't grab but as you walk forward and press attack player throws enemy by interrupting attack and switching to throw if enemy is within set distance

Code:
void walkthrow(int RxMin, int RxMax, int Rz, void Ani)

    void self = getlocalvar("self");
    void target = findtarget(self); //Get nearest player
    float x = getentityproperty(self, "x");
    float z = getentityproperty(self, "z");
    int dir = getentityproperty(self, "direction");
	int iPIndex = getentityproperty(self,"playerindex");
	void lef = playerkeys(iPIndex, 0, "moveleft");
	void rig = playerkeys(iPIndex, 0, "moveright");


    if(target!=NULL()){
      float Tx = getentityproperty(target, "x");
      float Tz = getentityproperty(target, "z");
      float Disx = Tx - x;
      float Disz = Tz - z;

      if(Disz < 0){
        Disz = -Disz;
      }

      if( Disx >= RxMin && rig && Disx <= RxMax && Disz <= Rz && dir == 1) // Target within range on right facing?
      {
        performattack(self, openborconstant(Ani)); //Change the animation
      } else if( Disx >= -RxMax && lef && Disx <= -RxMin && Disz <= Rz && dir == 0) // Target within range on left facing?
      {
        performattack(self, openborconstant(Ani)); //Change the animation
      }
    }
}


but sometimes it doesn't execute the throw and instead micro stutters or not at all unless I interact with entity first

any tips on making a walking throw smoother?
 
danno,

This is the most likely culprit:
Code:
void target = findtarget(self); //Get nearest player

findtarget(entity, int animation) -  Note the animation parameter. What find target really does is find the first hostile target in entity list that's within range of an animation. If you don't include the optional range parameter, OpenBOR just uses the entity's current animation instead... and there's your inconsistency.

I suggest you remove the manual range checks you coded into the script, and instead send the throwing animation ID to findtarget. Then you can adjust its range to suit your needs. While on the subject, I also see another problem. You are sending the animation name by text. Don't do that. It's severely taxing to the engine. See here for an explanation and what you should do instead.

The end result is a much simpler function that looks like this (hopefully no typos):

Code:
void walkthrow(int animation_id)
{

	void self = getlocalvar("self");
	void target = findtarget(self, animation_id); // Get nearest player
	int dir = getentityproperty(self, "direction");
	int iPIndex = getentityproperty(self, "playerindex");
	void lef = playerkeys(iPIndex, 0, "moveleft");
	void rig = playerkeys(iPIndex, 0, "moveright");

	/*
	* Did findtarget locate a valid target within the
	* throw animation's range?
	*/

	if (target)
	{
		/*
		* If key command and direction match, execute throw
		* animation.
		*/
		if (rig && dir == 1 || lef && dir == 0)
		{
			performattack(self, openborconstant(animation_id));
		}
	}
}

Here's what the fixed call looks like, if your throw animation was follow10.

Code:
walkthrow(openborconstant("ANI_FOLLOW10"))

HTH,
DC
 
Strange, I thought without the range checks it would of just played the throw animation as soon as target was in attack range but it doesn't, works great, smooth as butter Damon thank you.
 
This is kind of a double issue

danno said:
doesn't execute the throw and instead micro stutters or not at all unless I interact with entity first

I'm still having this issue it seems, I can walk past enemies while pressing attack and nothing will happen or a slight animation stutter, I have to interact with the enemy first before being able to walk throw

also I've tried scripting a non grab (grab) and the same entity I've previously thrown or interacted with teleports to me to be thrown in place of new target, I know this has something to do with ''opponent''
as I've looked at other threads but can't seem to find a clearing solution

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


heres my animations

Code:
anim attack
loop      0
delay     6
offset    63 104
bbox      62 42 17 63
hitfx	      data/sounds/hit.wav
@cmd    walkthrow2 (openborconstant("ANI_FREESPECIAL2"))
frame     data/chars/kim/a1.png
delay     10
attack    69 46  29 17 1
frame     data/chars/kim/a2.png
attack    0
delay     6
frame     data/chars/kim/a1.png

and

Code:
anim  freespecial2 #walking throw

range 0 24
attackone 1
loop          0
delay        11
offset        63 104
@cmd	 clearGrab
@cmd      grabStart5
@cmd	 position 0 8 10 0 -1
frame        data/chars/kim/t1.png
delay         20
@cmd	 position 4 -9 12 0 1
sound	  data/sounds/kim3.wav
frame     data/chars/kim/t2.png
delay     7
@cmd     position 5 -12 23 1 1
frame     data/chars/kim/t3.png
@cmd    position 7 41 6 1 1
frame     data/chars/kim/t4.png
@cmd    depost
@cmd    throw 4 2 2 2 0 0
frame     data/chars/kim/t4.png
frame     data/chars/kim/t5.png
delay      5
@cmd    clearL
frame     data/chars/kim/t6.png


grabstart5

Code:
void grabStart5()
{
   void self 	= getlocalvar("self");
    void target = getentityvar(self, "target" + "grabbed");

	if(target == NULL()){
		target = getentityproperty(self, "opponent");
		setentityvar(self, "target", target);
	
		
		if(target == NULL() || getentityproperty(target, "dead") == 1){
			setidle(self);
		}else{
			setentityvar(self, "grabbed", target);
		}
	}
	
	if(target != NULL()){
		damageentity(target, self, 0, 1, openborconstant("ATK_NORMAL7"));
}


clearing

Code:
void clearGrab()
{
   void self = getlocalvar("self");
   setlocalvar("Target" + self, NULL());
}

also tried

Code:
void clearGrab5()
{
   void self = getlocalvar("self");
   setentityvar(self, "target", NULL());
}

any ideas guys?
 
also I've tried scripting a non grab (grab) and the same entity I've previously thrown or interacted with teleports to me to be thrown in place of new target, I know this has something to do with ''opponent''

This happens because you haven't cleared the target variable after the move is finished, so every time you refer to target, the engine will use the last one because it's still active.
 
Yeah that's what I'm having problems with in other animations too, If you look in the video the first attack is a jab and as I go to throw another entity the previous one I jabbed teleports so this happens before I even start throwing.
 
Let's see:
Code:
void grabStart5()
{
   void self 	= getlocalvar("self");
    void target = getentityvar(self, "target" + "grabbed");

	if(target == NULL()){
		target = getentityproperty(self, "opponent");
		setentityvar(self, "target", target);
	
		
		if(target == NULL() || getentityproperty(target, "dead") == 1){
			setidle(self);
		}else{
			setentityvar(self, "grabbed", target);
		}
	}
	
	if(target != NULL()){
		damageentity(target, self, 0, 1, openborconstant("ATK_NORMAL7"));
}

Code:
void clearGrab()
{
   void self = getlocalvar("self");
   setlocalvar("Target" + self, NULL());
}

void clearGrab5()
{
   void self = getlocalvar("self");
   setentityvar(self, "target", NULL());
}

I can see mismatch here. clearGrab clears local variable : "Target" + self and clearGrab5 clears entity variable : "target" however grabStart5 checks entity variable : "target" + "grabbed" .
Try matching the name and type of variable being used here :).

Also, do you need to store grabbed opponent twice?
Code:
	setentityvar(self, "target", target); // <--- stores in "target"
			
		if(target == NULL() || getentityproperty(target, "dead") == 1){
			setidle(self);
		}else{
			setentityvar(self, "grabbed", target); // <--- stores in "grabbed"
 
Code:
void grabStart5()
{
   void self 	= getlocalvar("self");
    void target = getentityvar(self,"target");

	if(target == NULL()){
		target = getentityproperty(self, "opponent");

		
		if(target == NULL() || getentityproperty(target, "dead") == 1){
			setidle(self);
		}else{
			setentityvar(self, "grabbed", target);
		}
	}
	
	if(target != NULL()){
		damageentity(target, self, 0, 1, openborconstant("ATK_NORMAL7"));
	}
}

even with

Code:
void clearGrab5()
{
	void self = getlocalvar("self");
	void target = getentityvar(self,"target");
	setentityvar(self, "target", NULL());
}

grabbing works fine but non grabbing grabs I can't figure out the clearing issue

https://www.youtube.com/watch?v=rQ077N8_uIc
 
Hmmm... try this updated animation:
Code:
anim  freespecial2 #walking throw
range 0 24
attackone 1
delay        11
offset        63 104
@cmd      grabStart5
@cmd	position 0 8 10 0 -1
frame        data/chars/kim/t1.png
delay         20
@cmd	position 4 -9 12 0 1
sound	  data/sounds/kim3.wav
frame     data/chars/kim/t2.png
delay     7
@cmd     position 5 -12 23 1 1
frame     data/chars/kim/t3.png
@cmd    position 7 41 6 1 1
frame     data/chars/kim/t4.png
@cmd    depost
@cmd    throw 4 2 2 2 0 0
frame     data/chars/kim/t4.png
frame     data/chars/kim/t5.png
delay      5
@cmd	clearGrab
frame     data/chars/kim/t6.png

and updated functions:
Code:
void grabStart5()
{
   void self 	= getlocalvar("self");
    void target = getentityvar(self, "target" + self);

	if(target == NULL()){
		target = getentityproperty(self, "opponent");
			
		if(target == NULL() || getentityproperty(target, "dead") == 1){
			setidle(self);
		}else{
		  setentityvar(self, "target" + self, target);
		}
	}
	
	if(target != NULL()){
		damageentity(target, self, 0, 1, openborconstant("ATK_NORMAL7"));
}

void clearGrab()
{
   void self = getlocalvar("self");
   setlocalvar("target" + self, NULL());
}
 
does this

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

I've tried everything from storing "opponent" into entityvar/global/local I even tried findtarget because I thought maybe variables might have been continued over from @cmd walkthrow, I've tried clearing and unbinding but nothing,

only if target is destroyed does the engine start a new interaction, currently on grabstart9 hahaha I can show all the different scripts I've tried but didn't wanna post 5 minutes worth of code to read.
 
I guess I can show you which variations I've tried without having to paste too much code.


void grabStart7()
{
  void self  = getlocalvar("self"); 
  void target = getentityvar(self, "target" + self);  //<-------- localvar globalvar entityvar target opponent

if(target == NULL()){
      target = getentityproperty(self, "opponent"); //<-----  target grabbed
      setentityvar(self, "target", target); // <------ grabbed opponent  "target" + self and completely removed to not double store setlocal setglobal
 
    }
if(target == NULL() || getentityproperty(target, "dead") == 1){
setidle(self);
}else{
setentityvar(self, "grabbed", target);  //<---- anything other than grabbed causes instability but also tried all of the above




if(target != NULL())
{
damageentity(target, self, 0, 1, openborconstant("ATK_NORMAL7"));
  }
    }
}


2 days of different combinations
same applies to @cmd grabClear, I even tried moving the location of grabClear inside the throw animation to before grabstart, just after grabstart before/after throw and depost.  Only thing I can think of next is using an attackbox with a knockdown after entity is thrown  :o
 
Code:
void position(int frame, float dx, float dy, float dz, int face)
{//Modify grabbed entity's position relative to grabber
 //Use grabstart 1st before using this
	void self 	= getlocalvar("self");
	void target = getentityvar(self,"grabbed");
	int dead	= getentityproperty(target,"dead");

	if(target == NULL()){
		target = getentityproperty(self, "grabbing");
		setentityvar(self, "grabbed", target);
	}
	
	if(target != NULL()){
		if(dead == 1){ //USED WHEN PLAYER DIES BY TIME OVER AND THE GRABBER IS THE ENEMY
			bindentity(target, NULL());
			damageentity(target, self, 0, 1, openborconstant("ATK_NORMAL"));
			damageentity(self, self, 0, 1, openborconstant("ATK_NORMAL"));
			setentityvar(self, "grabbed", NULL());
		}else{
			updateframe(target, frame);
			bindentity(target, self, dx, dz, dy, face, 0);
		}
	}
}






Code:
void throw(int damage, int type, int Vx, int Vy, int Vz, int face)
{//Damage as throw finisher
	void self 	= getlocalvar("self");
	void target = getentityvar(self,"grabbed");
	int z 		= getentityproperty(self,"z");
	int tDir 	= getentityproperty(target,"direction");
	int vDir;
	
	if(face == 0){ //SAME FACING?
		vDir = tDir;
	}

	if(face == 1){ //OPPOSITE FACING?
		if(tDir == 0){ //FACING LEFT?
			vDir = 1;
		}else{
			vDir = 0;
		}
	}

	if(target == NULL()){
		target = getentityproperty(self, "grabbing");
		setentityvar(self, "grabbed", target);
	}
	
	if(target != NULL()){
		void atkType;
		void projectile;
		void eType = getentityproperty(target,"type"); //Get opponent's type
		int dir    = getentityproperty(target,"direction"); //Get opponent's facing direction

		if(dir == 0){ //FACING LEFT?
			Vx = -Vx;
		}
		
		if(type == 1){
			atkType = openborconstant("ATK_NORMAL8"); //1st Finisher
		}

		if(type == 2){
			atkType = openborconstant("ATK_NORMAL9"); //2nd Finisher
		}
		
		if(z > (openborconstant("PLAYER_MIN_Z")+openborconstant("PLAYER_MAX_Z"))/2){
			Vz = -Vz ;
		}
		
		if(eType == openborconstant("TYPE_PLAYER") || eType == openborconstant("TYPE_NPC")){
			changeentityproperty(target, "projectilehit", "type_player", "type_npc", "type_obstacle");
		}else if(eType == openborconstant("TYPE_ENEMY")){
			changeentityproperty(target, "projectilehit", "type_enemy", "type_obstacle");
		}
		
		damageentity(target, self, 0, 1, atkType);
		changeentityproperty(target, "direction", vDir);
		changeentityproperty(target, "aiflag", "projectile", 1);
		changeentityproperty(target, "damage_on_landing", damage); //RESET PROJECTILE STATUS TO 0 WHEN FALL ON THE GROUND, TOTAL DAMAGE
		tossentity(target, Vy, Vx, Vz); //TOSS OPPONENT
		antiWall();
		setentityvar(self, "grabbed", NULL()); //CLEAR ENTITYVAR
	}
}





Code:
void depost()
{//Release grabbed entity
	void self 	= getlocalvar("self");
	void target = getentityvar(self,"grabbed");

	if(target == NULL()){
		target = getentityproperty(self, "grabbing");
		setentityvar(self, "grabbed", target);
	}
	
	if(target != NULL()){
		bindentity(target, NULL());
	}
}
 
Thank you, so that's the name of variable used by your grab system  :D. Now I know how to use uniform variable name.

Try this updated functions:
Code:
void grabStart5()
{
   void self 	= getlocalvar("self");
    void target = getentityvar(self, "grabbed");

	if(target == NULL()){
		target = getentityproperty(self, "opponent");
			
		if(target == NULL() || getentityproperty(target, "dead") == 1){
			setidle(self);
		}else{
		  setentityvar(self, "grabbed", target);
		}
	}
	
	if(target != NULL()){
		damageentity(target, self, 0, 1, openborconstant("ATK_NORMAL7"));
}

void clearGrab()
{
   void self = getlocalvar("self");
   setentityvar("grabbed", NULL());
}
 
I tried that but it caused a shut down, I even tried carrying findtarget throw all the different scripts, I'll send you mod if you want to have a look and if a solutions found I'll post it back in this thread, I've honestly tried most combinations but it's beyond me. if you do decide to have a look its Kimberly the pink ranger I am trying this out on.
 
Ack, I've just noticed my mistake. It should be like this:
Code:
void clearGrab()
{
   void self = getlocalvar("self");
   setentityvar(self, "grabbed", NULL());
}
 
Back
Top Bottom