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.

573 lines
17 KiB

  1. //========= Copyright � 1996-2005, 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 "cs_gamerules.h"
  12. #include "keyvalues.h"
  13. #define LOG_DETAIL_ENEMY_ATTACKS 0x01
  14. #define LOG_DETAIL_TEAMMATE_ATTACKS 0x02
  15. ConVar mp_logdetail( "mp_logdetail", "0", FCVAR_RELEASE, "Logs attacks. Values are: 0=off, 1=enemy, 2=teammate, 3=both)", true, 0.0f, true, 3.0f );
  16. class CCSEventLog : public CEventLog
  17. {
  18. private:
  19. typedef CEventLog BaseClass;
  20. public:
  21. bool PrintEvent( IGameEvent *event ) // override virtual function
  22. {
  23. if ( !PrintCStrikeEvent( event ) ) // allow CS to override logging
  24. {
  25. return BaseClass::PrintEvent( event );
  26. }
  27. else
  28. {
  29. return true;
  30. }
  31. }
  32. bool Init()
  33. {
  34. BaseClass::Init();
  35. // listen to CS events
  36. ListenForGameEvent( "round_end" );
  37. ListenForGameEvent( "round_start" );
  38. ListenForGameEvent( "bomb_pickup" );
  39. ListenForGameEvent( "bomb_begindefuse" );
  40. ListenForGameEvent( "bomb_dropped" );
  41. ListenForGameEvent( "bomb_defused" );
  42. ListenForGameEvent( "bomb_planted" );
  43. ListenForGameEvent( "bomb_beginplant" );
  44. ListenForGameEvent( "hostage_rescued" );
  45. ListenForGameEvent( "hostage_killed" );
  46. ListenForGameEvent( "hostage_follows" );
  47. ListenForGameEvent( "player_hurt" );
  48. ListenForGameEvent( "player_death" );
  49. ListenForGameEvent( "other_death" );
  50. ListenForGameEvent( "hegrenade_detonate" );
  51. ListenForGameEvent( "flashbang_detonate" );
  52. ListenForGameEvent( "player_blind" );
  53. ListenForGameEvent( "smokegrenade_detonate" );
  54. ListenForGameEvent( "molotov_detonate" );
  55. ListenForGameEvent( "decoy_detonate" );
  56. ListenForGameEvent( "item_purchase" );
  57. return true;
  58. }
  59. protected:
  60. bool PrintCStrikeEvent( IGameEvent *event ) // print Mod specific logs
  61. {
  62. const char *eventName = event->GetName();
  63. // messages that don't have a user associated to them
  64. if ( StringHasPrefixCaseSensitive( eventName, "round_end" ) )
  65. {
  66. const int winner = event->GetInt( "winner" );
  67. const int reason = event->GetInt( "reason" );
  68. const char *msg = event->GetString( "message" );
  69. msg++; // remove the '#' char
  70. switch( reason )
  71. {
  72. case Game_Commencing:
  73. UTIL_LogPrintf( "World triggered \"Game_Commencing\"\n" );
  74. return true;
  75. break;
  76. }
  77. CTeam *ct = GetGlobalTeam( TEAM_CT );
  78. CTeam *ter = GetGlobalTeam( TEAM_TERRORIST );
  79. Assert( ct && ter );
  80. switch ( winner )
  81. {
  82. case WINNER_CT:
  83. UTIL_LogPrintf( "Team \"%s\" triggered \"%s\" (CT \"%i\") (T \"%i\")\n", ct->GetName(), msg, ct->GetScore(), ter->GetScore() );
  84. break;
  85. case WINNER_TER:
  86. UTIL_LogPrintf( "Team \"%s\" triggered \"%s\" (CT \"%i\") (T \"%i\")\n", ter->GetName(), msg, ct->GetScore(), ter->GetScore() );
  87. break;
  88. case WINNER_DRAW:
  89. default:
  90. UTIL_LogPrintf( "World triggered \"%s\" (CT \"%i\") (T \"%i\")\n", msg, ct->GetScore(), ter->GetScore() );
  91. break;
  92. }
  93. UTIL_LogPrintf( "Team \"CT\" scored \"%i\" with \"%i\" players\n", ct->GetScore(), ct->GetNumPlayers() );
  94. UTIL_LogPrintf( "Team \"TERRORIST\" scored \"%i\" with \"%i\" players\n", ter->GetScore(), ter->GetNumPlayers() );
  95. UTIL_LogPrintf("World triggered \"Round_End\"\n");
  96. return true;
  97. }
  98. else if ( StringHasPrefixCaseSensitive( eventName, "other_death" ) )
  99. {
  100. const int attackerid = event->GetInt( "attacker" );
  101. const char *weapon = event->GetString( "weapon" );
  102. const bool headShot = ( event->GetInt( "headshot" ) == 1 );
  103. const bool penetrated = ( event->GetInt( "penetrated" ) > 0 );
  104. const bool domination = false;
  105. const bool revenge = false;
  106. CBasePlayer *pAttacker = UTIL_PlayerByUserId( attackerid );
  107. const int otherid = event->GetInt( "otherid" );
  108. CBaseEntity *pOther = UTIL_EntityByIndex( otherid );
  109. if ( pAttacker && otherid && pOther )
  110. {
  111. UTIL_LogPrintf( "\"%s<%i><%s><%s>\" [%.0f %.0f %.0f] killed other \"%s<%i>\" [%.0f %.0f %.0f] with \"%s\"%s%s%s%s%s%s%s%s%s\n",
  112. //attacker
  113. pAttacker->GetPlayerName(),
  114. attackerid,
  115. pAttacker->GetNetworkIDString(),
  116. pAttacker->GetTeam()->GetName(),
  117. pAttacker->GetAbsOrigin().x,
  118. pAttacker->GetAbsOrigin().y,
  119. pAttacker->GetAbsOrigin().z,
  120. //target
  121. event->GetString( "othertype" ),
  122. event->GetInt( "otherid" ),
  123. pOther->GetAbsOrigin().x,
  124. pOther->GetAbsOrigin().y,
  125. pOther->GetAbsOrigin().z,
  126. //weapon
  127. weapon,
  128. ( domination || revenge || headShot || penetrated ) ? " (" : "",
  129. domination ? "domination" : "",
  130. ( revenge && ( domination ) ) ? " " : "",
  131. revenge ? "revenge" : "",
  132. ( headShot && ( domination || revenge ) ) ? " " : "",
  133. headShot ? "headshot" : "",
  134. ( penetrated && ( domination || revenge || headShot ) ) ? " " : "",
  135. penetrated ? "penetrated" : "",
  136. ( domination || revenge || headShot || penetrated ) ? ")" : ""
  137. );
  138. }
  139. else if ( pAttacker )
  140. {
  141. UTIL_LogPrintf( "\"%s<%i><%s><%s>\" [%.0f %.0f %.0f] killed other \"%s\" with \"%s\"%s%s%s%s%s%s%s%s%s\n",
  142. //attacker
  143. pAttacker->GetPlayerName(),
  144. attackerid,
  145. pAttacker->GetNetworkIDString(),
  146. pAttacker->GetTeam()->GetName(),
  147. pAttacker->GetAbsOrigin().x,
  148. pAttacker->GetAbsOrigin().y,
  149. pAttacker->GetAbsOrigin().z,
  150. //target
  151. event->GetString( "othertype" ),
  152. //weapon
  153. weapon,
  154. ( domination || revenge || headShot || penetrated ) ? " (" : "",
  155. domination ? "domination" : "",
  156. ( revenge && ( domination ) ) ? " " : "",
  157. revenge ? "revenge" : "",
  158. ( headShot && ( domination || revenge ) ) ? " " : "",
  159. headShot ? "headshot" : "",
  160. ( penetrated && ( domination || revenge || headShot ) ) ? " " : "",
  161. penetrated ? "penetrated" : "",
  162. ( domination || revenge || headShot || penetrated ) ? ")" : ""
  163. );
  164. }
  165. return true;
  166. }
  167. else if ( StringHasPrefixCaseSensitive( eventName, "server_" ) )
  168. {
  169. return false; // ignore server_ messages
  170. }
  171. const int userid = event->GetInt( "userid" );
  172. CBasePlayer *pPlayer = UTIL_PlayerByUserId( userid );
  173. if ( !pPlayer )
  174. {
  175. return false;
  176. }
  177. if ( FStrEq( eventName, "player_hurt" ) )
  178. {
  179. const int attackerid = event->GetInt("attacker" );
  180. const char *weapon = event->GetString( "weapon" );
  181. CBasePlayer *pAttacker = UTIL_PlayerByUserId( attackerid );
  182. if ( !pAttacker )
  183. {
  184. return false;
  185. }
  186. bool isTeamAttack = ( (pPlayer->GetTeamNumber() == pAttacker->GetTeamNumber() ) && (pPlayer != pAttacker) );
  187. int detail = mp_logdetail.GetInt();
  188. if ( ( isTeamAttack && ( detail & LOG_DETAIL_TEAMMATE_ATTACKS ) ) ||
  189. ( !isTeamAttack && ( detail & LOG_DETAIL_ENEMY_ATTACKS ) ) )
  190. {
  191. int hitgroup = event->GetInt( "hitgroup" );
  192. const char *hitgroupStr = "GENERIC";
  193. switch ( hitgroup )
  194. {
  195. case HITGROUP_GENERIC:
  196. hitgroupStr = "generic";
  197. break;
  198. case HITGROUP_HEAD:
  199. hitgroupStr = "head";
  200. break;
  201. case HITGROUP_CHEST:
  202. hitgroupStr = "chest";
  203. break;
  204. case HITGROUP_STOMACH:
  205. hitgroupStr = "stomach";
  206. break;
  207. case HITGROUP_LEFTARM:
  208. hitgroupStr = "left arm";
  209. break;
  210. case HITGROUP_RIGHTARM:
  211. hitgroupStr = "right arm";
  212. break;
  213. case HITGROUP_LEFTLEG:
  214. hitgroupStr = "left leg";
  215. break;
  216. case HITGROUP_RIGHTLEG:
  217. hitgroupStr = "right leg";
  218. break;
  219. }
  220. UTIL_LogPrintf( "\"%s<%i><%s><%s>\" [%.0f %.0f %.0f] attacked \"%s<%i><%s><%s>\" [%.0f %.0f %.0f] with \"%s\" (damage \"%d\") (damage_armor \"%d\") (health \"%d\") (armor \"%d\") (hitgroup \"%s\")\n",
  221. pAttacker->GetPlayerName(),
  222. attackerid,
  223. pAttacker->GetNetworkIDString(),
  224. pAttacker->GetTeam()->GetName(),
  225. pAttacker->GetAbsOrigin().x,
  226. pAttacker->GetAbsOrigin().y,
  227. pAttacker->GetAbsOrigin().z,
  228. pPlayer->GetPlayerName(),
  229. userid,
  230. pPlayer->GetNetworkIDString(),
  231. pPlayer->GetTeam()->GetName(),
  232. pPlayer->GetAbsOrigin().x,
  233. pPlayer->GetAbsOrigin().y,
  234. pPlayer->GetAbsOrigin().z,
  235. weapon,
  236. event->GetInt( "dmg_health" ),
  237. event->GetInt( "dmg_armor" ),
  238. event->GetInt( "health" ),
  239. event->GetInt( "armor" ),
  240. hitgroupStr );
  241. }
  242. return true;
  243. }
  244. else if ( StringHasPrefixCaseSensitive( eventName, "player_death" ) )
  245. {
  246. const int attackerid = event->GetInt("attacker" );
  247. const char *weapon = event->GetString( "weapon" );
  248. const bool headShot = (event->GetInt( "headshot" ) == 1);
  249. const bool penetrated = (event->GetInt( "penetrated" ) > 0);
  250. const bool domination = (event->GetInt( "dominated" ) > 0);
  251. const bool revenge = (event->GetInt( "revenge" ) > 0);
  252. CBasePlayer *pAttacker = UTIL_PlayerByUserId( attackerid );
  253. const int assisterid = event->GetInt( "assister" );
  254. CBasePlayer *pAssister = UTIL_PlayerByUserId( assisterid );
  255. if ( pPlayer == pAttacker )
  256. {
  257. UTIL_LogPrintf( "\"%s<%i><%s><%s>\" [%.0f %.0f %.0f] committed suicide with \"%s\"\n",
  258. pPlayer->GetPlayerName(),
  259. userid,
  260. pPlayer->GetNetworkIDString(),
  261. pPlayer->GetTeam()->GetName(),
  262. pPlayer->GetAbsOrigin().x,
  263. pPlayer->GetAbsOrigin().y,
  264. pPlayer->GetAbsOrigin().z,
  265. weapon
  266. );
  267. }
  268. else if ( pAttacker )
  269. {
  270. UTIL_LogPrintf( "\"%s<%i><%s><%s>\" [%.0f %.0f %.0f] killed \"%s<%i><%s><%s>\" [%.0f %.0f %.0f] with \"%s\"%s%s%s%s%s%s%s%s%s\n",
  271. //attacker
  272. pAttacker->GetPlayerName(),
  273. attackerid,
  274. pAttacker->GetNetworkIDString(),
  275. pAttacker->GetTeam()->GetName(),
  276. pAttacker->GetAbsOrigin().x,
  277. pAttacker->GetAbsOrigin().y,
  278. pAttacker->GetAbsOrigin().z,
  279. //target
  280. pPlayer->GetPlayerName(),
  281. userid,
  282. pPlayer->GetNetworkIDString(),
  283. pPlayer->GetTeam()->GetName(),
  284. pPlayer->GetAbsOrigin().x,
  285. pPlayer->GetAbsOrigin().y,
  286. pPlayer->GetAbsOrigin().z,
  287. weapon,
  288. ( domination || revenge || headShot || penetrated ) ? " (" : "",
  289. domination ? "domination":"",
  290. ( revenge && ( domination ) ) ? " " : "",
  291. revenge ? "revenge" : "",
  292. ( headShot && ( domination || revenge ) ) ? " " : "",
  293. headShot ? "headshot":"",
  294. ( penetrated && ( domination || revenge || headShot ) ) ? " " : "",
  295. penetrated ? "penetrated" : "",
  296. ( domination || revenge || headShot || penetrated ) ? ")" : ""
  297. );
  298. if ( pAssister )
  299. {
  300. UTIL_LogPrintf( "\"%s<%i><%s><%s>\" assisted killing \"%s<%i><%s><%s>\"\n",
  301. //attacker
  302. pAssister->GetPlayerName(),
  303. assisterid,
  304. pAssister->GetNetworkIDString(),
  305. pAssister->GetTeam()->GetName(),
  306. // target
  307. pPlayer->GetPlayerName(),
  308. userid,
  309. pPlayer->GetNetworkIDString(),
  310. pPlayer->GetTeam()->GetName()
  311. );
  312. }
  313. }
  314. else
  315. {
  316. // killed by the world
  317. UTIL_LogPrintf( "\"%s<%i><%s><%s>\" [%.0f %.0f %.0f] committed suicide with \"world\"\n",
  318. pPlayer->GetPlayerName(),
  319. userid,
  320. pPlayer->GetNetworkIDString(),
  321. pPlayer->GetTeam()->GetName(),
  322. pPlayer->GetAbsOrigin().x,
  323. pPlayer->GetAbsOrigin().y,
  324. pPlayer->GetAbsOrigin().z
  325. );
  326. }
  327. return true;
  328. }
  329. else if ( StringHasPrefixCaseSensitive( eventName, "hegrenade_detonate" ) )
  330. {
  331. UTIL_LogPrintf( "\"%s<%i><%s><%s>\" threw hegrenade [%.0f %.0f %.0f]\n",
  332. pPlayer->GetPlayerName(),
  333. userid,
  334. pPlayer->GetNetworkIDString(),
  335. pPlayer->GetTeam()->GetName(),
  336. event->GetFloat( "x" ),
  337. event->GetFloat( "y" ),
  338. event->GetFloat( "z" )
  339. );
  340. return true;
  341. }
  342. else if ( StringHasPrefixCaseSensitive( eventName, "flashbang_detonate" ) )
  343. {
  344. UTIL_LogPrintf( "\"%s<%i><%s><%s>\" threw flashbang [%.0f %.0f %.0f] flashbang entindex %d)\n",
  345. pPlayer->GetPlayerName(),
  346. userid,
  347. pPlayer->GetNetworkIDString(),
  348. pPlayer->GetTeam()->GetName(),
  349. event->GetFloat( "x" ),
  350. event->GetFloat( "y" ),
  351. event->GetFloat( "z" ),
  352. event->GetInt( "entityid")
  353. );
  354. return true;
  355. }
  356. else if ( StringHasPrefixCaseSensitive( eventName, "player_blind" ) )
  357. {
  358. const int attackerid = event->GetInt( "attacker" );
  359. CBasePlayer *pAttacker = UTIL_PlayerByUserId( attackerid );
  360. float flDuration = event->GetFloat( "blind_duration" );
  361. int entnum = event->GetInt( "entityid" );
  362. UTIL_LogPrintf( "\"%s<%i><%s><%s>\" blinded for %.2f by \"%s<%i><%s><%s>\" from flashbang entindex %d \n",
  363. pPlayer->GetPlayerName(),
  364. userid,
  365. pPlayer->GetNetworkIDString(),
  366. pPlayer->GetTeam()->GetName(),
  367. flDuration,
  368. pAttacker ? pAttacker->GetPlayerName() : "unknown",
  369. attackerid,
  370. pAttacker ? pAttacker->GetNetworkIDString() : "unknown",
  371. pAttacker ? pAttacker->GetTeam()->GetName() : "unknown",
  372. entnum
  373. );
  374. return true;
  375. }
  376. else if ( StringHasPrefixCaseSensitive( eventName, "smokegrenade_detonate" ) )
  377. {
  378. UTIL_LogPrintf( "\"%s<%i><%s><%s>\" threw smokegrenade [%.0f %.0f %.0f]\n",
  379. pPlayer->GetPlayerName(),
  380. userid,
  381. pPlayer->GetNetworkIDString(),
  382. pPlayer->GetTeam()->GetName(),
  383. event->GetFloat( "x" ),
  384. event->GetFloat( "y" ),
  385. event->GetFloat( "z" )
  386. );
  387. return true;
  388. }
  389. else if ( StringHasPrefixCaseSensitive( eventName, "molotov_detonate" ) )
  390. {
  391. UTIL_LogPrintf( "\"%s<%i><%s><%s>\" threw molotov [%.0f %.0f %.0f]\n",
  392. pPlayer->GetPlayerName(),
  393. userid,
  394. pPlayer->GetNetworkIDString(),
  395. pPlayer->GetTeam()->GetName(),
  396. event->GetFloat( "x" ),
  397. event->GetFloat( "y" ),
  398. event->GetFloat( "z" )
  399. );
  400. return true;
  401. }
  402. else if ( StringHasPrefix( eventName, "decoy_detonate" ) )
  403. {
  404. UTIL_LogPrintf( "\"%s<%i><%s><%s>\" threw decoy [%.0f %.0f %.0f]\n",
  405. pPlayer->GetPlayerName(),
  406. userid,
  407. pPlayer->GetNetworkIDString(),
  408. pPlayer->GetTeam()->GetName(),
  409. event->GetFloat( "x" ),
  410. event->GetFloat( "y" ),
  411. event->GetFloat( "z" )
  412. );
  413. return true;
  414. }
  415. else if ( StringHasPrefixCaseSensitive( eventName, "round_start" ) )
  416. {
  417. UTIL_LogPrintf("World triggered \"Round_Start\"\n");
  418. return true;
  419. }
  420. else if ( StringHasPrefixCaseSensitive( eventName, "player_team" ) )
  421. {
  422. UTIL_LogPrintf( "\"%s<%i><%s>\" switched from team <%s> to <%s>\n",
  423. pPlayer->GetPlayerName(),
  424. userid,
  425. pPlayer->GetNetworkIDString(),
  426. GetGlobalTeam( event->GetInt("oldteam") )->GetName(),
  427. GetGlobalTeam( event->GetInt("team") )->GetName()
  428. );
  429. return true;
  430. }
  431. else if ( StringHasPrefixCaseSensitive( eventName, "hostage_follows" ) )
  432. {
  433. UTIL_LogPrintf( "\"%s<%i><%s><CT>\" triggered \"Touched_A_Hostage\"\n",
  434. pPlayer->GetPlayerName(),
  435. userid,
  436. pPlayer->GetNetworkIDString()
  437. );
  438. return true;
  439. }
  440. else if ( StringHasPrefixCaseSensitive( eventName, "hostage_killed" ) )
  441. {
  442. UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"Killed_A_Hostage\"\n",
  443. pPlayer->GetPlayerName(),
  444. userid,
  445. pPlayer->GetNetworkIDString(),
  446. pPlayer->GetTeam()->GetName()
  447. );
  448. return true;
  449. }
  450. else if ( StringHasPrefixCaseSensitive( eventName, "hostage_rescued" ) )
  451. {
  452. UTIL_LogPrintf("\"%s<%i><%s><CT>\" triggered \"Rescued_A_Hostage\"\n",
  453. pPlayer->GetPlayerName(),
  454. userid,
  455. pPlayer->GetNetworkIDString()
  456. );
  457. return true;
  458. }
  459. else if ( StringHasPrefixCaseSensitive( eventName, "bomb_planted" ) )
  460. {
  461. UTIL_LogPrintf("\"%s<%i><%s><TERRORIST>\" triggered \"Planted_The_Bomb\"\n",
  462. pPlayer->GetPlayerName(),
  463. userid,
  464. pPlayer->GetNetworkIDString()
  465. );
  466. return true;
  467. }
  468. else if ( StringHasPrefix( eventName, "bomb_planted" ) )
  469. {
  470. UTIL_LogPrintf("\"%s<%i><%s><TERRORIST>\" triggered \"Bomb_Begin_Plant\"\n",
  471. pPlayer->GetPlayerName(),
  472. userid,
  473. pPlayer->GetNetworkIDString()
  474. );
  475. return true;
  476. }
  477. else if ( StringHasPrefixCaseSensitive( eventName, "bomb_defused" ) )
  478. {
  479. UTIL_LogPrintf("\"%s<%i><%s><CT>\" triggered \"Defused_The_Bomb\"\n",
  480. pPlayer->GetPlayerName(),
  481. userid,
  482. pPlayer->GetNetworkIDString()
  483. );
  484. return true;
  485. }
  486. else if ( StringHasPrefixCaseSensitive( eventName, "bomb_dropped" ) )
  487. {
  488. UTIL_LogPrintf("\"%s<%i><%s><TERRORIST>\" triggered \"Dropped_The_Bomb\"\n",
  489. pPlayer->GetPlayerName(),
  490. userid,
  491. pPlayer->GetNetworkIDString()
  492. );
  493. return true;
  494. }
  495. else if ( StringHasPrefixCaseSensitive( eventName, "bomb_begindefuse" ) )
  496. {
  497. const bool haskit = (event->GetInt( "haskit" ) == 1);
  498. UTIL_LogPrintf("\"%s<%i><%s><CT>\" triggered \"%s\"\n",
  499. pPlayer->GetPlayerName(),
  500. userid,
  501. pPlayer->GetNetworkIDString(),
  502. haskit ? "Begin_Bomb_Defuse_With_Kit" : "Begin_Bomb_Defuse_Without_Kit"
  503. );
  504. return true;
  505. }
  506. else if ( StringHasPrefixCaseSensitive( eventName, "bomb_pickup" ) )
  507. {
  508. UTIL_LogPrintf("\"%s<%i><%s><TERRORIST>\" triggered \"Got_The_Bomb\"\n",
  509. pPlayer->GetPlayerName(),
  510. userid,
  511. pPlayer->GetNetworkIDString()
  512. );
  513. return true;
  514. }
  515. else if ( StringHasPrefixCaseSensitive( eventName, "item_purchase" ) )
  516. {
  517. const char *weapon = event->GetString( "weapon" );
  518. UTIL_LogPrintf( "\"%s<%i><%s><%s>\" purchased \"%s\"\n",
  519. pPlayer->GetPlayerName(),
  520. userid,
  521. pPlayer->GetNetworkIDString(),
  522. pPlayer->GetTeam()->GetName(),
  523. weapon
  524. );
  525. return true;
  526. }
  527. // unused events:
  528. //hostage_hurt
  529. //bomb_exploded
  530. return false;
  531. }
  532. };
  533. CCSEventLog g_CSEventLog;
  534. //-----------------------------------------------------------------------------
  535. // Singleton access
  536. //-----------------------------------------------------------------------------
  537. CEventLog* GameLogSystem()
  538. {
  539. return &g_CSEventLog;
  540. }