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.
 
 
 

194 lines
3.9 KiB

  1. const getTargetPos = (physics, obj, m, pushback) => {
  2. let targetPos = {
  3. x: m.x,
  4. y: m.y
  5. };
  6. let dx = m.x - obj.x;
  7. let dy = m.y - obj.y;
  8. while ((dx === 0) && (dy === 0)) {
  9. dx = ~~(Math.random() * 2) - 1;
  10. dy = ~~(Math.random() * 2) - 1;
  11. }
  12. dx = ~~(dx / Math.abs(dx));
  13. dy = ~~(dy / Math.abs(dy));
  14. for (let l = 0; l < pushback; l++) {
  15. if (physics.isTileBlocking(targetPos.x + dx, targetPos.y + dy)) {
  16. if (physics.isTileBlocking(targetPos.x + dx, targetPos.y)) {
  17. if (physics.isTileBlocking(targetPos.x, targetPos.y + dy))
  18. break;
  19. else {
  20. dx = 0;
  21. targetPos.y += dy;
  22. }
  23. } else {
  24. dy = 0;
  25. targetPos.x += dx;
  26. }
  27. } else {
  28. targetPos.x += dx;
  29. targetPos.y += dy;
  30. }
  31. }
  32. return targetPos;
  33. };
  34. module.exports = {
  35. type: 'fireblast',
  36. targetGround: true,
  37. targetPlayerPos: true,
  38. radius: 2,
  39. pushback: 4,
  40. damage: 1,
  41. cast: function (action) {
  42. let obj = this.obj;
  43. let { x, y, instance: { physics, syncer } } = obj;
  44. let radius = this.radius;
  45. const particleEvent = {
  46. source: this,
  47. particleConfig: extend({}, this.particles)
  48. };
  49. obj.fireEvent('beforeSpawnParticles', particleEvent);
  50. for (let i = x - radius; i <= x + radius; i++) {
  51. for (let j = y - radius; j <= y + radius; j++) {
  52. if (!physics.hasLos(~~x, ~~y, ~~i, ~~j))
  53. continue;
  54. let effect = {
  55. x: i,
  56. y: j,
  57. components: [{
  58. type: 'particles',
  59. ttl: 10,
  60. blueprint: particleEvent.particleConfig
  61. }]
  62. };
  63. if ((i !== x) || (j !== y))
  64. syncer.queue('onGetObject', effect, -1);
  65. let mobs = physics.getCell(i, j);
  66. let mLen = mobs.length;
  67. for (let k = 0; k < mLen; k++) {
  68. let m = mobs[k];
  69. //Maybe we killed something?
  70. if (!m) {
  71. mLen--;
  72. continue;
  73. } else if (!m.aggro || !m.effects)
  74. continue;
  75. else if (!obj.aggro.canAttack(m))
  76. continue;
  77. const targetPos = getTargetPos(physics, obj, m, this.pushback);
  78. let distance = Math.max(Math.abs(m.x - targetPos.x), Math.abs(m.y - targetPos.y));
  79. let ttl = distance * 125;
  80. m.clearQueue();
  81. let damage = this.getDamage(m);
  82. m.stats.takeDamage({
  83. damage,
  84. threatMult: 1,
  85. source: this.obj,
  86. target: m,
  87. spellName: 'fireblast'
  88. });
  89. if (m.destroyed)
  90. continue;
  91. const eventMsg = {
  92. success: true,
  93. targetPos
  94. };
  95. m.fireEvent('beforePositionChange', eventMsg);
  96. if (!eventMsg.success)
  97. continue;
  98. const targetEffect = m.effects.addEffect({
  99. type: 'stunned',
  100. silent: true
  101. });
  102. //If targetEffect is undefined, it means that the target has become resistant
  103. if (!targetEffect)
  104. continue;
  105. this.sendAnimation({
  106. id: m.id,
  107. components: [{
  108. type: 'moveAnimation',
  109. targetX: targetPos.x,
  110. targetY: targetPos.y,
  111. ttl: ttl
  112. }]
  113. });
  114. this.queueCallback(this.endEffect.bind(this, m, targetPos, targetEffect), ttl, null, m);
  115. }
  116. }
  117. }
  118. this.sendBump({
  119. x: x,
  120. y: y - 1
  121. });
  122. return true;
  123. },
  124. endEffect: function (target, targetPos, targetEffect) {
  125. const { instance: { physics }, syncer, effects } = target;
  126. const { x: xNew, y: yNew } = targetPos;
  127. const xOld = target.x;
  128. const yOld = target.y;
  129. effects.removeEffect(targetEffect.id);
  130. target.x = xNew;
  131. target.y = yNew;
  132. if (physics.addObject(target, xNew, yNew, xOld, yOld))
  133. physics.removeObject(target, xOld, yOld, xNew, yNew);
  134. else {
  135. target.x = xOld;
  136. target.y = yOld;
  137. return false;
  138. }
  139. //We can't use xNew and yNew because addObject could have changed the position (like entering a building interior with stairs)
  140. const { x: xFinal, y: yFinal } = target;
  141. syncer.o.x = xFinal;
  142. syncer.o.y = yFinal;
  143. const moveEvent = {
  144. newPos: {
  145. x: xFinal,
  146. y: yFinal
  147. },
  148. source: this.obj,
  149. target,
  150. spellName: 'fireblast',
  151. spell: this
  152. };
  153. target.fireEvent('afterPositionChange', moveEvent);
  154. }
  155. };