mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-25 22:56:24 +00:00
Merge branch 'azerothcore:master' into Playerbot
This commit is contained in:
@@ -51,7 +51,8 @@ enum DataTypes
|
||||
DATA_HALL_RUNE_6 = 21,
|
||||
DATA_HALL_RUNE_7 = 22,
|
||||
DATA_SOLAKAR_FLAMEWREATH = 23,
|
||||
DATA_MOR_GRAYHOOF = 24
|
||||
DATA_MOR_GRAYHOOF = 24,
|
||||
DATA_VAELASTRASZ = 25
|
||||
};
|
||||
|
||||
enum CreaturesIds
|
||||
@@ -75,6 +76,8 @@ enum CreaturesIds
|
||||
NPC_BLACKHAND_VETERAN = 9819,
|
||||
NPC_BLACKHAND_INCARCERATOR = 10316,
|
||||
NPC_LORD_VICTOR_NEFARIUS = 10162,
|
||||
NPC_VAELASTRASZ_THE_RED = 10340,
|
||||
NPC_VAELASTRASZ_UBRS = 10538,
|
||||
|
||||
NPC_SCARSHIELD_INFILTRATOR = 10299,
|
||||
|
||||
|
||||
@@ -18,15 +18,19 @@
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "blackrock_spire.h"
|
||||
#include "SpellScript.h"
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_REND_MOUNTS = 16167, // Change model
|
||||
SPELL_CORROSIVE_ACID = 16359, // Combat (self cast)
|
||||
SPELL_FLAMEBREATH = 16390, // Combat (Self cast)
|
||||
SPELL_FREEZE = 16350, // Combat (Self cast)
|
||||
SPELL_KNOCK_AWAY = 10101, // Combat
|
||||
SPELL_SUMMON_REND = 16328 // Summons Rend near death
|
||||
SPELL_REND_MOUNTS = 16167, // Change model
|
||||
SPELL_CORROSIVE_ACID = 16359, // Combat (self cast)
|
||||
SPELL_FLAMEBREATH = 16390, // Combat (Self cast)
|
||||
SPELL_FREEZE = 16350, // Combat (Self cast)
|
||||
SPELL_KNOCK_AWAY = 10101, // Combat
|
||||
SPELL_SUMMON_REND = 16328, // Summons Rend near death
|
||||
SPELL_CHROMATIC_PROTECTION_FIRE = 16373,
|
||||
SPELL_CHROMATIC_PROTECTION_FROST = 16392,
|
||||
SPELL_CHROMATIC_PROTECTION_NATURE = 16391,
|
||||
};
|
||||
|
||||
enum Misc
|
||||
@@ -179,7 +183,64 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
// 16372 - Chromatic Protection
|
||||
class spell_gyth_chromatic_protection : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_gyth_chromatic_protection);
|
||||
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_CORROSIVE_ACID, SPELL_FLAMEBREATH, SPELL_FREEZE });
|
||||
}
|
||||
|
||||
bool CheckProc(ProcEventInfo& eventInfo)
|
||||
{
|
||||
if (SpellInfo const* spellInfo = eventInfo.GetSpellInfo())
|
||||
{
|
||||
switch (spellInfo->Id)
|
||||
{
|
||||
case SPELL_CORROSIVE_ACID:
|
||||
case SPELL_FLAMEBREATH:
|
||||
case SPELL_FREEZE:
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void HandleProc(AuraEffect const* /* aurEff */, ProcEventInfo& eventInfo)
|
||||
{
|
||||
PreventDefaultAction();
|
||||
if (SpellInfo const* spellInfo = eventInfo.GetSpellInfo())
|
||||
{
|
||||
switch (spellInfo->Id)
|
||||
{
|
||||
case SPELL_CORROSIVE_ACID:
|
||||
GetTarget()->CastSpell(GetTarget(), SPELL_CHROMATIC_PROTECTION_NATURE, true);
|
||||
break;
|
||||
case SPELL_FLAMEBREATH:
|
||||
GetTarget()->CastSpell(GetTarget(), SPELL_CHROMATIC_PROTECTION_FIRE, true);
|
||||
break;
|
||||
case SPELL_FREEZE:
|
||||
GetTarget()->CastSpell(GetTarget(), SPELL_CHROMATIC_PROTECTION_FROST, true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectProc += AuraEffectProcFn(spell_gyth_chromatic_protection::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_gyth()
|
||||
{
|
||||
new boss_gyth();
|
||||
RegisterSpellScript(spell_gyth_chromatic_protection);
|
||||
}
|
||||
|
||||
@@ -253,6 +253,7 @@ public:
|
||||
{
|
||||
case EVENT_START_1:
|
||||
instance->SetBossState(DATA_WARCHIEF_REND_BLACKHAND, IN_PROGRESS);
|
||||
instance->SetData(DATA_VAELASTRASZ, NOT_STARTED);
|
||||
|
||||
if (Creature* victor = ObjectAccessor::GetCreature(*me, victorGUID))
|
||||
victor->AI()->Talk(SAY_NEFARIUS_0);
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "ObjectMgr.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellScript.h"
|
||||
#include "blackrock_spire.h"
|
||||
|
||||
uint32 const DragonspireMobs[3] = { NPC_BLACKHAND_DREADWEAVER, NPC_BLACKHAND_SUMMONER, NPC_BLACKHAND_VETERAN };
|
||||
@@ -80,6 +81,7 @@ public:
|
||||
uint32 CurrentSolakarWave = 0;
|
||||
uint32 SolakarState = NOT_STARTED; // there should be a global instance encounter state, where is it?
|
||||
GuidVector SolakarSummons;
|
||||
uint32 VaelastraszState = NOT_STARTED;
|
||||
|
||||
instance_blackrock_spireMapScript(InstanceMap* map) : InstanceScript(map)
|
||||
{
|
||||
@@ -89,6 +91,7 @@ public:
|
||||
CurrentSolakarWave = 0;
|
||||
SolakarState = NOT_STARTED;
|
||||
SolakarSummons.clear();
|
||||
VaelastraszState = NOT_STARTED;
|
||||
}
|
||||
|
||||
void CreatureLooted(Creature* creature, LootType loot) override
|
||||
@@ -377,6 +380,9 @@ public:
|
||||
}
|
||||
SolakarState = data;
|
||||
break;
|
||||
case DATA_VAELASTRASZ:
|
||||
VaelastraszState = data;
|
||||
break;
|
||||
case DATA_UROK_DOOMHOWL:
|
||||
if (data == FAIL)
|
||||
{
|
||||
@@ -420,6 +426,10 @@ public:
|
||||
{
|
||||
return SolakarState;
|
||||
}
|
||||
else if (type == DATA_VAELASTRASZ)
|
||||
{
|
||||
return VaelastraszState;
|
||||
}
|
||||
else
|
||||
{
|
||||
return InstanceScript::GetData(type);
|
||||
@@ -877,6 +887,247 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/*#####
|
||||
# npc_vaelastrasz_the_red and Seal of Ascension event
|
||||
#####*/
|
||||
|
||||
// Set fixed spawn points so there's enough room for the dragon model
|
||||
Position VaelastraszTheRedPosNorth = Position(168.815506f, -420.311066f, 110.472298f, 3.141593f);
|
||||
Position VaelastraszTheRedPosSouth = Position(134.369049f, -420.311066f, 110.472298f, 6.283184f);
|
||||
|
||||
// 16349 - Call of Vaelastrasz
|
||||
|
||||
class spell_blackrock_spire_call_of_vaelastrasz : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_blackrock_spire_call_of_vaelastrasz);
|
||||
|
||||
void OnEffect(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (Unit* caster = GetCaster())
|
||||
{
|
||||
if (InstanceScript* instance = caster->GetInstanceScript())
|
||||
{
|
||||
instance->SetData(DATA_VAELASTRASZ, IN_PROGRESS);
|
||||
float distanceToNorthSpawn = caster->GetDistance2d(VaelastraszTheRedPosNorth.m_positionX, VaelastraszTheRedPosNorth.m_positionY);
|
||||
float distanceToSouthSpawn = caster->GetDistance2d(VaelastraszTheRedPosSouth.m_positionX, VaelastraszTheRedPosSouth.m_positionY);
|
||||
Position spawnPosition = distanceToNorthSpawn < distanceToSouthSpawn ? VaelastraszTheRedPosNorth : VaelastraszTheRedPosSouth;
|
||||
// despawn is called by the CreatureAI
|
||||
caster->SummonCreature(NPC_VAELASTRASZ_THE_RED, spawnPosition, TEMPSUMMON_TIMED_DESPAWN, 60 * IN_MILLISECONDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectLaunch += SpellEffectFn(spell_blackrock_spire_call_of_vaelastrasz::OnEffect, EFFECT_0, SPELL_EFFECT_SEND_EVENT);
|
||||
}
|
||||
};
|
||||
|
||||
enum Spells
|
||||
{
|
||||
// Vaelastrasz the Red
|
||||
SPELL_VAELAN_SPAWNS = 16634, // Lightning Effect (Self cast)
|
||||
SPELL_TOUCH_OF_VAELASTRASZ = 16319, // AoE heal (Self cast)
|
||||
// Vaelastrasz
|
||||
SPELL_FLAMEBREATH = 16396, // Combat (Self cast)
|
||||
SPELL_VAELASTRASZ_SPAWN = 16354, // Self Cast Despawn (Self cast)
|
||||
// Victor Nefarius
|
||||
SPELL_NEFARIUS_CORRUPTION = 23642,
|
||||
};
|
||||
|
||||
enum ModelIds
|
||||
{
|
||||
MODEL_VAELASTRASZ_UBRS = 9909,
|
||||
MODEL_VAELASTRASZ_THE_RED = 9912,
|
||||
};
|
||||
|
||||
enum Says
|
||||
{
|
||||
// Vaelastrasz the Red
|
||||
SAY_RED_SUMMONED = 0,
|
||||
SAY_RED_BEFORE_TRANSFORM = 1,
|
||||
// Vaelastrasz
|
||||
SAY_VAEL_SUMMONED = 0,
|
||||
SAY_VAEL_STOP_COMBAT = 1,
|
||||
// Victor Nefarius
|
||||
SAY_NEFARIUS_15 = 15,
|
||||
SAY_NEFARIUS_16 = 16,
|
||||
SAY_NEFARIUS_17 = 17,
|
||||
};
|
||||
|
||||
enum Events
|
||||
{
|
||||
// Vaelastrasz the Red
|
||||
EVENT_RED_1_TALK_BEFORE_TRANSFORM = 1,
|
||||
EVENT_RED_2_TRANSFORM,
|
||||
// Vaelastrasz
|
||||
EVENT_VAEL_TALK_SUMMON,
|
||||
EVENT_VAEL_1_START_COMBAT,
|
||||
EVENT_NEFARIUS_TALK_1,
|
||||
EVENT_NEFARIUS_TALK_2,
|
||||
EVENT_NEFARIUS_TALK_3,
|
||||
EVENT_NEFARIUS_CORRUPTION,
|
||||
EVENT_VAEL_2_TRANSFORM,
|
||||
EVENT_VAEL_3_DESPAWN,
|
||||
EVENT_FLAME_BREATH,
|
||||
};
|
||||
|
||||
class npc_vaelastrasz_the_red : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_vaelastrasz_the_red() : CreatureScript("npc_vaelastrasz_the_red") { }
|
||||
|
||||
struct npc_vaelastrasz_the_redAI : public CreatureAI
|
||||
{
|
||||
npc_vaelastrasz_the_redAI(Creature* creature) : CreatureAI(creature) { }
|
||||
|
||||
void IsSummonedBy(Unit* summoner) override
|
||||
{
|
||||
if (!summoner)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_combatEnabled = false;
|
||||
me->CastSpell(me, SPELL_VAELAN_SPAWNS, false);
|
||||
me->SetFacingToObject(summoner);
|
||||
Talk(SAY_RED_SUMMONED);
|
||||
if (Creature* victor = me->FindNearestCreature(NPC_LORD_VICTOR_NEFARIUS, 100.0f))
|
||||
{
|
||||
_victorGUID = victor->GetGUID();
|
||||
}
|
||||
events.ScheduleEvent(EVENT_RED_1_TALK_BEFORE_TRANSFORM, 3s);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
events.Update(diff);
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_RED_1_TALK_BEFORE_TRANSFORM:
|
||||
Talk(SAY_RED_BEFORE_TRANSFORM);
|
||||
events.ScheduleEvent(EVENT_RED_2_TRANSFORM, 2s);
|
||||
break;
|
||||
case EVENT_RED_2_TRANSFORM:
|
||||
me->CastSpell(me, SPELL_TOUCH_OF_VAELASTRASZ, false);
|
||||
me->SetEntry(NPC_VAELASTRASZ_UBRS);
|
||||
me->SetDisplayId(MODEL_VAELASTRASZ_UBRS);
|
||||
events.ScheduleEvent(EVENT_VAEL_TALK_SUMMON, 1s);
|
||||
events.ScheduleEvent(EVENT_VAEL_1_START_COMBAT, 5s);
|
||||
break;
|
||||
case EVENT_VAEL_TALK_SUMMON:
|
||||
Talk(SAY_VAEL_SUMMONED);
|
||||
break;
|
||||
case EVENT_VAEL_1_START_COMBAT:
|
||||
_combatEnabled = true;
|
||||
me->SetImmuneToNPC(false);
|
||||
if (Creature* gyth = me->FindNearestCreature(NPC_GYTH, 100.0f, true))
|
||||
{
|
||||
me->AddThreat(gyth, 1000000.f);
|
||||
me->AI()->AttackStart(gyth);
|
||||
}
|
||||
if (Creature* rend = me->FindNearestCreature(NPC_WARCHIEF_REND_BLACKHAND, 100.0f, true))
|
||||
{
|
||||
if (!rend->IsImmuneToNPC() && rend->isTargetableForAttack())
|
||||
{
|
||||
me->AddThreat(rend, 100000.f);
|
||||
if (!me->FindNearestCreature(NPC_GYTH, 100.0f, true))
|
||||
{
|
||||
me->AI()->AttackStart(rend);
|
||||
}
|
||||
}
|
||||
}
|
||||
_events2.ScheduleEvent(EVENT_FLAME_BREATH, 5s);
|
||||
events.ScheduleEvent(EVENT_NEFARIUS_TALK_1, 500ms);
|
||||
break;
|
||||
case EVENT_NEFARIUS_TALK_1:
|
||||
if (Creature* victor = ObjectAccessor::GetCreature(*me, _victorGUID))
|
||||
{
|
||||
victor->GetMotionMaster()->Clear(); // stop pacing
|
||||
victor->GetMotionMaster()->MoveIdle();
|
||||
victor->StopMovingOnCurrentPos();
|
||||
victor->SetFacingToObject(me);
|
||||
victor->AI()->Talk(SAY_NEFARIUS_15);
|
||||
}
|
||||
events.ScheduleEvent(EVENT_NEFARIUS_TALK_2, 6s);
|
||||
break;
|
||||
case EVENT_NEFARIUS_TALK_2:
|
||||
if (Creature* victor = ObjectAccessor::GetCreature(*me, _victorGUID))
|
||||
{
|
||||
victor->SetFacingToObject(me);
|
||||
victor->AI()->Talk(SAY_NEFARIUS_16);
|
||||
}
|
||||
events.ScheduleEvent(EVENT_NEFARIUS_TALK_3, 5s);
|
||||
break;
|
||||
case EVENT_NEFARIUS_TALK_3:
|
||||
if (Creature* victor = ObjectAccessor::GetCreature(*me, _victorGUID))
|
||||
{
|
||||
victor->SetFacingToObject(me);
|
||||
victor->AI()->Talk(SAY_NEFARIUS_17);
|
||||
}
|
||||
events.ScheduleEvent(EVENT_NEFARIUS_CORRUPTION, 5s);
|
||||
break;
|
||||
case EVENT_NEFARIUS_CORRUPTION:
|
||||
_combatEnabled = false;
|
||||
me->AttackStop();
|
||||
me->RemoveAllAuras();
|
||||
me->StopMovingOnCurrentPos();
|
||||
me->SetFaction(FACTION_FRIENDLY);
|
||||
if (Creature* victor = ObjectAccessor::GetCreature(*me, _victorGUID))
|
||||
{
|
||||
victor->SetFacingToObject(me);
|
||||
victor->CastSpell(me, SPELL_NEFARIUS_CORRUPTION, TRIGGERED_CAST_DIRECTLY);
|
||||
}
|
||||
events.ScheduleEvent(EVENT_VAEL_2_TRANSFORM, 1s);
|
||||
break;
|
||||
case EVENT_VAEL_2_TRANSFORM:
|
||||
Talk(SAY_VAEL_STOP_COMBAT);
|
||||
me->SetDisplayId(MODEL_VAELASTRASZ_THE_RED);
|
||||
events.ScheduleEvent(EVENT_VAEL_3_DESPAWN, 500ms);
|
||||
break;
|
||||
case EVENT_VAEL_3_DESPAWN:
|
||||
DoCast(me, SPELL_VAELASTRASZ_SPAWN);
|
||||
me->DespawnOrUnsummon(1500);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_combatEnabled || !UpdateVictim() || me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_events2.Update(diff);
|
||||
|
||||
switch (_events2.ExecuteEvent())
|
||||
{
|
||||
case EVENT_FLAME_BREATH:
|
||||
me->CastSpell(me, SPELL_FLAMEBREATH, false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
return;
|
||||
}
|
||||
|
||||
private:
|
||||
ObjectGuid _victorGUID;
|
||||
bool _combatEnabled;
|
||||
EventMap _events2;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetBlackrockSpireAI<npc_vaelastrasz_the_redAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_instance_blackrock_spire()
|
||||
{
|
||||
new instance_blackrock_spire();
|
||||
@@ -885,4 +1136,6 @@ void AddSC_instance_blackrock_spire()
|
||||
new go_father_flame();
|
||||
new near_scarshield_infiltrator();
|
||||
new at_scarshield_infiltrator();
|
||||
RegisterSpellScript(spell_blackrock_spire_call_of_vaelastrasz);
|
||||
new npc_vaelastrasz_the_red();
|
||||
}
|
||||
|
||||
@@ -17,34 +17,37 @@
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellInfo.h"
|
||||
#include "SpellScript.h"
|
||||
#include "TaskScheduler.h"
|
||||
#include "temple_of_ahnqiraj.h"
|
||||
|
||||
enum Spells
|
||||
{
|
||||
// Viscidus - Glob of Viscidus
|
||||
SPELL_POISON_SHOCK = 25993,
|
||||
SPELL_POISONBOLT_VOLLEY = 25991,
|
||||
SPELL_TOXIN = 26575,
|
||||
SPELL_SUMMON_TOXIN_SLIME = 26584,
|
||||
SPELL_SUMMON_TOXIN_SLIME_2 = 26577,
|
||||
SPELL_VISCIDUS_SLOWED = 26034,
|
||||
SPELL_VISCIDUS_SLOWED_MORE = 26036,
|
||||
SPELL_VISCIDUS_FREEZE = 25937,
|
||||
SPELL_REJOIN_VISCIDUS = 25896,
|
||||
SPELL_VISCIDUS_EXPLODE = 25938,
|
||||
SPELL_VISCIDUS_SUICIDE = 26003,
|
||||
SPELL_VISCIDUS_SHRINKS = 25893, // Removed from client, in world.spell_dbc
|
||||
SPELL_EXPLODE_TRIGGER = 25938,
|
||||
SPELL_VISCIDUS_SHRINKS = 25893, // Server-side
|
||||
SPELL_INVIS_SELF = 25905,
|
||||
SPELL_VISCIDUS_GROWS = 25897,
|
||||
SPELL_STUN_SELF = 25900,
|
||||
|
||||
SPELL_MEMBRANE_VISCIDUS = 25994, // damage reduction spell - removed from DBC
|
||||
SPELL_VISCIDUS_WEAKNESS = 25926, // aura which procs at damage - should trigger the slow spells - removed from DBC
|
||||
SPELL_VISCIDUS_GROWS = 25897, // removed from DBC
|
||||
SPELL_SUMMON_GLOBS = 25885, // summons npc 15667 using spells from 25865 to 25884; All spells have target coords - removed from DBC
|
||||
SPELL_VISCIDUS_TELEPORT = 25904, // removed from DBC
|
||||
// Toxic slime
|
||||
SPELL_TOXIN = 26575,
|
||||
};
|
||||
|
||||
enum Events
|
||||
{
|
||||
EVENT_POISONBOLT_VOLLEY = 1,
|
||||
EVENT_POISON_SHOCK = 2,
|
||||
EVENT_RESET_PHASE = 3
|
||||
EVENT_TOXIN = 3,
|
||||
EVENT_RESET_PHASE = 4
|
||||
};
|
||||
|
||||
enum Phases
|
||||
@@ -81,52 +84,98 @@ enum MovePoints
|
||||
ROOM_CENTER = 1
|
||||
};
|
||||
|
||||
Position const ViscidusCoord = { -7992.36f, 908.19f, -52.62f, 1.68f }; /// @todo Visci isn't in room middle
|
||||
float const RoomRadius = 40.0f; /// @todo Not sure if its correct
|
||||
enum Misc
|
||||
{
|
||||
MAX_GLOB_SPAWN = 20,
|
||||
};
|
||||
|
||||
Position const roomCenter = { -7992.36f, 908.19f, -52.62f, 1.68f };
|
||||
|
||||
Position const resetPoint = { -7992.0f, 1041.0f, -23.84f };
|
||||
|
||||
std::array<uint32, MAX_GLOB_SPAWN> const spawnGlobSpells = { 25865, 25866, 25867, 25868, 25869, 25870, 25871, 25872, 25873, 25874, 25875, 25876, 25877, 25878, 25879, 25880, 25881, 25882, 25883, 25884 };
|
||||
|
||||
struct boss_viscidus : public BossAI
|
||||
{
|
||||
boss_viscidus(Creature* creature) : BossAI(creature, DATA_VISCIDUS) { }
|
||||
boss_viscidus(Creature* creature) : BossAI(creature, DATA_VISCIDUS)
|
||||
{
|
||||
me->LowerPlayerDamageReq(me->GetMaxHealth());
|
||||
}
|
||||
|
||||
bool CheckInRoom() override
|
||||
{
|
||||
if (me->GetExactDist2d(resetPoint) <= 10.f)
|
||||
{
|
||||
EnterEvadeMode(EVADE_REASON_BOUNDARY);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_Reset();
|
||||
_hitcounter = 0;
|
||||
_phase = PHASE_FROST;
|
||||
BossAI::Reset();
|
||||
events.Reset();
|
||||
SoftReset();
|
||||
_scheduler.CancelAll();
|
||||
me->RemoveAurasDueToSpell(SPELL_VISCIDUS_SHRINKS);
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* attacker, uint32& /*damage*/, DamageEffectType, SpellSchoolMask) override
|
||||
void SoftReset()
|
||||
{
|
||||
_hitcounter = 0;
|
||||
me->RemoveAurasDueToSpell(SPELL_STUN_SELF);
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
_phase = PHASE_FROST;
|
||||
me->RemoveAurasDueToSpell(SPELL_INVIS_SELF);
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType effType, SpellSchoolMask) override
|
||||
{
|
||||
if (me->HealthBelowPct(5))
|
||||
damage = 0;
|
||||
|
||||
if (!attacker || _phase != PHASE_MELEE)
|
||||
return;
|
||||
|
||||
++_hitcounter;
|
||||
if (effType == DIRECT_DAMAGE)
|
||||
++_hitcounter;
|
||||
|
||||
if (attacker->HasUnitState(UNIT_STATE_MELEE_ATTACKING) && _hitcounter >= HITCOUNTER_EXPLODE)
|
||||
{
|
||||
if (me->GetHealthPct() <= 5.f)
|
||||
{
|
||||
Unit::Kill(attacker, me);
|
||||
return;
|
||||
}
|
||||
|
||||
Talk(EMOTE_EXPLODE);
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
events.Reset();
|
||||
_phase = PHASE_GLOB;
|
||||
DoCast(me, SPELL_VISCIDUS_EXPLODE);
|
||||
me->SetVisible(false);
|
||||
me->RemoveAura(SPELL_TOXIN);
|
||||
me->RemoveAura(SPELL_VISCIDUS_FREEZE);
|
||||
|
||||
uint8 NumGlobes = me->GetHealthPct() / 5.0f;
|
||||
for (uint8 i = 0; i < NumGlobes; ++i)
|
||||
{
|
||||
float Angle = i * 2 * M_PI / NumGlobes;
|
||||
float X = ViscidusCoord.GetPositionX() + std::cos(Angle) * RoomRadius;
|
||||
float Y = ViscidusCoord.GetPositionY() + std::sin(Angle) * RoomRadius;
|
||||
float Z = -35.0f;
|
||||
|
||||
if (TempSummon* Glob = me->SummonCreature(NPC_GLOB_OF_VISCIDUS, X, Y, Z))
|
||||
DoCastSelf(SPELL_STUN_SELF, true);
|
||||
me->AttackStop();
|
||||
me->CastStop();
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_FLYDEATH); // not found in sniff, this is the best one I found
|
||||
_scheduler
|
||||
.Schedule(2500ms, [this](TaskContext /*context*/)
|
||||
{
|
||||
Glob->UpdateAllowedPositionZ(X, Y, Z);
|
||||
Glob->NearTeleportTo(X, Y, Z, 0.0f);
|
||||
Glob->GetMotionMaster()->MovePoint(ROOM_CENTER, ViscidusCoord);
|
||||
}
|
||||
}
|
||||
DoCastSelf(SPELL_EXPLODE_TRIGGER, true);
|
||||
})
|
||||
.Schedule(3000ms, [this](TaskContext /*context*/)
|
||||
{
|
||||
DoCastSelf(SPELL_INVIS_SELF, true);
|
||||
me->SetAuraStack(SPELL_VISCIDUS_SHRINKS, me, 20);
|
||||
me->LowerPlayerDamageReq(me->GetMaxHealth());
|
||||
me->SetHealth(me->GetMaxHealth() * 0.01f); // set 1% health
|
||||
DoResetThreat();
|
||||
me->NearTeleportTo(roomCenter.GetPositionX(),
|
||||
roomCenter.GetPositionY(),
|
||||
roomCenter.GetPositionZ(),
|
||||
roomCenter.GetOrientation());
|
||||
});
|
||||
}
|
||||
else if (_hitcounter == HITCOUNTER_SHATTER)
|
||||
Talk(EMOTE_SHATTER);
|
||||
@@ -136,7 +185,12 @@ struct boss_viscidus : public BossAI
|
||||
|
||||
void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
|
||||
{
|
||||
if ((spell->GetSchoolMask() & SPELL_SCHOOL_MASK_FROST) && _phase == PHASE_FROST && me->GetHealthPct() > 5.0f)
|
||||
if (spell->Id == SPELL_REJOIN_VISCIDUS)
|
||||
{
|
||||
me->RemoveAuraFromStack(SPELL_VISCIDUS_SHRINKS);
|
||||
}
|
||||
|
||||
if ((spell->GetSchoolMask() & SPELL_SCHOOL_MASK_FROST) && _phase == PHASE_FROST)
|
||||
{
|
||||
++_hitcounter;
|
||||
|
||||
@@ -145,85 +199,89 @@ struct boss_viscidus : public BossAI
|
||||
_hitcounter = 0;
|
||||
Talk(EMOTE_FROZEN);
|
||||
_phase = PHASE_MELEE;
|
||||
DoCast(me, SPELL_VISCIDUS_FREEZE);
|
||||
me->RemoveAura(SPELL_VISCIDUS_SLOWED_MORE);
|
||||
events.ScheduleEvent(EVENT_RESET_PHASE, 15000);
|
||||
DoCastSelf(SPELL_VISCIDUS_FREEZE);
|
||||
events.ScheduleEvent(EVENT_RESET_PHASE, 15s);
|
||||
}
|
||||
else if (_hitcounter >= HITCOUNTER_SLOW_MORE)
|
||||
else if (_hitcounter == HITCOUNTER_SLOW_MORE)
|
||||
{
|
||||
Talk(EMOTE_FREEZE);
|
||||
me->RemoveAura(SPELL_VISCIDUS_SLOWED);
|
||||
DoCast(me, SPELL_VISCIDUS_SLOWED_MORE);
|
||||
DoCastSelf(SPELL_VISCIDUS_SLOWED_MORE);
|
||||
}
|
||||
else if (_hitcounter >= HITCOUNTER_SLOW)
|
||||
else if (_hitcounter == HITCOUNTER_SLOW)
|
||||
{
|
||||
Talk(EMOTE_SLOW);
|
||||
DoCast(me, SPELL_VISCIDUS_SLOWED);
|
||||
DoCastSelf(SPELL_VISCIDUS_SLOWED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
void SummonedCreatureDies(Creature* summon, Unit* killer) override
|
||||
{
|
||||
_EnterCombat();
|
||||
events.Reset();
|
||||
if (summon->GetEntry() != NPC_GLOB_OF_VISCIDUS)
|
||||
return;
|
||||
|
||||
if (killer && killer->GetEntry() == NPC_GLOB_OF_VISCIDUS)
|
||||
{
|
||||
if (_phase == PHASE_GLOB)
|
||||
{
|
||||
_phase = PHASE_FROST;
|
||||
me->RemoveAurasDueToSpell(SPELL_INVIS_SELF);
|
||||
}
|
||||
|
||||
int32 heal = me->GetMaxHealth() * 0.05f;
|
||||
me->CastCustomSpell(me, SPELL_VISCIDUS_GROWS, &heal, nullptr, nullptr, true);
|
||||
}
|
||||
|
||||
if (!summons.IsAnyCreatureWithEntryAlive(NPC_GLOB_OF_VISCIDUS)) // all globs were killed
|
||||
{
|
||||
SoftReset();
|
||||
InitSpells();
|
||||
me->LowerPlayerDamageReq(me->GetMaxHealth());
|
||||
}
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* who) override
|
||||
{
|
||||
BossAI::EnterCombat(who);
|
||||
InitSpells();
|
||||
}
|
||||
|
||||
void InitSpells()
|
||||
{
|
||||
DoCast(me, SPELL_TOXIN);
|
||||
events.ScheduleEvent(EVENT_TOXIN, 15s, 20s);
|
||||
events.ScheduleEvent(EVENT_POISONBOLT_VOLLEY, 10s, 15s);
|
||||
events.ScheduleEvent(EVENT_POISON_SHOCK, 7s, 12s);
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
summons.DespawnAll();
|
||||
ScriptedAI::EnterEvadeMode(why);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
DoCast(me, SPELL_VISCIDUS_SUICIDE);
|
||||
summons.DespawnAll();
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
if (!UpdateVictim() || !CheckInRoom())
|
||||
return;
|
||||
|
||||
if (_phase == PHASE_GLOB && summons.empty())
|
||||
{
|
||||
DoResetThreat();
|
||||
me->NearTeleportTo(ViscidusCoord.GetPositionX(),
|
||||
ViscidusCoord.GetPositionY(),
|
||||
ViscidusCoord.GetPositionZ(),
|
||||
ViscidusCoord.GetOrientation());
|
||||
|
||||
_hitcounter = 0;
|
||||
_phase = PHASE_FROST;
|
||||
InitSpells();
|
||||
me->SetVisible(true);
|
||||
}
|
||||
|
||||
events.Update(diff);
|
||||
_scheduler.Update(diff);
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_POISONBOLT_VOLLEY:
|
||||
DoCast(me, SPELL_POISONBOLT_VOLLEY);
|
||||
DoCastSelf(SPELL_POISONBOLT_VOLLEY);
|
||||
events.ScheduleEvent(EVENT_POISONBOLT_VOLLEY, 10s, 15s);
|
||||
break;
|
||||
case EVENT_POISON_SHOCK:
|
||||
DoCast(me, SPELL_POISON_SHOCK);
|
||||
DoCastSelf(SPELL_POISON_SHOCK);
|
||||
events.ScheduleEvent(EVENT_POISON_SHOCK, 7s, 12s);
|
||||
break;
|
||||
case EVENT_TOXIN:
|
||||
DoCastRandomTarget(SPELL_SUMMON_TOXIN_SLIME);
|
||||
events.ScheduleEvent(EVENT_TOXIN, 15s, 20s);
|
||||
break;
|
||||
case EVENT_RESET_PHASE:
|
||||
_hitcounter = 0;
|
||||
me->RemoveAura(SPELL_VISCIDUS_FREEZE);
|
||||
_phase = PHASE_FROST;
|
||||
break;
|
||||
default:
|
||||
@@ -231,54 +289,118 @@ struct boss_viscidus : public BossAI
|
||||
}
|
||||
}
|
||||
|
||||
if (_phase != PHASE_GLOB)
|
||||
if (_phase != PHASE_GLOB && me->GetReactState() == REACT_AGGRESSIVE)
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
uint8 _hitcounter;
|
||||
Phases _phase;
|
||||
uint8 _phase;
|
||||
TaskScheduler _scheduler;
|
||||
};
|
||||
|
||||
struct boss_glob_of_viscidus : public ScriptedAI
|
||||
{
|
||||
boss_glob_of_viscidus(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
boss_glob_of_viscidus(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
InstanceScript* instance = me->GetInstanceScript();
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
}
|
||||
|
||||
if (Creature* viscidus = me->GetMap()->GetCreature(instance->GetGuidData(DATA_VISCIDUS)))
|
||||
{
|
||||
if (BossAI* viscidusAI = dynamic_cast<BossAI*>(viscidus->GetAI()))
|
||||
viscidusAI->SummonedCreatureDespawn(me);
|
||||
|
||||
if (viscidus->IsAlive() && viscidus->GetHealthPct() < 5.0f)
|
||||
void InitializeAI() override
|
||||
{
|
||||
me->SetInCombatWithZone();
|
||||
_scheduler.CancelAll();
|
||||
_scheduler.Schedule(2400ms, [this](TaskContext context)
|
||||
{
|
||||
viscidus->SetVisible(true);
|
||||
Unit::Kill(viscidus->GetVictim(), viscidus);
|
||||
}
|
||||
else
|
||||
{
|
||||
viscidus->SetHealth(viscidus->GetHealth() - viscidus->GetMaxHealth() / 20);
|
||||
viscidus->CastSpell(viscidus, SPELL_VISCIDUS_SHRINKS);
|
||||
}
|
||||
}
|
||||
me->GetMotionMaster()->MovePoint(ROOM_CENTER, roomCenter);
|
||||
float topSpeed = me->GetSpeedRate(MOVE_RUN) + 0.2142855f * 4;
|
||||
context.Schedule(1s, [this, topSpeed](TaskContext context)
|
||||
{
|
||||
float newSpeed = me->GetSpeedRate(MOVE_RUN) + 0.2142855f; // sniffed
|
||||
me->SetSpeed(MOVE_RUN, newSpeed < topSpeed ? newSpeed : topSpeed);
|
||||
context.Repeat();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void MovementInform(uint32 /*type*/, uint32 id) override
|
||||
{
|
||||
if (id == ROOM_CENTER)
|
||||
{
|
||||
DoCast(me, SPELL_REJOIN_VISCIDUS);
|
||||
if (TempSummon* summon = me->ToTempSummon())
|
||||
summon->UnSummon();
|
||||
DoCastSelf(SPELL_REJOIN_VISCIDUS);
|
||||
Unit::Kill(me, me);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
_scheduler.Update(diff);
|
||||
}
|
||||
|
||||
protected:
|
||||
TaskScheduler _scheduler;
|
||||
};
|
||||
|
||||
struct npc_toxic_slime : public ScriptedAI
|
||||
{
|
||||
npc_toxic_slime(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
}
|
||||
|
||||
void InitializeAI() override
|
||||
{
|
||||
SetCombatMovement(false);
|
||||
DoCastSelf(SPELL_TOXIN);
|
||||
|
||||
InstanceScript* instance = me->GetInstanceScript();
|
||||
|
||||
if (Creature* viscidus = instance->GetCreature(DATA_VISCIDUS))
|
||||
if (viscidus->AI())
|
||||
viscidus->AI()->JustSummoned(me);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_explode_trigger : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_explode_trigger);
|
||||
|
||||
void HandleOnHit()
|
||||
{
|
||||
Unit* caster = GetCaster();
|
||||
|
||||
uint8 globsToSpawn = std::floor(caster->GetHealthPct() / 5.f);
|
||||
for (uint8 i = 0; i < globsToSpawn; i++)
|
||||
caster->CastSpell((Unit*)nullptr, spawnGlobSpells[i], true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnHit += SpellHitFn(spell_explode_trigger::HandleOnHit);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_summon_toxin_slime : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_summon_toxin_slime);
|
||||
|
||||
void HandleOnHit()
|
||||
{
|
||||
if (Unit* target = GetHitUnit())
|
||||
target->CastSpell(target, SPELL_SUMMON_TOXIN_SLIME_2, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnHit += SpellHitFn(spell_summon_toxin_slime::HandleOnHit);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_viscidus()
|
||||
{
|
||||
RegisterTempleOfAhnQirajCreatureAI(boss_viscidus);
|
||||
RegisterTempleOfAhnQirajCreatureAI(boss_glob_of_viscidus);
|
||||
RegisterTempleOfAhnQirajCreatureAI(npc_toxic_slime);
|
||||
RegisterSpellScript(spell_explode_trigger);
|
||||
RegisterSpellScript(spell_summon_toxin_slime);
|
||||
}
|
||||
|
||||
@@ -28,7 +28,8 @@ ObjectData const creatureData[] =
|
||||
{ NPC_OURO_SPAWNER, DATA_OURO_SPAWNER },
|
||||
{ NPC_MASTERS_EYE, DATA_MASTERS_EYE },
|
||||
{ NPC_VEKLOR, DATA_VEKLOR },
|
||||
{ NPC_VEKNILASH, DATA_VEKNILASH }
|
||||
{ NPC_VEKNILASH, DATA_VEKNILASH },
|
||||
{ NPC_VISCIDUS, DATA_VISCIDUS }
|
||||
};
|
||||
|
||||
DoorData const doorData[] =
|
||||
@@ -62,7 +63,6 @@ public:
|
||||
ObjectGuid VemGUID;
|
||||
ObjectGuid KriGUID;
|
||||
ObjectGuid YaujGUID;
|
||||
ObjectGuid ViscidusGUID;
|
||||
ObjectGuid CThunGUID;
|
||||
GuidVector CThunGraspGUIDs;
|
||||
|
||||
@@ -91,9 +91,6 @@ public:
|
||||
case NPC_YAUJ:
|
||||
YaujGUID = creature->GetGUID();
|
||||
break;
|
||||
case NPC_VISCIDUS:
|
||||
ViscidusGUID = creature->GetGUID();
|
||||
break;
|
||||
case NPC_OURO_SPAWNER:
|
||||
if (GetBossState(DATA_OURO) != DONE)
|
||||
creature->Respawn();
|
||||
@@ -168,8 +165,6 @@ public:
|
||||
return KriGUID;
|
||||
case DATA_YAUJ:
|
||||
return YaujGUID;
|
||||
case DATA_VISCIDUS:
|
||||
return ViscidusGUID;
|
||||
}
|
||||
return ObjectGuid::Empty;
|
||||
}
|
||||
|
||||
@@ -640,6 +640,27 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool AreAllWingsCleared() const
|
||||
{
|
||||
return (GetBossState(BOSS_MAEXXNA) == DONE) && (GetBossState(BOSS_LOATHEB) == DONE) && (GetBossState(BOSS_THADDIUS) == DONE) && (GetBossState(BOSS_HORSEMAN) == DONE);
|
||||
}
|
||||
|
||||
bool CheckRequiredBosses(uint32 bossId, Player const* /* player */) const override
|
||||
{
|
||||
switch (bossId)
|
||||
{
|
||||
case BOSS_SAPPHIRON:
|
||||
if (!AreAllWingsCleared())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SetBossState(uint32 bossId, EncounterState state) override
|
||||
{
|
||||
// pull all the trash if not killed
|
||||
@@ -1221,8 +1242,33 @@ public:
|
||||
};
|
||||
};
|
||||
|
||||
const Position sapphironEntryTP = { 3498.300049f, -5349.490234f, 144.968002f, 1.3698910f };
|
||||
|
||||
class at_naxxramas_hub_portal : public AreaTriggerScript
|
||||
{
|
||||
public:
|
||||
at_naxxramas_hub_portal() : AreaTriggerScript("at_naxxramas_hub_portal") { }
|
||||
|
||||
bool OnTrigger(Player* player, AreaTrigger const* /*trigger*/) override
|
||||
{
|
||||
if (player->IsAlive() && !player->IsInCombat())
|
||||
{
|
||||
if (InstanceScript *instance = player->GetInstanceScript())
|
||||
{
|
||||
if (instance->CheckRequiredBosses(BOSS_SAPPHIRON))
|
||||
{
|
||||
player->TeleportTo(533, sapphironEntryTP.m_positionX, sapphironEntryTP.m_positionY, sapphironEntryTP.m_positionZ, sapphironEntryTP.m_orientation);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_instance_naxxramas()
|
||||
{
|
||||
new instance_naxxramas();
|
||||
new boss_naxxramas_misc();
|
||||
new at_naxxramas_hub_portal();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user