From 5e8e3f396ef0b98ffaff14e318778a95f92e317b Mon Sep 17 00:00:00 2001 From: Mohab <133429578+MohabCodeX@users.noreply.github.com> Date: Thu, 14 Aug 2025 23:51:24 +0300 Subject: [PATCH 01/10] Fix marker screen detection and click events --- .../mods/deathmatch/logic/CClientEntity.cpp | 7 +++ Client/mods/deathmatch/logic/CClientEntity.h | 1 + Client/mods/deathmatch/logic/CClientGame.cpp | 60 +++++++++++++++++++ Client/mods/deathmatch/logic/CClientGame.h | 1 + .../mods/deathmatch/logic/CClientMarker.cpp | 39 +++++++++++- Client/mods/deathmatch/logic/CClientMarker.h | 2 + 6 files changed, 109 insertions(+), 1 deletion(-) diff --git a/Client/mods/deathmatch/logic/CClientEntity.cpp b/Client/mods/deathmatch/logic/CClientEntity.cpp index cc4ea3d7057..0b9cebd5246 100644 --- a/Client/mods/deathmatch/logic/CClientEntity.cpp +++ b/Client/mods/deathmatch/logic/CClientEntity.cpp @@ -1334,6 +1334,13 @@ bool CClientEntity::IsOnScreen() { return pEntity->IsOnScreen(); } + + if (GetType() == CCLIENTMARKER) + { + CClientMarker* pMarker = static_cast(this); + return pMarker->IsClientSideOnScreen(); + } + return false; } diff --git a/Client/mods/deathmatch/logic/CClientEntity.h b/Client/mods/deathmatch/logic/CClientEntity.h index 031c1418b8f..c961c79a779 100644 --- a/Client/mods/deathmatch/logic/CClientEntity.h +++ b/Client/mods/deathmatch/logic/CClientEntity.h @@ -84,6 +84,7 @@ enum eClientEntityType class CEntity; class CClientColShape; +class CClientMarker; class CClientPed; class CCustomData; class CElementGroup; diff --git a/Client/mods/deathmatch/logic/CClientGame.cpp b/Client/mods/deathmatch/logic/CClientGame.cpp index 49343f0c9e2..4b3ea233171 100644 --- a/Client/mods/deathmatch/logic/CClientGame.cpp +++ b/Client/mods/deathmatch/logic/CClientGame.cpp @@ -2325,6 +2325,55 @@ void CClientGame::ProcessServerControlBind(CControlFunctionBind* pBind) m_pNetAPI->RPC(KEY_BIND, bitStream.pBitStream); } +CClientEntity* CClientGame::CheckClientSideEntityClick(float fScreenX, float fScreenY) +{ + if (!m_pMarkerManager) + return NULL; + + CClientMarker* pClosestMarker = NULL; + float fClosestDist = 99999.9f; + + CFastList::const_iterator iter = m_pMarkerManager->m_Markers.begin(); + for (; iter != m_pMarkerManager->m_Markers.end(); ++iter) + { + CClientMarker* pMarker = *iter; + if (pMarker && pMarker->IsStreamedIn() && pMarker->IsVisible()) + { + CVector vecPosition; + pMarker->GetPosition(vecPosition); + + CVector vecScreen; + g_pCore->GetGraphics()->CalcScreenCoors(&vecPosition, &vecScreen); + + if (pMarker->IsClientSideOnScreen()) + { + CSphere boundingSphere = pMarker->GetWorldBoundingSphere(); + + CVector vecEdgePos = boundingSphere.vecPosition; + vecEdgePos.fX += boundingSphere.fRadius; + + CVector vecCenterScreen, vecEdgeScreen; + g_pCore->GetGraphics()->CalcScreenCoors(&boundingSphere.vecPosition, &vecCenterScreen); + g_pCore->GetGraphics()->CalcScreenCoors(&vecEdgePos, &vecEdgeScreen); + + float fScreenRadius = abs(vecEdgeScreen.fX - vecCenterScreen.fX); + + float fDistX = vecCenterScreen.fX - fScreenX; + float fDistY = vecCenterScreen.fY - fScreenY; + float fDist = sqrt(fDistX * fDistX + fDistY * fDistY); + + if (fDist < fScreenRadius && fDist < fClosestDist) + { + fClosestDist = fDist; + pClosestMarker = pMarker; + } + } + } + } + + return pClosestMarker; +} + bool CClientGame::ProcessMessageForCursorEvents(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { bool bCursorForcedVisible = g_pCore->IsCursorForcedVisible(); @@ -2419,6 +2468,17 @@ bool CClientGame::ProcessMessageForCursorEvents(HWND hwnd, UINT uMsg, WPARAM wPa pColPoint->Destroy(); } + if (!pCollisionEntity) + { + CClientEntity* pClientSideEntity = CheckClientSideEntityClick((float)iX, (float)iY); + if (pClientSideEntity) + { + pCollisionEntity = pClientSideEntity; + if (!pClientSideEntity->IsLocalEntity()) + CollisionEntityID = pClientSideEntity->GetID(); + } + } + const char* szButton = NULL; const char* szState = NULL; switch (ucButtonHit) diff --git a/Client/mods/deathmatch/logic/CClientGame.h b/Client/mods/deathmatch/logic/CClientGame.h index 0c33091763b..c24aba7324a 100644 --- a/Client/mods/deathmatch/logic/CClientGame.h +++ b/Client/mods/deathmatch/logic/CClientGame.h @@ -381,6 +381,7 @@ class CClientGame void ProcessServerControlBind(CControlFunctionBind* pBind); bool ProcessMessageForCursorEvents(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + CClientEntity* CheckClientSideEntityClick(float fScreenX, float fScreenY); bool AreCursorEventsEnabled() { return m_bCursorEventsEnabled; } void SetCursorEventsEnabled(bool bCursorEventsEnabled) { m_bCursorEventsEnabled = bCursorEventsEnabled; } diff --git a/Client/mods/deathmatch/logic/CClientMarker.cpp b/Client/mods/deathmatch/logic/CClientMarker.cpp index 7afc3c7311b..9e98f52dd77 100644 --- a/Client/mods/deathmatch/logic/CClientMarker.cpp +++ b/Client/mods/deathmatch/logic/CClientMarker.cpp @@ -16,6 +16,11 @@ extern CClientGame* g_pClientGame; #define M_PI 3.14159265358979323846 #endif +// Threshold for determining if a marker is considered on-screen. +// The value 0.1f represents the minimum depth (Z value in screen coordinates) at which a marker is visible. +// Markers with a screen Z value below this threshold are considered off-screen. +constexpr float CLIENT_MARKER_ONSCREEN_THRESHOLD = 0.1f; + unsigned int CClientMarker::m_uiStreamedInMarkers = 0; CClientMarker::CClientMarker(CClientManager* pManager, ElementID ID, int iMarkerType) : ClassInit(this), CClientStreamElement(pManager->GetMarkerStreamer(), ID) @@ -322,7 +327,6 @@ void CClientMarker::SetSize(float fSize) break; } } - m_pMarker->SetSize(fSize); } @@ -540,3 +544,36 @@ void CClientMarker::SetIgnoreAlphaLimits(bool ignore) { m_pMarker->SetIgnoreAlphaLimits(ignore); } + +bool CClientMarker::IsClientSideOnScreen() +{ + if (!IsStreamedIn() || !IsVisible()) + return false; + + CVector vecPosition; + GetPosition(vecPosition); + + CVector vecScreen; + g_pCore->GetGraphics()->CalcScreenCoors(&vecPosition, &vecScreen); + + if (vecScreen.fZ <= CLIENT_MARKER_ONSCREEN_THRESHOLD) + return false; + + float fResWidth = static_cast(g_pCore->GetGraphics()->GetViewportWidth()); + float fResHeight = static_cast(g_pCore->GetGraphics()->GetViewportHeight()); + + CSphere boundingSphere = GetWorldBoundingSphere(); + CVector vecEdgePos = boundingSphere.vecPosition; + vecEdgePos.fX += boundingSphere.fRadius; + + CVector vecEdgeScreen; + g_pCore->GetGraphics()->CalcScreenCoors(&vecEdgePos, &vecEdgeScreen); + + if (vecEdgeScreen.fZ <= CLIENT_MARKER_ONSCREEN_THRESHOLD) + return true; + + float fScreenRadius = fabs(vecEdgeScreen.fX - vecScreen.fX); + + return (vecScreen.fX + fScreenRadius) >= 0.0f && (vecScreen.fX - fScreenRadius) <= fResWidth && + (vecScreen.fY + fScreenRadius) >= 0.0f && (vecScreen.fY - fScreenRadius) <= fResHeight; +} diff --git a/Client/mods/deathmatch/logic/CClientMarker.h b/Client/mods/deathmatch/logic/CClientMarker.h index 4aee90b93d9..4baac43eba3 100644 --- a/Client/mods/deathmatch/logic/CClientMarker.h +++ b/Client/mods/deathmatch/logic/CClientMarker.h @@ -77,6 +77,8 @@ class CClientMarker final : public CClientStreamElement, private CClientColCallb static bool IsLimitReached(); + bool IsClientSideOnScreen(); + CClientColShape* GetColShape() { return m_pCollision; } void Callback_OnCollision(CClientColShape& Shape, CClientEntity& Entity); From 96d65338192561c3f181d34ed9e6101234de7997 Mon Sep 17 00:00:00 2001 From: Mohab <133429578+MohabCodeX@users.noreply.github.com> Date: Thu, 14 Aug 2025 23:57:26 +0300 Subject: [PATCH 02/10] Update --- Client/mods/deathmatch/logic/CClientMarker.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Client/mods/deathmatch/logic/CClientMarker.cpp b/Client/mods/deathmatch/logic/CClientMarker.cpp index 9e98f52dd77..47ad1e27cef 100644 --- a/Client/mods/deathmatch/logic/CClientMarker.cpp +++ b/Client/mods/deathmatch/logic/CClientMarker.cpp @@ -327,6 +327,7 @@ void CClientMarker::SetSize(float fSize) break; } } + m_pMarker->SetSize(fSize); } From a52e31c6307d6a39d0e92e89489a44b56808bc1c Mon Sep 17 00:00:00 2001 From: Mohab Date: Sun, 17 Aug 2025 00:11:32 +0300 Subject: [PATCH 03/10] update --- Client/mods/deathmatch/logic/CClientMarker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Client/mods/deathmatch/logic/CClientMarker.cpp b/Client/mods/deathmatch/logic/CClientMarker.cpp index 47ad1e27cef..e49bfebea2f 100644 --- a/Client/mods/deathmatch/logic/CClientMarker.cpp +++ b/Client/mods/deathmatch/logic/CClientMarker.cpp @@ -327,7 +327,7 @@ void CClientMarker::SetSize(float fSize) break; } } - + m_pMarker->SetSize(fSize); } From 592999845a8a327f9cdc71eee9c9038c62d88aa9 Mon Sep 17 00:00:00 2001 From: Mohab <133429578+MohabCodeX@users.noreply.github.com> Date: Tue, 19 Aug 2025 22:41:13 +0300 Subject: [PATCH 04/10] Refactor --- Client/mods/deathmatch/logic/CClientGame.cpp | 91 +++++++++++--------- 1 file changed, 49 insertions(+), 42 deletions(-) diff --git a/Client/mods/deathmatch/logic/CClientGame.cpp b/Client/mods/deathmatch/logic/CClientGame.cpp index 4b3ea233171..36a206bbcd0 100644 --- a/Client/mods/deathmatch/logic/CClientGame.cpp +++ b/Client/mods/deathmatch/logic/CClientGame.cpp @@ -2328,46 +2328,45 @@ void CClientGame::ProcessServerControlBind(CControlFunctionBind* pBind) CClientEntity* CClientGame::CheckClientSideEntityClick(float fScreenX, float fScreenY) { if (!m_pMarkerManager) - return NULL; - - CClientMarker* pClosestMarker = NULL; + return nullptr; + + CCamera* pCamera = g_pGame->GetCamera(); + CMatrix matCamera; + pCamera->GetMatrix(&matCamera); + CVector vecOrigin = matCamera.vPos; + + CVector vecTarget, vecScreen(fScreenX, fScreenY, 300.0f); + g_pCore->GetGraphics()->CalcWorldCoors(&vecScreen, &vecTarget); + + CVector vecRayDir = vecTarget - vecOrigin; + vecRayDir.Normalize(); + + CClientMarker* pClosestMarker = nullptr; float fClosestDist = 99999.9f; - CFastList::const_iterator iter = m_pMarkerManager->m_Markers.begin(); - for (; iter != m_pMarkerManager->m_Markers.end(); ++iter) + for (auto* pMarker : m_pMarkerManager->m_Markers) { - CClientMarker* pMarker = *iter; - if (pMarker && pMarker->IsStreamedIn() && pMarker->IsVisible()) - { - CVector vecPosition; - pMarker->GetPosition(vecPosition); - - CVector vecScreen; - g_pCore->GetGraphics()->CalcScreenCoors(&vecPosition, &vecScreen); + if (!pMarker || !pMarker->IsStreamedIn() || !pMarker->IsVisible()) + continue; - if (pMarker->IsClientSideOnScreen()) - { - CSphere boundingSphere = pMarker->GetWorldBoundingSphere(); - - CVector vecEdgePos = boundingSphere.vecPosition; - vecEdgePos.fX += boundingSphere.fRadius; - - CVector vecCenterScreen, vecEdgeScreen; - g_pCore->GetGraphics()->CalcScreenCoors(&boundingSphere.vecPosition, &vecCenterScreen); - g_pCore->GetGraphics()->CalcScreenCoors(&vecEdgePos, &vecEdgeScreen); - - float fScreenRadius = abs(vecEdgeScreen.fX - vecCenterScreen.fX); - - float fDistX = vecCenterScreen.fX - fScreenX; - float fDistY = vecCenterScreen.fY - fScreenY; - float fDist = sqrt(fDistX * fDistX + fDistY * fDistY); - - if (fDist < fScreenRadius && fDist < fClosestDist) - { - fClosestDist = fDist; - pClosestMarker = pMarker; - } - } + if (!pMarker->IsClientSideOnScreen()) + continue; + + CSphere boundingSphere = pMarker->GetWorldBoundingSphere(); + + CVector vecToSphere = boundingSphere.vecPosition - vecOrigin; + float fProjection = vecToSphere.DotProduct(&vecRayDir); + + if (fProjection <= 0.0f) + continue; + + CVector vecClosestPoint = vecOrigin + vecRayDir * fProjection; + float fDistanceToRay = (boundingSphere.vecPosition - vecClosestPoint).Length(); + + if (fDistanceToRay <= boundingSphere.fRadius && fProjection < fClosestDist) + { + fClosestDist = fProjection; + pClosestMarker = pMarker; } } @@ -2441,7 +2440,11 @@ bool CClientGame::ProcessMessageForCursorEvents(HWND hwnd, UINT uMsg, WPARAM wPa CVector vecCollision; ElementID CollisionEntityID = INVALID_ELEMENT_ID; - CClientEntity* pCollisionEntity = NULL; + CClientEntity* pCollisionEntity = nullptr; + float fObjectDistance = 99999.9f; + + CClientEntity* pClientSideEntity = CheckClientSideEntityClick(static_cast(iX), static_cast(iY)); + if (bCollision && pColPoint) { vecCollision = pColPoint->GetPosition(); @@ -2451,6 +2454,7 @@ bool CClientGame::ProcessMessageForCursorEvents(HWND hwnd, UINT uMsg, WPARAM wPa CClientEntity* pEntity = pPools->GetClientEntity((DWORD*)pGameEntity->GetInterface()); if (pEntity) { + fObjectDistance = (vecCollision - vecOrigin).Length(); pCollisionEntity = pEntity; if (!pEntity->IsLocalEntity()) CollisionEntityID = pEntity->GetID(); @@ -2464,18 +2468,21 @@ bool CClientGame::ProcessMessageForCursorEvents(HWND hwnd, UINT uMsg, WPARAM wPa // Destroy the colpoint so we don't get a leak if (pColPoint) - { pColPoint->Destroy(); - } - if (!pCollisionEntity) + if (pClientSideEntity) { - CClientEntity* pClientSideEntity = CheckClientSideEntityClick((float)iX, (float)iY); - if (pClientSideEntity) + CVector vecMarkerPos; + pClientSideEntity->GetPosition(vecMarkerPos); + float fMarkerDistance = (vecMarkerPos - vecOrigin).Length(); + + if (fMarkerDistance < fObjectDistance) { pCollisionEntity = pClientSideEntity; if (!pClientSideEntity->IsLocalEntity()) CollisionEntityID = pClientSideEntity->GetID(); + + vecCollision = vecMarkerPos; } } From 148684ccfa4d1f2ddf65ce19895cc1f2702f7ca8 Mon Sep 17 00:00:00 2001 From: Mohab <133429578+MohabCodeX@users.noreply.github.com> Date: Thu, 21 Aug 2025 00:06:14 +0300 Subject: [PATCH 05/10] Add marker click detection --- Client/mods/deathmatch/logic/CClientGame.cpp | 55 +++++++++++-------- Client/mods/deathmatch/logic/CClientGame.h | 2 +- .../mods/deathmatch/logic/CClientMarker.cpp | 1 - 3 files changed, 32 insertions(+), 26 deletions(-) diff --git a/Client/mods/deathmatch/logic/CClientGame.cpp b/Client/mods/deathmatch/logic/CClientGame.cpp index 36a206bbcd0..115e3c2848a 100644 --- a/Client/mods/deathmatch/logic/CClientGame.cpp +++ b/Client/mods/deathmatch/logic/CClientGame.cpp @@ -73,6 +73,10 @@ CVector g_vecBulletFireEndPosition; #define DOUBLECLICK_TIMEOUT 330 #define DOUBLECLICK_MOVE_THRESHOLD 10.0f +// Ray casting constants for marker click detection +constexpr float MARKER_CLICK_RAY_DEPTH = 300.0f; // Screen-to-world ray projection depth +constexpr float MARKER_CLICK_MAX_DISTANCE = 99999.9f; // Maximum distance for closest marker comparison + static constexpr long long TIME_DISCORD_UPDATE_RATE = 15000; CClientGame::CClientGame(bool bLocalPlay) : m_ServerInfo(new CServerInfo()) @@ -2325,7 +2329,7 @@ void CClientGame::ProcessServerControlBind(CControlFunctionBind* pBind) m_pNetAPI->RPC(KEY_BIND, bitStream.pBitStream); } -CClientEntity* CClientGame::CheckClientSideEntityClick(float fScreenX, float fScreenY) +CClientMarker* CClientGame::CheckMarkerClick(float fScreenX, float fScreenY, float& fDistance) { if (!m_pMarkerManager) return nullptr; @@ -2335,14 +2339,14 @@ CClientEntity* CClientGame::CheckClientSideEntityClick(float fScreenX, float fSc pCamera->GetMatrix(&matCamera); CVector vecOrigin = matCamera.vPos; - CVector vecTarget, vecScreen(fScreenX, fScreenY, 300.0f); + CVector vecTarget, vecScreen(fScreenX, fScreenY, MARKER_CLICK_RAY_DEPTH); g_pCore->GetGraphics()->CalcWorldCoors(&vecScreen, &vecTarget); CVector vecRayDir = vecTarget - vecOrigin; vecRayDir.Normalize(); CClientMarker* pClosestMarker = nullptr; - float fClosestDist = 99999.9f; + float fClosestDist = MARKER_CLICK_MAX_DISTANCE; for (auto* pMarker : m_pMarkerManager->m_Markers) { @@ -2370,6 +2374,9 @@ CClientEntity* CClientGame::CheckClientSideEntityClick(float fScreenX, float fSc } } + if (pClosestMarker) + fDistance = fClosestDist; + return pClosestMarker; } @@ -2441,9 +2448,6 @@ bool CClientGame::ProcessMessageForCursorEvents(HWND hwnd, UINT uMsg, WPARAM wPa CVector vecCollision; ElementID CollisionEntityID = INVALID_ELEMENT_ID; CClientEntity* pCollisionEntity = nullptr; - float fObjectDistance = 99999.9f; - - CClientEntity* pClientSideEntity = CheckClientSideEntityClick(static_cast(iX), static_cast(iY)); if (bCollision && pColPoint) { @@ -2454,7 +2458,6 @@ bool CClientGame::ProcessMessageForCursorEvents(HWND hwnd, UINT uMsg, WPARAM wPa CClientEntity* pEntity = pPools->GetClientEntity((DWORD*)pGameEntity->GetInterface()); if (pEntity) { - fObjectDistance = (vecCollision - vecOrigin).Length(); pCollisionEntity = pEntity; if (!pEntity->IsLocalEntity()) CollisionEntityID = pEntity->GetID(); @@ -2470,22 +2473,6 @@ bool CClientGame::ProcessMessageForCursorEvents(HWND hwnd, UINT uMsg, WPARAM wPa if (pColPoint) pColPoint->Destroy(); - if (pClientSideEntity) - { - CVector vecMarkerPos; - pClientSideEntity->GetPosition(vecMarkerPos); - float fMarkerDistance = (vecMarkerPos - vecOrigin).Length(); - - if (fMarkerDistance < fObjectDistance) - { - pCollisionEntity = pClientSideEntity; - if (!pClientSideEntity->IsLocalEntity()) - CollisionEntityID = pClientSideEntity->GetID(); - - vecCollision = vecMarkerPos; - } - } - const char* szButton = NULL; const char* szState = NULL; switch (ucButtonHit) @@ -2524,6 +2511,25 @@ bool CClientGame::ProcessMessageForCursorEvents(HWND hwnd, UINT uMsg, WPARAM wPa if (std::isnan(vecCollision.fZ)) vecCollision.fZ = 0; + float fMarkerDistance = 0.0f; + CClientMarker* pClickedMarker = CheckMarkerClick(static_cast(iX), static_cast(iY), fMarkerDistance); + if (pClickedMarker) + { + CVector vecMarkerPosition; + pClickedMarker->GetPosition(vecMarkerPosition); + + CLuaArguments MarkerArguments; + MarkerArguments.PushString(szButton); + MarkerArguments.PushString(szState); + MarkerArguments.PushNumber(vecCursorPosition.fX); + MarkerArguments.PushNumber(vecCursorPosition.fY); + MarkerArguments.PushNumber(vecMarkerPosition.fX); + MarkerArguments.PushNumber(vecMarkerPosition.fY); + MarkerArguments.PushNumber(vecMarkerPosition.fZ); + MarkerArguments.PushNumber(fMarkerDistance); + pClickedMarker->CallEvent("onClientMarkerClick", MarkerArguments, false); + } + // Call the event for the client CLuaArguments Arguments; Arguments.PushString(szButton); @@ -2607,7 +2613,7 @@ bool CClientGame::ProcessMessageForCursorEvents(HWND hwnd, UINT uMsg, WPARAM wPa CVector2D vecResolution = g_pCore->GetGUI()->GetResolution(); CVector2D vecCursorPosition(((float)iX) / vecResolution.fX, ((float)iY) / vecResolution.fY); - CVector vecTarget, vecScreen((float)iX, (float)iY, 300.0f); + CVector vecTarget, vecScreen((float)iX, (float)iY, MARKER_CLICK_RAY_DEPTH); g_pCore->GetGraphics()->CalcWorldCoors(&vecScreen, &vecTarget); // Call the onClientCursorMove event @@ -2806,6 +2812,7 @@ void CClientGame::AddBuiltInEvents() // Marker events m_Events.AddEvent("onClientMarkerHit", "entity, matchingDimension", nullptr, false); m_Events.AddEvent("onClientMarkerLeave", "entity, matchingDimension", nullptr, false); + m_Events.AddEvent("onClientMarkerClick", "button, state, screenX, screenY, worldX, worldY, worldZ, distance", nullptr, false); m_Events.AddEvent("onClientPlayerMarkerHit", "marker, matchingDimension", nullptr, false); m_Events.AddEvent("onClientPlayerMarkerLeave", "marker, matchingDimension", nullptr, false); diff --git a/Client/mods/deathmatch/logic/CClientGame.h b/Client/mods/deathmatch/logic/CClientGame.h index c24aba7324a..3a0aaf58ca1 100644 --- a/Client/mods/deathmatch/logic/CClientGame.h +++ b/Client/mods/deathmatch/logic/CClientGame.h @@ -381,7 +381,7 @@ class CClientGame void ProcessServerControlBind(CControlFunctionBind* pBind); bool ProcessMessageForCursorEvents(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - CClientEntity* CheckClientSideEntityClick(float fScreenX, float fScreenY); + CClientMarker* CheckMarkerClick(float fScreenX, float fScreenY, float& fDistance); bool AreCursorEventsEnabled() { return m_bCursorEventsEnabled; } void SetCursorEventsEnabled(bool bCursorEventsEnabled) { m_bCursorEventsEnabled = bCursorEventsEnabled; } diff --git a/Client/mods/deathmatch/logic/CClientMarker.cpp b/Client/mods/deathmatch/logic/CClientMarker.cpp index e49bfebea2f..9e98f52dd77 100644 --- a/Client/mods/deathmatch/logic/CClientMarker.cpp +++ b/Client/mods/deathmatch/logic/CClientMarker.cpp @@ -327,7 +327,6 @@ void CClientMarker::SetSize(float fSize) break; } } - m_pMarker->SetSize(fSize); } From a468c719e393d4411a654ed892656f916e1dab8f Mon Sep 17 00:00:00 2001 From: Mohab <133429578+MohabCodeX@users.noreply.github.com> Date: Thu, 21 Aug 2025 00:09:17 +0300 Subject: [PATCH 06/10] Update --- Client/mods/deathmatch/logic/CClientMarker.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Client/mods/deathmatch/logic/CClientMarker.cpp b/Client/mods/deathmatch/logic/CClientMarker.cpp index 9e98f52dd77..e49bfebea2f 100644 --- a/Client/mods/deathmatch/logic/CClientMarker.cpp +++ b/Client/mods/deathmatch/logic/CClientMarker.cpp @@ -327,6 +327,7 @@ void CClientMarker::SetSize(float fSize) break; } } + m_pMarker->SetSize(fSize); } From bcf244bbb658005a6b60e0b663a6b038f347044e Mon Sep 17 00:00:00 2001 From: Mohab <133429578+MohabCodeX@users.noreply.github.com> Date: Thu, 21 Aug 2025 02:59:29 +0300 Subject: [PATCH 07/10] Update Client/mods/deathmatch/logic/CClientEntity.cpp Co-authored-by: Nico <122193236+Nico8340@users.noreply.github.com> --- Client/mods/deathmatch/logic/CClientEntity.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Client/mods/deathmatch/logic/CClientEntity.cpp b/Client/mods/deathmatch/logic/CClientEntity.cpp index 0b9cebd5246..038daddc6f0 100644 --- a/Client/mods/deathmatch/logic/CClientEntity.cpp +++ b/Client/mods/deathmatch/logic/CClientEntity.cpp @@ -1337,8 +1337,8 @@ bool CClientEntity::IsOnScreen() if (GetType() == CCLIENTMARKER) { - CClientMarker* pMarker = static_cast(this); - return pMarker->IsClientSideOnScreen(); + CClientMarker* marker = static_cast(this); + return marker->IsClientSideOnScreen(); } return false; From 98a926779e3645eb909cc0ce64ee20fb00cb8336 Mon Sep 17 00:00:00 2001 From: Mohab <133429578+MohabCodeX@users.noreply.github.com> Date: Thu, 21 Aug 2025 03:39:45 +0300 Subject: [PATCH 08/10] Refactor --- Client/mods/deathmatch/logic/CClientGame.cpp | 62 +++++++++---------- Client/mods/deathmatch/logic/CClientGame.h | 2 +- .../mods/deathmatch/logic/CClientMarker.cpp | 32 +++++----- Client/mods/deathmatch/logic/CClientMarker.h | 2 +- 4 files changed, 49 insertions(+), 49 deletions(-) diff --git a/Client/mods/deathmatch/logic/CClientGame.cpp b/Client/mods/deathmatch/logic/CClientGame.cpp index 115e3c2848a..f65fcafdf22 100644 --- a/Client/mods/deathmatch/logic/CClientGame.cpp +++ b/Client/mods/deathmatch/logic/CClientGame.cpp @@ -73,9 +73,9 @@ CVector g_vecBulletFireEndPosition; #define DOUBLECLICK_TIMEOUT 330 #define DOUBLECLICK_MOVE_THRESHOLD 10.0f -// Ray casting constants for marker click detection -constexpr float MARKER_CLICK_RAY_DEPTH = 300.0f; // Screen-to-world ray projection depth -constexpr float MARKER_CLICK_MAX_DISTANCE = 99999.9f; // Maximum distance for closest marker comparison +// Ray casting constants for click detection +constexpr float CLICK_RAY_DEPTH = 300.0f; // Screen-to-world ray projection depth +constexpr float MAX_CLICK_DISTANCE = 6000.0f; // Maximum distance for closest marker comparison static constexpr long long TIME_DISCORD_UPDATE_RATE = 15000; @@ -2329,55 +2329,55 @@ void CClientGame::ProcessServerControlBind(CControlFunctionBind* pBind) m_pNetAPI->RPC(KEY_BIND, bitStream.pBitStream); } -CClientMarker* CClientGame::CheckMarkerClick(float fScreenX, float fScreenY, float& fDistance) +CClientMarker* CClientGame::CheckMarkerClick(float screenX, float screenY, float& distance) noexcept { if (!m_pMarkerManager) return nullptr; - CCamera* pCamera = g_pGame->GetCamera(); - CMatrix matCamera; - pCamera->GetMatrix(&matCamera); - CVector vecOrigin = matCamera.vPos; + CCamera* camera = g_pGame->GetCamera(); + CMatrix cameraMatrix; + camera->GetMatrix(&cameraMatrix); + CVector origin = cameraMatrix.vPos; - CVector vecTarget, vecScreen(fScreenX, fScreenY, MARKER_CLICK_RAY_DEPTH); - g_pCore->GetGraphics()->CalcWorldCoors(&vecScreen, &vecTarget); + CVector target, screen(screenX, screenY, CLICK_RAY_DEPTH); + g_pCore->GetGraphics()->CalcWorldCoors(&screen, &target); - CVector vecRayDir = vecTarget - vecOrigin; - vecRayDir.Normalize(); + CVector rayDirection = target - origin; + rayDirection.Normalize(); - CClientMarker* pClosestMarker = nullptr; - float fClosestDist = MARKER_CLICK_MAX_DISTANCE; + CClientMarker* closestMarker = nullptr; + float closestDistance = MAX_CLICK_DISTANCE; - for (auto* pMarker : m_pMarkerManager->m_Markers) + for (auto* marker : m_pMarkerManager->m_Markers) { - if (!pMarker || !pMarker->IsStreamedIn() || !pMarker->IsVisible()) + if (!marker || !marker->IsStreamedIn() || !marker->IsVisible()) continue; - if (!pMarker->IsClientSideOnScreen()) + if (!marker->IsClientSideOnScreen()) continue; - CSphere boundingSphere = pMarker->GetWorldBoundingSphere(); + CSphere boundingSphere = marker->GetWorldBoundingSphere(); - CVector vecToSphere = boundingSphere.vecPosition - vecOrigin; - float fProjection = vecToSphere.DotProduct(&vecRayDir); + CVector toSphere = boundingSphere.vecPosition - origin; + float projection = toSphere.DotProduct(&rayDirection); - if (fProjection <= 0.0f) + if (projection <= 0.0f) continue; - CVector vecClosestPoint = vecOrigin + vecRayDir * fProjection; - float fDistanceToRay = (boundingSphere.vecPosition - vecClosestPoint).Length(); + CVector closestPoint = origin + rayDirection * projection; + float distanceToRay = (boundingSphere.vecPosition - closestPoint).Length(); - if (fDistanceToRay <= boundingSphere.fRadius && fProjection < fClosestDist) + if (distanceToRay <= boundingSphere.fRadius && projection < closestDistance) { - fClosestDist = fProjection; - pClosestMarker = pMarker; + closestDistance = projection; + closestMarker = marker; } } - if (pClosestMarker) - fDistance = fClosestDist; + if (closestMarker) + distance = closestDistance; - return pClosestMarker; + return closestMarker; } bool CClientGame::ProcessMessageForCursorEvents(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) @@ -2429,7 +2429,7 @@ bool CClientGame::ProcessMessageForCursorEvents(HWND hwnd, UINT uMsg, WPARAM wPa CVector2D vecCursorPosition((float)iX, (float)iY); - CVector vecOrigin, vecTarget, vecScreen((float)iX, (float)iY, 300.0f); + CVector vecOrigin, vecTarget, vecScreen((float)iX, (float)iY, CLICK_RAY_DEPTH); g_pCore->GetGraphics()->CalcWorldCoors(&vecScreen, &vecTarget); // Grab the camera position @@ -2613,7 +2613,7 @@ bool CClientGame::ProcessMessageForCursorEvents(HWND hwnd, UINT uMsg, WPARAM wPa CVector2D vecResolution = g_pCore->GetGUI()->GetResolution(); CVector2D vecCursorPosition(((float)iX) / vecResolution.fX, ((float)iY) / vecResolution.fY); - CVector vecTarget, vecScreen((float)iX, (float)iY, MARKER_CLICK_RAY_DEPTH); + CVector vecTarget, vecScreen((float)iX, (float)iY, CLICK_RAY_DEPTH); g_pCore->GetGraphics()->CalcWorldCoors(&vecScreen, &vecTarget); // Call the onClientCursorMove event diff --git a/Client/mods/deathmatch/logic/CClientGame.h b/Client/mods/deathmatch/logic/CClientGame.h index 3a0aaf58ca1..648d643ca84 100644 --- a/Client/mods/deathmatch/logic/CClientGame.h +++ b/Client/mods/deathmatch/logic/CClientGame.h @@ -381,7 +381,7 @@ class CClientGame void ProcessServerControlBind(CControlFunctionBind* pBind); bool ProcessMessageForCursorEvents(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - CClientMarker* CheckMarkerClick(float fScreenX, float fScreenY, float& fDistance); + CClientMarker* CheckMarkerClick(float screenX, float screenY, float& distance) noexcept; bool AreCursorEventsEnabled() { return m_bCursorEventsEnabled; } void SetCursorEventsEnabled(bool bCursorEventsEnabled) { m_bCursorEventsEnabled = bCursorEventsEnabled; } diff --git a/Client/mods/deathmatch/logic/CClientMarker.cpp b/Client/mods/deathmatch/logic/CClientMarker.cpp index e49bfebea2f..f9a0c44246d 100644 --- a/Client/mods/deathmatch/logic/CClientMarker.cpp +++ b/Client/mods/deathmatch/logic/CClientMarker.cpp @@ -546,35 +546,35 @@ void CClientMarker::SetIgnoreAlphaLimits(bool ignore) m_pMarker->SetIgnoreAlphaLimits(ignore); } -bool CClientMarker::IsClientSideOnScreen() +bool CClientMarker::IsClientSideOnScreen() noexcept { if (!IsStreamedIn() || !IsVisible()) return false; - CVector vecPosition; - GetPosition(vecPosition); + CVector position; + GetPosition(position); - CVector vecScreen; - g_pCore->GetGraphics()->CalcScreenCoors(&vecPosition, &vecScreen); + CVector screen; + g_pCore->GetGraphics()->CalcScreenCoors(&position, &screen); - if (vecScreen.fZ <= CLIENT_MARKER_ONSCREEN_THRESHOLD) + if (screen.fZ <= CLIENT_MARKER_ONSCREEN_THRESHOLD) return false; - float fResWidth = static_cast(g_pCore->GetGraphics()->GetViewportWidth()); - float fResHeight = static_cast(g_pCore->GetGraphics()->GetViewportHeight()); + float resWidth = static_cast(g_pCore->GetGraphics()->GetViewportWidth()); + float resHeight = static_cast(g_pCore->GetGraphics()->GetViewportHeight()); CSphere boundingSphere = GetWorldBoundingSphere(); - CVector vecEdgePos = boundingSphere.vecPosition; - vecEdgePos.fX += boundingSphere.fRadius; + CVector edgePos = boundingSphere.vecPosition; + edgePos.fX += boundingSphere.fRadius; - CVector vecEdgeScreen; - g_pCore->GetGraphics()->CalcScreenCoors(&vecEdgePos, &vecEdgeScreen); + CVector edgeScreen; + g_pCore->GetGraphics()->CalcScreenCoors(&edgePos, &edgeScreen); - if (vecEdgeScreen.fZ <= CLIENT_MARKER_ONSCREEN_THRESHOLD) + if (edgeScreen.fZ <= CLIENT_MARKER_ONSCREEN_THRESHOLD) return true; - float fScreenRadius = fabs(vecEdgeScreen.fX - vecScreen.fX); + float screenRadius = fabs(edgeScreen.fX - screen.fX); - return (vecScreen.fX + fScreenRadius) >= 0.0f && (vecScreen.fX - fScreenRadius) <= fResWidth && - (vecScreen.fY + fScreenRadius) >= 0.0f && (vecScreen.fY - fScreenRadius) <= fResHeight; + return (screen.fX + screenRadius) >= 0.0f && (screen.fX - screenRadius) <= resWidth && + (screen.fY + screenRadius) >= 0.0f && (screen.fY - screenRadius) <= resHeight; } diff --git a/Client/mods/deathmatch/logic/CClientMarker.h b/Client/mods/deathmatch/logic/CClientMarker.h index 4baac43eba3..6f09992a50b 100644 --- a/Client/mods/deathmatch/logic/CClientMarker.h +++ b/Client/mods/deathmatch/logic/CClientMarker.h @@ -77,7 +77,7 @@ class CClientMarker final : public CClientStreamElement, private CClientColCallb static bool IsLimitReached(); - bool IsClientSideOnScreen(); + bool IsClientSideOnScreen() noexcept; CClientColShape* GetColShape() { return m_pCollision; } From eb7bde58379d8c60b0d8462e5e91b8be58041061 Mon Sep 17 00:00:00 2001 From: Mohab <133429578+MohabCodeX@users.noreply.github.com> Date: Thu, 21 Aug 2025 03:45:04 +0300 Subject: [PATCH 09/10] Refactor --- Client/mods/deathmatch/logic/CClientGame.cpp | 32 ++++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Client/mods/deathmatch/logic/CClientGame.cpp b/Client/mods/deathmatch/logic/CClientGame.cpp index f65fcafdf22..de8af9e8de6 100644 --- a/Client/mods/deathmatch/logic/CClientGame.cpp +++ b/Client/mods/deathmatch/logic/CClientGame.cpp @@ -2447,7 +2447,7 @@ bool CClientGame::ProcessMessageForCursorEvents(HWND hwnd, UINT uMsg, WPARAM wPa CVector vecCollision; ElementID CollisionEntityID = INVALID_ELEMENT_ID; - CClientEntity* pCollisionEntity = nullptr; + CClientEntity* collisionEntity = nullptr; if (bCollision && pColPoint) { @@ -2458,7 +2458,7 @@ bool CClientGame::ProcessMessageForCursorEvents(HWND hwnd, UINT uMsg, WPARAM wPa CClientEntity* pEntity = pPools->GetClientEntity((DWORD*)pGameEntity->GetInterface()); if (pEntity) { - pCollisionEntity = pEntity; + collisionEntity = pEntity; if (!pEntity->IsLocalEntity()) CollisionEntityID = pEntity->GetID(); } @@ -2511,23 +2511,23 @@ bool CClientGame::ProcessMessageForCursorEvents(HWND hwnd, UINT uMsg, WPARAM wPa if (std::isnan(vecCollision.fZ)) vecCollision.fZ = 0; - float fMarkerDistance = 0.0f; - CClientMarker* pClickedMarker = CheckMarkerClick(static_cast(iX), static_cast(iY), fMarkerDistance); - if (pClickedMarker) + float markerDistance = 0.0f; + CClientMarker* clickedMarker = CheckMarkerClick(static_cast(iX), static_cast(iY), markerDistance); + if (clickedMarker) { - CVector vecMarkerPosition; - pClickedMarker->GetPosition(vecMarkerPosition); + CVector markerPosition; + clickedMarker->GetPosition(markerPosition); CLuaArguments MarkerArguments; MarkerArguments.PushString(szButton); MarkerArguments.PushString(szState); MarkerArguments.PushNumber(vecCursorPosition.fX); MarkerArguments.PushNumber(vecCursorPosition.fY); - MarkerArguments.PushNumber(vecMarkerPosition.fX); - MarkerArguments.PushNumber(vecMarkerPosition.fY); - MarkerArguments.PushNumber(vecMarkerPosition.fZ); - MarkerArguments.PushNumber(fMarkerDistance); - pClickedMarker->CallEvent("onClientMarkerClick", MarkerArguments, false); + MarkerArguments.PushNumber(markerPosition.fX); + MarkerArguments.PushNumber(markerPosition.fY); + MarkerArguments.PushNumber(markerPosition.fZ); + MarkerArguments.PushNumber(markerDistance); + clickedMarker->CallEvent("onClientMarkerClick", MarkerArguments, false); } // Call the event for the client @@ -2539,8 +2539,8 @@ bool CClientGame::ProcessMessageForCursorEvents(HWND hwnd, UINT uMsg, WPARAM wPa Arguments.PushNumber(vecCollision.fX); Arguments.PushNumber(vecCollision.fY); Arguments.PushNumber(vecCollision.fZ); - if (pCollisionEntity) - Arguments.PushElement(pCollisionEntity); + if (collisionEntity) + Arguments.PushElement(collisionEntity); else Arguments.PushBoolean(false); m_pRootEntity->CallEvent("onClientClick", Arguments, false); @@ -2583,8 +2583,8 @@ bool CClientGame::ProcessMessageForCursorEvents(HWND hwnd, UINT uMsg, WPARAM wPa DoubleClickArguments.PushNumber(vecCollision.fX); DoubleClickArguments.PushNumber(vecCollision.fY); DoubleClickArguments.PushNumber(vecCollision.fZ); - if (pCollisionEntity) - DoubleClickArguments.PushElement(pCollisionEntity); + if (collisionEntity) + DoubleClickArguments.PushElement(collisionEntity); else DoubleClickArguments.PushBoolean(false); m_pRootEntity->CallEvent("onClientDoubleClick", DoubleClickArguments, false); From 2e75412449cdaa2256b9c3464c6d0db42a814d25 Mon Sep 17 00:00:00 2001 From: Mohab <133429578+MohabCodeX@users.noreply.github.com> Date: Thu, 21 Aug 2025 07:17:38 +0300 Subject: [PATCH 10/10] format --- Client/mods/deathmatch/logic/CClientGame.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Client/mods/deathmatch/logic/CClientGame.cpp b/Client/mods/deathmatch/logic/CClientGame.cpp index 1639fc1230c..9f05e52be71 100644 --- a/Client/mods/deathmatch/logic/CClientGame.cpp +++ b/Client/mods/deathmatch/logic/CClientGame.cpp @@ -2339,7 +2339,8 @@ CClientMarker* CClientGame::CheckMarkerClick(float screenX, float screenY, float camera->GetMatrix(&cameraMatrix); CVector origin = cameraMatrix.vPos; - CVector target, screen(screenX, screenY, CLICK_RAY_DEPTH); + CVector target; + CVector screen(screenX, screenY, CLICK_RAY_DEPTH); g_pCore->GetGraphics()->CalcWorldCoors(&screen, &target); CVector rayDirection = target - origin;