Core/Scripts: Rewritten Drakkari Colossus encounter from Gundrak.

Signed-off-by: Manuel <manue.l@live.com.ar>
This commit is contained in:
Manuel
2011-01-15 19:03:32 -03:00
parent 29a8b5407a
commit 58564cc496

View File

@@ -25,213 +25,336 @@
enum Spells
{
SPELL_EMERGE = 54850,
SPELL_MIGHTY_BLOW = 54719,
SPELL_ELEMENTAL_SPAWN_EFEFCT = 54888,
SPELL_MOJO_VOLLEY = 54849,
SPELL_SURGE_VISUAL = 54827,
SPELL_MERGE = 54878,
SPELL_MIGHTY_BLOW = 54719,
SPELL_SURGE = 54801,
SPELL_FREEZE_ANIM = 16245,
SPELL_MOJO_PUDDLE = 55627,
H_SPELL_MOJO_PUDDLE = 58994,
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
{
public:
boss_drakkari_colossus() : CreatureScript("boss_drakkari_colossus") { }
public:
boss_drakkari_colossus() : CreatureScript("boss_drakkari_colossus") { }
CreatureAI* GetAI(Creature* pCreature) const
{
return new boss_drakkari_colossusAI (pCreature);
}
struct boss_drakkari_colossusAI : public ScriptedAI
{
boss_drakkari_colossusAI(Creature* pCreature) : ScriptedAI(pCreature)
struct boss_drakkari_colossusAI : public BossAI
{
pInstance = pCreature->GetInstanceScript();
}
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)
boss_drakkari_colossusAI(Creature* creature) : BossAI(creature, DATA_DRAKKARI_COLOSSUS_EVENT)
{
pWho->ClearUnitState(UNIT_STAT_STUNNED | UNIT_STAT_ROOT);
pWho->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
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;
me->SetReactState(REACT_PASSIVE);
introDone = false;
}
if (!bHealth1 && HealthBelowPct(5))
void InitializeAI()
{
DoCast(me,SPELL_EMERGE);
CreatureState(me, false);
bHealth1 = true;
me->RemoveAllAuras();
if (!me->isDead())
Reset();
}
if (MightyBlowTimer <= diff)
void Reset()
{
DoCast(me->getVictim(), SPELL_MIGHTY_BLOW, true);
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 (GetData(DATA_INTRO_DONE))
{
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);
DoCast(pColossus, SPELL_MERGE);
bGoToColossus = true;
damage = 0;
phase = (phase == COLOSSUS_PHASE_NORMAL ? COLOSSUS_PHASE_FIRST_ELEMENTAL_SUMMON : COLOSSUS_PHASE_SECOND_ELEMENTAL_SUMMON);
DoAction(ACTION_FREEZE_COLOSSUS);
DoAction(ACTION_SUMMON_ELEMENTAL);
}
}
}
if (uiSurgeTimer <= diff)
uint32 GetData(uint32 data)
{
DoCast(me->getVictim(), SPELL_SURGE);
uiSurgeTimer = 7*IN_MILLISECONDS;
} else uiSurgeTimer -= diff;
if (data == DATA_COLOSSUS_PHASE)
return phase;
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))
pColossus->Kill(pColossus);
return new boss_drakkari_colossusAI(creature);
}
};
};
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
{
public:
@@ -244,76 +367,101 @@ public:
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()
{
uiMojoWaveTimer = 2*IN_MILLISECONDS;
uiMojoPuddleTimer = 7*IN_MILLISECONDS;
mojoWaveTimer = 2*IN_MILLISECONDS;
mojoPuddleTimer = 7*IN_MILLISECONDS;
}
void EnterCombat(Unit* /*who*/)
void MoveMojos(Creature* boss)
{
//Check if the npc is near of Drakkari Colossus.
if (Creature *pColossus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_DRAKKARI_COLOSSUS) : 0))
std::list<Creature*> mojosList;
boss->GetCreatureListWithEntryInGrid(mojosList,me->GetEntry(),12.0f);
if (!mojosList.empty())
{
if (pColossus->isAlive() && me->IsInRange3d(pColossus->GetHomePosition().GetPositionX(),pColossus->GetHomePosition().GetPositionY(),pColossus->GetHomePosition().GetPositionZ(),0.0f,17.0f))
me->SetReactState(REACT_PASSIVE);
else
me->SetReactState(REACT_AGGRESSIVE);
for (std::list<Creature*>::const_iterator itr = mojosList.begin(); itr != mojosList.end(); ++itr)
{
if (Creature* mojo = *itr)
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())
{
pColossus->RemoveAura(SPELL_FREEZE_ANIM);
pColossus->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE);
pColossus->SetReactState(REACT_AGGRESSIVE);
if (pDone_by && pDone_by->isAlive())
pColossus->AI()->AttackStart(pDone_by);
EnterEvadeMode();
}
colossus->AI()->DoAction(ACTION_UNFREEZE_COLOSSUS);
if (!colossus->AI()->GetData(DATA_INTRO_DONE))
colossus->AI()->SetData(DATA_INTRO_DONE,true);
colossus->SetInCombatWithZone();
me->DespawnOrUnsummon();
}
}
}
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)
{
//Return since we have no target
if (!UpdateVictim())
return;
if (uiMojoWaveTimer <= diff)
if (mojoWaveTimer <= diff)
{
DoCast(me->getVictim(), SPELL_MOJO_WAVE);
uiMojoWaveTimer = 15*IN_MILLISECONDS;
} else uiMojoWaveTimer -= diff;
mojoWaveTimer = 15*IN_MILLISECONDS;
} else mojoWaveTimer -= diff;
if (uiMojoPuddleTimer <= diff)
if (mojoPuddleTimer <= diff)
{
DoCast(me->getVictim(), SPELL_MOJO_PUDDLE);
uiMojoPuddleTimer = 18*IN_MILLISECONDS;
} else uiMojoPuddleTimer -= diff;
mojoPuddleTimer = 18*IN_MILLISECONDS;
} else mojoPuddleTimer -= diff;
DoMeleeAttackIfReady();
}
private:
InstanceScript* instance;
uint32 mojoWaveTimer;
uint32 mojoPuddleTimer;
};
};