diff options
-rw-r--r-- | src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp | 2124 |
1 files changed, 974 insertions, 1150 deletions
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp index 0f5c64fb1ed..73b452e90de 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp @@ -223,942 +223,874 @@ class FrostBeaconSelector : NonTankTargetSelector } }; -class boss_sindragosa : public CreatureScript +struct boss_sindragosa : public BossAI { - public: - boss_sindragosa() : CreatureScript("boss_sindragosa") { } + boss_sindragosa(Creature* creature) : BossAI(creature, DATA_SINDRAGOSA) + { + Initialize(); + } + + void Initialize() + { + _mysticBuffetStack = 0; + _isInAirPhase = false; + _isThirdPhase = false; + } - struct boss_sindragosaAI : public BossAI + void Reset() override + { + BossAI::Reset(); + DoCastSelf(SPELL_TANK_MARKER, true); + events.ScheduleEvent(EVENT_BERSERK, 10min); + events.ScheduleEvent(EVENT_CLEAVE, 10s, EVENT_GROUP_LAND_PHASE); + events.ScheduleEvent(EVENT_TAIL_SMASH, 20s, EVENT_GROUP_LAND_PHASE); + events.ScheduleEvent(EVENT_FROST_BREATH, 8s, 12s, EVENT_GROUP_LAND_PHASE); + events.ScheduleEvent(EVENT_UNCHAINED_MAGIC, 9s, 14s, EVENT_GROUP_LAND_PHASE); + events.ScheduleEvent(EVENT_ICY_GRIP, 33500ms, EVENT_GROUP_LAND_PHASE); + events.ScheduleEvent(EVENT_AIR_PHASE, 50s); + Initialize(); + + if (instance->GetData(DATA_SINDRAGOSA_INTRO)) { - boss_sindragosaAI(Creature* creature) : BossAI(creature, DATA_SINDRAGOSA) - { - Initialize(); - } + me->SetCanFly(true); + me->SetDisableGravity(true); + } + } - void Initialize() - { - _mysticBuffetStack = 0; - _isInAirPhase = false; - _isThirdPhase = false; - } + void JustDied(Unit* /* killer */) override + { + _JustDied(); + Talk(SAY_DEATH); - void Reset() override - { - BossAI::Reset(); - DoCast(me, SPELL_TANK_MARKER, true); - events.ScheduleEvent(EVENT_BERSERK, 10min); - events.ScheduleEvent(EVENT_CLEAVE, 10s, EVENT_GROUP_LAND_PHASE); - events.ScheduleEvent(EVENT_TAIL_SMASH, 20s, EVENT_GROUP_LAND_PHASE); - events.ScheduleEvent(EVENT_FROST_BREATH, 8s, 12s, EVENT_GROUP_LAND_PHASE); - events.ScheduleEvent(EVENT_UNCHAINED_MAGIC, 9s, 14s, EVENT_GROUP_LAND_PHASE); - events.ScheduleEvent(EVENT_ICY_GRIP, 33500ms, EVENT_GROUP_LAND_PHASE); - events.ScheduleEvent(EVENT_AIR_PHASE, 50s); - Initialize(); - - if (instance->GetData(DATA_SINDRAGOSA_INTRO)) - { - me->SetCanFly(true); - me->SetDisableGravity(true); - } - } + if (Is25ManRaid() && me->HasAura(SPELL_SHADOWS_FATE)) + DoCastAOE(SPELL_FROST_INFUSION_CREDIT, true); - void JustDied(Unit* /* killer */) override - { - _JustDied(); - Talk(SAY_DEATH); + } - if (Is25ManRaid() && me->HasAura(SPELL_SHADOWS_FATE)) - DoCastAOE(SPELL_FROST_INFUSION_CREDIT, true); + void JustEngagedWith(Unit* victim) override + { + if (!instance->CheckRequiredBosses(DATA_SINDRAGOSA, victim->ToPlayer())) + { + EnterEvadeMode(EVADE_REASON_SEQUENCE_BREAK); + instance->DoCastSpellOnPlayers(LIGHT_S_HAMMER_TELEPORT); + return; + } - } + DoCastSelf(SPELL_FROST_AURA); + DoCastSelf(SPELL_PERMAEATING_CHILL); + Talk(SAY_AGGRO); + instance->SetBossState(DATA_SINDRAGOSA, IN_PROGRESS); + me->SetCombatPulseDelay(5); + me->setActive(true); + me->SetFarVisible(true); + DoZoneInCombat(); + } - void JustEngagedWith(Unit* victim) override - { - if (!instance->CheckRequiredBosses(DATA_SINDRAGOSA, victim->ToPlayer())) - { - EnterEvadeMode(EVADE_REASON_SEQUENCE_BREAK); - instance->DoCastSpellOnPlayers(LIGHT_S_HAMMER_TELEPORT); - return; - } + void EnterEvadeMode(EvadeReason why) override + { + if (_isInAirPhase && why == EVADE_REASON_BOUNDARY) + return; + BossAI::EnterEvadeMode(why); + } - DoCast(me, SPELL_FROST_AURA); - DoCast(me, SPELL_PERMAEATING_CHILL); - Talk(SAY_AGGRO); - instance->SetBossState(DATA_SINDRAGOSA, IN_PROGRESS); - me->SetCombatPulseDelay(5); - me->setActive(true); - me->SetFarVisible(true); - DoZoneInCombat(); - } + void JustReachedHome() override + { + BossAI::JustReachedHome(); + instance->SetBossState(DATA_SINDRAGOSA, FAIL); + me->SetCanFly(false); + me->SetDisableGravity(false); + me->SetAnimTier(UnitBytes1_Flags(UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER), false); + me->SetReactState(REACT_DEFENSIVE); + } - void EnterEvadeMode(EvadeReason why) override - { - if (_isInAirPhase && why == EVADE_REASON_BOUNDARY) - return; - BossAI::EnterEvadeMode(why); - } + void KilledUnit(Unit* victim) override + { + if (victim->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_KILL); + } + + void DoAction(int32 action) override + { + if (action == ACTION_START_FROSTWYRM) + { + + instance->SetData(DATA_SINDRAGOSA_INTRO, 0); + if (TempSummon* summon = me->ToTempSummon()) + summon->SetTempSummonType(TEMPSUMMON_DEAD_DESPAWN); + + if (me->isDead()) + return; + + me->setActive(true); + me->SetFarVisible(true); + me->SetCanFly(true); + me->SetDisableGravity(true); + me->SetAnimTier(UnitBytes1_Flags(UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER), false); + me->SetSpeedRate(MOVE_FLIGHT, 4.0f); + me->AddUnitFlag(UNIT_FLAG_NON_ATTACKABLE); + Milliseconds moveTime = Milliseconds(uint64(me->GetExactDist(&SindragosaFlyPos) / (me->GetSpeed(MOVE_FLIGHT) * 0.001f))); + me->m_Events.AddEvent(new FrostwyrmLandEvent(*me, SindragosaLandPos), me->m_Events.CalculateTime(moveTime + 250ms)); + me->GetMotionMaster()->MovePoint(POINT_FROSTWYRM_FLY_IN, SindragosaFlyPos); + DoCastSelf(SPELL_SINDRAGOSA_S_FURY); + } + } + + uint32 GetData(uint32 type) const override + { + switch (type) + { + case DATA_MYSTIC_BUFFET_STACK: + return _mysticBuffetStack; + case DATA_IS_THIRD_PHASE: + return _isThirdPhase; + default: + return 0xFFFFFFFF; + } + } + + void MovementInform(uint32 type, uint32 point) override + { + if (type != POINT_MOTION_TYPE && type != EFFECT_MOTION_TYPE) + return; - void JustReachedHome() override + switch (point) + { + case POINT_FROSTWYRM_LAND: + me->setActive(false); + me->SetFarVisible(false); + me->SetCanFly(false); + me->SetDisableGravity(false); + me->SetAnimTier(UNIT_BYTE1_FLAG_NONE, false); + me->SetHomePosition(SindragosaLandPos); + me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE); + me->SetSpeedRate(MOVE_FLIGHT, 2.5f); + + // Sindragosa enters combat as soon as she lands + DoZoneInCombat(); + break; + case POINT_TAKEOFF: + events.ScheduleEvent(EVENT_AIR_MOVEMENT, 1ms); + break; + case POINT_AIR_PHASE: + { + CastSpellExtraArgs args(TRIGGERED_FULL_MASK); + args.AddSpellMod(SPELLVALUE_MAX_TARGETS, RAID_MODE<int32>(2, 5, 2, 6)); + me->CastSpell(nullptr, SPELL_ICE_TOMB_TARGET, args); + me->SetFacingTo(float(M_PI), true); + events.ScheduleEvent(EVENT_AIR_MOVEMENT_FAR, 1ms); + events.ScheduleEvent(EVENT_FROST_BOMB, 9s); + break; + } + case POINT_AIR_PHASE_FAR: + me->SetFacingTo(float(M_PI), true); + events.ScheduleEvent(EVENT_LAND, 30s); + break; + case POINT_LAND: + events.ScheduleEvent(EVENT_LAND_GROUND, 1ms); + break; + case POINT_LAND_GROUND: { - BossAI::JustReachedHome(); - instance->SetBossState(DATA_SINDRAGOSA, FAIL); me->SetCanFly(false); me->SetDisableGravity(false); - me->SetAnimTier(UnitBytes1_Flags(UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER), false); + me->SetAnimTier(UNIT_BYTE1_FLAG_NONE, false); me->SetReactState(REACT_DEFENSIVE); - } - void KilledUnit(Unit* victim) override - { - if (victim->GetTypeId() == TYPEID_PLAYER) - Talk(SAY_KILL); + _isInAirPhase = false; + // trigger Asphyxiation + EntryCheckPredicate pred(NPC_ICE_TOMB); + summons.DoAction(ACTION_TRIGGER_ASPHYXIATION, pred); + break; } + default: + break; + } + } - void DoAction(int32 action) override - { - if (action == ACTION_START_FROSTWYRM) - { + void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/) override + { + if (!_isThirdPhase && !HealthAbovePct(35)) + { + events.CancelEvent(EVENT_AIR_PHASE); + events.ScheduleEvent(EVENT_THIRD_PHASE_CHECK, 1s); + _isThirdPhase = true; + } + } + + void JustSummoned(Creature* summon) override + { + summons.Summon(summon); + if (summon->GetEntry() == NPC_FROST_BOMB) + { + summon->CastSpell(summon, SPELL_FROST_BOMB_VISUAL, true); + summon->CastSpell(summon, SPELL_BIRTH_NO_VISUAL, true); + summon->m_Events.AddEvent(new FrostBombExplosion(summon, me->GetGUID()), summon->m_Events.CalculateTime(5500ms)); + } + } + + void SummonedCreatureDespawn(Creature* summon) override + { + BossAI::SummonedCreatureDespawn(summon); + if (summon->GetEntry() == NPC_ICE_TOMB) + summon->AI()->JustDied(summon); + } + + void SpellHitTarget(WorldObject* target, SpellInfo const* spellInfo) override + { + Unit* unitTarget = target->ToUnit(); + if (!unitTarget) + return; + + if (70127 == spellInfo->Id) + if (Aura const* mysticBuffet = unitTarget->GetAura(spellInfo->Id)) + _mysticBuffetStack = std::max<uint8>(_mysticBuffetStack, mysticBuffet->GetStackAmount()); + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; - instance->SetData(DATA_SINDRAGOSA_INTRO, 0); - if (TempSummon* summon = me->ToTempSummon()) - summon->SetTempSummonType(TEMPSUMMON_DEAD_DESPAWN); + events.Update(diff); - if (me->isDead()) - return; + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - me->setActive(true); - me->SetFarVisible(true); + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_BERSERK: + Talk(EMOTE_BERSERK_RAID); + Talk(SAY_BERSERK); + DoCastSelf(SPELL_BERSERK); + break; + case EVENT_CLEAVE: + DoCastVictim(SPELL_CLEAVE); + events.ScheduleEvent(EVENT_CLEAVE, 15s, 20s, EVENT_GROUP_LAND_PHASE); + break; + case EVENT_TAIL_SMASH: + DoCastSelf(SPELL_TAIL_SMASH); + events.ScheduleEvent(EVENT_TAIL_SMASH, 27s, 32s, EVENT_GROUP_LAND_PHASE); + break; + case EVENT_FROST_BREATH: + DoCastVictim(_isThirdPhase ? SPELL_FROST_BREATH_P2 : SPELL_FROST_BREATH_P1); + events.ScheduleEvent(EVENT_FROST_BREATH, 20s, 25s, EVENT_GROUP_LAND_PHASE); + break; + case EVENT_UNCHAINED_MAGIC: + Talk(SAY_UNCHAINED_MAGIC); + DoCastSelf(SPELL_UNCHAINED_MAGIC); + events.ScheduleEvent(EVENT_UNCHAINED_MAGIC, 30s, 35s, EVENT_GROUP_LAND_PHASE); + break; + case EVENT_ICY_GRIP: + DoCastSelf(SPELL_ICY_GRIP); + events.ScheduleEvent(EVENT_BLISTERING_COLD, 1s, EVENT_GROUP_LAND_PHASE); + break; + case EVENT_BLISTERING_COLD: + Talk(EMOTE_WARN_BLISTERING_COLD); + DoCastSelf(SPELL_BLISTERING_COLD); + events.ScheduleEvent(EVENT_BLISTERING_COLD_YELL, 5s, EVENT_GROUP_LAND_PHASE); + break; + case EVENT_BLISTERING_COLD_YELL: + Talk(SAY_BLISTERING_COLD); + break; + case EVENT_AIR_PHASE: + { + _isInAirPhase = true; + Talk(SAY_AIR_PHASE); me->SetCanFly(true); me->SetDisableGravity(true); me->SetAnimTier(UnitBytes1_Flags(UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER), false); - me->SetSpeedRate(MOVE_FLIGHT, 4.0f); - me->AddUnitFlag(UNIT_FLAG_NON_ATTACKABLE); - Milliseconds moveTime = Milliseconds(uint64(me->GetExactDist(&SindragosaFlyPos) / (me->GetSpeed(MOVE_FLIGHT) * 0.001f))); - me->m_Events.AddEvent(new FrostwyrmLandEvent(*me, SindragosaLandPos), me->m_Events.CalculateTime(moveTime + 250ms)); - me->GetMotionMaster()->MovePoint(POINT_FROSTWYRM_FLY_IN, SindragosaFlyPos); - DoCast(me, SPELL_SINDRAGOSA_S_FURY); + me->SetReactState(REACT_PASSIVE); + me->AttackStop(); + Position pos; + pos.Relocate(me); + pos.m_positionZ += 17.0f; + me->GetMotionMaster()->MoveTakeoff(POINT_TAKEOFF, pos); + events.CancelEventGroup(EVENT_GROUP_LAND_PHASE); + events.ScheduleEvent(EVENT_AIR_PHASE, 110s); + break; } - } - - uint32 GetData(uint32 type) const override - { - switch (type) + case EVENT_AIR_MOVEMENT: + me->GetMotionMaster()->MovePoint(POINT_AIR_PHASE, SindragosaAirPos); + break; + case EVENT_AIR_MOVEMENT_FAR: + me->GetMotionMaster()->MovePoint(POINT_AIR_PHASE_FAR, SindragosaAirPosFar); + break; + case EVENT_ICE_TOMB: { - case DATA_MYSTIC_BUFFET_STACK: - return _mysticBuffetStack; - case DATA_IS_THIRD_PHASE: - return _isThirdPhase; - default: - return 0xFFFFFFFF; + CastSpellExtraArgs args(TRIGGERED_FULL_MASK); + args.AddSpellMod(SPELLVALUE_MAX_TARGETS, 1); + me->CastSpell(nullptr, SPELL_ICE_TOMB_TARGET, args); + events.ScheduleEvent(EVENT_ICE_TOMB, 16s, 23s); + break; } - } - - void MovementInform(uint32 type, uint32 point) override - { - if (type != POINT_MOTION_TYPE && type != EFFECT_MOTION_TYPE) - return; - - switch (point) + case EVENT_FROST_BOMB: { - case POINT_FROSTWYRM_LAND: - me->setActive(false); - me->SetFarVisible(false); - me->SetCanFly(false); - me->SetDisableGravity(false); - me->SetAnimTier(UNIT_BYTE1_FLAG_NONE, false); - me->SetHomePosition(SindragosaLandPos); - me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE); - me->SetSpeedRate(MOVE_FLIGHT, 2.5f); - - // Sindragosa enters combat as soon as she lands - DoZoneInCombat(); - break; - case POINT_TAKEOFF: - events.ScheduleEvent(EVENT_AIR_MOVEMENT, 1ms); - break; - case POINT_AIR_PHASE: - { - CastSpellExtraArgs args(TRIGGERED_FULL_MASK); - args.AddSpellMod(SPELLVALUE_MAX_TARGETS, RAID_MODE<int32>(2, 5, 2, 6)); - me->CastSpell(nullptr, SPELL_ICE_TOMB_TARGET, args); - me->SetFacingTo(float(M_PI), true); - events.ScheduleEvent(EVENT_AIR_MOVEMENT_FAR, 1ms); - events.ScheduleEvent(EVENT_FROST_BOMB, 9s); - break; - } - case POINT_AIR_PHASE_FAR: - me->SetFacingTo(float(M_PI), true); - events.ScheduleEvent(EVENT_LAND, 30s); - break; - case POINT_LAND: - events.ScheduleEvent(EVENT_LAND_GROUND, 1ms); - break; - case POINT_LAND_GROUND: - { - me->SetCanFly(false); - me->SetDisableGravity(false); - me->SetAnimTier(UNIT_BYTE1_FLAG_NONE, false); - me->SetReactState(REACT_DEFENSIVE); - - _isInAirPhase = false; - // trigger Asphyxiation - EntryCheckPredicate pred(NPC_ICE_TOMB); - summons.DoAction(ACTION_TRIGGER_ASPHYXIATION, pred); - break; - } - default: - break; + float destX, destY, destZ; + destX = float(rand_norm()) * 75.0f + 4350.0f; + destY = float(rand_norm()) * 75.0f + 2450.0f; + destZ = 205.0f; // random number close to ground, get exact in next call + me->UpdateGroundPositionZ(destX, destY, destZ); + me->CastSpell(Position{ destX, destY, destZ }, SPELL_FROST_BOMB_TRIGGER, false); + events.ScheduleEvent(EVENT_FROST_BOMB, 6s, 8s); + break; } - } - - void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/) override - { - if (!_isThirdPhase && !HealthAbovePct(35)) + case EVENT_LAND: { - events.CancelEvent(EVENT_AIR_PHASE); - events.ScheduleEvent(EVENT_THIRD_PHASE_CHECK, 1s); - _isThirdPhase = true; + events.CancelEvent(EVENT_FROST_BOMB); + me->GetMotionMaster()->MovePoint(POINT_LAND, SindragosaFlyInPos); + break; } - } - - void JustSummoned(Creature* summon) override - { - summons.Summon(summon); - if (summon->GetEntry() == NPC_FROST_BOMB) + case EVENT_LAND_GROUND: + events.ScheduleEvent(EVENT_CLEAVE, 13s, 15s, EVENT_GROUP_LAND_PHASE); + events.ScheduleEvent(EVENT_TAIL_SMASH, 19s, 23s, EVENT_GROUP_LAND_PHASE); + events.ScheduleEvent(EVENT_FROST_BREATH, 10s, 15s, EVENT_GROUP_LAND_PHASE); + events.ScheduleEvent(EVENT_UNCHAINED_MAGIC, 12s, 17s, EVENT_GROUP_LAND_PHASE); + events.ScheduleEvent(EVENT_ICY_GRIP, 35s, 40s, EVENT_GROUP_LAND_PHASE); + me->GetMotionMaster()->MoveLand(POINT_LAND_GROUND, SindragosaLandPos); + break; + case EVENT_THIRD_PHASE_CHECK: { - summon->CastSpell(summon, SPELL_FROST_BOMB_VISUAL, true); - summon->CastSpell(summon, SPELL_BIRTH_NO_VISUAL, true); - summon->m_Events.AddEvent(new FrostBombExplosion(summon, me->GetGUID()), summon->m_Events.CalculateTime(5500ms)); + if (!_isInAirPhase) + { + Talk(SAY_PHASE_2); + events.ScheduleEvent(EVENT_ICE_TOMB, 7s, 10s); + events.RescheduleEvent(EVENT_ICY_GRIP, 35s, 40s); + DoCastSelf(SPELL_MYSTIC_BUFFET, true); + } + else + events.ScheduleEvent(EVENT_THIRD_PHASE_CHECK, 5s); + break; } + default: + break; } - void SummonedCreatureDespawn(Creature* summon) override - { - BossAI::SummonedCreatureDespawn(summon); - if (summon->GetEntry() == NPC_ICE_TOMB) - summon->AI()->JustDied(summon); - } - - void SpellHitTarget(WorldObject* target, SpellInfo const* spellInfo) override - { - Unit* unitTarget = target->ToUnit(); - if (!unitTarget) - return; - - if (spellInfo->Id == 70127) - if (Aura const* mysticBuffet = unitTarget->GetAura(spellInfo->Id)) - _mysticBuffetStack = std::max<uint8>(_mysticBuffetStack, mysticBuffet->GetStackAmount()); - } + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + } - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; + DoMeleeAttackIfReady(); + } - events.Update(diff); +private: + uint8 _mysticBuffetStack; + bool _isInAirPhase; + bool _isThirdPhase; +}; - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; +struct npc_ice_tomb : public ScriptedAI +{ + npc_ice_tomb(Creature* creature) : ScriptedAI(creature) + { + _existenceCheckTimer = 0; + SetCombatMovement(false); + } - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_BERSERK: - Talk(EMOTE_BERSERK_RAID); - Talk(SAY_BERSERK); - DoCast(me, SPELL_BERSERK); - break; - case EVENT_CLEAVE: - DoCastVictim(SPELL_CLEAVE); - events.ScheduleEvent(EVENT_CLEAVE, 15s, 20s, EVENT_GROUP_LAND_PHASE); - break; - case EVENT_TAIL_SMASH: - DoCast(me, SPELL_TAIL_SMASH); - events.ScheduleEvent(EVENT_TAIL_SMASH, 27s, 32s, EVENT_GROUP_LAND_PHASE); - break; - case EVENT_FROST_BREATH: - DoCastVictim(_isThirdPhase ? SPELL_FROST_BREATH_P2 : SPELL_FROST_BREATH_P1); - events.ScheduleEvent(EVENT_FROST_BREATH, 20s, 25s, EVENT_GROUP_LAND_PHASE); - break; - case EVENT_UNCHAINED_MAGIC: - Talk(SAY_UNCHAINED_MAGIC); - DoCast(me, SPELL_UNCHAINED_MAGIC); - events.ScheduleEvent(EVENT_UNCHAINED_MAGIC, 30s, 35s, EVENT_GROUP_LAND_PHASE); - break; - case EVENT_ICY_GRIP: - DoCast(me, SPELL_ICY_GRIP); - events.ScheduleEvent(EVENT_BLISTERING_COLD, 1s, EVENT_GROUP_LAND_PHASE); - break; - case EVENT_BLISTERING_COLD: - Talk(EMOTE_WARN_BLISTERING_COLD); - DoCast(me, SPELL_BLISTERING_COLD); - events.ScheduleEvent(EVENT_BLISTERING_COLD_YELL, 5s, EVENT_GROUP_LAND_PHASE); - break; - case EVENT_BLISTERING_COLD_YELL: - Talk(SAY_BLISTERING_COLD); - break; - case EVENT_AIR_PHASE: - { - _isInAirPhase = true; - Talk(SAY_AIR_PHASE); - me->SetCanFly(true); - me->SetDisableGravity(true); - me->SetAnimTier(UnitBytes1_Flags(UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER), false); - me->SetReactState(REACT_PASSIVE); - me->AttackStop(); - Position pos; - pos.Relocate(me); - pos.m_positionZ += 17.0f; - me->GetMotionMaster()->MoveTakeoff(POINT_TAKEOFF, pos); - events.CancelEventGroup(EVENT_GROUP_LAND_PHASE); - events.ScheduleEvent(EVENT_AIR_PHASE, 110s); - break; - } - case EVENT_AIR_MOVEMENT: - me->GetMotionMaster()->MovePoint(POINT_AIR_PHASE, SindragosaAirPos); - break; - case EVENT_AIR_MOVEMENT_FAR: - me->GetMotionMaster()->MovePoint(POINT_AIR_PHASE_FAR, SindragosaAirPosFar); - break; - case EVENT_ICE_TOMB: - { - CastSpellExtraArgs args(TRIGGERED_FULL_MASK); - args.AddSpellMod(SPELLVALUE_MAX_TARGETS, 1); - me->CastSpell(nullptr, SPELL_ICE_TOMB_TARGET, args); - events.ScheduleEvent(EVENT_ICE_TOMB, 16s, 23s); - break; - } - case EVENT_FROST_BOMB: - { - float destX, destY, destZ; - destX = float(rand_norm()) * 75.0f + 4350.0f; - destY = float(rand_norm()) * 75.0f + 2450.0f; - destZ = 205.0f; // random number close to ground, get exact in next call - me->UpdateGroundPositionZ(destX, destY, destZ); - me->CastSpell(Position{ destX, destY, destZ }, SPELL_FROST_BOMB_TRIGGER, false); - events.ScheduleEvent(EVENT_FROST_BOMB, 6s, 8s); - break; - } - case EVENT_LAND: - { - events.CancelEvent(EVENT_FROST_BOMB); - me->GetMotionMaster()->MovePoint(POINT_LAND, SindragosaFlyInPos); - break; - } - case EVENT_LAND_GROUND: - events.ScheduleEvent(EVENT_CLEAVE, 13s, 15s, EVENT_GROUP_LAND_PHASE); - events.ScheduleEvent(EVENT_TAIL_SMASH, 19s, 23s, EVENT_GROUP_LAND_PHASE); - events.ScheduleEvent(EVENT_FROST_BREATH, 10s, 15s, EVENT_GROUP_LAND_PHASE); - events.ScheduleEvent(EVENT_UNCHAINED_MAGIC, 12s, 17s, EVENT_GROUP_LAND_PHASE); - events.ScheduleEvent(EVENT_ICY_GRIP, 35s, 40s, EVENT_GROUP_LAND_PHASE); - me->GetMotionMaster()->MoveLand(POINT_LAND_GROUND, SindragosaLandPos); - break; - case EVENT_THIRD_PHASE_CHECK: - { - if (!_isInAirPhase) - { - Talk(SAY_PHASE_2); - events.ScheduleEvent(EVENT_ICE_TOMB, 7s, 10s); - events.RescheduleEvent(EVENT_ICY_GRIP, 35s, 40s); - DoCast(me, SPELL_MYSTIC_BUFFET, true); - } - else - events.ScheduleEvent(EVENT_THIRD_PHASE_CHECK, 5s); - break; - } - default: - break; - } + void Reset() override + { + me->SetReactState(REACT_PASSIVE); + } - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - } + void SetGUID(ObjectGuid const& guid, int32 id) override + { + if (id == DATA_TRAPPED_PLAYER) + { + _trappedPlayerGUID = guid; + _existenceCheckTimer = 1000; + } + } - DoMeleeAttackIfReady(); - } + void DoAction(int32 action) override + { + if (action == ACTION_TRIGGER_ASPHYXIATION) + if (Player* player = ObjectAccessor::GetPlayer(*me, _trappedPlayerGUID)) + player->CastSpell(player, SPELL_ASPHYXIATION, true); + } - private: - uint8 _mysticBuffetStack; - bool _isInAirPhase; - bool _isThirdPhase; - }; + void JustDied(Unit* /*killer*/) override + { + me->RemoveAllGameObjects(); - CreatureAI* GetAI(Creature* creature) const override + if (Player* player = ObjectAccessor::GetPlayer(*me, _trappedPlayerGUID)) { - return GetIcecrownCitadelAI<boss_sindragosaAI>(creature); + _trappedPlayerGUID.Clear(); + player->RemoveAurasDueToSpell(SPELL_ICE_TOMB_DAMAGE); + player->RemoveAurasDueToSpell(SPELL_ASPHYXIATION); + player->RemoveAurasDueToSpell(SPELL_ICE_TOMB_UNTARGETABLE); } -}; + } -class npc_ice_tomb : public CreatureScript -{ - public: - npc_ice_tomb() : CreatureScript("npc_ice_tomb") { } + void UpdateAI(uint32 diff) override + { + if (!_trappedPlayerGUID) + return; - struct npc_ice_tombAI : public ScriptedAI + if (_existenceCheckTimer <= diff) { - npc_ice_tombAI(Creature* creature) : ScriptedAI(creature) + Player* player = ObjectAccessor::GetPlayer(*me, _trappedPlayerGUID); + if (!player || player->isDead() || !player->HasAura(SPELL_ICE_TOMB_DAMAGE)) { - _existenceCheckTimer = 0; - SetCombatMovement(false); + // Remove object + JustDied(me); + me->DespawnOrUnsummon(); + return; } + _existenceCheckTimer = 1000; + } + else + _existenceCheckTimer -= diff; + } - void Reset() override - { - me->SetReactState(REACT_PASSIVE); - } - - void SetGUID(ObjectGuid const& guid, int32 id) override - { - if (id == DATA_TRAPPED_PLAYER) - { - _trappedPlayerGUID = guid; - _existenceCheckTimer = 1000; - } - } - - void DoAction(int32 action) override - { - if (action == ACTION_TRIGGER_ASPHYXIATION) - if (Player* player = ObjectAccessor::GetPlayer(*me, _trappedPlayerGUID)) - player->CastSpell(player, SPELL_ASPHYXIATION, true); - } - - void JustDied(Unit* /*killer*/) override - { - me->RemoveAllGameObjects(); - - if (Player* player = ObjectAccessor::GetPlayer(*me, _trappedPlayerGUID)) - { - _trappedPlayerGUID.Clear(); - player->RemoveAurasDueToSpell(SPELL_ICE_TOMB_DAMAGE); - player->RemoveAurasDueToSpell(SPELL_ASPHYXIATION); - player->RemoveAurasDueToSpell(SPELL_ICE_TOMB_UNTARGETABLE); - } - } - - void UpdateAI(uint32 diff) override - { - if (!_trappedPlayerGUID) - return; - - if (_existenceCheckTimer <= diff) - { - Player* player = ObjectAccessor::GetPlayer(*me, _trappedPlayerGUID); - if (!player || player->isDead() || !player->HasAura(SPELL_ICE_TOMB_DAMAGE)) - { - // Remove object - JustDied(me); - me->DespawnOrUnsummon(); - return; - } - _existenceCheckTimer = 1000; - } - else - _existenceCheckTimer -= diff; - } +private: + ObjectGuid _trappedPlayerGUID; + uint32 _existenceCheckTimer; +}; - private: - ObjectGuid _trappedPlayerGUID; - uint32 _existenceCheckTimer; - }; +struct npc_spinestalker : public ScriptedAI +{ + npc_spinestalker(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()), _summoned(false) { } - CreatureAI* GetAI(Creature* creature) const override + void InitializeAI() override + { + // Increase add count + if (!me->isDead()) { - return GetIcecrownCitadelAI<npc_ice_tombAI>(creature); + _instance->SetGuidData(DATA_SINDRAGOSA_FROSTWYRMS, ObjectGuid::Create<HighGuid::Creature>(631, me->GetEntry(), me->GetSpawnId())); // this cannot be in Reset because reset also happens on evade + Reset(); } -}; + } -class npc_spinestalker : public CreatureScript -{ - public: - npc_spinestalker() : CreatureScript("npc_spinestalker") { } + void Reset() override + { + _events.Reset(); + _events.ScheduleEvent(EVENT_BELLOWING_ROAR, 20s, 25s); + _events.ScheduleEvent(EVENT_CLEAVE_SPINESTALKER, 10s, 15s); + _events.ScheduleEvent(EVENT_TAIL_SWEEP, 8s, 12s); - struct npc_spinestalkerAI : public ScriptedAI + if (!_summoned) { - npc_spinestalkerAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()), _summoned(false) - { - } + me->SetCanFly(true); + me->SetDisableGravity(true); + } + } - void InitializeAI() override - { - // Increase add count - if (!me->isDead()) - { - _instance->SetGuidData(DATA_SINDRAGOSA_FROSTWYRMS, ObjectGuid::Create<HighGuid::Creature>(631, me->GetEntry(), me->GetSpawnId())); // this cannot be in Reset because reset also happens on evade - Reset(); - } - } + void JustAppeared() override + { + ScriptedAI::JustAppeared(); + _instance->SetGuidData(DATA_SINDRAGOSA_FROSTWYRMS, ObjectGuid::Create<HighGuid::Creature>(631, me->GetEntry(), me->GetSpawnId())); // this cannot be in Reset because reset also happens on evade + } - void Reset() override - { - _events.Reset(); - _events.ScheduleEvent(EVENT_BELLOWING_ROAR, 20s, 25s); - _events.ScheduleEvent(EVENT_CLEAVE_SPINESTALKER, 10s, 15s); - _events.ScheduleEvent(EVENT_TAIL_SWEEP, 8s, 12s); + void JustDied(Unit* /*killer*/) override + { + _events.Reset(); + } - if (!_summoned) - { - me->SetCanFly(true); - me->SetDisableGravity(true); - } - } + void DoAction(int32 action) override + { + if (action == ACTION_START_FROSTWYRM) + { + if (_summoned) + return; + + _summoned = true; + if (me->isDead()) + return; + + me->setActive(true); + me->SetFarVisible(true); + me->SetSpeedRate(MOVE_FLIGHT, 2.0f); + me->AddUnitFlag(UNIT_FLAG_NON_ATTACKABLE); + Milliseconds moveTime = Milliseconds(uint64(me->GetExactDist(&SpinestalkerFlyPos) / (me->GetSpeed(MOVE_FLIGHT) * 0.001f))); + me->m_Events.AddEvent(new FrostwyrmLandEvent(*me, SpinestalkerLandPos), me->m_Events.CalculateTime(moveTime + 250ms)); + me->SetDefaultMovementType(IDLE_MOTION_TYPE); + me->GetMotionMaster()->MoveIdle(); + me->StopMoving(); + me->GetMotionMaster()->MovePoint(POINT_FROSTWYRM_FLY_IN, SpinestalkerFlyPos); + me->SetReactState(REACT_DEFENSIVE); + } + } - void JustAppeared() override - { - ScriptedAI::JustAppeared(); - _instance->SetGuidData(DATA_SINDRAGOSA_FROSTWYRMS, ObjectGuid::Create<HighGuid::Creature>(631, me->GetEntry(), me->GetSpawnId())); // this cannot be in Reset because reset also happens on evade - } + void MovementInform(uint32 type, uint32 point) override + { + if (type != EFFECT_MOTION_TYPE || point != POINT_FROSTWYRM_LAND) + return; + + me->setActive(false); + me->SetFarVisible(false); + me->SetCanFly(false); + me->SetDisableGravity(false); + me->SetAnimTier(UNIT_BYTE1_FLAG_NONE, false); + me->SetHomePosition(SpinestalkerLandPos); + me->SetFacingTo(SpinestalkerLandPos.GetOrientation()); + me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE); + me->SetReactState(REACT_AGGRESSIVE); + } - void JustDied(Unit* /*killer*/) override - { - _events.Reset(); - } + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; - void DoAction(int32 action) override - { - if (action == ACTION_START_FROSTWYRM) - { - if (_summoned) - return; - - _summoned = true; - if (me->isDead()) - return; - - me->setActive(true); - me->SetFarVisible(true); - me->SetSpeedRate(MOVE_FLIGHT, 2.0f); - me->AddUnitFlag(UNIT_FLAG_NON_ATTACKABLE); - Milliseconds moveTime = Milliseconds(uint64(me->GetExactDist(&SpinestalkerFlyPos) / (me->GetSpeed(MOVE_FLIGHT) * 0.001f))); - me->m_Events.AddEvent(new FrostwyrmLandEvent(*me, SpinestalkerLandPos), me->m_Events.CalculateTime(moveTime + 250ms)); - me->SetDefaultMovementType(IDLE_MOTION_TYPE); - me->GetMotionMaster()->MoveIdle(); - me->StopMoving(); - me->GetMotionMaster()->MovePoint(POINT_FROSTWYRM_FLY_IN, SpinestalkerFlyPos); - me->SetReactState(REACT_DEFENSIVE); - } - } + _events.Update(diff); - void MovementInform(uint32 type, uint32 point) override - { - if (type != EFFECT_MOTION_TYPE || point != POINT_FROSTWYRM_LAND) - return; + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - me->setActive(false); - me->SetFarVisible(false); - me->SetCanFly(false); - me->SetDisableGravity(false); - me->SetAnimTier(UNIT_BYTE1_FLAG_NONE, false); - me->SetHomePosition(SpinestalkerLandPos); - me->SetFacingTo(SpinestalkerLandPos.GetOrientation()); - me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE); - me->SetReactState(REACT_AGGRESSIVE); + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_BELLOWING_ROAR: + DoCastSelf(SPELL_BELLOWING_ROAR); + _events.ScheduleEvent(EVENT_BELLOWING_ROAR, 25s, 30s); + break; + case EVENT_CLEAVE_SPINESTALKER: + DoCastVictim(SPELL_CLEAVE_SPINESTALKER); + _events.ScheduleEvent(EVENT_CLEAVE_SPINESTALKER, 10s, 15s); + break; + case EVENT_TAIL_SWEEP: + DoCastSelf(SPELL_TAIL_SWEEP); + _events.ScheduleEvent(EVENT_TAIL_SWEEP, 22s, 25s); + break; + default: + break; } + } - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; + DoMeleeAttackIfReady(); + } - _events.Update(diff); +private: + EventMap _events; + InstanceScript* _instance; + bool _summoned; +}; - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; +struct npc_rimefang : public ScriptedAI +{ + npc_rimefang(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()), _summoned(false) + { + Initialize(); + } - while (uint32 eventId = _events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_BELLOWING_ROAR: - DoCast(me, SPELL_BELLOWING_ROAR); - _events.ScheduleEvent(EVENT_BELLOWING_ROAR, 25s, 30s); - break; - case EVENT_CLEAVE_SPINESTALKER: - DoCastVictim(SPELL_CLEAVE_SPINESTALKER); - _events.ScheduleEvent(EVENT_CLEAVE_SPINESTALKER, 10s, 15s); - break; - case EVENT_TAIL_SWEEP: - DoCast(me, SPELL_TAIL_SWEEP); - _events.ScheduleEvent(EVENT_TAIL_SWEEP, 22s, 25s); - break; - default: - break; - } - } + void Initialize() + { + _icyBlastCounter = 0; + } - DoMeleeAttackIfReady(); - } + void InitializeAI() override + { + // Increase add count + if (!me->isDead()) + { + _instance->SetGuidData(DATA_SINDRAGOSA_FROSTWYRMS, ObjectGuid::Create<HighGuid::Creature>(631, me->GetEntry(), me->GetSpawnId())); // this cannot be in Reset because reset also happens on evade + Reset(); + } + } - private: - EventMap _events; - InstanceScript* _instance; - bool _summoned; - }; + void Reset() override + { + _events.Reset(); + _events.ScheduleEvent(EVENT_FROST_BREATH_RIMEFANG, 12s, 15s); + _events.ScheduleEvent(EVENT_ICY_BLAST, 30s, 35s); + Initialize(); - CreatureAI* GetAI(Creature* creature) const override + if (!_summoned) { - return GetIcecrownCitadelAI<npc_spinestalkerAI>(creature); + me->SetCanFly(true); + me->SetDisableGravity(true); } -}; + } -class npc_rimefang : public CreatureScript -{ - public: - npc_rimefang() : CreatureScript("npc_rimefang_icc") { } + void JustAppeared() override + { + ScriptedAI::JustAppeared(); + _instance->SetGuidData(DATA_SINDRAGOSA_FROSTWYRMS, ObjectGuid::Create<HighGuid::Creature>(631, me->GetEntry(), me->GetSpawnId())); // this cannot be in Reset because reset also happens on evade + } - struct npc_rimefangAI : public ScriptedAI - { - npc_rimefangAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()), _summoned(false) - { - Initialize(); - } + void JustDied(Unit* /*killer*/) override + { + _events.Reset(); + } - void Initialize() - { - _icyBlastCounter = 0; - } + void DoAction(int32 action) override + { + if (action == ACTION_START_FROSTWYRM) + { + if (_summoned) + return; + + _summoned = true; + if (me->isDead()) + return; + + me->setActive(true); + me->SetFarVisible(true); + me->SetSpeedRate(MOVE_FLIGHT, 2.0f); + me->SetImmuneToPC(true); + Milliseconds moveTime = Milliseconds(uint64(me->GetExactDist(&RimefangFlyPos) / (me->GetSpeed(MOVE_FLIGHT) * 0.001f))); + me->m_Events.AddEvent(new FrostwyrmLandEvent(*me, RimefangLandPos), me->m_Events.CalculateTime(moveTime + 250ms)); + me->SetDefaultMovementType(IDLE_MOTION_TYPE); + me->GetMotionMaster()->MoveIdle(); + me->StopMoving(); + me->GetMotionMaster()->MovePoint(POINT_FROSTWYRM_FLY_IN, RimefangFlyPos); + me->SetReactState(REACT_DEFENSIVE); + } + } - void InitializeAI() override - { - // Increase add count - if (!me->isDead()) - { - _instance->SetGuidData(DATA_SINDRAGOSA_FROSTWYRMS, ObjectGuid::Create<HighGuid::Creature>(631, me->GetEntry(), me->GetSpawnId())); // this cannot be in Reset because reset also happens on evade - Reset(); - } - } + void MovementInform(uint32 type, uint32 point) override + { + if (type != EFFECT_MOTION_TYPE || point != POINT_FROSTWYRM_LAND) + return; + + me->setActive(false); + me->SetFarVisible(false); + me->SetCanFly(false); + me->SetDisableGravity(false); + me->SetAnimTier(UNIT_BYTE1_FLAG_NONE, false); + me->SetHomePosition(RimefangLandPos); + me->SetFacingTo(RimefangLandPos.GetOrientation()); + me->SetImmuneToPC(false); + me->SetReactState(REACT_AGGRESSIVE); + } - void Reset() override - { - _events.Reset(); - _events.ScheduleEvent(EVENT_FROST_BREATH_RIMEFANG, 12s, 15s); - _events.ScheduleEvent(EVENT_ICY_BLAST, 30s, 35s); - Initialize(); + void JustEngagedWith(Unit* /*victim*/) override + { + DoCastSelf(SPELL_FROST_AURA_RIMEFANG, true); + } - if (!_summoned) - { - me->SetCanFly(true); - me->SetDisableGravity(true); - } - } + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; - void JustAppeared() override - { - ScriptedAI::JustAppeared(); - _instance->SetGuidData(DATA_SINDRAGOSA_FROSTWYRMS, ObjectGuid::Create<HighGuid::Creature>(631, me->GetEntry(), me->GetSpawnId())); // this cannot be in Reset because reset also happens on evade - } + _events.Update(diff); - void JustDied(Unit* /*killer*/) override - { - _events.Reset(); - } + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - void DoAction(int32 action) override + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) { - if (action == ACTION_START_FROSTWYRM) + case EVENT_FROST_BREATH_RIMEFANG: + DoCastSelf(SPELL_FROST_BREATH); + _events.ScheduleEvent(EVENT_FROST_BREATH_RIMEFANG, 35s, 40s); + break; + case EVENT_ICY_BLAST: { - if (_summoned) - return; - - _summoned = true; - if (me->isDead()) - return; - - me->setActive(true); - me->SetFarVisible(true); - me->SetSpeedRate(MOVE_FLIGHT, 2.0f); - me->SetImmuneToPC(true); - Milliseconds moveTime = Milliseconds(uint64(me->GetExactDist(&RimefangFlyPos) / (me->GetSpeed(MOVE_FLIGHT) * 0.001f))); - me->m_Events.AddEvent(new FrostwyrmLandEvent(*me, RimefangLandPos), me->m_Events.CalculateTime(moveTime + 250ms)); - me->SetDefaultMovementType(IDLE_MOTION_TYPE); - me->GetMotionMaster()->MoveIdle(); - me->StopMoving(); + _icyBlastCounter = RAID_MODE<uint8>(5, 7, 6, 8); + me->SetReactState(REACT_PASSIVE); + me->AttackStop(); + me->SetCanFly(true); me->GetMotionMaster()->MovePoint(POINT_FROSTWYRM_FLY_IN, RimefangFlyPos); - me->SetReactState(REACT_DEFENSIVE); + Milliseconds moveTime = Milliseconds(uint64(me->GetExactDist(&RimefangFlyPos)/(me->GetSpeed(MOVE_FLIGHT)*0.001f))); + _events.ScheduleEvent(EVENT_ICY_BLAST, moveTime + 60s, moveTime + 70s); + _events.ScheduleEvent(EVENT_ICY_BLAST_CAST, moveTime + 250ms); + break; } - } - - void MovementInform(uint32 type, uint32 point) override - { - if (type != EFFECT_MOTION_TYPE || point != POINT_FROSTWYRM_LAND) - return; - - me->setActive(false); - me->SetFarVisible(false); - me->SetCanFly(false); - me->SetDisableGravity(false); - me->SetAnimTier(UNIT_BYTE1_FLAG_NONE, false); - me->SetHomePosition(RimefangLandPos); - me->SetFacingTo(RimefangLandPos.GetOrientation()); - me->SetImmuneToPC(false); - me->SetReactState(REACT_AGGRESSIVE); - } - - void JustEngagedWith(Unit* /*victim*/) override - { - DoCast(me, SPELL_FROST_AURA_RIMEFANG, true); - } - - 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_ICY_BLAST_CAST: + if (--_icyBlastCounter) { - case EVENT_FROST_BREATH_RIMEFANG: - DoCast(me, SPELL_FROST_BREATH); - _events.ScheduleEvent(EVENT_FROST_BREATH_RIMEFANG, 35s, 40s); - break; - case EVENT_ICY_BLAST: + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true)) { - _icyBlastCounter = RAID_MODE<uint8>(5, 7, 6, 8); - me->SetReactState(REACT_PASSIVE); - me->AttackStop(); - me->SetCanFly(true); - me->GetMotionMaster()->MovePoint(POINT_FROSTWYRM_FLY_IN, RimefangFlyPos); - Milliseconds moveTime = Milliseconds(uint64(me->GetExactDist(&RimefangFlyPos)/(me->GetSpeed(MOVE_FLIGHT)*0.001f))); - _events.ScheduleEvent(EVENT_ICY_BLAST, moveTime + 60s, moveTime + 70s); - _events.ScheduleEvent(EVENT_ICY_BLAST_CAST, moveTime + 250ms); - break; + me->SetFacingToObject(target); + DoCast(target, SPELL_ICY_BLAST); } - case EVENT_ICY_BLAST_CAST: - if (--_icyBlastCounter) - { - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true)) - { - me->SetFacingToObject(target); - DoCast(target, SPELL_ICY_BLAST); - } - _events.ScheduleEvent(EVENT_ICY_BLAST_CAST, 3s); - } - else if (Unit* victim = me->SelectVictim()) - { - me->SetReactState(REACT_DEFENSIVE); - AttackStart(victim); - me->SetCanFly(false); - } - break; - default: - break; + _events.ScheduleEvent(EVENT_ICY_BLAST_CAST, 3s); } - } - - DoMeleeAttackIfReady(); + else if (Unit* victim = me->SelectVictim()) + { + me->SetReactState(REACT_DEFENSIVE); + AttackStart(victim); + me->SetCanFly(false); + } + break; + default: + break; } + } - private: - EventMap _events; - InstanceScript* _instance; - uint8 _icyBlastCounter; - bool _summoned; - }; + DoMeleeAttackIfReady(); + } - CreatureAI* GetAI(Creature* creature) const override - { - return GetIcecrownCitadelAI<npc_rimefangAI>(creature); - } +private: + EventMap _events; + InstanceScript* _instance; + uint8 _icyBlastCounter; + bool _summoned; }; -class npc_sindragosa_trash : public CreatureScript +struct npc_sindragosa_trash : public ScriptedAI { - public: - npc_sindragosa_trash() : CreatureScript("npc_sindragosa_trash") { } - - struct npc_sindragosa_trashAI : public ScriptedAI - { - npc_sindragosa_trashAI(Creature* creature) : ScriptedAI(creature) - { - Initialize(); - _instance = creature->GetInstanceScript(); - _frostwyrmId = 0; - } - - void Initialize() - { - _isTaunted = false; - } + npc_sindragosa_trash(Creature* creature) : ScriptedAI(creature) + { + Initialize(); + _instance = creature->GetInstanceScript(); + _frostwyrmId = 0; + } - void InitializeAI() override - { - _frostwyrmId = (me->GetHomePosition().GetPositionY() < 2484.35f) ? DATA_RIMEFANG : DATA_SPINESTALKER; - // Increase add count - if (!me->isDead()) - { - if (me->GetEntry() == NPC_FROSTWING_WHELP) - _instance->SetGuidData(_frostwyrmId, ObjectGuid::Create<HighGuid::Creature>(631, me->GetEntry(), me->GetSpawnId())); // this cannot be in Reset because reset also happens on evade - Reset(); - } - } + void Initialize() + { + _isTaunted = false; + } - void Reset() override - { - // This is shared AI for handler and whelps - if (me->GetEntry() == NPC_FROSTWARDEN_HANDLER) - { - _events.ScheduleEvent(EVENT_FROSTWARDEN_ORDER_WHELP, 3s); - _events.ScheduleEvent(EVENT_CONCUSSIVE_SHOCK, 8s, 10s); - } + void InitializeAI() override + { + _frostwyrmId = (me->GetHomePosition().GetPositionY() < 2484.35f) ? DATA_RIMEFANG : DATA_SPINESTALKER; + // Increase add count + if (!me->isDead()) + { + if (me->GetEntry() == NPC_FROSTWING_WHELP) + _instance->SetGuidData(_frostwyrmId, ObjectGuid::Create<HighGuid::Creature>(631, me->GetEntry(), me->GetSpawnId())); // this cannot be in Reset because reset also happens on evade + Reset(); + } + } - Initialize(); - } + void Reset() override + { + // This is shared AI for handler and whelps + if (me->GetEntry() == NPC_FROSTWARDEN_HANDLER) + { + _events.ScheduleEvent(EVENT_FROSTWARDEN_ORDER_WHELP, 3s); + _events.ScheduleEvent(EVENT_CONCUSSIVE_SHOCK, 8s, 10s); + } - void JustAppeared() override - { - ScriptedAI::JustAppeared(); + Initialize(); + } - // Increase add count - if (me->GetEntry() == NPC_FROSTWING_WHELP) - _instance->SetGuidData(_frostwyrmId, ObjectGuid::Create<HighGuid::Creature>(631, me->GetEntry(), me->GetSpawnId())); // this cannot be in Reset because reset also happens on evade - } + void JustAppeared() override + { + ScriptedAI::JustAppeared(); - void SetData(uint32 type, uint32 data) override - { - if (type == DATA_WHELP_MARKER) - _isTaunted = data != 0; - } + // Increase add count + if (me->GetEntry() == NPC_FROSTWING_WHELP) + _instance->SetGuidData(_frostwyrmId, ObjectGuid::Create<HighGuid::Creature>(631, me->GetEntry(), me->GetSpawnId())); // this cannot be in Reset because reset also happens on evade + } - uint32 GetData(uint32 type) const override - { - if (type == DATA_FROSTWYRM_OWNER) - return _frostwyrmId; - else if (type == DATA_WHELP_MARKER) - return uint32(_isTaunted); - return 0; - } + void SetData(uint32 type, uint32 data) override + { + if (type == DATA_WHELP_MARKER) + _isTaunted = data != 0; + } - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; + uint32 GetData(uint32 type) const override + { + if (type == DATA_FROSTWYRM_OWNER) + return _frostwyrmId; + else if (type == DATA_WHELP_MARKER) + return uint32(_isTaunted); + return 0; + } - _events.Update(diff); + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; + _events.Update(diff); - while (uint32 eventId = _events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_FROSTWARDEN_ORDER_WHELP: - DoCast(me, SPELL_ORDER_WHELP); - _events.ScheduleEvent(EVENT_FROSTWARDEN_ORDER_WHELP, 3s); - break; - case EVENT_CONCUSSIVE_SHOCK: - DoCast(me, SPELL_CONCUSSIVE_SHOCK); - _events.ScheduleEvent(EVENT_CONCUSSIVE_SHOCK, 10s, 13s); - break; - default: - break; - } - } + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - DoMeleeAttackIfReady(); + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_FROSTWARDEN_ORDER_WHELP: + DoCastSelf(SPELL_ORDER_WHELP); + _events.ScheduleEvent(EVENT_FROSTWARDEN_ORDER_WHELP, 3s); + break; + case EVENT_CONCUSSIVE_SHOCK: + DoCastSelf(SPELL_CONCUSSIVE_SHOCK); + _events.ScheduleEvent(EVENT_CONCUSSIVE_SHOCK, 10s, 13s); + break; + default: + break; } + } - private: - EventMap _events; - InstanceScript* _instance; - uint32 _frostwyrmId; - bool _isTaunted; // Frostwing Whelp only - }; + DoMeleeAttackIfReady(); + } - CreatureAI* GetAI(Creature* creature) const override - { - return GetIcecrownCitadelAI<npc_sindragosa_trashAI>(creature); - } +private: + EventMap _events; + InstanceScript* _instance; + uint32 _frostwyrmId; + bool _isTaunted; // Frostwing Whelp only }; -class spell_sindragosa_s_fury : public SpellScriptLoader +class spell_sindragosa_s_fury : public SpellScript { - public: - spell_sindragosa_s_fury() : SpellScriptLoader("spell_sindragosa_s_fury") { } - - class spell_sindragosa_s_fury_SpellScript : public SpellScript - { - PrepareSpellScript(spell_sindragosa_s_fury_SpellScript); - - bool Load() override - { - // This script should execute only in Icecrown Citadel - return InstanceHasScript(GetCaster(), ICCScriptName); - } + PrepareSpellScript(spell_sindragosa_s_fury); - void SelectDest() - { - if (Position* dest = const_cast<WorldLocation*>(GetExplTargetDest())) - { - float destX = float(rand_norm()) * 75.0f + 4350.0f; - float destY = float(rand_norm()) * 75.0f + 2450.0f; - float destZ = 205.0f; // random number close to ground, get exact in next call - GetCaster()->UpdateGroundPositionZ(destX, destY, destZ); - dest->Relocate(destX, destY, destZ); - } - } + bool Load() override + { + // This script should execute only in Icecrown Citadel + return InstanceHasScript(GetCaster(), ICCScriptName); + } - void FilterTargets(std::list<WorldObject*>& targets) - { - targets.remove_if([](WorldObject* obj) -> bool - { - // remove GMs - if (Player* player = obj->ToPlayer()) - return player->IsGameMaster(); + void SelectDest() + { + if (Position* dest = const_cast<WorldLocation*>(GetExplTargetDest())) + { + float destX = float(rand_norm()) * 75.0f + 4350.0f; + float destY = float(rand_norm()) * 75.0f + 2450.0f; + float destZ = 205.0f; // random number close to ground, get exact in next call + GetCaster()->UpdateGroundPositionZ(destX, destY, destZ); + dest->Relocate(destX, destY, destZ); + } + } - // remove non-players too - return true; - }); + void FilterTargets(std::list<WorldObject*>& targets) + { + targets.remove_if([](WorldObject* obj) -> bool + { + // remove GMs + if (Player* player = obj->ToPlayer()) + return player->IsGameMaster(); - _targetCount = targets.size(); - } + // remove non-players too + return true; + }); - void HandleDummy(SpellEffIndex effIndex) - { - PreventHitDefaultEffect(effIndex); + _targetCount = targets.size(); + } - if (!GetHitUnit()->IsAlive() || !_targetCount) - return; + void HandleDummy(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); - if (GetHitUnit()->IsImmunedToDamage(GetSpellInfo())) - { - GetCaster()->SendSpellDamageImmune(GetHitUnit(), GetSpellInfo()->Id, false); - return; - } + if (!GetHitUnit()->IsAlive() || !_targetCount) + return; - float resistance = float(GetHitUnit()->GetResistance(SpellSchoolMask(GetSpellInfo()->SchoolMask))); - uint32 minResistFactor = uint32((resistance / (resistance + 510.0f)) * 10.0f) * 2; - uint32 randomResist = urand(0, (9 - minResistFactor) * 100) / 100 + minResistFactor; + if (GetHitUnit()->IsImmunedToDamage(GetSpellInfo())) + { + GetCaster()->SendSpellDamageImmune(GetHitUnit(), GetSpellInfo()->Id, false); + return; + } - uint32 damage = (uint32(GetEffectValue() / _targetCount) * randomResist) / 10; + float resistance = float(GetHitUnit()->GetResistance(SpellSchoolMask(GetSpellInfo()->SchoolMask))); + uint32 minResistFactor = uint32((resistance / (resistance + 510.0f)) * 10.0f) * 2; + uint32 randomResist = urand(0, (9 - minResistFactor) * 100) / 100 + minResistFactor; - SpellNonMeleeDamage damageInfo(GetCaster(), GetHitUnit(), GetSpellInfo(), GetSpell()->m_SpellVisual, GetSpellInfo()->SchoolMask); - damageInfo.damage = damage; - GetCaster()->DealSpellDamage(&damageInfo, false); - GetCaster()->SendSpellNonMeleeDamageLog(&damageInfo); - } + uint32 damage = (uint32(GetEffectValue() / _targetCount) * randomResist) / 10; - void Register() override - { - BeforeCast += SpellCastFn(spell_sindragosa_s_fury_SpellScript::SelectDest); - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_sindragosa_s_fury_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_DEST_AREA_ENTRY); - OnEffectHitTarget += SpellEffectFn(spell_sindragosa_s_fury_SpellScript::HandleDummy, EFFECT_1, SPELL_EFFECT_DUMMY); - } + SpellNonMeleeDamage damageInfo(GetCaster(), GetHitUnit(), GetSpellInfo(), GetSpell()->m_SpellVisual, GetSpellInfo()->SchoolMask); + damageInfo.damage = damage; + GetCaster()->DealSpellDamage(&damageInfo, false); + GetCaster()->SendSpellNonMeleeDamageLog(&damageInfo); + } - uint32 _targetCount = 0; - }; + void Register() override + { + BeforeCast += SpellCastFn(spell_sindragosa_s_fury::SelectDest); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_sindragosa_s_fury::FilterTargets, EFFECT_1, TARGET_UNIT_DEST_AREA_ENTRY); + OnEffectHitTarget += SpellEffectFn(spell_sindragosa_s_fury::HandleDummy, EFFECT_1, SPELL_EFFECT_DUMMY); + } - SpellScript* GetSpellScript() const override - { - return new spell_sindragosa_s_fury_SpellScript(); - } + uint32 _targetCount = 0; }; class spell_sindragosa_unchained_magic : public SpellScript @@ -1216,211 +1148,156 @@ class spell_sindragosa_unchained_magic : public SpellScript } }; -class spell_sindragosa_frost_breath : public SpellScriptLoader +class spell_sindragosa_frost_breath : public SpellScript { - public: - spell_sindragosa_frost_breath() : SpellScriptLoader("spell_sindragosa_frost_breath") { } - - class spell_sindragosa_frost_breath_SpellScript : public SpellScript - { - PrepareSpellScript(spell_sindragosa_frost_breath_SpellScript); - - void HandleInfusion() - { - Player* target = GetHitPlayer(); - if (!target) - return; + PrepareSpellScript(spell_sindragosa_frost_breath); - // Check difficulty and quest status - if (!target->GetMap()->Is25ManRaid() || target->GetQuestStatus(QUEST_FROST_INFUSION) != QUEST_STATUS_INCOMPLETE) - return; + void HandleInfusion() + { + Player* target = GetHitPlayer(); + if (!target) + return; - // Check if player has Shadow's Edge equipped and not ready for infusion - if (!target->HasAura(SPELL_UNSATED_CRAVING) || target->HasAura(SPELL_FROST_IMBUED_BLADE)) - return; + // Check difficulty and quest status + if (!target->GetMap()->Is25ManRaid() || target->GetQuestStatus(QUEST_FROST_INFUSION) != QUEST_STATUS_INCOMPLETE) + return; - Aura* infusion = target->GetAura(SPELL_FROST_INFUSION, target->GetGUID()); - if (infusion && infusion->GetStackAmount() >= 3) - { - target->RemoveAura(infusion); - target->CastSpell(target, SPELL_FROST_IMBUED_BLADE, TRIGGERED_FULL_MASK); - } - else - target->CastSpell(target, SPELL_FROST_INFUSION, TRIGGERED_FULL_MASK); - } + // Check if player has Shadow's Edge equipped and not ready for infusion + if (!target->HasAura(SPELL_UNSATED_CRAVING) || target->HasAura(SPELL_FROST_IMBUED_BLADE)) + return; - void Register() override - { - AfterHit += SpellHitFn(spell_sindragosa_frost_breath_SpellScript::HandleInfusion); - } - }; - - SpellScript* GetSpellScript() const override + Aura* infusion = target->GetAura(SPELL_FROST_INFUSION, target->GetGUID()); + if (infusion && infusion->GetStackAmount() >= 3) { - return new spell_sindragosa_frost_breath_SpellScript(); + target->RemoveAura(infusion); + target->CastSpell(target, SPELL_FROST_IMBUED_BLADE, TRIGGERED_FULL_MASK); } + else + target->CastSpell(target, SPELL_FROST_INFUSION, TRIGGERED_FULL_MASK); + } + + void Register() override + { + AfterHit += SpellHitFn(spell_sindragosa_frost_breath::HandleInfusion); + } }; -class spell_sindragosa_instability : public SpellScriptLoader +class spell_sindragosa_instability : public AuraScript { - public: - spell_sindragosa_instability() : SpellScriptLoader("spell_sindragosa_instability") { } + PrepareAuraScript(spell_sindragosa_instability); - class spell_sindragosa_instability_AuraScript : public AuraScript - { - PrepareAuraScript(spell_sindragosa_instability_AuraScript); - - bool Validate(SpellInfo const* /*spell*/) override - { - return ValidateSpellInfo({ SPELL_BACKLASH }); - } - - void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) - { - if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE) - { - CastSpellExtraArgs args(aurEff); - args.OriginalCaster = GetCasterGUID(); - args.AddSpellBP0(aurEff->GetAmount()); - GetTarget()->CastSpell(GetTarget(), SPELL_BACKLASH, args); - } - } - - void Register() override - { - AfterEffectRemove += AuraEffectRemoveFn(spell_sindragosa_instability_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); - } - }; + bool Validate(SpellInfo const* /*spell*/) override + { + return ValidateSpellInfo({ SPELL_BACKLASH }); + } - AuraScript* GetAuraScript() const override + void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) + { + if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE) { - return new spell_sindragosa_instability_AuraScript(); + CastSpellExtraArgs args(aurEff); + args.OriginalCaster = GetCasterGUID(); + args.AddSpellBP0(aurEff->GetAmount()); + GetTarget()->CastSpell(GetTarget(), SPELL_BACKLASH, args); } + } + + void Register() override + { + AfterEffectRemove += AuraEffectRemoveFn(spell_sindragosa_instability::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } }; -class spell_sindragosa_frost_beacon : public SpellScriptLoader +class spell_sindragosa_frost_beacon : public AuraScript { - public: - spell_sindragosa_frost_beacon() : SpellScriptLoader("spell_sindragosa_frost_beacon") { } - - class spell_sindragosa_frost_beacon_AuraScript : public AuraScript - { - PrepareAuraScript(spell_sindragosa_frost_beacon_AuraScript); - - bool Validate(SpellInfo const* /*spell*/) override - { - return ValidateSpellInfo({ SPELL_ICE_TOMB_DAMAGE }); - } + PrepareAuraScript(spell_sindragosa_frost_beacon); - void PeriodicTick(AuraEffect const* /*aurEff*/) - { - PreventDefaultAction(); - if (Unit* caster = GetCaster()) - caster->CastSpell(GetTarget(), SPELL_ICE_TOMB_DAMAGE, true); - } + bool Validate(SpellInfo const* /*spell*/) override + { + return ValidateSpellInfo({ SPELL_ICE_TOMB_DAMAGE }); + } - void Register() override - { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_sindragosa_frost_beacon_AuraScript::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); - } - }; + void PeriodicTick(AuraEffect const* /*aurEff*/) + { + PreventDefaultAction(); + if (Unit* caster = GetCaster()) + caster->CastSpell(GetTarget(), SPELL_ICE_TOMB_DAMAGE, true); + } - AuraScript* GetAuraScript() const override - { - return new spell_sindragosa_frost_beacon_AuraScript(); - } + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_sindragosa_frost_beacon::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } }; -class spell_sindragosa_ice_tomb : public SpellScriptLoader +class spell_sindragosa_ice_tomb : public AuraScript { - public: - spell_sindragosa_ice_tomb() : SpellScriptLoader("spell_sindragosa_ice_tomb_trap") { } + PrepareAuraScript(spell_sindragosa_ice_tomb); - class spell_sindragosa_ice_tomb_AuraScript : public AuraScript - { - PrepareAuraScript(spell_sindragosa_ice_tomb_AuraScript); + bool Validate(SpellInfo const* /*spell*/) override + { + if (!sObjectMgr->GetCreatureTemplate(NPC_ICE_TOMB)) + return false; + if (!sObjectMgr->GetGameObjectTemplate(GO_ICE_BLOCK)) + return false; + return true; + } - bool Validate(SpellInfo const* /*spell*/) override - { - if (!sObjectMgr->GetCreatureTemplate(NPC_ICE_TOMB)) - return false; - if (!sObjectMgr->GetGameObjectTemplate(GO_ICE_BLOCK)) - return false; - return true; - } + void PeriodicTick(AuraEffect const* aurEff) + { + PreventDefaultAction(); - void PeriodicTick(AuraEffect const* aurEff) + if (aurEff->GetTickNumber() == 1) + { + if (Unit* caster = GetCaster()) { - PreventDefaultAction(); + Position pos = GetTarget()->GetPosition(); - if (aurEff->GetTickNumber() == 1) + if (TempSummon* summon = caster->SummonCreature(NPC_ICE_TOMB, pos)) { - if (Unit* caster = GetCaster()) + summon->AI()->SetGUID(GetTarget()->GetGUID(), DATA_TRAPPED_PLAYER); + GetTarget()->CastSpell(GetTarget(), SPELL_ICE_TOMB_UNTARGETABLE); + if (GameObject* go = summon->SummonGameObject(GO_ICE_BLOCK, pos, QuaternionData::fromEulerAnglesZYX(pos.GetOrientation(), 0.0f, 0.0f), 0s)) { - Position pos = GetTarget()->GetPosition(); - - if (TempSummon* summon = caster->SummonCreature(NPC_ICE_TOMB, pos)) - { - summon->AI()->SetGUID(GetTarget()->GetGUID(), DATA_TRAPPED_PLAYER); - GetTarget()->CastSpell(GetTarget(), SPELL_ICE_TOMB_UNTARGETABLE); - if (GameObject* go = summon->SummonGameObject(GO_ICE_BLOCK, pos, QuaternionData::fromEulerAnglesZYX(pos.GetOrientation(), 0.0f, 0.0f), 0s)) - { - go->SetSpellId(SPELL_ICE_TOMB_DAMAGE); - summon->AddGameObject(go); - } - } + go->SetSpellId(SPELL_ICE_TOMB_DAMAGE); + summon->AddGameObject(go); } } } + } + } - void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - GetTarget()->RemoveAurasDueToSpell(SPELL_ICE_TOMB_UNTARGETABLE); - } - - void Register() override - { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_sindragosa_ice_tomb_AuraScript::PeriodicTick, EFFECT_2, SPELL_AURA_PERIODIC_TRIGGER_SPELL); - AfterEffectRemove += AuraEffectRemoveFn(spell_sindragosa_ice_tomb_AuraScript::HandleRemove, EFFECT_2, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL); - } - }; + void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + GetTarget()->RemoveAurasDueToSpell(SPELL_ICE_TOMB_UNTARGETABLE); + } - AuraScript* GetAuraScript() const override - { - return new spell_sindragosa_ice_tomb_AuraScript(); - } + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_sindragosa_ice_tomb::PeriodicTick, EFFECT_2, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + AfterEffectRemove += AuraEffectRemoveFn(spell_sindragosa_ice_tomb::HandleRemove, EFFECT_2, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL); + } }; -class spell_sindragosa_icy_grip : public SpellScriptLoader +class spell_sindragosa_icy_grip : public SpellScript { - public: - spell_sindragosa_icy_grip() : SpellScriptLoader("spell_sindragosa_icy_grip") { } + PrepareSpellScript(spell_sindragosa_icy_grip); - class spell_sindragosa_icy_grip_SpellScript : public SpellScript - { - PrepareSpellScript(spell_sindragosa_icy_grip_SpellScript); - - bool Validate(SpellInfo const* /*spell*/) override - { - return ValidateSpellInfo({ SPELL_ICY_GRIP_JUMP }); - } - - void HandleScript(SpellEffIndex effIndex) - { - PreventHitDefaultEffect(effIndex); - GetHitUnit()->CastSpell(GetCaster(), SPELL_ICY_GRIP_JUMP, true); - } + bool Validate(SpellInfo const* /*spell*/) override + { + return ValidateSpellInfo({ SPELL_ICY_GRIP_JUMP }); + } - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_sindragosa_icy_grip_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); - } - }; + void HandleScript(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + GetHitUnit()->CastSpell(GetCaster(), SPELL_ICY_GRIP_JUMP, true); + } - SpellScript* GetSpellScript() const override - { - return new spell_sindragosa_icy_grip_SpellScript(); - } + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_sindragosa_icy_grip::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } }; class MysticBuffetTargetFilter @@ -1437,64 +1314,42 @@ class MysticBuffetTargetFilter Unit* _caster; }; -class spell_sindragosa_mystic_buffet : public SpellScriptLoader +class spell_sindragosa_mystic_buffet : public SpellScript { - public: - spell_sindragosa_mystic_buffet() : SpellScriptLoader("spell_sindragosa_mystic_buffet") { } - - class spell_sindragosa_mystic_buffet_SpellScript : public SpellScript - { - PrepareSpellScript(spell_sindragosa_mystic_buffet_SpellScript); + PrepareSpellScript(spell_sindragosa_mystic_buffet); - void FilterTargets(std::list<WorldObject*>& targets) - { - targets.remove_if(MysticBuffetTargetFilter(GetCaster())); - } - - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_sindragosa_mystic_buffet_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - } - }; + void FilterTargets(std::list<WorldObject*>& targets) + { + targets.remove_if(MysticBuffetTargetFilter(GetCaster())); + } - SpellScript* GetSpellScript() const override - { - return new spell_sindragosa_mystic_buffet_SpellScript(); - } + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_sindragosa_mystic_buffet::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + } }; -class spell_rimefang_icy_blast : public SpellScriptLoader +class spell_rimefang_icy_blast : public SpellScript { - public: - spell_rimefang_icy_blast() : SpellScriptLoader("spell_rimefang_icy_blast") { } - - class spell_rimefang_icy_blast_SpellScript : public SpellScript - { - PrepareSpellScript(spell_rimefang_icy_blast_SpellScript); - - bool Validate(SpellInfo const* /*spell*/) override - { - return ValidateSpellInfo({ SPELL_ICY_BLAST_AREA }); - } + PrepareSpellScript(spell_rimefang_icy_blast); - void HandleTriggerMissile(SpellEffIndex effIndex) - { - PreventHitDefaultEffect(effIndex); - if (Position const* pos = GetExplTargetDest()) - if (TempSummon* summon = GetCaster()->SummonCreature(NPC_ICY_BLAST, *pos, TEMPSUMMON_TIMED_DESPAWN, 40s)) - summon->CastSpell(summon, SPELL_ICY_BLAST_AREA, true); - } + bool Validate(SpellInfo const* /*spell*/) override + { + return ValidateSpellInfo({ SPELL_ICY_BLAST_AREA }); + } - void Register() override - { - OnEffectHit += SpellEffectFn(spell_rimefang_icy_blast_SpellScript::HandleTriggerMissile, EFFECT_1, SPELL_EFFECT_TRIGGER_MISSILE); - } - }; + void HandleTriggerMissile(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + if (Position const* pos = GetExplTargetDest()) + if (TempSummon* summon = GetCaster()->SummonCreature(NPC_ICY_BLAST, *pos, TEMPSUMMON_TIMED_DESPAWN, 40s)) + summon->CastSpell(summon, SPELL_ICY_BLAST_AREA, true); + } - SpellScript* GetSpellScript() const override - { - return new spell_rimefang_icy_blast_SpellScript(); - } + void Register() override + { + OnEffectHit += SpellEffectFn(spell_rimefang_icy_blast::HandleTriggerMissile, EFFECT_1, SPELL_EFFECT_TRIGGER_MISSILE); + } }; class OrderWhelpTargetSelector @@ -1513,149 +1368,111 @@ class OrderWhelpTargetSelector Creature* _owner; }; -class spell_frostwarden_handler_order_whelp : public SpellScriptLoader +class spell_frostwarden_handler_order_whelp : public SpellScript { - public: - spell_frostwarden_handler_order_whelp() : SpellScriptLoader("spell_frostwarden_handler_order_whelp") { } + PrepareSpellScript(spell_frostwarden_handler_order_whelp); - class spell_frostwarden_handler_order_whelp_SpellScript : public SpellScript - { - PrepareSpellScript(spell_frostwarden_handler_order_whelp_SpellScript); - - bool Validate(SpellInfo const* /*spell*/) override - { - return ValidateSpellInfo({ SPELL_FOCUS_FIRE }); - } + bool Validate(SpellInfo const* /*spell*/) override + { + return ValidateSpellInfo({ SPELL_FOCUS_FIRE }); + } - void FilterTargets(std::list<WorldObject*>& targets) - { - targets.remove_if(Trinity::ObjectTypeIdCheck(TYPEID_PLAYER, false)); - if (targets.empty()) - return; + void FilterTargets(std::list<WorldObject*>& targets) + { + targets.remove_if(Trinity::ObjectTypeIdCheck(TYPEID_PLAYER, false)); + if (targets.empty()) + return; - WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); - targets.clear(); - targets.push_back(target); - } + WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); + targets.clear(); + targets.push_back(target); + } - void HandleForcedCast(SpellEffIndex effIndex) - { - // caster is Frostwarden Handler, target is player, caster of triggered is whelp - PreventHitDefaultEffect(effIndex); - std::list<Creature*> unitList; - GetCreatureListWithEntryInGrid(unitList, GetCaster(), NPC_FROSTWING_WHELP, 150.0f); - if (Creature* creature = GetCaster()->ToCreature()) - unitList.remove_if(OrderWhelpTargetSelector(creature)); + void HandleForcedCast(SpellEffIndex effIndex) + { + // caster is Frostwarden Handler, target is player, caster of triggered is whelp + PreventHitDefaultEffect(effIndex); + std::list<Creature*> unitList; + GetCreatureListWithEntryInGrid(unitList, GetCaster(), NPC_FROSTWING_WHELP, 150.0f); + if (Creature* creature = GetCaster()->ToCreature()) + unitList.remove_if(OrderWhelpTargetSelector(creature)); - if (unitList.empty()) - return; + if (unitList.empty()) + return; - Trinity::Containers::SelectRandomContainerElement(unitList)->CastSpell(GetHitUnit(), uint32(GetEffectValue()), true); - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_frostwarden_handler_order_whelp_SpellScript::HandleForcedCast, EFFECT_0, SPELL_EFFECT_FORCE_CAST); - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_frostwarden_handler_order_whelp_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY); - } - }; + Trinity::Containers::SelectRandomContainerElement(unitList)->CastSpell(GetHitUnit(), uint32(GetEffectValue()), true); + } - SpellScript* GetSpellScript() const override - { - return new spell_frostwarden_handler_order_whelp_SpellScript(); - } + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_frostwarden_handler_order_whelp::HandleForcedCast, EFFECT_0, SPELL_EFFECT_FORCE_CAST); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_frostwarden_handler_order_whelp::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY); + } }; -class spell_frostwarden_handler_focus_fire : public SpellScriptLoader +class spell_frostwarden_handler_focus_fire : public SpellScript { - public: - spell_frostwarden_handler_focus_fire() : SpellScriptLoader("spell_frostwarden_handler_focus_fire") { } + PrepareSpellScript(spell_frostwarden_handler_focus_fire); - class spell_frostwarden_handler_focus_fire_SpellScript : public SpellScript - { - PrepareSpellScript(spell_frostwarden_handler_focus_fire_SpellScript); - - void HandleScript(SpellEffIndex effIndex) - { - PreventHitDefaultEffect(effIndex); - GetCaster()->GetThreatManager().AddThreat(GetHitUnit(), float(GetEffectValue()), GetSpellInfo(), true, true); - GetCaster()->GetAI()->SetData(DATA_WHELP_MARKER, 1); - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_frostwarden_handler_focus_fire_SpellScript::HandleScript, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT); - } - }; - - class spell_frostwarden_handler_focus_fire_AuraScript : public AuraScript - { - PrepareAuraScript(spell_frostwarden_handler_focus_fire_AuraScript); + void HandleScript(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + GetCaster()->GetThreatManager().AddThreat(GetHitUnit(), float(GetEffectValue()), GetSpellInfo(), true, true); + GetCaster()->GetAI()->SetData(DATA_WHELP_MARKER, 1); + } - bool Validate(SpellInfo const* spellInfo) override - { - return spellInfo->GetEffects().size() > EFFECT_1; - } + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_frostwarden_handler_focus_fire::HandleScript, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT); + } +}; - void PeriodicTick(AuraEffect const* /*aurEff*/) - { - PreventDefaultAction(); - if (Unit* caster = GetCaster()) - { - caster->GetThreatManager().AddThreat(GetTarget(), -float(GetEffectInfo(EFFECT_1).CalcValue()), GetSpellInfo(), true, true); - caster->GetAI()->SetData(DATA_WHELP_MARKER, 0); - } - } +class spell_frostwarden_handler_focus_fire_aura : public AuraScript +{ + PrepareAuraScript(spell_frostwarden_handler_focus_fire_aura); - void Register() override - { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_frostwarden_handler_focus_fire_AuraScript::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); - } - }; + bool Validate(SpellInfo const* spellInfo) override + { + return spellInfo->GetEffects().size() > EFFECT_1; + } - SpellScript* GetSpellScript() const override + void PeriodicTick(AuraEffect const* /*aurEff*/) + { + PreventDefaultAction(); + if (Unit* caster = GetCaster()) { - return new spell_frostwarden_handler_focus_fire_SpellScript(); + caster->GetThreatManager().AddThreat(GetTarget(), -float(GetEffectInfo(EFFECT_1).CalcValue()), GetSpellInfo(), true, true); + caster->GetAI()->SetData(DATA_WHELP_MARKER, 0); } + } - AuraScript* GetAuraScript() const override - { - return new spell_frostwarden_handler_focus_fire_AuraScript(); - } + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_frostwarden_handler_focus_fire_aura::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + } }; -class spell_sindragosa_ice_tomb_target : public SpellScriptLoader +class spell_sindragosa_ice_tomb_target : public SpellScript { -public: - spell_sindragosa_ice_tomb_target() : SpellScriptLoader("spell_sindragosa_ice_tomb_target") { } + PrepareSpellScript(spell_sindragosa_ice_tomb_target); - class spell_sindragosa_ice_tomb_target_SpellScript : public SpellScript + void FilterTargets(std::list<WorldObject*>& unitList) { - PrepareSpellScript(spell_sindragosa_ice_tomb_target_SpellScript); - - void FilterTargets(std::list<WorldObject*>& unitList) - { - Unit* caster = GetCaster(); - unitList.remove_if(FrostBeaconSelector(caster)); - } - - void HandleSindragosaTalk(SpellEffIndex /*effIndex*/) - { - if (Creature* creatureCaster = GetCaster()->ToCreature()) - if (creatureCaster->GetAI()->GetData(DATA_IS_THIRD_PHASE)) - creatureCaster->AI()->Talk(EMOTE_WARN_FROZEN_ORB, GetHitUnit()); - } + Unit* caster = GetCaster(); + unitList.remove_if(FrostBeaconSelector(caster)); + } - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_sindragosa_ice_tomb_target_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - OnEffectLaunchTarget += SpellEffectFn(spell_sindragosa_ice_tomb_target_SpellScript::HandleSindragosaTalk, EFFECT_0, SPELL_EFFECT_DUMMY); - } - }; + void HandleSindragosaTalk(SpellEffIndex /*effIndex*/) + { + if (Creature* creatureCaster = GetCaster()->ToCreature()) + if (creatureCaster->GetAI()->GetData(DATA_IS_THIRD_PHASE)) + creatureCaster->AI()->Talk(EMOTE_WARN_FROZEN_ORB, GetHitUnit()); + } - SpellScript* GetSpellScript() const override + void Register() override { - return new spell_sindragosa_ice_tomb_target_SpellScript(); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_sindragosa_ice_tomb_target::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnEffectLaunchTarget += SpellEffectFn(spell_sindragosa_ice_tomb_target::HandleSindragosaTalk, EFFECT_0, SPELL_EFFECT_DUMMY); } }; @@ -1706,25 +1523,32 @@ class achievement_all_you_can_eat : public AchievementCriteriaScript void AddSC_boss_sindragosa() { - new boss_sindragosa(); - new npc_ice_tomb(); - new npc_spinestalker(); - new npc_rimefang(); - new npc_sindragosa_trash(); - new spell_sindragosa_s_fury(); + // Creatures + RegisterIcecrownCitadelCreatureAI(boss_sindragosa); + RegisterIcecrownCitadelCreatureAI(npc_ice_tomb); + RegisterIcecrownCitadelCreatureAI(npc_spinestalker); + RegisterIcecrownCitadelCreatureAI(npc_rimefang); + RegisterIcecrownCitadelCreatureAI(npc_sindragosa_trash); + + // Spells + RegisterSpellScript(spell_sindragosa_s_fury); RegisterSpellScript(spell_sindragosa_unchained_magic); - new spell_sindragosa_frost_breath(); - new spell_sindragosa_instability(); - new spell_sindragosa_frost_beacon(); - new spell_sindragosa_ice_tomb(); - new spell_sindragosa_icy_grip(); - new spell_sindragosa_mystic_buffet(); - new spell_rimefang_icy_blast(); - new spell_frostwarden_handler_order_whelp(); - new spell_frostwarden_handler_focus_fire(); + RegisterSpellScript(spell_sindragosa_frost_breath); + RegisterSpellScript(spell_sindragosa_instability); + RegisterSpellScript(spell_sindragosa_frost_beacon); + RegisterSpellScript(spell_sindragosa_ice_tomb); + RegisterSpellScript(spell_sindragosa_icy_grip); + RegisterSpellScript(spell_sindragosa_mystic_buffet); + RegisterSpellScript(spell_rimefang_icy_blast); + RegisterSpellScript(spell_frostwarden_handler_order_whelp); + RegisterSpellAndAuraScriptPair(spell_frostwarden_handler_focus_fire, spell_frostwarden_handler_focus_fire_aura); new spell_trigger_spell_from_caster("spell_sindragosa_ice_tomb", SPELL_ICE_TOMB_DUMMY, TRIGGERED_IGNORE_SET_FACING); new spell_trigger_spell_from_caster("spell_sindragosa_ice_tomb_dummy", SPELL_FROST_BEACON); - new spell_sindragosa_ice_tomb_target(); + RegisterSpellScript(spell_sindragosa_ice_tomb_target); + + // AreaTriggers new at_sindragosa_lair(); + + // Achievements new achievement_all_you_can_eat(); } |