refactor(Scripts/AI) ZG20: Mar'li (Spider Boss) modernization (#17715)

ZG/Marli modernized
This commit is contained in:
KJack
2023-11-16 13:24:11 -05:00
committed by GitHub
parent 81bd9b7ba4
commit bc18526ee7
@@ -37,13 +37,13 @@ enum Says
enum Spells enum Spells
{ {
// Spider form // Spider Form
SPELL_CHARGE = 22911, SPELL_CHARGE = 22911,
SPELL_ENVELOPING_WEB = 24110, SPELL_ENVELOPING_WEB = 24110,
SPELL_CORROSIVE_POISON = 24111, SPELL_CORROSIVE_POISON = 24111,
SPELL_POISON_SHOCK = 24112, SPELL_POISON_SHOCK = 24112,
//Troll form // Troll Form
SPELL_POISON_VOLLEY = 24099, SPELL_POISON_VOLLEY = 24099,
SPELL_DRAIN_LIFE = 24300, SPELL_DRAIN_LIFE = 24300,
SPELL_ENLARGE = 24109, SPELL_ENLARGE = 24109,
@@ -61,33 +61,10 @@ enum Spells
SPELL_FULL_GROWN = 24088 SPELL_FULL_GROWN = 24088
}; };
enum Events
{
// Spider form
EVENT_CHARGE_PLAYER = 7,
EVENT_ENVELOPING_WEB = 8,
EVENT_CORROSIVE_POISON = 9,
EVENT_POISON_SHOCK = 10,
// Troll form
EVENT_POISON_VOLLEY = 11,
EVENT_DRAIN_LIFE = 12,
EVENT_ENLARGE = 13,
// All
EVENT_SPAWN_START_SPIDERS = 1,
EVENT_TRANSFORM = 2,
EVENT_TRANSFORM_BACK = 3,
EVENT_HATCH_SPIDER_EGG = 4,
EVENT_THRASH = 5,
EVENT_TALK_FIRST_SPIDERS = 6,
};
enum Phases enum Phases
{ {
PHASE_ONE = 1, PHASE_TROLL = 1,
PHASE_TWO = 2, PHASE_SPIDER = 2
PHASE_THREE = 3
}; };
enum Misc enum Misc
@@ -95,14 +72,20 @@ enum Misc
GO_SPIDER_EGGS = 179985, GO_SPIDER_EGGS = 179985,
}; };
// High Priestess Mar'li (14510)
struct boss_marli : public BossAI struct boss_marli : public BossAI
{ {
public:
boss_marli(Creature* creature) : BossAI(creature, DATA_MARLI) { } boss_marli(Creature* creature) : BossAI(creature, DATA_MARLI) { }
void Reset() override void Reset() override
{ {
if (events.IsInPhase(PHASE_THREE)) if (_phase == PHASE_SPIDER)
me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, false); // hack {
me->RemoveAura(SPELL_SPIDER_FORM);
me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, false);
_phase = PHASE_TROLL;
}
std::list<GameObject*> eggs; std::list<GameObject*> eggs;
me->GetGameObjectListWithEntryInGrid(eggs, GO_SPIDER_EGGS, DEFAULT_VISIBILITY_INSTANCE); me->GetGameObjectListWithEntryInGrid(eggs, GO_SPIDER_EGGS, DEFAULT_VISIBILITY_INSTANCE);
@@ -116,84 +99,120 @@ struct boss_marli : public BossAI
BossAI::Reset(); BossAI::Reset();
} }
void JustEngagedWith(Unit* who) override
{
BossAI::JustEngagedWith(who);
Talk(SAY_AGGRO);
scheduler.Schedule(1s, [this](TaskContext)
{
DoCastAOE(SPELL_HATCH_EGGS);
scheduler.Schedule(500ms, [this](TaskContext)
{
Talk(SAY_SPIDER_SPAWN);
});
// Both Forms
scheduler.Schedule(4s, 6s, [this](TaskContext context)
{
DoCastVictim(SPELL_THRASH);
context.Repeat(10s, 20s);
});
_schedulePhaseTroll();
});
}
void JustDied(Unit* killer) override void JustDied(Unit* killer) override
{ {
BossAI::JustDied(killer); BossAI::JustDied(killer);
Talk(SAY_DEATH); Talk(SAY_DEATH);
} }
void JustEngagedWith(Unit* who) override private:
Phases _phase = PHASE_TROLL;
void _schedulePhaseTroll()
{ {
BossAI::JustEngagedWith(who); // only if switching back from spider form
events.ScheduleEvent(EVENT_SPAWN_START_SPIDERS, 1s, 0, PHASE_ONE); if (_phase == PHASE_SPIDER)
Talk(SAY_AGGRO); {
me->RemoveAura(SPELL_SPIDER_FORM);
DoCastSelf(SPELL_TRANSFORM_BACK, true);
Talk(SAY_TRANSFORM_BACK);
me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, false);
scheduler.CancelGroup(PHASE_SPIDER);
} }
void UpdateAI(uint32 diff) override _phase = PHASE_TROLL;
{
if (!UpdateVictim())
return;
events.Update(diff); scheduler.Schedule(15s, PHASE_TROLL, [this](TaskContext context)
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{ {
switch (eventId)
{
case EVENT_SPAWN_START_SPIDERS:
events.ScheduleEvent(EVENT_TALK_FIRST_SPIDERS, 500ms, 0, PHASE_TWO);
DoCastAOE(SPELL_HATCH_EGGS);
events.ScheduleEvent(EVENT_TRANSFORM, 1min, 0, PHASE_TWO);
events.ScheduleEvent(EVENT_POISON_VOLLEY, 15s, 0, PHASE_TWO);
events.ScheduleEvent(EVENT_HATCH_SPIDER_EGG, 30s, 0, PHASE_TWO);
events.ScheduleEvent(EVENT_DRAIN_LIFE, 30s, 0, PHASE_TWO);
events.ScheduleEvent(EVENT_THRASH, 4s, 6s); // all phases
events.ScheduleEvent(EVENT_ENLARGE, 10s, 20s, 0, PHASE_TWO);
events.SetPhase(PHASE_TWO);
break;
case EVENT_TALK_FIRST_SPIDERS:
Talk(SAY_SPIDER_SPAWN);
break;
case EVENT_POISON_VOLLEY:
DoCastVictim(SPELL_POISON_VOLLEY, true); DoCastVictim(SPELL_POISON_VOLLEY, true);
events.ScheduleEvent(EVENT_POISON_VOLLEY, 10s, 20s, 0, PHASE_TWO); context.Repeat(10s, 20s);
break; }).Schedule(30s, PHASE_TROLL, [this](TaskContext context)
case EVENT_HATCH_SPIDER_EGG: {
DoCastSelf(SPELL_HATCH_SPIDER_EGG, true);
events.ScheduleEvent(EVENT_HATCH_SPIDER_EGG, 20s, 0, PHASE_TWO);
break;
case EVENT_DRAIN_LIFE:
DoCastRandomTarget(SPELL_DRAIN_LIFE); DoCastRandomTarget(SPELL_DRAIN_LIFE);
events.ScheduleEvent(EVENT_DRAIN_LIFE, 20s, 50s, 0, PHASE_TWO); context.Repeat(20s, 50s);
break; }).Schedule(30s, PHASE_TROLL, [this](TaskContext context)
case EVENT_ENLARGE: {
DoCastSelf(SPELL_HATCH_SPIDER_EGG, true);
context.Repeat(20s);
}).Schedule(10s, 20s, PHASE_TROLL, [this](TaskContext context)
{ {
std::list<Creature*> targets = DoFindFriendlyMissingBuff(100.f, SPELL_ENLARGE); std::list<Creature*> targets = DoFindFriendlyMissingBuff(100.f, SPELL_ENLARGE);
if (targets.size() > 0) for (auto const& target : targets)
DoCast(*(targets.begin()), SPELL_ENLARGE); {
events.ScheduleEvent(EVENT_ENLARGE, 20s, 40s, 0, PHASE_TWO); DoCast(target, SPELL_ENLARGE);
break;
} }
case EVENT_TRANSFORM: context.Repeat(20s, 40s);
});
// Transition to PHASE_SPIDER
scheduler.Schedule(1min, PHASE_TROLL, [this](TaskContext)
{
_schedulePhaseSpider();
});
}
void _schedulePhaseSpider()
{
scheduler.CancelGroup(PHASE_TROLL);
_phase = PHASE_SPIDER;
Talk(SAY_TRANSFORM); Talk(SAY_TRANSFORM);
DoCastSelf(SPELL_SPIDER_FORM, true); DoCastSelf(SPELL_SPIDER_FORM, true);
me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, true); // hack me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, true);
events.ScheduleEvent(EVENT_ENVELOPING_WEB, 5s, 0, PHASE_THREE);
events.ScheduleEvent(EVENT_CHARGE_PLAYER, 6s, 0, PHASE_THREE); scheduler.Schedule(5s, PHASE_SPIDER, [this](TaskContext context)
events.ScheduleEvent(EVENT_CORROSIVE_POISON, 1s, 0, PHASE_THREE); {
events.ScheduleEvent(EVENT_POISON_SHOCK, 5s, 10s, 0, PHASE_THREE);
events.ScheduleEvent(EVENT_TRANSFORM_BACK, 1min, 0, PHASE_THREE);
events.SetPhase(PHASE_THREE);
break;
case EVENT_ENVELOPING_WEB:
DoCastAOE(SPELL_ENVELOPING_WEB); DoCastAOE(SPELL_ENVELOPING_WEB);
events.ScheduleEvent(EVENT_CHARGE_PLAYER, 500ms, 0, PHASE_THREE); scheduler.Schedule(500ms, PHASE_SPIDER, [this](TaskContext)
events.ScheduleEvent(EVENT_ENVELOPING_WEB, 15s, 20s, 0, PHASE_THREE); {
break; _chargePlayer();
case EVENT_CHARGE_PLAYER: });
context.Repeat(15s, 20s);
}).Schedule(1s, PHASE_SPIDER, [this](TaskContext context)
{
DoCastVictim(SPELL_CORROSIVE_POISON);
context.Repeat(25s, 35s);
}).Schedule(5s, 10s, PHASE_SPIDER, [this](TaskContext context)
{
DoCastRandomTarget(SPELL_POISON_SHOCK);
context.Repeat(10s);
});
// Transition to PHASE_TROLL
scheduler.Schedule(1min, PHASE_SPIDER, [this](TaskContext)
{
_schedulePhaseTroll();
});
}
void _chargePlayer()
{ {
Unit* target = SelectTarget(SelectTargetMethod::Random, 0, [this](Unit* target) -> bool Unit* target = SelectTarget(SelectTargetMethod::Random, 0, [this](Unit* target) -> bool
{ {
@@ -208,42 +227,11 @@ struct boss_marli : public BossAI
DoCast(target, SPELL_CHARGE); DoCast(target, SPELL_CHARGE);
AttackStart(target); AttackStart(target);
} }
break;
}
case EVENT_CORROSIVE_POISON:
DoCastVictim(SPELL_CORROSIVE_POISON);
events.ScheduleEvent(EVENT_CORROSIVE_POISON, 25s, 35s, 0, PHASE_THREE);
break;
case EVENT_POISON_SHOCK:
DoCastRandomTarget(SPELL_POISON_SHOCK);
events.ScheduleEvent(EVENT_POISON_SHOCK, 10s, 0, PHASE_THREE);
break;
case EVENT_TRANSFORM_BACK:
me->RemoveAura(SPELL_SPIDER_FORM);
DoCastSelf(SPELL_TRANSFORM_BACK, true);
Talk(SAY_TRANSFORM_BACK);
me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, false); // hack
events.ScheduleEvent(EVENT_TRANSFORM, 1min, 0, PHASE_TWO);
events.ScheduleEvent(EVENT_POISON_VOLLEY, 15s, 0, PHASE_TWO);
events.ScheduleEvent(EVENT_HATCH_SPIDER_EGG, 30s, 0, PHASE_TWO);
events.ScheduleEvent(EVENT_DRAIN_LIFE, 30s, 0, PHASE_TWO);
events.ScheduleEvent(EVENT_ENLARGE, 10s, 20s, 0, PHASE_TWO);
events.SetPhase(PHASE_TWO);
break;
case EVENT_THRASH:
DoCastVictim(SPELL_THRASH);
events.ScheduleEvent(EVENT_THRASH, 10s, 20s);
break;
default:
break;
}
} }
DoMeleeAttackIfReady();
}
}; };
// Spawn of Mar'li // Spawn of Mar'li (15041)
struct npc_spawn_of_marli : public ScriptedAI struct npc_spawn_of_marli : public ScriptedAI
{ {
npc_spawn_of_marli(Creature* creature) : ScriptedAI(creature) { } npc_spawn_of_marli(Creature* creature) : ScriptedAI(creature) { }
@@ -272,21 +260,19 @@ struct npc_spawn_of_marli : public ScriptedAI
void UpdateAI(uint32 diff) override void UpdateAI(uint32 diff) override
{ {
//Return since we have no target
if (!UpdateVictim()) if (!UpdateVictim())
return; return;
_scheduler.Update(diff, [this] _scheduler.Update(diff);
{
DoMeleeAttackIfReady(); DoMeleeAttackIfReady();
});
} }
private: private:
TaskScheduler _scheduler; TaskScheduler _scheduler;
}; };
// 24083 - Hatch Eggs // Hatch Eggs (24083)
class spell_hatch_eggs : public SpellScript class spell_hatch_eggs : public SpellScript
{ {
PrepareSpellScript(spell_hatch_eggs); PrepareSpellScript(spell_hatch_eggs);
@@ -303,7 +289,7 @@ class spell_hatch_eggs : public SpellScript
} }
}; };
// 24110 - Enveloping Webs // Enveloping Webs (24110)
class spell_enveloping_webs : public SpellScript class spell_enveloping_webs : public SpellScript
{ {
PrepareSpellScript(spell_enveloping_webs); PrepareSpellScript(spell_enveloping_webs);
@@ -324,7 +310,7 @@ class spell_enveloping_webs : public SpellScript
} }
}; };
// 24084 - Mar'li Transform // Mar'li Transform (24084)
class spell_marli_transform : public AuraScript class spell_marli_transform : public AuraScript
{ {
PrepareAuraScript(spell_marli_transform); PrepareAuraScript(spell_marli_transform);