diff --git a/AccessibilityMod/Data/en/strings.json b/AccessibilityMod/Data/en/strings.json index 8209d01..d23b17f 100644 --- a/AccessibilityMod/Data/en/strings.json +++ b/AccessibilityMod/Data/en/strings.json @@ -296,6 +296,7 @@ "trial.danger": "DANGER!", "trial.game_over": "Game Over!", "trial.health_percent": "Health: {0} percent", + "trial.cross_examination_hint": "Cross-examination. Press Q to press statements, open court record and press E to present evidence.", "_section_court_record": "=== Court Record ===", "court_record.evidence": "Evidence", @@ -309,6 +310,7 @@ "court_record.page_x_of_y": "Page {0} of {1}.", "court_record.page_navigation_hint": "Press left or right for pages.", "court_record.close_hint": "Press Backspace to close.", + "court_record.present_hint": "Press E to present selected evidence.", "_section_psyche_lock": "=== Psyche-Lock ===", "psyche_lock.total.one": "{0} Psyche-Lock", diff --git a/AccessibilityMod/Data/ko/strings.json b/AccessibilityMod/Data/ko/strings.json index 449c1f9..82e98b7 100644 --- a/AccessibilityMod/Data/ko/strings.json +++ b/AccessibilityMod/Data/ko/strings.json @@ -296,6 +296,7 @@ "trial.danger": "위험!", "trial.game_over": "게임 오버!", "trial.health_percent": "체력: {0}퍼센트", + "trial.cross_examination_hint": "심문. Q를 눌러 추궁, 법정기록을 열고 E를 눌러 증거물 제시.", "_section_court_record": "=== Court Record ===", "court_record.evidence": "증거물", @@ -309,6 +310,7 @@ "court_record.page_x_of_y": "페이지 {0}/{1}.", "court_record.page_navigation_hint": "좌우로 페이지 이동.", "court_record.close_hint": "Backspace를 눌러 닫기.", + "court_record.present_hint": "E를 눌러 선택한 증거물 제시.", "_section_psyche_lock": "=== Psyche-Lock ===", "psyche_lock.total.one": "사이코 록 {0}개", diff --git a/AccessibilityMod/Data/pt-BR/strings.json b/AccessibilityMod/Data/pt-BR/strings.json index 86374f0..720d66c 100644 --- a/AccessibilityMod/Data/pt-BR/strings.json +++ b/AccessibilityMod/Data/pt-BR/strings.json @@ -296,6 +296,7 @@ "trial.danger": "PERIGO!", "trial.game_over": "Game Over!", "trial.health_percent": "Saúde: {0} por cento", + "trial.cross_examination_hint": "Contra-interrogatório. Pressione Q para pressionar declarações, abra o registro do tribunal e pressione E para apresentar evidências.", "_section_court_record": "=== Registro do Tribunal ===", "court_record.evidence": "Evidências", @@ -309,6 +310,7 @@ "court_record.page_x_of_y": "Página {0} de {1}.", "court_record.page_navigation_hint": "Pressione esquerda ou direita para páginas.", "court_record.close_hint": "Pressione Backspace para fechar.", + "court_record.present_hint": "Pressione E para apresentar a evidência selecionada.", "_section_psyche_lock": "=== Tranca Psíquica ===", "psyche_lock.total.one": "{0} Psicotrava", diff --git a/AccessibilityMod/Data/zh-Hans/strings.json b/AccessibilityMod/Data/zh-Hans/strings.json index 4bfb07d..b3e9afc 100644 --- a/AccessibilityMod/Data/zh-Hans/strings.json +++ b/AccessibilityMod/Data/zh-Hans/strings.json @@ -296,6 +296,7 @@ "trial.danger": "危险!", "trial.game_over": "游戏结束。", "trial.health_percent": "血量: 百分之 {0} ", + "trial.cross_examination_hint": "交叉询问。按Q键威慑证词,打开法庭记录后按E键出示证物。", "_section_court_record": "=== Court Record ===", "court_record.evidence": "证物", @@ -309,6 +310,7 @@ "court_record.page_x_of_y": "第 {0} 页,共 {1} 页.", "court_record.page_navigation_hint": "按左右方向键可翻页。", "court_record.close_hint": "按退格键可关闭", + "court_record.present_hint": "按E键出示选中的证物。", "_section_psyche_lock": "=== Psyche-Lock ===", "psyche_lock.total.one": "发现{0} 个心灵枷锁", diff --git a/AccessibilityMod/Patches/CourtRecordPatches.cs b/AccessibilityMod/Patches/CourtRecordPatches.cs index 9ca042f..b900299 100644 --- a/AccessibilityMod/Patches/CourtRecordPatches.cs +++ b/AccessibilityMod/Patches/CourtRecordPatches.cs @@ -4,7 +4,6 @@ using AccessibilityMod.Services; using HarmonyLib; using UnityAccessibilityLib; -using UnityEngine.UI; using L = AccessibilityMod.Services.L; namespace AccessibilityMod.Patches @@ -39,6 +38,13 @@ public static void NoteOpen_Postfix(recordListCtrl __instance, int mode) } string message = L.Get("court_record.opened", tabName, itemCount); + + // Add present hint during cross-examination or psyche-lock + if (IsInPresentableMode()) + { + message += " " + L.Get("court_record.present_hint"); + } + SpeechManager.Announce(message, GameTextType.Menu); // Reset tracking @@ -335,6 +341,33 @@ public static void PlayPice_Postfix(picePlateCtrl __instance) #endregion + #region Present Mode Detection + + /// + /// Check if the player can present evidence from the court record. + /// This is true during cross-examination (trial) and Psyche-Lock sequences. + /// + private static bool IsInPresentableMode() + { + try + { + // Trial mode (questioning or cross-examination) + if (AccessibilityState.IsInTrialMode()) + return true; + + // Psyche-Lock sequences + if (PsycheLockPatches.GetRemainingLocks() > 0) + return true; + } + catch + { + // Safe to ignore - mode detection is best-effort + } + return false; + } + + #endregion + #region State Reset // Reset state when court record closes diff --git a/AccessibilityMod/Patches/DialoguePatches.cs b/AccessibilityMod/Patches/DialoguePatches.cs index 4fda0c6..dd04c1d 100644 --- a/AccessibilityMod/Patches/DialoguePatches.cs +++ b/AccessibilityMod/Patches/DialoguePatches.cs @@ -24,6 +24,9 @@ public static class DialoguePatches internal static string _lastAnnouncedText = ""; private static int _lastSpeakerId = -1; + // Cross-examination controls announcement tracking + private static int _crossExamSceneState = -1; + // Regex for detecting button placeholders (multiple spaces or full-width spaces) private static readonly Regex SpacePlaceholderRegex = new Regex( @"[\u3000]+| {3,}", @@ -114,6 +117,9 @@ public static void ChangeGuide_Postfix(guideCtrl __instance, guideCtrl.GuideType { try { + // Announce cross-examination controls on mode entry + CheckCrossExaminationEntry(in_type); + // Only output if the game is actually waiting for input, not during text display if (IsDialogueGuideType(in_type) && IsWaitingForInput()) { @@ -451,6 +457,46 @@ private static bool IsInStaleDialogueMode() || AccessibilityState.IsIn3DEvidenceMode(); } + /// + /// Announce cross-examination controls once when entering testimony mode. + /// Tracks scene state to avoid re-announcing after pressing a statement. + /// + private static void CheckCrossExaminationEntry(guideCtrl.GuideType guideType) + { + try + { + int currentNo0 = -1; + try + { + if (GSStatic.global_work_ != null) + currentNo0 = (int)GSStatic.global_work_.r.no_0; + } + catch { } + + // Reset tracking when leaving testimony mode + if (currentNo0 != 7) + { + _crossExamSceneState = -1; + return; + } + + // Announce once per testimony session when QUESTIONING guide appears + if ( + guideType == guideCtrl.GuideType.QUESTIONING + && _crossExamSceneState != 7 + && IsInCrossExaminationMode() + ) + { + _crossExamSceneState = 7; + SpeechManager.Announce( + L.Get("trial.cross_examination_hint"), + GameTextType.Trial + ); + } + } + catch { } + } + /// /// Check if we're in cross-examination mode (testimony with LOOP status). /// During cross-examination, the last testimony line doesn't show the forward arrow. diff --git a/README.md b/README.md index 91a8010..9d55240 100644 --- a/README.md +++ b/README.md @@ -49,15 +49,50 @@ You can install this in two ways, either by using the AccessMods Installer or by ## Keyboard Shortcuts -| Key | Context | Action | -| --------- | ----------------- | -------------------------------------------------- | -| **F5** | Global | Hot-reload config files | -| **R** | Global | Repeat last output | -| **I** | Global | Announce current state/context | -| **[ / ]** | Navigation modes | Navigate items (hotspots, evidence, targets, etc.) | -| **U** | Investigation | Jump to next unexamined hotspot | -| **H** | Trial | announce life gauge | -| **F1** | Context-sensitive | Announce help hints | +### Mod Shortcuts + +| Key | Context | Action | +| --------- | --------------------------------- | ----------------------------------------- | +| **F5** | Global | Hot-reload config files | +| **R** | Global (except vase/court record) | Repeat last output | +| **I** | Global | Announce current state/context | +| **H** | Trial (not pointing) | Announce life gauge | +| **[ / ]** | Investigation | Navigate hotspots | +| **U** | Investigation | Jump to next unexamined hotspot | +| **F1** | Investigation | List all hotspots | +| **[ / ]** | Pointing mode | Navigate target areas | +| **F1** | Pointing mode | List all target areas | +| **[ / ]** | Luminol mode | Navigate blood evidence | +| **[ / ]** | 3D Evidence | Navigate examination points | +| **[ / ]** | Fingerprint mode | Navigate fingerprint locations | +| **F1** | Fingerprint mode | Get hint for current phase | +| **[ / ]** | Video tape mode | Navigate to targets when paused | +| **F1** | Video tape mode | Get hint | +| **F1** | Vase puzzle | Get hint for current step | +| **F1** | Vase show (rotation) | Get hint | +| **[ / ]** | Dying message | Navigate between dots | +| **F1** | Dying message | Get hint for spelling | +| **F1** | Bug sweeper | Announce state/hint | +| **F1** | Orchestra mode | Announce controls help | + +### Game Controls (Default Keyboard Bindings) + +These are the game's own controls that work alongside the mod: + +| Key | Action | +| ---------------- | ------------------------------------------------- | +| **Enter/Space** | Confirm / Advance dialogue | +| **Backspace** | Cancel / Go back / Close | +| **Arrow keys** | Navigate menus / Move cursor | +| **Q** | Press witness statement (cross-examination) | +| **E** | Present evidence / Confirm action | +| **Tab** | Open court record / Switch tabs | + +#### Cross-Examination + +During cross-examination, the witness gives testimony one statement at a time. Use **Left/Right** arrows to move between statements. Press **Q** to press (question) the current statement, or open the court record with **Tab**, navigate to the contradicting evidence, and press **E** to present it. + +> **Note:** Key bindings can be remapped in the game's Key Config options menu. The keys above are the defaults. ## Configuration