Merge branch 'master' into Playerbot

This commit is contained in:
Yunfan Li
2024-05-26 23:00:39 +08:00
78 changed files with 102236 additions and 327 deletions
@@ -16,11 +16,19 @@
*/
#include "boss_four_horsemen.h"
#include "CreatureScript.h"
#include "Player.h"
#include "ScriptedCreature.h"
#include "SpellAuraEffects.h"
#include "SpellScript.h"
#include "SpellScriptLoader.h"
#include "naxxramas.h"
using namespace FourHorsemen;
void AddSC_boss_four_horsemen()
{
new boss_four_horsemen();
new spell_four_horsemen_mark();
RegisterSpellScript(spell_four_horsemen_consumption);
}
@@ -17,13 +17,19 @@
#include "boss_maexxna.h"
#include "CreatureScript.h"
#include "Player.h"
#include "PassiveAI.h"
#include "ScriptedCreature.h"
#include "SpellAuraEffects.h"
#include "SpellScript.h"
#include "SpellScriptLoader.h"
#include "naxxramas.h"
using namespace Maexxna;
void AddSC_boss_maexxna()
{
new boss_maexxna();
new boss_maexxna_webwrap();
RegisterSpellScript(spell_web_wrap_damage);
}
@@ -1196,7 +1196,12 @@ public:
{
if (InstanceScript *instance = player->GetInstanceScript())
{
if (instance->CheckRequiredBosses(BOSS_SAPPHIRON))
bool AreAllWingsCleared = instance->GetBossState(BOSS_MAEXXNA) == DONE
&& (instance->GetBossState(BOSS_LOATHEB) == DONE)
&& (instance->GetBossState(BOSS_THADDIUS) == DONE)
&& (instance->GetBossState(BOSS_HORSEMAN) == DONE);
if (AreAllWingsCleared)
{
player->TeleportTo(533, sapphironEntryTP.m_positionX, sapphironEntryTP.m_positionY, sapphironEntryTP.m_positionZ, sapphironEntryTP.m_orientation);
return true;
@@ -46,7 +46,6 @@ enum Spells
SPELL_COSMIC_SMASH_VISUAL_STATE = 62300,
SPELL_SELF_STUN = 65256,
SPELL_KILL_CREDIT = 65184,
SPELL_TELEPORT = 62940,
SPELL_DUAL_WIELD = 42459,
// Algalon Stalker
@@ -347,7 +347,6 @@ public:
uint32 chestId = RAID_MODE(GO_FREYA_CHEST, GO_FREYA_CHEST_HERO);
chestId -= 2 * _elderCount; // offset
me->DespawnOrUnsummon(5000);
if (GameObject* go = me->SummonGameObject(chestId, 2345.61f, -71.20f, 425.104f, 3.0f, 0, 0, 0, 0, 0))
{
go->ReplaceAllGameObjectFlags((GameObjectFlags)0);
@@ -360,10 +359,24 @@ public:
me->CastSpell(me, 65074, true); // credit
m_pInstance->SetData(TYPE_FREYA, DONE);
}
scheduler.Schedule(14s, [this](TaskContext /*context*/)
{
DoCastSelf(SPELL_TELEPORT);
});
}
}
}
void SpellHit(Unit* /*caster*/, SpellInfo const* spellInfo) override
{
if (spellInfo->Id == SPELL_TELEPORT)
{
me->DespawnOrUnsummon();
m_pInstance->SetData(EVENT_KEEPER_TELEPORTED, DONE);
}
}
void JustSummoned(Creature* cr) override
{
if (cr->GetEntry() == NPC_FREYA_UNSTABLE_SUN_BEAM)
@@ -547,6 +560,7 @@ public:
void UpdateAI(uint32 diff) override
{
scheduler.Update(diff);
if (!UpdateVictim())
return;
@@ -346,6 +346,7 @@ public:
{
pInstance->SetData(TYPE_HODIR, DONE);
me->CastSpell(me, 64899, true); // credit
pInstance->DoRemoveAurasDueToSpellOnPlayers(SPELL_BITING_COLD_PLAYER_AURA);
}
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
@@ -355,7 +356,6 @@ public:
me->CombatStop();
me->InterruptNonMeleeSpells(true);
me->RemoveAllAuras();
pInstance->DoRemoveAurasDueToSpellOnPlayers(SPELL_BITING_COLD_PLAYER_AURA);
events.Reset();
summons.DespawnAll();
@@ -383,13 +383,17 @@ public:
}
Talk(TEXT_DEATH);
me->DespawnOrUnsummon(10000);
scheduler.Schedule(14s, [this](TaskContext /*context*/)
{
DoCastSelf(SPELL_TELEPORT);
});
}
}
}
void UpdateAI(uint32 diff) override
{
scheduler.Update(diff);
if (me->GetPositionY() <= ENTRANCE_DOOR.GetPositionY() || me->GetPositionY() >= EXIT_DOOR.GetPositionY())
{
boss_hodirAI::EnterEvadeMode();
@@ -497,6 +501,15 @@ public:
DoMeleeAttackIfReady();
}
void SpellHit(Unit* /*caster*/, SpellInfo const* spellInfo) override
{
if (spellInfo->Id == SPELL_TELEPORT)
{
me->DespawnOrUnsummon();
pInstance->SetData(EVENT_KEEPER_TELEPORTED, DONE);
}
}
Creature* GetHelper(uint8 index)
{
return Helpers[index] ? ObjectAccessor::GetCreature(*me, Helpers[index]) : nullptr;
@@ -237,7 +237,6 @@ public:
_looksAchievement = true;
me->SetDisableGravity(true);
me->SetUnitFlag(UNIT_FLAG_DISABLE_MOVE);
me->DisableRotate(true);
events.Reset();
@@ -327,6 +326,8 @@ public:
arm->DespawnOrUnsummon(3000); // visual
if (Creature* arm = ObjectAccessor::GetCreature(*me, _right))
arm->DespawnOrUnsummon(3000); // visual
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
me->SetDisableGravity(true);
}
void KilledUnit(Unit*) override
@@ -802,12 +802,21 @@ public:
case EVENT_DISAPPEAR:
if( pInstance )
pInstance->SetData(TYPE_MIMIRON, DONE);
DoCastSelf(SPELL_TELEPORT);
summons.DespawnAll();
me->DespawnOrUnsummon();
break;
}
}
void SpellHit(Unit* /*caster*/, SpellInfo const* spellInfo) override
{
if (spellInfo->Id == SPELL_TELEPORT)
{
me->DespawnOrUnsummon();
pInstance->SetData(EVENT_KEEPER_TELEPORTED, DONE);
}
}
void MoveInLineOfSight(Unit* /*mover*/) override {}
void EnterEvadeMode(EvadeReason why) override
@@ -197,6 +197,7 @@ enum ThorimEvents
EVENT_THORIM_OUTRO1 = 13,
EVENT_THORIM_OUTRO2 = 14,
EVENT_THORIM_OUTRO3 = 15,
EVENT_THORIM_OUTRO4 = 16,
EVENT_DR_ACOLYTE_GH = 20,
EVENT_DR_ACOLYTE_HS = 21,
@@ -630,6 +631,11 @@ public:
me->CastSpell(me, SPELL_LIGHTNING_CHARGE_BUFF, true);
events.RescheduleEvent(EVENT_THORIM_LIGHTNING_CHARGE, 10s, 0, EVENT_PHASE_RING);
}
else if (spellInfo->Id == SPELL_TELEPORT)
{
me->DespawnOrUnsummon();
m_pInstance->SetData(EVENT_KEEPER_TELEPORTED, DONE);
}
}
void SpellHitTarget(Unit* target, SpellInfo const* spellInfo) override
@@ -773,12 +779,13 @@ public:
{
Talk(SAY_END_NORMAL_3);
}
// Defeat credit
if (m_pInstance)
m_pInstance->SetData(TYPE_THORIM, DONE);
me->DespawnOrUnsummon(8000);
events.ScheduleEvent(EVENT_THORIM_OUTRO4, 14s, 0, 3);
break;
case EVENT_THORIM_OUTRO4:
DoCastSelf(SPELL_TELEPORT);
break;
}
@@ -251,6 +251,8 @@ enum Misc
ACTION_ILLUSION_ICECROWN = 2,
ACTION_ILLUSION_STORMWIND = 3,
// ACTION_SARA_UPDATE_SUMMON_KEEPERS = 4, // defined in ulduar.h
EVENT_PHASE_ONE = 1,
EVENT_PHASE_TWO = 2,
EVENT_PHASE_THREE = 3,
@@ -271,6 +273,26 @@ struct LocationsXY
float x, y, z;
};
Position const GossipKeepersPos[4] =
{
{1945.6823f, 33.342014f, 411.44083f, 5.270895f}, // Freya
{1945.7609f, -81.52171f, 411.4407f, 1.029744f}, // Hodir
{2028.7656f, 17.42014f, 411.44458f, 3.857178f}, // Mimiron
{2028.8219f, -65.73573f, 411.44257f, 2.460914f} // Thorim
};
const Position KeepersPos[4] =
{
{1939.32f, 42.165f, 338.415f, 5.17955f}, // Freya
{1939.13f, -90.8332f, 338.415f, 1.00123f}, // Hodir
{2036.81f, 25.6646f, 338.415f, 3.74227f}, // Mimiron
{2036.59f, -73.8499f, 338.415f, 2.34819f} // Thorim
};
const uint32 TABLE_KEEPER_ENTRY[4] = {NPC_FREYA_KEEPER, NPC_HODIR_KEEPER, NPC_MIMIRON_KEEPER, NPC_THORIM_KEEPER};
const uint32 TABLE_GOSSIP_ENTRY[4] = {NPC_FREYA_GOSSIP, NPC_HODIR_GOSSIP, NPC_MIMIRON_GOSSIP, NPC_THORIM_GOSSIP};
const uint32 TABLE_KEEPER_TYPE[4] = {TYPE_FREYA, TYPE_HODIR, TYPE_MIMIRON, TYPE_THORIM};
static LocationsXY yoggPortalLoc[] =
{
{1970.48f, -9.75f, 325.5f},
@@ -344,7 +366,6 @@ enum Texts
SAY_LK_2 = 1,
SAY_YOGG_5 = 3,
SAY_YOGG_6 = 4,
};
const Position Middle = {1980.28f, -25.5868f, 329.397f, M_PI * 1.5f};
@@ -371,7 +392,6 @@ public:
SummonList summons;
uint32 _initFight;
ObjectGuid _keepersGUID[4];
uint8 _summonedGuardiansCount;
uint32 _p2TalkTimer;
bool _secondPhase;
@@ -382,17 +402,9 @@ public:
void AttackStart(Unit*) override { }
void MoveInLineOfSight(Unit*) override { }
void JustSummoned(Creature* cr) override
void JustSummoned(Creature* summon) override
{
summons.Summon(cr);
if (cr->GetEntry() >= NPC_FREYA_KEEPER && cr->GetEntry() <= NPC_THORIM_KEEPER)
{
if (cr->GetEntry() == NPC_FREYA_KEEPER)
cr->CastSpell(cr, SPELL_CONJURE_SANITY_WELL, false);
_keepersGUID[cr->GetEntry() - NPC_FREYA_KEEPER] = cr->GetGUID();
}
else if (cr->GetEntry() == NPC_SANITY_WELL)
cr->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_SCALE, true);
summons.Summon(summon);
}
void SpawnClouds()
@@ -407,15 +419,6 @@ public:
}
}
void SpawnWeels()
{
me->SummonCreature(NPC_SANITY_WELL, 2042.56f, -40.3667f, 329.274f, 0.0f);
me->SummonCreature(NPC_SANITY_WELL, 1975.89f, 40.0216f, 331.1f, 0.0f);
me->SummonCreature(NPC_SANITY_WELL, 1987.12f, -91.2702f, 330.186f, 0.0f);
me->SummonCreature(NPC_SANITY_WELL, 1900.48f, -51.2386f, 332.13f, 0.0f);
me->SummonCreature(NPC_SANITY_WELL, 1899.94f, 0.330621f, 332.296f, 0.0f);
}
void EnterEvadeMode(EvadeReason why) override
{
if (!_EnterEvadeMode(why))
@@ -469,9 +472,7 @@ public:
_initFight = 1;
for (uint8 i = 0; i < 4; ++i)
_keepersGUID[i].Clear();
UpdateKeeperSpawns();
_summonedGuardiansCount = 0;
_p2TalkTimer = 0;
_secondPhase = false;
@@ -503,9 +504,11 @@ public:
me->SetInCombatWithZone();
AttackStart(target);
me->CastSpell(me, SPELL_SANITY_BASE, true);
DespawnGossipKeepers();
// Engage Keepers
summons.DoZoneInCombat();
SaveKeepers();
me->CastSpell(me, SPELL_SANITY_BASE, true);
events.ScheduleEvent(EVENT_SARA_P1_DOORS_CLOSE, 15s, 0, EVENT_PHASE_ONE);
events.ScheduleEvent(EVENT_SARA_P1_BERSERK, 15min, 0, 0);
@@ -516,26 +519,27 @@ public:
me->setActive(true);
}
void SaveKeepers()
void DespawnGossipKeepers()
{
for (uint8 i = 0; i < 4; ++i)
for (uint8 i = KEEPER_FREYA; i <= KEEPER_THORIM; i++)
summons.DespawnEntry(TABLE_GOSSIP_ENTRY[i]);
}
void UpdateKeeperSpawns()
{
for (uint8 i = KEEPER_FREYA; i <= KEEPER_THORIM; i++)
{
if (m_pInstance->GetData(TYPE_WATCHERS) & (1 << i))
switch (i)
{
case KEEPER_FREYA:
SpawnWeels();
me->SummonCreature(NPC_FREYA_KEEPER, 1939.32f, 42.165f, 338.415f, 5.17955f);
break;
case KEEPER_HODIR:
me->SummonCreature(NPC_HODIR_KEEPER, 1939.13f, -90.8332f, 338.415f, 1.00123f);
break;
case KEEPER_MIMIRON:
me->SummonCreature(NPC_MIMIRON_KEEPER, 2036.81f, 25.6646f, 338.415f, 3.74227f);
break;
case KEEPER_THORIM:
me->SummonCreature(NPC_THORIM_KEEPER, 2036.59f, -73.8499f, 338.415f, 2.34819f);
break;
}
{
if (!summons.HasEntry(TABLE_KEEPER_ENTRY[i]))
me->SummonCreature(TABLE_KEEPER_ENTRY[i], KeepersPos[i]);
}
else if (m_pInstance->GetData(TABLE_KEEPER_TYPE[i]) == DONE)
{
if (!summons.HasEntry(TABLE_GOSSIP_ENTRY[i]))
me->SummonCreature(TABLE_GOSSIP_ENTRY[i], GossipKeepersPos[i]);
}
}
}
void InformCloud()
@@ -625,9 +629,8 @@ public:
{
uint8 _count = 0;
for (uint8 i = 0; i < 4; ++i)
if (_keepersGUID[i])
if (m_pInstance->GetData(TYPE_WATCHERS) & (1 << i))
++_count;
return _count;
}
else if (param == DATA_GET_SARA_PHASE)
@@ -638,7 +641,11 @@ public:
void DoAction(int32 param) override
{
if (param == ACTION_BRAIN_DAMAGED)
if (param == ACTION_SARA_UPDATE_SUMMON_KEEPERS)
{
UpdateKeeperSpawns();
}
else if (param == ACTION_BRAIN_DAMAGED)
{
summons.DoAction(ACTION_REMOVE_STUN);
@@ -648,7 +655,7 @@ public:
EntryCheckPredicate pred3(NPC_THORIM_KEEPER);
summons.DoAction(ACTION_THORIM_START_STORM, pred3);
if (!(_keepersGUID[0] && _keepersGUID[1] && _keepersGUID[2] && _keepersGUID[3]) && me->GetMap()->Is25ManRaid())
if (me->GetMap()->Is25ManRaid() && (GetData(DATA_GET_KEEPERS_COUNT) > 0))
summons.DoAction(ACTION_YOGG_SARON_HARD_MODE, pred2);
summons.DespawnEntry(NPC_DEATH_ORB);
@@ -660,8 +667,17 @@ public:
}
else if (param == ACTION_YOGG_SARON_DEATH)
{
// Despawn everything but Yogg-Saron's corpse
summons.DoAction(ACTION_DESPAWN_ADDS);
summons.DespawnEntry(NPC_CRUSHER_TENTACLE);
summons.DespawnEntry(NPC_CONSTRICTOR_TENTACLE);
summons.DespawnEntry(NPC_CORRUPTOR_TENTACLE);
summons.DespawnEntry(NPC_VOICE_OF_YOGG_SARON);
summons.DespawnEntry(NPC_BRAIN_OF_YOGG_SARON);
summons.DespawnEntry(NPC_MIMIRON_GOSSIP);
summons.DespawnEntry(NPC_HODIR_GOSSIP);
summons.DespawnEntry(NPC_FREYA_GOSSIP);
summons.DespawnEntry(NPC_THORIM_GOSSIP);
summons.DespawnEntry(NPC_MIMIRON_KEEPER);
summons.DespawnEntry(NPC_HODIR_KEEPER);
summons.DespawnEntry(NPC_FREYA_KEEPER);
@@ -1709,52 +1725,56 @@ public:
};
};
class boss_yoggsaron_keeper : public CreatureScript
struct boss_yoggsaron_keeper : public NullCreatureAI
{
public:
boss_yoggsaron_keeper() : CreatureScript("boss_yoggsaron_keeper") { }
boss_yoggsaron_keeper(Creature* creature) : NullCreatureAI(creature), _summons(creature) { }
CreatureAI* GetAI(Creature* pCreature) const override
void DoAction(int32 param) override
{
return GetUlduarAI<boss_yoggsaron_keeperAI>(pCreature);
if (me->GetEntry() == NPC_THORIM_KEEPER && param == ACTION_THORIM_START_STORM)
me->CastSpell(me, SPELL_TITANIC_STORM_PASSIVE, false);
else if (param == ACTION_DESPAWN_ADDS)
_summons.DespawnAll();
}
struct boss_yoggsaron_keeperAI : public NullCreatureAI
void JustSummoned(Creature* summon) override
{
boss_yoggsaron_keeperAI(Creature* pCreature) : NullCreatureAI(pCreature)
_summons.Summon(summon);
}
void JustEngagedWith(Unit* /*who*/) override
{
switch (me->GetEntry())
{
_checkTimer = 0;
me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_SCALE, true);
}
uint32 _checkTimer;
void DoAction(int32 param) override
{
if (me->GetEntry() == NPC_THORIM_KEEPER && param == ACTION_THORIM_START_STORM)
me->CastSpell(me, SPELL_TITANIC_STORM_PASSIVE, false);
}
void UpdateAI(uint32 diff) override
{
if (me->GetInstanceScript())
if (me->GetInstanceScript()->GetData(TYPE_YOGGSARON) != IN_PROGRESS)
return;
_checkTimer += diff;
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
if (me->GetEntry() == NPC_MIMIRON_KEEPER)
{
if (_checkTimer >= 2000)
case NPC_FREYA_KEEPER:
me->AddAura(SPELL_FREYA_PASSIVE, me);
me->CastSpell(me, SPELL_CONJURE_SANITY_WELL, false);
break;
case NPC_HODIR_KEEPER:
me->AddAura(SPELL_HODIR_PASSIVE, me);
me->AddAura(SPELL_PROTECTIVE_GAZE, me);
break;
case NPC_MIMIRON_KEEPER:
me->AddAura(SPELL_MIMIRON_PASSIVE, me);
scheduler.Schedule(2s, [this](TaskContext context)
{
me->CastSpell(me, SPELL_DESTABILIZATION_MATRIX, false);
_checkTimer = 0;
}
}
if (!me->HasUnitState(UNIT_STATE_CASTING))
me->CastSpell(me, SPELL_DESTABILIZATION_MATRIX, false);
context.Repeat(2s);
});
break;
case NPC_THORIM_KEEPER:
me->AddAura(SPELL_THORIM_PASSIVE, me);
break;
}
};
}
void UpdateAI(uint32 diff) override
{
scheduler.Update(diff);
}
private:
SummonList _summons;
};
class boss_yoggsaron_descend_portal : public CreatureScript
@@ -2739,6 +2759,33 @@ public:
}
};
const Position SanityWellsPos[5] =
{
{2042.56f, -40.3667f, 329.274f, 0.0f},
{1975.89f, 40.0216f, 331.1f, 0.0f},
{1987.12f, -91.2702f, 330.186f, 0.0f},
{1900.48f, -51.2386f, 332.13f, 0.0f},
{1899.94f, 0.330621f, 332.296f, 0.0f}
};
// 64170 - Sanity Well
class spell_keeper_freya_summon_sanity_well : public SpellScript
{
PrepareSpellScript(spell_keeper_freya_summon_sanity_well);
void OnEffect(SpellEffIndex /*effIndex*/)
{
if (Unit* caster = GetCaster())
for (int i = 0; i < 5; i++)
caster->SummonCreature(NPC_SANITY_WELL, SanityWellsPos[i]);
}
void Register() override
{
OnEffectLaunch += SpellEffectFn(spell_keeper_freya_summon_sanity_well::OnEffect, EFFECT_0, SPELL_EFFECT_SEND_EVENT);
}
};
/* 63881 - Malady of the Mind
63795 - Psychosis
63830 - Malady of the Mind
@@ -3032,7 +3079,7 @@ void AddSC_boss_yoggsaron()
new boss_yoggsaron_crusher_tentacle();
new boss_yoggsaron_corruptor_tentacle();
new boss_yoggsaron_constrictor_tentacle();
new boss_yoggsaron_keeper();
RegisterUlduarCreatureAI(boss_yoggsaron_keeper);
new boss_yoggsaron_descend_portal();
new boss_yoggsaron_influence_tentacle();
new boss_yoggsaron_immortal_guardian();
@@ -3053,6 +3100,7 @@ void AddSC_boss_yoggsaron()
new spell_yogg_saron_insane_periodic_trigger();
new spell_yogg_saron_insane();
new spell_yogg_saron_sanity_well();
RegisterSpellScript(spell_keeper_freya_summon_sanity_well);
new spell_yogg_saron_sanity_reduce();
new spell_yogg_saron_empowering_shadows();
new spell_yogg_saron_in_the_maws_of_the_old_god();
@@ -370,22 +370,6 @@ public:
case NPC_MIMIRON_ACU:
m_MimironACUguid = creature->GetGUID();
break;
case NPC_FREYA_GOSSIP:
m_keepersGossipGUID[TYPE_FREYA - TYPE_FREYA] = creature->GetGUID();
ShowKeeperGossip(TYPE_FREYA, creature);
break;
case NPC_HODIR_GOSSIP:
m_keepersGossipGUID[TYPE_HODIR - TYPE_FREYA] = creature->GetGUID();
ShowKeeperGossip(TYPE_HODIR, creature);
break;
case NPC_THORIM_GOSSIP:
m_keepersGossipGUID[TYPE_THORIM - TYPE_FREYA] = creature->GetGUID();
ShowKeeperGossip(TYPE_THORIM, creature);
break;
case NPC_MIMIRON_GOSSIP:
m_keepersGossipGUID[TYPE_MIMIRON - TYPE_FREYA] = creature->GetGUID();
ShowKeeperGossip(TYPE_MIMIRON, creature);
break;
case NPC_ELDER_IRONBRANCH:
case NPC_ELDER_STONEBARK:
case NPC_ELDER_BRIGHTLEAF:
@@ -433,19 +417,6 @@ public:
go->SetGoState(state);
}
void ShowKeeperGossip(uint8 type, Creature* cr, ObjectGuid guid = ObjectGuid::Empty)
{
if (!cr)
{
cr = instance->GetCreature(guid);
if (!cr)
return;
}
bool on = (GetData(type) == DONE && !(GetData(TYPE_WATCHERS) & (1 << (type - TYPE_FREYA))));
cr->SetVisible(on);
}
void OnGameObjectCreate(GameObject* gameObject) override
{
switch (gameObject->GetEntry())
@@ -695,7 +666,6 @@ public:
case TYPE_THORIM:
case TYPE_FREYA:
m_auiEncounter[type] = data;
ShowKeeperGossip(type, nullptr, m_keepersGossipGUID[type - TYPE_FREYA]);
if (GetData(TYPE_MIMIRON) == DONE && GetData(TYPE_FREYA) == DONE && GetData(TYPE_HODIR) == DONE && GetData(TYPE_THORIM) == DONE)
{
if (GameObject* go = instance->GetGameObject(m_keepersgateGUID))
@@ -716,8 +686,11 @@ public:
break;
case TYPE_WATCHERS:
m_auiEncounter[type] |= 1 << data;
[[fallthrough]];
case EVENT_KEEPER_TELEPORTED:
if (Creature* sara = instance->GetCreature(m_saraGUID))
sara->AI()->DoAction(ACTION_SARA_UPDATE_SUMMON_KEEPERS);
break;
case DATA_MAGE_BARRIER:
m_mageBarrier = data;
break;
@@ -728,6 +701,7 @@ public:
case EVENT_TOWER_OF_FLAMES_DESTROYED:
{
instance->LoadGrid(364.0f, -16.0f); //make sure leviathan is loaded
instance->LoadGrid(364.0f, 32.0f); //make sure Mimiron's and Thorim's Targetting Crystal are loaded
m_leviathanTowers[type - EVENT_TOWER_OF_LIFE_DESTROYED] = data;
for (uint8 i = 0; i < 2; ++i)
{
@@ -21,6 +21,7 @@
#include "GameObjectScript.h"
#include "Player.h"
#include "ScriptedCreature.h"
#include "PassiveAI.h"
#include "ScriptedGossip.h"
#include "SpellAuraEffects.h"
#include "SpellScript.h"
@@ -51,7 +52,14 @@ enum Texts
GOSSIP_MENU_CONFIRM = 10333,
NPC_TEXT_CONFIRM = 14325,
SAY_KEEPER_SELECTED = 1,
// Chosen
SAY_KEEPER_CHOSEN_TO_PLAYER = 0,
SAY_KEEPER_CHOSEN_ANNOUNCE = 1,
};
enum UldActions
{
ACTION_KEEPER_OUTRO = 0,
};
enum UldNPCs
@@ -69,6 +77,8 @@ enum UldGameObjects
enum UldSpells
{
SPELL_SIMPLE_TELEPORT = 12980,
SPELL_KEEPER_TELEPORT = 62940,
SPELL_SNOW_MOUND_PARTICLES = 64615
};
@@ -77,6 +87,68 @@ class npc_ulduar_keeper : public CreatureScript
public:
npc_ulduar_keeper() : CreatureScript("npc_ulduar_keeper_gossip") { }
struct npc_ulduar_keeperAI : public NullCreatureAI
{
npc_ulduar_keeperAI(Creature* creature) : NullCreatureAI(creature) { }
void Reset() override
{
scheduler.Schedule(250ms, [this](TaskContext /*context*/)
{
DoCastSelf(SPELL_SIMPLE_TELEPORT);
});
}
void DoAction(int32 param) override
{
if (param == ACTION_KEEPER_OUTRO)
{
switch (me->GetEntry())
{
case NPC_FREYA_GOSSIP:
_keeper = KEEPER_FREYA;
break;
case NPC_HODIR_GOSSIP:
_keeper = KEEPER_HODIR;
break;
case NPC_MIMIRON_GOSSIP:
_keeper = KEEPER_MIMIRON;
break;
case NPC_THORIM_GOSSIP:
_keeper = KEEPER_THORIM;
break;
default:
return;
}
scheduler.Schedule(1s, [this](TaskContext /*context*/)
{
DoCastSelf(SPELL_KEEPER_TELEPORT);
});
}
}
void SpellHit(Unit* /*caster*/, SpellInfo const* spellInfo) override
{
if (spellInfo->Id == SPELL_TELEPORT)
{
me->DespawnOrUnsummon();
me->GetInstanceScript()->SetData(TYPE_WATCHERS, _keeper);
}
}
void UpdateAI(uint32 diff) override
{
scheduler.Update(diff);
}
private:
uint8 _keeper;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetUlduarAI<npc_ulduar_keeperAI>(creature);
}
bool OnGossipHello(Player* player, Creature* creature) override
{
uint32 gossipMenuId = 0;
@@ -109,7 +181,6 @@ public:
bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override
{
ClearGossipMenuFor(player);
uint8 _keeper = 0;
switch (action)
{
case GOSSIP_ACTION_INFO_DEF+1:
@@ -118,34 +189,12 @@ public:
break;
case GOSSIP_ACTION_INFO_DEF+2:
{
switch (creature->GetEntry())
{
case NPC_FREYA_GOSSIP:
creature->AI()->Talk(SAY_KEEPER_SELECTED);
_keeper = KEEPER_FREYA;
break;
case NPC_HODIR_GOSSIP:
creature->AI()->Talk(SAY_KEEPER_SELECTED);
_keeper = KEEPER_HODIR;
break;
case NPC_MIMIRON_GOSSIP:
creature->AI()->Talk(SAY_KEEPER_SELECTED);
_keeper = KEEPER_MIMIRON;
break;
case NPC_THORIM_GOSSIP:
creature->AI()->Talk(SAY_KEEPER_SELECTED);
_keeper = KEEPER_THORIM;
break;
}
creature->ReplaceAllNpcFlags(UNIT_NPC_FLAG_NONE);
creature->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
CloseGossipMenuFor(player);
if (creature->GetInstanceScript())
{
creature->GetInstanceScript()->SetData(TYPE_WATCHERS, _keeper);
creature->DespawnOrUnsummon(6000);
}
creature->AI()->Talk(SAY_KEEPER_CHOSEN_TO_PLAYER, player);
creature->AI()->Talk(SAY_KEEPER_CHOSEN_ANNOUNCE);
creature->AI()->DoAction(ACTION_KEEPER_OUTRO);
}
}
return true;
@@ -284,6 +284,14 @@ enum UlduarMisc
TIMER_ALGALON_TO_SUMMON = 200,
TIMER_ALGALON_SUMMONED = 100,
// Algalon the Observer, Freya, Hodir, Mimiron, Thorim, Gossip Keepers
SPELL_TELEPORT = 62940,
// Freya, Hodir, Mimiron, Thorim
EVENT_KEEPER_TELEPORTED = 62941,
// Yogg-Saron
ACTION_SARA_UPDATE_SUMMON_KEEPERS = 4,
KEEPER_FREYA = 0,
KEEPER_HODIR = 1,
KEEPER_MIMIRON = 2,
@@ -1287,19 +1287,21 @@ public:
if (!summoner)
return;
if (summoner->GetTypeId() != TYPEID_UNIT)
{
if (summoner->GetTypeId() != TYPEID_PLAYER)
return;
}
summoner->ToUnit()->CastSpell(summoner->ToUnit(), SPELL_WAITING_FOR_A_BOMBER, true);
summoner->ToUnit()->CastSpell(summoner->ToUnit(), SPELL_FLIGHT_ORDERS, true);
Player* player = summoner->ToPlayer();
if (!player)
return;
player->CastSpell(player, SPELL_WAITING_FOR_A_BOMBER, true);
player->CastSpell(player, SPELL_FLIGHT_ORDERS, true);
events.ScheduleEvent(EVENT_START_FLIGHT, 0);
events.ScheduleEvent(EVENT_TAKE_PASSENGER, 3000);
me->SetCanFly(true);
me->AddUnitMovementFlag(MOVEMENTFLAG_FLYING);
me->SetSpeed(MOVE_FLIGHT, 0.1f);
me->SetFaction(summoner->ToUnit()->GetFaction());
me->SetFaction(player->GetFaction());
}
void DamageTaken(Unit* who, uint32&, DamageEffectType, SpellSchoolMask) override