Compare commits
2 Commits
7169d4533b
...
71712b834c
| Author | SHA1 | Date | |
|---|---|---|---|
| 71712b834c | |||
| aa3de01335 |
13
.beads/backup/backup_state.json
Normal file
13
.beads/backup/backup_state.json
Normal 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
|
||||
}
|
||||
}
|
||||
0
.beads/backup/comments.jsonl
Normal file
0
.beads/backup/comments.jsonl
Normal file
11
.beads/backup/config.jsonl
Normal file
11
.beads/backup/config.jsonl
Normal 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"}
|
||||
0
.beads/backup/dependencies.jsonl
Normal file
0
.beads/backup/dependencies.jsonl
Normal file
10
.beads/backup/events.jsonl
Normal file
10
.beads/backup/events.jsonl
Normal 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":""}
|
||||
6
.beads/backup/issues.jsonl
Normal file
6
.beads/backup/issues.jsonl
Normal 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":""}
|
||||
0
.beads/backup/labels.jsonl
Normal file
0
.beads/backup/labels.jsonl
Normal file
312
docs/CODE_ANALYSIS_PHASE2.md
Normal file
312
docs/CODE_ANALYSIS_PHASE2.md
Normal 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`
|
||||
@@ -1,19 +1,125 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using HarmonyLib;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HomuraHimeAudioMod.Patches
|
||||
{
|
||||
/// <summary>
|
||||
/// Patches for audio ducking system improvements.
|
||||
/// TO BE IMPLEMENTED AFTER PHASE 2 CODE ANALYSIS
|
||||
/// </summary>
|
||||
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)
|
||||
{
|
||||
// TODO: After Phase 2, implement patches for:
|
||||
// - Improve ducking fade times
|
||||
// - Adjust duck amounts for combat
|
||||
// - Add custom ducking rules
|
||||
Plugin.Log.LogInfo("Applying AudioDucking patches...");
|
||||
|
||||
var originalType = AccessTools.TypeByName("Andy.SnapshotManager");
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,141 @@
|
||||
using System;
|
||||
using HarmonyLib;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HomuraHimeAudioMod.Patches
|
||||
{
|
||||
/// <summary>
|
||||
/// Patches for enemy behavior audio indicator improvements.
|
||||
/// TO BE IMPLEMENTED AFTER PHASE 2 CODE ANALYSIS
|
||||
/// </summary>
|
||||
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)
|
||||
{
|
||||
// TODO: After Phase 2, implement patches for:
|
||||
// - Boost enemy indicator volumes
|
||||
// - Improve state change audio cues
|
||||
// - Add debug logging for enemy audio
|
||||
Plugin.Log.LogInfo("Applying EnemyAudio patches...");
|
||||
|
||||
PatchEnemyAttackBase(harmony);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,157 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using HarmonyLib;
|
||||
using UnityEngine;
|
||||
|
||||
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 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)
|
||||
{
|
||||
// TODO: After Phase 2, implement patches for:
|
||||
// - Increase max voice count
|
||||
// - Improve voice stealing behavior
|
||||
// - Adjust pooling sizes
|
||||
Plugin.Log.LogInfo("Applying VoiceManager patches...");
|
||||
|
||||
var originalType = AccessTools.TypeByName("Andy.UtageFmodVoiceManager");
|
||||
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
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,24 +24,27 @@ namespace HomuraHimeAudioMod
|
||||
|
||||
harmony = new Harmony(PluginInfo.PLUGIN_GUID);
|
||||
|
||||
Log.LogInfo($"HomuraHime Audio Mod v{PluginInfo.PLUGIN_VERSION} initializing...");
|
||||
|
||||
ApplyPatches();
|
||||
|
||||
Log.LogInfo("HomuraHime Audio Mod initialized successfully");
|
||||
}
|
||||
|
||||
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);
|
||||
// AudioDuckingPatch.Apply(ref harmony);
|
||||
// EnemyAudioPatch.Apply(ref harmony);
|
||||
VoiceManagerPatch.Apply(ref harmony);
|
||||
AudioDuckingPatch.Apply(ref harmony);
|
||||
EnemyAudioPatch.Apply(ref harmony);
|
||||
|
||||
Log.LogInfo($"Patches applied successfully");
|
||||
Log.LogInfo("All patches applied successfully");
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
harmony?.UnpatchAll();
|
||||
harmony?.UnpatchAll(PluginInfo.PLUGIN_GUID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user