Pre-release
AdventureJS Docs Downloads
Score: 0 Moves: 0
// 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 ||
      !direct_object.isDOV(verb)
    )
      return [];

    this.game.log(
      "L1489",
      "log",
      "high",
      "findNestedIndirectObjects.js >  " + verb + " " + direct_object.name,
      "Game"
    );

    var indirect_objects = [];
    // classes_that_can_verb_this
    var direct_object_classes = direct_object.dov[verb].with_classes;
    var direct_object_assets = direct_object.dov[verb].with_assets;

    // get class instances in player
    // findNestedAssetsWithClass calls getAllNestedContents
    if (direct_object_classes) {
      for (var i = 0; i < direct_object_classes.length; i++) {
        var classed_ids = this.findNestedAssetsWithClass(
          direct_object_classes[i]
        );
        for (var id = 0; id < classed_ids.length; id++) {
          indirect_objects.push(classed_ids[id]);
        }
      }
    }

    // find direct_object_assets in tangible
    if (direct_object_assets) {
      for (var i = 0; i < direct_object_assets.length; i++) {
        var indirect_object = this.game.getAsset(direct_object_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]?.with_classes &&
        -1 !== inventory_item.iov[verb]?.with_classes.indexOf(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 (!asset.is.known) indirect_objects.splice(i);
      if (!asset.areAnscestorsKnown()) indirect_objects.splice(i);
    }

    return indirect_objects;
  };
})();