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.
 
 
 

183 lines
3.4 KiB

  1. module.exports = {
  2. type: 'follower',
  3. master: null,
  4. lifetime: -1,
  5. maxDistance: 10,
  6. alwaysFollowMaster: false,
  7. lastMasterPos: {
  8. x: 0,
  9. y: 0
  10. },
  11. noNeedMaster: false,
  12. fGetHighest: {
  13. inCombat: null,
  14. outOfCombat: null
  15. },
  16. bindEvents: function () {
  17. let master = this.master;
  18. this.lastMasterPos.x = master.x;
  19. this.lastMasterPos.y = master.y;
  20. this.obj.aggro.faction = master.aggro.faction;
  21. this.fGetHighest.inCombat = master.aggro.getHighest.bind(master.aggro);
  22. this.fGetHighest.outOfCombat = this.returnNoAggro.bind(this);
  23. },
  24. returnNoAggro: function () {
  25. let master = this.master;
  26. let obj = this.obj;
  27. let mob = obj.mob;
  28. mob.originX = master.x;
  29. mob.originY = master.y;
  30. return null;
  31. },
  32. despawn: function () {
  33. let obj = this.obj;
  34. obj.destroyed = true;
  35. this.obj.instance.syncer.queue('onGetObject', {
  36. x: obj.x,
  37. y: obj.y,
  38. components: [{
  39. type: 'attackAnimation',
  40. row: 0,
  41. col: 4
  42. }]
  43. }, -1);
  44. },
  45. teleport: function () {
  46. let obj = this.obj;
  47. let physics = obj.instance.physics;
  48. let syncer = obj.syncer;
  49. let master = this.master;
  50. let newPosition = physics.getOpenCellInArea(master.x - 1, master.y - 1, master.x + 1, master.y + 1);
  51. if (!newPosition)
  52. return;
  53. physics.removeObject(obj, obj.x, obj.y);
  54. obj.x = newPosition.x;
  55. obj.y = newPosition.y;
  56. syncer.o.x = obj.x;
  57. syncer.o.y = obj.y;
  58. physics.addObject(obj, obj.x, obj.y);
  59. obj.instance.syncer.queue('onGetObject', {
  60. x: obj.x,
  61. y: obj.y,
  62. components: [{
  63. type: 'attackAnimation',
  64. row: 0,
  65. col: 4
  66. }]
  67. }, -1);
  68. },
  69. followMaster: function (distance) {
  70. const { obj, maxDistance, master: { x, y }, lastMasterPos: { x: lx, y: ly } } = this;
  71. if (distance < maxDistance)
  72. return;
  73. const masterDistanceFromLastPos = Math.max(Math.abs(x - lx), Math.abs(y - ly));
  74. if (masterDistanceFromLastPos <= maxDistance)
  75. return;
  76. obj.mob.goHome = true;
  77. obj.mob.originX = x;
  78. obj.mob.originY = y;
  79. this.lastMasterPos.x = x;
  80. this.lastMasterPos.y = y;
  81. },
  82. update: function () {
  83. if (this.lifetime > 0) {
  84. this.lifetime--;
  85. if (this.lifetime === 0) {
  86. this.despawn();
  87. return;
  88. }
  89. }
  90. let obj = this.obj;
  91. let master = this.master;
  92. if (master.destroyed && !this.noNeedMaster) {
  93. this.despawn();
  94. return;
  95. }
  96. let attacker = null;
  97. let maxDistance = this.maxDistance;
  98. let distance = Math.max(Math.abs(obj.x - master.x), Math.abs(obj.y - master.y));
  99. if (this.alwaysFollowMaster) {
  100. this.followMaster(distance);
  101. return;
  102. }
  103. if (obj.aggro)
  104. attacker = this.fGetHighest.inCombat();
  105. //When we're too far, just teleport
  106. if (!attacker && distance >= maxDistance * 2) {
  107. this.teleport();
  108. return;
  109. }
  110. let doMove = false;
  111. //If we're not too far from the master but the master is not in combat, move anyway
  112. if (!attacker) {
  113. let lastMasterPos = this.lastMasterPos;
  114. if ((master.x !== lastMasterPos.x) || (master.y !== lastMasterPos.y)) {
  115. doMove = true;
  116. lastMasterPos.x = master.x;
  117. lastMasterPos.y = master.y;
  118. }
  119. }
  120. if (doMove) {
  121. obj.clearQueue();
  122. obj.mob.target = obj;
  123. }
  124. if (obj.aggro)
  125. obj.aggro.getHighest = doMove ? this.fGetHighest.outOfCombat : this.fGetHighest.inCombat;
  126. else
  127. this.returnNoAggro();
  128. },
  129. simplify: function () {
  130. return {
  131. type: 'follower',
  132. master: this.master.id
  133. };
  134. },
  135. events: {
  136. afterDeath: function (deathEvent) {
  137. this.master.fireEvent('afterFollowerDeath', {
  138. deathEvent,
  139. master: this.master
  140. });
  141. }
  142. }
  143. };