Skip to content

New AudioStatics class and WeaponDef improvements#1

Open
Majavaa wants to merge 175 commits into
masterfrom
audio/weapondef-soundvariations
Open

New AudioStatics class and WeaponDef improvements#1
Majavaa wants to merge 175 commits into
masterfrom
audio/weapondef-soundvariations

Conversation

@Majavaa
Copy link
Copy Markdown
Owner

@Majavaa Majavaa commented Dec 17, 2025

Summary by CodeRabbit

  • New Features

    • Automatic sound fallback to gracefully handle missing audio and improve playback reliability.
    • Improved sound-loading debug logs for clearer diagnostics.
  • Refactor

    • Sound loading centralized into a shared utility to ensure consistent behavior and easier maintenance.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Dec 17, 2025

Important

Review skipped

Too many files!

This PR contains 291 files, which is 141 over the limit of 150.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 237ec676-139a-4455-a72c-57876098a10b

📥 Commits

Reviewing files that changed from the base of the PR and between d27d2e7 and 0bf65d6.

⛔ Files ignored due to path filters (1)
  • cont/base/springcontent/shaders/GLSL/GroundDecalsVertProg.glsl is excluded by !**/*.glsl
📒 Files selected for processing (291)
  • .github/_deprecated/build.yml
  • .github/workflows/build-docker.yml
  • .github/workflows/docker-images-build.yml
  • .github/workflows/engine-build.yml
  • .github/workflows/opencode.yml
  • .github/workflows/release.yml
  • .github/workflows/streflop-float-test.yml
  • .gitignore
  • .gitmodules
  • AGENTS.md
  • AI/CMakeLists.txt
  • AI/Wrappers/CUtils/SharedLibrary.c
  • AI_POLICY.md
  • CMakeLists.txt
  • README.markdown
  • cont/LuaUI/callins.lua
  • cont/LuaUI/fonts.lua
  • cont/LuaUI/main.lua
  • cont/LuaUI/widgets.lua
  • cont/base/springcontent/LuaGadgets/callins.lua
  • cont/base/springcontent/LuaGadgets/gadgets.lua
  • cont/base/springcontent/LuaHandler/Utilities/specialCallinHandlers.lua
  • cont/base/springcontent/gamedata/explosion_alias.lua
  • cont/examples/Widgets/RandomIconWidget.lua
  • cont/examples/Widgets/minimap_changed_mock.lua
  • doc/site/content/articles/netcode-overview.markdown
  • doc/site/content/changelogs/_index.markdown
  • doc/site/content/changelogs/changelog-105-2511.markdown
  • doc/site/content/changelogs/changelog-2025-04.markdown
  • doc/site/content/development/building-with-docker.md
  • doc/site/content/development/building-without-docker.md
  • doc/site/content/docs/guides/getting-started/_index.md
  • doc/site/content/docs/guides/getting-started/first-steps-with-the-engine.md
  • doc/site/content/docs/guides/wupget.md
  • doc/site/layouts/shortcodes/base_url.html
  • docker-build-v2/README.md
  • docker-build-v2/_resolve_container_runtime.sh
  • docker-build-v2/amd64-linux/Dockerfile.20.04
  • docker-build-v2/amd64-windows/ccache.conf
  • docker-build-v2/build.sh
  • docker-build-v2/images/all-linux/Dockerfile
  • docker-build-v2/images/all-linux/toolchain.cmake
  • docker-build-v2/images/all/ccache.conf
  • docker-build-v2/images/amd64-linux/build.sh
  • docker-build-v2/images/amd64-windows/Dockerfile
  • docker-build-v2/images/amd64-windows/build.sh
  • docker-build-v2/images/amd64-windows/toolchain.cmake
  • docker-build-v2/images/arm64-linux/build.sh
  • docker-build-v2/images_versions.sh
  • docker-build-v2/scripts/compile.sh
  • docker-build/Dockerfile
  • docker-build/README.md
  • docker-build/action.yml
  • docker-build/build.cmd
  • docker-build/build.sh
  • docker-build/config/ccache.conf
  • docker-build/init_container.sh
  • docker-build/scripts/00_setup.sh
  • docker-build/scripts/01_clone.sh
  • docker-build/scripts/02_configure.sh
  • docker-build/scripts/03_compile.sh
  • docker-build/scripts/04_install.sh
  • docker-build/scripts/05_fill_debugsymbol_dir.sh
  • docker-build/scripts/06_fill_build_options_file.sh
  • docker-build/scripts/07_pack_build_artifacts.sh
  • docker-build/scripts/08_copy_to_publish_dir.sh
  • docker-build/scripts/build.sh
  • docker-build/scripts/dev.sh
  • docker-build/scripts/entrypoint.sh
  • docker-build/scripts/linux-64.cmake
  • docker-build/scripts/update-ccache-symlinks.sh
  • docker-build/scripts/windows-64.cmake
  • rts/CMakeLists.txt
  • rts/ExternalAI/SSkirmishAICallbackImpl.cpp
  • rts/Game/Game.cpp
  • rts/Game/GameHelper.cpp
  • rts/Game/InMapDrawModel.cpp
  • rts/Game/InMapDrawModel.h
  • rts/Game/Players/TeamController.h
  • rts/Game/UI/MiniMap.cpp
  • rts/Game/UI/MiniMap.h
  • rts/Game/UI/TooltipConsole.cpp
  • rts/Game/UnsyncedGameCommands.cpp
  • rts/Lua/LuaConstCMD.cpp
  • rts/Lua/LuaConstCOB.cpp
  • rts/Lua/LuaConstEngine.cpp
  • rts/Lua/LuaConstGame.cpp
  • rts/Lua/LuaContextData.h
  • rts/Lua/LuaHandle.cpp
  • rts/Lua/LuaHandle.h
  • rts/Lua/LuaHandleSynced.cpp
  • rts/Lua/LuaMemPool.cpp
  • rts/Lua/LuaOpenGL.cpp
  • rts/Lua/LuaSyncedCtrl.cpp
  • rts/Lua/LuaSyncedCtrl.h
  • rts/Lua/LuaSyncedRead.cpp
  • rts/Lua/LuaSyncedRead.h
  • rts/Lua/LuaUnitDefs.cpp
  • rts/Lua/LuaUnsyncedCtrl.cpp
  • rts/Lua/LuaUnsyncedCtrl.h
  • rts/Lua/LuaUnsyncedRead.cpp
  • rts/Lua/LuaUnsyncedRead.h
  • rts/Lua/LuaUtils.h
  • rts/Lua/LuaVAOImpl.cpp
  • rts/Lua/LuaVBOImpl.cpp
  • rts/Lua/LuaVFS.cpp
  • rts/Lua/LuaWeaponDefs.cpp
  • rts/Net/GameServer.cpp
  • rts/Rendering/CMakeLists.txt
  • rts/Rendering/Env/Decals/GroundDecalHandler.cpp
  • rts/Rendering/Env/Decals/GroundDecalHandler.h
  • rts/Rendering/Env/IGroundDecalDrawer.h
  • rts/Rendering/Env/Particles/Classes/BitmapMuzzleFlame.cpp
  • rts/Rendering/Env/Particles/Classes/GeoThermSmokeProjectile.cpp
  • rts/Rendering/Env/Particles/Classes/SimpleParticleSystem.cpp
  • rts/Rendering/Env/Particles/Classes/SimpleParticleSystem.h
  • rts/Rendering/Env/Particles/ProjectileDrawer.cpp
  • rts/Rendering/Env/Particles/ProjectileDrawer.h
  • rts/Rendering/Fonts/TextWrap.cpp
  • rts/Rendering/Fonts/TextWrap.h
  • rts/Rendering/Fonts/glFont.cpp
  • rts/Rendering/Fonts/glFont.h
  • rts/Rendering/GL/RenderBuffers.h
  • rts/Rendering/GL/StreamBuffer.h
  • rts/Rendering/GL/myGL.cpp
  • rts/Rendering/IconHandler.cpp
  • rts/Rendering/IconHandler.h
  • rts/Rendering/Models/3DModelPiece.cpp
  • rts/Rendering/Models/3DModelPiece.hpp
  • rts/Rendering/Models/GLTFParser.cpp
  • rts/Rendering/Models/ModelUtils.cpp
  • rts/Rendering/Models/ModelUtils.h
  • rts/Rendering/Shaders/GLSLCopyState.cpp
  • rts/Rendering/ShadowHandler.cpp
  • rts/Rendering/Textures/3DOTextureHandler.cpp
  • rts/Rendering/Textures/3DOTextureHandler.h
  • rts/Rendering/Textures/Bitmap.cpp
  • rts/Rendering/Textures/IAtlasAllocator.cpp
  • rts/Rendering/Textures/IAtlasAllocator.h
  • rts/Rendering/Textures/LegacyAtlasAlloc.cpp
  • rts/Rendering/Textures/MultiPageAtlasAlloc.hpp
  • rts/Rendering/Textures/QuadtreeAtlasAlloc.cpp
  • rts/Rendering/Textures/RowAtlasAlloc.cpp
  • rts/Rendering/Textures/Texture.cpp
  • rts/Rendering/Textures/Texture.hpp
  • rts/Rendering/Textures/TextureAtlas.cpp
  • rts/Rendering/Textures/TextureAtlas.h
  • rts/Rendering/Textures/TextureRenderAtlas.cpp
  • rts/Rendering/Textures/TextureRenderAtlas.h
  • rts/Rendering/Units/UnitDrawer.h
  • rts/Rendering/Units/UnitDrawerData.cpp
  • rts/Rendering/Units/UnitDrawerData.h
  • rts/Rml/Backends/RmlUi_Backend.cpp
  • rts/Rml/Backends/RmlUi_Renderer_GL3_Recoil.cpp
  • rts/Rml/Backends/RmlUi_Renderer_GL3_Recoil.h
  • rts/Rml/Backends/RmlUi_SystemInterface.cpp
  • rts/Rml/Backends/RmlUi_SystemInterface.h
  • rts/Rml/Components/ElementLuaTexture.cpp
  • rts/Rml/SolLua/CMakeLists.txt
  • rts/Rml/SolLua/RmlSolLua.cpp
  • rts/Rml/SolLua/RmlSolLua.h
  • rts/Rml/SolLua/bind/Context.cpp
  • rts/Rml/SolLua/bind/Element.cpp
  • rts/Rml/SolLua/bind/ElementForm.cpp
  • rts/Rml/SolLua/bind/Global.cpp
  • rts/Rml/SolLua/bind/StyleSheet.cpp
  • rts/Rml/SolLua/bind/bind.h
  • rts/Rml/SolLua/plugin/SolLuaDataModel.cpp
  • rts/Rml/SolLua/plugin/SolLuaDataModel.h
  • rts/Rml/SolLua/plugin/SolLuaPlugin.h
  • rts/Sim/CMakeLists.txt
  • rts/Sim/Features/Feature.cpp
  • rts/Sim/Features/Feature.h
  • rts/Sim/Misc/ModInfo.cpp
  • rts/Sim/Misc/ModInfo.h
  • rts/Sim/Misc/QuadField.cpp
  • rts/Sim/Misc/Resource.h
  • rts/Sim/Misc/YardmapStatusEffectsMap.cpp
  • rts/Sim/Misc/YardmapStatusEffectsMap.h
  • rts/Sim/MoveTypes/AAirMoveType.cpp
  • rts/Sim/MoveTypes/GroundMoveType.cpp
  • rts/Sim/MoveTypes/HoverAirMoveType.cpp
  • rts/Sim/MoveTypes/MoveDefHandler.h
  • rts/Sim/MoveTypes/MoveMath/MoveMath.cpp
  • rts/Sim/MoveTypes/MoveMath/MoveMath.h
  • rts/Sim/MoveTypes/MoveType.h
  • rts/Sim/Objects/SolidObject.cpp
  • rts/Sim/Objects/SolidObject.h
  • rts/Sim/Path/HAPFS/IPathFinder.cpp
  • rts/Sim/Path/HAPFS/PathManager.cpp
  • rts/Sim/Path/HAPFS/PathManager.h
  • rts/Sim/Path/QTPFS/Components/RemoveDeadPaths.h
  • rts/Sim/Path/QTPFS/Components/SyncUpdatedPaths.h
  • rts/Sim/Path/QTPFS/Node.cpp
  • rts/Sim/Path/QTPFS/Node.h
  • rts/Sim/Path/QTPFS/NodeLayer.cpp
  • rts/Sim/Path/QTPFS/NodeLayer.h
  • rts/Sim/Path/QTPFS/Path.h
  • rts/Sim/Path/QTPFS/PathDefines.h
  • rts/Sim/Path/QTPFS/PathManager.cpp
  • rts/Sim/Path/QTPFS/PathManager.h
  • rts/Sim/Path/QTPFS/PathSearch.cpp
  • rts/Sim/Path/QTPFS/PathSearch.h
  • rts/Sim/Path/QTPFS/PathThreads.h
  • rts/Sim/Path/QTPFS/Systems/RemoveDeadPathsSystem.cpp
  • rts/Sim/Path/QTPFS/Systems/SyncUpdatedPathsSystem.cpp
  • rts/Sim/Path/QTPFS/Systems/SyncUpdatedPathsSystem.h
  • rts/Sim/Path/QTPFS/Utils/DestroyEntityUtils.h
  • rts/Sim/Path/QTPFS/Utils/PathSpeedModInfoSystemUtils.h
  • rts/Sim/Path/QTPFS/Utils/SyncUpdatedPathsSystemUtils.h
  • rts/Sim/Projectiles/ExpGenSpawnable.cpp
  • rts/Sim/Projectiles/ExpGenSpawnable.h
  • rts/Sim/Projectiles/Projectile.cpp
  • rts/Sim/Projectiles/Projectile.h
  • rts/Sim/Units/CommandAI/BuilderCaches.cpp
  • rts/Sim/Units/Scripts/CobDefines.h
  • rts/Sim/Units/Scripts/CobThread.h
  • rts/Sim/Units/Scripts/UnitScript.cpp
  • rts/Sim/Units/Unit.cpp
  • rts/Sim/Units/Unit.h
  • rts/Sim/Units/UnitDef.cpp
  • rts/Sim/Units/UnitDef.h
  • rts/Sim/Units/UnitTypes/Builder.cpp
  • rts/Sim/Units/UnitTypes/Factory.cpp
  • rts/Sim/Weapons/MissileLauncher.cpp
  • rts/Sim/Weapons/PlasmaRepulser.cpp
  • rts/Sim/Weapons/Weapon.cpp
  • rts/Sim/Weapons/WeaponDef.cpp
  • rts/Sim/Weapons/WeaponDef.h
  • rts/System/CMakeLists.txt
  • rts/System/ChunkedArray.hpp
  • rts/System/CompactVector.h
  • rts/System/ContainerUtil.h
  • rts/System/EventClient.cpp
  • rts/System/EventClient.h
  • rts/System/EventHandler.cpp
  • rts/System/EventHandler.h
  • rts/System/Events.def
  • rts/System/FastMath.h
  • rts/System/FileSystem/ArchiveLoader.cpp
  • rts/System/FileSystem/ArchiveScanner.cpp
  • rts/System/FileSystem/Archives/CMakeLists.txt
  • rts/System/FileSystem/Archives/ZipArchive.cpp
  • rts/System/FileSystem/FileSystem.cpp
  • rts/System/HashSpec.h
  • rts/System/Log/TracySink.cpp
  • rts/System/LogOutput.cpp
  • rts/System/Matrix44f.cpp
  • rts/System/Matrix44f.h
  • rts/System/MemoryOverride.cpp
  • rts/System/MemoryOverride.hpp
  • rts/System/Misc/SpringTime.h
  • rts/System/Platform/Linux/CpuTopology.cpp
  • rts/System/Platform/Linux/CrashHandler.cpp
  • rts/System/Platform/Threading.cpp
  • rts/System/Platform/Win/CpuTopology.cpp
  • rts/System/Sound/CMakeLists.txt
  • rts/System/Sound/SoundUtils.cpp
  • rts/System/Sound/SoundUtils.h
  • rts/System/SpringApp.cpp
  • rts/System/SpringHashMap.natvis
  • rts/System/SpringHashSet.natvis
  • rts/System/SpringMath.inl
  • rts/System/SpringMem.cpp
  • rts/System/SpringMem.h
  • rts/System/Sync/DumpState.cpp
  • rts/System/Sync/FPUCheck.cpp
  • rts/System/Sync/SyncChecker.h
  • rts/System/Sync/SyncedPrimitiveBase.h
  • rts/System/Threading/SpringThreading.h
  • rts/System/Threading/ThreadPool.cpp
  • rts/System/Threading/ThreadPool.h
  • rts/System/TimeUtil.cpp
  • rts/System/TraceMemory.cpp
  • rts/System/TypeToStr.h
  • rts/System/creg/creg.cpp
  • rts/System/creg/creg.h
  • rts/System/simd_compat.h
  • rts/build/cmake/TestCXXFlags.cmake
  • rts/builds/CMakeLists.txt
  • rts/builds/dedicated/CMakeLists.txt
  • rts/builds/headless/CMakeLists.txt
  • rts/builds/legacy/CMakeLists.txt
  • rts/lib/CMakeLists.txt
  • rts/lib/RmlUi
  • rts/lib/assimp/CMakeLists.txt
  • rts/lib/assimp/code/CMakeLists.txt
  • rts/lib/fmt
  • rts/lib/fmt/LICENSE.rst
  • rts/lib/fmt/VERSION
  • rts/lib/fmt/args.h

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Sound loading logic was extracted from WeaponDef into a new SoundStatics utility. WeaponDef now delegates sound parsing to SoundStatics::LoadSound. New header/source and CMake entries were added to include the SoundStatics implementation and audio sources.

Changes

Cohort / File(s) Summary
SoundStatics Utility
rts/System/Sound/SoundStatics.h, rts/System/Sound/SoundStatics.cpp
New static utility providing GetSoundFallbackKey() and LoadSound(..., depth=3). Implements a hashed soundFallbackMap, MAX_SOUND_FILES = 8, depth-limited fallback resolution, loading from LuaTable into GuiSoundSet, and debug logging.
WeaponDef update
rts/Sim/Weapons/WeaponDef.cpp
Replaced internal LoadSound implementation calls with SoundStatics::LoadSound; added include for System/Sound/SoundStatics.h; removed obsolete private LoadSound method.
Top-level CMake change
rts/CMakeLists.txt
Added ${sources_engine_Audio} to engineSources.
Sound module CMake
rts/System/Sound/CMakeLists.txt
Added SoundStatics.cpp to both no-sound and sound static library source lists.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Review SoundStatics::LoadSound logic (LuaTable handling, iteration limits, volume handling).
  • Verify soundFallbackMap correctness and hash-to-key mapping (potential missing entries).
  • Confirm recursion depth behavior and logging clarity in fallback paths.
  • Check WeaponDef call sites for parameter correctness and removed method cleanup.
  • Validate CMake additions for both sound/no-sound builds.

Poem

🐰 I hopped through headers, through code so neat,
I bundled echoes into one tidy suite,
WeaponDef whispers, "Delegate away!"
SoundStatics listens and finds the right play,
A rabbit's wiggle — sound loads come out sweet. 🎶

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'New AudioStatics class and WeaponDef improvements' accurately describes the main changes: introducing a new SoundStatics utility class (audio functionality) and refactoring WeaponDef to use it.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch audio/weapondef-soundvariations

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
rts/Sim/Weapons/WeaponDef.cpp (1)

586-587: Consider precomputing hash constants for readability.

The hash comparisons at line 587 compute hashes of string literals inline. While compilers may optimize these, precomputing them as named constants would improve code readability and make the intent clearer.

Consider this refactor:

+    static const uint32_t HASH_SOUND_HIT_WET = hashString("soundHitWet");
+    static const uint32_t HASH_SOUND_HIT_DRY = hashString("soundHitDry");
+
     uint32_t hash = hashString(soundKey.c_str());
-    bool useHitFallback = hash == hashString("soundHitWet") || hash == hashString("soundHitDry");
+    bool useHitFallback = hash == HASH_SOUND_HIT_WET || hash == HASH_SOUND_HIT_DRY;
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9c6e746 and e335c4f.

📒 Files selected for processing (1)
  • rts/Sim/Weapons/WeaponDef.cpp (1 hunks)

Comment thread rts/Sim/Weapons/WeaponDef.cpp Outdated
Comment thread rts/Sim/Weapons/WeaponDef.cpp Outdated
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Dec 17, 2025

Note

Docstrings generation - SUCCESS
Generated docstrings for this pull request at #2

coderabbitai Bot added a commit that referenced this pull request Dec 17, 2025
Docstrings generation was requested by @Majavaa.

* #1 (comment)

The following files were modified:

* `rts/Sim/Weapons/WeaponDef.cpp`
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 33e1a0b and 06b4929.

📒 Files selected for processing (3)
  • rts/Audio/AudioStatics.cpp (1 hunks)
  • rts/Audio/AudioStatics.h (1 hunks)
  • rts/Sim/Weapons/WeaponDef.cpp (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
rts/Audio/AudioStatics.h (1)
rts/Audio/AudioStatics.cpp (2)
  • ShouldUseHitFallback (10-12)
  • ShouldUseHitFallback (10-10)
rts/Sim/Weapons/WeaponDef.cpp (1)
rts/Audio/AudioStatics.cpp (2)
  • ShouldUseHitFallback (10-12)
  • ShouldUseHitFallback (10-10)
🔇 Additional comments (3)
rts/Audio/AudioStatics.cpp (1)

10-12: LGTM!

The implementation is clean and efficient. Using find with comparison to end() is the idiomatic way to check set membership in C++.

rts/Sim/Weapons/WeaponDef.cpp (2)

18-18: LGTM!

The include path is appropriate for accessing the new AudioStatics utility.


584-620: Overall refactoring looks good.

The new unified sound loading flow correctly:

  1. Uses AudioStatics::ShouldUseHitFallback to determine hit-fallback applicability
  2. Tries direct file first, returning early if found
  3. Falls back to subtable lookup with hit-fallback support
  4. Finally attempts string fallback for hit sounds

The logic on line 600 (!tbl.IsValid() && useHitFallback) is correct per the previous review discussion—the fallback table is only used when the specific table doesn't exist.

Comment thread rts/Audio/AudioStatics.cpp Outdated
Comment thread rts/System/Sound/SoundUtils.h Outdated
Comment thread rts/Sim/Weapons/WeaponDef.cpp Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
rts/Sim/Weapons/WeaponDef.cpp (1)

567-572: LGTM! Minor spacing inconsistency in function calls.

The delegation to AudioStatics::LoadSound is correct and successfully centralizes sound loading logic. Both soundHitDry and soundHitWet loading into the same hitSound GuiSoundSet is appropriate for sound variation support.

Minor: Fix spacing for consistency
 void WeaponDef::ParseWeaponSounds(const LuaTable& wdTable) {
     RECOIL_DETAILED_TRACY_ZONE;
-    AudioStatics::LoadSound(wdTable, "soundStart" , fireSound);
-    AudioStatics::LoadSound(wdTable, "soundHitDry",  hitSound);
-    AudioStatics::LoadSound(wdTable, "soundHitWet",  hitSound);
+    AudioStatics::LoadSound(wdTable, "soundStart", fireSound);
+    AudioStatics::LoadSound(wdTable, "soundHitDry", hitSound);
+    AudioStatics::LoadSound(wdTable, "soundHitWet", hitSound);
 }
rts/Audio/AudioStatics.cpp (1)

1-10: Remove unused include and fix spacing.

Line 8 includes <unordered_set> but std::unordered_set is not used anywhere in this file. Only std::unordered_map is used (for soundFallbackMap). Additionally, line 38 has a spacing issue.

🔎 Apply these diffs:

Remove unused include:

 #include "System/Log/ILog.h"
-#include <unordered_set>
 #include <string>
 #include <cstdint>

Fix spacing at line 38:

-    std::string fallbackKey= AudioStatics::GetSoundFallbackKey(key);
+    std::string fallbackKey = AudioStatics::GetSoundFallbackKey(key);
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between decd5e0 and 24a0e26.

📒 Files selected for processing (3)
  • rts/Audio/AudioStatics.cpp (1 hunks)
  • rts/Audio/AudioStatics.h (1 hunks)
  • rts/Sim/Weapons/WeaponDef.cpp (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
rts/Audio/AudioStatics.h (1)
rts/Audio/AudioStatics.cpp (4)
  • GetSoundFallbackKey (22-29)
  • GetSoundFallbackKey (22-22)
  • LoadSound (31-77)
  • LoadSound (31-35)
rts/Sim/Weapons/WeaponDef.cpp (1)
rts/Audio/AudioStatics.cpp (2)
  • LoadSound (31-77)
  • LoadSound (31-35)
🪛 Cppcheck (2.18.0)
rts/Audio/AudioStatics.cpp

[error] 63-63: Using iterator to local container 'v' that may be invalid.

(invalidContainer)

🔇 Additional comments (1)
rts/Audio/AudioStatics.cpp (1)

31-77: LGTM! Sound loading logic is well-structured.

The implementation correctly handles:

  • Direct sound file loading with volume control
  • Multi-file table-based loading
  • Recursive fallback resolution with appropriate logging

The centralization of sound loading logic successfully addresses the issues noted in previous reviews.

Comment thread rts/Audio/AudioStatics.cpp Outdated
Comment thread rts/Audio/AudioStatics.cpp Outdated
Comment thread rts/System/Sound/SoundStatics.h Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (2)
rts/Audio/AudioStatics.cpp (2)

17-20: Add missing scope qualifier for static member definition.

The static member soundFallbackMap must be defined with the class scope qualifier AudioStatics::. The current code creates a file-scope variable instead of defining the class member, causing linker errors.

🔎 Apply this diff:
-const std::unordered_map<uint32_t, std::string> soundFallbackMap = {
+const std::unordered_map<uint32_t, std::string> AudioStatics::soundFallbackMap = {
     {hashString("soundHitWet"), "soundHit"},
     {hashString("soundHitDry"), "soundHit"}
 };

22-29: Add missing scope qualifier for static member function definition.

The static member function GetSoundFallbackKey must be defined with the class scope qualifier AudioStatics::. The current code defines a free function instead of the class member, causing linker errors at line 38 where AudioStatics::GetSoundFallbackKey is called.

🔎 Apply this diff:
-std::string GetSoundFallbackKey(const std::string& soundKey) {
+std::string AudioStatics::GetSoundFallbackKey(const std::string& soundKey) {
     uint32_t keyHash = hashString(soundKey.c_str());
     auto it = soundFallbackMap.find(keyHash);
     if (it != soundFallbackMap.end()) {
         return it->second;
     }
     return "";
 }
🧹 Nitpick comments (2)
rts/Audio/AudioStatics.cpp (2)

38-38: Fix spacing around assignment operator.

Missing space after = in variable assignment.

🔎 Apply this diff:
-    std::string fallbackKey= AudioStatics::GetSoundFallbackKey(key);
+    std::string fallbackKey = AudioStatics::GetSoundFallbackKey(key);

54-63: Move success log after sound file is added.

Line 60 logs "Successfully loaded sound file" before the file is actually added to the sound set at line 61. This is misleading—the log should either be moved after line 61 or reworded to indicate intent rather than completion.

🔎 Apply this diff:
         for (int i = 1; i <= MAX_SOUND_FILES; i++) {
             soundFile = soundTable.GetString(i, "");
 
             if (soundFile.empty())
                 break;
 
-            LOG_L(L_DEBUG, "[AudioStatics::%s] Successfully loaded sound file: %s with volume: %f", __func__, soundFile.c_str(), volume);
             CommonDefHandler::AddSoundSetData(soundSet, soundFile, volume);
+            LOG_L(L_DEBUG, "[AudioStatics::%s] Successfully loaded sound file: %s with volume: %f", __func__, soundFile.c_str(), volume);
             success = true;
         }
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 24a0e26 and fc8918e.

📒 Files selected for processing (1)
  • rts/Audio/AudioStatics.cpp (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
rts/Audio/AudioStatics.cpp (1)
rts/Game/UnsyncedGameCommands.cpp (1)
  • LOG_L (1219-1222)
🪛 Cppcheck (2.18.0)
rts/Audio/AudioStatics.cpp

[error] 63-63: Using iterator to local container 'v' that may be invalid.

(invalidContainer)

Comment thread rts/Audio/AudioStatics.cpp Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
rts/Audio/AudioStatics.h (1)

4-7: Add missing headers and remove unused include.

Line 11 declares std::unordered_map<uint32_t, std::string> but <unordered_map> and <string> are not included. Line 5 includes <lualib.h> which is not used in this header.

🔎 Apply this diff to fix the includes
 #ifndef AUDIOSTATICS_H
 #define AUDIOSTATICS_H
 
 #include <cstdint>
-#include <lualib.h>
+#include <string>
+#include <unordered_map>
 #include "Lua/LuaParser.h"
 #include "Sim/Misc/GuiSoundSet.h"
🧹 Nitpick comments (4)
rts/Audio/AudioStatics.cpp (4)

8-8: Remove unused <unordered_set> header.

The <unordered_set> header is included but std::unordered_set is not used anywhere in this implementation. The recursion guard was implemented using the depth parameter instead.

🔎 Proposed fix
 #include "Sim/Misc/GuiSoundSet.h"
 #include "System/Log/ILog.h"
-#include <unordered_set>
 #include <string>
 #include <cstdint>

39-39: Minor style issue: missing space after assignment operator.

Line 39 has fallbackKey= instead of fallbackKey = .

🔎 Proposed fix
-    std::string fallbackKey= GetSoundFallbackKey(key);
+    std::string fallbackKey = GetSoundFallbackKey(key);

46-46: Consider using L_DEBUG for less verbose logging.

The successful load messages (lines 46, 61) and fallback attempts (lines 72, 79, 84) log at L_INFO level, which may be too verbose for production. Consider using L_DEBUG for routine sound loading operations and reserve L_INFO for more significant events.

Also applies to: 61-61, 72-72, 79-79, 84-84


15-15: Consider making MAX_SOUND_FILES constexpr.

The constant could be constexpr instead of static const int for modern C++ style, or could be moved to the class as a private member if preferred.

🔎 Possible alternatives
-static const int MAX_SOUND_FILES = 8;
+static constexpr int MAX_SOUND_FILES = 8;

Or as a class member in AudioStatics.h:

class AudioStatics {
    private:
        static constexpr int MAX_SOUND_FILES = 8;
        // ...
};
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fc8918e and f48f1fa.

📒 Files selected for processing (4)
  • rts/Audio/AudioStatics.cpp (1 hunks)
  • rts/Audio/AudioStatics.h (1 hunks)
  • rts/Audio/CMakeLists.txt (1 hunks)
  • rts/CMakeLists.txt (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
rts/Audio/AudioStatics.h (1)
rts/Audio/AudioStatics.cpp (4)
  • GetSoundFallbackKey (22-29)
  • GetSoundFallbackKey (22-22)
  • LoadSound (31-86)
  • LoadSound (31-36)
🪛 Cppcheck (2.18.0)
rts/Audio/AudioStatics.cpp

[error] 63-63: Using iterator to local container 'v' that may be invalid.

(invalidContainer)


[error] 85-85: Using iterator to local container 'v' that may be invalid.

(invalidContainer)

🔇 Additional comments (6)
rts/Audio/CMakeLists.txt (1)

1-4: LGTM!

The CMake configuration correctly exposes the Audio module sources to the parent scope for integration into the engine build.

rts/CMakeLists.txt (2)

131-131: LGTM!

The Audio subdirectory is properly added to the build system.


148-148: LGTM!

The Audio module sources are correctly integrated into the engine build.

rts/Audio/AudioStatics.h (1)

9-20: LGTM!

The class structure is well-designed with appropriate static utility methods and a private fallback mapping.

rts/Audio/AudioStatics.cpp (2)

17-20: LGTM!

The fallback map is correctly defined with the class scope qualifier and provides appropriate sound fallback mappings.


22-29: LGTM!

The fallback key lookup is correctly implemented with proper scope qualification.

Comment thread rts/Audio/AudioStatics.cpp Outdated
@Majavaa Majavaa changed the title Code rabbit test New AudioStatics class and WeaponDef improvements Dec 19, 2025
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
rts/Audio/AudioStatics.cpp (1)

61-62: Log ordering is inconsistent with the pattern used elsewhere.

The log on line 61 claims "Successfully loaded" before AddSoundSetData executes on line 62. This is inconsistent with lines 45-46 where the operation precedes the log. Consider swapping the order for consistency.

🔎 Proposed fix
-            LOG_L(L_INFO, "[AudioStatics::%s] Successfully loaded sound file: %s with volume: %f", __func__, soundFile.c_str(), volume);
             CommonDefHandler::AddSoundSetData(soundSet, soundFile, volume);
+            LOG_L(L_INFO, "[AudioStatics::%s] Successfully loaded sound file: %s with volume: %f", __func__, soundFile.c_str(), volume);
             success = true;
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f48f1fa and 498fd2b.

📒 Files selected for processing (1)
  • rts/Audio/AudioStatics.cpp (1 hunks)
🧰 Additional context used
🪛 Cppcheck (2.18.0)
rts/Audio/AudioStatics.cpp

[error] 63-63: Using iterator to local container 'v' that may be invalid.

(invalidContainer)


[error] 85-85: Using iterator to local container 'v' that may be invalid.

(invalidContainer)

🔇 Additional comments (4)
rts/Audio/AudioStatics.cpp (4)

1-15: LGTM!

The includes are properly organized with all necessary headers, including <unordered_set> which was previously flagged. The log section and constant definitions are appropriate.


17-20: LGTM!

The static map is now correctly defined with the AudioStatics:: scope qualifier. The compile-time hash-based lookup for fallback keys is an efficient approach.


22-29: LGTM!

The function is correctly scoped and provides efficient hash-based lookup for fallback keys.


71-85: LGTM!

The depth-limiting logic is now correctly implemented: checking depth == 0 before decrementing (avoiding the unsigned underflow issue), and properly passing the decremented depth to the recursive call.

Regarding the static analysis hint about "iterator to local container 'v'" at lines 63 and 85: this is a false positive—there is no container v in this file.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
rts/Audio/AudioStatics.cpp (2)

36-36: Optional: Consider lazy-loading the fallback key.

The fallback key is computed at line 36 but only used starting at line 68 if both direct string and subtable loading fail. Moving the computation to just before line 68 would avoid the hash lookup in the common case where sound loading succeeds.

🔎 Proposed optimization
     RECOIL_DETAILED_TRACY_ZONE;
 
-    std::string fallbackKey = GetSoundFallbackKey(key);
-
     float volume = table.GetFloat(key + "Volume", 1.0f);
 
     // ... existing direct string and subtable logic ...
     
+    std::string fallbackKey = GetSoundFallbackKey(key);
+
     if (fallbackKey.empty()) {
         LOG_L(L_INFO, "[AudioStatics::%s] Sound file not found: %s, there is no fallback to try, not adding sound-set", __func__, key.c_str());
         return false;
     }

43-43: Optional: Consider adjusting log levels for production.

Currently, all log messages use L_INFO, which provides good visibility during development. Once the feature is stable, you might consider:

  • L_DEBUG for successful loads (lines 43, 59) to reduce verbosity
  • L_WARNING for fallback attempts and failures (lines 69, 74, 80) to highlight unexpected conditions

The current logging is fine for initial deployment and debugging.

Also applies to: 59-59, 69-69, 74-74, 80-80

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 498fd2b and 5d1b320.

📒 Files selected for processing (2)
  • rts/Audio/AudioStatics.cpp (1 hunks)
  • rts/Audio/AudioStatics.h (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
rts/Audio/AudioStatics.h (1)
rts/Audio/AudioStatics.cpp (4)
  • GetSoundFallbackKey (19-26)
  • GetSoundFallbackKey (19-19)
  • LoadSound (28-82)
  • LoadSound (28-33)
🪛 Cppcheck (2.18.0)
rts/Audio/AudioStatics.cpp

[error] 63-63: Using iterator to local container 'v' that may be invalid.

(invalidContainer)

🔇 Additional comments (6)
rts/Audio/AudioStatics.h (1)

1-25: LGTM! Header is well-structured.

The header file is clean and properly organized:

  • Include guard correctly implemented
  • All necessary headers included without unused dependencies
  • Class interface clearly defined with appropriate access specifiers
  • Static members and methods properly declared

All previous concerns have been addressed.

rts/Audio/AudioStatics.cpp (5)

1-12: LGTM! Includes and logging setup are correct.

All necessary headers are included, and the LOG_SECTION_CURRENT macro appropriately categorizes log messages under "Audio".


14-17: LGTM! Fallback map properly defined.

The static member is correctly defined with the AudioStatics:: scope qualifier, and the fallback mappings are sensible (both wet and dry variants fall back to the generic hit sound).


19-26: LGTM! Fallback key lookup is correctly implemented.

The function properly hashes the key, performs the map lookup, and returns either the fallback key or an empty string. The scope qualifier is correct.


28-82: Depth limiting logic is now correct.

The recursion guard has been properly fixed:

  • Depth is checked against 0 before decrementing (line 73)
  • Decremented depth is correctly passed to the recursive call (line 81)
  • This prevents infinite recursion even with cyclic or long fallback chains

The overall loading logic is sound: attempts direct string, then subtable array, then falls back with depth limit.


63-63: Static analysis false positive - no issue here.

The static analysis tool reports an invalid iterator issue at this line, but line 63 is simply if (success) { with no iterator or container involved. This is a false positive and can be safely ignored.

lhog and others added 6 commits December 21, 2025 14:16
…son#2692)

* Speculatively handle SDL_WINDOWEVENT_DISPLAY_CHANGED.
Also add logging to TextureRenderAtlas finalization calls to track the issue better.
This is regards to beyond-all-reason#2661
* Replace SDL_WINDOWEVENT_DISPLAY_CHANGED missing in Linux headers with its surrogate
* Unlikely to fix beyond-all-reason#2661 but might give additional clues
* add rmlui resource tracking
---------

Co-authored-by: sprunk <spr.ng@o2.pl>
* some datamodel fixes
* length functions
* combine pairs function creation
* allow for array set
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
rts/System/Sound/SoundStatics.h (1)

1-2: Header guard name doesn't match class name.

The header guard uses AUDIOSTATICS_H but the class is named SoundStatics. Consider updating the guard to SOUNDSTATICS_H for consistency, or if "AudioStatics" was the intended name, the class should be renamed.

🔎 Proposed fix
-#ifndef AUDIOSTATICS_H
-#define AUDIOSTATICS_H
+#ifndef SOUNDSTATICS_H
+#define SOUNDSTATICS_H

And at the end of the file:

-#endif
+#endif // SOUNDSTATICS_H
rts/System/Sound/SoundStatics.cpp (2)

1-10: Remove redundant include.

Line 8 includes <string>, but this is already included in SoundStatics.h (line 5). While harmless, removing redundant includes improves clarity.

🔎 Proposed fix
 #include "SoundStatics.h"
 #include "System/Misc/TracyDefs.h"
 #include "System/StringHash.h"
 #include "Lua/LuaParser.h"
 #include "Sim/Misc/CommonDefHandler.h"
 #include "Sim/Misc/GuiSoundSet.h"
 #include "System/Log/ILog.h"
-#include <string>
 #include <cstdint>

36-36: Volume is applied uniformly to all sound variations.

The volume is read once and applied to all sound files in the array (lines 40, 56). This means all sound variations in a table share the same volume setting. If per-file volume control is needed in the future, consider reading individual volumes like soundTable.GetFloat(i, 1.0f) in the loop at line 50.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 18953fb and 42cb3dd.

📒 Files selected for processing (5)
  • rts/CMakeLists.txt
  • rts/Sim/Weapons/WeaponDef.cpp
  • rts/System/Sound/CMakeLists.txt
  • rts/System/Sound/SoundStatics.cpp
  • rts/System/Sound/SoundStatics.h
🚧 Files skipped from review as they are similar to previous changes (2)
  • rts/Sim/Weapons/WeaponDef.cpp
  • rts/CMakeLists.txt
🧰 Additional context used
🪛 Cppcheck (2.18.0)
rts/System/Sound/SoundStatics.cpp

[error] 63-63: Using iterator to local container 'v' that may be invalid.

(invalidContainer)

🔇 Additional comments (6)
rts/System/Sound/CMakeLists.txt (2)

11-11: LGTM!

The addition of SoundStatics.cpp to the no-sound library is correct and properly indented.


46-46: LGTM!

The addition of SoundStatics.cpp to the real-sound library is correct and consistent with the no-sound configuration.

rts/System/Sound/SoundStatics.h (1)

10-22: LGTM!

The class structure is well-designed with appropriate encapsulation. The static utility pattern is suitable for this centralized sound loading functionality, and the depth-limited recursion parameter provides protection against infinite loops in the fallback mechanism.

rts/System/Sound/SoundStatics.cpp (3)

14-26: LGTM!

The fallback map initialization and lookup logic are straightforward and correct. The use of hashed keys is appropriate for O(1) lookups.


50-59: LGTM!

The loop correctly handles Lua's 1-based indexing and respects the MAX_SOUND_FILES limit. The early break on empty strings is appropriate and prevents unnecessary iterations.


66-82: LGTM! Fallback logic is correct and well-protected.

The depth-limited recursion correctly prevents infinite loops:

  • Default depth of 3 allows up to 3 fallback attempts
  • Depth is checked before decrementing (line 73)
  • Clear debug logging at each decision point

Note: The static analysis hint about line 63 is a false positive—there's no iterator variable 'v' in this code.

lhog and others added 11 commits December 24, 2025 01:38
With this change, the docker build image becomes pinned to the source commit. Checking out older engine commits will use older build image to compile engine.

This allows for making backwards incompatible changes to the docker build images, libraries, etc without breaking building of older commits. It also allows updating the build image on master without touching release branch.

Also fixes beyond-all-reason#2693
Ensures that the newly build docker images can correctly compile
the engine, and we won't just get CI failure on master.
lhog and others added 29 commits March 27, 2026 02:37
Sort icon names before adding to atlas so insertion order is consistent
across runs. Replace non-deterministic GL texture IDs with stable
insertion-order indices for UniqueSubTexture naming. Fix stableIdx
assignment to be per-file at first insertion time.

Also sort icon rendering to use deterministic ProjectileDrawer iteration.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Allow specifying output format (e.g. "dumpatlas proj tga") instead of
hardcoded .png. The last argument is treated as a file extension if it
doesn't match a known atlas name. Also fixes "decal" typo in icons log message.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Edge-pixel padding: expand each icon's destination rect into the allocator
padding zone during atlas FBO baking. The shader clamps source UVs via a
srcClamp uniform so out-of-range samples repeat the edge pixel. This
prevents bilinear bleed from neighbouring icons at small icon sizes.

Fix sliding artifact: at mip levels > 0, the old code reused level-0
normalised coordinates, placing quad vertices at fractional pixel positions
for odd-positioned atlas entries (e.g. 9.75px at level 2). The triangle
rasteriser then handled the two halves of the quad differently. Two fixes:

1. Pixel-snapped mip-level rendering: compute destination rect in integer
   mip-level pixels using floor/ceil, then convert to NDC. Quad vertices
   now land on exact pixel boundaries at every mip level.

2. Use GL_LINEAR for source texture sampling in the FBO baking loop. For
   odd-positioned entries the source UV at interior pixels lands exactly
   halfway between two LOD-N source texels. GL_NEAREST is undefined there;
   floating-point barycentric differences between the two triangles cause
   them to pick different texels, baking a seam. GL_LINEAR gives smooth
   blending instead, which both triangles agree on.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fix card shortcode: use self-closing {{< card >}} instead of {{% card %}}...{{% /card %}} which broke Hugo build since the hextra theme's card shortcode does not support .Inner
- Replace ./recoil with ./spring and add note that spring is a temporary binary name
- Add git clone examples for RecoilExampleMod and VroomRTS with filesystem tree
- Clarify that .sdd is just a directory named with .sdd extension, no special format required
The fallback should only apply to sounds defs for hitting dry land or
wet water, where they should instead use the generic soundHit. Also
fixed the table case not having a fallback
L_INFO doesn't output in the builds, hopefully this is not only on my
end
The previous location and naming was bad, sound is already being used as
the keyword.
- soundHitDryVolume/soundHitWetVolume no longer incorrectly fall back to
  soundHitVolume for direct hits; soundHitVolume is now only used on the
  explicit soundHit fallback path, matching WEAPONDUMMYTAG declarations
- Replace recursive LoadSound+depth with a flat helper LoadSoundFromTable
  and an explicit fallback if-block; the fallback chain (soundHitDry/Wet
  -> soundHit) had only one hop so the generality was unwarranted
- Remove arbitrary MAX_SOUND_FILES=8 cap; loop breaks on empty string
  matching CUnitDefHandler::LoadSounds behaviour
- Remove undefined ${sources_engine_Audio} from rts/CMakeLists.txt
- Fix 4-space indentation to tabs throughout SoundUtils.cpp/h

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@lhog lhog force-pushed the audio/weapondef-soundvariations branch from 7d39901 to 0bf65d6 Compare April 4, 2026 00:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.