Adventure Game Studio

AGS Support => Beginners' Technical Questions => Topic started by: TheRoger on Sun 21/03/2010 16:03:35

Title: Take item only one time...
Post by: TheRoger on Sun 21/03/2010 16:03:35
I wanted to do that player could take item from somewhere only one time. I did this code for that

else if(UsedAction(eGA_Open)) {
 if (player.HasInventory(itape)) {
 player.Say("There's nothing useful anymore.");
 }
 else {player.Say("There might be something useful.");
 player.Say("Let me check.");
 cEgo.Walk(384, 314, eBlock, eWalkableAreas);
 cEgo.FaceLocation(cEgo.x, cEgo.y - 50);
 player.Say("Junk, junk, more junk...");
 player.Say("Eureka");
 cEgo.AddInventory(itape);
 }}

It says that if character has tape, he wont be able to get new one and vice-versa. Well when I was testing the game, I noticed that if I got that Item, used it somewhere else, and don't have in inventory, it gives me a new one(logical). How should I do that it won't happen.
Title: Re: Take item only one time...
Post by: Khris on Sun 21/03/2010 16:33:52
Usually the answer is use a variable, in this case though, there's the handy DoOnceOnly function:

  else if (UsedAction(eGA_Open)) {
    if (Game.DoOnceOnly("finding tape")) {
      player.Say("There might be something useful.");
      player.Say("Let me check.");
      player.Walk(384, 314, eBlock);
      player.FaceDirection(eDirUp);
      player.Say("Junk, junk, more junk...");
      player.Say("Eureka");
      player.AddInventory(itape);
    }
    else player.Say("There's nothing useful anymore.");
  }


For a specific string, this function returns true the first time, then false thereafter.
Title: Re: Take item only one time...
Post by: Peter Bear on Sun 21/03/2010 16:38:44
woh ! great one :)

I write it down too, I always used variables, this function is quite handy !

alternatively I was about to tell

set a variable to whatever, once the tape is used : ie :  vtape =1;

then  update your

if (player.HasInventory(itape)) {

to

  if (player.HasInventory(itape) || vtape == 1) {
Title: Re: Take item only one time...
Post by: TheRoger on Sun 21/03/2010 17:14:19
Didn't knew about DoOnceOnly function, It'll be time saver for me, thank you for help
Title: Re: Take item only one time...
Post by: TheRoger on Sun 21/03/2010 17:36:35
Can't get this work with this code:
player.HasInventory(icap)
any ideas?
Title: Re: Take item only one time...
Post by: Crimson Wizard on Sun 21/03/2010 18:06:55
Quote from: TheRoger on Sun 21/03/2010 17:36:35
Can't get this work with this code:
player.HasInventory(icap)
any ideas?
What is not working, exactly?
Title: Re: Take item only one time...
Post by: Khris on Mon 22/03/2010 01:21:14
Post the code you're using.
Title: Re: Take item only one time...
Post by: TheRoger on Mon 22/03/2010 05:26:00
I wanted to that, if player has bottle cap, he gets bottle, and won't lose the cap

else if(UsedAction(eGA_Use)) {
   
  if (player.HasInventory(icap))  {
    Game.DoOnceOnly("finding tape");
      player.Say("Maybe I have something here.");
      player.Walk(715, 325, eBlock);
      cEgo.FaceLocation(cEgo.x, cEgo.y - 50);
      player.Say("Found it");
      player.AddInventory(ihalfbottle);
    }
    else player.Say("There's nothing useful anymore.");
}}

But character still gets bottle if has cap.

Actually I think it's my fault, because I don't know where to put DoOnceOnly, I tried many locations before hasinventory and this, but it doesn't work...
Title: Re: Take item only one time...
Post by: Peter Bear on Mon 22/03/2010 07:22:15
you should use kriss code ( see upper )

the "if doonceonly" is as the beginning, once you've picked the tape, that you have or not in the inventory doesnt matter, it has been taken ! That's what does this function.

dont test the HasInventory value then !

quote :
Quote
  else if (UsedAction(eGA_Open)) {
    if (Game.DoOnceOnly("finding tape")) {
      player.Say("There might be something useful.");
      player.Say("Let me check.");
      player.Walk(384, 314, eBlock);
      player.FaceDirection(eDirUp);
      player.Say("Junk, junk, more junk...");
      player.Say("Eureka");
      player.AddInventory(itape);
    }
    else player.Say("There's nothing useful anymore.");
  }
Title: Re: Take item only one time...
Post by: Khris on Mon 22/03/2010 10:43:48
One sec.
After the player uses something, they will find an item, but only if they have a bottle cap in their possession?
That doesn't make sense.

Regarding the technical side:
DoOnceOnly is supposed to be used like this:

  if (Game.DoOnceOnly("arbitrary but unique string")) {

    // code in here will be executed only the first time

  }
  else {

    // code in here will be executed not the first but every subsequent time

  }


So don't use the string "finding tape" again, use another string instead, e.g. "finding bottle".
Title: Re: Take item only one time...
Post by: TheRoger on Mon 22/03/2010 14:13:37
Here's what I need, If player has bottle cap, he will take the bottle, because it is needed only after getting bottle cap, and before that, player don't even need bottle...
Title: Re: Take item only one time...
Post by: Crimson Wizard on Mon 22/03/2010 14:38:02
Maybe this:


if (player.HasInventory(icap) && !player.HasInventory(ihalfbottle))
{
     player.Say("Maybe I have something here.");
     player.Walk(715, 325, eBlock);
     cEgo.FaceLocation(cEgo.x, cEgo.y - 50);
     player.Say("Found it");
     player.AddInventory(ihalfbottle);
}


This will make character find bottle ONLY if he already has the cup AND if he does not have the bottle yet.

Just in case you did not know, ! operator means "not".
Title: Re: Take item only one time...
Post by: Khris on Mon 22/03/2010 15:09:27
This'll make the original problem resurface, because as soon as the player looses the bottle, they can get it again.

  else if(UsedAction(eGA_Use)) {
    if (player.HasInventory(icap))  {
      if (Game.DoOnceOnly("finding bottle")) {
        player.Say("Maybe I have something here.");
        player.Walk(715, 325, eBlock);
        player.FaceDirection(eDirUp);
        player.Say("Found it");
        player.AddInventory(ihalfbottle);
      }
      else player.Say("There's nothing useful anymore.");
    }
    else player.Say("I don't think there's anything in there I need.");
  }
Title: Re: Take item only one time...
Post by: Crimson Wizard on Mon 22/03/2010 15:29:11
Oh... right.  :P
Title: Re: Take item only one time...
Post by: monkey0506 on Tue 23/03/2010 12:08:24
Quote from: Khris on Mon 22/03/2010 10:43:48  if (Game.DoOnceOnly("arbitrary but unique string")) {
  // ...
}


So don't use the string "finding tape" again, use another string instead, e.g. "finding bottle".

I just wanted to clarify this a bit. What happens is when you call Game.DoOnceOnly you specify a string value as the parameter. It can be anything you want it to be. AGS then takes that value and checks if you ever used it before. If you have, then the function returns false; otherwise it returns true.

So, technically speaking, the following is completely valid:

if (Game.DoOnceOnly("some repeated string")) {
  Display("1");
}
else if (Game.DoOnceOnly("some repeated string")) {
  Display("2");
}
else if (Game.DoOnceOnly("some repeated string")) {
  Display("3");
}


That will compile and run fine. However, you will only ever see the message, "1" displayed. Since you're passing the same string AGS detects that you have used it before and will return false for each of the else clauses.

My reason behind pointing this out is that you might want to check whether the user has found the bottle in more than one place. Although the code will compile properly, if you are specifying the same identifier string value in more than one location in your script, the Game.DoOnceOnly function will only return true one time for every instance of that identifier.

This can be useful if properly applied, but it's important to recognize what exactly is taking place when you are using this function.
Title: Re: Take item only one time...
Post by: TheRoger on Tue 23/03/2010 13:13:16
I'll try to play more with this. Is there a code that I could do action if I did action before. For example: There are drawers, and you can't use them, but if you go and talk to a man, you can use drawers to take something from there.
Title: Re: Take item only one time...
Post by: Matti on Tue 23/03/2010 14:31:18
Just use a variable for these kind of things. Create a bool ("opendrawers" or something) and set it to true after talking to the man. Then in the drawer's action event, ask if the bool is true or not.