fix(Core/TempleOfAhnQiraj): Viscidus (#12956)
This commit is contained in:
@@ -0,0 +1,41 @@
|
|||||||
|
--
|
||||||
|
DELETE FROM `spell_target_position` WHERE `ID` IN (25865, 25866, 25867, 25868, 25869, 25870, 25871, 25872, 25873, 25874, 25875, 25876, 25877, 25878, 25879, 25880, 25881, 25882, 25883, 25884);
|
||||||
|
INSERT INTO `spell_target_position` (`ID`, `MapID`, `PositionX`, `PositionY`, `PositionZ`, `Orientation`) VALUES
|
||||||
|
(25865, 531, -8023.59, 964.772, -41.229, 5.376),
|
||||||
|
(25866, 531, -8042.13, 911.263, -42.841, 6.200),
|
||||||
|
(25867, 531, -7999.36, 860.525, -47.206, 1.417),
|
||||||
|
(25868, 531, -7971.30, 862.581, -48.099, 2.148),
|
||||||
|
(25869, 531, -7943.21, 903.804, -48.473, 3.078),
|
||||||
|
(25870, 531, -7954.38, 958.562, -41.609, 3.962),
|
||||||
|
(25871, 531, -7997.19, 979.192, -41.653, 4.896),
|
||||||
|
(25872, 531, -8037.89, 929.679, -43.416, 6.024),
|
||||||
|
(25873, 531, -8015.41, 867.734, -45.607, 1.103),
|
||||||
|
(25874, 531, -7982.80, 857.172, -48.212, 1.500),
|
||||||
|
(25875, 531, -7952.12, 883.183, -48.194, 2.430),
|
||||||
|
(25876, 531, -7947.22, 939.122, -44.014, 3.718),
|
||||||
|
(25877, 531, -7975.77, 974.820, -41.584, 4.417),
|
||||||
|
(25878, 531, -8032.75, 948.274, -41.919, 5.595),
|
||||||
|
(25879, 531, -8037.08, 887.268, -43.581, 0.675),
|
||||||
|
(25880, 531, -7992.21, 857.500, -47.762, 1.664),
|
||||||
|
(25881, 531, -7960.71, 872.483, -48.759, 2.360),
|
||||||
|
(25882, 531, -7942.98, 918.616, -46.401, 3.306),
|
||||||
|
(25883, 531, -7964.32, 967.879, -42.112, 4.087),
|
||||||
|
(25884, 531, -8015.24, 976.553, -41.647, 4.947);
|
||||||
|
|
||||||
|
DELETE FROM `spell_script_names` WHERE `ScriptName` = 'spell_explode_trigger' AND `spell_id` = 25938;
|
||||||
|
DELETE FROM `spell_script_names` WHERE `ScriptName` = 'spell_summon_toxin_slime' AND `spell_id` = 26584;
|
||||||
|
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
|
||||||
|
(25938, 'spell_explode_trigger'),
|
||||||
|
(26584, 'spell_summon_toxin_slime');
|
||||||
|
|
||||||
|
UPDATE `creature_template` SET `flags_extra` = `flags_extra`|1073741824 WHERE `entry` = 15667;
|
||||||
|
|
||||||
|
UPDATE `creature_template_addon` SET `auras` = '25994' WHERE `entry` = 15299;
|
||||||
|
|
||||||
|
UPDATE `creature_template` SET `modelid1` = 19595, `unit_flags` = `unit_flags`|33554432, `flags_extra` = `flags_extra`|64, `AIName` = '', `ScriptName` = 'npc_toxic_slime' WHERE `entry` = 15925;
|
||||||
|
|
||||||
|
DELETE FROM `creature_template_movement` WHERE `CreatureId` = 15925;
|
||||||
|
INSERT INTO `creature_template_movement` (`CreatureId`, `Ground`, `Swim`, `Flight`, `Rooted`, `Chase`, `Random`, `InteractionPauseTimer`) VALUES
|
||||||
|
(15925, 0, 0, 0, 1, 0, 0, 0);
|
||||||
|
|
||||||
|
UPDATE `spell_dbc` SET `Effect_1` = 28, `EffectBasePoints_1` = 1, `EffectDieSides_1` = 0, `EffectMiscValueB_1` = 64 WHERE `ID` = 26577;
|
||||||
@@ -153,6 +153,22 @@ bool SummonList::IsAnyCreatureAlive() const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SummonList::IsAnyCreatureWithEntryAlive(uint32 entry) const
|
||||||
|
{
|
||||||
|
for (auto const& guid : storage_)
|
||||||
|
{
|
||||||
|
if (Creature* summon = ObjectAccessor::GetCreature(*me, guid))
|
||||||
|
{
|
||||||
|
if (summon->GetEntry() == entry && summon->IsAlive())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool SummonList::IsAnyCreatureInCombat() const
|
bool SummonList::IsAnyCreatureInCombat() const
|
||||||
{
|
{
|
||||||
for (auto const& guid : storage_)
|
for (auto const& guid : storage_)
|
||||||
|
|||||||
@@ -91,6 +91,7 @@ public:
|
|||||||
void DespawnEntry(uint32 entry);
|
void DespawnEntry(uint32 entry);
|
||||||
void DespawnAll();
|
void DespawnAll();
|
||||||
bool IsAnyCreatureAlive() const;
|
bool IsAnyCreatureAlive() const;
|
||||||
|
bool IsAnyCreatureWithEntryAlive(uint32 entry) const;
|
||||||
bool IsAnyCreatureInCombat() const;
|
bool IsAnyCreatureInCombat() const;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|||||||
@@ -17,34 +17,37 @@
|
|||||||
|
|
||||||
#include "ScriptMgr.h"
|
#include "ScriptMgr.h"
|
||||||
#include "ScriptedCreature.h"
|
#include "ScriptedCreature.h"
|
||||||
#include "SpellInfo.h"
|
#include "SpellScript.h"
|
||||||
|
#include "TaskScheduler.h"
|
||||||
#include "temple_of_ahnqiraj.h"
|
#include "temple_of_ahnqiraj.h"
|
||||||
|
|
||||||
enum Spells
|
enum Spells
|
||||||
{
|
{
|
||||||
|
// Viscidus - Glob of Viscidus
|
||||||
SPELL_POISON_SHOCK = 25993,
|
SPELL_POISON_SHOCK = 25993,
|
||||||
SPELL_POISONBOLT_VOLLEY = 25991,
|
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 = 26034,
|
||||||
SPELL_VISCIDUS_SLOWED_MORE = 26036,
|
SPELL_VISCIDUS_SLOWED_MORE = 26036,
|
||||||
SPELL_VISCIDUS_FREEZE = 25937,
|
SPELL_VISCIDUS_FREEZE = 25937,
|
||||||
SPELL_REJOIN_VISCIDUS = 25896,
|
SPELL_REJOIN_VISCIDUS = 25896,
|
||||||
SPELL_VISCIDUS_EXPLODE = 25938,
|
SPELL_EXPLODE_TRIGGER = 25938,
|
||||||
SPELL_VISCIDUS_SUICIDE = 26003,
|
SPELL_VISCIDUS_SHRINKS = 25893, // Server-side
|
||||||
SPELL_VISCIDUS_SHRINKS = 25893, // Removed from client, in world.spell_dbc
|
SPELL_INVIS_SELF = 25905,
|
||||||
|
SPELL_VISCIDUS_GROWS = 25897,
|
||||||
|
SPELL_STUN_SELF = 25900,
|
||||||
|
|
||||||
SPELL_MEMBRANE_VISCIDUS = 25994, // damage reduction spell - removed from DBC
|
// Toxic slime
|
||||||
SPELL_VISCIDUS_WEAKNESS = 25926, // aura which procs at damage - should trigger the slow spells - removed from DBC
|
SPELL_TOXIN = 26575,
|
||||||
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
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Events
|
enum Events
|
||||||
{
|
{
|
||||||
EVENT_POISONBOLT_VOLLEY = 1,
|
EVENT_POISONBOLT_VOLLEY = 1,
|
||||||
EVENT_POISON_SHOCK = 2,
|
EVENT_POISON_SHOCK = 2,
|
||||||
EVENT_RESET_PHASE = 3
|
EVENT_TOXIN = 3,
|
||||||
|
EVENT_RESET_PHASE = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Phases
|
enum Phases
|
||||||
@@ -81,52 +84,98 @@ enum MovePoints
|
|||||||
ROOM_CENTER = 1
|
ROOM_CENTER = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
Position const ViscidusCoord = { -7992.36f, 908.19f, -52.62f, 1.68f }; /// @todo Visci isn't in room middle
|
enum Misc
|
||||||
float const RoomRadius = 40.0f; /// @todo Not sure if its correct
|
{
|
||||||
|
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
|
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
|
void Reset() override
|
||||||
{
|
{
|
||||||
_Reset();
|
BossAI::Reset();
|
||||||
_hitcounter = 0;
|
events.Reset();
|
||||||
_phase = PHASE_FROST;
|
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)
|
if (!attacker || _phase != PHASE_MELEE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (effType == DIRECT_DAMAGE)
|
||||||
++_hitcounter;
|
++_hitcounter;
|
||||||
|
|
||||||
if (attacker->HasUnitState(UNIT_STATE_MELEE_ATTACKING) && _hitcounter >= HITCOUNTER_EXPLODE)
|
if (attacker->HasUnitState(UNIT_STATE_MELEE_ATTACKING) && _hitcounter >= HITCOUNTER_EXPLODE)
|
||||||
{
|
{
|
||||||
|
if (me->GetHealthPct() <= 5.f)
|
||||||
|
{
|
||||||
|
Unit::Kill(attacker, me);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Talk(EMOTE_EXPLODE);
|
Talk(EMOTE_EXPLODE);
|
||||||
|
me->SetReactState(REACT_PASSIVE);
|
||||||
events.Reset();
|
events.Reset();
|
||||||
_phase = PHASE_GLOB;
|
_phase = PHASE_GLOB;
|
||||||
DoCast(me, SPELL_VISCIDUS_EXPLODE);
|
|
||||||
me->SetVisible(false);
|
|
||||||
me->RemoveAura(SPELL_TOXIN);
|
|
||||||
me->RemoveAura(SPELL_VISCIDUS_FREEZE);
|
me->RemoveAura(SPELL_VISCIDUS_FREEZE);
|
||||||
|
DoCastSelf(SPELL_STUN_SELF, true);
|
||||||
uint8 NumGlobes = me->GetHealthPct() / 5.0f;
|
me->AttackStop();
|
||||||
for (uint8 i = 0; i < NumGlobes; ++i)
|
me->CastStop();
|
||||||
|
me->HandleEmoteCommand(EMOTE_ONESHOT_FLYDEATH); // not found in sniff, this is the best one I found
|
||||||
|
_scheduler
|
||||||
|
.Schedule(2500ms, [this](TaskContext /*context*/)
|
||||||
{
|
{
|
||||||
float Angle = i * 2 * M_PI / NumGlobes;
|
DoCastSelf(SPELL_EXPLODE_TRIGGER, true);
|
||||||
float X = ViscidusCoord.GetPositionX() + std::cos(Angle) * RoomRadius;
|
})
|
||||||
float Y = ViscidusCoord.GetPositionY() + std::sin(Angle) * RoomRadius;
|
.Schedule(3000ms, [this](TaskContext /*context*/)
|
||||||
float Z = -35.0f;
|
|
||||||
|
|
||||||
if (TempSummon* Glob = me->SummonCreature(NPC_GLOB_OF_VISCIDUS, X, Y, Z))
|
|
||||||
{
|
{
|
||||||
Glob->UpdateAllowedPositionZ(X, Y, Z);
|
DoCastSelf(SPELL_INVIS_SELF, true);
|
||||||
Glob->NearTeleportTo(X, Y, Z, 0.0f);
|
me->SetAuraStack(SPELL_VISCIDUS_SHRINKS, me, 20);
|
||||||
Glob->GetMotionMaster()->MovePoint(ROOM_CENTER, ViscidusCoord);
|
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)
|
else if (_hitcounter == HITCOUNTER_SHATTER)
|
||||||
Talk(EMOTE_SHATTER);
|
Talk(EMOTE_SHATTER);
|
||||||
@@ -136,7 +185,12 @@ struct boss_viscidus : public BossAI
|
|||||||
|
|
||||||
void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
|
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;
|
++_hitcounter;
|
||||||
|
|
||||||
@@ -145,85 +199,89 @@ struct boss_viscidus : public BossAI
|
|||||||
_hitcounter = 0;
|
_hitcounter = 0;
|
||||||
Talk(EMOTE_FROZEN);
|
Talk(EMOTE_FROZEN);
|
||||||
_phase = PHASE_MELEE;
|
_phase = PHASE_MELEE;
|
||||||
DoCast(me, SPELL_VISCIDUS_FREEZE);
|
|
||||||
me->RemoveAura(SPELL_VISCIDUS_SLOWED_MORE);
|
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);
|
Talk(EMOTE_FREEZE);
|
||||||
me->RemoveAura(SPELL_VISCIDUS_SLOWED);
|
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);
|
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();
|
if (summon->GetEntry() != NPC_GLOB_OF_VISCIDUS)
|
||||||
events.Reset();
|
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();
|
InitSpells();
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitSpells()
|
void InitSpells()
|
||||||
{
|
{
|
||||||
DoCast(me, SPELL_TOXIN);
|
events.ScheduleEvent(EVENT_TOXIN, 15s, 20s);
|
||||||
events.ScheduleEvent(EVENT_POISONBOLT_VOLLEY, 10s, 15s);
|
events.ScheduleEvent(EVENT_POISONBOLT_VOLLEY, 10s, 15s);
|
||||||
events.ScheduleEvent(EVENT_POISON_SHOCK, 7s, 12s);
|
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
|
void UpdateAI(uint32 diff) override
|
||||||
{
|
{
|
||||||
if (!UpdateVictim())
|
if (!UpdateVictim() || !CheckInRoom())
|
||||||
return;
|
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);
|
events.Update(diff);
|
||||||
|
_scheduler.Update(diff);
|
||||||
|
|
||||||
while (uint32 eventId = events.ExecuteEvent())
|
while (uint32 eventId = events.ExecuteEvent())
|
||||||
{
|
{
|
||||||
switch (eventId)
|
switch (eventId)
|
||||||
{
|
{
|
||||||
case EVENT_POISONBOLT_VOLLEY:
|
case EVENT_POISONBOLT_VOLLEY:
|
||||||
DoCast(me, SPELL_POISONBOLT_VOLLEY);
|
DoCastSelf(SPELL_POISONBOLT_VOLLEY);
|
||||||
events.ScheduleEvent(EVENT_POISONBOLT_VOLLEY, 10s, 15s);
|
events.ScheduleEvent(EVENT_POISONBOLT_VOLLEY, 10s, 15s);
|
||||||
break;
|
break;
|
||||||
case EVENT_POISON_SHOCK:
|
case EVENT_POISON_SHOCK:
|
||||||
DoCast(me, SPELL_POISON_SHOCK);
|
DoCastSelf(SPELL_POISON_SHOCK);
|
||||||
events.ScheduleEvent(EVENT_POISON_SHOCK, 7s, 12s);
|
events.ScheduleEvent(EVENT_POISON_SHOCK, 7s, 12s);
|
||||||
break;
|
break;
|
||||||
|
case EVENT_TOXIN:
|
||||||
|
DoCastRandomTarget(SPELL_SUMMON_TOXIN_SLIME);
|
||||||
|
events.ScheduleEvent(EVENT_TOXIN, 15s, 20s);
|
||||||
|
break;
|
||||||
case EVENT_RESET_PHASE:
|
case EVENT_RESET_PHASE:
|
||||||
_hitcounter = 0;
|
_hitcounter = 0;
|
||||||
|
me->RemoveAura(SPELL_VISCIDUS_FREEZE);
|
||||||
_phase = PHASE_FROST;
|
_phase = PHASE_FROST;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -231,54 +289,118 @@ struct boss_viscidus : public BossAI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_phase != PHASE_GLOB)
|
if (_phase != PHASE_GLOB && me->GetReactState() == REACT_AGGRESSIVE)
|
||||||
DoMeleeAttackIfReady();
|
DoMeleeAttackIfReady();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8 _hitcounter;
|
uint8 _hitcounter;
|
||||||
Phases _phase;
|
uint8 _phase;
|
||||||
|
TaskScheduler _scheduler;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct boss_glob_of_viscidus : public ScriptedAI
|
struct boss_glob_of_viscidus : public ScriptedAI
|
||||||
{
|
{
|
||||||
boss_glob_of_viscidus(Creature* creature) : ScriptedAI(creature) { }
|
boss_glob_of_viscidus(Creature* creature) : ScriptedAI(creature)
|
||||||
|
|
||||||
void JustDied(Unit* /*killer*/) override
|
|
||||||
{
|
{
|
||||||
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)
|
|
||||||
{
|
|
||||||
viscidus->SetVisible(true);
|
|
||||||
Unit::Kill(viscidus->GetVictim(), viscidus);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
void InitializeAI() override
|
||||||
{
|
{
|
||||||
viscidus->SetHealth(viscidus->GetHealth() - viscidus->GetMaxHealth() / 20);
|
me->SetInCombatWithZone();
|
||||||
viscidus->CastSpell(viscidus, SPELL_VISCIDUS_SHRINKS);
|
_scheduler.CancelAll();
|
||||||
}
|
_scheduler.Schedule(2400ms, [this](TaskContext context)
|
||||||
}
|
{
|
||||||
|
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
|
void MovementInform(uint32 /*type*/, uint32 id) override
|
||||||
{
|
{
|
||||||
if (id == ROOM_CENTER)
|
if (id == ROOM_CENTER)
|
||||||
{
|
{
|
||||||
DoCast(me, SPELL_REJOIN_VISCIDUS);
|
DoCastSelf(SPELL_REJOIN_VISCIDUS);
|
||||||
if (TempSummon* summon = me->ToTempSummon())
|
Unit::Kill(me, me);
|
||||||
summon->UnSummon();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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()
|
void AddSC_boss_viscidus()
|
||||||
{
|
{
|
||||||
RegisterTempleOfAhnQirajCreatureAI(boss_viscidus);
|
RegisterTempleOfAhnQirajCreatureAI(boss_viscidus);
|
||||||
RegisterTempleOfAhnQirajCreatureAI(boss_glob_of_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_OURO_SPAWNER, DATA_OURO_SPAWNER },
|
||||||
{ NPC_MASTERS_EYE, DATA_MASTERS_EYE },
|
{ NPC_MASTERS_EYE, DATA_MASTERS_EYE },
|
||||||
{ NPC_VEKLOR, DATA_VEKLOR },
|
{ NPC_VEKLOR, DATA_VEKLOR },
|
||||||
{ NPC_VEKNILASH, DATA_VEKNILASH }
|
{ NPC_VEKNILASH, DATA_VEKNILASH },
|
||||||
|
{ NPC_VISCIDUS, DATA_VISCIDUS }
|
||||||
};
|
};
|
||||||
|
|
||||||
DoorData const doorData[] =
|
DoorData const doorData[] =
|
||||||
@@ -62,7 +63,6 @@ public:
|
|||||||
ObjectGuid VemGUID;
|
ObjectGuid VemGUID;
|
||||||
ObjectGuid KriGUID;
|
ObjectGuid KriGUID;
|
||||||
ObjectGuid YaujGUID;
|
ObjectGuid YaujGUID;
|
||||||
ObjectGuid ViscidusGUID;
|
|
||||||
ObjectGuid CThunGUID;
|
ObjectGuid CThunGUID;
|
||||||
GuidVector CThunGraspGUIDs;
|
GuidVector CThunGraspGUIDs;
|
||||||
|
|
||||||
@@ -91,9 +91,6 @@ public:
|
|||||||
case NPC_YAUJ:
|
case NPC_YAUJ:
|
||||||
YaujGUID = creature->GetGUID();
|
YaujGUID = creature->GetGUID();
|
||||||
break;
|
break;
|
||||||
case NPC_VISCIDUS:
|
|
||||||
ViscidusGUID = creature->GetGUID();
|
|
||||||
break;
|
|
||||||
case NPC_OURO_SPAWNER:
|
case NPC_OURO_SPAWNER:
|
||||||
if (GetBossState(DATA_OURO) != DONE)
|
if (GetBossState(DATA_OURO) != DONE)
|
||||||
creature->Respawn();
|
creature->Respawn();
|
||||||
@@ -168,8 +165,6 @@ public:
|
|||||||
return KriGUID;
|
return KriGUID;
|
||||||
case DATA_YAUJ:
|
case DATA_YAUJ:
|
||||||
return YaujGUID;
|
return YaujGUID;
|
||||||
case DATA_VISCIDUS:
|
|
||||||
return ViscidusGUID;
|
|
||||||
}
|
}
|
||||||
return ObjectGuid::Empty;
|
return ObjectGuid::Empty;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user