aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/game/Entities/Item/Item.cpp75
-rw-r--r--src/server/game/Entities/Item/Item.h6
-rw-r--r--src/server/game/Entities/Player/Player.cpp34
-rw-r--r--src/server/game/Entities/Player/Player.h6
4 files changed, 59 insertions, 62 deletions
diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp
index 90bbb1c2278..5d6be5e8c2a 100644
--- a/src/server/game/Entities/Item/Item.cpp
+++ b/src/server/game/Entities/Item/Item.cpp
@@ -51,7 +51,7 @@ void AddItemsSetItem(Player* player, Item* item)
for (size_t x = 0; x < player->ItemSetEff.size(); ++x)
{
- if (player->ItemSetEff[x] && player->ItemSetEff[x]->setid == setid)
+ if (player->ItemSetEff[x] && player->ItemSetEff[x]->ItemSetID == setid)
{
eff = player->ItemSetEff[x];
break;
@@ -61,7 +61,8 @@ void AddItemsSetItem(Player* player, Item* item)
if (!eff)
{
eff = new ItemSetEffect();
- eff->setid = setid;
+ eff->ItemSetID = setid;
+ eff->EquippedItemCount = 0;
size_t x = 0;
for (; x < player->ItemSetEff.size(); ++x)
@@ -69,51 +70,39 @@ void AddItemsSetItem(Player* player, Item* item)
break;
if (x < player->ItemSetEff.size())
- player->ItemSetEff[x]=eff;
+ player->ItemSetEff[x] = eff;
else
player->ItemSetEff.push_back(eff);
}
- ++eff->item_count;
+ ++eff->EquippedItemCount;
ItemSetSpells& spells = sItemSetSpellsStore[setid];
- for (uint32 x = 0; x < spells.size(); ++x)
+ for (ItemSetSpellEntry const* itemSetSpell : spells)
{
//not enough for spell
- if (spells[x]->Threshold > eff->item_count)
+ if (itemSetSpell->Threshold > eff->EquippedItemCount)
continue;
- uint32 z = 0;
- for (; z < MAX_ITEM_SET_SPELLS; ++z)
- if (eff->spells[z] && eff->spells[z]->Id == spells[x]->SpellID)
- break;
-
- if (z < MAX_ITEM_SET_SPELLS)
+ if (eff->SetBonuses.count(itemSetSpell))
continue;
- //new spell
- for (uint32 y = 0; y < MAX_ITEM_SET_SPELLS; ++y)
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itemSetSpell->SpellID);
+ if (!spellInfo)
{
- if (!eff->spells[y]) // free slot
- {
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spells[x]->SpellID);
- if (!spellInfo)
- {
- TC_LOG_ERROR("entities.player.items", "WORLD: unknown spell id %u in items set %u effects", spells[x]->SpellID, setid);
- break;
- }
-
- // spell cast only if fit form requirement, in other case will cast at form change
- player->ApplyEquipSpell(spellInfo, NULL, true);
- eff->spells[y] = spellInfo;
- break;
- }
+ TC_LOG_ERROR("entities.player.items", "WORLD: unknown spell id %u in items set %u effects", itemSetSpell->SpellID, setid);
+ continue;
}
+
+ eff->SetBonuses.insert(itemSetSpell);
+ // spell cast only if fit form requirement, in other case will cast at form change
+ if (!itemSetSpell->ChrSpecID || itemSetSpell->ChrSpecID == player->GetUInt32Value(PLAYER_FIELD_CURRENT_SPEC_ID))
+ player->ApplyEquipSpell(spellInfo, NULL, true);
}
}
-void RemoveItemsSetItem(Player*player, ItemTemplate const* proto)
+void RemoveItemsSetItem(Player* player, ItemTemplate const* proto)
{
uint32 setid = proto->GetItemSet();
@@ -129,7 +118,7 @@ void RemoveItemsSetItem(Player*player, ItemTemplate const* proto)
size_t setindex = 0;
for (; setindex < player->ItemSetEff.size(); setindex++)
{
- if (player->ItemSetEff[setindex] && player->ItemSetEff[setindex]->setid == setid)
+ if (player->ItemSetEff[setindex] && player->ItemSetEff[setindex]->ItemSetID == setid)
{
eff = player->ItemSetEff[setindex];
break;
@@ -140,29 +129,23 @@ void RemoveItemsSetItem(Player*player, ItemTemplate const* proto)
if (!eff)
return;
- --eff->item_count;
-
- ItemSetSpells& spells = sItemSetSpellsStore[setid];
+ --eff->EquippedItemCount;
- for (uint32 x = 0; x < spells.size(); x++)
+ ItemSetSpells const& spells = sItemSetSpellsStore[setid];
+ for (ItemSetSpellEntry const* itemSetSpell : spells)
{
// enough for spell
- if (spells[x]->Threshold <= eff->item_count)
+ if (itemSetSpell->Threshold <= eff->EquippedItemCount)
continue;
- for (uint32 z = 0; z < MAX_ITEM_SET_SPELLS; z++)
- {
- if (eff->spells[z] && eff->spells[z]->Id == spells[x]->SpellID)
- {
- // spell can be not active if not fit form requirement
- player->ApplyEquipSpell(eff->spells[z], NULL, false);
- eff->spells[z]=NULL;
- break;
- }
- }
+ if (!eff->SetBonuses.count(itemSetSpell))
+ continue;
+
+ player->ApplyEquipSpell(sSpellMgr->AssertSpellInfo(itemSetSpell->SpellID), nullptr, false);
+ eff->SetBonuses.erase(itemSetSpell);
}
- if (!eff->item_count) //all items of a set were removed
+ if (!eff->EquippedItemCount) //all items of a set were removed
{
ASSERT(eff == player->ItemSetEff[setindex]);
delete eff;
diff --git a/src/server/game/Entities/Item/Item.h b/src/server/game/Entities/Item/Item.h
index 545d402b699..ffd4872a2e8 100644
--- a/src/server/game/Entities/Item/Item.h
+++ b/src/server/game/Entities/Item/Item.h
@@ -31,9 +31,9 @@ class Unit;
struct ItemSetEffect
{
- uint32 setid;
- uint32 item_count;
- SpellInfo const* spells[8];
+ uint32 ItemSetID;
+ uint32 EquippedItemCount;
+ std::unordered_set<ItemSetSpellEntry const*> SetBonuses;
};
enum InventoryResult
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 3365b1c79dd..f3426010071 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -7970,7 +7970,7 @@ void Player::_ApplyWeaponDependentAuraDamageMod(Item* item, WeaponAttackType att
}
}
-void Player::ApplyItemEquipSpell(Item* item, bool apply, bool form_change)
+void Player::ApplyItemEquipSpell(Item* item, bool apply, bool formChange /*= false*/)
{
if (!item)
return;
@@ -7992,11 +7992,11 @@ void Player::ApplyItemEquipSpell(Item* item, bool apply, bool form_change)
if (!spellproto)
continue;
- ApplyEquipSpell(spellproto, item, apply, form_change);
+ ApplyEquipSpell(spellproto, item, apply, formChange);
}
}
-void Player::ApplyEquipSpell(SpellInfo const* spellInfo, Item* item, bool apply, bool form_change)
+void Player::ApplyEquipSpell(SpellInfo const* spellInfo, Item* item, bool apply, bool formChange /*= false*/)
{
if (apply)
{
@@ -8004,7 +8004,7 @@ void Player::ApplyEquipSpell(SpellInfo const* spellInfo, Item* item, bool apply,
if (spellInfo->CheckShapeshift(GetShapeshiftForm()) != SPELL_CAST_OK)
return;
- if (form_change) // check aura active state from other form
+ if (formChange) // check aura active state from other form
{
AuraApplicationMapBounds range = GetAppliedAuras().equal_range(spellInfo->Id);
for (AuraApplicationMap::const_iterator itr = range.first; itr != range.second; ++itr)
@@ -8018,7 +8018,7 @@ void Player::ApplyEquipSpell(SpellInfo const* spellInfo, Item* item, bool apply,
}
else
{
- if (form_change) // check aura compatibility
+ if (formChange) // check aura compatibility
{
// Cannot be used in this stance/form
if (spellInfo->CheckShapeshift(GetShapeshiftForm()) == SPELL_CAST_OK)
@@ -8043,6 +8043,11 @@ void Player::UpdateEquipSpellsAtFormChange()
}
}
+ UpdateItemSetAuras(true);
+}
+
+void Player::UpdateItemSetAuras(bool formChange /*= false*/)
+{
// item set bonuses not dependent from item broken state
for (size_t setindex = 0; setindex < ItemSetEff.size(); ++setindex)
{
@@ -8050,17 +8055,21 @@ void Player::UpdateEquipSpellsAtFormChange()
if (!eff)
continue;
- for (uint32 y = 0; y < MAX_ITEM_SET_SPELLS; ++y)
+ for (ItemSetSpellEntry const* itemSetSpell : eff->SetBonuses)
{
- SpellInfo const* spellInfo = eff->spells[y];
- if (!spellInfo)
- continue;
+ SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itemSetSpell->SpellID);
- ApplyEquipSpell(spellInfo, NULL, false, true); // remove spells that not fit to form
- ApplyEquipSpell(spellInfo, NULL, true, true); // add spells that fit form but not active
+ if (itemSetSpell->ChrSpecID && itemSetSpell->ChrSpecID != GetUInt32Value(PLAYER_FIELD_CURRENT_SPEC_ID))
+ ApplyEquipSpell(spellInfo, nullptr, false, false); // item set aura is not for current spec
+ else
+ {
+ ApplyEquipSpell(spellInfo, nullptr, false, formChange); // remove spells that not fit to form - removal is skipped if shapeshift condition is satisfied
+ ApplyEquipSpell(spellInfo, nullptr, true, formChange); // add spells that fit form but not active
+ }
}
}
}
+
void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32 procVictim, uint32 procEx)
{
if (!target || !target->IsAlive() || target == this)
@@ -25043,6 +25052,7 @@ void Player::LearnTalentSpecialization(uint32 talentSpec)
LearnSpecializationSpells();
SendTalentsInfoData();
+ UpdateItemSetAuras(false);
}
void Player::ResetTalentSpecialization()
@@ -25063,6 +25073,7 @@ void Player::ResetTalentSpecialization()
RemoveSpecializationSpells();
SendTalentsInfoData();
+ UpdateItemSetAuras(false);
}
void Player::UpdateFallInformationIfNeed(MovementInfo const& minfo, uint16 opcode)
@@ -25619,6 +25630,7 @@ void Player::ActivateTalentGroup(uint8 spec)
SetPower(POWER_MANA, 0); // Mana must be 0 even if it isn't the active power type.
SetPower(pw, 0);
+ UpdateItemSetAuras(false);
if (!sChrSpecializationStore.LookupEntry(GetSpecId(GetActiveTalentGroup())))
ResetTalents(true);
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index fa183c78cb3..d61b7845abf 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -2279,9 +2279,11 @@ class Player : public Unit, public GridObject<Player>
void CorrectMetaGemEnchants(uint8 slot, bool apply);
void InitDataForForm(bool reapplyMods = false);
- void ApplyItemEquipSpell(Item* item, bool apply, bool form_change = false);
- void ApplyEquipSpell(SpellInfo const* spellInfo, Item* item, bool apply, bool form_change = false);
+ void ApplyItemEquipSpell(Item* item, bool apply, bool formChange = false);
+ void ApplyEquipSpell(SpellInfo const* spellInfo, Item* item, bool apply, bool formChange = false);
void UpdateEquipSpellsAtFormChange();
+ void UpdateItemSetAuras(bool formChange = false);
+
void CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32 procVictim, uint32 procEx);
void CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8 castCount, uint32 misc);
void CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32 procVictim, uint32 procEx, Item* item, ItemTemplate const* proto);