Merge pull request #6 from liyunfan1223/revert-5-Playerbot

Revert "Split Ulduar's script files"
This commit is contained in:
Yunfan Li
2024-03-12 12:46:05 +08:00
committed by GitHub
28 changed files with 18967 additions and 19209 deletions

View File

@@ -15,7 +15,6 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "boss_assembly_of_iron.h"
#include "AchievementCriteriaScript.h"
#include "CreatureScript.h"
#include "Player.h"
@@ -25,6 +24,123 @@
#include "SpellScriptLoader.h"
#include "ulduar.h"
enum AssemblySpells
{
// Any boss
SPELL_SUPERCHARGE = 61920,
SPELL_BERSERK = 47008,
// Steelbreaker
SPELL_HIGH_VOLTAGE_10 = 61890,
SPELL_HIGH_VOLTAGE_25 = 63498,
SPELL_FUSION_PUNCH_10 = 61903,
SPELL_FUSION_PUNCH_25 = 63493,
SPELL_STATIC_DISRUPTION_10 = 61911,
SPELL_STATIC_DISRUPTION_25 = 63495,
SPELL_OVERWHELMING_POWER_10 = 64637,
SPELL_OVERWHELMING_POWER_25 = 61888,
SPELL_ELECTRICAL_CHARGE = 61902,
// Runemaster Molgeim
SPELL_SHIELD_OF_RUNES_BUFF = 62277,
SPELL_SHIELD_OF_RUNES_10 = 62274,
SPELL_SHIELD_OF_RUNES_25 = 63489,
SPELL_RUNE_OF_POWER = 61973,
SPELL_RUNE_OF_DEATH_10 = 62269,
SPELL_RUNE_OF_DEATH_25 = 63490,
SPELL_RUNE_OF_SUMMONING = 62273,
SPELL_RUNE_OF_SUMMONING_SUMMON = 62020,
SPELL_LIGHTNING_BLAST_10 = 62054,
SPELL_LIGHTNING_BLAST_25 = 63491,
CREATURE_LIGHTNING_ELEMENTAL = 32958,
CREATURE_RUNE_OF_SUMMONING = 33051,
SPELL_RUNE_OF_POWER_OOC_CHANNEL = 61975,
// Stormcaller Brundir
SPELL_CHAIN_LIGHTNING_10 = 61879,
SPELL_CHAIN_LIGHTNING_25 = 63479,
SPELL_OVERLOAD_10 = 61869,
SPELL_OVERLOAD_25 = 63481,
SPELL_LIGHTNING_WHIRL_10 = 61915,
SPELL_LIGHTNING_WHIRL_25 = 63483,
SPELL_LIGHTNING_TENDRILS_10 = 61887,
SPELL_LIGHTNING_TENDRILS_25 = 63486,
SPELL_STORMSHIELD = 64187,
SPELL_LIGHTNING_CHANNEL_PRE = 61942,
};
#define SPELL_HIGH_VOLTAGE RAID_MODE(SPELL_HIGH_VOLTAGE_10, SPELL_HIGH_VOLTAGE_25)
#define SPELL_FUSION_PUNCH RAID_MODE(SPELL_FUSION_PUNCH_10, SPELL_FUSION_PUNCH_25)
#define SPELL_STATIC_DISRUPTION RAID_MODE(SPELL_STATIC_DISRUPTION_10, SPELL_STATIC_DISRUPTION_25)
#define SPELL_OVERWHELMING_POWER RAID_MODE(SPELL_OVERWHELMING_POWER_10, SPELL_OVERWHELMING_POWER_25)
#define SPELL_SHIELD_OF_RUNES RAID_MODE(SPELL_SHIELD_OF_RUNES_10, SPELL_SHIELD_OF_RUNES_25)
#define SPELL_RUNE_OF_DEATH RAID_MODE(SPELL_RUNE_OF_DEATH_10, SPELL_RUNE_OF_DEATH_25)
#define SPELL_LIGHTNING_BLAST RAID_MODE(SPELL_LIGHTNING_BLAST_10, SPELL_LIGHTNING_BLAST_25)
#define SPELL_CHAIN_LIGHTNING RAID_MODE(SPELL_CHAIN_LIGHTNING_10, SPELL_CHAIN_LIGHTNING_25)
#define SPELL_OVERLOAD RAID_MODE(SPELL_OVERLOAD_10, SPELL_OVERLOAD_25)
#define SPELL_LIGHTNING_WHIRL RAID_MODE(SPELL_LIGHTNING_WHIRL_10, SPELL_LIGHTNING_WHIRL_25)
#define SPELL_LIGHTNING_TENDRILS RAID_MODE(SPELL_LIGHTNING_TENDRILS_10, SPELL_LIGHTNING_TENDRILS_25)
enum eEnums
{
// Steelbreaker
EVENT_FUSION_PUNCH = 1,
EVENT_STATIC_DISRUPTION = 2,
EVENT_OVERWHELMING_POWER = 3,
//EVENT_CHECK_MAIN_TANK = 4,
// Molgeim
EVENT_RUNE_OF_POWER = 11,
EVENT_SHIELD_OF_RUNES = 12,
EVENT_RUNE_OF_DEATH = 13,
EVENT_RUNE_OF_SUMMONING = 14,
EVENT_LIGHTNING_BLAST = 15,
// Brundir
EVENT_CHAIN_LIGHTNING = 21,
EVENT_OVERLOAD = 22,
EVENT_LIGHTNING_WHIRL = 23,
EVENT_LIGHTNING_TENDRILS = 24,
EVENT_LIGHTNING_LAND = 25,
EVENT_LAND_LAND = 26,
EVENT_LIGHTNING_FLIGHT = 27,
EVENT_ENRAGE = 30
};
enum AssemblyYells
{
SAY_STEELBREAKER_AGGRO = 0,
SAY_STEELBREAKER_SLAY = 1,
SAY_STEELBREAKER_POWER = 2,
SAY_STEELBREAKER_DEATH = 3,
SAY_STEELBREAKER_ENCOUNTER_DEFEATED = 4,
SAY_STEELBREAKER_BERSERK = 5,
SAY_MOLGEIM_AGGRO = 0,
SAY_MOLGEIM_SLAY = 1,
SAY_MOLGEIM_RUNE_DEATH = 2,
SAY_MOLGEIM_SUMMON = 3,
SAY_MOLGEIM_DEATH = 4,
SAY_MOLGEIM_ENCOUNTER_DEFEATED = 5,
SAY_MOLGEIM_BERSERK = 6,
SAY_BRUNDIR_AGGRO = 0,
SAY_BRUNDIR_SLAY = 1,
SAY_BRUNDIR_SPECIAL = 2,
SAY_BRUNDIR_FLIGHT = 3,
SAY_BRUNDIR_DEATH = 4,
SAY_BRUNDIR_ENCOUNTER_DEFEATED = 5,
SAY_BRUNDIR_BERSERK = 6,
EMOTE_BRUNDIR_OVERLOAD = 7
};
enum Misc
{
ACTION_ADD_CHARGE = 1,
POINT_CHANNEL_STEELBREAKER = 1
};
bool IsEncounterComplete(InstanceScript* pInstance, Creature* me)
{
if (!pInstance || !me)
@@ -77,6 +193,783 @@ void RestoreAssemblyHealth(ObjectGuid guid1, ObjectGuid guid2, Creature* me)
cr2->SetHealth(cr2->GetMaxHealth());
}
class boss_steelbreaker : public CreatureScript
{
public:
boss_steelbreaker() : CreatureScript("boss_steelbreaker") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return GetUlduarAI<boss_steelbreakerAI>(pCreature);
}
struct boss_steelbreakerAI : public ScriptedAI
{
boss_steelbreakerAI(Creature* c) : ScriptedAI(c)
{
pInstance = c->GetInstanceScript();
}
EventMap events;
InstanceScript* pInstance;
uint8 _phase;
void Reset() override
{
me->SetLootMode(0);
RespawnAssemblyOfIron(pInstance, me);
_phase = 0;
events.Reset();
if (pInstance)
pInstance->SetData(TYPE_ASSEMBLY, NOT_STARTED);
}
void JustReachedHome() override
{
me->setActive(false);
me->RemoveAllAuras();
}
void JustEngagedWith(Unit* who) override
{
if (pInstance)
pInstance->SetData(TYPE_ASSEMBLY, IN_PROGRESS);
me->setActive(true);
me->SetInCombatWithZone();
me->CastSpell(me, SPELL_HIGH_VOLTAGE, true);
events.ScheduleEvent(EVENT_ENRAGE, 15min);
UpdatePhase();
if (!pInstance)
return;
if (Creature* boss = ObjectAccessor::GetCreature(*me, pInstance->GetGuidData(DATA_STEELBREAKER + urand(0, 2))))
{
switch (boss->GetEntry())
{
case NPC_STEELBREAKER:
boss->AI()->Talk(SAY_STEELBREAKER_AGGRO);
break;
case NPC_MOLGEIM:
boss->AI()->Talk(SAY_MOLGEIM_AGGRO);
break;
case NPC_BRUNDIR:
boss->AI()->Talk(SAY_BRUNDIR_AGGRO);
break;
}
}
for (uint8 i = 0; i < 3; ++i)
if (Creature* boss = ObjectAccessor::GetCreature(*me, pInstance->GetGuidData(DATA_STEELBREAKER + i)))
if (!boss->IsInCombat())
boss->AI()->AttackStart(who);
}
void UpdatePhase()
{
if (_phase >= 3)
return;
++_phase;
switch (_phase)
{
case 1:
events.RescheduleEvent(EVENT_FUSION_PUNCH, 15s);
break;
case 2:
events.RescheduleEvent(EVENT_STATIC_DISRUPTION, 20s);
break;
case 3:
me->ResetLootMode();
events.RescheduleEvent(EVENT_OVERWHELMING_POWER, 8s);
break;
}
}
void JustDied(Unit* /*Killer*/) override
{
if (!pInstance)
return;
if (IsEncounterComplete(pInstance, me))
{
pInstance->SetData(TYPE_ASSEMBLY, DONE);
me->CastSpell(me, 65195, true); // credit
Talk(SAY_STEELBREAKER_ENCOUNTER_DEFEATED);
}
else
{
RestoreAssemblyHealth(pInstance->GetGuidData(DATA_BRUNDIR), pInstance->GetGuidData(DATA_MOLGEIM), me);
me->CastSpell(me, SPELL_SUPERCHARGE, true);
Talk(SAY_STEELBREAKER_DEATH);
}
}
void KilledUnit(Unit* who) override
{
if (who->GetTypeId() != TYPEID_PLAYER)
return;
if (_phase == 3)
me->CastSpell(me, SPELL_ELECTRICAL_CHARGE, true);
Talk(SAY_STEELBREAKER_SLAY);
}
void DoAction(int32 param) override
{
if (param == ACTION_ADD_CHARGE)
me->CastSpell(me, SPELL_ELECTRICAL_CHARGE, true);
}
void SpellHit(Unit* /*caster*/, SpellInfo const* spellInfo) override
{
if (spellInfo->Id == SPELL_SUPERCHARGE)
UpdatePhase();
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch(events.ExecuteEvent())
{
case EVENT_FUSION_PUNCH:
me->CastSpell(me->GetVictim(), SPELL_FUSION_PUNCH, false);
events.Repeat(15s, 20s);
break;
case EVENT_STATIC_DISRUPTION:
if (Unit* pTarget = SelectTarget(SelectTargetMethod::MinDistance, 0, 0, true))
me->CastSpell(pTarget, SPELL_STATIC_DISRUPTION, false);
events.Repeat(20s, 40s);
break;
case EVENT_OVERWHELMING_POWER:
Talk(SAY_STEELBREAKER_POWER);
me->CastSpell(me->GetVictim(), SPELL_OVERWHELMING_POWER, true);
events.RepeatEvent(RAID_MODE(61000, 36000));
break;
case EVENT_ENRAGE:
Talk(SAY_STEELBREAKER_BERSERK);
me->CastSpell(me, SPELL_BERSERK, true);
break;
}
DoMeleeAttackIfReady();
}
};
};
class CastRunesEvent : public BasicEvent
{
public:
CastRunesEvent(Creature& owner) : BasicEvent(), _owner(owner) { }
bool Execute(uint64 /*eventTime*/, uint32 /*diff*/) override
{
if (!_owner.IsInCombat())
_owner.CastSpell(&_owner, SPELL_RUNE_OF_POWER_OOC_CHANNEL, true);
return true;
}
private:
Creature& _owner;
};
class boss_runemaster_molgeim : public CreatureScript
{
public:
boss_runemaster_molgeim() : CreatureScript("boss_runemaster_molgeim") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return GetUlduarAI<boss_runemaster_molgeimAI>(pCreature);
}
struct boss_runemaster_molgeimAI : public ScriptedAI
{
boss_runemaster_molgeimAI(Creature* c) : ScriptedAI(c), summons(me)
{
pInstance = c->GetInstanceScript();
}
InstanceScript* pInstance;
SummonList summons;
EventMap events;
uint8 _phase;
void Reset() override
{
me->SetLootMode(0);
RespawnAssemblyOfIron(pInstance, me);
_phase = 0;
events.Reset();
summons.DespawnAll();
if (pInstance)
pInstance->SetData(TYPE_ASSEMBLY, NOT_STARTED);
me->m_Events.AddEvent(new CastRunesEvent(*me), me->m_Events.CalculateTime(8000));
}
void JustReachedHome() override
{
me->setActive(false);
me->RemoveAllAuras();
}
void JustEngagedWith(Unit* who) override
{
me->InterruptNonMeleeSpells(false);
me->setActive(true);
me->SetInCombatWithZone();
events.ScheduleEvent(EVENT_ENRAGE, 15min);
UpdatePhase();
if (!pInstance)
return;
for (uint8 i = 0; i < 3; ++i)
if (Creature* boss = ObjectAccessor::GetCreature(*me, pInstance->GetGuidData(DATA_STEELBREAKER + i)))
if (!boss->IsInCombat())
boss->AI()->AttackStart(who);
}
void UpdatePhase()
{
if (_phase >= 3)
return;
++_phase;
switch (_phase)
{
case 1:
events.RescheduleEvent(EVENT_SHIELD_OF_RUNES, 20s);
events.RescheduleEvent(EVENT_RUNE_OF_POWER, 30s);
break;
case 2:
events.RescheduleEvent(EVENT_RUNE_OF_DEATH, 35s);
break;
case 3:
me->ResetLootMode();
events.RescheduleEvent(EVENT_RUNE_OF_SUMMONING, 20s, 30s);
break;
}
}
void JustDied(Unit* /*killer*/) override
{
if (!pInstance)
return;
if (IsEncounterComplete(pInstance, me))
{
pInstance->SetData(TYPE_ASSEMBLY, DONE);
me->CastSpell(me, 65195, true); // credit
Talk(SAY_MOLGEIM_ENCOUNTER_DEFEATED);
}
else
{
RestoreAssemblyHealth(pInstance->GetGuidData(DATA_STEELBREAKER), pInstance->GetGuidData(DATA_BRUNDIR), me);
me->CastSpell(me, SPELL_SUPERCHARGE, true);
Talk(SAY_MOLGEIM_DEATH);
}
}
void KilledUnit(Unit* who) override
{
if (who->GetTypeId() != TYPEID_PLAYER)
return;
Talk(SAY_MOLGEIM_SLAY);
}
void SpellHit(Unit* /*caster*/, SpellInfo const* spellInfo) override
{
if (spellInfo->Id == SPELL_SUPERCHARGE)
UpdatePhase();
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch(events.ExecuteEvent())
{
case EVENT_RUNE_OF_POWER:
{
Unit* target = DoSelectLowestHpFriendly(60);
if (!target || !target->IsAlive())
target = me;
me->CastSpell(target, SPELL_RUNE_OF_POWER, true);
events.Repeat(1min);
break;
}
case EVENT_SHIELD_OF_RUNES:
me->CastSpell(me, SPELL_SHIELD_OF_RUNES, false);
events.RescheduleEvent(EVENT_SHIELD_OF_RUNES, 27s, 34s);
break;
case EVENT_RUNE_OF_DEATH:
if (Unit* target = SelectTarget(SelectTargetMethod::Random))
me->CastSpell(target, SPELL_RUNE_OF_DEATH, true);
Talk(SAY_MOLGEIM_RUNE_DEATH);
events.Repeat(30s, 40s);
break;
case EVENT_RUNE_OF_SUMMONING:
Talk(SAY_MOLGEIM_SUMMON);
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
me->CastSpell(target, SPELL_RUNE_OF_SUMMONING);
events.Repeat(30s, 45s);
break;
case EVENT_ENRAGE:
me->CastSpell(me, SPELL_BERSERK, true);
Talk(SAY_MOLGEIM_BERSERK);
break;
}
DoMeleeAttackIfReady();
}
};
};
class npc_assembly_lightning : public CreatureScript
{
public:
npc_assembly_lightning() : CreatureScript("npc_assembly_lightning") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return GetUlduarAI<npc_assembly_lightningAI>(pCreature);
}
struct npc_assembly_lightningAI : public ScriptedAI
{
npc_assembly_lightningAI(Creature* c) : ScriptedAI(c)
{
_boomed = false;
}
void MoveInLineOfSight(Unit*) override {}
void AttackStart(Unit*) override {}
void UpdateAI(uint32) override {}
void EnterEvadeMode(EvadeReason /* why */) override {}
void OnCharmed(bool /*apply*/) override {}
bool _boomed;
void Reset() override
{
if (Player* target = SelectTargetFromPlayerList(150))
me->GetMotionMaster()->MoveFollow(target, 0.0f, 0.0f);
else
me->DespawnOrUnsummon(1);
}
void MovementInform(uint32 type, uint32 /*id*/) override
{
if (type == FOLLOW_MOTION_TYPE && !_boomed)
{
_boomed = true;
me->CastSpell(me, SPELL_LIGHTNING_BLAST, true);
me->DespawnOrUnsummon(1000);
}
}
};
};
class boss_stormcaller_brundir : public CreatureScript
{
public:
boss_stormcaller_brundir() : CreatureScript("boss_stormcaller_brundir") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return GetUlduarAI<boss_stormcaller_brundirAI>(pCreature);
}
struct boss_stormcaller_brundirAI : public ScriptedAI
{
boss_stormcaller_brundirAI(Creature* c) : ScriptedAI(c)
{
pInstance = c->GetInstanceScript();
}
EventMap events;
InstanceScript* pInstance;
uint32 _phase;
ObjectGuid _flyTargetGUID;
uint32 _channelTimer;
bool _stunnedAchievement;
void Reset() override
{
me->SetLootMode(0);
RespawnAssemblyOfIron(pInstance, me);
_channelTimer = 0;
_phase = 0;
_flyTargetGUID.Clear();
_stunnedAchievement = true;
events.Reset();
me->SetDisableGravity(false);
me->SetRegeneratingHealth(true);
me->SetReactState(REACT_AGGRESSIVE);
if (pInstance)
pInstance->SetData(TYPE_ASSEMBLY, NOT_STARTED);
}
void JustReachedHome() override
{
me->setActive(false);
me->RemoveAllAuras();
}
void JustEngagedWith(Unit* who) override
{
me->InterruptNonMeleeSpells(false);
me->setActive(true);
me->SetInCombatWithZone();
events.ScheduleEvent(EVENT_ENRAGE, 15min);
UpdatePhase();
if (!pInstance)
return;
for (uint8 i = 0; i < 3; ++i)
if (Creature* boss = ObjectAccessor::GetCreature(*me, pInstance->GetGuidData(DATA_STEELBREAKER + i)))
if (!boss->IsInCombat())
boss->AI()->AttackStart(who);
}
void UpdatePhase()
{
if (_phase >= 3)
return;
++_phase;
switch (_phase)
{
case 1:
events.RescheduleEvent(EVENT_CHAIN_LIGHTNING, 9s, 17s);
events.RescheduleEvent(EVENT_OVERLOAD, 25s, 40s);
break;
case 2:
events.RescheduleEvent(EVENT_LIGHTNING_WHIRL, 20s, 40s);
break;
case 3:
me->ResetLootMode();
me->CastSpell(me, SPELL_STORMSHIELD, true);
events.RescheduleEvent(EVENT_LIGHTNING_TENDRILS, 15s, 16s);
break;
}
}
void JustDied(Unit* /*Killer*/) override
{
if (!pInstance)
return;
me->NearTeleportTo(me->GetPositionX(), me->GetPositionY(), 427.5, me->GetOrientation());
if (IsEncounterComplete(pInstance, me))
{
pInstance->SetData(TYPE_ASSEMBLY, DONE);
me->CastSpell(me, 65195, true); // credit
Talk(SAY_BRUNDIR_ENCOUNTER_DEFEATED);
}
else
{
RestoreAssemblyHealth(pInstance->GetGuidData(DATA_STEELBREAKER), pInstance->GetGuidData(DATA_MOLGEIM), me);
me->CastSpell(me, SPELL_SUPERCHARGE, true);
Talk(SAY_BRUNDIR_DEATH);
}
}
void KilledUnit(Unit* who) override
{
if (who->GetTypeId() != TYPEID_PLAYER || urand(0, 2))
return;
Talk(SAY_BRUNDIR_SLAY);
}
void SpellHit(Unit* /*caster*/, SpellInfo const* spellInfo) override
{
if (spellInfo->Id == SPELL_SUPERCHARGE)
UpdatePhase();
}
void SpellHitTarget(Unit* /*target*/, SpellInfo const* spellInfo) override
{
if (spellInfo->Id == SPELL_CHAIN_LIGHTNING || spellInfo->Id == uint32(RAID_MODE(61916, 63482))) // Lightning Whirl triggered
_stunnedAchievement = false;
}
uint32 GetData(uint32 param) const override
{
if (param == DATA_BRUNDIR)
return _stunnedAchievement;
return 0;
}
void MovementInform(uint32 type, uint32 point) override
{
if (type == POINT_MOTION_TYPE && point == POINT_CHANNEL_STEELBREAKER)
me->CastSpell(me, SPELL_LIGHTNING_CHANNEL_PRE, true);
}
void UpdateAI(uint32 diff) override
{
if (!me->IsInCombat() && me->GetReactState() == REACT_AGGRESSIVE)
{
_channelTimer += diff;
if (_channelTimer >= 10000)
{
_channelTimer = 0;
float o = urand(0, 5) * M_PI / 3.0f;
me->InterruptNonMeleeSpells(false);
me->GetMotionMaster()->MovePoint(POINT_CHANNEL_STEELBREAKER, 1587.18f + 10.0f * cos(o), 121.02f + 10.0f * std::sin(o), 427.3f);
}
}
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{
case EVENT_CHAIN_LIGHTNING:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
me->CastSpell(target, SPELL_CHAIN_LIGHTNING, false);
events.Repeat(9s, 17s);
break;
case EVENT_OVERLOAD:
Talk(EMOTE_BRUNDIR_OVERLOAD);
me->CastSpell(me, SPELL_OVERLOAD, true);
events.RescheduleEvent(EVENT_OVERLOAD, 25s, 40s);
break;
case EVENT_LIGHTNING_WHIRL:
Talk(SAY_BRUNDIR_SPECIAL);
me->CastSpell(me, SPELL_LIGHTNING_WHIRL, true);
events.Repeat(10s, 25s);
break;
case EVENT_LIGHTNING_TENDRILS:
{
// Reschedule old
events.Repeat(35s);
events.DelayEvents(18s);
Talk(SAY_BRUNDIR_FLIGHT);
Unit* oldVictim = me->GetVictim();
_flyTargetGUID = oldVictim->GetGUID();
me->SetRegeneratingHealth(false);
me->SetDisableGravity(true);
me->SetHover(true);
me->CombatStop();
me->StopMoving();
me->SetReactState(REACT_PASSIVE);
me->SetGuidValue(UNIT_FIELD_TARGET, ObjectGuid::Empty);
me->SetUnitFlag(UNIT_FLAG_STUNNED);
me->CastSpell(me, SPELL_LIGHTNING_TENDRILS, true);
me->CastSpell(me, 61883, true);
events.ScheduleEvent(EVENT_LIGHTNING_LAND, 16s);
events.ScheduleEvent(EVENT_LIGHTNING_FLIGHT, 1s);
break;
}
case EVENT_LIGHTNING_LAND:
{
float speed = me->GetDistance(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()) / (1000.0f * 0.001f);
me->MonsterMoveWithSpeed(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), speed);
events.ScheduleEvent(EVENT_LAND_LAND, 1s);
break;
}
case EVENT_LAND_LAND:
me->SetCanFly(false);
me->SetHover(false);
me->SetReactState(REACT_AGGRESSIVE);
me->SetDisableGravity(false);
if (Unit* flyTarget = ObjectAccessor::GetUnit(*me, _flyTargetGUID))
{
me->Attack(flyTarget, false);
}
me->SetRegeneratingHealth(true);
_flyTargetGUID.Clear();
me->RemoveAura(SPELL_LIGHTNING_TENDRILS);
me->RemoveAura(61883);
DoResetThreatList();
events.CancelEvent(EVENT_LIGHTNING_FLIGHT);
break;
case EVENT_ENRAGE:
Talk(SAY_BRUNDIR_BERSERK);
me->CastSpell(me, SPELL_BERSERK, true);
break;
case EVENT_LIGHTNING_FLIGHT:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true))
{
me->GetMotionMaster()->MovePoint(0, *target);
}
events.ScheduleEvent(EVENT_LIGHTNING_FLIGHT, 6s);
break;
}
DoMeleeAttackIfReady();
}
};
};
class spell_shield_of_runes : public SpellScriptLoader
{
public:
spell_shield_of_runes() : SpellScriptLoader("spell_shield_of_runes") { }
class spell_shield_of_runes_AuraScript : public AuraScript
{
PrepareAuraScript(spell_shield_of_runes_AuraScript);
void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
{
if (Unit* owner = GetUnitOwner())
if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_ENEMY_SPELL && aurEff->GetAmount() <= 0)
owner->CastSpell(owner, SPELL_SHIELD_OF_RUNES_BUFF, false);
}
void Register() override
{
AfterEffectRemove += AuraEffectRemoveFn(spell_shield_of_runes_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB, AURA_EFFECT_HANDLE_REAL);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_shield_of_runes_AuraScript();
}
};
class spell_assembly_meltdown : public SpellScriptLoader
{
public:
spell_assembly_meltdown() : SpellScriptLoader("spell_assembly_meltdown") { }
class spell_assembly_meltdown_SpellScript : public SpellScript
{
PrepareSpellScript(spell_assembly_meltdown_SpellScript);
void HandleInstaKill(SpellEffIndex /*effIndex*/)
{
if (InstanceScript* instance = GetCaster()->GetInstanceScript())
if (Creature* Steelbreaker = ObjectAccessor::GetCreature(*GetCaster(), instance->GetGuidData(DATA_STEELBREAKER)))
Steelbreaker->AI()->DoAction(ACTION_ADD_CHARGE);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_assembly_meltdown_SpellScript::HandleInstaKill, EFFECT_1, SPELL_EFFECT_INSTAKILL);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_assembly_meltdown_SpellScript();
}
};
class spell_assembly_rune_of_summoning : public SpellScriptLoader
{
public:
spell_assembly_rune_of_summoning() : SpellScriptLoader("spell_assembly_rune_of_summoning") { }
class spell_assembly_rune_of_summoning_AuraScript : public AuraScript
{
PrepareAuraScript(spell_assembly_rune_of_summoning_AuraScript);
void OnPeriodic(AuraEffect const* aurEff)
{
PreventDefaultAction();
if (aurEff->GetTickNumber() % 2 == 0)
GetTarget()->CastSpell(GetTarget(), SPELL_RUNE_OF_SUMMONING_SUMMON, true, nullptr, aurEff, GetTarget()->IsSummon() ? GetTarget()->ToTempSummon()->GetSummonerGUID() : ObjectGuid::Empty);
}
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
if (TempSummon* summ = GetTarget()->ToTempSummon())
summ->DespawnOrUnsummon(1);
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_assembly_rune_of_summoning_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
OnEffectRemove += AuraEffectRemoveFn(spell_assembly_rune_of_summoning_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_assembly_rune_of_summoning_AuraScript();
}
};
class achievement_assembly_of_iron : public AchievementCriteriaScript
{
public:
achievement_assembly_of_iron(char const* name, uint32 entry) : AchievementCriteriaScript(name),
_targetEntry(entry)
{
}
bool OnCheck(Player* /*player*/, Unit* target, uint32 /*criteria_id*/) override
{
return target && target->GetAuraCount(SPELL_SUPERCHARGE) >= 2 && (!_targetEntry || target->GetEntry() == _targetEntry);
}
private:
uint32 const _targetEntry;
};
class achievement_cant_do_that_while_stunned : public AchievementCriteriaScript
{
public:
achievement_cant_do_that_while_stunned() : AchievementCriteriaScript("achievement_cant_do_that_while_stunned") {}
bool OnCheck(Player* /*player*/, Unit* target, uint32 /*criteria_id*/) override
{
bool allow = target && target->GetAuraCount(SPELL_SUPERCHARGE) >= 2;
if (!allow)
return false;
if (InstanceScript* instance = target->GetInstanceScript())
if (Creature* cr = ObjectAccessor::GetCreature(*target, instance->GetGuidData(DATA_BRUNDIR)))
return cr->AI()->GetData(DATA_BRUNDIR);
return false;
}
};
void AddSC_boss_assembly_of_iron()
{

View File

@@ -1,908 +0,0 @@
#ifndef BOSS_ASSEMBLY_OF_IRON_H_
#define BOSS_ASSEMBLY_OF_IRON_H_
#include "AchievementCriteriaScript.h"
#include "CreatureScript.h"
#include "Player.h"
#include "ScriptedCreature.h"
#include "SpellAuraEffects.h"
#include "SpellScript.h"
#include "SpellScriptLoader.h"
#include "ulduar.h"
enum AssemblySpells
{
// Any boss
SPELL_SUPERCHARGE = 61920,
SPELL_BERSERK = 47008,
// Steelbreaker
SPELL_HIGH_VOLTAGE_10 = 61890,
SPELL_HIGH_VOLTAGE_25 = 63498,
SPELL_FUSION_PUNCH_10 = 61903,
SPELL_FUSION_PUNCH_25 = 63493,
SPELL_STATIC_DISRUPTION_10 = 61911,
SPELL_STATIC_DISRUPTION_25 = 63495,
SPELL_OVERWHELMING_POWER_10 = 64637,
SPELL_OVERWHELMING_POWER_25 = 61888,
SPELL_ELECTRICAL_CHARGE = 61902,
// Runemaster Molgeim
SPELL_SHIELD_OF_RUNES_BUFF = 62277,
SPELL_SHIELD_OF_RUNES_10 = 62274,
SPELL_SHIELD_OF_RUNES_25 = 63489,
SPELL_RUNE_OF_POWER = 61973,
SPELL_RUNE_OF_DEATH_10 = 62269,
SPELL_RUNE_OF_DEATH_25 = 63490,
SPELL_RUNE_OF_SUMMONING = 62273,
SPELL_RUNE_OF_SUMMONING_SUMMON = 62020,
SPELL_LIGHTNING_BLAST_10 = 62054,
SPELL_LIGHTNING_BLAST_25 = 63491,
CREATURE_LIGHTNING_ELEMENTAL = 32958,
CREATURE_RUNE_OF_SUMMONING = 33051,
SPELL_RUNE_OF_POWER_OOC_CHANNEL = 61975,
// Stormcaller Brundir
SPELL_CHAIN_LIGHTNING_10 = 61879,
SPELL_CHAIN_LIGHTNING_25 = 63479,
SPELL_OVERLOAD_10 = 61869,
SPELL_OVERLOAD_25 = 63481,
SPELL_LIGHTNING_WHIRL_10 = 61915,
SPELL_LIGHTNING_WHIRL_25 = 63483,
SPELL_LIGHTNING_TENDRILS_10 = 61887,
SPELL_LIGHTNING_TENDRILS_25 = 63486,
SPELL_STORMSHIELD = 64187,
SPELL_LIGHTNING_CHANNEL_PRE = 61942,
};
#define SPELL_HIGH_VOLTAGE RAID_MODE(SPELL_HIGH_VOLTAGE_10, SPELL_HIGH_VOLTAGE_25)
#define SPELL_FUSION_PUNCH RAID_MODE(SPELL_FUSION_PUNCH_10, SPELL_FUSION_PUNCH_25)
#define SPELL_STATIC_DISRUPTION RAID_MODE(SPELL_STATIC_DISRUPTION_10, SPELL_STATIC_DISRUPTION_25)
#define SPELL_OVERWHELMING_POWER RAID_MODE(SPELL_OVERWHELMING_POWER_10, SPELL_OVERWHELMING_POWER_25)
#define SPELL_SHIELD_OF_RUNES RAID_MODE(SPELL_SHIELD_OF_RUNES_10, SPELL_SHIELD_OF_RUNES_25)
#define SPELL_RUNE_OF_DEATH RAID_MODE(SPELL_RUNE_OF_DEATH_10, SPELL_RUNE_OF_DEATH_25)
#define SPELL_LIGHTNING_BLAST RAID_MODE(SPELL_LIGHTNING_BLAST_10, SPELL_LIGHTNING_BLAST_25)
#define SPELL_CHAIN_LIGHTNING RAID_MODE(SPELL_CHAIN_LIGHTNING_10, SPELL_CHAIN_LIGHTNING_25)
#define SPELL_OVERLOAD RAID_MODE(SPELL_OVERLOAD_10, SPELL_OVERLOAD_25)
#define SPELL_LIGHTNING_WHIRL RAID_MODE(SPELL_LIGHTNING_WHIRL_10, SPELL_LIGHTNING_WHIRL_25)
#define SPELL_LIGHTNING_TENDRILS RAID_MODE(SPELL_LIGHTNING_TENDRILS_10, SPELL_LIGHTNING_TENDRILS_25)
enum eEnums
{
// Steelbreaker
EVENT_FUSION_PUNCH = 1,
EVENT_STATIC_DISRUPTION = 2,
EVENT_OVERWHELMING_POWER = 3,
//EVENT_CHECK_MAIN_TANK = 4,
// Molgeim
EVENT_RUNE_OF_POWER = 11,
EVENT_SHIELD_OF_RUNES = 12,
EVENT_RUNE_OF_DEATH = 13,
EVENT_RUNE_OF_SUMMONING = 14,
EVENT_LIGHTNING_BLAST = 15,
// Brundir
EVENT_CHAIN_LIGHTNING = 21,
EVENT_OVERLOAD = 22,
EVENT_LIGHTNING_WHIRL = 23,
EVENT_LIGHTNING_TENDRILS = 24,
EVENT_LIGHTNING_LAND = 25,
EVENT_LAND_LAND = 26,
EVENT_LIGHTNING_FLIGHT = 27,
EVENT_ENRAGE = 30
};
enum AssemblyYells
{
SAY_STEELBREAKER_AGGRO = 0,
SAY_STEELBREAKER_SLAY = 1,
SAY_STEELBREAKER_POWER = 2,
SAY_STEELBREAKER_DEATH = 3,
SAY_STEELBREAKER_ENCOUNTER_DEFEATED = 4,
SAY_STEELBREAKER_BERSERK = 5,
SAY_MOLGEIM_AGGRO = 0,
SAY_MOLGEIM_SLAY = 1,
SAY_MOLGEIM_RUNE_DEATH = 2,
SAY_MOLGEIM_SUMMON = 3,
SAY_MOLGEIM_DEATH = 4,
SAY_MOLGEIM_ENCOUNTER_DEFEATED = 5,
SAY_MOLGEIM_BERSERK = 6,
SAY_BRUNDIR_AGGRO = 0,
SAY_BRUNDIR_SLAY = 1,
SAY_BRUNDIR_SPECIAL = 2,
SAY_BRUNDIR_FLIGHT = 3,
SAY_BRUNDIR_DEATH = 4,
SAY_BRUNDIR_ENCOUNTER_DEFEATED = 5,
SAY_BRUNDIR_BERSERK = 6,
EMOTE_BRUNDIR_OVERLOAD = 7
};
enum Misc
{
ACTION_ADD_CHARGE = 1,
POINT_CHANNEL_STEELBREAKER = 1
};
class boss_steelbreaker : public CreatureScript
{
public:
boss_steelbreaker() : CreatureScript("boss_steelbreaker") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return GetUlduarAI<boss_steelbreakerAI>(pCreature);
}
struct boss_steelbreakerAI : public ScriptedAI
{
boss_steelbreakerAI(Creature* c) : ScriptedAI(c)
{
pInstance = c->GetInstanceScript();
}
EventMap events;
InstanceScript* pInstance;
uint8 _phase;
void Reset() override
{
me->SetLootMode(0);
RespawnAssemblyOfIron(pInstance, me);
_phase = 0;
events.Reset();
if (pInstance)
pInstance->SetData(TYPE_ASSEMBLY, NOT_STARTED);
}
void JustReachedHome() override
{
me->setActive(false);
me->RemoveAllAuras();
}
void JustEngagedWith(Unit* who) override
{
if (pInstance)
pInstance->SetData(TYPE_ASSEMBLY, IN_PROGRESS);
me->setActive(true);
me->SetInCombatWithZone();
me->CastSpell(me, SPELL_HIGH_VOLTAGE, true);
events.ScheduleEvent(EVENT_ENRAGE, 15min);
UpdatePhase();
if (!pInstance)
return;
if (Creature* boss = ObjectAccessor::GetCreature(*me, pInstance->GetGuidData(DATA_STEELBREAKER + urand(0, 2))))
{
switch (boss->GetEntry())
{
case NPC_STEELBREAKER:
boss->AI()->Talk(SAY_STEELBREAKER_AGGRO);
break;
case NPC_MOLGEIM:
boss->AI()->Talk(SAY_MOLGEIM_AGGRO);
break;
case NPC_BRUNDIR:
boss->AI()->Talk(SAY_BRUNDIR_AGGRO);
break;
}
}
for (uint8 i = 0; i < 3; ++i)
if (Creature* boss = ObjectAccessor::GetCreature(*me, pInstance->GetGuidData(DATA_STEELBREAKER + i)))
if (!boss->IsInCombat())
boss->AI()->AttackStart(who);
}
void UpdatePhase()
{
if (_phase >= 3)
return;
++_phase;
switch (_phase)
{
case 1:
events.RescheduleEvent(EVENT_FUSION_PUNCH, 15s);
break;
case 2:
events.RescheduleEvent(EVENT_STATIC_DISRUPTION, 20s);
break;
case 3:
me->ResetLootMode();
events.RescheduleEvent(EVENT_OVERWHELMING_POWER, 8s);
break;
}
}
void JustDied(Unit* /*Killer*/) override
{
if (!pInstance)
return;
if (IsEncounterComplete(pInstance, me))
{
pInstance->SetData(TYPE_ASSEMBLY, DONE);
me->CastSpell(me, 65195, true); // credit
Talk(SAY_STEELBREAKER_ENCOUNTER_DEFEATED);
}
else
{
RestoreAssemblyHealth(pInstance->GetGuidData(DATA_BRUNDIR), pInstance->GetGuidData(DATA_MOLGEIM), me);
me->CastSpell(me, SPELL_SUPERCHARGE, true);
Talk(SAY_STEELBREAKER_DEATH);
}
}
void KilledUnit(Unit* who) override
{
if (who->GetTypeId() != TYPEID_PLAYER)
return;
if (_phase == 3)
me->CastSpell(me, SPELL_ELECTRICAL_CHARGE, true);
Talk(SAY_STEELBREAKER_SLAY);
}
void DoAction(int32 param) override
{
if (param == ACTION_ADD_CHARGE)
me->CastSpell(me, SPELL_ELECTRICAL_CHARGE, true);
}
void SpellHit(Unit* /*caster*/, SpellInfo const* spellInfo) override
{
if (spellInfo->Id == SPELL_SUPERCHARGE)
UpdatePhase();
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch(events.ExecuteEvent())
{
case EVENT_FUSION_PUNCH:
me->CastSpell(me->GetVictim(), SPELL_FUSION_PUNCH, false);
events.Repeat(15s, 20s);
break;
case EVENT_STATIC_DISRUPTION:
if (Unit* pTarget = SelectTarget(SelectTargetMethod::MinDistance, 0, 0, true))
me->CastSpell(pTarget, SPELL_STATIC_DISRUPTION, false);
events.Repeat(20s, 40s);
break;
case EVENT_OVERWHELMING_POWER:
Talk(SAY_STEELBREAKER_POWER);
me->CastSpell(me->GetVictim(), SPELL_OVERWHELMING_POWER, true);
events.RepeatEvent(RAID_MODE(61000, 36000));
break;
case EVENT_ENRAGE:
Talk(SAY_STEELBREAKER_BERSERK);
me->CastSpell(me, SPELL_BERSERK, true);
break;
}
DoMeleeAttackIfReady();
}
};
};
class CastRunesEvent : public BasicEvent
{
public:
CastRunesEvent(Creature& owner) : BasicEvent(), _owner(owner) { }
bool Execute(uint64 /*eventTime*/, uint32 /*diff*/) override
{
if (!_owner.IsInCombat())
_owner.CastSpell(&_owner, SPELL_RUNE_OF_POWER_OOC_CHANNEL, true);
return true;
}
private:
Creature& _owner;
};
class boss_runemaster_molgeim : public CreatureScript
{
public:
boss_runemaster_molgeim() : CreatureScript("boss_runemaster_molgeim") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return GetUlduarAI<boss_runemaster_molgeimAI>(pCreature);
}
struct boss_runemaster_molgeimAI : public ScriptedAI
{
boss_runemaster_molgeimAI(Creature* c) : ScriptedAI(c), summons(me)
{
pInstance = c->GetInstanceScript();
}
InstanceScript* pInstance;
SummonList summons;
EventMap events;
uint8 _phase;
void Reset() override
{
me->SetLootMode(0);
RespawnAssemblyOfIron(pInstance, me);
_phase = 0;
events.Reset();
summons.DespawnAll();
if (pInstance)
pInstance->SetData(TYPE_ASSEMBLY, NOT_STARTED);
me->m_Events.AddEvent(new CastRunesEvent(*me), me->m_Events.CalculateTime(8000));
}
void JustReachedHome() override
{
me->setActive(false);
me->RemoveAllAuras();
}
void JustEngagedWith(Unit* who) override
{
me->InterruptNonMeleeSpells(false);
me->setActive(true);
me->SetInCombatWithZone();
events.ScheduleEvent(EVENT_ENRAGE, 15min);
UpdatePhase();
if (!pInstance)
return;
for (uint8 i = 0; i < 3; ++i)
if (Creature* boss = ObjectAccessor::GetCreature(*me, pInstance->GetGuidData(DATA_STEELBREAKER + i)))
if (!boss->IsInCombat())
boss->AI()->AttackStart(who);
}
void UpdatePhase()
{
if (_phase >= 3)
return;
++_phase;
switch (_phase)
{
case 1:
events.RescheduleEvent(EVENT_SHIELD_OF_RUNES, 20s);
events.RescheduleEvent(EVENT_RUNE_OF_POWER, 30s);
break;
case 2:
events.RescheduleEvent(EVENT_RUNE_OF_DEATH, 35s);
break;
case 3:
me->ResetLootMode();
events.RescheduleEvent(EVENT_RUNE_OF_SUMMONING, 20s, 30s);
break;
}
}
void JustDied(Unit* /*killer*/) override
{
if (!pInstance)
return;
if (IsEncounterComplete(pInstance, me))
{
pInstance->SetData(TYPE_ASSEMBLY, DONE);
me->CastSpell(me, 65195, true); // credit
Talk(SAY_MOLGEIM_ENCOUNTER_DEFEATED);
}
else
{
RestoreAssemblyHealth(pInstance->GetGuidData(DATA_STEELBREAKER), pInstance->GetGuidData(DATA_BRUNDIR), me);
me->CastSpell(me, SPELL_SUPERCHARGE, true);
Talk(SAY_MOLGEIM_DEATH);
}
}
void KilledUnit(Unit* who) override
{
if (who->GetTypeId() != TYPEID_PLAYER)
return;
Talk(SAY_MOLGEIM_SLAY);
}
void SpellHit(Unit* /*caster*/, SpellInfo const* spellInfo) override
{
if (spellInfo->Id == SPELL_SUPERCHARGE)
UpdatePhase();
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch(events.ExecuteEvent())
{
case EVENT_RUNE_OF_POWER:
{
Unit* target = DoSelectLowestHpFriendly(60);
if (!target || !target->IsAlive())
target = me;
me->CastSpell(target, SPELL_RUNE_OF_POWER, true);
events.Repeat(1min);
break;
}
case EVENT_SHIELD_OF_RUNES:
me->CastSpell(me, SPELL_SHIELD_OF_RUNES, false);
events.RescheduleEvent(EVENT_SHIELD_OF_RUNES, 27s, 34s);
break;
case EVENT_RUNE_OF_DEATH:
if (Unit* target = SelectTarget(SelectTargetMethod::Random))
me->CastSpell(target, SPELL_RUNE_OF_DEATH, true);
Talk(SAY_MOLGEIM_RUNE_DEATH);
events.Repeat(30s, 40s);
break;
case EVENT_RUNE_OF_SUMMONING:
Talk(SAY_MOLGEIM_SUMMON);
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
me->CastSpell(target, SPELL_RUNE_OF_SUMMONING);
events.Repeat(30s, 45s);
break;
case EVENT_ENRAGE:
me->CastSpell(me, SPELL_BERSERK, true);
Talk(SAY_MOLGEIM_BERSERK);
break;
}
DoMeleeAttackIfReady();
}
};
};
class npc_assembly_lightning : public CreatureScript
{
public:
npc_assembly_lightning() : CreatureScript("npc_assembly_lightning") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return GetUlduarAI<npc_assembly_lightningAI>(pCreature);
}
struct npc_assembly_lightningAI : public ScriptedAI
{
npc_assembly_lightningAI(Creature* c) : ScriptedAI(c)
{
_boomed = false;
}
void MoveInLineOfSight(Unit*) override {}
void AttackStart(Unit*) override {}
void UpdateAI(uint32) override {}
void EnterEvadeMode(EvadeReason /* why */) override {}
void OnCharmed(bool /*apply*/) override {}
bool _boomed;
void Reset() override
{
if (Player* target = SelectTargetFromPlayerList(150))
me->GetMotionMaster()->MoveFollow(target, 0.0f, 0.0f);
else
me->DespawnOrUnsummon(1);
}
void MovementInform(uint32 type, uint32 /*id*/) override
{
if (type == FOLLOW_MOTION_TYPE && !_boomed)
{
_boomed = true;
me->CastSpell(me, SPELL_LIGHTNING_BLAST, true);
me->DespawnOrUnsummon(1000);
}
}
};
};
class boss_stormcaller_brundir : public CreatureScript
{
public:
boss_stormcaller_brundir() : CreatureScript("boss_stormcaller_brundir") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return GetUlduarAI<boss_stormcaller_brundirAI>(pCreature);
}
struct boss_stormcaller_brundirAI : public ScriptedAI
{
boss_stormcaller_brundirAI(Creature* c) : ScriptedAI(c)
{
pInstance = c->GetInstanceScript();
}
EventMap events;
InstanceScript* pInstance;
uint32 _phase;
ObjectGuid _flyTargetGUID;
uint32 _channelTimer;
bool _stunnedAchievement;
void Reset() override
{
me->SetLootMode(0);
RespawnAssemblyOfIron(pInstance, me);
_channelTimer = 0;
_phase = 0;
_flyTargetGUID.Clear();
_stunnedAchievement = true;
events.Reset();
me->SetDisableGravity(false);
me->SetRegeneratingHealth(true);
me->SetReactState(REACT_AGGRESSIVE);
if (pInstance)
pInstance->SetData(TYPE_ASSEMBLY, NOT_STARTED);
}
void JustReachedHome() override
{
me->setActive(false);
me->RemoveAllAuras();
}
void JustEngagedWith(Unit* who) override
{
me->InterruptNonMeleeSpells(false);
me->setActive(true);
me->SetInCombatWithZone();
events.ScheduleEvent(EVENT_ENRAGE, 15min);
UpdatePhase();
if (!pInstance)
return;
for (uint8 i = 0; i < 3; ++i)
if (Creature* boss = ObjectAccessor::GetCreature(*me, pInstance->GetGuidData(DATA_STEELBREAKER + i)))
if (!boss->IsInCombat())
boss->AI()->AttackStart(who);
}
void UpdatePhase()
{
if (_phase >= 3)
return;
++_phase;
switch (_phase)
{
case 1:
events.RescheduleEvent(EVENT_CHAIN_LIGHTNING, 9s, 17s);
events.RescheduleEvent(EVENT_OVERLOAD, 25s, 40s);
break;
case 2:
events.RescheduleEvent(EVENT_LIGHTNING_WHIRL, 20s, 40s);
break;
case 3:
me->ResetLootMode();
me->CastSpell(me, SPELL_STORMSHIELD, true);
events.RescheduleEvent(EVENT_LIGHTNING_TENDRILS, 15s, 16s);
break;
}
}
void JustDied(Unit* /*Killer*/) override
{
if (!pInstance)
return;
me->NearTeleportTo(me->GetPositionX(), me->GetPositionY(), 427.5, me->GetOrientation());
if (IsEncounterComplete(pInstance, me))
{
pInstance->SetData(TYPE_ASSEMBLY, DONE);
me->CastSpell(me, 65195, true); // credit
Talk(SAY_BRUNDIR_ENCOUNTER_DEFEATED);
}
else
{
RestoreAssemblyHealth(pInstance->GetGuidData(DATA_STEELBREAKER), pInstance->GetGuidData(DATA_MOLGEIM), me);
me->CastSpell(me, SPELL_SUPERCHARGE, true);
Talk(SAY_BRUNDIR_DEATH);
}
}
void KilledUnit(Unit* who) override
{
if (who->GetTypeId() != TYPEID_PLAYER || urand(0, 2))
return;
Talk(SAY_BRUNDIR_SLAY);
}
void SpellHit(Unit* /*caster*/, SpellInfo const* spellInfo) override
{
if (spellInfo->Id == SPELL_SUPERCHARGE)
UpdatePhase();
}
void SpellHitTarget(Unit* /*target*/, SpellInfo const* spellInfo) override
{
if (spellInfo->Id == SPELL_CHAIN_LIGHTNING || spellInfo->Id == uint32(RAID_MODE(61916, 63482))) // Lightning Whirl triggered
_stunnedAchievement = false;
}
uint32 GetData(uint32 param) const override
{
if (param == DATA_BRUNDIR)
return _stunnedAchievement;
return 0;
}
void MovementInform(uint32 type, uint32 point) override
{
if (type == POINT_MOTION_TYPE && point == POINT_CHANNEL_STEELBREAKER)
me->CastSpell(me, SPELL_LIGHTNING_CHANNEL_PRE, true);
}
void UpdateAI(uint32 diff) override
{
if (!me->IsInCombat() && me->GetReactState() == REACT_AGGRESSIVE)
{
_channelTimer += diff;
if (_channelTimer >= 10000)
{
_channelTimer = 0;
float o = urand(0, 5) * M_PI / 3.0f;
me->InterruptNonMeleeSpells(false);
me->GetMotionMaster()->MovePoint(POINT_CHANNEL_STEELBREAKER, 1587.18f + 10.0f * cos(o), 121.02f + 10.0f * std::sin(o), 427.3f);
}
}
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{
case EVENT_CHAIN_LIGHTNING:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
me->CastSpell(target, SPELL_CHAIN_LIGHTNING, false);
events.Repeat(9s, 17s);
break;
case EVENT_OVERLOAD:
Talk(EMOTE_BRUNDIR_OVERLOAD);
me->CastSpell(me, SPELL_OVERLOAD, true);
events.RescheduleEvent(EVENT_OVERLOAD, 25s, 40s);
break;
case EVENT_LIGHTNING_WHIRL:
Talk(SAY_BRUNDIR_SPECIAL);
me->CastSpell(me, SPELL_LIGHTNING_WHIRL, true);
events.Repeat(10s, 25s);
break;
case EVENT_LIGHTNING_TENDRILS:
{
// Reschedule old
events.Repeat(35s);
events.DelayEvents(18s);
Talk(SAY_BRUNDIR_FLIGHT);
Unit* oldVictim = me->GetVictim();
_flyTargetGUID = oldVictim->GetGUID();
me->SetRegeneratingHealth(false);
me->SetDisableGravity(true);
me->SetHover(true);
me->CombatStop();
me->StopMoving();
me->SetReactState(REACT_PASSIVE);
me->SetGuidValue(UNIT_FIELD_TARGET, ObjectGuid::Empty);
me->SetUnitFlag(UNIT_FLAG_STUNNED);
me->CastSpell(me, SPELL_LIGHTNING_TENDRILS, true);
me->CastSpell(me, 61883, true);
events.ScheduleEvent(EVENT_LIGHTNING_LAND, 16s);
events.ScheduleEvent(EVENT_LIGHTNING_FLIGHT, 1s);
break;
}
case EVENT_LIGHTNING_LAND:
{
float speed = me->GetDistance(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()) / (1000.0f * 0.001f);
me->MonsterMoveWithSpeed(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), speed);
events.ScheduleEvent(EVENT_LAND_LAND, 1s);
break;
}
case EVENT_LAND_LAND:
me->SetCanFly(false);
me->SetHover(false);
me->SetReactState(REACT_AGGRESSIVE);
me->SetDisableGravity(false);
if (Unit* flyTarget = ObjectAccessor::GetUnit(*me, _flyTargetGUID))
{
me->Attack(flyTarget, false);
}
me->SetRegeneratingHealth(true);
_flyTargetGUID.Clear();
me->RemoveAura(SPELL_LIGHTNING_TENDRILS);
me->RemoveAura(61883);
DoResetThreatList();
events.CancelEvent(EVENT_LIGHTNING_FLIGHT);
break;
case EVENT_ENRAGE:
Talk(SAY_BRUNDIR_BERSERK);
me->CastSpell(me, SPELL_BERSERK, true);
break;
case EVENT_LIGHTNING_FLIGHT:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true))
{
me->GetMotionMaster()->MovePoint(0, *target);
}
events.ScheduleEvent(EVENT_LIGHTNING_FLIGHT, 6s);
break;
}
DoMeleeAttackIfReady();
}
};
};
class spell_shield_of_runes : public SpellScriptLoader
{
public:
spell_shield_of_runes() : SpellScriptLoader("spell_shield_of_runes") { }
class spell_shield_of_runes_AuraScript : public AuraScript
{
PrepareAuraScript(spell_shield_of_runes_AuraScript);
void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
{
if (Unit* owner = GetUnitOwner())
if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_ENEMY_SPELL && aurEff->GetAmount() <= 0)
owner->CastSpell(owner, SPELL_SHIELD_OF_RUNES_BUFF, false);
}
void Register() override
{
AfterEffectRemove += AuraEffectRemoveFn(spell_shield_of_runes_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB, AURA_EFFECT_HANDLE_REAL);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_shield_of_runes_AuraScript();
}
};
class spell_assembly_meltdown : public SpellScriptLoader
{
public:
spell_assembly_meltdown() : SpellScriptLoader("spell_assembly_meltdown") { }
class spell_assembly_meltdown_SpellScript : public SpellScript
{
PrepareSpellScript(spell_assembly_meltdown_SpellScript);
void HandleInstaKill(SpellEffIndex /*effIndex*/)
{
if (InstanceScript* instance = GetCaster()->GetInstanceScript())
if (Creature* Steelbreaker = ObjectAccessor::GetCreature(*GetCaster(), instance->GetGuidData(DATA_STEELBREAKER)))
Steelbreaker->AI()->DoAction(ACTION_ADD_CHARGE);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_assembly_meltdown_SpellScript::HandleInstaKill, EFFECT_1, SPELL_EFFECT_INSTAKILL);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_assembly_meltdown_SpellScript();
}
};
class spell_assembly_rune_of_summoning : public SpellScriptLoader
{
public:
spell_assembly_rune_of_summoning() : SpellScriptLoader("spell_assembly_rune_of_summoning") { }
class spell_assembly_rune_of_summoning_AuraScript : public AuraScript
{
PrepareAuraScript(spell_assembly_rune_of_summoning_AuraScript);
void OnPeriodic(AuraEffect const* aurEff)
{
PreventDefaultAction();
if (aurEff->GetTickNumber() % 2 == 0)
GetTarget()->CastSpell(GetTarget(), SPELL_RUNE_OF_SUMMONING_SUMMON, true, nullptr, aurEff, GetTarget()->IsSummon() ? GetTarget()->ToTempSummon()->GetSummonerGUID() : ObjectGuid::Empty);
}
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
if (TempSummon* summ = GetTarget()->ToTempSummon())
summ->DespawnOrUnsummon(1);
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_assembly_rune_of_summoning_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
OnEffectRemove += AuraEffectRemoveFn(spell_assembly_rune_of_summoning_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_assembly_rune_of_summoning_AuraScript();
}
};
class achievement_assembly_of_iron : public AchievementCriteriaScript
{
public:
achievement_assembly_of_iron(char const* name, uint32 entry) : AchievementCriteriaScript(name),
_targetEntry(entry)
{
}
bool OnCheck(Player* /*player*/, Unit* target, uint32 /*criteria_id*/) override
{
return target && target->GetAuraCount(SPELL_SUPERCHARGE) >= 2 && (!_targetEntry || target->GetEntry() == _targetEntry);
}
private:
uint32 const _targetEntry;
};
class achievement_cant_do_that_while_stunned : public AchievementCriteriaScript
{
public:
achievement_cant_do_that_while_stunned() : AchievementCriteriaScript("achievement_cant_do_that_while_stunned") {}
bool OnCheck(Player* /*player*/, Unit* target, uint32 /*criteria_id*/) override
{
bool allow = target && target->GetAuraCount(SPELL_SUPERCHARGE) >= 2;
if (!allow)
return false;
if (InstanceScript* instance = target->GetInstanceScript())
if (Creature* cr = ObjectAccessor::GetCreature(*target, instance->GetGuidData(DATA_BRUNDIR)))
return cr->AI()->GetData(DATA_BRUNDIR);
return false;
}
};
#endif

View File

@@ -15,7 +15,6 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "boss_auriaya.h"
#include "AchievementCriteriaScript.h"
#include "CreatureScript.h"
#include "Player.h"
@@ -25,6 +24,472 @@
#include "SpellScriptLoader.h"
#include "ulduar.h"
enum AuriayaSpells
{
// BASIC
SPELL_TERRIFYING_SCREECH = 64386,
SPELL_SENTINEL_BLAST_10 = 64389,
SPELL_SENTINEL_BLAST_25 = 64678,
SPELL_SONIC_SCREECH_10 = 64422,
SPELL_SONIC_SCREECH_25 = 64688,
SPELL_GUARDIAN_SWARM = 64396,
SPELL_ENRAGE = 47008,
SPELL_ACTIVATE_FERAL_DEFENDER = 64449,
// Sanctum Sentry
SPELL_SAVAGE_POUNCE_10 = 64666,
SPELL_SAVAGE_POUNCE_25 = 64374,
SPELL_RIP_FLESH_10 = 64375,
SPELL_RIP_FLESH_25 = 64667,
SPELL_STRENGTH_OF_THE_PACK = 64369,
// Feral Defender
SPELL_FERAL_ESSENCE = 64455,
SPELL_FERAL_POUNCE_10 = 64478,
SPELL_FERAL_POUNCE_25 = 64669,
SPELL_FERAL_RUSH_10 = 64496,
SPELL_FERAL_RUSH_25 = 64674,
//SPELL_SEEPING_FERAL_ESSENCE_SUMMON = 64457,
SPELL_SEEPING_FERAL_ESSENCE_10 = 64458,
SPELL_SEEPING_FERAL_ESSENCE_25 = 64676,
};
#define SPELL_SONIC_SCREECH RAID_MODE(SPELL_SONIC_SCREECH_10, SPELL_SONIC_SCREECH_25)
#define SPELL_SENTINEL_BLAST RAID_MODE(SPELL_SENTINEL_BLAST_10, SPELL_SENTINEL_BLAST_25)
#define SPELL_SAVAGE_POUNCE RAID_MODE(SPELL_SAVAGE_POUNCE_10, SPELL_SAVAGE_POUNCE_25)
#define SPELL_RIP_FLESH RAID_MODE(SPELL_RIP_FLESH_10, SPELL_RIP_FLESH_25)
#define SPELL_FERAL_POUNCE RAID_MODE(SPELL_FERAL_POUNCE_10, SPELL_FERAL_POUNCE_25)
#define SPELL_FERAL_RUSH RAID_MODE(SPELL_FERAL_RUSH_10, SPELL_FERAL_RUSH_25)
//#define SPELL_SEEPING_FERAL_ESSENCE RAID_MODE(SPELL_SEEPING_FERAL_ESSENCE_10, SPELL_SEEPING_FERAL_ESSENCE_25)
enum AuriayaNPC
{
NPC_FERAL_DEFENDER = 34035,
NPC_SANCTUM_SENTRY = 34014,
NPC_SEEPING_FERAL_ESSENCE = 34098,
};
enum AuriayaEvents
{
EVENT_SUMMON_FERAL_DEFENDER = 1,
EVENT_TERRIFYING_SCREECH = 2,
EVENT_SONIC_SCREECH = 3,
EVENT_GUARDIAN_SWARM = 4,
EVENT_SENTINEL_BLAST = 5,
EVENT_REMOVE_IMMUNE = 6,
EVENT_RESPAWN_FERAL_DEFENDER = 9,
EVENT_ENRAGE = 10,
};
enum Texts
{
SAY_AGGRO = 0,
SAY_SLAY = 1,
SAY_BERSERK = 2,
EMOTE_DEATH = 3,
EMOTE_FEAR = 4,
EMOTE_DEFFENDER = 5,
};
enum Misc
{
ACTION_FERAL_RESPAWN = 1,
ACTION_FERAL_DEATH = 2,
ACTION_DESPAWN_ADDS = 3,
ACTION_FERAL_DEATH_WITH_STACK = 4,
DATA_CRAZY_CAT = 10,
DATA_NINE_LIVES = 11,
};
class boss_auriaya : public CreatureScript
{
public:
boss_auriaya() : CreatureScript("boss_auriaya") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return GetUlduarAI<boss_auriayaAI>(pCreature);
}
struct boss_auriayaAI : public ScriptedAI
{
boss_auriayaAI(Creature* pCreature) : ScriptedAI(pCreature), summons(pCreature)
{
m_pInstance = pCreature->GetInstanceScript();
}
InstanceScript* m_pInstance;
EventMap events;
SummonList summons;
bool _feralDied;
bool _nineLives;
void Reset() override
{
_feralDied = false;
_nineLives = false;
events.Reset();
EntryCheckPredicate pred(NPC_FERAL_DEFENDER);
summons.DoAction(ACTION_DESPAWN_ADDS, pred);
summons.DespawnAll();
if (m_pInstance)
m_pInstance->SetData(TYPE_AURIAYA, NOT_STARTED);
for (uint8 i = 0; i < RAID_MODE(2, 4); ++i)
me->SummonCreature(NPC_SANCTUM_SENTRY, me->GetPositionX() + urand(4, 12), me->GetPositionY() + urand(4, 12), me->GetPositionZ());
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, false);
}
uint32 GetData(uint32 param) const override
{
if (param == DATA_CRAZY_CAT)
return !_feralDied;
else if (param == DATA_NINE_LIVES)
return _nineLives;
return 0;
}
void JustSummoned(Creature* cr) override
{
if (cr->GetEntry() == NPC_SANCTUM_SENTRY)
cr->GetMotionMaster()->MoveFollow(me, 6, rand_norm() * 2 * 3.14f);
else
cr->SetInCombatWithZone();
summons.Summon(cr);
}
void SummonedCreatureDies(Creature* cr, Unit*) override
{
if (cr->GetEntry() == NPC_SANCTUM_SENTRY)
_feralDied = true;
}
void JustReachedHome() override { me->setActive(false); }
void JustEngagedWith(Unit* /*who*/) override
{
if (m_pInstance)
m_pInstance->SetData(TYPE_AURIAYA, IN_PROGRESS);
events.ScheduleEvent(EVENT_TERRIFYING_SCREECH, 35s);
events.ScheduleEvent(EVENT_SONIC_SCREECH, 45s);
events.ScheduleEvent(EVENT_GUARDIAN_SWARM, 70s);
events.ScheduleEvent(EVENT_SUMMON_FERAL_DEFENDER, 60s);
events.ScheduleEvent(EVENT_SENTINEL_BLAST, 36s);
events.ScheduleEvent(EVENT_ENRAGE, 10min);
summons.DoZoneInCombat(NPC_SANCTUM_SENTRY);
Talk(SAY_AGGRO);
me->setActive(true);
}
void KilledUnit(Unit* victim) override
{
if (victim->GetTypeId() != TYPEID_PLAYER || urand(0, 2))
return;
Talk(SAY_SLAY);
}
void JustDied(Unit* /*killer*/) override
{
if (m_pInstance)
m_pInstance->SetData(TYPE_AURIAYA, DONE);
EntryCheckPredicate pred(NPC_FERAL_DEFENDER);
summons.DoAction(ACTION_DESPAWN_ADDS, pred);
summons.DespawnAll();
Talk(EMOTE_DEATH);
}
void DoAction(int32 param) override
{
if (param == ACTION_FERAL_DEATH_WITH_STACK)
events.ScheduleEvent(EVENT_RESPAWN_FERAL_DEFENDER, 25s);
else if (param == ACTION_FERAL_DEATH)
_nineLives = true;
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{
case EVENT_SUMMON_FERAL_DEFENDER:
Talk(EMOTE_DEFFENDER);
me->CastSpell(me, SPELL_ACTIVATE_FERAL_DEFENDER, true);
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, true);
events.ScheduleEvent(EVENT_REMOVE_IMMUNE, 3s);
break;
case EVENT_REMOVE_IMMUNE:
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, false);
break;
case EVENT_TERRIFYING_SCREECH:
Talk(EMOTE_FEAR);
me->CastSpell(me, SPELL_TERRIFYING_SCREECH, false);
events.Repeat(35s);
break;
case EVENT_SONIC_SCREECH:
me->CastSpell(me, SPELL_SONIC_SCREECH, false);
events.Repeat(50s);
break;
case EVENT_GUARDIAN_SWARM:
me->CastSpell(me->GetVictim(), SPELL_GUARDIAN_SWARM, false);
events.Repeat(40s);
break;
case EVENT_SENTINEL_BLAST:
me->CastSpell(me, SPELL_SENTINEL_BLAST, false);
events.Repeat(35s);
events.DelayEvents(5000, 0);
break;
case EVENT_RESPAWN_FERAL_DEFENDER:
{
EntryCheckPredicate pred(NPC_FERAL_DEFENDER);
summons.DoAction(ACTION_FERAL_RESPAWN, pred);
break;
}
case EVENT_ENRAGE:
Talk(SAY_BERSERK);
me->CastSpell(me, SPELL_ENRAGE, true);
break;
}
DoMeleeAttackIfReady();
}
};
};
class npc_auriaya_sanctum_sentry : public CreatureScript
{
public:
npc_auriaya_sanctum_sentry() : CreatureScript("npc_auriaya_sanctum_sentry") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return GetUlduarAI<npc_auriaya_sanctum_sentryAI>(pCreature);
}
struct npc_auriaya_sanctum_sentryAI : public ScriptedAI
{
npc_auriaya_sanctum_sentryAI(Creature* pCreature) : ScriptedAI(pCreature) { }
uint32 _savagePounceTimer;
uint32 _ripFleshTimer;
void JustEngagedWith(Unit*) override
{
if (me->GetInstanceScript())
if (Creature* cr = ObjectAccessor::GetCreature(*me, me->GetInstanceScript()->GetGuidData(TYPE_AURIAYA)))
cr->SetInCombatWithZone();
}
void Reset() override
{
_savagePounceTimer = 5000;
_ripFleshTimer = 0;
me->CastSpell(me, SPELL_STRENGTH_OF_THE_PACK, true);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
_savagePounceTimer += diff;
_ripFleshTimer += diff;
if (_savagePounceTimer >= 5000)
{
float dist = me->GetDistance(me->GetVictim());
if (dist >= 8 && dist < 25 && me->IsWithinLOSInMap(me->GetVictim()))
{
me->CastSpell(me->GetVictim(), SPELL_SAVAGE_POUNCE, false);
_savagePounceTimer = 0;
return;
}
_savagePounceTimer = 200;
}
else if (_ripFleshTimer >= 10000)
{
me->CastSpell(me->GetVictim(), SPELL_RIP_FLESH, false);
_ripFleshTimer = 0;
}
DoMeleeAttackIfReady();
}
};
};
class npc_auriaya_feral_defender : public CreatureScript
{
public:
npc_auriaya_feral_defender() : CreatureScript("npc_auriaya_feral_defender") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return GetUlduarAI<npc_auriaya_feral_defenderAI>(pCreature);
}
struct npc_auriaya_feral_defenderAI : public ScriptedAI
{
npc_auriaya_feral_defenderAI(Creature* pCreature) : ScriptedAI(pCreature), summons(pCreature) { }
int32 _feralRushTimer;
int32 _feralPounceTimer;
uint8 _feralEssenceStack;
SummonList summons;
void Reset() override
{
summons.DespawnAll();
_feralRushTimer = 3000;
_feralPounceTimer = 0;
_feralEssenceStack = 8;
if (Aura* aur = me->AddAura(SPELL_FERAL_ESSENCE, me))
aur->SetStackAmount(_feralEssenceStack);
}
void JustDied(Unit*) override
{
// inform about our death, start timer
if (me->GetInstanceScript())
if (Creature* cr = ObjectAccessor::GetCreature(*me, me->GetInstanceScript()->GetGuidData(TYPE_AURIAYA)))
cr->AI()->DoAction(_feralEssenceStack ? ACTION_FERAL_DEATH_WITH_STACK : ACTION_FERAL_DEATH);
if (_feralEssenceStack)
{
if (Creature* cr = me->SummonCreature(NPC_SEEPING_FERAL_ESSENCE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0.0f))
summons.Summon(cr);
--_feralEssenceStack;
}
}
void DoAction(int32 param) override
{
if (param == ACTION_FERAL_RESPAWN)
{
me->setDeathState(DeathState::JustRespawned);
if (Player* target = SelectTargetFromPlayerList(200))
AttackStart(target);
else
{
summons.DespawnAll();
me->DespawnOrUnsummon(1);
}
if (_feralEssenceStack)
if (Aura* aur = me->AddAura(SPELL_FERAL_ESSENCE, me))
aur->SetStackAmount(_feralEssenceStack);
}
else if (param == ACTION_DESPAWN_ADDS)
summons.DespawnAll();
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
_feralRushTimer += diff;
_feralPounceTimer += diff;
if (_feralRushTimer >= 6000)
{
DoResetThreatList();
if (!UpdateVictim())
return;
me->CastSpell(me->GetVictim(), SPELL_FERAL_RUSH, true);
_feralRushTimer = 0;
}
else if (_feralPounceTimer >= 6000)
{
me->CastSpell(me->GetVictim(), SPELL_FERAL_POUNCE, false);
_feralPounceTimer = 0;
}
DoMeleeAttackIfReady();
}
};
};
class spell_auriaya_sentinel_blast : public SpellScriptLoader
{
public:
spell_auriaya_sentinel_blast() : SpellScriptLoader("spell_auriaya_sentinel_blast") { }
class spell_auriaya_sentinel_blast_SpellScript : public SpellScript
{
PrepareSpellScript(spell_auriaya_sentinel_blast_SpellScript);
void FilterTargets(std::list<WorldObject*>& unitList)
{
unitList.remove_if(PlayerOrPetCheck());
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_auriaya_sentinel_blast_SpellScript::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_auriaya_sentinel_blast_SpellScript();
}
};
class achievement_auriaya_crazy_cat_lady : public AchievementCriteriaScript
{
public:
achievement_auriaya_crazy_cat_lady() : AchievementCriteriaScript("achievement_auriaya_crazy_cat_lady") {}
bool OnCheck(Player* /*player*/, Unit* target, uint32 /*criteria_id*/) override
{
if (target)
if (InstanceScript* instance = target->GetInstanceScript())
if (Creature* cr = ObjectAccessor::GetCreature(*target, instance->GetGuidData(TYPE_AURIAYA)))
return cr->AI()->GetData(DATA_CRAZY_CAT);
return false;
}
};
class achievement_auriaya_nine_lives : public AchievementCriteriaScript
{
public:
achievement_auriaya_nine_lives() : AchievementCriteriaScript("achievement_auriaya_nine_lives") {}
bool OnCheck(Player* /*player*/, Unit* target, uint32 /*criteria_id*/) override
{
if (target)
if (InstanceScript* instance = target->GetInstanceScript())
if (Creature* cr = ObjectAccessor::GetCreature(*target, instance->GetGuidData(TYPE_AURIAYA)))
return cr->AI()->GetData(DATA_NINE_LIVES);
return false;
}
};
void AddSC_boss_auriaya()
{
new boss_auriaya();

View File

@@ -1,479 +0,0 @@
#ifndef BOSS_AURIAYA_H_
#define BOSS_AURIAYA_H_
#include "AchievementCriteriaScript.h"
#include "CreatureScript.h"
#include "Player.h"
#include "ScriptedCreature.h"
#include "SpellAuraEffects.h"
#include "SpellScript.h"
#include "SpellScriptLoader.h"
#include "ulduar.h"
enum AuriayaSpells
{
// BASIC
SPELL_TERRIFYING_SCREECH = 64386,
SPELL_SENTINEL_BLAST_10 = 64389,
SPELL_SENTINEL_BLAST_25 = 64678,
SPELL_SONIC_SCREECH_10 = 64422,
SPELL_SONIC_SCREECH_25 = 64688,
SPELL_GUARDIAN_SWARM = 64396,
SPELL_ENRAGE = 47008,
SPELL_ACTIVATE_FERAL_DEFENDER = 64449,
// Sanctum Sentry
SPELL_SAVAGE_POUNCE_10 = 64666,
SPELL_SAVAGE_POUNCE_25 = 64374,
SPELL_RIP_FLESH_10 = 64375,
SPELL_RIP_FLESH_25 = 64667,
SPELL_STRENGTH_OF_THE_PACK = 64369,
// Feral Defender
SPELL_FERAL_ESSENCE = 64455,
SPELL_FERAL_POUNCE_10 = 64478,
SPELL_FERAL_POUNCE_25 = 64669,
SPELL_FERAL_RUSH_10 = 64496,
SPELL_FERAL_RUSH_25 = 64674,
//SPELL_SEEPING_FERAL_ESSENCE_SUMMON = 64457,
SPELL_SEEPING_FERAL_ESSENCE_10 = 64458,
SPELL_SEEPING_FERAL_ESSENCE_25 = 64676,
};
#define SPELL_SONIC_SCREECH RAID_MODE(SPELL_SONIC_SCREECH_10, SPELL_SONIC_SCREECH_25)
#define SPELL_SENTINEL_BLAST RAID_MODE(SPELL_SENTINEL_BLAST_10, SPELL_SENTINEL_BLAST_25)
#define SPELL_SAVAGE_POUNCE RAID_MODE(SPELL_SAVAGE_POUNCE_10, SPELL_SAVAGE_POUNCE_25)
#define SPELL_RIP_FLESH RAID_MODE(SPELL_RIP_FLESH_10, SPELL_RIP_FLESH_25)
#define SPELL_FERAL_POUNCE RAID_MODE(SPELL_FERAL_POUNCE_10, SPELL_FERAL_POUNCE_25)
#define SPELL_FERAL_RUSH RAID_MODE(SPELL_FERAL_RUSH_10, SPELL_FERAL_RUSH_25)
//#define SPELL_SEEPING_FERAL_ESSENCE RAID_MODE(SPELL_SEEPING_FERAL_ESSENCE_10, SPELL_SEEPING_FERAL_ESSENCE_25)
enum AuriayaNPC
{
NPC_FERAL_DEFENDER = 34035,
NPC_SANCTUM_SENTRY = 34014,
NPC_SEEPING_FERAL_ESSENCE = 34098,
};
enum AuriayaEvents
{
EVENT_SUMMON_FERAL_DEFENDER = 1,
EVENT_TERRIFYING_SCREECH = 2,
EVENT_SONIC_SCREECH = 3,
EVENT_GUARDIAN_SWARM = 4,
EVENT_SENTINEL_BLAST = 5,
EVENT_REMOVE_IMMUNE = 6,
EVENT_RESPAWN_FERAL_DEFENDER = 9,
EVENT_ENRAGE = 10,
};
enum Texts
{
SAY_AGGRO = 0,
SAY_SLAY = 1,
SAY_BERSERK = 2,
EMOTE_DEATH = 3,
EMOTE_FEAR = 4,
EMOTE_DEFFENDER = 5,
};
enum Misc
{
ACTION_FERAL_RESPAWN = 1,
ACTION_FERAL_DEATH = 2,
ACTION_DESPAWN_ADDS = 3,
ACTION_FERAL_DEATH_WITH_STACK = 4,
DATA_CRAZY_CAT = 10,
DATA_NINE_LIVES = 11,
};
class boss_auriaya : public CreatureScript
{
public:
boss_auriaya() : CreatureScript("boss_auriaya") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return GetUlduarAI<boss_auriayaAI>(pCreature);
}
struct boss_auriayaAI : public ScriptedAI
{
boss_auriayaAI(Creature* pCreature) : ScriptedAI(pCreature), summons(pCreature)
{
m_pInstance = pCreature->GetInstanceScript();
}
InstanceScript* m_pInstance;
EventMap events;
SummonList summons;
bool _feralDied;
bool _nineLives;
void Reset() override
{
_feralDied = false;
_nineLives = false;
events.Reset();
EntryCheckPredicate pred(NPC_FERAL_DEFENDER);
summons.DoAction(ACTION_DESPAWN_ADDS, pred);
summons.DespawnAll();
if (m_pInstance)
m_pInstance->SetData(TYPE_AURIAYA, NOT_STARTED);
for (uint8 i = 0; i < RAID_MODE(2, 4); ++i)
me->SummonCreature(NPC_SANCTUM_SENTRY, me->GetPositionX() + urand(4, 12), me->GetPositionY() + urand(4, 12), me->GetPositionZ());
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, false);
}
uint32 GetData(uint32 param) const override
{
if (param == DATA_CRAZY_CAT)
return !_feralDied;
else if (param == DATA_NINE_LIVES)
return _nineLives;
return 0;
}
void JustSummoned(Creature* cr) override
{
if (cr->GetEntry() == NPC_SANCTUM_SENTRY)
cr->GetMotionMaster()->MoveFollow(me, 6, rand_norm() * 2 * 3.14f);
else
cr->SetInCombatWithZone();
summons.Summon(cr);
}
void SummonedCreatureDies(Creature* cr, Unit*) override
{
if (cr->GetEntry() == NPC_SANCTUM_SENTRY)
_feralDied = true;
}
void JustReachedHome() override { me->setActive(false); }
void JustEngagedWith(Unit* /*who*/) override
{
if (m_pInstance)
m_pInstance->SetData(TYPE_AURIAYA, IN_PROGRESS);
events.ScheduleEvent(EVENT_TERRIFYING_SCREECH, 35s);
events.ScheduleEvent(EVENT_SONIC_SCREECH, 45s);
events.ScheduleEvent(EVENT_GUARDIAN_SWARM, 70s);
events.ScheduleEvent(EVENT_SUMMON_FERAL_DEFENDER, 60s);
events.ScheduleEvent(EVENT_SENTINEL_BLAST, 36s);
events.ScheduleEvent(EVENT_ENRAGE, 10min);
summons.DoZoneInCombat(NPC_SANCTUM_SENTRY);
Talk(SAY_AGGRO);
me->setActive(true);
}
void KilledUnit(Unit* victim) override
{
if (victim->GetTypeId() != TYPEID_PLAYER || urand(0, 2))
return;
Talk(SAY_SLAY);
}
void JustDied(Unit* /*killer*/) override
{
if (m_pInstance)
m_pInstance->SetData(TYPE_AURIAYA, DONE);
EntryCheckPredicate pred(NPC_FERAL_DEFENDER);
summons.DoAction(ACTION_DESPAWN_ADDS, pred);
summons.DespawnAll();
Talk(EMOTE_DEATH);
}
void DoAction(int32 param) override
{
if (param == ACTION_FERAL_DEATH_WITH_STACK)
events.ScheduleEvent(EVENT_RESPAWN_FERAL_DEFENDER, 25s);
else if (param == ACTION_FERAL_DEATH)
_nineLives = true;
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{
case EVENT_SUMMON_FERAL_DEFENDER:
Talk(EMOTE_DEFFENDER);
me->CastSpell(me, SPELL_ACTIVATE_FERAL_DEFENDER, true);
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, true);
events.ScheduleEvent(EVENT_REMOVE_IMMUNE, 3s);
break;
case EVENT_REMOVE_IMMUNE:
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, false);
break;
case EVENT_TERRIFYING_SCREECH:
Talk(EMOTE_FEAR);
me->CastSpell(me, SPELL_TERRIFYING_SCREECH, false);
events.Repeat(35s);
break;
case EVENT_SONIC_SCREECH:
me->CastSpell(me, SPELL_SONIC_SCREECH, false);
events.Repeat(50s);
break;
case EVENT_GUARDIAN_SWARM:
me->CastSpell(me->GetVictim(), SPELL_GUARDIAN_SWARM, false);
events.Repeat(40s);
break;
case EVENT_SENTINEL_BLAST:
me->CastSpell(me, SPELL_SENTINEL_BLAST, false);
events.Repeat(35s);
events.DelayEvents(5000, 0);
break;
case EVENT_RESPAWN_FERAL_DEFENDER:
{
EntryCheckPredicate pred(NPC_FERAL_DEFENDER);
summons.DoAction(ACTION_FERAL_RESPAWN, pred);
break;
}
case EVENT_ENRAGE:
Talk(SAY_BERSERK);
me->CastSpell(me, SPELL_ENRAGE, true);
break;
}
DoMeleeAttackIfReady();
}
};
};
class npc_auriaya_sanctum_sentry : public CreatureScript
{
public:
npc_auriaya_sanctum_sentry() : CreatureScript("npc_auriaya_sanctum_sentry") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return GetUlduarAI<npc_auriaya_sanctum_sentryAI>(pCreature);
}
struct npc_auriaya_sanctum_sentryAI : public ScriptedAI
{
npc_auriaya_sanctum_sentryAI(Creature* pCreature) : ScriptedAI(pCreature) { }
uint32 _savagePounceTimer;
uint32 _ripFleshTimer;
void JustEngagedWith(Unit*) override
{
if (me->GetInstanceScript())
if (Creature* cr = ObjectAccessor::GetCreature(*me, me->GetInstanceScript()->GetGuidData(TYPE_AURIAYA)))
cr->SetInCombatWithZone();
}
void Reset() override
{
_savagePounceTimer = 5000;
_ripFleshTimer = 0;
me->CastSpell(me, SPELL_STRENGTH_OF_THE_PACK, true);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
_savagePounceTimer += diff;
_ripFleshTimer += diff;
if (_savagePounceTimer >= 5000)
{
float dist = me->GetDistance(me->GetVictim());
if (dist >= 8 && dist < 25 && me->IsWithinLOSInMap(me->GetVictim()))
{
me->CastSpell(me->GetVictim(), SPELL_SAVAGE_POUNCE, false);
_savagePounceTimer = 0;
return;
}
_savagePounceTimer = 200;
}
else if (_ripFleshTimer >= 10000)
{
me->CastSpell(me->GetVictim(), SPELL_RIP_FLESH, false);
_ripFleshTimer = 0;
}
DoMeleeAttackIfReady();
}
};
};
class npc_auriaya_feral_defender : public CreatureScript
{
public:
npc_auriaya_feral_defender() : CreatureScript("npc_auriaya_feral_defender") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return GetUlduarAI<npc_auriaya_feral_defenderAI>(pCreature);
}
struct npc_auriaya_feral_defenderAI : public ScriptedAI
{
npc_auriaya_feral_defenderAI(Creature* pCreature) : ScriptedAI(pCreature), summons(pCreature) { }
int32 _feralRushTimer;
int32 _feralPounceTimer;
uint8 _feralEssenceStack;
SummonList summons;
void Reset() override
{
summons.DespawnAll();
_feralRushTimer = 3000;
_feralPounceTimer = 0;
_feralEssenceStack = 8;
if (Aura* aur = me->AddAura(SPELL_FERAL_ESSENCE, me))
aur->SetStackAmount(_feralEssenceStack);
}
void JustDied(Unit*) override
{
// inform about our death, start timer
if (me->GetInstanceScript())
if (Creature* cr = ObjectAccessor::GetCreature(*me, me->GetInstanceScript()->GetGuidData(TYPE_AURIAYA)))
cr->AI()->DoAction(_feralEssenceStack ? ACTION_FERAL_DEATH_WITH_STACK : ACTION_FERAL_DEATH);
if (_feralEssenceStack)
{
if (Creature* cr = me->SummonCreature(NPC_SEEPING_FERAL_ESSENCE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0.0f))
summons.Summon(cr);
--_feralEssenceStack;
}
}
void DoAction(int32 param) override
{
if (param == ACTION_FERAL_RESPAWN)
{
me->setDeathState(DeathState::JustRespawned);
if (Player* target = SelectTargetFromPlayerList(200))
AttackStart(target);
else
{
summons.DespawnAll();
me->DespawnOrUnsummon(1);
}
if (_feralEssenceStack)
if (Aura* aur = me->AddAura(SPELL_FERAL_ESSENCE, me))
aur->SetStackAmount(_feralEssenceStack);
}
else if (param == ACTION_DESPAWN_ADDS)
summons.DespawnAll();
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
_feralRushTimer += diff;
_feralPounceTimer += diff;
if (_feralRushTimer >= 6000)
{
DoResetThreatList();
if (!UpdateVictim())
return;
me->CastSpell(me->GetVictim(), SPELL_FERAL_RUSH, true);
_feralRushTimer = 0;
}
else if (_feralPounceTimer >= 6000)
{
me->CastSpell(me->GetVictim(), SPELL_FERAL_POUNCE, false);
_feralPounceTimer = 0;
}
DoMeleeAttackIfReady();
}
};
};
class spell_auriaya_sentinel_blast : public SpellScriptLoader
{
public:
spell_auriaya_sentinel_blast() : SpellScriptLoader("spell_auriaya_sentinel_blast") { }
class spell_auriaya_sentinel_blast_SpellScript : public SpellScript
{
PrepareSpellScript(spell_auriaya_sentinel_blast_SpellScript);
void FilterTargets(std::list<WorldObject*>& unitList)
{
unitList.remove_if(PlayerOrPetCheck());
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_auriaya_sentinel_blast_SpellScript::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_auriaya_sentinel_blast_SpellScript();
}
};
class achievement_auriaya_crazy_cat_lady : public AchievementCriteriaScript
{
public:
achievement_auriaya_crazy_cat_lady() : AchievementCriteriaScript("achievement_auriaya_crazy_cat_lady") {}
bool OnCheck(Player* /*player*/, Unit* target, uint32 /*criteria_id*/) override
{
if (target)
if (InstanceScript* instance = target->GetInstanceScript())
if (Creature* cr = ObjectAccessor::GetCreature(*target, instance->GetGuidData(TYPE_AURIAYA)))
return cr->AI()->GetData(DATA_CRAZY_CAT);
return false;
}
};
class achievement_auriaya_nine_lives : public AchievementCriteriaScript
{
public:
achievement_auriaya_nine_lives() : AchievementCriteriaScript("achievement_auriaya_nine_lives") {}
bool OnCheck(Player* /*player*/, Unit* target, uint32 /*criteria_id*/) override
{
if (target)
if (InstanceScript* instance = target->GetInstanceScript())
if (Creature* cr = ObjectAccessor::GetCreature(*target, instance->GetGuidData(TYPE_AURIAYA)))
return cr->AI()->GetData(DATA_NINE_LIVES);
return false;
}
};
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -15,7 +15,6 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "boss_general_vezax.h"
#include "AccountMgr.h"
#include "AchievementCriteriaScript.h"
#include "BanMgr.h"
@@ -29,6 +28,665 @@
#include "WorldSession.h"
#include "ulduar.h"
enum VezaxSpellData
{
SPELL_VEZAX_BERSERK = 26662,
SPELL_VEZAX_SHADOW_CRASH = 62660,
SPELL_VEZAX_SHADOW_CRASH_DMG = 62659,
SPELL_VEZAX_SHADOW_CRASH_AREA_AURA = 63277,
SPELL_VEZAX_SHADOW_CRASH_AURA = 65269,
SPELL_SEARING_FLAMES = 62661,
SPELL_SURGE_OF_DARKNESS = 62662,
SPELL_MARK_OF_THE_FACELESS_AURA = 63276,
SPELL_MARK_OF_THE_FACELESS_EFFECT = 63278,
SPELL_AURA_OF_DESPAIR_1 = 62692,
SPELL_AURA_OF_DESPAIR_2 = 64848,
SPELL_CORRUPTED_RAGE = 68415,
SPELL_CORRUPTED_WISDOM = 64646,
SPELL_SHAMANISTIC_RAGE = 30823,
SPELL_JUDGEMENTS_OF_THE_WISDOM_RANK_1 = 31876,
SPELL_SUMMON_SARONITE_VAPORS = 63081,
NPC_SARONITE_VAPORS = 33488,
SPELL_SARONITE_VAPORS_DMG = 63338,
SPELL_SARONITE_VAPORS_ENERGIZE = 63337,
SPELL_SARONITE_VAPORS_AURA = 63323,
SPELL_SARONITE_VAPORS_DUMMYAURA = 63322,
SPELL_SARONITE_ANIMUS_FORMATION_VISUAL = 63319,
SPELL_SUMMON_SARONITE_ANIMUS = 63145,
SPELL_SARONITE_BARRIER = 63364,
SPELL_PROFOUND_DARKNESS = 63420,
};
enum VezaxNpcs
{
// NPC_VEZAX = 33271,
// NPC_VEZAX_BUNNY = 33500,
NPC_SARONITE_ANIMUS = 33524,
};
enum VezaxGOs
{
// GO_VEZAX_DOOR = 194750,
};
enum VezaxEvents
{
EVENT_SPELL_VEZAX_SHADOW_CRASH = 1,
EVENT_SPELL_SEARING_FLAMES = 2,
EVENT_SPELL_SURGE_OF_DARKNESS = 3,
EVENT_SPELL_MARK_OF_THE_FACELESS = 4,
EVENT_SPELL_SUMMON_SARONITE_VAPORS = 5,
EVENT_SARONITE_VAPORS_SWIRL = 6,
EVENT_SPELL_SUMMON_SARONITE_ANIMUS = 7,
EVENT_DESPAWN_SARONITE_VAPORS = 8,
EVENT_SPELL_PROFOUND_DARKNESS = 9,
EVENT_BERSERK = 10,
EVENT_RESTORE_TARGET = 11,
};
enum VezaxText
{
SAY_AGGRO = 0,
SAY_SLAY = 1,
SAY_SURGE_OF_DARKNESS = 2,
SAY_DEATH = 3,
SAY_BERSERK = 4,
SAY_HARDMODE = 5,
SAY_EMOTE_ANIMUS = 6,
SAY_EMOTE_BARRIER = 7,
SAY_EMOTE_SURGE_OF_DARKNESS = 8,
};
enum VaporsText
{
SAY_EMOTE_VAPORS = 0,
};
class boss_vezax : public CreatureScript
{
public:
boss_vezax() : CreatureScript("boss_vezax") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return GetUlduarAI<boss_vezaxAI>(pCreature);
}
struct boss_vezaxAI : public ScriptedAI
{
boss_vezaxAI(Creature* pCreature) : ScriptedAI(pCreature), summons(me)
{
pInstance = pCreature->GetInstanceScript();
}
EventMap events;
SummonList summons;
uint8 vaporsCount;
bool hardmodeAvailable;
bool berserk;
bool bAchievShadowdodger;
InstanceScript* pInstance;
void Reset() override
{
vaporsCount = 0;
hardmodeAvailable = true;
berserk = false;
bAchievShadowdodger = true;
events.Reset();
summons.DespawnAll();
me->SetLootMode(1);
if (pInstance)
pInstance->SetData(TYPE_VEZAX, NOT_STARTED);
}
void JustReachedHome() override
{
me->setActive(false);
}
void JustEngagedWith(Unit* /*pWho*/) override
{
me->setActive(true);
me->SetInCombatWithZone();
events.Reset();
events.RescheduleEvent(EVENT_SPELL_VEZAX_SHADOW_CRASH, 13s);
events.RescheduleEvent(EVENT_SPELL_SEARING_FLAMES, 10s, 1);
events.RescheduleEvent(EVENT_SPELL_SURGE_OF_DARKNESS, 63s);
events.RescheduleEvent(EVENT_SPELL_MARK_OF_THE_FACELESS, 20s);
events.RescheduleEvent(EVENT_SPELL_SUMMON_SARONITE_VAPORS, 30s);
events.RescheduleEvent(EVENT_BERSERK, 10min);
Talk(SAY_AGGRO);
if (pInstance)
pInstance->SetData(TYPE_VEZAX, IN_PROGRESS);
me->CastSpell(me, SPELL_AURA_OF_DESPAIR_1, true);
}
void DoAction(int32 param) override
{
switch( param )
{
case 1:
hardmodeAvailable = false;
break;
case 2:
me->RemoveAura(SPELL_SARONITE_BARRIER);
me->SetLootMode(3);
break;
}
}
uint32 GetData(uint32 id) const override
{
switch (id)
{
case 1:
return (me->GetLootMode() == 3 ? 1 : 0);
case 2:
return (bAchievShadowdodger ? 1 : 0);
}
return 0;
}
void SpellHitTarget(Unit* target, SpellInfo const* spell) override
{
if (target && spell && target->GetTypeId() == TYPEID_PLAYER && spell->Id == SPELL_VEZAX_SHADOW_CRASH_DMG)
bAchievShadowdodger = false;
}
void UpdateAI(uint32 diff) override
{
if( !UpdateVictim() )
return;
if( !berserk && (me->GetPositionX() < 1720.0f || me->GetPositionX() > 1940.0f || me->GetPositionY() < 20.0f || me->GetPositionY() > 210.0f) )
events.RescheduleEvent(EVENT_BERSERK, 1ms);
events.Update(diff);
if( me->HasUnitState(UNIT_STATE_CASTING) )
return;
switch( events.ExecuteEvent() )
{
case 0:
break;
case EVENT_BERSERK:
berserk = true;
me->CastSpell(me, SPELL_VEZAX_BERSERK, true);
Talk(SAY_BERSERK);
break;
case EVENT_SPELL_VEZAX_SHADOW_CRASH:
{
events.Repeat(10s);
std::vector<Player*> players;
Map::PlayerList const& pl = me->GetMap()->GetPlayers();
for( Map::PlayerList::const_iterator itr = pl.begin(); itr != pl.end(); ++itr )
{
Player* temp = itr->GetSource();
if( temp->IsAlive() && temp->GetDistance(me) > 15.0f )
players.push_back(temp);
}
if (!players.empty())
{
me->setAttackTimer(BASE_ATTACK, 2000);
Player* target = players.at(urand(0, players.size() - 1));
me->SetGuidValue(UNIT_FIELD_TARGET, target->GetGUID());
me->CastSpell(target, SPELL_VEZAX_SHADOW_CRASH, false);
events.ScheduleEvent(EVENT_RESTORE_TARGET, 750ms);
}
}
break;
case EVENT_RESTORE_TARGET:
if (me->GetVictim())
me->SetGuidValue(UNIT_FIELD_TARGET, me->GetVictim()->GetGUID());
break;
case EVENT_SPELL_SEARING_FLAMES:
if(!me->HasAura(SPELL_SARONITE_BARRIER))
me->CastSpell(me->GetVictim(), SPELL_SEARING_FLAMES, false);
events.Repeat(me->GetMap()->Is25ManRaid() ? 8s : 15s);
break;
case EVENT_SPELL_SURGE_OF_DARKNESS:
Talk(SAY_SURGE_OF_DARKNESS);
Talk(SAY_EMOTE_SURGE_OF_DARKNESS);
me->CastSpell(me, SPELL_SURGE_OF_DARKNESS, false);
events.Repeat(63s);
events.DelayEvents(10000, 1);
break;
case EVENT_SPELL_MARK_OF_THE_FACELESS:
{
std::vector<Player*> outside;
std::vector<Player*> inside;
Map::PlayerList const& pl = me->GetMap()->GetPlayers();
for( Map::PlayerList::const_iterator itr = pl.begin(); itr != pl.end(); ++itr )
if( Player* tmp = itr->GetSource() )
if( tmp->IsAlive() )
{
if( tmp->GetDistance(me) > 15.0f )
outside.push_back(tmp);
else
inside.push_back(tmp);
}
Player* t = nullptr;
if( outside.size() >= uint8(me->GetMap()->Is25ManRaid() ? 9 : 4) )
t = outside.at(urand(0, outside.size() - 1));
else if( !inside.empty() )
t = inside.at(urand(0, inside.size() - 1));
if (t)
me->CastSpell(t, SPELL_MARK_OF_THE_FACELESS_AURA, false);
events.Repeat(40s);
}
break;
case EVENT_SPELL_SUMMON_SARONITE_VAPORS:
{
vaporsCount++;
me->CastSpell(me, SPELL_SUMMON_SARONITE_VAPORS, false);
if( vaporsCount < 6 || !hardmodeAvailable )
events.Repeat(30s);
else
{
for (ObjectGuid const& guid : summons)
if (Creature* sv = ObjectAccessor::GetCreature(*me, guid))
{
sv->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
sv->GetMotionMaster()->MoveIdle();
sv->GetMotionMaster()->MoveCharge(1852.78f, 81.38f, 342.461f, 28.0f);
}
events.DelayEvents(12000, 0);
events.DelayEvents(12000, 1);
events.ScheduleEvent(EVENT_SARONITE_VAPORS_SWIRL, 6s);
}
}
break;
case EVENT_SARONITE_VAPORS_SWIRL:
if (summons.size())
{
Talk(SAY_EMOTE_ANIMUS);
if( Creature* sv = ObjectAccessor::GetCreature(*me, *(summons.begin())) )
sv->CastSpell(sv, SPELL_SARONITE_ANIMUS_FORMATION_VISUAL, true);
events.ScheduleEvent(EVENT_SPELL_SUMMON_SARONITE_ANIMUS, 2s);
break;
}
break;
case EVENT_SPELL_SUMMON_SARONITE_ANIMUS:
if (summons.size())
{
Talk(SAY_HARDMODE);
Talk(SAY_EMOTE_BARRIER);
me->CastSpell(me, SPELL_SARONITE_BARRIER, true);
if( Creature* sv = ObjectAccessor::GetCreature(*me, *(summons.begin())) )
sv->CastSpell(sv, SPELL_SUMMON_SARONITE_ANIMUS, true);
events.ScheduleEvent(EVENT_DESPAWN_SARONITE_VAPORS, 2500ms);
break;
}
break;
case EVENT_DESPAWN_SARONITE_VAPORS:
summons.DespawnEntry(NPC_SARONITE_VAPORS);
break;
}
DoMeleeAttackIfReady();
}
void JustDied(Unit* /*killer*/) override
{
summons.DespawnAll();
if (pInstance)
pInstance->SetData(TYPE_VEZAX, DONE);
Talk(SAY_DEATH);
if( GameObject* door = me->FindNearestGameObject(GO_VEZAX_DOOR, 500.0f) )
if( door->GetGoState() != GO_STATE_ACTIVE )
{
door->SetLootState(GO_READY);
door->UseDoorOrButton(0, false);
}
}
void KilledUnit(Unit* who) override
{
if( who->GetTypeId() == TYPEID_PLAYER )
Talk(SAY_SLAY);
}
void MoveInLineOfSight(Unit* /*who*/) override {}
void JustSummoned(Creature* summon) override
{
summons.Summon(summon);
}
void SummonedCreatureDespawn(Creature* s) override
{
summons.Despawn(s);
}
};
};
class npc_ulduar_saronite_vapors : public CreatureScript
{
public:
npc_ulduar_saronite_vapors() : CreatureScript("npc_ulduar_saronite_vapors") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return GetUlduarAI<npc_ulduar_saronite_vaporsAI>(pCreature);
}
struct npc_ulduar_saronite_vaporsAI : public NullCreatureAI
{
npc_ulduar_saronite_vaporsAI(Creature* pCreature) : NullCreatureAI(pCreature)
{
pInstance = pCreature->GetInstanceScript();
me->GetMotionMaster()->MoveRandom(4.0f);
}
InstanceScript* pInstance;
void JustDied(Unit* /*killer*/) override
{
me->CastSpell(me, SPELL_SARONITE_VAPORS_AURA, true);
// killed saronite vapors, hard mode unavailable
if( pInstance )
if( Creature* vezax = ObjectAccessor::GetCreature(*me, pInstance->GetGuidData(TYPE_VEZAX)) )
vezax->AI()->DoAction(1);
}
void IsSummonedBy(WorldObject* /*summoner*/) override
{
Talk(SAY_EMOTE_VAPORS);
}
};
};
class npc_ulduar_saronite_animus : public CreatureScript
{
public:
npc_ulduar_saronite_animus() : CreatureScript("npc_ulduar_saronite_animus") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return GetUlduarAI<npc_ulduar_saronite_animusAI>(pCreature);
}
struct npc_ulduar_saronite_animusAI : public ScriptedAI
{
npc_ulduar_saronite_animusAI(Creature* pCreature) : ScriptedAI(pCreature)
{
pInstance = pCreature->GetInstanceScript();
if( pInstance )
if( Creature* vezax = ObjectAccessor::GetCreature(*me, pInstance->GetGuidData(TYPE_VEZAX)) )
vezax->AI()->JustSummoned(me);
timer = 0;
me->SetInCombatWithZone();
}
InstanceScript* pInstance;
uint16 timer;
void JustDied(Unit* /*killer*/) override
{
me->DespawnOrUnsummon(3000);
if( pInstance )
if( Creature* vezax = ObjectAccessor::GetCreature(*me, pInstance->GetGuidData(TYPE_VEZAX)) )
vezax->AI()->DoAction(2);
}
void UpdateAI(uint32 diff) override
{
UpdateVictim();
timer += diff;
if (timer >= 2000)
{
me->CastSpell(me, SPELL_PROFOUND_DARKNESS, true);
timer -= 2000;
}
DoMeleeAttackIfReady();
}
};
};
class spell_aura_of_despair : public SpellScriptLoader
{
public:
spell_aura_of_despair() : SpellScriptLoader("spell_aura_of_despair") { }
class spell_aura_of_despair_AuraScript : public AuraScript
{
PrepareAuraScript(spell_aura_of_despair_AuraScript)
void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
if (Unit* caster = GetCaster())
if (Unit* target = GetTarget())
{
if (target->GetTypeId() != TYPEID_PLAYER)
return;
target->CastSpell(target, SPELL_AURA_OF_DESPAIR_2, true);
if( target->HasSpell(SPELL_SHAMANISTIC_RAGE) )
caster->CastSpell(target, SPELL_CORRUPTED_RAGE, true);
else if( target->HasSpell(SPELL_JUDGEMENTS_OF_THE_WISDOM_RANK_1) || target->HasSpell(SPELL_JUDGEMENTS_OF_THE_WISDOM_RANK_1 + 1) || target->HasSpell(SPELL_JUDGEMENTS_OF_THE_WISDOM_RANK_1 + 2) )
caster->CastSpell(target, SPELL_CORRUPTED_WISDOM, true);
}
}
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
if (Unit* target = GetTarget())
{
target->RemoveAurasDueToSpell(SPELL_AURA_OF_DESPAIR_2);
target->RemoveAurasDueToSpell(SPELL_CORRUPTED_RAGE);
target->RemoveAurasDueToSpell(SPELL_CORRUPTED_WISDOM);
}
}
void Register() override
{
OnEffectApply += AuraEffectApplyFn(spell_aura_of_despair_AuraScript::OnApply, EFFECT_0, SPELL_AURA_PREVENT_REGENERATE_POWER, AURA_EFFECT_HANDLE_REAL);
AfterEffectRemove += AuraEffectRemoveFn(spell_aura_of_despair_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PREVENT_REGENERATE_POWER, AURA_EFFECT_HANDLE_REAL);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_aura_of_despair_AuraScript();
}
};
class spell_mark_of_the_faceless_periodic : public SpellScriptLoader
{
public:
spell_mark_of_the_faceless_periodic() : SpellScriptLoader("spell_mark_of_the_faceless_periodic") { }
class spell_mark_of_the_faceless_periodic_AuraScript : public AuraScript
{
PrepareAuraScript(spell_mark_of_the_faceless_periodic_AuraScript)
void HandleEffectPeriodic(AuraEffect const* /*aurEff*/)
{
if (Unit* caster = GetCaster())
if (Unit* target = GetTarget())
if (target->GetMapId() == 603)
{
int32 dmg = 5000;
caster->CastCustomSpell(target, SPELL_MARK_OF_THE_FACELESS_EFFECT, 0, &dmg, 0, true);
}
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_mark_of_the_faceless_periodic_AuraScript::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_mark_of_the_faceless_periodic_AuraScript();
}
};
class spell_mark_of_the_faceless_drainhealth : public SpellScriptLoader
{
public:
spell_mark_of_the_faceless_drainhealth() : SpellScriptLoader("spell_mark_of_the_faceless_drainhealth") { }
class spell_mark_of_the_faceless_drainhealth_SpellScript : public SpellScript
{
PrepareSpellScript(spell_mark_of_the_faceless_drainhealth_SpellScript);
void FilterTargets(std::list<WorldObject*>& targets)
{
targets.remove(GetExplTargetUnit());
if (targets.empty())
Cancel();
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mark_of_the_faceless_drainhealth_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_DEST_AREA_ENEMY);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_mark_of_the_faceless_drainhealth_SpellScript();
}
};
class spell_saronite_vapors_dummy : public SpellScriptLoader
{
public:
spell_saronite_vapors_dummy() : SpellScriptLoader("spell_saronite_vapors_dummy") { }
class spell_saronite_vapors_dummy_AuraScript : public AuraScript
{
PrepareAuraScript(spell_saronite_vapors_dummy_AuraScript)
void HandleAfterEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
if (Unit* caster = GetCaster())
{
int32 damage = 100 * pow(2.0f, (float)GetStackAmount());
caster->CastCustomSpell(GetTarget(), SPELL_SARONITE_VAPORS_DMG, &damage, nullptr, nullptr, true);
}
}
void Register() override
{
AfterEffectApply += AuraEffectApplyFn(spell_saronite_vapors_dummy_AuraScript::HandleAfterEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_saronite_vapors_dummy_AuraScript();
}
};
class spell_saronite_vapors_damage : public SpellScriptLoader
{
public:
spell_saronite_vapors_damage() : SpellScriptLoader("spell_saronite_vapors_damage") { }
class spell_saronite_vapors_damage_SpellScript : public SpellScript
{
PrepareSpellScript(spell_saronite_vapors_damage_SpellScript);
void HandleAfterHit()
{
if (Unit* caster = GetCaster())
if (GetHitDamage() > 2)
{
int32 mana = GetHitDamage() / 2;
if (Unit* t = GetHitUnit())
caster->CastCustomSpell(t, SPELL_SARONITE_VAPORS_ENERGIZE, &mana, nullptr, nullptr, true);
}
}
void Register() override
{
AfterHit += SpellHitFn(spell_saronite_vapors_damage_SpellScript::HandleAfterHit);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_saronite_vapors_damage_SpellScript();
}
};
class achievement_smell_saronite : public AchievementCriteriaScript
{
public:
achievement_smell_saronite() : AchievementCriteriaScript("achievement_smell_saronite") {}
bool OnCheck(Player* /*player*/, Unit* target, uint32 /*criteria_id*/) override
{
return target && target->GetEntry() == NPC_VEZAX && target->GetTypeId() == TYPEID_UNIT && target->ToCreature()->AI()->GetData(1);
}
};
class achievement_shadowdodger : public AchievementCriteriaScript
{
public:
achievement_shadowdodger() : AchievementCriteriaScript("achievement_shadowdodger") {}
bool OnCheck(Player* /*player*/, Unit* target, uint32 /*criteria_id*/) override
{
return target && target->GetEntry() == NPC_VEZAX && target->GetTypeId() == TYPEID_UNIT && target->ToCreature()->AI()->GetData(2);
}
};
class go_ulduar_pure_saronite_deposit : public GameObjectScript
{
public:
go_ulduar_pure_saronite_deposit() : GameObjectScript("go_ulduar_pure_saronite_deposit") { }
bool OnGossipHello(Player* plr, GameObject* go) override
{
if (plr->IsGameMaster())
return false;
if (InstanceScript* pInstance = go->GetInstanceScript())
if (pInstance->GetData(TYPE_XT002) != DONE && pInstance->GetData(TYPE_MIMIRON) != DONE && pInstance->GetData(TYPE_THORIM) != DONE && pInstance->GetData(TYPE_FREYA) != DONE && pInstance->GetData(TYPE_HODIR) != DONE)
{
std::string accountName;
AccountMgr::GetName(plr->GetSession()->GetAccountId(), accountName);
sBan->BanAccount(accountName, "0s", "Tele hack", "Server");
return true;
}
return false;
}
};
void AddSC_boss_vezax()
{
new boss_vezax();

View File

@@ -1,676 +0,0 @@
#ifndef BOSS_GENERAL_VEZAX_H_
#define BOSS_GENERAL_VEZAX_H_
#include "AccountMgr.h"
#include "AchievementCriteriaScript.h"
#include "BanMgr.h"
#include "CreatureScript.h"
#include "GameObjectScript.h"
#include "PassiveAI.h"
#include "Player.h"
#include "ScriptedCreature.h"
#include "SpellScript.h"
#include "SpellScriptLoader.h"
#include "WorldSession.h"
#include "ulduar.h"
enum VezaxSpellData
{
SPELL_VEZAX_BERSERK = 26662,
SPELL_VEZAX_SHADOW_CRASH = 62660,
SPELL_VEZAX_SHADOW_CRASH_DMG = 62659,
SPELL_VEZAX_SHADOW_CRASH_AREA_AURA = 63277,
SPELL_VEZAX_SHADOW_CRASH_AURA = 65269,
SPELL_SEARING_FLAMES = 62661,
SPELL_SURGE_OF_DARKNESS = 62662,
SPELL_MARK_OF_THE_FACELESS_AURA = 63276,
SPELL_MARK_OF_THE_FACELESS_EFFECT = 63278,
SPELL_AURA_OF_DESPAIR_1 = 62692,
SPELL_AURA_OF_DESPAIR_2 = 64848,
SPELL_CORRUPTED_RAGE = 68415,
SPELL_CORRUPTED_WISDOM = 64646,
SPELL_SHAMANISTIC_RAGE = 30823,
SPELL_JUDGEMENTS_OF_THE_WISDOM_RANK_1 = 31876,
SPELL_SUMMON_SARONITE_VAPORS = 63081,
NPC_SARONITE_VAPORS = 33488,
SPELL_SARONITE_VAPORS_DMG = 63338,
SPELL_SARONITE_VAPORS_ENERGIZE = 63337,
SPELL_SARONITE_VAPORS_AURA = 63323,
SPELL_SARONITE_VAPORS_DUMMYAURA = 63322,
SPELL_SARONITE_ANIMUS_FORMATION_VISUAL = 63319,
SPELL_SUMMON_SARONITE_ANIMUS = 63145,
SPELL_SARONITE_BARRIER = 63364,
SPELL_PROFOUND_DARKNESS = 63420,
};
enum VezaxNpcs
{
// NPC_VEZAX = 33271,
// NPC_VEZAX_BUNNY = 33500,
NPC_SARONITE_ANIMUS = 33524,
};
enum VezaxGOs
{
// GO_VEZAX_DOOR = 194750,
};
enum VezaxEvents
{
EVENT_SPELL_VEZAX_SHADOW_CRASH = 1,
EVENT_SPELL_SEARING_FLAMES = 2,
EVENT_SPELL_SURGE_OF_DARKNESS = 3,
EVENT_SPELL_MARK_OF_THE_FACELESS = 4,
EVENT_SPELL_SUMMON_SARONITE_VAPORS = 5,
EVENT_SARONITE_VAPORS_SWIRL = 6,
EVENT_SPELL_SUMMON_SARONITE_ANIMUS = 7,
EVENT_DESPAWN_SARONITE_VAPORS = 8,
EVENT_SPELL_PROFOUND_DARKNESS = 9,
EVENT_BERSERK = 10,
EVENT_RESTORE_TARGET = 11,
};
enum VezaxText
{
SAY_AGGRO = 0,
SAY_SLAY = 1,
SAY_SURGE_OF_DARKNESS = 2,
SAY_DEATH = 3,
SAY_BERSERK = 4,
SAY_HARDMODE = 5,
SAY_EMOTE_ANIMUS = 6,
SAY_EMOTE_BARRIER = 7,
SAY_EMOTE_SURGE_OF_DARKNESS = 8,
};
enum VaporsText
{
SAY_EMOTE_VAPORS = 0,
};
class boss_vezax : public CreatureScript
{
public:
boss_vezax() : CreatureScript("boss_vezax") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return GetUlduarAI<boss_vezaxAI>(pCreature);
}
struct boss_vezaxAI : public ScriptedAI
{
boss_vezaxAI(Creature* pCreature) : ScriptedAI(pCreature), summons(me)
{
pInstance = pCreature->GetInstanceScript();
}
EventMap events;
SummonList summons;
uint8 vaporsCount;
bool hardmodeAvailable;
bool berserk;
bool bAchievShadowdodger;
InstanceScript* pInstance;
void Reset() override
{
vaporsCount = 0;
hardmodeAvailable = true;
berserk = false;
bAchievShadowdodger = true;
events.Reset();
summons.DespawnAll();
me->SetLootMode(1);
if (pInstance)
pInstance->SetData(TYPE_VEZAX, NOT_STARTED);
}
void JustReachedHome() override
{
me->setActive(false);
}
void JustEngagedWith(Unit* /*pWho*/) override
{
me->setActive(true);
me->SetInCombatWithZone();
events.Reset();
events.RescheduleEvent(EVENT_SPELL_VEZAX_SHADOW_CRASH, 13s);
events.RescheduleEvent(EVENT_SPELL_SEARING_FLAMES, 10s, 1);
events.RescheduleEvent(EVENT_SPELL_SURGE_OF_DARKNESS, 63s);
events.RescheduleEvent(EVENT_SPELL_MARK_OF_THE_FACELESS, 20s);
events.RescheduleEvent(EVENT_SPELL_SUMMON_SARONITE_VAPORS, 30s);
events.RescheduleEvent(EVENT_BERSERK, 10min);
Talk(SAY_AGGRO);
if (pInstance)
pInstance->SetData(TYPE_VEZAX, IN_PROGRESS);
me->CastSpell(me, SPELL_AURA_OF_DESPAIR_1, true);
}
void DoAction(int32 param) override
{
switch( param )
{
case 1:
hardmodeAvailable = false;
break;
case 2:
me->RemoveAura(SPELL_SARONITE_BARRIER);
me->SetLootMode(3);
break;
}
}
uint32 GetData(uint32 id) const override
{
switch (id)
{
case 1:
return (me->GetLootMode() == 3 ? 1 : 0);
case 2:
return (bAchievShadowdodger ? 1 : 0);
}
return 0;
}
void SpellHitTarget(Unit* target, SpellInfo const* spell) override
{
if (target && spell && target->GetTypeId() == TYPEID_PLAYER && spell->Id == SPELL_VEZAX_SHADOW_CRASH_DMG)
bAchievShadowdodger = false;
}
void UpdateAI(uint32 diff) override
{
if( !UpdateVictim() )
return;
if( !berserk && (me->GetPositionX() < 1720.0f || me->GetPositionX() > 1940.0f || me->GetPositionY() < 20.0f || me->GetPositionY() > 210.0f) )
events.RescheduleEvent(EVENT_BERSERK, 1ms);
events.Update(diff);
if( me->HasUnitState(UNIT_STATE_CASTING) )
return;
switch( events.ExecuteEvent() )
{
case 0:
break;
case EVENT_BERSERK:
berserk = true;
me->CastSpell(me, SPELL_VEZAX_BERSERK, true);
Talk(SAY_BERSERK);
break;
case EVENT_SPELL_VEZAX_SHADOW_CRASH:
{
events.Repeat(10s);
std::vector<Player*> players;
Map::PlayerList const& pl = me->GetMap()->GetPlayers();
for( Map::PlayerList::const_iterator itr = pl.begin(); itr != pl.end(); ++itr )
{
Player* temp = itr->GetSource();
if( temp->IsAlive() && temp->GetDistance(me) > 15.0f )
players.push_back(temp);
}
if (!players.empty())
{
me->setAttackTimer(BASE_ATTACK, 2000);
Player* target = players.at(urand(0, players.size() - 1));
me->SetGuidValue(UNIT_FIELD_TARGET, target->GetGUID());
me->CastSpell(target, SPELL_VEZAX_SHADOW_CRASH, false);
events.ScheduleEvent(EVENT_RESTORE_TARGET, 750ms);
}
}
break;
case EVENT_RESTORE_TARGET:
if (me->GetVictim())
me->SetGuidValue(UNIT_FIELD_TARGET, me->GetVictim()->GetGUID());
break;
case EVENT_SPELL_SEARING_FLAMES:
if(!me->HasAura(SPELL_SARONITE_BARRIER))
me->CastSpell(me->GetVictim(), SPELL_SEARING_FLAMES, false);
events.Repeat(me->GetMap()->Is25ManRaid() ? 8s : 15s);
break;
case EVENT_SPELL_SURGE_OF_DARKNESS:
Talk(SAY_SURGE_OF_DARKNESS);
Talk(SAY_EMOTE_SURGE_OF_DARKNESS);
me->CastSpell(me, SPELL_SURGE_OF_DARKNESS, false);
events.Repeat(63s);
events.DelayEvents(10000, 1);
break;
case EVENT_SPELL_MARK_OF_THE_FACELESS:
{
std::vector<Player*> outside;
std::vector<Player*> inside;
Map::PlayerList const& pl = me->GetMap()->GetPlayers();
for( Map::PlayerList::const_iterator itr = pl.begin(); itr != pl.end(); ++itr )
if( Player* tmp = itr->GetSource() )
if( tmp->IsAlive() )
{
if( tmp->GetDistance(me) > 15.0f )
outside.push_back(tmp);
else
inside.push_back(tmp);
}
Player* t = nullptr;
if( outside.size() >= uint8(me->GetMap()->Is25ManRaid() ? 9 : 4) )
t = outside.at(urand(0, outside.size() - 1));
else if( !inside.empty() )
t = inside.at(urand(0, inside.size() - 1));
if (t)
me->CastSpell(t, SPELL_MARK_OF_THE_FACELESS_AURA, false);
events.Repeat(40s);
}
break;
case EVENT_SPELL_SUMMON_SARONITE_VAPORS:
{
vaporsCount++;
me->CastSpell(me, SPELL_SUMMON_SARONITE_VAPORS, false);
if( vaporsCount < 6 || !hardmodeAvailable )
events.Repeat(30s);
else
{
for (ObjectGuid const& guid : summons)
if (Creature* sv = ObjectAccessor::GetCreature(*me, guid))
{
sv->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
sv->GetMotionMaster()->MoveIdle();
sv->GetMotionMaster()->MoveCharge(1852.78f, 81.38f, 342.461f, 28.0f);
}
events.DelayEvents(12000, 0);
events.DelayEvents(12000, 1);
events.ScheduleEvent(EVENT_SARONITE_VAPORS_SWIRL, 6s);
}
}
break;
case EVENT_SARONITE_VAPORS_SWIRL:
if (summons.size())
{
Talk(SAY_EMOTE_ANIMUS);
if( Creature* sv = ObjectAccessor::GetCreature(*me, *(summons.begin())) )
sv->CastSpell(sv, SPELL_SARONITE_ANIMUS_FORMATION_VISUAL, true);
events.ScheduleEvent(EVENT_SPELL_SUMMON_SARONITE_ANIMUS, 2s);
break;
}
break;
case EVENT_SPELL_SUMMON_SARONITE_ANIMUS:
if (summons.size())
{
Talk(SAY_HARDMODE);
Talk(SAY_EMOTE_BARRIER);
me->CastSpell(me, SPELL_SARONITE_BARRIER, true);
if( Creature* sv = ObjectAccessor::GetCreature(*me, *(summons.begin())) )
sv->CastSpell(sv, SPELL_SUMMON_SARONITE_ANIMUS, true);
events.ScheduleEvent(EVENT_DESPAWN_SARONITE_VAPORS, 2500ms);
break;
}
break;
case EVENT_DESPAWN_SARONITE_VAPORS:
summons.DespawnEntry(NPC_SARONITE_VAPORS);
break;
}
DoMeleeAttackIfReady();
}
void JustDied(Unit* /*killer*/) override
{
summons.DespawnAll();
if (pInstance)
pInstance->SetData(TYPE_VEZAX, DONE);
Talk(SAY_DEATH);
if( GameObject* door = me->FindNearestGameObject(GO_VEZAX_DOOR, 500.0f) )
if( door->GetGoState() != GO_STATE_ACTIVE )
{
door->SetLootState(GO_READY);
door->UseDoorOrButton(0, false);
}
}
void KilledUnit(Unit* who) override
{
if( who->GetTypeId() == TYPEID_PLAYER )
Talk(SAY_SLAY);
}
void MoveInLineOfSight(Unit* /*who*/) override {}
void JustSummoned(Creature* summon) override
{
summons.Summon(summon);
}
void SummonedCreatureDespawn(Creature* s) override
{
summons.Despawn(s);
}
};
};
class npc_ulduar_saronite_vapors : public CreatureScript
{
public:
npc_ulduar_saronite_vapors() : CreatureScript("npc_ulduar_saronite_vapors") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return GetUlduarAI<npc_ulduar_saronite_vaporsAI>(pCreature);
}
struct npc_ulduar_saronite_vaporsAI : public NullCreatureAI
{
npc_ulduar_saronite_vaporsAI(Creature* pCreature) : NullCreatureAI(pCreature)
{
pInstance = pCreature->GetInstanceScript();
me->GetMotionMaster()->MoveRandom(4.0f);
}
InstanceScript* pInstance;
void JustDied(Unit* /*killer*/) override
{
me->CastSpell(me, SPELL_SARONITE_VAPORS_AURA, true);
// killed saronite vapors, hard mode unavailable
if( pInstance )
if( Creature* vezax = ObjectAccessor::GetCreature(*me, pInstance->GetGuidData(TYPE_VEZAX)) )
vezax->AI()->DoAction(1);
}
void IsSummonedBy(WorldObject* /*summoner*/) override
{
Talk(SAY_EMOTE_VAPORS);
}
};
};
class npc_ulduar_saronite_animus : public CreatureScript
{
public:
npc_ulduar_saronite_animus() : CreatureScript("npc_ulduar_saronite_animus") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return GetUlduarAI<npc_ulduar_saronite_animusAI>(pCreature);
}
struct npc_ulduar_saronite_animusAI : public ScriptedAI
{
npc_ulduar_saronite_animusAI(Creature* pCreature) : ScriptedAI(pCreature)
{
pInstance = pCreature->GetInstanceScript();
if( pInstance )
if( Creature* vezax = ObjectAccessor::GetCreature(*me, pInstance->GetGuidData(TYPE_VEZAX)) )
vezax->AI()->JustSummoned(me);
timer = 0;
me->SetInCombatWithZone();
}
InstanceScript* pInstance;
uint16 timer;
void JustDied(Unit* /*killer*/) override
{
me->DespawnOrUnsummon(3000);
if( pInstance )
if( Creature* vezax = ObjectAccessor::GetCreature(*me, pInstance->GetGuidData(TYPE_VEZAX)) )
vezax->AI()->DoAction(2);
}
void UpdateAI(uint32 diff) override
{
UpdateVictim();
timer += diff;
if (timer >= 2000)
{
me->CastSpell(me, SPELL_PROFOUND_DARKNESS, true);
timer -= 2000;
}
DoMeleeAttackIfReady();
}
};
};
class spell_aura_of_despair : public SpellScriptLoader
{
public:
spell_aura_of_despair() : SpellScriptLoader("spell_aura_of_despair") { }
class spell_aura_of_despair_AuraScript : public AuraScript
{
PrepareAuraScript(spell_aura_of_despair_AuraScript)
void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
if (Unit* caster = GetCaster())
if (Unit* target = GetTarget())
{
if (target->GetTypeId() != TYPEID_PLAYER)
return;
target->CastSpell(target, SPELL_AURA_OF_DESPAIR_2, true);
if( target->HasSpell(SPELL_SHAMANISTIC_RAGE) )
caster->CastSpell(target, SPELL_CORRUPTED_RAGE, true);
else if( target->HasSpell(SPELL_JUDGEMENTS_OF_THE_WISDOM_RANK_1) || target->HasSpell(SPELL_JUDGEMENTS_OF_THE_WISDOM_RANK_1 + 1) || target->HasSpell(SPELL_JUDGEMENTS_OF_THE_WISDOM_RANK_1 + 2) )
caster->CastSpell(target, SPELL_CORRUPTED_WISDOM, true);
}
}
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
if (Unit* target = GetTarget())
{
target->RemoveAurasDueToSpell(SPELL_AURA_OF_DESPAIR_2);
target->RemoveAurasDueToSpell(SPELL_CORRUPTED_RAGE);
target->RemoveAurasDueToSpell(SPELL_CORRUPTED_WISDOM);
}
}
void Register() override
{
OnEffectApply += AuraEffectApplyFn(spell_aura_of_despair_AuraScript::OnApply, EFFECT_0, SPELL_AURA_PREVENT_REGENERATE_POWER, AURA_EFFECT_HANDLE_REAL);
AfterEffectRemove += AuraEffectRemoveFn(spell_aura_of_despair_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PREVENT_REGENERATE_POWER, AURA_EFFECT_HANDLE_REAL);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_aura_of_despair_AuraScript();
}
};
class spell_mark_of_the_faceless_periodic : public SpellScriptLoader
{
public:
spell_mark_of_the_faceless_periodic() : SpellScriptLoader("spell_mark_of_the_faceless_periodic") { }
class spell_mark_of_the_faceless_periodic_AuraScript : public AuraScript
{
PrepareAuraScript(spell_mark_of_the_faceless_periodic_AuraScript)
void HandleEffectPeriodic(AuraEffect const* /*aurEff*/)
{
if (Unit* caster = GetCaster())
if (Unit* target = GetTarget())
if (target->GetMapId() == 603)
{
int32 dmg = 5000;
caster->CastCustomSpell(target, SPELL_MARK_OF_THE_FACELESS_EFFECT, 0, &dmg, 0, true);
}
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_mark_of_the_faceless_periodic_AuraScript::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_mark_of_the_faceless_periodic_AuraScript();
}
};
class spell_mark_of_the_faceless_drainhealth : public SpellScriptLoader
{
public:
spell_mark_of_the_faceless_drainhealth() : SpellScriptLoader("spell_mark_of_the_faceless_drainhealth") { }
class spell_mark_of_the_faceless_drainhealth_SpellScript : public SpellScript
{
PrepareSpellScript(spell_mark_of_the_faceless_drainhealth_SpellScript);
void FilterTargets(std::list<WorldObject*>& targets)
{
targets.remove(GetExplTargetUnit());
if (targets.empty())
Cancel();
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mark_of_the_faceless_drainhealth_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_DEST_AREA_ENEMY);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_mark_of_the_faceless_drainhealth_SpellScript();
}
};
class spell_saronite_vapors_dummy : public SpellScriptLoader
{
public:
spell_saronite_vapors_dummy() : SpellScriptLoader("spell_saronite_vapors_dummy") { }
class spell_saronite_vapors_dummy_AuraScript : public AuraScript
{
PrepareAuraScript(spell_saronite_vapors_dummy_AuraScript)
void HandleAfterEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
if (Unit* caster = GetCaster())
{
int32 damage = 100 * pow(2.0f, (float)GetStackAmount());
caster->CastCustomSpell(GetTarget(), SPELL_SARONITE_VAPORS_DMG, &damage, nullptr, nullptr, true);
}
}
void Register() override
{
AfterEffectApply += AuraEffectApplyFn(spell_saronite_vapors_dummy_AuraScript::HandleAfterEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_saronite_vapors_dummy_AuraScript();
}
};
class spell_saronite_vapors_damage : public SpellScriptLoader
{
public:
spell_saronite_vapors_damage() : SpellScriptLoader("spell_saronite_vapors_damage") { }
class spell_saronite_vapors_damage_SpellScript : public SpellScript
{
PrepareSpellScript(spell_saronite_vapors_damage_SpellScript);
void HandleAfterHit()
{
if (Unit* caster = GetCaster())
if (GetHitDamage() > 2)
{
int32 mana = GetHitDamage() / 2;
if (Unit* t = GetHitUnit())
caster->CastCustomSpell(t, SPELL_SARONITE_VAPORS_ENERGIZE, &mana, nullptr, nullptr, true);
}
}
void Register() override
{
AfterHit += SpellHitFn(spell_saronite_vapors_damage_SpellScript::HandleAfterHit);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_saronite_vapors_damage_SpellScript();
}
};
class achievement_smell_saronite : public AchievementCriteriaScript
{
public:
achievement_smell_saronite() : AchievementCriteriaScript("achievement_smell_saronite") {}
bool OnCheck(Player* /*player*/, Unit* target, uint32 /*criteria_id*/) override
{
return target && target->GetEntry() == NPC_VEZAX && target->GetTypeId() == TYPEID_UNIT && target->ToCreature()->AI()->GetData(1);
}
};
class achievement_shadowdodger : public AchievementCriteriaScript
{
public:
achievement_shadowdodger() : AchievementCriteriaScript("achievement_shadowdodger") {}
bool OnCheck(Player* /*player*/, Unit* target, uint32 /*criteria_id*/) override
{
return target && target->GetEntry() == NPC_VEZAX && target->GetTypeId() == TYPEID_UNIT && target->ToCreature()->AI()->GetData(2);
}
};
class go_ulduar_pure_saronite_deposit : public GameObjectScript
{
public:
go_ulduar_pure_saronite_deposit() : GameObjectScript("go_ulduar_pure_saronite_deposit") { }
bool OnGossipHello(Player* plr, GameObject* go) override
{
if (plr->IsGameMaster())
return false;
if (InstanceScript* pInstance = go->GetInstanceScript())
if (pInstance->GetData(TYPE_XT002) != DONE && pInstance->GetData(TYPE_MIMIRON) != DONE && pInstance->GetData(TYPE_THORIM) != DONE && pInstance->GetData(TYPE_FREYA) != DONE && pInstance->GetData(TYPE_HODIR) != DONE)
{
std::string accountName;
AccountMgr::GetName(plr->GetSession()->GetAccountId(), accountName);
sBan->BanAccount(accountName, "0s", "Tele hack", "Server");
return true;
}
return false;
}
};
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -15,7 +15,6 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "boss_ignis.h"
#include "AchievementCriteriaScript.h"
#include "CreatureScript.h"
#include "GameTime.h"
@@ -28,6 +27,527 @@
#include "Vehicle.h"
#include "ulduar.h"
#define SPELL_FLAME_JETS_10 62680
#define SPELL_FLAME_JETS_25 63472
#define S_FLAME_JETS RAID_MODE(SPELL_FLAME_JETS_10, SPELL_FLAME_JETS_25)
#define SPELL_SCORCH_10 62546
#define SPELL_SCORCH_25 63474
#define S_SCORCH RAID_MODE(SPELL_SCORCH_10, SPELL_SCORCH_25)
#define SPELL_ACTIVATE_CONSTRUCT 62488
#define SPELL_STRENGTH_OF_THE_CREATOR 64473
#define SPELL_SLAG_POT_10 62717
#define SPELL_SLAG_POT_25 63477
#define S_SLAG_POT RAID_MODE(SPELL_SLAG_POT_10, SPELL_SLAG_POT_25)
#define SPELL_BERSERK 64238
#define SPELL_GRAB 62707
#define SPELL_GRAB_TRIGGERED 62708
#define SPELL_GRAB_CONTROL_2 62711
#define SPELL_SCORCHED_GROUND_10 62548
#define SPELL_SCORCHED_GROUND_25 63476
#define S_SCORCHED_GROUND RAID_MODE(SPELL_SCORCHED_GROUND_10, SPELL_SCORCHED_GROUND_25)
#define SPELL_HEAT_AREA 62343
#define SPELL_HEAT_BUFF 65667
#define SPELL_MOLTEN 62373
#define SPELL_BRITTLE_10 62382
#define SPELL_BRITTLE_25 67114
#define S_BRITTLE RAID_MODE(SPELL_BRITTLE_10, SPELL_BRITTLE_25)
#define SPELL_SHATTER 62383
#define BOSS_IGNIS 33118
#define NPC_IRON_CONSTRUCT 33121
#define NPC_SCORCHED_GROUND 33123
#define NPC_WATER_TRIGGER 22515
enum Texts
{
SAY_AGGRO = 0,
SAY_SUMMON = 1,
SAY_SLAG_POT = 2,
SAY_SCORCH = 3,
SAY_SLAY = 4,
SAY_BERSERK = 5,
SAY_DEATH = 6,
EMOTE_JETS = 7,
};
#define ACHIEV_STOKIN_THE_FURNACE_EVENT 20951
enum eEvents
{
EVENT_NONE = 0,
EVENT_ACTIVATE_CONSTRUCT,
EVENT_SPELL_SCORCH,
EVENT_ENABLE_ROTATE,
EVENT_SPELL_FLAME_JETS,
EVENT_GRAB,
};
class npc_ulduar_iron_construct : public CreatureScript
{
public:
npc_ulduar_iron_construct() : CreatureScript("npc_ulduar_iron_construct") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return GetUlduarAI<npc_ulduar_iron_constructAI>(pCreature);
}
struct npc_ulduar_iron_constructAI : public ScriptedAI
{
npc_ulduar_iron_constructAI(Creature* pCreature) : ScriptedAI(pCreature)
{
me->CastSpell(me, 38757, true);
}
uint16 timer;
void Reset() override
{
timer = 1000;
me->SetReactState(REACT_PASSIVE);
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
}
void JustReachedHome() override
{
me->CastSpell(me, 38757, true);
}
void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
{
if (spell->Id == SPELL_ACTIVATE_CONSTRUCT)
{
me->RemoveAura(38757);
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
me->SetReactState(REACT_AGGRESSIVE);
if (InstanceScript* instance = me->GetInstanceScript())
if (Creature* ignis = ObjectAccessor::GetCreature(*me, instance->GetGuidData(TYPE_IGNIS)))
{
ignis->CastSpell(ignis, SPELL_STRENGTH_OF_THE_CREATOR, true);
AttackStart(ignis->GetVictim());
DoZoneInCombat();
}
}
else if (spell->Id == SPELL_HEAT_BUFF)
{
if (Aura* heat = me->GetAura(SPELL_HEAT_BUFF))
{
if (heat->GetStackAmount() >= 10)
{
if (heat->GetStackAmount() > 10)
{
heat->ModStackAmount(-1);
}
me->CastSpell(me, SPELL_MOLTEN, true);
me->GetThreatMgr().ResetAllThreat();
}
}
}
}
void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType, SpellSchoolMask) override
{
if( damage >= RAID_MODE(3000U, 5000U) && me->GetAura(S_BRITTLE) )
{
me->CastSpell(me, SPELL_SHATTER, true);
Unit::Kill(attacker, me);
if (InstanceScript* instance = me->GetInstanceScript())
if (Creature* ignis = ObjectAccessor::GetCreature(*me, instance->GetGuidData(TYPE_IGNIS)))
ignis->AI()->SetData(1337, 0);
}
}
void JustDied(Unit* /*killer*/) override
{
if (InstanceScript* instance = me->GetInstanceScript())
if (Creature* ignis = ObjectAccessor::GetCreature(*me, instance->GetGuidData(TYPE_IGNIS)))
ignis->RemoveAuraFromStack(SPELL_STRENGTH_OF_THE_CREATOR);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
if (timer <= diff)
{
timer = 1000;
if (Aura* a = me->GetAura(SPELL_MOLTEN))
if (me->FindNearestCreature(NPC_WATER_TRIGGER, 18.0f, true))
{
me->RemoveAura(a);
me->CastSpell(me, S_BRITTLE, true);
}
}
else
timer -= diff;
DoMeleeAttackIfReady();
}
void MoveInLineOfSight(Unit* /*who*/) override {}
};
};
class boss_ignis : public CreatureScript
{
public:
boss_ignis() : CreatureScript("boss_ignis") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return GetUlduarAI<boss_ignisAI>(pCreature);
}
struct boss_ignisAI : public ScriptedAI
{
boss_ignisAI(Creature* pCreature) : ScriptedAI(pCreature) { }
EventMap events;
uint8 counter;
bool bShattered;
uint32 lastShatterMSTime;
void Reset() override
{
events.Reset();
me->SetControlled(false, UNIT_STATE_ROOT);
me->DisableRotate(false);
counter = 0;
bShattered = false;
lastShatterMSTime = 0;
if( InstanceScript* m_pInstance = me->GetInstanceScript() )
{
m_pInstance->SetData(TYPE_IGNIS, NOT_STARTED);
m_pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_STOKIN_THE_FURNACE_EVENT);
}
}
void JustEngagedWith(Unit* /*who*/) override
{
me->setActive(true);
std::list<Creature*> icl;
me->GetCreaturesWithEntryInRange(icl, 300.0f, NPC_IRON_CONSTRUCT);
for( std::list<Creature*>::iterator itr = icl.begin(); itr != icl.end(); ++itr )
{
if (!(*itr)->IsAlive())
{
(*itr)->Respawn();
(*itr)->UpdatePosition((*itr)->GetHomePosition(), true);
(*itr)->StopMovingOnCurrentPos();
}
(*itr)->AI()->Reset();
if (!(*itr)->HasAura(38757))
(*itr)->CastSpell((*itr), 38757, true);
}
bShattered = false;
lastShatterMSTime = 0;
events.Reset();
events.ScheduleEvent(EVENT_ACTIVATE_CONSTRUCT, RAID_MODE(40000, 30000));
events.ScheduleEvent(EVENT_SPELL_SCORCH, 10s);
events.ScheduleEvent(EVENT_SPELL_FLAME_JETS, 32s);
events.ScheduleEvent(EVENT_GRAB, 25s);
Talk(SAY_AGGRO);
DoZoneInCombat();
if( InstanceScript* m_pInstance = me->GetInstanceScript() )
{
m_pInstance->SetData(TYPE_IGNIS, IN_PROGRESS);
m_pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_STOKIN_THE_FURNACE_EVENT);
m_pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_STOKIN_THE_FURNACE_EVENT);
}
}
void SetData(uint32 id, uint32 /*value*/) override
{
if (id == 1337)
{
if (lastShatterMSTime)
if (getMSTimeDiff(lastShatterMSTime, GameTime::GetGameTimeMS().count()) <= 5000)
bShattered = true;
lastShatterMSTime = GameTime::GetGameTimeMS().count();
}
}
uint32 GetData(uint32 id) const override
{
if (id == 1337)
return (bShattered ? 1 : 0);
return 0;
}
void JustReachedHome() override
{
me->setActive(false);
}
void KilledUnit(Unit* victim) override
{
if (victim->GetTypeId() == TYPEID_PLAYER)
Talk(SAY_SLAY);
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_DEATH);
if( me->GetInstanceScript() )
me->GetInstanceScript()->SetData(TYPE_IGNIS, DONE);
std::list<Creature*> icl;
me->GetCreaturesWithEntryInRange(icl, 300.0f, NPC_IRON_CONSTRUCT);
for( std::list<Creature*>::iterator itr = icl.begin(); itr != icl.end(); ++itr )
if ((*itr)->IsAlive() && (*itr)->IsInCombat())
Unit::Kill(*itr, *itr);
}
void SpellHit(Unit* caster, SpellInfo const* spell) override
{
if (caster && spell->Id == SPELL_GRAB_CONTROL_2)
{
//caster->ClearUnitState(UNIT_STATE_ONVEHICLE);
me->CastSpell(caster, S_SLAG_POT, true);
}
}
void MoveInLineOfSight(Unit* /*who*/) override {}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
if( me->GetPositionX() < 490.0f || me->GetPositionX() > 690.0f || me->GetPositionY() < 130.0f || me->GetPositionY() > 410.0f )
{
EnterEvadeMode(EVADE_REASON_OTHER);
return;
}
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{
case 0:
break;
case EVENT_ACTIVATE_CONSTRUCT:
Talk(SAY_SUMMON);
me->CastCustomSpell(SPELL_ACTIVATE_CONSTRUCT, SPELLVALUE_MAX_TARGETS, 1, (Unit*)nullptr, false);
if (++counter >= 20)
{
Talk(SAY_BERSERK);
me->CastSpell(me, SPELL_BERSERK, true);
break;
}
events.RepeatEvent(RAID_MODE(40000, 30000));
break;
case EVENT_SPELL_SCORCH:
Talk(SAY_SCORCH);
me->SetControlled(true, UNIT_STATE_ROOT);
me->DisableRotate(true);
me->SendMovementFlagUpdate();
me->CastSpell(me->GetVictim(), S_SCORCH, false);
events.Repeat(20s);
events.RescheduleEvent(EVENT_ENABLE_ROTATE, 3s);
break;
case EVENT_ENABLE_ROTATE:
me->SetControlled(false, UNIT_STATE_ROOT);
me->DisableRotate(false);
break;
case EVENT_SPELL_FLAME_JETS:
Talk(EMOTE_JETS);
me->CastSpell(me->GetVictim(), S_FLAME_JETS, false);
events.Repeat(25s);
break;
case EVENT_GRAB:
{
std::list<Creature*> icl;
me->GetCreaturesWithEntryInRange(icl, 300.0f, NPC_IRON_CONSTRUCT);
GuidVector playerGUIDs;
Map::PlayerList const& pl = me->GetMap()->GetPlayers();
Player* temp = nullptr;
for( Map::PlayerList::const_iterator itr = pl.begin(); itr != pl.end(); ++itr )
{
temp = itr->GetSource();
if( !temp->IsAlive() || temp->GetExactDist2d(me) > 90.0f )
continue;
if( me->GetVictim() && temp->GetGUID() == me->GetVictim()->GetGUID() )
continue;
bool found = false;
for (std::list<Creature*>::iterator iterator = icl.begin(); iterator != icl.end(); ++iterator)
{
if ((*iterator)->GetVictim() && (*iterator)->GetVictim()->GetGUID() == temp->GetGUID())
{
found = true;
break;
}
}
if( !found )
playerGUIDs.push_back(temp->GetGUID());
}
if( !playerGUIDs.empty() )
{
int8 pos = urand(0, playerGUIDs.size() - 1);
if( Player* pTarget = ObjectAccessor::GetPlayer(*me, playerGUIDs.at(pos)) )
{
Talk(SAY_SLAG_POT);
me->CastSpell(pTarget, SPELL_GRAB, false);
}
}
events.Repeat(24s);
events.DelayEvents(6s);
}
break;
}
DoMeleeAttackIfReady();
}
void EnterEvadeMode(EvadeReason why) override
{
me->SetControlled(false, UNIT_STATE_ROOT);
me->DisableRotate(false);
ScriptedAI::EnterEvadeMode(why);
}
};
};
class spell_ignis_scorch : public SpellScriptLoader
{
public:
spell_ignis_scorch() : SpellScriptLoader("spell_ignis_scorch") { }
class spell_ignis_scorch_AuraScript : public AuraScript
{
PrepareAuraScript(spell_ignis_scorch_AuraScript)
void HandleEffectPeriodic(AuraEffect const* aurEff)
{
if (aurEff->GetTotalTicks() >= 0 && aurEff->GetTickNumber() == uint32(aurEff->GetTotalTicks()))
if (Unit* c = GetCaster())
if (Creature* s = c->SummonCreature(NPC_SCORCHED_GROUND, c->GetPositionX() + 20.0f * cos(c->GetOrientation()), c->GetPositionY() + 20.0f * std::sin(c->GetOrientation()), 361.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 30000))
{
if (!s->FindNearestCreature(NPC_WATER_TRIGGER, 25.0f, true)) // must be away from the water
s->CastSpell(s, (aurEff->GetId() == 62546 ? SPELL_SCORCHED_GROUND_10 : SPELL_SCORCHED_GROUND_25), true);
}
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_ignis_scorch_AuraScript::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_ignis_scorch_AuraScript();
}
};
class spell_ignis_grab_initial : public SpellScriptLoader
{
public:
spell_ignis_grab_initial() : SpellScriptLoader("spell_ignis_grab_initial") { }
class spell_ignis_grab_initial_SpellScript : public SpellScript
{
PrepareSpellScript(spell_ignis_grab_initial_SpellScript);
void HandleScript(SpellEffIndex /*effIndex*/)
{
if (Unit* t = GetHitUnit())
t->CastSpell(t, SPELL_GRAB_TRIGGERED, true);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_ignis_grab_initial_SpellScript::HandleScript, EFFECT_2, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_ignis_grab_initial_SpellScript();
}
};
class spell_ignis_slag_pot : public SpellScriptLoader
{
public:
spell_ignis_slag_pot() : SpellScriptLoader("spell_ignis_slag_pot") { }
class spell_ignis_slag_pot_AuraScript : public AuraScript
{
PrepareAuraScript(spell_ignis_slag_pot_AuraScript)
void HandleEffectPeriodic(AuraEffect const* /*aurEff*/)
{
if (Unit* c = GetCaster())
if (Unit* t = GetTarget())
c->CastSpell(t, (GetId() == 62717 ? 65722 : 65723), true);
}
void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
if (Unit* t = GetTarget())
{
t->ApplySpellImmune(GetId(), IMMUNITY_ID, 62549, true);
t->ApplySpellImmune(GetId(), IMMUNITY_ID, 63475, true);
}
}
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
if (Unit* t = GetTarget())
{
t->ApplySpellImmune(GetId(), IMMUNITY_ID, 62549, false);
t->ApplySpellImmune(GetId(), IMMUNITY_ID, 63475, false);
if (t->IsAlive())
t->CastSpell(t, (GetId() == 62717 ? 62836 : 63536), true);
}
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_ignis_slag_pot_AuraScript::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
OnEffectApply += AuraEffectApplyFn(spell_ignis_slag_pot_AuraScript::OnApply, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL);
AfterEffectRemove += AuraEffectRemoveFn(spell_ignis_slag_pot_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_ignis_slag_pot_AuraScript();
}
};
class achievement_ignis_shattered : public AchievementCriteriaScript
{
public:
achievement_ignis_shattered() : AchievementCriteriaScript("achievement_ignis_shattered") {}
bool OnCheck(Player* /*player*/, Unit* target, uint32 /*criteria_id*/) override
{
if (!target || target->GetTypeId() != TYPEID_UNIT)
return false;
return !!target->ToCreature()->AI()->GetData(1337);
}
};
void AddSC_boss_ignis()
{
new boss_ignis();

View File

@@ -1,537 +0,0 @@
#ifndef BOSS_IGNIS_H_
#define BOSS_IGNIS_H_
#include "AchievementCriteriaScript.h"
#include "CreatureScript.h"
#include "GameTime.h"
#include "Player.h"
#include "ScriptedCreature.h"
#include "SpellAuraEffects.h"
#include "SpellAuras.h"
#include "SpellScript.h"
#include "SpellScriptLoader.h"
#include "Vehicle.h"
#include "ulduar.h"
#define SPELL_FLAME_JETS_10 62680
#define SPELL_FLAME_JETS_25 63472
#define S_FLAME_JETS RAID_MODE(SPELL_FLAME_JETS_10, SPELL_FLAME_JETS_25)
#define SPELL_SCORCH_10 62546
#define SPELL_SCORCH_25 63474
#define S_SCORCH RAID_MODE(SPELL_SCORCH_10, SPELL_SCORCH_25)
#define SPELL_ACTIVATE_CONSTRUCT 62488
#define SPELL_STRENGTH_OF_THE_CREATOR 64473
#define SPELL_SLAG_POT_10 62717
#define SPELL_SLAG_POT_25 63477
#define S_SLAG_POT RAID_MODE(SPELL_SLAG_POT_10, SPELL_SLAG_POT_25)
#define SPELL_BERSERK 64238
#define SPELL_GRAB 62707
#define SPELL_GRAB_TRIGGERED 62708
#define SPELL_GRAB_CONTROL_2 62711
#define SPELL_SCORCHED_GROUND_10 62548
#define SPELL_SCORCHED_GROUND_25 63476
#define S_SCORCHED_GROUND RAID_MODE(SPELL_SCORCHED_GROUND_10, SPELL_SCORCHED_GROUND_25)
#define SPELL_HEAT_AREA 62343
#define SPELL_HEAT_BUFF 65667
#define SPELL_MOLTEN 62373
#define SPELL_BRITTLE_10 62382
#define SPELL_BRITTLE_25 67114
#define S_BRITTLE RAID_MODE(SPELL_BRITTLE_10, SPELL_BRITTLE_25)
#define SPELL_SHATTER 62383
#define BOSS_IGNIS 33118
#define NPC_IRON_CONSTRUCT 33121
#define NPC_SCORCHED_GROUND 33123
#define NPC_WATER_TRIGGER 22515
enum Texts
{
SAY_AGGRO = 0,
SAY_SUMMON = 1,
SAY_SLAG_POT = 2,
SAY_SCORCH = 3,
SAY_SLAY = 4,
SAY_BERSERK = 5,
SAY_DEATH = 6,
EMOTE_JETS = 7,
};
#define ACHIEV_STOKIN_THE_FURNACE_EVENT 20951
enum eEvents
{
EVENT_NONE = 0,
EVENT_ACTIVATE_CONSTRUCT,
EVENT_SPELL_SCORCH,
EVENT_ENABLE_ROTATE,
EVENT_SPELL_FLAME_JETS,
EVENT_GRAB,
};
class npc_ulduar_iron_construct : public CreatureScript
{
public:
npc_ulduar_iron_construct() : CreatureScript("npc_ulduar_iron_construct") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return GetUlduarAI<npc_ulduar_iron_constructAI>(pCreature);
}
struct npc_ulduar_iron_constructAI : public ScriptedAI
{
npc_ulduar_iron_constructAI(Creature* pCreature) : ScriptedAI(pCreature)
{
me->CastSpell(me, 38757, true);
}
uint16 timer;
void Reset() override
{
timer = 1000;
me->SetReactState(REACT_PASSIVE);
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
}
void JustReachedHome() override
{
me->CastSpell(me, 38757, true);
}
void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
{
if (spell->Id == SPELL_ACTIVATE_CONSTRUCT)
{
me->RemoveAura(38757);
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
me->SetReactState(REACT_AGGRESSIVE);
if (InstanceScript* instance = me->GetInstanceScript())
if (Creature* ignis = ObjectAccessor::GetCreature(*me, instance->GetGuidData(TYPE_IGNIS)))
{
ignis->CastSpell(ignis, SPELL_STRENGTH_OF_THE_CREATOR, true);
AttackStart(ignis->GetVictim());
DoZoneInCombat();
}
}
else if (spell->Id == SPELL_HEAT_BUFF)
{
if (Aura* heat = me->GetAura(SPELL_HEAT_BUFF))
{
if (heat->GetStackAmount() >= 10)
{
if (heat->GetStackAmount() > 10)
{
heat->ModStackAmount(-1);
}
me->CastSpell(me, SPELL_MOLTEN, true);
me->GetThreatMgr().ResetAllThreat();
}
}
}
}
void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType, SpellSchoolMask) override
{
if( damage >= RAID_MODE(3000U, 5000U) && me->GetAura(S_BRITTLE) )
{
me->CastSpell(me, SPELL_SHATTER, true);
Unit::Kill(attacker, me);
if (InstanceScript* instance = me->GetInstanceScript())
if (Creature* ignis = ObjectAccessor::GetCreature(*me, instance->GetGuidData(TYPE_IGNIS)))
ignis->AI()->SetData(1337, 0);
}
}
void JustDied(Unit* /*killer*/) override
{
if (InstanceScript* instance = me->GetInstanceScript())
if (Creature* ignis = ObjectAccessor::GetCreature(*me, instance->GetGuidData(TYPE_IGNIS)))
ignis->RemoveAuraFromStack(SPELL_STRENGTH_OF_THE_CREATOR);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
if (timer <= diff)
{
timer = 1000;
if (Aura* a = me->GetAura(SPELL_MOLTEN))
if (me->FindNearestCreature(NPC_WATER_TRIGGER, 18.0f, true))
{
me->RemoveAura(a);
me->CastSpell(me, S_BRITTLE, true);
}
}
else
timer -= diff;
DoMeleeAttackIfReady();
}
void MoveInLineOfSight(Unit* /*who*/) override {}
};
};
class boss_ignis : public CreatureScript
{
public:
boss_ignis() : CreatureScript("boss_ignis") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return GetUlduarAI<boss_ignisAI>(pCreature);
}
struct boss_ignisAI : public ScriptedAI
{
boss_ignisAI(Creature* pCreature) : ScriptedAI(pCreature) { }
EventMap events;
uint8 counter;
bool bShattered;
uint32 lastShatterMSTime;
void Reset() override
{
events.Reset();
me->SetControlled(false, UNIT_STATE_ROOT);
me->DisableRotate(false);
counter = 0;
bShattered = false;
lastShatterMSTime = 0;
if( InstanceScript* m_pInstance = me->GetInstanceScript() )
{
m_pInstance->SetData(TYPE_IGNIS, NOT_STARTED);
m_pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_STOKIN_THE_FURNACE_EVENT);
}
}
void JustEngagedWith(Unit* /*who*/) override
{
me->setActive(true);
std::list<Creature*> icl;
me->GetCreaturesWithEntryInRange(icl, 300.0f, NPC_IRON_CONSTRUCT);
for( std::list<Creature*>::iterator itr = icl.begin(); itr != icl.end(); ++itr )
{
if (!(*itr)->IsAlive())
{
(*itr)->Respawn();
(*itr)->UpdatePosition((*itr)->GetHomePosition(), true);
(*itr)->StopMovingOnCurrentPos();
}
(*itr)->AI()->Reset();
if (!(*itr)->HasAura(38757))
(*itr)->CastSpell((*itr), 38757, true);
}
bShattered = false;
lastShatterMSTime = 0;
events.Reset();
events.ScheduleEvent(EVENT_ACTIVATE_CONSTRUCT, RAID_MODE(40000, 30000));
events.ScheduleEvent(EVENT_SPELL_SCORCH, 10s);
events.ScheduleEvent(EVENT_SPELL_FLAME_JETS, 32s);
events.ScheduleEvent(EVENT_GRAB, 25s);
Talk(SAY_AGGRO);
DoZoneInCombat();
if( InstanceScript* m_pInstance = me->GetInstanceScript() )
{
m_pInstance->SetData(TYPE_IGNIS, IN_PROGRESS);
m_pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_STOKIN_THE_FURNACE_EVENT);
m_pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_STOKIN_THE_FURNACE_EVENT);
}
}
void SetData(uint32 id, uint32 /*value*/) override
{
if (id == 1337)
{
if (lastShatterMSTime)
if (getMSTimeDiff(lastShatterMSTime, GameTime::GetGameTimeMS().count()) <= 5000)
bShattered = true;
lastShatterMSTime = GameTime::GetGameTimeMS().count();
}
}
uint32 GetData(uint32 id) const override
{
if (id == 1337)
return (bShattered ? 1 : 0);
return 0;
}
void JustReachedHome() override
{
me->setActive(false);
}
void KilledUnit(Unit* victim) override
{
if (victim->GetTypeId() == TYPEID_PLAYER)
Talk(SAY_SLAY);
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_DEATH);
if( me->GetInstanceScript() )
me->GetInstanceScript()->SetData(TYPE_IGNIS, DONE);
std::list<Creature*> icl;
me->GetCreaturesWithEntryInRange(icl, 300.0f, NPC_IRON_CONSTRUCT);
for( std::list<Creature*>::iterator itr = icl.begin(); itr != icl.end(); ++itr )
if ((*itr)->IsAlive() && (*itr)->IsInCombat())
Unit::Kill(*itr, *itr);
}
void SpellHit(Unit* caster, SpellInfo const* spell) override
{
if (caster && spell->Id == SPELL_GRAB_CONTROL_2)
{
//caster->ClearUnitState(UNIT_STATE_ONVEHICLE);
me->CastSpell(caster, S_SLAG_POT, true);
}
}
void MoveInLineOfSight(Unit* /*who*/) override {}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
if( me->GetPositionX() < 490.0f || me->GetPositionX() > 690.0f || me->GetPositionY() < 130.0f || me->GetPositionY() > 410.0f )
{
EnterEvadeMode(EVADE_REASON_OTHER);
return;
}
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{
case 0:
break;
case EVENT_ACTIVATE_CONSTRUCT:
Talk(SAY_SUMMON);
me->CastCustomSpell(SPELL_ACTIVATE_CONSTRUCT, SPELLVALUE_MAX_TARGETS, 1, (Unit*)nullptr, false);
if (++counter >= 20)
{
Talk(SAY_BERSERK);
me->CastSpell(me, SPELL_BERSERK, true);
break;
}
events.RepeatEvent(RAID_MODE(40000, 30000));
break;
case EVENT_SPELL_SCORCH:
Talk(SAY_SCORCH);
me->SetControlled(true, UNIT_STATE_ROOT);
me->DisableRotate(true);
me->SendMovementFlagUpdate();
me->CastSpell(me->GetVictim(), S_SCORCH, false);
events.Repeat(20s);
events.RescheduleEvent(EVENT_ENABLE_ROTATE, 3s);
break;
case EVENT_ENABLE_ROTATE:
me->SetControlled(false, UNIT_STATE_ROOT);
me->DisableRotate(false);
break;
case EVENT_SPELL_FLAME_JETS:
Talk(EMOTE_JETS);
me->CastSpell(me->GetVictim(), S_FLAME_JETS, false);
events.Repeat(25s);
break;
case EVENT_GRAB:
{
std::list<Creature*> icl;
me->GetCreaturesWithEntryInRange(icl, 300.0f, NPC_IRON_CONSTRUCT);
GuidVector playerGUIDs;
Map::PlayerList const& pl = me->GetMap()->GetPlayers();
Player* temp = nullptr;
for( Map::PlayerList::const_iterator itr = pl.begin(); itr != pl.end(); ++itr )
{
temp = itr->GetSource();
if( !temp->IsAlive() || temp->GetExactDist2d(me) > 90.0f )
continue;
if( me->GetVictim() && temp->GetGUID() == me->GetVictim()->GetGUID() )
continue;
bool found = false;
for (std::list<Creature*>::iterator iterator = icl.begin(); iterator != icl.end(); ++iterator)
{
if ((*iterator)->GetVictim() && (*iterator)->GetVictim()->GetGUID() == temp->GetGUID())
{
found = true;
break;
}
}
if( !found )
playerGUIDs.push_back(temp->GetGUID());
}
if( !playerGUIDs.empty() )
{
int8 pos = urand(0, playerGUIDs.size() - 1);
if( Player* pTarget = ObjectAccessor::GetPlayer(*me, playerGUIDs.at(pos)) )
{
Talk(SAY_SLAG_POT);
me->CastSpell(pTarget, SPELL_GRAB, false);
}
}
events.Repeat(24s);
events.DelayEvents(6s);
}
break;
}
DoMeleeAttackIfReady();
}
void EnterEvadeMode(EvadeReason why) override
{
me->SetControlled(false, UNIT_STATE_ROOT);
me->DisableRotate(false);
ScriptedAI::EnterEvadeMode(why);
}
};
};
class spell_ignis_scorch : public SpellScriptLoader
{
public:
spell_ignis_scorch() : SpellScriptLoader("spell_ignis_scorch") { }
class spell_ignis_scorch_AuraScript : public AuraScript
{
PrepareAuraScript(spell_ignis_scorch_AuraScript)
void HandleEffectPeriodic(AuraEffect const* aurEff)
{
if (aurEff->GetTotalTicks() >= 0 && aurEff->GetTickNumber() == uint32(aurEff->GetTotalTicks()))
if (Unit* c = GetCaster())
if (Creature* s = c->SummonCreature(NPC_SCORCHED_GROUND, c->GetPositionX() + 20.0f * cos(c->GetOrientation()), c->GetPositionY() + 20.0f * std::sin(c->GetOrientation()), 361.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 30000))
{
if (!s->FindNearestCreature(NPC_WATER_TRIGGER, 25.0f, true)) // must be away from the water
s->CastSpell(s, (aurEff->GetId() == 62546 ? SPELL_SCORCHED_GROUND_10 : SPELL_SCORCHED_GROUND_25), true);
}
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_ignis_scorch_AuraScript::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_ignis_scorch_AuraScript();
}
};
class spell_ignis_grab_initial : public SpellScriptLoader
{
public:
spell_ignis_grab_initial() : SpellScriptLoader("spell_ignis_grab_initial") { }
class spell_ignis_grab_initial_SpellScript : public SpellScript
{
PrepareSpellScript(spell_ignis_grab_initial_SpellScript);
void HandleScript(SpellEffIndex /*effIndex*/)
{
if (Unit* t = GetHitUnit())
t->CastSpell(t, SPELL_GRAB_TRIGGERED, true);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_ignis_grab_initial_SpellScript::HandleScript, EFFECT_2, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_ignis_grab_initial_SpellScript();
}
};
class spell_ignis_slag_pot : public SpellScriptLoader
{
public:
spell_ignis_slag_pot() : SpellScriptLoader("spell_ignis_slag_pot") { }
class spell_ignis_slag_pot_AuraScript : public AuraScript
{
PrepareAuraScript(spell_ignis_slag_pot_AuraScript)
void HandleEffectPeriodic(AuraEffect const* /*aurEff*/)
{
if (Unit* c = GetCaster())
if (Unit* t = GetTarget())
c->CastSpell(t, (GetId() == 62717 ? 65722 : 65723), true);
}
void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
if (Unit* t = GetTarget())
{
t->ApplySpellImmune(GetId(), IMMUNITY_ID, 62549, true);
t->ApplySpellImmune(GetId(), IMMUNITY_ID, 63475, true);
}
}
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
if (Unit* t = GetTarget())
{
t->ApplySpellImmune(GetId(), IMMUNITY_ID, 62549, false);
t->ApplySpellImmune(GetId(), IMMUNITY_ID, 63475, false);
if (t->IsAlive())
t->CastSpell(t, (GetId() == 62717 ? 62836 : 63536), true);
}
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_ignis_slag_pot_AuraScript::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
OnEffectApply += AuraEffectApplyFn(spell_ignis_slag_pot_AuraScript::OnApply, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL);
AfterEffectRemove += AuraEffectRemoveFn(spell_ignis_slag_pot_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_ignis_slag_pot_AuraScript();
}
};
class achievement_ignis_shattered : public AchievementCriteriaScript
{
public:
achievement_ignis_shattered() : AchievementCriteriaScript("achievement_ignis_shattered") {}
bool OnCheck(Player* /*player*/, Unit* target, uint32 /*criteria_id*/) override
{
if (!target || target->GetTypeId() != TYPEID_UNIT)
return false;
return !!target->ToCreature()->AI()->GetData(1337);
}
};
#endif

View File

@@ -15,7 +15,6 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "boss_kologarn.h"
#include "AchievementCriteriaScript.h"
#include "CreatureScript.h"
#include "PassiveAI.h"
@@ -27,6 +26,867 @@
#include "Vehicle.h"
#include "ulduar.h"
enum KologarnSays
{
SAY_AGGRO = 0,
SAY_SLAY = 1,
SAY_LEFT_ARM_GONE = 2,
SAY_RIGHT_ARM_GONE = 3,
SAY_SHOCKWAVE = 4,
SAY_GRAB_PLAYER = 5,
SAY_DEATH = 6,
SAY_BERSERK = 7,
EMOTE_STONE_GRIP = 8,
EMOTE_EYES = 9
};
enum KologarnSpells
{
SPELL_KOLOGARN_REDUCE_PARRY = 64651,
// BASIC
SPELL_OVERHEAD_SMASH_10 = 63356,
SPELL_OVERHEAD_SMASH_25 = 64003,
SPELL_ONEARMED_OVERHEAD_SMASH_10 = 63573,
SPELL_ONEARMED_OVERHEAD_SMASH_25 = 64006,
SPELL_PETRIFYING_BREATH_10 = 62030,
SPELL_PETRIFYING_BREATH_25 = 63980,
SPELL_STONE_SHOUT_10 = 63716,
SPELL_STONE_SHOUT_25 = 64005,
// EYEBEAM
SPELL_FOCUSED_EYEBEAM_SUMMON = 63342,
SPELL_FOCUSED_EYEBEAM_10 = 63347,
SPELL_FOCUSED_EYEBEAM_25 = 63977,
SPELL_FOCUSED_EYEBEAM_RIGHT = 63702,
SPELL_FOCUSED_EYEBEAM_LEFT = 63676,
// ARMS
SPELL_ARM_DEAD_10 = 63629,
SPELL_ARM_DEAD_25 = 63979,
SPELL_RUBBLE_FALL_10 = 63821,
SPELL_RUBBLE_FALL_25 = 64001,
SPELL_ARM_RESPAWN_VISUAL = 64753,
// LEFT ARM
SPELL_ARM_SWEEP_10 = 63766,
SPELL_ARM_SWEEP_25 = 63983,
// RIGHT ARM
SPELL_STONE_GRIP_10 = 62166,
SPELL_STONE_GRIP_25 = 63981,
SPELL_RIDE_RIGHT_ARM_10 = 62056,
SPELL_RIDE_RIGHT_ARM_25 = 63985,
// RUBBLE TRASH
SPELL_RUBBLE_ATTACK_10 = 63818,
SPELL_RUBBLE_ATTACK_25 = 63978,
};
#define SPELL_PETRIFYING_BREATH RAID_MODE(SPELL_PETRIFYING_BREATH_10, SPELL_PETRIFYING_BREATH_25)
#define SPELL_OVERHEAD_SMASH RAID_MODE(SPELL_OVERHEAD_SMASH_10, SPELL_OVERHEAD_SMASH_25)
#define SPELL_ONEARMED_OVERHEAD_SMASH RAID_MODE(SPELL_ONEARMED_OVERHEAD_SMASH_10, SPELL_ONEARMED_OVERHEAD_SMASH_25)
#define SPELL_ARM_DEAD RAID_MODE(SPELL_ARM_DEAD_10, SPELL_ARM_DEAD_25)
#define SPELL_ARM_SWEEP RAID_MODE(SPELL_ARM_SWEEP_10, SPELL_ARM_SWEEP_25)
#define SPELL_STONE_GRIP RAID_MODE(SPELL_STONE_GRIP_10, SPELL_STONE_GRIP_25)
#define SPELL_FOCUSED_EYEBEAM RAID_MODE(SPELL_FOCUSED_EYEBEAM_10, SPELL_FOCUSED_EYEBEAM_25)
#define SPELL_RUBBLE_FALL RAID_MODE(SPELL_RUBBLE_FALL_10, SPELL_RUBBLE_FALL_25)
#define SPELL_RUBBLE_ATTACK RAID_MODE(SPELL_RUBBLE_ATTACK_10, SPELL_RUBBLE_ATTACK_25)
#define SPELL_RIDE_RIGHT_ARM RAID_MODE(SPELL_RIDE_RIGHT_ARM_10, SPELL_RIDE_RIGHT_ARM_25)
#define SPELL_STONE_SHOUT RAID_MODE(SPELL_STONE_SHOUT_10, SPELL_STONE_SHOUT_25)
enum KologarnEvents
{
EVENT_SMASH = 1,
EVENT_GRIP = 2,
EVENT_SWEEP = 3,
EVENT_RESTORE_ARM_LEFT = 4,
EVENT_RESTORE_ARM_RIGHT = 5,
EVENT_FOCUSED_EYEBEAM = 6,
EVENT_STONE_SHOUT = 7,
EVENT_PREPARE_BREATH = 8, // Kologarn can't cast breath on pull
};
enum KologarnNPCs
{
NPC_LEFT_ARM = 32933,
NPC_RIGHT_ARM = 32934,
NPC_SWEEP_TRIGGER = 33661,
NPC_EYE_LEFT = 33632,
NPC_EYE_RIGHT = 33802,
NPC_RUBBLE_TRIGGER = 33809,
NPC_RUBBLE_SUMMON = 33768,
};
enum KologarnSounds
{
SOUND_AGGRO = 15586,
SOUND_SLAY1 = 15587,
SOUND_SLAY2 = 15588,
SOUND_LARM_GONE = 15589,
SOUND_RARM_GONE = 15590,
SOUND_SHOCKWAVE = 15591,
SOUND_GRIP = 15592,
SOUND_DEATH = 15593,
SOUND_BERSERK = 15594,
};
enum Misc
{
ACHIEVEMENT_DISARMED_CRITERIA = 21687,
DATA_KOLOGARN_LOOKS_ACHIEV = 55,
DATA_KOLOGARN_RUBBLE_ACHIEV = 56,
DATA_KOLOGARN_ARMS_ACHIEV = 57,
};
class boss_kologarn : public CreatureScript
{
public:
boss_kologarn() : CreatureScript("boss_kologarn") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return GetUlduarAI<boss_kologarnAI>(pCreature);
}
struct boss_kologarnAI : public ScriptedAI
{
boss_kologarnAI(Creature* pCreature) : ScriptedAI(pCreature), vehicle(me->GetVehicleKit()), summons(me), breathReady(false)
{
m_pInstance = me->GetInstanceScript();
eyebeamTarget = nullptr;
assert(vehicle);
me->SetStandState(UNIT_STAND_STATE_SUBMERGED);
}
InstanceScript* m_pInstance;
Vehicle* vehicle;
ObjectGuid _left, _right;
EventMap events;
SummonList summons;
Unit* eyebeamTarget;
bool _looksAchievement, breathReady;
uint8 _rubbleAchievement;
void MoveInLineOfSight(Unit* who) override
{
if (who->GetTypeId() == TYPEID_PLAYER && me->GetExactDist2d(who) < 45.0f && me->getStandState() == UNIT_STAND_STATE_SUBMERGED)
{
me->SetStandState(UNIT_STAND_STATE_STAND);
if (Unit* arm = ObjectAccessor::GetCreature(*me, _left))
arm->CastSpell(arm, SPELL_ARM_RESPAWN_VISUAL, true);
if (Unit* arm = ObjectAccessor::GetCreature(*me, _right))
arm->CastSpell(arm, SPELL_ARM_RESPAWN_VISUAL, true);
}
if (me->GetExactDist2d(who) < 30.0f)
ScriptedAI::MoveInLineOfSight(who);
}
void EnterEvadeMode(EvadeReason why) override
{
if (!_EnterEvadeMode(why))
return;
Reset();
me->setActive(false);
}
void AttachLeftArm()
{
if (Unit* arm = ObjectAccessor::GetCreature(*me, _left))
arm->SetHealth(arm->GetMaxHealth());
else if (Creature* accessory = me->SummonCreature(NPC_LEFT_ARM, *me, TEMPSUMMON_MANUAL_DESPAWN))
{
accessory->AddUnitTypeMask(UNIT_MASK_ACCESSORY);
if (!me->HandleSpellClick(accessory, 0))
accessory->DespawnOrUnsummon();
else
{
_left = accessory->GetGUID();
accessory->SetOrientation(M_PI);
accessory->CastSpell(accessory, SPELL_ARM_RESPAWN_VISUAL, true);
}
}
}
void AttachRightArm()
{
if (Unit* arm = ObjectAccessor::GetCreature(*me, _right))
arm->SetHealth(arm->GetMaxHealth());
else if (Creature* accessory = me->SummonCreature(NPC_RIGHT_ARM, *me, TEMPSUMMON_MANUAL_DESPAWN))
{
accessory->AddUnitTypeMask(UNIT_MASK_ACCESSORY);
if (!me->HandleSpellClick(accessory, 1))
accessory->DespawnOrUnsummon();
else
{
_right = accessory->GetGUID();
accessory->SetOrientation(M_PI);
accessory->CastSpell(accessory, SPELL_ARM_RESPAWN_VISUAL, true);
}
}
}
void Reset() override
{
_rubbleAchievement = 0;
_looksAchievement = true;
me->SetDisableGravity(true);
me->SetUnitFlag(UNIT_FLAG_DISABLE_MOVE);
me->DisableRotate(true);
events.Reset();
summons.DespawnAll();
if (m_pInstance)
{
m_pInstance->SetData(TYPE_KOLOGARN, NOT_STARTED);
// Open the door inside Kologarn chamber
if (GameObject* door = m_pInstance->instance->GetGameObject(m_pInstance->GetGuidData(GO_KOLOGARN_DOORS)))
door->SetGoState(GO_STATE_ACTIVE);
}
AttachLeftArm();
AttachRightArm();
// Reset breath on pull
breathReady = false;
}
void DoAction(int32 param) override
{
if (param == DATA_KOLOGARN_LOOKS_ACHIEV)
_looksAchievement = false;
if (param == DATA_KOLOGARN_RUBBLE_ACHIEV)
{
// Means arm died
if (m_pInstance && (!_left || !_right))
m_pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEVEMENT_DISARMED_CRITERIA);
++_rubbleAchievement;
}
}
uint32 GetData(uint32 param) const override
{
if (param == DATA_KOLOGARN_LOOKS_ACHIEV)
return _looksAchievement;
else if (param == DATA_KOLOGARN_RUBBLE_ACHIEV)
return (_rubbleAchievement >= 5);
else if (param == DATA_KOLOGARN_ARMS_ACHIEV)
return !_rubbleAchievement;
return 0;
}
void AttackStart(Unit* who) override
{
me->Attack(who, true);
}
void JustSummoned(Creature* cr) override
{
if (cr->GetEntry() != NPC_LEFT_ARM && cr->GetEntry() != NPC_RIGHT_ARM)
summons.Summon(cr);
}
void JustDied(Unit*) override
{
summons.DespawnAll();
me->StopMoving();
if (m_pInstance)
m_pInstance->SetData(TYPE_KOLOGARN, DONE);
Talk(SAY_DEATH);
if (m_pInstance)
{
// Open the door inside Kologarn chamber
if (GameObject* door = m_pInstance->instance->GetGameObject(m_pInstance->GetGuidData(GO_KOLOGARN_DOORS)))
door->SetGoState(GO_STATE_ACTIVE);
}
if (GameObject* bridge = me->FindNearestGameObject(GO_KOLOGARN_BRIDGE, 100))
bridge->SetGoState(GO_STATE_READY);
// Summon Chest
if (GameObject* go = me->SummonGameObject(RAID_MODE(GO_KOLOGARN_CHEST, GO_KOLOGARN_CHEST_HERO), 1839.62f, -35.98f, 448.81f, 3.6f, 0, 0, 0, 0, 7 * 86400))
{
me->RemoveGameObject(go, false);
go->SetSpellId(1); // hack to make it despawn
go->ReplaceAllGameObjectFlags((GameObjectFlags)0);
go->SetLootRecipient(me);
}
if (Creature* arm = ObjectAccessor::GetCreature(*me, _left))
arm->DespawnOrUnsummon(3000); // visual
if (Creature* arm = ObjectAccessor::GetCreature(*me, _right))
arm->DespawnOrUnsummon(3000); // visual
}
void KilledUnit(Unit*) override
{
if (!urand(0, 2))
return;
Talk(SAY_SLAY);
}
void PassengerBoarded(Unit* who, int8 /*seatId*/, bool apply) override
{
if (!me->IsAlive())
return;
if (!apply)
{
// left arm
if (who->GetGUID() == _left)
{
_left.Clear();
if (me->IsInCombat())
{
Talk(SAY_LEFT_ARM_GONE);
events.ScheduleEvent(EVENT_RESTORE_ARM_LEFT, 50s);
}
}
else
{
_right.Clear();
if (me->IsInCombat())
{
Talk(SAY_RIGHT_ARM_GONE);
events.ScheduleEvent(EVENT_RESTORE_ARM_RIGHT, 50s);
}
}
me->CastSpell(me, SPELL_ARM_DEAD, true);
if (!_right && !_left)
events.ScheduleEvent(EVENT_STONE_SHOUT, 5s);
}
}
void DamageTaken(Unit* who, uint32& damage, DamageEffectType, SpellSchoolMask) override
{
if (who && who->GetEntry() == me->GetEntry() && me->GetHealth())
{
damage = std::min(damage, me->GetHealth() - 1);
me->LowerPlayerDamageReq(damage);
}
}
void JustEngagedWith(Unit* /*who*/) override
{
if (m_pInstance)
m_pInstance->SetData(TYPE_KOLOGARN, IN_PROGRESS);
events.ScheduleEvent(EVENT_SMASH, 8s);
events.ScheduleEvent(EVENT_SWEEP, 17s);
events.ScheduleEvent(EVENT_GRIP, 15s);
events.ScheduleEvent(EVENT_FOCUSED_EYEBEAM, 10s);
events.ScheduleEvent(EVENT_PREPARE_BREATH, 3s);
//events.ScheduleEvent(EVENT_ENRAGE, x); no info
Talk(SAY_AGGRO);
me->setActive(true);
// Close the door inside Kologarn chamber
if (m_pInstance)
{
if (GameObject* door = m_pInstance->instance->GetGameObject(m_pInstance->GetGuidData(GO_KOLOGARN_DOORS)))
{
door->SetGoState(GO_STATE_READY);
}
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
{
EnterEvadeMode(EVADE_REASON_OTHER);
return;
}
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{
case EVENT_PREPARE_BREATH:
breathReady = true;
break;
case EVENT_STONE_SHOUT:
if (_left || _right)
{
return;
}
me->CastSpell(me->GetVictim(), SPELL_STONE_SHOUT, false);
events.ScheduleEvent(EVENT_STONE_SHOUT, 2s);
break;
case EVENT_SMASH:
if (_left && _right)
me->CastSpell(me->GetVictim(), SPELL_OVERHEAD_SMASH, false);
else if (_left || _right)
me->CastSpell(me->GetVictim(), SPELL_ONEARMED_OVERHEAD_SMASH, false);
events.DelayEvents(1s);
events.ScheduleEvent(EVENT_SMASH, 14s);
return;
case EVENT_SWEEP:
if (_left)
{
if (Creature* cr = me->FindNearestCreature(NPC_SWEEP_TRIGGER, 300))
cr->CastSpell(cr, SPELL_ARM_SWEEP, false);
if (urand(0, 1))
Talk(SAY_SHOCKWAVE);
}
events.DelayEvents(1s);
events.ScheduleEvent(EVENT_SWEEP, 17s);
return;
case EVENT_GRIP:
events.ScheduleEvent(EVENT_GRIP, 25s);
if (!_right)
break;
me->CastSpell(me, SPELL_STONE_GRIP, false);
Talk(SAY_GRAB_PLAYER);
Talk(EMOTE_STONE_GRIP);
return;
case EVENT_FOCUSED_EYEBEAM:
{
events.ScheduleEvent(EVENT_FOCUSED_EYEBEAM, 20s);
if ((eyebeamTarget = SelectTarget(SelectTargetMethod::MinDistance, 0, 0, true)))
{
me->CastSpell(eyebeamTarget, SPELL_FOCUSED_EYEBEAM_SUMMON, false);
}
Talk(EMOTE_EYES);
return;
}
case EVENT_RESTORE_ARM_LEFT:
// shouldn't happen
AttachLeftArm();
return;
case EVENT_RESTORE_ARM_RIGHT:
// shouldn't happen
AttachRightArm();
return;
}
//Make sure our attack is ready and we aren't currently casting before checking distance
if (me->isAttackReady() && me->GetVictim()) // victim could die by a spell (IMPORTANT!!!) and kologarn entered evade mode
{
//If we are within range melee the target
if (me->IsWithinMeleeRange(me->GetVictim()))
{
me->AttackerStateUpdate(me->GetVictim());
me->resetAttackTimer();
return;
}
else if (Unit* tgt = me->SelectNearbyTarget())
{
me->AttackerStateUpdate(tgt);
me->resetAttackTimer();
return;
}
if (breathReady)
me->CastSpell(me->GetVictim(), SPELL_PETRIFYING_BREATH, false);
me->resetAttackTimer();
}
}
};
};
// also used for left arm, all functions except JustDied wont be used by left arm
class boss_kologarn_arms : public CreatureScript
{
public:
boss_kologarn_arms() : CreatureScript("boss_kologarn_arms") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return GetUlduarAI<boss_kologarn_armsAI>(pCreature);
}
struct boss_kologarn_armsAI : public ScriptedAI
{
boss_kologarn_armsAI(Creature* c) : ScriptedAI(c) { }
int32 _damageDone;
bool _combatStarted;
void EnterEvadeMode(EvadeReason /*why*/ = EVADE_REASON_OTHER) override {}
void MoveInLineOfSight(Unit*) override {}
void AttackStart(Unit*) override {}
void UpdateAI(uint32 /*diff*/) override {}
void Reset() override
{
_combatStarted = false;
_damageDone = 0;
}
void PassengerBoarded(Unit* /*who*/, int8 /*seatId*/, bool apply) override
{
if (!apply)
_damageDone = 0;
else
{
//who->ClearUnitState(UNIT_STATE_ONVEHICLE);
if (!_damageDone)
_damageDone = RAID_MODE(80000, 380000);
}
}
void DamageTaken(Unit* who, uint32& damage, DamageEffectType, SpellSchoolMask) override
{
if (!_combatStarted)
if (InstanceScript* instance = me->GetInstanceScript())
if (Creature* cr = ObjectAccessor::GetCreature(*me, instance->GetGuidData(TYPE_KOLOGARN)))
{
_combatStarted = true;
if (!cr->IsInCombat() && who)
cr->AI()->AttackStart(who);
}
if (_damageDone > 0)
{
_damageDone -= damage;
if (_damageDone <= 0 || damage >= me->GetHealth())
me->RemoveAurasByType(SPELL_AURA_CONTROL_VEHICLE);
}
}
void JustDied(Unit*) override
{
float x, y, z;
// left arm
if( me->GetEntry() == NPC_LEFT_ARM )
{
x = 1776.97f;
y = -44.8396f;
z = 448.888f;
}
else
{
x = 1777.82f;
y = -3.50803f;
z = 448.888f;
}
if (Creature* cr = me->SummonTrigger(x, y, z, 0, 5000))
{
cr->CastSpell(cr, SPELL_RUBBLE_FALL, true);
if (me->GetInstanceScript())
if (Creature* kologarn = ObjectAccessor::GetCreature(*me, me->GetInstanceScript()->GetGuidData(TYPE_KOLOGARN)))
for (uint8 i = 0; i < 5; ++i)
if (Creature* cr2 = kologarn->SummonCreature(NPC_RUBBLE_SUMMON, cr->GetPositionX() + irand(-5, 5), cr->GetPositionY() + irand(-5, 5), cr->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000))
{
cr2->SetInCombatWithZone();
if (Unit* target = SelectTargetFromPlayerList(100))
cr2->AI()->AttackStart(target);
}
}
if (me->GetInstanceScript())
if (Creature* cr = ObjectAccessor::GetCreature(*me, me->GetInstanceScript()->GetGuidData(TYPE_KOLOGARN)))
cr->AI()->DoAction(DATA_KOLOGARN_RUBBLE_ACHIEV);
me->ExitVehicle();
}
};
};
class boss_kologarn_eyebeam : public CreatureScript
{
public:
boss_kologarn_eyebeam() : CreatureScript("boss_kologarn_eyebeam") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return GetUlduarAI<boss_kologarn_eyebeamAI>(pCreature);
}
struct boss_kologarn_eyebeamAI : public ScriptedAI
{
boss_kologarn_eyebeamAI(Creature* c) : ScriptedAI(c), _timer(1), _damaged(false), justSpawned(true)
{
m_pInstance = (InstanceScript*)c->GetInstanceScript();
}
InstanceScript* m_pInstance;
uint32 _timer;
bool _damaged, justSpawned;
void DamageDealt(Unit* /*victim*/, uint32& damage, DamageEffectType /*damageType*/) override
{
if (damage > 0 && !_damaged && me->GetInstanceScript())
{
_damaged = true;
if (Creature* cr = ObjectAccessor::GetCreature(*me, me->GetInstanceScript()->GetGuidData(TYPE_KOLOGARN)))
cr->AI()->DoAction(DATA_KOLOGARN_LOOKS_ACHIEV);
}
}
void UpdateAI(uint32 diff) override
{
if (justSpawned)
{
me->DespawnOrUnsummon(10000);
if (Creature* cr = ObjectAccessor::GetCreature(*me, m_pInstance->GetGuidData(TYPE_KOLOGARN)))
{
me->CastSpell(cr, me->GetEntry() == NPC_EYE_LEFT ? SPELL_FOCUSED_EYEBEAM_LEFT : SPELL_FOCUSED_EYEBEAM_RIGHT, true);
}
me->CastSpell(me, SPELL_FOCUSED_EYEBEAM, true);
justSpawned = false;
}
if (_timer)
{
_timer += diff;
if (_timer >= 2000)
{
me->CastSpell(me, (me->GetMap()->Is25ManRaid() ? SPELL_FOCUSED_EYEBEAM_25 : SPELL_FOCUSED_EYEBEAM_10), true);
_timer = 0;
}
}
}
};
};
// predicate function to select non main tank target
class StoneGripTargetSelector
{
public:
StoneGripTargetSelector(Creature* me, Unit const* victim) : _me(me), _victim(victim) {}
bool operator() (WorldObject* target) const
{
if (target == _victim && _me->GetThreatMgr().GetThreatListSize() > 1)
return true;
if (target->GetTypeId() != TYPEID_PLAYER)
return true;
return false;
}
private:
Creature* _me;
Unit const* _victim;
};
class spell_ulduar_stone_grip_cast_target : public SpellScriptLoader
{
public:
spell_ulduar_stone_grip_cast_target() : SpellScriptLoader("spell_ulduar_stone_grip_cast_target") { }
class spell_ulduar_stone_grip_cast_target_SpellScript : public SpellScript
{
PrepareSpellScript(spell_ulduar_stone_grip_cast_target_SpellScript);
bool Load() override
{
if (GetCaster()->GetTypeId() != TYPEID_UNIT)
return false;
return true;
}
void FilterTargetsInitial(std::list<WorldObject*>& targets)
{
// Remove "main tank" and non-player targets
targets.remove_if (StoneGripTargetSelector(GetCaster()->ToCreature(), GetCaster()->GetVictim()));
// Maximum affected targets per difficulty mode
uint32 maxTargets = 1;
if (GetSpellInfo()->Id == 63981)
maxTargets = 3;
// Return a random amount of targets based on maxTargets
while (maxTargets < targets.size())
{
std::list<WorldObject*>::iterator itr = targets.begin();
advance(itr, urand(0, targets.size() - 1));
targets.erase(itr);
}
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_ulduar_stone_grip_cast_target_SpellScript::FilterTargetsInitial, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_ulduar_stone_grip_cast_target_SpellScript();
}
};
class spell_ulduar_stone_grip : public SpellScriptLoader
{
public:
spell_ulduar_stone_grip() : SpellScriptLoader("spell_ulduar_stone_grip") { }
class spell_ulduar_stone_grip_AuraScript : public AuraScript
{
PrepareAuraScript(spell_ulduar_stone_grip_AuraScript);
void OnRemoveStun(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
{
if (Player* owner = GetOwner()->ToPlayer())
owner->RemoveAurasDueToSpell(aurEff->GetAmount());
}
void Register() override
{
OnEffectRemove += AuraEffectRemoveFn(spell_ulduar_stone_grip_AuraScript::OnRemoveStun, EFFECT_2, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_ulduar_stone_grip_AuraScript();
}
};
class spell_ulduar_squeezed_lifeless : public SpellScriptLoader
{
public:
spell_ulduar_squeezed_lifeless() : SpellScriptLoader("spell_ulduar_squeezed_lifeless") { }
class spell_ulduar_squeezed_lifeless_SpellScript : public SpellScript
{
PrepareSpellScript(spell_ulduar_squeezed_lifeless_SpellScript);
void HandleInstaKill(SpellEffIndex /*effIndex*/)
{
if (!GetHitPlayer() || !GetHitPlayer()->GetVehicle())
return;
// Hack to set correct position is in _ExitVehicle()
GetHitPlayer()->ExitVehicle();
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_ulduar_squeezed_lifeless_SpellScript::HandleInstaKill, EFFECT_1, SPELL_EFFECT_INSTAKILL);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_ulduar_squeezed_lifeless_SpellScript();
}
};
class spell_kologarn_stone_shout : public SpellScriptLoader
{
public:
spell_kologarn_stone_shout() : SpellScriptLoader("spell_kologarn_stone_shout") { }
class spell_kologarn_stone_shout_AuraScript : public AuraScript
{
PrepareAuraScript(spell_kologarn_stone_shout_AuraScript);
void OnPeriodic(AuraEffect const* /*aurEff*/)
{
uint32 triggerSpellId = GetSpellInfo()->Effects[EFFECT_0].TriggerSpell;
if (Unit* caster = GetCaster())
caster->CastSpell(caster, triggerSpellId, false);
}
void Register() override
{
if (m_scriptSpellId == SPELL_STONE_SHOUT_10 || m_scriptSpellId == SPELL_STONE_SHOUT_25)
OnEffectPeriodic += AuraEffectPeriodicFn(spell_kologarn_stone_shout_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_kologarn_stone_shout_AuraScript();
}
class spell_kologarn_stone_shout_SpellScript : public SpellScript
{
PrepareSpellScript(spell_kologarn_stone_shout_SpellScript);
void FilterTargets(std::list<WorldObject*>& targets)
{
targets.remove_if (PlayerOrPetCheck());
}
void Register() override
{
if (m_scriptSpellId != SPELL_STONE_SHOUT_10 && m_scriptSpellId != SPELL_STONE_SHOUT_25)
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_kologarn_stone_shout_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_kologarn_stone_shout_SpellScript();
}
};
class achievement_kologarn_looks_could_kill : public AchievementCriteriaScript
{
public:
achievement_kologarn_looks_could_kill() : AchievementCriteriaScript("achievement_kologarn_looks_could_kill") {}
bool OnCheck(Player* /*player*/, Unit* target, uint32 /*criteria_id*/) override
{
if (target)
if (InstanceScript* instance = target->GetInstanceScript())
if (Creature* cr = ObjectAccessor::GetCreature(*target, instance->GetGuidData(TYPE_KOLOGARN)))
return cr->AI()->GetData(DATA_KOLOGARN_LOOKS_ACHIEV);
return false;
}
};
class achievement_kologarn_rubble_and_roll : public AchievementCriteriaScript
{
public:
achievement_kologarn_rubble_and_roll() : AchievementCriteriaScript("achievement_kologarn_rubble_and_roll") {}
bool OnCheck(Player* /*player*/, Unit* target, uint32 /*criteria_id*/) override
{
if (target)
if (InstanceScript* instance = target->GetInstanceScript())
if (Creature* cr = ObjectAccessor::GetCreature(*target, instance->GetGuidData(TYPE_KOLOGARN)))
return cr->AI()->GetData(DATA_KOLOGARN_RUBBLE_ACHIEV);
return false;
}
};
class achievement_kologarn_with_open_arms : public AchievementCriteriaScript
{
public:
achievement_kologarn_with_open_arms() : AchievementCriteriaScript("achievement_kologarn_with_open_arms") {}
bool OnCheck(Player* /*player*/, Unit* target, uint32 /*criteria_id*/) override
{
if (target)
if (InstanceScript* instance = target->GetInstanceScript())
if (Creature* cr = ObjectAccessor::GetCreature(*target, instance->GetGuidData(TYPE_KOLOGARN)))
return cr->AI()->GetData(DATA_KOLOGARN_ARMS_ACHIEV);
return false;
}
};
void AddSC_boss_kologarn()
{
// Npcs

View File

@@ -1,876 +0,0 @@
#ifndef BOSS_KOLOGARN_H_
#define BOSS_KOLOGARN_H_
#include "AchievementCriteriaScript.h"
#include "CreatureScript.h"
#include "PassiveAI.h"
#include "Player.h"
#include "ScriptedCreature.h"
#include "SpellAuraEffects.h"
#include "SpellScript.h"
#include "SpellScriptLoader.h"
#include "Vehicle.h"
#include "ulduar.h"
enum KologarnSays
{
SAY_AGGRO = 0,
SAY_SLAY = 1,
SAY_LEFT_ARM_GONE = 2,
SAY_RIGHT_ARM_GONE = 3,
SAY_SHOCKWAVE = 4,
SAY_GRAB_PLAYER = 5,
SAY_DEATH = 6,
SAY_BERSERK = 7,
EMOTE_STONE_GRIP = 8,
EMOTE_EYES = 9
};
enum KologarnSpells
{
SPELL_KOLOGARN_REDUCE_PARRY = 64651,
// BASIC
SPELL_OVERHEAD_SMASH_10 = 63356,
SPELL_OVERHEAD_SMASH_25 = 64003,
SPELL_ONEARMED_OVERHEAD_SMASH_10 = 63573,
SPELL_ONEARMED_OVERHEAD_SMASH_25 = 64006,
SPELL_PETRIFYING_BREATH_10 = 62030,
SPELL_PETRIFYING_BREATH_25 = 63980,
SPELL_STONE_SHOUT_10 = 63716,
SPELL_STONE_SHOUT_25 = 64005,
// EYEBEAM
SPELL_FOCUSED_EYEBEAM_SUMMON = 63342,
SPELL_FOCUSED_EYEBEAM_10 = 63347,
SPELL_FOCUSED_EYEBEAM_25 = 63977,
SPELL_FOCUSED_EYEBEAM_RIGHT = 63702,
SPELL_FOCUSED_EYEBEAM_LEFT = 63676,
// ARMS
SPELL_ARM_DEAD_10 = 63629,
SPELL_ARM_DEAD_25 = 63979,
SPELL_RUBBLE_FALL_10 = 63821,
SPELL_RUBBLE_FALL_25 = 64001,
SPELL_ARM_RESPAWN_VISUAL = 64753,
// LEFT ARM
SPELL_ARM_SWEEP_10 = 63766,
SPELL_ARM_SWEEP_25 = 63983,
// RIGHT ARM
SPELL_STONE_GRIP_10 = 62166,
SPELL_STONE_GRIP_25 = 63981,
SPELL_RIDE_RIGHT_ARM_10 = 62056,
SPELL_RIDE_RIGHT_ARM_25 = 63985,
// RUBBLE TRASH
SPELL_RUBBLE_ATTACK_10 = 63818,
SPELL_RUBBLE_ATTACK_25 = 63978,
};
#define SPELL_PETRIFYING_BREATH RAID_MODE(SPELL_PETRIFYING_BREATH_10, SPELL_PETRIFYING_BREATH_25)
#define SPELL_OVERHEAD_SMASH RAID_MODE(SPELL_OVERHEAD_SMASH_10, SPELL_OVERHEAD_SMASH_25)
#define SPELL_ONEARMED_OVERHEAD_SMASH RAID_MODE(SPELL_ONEARMED_OVERHEAD_SMASH_10, SPELL_ONEARMED_OVERHEAD_SMASH_25)
#define SPELL_ARM_DEAD RAID_MODE(SPELL_ARM_DEAD_10, SPELL_ARM_DEAD_25)
#define SPELL_ARM_SWEEP RAID_MODE(SPELL_ARM_SWEEP_10, SPELL_ARM_SWEEP_25)
#define SPELL_STONE_GRIP RAID_MODE(SPELL_STONE_GRIP_10, SPELL_STONE_GRIP_25)
#define SPELL_FOCUSED_EYEBEAM RAID_MODE(SPELL_FOCUSED_EYEBEAM_10, SPELL_FOCUSED_EYEBEAM_25)
#define SPELL_RUBBLE_FALL RAID_MODE(SPELL_RUBBLE_FALL_10, SPELL_RUBBLE_FALL_25)
#define SPELL_RUBBLE_ATTACK RAID_MODE(SPELL_RUBBLE_ATTACK_10, SPELL_RUBBLE_ATTACK_25)
#define SPELL_RIDE_RIGHT_ARM RAID_MODE(SPELL_RIDE_RIGHT_ARM_10, SPELL_RIDE_RIGHT_ARM_25)
#define SPELL_STONE_SHOUT RAID_MODE(SPELL_STONE_SHOUT_10, SPELL_STONE_SHOUT_25)
enum KologarnEvents
{
EVENT_SMASH = 1,
EVENT_GRIP = 2,
EVENT_SWEEP = 3,
EVENT_RESTORE_ARM_LEFT = 4,
EVENT_RESTORE_ARM_RIGHT = 5,
EVENT_FOCUSED_EYEBEAM = 6,
EVENT_STONE_SHOUT = 7,
EVENT_PREPARE_BREATH = 8, // Kologarn can't cast breath on pull
};
enum KologarnNPCs
{
NPC_LEFT_ARM = 32933,
NPC_RIGHT_ARM = 32934,
NPC_SWEEP_TRIGGER = 33661,
NPC_EYE_LEFT = 33632,
NPC_EYE_RIGHT = 33802,
NPC_RUBBLE_TRIGGER = 33809,
NPC_RUBBLE_SUMMON = 33768,
};
enum KologarnSounds
{
SOUND_AGGRO = 15586,
SOUND_SLAY1 = 15587,
SOUND_SLAY2 = 15588,
SOUND_LARM_GONE = 15589,
SOUND_RARM_GONE = 15590,
SOUND_SHOCKWAVE = 15591,
SOUND_GRIP = 15592,
SOUND_DEATH = 15593,
SOUND_BERSERK = 15594,
};
enum Misc
{
ACHIEVEMENT_DISARMED_CRITERIA = 21687,
DATA_KOLOGARN_LOOKS_ACHIEV = 55,
DATA_KOLOGARN_RUBBLE_ACHIEV = 56,
DATA_KOLOGARN_ARMS_ACHIEV = 57,
};
class boss_kologarn : public CreatureScript
{
public:
boss_kologarn() : CreatureScript("boss_kologarn") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return GetUlduarAI<boss_kologarnAI>(pCreature);
}
struct boss_kologarnAI : public ScriptedAI
{
boss_kologarnAI(Creature* pCreature) : ScriptedAI(pCreature), vehicle(me->GetVehicleKit()), summons(me), breathReady(false)
{
m_pInstance = me->GetInstanceScript();
eyebeamTarget = nullptr;
assert(vehicle);
me->SetStandState(UNIT_STAND_STATE_SUBMERGED);
}
InstanceScript* m_pInstance;
Vehicle* vehicle;
ObjectGuid _left, _right;
EventMap events;
SummonList summons;
Unit* eyebeamTarget;
bool _looksAchievement, breathReady;
uint8 _rubbleAchievement;
void MoveInLineOfSight(Unit* who) override
{
if (who->GetTypeId() == TYPEID_PLAYER && me->GetExactDist2d(who) < 45.0f && me->getStandState() == UNIT_STAND_STATE_SUBMERGED)
{
me->SetStandState(UNIT_STAND_STATE_STAND);
if (Unit* arm = ObjectAccessor::GetCreature(*me, _left))
arm->CastSpell(arm, SPELL_ARM_RESPAWN_VISUAL, true);
if (Unit* arm = ObjectAccessor::GetCreature(*me, _right))
arm->CastSpell(arm, SPELL_ARM_RESPAWN_VISUAL, true);
}
if (me->GetExactDist2d(who) < 30.0f)
ScriptedAI::MoveInLineOfSight(who);
}
void EnterEvadeMode(EvadeReason why) override
{
if (!_EnterEvadeMode(why))
return;
Reset();
me->setActive(false);
}
void AttachLeftArm()
{
if (Unit* arm = ObjectAccessor::GetCreature(*me, _left))
arm->SetHealth(arm->GetMaxHealth());
else if (Creature* accessory = me->SummonCreature(NPC_LEFT_ARM, *me, TEMPSUMMON_MANUAL_DESPAWN))
{
accessory->AddUnitTypeMask(UNIT_MASK_ACCESSORY);
if (!me->HandleSpellClick(accessory, 0))
accessory->DespawnOrUnsummon();
else
{
_left = accessory->GetGUID();
accessory->SetOrientation(M_PI);
accessory->CastSpell(accessory, SPELL_ARM_RESPAWN_VISUAL, true);
}
}
}
void AttachRightArm()
{
if (Unit* arm = ObjectAccessor::GetCreature(*me, _right))
arm->SetHealth(arm->GetMaxHealth());
else if (Creature* accessory = me->SummonCreature(NPC_RIGHT_ARM, *me, TEMPSUMMON_MANUAL_DESPAWN))
{
accessory->AddUnitTypeMask(UNIT_MASK_ACCESSORY);
if (!me->HandleSpellClick(accessory, 1))
accessory->DespawnOrUnsummon();
else
{
_right = accessory->GetGUID();
accessory->SetOrientation(M_PI);
accessory->CastSpell(accessory, SPELL_ARM_RESPAWN_VISUAL, true);
}
}
}
void Reset() override
{
_rubbleAchievement = 0;
_looksAchievement = true;
me->SetDisableGravity(true);
me->SetUnitFlag(UNIT_FLAG_DISABLE_MOVE);
me->DisableRotate(true);
events.Reset();
summons.DespawnAll();
if (m_pInstance)
{
m_pInstance->SetData(TYPE_KOLOGARN, NOT_STARTED);
// Open the door inside Kologarn chamber
if (GameObject* door = m_pInstance->instance->GetGameObject(m_pInstance->GetGuidData(GO_KOLOGARN_DOORS)))
door->SetGoState(GO_STATE_ACTIVE);
}
AttachLeftArm();
AttachRightArm();
// Reset breath on pull
breathReady = false;
}
void DoAction(int32 param) override
{
if (param == DATA_KOLOGARN_LOOKS_ACHIEV)
_looksAchievement = false;
if (param == DATA_KOLOGARN_RUBBLE_ACHIEV)
{
// Means arm died
if (m_pInstance && (!_left || !_right))
m_pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEVEMENT_DISARMED_CRITERIA);
++_rubbleAchievement;
}
}
uint32 GetData(uint32 param) const override
{
if (param == DATA_KOLOGARN_LOOKS_ACHIEV)
return _looksAchievement;
else if (param == DATA_KOLOGARN_RUBBLE_ACHIEV)
return (_rubbleAchievement >= 5);
else if (param == DATA_KOLOGARN_ARMS_ACHIEV)
return !_rubbleAchievement;
return 0;
}
void AttackStart(Unit* who) override
{
me->Attack(who, true);
}
void JustSummoned(Creature* cr) override
{
if (cr->GetEntry() != NPC_LEFT_ARM && cr->GetEntry() != NPC_RIGHT_ARM)
summons.Summon(cr);
}
void JustDied(Unit*) override
{
summons.DespawnAll();
me->StopMoving();
if (m_pInstance)
m_pInstance->SetData(TYPE_KOLOGARN, DONE);
Talk(SAY_DEATH);
if (m_pInstance)
{
// Open the door inside Kologarn chamber
if (GameObject* door = m_pInstance->instance->GetGameObject(m_pInstance->GetGuidData(GO_KOLOGARN_DOORS)))
door->SetGoState(GO_STATE_ACTIVE);
}
if (GameObject* bridge = me->FindNearestGameObject(GO_KOLOGARN_BRIDGE, 100))
bridge->SetGoState(GO_STATE_READY);
// Summon Chest
if (GameObject* go = me->SummonGameObject(RAID_MODE(GO_KOLOGARN_CHEST, GO_KOLOGARN_CHEST_HERO), 1839.62f, -35.98f, 448.81f, 3.6f, 0, 0, 0, 0, 7 * 86400))
{
me->RemoveGameObject(go, false);
go->SetSpellId(1); // hack to make it despawn
go->ReplaceAllGameObjectFlags((GameObjectFlags)0);
go->SetLootRecipient(me);
}
if (Creature* arm = ObjectAccessor::GetCreature(*me, _left))
arm->DespawnOrUnsummon(3000); // visual
if (Creature* arm = ObjectAccessor::GetCreature(*me, _right))
arm->DespawnOrUnsummon(3000); // visual
}
void KilledUnit(Unit*) override
{
if (!urand(0, 2))
return;
Talk(SAY_SLAY);
}
void PassengerBoarded(Unit* who, int8 /*seatId*/, bool apply) override
{
if (!me->IsAlive())
return;
if (!apply)
{
// left arm
if (who->GetGUID() == _left)
{
_left.Clear();
if (me->IsInCombat())
{
Talk(SAY_LEFT_ARM_GONE);
events.ScheduleEvent(EVENT_RESTORE_ARM_LEFT, 50s);
}
}
else
{
_right.Clear();
if (me->IsInCombat())
{
Talk(SAY_RIGHT_ARM_GONE);
events.ScheduleEvent(EVENT_RESTORE_ARM_RIGHT, 50s);
}
}
me->CastSpell(me, SPELL_ARM_DEAD, true);
if (!_right && !_left)
events.ScheduleEvent(EVENT_STONE_SHOUT, 5s);
}
}
void DamageTaken(Unit* who, uint32& damage, DamageEffectType, SpellSchoolMask) override
{
if (who && who->GetEntry() == me->GetEntry() && me->GetHealth())
{
damage = std::min(damage, me->GetHealth() - 1);
me->LowerPlayerDamageReq(damage);
}
}
void JustEngagedWith(Unit* /*who*/) override
{
if (m_pInstance)
m_pInstance->SetData(TYPE_KOLOGARN, IN_PROGRESS);
events.ScheduleEvent(EVENT_SMASH, 8s);
events.ScheduleEvent(EVENT_SWEEP, 17s);
events.ScheduleEvent(EVENT_GRIP, 15s);
events.ScheduleEvent(EVENT_FOCUSED_EYEBEAM, 10s);
events.ScheduleEvent(EVENT_PREPARE_BREATH, 3s);
//events.ScheduleEvent(EVENT_ENRAGE, x); no info
Talk(SAY_AGGRO);
me->setActive(true);
// Close the door inside Kologarn chamber
if (m_pInstance)
{
if (GameObject* door = m_pInstance->instance->GetGameObject(m_pInstance->GetGuidData(GO_KOLOGARN_DOORS)))
{
door->SetGoState(GO_STATE_READY);
}
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
{
EnterEvadeMode(EVADE_REASON_OTHER);
return;
}
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{
case EVENT_PREPARE_BREATH:
breathReady = true;
break;
case EVENT_STONE_SHOUT:
if (_left || _right)
{
return;
}
me->CastSpell(me->GetVictim(), SPELL_STONE_SHOUT, false);
events.ScheduleEvent(EVENT_STONE_SHOUT, 2s);
break;
case EVENT_SMASH:
if (_left && _right)
me->CastSpell(me->GetVictim(), SPELL_OVERHEAD_SMASH, false);
else if (_left || _right)
me->CastSpell(me->GetVictim(), SPELL_ONEARMED_OVERHEAD_SMASH, false);
events.DelayEvents(1s);
events.ScheduleEvent(EVENT_SMASH, 14s);
return;
case EVENT_SWEEP:
if (_left)
{
if (Creature* cr = me->FindNearestCreature(NPC_SWEEP_TRIGGER, 300))
cr->CastSpell(cr, SPELL_ARM_SWEEP, false);
if (urand(0, 1))
Talk(SAY_SHOCKWAVE);
}
events.DelayEvents(1s);
events.ScheduleEvent(EVENT_SWEEP, 17s);
return;
case EVENT_GRIP:
events.ScheduleEvent(EVENT_GRIP, 25s);
if (!_right)
break;
me->CastSpell(me, SPELL_STONE_GRIP, false);
Talk(SAY_GRAB_PLAYER);
Talk(EMOTE_STONE_GRIP);
return;
case EVENT_FOCUSED_EYEBEAM:
{
events.ScheduleEvent(EVENT_FOCUSED_EYEBEAM, 20s);
if ((eyebeamTarget = SelectTarget(SelectTargetMethod::MinDistance, 0, 0, true)))
{
me->CastSpell(eyebeamTarget, SPELL_FOCUSED_EYEBEAM_SUMMON, false);
}
Talk(EMOTE_EYES);
return;
}
case EVENT_RESTORE_ARM_LEFT:
// shouldn't happen
AttachLeftArm();
return;
case EVENT_RESTORE_ARM_RIGHT:
// shouldn't happen
AttachRightArm();
return;
}
//Make sure our attack is ready and we aren't currently casting before checking distance
if (me->isAttackReady() && me->GetVictim()) // victim could die by a spell (IMPORTANT!!!) and kologarn entered evade mode
{
//If we are within range melee the target
if (me->IsWithinMeleeRange(me->GetVictim()))
{
me->AttackerStateUpdate(me->GetVictim());
me->resetAttackTimer();
return;
}
else if (Unit* tgt = me->SelectNearbyTarget())
{
me->AttackerStateUpdate(tgt);
me->resetAttackTimer();
return;
}
if (breathReady)
me->CastSpell(me->GetVictim(), SPELL_PETRIFYING_BREATH, false);
me->resetAttackTimer();
}
}
};
};
// also used for left arm, all functions except JustDied wont be used by left arm
class boss_kologarn_arms : public CreatureScript
{
public:
boss_kologarn_arms() : CreatureScript("boss_kologarn_arms") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return GetUlduarAI<boss_kologarn_armsAI>(pCreature);
}
struct boss_kologarn_armsAI : public ScriptedAI
{
boss_kologarn_armsAI(Creature* c) : ScriptedAI(c) { }
int32 _damageDone;
bool _combatStarted;
void EnterEvadeMode(EvadeReason /*why*/ = EVADE_REASON_OTHER) override {}
void MoveInLineOfSight(Unit*) override {}
void AttackStart(Unit*) override {}
void UpdateAI(uint32 /*diff*/) override {}
void Reset() override
{
_combatStarted = false;
_damageDone = 0;
}
void PassengerBoarded(Unit* /*who*/, int8 /*seatId*/, bool apply) override
{
if (!apply)
_damageDone = 0;
else
{
//who->ClearUnitState(UNIT_STATE_ONVEHICLE);
if (!_damageDone)
_damageDone = RAID_MODE(80000, 380000);
}
}
void DamageTaken(Unit* who, uint32& damage, DamageEffectType, SpellSchoolMask) override
{
if (!_combatStarted)
if (InstanceScript* instance = me->GetInstanceScript())
if (Creature* cr = ObjectAccessor::GetCreature(*me, instance->GetGuidData(TYPE_KOLOGARN)))
{
_combatStarted = true;
if (!cr->IsInCombat() && who)
cr->AI()->AttackStart(who);
}
if (_damageDone > 0)
{
_damageDone -= damage;
if (_damageDone <= 0 || damage >= me->GetHealth())
me->RemoveAurasByType(SPELL_AURA_CONTROL_VEHICLE);
}
}
void JustDied(Unit*) override
{
float x, y, z;
// left arm
if( me->GetEntry() == NPC_LEFT_ARM )
{
x = 1776.97f;
y = -44.8396f;
z = 448.888f;
}
else
{
x = 1777.82f;
y = -3.50803f;
z = 448.888f;
}
if (Creature* cr = me->SummonTrigger(x, y, z, 0, 5000))
{
cr->CastSpell(cr, SPELL_RUBBLE_FALL, true);
if (me->GetInstanceScript())
if (Creature* kologarn = ObjectAccessor::GetCreature(*me, me->GetInstanceScript()->GetGuidData(TYPE_KOLOGARN)))
for (uint8 i = 0; i < 5; ++i)
if (Creature* cr2 = kologarn->SummonCreature(NPC_RUBBLE_SUMMON, cr->GetPositionX() + irand(-5, 5), cr->GetPositionY() + irand(-5, 5), cr->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000))
{
cr2->SetInCombatWithZone();
if (Unit* target = SelectTargetFromPlayerList(100))
cr2->AI()->AttackStart(target);
}
}
if (me->GetInstanceScript())
if (Creature* cr = ObjectAccessor::GetCreature(*me, me->GetInstanceScript()->GetGuidData(TYPE_KOLOGARN)))
cr->AI()->DoAction(DATA_KOLOGARN_RUBBLE_ACHIEV);
me->ExitVehicle();
}
};
};
class boss_kologarn_eyebeam : public CreatureScript
{
public:
boss_kologarn_eyebeam() : CreatureScript("boss_kologarn_eyebeam") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return GetUlduarAI<boss_kologarn_eyebeamAI>(pCreature);
}
struct boss_kologarn_eyebeamAI : public ScriptedAI
{
boss_kologarn_eyebeamAI(Creature* c) : ScriptedAI(c), _timer(1), _damaged(false), justSpawned(true)
{
m_pInstance = (InstanceScript*)c->GetInstanceScript();
}
InstanceScript* m_pInstance;
uint32 _timer;
bool _damaged, justSpawned;
void DamageDealt(Unit* /*victim*/, uint32& damage, DamageEffectType /*damageType*/) override
{
if (damage > 0 && !_damaged && me->GetInstanceScript())
{
_damaged = true;
if (Creature* cr = ObjectAccessor::GetCreature(*me, me->GetInstanceScript()->GetGuidData(TYPE_KOLOGARN)))
cr->AI()->DoAction(DATA_KOLOGARN_LOOKS_ACHIEV);
}
}
void UpdateAI(uint32 diff) override
{
if (justSpawned)
{
me->DespawnOrUnsummon(10000);
if (Creature* cr = ObjectAccessor::GetCreature(*me, m_pInstance->GetGuidData(TYPE_KOLOGARN)))
{
me->CastSpell(cr, me->GetEntry() == NPC_EYE_LEFT ? SPELL_FOCUSED_EYEBEAM_LEFT : SPELL_FOCUSED_EYEBEAM_RIGHT, true);
}
me->CastSpell(me, SPELL_FOCUSED_EYEBEAM, true);
justSpawned = false;
}
if (_timer)
{
_timer += diff;
if (_timer >= 2000)
{
me->CastSpell(me, (me->GetMap()->Is25ManRaid() ? SPELL_FOCUSED_EYEBEAM_25 : SPELL_FOCUSED_EYEBEAM_10), true);
_timer = 0;
}
}
}
};
};
// predicate function to select non main tank target
class StoneGripTargetSelector
{
public:
StoneGripTargetSelector(Creature* me, Unit const* victim) : _me(me), _victim(victim) {}
bool operator() (WorldObject* target) const
{
if (target == _victim && _me->GetThreatMgr().GetThreatListSize() > 1)
return true;
if (target->GetTypeId() != TYPEID_PLAYER)
return true;
return false;
}
private:
Creature* _me;
Unit const* _victim;
};
class spell_ulduar_stone_grip_cast_target : public SpellScriptLoader
{
public:
spell_ulduar_stone_grip_cast_target() : SpellScriptLoader("spell_ulduar_stone_grip_cast_target") { }
class spell_ulduar_stone_grip_cast_target_SpellScript : public SpellScript
{
PrepareSpellScript(spell_ulduar_stone_grip_cast_target_SpellScript);
bool Load() override
{
if (GetCaster()->GetTypeId() != TYPEID_UNIT)
return false;
return true;
}
void FilterTargetsInitial(std::list<WorldObject*>& targets)
{
// Remove "main tank" and non-player targets
targets.remove_if (StoneGripTargetSelector(GetCaster()->ToCreature(), GetCaster()->GetVictim()));
// Maximum affected targets per difficulty mode
uint32 maxTargets = 1;
if (GetSpellInfo()->Id == 63981)
maxTargets = 3;
// Return a random amount of targets based on maxTargets
while (maxTargets < targets.size())
{
std::list<WorldObject*>::iterator itr = targets.begin();
advance(itr, urand(0, targets.size() - 1));
targets.erase(itr);
}
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_ulduar_stone_grip_cast_target_SpellScript::FilterTargetsInitial, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_ulduar_stone_grip_cast_target_SpellScript();
}
};
class spell_ulduar_stone_grip : public SpellScriptLoader
{
public:
spell_ulduar_stone_grip() : SpellScriptLoader("spell_ulduar_stone_grip") { }
class spell_ulduar_stone_grip_AuraScript : public AuraScript
{
PrepareAuraScript(spell_ulduar_stone_grip_AuraScript);
void OnRemoveStun(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
{
if (Player* owner = GetOwner()->ToPlayer())
owner->RemoveAurasDueToSpell(aurEff->GetAmount());
}
void Register() override
{
OnEffectRemove += AuraEffectRemoveFn(spell_ulduar_stone_grip_AuraScript::OnRemoveStun, EFFECT_2, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_ulduar_stone_grip_AuraScript();
}
};
class spell_ulduar_squeezed_lifeless : public SpellScriptLoader
{
public:
spell_ulduar_squeezed_lifeless() : SpellScriptLoader("spell_ulduar_squeezed_lifeless") { }
class spell_ulduar_squeezed_lifeless_SpellScript : public SpellScript
{
PrepareSpellScript(spell_ulduar_squeezed_lifeless_SpellScript);
void HandleInstaKill(SpellEffIndex /*effIndex*/)
{
if (!GetHitPlayer() || !GetHitPlayer()->GetVehicle())
return;
// Hack to set correct position is in _ExitVehicle()
GetHitPlayer()->ExitVehicle();
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_ulduar_squeezed_lifeless_SpellScript::HandleInstaKill, EFFECT_1, SPELL_EFFECT_INSTAKILL);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_ulduar_squeezed_lifeless_SpellScript();
}
};
class spell_kologarn_stone_shout : public SpellScriptLoader
{
public:
spell_kologarn_stone_shout() : SpellScriptLoader("spell_kologarn_stone_shout") { }
class spell_kologarn_stone_shout_AuraScript : public AuraScript
{
PrepareAuraScript(spell_kologarn_stone_shout_AuraScript);
void OnPeriodic(AuraEffect const* /*aurEff*/)
{
uint32 triggerSpellId = GetSpellInfo()->Effects[EFFECT_0].TriggerSpell;
if (Unit* caster = GetCaster())
caster->CastSpell(caster, triggerSpellId, false);
}
void Register() override
{
if (m_scriptSpellId == SPELL_STONE_SHOUT_10 || m_scriptSpellId == SPELL_STONE_SHOUT_25)
OnEffectPeriodic += AuraEffectPeriodicFn(spell_kologarn_stone_shout_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_kologarn_stone_shout_AuraScript();
}
class spell_kologarn_stone_shout_SpellScript : public SpellScript
{
PrepareSpellScript(spell_kologarn_stone_shout_SpellScript);
void FilterTargets(std::list<WorldObject*>& targets)
{
targets.remove_if (PlayerOrPetCheck());
}
void Register() override
{
if (m_scriptSpellId != SPELL_STONE_SHOUT_10 && m_scriptSpellId != SPELL_STONE_SHOUT_25)
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_kologarn_stone_shout_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_kologarn_stone_shout_SpellScript();
}
};
class achievement_kologarn_looks_could_kill : public AchievementCriteriaScript
{
public:
achievement_kologarn_looks_could_kill() : AchievementCriteriaScript("achievement_kologarn_looks_could_kill") {}
bool OnCheck(Player* /*player*/, Unit* target, uint32 /*criteria_id*/) override
{
if (target)
if (InstanceScript* instance = target->GetInstanceScript())
if (Creature* cr = ObjectAccessor::GetCreature(*target, instance->GetGuidData(TYPE_KOLOGARN)))
return cr->AI()->GetData(DATA_KOLOGARN_LOOKS_ACHIEV);
return false;
}
};
class achievement_kologarn_rubble_and_roll : public AchievementCriteriaScript
{
public:
achievement_kologarn_rubble_and_roll() : AchievementCriteriaScript("achievement_kologarn_rubble_and_roll") {}
bool OnCheck(Player* /*player*/, Unit* target, uint32 /*criteria_id*/) override
{
if (target)
if (InstanceScript* instance = target->GetInstanceScript())
if (Creature* cr = ObjectAccessor::GetCreature(*target, instance->GetGuidData(TYPE_KOLOGARN)))
return cr->AI()->GetData(DATA_KOLOGARN_RUBBLE_ACHIEV);
return false;
}
};
class achievement_kologarn_with_open_arms : public AchievementCriteriaScript
{
public:
achievement_kologarn_with_open_arms() : AchievementCriteriaScript("achievement_kologarn_with_open_arms") {}
bool OnCheck(Player* /*player*/, Unit* target, uint32 /*criteria_id*/) override
{
if (target)
if (InstanceScript* instance = target->GetInstanceScript())
if (Creature* cr = ObjectAccessor::GetCreature(*target, instance->GetGuidData(TYPE_KOLOGARN)))
return cr->AI()->GetData(DATA_KOLOGARN_ARMS_ACHIEV);
return false;
}
};
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff