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.
 
 
 

316 lines
6.7 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. //We need to set visibility before components kick in as they sometimes need access to isVisible
  117. obj.updateVisibility();
  118. components.forEach(c => {
  119. //Map ids to objects
  120. let keys = Object.keys(c).filter(k => {
  121. return (k.indexOf('id') === 0 && k.length > 2);
  122. });
  123. keys.forEach(k => {
  124. let value = c[k];
  125. let newKey = k.substr(2, k.length).toLowerCase();
  126. c[newKey] = this.objects.find(o => o.id === value);
  127. delete c[k];
  128. });
  129. obj.addComponent(c.type, c);
  130. });
  131. if (obj.self) {
  132. events.emit('onGetPlayer', obj);
  133. window.player = obj;
  134. sound.unload(obj.zoneId);
  135. renderer.setPosition({
  136. x: (obj.x - (renderer.width / (scale * 2))) * scale,
  137. y: (obj.y - (renderer.height / (scale * 2))) * scale
  138. }, true);
  139. }
  140. this.objects.push(obj);
  141. return obj;
  142. },
  143. updateObject: function (obj, template) {
  144. let components = template.components || [];
  145. components.forEach(c => {
  146. //Map ids to objects
  147. let keys = Object.keys(c).filter(k => {
  148. return (k.indexOf('id') === 0 && k.length > 2);
  149. });
  150. keys.forEach(k => {
  151. let value = c[k];
  152. let newKey = k.substr(2, k.length).toLowerCase();
  153. c[newKey] = this.objects.find(o => o.id === value);
  154. delete c[k];
  155. });
  156. obj.addComponent(c.type, c);
  157. });
  158. delete template.components;
  159. if (template.removeComponents) {
  160. template.removeComponents.forEach(r => {
  161. obj.removeComponent(r);
  162. });
  163. delete template.removeComponents;
  164. }
  165. let oldX = obj.x;
  166. let sprite = obj.sprite;
  167. for (let p in template) {
  168. let value = template[p];
  169. let type = typeof (value);
  170. if (type !== 'object')
  171. obj[p] = value;
  172. if (p === 'casting') {
  173. if (obj === window.player)
  174. events.emit('onGetSelfCasting', value);
  175. else
  176. events.emit('onGetTargetCasting', obj.id, value);
  177. }
  178. if (sprite) {
  179. if (p === 'x') {
  180. if (obj.x < oldX)
  181. obj.flipX = true;
  182. else if (obj.x > oldX)
  183. obj.flipX = false;
  184. }
  185. }
  186. }
  187. if (((template.sheetName) || (template.cell)) && (sprite))
  188. renderer.setSprite(obj);
  189. if ((!obj.sprite) && (template.sheetName))
  190. obj.sprite = renderer.buildObject(obj);
  191. if (template.name) {
  192. if (obj.nameSprite)
  193. renderer.destroyObject({ sprite: obj.nameSprite });
  194. obj.nameSprite = renderer.buildText({
  195. layerName: 'effects',
  196. text: template.name,
  197. x: (obj.x * scale) + (scale / 2),
  198. y: (obj.y * scale) + scale
  199. });
  200. obj.nameSprite.visible = config.showNames;
  201. }
  202. if ((template.x !== 0) || (template.y !== 0)) {
  203. obj.updateVisibility();
  204. obj.setSpritePosition();
  205. if (obj.stats)
  206. obj.stats.updateHpSprite();
  207. }
  208. },
  209. update: function () {
  210. let objects = this.objects;
  211. let len = objects.length;
  212. for (let i = 0; i < len; i++) {
  213. let o = objects[i];
  214. if (o.destroyed) {
  215. o.destroy();
  216. objects.splice(i, 1);
  217. i--;
  218. len--;
  219. continue;
  220. }
  221. o.update();
  222. }
  223. },
  224. onTilesVisible: function (tiles, visible) {
  225. let objects = this.objects;
  226. let oLen = objects.length;
  227. for (let i = 0; i < oLen; i++) {
  228. let o = objects[i];
  229. let onPos = tiles.some(t => {
  230. return (!(t.x !== o.x || t.y !== o.y));
  231. });
  232. if (!onPos)
  233. continue;
  234. o.updateVisibility();
  235. }
  236. },
  237. onToggleNameplates: function (show) {
  238. let objects = this.objects;
  239. let oLen = objects.length;
  240. for (let i = 0; i < oLen; i++) {
  241. let obj = objects[i];
  242. let ns = obj.nameSprite;
  243. if ((!ns) || (obj.dead) || ((obj.sprite) && (!obj.sprite.visible)))
  244. continue;
  245. ns.visible = show;
  246. }
  247. }
  248. };
  249. });