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.
 
 
 

327 lines
7.0 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. pos: {
  139. x: obj.x,
  140. y: obj.y
  141. },
  142. instant: true
  143. });
  144. }
  145. this.objects.push(obj);
  146. return obj;
  147. },
  148. updateObject: function (obj, template) {
  149. let components = template.components || [];
  150. components.forEach(c => {
  151. //Map ids to objects
  152. let keys = Object.keys(c).filter(k => {
  153. return (k.indexOf('id') === 0 && k.length > 2);
  154. });
  155. keys.forEach(k => {
  156. let value = c[k];
  157. let newKey = k.substr(2, k.length).toLowerCase();
  158. c[newKey] = this.objects.find(o => o.id === value);
  159. delete c[k];
  160. });
  161. obj.addComponent(c.type, c);
  162. });
  163. delete template.components;
  164. if (template.removeComponents) {
  165. template.removeComponents.forEach(r => {
  166. obj.removeComponent(r);
  167. });
  168. delete template.removeComponents;
  169. }
  170. let oldX = obj.x;
  171. let sprite = obj.sprite;
  172. for (let p in template) {
  173. let value = template[p];
  174. let type = typeof (value);
  175. if (type !== 'object')
  176. obj[p] = value;
  177. if (p === 'casting') {
  178. if (obj === window.player)
  179. events.emit('onGetSelfCasting', value);
  180. else
  181. events.emit('onGetTargetCasting', obj.id, value);
  182. }
  183. if (sprite) {
  184. if (p === 'x') {
  185. if (obj.x < oldX)
  186. obj.flipX = true;
  187. else if (obj.x > oldX)
  188. obj.flipX = false;
  189. }
  190. }
  191. }
  192. if (((template.sheetName) || (template.cell)) && (sprite))
  193. renderer.setSprite(obj);
  194. if ((!obj.sprite) && (template.sheetName))
  195. obj.sprite = renderer.buildObject(obj);
  196. if (template.filters && !obj.sprite?.filters?.length)
  197. renderer.addFilter(obj.sprite, template.filters[0]);
  198. else if (template.filters && template.filters.length === 0 && obj.sprite?.filters?.length > 0)
  199. renderer.removeFilter(obj.sprite);
  200. if (template.name) {
  201. if (obj.nameSprite)
  202. renderer.destroyObject({ sprite: obj.nameSprite });
  203. obj.nameSprite = renderer.buildText({
  204. layerName: 'effects',
  205. text: template.name,
  206. x: (obj.x * scale) + (scale / 2),
  207. y: (obj.y * scale) + scale
  208. });
  209. obj.nameSprite.visible = config.showNames;
  210. }
  211. if ((template.x !== 0) || (template.y !== 0)) {
  212. obj.updateVisibility();
  213. obj.setSpritePosition();
  214. if (obj.stats)
  215. obj.stats.updateHpSprite();
  216. }
  217. },
  218. update: function () {
  219. let objects = this.objects;
  220. let len = objects.length;
  221. for (let i = 0; i < len; i++) {
  222. let o = objects[i];
  223. if (o.destroyed) {
  224. o.destroy();
  225. objects.splice(i, 1);
  226. i--;
  227. len--;
  228. continue;
  229. }
  230. o.update();
  231. }
  232. },
  233. onTilesVisible: function (tiles, visible) {
  234. let objects = this.objects;
  235. let oLen = objects.length;
  236. for (let i = 0; i < oLen; i++) {
  237. let o = objects[i];
  238. let onPos = tiles.some(t => {
  239. return (!(t.x !== o.x || t.y !== o.y));
  240. });
  241. if (!onPos)
  242. continue;
  243. o.updateVisibility();
  244. }
  245. },
  246. onToggleNameplates: function (show) {
  247. let objects = this.objects;
  248. let oLen = objects.length;
  249. for (let i = 0; i < oLen; i++) {
  250. let obj = objects[i];
  251. let ns = obj.nameSprite;
  252. if ((!ns) || (obj.dead) || ((obj.sprite) && (!obj.sprite.visible)))
  253. continue;
  254. ns.visible = show;
  255. }
  256. }
  257. };
  258. });