Skip to content

Commit 5e8e3f3

Browse files
committed
Fix marker screen detection and click events
1 parent 22c54a1 commit 5e8e3f3

File tree

6 files changed

+109
-1
lines changed

6 files changed

+109
-1
lines changed

Client/mods/deathmatch/logic/CClientEntity.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1334,6 +1334,13 @@ bool CClientEntity::IsOnScreen()
13341334
{
13351335
return pEntity->IsOnScreen();
13361336
}
1337+
1338+
if (GetType() == CCLIENTMARKER)
1339+
{
1340+
CClientMarker* pMarker = static_cast<CClientMarker*>(this);
1341+
return pMarker->IsClientSideOnScreen();
1342+
}
1343+
13371344
return false;
13381345
}
13391346

Client/mods/deathmatch/logic/CClientEntity.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ enum eClientEntityType
8484

8585
class CEntity;
8686
class CClientColShape;
87+
class CClientMarker;
8788
class CClientPed;
8889
class CCustomData;
8990
class CElementGroup;

Client/mods/deathmatch/logic/CClientGame.cpp

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2325,6 +2325,55 @@ void CClientGame::ProcessServerControlBind(CControlFunctionBind* pBind)
23252325
m_pNetAPI->RPC(KEY_BIND, bitStream.pBitStream);
23262326
}
23272327

2328+
CClientEntity* CClientGame::CheckClientSideEntityClick(float fScreenX, float fScreenY)
2329+
{
2330+
if (!m_pMarkerManager)
2331+
return NULL;
2332+
2333+
CClientMarker* pClosestMarker = NULL;
2334+
float fClosestDist = 99999.9f;
2335+
2336+
CFastList<CClientMarker*>::const_iterator iter = m_pMarkerManager->m_Markers.begin();
2337+
for (; iter != m_pMarkerManager->m_Markers.end(); ++iter)
2338+
{
2339+
CClientMarker* pMarker = *iter;
2340+
if (pMarker && pMarker->IsStreamedIn() && pMarker->IsVisible())
2341+
{
2342+
CVector vecPosition;
2343+
pMarker->GetPosition(vecPosition);
2344+
2345+
CVector vecScreen;
2346+
g_pCore->GetGraphics()->CalcScreenCoors(&vecPosition, &vecScreen);
2347+
2348+
if (pMarker->IsClientSideOnScreen())
2349+
{
2350+
CSphere boundingSphere = pMarker->GetWorldBoundingSphere();
2351+
2352+
CVector vecEdgePos = boundingSphere.vecPosition;
2353+
vecEdgePos.fX += boundingSphere.fRadius;
2354+
2355+
CVector vecCenterScreen, vecEdgeScreen;
2356+
g_pCore->GetGraphics()->CalcScreenCoors(&boundingSphere.vecPosition, &vecCenterScreen);
2357+
g_pCore->GetGraphics()->CalcScreenCoors(&vecEdgePos, &vecEdgeScreen);
2358+
2359+
float fScreenRadius = abs(vecEdgeScreen.fX - vecCenterScreen.fX);
2360+
2361+
float fDistX = vecCenterScreen.fX - fScreenX;
2362+
float fDistY = vecCenterScreen.fY - fScreenY;
2363+
float fDist = sqrt(fDistX * fDistX + fDistY * fDistY);
2364+
2365+
if (fDist < fScreenRadius && fDist < fClosestDist)
2366+
{
2367+
fClosestDist = fDist;
2368+
pClosestMarker = pMarker;
2369+
}
2370+
}
2371+
}
2372+
}
2373+
2374+
return pClosestMarker;
2375+
}
2376+
23282377
bool CClientGame::ProcessMessageForCursorEvents(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
23292378
{
23302379
bool bCursorForcedVisible = g_pCore->IsCursorForcedVisible();
@@ -2419,6 +2468,17 @@ bool CClientGame::ProcessMessageForCursorEvents(HWND hwnd, UINT uMsg, WPARAM wPa
24192468
pColPoint->Destroy();
24202469
}
24212470

2471+
if (!pCollisionEntity)
2472+
{
2473+
CClientEntity* pClientSideEntity = CheckClientSideEntityClick((float)iX, (float)iY);
2474+
if (pClientSideEntity)
2475+
{
2476+
pCollisionEntity = pClientSideEntity;
2477+
if (!pClientSideEntity->IsLocalEntity())
2478+
CollisionEntityID = pClientSideEntity->GetID();
2479+
}
2480+
}
2481+
24222482
const char* szButton = NULL;
24232483
const char* szState = NULL;
24242484
switch (ucButtonHit)

Client/mods/deathmatch/logic/CClientGame.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,7 @@ class CClientGame
381381
void ProcessServerControlBind(CControlFunctionBind* pBind);
382382

383383
bool ProcessMessageForCursorEvents(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
384+
CClientEntity* CheckClientSideEntityClick(float fScreenX, float fScreenY);
384385
bool AreCursorEventsEnabled() { return m_bCursorEventsEnabled; }
385386
void SetCursorEventsEnabled(bool bCursorEventsEnabled) { m_bCursorEventsEnabled = bCursorEventsEnabled; }
386387

Client/mods/deathmatch/logic/CClientMarker.cpp

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ extern CClientGame* g_pClientGame;
1616
#define M_PI 3.14159265358979323846
1717
#endif
1818

19+
// Threshold for determining if a marker is considered on-screen.
20+
// The value 0.1f represents the minimum depth (Z value in screen coordinates) at which a marker is visible.
21+
// Markers with a screen Z value below this threshold are considered off-screen.
22+
constexpr float CLIENT_MARKER_ONSCREEN_THRESHOLD = 0.1f;
23+
1924
unsigned int CClientMarker::m_uiStreamedInMarkers = 0;
2025

2126
CClientMarker::CClientMarker(CClientManager* pManager, ElementID ID, int iMarkerType) : ClassInit(this), CClientStreamElement(pManager->GetMarkerStreamer(), ID)
@@ -322,7 +327,6 @@ void CClientMarker::SetSize(float fSize)
322327
break;
323328
}
324329
}
325-
326330
m_pMarker->SetSize(fSize);
327331
}
328332

@@ -540,3 +544,36 @@ void CClientMarker::SetIgnoreAlphaLimits(bool ignore)
540544
{
541545
m_pMarker->SetIgnoreAlphaLimits(ignore);
542546
}
547+
548+
bool CClientMarker::IsClientSideOnScreen()
549+
{
550+
if (!IsStreamedIn() || !IsVisible())
551+
return false;
552+
553+
CVector vecPosition;
554+
GetPosition(vecPosition);
555+
556+
CVector vecScreen;
557+
g_pCore->GetGraphics()->CalcScreenCoors(&vecPosition, &vecScreen);
558+
559+
if (vecScreen.fZ <= CLIENT_MARKER_ONSCREEN_THRESHOLD)
560+
return false;
561+
562+
float fResWidth = static_cast<float>(g_pCore->GetGraphics()->GetViewportWidth());
563+
float fResHeight = static_cast<float>(g_pCore->GetGraphics()->GetViewportHeight());
564+
565+
CSphere boundingSphere = GetWorldBoundingSphere();
566+
CVector vecEdgePos = boundingSphere.vecPosition;
567+
vecEdgePos.fX += boundingSphere.fRadius;
568+
569+
CVector vecEdgeScreen;
570+
g_pCore->GetGraphics()->CalcScreenCoors(&vecEdgePos, &vecEdgeScreen);
571+
572+
if (vecEdgeScreen.fZ <= CLIENT_MARKER_ONSCREEN_THRESHOLD)
573+
return true;
574+
575+
float fScreenRadius = fabs(vecEdgeScreen.fX - vecScreen.fX);
576+
577+
return (vecScreen.fX + fScreenRadius) >= 0.0f && (vecScreen.fX - fScreenRadius) <= fResWidth &&
578+
(vecScreen.fY + fScreenRadius) >= 0.0f && (vecScreen.fY - fScreenRadius) <= fResHeight;
579+
}

Client/mods/deathmatch/logic/CClientMarker.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ class CClientMarker final : public CClientStreamElement, private CClientColCallb
7777

7878
static bool IsLimitReached();
7979

80+
bool IsClientSideOnScreen();
81+
8082
CClientColShape* GetColShape() { return m_pCollision; }
8183

8284
void Callback_OnCollision(CClientColShape& Shape, CClientEntity& Entity);

0 commit comments

Comments
 (0)