No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 

218 líneas
4.9 KiB

  1. const recipes = require('../config/recipes/recipes');
  2. const generator = require('../items/generator');
  3. const { applyItemStats } = require('./equipment/helpers');
  4. const buildRecipe = require('./workbench/buildRecipe');
  5. const buildMaterials = require('./workbench/buildMaterials');
  6. const buildPickedItems = require('./workbench/buildPickedItems');
  7. module.exports = {
  8. type: 'workbench',
  9. craftType: null,
  10. init: function (blueprint) {
  11. this.craftType = blueprint.type;
  12. this.obj.instance.objects.buildObjects([{
  13. properties: {
  14. x: this.obj.x - 1,
  15. y: this.obj.y - 1,
  16. width: 3,
  17. height: 3,
  18. cpnNotice: {
  19. actions: {
  20. enter: {
  21. cpn: 'workbench',
  22. method: 'enterArea',
  23. targetId: this.obj.id,
  24. args: []
  25. },
  26. exit: {
  27. cpn: 'workbench',
  28. method: 'exitArea',
  29. targetId: this.obj.id,
  30. args: []
  31. }
  32. }
  33. }
  34. }
  35. }]);
  36. },
  37. exitArea: function (obj) {
  38. if (!obj.player)
  39. return;
  40. obj.syncer.setArray(true, 'serverActions', 'removeActions', {
  41. key: 'u',
  42. action: {
  43. targetId: this.obj.id,
  44. cpn: 'workbench',
  45. method: 'access'
  46. }
  47. });
  48. this.obj.instance.syncer.queue('onCloseWorkbench', null, [obj.serverId]);
  49. },
  50. enterArea: function (obj) {
  51. if (!obj.player)
  52. return;
  53. let msg = `Press U to access the ${this.obj.name}`;
  54. obj.syncer.setArray(true, 'serverActions', 'addActions', {
  55. key: 'u',
  56. name: 'access workbench',
  57. action: {
  58. targetId: this.obj.id,
  59. cpn: 'workbench',
  60. method: 'open'
  61. }
  62. });
  63. this.obj.instance.syncer.queue('onGetAnnouncement', {
  64. src: this.obj.id,
  65. msg: msg
  66. }, [obj.serverId]);
  67. },
  68. open: async function (msg) {
  69. if (!msg.has('sourceId'))
  70. return;
  71. let obj = this.obj.instance.objects.objects.find(o => o.serverId === msg.sourceId);
  72. if ((!obj) || (!obj.player))
  73. return;
  74. let thisObj = this.obj;
  75. if ((Math.abs(thisObj.x - obj.x) > 1) || (Math.abs(thisObj.y - obj.y) > 1))
  76. return;
  77. const unlocked = await io.getAsync({
  78. key: obj.name,
  79. table: 'recipes',
  80. isArray: true
  81. });
  82. this.obj.instance.syncer.queue('onOpenWorkbench', {
  83. workbenchId: this.obj.id,
  84. name: this.obj.name,
  85. recipes: recipes.getList(this.craftType, unlocked)
  86. }, [obj.serverId]);
  87. },
  88. getRecipe: function (msg) {
  89. let obj = this.obj.instance.objects.objects.find(o => o.serverId === msg.sourceId);
  90. if ((!obj) || (!obj.player))
  91. return;
  92. const sendRecipe = buildRecipe(this.craftType, obj, msg);
  93. this.resolveCallback(msg, sendRecipe);
  94. },
  95. craft: function (msg) {
  96. const { craftType, obj: { instance: { objects: { objects } } } } = this;
  97. const { name: recipeName, sourceId } = msg;
  98. const crafter = objects.find(o => o.serverId === sourceId);
  99. if (!crafter || !crafter.player)
  100. return;
  101. const recipe = recipes.getRecipe(craftType, recipeName);
  102. if (!recipe)
  103. return;
  104. const { needItems } = recipe;
  105. const { syncer, inventory, equipment, spellbook } = crafter;
  106. const materials = buildMaterials(crafter, recipe, msg);
  107. const pickedItems = buildPickedItems(crafter, recipe, msg);
  108. const canCraft = (
  109. !materials.some(m => m.noHaveEnough) &&
  110. pickedItems.length === needItems.length &&
  111. !pickedItems.some(i => !i)
  112. );
  113. if (!canCraft)
  114. return;
  115. materials.forEach(m => inventory.destroyItem(m.id, m.needQuantity));
  116. let resultMsg = null;
  117. if (recipe.craftAction) {
  118. pickedItems.forEach(p => {
  119. if (p.eq)
  120. applyItemStats(crafter, p, false);
  121. });
  122. const oldSlots = pickedItems.map(p => p.slot);
  123. resultMsg = recipe.craftAction(crafter, pickedItems);
  124. pickedItems.forEach((p, i) => {
  125. if (!p.eq)
  126. return;
  127. applyItemStats(crafter, p, true);
  128. if (p.slot !== oldSlots[i])
  129. equipment.unequip(p.id);
  130. spellbook.calcDps();
  131. pickedItems.forEach(item => syncer.setArray(true, 'inventory', 'getItems', inventory.simplifyItem(item)));
  132. });
  133. equipment.unequipAttrRqrGear();
  134. }
  135. if (recipe.item || recipe.items) {
  136. const outputItems = recipe.item ? [ recipe.item ] : recipe.items;
  137. outputItems.forEach(itemBpt => {
  138. let item = null;
  139. if (itemBpt.generate)
  140. item = generator.generate(itemBpt);
  141. else
  142. item = extend({}, itemBpt);
  143. if (item.description)
  144. item.description += `<br /><br />(Crafted by ${crafter.name})`;
  145. else
  146. item.description = `<br /><br />(Crafted by ${crafter.name})`;
  147. const quantity = item.quantity;
  148. if (quantity && quantity.push)
  149. item.quantity = quantity[0] + ~~(Math.random() * (quantity[1] - quantity[0]));
  150. crafter.inventory.getItem(item);
  151. });
  152. }
  153. this.resolveCallback(msg, {
  154. resultMsg,
  155. recipe: buildRecipe(craftType, crafter, msg)
  156. });
  157. },
  158. resolveCallback: function (msg, result) {
  159. let callbackId = (msg.has('callbackId')) ? msg.callbackId : msg;
  160. result = result || [];
  161. if (!callbackId)
  162. return;
  163. process.send({
  164. module: 'atlas',
  165. method: 'resolveCallback',
  166. msg: {
  167. id: callbackId,
  168. result: result
  169. }
  170. });
  171. }
  172. };