Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 
 

307 Zeilen
6.0 KiB

  1. define([
  2. ], function(
  3. ) {
  4. return {
  5. type: 'aggro',
  6. range: 7,
  7. faction: null,
  8. physics: null,
  9. list: [],
  10. ignoreList: [],
  11. init: function(blueprint) {
  12. this.physics = this.obj.instance.physics;
  13. blueprint = blueprint || {};
  14. if (blueprint.faction) {
  15. this.faction = blueprint.faction;
  16. }
  17. //TODO: Why don't we move if faction is null?
  18. if (this.faction == null)
  19. return;
  20. if (this.physics.width > 0)
  21. this.move();
  22. else {
  23. //HACK: Don't fire on main thread (no physics set up)
  24. console.log('HACK: cpn/aggro');
  25. }
  26. },
  27. events: {
  28. beforeRezone: function() {
  29. this.die();
  30. }
  31. },
  32. simplify: function(self) {
  33. return {
  34. type: 'aggro',
  35. faction: this.faction
  36. };
  37. },
  38. move: function() {
  39. var result = {
  40. success: true
  41. };
  42. this.obj.fireEvent('beforeAggro', result);
  43. if (!result.success)
  44. return;
  45. var obj = this.obj;
  46. //If we're attacking something, don't try and look for more trouble. SAVE THE CPU!
  47. // this only counts for mobs, players can have multiple attackers
  48. var list = this.list;
  49. if (obj.isMob) {
  50. var lLen = list.length;
  51. for (var i = 0; i < lLen; i++) {
  52. var l = list[i];
  53. var lThreat = l.obj.aggro.getHighest();
  54. if (lThreat) {
  55. l.obj.aggro.list.forEach(function(a) {
  56. a.obj.aggro.unIgnore(lThreat);
  57. });
  58. }
  59. l.obj.aggro.unIgnore(obj);
  60. if (l.threat > 0)
  61. return;
  62. }
  63. } else {
  64. var lLen = list.length;
  65. for (var i = 0; i < lLen; i++) {
  66. list[i].obj.aggro.unIgnore(obj);
  67. }
  68. }
  69. var x = obj.x;
  70. var y = obj.y;
  71. //find mobs in range
  72. var range = this.range;
  73. var faction = this.faction;
  74. var inRange = this.physics.getArea(x - range, y - range, x + range, y + range, (c => (((!c.player) || (!obj.player)) && (c.aggro) && (c.aggro.willAttack(obj)))));
  75. if (inRange.length == 0)
  76. return;
  77. var iLen = inRange.length;
  78. for (var i = 0; i < iLen; i++) {
  79. var enemy = inRange[i];
  80. //The length could change
  81. lLen = list.length;
  82. for (var j = 0; j < lLen; j++) {
  83. //Set the enemy to null so we need we need to continue
  84. if (list[j].obj == enemy)
  85. enemy = null;
  86. }
  87. if (!enemy)
  88. continue;
  89. //Do we have LoS?
  90. if (!this.physics.hasLos(x, y, enemy.x, enemy.y))
  91. continue;
  92. if (enemy.aggro.tryEngage(obj))
  93. this.tryEngage(enemy, 0);
  94. }
  95. },
  96. willAttack: function(target) {
  97. if (this.obj == target)
  98. return false;
  99. var faction = target.aggro.faction;
  100. if (faction == null)
  101. return false;
  102. if ((target.player) && (this.obj.player))
  103. return ((this.obj.prophecies.hasProphecy('butcher')) && (target.prophecies.hasProphecy('butcher')));
  104. var rep = this.obj.reputation;
  105. if (!rep) {
  106. var targetRep = target.reputation;
  107. if (!targetRep)
  108. return false;
  109. else
  110. return (targetRep.getTier(this.faction) < 3);
  111. }
  112. return (rep.getTier(faction) < 3);
  113. },
  114. ignore: function(obj) {
  115. this.ignoreList.spliceWhere(o => o == obj);
  116. this.ignoreList.push(obj);
  117. },
  118. unIgnore: function(obj) {
  119. this.ignoreList.spliceWhere(o => o == obj);
  120. },
  121. tryEngage: function(obj, amount, threatMult) {
  122. //Don't aggro yourself, stupid
  123. if (obj == this.obj)
  124. return;
  125. var result = {
  126. success: true
  127. };
  128. this.obj.fireEvent('beforeAggro', result);
  129. if (!result.success)
  130. return false;
  131. var oId = obj.id;
  132. var list = this.list;
  133. amount = amount || 0;
  134. threatMult = threatMult || 1;
  135. var exists = list.find(l => l.obj.id == oId);
  136. if (exists) {
  137. exists.damage += amount;
  138. exists.threat += amount * threatMult;
  139. } else {
  140. var l = {
  141. obj: obj,
  142. damage: amount,
  143. threat: amount * threatMult
  144. };
  145. list.push(l);
  146. }
  147. //this.sortThreat();
  148. return true;
  149. },
  150. getFirstAttacker: function() {
  151. var first = this.list.find(l => ((l.obj.player) && (l.damage > 0)));
  152. if (first)
  153. return first.obj;
  154. else
  155. return null;
  156. },
  157. die: function() {
  158. var list = this.list;
  159. var lLen = list.length;
  160. for (var i = 0; i < lLen; i++) {
  161. var l = list[i];
  162. if (!l) {
  163. console.log('aggro obj empty???');
  164. continue;
  165. }
  166. l.obj.aggro.unAggro(this.obj);
  167. }
  168. this.list = [];
  169. },
  170. unAggro: function(obj, amount) {
  171. var oId = obj.id;
  172. var list = this.list;
  173. var lLen = list.length;
  174. for (var i = 0; i < lLen; i++) {
  175. var l = list[i];
  176. if (l.obj != obj)
  177. continue;
  178. if (amount == null) {
  179. list.splice(i, 1);
  180. break;
  181. } else {
  182. l.threat -= amount;
  183. if (l.threat <= 0) {
  184. list.splice(i, 1);
  185. break;
  186. }
  187. }
  188. }
  189. this.ignoreList.spliceWhere(o => o == obj);
  190. //Stuff like cocoons don't have spellbooks
  191. if (this.obj.spellbook)
  192. this.obj.spellbook.unregisterCallback(obj.id, true);
  193. if ((this.list.length == 0) && (this.obj.mob))
  194. this.obj.stats.resetHp();
  195. },
  196. sortThreat: function() {
  197. this.list.sort(function(a, b) {
  198. return (b.threat - a.threat);
  199. });
  200. },
  201. getHighest: function() {
  202. if (this.list.length == 0)
  203. return null;
  204. var list = this.list;
  205. var lLen = list.length;
  206. var highest = null;
  207. var closest = 99999;
  208. var thisObj = this.obj;
  209. var x = thisObj.x;
  210. var y = thisObj.y;
  211. for (var i = 0; i < lLen; i++) {
  212. var l = list[i];
  213. var obj = l.obj;
  214. if (this.ignoreList.some(o => o == obj))
  215. continue;
  216. if ((highest == null) || (l.threat > highest.threat)) {
  217. highest = l;
  218. closest = Math.max(Math.abs(x - obj.x), Math.abs(y - obj.y));
  219. } else if (l.threat == highest.threat) {
  220. var distance = Math.max(Math.abs(x - obj.x), Math.abs(y - obj.y));
  221. if (distance < closest) {
  222. highest = l;
  223. closest = distance;
  224. }
  225. }
  226. }
  227. if (highest)
  228. return highest.obj;
  229. else {
  230. //We have aggro but can't reach our target. Don't let the mob run away as if not in combat!
  231. return true;
  232. }
  233. },
  234. update: function() {
  235. var list = this.list;
  236. var lLen = list.length;
  237. for (var i = 0; i < lLen; i++) {
  238. var l = list[i];
  239. if (l.obj.destroyed) {
  240. this.unAggro(l.obj);
  241. i--;
  242. lLen--;
  243. }
  244. }
  245. }
  246. };
  247. });