Using DoOnceOnly twice in Repeatedly Execute?

Started by TheVolumeRemote, Mon 15/03/2021 05:51:34

Previous topic - Next topic

TheVolumeRemote

Hello! Is It possible to use Game.DoOnceOnly more than once in Repeatedly Execute? I could not figure out what I was doing wrong with the script below, there was a (Global) variable check and when it was correct, nothing happened. So eventually I removed the latter DoOnceOnly and made a variable for it instead and now everything works.

But I'm not certain that was the root of what fixed it. To elaborate, when testing it, if I set the game up to execute the first command (the first DoOnceOnly below), first- then everything worked. However if I approached the game play to where the game executes the second instance of DoOnceOnly first, then it would not work, the character wouldn't speak etc.

To summarize if my problem is not related to DoOnceOnly, I am a bit lost. I've tried a few things like making the second command an If statement instead of Else If, playing around with variations of the same basic command for checking inventory, making a variable for when the player takes the inventory item I need to check and checking the variable both with and instead of the inventory item and finally I can't use Room First Load because this needs to take place after the first visit.

Anyway I had said up top I found a work around for this, and I did however I have swappable player characters and sometimes they split up so I'm going to need figure out why this isn't working for the near future :) thank you for any advice!

Room Script
Code: ags
function room_RepExec()
{
    if (player == cEgo1 && Game.DoOnceOnly("Split Up"))
  {
    Wait(20);
    cEgo2.Say("Words.");
    cEgo1.SetAsPlayer();
    cEgo2.ChangeRoom(20, 90, 150, eDirectionLeft);
  }  
   else if (player == cEgo2 && Game.DoOnceOnly("Gave Hat") && player.HasInventory(iHatGlow) == true)
  {
    cEgo2.Say("Words.");
    cEgo1.SetAsPlayer();
    Hathandoff = true;
  }
}

morganw

I don't think it makes sense to have the checks in this order:
Code: ags
player == cEgo2 && Game.DoOnceOnly("Gave Hat") && player.HasInventory(iHatGlow) == true

...because the DoOnceOnly will run regardless of whether you have the hat or not.

To fix it you can move the DoOnceOnly later in the expression, so that it isn't run if you don't have the hat:
Code: ags
player == cEgo2 && player.HasInventory(iHatGlow) == true && Game.DoOnceOnly("Gave Hat")


But logically this also seem redundant unless Ego2 will later acquire an additional hat which shouldn't be given away, and you can simplify the inventory check instead of comparing it to true, so probably just:
Code: ags
player == cEgo2 && player.HasInventory(iHatGlow)

Khris

Indeed, an expression like  a && b && c  is evaluated from left to right.
As soon as player == cEgo2Game.DoOnceOnly("Gave Hat")  is also evaluated, returning  true. The entire test then fails because the player doesn't have the hat yet. From this point forward,  Game.DoOnceOnly("Gave Hat")  will only return false, and the entire expression will thus also always be false.

Like morganw says, you can put it last to prevent that, you can also do this:
Code: ags
  if (player == cEgo2 && player.HasInventory(iHatGlow)) {
    if (Game.DoOnceOnly("Gave Hat")) {
      // stuff happens
    }
  }

This version will always work, even if the engine suddenly decided to change the evaluation order, making the code 100% future-proof.

However there's an even better way to do this:

Code: ags
function on_event(EventType event, int data) {
  if (event == eEventAddInventory) {
    if (player == cEgo2 && data == iHatGlow.ID) {
      // stuff happens
    }
  }


If iHatGlow can be obtained multiple times, you'll want to use Game.DoOnceOnly() in addition.

TheVolumeRemote

Thank you so much Khris and Morgan! I really appreciate the help and the teach a man to fish explanation so I know what to do correctly going forward.

I hope you’re both having a lovely day and thank you again for taking time out of your day to help me, you mates are legends! :)

SMF spam blocked by CleanTalk