From 1421ad386bde6a2cb9851b860ea079d1dcdab98a Mon Sep 17 00:00:00 2001 From: "DESKTOP-CCL0V26\\DraGonM" Date: Thu, 20 Aug 2026 22:52:07 +0300 Subject: [PATCH 1/3] prototype --- src/game/shared/neo/neo_ghost_cap_point.cpp | 102 ++++++++++++++++++++ src/game/shared/neo/neo_ghost_cap_point.h | 9 ++ 2 files changed, 111 insertions(+) diff --git a/src/game/shared/neo/neo_ghost_cap_point.cpp b/src/game/shared/neo/neo_ghost_cap_point.cpp index 20b29002b..f5abd2b7c 100644 --- a/src/game/shared/neo/neo_ghost_cap_point.cpp +++ b/src/game/shared/neo/neo_ghost_cap_point.cpp @@ -13,6 +13,7 @@ #ifdef CLIENT_DLL #include "ui/neo_hud_ghost_cap_point.h" +#include "materialsystem/imaterialsystem.h" #endif // memdbgon must be the last include file in a .cpp file!!! @@ -202,6 +203,8 @@ void CNEOGhostCapturePoint::Spawn(void) SetContextThink(&CNEOGhostCapturePoint::Think_CheckMyRadius, gpGlobals->curtime, "CheckMyRadius"); #else + m_pRingMaterial = materials->FindMaterial("effects/cap_zone_ring", TEXTURE_GROUP_CLIENT_EFFECTS); + AddToLeafSystem(RENDER_GROUP_TRANSLUCENT_ENTITY); SetNextClientThink(gpGlobals->curtime + NEO_GHOSTCAP_GRAPHICS_THINK_INTERVAL); #endif } @@ -298,6 +301,105 @@ void CNEOGhostCapturePoint::ClientThink(void) SetNextClientThink(gpGlobals->curtime + NEO_GHOSTCAP_GRAPHICS_THINK_INTERVAL); } + +bool CNEOGhostCapturePoint::ShouldDraw() +{ + return m_bIsActive; +} + +RenderGroup_t CNEOGhostCapturePoint::GetRenderGroup() +{ + return RENDER_GROUP_TRANSLUCENT_ENTITY; +} + +void CNEOGhostCapturePoint::GetRenderBoundsWorldspace(Vector& mins, Vector& maxs) +{ + const Vector& origin = GetAbsOrigin(); + const float r = m_flCapzoneRadius; + mins = origin + Vector(-r, -r, -16.0f); + maxs = origin + Vector(r, r, 16.0f); +} + +int CNEOGhostCapturePoint::DrawModel(int flags) +{ + if (!m_bIsActive || !m_pRingMaterial) + return 0; + + // Mirror the arrow color logic from CNEOHud_GhostCapPoint::DrawNeoHudElement exactly + const int capTeam = owningTeamAlternate(); + Color ringColor = (capTeam == TEAM_ANY) ? COLOR_SPEC : ((capTeam == TEAM_JINRAI) ? COLOR_JINRAI : COLOR_NSF); + + auto *player = C_NEO_Player::GetLocalNEOPlayer(); + + if (player) + { + const int playerTeam = player->GetTeamNumber(); + const bool playerIsPlaying = (playerTeam == TEAM_JINRAI || playerTeam == TEAM_NSF); + + if (playerIsPlaying && capTeam != TEAM_ANY && playerTeam != capTeam) + { + ringColor = COLOR_RED; + } + } + + ringColor[3] = 180; + + const Vector& origin = GetAbsOrigin(); + constexpr int SEGMENTS = 64; + constexpr float RING_HEIGHT_BOTTOM = 4.0f; // units above cap zone origin + constexpr float RING_HEIGHT_TOP = 12.0f; // units above cap zone origin + + const float zBottom = origin.z + RING_HEIGHT_BOTTOM; + const float zTop = origin.z + RING_HEIGHT_TOP; + const float r = m_flCapzoneRadius; + + CMatRenderContextPtr pRenderContext(materials); + pRenderContext->Bind(m_pRingMaterial); + IMesh *pMesh = pRenderContext->GetDynamicMesh(true); + + CMeshBuilder meshBuilder; + meshBuilder.Begin(pMesh, MATERIAL_QUADS, SEGMENTS); + + for (int i = 0; i < SEGMENTS; i++) + { + const float a0 = ((float)i / SEGMENTS) * M_PI_F * 2.0f; + const float a1 = ((float)(i + 1) / SEGMENTS) * M_PI_F * 2.0f; + const float cos0 = cosf(a0), sin0 = sinf(a0); + const float cos1 = cosf(a1), sin1 = sinf(a1); + + // Each segment gets its own full 0→1 tile; VMT TextureScroll handles animation + // Bottom at a0 + meshBuilder.Position3f(origin.x + cos0 * r, origin.y + sin0 * r, zBottom); + meshBuilder.Normal3f(cos0, sin0, 0.0f); + meshBuilder.Color4ub(ringColor.r(), ringColor.g(), ringColor.b(), ringColor.a()); + meshBuilder.TexCoord2f(0, 0.0f, 1.0f); + meshBuilder.AdvanceVertex(); + + // Bottom at a1 + meshBuilder.Position3f(origin.x + cos1 * r, origin.y + sin1 * r, zBottom); + meshBuilder.Normal3f(cos1, sin1, 0.0f); + meshBuilder.Color4ub(ringColor.r(), ringColor.g(), ringColor.b(), ringColor.a()); + meshBuilder.TexCoord2f(0, 1.0f, 1.0f); + meshBuilder.AdvanceVertex(); + + // Top at a1 + meshBuilder.Position3f(origin.x + cos1 * r, origin.y + sin1 * r, zTop); + meshBuilder.Normal3f(cos1, sin1, 0.0f); + meshBuilder.Color4ub(ringColor.r(), ringColor.g(), ringColor.b(), ringColor.a()); + meshBuilder.TexCoord2f(0, 1.0f, 0.0f); + meshBuilder.AdvanceVertex(); + + // Top at a0 + meshBuilder.Position3f(origin.x + cos0 * r, origin.y + sin0 * r, zTop); + meshBuilder.Normal3f(cos0, sin0, 0.0f); + meshBuilder.Color4ub(ringColor.r(), ringColor.g(), ringColor.b(), ringColor.a()); + meshBuilder.TexCoord2f(0, 0.0f, 0.0f); + meshBuilder.AdvanceVertex(); + } + + meshBuilder.End(false, true); + return 1; +} #endif void CNEOGhostCapturePoint::Precache(void) diff --git a/src/game/shared/neo/neo_ghost_cap_point.h b/src/game/shared/neo/neo_ghost_cap_point.h index a53a168d9..bc120be21 100644 --- a/src/game/shared/neo/neo_ghost_cap_point.h +++ b/src/game/shared/neo/neo_ghost_cap_point.h @@ -24,6 +24,8 @@ #include "vphysics_interface.h" #include "c_neo_player.h" #include "ienginevgui.h" +#include "materialsystem/imaterial.h" +#include "materialsystem/imesh.h" #endif #ifdef CLIENT_DLL @@ -94,6 +96,13 @@ class CNEOGhostCapturePoint : public CBaseEntity bool m_bIsActive; CNEOHud_GhostCapPoint *m_pHUDCapPoint = nullptr; + IMaterial *m_pRingMaterial = nullptr; + +public: + virtual bool ShouldDraw() override; + virtual RenderGroup_t GetRenderGroup() override; + virtual void GetRenderBoundsWorldspace(Vector& mins, Vector& maxs) override; + virtual int DrawModel(int flags) override; #endif }; From 2d622da2e3db59915310668bf2b939125b76b300 Mon Sep 17 00:00:00 2001 From: "DESKTOP-CCL0V26\\DraGonM" Date: Sun, 6 Sep 2026 23:28:25 +0300 Subject: [PATCH 2/3] convar, logo layer, visibility clamping --- src/game/client/neo/ui/neo_root_settings.cpp | 9 + src/game/client/neo/ui/neo_root_settings.h | 2 + src/game/shared/neo/neo_ghost_cap_point.cpp | 184 ++++++++++++++----- src/game/shared/neo/neo_ghost_cap_point.h | 5 + 4 files changed, 153 insertions(+), 47 deletions(-) diff --git a/src/game/client/neo/ui/neo_root_settings.cpp b/src/game/client/neo/ui/neo_root_settings.cpp index 8057264bf..a2059dd02 100644 --- a/src/game/client/neo/ui/neo_root_settings.cpp +++ b/src/game/client/neo/ui/neo_root_settings.cpp @@ -123,6 +123,12 @@ static const wchar_t* AUTOMATIC_LEAN_LABELS[] = { L"Always", }; +static const wchar_t* CAP_ZONE_EDGE_LABELS[] = { + L"Disabled", + L"Line", + L"Line + Logo", +}; + static const wchar_t *CROSSHAIR_HIPFIRE_LABELS_DEFAULT[HIPFIREOPT__TOTAL] = { L"Disabled", L"Use default", @@ -424,6 +430,7 @@ void NeoSettingsRestore(NeoSettings *ns, const NeoSettings::Keys::Flags flagsKey pGeneral->bViewmodelRighthand = cvr->cl_righthand.GetBool(); pGeneral->bLeanViewmodelOnly = cvr->cl_neo_lean_viewmodel_only.GetBool(); pGeneral->iLeanAutomatic = cvr->cl_neo_lean_automatic.GetInt(); + pGeneral->iCapZoneEdge = cvr->cl_neo_cap_zone_edge.GetInt(); pGeneral->iEquipUtilityPriority = cvr->cl_neo_equip_utility_priority.GetInt(); pGeneral->bWeaponFastSwitch = cvr->hud_fastswitch.GetBool(); pGeneral->bShowPlayerSprays = !(cvr->cl_spraydisable.GetBool()); // Inverse @@ -792,6 +799,7 @@ void NeoSettingsSave(const NeoSettings *ns) cvr->cl_righthand.SetValue(pGeneral->bViewmodelRighthand); cvr->cl_neo_lean_viewmodel_only.SetValue(pGeneral->bLeanViewmodelOnly); cvr->cl_neo_lean_automatic.SetValue(pGeneral->iLeanAutomatic); + cvr->cl_neo_cap_zone_edge.SetValue(pGeneral->iCapZoneEdge); cvr->cl_neo_equip_utility_priority.SetValue(pGeneral->iEquipUtilityPriority); cvr->hud_fastswitch.SetValue(pGeneral->bWeaponFastSwitch); cvr->cl_spraydisable.SetValue(!pGeneral->bShowPlayerSprays); // Inverse @@ -1110,6 +1118,7 @@ void NeoSettings_General(NeoSettings *ns) NeoUI::RingBox(L"Utility slot equip priority", EQUIP_UTILITY_PRIORITY_LABELS, NeoSettings::EquipUtilityPriorityType::EQUIP_UTILITY_PRIORITY__TOTAL, &pGeneral->iEquipUtilityPriority); NeoUI::RingBoxBool(L"Weapon fastswitch", &pGeneral->bWeaponFastSwitch); NeoUI::RingBoxBool(L"Taking damage sounds", &pGeneral->bTakingDamageSounds); + NeoUI::RingBox(L"Cap zone edge", CAP_ZONE_EDGE_LABELS, ARRAYSIZE(CAP_ZONE_EDGE_LABELS), &pGeneral->iCapZoneEdge); NeoUI::Divider(L"MAIN MENU"); NeoUI::RingBox(L"Selected Background", const_cast(ns->p2WszCBList), ns->iCBListSize, &pGeneral->iBackground); diff --git a/src/game/client/neo/ui/neo_root_settings.h b/src/game/client/neo/ui/neo_root_settings.h index 6065ce8cc..c0e615f03 100644 --- a/src/game/client/neo/ui/neo_root_settings.h +++ b/src/game/client/neo/ui/neo_root_settings.h @@ -64,6 +64,7 @@ struct NeoSettings bool bViewmodelRighthand; bool bLeanViewmodelOnly; int iLeanAutomatic; + int iCapZoneEdge; int iEquipUtilityPriority; bool bWeaponFastSwitch; bool bShowPlayerSprays; @@ -260,6 +261,7 @@ struct NeoSettings CONVARREF_DEF(cl_righthand); CONVARREF_DEF(cl_neo_lean_viewmodel_only); CONVARREF_DEF(cl_neo_lean_automatic); + CONVARREF_DEF(cl_neo_cap_zone_edge); CONVARREF_DEF(cl_neo_squad_hud_original); CONVARREF_DEF(cl_neo_hud_health_mode); CONVARREF_DEF(cl_neo_hud_worldpos_verbose); diff --git a/src/game/shared/neo/neo_ghost_cap_point.cpp b/src/game/shared/neo/neo_ghost_cap_point.cpp index f5abd2b7c..48469dbf2 100644 --- a/src/game/shared/neo/neo_ghost_cap_point.cpp +++ b/src/game/shared/neo/neo_ghost_cap_point.cpp @@ -14,6 +14,7 @@ #ifdef CLIENT_DLL #include "ui/neo_hud_ghost_cap_point.h" #include "materialsystem/imaterialsystem.h" +#include #endif // memdbgon must be the last include file in a .cpp file!!! @@ -77,6 +78,17 @@ BEGIN_DATADESC(CNEOGhostCapturePoint) #endif END_DATADESC() +enum NeoCapEdgeType +{ + NEO_CAP_EDGE_OFF = 0, // disabled + NEO_CAP_EDGE_LINE, // show only a line around the capzone + NEO_CAP_EDGE_LINE_LOGO, // show the line + a team logo +}; + +#ifdef CLIENT_DLL +ConVar cl_neo_cap_zone_edge("cl_neo_cap_zone_edge", "2", FCVAR_ARCHIVE, "Cap zone edge rendering", true, 0, true, NEO_CAP_EDGE_LINE_LOGO); +#endif + CNEOGhostCapturePoint::CNEOGhostCapturePoint() { m_flCapzoneRadius = -1; @@ -143,6 +155,7 @@ int CNEOGhostCapturePoint::owningTeamAlternate() const void CNEOGhostCapturePoint::Spawn(void) { + Precache(); BaseClass::Spawn(); AddEFlags(EFL_FORCE_CHECK_TRANSMIT); @@ -204,6 +217,8 @@ void CNEOGhostCapturePoint::Spawn(void) gpGlobals->curtime, "CheckMyRadius"); #else m_pRingMaterial = materials->FindMaterial("effects/cap_zone_ring", TEXTURE_GROUP_CLIENT_EFFECTS); + m_pRingNsfMaterial = materials->FindMaterial("effects/cap_zone_ring_nsf", TEXTURE_GROUP_CLIENT_EFFECTS); + m_pRingJinraiMaterial = materials->FindMaterial("effects/cap_zone_ring_jinrai", TEXTURE_GROUP_CLIENT_EFFECTS); AddToLeafSystem(RENDER_GROUP_TRANSLUCENT_ENTITY); SetNextClientThink(gpGlobals->curtime + NEO_GHOSTCAP_GRAPHICS_THINK_INTERVAL); #endif @@ -322,8 +337,11 @@ void CNEOGhostCapturePoint::GetRenderBoundsWorldspace(Vector& mins, Vector& maxs int CNEOGhostCapturePoint::DrawModel(int flags) { - if (!m_bIsActive || !m_pRingMaterial) + int cl_neo_cap_zone_edge_value = cl_neo_cap_zone_edge.GetInt(); + + if (!m_bIsActive && !m_pRingMaterial || !m_pRingJinraiMaterial || !m_pRingNsfMaterial || cl_neo_cap_zone_edge_value == NEO_CAP_EDGE_OFF) { return 0; + } // Mirror the arrow color logic from CNEOHud_GhostCapPoint::DrawNeoHudElement exactly const int capTeam = owningTeamAlternate(); @@ -331,6 +349,10 @@ int CNEOGhostCapturePoint::DrawModel(int flags) auto *player = C_NEO_Player::GetLocalNEOPlayer(); + const Vector& capOrigin = GetAbsOrigin(); + int ringOpacity = 128; + constexpr float MAX_VISIBILITY_RANGE = 768.0f; + if (player) { const int playerTeam = player->GetTeamNumber(); @@ -340,66 +362,128 @@ int CNEOGhostCapturePoint::DrawModel(int flags) { ringColor = COLOR_RED; } + + const Vector& playerOrigin = player->GetAbsOrigin(); + const float distanceToCap = playerOrigin.DistTo(capOrigin); + + if (distanceToCap > MAX_VISIBILITY_RANGE) { + return 0; // Don't draw the ring if the player is too far away + } + + // smooth fade out of ring opacity based on distance to player + const float opacityCoef = distanceToCap / MAX_VISIBILITY_RANGE; + ringOpacity = static_cast(128 * (1.0f - opacityCoef)); } - ringColor[3] = 180; + ringColor[3] = ringOpacity; - const Vector& origin = GetAbsOrigin(); - constexpr int SEGMENTS = 64; - constexpr float RING_HEIGHT_BOTTOM = 4.0f; // units above cap zone origin - constexpr float RING_HEIGHT_TOP = 12.0f; // units above cap zone origin + // draw bars ring + constexpr float SEGMENT_SIZE = 8.0f; + constexpr float RING_BOTTOM = 4.0f; - const float zBottom = origin.z + RING_HEIGHT_BOTTOM; - const float zTop = origin.z + RING_HEIGHT_TOP; - const float r = m_flCapzoneRadius; + const int segments = (int)round(M_PI_F * 2.0f * m_flCapzoneRadius / SEGMENT_SIZE); + const float zBottom = capOrigin.z + RING_BOTTOM; + const float radius = m_flCapzoneRadius; CMatRenderContextPtr pRenderContext(materials); pRenderContext->Bind(m_pRingMaterial); IMesh *pMesh = pRenderContext->GetDynamicMesh(true); - CMeshBuilder meshBuilder; - meshBuilder.Begin(pMesh, MATERIAL_QUADS, SEGMENTS); + meshBuilder.Begin(pMesh, MATERIAL_QUADS, segments); - for (int i = 0; i < SEGMENTS; i++) - { - const float a0 = ((float)i / SEGMENTS) * M_PI_F * 2.0f; - const float a1 = ((float)(i + 1) / SEGMENTS) * M_PI_F * 2.0f; - const float cos0 = cosf(a0), sin0 = sinf(a0); - const float cos1 = cosf(a1), sin1 = sinf(a1); - - // Each segment gets its own full 0→1 tile; VMT TextureScroll handles animation - // Bottom at a0 - meshBuilder.Position3f(origin.x + cos0 * r, origin.y + sin0 * r, zBottom); - meshBuilder.Normal3f(cos0, sin0, 0.0f); - meshBuilder.Color4ub(ringColor.r(), ringColor.g(), ringColor.b(), ringColor.a()); - meshBuilder.TexCoord2f(0, 0.0f, 1.0f); - meshBuilder.AdvanceVertex(); - - // Bottom at a1 - meshBuilder.Position3f(origin.x + cos1 * r, origin.y + sin1 * r, zBottom); - meshBuilder.Normal3f(cos1, sin1, 0.0f); - meshBuilder.Color4ub(ringColor.r(), ringColor.g(), ringColor.b(), ringColor.a()); - meshBuilder.TexCoord2f(0, 1.0f, 1.0f); - meshBuilder.AdvanceVertex(); - - // Top at a1 - meshBuilder.Position3f(origin.x + cos1 * r, origin.y + sin1 * r, zTop); - meshBuilder.Normal3f(cos1, sin1, 0.0f); - meshBuilder.Color4ub(ringColor.r(), ringColor.g(), ringColor.b(), ringColor.a()); - meshBuilder.TexCoord2f(0, 1.0f, 0.0f); - meshBuilder.AdvanceVertex(); - - // Top at a0 - meshBuilder.Position3f(origin.x + cos0 * r, origin.y + sin0 * r, zTop); - meshBuilder.Normal3f(cos0, sin0, 0.0f); - meshBuilder.Color4ub(ringColor.r(), ringColor.g(), ringColor.b(), ringColor.a()); - meshBuilder.TexCoord2f(0, 0.0f, 0.0f); - meshBuilder.AdvanceVertex(); - } + this->DrawBarRing(meshBuilder, segments, zBottom, SEGMENT_SIZE, radius, capOrigin, ringColor); meshBuilder.End(false, true); + + if (cl_neo_cap_zone_edge_value != NEO_CAP_EDGE_LINE_LOGO || capTeam == TEAM_ANY) { + return 1; + } + + // draw logo ring + constexpr float LOGO_SIZE = 16.0f; + constexpr float LOGO_BOTTOM = 2.0f; + const float logoRadius = m_flCapzoneRadius - 1.0f; + // draw logo only 5 times + constexpr int LOGO_SEGMENTS = 5; + const float zLogoBottom = capOrigin.z + LOGO_BOTTOM; + + pRenderContext->Bind(capTeam == TEAM_JINRAI ? m_pRingJinraiMaterial : m_pRingNsfMaterial); + IMesh* pMeshTeam = pRenderContext->GetDynamicMesh(true); + CMeshBuilder meshBuilderTeam; + meshBuilderTeam.Begin(pMeshTeam, MATERIAL_QUADS, LOGO_SEGMENTS); + + this->DrawLogoRing(meshBuilderTeam, LOGO_SEGMENTS, zLogoBottom, LOGO_SIZE, logoRadius, capOrigin, ringColor); + + meshBuilderTeam.End(false, true); + return 1; } + +void CNEOGhostCapturePoint::DrawBarRing(CMeshBuilder& builder, int segments, float zBottom, float segmentSize, float radius, Vector capOrigin, Color ringColor) +{ + // for portal effect add currentRotationInRad to angle0, maybe use it for the cap effect? + //constexpr float ROTATION_SPEED = 45.0f; + //const float currentRotationInRad = ROTATION_SPEED * gpGlobals->curtime * (M_PI_F / 180.0f); + constexpr float CIRCLE_LENGTH = M_PI_F * 2.0f; + + for (int i = 0; i < segments; i++) + { + const float angle0 = ((float)i / segments) * CIRCLE_LENGTH; + const float angle1 = ((float)(i + 1) / segments) * CIRCLE_LENGTH; + this->DrawSegment(builder, angle0, angle1, zBottom, zBottom + segmentSize, radius, capOrigin, ringColor); + } +} + +void CNEOGhostCapturePoint::DrawLogoRing(CMeshBuilder& builder, int segmentsToFill, float zBottom, float segmentSize, float radius, Vector capOrigin, Color ringColor) +{ + constexpr float ROTATION_SPEED = 5.0f; + constexpr float CIRCLE_LENGTH = M_PI_F * 2.0f; + const float currentRotationInRad = ROTATION_SPEED * gpGlobals->curtime * (M_PI_F / 180.0f); + // calculate the number of segments to fill based on the segment size and radius + const int segmentsCountBySize = (int)round(CIRCLE_LENGTH * radius / segmentSize); + + for (int i = 0; i < segmentsToFill; i++) + { + const float angle0 = ((float)i / segmentsToFill) * CIRCLE_LENGTH + currentRotationInRad; + // we take angle0 and add angle increment based on single segment size to get angle1 + // that way we are achieving a partial fill of the ring based on the segment size and radius + const float angle1 = angle0 + ((float)1 / segmentsCountBySize) * CIRCLE_LENGTH; + this->DrawSegment(builder, angle0, angle1, zBottom, zBottom + segmentSize, radius, capOrigin, ringColor); + } +} + +void CNEOGhostCapturePoint::DrawSegment(CMeshBuilder& builder, float angle0, float angle1, float zBottom, float zTop, float radius, Vector capOrigin, Color ringColor) { + const float cos0 = cosf(angle0), sin0 = sinf(angle0); + const float cos1 = cosf(angle1), sin1 = sinf(angle1); + + // Bottom at angle0 + builder.Position3f(capOrigin.x + cos0 * radius, capOrigin.y + sin0 * radius, zBottom); + builder.Normal3f(cos0, sin0, 0.0f); + builder.Color4ub(ringColor.r(), ringColor.g(), ringColor.b(), ringColor.a()); + builder.TexCoord2f(0, 0.0f, 1.0f); + builder.AdvanceVertex(); + + // Bottom at angle1 + builder.Position3f(capOrigin.x + cos1 * radius, capOrigin.y + sin1 * radius, zBottom); + builder.Normal3f(cos1, sin1, 0.0f); + builder.Color4ub(ringColor.r(), ringColor.g(), ringColor.b(), ringColor.a()); + builder.TexCoord2f(0, 1.0f, 1.0f); + builder.AdvanceVertex(); + + // Top at angle1 + builder.Position3f(capOrigin.x + cos1 * radius, capOrigin.y + sin1 * radius, zTop); + builder.Normal3f(cos1, sin1, 0.0f); + builder.Color4ub(ringColor.r(), ringColor.g(), ringColor.b(), ringColor.a()); + builder.TexCoord2f(0, 1.0f, 0.0f); + builder.AdvanceVertex(); + + // Top at angle0 + builder.Position3f(capOrigin.x + cos0 * radius, capOrigin.y + sin0 * radius, zTop); + builder.Normal3f(cos0, sin0, 0.0f); + builder.Color4ub(ringColor.r(), ringColor.g(), ringColor.b(), ringColor.a()); + builder.TexCoord2f(0, 0.0f, 0.0f); + builder.AdvanceVertex(); +} #endif void CNEOGhostCapturePoint::Precache(void) @@ -407,6 +491,12 @@ void CNEOGhostCapturePoint::Precache(void) BaseClass::Precache(); AddEFlags(EFL_FORCE_CHECK_TRANSMIT); + + #ifdef CLIENT_DLL + PrecacheMaterial("effects/cap_zone_ring"); + PrecacheMaterial("effects/cap_zone_ring_nsf"); + PrecacheMaterial("effects/cap_zone_ring_jinrai"); + #endif } #ifdef GAME_DLL diff --git a/src/game/shared/neo/neo_ghost_cap_point.h b/src/game/shared/neo/neo_ghost_cap_point.h index bc120be21..fd92c68c0 100644 --- a/src/game/shared/neo/neo_ghost_cap_point.h +++ b/src/game/shared/neo/neo_ghost_cap_point.h @@ -97,12 +97,17 @@ class CNEOGhostCapturePoint : public CBaseEntity CNEOHud_GhostCapPoint *m_pHUDCapPoint = nullptr; IMaterial *m_pRingMaterial = nullptr; + IMaterial* m_pRingNsfMaterial = nullptr; + IMaterial* m_pRingJinraiMaterial = nullptr; public: virtual bool ShouldDraw() override; virtual RenderGroup_t GetRenderGroup() override; virtual void GetRenderBoundsWorldspace(Vector& mins, Vector& maxs) override; virtual int DrawModel(int flags) override; + virtual void DrawBarRing(CMeshBuilder& builder, int segments, float zBottom, float segmentSize, float radius, Vector capOrigin, Color ringColor); + virtual void DrawLogoRing(CMeshBuilder& builder, int segments, float zBottom, float segmentSize, float radius, Vector capOrigin, Color ringColor); + virtual void DrawSegment(CMeshBuilder& builder, float angle0, float angle1, float zBottom, float zTop, float radius, Vector capOrigin, Color ringColor); #endif }; From 9a73e47bdf53f392127cdcea9cb8a8e537c7f7df Mon Sep 17 00:00:00 2001 From: "DESKTOP-CCL0V26\\DraGonM" Date: Tue, 8 Sep 2026 00:17:07 +0300 Subject: [PATCH 3/3] fix typo --- src/game/shared/neo/neo_ghost_cap_point.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/shared/neo/neo_ghost_cap_point.cpp b/src/game/shared/neo/neo_ghost_cap_point.cpp index 48469dbf2..99926e553 100644 --- a/src/game/shared/neo/neo_ghost_cap_point.cpp +++ b/src/game/shared/neo/neo_ghost_cap_point.cpp @@ -339,7 +339,7 @@ int CNEOGhostCapturePoint::DrawModel(int flags) { int cl_neo_cap_zone_edge_value = cl_neo_cap_zone_edge.GetInt(); - if (!m_bIsActive && !m_pRingMaterial || !m_pRingJinraiMaterial || !m_pRingNsfMaterial || cl_neo_cap_zone_edge_value == NEO_CAP_EDGE_OFF) { + if (!m_bIsActive || !m_pRingMaterial || !m_pRingJinraiMaterial || !m_pRingNsfMaterial || cl_neo_cap_zone_edge_value == NEO_CAP_EDGE_OFF) { return 0; }