Take item only one time...

Started by TheRoger, Sun 21/03/2010 16:03:35

Previous topic - Next topic

TheRoger

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.

Khris

Usually the answer is use a variable, in this case though, there's the handy DoOnceOnly function:

Code: ags
  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.

Peter Bear

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) {
Not much time for gaming neither creating, but keeping an eye on everything :)

TheRoger

Didn't knew about DoOnceOnly function, It'll be time saver for me, thank you for help

TheRoger

Can't get this work with this code:
player.HasInventory(icap)
any ideas?

Crimson Wizard

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?

Khris


TheRoger

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...

Peter Bear

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.");
  }
Not much time for gaming neither creating, but keeping an eye on everything :)

Khris

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:

Code: ags
  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".

TheRoger

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...

Crimson Wizard

#11
Maybe this:

Code: ags

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".

Khris

This'll make the original problem resurface, because as soon as the player looses the bottle, they can get it again.

Code: ags
  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.");
  }


monkey0506

Quote from: Khris on Mon 22/03/2010 10:43:48
Code: ags
  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:

Code: ags
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.

TheRoger

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.

Matti

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.

SMF spam blocked by CleanTalk