// 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 BathroomClasses
* @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.
* @ajspartof Sink
* @ajsparts Plug
* @summary Roto Rooter, that's the name, to send your troubles down the drain.
* @tutorial Substances_Vessels
* @tutorial Tangibles_LinkedAssets
* @ajssubstancecontainer in
* @ajstangiblecontainer in
* @todo Implement parts: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">parts</code> property. Note that
* <code class="property">parts</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">parts</code>
* property, see <a href="/doc/Tangibles_LinkedAssets.html">Linked Assets</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. ", },
* parts: ["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_in_parent = 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"]);
this.can.be_poured_into = true;
this.can.be_filled_from = false;
this.aspects.in = new adventurejs.Aspect("in", this.game_name).set({
parent_id: this.id,
list_in_examine: true,
know_with_parent: true,
list_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.registerableClasses = {
Plug: function (object) {
// this plugs push plug // can have multiple plugs
if ("undefined" === typeof this.registered_parts.Plugs) {
this.registered_parts.Plugs = [];
}
this.registered_parts.Plugs.push(object.id);
},
};
this.linkRegisteredParts = function Drainable_linkRegisteredParts() {
// link plugs to drain
if ("undefined" !== typeof this.registered_parts.Plugs) {
var drain = this; //.game.getAsset(this.registered_parts.Drain);
this.registered_parts.Plugs.forEach(function (id) {
var plug = this.game.getAsset(id);
// console.warn("Drain linkRegisteredParts 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("plug", asset, "dov")) {
console.warn("DRAIN allowVerbWithAsset");
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);
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().appendOutput(msg);
}
}
return;
}
}
adventurejs.Drain = Drain;
})();