Core/Spells: don't allow spells with SPELL_EFFECT_CREATE_LOOT to be cast if there isn't enough space in inventory

Port From (https://github.com/TrinityCore/TrinityCore/commit/59da957165ef7d7529db30f90a30dc401d682052)
This commit is contained in:
hondacrx
2021-12-17 19:26:43 -05:00
parent 112803c149
commit b349f922b2
3 changed files with 99 additions and 71 deletions
+57 -34
View File
@@ -17,6 +17,7 @@
using Framework.Constants; using Framework.Constants;
using Framework.Database; using Framework.Database;
using Game.BattleFields;
using Game.BattleGrounds; using Game.BattleGrounds;
using Game.DataStorage; using Game.DataStorage;
using Game.Groups; using Game.Groups;
@@ -30,7 +31,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Game.BattleFields;
namespace Game.Entities namespace Game.Entities
{ {
@@ -1796,25 +1796,25 @@ namespace Game.Entities
{ {
case InventoryResult.CantEquipLevelI: case InventoryResult.CantEquipLevelI:
case InventoryResult.PurchaseLevelTooLow: case InventoryResult.PurchaseLevelTooLow:
{ {
failure.Level = (item1 ? item1.GetRequiredLevel() : 0); failure.Level = (item1 ? item1.GetRequiredLevel() : 0);
break; break;
} }
case InventoryResult.EventAutoequipBindConfirm: // no idea about this one... case InventoryResult.EventAutoequipBindConfirm: // no idea about this one...
{ {
//failure.SrcContainer //failure.SrcContainer
//failure.SrcSlot //failure.SrcSlot
//failure.DstContainer //failure.DstContainer
break; break;
} }
case InventoryResult.ItemMaxLimitCategoryCountExceededIs: case InventoryResult.ItemMaxLimitCategoryCountExceededIs:
case InventoryResult.ItemMaxLimitCategorySocketedExceededIs: case InventoryResult.ItemMaxLimitCategorySocketedExceededIs:
case InventoryResult.ItemMaxLimitCategoryEquippedExceededIs: case InventoryResult.ItemMaxLimitCategoryEquippedExceededIs:
{ {
ItemTemplate proto = item1 ? item1.GetTemplate() : Global.ObjectMgr.GetItemTemplate(itemId); ItemTemplate proto = item1 ? item1.GetTemplate() : Global.ObjectMgr.GetItemTemplate(itemId);
failure.LimitCategory = (int)(proto != null ? proto.GetItemLimitCategory() : 0u); failure.LimitCategory = (int)(proto != null ? proto.GetItemLimitCategory() : 0u);
break; break;
} }
default: default:
break; break;
} }
@@ -3480,7 +3480,7 @@ namespace Game.Entities
if (itemTemplate != null) if (itemTemplate != null)
if (itemTemplate.GetFlags().HasAnyFlag(ItemFlags.HasLoot)) if (itemTemplate.GetFlags().HasAnyFlag(ItemFlags.HasLoot))
Global.LootItemStorage.RemoveStoredLootForContainer(pItem.GetGUID().GetCounter()); Global.LootItemStorage.RemoveStoredLootForContainer(pItem.GetGUID().GetCounter());
pItem.SetState(ItemUpdateState.Removed, this); pItem.SetState(ItemUpdateState.Removed, this);
} }
} }
@@ -3566,7 +3566,7 @@ namespace Game.Entities
ApplyItemEquipSpell(item, apply); ApplyItemEquipSpell(item, apply);
if (updateItemAuras) if (updateItemAuras)
{ {
ApplyItemDependentAuras(item, apply); ApplyItemDependentAuras(item, apply);
WeaponAttackType attackType = Player.GetAttackBySlot(slot, item.GetTemplate().GetInventoryType()); WeaponAttackType attackType = Player.GetAttackBySlot(slot, item.GetTemplate().GetInventoryType());
if (attackType != WeaponAttackType.Max) if (attackType != WeaponAttackType.Max)
@@ -3622,9 +3622,9 @@ namespace Game.Entities
UpdateStatBuffMod(Stats.Intellect); UpdateStatBuffMod(Stats.Intellect);
break; break;
//case ItemModType.Spirit: //modify spirit //case ItemModType.Spirit: //modify spirit
//HandleStatModifier(UnitMods.StatSpirit, UnitModifierType.BaseValue, (float)val, apply); //HandleStatModifier(UnitMods.StatSpirit, UnitModifierType.BaseValue, (float)val, apply);
//ApplyStatBuffMod(Stats.Spirit, MathFunctions.CalculatePct(val, GetModifierValue(UnitMods.StatSpirit, UnitModifierType.BasePCTExcludeCreate)), apply); //ApplyStatBuffMod(Stats.Spirit, MathFunctions.CalculatePct(val, GetModifierValue(UnitMods.StatSpirit, UnitModifierType.BasePCTExcludeCreate)), apply);
//break; //break;
case ItemModType.Stamina: //modify stamina case ItemModType.Stamina: //modify stamina
GtGenericMultByILvlRecord staminaMult = CliDB.StaminaMultByILvlGameTable.GetRow(itemLevel); GtGenericMultByILvlRecord staminaMult = CliDB.StaminaMultByILvlGameTable.GetRow(itemLevel);
if (staminaMult != null) if (staminaMult != null)
@@ -4514,7 +4514,30 @@ namespace Game.Entities
return freeSlotCount; return freeSlotCount;
} }
public uint GetFreeInventorySpace()
{
uint freeSpace = 0;
// Check backpack
for (byte slot = InventorySlots.ItemStart; slot < InventorySlots.ItemEnd; ++slot)
{
Item item = GetItemByPos(InventorySlots.Bag0, slot);
if (item == null)
freeSpace += 1;
}
// Check bags
for (byte i = InventorySlots.BagStart; i < InventorySlots.BagEnd; i++)
{
Bag bag = GetBagByPos(i);
if (bag != null)
freeSpace += bag.GetFreeSlots();
}
return freeSpace;
}
//Bags //Bags
public Bag GetBagByPos(byte bag) public Bag GetBagByPos(byte bag)
{ {
@@ -4681,15 +4704,15 @@ namespace Game.Entities
slots[0] = EquipmentSlot.Cloak; slots[0] = EquipmentSlot.Cloak;
break; break;
case InventoryType.Weapon: case InventoryType.Weapon:
{ {
slots[0] = EquipmentSlot.MainHand; slots[0] = EquipmentSlot.MainHand;
// suggest offhand slot only if know dual wielding // suggest offhand slot only if know dual wielding
// (this will be replace mainhand weapon at auto equip instead unwonted "you don't known dual wielding" ... // (this will be replace mainhand weapon at auto equip instead unwonted "you don't known dual wielding" ...
if (CanDualWield()) if (CanDualWield())
slots[1] = EquipmentSlot.OffHand; slots[1] = EquipmentSlot.OffHand;
break; break;
} }
case InventoryType.Shield: case InventoryType.Shield:
slots[0] = EquipmentSlot.OffHand; slots[0] = EquipmentSlot.OffHand;
break; break;
@@ -5462,7 +5485,7 @@ namespace Game.Entities
// equipment visual show // equipment visual show
SetVisibleItemSlot(slot, null); SetVisibleItemSlot(slot, null);
} }
m_items[slot] = null; m_items[slot] = null;
} }
else if ((pBag = GetBagByPos(bag)) != null) else if ((pBag = GetBagByPos(bag)) != null)
@@ -5802,7 +5825,7 @@ namespace Game.Entities
} }
} }
public byte GetInventorySlotCount() { return m_activePlayerData.NumBackpackSlots; } public byte GetInventorySlotCount() { return m_activePlayerData.NumBackpackSlots; }
public void SetInventorySlotCount(byte slots) public void SetInventorySlotCount(byte slots)
{ {
//ASSERT(slots <= (INVENTORY_SLOT_ITEM_END - INVENTORY_SLOT_ITEM_START)); //ASSERT(slots <= (INVENTORY_SLOT_ITEM_END - INVENTORY_SLOT_ITEM_START));
@@ -5951,7 +5974,7 @@ namespace Game.Entities
} }
public Dictionary<ObjectGuid, ObjectGuid> GetAELootView() { return m_AELootView; } public Dictionary<ObjectGuid, ObjectGuid> GetAELootView() { return m_AELootView; }
/// <summary> /// <summary>
/// if in a Battleground a player dies, and an enemy removes the insignia, the player's bones is lootable /// if in a Battleground a player dies, and an enemy removes the insignia, the player's bones is lootable
/// Called by remove insignia spell effect /// Called by remove insignia spell effect
@@ -6559,7 +6582,7 @@ namespace Game.Entities
{ {
if (oldSlot >= SharedConst.VoidStorageMaxSlot || newSlot >= SharedConst.VoidStorageMaxSlot || oldSlot == newSlot) if (oldSlot >= SharedConst.VoidStorageMaxSlot || newSlot >= SharedConst.VoidStorageMaxSlot || oldSlot == newSlot)
return false; return false;
_voidStorageItems.Swap(newSlot, oldSlot); _voidStorageItems.Swap(newSlot, oldSlot);
return true; return true;
} }
+33 -17
View File
@@ -6094,33 +6094,49 @@ namespace Game.Spells
case SpellEffectName.CreateLoot: case SpellEffectName.CreateLoot:
{ {
// m_targets.GetUnitTarget() means explicit cast, otherwise we dont check for possible equip error // m_targets.GetUnitTarget() means explicit cast, otherwise we dont check for possible equip error
Unit target = m_targets.GetUnitTarget() ? m_targets.GetUnitTarget() : player; Unit target = m_targets.GetUnitTarget() ?? player;
if (target.IsPlayer() && !IsTriggered() && spellEffectInfo.ItemType != 0) if (target.IsPlayer() && !IsTriggered())
{ {
List<ItemPosCount> dest = new();
InventoryResult msg = target.ToPlayer().CanStoreNewItem(ItemConst.NullBag, ItemConst.NullSlot, dest, spellEffectInfo.ItemType, 1); // SPELL_EFFECT_CREATE_ITEM_2 differs from SPELL_EFFECT_CREATE_ITEM in that it picks the random item to create from a pool of potential items,
if (msg != InventoryResult.Ok) // so we need to make sure there is at least one free space in the player's inventory
if (spellEffectInfo.Effect == SpellEffectName.CreateLoot)
{ {
ItemTemplate itemTemplate = Global.ObjectMgr.GetItemTemplate(spellEffectInfo.ItemType); if (target.ToPlayer().GetFreeInventorySpace() == 0)
// @todo Needs review
if (itemTemplate != null && itemTemplate.GetItemLimitCategory() == 0)
{ {
player.SendEquipError(msg, null, null, spellEffectInfo.ItemType); player.SendEquipError(InventoryResult.InvFull, null, null, spellEffectInfo.ItemType);
return SpellCastResult.DontReport; return SpellCastResult.DontReport;
} }
else }
if (spellEffectInfo.ItemType != 0)
{
List<ItemPosCount> dest = new();
InventoryResult msg = target.ToPlayer().CanStoreNewItem(ItemConst.NullBag, ItemConst.NullSlot, dest, spellEffectInfo.ItemType, 1);
if (msg != InventoryResult.Ok)
{ {
// Conjure Food/Water/Refreshment spells ItemTemplate itemTemplate = Global.ObjectMgr.GetItemTemplate(spellEffectInfo.ItemType);
if (!(m_spellInfo.SpellFamilyName == SpellFamilyNames.Mage && m_spellInfo.SpellFamilyFlags[0].HasAnyFlag(0x40000000u))) /// @todo Needs review
return SpellCastResult.TooManyOfItem; if (itemTemplate != null && itemTemplate.GetItemLimitCategory() == 0)
else if (!target.ToPlayer().HasItemCount(spellEffectInfo.ItemType))
{ {
player.SendEquipError(msg, null, null, spellEffectInfo.ItemType); player.SendEquipError(msg, null, null, spellEffectInfo.ItemType);
return SpellCastResult.DontReport; return SpellCastResult.DontReport;
} }
else if (m_spellInfo.GetEffects().Count > 1) else
player.CastSpell(m_caster, (uint)m_spellInfo.GetEffect(1).CalcValue(), new CastSpellExtraArgs().SetOriginalCastId(m_castId)); // move this to anywhere {
return SpellCastResult.DontReport; // Conjure Food/Water/Refreshment spells
if (m_spellInfo.SpellFamilyName != SpellFamilyNames.Mage || (!m_spellInfo.SpellFamilyFlags[0].HasAnyFlag(0x40000000u)))
return SpellCastResult.TooManyOfItem;
else if (!(target.ToPlayer().HasItemCount(spellEffectInfo.ItemType)))
{
player.SendEquipError(msg, null, null, spellEffectInfo.ItemType);
return SpellCastResult.DontReport;
}
else if (m_spellInfo.GetEffects().Count > 1)
player.CastSpell(player, (uint)m_spellInfo.GetEffect(1).CalcValue(), new CastSpellExtraArgs()
.SetOriginalCastId(m_castId)); // move this to anywhere
return SpellCastResult.DontReport;
}
} }
} }
} }
+9 -20
View File
@@ -1098,32 +1098,21 @@ namespace Game.Spells
Player player = unitTarget.ToPlayer(); Player player = unitTarget.ToPlayer();
uint item_id = effectInfo.ItemType;
ItemContext context = m_spellInfo.HasAttribute(SpellAttr0.Tradespell) ? ItemContext.TradeSkill : ItemContext.None; ItemContext context = m_spellInfo.HasAttribute(SpellAttr0.Tradespell) ? ItemContext.TradeSkill : ItemContext.None;
if (item_id != 0) // Pick a random item from spell_loot_template
DoCreateItem(item_id, context);
// special case: fake item replaced by generate using spell_loot_template
if (m_spellInfo.IsLootCrafting()) if (m_spellInfo.IsLootCrafting())
{ {
if (item_id != 0) player.AutoStoreLoot(m_spellInfo.Id, LootStorage.Spell, context, false, true);
{
if (!player.HasItemCount(item_id))
return;
// remove reagent
uint count = 1;
player.DestroyItemCount(item_id, count, true);
// create some random items
player.AutoStoreLoot(m_spellInfo.Id, LootStorage.Spell, context);
}
else
player.AutoStoreLoot(m_spellInfo.Id, LootStorage.Spell, context); // create some random items
player.UpdateCraftSkill(m_spellInfo.Id); player.UpdateCraftSkill(m_spellInfo.Id);
} }
else // If there's no random loot entries for this spell, pick the item associated with this spell
{
uint itemId = effectInfo.ItemType;
if (itemId != 0)
DoCreateItem(itemId, context);
}
// @todo ExecuteLogEffectCreateItem(i, GetEffect(i].ItemType); // @todo ExecuteLogEffectCreateItem(i, GetEffect(i].ItemType);
} }