// findNestedIndirectObjects.js
(function () {
/* global adventurejs A */
var p = adventurejs.Tangible.prototype;
/**
* Returns a list of assets nested in this asset, if any, that can perform
* the specified verb upon the specified asset as defined in the
* target asset.dov[verb].with_assets/with_classes
* property. Works with verbs including open & close, pick,
* lock & unlock, and seal & unseal.
* @memberOf adventurejs.Tangible
* @method adventurejs.Tangible#findNestedIndirectObjects
* @param {String} verb The name of a verb.
* @param {Object|String} direct_object An asset or asset ID of a direct object that the player has tried to perform an indirect verb on.
* @returns {Array} An array of indirect objects, if found.
*/
p.findNestedIndirectObjects = function Tangible_findNestedIndirectObjects(
verb,
direct_object
) {
// we might've received a string
if ("string" === typeof direct_object) {
direct_object = this.game.getAsset(direct_object);
}
if (!verb || !this.game.dictionary.verbs[verb] || !direct_object) {
return [];
}
verb = this.game.dictionary.verbs[verb];
if (!direct_object.isDOV(verb) && !verb.allow_iov_on_iov) {
return [];
}
this.game.log(
"L1489",
"log",
"high",
`[findNestedIndirectObjects.js] ${verb.name} ${direct_object.name}`,
"Game"
);
var subject = this.game.getInput().getSubject();
var indirect_objects = [];
let dov_classes = [];
let dov_assets = [];
if (direct_object.isDOV(verb)) {
dov_classes = dov_classes.concat(
direct_object.dov[verb.name].with_classes
);
dov_assets = dov_assets.concat(direct_object.dov[verb.name].with_assets);
}
// account for verbs like write and type which treat
// both tool and target as indirect objects
if (verb.allow_iov_on_iov) {
dov_classes = dov_classes.concat(
direct_object.iov[verb.name].with_classes
);
dov_assets = dov_assets.concat(direct_object.iov[verb.name].with_assets);
}
// get class instances in player
// findNestedAssetsWithClass calls getAllNestedContents
if (dov_classes) {
for (var i = 0; i < dov_classes.length; i++) {
var classed_ids = this.findNestedAssetsWithClass(dov_classes[i]);
for (var id = 0; id < classed_ids.length; id++) {
indirect_objects.push(classed_ids[id]);
}
}
}
// find dov_assets in tangible
if (dov_assets) {
for (var i = 0; i < dov_assets.length; i++) {
var indirect_object = this.game.getAsset(dov_assets[i]);
if (indirect_object && indirect_object.isWithin(this))
indirect_objects.push(indirect_object);
}
}
// classes_this_can_verb
var inventory = this.getAllNestedContents();
for (var i = 0; i < inventory.length; i++) {
var inventory_item = this.game.getAsset(inventory[i]);
if (
inventory_item.iov[verb.name]?.with_classes &&
inventory_item.iov[verb.name].with_classes.includes(direct_object.id)
) {
var dupe = false;
for (var asset in indirect_objects) {
if (indirect_objects[asset].id === inventory_item.id) dupe = true;
}
if (!dupe) indirect_objects.push(indirect_object);
}
}
// subtract unknown / unreachable items
for (var i = indirect_objects.length - 1; i > -1; i--) {
// it's possible for player to not know about items in inventory
var asset = indirect_objects[i];
if (!subject.knowsAbout(asset)) indirect_objects.splice(i);
if (!asset.areAnscestorsKnown()) indirect_objects.splice(i);
}
return indirect_objects;
};
})();