Skip to content

Commit b2110d0

Browse files
committed
Added NPC PVS checking for point_cameras
1 parent a2e9175 commit b2110d0

3 files changed

Lines changed: 64 additions & 0 deletions

File tree

sp/src/game/server/ai_basenpc.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@
9898
#ifdef MAPBASE
9999
#include "mapbase/matchers.h"
100100
#include "items.h"
101+
#include "point_camera.h"
101102
#endif
102103

103104
#ifdef MAPBASE_VSCRIPT
@@ -4301,6 +4302,12 @@ bool CAI_BaseNPC::CheckPVSCondition()
43014302
{
43024303
bool bInPVS = ( UTIL_FindClientInPVS( edict() ) != NULL ) || (UTIL_ClientPVSIsExpanded() && UTIL_FindClientInVisibilityPVS( edict() ));
43034304

4305+
#ifdef MAPBASE
4306+
// We can be in a player's PVS if there is an active point_camera nearby (fixes issues with choreo)
4307+
if (!bInPVS && UTIL_FindRTCameraInEntityPVS( edict() ))
4308+
bInPVS = true;
4309+
#endif
4310+
43044311
if ( bInPVS )
43054312
SetCondition( COND_IN_PVS );
43064313
else

sp/src/game/server/point_camera.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,58 @@ CPointCamera* GetPointCameraList()
2828
return g_PointCameraList.m_pClassList;
2929
}
3030

31+
#ifdef MAPBASE
32+
//-----------------------------------------------------------------------------
33+
// Purpose: Returns true if a camera is in the PVS of the specified entity
34+
//-----------------------------------------------------------------------------
35+
edict_t *UTIL_FindRTCameraInEntityPVS( edict_t *pEdict )
36+
{
37+
CBaseEntity *pe = GetContainingEntity( pEdict );
38+
if ( !pe )
39+
return NULL;
40+
41+
bool bGotPVS = false;
42+
Vector org;
43+
static byte pvs[ MAX_MAP_CLUSTERS/8 ];
44+
static int pvssize = sizeof( pvs );
45+
46+
for ( CPointCamera *pCameraEnt = GetPointCameraList(); pCameraEnt != NULL; pCameraEnt = pCameraEnt->m_pNext )
47+
{
48+
if (!pCameraEnt->IsActive())
49+
continue;
50+
51+
if (!bGotPVS)
52+
{
53+
// Getting the PVS during the loop like this makes sure we only get the PVS if there's actually an active camera in the level
54+
org = pe->EyePosition();
55+
int clusterIndex = engine->GetClusterForOrigin( org );
56+
Assert( clusterIndex >= 0 );
57+
engine->GetPVSForCluster( clusterIndex, pvssize, pvs );
58+
bGotPVS = true;
59+
}
60+
61+
Vector vecCameraEye = pCameraEnt->EyePosition();
62+
63+
Vector vecCameraDirection;
64+
pCameraEnt->GetVectors( &vecCameraDirection, NULL, NULL );
65+
66+
Vector los = (org - vecCameraEye);
67+
float flDot = DotProduct( los, vecCameraDirection );
68+
69+
// Make sure we're in the camera's FOV before checking PVS
70+
if ( flDot <= cos( DEG2RAD( pCameraEnt->GetFOV() / 2 ) ) )
71+
continue;
72+
73+
if ( engine->CheckOriginInPVS( vecCameraEye, pvs, pvssize ) )
74+
{
75+
return pCameraEnt->edict();
76+
}
77+
}
78+
79+
return NULL;
80+
}
81+
#endif
82+
3183
// These are already built into CBaseEntity
3284
// DEFINE_KEYFIELD( m_iName, FIELD_STRING, "targetname" ),
3385
// DEFINE_KEYFIELD( m_iParent, FIELD_STRING, "parentname" ),

sp/src/game/server/point_camera.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ class CPointCamera : public CBaseEntity
4242
void InputSetRenderTarget( inputdata_t &inputdata ) { m_iszRenderTarget = inputdata.value.StringID(); }
4343

4444
float GetFOV() const { return m_FOV; }
45+
bool IsActive() const { return m_bIsOn; }
4546
#endif
4647

4748
private:
@@ -117,4 +118,8 @@ class CPointCameraOrtho : public CPointCamera
117118
#endif
118119

119120
CPointCamera *GetPointCameraList();
121+
122+
#ifdef MAPBASE
123+
edict_t *UTIL_FindRTCameraInEntityPVS( edict_t *pEdict );
124+
#endif
120125
#endif // CAMERA_H

0 commit comments

Comments
 (0)