fix(Core/Scripts): refactor Violet Hold to use DoAction and move gossip to DB (#25456)

Co-authored-by: Tartalo <none@none>
Co-authored-by: profPlum <dwyerfire@gmail.com>
Co-authored-by: Nay <dnpd.dd@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Andrew
2026-04-14 04:40:26 -03:00
committed by GitHub
parent db2e1325d2
commit 51208baf4a
4 changed files with 103 additions and 129 deletions

View File

@@ -189,19 +189,20 @@ public:
return true;
}
void SetData(uint32 type, uint32 data) override
void ProcessEvent(WorldObject* /*obj*/, uint32 eventId) override
{
switch (type)
if (eventId == EVENT_ACTIVATE_CRYSTAL)
{
case DATA_ACTIVATE_DEFENSE_SYSTEM:
{
if (data)
_defensesUsed = true;
Position const pos = {1919.09546f, 812.29724f, 86.2905f, M_PI};
instance->SummonCreature(NPC_DEFENSE_SYSTEM, pos, 0, 6499);
}
break;
case DATA_START_INSTANCE:
_defensesUsed = true;
SummonDefenseSystem();
}
}
void DoAction(int32 action) override
{
switch (action)
{
case ACTION_START_INSTANCE:
if (_encounterStatus == NOT_STARTED)
{
_encounterStatus = IN_PROGRESS;
@@ -214,13 +215,10 @@ public:
_events.RescheduleEvent(EVENT_CHECK_PLAYERS, 5s);
}
break;
case DATA_PORTAL_DEFEATED:
case ACTION_PORTAL_DEFEATED:
_events.RescheduleEvent(EVENT_SUMMON_PORTAL, 3s);
break;
case DATA_PORTAL_LOCATION:
_portalLocation = data;
break;
case DATA_DECREASE_DOOR_HEALTH:
case ACTION_DECREASE_DOOR_HEALTH:
if (_gateHealth > 0)
--_gateHealth;
if (_gateHealth == 0)
@@ -230,12 +228,22 @@ public:
}
DoUpdateWorldState(WORLD_STATE_VIOLET_HOLD_PRISON_STATE, (uint32)_gateHealth);
break;
case DATA_RELEASE_BOSS:
case ACTION_RELEASE_BOSS:
if (_waveCount == 6)
StartBossEncounter(GetPersistentData(PERSISTENT_DATA_FIRST_BOSS));
else
StartBossEncounter(GetPersistentData(PERSISTENT_DATA_SECOND_BOSS));
break;
}
}
void SetData(uint32 type, uint32 data) override
{
switch (type)
{
case DATA_PORTAL_LOCATION:
_portalLocation = data;
break;
case DATA_ACHIEV:
_achievementCompleted = !!data;
break;
@@ -370,14 +378,14 @@ public:
sinclari->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
sinclari->GetMotionMaster()->MovePoint(0, sinclariOutsidePosition);
}
SetData(DATA_ACTIVATE_DEFENSE_SYSTEM, 0);
SummonDefenseSystem();
_events.RescheduleEvent(EVENT_START_ENCOUNTER, 4s);
break;
case EVENT_START_ENCOUNTER:
if (Creature* sinclari = GetCreature(DATA_SINCLARI))
{
sinclari->AI()->Talk(SAY_SINCLARI_DOOR_LOCK);
sinclari->SetVisible(false);
sinclari->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
}
if (Creature* doorSeal = GetCreature(DATA_DOOR_SEAL))
doorSeal->RemoveAllAuras();
@@ -583,6 +591,12 @@ public:
return false;
}
void SummonDefenseSystem()
{
Position const pos = {1919.09546f, 812.29724f, 86.2905f, M_PI};
instance->SummonCreature(NPC_DEFENSE_SYSTEM, pos, 0, 6499);
}
private:
bool _cleaned{ false };
uint8 _encounterStatus{ NOT_STARTED };

View File

@@ -17,102 +17,14 @@
#include "violet_hold.h"
#include "CreatureScript.h"
#include "GameObjectScript.h"
#include "PassiveAI.h"
#include "Player.h"
#include "ScriptedCreature.h"
#include "ScriptedEscortAI.h"
#include "ScriptedGossip.h"
#include "SpellScript.h"
#include "SpellScriptLoader.h"
/// @todo: Missing Sinclari Trigger announcements (32204) Look at its creature_text for more info.
enum Texts
{
GOSSIP_MENU_START_1 = 9997,
GOSSIP_MENU_START_2 = 9998,
GOSSIP_MENU_LATE_JOIN = 10275,
NPC_TEXT_SINCLARI_IN = 13853,
NPC_TEXT_SINCLARI_START = 13854,
NPC_TEXT_SINCLARI_DONE = 13910,
NPC_TEXT_SINCLARI_LATE_JOIN = 14271,
};
/***********
** DEFENSE SYSTEM CRYSTAL
***********/
class go_vh_activation_crystal : public GameObjectScript
{
public:
go_vh_activation_crystal() : GameObjectScript("go_vh_activation_crystal") { }
bool OnGossipHello(Player* /*player*/, GameObject* go) override
{
if (InstanceScript* Instance = go->GetInstanceScript())
{
Instance->SetData(DATA_ACTIVATE_DEFENSE_SYSTEM, 1);
go->SetGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
}
return true;
}
};
/***********
** SINCLARI
***********/
class npc_vh_sinclari : public CreatureScript
{
public:
npc_vh_sinclari() : CreatureScript("npc_vh_sinclari") { }
bool OnGossipHello(Player* player, Creature* creature) override
{
if (InstanceScript* Instance = creature->GetInstanceScript())
switch (Instance->GetData(DATA_ENCOUNTER_STATUS))
{
case NOT_STARTED:
AddGossipItemFor(player, GOSSIP_MENU_START_1, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
SendGossipMenuFor(player, NPC_TEXT_SINCLARI_IN, creature->GetGUID());
break;
case IN_PROGRESS:
AddGossipItemFor(player, GOSSIP_MENU_LATE_JOIN, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
SendGossipMenuFor(player, NPC_TEXT_SINCLARI_LATE_JOIN, creature->GetGUID());
break;
default:
SendGossipMenuFor(player, NPC_TEXT_SINCLARI_DONE, creature->GetGUID());
}
return true;
}
bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override
{
ClearGossipMenuFor(player);
switch (action)
{
case GOSSIP_ACTION_INFO_DEF+1:
AddGossipItemFor(player, GOSSIP_MENU_START_2, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
SendGossipMenuFor(player, NPC_TEXT_SINCLARI_START, creature->GetGUID());
break;
case GOSSIP_ACTION_INFO_DEF+2:
CloseGossipMenuFor(player);
if (InstanceScript* Instance = creature->GetInstanceScript())
Instance->SetData(DATA_START_INSTANCE, 1);
break;
case GOSSIP_ACTION_INFO_DEF+3:
player->NearTeleportTo(playerTeleportPosition.GetPositionX(), playerTeleportPosition.GetPositionY(), playerTeleportPosition.GetPositionZ(), playerTeleportPosition.GetOrientation(), true);
CloseGossipMenuFor(player);
break;
}
return true;
}
};
/***********
** TELEPORTATION PORTAL
***********/
@@ -213,7 +125,7 @@ struct npc_vh_teleportation_portal : public NullCreatureAI
_events.Reset();
if (_wave % 6 == 0)
return;
_instance->SetData(DATA_PORTAL_DEFEATED, 0);
_instance->DoAction(ACTION_PORTAL_DEFEATED);
}
void JustSummoned(Creature* summoned) override
@@ -1012,7 +924,7 @@ struct npc_azure_saboteur : public npc_escortAI
_events.RescheduleEvent(EVENT_SABOTEUR_SHIELD_DISRUPTION, 1s);
else
{
_instance->SetData(DATA_RELEASE_BOSS, 0);
_instance->DoAction(ACTION_RELEASE_BOSS);
_events.RescheduleEvent(EVENT_SABOTEUR_DISAPPEAR, 500ms);
}
break;
@@ -1059,7 +971,7 @@ class spell_destroy_door_seal_aura : public AuraScript
PreventDefaultAction();
if (Unit* target = GetTarget())
if (InstanceScript* Instance = target->GetInstanceScript())
Instance->SetData(DATA_DECREASE_DOOR_HEALTH, 0);
Instance->DoAction(ACTION_DECREASE_DOOR_HEALTH);
}
void Register() override
@@ -1070,13 +982,16 @@ class spell_destroy_door_seal_aura : public AuraScript
struct npc_violet_hold_defense_system : public ScriptedAI
{
npc_violet_hold_defense_system(Creature* creature) : ScriptedAI(creature) { }
npc_violet_hold_defense_system(Creature* creature) : ScriptedAI(creature)
{
_tickCount = 0;
}
void Reset() override
{
_tickCount = 0;
DoCast(RAND(SPELL_DEFENSE_SYSTEM_SPAWN_EFFECT, SPELL_DEFENSE_SYSTEM_VISUAL));
events.ScheduleEvent(EVENT_ARCANE_LIGHTNING, 4s);
events.ScheduleEvent(EVENT_ARCANE_LIGHTNING_INSTAKILL, 4s);
me->DespawnOrUnsummon(7s, 0s);
}
@@ -1084,25 +999,24 @@ struct npc_violet_hold_defense_system : public ScriptedAI
{
events.Update(diff);
switch (events.ExecuteEvent())
if (events.ExecuteEvent() == EVENT_ARCANE_LIGHTNING)
{
case EVENT_ARCANE_LIGHTNING:
DoCastAOE(RAND(SPELL_ARCANE_LIGHTNING, SPELL_ARCANE_LIGHTNING_VISUAL));
events.Repeat(2s);
break;
case EVENT_ARCANE_LIGHTNING_INSTAKILL:
DoCastAOE(SPELL_ARCANE_LIGHTNING);
DoCastAOE(SPELL_ARCANE_LIGHTNING_VISUAL);
if (++_tickCount >= 3)
DoCastAOE(SPELL_ARCANE_LIGHTNING_INSTAKILL);
else
events.Repeat(1s);
break;
}
}
private:
uint8 _tickCount;
};
void AddSC_violet_hold()
{
new go_vh_activation_crystal();
new npc_vh_sinclari();
RegisterVioletHoldCreatureAI(npc_vh_teleportation_portal);
RegisterVioletHoldCreatureAI(npc_azure_saboteur);

View File

@@ -43,17 +43,12 @@ enum VHData
DATA_XEVOZZ_CELL,
DATA_ZURAMAT_CELL,
// Instance action/state IDs (used by SetData/GetData)
// Instance state IDs (used by SetData/GetData)
DATA_ENCOUNTER_STATUS = 30,
DATA_ACTIVATE_DEFENSE_SYSTEM,
DATA_START_INSTANCE,
DATA_ADD_TRASH_MOB,
DATA_DELETE_TRASH_MOB,
DATA_PORTAL_DEFEATED,
DATA_WAVE_COUNT,
DATA_PORTAL_LOCATION,
DATA_RELEASE_BOSS,
DATA_DECREASE_DOOR_HEALTH,
DATA_ACHIEV,
// Manual GUID tracking (multi-instance entries)
@@ -61,6 +56,14 @@ enum VHData
DATA_EREKEM_GUARD_2_GUID,
};
enum VHActions
{
ACTION_START_INSTANCE = 1,
ACTION_PORTAL_DEFEATED,
ACTION_RELEASE_BOSS,
ACTION_DECREASE_DOOR_HEALTH,
};
enum VHPersistentData
{
PERSISTENT_DATA_FIRST_BOSS,
@@ -165,7 +168,9 @@ enum VHInstanceEvents
// Event defense system
EVENT_ARCANE_LIGHTNING,
EVENT_ARCANE_LIGHTNING_INSTAKILL
// Spell event (SPELL_EFFECT_SEND_EVENT from spell 57804)
EVENT_ACTIVATE_CRYSTAL = 20001,
};
enum VHAchievCriteria