mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-20 09:17:36 +01:00
Scripts/Deadmines: reworked Glubtok encounter
* update script to new model * use sniffed spline points and velocity for Glubtok's firewall platter * corrected several timers * re-order death sequence to reflect sniff data perfectly * optimized several condition handlings * increased Glubtok's melee damage * added missing instance bind flag to Glubtok
This commit is contained in:
1
sql/updates/world/custom/custom_2019_10_05_01_world.sql
Normal file
1
sql/updates/world/custom/custom_2019_10_05_01_world.sql
Normal file
@@ -0,0 +1 @@
|
||||
UPDATE `creature_template` SET `DamageModifier`= 120, `flags_extra`= `flags_extra` | 1 WHERE `entry`= 48936;
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellScript.h"
|
||||
#include "SpellAuraEffects.h"
|
||||
#include "MoveSplineInit.h"
|
||||
#include "Player.h"
|
||||
#include "Vehicle.h"
|
||||
#include "deadmines.h"
|
||||
@@ -64,7 +65,7 @@ enum Events
|
||||
EVENT_ANNOUNCE_FIRE_WALL,
|
||||
EVENT_FIRE_WALL,
|
||||
EVENT_BLOSSOM_TARGETING,
|
||||
EVENT_ARCANE_OVERLOAD,
|
||||
EVENT_KILL_SELF
|
||||
};
|
||||
|
||||
enum Phases
|
||||
@@ -97,122 +98,185 @@ enum Data
|
||||
};
|
||||
|
||||
Position const leftSideDistanceCheck = { -210.840f, -443.449f, 61.179f };
|
||||
Position const FirewallPlatterSummonPos = { -193.4054f, -441.5011f, 54.57029f, 1.833041f };
|
||||
|
||||
class boss_glubtok : public CreatureScript
|
||||
static constexpr uint32 const FirewallPlatterCyclicPathSize = 9;
|
||||
Position const FirewallPlatterCyclicPath[FirewallPlatterCyclicPathSize] =
|
||||
{
|
||||
public:
|
||||
boss_glubtok() : CreatureScript("boss_glubtok") { }
|
||||
{ -193.2778f, -442.0017f, 53.70924f },
|
||||
{ -193.4514f, -441.0169f, 55.70924f },
|
||||
{ -192.7042f, -441.1826f, 55.70924f },
|
||||
{ -192.293f, -441.8281f, 55.70924f },
|
||||
{ -192.4586f, -442.5753f, 55.70924f },
|
||||
{ -193.1041f, -442.9865f, 55.70924f },
|
||||
{ -193.8514f, -442.8209f, 55.70924f },
|
||||
{ -194.2626f, -442.1754f, 55.70924f },
|
||||
{ -194.0969f, -441.4282f, 55.70924f }
|
||||
};
|
||||
|
||||
struct boss_glubtokAI : public BossAI
|
||||
struct boss_glubtok : public BossAI
|
||||
{
|
||||
boss_glubtok(Creature* creature) : BossAI(creature, DATA_GLUBTOK),
|
||||
_defeated(false), _nextBlossomBunny(NPC_FIRE_BLOSSOM_BUNNY), _lastFists(FISTS_OF_FLAME) { }
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
boss_glubtokAI(Creature* creature) : BossAI(creature, DATA_GLUBTOK)
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
_Reset();
|
||||
me->SetCanDualWield(true);
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
void JustAppeared() override
|
||||
{
|
||||
if (Creature* platter = DoSummon(NPC_GLUBTOK_FIREWALL_PLATTER, FirewallPlatterSummonPos, 0, TEMPSUMMON_MANUAL_DESPAWN))
|
||||
{
|
||||
_killed = false;
|
||||
_allowKill = false;
|
||||
_nextBlossomBunny = NPC_FIRE_BLOSSOM_BUNNY;
|
||||
_lastFists = FISTS_OF_FLAME;
|
||||
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_Reset();
|
||||
Initialize();
|
||||
me->SetCanDualWield(true);
|
||||
}
|
||||
|
||||
void JustAppeared() override
|
||||
{
|
||||
DoSummon(NPC_GLUBTOK_FIREWALL_PLATTER, { me->GetPositionX(), me->GetPositionY(), 54.57029f, me->GetOrientation() }, 0, TEMPSUMMON_MANUAL_DESPAWN);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_JustEngagedWith();
|
||||
Talk(SAY_AGGRO);
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me);
|
||||
events.SetPhase(PHASE_1);
|
||||
events.ScheduleEvent(EVENT_BLINK, Seconds(18), 0, PHASE_1);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
_JustDied();
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason /*why*/) override
|
||||
{
|
||||
_EnterEvadeMode();
|
||||
summons.DespawnAll();
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
_DespawnAtEvade();
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
switch (summon->GetEntry())
|
||||
platter->m_Events.AddEventAtOffset([platter]()
|
||||
{
|
||||
case NPC_GLUBTOK_FIREWALL_PLATTER:
|
||||
summon->SetSpeed(MOVE_RUN, 0.5f);
|
||||
summon->m_Events.AddEventAtOffset([summon]()
|
||||
{
|
||||
summon->GetMotionMaster()->MoveCirclePath(summon->GetPositionX(), summon->GetPositionY(), 55.70924f, 3.0f, true, 10);
|
||||
}, 1s);
|
||||
break;
|
||||
case NPC_FIREWALL_PLATTER_1A:
|
||||
case NPC_FIREWALL_PLATTER_1B:
|
||||
case NPC_FIREWALL_PLATTER_1C:
|
||||
case NPC_FIREWALL_PLATTER_2A:
|
||||
case NPC_FIREWALL_PLATTER_2B:
|
||||
case NPC_FIREWALL_PLATTER_2C:
|
||||
_firewallDummyGUIDs.push_back(summon->GetGUID());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
summons.Summon(summon);
|
||||
platter->GetMotionMaster()->MoveCyclicPath(FirewallPlatterCyclicPath, FirewallPlatterCyclicPathSize, false, true, 0.25f);
|
||||
}, 1s);
|
||||
}
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_JustEngagedWith();
|
||||
Talk(SAY_AGGRO);
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me);
|
||||
events.SetPhase(PHASE_1);
|
||||
events.ScheduleEvent(EVENT_BLINK, 16s, 18s, 0, PHASE_1);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
_JustDied();
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason /*why*/) override
|
||||
{
|
||||
_EnterEvadeMode();
|
||||
summons.DespawnAll();
|
||||
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
_DespawnAtEvade();
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
switch (summon->GetEntry())
|
||||
{
|
||||
case NPC_FIREWALL_PLATTER_2A:
|
||||
case NPC_FIREWALL_PLATTER_2B:
|
||||
case NPC_FIREWALL_PLATTER_2C:
|
||||
_firewallDummyGUIDs.push_back(summon->GetGUID());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
summons.Summon(summon);
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* /*attacker*/, uint32& damage) override
|
||||
{
|
||||
if (me->HealthBelowPctDamaged(50, damage) && !events.IsInPhase(PHASE_2) && !_defeated)
|
||||
{
|
||||
events.SetPhase(PHASE_2);
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->AttackStop();
|
||||
me->InterruptNonMeleeSpells(true);
|
||||
DoCastSelf(SPELL_TELEPORT, true);
|
||||
me->StopMoving();
|
||||
me->NearTeleportTo(me->GetHomePosition());
|
||||
events.ScheduleEvent(EVENT_PHASE_TWO_INTRO_1, 3s + 800ms, 0, PHASE_2);
|
||||
}
|
||||
|
||||
void SpellHitTarget(Unit* target, SpellInfo const* spell) override
|
||||
if (damage >= me->GetHealth())
|
||||
{
|
||||
if (spell->Id == SPELL_BLOSSOM_TARGETING)
|
||||
damage = me->GetHealth() - 1;
|
||||
if (!_defeated)
|
||||
{
|
||||
DoCast(target, target->GetEntry() == NPC_FIRE_BLOSSOM_BUNNY ? SPELL_FIRE_BLOSSOM : SPELL_FROST_BLOSSOM, true);
|
||||
target->CastSpell(target, target->GetEntry() == NPC_FIRE_BLOSSOM_BUNNY ? SPELL_FIRE_BLOSSOM_VISUAL : SPELL_FROST_BLOSSOM_VISUAL, true);
|
||||
}
|
||||
}
|
||||
_defeated = true;
|
||||
Talk(SAY_DEATH);
|
||||
events.Reset();
|
||||
DoCastSelf(SPELL_ARCANE_OVERLOAD);
|
||||
events.ScheduleEvent(EVENT_KILL_SELF, 4s + 800ms);
|
||||
|
||||
void DamageTaken(Unit* /*attacker*/, uint32& damage) override
|
||||
{
|
||||
if (me->HealthBelowPctDamaged(50, damage) && !events.IsInPhase(PHASE_2))
|
||||
{
|
||||
events.SetPhase(PHASE_2);
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->AttackStop();
|
||||
me->CastStop();
|
||||
DoCastSelf(SPELL_TELEPORT, true);
|
||||
me->StopMoving();
|
||||
me->NearTeleportTo(me->GetHomePosition());
|
||||
events.ScheduleEvent(EVENT_PHASE_TWO_INTRO_1, Seconds(3) + Milliseconds(600));
|
||||
}
|
||||
|
||||
if (damage >= me->GetHealth() && !_allowKill)
|
||||
{
|
||||
damage = me->GetHealth() - 1;
|
||||
if (!_killed)
|
||||
// We really need this here because there are more of those triggers in the instance...
|
||||
std::list<Creature*> units;
|
||||
GetCreatureListWithEntryInGrid(units, me, NPC_GENERAL_PURPOSE_BUNNY_L2, 30.0f);
|
||||
if (!units.empty())
|
||||
{
|
||||
_killed = true;
|
||||
Talk(SAY_DEATH);
|
||||
events.CancelEvent(EVENT_BLOSSOM_TARGETING);
|
||||
DoCastSelf(SPELL_ARCANE_OVERLOAD, true);
|
||||
events.ScheduleEvent(EVENT_ARCANE_OVERLOAD, Seconds(6));
|
||||
// We really need this here because there are more of those triggers in the instance...
|
||||
for (auto itr = units.begin(); itr != units.end(); ++itr)
|
||||
{
|
||||
if ((*itr)->GetHomePosition().GetExactDist(leftSideDistanceCheck) <= 20.0f)
|
||||
(*itr)->CastSpell((*itr), SPELL_ARCANE_FROST_BEAM);
|
||||
else
|
||||
(*itr)->CastSpell((*itr), SPELL_ARCANE_FIRE_BEAM);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32 GetData(uint32 type) const override
|
||||
{
|
||||
if (type == DATA_CURRENT_BLOSSOM)
|
||||
return _nextBlossomBunny;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_BLINK:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 50.0f, true, 0))
|
||||
{
|
||||
DoCast(target, SPELL_BLINK);
|
||||
if (IsHeroic())
|
||||
me->getThreatManager().resetAllAggro();
|
||||
|
||||
events.ScheduleEvent(EVENT_ELEMENTAL_FISTS, 800ms, 0, PHASE_1);
|
||||
events.Repeat(13s, 14s);
|
||||
}
|
||||
break;
|
||||
case EVENT_ELEMENTAL_FISTS:
|
||||
Talk(_lastFists == FISTS_OF_FLAME ? SAY_FISTS_OF_FROST : SAY_FISTS_OF_FLAME);
|
||||
DoCastSelf(_lastFists == FISTS_OF_FLAME ? SPELL_FISTS_OF_FROST : SPELL_FISTS_OF_FLAME);
|
||||
_lastFists = _lastFists == FISTS_OF_FLAME ? FISTS_OF_FROST : SPELL_FISTS_OF_FLAME;
|
||||
break;
|
||||
case EVENT_PHASE_TWO_INTRO_1:
|
||||
Talk(SAY_PHASE_TWO_INTRO_1);
|
||||
DoCastSelf(SPELL_EMOTE_TALK, true);
|
||||
events.ScheduleEvent(EVENT_PHASE_TWO_INTRO_2, 2s + 400ms, 0, PHASE_2);
|
||||
break;
|
||||
case EVENT_PHASE_TWO_INTRO_2:
|
||||
Talk(SAY_PHASE_TWO_INTRO_2);
|
||||
DoCastSelf(SPELL_EMOTE_ROAR, true);
|
||||
events.ScheduleEvent(EVENT_ARCANE_POWER, 2s + 400ms, 0, PHASE_2);
|
||||
break;
|
||||
case EVENT_ARCANE_POWER:
|
||||
{
|
||||
Talk(SAY_ARCANE_POWER);
|
||||
DoCastSelf(SPELL_ARCANE_POWER);
|
||||
me->SetDisableGravity(true);
|
||||
me->SendSetPlayHoverAnim(true);
|
||||
|
||||
Movement::MoveSplineInit init(me);
|
||||
init.MoveTo(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 2.0f, false);
|
||||
init.SetWalk(true);
|
||||
init.SetVelocity(0.8f);
|
||||
init.Launch();
|
||||
|
||||
// We really need this here because there are more of those triggers in other rooms...
|
||||
std::list<Creature*> units;
|
||||
GetCreatureListWithEntryInGrid(units, me, NPC_GENERAL_PURPOSE_BUNNY_L2, 30.0f);
|
||||
if (!units.empty())
|
||||
@@ -225,199 +289,106 @@ public:
|
||||
(*itr)->CastSpell((*itr), SPELL_ARCANE_FIRE_BEAM);
|
||||
}
|
||||
}
|
||||
events.ScheduleEvent(EVENT_STUN_SELF, 2s + 200ms, 0, PHASE_2);
|
||||
events.ScheduleEvent(EVENT_BLOSSOM_TARGETING, 6s, 0, PHASE_2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32 GetData(uint32 type) const override
|
||||
{
|
||||
if (type == DATA_CURRENT_BLOSSOM)
|
||||
return _nextBlossomBunny;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_BLINK:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 50.0f, true, 0))
|
||||
{
|
||||
DoCast(target, SPELL_BLINK);
|
||||
if (IsHeroic())
|
||||
me->getThreatManager().resetAllAggro();
|
||||
|
||||
events.ScheduleEvent(EVENT_ELEMENTAL_FISTS, Milliseconds(800), 0, PHASE_1);
|
||||
events.Repeat(Seconds(13) + Milliseconds(300));
|
||||
}
|
||||
break;
|
||||
case EVENT_ELEMENTAL_FISTS:
|
||||
switch (_lastFists)
|
||||
{
|
||||
case FISTS_OF_FLAME:
|
||||
Talk(SAY_FISTS_OF_FROST);
|
||||
DoCastSelf(SPELL_FISTS_OF_FROST);
|
||||
_lastFists = FISTS_OF_FROST;
|
||||
break;
|
||||
case FISTS_OF_FROST:
|
||||
Talk(SAY_FISTS_OF_FLAME);
|
||||
DoCastSelf(SPELL_FISTS_OF_FLAME);
|
||||
_lastFists = FISTS_OF_FLAME;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case EVENT_PHASE_TWO_INTRO_1:
|
||||
Talk(SAY_PHASE_TWO_INTRO_1);
|
||||
DoCastSelf(SPELL_EMOTE_TALK, true);
|
||||
events.ScheduleEvent(EVENT_PHASE_TWO_INTRO_2, Seconds(2) + Milliseconds(400));
|
||||
break;
|
||||
case EVENT_PHASE_TWO_INTRO_2:
|
||||
Talk(SAY_PHASE_TWO_INTRO_2);
|
||||
DoCastSelf(SPELL_EMOTE_ROAR, true);
|
||||
events.ScheduleEvent(EVENT_ARCANE_POWER, Seconds(2) + Milliseconds(400));
|
||||
break;
|
||||
case EVENT_ARCANE_POWER:
|
||||
case EVENT_STUN_SELF:
|
||||
DoCastSelf(SPELL_STUN_SELF);
|
||||
if (IsHeroic())
|
||||
events.ScheduleEvent(EVENT_ANNOUNCE_FIRE_WALL, 1s + 500ms, 0, PHASE_2);
|
||||
break;
|
||||
case EVENT_ANNOUNCE_FIRE_WALL:
|
||||
Talk(SAY_ANNOUNCE_FIRE_WALL);
|
||||
events.ScheduleEvent(EVENT_FIRE_WALL, 1s + 400ms, 0, PHASE_2);
|
||||
break;
|
||||
case EVENT_FIRE_WALL:
|
||||
for (ObjectGuid guid : _firewallDummyGUIDs)
|
||||
{
|
||||
Talk(SAY_ARCANE_POWER);
|
||||
DoCastSelf(SPELL_ARCANE_POWER);
|
||||
me->SetHover(true);
|
||||
|
||||
// We really need this here because there are more of those triggers in other rooms...
|
||||
std::list<Creature*> units;
|
||||
GetCreatureListWithEntryInGrid(units, me, NPC_GENERAL_PURPOSE_BUNNY_L2, 30.0f);
|
||||
if (!units.empty())
|
||||
{
|
||||
for (auto itr = units.begin(); itr != units.end(); ++itr)
|
||||
{
|
||||
if ((*itr)->GetHomePosition().GetExactDist(leftSideDistanceCheck) <= 20.0f)
|
||||
(*itr)->CastSpell((*itr), SPELL_ARCANE_FROST_BEAM);
|
||||
else
|
||||
(*itr)->CastSpell((*itr), SPELL_ARCANE_FIRE_BEAM);
|
||||
}
|
||||
}
|
||||
events.ScheduleEvent(EVENT_STUN_SELF, Seconds(2) + Milliseconds(500));
|
||||
events.ScheduleEvent(EVENT_BLOSSOM_TARGETING, Seconds(6));
|
||||
break;
|
||||
if (Creature* firewallDummy = ObjectAccessor::GetCreature(*me, guid))
|
||||
firewallDummy->CastSpell(firewallDummy, SPELL_FIRE_WALL);
|
||||
}
|
||||
case EVENT_STUN_SELF:
|
||||
DoCastSelf(SPELL_STUN_SELF, true);
|
||||
if (IsHeroic())
|
||||
events.ScheduleEvent(EVENT_ANNOUNCE_FIRE_WALL, Seconds(1) + Milliseconds(500));
|
||||
break;
|
||||
case EVENT_ANNOUNCE_FIRE_WALL:
|
||||
Talk(SAY_ANNOUNCE_FIRE_WALL);
|
||||
events.ScheduleEvent(EVENT_FIRE_WALL, Seconds(1) + Milliseconds(400));
|
||||
break;
|
||||
case EVENT_FIRE_WALL:
|
||||
for (ObjectGuid guid : _firewallDummyGUIDs)
|
||||
if (Creature* firewallDummy = ObjectAccessor::GetCreature(*me, guid))
|
||||
if (firewallDummy->GetEntry() != NPC_FIREWALL_PLATTER_1A
|
||||
&& firewallDummy->GetEntry() != NPC_FIREWALL_PLATTER_1B
|
||||
&& firewallDummy->GetEntry() != NPC_FIREWALL_PLATTER_1C)
|
||||
firewallDummy->CastSpell(firewallDummy, SPELL_FIRE_WALL);
|
||||
break;
|
||||
case EVENT_ARCANE_OVERLOAD:
|
||||
me->SetHover(false);
|
||||
_allowKill = true;
|
||||
DoCastSelf(SPELL_TRANSITION_INVISIBILITY, true);
|
||||
DoCastSelf(SPELL_ARCANE_OVERLOAD_INSTAKILL, true);
|
||||
if (Creature* bunny = me->FindNearestCreature(NPC_GENERAL_PURPOSE_DUMMY_JMF, 5.0f, true))
|
||||
break;
|
||||
case EVENT_BLOSSOM_TARGETING:
|
||||
_nextBlossomBunny == NPC_FIRE_BLOSSOM_BUNNY ? NPC_FROST_BLOSSOM_BUNNY : NPC_FIRE_BLOSSOM_BUNNY;
|
||||
DoCastAOE(SPELL_BLOSSOM_TARGETING, true);
|
||||
events.Repeat(2s + 400ms);
|
||||
break;
|
||||
case EVENT_KILL_SELF:
|
||||
{
|
||||
me->KillSelf();
|
||||
Creature* creature = me;
|
||||
me->m_Events.AddEventAtOffset([creature]()
|
||||
{
|
||||
creature->CastSpell(creature, SPELL_TRANSITION_INVISIBILITY);
|
||||
creature->CastSpell(creature, SPELL_ARCANE_OVERLOAD_INSTAKILL);
|
||||
if (Creature* bunny = creature->FindNearestCreature(NPC_GENERAL_PURPOSE_DUMMY_JMF, 5.0f, true))
|
||||
bunny->CastSpell(bunny, SPELL_ARCANE_OVERLOAD_EXPLOSION);
|
||||
break;
|
||||
case EVENT_BLOSSOM_TARGETING:
|
||||
if (_nextBlossomBunny == NPC_FIRE_BLOSSOM_BUNNY)
|
||||
_nextBlossomBunny = NPC_FROST_BLOSSOM_BUNNY;
|
||||
else
|
||||
_nextBlossomBunny = NPC_FIRE_BLOSSOM_BUNNY;
|
||||
}, 1s + 600ms);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
private:
|
||||
bool _defeated;
|
||||
uint8 _lastFists;
|
||||
uint32 _nextBlossomBunny;
|
||||
GuidVector _firewallDummyGUIDs;
|
||||
};
|
||||
|
||||
DoCastAOE(SPELL_BLOSSOM_TARGETING, true);
|
||||
events.Repeat(Seconds(2) + Milliseconds(400));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
class spell_glubtok_blossom_targeting : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_glubtok_blossom_targeting);
|
||||
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
if (targets.empty())
|
||||
return;
|
||||
|
||||
if (Unit* caster = GetCaster())
|
||||
{
|
||||
if (Creature* creature = caster->ToCreature())
|
||||
{
|
||||
if (creature->IsAIEnabled)
|
||||
{
|
||||
uint32 currentBlossomEntry = creature->AI()->GetData(DATA_CURRENT_BLOSSOM);
|
||||
targets.remove_if([currentBlossomEntry](WorldObject const* obj)->bool
|
||||
{
|
||||
return obj->GetTypeId() != TYPEID_UNIT || obj->GetEntry() != currentBlossomEntry;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
private:
|
||||
bool _killed;
|
||||
bool _allowKill;
|
||||
uint8 _lastFists;
|
||||
uint32 _nextBlossomBunny;
|
||||
GuidVector _firewallDummyGUIDs;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature *creature) const override
|
||||
{
|
||||
return GetDeadminesAI<boss_glubtokAI>(creature);
|
||||
if (targets.empty())
|
||||
return;
|
||||
|
||||
Trinity::Containers::RandomResize(targets, 1);
|
||||
}
|
||||
};
|
||||
|
||||
class CreatureEntryCheck
|
||||
{
|
||||
public:
|
||||
CreatureEntryCheck(uint32 entry) : _entry(entry) { }
|
||||
|
||||
bool operator()(WorldObject* object)
|
||||
void HandleBlossomEffect(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
Unit* target = GetHitUnit();
|
||||
if (Unit* caster = GetCaster())
|
||||
{
|
||||
return (object->GetEntry() != _entry);
|
||||
caster->CastSpell(target, target->GetEntry() == NPC_FIRE_BLOSSOM_BUNNY ? SPELL_FIRE_BLOSSOM : SPELL_FROST_BLOSSOM, true);
|
||||
target->CastSpell(target, target->GetEntry() == NPC_FIRE_BLOSSOM_BUNNY ? SPELL_FIRE_BLOSSOM_VISUAL : SPELL_FROST_BLOSSOM_VISUAL, true);
|
||||
}
|
||||
private:
|
||||
uint32 _entry;
|
||||
};
|
||||
}
|
||||
|
||||
class spell_glubtok_blossom_targeting : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_glubtok_blossom_targeting() : SpellScriptLoader("spell_glubtok_blossom_targeting") { }
|
||||
|
||||
class spell_glubtok_blossom_targeting_SpellScript : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_glubtok_blossom_targeting_SpellScript);
|
||||
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
if (targets.empty())
|
||||
return;
|
||||
|
||||
if (Unit* caster = GetCaster())
|
||||
if (Creature* creature = caster->ToCreature())
|
||||
if (creature->IsAIEnabled)
|
||||
targets.remove_if(CreatureEntryCheck(creature->GetAI()->GetData(DATA_CURRENT_BLOSSOM)));
|
||||
|
||||
if (targets.empty())
|
||||
return;
|
||||
|
||||
Trinity::Containers::RandomResize(targets, 1);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_glubtok_blossom_targeting_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
{
|
||||
return new spell_glubtok_blossom_targeting_SpellScript();
|
||||
}
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_glubtok_blossom_targeting::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY);
|
||||
OnEffectHitTarget += SpellEffectFn(spell_glubtok_blossom_targeting::HandleBlossomEffect, EFFECT_0, SPELL_EFFECT_APPLY_AURA);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_glubtok()
|
||||
{
|
||||
new boss_glubtok();
|
||||
new spell_glubtok_blossom_targeting();
|
||||
RegisterDeadminesCreatureAI(boss_glubtok);
|
||||
RegisterSpellScript(spell_glubtok_blossom_targeting);
|
||||
}
|
||||
|
||||
@@ -546,4 +546,7 @@ AI* GetDeadminesAI(GameObject* go)
|
||||
return GetInstanceAI<AI>(go, DMScriptName);
|
||||
}
|
||||
|
||||
#define RegisterDeadminesCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetDeadminesAI)
|
||||
|
||||
// DEADMINES_H_
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user