From dc5e6673ee5c892e8ca4ab2981e7de57ce92bc53 Mon Sep 17 00:00:00 2001 From: Ovah Date: Tue, 12 Dec 2017 14:47:39 +0000 Subject: [PATCH] Scripts/LCT: implement High Prophet Barim encounter --- .../world/4.3.4/2017_12_12_01_world.sql | 106 +++ src/server/game/Entities/Unit/Unit.cpp | 3 +- src/server/game/Spells/SpellMgr.cpp | 19 + .../boss_high_prophet_barim.cpp | 798 ++++++++++++++++++ .../instance_lost_city_of_the_tolvir.cpp | 14 +- .../lost_city_of_the_tolvir.h | 36 +- .../Kalimdor/kalimdor_script_loader.cpp | 2 + 7 files changed, 955 insertions(+), 23 deletions(-) create mode 100644 sql/updates/world/4.3.4/2017_12_12_01_world.sql create mode 100644 src/server/scripts/Kalimdor/LostCityOfTheTolvir/boss_high_prophet_barim.cpp diff --git a/sql/updates/world/4.3.4/2017_12_12_01_world.sql b/sql/updates/world/4.3.4/2017_12_12_01_world.sql new file mode 100644 index 0000000000..5501a6707e --- /dev/null +++ b/sql/updates/world/4.3.4/2017_12_12_01_world.sql @@ -0,0 +1,106 @@ +-- High Prophet Barim +UPDATE `creature_template` SET `difficulty_entry_1`= 48951, `mechanic_immune_mask`= 667893759, `lootid`= 43612, `mingold`= 19800, `maxgold`= 19900, `scriptname`= 'boss_high_prophet_barim' WHERE `entry`= 43612; +UPDATE `creature_template` SET `minlevel`= 87, `maxlevel`= 87, `faction`= 16, `exp`= 3, `mechanic_immune_mask`= 667893759, `lootid`= 48951, `mingold`= 19800, `maxgold`= 19900, `movementId`= 138 WHERE `entry`= 48951; +UPDATE `creature` SET `PhaseID`= 0, `PhaseGroup`= 391 WHERE `guid`= 306829; +-- Heavens Fury +UPDATE `creature_template` SET `minlevel`= 85, `maxlevel`= 85, `faction`= 16, `unit_flags`= 33554432, `flags_extra`= 128 WHERE `entry`= 43801; +-- Wail of Twilight +UPDATE `creature_template` SET `minlevel`= 85, `maxlevel`= 85, `faction`= 16, `unit_flags`= 33554432, `flags_extra`= 128 WHERE `entry`= 43926; +-- Repentance +UPDATE `creature_template` SET `minlevel`= 85, `maxlevel`= 85, `faction`= 14, `unit_flags`= 33554432, `flags_extra`= 2, `scriptname`= 'npc_barim_repentance' WHERE `entry`= 43817; +-- Harbinger of Darkness +UPDATE `creature_template` SET `difficulty_entry_1`= 48953, `minlevel`= 86, `maxlevel`= 86, `faction`= 16, `mechanic_immune_mask`= 667893759, `scriptname`= 'npc_barim_harbinger_of_darkness' WHERE `entry`= 43927; +UPDATE `creature_template` SET `minlevel`= 87, `maxlevel`= 87, `faction`= 16, `exp`= 3, `mechanic_immune_mask`= 667893759 WHERE `entry`= 48953; +-- Blaze of the Heavens Dummy +UPDATE `creature_template` SET `minlevel`= 85, `maxlevel`= 85, `faction`= 16, `unit_flags`= 33554432, `flags_extra`= 128 WHERE `entry`= 48904; +-- Blaze of the Heavens +UPDATE `creature_template` SET `minlevel`= 87, `maxlevel`= 87, `faction`= 16, `mechanic_immune_mask`= 667893759, `scriptname`= 'npc_barim_blaze_of_the_heavens' WHERE `entry`= 48906; +-- Blaze of the Heavens Fire Dummy +UPDATE `creature_template` SET `minlevel`= 85, `maxlevel`= 85, `faction`= 16, `unit_flags`= 33554496, `flags_extra`= 128 WHERE `entry`= 48907; +-- Soul Fragment +UPDATE `creature_template` SET `mechanic_immune_mask`= 667893759, `difficulty_entry_1`= 48954, `faction`= 16, `exp`= 3, `minlevel`= 84, `maxlevel`= 84, `scriptname`= 'npc_barim_soul_fragment' WHERE `entry`= 43934; +UPDATE `creature_template` SET `mechanic_immune_mask`= 667893759, `faction`= 16, `exp`= 3, `minlevel`= 85, `maxlevel`= 85 WHERE `entry`= 48954; +-- Burning Soul +UPDATE `creature_template` SET `difficulty_entry_1`= 49220, `minlevel`= 84, `maxlevel`= 84, `unit_flags`= 33554432, `faction`= 16, `flags_extra`= 128 WHERE `entry`= 49219; +UPDATE `creature_template` SET `minlevel`= 85, `maxlevel`= 85, `unit_flags`= 33554432, `faction`= 16, `flags_extra`= 131 WHERE `entry`= 49220; + +-- Creature Text +DELETE FROM `creature_text` WHERE `CreatureID` IN (43612, 43934); +INSERT INTO `creature_text` (`CreatureID`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `BroadcastTextId`, `comment`) VALUES +(43612, 0, 0, 'Begone infidels, you are not welcome here!', 14, 0, 100, 0, 0, 19735, 44791, 'High Prophet Barim'), +(43612, 1, 0, 'May peace find you now.', 14, 0, 100, 0, 0, 19738, 44793, 'High Prophet Barim'), +(43612, 1, 1, 'The heavens take you!', 14, 0, 100, 0, 0, 19736, 44794, 'High Prophet Barim'), +(43612, 2, 0, 'Kneel before me and repent!', 14, 0, 100, 0, 0, 19737, 44795, 'High Prophet Barim'), +(43612, 3, 0, 'Death is only the beginning!', 14, 0, 100, 0, 0, 19733, 44792, 'High Prophet Barim'), +(43934, 0, 0, 'A soul fragment merges souls with the Harbinger of Darkness!', 41, 0, 100, 0, 0, 0, 52151, 'Soul Fragment'); + +-- Spell Script Names +DELETE FROM `spell_script_names` WHERE `ScriptName` IN +('spell_barim_plague_of_ages_first', + 'spell_barim_plague_of_ages_second', + 'spell_barim_repentance_script', + 'spell_barim_repentance_pull'); + +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(82637, 'spell_barim_plague_of_ages_first'), +(89996, 'spell_barim_plague_of_ages_first'), +(82640, 'spell_barim_plague_of_ages_second'), +(89995, 'spell_barim_plague_of_ages_second'), +(82009, 'spell_barim_repentance_script'), +(81960, 'spell_barim_repentance_script'), +(82220, 'spell_barim_repentance_script'), +(82168, 'spell_barim_repentance_pull'); + +-- Template Addons +DELETE FROM `creature_template_addon` WHERE `entry` IN (43801, 43926, 48907); +INSERT INTO `creature_template_addon` (`entry`, `Auras`) VALUES +(43801, '81940 81941'), +(48907, '91195'); + +-- Creature Veil of Twilight 43926 SAI +SET @ENTRY := 43926; +UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`= @ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(@ENTRY, 0, 0, 0, 60, 0, 100, 1, 1000, 1000, 0, 0, 11, 82197, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Every 0 and 0 ms (for the first time, timer between 1000 and 1000 ms) - Self: Cast spell 82197 on Self // "), +(@ENTRY, 0, 1, 2, 60, 0, 100, 1, 2000, 2000, 0, 0, 41, 4000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Every 0 and 0 ms (for the first time, timer between 2000 and 2000 ms) - Self: Despawn in 4000 ms // "), +(@ENTRY, 0, 2, 0, 61, 0, 100, 0, 0, 0, 0, 0, 11, 82203, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, " Linked - Self: Cast spell 82203 on Self // "); + +-- Creature Blaze of the Heavens 48904 SAI +SET @ENTRY := 48904; +UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`= @ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(@ENTRY, 0, 0, 0, 60, 0, 100, 1, 1000, 1000, 0, 0, 11, 91179, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Every 0 and 0 ms (for the first time, timer between 1000 and 1000 ms) - Self: Cast spell 91179 on Self // "), +(@ENTRY, 0, 1, 2, 60, 0, 100, 1, 2000, 2000, 0, 0, 41, 4000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Every 0 and 0 ms (for the first time, timer between 2000 and 2000 ms) - Self: Despawn in 4000 ms // "), +(@ENTRY, 0, 2, 0, 61, 0, 100, 0, 0, 0, 0, 0, 11, 91180, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, " Linked - Self: Cast spell 91180 on Self // "); + +-- Conditions +DELETE FROM `conditions` WHERE `SourceEntry` IN (91196, 91277, 82224, 82263) AND `SourceTypeOrReferenceId`= 13; +INSERT INTO conditions (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ScriptName`, `Comment`) VALUES +(13, 2, 91196, 0, 0, 31, 0, 3, 48907, 0, 0, 0, '', 'Blaze of the Heavens - Target Blaze of the Heavens'), +(13, 2, 91196, 0, 0, 31, 0, 3, 48906, 0, 0, 0, '', 'Blaze of the Heavens - Target Blaze of the Heavens'), +(13, 1, 91277, 0, 0, 31, 0, 3, 43934, 0, 0, 0, '', 'Burning Soul - Target Soul Fragment'), +(13, 1, 82224, 0, 0, 31, 0, 3, 43927, 0, 0, 0, '', 'Soul Fragment - Target Harbinger of Darkness'), +(13, 7, 82263, 0, 0, 31, 0, 3, 43927, 0, 0, 0, '', 'Soul Fragment - Target Harbinger of Darkness'); + +-- Loot +DELETE FROM `creature_loot_template` WHERE `Entry` IN (43612, 48951); +INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `LootMode`, `MinCount`, `MaxCount`) VALUES +(43612, 436120, 436120, 100, 1, 1, 1), +(48951, 489510, 489510, 100, 1, 1, 1); + +DELETE FROM `reference_loot_template` WHERE `Entry` IN (436120, 489510); +INSERT INTO `reference_loot_template` (`Entry`, `Item`, `Chance`, `LootMode`, `MinCount`, `MaxCount`, `GroupId`) VALUES +-- Normal Mode +(436120, 55865, 0, 1, 1, 1, 1), +(436120, 55864, 0, 1, 1, 1, 1), +(436120, 55861, 0, 1, 1, 1, 1), +(436120, 55862, 0, 1, 1, 1, 1), +(436120, 55863, 0, 1, 1, 1, 1), +-- Heroic Mode +(489510, 56384, 0, 1, 1, 1, 1), +(489510, 56385, 0, 1, 1, 1, 1), +(489510, 56386, 0, 1, 1, 1, 1), +(489510, 56387, 0, 1, 1, 1, 1), +(489510, 56388, 0, 1, 1, 1, 1); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index ac376d84d9..bb349c8494 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -11758,7 +11758,6 @@ void Unit::SetStunned(bool apply) if (GetTypeId() == TYPEID_PLAYER) SetStandState(UNIT_STAND_STATE_STAND); - SetRooted(true); CastStop(); @@ -11789,7 +11788,7 @@ void Unit::SetRooted(bool apply, bool packetOnly /*= false*/) // setting MOVEMENTFLAG_ROOT RemoveUnitMovementFlag(MOVEMENTFLAG_MASK_MOVING); AddUnitMovementFlag(MOVEMENTFLAG_ROOT); - StopMoving(); + StopMoving(); } else RemoveUnitMovementFlag(MOVEMENTFLAG_ROOT); diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index d9f761772e..a30fa43d8b 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -3639,6 +3639,25 @@ void SpellMgr::LoadSpellInfoCorrections() spellInfo->Effects[EFFECT_0].Effect = SPELL_EFFECT_APPLY_AURA; spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_UNIT_TARGET_ANY); break; + // High Prophet Barim + case 81942: // Heaven's Fury + case 90040: + spellInfo->Effects[EFFECT_1].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_4_YARDS); + break; + case 88814: // Hallowed Ground + case 90010: + spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_13_YARDS); + spellInfo->Effects[EFFECT_1].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_13_YARDS); + break; + case 91196: // Blaze of the Heavens + spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_3_YARDS); + break; + case 82430: // Repentance + spellInfo->Effects[EFFECT_0].MiscValue = 150; + break; + case 95249: // Blaze of the Heavens + spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_3_YARDS); + break; // Halls Of Origination spells // Temple Guardian Anhuur case 76606: // Disable Beacon Beams L diff --git a/src/server/scripts/Kalimdor/LostCityOfTheTolvir/boss_high_prophet_barim.cpp b/src/server/scripts/Kalimdor/LostCityOfTheTolvir/boss_high_prophet_barim.cpp new file mode 100644 index 0000000000..75ea1aebe4 --- /dev/null +++ b/src/server/scripts/Kalimdor/LostCityOfTheTolvir/boss_high_prophet_barim.cpp @@ -0,0 +1,798 @@ +/* +* Copyright (C) 2008-2017 TrinityCore +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along +* with this program. If not, see . +*/ + +#include "ScriptMgr.h" +#include "lost_city_of_the_tolvir.h" +#include "ObjectMgr.h" +#include "Player.h" +#include "ScriptedCreature.h" +#include "SpellAuraEffects.h" +#include "SpellScript.h" + +enum Spells +{ + // High Prophet Barim + SPELL_FIFTY_LASHINGS = 82506, + SPELL_PLAGUE_OF_AGES = 82622, + SPELL_HEAVENS_FURY = 81939, + SPELL_REPANTANCE = 82320, + SPELL_REPENTANCE_PULL = 82168, + SPELL_REPENTANCE_STUN = 81947, + SPELL_REPENTANCE_KNOCKBACK = 82012, + SPELL_REPENTANCE_SCREEN_EFFECT = 82139, + SPELL_WAIL_OF_DARKNESS_DUMMY = 82195, + SPELL_BLAZE_OF_THE_HEAVENS = 91181, + + // Repentance + SPELL_REPENTANCE_SCRIPT_1 = 82009, + SPELL_REPENTANCE_SCRIPT_2 = 81960, + SPELL_REPENTANCE_PULL_BACK = 82430, + + // Harbinger of Darkness + SPELL_BIRTH = 26586, + SPELL_WAIL_OF_DARKNESS = 82533, + SPELL_SOUL_SEVER = 82255, + SPELL_WAIL_OF_DARKNESS_END = 82425, + + // Blaze of the Heavens + SPELL_BLAZE_OF_THE_HEAVENS_TRIGGER = 95248, + SPELL_BLAZE_OF_THE_HEAVENS_FLAME = 91189, + SPELL_TRANSFORM = 95276, + + // Soul Fragment + SPELL_SOUL_SEVER_SCRIPT = 82220, + SPELL_SOUL_FRAGMENT_DUMMY = 82224, + SPELL_MERGED_SOULS = 82263, +}; + +enum Events +{ + // High Prophet Barim + EVENT_FIFTY_LASHINGS = 1, + EVENT_PLAGUE_OF_AGES, + EVENT_HEAVENS_FURY, + EVENT_REPENTANCE_PULL, + EVENT_REPENTANCE_STUN, + EVENT_REPENTANCE_KNOCKBACK, + EVENT_BLAZE_OF_THE_HEAVENS, + EVENT_COUNT_PLAYERS, + + // Repentance + EVENT_COPY_WEAPON, + + // Harbinger of Darkness + EVENT_MAKE_AGGRESSIVE, + EVENT_WAIL_OF_DARKNESS, + EVENT_SOUL_SEVER, + + // Blaze of the Heavens + EVENT_TRIGGER_BLAZE, + EVENT_SUMMON_BLAZE_FLAME, + EVENT_CHECK_HEALTH, + EVENT_TRANSFORMED, + + // Soul Fragment + EVENT_MOVE_TO_HARBINGER, + EVENT_CHECK_DISTANCE +}; + +enum Actions +{ + ACTION_PULL_BACK = 1, + ACTION_MAKE_PASSIVE, + ACTION_ATTACK_PLAYERS, + ACTION_BLAZE_DIED +}; + +enum Texts +{ + // High Prophet Barim + SAY_AGGRO = 0, + SAY_SLAY = 1, + SAY_REPENTEANCE = 2, + SAY_DEATH = 3, + + // Soul Fragment + SAY_ANNOUNCE_MERGE_SOUL = 0 +}; + +enum PhaseMisc +{ + PHASE_ID_REPENTANCE = 173, + PHASE_GROUP_ENCOUNTER_1 = 391 +}; + +class boss_high_prophet_barim : public CreatureScript +{ +public: + boss_high_prophet_barim() : CreatureScript("boss_high_prophet_barim") { } + + struct boss_high_prophet_barimAI : public BossAI + { + boss_high_prophet_barimAI(Creature* creature) : BossAI(creature, DATA_HIGH_PROPHET_BARIM) { } + + void Reset() override + { + _Reset(); + _repentanceStarted = false; + } + + void EnterCombat(Unit* /*who*/) override + { + _EnterCombat(); + Talk(SAY_AGGRO); + instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me); + events.ScheduleEvent(EVENT_FIFTY_LASHINGS, Seconds(9)); + events.ScheduleEvent(EVENT_PLAGUE_OF_AGES, Seconds(7) + Milliseconds(500)); + events.ScheduleEvent(EVENT_HEAVENS_FURY, Seconds(7) + Milliseconds(500)); + if (IsHeroic()) + events.ScheduleEvent(EVENT_BLAZE_OF_THE_HEAVENS, Seconds(10)); + } + + void JustDied(Unit* /*killer*/) override + { + _JustDied(); + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + if (Creature* blaze = instance->GetCreature(DATA_BLAZE_OF_THE_HEAVENS)) + { + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, blaze); + blaze->DespawnOrUnsummon(Milliseconds(100)); + } + Talk(SAY_DEATH); + } + + void EnterEvadeMode(EvadeReason /*why*/) override + { + _EnterEvadeMode(); + summons.DespawnAll(); + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_SOUL_SEVER); + if (Creature* blaze = instance->GetCreature(DATA_BLAZE_OF_THE_HEAVENS)) + { + blaze->AI()->EnterEvadeMode(); + blaze->DespawnOrUnsummon(Milliseconds(700)); + } + _DespawnAtEvade(); + } + + void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/) override + { + if (me->HealthBelowPct(50) && !_repentanceStarted) + { + events.Reset(); + me->AttackStop(); + me->SetReactState(REACT_PASSIVE); + me->StopMoving(); + DoCastSelf(SPELL_REPANTANCE); + events.ScheduleEvent(EVENT_REPENTANCE_PULL, Seconds(1)); + _repentanceStarted = true; + } + } + + void DoAction(int32 action) override + { + switch (action) + { + case ACTION_PULL_BACK: + { + std::list units; + GetCreatureListWithEntryInGrid(units, me, NPC_REPENTANCE, 30.0f); + for (std::list::iterator itr = units.begin(); itr != units.end(); ++itr) + (*itr)->AI()->DoAction(ACTION_PULL_BACK); + + me->RemoveAurasDueToSpell(SPELL_REPANTANCE); + me->SetReactState(REACT_AGGRESSIVE); + + summons.DespawnEntry(NPC_SOUL_FRAGMENT); + instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_SOUL_SEVER); + if (Creature* blaze = instance->GetCreature(DATA_BLAZE_OF_THE_HEAVENS)) + blaze->AI()->DoAction(ACTION_ATTACK_PLAYERS); + break; + } + case ACTION_BLAZE_DIED: + events.ScheduleEvent(EVENT_BLAZE_OF_THE_HEAVENS, Seconds(3)); + break; + default: + break; + } + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_FIFTY_LASHINGS: + DoCastSelf(SPELL_FIFTY_LASHINGS); + events.Repeat(Seconds(40)); + break; + case EVENT_PLAGUE_OF_AGES: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0, true)) + DoCast(target, SPELL_PLAGUE_OF_AGES); + events.Repeat(Seconds(25)); + break; + case EVENT_HEAVENS_FURY: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0, true)) + DoCast(target, SPELL_HEAVENS_FURY); + events.Repeat(Seconds(22)); + break; + case EVENT_REPENTANCE_PULL: + Talk(SAY_REPENTEANCE); + DoCastSelf(SPELL_REPENTANCE_PULL); + events.ScheduleEvent(EVENT_REPENTANCE_STUN, Seconds(1) + Milliseconds(300)); + + if (Creature* blaze = instance->GetCreature(DATA_BLAZE_OF_THE_HEAVENS)) + blaze->AI()->DoAction(ACTION_MAKE_PASSIVE); + break; + case EVENT_REPENTANCE_STUN: + DoCastAOE(SPELL_REPENTANCE_STUN, true); + events.ScheduleEvent(EVENT_REPENTANCE_KNOCKBACK, Seconds(6)); + break; + case EVENT_REPENTANCE_KNOCKBACK: + DoCastAOE(SPELL_REPENTANCE_KNOCKBACK); + DoCastAOE(SPELL_REPENTANCE_SCREEN_EFFECT, true); + DoCastSelf(SPELL_WAIL_OF_DARKNESS_DUMMY, true); + break; + case EVENT_BLAZE_OF_THE_HEAVENS: + DoCastSelf(SPELL_BLAZE_OF_THE_HEAVENS, true); + break; + default: + break; + } + } + DoMeleeAttackIfReady(); + } + private: + bool _repentanceStarted; + }; + + CreatureAI* GetAI(Creature *creature) const override + { + return GetLostCityOfTheTolvirAI(creature); + } +}; + +class npc_barim_repentance : public CreatureScript +{ +public: + npc_barim_repentance() : CreatureScript("npc_barim_repentance") { } + + struct npc_barim_repentanceAI : public PassiveAI + { + npc_barim_repentanceAI(Creature* creature) : PassiveAI(creature), _instance(creature->GetInstanceScript()) { } + + void IsSummonedBy(Unit* summoner) override + { + if (Creature* barim = _instance->GetCreature(DATA_HIGH_PROPHET_BARIM)) + barim->AI()->JustSummoned(me); + + for (uint32 id : GetPhasesForGroup(PHASE_GROUP_ENCOUNTER_1)) + me->SetInPhase(id, false, true); + + DoCastSelf(SPELL_REPENTANCE_SCRIPT_1, true); + _events.ScheduleEvent(EVENT_COPY_WEAPON, Seconds(2)); + + if (Aura* aura = summoner->GetAura(SPELL_REPENTANCE_STUN)) + if (AuraEffect* aurEff = aura->GetEffect(EFFECT_1)) + aurEff->SetPeriodic(false); + } + + void DoAction(int32 action) override + { + if (action == ACTION_PULL_BACK) + { + DoCastAOE(SPELL_REPENTANCE_PULL_BACK, true); + me->DespawnOrUnsummon(Seconds(1) + Milliseconds(500)); + } + } + + void UpdateAI(uint32 diff) override + { + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_COPY_WEAPON: + DoCastSelf(SPELL_REPENTANCE_SCRIPT_2, true); + break; + default: + break; + } + } + } + + private: + EventMap _events; + InstanceScript* _instance; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetLostCityOfTheTolvirAI(creature); + } +}; + +class npc_barim_harbinger_of_darkness : public CreatureScript +{ +public: + npc_barim_harbinger_of_darkness() : CreatureScript("npc_barim_harbinger_of_darkness") { } + + struct npc_barim_harbinger_of_darknessAI : public ScriptedAI + { + npc_barim_harbinger_of_darknessAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } + + void IsSummonedBy(Unit* /*summoner*/) override + { + me->SetReactState(REACT_PASSIVE); + DoZoneInCombat(); + DoCastSelf(SPELL_BIRTH, true); + _events.ScheduleEvent(EVENT_WAIL_OF_DARKNESS, Seconds(6)); + _events.ScheduleEvent(EVENT_SOUL_SEVER, Seconds(11)); + } + + void EnterCombat(Unit* /*who*/) override + { + _instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me); + _events.ScheduleEvent(EVENT_MAKE_AGGRESSIVE, Seconds(1) + Milliseconds(500)); + } + + void JustDied(Unit* /*killer*/) override + { + _instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + DoCastAOE(SPELL_WAIL_OF_DARKNESS_END, true); + me->DespawnOrUnsummon(Milliseconds(700)); + + if (Creature* barim = _instance->GetCreature(DATA_HIGH_PROPHET_BARIM)) + barim->AI()->DoAction(ACTION_PULL_BACK); + } + + void EnterEvadeMode(EvadeReason /*why*/) override + { + _instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + me->DespawnOrUnsummon(Milliseconds(700)); + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + _events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_MAKE_AGGRESSIVE: + me->SetReactState(REACT_AGGRESSIVE); + if (Player* victim = me->SelectNearestPlayer(100.0f)) + me->AI()->AttackStart(victim); + break; + case EVENT_WAIL_OF_DARKNESS: + DoCastAOE(SPELL_WAIL_OF_DARKNESS); + _events.Repeat(Seconds(2) + Milliseconds(500)); + break; + case EVENT_SOUL_SEVER: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0, true, 0)) + DoCast(target, SPELL_SOUL_SEVER); + _events.Repeat(Seconds(11)); + break; + default: + break; + } + } + DoMeleeAttackIfReady(); + } + + private: + EventMap _events; + InstanceScript* _instance; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetLostCityOfTheTolvirAI(creature); + } +}; + +class npc_barim_blaze_of_the_heavens : public CreatureScript +{ +public: + npc_barim_blaze_of_the_heavens() : CreatureScript("npc_barim_blaze_of_the_heavens") { } + + struct npc_barim_blaze_of_the_heavensAI : public ScriptedAI + { + npc_barim_blaze_of_the_heavensAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } + + void IsSummonedBy(Unit* /*summoner*/) override + { + _isInEgg = false; + _isTransforming = false; + me->SetReactState(REACT_PASSIVE); + DoZoneInCombat(); + DoCastSelf(SPELL_BIRTH, true); + me->SetInPhase(PHASE_ID_REPENTANCE, true, false); + } + + void EnterCombat(Unit* /*who*/) override + { + _instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me); + _events.ScheduleEvent(EVENT_MAKE_AGGRESSIVE, Seconds(1) + Milliseconds(500)); + _events.ScheduleEvent(EVENT_TRIGGER_BLAZE, Seconds(3)); + _events.ScheduleEvent(EVENT_SUMMON_BLAZE_FLAME, Seconds(4)); + } + + void JustSummoned(Creature* summon) override + { + if (Creature* barim = _instance->GetCreature(DATA_HIGH_PROPHET_BARIM)) + barim->AI()->JustSummoned(summon); + + for (uint32 id : GetPhasesForGroup(PHASE_GROUP_ENCOUNTER_1)) + summon->SetInPhase(id, false, true); + } + + void JustDied(Unit* /*killer*/) override + { + _instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + me->DespawnOrUnsummon(Seconds(4)); + if (Creature* barim = _instance->GetCreature(DATA_HIGH_PROPHET_BARIM)) + barim->AI()->DoAction(ACTION_BLAZE_DIED); + } + + void EnterEvadeMode(EvadeReason /*why*/) override + { + _instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + } + + void DoAction(int32 action) override + { + switch (action) + { + case ACTION_ATTACK_PLAYERS: + if (Player* victim = me->SelectNearestPlayer(100.0f)) + { + _instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me); + if (!_isInEgg) + { + me->SetReactState(REACT_AGGRESSIVE); + me->AI()->AttackStart(victim); + _events.ScheduleEvent(EVENT_MAKE_AGGRESSIVE, Seconds(1) + Milliseconds(500)); + _events.ScheduleEvent(EVENT_TRIGGER_BLAZE, Seconds(3)); + _events.ScheduleEvent(EVENT_SUMMON_BLAZE_FLAME, Seconds(4)); + } + else + _events.ScheduleEvent(EVENT_CHECK_HEALTH, Seconds(1)); + } + break; + case ACTION_MAKE_PASSIVE: + _events.Reset(); + me->AttackStop(); + me->SetReactState(REACT_PASSIVE); + break; + default: + break; + } + } + + void DamageTaken(Unit* /*attacker*/, uint32& damage) override + { + if (me->HealthBelowPct(1) && !_isTransforming) + { + _events.Reset(); + _isTransforming = true; + _events.ScheduleEvent(EVENT_TRANSFORMED, Seconds(2) + Milliseconds(300)); + me->RemoveAllAuras(); + DoCastSelf(SPELL_TRANSFORM); + } + + if (damage >= me->GetHealth() && !_isInEgg) + damage = me->GetHealth() - 1; + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + _events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_MAKE_AGGRESSIVE: + me->SetReactState(REACT_AGGRESSIVE); + if (Player* victim = me->SelectNearestPlayer(100.0f)) + me->AI()->AttackStart(victim); + break; + case EVENT_TRIGGER_BLAZE: + DoCastSelf(SPELL_BLAZE_OF_THE_HEAVENS_TRIGGER, true); + break; + case EVENT_SUMMON_BLAZE_FLAME: + DoCastSelf(SPELL_BLAZE_OF_THE_HEAVENS_FLAME, true); + _events.Repeat(Seconds(1)); + break; + case EVENT_TRANSFORMED: + _isInEgg = true; + _events.ScheduleEvent(EVENT_CHECK_HEALTH, Seconds(1)); + break; + case EVENT_CHECK_HEALTH: + if (me->GetHealthPct() == 100.0f) + { + me->RemoveAurasDueToSpell(SPELL_TRANSFORM); + DoCastSelf(SPELL_BIRTH, true); + DoZoneInCombat(); + _events.ScheduleEvent(EVENT_MAKE_AGGRESSIVE, Seconds(1) + Milliseconds(500)); + _events.ScheduleEvent(EVENT_TRIGGER_BLAZE, Seconds(3)); + _events.ScheduleEvent(EVENT_SUMMON_BLAZE_FLAME, Seconds(4)); + _isInEgg = false; + _isTransforming = false; + } + else + _events.Repeat(Seconds(1)); + break; + default: + break; + } + } + DoMeleeAttackIfReady(); + } + + private: + EventMap _events; + InstanceScript* _instance; + bool _isInEgg; + bool _isTransforming; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetLostCityOfTheTolvirAI(creature); + } +}; + +class npc_barim_soul_fragment : public CreatureScript +{ +public: + npc_barim_soul_fragment() : CreatureScript("npc_barim_soul_fragment") { } + + struct npc_barim_soul_fragmentAI : public PassiveAI + { + npc_barim_soul_fragmentAI(Creature* creature) : PassiveAI(creature), _instance(creature->GetInstanceScript()) { } + + void IsSummonedBy(Unit* /*summoner*/) override + { + me->SetWalk(true); + DoCastSelf(SPELL_SOUL_SEVER_SCRIPT, true); + DoCastSelf(SPELL_REPENTANCE_SCRIPT_2, true); + DoCastAOE(SPELL_SOUL_FRAGMENT_DUMMY, true); + + if (Creature* barim = _instance->GetCreature(DATA_HIGH_PROPHET_BARIM)) + barim->AI()->JustSummoned(me); + + _events.ScheduleEvent(EVENT_MOVE_TO_HARBINGER, Seconds(5)); + } + + void JustDied(Unit* /*killer*/) override + { + me->DespawnOrUnsummon(Seconds(1)); + } + + void UpdateAI(uint32 diff) override + { + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_MOVE_TO_HARBINGER: + if (Creature* harbinger = _instance->GetCreature(DATA_HARBINGER_OF_DARKNESS)) + { + me->GetMotionMaster()->MovePoint(0, harbinger->GetPosition(), true); + _events.ScheduleEvent(EVENT_CHECK_DISTANCE, Milliseconds(500)); + } + break; + case EVENT_CHECK_DISTANCE: + if (Creature* harbinger = me->FindNearestCreature(NPC_HARBINGER_OF_DARKNESS, 0.3f, true)) + { + Talk(SAY_ANNOUNCE_MERGE_SOUL); + me->CastStop(); + DoCastAOE(SPELL_MERGED_SOULS, true); + me->DespawnOrUnsummon(Seconds(1)); + } + else + { + if (Creature* harbinger = _instance->GetCreature(DATA_HARBINGER_OF_DARKNESS)) + me->GetMotionMaster()->MovePoint(0, harbinger->GetPosition(), true); + _events.Repeat(Milliseconds(500)); + } + break; + default: + break; + } + } + } + + private: + EventMap _events; + InstanceScript* _instance; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetLostCityOfTheTolvirAI(creature); + } +}; + +class spell_barim_plague_of_ages_first : public SpellScriptLoader +{ +public: + spell_barim_plague_of_ages_first() : SpellScriptLoader("spell_barim_plague_of_ages_first") { } + + class spell_barim_plague_of_ages_first_SpellScript : public SpellScript + { + PrepareSpellScript(spell_barim_plague_of_ages_first_SpellScript); + + void FilterTargets(std::list& targets) + { + if (targets.empty()) + return; + + Trinity::Containers::RandomResize(targets, 1); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_barim_plague_of_ages_first_SpellScript::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ALLY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_barim_plague_of_ages_first_SpellScript(); + } +}; + +class spell_barim_plague_of_ages_second : public SpellScriptLoader +{ +public: + spell_barim_plague_of_ages_second() : SpellScriptLoader("spell_barim_plague_of_ages_second") { } + + class spell_barim_plague_of_ages_second_SpellScript : public SpellScript + { + PrepareSpellScript(spell_barim_plague_of_ages_second_SpellScript); + + void FilterTargets(std::list& targets) + { + if (targets.empty()) + return; + + Trinity::Containers::RandomResize(targets, 1); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_barim_plague_of_ages_second_SpellScript::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ALLY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_barim_plague_of_ages_second_SpellScript(); + } +}; + +class spell_barim_repentance_script : public SpellScriptLoader +{ +public: + spell_barim_repentance_script() : SpellScriptLoader("spell_barim_repentance_script") { } + + class spell_barim_repentance_script_SpellScript : public SpellScript + { + PrepareSpellScript(spell_barim_repentance_script_SpellScript); + + void EffectScriptEffect(SpellEffIndex /*effIndex*/) + { + if (Unit* playerTarget = GetHitPlayer()) + playerTarget->CastSpell(GetCaster(), GetSpellInfo()->Effects[EFFECT_0].BasePoints, true); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_barim_repentance_script_SpellScript::EffectScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_barim_repentance_script_SpellScript(); + } +}; + +class spell_barim_repentance_pull : public SpellScriptLoader +{ +public: + spell_barim_repentance_pull() : SpellScriptLoader("spell_barim_repentance_pull") { } + + class spell_barim_repentance_pull_SpellScript : public SpellScript + { + PrepareSpellScript(spell_barim_repentance_pull_SpellScript); + + void HandPullEffect(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + if (Unit* playerTarget = GetHitPlayer()) + { + if (Unit* barim = GetCaster()) // unneeded, but we use it for readability instead of tons of GetCaster() calls + { + // Calculate our own destination since players should land in front of Barim instead of inside him + Position pos; + float angle = barim->GetAngle(playerTarget); + float distance = barim->GetCombatReach() * 2; + pos.m_positionX = barim->GetPositionX() + cos(angle) * distance; + pos.m_positionY = barim->GetPositionY() + sin(angle) * distance; + pos.m_positionZ = barim->GetPositionZ(); + + float speedXY = float(GetSpellInfo()->Effects[EFFECT_0].MiscValue) * 0.1f; + float speedZ = playerTarget->GetDistance(pos) / speedXY * 0.5f * Movement::gravity; + playerTarget->GetMotionMaster()->MoveJump(pos, speedXY, speedZ); + } + } + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_barim_repentance_pull_SpellScript::HandPullEffect, EFFECT_0, SPELL_EFFECT_PULL_TOWARDS); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_barim_repentance_pull_SpellScript(); + } +}; + +void AddSC_boss_high_prophet_barim() +{ + new boss_high_prophet_barim(); + new npc_barim_repentance(); + new npc_barim_harbinger_of_darkness(); + new npc_barim_blaze_of_the_heavens(); + new npc_barim_soul_fragment(); + new spell_barim_plague_of_ages_first(); + new spell_barim_plague_of_ages_second(); + new spell_barim_repentance_script(); + new spell_barim_repentance_pull(); +} diff --git a/src/server/scripts/Kalimdor/LostCityOfTheTolvir/instance_lost_city_of_the_tolvir.cpp b/src/server/scripts/Kalimdor/LostCityOfTheTolvir/instance_lost_city_of_the_tolvir.cpp index d7c2a9cfdb..ea3be9c72c 100644 --- a/src/server/scripts/Kalimdor/LostCityOfTheTolvir/instance_lost_city_of_the_tolvir.cpp +++ b/src/server/scripts/Kalimdor/LostCityOfTheTolvir/instance_lost_city_of_the_tolvir.cpp @@ -21,12 +21,14 @@ ObjectData const creatureData[] = { - { BOSS_GENERAL_HUSAM, DATA_GENERAL_HUSAM }, - { BOSS_LOCKMAW, DATA_LOCKMAW }, - { BOSS_AUGH, DATA_AUGH }, - { BOSS_HIGH_PROPHET_BARIM, DATA_HIGH_PROPHET_BARIM }, - { BOSS_SIAMAT, DATA_SIAMAT }, - { 0, 0 } // End + { BOSS_GENERAL_HUSAM, DATA_GENERAL_HUSAM }, + { BOSS_LOCKMAW, DATA_LOCKMAW }, + { BOSS_AUGH, DATA_AUGH }, + { BOSS_HIGH_PROPHET_BARIM, DATA_HIGH_PROPHET_BARIM }, + { BOSS_SIAMAT, DATA_SIAMAT }, + { NPC_BLAZE_OF_THE_HEAVENS, DATA_BLAZE_OF_THE_HEAVENS }, + { NPC_HARBINGER_OF_DARKNESS, DATA_HARBINGER_OF_DARKNESS }, + { 0, 0 } // End }; ObjectData const gameObjectData[] = diff --git a/src/server/scripts/Kalimdor/LostCityOfTheTolvir/lost_city_of_the_tolvir.h b/src/server/scripts/Kalimdor/LostCityOfTheTolvir/lost_city_of_the_tolvir.h index f23f2780ef..1107ed6934 100644 --- a/src/server/scripts/Kalimdor/LostCityOfTheTolvir/lost_city_of_the_tolvir.h +++ b/src/server/scripts/Kalimdor/LostCityOfTheTolvir/lost_city_of_the_tolvir.h @@ -26,30 +26,36 @@ uint32 const EncounterCount = 4; enum LCTDataTypes { // Encounter States - DATA_GENERAL_HUSAM = 1, - DATA_LOCKMAW = 2, - DATA_AUGH = 3, - DATA_HIGH_PROPHET_BARIM = 4, - DATA_SIAMAT = 5, + DATA_GENERAL_HUSAM = 1, + DATA_LOCKMAW = 2, + DATA_AUGH = 3, + DATA_HIGH_PROPHET_BARIM = 4, + DATA_SIAMAT = 5, // Additional Data - DATA_SIAMAT_PLATFORM = 6 + DATA_SIAMAT_PLATFORM = 6, + DATA_BLAZE_OF_THE_HEAVENS = 7, + DATA_HARBINGER_OF_DARKNESS = 8, }; enum LCTCreatureIds { // Bosses - BOSS_GENERAL_HUSAM = 44577, - BOSS_LOCKMAW = 43614, - BOSS_AUGH = 49045, - BOSS_HIGH_PROPHET_BARIM = 43612, - BOSS_SIAMAT = 44819, + BOSS_GENERAL_HUSAM = 44577, + BOSS_LOCKMAW = 43614, + BOSS_AUGH = 49045, + BOSS_HIGH_PROPHET_BARIM = 43612, + BOSS_SIAMAT = 44819, // Misc - NPC_BAD_INTENTIONS_TARGET = 44586, - NPC_SHOCKWAVE_STALKER = 44711, - NPC_SHOCKWAVE_VISUAL = 44712, - NPC_TOLVIR_LAND_MINE = 44796 + NPC_BAD_INTENTIONS_TARGET = 44586, + NPC_SHOCKWAVE_STALKER = 44711, + NPC_SHOCKWAVE_VISUAL = 44712, + NPC_TOLVIR_LAND_MINE = 44796, + NPC_REPENTANCE = 43817, + NPC_BLAZE_OF_THE_HEAVENS = 48906, + NPC_SOUL_FRAGMENT = 43934, + NPC_HARBINGER_OF_DARKNESS = 43927, }; enum LCTGameObjectIds diff --git a/src/server/scripts/Kalimdor/kalimdor_script_loader.cpp b/src/server/scripts/Kalimdor/kalimdor_script_loader.cpp index 7e3382a269..d03254e618 100644 --- a/src/server/scripts/Kalimdor/kalimdor_script_loader.cpp +++ b/src/server/scripts/Kalimdor/kalimdor_script_loader.cpp @@ -95,6 +95,7 @@ void AddSC_zulfarrak(); void AddSC_instance_zulfarrak(); void AddSC_instance_lost_city_of_the_tolvir(); // Lost City of the Tol'Vir void AddSC_boss_general_husam(); +void AddSC_boss_high_prophet_barim(); void AddSC_instance_halls_of_origination(); //Halls of Origination void AddSC_boss_temple_guardian_anhuur(); void AddSC_boss_earthrager_ptah(); @@ -207,6 +208,7 @@ void AddKalimdorScripts() AddSC_instance_zulfarrak(); AddSC_instance_lost_city_of_the_tolvir(); // Lost City of the Tol'Vir AddSC_boss_general_husam(); + AddSC_boss_high_prophet_barim(); AddSC_instance_halls_of_origination(); //Halls of Origination AddSC_boss_temple_guardian_anhuur(); AddSC_boss_earthrager_ptah();