Adventure Game Studio | Forums

AGS Support => Beginners' Technical Questions => Topic started by: Stranga on Fri 09/02/2018 11:24:57

Title: Different ways to use an item only once? [SOLVED]
Post by: Stranga on Fri 09/02/2018 11:24:57
Hello everyone, I want to use an item on a hotspot only once to get another item without losing the initial item. So far I've been using
Code (ags) Select
if (Game.DoOnceOnly("GainItem"))

But I'm not sure if this is the best method/way to do this. Anyone have any ideas or experience on how to do this or is this way fine?

P.S wasn't sure If this sort of question should be posted here but any moderators are more than welcome to move it :)
Title: Re: Different ways to use an item only once?
Post by: Danvzare on Fri 09/02/2018 12:29:00
Create a variable in the room script and set it to false, then check if that variable is false when you use the item, and if it is, set the variable to true and gain the other item. That way if you use the item again, the check will fail and you'll get a different response, such as "I've got enough wood, I don't need to chop off any more."

I think something like this code should work:
Code (ags) Select

bool usedAxe = false;

if (!usedAxe)
{
    player.AddInventory(iWood);
    usedAxe = true;
}
else
{
    player.Say("I've got enough wood, I don't need to chop off any more.");
}
Title: Re: Different ways to use an item only once?
Post by: dayowlron on Fri 09/02/2018 13:05:06
the whole purpose for the Game.DoOnceOnly is for this purpose. Even though Danvzare's method will work, the way you had it works also and you don't need to set up the additional variable.
Title: Re: Different ways to use an item only once?
Post by: Stranga on Fri 09/02/2018 13:28:37
I thought it was the best method at the time didn't think it would be the actual way to do it. The bool method would be good if I weren't using the RestartGame() function. One other thing that I wanted to ask about is which way is better or they both do the same thing:

Code (ags) Select

if (player.ActiveInventory==iAxe && Game.DoOnceOnly("CutTree"))

//or

if (Game.DoOnceOnly("CutTree")){
    if (player.ActiveInventory==iAxe){

    }
}


I have used both ways and they both "seem" fine to me but I am unsure if they would conflict with each other some how with the first example.
Title: Re: Different ways to use an item only once?
Post by: Crimson Wizard on Fri 09/02/2018 13:54:09
Quote from: Stranga on Fri 09/02/2018 13:28:37
I thought it was the best method at the time didn't think it would be the actual way to do it. The bool method would be good if I weren't using the RestartGame() function.

Both boolean variables and DoOnceOnly are reset with the RestartGame.
Actually, what RestartGame does is simply loading a save that was made when game is started, or you call SetRestartPoint. So, this is like loading a savegame.


Quote from: Stranga on Fri 09/02/2018 13:28:37
One other thing that I wanted to ask about is which way is better or they both do the same thing:

Code (ags) Select

if (player.ActiveInventory==iAxe && Game.DoOnceOnly("CutTree"))

//or

if (Game.DoOnceOnly("CutTree")){
    if (player.ActiveInventory==iAxe){

    }
}


I have used both ways and they both "seem" fine to me but I am unsure if they would conflict with each other some how with the first example.


There is a difference, and that difference may be important or not important depending on situation.

First of all, the first example will run the block of statements if both conditions are true only.
The second example has TWO blocks of statements, one under "if (Game.DoOnceOnly("CutTree"))" and the second under "if (player.ActiveInventory==iAxe)", which is a "sub-block" of the first one.
If you only have commands under second condition, then there is no difference, but in theory you could also add commands under Game.DoOnceOnly like this:
Code (ags) Select

if (Game.DoOnceOnly("CutTree")){
    /// some commands here
    if (player.ActiveInventory==iAxe){

    }
    /// more commands here
}

In such hypothetical case these extra commands would be run if Game.DoOnceOnly returns true, but they won't depend on the second condition.


If you only suppose to have game react to both conditions at once always, I'd recommend to use the first variant, because it makes intentions more clear.
But then again, such things are rather important when you work in team and want other people understand your code. If you are working alone it's all up to you.
Title: Re: Different ways to use an item only once?
Post by: Khris on Fri 09/02/2018 16:02:12
I don't think that's correct, there is indeed a difference.

Code (ags) Select
  if (player.ActiveInventory==iAxe && Game.DoOnceOnly("CutTree"))

Expressions are evaluated from left to right (unless set differently in General Settings -> Backwards Compatibility). Which means if the player has used some other InventoryItem, the left test will fail. At this point AGS doesn't bother evaluating the right side, since "false && x" is always "false" anyway.
The downside of this method is that a subsequent else will catch both "other item was used" and "axe was used a second time", which is usually undesirable.

Here however:
if (Game.DoOnceOnly("CutTree")){
    if (player.ActiveInventory==iAxe){
      //...
    }
}


AGS always runs Game.DoOnceOnly() first, which means the entire outer block is disabled after the first run, regardless of the item that was used.
Which means:
1. Use Spoon on Tree -> (wrong)
2. Use Axe on Tree -> (wrong)

My suggestion would be to always handle the item first (after potentially approaching the hotspot and the like, of course):
  if (player.ActiveInventory == iAxe) {
    if (Game.DoOnceOnly("CutTree")) { ... }
    else ...
  }
  else Unhandled();


In general, always nest from generic to specific. Cutting the tree is part of the axe interaction, and should go inside it.
Title: Re: Different ways to use an item only once?
Post by: Stranga on Sat 10/02/2018 07:20:57
Thank you everyone and especially CW and Khris you both have gave great answers but also solved a few problems that I would of had to post here.
Title: Re: Different ways to use an item only once? [SOLVED]
Post by: Danvzare on Mon 12/02/2018 12:08:03
Quote from: dayowlron on Fri 09/02/2018 13:05:06
the whole purpose for the Game.DoOnceOnly is for this purpose. Even though Danvzare's method will work, the way you had it works also and you don't need to set up the additional variable.
Wow, can you believe that I've been using AGS for years, and I never knew that Game.DoOnceOnly worked like that.
I've learnt something new. :-D