//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
/*
= = = = = client . cpp = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
client / server game specific stuff
*/
# include "cbase.h"
# include "player.h"
# include "client.h"
# include "soundent.h"
# include "gamerules.h"
# include "game.h"
# include "physics.h"
# include "entitylist.h"
# include "shake.h"
# include "globalstate.h"
# include "event_tempentity_tester.h"
# include "ndebugoverlay.h"
# include "engine/IEngineSound.h"
# include <ctype.h>
# include "tier1/strtools.h"
# include "te_effect_dispatch.h"
# include "globals.h"
# include "nav_mesh.h"
# include "team.h"
# include "datacache/imdlcache.h"
# include "basemultiplayerplayer.h"
# include "voice_gamemgr.h"
# ifdef TF_DLL
# include "tf_player.h"
# include "tf_gamerules.h"
# endif
# ifdef HL2_DLL
# include "weapon_physcannon.h"
# endif
// memdbgon must be the last include file in a .cpp file!!!
# include "tier0/memdbgon.h"
extern int giPrecacheGrunt ;
// For not just using one big ai net
extern CBaseEntity * FindPickerEntity ( CBasePlayer * pPlayer ) ;
extern bool IsInCommentaryMode ( void ) ;
ConVar * sv_cheats = NULL ;
void ClientKill ( edict_t * pEdict , const Vector & vecForce , bool bExplode = false )
{
CBasePlayer * pPlayer = static_cast < CBasePlayer * > ( GetContainingEntity ( pEdict ) ) ;
pPlayer - > CommitSuicide ( vecForce , bExplode ) ;
}
char * CheckChatText ( CBasePlayer * pPlayer , char * text )
{
char * p = text ;
// invalid if NULL or empty
if ( ! text | | ! text [ 0 ] )
return NULL ;
int length = Q_strlen ( text ) ;
// remove quotes (leading & trailing) if present
if ( * p = = ' " ' )
{
p + + ;
length - = 2 ;
p [ length ] = 0 ;
}
// cut off after 127 chars
if ( length > 127 )
text [ 127 ] = 0 ;
GameRules ( ) - > CheckChatText ( pPlayer , p ) ;
return p ;
}
//// HOST_SAY
// String comes in as
// say blah blah blah
// or as
// blah blah blah
//
void Host_Say ( edict_t * pEdict , const CCommand & args , bool teamonly )
{
CBasePlayer * client ;
int j ;
char * p ;
char text [ 256 ] ;
char szTemp [ 256 ] ;
const char * cpSay = " say " ;
const char * cpSayTeam = " say_team " ;
const char * pcmd = args [ 0 ] ;
bool bSenderDead = false ;
// We can get a raw string now, without the "say " prepended
if ( args . ArgC ( ) = = 0 )
return ;
if ( ! stricmp ( pcmd , cpSay ) | | ! stricmp ( pcmd , cpSayTeam ) )
{
if ( args . ArgC ( ) > = 2 )
{
p = ( char * ) args . ArgS ( ) ;
}
else
{
// say with a blank message, nothing to do
return ;
}
}
else // Raw text, need to prepend argv[0]
{
if ( args . ArgC ( ) > = 2 )
{
Q_snprintf ( szTemp , sizeof ( szTemp ) , " %s %s " , ( char * ) pcmd , ( char * ) args . ArgS ( ) ) ;
}
else
{
// Just a one word command, use the first word...sigh
Q_snprintf ( szTemp , sizeof ( szTemp ) , " %s " , ( char * ) pcmd ) ;
}
p = szTemp ;
}
CBasePlayer * pPlayer = NULL ;
if ( pEdict )
{
pPlayer = ( ( CBasePlayer * ) CBaseEntity : : Instance ( pEdict ) ) ;
Assert ( pPlayer ) ;
// make sure the text has valid content
p = CheckChatText ( pPlayer , p ) ;
}
if ( ! p )
return ;
if ( pEdict )
{
if ( ! pPlayer - > CanSpeak ( ) )
return ;
// See if the player wants to modify of check the text
pPlayer - > CheckChatText ( p , 127 ) ; // though the buffer szTemp that p points to is 256,
// chat text is capped to 127 in CheckChatText above
Assert ( strlen ( pPlayer - > GetPlayerName ( ) ) > 0 ) ;
bSenderDead = ( pPlayer - > m_lifeState ! = LIFE_ALIVE ) ;
}
else
{
bSenderDead = false ;
}
const char * pszFormat = NULL ;
const char * pszPrefix = NULL ;
const char * pszLocation = NULL ;
if ( g_pGameRules )
{
pszFormat = g_pGameRules - > GetChatFormat ( teamonly , pPlayer ) ;
pszPrefix = g_pGameRules - > GetChatPrefix ( teamonly , pPlayer ) ;
pszLocation = g_pGameRules - > GetChatLocation ( teamonly , pPlayer ) ;
}
const char * pszPlayerName = pPlayer ? pPlayer - > GetPlayerName ( ) : " Console " ;
if ( pszPrefix & & strlen ( pszPrefix ) > 0 )
{
if ( pszLocation & & strlen ( pszLocation ) )
{
Q_snprintf ( text , sizeof ( text ) , " %s %s @ %s: " , pszPrefix , pszPlayerName , pszLocation ) ;
}
else
{
Q_snprintf ( text , sizeof ( text ) , " %s %s: " , pszPrefix , pszPlayerName ) ;
}
}
else
{
Q_snprintf ( text , sizeof ( text ) , " %s: " , pszPlayerName ) ;
}
j = sizeof ( text ) - 2 - strlen ( text ) ; // -2 for /n and null terminator
if ( ( int ) strlen ( p ) > j )
p [ j ] = 0 ;
Q_strncat ( text , p , sizeof ( text ) , COPY_ALL_CHARACTERS ) ;
Q_strncat ( text , " \n " , sizeof ( text ) , COPY_ALL_CHARACTERS ) ;
// loop through all players
// Start with the first player.
// This may return the world in single player if the client types something between levels or during spawn
// so check it, or it will infinite loop
client = NULL ;
for ( int i = 1 ; i < = gpGlobals - > maxClients ; i + + )
{
client = ToBaseMultiplayerPlayer ( UTIL_PlayerByIndex ( i ) ) ;
if ( ! client | | ! client - > edict ( ) )
continue ;
if ( client - > edict ( ) = = pEdict )
continue ;
if ( ! ( client - > IsNetClient ( ) ) ) // Not a client ? (should never be true)
continue ;
if ( teamonly & & g_pGameRules - > PlayerCanHearChat ( client , pPlayer ) ! = GR_TEAMMATE )
continue ;
if ( pPlayer & & ! client - > CanHearAndReadChatFrom ( pPlayer ) )
continue ;
if ( pPlayer & & GetVoiceGameMgr ( ) & & GetVoiceGameMgr ( ) - > IsPlayerIgnoringPlayer ( pPlayer - > entindex ( ) , i ) )
continue ;
CSingleUserRecipientFilter user ( client ) ;
user . MakeReliable ( ) ;
if ( pszFormat )
{
UTIL_SayText2Filter ( user , pPlayer , true , pszFormat , pszPlayerName , p , pszLocation ) ;
}
else
{
UTIL_SayTextFilter ( user , text , pPlayer , true ) ;
}
}
if ( pPlayer )
{
// print to the sending client
CSingleUserRecipientFilter user ( pPlayer ) ;
user . MakeReliable ( ) ;
if ( pszFormat )
{
UTIL_SayText2Filter ( user , pPlayer , true , pszFormat , pszPlayerName , p , pszLocation ) ;
}
else
{
UTIL_SayTextFilter ( user , text , pPlayer , true ) ;
}
}
// echo to server console
// Adrian: Only do this if we're running a dedicated server since we already print to console on the client.
if ( engine - > IsDedicatedServer ( ) )
Msg ( " %s " , text ) ;
Assert ( p ) ;
int userid = 0 ;
const char * networkID = " Console " ;
const char * playerName = " Console " ;
const char * playerTeam = " Console " ;
if ( pPlayer )
{
userid = pPlayer - > GetUserID ( ) ;
networkID = pPlayer - > GetNetworkIDString ( ) ;
playerName = pPlayer - > GetPlayerName ( ) ;
CTeam * team = pPlayer - > GetTeam ( ) ;
if ( team )
{
playerTeam = team - > GetName ( ) ;
}
}
if ( teamonly )
UTIL_LogPrintf ( " \" %s<%i><%s><%s> \" say_team \" %s \" \n " , playerName , userid , networkID , playerTeam , p ) ;
else
UTIL_LogPrintf ( " \" %s<%i><%s><%s> \" say \" %s \" \n " , playerName , userid , networkID , playerTeam , p ) ;
IGameEvent * event = gameeventmanager - > CreateEvent ( " player_say " , true ) ;
if ( event )
{
event - > SetInt ( " userid " , userid ) ;
event - > SetString ( " text " , p ) ;
event - > SetInt ( " priority " , 1 ) ; // HLTV event priority, not transmitted
gameeventmanager - > FireEvent ( event , true ) ;
}
}
void ClientPrecache ( void )
{
// Precache cable textures.
CBaseEntity : : PrecacheModel ( " cable/cable.vmt " ) ;
CBaseEntity : : PrecacheModel ( " cable/cable_lit.vmt " ) ;
CBaseEntity : : PrecacheModel ( " cable/chain.vmt " ) ;
CBaseEntity : : PrecacheModel ( " cable/rope.vmt " ) ;
CBaseEntity : : PrecacheModel ( " sprites/blueglow1.vmt " ) ;
CBaseEntity : : PrecacheModel ( " sprites/purpleglow1.vmt " ) ;
CBaseEntity : : PrecacheModel ( " sprites/purplelaser1.vmt " ) ;
# ifndef HL2MP
CBaseEntity : : PrecacheScriptSound ( " Hud.Hint " ) ;
# endif // HL2MP
CBaseEntity : : PrecacheScriptSound ( " Player.FallDamage " ) ;
CBaseEntity : : PrecacheScriptSound ( " Player.Swim " ) ;
// General HUD sounds
CBaseEntity : : PrecacheScriptSound ( " Player.PickupWeapon " ) ;
CBaseEntity : : PrecacheScriptSound ( " Player.DenyWeaponSelection " ) ;
CBaseEntity : : PrecacheScriptSound ( " Player.WeaponSelected " ) ;
CBaseEntity : : PrecacheScriptSound ( " Player.WeaponSelectionClose " ) ;
CBaseEntity : : PrecacheScriptSound ( " Player.WeaponSelectionMoveSlot " ) ;
// General legacy temp ents sounds
CBaseEntity : : PrecacheScriptSound ( " Bounce.Glass " ) ;
CBaseEntity : : PrecacheScriptSound ( " Bounce.Metal " ) ;
CBaseEntity : : PrecacheScriptSound ( " Bounce.Flesh " ) ;
CBaseEntity : : PrecacheScriptSound ( " Bounce.Wood " ) ;
CBaseEntity : : PrecacheScriptSound ( " Bounce.Shrapnel " ) ;
CBaseEntity : : PrecacheScriptSound ( " Bounce.ShotgunShell " ) ;
CBaseEntity : : PrecacheScriptSound ( " Bounce.Shell " ) ;
CBaseEntity : : PrecacheScriptSound ( " Bounce.Concrete " ) ;
ClientGamePrecache ( ) ;
}
CON_COMMAND_F ( cast_ray , " Tests collision detection " , FCVAR_CHEAT )
{
CBasePlayer * pPlayer = UTIL_GetCommandClient ( ) ;
Vector forward ;
trace_t tr ;
pPlayer - > EyeVectors ( & forward ) ;
Vector start = pPlayer - > EyePosition ( ) ;
UTIL_TraceLine ( start , start + forward * MAX_COORD_RANGE , MASK_SOLID , pPlayer , COLLISION_GROUP_NONE , & tr ) ;
if ( tr . DidHit ( ) )
{
DevMsg ( 1 , " Hit %s \n position %.2f, %.2f, %.2f \n angles %.2f, %.2f, %.2f \n " , tr . m_pEnt - > GetClassname ( ) ,
tr . m_pEnt - > GetAbsOrigin ( ) . x , tr . m_pEnt - > GetAbsOrigin ( ) . y , tr . m_pEnt - > GetAbsOrigin ( ) . z ,
tr . m_pEnt - > GetAbsAngles ( ) . x , tr . m_pEnt - > GetAbsAngles ( ) . y , tr . m_pEnt - > GetAbsAngles ( ) . z ) ;
DevMsg ( 1 , " Hit: hitbox %d, hitgroup %d, physics bone %d, solid %d, surface %s, surfaceprop %s, contents %08x \n " , tr . hitbox , tr . hitgroup , tr . physicsbone , tr . m_pEnt - > GetSolid ( ) , tr . surface . name , physprops - > GetPropName ( tr . surface . surfaceProps ) , tr . contents ) ;
NDebugOverlay : : Line ( start , tr . endpos , 0 , 255 , 0 , false , 10 ) ;
NDebugOverlay : : Line ( tr . endpos , tr . endpos + tr . plane . normal * 12 , 255 , 255 , 0 , false , 10 ) ;
}
}
CON_COMMAND_F ( cast_hull , " Tests hull collision detection " , FCVAR_CHEAT )
{
CBasePlayer * pPlayer = UTIL_GetCommandClient ( ) ;
Vector forward ;
trace_t tr ;
Vector extents ;
extents . Init ( 16 , 16 , 16 ) ;
pPlayer - > EyeVectors ( & forward ) ;
Vector start = pPlayer - > EyePosition ( ) ;
UTIL_TraceHull ( start , start + forward * MAX_COORD_RANGE , - extents , extents , MASK_SOLID , pPlayer , COLLISION_GROUP_NONE , & tr ) ;
if ( tr . DidHit ( ) )
{
DevMsg ( 1 , " Hit %s \n position %.2f, %.2f, %.2f \n angles %.2f, %.2f, %.2f \n " , tr . m_pEnt - > GetClassname ( ) ,
tr . m_pEnt - > GetAbsOrigin ( ) . x , tr . m_pEnt - > GetAbsOrigin ( ) . y , tr . m_pEnt - > GetAbsOrigin ( ) . z ,
tr . m_pEnt - > GetAbsAngles ( ) . x , tr . m_pEnt - > GetAbsAngles ( ) . y , tr . m_pEnt - > GetAbsAngles ( ) . z ) ;
DevMsg ( 1 , " Hit: hitbox %d, hitgroup %d, physics bone %d, solid %d, surface %s, surfaceprop %s \n " , tr . hitbox , tr . hitgroup , tr . physicsbone , tr . m_pEnt - > GetSolid ( ) , tr . surface . name , physprops - > GetPropName ( tr . surface . surfaceProps ) ) ;
NDebugOverlay : : SweptBox ( start , tr . endpos , - extents , extents , vec3_angle , 0 , 0 , 255 , 0 , 10 ) ;
Vector end = tr . endpos ; // - tr.plane.normal * DotProductAbs( tr.plane.normal, extents );
NDebugOverlay : : Line ( end , end + tr . plane . normal * 24 , 255 , 255 , 64 , false , 10 ) ;
}
}
//-----------------------------------------------------------------------------
// Purpose: Used to find targets for ent_* commands
// Without a name, returns the entity under the player's crosshair.
// With a name it finds entities via name/classname/index
//-----------------------------------------------------------------------------
CBaseEntity * GetNextCommandEntity ( CBasePlayer * pPlayer , const char * name , CBaseEntity * ent )
{
if ( ! pPlayer )
return NULL ;
// If no name was given set bits based on the picked
if ( FStrEq ( name , " " ) )
{
// If we've already found an entity, return NULL.
// Makes it easier to write code using this func.
if ( ent )
return NULL ;
return FindPickerEntity ( pPlayer ) ;
}
int index = atoi ( name ) ;
if ( index )
{
// If we've already found an entity, return NULL.
// Makes it easier to write code using this func.
if ( ent )
return NULL ;
return CBaseEntity : : Instance ( index ) ;
}
// Loop through all entities matching, starting from the specified previous
while ( ( ent = gEntList . NextEnt ( ent ) ) ! = NULL )
{
if ( ( ent - > GetEntityName ( ) ! = NULL_STRING & & ent - > NameMatches ( name ) ) | |
( ent - > m_iClassname ! = NULL_STRING & & ent - > ClassMatches ( name ) ) )
{
return ent ;
}
}
return NULL ;
}
//-----------------------------------------------------------------------------
// Purpose: called each time a player uses a "cmd" command
// Input : pPlayer - the player who issued the command
//-----------------------------------------------------------------------------
void SetDebugBits ( CBasePlayer * pPlayer , const char * name , int bit )
{
if ( ! pPlayer )
return ;
CBaseEntity * pEntity = NULL ;
while ( ( pEntity = GetNextCommandEntity ( pPlayer , name , pEntity ) ) ! = NULL )
{
if ( pEntity - > m_debugOverlays & bit )
{
pEntity - > m_debugOverlays & = ~ bit ;
}
else
{
pEntity - > m_debugOverlays | = bit ;
# ifdef AI_MONITOR_FOR_OSCILLATION
if ( pEntity - > IsNPC ( ) )
{
pEntity - > MyNPCPointer ( ) - > m_ScheduleHistory . RemoveAll ( ) ;
}
# endif //AI_MONITOR_FOR_OSCILLATION
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : pKillTargetName -
//-----------------------------------------------------------------------------
void KillTargets ( const char * pKillTargetName )
{
CBaseEntity * pentKillTarget = NULL ;
DevMsg ( 2 , " KillTarget: %s \n " , pKillTargetName ) ;
pentKillTarget = gEntList . FindEntityByName ( NULL , pKillTargetName ) ;
while ( pentKillTarget )
{
UTIL_Remove ( pentKillTarget ) ;
DevMsg ( 2 , " killing %s \n " , STRING ( pentKillTarget - > m_iClassname ) ) ;
pentKillTarget = gEntList . FindEntityByName ( pentKillTarget , pKillTargetName ) ;
}
}
//------------------------------------------------------------------------------
// Purpose:
//------------------------------------------------------------------------------
void ConsoleKillTarget ( CBasePlayer * pPlayer , const char * name )
{
// If no name was given use the picker
if ( FStrEq ( name , " " ) )
{
CBaseEntity * pEntity = FindPickerEntity ( pPlayer ) ;
if ( pEntity )
{
UTIL_Remove ( pEntity ) ;
Msg ( " killing %s \n " , pEntity - > GetDebugName ( ) ) ;
return ;
}
}
// Otherwise use name or classname
KillTargets ( name ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CPointClientCommand : public CPointEntity
{
public :
DECLARE_CLASS ( CPointClientCommand , CPointEntity ) ;
DECLARE_DATADESC ( ) ;
void InputCommand ( inputdata_t & inputdata ) ;
} ;
void CPointClientCommand : : InputCommand ( inputdata_t & inputdata )
{
if ( ! inputdata . value . String ( ) [ 0 ] )
return ;
edict_t * pClient = NULL ;
if ( gpGlobals - > maxClients = = 1 )
{
pClient = engine - > PEntityOfEntIndex ( 1 ) ;
}
else
{
// In multiplayer, send it back to the activator
CBasePlayer * player = dynamic_cast < CBasePlayer * > ( inputdata . pActivator ) ;
if ( player )
{
pClient = player - > edict ( ) ;
}
if ( IsInCommentaryMode ( ) & & ! pClient )
{
// Commentary is stuffing a command in. We'll pretend it came from the first player.
pClient = engine - > PEntityOfEntIndex ( 1 ) ;
}
}
if ( ! pClient | | ! pClient - > GetUnknown ( ) )
return ;
engine - > ClientCommand ( pClient , " %s \n " , inputdata . value . String ( ) ) ;
}
BEGIN_DATADESC ( CPointClientCommand )
DEFINE_INPUTFUNC ( FIELD_STRING , " Command " , InputCommand ) ,
END_DATADESC ( )
LINK_ENTITY_TO_CLASS ( point_clientcommand , CPointClientCommand ) ;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CPointServerCommand : public CPointEntity
{
public :
DECLARE_CLASS ( CPointServerCommand , CPointEntity ) ;
DECLARE_DATADESC ( ) ;
void InputCommand ( inputdata_t & inputdata ) ;
} ;
//-----------------------------------------------------------------------------
// Purpose:
// Input : inputdata -
//-----------------------------------------------------------------------------
void CPointServerCommand : : InputCommand ( inputdata_t & inputdata )
{
if ( ! inputdata . value . String ( ) [ 0 ] )
return ;
engine - > ServerCommand ( UTIL_VarArgs ( " %s \n " , inputdata . value . String ( ) ) ) ;
}
BEGIN_DATADESC ( CPointServerCommand )
DEFINE_INPUTFUNC ( FIELD_STRING , " Command " , InputCommand ) ,
END_DATADESC ( )
LINK_ENTITY_TO_CLASS ( point_servercommand , CPointServerCommand ) ;
//------------------------------------------------------------------------------
// Purpose : Draw a line betwen two points. White if no world collisions, red if collisions
// Input :
// Output :
//------------------------------------------------------------------------------
void CC_DrawLine ( const CCommand & args )
{
Vector startPos ;
Vector endPos ;
startPos . x = atof ( args [ 1 ] ) ;
startPos . y = atof ( args [ 2 ] ) ;
startPos . z = atof ( args [ 3 ] ) ;
endPos . x = atof ( args [ 4 ] ) ;
endPos . y = atof ( args [ 5 ] ) ;
endPos . z = atof ( args [ 6 ] ) ;
UTIL_AddDebugLine ( startPos , endPos , true , true ) ;
}
static ConCommand drawline ( " drawline " , CC_DrawLine , " Draws line between two 3D Points. \n \t Green if no collision \n \t Red is collides with something \n \t Arguments: x1 y1 z1 x2 y2 z2 " , FCVAR_CHEAT ) ;
//------------------------------------------------------------------------------
// Purpose : Draw a cross at a points.
// Input :
// Output :
//------------------------------------------------------------------------------
void CC_DrawCross ( const CCommand & args )
{
Vector vPosition ;
vPosition . x = atof ( args [ 1 ] ) ;
vPosition . y = atof ( args [ 2 ] ) ;
vPosition . z = atof ( args [ 3 ] ) ;
// Offset since min and max z in not about center
Vector mins = Vector ( - 5 , - 5 , - 5 ) ;
Vector maxs = Vector ( 5 , 5 , 5 ) ;
Vector start = mins + vPosition ;
Vector end = maxs + vPosition ;
UTIL_AddDebugLine ( start , end , true , true ) ;
start . x + = ( maxs . x - mins . x ) ;
end . x - = ( maxs . x - mins . x ) ;
UTIL_AddDebugLine ( start , end , true , true ) ;
start . y + = ( maxs . y - mins . y ) ;
end . y - = ( maxs . y - mins . y ) ;
UTIL_AddDebugLine ( start , end , true , true ) ;
start . x - = ( maxs . x - mins . x ) ;
end . x + = ( maxs . x - mins . x ) ;
UTIL_AddDebugLine ( start , end , true , true ) ;
}
static ConCommand drawcross ( " drawcross " , CC_DrawCross , " Draws a cross at the given location \n \t Arguments: x y z " , FCVAR_CHEAT ) ;
//------------------------------------------------------------------------------
// helper function for kill and explode
//------------------------------------------------------------------------------
void kill_helper ( const CCommand & args , bool bExplode )
{
if ( args . ArgC ( ) > 1 & & sv_cheats - > GetBool ( ) )
{
// Find the matching netname
for ( int i = 1 ; i < = gpGlobals - > maxClients ; i + + )
{
CBasePlayer * pPlayer = ToBasePlayer ( UTIL_PlayerByIndex ( i ) ) ;
if ( pPlayer )
{
if ( Q_strstr ( pPlayer - > GetPlayerName ( ) , args [ 1 ] ) )
{
pPlayer - > CommitSuicide ( bExplode ) ;
}
}
}
}
else
{
CBasePlayer * pPlayer = UTIL_GetCommandClient ( ) ;
if ( pPlayer )
{
pPlayer - > CommitSuicide ( bExplode ) ;
}
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
CON_COMMAND ( kill , " Kills the player with generic damage " )
{
kill_helper ( args , false ) ;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
CON_COMMAND ( explode , " Kills the player with explosive damage " )
{
kill_helper ( args , true ) ;
}
//------------------------------------------------------------------------------
// helper function for killvector and explodevector
//------------------------------------------------------------------------------
void killvector_helper ( const CCommand & args , bool bExplode )
{
CBasePlayer * pPlayer = UTIL_GetCommandClient ( ) ;
if ( pPlayer & & args . ArgC ( ) = = 5 )
{
// Find the matching netname.
for ( int iClient = 1 ; iClient < = gpGlobals - > maxClients ; iClient + + )
{
CBasePlayer * pPlayer = ToBasePlayer ( UTIL_PlayerByIndex ( iClient ) ) ;
if ( pPlayer )
{
if ( Q_strstr ( pPlayer - > GetPlayerName ( ) , args [ 1 ] ) )
{
// Build world-space force vector.
Vector vecForce ;
vecForce . x = atof ( args [ 2 ] ) ;
vecForce . y = atof ( args [ 3 ] ) ;
vecForce . z = atof ( args [ 4 ] ) ;
ClientKill ( pPlayer - > edict ( ) , vecForce , bExplode ) ;
}
}
}
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
CON_COMMAND_F ( killvector , " Kills a player applying force. Usage: killvector <player> <x value> <y value> <z value> " , FCVAR_CHEAT )
{
killvector_helper ( args , false ) ;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
CON_COMMAND_F ( explodevector , " Kills a player applying an explosive force. Usage: explodevector <player> <x value> <y value> <z value> " , FCVAR_CHEAT )
{
killvector_helper ( args , false ) ;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
CON_COMMAND_F ( buddha , " Toggle. Player takes damage but won't die. (Shows red cross when health is zero) " , FCVAR_CHEAT )
{
CBasePlayer * pPlayer = ToBasePlayer ( UTIL_GetCommandClient ( ) ) ;
if ( pPlayer )
{
if ( pPlayer - > m_debugOverlays & OVERLAY_BUDDHA_MODE )
{
pPlayer - > m_debugOverlays & = ~ OVERLAY_BUDDHA_MODE ;
Msg ( " Buddha Mode off... \n " ) ;
}
else
{
pPlayer - > m_debugOverlays | = OVERLAY_BUDDHA_MODE ;
Msg ( " Buddha Mode on... \n " ) ;
}
}
}
# define TALK_INTERVAL 0.66 // min time between say commands from a client
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
CON_COMMAND ( say , " Display player message " )
{
CBasePlayer * pPlayer = ToBasePlayer ( UTIL_GetCommandClient ( ) ) ;
if ( pPlayer )
{
if ( ( pPlayer - > LastTimePlayerTalked ( ) + TALK_INTERVAL ) < gpGlobals - > curtime )
{
Host_Say ( pPlayer - > edict ( ) , args , 0 ) ;
pPlayer - > NotePlayerTalked ( ) ;
}
}
// This will result in a "console" say. Ignore anything from
// an index greater than 0 when we don't have a player pointer,
// as would be the case when a client that's connecting generates
// text via a script. This can be exploited to flood everyone off.
else if ( UTIL_GetCommandClientIndex ( ) = = 0 )
{
Host_Say ( NULL , args , 0 ) ;
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
CON_COMMAND ( say_team , " Display player message to team " )
{
CBasePlayer * pPlayer = ToBasePlayer ( UTIL_GetCommandClient ( ) ) ;
if ( pPlayer )
{
if ( ( pPlayer - > LastTimePlayerTalked ( ) + TALK_INTERVAL ) < gpGlobals - > curtime )
{
Host_Say ( pPlayer - > edict ( ) , args , 1 ) ;
pPlayer - > NotePlayerTalked ( ) ;
}
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
CON_COMMAND ( give , " Give item to player. \n \t Arguments: <item_name> " )
{
CBasePlayer * pPlayer = ToBasePlayer ( UTIL_GetCommandClient ( ) ) ;
if ( pPlayer
& & ( gpGlobals - > maxClients = = 1 | | sv_cheats - > GetBool ( ) )
& & args . ArgC ( ) > = 2 )
{
char item_to_give [ 256 ] ;
Q_strncpy ( item_to_give , args [ 1 ] , sizeof ( item_to_give ) ) ;
Q_strlower ( item_to_give ) ;
// Don't allow regular users to create point_servercommand entities for the same reason as blocking ent_fire
if ( ! Q_stricmp ( item_to_give , " point_servercommand " ) )
{
if ( engine - > IsDedicatedServer ( ) )
{
// We allow people with disabled autokick to do it, because they already have rcon.
if ( pPlayer - > IsAutoKickDisabled ( ) = = false )
return ;
}
else if ( gpGlobals - > maxClients > 1 )
{
// On listen servers with more than 1 player, only allow the host to create point_servercommand.
CBasePlayer * pHostPlayer = UTIL_GetListenServerHost ( ) ;
if ( pPlayer ! = pHostPlayer )
return ;
}
}
// Dirty hack to avoid suit playing it's pickup sound
if ( ! Q_stricmp ( item_to_give , " item_suit " ) )
{
pPlayer - > EquipSuit ( false ) ;
return ;
}
string_t iszItem = AllocPooledString ( item_to_give ) ; // Make a copy of the classname
pPlayer - > GiveNamedItem ( STRING ( iszItem ) ) ;
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
CON_COMMAND ( fov , " Change players FOV " )
{
CBasePlayer * pPlayer = ToBasePlayer ( UTIL_GetCommandClient ( ) ) ;
if ( pPlayer & & sv_cheats - > GetBool ( ) )
{
if ( args . ArgC ( ) > 1 )
{
int nFOV = atoi ( args [ 1 ] ) ;
pPlayer - > SetDefaultFOV ( nFOV ) ;
}
else
{
ClientPrint ( pPlayer , HUD_PRINTCONSOLE , UTIL_VarArgs ( " \" fov \" is \" %d \" \n " , pPlayer - > GetFOV ( ) ) ) ;
}
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void CC_Player_SetModel ( const CCommand & args )
{
if ( gpGlobals - > deathmatch )
return ;
CBasePlayer * pPlayer = ToBasePlayer ( UTIL_GetCommandClient ( ) ) ;
if ( pPlayer & & args . ArgC ( ) = = 2 )
{
static char szName [ 256 ] ;
Q_snprintf ( szName , sizeof ( szName ) , " models/%s.mdl " , args [ 1 ] ) ;
pPlayer - > SetModel ( szName ) ;
UTIL_SetSize ( pPlayer , VEC_HULL_MIN , VEC_HULL_MAX ) ;
}
}
static ConCommand setmodel ( " setmodel " , CC_Player_SetModel , " Changes's player's model " , FCVAR_CHEAT ) ;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CC_Player_TestDispatchEffect ( const CCommand & args )
{
CBasePlayer * pPlayer = ToBasePlayer ( UTIL_GetCommandClient ( ) ) ;
if ( ! pPlayer )
return ;
if ( args . ArgC ( ) < 2 )
{
Msg ( " Usage: test_dispatcheffect <effect name> <distance away> <flags> <magnitude> <scale> \n " ) ;
Msg ( " defaults are: <distance 1024> <flags 0> <magnitude 0> <scale 0> \n " ) ;
return ;
}
// Optional distance
float flDistance = 1024 ;
if ( args . ArgC ( ) > = 3 )
{
flDistance = atoi ( args [ 2 ] ) ;
}
// Optional flags
float flags = 0 ;
if ( args . ArgC ( ) > = 4 )
{
flags = atoi ( args [ 3 ] ) ;
}
// Optional magnitude
float magnitude = 0 ;
if ( args . ArgC ( ) > = 5 )
{
magnitude = atof ( args [ 4 ] ) ;
}
// Optional scale
float scale = 0 ;
if ( args . ArgC ( ) > = 6 )
{
scale = atof ( args [ 5 ] ) ;
}
Vector vecForward ;
QAngle vecAngles = pPlayer - > EyeAngles ( ) ;
AngleVectors ( vecAngles , & vecForward ) ;
// Trace forward
trace_t tr ;
Vector vecSrc = pPlayer - > EyePosition ( ) ;
Vector vecEnd = vecSrc + ( vecForward * flDistance ) ;
UTIL_TraceLine ( vecSrc , vecEnd , MASK_ALL , pPlayer , COLLISION_GROUP_NONE , & tr ) ;
// Fill out the generic data
CEffectData data ;
// If we hit something, use that data
if ( tr . fraction < 1.0 )
{
data . m_vOrigin = tr . endpos ;
VectorAngles ( tr . plane . normal , data . m_vAngles ) ;
data . m_vNormal = tr . plane . normal ;
}
else
{
data . m_vOrigin = vecEnd ;
data . m_vAngles = vecAngles ;
AngleVectors ( vecAngles , & data . m_vNormal ) ;
}
data . m_nEntIndex = pPlayer - > entindex ( ) ;
data . m_fFlags = flags ;
data . m_flMagnitude = magnitude ;
data . m_flScale = scale ;
DispatchEffect ( ( char * ) args [ 1 ] , data ) ;
}
static ConCommand test_dispatcheffect ( " test_dispatcheffect " , CC_Player_TestDispatchEffect , " Test a clientside dispatch effect. \n \t Usage: test_dispatcheffect <effect name> <distance away> <flags> <magnitude> <scale> \n \t Defaults are: <distance 1024> <flags 0> <magnitude 0> <scale 0> \n " , FCVAR_CHEAT ) ;
# ifdef HL2_DLL
//-----------------------------------------------------------------------------
// Purpose: Quickly switch to the physics cannon, or back to previous item
//-----------------------------------------------------------------------------
void CC_Player_PhysSwap ( void )
{
CBasePlayer * pPlayer = ToBasePlayer ( UTIL_GetCommandClient ( ) ) ;
if ( pPlayer )
{
CBaseCombatWeapon * pWeapon = pPlayer - > GetActiveWeapon ( ) ;
if ( pWeapon )
{
// Tell the client to stop selecting weapons
engine - > ClientCommand ( UTIL_GetCommandClient ( ) - > edict ( ) , " cancelselect " ) ;
const char * strWeaponName = pWeapon - > GetName ( ) ;
if ( ! Q_stricmp ( strWeaponName , " weapon_physcannon " ) )
{
PhysCannonForceDrop ( pWeapon , NULL ) ;
pPlayer - > SelectLastItem ( ) ;
}
else
{
pPlayer - > SelectItem ( " weapon_physcannon " ) ;
}
}
}
}
static ConCommand physswap ( " phys_swap " , CC_Player_PhysSwap , " Automatically swaps the current weapon for the physcannon and back again. " ) ;
# endif
//-----------------------------------------------------------------------------
// Purpose: Quickly switch to the bug bait, or back to previous item
//-----------------------------------------------------------------------------
void CC_Player_BugBaitSwap ( void )
{
CBasePlayer * pPlayer = ToBasePlayer ( UTIL_GetCommandClient ( ) ) ;
if ( pPlayer )
{
CBaseCombatWeapon * pWeapon = pPlayer - > GetActiveWeapon ( ) ;
if ( pWeapon )
{
// Tell the client to stop selecting weapons
engine - > ClientCommand ( UTIL_GetCommandClient ( ) - > edict ( ) , " cancelselect " ) ;
const char * strWeaponName = pWeapon - > GetName ( ) ;
if ( ! Q_stricmp ( strWeaponName , " weapon_bugbait " ) )
{
pPlayer - > SelectLastItem ( ) ;
}
else
{
pPlayer - > SelectItem ( " weapon_bugbait " ) ;
}
}
}
}
static ConCommand bugswap ( " bug_swap " , CC_Player_BugBaitSwap , " Automatically swaps the current weapon for the bug bait and back again. " , FCVAR_CHEAT ) ;
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void CC_Player_Use ( const CCommand & args )
{
CBasePlayer * pPlayer = ToBasePlayer ( UTIL_GetCommandClient ( ) ) ;
if ( pPlayer )
{
pPlayer - > SelectItem ( ( char * ) args [ 1 ] ) ;
}
}
static ConCommand use ( " use " , CC_Player_Use , " Use a particular weapon \t \n Arguments: <weapon_name> " ) ;
//------------------------------------------------------------------------------
// A small wrapper around SV_Move that never clips against the supplied entity.
//------------------------------------------------------------------------------
static bool TestEntityPosition ( CBasePlayer * pPlayer )
{
trace_t trace ;
UTIL_TraceEntity ( pPlayer , pPlayer - > GetAbsOrigin ( ) , pPlayer - > GetAbsOrigin ( ) , MASK_PLAYERSOLID , & trace ) ;
return ( trace . startsolid = = 0 ) ;
}
//------------------------------------------------------------------------------
// Searches along the direction ray in steps of "step" to see if
// the entity position is passible.
// Used for putting the player in valid space when toggling off noclip mode.
//------------------------------------------------------------------------------
static int FindPassableSpace ( CBasePlayer * pPlayer , const Vector & direction , float step , Vector & oldorigin )
{
int i ;
for ( i = 0 ; i < 100 ; i + + )
{
Vector origin = pPlayer - > GetAbsOrigin ( ) ;
VectorMA ( origin , step , direction , origin ) ;
pPlayer - > SetAbsOrigin ( origin ) ;
if ( TestEntityPosition ( pPlayer ) )
{
VectorCopy ( pPlayer - > GetAbsOrigin ( ) , oldorigin ) ;
return 1 ;
}
}
return 0 ;
}
//------------------------------------------------------------------------------
// Noclip
//------------------------------------------------------------------------------
void EnableNoClip ( CBasePlayer * pPlayer )
{
// Disengage from hierarchy
pPlayer - > SetParent ( NULL ) ;
pPlayer - > SetMoveType ( MOVETYPE_NOCLIP ) ;
ClientPrint ( pPlayer , HUD_PRINTCONSOLE , " noclip ON \n " ) ;
pPlayer - > AddEFlags ( EFL_NOCLIP_ACTIVE ) ;
}
void CC_Player_NoClip ( void )
{
if ( ! sv_cheats - > GetBool ( ) )
return ;
CBasePlayer * pPlayer = ToBasePlayer ( UTIL_GetCommandClient ( ) ) ;
if ( ! pPlayer )
return ;
CPlayerState * pl = pPlayer - > PlayerData ( ) ;
Assert ( pl ) ;
if ( pPlayer - > GetMoveType ( ) ! = MOVETYPE_NOCLIP )
{
EnableNoClip ( pPlayer ) ;
return ;
}
pPlayer - > RemoveEFlags ( EFL_NOCLIP_ACTIVE ) ;
pPlayer - > SetMoveType ( MOVETYPE_WALK ) ;
Vector oldorigin = pPlayer - > GetAbsOrigin ( ) ;
ClientPrint ( pPlayer , HUD_PRINTCONSOLE , " noclip OFF \n " ) ;
if ( ! TestEntityPosition ( pPlayer ) )
{
Vector forward , right , up ;
AngleVectors ( pl - > v_angle , & forward , & right , & up ) ;
// Try to move into the world
if ( ! FindPassableSpace ( pPlayer , forward , 1 , oldorigin ) )
{
if ( ! FindPassableSpace ( pPlayer , right , 1 , oldorigin ) )
{
if ( ! FindPassableSpace ( pPlayer , right , - 1 , oldorigin ) ) // left
{
if ( ! FindPassableSpace ( pPlayer , up , 1 , oldorigin ) ) // up
{
if ( ! FindPassableSpace ( pPlayer , up , - 1 , oldorigin ) ) // down
{
if ( ! FindPassableSpace ( pPlayer , forward , - 1 , oldorigin ) ) // back
{
Msg ( " Can't find the world \n " ) ;
}
}
}
}
}
}
pPlayer - > SetAbsOrigin ( oldorigin ) ;
}
}
static ConCommand noclip ( " noclip " , CC_Player_NoClip , " Toggle. Player becomes non-solid and flies. " , FCVAR_CHEAT ) ;
//------------------------------------------------------------------------------
// Sets client to godmode
//------------------------------------------------------------------------------
void CC_God_f ( void )
{
if ( ! sv_cheats - > GetBool ( ) )
return ;
CBasePlayer * pPlayer = ToBasePlayer ( UTIL_GetCommandClient ( ) ) ;
if ( ! pPlayer )
return ;
# ifdef TF_DLL
if ( TFGameRules ( ) & & ( TFGameRules ( ) - > IsPVEModeActive ( ) = = false ) )
{
if ( gpGlobals - > deathmatch )
return ;
}
# else
if ( gpGlobals - > deathmatch )
return ;
# endif
pPlayer - > ToggleFlag ( FL_GODMODE ) ;
if ( ! ( pPlayer - > GetFlags ( ) & FL_GODMODE ) )
ClientPrint ( pPlayer , HUD_PRINTCONSOLE , " godmode OFF \n " ) ;
else
ClientPrint ( pPlayer , HUD_PRINTCONSOLE , " godmode ON \n " ) ;
}
static ConCommand god ( " god " , CC_God_f , " Toggle. Player becomes invulnerable. " , FCVAR_CHEAT ) ;
//------------------------------------------------------------------------------
// Sets client to godmode
//------------------------------------------------------------------------------
CON_COMMAND_F ( setpos , " Move player to specified origin (must have sv_cheats). " , FCVAR_CHEAT )
{
if ( ! sv_cheats - > GetBool ( ) )
return ;
CBasePlayer * pPlayer = ToBasePlayer ( UTIL_GetCommandClient ( ) ) ;
if ( ! pPlayer )
return ;
if ( args . ArgC ( ) < 3 )
{
ClientPrint ( pPlayer , HUD_PRINTCONSOLE , " Usage: setpos x y <z optional> \n " ) ;
return ;
}
Vector oldorigin = pPlayer - > GetAbsOrigin ( ) ;
Vector newpos ;
newpos . x = atof ( args [ 1 ] ) ;
newpos . y = atof ( args [ 2 ] ) ;
newpos . z = args . ArgC ( ) = = 4 ? atof ( args [ 3 ] ) : oldorigin . z ;
pPlayer - > SetAbsOrigin ( newpos ) ;
if ( ! TestEntityPosition ( pPlayer ) )
{
ClientPrint ( pPlayer , HUD_PRINTCONSOLE , " setpos into world, use noclip to unstick yourself! \n " ) ;
}
}
//------------------------------------------------------------------------------
// Sets client to godmode
//------------------------------------------------------------------------------
void CC_setang_f ( const CCommand & args )
{
if ( ! sv_cheats - > GetBool ( ) )
return ;
CBasePlayer * pPlayer = ToBasePlayer ( UTIL_GetCommandClient ( ) ) ;
if ( ! pPlayer )
return ;
if ( args . ArgC ( ) < 3 )
{
ClientPrint ( pPlayer , HUD_PRINTCONSOLE , " Usage: setang pitch yaw <roll optional> \n " ) ;
return ;
}
QAngle oldang = pPlayer - > GetAbsAngles ( ) ;
QAngle newang ;
newang . x = atof ( args [ 1 ] ) ;
newang . y = atof ( args [ 2 ] ) ;
newang . z = args . ArgC ( ) = = 4 ? atof ( args [ 3 ] ) : oldang . z ;
pPlayer - > SnapEyeAngles ( newang ) ;
}
static ConCommand setang ( " setang " , CC_setang_f , " Snap player eyes to specified pitch yaw <roll:optional> (must have sv_cheats) . " , FCVAR_CHEAT ) ;
static float GetHexFloat ( const char * pStr )
{
if ( ( pStr [ 0 ] = = ' 0 ' ) & & ( pStr [ 1 ] = = ' x ' ) )
{
uint32 f = ( uint32 ) V_atoi64 ( pStr ) ;
return * reinterpret_cast < const float * > ( & f ) ;
}
return atof ( pStr ) ;
}
//------------------------------------------------------------------------------
// Move position
//------------------------------------------------------------------------------
CON_COMMAND_F ( setpos_exact , " Move player to an exact specified origin (must have sv_cheats). " , FCVAR_CHEAT )
{
if ( ! sv_cheats - > GetBool ( ) )
return ;
CBasePlayer * pPlayer = ToBasePlayer ( UTIL_GetCommandClient ( ) ) ;
if ( ! pPlayer )
return ;
if ( args . ArgC ( ) < 3 )
{
ClientPrint ( pPlayer , HUD_PRINTCONSOLE , " Usage: setpos_exact x y <z optional> \n " ) ;
return ;
}
Vector oldorigin = pPlayer - > GetAbsOrigin ( ) ;
Vector newpos ;
newpos . x = GetHexFloat ( args [ 1 ] ) ;
newpos . y = GetHexFloat ( args [ 2 ] ) ;
newpos . z = args . ArgC ( ) = = 4 ? GetHexFloat ( args [ 3 ] ) : oldorigin . z ;
pPlayer - > Teleport ( & newpos , NULL , NULL ) ;
if ( ! TestEntityPosition ( pPlayer ) )
{
if ( pPlayer - > GetMoveType ( ) ! = MOVETYPE_NOCLIP )
{
EnableNoClip ( pPlayer ) ;
return ;
}
}
}
CON_COMMAND_F ( setang_exact , " Snap player eyes and orientation to specified pitch yaw <roll:optional> (must have sv_cheats). " , FCVAR_CHEAT )
{
if ( ! sv_cheats - > GetBool ( ) )
return ;
CBasePlayer * pPlayer = ToBasePlayer ( UTIL_GetCommandClient ( ) ) ;
if ( ! pPlayer )
return ;
if ( args . ArgC ( ) < 3 )
{
ClientPrint ( pPlayer , HUD_PRINTCONSOLE , " Usage: setang_exact pitch yaw <roll optional> \n " ) ;
return ;
}
QAngle oldang = pPlayer - > GetAbsAngles ( ) ;
QAngle newang ;
newang . x = GetHexFloat ( args [ 1 ] ) ;
newang . y = GetHexFloat ( args [ 2 ] ) ;
newang . z = args . ArgC ( ) = = 4 ? GetHexFloat ( args [ 3 ] ) : oldang . z ;
pPlayer - > Teleport ( NULL , & newang , NULL ) ;
pPlayer - > SnapEyeAngles ( newang ) ;
# ifdef TF_DLL
static_cast < CTFPlayer * > ( pPlayer ) - > DoAnimationEvent ( PLAYERANIMEVENT_SNAP_YAW ) ;
# endif
}
//------------------------------------------------------------------------------
// Sets client to notarget mode.
//------------------------------------------------------------------------------
void CC_Notarget_f ( void )
{
if ( ! sv_cheats - > GetBool ( ) )
return ;
CBasePlayer * pPlayer = ToBasePlayer ( UTIL_GetCommandClient ( ) ) ;
if ( ! pPlayer )
return ;
if ( gpGlobals - > deathmatch )
return ;
pPlayer - > ToggleFlag ( FL_NOTARGET ) ;
if ( ! ( pPlayer - > GetFlags ( ) & FL_NOTARGET ) )
ClientPrint ( pPlayer , HUD_PRINTCONSOLE , " notarget OFF \n " ) ;
else
ClientPrint ( pPlayer , HUD_PRINTCONSOLE , " notarget ON \n " ) ;
}
ConCommand notarget ( " notarget " , CC_Notarget_f , " Toggle. Player becomes hidden to NPCs. " , FCVAR_CHEAT ) ;
//------------------------------------------------------------------------------
// Damage the client the specified amount
//------------------------------------------------------------------------------
void CC_HurtMe_f ( const CCommand & args )
{
if ( ! sv_cheats - > GetBool ( ) )
return ;
CBasePlayer * pPlayer = ToBasePlayer ( UTIL_GetCommandClient ( ) ) ;
if ( ! pPlayer )
return ;
int iDamage = 10 ;
if ( args . ArgC ( ) > = 2 )
{
iDamage = atoi ( args [ 1 ] ) ;
}
pPlayer - > TakeDamage ( CTakeDamageInfo ( pPlayer , pPlayer , iDamage , DMG_PREVENT_PHYSICS_FORCE ) ) ;
}
static ConCommand hurtme ( " hurtme " , CC_HurtMe_f , " Hurts the player. \n \t Arguments: <health to lose> " , FCVAR_CHEAT ) ;
static bool IsInGroundList ( CBaseEntity * ent , CBaseEntity * ground )
{
if ( ! ground | | ! ent )
return false ;
groundlink_t * root = ( groundlink_t * ) ground - > GetDataObject ( GROUNDLINK ) ;
if ( root )
{
groundlink_t * link = root - > nextLink ;
while ( link ! = root )
{
CBaseEntity * other = link - > entity ;
if ( other = = ent )
return true ;
link = link - > nextLink ;
}
}
return false ;
}
static int DescribeGroundList ( CBaseEntity * ent )
{
if ( ! ent )
return 0 ;
int c = 1 ;
Msg ( " %i : %s (ground %i %s) \n " , ent - > entindex ( ) , ent - > GetClassname ( ) ,
ent - > GetGroundEntity ( ) ? ent - > GetGroundEntity ( ) - > entindex ( ) : - 1 ,
ent - > GetGroundEntity ( ) ? ent - > GetGroundEntity ( ) - > GetClassname ( ) : " NULL " ) ;
groundlink_t * root = ( groundlink_t * ) ent - > GetDataObject ( GROUNDLINK ) ;
if ( root )
{
groundlink_t * link = root - > nextLink ;
while ( link ! = root )
{
CBaseEntity * other = link - > entity ;
if ( other )
{
Msg ( " %02i: %i %s \n " , c + + , other - > entindex ( ) , other - > GetClassname ( ) ) ;
if ( other - > GetGroundEntity ( ) ! = ent )
{
Assert ( 0 ) ;
Msg ( " mismatched!!! \n " ) ;
}
}
else
{
Assert ( 0 ) ;
Msg ( " %02i: NULL link \n " , c + + ) ;
}
link = link - > nextLink ;
}
}
if ( ent - > GetGroundEntity ( ) ! = NULL )
{
Assert ( IsInGroundList ( ent , ent - > GetGroundEntity ( ) ) ) ;
}
return c - 1 ;
}
void CC_GroundList_f ( const CCommand & args )
{
if ( ! UTIL_IsCommandIssuedByServerAdmin ( ) )
return ;
if ( args . ArgC ( ) = = 2 )
{
int idx = atoi ( args [ 1 ] ) ;
CBaseEntity * ground = CBaseEntity : : Instance ( idx ) ;
if ( ground )
{
DescribeGroundList ( ground ) ;
}
}
else
{
CBaseEntity * ent = NULL ;
int linkCount = 0 ;
while ( ( ent = gEntList . NextEnt ( ent ) ) ! = NULL )
{
linkCount + = DescribeGroundList ( ent ) ;
}
extern int groundlinksallocated ;
Assert ( linkCount = = groundlinksallocated ) ;
Msg ( " --- %i links \n " , groundlinksallocated ) ;
}
}
static ConCommand groundlist ( " groundlist " , CC_GroundList_f , " Display ground entity list <index> " ) ;
//-----------------------------------------------------------------------------
// Purpose: called each time a player uses a "cmd" command
// Input : *pEdict - the player who issued the command
//-----------------------------------------------------------------------------
void ClientCommand ( CBasePlayer * pPlayer , const CCommand & args )
{
const char * pCmd = args [ 0 ] ;
// Is the client spawned yet?
if ( ! pPlayer )
return ;
MDLCACHE_CRITICAL_SECTION ( ) ;
/*
const char * pstr ;
if ( ( ( pstr = strstr ( pcmd , " weapon_ " ) ) ! = NULL ) & & ( pstr = = pcmd ) )
{
// Subtype may be specified
if ( args . ArgC ( ) = = 2 )
{
pPlayer - > SelectItem ( pcmd , atoi ( args [ 1 ] ) ) ;
}
else
{
pPlayer - > SelectItem ( pcmd ) ;
}
}
*/
if ( FStrEq ( pCmd , " killtarget " ) )
{
if ( g_pDeveloper - > GetBool ( ) & & sv_cheats - > GetBool ( ) & & UTIL_IsCommandIssuedByServerAdmin ( ) )
{
ConsoleKillTarget ( pPlayer , args [ 1 ] ) ;
}
}
else if ( FStrEq ( pCmd , " demorestart " ) )
{
pPlayer - > ForceClientDllUpdate ( ) ;
}
else if ( FStrEq ( pCmd , " fade " ) )
{
color32 black = { 32 , 63 , 100 , 200 } ;
UTIL_ScreenFade ( pPlayer , black , 3 , 3 , FFADE_OUT ) ;
}
else if ( FStrEq ( pCmd , " te " ) )
{
if ( sv_cheats - > GetBool ( ) & & UTIL_IsCommandIssuedByServerAdmin ( ) )
{
if ( FStrEq ( args [ 1 ] , " stop " ) )
{
// Destroy it
//
CBaseEntity * ent = gEntList . FindEntityByClassname ( NULL , " te_tester " ) ;
while ( ent )
{
CBaseEntity * next = gEntList . FindEntityByClassname ( ent , " te_tester " ) ;
UTIL_Remove ( ent ) ;
ent = next ;
}
}
else
{
CTempEntTester : : Create ( pPlayer - > WorldSpaceCenter ( ) , pPlayer - > EyeAngles ( ) , args [ 1 ] , args [ 2 ] ) ;
}
}
}
else
{
if ( ! g_pGameRules - > ClientCommand ( pPlayer , args ) )
{
if ( Q_strlen ( pCmd ) > 128 )
{
ClientPrint ( pPlayer , HUD_PRINTCONSOLE , " Console command too long. \n " ) ;
}
else
{
// tell the user they entered an unknown command
ClientPrint ( pPlayer , HUD_PRINTCONSOLE , UTIL_VarArgs ( " Unknown command: %s \n " , pCmd ) ) ;
}
}
}
}