예제 #1
0
void WeaponStats_t::PrepStatsForSend( CASW_Player *pPlayer )
{
	if( !GetDebriefStats() || !ASWGameResource() || !ASWEquipmentList() )
		return;

	// Check to see if the weapon is in the debrief stats
	CASW_Marine_Resource *pMR = ASWGameResource()->GetFirstMarineResourceForPlayer( pPlayer );
	if ( !pMR )
		return;
	
	int iMarineIndex = ASWGameResource()->GetMarineResourceIndex( pMR );
	if ( iMarineIndex == -1 )
		return;

	
	if( !m_szClassName )
		return;
	int iDamage, iFFDamage, iShotsFired, iShotsHit, iKills = 0;

	if( GetDebriefStats()->GetWeaponStats( iMarineIndex, m_iWeaponIndex, iDamage, iFFDamage, iShotsFired, iShotsHit, iKills ) )
	{
		SEND_STEAM_STATS( CFmtStr( "equips.%s.damage", m_szClassName ), m_iDamage + iDamage );
		SEND_STEAM_STATS( CFmtStr( "equips.%s.ff_damage", m_szClassName ), m_iFFDamage + iFFDamage );
		SEND_STEAM_STATS( CFmtStr( "equips.%s.shots_fired", m_szClassName ), m_iShotsFired + iShotsFired );
		SEND_STEAM_STATS( CFmtStr( "equips.%s.shots_hit", m_szClassName ), m_iShotsHit + iShotsHit );
		SEND_STEAM_STATS( CFmtStr( "equips.%s.kills", m_szClassName ), m_iKills + iKills );
	}
}
예제 #2
0
void DifficultyStats_t::PrepStatsForSend( CASW_Player *pPlayer )
{
	if( !steamapicontext )
		return;

	// Update stats from the briefing screen
	if( !GetDebriefStats() || !ASWGameResource() )
		return;

	CASW_Marine_Resource *pMR = ASWGameResource()->GetFirstMarineResourceForPlayer( pPlayer );
	if ( pMR )
	{
		int iMarineIndex = ASWGameResource()->GetMarineResourceIndex( pMR );
		if ( iMarineIndex != -1 )
		{
			m_iKillsTotal += GetDebriefStats()->GetKills( iMarineIndex );
			m_iFFTotal += GetDebriefStats()->GetFriendlyFire( iMarineIndex );
			m_iDamageTotal += GetDebriefStats()->GetDamageTaken( iMarineIndex );
			m_iShotsFiredTotal += GetDebriefStats()->GetShotsFired( iMarineIndex );
			m_iHealingTotal += GetDebriefStats()->GetHealthHealed( iMarineIndex );
			m_iShotsHitTotal += GetDebriefStats()->GetShotsHit( iMarineIndex );
			m_fAccuracyAvg = ( m_iShotsFiredTotal > 0 ) ? ( m_iShotsHitTotal / (float)m_iShotsFiredTotal * 100.0f ) : 0;
			m_iGamesTotal++;
			m_iGamesSuccess += ASWGameRules()->GetMissionSuccess() ? 1 : 0;
			m_fGamesSuccessPercent = m_iGamesSuccess / (float)m_iGamesTotal * 100.0f;
		}
	}
	char* szDifficulty = NULL;
	int iDifficulty = ASWGameRules()->GetSkillLevel();

	switch( iDifficulty )
	{
	case 1: szDifficulty = "easy"; 
		break;
	case 2: szDifficulty = "normal";
		break;
	case 3: szDifficulty = "hard";
		break;
	case 4: szDifficulty = "insane";
		break;
	case 5: szDifficulty = "imba";
		break;
	}
	if( szDifficulty )
	{
		SEND_STEAM_STATS( CFmtStr( "%s%s", szDifficulty, szGamesTotal ), m_iGamesTotal );
		SEND_STEAM_STATS( CFmtStr( "%s%s", szDifficulty, szGamesSuccess ), m_iGamesSuccess );
		SEND_STEAM_STATS( CFmtStr( "%s%s", szDifficulty, szGamesSuccessPercent ), m_fGamesSuccessPercent );
		SEND_STEAM_STATS( CFmtStr( "%s%s", szDifficulty, szKillsTotal ), m_iKillsTotal );
		SEND_STEAM_STATS( CFmtStr( "%s%s", szDifficulty, szDamageTotal ), m_iDamageTotal );
		SEND_STEAM_STATS( CFmtStr( "%s%s", szDifficulty, szFFTotal ), m_iFFTotal );
		SEND_STEAM_STATS( CFmtStr( "%s%s", szDifficulty, szAccuracy ), m_fAccuracyAvg );
		SEND_STEAM_STATS( CFmtStr( "%s%s", szDifficulty, szShotsHit ), m_iShotsHitTotal );
		SEND_STEAM_STATS( CFmtStr( "%s%s", szDifficulty, szShotsTotal ), m_iShotsFiredTotal );
		SEND_STEAM_STATS( CFmtStr( "%s%s", szDifficulty, szHealingTotal ), m_iHealingTotal );
	}
}
예제 #3
0
bool MissionStats_t::FetchMissionStats( CSteamAPIContext * pSteamContext, CSteamID playerSteamID )
{
	bool bOK = true;
	const char* szLevelName = NULL;
	if( !engine )
		return false;

	szLevelName = engine->GetLevelNameShort();
	if( !szLevelName )
		return false;

	// Fetch stats. Skip the averages, they're write only
	FETCH_STEAM_STATS( CFmtStr( "%s%s", szLevelName, szGamesTotal ), m_iGamesTotal );
	FETCH_STEAM_STATS( CFmtStr( "%s%s", szLevelName, szGamesSuccess ), m_iGamesSuccess );
	FETCH_STEAM_STATS( CFmtStr( "%s%s", szLevelName, szGamesSuccessPercent ), m_fGamesSuccessPercent );
	FETCH_STEAM_STATS( CFmtStr( "%s%s", szLevelName, szKillsTotal ), m_iKillsTotal );
	FETCH_STEAM_STATS( CFmtStr( "%s%s", szLevelName, szDamageTotal ), m_iDamageTotal );
	FETCH_STEAM_STATS( CFmtStr( "%s%s", szLevelName, szFFTotal ), m_iFFTotal );
	FETCH_STEAM_STATS( CFmtStr( "%s%s", szLevelName, szTimeTotal ), m_iTimeTotal );
	FETCH_STEAM_STATS( CFmtStr( "%s%s", szLevelName, szBestDifficulty ), m_iHighestDifficulty );
	for( int i=0; i<5; ++i )
	{
		FETCH_STEAM_STATS( CFmtStr( "%s%s.%s", szLevelName, szBestTime, g_szDifficulties[i] ), m_iBestSpeedrunTimes[i] );
	}

	return bOK;
}
예제 #4
0
bool WeaponStats_t::FetchWeaponStats( CSteamAPIContext * pSteamContext, CSteamID playerSteamID, const char *szClassName )
{
	bool bOK = true;

	// Fetch stats. Skip the averages, they're write only
	FETCH_STEAM_STATS( CFmtStr( "equips.%s.damage", szClassName ), m_iDamage );
	FETCH_STEAM_STATS( CFmtStr( "equips.%s.ff_damage", szClassName ), m_iFFDamage );
	FETCH_STEAM_STATS( CFmtStr( "equips.%s.shots_fired", szClassName ), m_iShotsFired );
	FETCH_STEAM_STATS( CFmtStr( "equips.%s.shots_hit", szClassName ), m_iShotsHit );
	FETCH_STEAM_STATS( CFmtStr( "equips.%s.kills", szClassName ), m_iKills );

	return bOK;
}
예제 #5
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CAI_Expresser::SpeechMsg( CBaseEntity *pFlex, const char *pszFormat, ... )
{
	if ( !DebuggingSpeech() )
		return;

	if ( pFlex->MyNPCPointer() )
	{
		DevMsg( pFlex->MyNPCPointer(), CFmtStr( &pszFormat ) );
	}
	else 
	{
		DevMsg( CFmtStr( &pszFormat ) );
	}
	UTIL_LogPrintf( (char *) ( (const char *) CFmtStr( &pszFormat ) ) );
}
예제 #6
0
int	CASW_Spawner::DrawDebugTextOverlays()
{
	int text_offset = BaseClass::DrawDebugTextOverlays();

	if (m_debugOverlays & OVERLAY_TEXT_BIT)
	{
		NDebugOverlay::EntityText( entindex(),text_offset,CFmtStr( "Num Live Aliens: %d", m_nCurrentLiveAliens ),0 );
		text_offset++;
		NDebugOverlay::EntityText( entindex(),text_offset,CFmtStr( "Max Live Aliens: %d", m_nMaxLiveAliens ),0 );
		text_offset++;
		NDebugOverlay::EntityText( entindex(),text_offset,CFmtStr( "Alien supply: %d", m_bInfiniteAliens ? -1 : m_nNumAliens ),0 );
		text_offset++;
	}
	return text_offset;
}
예제 #7
0
	// MSVC __cdecl?
	// access violation @ client.dll 20161002a .text:105512A9
	DETOUR_DECL_MEMBER(bool, vgui_AnimationController_StartAnimationSequence, vgui::Panel *pWithinParent, const char *sequenceName)
	{
		const char *name = CFmtStr("vgui::AnimationController::StartAnimationSequence(\"%s\")", sequenceName);
		
		VPROF_CUSTOM(name);
		return DETOUR_MEMBER_CALL(vgui_AnimationController_StartAnimationSequence)(pWithinParent, sequenceName);
	}
void IFaceposerModels::CFacePoserModel::RecreateAllAnimationBitmaps()
{
	StudioModel *model = m_pModel;
	if ( !model )
		return;

	CStudioHdr *hdr = model->GetStudioHdr();
	if ( !hdr )
		return;	

	g_pProgressDialog->Start( CFmtStr( "%s - Animation Thumbnails", GetShortModelName() ), "", true );

	for ( int i = 0; i < hdr->GetNumSeq(); ++i )
	{
		const mstudioseqdesc_t &seq = hdr->pSeqdesc( i );

		g_pProgressDialog->UpdateText( "%s", seq.pszLabel() );
		g_pProgressDialog->Update( (float)i / (float)hdr->GetNumSeq() );

		RecreateAnimationBitmap( i, false );

		if ( g_pProgressDialog->IsCancelled() )
		{
			Msg( "Cancelling\n" );
			break;
		}
	}

	g_pProgressDialog->Finish();

	ReconcileAnimationBitmaps();
}
예제 #9
0
bool DoIncludeScript( const char *pszScript, HSCRIPT hScope )
{
	if ( !VScriptRunScript( pszScript, hScope, true ) )
	{
		g_pScriptVM->RaiseException( CFmtStr( "Failed to include script \"%s\"", ( pszScript ) ? pszScript : "unknown" ) );
		return false;
	}
	return true;
}
//-----------------------------------------------------------------------------
// Purpose: Returns specified tip index for specified class
//-----------------------------------------------------------------------------
const wchar_t *CFRTips::GetTip(int iTip)
{
	static wchar_t wzTip[512] = L"";

	// get the tip
	const wchar_t *wzFmt = g_pVGuiLocalize->Find( CFmtStr( "#FR_Tip_%d", iTip ) );
	// replace any commands with their bound keys
	UTIL_ReplaceKeyBindings( wzFmt, 0, wzTip, sizeof( wzTip ) );

	return wzTip;
}
//-----------------------------------------------------------------------------
// Purpose: Initializer
//-----------------------------------------------------------------------------
bool CFRTips::Init()
{
	if ( !m_bInited )
	{
		// count how many tips there are for each class and in total
		m_iTipCountAll = 0;
		wchar_t *wzTipCount = g_pVGuiLocalize->Find(CFmtStr("FR_Tip_Count"));
		int iTipCount = wzTipCount ? _wtoi(wzTipCount) : 0;
		m_iTipCountAll += iTipCount;
		m_bInited = true;
	}

	return true;
}
예제 #12
0
bool DifficultyStats_t::FetchDifficultyStats( CSteamAPIContext * pSteamContext, CSteamID playerSteamID, int iDifficulty )
{
	if( !ASWGameRules() )
		return false;

	bool bOK = true;
	char* szDifficulty = NULL;

	switch( iDifficulty )
	{
		case 1: szDifficulty = "easy"; 
			break;
		case 2: szDifficulty = "normal";
			break;
		case 3: szDifficulty = "hard";
			break;
		case 4: szDifficulty = "insane";
			break;
		case 5: szDifficulty = "imba";
			break;
	}
	if( szDifficulty )
	{
		FETCH_STEAM_STATS( CFmtStr( "%s%s", szDifficulty, szGamesTotal ), m_iGamesTotal );
		FETCH_STEAM_STATS( CFmtStr( "%s%s", szDifficulty, szGamesSuccess ), m_iGamesSuccess );
		FETCH_STEAM_STATS( CFmtStr( "%s%s", szDifficulty, szGamesSuccessPercent ), m_fGamesSuccessPercent );
		FETCH_STEAM_STATS( CFmtStr( "%s%s", szDifficulty, szKillsTotal ), m_iKillsTotal );
		FETCH_STEAM_STATS( CFmtStr( "%s%s", szDifficulty, szDamageTotal ), m_iDamageTotal );
		FETCH_STEAM_STATS( CFmtStr( "%s%s", szDifficulty, szFFTotal ), m_iFFTotal );
		FETCH_STEAM_STATS( CFmtStr( "%s%s", szDifficulty, szAccuracy ), m_fAccuracyAvg );
		FETCH_STEAM_STATS( CFmtStr( "%s%s", szDifficulty, szShotsHit ), m_iShotsHitTotal );
		FETCH_STEAM_STATS( CFmtStr( "%s%s", szDifficulty, szShotsTotal ), m_iShotsFiredTotal );
		FETCH_STEAM_STATS( CFmtStr( "%s%s", szDifficulty, szHealingTotal ), m_iHealingTotal );
	}

	return bOK;
}
예제 #13
0
void CBaseGameStats_Driver::ResetData()
{
#ifdef GAME_DLL
	// on the server, if there is a gamestats data container registered (by a client in the same process), they're in charge of resetting it, nothing for us to do
	if ( engine->GetGamestatsData() != NULL )
		return;
#endif

	if ( m_pGamestatsData != NULL )
	{
		delete m_pGamestatsData;
		m_pGamestatsData = NULL;
	}

	m_pGamestatsData = new CGamestatsData();
	KeyValues *pKV = m_pGamestatsData->m_pKVData;

	pKV->SetInt( "version", GAMESTATS_VERSION );
	pKV->SetString( "srcid", s_szPseudoUniqueID );

#ifdef CLIENT_DLL
	const CPUInformation &cpu = GetCPUInformation();
	OverWriteCharsWeHate( cpu.m_szProcessorID );
	pKV->SetString( "CPUID", cpu.m_szProcessorID );
	pKV->SetFloat( "CPUGhz", cpu.m_Speed * ( 1.0 / 1.0e9 ) );
	pKV->SetInt( "NumCores", cpu.m_nPhysicalProcessors );

	MaterialAdapterInfo_t gpu;
	materials->GetDisplayAdapterInfo( materials->GetCurrentAdapter(), gpu );

	CMatRenderContextPtr pRenderContext( materials );
	int dest_width,dest_height;
	pRenderContext->GetRenderTargetDimensions( dest_width, dest_height );

	if ( gpu.m_pDriverName )
	{
		OverWriteCharsWeHate( gpu.m_pDriverName );
	}
	pKV->SetString( "GPUDrv", SafeString( gpu.m_pDriverName ) );
	pKV->SetInt( "GPUVendor", gpu.m_VendorID );
	pKV->SetInt( "GPUDeviceID", gpu.m_DeviceID );
	pKV->SetString( "GPUDriverVersion", CFmtStr( "%d.%d", gpu.m_nDriverVersionHigh, gpu.m_nDriverVersionLow ) );
	pKV->SetInt( "DxLvl", g_pMaterialSystemHardwareConfig->GetDXSupportLevel() );
	pKV->SetInt( "Width", dest_width );
	pKV->SetInt( "Height", dest_height );

	engine->SetGamestatsData( m_pGamestatsData );
#endif
}
예제 #14
0
void CASW_Spawn_Manager::LevelInitPostEntity()
{
	m_vecHordePosition = vec3_origin;
	m_angHordeAngle = vec3_angle;
	m_batchInterval.Invalidate();
	m_CandidateUpdateTimer.Invalidate();
	m_iHordeToSpawn = 0;
	m_iAliensToSpawn = 0;

	m_northCandidateNodes.Purge();
	m_southCandidateNodes.Purge();

	FindEscapeTriggers();

	LoadConfig(&m_pGlobalConfig, "resource/alien_selection.txt", true);
	LoadConfig(&m_pMissionConfig, CFmtStr("resource/alien_selection_%s.txt", STRING(gpGlobals->mapname)));
}
예제 #15
0
	DETOUR_DECL_MEMBER(bool, vgui_AnimationController_StartAnimationSequence, const char *sequenceName)
	{
		const char *name = CFmtStr("vgui::AnimationController::StartAnimationSequence(\"%s\")", sequenceName);
		
		if (cvar_trace.GetBool()) {
			DevMsg("ENTER vgui::AnimationController::StartAnimationSequence(\"%s\")\n", sequenceName);
		}
		
		VPROF_CUSTOM(name);
		auto result = DETOUR_MEMBER_CALL(vgui_AnimationController_StartAnimationSequence)(sequenceName);
		
		if (cvar_trace.GetBool()) {
			DevMsg("EXIT  vgui::AnimationController::StartAnimationSequence(\"%s\")\n", sequenceName);
		}
		
		return result;
	}
예제 #16
0
	DETOUR_DECL_MEMBER(void, CDamageAccountPanel_FireGameEvent, IGameEvent *event)
	{
		const char *name = "CDamageAccountPanel::FireGameEvent(nullptr)";
		if (event != nullptr) {
			name = CFmtStr("CDamageAccountPanel::FireGameEvent(\"%s\")", event->GetName());
		}
		
		if (cvar_trace.GetBool()) {
			DevMsg("ENTER CDamageAccountPanel::FireGameEvent(\"%s\")\n", name);
		}
		
		VPROF_CUSTOM(name);
		DETOUR_MEMBER_CALL(CDamageAccountPanel_FireGameEvent)(event);
		
		if (cvar_trace.GetBool()) {
			DevMsg("EXIT  CDamageAccountPanel::FireGameEvent\n");
		}
	}
예제 #17
0
void CASWJukeboxPlaylist::MarkTrackForDeletion( int index )
{
	if( index >= m_CombatMusicPlaylist.Count() )
		return;
	else
	{
		if( index == m_iCurrentTrack )
			StopTrack( true, 0.0f );

		m_CombatMusicPlaylist[index].m_bIsMarkedForDeletion = true;

		// Delete the audio file too
		const char *szFullpath = CFmtStr( "%s%s.mp3", "sound/music/_mp3/", m_CombatMusicPlaylist[index].m_szHexname );
		if( filesystem->FileExists( szFullpath, NULL ) )
		{
			filesystem->RemoveFile( szFullpath, NULL );
		}
	}
}
예제 #18
0
		virtual void FrameUpdatePostEntityThink() override
		{
			static long frame = 0;
			if (++frame % 2 == 0) return;
			
			ForEachEntityByRTTI<CTFMinigun>([](CTFMinigun *minigun){
				NDebugOverlay::EntityText(ENTINDEX(minigun), 0, CFmtStr("%d", (int)minigun->m_iWeaponState), 0.030f);
				
		//		DevMsg("Minigun WSC: % 6.1f % 6.1f % 6.1f\n",
		//			minigun->WorldSpaceCenter().x,
		//			minigun->WorldSpaceCenter().y,
		//			minigun->WorldSpaceCenter().z);
			});
		//	ForEachEntityByClassname("player", [](CBaseEntity *player){
		//		DevMsg(" Player WSC: % 6.1f % 6.1f % 6.1f\n",
		//			player->WorldSpaceCenter().x,
		//			player->WorldSpaceCenter().y,
		//			player->WorldSpaceCenter().z);
		//	});
		}
예제 #19
0
	DETOUR_DECL_MEMBER(bool, IGameEventManager2_FireEventClientSide, IGameEvent *event)
	{
		const char *name = "IGameEventManager2::FireEventClientSide(nullptr)";
		if (event != nullptr) {
			name = CFmtStr("IGameEventManager2::FireEventClientSide(\"%s\")", event->GetName());
		}
		
		if (cvar_trace.GetBool()) {
			DevMsg("ENTER IGameEventManager2::FireEventClientSide(\"%s\")\n", name);
		}
		
		VPROF_CUSTOM(name);
		auto result = DETOUR_MEMBER_CALL(IGameEventManager2_FireEventClientSide)(event);
		
		if (cvar_trace.GetBool()) {
			DevMsg("EXIT  IGameEventManager2::FireEventClientSide\n");
		}
		
		return result;
	}
void asw_ClearHousef()
{
	CASW_Player *pPlayer = ToASW_Player(UTIL_GetCommandClient());
	if (!pPlayer)
		return;

	// remove all alien NPCs
	if ( ASWSpawnManager() )
	{
		int nCount = ASWSpawnManager()->GetNumAlienClasses();
		for ( int i = 0; i < nCount; i++ )
		{
			engine->ClientCommand( pPlayer->edict(), CFmtStr( "ent_remove_all %s", ASWSpawnManager()->GetAlienClass(i)->m_pszAlienClass ) );
		}
	}

	// remove non NPC types
	engine->ClientCommand(pPlayer->edict(), "ent_remove_all asw_alien_goo");
	engine->ClientCommand(pPlayer->edict(), "ent_remove_all asw_grub_sac");
	engine->ClientCommand(pPlayer->edict(), "ent_remove_all asw_spawner");
	engine->ClientCommand(pPlayer->edict(), "ent_remove_all asw_egg");
}
예제 #21
0
//--------------------------------------------------------------------------------------------------------
void CFuncNavCost::Spawn( void )
{
	BaseClass::Spawn();

	gm_masterCostVector.AddToTail( this );
	gm_dirtyTimer.Start( UPDATE_DIRTY_TIME );

	SetSolid( SOLID_BSP );	
	AddSolidFlags( FSOLID_NOT_SOLID );

	SetMoveType( MOVETYPE_NONE );
	SetModel( STRING( GetModelName() ) );
	AddEffects( EF_NODRAW );
	SetCollisionGroup( COLLISION_GROUP_NONE );

	VPhysicsInitShadow( false, false );

	SetThink( &CFuncNavCost::CostThink );
	SetNextThink( gpGlobals->curtime + UPDATE_DIRTY_TIME );

	m_tags.RemoveAll();

	const char *tags = STRING( m_iszTags );

	// chop space-delimited string into individual tokens
	if ( tags )
	{
		char *buffer = new char [ strlen( tags ) + 1 ];
		Q_strcpy( buffer, tags );

		for( char *token = strtok( buffer, " " ); token; token = strtok( NULL, " " ) )
		{
			m_tags.AddToTail( CFmtStr( "%s", token ) );
		}

		delete [] buffer;
	}
}
int CAI_TacticalServices::FindLosNode(const Vector &vThreatPos, const Vector &vThreatEyePos, float flMinThreatDist, float flMaxThreatDist, float flBlockTime, FlankType_t eFlankType, const Vector &vecFlankRefPos, float flFlankParam )
{
	if ( !CAI_NetworkManager::NetworksLoaded() )
		return NO_NODE;

	AI_PROFILE_SCOPE( CAI_TacticalServices_FindLosNode );

	MARK_TASK_EXPENSIVE();

	int iMyNode	= GetPathfinder()->NearestNodeToNPC();
	if ( iMyNode == NO_NODE )
	{
		Vector pos = GetOuter()->GetAbsOrigin();
		DevWarning( 2, "FindCover() - %s has no nearest node! (Check near %f %f %f)\n", GetEntClassname(), pos.x, pos.y, pos.z);
		return NO_NODE;
	}

	// ------------------------------------------------------------------------------------
	// We're going to search for a shoot node by expanding to our current node's neighbors
	// and then their neighbors, until a shooting position is found, or all nodes are beyond MaxDist
	// ------------------------------------------------------------------------------------
	AI_NearNode_t *pBuffer = (AI_NearNode_t *)stackalloc( sizeof(AI_NearNode_t) * GetNetwork()->NumNodes() );
	CNodeList list( pBuffer, GetNetwork()->NumNodes() );
	CVarBitVec wasVisited(GetNetwork()->NumNodes());	// Nodes visited

	// mark start as visited
	wasVisited.Set( iMyNode );
	list.Insert( AI_NearNode_t(iMyNode, 0) );

	static int nSearchRandomizer = 0;		// tries to ensure the links are searched in a different order each time;

	while ( list.Count() )
	{
		int nodeIndex = list.ElementAtHead().nodeIndex;
		// remove this item from the list
		list.RemoveAtHead();

		const Vector &nodeOrigin = GetNetwork()->GetNode(nodeIndex)->GetPosition(GetHullType());

		// HACKHACK: Can't we rework this loop and get rid of this?
		// skip the starting node, or we probably wouldn't have called this function.
		if ( nodeIndex != iMyNode )
		{
			bool skip = false;

			// See if the node satisfies the flanking criteria.
			switch ( eFlankType )
			{
				case FLANKTYPE_NONE:
					break;
					
				case FLANKTYPE_RADIUS:
				{
					Vector vecDist = nodeOrigin - vecFlankRefPos;
					if ( vecDist.Length() < flFlankParam )
					{
						skip = true;
					}
					
					break;
				}
				
				case FLANKTYPE_ARC:
				{
					Vector vecEnemyToRef = vecFlankRefPos - vThreatPos;
					VectorNormalize( vecEnemyToRef );

					Vector vecEnemyToNode = nodeOrigin - vThreatPos;
					VectorNormalize( vecEnemyToNode );
					
					float flDot = DotProduct( vecEnemyToRef, vecEnemyToNode );
					
					if ( RAD2DEG( acos( flDot ) ) < flFlankParam )
					{
						skip = true;
					}
					
					break;
				}
			}

			// Don't accept climb nodes, and assume my nearest node isn't valid because
			// we decided to make this check in the first place.  Keep moving
			if ( !skip && !GetNetwork()->GetNode(nodeIndex)->IsLocked() &&
				GetNetwork()->GetNode(nodeIndex)->GetType() != NODE_CLIMB )
			{
				// Now check its distance and only accept if in range
				float flThreatDist = ( nodeOrigin - vThreatPos ).Length();

				if ( flThreatDist < flMaxThreatDist &&
					 flThreatDist > flMinThreatDist )
				{
					CAI_Node *pNode = GetNetwork()->GetNode(nodeIndex);
					if ( GetOuter()->IsValidShootPosition( nodeOrigin, pNode, pNode->GetHint() ) )
					{
						if (GetOuter()->TestShootPosition(nodeOrigin,vThreatEyePos))
						{
							// Note when this node was used, so we don't try 
							// to use it again right away.
							GetNetwork()->GetNode(nodeIndex)->Lock( flBlockTime );

#if 0
							if ( GetOuter()->GetHintNode() )
							{
								GetOuter()->GetHintNode()->Unlock(GetOuter()->GetHintDelay(GetOuter()->GetHintNode()->HintType()));
								GetOuter()->SetHintNode( NULL );
							}

							// This used to not be set, why? (kenb)
							// @Note (toml 05-19-04): I think because stomping  the hint can lead to
							// unintended side effects. The hint node is primarily a high level
							// tool, and certain NPCs break if it gets slammed here. If we need
							// this, we should propagate it out and let the schedule selector
							// or task decide to set the hint node
							GetOuter()->SetHintNode( GetNetwork()->GetNode(nodeIndex)->GetHint() );
#endif
							if ( ShouldDebugLos( nodeIndex ) )
							{
								NDebugOverlay::Text( nodeOrigin, CFmtStr( "%d:los!", nodeIndex), false, 1 );
							}

							// The next NPC who searches should use a slight different pattern
							nSearchRandomizer = nodeIndex;
							return nodeIndex;
						}
						else
						{
							if ( ShouldDebugLos( nodeIndex ) )
							{
								NDebugOverlay::Text( nodeOrigin, CFmtStr( "%d:!shoot", nodeIndex), false, 1 );
							}
						}
					}
					else
					{
						if ( ShouldDebugLos( nodeIndex ) )
						{
							NDebugOverlay::Text( nodeOrigin, CFmtStr( "%d:!valid", nodeIndex), false, 1 );
						}
					}
				}
				else
				{
					if ( ShouldDebugLos( nodeIndex ) )
					{
						CFmtStr msg( "%d:%s", nodeIndex, ( flThreatDist < flMaxThreatDist ) ? "too close" : "too far" );
						NDebugOverlay::Text( nodeOrigin, msg, false, 1 );
					}
				}
			}
		}

		// Go through each link and add connected nodes to the list
		for (int link=0; link < GetNetwork()->GetNode(nodeIndex)->NumLinks();link++) 
		{
			int index = (link + nSearchRandomizer) % GetNetwork()->GetNode(nodeIndex)->NumLinks();
			CAI_Link *nodeLink = GetNetwork()->GetNode(nodeIndex)->GetLinkByIndex(index);

			if ( !m_pPathfinder->IsLinkUsable( nodeLink, iMyNode ) )
				continue;

			int newID = nodeLink->DestNodeID(nodeIndex);

			// If not already visited, add to the list
			if (!wasVisited.IsBitSet(newID))
			{
				float dist = (GetLocalOrigin() - GetNetwork()->GetNode(newID)->GetPosition(GetHullType())).LengthSqr();
				list.Insert( AI_NearNode_t(newID, dist) );
				wasVisited.Set( newID );
			}
		}
	}
	// We failed.  No range attack node node was found
	return NO_NODE;
}
bool BuildReferencedFileList( CUtlVector< UnusedContent::CUtlSymbol >& resfiles, CUtlRBTree< ReferencedFile, int >& files, const char *resfile )
{

	// Load the reslist file
	FileHandle_t resfilehandle;
	resfilehandle = g_pFileSystem->Open( resfile, "rb" );
	if ( FILESYSTEM_INVALID_HANDLE != resfilehandle )
	{
		// Read in and parse mapcycle.txt
		int length = g_pFileSystem->Size(resfilehandle);
		if ( length > 0 )
		{
			char *pStart = (char *)new char[ length + 1 ];
			if ( pStart && ( length == g_pFileSystem->Read(pStart, length, resfilehandle) )
			   )
			{
				pStart[ length ] = 0;

				char *pFileList = pStart;

				while ( 1 )
				{
					char szResList[ 256 ];

					pFileList = COM_Parse( pFileList );
					if ( strlen( com_token ) <= 0 )
						break;

					Q_snprintf(szResList, sizeof( szResList ), "%s%s.lst", g_szReslistDir, com_token );
					_strlwr( szResList );
					Q_FixSlashes( szResList );

					if ( !g_pFileSystem->FileExists( szResList ) )
					{
						vprint( 0, "Couldn't find %s\n", szResList );
						continue;
					}

					UnusedContent::CUtlSymbol sym = g_Analysis.symbols.AddString( szResList );
					resfiles.AddToTail( sym );

				}
			}
			delete[] pStart;
		}

		g_pFileSystem->Close(resfilehandle);
	}
	else
	{
		Error( "Unable to open reslist file %s\n", resfile );
		exit( -1 );
	}

	if ( g_pFileSystem->FileExists( CFmtStr( "%sall.lst", g_szReslistDir ) ) )
	{
		UnusedContent::CUtlSymbol sym = g_Analysis.symbols.AddString( CFmtStr( "%sall.lst", g_szReslistDir ) );
		resfiles.AddToTail( sym );
	}

	if ( g_pFileSystem->FileExists( CFmtStr( "%sengine.lst", g_szReslistDir ) ) )
	{
		UnusedContent::CUtlSymbol sym = g_Analysis.symbols.AddString( CFmtStr( "%sengine.lst", g_szReslistDir ) );
		resfiles.AddToTail( sym );
	}

	// Do we have any resfiles?
	if ( resfiles.Count() <= 0 )
	{
		vprint( 0, "%s didn't have any actual .lst files in the reslists folder, have you run the engine with %s\n", resfile,
			"-makereslists -usereslistfile maplist.txt" );
		return false;
	}

	vprint( 0, "Parsed %i reslist files\n", resfiles.Count() );

	// Now load in each res file
	int c = resfiles.Count();
	for ( int i = 0; i < c; ++i )
	{
		UnusedContent::CUtlSymbol& filename = resfiles[ i ];
		char fn[ 256 ];
		Q_strncpy( fn, g_Analysis.symbols.String( filename ), sizeof( fn ) );

		ParseFilesFromResList( filename, files, fn );
	}


	return true;
}
예제 #24
0
//-----------------------------------------------------------------------------
// Purpose: Sends Hammer an update to the current position
//-----------------------------------------------------------------------------
void NWCEdit::UpdateEntityPosition( CBaseEntity *pEntity )
{
	const Vector &newPos = pEntity->GetAbsOrigin();
	const QAngle &newAng = pEntity->GetAbsAngles();

	DevMsg( 1, "%s\n   origin %f %f %f\n   angles %f %f %f\n", pEntity->GetClassname(), newPos.x, newPos.y, newPos.z, newAng.x, newAng.y, newAng.z );
	if ( Ragdoll_IsPropRagdoll(pEntity) )
	{
		char tmp[2048];
		Ragdoll_GetAngleOverrideString( tmp, sizeof(tmp), pEntity );
		DevMsg( 1, "pose: %s\n", tmp );
	}

	if ( !(pEntity->ObjectCaps() & FCAP_WCEDIT_POSITION) )
		return;
	
	// can't do this unless in edit mode
	if ( !engine->IsInEditMode() )
		return;

	int entIndex = pEntity->entindex();
	Vector pos = g_EntityPositions[entIndex];
	EditorSendResult_t result = Editor_BadCommand;
	const char *pClassname = STRING(g_EntityClassnames[entIndex]);

	if ( pEntity->GetModel() && modelinfo->GetModelType(pEntity->GetModel()) == mod_brush )
	{
		QAngle xformAngles;
		RotationDelta( g_EntityOrientations[entIndex], newAng, &xformAngles );
		if ( xformAngles.Length() > 1e-4 )
		{
			result = Editor_RotateEntity( pClassname, pos.x, pos.y, pos.z, xformAngles );
		}
		else
		{
			// don't call through for an identity rotation, may just increase error
			result = Editor_OK;
		}
	}
	else
	{
		if ( Ragdoll_IsPropRagdoll(pEntity) )
		{
			char tmp[2048];
			Ragdoll_GetAngleOverrideString( tmp, sizeof(tmp), pEntity );
			result = Editor_SetKeyValue( pClassname, pos.x, pos.y, pos.z, "angleOverride", tmp );
			if ( result != Editor_OK )
				goto error;
		}
		result = Editor_SetKeyValue( pClassname, pos.x, pos.y, pos.z, "angles", CFmtStr("%f %f %f", newAng.x, newAng.y, newAng.z) );
	}
	if ( result != Editor_OK )
		goto error;

	result = Editor_SetKeyValue( pClassname, pos.x, pos.y, pos.z, "origin", CFmtStr("%f %f %f", newPos.x, newPos.y, newPos.z) );
	if ( result != Editor_OK )
		goto error;

	NDebugOverlay::EntityBounds(pEntity, 0, 255, 0, 0 ,5);
	// save the update
	RememberEntityPosition( pEntity );
	return;

error:
	NDebugOverlay::EntityBounds(pEntity, 255, 0, 0, 0 ,5);
}
예제 #25
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CTFWinPanel::FireGameEvent( IGameEvent * event )
{
	const char *pEventName = event->GetName();

	if ( Q_strcmp( "teamplay_round_start", pEventName ) == 0 )
	{
		m_bShouldBeVisible = false;
	}
	else if ( Q_strcmp( "teamplay_game_over", pEventName ) == 0 )
	{
		m_bShouldBeVisible = false;
	}
	else if ( Q_strcmp( "tf_game_over", pEventName ) == 0 )
	{
		m_bShouldBeVisible = false;
	}
	else if ( Q_strcmp( "teamplay_win_panel", pEventName ) == 0 )
	{
		if ( !g_PR )
			return;

		int iWinningTeam = event->GetInt( "winning_team" );
		int iWinReason = event->GetInt( "winreason" );
		int iFlagCapLimit = event->GetInt( "flagcaplimit" );
		bool bRoundComplete = (bool) event->GetInt( "round_complete" );
		int iRoundsRemaining = event->GetInt( "rounds_remaining" );

		LoadControlSettings( "resource/UI/WinPanel.res" );		
		InvalidateLayout( false, true );

		SetDialogVariable( "WinningTeamLabel", "" );
		SetDialogVariable( "AdvancingTeamLabel", "" );
		SetDialogVariable( "WinReasonLabel", "" );
		SetDialogVariable( "DetailsLabel", "" );

		vgui::ImagePanel *pImagePanelBG = dynamic_cast<vgui::ImagePanel *>( FindChildByName("WinPanelBG") );
		Assert( pImagePanelBG );
		if ( !pImagePanelBG )
			return;

		// set the appropriate background image and label text
		const char *pTeamLabel = NULL;
		const char *pTopPlayersLabel = NULL;
		const wchar_t *pLocalizedTeamName = NULL;
		// this is an area defense, but not a round win, if this was a successful defend until time limit but not a complete round
		bool bIsAreaDefense = ( ( WINREASON_DEFEND_UNTIL_TIME_LIMIT == iWinReason ) && !bRoundComplete );
		switch ( iWinningTeam )
		{
		case TF_TEAM_BLUE:
			pImagePanelBG->SetImage( "../hud/winpanel_blue_bg_main.vmt" );
			pTeamLabel = ( bRoundComplete ? "#Winpanel_BlueWins" : ( bIsAreaDefense ? "#Winpanel_BlueDefends" : "#Winpanel_BlueAdvances" ) );
			pTopPlayersLabel = "#Winpanel_BlueMVPs";
			pLocalizedTeamName =  g_pVGuiLocalize->Find( "TF_BlueTeam_Name" );
			break;
		case TF_TEAM_RED:
			pImagePanelBG->SetImage( "../hud/winpanel_red_bg_main.vmt" );
			pTeamLabel = ( bRoundComplete ? "#Winpanel_RedWins" : ( bIsAreaDefense ? "#Winpanel_RedDefends" : "#Winpanel_RedAdvances" ) );
			pTopPlayersLabel = "#Winpanel_RedMVPs";
			pLocalizedTeamName =  g_pVGuiLocalize->Find( "TF_RedTeam_Name" );
			break;
		case TEAM_UNASSIGNED:	// stalemate
			pImagePanelBG->SetImage( "../hud/winpanel_black_bg_main.vmt" );
			pTeamLabel = "#Winpanel_Stalemate";
			pTopPlayersLabel = "#Winpanel_TopPlayers";
			break;
		default:
			Assert( false );
			break;
		}

		SetDialogVariable( bRoundComplete ? "WinningTeamLabel" : "AdvancingTeamLabel", g_pVGuiLocalize->Find( pTeamLabel ) );
		SetDialogVariable( "TopPlayersLabel", g_pVGuiLocalize->Find( pTopPlayersLabel ) );

		wchar_t wzWinReason[256]=L"";
		switch ( iWinReason )
		{
		case WINREASON_ALL_POINTS_CAPTURED:
			g_pVGuiLocalize->ConstructString( wzWinReason, sizeof( wzWinReason ), g_pVGuiLocalize->Find( "#Winreason_AllPointsCaptured" ), 1, pLocalizedTeamName );
			break;
		case WINREASON_FLAG_CAPTURE_LIMIT:
			{
				wchar_t wzFlagCaptureLimit[16];
				_snwprintf( wzFlagCaptureLimit, ARRAYSIZE( wzFlagCaptureLimit), L"%i", iFlagCapLimit );
				g_pVGuiLocalize->ConstructString( wzWinReason, sizeof( wzWinReason ), g_pVGuiLocalize->Find( "#Winreason_FlagCaptureLimit" ), 2, 
					pLocalizedTeamName, wzFlagCaptureLimit );
			}			
			break;
		case WINREASON_OPPONENTS_DEAD:
			g_pVGuiLocalize->ConstructString( wzWinReason, sizeof( wzWinReason ), g_pVGuiLocalize->Find( "#Winreason_OpponentsDead" ), 1, pLocalizedTeamName );
			break;
		case WINREASON_DEFEND_UNTIL_TIME_LIMIT:
			g_pVGuiLocalize->ConstructString( wzWinReason, sizeof( wzWinReason ), g_pVGuiLocalize->Find( "#Winreason_DefendedUntilTimeLimit" ), 1, pLocalizedTeamName );
			break;
		case WINREASON_STALEMATE:
			g_pVGuiLocalize->ConstructString( wzWinReason, sizeof( wzWinReason ), g_pVGuiLocalize->Find( "#Winreason_Stalemate" ), 0 );
			break;	
		default:
			Assert( false );
			break;
		}
		SetDialogVariable( "WinReasonLabel", wzWinReason );

		if ( !bRoundComplete && ( WINREASON_STALEMATE != iWinReason ) )
		{			
			// if this was a mini-round, show # of capture points remaining
			wchar_t wzNumCapturesRemaining[16];
			wchar_t wzCapturesRemainingMsg[256]=L"";
			_snwprintf( wzNumCapturesRemaining, ARRAYSIZE( wzNumCapturesRemaining ), L"%i", iRoundsRemaining );
			g_pVGuiLocalize->ConstructString( wzCapturesRemainingMsg, sizeof( wzCapturesRemainingMsg ), 
				g_pVGuiLocalize->Find( 1 == iRoundsRemaining ? "#Winpanel_CapturePointRemaining" : "Winpanel_CapturePointsRemaining" ),
				1, wzNumCapturesRemaining );
			SetDialogVariable( "DetailsLabel", wzCapturesRemainingMsg );
		}
		else if ( ( WINREASON_ALL_POINTS_CAPTURED == iWinReason ) || ( WINREASON_FLAG_CAPTURE_LIMIT == iWinReason ) )
		{
			// if this was a full round that ended with point capture or flag capture, show the winning cappers
			const char *pCappers = event->GetString( "cappers" );
			int iCappers = Q_strlen( pCappers );
			if ( iCappers > 0 )
			{	
				char szPlayerNames[256]="";
				wchar_t wzPlayerNames[256]=L"";
				wchar_t wzCapMsg[512]=L"";
				for ( int i = 0; i < iCappers; i++ )
				{
					Q_strncat( szPlayerNames, g_PR->GetPlayerName( (int) pCappers[i] ), ARRAYSIZE( szPlayerNames ) );
					if ( i < iCappers - 1 )
					{
						Q_strncat( szPlayerNames, ", ", ARRAYSIZE( szPlayerNames ) );
					}
				}
				g_pVGuiLocalize->ConvertANSIToUnicode( szPlayerNames, wzPlayerNames, sizeof( wzPlayerNames ) );
				g_pVGuiLocalize->ConstructString( wzCapMsg, sizeof( wzCapMsg ), g_pVGuiLocalize->Find( "#Winpanel_WinningCapture" ), 1, wzPlayerNames );
				SetDialogVariable( "DetailsLabel", wzCapMsg );
			}
		}

		// get the current & previous team scores
		int iBlueTeamPrevScore = event->GetInt( "blue_score_prev", 0 );
		int iRedTeamPrevScore = event->GetInt( "red_score_prev", 0 );
		m_iBlueTeamScore = event->GetInt( "blue_score", 0 );
		m_iRedTeamScore = event->GetInt( "red_score", 0 );
		
		if ( m_pTeamScorePanel )
		{			
			if ( bRoundComplete )
			{
				// set the previous team scores in scoreboard
				m_pTeamScorePanel->SetDialogVariable( "blueteamscore", iBlueTeamPrevScore );
				m_pTeamScorePanel->SetDialogVariable( "redteamscore", iRedTeamPrevScore );

				if ( ( m_iBlueTeamScore != iBlueTeamPrevScore ) || ( m_iRedTeamScore != iRedTeamPrevScore ) )
				{
					// if the new scores are different, set ourselves to update the scoreboard to the new values after a short delay, so players
					// see the scores tick up
					m_flTimeUpdateTeamScore = gpGlobals->curtime + 2.0f;
				}
			}
			// only show team scores if round is complete
			m_pTeamScorePanel->SetVisible( bRoundComplete );
		}

		C_TF_PlayerResource *tf_PR = dynamic_cast<C_TF_PlayerResource *>( g_PR );
		if ( !tf_PR )
			return;

		// look for the top 3 players sent in the event
		for ( int i = 1; i <= 3; i++ )
		{
			bool bShow = false;
			char szPlayerIndexVal[64]="", szPlayerScoreVal[64]="";
			// get player index and round points from the event
			Q_snprintf( szPlayerIndexVal, ARRAYSIZE( szPlayerIndexVal ), "player_%d", i );
			Q_snprintf( szPlayerScoreVal, ARRAYSIZE( szPlayerScoreVal ), "player_%d_points", i );
			int iPlayerIndex = event->GetInt( szPlayerIndexVal, 0 );
			int iRoundScore = event->GetInt( szPlayerScoreVal, 0 );
			// round score of 0 means no player to show for that position (not enough players, or didn't score any points that round)
			if ( iRoundScore > 0 )
				bShow = true;

#if !defined( _X360 )
			CAvatarImagePanel *pPlayerAvatar = dynamic_cast<CAvatarImagePanel *>( FindChildByName( CFmtStr( "Player%dAvatar", i ) ) );

			if ( pPlayerAvatar )
			{
				if ( bShow )
				{
					CBasePlayer *pPlayer = UTIL_PlayerByIndex( iPlayerIndex );
					pPlayerAvatar->SetPlayer( pPlayer );
				}

				pPlayerAvatar->SetVisible( bShow );
			}
#endif
			vgui::Label *pPlayerName = dynamic_cast<Label *>( FindChildByName( CFmtStr( "Player%dName", i ) ) );
			vgui::Label *pPlayerClass = dynamic_cast<Label *>( FindChildByName( CFmtStr( "Player%dClass", i ) ) );
			vgui::Label *pPlayerScore = dynamic_cast<Label *>( FindChildByName( CFmtStr( "Player%dScore", i ) ) );
			
			if ( !pPlayerName || !pPlayerClass || !pPlayerScore )
				return;

			if ( bShow )
			{
				// set the player labels to team color
				Color clr = g_PR->GetTeamColor( g_PR->GetTeam( iPlayerIndex ) );				
				pPlayerName->SetFgColor( clr );
				pPlayerClass->SetFgColor( clr );
				pPlayerScore->SetFgColor( clr );

				// set label contents
				pPlayerName->SetText( g_PR->GetPlayerName( iPlayerIndex ) );
				pPlayerClass->SetText( g_aPlayerClassNames[tf_PR->GetPlayerClass( iPlayerIndex )] );
				pPlayerScore->SetText( CFmtStr( "%d", iRoundScore ) );
			}

			// show or hide labels for this player position
			pPlayerName->SetVisible( bShow );
			pPlayerClass->SetVisible( bShow );
			pPlayerScore->SetVisible( bShow );
		}

		m_bShouldBeVisible = true;

		MoveToFront();
	}
}
예제 #26
0
void CASWJukeboxPlaylist::PlayRandomTrack( float fadeInTime /*= 1.0f*/, const char *szDefaultTrack /*= null */ )
{
	// Choose a random track to play
	int count = m_CombatMusicPlaylist.Count();
	int index = 0;
	CSoundPatch* pNewSound = null;
	CLocalPlayerFilter filter;
	if( count == 0 )
	{
		DevMsg( "JUKEBOX: Playing Track: %s%s.mp3\n", "*#music/_mp3/", szDefaultTrack );
		if( !Q_strcmp("", szDefaultTrack ) )
			return;
		pNewSound = CSoundEnvelopeController::GetController().SoundCreate( filter, 0, CHAN_STATIC, szDefaultTrack, SNDLVL_NONE );
	}
	else 
	{
		// If there's more than one track, randomize it so the current track doesn't repeat itself
		if( count > 1 )
		{
			do {
				index = rand() % (count );
			} while( index == m_iCurrentTrack );
		}

		DevMsg( "JUKEBOX: Playing Track: %s%s.mp3\n", "*#music/_mp3/", m_CombatMusicPlaylist[index].m_szHexname );
		pNewSound = CSoundEnvelopeController::GetController().SoundCreate( filter, 0, CHAN_STATIC, CFmtStr( "%s%s.mp3", "*#music/_mp3/", m_CombatMusicPlaylist[index].m_szHexname), SNDLVL_NONE );
	}

	if( !pNewSound )
	{
		return;
	}

	// If combat music is playing and there's more than one track, fade it out and play the new music once it's done
	if( m_pCombatMusic )
	{
		if( count == 1 )
			return;

		StopTrack( false, fadeInTime );
		CSoundEnvelopeController::GetController().Play( pNewSound, 0.0f, 100, 1.0f );	
	}
	else
	{
		CSoundEnvelopeController::GetController().Play( pNewSound, 0.0f, 100 );	
	}
	CSoundEnvelopeController::GetController().SoundChangeVolume( pNewSound, 1.0f, fadeInTime );

	m_pCombatMusic = pNewSound;
	m_iCurrentTrack = index;
}
예제 #27
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void C_ParticleSystem::PostDataUpdate( DataUpdateType_t updateType )
{
	BaseClass::PostDataUpdate( updateType );

	// Always restart if just created and updated
	// FIXME: Does this play fairly with PVS?
	if ( updateType == DATA_UPDATE_CREATED )
	{
		// TODO: !!HACK HACK HACK!! .PSF files should be loaded/refcounted through the CParticleSystemMgr (ala .PCFs).
		//       The current code will duplicate a given .PSF file in memory for every info_particle_system that uses it!
		if ( m_szSnapshotFileName[0] )
		{
			m_pSnapshot = new CParticleSnapshot();
			if ( !m_pSnapshot->Unserialize( CFmtStr( "particles/%s.psf", m_szSnapshotFileName ) ) )
			{
				delete m_pSnapshot;
				m_pSnapshot = NULL;
			}
		}

		if ( m_bActive )
		{
			// Delayed here so that we don't get invalid abs queries on level init with active particle systems
			SetNextClientThink( gpGlobals->curtime );
		}
	}
	else
	{
		if ( m_bOldActive != m_bActive )
		{
			if ( m_bActive )
			{
				// Delayed here so that we don't get invalid abs queries on level init with active particle systems
				SetNextClientThink( gpGlobals->curtime );
			}
			else
			{
				switch( m_nStopType )
				{
				case STOP_NORMAL:
					{
						ParticleProp()->StopEmission();
					}
					break;
				case STOP_DESTROY_IMMEDIATELY:
					{
						ParticleProp()->StopEmissionAndDestroyImmediately();
					}
					break;
				case STOP_PLAY_ENDCAP:
					{
						ParticleProp()->StopEmission( NULL, false, false, false, true);
					}
					break;
				}
			}
		}

		if( m_bActive && ParticleProp()->IsValidEffect( m_pEffect ) )
		{
			//server controlled control points (variables in particle effects instead of literal follow points)
			for( int i = 0; i != ARRAYSIZE( m_iServerControlPointAssignments ); ++i )
			{
				if( m_iServerControlPointAssignments[i] != 255 )
				{
					m_pEffect->SetControlPoint( m_iServerControlPointAssignments[i], m_vServerControlPoints[i] );
				}
				else
				{
					break;
				}
			}
		}
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : argc - 
//			argv[] - 
// Output : int
//-----------------------------------------------------------------------------
int main( int argc, char* argv[] )
{
	SpewOutputFunc( SpewFunc );
	SpewActivate( "unusedcontent", 2 );

	CommandLine()->CreateCmdLine( argc, argv );

	int i=1;
	for ( i ; i<argc ; i++)
	{
		if ( argv[ i ][ 0 ] == '-' )
		{
			switch( argv[ i ][ 1 ] )
			{
			case 'l':
				uselogfile = true;
				break;
			case 'v':
				verbose = true;
				break;
			case 'r':
				showreferencedfiles = true;
				break;
			case 'd':
				spewdeletions = true;
				break;
			case 'i':
				immediatedelete = true;
				break;
			case 'w':
				printwhitelist = true;
				break;
			case 'm':
				showmapfileusage = true;
				break;
			case 'g':
				// Just skip -game
				Assert( !Q_stricmp( argv[ i ], "-game" ) );
				++i;
				break;
			case 'f':
				// grab reslists folder
				{
					++i;
					Q_strncpy( g_szReslistDir, argv[ i ], sizeof( g_szReslistDir ) );
					Q_strlower( g_szReslistDir );
					Q_FixSlashes( g_szReslistDir );
					Q_AppendSlash( g_szReslistDir, sizeof( g_szReslistDir ) );
					
				}
				break;
			default:
				printusage();
				break;
			}
		}
	}

	if ( argc < 3 || ( i != argc ) )
	{
		PrintHeader();
		printusage();
		return 0;
	}

	CheckLogFile();

	PrintHeader();

	vprint( 0, "    Using reslist dir '%s'\n", g_szReslistDir );

	vprint( 0, "    Looking for extraneous content...\n" );

	char resfile[ 256 ];
	strcpy( resfile, argv[ i - 1 ] );

	vprint( 0, "    Comparing results of resfile (%s) with files under current directory...\n",	resfile );

	char workingdir[ 256 ];
	workingdir[0] = 0;
	Q_getwd( workingdir, sizeof( workingdir ) );

	// If they didn't specify -game on the command line, use VPROJECT.
	CmdLib_InitFileSystem( workingdir );

	filesystem = (IFileSystem *)(CmdLib_GetFileSystemFactory()( FILESYSTEM_INTERFACE_VERSION, NULL ));
	if ( !filesystem )
	{
		AssertMsg( 0, "Failed to create/get IFileSystem" );
		return 1;
	}

	g_pFullFileSystem->RemoveAllSearchPaths();
	g_pFullFileSystem->AddSearchPath(gamedir, "GAME");

	Q_strlower( gamedir );
	Q_FixSlashes( gamedir );

	//
	//ProcessMaterialsDirectory( vmtdir );

	// find out the mod dir name
	Q_strncpy( modname, gamedir, sizeof(modname) );
	modname[ strlen(modname) - 1] = 0;

	if ( strrchr( modname,  '\\' ) )
	{
		Q_strncpy( modname, strrchr( modname, '\\' ) + 1, sizeof(modname) );
	}
	else
	{
		Q_strncpy( modname, "", sizeof(modname) );
	}
	vprint( 1, "Mod Name:%s\n", modname);


	BuildCheckdirList();
	BuildWhiteList();

	vprint( 0, "Building aggregate file list from resfile output\n" );
	CUtlRBTree< ReferencedFile, int > referencedfiles( 0, 0, RefFileLessFunc );
	CUtlVector< UnusedContent::CUtlSymbol >	resfiles;

	BuildReferencedFileList( resfiles, referencedfiles, resfile );

	vprint( 0, "found %i files\n\n", referencedfiles.Count() );

	vprint( 0, "Building list of all game content files\n" );
	CUtlVector< FileEntry > contentfiles;
	CUtlVector< FileEntry > otherfiles;
	BuildFileList( 0, contentfiles, &otherfiles, "", 0 );
	vprint( 0, "found %i files in content tree\n\n", contentfiles.Count() );

	Correlate( referencedfiles, contentfiles, modname );

	// now output the files not referenced in the whitelist or general reslists
	filesystem->RemoveFile( CFmtStr( "%sunreferenced_files.lst", g_szReslistDir ), "GAME" );
	int c = otherfiles.Count();
	for ( i = 0; i < c; ++i )
	{
		FileEntry & entry = otherfiles[ i ];
		char const *name = g_Analysis.symbols.String( entry.sym );

		logprint( CFmtStr( "%sunreferenced_files.lst", g_szReslistDir ), "\"%s\\%s\"\n", modname, name );
	}

	// also include the files from deletions.bat, as we don't actually run that now
	c = contentfiles.Count();
	for ( i = 0; i < c; ++i )
	{
		FileEntry & entry = contentfiles[ i ];
		if ( entry.referenced != REFERENCED_NO )
			continue;

		char const *fn = g_Analysis.symbols.String( entry.sym );
		logprint( CFmtStr( "%sunreferenced_files.lst", g_szReslistDir ), "\"%s\\%s\"\n", modname, fn );
	}

	FileSystem_Term();

	return 0;
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CTFStatPanel::ShowStatPanel( int iClass, int iTeam, int iCurStatValue, TFStatType_t statType, RecordBreakType_t recordBreakType,
								 bool bAlive )
{
	ClassStats_t &classStats = GetClassStats( iClass );
	vgui::Label *pLabel = dynamic_cast<Label *>( FindChildByName( "summaryLabel" ) );
	if ( !pLabel )
		return;

	const char *pRecordTextSuffix[RECORDBREAK_MAX] = { "", "close", "tie", "best" };

	const char *pLocalizedTitle = bAlive ? "#StatPanel_Title_Alive" : "#StatPanel_Title_Dead";
	SetDialogVariable( "title", g_pVGuiLocalize->Find( pLocalizedTitle ) );
	SetDialogVariable( "stattextlarge", "" );
	SetDialogVariable( "stattextsmall", "" );
	if ( recordBreakType == RECORDBREAK_CLOSE )
	{		
		// if we are displaying that the player got close to a record, show current & best values
		char szCur[32],szBest[32];
		wchar_t wzCur[32],wzBest[32];
		GetStatValueAsString( iCurStatValue, statType, szCur, ARRAYSIZE( szCur ) );
		GetStatValueAsString( classStats.max.m_iStat[statType], statType, szBest, ARRAYSIZE( szBest ) );
		g_pVGuiLocalize->ConvertANSIToUnicode( szCur, wzCur, sizeof( wzCur ) );
		g_pVGuiLocalize->ConvertANSIToUnicode( szBest, wzBest, sizeof( wzBest ) );
		wchar_t *wzFormat = g_pVGuiLocalize->Find( "#StatPanel_Format_Close" );
		wchar_t wzText[256];
		g_pVGuiLocalize->ConstructString( wzText, sizeof( wzText ), wzFormat, 2, wzCur, wzBest );
		SetDialogVariable( "stattextsmall", wzText );
	}
	else
	{
		// player broke or tied a record, just show current value
		char szValue[32];
		GetStatValueAsString( iCurStatValue, statType, szValue, ARRAYSIZE( szValue ) );
		SetDialogVariable( "stattextlarge", szValue );
	}

	SetDialogVariable( "statdesc", g_pVGuiLocalize->Find( CFmtStr( "%s_%s", g_szLocalizedRecordText[statType], 
		pRecordTextSuffix[recordBreakType] ) ) );

	// Set the class name. We can't use a dialog variable because it's a string that's already
	// been set using a dialog variable, and apparently we don't support nested dialog variables.
	wchar_t szOriginalSummary[ 256 ];
	wchar_t szSummary[ 256 ];

	// This is the field that "statdesc" completed for us
	pLabel->GetText( szOriginalSummary, sizeof( szOriginalSummary ) );
	const wchar_t *pszPlayerClass = L"undefined";

	if ( ( iClass >= TF_FIRST_NORMAL_CLASS ) && ( iClass <= TF_LAST_NORMAL_CLASS ) )
	{
		pszPlayerClass = g_pVGuiLocalize->Find( g_aPlayerClassNames[ iClass ] );
	}

	g_pVGuiLocalize->ConstructString( szSummary, sizeof( szSummary ), szOriginalSummary, 1, pszPlayerClass );

	pLabel->SetText( szSummary );

	if ( m_pClassImage )
	{
		m_pClassImage->SetClass( iTeam, iClass, 0 );
	}

	Show();
}
void Correlate( CUtlRBTree< ReferencedFile, int >& referencedfiles, CUtlVector< FileEntry >& contentfiles, const char *modname )
{
	int i;
	int c = contentfiles.Count();
	
	double totalDiskSize = 0;
	double totalReferencedDiskSize = 0;
	double totalWhiteListDiskSize = 0;

	for ( i = 0; i < c; ++i )
	{
		totalDiskSize += contentfiles [ i ].size;
	}

	vprint( 0, "Content tree size on disk %s\n", Q_pretifymem( totalDiskSize, 3 ) );
	
	// Analysis is to walk tree and see which files on disk are referenced in the .lst files
	// Need a fast lookup from file symbol to referenced list
	CUtlRBTree< ReferencedFile, int >	tree( 0, 0, ReferencedFileLessFunc );
	c = referencedfiles.Count();
	for ( i = 0 ; i < c; ++i )
	{
		tree.Insert( referencedfiles[ i ] );
	}

	// Now walk the on disk file and see check off resources which are in referenced
	c = contentfiles.Count();
	int invalidindex = tree.InvalidIndex();
	unsigned int refcounted = 0;
	unsigned int whitelisted = 0;

	filesystem->RemoveFile( CFmtStr( "%swhitelist.lst", g_szReslistDir ), "GAME" );

	for ( i = 0; i < c; ++i )
	{
		FileEntry & entry = contentfiles[ i ];

		ReferencedFile foo;
		foo.sym = entry.sym;

		bool gameref = tree.Find( foo ) != invalidindex;
		char const *fn = g_Analysis.symbols.String( entry.sym );

		bool whitelist = g_WhiteList.Find( entry.sym ) != g_WhiteList.InvalidIndex();

		if ( gameref || whitelist )
		{
			entry.referenced = gameref ? REFERENCED_GAME : REFERENCED_WHITELIST;
			totalReferencedDiskSize += entry.size;
			if ( entry.referenced == REFERENCED_WHITELIST )
			{
				logprint( CFmtStr( "%swhitelist.lst", g_szReslistDir ), "\"%s\\%s\"\n", modname, fn );

				totalWhiteListDiskSize += entry.size;
				++whitelisted;
			}
			++refcounted;
		}
	}

	vprint( 0, "Found %i referenced (%i whitelist) files in tree, %s\n", refcounted, whitelisted, Q_pretifymem( totalReferencedDiskSize, 2 ) );
	vprint( 0, "%s appear unused\n", Q_pretifymem( totalDiskSize - totalReferencedDiskSize, 2 ) );

	// Now sort and dump the unreferenced ones..
	vprint( 0, "Sorting unreferenced files list...\n" );

	CUtlRBTree< FileEntry, int >	unreftree( 0, 0, FileEntryLessFunc );
	for ( i = 0; i < c; ++i )
	{
		FileEntry & entry = contentfiles[ i ];
		if ( entry.referenced != REFERENCED_NO )
			continue;

		unreftree.Insert( entry );
	}

	// Now walk the unref tree in order
	i = unreftree.FirstInorder();
	invalidindex = unreftree.InvalidIndex();
	int index = 0;
	while ( i != invalidindex )
	{
		FileEntry & entry = unreftree[ i ];

		if ( showreferencedfiles )
		{
			vprint( 1, "%6i %12s: %s\n", ++index, Q_pretifymem( entry.size, 2 ), g_Analysis.symbols.String( entry.sym ) );
		}
		
		i = unreftree.NextInorder( i );
	}

	if ( showmapfileusage )
	{
		vprint( 0, "Writing referenced.csv...\n" );

		// Now walk the list of referenced files and print out how many and which maps reference them
		i = tree.FirstInorder();
		invalidindex = tree.InvalidIndex();
		index = 0;
		while ( i != invalidindex )
		{
			ReferencedFile & entry = tree[ i ];

			char ext[ 32 ];
			Q_ExtractFileExtension( g_Analysis.symbols.String( entry.sym ), ext, sizeof( ext ) );

			logprint( "referenced.csv", "\"%s\",\"%s\",%d", g_Analysis.symbols.String( entry.sym ), ext, entry.maplist.Count() );

			int mapcount = entry.maplist.Count();
			for ( int j = 0 ; j < mapcount; ++j )
			{
				char basemap[ 128 ];
				Q_FileBase( g_Analysis.symbols.String( entry.maplist[ j ] ), basemap, sizeof( basemap ) );
				logprint( "referenced.csv", ",\"%s\"", basemap );
			}

			logprint( "referenced.csv", "\n" );
			
			i = tree.NextInorder( i );
		}
	}


	vprint( 0, "\nBuilding directory summary list...\n" );

	// Now build summaries by root branch off of gamedir (e.g., for sound, materials, models, etc.)
	CUtlDict< DirEntry, int > directories;
	invalidindex = directories.InvalidIndex();
	for ( i = 0; i < c; ++i )
	{
		FileEntry & entry = contentfiles[ i ];

		// Get the dir name
		char const *dirname = g_Analysis.symbols.String( entry.sym );

		const char *backslash = strstr( dirname, "\\" );

		char dir[ 256 ];
		if ( !backslash )
		{
			dir[0] = 0;
		}
		else
		{
			Q_strncpy( dir, dirname, backslash - dirname + 1);
		}

		
		int idx = directories.Find( dir );
		if ( idx == invalidindex )
		{
			DirEntry foo;
			idx = directories.Insert( dir, foo );
		}

		DirEntry & de = directories[ idx ];
		de.total += entry.size;
		if ( entry.referenced == REFERENCED_NO )
		{
			de.unreferenced += entry.size;
		}
		if ( entry.referenced == REFERENCED_WHITELIST )
		{
			de.whitelist += entry.size;
		}
	}

	if ( spewdeletions )
	{
		// Spew deletion commands to console
		if ( immediatedelete )
		{
			vprint( 0, "\n\nDeleting files...\n" );
		}
		else
		{
			vprint( 0, "\n\nGenerating deletions.bat\n" );
		}

		i = unreftree.FirstInorder();
		invalidindex = unreftree.InvalidIndex();
		float deletionSize = 0.0f;
		int deletionCount = 0;

		while ( i != invalidindex )
		{
			FileEntry & entry = unreftree[ i ];
			i = unreftree.NextInorder( i );

			// Don't delete stuff that's in the white list
			if ( g_WhiteList.Find( entry.sym ) != g_WhiteList.InvalidIndex() )
			{
				if ( verbose )
				{
					vprint( 0, "whitelist blocked deletion of %s\n", g_Analysis.symbols.String( entry.sym ) );
				}
				continue;
			}

			++deletionCount;
			deletionSize += entry.size;

			if ( immediatedelete ) 
			{
				if ( _chmod( g_Analysis.symbols.String( entry.sym ), _S_IWRITE ) == -1 )
				{
					vprint( 0, "Could not find file %s\n", g_Analysis.symbols.String( entry.sym ) );
				}
				if ( _unlink( g_Analysis.symbols.String( entry.sym ) ) == -1 )
				{
					vprint( 0, "Could not delete file %s\n", g_Analysis.symbols.String( entry.sym ) );
				}

				if ( deletionCount % 1000 == 0 )
				{
					vprint( 0, "...deleted %i files\n", deletionCount );
				}
			}
			else
			{
				logprint( "deletions.bat", "del \"%s\" /f\n",  g_Analysis.symbols.String( entry.sym ) );
			}
		}

		vprint( 0, "\nFile deletion (%d files, %s)\n\n", deletionCount, Q_pretifymem(deletionSize, 2) );
	}

	double grand_total = 0;
	double grand_total_unref = 0;
	double grand_total_white = 0;

	char totalstring[ 20 ];
	char unrefstring[ 20 ];
	char refstring[ 20 ];
	char whiteliststring[ 20 ];

	vprint( 0, "---------------------------------------- Summary ----------------------------------------\n" );

	vprint( 0, "% 15s               % 15s               % 15s               % 15s %12s\n",
		"Referenced",
		"WhiteListed",
		"Unreferenced",
		"Total",
		"Directory" );

	// Now walk the dictionary in order
	i = directories.First();
	while ( i != invalidindex )
	{
		DirEntry & de = directories[ i ];

		double remainder = de.total - de.unreferenced;

		float percent_unref = 0.0f;
		float percent_white = 0.0f;
		if ( de.total > 0 )
		{
			percent_unref = 100.0f * (float)de.unreferenced / (float)de.total;
			percent_white = 100.0f * (float)de.whitelist / (float)de.total;
		}

		Q_strncpy( totalstring, Q_pretifymem( de.total, 2 ), sizeof( totalstring ) );
		Q_strncpy( unrefstring, Q_pretifymem( de.unreferenced, 2 ), sizeof( unrefstring ) );
		Q_strncpy( refstring, Q_pretifymem( remainder, 2 ), sizeof( refstring ) );
		Q_strncpy( whiteliststring, Q_pretifymem( de.whitelist, 2 ), sizeof( whiteliststring ) );

		vprint( 0, "%15s (%8.3f%%)   %15s (%8.3f%%)   %15s (%8.3f%%)   %15s => dir: %s\n",
			refstring, 100.0f - percent_unref, whiteliststring, percent_white, unrefstring, percent_unref, totalstring, directories.GetElementName( i ) );

		grand_total += de.total;
		grand_total_unref += de.unreferenced;
		grand_total_white += de.whitelist;

		i = directories.Next( i );
	}

	Q_strncpy( totalstring, Q_pretifymem( grand_total, 2 ), sizeof( totalstring ) );
	Q_strncpy( unrefstring, Q_pretifymem( grand_total_unref, 2 ), sizeof( unrefstring ) );
	Q_strncpy( refstring, Q_pretifymem( grand_total - grand_total_unref, 2 ), sizeof( refstring ) );
	Q_strncpy( whiteliststring, Q_pretifymem( grand_total_white, 2 ), sizeof( whiteliststring ) );

	double percent_unref = 100.0 * grand_total_unref / grand_total;
	double percent_white = 100.0 * grand_total_white / grand_total;

	vprint( 0, "-----------------------------------------------------------------------------------------\n" );
	vprint( 0, "%15s (%8.3f%%)   %15s (%8.3f%%)   %15s (%8.3f%%)   %15s\n",
		refstring, 100.0f - percent_unref, whiteliststring, percent_white, unrefstring, percent_unref, totalstring );
}