aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormegamage <none@none>2009-04-29 00:15:18 -0500
committermegamage <none@none>2009-04-29 00:15:18 -0500
commitce68fc9c646e5a7b6ac7f33b12fa4296586b53e8 (patch)
tree933749fff97c6c8a15084ef6ec204896a054b39d
parent207c3f7afff6ee2b462bd6855487fbcbfdbd63a8 (diff)
*Update some naxx boss scripts.
--HG-- branch : trunk
-rw-r--r--sql/updates/2955_world_scripts_naxx.sql7
-rw-r--r--src/bindings/scripts/ScriptMgr.cpp2
-rw-r--r--src/bindings/scripts/include/sc_creature.cpp5
-rw-r--r--src/bindings/scripts/include/sc_creature.h8
-rw-r--r--src/bindings/scripts/scripts/zone/black_temple/boss_supremus.cpp20
-rw-r--r--src/bindings/scripts/scripts/zone/black_temple/boss_warlord_najentus.cpp16
-rw-r--r--src/bindings/scripts/scripts/zone/karazhan/boss_moroes.cpp6
-rw-r--r--src/bindings/scripts/scripts/zone/naxxramas/boss_anubrekhan.cpp120
-rw-r--r--src/bindings/scripts/scripts/zone/naxxramas/boss_grobbulus.cpp90
-rw-r--r--src/bindings/scripts/scripts/zone/naxxramas/boss_patchwerk.cpp121
-rw-r--r--src/game/CreatureAI.cpp6
-rw-r--r--src/game/CreatureAI.h4
12 files changed, 260 insertions, 145 deletions
diff --git a/sql/updates/2955_world_scripts_naxx.sql b/sql/updates/2955_world_scripts_naxx.sql
new file mode 100644
index 00000000000..ae3f9324752
--- /dev/null
+++ b/sql/updates/2955_world_scripts_naxx.sql
@@ -0,0 +1,7 @@
+INSERT INTO `spell_linked_spell` (`spell_trigger`, `spell_effect`, `type`, `comment`) VALUES
+(-28169, 28206, 0, 'Mutating Injection - Mutagen Explosion'),
+(-28169, 28240, 0, 'Mutating Injection - Poison Cloud');
+
+UPDATE creature_template SET spell1 = 28158, spell2 = 54362, flags_extra = 128 WHERE entry = 16363;
+
+UPDATE creature_template SET scriptname = 'boss_grobbulus' WHERE entry = 15931; \ No newline at end of file
diff --git a/src/bindings/scripts/ScriptMgr.cpp b/src/bindings/scripts/ScriptMgr.cpp
index d2a2c07706c..bf80865f0bc 100644
--- a/src/bindings/scripts/ScriptMgr.cpp
+++ b/src/bindings/scripts/ScriptMgr.cpp
@@ -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();
diff --git a/src/bindings/scripts/include/sc_creature.cpp b/src/bindings/scripts/include/sc_creature.cpp
index fde0f92f1c9..fed04c5303c 100644
--- a/src/bindings/scripts/include/sc_creature.cpp
+++ b/src/bindings/scripts/include/sc_creature.cpp
@@ -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)
diff --git a/src/bindings/scripts/include/sc_creature.h b/src/bindings/scripts/include/sc_creature.h
index 880cdffc504..dfdb23eeb14 100644
--- a/src/bindings/scripts/include/sc_creature.h
+++ b/src/bindings/scripts/include/sc_creature.h
@@ -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);
diff --git a/src/bindings/scripts/scripts/zone/black_temple/boss_supremus.cpp b/src/bindings/scripts/scripts/zone/black_temple/boss_supremus.cpp
index e9a23476543..a479b7c162b 100644
--- a/src/bindings/scripts/scripts/zone/black_temple/boss_supremus.cpp
+++ b/src/bindings/scripts/scripts/zone/black_temple/boss_supremus.cpp
@@ -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:
diff --git a/src/bindings/scripts/scripts/zone/black_temple/boss_warlord_najentus.cpp b/src/bindings/scripts/scripts/zone/black_temple/boss_warlord_najentus.cpp
index adf8011d989..7d6b7140a9d 100644
--- a/src/bindings/scripts/scripts/zone/black_temple/boss_warlord_najentus.cpp
+++ b/src/bindings/scripts/scripts/zone/black_temple/boss_warlord_najentus.cpp
@@ -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;
}
diff --git a/src/bindings/scripts/scripts/zone/karazhan/boss_moroes.cpp b/src/bindings/scripts/scripts/zone/karazhan/boss_moroes.cpp
index 988b0883754..a96b2043df6 100644
--- a/src/bindings/scripts/scripts/zone/karazhan/boss_moroes.cpp
+++ b/src/bindings/scripts/scripts/zone/karazhan/boss_moroes.cpp
@@ -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();
diff --git a/src/bindings/scripts/scripts/zone/naxxramas/boss_anubrekhan.cpp b/src/bindings/scripts/scripts/zone/naxxramas/boss_anubrekhan.cpp
index afc0957fc43..c0b23faa889 100644
--- a/src/bindings/scripts/scripts/zone/naxxramas/boss_anubrekhan.cpp
+++ b/src/bindings/scripts/scripts/zone/naxxramas/boss_anubrekhan.cpp
@@ -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)
{
- //Force the player to spawn corpse scarabs via spell
- Victim->CastSpell(Victim, SPELL_SELF_SPAWN_5, true);
+ summons.Summon(summon);
+ DoZoneInCombat(summon);
+ }
- if (rand()%5)
- return;
+ void SummonedCreatureDespawn(Creature *summon) {summons.Despawn(summon);}
- DoScriptText(SAY_SLAY, m_creature);
+ void KilledUnit(Unit* victim)
+ {
+ //Force the player to spawn corpse scarabs via spell
+ victim->CastSpell(victim, SPELL_SELF_SPAWN_5, true, NULL, NULL, me->GetGUID());
+
+ 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);
diff --git a/src/bindings/scripts/scripts/zone/naxxramas/boss_grobbulus.cpp b/src/bindings/scripts/scripts/zone/naxxramas/boss_grobbulus.cpp
index e0bf157dc43..98ab76e4fc0 100644
--- a/src/bindings/scripts/scripts/zone/naxxramas/boss_grobbulus.cpp
+++ b/src/bindings/scripts/scripts/zone/naxxramas/boss_grobbulus.cpp
@@ -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();
+}
diff --git a/src/bindings/scripts/scripts/zone/naxxramas/boss_patchwerk.cpp b/src/bindings/scripts/scripts/zone/naxxramas/boss_patchwerk.cpp
index edbfd760b9e..ac8fa5ba568 100644
--- a/src/bindings/scripts/scripts/zone/naxxramas/boss_patchwerk.cpp
+++ b/src/bindings/scripts/scripts/zone/naxxramas/boss_patchwerk.cpp
@@ -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)
+ events.Update(diff);
+
+ while(uint32 eventId = events.ExecuteEvent())
{
- //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();
-
- for (i = m_creature->getThreatManager().getThreatList().begin(); i!=m_creature->getThreatManager().getThreatList().end();)
+ 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)
- {
- 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)
+ if(!Enraged && HealthBelowPct(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);
diff --git a/src/game/CreatureAI.cpp b/src/game/CreatureAI.cpp
index 59df2e866f2..4668578c1be 100644
--- a/src/game/CreatureAI.cpp
+++ b/src/game/CreatureAI.cpp
@@ -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);
diff --git a/src/game/CreatureAI.h b/src/game/CreatureAI.h
index d83a9eb2cd8..cae7026f6c7 100644
--- a/src/game/CreatureAI.h
+++ b/src/game/CreatureAI.h
@@ -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) {}