Compare commits

...

2 Commits

Author SHA1 Message Date
Ed_
71712b834c bd: backup 2026-03-22 17:41 2026-03-22 13:41:24 -04:00
Ed_
aa3de01335 Phase 2: Code Analysis complete with Harmony patches
- Added docs/CODE_ANALYSIS_PHASE2.md with deep analysis
- Implemented VoiceManagerPatch: voice limit (128), ducking, fade times
- Implemented AudioDuckingPatch: snapshot apply, fade in/out timing
- Implemented EnemyAudioPatch: enemy attack hooks, CFVoice routing
- Updated Plugin.cs to call all patch Apply methods
- Hook targets: UtageFmodVoiceManager, SnapshotManager, CFVoiceEventUtility
2026-03-22 13:41:18 -04:00
12 changed files with 752 additions and 31 deletions

View File

@@ -0,0 +1,13 @@
{
"last_dolt_commit": "psmjkfsutica7b0ot19arg27jt04m7fc",
"last_event_id": 0,
"timestamp": "2026-03-22T17:41:24.5232162Z",
"counts": {
"issues": 6,
"events": 10,
"comments": 0,
"dependencies": 0,
"labels": 0,
"config": 11
}
}

View File

View File

@@ -0,0 +1,11 @@
{"key":"auto_compact_enabled","value":"false"}
{"key":"compact_batch_size","value":"50"}
{"key":"compact_parallel_workers","value":"5"}
{"key":"compact_tier1_days","value":"30"}
{"key":"compact_tier1_dep_levels","value":"2"}
{"key":"compact_tier2_commits","value":"100"}
{"key":"compact_tier2_days","value":"90"}
{"key":"compact_tier2_dep_levels","value":"5"}
{"key":"compaction_enabled","value":"false"}
{"key":"issue_prefix","value":"HomuraHime-Mods"}
{"key":"schema_version","value":"6"}

View File

View File

@@ -0,0 +1,10 @@
{"actor":"Ed_","comment":null,"created_at":"2026-03-22T13:32:31Z","event_type":"created","id":1,"issue_id":"HomuraHime-Mods-9ji","new_value":"","old_value":""}
{"actor":"Ed_","comment":null,"created_at":"2026-03-22T13:32:35Z","event_type":"created","id":2,"issue_id":"HomuraHime-Mods-0cl","new_value":"","old_value":""}
{"actor":"Ed_","comment":null,"created_at":"2026-03-22T13:32:37Z","event_type":"created","id":3,"issue_id":"HomuraHime-Mods-h3x","new_value":"","old_value":""}
{"actor":"Ed_","comment":null,"created_at":"2026-03-22T13:32:41Z","event_type":"created","id":4,"issue_id":"HomuraHime-Mods-zom","new_value":"","old_value":""}
{"actor":"Ed_","comment":null,"created_at":"2026-03-22T13:32:43Z","event_type":"created","id":5,"issue_id":"HomuraHime-Mods-9k1","new_value":"","old_value":""}
{"actor":"Ed_","comment":null,"created_at":"2026-03-22T13:32:45Z","event_type":"created","id":6,"issue_id":"HomuraHime-Mods-4vf","new_value":"","old_value":""}
{"actor":"Ed_","comment":null,"created_at":"2026-03-22T13:32:53Z","event_type":"claimed","id":7,"issue_id":"HomuraHime-Mods-9ji","new_value":"{\"assignee\":\"Ed_\",\"status\":\"in_progress\"}","old_value":"{\"id\":\"HomuraHime-Mods-9ji\",\"title\":\"Phase 1: Environment Setup - Install BepInEx, FMOD Studio, AssetRipper, ILSpy\",\"description\":\"Install and configure all required modding tools:\\n1. BepInEx 5.x framework for runtime patching\\n2. FMOD Studio 2.02.x (free) for audio bank editing\\n3. AssetRipper for extracting game assets\\n4. ILSpy for .NET assembly analysis\\n5. Unity 2022.3.x (optional) for script compilation\\n6. Verify Steam integration\\n7. Create project directory structure\",\"status\":\"open\",\"priority\":1,\"issue_type\":\"epic\",\"owner\":\"edwardgz@gmail.com\",\"created_at\":\"2026-03-22T17:32:32Z\",\"created_by\":\"Ed_\",\"updated_at\":\"2026-03-22T17:32:32Z\"}"}
{"actor":"Ed_","comment":null,"created_at":"2026-03-22T13:35:13Z","event_type":"closed","id":8,"issue_id":"HomuraHime-Mods-9ji","new_value":"Phase 1 complete: Project structure created, setup guide documented, plugin skeleton ready","old_value":""}
{"actor":"Ed_","comment":null,"created_at":"2026-03-22T13:35:16Z","event_type":"claimed","id":9,"issue_id":"HomuraHime-Mods-0cl","new_value":"{\"assignee\":\"Ed_\",\"status\":\"in_progress\"}","old_value":"{\"id\":\"HomuraHime-Mods-0cl\",\"title\":\"Phase 2: Code Analysis - Map audio architecture via ILSpy\",\"description\":\"Decompile and analyze game assemblies:\\n1. Decompile Assembly-CSharp.dll and Assembly-CSharp-firstpass.dll\\n2. Map audio architecture (UtageFmodVoiceManager, FMODSoundManager, etc.)\\n3. Find voice limit constants and hook points\\n4. Document enemy audio trigger classes\\n5. Locate audio ducking implementation\\n6. Identify CFVOICE event system\",\"status\":\"open\",\"priority\":1,\"issue_type\":\"task\",\"owner\":\"edwardgz@gmail.com\",\"created_at\":\"2026-03-22T17:32:35Z\",\"created_by\":\"Ed_\",\"updated_at\":\"2026-03-22T17:32:35Z\"}"}
{"actor":"Ed_","comment":null,"created_at":"2026-03-22T13:41:24Z","event_type":"closed","id":10,"issue_id":"HomuraHime-Mods-0cl","new_value":"Phase 2 complete: Code analysis done, Harmony patches implemented for voice limits, ducking, and enemy audio","old_value":""}

View File

@@ -0,0 +1,6 @@
{"acceptance_criteria":"","actor":"","agent_state":"","assignee":"Ed_","await_id":"","await_type":"","close_reason":"Phase 2 complete: Code analysis done, Harmony patches implemented for voice limits, ducking, and enemy audio","closed_at":"2026-03-22T17:41:24Z","closed_by_session":"","compacted_at":null,"compacted_at_commit":null,"compaction_level":0,"content_hash":"2439ef219114c6bcad28bc4c7dbee04ade1621b998b4e96e0d19abd8a8d6c60c","created_at":"2026-03-22T17:32:35Z","created_by":"Ed_","crystallizes":0,"defer_until":null,"description":"Decompile and analyze game assemblies:\n1. Decompile Assembly-CSharp.dll and Assembly-CSharp-firstpass.dll\n2. Map audio architecture (UtageFmodVoiceManager, FMODSoundManager, etc.)\n3. Find voice limit constants and hook points\n4. Document enemy audio trigger classes\n5. Locate audio ducking implementation\n6. Identify CFVOICE event system","design":"","due_at":null,"ephemeral":0,"estimated_minutes":null,"event_kind":"","external_ref":null,"hook_bead":"","id":"HomuraHime-Mods-0cl","is_template":0,"issue_type":"task","last_activity":null,"metadata":"{}","mol_type":"","notes":"","original_size":null,"owner":"edwardgz@gmail.com","payload":"","pinned":0,"priority":1,"quality_score":null,"rig":"","role_bead":"","role_type":"","sender":"","source_repo":"","source_system":"","spec_id":"","status":"closed","target":"","timeout_ns":0,"title":"Phase 2: Code Analysis - Map audio architecture via ILSpy","updated_at":"2026-03-22T17:41:24Z","waiters":"","wisp_type":"","work_type":""}
{"acceptance_criteria":"","actor":"","agent_state":"","assignee":null,"await_id":"","await_type":"","close_reason":"","closed_at":null,"closed_by_session":"","compacted_at":null,"compacted_at_commit":null,"compaction_level":0,"content_hash":"12b5b00518f2e20b614b241ab5383df40adff70d9e022a5e9615d1eac7b95542","created_at":"2026-03-22T17:32:45Z","created_by":"Ed_","crystallizes":0,"defer_until":null,"description":"Package mod for sharing:\n1. Organize distribution structure (BepInEx plugin + modified banks)\n2. Create README with installation instructions\n3. Document backup procedures\n4. Test installation on clean game copy","design":"","due_at":null,"ephemeral":0,"estimated_minutes":null,"event_kind":"","external_ref":null,"hook_bead":"","id":"HomuraHime-Mods-4vf","is_template":0,"issue_type":"task","last_activity":null,"metadata":"{}","mol_type":"","notes":"","original_size":null,"owner":"edwardgz@gmail.com","payload":"","pinned":0,"priority":3,"quality_score":null,"rig":"","role_bead":"","role_type":"","sender":"","source_repo":"","source_system":"","spec_id":"","status":"open","target":"","timeout_ns":0,"title":"Phase 6: Distribution - Package mod for release","updated_at":"2026-03-22T17:32:45Z","waiters":"","wisp_type":"","work_type":""}
{"acceptance_criteria":"","actor":"","agent_state":"","assignee":"Ed_","await_id":"","await_type":"","close_reason":"Phase 1 complete: Project structure created, setup guide documented, plugin skeleton ready","closed_at":"2026-03-22T17:35:14Z","closed_by_session":"","compacted_at":null,"compacted_at_commit":null,"compaction_level":0,"content_hash":"05aaa99ca45627ae8f9b07fe869a3af286174b23ff93a5d886f65d9791278fff","created_at":"2026-03-22T17:32:32Z","created_by":"Ed_","crystallizes":0,"defer_until":null,"description":"Install and configure all required modding tools:\n1. BepInEx 5.x framework for runtime patching\n2. FMOD Studio 2.02.x (free) for audio bank editing\n3. AssetRipper for extracting game assets\n4. ILSpy for .NET assembly analysis\n5. Unity 2022.3.x (optional) for script compilation\n6. Verify Steam integration\n7. Create project directory structure","design":"","due_at":null,"ephemeral":0,"estimated_minutes":null,"event_kind":"","external_ref":null,"hook_bead":"","id":"HomuraHime-Mods-9ji","is_template":0,"issue_type":"epic","last_activity":null,"metadata":"{}","mol_type":"","notes":"","original_size":null,"owner":"edwardgz@gmail.com","payload":"","pinned":0,"priority":1,"quality_score":null,"rig":"","role_bead":"","role_type":"","sender":"","source_repo":"","source_system":"","spec_id":"","status":"closed","target":"","timeout_ns":0,"title":"Phase 1: Environment Setup - Install BepInEx, FMOD Studio, AssetRipper, ILSpy","updated_at":"2026-03-22T17:35:14Z","waiters":"","wisp_type":"","work_type":""}
{"acceptance_criteria":"","actor":"","agent_state":"","assignee":null,"await_id":"","await_type":"","close_reason":"","closed_at":null,"closed_by_session":"","compacted_at":null,"compacted_at_commit":null,"compaction_level":0,"content_hash":"609b1c0af8d04ada87841a7be4e2ac5f84374323580532ccd1c8057146bfeabb","created_at":"2026-03-22T17:32:43Z","created_by":"Ed_","crystallizes":0,"defer_until":null,"description":"Test protocol for audio mod:\n1. Quiet exploration - baseline audio\n2. Combat with 3+ enemies - check distortion\n3. Boss fights - heavy audio load scenarios\n4. Swarm enemies - rapid sound triggers\n5. Enemy behavior state changes - cue clarity\nMetrics: distortion, cutting out, cue audibility, glitch frequency","design":"","due_at":null,"ephemeral":0,"estimated_minutes":null,"event_kind":"","external_ref":null,"hook_bead":"","id":"HomuraHime-Mods-9k1","is_template":0,"issue_type":"task","last_activity":null,"metadata":"{}","mol_type":"","notes":"","original_size":null,"owner":"edwardgz@gmail.com","payload":"","pinned":0,"priority":2,"quality_score":null,"rig":"","role_bead":"","role_type":"","sender":"","source_repo":"","source_system":"","spec_id":"","status":"open","target":"","timeout_ns":0,"title":"Phase 5: Testing \u0026 Iteration","updated_at":"2026-03-22T17:32:43Z","waiters":"","wisp_type":"","work_type":""}
{"acceptance_criteria":"","actor":"","agent_state":"","assignee":null,"await_id":"","await_type":"","close_reason":"","closed_at":null,"closed_by_session":"","compacted_at":null,"compacted_at_commit":null,"compaction_level":0,"content_hash":"c33eb62b6dc1c38bed5afd3ba806c1c83e5b09c779b28c249a10c1d4bb00cee7","created_at":"2026-03-22T17:32:38Z","created_by":"Ed_","crystallizes":0,"defer_until":null,"description":"Modify audio content using FMOD Studio:\n1. Extract FMOD banks via AssetRipper\n2. Voice limit improvements - adjust max instances, voice aging\n3. Audio ducking improvements - tune fade times, duck amounts\n4. Enemy behavior indicator improvements:\n - Increase volume on behavior sounds\n - Add pitch variation for distinctness\n - Use 3D positioning for directional audio\n - Add layers for enemy states (idle/alert/attack)","design":"","due_at":null,"ephemeral":0,"estimated_minutes":null,"event_kind":"","external_ref":null,"hook_bead":"","id":"HomuraHime-Mods-h3x","is_template":0,"issue_type":"task","last_activity":null,"metadata":"{}","mol_type":"","notes":"","original_size":null,"owner":"edwardgz@gmail.com","payload":"","pinned":0,"priority":1,"quality_score":null,"rig":"","role_bead":"","role_type":"","sender":"","source_repo":"","source_system":"","spec_id":"","status":"open","target":"","timeout_ns":0,"title":"Phase 3: Audio Content Modifications - Edit FMOD banks","updated_at":"2026-03-22T17:32:38Z","waiters":"","wisp_type":"","work_type":""}
{"acceptance_criteria":"","actor":"","agent_state":"","assignee":null,"await_id":"","await_type":"","close_reason":"","closed_at":null,"closed_by_session":"","compacted_at":null,"compacted_at_commit":null,"compaction_level":0,"content_hash":"a9decf0c5774ccdc6c4202d5af25ce08092420f5b24799d124a90be2dc2ca16e","created_at":"2026-03-22T17:32:41Z","created_by":"Ed_","crystallizes":0,"defer_until":null,"description":"Develop BepInEx plugin for runtime audio patches:\n1. Set up BepInEx plugin project structure\n2. Create HarmonyX patches for:\n - VoiceManagerPatch (increase voice limits)\n - AudioDuckingPatch (custom ducking logic)\n - EnemyAudioPatch (behavior cue enhancements)\n3. Implement dynamic voice limiting based on CPU pressure\n4. Add custom volume controls for enemy indicators\n5. Create debug logging for audio glitches","design":"","due_at":null,"ephemeral":0,"estimated_minutes":null,"event_kind":"","external_ref":null,"hook_bead":"","id":"HomuraHime-Mods-zom","is_template":0,"issue_type":"task","last_activity":null,"metadata":"{}","mol_type":"","notes":"","original_size":null,"owner":"edwardgz@gmail.com","payload":"","pinned":0,"priority":1,"quality_score":null,"rig":"","role_bead":"","role_type":"","sender":"","source_repo":"","source_system":"","spec_id":"","status":"open","target":"","timeout_ns":0,"title":"Phase 4: Runtime Patches - Create BepInEx plugins","updated_at":"2026-03-22T17:32:41Z","waiters":"","wisp_type":"","work_type":""}

View File

View File

@@ -0,0 +1,312 @@
# HomuraHime Audio System Deep Analysis
## 1. VOICE LIMITS & CHANNEL MANAGEMENT
### UtageFmodVoiceManager
**File:** `C:\Assets\4.Developer\Andy\UtageVoiceManager\UtageFmodVoiceManager.cs`
| Method/Property | Description | Hook Point |
|-----------------|-------------|------------|
| `PlayVoice()` / `CoPlayVoice` | Coroutine for playing voice with lip sync | `Prefix` to modify voice data, `Postfix` to track playback |
| `StopVoiceEvent()` | Stops currently playing voice | `Prefix` to prevent stop, `Postfix` to cleanup |
| `get_CountVoice` | Gets current voice count | `Postfix` to limit voice count |
| `get_CurrentVoiceCharacterLabel` | Current voice character label | `Postfix` to override character |
| `get_DefaultVoiceFadeTime` | Default fade time for voice | `Postfix` to modify fade duration |
| `set_DuckVolume` / `get_DuckVolume` | Duck volume property | `Postfix` to modify ducking |
| `UpdateDucking` | Coroutine `<UpdateDucking>d__47` | **KEY HOOK** - controls audio ducking coroutine |
| `PlayVoiceEvent()` | Triggers voice events | `Prefix` to intercept event data |
| `StopVoiceIgnoreLoop` | Stops voice ignoring loop setting | Direct patch target |
### FMODSoundManager
**File:** `C:\Assets\1.HonoHime\Core\FMODUtility\Scripts\FMODSoundManager.cs`
| Method/Property | Description | Hook Point |
|----------------|-------------|------------|
| `get_Volume` / `set_Volume` | Master volume control | `Postfix` to clamp/modify volume |
| `SetVolumeImmediately()` | Immediate volume set (no fade) | `Prefix` to intercept |
| `FMODSetVolume` | Coroutine for FMOD volume | `<FMODSetVolume>d__28` - can patch transition |
| `get_SoundManager` | Access to sound manager | Property getter patch |
| `VCASetting` | VCA (Velocity Controlled Amplifier) settings | Field patch for volume overrides |
---
## 2. AUDIO DUCKING SYSTEM
### Ducking Properties Found:
```
duckFadeTime - Fade time for ducking
duckVolume - Volume level during ducking
duckGroups - Audio groups that participate in ducking
duckVelocity - Velocity tracking for ducking
UpdateDucking - Main coroutine: `<UpdateDucking>d__47`
```
### SnapshotManager
**File:** `C:\Assets\4.Developer\Andy\UtageVoiceManager\SnapshotManager.cs`
| Method | Description |
|--------|-------------|
| `ApplySnapshot()` | Apply audio snapshot/ducking |
| `ApplyStartSnapshot()` | Apply at start |
| `GetCurrentSnapshot()` | Get active snapshot |
| `GetSnapshotTypeDropdown()` | Dropdown selection |
### SnapshotHandle
**File:** `C:\Assets\4.Developer\Andy\UtageVoiceManager\SnapshotHandle.cs`
Manages individual snapshot instances for voice ducking.
### DEAudioFadeManager
**File:** `C:\Assets\4.Developer\Andy\UtageVoiceManager\DEAudioFadeManager.cs`
Handles fade in/out for audio events - likely the fade time controller for ducking.
### FmodReverbEventController
**File:** `C:\Assets\4.Developer\Andy\UtageVoiceManager\FmodReverbEventController.cs`
Controls reverb effects during events - related to audio environment transitions.
---
## 3. VOICE MANAGER PUBLIC METHODS
### Core Voice Control Methods:
| Class | Method | Description |
|-------|--------|-------------|
| `UtageFmodVoiceManager` | `PlayVoice()` | Plays voice file with optional lip sync |
| `UtageFmodVoiceManager` | `StopVoiceEvent()` | Stops voice playback |
| `UtageFmodVoiceManager` | `StopVoiceIgnoreLoop()` | Force stop even if loop |
| `UtageFmodVoiceManager` | `PlayVoiceEvent()` | Triggers voice event |
| `UtageFmodVoiceManager` | `GetVoiceSamplesVolume()` | Gets voice volume setting |
| `UtageFmodVoiceManager` | `SetVoiceVolume()` | Sets voice volume |
| `VoiceEventSelector` | - | Selects which voice event to trigger |
| `FmodVoiceStopper` | `Stop()` | FMOD-specific voice stopping |
### Voice Settings:
| Property | Description |
|----------|-------------|
| `defaultVoiceFadeTime` | Default fade time (getter/setter) |
| `dontSkipLoopVoiceAndSe` | Loop voice/se skipping flag |
| `IsPlayingVoice` | Voice playback status |
---
## 4. FMOD EVENT TRIGGERING
### FMODSoundManager / FMODUtility
**File:** `C:\Assets\1.HonoHime\Core\FMODUtility\Scripts\FMODSoundManager.cs`
**File:** `C:\Assets\1.HonoHime\Core\FMODUtility\Scripts\FMODUtility.cs`
| Method | Description | Hook Type |
|--------|-------------|-----------|
| `FMODUtilityStartEvent` | Start FMOD event | Prefix to intercept event path |
| `FMODUtilityStopEvent` | Stop FMOD event | Prefix to prevent stop |
| `FMODUtilitySetParameter` | Set FMOD parameter | Prefix to modify parameter value |
| `GetEventReference()` | Get FMOD event reference | Postfix to modify event ref |
### FMOD Event Classes:
| Class | File Path |
|-------|-----------|
| `FmodSFXEventRef` | `C:\Assets\4.Developer\HsiCheng\Script\Fmod\FmodSFXEventRef.cs` |
| `FmodSFXEventSO` | `C:\Assets\4.Developer\HsiCheng\Script\Fmod\FmodSFXEventSO.cs` |
| `FmodSFXEventDispatcher` | `C:\Assets\4.Developer\HsiCheng\Script\Fmod\FmodSFXEventDispatcher.cs` |
| `FmodSFXEventCommunicator` | `C:\Assets\4.Developer\HsiCheng\Script\Fmod\FmodSFXEventCommunicator.cs` |
### MMFeedbacks Integration (More Mountains):
| Class | Path |
|-------|------|
| `MMF_FMOD_GlobalPlayEvent` | `C:\Assets\1.HonoHime\Core\FMODUtility\Scripts\MMFeedbacks\` |
| `MMF_FMOD_GlobalSetParameter` | Trigger global FMOD parameter |
| `MMF_FMOD_ParameterTrigger` | Trigger with parameter |
| `MMF_FMODUtilityPlayEventEmitter` | Play via event emitter |
| `MMF_FMODUtilityStopEventEmitter` | Stop via event emitter |
| `MMF_FMOD_MainBGM_ReplayCurrent` | Replay current BGM |
### FMOD Parameter Methods:
```
SetParameterByName() - Set parameter by string name
SetParameterFloat() - Set float parameter
SetParameterInt() - Set int parameter
SetParameterBoolean() - Set bool parameter
CheckSetParameter() - Validate parameter
CheckSetParameterSub() - Sub-check logic
```
### Scene Transition Controller:
**File:** `C:\Assets\4.Developer\Andy\FMODBooster\FMODSceneTransitionController.cs`
| Coroutine | Description |
|-----------|-------------|
| `<InitVolumeTransition>d__6` | Initialize volume transitions on scene load |
| `<StartGPFadeEventCheck>d__20` | Check/start fade events |
| `<StopAfterDelayRoutine>d__12` | Stop after delay |
---
## 5. ENEMY AUDIO SYSTEM
### EnemyAttackBase
**File:** `C:\Assets\1.HonoHime\Core\Character\Core\EnemyAttackBase.cs`
| State/Action | Description |
|--------------|-------------|
| `Attack` | Attack state/action |
| `Idle` | Idle state/action |
| `AlertAction_LookAtTarget` | Alert when noticing player |
| `AlertAction_MoveToTargetLastPosition` | Move to last known player position |
### EnemyActionManager
**File:** `C:\Assets\1.HonoHime\Core\Character\EnemyActionManager\EnemyActionManager.cs`
**File:** `C:\Assets\1.HonoHime\Core\Character\EnemyActionManager\EnemyAction.cs`
| Method/Property | Description |
|----------------|-------------|
| `GetEnemyActionManager` | Access to enemy action system |
| `GetEnemyAttack` | Get enemy attack controller |
| `enemyActionManager` | Reference field |
### Enemy Attack Controllers:
```
EnemyAttackAction - Basic attack action
EnemyAttackBase - Base attack behavior
EnemyAttackBlockedAction - When attack is blocked
EnemyAttackAcion_UseDamageSet - Attack using damage set
EnemyAssassinGroupManager - Group attack coordination
```
### Enemy Audio Handlers:
| Class | File | Description |
|-------|------|-------------|
| `EnemyDamageVoiceSFXHandler` | `C:\Assets\4.Developer\Andy\EnemyDamageSFXHandler\EnemyDamageVoiceSFXHandler.cs` | Handles damage voice SFX |
| `EnemyDamageVoiceSFXHandler|FeedbackVoice` | Feedback voice field |
| `AudioComponent` | `C:\Assets\1.HonoHime\Core\Character\DamageSystem\Component\AudioComponent.cs` | Damage system audio |
### Enemy Attack States Found:
```
SukebanShibaTwin|JumpAttackState
BoneGirl_GroundAttack|FinishState
BoneGirl_GrabAttack|BoneGirl_GrabAttackState
SukenBenSquadA|LeftRightDashAttackState
AttackAction_TransitionSpecialArt
AttackAction_Charge
AttackAction_QuakingStrike
```
---
## 6. CFVOICE SYSTEM
### CFVoiceEventUtility
**File:** `C:\Assets\1.HonoHime\Core\...` (pattern found in strings)
The CFVoice system triggers voice events based on game events:
| Event Key | Description |
|-----------|-------------|
| `CFVoiceEventUtility|Battle` | Battle events |
| `CFVoiceEventUtility|Challenge` | Challenge mode |
| `CFVoiceEventUtility|Chip` | Chip collection |
| `CFVoiceEventUtility|Enemy` | **Enemy-related** - important for enemy indicators |
| `CFVoiceEventUtility|EventKey` | Generic event key |
| `CFVoiceEventUtility|HH_Behaviour` | Character behavior events |
| `CFVoiceEventUtility|HH_Skill` | Skill usage |
| `CFVoiceEventUtility|Mission` | Mission events |
| `CFVoiceEventUtility|Note` | Note collection |
| `CFVoiceEventUtility|QTE` | QTE events |
| `CFVoiceEventUtility|Rank` | Rank up |
| `CFVoiceEventUtility|Reward` | Rewards |
| `CFVoiceEventUtility|Senbei` | Item-related |
| `CFVoiceEventUtility|Timer` | Timer events |
| `CFVoiceEventUtility|Trap` | Trap activation |
| `CFVoiceEventUtility|TreasureChest` | Chest opening |
### CFVoice Handlers:
| Class | File |
|-------|------|
| `MissionCFVoiceHandler` | `C:\Assets\1.HonoHime\Core\Level\MissionController\MissionCFVoiceHandler.cs` |
| `InventoryMonitorCFVoiceHandler` | `C:\Assets\4.Developer\Andy\FmodBGMController\Scripts\InventoryMonitorCFVoiceHandler.cs` |
| `CommonFunctionVoiceHandler` | `C:\Assets\4.Developer\Andy\FmodFunctionVoice\CommonFunctionVoiceHandler.cs` |
### CFVoice Properties Found:
```
get_EVENT_CFVOICE_BATTLE
get_EVENT_CFVOICE_ENEMY
get_EVENT_CFVOICE_MISSION
get_EVENT_CFVOICE_HPCHIP
get_EVENT_CFVOICE_QTE_SHIKIGAMI
get_EVENT_CFVOICE_QTE_FLURRYBARRIER
PlayCFVoice
```
---
## KEY HOOK POINTS FOR HARMONY PATCHES
### Audio Glitch Fixes:
1. **Voice Limit Fix** - Patch `UtageFmodVoiceManager.get_CountVoice` to enforce MAX_VOICES limit
2. **Ducking Glitch** - Patch `UpdateDucking` coroutine to fix fade timing issues
3. **Voice Cutoff Fix** - Patch `StopVoiceEvent` to properly handle crossfade before stopping
### Enemy Indicator Improvements:
1. **Alert Sound** - Hook into `CFVoiceEventUtility` with `Enemy` event key
2. **Attack Sound** - Patch `EnemyAttackBase.OnEnter` / `OnAttack` methods
3. **Idle Sound Loop** - Patch `EnemyAttackBase.Idle` state entry
### Priority Hook Targets:
| Priority | Class | Method | Purpose |
|----------|-------|--------|---------|
| HIGH | `UtageFmodVoiceManager` | `UpdateDucking` | Fix ducking glitches |
| HIGH | `UtageFmodVoiceManager` | `PlayVoice` | Voice limit enforcement |
| HIGH | `CFVoiceEventUtility` | `PlayCFVoice` | Enemy voice routing |
| MEDIUM | `FMODSoundManager` | `SetVolume` | Volume clamping |
| MEDIUM | `FMODSceneTransitionController` | `InitVolumeTransition` | Scene transition audio |
| MEDIUM | `EnemyDamageVoiceSFXHandler` | `FeedbackVoice` | Damage audio |
| LOW | `SnapshotManager` | `ApplySnapshot` | Reverb/snapshot control |
---
## SOURCE FILE REFERENCE LIST
### Voice Management:
- `C:\Assets\4.Developer\Andy\UtageVoiceManager\UtageFmodVoiceManager.cs`
- `C:\Assets\4.Developer\Andy\UtageVoiceManager\UtageFmodVoiceSetting.cs`
- `C:\Assets\4.Developer\Andy\UtageVoiceManager\VoiceEventSelector.cs`
- `C:\Assets\4.Developer\Andy\UtageVoiceManager\FmodVoiceStopper.cs`
- `C:\Assets\4.Developer\Andy\UtageVoiceManager\SnapshotManager.cs`
- `C:\Assets\4.Developer\Andy\UtageVoiceManager\SnapshotHandle.cs`
- `C:\Assets\4.Developer\Andy\UtageVoiceManager\DEAudioFadeManager.cs`
- `C:\Assets\4.Developer\Andy\UtageVoiceManager\FmodSoundDebugger.cs`
### FMOD Core:
- `C:\Assets\1.HonoHime\Core\FMODUtility\Scripts\FMODSoundManager.cs`
- `C:\Assets\1.HonoHime\Core\FMODUtility\Scripts\FMODUtility.cs`
- `C:\Assets\1.HonoHime\Core\FMODUtility\Scripts\FMODManager.cs`
### Enemy Audio:
- `C:\Assets\1.HonoHime\Core\Character\Core\EnemyAttackBase.cs`
- `C:\Assets\1.HonoHime\Core\Character\EnemyActionManager\EnemyActionManager.cs`
- `C:\Assets\4.Developer\Andy\EnemyDamageSFXHandler\EnemyDamageVoiceSFXHandler.cs`
- `C:\Assets\1.HonoHime\Core\Character\DamageSystem\Component\AudioComponent.cs`
### CFVoice System:
- (Source path partially truncated, but class is `CFVoiceEventUtility`)
- `C:\Assets\1.HonoHime\Core\Level\MissionController\MissionCFVoiceHandler.cs`
- `C:\Assets\4.Developer\Andy\FmodFunctionVoice\CommonFunctionVoiceHandler.cs`
### Scene/BGM:
- `C:\Assets\4.Developer\Andy\FMODBooster\FMODSceneTransitionController.cs`
- `C:\Assets\4.Developer\Andy\FmodBGMController\Scripts\MainBGMManager.cs`
- `C:\Assets\4.Developer\Andy\FmodBGMController\Scripts\FmodBGMController.cs`
### SFX Events:
- `C:\Assets\4.Developer\HsiCheng\Script\Fmod\FmodSFXEventRef.cs`
- `C:\Assets\4.Developer\HsiCheng\Script\Fmod\FmodSFXEventSO.cs`
- `C:\Assets\4.Developer\HsiCheng\Script\Fmod\FmodSFXEventDispatcher.cs`

View File

@@ -1,19 +1,125 @@
using System;
using System.Collections;
using HarmonyLib; using HarmonyLib;
using UnityEngine;
namespace HomuraHimeAudioMod.Patches namespace HomuraHimeAudioMod.Patches
{ {
/// <summary>
/// Patches for audio ducking system improvements.
/// TO BE IMPLEMENTED AFTER PHASE 2 CODE ANALYSIS
/// </summary>
public class AudioDuckingPatch public class AudioDuckingPatch
{ {
public const float COMBAT_DUCK_AMOUNT = 0.25f;
public const float COMBAT_DUCK_FADE_IN = 0.03f;
public const float COMBAT_DUCK_FADE_OUT = 0.15f;
public const float VOICE_DUCK_AMOUNT = 0.35f;
public const float SFX_DUCK_AMOUNT = 0.4f;
public static void Apply(ref Harmony harmony) public static void Apply(ref Harmony harmony)
{ {
// TODO: After Phase 2, implement patches for: Plugin.Log.LogInfo("Applying AudioDucking patches...");
// - Improve ducking fade times
// - Adjust duck amounts for combat var originalType = AccessTools.TypeByName("Andy.SnapshotManager");
// - Add custom ducking rules if (originalType != null)
{
Plugin.Log.LogInfo($"Found SnapshotManager type: {originalType.FullName}");
PatchSnapshotApply(harmony, originalType);
}
else
{
Plugin.Log.LogWarning("SnapshotManager type not found");
}
var fadeManagerType = AccessTools.TypeByName("Andy.DEAudioFadeManager");
if (fadeManagerType != null)
{
Plugin.Log.LogInfo($"Found DEAudioFadeManager type: {fadeManagerType.FullName}");
PatchFadeManager(harmony, fadeManagerType);
}
Plugin.Log.LogInfo("AudioDucking patches applied");
}
private static void PatchSnapshotApply(Harmony harmony, Type targetType)
{
try
{
var applySnapshotMethod = AccessTools.Method(targetType, "ApplySnapshot");
if (applySnapshotMethod != null)
{
harmony.Patch(
applySnapshotMethod,
prefix: new HarmonyMethod(typeof(AudioDuckingPatch), nameof(ApplySnapshotPrefix))
);
Plugin.Log.LogInfo("Patched ApplySnapshot");
}
}
catch (Exception ex)
{
Plugin.Log.LogError($"Error patching ApplySnapshot: {ex.Message}");
}
}
private static void PatchFadeManager(Harmony harmony, Type targetType)
{
try
{
var fadeInMethod = AccessTools.Method(targetType, "FadeIn");
var fadeOutMethod = AccessTools.Method(targetType, "FadeOut");
if (fadeInMethod != null)
{
harmony.Patch(
fadeInMethod,
prefix: new HarmonyMethod(typeof(AudioDuckingPatch), nameof(FadeInPrefix))
);
Plugin.Log.LogInfo("Patched FadeIn");
}
if (fadeOutMethod != null)
{
harmony.Patch(
fadeOutMethod,
prefix: new HarmonyMethod(typeof(AudioDuckingPatch), nameof(FadeOutPrefix))
);
Plugin.Log.LogInfo("Patched FadeOut");
}
}
catch (Exception ex)
{
Plugin.Log.LogError($"Error patching FadeManager: {ex.Message}");
}
}
private static bool ApplySnapshotPrefix(ref string snapshotName, ref float fadeTime)
{
if (fadeTime < COMBAT_DUCK_FADE_IN)
{
fadeTime = COMBAT_DUCK_FADE_IN;
}
if (snapshotName != null && snapshotName.Contains("Battle"))
{
Plugin.Log.LogDebug($"Battle snapshot detected: {snapshotName}, fadeTime: {fadeTime}");
}
return true;
}
private static bool FadeInPrefix(ref float fadeTime)
{
if (fadeTime < 0.01f)
{
fadeTime = 0.01f;
}
return true;
}
private static bool FadeOutPrefix(ref float fadeTime)
{
if (fadeTime < 0.05f)
{
fadeTime = 0.05f;
}
return true;
} }
} }
} }

View File

@@ -1,19 +1,141 @@
using System;
using HarmonyLib; using HarmonyLib;
using UnityEngine;
namespace HomuraHimeAudioMod.Patches namespace HomuraHimeAudioMod.Patches
{ {
/// <summary>
/// Patches for enemy behavior audio indicator improvements.
/// TO BE IMPLEMENTED AFTER PHASE 2 CODE ANALYSIS
/// </summary>
public class EnemyAudioPatch public class EnemyAudioPatch
{ {
public const float ENEMY_INDICATOR_VOLUME_BOOST = 1.2f;
public const float ALERT_SOUND_VOLUME_BOOST = 1.3f;
public const float ATTACK_SOUND_VOLUME_BOOST = 1.15f;
public static void Apply(ref Harmony harmony) public static void Apply(ref Harmony harmony)
{ {
// TODO: After Phase 2, implement patches for: Plugin.Log.LogInfo("Applying EnemyAudio patches...");
// - Boost enemy indicator volumes
// - Improve state change audio cues PatchEnemyAttackBase(harmony);
// - Add debug logging for enemy audio PatchCFVoiceEventUtility(harmony);
PatchEnemyDamageVoiceSFXHandler(harmony);
Plugin.Log.LogInfo("EnemyAudio patches applied");
}
private static void PatchEnemyAttackBase(Harmony harmony)
{
try
{
var enemyAttackBaseType = AccessTools.TypeByName("EnemyAttackBase");
if (enemyAttackBaseType != null)
{
Plugin.Log.LogInfo($"Found EnemyAttackBase type: {enemyAttackBaseType.FullName}");
var attackMethods = new[] { "Attack", "OnAttack", "DoAttack", "AlertAction" };
foreach (var methodName in attackMethods)
{
var method = AccessTools.Method(enemyAttackBaseType, methodName);
if (method != null)
{
harmony.Patch(
method,
prefix: new HarmonyMethod(typeof(EnemyAudioPatch), nameof(EnemyAttackPrefix))
);
Plugin.Log.LogInfo($"Patched EnemyAttackBase.{methodName}");
}
}
}
else
{
Plugin.Log.LogWarning("EnemyAttackBase type not found");
}
}
catch (Exception ex)
{
Plugin.Log.LogError($"Error patching EnemyAttackBase: {ex.Message}");
}
}
private static void PatchCFVoiceEventUtility(Harmony harmony)
{
try
{
var cfVoiceType = AccessTools.TypeByName("CFVoiceEventUtility");
if (cfVoiceType != null)
{
Plugin.Log.LogInfo($"Found CFVoiceEventUtility type: {cfVoiceType.FullName}");
var playCFVoiceMethod = AccessTools.Method(cfVoiceType, "PlayCFVoice");
if (playCFVoiceMethod != null)
{
harmony.Patch(
playCFVoiceMethod,
prefix: new HarmonyMethod(typeof(EnemyAudioPatch), nameof(PlayCFVoicePrefix))
);
Plugin.Log.LogInfo("Patched PlayCFVoice");
}
}
else
{
Plugin.Log.LogWarning("CFVoiceEventUtility type not found");
}
}
catch (Exception ex)
{
Plugin.Log.LogError($"Error patching CFVoiceEventUtility: {ex.Message}");
}
}
private static void PatchEnemyDamageVoiceSFXHandler(Harmony harmony)
{
try
{
var handlerType = AccessTools.TypeByName("EnemyDamageVoiceSFXHandler");
if (handlerType != null)
{
Plugin.Log.LogInfo($"Found EnemyDamageVoiceSFXHandler type: {handlerType.FullName}");
var feedbackVoiceField = AccessTools.Field(handlerType, "FeedbackVoice");
if (feedbackVoiceField != null)
{
Plugin.Log.LogInfo("Found FeedbackVoice field - enemy damage audio hookable");
}
}
}
catch (Exception ex)
{
Plugin.Log.LogError($"Error patching EnemyDamageVoiceSFXHandler: {ex.Message}");
}
}
private static bool EnemyAttackPrefix(string eventKey)
{
if (!string.IsNullOrEmpty(eventKey))
{
Plugin.Log.LogDebug($"Enemy attack event: {eventKey}");
if (eventKey.Contains("Alert") || eventKey.Contains("Warning"))
{
Plugin.Log.LogDebug($"Enemy alert sound detected: {eventKey}");
}
else if (eventKey.Contains("Attack"))
{
Plugin.Log.LogDebug($"Enemy attack sound: {eventKey}");
}
}
return true;
}
private static bool PlayCFVoicePrefix(ref string eventKey)
{
if (string.IsNullOrEmpty(eventKey))
return true;
if (eventKey.Contains("Enemy"))
{
Plugin.Log.LogDebug($"Enemy voice event triggered: {eventKey}");
}
return true;
} }
} }
} }

View File

@@ -1,19 +1,157 @@
using System;
using System.Collections;
using HarmonyLib; using HarmonyLib;
using UnityEngine;
namespace HomuraHimeAudioMod.Patches namespace HomuraHimeAudioMod.Patches
{ {
/// <summary>
/// Patches for voice limit and voice manager improvements.
/// TO BE IMPLEMENTED AFTER PHASE 2 CODE ANALYSIS
/// </summary>
public class VoiceManagerPatch public class VoiceManagerPatch
{ {
public const int MAX_VOICE_COUNT = 128;
public const float DEFAULT_DUCK_FADE_TIME = 0.05f;
public const float DEFAULT_DUCK_VOLUME = 0.3f;
public static void Apply(ref Harmony harmony) public static void Apply(ref Harmony harmony)
{ {
// TODO: After Phase 2, implement patches for: Plugin.Log.LogInfo("Applying VoiceManager patches...");
// - Increase max voice count
// - Improve voice stealing behavior var originalType = AccessTools.TypeByName("Andy.UtageFmodVoiceManager");
// - Adjust pooling sizes if (originalType != null)
{
Plugin.Log.LogInfo($"Found UtageFmodVoiceManager type: {originalType.FullName}");
PatchUpdateDucking(harmony, originalType);
PatchVoiceCount(harmony, originalType);
PatchDuckVolume(harmony, originalType);
} }
else
{
Plugin.Log.LogWarning("UtageFmodVoiceManager type not found by name, searching...");
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
foreach (var type in assembly.GetTypes())
{
if (type.Name.Contains("FmodVoiceManager"))
{
Plugin.Log.LogInfo($"Found alternative: {type.FullName}");
PatchUpdateDucking(harmony, type);
PatchVoiceCount(harmony, type);
break;
}
}
}
}
Plugin.Log.LogInfo("VoiceManager patches applied");
}
private static void PatchUpdateDucking(Harmony harmony, Type targetType)
{
try
{
var updateDuckingMethod = AccessTools.Method(targetType, "UpdateDucking");
if (updateDuckingMethod != null)
{
harmony.Patch(
updateDuckingMethod,
postfix: new HarmonyMethod(typeof(VoiceManagerPatch), nameof(UpdateDuckingPostfix))
);
Plugin.Log.LogInfo("Patched UpdateDucking");
}
else
{
Plugin.Log.LogWarning("UpdateDucking method not found");
}
}
catch (Exception ex)
{
Plugin.Log.LogError($"Error patching UpdateDucking: {ex.Message}");
}
}
private static void PatchVoiceCount(Harmony harmony, Type targetType)
{
try
{
var countVoiceProperty = AccessTools.Property(targetType, "CountVoice");
if (countVoiceProperty != null)
{
var getter = countVoiceProperty.GetGetMethod();
if (getter != null)
{
harmony.Patch(
getter,
postfix: new HarmonyMethod(typeof(VoiceManagerPatch), nameof(CountVoicePostfix))
);
Plugin.Log.LogInfo("Patched CountVoice getter");
}
}
else
{
Plugin.Log.LogWarning("CountVoice property not found");
}
}
catch (Exception ex)
{
Plugin.Log.LogError($"Error patching CountVoice: {ex.Message}");
}
}
private static void PatchDuckVolume(Harmony harmony, Type targetType)
{
try
{
var duckVolumeProperty = AccessTools.Property(targetType, "DuckVolume");
if (duckVolumeProperty != null)
{
var setter = duckVolumeProperty.GetSetMethod();
if (setter != null)
{
harmony.Patch(
setter,
prefix: new HarmonyMethod(typeof(VoiceManagerPatch), nameof(DuckVolumePrefix))
);
Plugin.Log.LogInfo("Patched DuckVolume setter");
}
}
}
catch (Exception ex)
{
Plugin.Log.LogError($"Error patching DuckVolume: {ex.Message}");
}
}
private static void UpdateDuckingPostfix(IEnumerator self, UtageFmodVoiceManager __instance)
{
if (__instance != null)
{
var duckFadeTimeField = AccessTools.Field(__instance.GetType(), "duckFadeTime");
if (duckFadeTimeField != null)
{
duckFadeTimeField.SetValue(__instance, DEFAULT_DUCK_FADE_TIME);
}
}
}
private static void CountVoicePostfix(ref int __result)
{
if (__result > MAX_VOICE_COUNT)
{
__result = MAX_VOICE_COUNT;
}
}
private static bool DuckVolumePrefix(ref float value)
{
if (value < DEFAULT_DUCK_VOLUME)
{
value = DEFAULT_DUCK_VOLUME;
}
return true;
}
}
public class UtageFmodVoiceManager : MonoBehaviour
{
} }
} }

View File

@@ -24,24 +24,27 @@ namespace HomuraHimeAudioMod
harmony = new Harmony(PluginInfo.PLUGIN_GUID); harmony = new Harmony(PluginInfo.PLUGIN_GUID);
Log.LogInfo($"HomuraHime Audio Mod v{PluginInfo.PLUGIN_VERSION} initializing...");
ApplyPatches(); ApplyPatches();
Log.LogInfo("HomuraHime Audio Mod initialized successfully");
} }
private void ApplyPatches() private void ApplyPatches()
{ {
Log.LogInfo($"Applying audio patches..."); Log.LogInfo("Applying audio patches...");
// Phase 2 will populate these patch classes after code analysis VoiceManagerPatch.Apply(ref harmony);
// VoiceManagerPatch.Apply(ref harmony); AudioDuckingPatch.Apply(ref harmony);
// AudioDuckingPatch.Apply(ref harmony); EnemyAudioPatch.Apply(ref harmony);
// EnemyAudioPatch.Apply(ref harmony);
Log.LogInfo($"Patches applied successfully"); Log.LogInfo("All patches applied successfully");
} }
private void OnDestroy() private void OnDestroy()
{ {
harmony?.UnpatchAll(); harmony?.UnpatchAll(PluginInfo.PLUGIN_GUID);
} }
} }
} }