您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 

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