Tossentity with Jump

danno

Moderator
Staff member
When using tossentity for jump if jumpkey is held upon landing another jump is performed can someone explain why and how to prevent it, I figure it's something to do with engine counting clicks

So jump using tossentity if key held performs an additional jump via keyscript or entity script
 
Most likely you forgot to verify press vs. release of the key. OpenBOR detects key releases too and fires the keyscrpits on them.

Post up the keyscrpit and I can show you where to add the check.

DC
 
Entity

Code:
anim freespecial #duckwalk jump
 @script
    void self = getlocalvar("self");
    int Dir = getentityproperty(self, "direction");
	
if(Dir==0){
  tossentity(self, 3 , -2, 0);
    }
if(Dir==1){
  tossentity(self, 3 , 2, 0);
    }
@end_script
loop      0
delay     300
offset    55 95
bbox      39 43 26 28
landframe 1
frame     data/chars/ninjaj2.gif
offset    55 95
bbox      37 67 26 28
delay     6
frame     data/chars/ninja/d1.gif

Or keyscript


Code:
  if(vAniID == openborconstant("ANI_FOLLOW1") ){ //Duck walk
      if(iJump){ //Jump pressed?
        changeentityproperty(vSelf, "animation", openborconstant("ANI_FREESPECIAL"));
        if(iLeftH){ //Left held?
          changeentityproperty(vSelf, "direction", 0);
          tossentity(vSelf, 3, -2, 0);
        } else if(iRightH){ //Right held?
          changeentityproperty(vSelf, "direction", 1);
          tossentity(vSelf, 3, 2, 0);
        } else { //Nothing
          tossentity(vSelf, 3, 0, 0);
        }
      }    
    }
 
I hate using magic numbers, but try replacing (iJump) with (iJump == 1).

I'm on a phone, but IIRC 1 is for press and 2 is release. Currently, you are evaluating any non false, so it's triggering on both press and release.

DC
 
Damon Caskey

Code:
void main()
{
    int iPlIndex = getlocalvar("player"); //Get calling player
    void vSelf = getplayerproperty(iPlIndex , "entity"); //Get calling entity
    void vAniID = getentityproperty(vSelf,"animationID"); //Get current animation ID
    void vAniPos = getentityproperty(vSelf, "animpos"); //Get current animation frame
    int iDir = getentityproperty(vSelf, "direction");  //Get current facing direction
    int MPower = getentityproperty(vSelf,"mp");
    void vName = getentityproperty(vSelf,"name"); //Get name of calling entity
    
    void iUp = playerkeys(iPlIndex, 1, "moveup"); // New key status of "Up"
    void iDown = playerkeys(iPlIndex, 1, "movedown"); // New key status of "Down"
    void iLeft = playerkeys(iPlIndex, 1, "moveleft"); // New key status of "Left"
    void iRight = playerkeys(iPlIndex, 1, "moveright"); // New key status of "Right"
    void iJump = playerkeys(iPlIndex, 1, "jump"); //New key status of "Jump"
    void iSpecial = playerkeys(iPlIndex, 1, "Special"); //New key status of "Special"
    void iAttack = playerkeys(iPlIndex, 1, "attack"); //New key status of "Attack"
    void iAttack2 = playerkeys(iPlIndex, 1, "attack2"); // New key of "Attack 2"
    void iAttack3 = playerkeys(iPlIndex, 1, "attack3"); // New key of "Attack 3"
    void iAttack4 = playerkeys(iPlIndex, 1, "attack4"); // New key of "Attack 4"


    void iUpR = playerkeys(iPlIndex, 2, "moveup"); // Release status of "UP"
    void iLeftR = playerkeys(iPlIndex, 2, "moveleft"); // Release status of "Left"
    void iRightR = playerkeys(iPlIndex, 2, "moveright"); // Release status of "Right"
    void iDownR = playerkeys(iPlIndex, 2, "movedown"); //Release status of "Down"
    void iAttackR = playerkeys(iPlIndex, 2, "attack"); //Release status of "Attack"
    void iAttack2R = playerkeys(iPlIndex, 2, "attack2"); //Release status of "Attack"

    void iUpH = playerkeys(iPlIndex, 0, "moveup");
    void iDownH = playerkeys(iPlIndex, 0, "movedown");
    void iLeftH = playerkeys(iPlIndex, 0, "moveleft");
    void iRightH = playerkeys(iPlIndex, 0, "moveright");
    void iAttackH = playerkeys(iPlIndex, 0, "attack");
    void iAttack2H = playerkeys(iPlIndex, 0, "attack2");





//Double jump
    if(vAniID == openborconstant("ANI_JUMP") ){ //Jumping 
      if(iJump ==  1){ //Jump pressed?
        changeentityproperty(vSelf, "animation", openborconstant("ANI_FOLLOW1"));
        if(iLeftH){ //Left held?
          changeentityproperty(vSelf, "direction", 0);
          tossentity(vSelf, 3, -2, 0);
        } else if(iRightH){ //Right held?
          changeentityproperty(vSelf, "direction", 1);
          tossentity(vSelf, 3, 2, 0);
        } else { //Nothing
          tossentity(vSelf, 3, 0, 0);
        }
      }    
    }
}

This is for double jump, same problem though
 
danno said:
When using tossentity for jump if jumpkey is held upon landing another jump is performed can someone explain why and how to prevent it, I figure it's something to do with engine counting clicks

So jump using tossentity if key held performs an additional jump via keyscript or entity script

Hi danno
I have the same issue but I think it is not a script problem, because if you perform a normal jump and hold the jump button before the character lands, he will do another jump, same as any scripted jump using tossentity.

I'm trying to avoid it too, I will share here if have any progress
 
Hey Kratus, I have a work around using jumpframe but just wondering why this happens and if it can be fixed because it happens in all script not just keyscript
 
danno said:
Hey Kratus, I have a work around using jumpframe but just wondering why this happens and if it can be fixed because it happens in all script not just keyscript

Maybe I found a way to avoid this issue. You will need an animation script (@cmd) and a keyscript event.
Basically, these two scripts will work in "jumpdelay" animation. The keyscript will register the time for button held/pressed and the animation script will check if the desired delay will be enough or not to perform a "jump".

If the delay is not enough to make a jump, the script will reset the character to idle status, otherwise a normal jump will be performed.

Here's the keyscript, simply add it to your keyscript.c file and call it in a "void main" function.
Code:
void keyDelay()
{//Activate delay counter when a defined key is held for further use
	void self 	= getlocalvar("self");
	void key	= "jump"; //THIS IS THE DESIRED KEY THAT THE SCRIPT WILL WORK ON
	int iPIndex = getentityproperty(self, "playerindex");
	float delay	= 20; //THIS IS THE MAXIMUM DESIRED DELAY TO DEFINE IF A BUTTON IS HELD OR SINGLE PRESSED
	
	if(playerkeys(iPIndex, 0, key)){ //DEFINED KEY IS HELD??
		setglobalvar("keyDelay"+self, openborvariant("elapsed_time")+delay); //START DELAY COUNTER AND SAVE IN A VARIABLE
	}
}

And here's the animation script, add it to your main animation.c file and call it in the entity jumpdelay animation:
Code:
void keyDelay(void key)
{//Used together with keyscript version of the keyDelay, calculate delay to lock or perform the current animation
	void self 	= getlocalvar("self");
	int iPIndex = getentityproperty(self, "playerindex");
	
	//PS: IF ELAPSED_TIME+DELAY IS HIGHER THAN CURRENT TIME, CONSIDER A SINGLE PRESS
	//PS: IF ELAPSED_TIME+DELAY IS LOWER THAN CURRENT TIME, CONSIDER A HELD KEY

	if(playerkeys(iPIndex, 0, key)){ //DEFINED KEY IS HELD??
		if(getglobalvar("keyDelay"+self) < openborvariant("elapsed_time")){ //GET SAVED DELAY AND CALCULATE ACCORDING TO CURRENT TIME
			setidle(self, 0); //RESET CHARACTER STATUS TO IDLE IF CURRENT TIME IS HIGHER THAN THE DELAY LIMIT
		}
	}
}

This is how your jumpdelay will be, need to add it to the first frame:
anim jumpdelay
loop 0
delay 12
offset 157 180
bbox 131 126 44 56
@cmd keyDelay "jump"
frame data/chars/bosses/yamato/jumpdelay00.gif

You can change the delay value as you want or add other conditions before any function runs on both scripts, is up to you.
Please, let me know if worked
 
danno said:
Kratus I tried your method but it doesn't work with tossentity  :'(
Strange danno, I tested it in Yamato character, that has tossentity, and worked.
In fact the way the character jumps doesn't matter because it works in jumpdelay animation.
Can I check your codes?
 
I can see the problem here:

Code:
anim freespecial #duckwalk jump
 @script
    void self = getlocalvar("self");
    int Dir = getentityproperty(self, "direction");
	
if(Dir==0){
  tossentity(self, 3 , -2, 0);
    }
if(Dir==1){
  tossentity(self, 3 , 2, 0);
    }
@end_script
loop      0
delay     300
offset    55 95
bbox      39 43 26 28
landframe 1
frame     data/chars/ninjaj2.gif
offset    55 95
bbox      37 67 26 28
delay     6
frame     data/chars/ninja/d1.gif

This animation script doesn't have frame check, therefore the jump or tossentity will occur in all frames of animation

Try this:
Code:
anim freespecial #duckwalk jump
@script
  if(frame==0){
    void self = getlocalvar("self");
    int Dir = getentityproperty(self, "direction");
	
    if(Dir==0){
      tossentity(self, 3 , -2, 0);
    } else {
      tossentity(self, 3 , 2, 0);
    }
  }
@end_script
delay     300
offset    55 95
bbox      39 43 26 28
landframe 1
frame     data/chars/ninjaj2.gif
bbox      37 67 26 28
delay     6
frame     data/chars/ninja/d1.gif
 
Frame check I forgot about that, thanks Bloodbane that works inside entity,

Kratus method works too inside keyscript, my mistake was not adding keydelay into void main like so

Code:
void main()
{
    keyDelay();
	
	int iPlIndex = getlocalvar("player"); //Get calling player
    void vSelf = getplayerproperty(iPlIndex , "entity"); //Get calling entity
    void vAniID = getentityproperty(vSelf,"animationID"); //Get current animation ID
    void vAniPos = getentityproperty(vSelf, "animpos"); //Get current animation frame
    int iDir = getentityproperty(vSelf, "direction");  //Get current facing direction
    int MPower = getentityproperty(vSelf,"mp");
    void vName = getentityproperty(vSelf,"name"); //Get name of calling entity
   
    void iUp = playerkeys(iPlIndex, 1, "moveup"); // New key status of "Up"
    void iDown = playerkeys(iPlIndex, 1, "movedown"); // New key status of "Down"
    void iLeft = playerkeys(iPlIndex, 1, "moveleft"); // New key status of "Left"
    void iRight = playerkeys(iPlIndex, 1, "moveright"); // New key status of "Right"
    void iJump = playerkeys(iPlIndex, 1, "jump"); //New key status of "Jump"
    void iSpecial = playerkeys(iPlIndex, 1, "Special"); //New key status of "Special"
    void iAttack = playerkeys(iPlIndex, 1, "attack"); //New key status of "Attack"
    void iAttack2 = playerkeys(iPlIndex, 1, "attack2"); // New key of "Attack 2"
    void iAttack3 = playerkeys(iPlIndex, 1, "attack3"); // New key of "Attack 3"
    void iAttack4 = playerkeys(iPlIndex, 1, "attack4"); // New key of "Attack 4"



 
The thing with keyscripts is they work on every tick, but when you put some key input reading in animations then they work/update per delay value, so when you have delay of  5 then youre losing like 4 button presses, when you put delay 2 then you lose every seconnd press, when delay 1 then its kinda like if you put it in keyscript that runs on every tick.I tested that using textobject and varialbe that updates on every button press, i could get identical result using delay1 without keyscript.c
But with delay1 you need long animations, many frames...
 
Thanks for the explanation bWWd, I figured it was something to do with ticks n' clicks just didn't know how to get past it as it also happens in other script unless frame checked so I thought it might be a bug with toss entity itself
 
Back
Top Bottom