Install & Uninstall
install and uninstall are two commands defined on Generic Room. A player runs install <thing> (holding the thing) or uninstall <thing> (standing in the room), and the command routes the object to a shared timed action. Several unrelated object families ride the same two commands: door locks and security systems, cyberware, and furniture. This page describes the shared flow and the verbs you implement to make a new kind of thing installable.
The flow
The command verb only parses arguments, picks the target, and calls the object's why_cant_install predicate. If that returns a non-empty reason it is shown and nothing happens. Otherwise the command queues the install action; it does not perform the install itself.
The two commands
Both commands live on Generic Room, so they work in any location.
install <thing>matches<thing>in the player's inventory, then branches on the object family to work out what it is being installed onto:- A lock or security system needs
install <thing> on <direction>; the target is the door in that direction. - Cyberware defaults to the player, or takes
into <creature>(and options takeinto <creature>'s <ware>). - Furniture targets the current room;
install <thing> in <container>is also accepted.
- A lock or security system needs
uninstall <thing>matches the already-installed object (on the door, in the room, or in a creature's cyberware list depending on thefromtarget) and queues the uninstall action.
The shared action
Both commands queue a timed action (the install / uninstall entries in $actions). Actions run a two-phase start -> finish lifecycle over a fixed duration, so an install takes a few seconds of game time and can be interrupted. See the action system for the general pattern.
start re-validates with why_cant_install, announces "begins installing", and returns the duration plus a finish_state. finish re-validates again (state can change while the timer runs) and then calls do_install. Uninstall mirrors this with why_cant_uninstall and do_uninstall.
Checked vs. check-free installs
Some installs are a skill check and some are automatic:
- If the object defines an
install_difficultyverb, the action rolls a security skill check against that difficulty. On success it installs and improves the skill; on failure it announces a fumble and still grants some practice. - If the object does not define
install_difficulty, the action skips the check entirely and installs automatically once the timer completes.
Furniture is the check-free case: there is no meaningful difficulty to putting a table down, so furniture omits the install_difficulty verb and installs with no roll. Locks, security systems, and cyberware define install_difficulty and go through the check.
The installable interface
To make a new kind of object installable, implement these verbs on it. The predicates return an empty string when the action is allowed, or a player-facing reason string when it is not.
| Verb | Contract |
|---|---|
why_cant_install(dude, target) |
Reason install is disallowed, or "". Checked both when the command is issued and again when the timer finishes. |
do_install(dude, check, target[, ...]) |
Commit the install: record where it is installed, move the object as needed, and announce via $you:do. |
why_cant_uninstall(dude, target) |
Reason uninstall is disallowed, or "". |
do_uninstall(dude, check, target) |
Commit the uninstall and announce it. |
is_installed() |
Whether the object is currently installed. |
install_difficulty() |
Optional. Define it to require a skill check; omit it for a check-free install. |
Worked example: furniture
Generic Furniture is the simplest installable and a good template. It tracks where it is installed in an installed_in property, and is_installed() just reports whether that is set.
Installing. why_cant_install refuses if the piece is already installed, if the player is not carrying it, if the target is not a room the player is standing in, or if the piece is broken. do_install sets installed_in, moves the piece into the room, and announces it. Because furniture defines no install_difficulty, the action installs it with no skill check.
No pickup while installed. Installed furniture cannot be carried off. Furniture implements cant_take, the same hook the pickup path already consults, and returns a reason whenever is_installed() is true. Any attempt to get or take the piece is refused with that message until it is uninstalled.
No uninstall while in use. why_cant_uninstall refuses if the piece is not installed, is flagged permanent, is not installed in the room the player is standing in, or is currently in use. Before checking occupancy it calls validate_occupants to drop anyone who has wandered off, then inspects the sitter list: if the only occupant is the player, they are told to get up first; if anyone else is using it, it reports the piece is in use. Only when it is empty can it be removed. do_uninstall clears installed_in, moves the piece back to the player, and announces it.
Adding your own installable
- Give the object the six interface verbs above (skip
install_difficultyfor a check-free install). - Add a branch to the room's
install/uninstallcommands for your object family, resolving the correct target and queueing the action. Existing branches for locks, cyberware, and furniture are the models. - If the object should resist being picked up or moved while installed, implement
cant_take(and any similar guard) keyed onis_installed(). - Keep every guard in the
why_cant_*predicate, not indo_*. The action re-runs the predicate at finish time, so state that changes during the timer is caught.
See also
- Programmer Docs - index and house rules.