|
- define([
- 'items/generator',
- 'items/salvager',
- 'items/enchanter',
- 'objects/objects',
- 'config/classes'
- ], function(
- generator,
- salvager,
- enchanter,
- objects,
- classes
- ) {
- return {
- type: 'inventory',
-
- inventorySize: 50,
- items: [],
-
- blueprint: null,
-
- init: function(blueprint, isTransfer) {
- var items = blueprint.items || [];
- var iLen = items.length;
-
- //Spells should be sorted so they're EQ'd in the right order
- items.sort(function(a, b) {
- var aId = (a.spellId != null) ? ~~a.spellId : 9999;
- var bId = (b.spellId != null) ? ~~b.spellId : 9999;
- return (aId - bId);
- });
-
- for (var i = 0; i < iLen; i++) {
- var item = items[i];
-
- if ((item.spell) && (!item.spell.rolls))
- continue;
-
- if (item.effects) {
- item.effects.forEach(function(e) {
- var faction = require('config/factions/' + e.factionId);
- var statGenerator = faction.uniqueStat;
- statGenerator.generate(item);
- });
- }
-
- this.getItem(items[i], true);
- }
-
- if ((this.obj.player) && (!isTransfer)) {
- this.getDefaultAbilities();
-
- /*this.getItem(generator.generate({
- spell: true,
- spellName: 'arcane barrier'
- }));*/
-
- /*for (var i = 0; i < 10; i++) {
- var item = generator.generate({
- slot: 'twoHanded',
- quality: 4,
- level: 1
- });
-
- this.getItem(item);
- }*/
- }
-
- delete blueprint.items;
-
- this.blueprint = blueprint;
- },
-
- //Client Actions
-
- enchantItem: function(msg) {
- var item = this.findItem(msg.itemId);
- if ((!item) || (!item.slot) || (item.eq) || ((msg.action == 'scour') && (item.power == 0))) {
- this.resolveCallback(msg);
- return;
- }
-
- enchanter.enchant(this.obj, item, msg);
- },
-
- getEnchantMaterials: function(msg) {
- var result = [];
- var item = this.findItem(msg.itemId);
- if ((item) && (item.slot))
- result = enchanter.getEnchantMaterials(item, msg.action);
-
- this.resolveCallback(msg, result);
- },
-
- learnAbility: function(id, forceLearn) {
- var replaceId = null;
- var newSpellId = id.spellId;
- if (id.id != null) {
- replaceId = id.replaceId;
- id = id.id;
- }
-
- var item = this.findItem(id);
- if ((!item) || (!item.spell) || ((item.spellId == null) && (item.eq) && (!forceLearn))) {
- if (item)
- item.eq = false;
- return;
- }
-
- var spellbook = this.obj.spellbook;
-
- if ((item.eq) && (!forceLearn)) {
- delete item.eq;
- spellbook.removeSpellById(item.spellId);
- delete item.spellId;
- this.obj.syncer.setArray(true, 'inventory', 'getItems', item);
- return;
- }
-
- if (replaceId != null) {
- var replaceItem = this.findItem(replaceId);
- if (replaceItem) {
- delete replaceItem.eq;
- spellbook.removeSpellById(replaceItem.spellId);
- newSpellId = replaceItem.spellId;
- delete replaceItem.spellId;
- this.obj.syncer.setArray(true, 'inventory', 'getItems', replaceItem);
- }
- }
-
- if (spellbook.spells.length >= 3) {
- if (item.slot)
- item.spellId = -1;
- this.obj.syncer.setArray(true, 'inventory', 'getItems', item);
- return;
- }
-
- item.spellId = spellbook.addSpellFromRune(item.spell, newSpellId);
- if (item.spellId != -1)
- item.eq = true;
- else
- delete item.spell;
- this.obj.syncer.setArray(true, 'inventory', 'getItems', item);
- },
-
- stashItem: function(id) {
- var item = this.findItem(id);
- if ((!item) || (item.quest) || (item.noSalvage))
- return;
-
- delete item.pos;
-
- var stash = this.obj.stash;
- if (!stash.active)
- return;
-
- var clonedItem = extend(true, {}, item);
- this.destroyItem(id);
- stash.deposit(clonedItem);
- },
-
- salvageItem: function(id) {
- var item = this.findItem(id);
- if ((!item) || (item.material) || (item.quest) || (item.noSalvage) || (item.eq))
- return;
-
- var messages = [];
-
- var items = salvager.salvage(item);
- var iLen = items.length;
-
- if (!iLen)
- return;
-
- for (var i = 0; i < iLen; i++) {
- var material = items[i];
-
- this.getItem(material, true);
-
- messages.push({
- class: 'q' + material.quality,
- message: 'salvage (' + material.name + ' x' + material.quantity + ')'
- });
- }
-
- this.obj.instance.syncer.queue('onGetMessages', {
- id: this.obj.id,
- messages: messages
- }, [this.obj.serverId]);
-
- this.destroyItem(id);
- },
-
- destroyItem: function(id, amount) {
- var item = this.findItem(id);
- if (!item)
- return;
-
- amount = amount || item.quantity;
-
- if (item.eq)
- this.obj.equipment.unequip(id);
-
- if ((item.quantity) && (amount)) {
- item.quantity -= amount;
- if (item.quantity <= 0) {
- this.items.spliceWhere(i => i.id == id);
- this.obj.syncer.setArray(true, 'inventory', 'destroyItems', id);
- } else
- this.obj.syncer.setArray(true, 'inventory', 'getItems', item);
- } else {
- this.items.spliceWhere(i => i.id == id);
- this.obj.syncer.setArray(true, 'inventory', 'destroyItems', id);
- }
-
- if (this.obj.player)
- this.getDefaultAbilities();
-
- this.obj.fireEvent('afterDestroyItem', item, amount);
-
- return item;
- },
-
- dropItem: function(id) {
- var item = this.findItem(id);
- if (!item)
- return;
-
- delete item.pos;
-
- //Find close open position
- var x = this.obj.x;
- var y = this.obj.y;
- var dropCell = this.obj.instance.physics.getOpenCellInArea(x - 1, y - 1, x + 1, y + 1);
- if (!dropCell)
- return;
-
- if (item.eq)
- this.obj.equipment.unequip(id);
-
- this.items.spliceWhere(i => i.id == id);
-
- this.obj.syncer.setArray(true, 'inventory', 'destroyItems', id);
-
- this.createBag(dropCell.x, dropCell.y, [item]);
- },
-
- moveItem: function(msgs) {
- msgs.forEach(function(m) {
- var item = this.findItem(m.id);
- if (!item)
- return;
-
- item.pos = m.pos;
- }, this);
- },
-
- //Helpers
-
- resolveCallback: function(msg, result) {
- var callbackId = (msg.callbackId != null) ? msg.callbackId : msg;
- result = result || [];
-
- if (callbackId == null)
- return;
-
- this.obj.instance.syncer.queue('serverModule', {
- module: 'atlas',
- method: 'resolveCallback',
- msg: {
- id: callbackId,
- result: result
- }
- });
- },
-
- findItem: function(id) {
- if (id == null)
- return null;
-
- return this.items.find(i => i.id == id);
- },
-
- getDefaultAbilities: function() {
- var hasWeapon = this.items.some(function(i) {
- return (
- (i.spell) &&
- (i.spell.rolls) &&
- (i.spell.rolls.damage != null) &&
- (i.slot == 'twoHanded')
- );
- });
-
- if (!hasWeapon) {
- var item = generator.generate({
- slot: 'twoHanded',
- type: classes.weapons[this.obj.class],
- quality: 0,
- spellQuality: 'mid'
- });
- item.eq = true;
- item.noSalvage = true;
- this.getItem(item);
- }
-
- var hasSpell = this.items.some(function(i) {
- return (
- (i.spell) &&
- (i.spell.rolls) &&
- ((i.spell.rolls.damage != null) || (i.spell.rolls.healing != null)) &&
- (i.slot != 'twoHanded')
- );
- });
-
- if (!hasSpell) {
- var item = generator.generate({
- spell: true,
- spellQuality: 'basic',
- spellName: classes.spells[this.obj.class][0]
- });
- item.eq = true;
- item.noSalvage = true;
- this.getItem(item);
- }
- },
-
- createBag: function(x, y, items, ownerId) {
- if (ownerId == null)
- ownerId = -1;
-
- var bagCell = 50;
-
- var topQuality = 0;
- var iLen = items.length;
- for (var i = 0; i < iLen; i++) {
- var quality = items[i].quality;
- items[i].fromMob = !!this.obj.mob;
- if (quality > topQuality)
- topQuality = quality;
- }
-
- if (topQuality == 0)
- bagCell = 50;
- else if (topQuality < 3)
- bagCell = 51;
- else if (topQuality == 3)
- bagCell = 52;
- else
- bagCell = 53;
-
- var obj = this.obj.instance.objects.buildObjects([{
- sheetName: 'objects',
- cell: bagCell,
- x: x,
- y: y,
- properties: {
- cpnChest: {
- ownerId: ownerId
- },
- cpnInventory: {
- items: extend(true, [], items)
- }
- }
- }]);
-
- return obj;
- },
-
- getItem: function(item, hideMessage) {
- //We need to know if a mob dropped it for quest purposes
- var fromMob = item.fromMob;
-
- if (item.quality == null)
- item.quality = 0;
-
- //Players can't have fromMob items in their inventory but bags can (dropped by a mob)
- if (this.obj.player)
- delete item.fromMob;
-
- //Store the quantity to send to the player
- var quantity = item.quantity;
-
- //Material?
- var exists = false;
- if ((item.material) || (item.quest)) {
- var existItem = this.items.find(i => i.name == item.name);
- if (existItem) {
- exists = true;
- if (!existItem.quantity)
- existItem.quantity = 1;
- existItem.quantity += item.quantity;
- item = existItem;
- }
- }
-
- //Get next id
- if (!exists) {
- var id = 0;
- var items = this.items;
- var iLen = items.length;
-
- var nonEqItems = items.filter(f => !f.eq).length;
-
- if ((nonEqItems >= this.inventorySize) && (!hideMessage)) {
- this.obj.instance.syncer.queue('onGetMessages', {
- id: this.obj.id,
- messages: [{
- class: 'q0',
- message: 'you bags are too full to loot any more items',
- type: 'info'
- }]
- }, [this.obj.serverId]);
-
- return false;
- }
-
- for (var i = 0; i < iLen; i++) {
- var fItem = items[i];
- if (fItem.id >= id) {
- id = fItem.id + 1;
- }
- }
- item.id = id;
-
- if (item.eq)
- delete item.pos;
-
- if ((item.pos == null) && (!item.eq)) {
- var pos = iLen;
- for (var i = 0; i < iLen; i++) {
- if (!items.some(fi => (fi.pos == i))) {
- pos = i;
- break;
- }
- }
- item.pos = pos;
- }
- }
-
- if ((this.obj.player) && (!hideMessage)) {
- var messages = [];
-
- var msg = item.name;
- if (quantity)
- msg += ' x' + quantity;
- messages.push({
- class: 'q' + item.quality,
- message: 'loot (' + msg + ')',
- type: 'loot'
- });
-
- this.obj.instance.syncer.queue('onGetDamage', {
- id: this.obj.id,
- event: true,
- text: 'loot'
- });
-
- this.obj.instance.syncer.queue('onGetMessages', {
- id: this.obj.id,
- messages: messages
- }, [this.obj.serverId]);
- }
-
- //TODO: Remove later, just for test
- if (item.stats) {
- var stats = Object.keys(item.stats);
- var sLen = stats.length
- for (var i = 0; i < sLen; i++) {
- var s = stats[i];
- var val = item.stats[s];
- if (s == 'maxHp') {
- delete item.stats[s];
- item.stats.hpMax = val;
- } else if (s == 'maxMana') {
- delete item.stats[s];
- item.stats.manaMax = val;
- }
- }
- }
-
- if (!exists)
- this.items.push(item);
-
- if (item.eq) {
- if (item.ability)
- this.learnAbility(item.id, true);
- else
- this.obj.equipment.equip(item.id);
- } else {
- if (!item.effects)
- this.obj.syncer.setArray(true, 'inventory', 'getItems', item);
- else {
- var result = extend(true, {}, item);
- result.effects = result.effects.map(e => ({
- factionId: e.factionId,
- text: e.text,
- properties: e.properties
- }));
-
- var reputation = this.obj.reputation;
-
- //Don't do this check if we don't have a reputation cpn. That means this is most likely a bag
- if ((reputation) && (result.factions)) {
- result.factions = result.factions.map(function(f) {
- var faction = reputation.getBlueprint(f.id);
- var factionTier = reputation.getTier(f.id);
-
- var noEquip = null;
- if (factionTier < f.tier)
- noEquip = true;
-
- return {
- name: faction.name,
- tier: f.tier,
- tierName: ['Hated', 'Hostile', 'Unfriendly', 'Neutral', 'Friendly', 'Honored', 'Revered', 'Exalted'][f.tier],
- noEquip: noEquip
- };
- }, this);
- }
-
- this.obj.syncer.setArray(true, 'inventory', 'getItems', result);
- }
- }
-
- if (!hideMessage) {
- if (fromMob)
- this.obj.fireEvent('afterLootMobItem', item);
- }
-
- return item;
- },
-
- dropBag: function(ownerId, killSource) {
- if (!this.blueprint)
- return;
-
- //Only drop loot if this player is in the zone
- var playerObject = this.obj.instance.objects.find(o => o.serverId == ownerId);
- if (!playerObject)
- return;
-
- //Get player's spells' statTypes
- var stats = [];
- playerObject.spellbook.spells.forEach(function(s) {
- var spellStatType = s.statType;
- if (!(spellStatType instanceof Array))
- spellStatType = [spellStatType];
- spellStatType.forEach(function(ss) {
- if (stats.indexOf(ss) == -1)
- stats.push(ss);
- });
- });
-
- var items = this.items;
- var iLen = items.length;
- for (var i = 0; i < iLen; i++) {
- delete items[i].eq;
- delete items[i].pos;
- }
-
- var blueprint = this.blueprint;
-
- if (blueprint.noRandom) {
- this.items = [];
- var blueprints = blueprint.blueprints;
- for (var i = 0; i < blueprints.length; i++) {
- var drop = blueprints[i];
- drop.level = drop.level || level;
- drop.magicFind = magicFind;
-
- this.getItem(generator.generate(drop), true);
- }
-
- killSource.fireEvent('beforeTargetDeath', this.obj, this.items);
-
- if (this.items.length > 0)
- this.createBag(this.obj.x, this.obj.y, this.items, ownerId);
- } else {
- var instancedItems = extend(true, [], this.items);
- var useItems = [];
-
- var magicFind = (blueprint.magicFind || 0) + killSource.stats.values.magicFind;
- for (var i = 0; i < blueprint.rolls; i++) {
- if (Math.random() * 100 >= (blueprint.chance || 35))
- continue;
-
- var useItem = null;
- if (Math.random() < generator.spellChance) {
- useItem = instancedItems
- .filter(item => item.ability);
- if (useItem.length > 0)
- useItem = useItem[~~(Math.random() * useItem.length)];
- }
-
- if (!useItem) {
- var slot = generator.pickRandomSlot();
- var useItem = instancedItems.find(item => item.slot == slot);
- }
-
- if (!useItem)
- useItem = instancedItems[~~(Math.random() * iLen)];
- iLen--;
- instancedItems.spliceWhere(item => item == useItem);
-
- //Spells don't have stats
- if (useItem.stats)
- delete useItem.stats.armor;
-
- var itemBlueprint = {
- level: useItem.level,
- slot: useItem.slot,
- type: useItem.type,
- spell: !!useItem.ability,
- stats: useItem.stats ? Object.keys(useItem.stats) : null,
- magicFind: magicFind
- };
-
- useItem = generator.generate(itemBlueprint);
-
- useItems.push(useItem);
- }
-
- killSource.fireEvent('beforeTargetDeath', this.obj, useItems);
-
- if (useItems.length > 0)
- this.createBag(this.obj.x, this.obj.y, useItems, ownerId);
- }
- },
-
- giveItems: function(obj, hideMessage) {
- var objInventory = obj.inventory;
-
- var messages = [];
-
- var items = this.items;
- var iLen = items.length;
- for (var i = 0; i < iLen; i++) {
- var item = items[i];
-
- if (objInventory.getItem(item, hideMessage)) {
- items.splice(i, 1);
- i--;
- iLen--;
- } else
- return false;
- }
-
- return true;
- },
-
- rollItems: function(party) {
- var items = this.items;
- var iLen = items.length;
- for (var i = 0; i < iLen; i++) {
- var item = items[i];
-
- this.obj.instance.syncer.queue('serverModule', {
- module: 'lootRoller',
- method: 'enqueue',
- msg: {
- party: party,
- item: item
- }
- });
- }
-
- this.items = [];
- },
-
- fireEvent: function(event, args) {
- var items = this.items;
- var iLen = items.length;
- for (var i = 0; i < iLen; i++) {
- var item = items[i];
- var effects = item.effects;
- if (!effects)
- continue;
-
- var eLen = effects.length;
- for (var j = 0; j < eLen; j++) {
- var effect = effects[j];
-
- var effectEvent = effect.events[event];
- if (!effectEvent)
- continue;
-
- effectEvent.call(this.obj, item, args[0]);
- }
- }
- },
-
- clear: function() {
- delete this.items;
- this.items = [];
- },
-
- save: function() {
- return {
- type: 'inventory',
- items: this.items
- };
- },
-
- simplify: function(self) {
- if (!self)
- return null;
-
- var reputation = this.obj.reputation;
-
- return {
- type: 'inventory',
- items: this.items
- .map(function(i) {
- if (!i.effects)
- return i;
- else {
- var item = extend(true, {}, i);
- item.effects = item.effects.map(e => ({
- factionId: e.factionId,
- text: e.text,
- properties: e.properties
- }));
- if (item.factions) {
- item.factions = item.factions.map(function(f) {
- var faction = reputation.getBlueprint(f.id);
- var factionTier = reputation.getTier(f.id);
-
- var noEquip = null;
- if (factionTier < f.tier)
- noEquip = true;
-
- return {
- id: f.id,
- name: faction.name,
- tier: f.tier,
- tierName: ['Hated', 'Hostile', 'Unfriendly', 'Neutral', 'Friendly', 'Honored', 'Revered', 'Exalted'][f.tier],
- noEquip: noEquip
- };
- }, this);
- }
-
- return item;
- }
- })
- };
- }
- };
- });
|