Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.
 
 
 

415 rindas
8.1 KiB

  1. let components = require('../components/components');
  2. module.exports = {
  3. components: [],
  4. actionQueue: [],
  5. addComponent: function (type, blueprint, isTransfer) {
  6. let cpn = this[type];
  7. if (!cpn) {
  8. let template = components.components[type];
  9. if (!template) {
  10. template = extend({
  11. type: type
  12. }, blueprint || {});
  13. }
  14. cpn = extend({}, template);
  15. cpn.obj = this;
  16. this.components.push(cpn);
  17. this[cpn.type] = cpn;
  18. }
  19. if (cpn.init && this.has('instance'))
  20. cpn.init(blueprint || {}, isTransfer);
  21. else {
  22. for (let p in blueprint)
  23. cpn[p] = blueprint[p];
  24. }
  25. return cpn;
  26. },
  27. removeComponent: function (type) {
  28. let cpn = this[type];
  29. if (!cpn)
  30. return;
  31. cpn.destroyed = true;
  32. },
  33. extendComponent: function (ext, type, blueprint) {
  34. let template = require('../components/extensions/' + type);
  35. let cpn = this[ext];
  36. extend(cpn, template);
  37. if (template.init)
  38. cpn.init(blueprint);
  39. return cpn;
  40. },
  41. update: function () {
  42. let usedTurn = false;
  43. let cpns = this.components;
  44. let len = cpns.length;
  45. for (let i = 0; i < len; i++) {
  46. let c = cpns[i];
  47. if (c.destroyed) {
  48. this.syncer.setSelfArray(false, 'removeComponents', c.type);
  49. cpns.spliceWhere(f => (f === c));
  50. delete this[c.type];
  51. len--;
  52. i--;
  53. } else if (c.update) {
  54. if (c.update())
  55. usedTurn = true;
  56. }
  57. }
  58. if (!usedTurn)
  59. this.performQueue();
  60. },
  61. getSimple: function (self, isSave, isTransfer) {
  62. let s = this.simplify(null, self, isSave, isTransfer);
  63. if (this.instance)
  64. s.zoneId = this.instance.zoneId;
  65. if (self && !isSave && this.syncer) {
  66. this.syncer.oSelf.components
  67. .forEach(c => {
  68. if (!this[c.type])
  69. s.components.push(c);
  70. });
  71. }
  72. return s;
  73. },
  74. simplify: function (o, self, isSave, isTransfer) {
  75. let result = {};
  76. if (!o) {
  77. result.components = [];
  78. o = this;
  79. }
  80. let syncTypes = ['portrait', 'area'];
  81. for (let p in o) {
  82. let value = o[p];
  83. if (value === null)
  84. continue;
  85. let type = typeof (value);
  86. if (type === 'function')
  87. continue;
  88. else if (type !== 'object')
  89. result[p] = value;
  90. else if (type === 'undefined')
  91. continue;
  92. else {
  93. if (value.type) {
  94. if (!value.simplify) {
  95. if (self) {
  96. result.components.push({
  97. type: value.type
  98. });
  99. }
  100. } else {
  101. let component = null;
  102. if (isSave && value.save)
  103. component = value.save();
  104. else if (isTransfer && value.simplifyTransfer)
  105. component = value.simplifyTransfer();
  106. else
  107. component = value.simplify(self);
  108. if (value.destroyed) {
  109. if (!component) {
  110. component = {
  111. type: value.type
  112. };
  113. }
  114. component.destroyed = true;
  115. }
  116. if (component)
  117. result.components.push(component);
  118. }
  119. } else if (syncTypes.includes(p))
  120. result[p] = value;
  121. continue;
  122. }
  123. }
  124. return result;
  125. },
  126. sendEvent: function (event, data) {
  127. process.send({
  128. method: 'event',
  129. id: this.serverId,
  130. data: {
  131. event: event,
  132. data: data
  133. }
  134. });
  135. },
  136. queue: function (action) {
  137. if (action.action === 'clearQueue') {
  138. let spellbook = this.spellbook;
  139. if (spellbook.isCasting())
  140. spellbook.stopCasting();
  141. else
  142. this.clearQueue();
  143. return;
  144. } else if (action.action === 'spell') {
  145. let spellbook = this.spellbook;
  146. const isCasting = spellbook.isCasting();
  147. if (isCasting && (!action.priority || !spellbook.canCast(action))) {
  148. if (action.auto)
  149. spellbook.queueAuto(action);
  150. return;
  151. }
  152. if (isCasting)
  153. spellbook.stopCasting();
  154. this.actionQueue.spliceWhere(a => a.priority);
  155. this.actionQueue.splice(0, 0, action);
  156. } else {
  157. if (action.priority) {
  158. this.spellbook.stopCasting();
  159. this.actionQueue.splice(0, 0, action);
  160. return;
  161. }
  162. this.actionQueue.push(action);
  163. }
  164. },
  165. dequeue: function () {
  166. if (this.actionQueue.length === 0)
  167. return null;
  168. return this.actionQueue.splice(0, 1)[0];
  169. },
  170. clearQueue: function () {
  171. if (this.has('serverId')) {
  172. this.instance.syncer.queue('onClearQueue', {
  173. id: this.id
  174. }, [this.serverId]);
  175. }
  176. this.actionQueue = [];
  177. this.fireEvent('clearQueue');
  178. },
  179. performAction: function (action) {
  180. if (action.instanceModule)
  181. return;
  182. let cpn = this[action.cpn];
  183. if (!cpn)
  184. return;
  185. cpn[action.method](action.data);
  186. },
  187. performQueue: function () {
  188. let q = this.dequeue();
  189. if (!q)
  190. return;
  191. if (q.action === 'move') {
  192. let maxDistance = 1;
  193. if ((this.actionQueue[0]) && (this.actionQueue[0].action === 'move')) {
  194. let moveEvent = {
  195. sprintChance: this.stats.values.sprintChance || 0
  196. };
  197. this.fireEvent('onBeforeTryMove', moveEvent);
  198. let physics = this.instance.physics;
  199. let sprintChance = moveEvent.sprintChance;
  200. do {
  201. if ((~~(Math.random() * 100) < sprintChance) && (!physics.isTileBlocking(q.data.x, q.data.y))) {
  202. q = this.dequeue();
  203. maxDistance++;
  204. }
  205. sprintChance -= 100;
  206. } while (sprintChance > 0 && this.actionQueue.length > 0);
  207. }
  208. q.maxDistance = maxDistance;
  209. let success = this.performMove(q);
  210. if (!success)
  211. this.clearQueue();
  212. } else if (q.action === 'spell') {
  213. let success = this.spellbook.cast(q);
  214. if (!success)
  215. this.performQueue();
  216. }
  217. },
  218. performMove: function (action) {
  219. let data = action.data;
  220. let physics = this.instance.physics;
  221. if (!action.force) {
  222. if (physics.isTileBlocking(data.x, data.y))
  223. return true;
  224. data.success = true;
  225. this.fireEvent('beforeMove', data);
  226. if (data.success === false) {
  227. action.priority = true;
  228. this.queue(action);
  229. return true;
  230. }
  231. let maxDistance = action.maxDistance || 1;
  232. let deltaX = Math.abs(this.x - data.x);
  233. let deltaY = Math.abs(this.y - data.y);
  234. if (
  235. (
  236. (deltaX > maxDistance) ||
  237. (deltaY > maxDistance)
  238. ) ||
  239. (
  240. (deltaX === 0) &&
  241. (deltaY === 0)
  242. )
  243. )
  244. return false;
  245. }
  246. //Don't allow mob overlap during combat
  247. if ((this.mob) && (this.mob.target)) {
  248. if (physics.addObject(this, data.x, data.y)) {
  249. physics.removeObject(this, this.x, this.y);
  250. this.x = data.x;
  251. this.y = data.y;
  252. } else
  253. return false;
  254. } else {
  255. physics.removeObject(this, this.x, this.y, data.x, data.y);
  256. physics.addObject(this, data.x, data.y, this.x, this.y);
  257. this.x = data.x;
  258. this.y = data.y;
  259. }
  260. let syncer = this.syncer;
  261. syncer.o.x = this.x;
  262. syncer.o.y = this.y;
  263. if (this.aggro)
  264. this.aggro.move();
  265. this.fireEvent('afterMove');
  266. return true;
  267. },
  268. collisionEnter: function (obj) {
  269. let cpns = this.components;
  270. let cLen = cpns.length;
  271. for (let i = 0; i < cLen; i++) {
  272. let c = cpns[i];
  273. if (c.collisionEnter) {
  274. if (c.collisionEnter(obj))
  275. return true;
  276. }
  277. }
  278. },
  279. collisionExit: function (obj) {
  280. let cpns = this.components;
  281. let cLen = cpns.length;
  282. for (let i = 0; i < cLen; i++) {
  283. let c = cpns[i];
  284. if (c.collisionExit)
  285. c.collisionExit(obj);
  286. }
  287. },
  288. fireEvent: function (event) {
  289. let args = [].slice.call(arguments, 1);
  290. let cpns = this.components;
  291. let cLen = cpns.length;
  292. for (let i = 0; i < cLen; i++) {
  293. let cpn = cpns[i];
  294. let events = cpn.events;
  295. if (!events)
  296. continue;
  297. let callback = events[event];
  298. if (!callback)
  299. continue;
  300. callback.apply(cpn, args);
  301. }
  302. if (this.effects)
  303. this.effects.fireEvent(event, args);
  304. if (this.quests)
  305. this.quests.fireEvent(event, args);
  306. if (this.prophecies)
  307. this.prophecies.fireEvent(event, args);
  308. if (this.inventory)
  309. this.inventory.fireEvent(event, args);
  310. if (this.spellbook)
  311. this.spellbook.fireEvent(event, args);
  312. },
  313. destroy: function () {
  314. let cpns = this.components;
  315. let len = cpns.length;
  316. for (let i = 0; i < len; i++) {
  317. let c = cpns[i];
  318. if (c.destroy)
  319. c.destroy();
  320. }
  321. },
  322. toString: function () {
  323. let res = {};
  324. for (let p in this) {
  325. if (['components', 'syncer'].includes(p))
  326. continue;
  327. let val = this[p];
  328. let stringVal = (val && val.toString) ? val.toString() : val;
  329. const type = typeof(val);
  330. if (
  331. type !== 'function' &&
  332. (
  333. type !== 'object' ||
  334. val.type
  335. )
  336. )
  337. res[p] = stringVal;
  338. }
  339. return JSON.stringify(res, null, 4).split('"').join('') + '\r\n';
  340. }
  341. };