//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CEP2GameStats::Event_PlayerKilled( CBasePlayer *pPlayer, const CTakeDamageInfo &info )
{
	BaseClass::Event_PlayerKilled( pPlayer, info );

	if ( info.GetDamageType() & DMG_FALL )
	{
		++m_pCurrentMap->m_IntCounters[ Ep2LevelStats_t::COUNTER_FALLINGDEATHS ];
	}

	Ep2LevelStats_t::PlayerDeathsLump_t death;

	// set the location where the target died
	const Vector &org = pPlayer->GetAbsOrigin();
	death.nPosition[ 0 ] = static_cast<short>( org.x );
	death.nPosition[ 1 ] = static_cast<short>( org.y );
	death.nPosition[ 2 ] = static_cast<short>( org.z );

	StatsLog( "CEP2GameStats::Event_PlayerKilled at location [%d %d %d]\n", (int)death.nPosition[ 0 ], (int)death.nPosition[ 1 ], (int)death.nPosition[ 2 ] );

	// set the class of the attacker
	CBaseEntity *pInflictor = info.GetInflictor();
	CBaseEntity *pKiller = info.GetAttacker();

	if ( pInflictor )
	{
		StatsLog( "Inflictor: %s\n", pInflictor->GetClassname() );
	}

	if ( pKiller )
	{
		char const *pchKiller = pKiller->GetClassname();
		Ep2LevelStats_t::EntityDeathsLump_t *lump = FindDeathsLump( pchKiller );
		if ( lump )
		{
			++lump->m_nKilledPlayer;
			StatsLog( "Player has been killed %d times by %s's\n", lump->m_nKilledPlayer, pchKiller );
		}
		else
		{
			StatsLog( "Player killed by %s (not tracked)\n", pchKiller );
		}
	}

	// add it to the list of deaths
	Ep2LevelStats_t *map = FindOrAddMapStats( STRING( gpGlobals->mapname ) );
	int slot = map->m_aPlayerDeaths.AddToTail( death );

	Ep2LevelStats_t::SaveGameInfoRecord2_t *rec = map->m_SaveGameInfo.m_pCurrentRecord;
	if ( rec )
	{
		if ( rec->m_nFirstDeathIndex == -1 )
		{
			rec->m_nFirstDeathIndex = slot;
		}
		++rec->m_nNumDeaths;

		StatsLog( "Player has died %d times since last save/load\n", rec->m_nNumDeaths );
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CEP2GameStats::Event_LevelInit( void )
{
	BaseClass::Event_LevelInit();

	char const *pchTag = NULL;
	CommandLine()->CheckParm( "-gamestatstag", &pchTag );
	if ( !pchTag )
	{
		pchTag = "";
	}

	m_pCurrentMap = FindOrAddMapStats( STRING( gpGlobals->mapname ) );
	m_pCurrentMap->Init( STRING( gpGlobals->mapname ), gpGlobals->curtime, pchTag, gpGlobals->mapversion );
}
//-----------------------------------------------------------------------------
// Purpose: Loads data from buffer
//-----------------------------------------------------------------------------
bool TFReportedStats_t::LoadCustomDataFromBuffer( CUtlBuffer &LoadBuffer )
{
	// read the version lump of beginning of file and verify version
	bool bGotEndTag = false;
	unsigned short iLump = 0;
	unsigned short iLumpCount = 0;
	if ( !CBaseGameStats::GetLumpHeader( MAX_LUMP_COUNT, LoadBuffer, iLump, iLumpCount ) )
		return false;
	if ( iLump != TFSTATS_LUMP_VERSION )
	{
		Msg( "Didn't find version header.  Expected lump type TFSTATS_LUMP_VERSION, got lump type %d.  Skipping file.\n", iLump );
		return false;
	}
	TF_Gamestats_Version_t versionLump;
	CBaseGameStats::LoadLump( LoadBuffer, iLumpCount, sizeof( versionLump ), &versionLump );
	if ( versionLump.m_iMagic != TF_GAMESTATS_MAGIC )
	{
		Msg( "Incorrect magic # in version header.  Expected %x, got %x.  Skipping file.\n", TF_GAMESTATS_MAGIC, versionLump.m_iMagic );
		return false;
	}
	if ( versionLump.m_iVersion != TF_GAMESTATS_FILE_VERSION )
	{
		Msg( "Mismatched file version.  Expected file version %d, got %d. Skipping file.\n", TF_GAMESTATS_FILE_VERSION, versionLump.m_iVersion  );
		return false;
	}

	// read all the lumps in the file
	while( CBaseGameStats::GetLumpHeader( MAX_LUMP_COUNT, LoadBuffer, iLump, iLumpCount ) )
	{
		switch ( iLump )
		{
		case TFSTATS_LUMP_MAPHEADER: 
			{
				TF_Gamestats_LevelStats_t::LevelHeader_t header;
				CBaseGameStats::LoadLump( LoadBuffer, iLumpCount, sizeof( TF_Gamestats_LevelStats_t::LevelHeader_t ), &header );

				// quick sanity check on some data -- we get some stat files that start out OK but are corrupted later in the file
				if ( ( header.m_iRoundsPlayed < 0 ) || ( header.m_iTotalTime < 0 ) || ( header.m_iRoundsPlayed > 1000 ) )
					return false;

				// if there's no interesting data, skip this file.  (Need to have server not send it in this case.)
				if ( header.m_iTotalTime == 0 )
					return false;

				m_pCurrentGame = FindOrAddMapStats( header.m_szMapName );
				if ( m_pCurrentGame )
				{
					m_pCurrentGame->m_Header = header;
				}
				break; 
			}
		case TFSTATS_LUMP_MAPDEATH:
			{
				CUtlVector<TF_Gamestats_LevelStats_t::PlayerDeathsLump_t> playerDeaths;

				playerDeaths.SetCount( iLumpCount );
				CBaseGameStats::LoadLump( LoadBuffer, iLumpCount, sizeof( TF_Gamestats_LevelStats_t::PlayerDeathsLump_t ), static_cast<void*>( playerDeaths.Base() ) );
				if ( m_pCurrentGame )
				{
					m_pCurrentGame->m_aPlayerDeaths = playerDeaths;
				}
				break;
			}
		case TFSTATS_LUMP_MAPDAMAGE:
			{
				CUtlVector<TF_Gamestats_LevelStats_t::PlayerDamageLump_t> playerDamage;

				playerDamage.SetCount( iLumpCount );
				CBaseGameStats::LoadLump( LoadBuffer, iLumpCount, sizeof( TF_Gamestats_LevelStats_t::PlayerDamageLump_t ), static_cast<void*>( playerDamage.Base() ) );
				if ( m_pCurrentGame )
				{
					m_pCurrentGame->m_aPlayerDamage = playerDamage;
				}
				break;
			}		
		case TFSTATS_LUMP_CLASS:
			{
				Assert( m_pCurrentGame );
				Assert ( iLumpCount == ARRAYSIZE( m_pCurrentGame->m_aClassStats ) );
				if ( iLumpCount == ARRAYSIZE( m_pCurrentGame->m_aClassStats ) )
				{
					CBaseGameStats::LoadLump( LoadBuffer, ARRAYSIZE( m_pCurrentGame->m_aClassStats ), sizeof( m_pCurrentGame->m_aClassStats[0] ), 
						m_pCurrentGame->m_aClassStats );

					// quick sanity check on some data -- we get some stat files that start out OK but are corrupted later in the file
					for ( int i = 0; i < ARRAYSIZE( m_pCurrentGame->m_aClassStats ); i++ )
					{
						TF_Gamestats_ClassStats_t &classStats = m_pCurrentGame->m_aClassStats[i];
						if ( ( classStats.iSpawns < 0 ) || ( classStats.iSpawns > 10000 ) || ( classStats.iTotalTime < 0 ) || ( classStats.iTotalTime > 36000 * 20 ) ||
							( classStats.iKills < 0 ) || ( classStats.iKills > 10000 ) )
						{
							return false;
						}
					}
				}
				else
				{
					// mismatched lump size, possibly from different build, don't know how it interpret it, just skip over it
					return false;
				}				
				break;
			}
		case TFSTATS_LUMP_WEAPON:
			{
				Assert( m_pCurrentGame );
				Assert ( iLumpCount == ARRAYSIZE( m_pCurrentGame->m_aWeaponStats ) );
				if ( iLumpCount == ARRAYSIZE( m_pCurrentGame->m_aWeaponStats ) )
				{
					CBaseGameStats::LoadLump( LoadBuffer, ARRAYSIZE( m_pCurrentGame->m_aWeaponStats ), sizeof( m_pCurrentGame->m_aWeaponStats[0] ), 
						m_pCurrentGame->m_aWeaponStats );

					// quick sanity check on some data -- we get some stat files that start out OK but are corrupted later in the file
					if ( ( m_pCurrentGame->m_aWeaponStats[TF_WEAPON_MEDIGUN].iShotsFired < 0 ) || ( m_pCurrentGame->m_aWeaponStats[TF_WEAPON_MEDIGUN].iShotsFired > 100000 )
						|| ( m_pCurrentGame->m_aWeaponStats[TF_WEAPON_FLAMETHROWER_ROCKET].iShotsFired != 0 ) ) // check that unused weapon has 0 shots
					{
						return false;
					}
					
				}				
				else
				{
					// mismatched lump size, possibly from different build, don't know how it interpret it, just skip over it
					return false;				
				}				
				break;
			}
		case TFSTATS_LUMP_ENDTAG:
			{
				// check that end tag is valid -- should be version lump again
				TF_Gamestats_Version_t versionLump;
				CBaseGameStats::LoadLump( LoadBuffer, iLumpCount, sizeof( versionLump ), &versionLump );
				if ( versionLump.m_iMagic != TF_GAMESTATS_MAGIC )
				{
					Msg( "Incorrect magic # in version header.  Expected %x, got %x.  Skipping file.\n", TF_GAMESTATS_MAGIC, versionLump.m_iMagic );
					return false;
				}
				if ( versionLump.m_iVersion != TF_GAMESTATS_FILE_VERSION )
				{
					Msg( "Mismatched file version.  Expected file version %d, got %d. Skipping file.\n", TF_GAMESTATS_FILE_VERSION, versionLump.m_iVersion  );
					return false;
				}
				bGotEndTag = true;
				break;
			}

		}
	}

	return bGotEndTag;
}