Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 

963 рядки
21 KiB

  1. define([
  2. 'items/generator',
  3. 'items/salvager',
  4. 'items/enchanter',
  5. 'objects/objects',
  6. 'config/classes',
  7. 'mtx/mtx',
  8. 'config/factions',
  9. 'misc/events',
  10. 'items/itemEffects'
  11. ], function (
  12. generator,
  13. salvager,
  14. enchanter,
  15. objects,
  16. classes,
  17. mtx,
  18. factions,
  19. events,
  20. itemEffects
  21. ) {
  22. return {
  23. type: 'inventory',
  24. inventorySize: 50,
  25. items: [],
  26. blueprint: null,
  27. init: function (blueprint, isTransfer) {
  28. var items = blueprint.items || [];
  29. var iLen = items.length;
  30. //Spells should be sorted so they're EQ'd in the right order
  31. items.sort(function (a, b) {
  32. var aId = (a.spellId != null) ? ~~a.spellId : 9999;
  33. var bId = (b.spellId != null) ? ~~b.spellId : 9999;
  34. return (aId - bId);
  35. });
  36. for (var i = 0; i < iLen; i++) {
  37. var item = items[i];
  38. if ((item.pos >= this.inventorySize) || (item.eq))
  39. delete item.pos;
  40. //Hacks for old items
  41. if (((item.spell) && (!item.spell.rolls)) || (!item.sprite)) {
  42. items.splice(i, 1);
  43. i--;
  44. iLen--;
  45. continue;
  46. } else if ((item.spell) && (item.type == 'Spear')) {
  47. item.spell.properties = item.spell.properties || {};
  48. item.spell.properties.range = item.range;
  49. } else if (item.quantity == NaN)
  50. item.quantity = 1;
  51. while (item.name.indexOf(`''`) > -1) {
  52. item.name = item.name.replace(`''`, `'`);
  53. }
  54. }
  55. this.hookItemEvents(items);
  56. for (var i = 0; i < iLen; i++) {
  57. var item = items[i];
  58. var pos = item.pos;
  59. var newItem = this.getItem(item, true);
  60. newItem.pos = pos;
  61. }
  62. if ((this.obj.player) && (!isTransfer))
  63. this.getDefaultAbilities();
  64. delete blueprint.items;
  65. this.blueprint = blueprint;
  66. },
  67. transfer: function () {
  68. this.hookItemEvents();
  69. },
  70. hookItemEvents: function (items) {
  71. var items = items || this.items;
  72. var iLen = items.length;
  73. for (var i = 0; i < iLen; i++) {
  74. var item = items[i];
  75. if (item.effects) {
  76. item.effects.forEach(function (e) {
  77. if (e.mtx) {
  78. var mtxUrl = mtx.get(e.mtx);
  79. var mtxModule = require(mtxUrl);
  80. e.events = mtxModule.events;
  81. } else if (e.factionId) {
  82. var faction = factions.getFaction(e.factionId);
  83. var statGenerator = faction.uniqueStat;
  84. statGenerator.generate(item);
  85. } else {
  86. var effectUrl = itemEffects.get(e.type);
  87. var effectModule = require(effectUrl);
  88. e.events = effectModule.events;
  89. }
  90. });
  91. }
  92. if ((item.pos == null) && (!item.eq)) {
  93. var pos = i;
  94. for (var j = 0; j < iLen; j++) {
  95. if (!items.some(fj => (fj.pos == j))) {
  96. pos = j;
  97. break;
  98. }
  99. }
  100. item.pos = pos;
  101. } else if ((!item.eq) && (items.some(ii => ((ii != item) && (ii.pos == item.pos))))) {
  102. var pos = item.pos;
  103. for (var j = 0; j < iLen; j++) {
  104. if (!items.some(fi => ((fi != item) && (fi.pos == j)))) {
  105. pos = j;
  106. break;
  107. }
  108. }
  109. item.pos = pos;
  110. }
  111. }
  112. },
  113. //Client Actions
  114. enchantItem: function (msg) {
  115. var item = this.findItem(msg.itemId);
  116. if ((!item) || (!item.slot) || (item.eq) || (item.noAugment) || ((msg.action == 'scour') && (item.power == 0))) {
  117. this.resolveCallback(msg);
  118. return;
  119. }
  120. enchanter.enchant(this.obj, item, msg);
  121. },
  122. getEnchantMaterials: function (msg) {
  123. var result = [];
  124. var item = this.findItem(msg.itemId);
  125. if ((item) && (item.slot))
  126. result = enchanter.getEnchantMaterials(item, msg.action);
  127. this.resolveCallback(msg, result);
  128. },
  129. learnAbility: function (itemId, runeSlot) {
  130. if (itemId.itemId != null) {
  131. var msg = itemId;
  132. itemId = msg.itemId;
  133. runeSlot = msg.slot;
  134. }
  135. var item = this.findItem(itemId);
  136. if (!item)
  137. return;
  138. else if (!item.spell) {
  139. item.eq = false;
  140. return;
  141. }
  142. var spellbook = this.obj.spellbook;
  143. if (item.slot == 'twoHanded')
  144. runeSlot = 0;
  145. else if (runeSlot == null) {
  146. if (!this.items.some(i => (i.runeSlot == 2)))
  147. runeSlot = 2;
  148. else
  149. runeSlot = 1;
  150. }
  151. var currentEq = this.items.find(i => (i.runeSlot == runeSlot));
  152. if (currentEq) {
  153. spellbook.removeSpellById(runeSlot);
  154. delete currentEq.eq;
  155. delete currentEq.runeSlot;
  156. this.obj.syncer.setArray(true, 'inventory', 'getItems', currentEq);
  157. }
  158. item.eq = true;
  159. item.runeSlot = runeSlot;
  160. delete item.pos;
  161. spellbook.addSpellFromRune(item.spell, runeSlot);
  162. this.obj.syncer.setArray(true, 'inventory', 'getItems', item);
  163. },
  164. activateMtx: function (itemId) {
  165. var item = this.findItem(itemId);
  166. if (!item)
  167. return;
  168. else if (item.type != 'mtx') {
  169. delete item.active;
  170. return;
  171. }
  172. item.active = !item.active;
  173. this.obj.syncer.setArray(true, 'inventory', 'getItems', item);
  174. },
  175. useItem: function (itemId) {
  176. var item = this.findItem(itemId);
  177. if (!item)
  178. return;
  179. if (item.cdMax) {
  180. if (item.cd) {
  181. process.send({
  182. method: 'events',
  183. data: {
  184. 'onGetAnnouncement': [{
  185. obj: {
  186. msg: 'That item is on cooldown'
  187. },
  188. to: [this.obj.serverId]
  189. }]
  190. }
  191. });
  192. return;
  193. }
  194. item.cd = item.cdMax;
  195. }
  196. var result = {};
  197. events.emit('onBeforeUseItem', this.obj, item, result);
  198. if (item.type == 'consumable')
  199. this.destroyItem(itemId, 1);
  200. },
  201. unlearnAbility: function (itemId) {
  202. if (itemId.itemId != null)
  203. itemId = itemId.itemId;
  204. var item = this.findItem(itemId);
  205. if (!item)
  206. return;
  207. else if (!item.spell) {
  208. item.eq = false;
  209. return;
  210. }
  211. var spellbook = this.obj.spellbook;
  212. spellbook.removeSpellById(item.runeSlot);
  213. delete item.eq;
  214. delete item.runeSlot;
  215. this.setItemPosition(itemId);
  216. this.obj.syncer.setArray(true, 'inventory', 'getItems', item);
  217. },
  218. stashItem: function (id) {
  219. var item = this.findItem(id);
  220. if ((!item) || (item.quest) || (item.noStash))
  221. return;
  222. delete item.pos;
  223. var stash = this.obj.stash;
  224. if (!stash.active)
  225. return;
  226. var clonedItem = extend(true, {}, item);
  227. this.destroyItem(id, null, true);
  228. stash.deposit(clonedItem);
  229. },
  230. salvageItem: function (id) {
  231. var item = this.findItem(id);
  232. if ((!item) || (item.material) || (item.quest) || (item.noSalvage) || (item.eq))
  233. return;
  234. var messages = [];
  235. var items = salvager.salvage(item);
  236. var iLen = items.length;
  237. if (!iLen)
  238. return;
  239. for (var i = 0; i < iLen; i++) {
  240. var material = items[i];
  241. this.getItem(material, true);
  242. messages.push({
  243. class: 'q' + material.quality,
  244. message: 'salvage (' + material.name + ' x' + material.quantity + ')'
  245. });
  246. }
  247. this.obj.instance.syncer.queue('onGetMessages', {
  248. id: this.obj.id,
  249. messages: messages
  250. }, [this.obj.serverId]);
  251. this.destroyItem(id);
  252. },
  253. destroyItem: function (id, amount, force) {
  254. var item = this.findItem(id);
  255. if ((!item) || ((item.noDestroy) && (!force)))
  256. return;
  257. amount = amount || item.quantity;
  258. if (item.eq)
  259. this.obj.equipment.unequip(id);
  260. if ((item.quantity) && (amount)) {
  261. item.quantity -= amount;
  262. if (item.quantity <= 0) {
  263. this.items.spliceWhere(i => i.id == id);
  264. this.obj.syncer.setArray(true, 'inventory', 'destroyItems', id);
  265. } else
  266. this.obj.syncer.setArray(true, 'inventory', 'getItems', item);
  267. } else {
  268. this.items.spliceWhere(i => i.id == id);
  269. this.obj.syncer.setArray(true, 'inventory', 'destroyItems', id);
  270. }
  271. if (this.obj.player)
  272. this.getDefaultAbilities();
  273. this.obj.fireEvent('afterDestroyItem', item, amount);
  274. return item;
  275. },
  276. dropItem: function (id) {
  277. var item = this.findItem(id);
  278. if ((!item) || (item.noDrop))
  279. return;
  280. delete item.pos;
  281. //Find close open position
  282. var x = this.obj.x;
  283. var y = this.obj.y;
  284. var dropCell = this.obj.instance.physics.getOpenCellInArea(x - 1, y - 1, x + 1, y + 1);
  285. if (!dropCell)
  286. return;
  287. if (item.eq)
  288. this.obj.equipment.unequip(id);
  289. this.items.spliceWhere(i => i.id == id);
  290. this.obj.syncer.setArray(true, 'inventory', 'destroyItems', id);
  291. this.createBag(dropCell.x, dropCell.y, [item]);
  292. },
  293. moveItem: function (msgs) {
  294. msgs.forEach(function (m) {
  295. var item = this.findItem(m.id);
  296. if (!item)
  297. return;
  298. item.pos = m.pos;
  299. }, this);
  300. },
  301. mailItem: function (msg) {
  302. var item = this.findItem(msg.itemId);
  303. if (!item) {
  304. this.resolveCallback(msg);
  305. return;
  306. }
  307. delete item.pos;
  308. var io = require('security/io');
  309. io.get({
  310. ent: msg.recipient,
  311. field: 'character',
  312. callback: this.onCheckCharExists.bind(this, msg, item)
  313. });
  314. },
  315. onCheckCharExists: function (msg, item, res) {
  316. if (!res) {
  317. this.resolveCallback(msg, 'Recipient does not exist');
  318. return;
  319. }
  320. this.obj.instance.mail.sendMail(msg.recipient, [extend(true, {}, item)]);
  321. this.destroyItem(item.id);
  322. this.resolveCallback(msg);
  323. },
  324. //Helpers
  325. setItemPosition: function (id) {
  326. var item = this.findItem(id);
  327. if (!item)
  328. return;
  329. var iSize = this.inventorySize;
  330. for (var i = 0; i < iSize; i++) {
  331. if (!this.items.some(j => (j.pos == i))) {
  332. item.pos = i;
  333. break;
  334. }
  335. }
  336. },
  337. resolveCallback: function (msg, result) {
  338. var callbackId = (msg.callbackId != null) ? msg.callbackId : msg;
  339. result = result || [];
  340. if (callbackId == null)
  341. return;
  342. this.obj.instance.syncer.queue('serverModule', {
  343. module: 'atlas',
  344. method: 'resolveCallback',
  345. msg: {
  346. id: callbackId,
  347. result: result
  348. }
  349. });
  350. },
  351. findItem: function (id) {
  352. if (id == null)
  353. return null;
  354. return this.items.find(i => i.id == id);
  355. },
  356. getDefaultAbilities: function () {
  357. var hasWeapon = this.items.some(function (i) {
  358. return (
  359. (i.spell) &&
  360. (i.spell.rolls) &&
  361. (i.spell.rolls.damage != null) &&
  362. (i.slot == 'twoHanded')
  363. );
  364. });
  365. if (!hasWeapon) {
  366. var item = generator.generate({
  367. slot: 'twoHanded',
  368. type: classes.weapons[this.obj.class],
  369. quality: 0,
  370. spellQuality: 'mid'
  371. });
  372. item.eq = true;
  373. item.noSalvage = true;
  374. this.getItem(item);
  375. }
  376. classes.spells[this.obj.class].forEach(function (spellName) {
  377. var hasSpell = this.items.some(function (i) {
  378. return (
  379. (i.spell) &&
  380. (i.spell.name.toLowerCase() == spellName)
  381. );
  382. });
  383. if (!hasSpell) {
  384. var item = generator.generate({
  385. spell: true,
  386. spellQuality: 'basic',
  387. spellName: spellName
  388. });
  389. item.eq = true;
  390. item.noSalvage = true;
  391. this.getItem(item);
  392. }
  393. }, this);
  394. },
  395. createBag: function (x, y, items, ownerId) {
  396. if (ownerId == null)
  397. ownerId = -1;
  398. var bagCell = 50;
  399. var topQuality = 0;
  400. var iLen = items.length;
  401. for (var i = 0; i < iLen; i++) {
  402. var quality = items[i].quality;
  403. items[i].fromMob = !!this.obj.mob;
  404. if (quality > topQuality)
  405. topQuality = quality;
  406. }
  407. if (topQuality == 0)
  408. bagCell = 50;
  409. else if (topQuality == 1)
  410. bagCell = 51;
  411. else if (topQuality == 2)
  412. bagCell = 128;
  413. else if (topQuality == 3)
  414. bagCell = 52;
  415. else
  416. bagCell = 53;
  417. var obj = this.obj.instance.objects.buildObjects([{
  418. sheetName: 'objects',
  419. cell: bagCell,
  420. x: x,
  421. y: y,
  422. properties: {
  423. cpnChest: {
  424. ownerId: ownerId
  425. },
  426. cpnInventory: {
  427. items: extend(true, [], items)
  428. }
  429. }
  430. }]);
  431. return obj;
  432. },
  433. getItem: function (item, hideMessage) {
  434. events.emit('onBeforeGetItem', item, this.obj);
  435. //We need to know if a mob dropped it for quest purposes
  436. var fromMob = item.fromMob;
  437. if (item.quality == null)
  438. item.quality = 0;
  439. //Players can't have fromMob items in their inventory but bags can (dropped by a mob)
  440. if (this.obj.player)
  441. delete item.fromMob;
  442. //Store the quantity to send to the player
  443. var quantity = item.quantity;
  444. //Material?
  445. var exists = false;
  446. if (((item.material) || (item.quest) || (item.quantity)) && (!item.noStack)) {
  447. var existItem = this.items.find(i => i.name == item.name);
  448. if (existItem) {
  449. exists = true;
  450. if (!existItem.quantity)
  451. existItem.quantity = 1;
  452. existItem.quantity += (item.quantity || 1);
  453. item = existItem;
  454. }
  455. }
  456. if (!exists)
  457. delete item.pos;
  458. //Get next id
  459. if (!exists) {
  460. var id = 0;
  461. var items = this.items;
  462. var iLen = items.length;
  463. if (this.inventorySize != -1) {
  464. var nonEqItems = items.filter(f => !f.eq).length;
  465. if ((nonEqItems >= this.inventorySize) && (!hideMessage)) {
  466. this.obj.instance.syncer.queue('onGetMessages', {
  467. id: this.obj.id,
  468. messages: [{
  469. class: 'q0',
  470. message: 'you bags are too full to loot any more items',
  471. type: 'info'
  472. }]
  473. }, [this.obj.serverId]);
  474. return false;
  475. }
  476. }
  477. for (var i = 0; i < iLen; i++) {
  478. var fItem = items[i];
  479. if (fItem.id >= id) {
  480. id = fItem.id + 1;
  481. }
  482. }
  483. item.id = id;
  484. if (item.eq)
  485. delete item.pos;
  486. if ((item.pos == null) && (!item.eq)) {
  487. var pos = iLen;
  488. for (var i = 0; i < iLen; i++) {
  489. if (!items.some(fi => (fi.pos == i))) {
  490. pos = i;
  491. break;
  492. }
  493. }
  494. item.pos = pos;
  495. }
  496. }
  497. if ((this.obj.player) && (!hideMessage)) {
  498. var messages = [];
  499. var msg = item.name;
  500. if (quantity)
  501. msg += ' x' + quantity;
  502. else if ((item.stats) && (item.stats.weight))
  503. msg += ` ${item.stats.weight}lb`;
  504. messages.push({
  505. class: 'q' + item.quality,
  506. message: 'loot: {' + msg + '}',
  507. item: item,
  508. type: 'loot'
  509. });
  510. this.obj.instance.syncer.queue('onGetDamage', {
  511. id: this.obj.id,
  512. event: true,
  513. text: 'loot'
  514. });
  515. this.obj.instance.syncer.queue('onGetMessages', {
  516. id: this.obj.id,
  517. messages: messages
  518. }, [this.obj.serverId]);
  519. }
  520. //TODO: Remove later, just for test
  521. if (item.stats) {
  522. var stats = Object.keys(item.stats);
  523. var sLen = stats.length
  524. for (var i = 0; i < sLen; i++) {
  525. var s = stats[i];
  526. var val = item.stats[s];
  527. if (s == 'maxHp') {
  528. delete item.stats[s];
  529. item.stats.hpMax = val;
  530. } else if (s == 'maxMana') {
  531. delete item.stats[s];
  532. item.stats.manaMax = val;
  533. }
  534. }
  535. }
  536. if (item.effects) {
  537. item.effects.forEach(function (e) {
  538. if (e.mtx) {
  539. var mtxUrl = mtx.get(e.mtx);
  540. var mtxModule = require(mtxUrl);
  541. e.events = mtxModule.events;
  542. }
  543. });
  544. }
  545. if (!exists)
  546. this.items.push(item);
  547. if (item.eq) {
  548. if (item.ability)
  549. this.learnAbility(item.id, item.runeSlot);
  550. else
  551. this.obj.equipment.equip(item.id);
  552. } else {
  553. if (!item.effects)
  554. this.obj.syncer.setArray(true, 'inventory', 'getItems', item);
  555. else {
  556. var result = extend(true, {}, item);
  557. result.effects = result.effects.map(e => ({
  558. factionId: e.factionId,
  559. text: e.text,
  560. properties: e.properties
  561. }));
  562. var reputation = this.obj.reputation;
  563. //Don't do this check if we don't have a reputation cpn. That means this is most likely a bag
  564. if ((reputation) && (result.factions)) {
  565. result.factions = result.factions.map(function (f) {
  566. var faction = reputation.getBlueprint(f.id);
  567. var factionTier = reputation.getTier(f.id);
  568. var noEquip = null;
  569. if (factionTier < f.tier)
  570. noEquip = true;
  571. return {
  572. name: faction.name,
  573. tier: f.tier,
  574. tierName: ['Hated', 'Hostile', 'Unfriendly', 'Neutral', 'Friendly', 'Honored', 'Revered', 'Exalted'][f.tier],
  575. noEquip: noEquip
  576. };
  577. }, this);
  578. }
  579. this.obj.syncer.setArray(true, 'inventory', 'getItems', result);
  580. }
  581. }
  582. if (!hideMessage) {
  583. if (fromMob)
  584. this.obj.fireEvent('afterLootMobItem', item);
  585. }
  586. return item;
  587. },
  588. dropBag: function (ownerId, killSource) {
  589. if (!this.blueprint)
  590. return;
  591. //Only drop loot if this player is in the zone
  592. var playerObject = this.obj.instance.objects.find(o => o.serverId == ownerId);
  593. if (!playerObject)
  594. return;
  595. //Get player's spells' statTypes
  596. var stats = [];
  597. playerObject.spellbook.spells.forEach(function (s) {
  598. var spellStatType = s.statType;
  599. if (!(spellStatType instanceof Array))
  600. spellStatType = [spellStatType];
  601. spellStatType.forEach(function (ss) {
  602. if (stats.indexOf(ss) == -1)
  603. stats.push(ss);
  604. });
  605. });
  606. var items = this.items;
  607. var iLen = items.length;
  608. for (var i = 0; i < iLen; i++) {
  609. delete items[i].eq;
  610. delete items[i].pos;
  611. }
  612. var blueprint = this.blueprint;
  613. var savedItems = extend(true, [], this.items);
  614. var instancedItems = extend(true, [], this.items);
  615. this.items = [];
  616. if ((!blueprint.noRandom) || (blueprint.alsoRandom)) {
  617. var magicFind = (blueprint.magicFind || 0);
  618. var bonusMagicFind = killSource.stats.values.magicFind;
  619. for (var i = 0; i < blueprint.rolls; i++) {
  620. if (Math.random() * 100 >= (blueprint.chance || 35))
  621. continue;
  622. /*var useItem = null;
  623. if (Math.random() < generator.spellChance) {
  624. useItem = instancedItems
  625. .filter(item => item.ability);
  626. if (useItem.length > 0)
  627. useItem = useItem[~~(Math.random() * useItem.length)];
  628. }
  629. if (!useItem) {
  630. var slot = generator.pickRandomSlot();
  631. var useItem = instancedItems.find(item => item.slot == slot);
  632. }
  633. if (!useItem)
  634. useItem = instancedItems[~~(Math.random() * iLen)];
  635. iLen--;
  636. instancedItems.spliceWhere(item => item == useItem);
  637. //Spells don't have stats
  638. if (useItem.stats)
  639. delete useItem.stats.armor;*/
  640. var itemBlueprint = {
  641. level: this.obj.stats.values.level,
  642. magicFind: magicFind,
  643. bonusMagicFind: bonusMagicFind
  644. };
  645. useItem = generator.generate(itemBlueprint);
  646. this.getItem(useItem);
  647. }
  648. }
  649. if (blueprint.noRandom) {
  650. var blueprints = blueprint.blueprints;
  651. for (var i = 0; i < blueprints.length; i++) {
  652. var drop = blueprints[i];
  653. if ((blueprint.chance) && (~~(Math.random() * 100) >= blueprint.chance))
  654. continue;
  655. else if ((drop.maxLevel) && (drop.maxLevel < killSource.stats.values.level))
  656. continue;
  657. else if ((drop.chance) && (~~(Math.random() * 100) >= drop.chance)) {
  658. continue;
  659. }
  660. drop.level = drop.level || this.obj.stats.values.level;
  661. drop.magicFind = magicFind;
  662. var item = drop;
  663. if (!item.quest)
  664. item = generator.generate(drop);
  665. if (!item.slot)
  666. delete item.level;
  667. this.getItem(item, true);
  668. }
  669. }
  670. killSource.fireEvent('beforeTargetDeath', this.obj, this.items);
  671. events.emit('onBeforeDropBag', this.obj, this.items, killSource);
  672. if (this.items.length > 0)
  673. this.createBag(this.obj.x, this.obj.y, this.items, ownerId);
  674. this.items = savedItems;
  675. },
  676. giveItems: function (obj, hideMessage) {
  677. var objInventory = obj.inventory;
  678. var messages = [];
  679. var items = this.items;
  680. var iLen = items.length;
  681. for (var i = 0; i < iLen; i++) {
  682. var item = items[i];
  683. if (objInventory.getItem(item, hideMessage)) {
  684. items.splice(i, 1);
  685. i--;
  686. iLen--;
  687. } else
  688. return false;
  689. }
  690. return true;
  691. },
  692. rollItems: function (party) {
  693. var items = this.items;
  694. var iLen = items.length;
  695. for (var i = 0; i < iLen; i++) {
  696. var item = items[i];
  697. this.obj.instance.syncer.queue('serverModule', {
  698. module: 'lootRoller',
  699. method: 'enqueue',
  700. msg: {
  701. party: party,
  702. item: item
  703. }
  704. });
  705. }
  706. this.items = [];
  707. },
  708. fireEvent: function (event, args) {
  709. var items = this.items;
  710. var iLen = items.length;
  711. for (var i = 0; i < iLen; i++) {
  712. var item = items[i];
  713. if ((!item.eq) && (!item.active))
  714. continue;
  715. var effects = item.effects;
  716. if (!effects)
  717. continue;
  718. var eLen = effects.length;
  719. for (var j = 0; j < eLen; j++) {
  720. var effect = effects[j];
  721. var effectEvent = effect.events[event];
  722. if (!effectEvent)
  723. continue;
  724. effectEvent.apply(this.obj, [item, ...args]);
  725. }
  726. }
  727. },
  728. clear: function () {
  729. delete this.items;
  730. this.items = [];
  731. },
  732. save: function () {
  733. return {
  734. type: 'inventory',
  735. items: this.items
  736. };
  737. },
  738. simplify: function (self) {
  739. if (!self)
  740. return null;
  741. var reputation = this.obj.reputation;
  742. return {
  743. type: 'inventory',
  744. items: this.items
  745. .map(function (i) {
  746. var item = extend(true, {}, i);
  747. if (item.effects) {
  748. item.effects = item.effects.map(e => ({
  749. factionId: e.factionId,
  750. text: e.text,
  751. properties: e.properties,
  752. mtx: e.mtx,
  753. name: e.name
  754. }));
  755. }
  756. if (item.factions) {
  757. item.factions = item.factions.map(function (f) {
  758. var faction = reputation.getBlueprint(f.id);
  759. var factionTier = reputation.getTier(f.id);
  760. var noEquip = null;
  761. if (factionTier < f.tier)
  762. noEquip = true;
  763. return {
  764. id: f.id,
  765. name: faction.name,
  766. tier: f.tier,
  767. tierName: ['Hated', 'Hostile', 'Unfriendly', 'Neutral', 'Friendly', 'Honored', 'Revered', 'Exalted'][f.tier],
  768. noEquip: noEquip
  769. };
  770. }, this);
  771. }
  772. return item;
  773. })
  774. };
  775. },
  776. update: function () {
  777. var items = this.items;
  778. var iLen = items.length;
  779. for (var i = 0; i < iLen; i++) {
  780. var item = items[i];
  781. if (!item.cd)
  782. continue;
  783. item.cd = 0; //--;
  784. this.obj.syncer.setArray(true, 'inventory', 'getItems', item);
  785. }
  786. }
  787. };
  788. });