// Drainable.js
(function () {
/* global adventurejs A */
/**
* @ajspath adventurejs.Atom.Asset.Matter.Tangible.Thing.Container.LiquidContainer.Drainable
* @augments adventurejs.LiquidContainer
* @class adventurejs.Drainable
* @ajsconstruct MyGame.createAsset({ "class":"Drainable", "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.
* @ajscomponents SubstanceEmitter, GraduatedController, Drain, Plug
* @summary Ancestor class for Sinks and Bathtubs.
* @ajssubstancecontainer in
* @ajstangiblecontainer in
* @ajstangiblecontainer attached
* @ajsdemo PlumbingDemo, BasicSink, IntegratedSink, BasicBathtub, IntegratedBathtub, Scorecard
* @classdesc
* <p>
* <strong>Drainable</strong> is a subsclass of
* {@link adventurejs.Container|Container} /
* {@link adventurejs.LiquidContainer|LiquidContainer},
* and the ancestor class for
* {@link adventurejs.Sink|Sink} and
* {@link adventurejs.Bathtub|Bathtub} and other basins.
* You wouldn't construct a Drainable directly, but you can
* subclass it to create new types of Drainables.
* </p>
* <p>
* Drainables can be easily linked with
* {@link adventurejs.Faucet|Faucets},
* {@link adventurejs.Handle|Handles},
* {@link adventurejs.Drain|Drains} and
* {@link adventurejs.Plug|Plugs}
* through the use of the
* <code class="property">{@link adventurejs.Tangible#components|components}</code>
* property,
* a special convenience property that can be used to link some
* {@link adventurejs.Asset|Asset} classes to other Asset classes.
* To learn more about which classes can be linked with
* <code class="property">components</code>, see <a href="/doc/Tangibles_Components.html">Components</a>.
* </p>
**/
class Drainable extends adventurejs.LiquidContainer {
constructor(name, game_name) {
super(name, game_name);
this.class = "Drainable";
this.noun = "drainable";
this.plural = "drainables";
this.singlePluralPairs = [["drainable", "drainables"]];
this.is = new adventurejs.Drainable_Is("is", this.game_name, this.id);
this.unsetDOVs(["get", "take", "give", "put"]);
this.setDOVs([
"fill",
"empty",
"drink",
"pour",
// { turn: { with_nothing: true } },
{ turnOn: { with_nothing: true } },
{ turnOff: { with_nothing: true } },
]);
this.default_aspect = "in";
this.aspects.attached = new adventurejs.Aspect(
"attached",
this.game_name,
this.id
).set({
list_contents_in_examine: false,
list_contents_in_room: false,
know_contents_with_parent: true,
see_contents_with_parent: true,
player_can_add_assets_to_contents: false,
player_can_remove_assets_from_contents: false,
});
this.linkableClasses = {
Faucet: function (object) {
this.linked_components.Faucet = object.id;
// this faucet = faucet
// faucet sink = this
// what else does a sink need to know about a faucet?
// faucet is attached to sink
object.setPlace("attached", this.id);
object.aspects.in.vessel.target_id = this.id;
},
GraduatedController: function (object) {
// this faucets push faucet
// can have multiple handles
// faucet sink = this
// where do we ask about multiple inputs mixing?
// is each handle worth a fraction of max_volume_of_flow_per_turn?
if (
"undefined" === typeof this.linked_components.GraduatedControllers
) {
this.linked_components.GraduatedControllers = [];
}
this.linked_components.GraduatedControllers.push(object.id);
// handles are attached to sink... but don't need to be? shower handles/
object.control_target_id = this.id;
object.setPlace("attached", this.id);
},
Drain: function (object) {
this.linked_components.Drain = object.id;
// this drain = drain
// drain sink = this
// what else does a sink need to know about a drain?
// drain is attached to sink
object.setPlace("attached", this.id);
},
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() {
var drain;
// link handle(s) to faucet
if (
"undefined" !== typeof this.linked_components.Faucet &&
"undefined" !== typeof this.linked_components.GraduatedControllers
) {
var faucet = this.game.getAsset(this.linked_components.Faucet);
if (
"undefined" === typeof faucet.linked_components.GraduatedControllers
) {
faucet.linked_components.GraduatedControllers = [];
}
this.linked_components.GraduatedControllers.forEach(function (id) {
this.game.getAsset(id).control_target_id =
this.linked_components.Faucet;
faucet.linked_components.GraduatedControllers.push(id);
}, this);
}
// link drain to sink
if ("undefined" !== typeof this.linked_components.Drain) {
drain = this.game.getAsset(this.linked_components.Drain);
this.aspects.in.vessel.drain_id = drain.id;
} else {
drain = this;
}
// link plug(s) to drain
if ("undefined" !== typeof this.linked_components.Plugs) {
this.linked_components.Plugs.forEach(function (id) {
var plug = this.game.getAsset(id);
// drain is direct object, should have plug as indirect connection
drain.setVerbWithAsset("plug", plug, "dov");
// plug is indirect object, should have drain as direct connection
plug.setVerbWithAsset("plug", drain, "iov");
}, this);
}
}; // linkComponents
this.dov.turnOn.doAfterTry = function (params) {
var input = this.game.getInput();
var direct_object = input.getAsset(1);
var msg = "";
// does this drainable have controllers?
if (direct_object.linked_components?.GraduatedControllers?.length) {
var controllers =
direct_object.linked_components.GraduatedControllers;
let controller;
// does it have more than one controller?
if (controllers.length === 1) {
controller = this.game.getAsset(controllers[0]);
}
if (controllers.length > 1) {
for (let n in controllers) {
let c = this.game.getAsset(controllers[n]);
if (c.current_position === 0) {
controller = c;
break;
// can_turn_on = true;
}
}
}
if (!controller || controller.current_position !== 0) {
this.game.debug(
`Dxxxx | ${this.name}.js | all controllers are on `
);
msg += `${direct_object.Articlename} is already on. `;
this.handleFailure(msg);
return false;
}
// var rand = Math.floor(Math.random() * controllers.length);
// var controller = this.game.getAsset(controllers[rand]);
input.setAsset(1, controller);
input.allow_circular_verb = true;
return this.game.dictionary.doVerb("turnOn");
}
// does this drainable have a faucet?
else if (direct_object.linked_components?.Faucet) {
var faucet = this.game.getAsset(
direct_object.linked_components.Faucet
);
input.setAsset(1, faucet);
input.allow_circular_verb = true;
return this.game.dictionary.doVerb("turnOn");
}
// no controllers or faucets so just let the verb act on it
else {
this.game.debug(
`D1847 | Drainable.js | ${direct_object.id} has no GraduatedControllers or Faucet`
);
// msg += `{We} can't turn on ${direct_object.articlename}. `;
// this.game.dictionary.verbs[params.verb].handleFailure(msg);
// return null;
}
};
this.dov.turnOff.doAfterTry = function (params) {
var input = this.game.getInput();
var direct_object = input.getAsset(1);
// does this drainable have controllers?
if (direct_object.linked_components?.GraduatedControllers?.length) {
var controllers =
direct_object.linked_components.GraduatedControllers;
var controller_count = controllers.length;
var controllers_to_turn_off_count = 0;
for (var c = 0; c < controller_count; c++) {
var controller = this.game.getAsset(controllers[c]);
if (0 < controller.current_position) {
controllers_to_turn_off_count++;
input.setAsset(1, controller);
input.allow_circular_verb = true;
this.game.dictionary.doVerb("turnOff");
}
}
if (0 === controllers_to_turn_off_count) {
var msg = direct_object.Articlename + " isn't on. ";
this.game.dictionary.verbs[params.verb].handleFailure(msg);
}
return null;
}
// does this drainable have a faucet(s)?
else if (direct_object.linked_components?.Faucet) {
var faucet = this.game.getAsset(
direct_object.linked_components.Faucet
);
input.setAsset(1, faucet);
input.allow_circular_verb = true;
return this.game.dictionary.doVerb("turnOff");
}
// no controllers or faucets so just let the verb act on it
else {
this.game.debug(
`D1846 | Drainable.js | ${direct_object.id} has no GraduatedControllers or Faucet`
);
// msg += `{We} can't turn off ${direct_object.articlename}. `;
// this.game.dictionary.verbs[params.verb].handleFailure(msg);
// return null;
}
};
}
}
adventurejs.Drainable = Drainable;
})();