aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp1263
-rwxr-xr-xsrc/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h47
-rwxr-xr-xsrc/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp46
3 files changed, 1351 insertions, 5 deletions
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp
index 0ae0515a35b..04dd5cda4e4 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp
@@ -18,7 +18,9 @@
#include "ObjectMgr.h"
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
+#include "ScriptedEscortAI.h"
#include "SpellAuraEffects.h"
+#include "SmartAI.h"
#include "icecrown_citadel.h"
// Weekly quest support
@@ -61,6 +63,33 @@ enum Texts
// Rotting Frost Giant
EMOTE_DEATH_PLAGUE_WARNING = 0,
+
+ // Sister Svalna
+ SAY_SVALNA_KILL_CAPTAIN = 1, // happens when she kills a captain
+ SAY_SVALNA_KILL = 4,
+ SAY_SVALNA_CAPTAIN_DEATH = 5, // happens when a captain resurrected by her dies
+ SAY_SVALNA_DEATH = 6,
+ EMOTE_SVALNA_IMPALE = 7,
+ EMOTE_SVALNA_BROKEN_SHIELD = 8,
+
+ SAY_CROK_INTRO_1 = 0, // Ready your arms, my Argent Brothers. The Vrykul will protect the Frost Queen with their lives.
+ SAY_ARNATH_INTRO_2 = 5, // Even dying here beats spending another day collecting reagents for that madman, Finklestein.
+ SAY_CROK_INTRO_3 = 1, // Enough idle banter! Our champions have arrived - support them as we push our way through the hall!
+ SAY_SVALNA_EVENT_START = 0, // You may have once fought beside me, Crok, but now you are nothing more than a traitor. Come, your second death approaches!
+ SAY_CROK_COMBAT_WP_0 = 2, // Draw them back to us, and we'll assist you.
+ SAY_CROK_COMBAT_WP_1 = 3, // Quickly, push on!
+ SAY_CROK_FINAL_WP = 4, // Her reinforcements will arrive shortly, we must bring her down quickly!
+ SAY_SVALNA_RESURRECT_CAPTAINS = 2, // Foolish Crok. You brought my reinforcements with you. Arise, Argent Champions, and serve the Lich King in death!
+ SAY_CROK_COMBAT_SVALNA = 5, // I'll draw her attacks. Return our brothers to their graves, then help me bring her down!
+ SAY_SVALNA_AGGRO = 3, // Come, Scourgebane. I'll show the master which of us is truly worthy of the title of "Champion"!
+ SAY_CAPTAIN_DEATH = 0,
+ SAY_CAPTAIN_RESURRECTED = 1,
+ SAY_CAPTAIN_KILL = 2,
+ SAY_CAPTAIN_SECOND_DEATH = 3,
+ SAY_CAPTAIN_SURVIVE_TALK = 4,
+ SAY_CROK_WEAKENING_GAUNTLET = 6,
+ SAY_CROK_WEAKENING_SVALNA = 7,
+ SAY_CROK_DEATH = 8,
};
enum Spells
@@ -79,8 +108,62 @@ enum Spells
// Alchemist Adrianna
SPELL_HARVEST_BLIGHT_SPECIMEN = 72155,
SPELL_HARVEST_BLIGHT_SPECIMEN25 = 72162,
+
+ // Crok Scourgebane
+ SPELL_ICEBOUND_ARMOR = 70714,
+ SPELL_SCOURGE_STRIKE = 71488,
+ SPELL_DEATH_STRIKE = 71489,
+
+ // Sister Svalna
+ SPELL_CARESS_OF_DEATH = 70078,
+ SPELL_IMPALING_SPEAR_KILL = 70196,
+ SPELL_REVIVE_CHAMPION = 70053,
+ SPELL_UNDEATH = 70089,
+ SPELL_IMPALING_SPEAR = 71443,
+ SPELL_AETHER_SHIELD = 71463,
+ SPELL_HURL_SPEAR = 71466,
+
+ // Captain Arnath
+ SPELL_DOMINATE_MIND = 14515,
+ SPELL_FLASH_HEAL_NORMAL = 71595,
+ SPELL_POWER_WORD_SHIELD_NORMAL = 71548,
+ SPELL_SMITE_NORMAL = 71546,
+ SPELL_FLASH_HEAL_UNDEAD = 71782,
+ SPELL_POWER_WORD_SHIELD_UNDEAD = 71780,
+ SPELL_SMITE_UNDEAD = 71778,
+
+ // Captain Brandon
+ SPELL_CRUSADER_STRIKE = 71549,
+ SPELL_DIVINE_SHIELD = 71550,
+ SPELL_JUDGEMENT_OF_COMMAND = 71551,
+ SPELL_HAMMER_OF_BETRAYAL = 71784,
+
+ // Captain Grondel
+ SPELL_CHARGE = 71553,
+ SPELL_MORTAL_STRIKE = 71552,
+ SPELL_SUNDER_ARMOR = 71554,
+ SPELL_CONFLAGRATION = 71785,
+
+ // Captain Rupert
+ SPELL_FEL_IRON_BOMB_NORMAL = 71592,
+ SPELL_MACHINE_GUN_NORMAL = 71594,
+ SPELL_ROCKET_LAUNCH_NORMAL = 71590,
+ SPELL_FEL_IRON_BOMB_UNDEAD = 71787,
+ SPELL_MACHINE_GUN_UNDEAD = 71788,
+ SPELL_ROCKET_LAUNCH_UNDEAD = 71786,
};
+// Helper defines
+// Captain Arnath
+#define SPELL_FLASH_HEAL (IsUndead ? SPELL_FLASH_HEAL_UNDEAD : SPELL_FLASH_HEAL_NORMAL)
+#define SPELL_POWER_WORD_SHIELD (IsUndead ? SPELL_POWER_WORD_SHIELD_UNDEAD : SPELL_POWER_WORD_SHIELD_NORMAL)
+#define SPELL_SMITE (IsUndead ? SPELL_SMITE_UNDEAD : SPELL_SMITE_NORMAL)
+
+// Captain Rupert
+#define SPELL_FEL_IRON_BOMB (IsUndead ? SPELL_FEL_IRON_BOMB_UNDEAD : SPELL_FEL_IRON_BOMB_NORMAL)
+#define SPELL_MACHINE_GUN (IsUndead ? SPELL_MACHINE_GUN_UNDEAD : SPELL_MACHINE_GUN_NORMAL)
+#define SPELL_ROCKET_LAUNCH (IsUndead ? SPELL_ROCKET_LAUNCH_UNDEAD : SPELL_ROCKET_LAUNCH_NORMAL)
+
enum EventTypes
{
// Highlord Tirion Fordring (at Light's Hammer)
@@ -121,6 +204,43 @@ enum EventTypes
// Frost Freeze Trap
EVENT_ACTIVATE_TRAP = 28,
+ // Crok Scourgebane
+ EVENT_SCOURGE_STRIKE = 29,
+ EVENT_DEATH_STRIKE = 30,
+ EVENT_HEALTH_CHECK = 31,
+ EVENT_CROK_INTRO_3 = 32,
+ EVENT_START_PATHING = 33,
+
+ // Sister Svalna
+ EVENT_ARNATH_INTRO_2 = 34,
+ EVENT_SVALNA_START = 35,
+ EVENT_SVALNA_RESURRECT = 36,
+ EVENT_SVALNA_COMBAT = 37,
+ EVENT_IMPALING_SPEAR = 38,
+ EVENT_AETHER_SHIELD = 39,
+
+ // Captain Arnath
+ EVENT_ARNATH_FLASH_HEAL = 40,
+ EVENT_ARNATH_PW_SHIELD = 41,
+ EVENT_ARNATH_SMITE = 42,
+ EVENT_ARNATH_DOMINATE_MIND = 43,
+
+ // Captain Brandon
+ EVENT_BRANDON_CRUSADER_STRIKE = 44,
+ EVENT_BRANDON_DIVINE_SHIELD = 45,
+ EVENT_BRANDON_JUDGEMENT_OF_COMMAND = 46,
+ EVENT_BRANDON_HAMMER_OF_BETRAYAL = 47,
+
+ // Captain Grondel
+ EVENT_GRONDEL_CHARGE_CHECK = 48,
+ EVENT_GRONDEL_MORTAL_STRIKE = 49,
+ EVENT_GRONDEL_SUNDER_ARMOR = 50,
+ EVENT_GRONDEL_CONFLAGRATION = 51,
+
+ // Captain Rupert
+ EVENT_RUPERT_FEL_IRON_BOMB = 52,
+ EVENT_RUPERT_MACHINE_GUN = 53,
+ EVENT_RUPERT_ROCKET_LAUNCH = 54,
};
enum DataTypesICC
@@ -128,6 +248,106 @@ enum DataTypesICC
DATA_DAMNED_KILLS = 1,
};
+enum Actions
+{
+ // Sister Svalna
+ ACTION_KILL_CAPTAIN = 1,
+ ACTION_START_GAUNTLET = 2,
+ ACTION_RESURRECT_CAPTAINS = 3,
+ ACTION_CAPTAIN_DIES = 4,
+ ACTION_RESET_EVENT = 5,
+};
+
+class FrostwingVrykulSearcher
+{
+ public:
+ FrostwingVrykulSearcher(Creature const* source, float range) : _source(source), _range(range) {}
+
+ bool operator()(Unit* unit)
+ {
+ if (!unit->isAlive())
+ return false;
+
+ switch (unit->GetEntry())
+ {
+ case NPC_YMIRJAR_BATTLE_MAIDEN:
+ case NPC_YMIRJAR_DEATHBRINGER:
+ case NPC_YMIRJAR_FROSTBINDER:
+ case NPC_YMIRJAR_HUNTRESS:
+ case NPC_YMIRJAR_WARLORD:
+ break;
+ default:
+ return false;
+ }
+
+ if (!unit->IsWithinDist(_source, _range, false))
+ return false;
+
+ return true;
+ }
+
+ private:
+ Creature const* _source;
+ float _range;
+};
+
+class FrostwingGauntletRespawner
+{
+ public:
+ void operator()(Creature* creature)
+ {
+ switch (creature->GetOriginalEntry())
+ {
+ case NPC_YMIRJAR_BATTLE_MAIDEN:
+ case NPC_YMIRJAR_DEATHBRINGER:
+ case NPC_YMIRJAR_FROSTBINDER:
+ case NPC_YMIRJAR_HUNTRESS:
+ case NPC_YMIRJAR_WARLORD:
+ break;
+ case NPC_CROK_SCOURGEBANE:
+ case NPC_CAPTAIN_ARNATH:
+ case NPC_CAPTAIN_BRANDON:
+ case NPC_CAPTAIN_GRONDEL:
+ case NPC_CAPTAIN_RUPERT:
+ creature->AI()->DoAction(ACTION_RESET_EVENT);
+ break;
+ case NPC_SISTER_SVALNA:
+ creature->AI()->DoAction(ACTION_RESET_EVENT);
+ // return, this creature is never dead if event is reset
+ return;
+ default:
+ return;
+ }
+
+ uint32 corpseDelay = creature->GetCorpseDelay();
+ uint32 respawnDelay = creature->GetRespawnDelay();
+ creature->SetCorpseDelay(1);
+ creature->SetRespawnDelay(2);
+
+ if (CreatureData const* data = creature->GetCreatureData())
+ creature->SetPosition(data->posX, data->posY, data->posZ, data->orientation);
+ creature->ForcedDespawn();
+
+ creature->SetCorpseDelay(corpseDelay);
+ creature->SetRespawnDelay(respawnDelay);
+ }
+};
+
+class CaptainSurviveTalk : public BasicEvent
+{
+ public:
+ explicit CaptainSurviveTalk(Creature const& owner) : _owner(owner) { }
+
+ bool Execute(uint64 /*currTime*/, uint32 /*diff*/)
+ {
+ _owner.AI()->Talk(SAY_CAPTAIN_SURVIVE_TALK);
+ return true;
+ }
+
+ private:
+ Creature const& _owner;
+};
+
// at Light's Hammer
class npc_highlord_tirion_fordring_lh : public CreatureScript
{
@@ -475,6 +695,958 @@ class npc_alchemist_adrianna : public CreatureScript
}
};
+class boss_sister_svalna : public CreatureScript
+{
+ public:
+ boss_sister_svalna() : CreatureScript("boss_sister_svalna") { }
+
+ struct boss_sister_svalnaAI : public BossAI
+ {
+ boss_sister_svalnaAI(Creature* creature) : BossAI(creature, DATA_SISTER_SVALNA),
+ _isEventInProgress(false)
+ {
+ }
+
+ void InitializeAI()
+ {
+ if (!me->isDead())
+ Reset();
+
+ me->SetReactState(REACT_PASSIVE);
+ }
+
+ void Reset()
+ {
+ _Reset();
+ me->SetReactState(REACT_DEFENSIVE);
+ _isEventInProgress = false;
+ }
+
+ void JustDied(Unit* /*killer*/)
+ {
+ _JustDied();
+ Talk(SAY_SVALNA_DEATH);
+
+ uint64 delay = 1;
+ for (uint32 i = 0; i < 4; ++i)
+ {
+ if (Creature* crusader = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_CAPTAIN_ARNATH + i)))
+ {
+ if (crusader->isAlive() && crusader->GetEntry() == crusader->GetCreatureData()->id)
+ {
+ crusader->m_Events.AddEvent(new CaptainSurviveTalk(*crusader), crusader->m_Events.CalculateTime(delay));
+ delay += 6000;
+ }
+ }
+ }
+ }
+
+ void EnterCombat(Unit* /*attacker*/)
+ {
+ _EnterCombat();
+ if (Creature* crok = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_CROK_SCOURGEBANE)))
+ crok->AI()->Talk(SAY_CROK_COMBAT_SVALNA);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_1);
+ events.ScheduleEvent(EVENT_SVALNA_COMBAT, 9000);
+ events.ScheduleEvent(EVENT_IMPALING_SPEAR, urand(40000, 50000));
+ events.ScheduleEvent(EVENT_AETHER_SHIELD, urand(100000, 110000));
+ }
+
+ void KilledUnit(Unit* victim)
+ {
+ switch (victim->GetTypeId())
+ {
+ case TYPEID_PLAYER:
+ Talk(SAY_SVALNA_KILL);
+ break;
+ case TYPEID_UNIT:
+ switch (victim->GetEntry())
+ {
+ case NPC_CAPTAIN_ARNATH:
+ case NPC_CAPTAIN_BRANDON:
+ case NPC_CAPTAIN_GRONDEL:
+ case NPC_CAPTAIN_RUPERT:
+ Talk(SAY_SVALNA_KILL_CAPTAIN);
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ void JustReachedHome()
+ {
+ _JustReachedHome();
+ me->SetReactState(REACT_PASSIVE);
+ }
+
+ void DoAction(int32 const action)
+ {
+ switch (action)
+ {
+ case ACTION_KILL_CAPTAIN:
+ me->CastCustomSpell(SPELL_CARESS_OF_DEATH, SPELLVALUE_MAX_TARGETS, 1, me, true);
+ break;
+ case ACTION_START_GAUNTLET:
+ me->setActive(true);
+ _isEventInProgress = true;
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_PASSIVE);
+ events.ScheduleEvent(EVENT_SVALNA_START, 25000);
+ break;
+ case ACTION_RESURRECT_CAPTAINS:
+ events.ScheduleEvent(EVENT_SVALNA_RESURRECT, 7000);
+ break;
+ case ACTION_CAPTAIN_DIES:
+ Talk(SAY_SVALNA_CAPTAIN_DEATH);
+ break;
+ case ACTION_RESET_EVENT:
+ me->setActive(false);
+ Reset();
+ break;
+ default:
+ break;
+ }
+ }
+
+ void SpellHit(Unit* caster, SpellEntry const* spell)
+ {
+ if (spell->Id == SPELL_HURL_SPEAR && me->HasAura(SPELL_AETHER_SHIELD))
+ {
+ me->RemoveAurasDueToSpell(SPELL_AETHER_SHIELD);
+ Talk(EMOTE_SVALNA_BROKEN_SHIELD, caster->GetGUID());
+ }
+ }
+
+ void SpellHitTarget(Unit* target, SpellEntry const* spell)
+ {
+ switch (spell->Id)
+ {
+ case SPELL_REVIVE_CHAMPION:
+ if (!_isEventInProgress)
+ break;
+ _isEventInProgress = false;
+ me->setActive(false);
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_PASSIVE);
+ break;
+ case SPELL_IMPALING_SPEAR_KILL:
+ me->Kill(target);
+ break;
+ case SPELL_IMPALING_SPEAR:
+ if (TempSummon* summon = target->SummonCreature(NPC_IMPALING_SPEAR, *target))
+ {
+ Talk(EMOTE_SVALNA_IMPALE, target->GetGUID());
+ summon->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_UNK1 | 0x4000);
+ summon->CastCustomSpell(VEHICLE_SPELL_RIDE_HARDCODED, SPELLVALUE_BASE_POINT0, 1, target, false);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ void UpdateAI(uint32 const diff)
+ {
+ if (!UpdateVictim() && !_isEventInProgress)
+ return;
+
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STAT_CASTING))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_SVALNA_START:
+ Talk(SAY_SVALNA_EVENT_START);
+ break;
+ case EVENT_SVALNA_RESURRECT:
+ Talk(SAY_SVALNA_RESURRECT_CAPTAINS);
+ me->CastSpell(me, SPELL_REVIVE_CHAMPION, false);
+ break;
+ case EVENT_SVALNA_COMBAT:
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_1);
+ me->SetReactState(REACT_DEFENSIVE);
+ Talk(SAY_SVALNA_AGGRO);
+ break;
+ case EVENT_IMPALING_SPEAR:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, -SPELL_IMPALING_SPEAR))
+ DoCast(target, SPELL_IMPALING_SPEAR);
+ events.ScheduleEvent(EVENT_IMPALING_SPEAR, urand(20000, 25000));
+ break;
+ default:
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+ private:
+ bool _isEventInProgress;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return GetIcecrownCitadelAI<boss_sister_svalnaAI>(creature);
+ }
+};
+
+class npc_crok_scourgebane : public CreatureScript
+{
+ public:
+ npc_crok_scourgebane() : CreatureScript("npc_crok_scourgebane") { }
+
+ struct npc_crok_scourgebaneAI : public npc_escortAI
+ {
+ npc_crok_scourgebaneAI(Creature* creature) : npc_escortAI(creature),
+ _instance(creature->GetInstanceScript()), _respawnTime(creature->GetRespawnDelay()),
+ _corpseDelay(creature->GetCorpseDelay())
+ {
+ SetDespawnAtEnd(false);
+ SetDespawnAtFar(false);
+ _isEventActive = false;
+ _isEventDone = false;
+ _didUnderTenPercentText = false;
+ }
+
+ void Reset()
+ {
+ _events.Reset();
+ _events.ScheduleEvent(EVENT_SCOURGE_STRIKE, urand(7500, 12500));
+ _events.ScheduleEvent(EVENT_DEATH_STRIKE, urand(25000, 30000));
+ me->SetReactState(REACT_DEFENSIVE);
+ _didUnderTenPercentText = false;
+ _wipeCheckTimer = 1000;
+ }
+
+ void DoAction(int32 const action)
+ {
+ if (action == ACTION_START_GAUNTLET)
+ {
+ if (_isEventDone || !me->isAlive())
+ return;
+
+ _isEventActive = true;
+ _isEventDone = true;
+ // Load Grid with Sister Svalna
+ me->GetMap()->LoadGrid(4356.71f, 2484.33f);
+ if (Creature* svalna = me->FindNearestCreature(NPC_SISTER_SVALNA, 333.0f, true))
+ svalna->AI()->DoAction(ACTION_START_GAUNTLET);
+ Talk(SAY_CROK_INTRO_1);
+ _events.ScheduleEvent(EVENT_ARNATH_INTRO_2, 7000);
+ _events.ScheduleEvent(EVENT_CROK_INTRO_3, 14000);
+ _events.ScheduleEvent(EVENT_START_PATHING, 37000);
+ me->setActive(true);
+ for (uint32 i = 0; i < 4; ++i)
+ if (Creature* crusader = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_CAPTAIN_ARNATH + i)))
+ crusader->AI()->DoAction(ACTION_START_GAUNTLET);
+ }
+ else if (action == ACTION_RESET_EVENT)
+ {
+ _isEventActive = false;
+ _isEventDone = false;
+ me->setActive(false);
+ _aliveTrash.clear();
+ _currentWPid = 0;
+ }
+ }
+
+ void SetGUID(uint64 const& guid, int32 type/* = 0*/)
+ {
+ if (type == ACTION_VRYKUL_DEATH)
+ {
+ _aliveTrash.erase(guid);
+ if (_aliveTrash.empty())
+ {
+ SetEscortPaused(false);
+ if (_currentWPid == 4 && _isEventActive)
+ {
+ _isEventActive = false;
+ me->setActive(false);
+ Talk(SAY_CROK_FINAL_WP);
+ if (Creature* svalna = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_SISTER_SVALNA)))
+ svalna->AI()->DoAction(ACTION_RESURRECT_CAPTAINS);
+ }
+ }
+ }
+ }
+
+ void WaypointReached(uint32 waypointId)
+ {
+ switch (waypointId)
+ {
+ // pause pathing until trash pack is cleared
+ case 0:
+ Talk(SAY_CROK_COMBAT_WP_0);
+ if (!_aliveTrash.empty())
+ SetEscortPaused(true);
+ break;
+ case 1:
+ Talk(SAY_CROK_COMBAT_WP_1);
+ if (!_aliveTrash.empty())
+ SetEscortPaused(true);
+ break;
+ case 4:
+ if (_aliveTrash.empty() && _isEventActive)
+ {
+ _isEventActive = false;
+ me->setActive(false);
+ Talk(SAY_CROK_FINAL_WP);
+ if (Creature* svalna = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_SISTER_SVALNA)))
+ svalna->AI()->DoAction(ACTION_RESURRECT_CAPTAINS);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ void WaypointStart(uint32 waypointId)
+ {
+ _currentWPid = waypointId;
+ switch (waypointId)
+ {
+ case 0:
+ case 1:
+ case 4:
+ {
+ // get spawns by home position
+ float minY = 2600.0f;
+ float maxY = 2650.0f;
+ if (waypointId == 1)
+ {
+ minY -= 50.0f;
+ maxY -= 50.0f;
+ // at waypoints 1 and 2 she kills one captain
+ if (Creature* svalna = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_SISTER_SVALNA)))
+ svalna->AI()->DoAction(ACTION_KILL_CAPTAIN);
+ }
+ else if (waypointId == 4)
+ {
+ minY -= 100.0f;
+ maxY -= 100.0f;
+ }
+
+ // get all nearby vrykul
+ std::list<Creature*> temp;
+ FrostwingVrykulSearcher check(me, 80.0f);
+ Trinity::CreatureListSearcher<FrostwingVrykulSearcher> searcher(me, temp, check);
+ me->VisitNearbyGridObject(80.0f, searcher);
+
+ _aliveTrash.clear();
+ for (std::list<Creature*>::iterator itr = temp.begin(); itr != temp.end(); ++itr)
+ if ((*itr)->GetHomePosition().GetPositionY() < maxY && (*itr)->GetHomePosition().GetPositionY() > minY)
+ _aliveTrash.insert((*itr)->GetGUID());
+ break;
+ }
+ // at waypoints 1 and 2 she kills one captain
+ case 2:
+ if (Creature* svalna = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_SISTER_SVALNA)))
+ svalna->AI()->DoAction(ACTION_KILL_CAPTAIN);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void DamageTaken(Unit* /*attacker*/, uint32& damage)
+ {
+ // check wipe
+ if (!_wipeCheckTimer)
+ {
+ _wipeCheckTimer = 1000;
+ Player* player = NULL;
+ Trinity::AnyPlayerInObjectRangeCheck check(me, 60.0f);
+ Trinity::PlayerSearcher<Trinity::AnyPlayerInObjectRangeCheck> searcher(me, player, check);
+ me->VisitNearbyWorldObject(60.0f, searcher);
+ // wipe
+ if (!player)
+ {
+ damage *= 100;
+ if (damage >= me->GetHealth())
+ {
+ FrostwingGauntletRespawner respawner;
+ Trinity::CreatureWorker<FrostwingGauntletRespawner> worker(me, respawner);
+ me->VisitNearbyGridObject(333.0f, worker);
+ Talk(SAY_CROK_DEATH);
+ }
+ return;
+ }
+ }
+
+ if (HealthBelowPct(10))
+ {
+ if (!_didUnderTenPercentText)
+ {
+ _didUnderTenPercentText = true;
+ if (_isEventActive)
+ Talk(SAY_CROK_WEAKENING_GAUNTLET);
+ else
+ Talk(SAY_CROK_WEAKENING_SVALNA);
+ }
+
+ damage = 0;
+ DoCast(me, SPELL_ICEBOUND_ARMOR);
+ _events.ScheduleEvent(EVENT_HEALTH_CHECK, 1000);
+ }
+ }
+
+ void UpdateEscortAI(uint32 const diff)
+ {
+ if (_wipeCheckTimer <= diff)
+ _wipeCheckTimer = 0;
+ else
+ _wipeCheckTimer -= diff;
+
+ if (!UpdateVictim() && !_isEventActive)
+ return;
+
+ _events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STAT_CASTING))
+ return;
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_ARNATH_INTRO_2:
+ if (Creature* arnath = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_CAPTAIN_ARNATH)))
+ arnath->AI()->Talk(SAY_ARNATH_INTRO_2);
+ break;
+ case EVENT_CROK_INTRO_3:
+ Talk(SAY_CROK_INTRO_3);
+ break;
+ case EVENT_START_PATHING:
+ Start(true, true);
+ break;
+ case EVENT_SCOURGE_STRIKE:
+ DoCastVictim(SPELL_SCOURGE_STRIKE);
+ _events.ScheduleEvent(EVENT_SCOURGE_STRIKE, urand(10000, 14000));
+ break;
+ case EVENT_DEATH_STRIKE:
+ if (HealthBelowPct(20))
+ DoCastVictim(SPELL_DEATH_STRIKE);
+ _events.ScheduleEvent(EVENT_DEATH_STRIKE, urand(5000, 10000));
+ break;
+ case EVENT_HEALTH_CHECK:
+ if (HealthAbovePct(15))
+ {
+ me->RemoveAurasDueToSpell(SPELL_ICEBOUND_ARMOR);
+ _didUnderTenPercentText = false;
+ }
+ else
+ {
+ me->DealHeal(me, me->CountPctFromMaxHealth(5));
+ _events.ScheduleEvent(EVENT_HEALTH_CHECK, 1000);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+ bool CanAIAttack(Unit const* target) const
+ {
+ // do not see targets inside Frostwing Halls when we are not there
+ return (me->GetPositionY() > 2660.0f) == (target->GetPositionY() > 2660.0f);
+ }
+
+ private:
+ EventMap _events;
+ std::set<uint64> _aliveTrash;
+ InstanceScript* _instance;
+ uint32 _currentWPid;
+ uint32 _wipeCheckTimer;
+ uint32 const _respawnTime;
+ uint32 const _corpseDelay;
+ bool _isEventActive;
+ bool _isEventDone;
+ bool _didUnderTenPercentText;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return GetIcecrownCitadelAI<npc_crok_scourgebaneAI>(creature);
+ }
+};
+
+struct npc_argent_captainAI : public ScriptedAI
+{
+ public:
+ npc_argent_captainAI(Creature* creature) : ScriptedAI(creature), Instance(creature->GetInstanceScript()), _firstDeath(true)
+ {
+ FollowAngle = PET_FOLLOW_ANGLE;
+ FollowDist = PET_FOLLOW_DIST;
+ IsUndead = false;
+ }
+
+ void JustDied(Unit* /*killer*/)
+ {
+ if (_firstDeath)
+ {
+ _firstDeath = false;
+ Talk(SAY_CAPTAIN_DEATH);
+ }
+ else
+ Talk(SAY_CAPTAIN_SECOND_DEATH);
+ }
+
+ void KilledUnit(Unit* victim)
+ {
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ Talk(SAY_CAPTAIN_KILL);
+ }
+
+ void DoAction(int32 const action)
+ {
+ if (action == ACTION_START_GAUNTLET)
+ {
+ if (Creature* crok = ObjectAccessor::GetCreature(*me, Instance->GetData64(DATA_CROK_SCOURGEBANE)))
+ {
+ me->SetReactState(REACT_DEFENSIVE);
+ FollowAngle = me->GetAngle(crok) + me->GetOrientation();
+ FollowDist = me->GetDistance2d(crok);
+ me->GetMotionMaster()->MoveFollow(crok, FollowDist, FollowAngle, MOTION_SLOT_IDLE);
+ }
+
+ me->setActive(true);
+ }
+ else if (action == ACTION_RESET_EVENT)
+ {
+ _firstDeath = true;
+ }
+ }
+
+ void EnterCombat(Unit* /*target*/)
+ {
+ me->SetHomePosition(*me);
+ if (IsUndead)
+ DoZoneInCombat();
+ }
+
+ bool CanAIAttack(Unit const* target) const
+ {
+ // do not see targets inside Frostwing Halls when we are not there
+ return (me->GetPositionY() > 2660.0f) == (target->GetPositionY() > 2660.0f);
+ }
+
+ void EnterEvadeMode()
+ {
+ // not yet following
+ if (me->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_IDLE) != TARGETED_MOTION_TYPE || IsUndead)
+ {
+ ScriptedAI::EnterEvadeMode();
+ return;
+ }
+
+ if (!_EnterEvadeMode())
+ return;
+
+ if (!me->GetVehicle())
+ {
+ me->GetMotionMaster()->Clear(false);
+ if (Creature* crok = ObjectAccessor::GetCreature(*me, Instance->GetData64(DATA_CROK_SCOURGEBANE)))
+ me->GetMotionMaster()->MoveFollow(crok, FollowDist, FollowAngle, MOTION_SLOT_IDLE);
+ }
+
+ Reset();
+ }
+
+ void SpellHit(Unit* /*caster*/, SpellEntry const* spell)
+ {
+ if (spell->Id == SPELL_REVIVE_CHAMPION && !IsUndead)
+ {
+ IsUndead = true;
+ me->setDeathState(JUST_ALIVED);
+ uint32 newEntry = 0;
+ switch (me->GetEntry())
+ {
+ case NPC_CAPTAIN_ARNATH:
+ newEntry = NPC_CAPTAIN_ARNATH_UNDEAD;
+ break;
+ case NPC_CAPTAIN_BRANDON:
+ newEntry = NPC_CAPTAIN_BRANDON_UNDEAD;
+ break;
+ case NPC_CAPTAIN_GRONDEL:
+ newEntry = NPC_CAPTAIN_GRONDEL_UNDEAD;
+ break;
+ case NPC_CAPTAIN_RUPERT:
+ newEntry = NPC_CAPTAIN_RUPERT_UNDEAD;
+ break;
+ default:
+ return;
+ }
+
+ Talk(SAY_CAPTAIN_RESURRECTED);
+ me->UpdateEntry(newEntry, Instance->GetData(DATA_TEAM_IN_INSTANCE), me->GetCreatureData());
+ DoCast(me, SPELL_UNDEATH, true);
+ }
+ }
+
+ protected:
+ EventMap Events;
+ InstanceScript* Instance;
+ float FollowAngle;
+ float FollowDist;
+ bool IsUndead;
+
+ private:
+ bool _firstDeath;
+};
+
+class npc_captain_arnath : public CreatureScript
+{
+ public:
+ npc_captain_arnath() : CreatureScript("npc_captain_arnath") { }
+
+ struct npc_captain_arnathAI : public npc_argent_captainAI
+ {
+ npc_captain_arnathAI(Creature* creature) : npc_argent_captainAI(creature)
+ {
+ }
+
+ void Reset()
+ {
+ Events.Reset();
+ Events.ScheduleEvent(EVENT_ARNATH_FLASH_HEAL, urand(4000, 7000));
+ Events.ScheduleEvent(EVENT_ARNATH_PW_SHIELD, urand(8000, 14000));
+ Events.ScheduleEvent(EVENT_ARNATH_SMITE, urand(3000, 6000));
+ if (Is25ManRaid() && IsUndead)
+ Events.ScheduleEvent(EVENT_ARNATH_DOMINATE_MIND, urand(22000, 27000));
+ }
+
+ void UpdateAI(uint32 const diff)
+ {
+ if (!UpdateVictim())
+ return;
+
+ Events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STAT_CASTING))
+ return;
+
+ while (uint32 eventId = Events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_ARNATH_FLASH_HEAL:
+ if (Creature* target = FindFriendlyCreature())
+ DoCast(target, SPELL_FLASH_HEAL);
+ Events.ScheduleEvent(EVENT_ARNATH_FLASH_HEAL, urand(6000, 9000));
+ break;
+ case EVENT_ARNATH_PW_SHIELD:
+ {
+ std::list<Creature*> targets = DoFindFriendlyMissingBuff(40.0f, SPELL_POWER_WORD_SHIELD);
+ std::list<Creature*>::iterator itr = targets.begin();
+ std::advance(itr, urand(0, targets.size() - 1));
+ DoCast(*itr, SPELL_POWER_WORD_SHIELD);
+ Events.ScheduleEvent(EVENT_ARNATH_PW_SHIELD, urand(15000, 20000));
+ break;
+ }
+ case EVENT_ARNATH_SMITE:
+ DoCastVictim(SPELL_SMITE);
+ Events.ScheduleEvent(EVENT_ARNATH_SMITE, urand(4000, 7000));
+ break;
+ case EVENT_ARNATH_DOMINATE_MIND:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true))
+ DoCast(target, SPELL_DOMINATE_MIND);
+ Events.ScheduleEvent(EVENT_ARNATH_DOMINATE_MIND, urand(28000, 37000));
+ break;
+ default:
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+ private:
+ Creature* FindFriendlyCreature() const
+ {
+ Creature* target = NULL;
+ Trinity::MostHPMissingInRange u_check(me, 60.0f, 0);
+ Trinity::CreatureLastSearcher<Trinity::MostHPMissingInRange> searcher(me, target, u_check);
+ me->VisitNearbyGridObject(60.0f, searcher);
+ return target;
+ }
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return GetIcecrownCitadelAI<npc_captain_arnathAI>(creature);
+ }
+};
+
+class npc_captain_brandon : public CreatureScript
+{
+ public:
+ npc_captain_brandon() : CreatureScript("npc_captain_brandon") { }
+
+ struct npc_captain_brandonAI : public npc_argent_captainAI
+ {
+ npc_captain_brandonAI(Creature* creature) : npc_argent_captainAI(creature)
+ {
+ }
+
+ void Reset()
+ {
+ Events.Reset();
+ Events.ScheduleEvent(EVENT_BRANDON_CRUSADER_STRIKE, urand(6000, 10000));
+ Events.ScheduleEvent(EVENT_BRANDON_DIVINE_SHIELD, 500);
+ Events.ScheduleEvent(EVENT_BRANDON_JUDGEMENT_OF_COMMAND, urand(8000, 13000));
+ if (IsUndead)
+ Events.ScheduleEvent(EVENT_BRANDON_HAMMER_OF_BETRAYAL, urand(25000, 30000));
+ }
+
+ void UpdateAI(uint32 const diff)
+ {
+ if (!UpdateVictim())
+ return;
+
+ Events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STAT_CASTING))
+ return;
+
+ while (uint32 eventId = Events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_BRANDON_CRUSADER_STRIKE:
+ DoCastVictim(SPELL_CRUSADER_STRIKE);
+ Events.ScheduleEvent(EVENT_BRANDON_CRUSADER_STRIKE, urand(6000, 12000));
+ break;
+ case EVENT_BRANDON_DIVINE_SHIELD:
+ if (HealthBelowPct(20))
+ DoCast(me, SPELL_DIVINE_SHIELD);
+ Events.ScheduleEvent(EVENT_BRANDON_DIVINE_SHIELD, 500);
+ break;
+ case EVENT_BRANDON_JUDGEMENT_OF_COMMAND:
+ DoCastVictim(SPELL_JUDGEMENT_OF_COMMAND);
+ Events.ScheduleEvent(EVENT_BRANDON_JUDGEMENT_OF_COMMAND, urand(8000, 13000));
+ break;
+ case EVENT_BRANDON_HAMMER_OF_BETRAYAL:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true))
+ DoCast(target, SPELL_HAMMER_OF_BETRAYAL);
+ Events.ScheduleEvent(EVENT_BRANDON_HAMMER_OF_BETRAYAL, urand(45000, 60000));
+ break;
+ default:
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return GetIcecrownCitadelAI<npc_captain_brandonAI>(creature);
+ }
+};
+
+class npc_captain_grondel : public CreatureScript
+{
+ public:
+ npc_captain_grondel() : CreatureScript("npc_captain_grondel") { }
+
+ struct npc_captain_grondelAI : public npc_argent_captainAI
+ {
+ npc_captain_grondelAI(Creature* creature) : npc_argent_captainAI(creature)
+ {
+ }
+
+ void Reset()
+ {
+ Events.Reset();
+ Events.ScheduleEvent(EVENT_GRONDEL_CHARGE_CHECK, 500);
+ Events.ScheduleEvent(EVENT_GRONDEL_MORTAL_STRIKE, urand(8000, 14000));
+ Events.ScheduleEvent(EVENT_GRONDEL_SUNDER_ARMOR, urand(3000, 12000));
+ if (IsUndead)
+ Events.ScheduleEvent(EVENT_GRONDEL_CONFLAGRATION, urand(12000, 17000));
+ }
+
+ void UpdateAI(uint32 const diff)
+ {
+ if (!UpdateVictim())
+ return;
+
+ Events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STAT_CASTING))
+ return;
+
+ while (uint32 eventId = Events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_GRONDEL_CHARGE_CHECK:
+ if (CanCast(me->getVictim(), sSpellStore.LookupEntry(SPELL_CHARGE)))
+ DoCastVictim(SPELL_CHARGE);
+ Events.ScheduleEvent(EVENT_GRONDEL_CHARGE_CHECK, 500);
+ break;
+ case EVENT_GRONDEL_MORTAL_STRIKE:
+ DoCastVictim(SPELL_MORTAL_STRIKE);
+ Events.ScheduleEvent(EVENT_GRONDEL_MORTAL_STRIKE, urand(10000, 15000));
+ break;
+ case EVENT_GRONDEL_SUNDER_ARMOR:
+ DoCastVictim(SPELL_SUNDER_ARMOR);
+ Events.ScheduleEvent(EVENT_GRONDEL_SUNDER_ARMOR, urand(5000, 17000));
+ break;
+ case EVENT_GRONDEL_CONFLAGRATION:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
+ DoCast(target, SPELL_CONFLAGRATION);
+ Events.ScheduleEvent(EVENT_GRONDEL_CONFLAGRATION, urand(10000, 15000));
+ break;
+ default:
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return GetIcecrownCitadelAI<npc_captain_grondelAI>(creature);
+ }
+};
+
+class npc_captain_rupert : public CreatureScript
+{
+ public:
+ npc_captain_rupert() : CreatureScript("npc_captain_rupert") { }
+
+ struct npc_captain_rupertAI : public npc_argent_captainAI
+ {
+ npc_captain_rupertAI(Creature* creature) : npc_argent_captainAI(creature)
+ {
+ }
+
+ void Reset()
+ {
+ Events.Reset();
+ Events.ScheduleEvent(EVENT_RUPERT_FEL_IRON_BOMB, urand(15000, 20000));
+ Events.ScheduleEvent(EVENT_RUPERT_MACHINE_GUN, urand(25000, 30000));
+ Events.ScheduleEvent(EVENT_RUPERT_ROCKET_LAUNCH, urand(10000, 15000));
+ }
+
+ void UpdateAI(uint32 const diff)
+ {
+ if (!UpdateVictim())
+ return;
+
+ Events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STAT_CASTING))
+ return;
+
+ while (uint32 eventId = Events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_RUPERT_FEL_IRON_BOMB:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
+ DoCast(target, SPELL_FEL_IRON_BOMB);
+ Events.ScheduleEvent(EVENT_RUPERT_FEL_IRON_BOMB, urand(15000, 20000));
+ break;
+ case EVENT_RUPERT_MACHINE_GUN:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1))
+ DoCast(target, SPELL_MACHINE_GUN);
+ Events.ScheduleEvent(EVENT_RUPERT_MACHINE_GUN, urand(25000, 30000));
+ break;
+ case EVENT_RUPERT_ROCKET_LAUNCH:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1))
+ DoCast(target, SPELL_ROCKET_LAUNCH);
+ Events.ScheduleEvent(EVENT_RUPERT_ROCKET_LAUNCH, urand(10000, 15000));
+ break;
+ default:
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return GetIcecrownCitadelAI<npc_captain_rupertAI>(creature);
+ }
+};
+
+class npc_frostwing_vrykul : public CreatureScript
+{
+ public:
+ npc_frostwing_vrykul() : CreatureScript("npc_frostwing_vrykul") { }
+
+ struct npc_frostwing_vrykulAI : public SmartAI
+ {
+ npc_frostwing_vrykulAI(Creature* creature) : SmartAI(creature)
+ {
+ }
+
+ bool CanAIAttack(Unit const* target) const
+ {
+ // do not see targets inside Frostwing Halls when we are not there
+ return (me->GetPositionY() > 2660.0f) == (target->GetPositionY() > 2660.0f) && SmartAI::CanAIAttack(target);
+ }
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return new npc_frostwing_vrykulAI(creature);
+ }
+};
+
+class npc_impaling_spear : public CreatureScript
+{
+ public:
+ npc_impaling_spear() : CreatureScript("npc_impaling_spear") { }
+
+ struct npc_impaling_spearAI : public CreatureAI
+ {
+ npc_impaling_spearAI(Creature* creature) : CreatureAI(creature)
+ {
+ }
+
+ void Reset()
+ {
+ me->SetReactState(REACT_PASSIVE);
+ _vehicleCheckTimer = 500;
+ }
+
+ void UpdateAI(uint32 const diff)
+ {
+ if (_vehicleCheckTimer <= diff)
+ {
+ _vehicleCheckTimer = 500;
+ if (!me->GetVehicle())
+ me->DespawnOrUnsummon(100);
+ }
+ else
+ _vehicleCheckTimer -= diff;
+ }
+
+ uint32 _vehicleCheckTimer;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return new npc_impaling_spearAI(creature);
+ }
+};
+
class DeathPlagueTargetSelector
{
public:
@@ -595,6 +1767,70 @@ class spell_icc_harvest_blight_specimen : public SpellScriptLoader
}
};
+class AliveCheck
+{
+ public:
+ bool operator()(Unit* unit)
+ {
+ return unit->isAlive();
+ }
+};
+
+class spell_svalna_revive_champion : public SpellScriptLoader
+{
+ public:
+ spell_svalna_revive_champion() : SpellScriptLoader("spell_svalna_revive_champion") { }
+
+ class spell_svalna_revive_champion_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_svalna_revive_champion_SpellScript);
+
+ void RemoveAliveTarget(std::list<Unit*>& unitList)
+ {
+ unitList.remove_if(AliveCheck());
+ Trinity::RandomResizeList(unitList, 2);
+ }
+
+ void Register()
+ {
+ OnUnitTargetSelect += SpellUnitTargetFn(spell_svalna_revive_champion_SpellScript::RemoveAliveTarget, EFFECT_0, TARGET_UNIT_AREA_ENTRY_DST);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_svalna_revive_champion_SpellScript();
+ }
+};
+
+class spell_svalna_remove_spear : public SpellScriptLoader
+{
+ public:
+ spell_svalna_remove_spear() : SpellScriptLoader("spell_svalna_remove_spear") { }
+
+ class spell_svalna_remove_spear_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_svalna_remove_spear_SpellScript);
+
+ void HandleScript(SpellEffIndex effIndex)
+ {
+ PreventHitDefaultEffect(effIndex);
+ if (Creature* target = GetHitCreature())
+ target->DespawnOrUnsummon();
+ }
+
+ void Register()
+ {
+ OnEffect += SpellEffectFn(spell_svalna_remove_spear_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_svalna_remove_spear_SpellScript();
+ }
+};
+
class at_icc_saurfang_portal : public AreaTriggerScript
{
public:
@@ -624,6 +1860,7 @@ class at_icc_saurfang_portal : public AreaTriggerScript
instant = !instant;
}
}
+
return true;
}
};
@@ -656,15 +1893,41 @@ class at_icc_start_blood_quickening : public AreaTriggerScript
}
};
+class at_icc_start_frostwing_gauntlet : public AreaTriggerScript
+{
+ public:
+ at_icc_start_frostwing_gauntlet() : AreaTriggerScript("at_icc_start_frostwing_gauntlet") { }
+
+ bool OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/)
+ {
+ if (InstanceScript* instance = player->GetInstanceScript())
+ if (Creature* crok = ObjectAccessor::GetCreature(*player, instance->GetData64(DATA_CROK_SCOURGEBANE)))
+ crok->AI()->DoAction(ACTION_START_GAUNTLET);
+ return true;
+ }
+};
+
void AddSC_icecrown_citadel()
{
new npc_highlord_tirion_fordring_lh();
new npc_rotting_frost_giant();
new npc_frost_freeze_trap();
new npc_alchemist_adrianna();
+ new boss_sister_svalna();
+ new npc_crok_scourgebane();
+ new npc_captain_arnath();
+ new npc_captain_brandon();
+ new npc_captain_grondel();
+ new npc_captain_rupert();
+ new npc_frostwing_vrykul();
+ new npc_impaling_spear();
new spell_frost_giant_death_plague();
new spell_icc_harvest_blight_specimen();
+ new spell_trigger_spell_from_caster("spell_svalna_caress_of_death", SPELL_IMPALING_SPEAR_KILL);
+ new spell_svalna_revive_champion();
+ new spell_svalna_remove_spear();
new at_icc_saurfang_portal();
new at_icc_shutdown_traps();
new at_icc_start_blood_quickening();
+ new at_icc_start_frostwing_gauntlet();
}
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h
index f46de1a6cd7..137ac32df24 100755
--- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h
+++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h
@@ -24,7 +24,7 @@
#define ICCScriptName "instance_icecrown_citadel"
-uint32 const EncounterCount = 12;
+uint32 const EncounterCount = 13;
uint32 const WeeklyNPCs = 9;
uint32 const MaxHeroicAttempts = 50;
// Defined in boss_sindragosa.cpp
@@ -64,12 +64,13 @@ enum DataTypes
DATA_PROFESSOR_PUTRICIDE = 6,
DATA_BLOOD_PRINCE_COUNCIL = 7,
DATA_BLOOD_QUEEN_LANA_THEL = 8,
- DATA_VALITHRIA_DREAMWALKER = 9,
- DATA_SINDRAGOSA = 10,
- DATA_THE_LICH_KING = 11,
+ DATA_SISTER_SVALNA = 9,
+ DATA_VALITHRIA_DREAMWALKER = 10,
+ DATA_SINDRAGOSA = 11,
+ DATA_THE_LICH_KING = 12,
// Additional data
- DATA_SAURFANG_EVENT_NPC = 12,
+ DATA_SAURFANG_EVENT_NPC = 34,
DATA_BONED_ACHIEVEMENT = 13,
DATA_OOZE_DANCE_ACHIEVEMENT = 14,
DATA_PUTRICIDE_TABLE = 15,
@@ -86,6 +87,11 @@ enum DataTypes
DATA_TEAM_IN_INSTANCE = 26,
DATA_BLOOD_QUICKENING_STATE = 27,
DATA_HEROIC_ATTEMPTS = 28,
+ DATA_CROK_SCOURGEBANE = 29,
+ DATA_CAPTAIN_ARNATH = 30,
+ DATA_CAPTAIN_BRANDON = 31,
+ DATA_CAPTAIN_GRONDEL = 32,
+ DATA_CAPTAIN_RUPERT = 33,
};
enum CreaturesIds
@@ -186,6 +192,34 @@ enum CreaturesIds
// Blood-Queen Lana'thel
NPC_BLOOD_QUEEN_LANA_THEL = 37955,
+ // Frostwing Halls gauntlet event
+ NPC_CROK_SCOURGEBANE = 37129,
+ NPC_CAPTAIN_ARNATH = 37122,
+ NPC_CAPTAIN_BRANDON = 37123,
+ NPC_CAPTAIN_GRONDEL = 37124,
+ NPC_CAPTAIN_RUPERT = 37125,
+ NPC_CAPTAIN_ARNATH_UNDEAD = 37491,
+ NPC_CAPTAIN_BRANDON_UNDEAD = 37493,
+ NPC_CAPTAIN_GRONDEL_UNDEAD = 37494,
+ NPC_CAPTAIN_RUPERT_UNDEAD = 37495,
+ NPC_YMIRJAR_BATTLE_MAIDEN = 37132,
+ NPC_YMIRJAR_DEATHBRINGER = 38125,
+ NPC_YMIRJAR_FROSTBINDER = 37127,
+ NPC_YMIRJAR_HUNTRESS = 37134,
+ NPC_YMIRJAR_WARLORD = 37133,
+ NPC_SISTER_SVALNA = 37126,
+ NPC_IMPALING_SPEAR = 38248,
+
+ // Valithria Dreamwalker
+ NPC_VALITHRIA_DREAMWALKER = 36789,
+ NPC_GREEN_DRAGON_COMBAT_TRIGGER = 38752,
+ NPC_RISEN_ARCHMAGE = 37868,
+ NPC_BLAZING_SKELETON = 36791,
+ NPC_SUPPRESSER = 37863,
+ NPC_BLISTERING_ZOMBIE = 37934,
+ NPC_GLUTTONOUS_ABOMINATION = 37886,
+ NPC_THE_LICH_KING_VALITHRIA = 16980,
+
// Sindragosa
NPC_SINDRAGOSA = 36853,
NPC_SPINESTALKER = 37534,
@@ -305,6 +339,9 @@ enum SharedActions
// Blood-Queen Lana'thel
ACTION_KILL_MINCHAR = -379550,
+ // Frostwing Halls gauntlet event
+ ACTION_VRYKUL_DEATH = 37129,
+
// Sindragosa
ACTION_START_FROSTWYRM = -368530,
ACTION_TRIGGER_ASPHYXIATION = -368531,
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp
index 7f00fa08ad7..f537a70d61e 100755
--- a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp
@@ -38,6 +38,7 @@ DoorData const doorData[] =
{GO_BLOOD_ELF_COUNCIL_DOOR_RIGHT, DATA_BLOOD_PRINCE_COUNCIL, DOOR_TYPE_PASSAGE, BOUNDARY_E },
{GO_DOODAD_ICECROWN_BLOODPRINCE_DOOR_01, DATA_BLOOD_QUEEN_LANA_THEL, DOOR_TYPE_ROOM, BOUNDARY_S },
{GO_DOODAD_ICECROWN_GRATE_01, DATA_BLOOD_QUEEN_LANA_THEL, DOOR_TYPE_PASSAGE, BOUNDARY_NONE},
+ {GO_GREEN_DRAGON_BOSS_ENTRANCE, DATA_SISTER_SVALNA, DOOR_TYPE_PASSAGE, BOUNDARY_S },
{GO_GREEN_DRAGON_BOSS_ENTRANCE, DATA_VALITHRIA_DREAMWALKER, DOOR_TYPE_ROOM, BOUNDARY_N },
{GO_GREEN_DRAGON_BOSS_EXIT, DATA_VALITHRIA_DREAMWALKER, DOOR_TYPE_PASSAGE, BOUNDARY_S },
{GO_SINDRAGOSA_ENTRANCE_DOOR, DATA_SINDRAGOSA, DOOR_TYPE_ROOM, BOUNDARY_S },
@@ -101,6 +102,9 @@ class instance_icecrown_citadel : public InstanceMapScript
memset(BloodCouncilGUIDs, 0, 3*sizeof(uint64));
BloodCouncilControllerGUID = 0;
BloodQueenLanaThelGUID = 0;
+ CrokScourgebaneGUID = 0;
+ memset(CrokCaptainGUIDs, 0, 4 * sizeof(uint64));
+ SisterSvalnaGUID = 0;
SindragosaGUID = 0;
SpinestalkerGUID = 0;
RimefangGUID = 0;
@@ -221,6 +225,19 @@ class instance_icecrown_citadel : public InstanceMapScript
case NPC_BLOOD_QUEEN_LANA_THEL:
BloodQueenLanaThelGUID = creature->GetGUID();
break;
+ case NPC_CROK_SCOURGEBANE:
+ CrokScourgebaneGUID = creature->GetGUID();
+ break;
+ // we can only do this because there are no gaps in their entries
+ case NPC_CAPTAIN_ARNATH:
+ case NPC_CAPTAIN_BRANDON:
+ case NPC_CAPTAIN_GRONDEL:
+ case NPC_CAPTAIN_RUPERT:
+ CrokCaptainGUIDs[creature->GetEntry()-NPC_CAPTAIN_ARNATH] = creature->GetGUID();
+ break;
+ case NPC_SISTER_SVALNA:
+ SisterSvalnaGUID = creature->GetGUID();
+ break;
case NPC_SINDRAGOSA:
SindragosaGUID = creature->GetGUID();
break;
@@ -278,6 +295,23 @@ class instance_icecrown_citadel : public InstanceMapScript
ColdflameJetGUIDs.erase(creature->GetGUID());
}
+ void OnCreatureDeath(Creature* creature)
+ {
+ switch (creature->GetEntry())
+ {
+ case NPC_YMIRJAR_BATTLE_MAIDEN:
+ case NPC_YMIRJAR_DEATHBRINGER:
+ case NPC_YMIRJAR_FROSTBINDER:
+ case NPC_YMIRJAR_HUNTRESS:
+ case NPC_YMIRJAR_WARLORD:
+ if (Creature* crok = instance->GetCreature(CrokScourgebaneGUID))
+ crok->AI()->SetGUID(creature->GetGUID(), ACTION_VRYKUL_DEATH);
+ break;
+ default:
+ break;
+ }
+ }
+
void OnGameObjectCreate(GameObject* go)
{
switch (go->GetEntry())
@@ -466,6 +500,15 @@ class instance_icecrown_citadel : public InstanceMapScript
return SpinestalkerGUID;
case DATA_RIMEFANG:
return RimefangGUID;
+ case DATA_CROK_SCOURGEBANE:
+ return CrokScourgebaneGUID;
+ case DATA_CAPTAIN_ARNATH:
+ case DATA_CAPTAIN_BRANDON:
+ case DATA_CAPTAIN_GRONDEL:
+ case DATA_CAPTAIN_RUPERT:
+ return CrokCaptainGUIDs[type-DATA_CAPTAIN_ARNATH];
+ case DATA_SISTER_SVALNA:
+ return SisterSvalnaGUID;
default:
break;
}
@@ -1011,6 +1054,9 @@ class instance_icecrown_citadel : public InstanceMapScript
uint64 BloodCouncilGUIDs[3];
uint64 BloodCouncilControllerGUID;
uint64 BloodQueenLanaThelGUID;
+ uint64 CrokScourgebaneGUID;
+ uint64 CrokCaptainGUIDs[4];
+ uint64 SisterSvalnaGUID;
uint64 SindragosaGUID;
uint64 SpinestalkerGUID;
uint64 RimefangGUID;