Skip to content

Commit

Permalink
Implement player outline glow
Browse files Browse the repository at this point in the history
  • Loading branch information
danielkrupinski committed Aug 31, 2024
1 parent e9f4f37 commit 0effd93
Show file tree
Hide file tree
Showing 64 changed files with 1,164 additions and 7 deletions.
11 changes: 11 additions & 0 deletions Source/CS2/Classes/CRenderComponent.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#pragma once

#include "CUtlVector.h"
#include "SceneObjectUpdaterHandle_t.h"

namespace cs2
{
struct CRenderComponent {
using sceneObjectUpdaters = cs2::CUtlVector<SceneObjectUpdaterHandle_t*>;
};
}
9 changes: 9 additions & 0 deletions Source/CS2/Classes/CSceneObject.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#pragma once

namespace cs2
{

struct CSceneObject {
};

}
12 changes: 12 additions & 0 deletions Source/CS2/Classes/CSceneSystem.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#pragma once

namespace cs2
{

struct CSceneObject;

struct CSceneSystem {
using DeleteSceneObject = void(CSceneSystem* sceneSystem, CSceneObject* sceneObject);
};

}
5 changes: 5 additions & 0 deletions Source/CS2/Classes/Color.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ struct Color {
return rgba[3];
}

[[nodiscard]] auto setAlpha(std::uint8_t newAlpha) const noexcept
{
return Color{r(), g(), b(), newAlpha};
}

private:
std::uint8_t rgba[4];
};
Expand Down
2 changes: 1 addition & 1 deletion Source/CS2/Classes/Entities/CCSPlayerController.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace cs2
struct CCSPlayerController : C_BaseEntity {
static constexpr auto kMangledTypeName{WIN64_LINUX(".?AVCCSPlayerController@@", "19CCSPlayerController")};

using m_hPawn = CEntityHandle;
using m_hPlayerPawn = CEntityHandle;
using m_iCompTeammateColor = std::int32_t;
};

Expand Down
6 changes: 6 additions & 0 deletions Source/CS2/Classes/Entities/CEntityInstance.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
#pragma once

#include <Utils/Pad.h>

namespace cs2
{

struct CEntityIdentity;

struct CEntityInstance {
const void* vmt;
PAD(8);
CEntityIdentity* identity;
};

}
2 changes: 2 additions & 0 deletions Source/CS2/Classes/Entities/C_BaseEntity.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ namespace cs2

struct CEntitySubclassVDataBase;
struct CGameSceneNode;
struct CRenderComponent;

struct C_BaseEntity : CEntityInstance {
using m_pGameSceneNode = CGameSceneNode*;
using m_iHealth = std::int32_t;
using m_lifeState = std::uint8_t;
using m_iTeamNum = std::uint8_t;
using m_pSubclassVData = CEntitySubclassVDataBase*;
using m_pRenderComponent = CRenderComponent*;
};

}
40 changes: 40 additions & 0 deletions Source/CS2/Classes/Glow.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#pragma once

#include <cstdint>

#include "CSceneObject.h"

#include <Platform/Macros/IsPlatform.h>

namespace cs2
{

enum SceneObjectFlags {
SceneObjectFlag_IsDeleted = 0x20
};

struct CGlowHelperSceneObject : CSceneObject {
using entity = C_BaseEntity*;
using flags = std::uint8_t;
};

#if IS_WIN64()

using ManageGlowSceneObject = void(
CGlowHelperSceneObject** glowHelperSceneObject,
CGlowHelperSceneObject** unused,
CSceneObject* sceneObject,
float color[4], float glowRangeMin, float glowRange, int glowType, float glowBackfaceMult);

#elif IS_LINUX()

using ManageGlowSceneObject = void(
CGlowHelperSceneObject** glowHelperSceneObject,
CGlowHelperSceneObject** unused,
CSceneObject* sceneObject,
int glowType,
double colorGA, double colorRG, float glowRangeMin, float glowRange, float glowBackfaceMult);

#endif

}
12 changes: 12 additions & 0 deletions Source/CS2/Classes/SceneObjectUpdaterHandle_t.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#pragma once

namespace cs2
{

struct CSceneObject;

struct SceneObjectUpdaterHandle_t {
using sceneObject = CSceneObject*;
};

}
1 change: 1 addition & 0 deletions Source/CS2/Constants/DllNames.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ constexpr auto CLIENT_DLL = WIN64_LINUX("client.dll", "libclient.so");
constexpr auto ENGINE_DLL = WIN64_LINUX("engine2.dll", "libengine2.so");
constexpr auto FILESYSTEM_DLL = WIN64_LINUX("filesystem_stdio.dll", "libfilesystem_stdio.so");
constexpr auto PANORAMA_DLL = WIN64_LINUX("panorama.dll", "libpanorama.so");
constexpr auto SCENESYSTEM_DLL = WIN64_LINUX("scenesystem.dll", "libscenesystem.so");
constexpr auto SDL_DLL = WIN64_LINUX("SDL3.dll", "libSDL3.so.0");
constexpr auto SOUNDSYSTEM_DLL = WIN64_LINUX("soundsystem.dll", "libsoundsystem.so");
constexpr auto TIER0_DLL = WIN64_LINUX("tier0.dll", "libtier0.so");
Expand Down
2 changes: 2 additions & 0 deletions Source/FeatureHelpers/RenderingHookEntityLoop.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <CS2/Classes/Entities/CEntityInstance.h>
#include <Features/Visuals/PlayerInformationThroughWalls/PlayerInformationThroughWalls.h>
#include <Features/Visuals/PlayerOutlineGlow/PlayerOutlineGlow.h>

#include "EntityFromHandleFinder.h"

Expand Down Expand Up @@ -34,6 +35,7 @@ class RenderingHookEntityLoop {
if (dependencies.gameDependencies().entitiesVMTs.isPlayerPawn(entity.vmt)) {
auto& playerPawn = static_cast<cs2::C_CSPlayerPawn&>(entity);
playerInformationThroughWalls.drawPlayerInformation(playerPawn);
dependencies.make<PlayerOutlineGlow>().applyGlowToPlayer(dependencies.make<PlayerPawn>(&playerPawn));
}
}

Expand Down
2 changes: 2 additions & 0 deletions Source/Features/FeaturesUnloadHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "FeaturesStates.h"
#include "Hud/HudFeaturesUnloadHandler.h"
#include "Visuals/PlayerOutlineGlow/PlayerOutlineGlowUnloadHandler.h"

template <typename HookContext>
struct FeaturesUnloadHandler {
Expand All @@ -14,6 +15,7 @@ struct FeaturesUnloadHandler {
void handleUnload() const noexcept
{
hookContext.template make<HudFeaturesUnloadHandler>(states.hudFeaturesStates).handleUnload();
hookContext.template make<PlayerOutlineGlowUnloadHandler>().handleUnload();
}

HookContext& hookContext;
Expand Down
85 changes: 85 additions & 0 deletions Source/Features/Visuals/PlayerOutlineGlow/PlayerOutlineGlow.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#pragma once

#include <OutlineGlow/GlowSceneObjects.h>
#include "PlayerOutlineGlowCondition.h"

template <typename HookContext>
class PlayerOutlineGlowContext {
public:
explicit PlayerOutlineGlowContext(HookContext& hookContext) noexcept
: hookContext{hookContext}
{
}

[[nodiscard]] auto& state() const noexcept
{
return hookContext.featuresStates().visualFeaturesStates.playerOutlineGlowState;
}

[[nodiscard]] decltype(auto) condition() const noexcept
{
return hookContext.template make<PlayerOutlineGlowCondition>();
}

[[nodiscard]] decltype(auto) getGlowSceneObjectFor(auto&& baseEntity) const noexcept
{
return hookContext.template make<GlowSceneObjects>().getGlowSceneObject(baseEntity.handle());
}

[[nodiscard]] auto& viewRenderHook() const noexcept
{
return hookContext.hooks().viewRenderHook;
}

void clearGlowSceneObjects() const noexcept
{
hookContext.template make<GlowSceneObjects>().clearObjects();
}

[[nodiscard]] bool isLocalPlayerAlive() const noexcept
{
return hookContext.localPlayerController2().playerPawn().isAlive().value_or(true);
}

private:
HookContext& hookContext;
};

template <typename Context>
class PlayerOutlineGlow {
public:
template <typename... Args>
PlayerOutlineGlow(Args&&... args) noexcept
: context{std::forward<Args>(args)...}
{
}

void applyGlowToPlayer(auto&& playerPawn) const noexcept
{
auto&& condition = context.condition();
if (!condition.shouldRun() || !condition.shouldGlowPlayer(playerPawn))
return;

applyGlow(playerPawn.baseEntity(), getColor(playerPawn));
}

private:
void applyGlow(auto&& baseEntity, cs2::Color color) const noexcept
{
context.getGlowSceneObjectFor(baseEntity).apply(baseEntity, color.setAlpha(102));
}

[[nodiscard]] cs2::Color getColor(auto&& playerPawn) const noexcept
{
switch (playerPawn.teamNumber()) {
case TeamNumber::TT: return cs2::kColorTeamTT;
case TeamNumber::CT: return cs2::kColorTeamCT;
default: return cs2::kColorWhite;
}
}

Context context;
};

template <typename HookContext>
PlayerOutlineGlow(HookContext&) -> PlayerOutlineGlow<PlayerOutlineGlowContext<HookContext>>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#pragma once

#include <utility>

template <typename Context>
class PlayerOutlineGlowCondition {
public:
template <typename... Args>
explicit PlayerOutlineGlowCondition(Args&&... args) noexcept
: context{std::forward<Args>(args)...}
{
}

[[nodiscard]] bool shouldRun() const noexcept
{
return context.state().enabled;
}

[[nodiscard]] bool shouldGlowPlayer(auto&& playerPawn) const noexcept
{
return context.isLocalPlayerAlive()
&& playerPawn.isAlive().value_or(true)
&& !(playerPawn.health() <= 0)
&& !playerPawn.isControlledByLocalPlayer()
&& playerPawn.isTTorCT()
&& (!context.state().showOnlyEnemies || playerPawn.isEnemy().value_or(true));
}

private:
Context context;
};

template <typename HookContext>
class PlayerOutlineGlowContext;

template <typename HookContext>
PlayerOutlineGlowCondition(HookContext&) -> PlayerOutlineGlowCondition<PlayerOutlineGlowContext<HookContext>>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#pragma once

struct PlayerOutlineGlowState {
bool enabled{false};
bool showOnlyEnemies{false};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#pragma once

#include <FeatureHelpers/FeatureToggle.h>

template <typename Context>
struct PlayerOutlineGlowToggle : FeatureToggleOnOff<PlayerOutlineGlowToggle<Context>> {
template <typename... Args>
PlayerOutlineGlowToggle(Args&&... args) noexcept
: context{std::forward<Args>(args)...}
{
}

void update(char option) noexcept
{
switch (option) {
case '0': this->enable(); context.state().showOnlyEnemies = true; break;
case '1': this->enable(); context.state().showOnlyEnemies = false; break;
case '2': this->disable(); break;
}
}

[[nodiscard]] auto& enabledVariable(typename PlayerOutlineGlowToggle::ToggleMethod) const noexcept
{
return context.state().enabled;
}

void onEnable(typename PlayerOutlineGlowToggle::ToggleMethod) noexcept
{
context.viewRenderHook().incrementReferenceCount();
}

void onDisable(typename PlayerOutlineGlowToggle::ToggleMethod) noexcept
{
context.viewRenderHook().decrementReferenceCount();
context.clearGlowSceneObjects();
}

private:
Context context;
};

template <typename HookContext>
class PlayerOutlineGlowContext;

template <typename HookContext>
PlayerOutlineGlowToggle(HookContext&) -> PlayerOutlineGlowToggle<PlayerOutlineGlowContext<HookContext>>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#pragma once

#include <utility>

#include "PlayerOutlineGlow.h"

template <typename Context>
class PlayerOutlineGlowUnloadHandler {
public:
template <typename... Args>
PlayerOutlineGlowUnloadHandler(Args&&... args) noexcept
: context{std::forward<Args>(args)...}
{
}

void handleUnload() const noexcept
{
context.clearGlowSceneObjects();
}

private:
Context context;
};

template <typename HookContext>
PlayerOutlineGlowUnloadHandler(HookContext&) -> PlayerOutlineGlowUnloadHandler<PlayerOutlineGlowContext<HookContext>>;
Loading

0 comments on commit 0effd93

Please sign in to comment.