Using player.HasInventory() in a switch statement. [SOLVED]

Started by Stranga, Tue 20/12/2022 23:55:09

Previous topic - Next topic

Stranga

Hello everyone,

I'm trying to simplify my code rather than using if and else statements and wish to convert it all to switch statements

For example:
Code: ags
 switch(player.HasInventory(item.ID))
 {
  case 1: do this; break;
  case 2: do that; break;
  default: yadda yadda; break;
 }

P.S I know this doesn't work as I'm trying to find a way to extract the item's ID and use it here but I keep running into a problem of cannot convert an ini into an inventory item.

Any help will be greatly appreciated :)

arj0n

As you have more then 1 item at a certain point, this idea won't work anyway, right?

Crimson Wizard

@Stranga, please clarify, what are you trying to achieve with this, what this code is for? The answer will depend on that.

Snarky

Yeah, you may have to rethink the logic behind this code; I think you must have gotten confused. HasInventoryItem can only return true or false, so it won't work in a switch statement (with more than two cases). And if you want to branch depending on what inventory item the player has, you need to consider what will happen if the player has more than one item in the inventory, as arj0n says.

Did you perhaps mean to use Character.ActiveInventory? In that case, you could do something like:

Code: ags
if(player.ActiveInventory != null)
{
  switch(player.ActiveInventory.ID)
  {
    case 1: do this; break;
    case 2: do that; break;
    default: yadda yadda; break;
  }
}

Crimson Wizard

Quote from: Snarky on Wed 21/12/2022 17:13:04Did you perhaps mean to use Character.ActiveInventory? In that case, you could do something like:

AFAIK in AGS you can also use Character.ActiveInventory directly in a switch, and compare to item script names:
Code: ags
switch(player.ActiveInventory)
{
case iKey:
case iBlueCup:
}

Stranga

My apologies, I should have clarified my intentions. It was going to be used to check if the player had certain items before proceeding. I've been using if and else statements but at the time I was unsure if it were a bool or was using the item's ID, as @Snarky mentioned.

Think about your code @Crimson Wizard, I'm not sure if that would work, would it? As I just want to check the items not exactly use them. 

Just to clarify, it's only to simplify my code and make it a little neater is all rather than:
Code: ags
if (player.HasInventory(iCup))
{

}
else if (player.HasInventory(iSpoon))
{

}

//e.c.t

P.S I was thinking of running loop checks but still I think the fact that it's using a boolean than an integer will still cause the same problem down the road.

Khris

First of all: it's called "int", short for "integer", which means "whole number" ;)
Second of all: Character.HasInventory() expects an InventoryItem*, not an int. This is why you're getting the error you mentioned.

As for the actual issue of making your code shorter: I'm still not sure if you're writing code for the something_Useinv function which is supposed to give different replies based on which item was used (because it feels like this is what you're trying to do based on the code) or whether you want "to check if the player had certain items before proceeding", because that's not something you'd use a switch statement for at all, and you'd also not check items individually I guess?

Anyways, here's how to do the first thing:
Code: ags
  switch (player.ActiveInventory) {
  case iKey:
    player.Say("It's the wrong key.");
    break;
  case iGoldenkey:
    player.Say("It's the wrong key.");
    break;
  case iSilverkey:
    player.Say("The door unlocks with a satisfying click.");
    break;
  default:
    player.Say("I need a key here.");
  }

The other thing works very differently:
Code: ags
  if (player.HasInventory(iRope) && player.HasInventory(iHook) && player.HasInventory(iInsurancePolicy)) {
    // ...
  }
  else {
    // ...
  }

Stranga

Thanks for pointing out that error, Khris! I meant to say integer.

The function is a basic interactive function, not using an item on something, so I can understand that ActiveInventory would work as I've made switch statements such as that in the past. It was only to check if the player had certain items then the other character would respond without having to type long lines with "if" and "else" statements.

I guess I could run a loop check to check all items in the game and use their ID in a switch statement that way but wasn't sure if it was exactly possible to do so?

Crimson Wizard

#8
Quote from: Stranga on Mon 26/12/2022 23:54:33It was only to check if the player had certain items then the other character would respond without having to type long lines with "if" and "else" statements.

I guess I could run a loop check to check all items in the game and use their ID in a switch statement that way but wasn't sure if it was exactly possible to do so?

I honestly do not see how having a switch inside a loop over all items would help you to achieve what you want in the above case (simplier code).

What exactly do you want to make simpler? Do you have a response per item, or a response per a combination of items?

Stranga

@Crimson Wizard I guess it's not generally for simpler code, just neatening up my old stuff, to be honest. (should have added that in the title) I'll mark this as solved as I'll use the else and if statements as it already work and play around with ideas in my test game.

Thanks again, everyone!

Crimson Wizard

#10
If this is about having many items to check in a single "if", like in Khris's example:
Code: ags
if (player.HasInventory(iRope) && player.HasInventory(iHook) && player.HasInventory(iInsurancePolicy)) {

Then what you may use instead is a list of required items, which you would iterate in a loop and test whether each of these items exist. Such list could be created in various ways, even as a comma-separated list in String, for example. The only issue would be to convert a textual name into inventory item's pointer or ID.

Simply hypothetically, it could look like this:
Code: ags
if (TestAllItems("iRope, iHook, iInsurancePolicy")) {
}
where TestAllItems would parse the string and check for all the items there.

But I am currently speculating, as I do not see your real code, so I don't know which kinds of cases you are trying to work on.

Stranga

Quote from: Crimson Wizard on Tue 27/12/2022 00:16:08Simply hypothetically, it could look like this:
Code: ags
if (TestAllItems("iRope, iHook, iInsurancePolicy")) {
}
where TestAllItems would parse the string and check for all the items there.

But I am currently speculating, as I do not see your real code, so I don't know which kinds of cases you are trying to work on.

Actually @Crimson Wizard I think you're onto something here, I'll play around with it as such. My real code is nothing special to be honest as this is mainly an idea I thought of to see if there was a way to compact it all into something with less code.


Quote from: Khris on Thu 22/12/2022 07:47:57The other thing works very differently:
Code: ags
  if (player.HasInventory(iRope) && player.HasInventory(iHook) && player.HasInventory(iInsurancePolicy)) {
    // ...
  }
  else {
    // ...
  }

Also, @Khris I'm a little worried about you :-\ 

Khris

No need to worry, it was supposed to be a lame joke about combining a hook and a rope into a grappling hook. :P

Also: I still don't understand what the code you're trying to simplify does. You posted
QuoteThe function is a basic interactive function, not using an item on something, so I can understand that ActiveInventory would work as I've made switch statements such as that in the past. It was only to check if the player had certain items then the other character would respond without having to type long lines with "if" and "else" statements.
but I have no idea what "a basic interactive function, not using an item on something" is supposed to mean or how to understand the inherent contradiction of "It was only to check if the player had certain items then the other character would respond" which again mixes the two concepts of merely possessing an item and using it on a character.

Why not simply post an example of old code so we can suggest possible improvements?

eri0o

I have no idea what's going on too, but are the possible outcomes mostly a text, except in some specific cases? Because then, maybe you could use a custom property to store this text, and then handle the exception cases where something else is required using if/else. Essentially, you would check the text of the custom property you assigned through the editor and run it through your own function, and then be doing the same if/else, but just when the text is not sufficient.

One thing to test for custom text properties is generating a translation file - I think they are there, but I don't remember since which AGS version.

SMF spam blocked by CleanTalk