refactor(Scripts/AI) ZG20: Mar'li (Spider Boss) modernization (#17715)
ZG/Marli modernized
This commit is contained in:
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user