diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/common/mmaps_common/Management/MMapManager.cpp | 86 | ||||
| -rw-r--r-- | src/server/game/Entities/Object/Updates/UpdateFields.cpp | 43 | ||||
| -rw-r--r-- | src/server/game/Entities/Object/Updates/UpdateFields.h | 12 | ||||
| -rw-r--r-- | src/server/game/Spells/Auras/SpellAuraEffects.cpp | 2 | ||||
| -rw-r--r-- | src/server/game/Spells/SpellDefines.h | 2 | ||||
| -rw-r--r-- | src/server/scripts/Spells/spell_paladin.cpp | 43 | ||||
| -rw-r--r-- | src/server/scripts/Spells/spell_priest.cpp | 66 |
7 files changed, 176 insertions, 78 deletions
diff --git a/src/common/mmaps_common/Management/MMapManager.cpp b/src/common/mmaps_common/Management/MMapManager.cpp index a45c1ee5fbb..32d77959d6e 100644 --- a/src/common/mmaps_common/Management/MMapManager.cpp +++ b/src/common/mmaps_common/Management/MMapManager.cpp @@ -29,8 +29,6 @@ namespace MMAP constexpr char MAP_FILE_NAME_FORMAT[] = "{}mmaps/{:04}.mmap"; constexpr char TILE_FILE_NAME_FORMAT[] = "{}mmaps/{:04}_{:02}_{:02}.mmtile"; - static thread_local bool thread_safe_environment = false; - using NavMeshQuerySet = std::unordered_map<std::pair<uint32, uint32>, dtNavMeshQuery>; using MMapTileSet = std::unordered_map<uint32, dtTileRef>; @@ -71,15 +69,18 @@ namespace MMAP std::pair<MeshDataMap::iterator, bool> GetMeshData(uint32 mapId, uint32 instanceId) { - // for maps that won't have dynamic mesh, return 0 to reuse the same mesh across all instances return meshData.try_emplace(GetInstanceIdForMeshLookup(mapId, instanceId)); } MeshDataMap::iterator FindMeshData(uint32 mapId, uint32 instanceId) { - // for maps that won't have dynamic mesh, return 0 to reuse the same mesh across all instances return meshData.find(GetInstanceIdForMeshLookup(mapId, instanceId)); } + + MeshDataMap::node_type RemoveMeshData(uint32 mapId, uint32 instanceId) + { + return meshData.extract(GetInstanceIdForMeshLookup(mapId, instanceId)); + } }; // ######################## MMapManager ######################## @@ -97,13 +98,10 @@ namespace MMAP // the caller must pass the list of all mapIds that will be used in the MMapManager lifetime for (auto const& [mapId, childMapIds] : mapData) { - loadedMMaps[mapId].reset(new MMapData()); + loadedMMaps.try_emplace(mapId, new MMapData()); for (uint32 childMapId : childMapIds) parentMapData[childMapId] = mapId; } - - // mark the loading main thread as safe - thread_safe_environment = true; } MMapDataSet::const_iterator MMapManager::GetMMapData(uint32 mapId) const @@ -124,20 +122,8 @@ namespace MMAP LoadResult MMapManager::loadMapData(std::string_view basePath, uint32 mapId, uint32 instanceId) { // we already have this map loaded? - MMapDataSet::iterator itr; - if (thread_safe_environment) - { - bool needsLoading; - std::tie(itr, needsLoading) = loadedMMaps.try_emplace(mapId); - if (needsLoading) - itr->second.reset(new MMapData()); - } - else - { - itr = loadedMMaps.find(mapId); - if (itr == loadedMMaps.end()) - ABORT_MSG("Invalid mapId %u passed to MMapManager after startup in thread unsafe environment", mapId); - } + MMapDataSet::iterator itr = loadedMMaps.find(mapId); + ASSERT(itr != loadedMMaps.end(), "Invalid mapId %u passed to MMapManager after startup in thread unsafe environment", mapId); auto [meshItr, needsLoading] = itr->second->GetMeshData(mapId, instanceId); if (!needsLoading) @@ -230,7 +216,7 @@ namespace MMAP } // get this mmap data - MMapData* mmap = loadedMMaps[mapId].get(); + MMapData* mmap = Trinity::Containers::MapGetValuePtr(loadedMMaps, mapId); MMapMapData& meshData = mmap->GetMeshData(mapId, instanceId).first->second; // check if we already have this tile loaded @@ -327,7 +313,7 @@ namespace MMAP return false; } - MMapData* mmap = loadedMMaps[meshMapId].get(); + MMapData* mmap = Trinity::Containers::MapGetValuePtr(loadedMMaps, meshMapId); auto [queryItr, inserted] = mmap->navMeshQueries.try_emplace({ instanceMapId, instanceId }); if (!inserted) return true; @@ -340,7 +326,6 @@ namespace MMAP // allocate mesh query if (dtStatusFailed(queryItr->second.init(&mmap->GetMeshData(meshMapId, instanceId).first->second.navMesh, 1024))) { - mmap->navMeshQueries.erase(queryItr); TC_LOG_ERROR("maps", "MMAP:GetNavMeshQuery: Failed to initialize dtNavMeshQuery for mapId {:04} instanceId {}", instanceMapId, instanceId); return false; } @@ -397,20 +382,21 @@ namespace MMAP return; } - if (MMapData::GetInstanceIdForMeshLookup(mapId, std::numeric_limits<uint32>::max()) == 0) + if (!isRebuildingTilesEnabledOnMap(mapId)) { - // unload all tiles from given map - MMapMapData& mesh = itr->second->meshData[0]; - for (auto const& [tileId, tileRef] : mesh.loadedTileRefs) + if (MeshDataMap::node_type meshNode = itr->second->RemoveMeshData(mapId, 0)) { - uint32 x = (tileId >> 16); - uint32 y = (tileId & 0x0000FFFF); - if (dtStatusFailed(mesh.navMesh.removeTile(tileRef, nullptr, nullptr))) - TC_LOG_ERROR("maps", "MMAP:unloadMap: Could not unload {:04}_{:02}_{:02}.mmtile from navmesh", mapId, x, y); - else + for (auto const& [tileId, tileRef] : meshNode.mapped().loadedTileRefs) { - --loadedTiles; - TC_LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded mmtile {:04}[{:02}, {:02}] from {:04}", mapId, x, y, mapId); + uint32 x = (tileId >> 16); + uint32 y = (tileId & 0x0000FFFF); + if (dtStatusFailed(meshNode.mapped().navMesh.removeTile(tileRef, nullptr, nullptr))) + TC_LOG_ERROR("maps", "MMAP:unloadMap: Could not unload {:04}_{:02}_{:02}.mmtile from navmesh", mapId, x, y); + else + { + --loadedTiles; + TC_LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded mmtile {:04}[{:02}, {:02}] from {:04}", mapId, x, y, mapId); + } } } } @@ -436,24 +422,24 @@ namespace MMAP if (!erased) TC_LOG_DEBUG("maps", "MMAP:unloadMapInstance: Asked to unload not loaded dtNavMeshQuery mapId {:04} instanceId {}", instanceMapId, instanceId); - MeshDataMap::iterator meshItr = mmap->FindMeshData(meshMapId, instanceId); - if (meshItr != mmap->meshData.end()) + if (isRebuildingTilesEnabledOnMap(meshMapId)) { - // unload all tiles from given map - for (auto const& [tileId, tileRef] : meshItr->second.loadedTileRefs) + if (MeshDataMap::node_type meshNode = mmap->RemoveMeshData(meshMapId, instanceId)) { - uint32 x = (tileId >> 16); - uint32 y = (tileId & 0x0000FFFF); - if (dtStatusFailed(meshItr->second.navMesh.removeTile(tileRef, nullptr, nullptr))) - TC_LOG_ERROR("maps", "MMAP:unloadMap: Could not unload {:04}_{:02}_{:02}.mmtile from navmesh", meshMapId, x, y); - else + // unload all tiles from given map + for (auto const& [tileId, tileRef] : meshNode.mapped().loadedTileRefs) { - --loadedTiles; - TC_LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded mmtile {:04}[{:02}, {:02}] from {:04}", meshMapId, x, y, meshMapId); + uint32 x = (tileId >> 16); + uint32 y = (tileId & 0x0000FFFF); + if (dtStatusFailed(meshNode.mapped().navMesh.removeTile(tileRef, nullptr, nullptr))) + TC_LOG_ERROR("maps", "MMAP:unloadMap: Could not unload {:04}_{:02}_{:02}.mmtile from navmesh", meshMapId, x, y); + else + { + --loadedTiles; + TC_LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded mmtile {:04}[{:02}, {:02}] from {:04}", meshMapId, x, y, meshMapId); + } } } - - mmap->meshData.erase(meshItr); } TC_LOG_DEBUG("maps", "MMAP:unloadMapInstance: Unloaded mapId {:04} instanceId {}", instanceMapId, instanceId); @@ -474,7 +460,7 @@ namespace MMAP dtNavMeshQuery const* MMapManager::GetNavMeshQuery(uint32 meshMapId, uint32 instanceMapId, uint32 instanceId) { - auto itr = GetMMapData(meshMapId); + MMapDataSet::const_iterator itr = GetMMapData(meshMapId); if (itr == loadedMMaps.end()) return nullptr; diff --git a/src/server/game/Entities/Object/Updates/UpdateFields.cpp b/src/server/game/Entities/Object/Updates/UpdateFields.cpp index 1f80091cb59..7627a6a82ae 100644 --- a/src/server/game/Entities/Object/Updates/UpdateFields.cpp +++ b/src/server/game/Entities/Object/Updates/UpdateFields.cpp @@ -7411,7 +7411,7 @@ void VisualAnim::ClearChangesMask() void ForceSetAreaTriggerPositionAndRotation::WriteCreate(ByteBuffer& data, AreaTrigger const* owner, Player const* receiver) const { data << TriggerGUID; - data << Position; + data << Pos; data << float(Rotation.x); data << float(Rotation.y); data << float(Rotation.z); @@ -7421,7 +7421,7 @@ void ForceSetAreaTriggerPositionAndRotation::WriteCreate(ByteBuffer& data, AreaT void ForceSetAreaTriggerPositionAndRotation::WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, AreaTrigger const* owner, Player const* receiver) const { data << TriggerGUID; - data << Position; + data << Pos; data << float(Rotation.x); data << float(Rotation.y); data << float(Rotation.z); @@ -7431,7 +7431,7 @@ void ForceSetAreaTriggerPositionAndRotation::WriteUpdate(ByteBuffer& data, bool bool ForceSetAreaTriggerPositionAndRotation::operator==(ForceSetAreaTriggerPositionAndRotation const& right) const { return TriggerGUID == right.TriggerGUID - && Position == right.Position + && Pos == right.Pos && Rotation == right.Rotation; } @@ -8614,6 +8614,7 @@ void DecorStoragePersistedData::WriteCreate(ByteBuffer& data, Object const* owne data << *HouseGUID; data << uint8(Field_20); data.WriteBits(Dyes.has_value(), 1); + data.FlushBits(); if (Dyes.has_value()) { Dyes->WriteCreate(data, owner, receiver); @@ -8626,26 +8627,24 @@ void DecorStoragePersistedData::WriteUpdate(ByteBuffer& data, bool ignoreChanges if (ignoreChangesMask) changesMask.SetAll(); - data.WriteBits(changesMask.GetBlock(0), 4); + data.WriteBits(changesMask.GetBlock(0), 3); data.FlushBits(); if (changesMask[0]) { - if (changesMask[1]) - { - data << *HouseGUID; - } - if (changesMask[3]) - { - data << uint8(Field_20); - } - data.WriteBits(Dyes.has_value(), 1); - if (changesMask[2]) + data << *HouseGUID; + } + if (changesMask[2]) + { + data << uint8(Field_20); + } + data.WriteBits(Dyes.has_value(), 1); + data.FlushBits(); + if (changesMask[1]) + { + if (Dyes.has_value()) { - if (Dyes.has_value()) - { - Dyes->WriteUpdate(data, ignoreChangesMask, owner, receiver); - } + Dyes->WriteUpdate(data, ignoreChangesMask, owner, receiver); } } } @@ -8663,8 +8662,9 @@ void HousingDecorData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> f data << *DecorGUID; data << *AttachParentGUID; data << uint8(Flags); - data << *Field_68; + data << *TargetGameObjectGUID; data.WriteBits(PersistedData.has_value(), 1); + data.FlushBits(); if (PersistedData.has_value()) { PersistedData->WriteCreate(data, owner, receiver); @@ -8697,9 +8697,10 @@ void HousingDecorData::WriteUpdate(ByteBuffer& data, Mask const& changesMask, bo } if (changesMask[5]) { - data << *Field_68; + data << *TargetGameObjectGUID; } data.WriteBits(PersistedData.has_value(), 1); + data.FlushBits(); if (changesMask[4]) { if (PersistedData.has_value()) @@ -8716,7 +8717,7 @@ void HousingDecorData::ClearChangesMask() Base::ClearChangesMask(AttachParentGUID); Base::ClearChangesMask(Flags); Base::ClearChangesMask(PersistedData); - Base::ClearChangesMask(Field_68); + Base::ClearChangesMask(TargetGameObjectGUID); _changesMask.ResetAll(); } diff --git a/src/server/game/Entities/Object/Updates/UpdateFields.h b/src/server/game/Entities/Object/Updates/UpdateFields.h index 1ccb5e0fdd7..582473c702c 100644 --- a/src/server/game/Entities/Object/Updates/UpdateFields.h +++ b/src/server/game/Entities/Object/Updates/UpdateFields.h @@ -1383,7 +1383,7 @@ struct VisualAnim : public IsUpdateFieldStructureTag, public HasChangesMask<5> struct ForceSetAreaTriggerPositionAndRotation : public IsUpdateFieldStructureTag { ObjectGuid TriggerGUID; - TaggedPosition<Position::XYZ> Position; + TaggedPosition<Position::XYZ> Pos; QuaternionData Rotation; void WriteCreate(ByteBuffer& data, AreaTrigger const* owner, Player const* receiver) const; @@ -1649,11 +1649,11 @@ struct DecorStoragePersistedDataDyes : public IsUpdateFieldStructureTag bool operator!=(DecorStoragePersistedDataDyes const& right) const { return !(*this == right); } }; -struct DecorStoragePersistedData : public IsUpdateFieldStructureTag, public HasChangesMask<4> +struct DecorStoragePersistedData : public IsUpdateFieldStructureTag, public HasChangesMask<3> { - UpdateField<ObjectGuid, 0, 1> HouseGUID; - OptionalUpdateField<UF::DecorStoragePersistedDataDyes, 0, 2> Dyes; - UpdateField<uint8, 0, 3> Field_20; + UpdateField<ObjectGuid, -1, 0> HouseGUID; + OptionalUpdateField<UF::DecorStoragePersistedDataDyes, -1, 1> Dyes; + UpdateField<uint8, -1, 2> Field_20; void WriteCreate(ByteBuffer& data, Object const* owner, Player const* receiver) const; void WriteUpdate(ByteBuffer& data, bool ignoreChangesMask, Object const* owner, Player const* receiver) const; @@ -1666,7 +1666,7 @@ struct HousingDecorData : public IsUpdateFieldStructureTag, public HasChangesMas UpdateField<ObjectGuid, 0, 2> AttachParentGUID; UpdateField<uint8, 0, 3> Flags; OptionalUpdateField<UF::DecorStoragePersistedData, 0, 4> PersistedData; - UpdateField<ObjectGuid, 0, 5> Field_68; + UpdateField<ObjectGuid, 0, 5> TargetGameObjectGUID; void WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, Object const* owner, Player const* receiver) const; void WriteUpdate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> fieldVisibilityFlags, Object const* owner, Player const* receiver) const; diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 86b4ab48672..49aa00c14e0 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -2256,6 +2256,8 @@ void AuraEffect::HandleAuraTransform(AuraApplication const* aurApp, uint8 mode, if (target->IsMounted()) target->RemoveAurasByType(SPELL_AURA_MOUNTED); } + + target->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags2::Transform); } else { diff --git a/src/server/game/Spells/SpellDefines.h b/src/server/game/Spells/SpellDefines.h index 120f2fa68c1..f5c849c3b32 100644 --- a/src/server/game/Spells/SpellDefines.h +++ b/src/server/game/Spells/SpellDefines.h @@ -122,7 +122,7 @@ enum class SpellAuraInterruptFlags2 : uint32 Swimming = 0x00000002, NotMoving = 0x00000004, // NYI Ground = 0x00000008, - Transform = 0x00000010, // NYI + Transform = 0x00000010, Jump = 0x00000020, ChangeSpec = 0x00000040, AbandonVehicle = 0x00000080, // Implemented in Unit::_ExitVehicle diff --git a/src/server/scripts/Spells/spell_paladin.cpp b/src/server/scripts/Spells/spell_paladin.cpp index 4ab419b1067..3bbf48b8d47 100644 --- a/src/server/scripts/Spells/spell_paladin.cpp +++ b/src/server/scripts/Spells/spell_paladin.cpp @@ -71,6 +71,7 @@ enum PaladinSpells SPELL_PALADIN_DIVINE_STORM_DAMAGE = 224239, SPELL_PALADIN_ENDURING_LIGHT = 40471, SPELL_PALADIN_ENDURING_JUDGEMENT = 40472, + SPELL_PALADIN_ETERNAL_FLAME = 156322, SPELL_PALADIN_EXECUTION_SENTENCE_DAMAGE = 387113, SPELL_PALADIN_EXECUTION_SENTENCE_11_SECONDS = 406919, SPELL_PALADIN_EXECUTION_SENTENCE_8_SECONDS = 386579, @@ -693,6 +694,47 @@ class spell_pal_divine_storm : public SpellScript } }; +// 156322 - Eternal Flame +class spell_pal_eternal_flame : public SpellScript +{ + bool Validate(SpellInfo const* spellInfo) override + { + return ValidateSpellEffect({ { spellInfo->Id, EFFECT_2 } }); + } + + void CalculateHealing(SpellEffectInfo const& /*effectInfo*/, Unit const* victim, int32& /*healing*/, int32& /*flatMod*/, float& pctMod) const + { + Unit* caster = GetCaster(); + if (victim == caster) + AddPct(pctMod, GetEffectInfo(EFFECT_2).CalcValue(caster)); + } + + void Register() override + { + CalcHealing += SpellCalcHealingFn(spell_pal_eternal_flame::CalculateHealing); + } +}; + +class spell_pal_eternal_flame_aura : public AuraScript +{ + bool Validate(SpellInfo const* spellInfo) override + { + return ValidateSpellEffect({ { spellInfo->Id, EFFECT_2 } }); + } + + void CalculateHealing(AuraEffect const* /*aurEff*/, Unit const* victim, int32& /*healing*/, int32& /*flatMod*/, float& pctMod) const + { + Unit* caster = GetCaster(); + if (victim == caster) + AddPct(pctMod, GetEffectInfo(EFFECT_2).CalcValue(caster)); + } + + void Register() override + { + DoEffectCalcDamageAndHealing += AuraEffectCalcHealingFn(spell_pal_eternal_flame_aura::CalculateHealing, EFFECT_0, SPELL_AURA_PERIODIC_HEAL); + } +}; + // 343527 - Execution Sentence class spell_pal_execution_sentence : public SpellScript { @@ -1806,6 +1848,7 @@ void AddSC_paladin_spell_scripts() RegisterSpellScript(spell_pal_divine_shield); RegisterSpellScript(spell_pal_divine_steed); RegisterSpellScript(spell_pal_divine_storm); + RegisterSpellAndAuraScriptPair(spell_pal_eternal_flame, spell_pal_eternal_flame_aura); RegisterSpellAndAuraScriptPair(spell_pal_execution_sentence, spell_pal_execution_sentence_aura); RegisterSpellScript(spell_pal_eye_for_an_eye); RegisterSpellScript(spell_pal_final_verdict); diff --git a/src/server/scripts/Spells/spell_priest.cpp b/src/server/scripts/Spells/spell_priest.cpp index 6100943eb12..1cb580810c5 100644 --- a/src/server/scripts/Spells/spell_priest.cpp +++ b/src/server/scripts/Spells/spell_priest.cpp @@ -38,6 +38,7 @@ #include "SpellScript.h" #include "TaskScheduler.h" #include "TemporarySummon.h" +#include "CommonPredicates.h" enum PriestSpells { @@ -70,6 +71,8 @@ enum PriestSpells SPELL_PRIEST_DARK_REPRIMAND_DAMAGE = 373130, SPELL_PRIEST_DARK_REPRIMAND_HEALING = 400187, SPELL_PRIEST_DAZZLING_LIGHT = 196810, + SPELL_PRIEST_DISPERSING_LIGHT = 1215265, + SPELL_PRIEST_DISPERSING_LIGHT_HEAL = 1215266, SPELL_PRIEST_DIVINE_AEGIS = 47515, SPELL_PRIEST_DIVINE_AEGIS_ABSORB = 47753, SPELL_PRIEST_DIVINE_BLESSING = 40440, @@ -796,6 +799,67 @@ class spell_pri_dark_indulgence : public SpellScript } }; +// 1215265 - Dispersing Light +class spell_pri_dispersing_light : public AuraScript +{ + bool Validate(SpellInfo const* spellInfo) override + { + return ValidateSpellInfo({ SPELL_PRIEST_DISPERSING_LIGHT_HEAL }) + && ValidateSpellEffect({ { spellInfo->Id, EFFECT_1 } }); + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo const& eventInfo) const + { + HealInfo* healInfo = eventInfo.GetHealInfo(); + if (!healInfo || !healInfo->GetHeal()) + return; + + Unit* caster = eventInfo.GetActor(); + Unit* target = eventInfo.GetActionTarget(); + + caster->CastSpell(nullptr, SPELL_PRIEST_DISPERSING_LIGHT_HEAL, CastSpellExtraArgsInit + { + .TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR, + .TriggeringAura = aurEff, + .SpellValueOverrides = + { + { SPELLVALUE_BASE_POINT0, int32(CalculatePct(healInfo->GetHeal(), aurEff->GetAmount())) }, + { SPELLVALUE_MAX_TARGETS, GetEffectInfo(EFFECT_1).CalcValue(caster) } + }, + .CustomArg = TriggerArgs{ .TargetToExclude = target->GetGUID() } + }); + } + + void Register() override + { + OnEffectProc += AuraEffectProcFn(spell_pri_dispersing_light::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } + +public: + struct TriggerArgs + { + ObjectGuid TargetToExclude; + }; +}; + +// 1215266 - Dispersing Light (Heal) +class spell_pri_dispersing_light_heal : public SpellScript +{ + void FilterTargets(std::list<WorldObject*>& targets) const + { + spell_pri_dispersing_light::TriggerArgs const* args = std::any_cast<spell_pri_dispersing_light::TriggerArgs>(&GetSpell()->m_customArg); + if (!args || args->TargetToExclude.IsEmpty()) + return; + + targets.remove_if(Trinity::ObjectGUIDCheck(args->TargetToExclude)); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_pri_dispersing_light_heal::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ALLY); + } +}; + namespace DivineImageHelpers { Unit* GetSummon(Unit const* owner) @@ -3681,6 +3745,8 @@ void AddSC_priest_spell_scripts() RegisterSpellScript(spell_pri_circle_of_healing); RegisterSpellScript(spell_pri_crystalline_reflection); RegisterSpellScript(spell_pri_dark_indulgence); + RegisterSpellScript(spell_pri_dispersing_light); + RegisterSpellScript(spell_pri_dispersing_light_heal); RegisterSpellScript(spell_pri_divine_aegis); RegisterSpellScript(spell_pri_divine_image); RegisterSpellScript(spell_pri_divine_image_spell_triggered); |
