Fix some issues with the boss_four_horsemen raid code

This commit is contained in:
2024-08-18 17:32:36 -04:00
parent e65196b085
commit 73c68d4d59

View File

@@ -26,417 +26,8 @@
using namespace FourHorsemen;
enum Spells
{
SPELL_BERSERK = 26662,
// Marks
SPELL_MARK_OF_KORTHAZZ = 28832,
SPELL_MARK_OF_BLAUMEUX = 28833,
SPELL_MARK_OF_RIVENDARE = 28834,
SPELL_MARK_OF_ZELIEK = 28835,
SPELL_MARK_DAMAGE = 28836,
// Korth'azz
SPELL_KORTHAZZ_METEOR_10 = 28884,
SPELL_KORTHAZZ_METEOR_25 = 57467,
// Blaumeux
SPELL_BLAUMEUX_SHADOW_BOLT_10 = 57374,
SPELL_BLAUMEUX_SHADOW_BOLT_25 = 57464,
SPELL_BLAUMEUX_VOID_ZONE_10 = 28863,
SPELL_BLAUMEUX_VOID_ZONE_25 = 57463,
SPELL_BLAUMEUX_UNYIELDING_PAIN = 57381,
// Zeliek
SPELL_ZELIEK_HOLY_WRATH_10 = 28883,
SPELL_ZELIEK_HOLY_WRATH_25 = 57466,
SPELL_ZELIEK_HOLY_BOLT_10 = 57376,
SPELL_ZELIEK_HOLY_BOLT_25 = 57465,
SPELL_ZELIEK_CONDEMNATION = 57377,
// Rivendare
SPELL_RIVENDARE_UNHOLY_SHADOW_10 = 28882,
SPELL_RIVENDARE_UNHOLY_SHADOW_25 = 57369
};
enum Events
{
EVENT_MARK_CAST = 1,
EVENT_PRIMARY_SPELL = 2,
EVENT_SECONDARY_SPELL = 3,
EVENT_BERSERK = 4
};
enum Misc
{
// Movement
MOVE_PHASE_NONE = 0,
MOVE_PHASE_STARTED = 1,
MOVE_PHASE_FINISHED = 2,
// Horseman
HORSEMAN_ZELIEK = 0,
HORSEMAN_BLAUMEUX = 1,
HORSEMAN_RIVENDARE = 2,
HORSEMAN_KORTHAZZ = 3
};
enum FourHorsemen
{
SAY_AGGRO = 0,
SAY_TAUNT = 1,
SAY_SPECIAL = 2,
SAY_SLAY = 3,
SAY_DEATH = 4,
EMOTE_RAGECAST = 7
};
// MARKS
const uint32 TABLE_SPELL_MARK[4] = {SPELL_MARK_OF_ZELIEK, SPELL_MARK_OF_BLAUMEUX, SPELL_MARK_OF_RIVENDARE, SPELL_MARK_OF_KORTHAZZ};
// PRIMARY SPELL
const uint32 TABLE_SPELL_PRIMARY_10[4] = {SPELL_ZELIEK_HOLY_BOLT_10, SPELL_BLAUMEUX_SHADOW_BOLT_10, SPELL_RIVENDARE_UNHOLY_SHADOW_10, SPELL_KORTHAZZ_METEOR_10};
const uint32 TABLE_SPELL_PRIMARY_25[4] = {SPELL_ZELIEK_HOLY_BOLT_25, SPELL_BLAUMEUX_SHADOW_BOLT_25, SPELL_RIVENDARE_UNHOLY_SHADOW_25, SPELL_KORTHAZZ_METEOR_25};
// PUNISH
const uint32 TABLE_SPELL_PUNISH[4] = {SPELL_ZELIEK_CONDEMNATION, SPELL_BLAUMEUX_UNYIELDING_PAIN, 0, 0};
// SECONDARY SPELL
const uint32 TABLE_SPELL_SECONDARY_10[4] = {SPELL_ZELIEK_HOLY_WRATH_10, SPELL_BLAUMEUX_VOID_ZONE_10, 0, 0};
const uint32 TABLE_SPELL_SECONDARY_25[4] = {SPELL_ZELIEK_HOLY_WRATH_25, SPELL_BLAUMEUX_VOID_ZONE_25, 0, 0};
const Position WaypointPositions[12] =
{
// Thane waypoints
{2542.3f, -2984.1f, 241.49f, 5.362f},
{2547.6f, -2999.4f, 241.34f, 5.049f},
{2542.9f, -3015.0f, 241.35f, 4.654f},
// Lady waypoints
{2498.3f, -2961.8f, 241.28f, 3.267f},
{2487.7f, -2959.2f, 241.28f, 2.890f},
{2469.4f, -2947.6f, 241.28f, 2.576f},
// Baron waypoints
{2553.8f, -2968.4f, 241.33f, 5.757f},
{2564.3f, -2972.5f, 241.33f, 5.890f},
{2583.9f, -2971.6f, 241.35f, 0.008f},
// Sir waypoints
{2534.5f, -2921.7f, 241.53f, 1.363f},
{2523.5f, -2902.8f, 241.28f, 2.095f},
{2517.8f, -2896.6f, 241.28f, 2.315f}
};
class boss_four_horsemen : public CreatureScript
{
public:
boss_four_horsemen() : CreatureScript("boss_four_horsemen") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return GetNaxxramasAI<boss_four_horsemenAI>(pCreature);
}
struct boss_four_horsemenAI : public BossAI
{
explicit boss_four_horsemenAI(Creature* c) : BossAI(c, BOSS_HORSEMAN)
{
pInstance = me->GetInstanceScript();
switch (me->GetEntry())
{
case NPC_SIR_ZELIEK:
horsemanId = HORSEMAN_ZELIEK;
break;
case NPC_LADY_BLAUMEUX:
horsemanId = HORSEMAN_BLAUMEUX;
break;
case NPC_BARON_RIVENDARE:
horsemanId = HORSEMAN_RIVENDARE;
break;
case NPC_THANE_KORTHAZZ:
horsemanId = HORSEMAN_KORTHAZZ;
break;
}
}
EventMap events;
InstanceScript* pInstance;
uint8 currentWaypoint{};
uint8 movementPhase{};
uint8 horsemanId;
void MoveToCorner()
{
switch(me->GetEntry())
{
case NPC_THANE_KORTHAZZ:
currentWaypoint = 0;
break;
case NPC_LADY_BLAUMEUX:
currentWaypoint = 3;
break;
case NPC_BARON_RIVENDARE:
currentWaypoint = 6;
break;
case NPC_SIR_ZELIEK:
currentWaypoint = 9;
break;
}
me->GetMotionMaster()->MovePoint(currentWaypoint, WaypointPositions[currentWaypoint]);
}
bool IsInRoom()
{
if (me->GetExactDist(2535.1f, -2968.7f, 241.3f) > 100.0f)
{
EnterEvadeMode();
return false;
}
return true;
}
void Reset() override
{
BossAI::Reset();
me->SetPosition(me->GetHomePosition());
movementPhase = MOVE_PHASE_NONE;
currentWaypoint = 0;
me->SetReactState(REACT_AGGRESSIVE);
events.Reset();
events.RescheduleEvent(EVENT_MARK_CAST, 24s);
events.RescheduleEvent(EVENT_BERSERK, 10min);
if ((me->GetEntry() != NPC_LADY_BLAUMEUX && me->GetEntry() != NPC_SIR_ZELIEK))
{
events.RescheduleEvent(EVENT_PRIMARY_SPELL, 10s, 15s);
}
else
{
events.RescheduleEvent(EVENT_SECONDARY_SPELL, 15s);
}
if (pInstance)
{
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetGuidData(DATA_HORSEMEN_GATE)))
{
if (pInstance->GetBossState(BOSS_GOTHIK) == DONE)
{
go->SetGoState(GO_STATE_ACTIVE);
}
}
}
}
void MovementInform(uint32 type, uint32 id) override
{
if (type != POINT_MOTION_TYPE)
return;
// final waypoint
if (id % 3 == 2)
{
movementPhase = MOVE_PHASE_FINISHED;
me->SetReactState(REACT_AGGRESSIVE);
me->SetInCombatWithZone();
if (!UpdateVictim())
{
EnterEvadeMode();
return;
}
if (me->GetEntry() == NPC_LADY_BLAUMEUX || me->GetEntry() == NPC_SIR_ZELIEK)
{
me->GetMotionMaster()->Clear(false);
me->GetMotionMaster()->MoveIdle();
}
return;
}
currentWaypoint = id + 1;
}
void AttackStart(Unit* who) override
{
if (movementPhase == MOVE_PHASE_FINISHED)
{
if (me->GetEntry() == NPC_LADY_BLAUMEUX || me->GetEntry() == NPC_SIR_ZELIEK)
{
me->Attack(who, false);
}
else
{
ScriptedAI::AttackStart(who);
}
}
}
void KilledUnit(Unit* who) override
{
if (who->GetTypeId() != TYPEID_PLAYER)
return;
Talk(SAY_SLAY);
if (pInstance)
{
pInstance->SetData(DATA_IMMORTAL_FAIL, 0);
}
}
void JustDied(Unit* killer) override
{
BossAI::JustDied(killer);
if (pInstance)
{
if (pInstance->GetBossState(BOSS_HORSEMAN) == DONE)
{
if (!me->GetMap()->GetPlayers().IsEmpty())
{
if (Player* player = me->GetMap()->GetPlayers().getFirst()->GetSource())
{
if (GameObject* chest = player->SummonGameObject(RAID_MODE(GO_HORSEMEN_CHEST_10, GO_HORSEMEN_CHEST_25), 2514.8f, -2944.9f, 245.55f, 5.51f, 0, 0, 0, 0, 0))
{
chest->SetLootRecipient(me);
}
}
}
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetGuidData(DATA_HORSEMEN_GATE)))
{
go->SetGoState(GO_STATE_ACTIVE);
}
}
}
Talk(SAY_DEATH);
}
void JustEngagedWith(Unit* who) override
{
BossAI::JustEngagedWith(who);
if (movementPhase == MOVE_PHASE_NONE)
{
Talk(SAY_AGGRO);
me->SetReactState(REACT_PASSIVE);
movementPhase = MOVE_PHASE_STARTED;
me->SetSpeed(MOVE_RUN, me->GetSpeedRate(MOVE_RUN), true);
MoveToCorner();
}
if (pInstance)
{
if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetGuidData(DATA_HORSEMEN_GATE)))
{
go->SetGoState(GO_STATE_READY);
}
}
}
void UpdateAI(uint32 diff) override
{
if (movementPhase == MOVE_PHASE_STARTED && currentWaypoint)
{
me->GetMotionMaster()->MovePoint(currentWaypoint, WaypointPositions[currentWaypoint]);
currentWaypoint = 0;
}
if (!IsInRoom())
return;
if (movementPhase < MOVE_PHASE_FINISHED || !UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{
case EVENT_MARK_CAST:
me->CastSpell(me, TABLE_SPELL_MARK[horsemanId], false);
events.Repeat((me->GetEntry() == NPC_LADY_BLAUMEUX || me->GetEntry() == NPC_SIR_ZELIEK) ? 15s : 12s);
return;
case EVENT_BERSERK:
Talk(SAY_SPECIAL);
me->CastSpell(me, SPELL_BERSERK, true);
return;
case EVENT_PRIMARY_SPELL:
Talk(SAY_TAUNT);
me->CastSpell(me->GetVictim(), RAID_MODE(TABLE_SPELL_PRIMARY_10[horsemanId], TABLE_SPELL_PRIMARY_25[horsemanId]), false);
events.Repeat(15s);
return;
case EVENT_SECONDARY_SPELL:
me->CastSpell(me->GetVictim(), RAID_MODE(TABLE_SPELL_SECONDARY_10[horsemanId], TABLE_SPELL_SECONDARY_25[horsemanId]), false);
events.Repeat(15s);
return;
}
if (me->GetEntry() == NPC_LADY_BLAUMEUX || me->GetEntry() == NPC_SIR_ZELIEK)
{
if (Unit* pTarget = me->SelectNearestTarget(300.0f))
{
if (pTarget && me->IsValidAttackTarget(pTarget))
{
AttackStart(pTarget);
}
}
if (me->IsWithinDistInMap(me->GetVictim(), 45.0f) && me->IsValidAttackTarget(me->GetVictim()))
{
DoCastVictim(RAID_MODE(TABLE_SPELL_PRIMARY_10[horsemanId], TABLE_SPELL_PRIMARY_25[horsemanId]));
}
else if (!me->IsWithinDistInMap(me->GetVictim(), 45.0f) || !me->IsValidAttackTarget(me->GetVictim()))
{
DoCastAOE(TABLE_SPELL_PUNISH[horsemanId]);
Talk(EMOTE_RAGECAST);
}
}
else
{
DoMeleeAttackIfReady();
}
}
};
};
class spell_four_horsemen_mark_aura : public AuraScript
{
PrepareAuraScript(spell_four_horsemen_mark_aura);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_MARK_DAMAGE });
}
void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
if (Unit* caster = GetCaster())
{
int32 damage;
switch (GetStackAmount())
{
case 1:
damage = 0;
break;
case 2:
damage = 500;
break;
case 3:
damage = 1500;
break;
case 4:
damage = 4000;
break;
case 5:
damage = 12500;
break;
case 6:
damage = 20000;
break;
default:
damage = 20000 + 1000 * (GetStackAmount() - 7);
break;
}
if (damage)
{
caster->CastCustomSpell(SPELL_MARK_DAMAGE, SPELLVALUE_BASE_POINT0, damage, GetTarget());
}
}
}
void Register() override
{
AfterEffectApply += AuraEffectApplyFn(spell_four_horsemen_mark_aura::OnApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
}
};
void AddSC_boss_four_horsemen()
{
new boss_four_horsemen();
RegisterSpellScript(spell_four_horsemen_mark_aura);
}