You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

206 lines
4.6 KiB

  1. module.exports = {
  2. type: 'dialogue',
  3. states: {},
  4. sourceStates: {},
  5. trigger: null,
  6. init: function (blueprint) {
  7. this.states = blueprint.config;
  8. },
  9. destroy: function () {
  10. if (this.trigger)
  11. this.trigger.destroyed = true;
  12. },
  13. talk: function (msg) {
  14. if (!msg)
  15. return false;
  16. let target = msg.target;
  17. if ((target === null) && (!msg.targetName))
  18. return false;
  19. if ((target !== null) && (target.id === null)) {
  20. target = this.obj.instance.objects.objects.find(o => o.id === target);
  21. if (!target)
  22. return false;
  23. } else if (msg.targetName !== null) {
  24. target = this.obj.instance.objects.objects.find(o => ((o.name) && (o.name.toLowerCase() === msg.targetName.toLowerCase())));
  25. if (!target)
  26. return false;
  27. }
  28. if (!target.dialogue)
  29. return false;
  30. //Auto-discover faction
  31. if ((target.trade) && (target.trade.faction))
  32. this.obj.reputation.discoverFaction(target.trade.faction.id);
  33. let state = target.dialogue.getState(this.obj, msg.state);
  34. if (!state) {
  35. this.obj.syncer.set(true, 'dialogue', 'state', null);
  36. return false;
  37. }
  38. this.obj.syncer.set(true, 'dialogue', 'state', state);
  39. },
  40. stopTalk: function () {
  41. this.obj.syncer.set(true, 'dialogue', 'state', null);
  42. },
  43. getState: function (sourceObj, state) {
  44. state = state || 1;
  45. //Goto?
  46. if ((state + '').indexOf('.') > -1) {
  47. let config = this.states[(state + '').split('.')[0]];
  48. if (!config)
  49. return false;
  50. let goto = (config.options[state] || {}).goto;
  51. if (goto instanceof Array) {
  52. let gotos = [];
  53. goto.forEach(function (g) {
  54. let rolls = (g.chance * 100) || 100;
  55. for (let i = 0; i < rolls; i++)
  56. gotos.push(g.number);
  57. });
  58. state = gotos[~~(Math.random() * gotos.length)];
  59. } else
  60. state = goto;
  61. }
  62. this.sourceStates[sourceObj.id] = state;
  63. if (!this.states) {
  64. console.log(sourceObj.name, this.obj.name, state);
  65. return null;
  66. }
  67. let stateConfig = this.states[state];
  68. if (!stateConfig)
  69. return null;
  70. let useMsg = stateConfig.msg;
  71. if (stateConfig.cpn) {
  72. let cpn = sourceObj[stateConfig.cpn];
  73. let newArgs = extend(true, [], stateConfig.args);
  74. newArgs.push(this.obj);
  75. let result = cpn[stateConfig.method].apply(cpn, newArgs);
  76. if (stateConfig.goto) {
  77. if (result)
  78. return this.getState(sourceObj, stateConfig.goto.success);
  79. return this.getState(sourceObj, stateConfig.goto.failure);
  80. }
  81. if (result) {
  82. useMsg = extend(true, [], useMsg);
  83. useMsg[0].msg = result;
  84. } else
  85. return null;
  86. } else if (stateConfig.method) {
  87. let methodResult = stateConfig.method.call(this.obj, sourceObj);
  88. if (methodResult) {
  89. useMsg = extend(true, [], useMsg);
  90. useMsg[0].msg = methodResult;
  91. }
  92. if (!useMsg)
  93. return;
  94. }
  95. let result = {
  96. id: this.obj.id,
  97. msg: null,
  98. from: this.obj.name,
  99. options: []
  100. };
  101. if (useMsg instanceof Array) {
  102. let msgs = [];
  103. useMsg.forEach(function (m, i) {
  104. let rolls = (m.chance * 100) || 100;
  105. for (let j = 0; j < rolls; j++) {
  106. msgs.push({
  107. msg: m,
  108. index: i
  109. });
  110. }
  111. });
  112. let pick = msgs[~~(Math.random() * msgs.length)];
  113. result.msg = pick.msg.msg;
  114. result.options = useMsg[pick.index].options;
  115. } else {
  116. result.msg = useMsg;
  117. result.options = stateConfig.options;
  118. }
  119. if (!(result.options instanceof Array)) {
  120. if (result.options[0] === '$')
  121. result.options = this.states[result.options.replace('$', '')].options;
  122. result.options = Object.keys(result.options);
  123. }
  124. result.options = result.options
  125. .map(function (o) {
  126. let gotoState = this.states[(o + '').split('.')[0]];
  127. let picked = gotoState.options[o];
  128. if (!picked)
  129. return null;
  130. else if (picked.prereq) {
  131. let doesConform = picked.prereq(sourceObj);
  132. if (!doesConform)
  133. return null;
  134. }
  135. return {
  136. id: o,
  137. msg: picked.msg
  138. };
  139. }, this)
  140. .filter(o => !!o);
  141. result.options.push({
  142. msg: 'Goodbye',
  143. id: 999
  144. });
  145. return result;
  146. },
  147. simplify: function (self) {
  148. return {
  149. type: 'dialogue'
  150. };
  151. },
  152. //These don't belong here, but I can't figure out where to put them right now
  153. //They are actions that can be performed while chatting with someone
  154. teleport: function (msg) {
  155. this.obj.syncer.set(true, 'dialogue', 'state', null);
  156. let portal = extend(true, {}, require('./portal'), msg);
  157. portal.collisionEnter(this.obj);
  158. },
  159. getItem: function (msg, source) {
  160. let inventory = this.obj.inventory;
  161. let exists = inventory.items.find(i => (i.name === msg.item.name));
  162. if (!exists) {
  163. inventory.getItem(msg.item);
  164. return msg.successMsg || false;
  165. } return msg.existsMsg || false;
  166. }
  167. };