Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
 
 
 

352 righe
7.2 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. if (this.obj.dead)
  40. return;
  41. var result = {
  42. success: true
  43. };
  44. this.obj.fireEvent('beforeAggro', result);
  45. if (!result.success)
  46. return;
  47. var obj = this.obj;
  48. //If we're attacking something, don't try and look for more trouble. SAVE THE CPU!
  49. // this only counts for mobs, players can have multiple attackers
  50. var list = this.list;
  51. if (obj.isMob) {
  52. var lLen = list.length;
  53. for (var i = 0; i < lLen; i++) {
  54. var l = list[i];
  55. var lThreat = l.obj.aggro.getHighest();
  56. if (lThreat) {
  57. l.obj.aggro.list.forEach(function (a) {
  58. a.obj.aggro.unIgnore(lThreat);
  59. });
  60. }
  61. l.obj.aggro.unIgnore(obj);
  62. if (l.threat > 0)
  63. return;
  64. }
  65. } else {
  66. var lLen = list.length;
  67. for (var i = 0; i < lLen; i++) {
  68. var targetAggro = list[i].obj.aggro;
  69. //Maybe the aggro component has been removed?
  70. if (targetAggro)
  71. targetAggro.unIgnore(obj);
  72. }
  73. }
  74. var x = obj.x;
  75. var y = obj.y;
  76. //find mobs in range
  77. var range = this.range;
  78. var faction = this.faction;
  79. var inRange = this.physics.getArea(x - range, y - range, x + range, y + range, (c => (((!c.player) || (!obj.player)) && (!obj.dead) && (c.aggro) && (c.aggro.willAutoAttack(obj)))));
  80. if (inRange.length == 0)
  81. return;
  82. var iLen = inRange.length;
  83. for (var i = 0; i < iLen; i++) {
  84. var enemy = inRange[i];
  85. //The length could change
  86. lLen = list.length;
  87. for (var j = 0; j < lLen; j++) {
  88. //Set the enemy to null so we need we need to continue
  89. if (list[j].obj == enemy)
  90. enemy = null;
  91. }
  92. if (!enemy)
  93. continue;
  94. //Do we have LoS?
  95. if (!this.physics.hasLos(x, y, enemy.x, enemy.y))
  96. continue;
  97. if (enemy.aggro.tryEngage(obj))
  98. this.tryEngage(enemy, 0);
  99. }
  100. },
  101. canAttack: function (target) {
  102. var obj = this.obj;
  103. if (target == obj)
  104. return false;
  105. else if ((target.player) && (obj.player)) {
  106. var hasButcher = (obj.prophecies.hasProphecy('butcher')) && (target.prophecies.hasProphecy('butcher'));
  107. if ((!target.social.party) || (!obj.social.party))
  108. return hasButcher;
  109. else if (target.social.partyLeaderId != obj.social.partyLeaderId)
  110. return hasButcher;
  111. else
  112. return false;
  113. } else if ((target.follower) && (target.follower.master.player) && (obj.player))
  114. return false;
  115. else if (obj.player)
  116. return true;
  117. else if (target.aggro.faction != obj.aggro.faction)
  118. return true;
  119. else if (!!target.player != !!obj.player)
  120. return true;
  121. },
  122. willAutoAttack: function (target) {
  123. if (this.obj == target)
  124. return false;
  125. var faction = target.aggro.faction;
  126. if ((faction == null) || (!this.faction))
  127. return false;
  128. var rep = this.obj.reputation;
  129. if (!rep) {
  130. var targetRep = target.reputation;
  131. if (!targetRep)
  132. return false;
  133. else
  134. return (targetRep.getTier(this.faction) < 3);
  135. }
  136. return (rep.getTier(faction) < 3);
  137. },
  138. ignore: function (obj) {
  139. this.ignoreList.spliceWhere(o => o == obj);
  140. this.ignoreList.push(obj);
  141. },
  142. unIgnore: function (obj) {
  143. this.ignoreList.spliceWhere(o => o == obj);
  144. },
  145. tryEngage: function (obj, amount, threatMult) {
  146. //Don't aggro yourself, stupid
  147. if (obj == this.obj)
  148. return;
  149. var result = {
  150. success: true
  151. };
  152. this.obj.fireEvent('beforeAggro', result);
  153. if (!result.success)
  154. return false;
  155. //Mobs shouldn't aggro players that are too far from their home
  156. var mob = this.obj.mob;
  157. if (!mob)
  158. mob = obj.mob;
  159. if (mob) {
  160. var notMob = (obj == mob) ? this.obj : obj;
  161. if (!mob.canChase(notMob))
  162. return false;
  163. }
  164. var oId = obj.id;
  165. var list = this.list;
  166. amount = amount || 0;
  167. threatMult = threatMult || 1;
  168. var exists = list.find(l => l.obj.id == oId);
  169. if (exists) {
  170. exists.damage += amount;
  171. exists.threat += amount * threatMult;
  172. } else {
  173. var l = {
  174. obj: obj,
  175. damage: amount,
  176. threat: amount * threatMult
  177. };
  178. list.push(l);
  179. }
  180. //this.sortThreat();
  181. return true;
  182. },
  183. getFirstAttacker: function () {
  184. var first = this.list.find(l => ((l.obj.player) && (l.damage > 0)));
  185. if (first)
  186. return first.obj;
  187. else
  188. return null;
  189. },
  190. die: function () {
  191. var list = this.list;
  192. var lLen = list.length;
  193. for (var i = 0; i < lLen; i++) {
  194. var l = list[i];
  195. if (!l) {
  196. lLen--;
  197. continue;
  198. }
  199. //Maybe the aggro component was removed?
  200. var targetAggro = l.obj.aggro;
  201. if (targetAggro) {
  202. targetAggro.unAggro(this.obj);
  203. i--;
  204. lLen--;
  205. }
  206. }
  207. this.list = [];
  208. },
  209. unAggro: function (obj, amount) {
  210. var oId = obj.id;
  211. var list = this.list;
  212. var lLen = list.length;
  213. for (var i = 0; i < lLen; i++) {
  214. var l = list[i];
  215. if (l.obj != obj)
  216. continue;
  217. if (amount == null) {
  218. list.splice(i, 1);
  219. obj.aggro.unAggro(this.obj);
  220. break;
  221. } else {
  222. l.threat -= amount;
  223. if (l.threat <= 0) {
  224. list.splice(i, 1);
  225. obj.aggro.unAggro(this.obj);
  226. break;
  227. }
  228. }
  229. }
  230. this.ignoreList.spliceWhere(o => o == obj);
  231. //Stuff like cocoons don't have spellbooks
  232. if (this.obj.spellbook)
  233. this.obj.spellbook.unregisterCallback(obj.id, true);
  234. if ((this.list.length == 0) && (this.obj.mob) && (!this.obj.follower))
  235. this.obj.stats.resetHp();
  236. },
  237. sortThreat: function () {
  238. this.list.sort(function (a, b) {
  239. return (b.threat - a.threat);
  240. });
  241. },
  242. getHighest: function () {
  243. if (this.list.length == 0)
  244. return null;
  245. var list = this.list;
  246. var lLen = list.length;
  247. var highest = null;
  248. var closest = 99999;
  249. var thisObj = this.obj;
  250. var x = thisObj.x;
  251. var y = thisObj.y;
  252. for (var i = 0; i < lLen; i++) {
  253. var l = list[i];
  254. var obj = l.obj;
  255. if (this.ignoreList.some(o => o == obj))
  256. continue;
  257. if ((highest == null) || (l.threat > highest.threat)) {
  258. highest = l;
  259. closest = Math.max(Math.abs(x - obj.x), Math.abs(y - obj.y));
  260. } else if (l.threat == highest.threat) {
  261. var distance = Math.max(Math.abs(x - obj.x), Math.abs(y - obj.y));
  262. if (distance < closest) {
  263. highest = l;
  264. closest = distance;
  265. }
  266. }
  267. }
  268. if (highest)
  269. return highest.obj;
  270. else {
  271. //We have aggro but can't reach our target. Don't let the mob run away as if not in combat!
  272. return true;
  273. }
  274. },
  275. update: function () {
  276. var list = this.list;
  277. var lLen = list.length;
  278. for (var i = 0; i < lLen; i++) {
  279. var l = list[i];
  280. if (l.obj.destroyed) {
  281. this.unAggro(l.obj);
  282. i--;
  283. lLen--;
  284. }
  285. }
  286. }
  287. };
  288. });