upload "kind" alien swarm

This commit is contained in:
nillerusr
2023-10-03 17:23:56 +03:00
parent b7bd94c52e
commit 7d3c0d8b5a
4229 changed files with 462903 additions and 495158 deletions

View File

@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Utility code.
//
@@ -35,19 +35,18 @@
#include "engine/ivdebugoverlay.h"
#include "datacache/imdlcache.h"
#include "util.h"
#include "cdll_int.h"
#ifdef PORTAL
#include "PortalSimulation.h"
//#include "Portal_PhysicsEnvironmentMgr.h"
#endif
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern short g_sModelIndexSmoke; // (in combatweapon.cpp) holds the index for the smoke cloud
extern short g_sModelIndexBloodDrop; // (in combatweapon.cpp) holds the sprite index for the initial blood
extern short g_sModelIndexBloodSpray; // (in combatweapon.cpp) holds the sprite index for splattered blood
extern int g_sModelIndexSmoke; // (in combatweapon.cpp) holds the index for the smoke cloud
extern int g_sModelIndexBloodDrop; // (in combatweapon.cpp) holds the sprite index for the initial blood
extern int g_sModelIndexBloodSpray; // (in combatweapon.cpp) holds the sprite index for splattered blood
// this is true if the engine should be sent log output. Once per frame it is rechecked to see if logging has been enabled.
bool g_bIsLogging = true;
#ifdef DEBUG
void DBG_AssertFunction( bool fExpr, const char *szExpr, const char *szFile, int szLine, const char *szMessage )
@@ -59,7 +58,7 @@ void DBG_AssertFunction( bool fExpr, const char *szExpr, const char *szFile, int
Q_snprintf(szOut,sizeof(szOut), "ASSERT FAILED:\n %s \n(%s@%d)\n%s", szExpr, szFile, szLine, szMessage);
else
Q_snprintf(szOut,sizeof(szOut), "ASSERT FAILED:\n %s \n(%s@%d)\n", szExpr, szFile, szLine);
Warning( "%s", szOut );
Warning( szOut);
}
#endif // DEBUG
@@ -95,9 +94,6 @@ IEntityFactoryDictionary *EntityFactoryDictionary()
void DumpEntityFactories_f()
{
if ( !UTIL_IsCommandIssuedByServerAdmin() )
return;
CEntityFactoryDictionary *dict = ( CEntityFactoryDictionary * )EntityFactoryDictionary();
if ( dict )
{
@@ -116,9 +112,6 @@ static ConCommand dumpentityfactories( "dumpentityfactories", DumpEntityFactorie
//-----------------------------------------------------------------------------
CON_COMMAND( dump_entity_sizes, "Print sizeof(entclass)" )
{
if ( !UTIL_IsCommandIssuedByServerAdmin() )
return;
((CEntityFactoryDictionary*)EntityFactoryDictionary())->ReportEntitySizes();
}
@@ -148,7 +141,7 @@ IEntityFactory *CEntityFactoryDictionary::FindFactory( const char *pClassName )
//-----------------------------------------------------------------------------
void CEntityFactoryDictionary::InstallFactory( IEntityFactory *pFactory, const char *pClassName )
{
Assert( FindFactory( pClassName ) == NULL );
AssertMsg1( FindFactory( pClassName ) == NULL, "Double installation of factory for %s", pClassName );
m_Factories.Insert( pClassName, pFactory );
}
@@ -205,46 +198,6 @@ void CEntityFactoryDictionary::ReportEntitySizes()
}
//-----------------------------------------------------------------------------
// class CFlaggedEntitiesEnum
//-----------------------------------------------------------------------------
CFlaggedEntitiesEnum::CFlaggedEntitiesEnum( CBaseEntity **pList, int listMax, int flagMask )
{
m_pList = pList;
m_listMax = listMax;
m_flagMask = flagMask;
m_count = 0;
}
bool CFlaggedEntitiesEnum::AddToList( CBaseEntity *pEntity )
{
if ( m_count >= m_listMax )
{
AssertMsgOnce( 0, "reached enumerated list limit. Increase limit, decrease radius, or make it so entity flags will work for you" );
return false;
}
m_pList[m_count] = pEntity;
m_count++;
return true;
}
IterationRetval_t CFlaggedEntitiesEnum::EnumElement( IHandleEntity *pHandleEntity )
{
CBaseEntity *pEntity = gEntList.GetBaseEntity( pHandleEntity->GetRefEHandle() );
if ( pEntity )
{
if ( m_flagMask && !(pEntity->GetFlags() & m_flagMask) ) // Does it meet the criteria?
return ITERATION_CONTINUE;
if ( !AddToList( pEntity ) )
return ITERATION_STOP;
}
return ITERATION_CONTINUE;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
@@ -283,12 +236,6 @@ int UTIL_EntitiesInBox( const Vector &mins, const Vector &maxs, CFlaggedEntities
return pEnum->GetCount();
}
int UTIL_EntitiesAlongRay( const Ray_t &ray, CFlaggedEntitiesEnum *pEnum )
{
partition->EnumerateElementsAlongRay( PARTITION_ENGINE_NON_STATIC_EDICTS, ray, false, pEnum );
return pEnum->GetCount();
}
int UTIL_EntitiesInSphere( const Vector &center, float radius, CFlaggedEntitiesEnum *pEnum )
{
partition->EnumerateElementsInSphere( PARTITION_ENGINE_NON_STATIC_EDICTS, center, radius, false, pEnum );
@@ -336,7 +283,7 @@ private:
//-----------------------------------------------------------------------------
// Drops an entity onto the floor
//-----------------------------------------------------------------------------
int UTIL_DropToFloor( CBaseEntity *pEntity, unsigned int mask, CBaseEntity *pIgnore )
int UTIL_DropToFloor( CBaseEntity *pEntity, unsigned int mask, CBaseEntity *pIgnore)
{
// Assume no ground
pEntity->SetGroundEntity( NULL );
@@ -344,20 +291,12 @@ int UTIL_DropToFloor( CBaseEntity *pEntity, unsigned int mask, CBaseEntity *pIgn
Assert( pEntity );
trace_t trace;
#if !defined(HL2MP) && !defined(HL1_DLL)
// HACK: is this really the only sure way to detect crossing a terrain boundry?
UTIL_TraceEntity( pEntity, pEntity->GetAbsOrigin(), pEntity->GetAbsOrigin(), mask, pIgnore, pEntity->GetCollisionGroup(), &trace );
if (trace.fraction == 0.0)
return -1;
#endif // HL2MP
UTIL_TraceEntity( pEntity, pEntity->GetAbsOrigin() + Vector(0,0,1), pEntity->GetAbsOrigin() - Vector(0,0,256), mask, pIgnore, pEntity->GetCollisionGroup(), &trace );
#ifdef HL1_DLL
if( fabs(pEntity->GetAbsOrigin().z - trace.endpos.z) <= 2.f )
return -1;
#endif
UTIL_TraceEntity( pEntity, pEntity->GetAbsOrigin(), pEntity->GetAbsOrigin() - Vector(0,0,256), mask, pIgnore, pEntity->GetCollisionGroup(), &trace );
if (trace.allsolid)
return -1;
@@ -479,9 +418,7 @@ void UTIL_Remove( IServerNetworkable *oldObj )
CBaseEntity *pBaseEnt = oldObj->GetBaseEntity();
if ( pBaseEnt )
{
#ifdef PORTAL //make sure entities are in the primary physics environment for the portal mod, this code should be safe even if the entity is in neither extra environment
CPortalSimulator::Pre_UTIL_Remove( pBaseEnt );
#endif
g_bReceivedChainedUpdateOnRemove = false;
pBaseEnt->UpdateOnRemove();
@@ -490,9 +427,7 @@ void UTIL_Remove( IServerNetworkable *oldObj )
// clear oldObj targetname / other flags now
pBaseEnt->SetName( NULL_STRING );
#ifdef PORTAL
CPortalSimulator::Post_UTIL_Remove( pBaseEnt );
#endif
}
gEntList.AddToDeleteList( oldObj );
@@ -532,9 +467,7 @@ void UTIL_RemoveImmediate( CBaseEntity *oldObj )
return;
}
#ifdef PORTAL //make sure entities are in the primary physics environment for the portal mod, this code should be safe even if the entity is in neither extra environment
CPortalSimulator::Pre_UTIL_Remove( oldObj );
#endif
oldObj->AddEFlags( EFL_KILLME ); // Make sure to ignore further calls into here or UTIL_Remove.
@@ -548,9 +481,7 @@ void UTIL_RemoveImmediate( CBaseEntity *oldObj )
delete oldObj;
g_bDisableEhandleAccess = false;
#ifdef PORTAL
CPortalSimulator::Post_UTIL_Remove( oldObj );
#endif
}
@@ -670,23 +601,8 @@ bool UTIL_IsCommandIssuedByServerAdmin( void )
if ( engine->IsDedicatedServer() && issuingPlayerIndex > 0 )
return false;
#if defined( REPLAY_ENABLED )
// entity 1 is replay?
player_info_t pi;
bool bPlayerIsReplay = engine->GetPlayerInfo( 1, &pi ) && pi.isreplay;
#else
bool bPlayerIsReplay = false;
#endif
if ( bPlayerIsReplay )
{
if ( issuingPlayerIndex > 2 )
return false;
}
else if ( issuingPlayerIndex > 1 )
{
if ( issuingPlayerIndex > 1 )
return false;
}
return true;
}
@@ -731,6 +647,12 @@ int ENTINDEX( CBaseEntity *pEnt )
void UTIL_GetPlayerConnectionInfo( int playerIndex, int& ping, int &packetloss )
{
CBasePlayer *player = UTIL_PlayerByIndex( playerIndex );
if ( player->IsSplitScreenPlayer() &&
player->GetSplitScreenPlayerOwner() )
{
player = player->GetSplitScreenPlayerOwner();
playerIndex = player->entindex();
}
INetChannelInfo *nci = engine->GetPlayerNetInfo(playerIndex);
@@ -840,7 +762,7 @@ inline void TransmitShakeEvent( CBasePlayer *pPlayer, float localAmplitude, floa
// bAirShake - if this is false, then it will only shake players standing on the ground.
//-----------------------------------------------------------------------------
const float MAX_SHAKE_AMPLITUDE = 16.0f;
void UTIL_ScreenShake( const Vector &center, float amplitude, float frequency, float duration, float radius, ShakeCommand_t eCommand, bool bAirShake )
void UTIL_ScreenShake( const Vector &center, float amplitude, float frequency, float duration, float radius, ShakeCommand_t eCommand, bool bAirShake, CUtlVector<CBasePlayer *> *ignore )
{
int i;
float localAmplitude;
@@ -851,7 +773,7 @@ void UTIL_ScreenShake( const Vector &center, float amplitude, float frequency, f
}
for ( i = 1; i <= gpGlobals->maxClients; i++ )
{
CBaseEntity *pPlayer = UTIL_PlayerByIndex( i );
CBasePlayer *pPlayer = UTIL_PlayerByIndex( i );
//
// Only start shakes for players that are on the ground unless doing an air shake.
@@ -861,6 +783,11 @@ void UTIL_ScreenShake( const Vector &center, float amplitude, float frequency, f
continue;
}
if ( ignore && ignore->HasElement( pPlayer ) )
{
continue;
}
localAmplitude = ComputeShakeAmplitude( center, pPlayer->WorldSpaceCenter(), amplitude, radius );
// This happens if the player is outside the radius, in which case we should ignore
@@ -868,7 +795,7 @@ void UTIL_ScreenShake( const Vector &center, float amplitude, float frequency, f
if (localAmplitude < 0)
continue;
TransmitShakeEvent( (CBasePlayer *)pPlayer, localAmplitude, frequency, duration, eCommand );
TransmitShakeEvent( pPlayer, localAmplitude, frequency, duration, eCommand );
}
}
@@ -894,7 +821,7 @@ void UTIL_ScreenShakeObject( CBaseEntity *pEnt, const Vector &center, float ampl
{
localAmplitude = amplitude;
}
else if ((pPlayer->GetFlags() & FL_ONGROUND) && (pPlayer->GetGroundEntity()->GetRootMoveParent() == pHighestParent))
else if ((pPlayer->GetFlags() & FL_ONGROUND) && pPlayer->GetGroundEntity() && (pPlayer->GetGroundEntity()->GetRootMoveParent() == pHighestParent))
{
// If the player is standing on the object, use maximum amplitude
localAmplitude = amplitude;
@@ -907,15 +834,7 @@ void UTIL_ScreenShakeObject( CBaseEntity *pEnt, const Vector &center, float ampl
continue;
}
if ( radius > 0 )
{
localAmplitude = ComputeShakeAmplitude( center, pPlayer->WorldSpaceCenter(), amplitude, radius );
}
else
{
// If using a 0 radius, apply to everyone with no falloff
localAmplitude = amplitude;
}
localAmplitude = ComputeShakeAmplitude( center, pPlayer->WorldSpaceCenter(), amplitude, radius );
// This happens if the player is outside the radius,
// in which case we should ignore all commands
@@ -928,6 +847,67 @@ void UTIL_ScreenShakeObject( CBaseEntity *pEnt, const Vector &center, float ampl
}
//-----------------------------------------------------------------------------
// Transmits the actual tilt event
//-----------------------------------------------------------------------------
inline void TransmitTiltEvent( CBasePlayer *pPlayer, QAngle tiltAngle, float duration, float tiltTime, ShakeCommand_t eCommand, bool bEaseInOut )
{
CSingleUserRecipientFilter user( pPlayer );
user.MakeReliable();
UserMessageBegin( user, "Tilt" );
WRITE_BYTE( eCommand ); // tilt command (SHAKE_START, STOP, FREQUENCY, AMPLITUDE)
WRITE_BYTE( bEaseInOut ); // tilt ease in/out
WRITE_FLOAT( tiltAngle.x ); // tilt angle
WRITE_FLOAT( tiltAngle.y );
WRITE_FLOAT( tiltAngle.z );
WRITE_FLOAT( duration ); // tilt lasts this long
WRITE_FLOAT( tiltTime ); // tilt time
MessageEnd();
}
//-----------------------------------------------------------------------------
// Purpose: Tilt the screen of all clients within radius.
// radius == 0, shake all clients
// Input : center - Center of screen tilt, radius is measured from here.
// tiltAngle - Angle that the world is pretending to tilt
// duration - duration of tilt in seconds.
// radius - Radius of effect, 0 shakes all clients.
// tiltTime - how long it takes to reach full tilt
// command - One of the following values:
// SHAKE_START - starts the screen tilt for all players within the radius
// SHAKE_STOP - stops the screen tilt for all players within the radius
// SHAKE_AMPLITUDE - modifies the amplitude of the screen tilt
// for all players within the radius
// SHAKE_FREQUENCY - modifies the frequency of the screen tilt
// for all players within the radius
// bAirShake - if this is false, then it will only tilt players standing on the ground.
//-----------------------------------------------------------------------------
void UTIL_ScreenTilt( const Vector &center, const QAngle &tiltAngle, float duration, float radius, float tiltTime, ShakeCommand_t eCommand, bool bEaseInOut )
{
int i;
for ( i = 1; i <= gpGlobals->maxClients; i++ )
{
CBaseEntity *pPlayer = UTIL_PlayerByIndex( i );
//
// Only start shakes for players that are on the ground unless doing an air shake.
//
if ( !pPlayer )
{
continue;
}
// This happens if the player is outside the radius, in which case we should ignore
// all commands
if ( radius != 0.0f && pPlayer->WorldSpaceCenter().DistTo( center ) > radius )
continue;
TransmitTiltEvent( (CBasePlayer *)pPlayer, tiltAngle, duration, tiltTime, eCommand, bEaseInOut );
}
}
//-----------------------------------------------------------------------------
// Purpose: Punches the view of all clients within radius.
// If radius is 0, punches all clients.
@@ -990,10 +970,17 @@ void UTIL_ScreenFadeWrite( const ScreenFade_t &fade, CBaseEntity *pEntity )
if ( !pEntity || !pEntity->IsNetClient() )
return;
CSingleUserRecipientFilter user( (CBasePlayer *)pEntity );
CBasePlayer *pRecipient = static_cast< CBasePlayer * >( pEntity );
if ( pRecipient->ShouldThrottleUserMessage( "Fade" ) )
{
return;
}
CSingleUserRecipientFilter user( pRecipient );
user.MakeReliable();
UserMessageBegin( user, "Fade" ); // use the magic #1 for "one client"
UserMessageBegin( user, "Fade" );
WRITE_SHORT( fade.duration ); // fade lasts this long
WRITE_SHORT( fade.holdTime ); // fade lasts this long
WRITE_SHORT( fade.fadeFlags ); // fade type (in / out)
@@ -1230,6 +1217,57 @@ void UTIL_ShowMessageAll( const char *pString )
UTIL_ShowMessage( pString, NULL );
}
//-------------------------------------------------------------------------------------------------
// HudMessagePanel helper
void UTIL_MessageTextAll( const char *text, Color color )
{
CReliableBroadcastRecipientFilter filter;
UserMessageBegin( filter, "MessageText" );
WRITE_BYTE( color.r() );
WRITE_BYTE( color.g() );
WRITE_BYTE( color.b() );
WRITE_STRING( text );
MessageEnd();
}
//-------------------------------------------------------------------------------------------------
// HudMessagePanel helper
void UTIL_MessageText( CBasePlayer *player, const char *text, Color color )
{
CSingleUserRecipientFilter filter( player );
filter.MakeReliable();
UserMessageBegin( filter, "MessageText" );
WRITE_BYTE( color.r() );
WRITE_BYTE( color.g() );
WRITE_BYTE( color.b() );
WRITE_STRING( text );
MessageEnd();
}
//-------------------------------------------------------------------------------------------------
// HudMessagePanel helper
void UTIL_ResetMessageTextAll( void )
{
CReliableBroadcastRecipientFilter filter;
UserMessageBegin( filter, "MessageText" );
MessageEnd();
}
//-------------------------------------------------------------------------------------------------
// HudMessagePanel helper
void UTIL_ResetMessageText( CBasePlayer *player )
{
CSingleUserRecipientFilter filter( player );
filter.MakeReliable();
UserMessageBegin( filter, "MessageText" );
MessageEnd();
}
// So we always return a valid surface
static csurface_t g_NullSurface = { "**empty**", 0 };
@@ -1293,23 +1331,34 @@ void UTIL_SetModel( CBaseEntity *pEntity, const char *pModelName )
{
// check to see if model was properly precached
int i = modelinfo->GetModelIndex( pModelName );
if ( i == -1 )
if ( i < 0 )
{
Error("%i/%s - %s: UTIL_SetModel: not precached: %s\n", pEntity->entindex(),
STRING( pEntity->GetEntityName() ),
pEntity->GetClassname(), pModelName);
}
pEntity->SetModelIndex( i ) ;
pEntity->SetModelName( AllocPooledString( pModelName ) );
// brush model
const model_t *mod = modelinfo->GetModel( i );
if ( mod )
{
Vector mins, maxs;
modelinfo->GetModelBounds( mod, mins, maxs );
SetMinMaxSize (pEntity, mins, maxs);
}
else
{
SetMinMaxSize (pEntity, vec3_origin, vec3_origin);
}
CBaseAnimating *pAnimating = pEntity->GetBaseAnimating();
if ( pAnimating )
{
pAnimating->m_nForceBone = 0;
}
pEntity->SetModelName( AllocPooledString( pModelName ) );
pEntity->SetModelIndex( i ) ;
SetMinMaxSize(pEntity, vec3_origin, vec3_origin);
pEntity->SetCollisionBoundsFromModel();
}
@@ -1323,7 +1372,7 @@ void UTIL_SetOrigin( CBaseEntity *entity, const Vector &vecOrigin, bool bFireTri
}
void UTIL_ParticleEffect( const Vector &vecOrigin, const Vector &vecDirection, ULONG ulColor, ULONG ulCount )
void UTIL_ParticleEffect( const Vector &vecOrigin, const Vector &vecDirection, uint32 ulColor, int ulCount )
{
Msg( "UTIL_ParticleEffect: Disabled\n" );
}
@@ -1414,7 +1463,7 @@ Vector UTIL_RandomBloodVector( void )
// Input :
// Output :
//------------------------------------------------------------------------------
void UTIL_ImpactTrace( trace_t *pTrace, int iDamageType, const char *pCustomImpactName )
void UTIL_ImpactTrace( trace_t *pTrace, int iDamageType, char *pCustomImpactName )
{
CBaseEntity *pEntity = pTrace->m_pEnt;
@@ -1533,18 +1582,18 @@ float UTIL_WaterLevel( const Vector &position, float minz, float maxz )
Vector midUp = position;
midUp.z = minz;
if ( !(UTIL_PointContents(midUp) & MASK_WATER) )
if ( !(UTIL_PointContents(midUp, MASK_WATER) & MASK_WATER) )
return minz;
midUp.z = maxz;
if ( UTIL_PointContents(midUp) & MASK_WATER )
if ( UTIL_PointContents(midUp, MASK_WATER) & MASK_WATER )
return maxz;
float diff = maxz - minz;
while (diff > 1.0)
{
midUp.z = minz + diff/2.0;
if ( UTIL_PointContents(midUp) & MASK_WATER )
if ( UTIL_PointContents(midUp, MASK_WATER) & MASK_WATER )
{
minz = midUp.z;
}
@@ -1598,7 +1647,7 @@ float UTIL_FindWaterSurface( const Vector &position, float minz, float maxz )
}
extern short g_sModelIndexBubbles;// holds the index for the bubbles model
extern int g_sModelIndexBubbles;// holds the index for the bubbles model
void UTIL_Bubbles( const Vector& mins, const Vector& maxs, int count )
{
@@ -1793,8 +1842,11 @@ void UTIL_PrecacheOther( const char *szClassname, const char *modelName )
// UTIL_LogPrintf - Prints a logged message to console.
// Preceded by LOG: ( timestamp ) < message >
//=========================================================
void UTIL_LogPrintf( const char *fmt, ... )
void UTIL_LogPrintf( char *fmt, ... )
{
if ( !g_bIsLogging )
return;
va_list argptr;
char tempString[1024];
@@ -1840,7 +1892,7 @@ void UTIL_StripToken( const char *pKey, char *pDest )
// computes gravity scale for an absolute gravity. Pass the result into CBaseEntity::SetGravity()
float UTIL_ScaleForGravity( float desiredGravity )
{
float worldGravity = GetCurrentGravity();
float worldGravity = sv_gravity.GetFloat();
return worldGravity > 0 ? desiredGravity / worldGravity : 0;
}
@@ -1869,7 +1921,7 @@ extern "C" void Sys_Error( char *error, ... )
// *mapData - pointer a block of entity map data
// Output : -1 if the entity was not successfully created; 0 on success
//-----------------------------------------------------------------------------
int DispatchSpawn( CBaseEntity *pEntity )
int DispatchSpawn( CBaseEntity *pEntity, bool bRunVScripts )
{
if ( pEntity )
{
@@ -1884,6 +1936,13 @@ int DispatchSpawn( CBaseEntity *pEntity )
//pEntity->SetAbsMins( pEntity->GetOrigin() - Vector(1,1,1) );
//pEntity->SetAbsMaxs( pEntity->GetOrigin() + Vector(1,1,1) );
if( bRunVScripts )
{
pEntity->RunVScripts();
pEntity->RunPrecacheScripts();
}
#if defined(TRACK_ENTITY_MEMORY) && defined(USE_MEM_DEBUG)
const char *pszClassname = NULL;
int iClassname = ((CEntityFactoryDictionary*)EntityFactoryDictionary())->m_Factories.Find( pEntity->GetClassname() );
@@ -1905,8 +1964,7 @@ int DispatchSpawn( CBaseEntity *pEntity )
// Don't allow the PVS check to skip animation setup during spawning
pAnimating->SetBoneCacheFlags( BCF_IS_IN_SPAWN );
pEntity->Spawn();
if ( pEntSafe != NULL )
pAnimating->ClearBoneCacheFlags( BCF_IS_IN_SPAWN );
pAnimating->ClearBoneCacheFlags( BCF_IS_IN_SPAWN );
}
mdlcache->SetAsyncLoad( MDLCACHE_ANIMBLOCK, bAsyncAnims );
@@ -1950,6 +2008,12 @@ int DispatchSpawn( CBaseEntity *pEntity )
}
gEntList.NotifySpawn( pEntity );
if( bRunVScripts )
{
pEntity->RunOnPostSpawnScripts();
}
}
return 0;
@@ -2134,7 +2198,7 @@ static int UTIL_GetNewCheckClient( int check )
i = 1;
}
ent = engine->PEntityOfEntIndex( i );
ent = INDEXENT( i );
if ( !ent )
continue;
@@ -2176,6 +2240,8 @@ static int UTIL_GetNewCheckClient( int check )
{
g_CheckClient.m_checkCluster = clusterIndex;
engine->GetPVSForCluster( clusterIndex, sizeof(g_CheckClient.m_checkPVS), g_CheckClient.m_checkPVS );
}
}
@@ -2199,7 +2265,7 @@ static edict_t *UTIL_GetCurrentCheckClient()
}
// return check if it might be visible
ent = engine->PEntityOfEntIndex( g_CheckClient.m_lastcheck );
ent = INDEXENT( g_CheckClient.m_lastcheck );
// Allow dead clients -- JAY
// Our monsters know the difference, and this function gates alot of behavior
@@ -2213,6 +2279,8 @@ static edict_t *UTIL_GetCurrentCheckClient()
return ent;
}
void UTIL_SetClientVisibilityPVS( edict_t *pClient, const unsigned char *pvs, int pvssize )
{
if ( pClient == UTIL_GetCurrentCheckClient() )
@@ -2290,7 +2358,7 @@ CBaseEntity *UTIL_FindClientInPVS( const Vector &vecBoxMins, const Vector &vecBo
//-----------------------------------------------------------------------------
ConVar sv_strict_notarget( "sv_strict_notarget", "0", 0, "If set, notarget will cause entities to never think they are in the pvs" );
static edict_t *UTIL_FindClientInPVSGuts(edict_t *pEdict, unsigned char *pvs, unsigned pvssize )
edict_t *UTIL_FindClientInPVSGuts(edict_t *pEdict, unsigned char *pvs, unsigned pvssize )
{
Vector view;
@@ -2329,7 +2397,7 @@ static edict_t *UTIL_FindClientInPVSGuts(edict_t *pEdict, unsigned char *pvs, un
edict_t *UTIL_FindClientInPVS(edict_t *pEdict)
{
return UTIL_FindClientInPVSGuts( pEdict, g_CheckClient.m_checkPVS, sizeof( g_CheckClient.m_checkPVS ) );
return g_pGameRules->DoFindClientInPVS( pEdict, g_CheckClient.m_checkPVS, sizeof( g_CheckClient.m_checkPVS ) );
}
//-----------------------------------------------------------------------------
@@ -2337,7 +2405,7 @@ edict_t *UTIL_FindClientInPVS(edict_t *pEdict)
//-----------------------------------------------------------------------------
edict_t *UTIL_FindClientInVisibilityPVS( edict_t *pEdict )
{
return UTIL_FindClientInPVSGuts( pEdict, g_CheckClient.m_checkVisibilityPVS, sizeof( g_CheckClient.m_checkVisibilityPVS ) );
return g_pGameRules->DoFindClientInPVS( pEdict, g_CheckClient.m_checkVisibilityPVS, sizeof( g_CheckClient.m_checkVisibilityPVS ) );
}
@@ -2718,7 +2786,7 @@ bool UTIL_LoadAndSpawnEntitiesFromScript( CUtlVector <CBaseEntity*> &entities, c
{
KeyValues *pkvFile = new KeyValues( pBlock );
if ( pkvFile->LoadFromFile( filesystem, pScriptFile, "MOD" ) )
if ( pkvFile->LoadFromFile( filesystem, pScriptFile, "GAME" ) )
{
// Load each block, and spawn the entities
KeyValues *pkvNode = pkvFile->GetFirstSubKey();
@@ -2890,6 +2958,84 @@ void UTIL_BoundToWorldSize( Vector *pVecPos )
}
}
//--------------------------------------------------------------------------------------------------------
/**
* Return true if ground is fairly level within the given radius around an entity
* Trace 4 vertical hull-quadrants and test their collisions and ground heights and normals
*/
bool UTIL_IsGroundLevel( float radius, const Vector &position, float hullHeight, int mask, const CBaseEntity *ignore, bool debugTraces )
{
const int subdivisions = 3;
const int samples = subdivisions * subdivisions;
// trace down below floor level to detect ledges and overhangs
trace_t result[ samples ];
float size = 2.0f * radius / subdivisions;
int i, j, s = 0;
float x, y = -radius;
for( j=0; j<subdivisions; ++j )
{
x = -radius;
for( int i=0; i<subdivisions; ++i )
{
UTIL_TraceHull( position + Vector( 0, 0, hullHeight ),
position + Vector( 0, 0, -100 ),
Vector( x, y, 0 ),
Vector( x + size, y + size, 10.0f ),
mask, ignore, COLLISION_GROUP_PLAYER_MOVEMENT,
&result[ s ] );
if ( debugTraces )
{
NDebugOverlay::SweptBox( position + Vector( 0, 0, hullHeight ),
result[ s ].endpos,
Vector( x, y, 0 ),
Vector( x + size, y + size, 10.0f ),
vec3_angle, 255, 255, 0, 255, 5.0f );
}
++s;
x += size;
}
y += size;
}
// UTIL_TraceHull( GetPosition() + Vector( 0, 0, body->GetCrouchHullHeight() ), GetPosition() + Vector( 0, 0, -100 ), Vector( -radius, -radius, 0 ), Vector( 0, 0, 10.0f ), MASK_ZOMBIESOLID, this, COLLISION_GROUP_PLAYER_MOVEMENT, &result[0] );
// UTIL_TraceHull( GetPosition() + Vector( 0, 0, body->GetCrouchHullHeight() ), GetPosition() + Vector( 0, 0, -100 ), Vector( -radius, 0, 0 ), Vector( 0, radius, 10.0f ), MASK_ZOMBIESOLID, this, COLLISION_GROUP_PLAYER_MOVEMENT, &result[1] );
// UTIL_TraceHull( GetPosition() + Vector( 0, 0, body->GetCrouchHullHeight() ), GetPosition() + Vector( 0, 0, -100 ), Vector( 0, 0, 0 ), Vector( radius, radius, 10.0f ), MASK_ZOMBIESOLID, this, COLLISION_GROUP_PLAYER_MOVEMENT, &result[2] );
// UTIL_TraceHull( GetPosition() + Vector( 0, 0, body->GetCrouchHullHeight() ), GetPosition() + Vector( 0, 0, -100 ), Vector( 0, -radius, 0 ), Vector( radius, 0, 10.0f ), MASK_ZOMBIESOLID, this, COLLISION_GROUP_PLAYER_MOVEMENT, &result[3] );
for( i=0; i<samples; ++i )
{
if ( result[i].startsolid )
{
return false;
}
if ( result[i].DidHit() )
{
const float flat = 0.9f;
if ( result[i].plane.normal.z < flat )
{
// too steep to sit here
return false;
}
const float maxZDelta = 10.0f;
for( j = 0; j<samples; ++j )
{
if ( i != j && abs( result[i].endpos.z - result[j].endpos.z ) > maxZDelta )
{
return false;
}
}
}
}
return true;
}
//=============================================================================
//
// Tests!
@@ -2985,7 +3131,7 @@ void CC_KDTreeTest( const CCommand &args )
trace_t trace;
for ( int iTest = 0; iTest < NUM_KDTREE_TESTS; ++iTest )
{
UTIL_TraceHull( vecStart, vecTargets[iTest], VEC_HULL_MIN_SCALED( pPlayer ), VEC_HULL_MAX_SCALED( pPlayer ), MASK_SOLID, pPlayer, COLLISION_GROUP_NONE, &trace );
UTIL_TraceHull( vecStart, vecTargets[iTest], VEC_HULL_MIN, VEC_HULL_MAX, MASK_SOLID, pPlayer, COLLISION_GROUP_NONE, &trace );
}
break;
}
@@ -3082,7 +3228,7 @@ void CC_VoxelTreePlayerView( void )
CBasePlayer *pPlayer = static_cast<CBasePlayer*>( UTIL_GetLocalPlayer() );
Vector vecStart = pPlayer->GetAbsOrigin();
partition->RenderObjectsInPlayerLeafs( vecStart - VEC_HULL_MIN_SCALED( pPlayer ), vecStart + VEC_HULL_MAX_SCALED( pPlayer ), 3.0f );
partition->RenderObjectsInPlayerLeafs( vecStart - VEC_HULL_MIN, vecStart + VEC_HULL_MAX, 3.0f );
}
static ConCommand voxeltree_playerview( "voxeltree_playerview", CC_VoxelTreePlayerView, "View entities in the voxel-tree at the player position.", FCVAR_CHEAT );
@@ -3254,7 +3400,7 @@ void CC_CollisionTest( const CCommand &args )
int nMask = MASK_ALL & ~(CONTENTS_MONSTER | CONTENTS_HITBOX );
for ( int j = 0; j < 2; j++ )
{
float startTime = engine->Time();
float startTime = Plat_FloatTime();
if ( testType == 1 )
{
trace_t tr;
@@ -3284,7 +3430,7 @@ void CC_CollisionTest( const CCommand &args )
}
}
duration += engine->Time() - startTime;
duration += Plat_FloatTime() - startTime;
}
test[testType] = duration;
Msg("%d collisions in %.2f ms (%u dots)\n", NUM_COLLISION_TESTS, duration*1000, dots );