mirror of
https://github.com/alliedmodders/hl2sdk.git
synced 2025-01-04 00:23:25 +08:00
481 lines
15 KiB
C
481 lines
15 KiB
C
|
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
|
|||
|
//
|
|||
|
// Purpose: Shared util code between client and server.
|
|||
|
//
|
|||
|
//=============================================================================//
|
|||
|
|
|||
|
#ifndef UTIL_SHARED_H
|
|||
|
#define UTIL_SHARED_H
|
|||
|
#ifdef _WIN32
|
|||
|
#pragma once
|
|||
|
#endif
|
|||
|
|
|||
|
#include "vector.h"
|
|||
|
#include "cmodel.h"
|
|||
|
#include "utlvector.h"
|
|||
|
#include "networkvar.h"
|
|||
|
#include "engine/IEngineTrace.h"
|
|||
|
#include "engine/IStaticPropMgr.h"
|
|||
|
#include "shared_classnames.h"
|
|||
|
|
|||
|
#ifdef CLIENT_DLL
|
|||
|
#include "cdll_client_int.h"
|
|||
|
#endif
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// Forward declarations
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
class CGameTrace;
|
|||
|
class CBasePlayer;
|
|||
|
typedef CGameTrace trace_t;
|
|||
|
|
|||
|
extern ConVar developer; // developer mode
|
|||
|
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// Language IDs.
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
#define LANGUAGE_ENGLISH 0
|
|||
|
#define LANGUAGE_GERMAN 1
|
|||
|
#define LANGUAGE_FRENCH 2
|
|||
|
#define LANGUAGE_BRITISH 3
|
|||
|
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// Pitch + yaw
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
float UTIL_VecToYaw (const Vector &vec);
|
|||
|
float UTIL_VecToPitch (const Vector &vec);
|
|||
|
float UTIL_VecToYaw (const matrix3x4_t& matrix, const Vector &vec);
|
|||
|
float UTIL_VecToPitch (const matrix3x4_t& matrix, const Vector &vec);
|
|||
|
Vector UTIL_YawToVector ( float yaw );
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// Shared random number generators for shared/predicted code:
|
|||
|
// whenever generating random numbers in shared/predicted code, these functions
|
|||
|
// have to be used. Each call should specify a unique "sharedname" string that
|
|||
|
// seeds the random number generator. In loops make sure the "additionalSeed"
|
|||
|
// is increased with the loop counter, otherwise it will always return the
|
|||
|
// same random number
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
float SharedRandomFloat( const char *sharedname, float flMinVal, float flMaxVal, int additionalSeed = 0 );
|
|||
|
int SharedRandomInt( const char *sharedname, int iMinVal, int iMaxVal, int additionalSeed = 0 );
|
|||
|
Vector SharedRandomVector( const char *sharedname, float minVal, float maxVal, int additionalSeed = 0 );
|
|||
|
QAngle SharedRandomAngle( const char *sharedname, float minVal, float maxVal, int additionalSeed = 0 );
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// Standard collision filters...
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
bool PassServerEntityFilter( const IHandleEntity *pTouch, const IHandleEntity *pPass );
|
|||
|
bool StandardFilterRules( IHandleEntity *pServerEntity, int fContentsMask );
|
|||
|
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// Converts an IHandleEntity to an CBaseEntity
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
inline const CBaseEntity *EntityFromEntityHandle( const IHandleEntity *pConstHandleEntity )
|
|||
|
{
|
|||
|
IHandleEntity *pHandleEntity = const_cast<IHandleEntity*>(pConstHandleEntity);
|
|||
|
|
|||
|
#ifdef CLIENT_DLL
|
|||
|
IClientUnknown *pUnk = (IClientUnknown*)pHandleEntity;
|
|||
|
return pUnk->GetBaseEntity();
|
|||
|
#else
|
|||
|
if ( staticpropmgr->IsStaticProp( pHandleEntity ) )
|
|||
|
return NULL;
|
|||
|
|
|||
|
IServerUnknown *pUnk = (IServerUnknown*)pHandleEntity;
|
|||
|
return pUnk->GetBaseEntity();
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
inline CBaseEntity *EntityFromEntityHandle( IHandleEntity *pHandleEntity )
|
|||
|
{
|
|||
|
#ifdef CLIENT_DLL
|
|||
|
IClientUnknown *pUnk = (IClientUnknown*)pHandleEntity;
|
|||
|
return pUnk->GetBaseEntity();
|
|||
|
#else
|
|||
|
if ( staticpropmgr->IsStaticProp( pHandleEntity ) )
|
|||
|
return NULL;
|
|||
|
|
|||
|
IServerUnknown *pUnk = (IServerUnknown*)pHandleEntity;
|
|||
|
return pUnk->GetBaseEntity();
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// traceline methods
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
class CTraceFilterSimple : public CTraceFilter
|
|||
|
{
|
|||
|
public:
|
|||
|
// It does have a base, but we'll never network anything below here..
|
|||
|
DECLARE_CLASS_NOBASE( CTraceFilterSimple );
|
|||
|
|
|||
|
CTraceFilterSimple( const IHandleEntity *passentity, int collisionGroup );
|
|||
|
virtual bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask );
|
|||
|
virtual void SetPassEntity( const IHandleEntity *pPassEntity ) { m_pPassEnt = pPassEntity; }
|
|||
|
|
|||
|
const IHandleEntity *GetPassEntity( void ){ return m_pPassEnt;}
|
|||
|
|
|||
|
private:
|
|||
|
const IHandleEntity *m_pPassEnt;
|
|||
|
int m_collisionGroup;
|
|||
|
};
|
|||
|
|
|||
|
class CTraceFilterSkipTwoEntities : public CTraceFilterSimple
|
|||
|
{
|
|||
|
public:
|
|||
|
// It does have a base, but we'll never network anything below here..
|
|||
|
DECLARE_CLASS( CTraceFilterSkipTwoEntities, CTraceFilterSimple );
|
|||
|
|
|||
|
CTraceFilterSkipTwoEntities( const IHandleEntity *passentity, const IHandleEntity *passentity2, int collisionGroup );
|
|||
|
virtual bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask );
|
|||
|
|
|||
|
private:
|
|||
|
const IHandleEntity *m_pPassEnt2;
|
|||
|
};
|
|||
|
|
|||
|
class CTraceFilterSimpleList : public CTraceFilterSimple
|
|||
|
{
|
|||
|
public:
|
|||
|
CTraceFilterSimpleList( int collisionGroup );
|
|||
|
virtual bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask );
|
|||
|
|
|||
|
void AddEntityToIgnore( IHandleEntity *pEntity );
|
|||
|
private:
|
|||
|
CUtlVector<IHandleEntity*> m_PassEntities;
|
|||
|
};
|
|||
|
|
|||
|
class CTraceFilterOnlyNPCsAndPlayer : public CTraceFilterSimple
|
|||
|
{
|
|||
|
public:
|
|||
|
CTraceFilterOnlyNPCsAndPlayer( const IHandleEntity *passentity, int collisionGroup )
|
|||
|
: CTraceFilterSimple( passentity, collisionGroup )
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
virtual TraceType_t GetTraceType() const
|
|||
|
{
|
|||
|
return TRACE_ENTITIES_ONLY;
|
|||
|
}
|
|||
|
|
|||
|
virtual bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask );
|
|||
|
};
|
|||
|
|
|||
|
class CTraceFilterNoNPCsOrPlayer : public CTraceFilterSimple
|
|||
|
{
|
|||
|
public:
|
|||
|
CTraceFilterNoNPCsOrPlayer( const IHandleEntity *passentity, int collisionGroup )
|
|||
|
: CTraceFilterSimple( passentity, collisionGroup )
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
virtual bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask );
|
|||
|
};
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// Purpose: Custom trace filter used for NPC LOS traces
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
class CTraceFilterLOS : public CTraceFilterSkipTwoEntities
|
|||
|
{
|
|||
|
public:
|
|||
|
CTraceFilterLOS( IHandleEntity *pHandleEntity, int collisionGroup, IHandleEntity *pHandleEntity2 = NULL );
|
|||
|
bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask );
|
|||
|
};
|
|||
|
|
|||
|
// helper
|
|||
|
void DebugDrawLine( const Vector& vecAbsStart, const Vector& vecAbsEnd, int r, int g, int b, bool test, float duration );
|
|||
|
|
|||
|
extern ConVar r_visualizetraces;
|
|||
|
|
|||
|
inline void UTIL_TraceLine( const Vector& vecAbsStart, const Vector& vecAbsEnd, unsigned int mask,
|
|||
|
const IHandleEntity *ignore, int collisionGroup, trace_t *ptr )
|
|||
|
{
|
|||
|
Ray_t ray;
|
|||
|
ray.Init( vecAbsStart, vecAbsEnd );
|
|||
|
CTraceFilterSimple traceFilter( ignore, collisionGroup );
|
|||
|
|
|||
|
enginetrace->TraceRay( ray, mask, &traceFilter, ptr );
|
|||
|
|
|||
|
if( r_visualizetraces.GetBool() )
|
|||
|
{
|
|||
|
DebugDrawLine( ptr->startpos, ptr->endpos, 255, 0, 0, true, -1.0f );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
inline void UTIL_TraceLine( const Vector& vecAbsStart, const Vector& vecAbsEnd, unsigned int mask,
|
|||
|
ITraceFilter *pFilter, trace_t *ptr )
|
|||
|
{
|
|||
|
Ray_t ray;
|
|||
|
ray.Init( vecAbsStart, vecAbsEnd );
|
|||
|
|
|||
|
enginetrace->TraceRay( ray, mask, pFilter, ptr );
|
|||
|
|
|||
|
|
|||
|
if( r_visualizetraces.GetBool() )
|
|||
|
{
|
|||
|
DebugDrawLine( ptr->startpos, ptr->endpos, 255, 0, 0, true, -1.0f );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
inline void UTIL_TraceHull( const Vector &vecAbsStart, const Vector &vecAbsEnd, const Vector &hullMin,
|
|||
|
const Vector &hullMax, unsigned int mask, const IHandleEntity *ignore,
|
|||
|
int collisionGroup, trace_t *ptr )
|
|||
|
{
|
|||
|
Ray_t ray;
|
|||
|
ray.Init( vecAbsStart, vecAbsEnd, hullMin, hullMax );
|
|||
|
CTraceFilterSimple traceFilter( ignore, collisionGroup );
|
|||
|
|
|||
|
enginetrace->TraceRay( ray, mask, &traceFilter, ptr );
|
|||
|
|
|||
|
if( r_visualizetraces.GetBool() )
|
|||
|
{
|
|||
|
DebugDrawLine( ptr->startpos, ptr->endpos, 255, 255, 0, true, -1.0f );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
inline void UTIL_TraceHull( const Vector &vecAbsStart, const Vector &vecAbsEnd, const Vector &hullMin,
|
|||
|
const Vector &hullMax, unsigned int mask, ITraceFilter *pFilter, trace_t *ptr )
|
|||
|
{
|
|||
|
Ray_t ray;
|
|||
|
ray.Init( vecAbsStart, vecAbsEnd, hullMin, hullMax );
|
|||
|
|
|||
|
enginetrace->TraceRay( ray, mask, pFilter, ptr );
|
|||
|
|
|||
|
if( r_visualizetraces.GetBool() )
|
|||
|
{
|
|||
|
DebugDrawLine( ptr->startpos, ptr->endpos, 255, 255, 0, true, -1.0f );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
inline void UTIL_TraceRay( const Ray_t &ray, unsigned int mask,
|
|||
|
const IHandleEntity *ignore, int collisionGroup, trace_t *ptr )
|
|||
|
{
|
|||
|
CTraceFilterSimple traceFilter( ignore, collisionGroup );
|
|||
|
|
|||
|
enginetrace->TraceRay( ray, mask, &traceFilter, ptr );
|
|||
|
|
|||
|
if( r_visualizetraces.GetBool() )
|
|||
|
{
|
|||
|
DebugDrawLine( ptr->startpos, ptr->endpos, 255, 0, 0, true, -1.0f );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Sweeps a particular entity through the world
|
|||
|
void UTIL_TraceEntity( CBaseEntity *pEntity, const Vector &vecAbsStart, const Vector &vecAbsEnd, unsigned int mask, trace_t *ptr );
|
|||
|
void UTIL_TraceEntity( CBaseEntity *pEntity, const Vector &vecAbsStart, const Vector &vecAbsEnd,
|
|||
|
unsigned int mask, ITraceFilter *pFilter, trace_t *ptr );
|
|||
|
void UTIL_TraceEntity( CBaseEntity *pEntity, const Vector &vecAbsStart, const Vector &vecAbsEnd,
|
|||
|
unsigned int mask, const IHandleEntity *ignore, int collisionGroup, trace_t *ptr );
|
|||
|
|
|||
|
bool UTIL_EntityHasMatchingRootParent( CBaseEntity *pRootParent, CBaseEntity *pEntity );
|
|||
|
|
|||
|
inline int UTIL_PointContents( const Vector &vec )
|
|||
|
{
|
|||
|
return enginetrace->GetPointContents( vec );
|
|||
|
}
|
|||
|
|
|||
|
// 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 );
|
|||
|
|
|||
|
void UTIL_ClipTraceToPlayers( const Vector& vecAbsStart, const Vector& vecAbsEnd, unsigned int mask, ITraceFilter *filter, trace_t *tr );
|
|||
|
|
|||
|
void UTIL_Tracer( const Vector &vecStart, const Vector &vecEnd, int iEntIndex = 0, int iAttachment = TRACER_DONT_USE_ATTACHMENT, float flVelocity = 0, bool bWhiz = false, const char *pCustomTracerName = NULL);
|
|||
|
|
|||
|
bool UTIL_IsLowViolence( void );
|
|||
|
bool UTIL_ShouldShowBlood( int bloodColor );
|
|||
|
void UTIL_BloodDrips( const Vector &origin, const Vector &direction, int color, int amount );
|
|||
|
|
|||
|
void UTIL_BloodImpact( const Vector &pos, const Vector &dir, int color, int amount );
|
|||
|
void UTIL_BloodDecalTrace( trace_t *pTrace, int bloodColor );
|
|||
|
void UTIL_DecalTrace( trace_t *pTrace, char const *decalName );
|
|||
|
bool UTIL_IsSpaceEmpty( CBaseEntity *pMainEnt, const Vector &vMin, const Vector &vMax );
|
|||
|
|
|||
|
void UTIL_StringToVector( float *pVector, const char *pString );
|
|||
|
void UTIL_StringToIntArray( int *pVector, int count, const char *pString );
|
|||
|
void UTIL_StringToFloatArray( float *pVector, int count, const char *pString );
|
|||
|
void UTIL_StringToColor32( color32 *color, const char *pString );
|
|||
|
|
|||
|
CBasePlayer *UTIL_PlayerByIndex( int entindex );
|
|||
|
|
|||
|
// decodes a buffer using a 64bit ICE key (inplace)
|
|||
|
void UTIL_DecodeICE( unsigned char * buffer, int size, const unsigned char *key);
|
|||
|
|
|||
|
|
|||
|
//--------------------------------------------------------------------------------------------------------------
|
|||
|
/**
|
|||
|
* Given a position and a ray, return the shortest distance between the two.
|
|||
|
* If 'pos' is beyond either end of the ray, the returned distance is negated.
|
|||
|
*/
|
|||
|
inline float DistanceToRay( const Vector &pos, const Vector &rayStart, const Vector &rayEnd, float *along = NULL, Vector *pointOnRay = NULL )
|
|||
|
{
|
|||
|
Vector to = pos - rayStart;
|
|||
|
Vector dir = rayEnd - rayStart;
|
|||
|
float length = dir.NormalizeInPlace();
|
|||
|
|
|||
|
float rangeAlong = DotProduct( dir, to );
|
|||
|
if (along)
|
|||
|
{
|
|||
|
*along = rangeAlong;
|
|||
|
}
|
|||
|
|
|||
|
float range;
|
|||
|
|
|||
|
if (rangeAlong < 0.0f)
|
|||
|
{
|
|||
|
// off start point
|
|||
|
range = -(pos - rayStart).Length();
|
|||
|
|
|||
|
if (pointOnRay)
|
|||
|
{
|
|||
|
*pointOnRay = rayStart;
|
|||
|
}
|
|||
|
}
|
|||
|
else if (rangeAlong > length)
|
|||
|
{
|
|||
|
// off end point
|
|||
|
range = -(pos - rayEnd).Length();
|
|||
|
|
|||
|
if (pointOnRay)
|
|||
|
{
|
|||
|
*pointOnRay = rayEnd;
|
|||
|
}
|
|||
|
}
|
|||
|
else // within ray bounds
|
|||
|
{
|
|||
|
Vector onRay = rayStart + rangeAlong * dir;
|
|||
|
range = (pos - onRay).Length();
|
|||
|
|
|||
|
if (pointOnRay)
|
|||
|
{
|
|||
|
*pointOnRay = onRay;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return range;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//--------------------------------------------------------------------------------------------------------------
|
|||
|
/**
|
|||
|
* Simple class for tracking intervals of game time.
|
|||
|
* Upon creation, the timer is invalidated. To measure time intervals, start the timer via Start().
|
|||
|
*/
|
|||
|
class IntervalTimer
|
|||
|
{
|
|||
|
public:
|
|||
|
IntervalTimer( void )
|
|||
|
{
|
|||
|
m_timestamp = -1.0f;
|
|||
|
}
|
|||
|
|
|||
|
void Reset( void )
|
|||
|
{
|
|||
|
m_timestamp = Now();
|
|||
|
}
|
|||
|
|
|||
|
void Start( void )
|
|||
|
{
|
|||
|
m_timestamp = Now();
|
|||
|
}
|
|||
|
|
|||
|
void Invalidate( void )
|
|||
|
{
|
|||
|
m_timestamp = -1.0f;
|
|||
|
}
|
|||
|
|
|||
|
bool HasStarted( void ) const
|
|||
|
{
|
|||
|
return (m_timestamp > 0.0f);
|
|||
|
}
|
|||
|
|
|||
|
/// if not started, elapsed time is very large
|
|||
|
float GetElapsedTime( void ) const
|
|||
|
{
|
|||
|
return (HasStarted()) ? (Now() - m_timestamp) : 99999.9f;
|
|||
|
}
|
|||
|
|
|||
|
bool IsLessThen( float duration ) const
|
|||
|
{
|
|||
|
return (Now() - m_timestamp < duration) ? true : false;
|
|||
|
}
|
|||
|
|
|||
|
bool IsGreaterThen( float duration ) const
|
|||
|
{
|
|||
|
return (Now() - m_timestamp > duration) ? true : false;
|
|||
|
}
|
|||
|
|
|||
|
private:
|
|||
|
float m_timestamp;
|
|||
|
float Now( void ) const; // work-around since client header doesn't like inlined gpGlobals->curtime
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
//--------------------------------------------------------------------------------------------------------------
|
|||
|
/**
|
|||
|
* Simple class for counting down a short interval of time.
|
|||
|
* Upon creation, the timer is invalidated. Invalidated countdown timers are considered to have elapsed.
|
|||
|
*/
|
|||
|
class CountdownTimer
|
|||
|
{
|
|||
|
public:
|
|||
|
CountdownTimer( void )
|
|||
|
{
|
|||
|
m_timestamp = -1.0f;
|
|||
|
m_duration = 0.0f;
|
|||
|
}
|
|||
|
|
|||
|
void Reset( void )
|
|||
|
{
|
|||
|
m_timestamp = Now() + m_duration;
|
|||
|
}
|
|||
|
|
|||
|
void Start( float duration )
|
|||
|
{
|
|||
|
m_timestamp = Now() + duration;
|
|||
|
m_duration = duration;
|
|||
|
}
|
|||
|
|
|||
|
void Invalidate( void )
|
|||
|
{
|
|||
|
m_timestamp = -1.0f;
|
|||
|
}
|
|||
|
|
|||
|
bool HasStarted( void ) const
|
|||
|
{
|
|||
|
return (m_timestamp > 0.0f);
|
|||
|
}
|
|||
|
|
|||
|
bool IsElapsed( void ) const
|
|||
|
{
|
|||
|
return (Now() > m_timestamp);
|
|||
|
}
|
|||
|
|
|||
|
float GetElapsedTime( void ) const
|
|||
|
{
|
|||
|
return Now() - m_timestamp + m_duration;
|
|||
|
}
|
|||
|
|
|||
|
float GetRemainingTime( void ) const
|
|||
|
{
|
|||
|
return (m_timestamp - Now());
|
|||
|
}
|
|||
|
|
|||
|
/// return original countdown time
|
|||
|
float GetCountdownDuration( void ) const
|
|||
|
{
|
|||
|
return (m_timestamp > 0.0f) ? m_duration : 0.0f;
|
|||
|
}
|
|||
|
|
|||
|
private:
|
|||
|
float m_duration;
|
|||
|
float m_timestamp;
|
|||
|
float Now( void ) const; // work-around since client header doesn't like inlined gpGlobals->curtime
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
#endif // UTIL_SHARED_H
|