mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-25 19:31:59 +01:00
Scripts/HallsOfOrigination: Added script for Earthrager Ptah.
ToDo: Fix spell Sand Vortex on Heroic difficulty. Note: Feedback needed.
This commit is contained in:
@@ -111,8 +111,9 @@ set(scripts_STAT_SRCS
|
||||
Kalimdor/OnyxiasLair/onyxias_lair.h
|
||||
Kalimdor/OnyxiasLair/instance_onyxias_lair.cpp
|
||||
Kalimdor/HallsOfOrigination/halls_of_origination.h
|
||||
Kalimdor/HallsOfOrigination/boss_temple_guardian_anhuur.cpp
|
||||
Kalimdor/HallsOfOrigination/instance_halls_of_origination.cpp
|
||||
Kalimdor/HallsOfOrigination/boss_temple_guardian_anhuur.cpp
|
||||
Kalimdor/HallsOfOrigination/boss_earthrager_ptah.cpp
|
||||
)
|
||||
|
||||
message(" -> Prepared: Kalimdor")
|
||||
|
||||
@@ -0,0 +1,350 @@
|
||||
#include "ObjectMgr.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellAuras.h"
|
||||
#include "halls_of_origination.h"
|
||||
#include "Player.h"
|
||||
|
||||
enum Texts
|
||||
{
|
||||
SAY_AGGRO = 0,
|
||||
SAY_DEATH = 1,
|
||||
};
|
||||
|
||||
enum Events
|
||||
{
|
||||
EVENT_RAGING_SMASH = 1,
|
||||
EVENT_FLAME_BOLT = 2,
|
||||
EVENT_EARTH_SPIKE = 3,
|
||||
EVENT_PTAH_EXPLODE = 4,
|
||||
EVENT_QUICKSAND = 5,
|
||||
};
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_RAGING_SMASH = 83650,
|
||||
SPELL_FLAME_BOLT = 77370,
|
||||
SPELL_EARTH_SPIKE_WARN = 94974,
|
||||
SPELL_EARTH_SPIKE_ERUPT = 75339,
|
||||
|
||||
SPELL_PTAH_EXPLOSION = 75519,
|
||||
SPELL_SANDSTORM = 75491,
|
||||
|
||||
SPELL_SUMMON_QUICKSAND = 75550, // Spell not in DBC, no SMSG_SPELL_START/GO for it
|
||||
|
||||
SPELL_BEETLE_BURROW = 75463,
|
||||
|
||||
SPELL_SUMMON_JEWELED_SCARAB = 75462,
|
||||
SPELL_SUMMON_DUSTBONE_HORROR = 75521,
|
||||
};
|
||||
|
||||
enum Phases
|
||||
{
|
||||
PHASE_NORMAL = 1,
|
||||
PHASE_DISPERSE = 2,
|
||||
|
||||
PHASE_MASK_DISPERSE = (1 << PHASE_DISPERSE),
|
||||
PHASE_MASK_NORMAL = (1 << PHASE_NORMAL),
|
||||
};
|
||||
|
||||
enum PtahData
|
||||
{
|
||||
DATA_SUMMON_DEATHS = 0
|
||||
};
|
||||
|
||||
class SummonScarab : public BasicEvent
|
||||
{
|
||||
public:
|
||||
SummonScarab(Unit* owner, InstanceScript* instance) : _owner(owner), _instance(instance) { }
|
||||
|
||||
bool Execute(uint64 execTime, uint32 /*diff*/)
|
||||
{
|
||||
if (!_instance || _instance->GetBossState(DATA_EARTHRAGER_PTAH) != IN_PROGRESS)
|
||||
return true; // delete event
|
||||
|
||||
_owner->CastSpell(_owner, SPELL_SUMMON_JEWELED_SCARAB);
|
||||
_owner->RemoveAurasDueToSpell(SPELL_BEETLE_BURROW);
|
||||
return true;
|
||||
}
|
||||
protected:
|
||||
InstanceScript* _instance;
|
||||
Unit* _owner;
|
||||
};
|
||||
|
||||
class EruptEarthSpike : public BasicEvent
|
||||
{
|
||||
public:
|
||||
EruptEarthSpike(Unit* caster, WorldLocation const target) : _caster(caster), _target(target) { }
|
||||
|
||||
bool Execute(uint64 execTime, uint32 /*diff*/)
|
||||
{
|
||||
_caster->CastSpell(_target.GetPositionX(), _target.GetPositionY(), _target.GetPositionZ(), SPELL_EARTH_SPIKE_ERUPT, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
Unit* _caster;
|
||||
WorldLocation const _target;
|
||||
};
|
||||
|
||||
class boss_earthrager_ptah : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_earthrager_ptah() : CreatureScript("boss_earthrager_ptah") { }
|
||||
|
||||
struct boss_earthrager_ptahAI : public BossAI
|
||||
{
|
||||
boss_earthrager_ptahAI(Creature* creature) : BossAI(creature, DATA_EARTHRAGER_PTAH), _summonDeaths(0), _hasDispersed(false) { }
|
||||
|
||||
void Cleanup()
|
||||
{
|
||||
std::list<Creature*> units;
|
||||
|
||||
GetCreatureListWithEntryInGrid(units, me, NPC_DUSTBONE_HORROR, 100.0f);
|
||||
for (std::list<Creature*>::iterator itr = units.begin(); itr != units.end(); ++itr)
|
||||
(*itr)->DespawnOrUnsummon();
|
||||
|
||||
GetCreatureListWithEntryInGrid(units, me, NPC_JEWELED_SCARAB, 100.0f);
|
||||
for (std::list<Creature*>::iterator itr = units.begin(); itr != units.end(); ++itr)
|
||||
(*itr)->DespawnOrUnsummon();
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
_summonDeaths = 0;
|
||||
_hasDispersed = false;
|
||||
Cleanup();
|
||||
_Reset();
|
||||
events.SetPhase(PHASE_NORMAL);
|
||||
events.ScheduleEvent(EVENT_RAGING_SMASH, urand(7000, 12000), 0, PHASE_NORMAL);
|
||||
events.ScheduleEvent(EVENT_FLAME_BOLT, 15000, 0, PHASE_NORMAL);
|
||||
events.ScheduleEvent(EVENT_EARTH_SPIKE, urand(16000, 21000), 0, PHASE_NORMAL);
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* /*attacker*/, uint32& damage)
|
||||
{
|
||||
if (me->HealthBelowPctDamaged(50, damage) && (events.GetPhaseMask() & PHASE_MASK_NORMAL) && !_hasDispersed)
|
||||
{
|
||||
events.SetPhase(PHASE_DISPERSE);
|
||||
_hasDispersed = true;
|
||||
|
||||
me->AttackStop();
|
||||
DoCast(me, SPELL_SANDSTORM);
|
||||
events.ScheduleEvent(EVENT_PTAH_EXPLODE, 6000, 0, PHASE_DISPERSE);
|
||||
events.ScheduleEvent(EVENT_QUICKSAND, 10000, 0, PHASE_DISPERSE);
|
||||
|
||||
std::list<Creature*> stalkers;
|
||||
GetCreatureListWithEntryInGrid(stalkers, me, NPC_BEETLE_STALKER, 100.0f);
|
||||
std::list<Creature*> beetlers = stalkers;
|
||||
|
||||
Trinity::Containers::RandomResizeList(beetlers, 9); // Holds the summoners of Jeweled Scarab
|
||||
|
||||
for (std::list<Creature*>::iterator itr = beetlers.begin(); itr != beetlers.end(); ++itr)
|
||||
{
|
||||
stalkers.remove((*itr)); // Remove it to prevent a single trigger from spawning multiple npcs.
|
||||
(*itr)->CastSpell((*itr), SPELL_BEETLE_BURROW); // Cast visual
|
||||
// Summon after 5 seconds.
|
||||
(*itr)->m_Events.AddEvent(new SummonScarab((*itr), instance), (*itr)->m_Events.CalculateTime(5000));
|
||||
}
|
||||
|
||||
Trinity::Containers::RandomResizeList(stalkers, 2); // Holds the summoners of Dustbone Horror
|
||||
|
||||
for (std::list<Creature*>::iterator itr = stalkers.begin(); itr != stalkers.end(); ++itr)
|
||||
(*itr)->CastSpell((*itr), SPELL_SUMMON_DUSTBONE_HORROR);
|
||||
}
|
||||
}
|
||||
|
||||
void SetData(uint32 index, uint32 value)
|
||||
{
|
||||
if (index == DATA_SUMMON_DEATHS)
|
||||
{
|
||||
++_summonDeaths;
|
||||
if (_summonDeaths == 11) // All summons died
|
||||
{
|
||||
me->RemoveAurasDueToSpell(SPELL_PTAH_EXPLOSION);
|
||||
events.SetPhase(PHASE_NORMAL);
|
||||
events.ScheduleEvent(EVENT_RAGING_SMASH, urand(7000, 12000), 0, PHASE_NORMAL);
|
||||
events.ScheduleEvent(EVENT_FLAME_BOLT, 15000, 0, PHASE_NORMAL);
|
||||
events.ScheduleEvent(EVENT_EARTH_SPIKE, urand(16000, 21000), 0, PHASE_NORMAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/)
|
||||
{
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1);
|
||||
Talk(SAY_AGGRO);
|
||||
_EnterCombat();
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/)
|
||||
{
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
Talk(SAY_DEATH);
|
||||
_JustDied();
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
void JustReachedHome()
|
||||
{
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
_JustReachedHome();
|
||||
instance->SetBossState(DATA_EARTHRAGER_PTAH, FAIL);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 const diff)
|
||||
{
|
||||
if (!UpdateVictim() || !CheckInRoom())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_RAGING_SMASH:
|
||||
DoCastVictim(SPELL_RAGING_SMASH);
|
||||
events.ScheduleEvent(EVENT_RAGING_SMASH, urand(7000, 12000), 0, PHASE_NORMAL);
|
||||
break;
|
||||
case EVENT_FLAME_BOLT:
|
||||
DoCast(me, SPELL_FLAME_BOLT);
|
||||
events.ScheduleEvent(EVENT_FLAME_BOLT, 15000, 0, PHASE_NORMAL);
|
||||
break;
|
||||
case EVENT_EARTH_SPIKE:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
|
||||
DoCast(target, SPELL_EARTH_SPIKE_WARN);
|
||||
events.ScheduleEvent(EVENT_EARTH_SPIKE, urand(16000, 21000), 0, PHASE_NORMAL);
|
||||
break;
|
||||
case EVENT_PTAH_EXPLODE:
|
||||
DoCast(me, SPELL_PTAH_EXPLOSION);
|
||||
break;
|
||||
case EVENT_QUICKSAND:
|
||||
// Spell not in DBC, it is not cast either, according to sniffs
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
|
||||
if (Creature* quicksand = me->SummonCreature(NPC_QUICKSAND, *target))
|
||||
quicksand->SetUInt32Value(UNIT_CREATED_BY_SPELL, SPELL_SUMMON_QUICKSAND);
|
||||
events.ScheduleEvent(EVENT_QUICKSAND, 10000, 0, PHASE_DISPERSE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (events.GetPhaseMask() & PHASE_MASK_NORMAL) // Do not melee in the disperse phase
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
protected:
|
||||
bool _hasDispersed;
|
||||
uint8 _summonDeaths;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const
|
||||
{
|
||||
return GetHallsOfOriginationAI<boss_earthrager_ptahAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_earthrager_ptah_flame_bolt : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_earthrager_ptah_flame_bolt() : SpellScriptLoader("spell_earthrager_ptah_flame_bolt") { }
|
||||
|
||||
class spell_earthrager_ptah_flame_bolt_SpellScript : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_earthrager_ptah_flame_bolt_SpellScript);
|
||||
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
Trinity::Containers::RandomResizeList(targets, GetCaster()->GetMap()->IsHeroic() ? 3 : 2);
|
||||
}
|
||||
|
||||
void Register()
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_earthrager_ptah_flame_bolt_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const
|
||||
{
|
||||
return new spell_earthrager_ptah_flame_bolt_SpellScript();
|
||||
}
|
||||
};
|
||||
|
||||
class spell_earthrager_ptah_earth_spike : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_earthrager_ptah_earth_spike() : SpellScriptLoader("spell_earthrager_ptah_earth_spike") { }
|
||||
|
||||
class spell_earthrager_ptah_earth_spike_SpellScript : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_earthrager_ptah_earth_spike_SpellScript);
|
||||
|
||||
void Launch(SpellEffIndex index)
|
||||
{
|
||||
PreventHitDefaultEffect(index);
|
||||
// Erupt the spike in 4 seconds.
|
||||
GetCaster()->m_Events.AddEvent(new EruptEarthSpike(GetCaster(), *GetExplTargetDest()), GetCaster()->m_Events.CalculateTime(4000));
|
||||
}
|
||||
|
||||
void Register()
|
||||
{
|
||||
OnEffectHit += SpellEffectFn(spell_earthrager_ptah_earth_spike_SpellScript::Launch, EFFECT_0, SPELL_EFFECT_TRIGGER_MISSILE);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const
|
||||
{
|
||||
return new spell_earthrager_ptah_earth_spike_SpellScript();
|
||||
}
|
||||
};
|
||||
|
||||
class spell_earthrager_ptah_explosion : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_earthrager_ptah_explosion() : SpellScriptLoader("spell_earthrager_ptah_explosion") { }
|
||||
|
||||
class spell_earthrager_ptah_explosion_AuraScript : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_earthrager_ptah_explosion_AuraScript);
|
||||
|
||||
void SetFlags(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (Unit* ptah = GetCaster())
|
||||
{
|
||||
ptah->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_UNK_29 | UNIT_FLAG_UNK_31);
|
||||
ptah->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveFlags(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (Unit* ptah = GetCaster())
|
||||
{
|
||||
ptah->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_UNK_29 | UNIT_FLAG_UNK_31);
|
||||
ptah->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
|
||||
}
|
||||
}
|
||||
|
||||
void Register()
|
||||
{
|
||||
OnEffectApply += AuraEffectApplyFn(spell_earthrager_ptah_explosion_AuraScript::SetFlags, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
|
||||
OnEffectRemove += AuraEffectRemoveFn(spell_earthrager_ptah_explosion_AuraScript::RemoveFlags, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const
|
||||
{
|
||||
return new spell_earthrager_ptah_explosion_AuraScript();
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_earthrager_ptah()
|
||||
{
|
||||
new boss_earthrager_ptah();
|
||||
new spell_earthrager_ptah_flame_bolt();
|
||||
new spell_earthrager_ptah_earth_spike();
|
||||
new spell_earthrager_ptah_explosion();
|
||||
}
|
||||
@@ -46,6 +46,12 @@ enum Creatures
|
||||
BOSS_TEMPLE_GUARDIAN_ANHUUR = 39425,
|
||||
NPC_CAVE_IN_STALKER = 40183,
|
||||
NPC_SEARING_LIGHT = 40283,
|
||||
|
||||
BOSS_EARTHRAGER_PTAH = 39428,
|
||||
NPC_BEETLE_STALKER = 40459, // Summons both Jeweled Scarab and Dustbone Horror
|
||||
NPC_JEWELED_SCARAB = 40458,
|
||||
NPC_DUSTBONE_HORROR = 40450,
|
||||
NPC_QUICKSAND = 40503, // Summoned by a spell not in dbc (75550)
|
||||
};
|
||||
|
||||
enum GameObjects
|
||||
|
||||
@@ -75,6 +75,18 @@ class instance_halls_of_origination : public InstanceMapScript
|
||||
}
|
||||
}
|
||||
|
||||
void OnGameObjectRemove(GameObject* go)
|
||||
{
|
||||
switch (go->GetEntry())
|
||||
{
|
||||
case GO_ANHUURS_BRIDGE:
|
||||
case GO_DOODAD_ULDUM_ELEVATOR_COL01:
|
||||
case GO_ANHUURS_DOOR:
|
||||
AddDoor(go, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OnCreatureCreate(Creature* creature)
|
||||
{
|
||||
switch (creature->GetEntry())
|
||||
|
||||
Reference in New Issue
Block a user