diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index 2fe16537f47..dfbdc5e4ee4 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -2644,6 +2644,19 @@ enum PetTameFailureReason PETTAME_UNKNOWNERROR = 13 }; +// Stored in SummonProperties.dbc with slot+1 values +enum TotemSlot +{ + TOTEM_SLOT_FIRE = 0, + TOTEM_SLOT_EARTH = 1, + TOTEM_SLOT_WATER = 2, + TOTEM_SLOT_AIR = 3, +}; + +#define TOTEM_SLOT_NONE 255 // custom value for no slot case + +#define MAX_TOTEM_SLOT 4 + // we need to stick to 1 version or half of the stuff will work for someone // others will not and opposite // will only support WoW, WoW:TBC and WoW:WotLK 3.3.2 client build 11403... diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 2a96b694101..a9f756910b5 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -4515,7 +4515,7 @@ SpellCastResult Spell::CheckCast(bool strict) if (m_spellInfo->SpellFamilyName == SPELLFAMILY_SHAMAN && m_spellInfo->SpellIconID == 33) { // fire totems slot - if (!m_caster->m_TotemSlot[0]) + if (!m_caster->GetTotemGUID(TOTEM_SLOT_FIRE)) return SPELL_FAILED_TOTEMS; } break; diff --git a/src/game/Spell.h b/src/game/Spell.h index 545abdd4599..ca93d5d361c 100644 --- a/src/game/Spell.h +++ b/src/game/Spell.h @@ -368,7 +368,7 @@ class Spell void DoSummon(SpellEffectIndex eff_idx); void DoSummonWild(SpellEffectIndex eff_idx, uint32 forceFaction = 0); void DoSummonGuardian(SpellEffectIndex eff_idx, uint32 forceFaction = 0); - void DoSummonTotem(SpellEffectIndex eff_idx, uint8 slot = 0); + void DoSummonTotem(SpellEffectIndex eff_idx, uint8 slot_dbc = 0); void DoSummonCritter(SpellEffectIndex eff_idx, uint32 forceFaction = 0); void WriteSpellGoTargets( WorldPacket * data ); diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 48da2040f6c..8e1ef9efe5d 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -2122,17 +2122,7 @@ void Aura::TriggerSpell() // Totemic Mastery (Skyshatter Regalia (Shaman Tier 6) - bonus) case 38443: { - bool all = true; - for(int i = 0; i < MAX_TOTEM; ++i) - { - if(!target->m_TotemSlot[i]) - { - all = false; - break; - } - } - - if(all) + if(target->IsAllTotemSlotsUsed()) target->CastSpell(target, 38437, true, NULL, this); else target->RemoveAurasDueToSpell(38437); diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index e0d5a70974f..fdb71a0556e 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -2214,10 +2214,7 @@ void Spell::EffectDummy(SpellEffectIndex eff_idx) if (m_spellInfo->SpellIconID == 33) { // fire totems slot - if (!m_caster->m_TotemSlot[0]) - return; - - Creature* totem = m_caster->GetMap()->GetCreature(m_caster->m_TotemSlot[0]); + Totem* totem = m_caster->GetTotem(TOTEM_SLOT_FIRE); if (!totem) return; @@ -6267,20 +6264,15 @@ void Spell::EffectApplyGlyph(SpellEffectIndex eff_idx) } } -void Spell::DoSummonTotem(SpellEffectIndex eff_idx, uint8 slot) +void Spell::DoSummonTotem(SpellEffectIndex eff_idx, uint8 slot_dbc) { - slot = slot ? (slot - 1): 255; + // DBC store slots starting from 1, with no slot 0 value) + int slot = slot_dbc ? slot_dbc - 1 : TOTEM_SLOT_NONE; - if(slot < MAX_TOTEM) - { - uint64 guid = m_caster->m_TotemSlot[slot]; - if(guid != 0) - { - Creature *OldTotem = m_caster->GetMap()->GetCreature(guid); - if(OldTotem && OldTotem->isTotem()) - ((Totem*)OldTotem)->UnSummon(); - } - } + // unsummon old totem + if(slot < MAX_TOTEM_SLOT) + if (Totem *OldTotem = m_caster->GetTotem(TotemSlot(slot))) + OldTotem->UnSummon(); uint32 team = 0; if (m_caster->GetTypeId()==TYPEID_PLAYER) @@ -6295,7 +6287,7 @@ void Spell::DoSummonTotem(SpellEffectIndex eff_idx, uint8 slot) return; } - float angle = slot < MAX_TOTEM ? M_PI_F/MAX_TOTEM - (slot*2*M_PI_F/MAX_TOTEM) : 0; + float angle = slot < MAX_TOTEM_SLOT ? M_PI_F/MAX_TOTEM_SLOT - (slot*2*M_PI_F/MAX_TOTEM_SLOT) : 0; float x, y, z; m_caster->GetClosePoint(x, y, z, pTotem->GetObjectSize(), 2.0f, angle); @@ -6306,14 +6298,14 @@ void Spell::DoSummonTotem(SpellEffectIndex eff_idx, uint8 slot) pTotem->Relocate(x, y, z, m_caster->GetOrientation()); - if(slot < MAX_TOTEM) - m_caster->m_TotemSlot[slot] = pTotem->GetGUID(); + if (slot < MAX_TOTEM_SLOT) + m_caster->_AddTotem(TotemSlot(slot),pTotem); pTotem->SetOwner(m_caster->GetGUID()); pTotem->SetTypeBySummonSpell(m_spellInfo); // must be after Create call where m_spells initilized int32 duration=GetSpellDuration(m_spellInfo); - if(Player* modOwner = m_caster->GetSpellModOwner()) + if (Player* modOwner = m_caster->GetSpellModOwner()) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration); pTotem->SetDuration(duration); @@ -6336,7 +6328,7 @@ void Spell::DoSummonTotem(SpellEffectIndex eff_idx, uint8 slot) pTotem->Summon(m_caster); - if(slot < MAX_TOTEM && m_caster->GetTypeId() == TYPEID_PLAYER) + if (slot < MAX_TOTEM_SLOT && m_caster->GetTypeId() == TYPEID_PLAYER) { WorldPacket data(SMSG_TOTEM_CREATED, 1 + 8 + 4 + 4); data << uint8(slot); @@ -6938,22 +6930,17 @@ void Spell::EffectSummonAllTotems(SpellEffectIndex eff_idx) void Spell::EffectDestroyAllTotems(SpellEffectIndex /*eff_idx*/) { int32 mana = 0; - for(int slot = 0; slot < MAX_TOTEM; ++slot) + for(int slot = 0; slot < MAX_TOTEM_SLOT; ++slot) { - if(!m_caster->m_TotemSlot[slot]) - continue; - - Creature* totem = m_caster->GetMap()->GetCreature(m_caster->m_TotemSlot[slot]); - if(totem && totem->isTotem()) + if (Totem* totem = m_caster->GetTotem(TotemSlot(slot))) { uint32 spell_id = totem->GetUInt32Value(UNIT_CREATED_BY_SPELL); - SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id); - if(spellInfo) + if (SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id)) { uint32 manacost = m_caster->GetCreateMana() * spellInfo->ManaCostPercentage / 100; mana += manacost * damage / 100; } - ((Totem*)totem)->UnSummon(); + totem->UnSummon(); } } diff --git a/src/game/SpellHandler.cpp b/src/game/SpellHandler.cpp index 7edaafc6e01..e42e5237b8d 100644 --- a/src/game/SpellHandler.cpp +++ b/src/game/SpellHandler.cpp @@ -521,15 +521,11 @@ void WorldSession::HandleTotemDestroyed( WorldPacket& recvPacket) recvPacket >> slotId; - if (slotId >= MAX_TOTEM) + if (int(slotId) >= MAX_TOTEM_SLOT) return; - if(!_player->m_TotemSlot[slotId]) - return; - - Creature* totem = GetPlayer()->GetMap()->GetCreature(_player->m_TotemSlot[slotId]); - if(totem && totem->isTotem()) - ((Totem*)totem)->UnSummon(); + if (Totem* totem = GetPlayer()->GetTotem(TotemSlot(slotId))) + totem->UnSummon(); } void WorldSession::HandleSelfResOpcode( WorldPacket & /*recv_data*/ ) diff --git a/src/game/Totem.cpp b/src/game/Totem.cpp index 81e8ae49072..12130d69e7c 100644 --- a/src/game/Totem.cpp +++ b/src/game/Totem.cpp @@ -90,16 +90,7 @@ void Totem::UnSummon() if (Unit *owner = GetOwner()) { - // clear owner's totem slot - for(int i = 0; i < MAX_TOTEM; ++i) - { - if(owner->m_TotemSlot[i] == GetGUID()) - { - owner->m_TotemSlot[i] = 0; - break; - } - } - + owner->_RemoveTotem(this); owner->RemoveAurasDueToSpell(GetSpell()); //remove aura all party members too diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index c13c8335a1b..806d846be17 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -213,7 +213,7 @@ Unit::Unit() m_addDmgOnce = 0; - for(int i = 0; i < MAX_TOTEM; ++i) + for(int i = 0; i < MAX_TOTEM_SLOT; ++i) m_TotemSlot[i] = 0; m_ObjectSlot[0] = m_ObjectSlot[1] = m_ObjectSlot[2] = m_ObjectSlot[3] = 0; @@ -8666,33 +8666,54 @@ Pet* Unit::FindGuardianWithEntry(uint32 entry) return NULL; } -Unit* Unit::_GetTotem(uint8 slot) const +Unit* Unit::_GetTotem(TotemSlot slot) const { return GetTotem(slot); } -Totem* Unit::GetTotem( uint8 slot ) const +Totem* Unit::GetTotem(TotemSlot slot ) const { - if(slot >= MAX_TOTEM || !IsInWorld()) + if(slot >= MAX_TOTEM_SLOT || !IsInWorld()) return NULL; Creature *totem = GetMap()->GetCreature(m_TotemSlot[slot]); return totem && totem->isTotem() ? (Totem*)totem : NULL; } -void Unit::UnsummonAllTotems() +bool Unit::IsAllTotemSlotsUsed() const { - for (int8 i = 0; i < MAX_TOTEM; ++i) - { - if(!m_TotemSlot[i]) - continue; + for (int i = 0; i < MAX_TOTEM_SLOT; ++i) + if (!m_TotemSlot[i]) + return false; + return true; +} - Creature *OldTotem = GetMap()->GetCreature(m_TotemSlot[i]); - if (OldTotem && OldTotem->isTotem()) - ((Totem*)OldTotem)->UnSummon(); +void Unit::_AddTotem(TotemSlot slot, Totem* totem) +{ + m_TotemSlot[slot] = totem->GetGUID(); +} + +void Unit::_RemoveTotem(Totem* totem) +{ + for(int i = 0; i < MAX_TOTEM_SLOT; ++i) + { + if (m_TotemSlot[i] == totem->GetGUID()) + { + m_TotemSlot[i] = 0; + break; + } } } + + +void Unit::UnsummonAllTotems() +{ + for (int i = 0; i < MAX_TOTEM_SLOT; ++i) + if (Totem* totem = GetTotem(TotemSlot(i))) + totem->UnSummon(); +} + int32 Unit::DealHeal(Unit *pVictim, uint32 addhealth, SpellEntry const *spellProto, bool critical) { int32 gain = pVictim->ModifyHealth(int32(addhealth)); diff --git a/src/game/Unit.h b/src/game/Unit.h index 00ccca9b533..04d88b66f9c 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -1049,7 +1049,6 @@ enum ReactiveType }; #define MAX_REACTIVE 3 -#define MAX_TOTEM 4 typedef std::set GuardianPetList; @@ -1441,7 +1440,12 @@ class MANGOS_DLL_SPEC Unit : public WorldObject Pet* CreateTamedPetFrom(Creature* creatureTarget,uint32 spell_id = 0); - Totem* GetTotem(uint8 slot) const; + uint64 const& GetTotemGUID(TotemSlot slot) const { return m_TotemSlot[slot]; } + Totem* GetTotem(TotemSlot slot) const; + bool IsAllTotemSlotsUsed() const; + + void _AddTotem(TotemSlot slot, Totem* totem); // only for call from Totem summon code + void _RemoveTotem(Totem* totem); // only for call from Totem class template void CallForAllControlledUnits(Func const& func, bool withTotems, bool withGuardians, bool withCharms); @@ -1533,7 +1537,6 @@ class MANGOS_DLL_SPEC Unit : public WorldObject void DecreaseCastCounter() { if (m_castCounter) --m_castCounter; } uint32 m_addDmgOnce; - uint64 m_TotemSlot[MAX_TOTEM]; uint64 m_ObjectSlot[4]; uint32 m_detectInvisibilityMask; uint32 m_invisibilityMask; @@ -1854,7 +1857,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject float GetCombatRatingReduction(CombatRating cr) const; uint32 GetCombatRatingDamageReduction(CombatRating cr, float rate, float cap, uint32 damage) const; - Unit* _GetTotem(uint8 slot) const; // for templated function without include need + Unit* _GetTotem(TotemSlot slot) const; // for templated function without include need uint32 m_state; // Even derived shouldn't modify uint32 m_CombatTimer; @@ -1875,6 +1878,8 @@ class MANGOS_DLL_SPEC Unit : public WorldObject ComboPointHolderSet m_ComboPointHolders; GuardianPetList m_guardianPets; + + uint64 m_TotemSlot[MAX_TOTEM_SLOT]; }; template @@ -1892,8 +1897,8 @@ void Unit::CallForAllControlledUnits(Func const& func, bool withTotems, bool wit if (withTotems) { - for (int8 i = 0; i < MAX_TOTEM; ++i) - if (Unit *totem = _GetTotem(i)) + for (int i = 0; i < MAX_TOTEM_SLOT; ++i) + if (Unit *totem = _GetTotem(TotemSlot(i))) func(totem); } @@ -1921,8 +1926,8 @@ bool Unit::CheckAllControlledUnits(Func const& func, bool withTotems, bool withG if (withTotems) { - for (int8 i = 0; i < MAX_TOTEM; ++i) - if (Unit *totem = _GetTotem(i)) + for (int i = 0; i < MAX_TOTEM_SLOT; ++i) + if (Unit *totem = _GetTotem(TotemSlot(i))) if (func(totem)) return true; } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index b5bbb810fef..ffe0abbceda 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "9474" + #define REVISION_NR "9475" #endif // __REVISION_NR_H__