Modified source engine (2017) developed by valve and leaked in 2020. Not for commercial purporses
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.

678 lines
21 KiB

5 years ago
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#include "cbase.h"
#include "../EventLog.h"
#include "team.h"
#include "teamplayroundbased_gamerules.h"
#include "tf_gamerules.h"
#include "team_control_point_master.h"
#include "team_control_point_round.h"
#include "tf_team.h"
#include "KeyValues.h"
extern ConVar tf_flag_caps_per_round;
class CTFEventLog : public CEventLog
{
private:
typedef CEventLog BaseClass;
public:
bool PrintEvent( IGameEvent *event ) // override virtual function
{
if ( !PrintTFEvent( event ) ) // allow TF to override logging
{
return BaseClass::PrintEvent( event );
}
else
{
return true;
}
}
bool Init()
{
BaseClass::Init();
ListenForGameEvent( "player_death" );
ListenForGameEvent( "medic_death" );
ListenForGameEvent( "player_hurt" );
ListenForGameEvent( "player_changeclass" );
ListenForGameEvent( "tf_game_over" );
ListenForGameEvent( "player_chargedeployed" );
ListenForGameEvent( "teamplay_flag_event" );
ListenForGameEvent( "teamplay_capture_blocked" );
ListenForGameEvent( "teamplay_point_captured" );
ListenForGameEvent( "teamplay_round_stalemate" );
ListenForGameEvent( "teamplay_round_win" );
ListenForGameEvent( "teamplay_game_over" );
ListenForGameEvent( "player_builtobject" );
ListenForGameEvent( "player_carryobject" );
ListenForGameEvent( "player_dropobject" );
ListenForGameEvent( "object_removed" );
ListenForGameEvent( "object_detonated" );
ListenForGameEvent( "object_destroyed" );
return true;
}
protected:
bool PrintTFEvent( IGameEvent *event ) // print Mod specific logs
{
const char *eventName = event->GetName();
if ( !Q_strncmp( eventName, "server_", strlen("server_")) )
{
return false; // ignore server_ messages
}
if ( !Q_strncmp( eventName, "player_death", Q_strlen( "player_death" ) ) )
{
const int userid = event->GetInt( "userid" );
CBasePlayer *pPlayer = UTIL_PlayerByUserId( userid );
if ( !pPlayer )
{
return false;
}
const int attackerid = event->GetInt( "attacker" );
const char *weapon = event->GetString( "weapon_logclassname" );
int iCustomDamage = event->GetInt( "customkill" );
CBasePlayer *pAttacker = UTIL_PlayerByUserId( attackerid );
if ( pPlayer == pAttacker )
{
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" committed suicide with \"%s\" (attacker_position \"%d %d %d\")\n",
pPlayer->GetPlayerName(),
userid,
pPlayer->GetNetworkIDString(),
pPlayer->GetTeam()->GetName(),
weapon,
(int)pPlayer->GetAbsOrigin().x,
(int)pPlayer->GetAbsOrigin().y,
(int)pPlayer->GetAbsOrigin().z );
}
else if ( pAttacker )
{
const char *pszCustom = NULL;
switch( iCustomDamage )
{
case TF_DMG_CUSTOM_HEADSHOT_DECAPITATION:
case TF_DMG_CUSTOM_HEADSHOT:
pszCustom = "headshot";
break;
case TF_DMG_CUSTOM_BACKSTAB:
pszCustom = "backstab";
break;
default:
break;
}
// is the spy feigning death?
if ( event->GetInt( "death_flags" ) & TF_DEATH_FEIGN_DEATH )
{
pszCustom = "feign_death";
}
if ( pszCustom )
{
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",
pAttacker->GetPlayerName(),
attackerid,
pAttacker->GetNetworkIDString(),
pAttacker->GetTeam()->GetName(),
pPlayer->GetPlayerName(),
userid,
pPlayer->GetNetworkIDString(),
pPlayer->GetTeam()->GetName(),
weapon,
pszCustom,
(int)pAttacker->GetAbsOrigin().x,
(int)pAttacker->GetAbsOrigin().y,
(int)pAttacker->GetAbsOrigin().z,
(int)pPlayer->GetAbsOrigin().x,
(int)pPlayer->GetAbsOrigin().y,
(int)pPlayer->GetAbsOrigin().z );
}
else
{
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" killed \"%s<%i><%s><%s>\" with \"%s\" (attacker_position \"%d %d %d\") (victim_position \"%d %d %d\")\n",
pAttacker->GetPlayerName(),
attackerid,
pAttacker->GetNetworkIDString(),
pAttacker->GetTeam()->GetName(),
pPlayer->GetPlayerName(),
userid,
pPlayer->GetNetworkIDString(),
pPlayer->GetTeam()->GetName(),
weapon,
(int)pAttacker->GetAbsOrigin().x,
(int)pAttacker->GetAbsOrigin().y,
(int)pAttacker->GetAbsOrigin().z,
(int)pPlayer->GetAbsOrigin().x,
(int)pPlayer->GetAbsOrigin().y,
(int)pPlayer->GetAbsOrigin().z );
}
}
else
{
int iDamageBits = event->GetInt( "damagebits" );
if ( ( iDamageBits & DMG_VEHICLE ) || ( iDamageBits & DMG_NERVEGAS ) )
{
const char *pszCustomKill = "train";
if ( iDamageBits & DMG_NERVEGAS )
{
pszCustomKill = "saw";
}
// killed by the world
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" committed suicide with \"world\" (customkill \"%s\") (attacker_position \"%d %d %d\")\n",
pPlayer->GetPlayerName(),
userid,
pPlayer->GetNetworkIDString(),
pPlayer->GetTeam()->GetName(),
pszCustomKill,
(int)pPlayer->GetAbsOrigin().x,
(int)pPlayer->GetAbsOrigin().y,
(int)pPlayer->GetAbsOrigin().z );
}
else
{
// killed by the world
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" committed suicide with \"world\" (attacker_position \"%d %d %d\")\n",
pPlayer->GetPlayerName(),
userid,
pPlayer->GetNetworkIDString(),
pPlayer->GetTeam()->GetName(),
(int)pPlayer->GetAbsOrigin().x,
(int)pPlayer->GetAbsOrigin().y,
(int)pPlayer->GetAbsOrigin().z );
}
}
// Assist kill
int assistid = event->GetInt( "assister" );
CBasePlayer *pAssister = UTIL_PlayerByUserId( assistid );
if ( pAssister )
{
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",
pAssister->GetPlayerName(),
assistid,
pAssister->GetNetworkIDString(),
pAssister->GetTeam()->GetName(),
pPlayer->GetPlayerName(),
userid,
pPlayer->GetNetworkIDString(),
pPlayer->GetTeam()->GetName(),
(int)pAssister->GetAbsOrigin().x,
(int)pAssister->GetAbsOrigin().y,
(int)pAssister->GetAbsOrigin().z,
pAttacker ? (int)pAttacker->GetAbsOrigin().x : 0,
pAttacker ? (int)pAttacker->GetAbsOrigin().y : 0,
pAttacker ? (int)pAttacker->GetAbsOrigin().z : 0,
(int)pPlayer->GetAbsOrigin().x,
(int)pPlayer->GetAbsOrigin().y,
(int)pPlayer->GetAbsOrigin().z );
}
// Domination and Revenge
// pAttacker //int attackerid = engine->GetPlayerForUserID( event->GetInt( "attacker" ) );
// pPlayer //int userid = engine->GetPlayerForUserID( event->GetInt( "userid" ) );
// pAssister // assistid
if ( event->GetInt( "death_flags" ) & TF_DEATH_DOMINATION && pAttacker )
{
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"domination\" against \"%s<%i><%s><%s>\"\n",
pAttacker->GetPlayerName(),
attackerid,
pAttacker->GetNetworkIDString(),
pAttacker->GetTeam()->GetName(),
pPlayer->GetPlayerName(),
userid,
pPlayer->GetNetworkIDString(),
pPlayer->GetTeam()->GetName()
);
}
if ( event->GetInt( "death_flags" ) & TF_DEATH_ASSISTER_DOMINATION && pAssister )
{
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"domination\" against \"%s<%i><%s><%s>\" (assist \"1\")\n",
pAssister->GetPlayerName(),
assistid,
pAssister->GetNetworkIDString(),
pAssister->GetTeam()->GetName(),
pPlayer->GetPlayerName(),
userid,
pPlayer->GetNetworkIDString(),
pPlayer->GetTeam()->GetName()
);
}
if ( event->GetInt( "death_flags" ) & TF_DEATH_REVENGE && pAttacker )
{
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"revenge\" against \"%s<%i><%s><%s>\"\n",
pAttacker->GetPlayerName(),
attackerid,
pAttacker->GetNetworkIDString(),
pAttacker->GetTeam()->GetName(),
pPlayer->GetPlayerName(),
userid,
pPlayer->GetNetworkIDString(),
pPlayer->GetTeam()->GetName()
);
}
if ( event->GetInt( "death_flags" ) & TF_DEATH_ASSISTER_REVENGE && pAssister )
{
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"revenge\" against \"%s<%i><%s><%s>\" (assist \"1\")\n",
pAssister->GetPlayerName(),
assistid,
pAssister->GetNetworkIDString(),
pAssister->GetTeam()->GetName(),
pPlayer->GetPlayerName(),
userid,
pPlayer->GetNetworkIDString(),
pPlayer->GetTeam()->GetName()
);
}
return true;
}
else if ( FStrEq( eventName, "player_changeclass" ) )
{
const int userid = event->GetInt( "userid" );
CBasePlayer *pPlayer = UTIL_PlayerByUserId( userid );
if ( !pPlayer )
{
return false;
}
int iClass = event->GetInt("class");
if ( pPlayer->GetTeamNumber() < FIRST_GAME_TEAM )
return true;
if ( iClass >= TF_FIRST_NORMAL_CLASS && iClass <= TF_LAST_NORMAL_CLASS )
{
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" changed role to \"%s\"\n",
pPlayer->GetPlayerName(),
userid,
pPlayer->GetNetworkIDString(),
pPlayer->GetTeam()->GetName(),
GetPlayerClassData( iClass )->m_szClassName
);
}
return true;
}
else if ( FStrEq( eventName, "tf_game_over" ) || FStrEq( eventName, "teamplay_game_over" ) )
{
UTIL_LogPrintf( "World triggered \"Game_Over\" reason \"%s\"\n", event->GetString( "reason" ) );
UTIL_LogPrintf( "Team \"Red\" final score \"%d\" with \"%d\" players\n", GetGlobalTeam( TF_TEAM_RED )->GetScore(), GetGlobalTeam( TF_TEAM_RED )->GetNumPlayers() );
UTIL_LogPrintf( "Team \"Blue\" final score \"%d\" with \"%d\" players\n", GetGlobalTeam( TF_TEAM_BLUE )->GetScore(), GetGlobalTeam( TF_TEAM_BLUE )->GetNumPlayers() );
return true;
}
else if ( FStrEq( eventName, "player_chargedeployed" ) )
{
const int userid = event->GetInt( "userid" );
CBasePlayer *pPlayer = UTIL_PlayerByUserId( userid );
if ( !pPlayer )
{
return false;
}
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"chargedeployed\"\n",
pPlayer->GetPlayerName(),
userid,
pPlayer->GetNetworkIDString(),
pPlayer->GetTeam()->GetName()
);
return true;
}
else if ( FStrEq( eventName, "player_builtobject" ) ||
FStrEq( eventName, "player_carryobject" ) ||
FStrEq( eventName, "player_dropobject" ) ||
FStrEq( eventName, "player_removed" ) ||
FStrEq( eventName, "object_detonated" ) )
{
const int userid = event->GetInt( "userid" );
CBasePlayer *pPlayer = UTIL_PlayerByUserId( userid );
if ( pPlayer )
{
// Some events have "object" and some have "objecttype". We can't change them as there are third-party
// scripts that listen for these events.
const int objectid = !event->IsEmpty( "objecttype" ) ? event->GetInt( "objecttype" ) : event->GetInt( "object" );
const CObjectInfo *pInfo = ( objectid >= 0 && objectid < OBJ_LAST ) ? GetObjectInfo( objectid ) : NULL;
if ( pInfo )
{
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"%s\" (object \"%s\") (position \"%d %d %d\")\n",
pPlayer->GetPlayerName(),
userid,
pPlayer->GetNetworkIDString(),
pPlayer->GetTeam()->GetName(),
eventName,
pInfo->m_pObjectName,
(int)pPlayer->GetAbsOrigin().x,
(int)pPlayer->GetAbsOrigin().y,
(int)pPlayer->GetAbsOrigin().z );
}
return true;
}
return false;
}
else if ( FStrEq( eventName, "object_destroyed" ) )
{
int objectid = event->GetInt( "objecttype" );
const CObjectInfo *pInfo = ( objectid >= 0 && objectid < OBJ_LAST ) ? GetObjectInfo( objectid ) : NULL;
if ( !pInfo )
return false;
const int userid = event->GetInt( "userid" );
CBasePlayer *pObjectOwner = UTIL_PlayerByUserId( userid );
if ( !pObjectOwner )
return false;
const int attackerid = event->GetInt( "attacker" );
CBasePlayer *pAttacker = UTIL_PlayerByUserId( attackerid );
if ( !pAttacker )
return false;
const char *weapon = event->GetString( "weapon" );
// log that the person killed an object
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"killedobject\" (object \"%s\") (weapon \"%s\") (objectowner \"%s<%i><%s><%s>\") (attacker_position \"%d %d %d\")\n",
pAttacker->GetPlayerName(),
attackerid,
pAttacker->GetNetworkIDString(),
pAttacker->GetTeam()->GetName(),
pInfo->m_pObjectName,
weapon,
pObjectOwner->GetPlayerName(),
userid,
pObjectOwner->GetNetworkIDString(),
pObjectOwner->GetTeam()->GetName(),
(int)pAttacker->GetAbsOrigin().x,
(int)pAttacker->GetAbsOrigin().y,
(int)pAttacker->GetAbsOrigin().z );
const int assisterid = event->GetInt( "assister" );
CBasePlayer *pAssister = UTIL_PlayerByUserId( assisterid );
if ( pAssister )
{
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",
pAssister->GetPlayerName(),
assisterid,
pAssister->GetNetworkIDString(),
pAssister->GetTeam()->GetName(),
pInfo->m_pObjectName,
pObjectOwner->GetPlayerName(),
userid,
pObjectOwner->GetNetworkIDString(),
pObjectOwner->GetTeam()->GetName(),
(int)pAssister->GetAbsOrigin().x,
(int)pAssister->GetAbsOrigin().y,
(int)pAssister->GetAbsOrigin().z,
(int)pAttacker->GetAbsOrigin().x,
(int)pAttacker->GetAbsOrigin().y,
(int)pAttacker->GetAbsOrigin().z );
}
}
else if ( FStrEq( eventName, "teamplay_flag_event" ) )
{
int playerindex = event->GetInt( "player" );
CBasePlayer *pPlayer = UTIL_PlayerByIndex( playerindex );
if ( !pPlayer )
{
return false;
}
const char *pszEvent = "unknown"; // picked up, dropped, defended, captured
int iEventType = event->GetInt( "eventtype" );
bool bPlainLogEntry = true;
switch ( iEventType )
{
case TF_FLAGEVENT_PICKUP:
pszEvent = "picked up";
break;
case TF_FLAGEVENT_CAPTURE:
pszEvent = "captured";
if ( tf_flag_caps_per_round.GetInt() > 0 )
{
bPlainLogEntry = false;
}
break;
case TF_FLAGEVENT_DEFEND:
pszEvent = "defended";
break;
case TF_FLAGEVENT_DROPPED:
pszEvent = "dropped";
break;
}
if ( bPlainLogEntry )
{
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"flagevent\" (event \"%s\") (position \"%d %d %d\")\n",
pPlayer->GetPlayerName(),
pPlayer->GetUserID(),
pPlayer->GetNetworkIDString(),
pPlayer->GetTeam()->GetName(),
pszEvent,
(int)pPlayer->GetAbsOrigin().x,
(int)pPlayer->GetAbsOrigin().y,
(int)pPlayer->GetAbsOrigin().z );
}
else
{
CTFTeam *pTeam = GetGlobalTFTeam( pPlayer->GetTeamNumber() );
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"flagevent\" (event \"%s\") (team_caps \"%d\") (caps_per_round \"%d\") (position \"%d %d %d\")\n",
pPlayer->GetPlayerName(),
pPlayer->GetUserID(),
pPlayer->GetNetworkIDString(),
pPlayer->GetTeam()->GetName(),
pszEvent,
pTeam->GetFlagCaptures(),
tf_flag_caps_per_round.GetInt(),
(int)pPlayer->GetAbsOrigin().x,
(int)pPlayer->GetAbsOrigin().y,
(int)pPlayer->GetAbsOrigin().z );
}
return true;
}
else if ( FStrEq( eventName, "teamplay_capture_blocked" ) )
{
int blockerindex = event->GetInt( "blocker" );
CBasePlayer *pBlocker = UTIL_PlayerByIndex( blockerindex );
if ( !pBlocker )
{
return true;
}
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"captureblocked\" (cp \"%d\") (cpname \"%s\") (position \"%d %d %d\")\n",
pBlocker->GetPlayerName(),
pBlocker->GetUserID(),
pBlocker->GetNetworkIDString(),
pBlocker->GetTeam()->GetName(),
event->GetInt( "cp" ),
event->GetString( "cpname" ),
(int)pBlocker->GetAbsOrigin().x,
(int)pBlocker->GetAbsOrigin().y,
(int)pBlocker->GetAbsOrigin().z );
}
else if ( FStrEq( eventName, "teamplay_point_captured" ) )
{
CTeam *pTeam = GetGlobalTeam( event->GetInt( "team" ) );
if ( !pTeam )
return true;
const char *szCappers = event->GetString( "cappers" );
int iNumCappers = Q_strlen( szCappers );
if ( iNumCappers <= 0 )
return true;
char buf[1024];
Q_snprintf( buf, sizeof(buf), "Team \"%s\" triggered \"pointcaptured\" (cp \"%d\") (cpname \"%s\") (numcappers \"%d\") ",
pTeam->GetName(),
event->GetInt( "cp" ),
event->GetString( "cpname" ),
iNumCappers );
for ( int i=0;i<iNumCappers;i++ )
{
int iPlayerIndex = szCappers[i];
Assert( iPlayerIndex != '\0' && iPlayerIndex > 0 && iPlayerIndex <= MAX_PLAYERS );
CBasePlayer *pPlayer = UTIL_PlayerByIndex( iPlayerIndex );
if ( !pPlayer )
continue;
char playerBuf[256];
Q_snprintf( playerBuf, sizeof(playerBuf), "(player%d \"%s<%i><%s><%s>\") (position%d \"%d %d %d\") ",
i + 1,
pPlayer->GetPlayerName(),
pPlayer->GetUserID(),
pPlayer->GetNetworkIDString(),
pPlayer->GetTeam()->GetName(),
i + 1,
(int)pPlayer->GetAbsOrigin().x,
(int)pPlayer->GetAbsOrigin().y,
(int)pPlayer->GetAbsOrigin().z );
Q_strncat( buf, playerBuf, sizeof(buf), COPY_ALL_CHARACTERS );
}
UTIL_LogPrintf( "%s\n", buf );
}
else if ( FStrEq( eventName, "teamplay_round_stalemate" ) )
{
int iReason = event->GetInt( "reason" );
if ( iReason == STALEMATE_TIMER )
{
UTIL_LogPrintf( "World triggered \"Round_SuddenDeath\" reason \"round timelimit reached\"\n" );
}
else if ( iReason == STALEMATE_SERVER_TIMELIMIT )
{
UTIL_LogPrintf( "World triggered \"Round_SuddenDeath\" reason \"server timelimit reached\"\n" );
}
else
{
UTIL_LogPrintf( "World triggered \"Round_SuddenDeath\"\n" );
}
return true;
}
else if ( FStrEq( eventName, "teamplay_round_win" ) )
{
bool bShowScores = true;
int iTeam = event->GetInt( "team" );
bool bFullRound = event->GetBool( "full_round" );
if ( iTeam == TEAM_UNASSIGNED )
{
UTIL_LogPrintf( "World triggered \"Round_Stalemate\"\n" );
}
else
{
const char *pszWinner = "Red";
if ( iTeam == TF_TEAM_BLUE )
{
pszWinner = "Blue";
}
CTeamControlPointMaster *pMaster = g_hControlPointMasters.Count() ? g_hControlPointMasters[0] : NULL;
if ( pMaster && pMaster->PlayingMiniRounds() )
{
UTIL_LogPrintf( "World triggered \"Mini_Round_Win\" (winner \"%s\") (round \"%s\")\n", pszWinner, pMaster->GetCurrentRound()->GetEntityName().ToCStr() );
UTIL_LogPrintf( "World triggered \"Mini_Round_Length\" (seconds \"%0.2f\")\n", event->GetFloat( "round_time" ) );
bShowScores = false;
}
if ( bFullRound )
{
UTIL_LogPrintf( "World triggered \"Round_Win\" (winner \"%s\")\n", pszWinner );
if ( !pMaster || !pMaster->PlayingMiniRounds() )
{
UTIL_LogPrintf( "World triggered \"Round_Length\" (seconds \"%0.2f\")\n", event->GetFloat( "round_time" ) );
}
bShowScores = true;
}
}
if ( bShowScores )
{
UTIL_LogPrintf( "Team \"Red\" current score \"%d\" with \"%d\" players\n", GetGlobalTeam( TF_TEAM_RED )->GetScore(), GetGlobalTeam( TF_TEAM_RED )->GetNumPlayers() );
UTIL_LogPrintf( "Team \"Blue\" current score \"%d\" with \"%d\" players\n", GetGlobalTeam( TF_TEAM_BLUE )->GetScore(), GetGlobalTeam( TF_TEAM_BLUE )->GetNumPlayers() );
}
}
else if ( FStrEq( eventName, "medic_death" ) )
{
const int userid = event->GetInt( "userid" );
CBasePlayer *pPlayer = UTIL_PlayerByUserId( userid );
if ( !pPlayer )
{
return false;
}
const int attackerid = event->GetInt( "attacker" );
CBasePlayer *pAttacker = UTIL_PlayerByUserId( attackerid );
bool bCharged = event->GetBool( "charged" );
int iHealing = event->GetInt( "healing" );
if ( !pAttacker )
{
pAttacker = pPlayer;
}
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"medic_death\" against \"%s<%i><%s><%s>\" (healing \"%d\") (ubercharge \"%s\")\n",
pAttacker->GetPlayerName(),
attackerid,
pAttacker->GetNetworkIDString(),
pAttacker->GetTeam()->GetName(),
pPlayer->GetPlayerName(),
userid,
pPlayer->GetNetworkIDString(),
pPlayer->GetTeam()->GetName(),
iHealing,
bCharged ? "1" : "0" );
return true;
}
return false;
}
};
CTFEventLog g_TFEventLog;
//-----------------------------------------------------------------------------
// Singleton access
//-----------------------------------------------------------------------------
IGameSystem* GameLogSystem()
{
return &g_TFEventLog;
}