aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWyrserth <43747507+Wyrserth@users.noreply.github.com>2019-06-15 15:11:49 +0200
committerGiacomo Pozzoni <giacomopoz@gmail.com>2019-06-15 15:11:49 +0200
commit218055280af4563f28643e2683eafe40808f90db (patch)
tree243d799c21e273775b07975d450e8ebc58861b3e
parent865ab86173b529bd96cbd1b7fb929def9fc895ce (diff)
Core/Spells: don't allow spells with SPELL_EFFECT_CREATE_ITEM_2 to be cast if there isn't enough space in inventory (#23404)
* Core/Spells: don't allow spells with SPELL_EFFECT_CREATE_ITEM_2 to be cast if there isn't enough space in inventory, * Move GetFreeInventorySpace() to a better place, thanks ccrs!
-rw-r--r--src/server/game/Entities/Player/Player.cpp22
-rw-r--r--src/server/game/Entities/Player/Player.h1
-rw-r--r--src/server/game/Spells/Spell.cpp44
-rw-r--r--src/server/game/Spells/SpellEffects.cpp31
4 files changed, 61 insertions, 37 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index c4348d15766..fd225e90094 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -9896,6 +9896,28 @@ Bag* Player::GetBagByPos(uint8 bag) const
return nullptr;
}
+uint32 Player::GetFreeInventorySpace() const
+{
+ uint32 freeSpace = 0;
+
+ // Check backpack
+ for (uint8 slot = INVENTORY_SLOT_ITEM_START; slot < INVENTORY_SLOT_ITEM_END; ++slot)
+ {
+ Item* item = GetItemByPos(INVENTORY_SLOT_BAG_0, slot);
+ if (!item)
+ freeSpace += 1;
+ }
+
+ // Check bags
+ for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++)
+ {
+ if (Bag* bag = GetBagByPos(i))
+ freeSpace += bag->GetFreeSlots();
+ }
+
+ return freeSpace;
+}
+
Item* Player::GetWeaponForAttack(WeaponAttackType attackType, bool useable /*= false*/) const
{
uint8 slot;
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 3414a55d0b1..626b75709d6 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -1033,6 +1033,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
Item* GetItemByPos(uint8 bag, uint8 slot) const;
Item* GetUseableItemByPos(uint8 bag, uint8 slot) const;
Bag* GetBagByPos(uint8 slot) const;
+ uint32 GetFreeInventorySpace() const;
Item* GetWeaponForAttack(WeaponAttackType attackType, bool useable = false) const;
Item* GetShield(bool useable = false) const;
static WeaponAttackType GetAttackBySlot(uint8 slot); // MAX_ATTACK if not weapon slot
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 6851f890ff0..e6df1995c09 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -6619,32 +6619,44 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 /
{
// m_targets.GetUnitTarget() means explicit cast, otherwise we dont check for possible equip error
Unit* target = m_targets.GetUnitTarget() ? m_targets.GetUnitTarget() : player;
- if (target->GetTypeId() == TYPEID_PLAYER && !IsTriggered() && m_spellInfo->Effects[i].ItemType)
+ if (target->GetTypeId() == TYPEID_PLAYER && !IsTriggered())
{
- ItemPosCountVec dest;
- InventoryResult msg = target->ToPlayer()->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, m_spellInfo->Effects[i].ItemType, 1);
- if (msg != EQUIP_ERR_OK)
- {
- ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(m_spellInfo->Effects[i].ItemType);
- /// @todo Needs review
- if (itemTemplate && !itemTemplate->ItemLimitCategory)
+ // 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,
+ // so we need to make sure there is at least one free space in the player's inventory
+ if (m_spellInfo->Effects[i].Effect == SPELL_EFFECT_CREATE_ITEM_2)
+ if (target->ToPlayer()->GetFreeInventorySpace() == 0)
{
- player->SendEquipError(msg, nullptr, nullptr, m_spellInfo->Effects[i].ItemType);
+ player->SendEquipError(EQUIP_ERR_INVENTORY_FULL, nullptr, nullptr, m_spellInfo->Effects[i].ItemType);
return SPELL_FAILED_DONT_REPORT;
}
- else
+
+ if (m_spellInfo->Effects[i].ItemType)
+ {
+ ItemPosCountVec dest;
+ InventoryResult msg = target->ToPlayer()->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, m_spellInfo->Effects[i].ItemType, 1);
+ if (msg != EQUIP_ERR_OK)
{
- // Conjure Food/Water/Refreshment spells
- if (m_spellInfo->SpellFamilyName != SPELLFAMILY_MAGE || (!(m_spellInfo->SpellFamilyFlags[0] & 0x40000000)))
- return SPELL_FAILED_TOO_MANY_OF_ITEM;
- else if (!(target->ToPlayer()->HasItemCount(m_spellInfo->Effects[i].ItemType)))
+ ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(m_spellInfo->Effects[i].ItemType);
+ /// @todo Needs review
+ if (itemTemplate && !itemTemplate->ItemLimitCategory)
{
player->SendEquipError(msg, nullptr, nullptr, m_spellInfo->Effects[i].ItemType);
return SPELL_FAILED_DONT_REPORT;
}
else
- player->CastSpell(player, m_spellInfo->Effects[EFFECT_1].CalcValue(), false); // move this to anywhere
- return SPELL_FAILED_DONT_REPORT;
+ {
+ // Conjure Food/Water/Refreshment spells
+ if (m_spellInfo->SpellFamilyName != SPELLFAMILY_MAGE || (!(m_spellInfo->SpellFamilyFlags[0] & 0x40000000)))
+ return SPELL_FAILED_TOO_MANY_OF_ITEM;
+ else if (!(target->ToPlayer()->HasItemCount(m_spellInfo->Effects[i].ItemType)))
+ {
+ player->SendEquipError(msg, nullptr, nullptr, m_spellInfo->Effects[i].ItemType);
+ return SPELL_FAILED_DONT_REPORT;
+ }
+ else
+ player->CastSpell(player, m_spellInfo->Effects[EFFECT_1].CalcValue(), false); // move this to anywhere
+ return SPELL_FAILED_DONT_REPORT;
+ }
}
}
}
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index cdc5936a80b..e0d54a6c107 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -1624,31 +1624,20 @@ void Spell::EffectCreateItem2(SpellEffIndex effIndex)
Player* player = unitTarget->ToPlayer();
- uint32 item_id = m_spellInfo->Effects[effIndex].ItemType;
-
- if (item_id)
- DoCreateItem(effIndex, item_id);
-
- // special case: fake item replaced by generate using spell_loot_template
+ // Pick a random item from spell_loot_template
if (m_spellInfo->IsLootCrafting())
{
- if (item_id)
- {
- if (!player->HasItemCount(item_id))
- return;
-
- // remove reagent
- uint32 count = 1;
- player->DestroyItemCount(item_id, count, true);
-
- // create some random items
- player->AutoStoreLoot(m_spellInfo->Id, LootTemplates_Spell);
- }
- else
- player->AutoStoreLoot(m_spellInfo->Id, LootTemplates_Spell); // create some random items
-
+ player->AutoStoreLoot(m_spellInfo->Id, LootTemplates_Spell, false, true);
player->UpdateCraftSkill(m_spellInfo->Id);
}
+ else // If there's no random loot entries for this spell, pick the item associated with this spell
+ {
+ uint32 item_id = m_spellInfo->Effects[effIndex].ItemType;
+
+ if (item_id)
+ DoCreateItem(effIndex, item_id);
+ }
+
/// @todo ExecuteLogEffectCreateItem(i, m_spellInfo->Effects[i].ItemType);
}