diff options
author | Keader <keader.android@gmail.com> | 2017-01-01 21:19:25 -0200 |
---|---|---|
committer | DoctorKraft <DoctorKraft@users.noreply.github.com> | 2018-03-18 00:19:50 +0100 |
commit | f7970166d7c5891e42835d5a6c5235c4e895bc0a (patch) | |
tree | 0966defc6d90ce341315bb8b5975e1d98de387cb /src | |
parent | 36910585c9cb27e22ecceca647909b4b20a2c087 (diff) |
Core/Scripts: Blood Prince Council refactored and fixed reported issues (#18632)
Closes #7150
(cherry picked from commit 64f6f2a0ae7294857d5ebd1ec6034476e94656e6)
Diffstat (limited to 'src')
3 files changed, 451 insertions, 624 deletions
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp index d1ed10dfb6c..d51c43b4255 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp @@ -28,6 +28,7 @@ #include "SpellInfo.h" #include "SpellScript.h" #include "TemporarySummon.h" +#include "PassiveAI.h" enum Texts { @@ -59,7 +60,7 @@ enum Texts EMOTE_VALANAR_SHOCK_VORTEX = 3, SAY_VALANAR_KILL = 4, SAY_VALANAR_BERSERK = 5, - SAY_VALANAR_DEATH = 6, + SAY_VALANAR_DEATH = 6 }; enum Spells @@ -116,72 +117,104 @@ enum Spells // Shock Vortex SPELL_SHOCK_VORTEX_PERIODIC = 71945, SPELL_SHOCK_VORTEX_DUMMY = 72633, + + // Visual Spells + SPELL_INVOCATION_VISUAL_VALANAR = 71070, + SPELL_INVOCATION_VISUAL_TALDARAM = 71081, + SPELL_INVOCATION_VISUAL_KELESETH = 71080 }; enum Events { EVENT_INTRO_1 = 1, - EVENT_INTRO_2 = 2, + EVENT_INTRO_2, - EVENT_INVOCATION_OF_BLOOD = 3, - EVENT_BERSERK = 4, + EVENT_INVOCATION_OF_BLOOD, + EVENT_BERSERK, // Keleseth - EVENT_SHADOW_RESONANCE = 5, - EVENT_SHADOW_LANCE = 6, + EVENT_SHADOW_RESONANCE, + EVENT_SHADOW_LANCE, // Taldaram - EVENT_GLITTERING_SPARKS = 7, - EVENT_CONJURE_FLAME = 8, + EVENT_GLITTERING_SPARKS, + EVENT_CONJURE_FLAME, // Valanar - EVENT_KINETIC_BOMB = 9, - EVENT_SHOCK_VORTEX = 10, - EVENT_BOMB_DESPAWN = 11, - EVENT_CONTINUE_FALLING = 12, + EVENT_KINETIC_BOMB, + EVENT_SHOCK_VORTEX, + EVENT_BOMB_DESPAWN, + EVENT_CONTINUE_FALLING }; enum Actions { ACTION_START_INTRO = 1, - ACTION_STAND_UP = 2, - ACTION_CAST_INVOCATION = 3, - ACTION_REMOVE_INVOCATION = 4, - ACTION_KINETIC_BOMB_JUMP = 5, - ACTION_FLAME_BALL_CHASE = 6, + ACTION_INTRO_DONE, + ACTION_STAND_UP, + ACTION_CAST_INVOCATION, + ACTION_REMOVE_INVOCATION, + ACTION_KINETIC_BOMB_JUMP, + ACTION_FLAME_BALL_CHASE }; enum Points { POINT_INTRO_DESPAWN = 380040, - POINT_KINETIC_BOMB_IMPACT = 384540, + POINT_KINETIC_BOMB_IMPACT = 384540 }; -enum Displays +enum Misc { DISPLAY_KINETIC_BOMB = 31095, + SUMMON_PRINCES_GROUP = 1, + DATA_INTRO = 2, + DATA_INTRO_DONE = 3, + DATA_PRINCE_EVADE = 4 }; class StandUpEvent : public BasicEvent { public: - StandUpEvent(Creature& owner) : BasicEvent(), _owner(owner) { } + StandUpEvent(Creature* owner) : BasicEvent(), _owner(owner) { } bool Execute(uint64 /*eventTime*/, uint32 /*diff*/) override { - _owner.HandleEmoteCommand(EMOTE_ONESHOT_ROAR); - _owner.SetReactState(REACT_AGGRESSIVE); + _owner->HandleEmoteCommand(EMOTE_ONESHOT_ROAR); + _owner->SetReactState(REACT_AGGRESSIVE); return true; } private: - Creature& _owner; + Creature* _owner; +}; + +class VortexEvent : public BasicEvent +{ +public: + VortexEvent(Creature* owner) : _owner(owner) { } + + bool Execute(uint64 /*eventTime*/, uint32 /*diff*/) override + { + _owner->CastSpell(_owner, SPELL_SHOCK_VORTEX_PERIODIC, true); + return true; + } + +private: + Creature* _owner; }; Position const introFinalPos = {4660.490f, 2769.200f, 430.0000f, 0.000000f}; Position const triggerPos = {4680.231f, 2769.134f, 379.9256f, 3.121708f}; Position const triggerEndPos = {4680.180f, 2769.150f, 365.5000f, 3.121708f}; +uint32 const PrincesData[] = +{ + DATA_PRINCE_KELESETH, + DATA_PRINCE_TALDARAM, + DATA_PRINCE_VALANAR +}; + class boss_blood_council_controller : public CreatureScript { public: @@ -189,9 +222,10 @@ class boss_blood_council_controller : public CreatureScript struct boss_blood_council_controllerAI : public BossAI { - boss_blood_council_controllerAI(Creature* creature) : BossAI(creature, DATA_BLOOD_PRINCE_COUNCIL) + boss_blood_council_controllerAI(Creature* creature) : BossAI(creature, DATA_BLOOD_PRINCE_COUNCIL), _intro(true) { Initialize(); + SetCombatMovement(false); } void Initialize() @@ -202,11 +236,32 @@ class boss_blood_council_controller : public CreatureScript void Reset() override { - events.Reset(); - me->SetReactState(REACT_PASSIVE); + _Reset(); Initialize(); + me->SummonCreatureGroup(SUMMON_PRINCES_GROUP); + + if (!_intro) + for (uint32 bossData : PrincesData) + if (Creature* prince = ObjectAccessor::GetCreature(*me, instance->GetGuidData(bossData))) + { + prince->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_PC); + if (bossData == DATA_PRINCE_VALANAR) + prince->SetHealth(prince->GetMaxHealth()); + } + } + + void EnterEvadeMode(EvadeReason /*why*/) override + { + // Avoid do set boss state to fail with hotswap + if (instance->GetBossState(DATA_BLOOD_PRINCE_COUNCIL) == DONE) + return; + + for (uint32 bossData : PrincesData) + if (Creature* prince = ObjectAccessor::GetCreature(*me, instance->GetGuidData(bossData))) + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, prince); - instance->SetBossState(DATA_BLOOD_PRINCE_COUNCIL, NOT_STARTED); + summons.DespawnAll(); + _DespawnAtEvade(); } void EnterCombat(Unit* who) override @@ -216,45 +271,37 @@ class boss_blood_council_controller : public CreatureScript if (!instance->CheckRequiredBosses(DATA_BLOOD_PRINCE_COUNCIL, who->ToPlayer())) { - EnterEvadeMode(); + EnterEvadeMode(EVADE_REASON_SEQUENCE_BREAK); instance->DoCastSpellOnPlayers(LIGHT_S_HAMMER_TELEPORT); return; } + me->SetCombatPulseDelay(5); + me->setActive(true); + DoZoneInCombat(); instance->SetBossState(DATA_BLOOD_PRINCE_COUNCIL, IN_PROGRESS); - DoCast(me, SPELL_INVOCATION_OF_BLOOD_VALANAR); - - if (Creature* keleseth = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_PRINCE_KELESETH_GUID))) - { - instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, keleseth); - DoZoneInCombat(keleseth); - } - - if (Creature* taldaram = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_PRINCE_TALDARAM_GUID))) - { - instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, taldaram); - DoZoneInCombat(taldaram); - } + DoCastSelf(SPELL_INVOCATION_OF_BLOOD_VALANAR); - if (Creature* valanar = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_PRINCE_VALANAR_GUID))) - { - instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, valanar); - DoZoneInCombat(valanar); - } + for (uint32 bossData : PrincesData) + if (Creature* prince = ObjectAccessor::GetCreature(*me, instance->GetGuidData(bossData))) + { + instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, prince); + DoZoneInCombat(prince); + } - events.ScheduleEvent(EVENT_INVOCATION_OF_BLOOD, 46500); + events.ScheduleEvent(EVENT_INVOCATION_OF_BLOOD, Seconds(46) + Milliseconds(500)); - _invocationOrder[0] = InvocationData(instance->GetGuidData(DATA_PRINCE_VALANAR_GUID), SPELL_INVOCATION_OF_BLOOD_VALANAR, EMOTE_VALANAR_INVOCATION, 71070); - if (urand(0, 1)) + _invocationOrder[0] = InvocationData(instance->GetGuidData(DATA_PRINCE_VALANAR), SPELL_INVOCATION_OF_BLOOD_VALANAR, EMOTE_VALANAR_INVOCATION, SPELL_INVOCATION_VISUAL_VALANAR); + if (roll_chance_i(50)) { - _invocationOrder[1] = InvocationData(instance->GetGuidData(DATA_PRINCE_TALDARAM_GUID), SPELL_INVOCATION_OF_BLOOD_TALDARAM, EMOTE_TALDARAM_INVOCATION, 71081); - _invocationOrder[2] = InvocationData(instance->GetGuidData(DATA_PRINCE_KELESETH_GUID), SPELL_INVOCATION_OF_BLOOD_KELESETH, EMOTE_KELESETH_INVOCATION, 71080); + _invocationOrder[1] = InvocationData(instance->GetGuidData(DATA_PRINCE_TALDARAM), SPELL_INVOCATION_OF_BLOOD_TALDARAM, EMOTE_TALDARAM_INVOCATION, SPELL_INVOCATION_VISUAL_TALDARAM); + _invocationOrder[2] = InvocationData(instance->GetGuidData(DATA_PRINCE_KELESETH), SPELL_INVOCATION_OF_BLOOD_KELESETH, EMOTE_KELESETH_INVOCATION, SPELL_INVOCATION_VISUAL_KELESETH); } else { - _invocationOrder[1] = InvocationData(instance->GetGuidData(DATA_PRINCE_KELESETH_GUID), SPELL_INVOCATION_OF_BLOOD_KELESETH, EMOTE_KELESETH_INVOCATION, 71080); - _invocationOrder[2] = InvocationData(instance->GetGuidData(DATA_PRINCE_TALDARAM_GUID), SPELL_INVOCATION_OF_BLOOD_TALDARAM, EMOTE_TALDARAM_INVOCATION, 71081); + _invocationOrder[1] = InvocationData(instance->GetGuidData(DATA_PRINCE_KELESETH), SPELL_INVOCATION_OF_BLOOD_KELESETH, EMOTE_KELESETH_INVOCATION, SPELL_INVOCATION_VISUAL_KELESETH); + _invocationOrder[2] = InvocationData(instance->GetGuidData(DATA_PRINCE_TALDARAM), SPELL_INVOCATION_OF_BLOOD_TALDARAM, EMOTE_TALDARAM_INVOCATION, SPELL_INVOCATION_VISUAL_TALDARAM); } } @@ -262,26 +309,21 @@ class boss_blood_council_controller : public CreatureScript { _resetCounter += uint8(data); if (_resetCounter == 3) - EnterEvadeMode(); + EnterEvadeMode(EVADE_REASON_OTHER); } - void JustReachedHome() override + uint32 GetData(uint32 data) const override { - _resetCounter = 0; - if (Creature* keleseth = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_PRINCE_KELESETH_GUID))) - keleseth->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - if (Creature* taldaram = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_PRINCE_TALDARAM_GUID))) - taldaram->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - if (Creature* valanar = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_PRINCE_VALANAR_GUID))) - valanar->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + if (data == DATA_INTRO && !_intro) + return DATA_INTRO_DONE; + return 0; } void JustDied(Unit* killer) override { - _JustDied(); - // kill all prices + events.Reset(); + instance->SetBossState(DATA_BLOOD_PRINCE_COUNCIL, DONE); + // Kill all prices for (uint8 i = 0; i < 3; ++i) { if (++_invocationStage == 3) @@ -289,7 +331,7 @@ class boss_blood_council_controller : public CreatureScript if (Creature* prince = ObjectAccessor::GetCreature(*me, _invocationOrder[_invocationStage].guid)) { - // make sure looting is allowed + // Make sure looting is allowed if (me->IsDamageEnoughForLootingAndReward()) prince->LowerPlayerDamageReq(prince->GetMaxHealth()); killer->Kill(prince); @@ -297,6 +339,27 @@ class boss_blood_council_controller : public CreatureScript } } + void DoAction(int32 actionId) override + { + if (actionId == ACTION_START_INTRO && _intro && instance->GetBossState(DATA_BLOOD_PRINCE_COUNCIL) != DONE) + { + _intro = false; + if (Creature* bloodQueen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_BLOOD_QUEEN_LANA_THEL_COUNCIL))) + bloodQueen->AI()->DoAction(ACTION_START_INTRO); + } + else if (actionId == ACTION_INTRO_DONE) + { + // Remove feigh death from princes + for (uint32 bossData : PrincesData) + if (Creature* prince = ObjectAccessor::GetCreature(*me, instance->GetGuidData(bossData))) + { + prince->AI()->DoAction(ACTION_STAND_UP); + if (bossData == DATA_PRINCE_VALANAR) + prince->SetHealth(prince->GetMaxHealth()); + } + } + } + void UpdateAI(uint32 diff) override { if (!UpdateVictim()) @@ -331,8 +394,8 @@ class boss_blood_council_controller : public CreatureScript newPrince->AI()->Talk(uint8(_invocationOrder[_invocationStage].textId)); } - DoCast(me, _invocationOrder[_invocationStage].spellId); - events.ScheduleEvent(EVENT_INVOCATION_OF_BLOOD, 46500); + DoCastSelf(_invocationOrder[_invocationStage].spellId); + events.Repeat(Seconds(46) + Milliseconds(500)); break; } default: @@ -365,6 +428,7 @@ class boss_blood_council_controller : public CreatureScript uint32 _invocationStage; uint32 _resetCounter; + bool _intro; }; CreatureAI* GetAI(Creature* creature) const override @@ -373,89 +437,214 @@ class boss_blood_council_controller : public CreatureScript } }; -class boss_prince_keleseth_icc : public CreatureScript +struct BloodPrincesBossAI : public BossAI { - public: - boss_prince_keleseth_icc() : CreatureScript("boss_prince_keleseth_icc") { } - - struct boss_prince_kelesethAI : public BossAI + BloodPrincesBossAI(Creature* creature, uint32 bossId) : BossAI(creature, bossId), _spawnHealth (creature->GetMaxHealth()), _isEmpowered(false) + { + SetBoundary(instance->GetBossBoundary(DATA_BLOOD_PRINCE_COUNCIL)); + } + + void InitializeAI() override + { + _spawnHealth = 1; + if (!me->isDead()) + JustRespawned(); + } + + void Reset() override + { + events.Reset(); + summons.DespawnAll(); + me->SetCombatPulseDelay(0); + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); + _isEmpowered = false; + me->SetHealth(_spawnHealth); + instance->SetData(DATA_ORB_WHISPERER_ACHIEVEMENT, uint32(true)); + } + + void EnterCombat(Unit* /*who*/) override + { + me->SetCombatPulseDelay(5); + me->setActive(true); + if (Creature* controller = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_BLOOD_PRINCES_CONTROL))) + DoZoneInCombat(controller); + ScheduleTasks(); + } + + virtual void ScheduleTasks() = 0; + + void JustDied(Unit* /*killer*/) override + { + events.Reset(); + summons.DespawnAll(); + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + + switch (me->GetEntry()) { - boss_prince_kelesethAI(Creature* creature) : BossAI(creature, DATA_BLOOD_PRINCE_COUNCIL) - { - _isEmpowered = false; - _spawnHealth = creature->GetMaxHealth(); - } + case NPC_PRINCE_KELESETH: + Talk(SAY_KELESETH_DEATH); + break; + case NPC_PRINCE_TALDARAM: + Talk(EMOTE_TALDARAM_DEATH); + break; + case NPC_PRINCE_VALANAR: + Talk(SAY_VALANAR_DEATH); + break; + default: + break; + } + } - void InitializeAI() override - { - if (CreatureData const* data = me->GetCreatureData()) - if (data->curhealth) - _spawnHealth = data->curhealth; + void JustRespawned() override + { + if (Creature* controller = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_BLOOD_PRINCES_CONTROL))) + if (controller->AI()->GetData(DATA_INTRO) != DATA_INTRO_DONE) + DoCastSelf(SPELL_FEIGN_DEATH); - if (!me->isDead()) - JustRespawned(); - } + me->SetHealth(_spawnHealth); + } - void Reset() override - { - events.Reset(); - summons.DespawnAll(); + void DamageTaken(Unit* attacker, uint32& damage) override + { + if (!_isEmpowered) + { + me->AddThreat(attacker, float(damage)); + damage = 0; + } + } - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); - _isEmpowered = false; + void KilledUnit(Unit* victim) override + { + if (victim->GetTypeId() == TYPEID_PLAYER) + switch (me->GetEntry()) + { + case NPC_PRINCE_KELESETH: + Talk(SAY_KELESETH_KILL); + break; + case NPC_PRINCE_TALDARAM: + Talk(SAY_TALDARAM_KILL); + break; + case NPC_PRINCE_VALANAR: + Talk(SAY_VALANAR_KILL); + break; + default: + break; + } + } + + void JustReachedHome() override + { + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + me->SetHealth(_spawnHealth); + _isEmpowered = false; + if (Creature* controller = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_BLOOD_PRINCES_CONTROL))) + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + controller->AI()->SetData(DATA_PRINCE_EVADE, 1); + } + } + + void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override + { + if (spell->Id == SelectInvocationSpell()) + DoAction(ACTION_CAST_INVOCATION); + } + + void DamageDealt(Unit* /*target*/, uint32& damage, DamageEffectType damageType) override + { + if (damageType != SPELL_DIRECT_DAMAGE) + return; + + if (damage > RAID_MODE<uint32>(23000, 25000, 23000, 25000)) + instance->SetData(DATA_ORB_WHISPERER_ACHIEVEMENT, uint32(false)); + } + + void DoAction(int32 action) override + { + switch (action) + { + case ACTION_STAND_UP: + me->RemoveAurasDueToSpell(SPELL_FEIGN_DEATH); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_PC); + me->RemoveFlag(OBJECT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD); + me->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH); + me->ForceValuesUpdateAtIndex(UNIT_NPC_FLAGS); // was in sniff. don't ask why + me->m_Events.AddEvent(new StandUpEvent(me), me->m_Events.CalculateTime(1000)); + break; + case ACTION_CAST_INVOCATION: + Talk(SelectInvocationSay()); + DoCastSelf(SPELL_INVOCATION_VISUAL_ACTIVE, true); + _isEmpowered = true; + break; + case ACTION_REMOVE_INVOCATION: me->SetHealth(_spawnHealth); - instance->SetData(DATA_ORB_WHISPERER_ACHIEVEMENT, uint32(true)); - } + me->RemoveAurasDueToSpell(SPELL_INVOCATION_VISUAL_ACTIVE); + me->RemoveAurasDueToSpell(SelectInvocationSpell()); + _isEmpowered = false; + break; + default: + break; + } + } - void EnterCombat(Unit* /*who*/) override - { - if (Creature* controller = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_BLOOD_PRINCES_CONTROL))) - DoZoneInCombat(controller); + uint32 SelectInvocationSay() + { + switch (me->GetEntry()) + { + case NPC_PRINCE_KELESETH: + return SAY_KELESETH_INVOCATION; + case NPC_PRINCE_TALDARAM: + return SAY_TALDARAM_INVOCATION; + case NPC_PRINCE_VALANAR: + return SAY_KELESETH_INVOCATION; + default: // Should never happen + return 0; + } + } - events.ScheduleEvent(EVENT_BERSERK, 600000); - events.ScheduleEvent(EVENT_SHADOW_RESONANCE, urand(10000, 15000)); - events.ScheduleEvent(EVENT_SHADOW_LANCE, 2000); + uint32 SelectInvocationSpell() + { + switch (me->GetEntry()) + { + case NPC_PRINCE_KELESETH: + return SPELL_INVOCATION_OF_BLOOD_KELESETH; + case NPC_PRINCE_TALDARAM: + return SPELL_INVOCATION_OF_BLOOD_TALDARAM; + case NPC_PRINCE_VALANAR: + return SPELL_INVOCATION_OF_BLOOD_VALANAR; + default: // Should never happen + return 0; + } + } - if (IsHeroic()) - { - me->AddAura(SPELL_SHADOW_PRISON, me); - DoCast(me, SPELL_SHADOW_PRISON_DUMMY); - } - } +protected: + uint32 _spawnHealth; + bool _isEmpowered; +}; - void JustDied(Unit* /*killer*/) override - { - events.Reset(); - summons.DespawnAll(); +class boss_prince_keleseth_icc : public CreatureScript +{ + public: + boss_prince_keleseth_icc() : CreatureScript("boss_prince_keleseth_icc") { } - Talk(SAY_KELESETH_DEATH); - instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); - } + struct boss_prince_kelesethAI : public BloodPrincesBossAI + { + boss_prince_kelesethAI(Creature* creature) : BloodPrincesBossAI(creature, DATA_PRINCE_KELESETH) { } - void JustReachedHome() override + void ScheduleTasks() override { - instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); - me->SetHealth(_spawnHealth); - _isEmpowered = false; - if (Creature* controller = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_BLOOD_PRINCES_CONTROL))) + events.ScheduleEvent(EVENT_BERSERK, Minutes(10)); + events.ScheduleEvent(EVENT_SHADOW_RESONANCE, Seconds(10), Seconds(15)); + events.ScheduleEvent(EVENT_SHADOW_LANCE, Seconds(2)); + + if (IsHeroic()) { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - controller->AI()->SetData(0, 1); + DoCastSelf(SPELL_SHADOW_PRISON, true); + DoCastSelf(SPELL_SHADOW_PRISON_DUMMY); } } - void JustRespawned() override - { - DoCast(me, SPELL_FEIGN_DEATH); - me->SetHealth(_spawnHealth); - } - - void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override - { - if (spell->Id == SPELL_INVOCATION_OF_BLOOD_KELESETH) - DoAction(ACTION_CAST_INVOCATION); - } - void JustSummoned(Creature* summon) override { summons.Summon(summon); @@ -467,78 +656,9 @@ class boss_prince_keleseth_icc : public CreatureScript summon->ToTempSummon()->SetTempSummonType(TEMPSUMMON_CORPSE_DESPAWN); } - void DamageDealt(Unit* /*target*/, uint32& damage, DamageEffectType damageType) override - { - if (damageType != SPELL_DIRECT_DAMAGE) - return; - - if (damage > RAID_MODE<uint32>(23000, 25000, 23000, 25000)) - instance->SetData(DATA_ORB_WHISPERER_ACHIEVEMENT, uint32(false)); - } - - void DamageTaken(Unit* attacker, uint32& damage) override - { - if (!_isEmpowered) - { - me->AddThreat(attacker, float(damage)); - damage = 0; - } - } - - void KilledUnit(Unit* victim) override - { - if (victim->GetTypeId() == TYPEID_PLAYER) - Talk(SAY_KELESETH_KILL); - } - - void DoAction(int32 action) override - { - switch (action) - { - case ACTION_STAND_UP: - me->RemoveAurasDueToSpell(SPELL_FEIGN_DEATH); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_PC); - me->RemoveFlag(OBJECT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD); - me->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH); - me->ForceValuesUpdateAtIndex(UNIT_NPC_FLAGS); // was in sniff. don't ask why - me->m_Events.AddEvent(new StandUpEvent(*me), me->m_Events.CalculateTime(1000)); - break; - case ACTION_CAST_INVOCATION: - Talk(SAY_KELESETH_INVOCATION); - DoCast(me, SPELL_INVOCATION_VISUAL_ACTIVE, true); - _isEmpowered = true; - break; - case ACTION_REMOVE_INVOCATION: - me->SetHealth(_spawnHealth); - me->RemoveAurasDueToSpell(SPELL_INVOCATION_VISUAL_ACTIVE); - me->RemoveAurasDueToSpell(SPELL_INVOCATION_OF_BLOOD_KELESETH); - _isEmpowered = false; - break; - default: - break; - } - } - - bool CheckInRoom() override - { - if (!CheckBoundary(me)) - { - EnterEvadeMode(); - if (Creature* taldaram = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_PRINCE_TALDARAM_GUID))) - taldaram->AI()->EnterEvadeMode(); - - if (Creature* valanar = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_PRINCE_VALANAR_GUID))) - valanar->AI()->EnterEvadeMode(); - - return false; - } - - return true; - } - void UpdateAI(uint32 diff) override { - if (!UpdateVictim() || !CheckInRoom()) + if (!UpdateVictim()) return; events.Update(diff); @@ -551,20 +671,17 @@ class boss_prince_keleseth_icc : public CreatureScript switch (eventId) { case EVENT_BERSERK: - DoCast(me, SPELL_BERSERK); + DoCastSelf(SPELL_BERSERK); Talk(EMOTE_KELESETH_BERSERK); break; case EVENT_SHADOW_RESONANCE: Talk(SAY_KELESETH_SPECIAL); - DoCast(me, SPELL_SHADOW_RESONANCE); - events.ScheduleEvent(EVENT_SHADOW_RESONANCE, urand(10000, 15000)); + DoCastSelf(SPELL_SHADOW_RESONANCE); + events.Repeat(Seconds(10), Seconds(15)); break; case EVENT_SHADOW_LANCE: - if (_isEmpowered) - DoCastVictim(SPELL_EMPOWERED_SHADOW_LANCE); - else - DoCastVictim(SPELL_SHADOW_LANCE); - events.ScheduleEvent(EVENT_SHADOW_LANCE, 2000); + _isEmpowered ? DoCastVictim(SPELL_EMPOWERED_SHADOW_LANCE) : DoCastVictim(SPELL_SHADOW_LANCE); + events.Repeat(Seconds(2)); break; default: break; @@ -576,10 +693,6 @@ class boss_prince_keleseth_icc : public CreatureScript // does not melee } - - private: - uint32 _spawnHealth; - bool _isEmpowered; }; CreatureAI* GetAI(Creature* creature) const override @@ -593,78 +706,17 @@ class boss_prince_taldaram_icc : public CreatureScript public: boss_prince_taldaram_icc() : CreatureScript("boss_prince_taldaram_icc") { } - struct boss_prince_taldaramAI : public BossAI + struct boss_prince_taldaramAI : public BloodPrincesBossAI { - boss_prince_taldaramAI(Creature* creature) : BossAI(creature, DATA_BLOOD_PRINCE_COUNCIL) - { - _isEmpowered = false; - _spawnHealth = creature->GetMaxHealth(); - } + boss_prince_taldaramAI(Creature* creature) : BloodPrincesBossAI(creature, DATA_PRINCE_TALDARAM) { } - void InitializeAI() override + void ScheduleTasks() override { - if (CreatureData const* data = me->GetCreatureData()) - if (data->curhealth) - _spawnHealth = data->curhealth; - - if (!me->isDead()) - JustRespawned(); - } - - void Reset() override - { - events.Reset(); - summons.DespawnAll(); - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); - _isEmpowered = false; - me->SetHealth(_spawnHealth); - instance->SetData(DATA_ORB_WHISPERER_ACHIEVEMENT, uint32(true)); - } - - void EnterCombat(Unit* /*who*/) override - { - if (Creature* controller = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_BLOOD_PRINCES_CONTROL))) - DoZoneInCombat(controller); - - events.ScheduleEvent(EVENT_BERSERK, 600000); - events.ScheduleEvent(EVENT_GLITTERING_SPARKS, urand(12000, 15000)); - events.ScheduleEvent(EVENT_CONJURE_FLAME, 20000); + events.ScheduleEvent(EVENT_BERSERK, Minutes(10)); + events.ScheduleEvent(EVENT_GLITTERING_SPARKS, Seconds(12), Seconds(15)); + events.ScheduleEvent(EVENT_CONJURE_FLAME, Seconds(20)); if (IsHeroic()) - me->AddAura(SPELL_SHADOW_PRISON, me); - } - - void JustDied(Unit* /*killer*/) override - { - events.Reset(); - summons.DespawnAll(); - - Talk(EMOTE_TALDARAM_DEATH); - instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); - } - - void JustReachedHome() override - { - instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); - me->SetHealth(_spawnHealth); - _isEmpowered = false; - if (Creature* controller = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_BLOOD_PRINCES_CONTROL))) - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - controller->AI()->SetData(0, 1); - } - } - - void JustRespawned() override - { - DoCast(me, SPELL_FEIGN_DEATH); - me->SetHealth(_spawnHealth); - } - - void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override - { - if (spell->Id == SPELL_INVOCATION_OF_BLOOD_TALDARAM) - DoAction(ACTION_CAST_INVOCATION); + DoCastSelf(SPELL_SHADOW_PRISON, true); } void JustSummoned(Creature* summon) override @@ -681,78 +733,9 @@ class boss_prince_taldaram_icc : public CreatureScript summon->AI()->SetGUID(target->GetGUID()); } - void DamageDealt(Unit* /*target*/, uint32& damage, DamageEffectType damageType) override - { - if (damageType != SPELL_DIRECT_DAMAGE) - return; - - if (damage > RAID_MODE<uint32>(23000, 25000, 23000, 25000)) - instance->SetData(DATA_ORB_WHISPERER_ACHIEVEMENT, uint32(false)); - } - - void DamageTaken(Unit* attacker, uint32& damage) override - { - if (!_isEmpowered) - { - me->AddThreat(attacker, float(damage)); - damage = 0; - } - } - - void KilledUnit(Unit* victim) override - { - if (victim->GetTypeId() == TYPEID_PLAYER) - Talk(SAY_TALDARAM_KILL); - } - - void DoAction(int32 action) override - { - switch (action) - { - case ACTION_STAND_UP: - me->RemoveAurasDueToSpell(SPELL_FEIGN_DEATH); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_PC); - me->RemoveFlag(OBJECT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD); - me->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH); - me->ForceValuesUpdateAtIndex(UNIT_NPC_FLAGS); // was in sniff. don't ask why - me->m_Events.AddEvent(new StandUpEvent(*me), me->m_Events.CalculateTime(1000)); - break; - case ACTION_CAST_INVOCATION: - Talk(SAY_TALDARAM_INVOCATION); - DoCast(me, SPELL_INVOCATION_VISUAL_ACTIVE, true); - _isEmpowered = true; - break; - case ACTION_REMOVE_INVOCATION: - me->SetHealth(_spawnHealth); - me->RemoveAurasDueToSpell(SPELL_INVOCATION_VISUAL_ACTIVE); - me->RemoveAurasDueToSpell(SPELL_INVOCATION_OF_BLOOD_TALDARAM); - _isEmpowered = false; - break; - default: - break; - } - } - - bool CheckInRoom() override - { - if (!CheckBoundary(me)) - { - EnterEvadeMode(); - if (Creature* keleseth = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_PRINCE_KELESETH_GUID))) - keleseth->AI()->EnterEvadeMode(); - - if (Creature* valanar = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_PRINCE_VALANAR_GUID))) - valanar->AI()->EnterEvadeMode(); - - return false; - } - - return true; - } - void UpdateAI(uint32 diff) override { - if (!UpdateVictim() || !CheckInRoom()) + if (!UpdateVictim()) return; events.Update(diff); @@ -765,23 +748,23 @@ class boss_prince_taldaram_icc : public CreatureScript switch (eventId) { case EVENT_BERSERK: - DoCast(me, SPELL_BERSERK); + DoCastSelf(SPELL_BERSERK); Talk(EMOTE_TALDARAM_BERSERK); break; case EVENT_GLITTERING_SPARKS: DoCastVictim(SPELL_GLITTERING_SPARKS); - events.ScheduleEvent(EVENT_GLITTERING_SPARKS, urand(15000, 50000)); + events.Repeat(Seconds(15), Seconds(50)); break; case EVENT_CONJURE_FLAME: if (_isEmpowered) { - DoCast(me, SPELL_CONJURE_EMPOWERED_FLAME); - events.ScheduleEvent(EVENT_CONJURE_FLAME, urand(15000, 25000)); + DoCastSelf(SPELL_CONJURE_EMPOWERED_FLAME); + events.Repeat(Seconds(15), Seconds(25)); } else { - DoCast(me, SPELL_CONJURE_FLAME); - events.ScheduleEvent(EVENT_CONJURE_FLAME, urand(20000, 30000)); + DoCastSelf(SPELL_CONJURE_FLAME); + events.Repeat(Seconds(20), Seconds(30)); } Talk(SAY_TALDARAM_SPECIAL); break; @@ -795,10 +778,6 @@ class boss_prince_taldaram_icc : public CreatureScript DoMeleeAttackIfReady(); } - - private: - uint32 _spawnHealth; - bool _isEmpowered; }; CreatureAI* GetAI(Creature* creature) const override @@ -812,72 +791,17 @@ class boss_prince_valanar_icc : public CreatureScript public: boss_prince_valanar_icc() : CreatureScript("boss_prince_valanar_icc") { } - struct boss_prince_valanarAI : public BossAI + struct boss_prince_valanarAI : public BloodPrincesBossAI { - boss_prince_valanarAI(Creature* creature) : BossAI(creature, DATA_BLOOD_PRINCE_COUNCIL) - { - _isEmpowered = false; - _spawnHealth = creature->GetMaxHealth(); - } - - void InitializeAI() override - { - if (CreatureData const* data = me->GetCreatureData()) - if (data->curhealth) - _spawnHealth = data->curhealth; - - if (!me->isDead()) - JustRespawned(); - } + boss_prince_valanarAI(Creature* creature) : BloodPrincesBossAI(creature, DATA_PRINCE_TALDARAM) { } - void Reset() override + void ScheduleTasks() override { - events.Reset(); - summons.DespawnAll(); - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); - _isEmpowered = false; - me->SetHealth(me->GetMaxHealth()); - instance->SetData(DATA_ORB_WHISPERER_ACHIEVEMENT, uint32(true)); - } - - void EnterCombat(Unit* /*who*/) override - { - if (Creature* controller = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_BLOOD_PRINCES_CONTROL))) - DoZoneInCombat(controller); - - events.ScheduleEvent(EVENT_BERSERK, 600000); - events.ScheduleEvent(EVENT_KINETIC_BOMB, urand(18000, 24000)); - events.ScheduleEvent(EVENT_SHOCK_VORTEX, urand(15000, 20000)); + events.ScheduleEvent(EVENT_BERSERK, Minutes(10)); + events.ScheduleEvent(EVENT_KINETIC_BOMB, Seconds(18), Seconds(24)); + events.ScheduleEvent(EVENT_SHOCK_VORTEX, Seconds(15), Seconds(20)); if (IsHeroic()) - me->AddAura(SPELL_SHADOW_PRISON, me); - } - - void JustDied(Unit* /*killer*/) override - { - events.Reset(); - summons.DespawnAll(); - - Talk(SAY_VALANAR_DEATH); - instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); - } - - void JustReachedHome() override - { - instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); - me->SetHealth(me->GetMaxHealth()); - _isEmpowered = false; - if (Creature* controller = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_BLOOD_PRINCES_CONTROL))) - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - controller->AI()->SetData(0, 1); - } - } - - void JustRespawned() override - { - DoCast(me, SPELL_FEIGN_DEATH); - me->SetHealth(_spawnHealth); + DoCastSelf(SPELL_SHADOW_PRISON, true); } void JustSummoned(Creature* summon) override @@ -886,7 +810,7 @@ class boss_prince_valanar_icc : public CreatureScript { case NPC_KINETIC_BOMB_TARGET: summon->SetReactState(REACT_PASSIVE); - summon->CastSpell(summon, SPELL_KINETIC_BOMB, true, NULL, NULL, me->GetGUID()); + summon->CastSpell(summon, SPELL_KINETIC_BOMB, true, nullptr, nullptr, me->GetGUID()); break; case NPC_KINETIC_BOMB: { @@ -899,7 +823,7 @@ class boss_prince_valanar_icc : public CreatureScript } case NPC_SHOCK_VORTEX: summon->CastSpell(summon, SPELL_SHOCK_VORTEX_DUMMY, true); - summon->CastSpell(summon, SPELL_SHOCK_VORTEX_PERIODIC, true); + summon->m_Events.AddEvent(new VortexEvent(summon), summon->m_Events.CalculateTime(5000)); break; default: break; @@ -910,84 +834,9 @@ class boss_prince_valanar_icc : public CreatureScript DoZoneInCombat(summon); } - void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override - { - if (spell->Id == SPELL_INVOCATION_OF_BLOOD_VALANAR) - DoAction(ACTION_CAST_INVOCATION); - } - - void DamageDealt(Unit* /*target*/, uint32& damage, DamageEffectType damageType) override - { - if (damageType != SPELL_DIRECT_DAMAGE) - return; - - if (damage > RAID_MODE<uint32>(23000, 25000, 23000, 25000)) - instance->SetData(DATA_ORB_WHISPERER_ACHIEVEMENT, uint32(false)); - } - - void DamageTaken(Unit* attacker, uint32& damage) override - { - if (!_isEmpowered) - { - me->AddThreat(attacker, float(damage)); - damage = 0; - } - } - - void KilledUnit(Unit* victim) override - { - if (victim->GetTypeId() == TYPEID_PLAYER) - Talk(SAY_VALANAR_KILL); - } - - void DoAction(int32 action) override - { - switch (action) - { - case ACTION_STAND_UP: - me->RemoveAurasDueToSpell(SPELL_FEIGN_DEATH); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_PC); - me->RemoveFlag(OBJECT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD); - me->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH); - me->ForceValuesUpdateAtIndex(UNIT_NPC_FLAGS); // was in sniff. don't ask why - me->m_Events.AddEvent(new StandUpEvent(*me), me->m_Events.CalculateTime(1000)); - break; - case ACTION_CAST_INVOCATION: - Talk(SAY_VALANAR_INVOCATION); - DoCast(me, SPELL_INVOCATION_VISUAL_ACTIVE, true); - _isEmpowered = true; - break; - case ACTION_REMOVE_INVOCATION: - me->SetHealth(_spawnHealth); - me->RemoveAurasDueToSpell(SPELL_INVOCATION_VISUAL_ACTIVE); - me->RemoveAurasDueToSpell(SPELL_INVOCATION_OF_BLOOD_VALANAR); - _isEmpowered = false; - break; - default: - break; - } - } - - bool CheckInRoom() override - { - if (!CheckBoundary(me)) - { - EnterEvadeMode(); - if (Creature* keleseth = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_PRINCE_KELESETH_GUID))) - keleseth->AI()->EnterEvadeMode(); - - if (Creature* taldaram = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_PRINCE_TALDARAM_GUID))) - taldaram->AI()->EnterEvadeMode(); - - return false; - } - - return true; - } - void UpdateAI(uint32 diff) override { - if (!UpdateVictim() || !CheckInRoom()) + if (!UpdateVictim()) return; events.Update(diff); @@ -1000,7 +849,7 @@ class boss_prince_valanar_icc : public CreatureScript switch (eventId) { case EVENT_BERSERK: - DoCast(me, SPELL_BERSERK); + DoCastSelf(SPELL_BERSERK); Talk(SAY_VALANAR_BERSERK); break; case EVENT_KINETIC_BOMB: @@ -1009,20 +858,20 @@ class boss_prince_valanar_icc : public CreatureScript DoCast(target, SPELL_KINETIC_BOMB_TARGET); Talk(SAY_VALANAR_SPECIAL); } - events.ScheduleEvent(EVENT_KINETIC_BOMB, urand(18000, 24000)); + events.Repeat(Seconds(18), Seconds(24)); break; case EVENT_SHOCK_VORTEX: if (_isEmpowered) { - DoCast(me, SPELL_EMPOWERED_SHOCK_VORTEX); + DoCastSelf(SPELL_EMPOWERED_SHOCK_VORTEX); Talk(EMOTE_VALANAR_SHOCK_VORTEX); - events.ScheduleEvent(EVENT_SHOCK_VORTEX, 30000); + events.Repeat(Seconds(30)); } else { if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true)) DoCast(target, SPELL_SHOCK_VORTEX); - events.ScheduleEvent(EVENT_SHOCK_VORTEX, urand(18000, 23000)); + events.Repeat(Seconds(18), Seconds(23)); } break; default: @@ -1035,10 +884,6 @@ class boss_prince_valanar_icc : public CreatureScript DoMeleeAttackIfReady(); } - - private: - uint32 _spawnHealth; - bool _isEmpowered; }; CreatureAI* GetAI(Creature* creature) const override @@ -1052,25 +897,15 @@ class npc_blood_queen_lana_thel : public CreatureScript public: npc_blood_queen_lana_thel() : CreatureScript("npc_blood_queen_lana_thel") { } - struct npc_blood_queen_lana_thelAI : public ScriptedAI + struct npc_blood_queen_lana_thelAI : public PassiveAI { - npc_blood_queen_lana_thelAI(Creature* creature) : ScriptedAI(creature) - { - _introDone = false; - _instance = creature->GetInstanceScript(); - } + npc_blood_queen_lana_thelAI(Creature* creature) : PassiveAI(creature), _instance(creature->GetInstanceScript()) { } void Reset() override { _events.Reset(); me->SetDisableGravity(true); - if (_instance->GetBossState(DATA_BLOOD_PRINCE_COUNCIL) == DONE) - { - me->SetVisible(false); - _introDone = true; - } - else - me->SetVisible(true); + _instance->GetBossState(DATA_BLOOD_PRINCE_COUNCIL) != DONE ? me->SetVisible(true) : me->SetVisible(false); } void DoAction(int32 action) override @@ -1078,19 +913,15 @@ class npc_blood_queen_lana_thel : public CreatureScript switch (action) { case ACTION_START_INTRO: - if (!_introDone) + Talk(SAY_INTRO_1); + _events.SetPhase(1); + _events.ScheduleEvent(EVENT_INTRO_1, Seconds(14)); + // summon a visual trigger + if (Creature* summon = DoSummon(NPC_FLOATING_TRIGGER, triggerPos, 15000, TEMPSUMMON_TIMED_DESPAWN)) { - _introDone = true; - Talk(SAY_INTRO_1); - _events.SetPhase(1); - _events.ScheduleEvent(EVENT_INTRO_1, 14000); - // summon a visual trigger - if (Creature* summon = DoSummon(NPC_FLOATING_TRIGGER, triggerPos, 15000, TEMPSUMMON_TIMED_DESPAWN)) - { - summon->CastSpell(summon, SPELL_OOC_INVOCATION_VISUAL, true); - summon->SetSpeedRate(MOVE_FLIGHT, 0.15f); // todo: creature is swimming, check if this is blizzlike or not. - summon->GetMotionMaster()->MovePoint(0, triggerEndPos); - } + summon->CastSpell(summon, SPELL_OOC_INVOCATION_VISUAL, true); + summon->SetSpeedRate(MOVE_RUN, 0.14f); + summon->GetMotionMaster()->MovePoint(0, triggerEndPos); } break; default: @@ -1117,25 +948,14 @@ class npc_blood_queen_lana_thel : public CreatureScript me->GetMotionMaster()->MovePoint(POINT_INTRO_DESPAWN, introFinalPos); _events.Reset(); - // remove Feign Death from princes - if (Creature* keleseth = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_PRINCE_KELESETH_GUID))) - keleseth->AI()->DoAction(ACTION_STAND_UP); - - if (Creature* taldaram = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_PRINCE_TALDARAM_GUID))) - taldaram->AI()->DoAction(ACTION_STAND_UP); - - if (Creature* valanar = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_PRINCE_VALANAR_GUID))) - { - valanar->AI()->DoAction(ACTION_STAND_UP); - valanar->SetHealth(valanar->GetMaxHealth()); - } + if (Creature* controller = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_BLOOD_PRINCES_CONTROL))) + controller->AI()->DoAction(ACTION_INTRO_DONE); } } private: EventMap _events; InstanceScript* _instance; - bool _introDone; }; CreatureAI* GetAI(Creature* creature) const override @@ -1151,18 +971,15 @@ class npc_ball_of_flame : public CreatureScript struct npc_ball_of_flameAI : public ScriptedAI { - npc_ball_of_flameAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) - { - _despawnTimer = 0; - } + npc_ball_of_flameAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } void Reset() override { - me->CastSpell(me, SPELL_BALL_OF_FLAMES_VISUAL, true); + DoCastSelf(SPELL_BALL_OF_FLAMES_VISUAL, true); if (me->GetEntry() == NPC_BALL_OF_INFERNO_FLAME) { - me->CastSpell(me, SPELL_BALL_OF_FLAMES_PROC, true); - me->CastSpell(me, SPELL_BALL_OF_FLAMES_PERIODIC, true); + DoCastSelf(SPELL_BALL_OF_FLAMES_PROC, true); + DoCastSelf(SPELL_BALL_OF_FLAMES_PERIODIC, true); } } @@ -1171,8 +988,11 @@ class npc_ball_of_flame : public CreatureScript if (type == CHASE_MOTION_TYPE && id == _chaseGUID.GetCounter() && !_chaseGUID.IsEmpty()) { me->RemoveAurasDueToSpell(SPELL_BALL_OF_FLAMES_PERIODIC); - DoCast(me, SPELL_FLAMES); - _despawnTimer = 1000; + DoCastSelf(SPELL_FLAMES); + _scheduler.Schedule(Seconds(2), [this](TaskContext /*context*/) + { + DoCastSelf(SPELL_FLAME_SPHERE_DEATH_EFFECT); + }); _chaseGUID.Clear(); } } @@ -1205,22 +1025,13 @@ class npc_ball_of_flame : public CreatureScript void UpdateAI(uint32 diff) override { - if (!_despawnTimer) - return; - - if (_despawnTimer <= diff) - { - _despawnTimer = 0; - DoCast(me, SPELL_FLAME_SPHERE_DEATH_EFFECT); - } - else - _despawnTimer -= diff; + _scheduler.Update(diff); } private: ObjectGuid _chaseGUID; InstanceScript* _instance; - uint32 _despawnTimer; + TaskScheduler _scheduler; }; CreatureAI* GetAI(Creature* creature) const override @@ -1236,19 +1047,14 @@ class npc_kinetic_bomb : public CreatureScript struct npc_kinetic_bombAI : public ScriptedAI { - npc_kinetic_bombAI(Creature* creature) : ScriptedAI(creature) - { - _x = 0.f; - _y = 0.f; - _groundZ = 0.f; - } + npc_kinetic_bombAI(Creature* creature) : ScriptedAI(creature), _x(0.f), _y(0.f), _groundZ(0.f) { } void Reset() override { _events.Reset(); me->SetWalk(true); - me->CastSpell(me, SPELL_UNSTABLE, true); - me->CastSpell(me, SPELL_KINETIC_BOMB_VISUAL, true); + DoCastSelf(SPELL_UNSTABLE, true); + DoCastSelf(SPELL_KINETIC_BOMB_VISUAL, true); me->SetReactState(REACT_PASSIVE); me->GetPosition(_x, _y, _groundZ); me->DespawnOrUnsummon(60000); @@ -1258,12 +1064,16 @@ class npc_kinetic_bomb : public CreatureScript void DoAction(int32 action) override { if (action == SPELL_KINETIC_BOMB_EXPLOSION) - _events.ScheduleEvent(EVENT_BOMB_DESPAWN, 1000); + _events.ScheduleEvent(EVENT_BOMB_DESPAWN, Seconds(1)); + else if (action == ACTION_KINETIC_BOMB_JUMP) { if (!me->HasAura(SPELL_KINETIC_BOMB_KNOCKBACK)) - me->GetMotionMaster()->MoveCharge(_x, _y, me->GetPositionZ() + 100.0f, me->GetSpeed(MOVE_RUN), 0); - _events.RescheduleEvent(EVENT_CONTINUE_FALLING, 3000); + { + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveCharge(_x, _y, me->GetPositionZ() + 100.0f, me->GetSpeed(MOVE_RUN), POINT_KINETIC_BOMB_IMPACT); + } + _events.RescheduleEvent(EVENT_CONTINUE_FALLING, Seconds(3)); } } @@ -1280,7 +1090,8 @@ class npc_kinetic_bomb : public CreatureScript me->DespawnOrUnsummon(5000); break; case EVENT_CONTINUE_FALLING: - me->GetMotionMaster()->MoveCharge(_x, _y, _groundZ, me->GetSpeed(MOVE_WALK), POINT_KINETIC_BOMB_IMPACT); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveCharge(_x, _y, _groundZ, me->GetSpeed(MOVE_RUN), POINT_KINETIC_BOMB_IMPACT); break; default: break; @@ -1308,21 +1119,31 @@ class npc_dark_nucleus : public CreatureScript struct npc_dark_nucleusAI : public ScriptedAI { - npc_dark_nucleusAI(Creature* creature) : ScriptedAI(creature) - { - _lockedTarget = false; - _targetAuraCheck = 0; - } + npc_dark_nucleusAI(Creature* creature) : ScriptedAI(creature) { } void Reset() override { me->SetReactState(REACT_DEFENSIVE); - me->CastSpell(me, SPELL_SHADOW_RESONANCE_AURA, true); + DoCastSelf(SPELL_SHADOW_RESONANCE_AURA, true); } void EnterCombat(Unit* who) override { - _targetAuraCheck = 1000; + _scheduler.Schedule(Seconds(1), [this](TaskContext targetAuraCheck) + { + if (Unit* victim = me->GetVictim()) + { + if (me->GetDistance(victim) < 15.0f && !victim->HasAura(SPELL_SHADOW_RESONANCE_RESIST, me->GetGUID())) + { + DoCast(victim, SPELL_SHADOW_RESONANCE_RESIST); + me->ClearUnitState(UNIT_STATE_CASTING); + } + else + MoveInLineOfSight(me->GetVictim()); + } + targetAuraCheck.Repeat(); + }); + if (me->GetDistance(who) >= 15.0f) { DoStartMovement(who); @@ -1333,11 +1154,6 @@ class npc_dark_nucleus : public CreatureScript me->ClearUnitState(UNIT_STATE_CASTING); } - void MoveInLineOfSight(Unit* who) override - { - ScriptedAI::MoveInLineOfSight(who); - } - void DamageTaken(Unit* attacker, uint32& /*damage*/) override { if (attacker == me) @@ -1352,28 +1168,11 @@ class npc_dark_nucleus : public CreatureScript if (!UpdateVictim()) return; - if (_targetAuraCheck <= diff) - { - _targetAuraCheck = 1000; - if (Unit* victim = me->GetVictim()) - { - if (me->GetDistance(victim) < 15.0f && - !victim->HasAura(SPELL_SHADOW_RESONANCE_RESIST, me->GetGUID())) - { - DoCast(victim, SPELL_SHADOW_RESONANCE_RESIST); - me->ClearUnitState(UNIT_STATE_CASTING); - } - else - MoveInLineOfSight(me->GetVictim()); - } - } - else - _targetAuraCheck -= diff; + _scheduler.Update(diff); } private: - uint32 _targetAuraCheck; - bool _lockedTarget; + TaskScheduler _scheduler; }; CreatureAI* GetAI(Creature* creature) const override @@ -1382,6 +1181,7 @@ class npc_dark_nucleus : public CreatureScript } }; +// 71806 - Glittering Sparks class spell_taldaram_glittering_sparks : public SpellScriptLoader { public: @@ -1409,6 +1209,8 @@ class spell_taldaram_glittering_sparks : public SpellScriptLoader } }; +/* 71718 - Conjure Flame + 72040 - Conjure Empowered Flame */ class spell_taldaram_summon_flame_ball : public SpellScriptLoader { public: @@ -1436,6 +1238,8 @@ class spell_taldaram_summon_flame_ball : public SpellScriptLoader } }; +/* 55891 - Flame Sphere Spawn Effect + 55947 - Flame Sphere Death Effect */ class spell_taldaram_flame_ball_visual : public SpellScriptLoader { public: @@ -1452,6 +1256,11 @@ class spell_taldaram_flame_ball_visual : public SpellScriptLoader return false; } + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_BALL_OF_FLAMES }); + } + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { Creature* target = GetTarget()->ToCreature(); @@ -1480,6 +1289,10 @@ class spell_taldaram_flame_ball_visual : public SpellScriptLoader } }; +/* 71756 - Ball of Flames Proc + 72782 - Ball of Flames Proc + 72783 - Ball of Flames Proc + 72784 - Ball of Flames Proc */ class spell_taldaram_ball_of_inferno_flame : public SpellScriptLoader { public: @@ -1527,7 +1340,7 @@ class spell_taldaram_ball_of_inferno_flame : public SpellScriptLoader } }; -// 72080 - Kinetic Bomb (Valanar) +// 72080 - Kinetic Bomb class spell_valanar_kinetic_bomb : public SpellScriptLoader { public: @@ -1553,6 +1366,11 @@ class spell_valanar_kinetic_bomb : public SpellScriptLoader { PrepareAuraScript(spell_valanar_kinetic_bomb_AuraScript); + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_KINETIC_BOMB_EXPLOSION, SPELL_KINETIC_BOMB_VISUAL }); + } + void HandleDummyTick(AuraEffect const* /*aurEff*/) { Unit* target = GetTarget(); @@ -1585,6 +1403,7 @@ class spell_valanar_kinetic_bomb : public SpellScriptLoader } }; +// 72087 - Kinetic Bomb Knockback class spell_valanar_kinetic_bomb_knockback : public SpellScriptLoader { public: @@ -1615,6 +1434,7 @@ class spell_valanar_kinetic_bomb_knockback : public SpellScriptLoader } }; +// 72054 - Kinetic Bomb Visual class spell_valanar_kinetic_bomb_absorb : public SpellScriptLoader { public: @@ -1643,6 +1463,7 @@ class spell_valanar_kinetic_bomb_absorb : public SpellScriptLoader } }; +// 73001 - Shadow Prison class spell_blood_council_shadow_prison : public SpellScriptLoader { public: @@ -1652,10 +1473,15 @@ class spell_blood_council_shadow_prison : public SpellScriptLoader { PrepareAuraScript(spell_blood_council_shadow_prison_AuraScript); + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_SHADOW_PRISON_DAMAGE }); + } + void HandleDummyTick(AuraEffect const* aurEff) { if (GetTarget()->isMoving()) - GetTarget()->CastSpell(GetTarget(), SPELL_SHADOW_PRISON_DAMAGE, true, NULL, aurEff); + GetTarget()->CastSpell(GetTarget(), SPELL_SHADOW_PRISON_DAMAGE, true, nullptr, aurEff); } void Register() override @@ -1670,6 +1496,7 @@ class spell_blood_council_shadow_prison : public SpellScriptLoader } }; +// 72999 - Shadow Prison class spell_blood_council_shadow_prison_damage : public SpellScriptLoader { public: @@ -1706,8 +1533,8 @@ class at_blood_prince_council_start_intro : public AreaTriggerScript bool OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/, bool /*entered*/) override { if (InstanceScript* instance = player->GetInstanceScript()) - if (Creature* bloodQueen = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_BLOOD_QUEEN_LANA_THEL_COUNCIL))) - bloodQueen->AI()->DoAction(ACTION_START_INTRO); + if (Creature* controller = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_BLOOD_PRINCES_CONTROL))) + controller->AI()->DoAction(ACTION_START_INTRO); return true; } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h index c52e6ab1787..2f4dd00fea2 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h +++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h @@ -97,9 +97,9 @@ enum ICDataTypes DATA_PUTRICIDE_TABLE = 16, DATA_NAUSEA_ACHIEVEMENT = 17, DATA_ORB_WHISPERER_ACHIEVEMENT = 18, - DATA_PRINCE_KELESETH_GUID = 19, - DATA_PRINCE_TALDARAM_GUID = 20, - DATA_PRINCE_VALANAR_GUID = 21, + DATA_PRINCE_KELESETH = 19, + DATA_PRINCE_TALDARAM = 20, + DATA_PRINCE_VALANAR = 21, DATA_BLOOD_PRINCES_CONTROL = 22, DATA_SINDRAGOSA_FROSTWYRMS = 23, DATA_SPINESTALKER = 24, diff --git a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp index c70adae71e1..87dc5f0ee77 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp @@ -769,11 +769,11 @@ class instance_icecrown_citadel : public InstanceMapScript return ProfessorPutricideGUID; case DATA_PUTRICIDE_TABLE: return PutricideTableGUID; - case DATA_PRINCE_KELESETH_GUID: + case DATA_PRINCE_KELESETH: return BloodCouncilGUIDs[0]; - case DATA_PRINCE_TALDARAM_GUID: + case DATA_PRINCE_TALDARAM: return BloodCouncilGUIDs[1]; - case DATA_PRINCE_VALANAR_GUID: + case DATA_PRINCE_VALANAR: return BloodCouncilGUIDs[2]; case DATA_BLOOD_PRINCES_CONTROL: return BloodCouncilControllerGUID; |