Skip to content

Commit

Permalink
refactor(Scripts/MagisterTerrace): Clean up Vexallus instance script … (
Browse files Browse the repository at this point in the history
  • Loading branch information
Nyeriah authored Feb 1, 2025
1 parent c94f41d commit d3296f6
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 155 deletions.
2 changes: 2 additions & 0 deletions data/sql/updates/pending_db_world/rev_1738389411836419000.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
--
UPDATE `creature_template` SET `ScriptName` = '' WHERE (`entry` = 24745);
220 changes: 65 additions & 155 deletions src/server/scripts/EasternKingdoms/MagistersTerrace/boss_vexallus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,72 +41,61 @@ enum Spells
SPELL_SUMMON_PURE_ENERGY_H2 = 46159 // Heroic mode summon 2
};

struct npc_pure_energy : public ScriptedAI
{
explicit npc_pure_energy(Creature* creature) : ScriptedAI(creature) {}

// Initialize on summon
void IsSummonedBy(WorldObject* summoner) override
{
if (!summoner)
return;
if (Creature* vexallus = summoner ? summoner->ToCreature() : nullptr)
{
if (Unit* target = vexallus->AI()->SelectTarget(SelectTargetMethod::Random, 0))
me->CastSpell(target, SPELL_ENERGY_FEEDBACK_CHANNEL, false);
}
}

void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType, SpellSchoolMask) override
{
if (!attacker || !attacker->IsPlayer() || attacker->GetVictim() != me)
damage = 0; // Only take damage from players targeting this add
}

void UpdateAI(uint32 /*diff*/) override
{
if (!UpdateVictim())
return;
}

void AttackStart(Unit* victim) override
{
if (victim)
{
me->Attack(victim, false);
me->GetMotionMaster()->MoveChase(victim, 0.0f, 0.0f);
}
}
};

struct boss_vexallus : public BossAI
{
// Configuration constants
static constexpr std::array<uint8_t, 5> HEALTH_THRESHOLDS = {85, 70, 55, 40, 25}; // HP % for energy spawns
static constexpr Seconds ENERGY_COOLDOWN = 5s; // Time between energy spawns
static constexpr Seconds ABILITY_TIMER = 8s; // Basic ability cooldown
static constexpr uint8 INITIAL_PURE_ENERGY = 5; // Starting energy count

explicit boss_vexallus(Creature* creature)
: BossAI(creature, DATA_VEXALLUS)
, _energyCooldown(false)
, _overloaded(false)
, _energyQueue(0)
, _pureEnergy(INITIAL_PURE_ENERGY)
, _thresholdsPassed({})
{
}
boss_vexallus(Creature* creature) : BossAI(creature, DATA_VEXALLUS), _energyCooldown(false), _energyCount(0) { }

void Reset() override
{
_Reset();
_energyCooldown = false;
_energyQueue = 0;
_overloaded = false;
_pureEnergy = INITIAL_PURE_ENERGY;
std::fill(_thresholdsPassed.begin(), _thresholdsPassed.end(), false);
_energyCount = 0;

ScheduleEnergyCheck();
ScheduleHealthCheckEvent({ 85, 70, 55, 40, 25 }, [&]
{
scheduler.Schedule(1s, [this](TaskContext context)
{
if (!_energyCooldown)
{
Talk(SAY_ENERGY);
Talk(EMOTE_DISCHARGE_ENERGY);
if (IsHeroic())
{
DoCastSelf(SPELL_SUMMON_PURE_ENERGY_H1);
DoCastSelf(SPELL_SUMMON_PURE_ENERGY_H2);
}
else
DoCastSelf(SPELL_SUMMON_PURE_ENERGY_N);

_energyCooldown = true;
++_energyCount;

me->m_Events.AddEventAtOffset([&]
{
_energyCooldown = false;
}, 5s);
}
else
context.Repeat(5s);

});
});

ScheduleHealthCheckEvent(20, [&]
{
scheduler.Schedule(1s, [this](TaskContext context)
{
if (_energyCount == 5 && !_energyCooldown)
{
scheduler.CancelAll();
Talk(SAY_OVERLOAD);
Talk(EMOTE_OVERLOAD);
DoCastSelf(SPELL_OVERLOAD, true);
}
else
context.Repeat(5s);
});
});
}

void JustDied(Unit*) override
Expand All @@ -125,123 +114,44 @@ struct boss_vexallus : public BossAI
{
_JustEngagedWith();
Talk(SAY_AGGRO);
ScheduleCombatAbilities();
}

void SummonedCreatureDies(Creature* summon, Unit* killer) override
{
summons.Despawn(summon);
summon->DespawnOrUnsummon(1);
if (killer)
killer->CastSpell(killer, SPELL_ENERGY_FEEDBACK, true, 0, 0, summon->GetGUID());
}

void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
DoMeleeAttackIfReady();
CheckOverload();
CheckHealthThresholds();

events.Update(diff);
scheduler.Update(diff);
}

private:
// Schedule periodic energy spawn checks
void ScheduleEnergyCheck()
{
scheduler.Schedule(1s, [this](TaskContext context)
{
ProcessEnergyQueue();
context.Repeat(1s);
});
}

// Handle energy spawn logic
void ProcessEnergyQueue()
{
if (!_energyCooldown && _energyQueue > 0)
{
Talk(SAY_ENERGY);
Talk(EMOTE_DISCHARGE_ENERGY);

if (IsHeroic())
{
DoCastSelf(SPELL_SUMMON_PURE_ENERGY_H1);
DoCastSelf(SPELL_SUMMON_PURE_ENERGY_H2);
}
else
{
DoCastSelf(SPELL_SUMMON_PURE_ENERGY_N);
}

_energyQueue--;
_pureEnergy--;
SetEnergyCooldown();
}
}

// Start energy spawn cooldown
void SetEnergyCooldown()
{
_energyCooldown = true;
scheduler.Schedule(ENERGY_COOLDOWN, [this](TaskContext)
{
_energyCooldown = false;
});
}

// Schedule basic combat abilities
void ScheduleCombatAbilities()
{
ScheduleTimedEvent(ABILITY_TIMER, [&]
ScheduleTimedEvent(5s, [&]
{
DoCastRandomTarget(SPELL_CHAIN_LIGHTNING);
}, ABILITY_TIMER, ABILITY_TIMER);
}, 8s);

ScheduleTimedEvent(5s, [&]
{
DoCastRandomTarget(SPELL_ARCANE_SHOCK);
}, ABILITY_TIMER, ABILITY_TIMER);
}, 5s);
}

// Check for final phase transition
void CheckOverload()
void JustSummoned(Creature* summon) override
{
if (!_overloaded && _pureEnergy == 0 && !_energyCooldown && HealthBelowPct(20))
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
{
Talk(SAY_OVERLOAD);
Talk(EMOTE_OVERLOAD);
DoCastSelf(SPELL_OVERLOAD, true);
_overloaded = true;
summon->SetReactState(REACT_PASSIVE);
summon->GetMotionMaster()->MoveFollow(target, 0.0f, 0.0f);
summon->CastSpell(target, SPELL_ENERGY_FEEDBACK_CHANNEL, false);
}

summons.Summon(summon);
}

// Check health-based energy spawn triggers
void CheckHealthThresholds()
void SummonedCreatureDies(Creature* summon, Unit* killer) override
{
for (size_t i = 0; i < HEALTH_THRESHOLDS.size(); ++i)
{
if (!_thresholdsPassed[i] && HealthBelowPct(HEALTH_THRESHOLDS[i]))
{
_energyQueue++;
_thresholdsPassed[i] = true;
}
}
summons.Despawn(summon);
summon->DespawnOrUnsummon(1);
if (killer)
killer->CastSpell(killer, SPELL_ENERGY_FEEDBACK, true, 0, 0, summon->GetGUID());
}

// State tracking
bool _energyCooldown; // Energy spawn on cooldown
bool _overloaded; // Final phase active
uint8 _energyQueue; // Pending energy spawns
uint8 _pureEnergy; // Remaining energy count
std::array<bool, 5> _thresholdsPassed; // Health threshold tracking
private:
bool _energyCooldown;
uint8 _energyCount;
};

void AddSC_boss_vexallus()
{
RegisterMagistersTerraceCreatureAI(npc_pure_energy);
RegisterMagistersTerraceCreatureAI(boss_vexallus);
}

0 comments on commit d3296f6

Please sign in to comment.