// Drain.js
(function () {
/* global adventurejs A */
/**
* @ajspath adventurejs.Atom.Asset.Matter.Tangible.Thing.Drain
* @augments adventurejs.Thing
* @class adventurejs.Drain
* @ajsconstruct MyGame.createAsset({ "class":"Drain", "name":"foo", [...] })
* @ajsconstructedby adventurejs.Game#createAsset
* @ajsnavheading PlumbingClasses
* @param {String} game_name The name of the top level game object.
* @param {String} name A name for the object, to be serialized and used as ID.
* @ajscomponentof Sink
* @ajscomponents Plug
* @summary Roto Rooter, that's the name, to send your troubles down the drain.
* @tutorial Substances_Vessels
* @tutorial Tangibles_Components
* @ajsdemo PlumbingDemo, BasicSink, IntegratedSink, BasicBathtub, IntegratedBathtub, Scorecard
* @ajssubstancecontainer in
* @ajstangiblecontainer in
* @todo Implement components:Plug separately for Drain.
* @classdesc
* <p>
* <strong>Drain</strong> is a subclass of the simple generic
* {@link adventurejs.Thing|Thing}. What makes it unique is its
* container properties. Drain has a
* {@link adventurejs.Aspect|Aspect} with a
* {@link adventurejs.Vessel|Vessel}.
* That part is typical - all Vessels reside inside
* Aspects – what makes Drain unique is that its
* Vessel has infinite capacity, and it can be linked
* with another Vessel such as a
* {@link adventurejs.Sink|Sink}
* with a limited capacity, so
* that when the Drain is plugged, the Sink fills, and when
* Drain is unplugged, the Sink empties into the Drain.
* </p>
* <p>
* A Drain can exist on its own, or a Drain can be
* attached to a
* {@link adventurejs.Sink|Sink} or
* {@link adventurejs.Bathtub|Bathtub} or other
* {@link adventurejs.Drainable|Drainable} subclass which itself
* has a Vessel, such that the Drainable drains
* via the Drain. A Drain can be plugged by a
* {@link adventurejs.Plug|Plug} to allow the
* linked Drainable to hold liquid.
* </p>
* <p>
* Links between a Drain and Plug
* can be created automatically through the use of the
* <code class="property">components</code> property. Note that
* <code class="property">components</code>
* is a special convenience property that only pertains to some
* classes with inherent code for making links.
* To learn more about the <code class="property">components</code>
* property, see <a href="/doc/Tangibles_Components.html">Components</a>.
* </p>
* <p>
* Following is an example of a Drain with a
* related Plug.
* To see an example of a more complete
* arrangement with a Drainable, Faucet, Handles, Drain
* and Plug, see the {@link adventurejs.Sink|Sink class}.
* </p>
* <h3 class="examples">Example:</h3>
* <pre class="display"><code class="language-javascript">MyGame.createAsset({
* class: "Drain",
* name: "dank drain",
* descriptions: { look: "A dark drain. ", },
* components: ["plug"],
* });
*
* MyGame.createAsset({
* class: "Plug",
* name: "plug",
* synonyms: "plug",
* descriptions: { look: "A drain plug. ", },
* });
* </code></pre>
**/
class Drain extends adventurejs.Thing {
constructor(name, game_name) {
super(name, game_name);
this.class = "Drain";
this.singlePluralPairs = [["drain", "drains"]];
this.is.listed = false;
this.descriptions.look = "It's a drain.";
this.setDOVs(["open", "close", "plug"]);
this.setDOV({ unplug: { with_nothing: true } });
this.setIOVs(["pour", "fill", "put", "throw", "take"]);
this.aspects.in = new adventurejs.Aspect(
"in",
this.game_name,
this.id
).set({
list_contents_in_examine: true,
know_contents_with_parent: true,
list_contents_in_room: false,
contents_limits: { height: 0.1, width: 0.1, depth: 0.1, count: 1 },
});
this.aspects.in.vessel = new adventurejs.Vessel(
"in",
game_name,
this.id
).set({ maxvolume: Infinity, is: { drain: true } });
this.linkableClasses = {
Plug: function (object) {
// this plugs push plug // can have multiple plugs
if ("undefined" === typeof this.linked_components.Plugs) {
this.linked_components.Plugs = [];
}
this.linked_components.Plugs.push(object.id);
},
};
this.linkComponents = function Drainable_linkComponents() {
// link plugs to drain
if ("undefined" !== typeof this.linked_components.Plugs) {
var drain = this; //.game.getAsset(this.linked_components.Drain);
this.linked_components.Plugs.forEach(function (id) {
var plug = this.game.getAsset(id);
// console.warn("Drain linkComponents plug", plug);
drain.setVerbWithAsset("plug", plug, "iov");
plug.setVerbWithAsset("plug", drain, "dov");
}, this);
}
};
}
// override onMoveThatToThis inherited from Tangible
// to check if asset is plug and close drain
onMoveThatToThis(asset, where) {
var results = super.onMoveThatToThis(asset, where);
if ("undefined" !== typeof results) return results;
if (this.allowVerbWithAsset({ verb: "plug", asset: asset, ov: "dov" })) {
this.game.dictionary.verbs.plug.setVerbConnection(this, asset);
this.is.plugged = true;
}
return;
}
// override onRemoveThatFromThis inherited from Tangible
// to check if asset is plug and open drain
onRemoveThatFromThis(asset) {
var results = super.onRemoveThatFromThis(asset);
if ("undefined" !== typeof results) return results;
if (this.isConnectedToAsset("plug", asset, "to_iov")) {
this.game.dictionary.verbs.plug.unsetVerbConnection(this, asset);
this.is.plugged = false;
var parent = this.getPlaceAsset();
if (parent.aspects.in.vessel.getVolume() > 0) {
var substance = this.game.getAsset(
parent.aspects.in.vessel.substance_id
);
parent.aspects.in.vessel.empty();
var msg = `${substance.Name} drains out of ${parent.articlename}. `;
this.game.getInput().appendTurn(msg);
}
}
return;
}
}
adventurejs.Drain = Drain;
})();