fix(multiplayer): Fix a crash when player gets near a portal in multiplayer.

fix(crowbar): Fix crowbar not hitting through portals.

chore(util): Added UTIL_GetNearestPlayer function from valve developer wiki.

Made this a month ago and didn't really test anything now.
A lot of useless portal ray traces.
This commit is contained in:
tupoy-ya 2023-05-19 21:36:42 +05:00
parent 398645a181
commit cd2241af21
No known key found for this signature in database
GPG Key ID: 3541E2B1B448A2DB
6 changed files with 76 additions and 34 deletions

View File

@ -306,7 +306,17 @@ void CBaseHLBludgeonWeapon::Swing( int bIsSecondary )
forward = pOwner->GetAutoaimVector( AUTOAIM_SCALE_DEFAULT, GetRange() );
Vector swingEnd = swingStart + forward * GetRange();
#ifdef PORTAL
Ray_t rayPath;
CTraceFilterSkipTwoEntities m_filterBeams( pOwner, NULL, COLLISION_GROUP_NONE );
rayPath.Init( swingStart, swingEnd );
g_bBulletPortalTrace = true; // Why is this a global???
UTIL_Portal_TraceRay( rayPath, MASK_SHOT_HULL, &m_filterBeams, &traceHit );
g_bBulletPortalTrace = false;
#else
UTIL_TraceLine( swingStart, swingEnd, MASK_SHOT_HULL, pOwner, COLLISION_GROUP_NONE, &traceHit );
#endif // PORTAL
Activity nHitActivity = ACT_VM_HITCENTER;
// Like bullets, bludgeon traces have to trace against triggers.

View File

@ -702,8 +702,7 @@ void CWeaponGravityGun::EffectUpdate( void )
#ifdef PORTAL
Ray_t rayPath;
CTraceFilterSkipTwoEntities m_filterBeams( NULL, NULL, COLLISION_GROUP_NONE );
m_filterBeams.SetPassEntity( pOwner );
CTraceFilterSkipTwoEntities m_filterBeams( pOwner, NULL, COLLISION_GROUP_NONE );
rayPath.Init( start, end );
g_bBulletPortalTrace = true; // Why is this a global???
@ -787,12 +786,12 @@ void CWeaponGravityGun::EffectUpdate( void )
#ifdef PORTAL
Ray_t rayPath;
CTraceFilterSkipTwoEntities m_filterBeams( NULL, NULL, COLLISION_GROUP_NONE );
m_filterBeams.SetPassEntity( pOwner );
CTraceFilterSkipTwoEntities m_filterBeams( pOwner, NULL, COLLISION_GROUP_NONE );
rayPath.Init( start, awayfromPlayer );
g_bBulletPortalTrace = true; // Why is this a global???
UTIL_Portal_TraceRay(rayPath, MASK_SOLID, &m_filterBeams, &tr);
g_bBulletPortalTrace = false;
#else
UTIL_TraceLine( start, awayfromPlayer, MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &tr );
#endif
@ -801,16 +800,18 @@ void CWeaponGravityGun::EffectUpdate( void )
#ifdef PORTAL
rayPath.Init( awayfromPlayer, newPosition );
m_filterBeams.SetPassEntity( pObject );
g_bBulletPortalTrace = true; // Why is this a global???
UTIL_Portal_TraceRay(rayPath, MASK_SOLID, &m_filterBeams, &tr);
g_bBulletPortalTrace = false;
#else
UTIL_TraceLine( awayfromPlayer, newPosition, MASK_SOLID, pObject, COLLISION_GROUP_NONE, &tr );
#endif
Vector dir = tr.endpos - newPosition;
float distance = VectorNormalize(dir);
float distance = VectorNormalize(tr.endpos);
float maxDist = m_gravCallback.m_maxVel * gpGlobals->frametime;
if ( distance > maxDist )
if ( distance > maxDist )
{
newPosition += dir * maxDist;
newPosition += tr.endpos * maxDist;
}
else
{
@ -821,7 +822,6 @@ void CWeaponGravityGun::EffectUpdate( void )
{
newPosition = tr.endpos;
}
g_bBulletPortalTrace = false;
CreatePelletAttraction( phys_gunglueradius.GetFloat(), pObject );
@ -1322,8 +1322,7 @@ void CWeaponGravityGun::SecondaryAttack( void )
trace_t tr;
#ifdef PORTAL
Ray_t rayPath;
CTraceFilterSkipTwoEntities m_filterBeams( NULL, NULL, COLLISION_GROUP_NONE );
m_filterBeams.SetPassEntity( pOwner );
CTraceFilterSkipTwoEntities m_filterBeams( pOwner, NULL, COLLISION_GROUP_NONE );
rayPath.Init( start, end );
g_bBulletPortalTrace = true; // Why is this a global???

View File

@ -221,24 +221,28 @@ protected:
//-----------------------------------------------------------------------------
void UTIL_PhyscannonTraceLine( const Vector &vecAbsStart, const Vector &vecAbsEnd, CBaseEntity *pTraceOwner, trace_t *pTrace )
{
Ray_t ray;
// Default to HL2 vanilla
if ( hl2_episodic.GetBool() == false )
{
CTraceFilterNoOwnerTest filter( pTraceOwner, COLLISION_GROUP_NONE );
UTIL_TraceLine( vecAbsStart, vecAbsEnd, (MASK_SHOT|CONTENTS_GRATE), &filter, pTrace );
ray.Init( vecAbsStart, vecAbsEnd );
UTIL_Portal_TraceRay(ray, (MASK_SHOT|CONTENTS_GRATE), &filter, pTrace);
return;
}
// First, trace against entities
CTraceFilterPhyscannon filter( pTraceOwner, COLLISION_GROUP_NONE );
UTIL_TraceLine( vecAbsStart, vecAbsEnd, (MASK_SHOT|CONTENTS_GRATE), &filter, pTrace );
ray.Init( vecAbsStart, vecAbsEnd );
UTIL_Portal_TraceRay(ray, (MASK_SHOT|CONTENTS_GRATE), &filter, pTrace);
// If we've hit something, test again to make sure no brushes block us
if ( pTrace->m_pEnt != NULL )
{
trace_t testTrace;
CTraceFilterOnlyBrushes brushFilter( COLLISION_GROUP_NONE );
UTIL_TraceLine( pTrace->startpos, pTrace->endpos, MASK_SHOT, &brushFilter, &testTrace );
ray.Init( pTrace->startpos, pTrace->endpos );
UTIL_Portal_TraceRay(ray, MASK_SHOT, &brushFilter, &testTrace);
// If we hit a brush, replace the trace with that result
if ( testTrace.fraction < 1.0f || testTrace.startsolid || testTrace.allsolid )

View File

@ -657,6 +657,44 @@ CBasePlayer *UTIL_GetListenServerHost( void )
return UTIL_PlayerByIndex( 1 );
}
//
// Returns nearest player.
// Control with boolean if line of sight is needed.
// Taken from https://developer.valvesoftware.com/wiki/GetLocalPlayer
CBasePlayer *UTIL_GetNearestPlayer(CBaseEntity *pLooker, bool bNeedsLOS)
{
float flFinalDistance = 99999.0f;
CBasePlayer *pFinalPlayer = NULL;
for (int i = 1; i < gpGlobals->maxClients; i++)
{
CBasePlayer *pPlayer = UTIL_PlayerByIndex(i);
if (!pPlayer){
continue;
}
float flDistance = (pPlayer->GetAbsOrigin() - pLooker->GetAbsOrigin()).LengthSqr();
if (flDistance < flFinalDistance)
{
if (bNeedsLOS)
{
//Check if the player is visible to the entity (only brushes obstruct vision)
if (!pLooker->FVisible(pPlayer, MASK_SOLID_BRUSHONLY))
{
continue;
}
}
pFinalPlayer = pPlayer;
flFinalDistance = flDistance;
}
}
return pFinalPlayer;
}
//--------------------------------------------------------------------------------------------------------------
/**

View File

@ -231,6 +231,8 @@ CBasePlayer* UTIL_GetLocalPlayer( void );
// get the local player on a listen server
CBasePlayer *UTIL_GetListenServerHost( void );
CBasePlayer *UTIL_GetNearestPlayer(CBaseEntity *pLooker, bool needsLOS = false);
CBasePlayer* UTIL_PlayerByUserId( int userID );
CBasePlayer* UTIL_PlayerByName( const char *name ); // not case sensitive

View File

@ -104,7 +104,6 @@ static CPhysCollide *ConvertPolyhedronsToCollideable( CPolyhedron **pPolyhedrons
#ifndef CLIENT_DLL
static void UpdateShadowClonesPortalSimulationFlags( const CBaseEntity *pSourceEntity, unsigned int iFlags, int iSourceFlags );
static bool g_bPlayerIsInSimulator = false;
#endif
static CUtlVector<CPortalSimulator *> s_PortalSimulators;
@ -1099,11 +1098,6 @@ void CPortalSimulator::MarkAsOwned( CBaseEntity *pEntity )
m_InternalData.Simulation.Dynamic.EntFlags[iEntIndex] |= PSEF_OWNS_ENTITY;
s_OwnedEntityMap[iEntIndex] = this;
m_InternalData.Simulation.Dynamic.OwnedEntities.AddToTail( pEntity );
if ( pEntity->IsPlayer() )
{
g_bPlayerIsInSimulator = true;
}
}
void CPortalSimulator::MarkAsReleased( CBaseEntity *pEntity )
@ -1125,12 +1119,6 @@ void CPortalSimulator::MarkAsReleased( CBaseEntity *pEntity )
}
}
Assert( i >= 0 );
if ( pEntity->IsPlayer() )
{
g_bPlayerIsInSimulator = false;
}
}
@ -2454,20 +2442,21 @@ void CPortalSimulator::PrePhysFrame( void )
}
}
// Taken from portal 2.
void CPortalSimulator::PostPhysFrame( void )
{
if ( g_bPlayerIsInSimulator )
for( int i = 1; i <= gpGlobals->maxClients; ++i )
{
CPortal_Player* pPlayer = dynamic_cast<CPortal_Player*>( UTIL_GetLocalPlayer() );
CProp_Portal* pTouchedPortal = pPlayer->m_hPortalEnvironment.Get();
CPortalSimulator* pSim = GetSimulatorThatOwnsEntity( pPlayer );
if ( pTouchedPortal && pSim && (pTouchedPortal->m_PortalSimulator.GetPortalSimulatorGUID() != pSim->GetPortalSimulatorGUID()) )
CPortal_Player* pPlayer = (CPortal_Player *)UTIL_PlayerByIndex( i );
if( pPlayer )
{
Warning ( "Player is simulated in a physics environment but isn't touching a portal! Can't teleport, but can fall through portal hole. Returning player to main environment.\n" );
ADD_DEBUG_HISTORY( HISTORY_PLAYER_DAMAGE, UTIL_VarArgs( "Player in PortalSimulator but not touching a portal, removing from sim at : %f\n", gpGlobals->curtime ) );
if ( pSim )
CProp_Portal* pTouchedPortal = pPlayer->m_hPortalEnvironment.Get();
CPortalSimulator* pSim = GetSimulatorThatOwnsEntity( pPlayer );
if ( pTouchedPortal && pSim && (pTouchedPortal->m_PortalSimulator.GetPortalSimulatorGUID() != pSim->GetPortalSimulatorGUID()) )
{
Warning ( "Player is simulated in a physics environment but isn't touching a portal! Can't teleport, but can fall through portal hole. Returning player to main environment.\n" );
ADD_DEBUG_HISTORY( HISTORY_PLAYER_DAMAGE, UTIL_VarArgs( "Player in PortalSimulator but not touching a portal, removing from sim at : %f\n", gpGlobals->curtime ) );
pSim->ReleaseOwnershipOfEntity( pPlayer, false );
}
}