Scripts/HallsOfOrigination: Added script for Earthrager Ptah.

ToDo: Fix spell Sand Vortex on Heroic difficulty.
Note: Feedback needed.
This commit is contained in:
Subv
2012-12-25 19:35:13 -05:00
parent cfb6a1b4d5
commit 587710feb5
7 changed files with 431 additions and 1 deletions

View File

@@ -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")

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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())