From 586590e06f7cf130845a784121a7b387867c9f57 Mon Sep 17 00:00:00 2001 From: Acentech Dev Date: Tue, 21 Jul 2026 16:19:07 +0300 Subject: [PATCH] feat(tvt): test-phase statue HP override, stationary guards, in-game rename - Statue HP overridden to 100k at spawn (MaximumHealthOverride) for the test phase - no DB change. - Guards made fully stationary by overriding their definition's IntelligenceTypeName to NullMonsterIntelligence at runtime (no wander, no chase); no DB change. - Statue/guard in-game names rebranded to 'TvT Statue' / 'TvT Guard' (runtime designation override). --- .../MiniGames/HeykelSavasiContext.cs | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/GameLogic/MiniGames/HeykelSavasiContext.cs b/src/GameLogic/MiniGames/HeykelSavasiContext.cs index d091d64..81a047d 100644 --- a/src/GameLogic/MiniGames/HeykelSavasiContext.cs +++ b/src/GameLogic/MiniGames/HeykelSavasiContext.cs @@ -120,6 +120,21 @@ public class HeykelSavasiContext : MiniGameContext (459, 56, 58), }; + /// + /// TEST-PHASE statue health: overrides the statue definition's real (3,000,000) health at spawn via + /// , so statues can be fully broken within a match + /// while tuning. Applied purely at spawn time (no DB/config change); raise or remove after testing. + /// + private const int StatueTestHealth = 100_000; + + /// + /// Assembly-qualified type name of the NPC intelligence used to make the statue guards completely + /// STATIONARY (no wandering, no chasing): they stay at their fixed spawn tile next to the statue until + /// killed. Applied by overriding the guard definition's IntelligenceTypeName at runtime (see + /// ), so no configuration/DB change is needed. + /// + private const string StationaryGuardIntelligenceTypeName = "MUnique.OpenMU.GameLogic.NPC.NullMonsterIntelligence, MUnique.OpenMU.GameLogic"; + /// /// Maps a destroyed statue's index (0..5) to the /// of the class buff granted to the whole attacking team. All of these effects already exist in @@ -774,6 +789,9 @@ public class HeykelSavasiContext : MiniGameContext return; } + // Rename the in-game statue name to the event branding (runtime override, no DB change). + statueDefinition.Designation = "TvT Statue"; + // Distinct spawn-index ranges per (defender, index), so the up-front spawns never collide: // e.g. Red index 0 -> 1000..1003, Blue index 3 -> 2030..2033. var spawnIndexBase = ((int)defender * 1000) + (index * 10); @@ -788,6 +806,10 @@ public class HeykelSavasiContext : MiniGameContext Y2 = pos.Y, Direction = Direction.South, SpawnTrigger = SpawnTrigger.OnceAtEventStart, + + // TEST PHASE: lower the statue's effective HP so it can be broken within a match (see + // StatueTestHealth). Overrides the definition's 3M health only for this spawn - no DB change. + MaximumHealthOverride = StatueTestHealth, }; var statueNpc = await this._mapInitializer.InitializeSpawnAsync(spawnIndexBase, this.Map, statueSpawnArea, this).ConfigureAwait(false); @@ -805,6 +827,12 @@ public class HeykelSavasiContext : MiniGameContext return; } + // Runtime overrides (no DB change): make the guards fully STATIONARY next to the statue and + // brand their in-game name. Guard 580 is only used by this event, so mutating its shared + // definition here is safe and idempotent (re-applied on every event start). + guardDefinition.IntelligenceTypeName = StationaryGuardIntelligenceTypeName; + guardDefinition.Designation = "TvT Guard"; + var spawnedGuards = 0; for (var i = 0; i < GuardsPerStatue; i++) {