|
- module.exports = {
- type: 'dialogue',
-
- states: {},
- sourceStates: {},
-
- trigger: null,
-
- init: function (blueprint) {
- this.states = blueprint.config;
- },
-
- destroy: function () {
- if (this.trigger)
- this.trigger.destroyed = true;
- },
-
- talk: async function (msg) {
- if (!msg)
- return false;
-
- let target = msg.target;
-
- if (!target && !msg.targetName)
- return false;
-
- if (target && !target.id) {
- target = this.obj.instance.objects.objects.find(o => o.id === target);
- if (!target)
- return false;
- } else if (msg.targetName) {
- target = this.obj.instance.objects.objects.find(o => ((o.name) && (o.name.toLowerCase() === msg.targetName.toLowerCase())));
- if (!target)
- return false;
- }
-
- if (!target.dialogue)
- return false;
-
- //Auto-discover faction
- if ((target.trade) && (target.trade.faction))
- this.obj.reputation.discoverFaction(target.trade.faction.id);
-
- let state = await target.dialogue.getState(this.obj, msg.state);
- if (!state) {
- this.obj.syncer.set(true, 'dialogue', 'state', null);
- return false;
- }
-
- this.obj.syncer.set(true, 'dialogue', 'state', state);
- },
-
- stopTalk: function () {
- this.obj.syncer.set(true, 'dialogue', 'state', null);
- },
-
- /* eslint-disable-next-line max-lines-per-function */
- getState: async function (sourceObj, state = 1) {
- let result = null;
- if ((state + '').indexOf('.') > -1) {
- let config = this.states[(state + '').split('.')[0]];
- if (!config)
- return false;
-
- let goto = (config.options[state] || {}).goto;
- if (goto instanceof Array) {
- let gotos = [];
- goto.forEach(function (g) {
- let rolls = (g.chance * 100) || 100;
- for (let i = 0; i < rolls; i++)
- gotos.push(g.number);
- });
-
- state = gotos[~~(Math.random() * gotos.length)];
- } else
- state = goto;
- }
-
- this.sourceStates[sourceObj.id] = state;
-
- if (!this.states)
- return null;
-
- let stateConfig = this.states[state];
- if (!stateConfig)
- return null;
-
- let useMsg = stateConfig.msg;
- if (stateConfig.cpn) {
- let cpn = sourceObj[stateConfig.cpn];
- let newArgs = extend([], stateConfig.args);
- newArgs.push(this.obj);
- result = cpn[stateConfig.method].apply(cpn, newArgs);
-
- if (stateConfig.goto) {
- if (result)
- return await this.getState(sourceObj, stateConfig.goto.success);
-
- return await this.getState(sourceObj, stateConfig.goto.failure);
- }
- if (result) {
- useMsg = extend([], useMsg);
- useMsg[0].msg = result;
- } else
- return null;
- } else if (stateConfig.method) {
- let methodResult = await stateConfig.method.call(this.obj, sourceObj);
- if (methodResult) {
- useMsg = extend([], useMsg);
- useMsg[0].msg = methodResult;
- }
-
- if (!useMsg)
- return;
- }
-
- result = {
- id: this.obj.id,
- msg: null,
- from: this.obj.name,
- options: []
- };
-
- if (useMsg instanceof Array) {
- let msgs = [];
- useMsg.forEach(function (m, i) {
- let rolls = (m.chance * 100) || 100;
- for (let j = 0; j < rolls; j++) {
- msgs.push({
- msg: m,
- index: i
- });
- }
- });
-
- let pick = msgs[~~(Math.random() * msgs.length)];
-
- result.msg = pick.msg.msg;
- result.options = useMsg[pick.index].options;
- } else {
- result.msg = useMsg;
- result.options = stateConfig.options;
- }
-
- if (!(result.options instanceof Array)) {
- if (result.options[0] === '$')
- result.options = this.states[result.options.replace('$', '')].options;
-
- result.options = Object.keys(result.options);
- }
-
- result.options = result.options
- .map(function (o) {
- let gotoState = this.states[(o + '').split('.')[0]];
- let picked = gotoState.options[o];
-
- if (!picked)
- return null;
- else if (picked.prereq) {
- let doesConform = picked.prereq(sourceObj);
- if (!doesConform)
- return null;
- }
-
- return {
- id: o,
- msg: picked.msg
- };
- }, this)
- .filter(o => !!o);
-
- result.options.push({
- msg: 'Goodbye',
- id: 999
- });
-
- return result;
- },
-
- simplify: function (self) {
- return {
- type: 'dialogue'
- };
- },
-
- //These don't belong here, but I can't figure out where to put them right now
- //They are actions that can be performed while chatting with someone
- teleport: function (msg) {
- this.obj.syncer.set(true, 'dialogue', 'state', null);
-
- let portal = extend({}, require('./portal'), msg);
- portal.collisionEnter(this.obj);
- },
-
- getItem: function (msg, source) {
- let inventory = this.obj.inventory;
- let exists = inventory.items.find(i => (i.name === msg.item.name));
- if (!exists) {
- inventory.getItem(msg.item);
- return msg.successMsg || false;
- } return msg.existsMsg || false;
- }
- };
|