mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-27 15:46:24 +00:00
fix(Scripts/MoltenCore): rewrite (#8741)
This commit is contained in:
@@ -15,36 +15,31 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* ScriptData
|
||||
SDName: Boss_Baron_Geddon
|
||||
SD%Complete: 100
|
||||
SDComment:
|
||||
SDCategory: Molten Core
|
||||
EndScriptData */
|
||||
|
||||
#include "molten_core.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "molten_core.h"
|
||||
#include "SpellAuraEffects.h"
|
||||
#include "SpellScript.h"
|
||||
|
||||
enum Emotes
|
||||
{
|
||||
EMOTE_SERVICE = 0
|
||||
EMOTE_SERVICE = 0
|
||||
};
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_INFERNO = 19695,
|
||||
SPELL_IGNITE_MANA = 19659,
|
||||
SPELL_LIVING_BOMB = 20475,
|
||||
SPELL_ARMAGEDDON = 20479,
|
||||
SPELL_INFERNO = 19695,
|
||||
SPELL_INFERNO_DUMMY_EFFECT = 19698, // Server side spell which inflicts damage
|
||||
SPELL_IGNITE_MANA = 19659,
|
||||
SPELL_LIVING_BOMB = 20475,
|
||||
SPELL_ARMAGEDDON = 20478,
|
||||
};
|
||||
|
||||
enum Events
|
||||
{
|
||||
EVENT_INFERNO = 1,
|
||||
EVENT_IGNITE_MANA = 2,
|
||||
EVENT_LIVING_BOMB = 3,
|
||||
EVENT_INFERNO = 1,
|
||||
EVENT_IGNITE_MANA,
|
||||
EVENT_LIVING_BOMB,
|
||||
};
|
||||
|
||||
class boss_baron_geddon : public CreatureScript
|
||||
@@ -54,62 +49,75 @@ public:
|
||||
|
||||
struct boss_baron_geddonAI : public BossAI
|
||||
{
|
||||
boss_baron_geddonAI(Creature* creature) : BossAI(creature, BOSS_BARON_GEDDON)
|
||||
boss_baron_geddonAI(Creature* creature) : BossAI(creature, DATA_GEDDON),
|
||||
armageddonCasted(false)
|
||||
{
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* victim) override
|
||||
void Reset() override
|
||||
{
|
||||
BossAI::EnterCombat(victim);
|
||||
events.ScheduleEvent(EVENT_INFERNO, 45000);
|
||||
events.ScheduleEvent(EVENT_IGNITE_MANA, 30000);
|
||||
events.ScheduleEvent(EVENT_LIVING_BOMB, 35000);
|
||||
_Reset();
|
||||
armageddonCasted = false;
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
void EnterCombat(Unit* /*attacker*/) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
_EnterCombat();
|
||||
events.ScheduleEvent(EVENT_INFERNO, urand(13000, 15000));
|
||||
events.ScheduleEvent(EVENT_IGNITE_MANA, urand(7000, 19000));
|
||||
events.ScheduleEvent(EVENT_LIVING_BOMB, urand(11000, 16000));
|
||||
}
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
// If we are <2% hp cast Armageddon
|
||||
if (!HealthAbovePct(2))
|
||||
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*dmgType*/, SpellSchoolMask /*school*/) override
|
||||
{
|
||||
// If boss is below 2% hp - cast Armageddon
|
||||
if (!armageddonCasted && damage < me->GetHealth() && me->HealthBelowPctDamaged(2, damage))
|
||||
{
|
||||
me->InterruptNonMeleeSpells(true);
|
||||
DoCast(me, SPELL_ARMAGEDDON);
|
||||
Talk(EMOTE_SERVICE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
if (me->CastSpell(me, SPELL_ARMAGEDDON) == SPELL_CAST_OK)
|
||||
{
|
||||
case EVENT_INFERNO:
|
||||
DoCast(me, SPELL_INFERNO);
|
||||
events.ScheduleEvent(EVENT_INFERNO, 45000);
|
||||
break;
|
||||
case EVENT_IGNITE_MANA:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_IGNITE_MANA))
|
||||
DoCast(target, SPELL_IGNITE_MANA);
|
||||
events.ScheduleEvent(EVENT_IGNITE_MANA, 30000);
|
||||
break;
|
||||
case EVENT_LIVING_BOMB:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
|
||||
DoCast(target, SPELL_LIVING_BOMB);
|
||||
events.ScheduleEvent(EVENT_LIVING_BOMB, 35000);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
Talk(EMOTE_SERVICE);
|
||||
}
|
||||
|
||||
armageddonCasted = true;
|
||||
}
|
||||
}
|
||||
|
||||
void ExecuteEvent(uint32 eventId) override
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_INFERNO:
|
||||
{
|
||||
DoCastSelf(SPELL_INFERNO);
|
||||
events.RepeatEvent(urand(21000, 26000));
|
||||
break;
|
||||
}
|
||||
case EVENT_IGNITE_MANA:
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_IGNITE_MANA))
|
||||
{
|
||||
DoCast(target, SPELL_IGNITE_MANA);
|
||||
}
|
||||
|
||||
events.RepeatEvent(urand(27000, 32000));
|
||||
break;
|
||||
}
|
||||
case EVENT_LIVING_BOMB:
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
|
||||
{
|
||||
DoCast(target, SPELL_LIVING_BOMB);
|
||||
}
|
||||
|
||||
events.RepeatEvent(urand(11000, 16000));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
bool armageddonCasted;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
@@ -118,7 +126,68 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
// 19695 Inferno
|
||||
class spell_geddon_inferno : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_geddon_inferno() : SpellScriptLoader("spell_geddon_inferno") { }
|
||||
|
||||
class spell_geddon_inferno_AuraScript : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_geddon_inferno_AuraScript);
|
||||
|
||||
bool Validate(SpellInfo const* /*spell*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_INFERNO_DUMMY_EFFECT });
|
||||
}
|
||||
|
||||
void PeriodicTick(AuraEffect const* aurEff)
|
||||
{
|
||||
PreventDefaultAction();
|
||||
|
||||
if (Unit* caster = GetUnitOwner())
|
||||
{
|
||||
//The pulses come about 1 second apart and last for 10 seconds. Damage starts at 500 damage per pulse and increases by 500 every other pulse (500, 500, 1000, 1000, 1500, etc.). (Source: Wowwiki)
|
||||
int32 multiplier = 1;
|
||||
switch (aurEff->GetTickNumber())
|
||||
{
|
||||
case 2:
|
||||
case 3:
|
||||
multiplier = 2;
|
||||
break;
|
||||
case 4:
|
||||
case 5:
|
||||
multiplier = 3;
|
||||
break;
|
||||
case 6:
|
||||
case 7:
|
||||
multiplier = 4;
|
||||
break;
|
||||
case 8:
|
||||
multiplier = 5;
|
||||
break;
|
||||
}
|
||||
|
||||
caster->CastCustomSpell(SPELL_INFERNO_DUMMY_EFFECT, SPELLVALUE_BASE_POINT0, 500 * multiplier, caster, TRIGGERED_NONE, nullptr, aurEff);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_geddon_inferno_AuraScript::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
{
|
||||
return new spell_geddon_inferno_AuraScript();
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_baron_geddon()
|
||||
{
|
||||
new boss_baron_geddon();
|
||||
|
||||
// Spells
|
||||
new spell_geddon_inferno();
|
||||
}
|
||||
|
||||
@@ -15,83 +15,124 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* ScriptData
|
||||
SDName: Boss_Garr
|
||||
SD%Complete: 50
|
||||
SDComment: Adds NYI
|
||||
SDCategory: Molten Core
|
||||
EndScriptData */
|
||||
|
||||
#include "molten_core.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "Containers.h"
|
||||
#include "ObjectAccessor.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellAuras.h"
|
||||
#include "SpellInfo.h"
|
||||
#include "SpellScript.h"
|
||||
#include "molten_core.h"
|
||||
|
||||
enum Texts
|
||||
{
|
||||
EMOTE_MASS_ERRUPTION = 0,
|
||||
};
|
||||
|
||||
enum Spells
|
||||
{
|
||||
// Garr
|
||||
SPELL_ANTIMAGIC_PULSE = 19492,
|
||||
SPELL_MAGMA_SHACKLES = 19496,
|
||||
SPELL_ENRAGE = 19516,
|
||||
SPELL_ANTIMAGIC_PULSE = 19492, // Dispels magic on nearby enemies, removing 1 beneficial spell
|
||||
SPELL_MAGMA_SHACKLES = 19496, // Reduces the movement speed of nearby enemies by 60%
|
||||
SPELL_SEPARATION_ANXIETY = 23487, // Aura cast on himself by Garr, if adds move out of range, they will cast spell 23492 on themselves (server side)
|
||||
SPELL_FRENZY = 19516, // Increases the caster's attack speed by 9 + scale. Stacks up to 10 times
|
||||
|
||||
// Adds
|
||||
SPELL_ERUPTION = 19497,
|
||||
SPELL_IMMOLATE = 20294,
|
||||
// Fireworn
|
||||
SPELL_SEPARATION_ANXIETY_MINION = 23492, // Increases damage done by 300% and applied banish immunity
|
||||
SPELL_ERUPTION = 19497, // Deals fire aoe damage and knockbacks nearby enemies
|
||||
SPELL_MASSIVE_ERUPTION = 20483, // Deals fire aoe damage, knockbacks nearby enemies and kills caster
|
||||
SPELL_ERUPTION_TRIGGER = 20482, // Removes banish auras and applied immunity to banish (server side)
|
||||
SPELL_ENRAGE_TRIGGER = 19515, // Server side. Triggers 19516 on hit
|
||||
};
|
||||
|
||||
enum Events
|
||||
{
|
||||
EVENT_ANTIMAGIC_PULSE = 1,
|
||||
EVENT_MAGMA_SHACKLES = 2,
|
||||
EVENT_ANTIMAGIC_PULSE = 1,
|
||||
EVENT_MAGMA_SHACKLES,
|
||||
};
|
||||
|
||||
class boss_garr : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_garr() : CreatureScript("boss_garr") { }
|
||||
boss_garr() : CreatureScript("boss_garr") {}
|
||||
|
||||
struct boss_garrAI : public BossAI
|
||||
{
|
||||
boss_garrAI(Creature* creature) : BossAI(creature, BOSS_GARR)
|
||||
boss_garrAI(Creature* creature) : BossAI(creature, DATA_GARR),
|
||||
massEruptionTimer(600000) // 10 mins
|
||||
{
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* victim) override
|
||||
void Reset() override
|
||||
{
|
||||
BossAI::EnterCombat(victim);
|
||||
_Reset();
|
||||
massEruptionTimer = 600000;
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*attacker*/) override
|
||||
{
|
||||
_EnterCombat();
|
||||
DoCastSelf(SPELL_SEPARATION_ANXIETY, true);
|
||||
events.ScheduleEvent(EVENT_ANTIMAGIC_PULSE, 15000);
|
||||
events.ScheduleEvent(EVENT_MAGMA_SHACKLES, 10000);
|
||||
massEruptionTimer = 600000; // 10 mins
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// This should always process
|
||||
if (massEruptionTimer <= diff)
|
||||
{
|
||||
Talk(EMOTE_MASS_ERRUPTION, me);
|
||||
DoCastAOE(SPELL_ERUPTION_TRIGGER, true);
|
||||
massEruptionTimer = 20000;
|
||||
}
|
||||
else
|
||||
{
|
||||
massEruptionTimer -= diff;
|
||||
}
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
while (uint32 const eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_ANTIMAGIC_PULSE:
|
||||
DoCast(me, SPELL_ANTIMAGIC_PULSE);
|
||||
events.ScheduleEvent(EVENT_ANTIMAGIC_PULSE, 20000);
|
||||
{
|
||||
DoCastSelf(SPELL_ANTIMAGIC_PULSE);
|
||||
events.RepeatEvent(20000);
|
||||
break;
|
||||
}
|
||||
case EVENT_MAGMA_SHACKLES:
|
||||
DoCast(me, SPELL_MAGMA_SHACKLES);
|
||||
events.ScheduleEvent(EVENT_MAGMA_SHACKLES, 15000);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
DoCastSelf(SPELL_MAGMA_SHACKLES);
|
||||
events.RepeatEvent(15000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
uint32 massEruptionTimer;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
@@ -100,60 +141,115 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class npc_firesworn : public CreatureScript
|
||||
class npc_garr_firesworn : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_firesworn() : CreatureScript("npc_firesworn") { }
|
||||
npc_garr_firesworn() : CreatureScript("npc_garr_firesworn") {}
|
||||
|
||||
struct npc_fireswornAI : public ScriptedAI
|
||||
struct npc_garr_fireswornAI : public ScriptedAI
|
||||
{
|
||||
npc_fireswornAI(Creature* creature) : ScriptedAI(creature) { }
|
||||
npc_garr_fireswornAI(Creature* creature) : ScriptedAI(creature) {}
|
||||
|
||||
uint32 immolateTimer;
|
||||
|
||||
void Reset() override
|
||||
void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/ ) override
|
||||
{
|
||||
immolateTimer = 4000; //These times are probably wrong
|
||||
}
|
||||
|
||||
void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
||||
{
|
||||
uint32 const health10pct = me->CountPctFromMaxHealth(10);
|
||||
uint32 health = me->GetHealth();
|
||||
if (int32(health) - int32(damage) < int32(health10pct))
|
||||
if (damage >= me->GetHealth())
|
||||
{
|
||||
damage = 0;
|
||||
DoCastVictim(SPELL_ERUPTION);
|
||||
me->DespawnOrUnsummon();
|
||||
// Prevent double damage because Firesworn can kill himself with Massive Erruption
|
||||
if (me != attacker)
|
||||
{
|
||||
DoCastSelf(SPELL_ERUPTION, true);
|
||||
}
|
||||
|
||||
DoCastAOE(SPELL_ENRAGE_TRIGGER);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (immolateTimer <= diff)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
|
||||
DoCast(target, SPELL_IMMOLATE);
|
||||
immolateTimer = urand(5000, 10000);
|
||||
}
|
||||
else
|
||||
immolateTimer -= diff;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetMoltenCoreAI<npc_fireswornAI>(creature);
|
||||
return GetMoltenCoreAI<npc_garr_fireswornAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
// 23487 Separation Anxiety (server side)
|
||||
class spell_garr_separation_nexiety : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_garr_separation_nexiety() : SpellScriptLoader("spell_garr_separation_nexiety") {}
|
||||
|
||||
class spell_garr_separation_nexiety_AuraScript : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_garr_separation_nexiety_AuraScript);
|
||||
|
||||
bool Validate(SpellInfo const* /*spell*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_SEPARATION_ANXIETY_MINION });
|
||||
}
|
||||
|
||||
void HandlePeriodic(AuraEffect const* aurEff)
|
||||
{
|
||||
Unit const* caster = GetCaster();
|
||||
Unit* target = GetTarget();
|
||||
if (caster && target && target->GetDistance(caster) > 40.0f && !target->HasAura(SPELL_SEPARATION_ANXIETY_MINION))
|
||||
{
|
||||
target->CastSpell(target, SPELL_SEPARATION_ANXIETY_MINION, true, nullptr, aurEff);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_garr_separation_nexiety_AuraScript::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
// Should return a fully valid AuraScript pointer.
|
||||
AuraScript* GetAuraScript() const override
|
||||
{
|
||||
return new spell_garr_separation_nexiety_AuraScript();
|
||||
}
|
||||
};
|
||||
|
||||
//19515 Frenzy (SERVERSIDE)
|
||||
class spell_garr_frenzy : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_garr_frenzy() : SpellScriptLoader("spell_garr_frenzy") {}
|
||||
|
||||
class spell_garr_frenzy_SpellScript : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_garr_frenzy_SpellScript);
|
||||
|
||||
bool Validate(SpellInfo const* /*spell*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_FRENZY });
|
||||
}
|
||||
|
||||
void HandleHit(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (Unit* target = GetHitUnit())
|
||||
{
|
||||
target->CastSpell(target, SPELL_FRENZY);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_garr_frenzy_SpellScript::HandleHit, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
{
|
||||
return new spell_garr_frenzy_SpellScript();
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_garr()
|
||||
{
|
||||
new boss_garr();
|
||||
new npc_firesworn();
|
||||
new npc_garr_firesworn();
|
||||
|
||||
// Spells
|
||||
new spell_garr_separation_nexiety();
|
||||
new spell_garr_frenzy();
|
||||
}
|
||||
|
||||
@@ -15,13 +15,6 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* ScriptData
|
||||
SDName: Boss_Gehennas
|
||||
SD%Complete: 90
|
||||
SDComment: Adds MC NYI
|
||||
SDCategory: Molten Core
|
||||
EndScriptData */
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "molten_core.h"
|
||||
@@ -48,9 +41,7 @@ public:
|
||||
|
||||
struct boss_gehennasAI : public BossAI
|
||||
{
|
||||
boss_gehennasAI(Creature* creature) : BossAI(creature, BOSS_GEHENNAS)
|
||||
{
|
||||
}
|
||||
boss_gehennasAI(Creature* creature) : BossAI(creature, DATA_GEHENNAS) {}
|
||||
|
||||
void EnterCombat(Unit* /*attacker*/) override
|
||||
{
|
||||
@@ -60,69 +51,47 @@ public:
|
||||
events.ScheduleEvent(EVENT_SHADOW_BOLT, urand(3000, 5000));
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
void ExecuteEvent(uint32 eventId) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
switch (eventId)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (uint32 const eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
case EVENT_GEHENNAS_CURSE:
|
||||
{
|
||||
case EVENT_GEHENNAS_CURSE:
|
||||
DoCastVictim(SPELL_GEHENNAS_CURSE);
|
||||
events.RepeatEvent(urand(25000, 30000));
|
||||
break;
|
||||
}
|
||||
case EVENT_RAIN_OF_FIRE:
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
|
||||
{
|
||||
DoCastVictim(SPELL_GEHENNAS_CURSE);
|
||||
events.RepeatEvent(urand(25000, 30000));
|
||||
break;
|
||||
DoCast(target, SPELL_RAIN_OF_FIRE, true);
|
||||
}
|
||||
case EVENT_RAIN_OF_FIRE:
|
||||
events.RepeatEvent(6000);
|
||||
break;
|
||||
}
|
||||
case EVENT_SHADOW_BOLT:
|
||||
{
|
||||
if (urand(0, 1))
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true))
|
||||
{
|
||||
DoCast(target, SPELL_RAIN_OF_FIRE);
|
||||
}
|
||||
events.RepeatEvent(6000);
|
||||
break;
|
||||
}
|
||||
case EVENT_SHADOW_BOLT:
|
||||
{
|
||||
if (urand(0, 1))
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true))
|
||||
{
|
||||
DoCast(target, SPELL_SHADOW_BOLT_RANDOM);
|
||||
}
|
||||
else
|
||||
{
|
||||
DoCastVictim(SPELL_SHADOW_BOLT_VICTIM);
|
||||
}
|
||||
DoCast(target, SPELL_SHADOW_BOLT_RANDOM);
|
||||
}
|
||||
else
|
||||
{
|
||||
DoCastVictim(SPELL_SHADOW_BOLT_VICTIM);
|
||||
}
|
||||
|
||||
events.RepeatEvent(5000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DoCastVictim(SPELL_SHADOW_BOLT_VICTIM);
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
events.RepeatEvent(5000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -15,40 +15,28 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* ScriptData
|
||||
SDName: Boss_Golemagg
|
||||
SD%Complete: 90
|
||||
SDComment: Timers need to be confirmed, Golemagg's Trust need to be checked
|
||||
SDCategory: Molten Core
|
||||
EndScriptData */
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "molten_core.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ObjectAccessor.h"
|
||||
|
||||
enum Texts
|
||||
{
|
||||
EMOTE_LOWHP = 0,
|
||||
EMOTE_LOWHP = 0,
|
||||
};
|
||||
|
||||
enum Spells
|
||||
{
|
||||
// Golemagg
|
||||
SPELL_MAGMASPLASH = 13879,
|
||||
SPELL_PYROBLAST = 20228,
|
||||
SPELL_EARTHQUAKE = 19798,
|
||||
SPELL_ENRAGE = 19953,
|
||||
SPELL_GOLEMAGG_TRUST = 20553,
|
||||
SPELL_PYROBLAST = 20228,
|
||||
SPELL_EARTHQUAKE = 19798,
|
||||
SPELL_ENRAGE = 19953,
|
||||
SPELL_ATTRACK_RAGER = 20544,
|
||||
|
||||
// Core Rager
|
||||
SPELL_MANGLE = 19820
|
||||
};
|
||||
|
||||
enum Events
|
||||
{
|
||||
EVENT_PYROBLAST = 1,
|
||||
EVENT_EARTHQUAKE = 2,
|
||||
SPELL_MANGLE = 19820,
|
||||
SPELL_FULL_HEAL = 17683,
|
||||
};
|
||||
|
||||
class boss_golemagg : public CreatureScript
|
||||
@@ -58,72 +46,79 @@ public:
|
||||
|
||||
struct boss_golemaggAI : public BossAI
|
||||
{
|
||||
boss_golemaggAI(Creature* creature) : BossAI(creature, BOSS_GOLEMAGG_THE_INCINERATOR)
|
||||
{
|
||||
}
|
||||
boss_golemaggAI(Creature* creature) : BossAI(creature, DATA_GOLEMAGG),
|
||||
earthquakeTimer(0),
|
||||
pyroblastTimer(0),
|
||||
enraged(false)
|
||||
{}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
BossAI::Reset();
|
||||
DoCast(me, SPELL_MAGMASPLASH, true);
|
||||
_Reset();
|
||||
earthquakeTimer = 0;
|
||||
pyroblastTimer = urand(3000, 7000);
|
||||
enraged = false;
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* victim) override
|
||||
void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
||||
{
|
||||
BossAI::EnterCombat(victim);
|
||||
events.ScheduleEvent(EVENT_PYROBLAST, 7000);
|
||||
|
||||
// The two ragers should join the fight alongside me against my foes.
|
||||
std::list<Creature*> ragers;
|
||||
me->GetCreaturesWithEntryInRange(ragers, 100, NPC_CORE_RAGER);
|
||||
for (Creature* i : ragers)
|
||||
if (!enraged && me->HealthBelowPctDamaged(10, damage))
|
||||
{
|
||||
if (i && i->IsAlive() && !i->IsInCombat())
|
||||
{
|
||||
i->AI()->AttackStart(victim);
|
||||
}
|
||||
DoCastSelf(SPELL_ENRAGE, true);
|
||||
DoCastSelf(SPELL_ATTRACK_RAGER, true);
|
||||
DoCastAOE(SPELL_EARTHQUAKE, true);
|
||||
earthquakeTimer = 5000;
|
||||
enraged = true;
|
||||
}
|
||||
}
|
||||
|
||||
void DamageTaken(Unit*, uint32& /*damage*/, DamageEffectType, SpellSchoolMask) override
|
||||
{
|
||||
if (!HealthBelowPct(10) || me->HasAura(SPELL_ENRAGE))
|
||||
return;
|
||||
|
||||
DoCast(me, SPELL_ENRAGE, true);
|
||||
events.ScheduleEvent(EVENT_EARTHQUAKE, 3000);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
events.Update(diff);
|
||||
// Should not get impact by cast state (cast should always happen)
|
||||
if (earthquakeTimer)
|
||||
{
|
||||
if (earthquakeTimer <= diff)
|
||||
{
|
||||
DoCastAOE(SPELL_EARTHQUAKE, true);
|
||||
earthquakeTimer = 5000;
|
||||
}
|
||||
else
|
||||
{
|
||||
earthquakeTimer -= diff;
|
||||
}
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
return;
|
||||
}
|
||||
|
||||
if (pyroblastTimer <= diff)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
|
||||
{
|
||||
case EVENT_PYROBLAST:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
|
||||
DoCast(target, SPELL_PYROBLAST);
|
||||
events.ScheduleEvent(EVENT_PYROBLAST, 7000);
|
||||
break;
|
||||
case EVENT_EARTHQUAKE:
|
||||
DoCastVictim(SPELL_EARTHQUAKE);
|
||||
events.ScheduleEvent(EVENT_EARTHQUAKE, 3000);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
DoCast(target, SPELL_PYROBLAST);
|
||||
}
|
||||
|
||||
pyroblastTimer = 7000;
|
||||
}
|
||||
else
|
||||
{
|
||||
pyroblastTimer -= diff;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
uint32 earthquakeTimer;
|
||||
uint32 pyroblastTimer;
|
||||
bool enraged;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
@@ -139,45 +134,79 @@ public:
|
||||
|
||||
struct npc_core_ragerAI : public ScriptedAI
|
||||
{
|
||||
npc_core_ragerAI(Creature* creature) : ScriptedAI(creature)
|
||||
npc_core_ragerAI(Creature* creature) : ScriptedAI(creature),
|
||||
instance(creature->GetInstanceScript()),
|
||||
mangleTimer(7000),
|
||||
rangeCheckTimer(1000)
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
mangleTimer = 7 * IN_MILLISECONDS; // These times are probably wrong
|
||||
mangleTimer = 7000; // These times are probably wrong
|
||||
rangeCheckTimer = 1000;
|
||||
|
||||
if (instance->GetBossState(DATA_GOLEMAGG) == DONE)
|
||||
{
|
||||
DoCastSelf(SPELL_CORE_RAGER_QUIET_SUICIDE, true);
|
||||
}
|
||||
}
|
||||
|
||||
void DamageTaken(Unit*, uint32& /*damage*/, DamageEffectType, SpellSchoolMask) override
|
||||
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*dmgType*/, SpellSchoolMask /*school*/) override
|
||||
{
|
||||
if (HealthAbovePct(50) || !instance)
|
||||
return;
|
||||
|
||||
if (Creature* pGolemagg = instance->instance->GetCreature(instance->GetGuidData(BOSS_GOLEMAGG_THE_INCINERATOR)))
|
||||
// Just in case if something will go bad, let players to kill this creature
|
||||
if (instance->GetBossState(DATA_GOLEMAGG) == DONE)
|
||||
{
|
||||
if (pGolemagg->IsAlive())
|
||||
{
|
||||
me->AddAura(SPELL_GOLEMAGG_TRUST, me);
|
||||
Talk(EMOTE_LOWHP);
|
||||
me->SetFullHealth();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (me->HealthBelowPctDamaged(50, damage))
|
||||
{
|
||||
damage = 0;
|
||||
DoCastSelf(SPELL_FULL_HEAL, true);
|
||||
Talk(EMOTE_LOWHP);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Should have no impact from unit state
|
||||
if (rangeCheckTimer <= diff)
|
||||
{
|
||||
Creature const* golemagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_GEDDON));
|
||||
if (golemagg && me->GetDistance(golemagg) > 100.0f)
|
||||
{
|
||||
instance->DoAction(ACTION_RESET_MAGMADAR_ENCOUNTER);
|
||||
return;
|
||||
}
|
||||
|
||||
rangeCheckTimer = 1000;
|
||||
}
|
||||
else
|
||||
{
|
||||
rangeCheckTimer -= diff;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Mangle
|
||||
if (mangleTimer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_MANGLE);
|
||||
mangleTimer = 10 * IN_MILLISECONDS;
|
||||
mangleTimer = 10000;
|
||||
}
|
||||
else
|
||||
{
|
||||
mangleTimer -= diff;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
@@ -185,6 +214,7 @@ public:
|
||||
private:
|
||||
InstanceScript* instance;
|
||||
uint32 mangleTimer;
|
||||
uint32 rangeCheckTimer;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
|
||||
@@ -15,13 +15,6 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* ScriptData
|
||||
SDName: Boss_Lucifron
|
||||
SD%Complete: 100
|
||||
SDComment:
|
||||
SDCategory: Molten Core
|
||||
EndScriptData */
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "molten_core.h"
|
||||
@@ -47,9 +40,7 @@ public:
|
||||
|
||||
struct boss_lucifronAI : public BossAI
|
||||
{
|
||||
boss_lucifronAI(Creature* creature) : BossAI(creature, BOSS_LUCIFRON)
|
||||
{
|
||||
}
|
||||
boss_lucifronAI(Creature* creature) : BossAI(creature, DATA_LUCIFRON) {}
|
||||
|
||||
void EnterCombat(Unit* /*victim*/) override
|
||||
{
|
||||
@@ -59,46 +50,29 @@ public:
|
||||
events.ScheduleEvent(EVENT_SHADOW_SHOCK, 5000);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
void ExecuteEvent(uint32 eventId) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
switch (eventId)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (uint32 const eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
case EVENT_IMPENDING_DOOM:
|
||||
{
|
||||
case EVENT_IMPENDING_DOOM:
|
||||
{
|
||||
DoCastVictim(SPELL_IMPENDING_DOOM);
|
||||
events.RepeatEvent(20000);
|
||||
break;
|
||||
}
|
||||
case EVENT_LUCIFRON_CURSE:
|
||||
{
|
||||
DoCastVictim(SPELL_LUCIFRON_CURSE);
|
||||
events.RepeatEvent(20000);
|
||||
break;
|
||||
}
|
||||
case EVENT_SHADOW_SHOCK:
|
||||
{
|
||||
DoCastVictim(SPELL_SHADOW_SHOCK);
|
||||
events.RepeatEvent(5000);
|
||||
break;
|
||||
}
|
||||
DoCastVictim(SPELL_IMPENDING_DOOM);
|
||||
events.RepeatEvent(20000);
|
||||
break;
|
||||
}
|
||||
case EVENT_LUCIFRON_CURSE:
|
||||
{
|
||||
DoCastVictim(SPELL_LUCIFRON_CURSE);
|
||||
events.RepeatEvent(20000);
|
||||
break;
|
||||
}
|
||||
case EVENT_SHADOW_SHOCK:
|
||||
{
|
||||
DoCastVictim(SPELL_SHADOW_SHOCK);
|
||||
events.RepeatEvent(5000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -15,102 +15,98 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* ScriptData
|
||||
SDName: Boss_Magmadar
|
||||
SD%Complete: 75
|
||||
SDComment: Conflag on ground nyi
|
||||
SDCategory: Molten Core
|
||||
EndScriptData */
|
||||
|
||||
#include "molten_core.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "SpellScript.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "molten_core.h"
|
||||
|
||||
enum Texts
|
||||
{
|
||||
EMOTE_FRENZY = 0,
|
||||
EMOTE_SMOLDERING = 0,
|
||||
EMOTE_IGNITE = 1,
|
||||
EMOTE_FRENZY = 0,
|
||||
};
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_FRENZY = 19451,
|
||||
SPELL_MAGMA_SPIT = 19449,
|
||||
SPELL_PANIC = 19408,
|
||||
SPELL_LAVA_BOMB = 19428,
|
||||
SPELL_SERRATED_BITE = 19771,
|
||||
SPELL_FRENZY = 19451,
|
||||
SPELL_MAGMA_SPIT = 19449,
|
||||
SPELL_PANIC = 19408,
|
||||
SPELL_LAVA_BOMB = 19411, // This calls a dummy server side effect that cast spell 20494 to spawn GO 177704 for 30s
|
||||
SPELL_LAVA_BOMB_EFFECT = 20494, // Spawns trap GO 177704 which triggers 19428
|
||||
SPELL_LAVA_BOMB_RANGED = 20474, // This calls a dummy server side effect that cast spell 20495 to spawn GO 177704 for 60s
|
||||
SPELL_LAVA_BOMB_RANGED_EFFECT = 20495, // Spawns trap GO 177704 which triggers 19428
|
||||
};
|
||||
|
||||
enum Events
|
||||
{
|
||||
EVENT_FRENZY = 1,
|
||||
EVENT_PANIC = 2,
|
||||
EVENT_LAVA_BOMB = 3,
|
||||
EVENT_SERRATED_BITE = 1,
|
||||
EVENT_IGNITE = 2,
|
||||
EVENT_FRENZY = 1,
|
||||
EVENT_PANIC,
|
||||
EVENT_LAVA_BOMB,
|
||||
EVENT_LAVA_BOMB_RANGED,
|
||||
};
|
||||
|
||||
constexpr float MELEE_TARGET_LOOKUP_DIST = 10.0f;
|
||||
|
||||
class boss_magmadar : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_magmadar() : CreatureScript("boss_magmadar") { }
|
||||
boss_magmadar() : CreatureScript("boss_magmadar") {}
|
||||
|
||||
struct boss_magmadarAI : public BossAI
|
||||
{
|
||||
boss_magmadarAI(Creature* creature) : BossAI(creature, BOSS_MAGMADAR)
|
||||
{
|
||||
}
|
||||
boss_magmadarAI(Creature* creature) : BossAI(creature, DATA_MAGMADAR) {}
|
||||
|
||||
void Reset() override
|
||||
void EnterCombat(Unit* /*victim*/) override
|
||||
{
|
||||
BossAI::Reset();
|
||||
DoCast(me, SPELL_MAGMA_SPIT, true);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* victim) override
|
||||
{
|
||||
BossAI::EnterCombat(victim);
|
||||
events.ScheduleEvent(EVENT_FRENZY, 30000);
|
||||
events.ScheduleEvent(EVENT_PANIC, 20000);
|
||||
_EnterCombat();
|
||||
events.ScheduleEvent(EVENT_FRENZY, 8500);
|
||||
events.ScheduleEvent(EVENT_PANIC, 9500);
|
||||
events.ScheduleEvent(EVENT_LAVA_BOMB, 12000);
|
||||
events.ScheduleEvent(EVENT_LAVA_BOMB_RANGED, 15000);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
void ExecuteEvent(uint32 eventId) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
switch (eventId)
|
||||
{
|
||||
switch (eventId)
|
||||
case EVENT_FRENZY:
|
||||
{
|
||||
case EVENT_FRENZY:
|
||||
Talk(EMOTE_FRENZY);
|
||||
DoCast(me, SPELL_FRENZY);
|
||||
events.ScheduleEvent(EVENT_FRENZY, 15000);
|
||||
break;
|
||||
case EVENT_PANIC:
|
||||
DoCastVictim(SPELL_PANIC);
|
||||
events.ScheduleEvent(EVENT_PANIC, 35000);
|
||||
break;
|
||||
case EVENT_LAVA_BOMB:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_LAVA_BOMB))
|
||||
DoCast(target, SPELL_LAVA_BOMB);
|
||||
events.ScheduleEvent(EVENT_LAVA_BOMB, 12000);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
Talk(EMOTE_FRENZY);
|
||||
DoCastSelf(SPELL_FRENZY);
|
||||
events.RepeatEvent(urand(15000, 20000));
|
||||
break;
|
||||
}
|
||||
case EVENT_PANIC:
|
||||
{
|
||||
DoCastVictim(SPELL_PANIC);
|
||||
events.RepeatEvent(urand(31000, 38000));
|
||||
break;
|
||||
}
|
||||
case EVENT_LAVA_BOMB:
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, MELEE_TARGET_LOOKUP_DIST, true))
|
||||
{
|
||||
DoCast(target, SPELL_LAVA_BOMB);
|
||||
}
|
||||
|
||||
events.RepeatEvent(urand(12000, 15000));
|
||||
break;
|
||||
}
|
||||
case EVENT_LAVA_BOMB_RANGED:
|
||||
{
|
||||
std::list<Unit*> targets;
|
||||
SelectTargetList(targets, [this](Unit* target)
|
||||
{
|
||||
return target && target->IsPlayer() && target->GetDistance(me) > MELEE_TARGET_LOOKUP_DIST && target->GetDistance(me) < 100.0f;
|
||||
}, 1, SELECT_TARGET_RANDOM);
|
||||
|
||||
if (!targets.empty())
|
||||
{
|
||||
DoCast(targets.front() , SPELL_LAVA_BOMB_RANGED);
|
||||
}
|
||||
events.RepeatEvent(urand(12000, 15000));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -120,142 +116,64 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
// Serrated Bites timer may be wrong
|
||||
class npc_magmadar_core_hound : public CreatureScript
|
||||
// 19411 Lava Bomb
|
||||
// 20474 Lava Bomb
|
||||
class spell_magmadar_lava_bomb : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
npc_magmadar_core_hound() : CreatureScript("npc_magmadar_core_hound") { }
|
||||
spell_magmadar_lava_bomb() : SpellScriptLoader("spell_magmadar_lava_bomb") {}
|
||||
|
||||
struct npc_magmadar_core_houndAI : public CreatureAI
|
||||
class spell_magmadar_lava_bomb_SpellScript : public SpellScript
|
||||
{
|
||||
npc_magmadar_core_houndAI(Creature* creature) : CreatureAI(creature)
|
||||
PrepareSpellScript(spell_magmadar_lava_bomb_SpellScript);
|
||||
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_LAVA_BOMB_EFFECT, SPELL_LAVA_BOMB_RANGED_EFFECT });
|
||||
}
|
||||
|
||||
EventMap events;
|
||||
std::list<Creature*> hounds;
|
||||
bool smoldering = false;
|
||||
Unit* killer;
|
||||
|
||||
void removeFeignDeath()
|
||||
void HandleDummy(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREVENT_EMOTES_FROM_CHAT_TEXT);
|
||||
me->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
|
||||
me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
|
||||
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
|
||||
me->RemoveUnitMovementFlag(MOVEMENTFLAG_ROOT);
|
||||
me->ClearUnitState(UNIT_STATE_DIED);
|
||||
me->ClearUnitState(UNIT_STATE_CANNOT_AUTOATTACK);
|
||||
me->DisableRotate(false);
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/) override
|
||||
{
|
||||
if (me->HealthBelowPctDamaged(0, damage))
|
||||
if (Unit* target = GetHitUnit())
|
||||
{
|
||||
if (!smoldering)
|
||||
uint32 spellId = 0;
|
||||
switch (m_scriptSpellId)
|
||||
{
|
||||
killer = attacker;
|
||||
events.ScheduleEvent(EVENT_IGNITE, 10000);
|
||||
me->SetHealth(1);
|
||||
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREVENT_EMOTES_FROM_CHAT_TEXT);
|
||||
me->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
|
||||
me->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
|
||||
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
|
||||
me->AddUnitMovementFlag(MOVEMENTFLAG_ROOT);
|
||||
me->AddUnitState(UNIT_STATE_DIED);
|
||||
me->AddUnitState(UNIT_STATE_CANNOT_AUTOATTACK);
|
||||
me->DisableRotate(true);
|
||||
Talk(EMOTE_SMOLDERING);
|
||||
}
|
||||
damage = 0;
|
||||
smoldering = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
removeFeignDeath();
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
removeFeignDeath();
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*victim*/) override
|
||||
{
|
||||
events.ScheduleEvent(EVENT_SERRATED_BITE, 10000); // timer may be wrong
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim() && !smoldering)
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_SERRATED_BITE:
|
||||
if (UpdateVictim() && !smoldering)
|
||||
{
|
||||
DoCast(me->GetVictim(), SPELL_SERRATED_BITE);
|
||||
events.ScheduleEvent(EVENT_SERRATED_BITE, 10000); // again, timer may be wrong
|
||||
}
|
||||
case SPELL_LAVA_BOMB:
|
||||
{
|
||||
spellId = SPELL_LAVA_BOMB_EFFECT;
|
||||
break;
|
||||
case EVENT_IGNITE:
|
||||
smoldering = false;
|
||||
me->GetCreaturesWithEntryInRange(hounds, 80, NPC_CORE_HOUND);
|
||||
for (Creature* i : hounds)
|
||||
{
|
||||
if (i && i->IsAlive() && i->IsInCombat() && !i->HasUnitState(UNIT_STATE_DIED))
|
||||
{
|
||||
Talk(EMOTE_IGNITE);
|
||||
me->SetFullHealth();
|
||||
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREVENT_EMOTES_FROM_CHAT_TEXT);
|
||||
me->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
|
||||
me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
|
||||
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
|
||||
me->RemoveUnitMovementFlag(MOVEMENTFLAG_ROOT);
|
||||
me->ClearUnitState(UNIT_STATE_DIED);
|
||||
me->ClearUnitState(UNIT_STATE_CANNOT_AUTOATTACK);
|
||||
me->DisableRotate(false);
|
||||
me->AI()->AttackStart(i->GetVictim());
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (me->HasUnitState(UNIT_STATE_DIED))
|
||||
{
|
||||
if (killer)
|
||||
{
|
||||
me->Kill(killer, me);
|
||||
}
|
||||
else
|
||||
{
|
||||
me->Kill(me, me);
|
||||
}
|
||||
}
|
||||
}
|
||||
case SPELL_LAVA_BOMB_RANGED:
|
||||
{
|
||||
spellId = SPELL_LAVA_BOMB_RANGED_EFFECT;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
target->CastSpell(target, spellId, true, nullptr, nullptr, GetCaster()->GetGUID());
|
||||
}
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_magmadar_lava_bomb_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
SpellScript* GetSpellScript() const override
|
||||
{
|
||||
return GetMoltenCoreAI<npc_magmadar_core_houndAI>(creature);
|
||||
return new spell_magmadar_lava_bomb_SpellScript();
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_magmadar()
|
||||
{
|
||||
new boss_magmadar();
|
||||
new npc_magmadar_core_hound();
|
||||
|
||||
// Spells
|
||||
new spell_magmadar_lava_bomb();
|
||||
}
|
||||
|
||||
@@ -15,192 +15,561 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* ScriptData
|
||||
SDName: Boss_Majordomo_Executus
|
||||
SD%Complete: 30
|
||||
SDComment: Correct spawning and Event NYI
|
||||
SDCategory: Molten Core
|
||||
EndScriptData */
|
||||
|
||||
#include "molten_core.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "Player.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "ScriptedGossip.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "molten_core.h"
|
||||
#include "Player.h"
|
||||
#include "ScriptedGossip.h"
|
||||
#include "ObjectAccessor.h"
|
||||
#include "SpellScript.h"
|
||||
|
||||
enum Texts
|
||||
{
|
||||
SAY_AGGRO = 0,
|
||||
SAY_SPAWN = 1,
|
||||
SAY_SLAY = 2,
|
||||
SAY_SPECIAL = 3,
|
||||
SAY_DEFEAT = 4,
|
||||
SAY_AGGRO = 0,
|
||||
SAY_SPAWN = 1,
|
||||
SAY_SLAY = 2,
|
||||
SAY_DEFEAT = 3,
|
||||
SAY_SUMMON_MAJ = 4,
|
||||
SAY_ARRIVAL2_MAJ = 5,
|
||||
SAY_LAST_ADD = 6,
|
||||
|
||||
SAY_SUMMON_MAJ = 5,
|
||||
SAY_ARRIVAL2_MAJ = 6
|
||||
SAY_DEFEAT_2 = 7,
|
||||
SAY_DEFEAT_3 = 8,
|
||||
|
||||
// Ragnaros event
|
||||
// Majordomo
|
||||
SAY_RAG_SUM_1 = 9,
|
||||
SAY_RAG_SUM_2 = 10,
|
||||
|
||||
// Ragnaros
|
||||
SAY_ARRIVAL1_RAG = 1,
|
||||
SAY_ARRIVAL3_RAG = 3,
|
||||
};
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_MAGIC_REFLECTION = 20619,
|
||||
SPELL_DAMAGE_REFLECTION = 21075,
|
||||
SPELL_BLAST_WAVE = 20229,
|
||||
SPELL_AEGIS_OF_RAGNAROS = 20620,
|
||||
SPELL_TELEPORT = 20618,
|
||||
SPELL_SUMMON_RAGNAROS = 19774,
|
||||
};
|
||||
SPELL_MAGIC_REFLECTION = 20619,
|
||||
SPELL_DAMAGE_REFLECTION = 21075,
|
||||
SPELL_BLAST_WAVE = 20229,
|
||||
SPELL_AEGIS_OF_RAGNAROS = 20620,
|
||||
SPELL_TELEPORT_RANDOM = 20618, // Teleport random target
|
||||
SPELL_TELEPORT_TARGET = 20534, // Teleport Victim
|
||||
SPELL_ENCOURAGEMENT = 21086,
|
||||
SPELL_CHAMPION = 21090, // Server side
|
||||
SPELL_IMMUNE_POLY = 21087, // Server side
|
||||
SPELL_HATE_TO_ZERO = 20538, // Threat reset after each teleport. Server side
|
||||
SPELL_SEPARATION_ANXIETY = 21094, // Aura cast on himself by Majordomo Executus, if adds move out of range, they will cast spell 21095 on themselves
|
||||
SPELL_SEPARATION_ANXIETY_MINION = 21095,
|
||||
|
||||
#define GOSSIP_HELLO 4995
|
||||
// Outro & Ragnaros intro
|
||||
SPELL_TELEPORT_SELF = 19484,
|
||||
SPELL_SUMMON_RAGNAROS = 19774,
|
||||
SPELL_ELEMENTAL_FIRE = 19773,
|
||||
SPELL_RAGNA_EMERGE = 20568,
|
||||
SPELL_RAGNAROS_FADE = 21107,
|
||||
SPELL_RAGNAROS_SUBMERGE_EFFECT = 21859, // Applies pacify state and applies all schools immunity
|
||||
};
|
||||
|
||||
enum Events
|
||||
{
|
||||
EVENT_MAGIC_REFLECTION = 1,
|
||||
EVENT_DAMAGE_REFLECTION = 2,
|
||||
EVENT_BLAST_WAVE = 3,
|
||||
EVENT_TELEPORT = 4,
|
||||
EVENT_MAGIC_REFLECTION = 1,
|
||||
EVENT_DAMAGE_REFLECTION,
|
||||
EVENT_BLAST_WAVE,
|
||||
EVENT_TELEPORT_RANDOM,
|
||||
EVENT_TELEPORT_TARGET,
|
||||
EVENT_AEGIS_OF_RAGNAROS,
|
||||
|
||||
EVENT_OUTRO_1 = 5,
|
||||
EVENT_OUTRO_2 = 6,
|
||||
EVENT_OUTRO_3 = 7,
|
||||
EVENT_DEFEAT_OUTRO_1 = 1,
|
||||
EVENT_DEFEAT_OUTRO_2,
|
||||
EVENT_DEFEAT_OUTRO_3,
|
||||
|
||||
EVENT_RAGNAROS_SUMMON_1 = 1,
|
||||
EVENT_RAGNAROS_SUMMON_2,
|
||||
EVENT_RAGNAROS_SUMMON_3,
|
||||
EVENT_RAGNAROS_SUMMON_4,
|
||||
EVENT_RAGNAROS_SUMMON_5,
|
||||
EVENT_RAGNAROS_SUMMON_6,
|
||||
EVENT_RAGNAROS_SUMMON_7,
|
||||
EVENT_RAGNAROS_EMERGE,
|
||||
};
|
||||
|
||||
enum Misc
|
||||
{
|
||||
TEXT_ID_SUMMON_1 = 4995,
|
||||
TEXT_ID_SUMMON_2 = 5011,
|
||||
TEXT_ID_SUMMON_3 = 5012,
|
||||
|
||||
GOSSIP_ITEM_SUMMON_1 = 4093,
|
||||
GOSSIP_ITEM_SUMMON_2 = 4109,
|
||||
GOSSIP_ITEM_SUMMON_3 = 4108,
|
||||
|
||||
FACTION_MAJORDOMO_FRIENDLY = 1080,
|
||||
SUMMON_GROUP_ADDS = 1,
|
||||
|
||||
// Points
|
||||
POINT_RAGNAROS_SUMMON = 1,
|
||||
|
||||
// Event phases
|
||||
PHASE_NONE = 1,
|
||||
PHASE_COMBAT = 2,
|
||||
PHASE_DEFEAT_OUTRO = 3,
|
||||
PHASE_RAGNAROS_SUMMONING = 4,
|
||||
};
|
||||
|
||||
Position const MajordomoRagnaros = { 848.933f, -812.875f, -229.601f, 4.046f };
|
||||
Position const MajordomoSummonPos = {759.542f, -1173.43f, -118.974f, 3.3048f };
|
||||
Position const MajordomoMoveRagPos = { 830.9636f, -814.7055f, -228.9733f, 0.0f }; // Position used at Ragnaros summoning event
|
||||
Position const RagnarosSummonPos = { 838.3082f, -831.4665f, -232.1853f, 2.199115f };
|
||||
|
||||
class boss_majordomo : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_majordomo() : CreatureScript("boss_majordomo") { }
|
||||
boss_majordomo() : CreatureScript("boss_majordomo") {}
|
||||
|
||||
struct boss_majordomoAI : public BossAI
|
||||
{
|
||||
boss_majordomoAI(Creature* creature) : BossAI(creature, BOSS_MAJORDOMO_EXECUTUS)
|
||||
boss_majordomoAI(Creature* creature) : BossAI(creature, DATA_MAJORDOMO_EXECUTUS), spawnInTextTimer(0) {}
|
||||
|
||||
// Disabled events
|
||||
void JustDied(Unit* /*killer*/) override {}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
if (summon->GetEntry() == NPC_RAGNAROS)
|
||||
{
|
||||
summon->CastSpell(summon, SPELL_RAGNAROS_FADE);
|
||||
summon->CastSpell(summon, SPELL_RAGNAROS_SUBMERGE_EFFECT, true);
|
||||
summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC | UNIT_FLAG_NON_ATTACKABLE);
|
||||
summon->SetReactState(REACT_PASSIVE);
|
||||
}
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
void InitializeAI() override
|
||||
{
|
||||
if (urand(0, 99) < 25)
|
||||
BossAI::InitializeAI();
|
||||
if (instance->GetBossState(DATA_MAJORDOMO_EXECUTUS) != DONE)
|
||||
{
|
||||
events.SetPhase(PHASE_COMBAT);
|
||||
|
||||
std::list<TempSummon*> p_summons;
|
||||
me->SummonCreatureGroup(SUMMON_GROUP_ADDS, &p_summons);
|
||||
if (!p_summons.empty())
|
||||
{
|
||||
for (TempSummon const* summon : p_summons)
|
||||
{
|
||||
if (summon)
|
||||
{
|
||||
static_minionsGUIDS.insert(summon->GetGUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
spawnInTextTimer = 10000;
|
||||
}
|
||||
else
|
||||
{
|
||||
events.SetPhase(PHASE_NONE);
|
||||
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC);
|
||||
me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
|
||||
me->SetFaction(FACTION_MAJORDOMO_FRIENDLY);
|
||||
}
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
me->ResetLootMode();
|
||||
events.Reset();
|
||||
aliveMinionsGUIDS.clear();
|
||||
|
||||
if (instance->GetBossState(DATA_MAJORDOMO_EXECUTUS) != DONE)
|
||||
{
|
||||
events.SetPhase(PHASE_COMBAT);
|
||||
instance->SetBossState(DATA_MAJORDOMO_EXECUTUS, NOT_STARTED);
|
||||
}
|
||||
else
|
||||
{
|
||||
static_minionsGUIDS.clear();
|
||||
summons.DespawnAll();
|
||||
}
|
||||
}
|
||||
|
||||
bool CanAIAttack(Unit const* /*target*/) const override
|
||||
{
|
||||
return instance->GetBossState(DATA_MAJORDOMO_EXECUTUS) != DONE;
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (roll_chance_i(25) && victim->IsPlayer())
|
||||
{
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* who) override
|
||||
void EnterCombat(Unit* /*attacker*/) override
|
||||
{
|
||||
BossAI::EnterCombat(who);
|
||||
if (!events.IsInPhase(PHASE_COMBAT))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_EnterCombat();
|
||||
DoCastAOE(SPELL_SEPARATION_ANXIETY);
|
||||
spawnInTextTimer = 0;
|
||||
Talk(SAY_AGGRO);
|
||||
events.ScheduleEvent(EVENT_MAGIC_REFLECTION, 30000);
|
||||
events.ScheduleEvent(EVENT_DAMAGE_REFLECTION, 15000);
|
||||
events.ScheduleEvent(EVENT_BLAST_WAVE, 10000);
|
||||
events.ScheduleEvent(EVENT_TELEPORT, 20000);
|
||||
// Call every flamewaker around him
|
||||
me->CallForHelp(30);
|
||||
DoCastSelf(SPELL_AEGIS_OF_RAGNAROS, true);
|
||||
|
||||
events.ScheduleEvent(EVENT_MAGIC_REFLECTION, 30000, PHASE_COMBAT, PHASE_COMBAT);
|
||||
events.ScheduleEvent(EVENT_DAMAGE_REFLECTION, 15000, PHASE_COMBAT, PHASE_COMBAT);
|
||||
events.ScheduleEvent(EVENT_BLAST_WAVE, 10000, PHASE_COMBAT, PHASE_COMBAT);
|
||||
events.ScheduleEvent(EVENT_TELEPORT_RANDOM, 15000, PHASE_COMBAT, PHASE_COMBAT);
|
||||
events.ScheduleEvent(EVENT_TELEPORT_TARGET, 30000, PHASE_COMBAT, PHASE_COMBAT);
|
||||
|
||||
aliveMinionsGUIDS.clear();
|
||||
aliveMinionsGUIDS = static_minionsGUIDS;
|
||||
}
|
||||
|
||||
void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override
|
||||
{
|
||||
aliveMinionsGUIDS.erase(summon->GetGUID());
|
||||
if (summon->GetEntry() == NPC_FLAMEWAKER_HEALER || summon->GetEntry() == NPC_FLAMEWAKER_ELITE)
|
||||
{
|
||||
uint32 const remainingAdds = std::count_if(aliveMinionsGUIDS.begin(), aliveMinionsGUIDS.end(), [](ObjectGuid const& summonGuid)
|
||||
{
|
||||
return summonGuid.GetEntry() == NPC_FLAMEWAKER_HEALER || summonGuid.GetEntry() == NPC_FLAMEWAKER_ELITE;
|
||||
});
|
||||
|
||||
// Last remaining add
|
||||
if (remainingAdds == 1)
|
||||
{
|
||||
Talk(SAY_LAST_ADD);
|
||||
DoCastAOE(SPELL_CHAMPION);
|
||||
}
|
||||
// 50% of adds
|
||||
else if (remainingAdds == 4)
|
||||
{
|
||||
DoCastAOE(SPELL_IMMUNE_POLY);
|
||||
}
|
||||
else if (!remainingAdds)
|
||||
{
|
||||
if (!static_minionsGUIDS.empty())
|
||||
{
|
||||
for (ObjectGuid const& guid : static_minionsGUIDS)
|
||||
{
|
||||
if (Creature* minion = ObjectAccessor::GetCreature(*me, guid))
|
||||
{
|
||||
minion->DespawnOrUnsummon();
|
||||
}
|
||||
}
|
||||
|
||||
static_minionsGUIDS.clear();
|
||||
}
|
||||
|
||||
instance->SetBossState(DATA_MAJORDOMO_EXECUTUS, DONE);
|
||||
events.CancelEventGroup(PHASE_COMBAT);
|
||||
me->GetMap()->UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, me->GetEntry(), me);
|
||||
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC);
|
||||
me->SetFaction(FACTION_MAJORDOMO_FRIENDLY);
|
||||
EnterEvadeMode();
|
||||
Talk(SAY_DEFEAT);
|
||||
return;
|
||||
}
|
||||
DoCastAOE(SPELL_ENCOURAGEMENT);
|
||||
}
|
||||
}
|
||||
|
||||
void JustReachedHome() override
|
||||
{
|
||||
_JustReachedHome();
|
||||
if (instance->GetBossState(DATA_MAJORDOMO_EXECUTUS) == DONE)
|
||||
{
|
||||
events.Reset();
|
||||
events.SetPhase(PHASE_DEFEAT_OUTRO);
|
||||
events.ScheduleEvent(EVENT_DEFEAT_OUTRO_1, 7500, PHASE_DEFEAT_OUTRO, PHASE_DEFEAT_OUTRO);
|
||||
}
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*dmgType*/, SpellSchoolMask /*school*/) override
|
||||
{
|
||||
if (events.IsInPhase(PHASE_COMBAT) && me->GetHealth() <= damage)
|
||||
{
|
||||
damage = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (instance->GetBossState(BOSS_MAJORDOMO_EXECUTUS) != DONE)
|
||||
if (spawnInTextTimer)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (!me->FindNearestCreature(NPC_FLAMEWAKER_HEALER, 100.0f) && !me->FindNearestCreature(NPC_FLAMEWAKER_ELITE, 100.0f))
|
||||
if (spawnInTextTimer <= diff)
|
||||
{
|
||||
me->GetMap()->UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, me->GetEntry(), me);
|
||||
me->SetFaction(FACTION_FRIENDLY);
|
||||
EnterEvadeMode();
|
||||
Talk(SAY_DEFEAT);
|
||||
_JustDied();
|
||||
events.ScheduleEvent(EVENT_OUTRO_1, 32000);
|
||||
return;
|
||||
spawnInTextTimer = 0;
|
||||
Talk(SAY_SPAWN);
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
if (HealthBelowPct(50))
|
||||
DoCast(me, SPELL_AEGIS_OF_RAGNAROS, true);
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
else
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_MAGIC_REFLECTION:
|
||||
DoCast(me, SPELL_MAGIC_REFLECTION);
|
||||
events.ScheduleEvent(EVENT_MAGIC_REFLECTION, 30000);
|
||||
break;
|
||||
case EVENT_DAMAGE_REFLECTION:
|
||||
DoCast(me, SPELL_DAMAGE_REFLECTION);
|
||||
events.ScheduleEvent(EVENT_DAMAGE_REFLECTION, 30000);
|
||||
break;
|
||||
case EVENT_BLAST_WAVE:
|
||||
DoCastVictim(SPELL_BLAST_WAVE);
|
||||
events.ScheduleEvent(EVENT_BLAST_WAVE, 10000);
|
||||
break;
|
||||
case EVENT_TELEPORT:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1))
|
||||
DoCast(target, SPELL_TELEPORT);
|
||||
events.ScheduleEvent(EVENT_TELEPORT, 20000);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
spawnInTextTimer -= diff;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
else
|
||||
{
|
||||
events.Update(diff);
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
switch (events.GetPhaseMask())
|
||||
{
|
||||
case (1 << (PHASE_COMBAT - 1)):
|
||||
{
|
||||
switch (eventId)
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
case EVENT_OUTRO_1:
|
||||
me->NearTeleportTo(RagnarosTelePos.GetPositionX(), RagnarosTelePos.GetPositionY(), RagnarosTelePos.GetPositionZ(), RagnarosTelePos.GetOrientation());
|
||||
me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
|
||||
break;
|
||||
case EVENT_OUTRO_2:
|
||||
instance->instance->SummonCreature(NPC_RAGNAROS, RagnarosSummonPos);
|
||||
break;
|
||||
case EVENT_OUTRO_3:
|
||||
Talk(SAY_ARRIVAL2_MAJ);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
return;
|
||||
}
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (uint32 const eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_MAGIC_REFLECTION:
|
||||
{
|
||||
DoCastSelf(SPELL_MAGIC_REFLECTION);
|
||||
events.RepeatEvent(30000);
|
||||
break;
|
||||
}
|
||||
case EVENT_DAMAGE_REFLECTION:
|
||||
{
|
||||
DoCastSelf(SPELL_DAMAGE_REFLECTION);
|
||||
events.RepeatEvent(30000);
|
||||
break;
|
||||
}
|
||||
case EVENT_BLAST_WAVE:
|
||||
{
|
||||
DoCastVictim(SPELL_BLAST_WAVE);
|
||||
events.RepeatEvent(10000);
|
||||
break;
|
||||
}
|
||||
case EVENT_TELEPORT_RANDOM:
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true))
|
||||
{
|
||||
DoCastSelf(SPELL_HATE_TO_ZERO, true);
|
||||
DoCast(target, SPELL_TELEPORT_RANDOM);
|
||||
}
|
||||
|
||||
events.RepeatEvent(15000);
|
||||
break;
|
||||
}
|
||||
case EVENT_TELEPORT_TARGET:
|
||||
{
|
||||
DoCastSelf(SPELL_HATE_TO_ZERO, true);
|
||||
DoCastAOE(SPELL_TELEPORT_TARGET);
|
||||
events.RepeatEvent(30000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
break;
|
||||
}
|
||||
case (1 << (PHASE_DEFEAT_OUTRO - 1)):
|
||||
{
|
||||
events.Update(diff);
|
||||
while (uint32 const eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_DEFEAT_OUTRO_1:
|
||||
{
|
||||
Talk(SAY_DEFEAT_2);
|
||||
events.ScheduleEvent(EVENT_DEFEAT_OUTRO_2, 8000, PHASE_DEFEAT_OUTRO, PHASE_DEFEAT_OUTRO);
|
||||
break;
|
||||
}
|
||||
case EVENT_DEFEAT_OUTRO_2:
|
||||
{
|
||||
Talk(SAY_DEFEAT_3);
|
||||
events.ScheduleEvent(EVENT_DEFEAT_OUTRO_3, 21500, PHASE_DEFEAT_OUTRO, PHASE_DEFEAT_OUTRO);
|
||||
break;
|
||||
}
|
||||
case EVENT_DEFEAT_OUTRO_3:
|
||||
{
|
||||
DoCastSelf(SPELL_TELEPORT_SELF);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case (1 << (PHASE_RAGNAROS_SUMMONING - 1)):
|
||||
{
|
||||
events.Update(diff);
|
||||
while (uint32 const eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_RAGNAROS_SUMMON_1:
|
||||
{
|
||||
if (GameObject* lavaSplash = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_LAVA_SPLASH)))
|
||||
{
|
||||
lavaSplash->SetRespawnTime(900);
|
||||
lavaSplash->Refresh();
|
||||
}
|
||||
if (GameObject* lavaSteam = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_LAVA_STEAM)))
|
||||
{
|
||||
lavaSteam->SetRespawnTime(900);
|
||||
lavaSteam->Refresh();
|
||||
}
|
||||
Talk(SAY_RAG_SUM_2);
|
||||
// Next event will get triggered in MovementInform
|
||||
me->SetWalk(true);
|
||||
me->GetMotionMaster()->MovePoint(POINT_RAGNAROS_SUMMON, MajordomoMoveRagPos, true, false);
|
||||
break;
|
||||
}
|
||||
case EVENT_RAGNAROS_SUMMON_2:
|
||||
{
|
||||
if (GameObject* lavaSteam = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_LAVA_STEAM)))
|
||||
{
|
||||
me->SetFacingToObject(lavaSteam);
|
||||
}
|
||||
|
||||
Talk(SAY_SUMMON_MAJ);
|
||||
events.ScheduleEvent(EVENT_RAGNAROS_SUMMON_3, 16700, PHASE_RAGNAROS_SUMMONING, PHASE_RAGNAROS_SUMMONING);
|
||||
events.ScheduleEvent(EVENT_RAGNAROS_EMERGE, 15000, PHASE_RAGNAROS_SUMMONING, PHASE_RAGNAROS_SUMMONING);
|
||||
break;
|
||||
}
|
||||
case EVENT_RAGNAROS_SUMMON_3:
|
||||
{
|
||||
if (Creature* ragnaros = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_RAGNAROS)))
|
||||
{
|
||||
ragnaros->AI()->Talk(SAY_ARRIVAL1_RAG);
|
||||
}
|
||||
events.ScheduleEvent(EVENT_RAGNAROS_SUMMON_4, 11700, PHASE_RAGNAROS_SUMMONING, PHASE_RAGNAROS_SUMMONING);
|
||||
break;
|
||||
}
|
||||
case EVENT_RAGNAROS_SUMMON_4:
|
||||
{
|
||||
Talk(SAY_ARRIVAL2_MAJ);
|
||||
events.ScheduleEvent(EVENT_RAGNAROS_SUMMON_5, 8700, PHASE_RAGNAROS_SUMMONING, PHASE_RAGNAROS_SUMMONING);
|
||||
break;
|
||||
}
|
||||
case EVENT_RAGNAROS_SUMMON_5:
|
||||
{
|
||||
if (Creature* ragnaros = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_RAGNAROS)))
|
||||
{
|
||||
ragnaros->AI()->Talk(SAY_ARRIVAL3_RAG);
|
||||
}
|
||||
|
||||
events.ScheduleEvent(EVENT_RAGNAROS_SUMMON_6, 16500, PHASE_RAGNAROS_SUMMONING, PHASE_RAGNAROS_SUMMONING);
|
||||
break;
|
||||
}
|
||||
case EVENT_RAGNAROS_SUMMON_6:
|
||||
{
|
||||
if (Creature* ragnaros = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_RAGNAROS)))
|
||||
{
|
||||
ragnaros->CastSpell(me, SPELL_ELEMENTAL_FIRE, true);
|
||||
ragnaros->AI()->DoAction(ACTION_FINISH_RAGNAROS_INTRO);
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Additional events
|
||||
case EVENT_RAGNAROS_EMERGE:
|
||||
{
|
||||
if (Creature* ragnaros = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_RAGNAROS)))
|
||||
{
|
||||
ragnaros->RemoveAurasDueToSpell(SPELL_RAGNAROS_FADE);
|
||||
ragnaros->CastSpell(ragnaros, SPELL_RAGNA_EMERGE);
|
||||
}
|
||||
}break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 pointId) override
|
||||
{
|
||||
if (type == POINT_MOTION_TYPE && pointId == POINT_RAGNAROS_SUMMON)
|
||||
{
|
||||
DoCastAOE(SPELL_SUMMON_RAGNAROS);
|
||||
events.ScheduleEvent(EVENT_RAGNAROS_SUMMON_2, 11500, PHASE_RAGNAROS_SUMMONING, PHASE_RAGNAROS_SUMMONING);
|
||||
}
|
||||
}
|
||||
|
||||
void SpellHit(Unit* /*caster*/, SpellInfo const* spellInfo) override
|
||||
{
|
||||
if (events.IsInPhase(PHASE_DEFEAT_OUTRO) && spellInfo->Id == SPELL_TELEPORT_SELF)
|
||||
{
|
||||
me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
|
||||
me->SetHomePosition(MajordomoRagnaros);
|
||||
me->NearTeleportTo(MajordomoRagnaros.GetPositionX(), MajordomoRagnaros.GetPositionY(), MajordomoRagnaros.GetPositionZ(), MajordomoRagnaros.GetOrientation());
|
||||
events.SetPhase(PHASE_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
void DoAction(int32 action) override
|
||||
{
|
||||
if (action == ACTION_START_RAGNAROS && events.GetNextEventTime(EVENT_OUTRO_2) == 0)
|
||||
if (action == ACTION_START_RAGNAROS_INTRO && !events.IsInPhase(PHASE_RAGNAROS_SUMMONING))
|
||||
{
|
||||
me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
|
||||
Talk(SAY_SUMMON_MAJ);
|
||||
events.ScheduleEvent(EVENT_OUTRO_2, 8000);
|
||||
events.ScheduleEvent(EVENT_OUTRO_3, 24000);
|
||||
}
|
||||
else if (action == ACTION_START_RAGNAROS_ALT)
|
||||
{
|
||||
me->SetFaction(FACTION_FRIENDLY);
|
||||
me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
|
||||
events.SetPhase(PHASE_RAGNAROS_SUMMONING);
|
||||
events.ScheduleEvent(EVENT_RAGNAROS_SUMMON_1, 5000, PHASE_RAGNAROS_SUMMONING, PHASE_RAGNAROS_SUMMONING);
|
||||
}
|
||||
}
|
||||
private:
|
||||
GuidSet static_minionsGUIDS; // contained data should be changed on encounter completion
|
||||
GuidSet aliveMinionsGUIDS; // used for calculations
|
||||
uint32 spawnInTextTimer;
|
||||
};
|
||||
|
||||
bool OnGossipHello(Player* player, Creature* creature) override
|
||||
{
|
||||
AddGossipItemFor(player, 4093, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
||||
SendGossipMenuFor(player, GOSSIP_HELLO, creature->GetGUID());
|
||||
AddGossipItemFor(player, GOSSIP_ITEM_SUMMON_1, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
|
||||
SendGossipMenuFor(player, TEXT_ID_SUMMON_1, creature->GetGUID());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 /*action*/) override
|
||||
bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override
|
||||
{
|
||||
CloseGossipMenuFor(player);
|
||||
creature->AI()->DoAction(ACTION_START_RAGNAROS);
|
||||
ClearGossipMenuFor(player);
|
||||
switch (action)
|
||||
{
|
||||
case GOSSIP_ACTION_INFO_DEF:
|
||||
{
|
||||
AddGossipItemFor(player, GOSSIP_ITEM_SUMMON_2, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
||||
SendGossipMenuFor(player, TEXT_ID_SUMMON_2, creature->GetGUID());
|
||||
break;
|
||||
}
|
||||
case GOSSIP_ACTION_INFO_DEF+1:
|
||||
{
|
||||
AddGossipItemFor(player, GOSSIP_ITEM_SUMMON_2, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
|
||||
SendGossipMenuFor(player, TEXT_ID_SUMMON_2, creature->GetGUID());
|
||||
break;
|
||||
}
|
||||
case GOSSIP_ACTION_INFO_DEF+2:
|
||||
{
|
||||
AddGossipItemFor(player, GOSSIP_ITEM_SUMMON_3, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
|
||||
SendGossipMenuFor(player, TEXT_ID_SUMMON_3, creature->GetGUID());
|
||||
break;
|
||||
}
|
||||
case GOSSIP_ACTION_INFO_DEF+3:
|
||||
{
|
||||
CloseGossipMenuFor(player);
|
||||
creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
|
||||
creature->AI()->Talk(SAY_RAG_SUM_1, player);
|
||||
creature->AI()->DoAction(ACTION_START_RAGNAROS_INTRO);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
CloseGossipMenuFor(player);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -210,7 +579,118 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
// 20538 Hate to Zero (SERVERSIDE)
|
||||
class spell_hate_to_zero : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_hate_to_zero() : SpellScriptLoader("spell_hate_to_zero") {}
|
||||
|
||||
class spell_hate_to_zero_SpellScript : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_hate_to_zero_SpellScript);
|
||||
|
||||
bool Load() override
|
||||
{
|
||||
return GetCaster()->GetTypeId() == TYPEID_UNIT;
|
||||
}
|
||||
|
||||
void HandleHit(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (Unit* caster = GetCaster())
|
||||
{
|
||||
if (Creature* creatureCaster = caster->ToCreature())
|
||||
{
|
||||
creatureCaster->getThreatMgr().resetAllAggro();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_hate_to_zero_SpellScript::HandleHit, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
{
|
||||
return new spell_hate_to_zero_SpellScript();
|
||||
}
|
||||
};
|
||||
|
||||
// 21094 Separation Anxiety (server side)
|
||||
class spell_majordomo_separation_nexiety : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_majordomo_separation_nexiety() : SpellScriptLoader("spell_majordomo_separation_nexiety") {}
|
||||
|
||||
class spell_majordomo_separation_nexiety_AuraScript : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_majordomo_separation_nexiety_AuraScript);
|
||||
|
||||
bool Validate(SpellInfo const* /*spell*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_SEPARATION_ANXIETY_MINION });
|
||||
}
|
||||
|
||||
void HandlePeriodic(AuraEffect const* aurEff)
|
||||
{
|
||||
Unit const* caster = GetCaster();
|
||||
Unit* target = GetTarget();
|
||||
if (caster && target && target->GetDistance(caster) > 40.0f && !target->HasAura(SPELL_SEPARATION_ANXIETY_MINION))
|
||||
{
|
||||
target->CastSpell(target, SPELL_SEPARATION_ANXIETY_MINION, true, nullptr, aurEff);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_majordomo_separation_nexiety_AuraScript::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
// Should return a fully valid AuraScript pointer.
|
||||
AuraScript* GetAuraScript() const override
|
||||
{
|
||||
return new spell_majordomo_separation_nexiety_AuraScript();
|
||||
}
|
||||
};
|
||||
|
||||
// 19774 Summon Ragnaros
|
||||
class spell_summon_ragnaros : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_summon_ragnaros() : SpellScriptLoader("spell_summon_ragnaros") {}
|
||||
|
||||
class spell_summon_ragnaros_SpellScript : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_summon_ragnaros_SpellScript);
|
||||
|
||||
void HandleHit()
|
||||
{
|
||||
if (Unit* caster = GetCaster())
|
||||
{
|
||||
caster->SummonCreature(NPC_RAGNAROS, RagnarosSummonPos, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 2 * HOUR * IN_MILLISECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
AfterCast += SpellCastFn(spell_summon_ragnaros_SpellScript::HandleHit);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
{
|
||||
return new spell_summon_ragnaros_SpellScript();
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_majordomo()
|
||||
{
|
||||
new boss_majordomo();
|
||||
|
||||
// Spells
|
||||
new spell_hate_to_zero();
|
||||
new spell_majordomo_separation_nexiety();
|
||||
new spell_summon_ragnaros();
|
||||
}
|
||||
|
||||
@@ -15,289 +15,304 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* ScriptData
|
||||
SDName: Boss_Ragnaros
|
||||
SD%Complete: 95
|
||||
SDComment: some spells doesnt work correctly
|
||||
SDCategory: Molten Core
|
||||
EndScriptData */
|
||||
|
||||
#include "molten_core.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "molten_core.h"
|
||||
|
||||
enum Texts
|
||||
{
|
||||
SAY_SUMMON_MAJ = 0,
|
||||
SAY_ARRIVAL1_RAG = 1,
|
||||
SAY_ARRIVAL2_MAJ = 2,
|
||||
SAY_ARRIVAL3_RAG = 3,
|
||||
SAY_ARRIVAL5_RAG = 4,
|
||||
SAY_REINFORCEMENTS1 = 5,
|
||||
SAY_REINFORCEMENTS2 = 6,
|
||||
SAY_HAND = 7,
|
||||
SAY_WRATH = 8,
|
||||
SAY_KILL = 9,
|
||||
SAY_MAGMABURST = 10
|
||||
SAY_SUMMON_MAJ = 0,
|
||||
SAY_ARRIVAL1_RAG = 1,
|
||||
SAY_ARRIVAL2_MAJ = 2,
|
||||
SAY_ARRIVAL3_RAG = 3,
|
||||
SAY_ARRIVAL5_RAG = 4,
|
||||
SAY_REINFORCEMENTS1 = 5,
|
||||
SAY_REINFORCEMENTS2 = 6,
|
||||
SAY_HAND = 7,
|
||||
SAY_WRATH = 8,
|
||||
SAY_KILL = 9,
|
||||
SAY_MAGMABURST = 10
|
||||
};
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_HAND_OF_RAGNAROS = 19780,
|
||||
SPELL_WRATH_OF_RAGNAROS = 20566,
|
||||
SPELL_LAVA_BURST = 21158,
|
||||
SPELL_MAGMA_BLAST = 20565, // Ranged attack
|
||||
SPELL_SONS_OF_FLAME_DUMMY = 21108, // Server side effect
|
||||
SPELL_RAGSUBMERGE = 21107, // Stealth aura
|
||||
SPELL_RAGEMERGE = 20568,
|
||||
SPELL_MELT_WEAPON = 21388,
|
||||
SPELL_ELEMENTAL_FIRE = 20564,
|
||||
SPELL_ERRUPTION = 17731
|
||||
SPELL_HAND_OF_RAGNAROS = 19780,
|
||||
SPELL_WRATH_OF_RAGNAROS = 20566,
|
||||
SPELL_LAVA_BURST = 21158,
|
||||
SPELL_MAGMA_BLAST = 20565, // Ranged attack
|
||||
SPELL_SONS_OF_FLAME_DUMMY = 21108, // Server side effect
|
||||
SPELL_RAGSUBMERGE = 21107, // Stealth aura
|
||||
SPELL_RAGNA_SUBMERGE_VISUAL = 20567, // Visual for submerging into lava
|
||||
SPELL_RAGEMERGE = 20568,
|
||||
SPELL_MELT_WEAPON = 21387,
|
||||
SPELL_ELEMENTAL_FIRE = 20563,
|
||||
SPELL_ERRUPTION = 17731,
|
||||
SPELL_RAGNAROS_SUBMERGE_EFFECT = 21859, // Applies pacify state and applies all schools immunity
|
||||
};
|
||||
|
||||
enum Events
|
||||
{
|
||||
EVENT_ERUPTION = 1,
|
||||
EVENT_WRATH_OF_RAGNAROS = 2,
|
||||
EVENT_HAND_OF_RAGNAROS = 3,
|
||||
EVENT_LAVA_BURST = 4,
|
||||
EVENT_ELEMENTAL_FIRE = 5,
|
||||
EVENT_MAGMA_BLAST = 6,
|
||||
EVENT_SUBMERGE = 7,
|
||||
EVENT_WRATH_OF_RAGNAROS,
|
||||
EVENT_HAND_OF_RAGNAROS,
|
||||
EVENT_LAVA_BURST,
|
||||
EVENT_MAGMA_BLAST,
|
||||
EVENT_SUBMERGE,
|
||||
|
||||
EVENT_INTRO_1 = 8,
|
||||
EVENT_INTRO_2 = 9,
|
||||
EVENT_INTRO_3 = 10,
|
||||
EVENT_INTRO_4 = 11,
|
||||
EVENT_INTRO_5 = 12
|
||||
EVENT_INTRO_1,
|
||||
EVENT_INTRO_2,
|
||||
EVENT_INTRO_3,
|
||||
EVENT_INTRO_4,
|
||||
EVENT_INTRO_5,
|
||||
};
|
||||
|
||||
enum Creatures
|
||||
{
|
||||
NPC_SON_OF_FLAME = 12143,
|
||||
};
|
||||
|
||||
enum Misc
|
||||
{
|
||||
MAX_SON_OF_FLAME_COUNT = 8,
|
||||
};
|
||||
|
||||
constexpr float DEATH_ORIENTATION = 4.0f;
|
||||
|
||||
class boss_ragnaros : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_ragnaros() : CreatureScript("boss_ragnaros") { }
|
||||
boss_ragnaros() : CreatureScript("boss_ragnaros") {}
|
||||
|
||||
struct boss_ragnarosAI : public BossAI
|
||||
{
|
||||
boss_ragnarosAI(Creature* creature) : BossAI(creature, BOSS_RAGNAROS)
|
||||
boss_ragnarosAI(Creature* creature) : BossAI(creature, DATA_RAGNAROS),
|
||||
attackableTImer(0),
|
||||
_emergeTimer(90000),
|
||||
_hasYelledMagmaBurst(false),
|
||||
_hasSubmergedOnce(false),
|
||||
_isBanished(false)
|
||||
{
|
||||
_introState = 0;
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
|
||||
creature->SetReactState(REACT_PASSIVE);
|
||||
creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
BossAI::Reset();
|
||||
_Reset();
|
||||
_emergeTimer = 90000;
|
||||
_hasYelledMagmaBurst = false;
|
||||
_hasSubmergedOnce = false;
|
||||
_isBanished = false;
|
||||
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
|
||||
DoCastSelf(SPELL_MELT_WEAPON, true);
|
||||
DoCastSelf(SPELL_ELEMENTAL_FIRE, true);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* victim) override
|
||||
void DoAction(int32 action) override
|
||||
{
|
||||
BossAI::EnterCombat(victim);
|
||||
if (action == ACTION_FINISH_RAGNAROS_INTRO)
|
||||
{
|
||||
attackableTImer = 10000;
|
||||
}
|
||||
}
|
||||
|
||||
void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override
|
||||
{
|
||||
summons.Despawn(summon);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*victim*/) override
|
||||
{
|
||||
_EnterCombat();
|
||||
events.ScheduleEvent(EVENT_ERUPTION, 15000);
|
||||
events.ScheduleEvent(EVENT_WRATH_OF_RAGNAROS, 30000);
|
||||
events.ScheduleEvent(EVENT_HAND_OF_RAGNAROS, 25000);
|
||||
events.ScheduleEvent(EVENT_LAVA_BURST, 10000);
|
||||
events.ScheduleEvent(EVENT_ELEMENTAL_FIRE, 3000);
|
||||
events.ScheduleEvent(EVENT_MAGMA_BLAST, 2000);
|
||||
events.ScheduleEvent(EVENT_SUBMERGE, 180000);
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
BossAI::JustDied(killer);
|
||||
_JustDied();
|
||||
me->SetFacingTo(DEATH_ORIENTATION);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (urand(0, 99) < 25)
|
||||
if (roll_chance_i(25) && victim->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
Talk(SAY_KILL);
|
||||
}
|
||||
}
|
||||
|
||||
void AttackStart(Unit* target) override
|
||||
{
|
||||
if (target && me->Attack(target, true))
|
||||
{
|
||||
DoStartNoMovement(target);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (_introState != 2)
|
||||
if (attackableTImer)
|
||||
{
|
||||
if (!_introState)
|
||||
if (attackableTImer <= diff)
|
||||
{
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_EMERGE);
|
||||
events.ScheduleEvent(EVENT_INTRO_1, 4000);
|
||||
events.ScheduleEvent(EVENT_INTRO_2, 23000);
|
||||
events.ScheduleEvent(EVENT_INTRO_3, 42000);
|
||||
events.ScheduleEvent(EVENT_INTRO_4, 43000);
|
||||
events.ScheduleEvent(EVENT_INTRO_5, 53000);
|
||||
_introState = 1;
|
||||
}
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_INTRO_1:
|
||||
Talk(SAY_ARRIVAL1_RAG);
|
||||
break;
|
||||
case EVENT_INTRO_2:
|
||||
Talk(SAY_ARRIVAL3_RAG);
|
||||
break;
|
||||
case EVENT_INTRO_3:
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_ATTACK1H);
|
||||
break;
|
||||
case EVENT_INTRO_4:
|
||||
Talk(SAY_ARRIVAL5_RAG);
|
||||
if (Creature* executus = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_MAJORDOMO_EXECUTUS)))
|
||||
Unit::Kill(me, executus);
|
||||
break;
|
||||
case EVENT_INTRO_5:
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
|
||||
_introState = 2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_isBanished && ((_emergeTimer <= diff) || (instance->GetData(DATA_RAGNAROS_ADDS)) > 8))
|
||||
{
|
||||
//Become unbanished again
|
||||
me->RemoveAurasDueToSpell(SPELL_RAGNAROS_SUBMERGE_EFFECT);
|
||||
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC | UNIT_FLAG_NON_ATTACKABLE);
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->SetFaction(FACTION_MONSTER);
|
||||
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_EMERGE);
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
|
||||
AttackStart(target);
|
||||
instance->SetData(DATA_RAGNAROS_ADDS, 0);
|
||||
_isBanished = false;
|
||||
DoZoneInCombat();
|
||||
attackableTImer = 0;
|
||||
}
|
||||
else if (_isBanished)
|
||||
else
|
||||
{
|
||||
_emergeTimer -= diff;
|
||||
return;
|
||||
attackableTImer -= diff;
|
||||
}
|
||||
}
|
||||
|
||||
if (_isBanished && (_emergeTimer <= diff || !summons.HasEntry(NPC_SON_OF_FLAME)))
|
||||
{
|
||||
//Become unbanished again
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->SetFaction(14);
|
||||
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_EMERGE);
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
|
||||
{
|
||||
AttackStart(target);
|
||||
}
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
_isBanished = false;
|
||||
}
|
||||
else if (_isBanished)
|
||||
{
|
||||
_emergeTimer -= diff;
|
||||
return;
|
||||
}
|
||||
|
||||
events.Update(diff);
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
while (uint32 const eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
switch (eventId)
|
||||
case EVENT_ERUPTION:
|
||||
{
|
||||
case EVENT_ERUPTION:
|
||||
DoCastVictim(SPELL_ERRUPTION);
|
||||
events.ScheduleEvent(EVENT_ERUPTION, urand(20000, 45000));
|
||||
break;
|
||||
case EVENT_WRATH_OF_RAGNAROS:
|
||||
DoCastVictim(SPELL_WRATH_OF_RAGNAROS);
|
||||
if (urand(0, 1))
|
||||
Talk(SAY_WRATH);
|
||||
events.ScheduleEvent(EVENT_WRATH_OF_RAGNAROS, 25000);
|
||||
break;
|
||||
case EVENT_HAND_OF_RAGNAROS:
|
||||
DoCast(me, SPELL_HAND_OF_RAGNAROS);
|
||||
if (urand(0, 1))
|
||||
Talk(SAY_HAND);
|
||||
events.ScheduleEvent(EVENT_HAND_OF_RAGNAROS, 20000);
|
||||
break;
|
||||
case EVENT_LAVA_BURST:
|
||||
DoCastVictim(SPELL_LAVA_BURST);
|
||||
events.ScheduleEvent(EVENT_LAVA_BURST, 10000);
|
||||
break;
|
||||
case EVENT_ELEMENTAL_FIRE:
|
||||
DoCastVictim(SPELL_ELEMENTAL_FIRE);
|
||||
events.ScheduleEvent(EVENT_ELEMENTAL_FIRE, urand(10000, 14000));
|
||||
break;
|
||||
case EVENT_MAGMA_BLAST:
|
||||
if (!me->IsWithinMeleeRange(me->GetVictim()))
|
||||
DoCastVictim(SPELL_ERRUPTION);
|
||||
events.RepeatEvent(urand(20000, 45000));
|
||||
break;
|
||||
}
|
||||
case EVENT_WRATH_OF_RAGNAROS:
|
||||
{
|
||||
DoCastVictim(SPELL_WRATH_OF_RAGNAROS);
|
||||
if (urand(0, 1))
|
||||
{
|
||||
Talk(SAY_WRATH);
|
||||
}
|
||||
events.RepeatEvent(25000);
|
||||
break;
|
||||
}
|
||||
case EVENT_HAND_OF_RAGNAROS:
|
||||
{
|
||||
DoCastSelf(SPELL_HAND_OF_RAGNAROS);
|
||||
if (urand(0, 1))
|
||||
{
|
||||
Talk(SAY_HAND);
|
||||
}
|
||||
events.RepeatEvent(20000);
|
||||
break;
|
||||
}
|
||||
case EVENT_LAVA_BURST:
|
||||
{
|
||||
DoCastVictim(SPELL_LAVA_BURST);
|
||||
events.RepeatEvent(10000);
|
||||
break;
|
||||
}
|
||||
case EVENT_MAGMA_BLAST:
|
||||
{
|
||||
Unit* victim = me->GetVictim();
|
||||
if (victim && !me->IsWithinMeleeRange(victim))
|
||||
{
|
||||
DoCast(victim, SPELL_MAGMA_BLAST);
|
||||
if (!_hasYelledMagmaBurst)
|
||||
{
|
||||
DoCastVictim(SPELL_MAGMA_BLAST);
|
||||
if (!_hasYelledMagmaBurst)
|
||||
{
|
||||
Talk(SAY_MAGMABURST);
|
||||
_hasYelledMagmaBurst = true;
|
||||
}
|
||||
Talk(SAY_MAGMABURST);
|
||||
_hasYelledMagmaBurst = true;
|
||||
}
|
||||
events.ScheduleEvent(EVENT_MAGMA_BLAST, 2500);
|
||||
break;
|
||||
case EVENT_SUBMERGE:
|
||||
{
|
||||
if (!_isBanished)
|
||||
{
|
||||
// TODO: There is a spell to summon him
|
||||
me->AttackStop();
|
||||
DoResetThreat();
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
me->SetFaction(FACTION_FRIENDLY);
|
||||
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_SUBMERGED);
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_SUBMERGE);
|
||||
instance->SetData(DATA_RAGNAROS_ADDS, 0);
|
||||
|
||||
if (!_hasSubmergedOnce)
|
||||
{
|
||||
Talk(SAY_REINFORCEMENTS1);
|
||||
|
||||
// summon 8 elementals
|
||||
for (uint8 i = 0; i < 8; ++i)
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
|
||||
if (Creature* summoned = me->SummonCreature(12143, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 900000))
|
||||
summoned->AI()->AttackStart(target);
|
||||
|
||||
_hasSubmergedOnce = true;
|
||||
_isBanished = true;
|
||||
_emergeTimer = 90000;
|
||||
}
|
||||
else
|
||||
{
|
||||
Talk(SAY_REINFORCEMENTS2);
|
||||
|
||||
for (uint8 i = 0; i < 8; ++i)
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
|
||||
if (Creature* summoned = me->SummonCreature(12143, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 900000))
|
||||
summoned->AI()->AttackStart(target);
|
||||
|
||||
_isBanished = true;
|
||||
_emergeTimer = 90000;
|
||||
}
|
||||
}
|
||||
events.ScheduleEvent(EVENT_SUBMERGE, 180000);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
events.RepeatEvent(2500);
|
||||
break;
|
||||
}
|
||||
case EVENT_SUBMERGE:
|
||||
{
|
||||
if (!_isBanished)
|
||||
{
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
me->AttackStop();
|
||||
DoResetThreat();
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->SetFaction(35);
|
||||
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_SUBMERGED);
|
||||
DoCastSelf(SPELL_RAGNA_SUBMERGE_VISUAL, true);
|
||||
//me->HandleEmoteCommand(EMOTE_ONESHOT_SUBMERGE);
|
||||
SummonMinions();
|
||||
}
|
||||
events.ScheduleEvent(EVENT_SUBMERGE, 180000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
float const DEATH_ORIENTATION = 4.0f;
|
||||
uint32 attackableTImer; // used after intro
|
||||
uint32 _emergeTimer;
|
||||
uint8 _introState;
|
||||
bool _hasYelledMagmaBurst;
|
||||
bool _hasSubmergedOnce;
|
||||
bool _isBanished;
|
||||
|
||||
void SummonMinions()
|
||||
{
|
||||
Talk(_hasSubmergedOnce ? SAY_REINFORCEMENTS2 : SAY_REINFORCEMENTS1);
|
||||
|
||||
for (uint8 i = 0; i < MAX_SON_OF_FLAME_COUNT; ++i)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
|
||||
{
|
||||
if (Creature* summoned = me->SummonCreature(NPC_SON_OF_FLAME, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 900000))
|
||||
{
|
||||
summoned->AI()->AttackStart(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_isBanished = true;
|
||||
_emergeTimer = 90000;
|
||||
if (!_hasSubmergedOnce)
|
||||
{
|
||||
_hasSubmergedOnce = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
@@ -306,40 +321,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class npc_son_of_flame : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_son_of_flame() : CreatureScript("npc_SonOfFlame") { }
|
||||
|
||||
struct npc_son_of_flameAI : public ScriptedAI
|
||||
{
|
||||
npc_son_of_flameAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
instance = me->GetInstanceScript();
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override { instance->SetData(DATA_RAGNAROS_ADDS, 1); }
|
||||
|
||||
void UpdateAI(uint32 /*diff*/) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
InstanceScript* instance;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetMoltenCoreAI<npc_son_of_flameAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_ragnaros()
|
||||
{
|
||||
new boss_ragnaros();
|
||||
new npc_son_of_flame();
|
||||
}
|
||||
|
||||
@@ -15,29 +15,29 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "molten_core.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellScript.h"
|
||||
#include "molten_core.h"
|
||||
#include "Player.h"
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_ARCANE_EXPLOSION = 19712,
|
||||
SPELL_SHAZZRAH_CURSE = 19713,
|
||||
SPELL_MAGIC_GROUNDING = 19714,
|
||||
SPELL_COUNTERSPELL = 19715,
|
||||
SPELL_SHAZZRAH_GATE_DUMMY = 23138, // Teleports to and attacks a random target.
|
||||
SPELL_SHAZZRAH_GATE = 23139,
|
||||
SPELL_ARCANE_EXPLOSION = 19712,
|
||||
SPELL_SHAZZRAH_CURSE = 19713,
|
||||
SPELL_MAGIC_GROUNDING = 19714,
|
||||
SPELL_COUNTERSPELL = 19715,
|
||||
SPELL_SHAZZRAH_GATE_DUMMY = 23138, // Teleports to and attacks a random target. About every 45 seconds Shazzrah will blink to random target causing a wipe of the threat list (source: wowwwiki)
|
||||
SPELL_SHAZZRAH_GATE = 23139,
|
||||
};
|
||||
|
||||
enum Events
|
||||
{
|
||||
EVENT_ARCANE_EXPLOSION = 1,
|
||||
EVENT_ARCANE_EXPLOSION_TRIGGERED = 2,
|
||||
EVENT_SHAZZRAH_CURSE = 3,
|
||||
EVENT_MAGIC_GROUNDING = 4,
|
||||
EVENT_COUNTERSPELL = 5,
|
||||
EVENT_SHAZZRAH_GATE = 6,
|
||||
EVENT_SHAZZRAH_CURSE,
|
||||
EVENT_MAGIC_GROUNDING,
|
||||
EVENT_COUNTERSPELL,
|
||||
EVENT_SHAZZRAH_GATE,
|
||||
};
|
||||
|
||||
class boss_shazzrah : public CreatureScript
|
||||
@@ -47,66 +47,57 @@ public:
|
||||
|
||||
struct boss_shazzrahAI : public BossAI
|
||||
{
|
||||
boss_shazzrahAI(Creature* creature) : BossAI(creature, BOSS_SHAZZRAH) { }
|
||||
boss_shazzrahAI(Creature* creature) : BossAI(creature, DATA_SHAZZRAH) {}
|
||||
|
||||
void EnterCombat(Unit* target) override
|
||||
void EnterCombat(Unit* /*target*/) override
|
||||
{
|
||||
BossAI::EnterCombat(target);
|
||||
events.ScheduleEvent(EVENT_ARCANE_EXPLOSION, 6000);
|
||||
events.ScheduleEvent(EVENT_SHAZZRAH_CURSE, 10000);
|
||||
events.ScheduleEvent(EVENT_MAGIC_GROUNDING, 24000);
|
||||
events.ScheduleEvent(EVENT_COUNTERSPELL, 15000);
|
||||
events.ScheduleEvent(EVENT_SHAZZRAH_GATE, 45000);
|
||||
_EnterCombat();
|
||||
events.ScheduleEvent(EVENT_ARCANE_EXPLOSION, urand(2000, 4000));
|
||||
events.ScheduleEvent(EVENT_SHAZZRAH_CURSE, urand(7000, 11000));
|
||||
events.ScheduleEvent(EVENT_MAGIC_GROUNDING, urand(14000, 19000));
|
||||
events.ScheduleEvent(EVENT_COUNTERSPELL, urand(9000, 10000));
|
||||
events.ScheduleEvent(EVENT_SHAZZRAH_GATE, 30000);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
void ExecuteEvent(uint32 eventId) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
switch (eventId)
|
||||
{
|
||||
switch (eventId)
|
||||
case EVENT_ARCANE_EXPLOSION:
|
||||
{
|
||||
case EVENT_ARCANE_EXPLOSION:
|
||||
DoCastVictim(SPELL_ARCANE_EXPLOSION);
|
||||
events.ScheduleEvent(EVENT_ARCANE_EXPLOSION, urand(4000, 7000));
|
||||
break;
|
||||
// Triggered subsequent to using "Gate of Shazzrah".
|
||||
case EVENT_ARCANE_EXPLOSION_TRIGGERED:
|
||||
DoCastVictim(SPELL_ARCANE_EXPLOSION);
|
||||
break;
|
||||
case EVENT_SHAZZRAH_CURSE:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_SHAZZRAH_CURSE))
|
||||
DoCast(target, SPELL_SHAZZRAH_CURSE);
|
||||
events.ScheduleEvent(EVENT_SHAZZRAH_CURSE, urand(25000, 30000));
|
||||
break;
|
||||
case EVENT_MAGIC_GROUNDING:
|
||||
DoCast(me, SPELL_MAGIC_GROUNDING);
|
||||
events.ScheduleEvent(EVENT_MAGIC_GROUNDING, 35000);
|
||||
break;
|
||||
case EVENT_COUNTERSPELL:
|
||||
DoCastVictim(SPELL_COUNTERSPELL);
|
||||
events.ScheduleEvent(EVENT_COUNTERSPELL, urand(16000, 20000));
|
||||
break;
|
||||
case EVENT_SHAZZRAH_GATE:
|
||||
DoResetThreat();
|
||||
DoCastAOE(SPELL_SHAZZRAH_GATE_DUMMY);
|
||||
events.ScheduleEvent(EVENT_ARCANE_EXPLOSION_TRIGGERED, 2000);
|
||||
events.RescheduleEvent(EVENT_ARCANE_EXPLOSION, urand(3000, 6000));
|
||||
events.ScheduleEvent(EVENT_SHAZZRAH_GATE, 45000);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
DoCastVictim(SPELL_ARCANE_EXPLOSION);
|
||||
events.RepeatEvent(urand(4000, 5000));
|
||||
break;
|
||||
}
|
||||
case EVENT_SHAZZRAH_CURSE:
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_SHAZZRAH_CURSE))
|
||||
{
|
||||
DoCast(target, SPELL_SHAZZRAH_CURSE);
|
||||
}
|
||||
events.RepeatEvent(urand(23000, 26000));
|
||||
break;
|
||||
}
|
||||
case EVENT_MAGIC_GROUNDING:
|
||||
{
|
||||
DoCastSelf(SPELL_MAGIC_GROUNDING);
|
||||
events.RepeatEvent(urand(7000, 9000));
|
||||
break;
|
||||
}
|
||||
case EVENT_COUNTERSPELL:
|
||||
{
|
||||
DoCastAOE(SPELL_COUNTERSPELL);
|
||||
events.RepeatEvent(urand(15000, 18000));
|
||||
break;
|
||||
}
|
||||
case EVENT_SHAZZRAH_GATE:
|
||||
{
|
||||
DoCastAOE(SPELL_SHAZZRAH_GATE_DUMMY);
|
||||
events.RescheduleEvent(EVENT_ARCANE_EXPLOSION, urand(3000, 6000));
|
||||
events.RepeatEvent(45000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -120,7 +111,7 @@ public:
|
||||
class spell_shazzrah_gate_dummy : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_shazzrah_gate_dummy() : SpellScriptLoader("spell_shazzrah_gate_dummy") { }
|
||||
spell_shazzrah_gate_dummy() : SpellScriptLoader("spell_shazzrah_gate_dummy") {}
|
||||
|
||||
class spell_shazzrah_gate_dummy_SpellScript : public SpellScript
|
||||
{
|
||||
@@ -133,21 +124,55 @@ public:
|
||||
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
if (targets.empty())
|
||||
return;
|
||||
Unit* caster = GetCaster();
|
||||
if (!targets.empty())
|
||||
{
|
||||
targets.remove_if([caster](WorldObject const* target) -> bool
|
||||
{
|
||||
Player const* plrTarget = target->ToPlayer();
|
||||
// Should not target non player targets
|
||||
if (!plrTarget)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
WorldObject* target = Acore::Containers::SelectRandomContainerElement(targets);
|
||||
targets.clear();
|
||||
targets.push_back(target);
|
||||
// Should skip current victim
|
||||
if (caster->GetVictim() == plrTarget)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Should not target enemies within melee range
|
||||
if (plrTarget->IsWithinDistInMap(caster, caster->GetMeleeRange(plrTarget)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
if (!targets.empty())
|
||||
{
|
||||
Acore::Containers::RandomResize(targets, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void HandleScript(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (Unit* target = GetHitUnit())
|
||||
Unit* caster = GetCaster();
|
||||
Unit* target = GetHitUnit();
|
||||
|
||||
if (!caster || !target)
|
||||
{
|
||||
target->CastSpell(GetCaster(), SPELL_SHAZZRAH_GATE, true);
|
||||
if (Creature* creature = GetCaster()->ToCreature())
|
||||
creature->AI()->AttackStart(target); // Attack the target which caster will teleport to.
|
||||
target->CastSpell(caster, SPELL_SHAZZRAH_GATE, true, nullptr, nullptr, caster->GetGUID());
|
||||
caster->CastSpell(caster, SPELL_ARCANE_EXPLOSION);
|
||||
|
||||
if (Creature* creatureCaster = caster->ToCreature())
|
||||
{
|
||||
creatureCaster->getThreatMgr().resetAllAggro();
|
||||
creatureCaster->AI()->AttackStart(target); // Attack the target which caster will teleport to.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,5 +192,7 @@ public:
|
||||
void AddSC_boss_shazzrah()
|
||||
{
|
||||
new boss_shazzrah();
|
||||
|
||||
// Spells
|
||||
new spell_shazzrah_gate_dummy();
|
||||
}
|
||||
|
||||
@@ -15,17 +15,9 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* ScriptData
|
||||
SDName: Boss_Sulfuron_Harbringer
|
||||
SD%Complete: 80
|
||||
SDComment: Adds NYI
|
||||
SDCategory: Molten Core
|
||||
EndScriptData */
|
||||
|
||||
#include "molten_core.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "molten_core.h"
|
||||
|
||||
enum Spells
|
||||
{
|
||||
@@ -45,84 +37,79 @@ enum Spells
|
||||
enum Events
|
||||
{
|
||||
EVENT_DARK_STRIKE = 1,
|
||||
EVENT_DEMORALIZING_SHOUT = 2,
|
||||
EVENT_INSPIRE = 3,
|
||||
EVENT_KNOCKDOWN = 4,
|
||||
EVENT_FLAMESPEAR = 5,
|
||||
EVENT_DEMORALIZING_SHOUT,
|
||||
EVENT_INSPIRE,
|
||||
EVENT_KNOCKDOWN,
|
||||
EVENT_FLAMESPEAR,
|
||||
|
||||
EVENT_HEAL = 6,
|
||||
EVENT_SHADOW_WORD_PAIN = 7,
|
||||
EVENT_IMMOLATE = 8,
|
||||
EVENT_HEAL,
|
||||
EVENT_SHADOW_WORD_PAIN,
|
||||
EVENT_IMMOLATE,
|
||||
};
|
||||
|
||||
class boss_sulfuron : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_sulfuron() : CreatureScript("boss_sulfuron") { }
|
||||
boss_sulfuron() : CreatureScript("boss_sulfuron") {}
|
||||
|
||||
struct boss_sulfuronAI : public BossAI
|
||||
{
|
||||
boss_sulfuronAI(Creature* creature) : BossAI(creature, BOSS_SULFURON_HARBINGER)
|
||||
{
|
||||
}
|
||||
boss_sulfuronAI(Creature* creature) : BossAI(creature, DATA_SULFURON) {}
|
||||
|
||||
void EnterCombat(Unit* victim) override
|
||||
void EnterCombat(Unit* /*victim*/) override
|
||||
{
|
||||
BossAI::EnterCombat(victim);
|
||||
events.ScheduleEvent(EVENT_DARK_STRIKE, 10000);
|
||||
events.ScheduleEvent(EVENT_DEMORALIZING_SHOUT, 15000);
|
||||
events.ScheduleEvent(EVENT_INSPIRE, 13000);
|
||||
_EnterCombat();
|
||||
events.ScheduleEvent(EVENT_DARK_STRIKE, urand(4000, 7000));
|
||||
events.ScheduleEvent(EVENT_DEMORALIZING_SHOUT, urand(6000, 20000));
|
||||
events.ScheduleEvent(EVENT_INSPIRE, urand(7000, 10000));
|
||||
events.ScheduleEvent(EVENT_KNOCKDOWN, 6000);
|
||||
events.ScheduleEvent(EVENT_FLAMESPEAR, 2000);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
void ExecuteEvent(uint32 eventId) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
switch (eventId)
|
||||
{
|
||||
switch (eventId)
|
||||
case EVENT_DARK_STRIKE:
|
||||
{
|
||||
case EVENT_DARK_STRIKE:
|
||||
DoCast(me, SPELL_DARK_STRIKE);
|
||||
events.ScheduleEvent(EVENT_DARK_STRIKE, urand(15000, 18000));
|
||||
break;
|
||||
case EVENT_DEMORALIZING_SHOUT:
|
||||
DoCastVictim(SPELL_DEMORALIZING_SHOUT);
|
||||
events.ScheduleEvent(EVENT_DEMORALIZING_SHOUT, urand(15000, 20000));
|
||||
break;
|
||||
case EVENT_INSPIRE:
|
||||
{
|
||||
std::list<Creature*> healers = DoFindFriendlyMissingBuff(45.0f, SPELL_INSPIRE);
|
||||
if (!healers.empty())
|
||||
DoCast(Acore::Containers::SelectRandomContainerElement(healers), SPELL_INSPIRE);
|
||||
DoCastSelf(SPELL_DARK_STRIKE);
|
||||
events.RepeatEvent(urand(4000, 7000));
|
||||
break;
|
||||
}
|
||||
case EVENT_DEMORALIZING_SHOUT:
|
||||
{
|
||||
DoCastVictim(SPELL_DEMORALIZING_SHOUT);
|
||||
events.RepeatEvent(urand(12000, 18000));
|
||||
break;
|
||||
}
|
||||
case EVENT_INSPIRE:
|
||||
{
|
||||
std::list<Creature*> healers = DoFindFriendlyMissingBuff(45.0f, SPELL_INSPIRE);
|
||||
if (!healers.empty())
|
||||
{
|
||||
DoCast(Acore::Containers::SelectRandomContainerElement(healers), SPELL_INSPIRE);
|
||||
}
|
||||
|
||||
DoCast(me, SPELL_INSPIRE);
|
||||
events.ScheduleEvent(EVENT_INSPIRE, urand(20000, 26000));
|
||||
break;
|
||||
}
|
||||
case EVENT_KNOCKDOWN:
|
||||
DoCastVictim(SPELL_KNOCKDOWN);
|
||||
events.ScheduleEvent(EVENT_KNOCKDOWN, urand(12000, 15000));
|
||||
break;
|
||||
case EVENT_FLAMESPEAR:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
|
||||
DoCast(target, SPELL_FLAMESPEAR);
|
||||
events.ScheduleEvent(EVENT_FLAMESPEAR, urand(12000, 16000));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
DoCastSelf(SPELL_INSPIRE);
|
||||
events.RepeatEvent(urand(13000, 20000));
|
||||
break;
|
||||
}
|
||||
case EVENT_KNOCKDOWN:
|
||||
{
|
||||
DoCastVictim(SPELL_KNOCKDOWN);
|
||||
events.RepeatEvent(urand(10000, 20000));
|
||||
break;
|
||||
}
|
||||
case EVENT_FLAMESPEAR:
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
|
||||
{
|
||||
DoCast(target, SPELL_FLAMESPEAR);
|
||||
}
|
||||
events.RepeatEvent(urand(12000, 16000));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -135,13 +122,11 @@ public:
|
||||
class npc_flamewaker_priest : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_flamewaker_priest() : CreatureScript("npc_flamewaker_priest") { }
|
||||
npc_flamewaker_priest() : CreatureScript("npc_flamewaker_priest") {}
|
||||
|
||||
struct npc_flamewaker_priestAI : public ScriptedAI
|
||||
{
|
||||
npc_flamewaker_priestAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
}
|
||||
npc_flamewaker_priestAI(Creature* creature) : ScriptedAI(creature) {}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
@@ -153,45 +138,63 @@ public:
|
||||
events.Reset();
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* victim) override
|
||||
void EnterCombat(Unit* /*victim*/) override
|
||||
{
|
||||
ScriptedAI::EnterCombat(victim);
|
||||
events.ScheduleEvent(EVENT_HEAL, urand(15000, 30000));
|
||||
events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 2000);
|
||||
events.ScheduleEvent(EVENT_IMMOLATE, 8000);
|
||||
events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(2000, 4000));
|
||||
events.ScheduleEvent(EVENT_IMMOLATE, urand(3500, 6000));
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
while (uint32 const eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_HEAL:
|
||||
{
|
||||
if (Unit* target = DoSelectLowestHpFriendly(60.0f, 1))
|
||||
{
|
||||
DoCast(target, SPELL_HEAL);
|
||||
events.ScheduleEvent(EVENT_HEAL, urand(15000, 20000));
|
||||
}
|
||||
events.RepeatEvent(urand(15000, 20000));
|
||||
break;
|
||||
}
|
||||
case EVENT_SHADOW_WORD_PAIN:
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_SHADOWWORDPAIN))
|
||||
{
|
||||
DoCast(target, SPELL_SHADOWWORDPAIN);
|
||||
events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(18000, 26000));
|
||||
}
|
||||
events.RepeatEvent(urand(2500, 5000));
|
||||
break;
|
||||
}
|
||||
case EVENT_IMMOLATE:
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_IMMOLATE))
|
||||
{
|
||||
DoCast(target, SPELL_IMMOLATE);
|
||||
events.ScheduleEvent(EVENT_IMMOLATE, urand(15000, 25000));
|
||||
break;
|
||||
default:
|
||||
}
|
||||
events.RepeatEvent(urand(5000, 7000));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,51 +15,64 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* ScriptData
|
||||
SDName: Instance_Molten_Core
|
||||
SD%Complete: 0
|
||||
SDComment: Place Holder
|
||||
SDCategory: Molten Core
|
||||
EndScriptData */
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "molten_core.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "TemporarySummon.h"
|
||||
#include "molten_core.h"
|
||||
|
||||
Position const SummonPositions[10] =
|
||||
MinionData const minionData[] =
|
||||
{
|
||||
{759.542f, -1173.43f, -118.974f, 3.3048f},
|
||||
{761.652f, -1164.30f, -119.533f, 3.3919f},
|
||||
{747.323f, -1149.24f, -120.060f, 3.6629f},
|
||||
{766.734f, -1183.16f, -119.292f, 2.9889f},
|
||||
{757.364f, -1198.31f, -118.652f, 2.3095f},
|
||||
{752.349f, -1159.19f, -119.261f, 3.6032f},
|
||||
{738.015f, -1152.22f, -119.512f, 4.0792f},
|
||||
{757.246f, -1189.79f, -118.633f, 2.5333f},
|
||||
{745.916f, -1199.35f, -118.119f, 1.8932f},
|
||||
{838.510f, -829.840f, -232.000f, 2.00000f},
|
||||
{ NPC_FIRESWORN, DATA_GARR },
|
||||
{ NPC_FLAMEWALKER, DATA_GEHENNAS },
|
||||
{ NPC_FLAMEWALKER_PROTECTOR, DATA_LUCIFRON },
|
||||
{ NPC_FLAMEWALKER_PRIEST, DATA_SULFURON },
|
||||
{ NPC_FLAMEWALKER_HEALER, DATA_MAJORDOMO_EXECUTUS },
|
||||
{ NPC_FLAMEWALKER_ELITE, DATA_MAJORDOMO_EXECUTUS },
|
||||
{ 0, 0 } // END
|
||||
};
|
||||
|
||||
struct MCBossObject
|
||||
{
|
||||
uint32 bossId;
|
||||
uint32 runeId;
|
||||
uint32 circleId;
|
||||
};
|
||||
|
||||
constexpr uint8 MAX_MC_LINKED_BOSS_OBJ = 7;
|
||||
MCBossObject const linkedBossObjData[MAX_MC_LINKED_BOSS_OBJ]=
|
||||
{
|
||||
{ DATA_MAGMADAR, GO_RUNE_KRESS, GO_CIRCLE_MAGMADAR },
|
||||
{ DATA_GEHENNAS, GO_RUNE_MOHN, GO_CIRCLE_GEHENNAS },
|
||||
{ DATA_GARR, GO_RUNE_BLAZ, GO_CIRCLE_GARR },
|
||||
{ DATA_SHAZZRAH, GO_RUNE_MAZJ, GO_CIRCLE_SHAZZRAH },
|
||||
{ DATA_GEDDON, GO_RUNE_ZETH, GO_CIRCLE_GEDDON },
|
||||
{ DATA_GOLEMAGG, GO_RUNE_THERI, GO_CIRCLE_GOLEMAGG },
|
||||
{ DATA_SULFURON, GO_RUNE_KORO, GO_CIRCLE_SULFURON },
|
||||
};
|
||||
|
||||
class instance_molten_core : public InstanceMapScript
|
||||
{
|
||||
public:
|
||||
instance_molten_core() : InstanceMapScript("instance_molten_core", 409) { }
|
||||
instance_molten_core() : InstanceMapScript(MCScriptName, 409) {}
|
||||
|
||||
struct instance_molten_core_InstanceMapScript : public InstanceScript
|
||||
{
|
||||
instance_molten_core_InstanceMapScript(Map* map) : InstanceScript(map)
|
||||
{
|
||||
SetBossNumber(MAX_ENCOUNTER);
|
||||
_deadBossCount = 0;
|
||||
_ragnarosAddDeaths = 0;
|
||||
LoadMinionData(minionData);
|
||||
}
|
||||
|
||||
void OnPlayerEnter(Player* /*player*/) override
|
||||
{
|
||||
if (CheckMajordomoExecutus())
|
||||
{
|
||||
SummonMajordomoExecutus();
|
||||
}
|
||||
}
|
||||
|
||||
void OnCreatureCreate(Creature* creature) override
|
||||
@@ -67,13 +80,61 @@ public:
|
||||
switch (creature->GetEntry())
|
||||
{
|
||||
case NPC_GOLEMAGG_THE_INCINERATOR:
|
||||
_golemaggTheIncineratorGUID = creature->GetGUID();
|
||||
{
|
||||
_golemaggGUID = creature->GetGUID();
|
||||
break;
|
||||
}
|
||||
case NPC_CORE_RAGER:
|
||||
{
|
||||
_golemaggMinionsGUIDS.insert(creature->GetGUID());
|
||||
break;
|
||||
}
|
||||
case NPC_MAJORDOMO_EXECUTUS:
|
||||
{
|
||||
_majordomoExecutusGUID = creature->GetGUID();
|
||||
break;
|
||||
default:
|
||||
}
|
||||
case NPC_GARR:
|
||||
{
|
||||
_garrGUID = creature->GetGUID();
|
||||
break;
|
||||
}
|
||||
case NPC_RAGNAROS:
|
||||
{
|
||||
_ragnarosGUID = creature->GetGUID();
|
||||
break;
|
||||
}
|
||||
case NPC_FIRESWORN:
|
||||
case NPC_FLAMEWALKER:
|
||||
case NPC_FLAMEWALKER_PROTECTOR:
|
||||
case NPC_FLAMEWALKER_PRIEST:
|
||||
case NPC_FLAMEWALKER_HEALER:
|
||||
case NPC_FLAMEWALKER_ELITE:
|
||||
{
|
||||
AddMinion(creature, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnCreatureRemove(Creature* creature) override
|
||||
{
|
||||
switch (creature->GetEntry())
|
||||
{
|
||||
case NPC_FIRESWORN:
|
||||
{
|
||||
AddMinion(creature, false);
|
||||
break;
|
||||
}
|
||||
case NPC_FLAMEWALKER:
|
||||
case NPC_FLAMEWALKER_PROTECTOR:
|
||||
case NPC_FLAMEWALKER_PRIEST:
|
||||
case NPC_FLAMEWALKER_HEALER:
|
||||
case NPC_FLAMEWALKER_ELITE:
|
||||
{
|
||||
AddMinion(creature, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,64 +143,92 @@ public:
|
||||
switch (go->GetEntry())
|
||||
{
|
||||
case GO_CACHE_OF_THE_FIRELORD:
|
||||
{
|
||||
_cacheOfTheFirelordGUID = go->GetGUID();
|
||||
break;
|
||||
case GO_CIRCLE_BARON:
|
||||
_circlesGUIDs[5] = go->GetGUID();
|
||||
break;
|
||||
}
|
||||
case GO_CIRCLE_GEDDON:
|
||||
case GO_CIRCLE_GARR:
|
||||
_circlesGUIDs[3] = go->GetGUID();
|
||||
break;
|
||||
case GO_CIRCLE_GEHENNAS:
|
||||
_circlesGUIDs[2] = go->GetGUID();
|
||||
break;
|
||||
case GO_CIRCLE_GOLEMAGG:
|
||||
_circlesGUIDs[7] = go->GetGUID();
|
||||
break;
|
||||
case GO_CIRCLE_MAGMADAR:
|
||||
_circlesGUIDs[1] = go->GetGUID();
|
||||
break;
|
||||
case GO_CIRCLE_SHAZZRAH:
|
||||
_circlesGUIDs[4] = go->GetGUID();
|
||||
break;
|
||||
case GO_CIRCLE_SULFURON:
|
||||
_circlesGUIDs[6] = go->GetGUID();
|
||||
{
|
||||
for (uint8 i = 0; i < MAX_MC_LINKED_BOSS_OBJ; ++i)
|
||||
{
|
||||
if (linkedBossObjData[i].circleId != go->GetEntry())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (GetBossState(linkedBossObjData[i].bossId) == DONE)
|
||||
{
|
||||
go->DespawnOrUnsummon();
|
||||
}
|
||||
else
|
||||
{
|
||||
_circlesGUIDs[linkedBossObjData[i].bossId] = go->GetGUID();
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
}
|
||||
case GO_RUNE_KRESS:
|
||||
case GO_RUNE_MOHN:
|
||||
case GO_RUNE_BLAZ:
|
||||
case GO_RUNE_MAZJ:
|
||||
case GO_RUNE_ZETH:
|
||||
case GO_RUNE_THERI:
|
||||
case GO_RUNE_KORO:
|
||||
{
|
||||
for (uint8 i = 0; i < MAX_MC_LINKED_BOSS_OBJ; ++i)
|
||||
{
|
||||
if (linkedBossObjData[i].runeId != go->GetEntry())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (GetBossState(linkedBossObjData[i].bossId) == DONE)
|
||||
{
|
||||
go->SetGoState(GO_STATE_ACTIVE);
|
||||
}
|
||||
else
|
||||
{
|
||||
_runesGUIDs[linkedBossObjData[i].bossId] = go->GetGUID();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GO_LAVA_STEAM:
|
||||
{
|
||||
_lavaSteamGUID = go->GetGUID();
|
||||
break;
|
||||
}
|
||||
case GO_LAVA_SPLASH:
|
||||
{
|
||||
_lavaSplashGUID = go->GetGUID();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SetData(uint32 type, uint32 data) override
|
||||
{
|
||||
if (type == DATA_RAGNAROS_ADDS)
|
||||
{
|
||||
if (data == 1)
|
||||
++_ragnarosAddDeaths;
|
||||
else if (data == 0)
|
||||
_ragnarosAddDeaths = 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 GetData(uint32 type) const override
|
||||
ObjectGuid GetGuidData(uint32 type) const override
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DATA_RAGNAROS_ADDS:
|
||||
return _ragnarosAddDeaths;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ObjectGuid GetGuidData(uint32 type) const override
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case BOSS_GOLEMAGG_THE_INCINERATOR:
|
||||
return _golemaggTheIncineratorGUID;
|
||||
case BOSS_MAJORDOMO_EXECUTUS:
|
||||
case DATA_GOLEMAGG:
|
||||
return _golemaggGUID;
|
||||
case DATA_MAJORDOMO_EXECUTUS:
|
||||
return _majordomoExecutusGUID;
|
||||
case DATA_GARR:
|
||||
return _garrGUID;
|
||||
case DATA_LAVA_STEAM:
|
||||
return _lavaSteamGUID;
|
||||
case DATA_LAVA_SPLASH:
|
||||
return _lavaSplashGUID;
|
||||
case DATA_RAGNAROS:
|
||||
return _ragnarosGUID;
|
||||
}
|
||||
|
||||
return ObjectGuid::Empty;
|
||||
@@ -148,54 +237,153 @@ public:
|
||||
bool SetBossState(uint32 bossId, EncounterState state) override
|
||||
{
|
||||
if (!InstanceScript::SetBossState(bossId, state))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (state == DONE && bossId < BOSS_MAJORDOMO_EXECUTUS)
|
||||
if (CheckMajordomoExecutus())
|
||||
SummonMajordomoExecutus();
|
||||
|
||||
if (bossId == BOSS_MAJORDOMO_EXECUTUS && state == DONE)
|
||||
if (bossId == DATA_MAJORDOMO_EXECUTUS && state == DONE)
|
||||
{
|
||||
DoRespawnGameObject(_cacheOfTheFirelordGUID, 7 * DAY);
|
||||
}
|
||||
else if (bossId == DATA_GOLEMAGG)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case NOT_STARTED:
|
||||
case FAIL:
|
||||
{
|
||||
if (!_golemaggMinionsGUIDS.empty())
|
||||
{
|
||||
for (ObjectGuid const& minionGuid : _golemaggMinionsGUIDS)
|
||||
{
|
||||
Creature* minion = instance->GetCreature(minionGuid);
|
||||
if (minion && minion->isDead())
|
||||
{
|
||||
minion->Respawn();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IN_PROGRESS:
|
||||
{
|
||||
if (!_golemaggMinionsGUIDS.empty())
|
||||
{
|
||||
for (ObjectGuid const& minionGuid : _golemaggMinionsGUIDS)
|
||||
{
|
||||
if (Creature* minion = instance->GetCreature(minionGuid))
|
||||
{
|
||||
minion->AI()->DoZoneInCombat(nullptr, 150.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DONE:
|
||||
{
|
||||
if (!_golemaggMinionsGUIDS.empty())
|
||||
{
|
||||
for (ObjectGuid const& minionGuid : _golemaggMinionsGUIDS)
|
||||
{
|
||||
if (Creature* minion = instance->GetCreature(minionGuid))
|
||||
{
|
||||
minion->CastSpell(minion, SPELL_CORE_RAGER_QUIET_SUICIDE, true);
|
||||
}
|
||||
}
|
||||
_golemaggMinionsGUIDS.clear();
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Perform needed checks for Majordomu
|
||||
if (bossId < DATA_MAJORDOMO_EXECUTUS && state == DONE)
|
||||
{
|
||||
if (GameObject* circle = instance->GetGameObject(_circlesGUIDs[bossId]))
|
||||
{
|
||||
circle->DespawnOrUnsummon();
|
||||
_circlesGUIDs[bossId].Clear();
|
||||
}
|
||||
|
||||
if (GameObject* rune = instance->GetGameObject(_runesGUIDs[bossId]))
|
||||
{
|
||||
rune->SetGoState(GO_STATE_ACTIVE);
|
||||
_runesGUIDs[bossId].Clear();
|
||||
}
|
||||
|
||||
if (CheckMajordomoExecutus())
|
||||
{
|
||||
SummonMajordomoExecutus();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DoAction(int32 action) override
|
||||
{
|
||||
if (action == ACTION_RESET_MAGMADAR_ENCOUNTER)
|
||||
{
|
||||
if (Creature* golemagg = instance->GetCreature(_golemaggGUID))
|
||||
{
|
||||
golemagg->AI()->EnterEvadeMode();
|
||||
}
|
||||
|
||||
if (!_golemaggMinionsGUIDS.empty())
|
||||
{
|
||||
for (ObjectGuid const& minionGuid : _golemaggMinionsGUIDS)
|
||||
{
|
||||
if (Creature* minion = instance->GetCreature(minionGuid))
|
||||
{
|
||||
minion->AI()->EnterEvadeMode();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SummonMajordomoExecutus()
|
||||
{
|
||||
if (_majordomoExecutusGUID)
|
||||
return;
|
||||
|
||||
if (GetBossState(BOSS_MAJORDOMO_EXECUTUS) != DONE)
|
||||
if (instance->GetCreature(_majordomoExecutusGUID))
|
||||
{
|
||||
instance->SummonCreature(NPC_MAJORDOMO_EXECUTUS, SummonPositions[0]);
|
||||
instance->SummonCreature(NPC_FLAMEWAKER_HEALER, SummonPositions[1]);
|
||||
instance->SummonCreature(NPC_FLAMEWAKER_HEALER, SummonPositions[2]);
|
||||
instance->SummonCreature(NPC_FLAMEWAKER_HEALER, SummonPositions[3]);
|
||||
instance->SummonCreature(NPC_FLAMEWAKER_HEALER, SummonPositions[4]);
|
||||
instance->SummonCreature(NPC_FLAMEWAKER_ELITE, SummonPositions[5]);
|
||||
instance->SummonCreature(NPC_FLAMEWAKER_ELITE, SummonPositions[6]);
|
||||
instance->SummonCreature(NPC_FLAMEWAKER_ELITE, SummonPositions[7]);
|
||||
instance->SummonCreature(NPC_FLAMEWAKER_ELITE, SummonPositions[8]);
|
||||
return;
|
||||
}
|
||||
else if (TempSummon* summon = instance->SummonCreature(NPC_MAJORDOMO_EXECUTUS, RagnarosTelePos))
|
||||
summon->AI()->DoAction(ACTION_START_RAGNAROS_ALT);
|
||||
|
||||
instance->SummonCreature(NPC_MAJORDOMO_EXECUTUS, GetBossState(DATA_MAJORDOMO_EXECUTUS) != DONE ? MajordomoSummonPos : MajordomoRagnaros);
|
||||
}
|
||||
|
||||
bool CheckMajordomoExecutus() const
|
||||
{
|
||||
if (GetBossState(BOSS_RAGNAROS) == DONE)
|
||||
if (GetBossState(DATA_RAGNAROS) == DONE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint8 i = 0; i < DATA_MAJORDOMO_EXECUTUS; ++i)
|
||||
{
|
||||
if (i == DATA_LUCIFRON)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (uint8 i = 0; i < BOSS_MAJORDOMO_EXECUTUS; ++i)
|
||||
if (GetBossState(i) != DONE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Prevent spawning if Ragnaros is present
|
||||
if (instance->GetCreature(_ragnarosGUID))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string GetSaveData() override
|
||||
std::string GetSaveData() override
|
||||
{
|
||||
OUT_SAVE_INST_DATA;
|
||||
|
||||
@@ -206,7 +394,7 @@ public:
|
||||
return saveStream.str();
|
||||
}
|
||||
|
||||
void Load(char const* data) override
|
||||
void Load(char const* data) override
|
||||
{
|
||||
if (!data)
|
||||
{
|
||||
@@ -228,27 +416,43 @@ public:
|
||||
uint32 tmpState;
|
||||
loadStream >> tmpState;
|
||||
if (tmpState == IN_PROGRESS || tmpState > TO_BE_DECIDED)
|
||||
{
|
||||
tmpState = NOT_STARTED;
|
||||
}
|
||||
|
||||
SetBossState(i, EncounterState(tmpState));
|
||||
SetBossState(i, static_cast<EncounterState>(tmpState));
|
||||
}
|
||||
|
||||
if (CheckMajordomoExecutus())
|
||||
{
|
||||
SummonMajordomoExecutus();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
OUT_LOAD_INST_DATA_FAIL;
|
||||
}
|
||||
|
||||
OUT_LOAD_INST_DATA_COMPLETE;
|
||||
}
|
||||
|
||||
private:
|
||||
ObjectGuid _golemaggTheIncineratorGUID;
|
||||
std::unordered_map<uint32/*bossid*/, ObjectGuid/*circleGUID*/> _circlesGUIDs;
|
||||
std::unordered_map<uint32/*bossid*/, ObjectGuid/*runeGUID*/> _runesGUIDs;
|
||||
|
||||
// Golemagg encounter related
|
||||
ObjectGuid _golemaggGUID;
|
||||
GuidSet _golemaggMinionsGUIDS;
|
||||
|
||||
// Ragnaros encounter related
|
||||
ObjectGuid _ragnarosGUID;
|
||||
ObjectGuid _lavaSteamGUID;
|
||||
ObjectGuid _lavaSplashGUID;
|
||||
|
||||
ObjectGuid _majordomoExecutusGUID;
|
||||
ObjectGuid _cacheOfTheFirelordGUID;
|
||||
uint8 _deadBossCount;
|
||||
uint8 _ragnarosAddDeaths;
|
||||
std::unordered_map<uint8, ObjectGuid> _circlesGUIDs;
|
||||
ObjectGuid _garrGUID;
|
||||
ObjectGuid _magmadarGUID;
|
||||
};
|
||||
|
||||
InstanceScript* GetInstanceScript(InstanceMap* map) const override
|
||||
|
||||
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by the
|
||||
* Free Software Foundation; either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellScript.h"
|
||||
#include "molten_core.h"
|
||||
|
||||
enum Texts
|
||||
{
|
||||
EMOTE_SMOLDERING = 0,
|
||||
EMOTE_IGNITE = 1,
|
||||
};
|
||||
|
||||
enum Spells
|
||||
{
|
||||
// Ancient Core Hound
|
||||
SPELL_SERRATED_BITE = 19771,
|
||||
SPELL_PLAY_DEAD = 19822,
|
||||
SPELL_FULL_HEALTH = 17683,
|
||||
SPELL_FIRE_NOVA_VISUAL = 19823,
|
||||
SPELL_PLAY_DEAD_PACIFY = 19951, // Server side spell
|
||||
};
|
||||
|
||||
// Serrated Bites timer may be wrong
|
||||
class npc_mc_core_hound : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_mc_core_hound() : CreatureScript("npc_mc_core_hound") {}
|
||||
|
||||
struct npc_mc_core_houndAI : public CreatureAI
|
||||
{
|
||||
npc_mc_core_houndAI(Creature* creature) :
|
||||
CreatureAI(creature),
|
||||
instance(creature->GetInstanceScript()),
|
||||
serratedBiteTimer(3000)
|
||||
{
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
serratedBiteTimer = 3000;
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/) override
|
||||
{
|
||||
// Prevent receiving any extra damage if Hound is playing dead
|
||||
if (me->HasAura(SPELL_PLAY_DEAD))
|
||||
{
|
||||
damage = 0;
|
||||
return;
|
||||
}
|
||||
else if (me->GetHealth() <= damage)
|
||||
{
|
||||
damage = 0;
|
||||
Talk(EMOTE_SMOLDERING);
|
||||
DoCastSelf(SPELL_PLAY_DEAD);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING) || me->HasAura(SPELL_PLAY_DEAD))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (serratedBiteTimer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_SERRATED_BITE);
|
||||
serratedBiteTimer = urand(5000, 6000);
|
||||
}
|
||||
else
|
||||
{
|
||||
serratedBiteTimer -= diff;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
InstanceScript* instance;
|
||||
uint32 serratedBiteTimer;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetMoltenCoreAI<npc_mc_core_houndAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
// 19822 Play Dead
|
||||
class spell_mc_play_dead : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_mc_play_dead() : SpellScriptLoader("spell_mc_play_dead") { }
|
||||
|
||||
class spell_mc_play_dead_AuraScript : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_mc_play_dead_AuraScript);
|
||||
|
||||
bool Load() override
|
||||
{
|
||||
return GetCaster()->GetTypeId() == TYPEID_UNIT;
|
||||
}
|
||||
|
||||
void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
Creature* creatureTarget = GetTarget()->ToCreature();
|
||||
if (!creatureTarget)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
creatureTarget->CastSpell(creatureTarget, SPELL_PLAY_DEAD_PACIFY, true);
|
||||
creatureTarget->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
|
||||
creatureTarget->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
|
||||
//creatureTarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC);
|
||||
creatureTarget->SetReactState(REACT_PASSIVE);
|
||||
creatureTarget->SetControlled(true, UNIT_STATE_ROOT);
|
||||
|
||||
creatureTarget->AttackStop();
|
||||
}
|
||||
|
||||
void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
Creature* creatureTarget = GetTarget()->ToCreature();
|
||||
if (!creatureTarget)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
creatureTarget->RemoveAurasDueToSpell(SPELL_PLAY_DEAD_PACIFY);
|
||||
creatureTarget->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
|
||||
creatureTarget->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
|
||||
//creatureTarget->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC);
|
||||
creatureTarget->SetControlled(false, UNIT_STATE_ROOT);
|
||||
creatureTarget->SetReactState(REACT_AGGRESSIVE);
|
||||
|
||||
if (!creatureTarget->IsInCombat())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool shouldDie = true;
|
||||
std::list<Creature*> hounds;
|
||||
creatureTarget->GetCreaturesWithEntryInRange(hounds, 80.0f, NPC_CORE_HOUND);
|
||||
|
||||
// Perform lambda based check to find if there is any nearby
|
||||
if (!hounds.empty())
|
||||
{
|
||||
// Alive hound been found within 80 yards -> cancel suicide
|
||||
if (std::find_if(hounds.begin(), hounds.end(), [creatureTarget](Creature const* hound)
|
||||
{
|
||||
return creatureTarget != hound && creatureTarget->IsWithinLOSInMap(hound) && hound->IsAlive() && hound->IsInCombat() && !hound->HasAura(SPELL_PLAY_DEAD);
|
||||
}) != hounds.end())
|
||||
{
|
||||
shouldDie = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!shouldDie)
|
||||
{
|
||||
if (CreatureAI* targetAI = creatureTarget->AI())
|
||||
{
|
||||
targetAI->DoCastSelf(SPELL_FIRE_NOVA_VISUAL, true);
|
||||
targetAI->DoCastSelf(SPELL_FULL_HEALTH, true);
|
||||
targetAI->Talk(EMOTE_IGNITE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Unit::Kill(creatureTarget, creatureTarget);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
AfterEffectApply += AuraEffectApplyFn(spell_mc_play_dead_AuraScript::HandleEffectApply, EFFECT_0, SPELL_AURA_FEIGN_DEATH, AURA_EFFECT_HANDLE_REAL);
|
||||
AfterEffectRemove += AuraEffectApplyFn(spell_mc_play_dead_AuraScript::HandleEffectRemove, EFFECT_0, SPELL_AURA_FEIGN_DEATH, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
{
|
||||
return new spell_mc_play_dead_AuraScript();
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_molten_core()
|
||||
{
|
||||
// Creatures
|
||||
new npc_mc_core_hound();
|
||||
|
||||
// Spells
|
||||
new spell_mc_play_dead();
|
||||
}
|
||||
@@ -15,74 +15,107 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Player.h"
|
||||
|
||||
#ifndef DEF_MOLTEN_CORE_H
|
||||
#define DEF_MOLTEN_CORE_H
|
||||
|
||||
#include "CreatureAIImpl.h"
|
||||
|
||||
#define MCScriptName "instance_molten_core"
|
||||
|
||||
enum Encounters
|
||||
constexpr uint32 MAX_ENCOUNTER = 10;
|
||||
|
||||
enum MCData
|
||||
{
|
||||
BOSS_LUCIFRON = 0,
|
||||
BOSS_MAGMADAR = 1,
|
||||
BOSS_GEHENNAS = 2,
|
||||
BOSS_GARR = 3,
|
||||
BOSS_SHAZZRAH = 4,
|
||||
BOSS_BARON_GEDDON = 5,
|
||||
BOSS_SULFURON_HARBINGER = 6,
|
||||
BOSS_GOLEMAGG_THE_INCINERATOR = 7,
|
||||
BOSS_MAJORDOMO_EXECUTUS = 8,
|
||||
BOSS_RAGNAROS = 9,
|
||||
MAX_ENCOUNTER,
|
||||
DATA_LUCIFRON = 0,
|
||||
DATA_MAGMADAR = 1,
|
||||
DATA_GEHENNAS = 2,
|
||||
DATA_GARR = 3,
|
||||
DATA_SHAZZRAH = 4,
|
||||
DATA_GEDDON = 5,
|
||||
DATA_SULFURON = 6,
|
||||
DATA_GOLEMAGG = 7,
|
||||
DATA_MAJORDOMO_EXECUTUS = 8,
|
||||
DATA_RAGNAROS = 9,
|
||||
|
||||
// Other data
|
||||
DATA_LAVA_STEAM = 10,
|
||||
DATA_LAVA_SPLASH = 11,
|
||||
};
|
||||
|
||||
enum Actions
|
||||
enum MCActions
|
||||
{
|
||||
ACTION_START_RAGNAROS = 0,
|
||||
ACTION_START_RAGNAROS_ALT = 1,
|
||||
ACTION_START_RAGNAROS_INTRO = -1,
|
||||
ACTION_FINISH_RAGNAROS_INTRO = -2,
|
||||
ACTION_RESET_MAGMADAR_ENCOUNTER = -3, // Used when ragers are pulled far away
|
||||
ACTION_PREPARE_MAJORDOMO_RAGNA = -4,
|
||||
};
|
||||
|
||||
Position const RagnarosTelePos = {829.159f, -815.773f, -228.972f, 5.30500f};
|
||||
Position const RagnarosSummonPos = {838.510f, -829.840f, -232.000f, 2.00000f};
|
||||
|
||||
enum Creatures
|
||||
enum MCCreatures
|
||||
{
|
||||
NPC_LUCIFRON = 12118,
|
||||
NPC_MAGMADAR = 11982,
|
||||
NPC_GEHENNAS = 12259,
|
||||
NPC_GARR = 12057,
|
||||
NPC_SHAZZRAH = 12264,
|
||||
NPC_BARON_GEDDON = 12056,
|
||||
NPC_SULFURON_HARBINGER = 12098,
|
||||
NPC_GOLEMAGG_THE_INCINERATOR = 11988,
|
||||
NPC_MAJORDOMO_EXECUTUS = 12018,
|
||||
NPC_RAGNAROS = 11502,
|
||||
NPC_FLAMEWAKER_HEALER = 11663,
|
||||
NPC_FLAMEWAKER_ELITE = 11664,
|
||||
NPC_CORE_RAGER = 11672,
|
||||
NPC_CORE_HOUND = 11671,
|
||||
|
||||
// Garr
|
||||
NPC_GARR = 12057,
|
||||
NPC_FIRESWORN = 12099,
|
||||
|
||||
// Gehennas
|
||||
NPC_GEHENNAS = 12259,
|
||||
NPC_FLAMEWALKER = 11661,
|
||||
|
||||
// Golemagg
|
||||
NPC_GOLEMAGG_THE_INCINERATOR = 11988,
|
||||
NPC_CORE_RAGER = 11672,
|
||||
|
||||
// Lucifron
|
||||
NPC_LUCIFRON = 12118,
|
||||
NPC_FLAMEWALKER_PROTECTOR = 12119,
|
||||
|
||||
// Sulfuron
|
||||
NPC_SULFURON_HARBINGER = 12098,
|
||||
NPC_FLAMEWALKER_PRIEST = 11662,
|
||||
|
||||
// Majordomo
|
||||
NPC_MAJORDOMO_EXECUTUS = 12018,
|
||||
NPC_FLAMEWALKER_HEALER = 11663,
|
||||
NPC_FLAMEWALKER_ELITE = 11664,
|
||||
};
|
||||
|
||||
enum GameObjects
|
||||
enum MCGameObjects
|
||||
{
|
||||
GO_CACHE_OF_THE_FIRELORD = 179703,
|
||||
GO_CIRCLE_SULFURON = 178187,
|
||||
GO_CIRCLE_BARON = 178188,
|
||||
GO_CIRCLE_GEDDON = 178188,
|
||||
GO_CIRCLE_SHAZZRAH = 178189,
|
||||
GO_CIRCLE_GOLEMAGG = 178190,
|
||||
GO_CIRCLE_GARR = 178191,
|
||||
GO_CIRCLE_MAGMADAR = 178192,
|
||||
GO_CIRCLE_GEHENNAS = 178193,
|
||||
|
||||
GO_RUNE_KRESS = 176956, // Magmadar
|
||||
GO_RUNE_MOHN = 176957, // Gehennas
|
||||
GO_RUNE_BLAZ = 176955, // Garr
|
||||
GO_RUNE_MAZJ = 176953, // Shazzrah
|
||||
GO_RUNE_ZETH = 176952, // Geddon
|
||||
GO_RUNE_THERI = 176954, // Golemagg
|
||||
GO_RUNE_KORO = 176951, // Sulfuron
|
||||
|
||||
// Ragnaros event related
|
||||
GO_LAVA_STEAM = 178107,
|
||||
GO_LAVA_SPLASH = 178108,
|
||||
};
|
||||
|
||||
enum Data
|
||||
enum MCSpells
|
||||
{
|
||||
DATA_RAGNAROS_ADDS = 0,
|
||||
SPELL_CORE_RAGER_QUIET_SUICIDE = 3617, // Server side
|
||||
};
|
||||
|
||||
extern Position const MajordomoRagnaros; // Teleport location to Ragnaros summons area
|
||||
extern Position const MajordomoSummonPos; // Majordomo summon position (battle)
|
||||
|
||||
template <class AI, class T>
|
||||
inline AI* GetMoltenCoreAI(T* obj)
|
||||
{
|
||||
|
||||
@@ -74,7 +74,8 @@ void AddSC_boss_selin_fireheart();
|
||||
void AddSC_boss_vexallus();
|
||||
void AddSC_boss_priestess_delrissa();
|
||||
void AddSC_instance_magisters_terrace();
|
||||
void AddSC_boss_lucifron(); //Molten core
|
||||
void AddSC_molten_core(); //Molten core
|
||||
void AddSC_boss_lucifron();
|
||||
void AddSC_boss_magmadar();
|
||||
void AddSC_boss_gehennas();
|
||||
void AddSC_boss_garr();
|
||||
@@ -210,7 +211,8 @@ void AddEasternKingdomsScripts()
|
||||
AddSC_boss_vexallus();
|
||||
AddSC_boss_priestess_delrissa();
|
||||
AddSC_instance_magisters_terrace();
|
||||
AddSC_boss_lucifron(); //Molten core
|
||||
AddSC_molten_core(); // Molten core
|
||||
AddSC_boss_lucifron();
|
||||
AddSC_boss_magmadar();
|
||||
AddSC_boss_gehennas();
|
||||
AddSC_boss_garr();
|
||||
|
||||
Reference in New Issue
Block a user