mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-25 22:56:24 +00:00
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:
@@ -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);
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user