@@ -171,7 +171,7 @@ void AuctionPosting::BuildAuctionItem(WorldPackets::AuctionHouse::AuctionItem* a
|
||||
{
|
||||
auctionItem->Item.emplace();
|
||||
auctionItem->Item->Initialize(Items[0]);
|
||||
auctionItem->Charges = std::max({ Items[0]->GetSpellCharges(0), Items[0]->GetSpellCharges(1), Items[0]->GetSpellCharges(2), Items[0]->GetSpellCharges(3), Items[0]->GetSpellCharges(4) });
|
||||
auctionItem->Charges = Items[0]->GetSpellCharges();
|
||||
for (uint8 i = 0; i < MAX_INSPECTED_ENCHANTMENT_SLOT; i++)
|
||||
{
|
||||
uint32 enchantId = Items[0]->GetEnchantmentId(EnchantmentSlot(i));
|
||||
|
||||
@@ -488,9 +488,8 @@ bool Item::Create(ObjectGuid::LowType guidlow, uint32 itemId, ItemContext contex
|
||||
SetUpdateFieldValue(m_values.ModifyValue(&Item::m_itemData).ModifyValue(&UF::ItemData::MaxDurability), itemProto->MaxDurability);
|
||||
SetDurability(itemProto->MaxDurability);
|
||||
|
||||
for (std::size_t i = 0; i < itemProto->Effects.size(); ++i)
|
||||
if (itemProto->Effects[i]->LegacySlotIndex < 5)
|
||||
SetSpellCharges(itemProto->Effects[i]->LegacySlotIndex, itemProto->Effects[i]->Charges);
|
||||
for (ItemEffectEntry const* effect : GetEffects())
|
||||
SetSpellCharges(effect, effect->Charges);
|
||||
|
||||
SetExpiration(itemProto->GetDuration());
|
||||
SetCreatePlayedTime(0);
|
||||
@@ -559,6 +558,43 @@ void Item::UpdateDuration(Player* owner, uint32 diff)
|
||||
SetState(ITEM_CHANGED, owner); // save new time in database
|
||||
}
|
||||
|
||||
static uint32 FindSpellChargesSlot(BonusData const& bonusData, ItemEffectEntry const* effect)
|
||||
{
|
||||
static constexpr uint32 MaxSpellChargesSlot = UF::size<decltype(UF::ItemData::SpellCharges)>();
|
||||
|
||||
if (!effect)
|
||||
{
|
||||
// return fist effect that has charges
|
||||
for (uint32 i = 0; i < bonusData.EffectCount && i < MaxSpellChargesSlot; ++i)
|
||||
if (bonusData.Effects[i] && bonusData.Effects[i]->Charges != 0)
|
||||
return i;
|
||||
|
||||
return MaxSpellChargesSlot;
|
||||
}
|
||||
|
||||
for (uint32 i = 0; i < bonusData.EffectCount && i < MaxSpellChargesSlot; ++i)
|
||||
if (bonusData.Effects[i] == effect)
|
||||
return i;
|
||||
|
||||
return MaxSpellChargesSlot;
|
||||
}
|
||||
|
||||
int32 Item::GetSpellCharges(ItemEffectEntry const* effect /*= nullptr*/) const
|
||||
{
|
||||
uint32 slot = FindSpellChargesSlot(_bonusData, effect);
|
||||
if (slot < m_itemData->SpellCharges.size())
|
||||
return m_itemData->SpellCharges[slot];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Item::SetSpellCharges(ItemEffectEntry const* effect, int32 value)
|
||||
{
|
||||
uint32 slot = FindSpellChargesSlot(_bonusData, effect);
|
||||
if (slot < m_itemData->SpellCharges.size())
|
||||
SetUpdateFieldValue(m_values.ModifyValue(&Item::m_itemData).ModifyValue(&UF::ItemData::SpellCharges, slot), value);
|
||||
}
|
||||
|
||||
void Item::SaveToDB(CharacterDatabaseTransaction trans)
|
||||
{
|
||||
bool isInTransaction = bool(trans);
|
||||
@@ -581,7 +617,7 @@ void Item::SaveToDB(CharacterDatabaseTransaction trans)
|
||||
|
||||
std::ostringstream ssSpells;
|
||||
for (uint8 i = 0; i < m_itemData->SpellCharges.size() && i < _bonusData.EffectCount; ++i)
|
||||
ssSpells << GetSpellCharges(i) << ' ';
|
||||
ssSpells << m_itemData->SpellCharges[i] << ' ';
|
||||
stmt->setString(++index, ssSpells.str());
|
||||
|
||||
stmt->setUInt32(++index, m_itemData->DynamicFlags);
|
||||
@@ -927,7 +963,7 @@ bool Item::LoadFromDB(ObjectGuid::LowType guid, ObjectGuid ownerGuid, Field* fie
|
||||
// load charges after bonuses, they can add more item effects
|
||||
std::vector<std::string_view> tokens = Trinity::Tokenize(fields[6].GetStringView(), ' ', false);
|
||||
for (uint8 i = 0; i < m_itemData->SpellCharges.size() && i < _bonusData.EffectCount && i < tokens.size(); ++i)
|
||||
SetSpellCharges(i, Trinity::StringTo<int32>(tokens[i]).value_or(0));
|
||||
SetUpdateFieldValue(m_values.ModifyValue(&Item::m_itemData).ModifyValue(&UF::ItemData::SpellCharges, i), Trinity::StringTo<int32>(tokens[i]).value_or(0));
|
||||
|
||||
SetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_ALL_SPECS, fields[20].GetUInt32());
|
||||
SetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_SPEC_1, fields[21].GetUInt32());
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include "ItemDefines.h"
|
||||
#include "ItemEnchantmentMgr.h"
|
||||
#include "ItemTemplate.h"
|
||||
#include "IteratorPair.h"
|
||||
|
||||
class SpellInfo;
|
||||
class Bag;
|
||||
@@ -313,8 +312,8 @@ class TC_GAME_API Item : public Object
|
||||
void SetCreateTime(int64 createTime) { SetUpdateFieldValue(m_values.ModifyValue(&Item::m_itemData).ModifyValue(&UF::ItemData::CreateTime), createTime); }
|
||||
|
||||
// spell charges (signed but stored as unsigned)
|
||||
int32 GetSpellCharges(uint8 index/*0..5*/ = 0) const { return m_itemData->SpellCharges[index]; }
|
||||
void SetSpellCharges(uint8 index/*0..5*/, int32 value) { SetUpdateFieldValue(m_values.ModifyValue(&Item::m_itemData).ModifyValue(&UF::ItemData::SpellCharges, index), value); }
|
||||
int32 GetSpellCharges(ItemEffectEntry const* effect = nullptr) const;
|
||||
void SetSpellCharges(ItemEffectEntry const* effect, int32 value);
|
||||
|
||||
std::unique_ptr<Loot> m_loot;
|
||||
bool m_lootGenerated;
|
||||
@@ -354,7 +353,7 @@ class TC_GAME_API Item : public Object
|
||||
Optional<uint16> GetDisenchantSkillRequired() const;
|
||||
static ItemDisenchantLootEntry const* GetBaseDisenchantLoot(ItemTemplate const* itemTemplate, uint32 quality, uint32 itemLevel);
|
||||
void SetFixedLevel(uint8 level);
|
||||
Trinity::IteratorPair<ItemEffectEntry const* const*> GetEffects() const { return { std::make_pair(_bonusData.Effects.data(), _bonusData.Effects.data() + _bonusData.EffectCount) }; }
|
||||
std::span<ItemEffectEntry const* const> GetEffects() const { return { _bonusData.Effects.data(), _bonusData.EffectCount }; }
|
||||
|
||||
// Item Refund system
|
||||
void SetNotRefundable(Player* owner, bool changestate = true, CharacterDatabaseTransaction* trans = nullptr, bool addToCollection = true);
|
||||
|
||||
@@ -3369,9 +3369,16 @@ void ObjectMgr::LoadItemTemplates()
|
||||
|
||||
// Load item effects (spells)
|
||||
for (ItemXItemEffectEntry const* effectEntry : sItemXItemEffectStore)
|
||||
{
|
||||
if (ItemTemplate* item = Trinity::Containers::MapGetValuePtr(_itemTemplateStore, effectEntry->ItemID))
|
||||
{
|
||||
if (ItemEffectEntry const* effect = sItemEffectStore.LookupEntry(effectEntry->ItemEffectID))
|
||||
item->Effects.push_back(effect);
|
||||
{
|
||||
auto itr = std::ranges::lower_bound(item->Effects, effect->LegacySlotIndex, {}, &ItemEffectEntry::LegacySlotIndex);
|
||||
item->Effects.insert(itr, effect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TC_LOG_INFO("server.loading", ">> Loaded {} item templates in {} ms", _itemTemplateStore.size(), GetMSTimeDiffToNow(oldMSTime));
|
||||
}
|
||||
|
||||
@@ -5478,23 +5478,24 @@ void Spell::TakeCastItem()
|
||||
|
||||
for (ItemEffectEntry const* itemEffect : m_CastItem->GetEffects())
|
||||
{
|
||||
if (itemEffect->LegacySlotIndex >= m_CastItem->m_itemData->SpellCharges.size())
|
||||
continue;
|
||||
|
||||
// item has limited charges
|
||||
if (itemEffect->Charges)
|
||||
{
|
||||
if (itemEffect->Charges < 0)
|
||||
expendable = true;
|
||||
|
||||
int32 charges = m_CastItem->GetSpellCharges(itemEffect->LegacySlotIndex);
|
||||
int32 charges = m_CastItem->GetSpellCharges(itemEffect);
|
||||
|
||||
// item has charges left for this slot
|
||||
if (charges && itemEffect->SpellID == int32(m_spellInfo->Id))
|
||||
{
|
||||
(charges > 0) ? --charges : ++charges; // abs(charges) less at 1 after use
|
||||
if (charges > 0)
|
||||
--charges;
|
||||
else
|
||||
++charges;
|
||||
|
||||
if (proto->GetMaxStackSize() == 1)
|
||||
m_CastItem->SetSpellCharges(itemEffect->LegacySlotIndex, charges);
|
||||
m_CastItem->SetSpellCharges(itemEffect, charges);
|
||||
m_CastItem->SetState(ITEM_CHANGED, player);
|
||||
}
|
||||
|
||||
@@ -5712,11 +5713,8 @@ void Spell::TakeReagents()
|
||||
{
|
||||
for (ItemEffectEntry const* itemEffect : m_CastItem->GetEffects())
|
||||
{
|
||||
if (itemEffect->LegacySlotIndex >= m_CastItem->m_itemData->SpellCharges.size())
|
||||
continue;
|
||||
|
||||
// CastItem will be used up and does not count as reagent
|
||||
int32 charges = m_CastItem->GetSpellCharges(itemEffect->LegacySlotIndex);
|
||||
int32 charges = m_CastItem->GetSpellCharges(itemEffect);
|
||||
if (itemEffect->Charges < 0 && abs(charges) < 2)
|
||||
{
|
||||
++itemcount;
|
||||
@@ -7527,9 +7525,8 @@ SpellCastResult Spell::CheckItems(int32* param1 /*= nullptr*/, int32* param2 /*=
|
||||
return SPELL_FAILED_ITEM_NOT_READY;
|
||||
|
||||
for (ItemEffectEntry const* itemEffect : m_CastItem->GetEffects())
|
||||
if (itemEffect->LegacySlotIndex < m_CastItem->m_itemData->SpellCharges.size() && itemEffect->Charges)
|
||||
if (m_CastItem->GetSpellCharges(itemEffect->LegacySlotIndex) == 0)
|
||||
return SPELL_FAILED_NO_CHARGES_REMAIN;
|
||||
if (itemEffect->Charges && m_CastItem->GetSpellCharges(itemEffect) == 0)
|
||||
return SPELL_FAILED_NO_CHARGES_REMAIN;
|
||||
|
||||
// consumable cast item checks
|
||||
if (proto->GetClass() == ITEM_CLASS_CONSUMABLE && m_targets.GetUnitTarget())
|
||||
@@ -7631,11 +7628,8 @@ SpellCastResult Spell::CheckItems(int32* param1 /*= nullptr*/, int32* param2 /*=
|
||||
|
||||
for (ItemEffectEntry const* itemEffect : m_CastItem->GetEffects())
|
||||
{
|
||||
if (itemEffect->LegacySlotIndex >= m_CastItem->m_itemData->SpellCharges.size())
|
||||
continue;
|
||||
|
||||
// CastItem will be used up and does not count as reagent
|
||||
int32 charges = m_CastItem->GetSpellCharges(itemEffect->LegacySlotIndex);
|
||||
int32 charges = m_CastItem->GetSpellCharges(itemEffect);
|
||||
if (itemEffect->Charges < 0 && abs(charges) < 2)
|
||||
{
|
||||
++itemcount;
|
||||
@@ -7991,9 +7985,7 @@ SpellCastResult Spell::CheckItems(int32* param1 /*= nullptr*/, int32* param2 /*=
|
||||
|
||||
if (Item* item = player->GetItemByEntry(itemId))
|
||||
for (ItemEffectEntry const* itemEffect : item->GetEffects())
|
||||
if (itemEffect->LegacySlotIndex <= item->m_itemData->SpellCharges.size()
|
||||
&& itemEffect->Charges != 0
|
||||
&& item->GetSpellCharges(itemEffect->LegacySlotIndex) == itemEffect->Charges)
|
||||
if (itemEffect->Charges != 0 && item->GetSpellCharges(itemEffect) == itemEffect->Charges)
|
||||
return SPELL_FAILED_ITEM_AT_MAX_CHARGES;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -5170,8 +5170,7 @@ void Spell::EffectRechargeItem()
|
||||
if (Item* item = player->GetItemByEntry(effectInfo->ItemType))
|
||||
{
|
||||
for (ItemEffectEntry const* itemEffect : item->GetEffects())
|
||||
if (itemEffect->LegacySlotIndex <= item->m_itemData->SpellCharges.size())
|
||||
item->SetSpellCharges(itemEffect->LegacySlotIndex, itemEffect->Charges);
|
||||
item->SetSpellCharges(itemEffect, itemEffect->Charges);
|
||||
|
||||
item->SetState(ITEM_CHANGED, player);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user