25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

214 lines
4.8 KiB

  1. define([
  2. 'items/generator'
  3. ], function (
  4. itemGenerator
  5. ) {
  6. var abs = Math.abs.bind(Math);
  7. var rnd = Math.random.bind(Math);
  8. var max = Math.max.bind(Math);
  9. return {
  10. type: 'mob',
  11. target: null,
  12. physics: null,
  13. originX: 0,
  14. originY: 0,
  15. walkDistance: 1,
  16. maxChaseDistance: 25,
  17. goHome: false,
  18. init: function (blueprint) {
  19. this.physics = this.obj.instance.physics;
  20. this.originX = this.obj.x;
  21. this.originY = this.obj.y;
  22. },
  23. update: function () {
  24. var obj = this.obj;
  25. var target = null;
  26. if (obj.aggro)
  27. target = obj.aggro.getHighest();
  28. //Have we reached home?
  29. if (this.goHome) {
  30. var distanceFromHome = Math.max(Math.abs(this.originX - obj.x), Math.abs(this.originY - obj.y));
  31. if (distanceFromHome < this.walkDistance)
  32. this.goHome = false;
  33. }
  34. //Are we too far from home?
  35. if ((!this.goHome) && (!obj.follower) && (target)) {
  36. if (!this.canChase(target)) {
  37. obj.clearQueue();
  38. obj.aggro.unAggro(target);
  39. target = obj.aggro.getHighest();
  40. }
  41. }
  42. if (!this.goHome) {
  43. //Are we in fight mode?
  44. if ((target) && (target != obj) && ((!obj.follower) || (obj.follower.master != target))) {
  45. this.fight(target);
  46. return;
  47. }
  48. //Is fight mode over?
  49. else if ((!target) && (this.target)) {
  50. this.target = null;
  51. obj.clearQueue();
  52. this.goHome = true;
  53. }
  54. }
  55. //If we're already going somewhere, don't calculate a new path
  56. if (obj.actionQueue.length > 0)
  57. return;
  58. //Unless we're going home, don't always move
  59. if ((!this.goHome) && (rnd() < 0.85))
  60. return;
  61. //don't move around if we're not allowed to, unless we're going home
  62. var walkDistance = this.walkDistance;
  63. if ((!this.goHome) && (walkDistance <= 0))
  64. return;
  65. var toX = this.originX + ~~(rnd() * (walkDistance * 2)) - walkDistance;
  66. var toY = this.originY + ~~(rnd() * (walkDistance * 2)) - walkDistance;
  67. if (!this.physics.isCellOpen(toX, toY))
  68. return;
  69. var path = this.physics.getPath({
  70. x: obj.x,
  71. y: obj.y
  72. }, {
  73. x: toX,
  74. y: toY
  75. }, false);
  76. var pLen = path.length;
  77. for (var i = 0; i < pLen; i++) {
  78. var p = path[i];
  79. obj.queue({
  80. action: 'move',
  81. data: {
  82. x: p.x,
  83. y: p.y
  84. }
  85. });
  86. }
  87. //We use goHometo force followers to follow us around but they should never stay in that state
  88. // since it messes with combat
  89. if (obj.follower)
  90. this.goHome = false;
  91. },
  92. fight: function (target) {
  93. if (this.target != target) {
  94. this.obj.clearQueue();
  95. this.target = target;
  96. }
  97. //If the target is true, it means we can't reach the target and should wait for a new one
  98. if (this.target == true)
  99. return;
  100. var obj = this.obj;
  101. var x = obj.x;
  102. var y = obj.y;
  103. var tx = ~~target.x;
  104. var ty = ~~target.y;
  105. var distance = max(abs(x - tx), abs(y - ty));
  106. var furthestRange = obj.spellbook.getFurthestRange();
  107. var doesCollide = null;
  108. var hasLos = null;
  109. if (distance <= furthestRange) {
  110. doesCollide = this.physics.mobsCollide(x, y, obj);
  111. if (!doesCollide) {
  112. hasLos = this.physics.hasLos(x, y, tx, ty);
  113. if (hasLos) {
  114. if (((obj.follower) && (obj.follower.master.player)) || (rnd() < 0.65)) {
  115. var spell = obj.spellbook.getRandomSpell(target);
  116. var success = obj.spellbook.cast({
  117. spell: spell,
  118. target: target
  119. });
  120. //null means we don't have LoS
  121. if (success != null)
  122. return;
  123. else
  124. hasLos = false;
  125. } else
  126. return;
  127. }
  128. }
  129. }
  130. var targetPos = this.physics.getClosestPos(x, y, tx, ty, target);
  131. if (!targetPos) {
  132. //Find a new target
  133. obj.aggro.ignore(target);
  134. //TODO: Don't skip a turn
  135. return;
  136. }
  137. var newDistance = max(abs(targetPos.x - tx), abs(targetPos.y - ty));
  138. if ((newDistance >= distance) && (newDistance > furthestRange)) {
  139. if (hasLos == null)
  140. hasLos = this.physics.hasLos(x, y, tx, ty);
  141. if (hasLos) {
  142. if (doesCollide == null)
  143. doesCollide = this.physics.mobsCollide(x, y, obj);
  144. if (!doesCollide) {
  145. obj.aggro.ignore(target);
  146. return;
  147. }
  148. } else {
  149. if (doesCollide == null)
  150. doesCollide = this.physics.mobsCollide(x, y, obj);
  151. if (!doesCollide) {
  152. obj.aggro.ignore(target);
  153. return;
  154. }
  155. }
  156. }
  157. var path = this.physics.getPath({
  158. x: x,
  159. y: y
  160. }, {
  161. x: targetPos.x,
  162. y: targetPos.y
  163. });
  164. if (path.length == 0) {
  165. obj.aggro.ignore(target);
  166. //TODO: Don't skip a turn
  167. return;
  168. }
  169. var p = path[0];
  170. obj.queue({
  171. action: 'move',
  172. data: {
  173. x: p.x,
  174. y: p.y
  175. }
  176. });
  177. },
  178. canChase: function (obj) {
  179. var distanceFromHome = Math.max(Math.abs(this.originX - obj.x), Math.abs(this.originY - obj.y));
  180. return ((!this.goHome) && (distanceFromHome <= this.maxChaseDistance));
  181. }
  182. };
  183. });