diff options
| author | Wyrserth <43747507+Wyrserth@users.noreply.github.com> | 2019-06-15 15:11:49 +0200 | 
|---|---|---|
| committer | Giacomo Pozzoni <giacomopoz@gmail.com> | 2019-06-15 15:11:49 +0200 | 
| commit | 218055280af4563f28643e2683eafe40808f90db (patch) | |
| tree | 243d799c21e273775b07975d450e8ebc58861b3e | |
| parent | 865ab86173b529bd96cbd1b7fb929def9fc895ce (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.cpp | 22 | ||||
| -rw-r--r-- | src/server/game/Entities/Player/Player.h | 1 | ||||
| -rw-r--r-- | src/server/game/Spells/Spell.cpp | 44 | ||||
| -rw-r--r-- | src/server/game/Spells/SpellEffects.cpp | 31 | 
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);  }  | 
