refactor(Scripts/Ulduar): Update Ulduar to use boss states and other modernizations (#24714)

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Andrew
2026-02-15 08:57:57 -03:00
committed by GitHub
parent b348455d53
commit a05a43cee1
18 changed files with 9986 additions and 11504 deletions

View File

@@ -0,0 +1,2 @@
-- Remove unused ScriptName from Pure Saronite Deposit
UPDATE `gameobject_template` SET `ScriptName` = '' WHERE `entry` = 195036;

View File

@@ -97,7 +97,7 @@ enum Misc
struct boss_auriaya : public BossAI
{
boss_auriaya(Creature* creature) : BossAI(creature, TYPE_AURIAYA) { }
boss_auriaya(Creature* creature) : BossAI(creature, BOSS_AURIAYA) { }
bool _feralDied{false};
bool _nineLives{false};
@@ -230,8 +230,8 @@ struct npc_auriaya_sanctum_sentry : public ScriptedAI
void JustEngagedWith(Unit*) override
{
if (me->GetInstanceScript())
if (Creature* cr = ObjectAccessor::GetCreature(*me, me->GetInstanceScript()->GetGuidData(TYPE_AURIAYA)))
if (InstanceScript* instance = me->GetInstanceScript())
if (Creature* cr = instance->GetCreature(BOSS_AURIAYA))
cr->SetInCombatWithZone();
events.ScheduleEvent(EVENT_SAVAGE_POUNCE, 5s);
@@ -241,7 +241,7 @@ struct npc_auriaya_sanctum_sentry : public ScriptedAI
void Reset() override
{
events.Reset();
me->CastSpell(me, SPELL_STRENGTH_OF_THE_PACK, true);
DoCastSelf(SPELL_STRENGTH_OF_THE_PACK, true);
}
void UpdateAI(uint32 diff) override
@@ -303,8 +303,8 @@ struct npc_auriaya_feral_defender : public ScriptedAI
void JustDied(Unit*) override
{
if (me->GetInstanceScript())
if (Creature* cr = ObjectAccessor::GetCreature(*me, me->GetInstanceScript()->GetGuidData(TYPE_AURIAYA)))
if (InstanceScript* instance = me->GetInstanceScript())
if (Creature* cr = instance->GetCreature(BOSS_AURIAYA))
cr->AI()->DoAction(_feralEssenceStack ? ACTION_FERAL_DEATH_WITH_STACK : ACTION_FERAL_DEATH);
if (_feralEssenceStack)
@@ -357,11 +357,11 @@ struct npc_auriaya_feral_defender : public ScriptedAI
DoResetThreatList();
if (!UpdateVictim())
return;
me->CastSpell(me->GetVictim(), SPELL_FERAL_RUSH, true);
DoCastVictim(SPELL_FERAL_RUSH, true);
events.Repeat(6s);
break;
case EVENT_FERAL_POUNCE:
me->CastSpell(me->GetVictim(), SPELL_FERAL_POUNCE, false);
DoCastVictim(SPELL_FERAL_POUNCE);
events.Repeat(6s);
break;
}
@@ -394,8 +394,8 @@ public:
{
if (target)
if (InstanceScript* instance = target->GetInstanceScript())
if (Creature* cr = ObjectAccessor::GetCreature(*target, instance->GetGuidData(TYPE_AURIAYA)))
return cr->AI()->GetData(DATA_CRAZY_CAT);
if (Creature* auriaya = instance->GetCreature(BOSS_AURIAYA))
return auriaya->AI()->GetData(DATA_CRAZY_CAT);
return false;
}
@@ -410,7 +410,7 @@ public:
{
if (target)
if (InstanceScript* instance = target->GetInstanceScript())
if (Creature* cr = ObjectAccessor::GetCreature(*target, instance->GetGuidData(TYPE_AURIAYA)))
if (Creature* cr = instance->GetCreature(BOSS_AURIAYA))
return cr->AI()->GetData(DATA_NINE_LIVES);
return false;

File diff suppressed because it is too large Load Diff

View File

@@ -15,18 +15,14 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "AccountMgr.h"
#include "AchievementCriteriaScript.h"
#include "AreaDefines.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
@@ -110,367 +106,307 @@ enum VaporsText
SAY_EMOTE_VAPORS = 0,
};
class boss_vezax : public CreatureScript
struct boss_vezax : public BossAI
{
public:
boss_vezax() : CreatureScript("boss_vezax") { }
boss_vezax(Creature* pCreature) : BossAI(pCreature, BOSS_VEZAX) { }
CreatureAI* GetAI(Creature* pCreature) const override
uint8 vaporsCount;
bool hardmodeAvailable;
bool berserk;
bool bAchievShadowdodger;
void Reset() override
{
return GetUlduarAI<boss_vezaxAI>(pCreature);
_Reset();
vaporsCount = 0;
hardmodeAvailable = true;
berserk = false;
bAchievShadowdodger = true;
me->SetLootMode(1);
}
struct boss_vezaxAI : public ScriptedAI
void JustReachedHome() override
{
boss_vezaxAI(Creature* pCreature) : ScriptedAI(pCreature), summons(me)
_JustReachedHome();
me->setActive(false);
}
void JustEngagedWith(Unit* /*pWho*/) override
{
me->setActive(true);
_JustEngagedWith();
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);
me->CastSpell(me, SPELL_AURA_OF_DESPAIR_1, true);
}
void DoAction(int32 param) override
{
switch (param)
{
pInstance = pCreature->GetInstanceScript();
case 1:
hardmodeAvailable = false;
break;
case 2:
me->RemoveAura(SPELL_SARONITE_BARRIER);
me->SetLootMode(3);
break;
}
}
EventMap events;
SummonList summons;
uint8 vaporsCount;
bool hardmodeAvailable;
bool berserk;
bool bAchievShadowdodger;
InstanceScript* pInstance;
void Reset() override
uint32 GetData(uint32 id) const override
{
switch (id)
{
vaporsCount = 0;
hardmodeAvailable = true;
berserk = false;
bAchievShadowdodger = true;
events.Reset();
summons.DespawnAll();
me->SetLootMode(1);
if (pInstance)
pInstance->SetData(TYPE_VEZAX, NOT_STARTED);
case 1:
return (me->GetLootMode() == 3 ? 1 : 0);
case 2:
return (bAchievShadowdodger ? 1 : 0);
}
return 0;
}
void JustReachedHome() override
void SpellHitTarget(Unit* target, SpellInfo const* spell) override
{
if (target && spell && target->IsPlayer() && 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())
{
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->IsPlayer() && 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(10s, 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(12s, 0);
events.DelayEvents(12s, 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 )
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:
{
door->SetLootState(GO_READY);
door->UseDoorOrButton(0, false);
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(10s, 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(12s, 0);
events.DelayEvents(12s, 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;
}
void KilledUnit(Unit* who) override
{
if (who->IsPlayer())
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);
DoMeleeAttackIfReady();
}
struct npc_ulduar_saronite_vaporsAI : public NullCreatureAI
void JustDied(Unit* /*killer*/) override
{
npc_ulduar_saronite_vaporsAI(Creature* pCreature) : NullCreatureAI(pCreature)
{
pInstance = pCreature->GetInstanceScript();
me->GetMotionMaster()->MoveRandom(4.0f);
}
_JustDied();
Talk(SAY_DEATH);
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(3s);
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)
if (GameObject* door = me->FindNearestGameObject(GO_VEZAX_DOOR, 500.0f))
if (door->GetGoState() != GO_STATE_ACTIVE)
{
me->CastSpell(me, SPELL_PROFOUND_DARKNESS, true);
timer -= 2000;
door->SetLootState(GO_READY);
door->UseDoorOrButton(0, false);
}
}
DoMeleeAttackIfReady();
void KilledUnit(Unit* who) override
{
if (who->IsPlayer())
Talk(SAY_SLAY);
}
void MoveInLineOfSight(Unit* /*who*/) override {}
};
struct npc_ulduar_saronite_vapors : public NullCreatureAI
{
npc_ulduar_saronite_vapors(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 = pInstance->GetCreature(BOSS_VEZAX))
vezax->AI()->DoAction(1);
}
void IsSummonedBy(WorldObject* /*summoner*/) override
{
Talk(SAY_EMOTE_VAPORS);
}
};
struct npc_ulduar_saronite_animus : public ScriptedAI
{
npc_ulduar_saronite_animus(Creature* pCreature) : ScriptedAI(pCreature)
{
pInstance = pCreature->GetInstanceScript();
if (pInstance)
if (Creature* vezax = pInstance->GetCreature(BOSS_VEZAX))
vezax->AI()->JustSummoned(me);
timer = 0;
me->SetInCombatWithZone();
}
InstanceScript* pInstance;
uint16 timer;
void JustDied(Unit* /*killer*/) override
{
me->DespawnOrUnsummon(3s);
if (pInstance)
if (Creature* vezax = pInstance->GetCreature(BOSS_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_aura : public AuraScript
@@ -630,34 +566,11 @@ public:
}
};
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();
new npc_ulduar_saronite_vapors();
new npc_ulduar_saronite_animus();
RegisterUlduarCreatureAI(boss_vezax);
RegisterUlduarCreatureAI(npc_ulduar_saronite_vapors);
RegisterUlduarCreatureAI(npc_ulduar_saronite_animus);
RegisterSpellScript(spell_aura_of_despair_aura);
RegisterSpellScript(spell_mark_of_the_faceless_periodic_aura);
@@ -668,5 +581,4 @@ void AddSC_boss_vezax()
new achievement_smell_saronite();
new achievement_shadowdodger();
new go_ulduar_pure_saronite_deposit();
}

File diff suppressed because it is too large Load Diff

View File

@@ -48,7 +48,6 @@ enum IgnisSpellData
enum IgnisNPCs
{
BOSS_IGNIS = 33118,
NPC_IRON_CONSTRUCT = 33121,
NPC_SCORCHED_GROUND = 33123,
NPC_WATER_TRIGGER = 22515,
@@ -78,155 +77,130 @@ enum eEvents
EVENT_GRAB,
};
class npc_ulduar_iron_construct : public CreatureScript
struct npc_ulduar_iron_construct : public ScriptedAI
{
public:
npc_ulduar_iron_construct() : CreatureScript("npc_ulduar_iron_construct") { }
CreatureAI* GetAI(Creature* pCreature) const override
npc_ulduar_iron_construct(Creature* pCreature) : ScriptedAI(pCreature)
{
return GetUlduarAI<npc_ulduar_iron_constructAI>(pCreature);
me->CastSpell(me, 38757, true);
}
struct npc_ulduar_iron_constructAI : public ScriptedAI
uint16 timer;
void Reset() override
{
npc_ulduar_iron_constructAI(Creature* pCreature) : ScriptedAI(pCreature)
{
me->CastSpell(me, 38757, true);
}
timer = 1000;
me->SetReactState(REACT_PASSIVE);
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
}
uint16 timer;
void JustReachedHome() override
{
me->CastSpell(me, 38757, true);
}
void Reset() override
void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
{
if (spell->Id == SPELL_ACTIVATE_CONSTRUCT)
{
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))
me->RemoveAura(38757);
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
me->SetReactState(REACT_AGGRESSIVE);
if (InstanceScript* instance = me->GetInstanceScript())
if (Creature* ignis = instance->GetCreature(BOSS_IGNIS))
{
if (heat->GetStackAmount() >= 10)
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)
{
if (heat->GetStackAmount() > 10)
{
heat->ModStackAmount(-1);
}
me->CastSpell(me, SPELL_MOLTEN, true);
me->GetThreatMgr().ResetAllThreat();
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(sSpellMgr->GetSpellIdForDifficulty(SPELL_BRITTLE, me)))
{
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, SPELL_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
void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType, SpellSchoolMask) override
{
boss_ignisAI(Creature* pCreature) : ScriptedAI(pCreature) { }
EventMap events;
uint8 counter;
bool bShattered;
uint32 lastShatterMSTime;
void Reset() override
if (damage >= RAID_MODE(3000U, 5000U) && me->GetAura(sSpellMgr->GetSpellIdForDifficulty(SPELL_BRITTLE, me)))
{
events.Reset();
me->SetControlled(false, UNIT_STATE_ROOT);
me->DisableRotate(false);
counter = 0;
bShattered = false;
lastShatterMSTime = 0;
me->CastSpell(me, SPELL_SHATTER, true);
Unit::Kill(attacker, me);
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);
}
if (InstanceScript* instance = me->GetInstanceScript())
if (Creature* ignis = instance->GetCreature(BOSS_IGNIS))
ignis->AI()->SetData(1337, 0);
}
}
void JustEngagedWith(Unit* /*who*/) override
void JustDied(Unit* /*killer*/) override
{
if (InstanceScript* instance = me->GetInstanceScript())
if (Creature* ignis = instance->GetCreature(BOSS_IGNIS))
ignis->RemoveAuraFromStack(SPELL_STRENGTH_OF_THE_CREATOR);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
if (timer <= diff)
{
me->setActive(true);
timer = 1000;
if (Aura* a = me->GetAura(SPELL_MOLTEN))
if (me->FindNearestCreature(NPC_WATER_TRIGGER, 18.0f, true))
{
me->RemoveAura(a);
me->CastSpell(me, SPELL_BRITTLE, true);
}
}
else
timer -= diff;
std::list<Creature*> icl;
me->GetCreaturesWithEntryInRange(icl, 300.0f, NPC_IRON_CONSTRUCT);
DoMeleeAttackIfReady();
}
void MoveInLineOfSight(Unit* /*who*/) override {}
};
struct boss_ignis : public BossAI
{
boss_ignis(Creature* pCreature) : BossAI(pCreature, BOSS_IGNIS) { }
uint8 counter;
bool bShattered;
uint32 lastShatterMSTime;
void Reset() override
{
_Reset();
me->SetControlled(false, UNIT_STATE_ROOT);
me->DisableRotate(false);
counter = 0;
bShattered = false;
lastShatterMSTime = 0;
if (instance)
instance->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())
@@ -240,185 +214,183 @@ public:
(*itr)->CastSpell((*itr), 38757, true);
}
bShattered = false;
lastShatterMSTime = 0;
events.Reset();
events.ScheduleEvent(EVENT_ACTIVATE_CONSTRUCT, RAID_MODE(40s, 30s));
events.ScheduleEvent(EVENT_SPELL_SCORCH, 10s);
events.ScheduleEvent(EVENT_SPELL_FLAME_JETS, 32s);
events.ScheduleEvent(EVENT_GRAB, 25s);
bShattered = false;
lastShatterMSTime = 0;
events.Reset();
events.ScheduleEvent(EVENT_ACTIVATE_CONSTRUCT, RAID_MODE(40s, 30s));
events.ScheduleEvent(EVENT_SPELL_SCORCH, 10s);
events.ScheduleEvent(EVENT_SPELL_FLAME_JETS, 32s);
events.ScheduleEvent(EVENT_GRAB, 25s);
Talk(SAY_AGGRO);
DoZoneInCombat();
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);
}
if (instance)
{
instance->SetBossState(BOSS_IGNIS, IN_PROGRESS);
instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_STOKIN_THE_FURNACE_EVENT);
instance->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
{
_JustReachedHome();
me->setActive(false);
}
void KilledUnit(Unit* victim) override
{
if (victim->IsPlayer())
Talk(SAY_SLAY);
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_DEATH);
_JustDied();
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, SPELL_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;
}
void SetData(uint32 id, uint32 /*value*/) override
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{
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->IsPlayer())
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, SPELL_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:
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;
case EVENT_ACTIVATE_CONSTRUCT:
Talk(SAY_SUMMON);
me->CastCustomSpell(SPELL_ACTIVATE_CONSTRUCT, SPELLVALUE_MAX_TARGETS, 1, (Unit*)nullptr, false);
if (++counter >= 20)
}
events.Repeat(RAID_MODE(40s, 30s));
break;
case EVENT_SPELL_SCORCH:
Talk(SAY_SCORCH);
me->SetControlled(true, UNIT_STATE_ROOT);
me->DisableRotate(true);
me->SendMovementFlagUpdate();
me->CastSpell(me->GetVictim(), SPELL_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(), SPELL_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)
{
Talk(SAY_BERSERK);
me->CastSpell(me, SPELL_BERSERK, true);
break;
}
events.Repeat(RAID_MODE(40s, 30s));
break;
case EVENT_SPELL_SCORCH:
Talk(SAY_SCORCH);
me->SetControlled(true, UNIT_STATE_ROOT);
me->DisableRotate(true);
me->SendMovementFlagUpdate();
me->CastSpell(me->GetVictim(), SPELL_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(), SPELL_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)
{
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())
{
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);
found = true;
break;
}
}
events.Repeat(24s);
events.DelayEvents(6s);
if (!found)
playerGUIDs.push_back(temp->GetGUID());
}
break;
}
DoMeleeAttackIfReady();
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;
}
void EnterEvadeMode(EvadeReason why) override
{
me->SetControlled(false, UNIT_STATE_ROOT);
me->DisableRotate(false);
ScriptedAI::EnterEvadeMode(why);
}
};
DoMeleeAttackIfReady();
}
void EnterEvadeMode(EvadeReason why) override
{
me->SetControlled(false, UNIT_STATE_ROOT);
me->DisableRotate(false);
BossAI::EnterEvadeMode(why);
}
};
class spell_ignis_scorch_aura : public AuraScript
@@ -541,8 +513,8 @@ public:
void AddSC_boss_ignis()
{
new boss_ignis();
new npc_ulduar_iron_construct();
RegisterUlduarCreatureAI(boss_ignis);
RegisterUlduarCreatureAI(npc_ulduar_iron_construct);
RegisterSpellScript(spell_ignis_scorch_aura);
RegisterSpellScript(spell_ignis_grab_initial);
RegisterSpellScript(spell_ignis_slag_pot_aura);

View File

@@ -117,34 +117,19 @@ enum Misc
DATA_KOLOGARN_ARMS_ACHIEV = 57,
};
class boss_kologarn : public CreatureScript
struct boss_kologarn : public BossAI
{
public:
boss_kologarn() : CreatureScript("boss_kologarn") { }
CreatureAI* GetAI(Creature* pCreature) const override
boss_kologarn(Creature* creature) : BossAI(creature, BOSS_KOLOGARN), vehicle(me->GetVehicleKit()), breathReady(false)
{
return GetUlduarAI<boss_kologarnAI>(pCreature);
assert(vehicle);
me->SetStandState(UNIT_STAND_STATE_SUBMERGED);
}
struct boss_kologarnAI : public ScriptedAI
{
boss_kologarnAI(Creature* pCreature) : ScriptedAI(pCreature), vehicle(me->GetVehicleKit()), summons(me), breathReady(false)
{
m_pInstance = me->GetInstanceScript();
assert(vehicle);
me->SetStandState(UNIT_STAND_STATE_SUBMERGED);
}
Vehicle* vehicle;
ObjectGuid _left, _right;
InstanceScript* m_pInstance;
Vehicle* vehicle;
ObjectGuid _left, _right;
EventMap events;
SummonList summons;
bool _looksAchievement, breathReady;
uint8 _rubbleAchievement;
bool _looksAchievement, breathReady;
uint8 _rubbleAchievement;
void MoveInLineOfSight(Unit* who) override
{
@@ -158,13 +143,18 @@ public:
}
if (me->GetExactDist2d(who) < 30.0f)
ScriptedAI::MoveInLineOfSight(who);
BossAI::MoveInLineOfSight(who);
}
void EnterEvadeMode(EvadeReason why) override
{
if (!_EnterEvadeMode(why))
if (!CreatureAI::_EnterEvadeMode(why))
return;
if (instance && instance->GetBossState(BOSS_KOLOGARN) != DONE)
{
instance->SetBossState(BOSS_KOLOGARN, NOT_STARTED);
instance->SaveToDB();
}
Reset();
me->setActive(false);
}
@@ -214,15 +204,12 @@ public:
me->SetDisableGravity(true);
me->DisableRotate(true);
events.Reset();
summons.DespawnAll();
_Reset();
if (m_pInstance)
if (instance)
{
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)))
if (GameObject* door = instance->GetGameObject(DATA_KOLOGARN_DOORS))
door->SetGoState(GO_STATE_ACTIVE);
}
@@ -240,8 +227,8 @@ public:
if (param == DATA_KOLOGARN_RUBBLE_ACHIEV)
{
// Means arm died
if (m_pInstance && (!_left || !_right))
m_pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEVEMENT_DISARMED_CRITERIA);
if (instance && (!_left || !_right))
instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEVEMENT_DISARMED_CRITERIA);
++_rubbleAchievement;
}
@@ -267,12 +254,12 @@ public:
void JustSummoned(Creature* cr) override
{
if (cr->GetEntry() != NPC_LEFT_ARM && cr->GetEntry() != NPC_RIGHT_ARM)
summons.Summon(cr);
BossAI::JustSummoned(cr);
}
void SummonedCreatureDespawn(Creature* cr) override
{
if (m_pInstance->GetData(TYPE_KOLOGARN) > NOT_STARTED)
if (instance->GetBossState(BOSS_KOLOGARN) > NOT_STARTED)
return;
if (cr->GetEntry() == NPC_LEFT_ARM)
@@ -290,17 +277,15 @@ public:
void JustDied(Unit*) override
{
summons.DespawnAll();
_JustDied();
me->StopMoving();
if (m_pInstance)
m_pInstance->SetData(TYPE_KOLOGARN, DONE);
Talk(SAY_DEATH);
if (m_pInstance)
if (instance)
{
// Open the door inside Kologarn chamber
if (GameObject* door = m_pInstance->instance->GetGameObject(m_pInstance->GetGuidData(GO_KOLOGARN_DOORS)))
if (GameObject* door = instance->GetGameObject(DATA_KOLOGARN_DOORS))
door->SetGoState(GO_STATE_ACTIVE);
}
@@ -333,7 +318,7 @@ public:
void PassengerBoarded(Unit* who, int8 /*seatId*/, bool apply) override
{
if (!me->IsAlive() || m_pInstance->GetData(TYPE_KOLOGARN) != IN_PROGRESS)
if (!me->IsAlive() || instance->GetBossState(BOSS_KOLOGARN) != IN_PROGRESS)
return;
if (!apply)
@@ -375,8 +360,8 @@ public:
void JustEngagedWith(Unit* /*who*/) override
{
if (m_pInstance)
m_pInstance->SetData(TYPE_KOLOGARN, IN_PROGRESS);
if (instance)
instance->SetBossState(BOSS_KOLOGARN, IN_PROGRESS);
events.ScheduleEvent(EVENT_SMASH, 8s);
events.ScheduleEvent(EVENT_SWEEP, 17s);
@@ -389,9 +374,9 @@ public:
me->setActive(true);
// Close the door inside Kologarn chamber
if (m_pInstance)
if (instance)
{
if (GameObject* door = m_pInstance->instance->GetGameObject(m_pInstance->GetGuidData(GO_KOLOGARN_DOORS)))
if (GameObject* door = instance->GetGameObject(DATA_KOLOGARN_DOORS))
{
door->SetGoState(GO_STATE_READY);
}
@@ -491,173 +476,151 @@ public:
me->resetAttackTimer();
}
}
};
};
// also used for left arm, all functions except JustDied wont be used by left arm
class boss_kologarn_arms : public CreatureScript
struct boss_kologarn_arms : public ScriptedAI
{
public:
boss_kologarn_arms() : CreatureScript("boss_kologarn_arms") { }
boss_kologarn_arms(Creature* c) : ScriptedAI(c) { }
CreatureAI* GetAI(Creature* pCreature) const override
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
{
return GetUlduarAI<boss_kologarn_armsAI>(pCreature);
_combatStarted = false;
_damageDone = 0;
}
struct boss_kologarn_armsAI : public ScriptedAI
void PassengerBoarded(Unit* /*who*/, int8 /*seatId*/, bool apply) override
{
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;
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 = instance->GetCreature(BOSS_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;
}
void PassengerBoarded(Unit* /*who*/, int8 /*seatId*/, bool apply) override
if (Creature* cr = me->SummonTrigger(x, y, z, 0, 5000))
{
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);
}
}
cr->CastSpell(cr, SPELL_RUBBLE_FALL, true);
if (me->GetInstanceScript())
if (Creature* cr = ObjectAccessor::GetCreature(*me, me->GetInstanceScript()->GetGuidData(TYPE_KOLOGARN)))
cr->AI()->DoAction(DATA_KOLOGARN_RUBBLE_ACHIEV);
me->ExitVehicle();
if (Creature* kologarn = me->GetInstanceScript()->GetCreature(BOSS_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 = me->GetInstanceScript()->GetCreature(BOSS_KOLOGARN))
cr->AI()->DoAction(DATA_KOLOGARN_RUBBLE_ACHIEV);
me->ExitVehicle();
}
};
class boss_kologarn_eyebeam : public CreatureScript
struct boss_kologarn_eyebeam : public ScriptedAI
{
public:
boss_kologarn_eyebeam() : CreatureScript("boss_kologarn_eyebeam") { }
CreatureAI* GetAI(Creature* pCreature) const override
boss_kologarn_eyebeam(Creature* c) : ScriptedAI(c), _timer(1), _damaged(false)
{
return GetUlduarAI<boss_kologarn_eyebeamAI>(pCreature);
m_pInstance = (InstanceScript*)c->GetInstanceScript();
}
struct boss_kologarn_eyebeamAI : public ScriptedAI
InstanceScript* m_pInstance;
uint32 _timer;
bool _damaged;
void DamageDealt(Unit* /*victim*/, uint32& damage, DamageEffectType /*damageType*/, SpellSchoolMask /*damageSchoolMask*/) override
{
boss_kologarn_eyebeamAI(Creature* c) : ScriptedAI(c), _timer(1), _damaged(false)
if (damage > 0 && !_damaged && me->GetInstanceScript())
{
m_pInstance = (InstanceScript*)c->GetInstanceScript();
_damaged = true;
if (Creature* cr = me->GetInstanceScript()->GetCreature(BOSS_KOLOGARN))
cr->AI()->DoAction(DATA_KOLOGARN_LOOKS_ACHIEV);
}
}
void IsSummonedBy(WorldObject* summoner) override
{
if (!summoner)
{
return;
}
InstanceScript* m_pInstance;
uint32 _timer;
bool _damaged;
void DamageDealt(Unit* /*victim*/, uint32& damage, DamageEffectType /*damageType*/, SpellSchoolMask /*damageSchoolMask*/) override
// Should only work on playable characters
if (Player* player = summoner->ToPlayer())
{
if (damage > 0 && !_damaged && me->GetInstanceScript())
me->Attack(player, false);
me->GetMotionMaster()->MoveChase(player);
if (Creature* cr = m_pInstance->GetCreature(BOSS_KOLOGARN))
{
_damaged = true;
if (Creature* cr = ObjectAccessor::GetCreature(*me, me->GetInstanceScript()->GetGuidData(TYPE_KOLOGARN)))
cr->AI()->DoAction(DATA_KOLOGARN_LOOKS_ACHIEV);
me->CastSpell(cr, me->GetEntry() == NPC_EYE_LEFT ? SPELL_FOCUSED_EYEBEAM_LEFT : SPELL_FOCUSED_EYEBEAM_RIGHT, true);
}
}
}
void IsSummonedBy(WorldObject* summoner) override
void UpdateAI(uint32 diff) override
{
if (_timer)
{
if (!summoner)
_timer += diff;
if (_timer >= 2000)
{
return;
}
// Should only work on playable characters
if (Player* player = summoner->ToPlayer())
{
me->Attack(player, false);
me->GetMotionMaster()->MoveChase(player);
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);
_timer = 0;
}
}
void UpdateAI(uint32 diff) override
{
if (_timer)
{
_timer += diff;
if (_timer >= 2000)
{
me->CastSpell(me, SPELL_FOCUSED_EYEBEAM, true);
_timer = 0;
}
}
}
};
}
};
class spell_kologarn_focused_eyebeam : public SpellScript
@@ -867,7 +830,7 @@ public:
{
if (target)
if (InstanceScript* instance = target->GetInstanceScript())
if (Creature* cr = ObjectAccessor::GetCreature(*target, instance->GetGuidData(TYPE_KOLOGARN)))
if (Creature* cr = instance->GetCreature(BOSS_KOLOGARN))
return cr->AI()->GetData(DATA_KOLOGARN_LOOKS_ACHIEV);
return false;
@@ -883,7 +846,7 @@ public:
{
if (target)
if (InstanceScript* instance = target->GetInstanceScript())
if (Creature* cr = ObjectAccessor::GetCreature(*target, instance->GetGuidData(TYPE_KOLOGARN)))
if (Creature* cr = instance->GetCreature(BOSS_KOLOGARN))
return cr->AI()->GetData(DATA_KOLOGARN_RUBBLE_ACHIEV);
return false;
@@ -899,7 +862,7 @@ public:
{
if (target)
if (InstanceScript* instance = target->GetInstanceScript())
if (Creature* cr = ObjectAccessor::GetCreature(*target, instance->GetGuidData(TYPE_KOLOGARN)))
if (Creature* cr = instance->GetCreature(BOSS_KOLOGARN))
return cr->AI()->GetData(DATA_KOLOGARN_ARMS_ACHIEV);
return false;
@@ -909,9 +872,9 @@ public:
void AddSC_boss_kologarn()
{
// Npcs
new boss_kologarn();
new boss_kologarn_arms();
new boss_kologarn_eyebeam();
RegisterUlduarCreatureAI(boss_kologarn);
RegisterUlduarCreatureAI(boss_kologarn_arms);
RegisterUlduarCreatureAI(boss_kologarn_eyebeam);
RegisterUlduarCreatureAI(boss_kologarn_pit_kill_bunny);
// Spells

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

View File

@@ -300,56 +300,148 @@ private:
uint8 _counter;
};
class npc_ulduar_storm_tempered_keeper : public CreatureScript
struct npc_ulduar_storm_tempered_keeper : public ScriptedAI
{
public:
npc_ulduar_storm_tempered_keeper() : CreatureScript("npc_ulduar_storm_tempered_keeper") { }
CreatureAI* GetAI(Creature* creature) const override
npc_ulduar_storm_tempered_keeper(Creature* creature) : ScriptedAI(creature)
{
return GetUlduarAI<npc_ulduar_storm_tempered_keeperAI>(creature);
otherGUID.Clear();
}
struct npc_ulduar_storm_tempered_keeperAI : public ScriptedAI
EventMap events;
ObjectGuid otherGUID;
void Reset() override
{
npc_ulduar_storm_tempered_keeperAI(Creature* creature) : ScriptedAI(creature)
events.Reset();
}
void JustEngagedWith(Unit* /*who*/) override
{
events.Reset();
events.ScheduleEvent(1, 2s); // checking Separation Anxiety, Charged Sphere
events.ScheduleEvent(2, 5s, 8s); // Forked Lightning
events.ScheduleEvent(3, (me->GetEntry() == 33722 ? 20s : 50s)); // Summon Charged Sphere
if (Creature* c = me->FindNearestCreature((me->GetEntry() == 33722 ? 33699 : 33722), 30.0f, true))
otherGUID = c->GetGUID();
else
me->CastSpell(me, 63630, true); // Vengeful Surge
}
void JustDied(Unit* /*killer*/) override
{
if (Creature* c = ObjectAccessor::GetCreature(*me, otherGUID))
c->CastSpell(c, 63630, true); // Vengeful Surge
}
void JustSummoned(Creature* s) override
{
if (Creature* c = ObjectAccessor::GetCreature(*me, otherGUID))
s->GetMotionMaster()->MoveFollow(c, 0.0f, 0.0f);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{
otherGUID.Clear();
case 0:
break;
case 1:
if (Creature* c = ObjectAccessor::GetCreature(*me, otherGUID))
if (c->IsAlive() && me->GetExactDist2d(c) > 45.0f)
me->CastSpell(me, 63539, true);
if (Creature* c = me->FindNearestCreature(33715, 2.0f, true))
if (c->IsSummon())
if (c->ToTempSummon()->GetSummonerGUID() != me->GetGUID())
me->CastSpell(me, 63528, true);
events.Repeat(2s);
break;
case 2:
me->CastSpell(me->GetVictim(), 63541, false);
events.Repeat(10s, 14s);
break;
case 3:
if (!me->HasAura(63630))
me->CastSpell(me, 63527, false);
events.Repeat(1min);
break;
}
EventMap events;
ObjectGuid otherGUID;
DoMeleeAttackIfReady();
}
};
void Reset() override
struct npc_ulduar_arachnopod_destroyer : public ScriptedAI
{
npc_ulduar_arachnopod_destroyer(Creature* creature) : ScriptedAI(creature)
{
_spawnedMechanic = false;
me->ApplySpellImmune(0, IMMUNITY_ID, 64919, true); // Ice Nova from Ice Turret
}
EventMap events;
bool _spawnedMechanic;
void Reset() override
{
events.Reset();
events.ScheduleEvent(1, 5s, 8s); // Flame Spray
events.ScheduleEvent(2, 3s, 6s); // Machine Gun
events.ScheduleEvent(3, 1s); // Charged Leap
}
void PassengerBoarded(Unit* p, int8 /*seat*/, bool /*apply*/) override
{
me->SetFaction(p->GetFaction());
me->SetReactState(REACT_PASSIVE);
}
void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
{
if (!_spawnedMechanic && me->HealthBelowPctDamaged(20, damage))
{
events.Reset();
_spawnedMechanic = true;
if (Creature* c = me->SummonCreature(34184, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), TEMPSUMMON_MANUAL_DESPAWN, 0))
c->AI()->AttackStart(me->GetVictim());
me->InterruptNonMeleeSpells(false);
me->CombatStop(true);
me->SetReactState(REACT_PASSIVE);
me->SetRegeneratingHealth(false);
me->SetFaction(FACTION_PREY);
me->SetNpcFlag(UNIT_NPC_FLAG_SPELLCLICK);
me->CastSpell(me, 64770, true);
}
}
void JustEngagedWith(Unit* /*who*/) override
void AttackStart(Unit* who) override
{
if (me->GetFaction() == FACTION_MONSTER_2)
ScriptedAI::AttackStart(who);
}
void EnterEvadeMode(EvadeReason why) override
{
if (me->GetFaction() == FACTION_MONSTER_2)
ScriptedAI::EnterEvadeMode(why);
}
void OnCharmed(bool /*apply*/) override {}
void UpdateAI(uint32 diff) override
{
if (me->GetFaction() != FACTION_MONSTER_2)
{
events.Reset();
events.ScheduleEvent(1, 2s); // checking Separation Anxiety, Charged Sphere
events.ScheduleEvent(2, 5s, 8s); // Forked Lightning
events.ScheduleEvent(3, (me->GetEntry() == 33722 ? 20s : 50s)); // Summon Charged Sphere
if (Creature* c = me->FindNearestCreature((me->GetEntry() == 33722 ? 33699 : 33722), 30.0f, true))
otherGUID = c->GetGUID();
else
me->CastSpell(me, 63630, true); // Vengeful Surge
if (me->IsAlive() && (me->GetExactDist2dSq(2058.0f, 42.0f) < 25.0f * 25.0f || me->GetExactDist2dSq(2203.0f, 292.0f) < 25.0f * 25.0f || me->GetExactDist2dSq(2125.0f, 170.0f) > 160.0f * 160.0f))
Unit::Kill(me, me, false);
}
void JustDied(Unit* /*killer*/) override
{
if (Creature* c = ObjectAccessor::GetCreature(*me, otherGUID))
c->CastSpell(c, 63630, true); // Vengeful Surge
}
void JustSummoned(Creature* s) override
{
if (Creature* c = ObjectAccessor::GetCreature(*me, otherGUID))
s->GetMotionMaster()->MoveFollow(c, 0.0f, 0.0f);
}
void UpdateAI(uint32 diff) override
else
{
if (!UpdateVictim())
return;
@@ -364,144 +456,30 @@ public:
case 0:
break;
case 1:
if (Creature* c = ObjectAccessor::GetCreature(*me, otherGUID))
if (c->IsAlive() && me->GetExactDist2d(c) > 45.0f)
me->CastSpell(me, 63539, true);
if (Creature* c = me->FindNearestCreature(33715, 2.0f, true))
if (c->IsSummon())
if (c->ToTempSummon()->GetSummonerGUID() != me->GetGUID())
me->CastSpell(me, 63528, true);
events.Repeat(2s);
me->CastSpell(me->GetVictim(), SPELL_FLAME_SPRAY, false);
events.Repeat(15s, 25s);
break;
case 2:
me->CastSpell(me->GetVictim(), 63541, false);
events.Repeat(10s, 14s);
me->CastSpell(me->GetVictim(), SPELL_MACHINE_GUN, false);
events.Repeat(10s, 15s);
break;
case 3:
if (!me->HasAura(63630))
me->CastSpell(me, 63527, false);
events.Repeat(1min);
{
float dist = me->GetDistance(me->GetVictim());
if (dist > 10.0f && dist < 40.0f)
{
me->CastSpell(me->GetVictim(), 64779, false);
events.Repeat(25s);
}
else
events.Repeat(3s);
}
break;
}
DoMeleeAttackIfReady();
}
};
};
class npc_ulduar_arachnopod_destroyer : public CreatureScript
{
public:
npc_ulduar_arachnopod_destroyer() : CreatureScript("npc_ulduar_arachnopod_destroyer") { }
CreatureAI* GetAI(Creature* creature) const override
{
return GetUlduarAI<npc_ulduar_arachnopod_destroyerAI>(creature);
}
struct npc_ulduar_arachnopod_destroyerAI : public ScriptedAI
{
npc_ulduar_arachnopod_destroyerAI(Creature* creature) : ScriptedAI(creature)
{
_spawnedMechanic = false;
me->ApplySpellImmune(0, IMMUNITY_ID, 64919, true); // Ice Nova from Ice Turret
}
EventMap events;
bool _spawnedMechanic;
void Reset() override
{
events.Reset();
events.ScheduleEvent(1, 5s, 8s); // Flame Spray
events.ScheduleEvent(2, 3s, 6s); // Machine Gun
events.ScheduleEvent(3, 1s); // Charged Leap
}
void PassengerBoarded(Unit* p, int8 /*seat*/, bool /*apply*/) override
{
me->SetFaction(p->GetFaction());
me->SetReactState(REACT_PASSIVE);
}
void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
{
if (!_spawnedMechanic && me->HealthBelowPctDamaged(20, damage))
{
_spawnedMechanic = true;
if (Creature* c = me->SummonCreature(34184, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), TEMPSUMMON_MANUAL_DESPAWN, 0))
c->AI()->AttackStart(me->GetVictim());
me->InterruptNonMeleeSpells(false);
me->CombatStop(true);
me->SetReactState(REACT_PASSIVE);
me->SetRegeneratingHealth(false);
me->SetFaction(FACTION_PREY);
me->SetNpcFlag(UNIT_NPC_FLAG_SPELLCLICK);
me->CastSpell(me, 64770, true);
}
}
void AttackStart(Unit* who) override
{
if (me->GetFaction() == FACTION_MONSTER_2)
ScriptedAI::AttackStart(who);
}
void EnterEvadeMode(EvadeReason why) override
{
if (me->GetFaction() == FACTION_MONSTER_2)
ScriptedAI::EnterEvadeMode(why);
}
void OnCharmed(bool /*apply*/) override {}
void UpdateAI(uint32 diff) override
{
if (me->GetFaction() != FACTION_MONSTER_2)
{
if (me->IsAlive() && (me->GetExactDist2dSq(2058.0f, 42.0f) < 25.0f * 25.0f || me->GetExactDist2dSq(2203.0f, 292.0f) < 25.0f * 25.0f || me->GetExactDist2dSq(2125.0f, 170.0f) > 160.0f * 160.0f))
Unit::Kill(me, me, false);
}
else
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{
case 0:
break;
case 1:
me->CastSpell(me->GetVictim(), SPELL_FLAME_SPRAY, false);
events.Repeat(15s, 25s);
break;
case 2:
me->CastSpell(me->GetVictim(), SPELL_MACHINE_GUN, false);
events.Repeat(10s, 15s);
break;
case 3:
{
float dist = me->GetDistance(me->GetVictim());
if (dist > 10.0f && dist < 40.0f)
{
me->CastSpell(me->GetVictim(), 64779, false);
events.Repeat(25s);
}
else
events.Repeat(3s);
}
break;
}
DoMeleeAttackIfReady();
}
}
};
};
class spell_ulduar_arachnopod_damaged_aura : public AuraScript
@@ -571,8 +549,8 @@ void AddSC_ulduar()
new npc_ulduar_keeper();
RegisterSpellScript(spell_ulduar_energy_sap_aura);
RegisterUlduarCreatureAI(npc_ulduar_snow_mound);
new npc_ulduar_storm_tempered_keeper();
new npc_ulduar_arachnopod_destroyer();
RegisterUlduarCreatureAI(npc_ulduar_storm_tempered_keeper);
RegisterUlduarCreatureAI(npc_ulduar_arachnopod_destroyer);
RegisterSpellScript(spell_ulduar_arachnopod_damaged_aura);
new AreaTrigger_at_celestial_planetarium_enterance();
RegisterCreatureAI(npc_salvaged_siege_engine);

View File

@@ -25,31 +25,38 @@
#define UlduarScriptName "instance_ulduar"
enum UlduarEncounters
enum UlduarBossIds
{
MAX_ENCOUNTER = 15,
TYPE_LEVIATHAN = 0,
TYPE_IGNIS = 1,
TYPE_RAZORSCALE = 2,
TYPE_XT002 = 3,
TYPE_ASSEMBLY = 4,
TYPE_KOLOGARN = 5,
TYPE_AURIAYA = 6,
TYPE_FREYA = 7,
TYPE_HODIR = 8,
TYPE_MIMIRON = 9,
TYPE_THORIM = 10,
TYPE_VEZAX = 11,
TYPE_YOGGSARON = 12,
TYPE_ALGALON = 13,
TYPE_WATCHERS = 14,
TYPE_HODIR_HM_FAIL = 15,
TYPE_WINTER_CACHE = 16
// Boss IDs used by SetBossNumber/SetBossState (0-indexed)
BOSS_LEVIATHAN = 0,
BOSS_IGNIS = 1,
BOSS_RAZORSCALE = 2,
BOSS_XT002 = 3,
BOSS_ASSEMBLY = 4,
BOSS_KOLOGARN = 5,
BOSS_AURIAYA = 6,
BOSS_FREYA = 7,
BOSS_HODIR = 8,
BOSS_MIMIRON = 9,
BOSS_THORIM = 10,
BOSS_VEZAX = 11,
BOSS_YOGGSARON = 12,
BOSS_ALGALON = 13,
MAX_ENCOUNTER = 14
};
enum UlduarData
{
// Non-boss encounter data
TYPE_WATCHERS = 14,
TYPE_HODIR_HM_FAIL = 15,
TYPE_WINTER_CACHE = 16,
// Assembly of Iron
DATA_STEELBREAKER = 20,
DATA_MOLGEIM = 21,
DATA_BRUNDIR = 22,
// Flame Leviathan
DATA_VEHICLE_SPAWN = 100,
DATA_LIGHTNING_WALL1 = 101,
@@ -57,6 +64,7 @@ enum UlduarData
DATA_REPAIR_STATION1 = 103,
DATA_REPAIR_STATION2 = 104,
DATA_UNBROKEN_ACHIEVEMENT = 105,
DATA_LEVIATHAN_DOORS = 106,
// Razorscales Harpoon Fire State GUIDs
DATA_HARPOON_FIRE_STATE_1 = 200,
@@ -64,16 +72,31 @@ enum UlduarData
DATA_HARPOON_FIRE_STATE_3 = 202,
DATA_HARPOON_FIRE_STATE_4 = 203,
// Mimiron's first vehicle (spawned by default)
// Mimiron creatures
DATA_MIMIRON_LEVIATHAN_MKII = 301,
DATA_MIMIRON_VX001 = 302,
DATA_MIMIRON_ACU = 303,
// Mimiron's Doors
// Mimiron doors
DATA_GO_MIMIRON_DOOR_1 = 311,
DATA_GO_MIMIRON_DOOR_2 = 312,
DATA_GO_MIMIRON_DOOR_3 = 313,
// Mimiron tram
DATA_MIMIRON_TRAM = 320,
DATA_MIMIRON_ACTIVATE_TRAM = 321,
DATA_MIMIRON_TRAM_ROCKET_BOOSTER = 322,
DATA_MIMIRON_CALL_TRAM_CENTER = 323,
DATA_MIMIRON_CALL_TRAM_MIMIRON = 324,
DATA_MIMIRON_TRAM_TURNAROUND_1 = 325,
DATA_MIMIRON_TRAM_TURNAROUND_2 = 326,
// XT-002
DATA_XT002_DOORS = 400,
// Kologarn
DATA_KOLOGARN_DOORS = 410,
// Thorim
DATA_THORIM_LEVER_GATE = 500,
DATA_THORIM_LEVER = 501,
@@ -81,15 +104,18 @@ enum UlduarData
DATA_THORIM_FIRST_DOORS = 503,
DATA_THORIM_SECOND_DOORS = 504,
// Assembly of Iron
DATA_STEELBREAKER = 20,
DATA_MOLGEIM = 21,
DATA_BRUNDIR = 22,
// Algalon the Observer
DATA_ALGALON_SUMMON_STATE = 600,
DATA_DESPAWN_ALGALON = 601,
DATA_ALGALON_DEFEATED = 602,
DATA_SIGILDOOR_01 = 603,
DATA_SIGILDOOR_02 = 604,
DATA_SIGILDOOR_03 = 605,
DATA_UNIVERSE_FLOOR_01 = 606,
DATA_UNIVERSE_FLOOR_02 = 607,
DATA_UNIVERSE_GLOBE = 608,
DATA_ALGALON_TRAPDOOR = 609,
DATA_BRANN_BRONZEBEARD_ALG = 610,
// Achievements
DATA_DWARFAGEDDON = 700,
@@ -97,10 +123,32 @@ enum UlduarData
// Tram
DATA_CALL_TRAM = 710,
// Freya elders
DATA_ELDER_IRONBRANCH = 750,
DATA_ELDER_STONEBARK = 751,
DATA_ELDER_BRIGHTLEAF = 752,
// Yogg-Saron
DATA_SARA = 760,
DATA_BRAIN_OF_YOGG_SARON = 761,
DATA_YOGG_SARON_DOORS = 762,
// Middle section
DATA_ASSEMBLY_DOORS = 770,
DATA_ARCHIVUM_DOORS = 771,
DATA_KEEPERS_GATE = 772,
// Hodir chests (dynamically spawned)
DATA_HODIR_CHEST_NORMAL = 780,
DATA_HODIR_CHEST_HARD = 781,
DATA_HODIR_CHEST_NORMAL_HERO = 782,
DATA_HODIR_CHEST_HARD_HERO = 783,
// Mage Barrier
DATA_MAGE_BARRIER = 800,
DATA_BRANN_MEMOTESAY = 801,
DATA_BRANN_EASY_MODE = 802,
DATA_BRANN_BASE_CAMP = 803,
};
enum UlduarNPCs