Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions AccessibilityMod/Data/en/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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",
Expand Down
2 changes: 2 additions & 0 deletions AccessibilityMod/Data/ko/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": "증거물",
Expand All @@ -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}개",
Expand Down
2 changes: 2 additions & 0 deletions AccessibilityMod/Data/pt-BR/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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",
Expand Down
2 changes: 2 additions & 0 deletions AccessibilityMod/Data/zh-Hans/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": "证物",
Expand All @@ -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} 个心灵枷锁",
Expand Down
35 changes: 34 additions & 1 deletion AccessibilityMod/Patches/CourtRecordPatches.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using AccessibilityMod.Services;
using HarmonyLib;
using UnityAccessibilityLib;
using UnityEngine.UI;
using L = AccessibilityMod.Services.L;

namespace AccessibilityMod.Patches
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -335,6 +341,33 @@ public static void PlayPice_Postfix(picePlateCtrl __instance)

#endregion

#region Present Mode Detection

/// <summary>
/// Check if the player can present evidence from the court record.
/// This is true during cross-examination (trial) and Psyche-Lock sequences.
/// </summary>
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
Expand Down
46 changes: 46 additions & 0 deletions AccessibilityMod/Patches/DialoguePatches.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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,}",
Expand Down Expand Up @@ -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())
{
Expand Down Expand Up @@ -451,6 +457,46 @@ private static bool IsInStaleDialogueMode()
|| AccessibilityState.IsIn3DEvidenceMode();
}

/// <summary>
/// Announce cross-examination controls once when entering testimony mode.
/// Tracks scene state to avoid re-announcing after pressing a statement.
/// </summary>
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 { }
}

/// <summary>
/// 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.
Expand Down
53 changes: 44 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down