25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

224 lines
4.5 KiB

  1. let mobBuilder = require('./mobBuilder');
  2. let animations = require('../config/animations');
  3. let scheduler = require('../misc/scheduler');
  4. module.exports = {
  5. list: [],
  6. mobTypes: {},
  7. init: function (msg) {
  8. this.objects = msg.objects;
  9. this.syncer = msg.syncer;
  10. this.zone = msg.zone;
  11. this.mobBuilder = extend(true, {
  12. zone: this.zone
  13. }, mobBuilder);
  14. },
  15. reset: function () {
  16. this.list = [];
  17. this.mobTypes = {};
  18. },
  19. register: function (blueprint, cdMax) {
  20. let spawner = extend(true, {
  21. cdMax: cdMax || 171,
  22. cron: blueprint.cron,
  23. lifetime: blueprint.lifetime,
  24. blueprint: blueprint,
  25. amountLeft: blueprint.amount || -1
  26. });
  27. this.list.push(spawner);
  28. if ((blueprint.sheetName != 'mobs') && (blueprint.sheetName != 'bosses'))
  29. return;
  30. let name = blueprint.name.toLowerCase();
  31. if (!this.mobTypes[name])
  32. this.mobTypes[name] = 1;
  33. else
  34. this.mobTypes[name]++;
  35. spawner.zonePrint = extend(true, {}, this.zone.mobs.default, this.zone.mobs[name] || {});
  36. },
  37. spawn: function (spawner) {
  38. if (spawner.amountLeft == 0)
  39. return;
  40. let blueprint = spawner.blueprint;
  41. let obj = this.objects.buildObjects([blueprint]);
  42. let customSpawn = false;
  43. let sheetName = blueprint.sheetName;
  44. if ((sheetName) && (blueprint.sheetName.indexOf('/'))) {
  45. let spawnAnimation = _.getDeepProperty(animations, ['mobs', sheetName, blueprint.cell, 'spawn']);
  46. if (spawnAnimation) {
  47. customSpawn = true;
  48. this.syncer.queue('onGetObject', {
  49. id: obj.id,
  50. performLast: true,
  51. components: [spawnAnimation]
  52. }, -1);
  53. }
  54. }
  55. if (!customSpawn) {
  56. this.syncer.queue('onGetObject', {
  57. x: obj.x,
  58. y: obj.y,
  59. components: [{
  60. type: 'attackAnimation',
  61. row: 0,
  62. col: 4
  63. }]
  64. }, -1);
  65. }
  66. if (spawner.amountLeft != -1)
  67. spawner.amountLeft--;
  68. return obj;
  69. },
  70. update: function () {
  71. let list = this.list;
  72. let lLen = list.length;
  73. for (let i = 0; i < lLen; i++) {
  74. let l = list[i];
  75. if ((l.lifetime) && (l.mob) && (!l.mob.destroyed)) {
  76. if (!l.age)
  77. l.age = 1;
  78. else
  79. l.age++;
  80. if (l.age >= l.lifetime) {
  81. this.syncer.queue('onGetObject', {
  82. x: l.mob.x,
  83. y: l.mob.y,
  84. components: [{
  85. type: 'attackAnimation',
  86. row: 0,
  87. col: 4
  88. }]
  89. }, -1);
  90. l.mob.destroyed = true;
  91. }
  92. }
  93. if (!l.cron) {
  94. if (l.cd > 0)
  95. l.cd--;
  96. else if ((l.mob) && (l.mob.destroyed))
  97. l.cd = l.cdMax;
  98. }
  99. let cronInfo = {
  100. cron: l.cron,
  101. lastRun: l.lastRun
  102. };
  103. let doSpawn = (
  104. (
  105. (!l.cron) &&
  106. (!l.mob)
  107. ) ||
  108. (
  109. (!l.cron) &&
  110. (l.cd == 0)
  111. ) ||
  112. (
  113. (!l.mob) &&
  114. (l.cron) &&
  115. (scheduler.shouldRun(cronInfo))
  116. )
  117. );
  118. if (doSpawn) {
  119. if (!l.cron)
  120. l.cd = -1;
  121. let mob = this.spawn(l);
  122. if (!mob)
  123. continue;
  124. let name = (l.blueprint.objZoneName || l.blueprint.name).toLowerCase();
  125. if ((l.blueprint.sheetName == 'mobs') || (l.blueprint.sheetName == 'bosses'))
  126. this.setupMob(mob, l.zonePrint, l.blueprint.scaleDrops);
  127. else {
  128. let blueprint = extend(true, {}, this.zone.objects.default, this.zone.objects[name] || {});
  129. this.setupObj(mob, blueprint);
  130. }
  131. if (l.blueprint.objZoneName)
  132. mob.objZoneName = l.blueprint.objZoneName;
  133. l.mob = mob;
  134. }
  135. }
  136. },
  137. scale: function (level) {
  138. level += (this.zone.addLevel || 0);
  139. this.list.forEach(function (l) {
  140. if (!l.zonePrint)
  141. return;
  142. if (l.zonePrint.level !== null)
  143. l.zonePrint.level = level;
  144. if ((!l.mob) || (l.mob.destroyed))
  145. return;
  146. this.mobBuilder.scale(l.mob, level);
  147. }, this);
  148. },
  149. setupMob: function (mob, blueprint, scaleDrops) {
  150. let type = 'regular';
  151. if (blueprint.isChampion)
  152. type = 'champion';
  153. else if (blueprint.rare.count > 0) {
  154. let rareCount = this.list.filter(l => (
  155. (l.mob) &&
  156. (!l.mob.destroyed) &&
  157. (l.mob.isRare) &&
  158. (l.mob.baseName == mob.name)
  159. ));
  160. if (rareCount.length < blueprint.rare.count) {
  161. let roll = Math.random() * 100;
  162. if (roll < blueprint.rare.chance)
  163. type = 'rare';
  164. }
  165. }
  166. this.setupObj(mob, blueprint);
  167. this.mobBuilder.build(mob, blueprint, scaleDrops, type, this.zone.name);
  168. },
  169. setupObj: function (obj, blueprint) {
  170. let cpns = blueprint.components;
  171. if (!cpns)
  172. return;
  173. for (let c in cpns) {
  174. let cpn = cpns[c];
  175. let cType = c.replace('cpn', '');
  176. cType = cType[0].toLowerCase() + cType.substr(1);
  177. let builtCpn = obj.addComponent(cType, cpn);
  178. if (cpn.simplify)
  179. builtCpn.simplify = cpn.simplify.bind(builtCpn);
  180. }
  181. }
  182. };