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.
 
 
 

188 lines
4.0 KiB

  1. let spellCallbacks = require('./spellCallbacks');
  2. let combat = require('../../combat/combat');
  3. module.exports = {
  4. cd: 0,
  5. cdMax: 0,
  6. manaCost: 1,
  7. threatMult: 1,
  8. needLos: false,
  9. pendingAttacks: [],
  10. castBase: function () {
  11. if (this.cd > 0)
  12. return false;
  13. else if (this.manaCost > this.obj.stats.values.mana)
  14. return false;
  15. return true;
  16. },
  17. canCast: function (target) {
  18. if (this.cd > 0)
  19. return false;
  20. else if (this.manaCost > this.obj.stats.values.mana)
  21. return false;
  22. else if (!target)
  23. return true;
  24. let inRange = true;
  25. if (this.range !== null) {
  26. let obj = this.obj;
  27. let distance = Math.max(Math.abs(target.x - obj.x), Math.abs(target.y - obj.y));
  28. inRange = (distance <= this.range);
  29. }
  30. return inRange;
  31. },
  32. updateBase: function () {
  33. if (this.cd > 0)
  34. this.cd--;
  35. },
  36. calcDps: function (target, noSync) {
  37. if ((!this.values) || (this.spellType === 'buff'))
  38. return;
  39. if ((!this.damage) && (!this.healing))
  40. delete this.values.dps;
  41. else {
  42. let noMitigate = !target;
  43. let dmg = combat.getDamage({
  44. source: this.obj,
  45. target: (target || {
  46. stats: {
  47. values: {}
  48. }
  49. }),
  50. damage: (this.damage || this.healing) * (this.dmgMult || 1),
  51. cd: this.cdMax,
  52. element: this.element,
  53. statType: this.statType,
  54. statMult: this.statMult,
  55. noMitigate: noMitigate,
  56. noCrit: true
  57. }).amount;
  58. let isAttack = (this.type === 'melee');
  59. let statValues = this.obj.stats.values;
  60. let critChance = isAttack ? statValues.attackCritChance : statValues.spellCritChance;
  61. let critMultiplier = 100 + (isAttack ? statValues.attackCritMultiplier : statValues.spellCritMultiplier);
  62. let attackSpeed = (statValues.attackSpeed / 100);
  63. attackSpeed += 1;
  64. dmg = (((dmg / 100) * (100 - critChance)) + (((dmg / 100) * critChance) * (critMultiplier / 100))) * attackSpeed;
  65. let duration = this.values.duration;
  66. if (duration)
  67. dmg *= duration;
  68. dmg /= this.cdMax;
  69. if (this.damage)
  70. this.values.dmg = ~~(dmg * 100) / 100 + '/tick';
  71. else
  72. this.values.heal = ~~(dmg * 100) / 100 + '/tick';
  73. if (!noSync)
  74. this.obj.syncer.setArray(true, 'spellbook', 'getSpells', this.simplify());
  75. }
  76. },
  77. sendAnimation: function (blueprint) {
  78. this.obj.instance.syncer.queue('onGetObject', blueprint, -1);
  79. },
  80. sendBump: function (target) {
  81. let x = this.obj.x;
  82. let y = this.obj.y;
  83. let tx = target.x;
  84. let ty = target.y;
  85. let deltaX = 0;
  86. let deltaY = 0;
  87. if (tx < x)
  88. deltaX = -1;
  89. else if (tx > x)
  90. deltaX = 1;
  91. if (ty < y)
  92. deltaY = -1;
  93. else if (ty > y)
  94. deltaY = 1;
  95. let components = [{
  96. type: 'bumpAnimation',
  97. deltaX: deltaX,
  98. deltaY: deltaY
  99. }];
  100. if (this.animation) {
  101. components.push({
  102. type: 'animation',
  103. template: this.animation
  104. });
  105. }
  106. this.obj.instance.syncer.queue('onGetObject', {
  107. id: this.obj.id,
  108. components: components
  109. }, -1);
  110. },
  111. simplify: function (self) {
  112. let values = {};
  113. for (let p in this) {
  114. let value = this[p];
  115. if ((typeof (value) === 'function') || (p === 'obj'))
  116. continue;
  117. values[p] = value;
  118. }
  119. if (this.animation)
  120. values.animation = this.animation.name;
  121. if (this.values)
  122. values.values = this.values;
  123. if (this.onAfterSimplify)
  124. this.onAfterSimplify(values);
  125. return values;
  126. },
  127. getDamage: function (target, noMitigate) {
  128. let config = {
  129. source: this.obj,
  130. target: target,
  131. damage: (this.damage || this.healing) * (this.dmgMult || 1),
  132. cd: this.cdMax,
  133. element: this.element,
  134. statType: this.statType,
  135. statMult: this.statMult,
  136. isAttack: (this.type === 'melee'),
  137. noMitigate: noMitigate
  138. };
  139. this.obj.fireEvent('onBeforeCalculateDamage', config);
  140. let damage = combat.getDamage(config);
  141. return damage;
  142. },
  143. queueCallback: function (callback, delay, destroyCallback, target, destroyOnRezone) {
  144. return this.obj.spellbook.registerCallback(this.obj.id, callback, delay, destroyCallback, target ? target.id : null, destroyOnRezone);
  145. },
  146. die: function () {
  147. this.obj.spellbook.unregisterCallback(this.obj.id);
  148. }
  149. };