// StateManager.js
(function () {
/*global adventurejs A*/
"use strict";
/**
* @ajspath adventurejs.Atom.StateManager
* @augments adventurejs.Atom
* @class adventurejs.StateManager
* @ajsnavheading FrameworkReference
* @param {String} game_name Name of top level game instance that is scoped to window.
* @param {String} name Instance name.
* @param {String} parent_id The ID of the containing asset instance.
* @summary A container for state variables.
* @classdesc
* <p>
* <strong>StateManager</strong> is a special class used
* for storing general state variables. For example,
* <a href="/doc/adventurejs.Tangible.html#property_is">tangible.is</a>
* is used to store states such as
* <a href="/doc/adventurejs.Tangible.html#property_is_closed">tangible.is.closed</a>,
* <a href="/doc/adventurejs.Tangible.html#property_is_locked">tangible.is.locked</a>,
* <a href="/doc/adventurejs.Tangible.html#property_is_global">tangible.is.global</a>,
* etc.
* This is done chiefly for organizational purposes. With hundreds of
* properties per asset, it seemed cleaner
* to group similar types of properties into clusters and access them
* through dot notation, rather than leave hundreds of properties
* floating around the top level of each object. The reason to make it a
* classed object rather than a generic object (as we do for some collections)
* is so we can add prototype methods and properties that have access to scope
* of <code>this</code> (meaning the parent asset) and <code>game</code>
* (the top level game object).
* <br><br>
* State containers and their values are passed down the inheritance chain.
* For example: {@link adventurejs.Tangible|Tangible} inherits from
* {@link adventurejs.Asset|Asset}, and
* <a href="/doc/adventurejs.Asset.html#property_is_global">asset.is.global</a>
* is available on
* <a href="/doc/adventurejs.Tangible.html#property_is_global">tangible.is.global</a>.
* It's also possible to override
* inherited nested properties. For example:
* {@link adventurejs.Exit|Exit} inherits
* <a href="/doc/adventurejs.Tangible.html#property_is_closed">tangible.is.closed</a>
* and
* <a href="/doc/adventurejs.Tangible.html#property_is_locked">tangible.is.locked</a>,
* but overrides them with new definitions in order to account
* for Exit's relationship to the linked class
* {@link adventurejs.Aperture|Aperture}.
**/
class StateManager extends adventurejs.Atom {
constructor(name = "is", game_name, parent_id) {
super(name, game_name);
this.class = "StateManager";
if ("string" === typeof parent_id && parent_id) {
this.parent_id = parent_id;
} else this.parent_id = "";
return this;
}
get parent() {
return this.game.getAsset(this.parent_id);
}
/**
* See if there is a linked asset, such as an other side of a door,
* and set this value for it. Intended primarily for open/closed,
* locked/unlocked, sealed/unsealed, and known / seen / used.
* @param {*} value
* @param {String} property
*/
setLinkedAssetState(property, value) {
var parent = this.parent;
if (parent && parent.linked_asset) {
var linked_asset = this.game.getAsset(parent.linked_asset);
if (linked_asset && linked_asset[this.name])
linked_asset[this.name][property] = value;
}
}
/**
* Set linked values such as open/close. Also see if there is a linked asset,
* such as an other side of door, and set the same values for it.
* @param {Boolean} value
* @param {String} posprep
* @param {String} negprep
*/
setUnstate(value, posprop, negprop) {
this[posprop] = value;
this[negprop] = "boolean" === typeof value ? !value : value;
var parent = this.parent;
if (parent && parent.linked_asset) {
var linked_asset = this.game.getAsset(parent.linked_asset);
if (linked_asset && linked_asset[this.name]) {
linked_asset[this.name][posprop] = this[posprop];
linked_asset[this.name][negprop] = this[negprop];
}
}
}
} // class State
adventurejs.StateManager = StateManager;
})();