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.
 
 
 

322 lines
6.9 KiB

  1. define([
  2. 'js/objects/objBase',
  3. 'js/system/events',
  4. 'js/rendering/renderer',
  5. 'js/sound/sound',
  6. 'js/config'
  7. ], function (
  8. objBase,
  9. events,
  10. renderer,
  11. sound,
  12. config
  13. ) {
  14. return {
  15. objects: [],
  16. init: function () {
  17. events.on('onChangeHoverTile', this.getLocation.bind(this));
  18. [
  19. 'onGetObject',
  20. 'onTilesVisible',
  21. 'onToggleNameplates',
  22. 'destroyAllObjects'
  23. ]
  24. .forEach(e => events.on(e, this[e].bind(this)));
  25. },
  26. getLocation: function (x, y) {
  27. let objects = this.objects;
  28. let oLen = objects.length;
  29. let closest = 999;
  30. let mob = null;
  31. for (let i = 0; i < oLen; i++) {
  32. let o = objects[i];
  33. if (!o.stats || o.nonSelectable || o === window.player || !o.sprite || !o.sprite.visible)
  34. continue;
  35. let dx = Math.abs(o.x - x);
  36. if ((dx < 3) && (dx < closest)) {
  37. let dy = Math.abs(o.y - y);
  38. if ((dy < 3) && (dy < closest)) {
  39. mob = o;
  40. closest = Math.max(dx, dy);
  41. }
  42. }
  43. }
  44. events.emit('onMobHover', mob);
  45. },
  46. getClosest: function (x, y, maxDistance, reverse, fromMob) {
  47. let objects = this.objects;
  48. let list = objects.filter(o => {
  49. if ((!o.stats) || (o.nonSelectable) || (o === window.player) || (!o.sprite.visible))
  50. return false;
  51. let dx = Math.abs(o.x - x);
  52. if (dx < maxDistance) {
  53. let dy = Math.abs(o.y - y);
  54. if (dy < maxDistance)
  55. return true;
  56. }
  57. });
  58. if (list.length === 0)
  59. return null;
  60. list.sort((a, b) => {
  61. let aDistance = Math.max(Math.abs(x - a.x), Math.abs(y - a.y));
  62. let bDistance = Math.max(Math.abs(x - b.x), Math.abs(y - b.y));
  63. return (aDistance - bDistance);
  64. });
  65. list = list.filter(o => ((o.aggro) && (o.aggro.faction !== window.player.aggro.faction)));
  66. if (!fromMob)
  67. return list[0];
  68. let fromIndex = list.findIndex(l => l.id === fromMob.id);
  69. if (reverse)
  70. fromIndex = (fromIndex === 0 ? list.length : fromIndex) - 1;
  71. else
  72. fromIndex = (fromIndex + 1) % list.length;
  73. return list[fromIndex];
  74. },
  75. destroyAllObjects: function () {
  76. this.objects.forEach(o => {
  77. o.destroy();
  78. });
  79. this.objects.length = 0;
  80. window?.player?.offEvents();
  81. },
  82. onGetObject: function (obj) {
  83. //Things like attacks don't have ids
  84. let exists = null;
  85. if (obj.has('id'))
  86. exists = this.objects.find(({ id, destroyed }) => id === obj.id && !destroyed);
  87. if (!exists)
  88. exists = this.buildObject(obj);
  89. else
  90. this.updateObject(exists, obj);
  91. },
  92. buildObject: function (template) {
  93. let obj = $.extend(true, {}, objBase);
  94. let components = template.components || [];
  95. delete template.components;
  96. let syncTypes = ['portrait', 'area'];
  97. for (let p in template) {
  98. let value = template[p];
  99. let type = typeof (value);
  100. if (type === 'object') {
  101. if (syncTypes.indexOf(p) > -1)
  102. obj[p] = value;
  103. } else
  104. obj[p] = value;
  105. }
  106. if (obj.sheetName)
  107. obj.sprite = renderer.buildObject(obj);
  108. if (obj.name && obj.sprite) {
  109. obj.nameSprite = renderer.buildText({
  110. layerName: 'effects',
  111. text: obj.name,
  112. x: (obj.x * scale) + (scale / 2),
  113. y: (obj.y * scale) + scale
  114. });
  115. }
  116. if (template.filters && obj.sprite)
  117. renderer.addFilter(obj.sprite, template.filters[0]);
  118. //We need to set visibility before components kick in as they sometimes need access to isVisible
  119. obj.updateVisibility();
  120. components.forEach(c => {
  121. //Map ids to objects
  122. let keys = Object.keys(c).filter(k => {
  123. return (k.indexOf('id') === 0 && k.length > 2);
  124. });
  125. keys.forEach(k => {
  126. let value = c[k];
  127. let newKey = k.substr(2, k.length).toLowerCase();
  128. c[newKey] = this.objects.find(o => o.id === value);
  129. delete c[k];
  130. });
  131. obj.addComponent(c.type, c);
  132. });
  133. if (obj.self) {
  134. events.emit('onGetPlayer', obj);
  135. window.player = obj;
  136. sound.unload(obj.zoneId);
  137. renderer.setPosition({
  138. x: (obj.x - (renderer.width / (scale * 2))) * scale,
  139. y: (obj.y - (renderer.height / (scale * 2))) * scale
  140. }, true);
  141. }
  142. this.objects.push(obj);
  143. return obj;
  144. },
  145. updateObject: function (obj, template) {
  146. let components = template.components || [];
  147. components.forEach(c => {
  148. //Map ids to objects
  149. let keys = Object.keys(c).filter(k => {
  150. return (k.indexOf('id') === 0 && k.length > 2);
  151. });
  152. keys.forEach(k => {
  153. let value = c[k];
  154. let newKey = k.substr(2, k.length).toLowerCase();
  155. c[newKey] = this.objects.find(o => o.id === value);
  156. delete c[k];
  157. });
  158. obj.addComponent(c.type, c);
  159. });
  160. delete template.components;
  161. if (template.removeComponents) {
  162. template.removeComponents.forEach(r => {
  163. obj.removeComponent(r);
  164. });
  165. delete template.removeComponents;
  166. }
  167. let oldX = obj.x;
  168. let sprite = obj.sprite;
  169. for (let p in template) {
  170. let value = template[p];
  171. let type = typeof (value);
  172. if (type !== 'object')
  173. obj[p] = value;
  174. if (p === 'casting') {
  175. if (obj === window.player)
  176. events.emit('onGetSelfCasting', value);
  177. else
  178. events.emit('onGetTargetCasting', obj.id, value);
  179. }
  180. if (sprite) {
  181. if (p === 'x') {
  182. if (obj.x < oldX)
  183. obj.flipX = true;
  184. else if (obj.x > oldX)
  185. obj.flipX = false;
  186. }
  187. }
  188. }
  189. if (((template.sheetName) || (template.cell)) && (sprite))
  190. renderer.setSprite(obj);
  191. if ((!obj.sprite) && (template.sheetName))
  192. obj.sprite = renderer.buildObject(obj);
  193. if (template.filters && !obj.sprite?.filters?.length)
  194. renderer.addFilter(obj.sprite, template.filters[0]);
  195. if (template.name) {
  196. if (obj.nameSprite)
  197. renderer.destroyObject({ sprite: obj.nameSprite });
  198. obj.nameSprite = renderer.buildText({
  199. layerName: 'effects',
  200. text: template.name,
  201. x: (obj.x * scale) + (scale / 2),
  202. y: (obj.y * scale) + scale
  203. });
  204. obj.nameSprite.visible = config.showNames;
  205. }
  206. if ((template.x !== 0) || (template.y !== 0)) {
  207. obj.updateVisibility();
  208. obj.setSpritePosition();
  209. if (obj.stats)
  210. obj.stats.updateHpSprite();
  211. }
  212. },
  213. update: function () {
  214. let objects = this.objects;
  215. let len = objects.length;
  216. for (let i = 0; i < len; i++) {
  217. let o = objects[i];
  218. if (o.destroyed) {
  219. o.destroy();
  220. objects.splice(i, 1);
  221. i--;
  222. len--;
  223. continue;
  224. }
  225. o.update();
  226. }
  227. },
  228. onTilesVisible: function (tiles, visible) {
  229. let objects = this.objects;
  230. let oLen = objects.length;
  231. for (let i = 0; i < oLen; i++) {
  232. let o = objects[i];
  233. let onPos = tiles.some(t => {
  234. return (!(t.x !== o.x || t.y !== o.y));
  235. });
  236. if (!onPos)
  237. continue;
  238. o.updateVisibility();
  239. }
  240. },
  241. onToggleNameplates: function (show) {
  242. let objects = this.objects;
  243. let oLen = objects.length;
  244. for (let i = 0; i < oLen; i++) {
  245. let obj = objects[i];
  246. let ns = obj.nameSprite;
  247. if ((!ns) || (obj.dead) || ((obj.sprite) && (!obj.sprite.visible)))
  248. continue;
  249. ns.visible = show;
  250. }
  251. }
  252. };
  253. });