how to cancel a running timer? [SOLVED]

Started by Caracal, Wed 25/07/2012 08:40:35

Previous topic - Next topic

Caracal

I have the following problem:
I would like the player to press the bell of a house. After about 5 seconds a which opens the door and enchants the player. Only if the player hides behind a flowerpot the which will not find him. For this I have set up the following:
Code: AGS

function hDoorbell_Interact()
{
cBellatrix.LockViewFrame(3, 2, 1);
Wait(80);
cBellatrix.UnlockView();
SetTimer(1, 220);
isBell = true;
  if  ( false && BellaHidden == false && IsTimerExpired(1)) {
Death Scene occurs
}
}

This is basically what happens when the doorbell is rung. I used the bool “Bella Hidden” to check if the player is behind the flower pot or not.
If the player does not go behind the pot, and just waits until the timer expires I have set up this:
Code: AGS

function room_RepExec()
{
if (IsTimerExpired(1)){ 
Death Scene occurs
}
}

But if the player does click on the big flower pot just in time then the player hides and the following appears:
Code: AGS

function hTopf_Interact()
{
if (isBell == false){
cBellatrix.Walk(195, 484, eBlock, eWalkableAreas);
cBellatrix.Say("There is a big Flowerpot.");
}
else if (isBell == true){
cBellatrix.Walk(98, 508, eBlock, eWalkableAreas);
cBellatrix.LockViewFrame(3, 2, 0);
Wait(90);
Death Scene occurs
isBell = false;
  }
}

Now thats all pretty simple i think. The reason why I am telling this is that once the player hides behind the flowerpot basically
function Topf_Interact
else if (is Bell == true)
and after the death scene occurred. The scene which happens within function rep.ececute (  if  ( false && BellaHidden == false && IsTimerExpired(1))) also occurs right afterwards.
So the “rep execute” function happens in any way.

I was thinking that this problem might be solved if I turn the first timer off while it is running, in case the player hides behind the flowerpot. But how do I turn a timer off?

Khris

You can't really do it that way.

First of all, in hDoorbell_Interact Bellatrix doesn't walk to the hotspot first, while in hTopf_Interact she does. Not sure how your game is set up, but one of those must be wrong, right?
Now, further down in hDoorbell_Interact you're testing a condition. That won't work in the way you think because this condition is tested exactly once, and it's tested immediately after you've started the timer. So disregarding the false, the condition won't ever be fulfilled anyway.

What you need to do:
-Interacting with the doorbell starts a timer and sets a variable (isBell) to true, IF isBell is false. Otherwise we get "I just pressed the doorbell."
-Interacting with the flower pot: IF isBell: hide, else look at it
-rep_ex: if TimerExpired
                   if (hidden) stuff happens
                   else death scene happens

Also, and I can't stress this enough: INDENTATION!

Caracal

I sometimes use the „walk to hotspot“ function in the room editor. But sometimes I simply forget about that and put the coordinates into the roomscript that’s why there is a difference.
Anyhow.
The ting is that I want the Timer to stop right after the player hides behind the flowerpot. Since it is not possible to determine the exact time of when the player does that I simply trigger a cutscene right after Bella is hitten == ture. But the disadvantage is that after the death screen is left… the scene which follows after the timer, will also occur. The player dies twice for one and the same thing.
(actually in my room script it is a bit more difficult I have 3 bools concerning this, since there is a 3rd character that is involved. So in the end the timer has to stop when isBell == true, BellaHidden == true, Witnessisblind == true, or something like this)

Khris

You can always use your own timer. Just set a room variable, decrease it in room_RepExec and check its value. Assuming the event is triggered as soon as the variable reaches 0, to turn off the timer, set it to -1.
A better way of course is to set it to 1 when Bella hides behind the pot, so the cutscene is started in the next game loop.
Code: ags
// room script
int doorbell_timer = -1;

// instead of SetTimer
  doorbell_timer = 220;

// in room_RepExec
  if (doorbell_timer > 0) doorbell_timer--;
  if (doorbell_timer == 0) {
    ...
  }


Btw, you didn't have the entire cutscene code twice in your room script, did you?

Caracal

Well now it works just fine!!!
And... jes... i had the cutscenecode twice. Once for each possibility. But i removed it and the problem was solved.
Thank you very much! 
But still i am having difficultys with the "respawn" after exiting the "death-message room" the character does not return into the previous room, even though the room is shown.

Khris

#5
Quote from: Caracal on Fri 27/07/2012 22:05:22And... jes... i had the cutscenecode twice.
Even if my method hadn't made it obsolete, you wouldn't have had to write down the exact same code twice. Just put it inside a function and call that twice:
Code: ags
function death_scene() {
  ...
  ...
}

// in the appropriate place(s)
  death_scene();

Even if the code is merely similar you can do the same thing, just add one or two parameters for the differences in that case. A cornerstone of good programming is getting rid of duplicate code.

Regarding the respawning, if the room is shown, the character is there, too. They might be outside the screen, transparent, behind a walkable area or use an empty sprite, but they must be there because the current room is always the one the player character currently is in.
If debug mode is enabled, test the game and hit Ctrl-D to get an overview of all the characters within the current room.

Caracal

Quote from: Khris on Sat 28/07/2012 00:50:27
Regarding the respawning, if the room is shown, the character is there, too. They might be outside the screen, transparent, behind a walkable area or use an empty sprite, but they must be there because the current room is always the one the player character currently is in.
If debug mode is enabled, test the game and hit Ctrl-D to get an overview of all the characters within the current room.

Well its true, the player is there (logically as you say) but... somewhere totally off space. On a position in the room which is out of any sight (280, 0 or something) which is odd. Even if i interact with other characters in the screen, the dialog will be properly triggered just that i cant walk around and that my playercharacter is not there.

Khris

Well, what are the parameters of the player.ChangeRoom() command?

Caracal

Thats the function for the "Try again Button":
Code: AGS

function btnDeathButton_OnClick(GUIControl *control, MouseButton button)
{
    gInventory.Visible=true;
    gDeathMessage.Visible = false;
    player.Loop = player_loop;
    player.ChangeRoom(player_Room, player_x, player_y);
}

I have created global variables with the name "plaer_loop" "player_Room" "player_x" "player_y". Actually... everything as it should be. I thought.

Khris

So you're setting all these variables at the start of the function that leads to the player's death, right?
Because if you forget to set player_y, it remains 0 and thus the character will be placed at (X, 0), outside the visible area.

Caracal

Quote from: Khris on Sun 29/07/2012 17:16:58
So you're setting all these variables at the start of the function that leads to the player's death, right?
Because if you forget to set player_y, it remains 0 and thus the character will be placed at (X, 0), outside the visible area.

That sounds like this might be what happens. I dont set the these variables properly. But how do i do it? Last time i just created the global variables and it worked macikally.

Khris

There's no magic involved; the variables are simply set before the death scene. I remember posting the code but I'm too lazy to search the thread right now.

The logic is this:

// deadly interaction
1. save player's position, direction and room
2. walk player into doom
3. show death GUI
4. if "undo" is selected, restore player to state saved in point 1.

Try to find 1. in your code and post it. It's probably a custom function call.

Caracal

The only function i have imported (custom made) is this:
Code: AGS
enum CauseOfDeath {
    eDeathTree, 
    eDeathSwamp
};

import function ShowgDeathGui(CauseOfDeath cod);

import function ShowDeathGUI(CauseOfDeath cod);     
String death_message[100];                        //Death message text
int death_picture[100];                           //Death message image

But this is actually only concerning the image and the text of a death scene which is obsolet for the current game as the player is just going to hear a diffrent voicefile...

But then i might have this here:
Code: AGS
function on_mouse_click(MouseButton button) {
  // called when a mouse button is clicked. button is either LEFT or RIGHT
  if (IsGamePaused() == 1) {
    // Game is paused, so do nothing (ie. don't allow mouse click)
  }
  else if (button == eMouseLeft) {
    ProcessClick(mouse.x, mouse.y, mouse.Mode );
    player_loop = player.Loop;
    player_x = player.x; player_y = player_y;
    player_Room = player.Room;
  }
  else if (button == eMouseRight || button == eMouseWheelSouth){
    // right-click our mouse-wheel down, so cycle cursor
   mouse.SelectNextMode();                                                                     
  }
  else if (button == eMouseMiddle) { 
    // Middle-button-click, default make character walk to clicked area (a little shortcut)
    // Could have been just "player.Walk(mouse.x,mouse.y)", but it's best to
    // leave our options open - what if you have a special script triggered
    // on "walking" mode?
    ProcessClick(mouse.x, mouse.y, eModeWalkto); 
  }
  else if (button == eMouseWheelNorth) { 
    // Mouse-wheel up, cycle cursors 
    // If mode isn't WALK, set the previous mode (notice usage of numbers instead
    // of eNums, when it suits us)...
    if (mouse.Mode>0) mouse.Mode=mouse.Mode-1; 
    else 
    { 
      // ...but if it is WALK mode...
      if (player.ActiveInventory!=null) 
      {
        //...and the player has a selected inventory item, set mouse mode to UseInv. 
        mouse.Mode=eModeUseinv; 
      }
      else 
      {
        // If they don't, however, just set it to mode TALK (change this line if you add more cursor modes)
        mouse.Mode=eModeTalkto; 
      }
    }
  }

The first lines are what i thought important. I thought this would be enough to save the position of the player. But oubviously its not sufficient enought.


Khris

There's a typo in there:

player_y = player_y;

is of course supposed to be:

player_y = player.y;

Caracal

Quote from: Khris on Wed 01/08/2012 01:41:32
There's a typo in there:

player_y = player_y;

is of course supposed to be:

player_y = player.y;

THATS IT!
Let me call you this: Genious! ;-P
Thank you so mutch, i just dont know how to thank you!
Sutch a tiny mistake i would have never noticed. But now everything works perfect. Now i am so close to create a totally new KingsQuest 7 like game!
Thank you Khris!

Khris

No problem.
It's actually my fault anyway, I corrected the typo back then but didn't mention it later in the thread.
http://www.adventuregamestudio.co.uk/yabb/index.php?topic=45643.msg612779#msg612779

SMF spam blocked by CleanTalk