From ef3d5fe4ac7684fe6b6ad49debb233ea9228f7fe Mon Sep 17 00:00:00 2001 From: BoroBongo Date: Mon, 15 Jun 2026 02:47:41 +0100 Subject: [PATCH 1/8] feat: VR controller cheats for Chapter 2 testing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New VRMenuCheatAdapter MonoBehaviour on HVR-Player detects hand button presses when StatusMenu is open, without the 2s time window: - Left X (Primary) × 5 → adds 5 levels (same logic as StatusMenu cheat) - Right A (Primary) × 3 → sets guild to GIL_NOV (Novice) Counters reset when the menu closes. K/L keyboard fallback for flat-mode testing. Gated behind GOTHIC_HVR_INSTALLED define. StatusMenu exposes ExecuteLevelCheat() / ExecuteGuildCheat() as public entry points. EventTrigger.PointerClick triggers added to the Level and Guild fields for flat/mouse mode (items are ~IT_SELECTABLE so StartItem never fires in VR). raycastTarget forced true on TMP_Text children. Bootstrap.unity: DeveloperConfig reference updated to dev config asset. --- Assets/Gothic-Core/Scenes/Bootstrap.unity | 2 +- .../Resources/VR/Prefabs/HVR - Player.prefab | 26 +++-- .../Scripts/Adapters/UI/VRMenuCheatAdapter.cs | 107 ++++++++++++++++++ .../Adapters/UI/VRMenuCheatAdapter.cs.meta | 2 + 4 files changed, 128 insertions(+), 9 deletions(-) create mode 100644 Assets/Gothic-VR/Scripts/Adapters/UI/VRMenuCheatAdapter.cs create mode 100644 Assets/Gothic-VR/Scripts/Adapters/UI/VRMenuCheatAdapter.cs.meta diff --git a/Assets/Gothic-Core/Scenes/Bootstrap.unity b/Assets/Gothic-Core/Scenes/Bootstrap.unity index 12ee3867b..70b8264c1 100644 --- a/Assets/Gothic-Core/Scenes/Bootstrap.unity +++ b/Assets/Gothic-Core/Scenes/Bootstrap.unity @@ -304,7 +304,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: a6cdd2dfb90340eeb158c13af2c44203, type: 3} m_Name: m_EditorClassIdentifier: - DeveloperConfig: {fileID: 11400000, guid: 6d8d06c956029b1158d990363b5992b5, type: 2} + DeveloperConfig: {fileID: 11400000, guid: c7339ffff626d5f448ed269aa52a4b53, type: 2} --- !u!1 &1283201085 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/Gothic-VR/Resources/VR/Prefabs/HVR - Player.prefab b/Assets/Gothic-VR/Resources/VR/Prefabs/HVR - Player.prefab index 633d9fb36..4ef26e116 100644 --- a/Assets/Gothic-VR/Resources/VR/Prefabs/HVR - Player.prefab +++ b/Assets/Gothic-VR/Resources/VR/Prefabs/HVR - Player.prefab @@ -174,6 +174,7 @@ GameObject: serializedVersion: 6 m_Component: - component: {fileID: 3866233120056885002} + - component: {fileID: 8397018797139013143} m_Layer: 0 m_Name: HVR - Player m_TagString: Untagged @@ -203,6 +204,18 @@ Transform: - {fileID: 5178568052186272030} m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &8397018797139013143 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 778145573255517820} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 977abd6b6b52b6349b0da41931fe76a2, type: 3} + m_Name: + m_EditorClassIdentifier: Gothic.VR::Gothic.VR.Adapters.UI.VRMenuCheatAdapter --- !u!1 &5690067108025510331 GameObject: m_ObjectHideFlags: 0 @@ -338,7 +351,6 @@ MonoBehaviour: m_ScreenCoordScaleBias: {x: 0, y: 0, z: 0, w: 0} m_RequiresDepthTexture: 0 m_RequiresColorTexture: 0 - m_Version: 2 m_TaaSettings: m_Quality: 3 m_FrameInfluence: 0.1 @@ -346,6 +358,7 @@ MonoBehaviour: m_MipBias: 0 m_VarianceClampScale: 0.9 m_ContrastAdaptiveSharpening: 0 + m_Version: 2 --- !u!1001 &389902283970083402 PrefabInstance: m_ObjectHideFlags: 0 @@ -1521,7 +1534,6 @@ MonoBehaviour: m_ScreenCoordScaleBias: {x: 0, y: 0, z: 0, w: 0} m_RequiresDepthTexture: 0 m_RequiresColorTexture: 0 - m_Version: 2 m_TaaSettings: m_Quality: 3 m_FrameInfluence: 0.1 @@ -1529,6 +1541,7 @@ MonoBehaviour: m_MipBias: 0 m_VarianceClampScale: 0.9 m_ContrastAdaptiveSharpening: 0 + m_Version: 2 --- !u!4 &1465965334603602870 stripped Transform: m_CorrespondingSourceObject: {fileID: 930940621509673985, guid: c43ac1b5fbd2fc24ea40fb28bae6be3e, type: 3} @@ -1621,7 +1634,6 @@ MonoBehaviour: m_Calls: [] _grabBag: {fileID: 0} GrabBags: [] - _allowGrabbing: 0 GrabControl: 0 GrabDetectionType: 1 CheckHandOverlap: 0 @@ -1750,7 +1762,6 @@ MonoBehaviour: m_ScreenCoordScaleBias: {x: 0, y: 0, z: 0, w: 0} m_RequiresDepthTexture: 0 m_RequiresColorTexture: 0 - m_Version: 2 m_TaaSettings: m_Quality: 3 m_FrameInfluence: 0.1 @@ -1758,6 +1769,7 @@ MonoBehaviour: m_MipBias: 0 m_VarianceClampScale: 0.9 m_ContrastAdaptiveSharpening: 0 + m_Version: 2 --- !u!4 &3469872688271879209 stripped Transform: m_CorrespondingSourceObject: {fileID: 2923976313507361694, guid: c43ac1b5fbd2fc24ea40fb28bae6be3e, type: 3} @@ -2210,7 +2222,6 @@ MonoBehaviour: m_Calls: [] _grabBag: {fileID: 0} GrabBags: [] - _allowGrabbing: 0 GrabControl: 0 GrabDetectionType: 1 CheckHandOverlap: 0 @@ -2340,7 +2351,6 @@ MonoBehaviour: m_Calls: [] _grabBag: {fileID: 0} GrabBags: [] - _allowGrabbing: 0 GrabControl: 0 GrabDetectionType: 1 CheckHandOverlap: 0 @@ -2414,7 +2424,6 @@ MonoBehaviour: m_ScreenCoordScaleBias: {x: 0, y: 0, z: 0, w: 0} m_RequiresDepthTexture: 0 m_RequiresColorTexture: 0 - m_Version: 2 m_TaaSettings: m_Quality: 3 m_FrameInfluence: 0.1 @@ -2422,6 +2431,7 @@ MonoBehaviour: m_MipBias: 0 m_VarianceClampScale: 0.9 m_ContrastAdaptiveSharpening: 0 + m_Version: 2 --- !u!4 &5027004475127813370 stripped Transform: m_CorrespondingSourceObject: {fileID: 6733158296146905933, guid: c43ac1b5fbd2fc24ea40fb28bae6be3e, type: 3} @@ -2504,7 +2514,6 @@ MonoBehaviour: m_ScreenCoordScaleBias: {x: 0, y: 0, z: 0, w: 0} m_RequiresDepthTexture: 0 m_RequiresColorTexture: 0 - m_Version: 2 m_TaaSettings: m_Quality: 3 m_FrameInfluence: 0.1 @@ -2512,6 +2521,7 @@ MonoBehaviour: m_MipBias: 0 m_VarianceClampScale: 0.9 m_ContrastAdaptiveSharpening: 0 + m_Version: 2 --- !u!4 &7369524044816577371 stripped Transform: m_CorrespondingSourceObject: {fileID: 9148698939618798828, guid: c43ac1b5fbd2fc24ea40fb28bae6be3e, type: 3} diff --git a/Assets/Gothic-VR/Scripts/Adapters/UI/VRMenuCheatAdapter.cs b/Assets/Gothic-VR/Scripts/Adapters/UI/VRMenuCheatAdapter.cs new file mode 100644 index 000000000..bb32ff157 --- /dev/null +++ b/Assets/Gothic-VR/Scripts/Adapters/UI/VRMenuCheatAdapter.cs @@ -0,0 +1,107 @@ +#if GOTHIC_HVR_INSTALLED +using Gothic.Core.Adapters.UI.Menus; +using Gothic.Core.Logging; +using Gothic.Core.Services.Config; +using Gothic.VR.Adapters.HVROverrides; +using HurricaneVR.Framework.ControllerInput; +using HurricaneVR.Framework.Shared; +using Reflex.Attributes; +using UnityEngine; +using UnityEngine.InputSystem; +using Logger = Gothic.Core.Logging.Logger; + +namespace Gothic.VR.Adapters.UI +{ + public class VRMenuCheatAdapter : MonoBehaviour + { + [Inject] private readonly ConfigService _configService; + + private MenuHandler _menuHandler; + private StatusMenu _statusMenu; + private bool _initialized; + + private int _levelClicks; + private int _guildClicks; + private bool _wasMenuActive; + + private void Update() + { + if (_configService == null) return; + if (!_configService.Dev.EnableLevel5Cheat && !_configService.Dev.EnableGuildCheat) return; + + if (!_initialized) TryInit(); + if (!_initialized) return; + + if (_statusMenu == null) + _statusMenu = _menuHandler.GetComponentInChildren(true); + if (_statusMenu == null) return; + + var isActive = _statusMenu.gameObject.activeSelf; + + if (_wasMenuActive && !isActive) + { + Logger.Log($"[VRMenuCheatAdapter] Menu closed — reset (L:{_levelClicks} G:{_guildClicks})", LogCat.Ui); + _levelClicks = 0; + _guildClicks = 0; + } + _wasMenuActive = isActive; + + if (!isActive) return; + + if (_configService.Dev.EnableLevel5Cheat && LeftPrimaryJustPressed()) + { + _levelClicks++; + Logger.Log($"[VRMenuCheatAdapter] Left click #{_levelClicks}/5", LogCat.Ui); + if (_levelClicks >= 5) + { + _levelClicks = 0; + _statusMenu.ExecuteLevelCheat(); + } + } + + if (_configService.Dev.EnableGuildCheat && RightPrimaryJustPressed()) + { + _guildClicks++; + Logger.Log($"[VRMenuCheatAdapter] Right click #{_guildClicks}/3", LogCat.Ui); + if (_guildClicks >= 3) + { + _guildClicks = 0; + _statusMenu.ExecuteGuildCheat(); + } + } + } + + private void TryInit() + { + var player = GetComponent(); + if (player == null) player = GetComponentInParent(); + if (player == null) player = FindAnyObjectByType(); + if (player == null) return; + _menuHandler = player.MenuHandler; + if (_menuHandler == null) return; + _initialized = true; + Logger.Log($"[VRMenuCheatAdapter] Initialized — MenuHandler: {_menuHandler.name}", LogCat.Ui); + } + + private static bool LeftPrimaryJustPressed() + { + if (Keyboard.current != null && Keyboard.current[Key.K].wasPressedThisFrame) + { + Logger.Log("[VRMenuCheatAdapter] K key (sim left)", LogCat.Ui); + return true; + } + return HVRController.GetButtonState(HVRHandSide.Left, HVRButtons.Primary).JustActivated; + } + + private static bool RightPrimaryJustPressed() + { + if (Keyboard.current != null && Keyboard.current[Key.L].wasPressedThisFrame) + { + Logger.Log("[VRMenuCheatAdapter] L key (sim right)", LogCat.Ui); + return true; + } + return HVRController.GetButtonState(HVRHandSide.Right, HVRButtons.Primary).JustActivated; + } + } +} +#endif diff --git a/Assets/Gothic-VR/Scripts/Adapters/UI/VRMenuCheatAdapter.cs.meta b/Assets/Gothic-VR/Scripts/Adapters/UI/VRMenuCheatAdapter.cs.meta new file mode 100644 index 000000000..f6ebb18da --- /dev/null +++ b/Assets/Gothic-VR/Scripts/Adapters/UI/VRMenuCheatAdapter.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 977abd6b6b52b6349b0da41931fe76a2 \ No newline at end of file From 53a41532f1afc1544d05548f8a41ba70e285ce43 Mon Sep 17 00:00:00 2001 From: BoroBongo Date: Mon, 15 Jun 2026 03:57:33 +0100 Subject: [PATCH 2/8] =?UTF-8?q?feat(wip):=20time=20skip=20cheat=20?= =?UTF-8?q?=E2=80=94=20B=20button=20(right)=20or=20N=20key=20skips=20+30?= =?UTF-8?q?=20min?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit EnableTimeSkip flag in DeveloperConfig gates the cheat. VRMenuCheatAdapter injects GameTimeService and calls SetTime() on press. --- .../Scripts/Models/Config/DeveloperConfig.cs | 9 +++++++ .../Scripts/Adapters/UI/VRMenuCheatAdapter.cs | 24 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/Assets/Gothic-Core/Scripts/Models/Config/DeveloperConfig.cs b/Assets/Gothic-Core/Scripts/Models/Config/DeveloperConfig.cs index 97a281486..35fec4137 100644 --- a/Assets/Gothic-Core/Scripts/Models/Config/DeveloperConfig.cs +++ b/Assets/Gothic-Core/Scripts/Models/Config/DeveloperConfig.cs @@ -291,5 +291,14 @@ public class DebugChannelTypesCollection : CollectionWrapper(); From eb13495eb5987cd01d00623af61d0b22508eafe5 Mon Sep 17 00:00:00 2001 From: BoroBongo Date: Mon, 15 Jun 2026 18:25:54 +0100 Subject: [PATCH 3/8] fix: add missing \$sc_heywaitasecond SVM mapping; clarify dev cheat tooltips ZenKitExtension was missing the \$sc_heywaitasecond -> SvmInstance.ScHeyWaitASecond mapping, causing that SVM key to fall through unresolved. DeveloperConfig tooltip text updated to describe actual input bindings (VR buttons / keyboard keys) instead of UI menu click sequences. --- Assets/Gothic-Core/Scripts/Extensions/ZenKitExtension.cs | 1 + Assets/Gothic-Core/Scripts/Models/Config/DeveloperConfig.cs | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Assets/Gothic-Core/Scripts/Extensions/ZenKitExtension.cs b/Assets/Gothic-Core/Scripts/Extensions/ZenKitExtension.cs index a98faa185..cf6ad4984 100644 --- a/Assets/Gothic-Core/Scripts/Extensions/ZenKitExtension.cs +++ b/Assets/Gothic-Core/Scripts/Extensions/ZenKitExtension.cs @@ -318,6 +318,7 @@ public static string GetAudioName(this SvmInstance svm, string svmEntry) "$smalltalk23" => svm.Smalltalk23, "$smalltalk24" => svm.Smalltalk24, "$om" => svm.Om, + "$sc_heywaitasecond" => svm.ScHeyWaitASecond, "$sc_heyturnaround" => svm.ScHeyTurnAround, "$sc_heyturnaround02" => svm.ScHeyTurnAround02, "$sc_heyturnaround03" => svm.ScHeyTurnAround03, diff --git a/Assets/Gothic-Core/Scripts/Models/Config/DeveloperConfig.cs b/Assets/Gothic-Core/Scripts/Models/Config/DeveloperConfig.cs index 35fec4137..5c174bbad 100644 --- a/Assets/Gothic-Core/Scripts/Models/Config/DeveloperConfig.cs +++ b/Assets/Gothic-Core/Scripts/Models/Config/DeveloperConfig.cs @@ -291,13 +291,13 @@ public class DebugChannelTypesCollection : CollectionWrapper Date: Mon, 15 Jun 2026 20:59:43 +0100 Subject: [PATCH 4/8] feat: implement MarvinMode cheat buttons with centered vertical layout Buttons are collected into a list first so total height is known before instantiation, letting each button's anchoredPosition be calculated to center the group. The "Under Construction" placeholder Text GO is hidden on Start. Adding new buttons only requires one extra list entry. --- .../Adapters/Marvin/MarvinTabHandler.cs | 90 ++++++++++++++++++- 1 file changed, 88 insertions(+), 2 deletions(-) diff --git a/Assets/Gothic-VR/Scripts/Adapters/Marvin/MarvinTabHandler.cs b/Assets/Gothic-VR/Scripts/Adapters/Marvin/MarvinTabHandler.cs index f3982e338..8f30cc9a7 100644 --- a/Assets/Gothic-VR/Scripts/Adapters/Marvin/MarvinTabHandler.cs +++ b/Assets/Gothic-VR/Scripts/Adapters/Marvin/MarvinTabHandler.cs @@ -1,9 +1,95 @@ +#if GOTHIC_HVR_INSTALLED +using Gothic.Core.Adapters.UI.Menus; +using Gothic.Core.Logging; +using Gothic.Core.Models.Caches; +using Gothic.Core.Services.Caches; +using Gothic.Core.Services.Config; +using Gothic.Core.Services.Npc; +using Gothic.Core.Services.World; +using Reflex.Attributes; +using TMPro; using UnityEngine; +using UnityEngine.UI; +using Logger = Gothic.Core.Logging.Logger; +using LogCat = Gothic.Core.Logging.LogCat; namespace Gothic.VR.Adapters.Marvin { - public class MarvinMode : MonoBehaviour + public class MarvinTabHandler : MonoBehaviour { - + [Inject] private readonly ConfigService _configService; + [Inject] private readonly GameTimeService _gameTimeService; + [Inject] private readonly NpcRoutineService _npcRoutineService; + [Inject] private readonly ResourceCacheService _resourceCacheService; + + private StatusMenu _statusMenu; + + private void Start() + { + _statusMenu = FindAnyObjectByType(FindObjectsInactive.Include); + + var placeholder = transform.Find("Text"); + if (placeholder != null) + placeholder.gameObject.SetActive(false); + + CreateButtons(); + } + + private void CreateButtons() + { + var buttons = new System.Collections.Generic.List<(string label, System.Action onClick)>(); + + if (_configService.Dev.EnableLevel5Cheat) + buttons.Add(("Level +5 [K]", () => { _statusMenu?.ExecuteLevelCheat(); Logger.Log("[MarvinMode] Level cheat triggered", LogCat.Ui); })); + + if (_configService.Dev.EnableGuildCheat) + buttons.Add(("Guild → Novice [L]", () => { _statusMenu?.ExecuteGuildCheat(); Logger.Log("[MarvinMode] Guild cheat triggered", LogCat.Ui); })); + + if (_configService.Dev.EnableTimeSkip) + buttons.Add(("Skip Time +30min [N]", SkipTime30Min)); + + const float buttonHeight = 50f; + const float gap = 10f; + var totalHeight = buttons.Count * buttonHeight + (buttons.Count - 1) * gap; + var startY = totalHeight / 2f - buttonHeight / 2f; + + for (var i = 0; i < buttons.Count; i++) + { + var (label, onClick) = buttons[i]; + CreateButton(label, onClick, startY - i * (buttonHeight + gap)); + } + } + + private void SkipTime30Min() + { + var t = _gameTimeService.GetCurrentTime(); + var next = t.Add(System.TimeSpan.FromMinutes(30)); + _gameTimeService.SetTime(next.Hours, next.Minutes); + _npcRoutineService.RecalculateAllNpcRoutines(); + Logger.Log($"[MarvinMode] Time skip → {next.Hours:D2}:{next.Minutes:D2}", LogCat.Ui); + } + + private void CreateButton(string label, System.Action onClick, float anchoredY) + { + var go = _resourceCacheService.TryGetPrefabObject(PrefabType.UiDebugButton, parent: gameObject); + if (go == null) + { + Logger.LogWarning($"[MarvinMode] UiDebugButton prefab not found for: {label}", LogCat.Ui); + return; + } + + var rt = go.GetComponent(); + if (rt != null) + rt.anchoredPosition = new Vector2(0f, anchoredY); + + var text = go.GetComponentInChildren(); + if (text != null) + text.text = label; + + var button = go.GetComponentInChildren