using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using DiIiS_NA.Core.Logging; using DiIiS_NA.Core.Helpers.Math; using DiIiS_NA.Core.Storage.AccountDataBase.Entities; using DiIiS_NA.Core.MPQ; using DiIiS_NA.Core.MPQ.FileFormats; using DiIiS_NA.GameServer.Core.Types.SNO; using DiIiS_NA.GameServer.GSSystem.ActorSystem.Implementations; using DiIiS_NA.GameServer.GSSystem.ItemsSystem; using DiIiS_NA.GameServer.MessageSystem; using DiIiS_NA.GameServer.MessageSystem.Message.Definitions.Inventory; using DiIiS_NA.GameServer.MessageSystem.Message.Definitions.ACD; using DiIiS_NA.GameServer.MessageSystem.Message.Definitions.Artisan; using DiIiS_NA.GameServer.MessageSystem.Message.Definitions.Misc; using DiIiS_NA.GameServer.GSSystem.ObjectsSystem; using DiIiS_NA.GameServer.Core; using DiIiS_NA.GameServer.MessageSystem.Message.Fields; using DiIiS_NA.GameServer.MessageSystem.Message.Definitions.Effect; using DiIiS_NA.GameServer.ClientSystem; using DiIiS_NA.GameServer.MessageSystem.Message.Definitions.Base; using static DiIiS_NA.Core.MPQ.FileFormats.GameBalance; using DiIiS_NA.Core.Extensions; namespace DiIiS_NA.GameServer.GSSystem.PlayerSystem { public class Inventory : IMessageConsumer, IRevealable { static readonly Logger Logger = LogManager.CreateLogger(); // Access by ID private readonly Player _owner; // Used, because most information is not in the item class but Actors managed by the world //Values for buying new slots on stash private readonly int[] _stashBuyValue = { 100000, 200000, 300000 }; public bool Loaded { get; private set; } public bool StashLoaded { get; private set; } public bool StashRevealed { get; set; } private Equipment _equipment; private InventoryGrid _inventoryGrid; private InventoryGrid _stashGrid; private InventoryGrid _buybackGrid; private Item _inventoryGold; private Item inventoryPotion; public int BloodShards; public int Platinum; // backpack for spellRunes, their Items are kept in equipment private uint[] _skillSocketRunes; public Inventory(Player owner) { _owner = owner; _equipment = new Equipment(owner); _inventoryGrid = new InventoryGrid(owner, owner.Attributes[GameAttributes.Backpack_Slots] / 10, 10); _stashGrid = new InventoryGrid(owner, owner.Attributes[GameAttributes.Shared_Stash_Slots] / 7, 7, (int)EquipmentSlotId.Stash); _buybackGrid = new InventoryGrid(owner, 1, 20, (int)EquipmentSlotId.VendorBuyback); _skillSocketRunes = new uint[6]; StashRevealed = false; } private void AcceptMoveRequest(Item item) { UpdateCurrencies(); } public List GetBackPackItems() { return new List(_inventoryGrid.Items.Values); } public InventoryGrid GetBag() { return _inventoryGrid; } public List GetStashItems() { return new List(_stashGrid.Items.Values); } public List GetEquippedItems() { return _equipment.Items.Values.ToList(); } public List GetBuybackItems() { return new List(_buybackGrid.Items.Values); } public InventoryGrid GetBuybackGrid() { return _buybackGrid; } public bool HaveEnough(int GBid, int count) { return (_inventoryGrid.TotalItemCount(GBid) + _stashGrid.TotalItemCount(GBid)) >= count; } public void GrabSomeItems(int GBid, int count) { if (_inventoryGrid.HaveEnough(GBid, count)) _inventoryGrid.GrabSomeItems(GBid, count); else { int inBag = _inventoryGrid.TotalItemCount(GBid); _inventoryGrid.GrabSomeItems(GBid, inBag); count -= inBag; _stashGrid.GrabSomeItems(GBid, count); } } public int GetGearScore() { return GetEquippedItems().Where(item => item.Attributes[GameAttributes.Item_Binding_Level_Override] == 0).Select(i => i.Rating).Sum(); } public int GetAvgLevel() { if (GetEquippedItems().Count == 0) return 0; return (int)GetEquippedItems().Select(item => item.ItemDefinition.ItemLevel).Average(); } /// /// Refreshes the visual appearance of the hero /// public void SendVisualInventory(Player player) { //player.InGameClient.SendMessage(message); player.World.BroadcastIfRevealed(plr => new VisualInventoryMessage() { ActorID = _owner.DynamicID(plr), EquipmentList = new VisualEquipment() { Equipment = _equipment.GetVisualEquipment(), CosmeticEquipment = _equipment.GetVisualCosmeticEquipment() }, }, _owner); } public D3.Hero.VisualEquipment GetVisualEquipment() { return _equipment.GetVisualEquipmentForToon(); } public bool HasInventorySpace(Item item) { return _inventoryGrid.HasFreeSpace(item); } /// /// Picks an item up after client request /// /// true if the item was picked up, or false if the player could not pick up the item. public bool PickUp(Item item) { if (_inventoryGrid.Contains(item) || _equipment.IsItemEquipped(item)) return false; // TODO: Autoequip when equipment slot is empty // If Item is Stackable try to add the amount if (item.IsStackable()) { // Find items of same type (GBID) and try to add it to one of them List baseItems = FindSameItems(item.GBHandle.GBID); foreach (Item baseItem in baseItems) { if (baseItem.Attributes[GameAttributes.ItemStackQuantityLo] + item.Attributes[GameAttributes.ItemStackQuantityLo] <= baseItem.ItemDefinition.MaxStackSize) { baseItem.UpdateStackCount(baseItem.Attributes[GameAttributes.ItemStackQuantityLo] + item.Attributes[GameAttributes.ItemStackQuantityLo]); baseItem.Attributes.SendChangedMessage(_owner.InGameClient); // Item amount successful added. Don't place item in inventory instead destroy it. item.Destroy(); return true; } } } bool success = false; if (!_inventoryGrid.HasFreeSpace(item)) { // Inventory full _owner.InGameClient.SendMessage(new ACDPickupFailedMessage() { IsCurrency = false, Reason = ACDPickupFailedMessage.Reasons.InventoryFull, ItemID = unchecked((uint)-1) }); _owner.PlayEffect(Effect.PickupFailOverburden1, null, false); } else { item.CurrentState = ItemState.PickingUp; if (item.HasWorldLocation && item.World != null) { item.Owner = _owner; item.World.Leave(item); } _inventoryGrid.AddItem(item); if (_owner.GroundItems.ContainsKey(item.GlobalID)) _owner.GroundItems.Remove(item.GlobalID); success = true; item.CurrentState = ItemState.Normal; foreach (var plr in _owner.World.Players.Values) if (plr != _owner) item.Unreveal(plr); AcceptMoveRequest(item); } //System.Threading.Thread.Sleep(10000); if (item.ItemType.Name.Contains("TemplarSpecial")) _owner.GrantCriteria(74987243307208); if (item.ItemType.Name.Contains("EnchantressSpecial")) _owner.GrantCriteria(74987243308421); if (item.ItemType.Name.Contains("ScoundrelSpecial")) _owner.GrantCriteria(74987243308422); _owner.PlayEffect(Effect.Sound, 196576); return success; } /// /// Used for equiping item /// /// /// public void EquipItem(Item item, int slot, bool save = true) { _equipment.EquipItem(item, slot, save); if (save) ChangeItemSlotDB(slot, item); } public List PublicFindSameItems(int gbid) { return FindSameItems(gbid); } private List FindSameItems(int gbid) { return _inventoryGrid.Items.Values.Where(i => i.GBHandle.GBID == gbid).ToList(); } private static readonly List OneHandedWeapons = new List{ "Axe", "Sword", "Mace", "FistWeapon", "MightyWeapon1H", "Flail1H", "CeremonialDagger", "Dagger", "Spear", "HandXbow", "Wand" }; private static readonly List TwoHandedWeapons = new List{ "Axe2H", "Sword2H", "Mace2H", "CombatStaff", "MightyWeapon2H", "Staff", "Flail2H", "Polearm", "Bow", "Crossbow" }; public void BuyItem(ActorSystem.Actor vendor, Item originalItem, bool buyback) { if (originalItem.ItemDefinition.Name.StartsWith("PH_")) { string itemType = originalItem.ItemDefinition.Name.Substring(3); if (itemType.Contains("1HWeapon")) itemType = OneHandedWeapons.PickRandom(); if (itemType.Contains("2HWeapon")) itemType = TwoHandedWeapons.PickRandom(); if (itemType.Contains("Pants")) itemType = "Legs"; _inventoryGrid.AddItem(ItemGenerator.GetRandomItemOfType(_owner, ItemGroup.FromString(itemType))); } else { if (Item.IsDye(originalItem.ItemType) || Item.IsPotion(originalItem.ItemType)) { Item newItem = ItemGenerator.CloneItem(originalItem); newItem.DBInventory = null; _inventoryGrid.AddItem(newItem); } else { if (buyback) _buybackGrid.DeleteItem(originalItem); else (vendor as Vendor).DeleteItem(originalItem); _inventoryGrid.AddItem(originalItem); } } } public void SellItem(ActorSystem.Actor vendor, int itemId) { Item item = _inventoryGrid.GetItemByDynId(_owner, (uint)itemId); if (item == null) return; int cost = (int)Math.Floor(item.GetPrice() / 25f) * Math.Max(1, item.Attributes[GameAttributes.Gold]); _inventoryGrid.RemoveItem(item); item.Unreveal(_owner); AddGoldAmount(cost); (vendor as Vendor).AddBuybackItem(item, _owner); _owner.PlayEffect(Effect.Sound, 36744); } public bool CheckItemSlots(Item target_item, int destination_slot) { if (destination_slot == 0 || destination_slot == 15) return true; //bag and stash if (Item.IsGem(target_item.ItemType)) return false; //can't equip gem if (target_item.Attributes[GameAttributes.Requirement, 67] > (_owner.Level + 5)) return false; //can't equip too high level if (destination_slot == 14 || destination_slot == 16 || destination_slot == 17) return false; //can't equip in utility slots if (!(destination_slot == 3 || destination_slot == 4 || destination_slot == 21 || destination_slot == 22) && Item.IsWeapon(target_item.ItemType)) return false; //can't equip weapon in another slots if (destination_slot != 1 && destination_slot != 27 && Item.IsHelm(target_item.ItemType)) return false; //can't equip helm in another slots if (destination_slot != 2 && destination_slot != 28 && Item.IsChestArmor(target_item.ItemType)) return false; //can't equip chest in another slots if (!(destination_slot == 13 || destination_slot == 24) && Item.IsAmulet(target_item.ItemType)) return false; //can't equip amulets in another slots if (!(destination_slot == 11 || destination_slot == 12 || destination_slot == 25 || destination_slot == 26) && Item.IsRing(target_item.ItemType)) return false; //can't equip rings in another slots return true; } /// /// Handles a request to move an item within the inventory. /// This covers moving items within the backpack, from equipment /// slot to backpack and from backpack to equipment slot /// public void HandleInventoryRequestMoveMessage(InventoryRequestMoveMessage request) { // TODO Normal inventory movement does not require setting of inv loc msg! Just Tick. /fasbat Item item = GetItemByDynId(_owner, request.ItemID); if (item == null) { if (_owner.ActiveHireling == null) return; else item = _owner.ActiveHireling.GetItemByDynId(_owner, request.ItemID); } if (!CheckItemSlots(item, request.Location.EquipmentSlot)) return; if (item.InvLoc(_owner).EquipmentSlot > 20) { if (_owner.ActiveHireling != null) _owner.ActiveHireling.UnequipItem(_owner, item.InvLoc(_owner).EquipmentSlot, item); return; } if (request.Location.EquipmentSlot > 20) { var sourceGrid = (item.InvLoc(_owner).EquipmentSlot == 0 ? _inventoryGrid : item.InvLoc(_owner).EquipmentSlot == (int)EquipmentSlotId.Stash ? _stashGrid : null); sourceGrid.UnplaceItem(item); if (_owner.ActiveHireling != null) { _owner.ActiveHireling.UnequipItemFromSlot(_owner, request.Location.EquipmentSlot); _owner.ActiveHireling.EquipItem(_owner, request.Location.EquipmentSlot, item); } return; } // Request to equip item from backpack if (request.Location.EquipmentSlot != 0 && request.Location.EquipmentSlot != (int)EquipmentSlotId.Stash) { var sourceGrid = (item.InvLoc(_owner).EquipmentSlot == 0 ? _inventoryGrid : item.InvLoc(_owner).EquipmentSlot == (int)EquipmentSlotId.Stash ? _stashGrid : null); //System.Diagnostics.Debug.Assert((sourceGrid != null && sourceGrid.Contains(request.ItemID)) || _equipment.IsItemEquipped(request.ItemID), "Request to equip unknown item"); int targetEquipSlot = request.Location.EquipmentSlot; if (Item.Is2H(item.ItemType)) targetEquipSlot = (int)EquipmentSlotId.Main_Hand; if (IsValidEquipmentRequest(item, targetEquipSlot)) { Item oldEquipItem = _equipment.GetEquipment(targetEquipSlot); // check if equipment slot is empty if (oldEquipItem == null) { // determine if item is in backpack or switching item from position with target originally empty if (sourceGrid == null) _equipment.UnequipItem(item); else sourceGrid.UnplaceItem(item); _equipment.EquipItem(item, targetEquipSlot); AcceptMoveRequest(item); } else { // check if item is already equipped at another equipmentslot if (_equipment.IsItemEquipped(item)) { // switch both items if (!IsValidEquipmentRequest(oldEquipItem, item.EquipmentSlot)) return; int oldEquipmentSlot = _equipment.UnequipItem(item); _equipment.EquipItem(item, targetEquipSlot); _equipment.EquipItem(oldEquipItem, oldEquipmentSlot); } else { // Get original location int x = item.InventoryLocation.X; int y = item.InventoryLocation.Y; // equip item and place other item in the backpack sourceGrid.UnplaceItem(item); int oldEquipmentSlot = item.EquipmentSlot; _equipment.UnequipItem(oldEquipItem); ChangeItemSlotDB(oldEquipmentSlot, oldEquipItem); ChangeItemLocationDB(x, y, oldEquipItem); Logger.Trace("HandleInventoryRequestMoveMessage, Slot: {0}, x: {1}, y: {2}", targetEquipSlot, request.Location.Column, request.Location.Row); oldEquipItem.SetInventoryLocation(oldEquipmentSlot, x, y); sourceGrid.PlaceItem(oldEquipItem, y, x); _equipment.EquipItem(item, targetEquipSlot); } AcceptMoveRequest(item); AcceptMoveRequest(oldEquipItem); } SendVisualInventory(_owner); } } // Request to move an item (from backpack or equipmentslot) else { var destGrid = (request.Location.EquipmentSlot == 0 ? _inventoryGrid : _stashGrid); var sourceGrid = (item.EquipmentSlot == 0 ? _inventoryGrid : _stashGrid); if (destGrid.HasFreeSpace(item, request.Location.Row, request.Location.Column)) //if cell is free { if (sourceGrid.GetItemInventorySize(item).Height == 2) { //Item crossitem = sourceGrid.GetItem(request.Location.Column, request.Location.Row + 1); try { Item crossitem = sourceGrid.GetItem(request.Location.Row + 1, request.Location.Column); if (crossitem != null) { sourceGrid.GetItem(request.Location.Row + 1, request.Location.Column); ChangeItemSlotDB(item.EquipmentSlot, crossitem); ChangeItemLocationDB(item.InventoryLocation.X, item.InventoryLocation.Y + 1, crossitem); sourceGrid.PlaceItem(crossitem, item.InventoryLocation.Y + 1, item.InventoryLocation.X); } } catch { Item crossitem = sourceGrid.GetItem(request.Location.Column, request.Location.Row + 1); if (crossitem != null) { sourceGrid.GetItem(request.Location.Row + 1, request.Location.Column); ChangeItemSlotDB(item.EquipmentSlot, crossitem); ChangeItemLocationDB(item.InventoryLocation.X, item.InventoryLocation.Y + 1, crossitem); sourceGrid.PlaceItem(crossitem, item.InventoryLocation.Y + 1, item.InventoryLocation.X); } } } if (_equipment.IsItemEquipped(item)) { _equipment.UnequipItem(item); // Unequip the item SendVisualInventory(_owner); } else { sourceGrid.UnplaceItem(item); } ChangeItemSlotDB(request.Location.EquipmentSlot, item); ChangeItemLocationDB(request.Location.Column, request.Location.Row, item); if (item.InvLoc(_owner).EquipmentSlot != request.Location.EquipmentSlot) AcceptMoveRequest(item); destGrid.PlaceItem(item, request.Location.Row, request.Location.Column); Logger.Trace("HandleInventoryRequestMoveMessage, Slot: {0}, x: {1}, y: {2}", request.Location.EquipmentSlot, request.Location.Column, request.Location.Row); //item.SetInventoryLocation(request.Location.EquipmentSlot, request.Location.Column, request.Location.Row); } else {//if item in cell already exists (swaps them) if (_equipment.IsItemEquipped(item)) { SendVisualInventory(_owner); return; //don't allow to swap item from equipped } Item oldItem = destGrid.GetItem(request.Location.Row, request.Location.Column); if (item.IsStackable() && item.GBHandle.GBID == oldItem.GBHandle.GBID && oldItem.Attributes[GameAttributes.ItemStackQuantityLo] < oldItem.ItemDefinition.MaxStackSize) //if it's stackable and same item (merge stacks) { if (item.Attributes[GameAttributes.ItemStackQuantityLo] + oldItem.Attributes[GameAttributes.ItemStackQuantityLo] <= oldItem.ItemDefinition.MaxStackSize) { oldItem.UpdateStackCount(oldItem.Attributes[GameAttributes.ItemStackQuantityLo] + item.Attributes[GameAttributes.ItemStackQuantityLo]); DestroyInventoryItem(item); oldItem.Attributes.SendChangedMessage((_owner as Player).InGameClient); } else { item.UpdateStackCount(item.Attributes[GameAttributes.ItemStackQuantityLo] - (oldItem.ItemDefinition.MaxStackSize - oldItem.Attributes[GameAttributes.ItemStackQuantityLo])); item.Attributes.SendChangedMessage((_owner as Player).InGameClient); oldItem.UpdateStackCount(oldItem.ItemDefinition.MaxStackSize); oldItem.Attributes.SendChangedMessage((_owner as Player).InGameClient); } Logger.Trace("HandleInventoryRequestMoveMessage(StackMerge) Slot: {0}, x: {1}, y: {2}", request.Location.EquipmentSlot, request.Location.Row, request.Location.Column); } else { bool Replaced = false; bool ReplacedNew = false; if (oldItem == null) oldItem = destGrid.GetItem(request.Location.Row + 1, request.Location.Column); if (oldItem == null) oldItem = destGrid.GetItem(request.Location.Row + 2, request.Location.Column); // Get original location int oldEquipmentSlot = item.EquipmentSlot; int new_x = item.InventoryLocation.X; int new_y = item.InventoryLocation.Y; int old_x = oldItem.InventoryLocation.X; int old_y = oldItem.InventoryLocation.Y; //grab from current positions sourceGrid.UnplaceItem(item); destGrid.UnplaceItem(oldItem); //save to db //InventorySize size = sourceGrid.GetItemInventorySize(item) if (sourceGrid.GetItemInventorySize(item).Height == 2 && destGrid.GetItemInventorySize(oldItem).Height == 1 && new_x == old_x) { if (new_y - old_y < 2 && new_y - old_y > -2) new_y++; } else if (sourceGrid.GetItemInventorySize(item).Height == 1 && destGrid.GetItemInventorySize(oldItem).Height == 2 && new_x == old_x) { if (sourceGrid.HasFreeSpace(oldItem, new_y, new_x)) { if (new_y - old_y <= 2 && new_y - old_y >= -2) new_y--; if (item.InventoryLocation.Y > 0) { var addedItem = destGrid.GetItem(item.InvLoc(_owner).Row - 1, item.InvLoc(_owner).Column); if (addedItem != null) { ChangeItemSlotDB(request.Location.EquipmentSlot, addedItem); ChangeItemLocationDB(old_x, old_y++, addedItem); destGrid.PlaceItem(addedItem, old_y++, old_x); } } else { new_y++; old_y++; } } else { if (new_y < 5) { var addedItem = destGrid.GetItem(item.InvLoc(_owner).Row + 1, item.InvLoc(_owner).Column); if (addedItem != null) { if (sourceGrid.GetItemInventorySize(addedItem).Height != 2) { ChangeItemSlotDB(request.Location.EquipmentSlot, addedItem); ChangeItemLocationDB(old_x, old_y + 1, addedItem); destGrid.PlaceItem(addedItem, old_y + 1, old_x); } }; } else { new_y--; } } } else if (sourceGrid.GetItemInventorySize(item).Height == 1 && destGrid.GetItemInventorySize(oldItem).Height == 2 && new_x != old_x) { if (!sourceGrid.HasFreeSpace(oldItem, item.InvLoc(_owner).Row + 1, item.InvLoc(_owner).Column)) { if (new_y < 5) { var addedItem = destGrid.GetItem(item.InventoryLocation.Y + 1, item.InventoryLocation.X); if (addedItem != null) { if (sourceGrid.GetItemInventorySize(addedItem).Height == 2) { if (!sourceGrid.HasFreeSpace(oldItem)) { // Inventory full _owner.InGameClient.SendMessage(new ACDPickupFailedMessage() { IsCurrency = false, Reason = ACDPickupFailedMessage.Reasons.InventoryFull, ItemID = unchecked((uint)-1) }); _owner.PlayEffect(Effect.PickupFailOverburden1, null, false); } else { sourceGrid.RemoveItem(oldItem); sourceGrid.AddItem(oldItem); ChangeItemSlotDB(oldEquipmentSlot, oldItem); ChangeItemLocationDB(oldItem.InventoryLocation.X, oldItem.InventoryLocation.Y, oldItem); Replaced = true; } } else { ChangeItemSlotDB(request.Location.EquipmentSlot, addedItem); ChangeItemLocationDB(old_x, old_y + 1, addedItem); destGrid.PlaceItem(addedItem, old_y + 1, old_x); } } } else { new_y--; } } /* if (!sourceGrid.HasFreeSpace(oldItem, item.InvLoc(_owner).Row - 1, item.InvLoc(_owner).Column)) { var addedItem = destGrid.GetItem(item.InvLoc(_owner).Row - 1, item.InvLoc(_owner).Column); if (sourceGrid.GetItemInventorySize(addedItem).Height == 2) return; else { if (old_y != 0) old_y--; ChangeItemSlotDB(request.Location.EquipmentSlot, addedItem); ChangeItemLocationDB(old_x, old_y, addedItem); destGrid.PlaceItem(addedItem, old_y, old_x); } } //else if (sourceGrid.HasFreeSpace(oldItem, item.InvLoc(_owner).Row + 1, item.InvLoc(_owner).Column)) // new_y--; else { var addedItem = destGrid.GetItem(item.InvLoc(_owner).Row + 1, item.InvLoc(_owner).Column); if (addedItem != null) { if (sourceGrid.GetItemInventorySize(addedItem).Height == 2) ; else { ChangeItemSlotDB(request.Location.EquipmentSlot, addedItem); ChangeItemLocationDB(old_x, old_y + 1, addedItem); destGrid.PlaceItem(addedItem, old_y + 1, old_x); } } }//*/ } else if (sourceGrid.GetItemInventorySize(item).Height == 2 && destGrid.GetItemInventorySize(oldItem).Height == 2) { old_x = request.Location.Column; old_y = request.Location.Row; if (!sourceGrid.HasFreeSpace(oldItem)) { // Inventory full _owner.InGameClient.SendMessage(new ACDPickupFailedMessage() { IsCurrency = false, Reason = ACDPickupFailedMessage.Reasons.InventoryFull, ItemID = unchecked((uint)-1) }); _owner.PlayEffect(Effect.PickupFailOverburden1, null, false); Replaced = true; ReplacedNew = true; } else { Replaced = true; } } if (!Replaced) { ChangeItemSlotDB(oldEquipmentSlot, oldItem); ChangeItemLocationDB(new_x, new_y, oldItem); } if (!ReplacedNew) { ChangeItemSlotDB(request.Location.EquipmentSlot, item); ChangeItemLocationDB(old_x, old_y, item); } //changing locations Logger.Trace("HandleInventoryRequestMoveMessage, Slot: {0}, x: {1}, y: {2}", request.Location.EquipmentSlot, request.Location.Row, request.Location.Column); //oldItem.SetInventoryLocation(oldEquipmentSlot, x, y); if (!ReplacedNew) destGrid.PlaceItem(item, old_y, old_x); if (!Replaced) sourceGrid.PlaceItem(oldItem, new_y, new_x); if (Replaced) { sourceGrid.RemoveItem(oldItem); sourceGrid.AddItem(oldItem); ChangeItemSlotDB(oldEquipmentSlot, oldItem); ChangeItemLocationDB(oldItem.InventoryLocation.X, oldItem.InventoryLocation.Y, oldItem); } } } } RefreshInventoryToClient(); CheckAchievements(); } private void Recheckall() { } private void CheckAchievements() { if (GetEquippedItems().Count == 0) return; if (GetAvgLevel() >= 25) _owner.GrantAchievement(74987243307124); if (GetAvgLevel() >= 60) _owner.GrantAchievement(74987243307126); var items = GetEquippedItems(); if (items.Any(item => ItemGroup.IsSubType(item.ItemType, "Belt_Barbarian")) && (items.Any(item => ItemGroup.IsSubType(item.ItemType, "MightyWeapon1H")) || items.Any(item => ItemGroup.IsSubType(item.ItemType, "MightyWeapon2H")))) //barb _owner.GrantAchievement(74987243307046); if (items.Any(item => ItemGroup.IsSubType(item.ItemType, "Cloak")) && items.Any(item => ItemGroup.IsSubType(item.ItemType, "HandXbow"))) //dh _owner.GrantAchievement(74987243307058); if (items.Any(item => ItemGroup.IsSubType(item.ItemType, "SpiritStone_Monk")) && (items.Any(item => ItemGroup.IsSubType(item.ItemType, "FistWeapon")) || items.Any(item => ItemGroup.IsSubType(item.ItemType, "CombatStaff")))) //monk _owner.GrantAchievement(74987243307544); if (items.Any(item => ItemGroup.IsSubType(item.ItemType, "VoodooMask")) && items.Any(item => ItemGroup.IsSubType(item.ItemType, "CeremonialDagger")) && items.Any(item => ItemGroup.IsSubType(item.ItemType, "Mojo"))) //wd _owner.GrantAchievement(74987243307561); if (items.Any(item => ItemGroup.IsSubType(item.ItemType, "WizardHat")) && items.Any(item => ItemGroup.IsSubType(item.ItemType, "Wand")) && items.Any(item => ItemGroup.IsSubType(item.ItemType, "Orb"))) //wiz _owner.GrantAchievement(74987243307582); } /// /// Handles a request to move an item from stash the inventory and back /// public void HandleInventoryRequestQuickMoveMessage(InventoryRequestQuickMoveMessage request) { Item item = GetItemByDynId(_owner, request.ItemID); if (item == null || (request.DestEquipmentSlot != (int)EquipmentSlotId.Stash && request.DestEquipmentSlot != (int)EquipmentSlotId.Inventory)) return; if (!CheckItemSlots(item, request.DestEquipmentSlot)) return; // Identify source and destination grids var destinationGrid = request.DestEquipmentSlot == 0 ? _inventoryGrid : _stashGrid; var sourceGrid = request.DestEquipmentSlot == 0 ? _stashGrid : _inventoryGrid; if (destinationGrid.HasFreeSpace(request.DestRowStart, request.DestRowEnd, item)) { var slot = destinationGrid.FindSlotForItem(request.DestRowStart, request.DestRowEnd, item); if (!slot.HasValue) return; sourceGrid.UnplaceItem(item); ChangeItemSlotDB(request.DestEquipmentSlot, item); ChangeItemLocationDB(slot.Value.Column, slot.Value.Row, item); destinationGrid.PlaceItem(item, slot.Value.Row, slot.Value.Column); Logger.Trace("HandleInventoryRequestQuickMoveMessage, Slot: {0}, pos: {1}|{2}, DestRow: {3}|{4}", request.DestEquipmentSlot, slot.Value.Row, slot.Value.Column, request.DestRowStart, request.DestRowEnd); //item.SetInventoryLocation(request.DestEquipmentSlot, slot.Value.Column, slot.Value.Row); } } public void CheckWeapons() { Item itemMainHand = _equipment.GetEquipment(EquipmentSlotId.Main_Hand); Item itemOffHand = _equipment.GetEquipment(EquipmentSlotId.Off_Hand); bool bugged = false; if (itemOffHand == null) return; if (Item.Is2H(itemOffHand.ItemType)) bugged = true; if (itemMainHand != null) { if (Item.Is2H(itemMainHand.ItemType)) { if (Item.IsShield(itemOffHand.ItemType) && !_owner.Attributes[GameAttributes.Allow_2H_And_Shield]) bugged = true; //Crusader - Heavenly Strength if (Item.IsBow(itemMainHand.ItemType) && !Item.IsQuiver(itemOffHand.ItemType)) bugged = true; } else { if (Item.IsHandXbow(itemMainHand.ItemType) && !Item.IsHandXbow(itemOffHand.ItemType) && !Item.IsQuiver(itemOffHand.ItemType)) bugged = true; if (!Item.IsHandXbow(itemMainHand.ItemType) && Item.IsHandXbow(itemOffHand.ItemType)) bugged = true; } } if (bugged) { _equipment.UnequipItem(itemMainHand); RemoveItemFromDB(itemMainHand); _inventoryGrid.AddItem(itemMainHand); _equipment.UnequipItem(itemOffHand); RemoveItemFromDB(itemOffHand); _inventoryGrid.AddItem(itemOffHand); SendVisualInventory(_owner); } } public float AdjustDualWieldMin(PowerSystem.DamageType damageType) { float mainDmgMin = 0f; float offDmgMin = 0f; Item itemMainHand = _equipment.GetEquipment(EquipmentSlotId.Main_Hand); Item itemOffHand = _equipment.GetEquipment(EquipmentSlotId.Off_Hand); if (itemMainHand != null) if (itemOffHand != null && !Item.IsOffhand(itemOffHand.ItemType)) { mainDmgMin = itemMainHand.Attributes[GameAttributes.Damage_Weapon_Min_Total, damageType.AttributeKey]; offDmgMin = itemOffHand.Attributes[GameAttributes.Damage_Weapon_Min_Total, damageType.AttributeKey]; } return (mainDmgMin + offDmgMin) * 0.5f; } public float AdjustDualWieldDelta(PowerSystem.DamageType damageType) { float mainDmgDelta = 0f; float offDmgDelta = 0f; Item itemMainHand = _equipment.GetEquipment(EquipmentSlotId.Main_Hand); Item itemOffHand = _equipment.GetEquipment(EquipmentSlotId.Off_Hand); if (itemMainHand != null) if (itemOffHand != null && !Item.IsOffhand(itemOffHand.ItemType)) { mainDmgDelta = itemMainHand.Attributes[GameAttributes.Damage_Weapon_Delta_Total, damageType.AttributeKey]; offDmgDelta = itemOffHand.Attributes[GameAttributes.Damage_Weapon_Delta_Total, damageType.AttributeKey]; } return (mainDmgDelta + offDmgDelta) * 0.5f; } public float GetAPS() { float aps = 0f; Item itemMainHand = _equipment.GetEquipment(EquipmentSlotId.Main_Hand); Item itemOffHand = _equipment.GetEquipment(EquipmentSlotId.Off_Hand); if (itemMainHand != null) { float main_aps = itemMainHand.Attributes[GameAttributes.Attacks_Per_Second_Item]; aps = main_aps; if (itemOffHand != null && !Item.IsOffhand(itemOffHand.ItemType)) { float off_aps = itemOffHand.Attributes[GameAttributes.Attacks_Per_Second_Item]; if (main_aps > 0f && off_aps > 0f) aps = 2f / ((1f / (main_aps * 1.15f)) + (1f / (off_aps * 1.15f))); } } else if (itemOffHand != null) { aps = itemOffHand.Attributes[GameAttributes.Attacks_Per_Second_Item]; } if (aps < 0.5f) aps = 0.5f; return Math.Min(aps, 4f); } public float GetMagicFind() { if (_owner.World == null) return GetItemBonus(GameAttributes.Magic_Find); var difficulty = _owner.World.Game.Difficulty; var mult = 1f; switch (difficulty) { case 0: mult = 0.1f; break; //Normal case 1: mult = 0.2f; break; //Hard case 2: mult = 0.3f; break; //Expert case 3: mult = 0.4f; break; //Master case 4: mult = 0.5f; break; //T1 case 5: mult = 0.6f; break; //T2 case 6: mult = 0.7f; break; //T3 case 7: mult = 0.8f; break; //T4 case 8: mult = 0.9f; break; //T5 case 9: mult = 1f; break; //T6 default: mult = 1f; break; } return GetItemBonus(GameAttributes.Magic_Find) * mult; } public float GetGoldFind() { if (_owner.World == null) return GetItemBonus(GameAttributes.Gold_Find); var difficulty = _owner.World.Game.Difficulty; var mult = 1f; switch (difficulty) { case 0: mult = 0.1f; break; //Normal case 1: mult = 0.2f; break; //Hard case 2: mult = 0.3f; break; //Expert case 3: mult = 0.4f; break; //Master case 4: mult = 0.5f; break; //T1 case 5: mult = 0.6f; break; //T2 case 6: mult = 0.7f; break; //T3 case 7: mult = 0.8f; break; //T4 case 8: mult = 0.9f; break; //T5 case 9: mult = 1f; break; //T6 default: mult = 1f; break; } return GetItemBonus(GameAttributes.Gold_Find) * mult; } /// /// Checks if Item can be equipped at that slot. Handels equipment for Two-Handed-Weapons. /// /// /// /// private bool IsValidEquipmentRequest(Item item, int equipmentSlot) { ItemTypeTable type = item.ItemType; if (equipmentSlot == (int)EquipmentSlotId.Main_Hand) { // useful for 1hand + shield switching, this is to avoid shield to be go to main hand if (!Item.IsWeapon(type)) return false; if (Item.Is2H(type)) { Item itemOffHand = _equipment.GetEquipment(EquipmentSlotId.Off_Hand); if (itemOffHand != null) { if (Item.IsQuiver(itemOffHand.ItemType) && (item.Attributes[GameAttributes.Bow] > 0 || _owner.Attributes[GameAttributes.Crossbow] > 0)) return true; if (Item.IsShield(itemOffHand.ItemType) && _owner.Attributes[GameAttributes.Allow_2H_And_Shield]) if (!Item.IsBow(type) && (_owner.Attributes[GameAttributes.Crossbow] <= 0)) return true; _equipment.UnequipItem(itemOffHand); RemoveItemFromDB(itemOffHand); if (!_inventoryGrid.AddItem(itemOffHand)) { // unequip failed, put back _equipment.EquipItem(itemOffHand, (int)EquipmentSlotId.Off_Hand); return false; } AcceptMoveRequest(itemOffHand); } } } else if (equipmentSlot == (int)EquipmentSlotId.Off_Hand) { Item itemMainHand = _equipment.GetEquipment(EquipmentSlotId.Main_Hand); if (Item.Is2H(type)) { //remove object first to make room for possible unequiped item //_inventoryGrid.RemoveItem(item); if (itemMainHand != null) { _equipment.UnequipItem(itemMainHand); RemoveItemFromDB(itemMainHand); _inventoryGrid.AddItem(itemMainHand); AcceptMoveRequest(itemMainHand); } //_equipment.EquipItem(item, (int)EquipmentSlotId.Main_Hand); //why it's here? it's just a check or not? AcceptMoveRequest(item); SendVisualInventory(_owner); return true; } else if (Item.IsQuiver(type)) { return (_owner.Attributes[GameAttributes.Bow] > 0 || _owner.Attributes[GameAttributes.Crossbow] > 0); } else if (Item.IsShield(type) && _owner.Attributes[GameAttributes.Allow_2H_And_Shield]) { return true; } if (itemMainHand != null) { if (Item.Is2H(itemMainHand.ItemType)) { _equipment.UnequipItem(itemMainHand); RemoveItemFromDB(itemMainHand); if (!_inventoryGrid.AddItem(itemMainHand)) { // unequip failed, put back _equipment.EquipItem(itemMainHand, (int)EquipmentSlotId.Main_Hand); return false; } AcceptMoveRequest(itemMainHand); } } } return true; } /// /// Transfers an amount from one stack to a free space /// public void OnInventorySplitStackMessage(InventorySplitStackMessage msg) { Logger.Trace("OnInventorySplitStackMessage()"); Item itemFrom = GetItemByDynId(_owner, (uint)msg.FromID); int amount = Math.Min((int)msg.Amount, itemFrom.Attributes[GameAttributes.ItemStackQuantityLo] - 1); itemFrom.UpdateStackCount(itemFrom.Attributes[GameAttributes.ItemStackQuantityLo] - amount); itemFrom.Attributes.SendChangedMessage(_owner.InGameClient); Item item = ItemGenerator.CreateItem(_owner, itemFrom.ItemDefinition); item.Owner = _owner; InventoryGrid targetGrid = (msg.InvLoc.EquipmentSlot == (int)EquipmentSlotId.Stash) ? _stashGrid : _inventoryGrid; SaveItemToDB(_owner.Toon.GameAccount.DBGameAccount, _owner.Toon.DbToon, EquipmentSlotId.Inventory, item); ChangeItemLocationDB(msg.InvLoc.Column, msg.InvLoc.Row, item); item.UpdateStackCount(amount); targetGrid.PlaceItem(item, msg.InvLoc.Row, msg.InvLoc.Column); } /// /// Transfers an amount from one stack to another /// public void OnInventoryStackTransferMessage(InventoryStackTransferMessage msg) { Item itemFrom = GetItemByDynId(_owner, msg.FromID); Item itemTo = GetItemByDynId(_owner, msg.ToID); int amount = Math.Min((int)msg.Amount, itemFrom.Attributes[GameAttributes.ItemStackQuantityLo] - 1); itemFrom.UpdateStackCount(itemFrom.Attributes[GameAttributes.ItemStackQuantityLo] - amount); itemTo.UpdateStackCount(itemTo.Attributes[GameAttributes.ItemStackQuantityLo] + amount); itemFrom.Attributes.SendChangedMessage(_owner.InGameClient); itemTo.Attributes.SendChangedMessage(_owner.InGameClient); } private void OnInventoryDropItemMessage(InventoryDropItemMessage msg) { if (_owner.World != null && _owner.World.IsPvP) return; var item = GetItemByDynId(_owner, msg.ItemID); if (item == null) return; // TODO: Throw smthg? /fasbat if (_equipment.IsItemEquipped(item)) { _equipment.UnequipItem(item); SendVisualInventory(_owner); RemoveItemFromDB(item); } else { var sourceGrid = (item.InvLoc(_owner).EquipmentSlot == 0 ? _inventoryGrid : _stashGrid); sourceGrid.RemoveItem(item); } item.CurrentState = ItemState.Dropping; item.Unreveal(_owner); item.SetNewWorld(_owner.World); _owner.World.DropItem(_owner, item); //if (item.DBInventory != null) //_dbInventoriesToDelete.Add(item.DBInventory); item.DBInventory = null; item.CurrentState = ItemState.Normal; AcceptMoveRequest(item); } public void Consume(GameClient client, GameMessage message) { if (client.Game.PvP) return; if (_owner.IsCasting) _owner.StopCasting(); if (message is InventoryRequestMoveMessage moveMessage) HandleInventoryRequestMoveMessage(moveMessage); else if (message is InventoryRequestQuickMoveMessage quickMoveMessage) HandleInventoryRequestQuickMoveMessage(quickMoveMessage); else if (message is InventorySplitStackMessage stackMessage) OnInventorySplitStackMessage(stackMessage); else if (message is InventoryStackTransferMessage transferMessage) OnInventoryStackTransferMessage(transferMessage); else if (message is InventoryDropItemMessage dropItemMessage) OnInventoryDropItemMessage(dropItemMessage); else if (message is InventoryRequestUseMessage useMessage) OnInventoryRequestUseMessage(useMessage); else if (message is InventoryRequestSocketMessage socketMessage) OnSocketMessage(socketMessage); else if (message is InventoryGemsExtractMessage extractMessage) OnGemsExtractMessage(extractMessage); else if (message is RequestBuySharedStashSlotsMessage slotsMessage) OnBuySharedStashSlots(slotsMessage); else if (message is InventoryIdentifyItemMessage identifyItemMessage) OnInventoryIdentifyItemMessage(identifyItemMessage); else if (message is InventoryUseIdentifyItemMessage itemMessage) OnInventoryUseIdentifyItemMessage(itemMessage); else if (message is TrySalvageMessage salvageMessage) OnTrySalvageMessage(salvageMessage); else if (message is TrySalvageAllMessage allMessage) OnTrySalvageAllMessage(allMessage); else if (message is CraftItemsMessage itemsMessage) OnCraftItemMessage(client, itemsMessage); else if (message is EnchantAffixMessage affixMessage) OnEnchantAffixMessage(client, affixMessage); else if (message is TryTransmogItemMessage transmogItemMessage) OnTryTransmogItemMessage(client, transmogItemMessage); else if (message is DyeItemMessage dyeItemMessage) OnDyeItemMessage(client, dyeItemMessage); else if (message is InventoryRepairAllMessage) RepairAll(); else if (message is InventoryRepairEquippedMessage) RepairEquipment(); if (_equipment.EquipmentChanged) { _owner.World.BuffManager.RemoveAllBuffs(_owner, false); _owner.SetAttributesByItems(); _owner.SetAttributesByItemProcs(); _owner.SetAttributesByGems(); _owner.SetAttributesByItemSets(); _owner.SetAttributesByPassives(); _owner.SetAttributesByParagon(); _owner.SetAttributesSkillSets(); CheckWeapons(); _owner.Attributes.BroadcastChangedIfRevealed(); _owner.SaveStats(); _owner.UpdatePercentageHP(_owner.PercHPbeforeChange); _owner.Toon.PvERating = GetGearScore(); _equipment.EquipmentChanged = false; _owner.ToonStateChanged(); } } private void OnDyeItemMessage(GameClient client, DyeItemMessage msg) { _equipment.EquipmentChanged = true; var Item = GetItemByDynId(_owner, msg.ItemID); ; Item.Attributes[GameAttributes.DyeType] = msg.DyeID; Item.Attributes.BroadcastChangedIfRevealed(); RefreshInventoryToClient(); } private void OnEnchantAffixMessage(GameClient client, EnchantAffixMessage msg) { _equipment.EquipmentChanged = true; List ListWithoutNo = new List(); Affix ReloadAffix = null; var EnchData = //(DiIiS_NA.Core.MPQ.FileFormats.GameBalance.EnchantItemAffixUseCountCostScalarsTables) MPQStorage.Data.Assets[SNOGroup.GameBalance][346698].Data; var Item = GetItemByDynId(_owner, (uint)msg.Field0); foreach (var aff in Item.AffixList) if (aff.AffixGbid != msg.GBIDAffixToReroll) ListWithoutNo.Add(aff); else ReloadAffix = aff; if (ReloadAffix == null) return; #region Поиск аффикса bool IsUnique = Item.ItemDefinition.Name.Contains("Unique_"); List itemTypes = ItemGroup.HierarchyToHashList(Item.ItemType); //itemGroups.Add(ItemGroup.GetRootType(item.ItemType)); int levelToFind = (Item.ItemLevel < 5 ? 0 : Math.Min(Item.ItemLevel, 70)); if (Item.GBHandle.GBID == -4139386) levelToFind = 10; if (itemTypes[0] == 828360981) itemTypes.Add(-1028103400); else if (itemTypes[0] == -947867741) itemTypes.Add(3851110); else if (itemTypes[0] == 110504) itemTypes.Add(395678127); else if (itemTypes[0] == 151398954) itemTypes.Add(140775496); Class ItemPlayerClass = Class.None; if (Item.ItemType.Usable.HasFlag(ItemFlags.Barbarian)) ItemPlayerClass = Class.Barbarian; if (Item.ItemType.Usable.HasFlag(ItemFlags.Crusader)) ItemPlayerClass = Class.Crusader; if (Item.ItemType.Usable.HasFlag(ItemFlags.Necromancer)) ItemPlayerClass = Class.Necromancer; if (Item.ItemType.Usable.HasFlag(ItemFlags.DemonHunter)) ItemPlayerClass = Class.DemonHunter; if (Item.ItemType.Usable.HasFlag(ItemFlags.Wizard)) ItemPlayerClass = Class.Wizard; if (Item.ItemType.Usable.HasFlag(ItemFlags.WitchDoctor)) ItemPlayerClass = Class.Witchdoctor; if (Item.ItemType.Usable.HasFlag(ItemFlags.Monk)) ItemPlayerClass = Class.Monk; var filteredList = AffixGenerator.AllAffix.Where(a => //(a.PlayerClass == ItemPlayerClass || a.PlayerClass == Class.None) &&//(a.PlayerClass == ItemPlayerClass || a.PlayerClass == Class.None) && itemTypes.ContainsAtLeastOne(a.ItemGroup) && (a.AffixLevelMax <= ReloadAffix.Definition.AffixLevelMax) && (a.AffixLevelMin >= ReloadAffix.Definition.AffixLevelMin) && (a.OverrideLevelReq <= Item.ItemDefinition.RequiredLevel) ); if (!ReloadAffix.Definition.Name.Contains("Secondary")) filteredList = filteredList.Where( a => !a.Name.Contains("Secondary") ); if (!ReloadAffix.Definition.Name.Contains("Experience")) filteredList = filteredList.Where(a => !a.Name.Contains("Experience")); if (!ReloadAffix.Definition.Name.Contains("Archon")) filteredList = filteredList.Where(a => !a.Name.Contains("Archon")); // FIXME: always true? if (ReloadAffix.Definition.Hash == ReloadAffix.Definition.Hash) filteredList = filteredList.Where(a => a.Hash != ReloadAffix.Definition.Hash); if (Item.GBHandle.GBID == -4139386) filteredList = filteredList.Where( a => !a.Name.Contains("Str") && !a.Name.Contains("Dex") && !a.Name.Contains("Int") && !a.Name.Contains("Vit" )); Dictionary bestDefinitions = new Dictionary(); foreach (var affix_group in filteredList.GroupBy(a => a.AffixFamily0)) { if (Item.AffixFamilies.Contains(affix_group.First().AffixFamily0)) continue; int s = Item.ItemDefinition.RequiredLevel; bestDefinitions[affix_group.First().AffixFamily0] = affix_group.ToList()[FastRandom.Instance.Next(0, 1)]; // FIXME: random always returns 0 } var SocketsAffixs = AffixGenerator.AllAffix.Where(a => a.Name.ToLower().Contains("1xx_socket") && itemTypes.ContainsAtLeastOne(a.ItemGroup)).ToList(); //if (bestDefinitions.Values.Where(a => a.Name.Contains("PoisonD")).Count() > 0) Logger.Debug("PoisonD in bestDefinitions"); List selectedGroups = bestDefinitions.Values .OrderBy(_ => FastRandom.Instance.Next()) //random order .GroupBy(x => x.AffixFamily1 == -1 ? x.AffixFamily0 : x.AffixFamily1) .Select(x => x.First()) // only one from group .Take(1) // take needed amount .ToList(); if (selectedGroups.Count == 0) if (ReloadAffix.Definition.Name.ToLower().Contains("socket")) { selectedGroups = SocketsAffixs .Where(x => x.OverrideLevelReq <= ReloadAffix.Definition.AffixLevelMax) //&& x.AffixLevelMin == ReloadAffix.Definition.AffixLevelMin .OrderBy(_ => FastRandom.Instance.Next()) .Take(1) .ToList(); } else return; #region Удаление действующего аффикса foreach (var effect in ReloadAffix.Definition.AttributeSpecifier) { //if (def.Name.Contains("Sockets")) Logger.Info("socket affix attribute: {0}, {1}", effect.AttributeId, effect.SNOParam); if (effect.AttributeId > 0) { float result; float minValue; float maxValue; if (Item.RandomGenerator == null) Item.RandomGenerator = new ItemRandomHelper(Item.Attributes[GameAttributes.Seed]); if (FormulaScript.Evaluate(effect.Formula.ToArray(), Item.RandomGenerator, out result, out minValue, out maxValue)) { if (effect.AttributeId == 369) continue; //Durability_Max if (effect.AttributeId == 380) //Sockets { result = Math.Max(result, 1f); if (ReloadAffix.Definition.Name.Contains("Chest")) result = (float)FastRandom.Instance.Next(1, 4); if (ReloadAffix.Definition.Name.Contains("Bracer")) result = (float)FastRandom.Instance.Next(1, 3); } if (GameAttributes.Attributes[effect.AttributeId] is GameAttributeF) { var attr = GameAttributes.Attributes[effect.AttributeId] as GameAttributeF; if (effect.SNOParam != -1) Item.Attributes[attr, effect.SNOParam] -= result; else Item.Attributes[attr] -= result; } else if (GameAttributes.Attributes[effect.AttributeId] is GameAttributeI) { var attr = GameAttributes.Attributes[effect.AttributeId] as GameAttributeI; if (effect.SNOParam != -1) Item.Attributes[attr, effect.SNOParam] -= (int)result; else Item.Attributes[attr] -= (int)result; } } } } Item.Attributes.BroadcastChangedIfRevealed(); #endregion foreach (var def in selectedGroups) { if (def != null) { List Scores = new List(); foreach (var effect in def.AttributeSpecifier) { //if (def.Name.Contains("Sockets")) Logger.Info("socket affix attribute: {0}, {1}", effect.AttributeId, effect.SNOParam); if (effect.AttributeId > 0) { float result; float minValue; float maxValue; if (Item.RandomGenerator == null) Item.RandomGenerator = new ItemRandomHelper(Item.Attributes[GameAttributes.Seed]); if (FormulaScript.Evaluate(effect.Formula.ToArray(), Item.RandomGenerator, out result, out minValue, out maxValue)) { if (effect.AttributeId == 369) continue; //Durability_Max if (effect.AttributeId == 380) //Sockets { result = Math.Max(result, 1f); if (def.Name.Contains("Chest")) result = (float)FastRandom.Instance.Next(1, 4); if (def.Name.Contains("Bracer")) result = (float)FastRandom.Instance.Next(1, 3); } float score = (minValue == maxValue ? 0.5f : ((result - minValue) / (maxValue - minValue))); Scores.Add(score); //Logger.Debug("Randomized value for attribute " + GameAttribute.Attributes[effect.AttributeId].Name + "(" + minValue + "," + maxValue + ")" + " is " + result + ", score is " + score); //var tmpAttr = GameAttribute.Attributes[effect.AttributeId]; //var attrName = tmpAttr.Name; // if (GameAttributes.Attributes[effect.AttributeId] is GameAttributeF) { var attr = GameAttributes.Attributes[effect.AttributeId] as GameAttributeF; if (effect.SNOParam != -1) Item.Attributes[attr, effect.SNOParam] += result; else Item.Attributes[attr] += result; } else if (GameAttributes.Attributes[effect.AttributeId] is GameAttributeI) { var attr = GameAttributes.Attributes[effect.AttributeId] as GameAttributeI; if (effect.SNOParam != -1) Item.Attributes[attr, effect.SNOParam] += (int)result; else Item.Attributes[attr] += (int)result; } //Logger.Debug("{0} - Str: {1} ({2})", n, result, item.Attributes[GameAttribute.Attributes[effect.AttributeId] as GameAttributeF]); } } } var affix = new Affix(def.Hash); affix.Score = (Scores.Count == 0 ? 0 : Scores.Average()); //Logger.Debug("Affix " + def.Hash + ", final score is" + affix.Score); Item.AffixList.Clear(); foreach (var Aff in ListWithoutNo) Item.AffixList.Add(Aff); Item.AffixList.Add(affix); if (!IsUnique && !Item.ItemDefinition.Name.Contains("StaffOfCow")) { Item.RareItemName = AffixGenerator.GenerateItemName(); } var affixGbis = new int[Item.AffixList.Count]; for (int i = 0; i < Item.AffixList.Count; i++) { affixGbis[i] = Item.AffixList[i].AffixGbid; } _owner.InGameClient.SendMessage(new AffixMessage() { ActorID = Item.DynamicID(_owner), Field1 = (Item.Unidentified ? 0x00000002 : 0x00000001), aAffixGBIDs = affixGbis, }); //*/ } } #endregion _owner.GrantCriteria(74987255495718); } private void OnTrySalvageAllMessage(TrySalvageAllMessage msg) { int last_item_gbid = 0; int last_item_quality = 0; int count_reward = 0; switch (msg.SalvageType) { // Simple items case 0: foreach (var item in GetBackPackItems()) if (!item.ItemDefinition.Name.ToLower().Contains("potion") && !item.ItemDefinition.Name.ToLower().Contains("gem") && !item.ItemType.Name.ToLower().Contains("gem") && !item.ItemDefinition.Name.ToLower().Contains("book") && !item.ItemDefinition.Name.ToLower().Contains("potion") && !item.ItemDefinition.Name.ToLower().Contains("plan") && !item.ItemDefinition.Name.ToLower().Contains("key") && !item.ItemDefinition.Name.ToLower().Contains("horadric") && !item.ItemDefinition.Name.ToLower().Contains("dye")) if (item.Attributes[GameAttributes.Item_Quality_Level] < 3) { last_item_gbid = item.GBHandle.GBID; last_item_quality = item.Attributes[GameAttributes.Item_Quality_Level]; count_reward += SalvageItem(item); } break; // Magical items case 1: foreach (var item in GetBackPackItems()) if (item.Attributes[GameAttributes.Item_Quality_Level] > 2 & item.Attributes[GameAttributes.Item_Quality_Level] < 6) { last_item_gbid = item.GBHandle.GBID; last_item_quality = item.Attributes[GameAttributes.Item_Quality_Level]; count_reward += SalvageItem(item); } break; // Rare Items case 2: foreach (var item in GetBackPackItems()) if (item.Attributes[GameAttributes.Item_Quality_Level] > 5 & item.Attributes[GameAttributes.Item_Quality_Level] < 9) { last_item_gbid = item.GBHandle.GBID; last_item_quality = item.Attributes[GameAttributes.Item_Quality_Level]; count_reward += SalvageItem(item); } break; } //6-8 Rare //3-5 Magic //012 _owner.InGameClient.SendMessage(new SalvageResultsMessage() { gbidOriginalItem = last_item_gbid, IQLOriginalItem = Math.Min(last_item_quality, 9), MaterialsResults = 1, gbidNewItems = new int[] { msg.SalvageType == 0 ? -363607620 : msg.SalvageType == 1 ? -1585802162 : -605947593, -1, -1, -1 }, MaterialsCounts = new int[] { count_reward, 0, 0, 0 } }); } private int SalvageItem(Item salvageitem) { var item = salvageitem; if (item == null) return 0; if (item.Attributes[GameAttributes.IsCrafted] == true && item.DBInventory.Version > 1) return 0; if (item.Attributes[GameAttributes.Item_Equipped] == true) return 0; string rewardName = "Crafting_"; if (item.ItemLevel >= 60) { if (item.Attributes[GameAttributes.Item_Quality_Level] > 5) rewardName += "Rare_01"; //Veiled Crystal else if (item.Attributes[GameAttributes.Item_Quality_Level] > 2) rewardName += "Magic_01"; //Arcane Dust else rewardName += "AssortedParts_01"; //Reusable Parts } else if (item.Attributes[GameAttributes.Item_Quality_Level] > 5) rewardName += "Rare_01"; //Iridescent Tear else if (item.Attributes[GameAttributes.Item_Quality_Level] > 2) rewardName += "Magic_01"; //Exquisite Essence else rewardName += "AssortedParts_01"; //Common Debris Item reward = ItemGenerator.Cook(_owner, rewardName); int count_reward = RandomHelper.Next(1, 5) * (10 - item.Attributes[GameAttributes.Item_Quality_Level]); var playerAcc = _owner.Toon.GameAccount; if (reward == null) return 0; for (int i = 0; i < count_reward; i++) { switch (rewardName) { case "Crafting_AssortedParts_01": playerAcc.CraftItem1++; break; case "Crafting_Magic_01": playerAcc.CraftItem2++; break; case "Crafting_Rare_01": playerAcc.CraftItem3++; break; } //Item reward1 = ItemGenerator.Cook(_owner, rewardName); //_inventoryGrid.AddItem(reward1); } //reward.Owner = _owner; if (item.DBInventory.FirstGem != -1) { _owner.InGameClient.SendMessage(new GemNotificationMessage()); _inventoryGrid.AddItem(ItemGenerator.CookFromDefinition(_owner.World, ItemGenerator.GetItemDefinition(item.DBInventory.FirstGem))); if (item.DBInventory.SecondGem != -1) _inventoryGrid.AddItem(ItemGenerator.CookFromDefinition(_owner.World, ItemGenerator.GetItemDefinition(item.DBInventory.SecondGem))); if (item.DBInventory.ThirdGem != -1) _inventoryGrid.AddItem(ItemGenerator.CookFromDefinition(_owner.World, ItemGenerator.GetItemDefinition(item.DBInventory.ThirdGem))); foreach (var gem in item.Gems) gem.Unreveal(_owner); item.Gems.Clear(); item.Attributes[GameAttributes.Sockets_Filled] = 0; item.Attributes.BroadcastChangedIfRevealed(); } _inventoryGrid.RemoveItem(item); item.Unreveal(_owner); bool haveBrimstone = false; Item brimstone = null; if (item.Attributes[GameAttributes.Item_Quality_Level] > 8 || FastRandom.Instance.Next(1, 1000) == 1) { if (item.ItemLevel >= 60) rewardName = "Crafting_Legendary_01"; //Forgotten Soul else rewardName = "Crafting_Legendary_01"; //Fiery Brimstone brimstone = ItemGenerator.Cook(_owner, rewardName); if (brimstone != null) { _owner.Toon.GameAccount.CraftItem5++; //_inventoryGrid.AddItem(brimstone); haveBrimstone = true; } } UpdateCurrencies(); _owner.CheckSalvageItemCriteria(reward.GBHandle.GBID); if (haveBrimstone) _owner.CheckSalvageItemCriteria(brimstone.GBHandle.GBID); if (Item.IsWeapon(item.ItemType)) _owner.GrantCriteria(74987243307733); if (Item.IsArmor(item.ItemType)) _owner.GrantCriteria(74987243307734); if (Item.IsAmulet(item.ItemType)) _owner.GrantCriteria(74987243307735); if (Item.IsRing(item.ItemType)) _owner.GrantCriteria(74987243309909); //DestroyInventoryItem(item); return count_reward; } private void OnInventoryIdentifyItemMessage(InventoryIdentifyItemMessage msg) { var item = GetItemByDynId(_owner, msg.ItemID); if (item == null) return; Logger.Warn("Identifying items not implemented yet"); } private void OnInventoryUseIdentifyItemMessage(InventoryUseIdentifyItemMessage msg) { var item = GetItemByDynId(_owner, msg.ItemID); if (item == null) return; int idDuration = 60; _owner.StartCasting(idDuration, new Action(() => { item.Identify(); })); } //* private void OnTrySalvageMessage(TrySalvageMessage msg) { var item = GetItemByDynId(_owner, msg.ActorID); if (item == null) return; //if (item.Attributes[GameAttribute.IsCrafted] == true)// && item.DBInventory.Version > 1) // return; if (item.Attributes[GameAttributes.Item_Equipped] == true) return; string rewardName = "Crafting_"; if (item.ItemLevel >= 60) { if (item.Attributes[GameAttributes.Item_Quality_Level] > 5) rewardName += "Rare_01"; //Veiled Crystal else if (item.Attributes[GameAttributes.Item_Quality_Level] > 2) rewardName += "Magic_01"; //Arcane Dust else rewardName += "AssortedParts_01"; //Reusable Parts } else if (item.Attributes[GameAttributes.Item_Quality_Level] > 5) rewardName += "Rare_01"; //Iridescent Tear else if (item.Attributes[GameAttributes.Item_Quality_Level] > 2) rewardName += "Magic_01"; //Exquisite Essence else rewardName += "AssortedParts_01"; //Common Debris Item reward = ItemGenerator.Cook(_owner, rewardName); int count_reward = RandomHelper.Next(1, 5) * (10 - item.Attributes[GameAttributes.Item_Quality_Level]); if (item.Attributes[GameAttributes.IsCrafted] == true) count_reward /= 4; if (reward == null) return; for (int i = 0; i < count_reward; i++) { switch (rewardName) { case "Crafting_AssortedParts_01": _owner.Toon.GameAccount.CraftItem1++; break; case "Crafting_Magic_01": _owner.Toon.GameAccount.CraftItem2++; break; case "Crafting_Rare_01": _owner.Toon.GameAccount.CraftItem3++; break; } } //reward.Owner = _owner; if (item.DBInventory.FirstGem != -1) { _owner.InGameClient.SendMessage(new GemNotificationMessage()); _inventoryGrid.AddItem(ItemGenerator.CookFromDefinition(_owner.World, ItemGenerator.GetItemDefinition(item.DBInventory.FirstGem))); if (item.DBInventory.SecondGem != -1) _inventoryGrid.AddItem(ItemGenerator.CookFromDefinition(_owner.World, ItemGenerator.GetItemDefinition(item.DBInventory.SecondGem))); if (item.DBInventory.ThirdGem != -1) _inventoryGrid.AddItem(ItemGenerator.CookFromDefinition(_owner.World, ItemGenerator.GetItemDefinition(item.DBInventory.ThirdGem))); foreach (var gem in item.Gems) gem.Unreveal(_owner); item.Gems.Clear(); item.Attributes[GameAttributes.Sockets_Filled] = 0; item.Attributes.BroadcastChangedIfRevealed(); } _inventoryGrid.RemoveItem(item); item.Unreveal(_owner); bool haveBrimstone = false; Item brimstone = null; if (item.Attributes[GameAttributes.Item_Quality_Level] > 8 || FastRandom.Instance.Next(1, 1000) == 1) { if (item.ItemLevel >= 60) rewardName = "Crafting_Legendary_01"; //Forgotten Soul else rewardName = "Crafting_Legendary_01"; //Fiery Brimstone brimstone = ItemGenerator.Cook(_owner, rewardName); if (brimstone != null) { _owner.Toon.GameAccount.CraftItem5++; haveBrimstone = true; } } _owner.InGameClient.SendMessage(new SalvageResultsMessage() { gbidOriginalItem = item.GBHandle.GBID, IQLOriginalItem = Math.Min(item.Attributes[GameAttributes.Item_Quality_Level], 9), MaterialsResults = haveBrimstone ? 2 : 1, gbidNewItems = new int[] { reward.GBHandle.GBID, haveBrimstone ? brimstone.GBHandle.GBID : -1, -1, -1 }, MaterialsCounts = new int[] { count_reward, haveBrimstone ? 1 : 0, 0, 0 } }); UpdateCurrencies(); _owner.CheckSalvageItemCriteria(reward.GBHandle.GBID); if (haveBrimstone) _owner.CheckSalvageItemCriteria(brimstone.GBHandle.GBID); if (Item.IsWeapon(item.ItemType)) _owner.GrantCriteria(74987243307733); if (Item.IsArmor(item.ItemType)) _owner.GrantCriteria(74987243307734); if (Item.IsAmulet(item.ItemType)) _owner.GrantCriteria(74987243307735); if (Item.IsRing(item.ItemType)) _owner.GrantCriteria(74987243309909); //DestroyInventoryItem(item); } //*/ private bool _achievementGranted = false; private bool _radiantAchievementGranted = false; //* private void OnCraftItemMessage(GameClient client, CraftItemsMessage msg) { var recipeGBId = msg.GBIDRecipe; var recipeDefinition = ItemGenerator.GetRecipeDefinition(recipeGBId); //if (!this._owner.RecipeAvailable(recipeDefinition)) return; var recipe = (Recipe)MPQStorage.Data.Assets[SNOGroup.Recipe][recipeDefinition.SNORecipe].Data; var extraAffixCount = recipe.ItemSpecifierData.AdditionalRandomAffixes + FastRandom.Instance.Next(0, recipe.ItemSpecifierData.AdditionalRandomAffixesDelta); Item reward = ItemGenerator.CookFromDefinition(_owner.World, ItemGenerator.GetItemDefinition(recipe.ItemSpecifierData.ItemGBId), Math.Min(extraAffixCount, 9), false, true); reward.Attributes[GameAttributes.ItemStackQuantityLo] = 0; if (!Item.IsAmulet(reward.ItemType) && !Item.IsRing(reward.ItemType)) { if (reward.ItemLevel >= 70) _owner.GrantCriteria(74987254004798); } else { if (reward.ItemLevel >= 70) _owner.GrantCriteria(74987254245219); } if (GetGoldAmount() < recipeDefinition.Gold) return; bool haveEnoughIngredients = true; foreach (var ingr in recipeDefinition.Ingredients) { if (ingr.ItemsGBID == -1 || ingr.ItemsGBID == 0) continue; switch (ingr.ItemsGBID) { case -363607620: // Common parts. if(_owner.Toon.GameAccount.CraftItem1 < ingr.Count) haveEnoughIngredients = false; break; case -1585802162: // Wizard Dust. if (_owner.Toon.GameAccount.CraftItem2 < ingr.Count) haveEnoughIngredients = false; break; case -605947593: // Blurred Crystal. if (_owner.Toon.GameAccount.CraftItem3 < ingr.Count) haveEnoughIngredients = false; break; } if (Item.IsGem(reward.ItemType)) { Item FoundedItem = null; foreach (var item in GetBackPackItems()) if (item.ItemDefinition.Hash == ingr.ItemsGBID) { FoundedItem = item; if (FoundedItem.Attributes[GameAttributes.ItemStackQuantityLo] == ingr.Count) { _inventoryGrid.RemoveItem(FoundedItem); FoundedItem.Unreveal(FoundedItem.Owner as Player); } else if (FoundedItem.Attributes[GameAttributes.ItemStackQuantityLo] > ingr.Count) { FoundedItem.Attributes[GameAttributes.ItemStackQuantityLo] -= ingr.Count; FoundedItem.Attributes.BroadcastChangedIfRevealed(); } else return; } if (FoundedItem == null) foreach (var item in GetStashItems()) if (item.ItemDefinition.Hash == ingr.ItemsGBID) { if (item.Attributes[GameAttributes.ItemStackQuantityLo] == ingr.Count) { _stashGrid.RemoveItem(item); item.Unreveal(item.Owner as Player); } else if(item.Attributes[GameAttributes.ItemStackQuantityLo] > ingr.Count) { item.Attributes[GameAttributes.ItemStackQuantityLo] -= ingr.Count; item.Attributes.BroadcastChangedIfRevealed(); } else return; } } } if (!haveEnoughIngredients) return; foreach (var ingr in recipeDefinition.Ingredients) { if (ingr.ItemsGBID == -1 || ingr.ItemsGBID == 0) continue; switch (ingr.ItemsGBID) { case -363607620: // Common parts. _owner.Toon.GameAccount.CraftItem1 -= ingr.Count; break; case -1585802162: // Wizard Dust. _owner.Toon.GameAccount.CraftItem2 -= ingr.Count; break; case -605947593: // Blurred Crystal. _owner.Toon.GameAccount.CraftItem3 -= ingr.Count; break; } } RemoveGoldAmount(recipeDefinition.Gold); if (Item.IsGem(reward.ItemType)) reward.Attributes[GameAttributes.Item_Quality_Level] = 1; else { foreach (int affixId in recipe.ItemSpecifierData.GBIdAffixes) if (affixId != -1) AffixGenerator.AddAffix(reward, affixId, true); if (reward.ItemDefinition.Name.StartsWith("Unique_")) { AffixGenerator.Generate(reward, recipe.ItemSpecifierData.AdditionalRandomAffixes, true); reward.Attributes[GameAttributes.Item_Quality_Level] = 9; } //else if (!(recipeDefinition.Name.StartsWith("T12_") || recipeDefinition.Name.StartsWith("T11_"))) reward.Attributes[GameAttributes.Item_Quality_Level] = Math.Min(recipe.ItemSpecifierData.AdditionalRandomAffixes + 2 , 9); if (reward.Attributes[GameAttributes.Item_Quality_Level] < 9) { AffixGenerator.Generate(reward, recipe.ItemSpecifierData.AdditionalRandomAffixes, true); } //reward.Attributes[GameAttribute.IsCrafted] = true; } reward.Attributes[GameAttributes.IsCrafted] = true; reward.Attributes[GameAttributes.Attachment_Handled_By_Client] = true; reward.Attributes[GameAttributes.ItemStackQuantityLo]++; if (Item.IsGem(reward.ItemType)) { if (!_achievementGranted) { _achievementGranted = true; _owner.GrantAchievement(74987243307784); } if (_owner.Toon.IsSeasoned) if (Int32.Parse(reward.ItemDefinition.Name.Split('_')[2]) >= 7) { _owner.GrantCriteria(74987245885431); //74987245885431 } if (reward.ItemDefinition.Name.Contains("_06") && !_radiantAchievementGranted) { _radiantAchievementGranted = true; _owner.GrantAchievement(74987243307785); } if (reward.ItemDefinition.Name.Contains("Amethyst")) _owner.GrantCriteria(74987243308254); if (reward.ItemDefinition.Name.Contains("Emerald")) _owner.GrantCriteria(74987243309059); if (reward.ItemDefinition.Name.Contains("Ruby")) _owner.GrantCriteria(74987243309060); if (reward.ItemDefinition.Name.Contains("Topaz")) _owner.GrantCriteria(74987243309061); if (reward.ItemDefinition.Name.Contains("_14")) { _owner.GrantAchievement(74987243307787); if (reward.ItemDefinition.Name.Contains("Amethyst")) _owner.GrantCriteria(74987243309067); if (reward.ItemDefinition.Name.Contains("Emerald")) _owner.GrantCriteria(74987243308256); if (reward.ItemDefinition.Name.Contains("Ruby")) _owner.GrantCriteria(74987243309066); if (reward.ItemDefinition.Name.Contains("Topaz")) _owner.GrantCriteria(74987243309065); } } else { if (reward.Attributes[GameAttributes.Strength_Item] > 0) _owner.GrantCriteria(74987243308238); if (reward.Attributes[GameAttributes.Dexterity_Item] > 0) _owner.GrantCriteria(74987243308941); if (reward.Attributes[GameAttributes.Intelligence_Item] > 0) _owner.GrantCriteria(74987243308942); if (reward.Attributes[GameAttributes.Vitality_Item] > 0) _owner.GrantCriteria(74987243308943); if (reward.Attributes[GameAttributes.Block_Chance_Item_Total] > 0) _owner.GrantCriteria(74987243308239); if (reward.Attributes[GameAttributes.Thorns_Percent_Total] > 0 || reward.Attributes[GameAttributes.Thorns_Fixed, 0] > 0) _owner.GrantCriteria(74987243308945); if (reward.Attributes[GameAttributes.Sockets] > 0) _owner.GrantCriteria(74987243308946); if (reward.Attributes[GameAttributes.Experience_Bonus] > 0 || reward.Attributes[GameAttributes.Experience_Bonus_Percent] > 0) _owner.GrantCriteria(74987243308947); if (reward.Attributes[GameAttributes.Gold_Find_Total] > 0) _owner.GrantCriteria(74987243308948); if (reward.Attributes[GameAttributes.Attacks_Per_Second_Item_Bonus] > 0 || reward.Attributes[GameAttributes.Attacks_Per_Second_Item_Percent] > 0) _owner.GrantCriteria(74987243308949); if (reward.Attributes[GameAttributes.Hitpoints_Regen_Per_Second] > 0) _owner.GrantCriteria(74987243308950); if (reward.Attributes[GameAttributes.Magic_Find_Total] > 0) _owner.GrantCriteria(74987243308951); if (reward.Attributes[GameAttributes.Crit_Percent_Bonus_Capped] > 0 || reward.Attributes[GameAttributes.Crit_Damage_Percent] > 0) _owner.GrantCriteria(74987243308952); if (reward.Attributes[GameAttributes.Movement_Scalar] > 0) _owner.GrantCriteria(74987243312486); if (reward.Attributes[GameAttributes.Resistance, 3] > 0) //cold _owner.GrantCriteria(74987243308240); if (reward.Attributes[GameAttributes.Resource_Regen_Per_Second, 3] > 0) //spirit _owner.GrantCriteria(74987243308954); if (reward.Attributes[GameAttributes.Resource_Max_Bonus, 6] > 0) //discipline _owner.GrantCriteria(74987243308955); if (reward.Attributes[GameAttributes.Resistance, 5] > 0) //arcane _owner.GrantCriteria(74987243308956); if (reward.Attributes[GameAttributes.Resistance, 1] > 0) //fire _owner.GrantCriteria(74987243308957); if (reward.Attributes[GameAttributes.Resistance, 2] > 0) //lightning _owner.GrantCriteria(74987243308958); if (reward.Attributes[GameAttributes.Resistance, 4] > 0) //poison _owner.GrantCriteria(74987243308959); if (reward.Attributes[GameAttributes.Resource_Max_Bonus, 2] > 0) //fury _owner.GrantCriteria(74987243308960); if (reward.Attributes[GameAttributes.Resource_Max_Bonus, 1] > 0) //arcane _owner.GrantCriteria(74987243308961); if (reward.Attributes[GameAttributes.Resource_Max_Bonus, 0] > 0) //mana _owner.GrantCriteria(74987243308962); if (reward.Attributes[GameAttributes.Resistance_All] > 0) _owner.GrantCriteria(74987243308963); if (reward.Attributes[GameAttributes.Hitpoints_On_Hit] > 0 || reward.Attributes[GameAttributes.Steal_Health_Percent] > 0) _owner.GrantCriteria(74987243308966); if (reward.Attributes[GameAttributes.Health_Globe_Bonus_Health] > 0) _owner.GrantCriteria(74987243308967); if (reward.Attributes[GameAttributes.Armor_Bonus_Item] > 0 || reward.Attributes[GameAttributes.Armor_Item_Percent] > 0) _owner.GrantCriteria(74987243308968); } _owner.UpdateQuantity(74987243307366, 1); _owner.UpdateQuantity(74987243307371, 1); _owner.UpdateQuantity(74987243307374, 1); if (reward.Attributes[GameAttributes.ItemStackQuantityLo] > 0) _inventoryGrid.AddItem(reward); client.SendMessage(new CraftingResultsMessage { annItem = reward.GlobalID, GBIDItem = recipe.ItemSpecifierData.ItemGBId, IQL = reward.Attributes[GameAttributes.Item_Quality_Level] }); UpdateCurrencies(); } private void OnTryTransmogItemMessage(GameClient client, TryTransmogItemMessage msg) { Logger.Debug("OnTryTransmogItemMessage, itemID: {0}, GBIDTransmog: {1}", msg.annItem, msg.GBIDTransmog); var item = _inventoryGrid.GetItemByDynId(_owner, msg.annItem); if (item == null) { item = _equipment.GetItemByDynId(_owner, msg.annItem); if (item == null) return; } var transmogItem = ItemGenerator.GetItemDefinition(msg.GBIDTransmog); if (transmogItem == null) return; int amount = transmogItem.TransmogCost; if (GetGoldAmount() >= amount) { RemoveGoldAmount(amount); item.UpdateTransmog(msg.GBIDTransmog); item.Attributes.BroadcastChangedIfRevealed(); SendVisualInventory(_owner); } _owner.GrantCriteria(74987253143400); } //*/ public void OnBuySharedStashSlots(RequestBuySharedStashSlotsMessage requestBuySharedStashSlotsMessage) { int amount = 0; if (_stashGrid.Rows % 10 == 0) { if (_stashGrid.Rows / 10 - 1 >= _stashBuyValue.Length) return; amount = _stashBuyValue[_stashGrid.Rows / 10 - 1]; } if (GetGoldAmount() >= amount) { RemoveGoldAmount(amount); _owner.Attributes[GameAttributes.Shared_Stash_Slots] += 70; _owner.Attributes.BroadcastChangedIfRevealed(); _stashGrid.ResizeGrid(_owner.Attributes[GameAttributes.Shared_Stash_Slots] / 7, 7); var dbGAcc = _owner.Toon.GameAccount.DBGameAccount; dbGAcc.StashSize = _owner.Attributes[GameAttributes.Shared_Stash_Slots]; _owner.World.Game.GameDbSession.SessionUpdate(dbGAcc); } if (_owner.Attributes[GameAttributes.Shared_Stash_Slots] >= 280) _owner.GrantAchievement(74987243307163); } private void OnSocketMessage(InventoryRequestSocketMessage requestSocketMessage) { Logger.Debug("requestSocketMessage, Field0: {0}, Field1: {1}", requestSocketMessage.annGem, requestSocketMessage.annItemToReceiveGem); var gem = _inventoryGrid.GetItemByDynId(_owner, requestSocketMessage.annGem); var item = _inventoryGrid.GetItemByDynId(_owner, requestSocketMessage.annItemToReceiveGem); if (item == null) { item = _equipment.GetItemByDynId(_owner, requestSocketMessage.annItemToReceiveGem); if (item == null) return; } if (item.Attributes[GameAttributes.Sockets_Filled] >= item.Attributes[GameAttributes.Sockets]) return; gem.Owner = item; gem.SetInventoryLocation(20, 0, item.Attributes[GameAttributes.Sockets_Filled]); (item.Owner as Player).InGameClient.SendMessage(gem.ACDInventoryPositionMessage(item.Owner as Player)); item.Gems.Add(gem); switch (item.Gems.Count) { case 1: item.DBInventory.FirstGem = gem.GBHandle.GBID; _owner.World.Game.GameDbSession.SessionUpdate(item.DBInventory); break; case 2: item.DBInventory.SecondGem = gem.GBHandle.GBID; _owner.World.Game.GameDbSession.SessionUpdate(item.DBInventory); break; case 3: item.DBInventory.ThirdGem = gem.GBHandle.GBID; _owner.World.Game.GameDbSession.SessionUpdate(item.DBInventory); break; } if (gem.Attributes[GameAttributes.ItemStackQuantityLo] > 1) { var compensation = ItemGenerator.CookFromDefinition(_owner.World, ItemGenerator.GetItemDefinition(gem.GBHandle.GBID), 1); compensation.Attributes[GameAttributes.ItemStackQuantityLo] = gem.Attributes[GameAttributes.ItemStackQuantityLo] - 1; gem.Attributes[GameAttributes.ItemStackQuantityLo] = 1; _inventoryGrid.RemoveItem(gem); _inventoryGrid.AddItem(compensation); } else { _inventoryGrid.RemoveItem(gem); } //this.GrabSomeItems(gem.GBHandle.GBID, 1); _owner.SetAttributesByItems(); _owner.SetAttributesByItemProcs(); _owner.SetAttributesByGems(); item.Attributes[GameAttributes.Sockets_Filled] = item.Gems.Count; item.Attributes.BroadcastChangedIfRevealed(); _owner.GrantAchievement(74987243307166); if (gem.ItemDefinition.Name.Contains("Topaz")) _owner.GrantCriteria(74987243307541); if (gem.ItemDefinition.Name.Contains("Emerald")) _owner.GrantCriteria(74987243307549); if (gem.ItemDefinition.Name.Contains("Ruby")) _owner.GrantCriteria(74987243307550); if (gem.ItemDefinition.Name.Contains("Amethyst")) _owner.GrantCriteria(74987243307552); _owner.UpdatePercentageHP(_owner.PercHPbeforeChange); } //* private void OnGemsExtractMessage(InventoryGemsExtractMessage msg) { Logger.Debug("OnGemsExtractMessage"); var item = _inventoryGrid.GetItemByDynId(_owner, msg.ItemID); if (item == null) { item = _equipment.GetItemByDynId(_owner, msg.ItemID); if (item == null) return; } if (item.DBInventory.FirstGem != -1) { PickUp(ItemGenerator.CookFromDefinition(_owner.World, ItemGenerator.GetItemDefinition(item.DBInventory.FirstGem))); } if (item.DBInventory.SecondGem != -1) PickUp(ItemGenerator.CookFromDefinition(_owner.World, ItemGenerator.GetItemDefinition(item.DBInventory.SecondGem))); if (item.DBInventory.ThirdGem != -1) PickUp(ItemGenerator.CookFromDefinition(_owner.World, ItemGenerator.GetItemDefinition(item.DBInventory.ThirdGem))); item.DBInventory.FirstGem = -1; item.DBInventory.SecondGem = -1; item.DBInventory.ThirdGem = -1; _owner.World.Game.GameDbSession.SessionUpdate(item.DBInventory); foreach (var gem in item.Gems) gem.Unreveal(_owner); item.Gems.Clear(); item.Attributes[GameAttributes.Sockets_Filled] = 0; item.Attributes.BroadcastChangedIfRevealed(); _owner.GrantAchievement(74987243307789); } //*/ public void RepairAll() { RepairEquipment(); int cost = 0; foreach (var item in GetBackPackItems()) if (item.Attributes[GameAttributes.Durability_Cur] < item.Attributes[GameAttributes.Durability_Max]) { cost += (int)((item.GetPrice() * (item.Attributes[GameAttributes.Durability_Max] - item.Attributes[GameAttributes.Durability_Cur])) / (item.Attributes[GameAttributes.Durability_Max] * 25)); item.UpdateDurability(item.Attributes[GameAttributes.Durability_Max]); } RemoveGoldAmount(cost); } public void RepairEquipment() { int cost = 0; foreach (var item in GetEquippedItems()) if (item.Attributes[GameAttributes.Durability_Cur] < item.Attributes[GameAttributes.Durability_Max]) { cost += (int)((item.GetPrice() * (item.Attributes[GameAttributes.Durability_Max] - item.Attributes[GameAttributes.Durability_Cur])) / (item.Attributes[GameAttributes.Durability_Max] * 25)); item.UpdateDurability(item.Attributes[GameAttributes.Durability_Max]); } RemoveGoldAmount(cost); _owner.GrantAchievement(74987243307773); } public void PickUpGold(Item item) { int amount = item.Attributes[GameAttributes.Gold];//item.Attributes[GameAttribute.ItemStackQuantityLo]; AddGoldAmount(amount, false); } public void PickUpBloodShard(Item item) { int amount = item.Attributes[GameAttributes.ItemStackQuantityLo]; AddBloodShardsAmount(amount, false); } public void PickUpPlatinum(Item item) { int amount = item.Attributes[GameAttributes.ItemStackQuantityLo]; AddPlatinumAmount(amount); } private void OnInventoryRequestUseMessage(InventoryRequestUseMessage inventoryRequestUseMessage) { uint targetItemId = inventoryRequestUseMessage.UsedOnItem; uint usedItemId = inventoryRequestUseMessage.UsedItem; int actionId = inventoryRequestUseMessage.Type; Item usedItem = GetItemByDynId(_owner, usedItemId); Item targetItem = GetItemByDynId(_owner, targetItemId); if (usedItem != null) usedItem.OnRequestUse(_owner, targetItem, actionId, inventoryRequestUseMessage.Location); } public void DecreaseItemStack(Item item, int count = 1) { GrabSomeItems(item.GBHandle.GBID, count); } public void DestroyInventoryItem(Item item) { if (_equipment.IsItemEquipped(item)) { _equipment.UnequipItem(item); SendVisualInventory(_owner); } else { _inventoryGrid.RemoveItem(item); _stashGrid.RemoveItem(item); } item.Unreveal(_owner); item.Destroy(); //_destroyedItems.Add(item); } //private List _destroyedItems = new List(); public bool Reveal(Player player) { _equipment.Reveal(player); if (player == _owner) { //_inventoryGrid.Reveal(player); //_stashGrid.Reveal(player); } return true; } public bool Unreveal(Player player) { _equipment.Unreveal(player); if (player == _owner) { //_inventoryGrid.Unreveal(player); //_stashGrid.Unreveal(player); } return true; } public Item GetItem(uint itemId) { Item result; if (!_inventoryGrid.Items.TryGetValue(itemId, out result) && !_stashGrid.Items.TryGetValue(itemId, out result) && !_equipment.Items.TryGetValue(itemId, out result)) { return null; } return result; } public Item GetItemByDynId(Player plr, uint dynId) { if (_inventoryGrid.Items.Values.Union(_stashGrid.Items.Values).Union(_equipment.Items.Values).Any(it => it.IsRevealedToPlayer(plr) && it.DynamicID(plr) == dynId)) return _inventoryGrid.Items.Values.Union(_stashGrid.Items.Values).Union(_equipment.Items.Values).Single(it => it.IsRevealedToPlayer(plr) && it.DynamicID(plr) == dynId); return null; } public bool HasItem(int GBid) { return _inventoryGrid.HaveEnough(GBid, 1); } public bool HasGold(int amount) { return _inventoryGold.Attributes[GameAttributes.Gold] >= amount; } public Item GetEquippedWeapon() { return _equipment.GetWeapon(); } public Item GetEquippedOffHand() { return _equipment.GetOffHand(); } public void AddGoldAmount(int amount, bool immediately = true) { _inventoryGold.Attributes[GameAttributes.Gold] += amount; _inventoryGold.Attributes[GameAttributes.ItemStackQuantityLo] = _inventoryGold.Attributes[GameAttributes.Gold]; _inventoryGold.Attributes.SendChangedMessage(_owner.InGameClient); if (immediately) { _owner.Toon.GameAccount.Gold += (ulong)amount; } else _owner.GoldCollectedTempCount += amount; UpdateCurrencies(); } public void RemoveGoldAmount(int amount) { _inventoryGold.Attributes[GameAttributes.Gold] -= amount; _inventoryGold.Attributes[GameAttributes.ItemStackQuantityLo] = _inventoryGold.Attributes[GameAttributes.Gold]; _inventoryGold.Attributes.SendChangedMessage(_owner.InGameClient); _owner.Toon.GameAccount.Gold -= (ulong)amount; UpdateCurrencies(); } public int GetGoldAmount() { if (_inventoryGold != null) { //Logger.Warn($"InventoryGold is not null: $[yellow]${_inventoryGold.Attributes[GameAttribute.Gold]} / {_owner.Toon.GameAccount.Gold}$[/]$"); return _inventoryGold.Attributes[GameAttributes.Gold]; } else { //Logger.Warn($"InventoryGold is null"); return -1; } } public void AddBloodShardsAmount(int amount, bool immediately = true) { int C1 = 0; foreach (var item in FindSameItems(-363607620)) C1 += item.Attributes[GameAttributes.ItemStackQuantityLo]; int C2 = 0; foreach (var item in FindSameItems(-1585802162)) C2 += item.Attributes[GameAttributes.ItemStackQuantityLo]; int C3 = 0; foreach (var item in FindSameItems(-605947593)) C3 += item.Attributes[GameAttributes.ItemStackQuantityLo]; var Moneys = D3.Items.CurrencySavedData.CreateBuilder(); D3.Items.CurrencyData GoldData = D3.Items.CurrencyData.CreateBuilder().SetId(0).SetCount((long)GetGoldAmount()).Build(); //D3.Items.CurrencyData.CreateBuilder().SetId(1).SetCount(_owner.InGameClient.BnetClient.Account.GameAccount.BloodShards).Build(); var BloodShardsElement = D3.Items.CurrencyData.CreateBuilder().SetId(1); if (immediately) { BloodShardsElement.SetCount(_owner.Toon.GameAccount.BloodShards); } else { _owner.BloodShardsCollectedTempCount += amount; if (_owner.World.Game.IsHardcore) BloodShardsElement.SetCount(_owner.BloodShardsCollectedTempCount + _owner.Toon.GameAccount.BloodShards); } } public void UpdateCurrencies() { var moneys = D3.Items.CurrencySavedData.CreateBuilder(); var playerAcc = _owner.InGameClient.BnetClient.Account.GameAccount; D3.Items.CurrencyData goldData = D3.Items.CurrencyData.CreateBuilder().SetId(0).SetCount(GetGoldAmount()).Build(); D3.Items.CurrencyData bloodShardData = D3.Items.CurrencyData.CreateBuilder().SetId(1).SetCount(playerAcc.BloodShards).Build(); D3.Items.CurrencyData platinumData = D3.Items.CurrencyData.CreateBuilder().SetId(2).SetCount(playerAcc.Platinum).Build(); D3.Items.CurrencyData craft1Data = D3.Items.CurrencyData.CreateBuilder().SetId(3).SetCount(playerAcc.CraftItem1).Build(); // Reusable Parts. D3.Items.CurrencyData craft2Data = D3.Items.CurrencyData.CreateBuilder().SetId(4).SetCount(playerAcc.CraftItem2).Build(); // Arcanes Dust. D3.Items.CurrencyData craft3Data = D3.Items.CurrencyData.CreateBuilder().SetId(5).SetCount(playerAcc.CraftItem3).Build(); // Veiled Crystal. D3.Items.CurrencyData craft4Data = D3.Items.CurrencyData.CreateBuilder().SetId(6).SetCount(playerAcc.CraftItem4).Build(); // Death's Breath. D3.Items.CurrencyData craft5Data = D3.Items.CurrencyData.CreateBuilder().SetId(7).SetCount(playerAcc.CraftItem5).Build(); // Forgotten Soul. D3.Items.CurrencyData horadric1Data = D3.Items.CurrencyData.CreateBuilder().SetId(8).SetCount(playerAcc.HoradricA1Res).Build(); // Khanduran Rune Bounty itens Act I. D3.Items.CurrencyData horadric2Data = D3.Items.CurrencyData.CreateBuilder().SetId(9).SetCount(playerAcc.HoradricA2Res).Build(); // Caldeum Nightshade Bounty itens Act II. D3.Items.CurrencyData horadric3Data = D3.Items.CurrencyData.CreateBuilder().SetId(10).SetCount(playerAcc.HoradricA3Res).Build(); // Arreat War Tapestry Bounty itens Act III. D3.Items.CurrencyData horadric4Data = D3.Items.CurrencyData.CreateBuilder().SetId(11).SetCount(playerAcc.HoradricA4Res).Build(); // Copputed Angel Flesh Bounty itens Act IV. D3.Items.CurrencyData horadric5Data = D3.Items.CurrencyData.CreateBuilder().SetId(12).SetCount(playerAcc.HoradricA5Res).Build(); // Westmarch Holy Water Bounty itens Act V. D3.Items.CurrencyData craft8Data = D3.Items.CurrencyData.CreateBuilder().SetId(13).SetCount(playerAcc.HeartofFright).Build(); // Heart of Fright. D3.Items.CurrencyData craft9Data = D3.Items.CurrencyData.CreateBuilder().SetId(14).SetCount(playerAcc.VialofPutridness).Build(); // Idol of Terror. D3.Items.CurrencyData craft10Data = D3.Items.CurrencyData.CreateBuilder().SetId(15).SetCount(playerAcc.IdolofTerror).Build(); // Vail of Putridiness. D3.Items.CurrencyData craft11Data = D3.Items.CurrencyData.CreateBuilder().SetId(16).SetCount(playerAcc.LeorikKey).Build(); // Leorik Regret. D3.Items.CurrencyData craft7Data = D3.Items.CurrencyData.CreateBuilder().SetId(20).SetCount(playerAcc.BigPortalKey).Build(); // KeyStone Greater Rift. D3.Items.CurrencyData[] consumables = {goldData, bloodShardData, platinumData, craft1Data, craft2Data, craft3Data, craft4Data, craft5Data, craft7Data, horadric1Data, horadric2Data, horadric3Data, horadric4Data, horadric5Data, craft8Data, craft9Data, craft10Data, craft11Data}; foreach (var consumable in consumables) { moneys.AddCurrency(consumable); } _owner.InGameClient.SendMessage(new GenericBlobMessage(Opcodes.CurrencyDataFull) { Data = moneys.Build().ToByteArray() }); } public void AddPlatinumAmount(int amount) { _owner.Toon.GameAccount.Platinum += amount; UpdateCurrencies(); } public void RemoveBloodShardsAmount(int amount) { this.BloodShards -= amount; _owner.Toon.GameAccount.BloodShards -= amount; UpdateCurrencies(); } public int GetBloodShardsAmount() { return BloodShards; } public void LoadFromDB() { //load everything and make a switch on slot_id Item item = null; int goldAmount = (int)_owner.World.Game.GameDbSession.SessionGet(_owner.Toon.GameAccount.PersistentID).Gold; // Logger.Warn($"User {this._owner.Toon.PersistentID} has {goldAmount} gold."); this.BloodShards = (int)_owner.World.Game.GameDbSession.SessionGet(_owner.Toon.GameAccount.PersistentID).BloodShards; // Clear already present items // LoadFromDB is called every time World is changed, even entering a dungeon _inventoryGrid.Clear(); // first of all load stash size var slots = _owner.World.Game.GameDbSession.SessionGet(_owner.Toon.GameAccount.PersistentID).StashSize; if (slots > 0) { _owner.Attributes[GameAttributes.Shared_Stash_Slots] = slots; _owner.Attributes.BroadcastChangedIfRevealed(); // To be applied before loading items, to have all the space needed _stashGrid.ResizeGrid(_owner.Attributes[GameAttributes.Shared_Stash_Slots] / 7, 7); } // next read all items var allInventoryItems = _owner.World.Game.GameDbSession.SessionQueryWhere( dbi => dbi.DBToon != null && dbi.HirelingId == 0 && dbi.DBToon.Id == _owner.Toon.PersistentID).ToList(); //Task.Run(() => //{ foreach (var inv in allInventoryItems) { //Thread.Sleep(31); var slot = inv.EquipmentSlot; if (slot >= (int)EquipmentSlotId.Inventory && slot <= (int)EquipmentSlotId.Neck) { item = ItemGenerator.LoadFromDB(_owner, inv); //item.DBInventory = inv; if (slot == (int)EquipmentSlotId.Inventory) { _inventoryGrid.PlaceItem(item, inv.LocationY, inv.LocationX); } else { _equipment.EquipItem(item, (int)slot, false); } } } SendVisualInventory(_owner); _owner.SetAttributesByItems(); _owner.SetAttributesByItemProcs(); _owner.SetAttributesByGems(); _owner.SetAttributesByItemSets(); _owner.SetAttributesByPassives(); _owner.SetAttributesByParagon(); CheckWeapons(); _owner.Attributes.BroadcastChangedIfRevealed(); Task.Delay(3000).ContinueWith((t) => { try { _owner.CheckBonusSets(); } catch { } }); //}).ContinueWith((a) =>{ _inventoryGold = ItemGenerator.CreateGold(_owner, goldAmount); _inventoryGold.Attributes[GameAttributes.Gold] = goldAmount; // Logger.Warn($"User {this._owner.Toon.PersistentID} - inventory gold has {_inventoryGold.Attributes[GameAttribute.Gold]} gold."); _inventoryGold.Attributes[GameAttributes.ItemStackQuantityLo] = goldAmount; // This is the attribute that makes the gold visible in gamethe gold visible in game _inventoryGold.Owner = _owner; _inventoryGold.SetInventoryLocation((int)EquipmentSlotId.Gold, 0, 0); _inventoryGold.Attributes.SendChangedMessage(_owner.InGameClient); //this.inventoryPotion = ItemGenerator.CreateItem(this._owner, ItemGenerator.GetItemDefinition(DiIiS_NA.Core.Helpers.Hash.StringHashHelper.HashItemName("HealthPotionBottomless"))); //this.inventoryPotion.Owner = _owner; //this.inventoryPotion.SetInventoryLocation((int)EquipmentSlotId.Inventory, 0, 0); //*/ Loaded = true; UpdateCurrencies(); //}); _owner.UpdatePercentageHP(_owner.PercHPbeforeChange); } public void LoadStashFromDB() { Item item = null; _stashGrid.Clear(); // next load all stash items var stashInventoryItems = _owner.World.Game.GameDbSession.SessionQueryWhere( dbi => dbi.DBGameAccount.Id == _owner.Toon.GameAccount.PersistentID && dbi.HirelingId == 0 && dbi.DBToon == null && dbi.isHardcore == _owner.World.Game.IsHardcore).ToList(); //Task.Run(() => //{ foreach (var inv in stashInventoryItems) { //Thread.Sleep(15); var slot = inv.EquipmentSlot; if (slot == (int)EquipmentSlotId.Stash) { // load stash item = ItemGenerator.LoadFromDB(_owner, inv); item.DBInventory = inv; _stashGrid.PlaceItem(item, inv.LocationY, inv.LocationX); } } //}).Wait(); StashLoaded = true; } public void UnrevealStash() { _stashGrid.Unreveal(_owner); } public void RefreshInventoryToClient() { var itemsToUpdate = new List(); itemsToUpdate.AddRange(_inventoryGrid.Items.Values); if (StashRevealed) itemsToUpdate.AddRange(_stashGrid.Items.Values); itemsToUpdate.AddRange(_buybackGrid.Items.Values); itemsToUpdate.Add(_inventoryGold); //Task.Run(() => //{ foreach (var itm in itemsToUpdate) { if (itm.Owner is Player) { var player = (itm.Owner as Player); //Thread.Sleep(30); if (!itm.Reveal(player)) { player.InGameClient.SendMessage(itm.ACDInventoryPositionMessage(player)); } } } SendVisualInventory(_owner); _owner.SetAttributesByItems(); _owner.SetAttributesByItemProcs(); _owner.SetAttributesByGems(); _owner.SetAttributesByItemSets(); _owner.SetAttributesByPassives(); _owner.SetAttributesByParagon(); _owner.Attributes.BroadcastChangedIfRevealed(); //}); UpdateCurrencies(); _owner.UpdatePercentageHP(_owner.PercHPbeforeChange); } public void SaveItemToDB(DBGameAccount dbGameAccount, DBToon dbToon, EquipmentSlotId slotId, Item item) //public only for Grids { //Logger.Debug("SaveItemToDB"); if (item == null) return; //bool newItem = false; item.DBInventory = new DBInventory(); item.DBInventory.DBGameAccount = dbGameAccount; item.DBInventory.DBToon = dbToon; item.DBInventory.LocationX = item.InventoryLocation.X; item.DBInventory.LocationY = item.InventoryLocation.Y; item.DBInventory.EquipmentSlot = (int)slotId; item.DBInventory.isHardcore = item.Owner.World.Game.IsHardcore; item.DBInventory.FirstGem = -1; item.DBInventory.SecondGem = -1; item.DBInventory.ThirdGem = -1; item.DBInventory.Unidentified = item.Unidentified; item.DBInventory.TransmogGBID = -1; if (item.Gems.Count > 0) { item.DBInventory.FirstGem = item.Gems[0].GBHandle.GBID; if (item.Gems.Count > 1) { item.DBInventory.SecondGem = item.Gems[1].GBHandle.GBID; if (item.Gems.Count > 2) { item.DBInventory.ThirdGem = item.Gems[2].GBHandle.GBID; } } } ItemGenerator.SaveToDB(item); //Logger.Debug("SaveItemToDB, SessionSave"); _owner.World.Game.GameDbSession.SessionSave(item.DBInventory); //Logger.Debug("SaveItemToDB success, item dbid: {0}", item.DBInventory.Id); } public void RemoveItemFromDB(Item item) //public only for Grids { //Logger.Debug("RemoveItemFromDB"); if (item == null) return; if (item.DBInventory == null) return; //var inventory = item.Owner.World.Game.GameDBSession.SessionGet(item.DBInventory.Id); _owner.World.Game.GameDbSession.SessionDelete(item.DBInventory); //Logger.Debug("RemoveItemFromDB success, item dbid: {0}", item.DBInventory.Id); item.DBInventory = null; } public void ChangeItemSlotDB(int slotId, Item item) { //Logger.Debug("ChangeItemSlotDB"); if (item == null) return; if (item.DBInventory == null) return; item.DBInventory.EquipmentSlot = slotId; item.DBInventory.LocationX = 0; item.DBInventory.LocationY = 0; if (slotId == 15) item.DBInventory.DBToon = null; else item.DBInventory.DBToon = (_owner as Player).Toon.DbToon; item.Owner.World.Game.GameDbSession.SessionUpdate(item.DBInventory); //Logger.Debug("ChangeItemSlotDB success, item dbid: {0}", item.DBInventory.Id); } public void ChangeItemLocationDB(int locX, int locY, Item item) { //Logger.Trace("ChangeItemLocationDB"); if (item == null) return; if (item.DBInventory == null) return; item.DBInventory.LocationX = locX; item.DBInventory.LocationY = locY; item.Owner.World.Game.GameDbSession.SessionUpdate(item.DBInventory); //Logger.Debug("ChangeItemLocationDB success, item dbid: {0}", item.DBInventory.Id); } #region EqupimentStats public float GetItemBonus(GameAttributeF attributeF) { if (!Loaded) return _owner.Attributes[attributeF]; var stats = GetEquippedItems().Where(item => item.Attributes[GameAttributes.Durability_Cur] > 0 || item.Attributes[GameAttributes.Durability_Max] == 0); return stats.Sum(item => item.Attributes[attributeF]); } public int GetItemBonus(GameAttributeI attributeI) { return Loaded ? GetEquippedItems().Where(item => item.Attributes[GameAttributes.Durability_Cur] > 0 || item.Attributes[GameAttributes.Durability_Max] == 0).Sum(item => item.Attributes[attributeI]) : _owner.Attributes[attributeI]; } public bool GetItemBonus(GameAttributeB attributeB) { return Loaded ? GetEquippedItems().Any(item => item.Attributes[attributeB]) : _owner.Attributes[attributeB]; } public float GetItemBonus(GameAttributeF attributeF, int attributeKey) { return Loaded ? GetEquippedItems().Where(item => item.Attributes[GameAttributes.Durability_Cur] > 0 || item.Attributes[GameAttributes.Durability_Max] == 0).Sum(item => item.Attributes[attributeF, attributeKey]) : _owner.Attributes[attributeF]; } public int GetItemBonus(GameAttributeI attributeI, int attributeKey) { return Loaded ? GetEquippedItems().Where(item => item.Attributes[GameAttributes.Durability_Cur] > 0 || item.Attributes[GameAttributes.Durability_Max] == 0).Sum(item => item.Attributes[attributeI, attributeKey]) : _owner.Attributes[attributeI]; } public void SetGemBonuses() { uint countofGems = 0; foreach (var equip in GetEquippedItems()) { foreach (var gem in equip.Gems) { var effect = ItemGenerator.GetGemEffectDefinition(gem.GBHandle.GBID, equip.EquipGemType); if (effect == null) continue; foreach (var attr in effect.Attribute) { float result; if (attr.AttributeId > 0) if (FormulaScript.Evaluate(attr.Formula.ToArray(), new ItemRandomHelper(35674658), out result)) { //Logger.Info("attr: {0}, {1} {2}", attr.AttributeId, attr.SNOParam, result); var attrib = GameAttributes.Attributes[attr.AttributeId] as GameAttributeF; //if (attrib == GameAttribute.Dexterity_Item || attrib == GameAttribute.Vitality_Item || attrib == GameAttribute.Strength_Item || attrib == GameAttribute.Intelligence_Item) result /= 1065353216; //dat shit is crazy if (attr.SNOParam != -1) _owner.Attributes[attrib, attr.SNOParam] += result; else _owner.Attributes[attrib] += result; } } _owner.Attributes.BroadcastChangedIfRevealed(); //_owner.Attributes[effect.Attribute[0].] countofGems++; if (_owner.InGameClient.Game.IsSeasoned && countofGems >= 5) _owner.GrantCriteria(74987254401623); } } } public void SetItemSetBonuses() { foreach (var set in GetEquippedItems().Where(i => i.ItemDefinition.SNOSet != -1).GroupBy(i => i.ItemDefinition.SNOSet)) { for (int c = 1; c <= set.Count(); c++) { var effect = ItemGenerator.GetItemSetEffectDefinition(set.First().ItemDefinition.SNOSet, c); if (effect == null) continue; foreach (var attr in effect.Attribute) { float result; if (attr.AttributeId > 0) if (FormulaScript.Evaluate(attr.Formula.ToArray(), new ItemRandomHelper(35674658), out result)) { //Logger.Debug("attr: {0}, {1} {2}", attr.AttributeId, attr.SNOParam, result); var attrib = GameAttributes.Attributes[attr.AttributeId] as GameAttributeF; if (attrib == GameAttributes.Dexterity_Item || attrib == GameAttributes.Vitality_Item || attrib == GameAttributes.Strength_Item || attrib == GameAttributes.Intelligence_Item) result /= 1065353216; //dat shit is crazy if (attr.SNOParam != -1) _owner.Attributes[attrib, attr.SNOParam] += result; else _owner.Attributes[attrib] += result; } } } _owner.Attributes[GameAttributes.Set_Item_Count, set.First().ItemDefinition.SNOSet] = set.Count(); if (set.Count() >= 6) _owner.GrantAchievement(74987243307160); } _owner.Attributes.BroadcastChangedIfRevealed(); } public void DecreaseDurability(float percent) { foreach (var equip in GetEquippedItems()) { if (equip.Attributes[GameAttributes.Item_Indestructible] == false) { equip.UpdateDurability(Math.Max(0, (equip.Attributes[GameAttributes.Durability_Cur] - (int)((float)equip.Attributes[GameAttributes.Durability_Max] * percent)))); equip.Attributes.SendChangedMessage(_owner.InGameClient); } } } #endregion } }