Scripts/Maraudon: Modernize scripts (#31092)

* New register model
* Codestyle changes
* TaskScheduler instead of timer variables
* Implement one spell script for Noxxion encounter
This commit is contained in:
offl
2025-07-13 22:03:02 +03:00
committed by GitHub
parent 70d1875484
commit f40409ce68
6 changed files with 236 additions and 330 deletions

View File

@@ -0,0 +1,6 @@
--
UPDATE `creature_template` SET `ScriptName` = 'boss_celebras_the_cursed' WHERE `entry` = 12225;
DELETE FROM `spell_script_names` WHERE `ScriptName` = 'spell_noxxion_summon_spawns';
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
(21708, 'spell_noxxion_summon_spawns');

View File

@@ -15,101 +15,77 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* ScriptData
SDName: Boss_Celebras_the_Cursed
SD%Complete: 100
SDComment:
SDCategory: Maraudon
EndScriptData */
#include "ScriptMgr.h"
#include "maraudon.h"
#include "ScriptedCreature.h"
enum Spells
enum CelebrasSpells
{
SPELL_WRATH = 21807,
SPELL_ENTANGLINGROOTS = 12747,
SPELL_ENTANGLING_ROOTS = 12747,
SPELL_CORRUPT_FORCES = 21968
};
class celebras_the_cursed : public CreatureScript
enum CelebrasMisc
{
public:
celebras_the_cursed() : CreatureScript("celebras_the_cursed") { }
NPC_CELEBRAS_THE_REDEEMED = 13716
};
CreatureAI* GetAI(Creature* creature) const override
// 12225 - Celebras the Cursed
struct boss_celebras_the_cursed : public ScriptedAI
{
boss_celebras_the_cursed(Creature* creature) : ScriptedAI(creature) { }
void Reset() override
{
return GetMaraudonAI<celebras_the_cursedAI>(creature);
_scheduler.CancelAll();
}
struct celebras_the_cursedAI : public ScriptedAI
void JustEngagedWith(Unit* /*who*/) override
{
celebras_the_cursedAI(Creature* creature) : ScriptedAI(creature)
{
Initialize();
}
void Initialize()
{
WrathTimer = 8000;
EntanglingRootsTimer = 2000;
CorruptForcesTimer = 30000;
}
uint32 WrathTimer;
uint32 EntanglingRootsTimer;
uint32 CorruptForcesTimer;
void Reset() override
{
Initialize();
}
void JustEngagedWith(Unit* /*who*/) override { }
void JustDied(Unit* /*killer*/) override
{
me->SummonCreature(13716, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 10min);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
//Wrath
if (WrathTimer <= diff)
_scheduler
.SetValidator([this]
{
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
DoCast(target, SPELL_WRATH);
WrathTimer = 8000;
}
else WrathTimer -= diff;
//EntanglingRoots
if (EntanglingRootsTimer <= diff)
return !me->HasUnitState(UNIT_STATE_CASTING);
})
.Schedule(0s, 6s, [this](TaskContext task)
{
DoCastVictim(SPELL_ENTANGLINGROOTS);
EntanglingRootsTimer = 20000;
}
else EntanglingRootsTimer -= diff;
//CorruptForces
if (CorruptForcesTimer <= diff)
DoCastVictim(SPELL_WRATH);
task.Repeat(4s, 8s);
})
.Schedule(0s, 5s, [this](TaskContext task)
{
me->InterruptNonMeleeSpells(false);
DoCast(me, SPELL_CORRUPT_FORCES);
CorruptForcesTimer = 20000;
}
else CorruptForcesTimer -= diff;
DoCastVictim(SPELL_ENTANGLING_ROOTS);
task.Repeat(20s);
})
.Schedule(30s, [this](TaskContext task)
{
DoCastSelf(SPELL_CORRUPT_FORCES);
task.Repeat(20s);
});
}
void JustDied(Unit* /*killer*/) override
{
me->SummonCreature(NPC_CELEBRAS_THE_REDEEMED, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_MANUAL_DESPAWN);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
_scheduler.Update(diff, [this]
{
DoMeleeAttackIfReady();
}
};
});
}
private:
TaskScheduler _scheduler;
};
void AddSC_boss_celebras_the_cursed()
{
new celebras_the_cursed();
RegisterMaraudonCreatureAI(boss_celebras_the_cursed);
}

View File

@@ -15,100 +15,78 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* ScriptData
SDName: Boss_Landslide
SD%Complete: 100
SDComment:
SDCategory: Maraudon
EndScriptData */
#include "ScriptMgr.h"
#include "maraudon.h"
#include "ScriptedCreature.h"
enum Spells
enum LandslideSpells
{
SPELL_KNOCKAWAY = 18670,
SPELL_KNOCK_AWAY = 18670,
SPELL_TRAMPLE = 5568,
SPELL_LANDSLIDE = 21808
};
class boss_landslide : public CreatureScript
// 12203 - Landslide
struct boss_landslide : public ScriptedAI
{
public:
boss_landslide() : CreatureScript("boss_landslide") { }
boss_landslide(Creature* creature) : ScriptedAI(creature), _landslide(false) { }
CreatureAI* GetAI(Creature* creature) const override
void Reset() override
{
return GetMaraudonAI<boss_landslideAI>(creature);
_scheduler.CancelAll();
_landslide = false;
}
struct boss_landslideAI : public ScriptedAI
void JustEngagedWith(Unit* /*who*/) override
{
boss_landslideAI(Creature* creature) : ScriptedAI(creature)
{
Initialize();
}
void Initialize()
{
KnockAwayTimer = 8000;
TrampleTimer = 2000;
LandslideTimer = 0;
}
uint32 KnockAwayTimer;
uint32 TrampleTimer;
uint32 LandslideTimer;
void Reset() override
{
Initialize();
}
void JustEngagedWith(Unit* /*who*/) override
{
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
//KnockAwayTimer
if (KnockAwayTimer <= diff)
_scheduler
.SetValidator([this]
{
DoCastVictim(SPELL_KNOCKAWAY);
KnockAwayTimer = 15000;
}
else KnockAwayTimer -= diff;
//TrampleTimer
if (TrampleTimer <= diff)
return !me->HasUnitState(UNIT_STATE_CASTING);
})
.Schedule(5s, 10s, [this](TaskContext task)
{
DoCast(me, SPELL_TRAMPLE);
TrampleTimer = 8000;
}
else TrampleTimer -= diff;
//Landslide
if (HealthBelowPct(50))
DoCastVictim(SPELL_KNOCK_AWAY);
task.Repeat(15s, 25s);
})
.Schedule(10s, 15s, [this](TaskContext task)
{
if (LandslideTimer <= diff)
{
me->InterruptNonMeleeSpells(false);
DoCast(me, SPELL_LANDSLIDE);
LandslideTimer = 60000;
}
else LandslideTimer -= diff;
}
DoCastSelf(SPELL_TRAMPLE);
task.Repeat(10s, 20s);
});
}
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
{
if (!_landslide && me->HealthBelowPctDamaged(50, damage))
{
_landslide = true;
_scheduler.Schedule(0s, [this](TaskContext task)
{
DoCastSelf(SPELL_LANDSLIDE);
task.Repeat(30s, 40s);
});
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
_scheduler.Update(diff, [this]
{
DoMeleeAttackIfReady();
}
};
});
}
private:
TaskScheduler _scheduler;
bool _landslide;
};
void AddSC_boss_landslide()
{
new boss_landslide();
RegisterMaraudonCreatureAI(boss_landslide);
}

View File

@@ -15,135 +15,106 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* ScriptData
SDName: Boss_Noxxion
SD%Complete: 100
SDComment:
SDCategory: Maraudon
EndScriptData */
#include "ScriptMgr.h"
#include "maraudon.h"
#include "ScriptedCreature.h"
#include "SpellScript.h"
enum Spells
enum NoxxionSpells
{
SPELL_TOXICVOLLEY = 21687,
SPELL_UPPERCUT = 22916
SPELL_TOXIC_VOLLEY = 21687,
SPELL_UPPERCUT = 22916,
SPELL_SUMMON_SPAWNS_DUMMY = 21708,
SPELL_SUMMON_SPAWNS = 21707
};
class boss_noxxion : public CreatureScript
// 13282 - Noxxion
struct boss_noxxion : public ScriptedAI
{
public:
boss_noxxion() : CreatureScript("boss_noxxion") { }
boss_noxxion(Creature* creature) : ScriptedAI(creature) { }
CreatureAI* GetAI(Creature* creature) const override
void Reset() override
{
return GetMaraudonAI<boss_noxxionAI>(creature);
_scheduler.CancelAll();
}
struct boss_noxxionAI : public ScriptedAI
void JustEngagedWith(Unit* /*who*/) override
{
boss_noxxionAI(Creature* creature) : ScriptedAI(creature)
{
Initialize();
}
void Initialize()
{
ToxicVolleyTimer = 7000;
UppercutTimer = 16000;
AddsTimer = 19000;
InvisibleTimer = 15000; //Too much too low?
Invisible = false;
}
uint32 ToxicVolleyTimer;
uint32 UppercutTimer;
uint32 AddsTimer;
uint32 InvisibleTimer;
bool Invisible;
void Reset() override
{
Initialize();
}
void JustEngagedWith(Unit* /*who*/) override { }
void SummonAdds(Unit* victim)
{
if (Creature* Add = DoSpawnCreature(13456, float(irand(-7, 7)), float(irand(-7, 7)), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 90s))
Add->AI()->AttackStart(victim);
}
void UpdateAI(uint32 diff) override
{
if (Invisible && InvisibleTimer <= diff)
_scheduler
.SetValidator([this]
{
//Become visible again
me->SetFaction(FACTION_MONSTER);
me->RemoveUnitFlag(UNIT_FLAG_UNINTERACTIBLE);
//Noxxion model
me->SetDisplayId(11172);
Invisible = false;
//me->m_canMove = true;
}
else if (Invisible)
return !me->HasUnitState(UNIT_STATE_CASTING);
})
.Schedule(5s, 10s, [this](TaskContext task)
{
InvisibleTimer -= diff;
//Do nothing while invisible
return;
}
//Return since we have no target
if (!UpdateVictim())
return;
//ToxicVolleyTimer
if (ToxicVolleyTimer <= diff)
{
DoCastVictim(SPELL_TOXICVOLLEY);
ToxicVolleyTimer = 9000;
}
else ToxicVolleyTimer -= diff;
//UppercutTimer
if (UppercutTimer <= diff)
DoCastSelf(SPELL_TOXIC_VOLLEY);
task.Repeat(15s, 20s);
})
.Schedule(15s, 20s, [this](TaskContext task)
{
DoCastVictim(SPELL_UPPERCUT);
UppercutTimer = 12000;
}
else UppercutTimer -= diff;
//AddsTimer
if (!Invisible && AddsTimer <= diff)
task.Repeat(20s, 30s);
})
.Schedule(30s, 40s, [this](TaskContext task)
{
//Interrupt any spell casting
//me->m_canMove = true;
me->InterruptNonMeleeSpells(false);
me->SetFaction(FACTION_FRIENDLY);
me->SetUnitFlag(UNIT_FLAG_UNINTERACTIBLE);
// Invisible Model
me->SetDisplayId(11686);
SummonAdds(me->GetVictim());
SummonAdds(me->GetVictim());
SummonAdds(me->GetVictim());
SummonAdds(me->GetVictim());
SummonAdds(me->GetVictim());
Invisible = true;
InvisibleTimer = 15000;
DoCastSelf(SPELL_SUMMON_SPAWNS_DUMMY);
task.Repeat(50s, 60s);
});
}
AddsTimer = 40000;
}
else AddsTimer -= diff;
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
_scheduler.Update(diff, [this]
{
DoMeleeAttackIfReady();
});
}
private:
TaskScheduler _scheduler;
};
// 21708 - Summon Noxxion's Spawns
class spell_noxxion_summon_spawns : public AuraScript
{
PrepareAuraScript(spell_noxxion_summon_spawns);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_SUMMON_SPAWNS });
}
void AfterApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
if (Creature* target = GetTarget()->ToCreature())
{
target->SetReactState(REACT_PASSIVE);
target->SetUnitFlag(UNIT_FLAG_UNINTERACTIBLE);
target->CastSpell(target, SPELL_SUMMON_SPAWNS, true);
}
};
}
void AfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
if (Creature* target = GetTarget()->ToCreature())
{
target->SetReactState(REACT_AGGRESSIVE);
target->RemoveUnitFlag(UNIT_FLAG_UNINTERACTIBLE);
}
}
void Register() override
{
AfterEffectApply += AuraEffectApplyFn(spell_noxxion_summon_spawns::AfterApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
AfterEffectRemove += AuraEffectApplyFn(spell_noxxion_summon_spawns::AfterRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
void AddSC_boss_noxxion()
{
new boss_noxxion();
RegisterMaraudonCreatureAI(boss_noxxion);
RegisterSpellScript(spell_noxxion_summon_spawns);
}

View File

@@ -15,111 +15,84 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* ScriptData
SDName: Boss_Princess_Theradras
SD%Complete: 100
SDComment:
SDCategory: Maraudon
EndScriptData */
#include "ScriptMgr.h"
#include "maraudon.h"
#include "ScriptedCreature.h"
enum Spells
enum TheradrasSpells
{
SPELL_DUSTFIELD = 21909,
SPELL_DUST_FIELD = 21909,
SPELL_BOULDER = 21832,
SPELL_THRASH = 3391,
SPELL_REPULSIVEGAZE = 21869
SPELL_REPULSIVE_GAZE = 21869
};
class boss_princess_theradras : public CreatureScript
enum TheradrasMisc
{
public:
boss_princess_theradras() : CreatureScript("boss_princess_theradras") { }
NPC_ZAETARS_SPIRIT = 12238
};
CreatureAI* GetAI(Creature* creature) const override
// 12201 - Princess Theradras
struct boss_princess_theradras : public ScriptedAI
{
boss_princess_theradras(Creature* creature) : ScriptedAI(creature) { }
void Reset() override
{
return GetMaraudonAI<boss_ptheradrasAI>(creature);
_scheduler.CancelAll();
}
struct boss_ptheradrasAI : public ScriptedAI
void JustEngagedWith(Unit* /*who*/) override
{
boss_ptheradrasAI(Creature* creature) : ScriptedAI(creature)
{
Initialize();
}
void Initialize()
{
DustfieldTimer = 8000;
BoulderTimer = 2000;
ThrashTimer = 5000;
RepulsiveGazeTimer = 23000;
}
uint32 DustfieldTimer;
uint32 BoulderTimer;
uint32 ThrashTimer;
uint32 RepulsiveGazeTimer;
void Reset() override
{
Initialize();
}
void JustEngagedWith(Unit* /*who*/) override { }
void JustDied(Unit* /*killer*/) override
{
me->SummonCreature(12238, 28.1887f, 62.3964f, -123.161f, 4.31096f, TEMPSUMMON_TIMED_DESPAWN, 10min);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
//DustfieldTimer
if (DustfieldTimer <= diff)
_scheduler
.SetValidator([this]
{
DoCast(me, SPELL_DUSTFIELD);
DustfieldTimer = 14000;
}
else DustfieldTimer -= diff;
//BoulderTimer
if (BoulderTimer <= diff)
return !me->HasUnitState(UNIT_STATE_CASTING);
})
.Schedule(20s, 25s, [this](TaskContext task)
{
DoCastSelf(SPELL_DUST_FIELD);
task.Repeat(20s, 25s);
})
.Schedule(20s, 30s, [this](TaskContext task)
{
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
DoCast(target, SPELL_BOULDER);
BoulderTimer = 10000;
}
else BoulderTimer -= diff;
//RepulsiveGazeTimer
if (RepulsiveGazeTimer <= diff)
task.Repeat(15s, 25s);
})
.Schedule(10s, 20s, [this](TaskContext task)
{
DoCastVictim(SPELL_REPULSIVEGAZE);
RepulsiveGazeTimer = 20000;
}
else RepulsiveGazeTimer -= diff;
//ThrashTimer
if (ThrashTimer <= diff)
DoCastSelf(SPELL_THRASH);
task.Repeat(10s, 20s);
})
.Schedule(25s, 35s, [this](TaskContext task)
{
DoCast(me, SPELL_THRASH);
ThrashTimer = 18000;
}
else ThrashTimer -= diff;
DoCastSelf(SPELL_REPULSIVE_GAZE);
task.Repeat(30s, 40s);
});
}
void JustDied(Unit* /*killer*/) override
{
me->SummonCreature(NPC_ZAETARS_SPIRIT, 28.1887f, 62.3964f, -123.161f, 4.31096f, TEMPSUMMON_MANUAL_DESPAWN);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
_scheduler.Update(diff, [this]
{
DoMeleeAttackIfReady();
}
};
});
}
private:
TaskScheduler _scheduler;
};
void AddSC_boss_ptheradras()
{
new boss_princess_theradras();
RegisterMaraudonCreatureAI(boss_princess_theradras);
}

View File

@@ -28,4 +28,6 @@ inline AI* GetMaraudonAI(T* obj)
return GetInstanceAI<AI>(obj, MaraudonScriptName);
}
#define RegisterMaraudonCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetMaraudonAI)
#endif // maraudon_h__