Skip to content

Commit

Permalink
Implement showing an icon on player blinded by flashbang (#4287)
Browse files Browse the repository at this point in the history
  • Loading branch information
danielkrupinski committed May 15, 2024
1 parent 5de4d57 commit ecb9998
Show file tree
Hide file tree
Showing 13 changed files with 89 additions and 4 deletions.
1 change: 1 addition & 0 deletions Source/CS2/Classes/Entities/C_CSPlayerPawn.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ struct C_CSPlayerPawn : C_BaseEntity {
using m_bIsDefusing = bool;
using m_bIsGrabbingHostage = bool;
using m_pHostageServices = CCSPlayer_HostageServices*;
using m_flFlashBangTime = float;
};

}
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ struct PlayerStateIconToggle {
using PlayerDefuseIconToggle = PlayerStateIconToggle<DefuseIconPanel>;
using HostagePickupIconToggle = PlayerStateIconToggle<HostagePickupPanel>;
using HostageRescueIconToggle = PlayerStateIconToggle<HostageRescuePanel>;
using BlindedIconToggle = PlayerStateIconToggle<BlindedIconPanel>;

struct PlayerInformationThroughWallsToggle : private TogglableFeature<PlayerInformationThroughWallsToggle> {
PlayerInformationThroughWallsToggle(PlayerInformationThroughWallsState& state, HudInWorldPanelContainer& hudInWorldPanelContainer, ViewRenderHook& viewRenderHook, PanelConfigurator panelConfigurator, HudProvider hudProvider) noexcept
Expand Down Expand Up @@ -430,12 +431,52 @@ class PlayerInformationThroughWalls {
playerStateIconsPanel.setVisible(true);

const auto playerStateChildren = playerStateIconsPanel.children();
if (!playerStateChildren || playerStateChildren->size != 3)
if (!playerStateChildren || playerStateChildren->size != 4)
return;

PanoramaUiPanel{playerStateChildren->memory[0]}.setVisible(state.playerStateIconsToShow.has<DefuseIconPanel>() && isDefusing(playerPawn));
PanoramaUiPanel{playerStateChildren->memory[1]}.setVisible(state.playerStateIconsToShow.has<HostagePickupPanel>() && isPickingUpHostage(playerPawn));
PanoramaUiPanel{playerStateChildren->memory[2]}.setVisible(state.playerStateIconsToShow.has<HostageRescuePanel>() && isRescuingHostage(playerPawn));
updateBlindedIconPanel(PanoramaUiPanel{playerStateChildren->memory[3]}, playerPawn);
}

void updateBlindedIconPanel(PanoramaUiPanel blindedIconPanel, cs2::C_CSPlayerPawn& playerPawn) const noexcept
{
if (!state.playerStateIconsToShow.has<BlindedIconPanel>()) {
blindedIconPanel.setVisible(false);
return;
}

const auto remainingFlashBangTime = getRemainingFlashBangTime(playerPawn);
constexpr auto kFullBlindEnd{3.0f};
constexpr auto kBlindEnd{1.0f};
constexpr auto kPartiallyBlindDuration{kFullBlindEnd - kBlindEnd};
if (remainingFlashBangTime <= kBlindEnd) {
blindedIconPanel.setVisible(false);
return;
}

blindedIconPanel.setVisible(true);
const auto opacity = remainingFlashBangTime >= kFullBlindEnd ? 1.0f : (remainingFlashBangTime - kBlindEnd) / kPartiallyBlindDuration;
if (const auto style{blindedIconPanel.getStyle()}) {
const auto styler{dependencies.getDependency<PanelConfigurator>().panelStyle(*style)};
styler.setOpacity(opacity);
}
}

[[nodiscard]] float getRemainingFlashBangTime(cs2::C_CSPlayerPawn& playerPawn) const noexcept
{
if (!dependencies.requestDependency<CurTime>())
return 0.0f;

if (!dependencies.offsets().playerPawn.offsetToFlashBangEndTime)
return 0.0f;

const auto curTime = dependencies.getDependency<CurTime>();
const auto flashBangEndTime = *dependencies.offsets().playerPawn.offsetToFlashBangEndTime.of(&playerPawn).get();
if (flashBangEndTime <= curTime)
return 0.0f;
return flashBangEndTime - curTime;
}

[[nodiscard]] bool isRescuingHostage(cs2::C_CSPlayerPawn& playerPawn) const noexcept
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class PlayerInformationThroughWallsPanelFactory {
createDefuseIconPanel(panel->uiPanel);
createHostagePickupPanel(panel->uiPanel);
createHostageRescuePanel(panel->uiPanel);
createBlindedIconPanel(panel->uiPanel);
}

void createDefuseIconPanel(cs2::CUIPanel* containerPanel) const noexcept
Expand Down Expand Up @@ -89,12 +90,25 @@ class PlayerInformationThroughWallsPanelFactory {
if (const auto style{PanoramaUiPanel{imagePanel->uiPanel}.getStyle()}) {
const auto styler{panelConfigurator.panelStyle(*style)};
styler.setAlign(cs2::k_EHorizontalAlignmentUnset, cs2::k_EVerticalAlignmentCenter);
styler.setMargin(cs2::CUILength::pixels(0), cs2::CUILength::pixels(5), cs2::CUILength::pixels(0), cs2::CUILength::pixels(0));
styler.setImageShadow(shadowParams());
styler.setWashColor(color);
}
}

void createBlindedIconPanel(cs2::CUIPanel* containerPanel) const noexcept
{
const auto imagePanel = PanoramaImagePanel::create("", containerPanel);
if (!imagePanel)
return;

PanoramaImagePanel{imagePanel}.setImageSvg("s2r://panorama/images/hud/deathnotice/blind_kill.svg", 26);
if (const auto style{PanoramaUiPanel{imagePanel->uiPanel}.getStyle()}) {
const auto styler{panelConfigurator.panelStyle(*style)};
styler.setAlign(cs2::k_EHorizontalAlignmentUnset, cs2::k_EVerticalAlignmentCenter);
styler.setImageShadow(shadowParams());
}
}

void createActiveWeaponIconPanel(cs2::CUIPanel* containerPanel) const noexcept
{
const auto weaponIconPanel = PanoramaImagePanel::create("", containerPanel);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,12 @@ struct PlayerInformationThroughWallsState {
bool showPlayerHealth{true};
PlayerHealthTextColor playerHealthTextColor{PlayerHealthTextColor::HealthBased};
bool showPlayerActiveWeapon{true};
PlayerStateIconsToShow playerStateIconsToShow{PlayerStateIconsToShow{}.set<DefuseIconPanel>().set<HostagePickupPanel>().set<HostageRescuePanel>()};
PlayerStateIconsToShow playerStateIconsToShow{
PlayerStateIconsToShow{}
.set<DefuseIconPanel>()
.set<HostagePickupPanel>()
.set<HostageRescuePanel>()
.set<BlindedIconPanel>()};

cs2::PanelHandle containerPanelHandle;
DynamicArray<HudInWorldPanelIndex> panelIndices;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
struct DefuseIconPanel;
struct HostagePickupPanel;
struct HostageRescuePanel;
struct BlindedIconPanel;

using PlayerStateIconsToShow = TypeBitFlags<DefuseIconPanel, HostagePickupPanel, HostageRescuePanel>;
using PlayerStateIconsToShow = TypeBitFlags<DefuseIconPanel, HostagePickupPanel, HostageRescuePanel, BlindedIconPanel>;
5 changes: 5 additions & 0 deletions Source/Features/Visuals/VisualFeatures.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ struct VisualFeatures {
return HostageRescueIconToggle{states.playerInformationThroughWallsState.playerStateIconsToShow};
}

[[nodiscard]] BlindedIconToggle blindedIconToggle() const noexcept
{
return BlindedIconToggle{states.playerInformationThroughWallsState.playerStateIconsToShow};
}

VisualFeaturesStates& states;
FeatureHelpers& helpers;
ViewRenderHook& viewRenderHook;
Expand Down
2 changes: 2 additions & 0 deletions Source/GameClasses/Implementation/PlayerPawnImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ struct PlayerPawnImpl {
, offsetToIsDefusing{playerPawnPatterns.offsetToIsDefusing()}
, offsetToIsPickingUpHostage{playerPawnPatterns.offsetToIsPickingUpHostage()}
, offsetToHostageServices{playerPawnPatterns.offsetToHostageServices()}
, offsetToFlashBangEndTime{playerPawnPatterns.offsetToFlashBangEndTime()}
{
}

Expand All @@ -19,4 +20,5 @@ struct PlayerPawnImpl {
OffsetToIsDefusing offsetToIsDefusing;
OffsetToIsPickingUpHostage offsetToIsPickingUpHostage;
OffsetToHostageServices offsetToHostageServices;
OffsetToFlashBangEndTime offsetToFlashBangEndTime;
};
1 change: 1 addition & 0 deletions Source/GameClasses/OffsetTypes/PlayerPawnOffset.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ using OffsetToPlayerController = PlayerPawnOffset<cs2::C_CSPlayerPawn::m_hContro
using OffsetToIsDefusing = PlayerPawnOffset<cs2::C_CSPlayerPawn::m_bIsDefusing, std::int32_t>;
using OffsetToIsPickingUpHostage = PlayerPawnOffset<cs2::C_CSPlayerPawn::m_bIsGrabbingHostage, std::int32_t>;
using OffsetToHostageServices = PlayerPawnOffset<cs2::C_CSPlayerPawn::m_pHostageServices, std::int32_t>;
using OffsetToFlashBangEndTime = PlayerPawnOffset<cs2::C_CSPlayerPawn::m_flFlashBangTime, std::int32_t>;
5 changes: 5 additions & 0 deletions Source/MemoryPatterns/Linux/PlayerPawnPatternsLinux.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,8 @@ inline OffsetToHostageServices PlayerPawnPatterns::offsetToHostageServices() con
{
return clientPatternFinder("E8 ? ? ? ? 49 8B B5 ? ? ? ? 48 85 F6 0F 84 ? ? ? ? 0F"_pat).add(8).readOffset<OffsetToHostageServices>();
}

inline OffsetToFlashBangEndTime PlayerPawnPatterns::offsetToFlashBangEndTime() const noexcept
{
return clientPatternFinder("F3 0F 10 83 ? ? ? ? 48 8B 18"_pat).add(4).readOffset<OffsetToFlashBangEndTime>();
}
1 change: 1 addition & 0 deletions Source/MemoryPatterns/PlayerPawnPatterns.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ struct PlayerPawnPatterns {
[[nodiscard]] OffsetToIsDefusing offsetToIsDefusing() const noexcept;
[[nodiscard]] OffsetToIsPickingUpHostage offsetToIsPickingUpHostage() const noexcept;
[[nodiscard]] OffsetToHostageServices offsetToHostageServices() const noexcept;
[[nodiscard]] OffsetToFlashBangEndTime offsetToFlashBangEndTime() const noexcept;

const PatternFinder<PatternNotFoundLogger>& clientPatternFinder;
};
5 changes: 5 additions & 0 deletions Source/MemoryPatterns/Windows/PlayerPawnPatternsWindows.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,8 @@ inline OffsetToHostageServices PlayerPawnPatterns::offsetToHostageServices() con
{
return clientPatternFinder("E8 ? ? ? ? 48 8B 87 ? ? ? ? 33 ? 4C"_pat).add(8).readOffset<OffsetToHostageServices>();
}

inline OffsetToFlashBangEndTime PlayerPawnPatterns::offsetToFlashBangEndTime() const noexcept
{
return clientPatternFinder("0F 2F 86 ? ? ? ? 48 8B 7C 24"_pat).add(3).readOffset<OffsetToFlashBangEndTime>();
}
2 changes: 2 additions & 0 deletions Source/UI/Panorama/CreateGUI.js
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@ $.Osiris = (function () {
createYesNoDropDown(playerInfo, 'Show Picking Up Hostage Icon', 'visuals', 'player_info_hostage_pickup', 0);
$.CreatePanel('Panel', playerInfo, '', { class: "horizontal-separator" });
createYesNoDropDown(playerInfo, 'Show Rescuing Hostage Icon', 'visuals', 'player_info_hostage_rescue', 0);
$.CreatePanel('Panel', playerInfo, '', { class: "horizontal-separator" });
createYesNoDropDown(playerInfo, 'Show Blinded By Flashbang Icon', 'visuals', 'player_info_blinded', 0);

var sound = createTab('sound');

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 @@ -71,6 +71,8 @@ struct SetCommandHandler {
handleFeature(features.visualFeatures().hostagePickupIconToggle());
} else if (feature == "player_info_hostage_rescue") {
handleFeature(features.visualFeatures().hostageRescueIconToggle());
} else if (feature == "player_info_blinded") {
handleFeature(features.visualFeatures().blindedIconToggle());
}
}

Expand Down

0 comments on commit ecb9998

Please sign in to comment.