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.
 
 
 

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