Core/Items: Reagent bank

Port From (https://github.com/TrinityCore/TrinityCore/commit/a3b2e4d9873874e29291f0c9851ae154029b1b3b)
This commit is contained in:
hondacrx
2022-02-26 23:32:00 -05:00
parent dfe2303d6f
commit 2c03f9d1be
5 changed files with 294 additions and 103 deletions
@@ -232,6 +232,8 @@ namespace Game.Chat.Commands
itemPos = "[equipped]";
else if (Player.IsInventoryPos((byte)itemBag, itemSlot))
itemPos = "[in inventory]";
else if (Player.IsReagentBankPos((byte)itemBag, itemSlot))
itemPos = "[in reagent bank]";
else if (Player.IsBankPos((byte)itemBag, itemSlot))
itemPos = "[in bank]";
else
+91 -103
View File
@@ -583,22 +583,6 @@ namespace Game.Entities
return InventoryResult.ItemMaxCount;
}
res = CanStoreItem_InInventorySlots(InventorySlots.ReagentStart, InventorySlots.ReagentEnd, dest, pProto, ref count, true, pItem, bag, slot);
if (res != InventoryResult.Ok)
{
no_space_count = count + no_similar_count;
return res;
}
if (count == 0)
{
if (no_similar_count == 0)
return InventoryResult.Ok;
no_space_count = count + no_similar_count;
return InventoryResult.ItemMaxCount;
}
res = CanStoreItem_InInventorySlots(InventorySlots.ItemStart, inventoryEnd, dest, pProto, ref count, true, pItem, bag, slot);
if (res != InventoryResult.Ok)
{
@@ -661,24 +645,6 @@ namespace Game.Entities
return InventoryResult.ItemMaxCount;
}
}
else if (pProto.IsCraftingReagent() && HasPlayerFlagEx(PlayerFlagsEx.ReagentBankUnlocked))
{
res = CanStoreItem_InInventorySlots(InventorySlots.ReagentStart, InventorySlots.ReagentEnd, dest, pProto, ref count, false, pItem, bag, slot);
if (res != InventoryResult.Ok)
{
no_space_count = count + no_similar_count;
return res;
}
if (count == 0)
{
if (no_similar_count == 0)
return InventoryResult.Ok;
no_space_count = count + no_similar_count;
return InventoryResult.ItemMaxCount;
}
}
res = CanStoreItem_InInventorySlots(InventorySlots.ItemStart, inventoryEnd, dest, pProto, ref count, false, pItem, bag, slot);
if (res != InventoryResult.Ok)
@@ -740,22 +706,6 @@ namespace Game.Entities
return InventoryResult.ItemMaxCount;
}
res = CanStoreItem_InInventorySlots(InventorySlots.ReagentStart, InventorySlots.ReagentEnd, dest, pProto, ref count, true, pItem, bag, slot);
if (res != InventoryResult.Ok)
{
no_space_count = count + no_similar_count;
return res;
}
if (count == 0)
{
if (no_similar_count == 0)
return InventoryResult.Ok;
no_space_count = count + no_similar_count;
return InventoryResult.ItemMaxCount;
}
res = CanStoreItem_InInventorySlots(InventorySlots.ItemStart, inventoryEnd, dest, pProto, ref count, true, pItem, bag, slot);
if (res != InventoryResult.Ok)
{
@@ -849,24 +799,6 @@ namespace Game.Entities
return InventoryResult.ItemMaxCount;
}
}
else if (pProto.IsCraftingReagent() && HasPlayerFlagEx(PlayerFlagsEx.ReagentBankUnlocked))
{
res = CanStoreItem_InInventorySlots(InventorySlots.ReagentStart, InventorySlots.ReagentEnd, dest, pProto, ref count, false, pItem, bag, slot);
if (res != InventoryResult.Ok)
{
no_space_count = count + no_similar_count;
return res;
}
if (count == 0)
{
if (no_similar_count == 0)
return InventoryResult.Ok;
no_space_count = count + no_similar_count;
return InventoryResult.ItemMaxCount;
}
}
// search free slot
byte searchSlotStart = InventorySlots.ItemStart;
@@ -2177,6 +2109,12 @@ namespace Game.Entities
}
}
if (IsReagentBankPos(dst) && !IsReagentBankUnlocked())
{
SendEquipError(InventoryResult.ReagentBankLocked, pSrcItem, pDstItem);
return;
}
// NOW this is or item move (swap with empty), or swap with another item (including bags in bag possitions)
// or swap empty bag with another empty or not empty bag (with items exchange)
@@ -2210,7 +2148,8 @@ namespace Game.Entities
RemoveItem(srcbag, srcslot, true);
BankItem(dest, pSrcItem, true);
ItemRemovedQuestCheck(pSrcItem.GetEntry(), pSrcItem.GetCount());
if (!IsReagentBankPos(dst))
ItemRemovedQuestCheck(pSrcItem.GetEntry(), pSrcItem.GetCount());
}
else if (IsEquipmentPos(dst))
{
@@ -2660,6 +2599,21 @@ namespace Game.Entities
return sum / count;
}
public List<Item> GetCraftingReagentItemsToDeposit()
{
List<Item> itemList = new();
ForEachItem(ItemSearchLocation.Inventory, item =>
{
if (item.GetTemplate().IsCraftingReagent())
itemList.Add(item);
return true;
});
return itemList;
}
public Item GetItemByGuid(ObjectGuid guid)
{
Item result = null;
@@ -2817,6 +2771,10 @@ namespace Game.Entities
if (slot >= InventorySlots.BankBagStart && slot < InventorySlots.BankBagEnd)
return true;
// reagent bank bag slots
if (slot >= InventorySlots.ReagentStart && slot < InventorySlots.ReagentEnd)
return true;
return false;
}
@@ -3577,13 +3535,6 @@ namespace Game.Entities
}
}
for (byte i = InventorySlots.ReagentStart; i < InventorySlots.ReagentEnd; ++i)
{
Item item = GetUseableItemByPos(InventorySlots.Bag0, i);
if (item && Global.DB2Mgr.IsTotemCategoryCompatibleWith(item.GetTemplate().GetTotemCategory(), TotemCategory))
return true;
}
for (byte i = InventorySlots.ChildEquipmentStart; i < InventorySlots.ChildEquipmentEnd; ++i)
{
Item item = GetUseableItemByPos(InventorySlots.Bag0, i);
@@ -4227,6 +4178,10 @@ namespace Game.Entities
// prevent cheating
if ((slot >= InventorySlots.BuyBackStart && slot < InventorySlots.BuyBackEnd) || slot >= (byte)PlayerSlots.End)
return InventoryResult.WrongBagType;
// can't store anything else than crafting reagents in Reagent Bank
if (IsReagentBankPos(bag, slot) && (!IsReagentBankUnlocked() || !pProto.IsCraftingReagent()))
return InventoryResult.WrongBagType;
}
else
{
@@ -4329,13 +4284,27 @@ namespace Game.Entities
return true;
if (bag >= InventorySlots.BankBagStart && bag < InventorySlots.BankBagEnd)
return true;
if (bag == InventorySlots.Bag0 && (slot >= InventorySlots.ReagentStart && slot < InventorySlots.ReagentEnd))
return true;
return false;
}
public InventoryResult CanBankItem(byte bag, byte slot, List<ItemPosCount> dest, Item pItem, bool swap, bool not_loading = true)
public InventoryResult CanBankItem(byte bag, byte slot, List<ItemPosCount> dest, Item pItem, bool swap, bool not_loading = true, bool reagentBankOnly = false)
{
if (pItem == null)
return swap ? InventoryResult.CantSwap : InventoryResult.ItemNotFound;
// different slots range if we're trying to store item in Reagent Bank
if (reagentBankOnly)
{
Cypher.Assert(bag == ItemConst.NullBag && slot == ItemConst.NullSlot); // when reagentBankOnly is true then bag & slot must be hardcoded constants, not client input
}
if ((IsReagentBankPos(bag, slot) || reagentBankOnly) && !IsReagentBankUnlocked())
return InventoryResult.ReagentBankLocked;
byte slotStart = reagentBankOnly ? InventorySlots.ReagentStart : InventorySlots.BankItemStart;
byte slotEnd = reagentBankOnly ? InventorySlots.ReagentEnd : InventorySlots.BankItemEnd;
uint count = pItem.GetCount();
Log.outDebug(LogFilter.Player, "STORAGE: CanBankItem bag = {0}, slot = {1}, item = {2}, count = {3}", bag, slot, pItem.GetEntry(), count);
@@ -4400,7 +4369,7 @@ namespace Game.Entities
{
if (bag == InventorySlots.Bag0)
{
res = CanStoreItem_InInventorySlots(InventorySlots.BankItemStart, InventorySlots.BankItemEnd, dest, pProto, ref count, true, pItem, bag, slot);
res = CanStoreItem_InInventorySlots(slotStart, slotEnd, dest, pProto, ref count, true, pItem, bag, slot);
if (res != InventoryResult.Ok)
return res;
@@ -4424,7 +4393,7 @@ namespace Game.Entities
// search free slot in bag
if (bag == InventorySlots.Bag0)
{
res = CanStoreItem_InInventorySlots(InventorySlots.BankItemStart, InventorySlots.BankItemEnd, dest, pProto, ref count, false, pItem, bag, slot);
res = CanStoreItem_InInventorySlots(slotStart, slotEnd, dest, pProto, ref count, false, pItem, bag, slot);
if (res != InventoryResult.Ok)
return res;
@@ -4451,19 +4420,34 @@ namespace Game.Entities
if (pProto.GetMaxStackSize() != 1)
{
// in slots
res = CanStoreItem_InInventorySlots(InventorySlots.BankItemStart, InventorySlots.BankItemEnd, dest, pProto, ref count, true, pItem, bag, slot);
res = CanStoreItem_InInventorySlots(slotStart, slotEnd, dest, pProto, ref count, true, pItem, bag, slot);
if (res != InventoryResult.Ok)
return res;
if (count == 0)
return InventoryResult.Ok;
// in special bags
if (pProto.GetBagFamily() != BagFamilyMask.None)
// don't try to store reagents anywhere else than in Reagent Bank if we're on it
if (!reagentBankOnly)
{
// in special bags
if (pProto.GetBagFamily() != BagFamilyMask.None)
{
for (byte i = InventorySlots.BankBagStart; i < InventorySlots.BankBagEnd; i++)
{
res = CanStoreItem_InBag(i, dest, pProto, ref count, true, false, pItem, bag, slot);
if (res != InventoryResult.Ok)
continue;
if (count == 0)
return InventoryResult.Ok;
}
}
// in regular bags
for (byte i = InventorySlots.BankBagStart; i < InventorySlots.BankBagEnd; i++)
{
res = CanStoreItem_InBag(i, dest, pProto, ref count, true, false, pItem, bag, slot);
res = CanStoreItem_InBag(i, dest, pProto, ref count, true, true, pItem, bag, slot);
if (res != InventoryResult.Ok)
continue;
@@ -4471,22 +4455,12 @@ namespace Game.Entities
return InventoryResult.Ok;
}
}
for (byte i = InventorySlots.BankBagStart; i < InventorySlots.BankBagEnd; i++)
{
res = CanStoreItem_InBag(i, dest, pProto, ref count, true, true, pItem, bag, slot);
if (res != InventoryResult.Ok)
continue;
if (count == 0)
return InventoryResult.Ok;
}
}
// search free place in special bag
if (pProto.GetBagFamily() != BagFamilyMask.None)
if (!reagentBankOnly && pProto.GetBagFamily() != BagFamilyMask.None)
{
for (byte i = InventorySlots.BagStart; i < InventorySlots.BankBagEnd; i++)
for (byte i = InventorySlots.BankBagStart; i < InventorySlots.BankBagEnd; i++)
{
res = CanStoreItem_InBag(i, dest, pProto, ref count, false, false, pItem, bag, slot);
if (res != InventoryResult.Ok)
@@ -4498,24 +4472,29 @@ namespace Game.Entities
}
// search free space
res = CanStoreItem_InInventorySlots(InventorySlots.BankItemStart, InventorySlots.BankItemEnd, dest, pProto, ref count, false, pItem, bag, slot);
res = CanStoreItem_InInventorySlots(slotStart, slotEnd, dest, pProto, ref count, false, pItem, bag, slot);
if (res != InventoryResult.Ok)
return res;
if (count == 0)
return InventoryResult.Ok;
for (byte i = InventorySlots.BankBagStart; i < InventorySlots.BankBagEnd; i++)
// search free space in regular bags (don't try to store reagents anywhere else than in Reagent Bank if we're on it)
if (!reagentBankOnly)
{
res = CanStoreItem_InBag(i, dest, pProto, ref count, false, true, pItem, bag, slot);
if (res != InventoryResult.Ok)
continue;
for (byte i = InventorySlots.BankBagStart; i < InventorySlots.BankBagEnd; i++)
{
res = CanStoreItem_InBag(i, dest, pProto, ref count, false, true, pItem, bag, slot);
if (res != InventoryResult.Ok)
continue;
if (count == 0)
return InventoryResult.Ok;
if (count == 0)
return InventoryResult.Ok;
}
}
return InventoryResult.BankFull;
return reagentBankOnly ? InventoryResult.ReagentBankFull : InventoryResult.BankFull;
}
public Item BankItem(List<ItemPosCount> dest, Item pItem, bool update)
{
return StoreItem(dest, pItem, update);
@@ -4597,6 +4576,15 @@ namespace Game.Entities
return freeSpace;
}
//Reagent
public static bool IsReagentBankPos(ushort pos) { return IsReagentBankPos((byte)(pos >> 8), (byte)(pos & 255)); }
public static bool IsReagentBankPos(byte bag, byte slot)
{
if (bag == InventorySlots.Bag0 && (slot >= InventorySlots.ReagentStart && slot < InventorySlots.ReagentEnd))
return true;
return false;
}
//Bags
public Bag GetBagByPos(byte bag)
{
+3
View File
@@ -7174,6 +7174,9 @@ namespace Game.Entities
public void SetSemaphoreTeleportNear(bool semphsetting) { mSemaphoreTeleport_Near = semphsetting; }
public void SetSemaphoreTeleportFar(bool semphsetting) { mSemaphoreTeleport_Far = semphsetting; }
public bool IsReagentBankUnlocked() { return HasPlayerFlagEx(PlayerFlagsEx.ReagentBankUnlocked); }
public void UnlockReagentBank() { AddPlayerFlagEx(PlayerFlagsEx.ReagentBankUnlocked); }
//new
public uint DoRandomRoll(uint minimum, uint maximum)
{
+152
View File
@@ -143,6 +143,158 @@ namespace Game
GetPlayer().UpdateCriteria(CriteriaType.BankSlotsPurchased);
}
[WorldPacketHandler(ClientOpcodes.BuyReagentBank)]
void HandleBuyReagentBank(ReagentBank reagentBank)
{
if (!CanUseBank(reagentBank.Banker))
{
Log.outDebug(LogFilter.Network, $"WORLD: HandleBuyReagentBankOpcode - {reagentBank.Banker} not found or you can't interact with him.");
return;
}
if (_player.IsReagentBankUnlocked())
{
Log.outDebug(LogFilter.Network, $"WORLD: HandleBuyReagentBankOpcode - Player ({_player.GetGUID()}, name: {_player.GetName()}) tried to unlock reagent bank a 2nd time.");
return;
}
long price = 100 * MoneyConstants.Gold;
if (!_player.HasEnoughMoney(price))
{
Log.outDebug(LogFilter.Network, $"WORLD: HandleBuyReagentBankOpcode - Player ({_player.GetGUID()}, name: {_player.GetName()}) without enough gold.");
return;
}
_player.ModifyMoney(-price);
_player.UnlockReagentBank();
}
[WorldPacketHandler(ClientOpcodes.DepositReagentBank)]
void HandleReagentBankDeposit(ReagentBank reagentBank)
{
if (!CanUseBank(reagentBank.Banker))
{
Log.outDebug(LogFilter.Network, $"WORLD: HandleReagentBankDepositOpcode - {reagentBank.Banker} not found or you can't interact with him.");
return;
}
if (!_player.IsReagentBankUnlocked())
{
_player.SendEquipError(InventoryResult.ReagentBankLocked);
return;
}
// query all reagents from player's inventory
bool anyDeposited = false;
foreach (Item item in _player.GetCraftingReagentItemsToDeposit())
{
List<ItemPosCount> dest = new();
InventoryResult msg = _player.CanBankItem(ItemConst.NullBag, ItemConst.NullSlot, dest, item, false, true, true);
if (msg != InventoryResult.Ok)
{
if (msg != InventoryResult.ReagentBankFull || !anyDeposited)
_player.SendEquipError(msg, item);
break;
}
if (dest.Count == 1 && dest[0].pos == item.GetPos())
{
_player.SendEquipError(InventoryResult.CantSwap, item);
continue;
}
// store reagent
_player.RemoveItem(item.GetBagSlot(), item.GetSlot(), true);
_player.BankItem(dest, item, true);
anyDeposited = true;
}
}
[WorldPacketHandler(ClientOpcodes.AutobankReagent)]
void HandleAutoBankReagent(AutoBankReagent autoBankReagent)
{
if (!CanUseBank())
{
Log.outDebug(LogFilter.Network, $"WORLD: HandleAutoBankReagentOpcode - {m_currentBankerGUID} not found or you can't interact with him.");
return;
}
if (!_player.IsReagentBankUnlocked())
{
_player.SendEquipError(InventoryResult.ReagentBankLocked);
return;
}
Item item = _player.GetItemByPos(autoBankReagent.PackSlot, autoBankReagent.Slot);
if (!item)
return;
List<ItemPosCount> dest = new();
InventoryResult msg = _player.CanBankItem(ItemConst.NullBag, ItemConst.NullSlot, dest, item, false, true, true);
if (msg != InventoryResult.Ok)
{
_player.SendEquipError(msg, item);
return;
}
if (dest.Count == 1 && dest[0].pos == item.GetPos())
{
_player.SendEquipError(InventoryResult.CantSwap, item);
return;
}
_player.RemoveItem(autoBankReagent.PackSlot, autoBankReagent.Slot, true);
_player.BankItem(dest, item, true);
}
[WorldPacketHandler(ClientOpcodes.AutostoreBankReagent)]
void HandleAutoStoreBankReagent(AutoStoreBankReagent autoStoreBankReagent)
{
if (!CanUseBank())
{
Log.outDebug(LogFilter.Network, $"WORLD: HandleAutoBankReagentOpcode - {m_currentBankerGUID} not found or you can't interact with him.");
return;
}
if (!_player.IsReagentBankUnlocked())
{
_player.SendEquipError(InventoryResult.ReagentBankLocked);
return;
}
Item pItem = _player.GetItemByPos(autoStoreBankReagent.Slot, autoStoreBankReagent.PackSlot);
if (!pItem)
return;
if (Player.IsReagentBankPos(autoStoreBankReagent.Slot, autoStoreBankReagent.PackSlot))
{
List<ItemPosCount> dest = new();
InventoryResult msg = _player.CanStoreItem(ItemConst.NullBag, ItemConst.NullSlot, dest, pItem, false);
if (msg != InventoryResult.Ok)
{
_player.SendEquipError(msg, pItem);
return;
}
_player.RemoveItem(autoStoreBankReagent.Slot, autoStoreBankReagent.PackSlot, true);
_player.StoreItem(dest, pItem, true);
}
else
{
List<ItemPosCount> dest = new();
InventoryResult msg = _player.CanBankItem(ItemConst.NullBag, ItemConst.NullSlot, dest, pItem, false, true, true);
if (msg != InventoryResult.Ok)
{
_player.SendEquipError(msg, pItem);
return;
}
_player.RemoveItem(autoStoreBankReagent.Slot, autoStoreBankReagent.PackSlot, true);
_player.BankItem(dest, pItem, true);
}
}
public void SendShowBank(ObjectGuid guid)
{
m_currentBankerGUID = guid;
@@ -62,4 +62,50 @@ namespace Game.Networking.Packets
public ObjectGuid Guid;
}
class AutoBankReagent : ClientPacket
{
public AutoBankReagent(WorldPacket packet) : base(packet) { }
public override void Read()
{
Inv = new(_worldPacket);
PackSlot = _worldPacket.ReadUInt8();
Slot = _worldPacket.ReadUInt8();
}
public InvUpdate Inv;
public byte Slot;
public byte PackSlot;
}
class AutoStoreBankReagent : ClientPacket
{
public AutoStoreBankReagent(WorldPacket packet) : base(packet) { }
public override void Read()
{
Inv = new(_worldPacket);
Slot = _worldPacket.ReadUInt8();
PackSlot = _worldPacket.ReadUInt8();
}
public InvUpdate Inv;
public byte Slot;
public byte PackSlot;
}
// CMSG_BUY_REAGENT_BANK
// CMSG_REAGENT_BANK_DEPOSIT
class ReagentBank : ClientPacket
{
public ReagentBank(WorldPacket packet) : base(packet) { }
public override void Read()
{
Banker = _worldPacket.ReadPackedGuid();
}
public ObjectGuid Banker;
}
}