I was wondering if there is a way to execute commands based on whether the player types a specific word within a specific timeframe?
The way I envision it, it ought to be something like this:
If the player types 'P', then a timer is set off, say, 1 second; if the player within that timelimit preceeds to type 'U', then the timer starts again, and so on until the player has typed "PUNCH" without any timers expiring, in which case the character will successfully punch another character. If the player types 'P' and the timer expires the character will produce an unsuccessful punch and be punished, and the same should happen if he doesn't spell right.
I tried to do this in the global script in the on_key_press-section, but the game seems to ignore the conditionals.
Keep in mind that I'm a complete noob, so I might have overlooked something really simple.
Do you have a TextBox on screen (i.e. to show what's been typed so far)? If so, on_key_press isn't run for some keypresses (See Manual). Also,what acsii codes are you using in on_key_press? AFAIK, letterkeys are always passed as uppercase (codes 65-90).
Otherwise:
What exactly do you have in on_key_press so far?
Something like this should work:
(at top of Global script:)
string buffer;
(in 'on_key_press:)
if (keycode >=65 && keycode <= 90) {
SetTimer(1, 20); // About 1/2 a second
StrFormat (buffer, "%s%c", buffer, keycode);
lblTest.SetText(buffer);
}
(in 'repeatedly_exectute':)
if (IsTimerExpired(1)) {
if (StrCaseComp("PUNCH", buffer)==0) {
Display ("Bam! Right between the eyes!");
// Or whatever you want to happen.
}
else {
Display ("Missed!");
// Or whatever
}
StrFormat(buffer, "");
lblTest.SetText(buffer);
}
NOTE: Uses a label (lblTest) in place of a TextBox. Rename this as needed, or delete those lines if you dont want the player to see what they've typed.
NOTE 2: This waits for the timer to have expired, before running the hit/miss reponse. If you want it to happen as soon as the word is typed correctly, you could jiggle some of the code into on_key_press.
Now, obviously that's very basic and a bit crap, since I'm not sure exactly what you're aiming for. It's a start, but you'll need to consider exactly how you want it to work (e.g. is this the main control method, or just for a few 'action' scenes? Should there be different responses for, say, 'PUNCH', 'KICK' and 'SLAP', or just a single 'you hit the bad guy' response?).
Thanks for your help! However, AGS objects to the undefined symbol 'buffer'. I feel stupid.
I also just tried to write it by juggling integers. In the keypress-section I wrote
if (keypress ==80){
SetGlobalInt(205,1)
if ((keypress == 85) && (GetGlobalInt(205) == 1)){
SetGlobalInt(206, 1);
}
And so on. This way I hoped to produce a mechanic that follows something like a "canned string"-logic, so that typing "P" opens up a window of opportunity to type "U" (otherwise typing "U" will do either nothing or produce a miss), which in turn produces a window of opportunity for typing "N", then "C", then "H".
and in the repeatedly_execute-thingy:
if (GetGlobalInt(205) == 1){
SetTimer(1, 40);
if ((IsTimerExpired(1) == 1) && (GetGlobalInt(206)==0){
character[EGO].Animate(5,0)//(run miss-animation)
}
if ((IsTimerExpired(1) == 1) && (GetGlobalInt(206)==1)){
character[EGO].Animate(6,0)//(run hit-animation)
}
Or something like that (I don't remember exactly what I wrote and I erased it when it wouldn't work). But I think I might have misunderstood either the timer-function or the SetGlobalInt-function, because this way it was possible to produce a hit by typing PUNCH, but it wouldn't run a miss-animation if I typed "PV" or typed very slowly.
But even if this were to work, it's still not quite what I want, because I want to create the possibility of stringing certain moves together, so that typing "PUNCH" will produce a punch, "PUNCHPUNCH" will produce a two-hit combo, while "PUNCHPUN" produces a miss. I also want to be able to have an extended timeframe if the player keeps typing after having successfully typed "PUNCH".
QuoteAGS objects to the undefined symbol 'buffer'
This probably means you've missed the
string buffer; line, or put it inside another function. Make sure it's right at the top of the global script, and that there isn't a second one somewhere. (If you already use 'buffer' as a string name somewhere, change it to something else). It could also be that you've declared it in the global script and are trying to access it in the room script (or the other way around). You might be better using a GlobalString.
However, looking at what you've done yourself, you can probably just ignore the string altogether -
ints may be the easier way.
Try this (I've also added a 'Kick' command, at no extra cost. If you don't want it, remove to relevant lines):
on_key_press:
SetTimer (1,40);
if (keycode == 80 && GetGlobalInt(205) == 0) SetGlobalInt (205, 1); // 'P'
else if (keycode == 85 && GetGlobalInt (205) == 1) SetGlobalInt (205,2); //'U'
else if (keycode == 78 && GetGlobalInt (205) == 2) SetGlobalInt (205,3); // 'N'
else if (keycode == 67 && GetGlobalInt (205) == 3) SetGlobalInt (205,4); // 'C'
else if (keycode == 72 && GetGlobalInt (205) == 4) {
SetGlobalInt (205,5); // 'H'
SetTimer(1,1);
}
else if (keycode == 'K') {
if (GetGlobalInt(205) == 0) SetGlobalInt (205, 1);
else if (GetGlobalInt (205) == 3) {
SetGlobalInt (205,4);
SetTimer(1,1);
}
}
else if (keycode == 'I' && GetGlobalInt(205) == 1) setGlobalInt (205, 2);
else if (keycode == 'C' && GetGlobalInt(205) == 2) setGlobalInt (205, 3);
else SetGlobalInt (205,-1); // If they make a mistake
repeatedly_execute:
if (IsTimerExpired (1)) {
if (GetGlobalInt (205) == 5) {
character[EGO].Animate(6,0);//(run hit-animation)
}
else if (GetGlobalInt(205) == 4) Display("Kick"); // Or run a kick-animation
else if (GetGlobalInt (205) == -1) {
character[EGO].Animate(5,0);//(run miss-animation)
}
SetGlobalInt (205,0);
}
The combo idea may still be a bit tricky, though. Perhaps use another GlobalInt/Timer check?
Thanks a million, that worked perfectly! I'll figure something out for the combos.
Right, I'm still having a bit of a problem with those timers. I want a defense-function which allows the player to type "BLOCK" to block all attacks within a set time limit.
I've written in "Repeatedly execute" for the room:
if (GetGlobalInt(210)==1){
if (GetGlobalInt(207) == 0) {
SetTimer(3, 60);
}
else if (GetGlobalInt(207) == 1) {
SetTimer(3, 100);
}
else if (GetGlobalInt(207) == 2) {
SetTimer(3, 180);
}
}
if (IsTimerExpired(3)) {
SetGlobalInt(210,0);
}
GlobalInt 210 is set to 1 by typing "Block" within the time-limit. I have conditionals for actions based on whether 210 is set to 1 or 0. ( 207 is the player's defense-powers, so that a block will last longer if the Global Int is increased.)
My character will block all attacks when I type Block, but the block isn't disabled after a while: I'm just blocking all attacks for the rest of the fight, and that was hardly the point!
You're setting timer 3 in rep_ex, so it keeps getting reset - never expiring, never removing the block.
You need to use another GlobalInt, to check if the timer has been set:
if (GetGlobalInt(210)==1 && GetGlobalInt (211) == 0){
if (GetGlobalInt(207) == 0) {
SetTimer(3, 60);
}
else if (GetGlobalInt(207) == 1) {
SetTimer(3, 100);
}
else if (GetGlobalInt(207) == 2) {
SetTimer(3, 180);
}
SetGlobalInt (211,1);
}
if (IsTimerExpired(3)) {
SetGlobalInt(210,0);
SetGlobalInt (211, 0);
}
Alternatively, if you want to keep the number of GIs used down, you could change GI210 when you set the timer. I'd guess you have a check somewhere for 'if GI210 == 1, don't allow hits' - if so, you'd also need to change that (if you went with changing GI210, instead of an extra Int).
Also, with all the ints you seem to be using, you might want to declare your own, instead of using GlobalInts. For one thing, they're unlimited, for another you can set their names, amking them easier to track (if (block == 1), for example, instead of if (GetGlobalInt(210) == 1)).
Total side note - I'm intrigued, are you making a beat-'em-up, or is this just for fight scenes within a game?
Works like a charm. I don't quite understand why it works now, so I still feel a bit shaky when it comes to grasping the logic of the timer, but the penny will probably drop soon. Thanks once again, I really appreciate it!
"Total side note - I'm intrigued, are you making a beat-'em-up, or is this just for fight scenes within a game?"
It's supposed to be a puzzle-driven adventure game with fight-sequences, but since it's my first crack at making a game I realise I might have to scale down the ambitions.