From b06f358d689e45b49c2f791c92c5e94e43dce6e4 Mon Sep 17 00:00:00 2001 From: AdamTadeusz Date: Fri, 21 Aug 2026 18:55:16 +0100 Subject: [PATCH 1/3] init --- game/neo/scripts/HudLayout.res | 4 + src/game/client/CMakeLists.txt | 1 + .../neo_matproxy_ghost_beacon_rotation.cpp | 80 ++++++++++ .../client/neo/ui/neo_hud_ghost_beacons.cpp | 140 +++++++++++------- .../client/neo/ui/neo_hud_ghost_beacons.h | 11 +- src/public/mathlib/mathlib.h | 29 ++++ 6 files changed, 206 insertions(+), 59 deletions(-) create mode 100644 src/game/client/neo/material_proxies/neo_matproxy_ghost_beacon_rotation.cpp diff --git a/game/neo/scripts/HudLayout.res b/game/neo/scripts/HudLayout.res index d692ff1c01..34aa1d96ad 100644 --- a/game/neo/scripts/HudLayout.res +++ b/game/neo/scripts/HudLayout.res @@ -950,6 +950,10 @@ "ypos" "0" "wide" "640" "tall" "480" + + "color" "255 20 20 150" + "font" "NHudOCRSmall" + "texture" "vgui/hud/ctg/g_beacon_enemy" } CNEOHud_GameEvent diff --git a/src/game/client/CMakeLists.txt b/src/game/client/CMakeLists.txt index 7fbb698e43..b27b402b4d 100644 --- a/src/game/client/CMakeLists.txt +++ b/src/game/client/CMakeLists.txt @@ -1636,6 +1636,7 @@ target_sources_grouped( TARGET client NAME "Source Files\\NEO\\Material Proxies" FILES + neo/material_proxies/neo_matproxy_ghost_beacon_rotation.cpp neo/material_proxies/neo_matproxy_thermoptic.cpp neo/material_proxies/neo_matproxy_thermoptic.h neo/material_proxies/neo_matproxy_teamnum.cpp diff --git a/src/game/client/neo/material_proxies/neo_matproxy_ghost_beacon_rotation.cpp b/src/game/client/neo/material_proxies/neo_matproxy_ghost_beacon_rotation.cpp new file mode 100644 index 0000000000..d7ef27a5d7 --- /dev/null +++ b/src/game/client/neo/material_proxies/neo_matproxy_ghost_beacon_rotation.cpp @@ -0,0 +1,80 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// +#include "cbase.h" +#include "materialsystem/imaterialproxy.h" +#include "materialsystem/imaterial.h" +#include "materialsystem/imaterialvar.h" +#include +#include "functionproxy.h" +#include "neo/ui/neo_hud_ghost_beacons.h" +#include "toolframework_client.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +// forward declarations +void ToolFramework_RecordMaterialParams( IMaterial *pMaterial ); + +class CGhostBeaconRotationMaterialProxy : public IMaterialProxy +{ +public: + CGhostBeaconRotationMaterialProxy(); + virtual ~CGhostBeaconRotationMaterialProxy(); + virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues ); + virtual void OnBind( void *pC_BaseEntity ); + virtual void Release( void ) { delete this; } + virtual IMaterial *GetMaterial(); + +private: + IMaterialVar *m_pGhostBeaconRotationVar; +}; + +CGhostBeaconRotationMaterialProxy::CGhostBeaconRotationMaterialProxy() +{ + m_pGhostBeaconRotationVar = NULL; +} + +CGhostBeaconRotationMaterialProxy::~CGhostBeaconRotationMaterialProxy() +{ +} + +bool CGhostBeaconRotationMaterialProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues ) +{ + char const* pScrollVarName = pKeyValues->GetString( "ghostBeaconRotationVar" ); + if( !pScrollVarName ) + return false; + + bool foundVar; + m_pGhostBeaconRotationVar = pMaterial->FindVar( pScrollVarName, &foundVar, false ); + if( !foundVar ) + return false; + + return true; +} + +extern CNEOHud_GhostBeacons* gHudGhostBeacons; +void CGhostBeaconRotationMaterialProxy::OnBind( void *pC_BaseEntity ) +{ + if( !m_pGhostBeaconRotationVar || !gHudGhostBeacons ) + { + return; + } + + m_pGhostBeaconRotationVar->SetFloatValue( gHudGhostBeacons->GetRotation() ); + + if ( ToolsEnabled() ) + { + ToolFramework_RecordMaterialParams( GetMaterial() ); + } +} + +IMaterial *CGhostBeaconRotationMaterialProxy::GetMaterial() +{ + return m_pGhostBeaconRotationVar->GetOwningMaterial(); +} + +EXPOSE_INTERFACE( CGhostBeaconRotationMaterialProxy, IMaterialProxy, "GhostBeaconRotation" IMATERIAL_PROXY_INTERFACE_VERSION ); diff --git a/src/game/client/neo/ui/neo_hud_ghost_beacons.cpp b/src/game/client/neo/ui/neo_hud_ghost_beacons.cpp index c3a4c3058b..82cecb4ce8 100644 --- a/src/game/client/neo/ui/neo_hud_ghost_beacons.cpp +++ b/src/game/client/neo/ui/neo_hud_ghost_beacons.cpp @@ -1,17 +1,9 @@ #include "neo_hud_ghost_beacons.h" -#include "cbase.h" - #include "iclientmode.h" -#include "ienginevgui.h" -#include -#include -#include -#include #include "c_neo_npc_dummy.h" #include "c_neo_player.h" -#include "neo_player_shared.h" #include "c_team.h" #include "neo_gamerules.h" #include "weapon_ghost.h" @@ -19,18 +11,20 @@ // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" -using vgui::surface; - -ConVar cl_neo_ghost_beacon_scale("cl_neo_ghost_beacon_scale", "1", FCVAR_ARCHIVE, +ConVar cl_neo_hud_ghost_beacon_scale("cl_neo_hud_ghost_beacon_scale", "1", FCVAR_ARCHIVE, "Ghost beacons scale.", true, 0.01, false, 0); -ConVar cl_neo_ghost_beacon_scale_with_distance("cl_neo_ghost_beacon_scale_with_distance", "0", FCVAR_ARCHIVE, - "Toggles the scaling of ghost beacons with distance.", true, 0, true, 1); - -ConVar cl_neo_ghost_beacon_alpha("cl_neo_ghost_beacon_alpha", "150", FCVAR_ARCHIVE, - "Alpha channel transparency of HUD ghost beacons.", true, 0, true, 255); +static float ghostBeaconRotation = 0.f; +ConVar cl_neo_hud_ghost_beacon_scale_with_distance("cl_neo_hud_ghost_beacon_scale_with_distance", "0", FCVAR_ARCHIVE, + "Toggles the scaling of ghost beacons with distance.", true, 0, true, 1, [](IConVar* var, const char* pOldValue, float flOldValue)->void{ + if (!cl_neo_hud_ghost_beacon_scale_with_distance.GetBool()) + ghostBeaconRotation = 0.f; +}); +ConVar cl_neo_hud_ghost_beacon_draw_distance("cl_neo_hud_ghost_beacon_draw_distance", "1", FCVAR_ARCHIVE, + "Draw the distance to the ghost beacons.", true, 0, true, 1); +CNEOHud_GhostBeacons* gHudGhostBeacons; DECLARE_NAMED_HUDELEMENT(CNEOHud_GhostBeacons, neo_ghost_beacons); @@ -39,6 +33,8 @@ NEO_HUD_ELEMENT_DECLARE_FREQ_CVAR(GhostBeacons, 0.01) CNEOHud_GhostBeacons::CNEOHud_GhostBeacons(const char *pElementName, vgui::Panel *parent) : CHudElement(pElementName), EditablePanel(parent, pElementName) { + gHudGhostBeacons = this; + SetAutoDelete(true); m_iHideHudElementNumber = NEO_HUD_ELEMENT_GHOST_BEACONS; @@ -51,17 +47,14 @@ CNEOHud_GhostBeacons::CNEOHud_GhostBeacons(const char *pElementName, vgui::Panel SetParent(g_pClientMode->GetViewport()); } - int screenWidth, screenHeight; - surface()->GetScreenSize(screenWidth, screenHeight); - SetBounds(0, 0, screenWidth, screenHeight); - - m_hTex = surface()->CreateNewTextureID(); - Assert(m_hTex > 0); - surface()->DrawSetTextureFile(m_hTex, "vgui/hud/ctg/g_beacon_enemy", 1, false); - SetVisible(true); } +CNEOHud_GhostBeacons::~CNEOHud_GhostBeacons() +{ + gHudGhostBeacons = nullptr; +} + void CNEOHud_GhostBeacons::UpdateStateForNeoHudElementDraw() { } @@ -70,11 +63,11 @@ void CNEOHud_GhostBeacons::ApplySchemeSettings(vgui::IScheme* pScheme) { BaseClass::ApplySchemeSettings(pScheme); - m_hFont = pScheme->GetFont("NHudOCRSmall", true); - - int screenWidth, screenHeight; - surface()->GetScreenSize(screenWidth, screenHeight); + vgui::surface()->GetScreenSize(screenWidth, screenHeight); SetBounds(0, 0, screenWidth, screenHeight); + doubleScreenWidth = 2 * screenWidth; + doubleScreenHeight = 2 * screenHeight; + SetFgColor(COLOR_TRANSPARENT); SetBgColor(COLOR_TRANSPARENT); } @@ -160,42 +153,79 @@ void CNEOHud_GhostBeacons::Paint() void CNEOHud_GhostBeacons::DrawPlayer(float distance, const Vector& playerPos) const { - const auto distInMeters = distance * METERS_PER_INCH; - const float scale = cl_neo_ghost_beacon_scale.GetFloat(); - constexpr float HALF_BASE_TEX_LENGTH = 32; + const float distInMeters = distance * METERS_PER_INCH; + constexpr float BASE_TEX_LENGTH = 64; + float halfBeaconLength = BASE_TEX_LENGTH * 0.5f * cl_neo_hud_ghost_beacon_scale.GetFloat(); - float halfBeaconLength = HALF_BASE_TEX_LENGTH * scale; int posX, posY; - Vector ghostBeaconOffset = Vector(0, 0, cl_neo_ghost_beacon_scale_with_distance.GetBool() ? 32 : 48); // The center of the player, or raise slightly if not scaling - GetVectorInScreenSpace(playerPos, posX, posY, &ghostBeaconOffset); - if (cl_neo_ghost_beacon_scale_with_distance.GetBool()) + Vector ghostBeaconOffset = Vector(0, 0, cl_neo_hud_ghost_beacon_scale_with_distance.GetBool() ? 0 : 48); + if (!GetVectorInScreenSpace(playerPos, posX, posY, &ghostBeaconOffset)) + { + return; + } + bool centerXClamped = clamp(&posX, -screenWidth, doubleScreenWidth); + bool centerYClamped = clamp(&posY, -screenHeight, doubleScreenHeight); + + if (cl_neo_hud_ghost_beacon_scale_with_distance.GetBool()) { + if (centerXClamped && centerYClamped) + { + return; + } + int pos2X, pos2Y; - Vector ghostBeaconOffset2 = Vector(0, 0, 64); // The top of the player - GetVectorInScreenSpace(playerPos, pos2X, pos2Y, &ghostBeaconOffset2); - halfBeaconLength = (posY - pos2Y) * 0.5 * scale; + Vector ghostBeaconEyeOffset = Vector(0, 0, 64); + if (!GetVectorInScreenSpace(playerPos, pos2X, pos2Y, &ghostBeaconEyeOffset)) + { + return; + } + + if (clamp(&pos2X, -screenWidth, doubleScreenWidth) && clamp(&pos2Y, -screenHeight, doubleScreenHeight)) + { + return; + } + + Vector2D playerUpDirectionOnScreen = Vector2D(pos2X - posX, pos2Y - posY); + const Vector2D screenUpDirection = Vector2D(0, 1); + float rotation = acos((playerUpDirectionOnScreen.Dot(screenUpDirection)) / playerUpDirectionOnScreen.Length()) + M_PI; + if (pos2X < posX) + { + rotation *= -1; + } + ghostBeaconRotation = RAD2DEG(rotation); + + halfBeaconLength = (posY - pos2Y) * 0.5f * cl_neo_hud_ghost_beacon_scale.GetFloat(); + posX = (posX + pos2X) / 2; + posY = (posY + pos2Y) / 2; } - - wchar_t m_wszBeaconTextUnicode[4 + 1]; - V_snwprintf(m_wszBeaconTextUnicode, ARRAYSIZE(m_wszBeaconTextUnicode), L"%02d m", FastFloatToSmallInt(distInMeters)); const auto ghostViewDist = sv_neo_ghost_view_distance.GetFloat(); - const float alphaMultiplier = (distInMeters < ghostViewDist * 35.f / 45) ? 1.0 : ((ghostViewDist - distInMeters) / 10); - const int alpha = cl_neo_ghost_beacon_alpha.GetInt() * alphaMultiplier; - surface()->DrawSetTextColor(255, 255, 255, alpha); - surface()->DrawSetTextFont(m_hFont); - int textWidth, textHeight; - surface()->GetTextSize(m_hFont, m_wszBeaconTextUnicode, textWidth, textHeight); - surface()->DrawSetTextPos(posX - (textWidth / 2), posY + halfBeaconLength); - surface()->DrawPrintText(m_wszBeaconTextUnicode, V_wcslen(m_wszBeaconTextUnicode)); - - surface()->DrawSetColor(255, 20, 20, alpha); - surface()->DrawSetTexture(m_hTex); - - // End coordinates according to art size (and our distance scaling) - surface()->DrawTexturedRect( + const float alphaMultiplier = distInMeters < (ghostViewDist * 35.f / 45) ? 1.0f : (ghostViewDist - distInMeters) / 10; + const int alpha = beaconColor.a() * alphaMultiplier; + + if (cl_neo_hud_ghost_beacon_draw_distance.GetBool()) + { + wchar_t m_wszBeaconTextUnicode[4 + 1]; + V_snwprintf(m_wszBeaconTextUnicode, ARRAYSIZE(m_wszBeaconTextUnicode), L"%02d m", FastFloatToSmallInt(distInMeters)); + + vgui::surface()->DrawSetTextColor(255, 255, 255, alpha); + vgui::surface()->DrawSetTextFont(m_hFont); + int textWidth, textHeight; + vgui::surface()->GetTextSize(m_hFont, m_wszBeaconTextUnicode, textWidth, textHeight); + vgui::surface()->DrawSetTextPos(posX - (textWidth / 2), posY + halfBeaconLength); + vgui::surface()->DrawPrintText(m_wszBeaconTextUnicode, V_wcslen(m_wszBeaconTextUnicode)); + } + + vgui::surface()->DrawSetColor(beaconColor.r(), beaconColor.g(), beaconColor.b(), alpha); + vgui::surface()->DrawSetTexture(m_hTex); + vgui::surface()->DrawTexturedRect( posX - halfBeaconLength, posY - halfBeaconLength, posX + halfBeaconLength, posY + halfBeaconLength); } + +float CNEOHud_GhostBeacons::GetRotation() +{ + return ghostBeaconRotation; +} diff --git a/src/game/client/neo/ui/neo_hud_ghost_beacons.h b/src/game/client/neo/ui/neo_hud_ghost_beacons.h index 2d826d6f6a..55ade9b654 100644 --- a/src/game/client/neo/ui/neo_hud_ghost_beacons.h +++ b/src/game/client/neo/ui/neo_hud_ghost_beacons.h @@ -8,16 +8,16 @@ #include "hudelement.h" #include -#include "weapon_ghost.h" - class CNEOHud_GhostBeacons : public CNEOHud_ChildElement, public CHudElement, public vgui::EditablePanel { DECLARE_CLASS_SIMPLE(CNEOHud_GhostBeacons, EditablePanel); public: CNEOHud_GhostBeacons(const char *pElementName, vgui::Panel *parent = NULL); + ~CNEOHud_GhostBeacons(); virtual void ApplySchemeSettings(vgui::IScheme* pScheme) override; virtual void Paint() override; + float GetRotation(); private: void DrawPlayer(float distance, const Vector& playerPos) const; @@ -28,8 +28,11 @@ class CNEOHud_GhostBeacons : public CNEOHud_ChildElement, public CHudElement, pu virtual ConVar* GetUpdateFrequencyConVar() const override; private: - vgui::HFont m_hFont; - vgui::HTexture m_hTex; + int screenWidth = 0, screenHeight = 0, doubleScreenWidth = 0, doubleScreenHeight = 0; + + CPanelAnimationVar(Color, beaconColor, "color", "");// "255, 20, 20, 150"); + CPanelAnimationVar(vgui::HFont, m_hFont, "font", "");// "NHudOCRSmall"); + CPanelAnimationVarAliasType(int, m_hTex, "texture", "", "textureid");// "vgui/hud/ctg/g_beacon_enemy", "textureid"); private: CNEOHud_GhostBeacons(const CNEOHud_GhostBeacons &other); diff --git a/src/public/mathlib/mathlib.h b/src/public/mathlib/mathlib.h index 13770afb74..783389259c 100644 --- a/src/public/mathlib/mathlib.h +++ b/src/public/mathlib/mathlib.h @@ -164,6 +164,35 @@ inline T clamp( T const &val, T const &minVal, T const &maxVal ) return val; } +#ifdef NEO +// +// Clamps a value in the range [min, max]. Returns true if the value was clamped +// +template< class T > +inline bool clamp( T *val, T const &minVal, T const &maxVal ) +{ + if (maxVal < minVal) + { + *val = maxVal; + return true; + } + else if (*val < minVal) + { + *val = minVal; + return true; + } + else if (*val > maxVal) + { + *val = maxVal; + return true; + } + else + { + return false; + } +} +#endif // NEO + // plane_t structure // !!! if this is changed, it must be changed in asm code too !!! From 06ea82f08d9166114fb48ba5db4d7848e6b15bbb Mon Sep 17 00:00:00 2001 From: AdamTadeusz Date: Fri, 21 Aug 2026 18:59:24 +0100 Subject: [PATCH 2/3] unused include --- .../neo/material_proxies/neo_matproxy_ghost_beacon_rotation.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/game/client/neo/material_proxies/neo_matproxy_ghost_beacon_rotation.cpp b/src/game/client/neo/material_proxies/neo_matproxy_ghost_beacon_rotation.cpp index d7ef27a5d7..9abdf7bb6f 100644 --- a/src/game/client/neo/material_proxies/neo_matproxy_ghost_beacon_rotation.cpp +++ b/src/game/client/neo/material_proxies/neo_matproxy_ghost_beacon_rotation.cpp @@ -4,12 +4,10 @@ // // $NoKeywords: $ //=============================================================================// -#include "cbase.h" #include "materialsystem/imaterialproxy.h" #include "materialsystem/imaterial.h" #include "materialsystem/imaterialvar.h" #include -#include "functionproxy.h" #include "neo/ui/neo_hud_ghost_beacons.h" #include "toolframework_client.h" From 671ae65856829561e3a05585d9c04c9629669d5f Mon Sep 17 00:00:00 2001 From: AdamTadeusz Date: Fri, 21 Aug 2026 19:02:28 +0100 Subject: [PATCH 3/3] hud_layout fields work, reinclude defaults again --- src/game/client/neo/ui/neo_hud_ghost_beacons.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/game/client/neo/ui/neo_hud_ghost_beacons.h b/src/game/client/neo/ui/neo_hud_ghost_beacons.h index 55ade9b654..0f30a258e2 100644 --- a/src/game/client/neo/ui/neo_hud_ghost_beacons.h +++ b/src/game/client/neo/ui/neo_hud_ghost_beacons.h @@ -30,9 +30,9 @@ class CNEOHud_GhostBeacons : public CNEOHud_ChildElement, public CHudElement, pu private: int screenWidth = 0, screenHeight = 0, doubleScreenWidth = 0, doubleScreenHeight = 0; - CPanelAnimationVar(Color, beaconColor, "color", "");// "255, 20, 20, 150"); - CPanelAnimationVar(vgui::HFont, m_hFont, "font", "");// "NHudOCRSmall"); - CPanelAnimationVarAliasType(int, m_hTex, "texture", "", "textureid");// "vgui/hud/ctg/g_beacon_enemy", "textureid"); + CPanelAnimationVar(Color, beaconColor, "color", "255, 20, 20, 150"); + CPanelAnimationVar(vgui::HFont, m_hFont, "font", "NHudOCRSmall"); + CPanelAnimationVarAliasType(int, m_hTex, "texture", "vgui/hud/ctg/g_beacon_enemy", "textureid"); private: CNEOHud_GhostBeacons(const CNEOHud_GhostBeacons &other);