*Update some naxx boss scripts.
--HG-- branch : trunk
This commit is contained in:
@@ -378,6 +378,7 @@ extern void AddSC_nagrand();
|
||||
extern void AddSC_boss_anubrekhan();
|
||||
extern void AddSC_boss_maexxna();
|
||||
extern void AddSC_boss_patchwerk();
|
||||
extern void AddSC_boss_grobbulus();
|
||||
extern void AddSC_boss_razuvious();
|
||||
extern void AddSC_boss_kelthuzad();
|
||||
extern void AddSC_boss_loatheb();
|
||||
@@ -1307,6 +1308,7 @@ void ScriptsInit(char const* cfg_file = "trinitycore.conf")
|
||||
AddSC_boss_faerlina();
|
||||
AddSC_boss_maexxna();
|
||||
AddSC_boss_patchwerk();
|
||||
AddSC_boss_grobbulus();
|
||||
AddSC_boss_razuvious();
|
||||
AddSC_boss_kelthuzad();
|
||||
AddSC_boss_loatheb();
|
||||
|
||||
@@ -61,6 +61,11 @@ void SummonList::DespawnAll()
|
||||
}
|
||||
}
|
||||
|
||||
ScriptedAI::ScriptedAI(Creature* creature) : CreatureAI(creature), m_creature(creature), IsFleeing(false)
|
||||
{
|
||||
HeroicMode = m_creature->GetMap()->IsHeroic();
|
||||
}
|
||||
|
||||
void ScriptedAI::AttackStart(Unit* who, bool melee)
|
||||
{
|
||||
if (!who)
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
#include "CreatureAI.h"
|
||||
#include "Creature.h"
|
||||
|
||||
#define HEROIC(n,h) (HeroicMode ? h : n)
|
||||
|
||||
float GetSpellMaxRangeForHostile(uint32 id);
|
||||
|
||||
class SummonList : private std::list<uint64>
|
||||
@@ -44,7 +46,7 @@ struct PointMovement
|
||||
|
||||
struct TRINITY_DLL_DECL ScriptedAI : public CreatureAI
|
||||
{
|
||||
ScriptedAI(Creature* creature) : CreatureAI(creature), m_creature(creature), IsFleeing(false) {}
|
||||
explicit ScriptedAI(Creature* creature);
|
||||
~ScriptedAI() {}
|
||||
|
||||
//*************
|
||||
@@ -101,6 +103,8 @@ struct TRINITY_DLL_DECL ScriptedAI : public CreatureAI
|
||||
//For fleeing
|
||||
bool IsFleeing;
|
||||
|
||||
bool HeroicMode;
|
||||
|
||||
//*************
|
||||
//Pure virtual functions
|
||||
//*************
|
||||
@@ -177,6 +181,8 @@ struct TRINITY_DLL_DECL ScriptedAI : public CreatureAI
|
||||
Unit* SelectUnit(SelectAggroTarget target, uint32 position, float dist, bool playerOnly);
|
||||
void SelectUnitList(std::list<Unit*> &targetList, uint32 num, SelectAggroTarget target, float dist, bool playerOnly);
|
||||
|
||||
bool HealthBelowPct(uint32 pct) const { return me->GetHealth() * 100 < m_creature->GetMaxHealth() * pct; }
|
||||
|
||||
//Returns spells that meet the specified criteria from the creatures spell list
|
||||
SpellEntry const* SelectSpell(Unit* Target, int32 School, int32 Mechanic, SelectTarget Targets, uint32 PowerCostMin, uint32 PowerCostMax, float RangeMin, float RangeMax, SelectEffect Effect);
|
||||
|
||||
|
||||
@@ -97,8 +97,8 @@ struct TRINITY_DLL_DECL boss_supremusAI : public ScriptedAI
|
||||
pInstance->SetData(DATA_SUPREMUSEVENT, IN_PROGRESS);
|
||||
|
||||
ChangePhase();
|
||||
events.ScheduleEvent(900000, EVENT_BERSERK, GCD_CAST);
|
||||
events.ScheduleEvent(20000, EVENT_FLAME, GCD_CAST);
|
||||
events.ScheduleEvent(EVENT_BERSERK, 900000, GCD_CAST);
|
||||
events.ScheduleEvent(EVENT_FLAME, 20000, GCD_CAST);
|
||||
}
|
||||
|
||||
void ToggleDoors(bool close)
|
||||
@@ -116,7 +116,7 @@ struct TRINITY_DLL_DECL boss_supremusAI : public ScriptedAI
|
||||
{
|
||||
phase = PHASE_STRIKE;
|
||||
summons.DoAction(EVENT_VOLCANO, 0);
|
||||
events.ScheduleEvent(5000, EVENT_HATEFUL_STRIKE, GCD_CAST, PHASE_STRIKE);
|
||||
events.ScheduleEvent(EVENT_HATEFUL_STRIKE, 5000, 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);
|
||||
@@ -124,8 +124,8 @@ struct TRINITY_DLL_DECL boss_supremusAI : public ScriptedAI
|
||||
else
|
||||
{
|
||||
phase = PHASE_CHASE;
|
||||
events.ScheduleEvent(5000, EVENT_VOLCANO, GCD_CAST, PHASE_CHASE);
|
||||
events.ScheduleEvent(10000, EVENT_SWITCH_TARGET, 0, PHASE_CHASE);
|
||||
events.ScheduleEvent(EVENT_VOLCANO, 5000, GCD_CAST, PHASE_CHASE);
|
||||
events.ScheduleEvent(EVENT_SWITCH_TARGET, 10000, 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);
|
||||
@@ -133,7 +133,7 @@ struct TRINITY_DLL_DECL boss_supremusAI : public ScriptedAI
|
||||
DoResetThreat();
|
||||
DoZoneInCombat();
|
||||
events.SetPhase(phase);
|
||||
events.ScheduleEvent(60000, EVENT_SWITCH_PHASE, GCD_CAST);
|
||||
events.ScheduleEvent(EVENT_SWITCH_PHASE, 60000, GCD_CAST);
|
||||
}
|
||||
|
||||
void JustDied(Unit *killer)
|
||||
@@ -189,13 +189,13 @@ struct TRINITY_DLL_DECL boss_supremusAI : public ScriptedAI
|
||||
case EVENT_FLAME:
|
||||
DoCast(m_creature, SPELL_MOLTEN_PUNCH);
|
||||
events.DelayEvents(1500, GCD_CAST);
|
||||
events.ScheduleEvent(20000, EVENT_FLAME, GCD_CAST);
|
||||
events.ScheduleEvent(EVENT_FLAME, 20000, 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);
|
||||
events.ScheduleEvent(EVENT_HATEFUL_STRIKE, 5000, GCD_CAST, PHASE_STRIKE);
|
||||
break;
|
||||
case EVENT_SWITCH_TARGET:
|
||||
if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 1, 100, true))
|
||||
@@ -204,7 +204,7 @@ struct TRINITY_DLL_DECL boss_supremusAI : public ScriptedAI
|
||||
m_creature->AddThreat(target, 5000000.0f);
|
||||
DoScriptText(EMOTE_NEW_TARGET, m_creature);
|
||||
}
|
||||
events.ScheduleEvent(10000, EVENT_SWITCH_TARGET, 0, PHASE_CHASE);
|
||||
events.ScheduleEvent(EVENT_SWITCH_TARGET, 10000, 0, PHASE_CHASE);
|
||||
break;
|
||||
case EVENT_VOLCANO:
|
||||
{
|
||||
@@ -216,7 +216,7 @@ struct TRINITY_DLL_DECL boss_supremusAI : public ScriptedAI
|
||||
DoScriptText(EMOTE_GROUND_CRACK, m_creature);
|
||||
events.DelayEvents(1500, GCD_CAST);
|
||||
}
|
||||
events.ScheduleEvent(10000, EVENT_VOLCANO, GCD_CAST, PHASE_CHASE);
|
||||
events.ScheduleEvent(EVENT_VOLCANO, 10000, GCD_CAST, PHASE_CHASE);
|
||||
return;
|
||||
}
|
||||
case EVENT_SWITCH_PHASE:
|
||||
|
||||
@@ -108,8 +108,8 @@ 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);
|
||||
events.ScheduleEvent(EVENT_BERSERK, 480000, GCD_CAST);
|
||||
events.ScheduleEvent(EVENT_YELL, 45000 + (rand()%76)*1000, GCD_YELL);
|
||||
ResetTimer();
|
||||
}
|
||||
|
||||
@@ -125,9 +125,9 @@ struct TRINITY_DLL_DECL boss_najentusAI : public ScriptedAI
|
||||
|
||||
void ResetTimer(uint32 inc = 0)
|
||||
{
|
||||
events.ScheduleEvent(10000 + inc, EVENT_NEEDLE, GCD_CAST);
|
||||
events.ScheduleEvent(20000 + inc, EVENT_SPINE, GCD_CAST);
|
||||
events.ScheduleEvent(60000 + inc, EVENT_SHIELD);
|
||||
events.ScheduleEvent(EVENT_NEEDLE, 10000 + inc, GCD_CAST);
|
||||
events.ScheduleEvent(EVENT_SPINE, 20000 + inc, GCD_CAST);
|
||||
events.ScheduleEvent(EVENT_SHIELD, 60000 + inc);
|
||||
}
|
||||
|
||||
void UpdateAI(const uint32 diff)
|
||||
@@ -164,7 +164,7 @@ struct TRINITY_DLL_DECL boss_najentusAI : public ScriptedAI
|
||||
events.DelayEvents(1500, GCD_CAST);
|
||||
events.DelayEvents(15000, GCD_YELL);
|
||||
}
|
||||
events.ScheduleEvent(21000, EVENT_SPINE, GCD_CAST);
|
||||
events.ScheduleEvent(EVENT_SPINE, 21000, GCD_CAST);
|
||||
return;
|
||||
}
|
||||
case EVENT_NEEDLE:
|
||||
@@ -174,13 +174,13 @@ struct TRINITY_DLL_DECL boss_najentusAI : public ScriptedAI
|
||||
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.ScheduleEvent(EVENT_NEEDLE, 15000+rand()%10000, 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.ScheduleEvent(EVENT_YELL, 25000 + (rand()%76)*1000, GCD_YELL);
|
||||
events.DelayEvents(15000, GCD_YELL);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -246,13 +246,13 @@ struct TRINITY_DLL_DECL boss_moroesAI : public ScriptedAI
|
||||
{
|
||||
for(uint8 i = 0; i < 4; ++i)
|
||||
{
|
||||
Unit* Temp = NULL;
|
||||
Creature* Temp = NULL;
|
||||
if (AddGUID[i])
|
||||
{
|
||||
Temp = Unit::GetUnit((*m_creature),AddGUID[i]);
|
||||
Temp = Unit::GetCreature(*m_creature, AddGUID[i]);
|
||||
if (Temp && Temp->isAlive())
|
||||
{
|
||||
((Creature*)Temp)->AI()->AttackStart(m_creature->getVictim());
|
||||
Temp->AI()->AttackStart(m_creature->getVictim());
|
||||
DoZoneInCombat(Temp);
|
||||
}else
|
||||
EnterEvadeMode();
|
||||
|
||||
@@ -33,42 +33,50 @@ EndScriptData */
|
||||
#define SAY_TAUNT4 -1533007
|
||||
#define SAY_SLAY -1533008
|
||||
|
||||
#define SPELL_IMPALE 28783 //May be wrong spell id. Causes more dmg than I expect
|
||||
#define H_SPELL_IMPALE 56090
|
||||
#define SPELL_LOCUSTSWARM 28785 //This is a self buff that triggers the dmg debuff
|
||||
#define H_SPELL_LOCUSTSWARM 54021
|
||||
|
||||
//spellId invalid
|
||||
#define SPELL_SUMMONGUARD 29508 //Summons 1 crypt guard at targeted location
|
||||
#define SPELL_IMPALE HEROIC(28783,56090)
|
||||
#define SPELL_LOCUSTSWARM HEROIC(28785,54021)
|
||||
|
||||
#define SPELL_SELF_SPAWN_5 29105 //This spawns 5 corpse scarabs ontop of us (most likely the player casts this on death)
|
||||
#define SPELL_SELF_SPAWN_10 28864 //This is used by the crypt guards when they die
|
||||
|
||||
#define EVENT_IMPALE 1
|
||||
#define EVENT_LOCUST 2
|
||||
|
||||
#define MOB_CRYPT_GUARD 16573
|
||||
|
||||
struct TRINITY_DLL_DECL boss_anubrekhanAI : public ScriptedAI
|
||||
{
|
||||
boss_anubrekhanAI(Creature *c) : ScriptedAI(c) {}
|
||||
boss_anubrekhanAI(Creature *c) : ScriptedAI(c), summons(me) {}
|
||||
|
||||
uint32 Impale_Timer;
|
||||
uint32 LocustSwarm_Timer;
|
||||
uint32 Summon_Timer;
|
||||
bool HasTaunted;
|
||||
EventMap events;
|
||||
SummonList summons;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
Impale_Timer = 15000; //15 seconds
|
||||
LocustSwarm_Timer = 80000 + (rand()%40000); //Random time between 80 seconds and 2 minutes for initial cast
|
||||
Summon_Timer = LocustSwarm_Timer + 45000; //45 seconds after initial locust swarm
|
||||
events.Reset();
|
||||
summons.DespawnAll();
|
||||
HasTaunted = false;
|
||||
DoSpawnCreature(MOB_CRYPT_GUARD, 0, 10, 0, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000);
|
||||
if(HeroicMode)
|
||||
DoSpawnCreature(MOB_CRYPT_GUARD, 0, -10, 0, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* Victim)
|
||||
void JustSummoned(Creature *summon)
|
||||
{
|
||||
summons.Summon(summon);
|
||||
DoZoneInCombat(summon);
|
||||
}
|
||||
|
||||
void SummonedCreatureDespawn(Creature *summon) {summons.Despawn(summon);}
|
||||
|
||||
void KilledUnit(Unit* victim)
|
||||
{
|
||||
//Force the player to spawn corpse scarabs via spell
|
||||
Victim->CastSpell(Victim, SPELL_SELF_SPAWN_5, true);
|
||||
victim->CastSpell(victim, SPELL_SELF_SPAWN_5, true, NULL, NULL, me->GetGUID());
|
||||
|
||||
if (rand()%5)
|
||||
return;
|
||||
|
||||
DoScriptText(SAY_SLAY, m_creature);
|
||||
if(!(rand()%5))
|
||||
DoScriptText(SAY_SLAY, me);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit *who)
|
||||
@@ -79,62 +87,62 @@ struct TRINITY_DLL_DECL boss_anubrekhanAI : public ScriptedAI
|
||||
case 1: DoScriptText(SAY_AGGRO2, m_creature); break;
|
||||
case 2: DoScriptText(SAY_AGGRO3, m_creature); break;
|
||||
}
|
||||
|
||||
DoZoneInCombat();
|
||||
|
||||
events.ScheduleEvent(EVENT_IMPALE, 15000, 1);
|
||||
events.ScheduleEvent(EVENT_LOCUST, 80000 + rand()%40000, 1);
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit *who)
|
||||
{
|
||||
|
||||
if (!HasTaunted && m_creature->IsWithinDistInMap(who, 60.0f))
|
||||
if (!HasTaunted && m_creature->IsWithinDistInMap(who, 60.0f))
|
||||
{
|
||||
switch(rand()%5)
|
||||
{
|
||||
switch(rand()%5)
|
||||
{
|
||||
case 0: DoScriptText(SAY_GREET, m_creature); break;
|
||||
case 1: DoScriptText(SAY_TAUNT1, m_creature); break;
|
||||
case 2: DoScriptText(SAY_TAUNT2, m_creature); break;
|
||||
case 3: DoScriptText(SAY_TAUNT3, m_creature); break;
|
||||
case 4: DoScriptText(SAY_TAUNT4, m_creature); break;
|
||||
}
|
||||
HasTaunted = true;
|
||||
case 0: DoScriptText(SAY_GREET, m_creature); break;
|
||||
case 1: DoScriptText(SAY_TAUNT1, m_creature); break;
|
||||
case 2: DoScriptText(SAY_TAUNT2, m_creature); break;
|
||||
case 3: DoScriptText(SAY_TAUNT3, m_creature); break;
|
||||
case 4: DoScriptText(SAY_TAUNT4, m_creature); break;
|
||||
}
|
||||
HasTaunted = true;
|
||||
}
|
||||
ScriptedAI::MoveInLineOfSight(who);
|
||||
}
|
||||
|
||||
void UpdateAI(const uint32 diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
if(!UpdateVictim())
|
||||
return;
|
||||
|
||||
//Impale_Timer
|
||||
if (Impale_Timer < diff)
|
||||
events.Update(diff);
|
||||
|
||||
while(uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
//Cast Impale on a random target
|
||||
//Do NOT cast it when we are afflicted by locust swarm
|
||||
if (!m_creature->HasAura(SPELL_LOCUSTSWARM))
|
||||
switch(eventId)
|
||||
{
|
||||
if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0))
|
||||
DoCast(target,SPELL_IMPALE);
|
||||
case EVENT_IMPALE:
|
||||
//Cast Impale on a random target
|
||||
//Do NOT cast it when we are afflicted by locust swarm
|
||||
if(!me->HasAura(SPELL_LOCUSTSWARM))
|
||||
if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0))
|
||||
DoCast(target, SPELL_IMPALE);
|
||||
events.ScheduleEvent(EVENT_IMPALE, 15000, 1);
|
||||
events.DelayEvents(1500, 1);
|
||||
return;
|
||||
case EVENT_LOCUST:
|
||||
DoCast(m_creature, SPELL_LOCUSTSWARM);
|
||||
DoSpawnCreature(MOB_CRYPT_GUARD, 5, 5, 0, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000);
|
||||
events.ScheduleEvent(EVENT_LOCUST, 90000, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
Impale_Timer = 15000;
|
||||
}else Impale_Timer -= diff;
|
||||
|
||||
//LocustSwarm_Timer
|
||||
if (LocustSwarm_Timer < diff)
|
||||
{
|
||||
DoCast(m_creature, SPELL_LOCUSTSWARM);
|
||||
LocustSwarm_Timer = 90000;
|
||||
}else LocustSwarm_Timer -= diff;
|
||||
|
||||
//Summon_Timer
|
||||
if (Summon_Timer < diff)
|
||||
{
|
||||
DoCast(m_creature, SPELL_SUMMONGUARD);
|
||||
Summon_Timer = 45000;
|
||||
}else Summon_Timer -= diff;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI_boss_anubrekhan(Creature *_Creature)
|
||||
{
|
||||
return new boss_anubrekhanAI (_Creature);
|
||||
|
||||
@@ -29,3 +29,93 @@ Enrages 26527*/
|
||||
|
||||
#include "precompiled.h"
|
||||
|
||||
#define SPELL_BOMBARD_SLIME 28280
|
||||
|
||||
#define SPELL_POISON_CLOUD 28240
|
||||
#define SPELL_MUTATING_INJECTION 28169
|
||||
#define SPELL_SLIME_SPRAY HEROIC(28157,54364)
|
||||
#define SPELL_BERSERK 26662
|
||||
|
||||
#define EVENT_BERSERK 1
|
||||
#define EVENT_CLOUD 2
|
||||
#define EVENT_INJECT 3
|
||||
#define EVENT_SPRAY 4
|
||||
|
||||
#define MOB_FALLOUT_SLIME 16290
|
||||
|
||||
struct TRINITY_DLL_DECL boss_grobbulusAI : public ScriptedAI
|
||||
{
|
||||
boss_grobbulusAI(Creature *c) : ScriptedAI(c) {}
|
||||
|
||||
EventMap events;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
events.Reset();
|
||||
}
|
||||
|
||||
void EnterCombat(Unit *who)
|
||||
{
|
||||
DoZoneInCombat();
|
||||
events.ScheduleEvent(EVENT_CLOUD, 15000);
|
||||
events.ScheduleEvent(EVENT_INJECT, 20000);
|
||||
events.ScheduleEvent(EVENT_SPRAY, 15000+rand()%15000); //not sure
|
||||
events.ScheduleEvent(EVENT_BERSERK, 12*60000);
|
||||
}
|
||||
|
||||
void SpellHitTarget(Unit *target, const SpellEntry *spell)
|
||||
{
|
||||
if(spell->Id == SPELL_SLIME_SPRAY)
|
||||
{
|
||||
if(TempSummon *slime = me->SummonCreature(MOB_FALLOUT_SLIME, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0))
|
||||
DoZoneInCombat(slime);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(const uint32 diff)
|
||||
{
|
||||
if(!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
while(uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch(eventId)
|
||||
{
|
||||
case EVENT_CLOUD:
|
||||
DoCastAOE(SPELL_POISON_CLOUD);
|
||||
events.ScheduleEvent(EVENT_CLOUD, 15000);
|
||||
return;
|
||||
case EVENT_BERSERK:
|
||||
DoCastAOE(SPELL_BERSERK);
|
||||
return;
|
||||
case EVENT_SPRAY:
|
||||
DoCastAOE(SPELL_SLIME_SPRAY);
|
||||
events.ScheduleEvent(EVENT_SPRAY, 15000+rand()%15000);
|
||||
return;
|
||||
case EVENT_INJECT:
|
||||
if(Unit *target = SelectUnit(SELECT_TARGET_RANDOM, 0))
|
||||
DoCast(target, SPELL_MUTATING_INJECTION);
|
||||
events.ScheduleEvent(EVENT_INJECT, 8000 + 12000 * me->GetHealth() / me->GetMaxHealth());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI_boss_grobbulus(Creature *_Creature)
|
||||
{
|
||||
return new boss_grobbulusAI (_Creature);
|
||||
}
|
||||
|
||||
void AddSC_boss_grobbulus()
|
||||
{
|
||||
Script *newscript;
|
||||
newscript = new Script;
|
||||
newscript->Name="boss_grobbulus";
|
||||
newscript->GetAI = &GetAI_boss_grobbulus;
|
||||
newscript->RegisterSelf();
|
||||
}
|
||||
|
||||
@@ -31,113 +31,106 @@ EndScriptData */
|
||||
#define EMOTE_BERSERK -1533021
|
||||
#define EMOTE_ENRAGE -1533022
|
||||
|
||||
#define SPELL_HATEFULSTRIKE 28308
|
||||
#define H_SPELL_HATEFULSTRIKE 59192
|
||||
#define SPELL_ENRAGE 2813
|
||||
#define SPELL_HATEFULSTRIKE HEROIC(41926,59192)
|
||||
#define SPELL_FRENZY 28131
|
||||
#define SPELL_BERSERK 26662
|
||||
#define SPELL_SLIMEBOLT 32309
|
||||
|
||||
#define EVENT_BERSERK 1
|
||||
#define EVENT_HATEFUL 2
|
||||
#define EVENT_SLIME 3
|
||||
|
||||
struct TRINITY_DLL_DECL boss_patchwerkAI : public ScriptedAI
|
||||
{
|
||||
boss_patchwerkAI(Creature *c) : ScriptedAI(c) {}
|
||||
|
||||
uint32 HatefullStrike_Timer;
|
||||
uint32 Enrage_Timer;
|
||||
uint32 Slimebolt_Timer;
|
||||
bool Enraged;
|
||||
EventMap events;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
HatefullStrike_Timer = 1200; //1.2 seconds
|
||||
Enrage_Timer = 420000; //7 minutes 420,000
|
||||
Slimebolt_Timer = 450000; //7.5 minutes 450,000
|
||||
events.Reset();
|
||||
Enraged = false;
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* Victim)
|
||||
{
|
||||
if (rand()%5)
|
||||
return;
|
||||
|
||||
DoScriptText(SAY_SLAY, m_creature);
|
||||
if(!(rand()%5))
|
||||
DoScriptText(SAY_SLAY, me);
|
||||
}
|
||||
|
||||
void JustDied(Unit* Killer)
|
||||
{
|
||||
DoScriptText(SAY_DEATH, m_creature);
|
||||
DoScriptText(SAY_DEATH, me);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit *who)
|
||||
{
|
||||
if (rand()%2)
|
||||
{
|
||||
DoScriptText(SAY_AGGRO1, m_creature);
|
||||
}
|
||||
else
|
||||
{
|
||||
DoScriptText(SAY_AGGRO2, m_creature);
|
||||
}
|
||||
DoScriptText(rand()%2 ? SAY_AGGRO1 : SAY_AGGRO2, me);
|
||||
DoZoneInCombat();
|
||||
events.ScheduleEvent(EVENT_HATEFUL, 1200);
|
||||
events.ScheduleEvent(EVENT_BERSERK, 360000);
|
||||
}
|
||||
|
||||
void UpdateAI(const uint32 diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
if(!UpdateVictim())
|
||||
return;
|
||||
|
||||
//HatefullStrike_Timer
|
||||
if (HatefullStrike_Timer < diff)
|
||||
{
|
||||
//Cast Hateful strike on the player with the highest
|
||||
//amount of HP within melee distance
|
||||
uint32 MostHP = 0;
|
||||
Unit* pMostHPTarget = NULL;
|
||||
Unit* pTemp = NULL;
|
||||
std::list<HostilReference*>::iterator i = m_creature->getThreatManager().getThreatList().begin();
|
||||
events.Update(diff);
|
||||
|
||||
for (i = m_creature->getThreatManager().getThreatList().begin(); i!=m_creature->getThreatManager().getThreatList().end();)
|
||||
while(uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch(eventId)
|
||||
{
|
||||
pTemp = Unit::GetUnit((*m_creature),(*i)->getUnitGuid());
|
||||
++i;
|
||||
if (pTemp && pTemp->isAlive() && pTemp->GetHealth() > MostHP && m_creature->GetDistance2d(pTemp) < 5)
|
||||
case EVENT_HATEFUL:
|
||||
{
|
||||
MostHP = pTemp->GetHealth();
|
||||
pMostHPTarget = pTemp;
|
||||
//Cast Hateful strike on the player with the highest
|
||||
//amount of HP within melee distance
|
||||
uint32 MostHP = 0;
|
||||
Unit* pMostHPTarget = NULL;
|
||||
std::list<HostilReference*>::iterator i = m_creature->getThreatManager().getThreatList().begin();
|
||||
for(; i != m_creature->getThreatManager().getThreatList().end();)
|
||||
{
|
||||
Unit* pTemp = Unit::GetUnit(*m_creature, (*i)->getUnitGuid());
|
||||
++i;
|
||||
if (pTemp && pTemp->isAlive() && pTemp->GetHealth() > MostHP && m_creature->IsWithinMeleeRange(pTemp))
|
||||
{
|
||||
MostHP = pTemp->GetHealth();
|
||||
pMostHPTarget = pTemp;
|
||||
}
|
||||
}
|
||||
|
||||
if (pMostHPTarget)
|
||||
DoCast(pMostHPTarget, SPELL_HATEFULSTRIKE, true);
|
||||
|
||||
events.ScheduleEvent(EVENT_HATEFUL, 1200);
|
||||
return;
|
||||
}
|
||||
case EVENT_BERSERK:
|
||||
DoCast(m_creature, SPELL_BERSERK);
|
||||
DoScriptText(EMOTE_BERSERK, m_creature);
|
||||
events.ScheduleEvent(EVENT_SLIME, 2000);
|
||||
return;
|
||||
case EVENT_SLIME:
|
||||
DoCast(m_creature->getVictim(), SPELL_SLIMEBOLT);
|
||||
events.ScheduleEvent(EVENT_SLIME, 2000);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (pMostHPTarget)
|
||||
DoCast(pMostHPTarget, SPELL_HATEFULSTRIKE);
|
||||
|
||||
HatefullStrike_Timer = 1200;
|
||||
}else HatefullStrike_Timer -= diff;
|
||||
|
||||
//Enrage_Timer
|
||||
if (Enrage_Timer < diff)
|
||||
if(!Enraged && HealthBelowPct(5))
|
||||
{
|
||||
DoCast(m_creature, SPELL_BERSERK);
|
||||
DoScriptText(EMOTE_BERSERK, m_creature);
|
||||
|
||||
Enrage_Timer = 300000;
|
||||
}else Enrage_Timer -= diff;
|
||||
|
||||
//Slimebolt_Timer
|
||||
if (Slimebolt_Timer < diff)
|
||||
{
|
||||
DoCast(m_creature->getVictim(),SPELL_SLIMEBOLT);
|
||||
Slimebolt_Timer = 5000;
|
||||
}else Slimebolt_Timer -= diff;
|
||||
|
||||
//Enrage if not already enraged and below 5%
|
||||
if (!Enraged && (m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 5)
|
||||
{
|
||||
DoCast(m_creature,SPELL_ENRAGE);
|
||||
DoScriptText(EMOTE_ENRAGE,NULL);
|
||||
DoCast(m_creature, SPELL_FRENZY);
|
||||
DoScriptText(EMOTE_ENRAGE, NULL);
|
||||
Enraged = true;
|
||||
return;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI_boss_patchwerk(Creature *_Creature)
|
||||
{
|
||||
return new boss_patchwerkAI (_Creature);
|
||||
|
||||
@@ -71,7 +71,7 @@ void CreatureAI::OnCharmed(bool apply)
|
||||
me->IsAIEnabled = false;
|
||||
}
|
||||
|
||||
void CreatureAI::DoZoneInCombat(Unit* pUnit)
|
||||
void CreatureAI::DoZoneInCombat(Creature* pUnit)
|
||||
{
|
||||
if (!pUnit)
|
||||
pUnit = me;
|
||||
@@ -84,6 +84,10 @@ void CreatureAI::DoZoneInCombat(Unit* pUnit)
|
||||
return;
|
||||
}
|
||||
|
||||
if(!pUnit->getVictim())
|
||||
if(Unit *target = pUnit->SelectNearestTarget())
|
||||
AttackStart(target);
|
||||
|
||||
if (!pUnit->CanHaveThreatList() || pUnit->getThreatManager().isThreatListEmpty())
|
||||
{
|
||||
sLog.outError("DoZoneInCombat called for creature that either cannot have threat list or has empty threat list (pUnit entry = %d)", pUnit->GetTypeId() == TYPEID_UNIT ? ((Creature*)pUnit)->GetEntry() : 0);
|
||||
|
||||
@@ -94,7 +94,7 @@ class EventMap : private std::map<uint32, uint32>
|
||||
m_phase = (1 << (phase + 24));
|
||||
}
|
||||
|
||||
void ScheduleEvent(uint32 time, uint32 eventId, uint32 gcd = 0, uint32 phase = 0)
|
||||
void ScheduleEvent(uint32 eventId, uint32 time, uint32 gcd = 0, uint32 phase = 0)
|
||||
{
|
||||
time += m_time;
|
||||
if(gcd && gcd < 9)
|
||||
@@ -245,7 +245,7 @@ class TRINITY_DLL_SPEC CreatureAI : public UnitAI
|
||||
// Called at reaching home after evade
|
||||
virtual void JustReachedHome() {}
|
||||
|
||||
void DoZoneInCombat(Unit* pUnit = NULL);
|
||||
void DoZoneInCombat(Creature* pUnit = NULL);
|
||||
|
||||
// Called at text emote receive from player
|
||||
virtual void ReceiveEmote(Player* pPlayer, uint32 text_emote) {}
|
||||
|
||||
Reference in New Issue
Block a user