mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-18 16:38:42 +01:00
*Add a new class for event based scripts. Two examples are given.
--HG-- branch : trunk
This commit is contained in:
@@ -16,52 +16,49 @@ struct TSpellSummary {
|
||||
uint8 Effects; // set of enum SelectEffect
|
||||
} *SpellSummary;
|
||||
|
||||
void SummonList::Despawn(Creature *summon)
|
||||
void SummonList::DoAction(uint32 entry, uint32 info)
|
||||
{
|
||||
uint64 guid = summon->GetGUID();
|
||||
for(iterator i = begin(); i != end(); ++i)
|
||||
for(iterator i = begin(); i != end();)
|
||||
{
|
||||
if(*i == guid)
|
||||
{
|
||||
erase(i);
|
||||
return;
|
||||
}
|
||||
Creature *summon = Unit::GetCreature(*m_creature, *i);
|
||||
++i;
|
||||
if(summon && summon->IsAIEnabled)
|
||||
summon->AI()->DoAction(info);
|
||||
}
|
||||
}
|
||||
|
||||
void SummonList::DespawnEntry(uint32 entry)
|
||||
{
|
||||
for(iterator i = begin(); i != end(); ++i)
|
||||
for(iterator i = begin(); i != end();)
|
||||
{
|
||||
if(Creature *summon = Unit::GetCreature(*m_creature, *i))
|
||||
Creature *summon = Unit::GetCreature(*m_creature, *i);
|
||||
if(!summon)
|
||||
erase(i++);
|
||||
else if(summon->GetEntry() == entry)
|
||||
{
|
||||
if(summon->GetEntry() == entry)
|
||||
{
|
||||
summon->setDeathState(JUST_DIED);
|
||||
summon->RemoveCorpse();
|
||||
i = erase(i);
|
||||
--i;
|
||||
}
|
||||
erase(i++);
|
||||
summon->setDeathState(JUST_DIED);
|
||||
summon->RemoveCorpse();
|
||||
}
|
||||
else
|
||||
{
|
||||
i = erase(i);
|
||||
--i;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
void SummonList::DespawnAll()
|
||||
{
|
||||
for(iterator i = begin(); i != end(); ++i)
|
||||
while(!empty())
|
||||
{
|
||||
if(Creature *summon = Unit::GetCreature(*m_creature, *i))
|
||||
Creature *summon = Unit::GetCreature(*m_creature, *begin());
|
||||
if(!summon)
|
||||
erase(begin());
|
||||
else
|
||||
{
|
||||
erase(begin());
|
||||
summon->setDeathState(JUST_DIED);
|
||||
summon->RemoveCorpse();
|
||||
}
|
||||
}
|
||||
clear();
|
||||
}
|
||||
|
||||
void ScriptedAI::AttackStart(Unit* who, bool melee)
|
||||
|
||||
@@ -13,14 +13,15 @@
|
||||
|
||||
float GetSpellMaxRangeForHostile(uint32 id);
|
||||
|
||||
class SummonList : std::list<uint64>
|
||||
class SummonList : private std::list<uint64>
|
||||
{
|
||||
public:
|
||||
SummonList(Creature* creature) : m_creature(creature) {}
|
||||
void Summon(Creature *summon) {push_back(summon->GetGUID());}
|
||||
void Despawn(Creature *summon);
|
||||
explicit SummonList(Creature* creature) : m_creature(creature) {}
|
||||
void Summon(Creature *summon) { push_back(summon->GetGUID()); }
|
||||
void Despawn(Creature *summon) { remove(summon->GetGUID()); }
|
||||
void DespawnEntry(uint32 entry);
|
||||
void DespawnAll();
|
||||
void DoAction(uint32 entry, uint32 info);
|
||||
private:
|
||||
Creature *m_creature;
|
||||
};
|
||||
|
||||
@@ -39,6 +39,18 @@ EndScriptData */
|
||||
#define CREATURE_VOLCANO 23085
|
||||
#define CREATURE_STALKER 23095
|
||||
|
||||
#define PHASE_STRIKE 1
|
||||
#define PHASE_CHASE 2
|
||||
|
||||
#define EVENT_BERSERK 1
|
||||
#define EVENT_SWITCH_PHASE 2
|
||||
#define EVENT_FLAME 3
|
||||
#define EVENT_VOLCANO 4
|
||||
#define EVENT_SWITCH_TARGET 5
|
||||
#define EVENT_HATEFUL_STRIKE 6
|
||||
|
||||
#define GCD_CAST 1
|
||||
|
||||
struct TRINITY_DLL_DECL molten_flameAI : public NullCreatureAI
|
||||
{
|
||||
molten_flameAI(Creature *c) : NullCreatureAI(c)
|
||||
@@ -57,17 +69,9 @@ struct TRINITY_DLL_DECL boss_supremusAI : public ScriptedAI
|
||||
}
|
||||
|
||||
ScriptedInstance* pInstance;
|
||||
|
||||
uint32 SummonFlameTimer;
|
||||
uint32 SwitchTargetTimer;
|
||||
uint32 PhaseSwitchTimer;
|
||||
uint32 SummonVolcanoTimer;
|
||||
uint32 HatefulStrikeTimer;
|
||||
uint32 BerserkTimer;
|
||||
|
||||
bool Phase1;
|
||||
|
||||
EventMap events;
|
||||
SummonList summons;
|
||||
uint32 phase;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
@@ -81,26 +85,20 @@ struct TRINITY_DLL_DECL boss_supremusAI : public ScriptedAI
|
||||
//else ToggleDoors(false);
|
||||
}
|
||||
|
||||
HatefulStrikeTimer = 5000;
|
||||
SummonFlameTimer = 20000;
|
||||
SwitchTargetTimer = 90000;
|
||||
PhaseSwitchTimer = 60000;
|
||||
SummonVolcanoTimer = 5000;
|
||||
BerserkTimer = 900000; // 15 minute enrage
|
||||
phase = 0;
|
||||
|
||||
Phase1 = true;
|
||||
events.Reset();
|
||||
summons.DespawnAll();
|
||||
|
||||
m_creature->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false);
|
||||
m_creature->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, false);
|
||||
}
|
||||
|
||||
void Aggro(Unit *who)
|
||||
{
|
||||
DoZoneInCombat();
|
||||
|
||||
if(pInstance)
|
||||
pInstance->SetData(DATA_SUPREMUSEVENT, IN_PROGRESS);
|
||||
|
||||
ChangePhase();
|
||||
events.ScheduleEvent(900000, EVENT_BERSERK, GCD_CAST);
|
||||
events.ScheduleEvent(20000, EVENT_FLAME, GCD_CAST);
|
||||
}
|
||||
|
||||
void ToggleDoors(bool close)
|
||||
@@ -112,6 +110,32 @@ struct TRINITY_DLL_DECL boss_supremusAI : public ScriptedAI
|
||||
}
|
||||
}
|
||||
|
||||
void ChangePhase()
|
||||
{
|
||||
if(!phase || phase == PHASE_CHASE)
|
||||
{
|
||||
phase = PHASE_STRIKE;
|
||||
summons.DoAction(EVENT_VOLCANO, 0);
|
||||
events.ScheduleEvent(5000, EVENT_HATEFUL_STRIKE, GCD_CAST, PHASE_STRIKE);
|
||||
m_creature->SetSpeed(MOVE_RUN, 1.2f);
|
||||
m_creature->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false);
|
||||
m_creature->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
phase = PHASE_CHASE;
|
||||
events.ScheduleEvent(5000, EVENT_VOLCANO, GCD_CAST, PHASE_CHASE);
|
||||
events.ScheduleEvent(10000, EVENT_SWITCH_TARGET, 0, PHASE_CHASE);
|
||||
m_creature->SetSpeed(MOVE_RUN, 0.9f);
|
||||
m_creature->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true);
|
||||
m_creature->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, true);
|
||||
}
|
||||
DoResetThreat();
|
||||
DoZoneInCombat();
|
||||
events.SetPhase(phase);
|
||||
events.ScheduleEvent(60000, EVENT_SWITCH_PHASE, GCD_CAST);
|
||||
}
|
||||
|
||||
void JustDied(Unit *killer)
|
||||
{
|
||||
if(pInstance)
|
||||
@@ -153,83 +177,53 @@ struct TRINITY_DLL_DECL boss_supremusAI : public ScriptedAI
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if(!m_creature->HasAura(SPELL_BERSERK))
|
||||
{
|
||||
if(BerserkTimer < diff)
|
||||
DoCast(m_creature, SPELL_BERSERK);
|
||||
else BerserkTimer -= diff;
|
||||
}
|
||||
events.Update(diff);
|
||||
|
||||
if(SummonFlameTimer < diff)
|
||||
while(uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
DoCast(m_creature, SPELL_MOLTEN_PUNCH);
|
||||
SummonFlameTimer = 20000;
|
||||
}else SummonFlameTimer -= diff;
|
||||
|
||||
if(Phase1)
|
||||
{
|
||||
if(HatefulStrikeTimer < diff)
|
||||
switch(eventId)
|
||||
{
|
||||
if(Unit* target = CalculateHatefulStrikeTarget())
|
||||
case EVENT_BERSERK:
|
||||
m_creature->CastSpell(m_creature, SPELL_BERSERK, true);
|
||||
break;
|
||||
case EVENT_FLAME:
|
||||
DoCast(m_creature, SPELL_MOLTEN_PUNCH);
|
||||
events.DelayEvents(1500, GCD_CAST);
|
||||
events.ScheduleEvent(20000, EVENT_FLAME, GCD_CAST);
|
||||
break;
|
||||
case EVENT_HATEFUL_STRIKE:
|
||||
if(Unit* target = CalculateHatefulStrikeTarget())
|
||||
DoCast(target, SPELL_HATEFUL_STRIKE);
|
||||
events.DelayEvents(1000, GCD_CAST);
|
||||
events.ScheduleEvent(5000, EVENT_HATEFUL_STRIKE, GCD_CAST, PHASE_STRIKE);
|
||||
break;
|
||||
case EVENT_SWITCH_TARGET:
|
||||
if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 1, 100, true))
|
||||
{
|
||||
DoResetThreat();
|
||||
m_creature->AddThreat(target, 5000000.0f);
|
||||
DoScriptText(EMOTE_NEW_TARGET, m_creature);
|
||||
}
|
||||
events.ScheduleEvent(10000, EVENT_SWITCH_TARGET, 0, PHASE_CHASE);
|
||||
break;
|
||||
case EVENT_VOLCANO:
|
||||
{
|
||||
DoCast(target, SPELL_HATEFUL_STRIKE);
|
||||
HatefulStrikeTimer = 5000;
|
||||
Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0, 999, true);
|
||||
if(!target) target = m_creature->getVictim();
|
||||
if(target)
|
||||
{
|
||||
DoCast(target, SPELL_VOLCANIC_SUMMON);
|
||||
DoScriptText(EMOTE_GROUND_CRACK, m_creature);
|
||||
events.DelayEvents(1500, GCD_CAST);
|
||||
}
|
||||
events.ScheduleEvent(10000, EVENT_VOLCANO, GCD_CAST, PHASE_CHASE);
|
||||
return;
|
||||
}
|
||||
}else HatefulStrikeTimer -= diff;
|
||||
}
|
||||
|
||||
if(!Phase1)
|
||||
{
|
||||
if(SwitchTargetTimer < diff)
|
||||
{
|
||||
if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 1, 100, true))
|
||||
{
|
||||
DoResetThreat();
|
||||
m_creature->AddThreat(target, 5000000.0f);
|
||||
DoScriptText(EMOTE_NEW_TARGET, m_creature);
|
||||
SwitchTargetTimer = 10000;
|
||||
}
|
||||
}else SwitchTargetTimer -= diff;
|
||||
|
||||
if(SummonVolcanoTimer < diff)
|
||||
{
|
||||
if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0, 999, true))
|
||||
{
|
||||
if(!target)
|
||||
target = m_creature->getVictim();
|
||||
|
||||
DoCast(target, SPELL_VOLCANIC_SUMMON);
|
||||
DoScriptText(EMOTE_GROUND_CRACK, m_creature);
|
||||
SummonVolcanoTimer = 10000;
|
||||
}
|
||||
}else SummonVolcanoTimer -= diff;
|
||||
}
|
||||
|
||||
if(PhaseSwitchTimer < diff)
|
||||
{
|
||||
if(!Phase1)
|
||||
{
|
||||
Phase1 = true;
|
||||
DoResetThreat();
|
||||
PhaseSwitchTimer = 60000;
|
||||
m_creature->SetSpeed(MOVE_RUN, 1.2f);
|
||||
DoZoneInCombat();
|
||||
m_creature->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false);
|
||||
m_creature->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, false);
|
||||
case EVENT_SWITCH_PHASE:
|
||||
ChangePhase();
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
Phase1 = false;
|
||||
DoResetThreat();
|
||||
SwitchTargetTimer = 10000;
|
||||
SummonVolcanoTimer = 2000;
|
||||
PhaseSwitchTimer = 60000;
|
||||
m_creature->SetSpeed(MOVE_RUN, 0.9f);
|
||||
DoZoneInCombat();
|
||||
m_creature->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true);
|
||||
m_creature->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, true);
|
||||
}
|
||||
}else PhaseSwitchTimer -= diff;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
@@ -237,50 +231,25 @@ struct TRINITY_DLL_DECL boss_supremusAI : public ScriptedAI
|
||||
|
||||
struct TRINITY_DLL_DECL npc_volcanoAI : public ScriptedAI
|
||||
{
|
||||
npc_volcanoAI(Creature *c) : ScriptedAI(c)
|
||||
{
|
||||
pInstance = ((ScriptedInstance*)c->GetInstanceData());
|
||||
}
|
||||
|
||||
ScriptedInstance *pInstance;
|
||||
|
||||
uint32 CheckTimer;
|
||||
bool Eruption;
|
||||
npc_volcanoAI(Creature *c) : ScriptedAI(c) {}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
CheckTimer = 1500;
|
||||
Eruption = false;
|
||||
|
||||
m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
|
||||
m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
DoCast(m_creature, SPELL_VOLCANIC_ERUPTION);
|
||||
}
|
||||
|
||||
void Aggro(Unit *who) {}
|
||||
|
||||
void MoveInLineOfSight(Unit *who)
|
||||
void MoveInLineOfSight(Unit *who) {}
|
||||
|
||||
void DoAction(const uint32 info)
|
||||
{
|
||||
return; // paralyze the npc
|
||||
m_creature->RemoveAura(SPELL_VOLCANIC_ERUPTION);
|
||||
}
|
||||
|
||||
void UpdateAI(const uint32 diff)
|
||||
{
|
||||
if(CheckTimer < diff)
|
||||
{
|
||||
uint64 SupremusGUID = pInstance->GetData64(DATA_SUPREMUS);
|
||||
Creature* Supremus = (Unit::GetCreature((*m_creature), SupremusGUID));
|
||||
if(!Eruption && !((boss_supremusAI*)Supremus->AI())->Phase1)
|
||||
{
|
||||
Eruption = true;
|
||||
DoCast(m_creature, SPELL_VOLCANIC_ERUPTION);
|
||||
}
|
||||
else if(Eruption && ((boss_supremusAI*)Supremus->AI())->Phase1)
|
||||
{
|
||||
m_creature->RemoveAura(SPELL_VOLCANIC_ERUPTION);
|
||||
}
|
||||
CheckTimer = 1500;
|
||||
}else CheckTimer -= diff;
|
||||
}
|
||||
void UpdateAI(const uint32 diff) {}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI_boss_supremus(Creature *_Creature)
|
||||
|
||||
@@ -46,6 +46,15 @@ EndScriptData */
|
||||
|
||||
#define GOBJECT_SPINE 185584
|
||||
|
||||
#define EVENT_BERSERK 1
|
||||
#define EVENT_YELL 2
|
||||
#define EVENT_NEEDLE 3
|
||||
#define EVENT_SPINE 4
|
||||
#define EVENT_SHIELD 5
|
||||
|
||||
#define GCD_CAST 1
|
||||
#define GCD_YELL 2
|
||||
|
||||
struct TRINITY_DLL_DECL boss_najentusAI : public ScriptedAI
|
||||
{
|
||||
boss_najentusAI(Creature *c) : ScriptedAI(c)
|
||||
@@ -54,21 +63,13 @@ struct TRINITY_DLL_DECL boss_najentusAI : public ScriptedAI
|
||||
}
|
||||
|
||||
ScriptedInstance* pInstance;
|
||||
|
||||
uint32 NeedleSpineTimer;
|
||||
uint32 EnrageTimer;
|
||||
uint32 SpecialYellTimer;
|
||||
uint32 TidalShieldTimer;
|
||||
uint32 ImpalingSpineTimer;
|
||||
EventMap events;
|
||||
|
||||
uint64 SpineTargetGUID;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
EnrageTimer = 480000;
|
||||
SpecialYellTimer = 45000 + (rand()%76)*1000;
|
||||
|
||||
ResetTimer();
|
||||
events.Reset();
|
||||
|
||||
SpineTargetGUID = 0;
|
||||
|
||||
@@ -78,11 +79,8 @@ struct TRINITY_DLL_DECL boss_najentusAI : public ScriptedAI
|
||||
|
||||
void KilledUnit(Unit *victim)
|
||||
{
|
||||
switch(rand()%2)
|
||||
{
|
||||
case 0: DoScriptText(SAY_SLAY1, m_creature); break;
|
||||
case 1: DoScriptText(SAY_SLAY2, m_creature); break;
|
||||
}
|
||||
DoScriptText(rand()%2 ? SAY_SLAY1 : SAY_SLAY2, m_creature);
|
||||
events.DelayEvents(5000, GCD_YELL);
|
||||
}
|
||||
|
||||
void JustDied(Unit *victim)
|
||||
@@ -110,6 +108,9 @@ struct TRINITY_DLL_DECL boss_najentusAI : public ScriptedAI
|
||||
|
||||
DoScriptText(SAY_AGGRO, m_creature);
|
||||
DoZoneInCombat();
|
||||
events.ScheduleEvent(480000, EVENT_BERSERK, GCD_CAST);
|
||||
events.ScheduleEvent(45000 + (rand()%76)*1000, EVENT_YELL, GCD_YELL);
|
||||
ResetTimer();
|
||||
}
|
||||
|
||||
bool RemoveImpalingSpine()
|
||||
@@ -124,9 +125,9 @@ struct TRINITY_DLL_DECL boss_najentusAI : public ScriptedAI
|
||||
|
||||
void ResetTimer(uint32 inc = 0)
|
||||
{
|
||||
NeedleSpineTimer = 10000 + inc;
|
||||
TidalShieldTimer = 60000 + inc;
|
||||
ImpalingSpineTimer = 20000 + inc;
|
||||
events.ScheduleEvent(10000 + inc, EVENT_NEEDLE, GCD_CAST);
|
||||
events.ScheduleEvent(20000 + inc, EVENT_SPINE, GCD_CAST);
|
||||
events.ScheduleEvent(60000 + inc, EVENT_SHIELD);
|
||||
}
|
||||
|
||||
void UpdateAI(const uint32 diff)
|
||||
@@ -134,58 +135,56 @@ struct TRINITY_DLL_DECL boss_najentusAI : public ScriptedAI
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if(TidalShieldTimer < diff)
|
||||
{
|
||||
m_creature->CastSpell(m_creature, SPELL_TIDAL_SHIELD, true);
|
||||
ResetTimer(45000);
|
||||
}else TidalShieldTimer -= diff;
|
||||
events.Update(diff);
|
||||
|
||||
if(EnrageTimer < diff)
|
||||
while(uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
DoScriptText(SAY_ENRAGE2, m_creature);
|
||||
m_creature->CastSpell(m_creature, SPELL_BERSERK, true);
|
||||
EnrageTimer = 600000;
|
||||
}else EnrageTimer -= diff;
|
||||
|
||||
if(NeedleSpineTimer < diff)
|
||||
{
|
||||
//m_creature->CastSpell(m_creature, SPELL_NEEDLE_SPINE, true);
|
||||
std::list<Unit*> target;
|
||||
SelectUnitList(target, 3, SELECT_TARGET_RANDOM, 80, true);
|
||||
for(std::list<Unit*>::iterator i = target.begin(); i != target.end(); ++i)
|
||||
m_creature->CastSpell(*i, 39835, true);
|
||||
NeedleSpineTimer = 2000+rand()%1000;
|
||||
}else NeedleSpineTimer -= diff;
|
||||
|
||||
if(SpecialYellTimer < diff)
|
||||
{
|
||||
switch(rand()%2)
|
||||
switch(eventId)
|
||||
{
|
||||
case 0: DoScriptText(SAY_SPECIAL1, m_creature); break;
|
||||
case 1: DoScriptText(SAY_SPECIAL2, m_creature); break;
|
||||
}
|
||||
SpecialYellTimer = 25000 + (rand()%76)*1000;
|
||||
}else SpecialYellTimer -= diff;
|
||||
|
||||
if(ImpalingSpineTimer < diff)
|
||||
{
|
||||
Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 1);
|
||||
if(!target) target = m_creature->getVictim();
|
||||
if(target)
|
||||
{
|
||||
m_creature->CastSpell(target, SPELL_IMPALING_SPINE, true);
|
||||
SpineTargetGUID = target->GetGUID();
|
||||
//must let target summon, otherwise you cannot click the spine
|
||||
target->SummonGameObject(GOBJECT_SPINE, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), m_creature->GetOrientation(), 0, 0, 0, 0, 30);
|
||||
|
||||
switch(rand()%2)
|
||||
case EVENT_SHIELD:
|
||||
m_creature->CastSpell(m_creature, SPELL_TIDAL_SHIELD, true);
|
||||
ResetTimer(45000);
|
||||
break;
|
||||
case EVENT_BERSERK:
|
||||
DoScriptText(SAY_ENRAGE2, m_creature);
|
||||
m_creature->CastSpell(m_creature, SPELL_BERSERK, true);
|
||||
events.DelayEvents(15000, GCD_YELL);
|
||||
break;
|
||||
case EVENT_SPINE:
|
||||
{
|
||||
case 0: DoScriptText(SAY_NEEDLE1, m_creature); break;
|
||||
case 1: DoScriptText(SAY_NEEDLE2, m_creature); break;
|
||||
Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 1);
|
||||
if(!target) target = m_creature->getVictim();
|
||||
if(target)
|
||||
{
|
||||
m_creature->CastSpell(target, SPELL_IMPALING_SPINE, true);
|
||||
SpineTargetGUID = target->GetGUID();
|
||||
//must let target summon, otherwise you cannot click the spine
|
||||
target->SummonGameObject(GOBJECT_SPINE, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), m_creature->GetOrientation(), 0, 0, 0, 0, 30);
|
||||
DoScriptText(rand()%2 ? SAY_NEEDLE1 : SAY_NEEDLE2, m_creature);
|
||||
events.DelayEvents(1500, GCD_CAST);
|
||||
events.DelayEvents(15000, GCD_YELL);
|
||||
}
|
||||
events.ScheduleEvent(21000, EVENT_SPINE, GCD_CAST);
|
||||
return;
|
||||
}
|
||||
ImpalingSpineTimer = 21000;
|
||||
case EVENT_NEEDLE:
|
||||
{
|
||||
//m_creature->CastSpell(m_creature, SPELL_NEEDLE_SPINE, true);
|
||||
std::list<Unit*> target;
|
||||
SelectUnitList(target, 3, SELECT_TARGET_RANDOM, 80, true);
|
||||
for(std::list<Unit*>::iterator i = target.begin(); i != target.end(); ++i)
|
||||
m_creature->CastSpell(*i, 39835, true);
|
||||
events.ScheduleEvent(15000+rand()%10000, EVENT_NEEDLE, GCD_CAST);
|
||||
events.DelayEvents(1500, GCD_CAST);
|
||||
return;
|
||||
}
|
||||
case EVENT_YELL:
|
||||
DoScriptText(rand()%2 ? SAY_SPECIAL1 : SAY_SPECIAL2, m_creature);
|
||||
events.ScheduleEvent(25000 + (rand()%76)*1000, EVENT_YELL, GCD_YELL);
|
||||
events.DelayEvents(15000, GCD_YELL);
|
||||
break;
|
||||
}
|
||||
}else ImpalingSpineTimer -= diff;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
@@ -77,6 +77,76 @@ enum SCEquip
|
||||
EQUIP_UNEQUIP = 0
|
||||
};
|
||||
|
||||
class EventMap : private std::map<uint32, uint32>
|
||||
{
|
||||
private:
|
||||
uint32 m_time, m_phase;
|
||||
public:
|
||||
explicit EventMap() : m_phase(0), m_time(0) {}
|
||||
|
||||
void Reset() { clear(); m_time = 0; m_phase = 0; }
|
||||
|
||||
void Update(uint32 time) { m_time += time; }
|
||||
|
||||
void SetPhase(uint32 phase)
|
||||
{
|
||||
if(phase && phase < 9)
|
||||
m_phase = (1 << (phase + 24));
|
||||
}
|
||||
|
||||
void ScheduleEvent(uint32 time, uint32 eventId, uint32 gcd = 0, uint32 phase = 0)
|
||||
{
|
||||
time += m_time;
|
||||
if(gcd && gcd < 9)
|
||||
eventId |= (1 << (gcd + 16));
|
||||
if(phase && phase < 9)
|
||||
eventId |= (1 << (phase + 24));
|
||||
iterator itr = find(time);
|
||||
while(itr != end())
|
||||
{
|
||||
++time;
|
||||
itr = find(time);
|
||||
}
|
||||
insert(std::make_pair(time, eventId));
|
||||
}
|
||||
|
||||
uint32 ExecuteEvent()
|
||||
{
|
||||
while(!empty())
|
||||
{
|
||||
if(begin()->first > m_time)
|
||||
return 0;
|
||||
else if(m_phase && (begin()->second & 0xFF000000) && !(begin()->second & m_phase))
|
||||
erase(begin());
|
||||
else
|
||||
{
|
||||
uint32 eventId = (begin()->second & 0x0000FFFF);
|
||||
erase(begin());
|
||||
return eventId;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DelayEvents(uint32 time, uint32 gcd)
|
||||
{
|
||||
time += m_time;
|
||||
gcd = (1 << (gcd + 16));
|
||||
for(iterator itr = begin(); itr != end();)
|
||||
{
|
||||
if(itr->first >= time)
|
||||
break;
|
||||
if(itr->second & gcd)
|
||||
{
|
||||
ScheduleEvent(time, itr->second);
|
||||
erase(itr++);
|
||||
}
|
||||
else
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class TRINITY_DLL_SPEC UnitAI
|
||||
{
|
||||
protected:
|
||||
|
||||
Reference in New Issue
Block a user