// doVerbAction.js
(function () {
/* global AdventureJS A */
var p = AdventureJS.Assets.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
* getStringArrayFunction 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.Assets.Asset
* @method AdventureJS.Assets.Asset#doVerbAction
* @param {string} action The name of this action.
* @param {string} target Target is relative. Depending on whether
* "this" is a direct or indirect object, the target may be an
* indirect or direct object. The target is the other object in the
* sentence, regardless of where in the sentence it lies. We pass
* asset.name here instead of asset.id – though ids are also
* accepted – because this is an author facing system and we've
* trained authors to work with names rather than IDs. 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} target2 An optional second target. In a sentence
* with three nouns, this would be the last noun. For example,
* in "throw rock at troll with slingshot", the slingshot would
* be target2.
* @param {object} params Arbitrary parameter object.
* @return {Boolean}
*/
p.doVerbAction = function Asset_doVerbAction({
action,
params = {},
type = "Hook",
target,
target2,
} = {}) {
// if we didn't receive an action, exit
if (!action) return;
let target_key = "";
let target2_key = "";
// in addition to checking for camel cased method properties,
// we also look for alternative snake cased string properties
// const _action_ = A.FX.camelToSnake(action);
// if this hasn't got function or string, exit
// if (!this[action] && !this[_action_]) return;
if ("undefined" === typeof this[action] || null === this[action]) return;
const input = this.game.getInput();
if (target) {
// if an asset was passed, disregard assets retrieved from input
target = target.class ? target : this.game.getAsset(target);
if (target2) {
target2 = target2.class ? target2 : this.game.getAsset(target2);
}
} else {
target = input.getAsset(2);
target2 = input.getAsset(3);
if (!target) target = this.game.getPlayer();
}
let target_is_player = target && target.id === this.game.world._player;
//
if (target2) {
this.game.log(
"L1459",
"log",
"high",
`[doVerbAction.js] TRY ${type}: ${this.id}.${action}(${target.id ? target.id : target}, ${target2.id ? target2.id : target2})`,
type
);
this.game.debug(
`D1442`,
`${type}`,
`<span class="ajs-tryfound">HOOK</span> <span class="ajs-actor">${this.id}</span>.<span class="ajs-action">${action}(</span><span class="ajs-target">"${target.name ? target.name : target}", "${target2.name ? target2.name : target2}"</span><span class="ajs-action">)</span>`
);
} else if (target) {
this.game.log(
"L1456",
"log",
"high",
`[doVerbAction.js] TRY ${type}: ${this.id}.${action}(${target.id ? target.id : target})`,
type
);
this.game.debug(
`D1420`,
`${type}`,
`<span class="ajs-tryfound">HOOK</span> <span class="ajs-actor">${this.id}</span>.<span class="ajs-action">${action}(</span><span class="ajs-target">"${target.name ? target.name : target}"</span><span class="ajs-action">)</span>`
);
} else {
this.game.log(
"L1476",
"log",
"high",
`[doVerbAction.js] TRY ${type}: ${this.id}.${action}()`,
type
);
this.game.debug(
`D1415`,
`${type}`,
`<span class="ajs-tryfound">HOOK</span> <span class="ajs-actor">${this.id}</span>.<span class="ajs-action">${action}(</span><span class="ajs-target">${""}</span><span class="ajs-action">)</span>`
);
}
//
let _a = action;
let _o = "(";
let _c = ")";
this.game.log(
"L1394",
"log",
"high",
`[doVerbAction.js] ↳ FOUND ${type}: ${this.id}.${_a}${_o}${target ? target.id : ""}${target && target2 ? ", " : ""}${target2 ? target2.id : ""}${_c}`,
`${type}`
);
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">${target ? '"' + target.name + '"' : ""}${target && target2 ? ", " : ""}${target2 ? '"' + target2.name + '"' : ""}</span><span class="ajs-action">${_c}</span>`
);
// is there a method at this[action]?
if (this[action]) {
const value = this[action];
if (typeof value === "function") {
return value.call(this, {
action,
target,
target2,
params,
type,
self: this,
});
} else if (A.FX.isSAF(value)) {
return A.FX.getSAF.call(this.game, value);
}
}
// --------------------------------------------------
// is there a method at this[action][target]?
// --------------------------------------------------
if (target) {
// look for key with name or id
target_key = [target.name, target.id].find((key) => {
const value = this[action]?.[key];
// look for string array function under name or id
return A.FX.isSAF(value);
});
}
if (target_key) {
const value = this[action][target_key];
if (typeof value === "function") {
return value.call(this, {
action,
target,
target2,
params,
type,
self: this,
});
} else {
return A.FX.getSAF.call(this.game, value);
}
}
// --------------------------------------------------
// @TODO testing out using "player" as an identifier
// have not carried this through remaining blocks
// --------------------------------------------------
if (target_is_player && this[action]?.player) {
const value = this[action].player;
if (typeof value === "function") {
return value.call(this, {
action,
target,
target2,
params,
type,
self: this,
});
} else {
return A.FX.getSAF.call(this.game, value);
}
}
// --------------------------------------------------
// is there a method at this[action][target][target2]?
// --------------------------------------------------
if (target && target2) {
target_key = [target.name, target.id].find(
(key) => "undefined" !== typeof this[action]?.[key]
);
if (target_key) {
target2_key = [target2.name, target2.id].find((key) => {
const value = this[action][target_key]?.[key];
// look for string array function under name or id
return A.FX.isSAF(value);
});
}
}
if (target_key && target2_key) {
const value = this[action][target.name][target2.name];
if (typeof value === "function") {
return value.call(this, {
action,
target,
target2,
params,
type,
self: this,
});
} else {
return A.FX.getSAF.call(this.game, value);
}
}
return;
};
})();