From 5b36c02ff07f5d75e3559111e5620bbe8398ebf8 Mon Sep 17 00:00:00 2001 From: Gabe Kauffman Date: Thu, 2 Oct 2025 19:27:06 -0400 Subject: [PATCH] Implement a "ka-ching" sound effect on kill (#2097) ## Description: Building off of [this PR](https://github.com/openfrontio/OpenFrontIO/pull/2090) which implemented music, I extend this functionality to add sound effects. Diff will be reduced if and when that PR gets merged! I think the game would benefit from more sound effects, and adding a "ka-ching" sound effect on kill seems like an easy place to start. The ka-ching sound effect was found [here](https://freesound.org/people/AKkingStudio/sounds/684165/) and is licensed under Creative Commons. ## Please complete the following: - [x] I have added screenshots for all UI updates - [x] I process any text displayed to the user through translateText() and I've added it to the en.json file - [x] I have added relevant tests to the test directory - [x] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced Demo video with sound: https://github.com/user-attachments/assets/18c857a4-a741-492a-bbc1-68d4f3ba38da ## Please put your Discord username so you can be contacted if a bug or regression is found: basedgob --------- Co-authored-by: icslucas --- resources/lang/en.json | 3 +- resources/sounds/effects/ka-ching.mp3 | Bin 0 -> 10906 bytes src/client/graphics/layers/FxLayer.ts | 3 + src/client/graphics/layers/SettingsModal.ts | 35 ++++++++++ src/client/sound/SoundManager.ts | 73 ++++++++++++++++++-- src/core/game/UserSettings.ts | 8 +++ 6 files changed, 115 insertions(+), 7 deletions(-) create mode 100644 resources/sounds/effects/ka-ching.mp3 diff --git a/resources/lang/en.json b/resources/lang/en.json index f3ef57e7d..f4165a490 100644 --- a/resources/lang/en.json +++ b/resources/lang/en.json @@ -380,7 +380,8 @@ "terrain_disabled": "Terrain view disabled", "exit_game_label": "Exit Game", "exit_game_info": "Return to main menu", - "background_music_volume": "Background Music Volume" + "background_music_volume": "Background Music Volume", + "sound_effects_volume": "Sound Effects Volume" }, "chat": { "title": "Quick Chat", diff --git a/resources/sounds/effects/ka-ching.mp3 b/resources/sounds/effects/ka-ching.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..fc506bdcfcee85521c42e48fd5844227ea6419e0 GIT binary patch literal 10906 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 { this.isVisible = event.isVisible; this.shouldPause = event.shouldPause; @@ -162,6 +163,13 @@ export class SettingsModal extends LitElement implements Layer { this.requestUpdate(); } + private onSoundEffectsVolumeChange(event: Event) { + const volume = parseFloat((event.target as HTMLInputElement).value) / 100; + this.userSettings.setSoundEffectsVolume(volume); + SoundManager.setSoundEffectsVolume(volume); + this.requestUpdate(); + } + render() { if (!this.isVisible) { return null; @@ -221,6 +229,33 @@ export class SettingsModal extends LitElement implements Layer { +
+ soundEffectsIcon +
+
+ ${translateText("user_setting.sound_effects_volume")} +
+ +
+
+ ${Math.round(this.userSettings.soundEffectsVolume() * 100)}% +
+
+