Pre-release
AdventureJS Docs Downloads
Score: 0 Moves: 0
// doVerbAction.js
(function () {
  /* global adventurejs A */
  var p = adventurejs.Asset.prototype;
  /**
   * Check if this asset has a general verb action or reaction
   * for the specified event, or if the asset has an action for
   * the specific asset. If either form is found, pass it to
   * getStringOrArrayOrFunction and return the results. If the
   * result returns false or null it will terminate the calling
   * verb's default behavior.
   * <br><br>
   * We look for actions in two forms:<br>
   * <li>Function properties such as <code>asset.doThisToThat()</code>
   * are called. If a function returns null or false, that effectively
   * ends the turn.</li>
   * <li>String properties such as <code>asset.do_this_to_that</code>
   * override the turn's default output.</li>
   * @memberOf adventurejs.Asset
   * @method adventurejs.Asset#doVerbAction
   * @param {string} action
   * @param {string} asset2 We use asset.name here instead of asset.id
   * in support of authors, because we're never asking them to deal in IDs,
   * only names. Hooks will only be defined by authors, so we let them use
   * asset.name as their identifier. We do however make an effort to see if
   * an id has been passed instead of a name, because Ivan.
   * @param {string} asset3
   * @param {object} params Arbitrary parameter object.
   * @return {Boolean}
   */
  p.doVerbAction = function Asset_doVerbAction({
    action,
    asset2,
    asset3,
    params = {},
    type = "Hook",
  } = {}) {
    // if we didn't receive an action, exit
    if (!action) return;

    if (asset3) {
      this.game.log(
        "L1459",
        "log",
        "high",
        `[doVerbAction.js] ${this.id}.${action}(${asset2.id ? asset2.id : asset2}, ${asset3.id ? asset3.id : asset3})`,
        type
      );

      this.game.debug(
        `D1442 | ${type} | <span class="ajs-tryfound">TRY</span> <span class="ajs-actor">${this.id}</span>.<span class="ajs-action">${action}(</span><span class="ajs-target">"${asset2.name ? asset2.name : asset2}", "${asset3.name ? asset3.name : asset3}"</span><span class="ajs-action">)</span>`
      );
    } else if (asset2) {
      this.game.log(
        "L1456",
        "log",
        "high",
        `[doVerbAction.js] ${this.id}.${action}(${asset2.id ? asset2.id : asset2})`,
        type
      );

      this.game.debug(
        `D1420 | ${type} | <span class="ajs-tryfound">TRY</span> <span class="ajs-actor">${this.id}</span>.<span class="ajs-action">${action}(</span><span class="ajs-target">"${asset2.name ? asset2.name : asset2}"</span><span class="ajs-action">)</span>`
      );
    } else {
      this.game.log(
        "L1476",
        "log",
        "high",
        `[doVerbAction.js] ${this.id}.${action}()`,
        type
      );

      this.game.debug(
        `D1415 | ${type} | <span class="ajs-tryfound">TRY</span> <span class="ajs-actor">${this.id}</span>.<span class="ajs-action">${action}(</span><span class="ajs-target">${""}</span><span class="ajs-action">)</span>`
      );
    }

    // in addition to checking for camel cased method properties,
    // we also look for alternative snake cased string properties
    const _action_ = A.camelToSnake(action);

    // if this hasn't got function or string, exit
    if (!this[action] && !this[_action_]) return;

    const input = this.game.getInput();

    if (asset2) {
      // if an asset was passed, disregard assets retrieved from input
      asset2 = asset2.class ? asset2 : this.game.getAsset(asset2);
      if (asset3) {
        asset3 = asset3.class ? asset3 : this.game.getAsset(asset3);
      }
    } else {
      asset2 = input.getAsset(2);
      asset3 = input.getAsset(3);
      if (!asset2) asset2 = this.game.getPlayer();
    }

    let _a = this[action] ? action : _action_;
    let _o = this[action] ? "(" : "[";
    let _c = this[action] ? ")" : "]";

    this.game.log(
      "L1038",
      "log",
      "high",
      `[doVerbAction.js] Asset.doVerbAction() FOUND ${this.id}.${_a}${_o}${asset2 ? asset2.id : ""}${asset2 && asset3 ? ", " : ""}${asset3 ? asset3.id : ""}${_c}`,
      "VerbAction"
    );

    //→ ↳
    this.game.debug(
      `D1383 | ${type} | <span class="ajs-tryfound">↳ FOUND</span> <span class="ajs-actor">${this.id}</span>.<span class="ajs-action">${_a}${_o}</span><span class="ajs-target">${asset2 ? '"' + asset2.name + '"' : ""}${asset2 && asset3 ? ", " : ""}${asset3 ? '"' + asset3.name + '"' : ""}</span><span class="ajs-action">${_c}</span>`
    );

    // is there a method at this[action]?
    if ("function" === typeof this[action]) {
      return this[action].call(this, { asset2, asset3, params });
    }

    // if no method was found at this[action]
    // is there an alt string at this[_action_]?
    if (this[_action_]) {
      // did author specify an output method?
      if (
        this[_action_].append ||
        this[_action_].prepend ||
        this[_action_].override
      ) {
        let method = this[_action_].append
          ? "append"
          : this[_action_].prepend
            ? "prepend"
            : "override";
        // console.warn(`this[_action_][method]`, this[_action_][method]);
        input[`${method}Output`](
          A.getSAF.call(this.game, this[_action_][method])
        );
      } else if (
        "string" === typeof this[_action_] ||
        Array.isArray(this[_action_]) ||
        "function" === typeof this[_action_]
      ) {
        input.overrideOutput(A.getSAF.call(this.game, this[_action_]));
      }
    } // this[_action_]

    // is there a method at this[action][asset2]?
    if (this[action] && "function" === typeof this[action][asset2.name]) {
      return this[action][asset2.name].call(this, { asset2, asset3, params });
    }

    // if no method was found at this[action][asset2]
    // is there an alt string at this[_action_][asset2]?
    if (this[_action_] && asset2 && this[_action_][asset2.name]) {
      if (
        this[_action_][asset2.name].append ||
        this[_action_][asset2.name].prepend ||
        this[_action_][asset2.name].override
      ) {
        let method = this[_action_][asset2.name].append
          ? "append"
          : this[_action_][asset2.name].prepend
            ? "prepend"
            : "override";
        // console.warn(
        //   `this[_action_][asset2.name][method]`,
        //   this[_action_][asset2.name][method]
        // );
        input[`${method}Output`](
          A.getSAF.call(this.game, this[_action_][asset2.name][method])
        );
      } else if (
        "string" === typeof this[_action_][asset2.name] ||
        Array.isArray(this[_action_][asset2.name]) ||
        "function" === typeof this[_action_][asset2.name]
      ) {
        input.overrideOutput(
          A.getSAF.call(this.game, this[_action_][asset2.name])
        );
        return;
      }
    }

    // is there a method at this[action][asset2][asset3]?
    if (
      this[action] &&
      asset2 &&
      this[action][asset2.name] &&
      asset3 &&
      "function" === typeof this[action][asset2.name][asset3.name]
    ) {
      return this[action][asset2.name][asset3.name].call(this, {
        asset2,
        asset3,
        params,
      });
    }

    // if no method was found at this[action][asset2][asset3]
    // is there an alt string at this[_action_][asset2][asset3]?
    if (
      this[_action_] &&
      asset2 &&
      this[_action_][asset2.name] &&
      asset3 &&
      this[_action_][asset2.name][asset3.name]
    ) {
      if (
        this[_action_][asset2.name][asset3.name].append ||
        this[_action_][asset2.name][asset3.name].prepend ||
        this[_action_][asset2.name][asset3.name].override
      ) {
        let method = this[_action_][asset2.name][asset3.name].append
          ? "append"
          : this[_action_][asset2.name][asset3.name].prepend
            ? "prepend"
            : "override";
        // console.warn(
        //   `this[_action_][asset2.name][asset3.name][method]`,
        //   this[_action_][asset2.name][asset3.name][method]
        // );
        input[`${method}Output`](
          A.getSAF.call(
            this.game,
            this[_action_][asset2.name][asset3.name][method]
          )
        );
      } else if (
        "string" === typeof this[_action_][asset2.name][asset3.name] ||
        Array.isArray(this[_action_][asset2.name][asset3.name]) ||
        "function" === typeof this[_action_][asset2.name][asset3.name]
      ) {
        input.overrideOutput(
          A.getSAF.call(this.game, this[_action_][asset2.name][asset3.name])
        );
        return;
      }
    }

    return;
  };
})();