Identify Objects by Common Attribute

MattFinucane
07 Aug 2019, 21:04

Hi!

I'd like to have the player searched at one point in my game, and if any objects in the player's inventory have the attribute "forbidden" for there to be consequences.

Ideally in this instance, I'd like to then be able to list all the objects in the player's inventory that meet this condition, a kind of "this is where you fucked up", but that's less important.

Any help in achieving this would be much appreciated!


mrangel
07 Aug 2019, 23:23

If the attribute is a boolean one, then you'd want something like:

forbiddenobjects = FilterByAttribute (ScopeInventory(), "forbidden", true)

If the 'forbidden' attribute has different values, but you want to find all objects that have that attribute, then you'd do:

forbiddenobjects = FilterByNotAttribute (ScopeInventory(), "forbidden", null)

(an attribute that doesn't exist is the same as an attribute whose value is null, so you search for the ones whose value is not null)

Your logic probably ends up looking like:

forbiddenobjects = FilterByNotAttribute (ScopeInventory(), "forbidden", null)
if (ListCount (forbiddenobjects) = 0) {
  msg ("Okay, you can pass.")
}
else {
  msg ("You aren't allowed to come in here carrying "+FormatList (forbiddenobjects, ",", ", and", "")+"!")
  // insert consequences here
}

hegemonkhan
08 Aug 2019, 07:33

you can also do this (but the newer 'FilterByAttribute' and 'FilterByNotAttribute' helper Functions do it for you):

game.count = 0

foreach (object_variable, ScopeInventory()) {
  if (HasAttribute (object_variable, "forbidden")) {
    game.count = game.count + 1
  }
}

if (game.count = 0) {
  // WHATEVER
} else {
  // WHATEVER
}

or

game.count = 0

foreach (object_variable, ScopeInventory()) {
  if (GetAttribute (object_variable, "forbidden") = WHATEVER_VALUE) {
    game.count = game.count + 1
  }
}

if (game.count = 0) {
  // WHATEVER
} else {
  // WHATEVER
}

MattFinucane
08 Aug 2019, 08:22

Thanks both for the quick responses - I don't generally use the code editor view except to check things, but will give this a shot (doesn't look too complicated).

A quick follow-up question - I'd like to improve on the in-built 'if object contains' such that if an object the player contains (i.e. a backpack) contains the requisite item, the function would still work. Basically how can I make that IF go down multiple levels without resorting to an if statement for every conceivable sub-container?

Thanks again!


mrangel
08 Aug 2019, 10:04

I'd like to improve on the in-built 'if object contains' such that if an object the player contains (i.e. a backpack) contains the requisite item, the function would still work.

There are a few different ways to check if the player contains an object. The expression in the if statement could be any of the following (I'm testing if the player object game.pov contains an object called gem as an example, but the same will work for any objects)

  • gem.parent = game.pov - tests if the gem is directly held by a player, not in a container
  • ContainsReachable (game.pov, gem) - also finds the gem if it is in an open container the player is holding
  • ContainsVisible (game.pov, gem) - as above, but also finds objects inside transparent containers that the player can see but can't use.
  • Contains (game.pov, gem) - Finds all objects inside the player, including invisible objects and those inside containers, regardless of whether the player can see or reach them. This is the code that is generated by "if object contains" in the GUI editor.

It's worth noting that ContainsVisible and ContainsReachable are both false if the gem is invisible; the other two don't care, they only test the location of the gem.

If you want to get a list of objects in a particular function, you've got a similar set of functions (these each return a list of objects):

  • GetDirectChildren (game.pov) - returns all objects directly inside a container, not in subcontainers. In this case, it finds objects the player is carrying. This will include invisible items.
  • ScopeReachableInventory () - returns all inventory objects the player can use from their inventory; this is all objects inside the player that aren't invisible, in an invisible container, or inside a closed container
  • ScopeInventory() - as above, but objects in a closed container will be included if the container is transparent.
  • GetAllChildObjects (game.pov) - gets a list of all objects inside the player. This only checks the location, and doesn't care if an object is invisible or inside a container.

MattFinucane
08 Aug 2019, 13:12

Very helpful, thanks again - will try these both out this evening and report back!


MattFinucane
08 Aug 2019, 22:10

Thanks both! Everything you provided worked, especially when I tweaked the first code with GetAllChildObjects, so the sentries would search the player's bags as well.