Skip to content

Commit

Permalink
Implement bomb defuse sound visualization (#4191)
Browse files Browse the repository at this point in the history
  • Loading branch information
danielkrupinski authored Nov 23, 2023
1 parent fb4611c commit cd648f4
Show file tree
Hide file tree
Showing 13 changed files with 199 additions and 2 deletions.
1 change: 1 addition & 0 deletions Source/CS2/Constants/SoundNames.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@ constexpr std::string_view kBombSoundsPath = "sounds/weapons/c4/";

constexpr std::string_view kPlayerSuitSoundPrefix = "suit";
constexpr std::string_view kBombBeepSoundsPrefix = "c4_beep";
constexpr std::string_view kBombDefuseStartSoundName = "c4_disarmstart.vsnd";

}
6 changes: 6 additions & 0 deletions Source/FeatureHelpers/FeatureHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,17 @@
#include "Hud/DefusingAlertHelpers.h"
#include "Hud/KillfeedPreserverHelpers.h"
#include "Sound/BombBeepVisualizerHelpers.h"
#include "Sound/BombDefuseVisualizerHelpers.h"
#include "Sound/BombPlantVisualizerHelpers.h"
#include "Sound/FootstepVisualizerHelpers.h"
#include "WorldToClipSpaceConverter.h"

struct FeatureHelpers {
[[nodiscard]] BombDefuseVisualizerHelpers getBombDefuseVisualizerHelpers() noexcept
{
return BombDefuseVisualizerHelpers{ HudInWorldPanelFactory{hudInWorldPanelContainer, hudProvider}, globalVarsProvider, transformFactory, worldtoClipSpaceConverter };
}

[[nodiscard]] BombBeepVisualizerHelpers getBombBeepVisualizerHelpers() noexcept
{
return BombBeepVisualizerHelpers{ HudInWorldPanelFactory{hudInWorldPanelContainer, hudProvider}, globalVarsProvider, transformFactory, worldtoClipSpaceConverter };
Expand Down
3 changes: 2 additions & 1 deletion Source/FeatureHelpers/HudInWorldPanelZOrder.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
enum class HudInWorldPanelZOrder {
Footstep,
BombBeep,
BombPlant
BombPlant,
BombDefuse
};
31 changes: 31 additions & 0 deletions Source/FeatureHelpers/Sound/BombDefuseSound.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#pragma once

#include <algorithm>
#include <cassert>
#include <string_view>

#include <CS2/Constants/SoundNames.h>

struct BombDefuseSound {
static constexpr auto kFadeAwayStart = 2.0f;
static constexpr auto kFadeAwayDuration = 1.0f;

[[nodiscard]] static constexpr float getScale(float clipSpaceZ) noexcept
{
return (std::max)(1.0f - clipSpaceZ / 1000.0f, 0.4f);
}

[[nodiscard]] static constexpr float getOpacity(float timeAlive) noexcept
{
if (timeAlive >= kFadeAwayStart) {
return 1.0f - (std::min)((timeAlive - kFadeAwayStart) / kFadeAwayDuration, 1.0f);
} else {
return 1.0f;
}
}

[[nodiscard]] static constexpr bool isSound(std::string_view soundName) noexcept
{
return soundName.starts_with(cs2::kBombSoundsPath) && std::string_view{ soundName.data() + cs2::kBombSoundsPath.length(), soundName.length() - cs2::kBombSoundsPath.length() }.starts_with(cs2::kBombDefuseStartSoundName);
}
};
13 changes: 13 additions & 0 deletions Source/FeatureHelpers/Sound/BombDefuseVisualizerHelpers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#pragma once

#include <FeatureHelpers/GlobalVarsProvider.h>
#include <FeatureHelpers/HudInWorldPanelFactory.h>
#include <FeatureHelpers/WorldToClipSpaceConverter.h>
#include <Helpers/PanoramaTransformFactory.h>

struct BombDefuseVisualizerHelpers {
HudInWorldPanelFactory hudInWorldPanelFactory;
GlobalVarsProvider globalVarsProvider;
PanoramaTransformFactory transformFactory;
WorldToClipSpaceConverter worldtoClipSpaceConverter;
};
3 changes: 2 additions & 1 deletion Source/FeatureHelpers/Sound/SoundWatcher.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
#pragma once

#include "BombBeepSound.h"
#include "BombDefuseSound.h"
#include "BombPlantSound.h"
#include "FootstepSound.h"
#include "SoundWatcherImpl.h"

using SoundWatcher = SoundWatcherImpl<FootstepSound, BombPlantSound, BombBeepSound>;
using SoundWatcher = SoundWatcherImpl<FootstepSound, BombPlantSound, BombBeepSound, BombDefuseSound>;
124 changes: 124 additions & 0 deletions Source/Features/Sound/BombDefuseVisualizer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
#pragma once

#include <CS2/Classes/Panorama.h>
#include <FeatureHelpers/HudInWorldPanels.h>
#include <FeatureHelpers/HudInWorldPanelFactory.h>
#include <FeatureHelpers/Sound/BombDefuseSound.h>
#include <FeatureHelpers/Sound/BombDefuseVisualizerHelpers.h>
#include <FeatureHelpers/Sound/SoundWatcher.h>
#include <FeatureHelpers/TogglableFeature.h>
#include <GameClasses/PanoramaUiEngine.h>
#include <Hooks/ViewRenderHook.h>

struct BombDefusePanels {
[[nodiscard]] static cs2::CPanel2D* createContainerPanel(const HudInWorldPanelFactory& inWorldFactory) noexcept
{
return inWorldFactory.createPanel("BombDefuseContainer", HudInWorldPanelZOrder::BombDefuse);
}

static void createContentPanels(cs2::CUIPanel& containerPanel) noexcept
{
for (std::size_t i = 0; i < kMaxNumberOfPanels; ++i) {
PanoramaUiEngine::runScript(&containerPanel,
R"(
(function() {
var bombDefusePanel = $.CreatePanel('Panel', $.GetContextPanel().FindChildInLayoutFile("BombDefuseContainer"), '', {
style: 'width: 100px; height: 100px; x: -50px; y: -50px;'
});
$.CreatePanel('Image', bombDefusePanel, '', {
src: "s2r://panorama/images/icons/equipment/defuser.vsvg",
style: "horizontal-align: center; vertical-align: center; img-shadow: 0px 0px 1px 3 #000000;",
textureheight: "40"
});
})();)", "", 0);
}
}

static constexpr auto kMaxNumberOfPanels = 5;
};

class BombDefuseVisualizer : public TogglableFeature<BombDefuseVisualizer> {
public:
explicit BombDefuseVisualizer(ViewRenderHook& viewRenderHook, SoundWatcher& soundWatcher) noexcept
: viewRenderHook{ viewRenderHook }
, soundWatcher{ soundWatcher }
{
}

void run(const BombDefuseVisualizerHelpers& params) noexcept
{
if (!isEnabled())
return;

if (!params.globalVarsProvider || !params.globalVarsProvider.getGlobalVars())
return;

if (!params.worldtoClipSpaceConverter)
return;

panels.createPanels(params.hudInWorldPanelFactory);

std::size_t currentIndex = 0;
std::as_const(soundWatcher).getSoundsOfType<BombDefuseSound>().forEach([this, &currentIndex, params](const PlayedSound& sound) {
const auto soundInClipSpace = params.worldtoClipSpaceConverter.toClipSpace(sound.origin);
if (!soundInClipSpace.onScreen())
return;

const auto opacity = BombDefuseSound::getOpacity(sound.getTimeAlive(params.globalVarsProvider.getGlobalVars()->curtime));
if (opacity <= 0.0f)
return;

const auto panel = panels.getPanel(currentIndex);
if (!panel)
return;

const auto style = panel.getStyle();
if (!style)
return;

style.setOpacity(opacity);
style.setZIndex(-soundInClipSpace.z);

const auto deviceCoordinates = soundInClipSpace.toNormalizedDeviceCoordinates();
cs2::CTransform3D* transformations[]{ params.transformFactory.create<cs2::CTransformScale3D>(
BombDefuseSound::getScale(soundInClipSpace.z), BombDefuseSound::getScale(soundInClipSpace.z), 1.0f
), params.transformFactory.create<cs2::CTransformTranslate3D>(
deviceCoordinates.getX(),
deviceCoordinates.getY(),
cs2::CUILength{ 0.0f, cs2::CUILength::k_EUILengthLength }
) };

cs2::CUtlVector<cs2::CTransform3D*> dummyVector;
dummyVector.allocationCount = 2;
dummyVector.memory = transformations;
dummyVector.growSize = 0;
dummyVector.size = 2;

style.setTransform3D(dummyVector);
++currentIndex;
});

panels.hidePanels(currentIndex);
}

private:
friend TogglableFeature;

void onEnable() noexcept
{
viewRenderHook.incrementReferenceCount();
soundWatcher.startWatching<BombDefuseSound>();
}

void onDisable() noexcept
{
viewRenderHook.decrementReferenceCount();
soundWatcher.stopWatching<BombDefuseSound>();
panels.hidePanels(0);
}

HudInWorldPanels<BombDefusePanels> panels;
ViewRenderHook& viewRenderHook;
SoundWatcher& soundWatcher;
};
3 changes: 3 additions & 0 deletions Source/Features/Sound/SoundFeatures.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include "BombBeepVisualizer.h"
#include "BombDefuseVisualizer.h"
#include "BombPlantVisualizer.h"
#include "FootstepVisualizer.h"
#include <Helpers/HudProvider.h>
Expand All @@ -11,10 +12,12 @@ struct SoundFeatures {
: footstepVisualizer{ viewRenderHook, soundWatcher }
, bombPlantVisualizer{ viewRenderHook, soundWatcher }
, bombBeepVisualizer{ viewRenderHook, soundWatcher }
, bombDefuseVisualizer{ viewRenderHook, soundWatcher }
{
}

FootstepVisualizer footstepVisualizer;
BombPlantVisualizer bombPlantVisualizer;
BombBeepVisualizer bombBeepVisualizer;
BombDefuseVisualizer bombDefuseVisualizer;
};
1 change: 1 addition & 0 deletions Source/GlobalContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ struct GlobalContext {
features->soundFeatures.footstepVisualizer.run(featureHelpers->getFootstepVisualizerHelpers());
features->soundFeatures.bombPlantVisualizer.run(featureHelpers->getBombPlantVisualizerHelpers());
features->soundFeatures.bombBeepVisualizer.run(featureHelpers->getBombBeepVisualizerHelpers());
features->soundFeatures.bombDefuseVisualizer.run(featureHelpers->getBombDefuseVisualizerHelpers());
}

private:
Expand Down
3 changes: 3 additions & 0 deletions Source/Osiris.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@
<ClInclude Include="FeatureHelpers\NormalizedDeviceCoordinates.h" />
<ClInclude Include="FeatureHelpers\Sound\BombBeepSound.h" />
<ClInclude Include="FeatureHelpers\Sound\BombBeepVisualizerHelpers.h" />
<ClInclude Include="FeatureHelpers\Sound\BombDefuseSound.h" />
<ClInclude Include="FeatureHelpers\Sound\BombDefuseVisualizerHelpers.h" />
<ClInclude Include="FeatureHelpers\Sound\BombPlantSound.h" />
<ClInclude Include="FeatureHelpers\Sound\BombPlantVisualizerHelpers.h" />
<ClInclude Include="FeatureHelpers\Sound\FootstepSound.h" />
Expand All @@ -63,6 +65,7 @@
<ClInclude Include="Features\Hud\HudFeatures.h" />
<ClInclude Include="Features\Hud\KillfeedPreserver.h" />
<ClInclude Include="Features\Sound\BombBeepVisualizer.h" />
<ClInclude Include="Features\Sound\BombDefuseVisualizer.h" />
<ClInclude Include="Features\Sound\BombPlantVisualizer.h" />
<ClInclude Include="Features\Sound\FootstepVisualizer.h" />
<ClInclude Include="Features\Sound\SoundFeatures.h" />
Expand Down
9 changes: 9 additions & 0 deletions Source/Osiris.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,15 @@
<ClInclude Include="FeatureHelpers\HudInWorldPanels.h">
<Filter>FeatureHelpers</Filter>
</ClInclude>
<ClInclude Include="FeatureHelpers\Sound\BombDefuseSound.h">
<Filter>FeatureHelpers\Sound</Filter>
</ClInclude>
<ClInclude Include="FeatureHelpers\Sound\BombDefuseVisualizerHelpers.h">
<Filter>FeatureHelpers\Sound</Filter>
</ClInclude>
<ClInclude Include="Features\Sound\BombDefuseVisualizer.h">
<Filter>Features\Sound</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="UI\Panorama\CreateGUI.js">
Expand Down
2 changes: 2 additions & 0 deletions Source/UI/Panorama/CreateGUI.js
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@ $.Osiris = (function () {
createYesNoDropDown(visualization, "Visualize Bomb Plant", 'sound', 'visualize_bomb_plant');
$.CreatePanel('Panel', visualization, '', { class: "horizontal-separator" });
createYesNoDropDown(visualization, "Visualize Bomb Beep", 'sound', 'visualize_bomb_beep');
$.CreatePanel('Panel', visualization, '', { class: "horizontal-separator" });
createYesNoDropDown(visualization, "Visualize Bomb Defuse", 'sound', 'visualize_bomb_defuse');

$.Osiris.navigateToTab('hud');
})();
Expand Down
2 changes: 2 additions & 0 deletions Source/UI/Panorama/SetCommandHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ struct SetCommandHandler {
handleTogglableFeature(features.soundFeatures.bombPlantVisualizer);
} else if (feature == "visualize_bomb_beep") {
handleTogglableFeature(features.soundFeatures.bombBeepVisualizer);
} else if (feature == "visualize_bomb_defuse") {
handleTogglableFeature(features.soundFeatures.bombDefuseVisualizer);
}
}

Expand Down

0 comments on commit cd648f4

Please sign in to comment.