Team Fortress 2 Source Code as on 22/4/2020
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.

677 lines
21 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #include "cbase.h"
  9. #include "../EventLog.h"
  10. #include "team.h"
  11. #include "teamplayroundbased_gamerules.h"
  12. #include "tf_gamerules.h"
  13. #include "team_control_point_master.h"
  14. #include "team_control_point_round.h"
  15. #include "tf_team.h"
  16. #include "KeyValues.h"
  17. extern ConVar tf_flag_caps_per_round;
  18. class CTFEventLog : public CEventLog
  19. {
  20. private:
  21. typedef CEventLog BaseClass;
  22. public:
  23. bool PrintEvent( IGameEvent *event ) // override virtual function
  24. {
  25. if ( !PrintTFEvent( event ) ) // allow TF to override logging
  26. {
  27. return BaseClass::PrintEvent( event );
  28. }
  29. else
  30. {
  31. return true;
  32. }
  33. }
  34. bool Init()
  35. {
  36. BaseClass::Init();
  37. ListenForGameEvent( "player_death" );
  38. ListenForGameEvent( "medic_death" );
  39. ListenForGameEvent( "player_hurt" );
  40. ListenForGameEvent( "player_changeclass" );
  41. ListenForGameEvent( "tf_game_over" );
  42. ListenForGameEvent( "player_chargedeployed" );
  43. ListenForGameEvent( "teamplay_flag_event" );
  44. ListenForGameEvent( "teamplay_capture_blocked" );
  45. ListenForGameEvent( "teamplay_point_captured" );
  46. ListenForGameEvent( "teamplay_round_stalemate" );
  47. ListenForGameEvent( "teamplay_round_win" );
  48. ListenForGameEvent( "teamplay_game_over" );
  49. ListenForGameEvent( "player_builtobject" );
  50. ListenForGameEvent( "player_carryobject" );
  51. ListenForGameEvent( "player_dropobject" );
  52. ListenForGameEvent( "object_removed" );
  53. ListenForGameEvent( "object_detonated" );
  54. ListenForGameEvent( "object_destroyed" );
  55. return true;
  56. }
  57. protected:
  58. bool PrintTFEvent( IGameEvent *event ) // print Mod specific logs
  59. {
  60. const char *eventName = event->GetName();
  61. if ( !Q_strncmp( eventName, "server_", strlen("server_")) )
  62. {
  63. return false; // ignore server_ messages
  64. }
  65. if ( !Q_strncmp( eventName, "player_death", Q_strlen( "player_death" ) ) )
  66. {
  67. const int userid = event->GetInt( "userid" );
  68. CBasePlayer *pPlayer = UTIL_PlayerByUserId( userid );
  69. if ( !pPlayer )
  70. {
  71. return false;
  72. }
  73. const int attackerid = event->GetInt( "attacker" );
  74. const char *weapon = event->GetString( "weapon_logclassname" );
  75. int iCustomDamage = event->GetInt( "customkill" );
  76. CBasePlayer *pAttacker = UTIL_PlayerByUserId( attackerid );
  77. if ( pPlayer == pAttacker )
  78. {
  79. UTIL_LogPrintf( "\"%s<%i><%s><%s>\" committed suicide with \"%s\" (attacker_position \"%d %d %d\")\n",
  80. pPlayer->GetPlayerName(),
  81. userid,
  82. pPlayer->GetNetworkIDString(),
  83. pPlayer->GetTeam()->GetName(),
  84. weapon,
  85. (int)pPlayer->GetAbsOrigin().x,
  86. (int)pPlayer->GetAbsOrigin().y,
  87. (int)pPlayer->GetAbsOrigin().z );
  88. }
  89. else if ( pAttacker )
  90. {
  91. const char *pszCustom = NULL;
  92. switch( iCustomDamage )
  93. {
  94. case TF_DMG_CUSTOM_HEADSHOT_DECAPITATION:
  95. case TF_DMG_CUSTOM_HEADSHOT:
  96. pszCustom = "headshot";
  97. break;
  98. case TF_DMG_CUSTOM_BACKSTAB:
  99. pszCustom = "backstab";
  100. break;
  101. default:
  102. break;
  103. }
  104. // is the spy feigning death?
  105. if ( event->GetInt( "death_flags" ) & TF_DEATH_FEIGN_DEATH )
  106. {
  107. pszCustom = "feign_death";
  108. }
  109. if ( pszCustom )
  110. {
  111. UTIL_LogPrintf( "\"%s<%i><%s><%s>\" killed \"%s<%i><%s><%s>\" with \"%s\" (customkill \"%s\") (attacker_position \"%d %d %d\") (victim_position \"%d %d %d\")\n",
  112. pAttacker->GetPlayerName(),
  113. attackerid,
  114. pAttacker->GetNetworkIDString(),
  115. pAttacker->GetTeam()->GetName(),
  116. pPlayer->GetPlayerName(),
  117. userid,
  118. pPlayer->GetNetworkIDString(),
  119. pPlayer->GetTeam()->GetName(),
  120. weapon,
  121. pszCustom,
  122. (int)pAttacker->GetAbsOrigin().x,
  123. (int)pAttacker->GetAbsOrigin().y,
  124. (int)pAttacker->GetAbsOrigin().z,
  125. (int)pPlayer->GetAbsOrigin().x,
  126. (int)pPlayer->GetAbsOrigin().y,
  127. (int)pPlayer->GetAbsOrigin().z );
  128. }
  129. else
  130. {
  131. UTIL_LogPrintf( "\"%s<%i><%s><%s>\" killed \"%s<%i><%s><%s>\" with \"%s\" (attacker_position \"%d %d %d\") (victim_position \"%d %d %d\")\n",
  132. pAttacker->GetPlayerName(),
  133. attackerid,
  134. pAttacker->GetNetworkIDString(),
  135. pAttacker->GetTeam()->GetName(),
  136. pPlayer->GetPlayerName(),
  137. userid,
  138. pPlayer->GetNetworkIDString(),
  139. pPlayer->GetTeam()->GetName(),
  140. weapon,
  141. (int)pAttacker->GetAbsOrigin().x,
  142. (int)pAttacker->GetAbsOrigin().y,
  143. (int)pAttacker->GetAbsOrigin().z,
  144. (int)pPlayer->GetAbsOrigin().x,
  145. (int)pPlayer->GetAbsOrigin().y,
  146. (int)pPlayer->GetAbsOrigin().z );
  147. }
  148. }
  149. else
  150. {
  151. int iDamageBits = event->GetInt( "damagebits" );
  152. if ( ( iDamageBits & DMG_VEHICLE ) || ( iDamageBits & DMG_NERVEGAS ) )
  153. {
  154. const char *pszCustomKill = "train";
  155. if ( iDamageBits & DMG_NERVEGAS )
  156. {
  157. pszCustomKill = "saw";
  158. }
  159. // killed by the world
  160. UTIL_LogPrintf( "\"%s<%i><%s><%s>\" committed suicide with \"world\" (customkill \"%s\") (attacker_position \"%d %d %d\")\n",
  161. pPlayer->GetPlayerName(),
  162. userid,
  163. pPlayer->GetNetworkIDString(),
  164. pPlayer->GetTeam()->GetName(),
  165. pszCustomKill,
  166. (int)pPlayer->GetAbsOrigin().x,
  167. (int)pPlayer->GetAbsOrigin().y,
  168. (int)pPlayer->GetAbsOrigin().z );
  169. }
  170. else
  171. {
  172. // killed by the world
  173. UTIL_LogPrintf( "\"%s<%i><%s><%s>\" committed suicide with \"world\" (attacker_position \"%d %d %d\")\n",
  174. pPlayer->GetPlayerName(),
  175. userid,
  176. pPlayer->GetNetworkIDString(),
  177. pPlayer->GetTeam()->GetName(),
  178. (int)pPlayer->GetAbsOrigin().x,
  179. (int)pPlayer->GetAbsOrigin().y,
  180. (int)pPlayer->GetAbsOrigin().z );
  181. }
  182. }
  183. // Assist kill
  184. int assistid = event->GetInt( "assister" );
  185. CBasePlayer *pAssister = UTIL_PlayerByUserId( assistid );
  186. if ( pAssister )
  187. {
  188. UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"kill assist\" against \"%s<%i><%s><%s>\" (assister_position \"%d %d %d\") (attacker_position \"%d %d %d\") (victim_position \"%d %d %d\")\n",
  189. pAssister->GetPlayerName(),
  190. assistid,
  191. pAssister->GetNetworkIDString(),
  192. pAssister->GetTeam()->GetName(),
  193. pPlayer->GetPlayerName(),
  194. userid,
  195. pPlayer->GetNetworkIDString(),
  196. pPlayer->GetTeam()->GetName(),
  197. (int)pAssister->GetAbsOrigin().x,
  198. (int)pAssister->GetAbsOrigin().y,
  199. (int)pAssister->GetAbsOrigin().z,
  200. pAttacker ? (int)pAttacker->GetAbsOrigin().x : 0,
  201. pAttacker ? (int)pAttacker->GetAbsOrigin().y : 0,
  202. pAttacker ? (int)pAttacker->GetAbsOrigin().z : 0,
  203. (int)pPlayer->GetAbsOrigin().x,
  204. (int)pPlayer->GetAbsOrigin().y,
  205. (int)pPlayer->GetAbsOrigin().z );
  206. }
  207. // Domination and Revenge
  208. // pAttacker //int attackerid = engine->GetPlayerForUserID( event->GetInt( "attacker" ) );
  209. // pPlayer //int userid = engine->GetPlayerForUserID( event->GetInt( "userid" ) );
  210. // pAssister // assistid
  211. if ( event->GetInt( "death_flags" ) & TF_DEATH_DOMINATION && pAttacker )
  212. {
  213. UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"domination\" against \"%s<%i><%s><%s>\"\n",
  214. pAttacker->GetPlayerName(),
  215. attackerid,
  216. pAttacker->GetNetworkIDString(),
  217. pAttacker->GetTeam()->GetName(),
  218. pPlayer->GetPlayerName(),
  219. userid,
  220. pPlayer->GetNetworkIDString(),
  221. pPlayer->GetTeam()->GetName()
  222. );
  223. }
  224. if ( event->GetInt( "death_flags" ) & TF_DEATH_ASSISTER_DOMINATION && pAssister )
  225. {
  226. UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"domination\" against \"%s<%i><%s><%s>\" (assist \"1\")\n",
  227. pAssister->GetPlayerName(),
  228. assistid,
  229. pAssister->GetNetworkIDString(),
  230. pAssister->GetTeam()->GetName(),
  231. pPlayer->GetPlayerName(),
  232. userid,
  233. pPlayer->GetNetworkIDString(),
  234. pPlayer->GetTeam()->GetName()
  235. );
  236. }
  237. if ( event->GetInt( "death_flags" ) & TF_DEATH_REVENGE && pAttacker )
  238. {
  239. UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"revenge\" against \"%s<%i><%s><%s>\"\n",
  240. pAttacker->GetPlayerName(),
  241. attackerid,
  242. pAttacker->GetNetworkIDString(),
  243. pAttacker->GetTeam()->GetName(),
  244. pPlayer->GetPlayerName(),
  245. userid,
  246. pPlayer->GetNetworkIDString(),
  247. pPlayer->GetTeam()->GetName()
  248. );
  249. }
  250. if ( event->GetInt( "death_flags" ) & TF_DEATH_ASSISTER_REVENGE && pAssister )
  251. {
  252. UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"revenge\" against \"%s<%i><%s><%s>\" (assist \"1\")\n",
  253. pAssister->GetPlayerName(),
  254. assistid,
  255. pAssister->GetNetworkIDString(),
  256. pAssister->GetTeam()->GetName(),
  257. pPlayer->GetPlayerName(),
  258. userid,
  259. pPlayer->GetNetworkIDString(),
  260. pPlayer->GetTeam()->GetName()
  261. );
  262. }
  263. return true;
  264. }
  265. else if ( FStrEq( eventName, "player_changeclass" ) )
  266. {
  267. const int userid = event->GetInt( "userid" );
  268. CBasePlayer *pPlayer = UTIL_PlayerByUserId( userid );
  269. if ( !pPlayer )
  270. {
  271. return false;
  272. }
  273. int iClass = event->GetInt("class");
  274. if ( pPlayer->GetTeamNumber() < FIRST_GAME_TEAM )
  275. return true;
  276. if ( iClass >= TF_FIRST_NORMAL_CLASS && iClass <= TF_LAST_NORMAL_CLASS )
  277. {
  278. UTIL_LogPrintf( "\"%s<%i><%s><%s>\" changed role to \"%s\"\n",
  279. pPlayer->GetPlayerName(),
  280. userid,
  281. pPlayer->GetNetworkIDString(),
  282. pPlayer->GetTeam()->GetName(),
  283. GetPlayerClassData( iClass )->m_szClassName
  284. );
  285. }
  286. return true;
  287. }
  288. else if ( FStrEq( eventName, "tf_game_over" ) || FStrEq( eventName, "teamplay_game_over" ) )
  289. {
  290. UTIL_LogPrintf( "World triggered \"Game_Over\" reason \"%s\"\n", event->GetString( "reason" ) );
  291. UTIL_LogPrintf( "Team \"Red\" final score \"%d\" with \"%d\" players\n", GetGlobalTeam( TF_TEAM_RED )->GetScore(), GetGlobalTeam( TF_TEAM_RED )->GetNumPlayers() );
  292. UTIL_LogPrintf( "Team \"Blue\" final score \"%d\" with \"%d\" players\n", GetGlobalTeam( TF_TEAM_BLUE )->GetScore(), GetGlobalTeam( TF_TEAM_BLUE )->GetNumPlayers() );
  293. return true;
  294. }
  295. else if ( FStrEq( eventName, "player_chargedeployed" ) )
  296. {
  297. const int userid = event->GetInt( "userid" );
  298. CBasePlayer *pPlayer = UTIL_PlayerByUserId( userid );
  299. if ( !pPlayer )
  300. {
  301. return false;
  302. }
  303. UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"chargedeployed\"\n",
  304. pPlayer->GetPlayerName(),
  305. userid,
  306. pPlayer->GetNetworkIDString(),
  307. pPlayer->GetTeam()->GetName()
  308. );
  309. return true;
  310. }
  311. else if ( FStrEq( eventName, "player_builtobject" ) ||
  312. FStrEq( eventName, "player_carryobject" ) ||
  313. FStrEq( eventName, "player_dropobject" ) ||
  314. FStrEq( eventName, "player_removed" ) ||
  315. FStrEq( eventName, "object_detonated" ) )
  316. {
  317. const int userid = event->GetInt( "userid" );
  318. CBasePlayer *pPlayer = UTIL_PlayerByUserId( userid );
  319. if ( pPlayer )
  320. {
  321. // Some events have "object" and some have "objecttype". We can't change them as there are third-party
  322. // scripts that listen for these events.
  323. const int objectid = !event->IsEmpty( "objecttype" ) ? event->GetInt( "objecttype" ) : event->GetInt( "object" );
  324. const CObjectInfo *pInfo = ( objectid >= 0 && objectid < OBJ_LAST ) ? GetObjectInfo( objectid ) : NULL;
  325. if ( pInfo )
  326. {
  327. UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"%s\" (object \"%s\") (position \"%d %d %d\")\n",
  328. pPlayer->GetPlayerName(),
  329. userid,
  330. pPlayer->GetNetworkIDString(),
  331. pPlayer->GetTeam()->GetName(),
  332. eventName,
  333. pInfo->m_pObjectName,
  334. (int)pPlayer->GetAbsOrigin().x,
  335. (int)pPlayer->GetAbsOrigin().y,
  336. (int)pPlayer->GetAbsOrigin().z );
  337. }
  338. return true;
  339. }
  340. return false;
  341. }
  342. else if ( FStrEq( eventName, "object_destroyed" ) )
  343. {
  344. int objectid = event->GetInt( "objecttype" );
  345. const CObjectInfo *pInfo = ( objectid >= 0 && objectid < OBJ_LAST ) ? GetObjectInfo( objectid ) : NULL;
  346. if ( !pInfo )
  347. return false;
  348. const int userid = event->GetInt( "userid" );
  349. CBasePlayer *pObjectOwner = UTIL_PlayerByUserId( userid );
  350. if ( !pObjectOwner )
  351. return false;
  352. const int attackerid = event->GetInt( "attacker" );
  353. CBasePlayer *pAttacker = UTIL_PlayerByUserId( attackerid );
  354. if ( !pAttacker )
  355. return false;
  356. const char *weapon = event->GetString( "weapon" );
  357. // log that the person killed an object
  358. UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"killedobject\" (object \"%s\") (weapon \"%s\") (objectowner \"%s<%i><%s><%s>\") (attacker_position \"%d %d %d\")\n",
  359. pAttacker->GetPlayerName(),
  360. attackerid,
  361. pAttacker->GetNetworkIDString(),
  362. pAttacker->GetTeam()->GetName(),
  363. pInfo->m_pObjectName,
  364. weapon,
  365. pObjectOwner->GetPlayerName(),
  366. userid,
  367. pObjectOwner->GetNetworkIDString(),
  368. pObjectOwner->GetTeam()->GetName(),
  369. (int)pAttacker->GetAbsOrigin().x,
  370. (int)pAttacker->GetAbsOrigin().y,
  371. (int)pAttacker->GetAbsOrigin().z );
  372. const int assisterid = event->GetInt( "assister" );
  373. CBasePlayer *pAssister = UTIL_PlayerByUserId( assisterid );
  374. if ( pAssister )
  375. {
  376. UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"killedobject\" (object \"%s\") (objectowner \"%s<%i><%s><%s>\") (assist \"1\") (assister_position \"%d %d %d\") (attacker_position \"%d %d %d\")\n",
  377. pAssister->GetPlayerName(),
  378. assisterid,
  379. pAssister->GetNetworkIDString(),
  380. pAssister->GetTeam()->GetName(),
  381. pInfo->m_pObjectName,
  382. pObjectOwner->GetPlayerName(),
  383. userid,
  384. pObjectOwner->GetNetworkIDString(),
  385. pObjectOwner->GetTeam()->GetName(),
  386. (int)pAssister->GetAbsOrigin().x,
  387. (int)pAssister->GetAbsOrigin().y,
  388. (int)pAssister->GetAbsOrigin().z,
  389. (int)pAttacker->GetAbsOrigin().x,
  390. (int)pAttacker->GetAbsOrigin().y,
  391. (int)pAttacker->GetAbsOrigin().z );
  392. }
  393. }
  394. else if ( FStrEq( eventName, "teamplay_flag_event" ) )
  395. {
  396. int playerindex = event->GetInt( "player" );
  397. CBasePlayer *pPlayer = UTIL_PlayerByIndex( playerindex );
  398. if ( !pPlayer )
  399. {
  400. return false;
  401. }
  402. const char *pszEvent = "unknown"; // picked up, dropped, defended, captured
  403. int iEventType = event->GetInt( "eventtype" );
  404. bool bPlainLogEntry = true;
  405. switch ( iEventType )
  406. {
  407. case TF_FLAGEVENT_PICKUP:
  408. pszEvent = "picked up";
  409. break;
  410. case TF_FLAGEVENT_CAPTURE:
  411. pszEvent = "captured";
  412. if ( tf_flag_caps_per_round.GetInt() > 0 )
  413. {
  414. bPlainLogEntry = false;
  415. }
  416. break;
  417. case TF_FLAGEVENT_DEFEND:
  418. pszEvent = "defended";
  419. break;
  420. case TF_FLAGEVENT_DROPPED:
  421. pszEvent = "dropped";
  422. break;
  423. }
  424. if ( bPlainLogEntry )
  425. {
  426. UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"flagevent\" (event \"%s\") (position \"%d %d %d\")\n",
  427. pPlayer->GetPlayerName(),
  428. pPlayer->GetUserID(),
  429. pPlayer->GetNetworkIDString(),
  430. pPlayer->GetTeam()->GetName(),
  431. pszEvent,
  432. (int)pPlayer->GetAbsOrigin().x,
  433. (int)pPlayer->GetAbsOrigin().y,
  434. (int)pPlayer->GetAbsOrigin().z );
  435. }
  436. else
  437. {
  438. CTFTeam *pTeam = GetGlobalTFTeam( pPlayer->GetTeamNumber() );
  439. UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"flagevent\" (event \"%s\") (team_caps \"%d\") (caps_per_round \"%d\") (position \"%d %d %d\")\n",
  440. pPlayer->GetPlayerName(),
  441. pPlayer->GetUserID(),
  442. pPlayer->GetNetworkIDString(),
  443. pPlayer->GetTeam()->GetName(),
  444. pszEvent,
  445. pTeam->GetFlagCaptures(),
  446. tf_flag_caps_per_round.GetInt(),
  447. (int)pPlayer->GetAbsOrigin().x,
  448. (int)pPlayer->GetAbsOrigin().y,
  449. (int)pPlayer->GetAbsOrigin().z );
  450. }
  451. return true;
  452. }
  453. else if ( FStrEq( eventName, "teamplay_capture_blocked" ) )
  454. {
  455. int blockerindex = event->GetInt( "blocker" );
  456. CBasePlayer *pBlocker = UTIL_PlayerByIndex( blockerindex );
  457. if ( !pBlocker )
  458. {
  459. return true;
  460. }
  461. UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"captureblocked\" (cp \"%d\") (cpname \"%s\") (position \"%d %d %d\")\n",
  462. pBlocker->GetPlayerName(),
  463. pBlocker->GetUserID(),
  464. pBlocker->GetNetworkIDString(),
  465. pBlocker->GetTeam()->GetName(),
  466. event->GetInt( "cp" ),
  467. event->GetString( "cpname" ),
  468. (int)pBlocker->GetAbsOrigin().x,
  469. (int)pBlocker->GetAbsOrigin().y,
  470. (int)pBlocker->GetAbsOrigin().z );
  471. }
  472. else if ( FStrEq( eventName, "teamplay_point_captured" ) )
  473. {
  474. CTeam *pTeam = GetGlobalTeam( event->GetInt( "team" ) );
  475. if ( !pTeam )
  476. return true;
  477. const char *szCappers = event->GetString( "cappers" );
  478. int iNumCappers = Q_strlen( szCappers );
  479. if ( iNumCappers <= 0 )
  480. return true;
  481. char buf[1024];
  482. Q_snprintf( buf, sizeof(buf), "Team \"%s\" triggered \"pointcaptured\" (cp \"%d\") (cpname \"%s\") (numcappers \"%d\") ",
  483. pTeam->GetName(),
  484. event->GetInt( "cp" ),
  485. event->GetString( "cpname" ),
  486. iNumCappers );
  487. for ( int i=0;i<iNumCappers;i++ )
  488. {
  489. int iPlayerIndex = szCappers[i];
  490. Assert( iPlayerIndex != '\0' && iPlayerIndex > 0 && iPlayerIndex <= MAX_PLAYERS );
  491. CBasePlayer *pPlayer = UTIL_PlayerByIndex( iPlayerIndex );
  492. if ( !pPlayer )
  493. continue;
  494. char playerBuf[256];
  495. Q_snprintf( playerBuf, sizeof(playerBuf), "(player%d \"%s<%i><%s><%s>\") (position%d \"%d %d %d\") ",
  496. i + 1,
  497. pPlayer->GetPlayerName(),
  498. pPlayer->GetUserID(),
  499. pPlayer->GetNetworkIDString(),
  500. pPlayer->GetTeam()->GetName(),
  501. i + 1,
  502. (int)pPlayer->GetAbsOrigin().x,
  503. (int)pPlayer->GetAbsOrigin().y,
  504. (int)pPlayer->GetAbsOrigin().z );
  505. Q_strncat( buf, playerBuf, sizeof(buf), COPY_ALL_CHARACTERS );
  506. }
  507. UTIL_LogPrintf( "%s\n", buf );
  508. }
  509. else if ( FStrEq( eventName, "teamplay_round_stalemate" ) )
  510. {
  511. int iReason = event->GetInt( "reason" );
  512. if ( iReason == STALEMATE_TIMER )
  513. {
  514. UTIL_LogPrintf( "World triggered \"Round_SuddenDeath\" reason \"round timelimit reached\"\n" );
  515. }
  516. else if ( iReason == STALEMATE_SERVER_TIMELIMIT )
  517. {
  518. UTIL_LogPrintf( "World triggered \"Round_SuddenDeath\" reason \"server timelimit reached\"\n" );
  519. }
  520. else
  521. {
  522. UTIL_LogPrintf( "World triggered \"Round_SuddenDeath\"\n" );
  523. }
  524. return true;
  525. }
  526. else if ( FStrEq( eventName, "teamplay_round_win" ) )
  527. {
  528. bool bShowScores = true;
  529. int iTeam = event->GetInt( "team" );
  530. bool bFullRound = event->GetBool( "full_round" );
  531. if ( iTeam == TEAM_UNASSIGNED )
  532. {
  533. UTIL_LogPrintf( "World triggered \"Round_Stalemate\"\n" );
  534. }
  535. else
  536. {
  537. const char *pszWinner = "Red";
  538. if ( iTeam == TF_TEAM_BLUE )
  539. {
  540. pszWinner = "Blue";
  541. }
  542. CTeamControlPointMaster *pMaster = g_hControlPointMasters.Count() ? g_hControlPointMasters[0] : NULL;
  543. if ( pMaster && pMaster->PlayingMiniRounds() )
  544. {
  545. UTIL_LogPrintf( "World triggered \"Mini_Round_Win\" (winner \"%s\") (round \"%s\")\n", pszWinner, pMaster->GetCurrentRound()->GetEntityName().ToCStr() );
  546. UTIL_LogPrintf( "World triggered \"Mini_Round_Length\" (seconds \"%0.2f\")\n", event->GetFloat( "round_time" ) );
  547. bShowScores = false;
  548. }
  549. if ( bFullRound )
  550. {
  551. UTIL_LogPrintf( "World triggered \"Round_Win\" (winner \"%s\")\n", pszWinner );
  552. if ( !pMaster || !pMaster->PlayingMiniRounds() )
  553. {
  554. UTIL_LogPrintf( "World triggered \"Round_Length\" (seconds \"%0.2f\")\n", event->GetFloat( "round_time" ) );
  555. }
  556. bShowScores = true;
  557. }
  558. }
  559. if ( bShowScores )
  560. {
  561. UTIL_LogPrintf( "Team \"Red\" current score \"%d\" with \"%d\" players\n", GetGlobalTeam( TF_TEAM_RED )->GetScore(), GetGlobalTeam( TF_TEAM_RED )->GetNumPlayers() );
  562. UTIL_LogPrintf( "Team \"Blue\" current score \"%d\" with \"%d\" players\n", GetGlobalTeam( TF_TEAM_BLUE )->GetScore(), GetGlobalTeam( TF_TEAM_BLUE )->GetNumPlayers() );
  563. }
  564. }
  565. else if ( FStrEq( eventName, "medic_death" ) )
  566. {
  567. const int userid = event->GetInt( "userid" );
  568. CBasePlayer *pPlayer = UTIL_PlayerByUserId( userid );
  569. if ( !pPlayer )
  570. {
  571. return false;
  572. }
  573. const int attackerid = event->GetInt( "attacker" );
  574. CBasePlayer *pAttacker = UTIL_PlayerByUserId( attackerid );
  575. bool bCharged = event->GetBool( "charged" );
  576. int iHealing = event->GetInt( "healing" );
  577. if ( !pAttacker )
  578. {
  579. pAttacker = pPlayer;
  580. }
  581. UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"medic_death\" against \"%s<%i><%s><%s>\" (healing \"%d\") (ubercharge \"%s\")\n",
  582. pAttacker->GetPlayerName(),
  583. attackerid,
  584. pAttacker->GetNetworkIDString(),
  585. pAttacker->GetTeam()->GetName(),
  586. pPlayer->GetPlayerName(),
  587. userid,
  588. pPlayer->GetNetworkIDString(),
  589. pPlayer->GetTeam()->GetName(),
  590. iHealing,
  591. bCharged ? "1" : "0" );
  592. return true;
  593. }
  594. return false;
  595. }
  596. };
  597. CTFEventLog g_TFEventLog;
  598. //-----------------------------------------------------------------------------
  599. // Singleton access
  600. //-----------------------------------------------------------------------------
  601. IGameSystem* GameLogSystem()
  602. {
  603. return &g_TFEventLog;
  604. }