Core/Scripts: Rewritten Drakkari Colossus encounter from Gundrak.

Signed-off-by: Manuel <[email protected]>
This commit is contained in:
Manuel
2011-01-15 19:03:32 -03:00
parent 29a8b5407a
commit 58564cc496
@@ -25,213 +25,336 @@
enum Spells enum Spells
{ {
SPELL_EMERGE = 54850, SPELL_EMERGE = 54850,
SPELL_MIGHTY_BLOW = 54719, SPELL_ELEMENTAL_SPAWN_EFEFCT = 54888,
SPELL_MOJO_VOLLEY = 54849,
SPELL_SURGE_VISUAL = 54827,
SPELL_MERGE = 54878, SPELL_MERGE = 54878,
SPELL_MIGHTY_BLOW = 54719,
SPELL_SURGE = 54801, SPELL_SURGE = 54801,
SPELL_FREEZE_ANIM = 16245, SPELL_FREEZE_ANIM = 16245,
SPELL_MOJO_PUDDLE = 55627, SPELL_MOJO_PUDDLE = 55627,
H_SPELL_MOJO_PUDDLE = 58994,
SPELL_MOJO_WAVE = 55626, SPELL_MOJO_WAVE = 55626,
H_SPELL_MOJO_WAVE = 58993 };
enum ColossusEvents
{
EVENT_MIGHTY_BLOW = 1,
};
enum ColossusActions
{
ACTION_SUMMON_ELEMENTAL = 1,
ACTION_FREEZE_COLOSSUS = 2,
ACTION_UNFREEZE_COLOSSUS = 3,
};
enum ColossusPhases
{
COLOSSUS_PHASE_NORMAL = 1,
COLOSSUS_PHASE_FIRST_ELEMENTAL_SUMMON = 2,
COLOSSUS_PHASE_SECOND_ELEMENTAL_SUMMON = 3
};
enum ColossusData
{
DATA_COLOSSUS_PHASE = 1,
DATA_INTRO_DONE = 2
};
enum ElementalActions
{
ACTION_RETURN_TO_COLOSSUS = 1
};
enum ElementalEvents
{
EVENT_SURGE = 1
}; };
class boss_drakkari_colossus : public CreatureScript class boss_drakkari_colossus : public CreatureScript
{ {
public: public:
boss_drakkari_colossus() : CreatureScript("boss_drakkari_colossus") { } boss_drakkari_colossus() : CreatureScript("boss_drakkari_colossus") { }
CreatureAI* GetAI(Creature* pCreature) const struct boss_drakkari_colossusAI : public BossAI
{
return new boss_drakkari_colossusAI (pCreature);
}
struct boss_drakkari_colossusAI : public ScriptedAI
{
boss_drakkari_colossusAI(Creature* pCreature) : ScriptedAI(pCreature)
{ {
pInstance = pCreature->GetInstanceScript(); boss_drakkari_colossusAI(Creature* creature) : BossAI(creature, DATA_DRAKKARI_COLOSSUS_EVENT)
}
InstanceScript* pInstance;
bool bHealth;
bool bHealth1;
uint32 MightyBlowTimer;
void Reset()
{
if (pInstance)
pInstance->SetData(DATA_DRAKKARI_COLOSSUS_EVENT, NOT_STARTED);
if (!me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE))
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
me->ClearUnitState(UNIT_STAT_STUNNED | UNIT_STAT_ROOT);
me->SetReactState(REACT_PASSIVE);
MightyBlowTimer = 10*IN_MILLISECONDS;
bHealth = false;
bHealth1 = false;
}
void EnterCombat(Unit* /*who*/)
{
if (pInstance)
pInstance->SetData(DATA_DRAKKARI_COLOSSUS_EVENT, IN_PROGRESS);
}
void CreatureState(Creature* pWho, bool bRestore = false)
{
if (!pWho)
return;
if (bRestore)
{ {
pWho->ClearUnitState(UNIT_STAT_STUNNED | UNIT_STAT_ROOT); me->SetReactState(REACT_PASSIVE);
pWho->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); introDone = false;
if (pWho == me)
me->RemoveAura(SPELL_FREEZE_ANIM);
}else
{
pWho->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
pWho->AddUnitState(UNIT_STAT_STUNNED | UNIT_STAT_ROOT);
if (pWho == me)
DoCast(me,SPELL_FREEZE_ANIM);
}
}
void UpdateAI(const uint32 diff)
{
//Return since we have no target
if (!UpdateVictim())
return;
if (!bHealth && HealthBelowPct(50) && !HealthBelowPct(5))
{
CreatureState(me, false);
DoCast(me,SPELL_FREEZE_ANIM);
DoCast(me,SPELL_EMERGE);
bHealth = true;
} }
if (!bHealth1 && HealthBelowPct(5)) void InitializeAI()
{ {
DoCast(me,SPELL_EMERGE); if (!me->isDead())
CreatureState(me, false); Reset();
bHealth1 = true;
me->RemoveAllAuras();
} }
if (MightyBlowTimer <= diff) void Reset()
{ {
DoCast(me->getVictim(), SPELL_MIGHTY_BLOW, true); if (GetData(DATA_INTRO_DONE))
MightyBlowTimer = 10*IN_MILLISECONDS;
} else MightyBlowTimer -= diff;
if (!me->HasUnitState(UNIT_STAT_STUNNED))
DoMeleeAttackIfReady();
}
void JustDied(Unit* /*killer*/)
{
if (pInstance)
pInstance->SetData(DATA_DRAKKARI_COLOSSUS_EVENT, DONE);
}
void JustSummoned(Creature* pSummon)
{
if (HealthBelowPct(5))
pSummon->DealDamage(pSummon, uint32(pSummon->GetHealth() * 0.5), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
pSummon->AI()->AttackStart(me->getVictim());
}
};
};
class boss_drakkari_elemental : public CreatureScript
{
public:
boss_drakkari_elemental() : CreatureScript("boss_drakkari_elemental") { }
CreatureAI* GetAI(Creature* pCreature) const
{
return new boss_drakkari_elementalAI (pCreature);
}
struct boss_drakkari_elementalAI : public ScriptedAI
{
boss_drakkari_elementalAI(Creature* pCreature) : ScriptedAI(pCreature)
{
pInstance = pCreature->GetInstanceScript();
}
InstanceScript* pInstance;
uint32 uiSurgeTimer;
bool bGoToColossus;
void Reset()
{
if (Creature *pColossus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0))
CAST_AI(boss_drakkari_colossus::boss_drakkari_colossusAI, pColossus->AI())->CreatureState(me, true);
uiSurgeTimer = 7*IN_MILLISECONDS;
bGoToColossus = false;
}
void EnterEvadeMode()
{
me->RemoveFromWorld();
}
void MovementInform(uint32 uiType, uint32 /*uiId*/)
{
if (uiType != POINT_MOTION_TYPE)
return;
if (Creature *pColossus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0))
{
CAST_AI(boss_drakkari_colossus::boss_drakkari_colossusAI, pColossus->AI())->CreatureState(pColossus, true);
CAST_AI(boss_drakkari_colossus::boss_drakkari_colossusAI, pColossus->AI())->bHealth1 = false;
}
me->RemoveFromWorld();
}
void UpdateAI(const uint32 diff)
{
//Return since we have no target
if (!UpdateVictim())
return;
if (!bGoToColossus && HealthBelowPct(50))
{
if (Creature *pColossus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0))
{ {
if (!CAST_AI(boss_drakkari_colossus::boss_drakkari_colossusAI,pColossus->AI())->HealthBelowPct(6)) me->SetReactState(REACT_AGGRESSIVE);
me->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_OOC_NOT_ATTACKABLE);
me->RemoveAura(SPELL_FREEZE_ANIM);
}
events.Reset();
events.ScheduleEvent(EVENT_MIGHTY_BLOW, urand(10000,30000));
phase = COLOSSUS_PHASE_NORMAL;
instance->SetBossState(DATA_DRAKKARI_COLOSSUS_EVENT, NOT_STARTED);
}
void EnterCombat(Unit* /*who*/)
{
instance->SetBossState(DATA_DRAKKARI_COLOSSUS_EVENT, IN_PROGRESS);
me->RemoveAura(SPELL_FREEZE_ANIM);
}
void JustDied(Unit* /*killer*/)
{
instance->SetBossState(DATA_DRAKKARI_COLOSSUS_EVENT, DONE);
}
void JustReachedHome()
{
instance->SetBossState(DATA_DRAKKARI_COLOSSUS_EVENT, FAIL);
}
void DoAction(const int32 action)
{
switch (action)
{
case ACTION_SUMMON_ELEMENTAL:
DoCast(SPELL_EMERGE);
break;
case ACTION_FREEZE_COLOSSUS:
me->GetMotionMaster()->MoveIdle();
me->SetReactState(REACT_PASSIVE);
me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_OOC_NOT_ATTACKABLE);
DoCast(me,SPELL_FREEZE_ANIM);
break;
case ACTION_UNFREEZE_COLOSSUS:
if (me->GetReactState() == REACT_AGGRESSIVE)
return;
me->SetReactState(REACT_AGGRESSIVE);
me->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_OOC_NOT_ATTACKABLE);
me->RemoveAura(SPELL_FREEZE_ANIM);
me->SetInCombatWithZone();
if (me->getVictim())
me->GetMotionMaster()->MoveChase(me->getVictim(), 0,0);
break;
}
}
void DamageTaken(Unit* /*attacker*/, uint32& damage)
{
if (me->HasFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_OOC_NOT_ATTACKABLE))
damage = 0;
if (phase == COLOSSUS_PHASE_NORMAL ||
phase == COLOSSUS_PHASE_FIRST_ELEMENTAL_SUMMON)
{
if (HealthBelowPct( phase == COLOSSUS_PHASE_NORMAL ? 50 : 5))
{ {
me->InterruptNonMeleeSpells(true); damage = 0;
DoCast(pColossus, SPELL_MERGE); phase = (phase == COLOSSUS_PHASE_NORMAL ? COLOSSUS_PHASE_FIRST_ELEMENTAL_SUMMON : COLOSSUS_PHASE_SECOND_ELEMENTAL_SUMMON);
bGoToColossus = true; DoAction(ACTION_FREEZE_COLOSSUS);
DoAction(ACTION_SUMMON_ELEMENTAL);
} }
} }
} }
if (uiSurgeTimer <= diff) uint32 GetData(uint32 data)
{ {
DoCast(me->getVictim(), SPELL_SURGE); if (data == DATA_COLOSSUS_PHASE)
uiSurgeTimer = 7*IN_MILLISECONDS; return phase;
} else uiSurgeTimer -= diff; else if (data == DATA_INTRO_DONE)
return introDone;
DoMeleeAttackIfReady(); return 0;
} }
void JustDied(Unit* /*killer*/) void SetData(uint32 type, uint32 data)
{
if (type == DATA_INTRO_DONE)
introDone = data;
}
void UpdateAI(const uint32 diff)
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STAT_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_MIGHTY_BLOW:
DoCast(me->getVictim(),SPELL_MIGHTY_BLOW);
events.ScheduleEvent(EVENT_MIGHTY_BLOW, urand(5000,15000));
break;
}
}
if (me->GetReactState() == REACT_AGGRESSIVE)
DoMeleeAttackIfReady();
}
void JustSummoned(Creature* summon)
{
summon->SetInCombatWithZone();
if (phase == COLOSSUS_PHASE_SECOND_ELEMENTAL_SUMMON)
summon->SetHealth(summon->GetMaxHealth() / 2);
}
private:
uint8 phase;
bool introDone;
};
CreatureAI* GetAI(Creature* creature) const
{ {
if (Creature *pColossus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0)) return new boss_drakkari_colossusAI(creature);
pColossus->Kill(pColossus);
} }
};
}; };
class boss_drakkari_elemental : public CreatureScript
{
public:
boss_drakkari_elemental() : CreatureScript("boss_drakkari_elemental") { }
struct boss_drakkari_elementalAI : public ScriptedAI
{
boss_drakkari_elementalAI(Creature* creature) : ScriptedAI(creature)
{
DoCast(me,SPELL_ELEMENTAL_SPAWN_EFEFCT);
instance = creature->GetInstanceScript();
}
void Reset()
{
events.Reset();
events.ScheduleEvent(EVENT_SURGE,urand(5000,15000));
me->AddAura(SPELL_MOJO_VOLLEY,me);
}
void JustDied(Unit* killer)
{
if (killer == me)
return;
if (instance)
{
if (Creature* colossus = Unit::GetCreature(*me, instance->GetData64(DATA_DRAKKARI_COLOSSUS)))
killer->Kill(colossus);
}
}
void UpdateAI(const uint32 diff)
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STAT_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_SURGE:
DoCast(SPELL_SURGE_VISUAL);
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true))
DoCast(target,SPELL_SURGE);
events.ScheduleEvent(EVENT_SURGE,urand(5000,15000));
break;
}
}
DoMeleeAttackIfReady();
}
void DoAction(const int32 action)
{
switch (action)
{
case ACTION_RETURN_TO_COLOSSUS:
DoCast(SPELL_SURGE_VISUAL);
if (instance)
{
if (Creature* colossus = Unit::GetCreature(*me, instance->GetData64(DATA_DRAKKARI_COLOSSUS)))
DoCast(colossus,SPELL_MERGE);
}
break;
}
}
void DamageTaken(Unit* /*attacker*/, uint32& damage)
{
if (HealthBelowPct(50) && instance)
{
if (Creature* colossus = Unit::GetCreature(*me, instance->GetData64(DATA_DRAKKARI_COLOSSUS)))
{
if (colossus->AI()->GetData(DATA_COLOSSUS_PHASE) == COLOSSUS_PHASE_FIRST_ELEMENTAL_SUMMON)
{
DoAction(ACTION_RETURN_TO_COLOSSUS);
damage = 0;
}
}
}
}
void EnterEvadeMode()
{
me->DespawnOrUnsummon();
}
void SpellHitTarget(Unit* target, SpellEntry const* spell)
{
if (spell->Id == SPELL_MERGE)
{
if (Creature* colossus = target->ToCreature())
{
colossus->AI()->DoAction(ACTION_UNFREEZE_COLOSSUS);
me->DespawnOrUnsummon();
}
}
}
private:
EventMap events;
InstanceScript* instance;
};
CreatureAI* GetAI(Creature* creature) const
{
return new boss_drakkari_elementalAI(creature);
}
};
class npc_living_mojo : public CreatureScript class npc_living_mojo : public CreatureScript
{ {
public: public:
@@ -244,76 +367,101 @@ public:
struct npc_living_mojoAI : public ScriptedAI struct npc_living_mojoAI : public ScriptedAI
{ {
npc_living_mojoAI(Creature* pCreature) : ScriptedAI(pCreature) npc_living_mojoAI(Creature* creature) : ScriptedAI(creature)
{ {
pInstance = pCreature->GetInstanceScript(); instance = creature->GetInstanceScript();
} }
InstanceScript* pInstance;
uint32 uiMojoWaveTimer;
uint32 uiMojoPuddleTimer;
void Reset() void Reset()
{ {
uiMojoWaveTimer = 2*IN_MILLISECONDS; mojoWaveTimer = 2*IN_MILLISECONDS;
uiMojoPuddleTimer = 7*IN_MILLISECONDS; mojoPuddleTimer = 7*IN_MILLISECONDS;
} }
void EnterCombat(Unit* /*who*/) void MoveMojos(Creature* boss)
{ {
std::list<Creature*> mojosList;
//Check if the npc is near of Drakkari Colossus. boss->GetCreatureListWithEntryInGrid(mojosList,me->GetEntry(),12.0f);
if (Creature *pColossus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0)) if (!mojosList.empty())
{ {
if (pColossus->isAlive() && me->IsInRange3d(pColossus->GetHomePosition().GetPositionX(),pColossus->GetHomePosition().GetPositionY(),pColossus->GetHomePosition().GetPositionZ(),0.0f,17.0f)) for (std::list<Creature*>::const_iterator itr = mojosList.begin(); itr != mojosList.end(); ++itr)
me->SetReactState(REACT_PASSIVE); {
else if (Creature* mojo = *itr)
me->SetReactState(REACT_AGGRESSIVE); mojo->GetMotionMaster()->MovePoint(1,boss->GetHomePosition().GetPositionX(),boss->GetHomePosition().GetPositionY(),boss->GetHomePosition().GetPositionZ());
}
} }
} }
void DamageTaken(Unit* pDone_by, uint32& /*uiDamage*/) void MovementInform(uint32 type, uint32 id)
{ {
if (me->HasReactState(REACT_PASSIVE)) if (type != POINT_MOTION_TYPE)
return;
if (id == 1)
{ {
if (Creature *pColossus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0)) if (Creature* colossus = Unit::GetCreature(*me, instance ? instance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0))
{ {
if (pColossus->isAlive() && !pColossus->isInCombat()) colossus->AI()->DoAction(ACTION_UNFREEZE_COLOSSUS);
{ if (!colossus->AI()->GetData(DATA_INTRO_DONE))
pColossus->RemoveAura(SPELL_FREEZE_ANIM); colossus->AI()->SetData(DATA_INTRO_DONE,true);
pColossus->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); colossus->SetInCombatWithZone();
pColossus->SetReactState(REACT_AGGRESSIVE); me->DespawnOrUnsummon();
if (pDone_by && pDone_by->isAlive())
pColossus->AI()->AttackStart(pDone_by);
EnterEvadeMode();
}
} }
} }
} }
void AttackStart(Unit* attacker)
{
if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE)
return;
// we do this checks to see if the creature is one of the creatures that sorround the boss
if (Creature* colossus = Unit::GetCreature(*me, instance ? instance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0))
{
Position homePosition;
me->GetHomePosition().GetPosition(&homePosition);
Position colossusHomePosition;
colossus->GetHomePosition().GetPosition(&colossusHomePosition);
float distance = homePosition.GetExactDist(colossusHomePosition.GetPositionX(),colossusHomePosition.GetPositionY(),colossusHomePosition.GetPositionZ());
if (distance < 12.0f)
{
MoveMojos(colossus);
me->SetReactState(REACT_PASSIVE);
}
else
ScriptedAI::AttackStart(attacker);
}
}
void UpdateAI(const uint32 diff) void UpdateAI(const uint32 diff)
{ {
//Return since we have no target //Return since we have no target
if (!UpdateVictim()) if (!UpdateVictim())
return; return;
if (uiMojoWaveTimer <= diff) if (mojoWaveTimer <= diff)
{ {
DoCast(me->getVictim(), SPELL_MOJO_WAVE); DoCast(me->getVictim(), SPELL_MOJO_WAVE);
uiMojoWaveTimer = 15*IN_MILLISECONDS; mojoWaveTimer = 15*IN_MILLISECONDS;
} else uiMojoWaveTimer -= diff; } else mojoWaveTimer -= diff;
if (uiMojoPuddleTimer <= diff) if (mojoPuddleTimer <= diff)
{ {
DoCast(me->getVictim(), SPELL_MOJO_PUDDLE); DoCast(me->getVictim(), SPELL_MOJO_PUDDLE);
uiMojoPuddleTimer = 18*IN_MILLISECONDS; mojoPuddleTimer = 18*IN_MILLISECONDS;
} else uiMojoPuddleTimer -= diff; } else mojoPuddleTimer -= diff;
DoMeleeAttackIfReady(); DoMeleeAttackIfReady();
} }
private:
InstanceScript* instance;
uint32 mojoWaveTimer;
uint32 mojoPuddleTimer;
}; };
}; };