Fixed knockout grunts still only playing for the knocked player: hook moved to PlayerAudio.StartKnockoutLoopLocalOnly, which the game invokes on all clients via the synced knockout VFX hook (remote SyncVar updates bypass the knockout-state setter we patched before).
Knockout clip choice now derives from synced KnockedOutVfxData so all clients pick the same variant.
v1.4.10
Fixed knockout grunts only playing for the knocked player in multiplayer: the SyncVar hook now plays for all clients (like jump grunts). Removed the TargetRpc-only observer hook that never reached other players.
v1.4.9
Fixed mouse cursor staying on screen after closing the F2 overlay: release the game's CursorManager force-unlock and call InputManager.UpdateCursorLock() so gameplay re-hides the cursor.
v1.4.8
Fixed remaining startup Harmony error: avoid ambiguous Mirror ReadNetworkBehaviour lookup in a static constructor (match the call site from transpiler IL instead).
v1.4.7
Fixed F2 overlay not listing VoicePack folders when Harmony PatchAll failed during startup (pack discovery now runs before patches; PatchAll is caught so Start() always runs).
Fixed ReadNetworkBehaviour<PlayerInfo> ambiguous Mirror method lookup that broke jump/knock clip sync patches in v1.4.6.
v1.4.6
Fixed BepInEx startup errors: invalid Harmony __knockClipIndex state on knockout SyncVar patch, and invalid IL from the knockout Rpc clip transpiler (stack mismatch).
v1.4.5
Fixed jump and knocked clip sync in multiplayer: clip index now piggybacks on existing Cmd/Rpc payloads the same way swing clips use encoded power, instead of per-client random or mismatched timestamps.
v1.4.4
F2 overlay title now shows uhm — VoiceGrunts.
v1.4.2
Fixed BepInEx log spam when closing the overlay with Esc on games using Unity's new Input System.
v1.4.1
F2 overlay buttons can show custom pack names via Sounds/VoicePackN/displayname.txt or BepInEx config [DisplayNames] PackN.
v1.4.0
Jump grunt clip choice now syncs in multiplayer (clip index piggybacked on existing jump Cmd/Rpc).
Knocked grunt clip choice now syncs via deterministic selection from the synced knockout timestamp (all clients pick the same clip).
Added F2 voice pack overlay — toggle in-game picker to switch packs on the fly (configurable hotkey under [UI] OverlayHotkey).
v1.3.5
Fixed remote players always hearing the first swing clip (grunt_1): the server was re-encoding the swing RPC with clip index 0 after stripping it in the Cmd handler. It now preserves the captured clip index when re-sending the Rpc.
v1.3.4
Fixed knocked grunts still only playing locally in multiplayer: observers now hook PlayerMovement.RpcInformKnockedOutOtherPlayer (the game's actual knockout notification RPC). Local knocked player still uses the SyncVar setter hook.
Swing grunt clip choice is now synced across clients: the random variant index is piggybacked on the existing swing RPC alongside voice pack id (both players must run v1.3.4+).
v1.3.3
Fixed knocked grunts not playing for remote players in multiplayer: hook moved from local-only SetKnockOutState to Mirror SyncVar setter set_NetworkknockoutState, which runs on all clients when knockout state replicates.
v1.3.2
Fixed knocked grunts not playing: Harmony patch parameter renamed to state to match PlayerMovement.SetKnockOutState.
Fixed Announcer volume slider having no effect: v1.3.1 routed through a non-existent announcerBus field; grunts now read GameSettings.All.Audio.AnnouncerVolume and apply it via channel.setVolume after each play.
v1.3.1
Voice grunts (swing, jump, knocked) now route through the game's Announcer FMOD bus, so the Announcer volume slider controls mod audio.
v1.3.0
Voice packs expanded to 1–9 (drop in VoicePack5–VoicePack9 folders; config accepts up to 9).
Added Knocked grunts when a player is knocked out (Knocked/Standard/ per pack, same layout as jump).
Knocked grunts replicate in multiplayer using the same pack sync as swings/jumps.
v1.2.3
Fixed host→client voice pack sync: the game server was stripping the encoded swing power before Rpc, so joining players always heard the host on VoicePack1. The server now captures the pack from the Cmd and re-encodes before Rpc is sent to clients.
v1.2.2
Fixed asymmetric voice pack sync: pack 1 appeared to work for everyone because decode defaulted to 1 when the tiny float offset was lost over the network. Encoding now uses a ones-digit suffix (e.g. power 0.75 + pack 2 → 0.7502) that survives Mirror float serialization.
v1.2.1
Fixed joining player disconnect on first swing. Removed custom Mirror network messages entirely.
Voice pack id now piggybacks on the existing swing RPC via a tiny offset in normalizedPower (invisible to gameplay audio).
Jump grunts use the last pack learned from that player's most recent swing.
v1.2.0
Restored multiplayer voice pack sync using a safer approach: pack choice is sent when you swing or jump (not at lobby creation), so hosts no longer disconnect when opening a lobby.
Other modded players hear your configured voice pack once you take your first swing or jump in a match.
v1.1.3
Removed all custom Mirror network messages — they were disconnecting hosts from their own lobbies. Voice pack selection now applies locally from config only (your swings use your chosen pack). Multiplayer voice sync will return in a future version using a safer approach.
v1.1.2
Fixed lobby disconnects caused by custom Mirror network messages missing IL2CPP writers. Voice pack sync now uses manual message handlers compatible with BepInEx.
v1.1.1
Fixed voice pack selection staying on pack 1 (VoicePackSync NullReferenceException). Pack choice now reads config directly for your swings and broadcasts via Mirror network messages for multiplayer.
Startup log now lists each loaded clip path so you can verify the correct files were picked up.
v1.1.0
Added four voice packs (VoicePack1–VoicePack4) with Mirror SyncVar replication.
Your configured pack is what other modded players hear when you swing or jump.
Choose your pack via BepInEx config: [Voice] SelectedPack = 1 (1–4), editable in r2modman mod settings.
v1.0.0
Initial release as a standalone mod.
Layered swing grunts by power tier and jump grunts from local Sounds/ folders.