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.

195 lines
4.8 KiB

  1. let animations = require('../config/animations');
  2. let itemGenerator = require('../items/generator');
  3. module.exports = {
  4. build: function (mob, blueprint, scaleDrops, type, zoneName) {
  5. mob.instance.eventEmitter.emit('onBeforeBuildMob', zoneName, mob.name.toLowerCase(), blueprint);
  6. let typeDefinition = blueprint[type] || blueprint;
  7. let drops = typeDefinition.drops;
  8. mob.isMob = true;
  9. mob.scaleDrops = scaleDrops;
  10. if (blueprint.nonSelectable)
  11. mob.nonSelectable = true;
  12. mob.addComponent('effects');
  13. if (type) {
  14. if (type != 'regular') {
  15. mob.effects.addEffect({
  16. type: type
  17. });
  18. mob['is' + type[0].toUpperCase() + type.substr(1)] = true;
  19. mob.baseName = mob.name;
  20. mob.name = typeDefinition.name || mob.baseName;
  21. if (typeDefinition.sheetName)
  22. mob.sheetName = typeDefinition.sheetName;
  23. if (typeDefinition.cell != null)
  24. mob.cell = typeDefinition.cell;
  25. }
  26. }
  27. mob.addComponent('stats', {
  28. values: {
  29. level: blueprint.level
  30. }
  31. });
  32. let cpnMob = mob.addComponent('mob');
  33. cpnMob.walkDistance = blueprint.walkDistance;
  34. cpnMob.hpMult = blueprint.hpMult || typeDefinition.hpMult;
  35. cpnMob.dmgMult = blueprint.dmgMult || typeDefinition.dmgMult;
  36. cpnMob.grantRep = blueprint.grantRep;
  37. cpnMob.deathRep = blueprint.deathRep;
  38. let spells = extend(true, [], blueprint.spells);
  39. spells.forEach(function (s) {
  40. if (!s.animation) {
  41. if ((mob.sheetName == 'mobs') && (animations.mobs[mob.cell]))
  42. s.animation = 'basic';
  43. }
  44. });
  45. mob.addComponent('spellbook', {
  46. spells: spells,
  47. dmgMult: typeDefinition.dmgMult
  48. });
  49. let attackable = blueprint.attackable;
  50. if ((attackable === undefined) || (attackable === true)) {
  51. mob.addComponent('aggro', {
  52. faction: blueprint.faction
  53. });
  54. }
  55. mob.addComponent('equipment');
  56. mob.addComponent('inventory', drops);
  57. mob.inventory.inventorySize = -1;
  58. mob.inventory.dailyDrops = blueprint.dailyDrops;
  59. if (this.zone) {
  60. let chats = this.zone.chats;
  61. if ((chats) && (chats[mob.name.toLowerCase()])) {
  62. mob.addComponent('chatter', {
  63. chats: chats[mob.name.toLowerCase()]
  64. });
  65. }
  66. let dialogues = this.zone.dialogues;
  67. if ((dialogues) && (dialogues[mob.name.toLowerCase()])) {
  68. mob.addComponent('dialogue', {
  69. config: dialogues[mob.name.toLowerCase()]
  70. });
  71. }
  72. }
  73. if ((blueprint.properties) && (blueprint.properties.cpnTrade))
  74. mob.addComponent('trade', blueprint.properties.cpnTrade);
  75. this.scale(mob, blueprint.level);
  76. },
  77. scale: function (mob, level) {
  78. if ((mob.aggro) && (mob.aggro.list > 0))
  79. return;
  80. let drops = mob.inventory.blueprint || {};
  81. let statValues = mob.stats.values;
  82. let preferStat = ['str', 'dex', 'int'][~~(Math.random() * 3)];
  83. let elementType = [null, 'poison', 'frost', 'fire', 'holy', 'arcane'][~~(Math.random() * 6)];
  84. mob.equipment.unequipAll();
  85. mob.inventory.clear();
  86. let hp = level * 32.7;
  87. statValues.hpMax = hp;
  88. statValues.level = level;
  89. if ((!drops.blueprints) || (drops.alsoRandom)) {
  90. [
  91. 'head',
  92. 'chest',
  93. 'neck',
  94. 'hands',
  95. 'waist',
  96. 'legs',
  97. 'feet',
  98. 'finger',
  99. 'trinket',
  100. 'twoHanded'
  101. ].forEach(function (slot) {
  102. let item = itemGenerator.generate({
  103. noSpell: true,
  104. level: level,
  105. slot: slot,
  106. quality: 4,
  107. forceStats: [preferStat]
  108. });
  109. delete item.spell;
  110. mob.inventory.getItem(item);
  111. mob.equipment.autoEquip(item.id);
  112. }, this);
  113. } else {
  114. //TODO: Don't give the mob these items: he'll drop them anyway
  115. drops.blueprints.forEach(function (d) {
  116. let drop = extend(true, {}, d);
  117. d.level = level;
  118. if (drop.type == 'key')
  119. return;
  120. mob.inventory.getItem(itemGenerator.generate(drop));
  121. }, this);
  122. }
  123. let spellCount = (mob.isRare ? 1 : 0) + (mob.isChampion ? 2 : 0);
  124. for (let i = 0; i < spellCount; i++) {
  125. let rune = itemGenerator.generate({
  126. spell: true
  127. });
  128. rune.eq = true;
  129. mob.inventory.getItem(rune);
  130. }
  131. let dmgMult = 4.5 * mob.mob.dmgMult;
  132. let hpMult = 1 * mob.mob.hpMult;
  133. dmgMult *= [0.25, 0.4, 0.575, 0.8, 1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2, 2.1, 2.2, 2.3, 2.4, 2.5][level - 1];
  134. statValues.hpMax = ~~(statValues.hpMax * [0.1, 0.2, 0.4, 0.7, 0.78, 0.91, 1.16, 1.19, 1.65, 2.36, 3.07, 3.55, 4.1, 4.85, 5.6, 5.9, 6.5, 7.1, 7.9, 12][level - 1]);
  135. if (mob.isRare) {
  136. dmgMult *= 1.25;
  137. hpMult *= 1.25;
  138. }
  139. if (mob.isChampion) {
  140. dmgMult *= 2;
  141. hpMult *= 3;
  142. }
  143. statValues.hpMax *= hpMult;
  144. statValues.hp = statValues.hpMax;
  145. statValues.mana = statValues.manaMax;
  146. mob.spellbook.spells.forEach(function (s) {
  147. s.dmgMult = dmgMult;
  148. s.statType = preferStat;
  149. s.element = elementType;
  150. s.manaCost = 0;
  151. }, this);
  152. ['hp', 'hpMax', 'mana', 'manaMax', 'level'].forEach(function (s) {
  153. mob.syncer.setObject(false, 'stats', 'values', s, statValues[s]);
  154. });
  155. }
  156. };