aboutsummaryrefslogtreecommitdiff
path: root/sp/src/game/shared/util_shared.cpp
diff options
context:
space:
mode:
authorJørgen P. Tjernø <[email protected]>2013-12-02 19:31:46 -0800
committerJørgen P. Tjernø <[email protected]>2013-12-02 19:46:31 -0800
commitf56bb35301836e56582a575a75864392a0177875 (patch)
treede61ddd39de3e7df52759711950b4c288592f0dc /sp/src/game/shared/util_shared.cpp
parentMark some more files as text. (diff)
downloadsource-sdk-2013-f56bb35301836e56582a575a75864392a0177875.tar.xz
source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.zip
Fix line endings. WHAMMY.
Diffstat (limited to 'sp/src/game/shared/util_shared.cpp')
-rw-r--r--sp/src/game/shared/util_shared.cpp2354
1 files changed, 1177 insertions, 1177 deletions
diff --git a/sp/src/game/shared/util_shared.cpp b/sp/src/game/shared/util_shared.cpp
index 889ed9ab..de7aea4e 100644
--- a/sp/src/game/shared/util_shared.cpp
+++ b/sp/src/game/shared/util_shared.cpp
@@ -1,1177 +1,1177 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-//=============================================================================//
-
-#include "cbase.h"
-#include "mathlib/mathlib.h"
-#include "util_shared.h"
-#include "model_types.h"
-#include "convar.h"
-#include "IEffects.h"
-#include "vphysics/object_hash.h"
-#include "mathlib/IceKey.H"
-#include "checksum_crc.h"
-#ifdef TF_CLIENT_DLL
-#include "cdll_util.h"
-#endif
-#include "particle_parse.h"
-#include "KeyValues.h"
-#include "time.h"
-
-#ifdef USES_ECON_ITEMS
- #include "econ_item_constants.h"
- #include "econ_holidays.h"
- #include "rtime.h"
-#endif // USES_ECON_ITEMS
-
-#ifdef CLIENT_DLL
- #include "c_te_effect_dispatch.h"
-#else
- #include "te_effect_dispatch.h"
-
-bool NPC_CheckBrushExclude( CBaseEntity *pEntity, CBaseEntity *pBrush );
-#endif
-
-
-// memdbgon must be the last include file in a .cpp file!!!
-#include "tier0/memdbgon.h"
-
-ConVar r_visualizetraces( "r_visualizetraces", "0", FCVAR_CHEAT );
-ConVar developer("developer", "0", 0, "Set developer message level" ); // developer mode
-
-float UTIL_VecToYaw( const Vector &vec )
-{
- if (vec.y == 0 && vec.x == 0)
- return 0;
-
- float yaw = atan2( vec.y, vec.x );
-
- yaw = RAD2DEG(yaw);
-
- if (yaw < 0)
- yaw += 360;
-
- return yaw;
-}
-
-
-float UTIL_VecToPitch( const Vector &vec )
-{
- if (vec.y == 0 && vec.x == 0)
- {
- if (vec.z < 0)
- return 180.0;
- else
- return -180.0;
- }
-
- float dist = vec.Length2D();
- float pitch = atan2( -vec.z, dist );
-
- pitch = RAD2DEG(pitch);
-
- return pitch;
-}
-
-float UTIL_VecToYaw( const matrix3x4_t &matrix, const Vector &vec )
-{
- Vector tmp = vec;
- VectorNormalize( tmp );
-
- float x = matrix[0][0] * tmp.x + matrix[1][0] * tmp.y + matrix[2][0] * tmp.z;
- float y = matrix[0][1] * tmp.x + matrix[1][1] * tmp.y + matrix[2][1] * tmp.z;
-
- if (x == 0.0f && y == 0.0f)
- return 0.0f;
-
- float yaw = atan2( -y, x );
-
- yaw = RAD2DEG(yaw);
-
- if (yaw < 0)
- yaw += 360;
-
- return yaw;
-}
-
-
-float UTIL_VecToPitch( const matrix3x4_t &matrix, const Vector &vec )
-{
- Vector tmp = vec;
- VectorNormalize( tmp );
-
- float x = matrix[0][0] * tmp.x + matrix[1][0] * tmp.y + matrix[2][0] * tmp.z;
- float z = matrix[0][2] * tmp.x + matrix[1][2] * tmp.y + matrix[2][2] * tmp.z;
-
- if (x == 0.0f && z == 0.0f)
- return 0.0f;
-
- float pitch = atan2( z, x );
-
- pitch = RAD2DEG(pitch);
-
- if (pitch < 0)
- pitch += 360;
-
- return pitch;
-}
-
-Vector UTIL_YawToVector( float yaw )
-{
- Vector ret;
-
- ret.z = 0;
- float angle = DEG2RAD( yaw );
- SinCos( angle, &ret.y, &ret.x );
-
- return ret;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Helper function get get determinisitc random values for shared/prediction code
-// Input : seedvalue -
-// *module -
-// line -
-// Output : static int
-//-----------------------------------------------------------------------------
-static int SeedFileLineHash( int seedvalue, const char *sharedname, int additionalSeed )
-{
- CRC32_t retval;
-
- CRC32_Init( &retval );
-
- CRC32_ProcessBuffer( &retval, (void *)&seedvalue, sizeof( int ) );
- CRC32_ProcessBuffer( &retval, (void *)&additionalSeed, sizeof( int ) );
- CRC32_ProcessBuffer( &retval, (void *)sharedname, Q_strlen( sharedname ) );
-
- CRC32_Final( &retval );
-
- return (int)( retval );
-}
-
-float SharedRandomFloat( const char *sharedname, float flMinVal, float flMaxVal, int additionalSeed /*=0*/ )
-{
- Assert( CBaseEntity::GetPredictionRandomSeed() != -1 );
-
- int seed = SeedFileLineHash( CBaseEntity::GetPredictionRandomSeed(), sharedname, additionalSeed );
- RandomSeed( seed );
- return RandomFloat( flMinVal, flMaxVal );
-}
-
-int SharedRandomInt( const char *sharedname, int iMinVal, int iMaxVal, int additionalSeed /*=0*/ )
-{
- Assert( CBaseEntity::GetPredictionRandomSeed() != -1 );
-
- int seed = SeedFileLineHash( CBaseEntity::GetPredictionRandomSeed(), sharedname, additionalSeed );
- RandomSeed( seed );
- return RandomInt( iMinVal, iMaxVal );
-}
-
-Vector SharedRandomVector( const char *sharedname, float minVal, float maxVal, int additionalSeed /*=0*/ )
-{
- Assert( CBaseEntity::GetPredictionRandomSeed() != -1 );
-
- int seed = SeedFileLineHash( CBaseEntity::GetPredictionRandomSeed(), sharedname, additionalSeed );
- RandomSeed( seed );
- // HACK: Can't call RandomVector/Angle because it uses rand() not vstlib Random*() functions!
- // Get a random vector.
- Vector random;
- random.x = RandomFloat( minVal, maxVal );
- random.y = RandomFloat( minVal, maxVal );
- random.z = RandomFloat( minVal, maxVal );
- return random;
-}
-
-QAngle SharedRandomAngle( const char *sharedname, float minVal, float maxVal, int additionalSeed /*=0*/ )
-{
- Assert( CBaseEntity::GetPredictionRandomSeed() != -1 );
-
- int seed = SeedFileLineHash( CBaseEntity::GetPredictionRandomSeed(), sharedname, additionalSeed );
- RandomSeed( seed );
-
- // HACK: Can't call RandomVector/Angle because it uses rand() not vstlib Random*() functions!
- // Get a random vector.
- Vector random;
- random.x = RandomFloat( minVal, maxVal );
- random.y = RandomFloat( minVal, maxVal );
- random.z = RandomFloat( minVal, maxVal );
- return QAngle( random.x, random.y, random.z );
-}
-
-
-//-----------------------------------------------------------------------------
-//
-// Shared client/server trace filter code
-//
-//-----------------------------------------------------------------------------
-bool PassServerEntityFilter( const IHandleEntity *pTouch, const IHandleEntity *pPass )
-{
- if ( !pPass )
- return true;
-
- if ( pTouch == pPass )
- return false;
-
- const CBaseEntity *pEntTouch = EntityFromEntityHandle( pTouch );
- const CBaseEntity *pEntPass = EntityFromEntityHandle( pPass );
- if ( !pEntTouch || !pEntPass )
- return true;
-
- // don't clip against own missiles
- if ( pEntTouch->GetOwnerEntity() == pEntPass )
- return false;
-
- // don't clip against owner
- if ( pEntPass->GetOwnerEntity() == pEntTouch )
- return false;
-
-
- return true;
-}
-
-
-//-----------------------------------------------------------------------------
-// A standard filter to be applied to just about everything.
-//-----------------------------------------------------------------------------
-bool StandardFilterRules( IHandleEntity *pHandleEntity, int fContentsMask )
-{
- CBaseEntity *pCollide = EntityFromEntityHandle( pHandleEntity );
-
- // Static prop case...
- if ( !pCollide )
- return true;
-
- SolidType_t solid = pCollide->GetSolid();
- const model_t *pModel = pCollide->GetModel();
-
- if ( ( modelinfo->GetModelType( pModel ) != mod_brush ) || (solid != SOLID_BSP && solid != SOLID_VPHYSICS) )
- {
- if ( (fContentsMask & CONTENTS_MONSTER) == 0 )
- return false;
- }
-
- // This code is used to cull out tests against see-thru entities
- if ( !(fContentsMask & CONTENTS_WINDOW) && pCollide->IsTransparent() )
- return false;
-
- // FIXME: this is to skip BSP models that are entities that can be
- // potentially moved/deleted, similar to a monster but doors don't seem to
- // be flagged as monsters
- // FIXME: the FL_WORLDBRUSH looked promising, but it needs to be set on
- // everything that's actually a worldbrush and it currently isn't
- if ( !(fContentsMask & CONTENTS_MOVEABLE) && (pCollide->GetMoveType() == MOVETYPE_PUSH))// !(touch->flags & FL_WORLDBRUSH) )
- return false;
-
- return true;
-}
-
-
-//-----------------------------------------------------------------------------
-// Simple trace filter
-//-----------------------------------------------------------------------------
-CTraceFilterSimple::CTraceFilterSimple( const IHandleEntity *passedict, int collisionGroup,
- ShouldHitFunc_t pExtraShouldHitFunc )
-{
- m_pPassEnt = passedict;
- m_collisionGroup = collisionGroup;
- m_pExtraShouldHitCheckFunction = pExtraShouldHitFunc;
-}
-
-//-----------------------------------------------------------------------------
-// The trace filter!
-//-----------------------------------------------------------------------------
-bool CTraceFilterSimple::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask )
-{
- if ( !StandardFilterRules( pHandleEntity, contentsMask ) )
- return false;
-
- if ( m_pPassEnt )
- {
- if ( !PassServerEntityFilter( pHandleEntity, m_pPassEnt ) )
- {
- return false;
- }
- }
-
- // Don't test if the game code tells us we should ignore this collision...
- CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity );
- if ( !pEntity )
- return false;
- if ( !pEntity->ShouldCollide( m_collisionGroup, contentsMask ) )
- return false;
- if ( pEntity && !g_pGameRules->ShouldCollide( m_collisionGroup, pEntity->GetCollisionGroup() ) )
- return false;
- if ( m_pExtraShouldHitCheckFunction &&
- (! ( m_pExtraShouldHitCheckFunction( pHandleEntity, contentsMask ) ) ) )
- return false;
-
- return true;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Trace filter that only hits NPCs and the player
-//-----------------------------------------------------------------------------
-bool CTraceFilterOnlyNPCsAndPlayer::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask )
-{
- if ( CTraceFilterSimple::ShouldHitEntity( pHandleEntity, contentsMask ) )
- {
- CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity );
- if ( !pEntity )
- return false;
-
-#ifdef CSTRIKE_DLL
-#ifndef CLIENT_DLL
- if ( pEntity->Classify() == CLASS_PLAYER_ALLY )
- return true; // CS hostages are CLASS_PLAYER_ALLY but not IsNPC()
-#endif // !CLIENT_DLL
-#endif // CSTRIKE_DLL
- return (pEntity->IsNPC() || pEntity->IsPlayer());
- }
- return false;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Trace filter that only hits anything but NPCs and the player
-//-----------------------------------------------------------------------------
-bool CTraceFilterNoNPCsOrPlayer::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask )
-{
- if ( CTraceFilterSimple::ShouldHitEntity( pHandleEntity, contentsMask ) )
- {
- CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity );
- if ( !pEntity )
- return NULL;
-#ifndef CLIENT_DLL
- if ( pEntity->Classify() == CLASS_PLAYER_ALLY )
- return false; // CS hostages are CLASS_PLAYER_ALLY but not IsNPC()
-#endif
- return (!pEntity->IsNPC() && !pEntity->IsPlayer());
- }
- return false;
-}
-
-//-----------------------------------------------------------------------------
-// Trace filter that skips two entities
-//-----------------------------------------------------------------------------
-CTraceFilterSkipTwoEntities::CTraceFilterSkipTwoEntities( const IHandleEntity *passentity, const IHandleEntity *passentity2, int collisionGroup ) :
- BaseClass( passentity, collisionGroup ), m_pPassEnt2(passentity2)
-{
-}
-
-bool CTraceFilterSkipTwoEntities::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask )
-{
- Assert( pHandleEntity );
- if ( !PassServerEntityFilter( pHandleEntity, m_pPassEnt2 ) )
- return false;
-
- return BaseClass::ShouldHitEntity( pHandleEntity, contentsMask );
-}
-
-
-//-----------------------------------------------------------------------------
-// Trace filter that can take a list of entities to ignore
-//-----------------------------------------------------------------------------
-CTraceFilterSimpleList::CTraceFilterSimpleList( int collisionGroup ) :
- CTraceFilterSimple( NULL, collisionGroup )
-{
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-bool CTraceFilterSimpleList::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask )
-{
- if ( m_PassEntities.Find(pHandleEntity) != m_PassEntities.InvalidIndex() )
- return false;
-
- return CTraceFilterSimple::ShouldHitEntity( pHandleEntity, contentsMask );
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Add an entity to my list of entities to ignore in the trace
-//-----------------------------------------------------------------------------
-void CTraceFilterSimpleList::AddEntityToIgnore( IHandleEntity *pEntity )
-{
- m_PassEntities.AddToTail( pEntity );
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Custom trace filter used for NPC LOS traces
-//-----------------------------------------------------------------------------
-CTraceFilterLOS::CTraceFilterLOS( IHandleEntity *pHandleEntity, int collisionGroup, IHandleEntity *pHandleEntity2 ) :
- CTraceFilterSkipTwoEntities( pHandleEntity, pHandleEntity2, collisionGroup )
-{
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-bool CTraceFilterLOS::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask )
-{
- CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity );
-
- if ( !pEntity->BlocksLOS() )
- return false;
-
- return CTraceFilterSimple::ShouldHitEntity( pHandleEntity, contentsMask );
-}
-
-//-----------------------------------------------------------------------------
-// Trace filter that can take a classname to ignore
-//-----------------------------------------------------------------------------
-CTraceFilterSkipClassname::CTraceFilterSkipClassname( const IHandleEntity *passentity, const char *pchClassname, int collisionGroup ) :
-CTraceFilterSimple( passentity, collisionGroup ), m_pchClassname( pchClassname )
-{
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-bool CTraceFilterSkipClassname::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask )
-{
- CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity );
- if ( !pEntity || FClassnameIs( pEntity, m_pchClassname ) )
- return false;
-
- return CTraceFilterSimple::ShouldHitEntity( pHandleEntity, contentsMask );
-}
-
-//-----------------------------------------------------------------------------
-// Trace filter that skips two classnames
-//-----------------------------------------------------------------------------
-CTraceFilterSkipTwoClassnames::CTraceFilterSkipTwoClassnames( const IHandleEntity *passentity, const char *pchClassname, const char *pchClassname2, int collisionGroup ) :
-BaseClass( passentity, pchClassname, collisionGroup ), m_pchClassname2(pchClassname2)
-{
-}
-
-bool CTraceFilterSkipTwoClassnames::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask )
-{
- CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity );
- if ( !pEntity || FClassnameIs( pEntity, m_pchClassname2 ) )
- return false;
-
- return BaseClass::ShouldHitEntity( pHandleEntity, contentsMask );
-}
-
-//-----------------------------------------------------------------------------
-// Trace filter that can take a list of entities to ignore
-//-----------------------------------------------------------------------------
-CTraceFilterSimpleClassnameList::CTraceFilterSimpleClassnameList( const IHandleEntity *passentity, int collisionGroup ) :
-CTraceFilterSimple( passentity, collisionGroup )
-{
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-bool CTraceFilterSimpleClassnameList::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask )
-{
- CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity );
- if ( !pEntity )
- return false;
-
- for ( int i = 0; i < m_PassClassnames.Count(); ++i )
- {
- if ( FClassnameIs( pEntity, m_PassClassnames[ i ] ) )
- return false;
- }
-
- return CTraceFilterSimple::ShouldHitEntity( pHandleEntity, contentsMask );
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Add an entity to my list of entities to ignore in the trace
-//-----------------------------------------------------------------------------
-void CTraceFilterSimpleClassnameList::AddClassnameToIgnore( const char *pchClassname )
-{
- m_PassClassnames.AddToTail( pchClassname );
-}
-
-CTraceFilterChain::CTraceFilterChain( ITraceFilter *pTraceFilter1, ITraceFilter *pTraceFilter2 )
-{
- m_pTraceFilter1 = pTraceFilter1;
- m_pTraceFilter2 = pTraceFilter2;
-}
-
-bool CTraceFilterChain::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask )
-{
- bool bResult1 = true;
- bool bResult2 = true;
-
- if ( m_pTraceFilter1 )
- bResult1 = m_pTraceFilter1->ShouldHitEntity( pHandleEntity, contentsMask );
-
- if ( m_pTraceFilter2 )
- bResult2 = m_pTraceFilter2->ShouldHitEntity( pHandleEntity, contentsMask );
-
- return ( bResult1 && bResult2 );
-}
-
-//-----------------------------------------------------------------------------
-// Sweeps against a particular model, using collision rules
-//-----------------------------------------------------------------------------
-void UTIL_TraceModel( const Vector &vecStart, const Vector &vecEnd, const Vector &hullMin,
- const Vector &hullMax, CBaseEntity *pentModel, int collisionGroup, trace_t *ptr )
-{
- // Cull it....
- if ( pentModel && pentModel->ShouldCollide( collisionGroup, MASK_ALL ) )
- {
- Ray_t ray;
- ray.Init( vecStart, vecEnd, hullMin, hullMax );
- enginetrace->ClipRayToEntity( ray, MASK_ALL, pentModel, ptr );
- }
- else
- {
- memset( ptr, 0, sizeof(trace_t) );
- ptr->fraction = 1.0f;
- }
-}
-
-bool UTIL_EntityHasMatchingRootParent( CBaseEntity *pRootParent, CBaseEntity *pEntity )
-{
- if ( pRootParent )
- {
- // NOTE: Don't let siblings/parents collide.
- if ( pRootParent == pEntity->GetRootMoveParent() )
- return true;
- if ( pEntity->GetOwnerEntity() && pRootParent == pEntity->GetOwnerEntity()->GetRootMoveParent() )
- return true;
- }
- return false;
-}
-
-//-----------------------------------------------------------------------------
-// Sweep an entity from the starting to the ending position
-//-----------------------------------------------------------------------------
-class CTraceFilterEntity : public CTraceFilterSimple
-{
- DECLARE_CLASS( CTraceFilterEntity, CTraceFilterSimple );
-
-public:
- CTraceFilterEntity( CBaseEntity *pEntity, int nCollisionGroup )
- : CTraceFilterSimple( pEntity, nCollisionGroup )
- {
- m_pRootParent = pEntity->GetRootMoveParent();
- m_pEntity = pEntity;
- m_checkHash = g_EntityCollisionHash->IsObjectInHash(pEntity);
- }
-
- bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask )
- {
- CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity );
- if ( !pEntity )
- return false;
-
- // Check parents against each other
- // NOTE: Don't let siblings/parents collide.
- if ( UTIL_EntityHasMatchingRootParent( m_pRootParent, pEntity ) )
- return false;
-
- if ( m_checkHash )
- {
- if ( g_EntityCollisionHash->IsObjectPairInHash( m_pEntity, pEntity ) )
- return false;
- }
-
-#ifndef CLIENT_DLL
- if ( m_pEntity->IsNPC() )
- {
- if ( NPC_CheckBrushExclude( m_pEntity, pEntity ) )
- return false;
-
- }
-#endif
-
- return BaseClass::ShouldHitEntity( pHandleEntity, contentsMask );
- }
-
-private:
-
- CBaseEntity *m_pRootParent;
- CBaseEntity *m_pEntity;
- bool m_checkHash;
-};
-
-class CTraceFilterEntityIgnoreOther : public CTraceFilterEntity
-{
- DECLARE_CLASS( CTraceFilterEntityIgnoreOther, CTraceFilterEntity );
-public:
- CTraceFilterEntityIgnoreOther( CBaseEntity *pEntity, const IHandleEntity *pIgnore, int nCollisionGroup ) :
- CTraceFilterEntity( pEntity, nCollisionGroup ), m_pIgnoreOther( pIgnore )
- {
- }
-
- bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask )
- {
- if ( pHandleEntity == m_pIgnoreOther )
- return false;
-
- return BaseClass::ShouldHitEntity( pHandleEntity, contentsMask );
- }
-
-private:
- const IHandleEntity *m_pIgnoreOther;
-};
-
-//-----------------------------------------------------------------------------
-// Sweeps a particular entity through the world
-//-----------------------------------------------------------------------------
-void UTIL_TraceEntity( CBaseEntity *pEntity, const Vector &vecAbsStart, const Vector &vecAbsEnd, unsigned int mask, trace_t *ptr )
-{
- ICollideable *pCollision = pEntity->GetCollideable();
-
- // Adding this assertion here so game code catches it, but really the assertion belongs in the engine
- // because one day, rotated collideables will work!
- Assert( pCollision->GetCollisionAngles() == vec3_angle );
-
- CTraceFilterEntity traceFilter( pEntity, pCollision->GetCollisionGroup() );
-
-#ifdef PORTAL
- UTIL_Portal_TraceEntity( pEntity, vecAbsStart, vecAbsEnd, mask, &traceFilter, ptr );
-#else
- enginetrace->SweepCollideable( pCollision, vecAbsStart, vecAbsEnd, pCollision->GetCollisionAngles(), mask, &traceFilter, ptr );
-#endif
-}
-
-void UTIL_TraceEntity( CBaseEntity *pEntity, const Vector &vecAbsStart, const Vector &vecAbsEnd,
- unsigned int mask, const IHandleEntity *pIgnore, int nCollisionGroup, trace_t *ptr )
-{
- ICollideable *pCollision;
- pCollision = pEntity->GetCollideable();
-
- // Adding this assertion here so game code catches it, but really the assertion belongs in the engine
- // because one day, rotated collideables will work!
- Assert( pCollision->GetCollisionAngles() == vec3_angle );
-
- CTraceFilterEntityIgnoreOther traceFilter( pEntity, pIgnore, nCollisionGroup );
-
-#ifdef PORTAL
- UTIL_Portal_TraceEntity( pEntity, vecAbsStart, vecAbsEnd, mask, &traceFilter, ptr );
-#else
- enginetrace->SweepCollideable( pCollision, vecAbsStart, vecAbsEnd, pCollision->GetCollisionAngles(), mask, &traceFilter, ptr );
-#endif
-}
-
-void UTIL_TraceEntity( CBaseEntity *pEntity, const Vector &vecAbsStart, const Vector &vecAbsEnd,
- unsigned int mask, ITraceFilter *pFilter, trace_t *ptr )
-{
- ICollideable *pCollision;
- pCollision = pEntity->GetCollideable();
-
- // Adding this assertion here so game code catches it, but really the assertion belongs in the engine
- // because one day, rotated collideables will work!
- Assert( pCollision->GetCollisionAngles() == vec3_angle );
-
-#ifdef PORTAL
- UTIL_Portal_TraceEntity( pEntity, vecAbsStart, vecAbsEnd, mask, pFilter, ptr );
-#else
- enginetrace->SweepCollideable( pCollision, vecAbsStart, vecAbsEnd, pCollision->GetCollisionAngles(), mask, pFilter, ptr );
-#endif
-}
-
-// ----
-// This is basically a regular TraceLine that uses the FilterEntity filter.
-void UTIL_TraceLineFilterEntity( CBaseEntity *pEntity, const Vector &vecAbsStart, const Vector &vecAbsEnd,
- unsigned int mask, int nCollisionGroup, trace_t *ptr )
-{
- CTraceFilterEntity traceFilter( pEntity, nCollisionGroup );
- UTIL_TraceLine( vecAbsStart, vecAbsEnd, mask, &traceFilter, ptr );
-}
-
-void UTIL_ClipTraceToPlayers( const Vector& vecAbsStart, const Vector& vecAbsEnd, unsigned int mask, ITraceFilter *filter, trace_t *tr )
-{
- trace_t playerTrace;
- Ray_t ray;
- float smallestFraction = tr->fraction;
- const float maxRange = 60.0f;
-
- ray.Init( vecAbsStart, vecAbsEnd );
-
- for ( int k = 1; k <= gpGlobals->maxClients; ++k )
- {
- CBasePlayer *player = UTIL_PlayerByIndex( k );
-
- if ( !player || !player->IsAlive() )
- continue;
-
-#ifdef CLIENT_DLL
- if ( player->IsDormant() )
- continue;
-#endif // CLIENT_DLL
-
- if ( filter && filter->ShouldHitEntity( player, mask ) == false )
- continue;
-
- float range = DistanceToRay( player->WorldSpaceCenter(), vecAbsStart, vecAbsEnd );
- if ( range < 0.0f || range > maxRange )
- continue;
-
- enginetrace->ClipRayToEntity( ray, mask|CONTENTS_HITBOX, player, &playerTrace );
- if ( playerTrace.fraction < smallestFraction )
- {
- // we shortened the ray - save off the trace
- *tr = playerTrace;
- smallestFraction = playerTrace.fraction;
- }
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Make a tracer using a particle effect
-//-----------------------------------------------------------------------------
-void UTIL_ParticleTracer( const char *pszTracerEffectName, const Vector &vecStart, const Vector &vecEnd,
- int iEntIndex, int iAttachment, bool bWhiz )
-{
- int iParticleIndex = GetParticleSystemIndex( pszTracerEffectName );
- UTIL_Tracer( vecStart, vecEnd, iEntIndex, iAttachment, 0, bWhiz, "ParticleTracer", iParticleIndex );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Make a tracer effect using the old, non-particle system, tracer effects.
-//-----------------------------------------------------------------------------
-void UTIL_Tracer( const Vector &vecStart, const Vector &vecEnd, int iEntIndex,
- int iAttachment, float flVelocity, bool bWhiz, const char *pCustomTracerName, int iParticleID )
-{
- CEffectData data;
- data.m_vStart = vecStart;
- data.m_vOrigin = vecEnd;
-#ifdef CLIENT_DLL
- data.m_hEntity = ClientEntityList().EntIndexToHandle( iEntIndex );
-#else
- data.m_nEntIndex = iEntIndex;
-#endif
- data.m_flScale = flVelocity;
- data.m_nHitBox = iParticleID;
-
- // Flags
- if ( bWhiz )
- {
- data.m_fFlags |= TRACER_FLAG_WHIZ;
- }
-
- if ( iAttachment != TRACER_DONT_USE_ATTACHMENT )
- {
- data.m_fFlags |= TRACER_FLAG_USEATTACHMENT;
- data.m_nAttachmentIndex = iAttachment;
- }
-
- // Fire it off
- if ( pCustomTracerName )
- {
- DispatchEffect( pCustomTracerName, data );
- }
- else
- {
- DispatchEffect( "Tracer", data );
- }
-}
-
-
-void UTIL_BloodDrips( const Vector &origin, const Vector &direction, int color, int amount )
-{
- if ( !UTIL_ShouldShowBlood( color ) )
- return;
-
- if ( color == DONT_BLEED || amount == 0 )
- return;
-
- if ( g_Language.GetInt() == LANGUAGE_GERMAN && color == BLOOD_COLOR_RED )
- color = 0;
-
- if ( g_pGameRules->IsMultiplayer() )
- {
- // scale up blood effect in multiplayer for better visibility
- amount *= 5;
- }
-
- if ( amount > 255 )
- amount = 255;
-
- if (color == BLOOD_COLOR_MECH)
- {
- g_pEffects->Sparks(origin);
- if (random->RandomFloat(0, 2) >= 1)
- {
- UTIL_Smoke(origin, random->RandomInt(10, 15), 10);
- }
- }
- else
- {
- // Normal blood impact
- UTIL_BloodImpact( origin, direction, color, amount );
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Returns low violence settings
-//-----------------------------------------------------------------------------
-static ConVar violence_hblood( "violence_hblood","1", 0, "Draw human blood" );
-static ConVar violence_hgibs( "violence_hgibs","1", 0, "Show human gib entities" );
-static ConVar violence_ablood( "violence_ablood","1", 0, "Draw alien blood" );
-static ConVar violence_agibs( "violence_agibs","1", 0, "Show alien gib entities" );
-
-bool UTIL_IsLowViolence( void )
-{
- // These convars are no longer necessary -- the engine is the final arbiter of
- // violence settings -- but they're here for legacy support and for testing low
- // violence when the engine is in normal violence mode.
- if ( !violence_hblood.GetBool() || !violence_ablood.GetBool() || !violence_hgibs.GetBool() || !violence_agibs.GetBool() )
- return true;
-
-#ifdef TF_CLIENT_DLL
- // Use low violence if the local player has an item that allows them to see it (Pyro Goggles)
- if ( IsLocalPlayerUsingVisionFilterFlags( TF_VISION_FILTER_PYRO ) )
- {
- return true;
- }
-#endif
-
- return engine->IsLowViolence();
-}
-
-bool UTIL_ShouldShowBlood( int color )
-{
- if ( color != DONT_BLEED )
- {
- if ( color == BLOOD_COLOR_RED )
- {
- return violence_hblood.GetBool();
- }
- else
- {
- return violence_ablood.GetBool();
- }
- }
- return false;
-}
-
-
-//------------------------------------------------------------------------------
-// Purpose : Use trace to pass a specific decal type to the entity being decaled
-// Input :
-// Output :
-//------------------------------------------------------------------------------
-void UTIL_DecalTrace( trace_t *pTrace, char const *decalName )
-{
- if (pTrace->fraction == 1.0)
- return;
-
- CBaseEntity *pEntity = pTrace->m_pEnt;
- pEntity->DecalTrace( pTrace, decalName );
-}
-
-
-void UTIL_BloodDecalTrace( trace_t *pTrace, int bloodColor )
-{
- if ( UTIL_ShouldShowBlood( bloodColor ) )
- {
- if ( bloodColor == BLOOD_COLOR_RED )
- {
- UTIL_DecalTrace( pTrace, "Blood" );
- }
- else
- {
- UTIL_DecalTrace( pTrace, "YellowBlood" );
- }
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : &pos -
-// &dir -
-// color -
-// amount -
-//-----------------------------------------------------------------------------
-void UTIL_BloodImpact( const Vector &pos, const Vector &dir, int color, int amount )
-{
- CEffectData data;
-
- data.m_vOrigin = pos;
- data.m_vNormal = dir;
- data.m_flScale = (float)amount;
- data.m_nColor = (unsigned char)color;
-
- DispatchEffect( "bloodimpact", data );
-}
-
-bool UTIL_IsSpaceEmpty( CBaseEntity *pMainEnt, const Vector &vMin, const Vector &vMax )
-{
- Vector vHalfDims = ( vMax - vMin ) * 0.5f;
- Vector vCenter = vMin + vHalfDims;
-
- trace_t trace;
- UTIL_TraceHull( vCenter, vCenter, -vHalfDims, vHalfDims, MASK_SOLID, pMainEnt, COLLISION_GROUP_NONE, &trace );
-
- bool bClear = ( trace.fraction == 1 && trace.allsolid != 1 && (trace.startsolid != 1) );
- return bClear;
-}
-
-void UTIL_StringToFloatArray( float *pVector, int count, const char *pString )
-{
- char *pstr, *pfront, tempString[128];
- int j;
-
- Q_strncpy( tempString, pString, sizeof(tempString) );
- pstr = pfront = tempString;
-
- for ( j = 0; j < count; j++ ) // lifted from pr_edict.c
- {
- pVector[j] = atof( pfront );
-
- // skip any leading whitespace
- while ( *pstr && *pstr <= ' ' )
- pstr++;
-
- // skip to next whitespace
- while ( *pstr && *pstr > ' ' )
- pstr++;
-
- if (!*pstr)
- break;
-
- pstr++;
- pfront = pstr;
- }
- for ( j++; j < count; j++ )
- {
- pVector[j] = 0;
- }
-}
-
-void UTIL_StringToVector( float *pVector, const char *pString )
-{
- UTIL_StringToFloatArray( pVector, 3, pString );
-}
-
-void UTIL_StringToIntArray( int *pVector, int count, const char *pString )
-{
- char *pstr, *pfront, tempString[128];
- int j;
-
- Q_strncpy( tempString, pString, sizeof(tempString) );
- pstr = pfront = tempString;
-
- for ( j = 0; j < count; j++ ) // lifted from pr_edict.c
- {
- pVector[j] = atoi( pfront );
-
- while ( *pstr && *pstr != ' ' )
- pstr++;
- if (!*pstr)
- break;
- pstr++;
- pfront = pstr;
- }
-
- for ( j++; j < count; j++ )
- {
- pVector[j] = 0;
- }
-}
-
-void UTIL_StringToColor32( color32 *color, const char *pString )
-{
- int tmp[4];
- UTIL_StringToIntArray( tmp, 4, pString );
- color->r = tmp[0];
- color->g = tmp[1];
- color->b = tmp[2];
- color->a = tmp[3];
-}
-
-#ifndef _XBOX
-void UTIL_DecodeICE( unsigned char * buffer, int size, const unsigned char *key)
-{
- if ( !key )
- return;
-
- IceKey ice( 0 ); // level 0 = 64bit key
- ice.set( key ); // set key
-
- int blockSize = ice.blockSize();
-
- unsigned char *temp = (unsigned char *)_alloca( PAD_NUMBER( size, blockSize ) );
- unsigned char *p1 = buffer;
- unsigned char *p2 = temp;
-
- // encrypt data in 8 byte blocks
- int bytesLeft = size;
- while ( bytesLeft >= blockSize )
- {
- ice.decrypt( p1, p2 );
- bytesLeft -= blockSize;
- p1+=blockSize;
- p2+=blockSize;
- }
-
- // copy encrypted data back to original buffer
- Q_memcpy( buffer, temp, size-bytesLeft );
-}
-#endif
-
-// work-around since client header doesn't like inlined gpGlobals->curtime
-float IntervalTimer::Now( void ) const
-{
- return gpGlobals->curtime;
-}
-
-// work-around since client header doesn't like inlined gpGlobals->curtime
-float CountdownTimer::Now( void ) const
-{
- return gpGlobals->curtime;
-}
-
-
-#ifdef CLIENT_DLL
- CBasePlayer *UTIL_PlayerByIndex( int entindex )
- {
- return ToBasePlayer( ClientEntityList().GetEnt( entindex ) );
- }
-
-//=============================================================================
-// HPE_BEGIN:
-// [menglish] Added UTIL function for events in client win_panel which transmit the player as a user ID
-//=============================================================================
-
- CBasePlayer* UTIL_PlayerByUserId( int userID )
- {
- for (int i = 1; i<=gpGlobals->maxClients; i++ )
- {
- CBasePlayer *pPlayer = UTIL_PlayerByIndex( i );
-
- if ( !pPlayer )
- continue;
-
- if ( pPlayer->GetUserID() == userID )
- {
- return pPlayer;
- }
- }
-
- return NULL;
- }
-
-//=============================================================================
-// HPE_END
-//=============================================================================
-
-#endif
-
-
-char* ReadAndAllocStringValue( KeyValues *pSub, const char *pName, const char *pFilename )
-{
- const char *pValue = pSub->GetString( pName, NULL );
- if ( !pValue )
- {
- if ( pFilename )
- {
- DevWarning( "Can't get key value '%s' from file '%s'.\n", pName, pFilename );
- }
- return "";
- }
-
- int len = Q_strlen( pValue ) + 1;
- char *pAlloced = new char[ len ];
- Assert( pAlloced );
- Q_strncpy( pAlloced, pValue, len );
- return pAlloced;
-}
-
-int UTIL_StringFieldToInt( const char *szValue, const char **pValueStrings, int iNumStrings )
-{
- if ( !szValue || !szValue[0] )
- return -1;
-
- for ( int i = 0; i < iNumStrings; i++ )
- {
- if ( FStrEq(szValue, pValueStrings[i]) )
- return i;
- }
-
- Assert(0);
- return -1;
-}
-
-
-int find_day_of_week( struct tm& found_day, int day_of_week, int step )
-{
- return 0;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-#ifdef USES_ECON_ITEMS
-static bool s_HolidaysCalculated = false;
-static CBitVec<kHolidayCount> s_HolidaysActive;
-
-//-----------------------------------------------------------------------------
-// Purpose: Used at level change and round start to re-calculate which holiday is active
-//-----------------------------------------------------------------------------
-void UTIL_CalculateHolidays()
-{
- s_HolidaysActive.ClearAll();
-
- CRTime::UpdateRealTime();
- for ( int iHoliday = 0; iHoliday < kHolidayCount; iHoliday++ )
- {
- if ( EconHolidays_IsHolidayActive( iHoliday, CRTime::RTime32TimeCur() ) )
- {
- s_HolidaysActive.Set( iHoliday );
- }
- }
-
- s_HolidaysCalculated = true;
-}
-#endif // USES_ECON_ITEMS
-
-bool UTIL_IsHolidayActive( /*EHoliday*/ int eHoliday )
-{
-#ifdef USES_ECON_ITEMS
- if ( IsX360() )
- return false;
-
- if ( !s_HolidaysCalculated )
- {
- UTIL_CalculateHolidays();
- }
-
- return s_HolidaysActive.IsBitSet( eHoliday );
-#else
- return false;
-#endif
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-int UTIL_GetHolidayForString( const char* pszHolidayName )
-{
-#ifdef USES_ECON_ITEMS
- if ( !pszHolidayName )
- return kHoliday_None;
-
- return EconHolidays_GetHolidayForString( pszHolidayName );
-#else
- return 0;
-#endif
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-const char* UTIL_GetActiveHolidayString()
-{
-#ifdef USES_ECON_ITEMS
- return EconHolidays_GetActiveHolidayString();
-#else
- return NULL;
-#endif
-}
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#include "cbase.h"
+#include "mathlib/mathlib.h"
+#include "util_shared.h"
+#include "model_types.h"
+#include "convar.h"
+#include "IEffects.h"
+#include "vphysics/object_hash.h"
+#include "mathlib/IceKey.H"
+#include "checksum_crc.h"
+#ifdef TF_CLIENT_DLL
+#include "cdll_util.h"
+#endif
+#include "particle_parse.h"
+#include "KeyValues.h"
+#include "time.h"
+
+#ifdef USES_ECON_ITEMS
+ #include "econ_item_constants.h"
+ #include "econ_holidays.h"
+ #include "rtime.h"
+#endif // USES_ECON_ITEMS
+
+#ifdef CLIENT_DLL
+ #include "c_te_effect_dispatch.h"
+#else
+ #include "te_effect_dispatch.h"
+
+bool NPC_CheckBrushExclude( CBaseEntity *pEntity, CBaseEntity *pBrush );
+#endif
+
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+ConVar r_visualizetraces( "r_visualizetraces", "0", FCVAR_CHEAT );
+ConVar developer("developer", "0", 0, "Set developer message level" ); // developer mode
+
+float UTIL_VecToYaw( const Vector &vec )
+{
+ if (vec.y == 0 && vec.x == 0)
+ return 0;
+
+ float yaw = atan2( vec.y, vec.x );
+
+ yaw = RAD2DEG(yaw);
+
+ if (yaw < 0)
+ yaw += 360;
+
+ return yaw;
+}
+
+
+float UTIL_VecToPitch( const Vector &vec )
+{
+ if (vec.y == 0 && vec.x == 0)
+ {
+ if (vec.z < 0)
+ return 180.0;
+ else
+ return -180.0;
+ }
+
+ float dist = vec.Length2D();
+ float pitch = atan2( -vec.z, dist );
+
+ pitch = RAD2DEG(pitch);
+
+ return pitch;
+}
+
+float UTIL_VecToYaw( const matrix3x4_t &matrix, const Vector &vec )
+{
+ Vector tmp = vec;
+ VectorNormalize( tmp );
+
+ float x = matrix[0][0] * tmp.x + matrix[1][0] * tmp.y + matrix[2][0] * tmp.z;
+ float y = matrix[0][1] * tmp.x + matrix[1][1] * tmp.y + matrix[2][1] * tmp.z;
+
+ if (x == 0.0f && y == 0.0f)
+ return 0.0f;
+
+ float yaw = atan2( -y, x );
+
+ yaw = RAD2DEG(yaw);
+
+ if (yaw < 0)
+ yaw += 360;
+
+ return yaw;
+}
+
+
+float UTIL_VecToPitch( const matrix3x4_t &matrix, const Vector &vec )
+{
+ Vector tmp = vec;
+ VectorNormalize( tmp );
+
+ float x = matrix[0][0] * tmp.x + matrix[1][0] * tmp.y + matrix[2][0] * tmp.z;
+ float z = matrix[0][2] * tmp.x + matrix[1][2] * tmp.y + matrix[2][2] * tmp.z;
+
+ if (x == 0.0f && z == 0.0f)
+ return 0.0f;
+
+ float pitch = atan2( z, x );
+
+ pitch = RAD2DEG(pitch);
+
+ if (pitch < 0)
+ pitch += 360;
+
+ return pitch;
+}
+
+Vector UTIL_YawToVector( float yaw )
+{
+ Vector ret;
+
+ ret.z = 0;
+ float angle = DEG2RAD( yaw );
+ SinCos( angle, &ret.y, &ret.x );
+
+ return ret;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Helper function get get determinisitc random values for shared/prediction code
+// Input : seedvalue -
+// *module -
+// line -
+// Output : static int
+//-----------------------------------------------------------------------------
+static int SeedFileLineHash( int seedvalue, const char *sharedname, int additionalSeed )
+{
+ CRC32_t retval;
+
+ CRC32_Init( &retval );
+
+ CRC32_ProcessBuffer( &retval, (void *)&seedvalue, sizeof( int ) );
+ CRC32_ProcessBuffer( &retval, (void *)&additionalSeed, sizeof( int ) );
+ CRC32_ProcessBuffer( &retval, (void *)sharedname, Q_strlen( sharedname ) );
+
+ CRC32_Final( &retval );
+
+ return (int)( retval );
+}
+
+float SharedRandomFloat( const char *sharedname, float flMinVal, float flMaxVal, int additionalSeed /*=0*/ )
+{
+ Assert( CBaseEntity::GetPredictionRandomSeed() != -1 );
+
+ int seed = SeedFileLineHash( CBaseEntity::GetPredictionRandomSeed(), sharedname, additionalSeed );
+ RandomSeed( seed );
+ return RandomFloat( flMinVal, flMaxVal );
+}
+
+int SharedRandomInt( const char *sharedname, int iMinVal, int iMaxVal, int additionalSeed /*=0*/ )
+{
+ Assert( CBaseEntity::GetPredictionRandomSeed() != -1 );
+
+ int seed = SeedFileLineHash( CBaseEntity::GetPredictionRandomSeed(), sharedname, additionalSeed );
+ RandomSeed( seed );
+ return RandomInt( iMinVal, iMaxVal );
+}
+
+Vector SharedRandomVector( const char *sharedname, float minVal, float maxVal, int additionalSeed /*=0*/ )
+{
+ Assert( CBaseEntity::GetPredictionRandomSeed() != -1 );
+
+ int seed = SeedFileLineHash( CBaseEntity::GetPredictionRandomSeed(), sharedname, additionalSeed );
+ RandomSeed( seed );
+ // HACK: Can't call RandomVector/Angle because it uses rand() not vstlib Random*() functions!
+ // Get a random vector.
+ Vector random;
+ random.x = RandomFloat( minVal, maxVal );
+ random.y = RandomFloat( minVal, maxVal );
+ random.z = RandomFloat( minVal, maxVal );
+ return random;
+}
+
+QAngle SharedRandomAngle( const char *sharedname, float minVal, float maxVal, int additionalSeed /*=0*/ )
+{
+ Assert( CBaseEntity::GetPredictionRandomSeed() != -1 );
+
+ int seed = SeedFileLineHash( CBaseEntity::GetPredictionRandomSeed(), sharedname, additionalSeed );
+ RandomSeed( seed );
+
+ // HACK: Can't call RandomVector/Angle because it uses rand() not vstlib Random*() functions!
+ // Get a random vector.
+ Vector random;
+ random.x = RandomFloat( minVal, maxVal );
+ random.y = RandomFloat( minVal, maxVal );
+ random.z = RandomFloat( minVal, maxVal );
+ return QAngle( random.x, random.y, random.z );
+}
+
+
+//-----------------------------------------------------------------------------
+//
+// Shared client/server trace filter code
+//
+//-----------------------------------------------------------------------------
+bool PassServerEntityFilter( const IHandleEntity *pTouch, const IHandleEntity *pPass )
+{
+ if ( !pPass )
+ return true;
+
+ if ( pTouch == pPass )
+ return false;
+
+ const CBaseEntity *pEntTouch = EntityFromEntityHandle( pTouch );
+ const CBaseEntity *pEntPass = EntityFromEntityHandle( pPass );
+ if ( !pEntTouch || !pEntPass )
+ return true;
+
+ // don't clip against own missiles
+ if ( pEntTouch->GetOwnerEntity() == pEntPass )
+ return false;
+
+ // don't clip against owner
+ if ( pEntPass->GetOwnerEntity() == pEntTouch )
+ return false;
+
+
+ return true;
+}
+
+
+//-----------------------------------------------------------------------------
+// A standard filter to be applied to just about everything.
+//-----------------------------------------------------------------------------
+bool StandardFilterRules( IHandleEntity *pHandleEntity, int fContentsMask )
+{
+ CBaseEntity *pCollide = EntityFromEntityHandle( pHandleEntity );
+
+ // Static prop case...
+ if ( !pCollide )
+ return true;
+
+ SolidType_t solid = pCollide->GetSolid();
+ const model_t *pModel = pCollide->GetModel();
+
+ if ( ( modelinfo->GetModelType( pModel ) != mod_brush ) || (solid != SOLID_BSP && solid != SOLID_VPHYSICS) )
+ {
+ if ( (fContentsMask & CONTENTS_MONSTER) == 0 )
+ return false;
+ }
+
+ // This code is used to cull out tests against see-thru entities
+ if ( !(fContentsMask & CONTENTS_WINDOW) && pCollide->IsTransparent() )
+ return false;
+
+ // FIXME: this is to skip BSP models that are entities that can be
+ // potentially moved/deleted, similar to a monster but doors don't seem to
+ // be flagged as monsters
+ // FIXME: the FL_WORLDBRUSH looked promising, but it needs to be set on
+ // everything that's actually a worldbrush and it currently isn't
+ if ( !(fContentsMask & CONTENTS_MOVEABLE) && (pCollide->GetMoveType() == MOVETYPE_PUSH))// !(touch->flags & FL_WORLDBRUSH) )
+ return false;
+
+ return true;
+}
+
+
+//-----------------------------------------------------------------------------
+// Simple trace filter
+//-----------------------------------------------------------------------------
+CTraceFilterSimple::CTraceFilterSimple( const IHandleEntity *passedict, int collisionGroup,
+ ShouldHitFunc_t pExtraShouldHitFunc )
+{
+ m_pPassEnt = passedict;
+ m_collisionGroup = collisionGroup;
+ m_pExtraShouldHitCheckFunction = pExtraShouldHitFunc;
+}
+
+//-----------------------------------------------------------------------------
+// The trace filter!
+//-----------------------------------------------------------------------------
+bool CTraceFilterSimple::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask )
+{
+ if ( !StandardFilterRules( pHandleEntity, contentsMask ) )
+ return false;
+
+ if ( m_pPassEnt )
+ {
+ if ( !PassServerEntityFilter( pHandleEntity, m_pPassEnt ) )
+ {
+ return false;
+ }
+ }
+
+ // Don't test if the game code tells us we should ignore this collision...
+ CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity );
+ if ( !pEntity )
+ return false;
+ if ( !pEntity->ShouldCollide( m_collisionGroup, contentsMask ) )
+ return false;
+ if ( pEntity && !g_pGameRules->ShouldCollide( m_collisionGroup, pEntity->GetCollisionGroup() ) )
+ return false;
+ if ( m_pExtraShouldHitCheckFunction &&
+ (! ( m_pExtraShouldHitCheckFunction( pHandleEntity, contentsMask ) ) ) )
+ return false;
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Trace filter that only hits NPCs and the player
+//-----------------------------------------------------------------------------
+bool CTraceFilterOnlyNPCsAndPlayer::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask )
+{
+ if ( CTraceFilterSimple::ShouldHitEntity( pHandleEntity, contentsMask ) )
+ {
+ CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity );
+ if ( !pEntity )
+ return false;
+
+#ifdef CSTRIKE_DLL
+#ifndef CLIENT_DLL
+ if ( pEntity->Classify() == CLASS_PLAYER_ALLY )
+ return true; // CS hostages are CLASS_PLAYER_ALLY but not IsNPC()
+#endif // !CLIENT_DLL
+#endif // CSTRIKE_DLL
+ return (pEntity->IsNPC() || pEntity->IsPlayer());
+ }
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Trace filter that only hits anything but NPCs and the player
+//-----------------------------------------------------------------------------
+bool CTraceFilterNoNPCsOrPlayer::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask )
+{
+ if ( CTraceFilterSimple::ShouldHitEntity( pHandleEntity, contentsMask ) )
+ {
+ CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity );
+ if ( !pEntity )
+ return NULL;
+#ifndef CLIENT_DLL
+ if ( pEntity->Classify() == CLASS_PLAYER_ALLY )
+ return false; // CS hostages are CLASS_PLAYER_ALLY but not IsNPC()
+#endif
+ return (!pEntity->IsNPC() && !pEntity->IsPlayer());
+ }
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// Trace filter that skips two entities
+//-----------------------------------------------------------------------------
+CTraceFilterSkipTwoEntities::CTraceFilterSkipTwoEntities( const IHandleEntity *passentity, const IHandleEntity *passentity2, int collisionGroup ) :
+ BaseClass( passentity, collisionGroup ), m_pPassEnt2(passentity2)
+{
+}
+
+bool CTraceFilterSkipTwoEntities::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask )
+{
+ Assert( pHandleEntity );
+ if ( !PassServerEntityFilter( pHandleEntity, m_pPassEnt2 ) )
+ return false;
+
+ return BaseClass::ShouldHitEntity( pHandleEntity, contentsMask );
+}
+
+
+//-----------------------------------------------------------------------------
+// Trace filter that can take a list of entities to ignore
+//-----------------------------------------------------------------------------
+CTraceFilterSimpleList::CTraceFilterSimpleList( int collisionGroup ) :
+ CTraceFilterSimple( NULL, collisionGroup )
+{
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+bool CTraceFilterSimpleList::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask )
+{
+ if ( m_PassEntities.Find(pHandleEntity) != m_PassEntities.InvalidIndex() )
+ return false;
+
+ return CTraceFilterSimple::ShouldHitEntity( pHandleEntity, contentsMask );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Add an entity to my list of entities to ignore in the trace
+//-----------------------------------------------------------------------------
+void CTraceFilterSimpleList::AddEntityToIgnore( IHandleEntity *pEntity )
+{
+ m_PassEntities.AddToTail( pEntity );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Custom trace filter used for NPC LOS traces
+//-----------------------------------------------------------------------------
+CTraceFilterLOS::CTraceFilterLOS( IHandleEntity *pHandleEntity, int collisionGroup, IHandleEntity *pHandleEntity2 ) :
+ CTraceFilterSkipTwoEntities( pHandleEntity, pHandleEntity2, collisionGroup )
+{
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+bool CTraceFilterLOS::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask )
+{
+ CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity );
+
+ if ( !pEntity->BlocksLOS() )
+ return false;
+
+ return CTraceFilterSimple::ShouldHitEntity( pHandleEntity, contentsMask );
+}
+
+//-----------------------------------------------------------------------------
+// Trace filter that can take a classname to ignore
+//-----------------------------------------------------------------------------
+CTraceFilterSkipClassname::CTraceFilterSkipClassname( const IHandleEntity *passentity, const char *pchClassname, int collisionGroup ) :
+CTraceFilterSimple( passentity, collisionGroup ), m_pchClassname( pchClassname )
+{
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+bool CTraceFilterSkipClassname::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask )
+{
+ CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity );
+ if ( !pEntity || FClassnameIs( pEntity, m_pchClassname ) )
+ return false;
+
+ return CTraceFilterSimple::ShouldHitEntity( pHandleEntity, contentsMask );
+}
+
+//-----------------------------------------------------------------------------
+// Trace filter that skips two classnames
+//-----------------------------------------------------------------------------
+CTraceFilterSkipTwoClassnames::CTraceFilterSkipTwoClassnames( const IHandleEntity *passentity, const char *pchClassname, const char *pchClassname2, int collisionGroup ) :
+BaseClass( passentity, pchClassname, collisionGroup ), m_pchClassname2(pchClassname2)
+{
+}
+
+bool CTraceFilterSkipTwoClassnames::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask )
+{
+ CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity );
+ if ( !pEntity || FClassnameIs( pEntity, m_pchClassname2 ) )
+ return false;
+
+ return BaseClass::ShouldHitEntity( pHandleEntity, contentsMask );
+}
+
+//-----------------------------------------------------------------------------
+// Trace filter that can take a list of entities to ignore
+//-----------------------------------------------------------------------------
+CTraceFilterSimpleClassnameList::CTraceFilterSimpleClassnameList( const IHandleEntity *passentity, int collisionGroup ) :
+CTraceFilterSimple( passentity, collisionGroup )
+{
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+bool CTraceFilterSimpleClassnameList::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask )
+{
+ CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity );
+ if ( !pEntity )
+ return false;
+
+ for ( int i = 0; i < m_PassClassnames.Count(); ++i )
+ {
+ if ( FClassnameIs( pEntity, m_PassClassnames[ i ] ) )
+ return false;
+ }
+
+ return CTraceFilterSimple::ShouldHitEntity( pHandleEntity, contentsMask );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Add an entity to my list of entities to ignore in the trace
+//-----------------------------------------------------------------------------
+void CTraceFilterSimpleClassnameList::AddClassnameToIgnore( const char *pchClassname )
+{
+ m_PassClassnames.AddToTail( pchClassname );
+}
+
+CTraceFilterChain::CTraceFilterChain( ITraceFilter *pTraceFilter1, ITraceFilter *pTraceFilter2 )
+{
+ m_pTraceFilter1 = pTraceFilter1;
+ m_pTraceFilter2 = pTraceFilter2;
+}
+
+bool CTraceFilterChain::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask )
+{
+ bool bResult1 = true;
+ bool bResult2 = true;
+
+ if ( m_pTraceFilter1 )
+ bResult1 = m_pTraceFilter1->ShouldHitEntity( pHandleEntity, contentsMask );
+
+ if ( m_pTraceFilter2 )
+ bResult2 = m_pTraceFilter2->ShouldHitEntity( pHandleEntity, contentsMask );
+
+ return ( bResult1 && bResult2 );
+}
+
+//-----------------------------------------------------------------------------
+// Sweeps against a particular model, using collision rules
+//-----------------------------------------------------------------------------
+void UTIL_TraceModel( const Vector &vecStart, const Vector &vecEnd, const Vector &hullMin,
+ const Vector &hullMax, CBaseEntity *pentModel, int collisionGroup, trace_t *ptr )
+{
+ // Cull it....
+ if ( pentModel && pentModel->ShouldCollide( collisionGroup, MASK_ALL ) )
+ {
+ Ray_t ray;
+ ray.Init( vecStart, vecEnd, hullMin, hullMax );
+ enginetrace->ClipRayToEntity( ray, MASK_ALL, pentModel, ptr );
+ }
+ else
+ {
+ memset( ptr, 0, sizeof(trace_t) );
+ ptr->fraction = 1.0f;
+ }
+}
+
+bool UTIL_EntityHasMatchingRootParent( CBaseEntity *pRootParent, CBaseEntity *pEntity )
+{
+ if ( pRootParent )
+ {
+ // NOTE: Don't let siblings/parents collide.
+ if ( pRootParent == pEntity->GetRootMoveParent() )
+ return true;
+ if ( pEntity->GetOwnerEntity() && pRootParent == pEntity->GetOwnerEntity()->GetRootMoveParent() )
+ return true;
+ }
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// Sweep an entity from the starting to the ending position
+//-----------------------------------------------------------------------------
+class CTraceFilterEntity : public CTraceFilterSimple
+{
+ DECLARE_CLASS( CTraceFilterEntity, CTraceFilterSimple );
+
+public:
+ CTraceFilterEntity( CBaseEntity *pEntity, int nCollisionGroup )
+ : CTraceFilterSimple( pEntity, nCollisionGroup )
+ {
+ m_pRootParent = pEntity->GetRootMoveParent();
+ m_pEntity = pEntity;
+ m_checkHash = g_EntityCollisionHash->IsObjectInHash(pEntity);
+ }
+
+ bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask )
+ {
+ CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity );
+ if ( !pEntity )
+ return false;
+
+ // Check parents against each other
+ // NOTE: Don't let siblings/parents collide.
+ if ( UTIL_EntityHasMatchingRootParent( m_pRootParent, pEntity ) )
+ return false;
+
+ if ( m_checkHash )
+ {
+ if ( g_EntityCollisionHash->IsObjectPairInHash( m_pEntity, pEntity ) )
+ return false;
+ }
+
+#ifndef CLIENT_DLL
+ if ( m_pEntity->IsNPC() )
+ {
+ if ( NPC_CheckBrushExclude( m_pEntity, pEntity ) )
+ return false;
+
+ }
+#endif
+
+ return BaseClass::ShouldHitEntity( pHandleEntity, contentsMask );
+ }
+
+private:
+
+ CBaseEntity *m_pRootParent;
+ CBaseEntity *m_pEntity;
+ bool m_checkHash;
+};
+
+class CTraceFilterEntityIgnoreOther : public CTraceFilterEntity
+{
+ DECLARE_CLASS( CTraceFilterEntityIgnoreOther, CTraceFilterEntity );
+public:
+ CTraceFilterEntityIgnoreOther( CBaseEntity *pEntity, const IHandleEntity *pIgnore, int nCollisionGroup ) :
+ CTraceFilterEntity( pEntity, nCollisionGroup ), m_pIgnoreOther( pIgnore )
+ {
+ }
+
+ bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask )
+ {
+ if ( pHandleEntity == m_pIgnoreOther )
+ return false;
+
+ return BaseClass::ShouldHitEntity( pHandleEntity, contentsMask );
+ }
+
+private:
+ const IHandleEntity *m_pIgnoreOther;
+};
+
+//-----------------------------------------------------------------------------
+// Sweeps a particular entity through the world
+//-----------------------------------------------------------------------------
+void UTIL_TraceEntity( CBaseEntity *pEntity, const Vector &vecAbsStart, const Vector &vecAbsEnd, unsigned int mask, trace_t *ptr )
+{
+ ICollideable *pCollision = pEntity->GetCollideable();
+
+ // Adding this assertion here so game code catches it, but really the assertion belongs in the engine
+ // because one day, rotated collideables will work!
+ Assert( pCollision->GetCollisionAngles() == vec3_angle );
+
+ CTraceFilterEntity traceFilter( pEntity, pCollision->GetCollisionGroup() );
+
+#ifdef PORTAL
+ UTIL_Portal_TraceEntity( pEntity, vecAbsStart, vecAbsEnd, mask, &traceFilter, ptr );
+#else
+ enginetrace->SweepCollideable( pCollision, vecAbsStart, vecAbsEnd, pCollision->GetCollisionAngles(), mask, &traceFilter, ptr );
+#endif
+}
+
+void UTIL_TraceEntity( CBaseEntity *pEntity, const Vector &vecAbsStart, const Vector &vecAbsEnd,
+ unsigned int mask, const IHandleEntity *pIgnore, int nCollisionGroup, trace_t *ptr )
+{
+ ICollideable *pCollision;
+ pCollision = pEntity->GetCollideable();
+
+ // Adding this assertion here so game code catches it, but really the assertion belongs in the engine
+ // because one day, rotated collideables will work!
+ Assert( pCollision->GetCollisionAngles() == vec3_angle );
+
+ CTraceFilterEntityIgnoreOther traceFilter( pEntity, pIgnore, nCollisionGroup );
+
+#ifdef PORTAL
+ UTIL_Portal_TraceEntity( pEntity, vecAbsStart, vecAbsEnd, mask, &traceFilter, ptr );
+#else
+ enginetrace->SweepCollideable( pCollision, vecAbsStart, vecAbsEnd, pCollision->GetCollisionAngles(), mask, &traceFilter, ptr );
+#endif
+}
+
+void UTIL_TraceEntity( CBaseEntity *pEntity, const Vector &vecAbsStart, const Vector &vecAbsEnd,
+ unsigned int mask, ITraceFilter *pFilter, trace_t *ptr )
+{
+ ICollideable *pCollision;
+ pCollision = pEntity->GetCollideable();
+
+ // Adding this assertion here so game code catches it, but really the assertion belongs in the engine
+ // because one day, rotated collideables will work!
+ Assert( pCollision->GetCollisionAngles() == vec3_angle );
+
+#ifdef PORTAL
+ UTIL_Portal_TraceEntity( pEntity, vecAbsStart, vecAbsEnd, mask, pFilter, ptr );
+#else
+ enginetrace->SweepCollideable( pCollision, vecAbsStart, vecAbsEnd, pCollision->GetCollisionAngles(), mask, pFilter, ptr );
+#endif
+}
+
+// ----
+// This is basically a regular TraceLine that uses the FilterEntity filter.
+void UTIL_TraceLineFilterEntity( CBaseEntity *pEntity, const Vector &vecAbsStart, const Vector &vecAbsEnd,
+ unsigned int mask, int nCollisionGroup, trace_t *ptr )
+{
+ CTraceFilterEntity traceFilter( pEntity, nCollisionGroup );
+ UTIL_TraceLine( vecAbsStart, vecAbsEnd, mask, &traceFilter, ptr );
+}
+
+void UTIL_ClipTraceToPlayers( const Vector& vecAbsStart, const Vector& vecAbsEnd, unsigned int mask, ITraceFilter *filter, trace_t *tr )
+{
+ trace_t playerTrace;
+ Ray_t ray;
+ float smallestFraction = tr->fraction;
+ const float maxRange = 60.0f;
+
+ ray.Init( vecAbsStart, vecAbsEnd );
+
+ for ( int k = 1; k <= gpGlobals->maxClients; ++k )
+ {
+ CBasePlayer *player = UTIL_PlayerByIndex( k );
+
+ if ( !player || !player->IsAlive() )
+ continue;
+
+#ifdef CLIENT_DLL
+ if ( player->IsDormant() )
+ continue;
+#endif // CLIENT_DLL
+
+ if ( filter && filter->ShouldHitEntity( player, mask ) == false )
+ continue;
+
+ float range = DistanceToRay( player->WorldSpaceCenter(), vecAbsStart, vecAbsEnd );
+ if ( range < 0.0f || range > maxRange )
+ continue;
+
+ enginetrace->ClipRayToEntity( ray, mask|CONTENTS_HITBOX, player, &playerTrace );
+ if ( playerTrace.fraction < smallestFraction )
+ {
+ // we shortened the ray - save off the trace
+ *tr = playerTrace;
+ smallestFraction = playerTrace.fraction;
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Make a tracer using a particle effect
+//-----------------------------------------------------------------------------
+void UTIL_ParticleTracer( const char *pszTracerEffectName, const Vector &vecStart, const Vector &vecEnd,
+ int iEntIndex, int iAttachment, bool bWhiz )
+{
+ int iParticleIndex = GetParticleSystemIndex( pszTracerEffectName );
+ UTIL_Tracer( vecStart, vecEnd, iEntIndex, iAttachment, 0, bWhiz, "ParticleTracer", iParticleIndex );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Make a tracer effect using the old, non-particle system, tracer effects.
+//-----------------------------------------------------------------------------
+void UTIL_Tracer( const Vector &vecStart, const Vector &vecEnd, int iEntIndex,
+ int iAttachment, float flVelocity, bool bWhiz, const char *pCustomTracerName, int iParticleID )
+{
+ CEffectData data;
+ data.m_vStart = vecStart;
+ data.m_vOrigin = vecEnd;
+#ifdef CLIENT_DLL
+ data.m_hEntity = ClientEntityList().EntIndexToHandle( iEntIndex );
+#else
+ data.m_nEntIndex = iEntIndex;
+#endif
+ data.m_flScale = flVelocity;
+ data.m_nHitBox = iParticleID;
+
+ // Flags
+ if ( bWhiz )
+ {
+ data.m_fFlags |= TRACER_FLAG_WHIZ;
+ }
+
+ if ( iAttachment != TRACER_DONT_USE_ATTACHMENT )
+ {
+ data.m_fFlags |= TRACER_FLAG_USEATTACHMENT;
+ data.m_nAttachmentIndex = iAttachment;
+ }
+
+ // Fire it off
+ if ( pCustomTracerName )
+ {
+ DispatchEffect( pCustomTracerName, data );
+ }
+ else
+ {
+ DispatchEffect( "Tracer", data );
+ }
+}
+
+
+void UTIL_BloodDrips( const Vector &origin, const Vector &direction, int color, int amount )
+{
+ if ( !UTIL_ShouldShowBlood( color ) )
+ return;
+
+ if ( color == DONT_BLEED || amount == 0 )
+ return;
+
+ if ( g_Language.GetInt() == LANGUAGE_GERMAN && color == BLOOD_COLOR_RED )
+ color = 0;
+
+ if ( g_pGameRules->IsMultiplayer() )
+ {
+ // scale up blood effect in multiplayer for better visibility
+ amount *= 5;
+ }
+
+ if ( amount > 255 )
+ amount = 255;
+
+ if (color == BLOOD_COLOR_MECH)
+ {
+ g_pEffects->Sparks(origin);
+ if (random->RandomFloat(0, 2) >= 1)
+ {
+ UTIL_Smoke(origin, random->RandomInt(10, 15), 10);
+ }
+ }
+ else
+ {
+ // Normal blood impact
+ UTIL_BloodImpact( origin, direction, color, amount );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns low violence settings
+//-----------------------------------------------------------------------------
+static ConVar violence_hblood( "violence_hblood","1", 0, "Draw human blood" );
+static ConVar violence_hgibs( "violence_hgibs","1", 0, "Show human gib entities" );
+static ConVar violence_ablood( "violence_ablood","1", 0, "Draw alien blood" );
+static ConVar violence_agibs( "violence_agibs","1", 0, "Show alien gib entities" );
+
+bool UTIL_IsLowViolence( void )
+{
+ // These convars are no longer necessary -- the engine is the final arbiter of
+ // violence settings -- but they're here for legacy support and for testing low
+ // violence when the engine is in normal violence mode.
+ if ( !violence_hblood.GetBool() || !violence_ablood.GetBool() || !violence_hgibs.GetBool() || !violence_agibs.GetBool() )
+ return true;
+
+#ifdef TF_CLIENT_DLL
+ // Use low violence if the local player has an item that allows them to see it (Pyro Goggles)
+ if ( IsLocalPlayerUsingVisionFilterFlags( TF_VISION_FILTER_PYRO ) )
+ {
+ return true;
+ }
+#endif
+
+ return engine->IsLowViolence();
+}
+
+bool UTIL_ShouldShowBlood( int color )
+{
+ if ( color != DONT_BLEED )
+ {
+ if ( color == BLOOD_COLOR_RED )
+ {
+ return violence_hblood.GetBool();
+ }
+ else
+ {
+ return violence_ablood.GetBool();
+ }
+ }
+ return false;
+}
+
+
+//------------------------------------------------------------------------------
+// Purpose : Use trace to pass a specific decal type to the entity being decaled
+// Input :
+// Output :
+//------------------------------------------------------------------------------
+void UTIL_DecalTrace( trace_t *pTrace, char const *decalName )
+{
+ if (pTrace->fraction == 1.0)
+ return;
+
+ CBaseEntity *pEntity = pTrace->m_pEnt;
+ pEntity->DecalTrace( pTrace, decalName );
+}
+
+
+void UTIL_BloodDecalTrace( trace_t *pTrace, int bloodColor )
+{
+ if ( UTIL_ShouldShowBlood( bloodColor ) )
+ {
+ if ( bloodColor == BLOOD_COLOR_RED )
+ {
+ UTIL_DecalTrace( pTrace, "Blood" );
+ }
+ else
+ {
+ UTIL_DecalTrace( pTrace, "YellowBlood" );
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : &pos -
+// &dir -
+// color -
+// amount -
+//-----------------------------------------------------------------------------
+void UTIL_BloodImpact( const Vector &pos, const Vector &dir, int color, int amount )
+{
+ CEffectData data;
+
+ data.m_vOrigin = pos;
+ data.m_vNormal = dir;
+ data.m_flScale = (float)amount;
+ data.m_nColor = (unsigned char)color;
+
+ DispatchEffect( "bloodimpact", data );
+}
+
+bool UTIL_IsSpaceEmpty( CBaseEntity *pMainEnt, const Vector &vMin, const Vector &vMax )
+{
+ Vector vHalfDims = ( vMax - vMin ) * 0.5f;
+ Vector vCenter = vMin + vHalfDims;
+
+ trace_t trace;
+ UTIL_TraceHull( vCenter, vCenter, -vHalfDims, vHalfDims, MASK_SOLID, pMainEnt, COLLISION_GROUP_NONE, &trace );
+
+ bool bClear = ( trace.fraction == 1 && trace.allsolid != 1 && (trace.startsolid != 1) );
+ return bClear;
+}
+
+void UTIL_StringToFloatArray( float *pVector, int count, const char *pString )
+{
+ char *pstr, *pfront, tempString[128];
+ int j;
+
+ Q_strncpy( tempString, pString, sizeof(tempString) );
+ pstr = pfront = tempString;
+
+ for ( j = 0; j < count; j++ ) // lifted from pr_edict.c
+ {
+ pVector[j] = atof( pfront );
+
+ // skip any leading whitespace
+ while ( *pstr && *pstr <= ' ' )
+ pstr++;
+
+ // skip to next whitespace
+ while ( *pstr && *pstr > ' ' )
+ pstr++;
+
+ if (!*pstr)
+ break;
+
+ pstr++;
+ pfront = pstr;
+ }
+ for ( j++; j < count; j++ )
+ {
+ pVector[j] = 0;
+ }
+}
+
+void UTIL_StringToVector( float *pVector, const char *pString )
+{
+ UTIL_StringToFloatArray( pVector, 3, pString );
+}
+
+void UTIL_StringToIntArray( int *pVector, int count, const char *pString )
+{
+ char *pstr, *pfront, tempString[128];
+ int j;
+
+ Q_strncpy( tempString, pString, sizeof(tempString) );
+ pstr = pfront = tempString;
+
+ for ( j = 0; j < count; j++ ) // lifted from pr_edict.c
+ {
+ pVector[j] = atoi( pfront );
+
+ while ( *pstr && *pstr != ' ' )
+ pstr++;
+ if (!*pstr)
+ break;
+ pstr++;
+ pfront = pstr;
+ }
+
+ for ( j++; j < count; j++ )
+ {
+ pVector[j] = 0;
+ }
+}
+
+void UTIL_StringToColor32( color32 *color, const char *pString )
+{
+ int tmp[4];
+ UTIL_StringToIntArray( tmp, 4, pString );
+ color->r = tmp[0];
+ color->g = tmp[1];
+ color->b = tmp[2];
+ color->a = tmp[3];
+}
+
+#ifndef _XBOX
+void UTIL_DecodeICE( unsigned char * buffer, int size, const unsigned char *key)
+{
+ if ( !key )
+ return;
+
+ IceKey ice( 0 ); // level 0 = 64bit key
+ ice.set( key ); // set key
+
+ int blockSize = ice.blockSize();
+
+ unsigned char *temp = (unsigned char *)_alloca( PAD_NUMBER( size, blockSize ) );
+ unsigned char *p1 = buffer;
+ unsigned char *p2 = temp;
+
+ // encrypt data in 8 byte blocks
+ int bytesLeft = size;
+ while ( bytesLeft >= blockSize )
+ {
+ ice.decrypt( p1, p2 );
+ bytesLeft -= blockSize;
+ p1+=blockSize;
+ p2+=blockSize;
+ }
+
+ // copy encrypted data back to original buffer
+ Q_memcpy( buffer, temp, size-bytesLeft );
+}
+#endif
+
+// work-around since client header doesn't like inlined gpGlobals->curtime
+float IntervalTimer::Now( void ) const
+{
+ return gpGlobals->curtime;
+}
+
+// work-around since client header doesn't like inlined gpGlobals->curtime
+float CountdownTimer::Now( void ) const
+{
+ return gpGlobals->curtime;
+}
+
+
+#ifdef CLIENT_DLL
+ CBasePlayer *UTIL_PlayerByIndex( int entindex )
+ {
+ return ToBasePlayer( ClientEntityList().GetEnt( entindex ) );
+ }
+
+//=============================================================================
+// HPE_BEGIN:
+// [menglish] Added UTIL function for events in client win_panel which transmit the player as a user ID
+//=============================================================================
+
+ CBasePlayer* UTIL_PlayerByUserId( int userID )
+ {
+ for (int i = 1; i<=gpGlobals->maxClients; i++ )
+ {
+ CBasePlayer *pPlayer = UTIL_PlayerByIndex( i );
+
+ if ( !pPlayer )
+ continue;
+
+ if ( pPlayer->GetUserID() == userID )
+ {
+ return pPlayer;
+ }
+ }
+
+ return NULL;
+ }
+
+//=============================================================================
+// HPE_END
+//=============================================================================
+
+#endif
+
+
+char* ReadAndAllocStringValue( KeyValues *pSub, const char *pName, const char *pFilename )
+{
+ const char *pValue = pSub->GetString( pName, NULL );
+ if ( !pValue )
+ {
+ if ( pFilename )
+ {
+ DevWarning( "Can't get key value '%s' from file '%s'.\n", pName, pFilename );
+ }
+ return "";
+ }
+
+ int len = Q_strlen( pValue ) + 1;
+ char *pAlloced = new char[ len ];
+ Assert( pAlloced );
+ Q_strncpy( pAlloced, pValue, len );
+ return pAlloced;
+}
+
+int UTIL_StringFieldToInt( const char *szValue, const char **pValueStrings, int iNumStrings )
+{
+ if ( !szValue || !szValue[0] )
+ return -1;
+
+ for ( int i = 0; i < iNumStrings; i++ )
+ {
+ if ( FStrEq(szValue, pValueStrings[i]) )
+ return i;
+ }
+
+ Assert(0);
+ return -1;
+}
+
+
+int find_day_of_week( struct tm& found_day, int day_of_week, int step )
+{
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+#ifdef USES_ECON_ITEMS
+static bool s_HolidaysCalculated = false;
+static CBitVec<kHolidayCount> s_HolidaysActive;
+
+//-----------------------------------------------------------------------------
+// Purpose: Used at level change and round start to re-calculate which holiday is active
+//-----------------------------------------------------------------------------
+void UTIL_CalculateHolidays()
+{
+ s_HolidaysActive.ClearAll();
+
+ CRTime::UpdateRealTime();
+ for ( int iHoliday = 0; iHoliday < kHolidayCount; iHoliday++ )
+ {
+ if ( EconHolidays_IsHolidayActive( iHoliday, CRTime::RTime32TimeCur() ) )
+ {
+ s_HolidaysActive.Set( iHoliday );
+ }
+ }
+
+ s_HolidaysCalculated = true;
+}
+#endif // USES_ECON_ITEMS
+
+bool UTIL_IsHolidayActive( /*EHoliday*/ int eHoliday )
+{
+#ifdef USES_ECON_ITEMS
+ if ( IsX360() )
+ return false;
+
+ if ( !s_HolidaysCalculated )
+ {
+ UTIL_CalculateHolidays();
+ }
+
+ return s_HolidaysActive.IsBitSet( eHoliday );
+#else
+ return false;
+#endif
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+int UTIL_GetHolidayForString( const char* pszHolidayName )
+{
+#ifdef USES_ECON_ITEMS
+ if ( !pszHolidayName )
+ return kHoliday_None;
+
+ return EconHolidays_GetHolidayForString( pszHolidayName );
+#else
+ return 0;
+#endif
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+const char* UTIL_GetActiveHolidayString()
+{
+#ifdef USES_ECON_ITEMS
+ return EconHolidays_GetActiveHolidayString();
+#else
+ return NULL;
+#endif
+}