Skip to content

Commit

Permalink
add bitfield to indicate which players can see an entity
Browse files Browse the repository at this point in the history
accounts for AddToFullPack checks beyond the PVS/PAS checks, to truly know if a player is able to see an entity
  • Loading branch information
wootguy committed Nov 8, 2024
1 parent 0b22c5e commit b30af61
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 25 deletions.
8 changes: 0 additions & 8 deletions dlls/CBaseEntity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -986,12 +986,4 @@ bool CBaseEntity::CanReach(CBaseEntity* toucher) {
bool enteredItemBox = boxesIntersect(pev->absmin, pev->absmax, tr.vecEndPos, tr.vecEndPos);

return hitItemSurface || enteredItemBox;
}

bool CBaseEntity::IsVisibleTo(edict_t* player) {
return m_visiblePlayers & PLRBIT(player);
}

bool CBaseEntity::IsAudibleTo(edict_t* player) {
return m_audiblePlayers & PLRBIT(player);
}
16 changes: 10 additions & 6 deletions dlls/cbase.h
Original file line number Diff line number Diff line change
Expand Up @@ -389,11 +389,14 @@ class EXPORT CBaseEntity
// or is there something in the way? (player use code assumes arms have noclip)
bool CanReach(CBaseEntity* toucher);

// true if the player can potentially see this entity
bool IsVisibleTo(edict_t* player);
// true if this entity is in the PVS of the given player
inline bool InPVS(edict_t* player) { return m_pvsPlayers & PLRBIT(player); }

// true if the player can potentially hear this entity
bool IsAudibleTo(edict_t* player);
// true if the entity is in the PAS of the given player
inline bool InPAS(edict_t* player) { return m_pasPlayers & PLRBIT(player); }

// true if the entity is networked to the given player
inline bool isVisibleTo(edict_t* player) { return m_netPlayers & PLRBIT(player); }

//We use this variables to store each ammo count.
int ammo_9mm;
Expand All @@ -414,8 +417,9 @@ class EXPORT CBaseEntity
int m_fireState;
int m_Classify; // Classify, to let mappers override the default

uint32_t m_audiblePlayers; // players in the audible set of this entity (invalid for invisible ents)
uint32_t m_visiblePlayers; // players in the visible set of this entity (invalid for invisible ents)
uint32_t m_pasPlayers; // players in the audible set of this entity (invalid for invisible ents)
uint32_t m_pvsPlayers; // players in the visible set of this entity (invalid for invisible ents)
uint32_t m_netPlayers; // players this entity has been networked to (AddToFullPack returned 1)
};


Expand Down
16 changes: 10 additions & 6 deletions dlls/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,9 @@ void ClientDisconnect( edict_t *pEntity )

CBaseEntity* ent = (CBaseEntity*)GET_PRIVATE(&edicts[i]);
if (ent) {
ent->m_visiblePlayers &= ~plrbit;
ent->m_audiblePlayers &= ~plrbit;
ent->m_pvsPlayers &= ~plrbit;
ent->m_pasPlayers &= ~plrbit;
ent->m_netPlayers &= ~plrbit;
}
}

Expand Down Expand Up @@ -1093,8 +1094,9 @@ int AddToFullPack( struct entity_state_s *state, int e, edict_t *ent, edict_t *h
return 0; // should never happen?

uint32_t plrbit = PLRBIT(host);
baseent->m_audiblePlayers &= ~plrbit;
baseent->m_visiblePlayers &= ~plrbit;
baseent->m_pvsPlayers &= ~plrbit;
baseent->m_pasPlayers &= ~plrbit;
baseent->m_netPlayers &= ~plrbit;

// don't send if flagged for NODRAW and it's not the host getting the message
// Ignore ents without valid / visible models
Expand All @@ -1114,11 +1116,11 @@ int AddToFullPack( struct entity_state_s *state, int e, edict_t *ent, edict_t *h
return 0; // should never happen?

if (ENGINE_CHECK_VISIBILITY((const struct edict_s*)ent, plr->m_lastPas)) {
baseent->m_audiblePlayers |= plrbit;
baseent->m_pasPlayers |= plrbit;
}

if (ENGINE_CHECK_VISIBILITY((const struct edict_s*)ent, plr->m_lastPvs)) {
baseent->m_visiblePlayers |= plrbit;
baseent->m_pvsPlayers |= plrbit;
}
else if(ent != host) {
// Ignore if not the host and not touching a PVS leaf
Expand Down Expand Up @@ -1302,6 +1304,8 @@ int AddToFullPack( struct entity_state_s *state, int e, edict_t *ent, edict_t *h
else
state->eflags &= ~EFLAG_FLESH_SOUND;

baseent->m_netPlayers |= plrbit;

return 1;
}

Expand Down
4 changes: 2 additions & 2 deletions dlls/sound.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -627,7 +627,7 @@ void EMIT_SOUND_DYN(edict_t *entity, int channel, const char *sample, float volu
continue;
}

if (isStatic && !bent->IsVisibleTo(plr)) {
if (isStatic && !bent->InPAS(plr)) {
ambientsound_msg(entity, ori, sample, volume, attenuation, flags, pitch, MSG_ONE, plr);
}
else {
Expand Down Expand Up @@ -698,7 +698,7 @@ void PLAY_DISTANT_SOUND(edict_t* emitter, int soundType) {

// if listener is in the audible set and too close, don't play the sound.
// otherwise, the player may be close, but on the other side of a wall, so they should hear the sound
if ((baseEmitter->m_audiblePlayers & pbit) && (ent->v.origin - emitter->v.origin).Length() < minRange) {
if (baseEmitter->InPAS(ent) && (ent->v.origin - emitter->v.origin).Length() < minRange) {
continue;
}

Expand Down
6 changes: 3 additions & 3 deletions dlls/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -702,7 +702,7 @@ edict_t* UTIL_ClientsInPVS(edict_t* edict, int& playerCount) {

bool UTIL_IsClientInPVS(edict_t* edict) {
CBaseEntity* ent = (CBaseEntity*)GET_PRIVATE(edict);
return ent && ent->m_visiblePlayers;
return ent && ent->m_pvsPlayers;
}

bool IsValidPlayer(edict_t* edict) {
Expand Down Expand Up @@ -834,10 +834,10 @@ bool TestMsgVis(edict_t* plr, int testEntIdx, int netMsgMode) {
switch (netMsgMode) {
case MSG_PVS:
case MSG_PVS_R:
return ent->IsVisibleTo(plr);
return ent->InPVS(plr);
case MSG_PAS:
case MSG_PAS_R:
return ent->IsAudibleTo(plr);
return ent->InPAS(plr);
default:
return true;
}
Expand Down

0 comments on commit b30af61

Please sign in to comment.