Skip to content

Attributes for items

ThePix edited this page Jul 3, 2021 · 92 revisions

This lists the attributes you might want to add or modify for items in your game. Several are functions; I am wanting to pass responsibility for decisions to the item, so, for example, the container can decide if it is blocking access to its contents (which by default depends on the "closed" attribute, but can be modified for your container).

Note 1: Attributes will only be saved if they are string, number, Boolean, string array or number array. Functions, other arrays and objects will not be saved.

Note 2: For how to display and track the value of attributes in the user interface, see here.

Names

There are a surprising number of attributes just to give an item a name! The only one you must provide is "name", and that is usually enough. However, using the others where required will make your game far more slick, as Quest will know how to properly refer to the object.

When you refer to a general object in text the user will see - that is, when the same text string can be used by different items - you should be using the lang.getName function - or better, use a text processor directive - as again this will allow Quest to decide exactly how to modify the name.

For full details on attributes related to names, go here.

Location attributes

These are attributes involving in defining where the item is. Note that "loc" (short for location) is always a string, the name of the location, not the object that is the location. To change a location, it is often best to use moveChar for the player or an NPC (discussed here) and for items it is usually best to use the moveToFrom method described below, though if you know for certain what the item is and that it has a "loc" attribute, and you do not want events getting triggered, it should be safe to set "loc".

loc

Used by the default isAtLoc to determine where the item is. You cannot rely on setting this to work for all items, as some (for example COUNTABLE items) will ignore it.

Only use this attribute to determine an item's location when you are certain it will exist for that specific item.

isAtLoc(location_name, situation)

This is the definitive source for where an item is - this is how Quest ultimately decides where things are.

Behind the scenes, this uses two functions to decide, the first, "isLocatedAt", using the location and the second, "isApparentTo" using the situation, as discussed later.

If you want to know if something is here, use "isAtLoc". However, if you want to modify the behavior of an item, it is generally easier to give is a custom "isLocatedAt" or "isApparentTo".

The "isAtLoc" should be able to accept either the name of the object or the object itself, and ideally will also check the item exists; "isLocatedAt" expects the name of the object.

This example of a custom "isAtLoc" is from the COMPONENT template.

    isAtLoc:function(loc, situation) {
      if (typeof loc !== "string") loc = loc.name
      if (!w[loc]) errormsg("The location name `" + loc + "`, does not match anything in the game.")
      if (situation !== world.PARSER && situation !== world.ALL) return false;
      let cont = w[this.loc];
      return cont.isAtLoc(loc);
    },

isLocatedAt(location_name, situation)

Is this object at the given location? By default, this returns true if the given location matches the "loc" attribute (which must be the name of the location, not the location itself), but you can override this to give ultimate control on where an item is. If it always returns true, an item will be everywhere. In this example, the cabinet is in two rooms (and note, has no "loc" attribute):

createItem("glass_cabinet", CONTAINER(true), {
  examine:"A cabinet with a glass front.",
  transparent:true,
  isLocatedAt:function(loc) {
    return (loc == "lounge" || loc == "dining_room") 
  }
})

For an item that is everywhere, check if the location is actually a location (so it does not appear in the player inventory or containers):

createItem("walls", {
  examine:"They're walls, what are you expecting?", 
  regex:/^wall$/,
  isLocatedAt:function(location_name) { return w[room_name].room },
});

isApparentTo(situation)

This is used by "isAtLoc" to decide if we want to hide the item for this situation. Why would we want to do that?

A common reason is because an item is flagged as scenery. We want the parser to be able to find the object here, but the list of items in the room.

world.ALL
world.PARSER
world.SIDE_PANE
world.LOOK
world.INVENTORY
world.SIDE_PANE
world.PURCHASE

If the parser is asking if the item is there, situation will be world.PARSER. If it is the LOOK command, or the equivalent, then situation will be world.LOOK. A scenery object would return true for the former, but not the latter. If the information has been requested by the inventories in the side pane, the value will be world.SIDE_PANE. If the situation is world.ALL, then the item should just be there (this is used to determine if a container holds the item or an NPC has it); world.INVENTORY is for when the player uses the INVENTORY command, and world.PURCHASE for when making a purchase.

You could add your own situations. They are actually integers behind the scenes, and to avoid any conflicts, just assign your custom situation to a high value in code.js.

world.CAST_SPELL = 101

This simple example just returns false for the room description if this item is flagged as scenery, and true otherwise.

  isApparentTo:function(situation) {
    if (situation === world.LOOK && this.scenery) return false;
    return true;
  },

It is good to flag an item as "scenery" even if you have a custom "isApparentTo" function that serves that purpose, as the parser will check that when the player does ALL; if flagged as scenery it will be excluded from the list.

In fact, in generally it is probably not that good an idea to have custom "isApparentTo" function. If you have strange situations, either handle it in the "isLocatedAt" function if it is specific to an item, or use a custom function that gets used for everything, as this will ensure consistency.

If you want to change how things are done across the whole game, you can have a settings.defaultIsApparentTo function in settings.js.

settings.defaultIsApparentTo = function(situation) {
  if (situation === world.LOOK && this.scenery) return false
  if (situation === world.SIDE_PANE && this.scenery) return false
  return true
}

Note, however, that you can control whether scenery items are seen in the side pane with settings.showSceneryInSidePanes.

countAtLoc(loc)

For a COUNTABLE item, returns the number at the given location. Otherwise returns 1 if the item is there, 0 otherwise.

moveToFrom(options, to, from)

Use this to move an item. This will ensure items that do not use the "loc" attribute get moved properly. The "from" parameter is optional, and probably only useful for COUNTABLE items ("toLoc" will get set to the items currently location if not set, so should be supplied for items that do not use "loc").

If fromLoc is the same as toLoc, nothing happens (i.e., the three event functions below will not get called).

If you have an item with a custom "isAtLoc" or "isLocatedAt" you will need to give it a custom "moveToFrom" if the item can be moved.

afterMove(options)

If an item has this function, it will be called after the item is moved.

Note that if this function uses moveToFrom to subsequently move the item, you could end up in an endless loop! You will need to use "loc" and some care in that situation.

afterTakeOut(options), afterDropIn(options)

These are attributes of the location (or container or character), and will be triggered when an item goes from it or arrives at it - as long as moveToFrom has been used. This means you can have a container or room respond when an item is put there or is taken away.

previousLoc

Stores the previous location for the player and NPCs (as long as they are moved using world.setRoom). Note that by default this will initially be undefined, so if you use this, you need to either check that or set an inital value in the createItem call..

This could be useful for a lift system. When the player enters the lift, you want to know what floor she is currently on, which you can get from what the previousLoc value. If the game starts in the lift, you might want to set previousLoc to "lobby", say, to have the lift start the game on that floor.

Other

scenery

Just as with Quest 5, setting this to true makes the object scenery, so it will not appear in a room description (say when the user does LOOK), but the player can still interact with it.

If the player picks up an item, this attribute will automatically be set to false.

It can be a good idea to check the value of this attribute in a room description via the text processor, so the item only gets mentioned when the attribute is true. When the player picks it up, scenery is set to false, and the room description no longer says it is there.

The shed is disappointingly empty{if:flashlight:scenery:, apart from a torch in the far corner}.

By default, items flagged as scenery do not appear in the lists in the side panes. However, setting settings.showSceneryInSidePanes to true will change that; items will still not appear in the list for rooms, but will appear in the side panes. This is important if you have no command line in your game.

examine

This can be a string or a function, and will be used when an item is looked at.

If this is a function, it can be given two parameters. The first is a Boolean that will be true if this is one of several objects being examined. To allow for that, you should prefix the output with prefix(item, isMultiple), for example like this:

  examine:function(isMultiple) {
    msg(prefix(item, isMultiple) + "A funny-looking thing.")
  }

If it is a long description that makes clear what the object is, you may consider that to be unnecessary.

The second parameter is the character doing the examining. By default that will only ever be the player, so generally this can be ignored, as in the example above.

The function should return true to indicate the action was successful.

Some templates (such as ROPE) use examineAddendum() to automatically append the state of the rope to the description - but only if it is a string. You can add it to your own function like this:

  examine:function(isMultiple) {
    msg(prefix(this, isMultiple) + "The rope is about 40' long." + this.examineAddendum())
    return true
  },

parserPriority

If the parser cannot decide if the user is referring to a number of different items, the disambiguation menu is displayed. Sometimes we can guess in advance, and you can use this attribute to encourage or discourage the parser to pick this item when decided what the user is referring to. Use a positive value to have the parser tend towards this item (perhaps 10) and a negative to indicate it should tend not to (say -10).

excludeFromAll

If the user does GET ALL, any item with excludeFromAll set to true will be skipped. This is set by default for NPCs and items flagged as scenery

takeable, player, room, wearable, countable, etc.

Most templates set a Boolean flag, so items can be identified as that type. Should not be changed!

lightSource()

A function, defaults to LIGHT_FULL for rooms and LIGHT_NONE for items.

icon()

Returns the file name of the item's icon. As this is a function, the name returned could depend on the item state, for example, whether a container is open or closed.

Notes

When an item is created

You can use settings.itemCreateFunc to do something each time an item is created. You could use this to set an attribute on every item, in the example the zone is set to the current value of the global variable 'zone'. You could include a counter too.

settings.itemCreateFunc = function(o) {
  o.zone = zone
}

Tutorial

QuestJS Basics

The Text Processor

Commands

Templates for Items

See also:

Handing NPCs

The User Experience (UI)

The main screen

The Side Panes

Multi-media (sounds, images, maps, etc.)

Dialogue boxes

Other Elements

Role-playing Games

Web Basics

How-to

Time

Items

Locations

Exits

Meta

Meta: About The Whole Game

Releasing Your Game

Reference

Clone this wiki locally