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