refactor(Scripts/AI) ZG20: Venoxis (Snake Boss) modernization (#17699)

* npc_razzashi_cobra_venoxis: modernize

* ZG/Venoxis : npc_razzashi_cobra_venoxis

* ZG20/Venoxis - modernize AI

* Reimplement cobras with SAI and DB edits
This commit is contained in:
KJack
2023-11-16 15:42:11 -05:00
committed by GitHub
parent d1e26997ca
commit 05e530317a
2 changed files with 133 additions and 280 deletions

View File

@@ -0,0 +1,32 @@
-- Spawns for Razzashi Cobra (11373)
DELETE FROM `creature` WHERE `guid` IN (52323, 52324, 52325, 52326);
INSERT INTO `creature` (`guid`, `id1`, `id2`, `id3`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `wander_distance`, `currentwaypoint`, `curhealth`, `curmana`, `MovementType`, `npcflag`, `unit_flags`, `dynamicflags`, `ScriptName`, `VerifiedBuild`, `CreateObject`, `Comment`) VALUES
(52323, 11373, 0, 0, 309, 0, 0, 1, 1, 0, -12021.2, -1719.73, 39.2625, 0.85, 259200, 0, 0, 15260, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(52324, 11373, 0, 0, 309, 0, 0, 1, 1, 0, -12029.4, -1714.54, 39.2802, 0.68, 259200, 0, 0, 15260, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(52325, 11373, 0, 0, 309, 0, 0, 1, 1, 0, -12036.8, -1704.27, 39.9802, 0.45, 259200, 0, 0, 15260, 0, 0, 0, 0, 0, '', NULL, 0, NULL),
(52326, 11373, 0, 0, 309, 0, 0, 1, 1, 0, -12037.7, -1694.2, 39.2746, 0.27, 259200, 0, 0, 15260, 0, 0, 0, 0, 0, '', NULL, 0, NULL);
-- Remove script from Razzashi Cobra (11373)
UPDATE `creature_template` SET `ScriptName` = '' WHERE (`entry` = 11373);
-- Update SAI for Razzaishi Cobra (11373)
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 11373) AND (`source_type` = 0) AND (`id` IN (0));
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
(11373, 0, 0, 0, 0, 0, 100, 0, 8000, 8000, 15000, 15000, 0, 0, 11, 24097, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Razzashi Cobra - In Combat - Cast \'Poison\'');
-- High Priest Venoxis (GUID: 49194) and Razzashi Cobra (GUID: 52323-52326) creature formation
DELETE FROM `creature_formations` WHERE `leaderGUID` = 49194;
INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES
(49194, 49194, 0, 0, 27, 0, 0),
(49194, 52323, 0, 0, 27, 0, 0),
(49194, 52324, 0, 0, 27, 0, 0),
(49194, 52325, 0, 0, 27, 0, 0),
(49194, 52326, 0, 0, 27, 0, 0);
-- High Priest Venoxis (GUID: 49194) and Razzashi Cobra (GUID: 52323-52326) linked respawn
DELETE FROM `linked_respawn` WHERE `linkedGuid` = 49194;
INSERT INTO `linked_respawn` (`guid`, `linkedGuid`, `linkType`) VALUES
(52323, 49194, 0),
(52324, 49194, 0),
(52325, 49194, 0),
(52326, 49194, 0);

View File

@@ -33,43 +33,25 @@ enum Says
enum Spells
{
// troll form
// High Priest Venoxis (14507)
// All Phases
SPELL_THRASH = 3391,
// Phase 1 - Troll Form
SPELL_DISPEL_MAGIC = 23859,
SPELL_RENEW = 23895,
SPELL_HOLY_NOVA = 23858,
SPELL_HOLY_FIRE = 23860,
SPELL_HOLY_WRATH = 23979,
// snake form
// Transform
SPELL_VENOXIS_TRANSFORM = 23849,
// Phase 2 - Snake Form
SPELL_POISON_CLOUD = 23861,
SPELL_VENOM_SPIT = 23862,
SPELL_PARASITIC_SERPENT = 23865,
SPELL_SUMMON_PARASITIC_SERPENT = 23866,
SPELL_PARASITIC_SERPENT_TRIGGER = 23867,
// used when swapping event-stages
SPELL_VENOXIS_TRANSFORM = 23849, // 50% health - shapechange to cobra
SPELL_FRENZY = 8269, // 20% health - frenzy
SPELL_POISON = 24097
};
enum Events
{
// troll form
EVENT_THRASH = 1,
EVENT_DISPEL_MAGIC = 2,
EVENT_RENEW = 3,
EVENT_HOLY_NOVA = 4,
EVENT_HOLY_FIRE = 5,
EVENT_HOLY_WRATH = 6,
// phase-changing
EVENT_TRANSFORM = 7,
// snake form events
EVENT_POISON_CLOUD = 8,
EVENT_VENOM_SPIT = 9,
EVENT_PARASITIC_SERPENT = 10,
EVENT_FRENZY = 11,
EVENT_POISON
SPELL_FRENZY = 8269,
};
enum Phases
@@ -80,275 +62,114 @@ enum Phases
enum NPCs
{
NPC_PARASITIC_SERPENT = 14884,
NPC_RAZZASHI_COBRA = 11373,
BOSS_VENOXIS = 14507
BOSS_VENOXIS = 14507,
NPC_RAZZASHI_COBRA = 11373,
NPC_PARASITIC_SERPENT = 14884
};
class boss_venoxis : public CreatureScript
// High Priest Venoxis (14507)
struct boss_venoxis : public BossAI
{
public:
boss_venoxis() : CreatureScript("boss_venoxis") { }
boss_venoxis(Creature* creature) : BossAI(creature, DATA_VENOXIS) { }
struct boss_venoxisAI : public BossAI
void InitializeAI() override
{
boss_venoxisAI(Creature* creature) : BossAI(creature, DATA_VENOXIS) { }
void Reset() override
scheduler.SetValidator([this]
{
_Reset();
// remove all spells and auras from previous attempts
me->RemoveAllAuras();
me->SetReactState(REACT_PASSIVE);
// set some internally used variables to their defaults
_inMeleeRange = 0;
_transformed = false;
_frenzied = false;
events.SetPhase(PHASE_ONE);
return !me->HasUnitState(UNIT_STATE_CASTING);
});
SpawnCobras();
}
void JustDied(Unit* /*killer*/) override
{
_JustDied();
Talk(SAY_VENOXIS_DEATH);
me->RemoveAllAuras();
}
void SpawnCobras()
{
me->SummonCreature(NPC_RAZZASHI_COBRA, -12021.20f, -1719.73f, 39.34f, 0.85f, TEMPSUMMON_CORPSE_DESPAWN);
me->SummonCreature(NPC_RAZZASHI_COBRA, -12029.40f, -1714.54f, 39.36f, 0.68f, TEMPSUMMON_CORPSE_DESPAWN);
me->SummonCreature(NPC_RAZZASHI_COBRA, -12036.79f, -1704.27f, 40.06f, 0.45f, TEMPSUMMON_CORPSE_DESPAWN);
me->SummonCreature(NPC_RAZZASHI_COBRA, -12037.70f, -1694.20f, 39.35f, 0.27f, TEMPSUMMON_CORPSE_DESPAWN);
}
void SetCombatCombras()
{
std::list<Creature*> cobraList;
me->GetCreatureListWithEntryInGrid(cobraList, NPC_RAZZASHI_COBRA, 50.0f);
if (!cobraList.empty())
{
for (auto& cobras : cobraList)
{
cobras->SetInCombatWithZone();
}
}
}
void JustEngagedWith(Unit* /*who*/) override
{
_JustEngagedWith();
me->SetReactState(REACT_AGGRESSIVE);
// Always running events
events.ScheduleEvent(EVENT_THRASH, 5s);
// Phase one events (regular form)
events.ScheduleEvent(EVENT_HOLY_NOVA, 5s, 15s, 0, PHASE_ONE);
events.ScheduleEvent(EVENT_DISPEL_MAGIC, 35s, 0, PHASE_ONE);
events.ScheduleEvent(EVENT_HOLY_FIRE, 10s, 20s, 0, PHASE_ONE);
events.ScheduleEvent(EVENT_RENEW, 30s, 0, PHASE_ONE);
events.ScheduleEvent(EVENT_HOLY_WRATH, 15s, 25s, 0, PHASE_ONE);
events.SetPhase(PHASE_ONE);
// Set zone in combat
DoZoneInCombat();
SetCombatCombras();
}
void DamageTaken(Unit*, uint32& /*damage*/, DamageEffectType, SpellSchoolMask) override
{
// check if venoxis is ready to transform
if (!_transformed && !HealthAbovePct(50))
{
_transformed = true;
// schedule the event that changes our phase
events.ScheduleEvent(EVENT_TRANSFORM, 100ms);
}
// we're losing health, bad, go frenzy
else if (!_frenzied && !HealthAbovePct(20))
{
_frenzied = true;
events.ScheduleEvent(EVENT_FRENZY, 100ms);
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
// return back to main code if we're still casting
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
// thrash is available in all phases
case EVENT_THRASH:
DoCast(me, SPELL_THRASH, true);
events.ScheduleEvent(EVENT_THRASH, 10s, 20s);
break;
// troll form spells and Actions (first part)
case EVENT_DISPEL_MAGIC:
DoCast(me, SPELL_DISPEL_MAGIC);
events.ScheduleEvent(EVENT_DISPEL_MAGIC, 15s, 20s, 0, PHASE_ONE);
break;
case EVENT_RENEW:
DoCast(me, SPELL_RENEW);
events.ScheduleEvent(EVENT_RENEW, 25s, 30s, 0, PHASE_ONE);
break;
case EVENT_HOLY_WRATH:
if (Unit* target = SelectTarget(SelectTargetMethod::MaxThreat))
DoCast(target, SPELL_HOLY_WRATH);
events.ScheduleEvent(EVENT_HOLY_WRATH, 12s, 22s, 0, PHASE_ONE);
break;
case EVENT_HOLY_FIRE:
if (Unit* target = SelectTarget(SelectTargetMethod::Random))
DoCast(target, SPELL_HOLY_FIRE);
events.ScheduleEvent(EVENT_HOLY_FIRE, 10s, 24s, 0, PHASE_ONE);
break;
case EVENT_HOLY_NOVA:
DoCastSelf(SPELL_HOLY_NOVA);
events.ScheduleEvent(EVENT_HOLY_NOVA, 10s, 24s, 0, PHASE_ONE);
break;
//
// snake form spells and Actions
//
case EVENT_VENOM_SPIT:
if (Unit* target = SelectTarget(SelectTargetMethod::Random))
DoCast(target, SPELL_VENOM_SPIT);
events.ScheduleEvent(EVENT_VENOM_SPIT, 5s, 15s, 0, PHASE_TWO);
break;
case EVENT_POISON_CLOUD:
if (Unit* target = SelectTarget(SelectTargetMethod::Random))
DoCast(target, SPELL_POISON_CLOUD);
events.ScheduleEvent(EVENT_POISON_CLOUD, 15s, 20s, 0, PHASE_TWO);
break;
case EVENT_PARASITIC_SERPENT:
if (Unit* target = SelectTarget(SelectTargetMethod::Random))
DoCast(target, SPELL_SUMMON_PARASITIC_SERPENT);
events.ScheduleEvent(EVENT_PARASITIC_SERPENT, 15s, 0, PHASE_TWO);
break;
case EVENT_FRENZY:
// frenzy at 20% health
DoCast(me, SPELL_FRENZY, true);
break;
//
// shape and phase-changing
//
case EVENT_TRANSFORM:
// shapeshift at 50% health
DoCast(me, SPELL_VENOXIS_TRANSFORM);
Talk(SAY_VENOXIS_TRANSFORM);
DoResetThreatList();
// phase two events (snakeform)
events.ScheduleEvent(EVENT_VENOM_SPIT, 5s, 0, PHASE_TWO);
events.ScheduleEvent(EVENT_POISON_CLOUD, 10s, 0, PHASE_TWO);
events.ScheduleEvent(EVENT_PARASITIC_SERPENT, 30s, 0, PHASE_TWO);
// transformed, start phase two
events.SetPhase(PHASE_TWO);
break;
default:
break;
}
}
DoMeleeAttackIfReady();
}
private:
uint8 _inMeleeRange;
bool _transformed;
bool _frenzied;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetZulGurubAI<boss_venoxisAI>(creature);
Reset();
}
};
class npc_razzashi_cobra_venoxis : public CreatureScript
{
public:
npc_razzashi_cobra_venoxis() : CreatureScript("npc_razzashi_cobra_venoxis") {}
struct npc_razzashi_cobra_venoxis_AI : public ScriptedAI
void Reset() override
{
npc_razzashi_cobra_venoxis_AI(Creature* creature) : ScriptedAI(creature) {}
BossAI::Reset();
EventMap events;
me->RemoveAllAuras();
me->SetReactState(REACT_PASSIVE);
}
void Reset()
{
events.Reset();
}
void JustEngagedWith(Unit*)
{
events.ScheduleEvent(EVENT_POISON, 8s);
if (Creature* Venoxis = GetVenoxis())
{
Venoxis->SetInCombatWithZone();
}
}
Creature* GetVenoxis()
{
return me->FindNearestCreature(BOSS_VENOXIS, 200.0f, true);
}
void UpdateAI(uint32 diff)
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_POISON:
{
me->CastSpell(me->GetVictim(), SPELL_POISON);
events.ScheduleEvent(EVENT_POISON, 15s);
break;
}
}
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* creature) const override
void JustEngagedWith(Unit* /*who*/) override
{
return new npc_razzashi_cobra_venoxis_AI(creature);
_JustEngagedWith();
me->SetReactState(REACT_AGGRESSIVE);
// Both phases
scheduler.Schedule(8s, [this](TaskContext context)
{
DoCastSelf(SPELL_THRASH, true);
context.Repeat(10s, 20s);
});
//
// Phase 1 - Troll Form
//
scheduler.Schedule(5s, 15s, PHASE_ONE, [this](TaskContext context)
{
DoCastSelf(SPELL_HOLY_NOVA);
context.Repeat(10s, 24s);
}).Schedule(35s, PHASE_ONE, [this](TaskContext context)
{
DoCastSelf(SPELL_DISPEL_MAGIC);
context.Repeat(15s, 20s);
}).Schedule(10s, 20s, PHASE_ONE, [this](TaskContext context)
{
DoCastRandomTarget(SPELL_HOLY_FIRE);
context.Repeat(10s, 24s);
}).Schedule(30s, PHASE_ONE, [this](TaskContext context)
{
DoCastSelf(SPELL_RENEW);
context.Repeat(25s, 30s);
}).Schedule(15s, 25s, PHASE_ONE, [this](TaskContext context)
{
DoCastRandomTarget(SPELL_HOLY_WRATH);
context.Repeat(12s, 22s);
});
//
// Phase 2 - Snake Form (50% health)
//
ScheduleHealthCheckEvent(50, [&]
{
scheduler.CancelGroup(PHASE_ONE);
DoCastSelf(SPELL_VENOXIS_TRANSFORM);
Talk(SAY_VENOXIS_TRANSFORM);
DoResetThreatList();
scheduler.Schedule(5s, PHASE_TWO, [this](TaskContext context)
{
DoCastSelf(SPELL_VENOM_SPIT);
context.Repeat(5s, 15s);
}).Schedule(10s, PHASE_TWO, [this](TaskContext context)
{
DoCastSelf(SPELL_POISON_CLOUD);
context.Repeat(15s, 20s);
}).Schedule(30s, PHASE_TWO, [this](TaskContext context)
{
DoCastSelf(SPELL_SUMMON_PARASITIC_SERPENT);
context.Repeat(15s);
});
// frenzy at 20% health
ScheduleHealthCheckEvent(20, [&]
{
DoCastSelf(SPELL_FRENZY, true);
});
});
}
void JustDied(Unit* killer) override
{
BossAI::JustDied(killer);
Talk(SAY_VENOXIS_DEATH);
me->RemoveAllAuras(); // removes transform
}
};
void AddSC_boss_venoxis()
{
new boss_venoxis();
new npc_razzashi_cobra_venoxis();
RegisterCreatureAI(boss_venoxis);
}