Solved Button hold detection

Question that is answered or resolved.

O Ilusionista

Captain 100K
Hi everyone, long time no see. I haven't touched scripting for ages, so I get a bit rusty.

I would like to know what would be the best option for detecting if a specific button is held in a specific frame.
For example, if I have an animation with 3 frames (in loop) and I want to detect if a specific button is being held in frame 3, what would be the best option?

I would like to not rely on keyscript. Instead, I would prefer something more "modular", like a function called directly in the animation (those functions we call with "@cmd".

Any ideas?
 
Hi O',

If you want a solution bundled with a full-fledged system : http://www.chronocrash.com/forum/index.php?topic=2466.msg37022#msg37022

If you only want a stand-alone version, tell me and I'll give you an example.
 
I would like to know what would be the best option for detecting if a specific button is held in a specific frame.

Glad you asked for held state cause that state can be detected with animation script.
This variable:

Code:
iRKey = playerkeys(iPIndex, 0, "attack");

will be true if attack button is held when this function is ran. iPIndex defines which player who should be holding the attack button you want to detect

I would like to not rely on keyscript...

Well, if you want to detect hold or not holding state of a key, animation script is sufficient but if you want to detect press or release state of a key, you need keyscript
 
Here's my stand-alone function :

Code:
/*
 * If button (coded by keyCond) is maintained from first call to endFrame call, switch to startFrame of animation vAni
 */
void aniHoldSwitch(char vAni, char keyCond, int endFrame, int startFrame){
	
	void vEnt = getlocalvar("self");
	int iIndex = getentityproperty(vEnt, "playerindex");
	int vHolding = getlocalvar(vEnt + ".holding." + iIndex);
	int currentFrame = getlocalvar("frame");
	int debug = 0;
	
	if(startFrame == NULL()) startFrame = 0;
	
	if(currentFrame == 0) vHolding = NULL();
	
	if(currentFrame <= endFrame){
	
		if(vHolding == NULL()){ // First frame
			if(debug) log("\n********** START HOLDING TEST (ani = " + getentityproperty(vEnt, "animationID") + ") **********");
			//if(playerkeys(iIndex, 0, keyCond)) log("\nHolding on first frame");
			//if(playerkeys(iIndex, 1, keyCond)) log("\nPush on first frame");
			if(playerkeys(iIndex, 0, keyCond) && ! playerkeys(iIndex, 2, keyCond)) vHolding = 1;
			else vHolding = 0;
			setlocalvar(vEnt + ".holding." + iIndex, vHolding);
		} else if(vHolding == 1){ // Still valid, still possible, test further
			if(!playerkeys(iIndex, 0, keyCond) || playerkeys(iIndex, 2, keyCond)){ // Not holding or, Released = Screwed
				vHolding = 2;
				setlocalvar(vEnt + ".holding." + iIndex, vHolding);
			}
		}
		
		if(debug){
			log("\n- Frame " + currentFrame);
			log("\n	Push = " + playerkeys(iIndex, 1, keyCond));
			log("\n	Hold = " + playerkeys(iIndex, 0, keyCond));
			log("\n	Release = " + playerkeys(iIndex, 2, keyCond));
		}
			
		if(debug && playerkeys(iIndex, 2, keyCond)) log("\nReleased on frame " + currentFrame);
		if(currentFrame == endFrame){
			setlocalvar(vEnt + ".holding." + iIndex, NULL());
			
			if(debug) log("\nVAR CLEARED\n");
			if(vHolding == 1){
				if(startFrame != 0) setlocalvar("startFrame", startFrame);
				changeentityproperty(vEnt, "animation", openborconstant(vAni));
			}
		}
	}
	
}

Should be available in animationscript. Usage in entity model file  :

Code:
anim attack1 # Light Punch
	@script
		aniHoldSwitch("ANI_follow4", "attack", 4, 0);
	@end_script
	delay 4
	offset 54 87
	frame data/chars/oro/841.gif
	frame data/chars/oro/842.gif
	frame data/chars/oro/843.gif
	frame data/chars/oro/844.gif
	frame data/chars/oro/845.gif
	frame data/chars/oro/846.gif

If "attack" key is pressed from frame 0 to frame 4, then on frame 4 entity will play follow4 animation.
 
Thanks Piccolo. But how I do the opposite? I want to check, for example, if at frame 4 the attack1 button is not being held. If is being held, does nothing. But if is hot beeing held, then play X anim. Its doable with that code?
 
For this purpose you'd rather use this one :

Code:
void aniNHoldSwitch(char vAni, char keyCond){
	void vEnt = getlocalvar("self");
	int iIndex = getentityproperty(vEnt, "playerindex");
	
	if(keyCond == "back"){ // DEPRECATED use "forward" and "backward" instead (already coded in engine)
		if(keyCond == "back" && !((getentityproperty(vEnt, "direction") == 0 && (playerkeys(iIndex, 0, "moveright")))
			|| (getentityproperty(vEnt, "direction") == 1 && (playerkeys(iIndex, 0, "moveleft"))))
		){
				changeentityproperty(vEnt, "animation", openborconstant(vAni));
		}
	}
	
	     
	
	else if(! (playerkeys(iIndex, 0, keyCond) && ! playerkeys(iIndex, 2, keyCond))){
		changeentityproperty(vEnt, "animation", openborconstant(vAni));
	}
}


Usage example :

Code:
anim attack4 # Strong Direct
	loop 1
	delay 4
	offset 130 126
	frame data/chars/sasquatch/365.gif
	@cmd aniNHoldSwitch "ANI_follow2" "back"
	offset 128 126
	frame data/chars/sasquatch/366.gif
	offset 125 101
	frame data/chars/sasquatch/367.gif

The animation will loop (loop 1) if "back" key is held on second frame. If back key is not held on second frame, it will play follow2.
 
Piccolo, I tried to change to the button I use (A2) but no luck - the player gets automatically to the follow animation:

@cmd aniNHoldSwitch "ANI_FOLLOW16" "A2"

What do I need to change to work with A2 button?

Nevermind, I got it. I just changed this part:

Code:
if(keyCond == "A2"){ // DEPRECATED use "forward" and "backward" instead (already coded in engine)
		if(keyCond == "A2" && !(((playerkeys(iIndex, 0, "attack2")))
			)
		){
				changeentityproperty(vEnt, "animation", openborconstant(vAni));
		}
	}
 
Back
Top Bottom