Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1869 lines
53 KiB

  1. //======= Copyright (c) 1996-2009, Valve Corporation, All rights reserved. ======
  2. //
  3. // Purpose: client/server game specific stuff
  4. //
  5. //===============================================================================
  6. #include "cbase.h"
  7. #include "player.h"
  8. #include "client.h"
  9. #include "soundent.h"
  10. #include "gamerules.h"
  11. #include "game.h"
  12. #include "physics.h"
  13. #include "entitylist.h"
  14. #include "shake.h"
  15. #include "globalstate.h"
  16. #include "event_tempentity_tester.h"
  17. #include "ndebugoverlay.h"
  18. #include "engine/IEngineSound.h"
  19. #include <ctype.h>
  20. #include "tier1/strtools.h"
  21. #include "te_effect_dispatch.h"
  22. #include "globals.h"
  23. #include "nav_mesh.h"
  24. #include "team.h"
  25. #include "EventLog.h"
  26. #include "datacache/imdlcache.h"
  27. #include "basemultiplayerplayer.h"
  28. #include "voice_gamemgr.h"
  29. #include "fmtstr.h"
  30. #include "videocfg/videocfg.h"
  31. #if defined( CSTRIKE15 )
  32. #include "cs_gamerules.h"
  33. #include "cs_team.h"
  34. #endif
  35. #ifdef TF_DLL
  36. #include "tf_player.h"
  37. #endif
  38. #ifdef HL2_DLL
  39. #include "weapon_physcannon.h"
  40. #endif
  41. // memdbgon must be the last include file in a .cpp file!!!
  42. #include "tier0/memdbgon.h"
  43. extern int giPrecacheGrunt;
  44. extern bool IsInCommentaryMode( void );
  45. ConVar *sv_cheats = NULL;
  46. static ConVar tv_relaytextchat( "tv_relaytextchat", "1", FCVAR_RELEASE, "Relay text chat data: 0=off, 1=say, 2=say+say_team" );
  47. void ClientKill( edict_t *pEdict, const Vector &vecForce, bool bExplode = false )
  48. {
  49. CBasePlayer *pPlayer = static_cast<CBasePlayer*>( GetContainingEntity( pEdict ) );
  50. pPlayer->CommitSuicide( vecForce, bExplode );
  51. }
  52. char * CheckChatText( CBasePlayer *pPlayer, char *text )
  53. {
  54. char *p = text;
  55. // invalid if NULL or empty
  56. if ( !text || !text[0] )
  57. return NULL;
  58. int length = Q_strlen( text );
  59. // remove quotes (leading & trailing) if present
  60. if (*p == '"')
  61. {
  62. p++;
  63. length -=2;
  64. p[length] = 0;
  65. }
  66. // cut off after 127 chars
  67. if ( length > 127 )
  68. text[127] = 0;
  69. GameRules()->CheckChatText( pPlayer, p );
  70. return p;
  71. }
  72. //// HOST_SAY
  73. // String comes in as
  74. // say blah blah blah
  75. // or as
  76. // blah blah blah
  77. //
  78. void Host_Say( edict_t *pEdict, const CCommand &args, bool teamonly )
  79. {
  80. CBasePlayer *client;
  81. int j;
  82. char *p;
  83. char text[256];
  84. char szTemp[256];
  85. const char *cpSay = "say";
  86. const char *cpSayTeam = "say_team";
  87. const char *pcmd = args[0];
  88. bool bSenderDead = false;
  89. // We can get a raw string now, without the "say " prepended
  90. if ( args.ArgC() == 0 )
  91. return;
  92. if ( !stricmp( pcmd, cpSay) || !stricmp( pcmd, cpSayTeam ) )
  93. {
  94. if ( args.ArgC() >= 2 )
  95. {
  96. p = (char *)args.ArgS();
  97. }
  98. else
  99. {
  100. // say with a blank message, nothing to do
  101. return;
  102. }
  103. }
  104. else // Raw text, need to prepend argv[0]
  105. {
  106. if ( args.ArgC() >= 2 )
  107. {
  108. Q_snprintf( szTemp,sizeof(szTemp), "%s %s", ( char * )pcmd, (char *)args.ArgS() );
  109. }
  110. else
  111. {
  112. // Just a one word command, use the first word...sigh
  113. Q_snprintf( szTemp,sizeof(szTemp), "%s", ( char * )pcmd );
  114. }
  115. p = szTemp;
  116. }
  117. CBasePlayer *pPlayer = NULL;
  118. if ( pEdict )
  119. {
  120. pPlayer = ((CBasePlayer *)CBaseEntity::Instance( pEdict ));
  121. Assert( pPlayer );
  122. // make sure the text has valid content
  123. p = CheckChatText( pPlayer, p );
  124. }
  125. if ( !p )
  126. return;
  127. if ( pEdict )
  128. {
  129. if ( !pPlayer->CanSpeak() )
  130. return;
  131. // See if the player wants to modify of check the text
  132. pPlayer->CheckChatText( p, 127 ); // though the buffer szTemp that p points to is 256,
  133. // chat text is capped to 127 in CheckChatText above
  134. // make sure the text has valid content
  135. p = CheckChatText( pPlayer, p );
  136. if ( !p )
  137. return;
  138. Assert( strlen( pPlayer->GetPlayerName() ) > 0 );
  139. bSenderDead = ( pPlayer->m_lifeState != LIFE_ALIVE );
  140. }
  141. else
  142. {
  143. bSenderDead = false;
  144. }
  145. const char *pszFormat = NULL;
  146. const char *pszPrefix = NULL;
  147. const char *pszLocation = NULL;
  148. if ( g_pGameRules )
  149. {
  150. pszFormat = g_pGameRules->GetChatFormat( teamonly, pPlayer );
  151. pszPrefix = g_pGameRules->GetChatPrefix( teamonly, pPlayer );
  152. pszLocation = g_pGameRules->GetChatLocation( teamonly, pPlayer );
  153. }
  154. const char *pszPlayerName = pPlayer ? pPlayer->GetPlayerName():"Console";
  155. if ( pszPrefix && strlen( pszPrefix ) > 0 )
  156. {
  157. if ( pszLocation && strlen( pszLocation ) )
  158. {
  159. Q_snprintf( text, sizeof(text), "%s %s @ %s: ", pszPrefix, pszPlayerName, pszLocation );
  160. }
  161. else
  162. {
  163. Q_snprintf( text, sizeof(text), "%s %s: ", pszPrefix, pszPlayerName );
  164. }
  165. }
  166. else
  167. {
  168. Q_snprintf( text, sizeof(text), "%s: ", pszPlayerName );
  169. }
  170. j = sizeof(text) - 2 - strlen(text); // -2 for /n and null terminator
  171. if ( (int)strlen(p) > j )
  172. p[j] = 0;
  173. Q_strncat( text, p, sizeof( text ), COPY_ALL_CHARACTERS );
  174. Q_strncat( text, "\n", sizeof( text ), COPY_ALL_CHARACTERS );
  175. // loop through all players
  176. // Start with the first player.
  177. // This may return the world in single player if the client types something between levels or during spawn
  178. // so check it, or it will infinite loop
  179. client = NULL;
  180. for ( int i = 1; i <= gpGlobals->maxClients; i++ )
  181. {
  182. client = ToBaseMultiplayerPlayer( UTIL_PlayerByIndex( i ) );
  183. if ( !client || !client->edict() )
  184. continue;
  185. if ( client->edict() == pEdict )
  186. continue;
  187. if ( !(client->IsNetClient()) ) // Not a client ? (should never be true)
  188. continue;
  189. if ( client->IsHLTV() )
  190. {
  191. if ( !tv_relaytextchat.GetInt() )
  192. continue; // chat is not relayed to TV
  193. else if ( teamonly && ( tv_relaytextchat.GetInt() < 2 ) )
  194. continue; // team-only chat, in mode that TV doesn't relay
  195. }
  196. else
  197. {
  198. if ( pPlayer && !g_pGameRules->PlayerCanHearChat( client, pPlayer, teamonly ) )
  199. continue;
  200. if ( pPlayer && !client->CanHearAndReadChatFrom( pPlayer ) )
  201. continue;
  202. if ( pPlayer && GetVoiceGameMgr() && GetVoiceGameMgr()->IsPlayerIgnoringPlayer( pPlayer->entindex(), i ) )
  203. continue;
  204. }
  205. CSingleUserRecipientFilter user( client );
  206. user.MakeReliable();
  207. if ( pszFormat )
  208. {
  209. UTIL_SayText2Filter( user, pPlayer,
  210. teamonly ? kEUtilSayTextMessageType_TeamonlyChat : kEUtilSayTextMessageType_AllChat,
  211. pszFormat, pszPlayerName, p, pszLocation );
  212. }
  213. else
  214. {
  215. UTIL_SayTextFilter( user, text, pPlayer,
  216. teamonly ? kEUtilSayTextMessageType_TeamonlyChat : kEUtilSayTextMessageType_AllChat );
  217. }
  218. }
  219. if ( pPlayer )
  220. {
  221. // print to the sending client
  222. CSingleUserRecipientFilter user( pPlayer );
  223. user.MakeReliable();
  224. if ( pszFormat )
  225. {
  226. UTIL_SayText2Filter( user, pPlayer,
  227. teamonly ? kEUtilSayTextMessageType_TeamonlyChat : kEUtilSayTextMessageType_AllChat,
  228. pszFormat, pszPlayerName, p, pszLocation );
  229. }
  230. else
  231. {
  232. UTIL_SayTextFilter( user, text, pPlayer,
  233. teamonly ? kEUtilSayTextMessageType_TeamonlyChat : kEUtilSayTextMessageType_AllChat );
  234. }
  235. }
  236. // echo to server console
  237. // Adrian: Only do this if we're running a dedicated server since we already print to console on the client.
  238. if ( engine->IsDedicatedServer() )
  239. Msg( "%s", text );
  240. Assert( p );
  241. int userid = 0;
  242. const char *networkID = "Console";
  243. const char *playerName = "Console";
  244. const char *playerTeam = "Console";
  245. if ( pPlayer )
  246. {
  247. userid = pPlayer->GetUserID();
  248. networkID = pPlayer->GetNetworkIDString();
  249. playerName = pPlayer->GetPlayerName();
  250. CTeam *team = pPlayer->GetTeam();
  251. if ( team )
  252. {
  253. playerTeam = team->GetName();
  254. }
  255. }
  256. if ( teamonly )
  257. UTIL_LogPrintf( "\"%s<%i><%s><%s>\" say_team \"%s\"\n", playerName, userid, networkID, playerTeam, p );
  258. else
  259. UTIL_LogPrintf( "\"%s<%i><%s><%s>\" say \"%s\"\n", playerName, userid, networkID, playerTeam, p );
  260. // Vitaliy 1/24/2013 -- converting text chat and voice chat to encrypted data
  261. // for TV implies that no unencrypted messages would contain the same text/voice.
  262. // Even though nothing in CS:GO codebase listens for "player_say" event there
  263. // are plugins that might want it. Broadcast the event if we are not encrypting
  264. // text data (3/22/2013)
  265. static ConVarRef tv_encryptdata_key( "tv_encryptdata_key" );
  266. static ConVarRef tv_encryptdata_key_pub( "tv_encryptdata_key_pub" );
  267. if ( *tv_encryptdata_key.GetString() || *tv_encryptdata_key_pub.GetString() )
  268. {
  269. // Do nothing, since we are encrypting text
  270. }
  271. else if ( IGameEvent * event = gameeventmanager->CreateEvent( "player_say" ) ) // will be null if there are no listeners!
  272. {
  273. event->SetInt("userid", userid );
  274. event->SetString("text", p );
  275. event->SetInt( "priority", 1 ); // player_say
  276. gameeventmanager->FireEvent( event );
  277. }
  278. }
  279. PRECACHE_REGISTER_BEGIN( GLOBAL, ClientPrecache )
  280. #ifndef DOTA_DLL
  281. // Precache cable textures.
  282. PRECACHE( MODEL, "cable/phonecable.vmt" )
  283. PRECACHE( MODEL, "cable/phonecable_red.vmt" )
  284. PRECACHE( MODEL, "cable/cable.vmt" )
  285. PRECACHE( MODEL, "cable/cable_lit.vmt" )
  286. PRECACHE( MODEL, "cable/chain.vmt" )
  287. PRECACHE( MODEL, "cable/rope.vmt" )
  288. PRECACHE( MODEL, "sprites/blueglow1.vmt" )
  289. PRECACHE( MODEL, "sprites/purpleglow1.vmt" )
  290. PRECACHE( MODEL, "sprites/purplelaser1.vmt" )
  291. #ifndef _WIN64 // TODO64: do we need to implement conditional precache in 64-bit?
  292. PRECACHE_CONDITIONAL( MODEL, "models/germangibs.mdl", g_Language.GetInt() == LANGUAGE_GERMAN )
  293. PRECACHE_CONDITIONAL( MODEL, "models/gibs/hgibs.mdl", g_Language.GetInt() != LANGUAGE_GERMAN )
  294. #endif
  295. PRECACHE( GAMESOUND, "Error" )
  296. PRECACHE( GAMESOUND, "Hud.Hint" )
  297. PRECACHE( GAMESOUND, "Player.FallDamage" )
  298. PRECACHE( GAMESOUND, "Player.Swim" )
  299. // General HUD sounds
  300. PRECACHE( GAMESOUND, "Player.PickupWeapon" )
  301. PRECACHE( GAMESOUND, "Player.DenyWeaponSelection" )
  302. PRECACHE( GAMESOUND, "Player.WeaponSelected" )
  303. PRECACHE( GAMESOUND, "Player.WeaponSelected_CT")
  304. PRECACHE( GAMESOUND, "Player.WeaponSelected_T")
  305. PRECACHE( GAMESOUND, "Player.WeaponSelectionClose" )
  306. PRECACHE( GAMESOUND, "Player.WeaponSelectionMoveSlot" )
  307. // General legacy temp ents sounds
  308. PRECACHE( GAMESOUND, "Bounce.Glass" )
  309. PRECACHE( GAMESOUND, "Bounce.Metal" )
  310. PRECACHE( GAMESOUND, "Bounce.Flesh" )
  311. PRECACHE( GAMESOUND, "Bounce.Wood" )
  312. PRECACHE( GAMESOUND, "Bounce.Shrapnel" )
  313. PRECACHE( GAMESOUND, "Bounce.ShotgunShell" )
  314. PRECACHE( GAMESOUND, "Bounce.Shell" )
  315. PRECACHE( GAMESOUND, "Bounce.Concrete" )
  316. PRECACHE( GAMESOUND, "BaseEntity.EnterWater" )
  317. PRECACHE( GAMESOUND, "BaseEntity.ExitWater" )
  318. #endif
  319. #ifdef PORTAL2
  320. PRECACHE( GAMESOUND, "GameUI.UiCoopHudActivate" )
  321. PRECACHE( GAMESOUND, "GameUI.UiCoopHudClick" )
  322. PRECACHE( GAMESOUND, "GameUI.UiCoopHudClickLow" )
  323. PRECACHE( GAMESOUND, "GameUI.UiCoopHudClickHigh" )
  324. PRECACHE( GAMESOUND, "GameUI.UiCoopHudDeactivate" )
  325. PRECACHE( GAMESOUND, "GameUI.UiCoopHudFocus" )
  326. PRECACHE( GAMESOUND, "GameUI.UiCoopHudUnfocus" )
  327. #endif
  328. // Game Instructor sounds
  329. PRECACHE( GAMESOUND, "Instructor.LessonStart" )
  330. PRECACHE( GAMESOUND, "Instructor.ImportantLessonStart" )
  331. PRECACHE_REGISTER_END()
  332. void ClientPrecache( void )
  333. {
  334. ClientGamePrecache();
  335. if ( !IsGameConsole() && !engine->IsDedicatedServerForXbox() )
  336. {
  337. // Force levels
  338. char pBuf[MAX_PATH];
  339. for ( int i = 0; i < CPU_LEVEL_PC_COUNT; ++i )
  340. {
  341. Q_snprintf( pBuf, sizeof(pBuf), "cfg/cpu_level_%d_pc.ekv", i );
  342. engine->ForceExactFile( pBuf );
  343. Q_snprintf( pBuf, sizeof(pBuf), "cfg/cpu_level_%d_pc_ss.ekv", i );
  344. engine->ForceExactFile( pBuf );
  345. }
  346. for ( int i = 0; i < GPU_LEVEL_PC_COUNT; ++i )
  347. {
  348. Q_snprintf( pBuf, sizeof(pBuf), "cfg/gpu_level_%d_pc.ekv", i );
  349. engine->ForceExactFile( pBuf );
  350. }
  351. for ( int i = 0; i < MEM_LEVEL_PC_COUNT; ++i )
  352. {
  353. Q_snprintf( pBuf, sizeof(pBuf), "cfg/mem_level_%d_pc.ekv", i );
  354. engine->ForceExactFile( pBuf );
  355. }
  356. for ( int i = 0; i < GPU_MEM_LEVEL_PC_COUNT; ++i )
  357. {
  358. Q_snprintf( pBuf, sizeof(pBuf), "cfg/gpu_mem_level_%d_pc.ekv", i );
  359. engine->ForceExactFile( pBuf );
  360. }
  361. }
  362. else
  363. {
  364. engine->ForceExactFile( "cfg/mem_level_360.ekv" );
  365. engine->ForceExactFile( "cfg/gpu_mem_level_360.ekv" );
  366. engine->ForceExactFile( "cfg/gpu_level_360.ekv" );
  367. engine->ForceExactFile( "cfg/cpu_level_360.ekv" );
  368. engine->ForceExactFile( "cfg/cpu_level_360_ss.ekv" );
  369. }
  370. // Game Instructor lessons - don't want people making simple scripted wall hacks
  371. engine->ForceExactFile( "scripts/instructor_lessons.txt" );
  372. engine->ForceExactFile( "scripts/mod_lessons.txt" );
  373. }
  374. CON_COMMAND_F( cast_ray, "Tests collision detection", FCVAR_CHEAT )
  375. {
  376. CBasePlayer *pPlayer = UTIL_GetCommandClient();
  377. Vector forward;
  378. trace_t tr;
  379. pPlayer->EyeVectors( &forward );
  380. Vector start = pPlayer->EyePosition();
  381. UTIL_TraceLine(start, start + forward * MAX_COORD_RANGE, MASK_SOLID, pPlayer, COLLISION_GROUP_NONE, &tr );
  382. if ( tr.DidHit() )
  383. {
  384. DevMsg(1, "Hit %s\nposition %.2f, %.2f, %.2f\nangles %.2f, %.2f, %.2f\n", tr.m_pEnt->GetClassname(),
  385. tr.m_pEnt->GetAbsOrigin().x, tr.m_pEnt->GetAbsOrigin().y, tr.m_pEnt->GetAbsOrigin().z,
  386. tr.m_pEnt->GetAbsAngles().x, tr.m_pEnt->GetAbsAngles().y, tr.m_pEnt->GetAbsAngles().z );
  387. 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 );
  388. NDebugOverlay::Line( start, tr.endpos, 0, 255, 0, false, 10 );
  389. NDebugOverlay::Line( tr.endpos, tr.endpos + tr.plane.normal * 12, 255, 255, 0, false, 10 );
  390. }
  391. }
  392. CON_COMMAND_F( cast_hull, "Tests hull collision detection", FCVAR_CHEAT )
  393. {
  394. CBasePlayer *pPlayer = UTIL_GetCommandClient();
  395. Vector forward;
  396. trace_t tr;
  397. Vector extents;
  398. extents.Init(16,16,16);
  399. pPlayer->EyeVectors( &forward );
  400. Vector start = pPlayer->EyePosition();
  401. UTIL_TraceHull(start, start + forward * MAX_COORD_RANGE, -extents, extents, MASK_SOLID, pPlayer, COLLISION_GROUP_NONE, &tr );
  402. if ( tr.DidHit() )
  403. {
  404. DevMsg(1, "Hit %s\nposition %.2f, %.2f, %.2f\nangles %.2f, %.2f, %.2f\n", tr.m_pEnt->GetClassname(),
  405. tr.m_pEnt->GetAbsOrigin().x, tr.m_pEnt->GetAbsOrigin().y, tr.m_pEnt->GetAbsOrigin().z,
  406. tr.m_pEnt->GetAbsAngles().x, tr.m_pEnt->GetAbsAngles().y, tr.m_pEnt->GetAbsAngles().z );
  407. 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 ) );
  408. NDebugOverlay::SweptBox( start, tr.endpos, -extents, extents, vec3_angle, 0, 0, 255, 0, 10 );
  409. Vector end = tr.endpos;// - tr.plane.normal * DotProductAbs( tr.plane.normal, extents );
  410. NDebugOverlay::Line( end, end + tr.plane.normal * 24, 255, 255, 64, false, 10 );
  411. }
  412. }
  413. //-----------------------------------------------------------------------------
  414. // Purpose: Used to find targets for ent_* commands
  415. // Without a name, returns the entity under the player's crosshair.
  416. // With a name it finds entities via name/classname/index
  417. //-----------------------------------------------------------------------------
  418. CBaseEntity *GetNextCommandEntity( CBasePlayer *pPlayer, const char *name, CBaseEntity *ent )
  419. {
  420. if ( !pPlayer )
  421. return NULL;
  422. // If no name was given set bits based on the picked
  423. if (FStrEq(name,""))
  424. {
  425. // If we've already found an entity, return NULL.
  426. // Makes it easier to write code using this func.
  427. if ( ent )
  428. return NULL;
  429. return pPlayer ? pPlayer->FindPickerEntity() : NULL;
  430. }
  431. int index = atoi( name );
  432. if ( index )
  433. {
  434. // If we've already found an entity, return NULL.
  435. // Makes it easier to write code using this func.
  436. if ( ent )
  437. return NULL;
  438. return CBaseEntity::Instance( index );
  439. }
  440. // Loop through all entities matching, starting from the specified previous
  441. while ( (ent = gEntList.NextEnt(ent)) != NULL )
  442. {
  443. if ( (ent->GetEntityName() != NULL_STRING && ent->NameMatches(name)) ||
  444. (ent->m_iClassname != NULL_STRING && ent->ClassMatches(name)) )
  445. {
  446. return ent;
  447. }
  448. }
  449. return NULL;
  450. }
  451. //-----------------------------------------------------------------------------
  452. // Purpose: called each time a player uses a "cmd" command
  453. // Input : pPlayer - the player who issued the command
  454. //-----------------------------------------------------------------------------
  455. void SetDebugBits( CBasePlayer* pPlayer, const char *name, int bit )
  456. {
  457. if ( !pPlayer )
  458. return;
  459. CBaseEntity *pEntity = NULL;
  460. while ( (pEntity = GetNextCommandEntity( pPlayer, name, pEntity )) != NULL )
  461. {
  462. if (pEntity->m_debugOverlays & bit)
  463. {
  464. pEntity->m_debugOverlays &= ~bit;
  465. }
  466. else
  467. {
  468. pEntity->m_debugOverlays |= bit;
  469. #ifdef AI_MONITOR_FOR_OSCILLATION
  470. if( pEntity->IsNPC() )
  471. {
  472. pEntity->MyNPCPointer()->m_ScheduleHistory.RemoveAll();
  473. }
  474. #endif//AI_MONITOR_FOR_OSCILLATION
  475. }
  476. }
  477. }
  478. //-----------------------------------------------------------------------------
  479. // Purpose:
  480. // Input : pKillTargetName -
  481. //-----------------------------------------------------------------------------
  482. void KillTargets( const char *pKillTargetName )
  483. {
  484. CBaseEntity *pentKillTarget = NULL;
  485. DevMsg( 2, "KillTarget: %s\n", pKillTargetName );
  486. pentKillTarget = gEntList.FindEntityByName( NULL, pKillTargetName );
  487. while ( pentKillTarget )
  488. {
  489. UTIL_Remove( pentKillTarget );
  490. DevMsg( 2, "killing %s\n", STRING( pentKillTarget->m_iClassname ) );
  491. pentKillTarget = gEntList.FindEntityByName( pentKillTarget, pKillTargetName );
  492. }
  493. }
  494. //------------------------------------------------------------------------------
  495. // Purpose:
  496. //------------------------------------------------------------------------------
  497. void ConsoleKillTarget( CBasePlayer *pPlayer, const char *name )
  498. {
  499. // If no name was given use the picker
  500. if (FStrEq(name,""))
  501. {
  502. CBaseEntity *pEntity = pPlayer ? pPlayer->FindPickerEntity() : NULL;
  503. if ( pEntity )
  504. {
  505. UTIL_Remove( pEntity );
  506. Msg( "killing %s\n", pEntity->GetDebugName() );
  507. return;
  508. }
  509. }
  510. // Otherwise use name or classname
  511. KillTargets( name );
  512. }
  513. //-----------------------------------------------------------------------------
  514. // Purpose:
  515. //-----------------------------------------------------------------------------
  516. class CPointClientCommand : public CPointEntity
  517. {
  518. public:
  519. DECLARE_CLASS( CPointClientCommand, CPointEntity );
  520. DECLARE_DATADESC();
  521. void InputCommand( inputdata_t& inputdata );
  522. };
  523. void CPointClientCommand::InputCommand( inputdata_t& inputdata )
  524. {
  525. if ( !inputdata.value.String()[0] )
  526. return;
  527. edict_t *pClient = NULL;
  528. if ( gpGlobals->maxClients == 1 )
  529. {
  530. pClient = INDEXENT( 1 );
  531. }
  532. else
  533. {
  534. // In multiplayer, send it back to the activator
  535. CBasePlayer *player = dynamic_cast< CBasePlayer * >( inputdata.pActivator );
  536. if ( player )
  537. {
  538. pClient = player->edict();
  539. }
  540. if ( IsInCommentaryMode() && !pClient )
  541. {
  542. // Commentary is stuffing a command in. We'll pretend it came from the first player.
  543. pClient = INDEXENT( 1 );
  544. }
  545. }
  546. if ( !pClient || !pClient->GetUnknown() )
  547. return;
  548. engine->ClientCommand( pClient, "%s\n", inputdata.value.String() );
  549. }
  550. BEGIN_DATADESC( CPointClientCommand )
  551. DEFINE_INPUTFUNC( FIELD_STRING, "Command", InputCommand ),
  552. END_DATADESC()
  553. LINK_ENTITY_TO_CLASS( point_clientcommand, CPointClientCommand );
  554. //-----------------------------------------------------------------------------
  555. // Purpose:
  556. //-----------------------------------------------------------------------------
  557. class CPointServerCommand : public CPointEntity
  558. {
  559. public:
  560. DECLARE_CLASS( CPointServerCommand, CPointEntity );
  561. DECLARE_DATADESC();
  562. void InputCommand( inputdata_t& inputdata );
  563. };
  564. //-----------------------------------------------------------------------------
  565. // Purpose:
  566. // Input : inputdata -
  567. //-----------------------------------------------------------------------------
  568. void CPointServerCommand::InputCommand( inputdata_t& inputdata )
  569. {
  570. if ( !inputdata.value.String()[0] )
  571. return;
  572. #if defined( CSTRIKE15 )
  573. CBasePlayer *player = UTIL_GetListenServerHost();
  574. // if we're on a dedicated server or a non-listen server, only accept whitelisted commands
  575. if ( engine->IsDedicatedServer() || player == NULL )
  576. {
  577. // Parse the text into distinct commands
  578. const char *pCurrentCommand = inputdata.value.String();
  579. int nOffsetToNextCommand;
  580. int nLen = Q_strlen( inputdata.value.String() );
  581. for( ; nLen > 0; nLen -= nOffsetToNextCommand+1, pCurrentCommand += nOffsetToNextCommand+1 )
  582. {
  583. // find a \n or ; line break
  584. int nCommandLength;
  585. UTIL_GetNextCommandLength( pCurrentCommand, nLen, &nCommandLength, &nOffsetToNextCommand );
  586. if ( nCommandLength <= 0 )
  587. continue;
  588. engine->ServerCommand( UTIL_VarArgs( "whitelistcmd %.*s\n", nCommandLength, pCurrentCommand ) );
  589. }
  590. return;
  591. }
  592. #endif
  593. engine->ServerCommand( UTIL_VarArgs( "%s\n", inputdata.value.String() ) );
  594. }
  595. BEGIN_DATADESC( CPointServerCommand )
  596. DEFINE_INPUTFUNC( FIELD_STRING, "Command", InputCommand ),
  597. END_DATADESC()
  598. LINK_ENTITY_TO_CLASS( point_servercommand, CPointServerCommand );
  599. //-----------------------------------------------------------------------------
  600. // Purpose:
  601. //-----------------------------------------------------------------------------
  602. class CPointBroadcastClientCommand : public CPointEntity
  603. {
  604. public:
  605. DECLARE_CLASS( CPointBroadcastClientCommand, CPointEntity );
  606. DECLARE_DATADESC();
  607. void InputCommand( inputdata_t& inputdata );
  608. };
  609. //-----------------------------------------------------------------------------
  610. // Purpose:
  611. // Input : inputdata -
  612. //-----------------------------------------------------------------------------
  613. void CPointBroadcastClientCommand::InputCommand( inputdata_t& inputdata )
  614. {
  615. if ( !inputdata.value.String()[0] )
  616. return;
  617. for ( int i = 1; i <= gpGlobals->maxClients; ++i )
  618. {
  619. CBasePlayer *pl = UTIL_PlayerByIndex( i );
  620. if ( !pl )
  621. continue;
  622. edict_t *pClient = pl->edict();
  623. if ( !pClient || !pClient->GetUnknown() )
  624. continue;
  625. engine->ClientCommand( pClient, "%s\n", inputdata.value.String() );
  626. }
  627. }
  628. BEGIN_DATADESC( CPointBroadcastClientCommand )
  629. DEFINE_INPUTFUNC( FIELD_STRING, "Command", InputCommand ),
  630. END_DATADESC()
  631. LINK_ENTITY_TO_CLASS( point_broadcastclientcommand, CPointBroadcastClientCommand );
  632. //------------------------------------------------------------------------------
  633. // Purpose : Draw a line betwen two points. White if no world collisions, red if collisions
  634. // Input :
  635. // Output :
  636. //------------------------------------------------------------------------------
  637. void CC_DrawLine( const CCommand &args )
  638. {
  639. Vector startPos;
  640. Vector endPos;
  641. startPos.x = clamp( atof(args[1]), MIN_COORD_FLOAT, MAX_COORD_FLOAT );
  642. startPos.y = clamp( atof(args[2]), MIN_COORD_FLOAT, MAX_COORD_FLOAT );
  643. startPos.z = clamp( atof(args[3]), MIN_COORD_FLOAT, MAX_COORD_FLOAT );
  644. endPos.x = clamp( atof(args[4]), MIN_COORD_FLOAT, MAX_COORD_FLOAT );
  645. endPos.y = clamp( atof(args[5]), MIN_COORD_FLOAT, MAX_COORD_FLOAT );
  646. endPos.z = clamp( atof(args[6]), MIN_COORD_FLOAT, MAX_COORD_FLOAT );
  647. UTIL_AddDebugLine(startPos,endPos,true,true);
  648. }
  649. static ConCommand drawline("drawline", CC_DrawLine, "Draws line between two 3D Points.\n\tGreen if no collision\n\tRed is collides with something\n\tArguments: x1 y1 z1 x2 y2 z2", FCVAR_CHEAT);
  650. //------------------------------------------------------------------------------
  651. // Purpose : Draw a cross at a points.
  652. // Input :
  653. // Output :
  654. //------------------------------------------------------------------------------
  655. void CC_DrawCross( const CCommand &args )
  656. {
  657. Vector vPosition;
  658. vPosition.x = clamp( atof(args[1]), MIN_COORD_FLOAT, MAX_COORD_FLOAT );
  659. vPosition.y = clamp( atof(args[2]), MIN_COORD_FLOAT, MAX_COORD_FLOAT );
  660. vPosition.z = clamp( atof(args[3]), MIN_COORD_FLOAT, MAX_COORD_FLOAT );
  661. // Offset since min and max z in not about center
  662. Vector mins = Vector(-5,-5,-5);
  663. Vector maxs = Vector(5,5,5);
  664. Vector start = mins + vPosition;
  665. Vector end = maxs + vPosition;
  666. UTIL_AddDebugLine(start,end,true,true);
  667. start.x += (maxs.x - mins.x);
  668. end.x -= (maxs.x - mins.x);
  669. UTIL_AddDebugLine(start,end,true,true);
  670. start.y += (maxs.y - mins.y);
  671. end.y -= (maxs.y - mins.y);
  672. UTIL_AddDebugLine(start,end,true,true);
  673. start.x -= (maxs.x - mins.x);
  674. end.x += (maxs.x - mins.x);
  675. UTIL_AddDebugLine(start,end,true,true);
  676. }
  677. static ConCommand drawcross("drawcross", CC_DrawCross, "Draws a cross at the given location\n\tArguments: x y z", FCVAR_CHEAT);
  678. //------------------------------------------------------------------------------
  679. // helper function for kill and explode
  680. //------------------------------------------------------------------------------
  681. void kill_helper( const CCommand &args, bool bVector, bool bExplode )
  682. {
  683. bool bKillOther = args.ArgC() > ( bVector ? 4 : 1 );
  684. CBasePlayer *pPlayer = NULL;
  685. if ( bKillOther && sv_cheats->GetBool() )
  686. {
  687. // Find the matching netname
  688. for ( int i = 1; i <= gpGlobals->maxClients; i++ )
  689. {
  690. pPlayer = ToBasePlayer( UTIL_PlayerByIndex(i) );
  691. if ( pPlayer && Q_strstr( pPlayer->GetPlayerName(), args[1] ) )
  692. break;
  693. pPlayer = NULL;
  694. }
  695. }
  696. else
  697. {
  698. pPlayer = UTIL_GetCommandClient();
  699. }
  700. if ( !pPlayer || g_pGameRules->IgnorePlayerKillCommand() )
  701. {
  702. return;
  703. }
  704. #if defined ( CSTRIKE15 )
  705. // If we're doing global assassination targets, we have a known assassinate quest and the player who is the target is on the correct team
  706. // then don't let them suicide.
  707. if ( CSGameRules() && CSGameRules()->GetActiveAssassinationQuest() )
  708. {
  709. CEconQuestDefinition *pQuest = CSGameRules()->GetActiveAssassinationQuest();
  710. CCSPlayer *pCSPlayer = ToCSPlayer( pPlayer );
  711. if ( pQuest && pCSPlayer
  712. && ( int( pQuest->GetTargetTeam() ) == pPlayer->GetTeamNumber() )
  713. && ( pCSPlayer->IsAssassinationTarget() ) )
  714. return;
  715. }
  716. #endif
  717. if ( bVector && sv_cheats->GetBool() )
  718. {
  719. int i = bKillOther ? 2 : 1;
  720. Vector vecForce;
  721. vecForce.x = atof( args[i++] );
  722. vecForce.y = atof( args[i++] );
  723. vecForce.z = atof( args[i++] );
  724. pPlayer->CommitSuicide( vecForce, bExplode );
  725. }
  726. else
  727. {
  728. pPlayer->CommitSuicide( bExplode );
  729. }
  730. }
  731. //------------------------------------------------------------------------------
  732. //------------------------------------------------------------------------------
  733. CON_COMMAND_F( kill, "Kills the player with generic damage", FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS )
  734. {
  735. kill_helper( args, false, false );
  736. }
  737. //------------------------------------------------------------------------------
  738. //------------------------------------------------------------------------------
  739. CON_COMMAND_F( explode, "Kills the player with explosive damage", FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS )
  740. {
  741. kill_helper( args, false, true );
  742. }
  743. //------------------------------------------------------------------------------
  744. //------------------------------------------------------------------------------
  745. CON_COMMAND_F( killvector, "Kills a player applying force. Usage: killvector <player> <x value> <y value> <z value>", FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS )
  746. {
  747. kill_helper( args, true, false );
  748. }
  749. //------------------------------------------------------------------------------
  750. //------------------------------------------------------------------------------
  751. CON_COMMAND_F( explodevector, "Kills a player applying an explosive force. Usage: explodevector <player> <x value> <y value> <z value>", FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS )
  752. {
  753. kill_helper( args, true, true );
  754. }
  755. //------------------------------------------------------------------------------
  756. //------------------------------------------------------------------------------
  757. CON_COMMAND_F( buddha, "Toggle. Player takes damage but won't die. (Shows red cross when health is zero)", FCVAR_CHEAT )
  758. {
  759. CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() );
  760. if ( pPlayer )
  761. {
  762. if (pPlayer->m_debugOverlays & OVERLAY_BUDDHA_MODE)
  763. {
  764. pPlayer->m_debugOverlays &= ~OVERLAY_BUDDHA_MODE;
  765. Msg("Buddha Mode off...\n");
  766. }
  767. else
  768. {
  769. pPlayer->m_debugOverlays |= OVERLAY_BUDDHA_MODE;
  770. Msg("Buddha Mode on...\n");
  771. }
  772. }
  773. }
  774. #define TALK_INTERVAL 0.66 // min time between say commands from a client
  775. //------------------------------------------------------------------------------
  776. //------------------------------------------------------------------------------
  777. CON_COMMAND_F( say, "Display player message", FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS )
  778. {
  779. CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() );
  780. if ( pPlayer )
  781. {
  782. if (( pPlayer->LastTimePlayerTalked() + TALK_INTERVAL ) < gpGlobals->curtime)
  783. {
  784. Host_Say( pPlayer->edict(), args, 0 );
  785. pPlayer->NotePlayerTalked();
  786. }
  787. }
  788. else if ( UTIL_IsCommandIssuedByServerAdmin() )
  789. {
  790. Host_Say( NULL, args, 0 );
  791. }
  792. }
  793. //------------------------------------------------------------------------------
  794. //------------------------------------------------------------------------------
  795. CON_COMMAND_F( say_team, "Display player message to team", FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS )
  796. {
  797. CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() );
  798. if (pPlayer)
  799. {
  800. if (( pPlayer->LastTimePlayerTalked() + TALK_INTERVAL ) < gpGlobals->curtime)
  801. {
  802. Host_Say( pPlayer->edict(), args, 1 );
  803. pPlayer->NotePlayerTalked();
  804. }
  805. }
  806. }
  807. //------------------------------------------------------------------------------
  808. //------------------------------------------------------------------------------
  809. CON_COMMAND_F( give, "Give item to player.\n\tArguments: <item_name>", FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS )
  810. {
  811. CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() );
  812. if ( pPlayer
  813. && (gpGlobals->maxClients == 1 || sv_cheats->GetBool())
  814. && args.ArgC() >= 2 )
  815. {
  816. char item_to_give[ 256 ];
  817. Q_strncpy( item_to_give, args[1], sizeof( item_to_give ) );
  818. Q_strlower( item_to_give );
  819. // Dirty hack to avoid suit playing it's pickup sound
  820. if ( !Q_stricmp( item_to_give, "item_suit" ) )
  821. {
  822. pPlayer->EquipSuit( false );
  823. return;
  824. }
  825. string_t iszItem = AllocPooledString( item_to_give ); // Make a copy of the classname
  826. pPlayer->GiveNamedItem( STRING(iszItem) );
  827. }
  828. }
  829. //------------------------------------------------------------------------------
  830. //------------------------------------------------------------------------------
  831. void CC_Player_SetModel( const CCommand &args )
  832. {
  833. if ( gpGlobals->deathmatch )
  834. return;
  835. CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() );
  836. if ( pPlayer && args.ArgC() == 2)
  837. {
  838. static char szName[256];
  839. Q_snprintf( szName, sizeof( szName ), "models/%s.mdl", args[1] );
  840. pPlayer->SetModel( szName );
  841. UTIL_SetSize(pPlayer, VEC_HULL_MIN, VEC_HULL_MAX);
  842. }
  843. }
  844. static ConCommand setmodel("setmodel", CC_Player_SetModel, "Changes's player's model", FCVAR_CHEAT );
  845. //-----------------------------------------------------------------------------
  846. // Purpose:
  847. //-----------------------------------------------------------------------------
  848. void CC_Player_TestDispatchEffect( const CCommand &args )
  849. {
  850. CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() );
  851. if ( !pPlayer)
  852. return;
  853. if ( args.ArgC() < 2 )
  854. {
  855. Msg(" Usage: test_dispatcheffect <effect name> <distance away> <flags> <magnitude> <scale>\n " );
  856. Msg(" defaults are: <distance 1024> <flags 0> <magnitude 0> <scale 0>\n" );
  857. return;
  858. }
  859. // Optional distance
  860. float flDistance = 1024;
  861. if ( args.ArgC() >= 3 )
  862. {
  863. flDistance = atoi( args[ 2 ] );
  864. }
  865. // Optional flags
  866. float flags = 0;
  867. if ( args.ArgC() >= 4 )
  868. {
  869. flags = atoi( args[ 3 ] );
  870. }
  871. // Optional magnitude
  872. float magnitude = 0;
  873. if ( args.ArgC() >= 5 )
  874. {
  875. magnitude = atof( args[ 4 ] );
  876. }
  877. // Optional scale
  878. float scale = 0;
  879. if ( args.ArgC() >= 6 )
  880. {
  881. scale = atof( args[ 5 ] );
  882. }
  883. Vector vecForward;
  884. QAngle vecAngles = pPlayer->EyeAngles();
  885. AngleVectors( vecAngles, &vecForward );
  886. // Trace forward
  887. trace_t tr;
  888. Vector vecSrc = pPlayer->EyePosition();
  889. Vector vecEnd = vecSrc + (vecForward * flDistance);
  890. UTIL_TraceLine( vecSrc, vecEnd, MASK_ALL, pPlayer, COLLISION_GROUP_NONE, &tr );
  891. // Fill out the generic data
  892. CEffectData data;
  893. // If we hit something, use that data
  894. if ( tr.fraction < 1.0 )
  895. {
  896. data.m_vOrigin = tr.endpos;
  897. VectorAngles( tr.plane.normal, data.m_vAngles );
  898. data.m_vNormal = tr.plane.normal;
  899. }
  900. else
  901. {
  902. data.m_vOrigin = vecEnd;
  903. data.m_vAngles = vecAngles;
  904. AngleVectors( vecAngles, &data.m_vNormal );
  905. }
  906. data.m_nEntIndex = pPlayer->entindex();
  907. data.m_fFlags = flags;
  908. data.m_flMagnitude = magnitude;
  909. data.m_flScale = scale;
  910. PrecacheEffect( (char *)args[1] );
  911. DispatchEffect( (char *)args[1], data );
  912. }
  913. static ConCommand test_dispatcheffect("test_dispatcheffect", CC_Player_TestDispatchEffect, "Test a clientside dispatch effect.\n\tUsage: test_dispatcheffect <effect name> <distance away> <flags> <magnitude> <scale>\n\tDefaults are: <distance 1024> <flags 0> <magnitude 0> <scale 0>\n", FCVAR_CHEAT);
  914. #ifdef HL2_DLL
  915. //-----------------------------------------------------------------------------
  916. // Purpose: Quickly switch to the physics cannon, or back to previous item
  917. //-----------------------------------------------------------------------------
  918. void CC_Player_PhysSwap( void )
  919. {
  920. CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() );
  921. if ( pPlayer )
  922. {
  923. CBaseCombatWeapon *pWeapon = pPlayer->GetActiveWeapon();
  924. if ( pWeapon )
  925. {
  926. // Tell the client to stop selecting weapons
  927. engine->ClientCommand( UTIL_GetCommandClient()->edict(), "cancelselect" );
  928. const char *strWeaponName = pWeapon->GetName();
  929. if ( !Q_stricmp( strWeaponName, "weapon_physcannon" ) )
  930. {
  931. PhysCannonForceDrop( pWeapon, NULL );
  932. pPlayer->SelectLastItem();
  933. }
  934. else
  935. {
  936. pPlayer->SelectItem( "weapon_physcannon" );
  937. }
  938. }
  939. }
  940. }
  941. static ConCommand physswap("phys_swap", CC_Player_PhysSwap, "Automatically swaps the current weapon for the physcannon and back again." );
  942. #endif
  943. //-----------------------------------------------------------------------------
  944. // Purpose: Quickly switch to the bug bait, or back to previous item
  945. //-----------------------------------------------------------------------------
  946. void CC_Player_BugBaitSwap( void )
  947. {
  948. CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() );
  949. if ( pPlayer )
  950. {
  951. CBaseCombatWeapon *pWeapon = pPlayer->GetActiveWeapon();
  952. if ( pWeapon )
  953. {
  954. // Tell the client to stop selecting weapons
  955. engine->ClientCommand( UTIL_GetCommandClient()->edict(), "cancelselect" );
  956. const char *strWeaponName = pWeapon->GetName();
  957. if ( !Q_stricmp( strWeaponName, "weapon_bugbait" ) )
  958. {
  959. pPlayer->SelectLastItem();
  960. }
  961. else
  962. {
  963. pPlayer->SelectItem( "weapon_bugbait" );
  964. }
  965. }
  966. }
  967. }
  968. static ConCommand bugswap("bug_swap", CC_Player_BugBaitSwap, "Automatically swaps the current weapon for the bug bait and back again.", FCVAR_CHEAT );
  969. //------------------------------------------------------------------------------
  970. //------------------------------------------------------------------------------
  971. void CC_Player_Use( const CCommand &args )
  972. {
  973. CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() );
  974. if ( pPlayer)
  975. {
  976. pPlayer->SelectItem((char *)args[1]);
  977. }
  978. }
  979. static ConCommand use("use", CC_Player_Use, "Use a particular weapon\t\nArguments: <weapon_name>", FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS );
  980. class SimplePhysicsTraceFilter : public IPhysicsTraceFilter
  981. {
  982. CBaseEntity *m_pEntity;
  983. int m_mask;
  984. public:
  985. SimplePhysicsTraceFilter( CBaseEntity *pEntity, int mask )
  986. {
  987. m_pEntity = pEntity;
  988. m_mask = mask;
  989. }
  990. virtual bool ShouldHitObject( IPhysicsObject *pObject, int contentsMask )
  991. {
  992. if ( m_pEntity->VPhysicsGetObject() == pObject )
  993. return false;
  994. if ( (m_mask & contentsMask) == 0 )
  995. return false;
  996. return true;
  997. }
  998. virtual PhysicsTraceType_t GetTraceType() const
  999. {
  1000. return VPHYSICS_TRACE_STATIC_AND_MOVING;
  1001. }
  1002. };
  1003. //------------------------------------------------------------------------------
  1004. // A small wrapper around SV_Move that never clips against the supplied entity.
  1005. //------------------------------------------------------------------------------
  1006. bool TestEntityPosition ( CBaseEntity *pEntity, unsigned int mask )
  1007. {
  1008. trace_t trace;
  1009. IPhysicsObject *physObject = pEntity->VPhysicsGetObject();
  1010. const Vector &origin = pEntity->GetAbsOrigin();
  1011. if ( physObject )
  1012. {
  1013. QAngle angles = pEntity->GetAbsAngles();
  1014. //Vector obbMins, obbMaxs;
  1015. Vector mins, maxs;
  1016. //obbMins = pEntity->CollisionProp()->OBBMins();
  1017. //obbMaxs = pEntity->CollisionProp()->OBBMaxs();
  1018. //pEntity->CollisionProp()->CollisionAABBToWorldAABB( obbMins, obbMaxs, &mins, &maxs );
  1019. pEntity->CollisionProp()->WorldSpaceSurroundingBounds( &mins, &maxs );
  1020. UTIL_TraceHull( vec3_origin, vec3_origin, mins, maxs, mask, pEntity, COLLISION_GROUP_NONE, &trace );
  1021. //SimplePhysicsTraceFilter filter( pEntity, (int)mask );
  1022. //physenv->SweepCollideable( physObject->GetCollide(), origin, origin, angles, mask, &filter, &trace );
  1023. }
  1024. else
  1025. {
  1026. UTIL_TraceEntity( pEntity, origin, origin, mask, &trace );
  1027. }
  1028. return (trace.startsolid == 0);
  1029. }
  1030. //------------------------------------------------------------------------------
  1031. // Searches along the direction ray in steps of "step" to see if
  1032. // the entity position is passible.
  1033. // Used for putting the player in valid space when toggling off noclip mode.
  1034. //------------------------------------------------------------------------------
  1035. static int FindPassableSpace( CBaseEntity *pEntity, unsigned int mask, const Vector& direction, float step, Vector& oldorigin )
  1036. {
  1037. int i;
  1038. for ( i = 0; i < 100; i++ )
  1039. {
  1040. Vector origin = pEntity->GetAbsOrigin();
  1041. VectorMA( origin, step, direction, origin );
  1042. pEntity->SetAbsOrigin( origin );
  1043. if ( TestEntityPosition( pEntity, mask ) )
  1044. {
  1045. VectorCopy( pEntity->GetAbsOrigin(), oldorigin );
  1046. return 1;
  1047. }
  1048. }
  1049. return 0;
  1050. }
  1051. //------------------------------------------------------------------------------
  1052. // Test various directions for empty space -- for debugging only; this is slow and
  1053. // meant for finding a place to put a noclipped player who goes solid again.
  1054. //------------------------------------------------------------------------------
  1055. bool FindEmptySpace( CBaseEntity *pEntity, unsigned int mask, const Vector &forward, const Vector &right, const Vector &up, Vector *testOrigin )
  1056. {
  1057. return FindPassableSpace( pEntity, mask, forward, 1, *testOrigin ) || // forward
  1058. FindPassableSpace( pEntity, mask, right, 1, *testOrigin ) || // right
  1059. FindPassableSpace( pEntity, mask, right, -1, *testOrigin ) || // left
  1060. FindPassableSpace( pEntity, mask, up, 1, *testOrigin ) || // up
  1061. FindPassableSpace( pEntity, mask, up, -1, *testOrigin ) || // down
  1062. FindPassableSpace( pEntity, mask, forward, -1, *testOrigin ) ; // back
  1063. }
  1064. //------------------------------------------------------------------------------
  1065. // Noclip
  1066. //------------------------------------------------------------------------------
  1067. ConVar noclip_fixup( "noclip_fixup", "1", FCVAR_CHEAT );
  1068. void EnableNoClip( CBasePlayer *pPlayer )
  1069. {
  1070. // Disengage from hierarchy
  1071. pPlayer->SetParent( NULL );
  1072. pPlayer->SetMoveType( MOVETYPE_NOCLIP );
  1073. ClientPrint( pPlayer, HUD_PRINTCONSOLE, "noclip ON\n");
  1074. pPlayer->AddEFlags( EFL_NOCLIP_ACTIVE );
  1075. pPlayer->NoClipStateChanged();
  1076. engine->SetNoClipEnabled( true );
  1077. UTIL_LogPrintf( "%s entered NOCLIP mode\n", GameLogSystem()->FormatPlayer( pPlayer ) );
  1078. }
  1079. void DisableNoClip( CBasePlayer *pPlayer )
  1080. {
  1081. CPlayerState *pl = pPlayer->PlayerData();
  1082. Assert( pl );
  1083. pPlayer->RemoveEFlags( EFL_NOCLIP_ACTIVE );
  1084. pPlayer->SetMoveType( MOVETYPE_WALK );
  1085. ClientPrint( pPlayer, HUD_PRINTCONSOLE, "noclip OFF\n");
  1086. Vector oldorigin = pPlayer->GetAbsOrigin();
  1087. unsigned int mask = MASK_PLAYERSOLID;
  1088. if ( noclip_fixup.GetBool() && !TestEntityPosition( pPlayer, mask ) )
  1089. {
  1090. Vector forward, right, up;
  1091. AngleVectors ( pl->v_angle, &forward, &right, &up);
  1092. if ( !FindEmptySpace( pPlayer, mask, forward, right, up, &oldorigin ) )
  1093. {
  1094. Msg( "Can't find the world\n" );
  1095. }
  1096. pPlayer->SetAbsOrigin( oldorigin );
  1097. }
  1098. pPlayer->NoClipStateChanged();
  1099. engine->SetNoClipEnabled( false );
  1100. UTIL_LogPrintf( "%s left NOCLIP mode\n", GameLogSystem()->FormatPlayer( pPlayer ) );
  1101. }
  1102. CON_COMMAND_F( noclip, "Toggle. Player becomes non-solid and flies. Optional argument of 0 or 1 to force enable/disable", FCVAR_CHEAT )
  1103. {
  1104. if ( !sv_cheats->GetBool() )
  1105. return;
  1106. CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() );
  1107. if ( !pPlayer )
  1108. return;
  1109. if ( args.ArgC() >= 2 )
  1110. {
  1111. bool bEnable = Q_atoi( args.Arg( 1 ) ) ? true : false;
  1112. if ( bEnable && pPlayer->GetMoveType() != MOVETYPE_NOCLIP )
  1113. {
  1114. EnableNoClip( pPlayer );
  1115. }
  1116. else if ( !bEnable && pPlayer->GetMoveType() == MOVETYPE_NOCLIP )
  1117. {
  1118. DisableNoClip( pPlayer );
  1119. }
  1120. }
  1121. else
  1122. {
  1123. // Toggle the noclip state if there aren't any arguments.
  1124. if ( pPlayer->GetMoveType() != MOVETYPE_NOCLIP )
  1125. {
  1126. EnableNoClip( pPlayer );
  1127. }
  1128. else
  1129. {
  1130. DisableNoClip( pPlayer );
  1131. }
  1132. }
  1133. }
  1134. //------------------------------------------------------------------------------
  1135. // Sets client to godmode
  1136. //------------------------------------------------------------------------------
  1137. void CC_God_f (void)
  1138. {
  1139. if ( !sv_cheats->GetBool() )
  1140. return;
  1141. CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() );
  1142. if ( !pPlayer )
  1143. return;
  1144. // if ( gpGlobals->deathmatch )
  1145. // return;
  1146. pPlayer->ToggleFlag( FL_GODMODE );
  1147. if (!(pPlayer->GetFlags() & FL_GODMODE ) )
  1148. ClientPrint( pPlayer, HUD_PRINTCONSOLE, "godmode OFF\n");
  1149. else
  1150. ClientPrint( pPlayer, HUD_PRINTCONSOLE, "godmode ON\n");
  1151. }
  1152. //------------------------------------------------------------------------------
  1153. // Sets all players to godmode
  1154. //------------------------------------------------------------------------------
  1155. void CC_Gods_f (void)
  1156. {
  1157. if ( !sv_cheats->GetBool() )
  1158. return;
  1159. // Decide how to toggle based on the state of the local player.
  1160. bool turnOn = false;
  1161. CBasePlayer *pLocalPlayer = ToBasePlayer( UTIL_GetCommandClient() );
  1162. if ( pLocalPlayer )
  1163. {
  1164. turnOn = !(pLocalPlayer->GetFlags() & FL_GODMODE);
  1165. }
  1166. for ( int i = 1; i <= gpGlobals->maxClients; ++i )
  1167. {
  1168. CBasePlayer *pPlayer = ToBasePlayer( UTIL_PlayerByIndex( i ) );
  1169. if ( !pPlayer )
  1170. continue;
  1171. if ( turnOn != ( ( pPlayer->GetFlags() & FL_GODMODE ) > 0 ) )
  1172. {
  1173. pPlayer->ToggleFlag( FL_GODMODE );
  1174. }
  1175. }
  1176. ClientPrint( pLocalPlayer, HUD_PRINTCONSOLE, turnOn ? "godsmode ON\n" : "godsmode OFF\n");
  1177. }
  1178. static ConCommand god("god", CC_God_f, "Toggle. Player becomes invulnerable.", FCVAR_CHEAT );
  1179. static ConCommand gods("gods", CC_Gods_f, "Toggle. All players become invulnerable.", FCVAR_CHEAT );
  1180. CON_COMMAND_F( ent_setpos, "Move entity to position", FCVAR_CHEAT )
  1181. {
  1182. if ( !sv_cheats->GetBool() )
  1183. return;
  1184. CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() );
  1185. if ( !pPlayer )
  1186. return;
  1187. if ( args.ArgC() < 4 )
  1188. {
  1189. ClientPrint( pPlayer, HUD_PRINTCONSOLE, "Usage: ent_setpos index x y <optional z>\n");
  1190. return;
  1191. }
  1192. int nIndex = Q_atoi( args[ 1 ] );
  1193. CBaseEntity *ent = CBaseEntity::Instance( nIndex );
  1194. if ( !ent )
  1195. {
  1196. ClientPrint( pPlayer, HUD_PRINTCONSOLE, UTIL_VarArgs( "ent_setpos no entity %d\n", nIndex ) );
  1197. return;
  1198. }
  1199. Vector oldorigin = ent->GetAbsOrigin();
  1200. Vector newpos;
  1201. newpos.x = atof( args[2] );
  1202. newpos.y = atof( args[3] );
  1203. newpos.z = args.ArgC() == 5 ? atof( args[4] ) : oldorigin.z;
  1204. ent->SetAbsOrigin( newpos );
  1205. }
  1206. CON_COMMAND_F( ent_setang, "Set entity angles", FCVAR_CHEAT )
  1207. {
  1208. if ( !sv_cheats->GetBool() )
  1209. return;
  1210. CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() );
  1211. if ( !pPlayer )
  1212. return;
  1213. if ( args.ArgC() < 4 )
  1214. {
  1215. ClientPrint( pPlayer, HUD_PRINTCONSOLE, "Usage: ent_setang index pitch yaw <optional roll>\n");
  1216. return;
  1217. }
  1218. int nIndex = Q_atoi( args[ 1 ] );
  1219. CBaseEntity *ent = CBaseEntity::Instance( nIndex );
  1220. if ( !ent )
  1221. {
  1222. ClientPrint( pPlayer, HUD_PRINTCONSOLE, UTIL_VarArgs( "ent_setang no entity %d\n", nIndex ) );
  1223. return;
  1224. }
  1225. QAngle old = ent->GetAbsAngles();
  1226. QAngle newAng;
  1227. newAng.x = atof( args[2] );
  1228. newAng.y = atof( args[3] );
  1229. newAng.z = args.ArgC() == 5 ? atof( args[4] ) : old.z;
  1230. ent->SetAbsAngles( newAng );
  1231. }
  1232. //------------------------------------------------------------------------------
  1233. // Sets client to godmode
  1234. //------------------------------------------------------------------------------
  1235. CON_COMMAND_F( setpos, "Move player to specified origin (must have sv_cheats).", FCVAR_CHEAT )
  1236. {
  1237. if ( !sv_cheats->GetBool() )
  1238. return;
  1239. CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() );
  1240. if ( !pPlayer )
  1241. return;
  1242. if ( args.ArgC() < 3 )
  1243. {
  1244. ClientPrint( pPlayer, HUD_PRINTCONSOLE, "Usage: setpos x y <z optional>\n");
  1245. return;
  1246. }
  1247. Vector oldorigin = pPlayer->GetAbsOrigin();
  1248. Vector newpos;
  1249. newpos.x = clamp( atof( args[1] ), MIN_COORD_FLOAT, MAX_COORD_FLOAT );
  1250. newpos.y = clamp( atof( args[2] ), MIN_COORD_FLOAT, MAX_COORD_FLOAT );
  1251. newpos.z = args.ArgC() == 4 ? clamp( atof( args[3] ), MIN_COORD_FLOAT, MAX_COORD_FLOAT ) : oldorigin.z;
  1252. pPlayer->SetAbsOrigin( newpos );
  1253. if ( !TestEntityPosition( pPlayer, MASK_PLAYERSOLID ) )
  1254. {
  1255. ClientPrint( pPlayer, HUD_PRINTCONSOLE, "setpos into world, use noclip to unstick yourself!\n");
  1256. }
  1257. }
  1258. //------------------------------------------------------------------------------
  1259. // Sets client to godmode
  1260. //------------------------------------------------------------------------------
  1261. CON_COMMAND_F( setpos_player, "Move specified player to specified origin (must have sv_cheats).", FCVAR_CHEAT )
  1262. {
  1263. if ( !sv_cheats->GetBool() )
  1264. return;
  1265. CBasePlayer *pCommandPlayer = ToBasePlayer( UTIL_GetCommandClient() );
  1266. if ( !pCommandPlayer )
  1267. return;
  1268. if ( args.ArgC() < 4 )
  1269. {
  1270. ClientPrint( pCommandPlayer, HUD_PRINTCONSOLE, "Usage: setpos player_index x y <z optional>\n");
  1271. return;
  1272. }
  1273. CBasePlayer *pPlayer = ToBasePlayer( UTIL_PlayerByIndex( atoi( args[1] ) ) );
  1274. if ( !pPlayer )
  1275. return;
  1276. Vector oldorigin = pPlayer->GetAbsOrigin();
  1277. Vector newpos;
  1278. newpos.x = atof( args[2] );
  1279. newpos.y = atof( args[3] );
  1280. newpos.z = args.ArgC() == 5 ? atof( args[4] ) : oldorigin.z;
  1281. pPlayer->SetAbsOrigin( newpos );
  1282. if ( !TestEntityPosition( pPlayer, MASK_PLAYERSOLID ) )
  1283. {
  1284. ClientPrint( pPlayer, HUD_PRINTCONSOLE, "setpos into world, use noclip to unstick yourself!\n");
  1285. }
  1286. }
  1287. //------------------------------------------------------------------------------
  1288. // Sets client to godmode
  1289. //------------------------------------------------------------------------------
  1290. void CC_setang_f (const CCommand &args)
  1291. {
  1292. if ( !sv_cheats->GetBool() )
  1293. return;
  1294. CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() );
  1295. if ( !pPlayer )
  1296. return;
  1297. if ( args.ArgC() < 3 )
  1298. {
  1299. ClientPrint( pPlayer, HUD_PRINTCONSOLE, "Usage: setang pitch yaw <roll optional>\n");
  1300. return;
  1301. }
  1302. QAngle oldang = pPlayer->GetAbsAngles();
  1303. QAngle newang;
  1304. newang.x = atof( args[1] );
  1305. newang.y = atof( args[2] );
  1306. newang.z = args.ArgC() == 4 ? atof( args[3] ) : oldang.z;
  1307. pPlayer->SnapEyeAngles( newang );
  1308. }
  1309. static ConCommand setang("setang", CC_setang_f, "Snap player eyes to specified pitch yaw <roll:optional> (must have sv_cheats).", FCVAR_CHEAT );
  1310. //------------------------------------------------------------------------------
  1311. // Move position
  1312. //------------------------------------------------------------------------------
  1313. CON_COMMAND_F( setpos_exact, "Move player to an exact specified origin (must have sv_cheats).", FCVAR_CHEAT )
  1314. {
  1315. if ( !sv_cheats->GetBool() )
  1316. return;
  1317. CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() );
  1318. if ( !pPlayer )
  1319. return;
  1320. if ( args.ArgC() < 3 )
  1321. {
  1322. ClientPrint( pPlayer, HUD_PRINTCONSOLE, "Usage: setpos_exact x y <z optional>\n");
  1323. return;
  1324. }
  1325. Vector oldorigin = pPlayer->GetAbsOrigin();
  1326. Vector newpos;
  1327. newpos.x = atof( args[1] );
  1328. newpos.y = atof( args[2] );
  1329. newpos.z = args.ArgC() == 4 ? atof( args[3] ) : oldorigin.z;
  1330. pPlayer->Teleport( &newpos, NULL, NULL );
  1331. if ( !TestEntityPosition( pPlayer, MASK_PLAYERSOLID ) )
  1332. {
  1333. if ( pPlayer->GetMoveType() != MOVETYPE_NOCLIP )
  1334. {
  1335. EnableNoClip( pPlayer );
  1336. return;
  1337. }
  1338. }
  1339. }
  1340. CON_COMMAND_F( setang_exact, "Snap player eyes and orientation to specified pitch yaw <roll:optional> (must have sv_cheats).", FCVAR_CHEAT )
  1341. {
  1342. if ( !sv_cheats->GetBool() )
  1343. return;
  1344. CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() );
  1345. if ( !pPlayer )
  1346. return;
  1347. if ( args.ArgC() < 3 )
  1348. {
  1349. ClientPrint( pPlayer, HUD_PRINTCONSOLE, "Usage: setang_exact pitch yaw <roll optional>\n");
  1350. return;
  1351. }
  1352. QAngle oldang = pPlayer->GetAbsAngles();
  1353. QAngle newang;
  1354. newang.x = atof( args[1] );
  1355. newang.y = atof( args[2] );
  1356. newang.z = args.ArgC() == 4 ? atof( args[3] ) : oldang.z;
  1357. pPlayer->Teleport( NULL, &newang, NULL );
  1358. pPlayer->SnapEyeAngles( newang );
  1359. #ifdef TF_DLL
  1360. static_cast<CTFPlayer*>( pPlayer )->DoAnimationEvent( PLAYERANIMEVENT_SNAP_YAW );
  1361. #endif
  1362. }
  1363. //------------------------------------------------------------------------------
  1364. // Sets client to notarget mode.
  1365. //------------------------------------------------------------------------------
  1366. void CC_Notarget_f (void)
  1367. {
  1368. if ( !sv_cheats->GetBool() )
  1369. return;
  1370. CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() );
  1371. if ( !pPlayer )
  1372. return;
  1373. if ( gpGlobals->deathmatch )
  1374. return;
  1375. pPlayer->ToggleFlag( FL_NOTARGET );
  1376. if ( !(pPlayer->GetFlags() & FL_NOTARGET ) )
  1377. ClientPrint( pPlayer, HUD_PRINTCONSOLE, "notarget OFF\n");
  1378. else
  1379. ClientPrint( pPlayer, HUD_PRINTCONSOLE, "notarget ON\n");
  1380. }
  1381. ConCommand notarget("notarget", CC_Notarget_f, "Toggle. Player becomes hidden to NPCs.", FCVAR_CHEAT);
  1382. //------------------------------------------------------------------------------
  1383. // Damage the client the specified amount
  1384. //------------------------------------------------------------------------------
  1385. void CC_HurtMe_f(const CCommand &args)
  1386. {
  1387. if ( !sv_cheats->GetBool() )
  1388. return;
  1389. CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() );
  1390. if ( !pPlayer )
  1391. return;
  1392. int iDamage = 10;
  1393. if ( args.ArgC() >= 2 )
  1394. {
  1395. iDamage = atoi( args[ 1 ] );
  1396. }
  1397. pPlayer->TakeDamage( CTakeDamageInfo( pPlayer, pPlayer, iDamage, DMG_PREVENT_PHYSICS_FORCE ) );
  1398. }
  1399. static ConCommand hurtme("hurtme", CC_HurtMe_f, "Hurts the player.\n\tArguments: <health to lose>", FCVAR_CHEAT);
  1400. static bool IsInGroundList( CBaseEntity *ent, CBaseEntity *ground )
  1401. {
  1402. if ( !ground || !ent )
  1403. return false;
  1404. groundlink_t *root = ( groundlink_t * )ground->GetDataObject( GROUNDLINK );
  1405. if ( root )
  1406. {
  1407. groundlink_t *link = root->nextLink;
  1408. while ( link != root )
  1409. {
  1410. CBaseEntity *other = link->entity;
  1411. if ( other == ent )
  1412. return true;
  1413. link = link->nextLink;
  1414. }
  1415. }
  1416. return false;
  1417. }
  1418. static int DescribeGroundList( CBaseEntity *ent )
  1419. {
  1420. if ( !ent )
  1421. return 0;
  1422. int c = 1;
  1423. Msg( "%i : %s (ground %i %s)\n", ent->entindex(), ent->GetClassname(),
  1424. ent->GetGroundEntity() ? ent->GetGroundEntity()->entindex() : -1,
  1425. ent->GetGroundEntity() ? ent->GetGroundEntity()->GetClassname() : "NULL" );
  1426. groundlink_t *root = ( groundlink_t * )ent->GetDataObject( GROUNDLINK );
  1427. if ( root )
  1428. {
  1429. groundlink_t *link = root->nextLink;
  1430. while ( link != root )
  1431. {
  1432. CBaseEntity *other = link->entity;
  1433. if ( other )
  1434. {
  1435. Msg( " %02i: %i %s\n", c++, other->entindex(), other->GetClassname() );
  1436. if ( other->GetGroundEntity() != ent )
  1437. {
  1438. Assert( 0 );
  1439. Msg( " mismatched!!!\n" );
  1440. }
  1441. }
  1442. else
  1443. {
  1444. Assert( 0 );
  1445. Msg( " %02i: NULL link\n", c++ );
  1446. }
  1447. link = link->nextLink;
  1448. }
  1449. }
  1450. if ( ent->GetGroundEntity() != NULL )
  1451. {
  1452. Assert( IsInGroundList( ent, ent->GetGroundEntity() ) );
  1453. }
  1454. return c - 1;
  1455. }
  1456. void CC_GroundList_f(const CCommand &args)
  1457. {
  1458. if ( !UTIL_IsCommandIssuedByServerAdmin() )
  1459. return;
  1460. if ( args.ArgC() == 2 )
  1461. {
  1462. int idx = atoi( args[1] );
  1463. CBaseEntity *ground = CBaseEntity::Instance( idx );
  1464. if ( ground )
  1465. {
  1466. DescribeGroundList( ground );
  1467. }
  1468. }
  1469. else
  1470. {
  1471. CBaseEntity *ent = NULL;
  1472. int linkCount = 0;
  1473. while ( (ent = gEntList.NextEnt(ent)) != NULL )
  1474. {
  1475. linkCount += DescribeGroundList( ent );
  1476. }
  1477. extern int groundlinksallocated;
  1478. Assert( linkCount == groundlinksallocated );
  1479. Msg( "--- %i links\n", groundlinksallocated );
  1480. }
  1481. }
  1482. static ConCommand groundlist("groundlist", CC_GroundList_f, "Display ground entity list <index>" );
  1483. //-----------------------------------------------------------------------------
  1484. // Purpose: called each time a player uses a "cmd" command
  1485. // Input : *pEdict - the player who issued the command
  1486. //-----------------------------------------------------------------------------
  1487. void ClientCommand( CBasePlayer *pPlayer, const CCommand &args )
  1488. {
  1489. const char *pCmd = args[0];
  1490. // Is the client spawned yet?
  1491. if ( !pPlayer )
  1492. return;
  1493. MDLCACHE_CRITICAL_SECTION();
  1494. /*
  1495. const char *pstr;
  1496. if (((pstr = strstr(pcmd, "weapon_")) != NULL) && (pstr == pcmd))
  1497. {
  1498. // Subtype may be specified
  1499. if ( args.ArgC() == 2 )
  1500. {
  1501. pPlayer->SelectItem( pcmd, atoi( args[1] ) );
  1502. }
  1503. else
  1504. {
  1505. pPlayer->SelectItem(pcmd);
  1506. }
  1507. }
  1508. */
  1509. if ( FStrEq( pCmd, "killtarget" ) )
  1510. {
  1511. if ( g_pDeveloper->GetBool() && sv_cheats->GetBool() && UTIL_IsCommandIssuedByServerAdmin() )
  1512. {
  1513. ConsoleKillTarget( pPlayer, args[1] );
  1514. }
  1515. }
  1516. else if ( FStrEq( pCmd, "demorestart" ) )
  1517. {
  1518. pPlayer->ForceClientDllUpdate();
  1519. }
  1520. else if ( FStrEq( pCmd, "fade" ) )
  1521. {
  1522. color32 black = {32,63,100,200};
  1523. UTIL_ScreenFade( pPlayer, black, 3, 3, FFADE_OUT );
  1524. }
  1525. else if ( FStrEq( pCmd, "te" ) )
  1526. {
  1527. if ( sv_cheats->GetBool() && UTIL_IsCommandIssuedByServerAdmin() )
  1528. {
  1529. if ( FStrEq( args[1], "stop" ) )
  1530. {
  1531. // Destroy it
  1532. //
  1533. CBaseEntity *ent = gEntList.FindEntityByClassname( NULL, "te_tester" );
  1534. while ( ent )
  1535. {
  1536. CBaseEntity *next = gEntList.FindEntityByClassname( ent, "te_tester" );
  1537. UTIL_Remove( ent );
  1538. ent = next;
  1539. }
  1540. }
  1541. else
  1542. {
  1543. CTempEntTester::Create( pPlayer->WorldSpaceCenter(), pPlayer->EyeAngles(), args[1], args[2] );
  1544. }
  1545. }
  1546. }
  1547. #ifdef _DEBUG
  1548. else if ( FStrEq( pCmd, "bugpause" ) )
  1549. {
  1550. // bug reporter opening, pause all connected clients
  1551. CFmtStr str;
  1552. UTIL_ClientPrintAll( HUD_PRINTTALK, str.sprintf( "BUG REPORTER ACTIVATED BY: %s\n", pPlayer->GetPlayerName() ) );
  1553. engine->Pause( true, true );
  1554. }
  1555. else if ( FStrEq( pCmd, "bugunpause" ) )
  1556. {
  1557. // bug reporter closing, unpause all connected clients
  1558. engine->Pause( false, true );
  1559. }
  1560. #endif
  1561. else
  1562. {
  1563. if ( !g_pGameRules->ClientCommand( pPlayer, args ) )
  1564. {
  1565. if ( Q_strlen( pCmd ) > 128 )
  1566. {
  1567. ClientPrint( pPlayer, HUD_PRINTCONSOLE, "Console command too long.\n" );
  1568. }
  1569. else
  1570. {
  1571. // tell the user they entered an unknown command
  1572. ClientPrint( pPlayer, HUD_PRINTCONSOLE, UTIL_VarArgs( "Unknown command: %s\n", pCmd ) );
  1573. }
  1574. }
  1575. }
  1576. }