Last active
December 29, 2015 03:08
-
-
Save Cashew/7605092 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From bf267e6a2e9c9153b3891658d501416f8bbac216 Mon Sep 17 00:00:00 2001 | |
From: Cashew <KWossning@web.de> | |
Date: Fri, 22 Nov 2013 22:54:47 +0100 | |
Subject: [PATCH] Skadi-rewrite | |
--- | |
sql/updates/world_skadi.sql | 11 + | |
.../UtgardeKeep/UtgardePinnacle/boss_skadi.cpp | 545 ++++++++++++--------- | |
.../UtgardePinnacle/instance_utgarde_pinnacle.cpp | 6 + | |
.../UtgardeKeep/UtgardePinnacle/utgarde_pinnacle.h | 3 +- | |
4 files changed, 335 insertions(+), 230 deletions(-) | |
create mode 100644 sql/updates/world_skadi.sql | |
diff --git a/sql/updates/world_skadi.sql b/sql/updates/world_skadi.sql | |
new file mode 100644 | |
index 0000000..e8331e7 | |
--- /dev/null | |
+++ b/sql/updates/world_skadi.sql | |
@@ -0,0 +1,11 @@ | |
+UPDATE `creature_template` SET `InhabitType`= 7, `ScriptName`= "mob_grauf" WHERE `entry`= 26893; | |
+ | |
+-- Written by Carbenium | |
+DELETE FROM `spell_target_position` WHERE `id` = 61790; | |
+INSERT INTO `spell_target_position` (`id`, `effIndex`, `target_map`, `target_position_x`, `target_position_y`, `target_position_z`, `target_orientation`) VALUES | |
+('61790', '0', '575', '480.84', '-511.95', '104.72', '2.71'); | |
+ | |
+-- Without this modification the Harpoondamage will be affected by players spellpower | |
+DELETE FROM `spell_bonus_data` WHERE `entry` IN (56578); | |
+INSERT INTO `spell_bonus_data` (`entry`,`direct_bonus`,`dot_bonus`,`ap_bonus`,`ap_dot_bonus`,`comments`) VALUES | |
+(56578,0,0,0,0,'Skadi - Harpoondamage'); | |
\ No newline at end of file | |
diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp | |
index 08670af..7b56af7 100644 | |
--- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp | |
+++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp | |
@@ -15,21 +15,18 @@ | |
* with this program. If not, see <http://www.gnu.org/licenses/>. | |
*/ | |
-/* Script Data Start | |
-SDName: Boss_Skadi | |
-SDAuthor: LordVanMartin, JohnHoliver | |
-SD%Complete: 90% | |
-SDComment: <Known Bugs> | |
- After Unmount() he appears to still be flying even with SetFlying(false) | |
- </Known Bugs> | |
-SDCategory: Utgarde Pinnacle | |
-Script Data End */ | |
+/* | |
+ * Credits: | |
+ * Some functions and data(waypoints, spells etc.) are taken from the original-script, written by LordVanMartin and JohnHoliver | |
+ * Skadi-teleport at graufs death taken from Carbenium | |
+ */ | |
#include "ScriptMgr.h" | |
#include "ScriptedCreature.h" | |
#include "utgarde_pinnacle.h" | |
#include "Player.h" | |
#include "SpellInfo.h" | |
+#include "Vehicle.h" | |
enum Yells | |
{ | |
@@ -123,21 +120,34 @@ static Position Location[]= | |
{413.9327f, -540.9407f, 138.2614f, 0}, //71 | |
}; | |
-enum CombatPhase | |
+enum SkadiPhases | |
{ | |
- FLYING, | |
- SKADI | |
+ PHASE_FLYING = 1, | |
+ PHASE_GROUND = 2, | |
}; | |
-enum Spells | |
+enum SkadiSpells | |
{ | |
- // Skadi Spells | |
SPELL_CRUSH = 50234, | |
- SPELL_POISONED_SPEAR = 50225, //isn't being casted =/ | |
- SPELL_WHIRLWIND = 50228, //random target, but not the tank approx. every 20s | |
+ H_SPELL_CRUSH = 59330, | |
+ SPELL_POISONED_SPEAR = 50225, | |
+ H_SPELL_POISONED_SPEAR = 59331, | |
+ SPELL_WHIRLWIND = 50228, | |
+ H_SPELL_WHIRWIND = 59322, | |
SPELL_RAPID_FIRE = 56570, | |
SPELL_HARPOON_DAMAGE = 56578, | |
SPELL_FREEZING_CLOUD = 47579, | |
+ H_SPELL_FREEZING_CLOUD = 60020, | |
+ SPELL_ENTER_VEHICLE = 61791, | |
+ SPELL_SKADI_TELEPORT = 61790, | |
+}; | |
+ | |
+enum SkadiEvents | |
+{ | |
+ EVENT_CRUSH = 1, | |
+ EVENT_POISONED_SPEAR, | |
+ EVENT_WHIRLWIND, | |
+ EVENT_SUMMON, | |
}; | |
enum Creatures | |
@@ -145,14 +155,18 @@ enum Creatures | |
NPC_YMIRJAR_WARRIOR = 26690, | |
NPC_YMIRJAR_WITCH_DOCTOR = 26691, | |
NPC_YMIRJAR_HARPOONER = 26692, | |
- NPC_GRAUF = 26893, | |
NPC_TRIGGER = 28351, | |
- DATA_MOUNT = 27043, | |
}; | |
enum Achievments | |
{ | |
- ACHIEV_TIMED_START_EVENT = 17726, | |
+ ACHIEV_TIMED_START_EVENT = 17726, | |
+}; | |
+ | |
+enum SkadiActions | |
+{ | |
+ ACTION_TRIGGER_SPAWN = 1, | |
+ ACTION_DISMOUNT = 2, | |
}; | |
class boss_skadi : public CreatureScript | |
@@ -165,275 +179,156 @@ public: | |
return new boss_skadiAI(creature); | |
} | |
- struct boss_skadiAI : public ScriptedAI | |
+ struct boss_skadiAI : public BossAI | |
{ | |
- boss_skadiAI(Creature* creature) : ScriptedAI(creature), Summons(me) | |
+ boss_skadiAI(Creature* creature) : BossAI(creature, DATA_SKADI_THE_RUTHLESS_EVENT), Summons(me) | |
{ | |
instance = creature->GetInstanceScript(); | |
- m_uiGraufGUID = 0; | |
+ me->ApplySpellImmune(0, IMMUNITY_ID, SPELL_HARPOON_DAMAGE, true); | |
} | |
+ EventMap events; | |
InstanceScript* instance; | |
SummonList Summons; | |
- uint64 m_uiGraufGUID; | |
- std::vector<uint64> triggersGUID; | |
- | |
- uint32 m_uiCrushTimer; | |
- uint32 m_uiPoisonedSpearTimer; | |
- uint32 m_uiWhirlwindTimer; | |
- uint32 m_uiWaypointId; | |
- uint32 m_uiMovementTimer; | |
- uint32 m_uiMountTimer; | |
- uint32 m_uiSummonTimer; | |
- uint8 m_uiSpellHitCount; | |
- bool m_bSaidEmote; | |
- | |
- CombatPhase Phase; | |
+ SkadiPhases phase; | |
void Reset() OVERRIDE | |
{ | |
- triggersGUID.clear(); | |
+ _Reset(); | |
+ me->ExitVehicle(); | |
- m_uiCrushTimer = 8000; | |
- m_uiPoisonedSpearTimer = 10000; | |
- m_uiWhirlwindTimer = 20000; | |
- m_uiMountTimer = 3000; | |
- m_uiWaypointId = 0; | |
- m_bSaidEmote = false; | |
- m_uiSpellHitCount = 0; | |
- | |
- Phase = SKADI; | |
- | |
- Summons.DespawnAll(); | |
- me->SetSpeed(MOVE_FLIGHT, 3.0f); | |
- if ((Unit::GetCreature(*me, m_uiGraufGUID) == NULL) && !me->IsMounted()) | |
- me->SummonCreature(NPC_GRAUF, Location[0].GetPositionX(), Location[0].GetPositionY(), Location[0].GetPositionZ(), 3.0f); | |
if (instance) | |
{ | |
- instance->SetData(DATA_SKADI_THE_RUTHLESS_EVENT, NOT_STARTED); | |
- instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); | |
+ if (Creature* grauf = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_NPC_GRAUF))) | |
+ { | |
+ if (grauf->isDead()) | |
+ { | |
+ grauf->Respawn(); | |
+ grauf->AI()->EnterEvadeMode(); | |
+ } | |
+ } | |
} | |
- } | |
- void JustReachedHome() OVERRIDE | |
- { | |
- me->SetCanFly(false); | |
- me->Dismount(); | |
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); | |
- if (!Unit::GetCreature(*me, m_uiGraufGUID)) | |
- me->SummonCreature(NPC_GRAUF, Location[0].GetPositionX(), Location[0].GetPositionY(), Location[0].GetPositionZ(), 3.0f); | |
+ Summons.DespawnAll(); | |
+ | |
+ EnterEvadeMode(); | |
} | |
- void EnterCombat(Unit* /*who*/) OVERRIDE | |
+ void JustSummoned(Creature* summon) OVERRIDE | |
{ | |
- Talk(SAY_AGGRO); | |
- | |
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); | |
+ summons.Summon(summon); | |
- Phase = FLYING; | |
- | |
- m_uiMovementTimer = 1000; | |
- m_uiSummonTimer = 10000; | |
- me->SetInCombatWithZone(); | |
- if (instance) | |
+ if (summon->GetEntry() == NPC_YMIRJAR_WARRIOR || | |
+ summon->GetEntry() == NPC_YMIRJAR_HARPOONER || | |
+ summon->GetEntry() == NPC_YMIRJAR_WITCH_DOCTOR) | |
{ | |
- instance->SetData(DATA_SKADI_THE_RUTHLESS_EVENT, IN_PROGRESS); | |
- instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); | |
- me->GetMotionMaster()->MoveJump(Location[0].GetPositionX(), Location[0].GetPositionY(), Location[0].GetPositionZ(), 5.0f, 10.0f); | |
- me->SetWalk(false); | |
- m_uiMountTimer = 1000; | |
- Summons.DespawnEntry(NPC_GRAUF); | |
+ if (Unit* target = me->GetVictim()) | |
+ summon->GetAI()->AttackStart(target); | |
+ else | |
+ summon->GetAI()->AttackStart(summon->SelectNearestPlayer(250.0f)); | |
} | |
- } | |
- void JustSummoned(Creature* summoned) OVERRIDE | |
- { | |
- switch (summoned->GetEntry()) | |
+ if (summon->GetEntry() == NPC_TRIGGER) | |
{ | |
- case NPC_GRAUF: | |
- m_uiGraufGUID = summoned->GetGUID(); | |
- break; | |
- case NPC_YMIRJAR_WARRIOR: | |
- case NPC_YMIRJAR_WITCH_DOCTOR: | |
- case NPC_YMIRJAR_HARPOONER: | |
- summoned->setActive(true); | |
- summoned->SetInCombatWithZone(); | |
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) | |
- summoned->AI()->AttackStart(target); | |
- break; | |
- case NPC_TRIGGER: | |
- summoned->CastSpell((Unit*)NULL, SPELL_FREEZING_CLOUD, true); | |
- summoned->DespawnOrUnsummon(10*IN_MILLISECONDS); | |
- break; | |
+ summon->CastSpell(summon, DUNGEON_MODE(SPELL_FREEZING_CLOUD, H_SPELL_FREEZING_CLOUD), true); | |
+ summon->DespawnOrUnsummon(10*IN_MILLISECONDS); | |
} | |
- Summons.Summon(summoned); | |
} | |
- void SummonedCreatureDespawn(Creature* summoned) OVERRIDE | |
+ void EnterPhase(SkadiPhases newPhase) | |
{ | |
- if (summoned->GetEntry() == NPC_GRAUF) | |
- m_uiGraufGUID = 0; | |
- Summons.Despawn(summoned); | |
- } | |
+ phase = newPhase; | |
+ events.Reset(); | |
- void SpellHit(Unit* /*caster*/, const SpellInfo* spell) OVERRIDE | |
- { | |
- if (spell->Id == SPELL_HARPOON_DAMAGE) | |
+ if (phase == PHASE_FLYING) | |
{ | |
- m_uiSpellHitCount++; | |
- if (m_uiSpellHitCount >= 3) | |
+ if (instance) | |
{ | |
- Phase = SKADI; | |
- me->SetCanFly(false); | |
- me->Dismount(); | |
- if (Creature* pGrauf = me->SummonCreature(NPC_GRAUF, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3*IN_MILLISECONDS)) | |
+ if (Creature* grauf = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_NPC_GRAUF))) | |
{ | |
- pGrauf->GetMotionMaster()->MoveFall(); | |
- pGrauf->HandleEmoteCommand(EMOTE_ONESHOT_FLYDEATH); | |
+ DoCast(grauf, SPELL_ENTER_VEHICLE); | |
+ | |
+ events.ScheduleEvent(EVENT_SUMMON, 10000); | |
+ | |
+ instance->SetData(DATA_SKADI_THE_RUTHLESS_EVENT, IN_PROGRESS); | |
+ instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); | |
} | |
- me->GetMotionMaster()->MoveJump(Location[4].GetPositionX(), Location[4].GetPositionY(), Location[4].GetPositionZ(), 5.0f, 10.0f); | |
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); | |
- Talk(SAY_DRAKE_DEATH); | |
- m_uiCrushTimer = 8000; | |
- m_uiPoisonedSpearTimer = 10000; | |
- m_uiWhirlwindTimer = 20000; | |
- me->AI()->AttackStart(SelectTarget(SELECT_TARGET_RANDOM)); | |
} | |
} | |
- } | |
- void UpdateAI(uint32 diff) OVERRIDE | |
- { | |
- switch (Phase) | |
+ if (phase == PHASE_GROUND) | |
{ | |
- case FLYING: | |
- if (!UpdateVictim()) | |
- return; | |
- | |
- if (me->GetPositionX() >= 519) | |
- { | |
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); | |
- if (!m_bSaidEmote) | |
- { | |
- Talk(EMOTE_RANGE); | |
- m_bSaidEmote = true; | |
- } | |
- } | |
- else | |
- { | |
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); | |
- m_bSaidEmote = false; | |
- } | |
+ Talk(SAY_DRAKE_DEATH); | |
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); | |
- if (m_uiMountTimer && m_uiMountTimer <= diff) | |
- { | |
- me->Mount(DATA_MOUNT); | |
- me->SetCanFly(true); | |
- m_uiMountTimer = 0; | |
- } else m_uiMountTimer -= diff; | |
+ if (Unit* grauf = me->GetVehicleCreatureBase()) | |
+ { | |
+ me->ExitVehicle(); | |
+ me->DealDamage(grauf, grauf->GetMaxHealth()); | |
- if (m_uiSummonTimer <= diff) | |
- { | |
- SpawnMobs(); | |
- m_uiSummonTimer = 25000; | |
- } else m_uiSummonTimer -= diff; | |
+ DoCast(SPELL_SKADI_TELEPORT); | |
- if (m_uiMovementTimer <= diff) | |
- { | |
- switch (m_uiWaypointId) | |
- { | |
- case 0: | |
- me->GetMotionMaster()->MovePoint(0, Location[1].GetPositionX(), Location[1].GetPositionY(), Location[1].GetPositionZ()); | |
- m_uiMovementTimer = 5000; | |
- break; | |
- case 1: | |
- me->GetMotionMaster()->MovePoint(0, Location[2].GetPositionX(), Location[2].GetPositionY(), Location[2].GetPositionZ()); | |
- m_uiMovementTimer = 2000; | |
- break; | |
- case 2: | |
- me->GetMotionMaster()->MovePoint(0, Location[3].GetPositionX(), Location[3].GetPositionY(), Location[3].GetPositionZ()); | |
- m_uiMovementTimer = 15000; | |
- break; | |
- case 3: | |
- me->GetMotionMaster()->MovePoint(0, Location[69].GetPositionX(), Location[69].GetPositionY(), Location[69].GetPositionZ()); | |
- Talk(SAY_DRAKE_BREATH); | |
- Talk(EMOTE_BREATH); | |
- m_uiMovementTimer = 2500; | |
- break; | |
- case 4: | |
- me->GetMotionMaster()->MovePoint(0, Location[70].GetPositionX(), Location[70].GetPositionY(), Location[70].GetPositionZ()); | |
- m_uiMovementTimer = 2000; | |
- SpawnTrigger(); | |
- break; | |
- case 5: | |
- me->GetMotionMaster()->MovePoint(0, Location[71].GetPositionX(), Location[71].GetPositionY(), Location[71].GetPositionZ()); | |
- m_uiMovementTimer = 3000; | |
- break; | |
- case 6: | |
- me->GetMotionMaster()->MovePoint(0, Location[3].GetPositionX(), Location[3].GetPositionY(), Location[3].GetPositionZ()); | |
- m_uiWaypointId = 2; | |
- m_uiMovementTimer = 15000; | |
- break; | |
- } | |
- m_uiWaypointId++; | |
- } else m_uiMovementTimer -= diff; | |
- break; | |
- case SKADI: | |
- //Return since we have no target | |
- if (!UpdateVictim()) | |
- return; | |
+ grauf->ToCreature()->DespawnOrUnsummon(2000); | |
+ } | |
- if (m_uiCrushTimer <= diff) | |
- { | |
- DoCastVictim(SPELL_CRUSH); | |
- m_uiCrushTimer = 8000; | |
- } else m_uiCrushTimer -= diff; | |
+ events.ScheduleEvent(EVENT_CRUSH, 8000); | |
+ events.ScheduleEvent(EVENT_POISONED_SPEAR, 10000); | |
+ events.ScheduleEvent(EVENT_WHIRLWIND, 20000); | |
- if (m_uiPoisonedSpearTimer <= diff) | |
- { | |
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM)) | |
- DoCast(target, SPELL_POISONED_SPEAR); | |
- m_uiPoisonedSpearTimer = 10000; | |
- } else m_uiPoisonedSpearTimer -= diff; | |
+ AttackStart(SelectTarget(SELECT_TARGET_RANDOM)); | |
+ } | |
+ } | |
- if (m_uiWhirlwindTimer <= diff) | |
- { | |
- DoCastAOE(SPELL_WHIRLWIND); | |
- m_uiWhirlwindTimer = 20000; | |
- } else m_uiWhirlwindTimer -= diff; | |
+ void EnterCombat(Unit* who) OVERRIDE | |
+ { | |
+ _EnterCombat(); | |
+ Talk(SAY_AGGRO); | |
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); | |
- DoMeleeAttackIfReady(); | |
- break; | |
- } | |
+ EnterPhase(PHASE_FLYING); | |
} | |
void JustDied(Unit* /*killer*/) OVERRIDE | |
{ | |
+ _JustDied(); | |
Talk(SAY_DEATH); | |
- Summons.DespawnAll(); | |
- if (instance) | |
- instance->SetData(DATA_SKADI_THE_RUTHLESS_EVENT, DONE); | |
+ | |
+ summons.DespawnAll(); | |
+ | |
+ instance->SetData(DATA_SKADI_THE_RUTHLESS_EVENT, DONE); | |
} | |
- void KilledUnit(Unit* /*victim*/) OVERRIDE | |
+ void KilledUnit(Unit* who) OVERRIDE | |
{ | |
Talk(SAY_KILL); | |
} | |
- void SpawnMobs() | |
+ void DoAction(int32 action) OVERRIDE | |
+ { | |
+ if (action == ACTION_TRIGGER_SPAWN) | |
+ { | |
+ Talk(SAY_DRAKE_BREATH); | |
+ Talk(EMOTE_BREATH); | |
+ SpawnTrigger(); | |
+ } | |
+ | |
+ if (action == ACTION_DISMOUNT) | |
+ EnterPhase(PHASE_GROUND); | |
+ } | |
+ | |
+ void SummonVrykul() | |
{ | |
- for (uint8 i = 0; i < DUNGEON_MODE(5, 6); ++i) | |
+ for (uint8 i = 0; i < DUNGEON_MODE(5,6); i++) | |
{ | |
- switch (urand(0, 2)) | |
+ switch (RAND(0,1,2)) | |
{ | |
case 0: | |
me->SummonCreature(NPC_YMIRJAR_WARRIOR, SpawnLoc.GetPositionX()+rand()%5, SpawnLoc.GetPositionY()+rand()%5, SpawnLoc.GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); | |
break; | |
- | |
case 1: | |
me->SummonCreature(NPC_YMIRJAR_WITCH_DOCTOR, SpawnLoc.GetPositionX()+rand()%5, SpawnLoc.GetPositionY()+rand()%5, SpawnLoc.GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); | |
break; | |
- | |
case 2: | |
me->SummonCreature(NPC_YMIRJAR_HARPOONER, SpawnLoc.GetPositionX()+rand()%5, SpawnLoc.GetPositionY()+rand()%5, SpawnLoc.GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); | |
break; | |
@@ -460,8 +355,200 @@ public: | |
for (uint32 i = iStart; i < iEnd; ++i) | |
me->SummonCreature(NPC_TRIGGER, Location[i]); | |
} | |
+ | |
+ void UpdateAI(uint32 diff) OVERRIDE | |
+ { | |
+ if (!UpdateVictim()) | |
+ return; | |
+ | |
+ events.Update(diff); | |
+ | |
+ while (uint32 eventId = events.ExecuteEvent()) | |
+ { | |
+ switch (eventId) | |
+ { | |
+ case EVENT_SUMMON: | |
+ SummonVrykul(); | |
+ events.ScheduleEvent(EVENT_SUMMON, 25000); | |
+ break; | |
+ | |
+ case EVENT_CRUSH: | |
+ DoCastVictim(DUNGEON_MODE(SPELL_CRUSH, H_SPELL_CRUSH)); | |
+ events.ScheduleEvent(EVENT_CRUSH, 8000); | |
+ break; | |
+ case EVENT_POISONED_SPEAR: | |
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM)) | |
+ DoCast(target, DUNGEON_MODE(SPELL_POISONED_SPEAR, H_SPELL_POISONED_SPEAR)); | |
+ events.ScheduleEvent(EVENT_POISONED_SPEAR, 10000); | |
+ break; | |
+ case EVENT_WHIRLWIND: | |
+ DoCastAOE(DUNGEON_MODE(SPELL_WHIRLWIND, H_SPELL_WHIRWIND)); | |
+ events.ScheduleEvent(EVENT_WHIRLWIND, 23000); | |
+ break; | |
+ } | |
+ } | |
+ | |
+ DoMeleeAttackIfReady(); | |
+ } | |
}; | |
+}; | |
+enum GraufEvent | |
+{ | |
+ EVENT_MOVE = 1, | |
+}; | |
+ | |
+class mob_grauf : public CreatureScript | |
+{ | |
+public: | |
+ mob_grauf() : CreatureScript("mob_grauf") { } | |
+ | |
+ CreatureAI* GetAI(Creature* creature) const OVERRIDE | |
+ { | |
+ return new mob_graufAI(creature); | |
+ } | |
+ | |
+ struct mob_graufAI : public ScriptedAI | |
+ { | |
+ mob_graufAI(Creature* creature) : ScriptedAI(creature) | |
+ { | |
+ instance = creature->GetInstanceScript(); | |
+ } | |
+ | |
+ EventMap events; | |
+ InstanceScript* instance; | |
+ uint8 waypointId; | |
+ uint8 harpoonHitCounter; | |
+ | |
+ void Reset() OVERRIDE | |
+ { | |
+ me->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER); | |
+ | |
+ me->SetCanFly(false); | |
+ me->SetDisableGravity(false); | |
+ } | |
+ | |
+ void PassengerBoarded(Unit* who, int8 /*seatId*/, bool apply) OVERRIDE | |
+ { | |
+ if (apply) | |
+ { | |
+ events.Reset(); | |
+ events.ScheduleEvent(EVENT_MOVE, 1000); | |
+ | |
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); | |
+ | |
+ waypointId = 0; | |
+ harpoonHitCounter = 0; | |
+ | |
+ me->SetCanFly(true); | |
+ me->SetDisableGravity(true); | |
+ me->SetSpeed(MOVE_FLIGHT, 3.0f); | |
+ | |
+ me->SetByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER); | |
+ } | |
+ } | |
+ | |
+ void SpellHit(Unit* /*caster*/, const SpellInfo* spell) OVERRIDE | |
+ { | |
+ if (spell->Id == SPELL_HARPOON_DAMAGE) | |
+ { | |
+ harpoonHitCounter++; | |
+ | |
+ //3 Hits since Patch 3.3.2 http://www.wowwiki.com/Skadi_the_Ruthless | |
+ if (harpoonHitCounter >= 3) | |
+ if (instance) | |
+ if (Creature* skadi = me->GetCreature(*me, instance->GetData64(DATA_SKADI_THE_RUTHLESS))) | |
+ skadi->AI()->DoAction(ACTION_DISMOUNT); | |
+ } | |
+ } | |
+ | |
+ void MovementInform(uint32 type, uint32 pointId) OVERRIDE | |
+ { | |
+ if (type != POINT_MOTION_TYPE) | |
+ return; | |
+ | |
+ switch (pointId) | |
+ { | |
+ case 0: | |
+ events.ScheduleEvent(EVENT_MOVE, 5000); | |
+ break; | |
+ case 1: | |
+ events.ScheduleEvent(EVENT_MOVE, 2000); | |
+ break; | |
+ case 2: | |
+ events.ScheduleEvent(EVENT_MOVE, 15000); | |
+ break; | |
+ case 3: | |
+ if (instance) | |
+ if (Creature* skadi = me->GetCreature(*me, instance->GetData64(DATA_SKADI_THE_RUTHLESS))) | |
+ skadi->AI()->DoAction(ACTION_TRIGGER_SPAWN); | |
+ | |
+ events.ScheduleEvent(EVENT_MOVE, 2000); | |
+ break; | |
+ case 4: | |
+ events.ScheduleEvent(EVENT_MOVE, 2500); | |
+ break; | |
+ case 5: | |
+ events.ScheduleEvent(EVENT_MOVE, 3000); | |
+ break; | |
+ case 6: | |
+ if (Creature* skadi = me->GetCreature(*me, instance->GetData64(DATA_SKADI_THE_RUTHLESS))) | |
+ skadi->AI()->Talk(EMOTE_RANGE); | |
+ | |
+ waypointId = 2; | |
+ events.ScheduleEvent(EVENT_MOVE, 15000); | |
+ break; | |
+ } | |
+ } | |
+ | |
+ void UpdateAI(uint32 diff) OVERRIDE | |
+ { | |
+ if (!me->GetVehicleKit()->GetPassenger(0)) | |
+ return; | |
+ | |
+ events.Update(diff); | |
+ | |
+ while (uint32 eventId = events.ExecuteEvent()) | |
+ { | |
+ switch (eventId) | |
+ { | |
+ case EVENT_MOVE: | |
+ switch (waypointId) | |
+ { | |
+ case 0: | |
+ me->GetMotionMaster()->MovePoint(0, Location[1]); | |
+ waypointId++; | |
+ break; | |
+ case 1: | |
+ me->GetMotionMaster()->MovePoint(1, Location[2]); | |
+ waypointId++; | |
+ break; | |
+ case 2: | |
+ me->GetMotionMaster()->MovePoint(2, Location[3]); | |
+ waypointId++; | |
+ break; | |
+ case 3: | |
+ me->GetMotionMaster()->MovePoint(3, Location[69]); | |
+ waypointId++; | |
+ break; | |
+ case 4: | |
+ me->GetMotionMaster()->MovePoint(4, Location[70]); | |
+ waypointId++; | |
+ break; | |
+ case 5: | |
+ me->GetMotionMaster()->MovePoint(5, Location[71]); | |
+ waypointId++; | |
+ break; | |
+ case 6: | |
+ me->GetMotionMaster()->MovePoint(6, Location[3]); | |
+ waypointId++; | |
+ break; | |
+ } | |
+ break; | |
+ } | |
+ } | |
+ } | |
+ }; | |
}; | |
class go_harpoon_launcher : public GameObjectScript | |
@@ -475,16 +562,16 @@ public: | |
if (!instance) | |
return false; | |
- if (Creature* pSkadi = Unit::GetCreature(*go, instance->GetData64(DATA_SKADI_THE_RUTHLESS))) | |
- player->CastSpell(pSkadi, SPELL_RAPID_FIRE, true); | |
+ //Using a position as target, so that the player can miss the dragon, if grauf isn't at the right position | |
+ player->CastSpell(Location[3].GetPositionX(), Location[3].GetPositionY(), Location[3].GetPositionZ(), SPELL_RAPID_FIRE, true); | |
- return false; | |
+ return true; | |
} | |
- | |
}; | |
void AddSC_boss_skadi() | |
{ | |
new boss_skadi(); | |
+ new mob_grauf(); | |
new go_harpoon_launcher(); | |
-} | |
+} | |
\ No newline at end of file | |
diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_utgarde_pinnacle.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_utgarde_pinnacle.cpp | |
index 4959b3a..0ba2d82 100644 | |
--- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_utgarde_pinnacle.cpp | |
+++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_utgarde_pinnacle.cpp | |
@@ -54,6 +54,8 @@ public: | |
uint64 uiSkadiTheRuthless; | |
uint64 uiKingYmiron; | |
+ uint64 uiGrauf; | |
+ | |
uint64 uiSkadiTheRuthlessDoor; | |
uint64 uiKingYmironDoor; | |
uint64 uiGortokPalehoofSphere; | |
@@ -81,6 +83,8 @@ public: | |
uiSkadiTheRuthless = 0; | |
uiKingYmiron = 0; | |
+ uiGrauf = 0; | |
+ | |
uiSkadiTheRuthlessDoor = 0; | |
uiKingYmironDoor = 0; | |
uiGortokPalehoofSphere = 0; | |
@@ -118,6 +122,7 @@ public: | |
case NPC_FEROCIOUS_RHINO: uiFerociousRhino = creature->GetGUID(); break; | |
case NPC_SVALA: uiSvala = creature->GetGUID(); break; | |
case NPC_PALEHOOF_ORB: uiPalehoofOrb = creature->GetGUID(); break; | |
+ case NPC_GRAUF: uiGrauf = creature->GetGUID(); break; | |
} | |
} | |
@@ -208,6 +213,7 @@ public: | |
case DATA_SVALA: return uiSvala; | |
case DATA_GORTOK_PALEHOOF_SPHERE: return uiGortokPalehoofSphere; | |
case DATA_SACRIFICED_PLAYER: return uiSacrificedPlayer; | |
+ case DATA_NPC_GRAUF: return uiGrauf; | |
} | |
return 0; | |
diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/utgarde_pinnacle.h b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/utgarde_pinnacle.h | |
index 6166b7c..48045e0 100644 | |
--- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/utgarde_pinnacle.h | |
+++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/utgarde_pinnacle.h | |
@@ -54,7 +54,8 @@ enum CreatureID | |
NPC_MASSIVE_JORMUNGAR = 26685, | |
NPC_FEROCIOUS_RHINO = 26686, | |
NPC_SVALA = 29281, | |
- NPC_PALEHOOF_ORB = 26688 | |
+ NPC_PALEHOOF_ORB = 26688, | |
+ NPC_GRAUF = 26893 | |
}; | |
#endif | |
-- | |
1.8.0.msysgit.0 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment