diff options
author | megamage <none@none> | 2009-04-29 00:15:18 -0500 |
---|---|---|
committer | megamage <none@none> | 2009-04-29 00:15:18 -0500 |
commit | ce68fc9c646e5a7b6ac7f33b12fa4296586b53e8 (patch) | |
tree | 933749fff97c6c8a15084ef6ec204896a054b39d | |
parent | 207c3f7afff6ee2b462bd6855487fbcbfdbd63a8 (diff) |
*Update some naxx boss scripts.
--HG--
branch : trunk
-rw-r--r-- | sql/updates/2955_world_scripts_naxx.sql | 7 | ||||
-rw-r--r-- | src/bindings/scripts/ScriptMgr.cpp | 2 | ||||
-rw-r--r-- | src/bindings/scripts/include/sc_creature.cpp | 5 | ||||
-rw-r--r-- | src/bindings/scripts/include/sc_creature.h | 8 | ||||
-rw-r--r-- | src/bindings/scripts/scripts/zone/black_temple/boss_supremus.cpp | 20 | ||||
-rw-r--r-- | src/bindings/scripts/scripts/zone/black_temple/boss_warlord_najentus.cpp | 16 | ||||
-rw-r--r-- | src/bindings/scripts/scripts/zone/karazhan/boss_moroes.cpp | 6 | ||||
-rw-r--r-- | src/bindings/scripts/scripts/zone/naxxramas/boss_anubrekhan.cpp | 120 | ||||
-rw-r--r-- | src/bindings/scripts/scripts/zone/naxxramas/boss_grobbulus.cpp | 90 | ||||
-rw-r--r-- | src/bindings/scripts/scripts/zone/naxxramas/boss_patchwerk.cpp | 121 | ||||
-rw-r--r-- | src/game/CreatureAI.cpp | 6 | ||||
-rw-r--r-- | src/game/CreatureAI.h | 4 |
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) {} |