diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 309289e6f..20da49f42 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -10636,6 +10636,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 4cc62b529..9d64e6ed7 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1242,6 +1242,7 @@ public: [[nodiscard]] Item* GetItemByPos(uint16 pos) const; [[nodiscard]] Item* GetItemByPos(uint8 bag, uint8 slot) const; [[nodiscard]] Bag* GetBagByPos(uint8 slot) const; + [[nodiscard]] uint32 GetFreeInventorySpace() const; [[nodiscard]] inline Item* GetUseableItemByPos(uint8 bag, uint8 slot) const //Does additional check for disarmed weapons { if (!CanUseAttackType(GetAttackBySlot(slot))) diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index f889b09e7..63e402183 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -6695,10 +6695,11 @@ SpellCastResult Spell::CheckPower() SpellCastResult Spell::CheckItems() { - if (m_caster->GetTypeId() != TYPEID_PLAYER) + Player* player = m_caster->ToPlayer(); + if (!player) + { return SPELL_CAST_OK; - - Player* p_caster = m_caster->ToPlayer(); + } if (!m_CastItem) { @@ -6708,7 +6709,7 @@ SpellCastResult Spell::CheckItems() else { uint32 itemid = m_CastItem->GetEntry(); - if (!p_caster->HasItemCount(itemid)) + if (!player->HasItemCount(itemid)) return SPELL_FAILED_ITEM_NOT_READY; ItemTemplate const* proto = m_CastItem->GetTemplate(); @@ -6796,7 +6797,7 @@ SpellCastResult Spell::CheckItems() // do not take reagents for these item casts if (!(m_CastItem && m_CastItem->GetTemplate()->Flags & ITEM_FLAG_NO_REAGENT_COST)) { - bool checkReagents = !(_triggeredCastFlags & TRIGGERED_IGNORE_POWER_AND_REAGENT_COST) && !p_caster->CanNoReagentCast(m_spellInfo); + bool checkReagents = !(_triggeredCastFlags & TRIGGERED_IGNORE_POWER_AND_REAGENT_COST) && !player->CanNoReagentCast(m_spellInfo); // Not own traded item (in trader trade slot) requires reagents even if triggered spell if (!checkReagents) if (Item* targetItem = m_targets.GetItemTarget()) @@ -6831,7 +6832,7 @@ SpellCastResult Spell::CheckItems() } } } - if (!p_caster->HasItemCount(itemid, itemcount)) + if (!player->HasItemCount(itemid, itemcount)) return SPELL_FAILED_REAGENTS; } } @@ -6842,7 +6843,7 @@ SpellCastResult Spell::CheckItems() { if (m_spellInfo->Totem[i] != 0) { - if (p_caster->HasItemCount(m_spellInfo->Totem[i])) + if (player->HasItemCount(m_spellInfo->Totem[i])) { totems -= 1; continue; @@ -6860,7 +6861,7 @@ SpellCastResult Spell::CheckItems() { if (m_spellInfo->TotemCategory[i] != 0) { - if (p_caster->HasItemTotemCategory(m_spellInfo->TotemCategory[i])) + if (player->HasItemTotemCategory(m_spellInfo->TotemCategory[i])) { TotemCategory -= 1; continue; @@ -6895,7 +6896,7 @@ SpellCastResult Spell::CheckItems() // TODO: Needs review if (pProto && !(pProto->ItemLimitCategory)) { - p_caster->SendEquipError(msg, nullptr, nullptr, m_spellInfo->Effects[i].ItemType); + player->SendEquipError(msg, nullptr, nullptr, m_spellInfo->Effects[i].ItemType); return SPELL_FAILED_DONT_REPORT; } else @@ -6904,11 +6905,11 @@ SpellCastResult Spell::CheckItems() return SPELL_FAILED_TOO_MANY_OF_ITEM; else if (!(target->ToPlayer()->HasItemCount(m_spellInfo->Effects[i].ItemType))) { - p_caster->SendEquipError(msg, nullptr, nullptr, m_spellInfo->Effects[i].ItemType); + player->SendEquipError(msg, nullptr, nullptr, m_spellInfo->Effects[i].ItemType); return SPELL_FAILED_DONT_REPORT; } else - p_caster->CastSpell(m_caster, m_spellInfo->Effects[EFFECT_1].CalcValue(), false); // move this to anywhere + player->CastSpell(m_caster, m_spellInfo->Effects[EFFECT_1].CalcValue(), false); // move this to anywhere return SPELL_FAILED_DONT_REPORT; } } @@ -6926,10 +6927,10 @@ SpellCastResult Spell::CheckItems() if (m_CastItem && m_CastItem->GetTemplate()->Flags & ITEM_FLAG_NO_REAGENT_COST) return SPELL_FAILED_TOTEM_CATEGORY; ItemPosCountVec dest; - InventoryResult msg = p_caster->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, m_spellInfo->Effects[i].ItemType, 1); + InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, m_spellInfo->Effects[i].ItemType, 1); if (msg != EQUIP_ERR_OK) { - p_caster->SendEquipError(msg, nullptr, nullptr, m_spellInfo->Effects[i].ItemType); + player->SendEquipError(msg, nullptr, nullptr, m_spellInfo->Effects[i].ItemType); return SPELL_FAILED_DONT_REPORT; } } @@ -7042,7 +7043,7 @@ SpellCastResult Spell::CheckItems() uint32 item_disenchantskilllevel = itemProto->RequiredDisenchantSkill; if (item_disenchantskilllevel == uint32(-1)) return SPELL_FAILED_CANT_BE_DISENCHANTED; - if (item_disenchantskilllevel > p_caster->GetSkillValue(SKILL_ENCHANTING)) + if (item_disenchantskilllevel > player->GetSkillValue(SKILL_ENCHANTING)) return SPELL_FAILED_LOW_CASTLEVEL; if (item_quality > 4 || item_quality < 2) return SPELL_FAILED_CANT_BE_DISENCHANTED; @@ -7064,7 +7065,7 @@ SpellCastResult Spell::CheckItems() return SPELL_FAILED_CANT_BE_PROSPECTED; //Check for enough skill in jewelcrafting uint32 item_prospectingskilllevel = m_targets.GetItemTarget()->GetTemplate()->RequiredSkillRank; - if (item_prospectingskilllevel > p_caster->GetSkillValue(SKILL_JEWELCRAFTING)) + if (item_prospectingskilllevel > player->GetSkillValue(SKILL_JEWELCRAFTING)) return SPELL_FAILED_LOW_CASTLEVEL; //make sure the player has the required ores in inventory if (m_targets.GetItemTarget()->GetCount() < 5) @@ -7087,7 +7088,7 @@ SpellCastResult Spell::CheckItems() return SPELL_FAILED_CANT_BE_MILLED; //Check for enough skill in inscription uint32 item_millingskilllevel = m_targets.GetItemTarget()->GetTemplate()->RequiredSkillRank; - if (item_millingskilllevel > p_caster->GetSkillValue(SKILL_INSCRIPTION)) + if (item_millingskilllevel > player->GetSkillValue(SKILL_INSCRIPTION)) return SPELL_FAILED_LOW_CASTLEVEL; //make sure the player has the required herbs in inventory if (m_targets.GetItemTarget()->GetCount() < 5) @@ -7179,7 +7180,7 @@ SpellCastResult Spell::CheckItems() if (!pProto) return SPELL_FAILED_ITEM_AT_MAX_CHARGES; - if (Item* pitem = p_caster->GetItemByEntry(item_id)) + if (Item* pitem = player->GetItemByEntry(item_id)) { for (int x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x) if (pProto->Spells[x].SpellCharges != 0 && pitem->GetSpellCharges(x) == pProto->Spells[x].SpellCharges)