aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp1042
1 files changed, 473 insertions, 569 deletions
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp
index 7caff89ce37..fcbbf37c0cc 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp
@@ -129,643 +129,542 @@ class BoneSpikeTargetSelector
UnitAI* _ai;
};
-class boss_lord_marrowgar : public CreatureScript
+struct boss_lord_marrowgar : public BossAI
{
- public:
- boss_lord_marrowgar() : CreatureScript("boss_lord_marrowgar") { }
-
- struct boss_lord_marrowgarAI : public BossAI
+ boss_lord_marrowgar(Creature* creature) : BossAI(creature, DATA_LORD_MARROWGAR)
+ {
+ _boneStormDuration = RAID_MODE(20s, 30s, 20s, 30s);
+ _baseSpeed = creature->GetSpeedRate(MOVE_RUN);
+ _coldflameLastPos.Relocate(creature);
+ _boneSlice = false;
+ }
+
+ void Reset() override
+ {
+ _Reset();
+ me->SetSpeedRate(MOVE_RUN, _baseSpeed);
+ me->RemoveAurasDueToSpell(SPELL_BONE_STORM);
+ me->RemoveAurasDueToSpell(SPELL_BERSERK);
+ events.ScheduleEvent(EVENT_ENABLE_BONE_SLICE, 10s);
+ events.ScheduleEvent(EVENT_BONE_SPIKE_GRAVEYARD, 15s, EVENT_GROUP_SPECIAL);
+ events.ScheduleEvent(EVENT_COLDFLAME, 5s, EVENT_GROUP_SPECIAL);
+ events.ScheduleEvent(EVENT_WARN_BONE_STORM, 45s, 50s);
+ events.ScheduleEvent(EVENT_ENRAGE, 10min);
+ _boneSlice = false;
+ _boneSpikeImmune.clear();
+ }
+
+ void JustEngagedWith(Unit* /*who*/) override
+ {
+ Talk(SAY_AGGRO);
+
+ me->setActive(true);
+ DoZoneInCombat();
+ instance->SetBossState(DATA_LORD_MARROWGAR, IN_PROGRESS);
+ }
+
+ void JustDied(Unit* /*killer*/) override
+ {
+ Talk(SAY_DEATH);
+
+ _JustDied();
+ }
+
+ void JustReachedHome() override
+ {
+ _JustReachedHome();
+ instance->SetBossState(DATA_LORD_MARROWGAR, FAIL);
+ instance->SetData(DATA_BONED_ACHIEVEMENT, uint32(true)); // reset
+ }
+
+ void KilledUnit(Unit* victim) override
+ {
+ if (victim->GetTypeId() == TYPEID_PLAYER)
+ Talk(SAY_KILL);
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
{
- boss_lord_marrowgarAI(Creature* creature) : BossAI(creature, DATA_LORD_MARROWGAR)
- {
- _boneStormDuration = RAID_MODE(20s, 30s, 20s, 30s);
- _baseSpeed = creature->GetSpeedRate(MOVE_RUN);
- _coldflameLastPos.Relocate(creature);
- _boneSlice = false;
- }
-
- void Reset() override
- {
- _Reset();
- me->SetSpeedRate(MOVE_RUN, _baseSpeed);
- me->RemoveAurasDueToSpell(SPELL_BONE_STORM);
- me->RemoveAurasDueToSpell(SPELL_BERSERK);
- events.ScheduleEvent(EVENT_ENABLE_BONE_SLICE, 10s);
- events.ScheduleEvent(EVENT_BONE_SPIKE_GRAVEYARD, 15s, EVENT_GROUP_SPECIAL);
- events.ScheduleEvent(EVENT_COLDFLAME, 5s, EVENT_GROUP_SPECIAL);
- events.ScheduleEvent(EVENT_WARN_BONE_STORM, 45s, 50s);
- events.ScheduleEvent(EVENT_ENRAGE, 10min);
- _boneSlice = false;
- _boneSpikeImmune.clear();
- }
-
- void JustEngagedWith(Unit* /*who*/) override
- {
- Talk(SAY_AGGRO);
-
- me->setActive(true);
- DoZoneInCombat();
- instance->SetBossState(DATA_LORD_MARROWGAR, IN_PROGRESS);
- }
-
- void JustDied(Unit* /*killer*/) override
- {
- Talk(SAY_DEATH);
-
- _JustDied();
- }
-
- void JustReachedHome() override
- {
- _JustReachedHome();
- instance->SetBossState(DATA_LORD_MARROWGAR, FAIL);
- instance->SetData(DATA_BONED_ACHIEVEMENT, uint32(true)); // reset
- }
-
- void KilledUnit(Unit* victim) override
- {
- if (victim->GetTypeId() == TYPEID_PLAYER)
- Talk(SAY_KILL);
- }
-
- 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_BONE_SPIKE_GRAVEYARD:
+ if (IsHeroic() || !me->HasAura(SPELL_BONE_STORM))
+ DoCast(me, SPELL_BONE_SPIKE_GRAVEYARD);
+ events.ScheduleEvent(EVENT_BONE_SPIKE_GRAVEYARD, 15s, 20s, EVENT_GROUP_SPECIAL);
+ break;
+ case EVENT_COLDFLAME:
+ _coldflameLastPos.Relocate(me);
+ _coldflameTarget.Clear();
+ if (!me->HasAura(SPELL_BONE_STORM))
+ DoCastAOE(SPELL_COLDFLAME_NORMAL);
+ else
+ DoCast(me, SPELL_COLDFLAME_BONE_STORM);
+ events.ScheduleEvent(EVENT_COLDFLAME, 5s, EVENT_GROUP_SPECIAL);
+ break;
+ case EVENT_WARN_BONE_STORM:
+ _boneSlice = false;
+ Talk(EMOTE_BONE_STORM);
+ me->FinishSpell(CURRENT_MELEE_SPELL, false);
+ DoCast(me, SPELL_BONE_STORM);
+ events.DelayEvents(3s, EVENT_GROUP_SPECIAL);
+ events.ScheduleEvent(EVENT_BONE_STORM_BEGIN, 3050ms);
+ events.ScheduleEvent(EVENT_WARN_BONE_STORM, 90s, 95s);
+ break;
+ case EVENT_BONE_STORM_BEGIN:
+ if (Aura* pStorm = me->GetAura(SPELL_BONE_STORM))
+ pStorm->SetDuration(int32(_boneStormDuration.count()));
+ me->SetSpeedRate(MOVE_RUN, _baseSpeed*3.0f);
+ Talk(SAY_BONE_STORM);
+ events.ScheduleEvent(EVENT_BONE_STORM_END, _boneStormDuration + 1ms);
+ [[fallthrough]];
+ case EVENT_BONE_STORM_MOVE:
{
- switch (eventId)
+ events.ScheduleEvent(EVENT_BONE_STORM_MOVE, _boneStormDuration/3);
+ Unit* unit = SelectTarget(SelectTargetMethod::Random, 0, NonTankTargetSelector(me));
+ if (!unit)
+ unit = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true);
+ if (unit)
+ me->GetMotionMaster()->MovePoint(POINT_TARGET_BONESTORM_PLAYER, *unit);
+ break;
+ }
+ case EVENT_BONE_STORM_END:
+ if (MovementGenerator* movement = me->GetMotionMaster()->GetMovementGenerator([](MovementGenerator const* a) -> bool
{
- case EVENT_BONE_SPIKE_GRAVEYARD:
- if (IsHeroic() || !me->HasAura(SPELL_BONE_STORM))
- DoCast(me, SPELL_BONE_SPIKE_GRAVEYARD);
- events.ScheduleEvent(EVENT_BONE_SPIKE_GRAVEYARD, 15s, 20s, EVENT_GROUP_SPECIAL);
- break;
- case EVENT_COLDFLAME:
- _coldflameLastPos.Relocate(me);
- _coldflameTarget.Clear();
- if (!me->HasAura(SPELL_BONE_STORM))
- DoCastAOE(SPELL_COLDFLAME_NORMAL);
- else
- DoCast(me, SPELL_COLDFLAME_BONE_STORM);
- events.ScheduleEvent(EVENT_COLDFLAME, 5s, EVENT_GROUP_SPECIAL);
- break;
- case EVENT_WARN_BONE_STORM:
- _boneSlice = false;
- Talk(EMOTE_BONE_STORM);
- me->FinishSpell(CURRENT_MELEE_SPELL, false);
- DoCast(me, SPELL_BONE_STORM);
- events.DelayEvents(3s, EVENT_GROUP_SPECIAL);
- events.ScheduleEvent(EVENT_BONE_STORM_BEGIN, 3050ms);
- events.ScheduleEvent(EVENT_WARN_BONE_STORM, 90s, 95s);
- break;
- case EVENT_BONE_STORM_BEGIN:
- if (Aura* pStorm = me->GetAura(SPELL_BONE_STORM))
- pStorm->SetDuration(int32(_boneStormDuration.count()));
- me->SetSpeedRate(MOVE_RUN, _baseSpeed*3.0f);
- Talk(SAY_BONE_STORM);
- events.ScheduleEvent(EVENT_BONE_STORM_END, _boneStormDuration + 1ms);
- [[fallthrough]];
- case EVENT_BONE_STORM_MOVE:
+ if (a->GetMovementGeneratorType() == POINT_MOTION_TYPE)
{
- events.ScheduleEvent(EVENT_BONE_STORM_MOVE, _boneStormDuration/3);
- Unit* unit = SelectTarget(SelectTargetMethod::Random, 0, NonTankTargetSelector(me));
- if (!unit)
- unit = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true);
- if (unit)
- me->GetMotionMaster()->MovePoint(POINT_TARGET_BONESTORM_PLAYER, *unit);
- break;
+ PointMovementGenerator<Creature> const* pointMovement = dynamic_cast<PointMovementGenerator<Creature> const*>(a);
+ return pointMovement && pointMovement->GetId() == POINT_TARGET_BONESTORM_PLAYER;
}
- case EVENT_BONE_STORM_END:
- if (MovementGenerator* movement = me->GetMotionMaster()->GetMovementGenerator([](MovementGenerator const* a) -> bool
- {
- if (a->GetMovementGeneratorType() == POINT_MOTION_TYPE)
- {
- PointMovementGenerator<Creature> const* pointMovement = dynamic_cast<PointMovementGenerator<Creature> const*>(a);
- return pointMovement && pointMovement->GetId() == POINT_TARGET_BONESTORM_PLAYER;
- }
- return false;
- }))
- me->GetMotionMaster()->Remove(movement);
- me->GetMotionMaster()->MoveChase(me->GetVictim());
- me->SetSpeedRate(MOVE_RUN, _baseSpeed);
- events.CancelEvent(EVENT_BONE_STORM_MOVE);
- events.ScheduleEvent(EVENT_ENABLE_BONE_SLICE, 10s);
- if (!IsHeroic())
- events.RescheduleEvent(EVENT_BONE_SPIKE_GRAVEYARD, 15s, EVENT_GROUP_SPECIAL);
- break;
- case EVENT_ENABLE_BONE_SLICE:
- _boneSlice = true;
- break;
- case EVENT_ENRAGE:
- DoCast(me, SPELL_BERSERK, true);
- Talk(SAY_BERSERK);
- break;
- }
+ return false;
+ }))
+ me->GetMotionMaster()->Remove(movement);
+ me->GetMotionMaster()->MoveChase(me->GetVictim());
+ me->SetSpeedRate(MOVE_RUN, _baseSpeed);
+ events.CancelEvent(EVENT_BONE_STORM_MOVE);
+ events.ScheduleEvent(EVENT_ENABLE_BONE_SLICE, 10s);
+ if (!IsHeroic())
+ events.RescheduleEvent(EVENT_BONE_SPIKE_GRAVEYARD, 15s, EVENT_GROUP_SPECIAL);
+ break;
+ case EVENT_ENABLE_BONE_SLICE:
+ _boneSlice = true;
+ break;
+ case EVENT_ENRAGE:
+ DoCast(me, SPELL_BERSERK, true);
+ Talk(SAY_BERSERK);
+ break;
+ }
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+ }
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
- }
+ // We should not melee attack when storming
+ if (me->HasAura(SPELL_BONE_STORM))
+ return;
- // We should not melee attack when storming
- if (me->HasAura(SPELL_BONE_STORM))
- return;
+ // 10 seconds since encounter start Bone Slice replaces melee attacks
+ if (_boneSlice && !me->GetCurrentSpell(CURRENT_MELEE_SPELL))
+ DoCastVictim(SPELL_BONE_SLICE);
- // 10 seconds since encounter start Bone Slice replaces melee attacks
- if (_boneSlice && !me->GetCurrentSpell(CURRENT_MELEE_SPELL))
- DoCastVictim(SPELL_BONE_SLICE);
+ DoMeleeAttackIfReady();
+ }
- DoMeleeAttackIfReady();
- }
+ void MovementInform(uint32 type, uint32 id) override
+ {
+ if (type != POINT_MOTION_TYPE || id != POINT_TARGET_BONESTORM_PLAYER)
+ return;
- void MovementInform(uint32 type, uint32 id) override
- {
- if (type != POINT_MOTION_TYPE || id != POINT_TARGET_BONESTORM_PLAYER)
- return;
+ // lock movement
+ me->GetMotionMaster()->MoveIdle();
+ }
- // lock movement
- me->GetMotionMaster()->MoveIdle();
- }
+ Position const* GetLastColdflamePosition() const
+ {
+ return &_coldflameLastPos;
+ }
- Position const* GetLastColdflamePosition() const
+ ObjectGuid GetGUID(int32 type /*= 0 */) const override
+ {
+ switch (type)
+ {
+ case DATA_COLDFLAME_GUID:
+ return _coldflameTarget;
+ case DATA_SPIKE_IMMUNE + 0:
+ case DATA_SPIKE_IMMUNE + 1:
+ case DATA_SPIKE_IMMUNE + 2:
{
- return &_coldflameLastPos;
- }
+ uint32 index = uint32(type - DATA_SPIKE_IMMUNE);
+ if (index < _boneSpikeImmune.size())
+ return _boneSpikeImmune[index];
- ObjectGuid GetGUID(int32 type /*= 0 */) const override
- {
- switch (type)
- {
- case DATA_COLDFLAME_GUID:
- return _coldflameTarget;
- case DATA_SPIKE_IMMUNE + 0:
- case DATA_SPIKE_IMMUNE + 1:
- case DATA_SPIKE_IMMUNE + 2:
- {
- uint32 index = uint32(type - DATA_SPIKE_IMMUNE);
- if (index < _boneSpikeImmune.size())
- return _boneSpikeImmune[index];
-
- break;
- }
- }
-
- return ObjectGuid::Empty;
+ break;
}
+ }
- void SetGUID(ObjectGuid const& guid, int32 id) override
- {
- switch (id)
- {
- case DATA_COLDFLAME_GUID:
- _coldflameTarget = guid;
- break;
- case DATA_SPIKE_IMMUNE:
- _boneSpikeImmune.push_back(guid);
- break;
- }
- }
+ return ObjectGuid::Empty;
+ }
- void DoAction(int32 action) override
- {
- switch (action)
- {
- case ACTION_CLEAR_SPIKE_IMMUNITIES:
- _boneSpikeImmune.clear();
- break;
- case ACTION_TALK_ENTER_ZONE:
- if (me->IsAlive())
- Talk(SAY_ENTER_ZONE);
- break;
- default:
- break;
- }
- }
-
- private:
- Position _coldflameLastPos;
- GuidVector _boneSpikeImmune;
- ObjectGuid _coldflameTarget;
- Milliseconds _boneStormDuration;
- float _baseSpeed;
- bool _boneSlice;
- };
+ void SetGUID(ObjectGuid const& guid, int32 id) override
+ {
+ switch (id)
+ {
+ case DATA_COLDFLAME_GUID:
+ _coldflameTarget = guid;
+ break;
+ case DATA_SPIKE_IMMUNE:
+ _boneSpikeImmune.push_back(guid);
+ break;
+ }
+ }
- CreatureAI* GetAI(Creature* creature) const override
+ void DoAction(int32 action) override
+ {
+ switch (action)
{
- return GetIcecrownCitadelAI<boss_lord_marrowgarAI>(creature);
+ case ACTION_CLEAR_SPIKE_IMMUNITIES:
+ _boneSpikeImmune.clear();
+ break;
+ case ACTION_TALK_ENTER_ZONE:
+ if (me->IsAlive())
+ Talk(SAY_ENTER_ZONE);
+ break;
+ default:
+ break;
}
+ }
+
+private:
+ Position _coldflameLastPos;
+ GuidVector _boneSpikeImmune;
+ ObjectGuid _coldflameTarget;
+ Milliseconds _boneStormDuration;
+ float _baseSpeed;
+ bool _boneSlice;
};
-typedef boss_lord_marrowgar::boss_lord_marrowgarAI MarrowgarAI;
+typedef boss_lord_marrowgar MarrowgarAI;
-class npc_coldflame : public CreatureScript
+struct npc_coldflame : public ScriptedAI
{
- public:
- npc_coldflame() : CreatureScript("npc_coldflame") { }
-
- struct npc_coldflameAI : public ScriptedAI
- {
- npc_coldflameAI(Creature* creature) : ScriptedAI(creature)
- {
- }
-
- void IsSummonedBy(WorldObject* ownerWO) override
- {
- Creature* owner = ownerWO->ToCreature();
- if (!owner)
- return;
-
- Position pos;
- if (MarrowgarAI* marrowgarAI = CAST_AI(MarrowgarAI, owner->GetAI()))
- pos.Relocate(marrowgarAI->GetLastColdflamePosition());
- else
- pos.Relocate(owner);
-
- if (owner->HasAura(SPELL_BONE_STORM))
- {
- float ang = pos.GetAbsoluteAngle(me);
- me->SetOrientation(ang);
- owner->GetNearPoint2D(nullptr, pos.m_positionX, pos.m_positionY, 5.0f - owner->GetCombatReach(), ang);
- }
- else
- {
- Player* target = ObjectAccessor::GetPlayer(*owner, owner->GetAI()->GetGUID(DATA_COLDFLAME_GUID));
- if (!target)
- {
- me->DespawnOrUnsummon();
- return;
- }
-
- float ang = pos.GetAbsoluteAngle(target);
- me->SetOrientation(ang);
- owner->GetNearPoint2D(nullptr, pos.m_positionX, pos.m_positionY, 15.0f - owner->GetCombatReach(), ang);
- }
-
- me->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), me->GetPositionZ(), me->GetOrientation());
- DoCast(SPELL_COLDFLAME_SUMMON);
- _events.ScheduleEvent(EVENT_COLDFLAME_TRIGGER, 500ms);
- }
-
- void UpdateAI(uint32 diff) override
- {
- _events.Update(diff);
+ npc_coldflame(Creature* creature) : ScriptedAI(creature) { }
- if (_events.ExecuteEvent() == EVENT_COLDFLAME_TRIGGER)
- {
- Position newPos = me->GetNearPosition(5.0f, 0.0f);
- me->NearTeleportTo(newPos.GetPositionX(), newPos.GetPositionY(), me->GetPositionZ(), me->GetOrientation());
- DoCast(SPELL_COLDFLAME_SUMMON);
- _events.ScheduleEvent(EVENT_COLDFLAME_TRIGGER, 500ms);
- }
- }
+ void IsSummonedBy(WorldObject* ownerWO) override
+ {
+ Creature* owner = ownerWO->ToCreature();
+ if (!owner)
+ return;
- private:
- EventMap _events;
- };
+ Position pos;
+ if (MarrowgarAI* marrowgarAI = CAST_AI(MarrowgarAI, owner->GetAI()))
+ pos.Relocate(marrowgarAI->GetLastColdflamePosition());
+ else
+ pos.Relocate(owner);
- CreatureAI* GetAI(Creature* creature) const override
+ if (owner->HasAura(SPELL_BONE_STORM))
{
- return GetIcecrownCitadelAI<npc_coldflameAI>(creature);
+ float ang = pos.GetAbsoluteAngle(me);
+ me->SetOrientation(ang);
+ owner->GetNearPoint2D(nullptr, pos.m_positionX, pos.m_positionY, 5.0f - owner->GetCombatReach(), ang);
}
-};
-
-class npc_bone_spike : public CreatureScript
-{
- public:
- npc_bone_spike() : CreatureScript("npc_bone_spike") { }
-
- struct npc_bone_spikeAI : public ScriptedAI
+ else
{
- npc_bone_spikeAI(Creature* creature) : ScriptedAI(creature), _hasTrappedUnit(false)
- {
- ASSERT(creature->GetVehicleKit());
-
- SetCombatMovement(false);
- }
-
- void JustDied(Unit* /*killer*/) override
- {
- if (TempSummon* summ = me->ToTempSummon())
- if (Unit* trapped = summ->GetSummonerUnit())
- trapped->RemoveAurasDueToSpell(SPELL_IMPALED);
-
- me->DespawnOrUnsummon();
- }
-
- void KilledUnit(Unit* victim) override
+ Player* target = ObjectAccessor::GetPlayer(*owner, owner->GetAI()->GetGUID(DATA_COLDFLAME_GUID));
+ if (!target)
{
me->DespawnOrUnsummon();
- victim->RemoveAurasDueToSpell(SPELL_IMPALED);
- }
-
- void IsSummonedBy(WorldObject* summonerWO) override
- {
- Unit* summoner = summonerWO->ToUnit();
- if (!summoner)
- return;
- DoCast(summoner, SPELL_IMPALED);
- summoner->CastSpell(me, SPELL_RIDE_VEHICLE, true);
- _events.ScheduleEvent(EVENT_FAIL_BONED, 8s);
- _hasTrappedUnit = true;
- }
-
- void PassengerBoarded(Unit* passenger, int8 /*seat*/, bool apply) override
- {
- if (!apply)
- return;
-
- /// @HACK - Change passenger offset to the one taken directly from sniffs
- /// Remove this when proper calculations are implemented.
- /// This fixes healing spiked people
- Movement::MoveSplineInit init(passenger);
- init.DisableTransportPathTransformations();
- init.MoveTo(-0.02206125f, -0.02132235f, 5.514783f, false);
- passenger->GetMotionMaster()->LaunchMoveSpline(std::move(init), EVENT_VEHICLE_BOARD, MOTION_PRIORITY_HIGHEST);
+ return;
}
- void UpdateAI(uint32 diff) override
- {
- if (!_hasTrappedUnit)
- return;
-
- _events.Update(diff);
+ float ang = pos.GetAbsoluteAngle(target);
+ me->SetOrientation(ang);
+ owner->GetNearPoint2D(nullptr, pos.m_positionX, pos.m_positionY, 15.0f - owner->GetCombatReach(), ang);
+ }
- if (_events.ExecuteEvent() == EVENT_FAIL_BONED)
- if (InstanceScript* instance = me->GetInstanceScript())
- instance->SetData(DATA_BONED_ACHIEVEMENT, uint32(false));
- }
+ me->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), me->GetPositionZ(), me->GetOrientation());
+ DoCast(SPELL_COLDFLAME_SUMMON);
+ _events.ScheduleEvent(EVENT_COLDFLAME_TRIGGER, 500ms);
+ }
- private:
- EventMap _events;
- bool _hasTrappedUnit;
- };
+ void UpdateAI(uint32 diff) override
+ {
+ _events.Update(diff);
- CreatureAI* GetAI(Creature* creature) const override
+ if (_events.ExecuteEvent() == EVENT_COLDFLAME_TRIGGER)
{
- return GetIcecrownCitadelAI<npc_bone_spikeAI>(creature);
+ Position newPos = me->GetNearPosition(5.0f, 0.0f);
+ me->NearTeleportTo(newPos.GetPositionX(), newPos.GetPositionY(), me->GetPositionZ(), me->GetOrientation());
+ DoCast(SPELL_COLDFLAME_SUMMON);
+ _events.ScheduleEvent(EVENT_COLDFLAME_TRIGGER, 500ms);
}
+ }
+
+private:
+ EventMap _events;
};
-class spell_marrowgar_coldflame : public SpellScriptLoader
+struct npc_bone_spike : public ScriptedAI
{
- public:
- spell_marrowgar_coldflame() : SpellScriptLoader("spell_marrowgar_coldflame") { }
-
- class spell_marrowgar_coldflame_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_marrowgar_coldflame_SpellScript);
-
- void SelectTarget(std::list<WorldObject*>& targets)
- {
- targets.clear();
- // select any unit but not the tank
- Unit* target = GetCaster()->GetAI()->SelectTarget(SelectTargetMethod::Random, 0, -GetCaster()->GetCombatReach(), true, false, -SPELL_IMPALED);
- if (!target)
- target = GetCaster()->GetAI()->SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true); // or the tank if its solo
- if (!target)
- return;
-
- GetCaster()->GetAI()->SetGUID(target->GetGUID(), DATA_COLDFLAME_GUID);
- targets.push_back(target);
- }
-
- void HandleScriptEffect(SpellEffIndex effIndex)
- {
- PreventHitDefaultEffect(effIndex);
- GetCaster()->CastSpell(GetHitUnit(), uint32(GetEffectValue()), true);
- }
-
- void Register() override
- {
- OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_marrowgar_coldflame_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY);
- OnEffectHitTarget += SpellEffectFn(spell_marrowgar_coldflame_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
- }
- };
-
- SpellScript* GetSpellScript() const override
- {
- return new spell_marrowgar_coldflame_SpellScript();
- }
+ npc_bone_spike(Creature* creature) : ScriptedAI(creature), _hasTrappedUnit(false)
+ {
+ ASSERT(creature->GetVehicleKit());
+
+ SetCombatMovement(false);
+ }
+
+ void JustDied(Unit* /*killer*/) override
+ {
+ if (TempSummon* summ = me->ToTempSummon())
+ if (Unit* trapped = summ->GetSummonerUnit())
+ trapped->RemoveAurasDueToSpell(SPELL_IMPALED);
+
+ me->DespawnOrUnsummon();
+ }
+
+ void KilledUnit(Unit* victim) override
+ {
+ me->DespawnOrUnsummon();
+ victim->RemoveAurasDueToSpell(SPELL_IMPALED);
+ }
+
+ void IsSummonedBy(WorldObject* summonerWO) override
+ {
+ Unit* summoner = summonerWO->ToUnit();
+ if (!summoner)
+ return;
+ DoCast(summoner, SPELL_IMPALED);
+ summoner->CastSpell(me, SPELL_RIDE_VEHICLE, true);
+ _events.ScheduleEvent(EVENT_FAIL_BONED, 8s);
+ _hasTrappedUnit = true;
+ }
+
+ void PassengerBoarded(Unit* passenger, int8 /*seat*/, bool apply) override
+ {
+ if (!apply)
+ return;
+
+ /// @HACK - Change passenger offset to the one taken directly from sniffs
+ /// Remove this when proper calculations are implemented.
+ /// This fixes healing spiked people
+ Movement::MoveSplineInit init(passenger);
+ init.DisableTransportPathTransformations();
+ init.MoveTo(-0.02206125f, -0.02132235f, 5.514783f, false);
+ passenger->GetMotionMaster()->LaunchMoveSpline(std::move(init), EVENT_VEHICLE_BOARD, MOTION_PRIORITY_HIGHEST);
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!_hasTrappedUnit)
+ return;
+
+ _events.Update(diff);
+
+ if (_events.ExecuteEvent() == EVENT_FAIL_BONED)
+ if (InstanceScript* instance = me->GetInstanceScript())
+ instance->SetData(DATA_BONED_ACHIEVEMENT, uint32(false));
+ }
+
+private:
+ EventMap _events;
+ bool _hasTrappedUnit;
};
-class spell_marrowgar_coldflame_bonestorm : public SpellScriptLoader
+class spell_marrowgar_coldflame : public SpellScript
{
- public:
- spell_marrowgar_coldflame_bonestorm() : SpellScriptLoader("spell_marrowgar_coldflame_bonestorm") { }
-
- class spell_marrowgar_coldflame_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_marrowgar_coldflame_SpellScript);
-
- void HandleScriptEffect(SpellEffIndex effIndex)
- {
- PreventHitDefaultEffect(effIndex);
- for (uint8 i = 0; i < 4; ++i)
- GetCaster()->CastSpell(GetHitUnit(), uint32(GetEffectValue() + i), true);
- }
-
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_marrowgar_coldflame_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
- }
- };
-
- SpellScript* GetSpellScript() const override
- {
- return new spell_marrowgar_coldflame_SpellScript();
- }
+ PrepareSpellScript(spell_marrowgar_coldflame);
+
+ void SelectTarget(std::list<WorldObject*>& targets)
+ {
+ targets.clear();
+ // select any unit but not the tank
+ Unit* target = GetCaster()->GetAI()->SelectTarget(SelectTargetMethod::Random, 0, -GetCaster()->GetCombatReach(), true, false, -SPELL_IMPALED);
+ if (!target)
+ target = GetCaster()->GetAI()->SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true); // or the tank if its solo
+ if (!target)
+ return;
+
+ GetCaster()->GetAI()->SetGUID(target->GetGUID(), DATA_COLDFLAME_GUID);
+ targets.push_back(target);
+ }
+
+ void HandleScriptEffect(SpellEffIndex effIndex)
+ {
+ PreventHitDefaultEffect(effIndex);
+ GetCaster()->CastSpell(GetHitUnit(), uint32(GetEffectValue()), true);
+ }
+
+ void Register() override
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_marrowgar_coldflame::SelectTarget, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY);
+ OnEffectHitTarget += SpellEffectFn(spell_marrowgar_coldflame::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
};
-class spell_marrowgar_coldflame_damage : public SpellScriptLoader
+class spell_marrowgar_coldflame_bonestorm : public SpellScript
{
- public:
- spell_marrowgar_coldflame_damage() : SpellScriptLoader("spell_marrowgar_coldflame_damage") { }
+ PrepareSpellScript(spell_marrowgar_coldflame_bonestorm);
+
+ void HandleScriptEffect(SpellEffIndex effIndex)
+ {
+ PreventHitDefaultEffect(effIndex);
+ for (uint8 i = 0; i < 4; ++i)
+ GetCaster()->CastSpell(GetHitUnit(), uint32(GetEffectValue() + i), true);
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_marrowgar_coldflame_bonestorm::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+};
- class spell_marrowgar_coldflame_damage_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_marrowgar_coldflame_damage_AuraScript);
+class spell_marrowgar_coldflame_damage : public AuraScript
+{
+ PrepareAuraScript(spell_marrowgar_coldflame_damage);
- bool CanBeAppliedOn(Unit* target)
- {
- if (target->HasAura(SPELL_IMPALED))
- return false;
+ bool CanBeAppliedOn(Unit* target)
+ {
+ if (target->HasAura(SPELL_IMPALED))
+ return false;
- if (target->GetExactDist2d(GetOwner()) > GetEffectInfo(EFFECT_0).CalcRadius())
- return false;
+ if (target->GetExactDist2d(GetOwner()) > GetEffectInfo(EFFECT_0).CalcRadius())
+ return false;
- if (Aura* aur = target->GetAura(GetId()))
- if (aur->GetOwner() != GetOwner())
- return false;
-
- return true;
- }
+ if (Aura* aur = target->GetAura(GetId()))
+ if (aur->GetOwner() != GetOwner())
+ return false;
- void Register() override
- {
- DoCheckAreaTarget += AuraCheckAreaTargetFn(spell_marrowgar_coldflame_damage_AuraScript::CanBeAppliedOn);
- }
- };
+ return true;
+ }
- AuraScript* GetAuraScript() const override
- {
- return new spell_marrowgar_coldflame_damage_AuraScript();
- }
+ void Register() override
+ {
+ DoCheckAreaTarget += AuraCheckAreaTargetFn(spell_marrowgar_coldflame_damage::CanBeAppliedOn);
+ }
};
-class spell_marrowgar_bone_spike_graveyard : public SpellScriptLoader
+class spell_marrowgar_bone_spike_graveyard : public SpellScript
{
- public:
- spell_marrowgar_bone_spike_graveyard() : SpellScriptLoader("spell_marrowgar_bone_spike_graveyard") { }
-
- class spell_marrowgar_bone_spike_graveyard_SpellScript : public SpellScript
+ PrepareSpellScript(spell_marrowgar_bone_spike_graveyard);
+
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ return ValidateSpellInfo(BoneSpikeSummonId);
+ }
+
+ bool Load() override
+ {
+ return GetCaster()->GetTypeId() == TYPEID_UNIT && GetCaster()->IsAIEnabled();
+ }
+
+ SpellCastResult CheckCast()
+ {
+ return GetCaster()->GetAI()->SelectTarget(SelectTargetMethod::Random, 0, BoneSpikeTargetSelector(GetCaster()->GetAI())) ? SPELL_CAST_OK : SPELL_FAILED_NO_VALID_TARGETS;
+ }
+
+ void HandleSpikes(SpellEffIndex effIndex)
+ {
+ PreventHitDefaultEffect(effIndex);
+ if (Creature* marrowgar = GetCaster()->ToCreature())
{
- PrepareSpellScript(spell_marrowgar_bone_spike_graveyard_SpellScript);
-
- bool Validate(SpellInfo const* /*spell*/) override
- {
- return ValidateSpellInfo(BoneSpikeSummonId);
- }
+ CreatureAI* marrowgarAI = marrowgar->AI();
+ uint8 boneSpikeCount = uint8(GetCaster()->GetMap()->Is25ManRaid() ? 3 : 1);
- bool Load() override
- {
- return GetCaster()->GetTypeId() == TYPEID_UNIT && GetCaster()->IsAIEnabled();
- }
+ std::list<Unit*> targets;
+ marrowgarAI->SelectTargetList(targets, boneSpikeCount, SelectTargetMethod::Random, 1, BoneSpikeTargetSelector(marrowgarAI));
+ if (targets.empty())
+ return;
- SpellCastResult CheckCast()
+ uint32 i = 0;
+ for (std::list<Unit*>::const_iterator itr = targets.begin(); itr != targets.end(); ++itr, ++i)
{
- return GetCaster()->GetAI()->SelectTarget(SelectTargetMethod::Random, 0, BoneSpikeTargetSelector(GetCaster()->GetAI())) ? SPELL_CAST_OK : SPELL_FAILED_NO_VALID_TARGETS;
- }
-
- void HandleSpikes(SpellEffIndex effIndex)
- {
- PreventHitDefaultEffect(effIndex);
- if (Creature* marrowgar = GetCaster()->ToCreature())
+ Unit* target = *itr;
+ target->CastSpell(target, BoneSpikeSummonId[i], true);
+ if (!target->IsAlive()) // make sure we don't get any stuck spikes on dead targets
{
- CreatureAI* marrowgarAI = marrowgar->AI();
- uint8 boneSpikeCount = uint8(GetCaster()->GetMap()->Is25ManRaid() ? 3 : 1);
-
- std::list<Unit*> targets;
- marrowgarAI->SelectTargetList(targets, boneSpikeCount, SelectTargetMethod::Random, 1, BoneSpikeTargetSelector(marrowgarAI));
- if (targets.empty())
- return;
-
- uint32 i = 0;
- for (std::list<Unit*>::const_iterator itr = targets.begin(); itr != targets.end(); ++itr, ++i)
+ if (Aura* aura = target->GetAura(SPELL_IMPALED))
{
- Unit* target = *itr;
- target->CastSpell(target, BoneSpikeSummonId[i], true);
- if (!target->IsAlive()) // make sure we don't get any stuck spikes on dead targets
- {
- if (Aura* aura = target->GetAura(SPELL_IMPALED))
- {
- if (Creature* spike = ObjectAccessor::GetCreature(*target, aura->GetCasterGUID()))
- spike->DespawnOrUnsummon();
- aura->Remove();
- }
- }
+ if (Creature* spike = ObjectAccessor::GetCreature(*target, aura->GetCasterGUID()))
+ spike->DespawnOrUnsummon();
+ aura->Remove();
}
-
- marrowgarAI->Talk(SAY_BONESPIKE);
}
}
- void Register() override
- {
- OnCheckCast += SpellCheckCastFn(spell_marrowgar_bone_spike_graveyard_SpellScript::CheckCast);
- OnEffectHitTarget += SpellEffectFn(spell_marrowgar_bone_spike_graveyard_SpellScript::HandleSpikes, EFFECT_1, SPELL_EFFECT_APPLY_AURA);
- }
- };
-
- SpellScript* GetSpellScript() const override
- {
- return new spell_marrowgar_bone_spike_graveyard_SpellScript();
+ marrowgarAI->Talk(SAY_BONESPIKE);
}
+ }
+
+ void Register() override
+ {
+ OnCheckCast += SpellCheckCastFn(spell_marrowgar_bone_spike_graveyard::CheckCast);
+ OnEffectHitTarget += SpellEffectFn(spell_marrowgar_bone_spike_graveyard::HandleSpikes, EFFECT_1, SPELL_EFFECT_APPLY_AURA);
+ }
};
-class spell_marrowgar_bone_storm : public SpellScriptLoader
+class spell_marrowgar_bone_storm : public SpellScript
{
- public:
- spell_marrowgar_bone_storm() : SpellScriptLoader("spell_marrowgar_bone_storm") { }
-
- class spell_marrowgar_bone_storm_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_marrowgar_bone_storm_SpellScript);
+ PrepareSpellScript(spell_marrowgar_bone_storm);
- void RecalculateDamage()
- {
- SetHitDamage(int32(GetHitDamage() / std::max(std::sqrt(GetHitUnit()->GetExactDist2d(GetCaster())), 1.0f)));
- }
-
- void Register() override
- {
- OnHit += SpellHitFn(spell_marrowgar_bone_storm_SpellScript::RecalculateDamage);
- }
- };
+ void RecalculateDamage()
+ {
+ SetHitDamage(int32(GetHitDamage() / std::max(std::sqrt(GetHitUnit()->GetExactDist2d(GetCaster())), 1.0f)));
+ }
- SpellScript* GetSpellScript() const override
- {
- return new spell_marrowgar_bone_storm_SpellScript();
- }
+ void Register() override
+ {
+ OnHit += SpellHitFn(spell_marrowgar_bone_storm::RecalculateDamage);
+ }
};
-class spell_marrowgar_bone_slice : public SpellScriptLoader
+class spell_marrowgar_bone_slice : public SpellScript
{
- public:
- spell_marrowgar_bone_slice() : SpellScriptLoader("spell_marrowgar_bone_slice") { }
-
- class spell_marrowgar_bone_slice_SpellScript : public SpellScript
- {
- PrepareSpellScript(spell_marrowgar_bone_slice_SpellScript);
-
- public:
- spell_marrowgar_bone_slice_SpellScript()
- {
- _targetCount = 0;
- }
-
- private:
- void ClearSpikeImmunities()
- {
- GetCaster()->GetAI()->DoAction(ACTION_CLEAR_SPIKE_IMMUNITIES);
- }
-
- void CountTargets(std::list<WorldObject*>& targets)
- {
- _targetCount = std::min<uint32>(targets.size(), GetSpellInfo()->MaxAffectedTargets);
- }
-
- void SplitDamage()
- {
- // Mark the unit as hit, even if the spell missed or was dodged/parried
- GetCaster()->GetAI()->SetGUID(GetHitUnit()->GetGUID(), DATA_SPIKE_IMMUNE);
-
- if (!_targetCount)
- return; // This spell can miss all targets
-
- SetHitDamage(GetHitDamage() / _targetCount);
- }
-
- void Register() override
- {
- BeforeCast += SpellCastFn(spell_marrowgar_bone_slice_SpellScript::ClearSpikeImmunities);
- OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_marrowgar_bone_slice_SpellScript::CountTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY);
- OnHit += SpellHitFn(spell_marrowgar_bone_slice_SpellScript::SplitDamage);
- }
-
- uint32 _targetCount;
- };
-
- SpellScript* GetSpellScript() const override
- {
- return new spell_marrowgar_bone_slice_SpellScript();
- }
+ PrepareSpellScript(spell_marrowgar_bone_slice);
+
+public:
+ spell_marrowgar_bone_slice()
+ {
+ _targetCount = 0;
+ }
+
+private:
+ void ClearSpikeImmunities()
+ {
+ GetCaster()->GetAI()->DoAction(ACTION_CLEAR_SPIKE_IMMUNITIES);
+ }
+
+ void CountTargets(std::list<WorldObject*>& targets)
+ {
+ _targetCount = std::min<uint32>(targets.size(), GetSpellInfo()->MaxAffectedTargets);
+ }
+
+ void SplitDamage()
+ {
+ // Mark the unit as hit, even if the spell missed or was dodged/parried
+ GetCaster()->GetAI()->SetGUID(GetHitUnit()->GetGUID(), DATA_SPIKE_IMMUNE);
+
+ if (!_targetCount)
+ return; // This spell can miss all targets
+
+ SetHitDamage(GetHitDamage() / _targetCount);
+ }
+
+ void Register() override
+ {
+ BeforeCast += SpellCastFn(spell_marrowgar_bone_slice::ClearSpikeImmunities);
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_marrowgar_bone_slice::CountTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY);
+ OnHit += SpellHitFn(spell_marrowgar_bone_slice::SplitDamage);
+ }
+
+ uint32 _targetCount;
};
class at_lord_marrowgar_entrance : public OnlyOnceAreaTriggerScript
@@ -786,14 +685,19 @@ class at_lord_marrowgar_entrance : public OnlyOnceAreaTriggerScript
void AddSC_boss_lord_marrowgar()
{
- new boss_lord_marrowgar();
- new npc_coldflame();
- new npc_bone_spike();
- new spell_marrowgar_coldflame();
- new spell_marrowgar_coldflame_bonestorm();
- new spell_marrowgar_coldflame_damage();
- new spell_marrowgar_bone_spike_graveyard();
- new spell_marrowgar_bone_storm();
- new spell_marrowgar_bone_slice();
+ // Creatures
+ RegisterIcecrownCitadelCreatureAI(boss_lord_marrowgar);
+ RegisterIcecrownCitadelCreatureAI(npc_coldflame);
+ RegisterIcecrownCitadelCreatureAI(npc_bone_spike);
+
+ // Spells
+ RegisterSpellScript(spell_marrowgar_coldflame);
+ RegisterSpellScript(spell_marrowgar_coldflame_bonestorm);
+ RegisterSpellScript(spell_marrowgar_coldflame_damage);
+ RegisterSpellScript(spell_marrowgar_bone_spike_graveyard);
+ RegisterSpellScript(spell_marrowgar_bone_storm);
+ RegisterSpellScript(spell_marrowgar_bone_slice);
+
+ // AreaTriggers
new at_lord_marrowgar_entrance();
}