-
Notifications
You must be signed in to change notification settings - Fork 17
Attributes for items
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.
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.
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".
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.
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);
},
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 },
});
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
.
For a COUNTABLE item, returns the number at the given location. Otherwise returns 1 if the item is there, 0 otherwise.
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.
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.
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.
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.
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.
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
},
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).
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
Most templates set a Boolean flag, so items can be identified as that type. Should not be changed!
A function, defaults to LIGHT_FULL for rooms and LIGHT_NONE for items.
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.
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
- First steps
- Rooms and Exits
- Items
- Templates
- Items and rooms again
- More items
- Locks
- Commands
- Complex mechanisms
- Uploading
QuestJS Basics
- General
- Settings
- Attributes for items
- Attributes for rooms
- Attributes for exits
- Naming Items and Rooms
- Restrictions, Messages and Reactions
- Creating objects on the fly
- String Functions
- Random Functions
- Array/List Functions
- The
respond
function - Other Functions
The Text Processor
Commands
- Introduction
- Basic commands (from the tutorial)
- Complex commands
- Example of creating a command (implementing SHOOT GUN AT HENRY)
- More on commands
- Shortcut for commands
- Modifying existing commands
- Custom parser types
- Note on command results
- Meta-Commands
- Neutral language (including alternatives to "you")
- The parser
- Command matching
- Vari-verbs (for verbs that are almost synonyms)
Templates for Items
- Introduction
- Takeable
- Openable
- Container and surface
- Locks and keys
- Wearable
- Furniture
- Button and Switch
- Readable
- Edible
- Vessel (handling liquids)
- Components
- Countable
- Consultable
- Rope
- Construction
- Backscene (walls, etc.)
- Merchandise (including how to create a shop)
- Shiftable (can be pushed from one room to another)
See also:
- Custom templates (and alternatives)
Handing NPCs
- Introduction
- Attributes
- Allowing the player to give commands
- Conversations
- Simple TALK TO
- SAY
- ASK and TELL
- Dynamic conversations with TALK TO
- TALK and DISCUSS
- Following an agenda
- Reactions
- Giving
- Followers
- Visibility
- Changing the player point-of-view
The User Experience (UI)
The main screen
- Basics
- Printing Text Functions
- Special Text Effects
- Output effects (including pausing)
- Hyperlinks
- User Input
The Side Panes
Multi-media (sounds, images, maps, etc.)
- Images
- Sounds
- Youtube Video (Contribution by KV)
- Adding a map
- Node-based maps
- Image-based maps
- Hex maps
- Adding a playing board
- Roulette!... in a grid
Dialogue boxes
- Character Creation
- Other example dialogs [See also "User Input"]
Other Elements
- Toolbar (status bar across the top)
- Custom UI Elements
Role-playing Games
- Introduction
- Getting started
- Items
- Characters (and Monsters!)
- Spawning Monsters and Items)
- Systema Naturae
- Who, When and How NPCs Attack
- Attributes for characters
- Attacking and guarding
- Communicating monsters
- Skills and Spells
- Limiting Magic
- Effects
- The Attack Object
- [Extra utility functions](https://github.com/ThePix/QuestJS/wiki/RPG-Library-%E2%80%90-Extra Functions)
- Randomly Generated Dungeon
- Quests for Quest
- User Interface
Web Basics
- HTML (the basic elements of a web page)
- CSS (how to style web pages)
- SVG (scalable vector graphics)
- Colours
- JavaScript
- Regular Expressions
How-to
Time
- Events (and Turnscripts)
- Date and Time (including custom calendars)
- Timed Events (i.e., real time, not game time)
Items
- Phone a Friend
- Using the USE verb
- Display Verbs
- Change Listeners
- Ensembles (grouping items)
- How to spit
Locations
- Large, open areas
- Region,s with sky, walls, etc.
- Dynamic Room Descriptions
- Transit system (lifts/elevators, buses, trains, simple vehicles)
- Rooms split into multiple locations
- Create rooms on the fly
- Handling weather
Exits
- Alternative Directions (eg, port and starboard)
- Destinations, Not Directions
Meta
- Customise Help
- Provide hints
- Include Achievements
- Add comments to your code
-
End The Game (
io.finish
)
Meta: About The Whole Game
- Translate from Quest 5
- Authoring Several Games at Once
- Chaining Several Games Together
- Competition Entry
- Walk-throughs
- Unit testing
- Debugging (trouble-shooting)
Releasing Your Game
Reference
- The Language File
- List of settings
- Scope
- The Output Queue
- Security
- Implementation notes (initialisation order, data structures)
- Files
- Code guidelines
- Save/load
- UNDO
- The editor
- The Cloak of Darkness
- Versions
- Quest 6 or QuestJS
- The other Folders
- Choose your own adventure