Skip to content

refactor(Scripts/VioletHold): Modernize Violet Hold dungeon scripts#25187

Merged
Nyeriah merged 4 commits intoazerothcore:masterfrom
Nyeriah:vh
Apr 11, 2026
Merged

refactor(Scripts/VioletHold): Modernize Violet Hold dungeon scripts#25187
Nyeriah merged 4 commits intoazerothcore:masterfrom
Nyeriah:vh

Conversation

@Nyeriah
Copy link
Copy Markdown
Member

@Nyeriah Nyeriah commented Mar 22, 2026

Changes Proposed:

This PR proposes changes to:

  • Core (units, players, creatures, game systems).
  • Scripts (bosses, spell scripts, creature scripts).
  • Database (SAI, creatures, etc).

Full modernization of the Violet Hold instance and boss scripts, bringing them in line with modern AzerothCore conventions.

Script changes (12 files, net -483 lines):

  • Convert all 7 bosses from ScriptedAI to BossAI with encounter slot redirection — individual boss SetBossState calls (e.g. BOSS_MORAGG) are caught by the instance script and redirected to encounter slots (DATA_1ST_BOSS/DATA_2ND_BOSS) based on wave count
  • Instance script uses SetBossState/GetBossState instead of raw Encounter[] array
  • Add ObjectData arrays with LoadObjectData() for automatic creature/GO tracking, removing manual ObjectGuid members
  • Add RegisterVioletHoldCreatureAI macro; remove class wrappers from all boss and trash AI structs
  • Convert all trash mob manual uint32 timers to EventMap-based events
  • Remove redundant if (Instance) nullptr checks (guaranteed by registration macro)
  • Use StorePersistentData/GetPersistentData for boss selection instead of custom save/load
  • Use new HandleGameObject(uint32, bool) overload throughout
  • Fix IsEncounterInProgress() to return actual encounter state (was hardcoded false)
  • Fix save/load: SecondBoss was written but never loaded back
  • Fix variable naming per AzerothCore code standards (remove Hungarian notation)

Core change:

  • Add aliveOnly parameter to Map::GetPlayersCountExceptGMs() (default false, existing callers unaffected), excluding Spirit of Redemption players when set

AI-assisted Pull Requests

Important

While the use of AI tools when preparing pull requests is not prohibited, contributors must clearly disclose when such tools have been used and specify the model involved.

Contributors are also expected to fully understand the changes they are submitting and must be able to explain and justify those changes when requested by maintainers.

  • AI tools (e.g. ChatGPT, Claude, or similar) were used entirely or partially in preparing this pull request. Claude Code (claude-opus-4-6) was used for implementation with human review and direction at each step.

Issues Addressed:

  • No specific issue — modernization/code quality improvement

SOURCE:

The changes have been validated through:

  • Live research (checked on live servers, e.g Classic WotLK, Retail, etc.)
  • Sniffs (remember to share them with the open source community!)
  • Video evidence, knowledge databases or other public sources (e.g forums, Wowhead, etc.)
  • The changes promoted by this pull request come partially or entirely from another project (cherry-pick). The SetBossState encounter slot redirection pattern is based on TrinityCore's implementation by joschiwald, credited via Co-Authored-By.

Tests Performed:

This PR has been:

  • Tested in-game by the author.
  • Tested in-game by other community members/someone else other than the author/has been live on production servers.
  • This pull request requires further testing and may have edge cases to be tested.

How to Test the Changes:

  • This pull request can be tested by following the reproduction steps provided in the linked issue
  • This pull request requires further testing. Provide steps to test your changes. If it requires any specific setup e.g multiple players please specify it as well.
  1. Enter Violet Hold dungeon
  2. Start the encounter via Sinclari gossip
  3. Verify waves spawn correctly (trash at waves 1-5, boss at wave 6, trash at 7-11, boss at wave 12, trash at 13-17, Cyanigosa at wave 18)
  4. Verify boss evade resets the instance correctly
  5. Verify late-join teleport gossip works during encounter
  6. Verify instance resets properly when all players die
  7. Test activation crystal defense system
  8. Verify achievements (Defenseless, Dehydration, A Void Dance)

Known Issues and TODO List:

  • Needs in-game testing for all 6 random bosses + Cyanigosa
  • Save/load format changed — existing saved VH instances will need to be reset

How to Test AzerothCore PRs

When a PR is ready to be tested, it will be marked as [WAITING TO BE TESTED].

You can help by testing PRs and writing your feedback here on the PR's page on GitHub. Follow the instructions here:

http://www.azerothcore.org/wiki/How-to-test-a-PR

REMEMBER: when testing a PR that changes something generic (i.e. a part of code that handles more than one specific thing), the tester should not only check that the PR does its job (e.g. fixing spell XXX) but especially check that the PR does not cause any regression (i.e. introducing new bugs).

For example: if a PR fixes spell X by changing a part of code that handles spells X, Y, and Z, we should not only test X, but we should test Y and Z as well.

Copilot AI review requested due to automatic review settings March 22, 2026 16:17
@Nyeriah Nyeriah changed the title refactor(Core/Scripts): Modernize Violet Hold dungeon scripts refactor(Scripts/VioletHold): Modernize Violet Hold dungeon scripts Mar 22, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Modernizes the Violet Hold instance/boss scripts to newer AzerothCore conventions, and adds an optional “alive-only” player counting mode in core map utilities.

Changes:

  • Refactors Violet Hold instance/boss/trash scripts to use BossAI, EventMap, ObjectData/LoadObjectData(), and a new RegisterVioletHoldCreatureAI macro.
  • Reworks encounter state handling (slots + redirection) and cleanup logic, including fixing IsEncounterInProgress().
  • Extends Map::GetPlayersCountExceptGMs() with an aliveOnly flag used by Violet Hold cleanup.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/server/scripts/Northrend/VioletHold/violet_hold.h Introduces new VH enums/IDs and a registration macro to support modernized instance/object tracking.
src/server/scripts/Northrend/VioletHold/violet_hold.cpp Refactors gossip and multiple trash AIs to EventMap + registration macro; updates instance interactions.
src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp Reworks instance state, object tracking, boss-state routing, cleanup logic, and uses persistent data for boss selection.
src/server/scripts/Northrend/VioletHold/boss_zuramat.cpp Migrates Zuramat to BossAI and modernizes void sentry handling/instance interactions.
src/server/scripts/Northrend/VioletHold/boss_xevozz.cpp Migrates Xevozz to BossAI and updates summon tracking via instance GUID bookkeeping.
src/server/scripts/Northrend/VioletHold/boss_moragg.cpp Migrates Moragg to BossAI + event execution style.
src/server/scripts/Northrend/VioletHold/boss_lavanthor.cpp Migrates Lavanthor to BossAI + event execution style.
src/server/scripts/Northrend/VioletHold/boss_ichoron.cpp Migrates Ichoron to BossAI, reworks globule behavior, and replaces timers with EventMap.
src/server/scripts/Northrend/VioletHold/boss_erekem.cpp Migrates Erekem and guards to modern AI patterns and updates inter-AI coordination.
src/server/scripts/Northrend/VioletHold/boss_cyanigosa.cpp Migrates Cyanigosa to BossAI and keeps special vacuum/root behavior.
src/server/game/Maps/Map.h Adds the aliveOnly parameter to the public API (defaulting to current behavior).
src/server/game/Maps/Map.cpp Implements aliveOnly filtering, excluding Spirit of Redemption “alive” states.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +156 to 182
bool SetBossState(uint32 id, EncounterState state) override
{
if (!InstanceScript::SetBossState(id, state))
return false;

switch (id)
{
case BOSS_MORAGG:
case BOSS_EREKEM:
case BOSS_ICHORON:
case BOSS_LAVANTHOR:
case BOSS_XEVOZZ:
case BOSS_ZURAMAT:
if (state == DONE)
{
if (WaveCount == 6)
SetBossState(DATA_1ST_BOSS, DONE);
else if (WaveCount == 12)
SetBossState(DATA_2ND_BOSS, DONE);
events.RescheduleEvent(EVENT_SUMMON_PORTAL, 35s);
}
else if (state == NOT_STARTED)
{
_cleaned = false;
InstanceCleanup();
}
break;
Copy link

Copilot AI Mar 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The instance cleanup on boss reset only triggers when state == NOT_STARTED. BossAI commonly reports an evade as FAIL, not NOT_STARTED, which can leave the instance stuck (no cleanup/portal progression). Treat FAIL the same as NOT_STARTED here (and for DATA_CYANIGOSA below) so evades reliably reset the run.

Copilot uses AI. Check for mistakes.
void FinishPointReached()
{
IsOpening = true;
Count = 0;
Copy link

Copilot AI Mar 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This now casts SABOTEUR_SHIELD_DISRUPTION immediately and then schedules 3 more casts via EVENT_SABOTEUR_SHIELD_DISRUPTION (since Count is only incremented in the event handler). Previously the sequence was 3 casts total. Consider either removing the immediate cast and letting the event drive all casts, or initialize/increment Count so the total number of casts matches the prior behavior.

Suggested change
Count = 0;
Count = 1;

Copilot uses AI. Check for mistakes.
Comment on lines +146 to +191
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;

for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
if (Player* plr = i->GetSource())
me->CastSpell(plr, spellId, triggered);
}
events.Update(diff);

void JustEngagedWith(Unit* /*who*/) override
if (!IsFrenzy && !IsExploded && HealthBelowPct(25))
{
bIsExploded = false;
bIsFrenzy = false;
uiDrainedTimer = 15000;
uiWaterBoltVolleyTimer = urand(7000, 12000);
DoZoneInCombat();
Talk(SAY_AGGRO);
me->CastSpell(me, SPELL_PROTECTIVE_BUBBLE, true);
if (pInstance)
pInstance->SetData(DATA_ACHIEV, 1);
Talk(SAY_ENRAGE);
me->CastSpell(me, SPELL_FRENZY, true);
IsFrenzy = true;
}

void UpdateAI(uint32 uiDiff) override
if (!IsFrenzy)
{
if (!UpdateVictim())
return;

if (!bIsFrenzy && !bIsExploded && HealthBelowPct(25))
if (!IsExploded)
{
Talk(SAY_ENRAGE);
me->CastSpell(me, SPELL_FRENZY, true);
bIsFrenzy = true;
}

if (!bIsFrenzy)
{
if (!bIsExploded)
if (!me->HasAura(SPELL_PROTECTIVE_BUBBLE))
{
if (!me->HasAura(SPELL_PROTECTIVE_BUBBLE))
me->InterruptNonMeleeSpells(false);
Talk(SAY_SHATTER);
DoZoneInCombat();
IchoronDoCastToAllHostilePlayers(SPELL_WATER_BLAST, true);
me->CastSpell(me, SPELL_DRAINED, true);
IsExploded = true;
events.RescheduleEvent(EVENT_DRAINED_CHECK, 15s);
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
me->SetDisplayId(11686);
for (uint8 i = 0; i < MAX_SPAWN_LOC; ++i)
{
me->InterruptNonMeleeSpells(false);
Talk(SAY_SHATTER);
DoZoneInCombat();
IchoronDoCastToAllHostilePlayers(SPELL_WATER_BLAST, true);
me->CastSpell(me, SPELL_DRAINED, true);
bIsExploded = true;
uiDrainedTimer = 15000;
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
me->SetDisplayId(11686);
for (uint8 i = 0; i < MAX_SPAWN_LOC; ++i)
{
float angle = rand_norm() * 2 * M_PI;
Position p1(SpawnLoc[i]), p2(SpawnLoc[i]);
p1.m_positionX += 2.5f * cos(angle);
p1.m_positionY += 2.5f * std::sin(angle);
p2.m_positionX -= 2.5f * cos(angle);
p2.m_positionY -= 2.5f * std::sin(angle);
DoSummon(NPC_ICHOR_GLOBULE, p1, 60000, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN);
DoSummon(NPC_ICHOR_GLOBULE, p2, 60000, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN);
}
float angle = rand_norm() * 2 * M_PI;
Position p1(SpawnLoc[i]), p2(SpawnLoc[i]);
p1.m_positionX += 2.5f * cos(angle);
p1.m_positionY += 2.5f * std::sin(angle);
p2.m_positionX -= 2.5f * cos(angle);
p2.m_positionY -= 2.5f * std::sin(angle);
DoSummon(NPC_ICHOR_GLOBULE, p1, 60000, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN);
DoSummon(NPC_ICHOR_GLOBULE, p2, 60000, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN);
}
}
}
else
{
if (events.ExecuteEvent() == EVENT_DRAINED_CHECK)
DoExplodeCompleted();
Copy link

Copilot AI Mar 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While exploded, events.ExecuteEvent() is used as a single if check. If any other event (e.g., EVENT_WATER_BOLT_VOLLEY still queued from before the explosion) becomes due first, it will be consumed and ignored, permanently desynchronizing Ichoron’s spell schedule. Recommended fix: cancel/ignore EVENT_WATER_BOLT_VOLLEY when entering the exploded state (e.g., CancelEvent) and process events using an eventId variable (or a while loop over due events) so unrelated due events aren’t accidentally consumed.

Copilot uses AI. Check for mistakes.
Comment thread src/server/scripts/Northrend/VioletHold/boss_lavanthor.cpp Outdated
Comment on lines 855 to 863
uint32 ArcaneStreamTimerStartingValue;

void Reset() override
{
return GetVioletHoldAI<npc_azure_sorcerorAI>(creature);
events.Reset();
events.RescheduleEvent(EVENT_SORCEROR_ARCANE_STREAM, 4s);
ArcaneStreamTimerStartingValue = 4000;
events.RescheduleEvent(EVENT_SORCEROR_MANA_DETONATION, 5s);
}
Copy link

Copilot AI Mar 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The previous sorceror logic gated SPELL_MANA_DETONATION based on the current Arcane Stream cooldown window; the refactor now repeats Mana Detonation every 2–6s unconditionally (see EVENT_SORCEROR_MANA_DETONATION), which is a significant behavior change (likely much more frequent casts). Either reintroduce the original gating (using ArcaneStreamTimerStartingValue as intended) or adjust scheduling so detonation frequency matches prior behavior. As-is, ArcaneStreamTimerStartingValue is also written but never read, which suggests the gating was accidentally dropped.

Copilot uses AI. Check for mistakes.
@github-actions github-actions Bot added CORE Related to the core Script Refers to C++ Scripts for the Core file-cpp Used to trigger the matrix build labels Mar 22, 2026
@Nyeriah Nyeriah force-pushed the vh branch 2 times, most recently from bf1b966 to b00f212 Compare March 22, 2026 16:50
@Nyeriah Nyeriah requested a review from Copilot March 22, 2026 16:51
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated 7 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +919 to 925
_instance = c->GetInstanceScript();
_boss = _instance->GetData(DATA_WAVE_COUNT) == 6
? _instance->GetPersistentData(PERSISTENT_DATA_FIRST_BOSS)
: _instance->GetPersistentData(PERSISTENT_DATA_SECOND_BOSS);
_addedWaypoints = false;
_isOpening = false;
}
Copy link

Copilot AI Mar 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_boss is loaded from persistent data that now stores boss IDs (e.g., BOSS_MORAGG..BOSS_ZURAMAT), but the waypoint logic still switches on legacy 1..6 values. As a result, no case will match for boss IDs 3..8, preventing the saboteur from reaching the correct point and releasing the boss. Fix by switching on BOSS_MORAGG/BOSS_EREKEM/... (or map _boss to a 1..6 index like (_boss - BOSS_MORAGG + 1) before the switch) consistently in both WaypointReached and the waypoint-building logic.

Copilot uses AI. Check for mistakes.
Comment on lines +929 to 955
switch (_boss)
{
pInstance = c->GetInstanceScript();
uiBoss = 0;
if (pInstance)
uiBoss = pInstance->GetData(DATA_WAVE_COUNT) == 6 ? pInstance->GetData(DATA_FIRST_BOSS_NUMBER) : pInstance->GetData(DATA_SECOND_BOSS_NUMBER);
bAddedWPs = false;
bOpening = false;
case 1:
if (waypointId == 2)
FinishPointReached();
break;
case 2:
if (waypointId == 2)
FinishPointReached();
break;
case 3:
if (waypointId == 1)
FinishPointReached();
break;
case 4:
if (waypointId == 0)
FinishPointReached();
break;
case 5:
if (waypointId == 0)
FinishPointReached();
break;
case 6:
if (waypointId == 4)
FinishPointReached();
break;
}
Copy link

Copilot AI Mar 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_boss is loaded from persistent data that now stores boss IDs (e.g., BOSS_MORAGG..BOSS_ZURAMAT), but the waypoint logic still switches on legacy 1..6 values. As a result, no case will match for boss IDs 3..8, preventing the saboteur from reaching the correct point and releasing the boss. Fix by switching on BOSS_MORAGG/BOSS_EREKEM/... (or map _boss to a 1..6 index like (_boss - BOSS_MORAGG + 1) before the switch) consistently in both WaypointReached and the waypoint-building logic.

Copilot uses AI. Check for mistakes.
Comment thread src/server/scripts/Northrend/VioletHold/violet_hold.cpp Outdated
Comment on lines +159 to +160
if (Creature* c = DoSummon(RAND(NPC_PORTAL_GUARDIAN, NPC_PORTAL_KEEPER_1, NPC_PORTAL_KEEPER_2), me, 2.0f, 0, TEMPSUMMON_DEAD_DESPAWN))
DoCast(c, SPELL_PORTAL_CHANNEL);
Copy link

Copilot AI Mar 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

npc_vh_teleportation_portalAI now derives from NullCreatureAI but calls DoSummon/DoCast helpers. In AzerothCore/Trinity-style scripting these helpers are typically provided by ScriptedAI/BossAI (not NullCreatureAI), which can lead to compilation errors or unintended behavior depending on the base-class API. Prefer deriving this AI from ScriptedAI (or switch to explicit me->SummonCreature(...) / me->CastSpell(...) calls) to ensure the used helpers are valid.

Copilot uses AI. Check for mistakes.
Comment thread src/server/scripts/Northrend/VioletHold/violet_hold.cpp
Comment thread src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp
Comment thread src/server/game/Maps/Map.h
@Nyeriah
Copy link
Copy Markdown
Member Author

Nyeriah commented Mar 22, 2026

Regarding the NullCreatureAI comments on the portal AI: dismissed — the portal was already NullCreatureAI before this PR. DoSummon is defined on CreatureAI (the base of NullCreatureAI), not ScriptedAI, so it compiles and works correctly. The portal is passive (no combat behavior) so NullCreatureAI is the correct base.

@Nyeriah Nyeriah force-pushed the vh branch 3 times, most recently from 3946fcf to fbb24ea Compare March 22, 2026 18:49
Full modernization of the Violet Hold instance and boss scripts:

- Convert all bosses from ScriptedAI to BossAI with encounter slot
  redirection (individual boss states map to DATA_1ST_BOSS/DATA_2ND_BOSS
  based on wave count, following TrinityCore's pattern by joschiwald)
- Instance script uses SetBossState/GetBossState with override to handle
  wave progression and cleanup on evade
- Add ObjectData arrays with LoadObjectData() for automatic creature and
  gameobject tracking, removing manual ObjectGuid members
- Add RegisterVioletHoldCreatureAI macro; remove class wrappers from all
  boss and trash AI structs
- Convert all trash mob manual timers to EventMap-based events
- Remove redundant if(Instance) nullptr checks (guaranteed by registration
  macro)
- Use persistent data storage for boss selection instead of custom
  save/load
- Fix IsEncounterInProgress to return actual encounter state
- Fix save/load: SecondBoss was written but never loaded
- Add aliveOnly parameter to Map::GetPlayersCountExceptGMs(), excluding
  Spirit of Redemption; used in VH DoNeedCleanup
- Use new HandleGameObject(uint32, bool) overload throughout
- Fix variable naming per AzerothCore code standards

Co-Authored-By: joschiwald <joschiwald@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@chauusie
Copy link
Copy Markdown
Contributor

chauusie commented Apr 7, 2026

Tested:

Waves spawn correctly
Achievement: Void dance
Achievement: Defenseless
Dying resets the instance
Late instance teleport gossip during encounter tested a few times

Above all works grand

Crystal defense system seems a bit delayed when clicking them. I tried to use them on Icharon for the Dehydration achievement but they took so long to activate he still got a bunch of the water eles.

Cyanigosa seems to take longer than before to become active after turning into dragon form. Maybe imagining it, but feels like a few extra seconds there. No big deal anyway.

To do:
Evade boss - Unsure on how to get one to evade
Achievement: Dehydration

@Nyeriah
Copy link
Copy Markdown
Member Author

Nyeriah commented Apr 8, 2026

Crystal defense system seems a bit delayed when clicking them. I tried to use them on Icharon for the Dehydration achievement but they took so long to activate he still got a bunch of the water eles.

Cyanigosa seems to take longer than before to become active after turning into dragon form. Maybe imagining it, but feels like a few extra seconds there. No big deal anyway.

Hmm, this PR shouldn't have changed any of this

# Conflicts:
#	src/server/scripts/Northrend/VioletHold/boss_xevozz.cpp
#	src/server/scripts/Northrend/VioletHold/violet_hold.cpp
@chauusie
Copy link
Copy Markdown
Contributor

chauusie commented Apr 8, 2026

The cynagosa one may be me imagining it as I'm used to doing it as 5man where there's others around and more going on and boss fight prep. When alone it could just be that delay is highlighted tbh so can ignore that.

The crystals.. I have never used them in game myself but I assumed they should go off instantly? I was right next to one and clicked when Icharon did his thing and 2 eles got to him before it went off

I'll go in there again today and see if I can get icharon again

@chauusie
Copy link
Copy Markdown
Contributor

chauusie commented Apr 8, 2026

Achievement: Dehydration works

Crystals take 4-5 seconds from clicking them to killing the current mobs, as seen

violet.crystals.mp4

But the delay could be normal, a quick search says it takes 'a second' and the one video I could find with it, in the right time frame of OG wrath, another player goes up to one in the background and it takes a few seconds before the mobs die, that's assuming the player pressed the crystal as soon as they could. I did a run in game to see how they are and it takes about the same amount of time so I figure the crystals are a none issue.

Only thing I haven't tested for this one is evading a boss as I can't get one to evade, but other than that everything seems grand!

@chauusie
Copy link
Copy Markdown
Contributor

I got a notification this has been updated, do you need me to test it again, or a different aspect?

@Nyeriah
Copy link
Copy Markdown
Member Author

Nyeriah commented Apr 11, 2026

No, its just the build that needed fixing, thanks

@Nyeriah Nyeriah merged commit 272da9f into azerothcore:master Apr 11, 2026
17 checks passed
@Nyeriah Nyeriah deleted the vh branch April 11, 2026 16:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CORE Related to the core file-cpp Used to trigger the matrix build Ready to be Reviewed Script Refers to C++ Scripts for the Core Waiting to be Tested

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants