static cell_t smn_StringToKeyValues(IPluginContext *pCtx, const cell_t *params)
{
	Handle_t hndl = static_cast<Handle_t>(params[1]);
	HandleError herr;
	HandleSecurity sec;
	KeyValueStack *pStk;
	KeyValues *kv;

	sec.pOwner = NULL;
	sec.pIdentity = g_pCoreIdent;

	if ((herr=handlesys->ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
		!= HandleError_None)
	{
		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
	}

	char *buffer;
	char *resourceName;
	pCtx->LocalToString(params[2], &buffer);
	pCtx->LocalToString(params[3], &resourceName);

	kv = pStk->pCurRoot.front();
	return kv->LoadFromBuffer(resourceName, buffer);
}
//
// This method handles parsing a single file, it can be called
//  many times if a wildcard path was passed to InitParser.
// Input: pszFilePath - FS path to a KeyValue file for parsing.
//		  bWildcard - Is this file the only one to be parsed? or will more come...
//
bool CScriptParser::ParseFile( const char *pszFilePath )
{
	// Load the file into a buffer (null-terminated)
	char *buffer = (char*) UTIL_LoadFileForMe( pszFilePath, NULL );
	if ( !buffer )
		return false;

	// If we are encrypted, decrypt us
	const char *fileName = Q_UnqualifiedFileName( pszFilePath );
	if( CompareExtensions( fileName, GetEncryptedEXT() ) )
		UTIL_DecodeICE( (unsigned char*)buffer, Q_strlen(buffer), g_pGameRules->GetEncryptionKey() );

	// Remove the extension
	char fileNameNoExt[64];
	Q_StripExtension( fileName, fileNameNoExt, 64 );

	KeyValues *pKV = new KeyValues( fileNameNoExt );
	if( !pKV->LoadFromBuffer( fileNameNoExt, buffer ) )
	{
		pKV->deleteThis();
		delete [] buffer;
		return false;
	}

	Parse( pKV, fileNameNoExt );

	pKV->deleteThis();
	delete[] buffer;
	return true;
}
static float FindPoseCycle( StudioModel *model, int sequence )
{
	float cycle = 0.0f;
	if ( !model->GetStudioHdr() )
		return cycle;

	KeyValues *seqKeyValues = new KeyValues("");
	if ( seqKeyValues->LoadFromBuffer( model->GetFileName( ), model->GetKeyValueText( sequence ) ) )
	{
		// Do we have a build point section?
		KeyValues *pkvAllFaceposer = seqKeyValues->FindKey("faceposer");
		if ( pkvAllFaceposer )
		{
			int thumbnail_frame = pkvAllFaceposer->GetInt( "thumbnail_frame", 0 );
			if ( thumbnail_frame )
			{
				// Convert frame to cycle if we have valid data
				int maxFrame = model->GetNumFrames( sequence ) - 1;

				if ( maxFrame > 0 )
				{
					cycle = thumbnail_frame / (float)maxFrame;
				}
			}
		}
	}

	seqKeyValues->deleteThis();

	return cycle;
}
//------------------------------------------------------------------------------
// Purpose:
//------------------------------------------------------------------------------
bool CNPC_Furniture::CreateVPhysics( void )
{
#ifndef HL2_DLL
	return false;
#endif

	if ( !m_BoneFollowerManager.GetNumBoneFollowers() )
	{
		KeyValues *modelKeyValues = new KeyValues("");
		if ( modelKeyValues->LoadFromBuffer( modelinfo->GetModelName( GetModel() ), modelinfo->GetModelKeyValueText( GetModel() ) ) )
		{
			// Do we have a bone follower section?
			KeyValues *pkvBoneFollowers = modelKeyValues->FindKey("bone_followers");
			if ( pkvBoneFollowers )
			{
				// Loop through the list and create the bone followers
				KeyValues *pBone = pkvBoneFollowers->GetFirstSubKey();
				while ( pBone )
				{
					// Add it to the list
					const char *pBoneName = pBone->GetString();
					m_BoneFollowerManager.AddBoneFollower( this, pBoneName );

					pBone = pBone->GetNextKey();
				}
			}
		}
		modelKeyValues->deleteThis();
	}

	return true;
}
/**
 * @brief Initializes all file variables from the file variable database.
 */
void CRPG_FileVar::LoadFVars(void) {
    char *fvdb_path, *buf;
    unsigned int fsize;
    FILE *fptr;
    KeyValues *kv;

    if(!ll_count)
        return;

    fvdb_path = (char*)calloc(512, sizeof(char));
    s_engine->GetGameDir(fvdb_path, 256);

#ifdef WIN32
    CRPG::snprintf(fvdb_path, 512, "%s\\cfg\\cssrpg\\", fvdb_path);
#else
    CRPG::snprintf(fvdb_path, 512, "%s/cfg/cssrpg/", fvdb_path);
#endif

    s_filesystem->CreateDirHierarchy(fvdb_path);
    CRPG::snprintf(fvdb_path, 512, "%s%s", fvdb_path, FVAR_DBNAME);

    fptr = fopen(fvdb_path, "rb");
    if(!fptr) {
        CRPG::ConsoleMsg("No file variable database located at \"%s\", using default values", MTYPE_WARNING, fvdb_path);
        free(fvdb_path);
        return ;
    }

    /* Get the file variable database size for allocation */
    fseek(fptr, 0, SEEK_END);
    fsize = ftell(fptr);
    rewind(fptr);

    buf = (char*)calloc(fsize+1, sizeof(char));
    fread(buf, sizeof(char), fsize, fptr);
    fclose(fptr);

    /* Check for "EF BB BF" UTF-8 BOM */
    if(!memcmp(buf, "\xEF\xBB\xBF", 3))
        buf += 3;

    /* Load the file variable database into a KeyValues class */
    kv = new KeyValues(FVAR_DBNAME);
    kv->UsesEscapeSequences(true);
    if(!kv->LoadFromBuffer(FVAR_DBNAME, buf)) {
        CRPG::ConsoleMsg("Failed to parse file variable database \"%s\", using default values", MTYPE_WARNING, fvdb_path);
        kv->deleteThis();
        free(buf);
        free(fvdb_path);
        return ;
    }

    parse_fvdb(kv);

    kv->deleteThis();
    free(buf);
    free(fvdb_path);
    return ;
}
KeyValues* ReadEncryptedKVPlayerClassFile( IFileSystem *filesystem, const char *szFilenameWithoutExtension, const unsigned char *pICEKey )
{
	Assert( strchr( szFilenameWithoutExtension, '.' ) == NULL );
	char szFullName[512];

	// Open the weapon data file, and abort if we can't
	KeyValues *pKV = new KeyValues( "PlayerClassDatafile" );

	Q_snprintf(szFullName,sizeof(szFullName), "%s.txt", szFilenameWithoutExtension);

	if ( !pKV->LoadFromFile( filesystem, szFullName, "GAME" ) ) // try to load the normal .txt file first
	{
		if ( pICEKey )
		{
			Q_snprintf(szFullName,sizeof(szFullName), "%s.ctx", szFilenameWithoutExtension); // fall back to the .ctx file

			FileHandle_t f = filesystem->Open( szFullName, "rb", "GAME");

			if (!f)
			{
				pKV->deleteThis();
				return NULL;
			}
			// load file into a null-terminated buffer
			int fileSize = filesystem->Size(f);
			char *buffer = (char*)MemAllocScratch(fileSize + 1);
		
			Assert(buffer);
		
			filesystem->Read(buffer, fileSize, f); // read into local buffer
			buffer[fileSize] = 0; // null terminate file as EOF
			filesystem->Close( f );	// close file after reading

			UTIL_DecodeICE( (unsigned char*)buffer, fileSize, pICEKey );

			bool retOK = pKV->LoadFromBuffer( szFullName, buffer, filesystem );

			MemFreeScratch();

			if ( !retOK )
			{
				pKV->deleteThis();
				return NULL;
			}
		}
		else
		{
			pKV->deleteThis();
			return NULL;
		}
	}

	return pKV;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input  :
// Output :
//-----------------------------------------------------------------------------
KeyValues *CAnimating::GetSequenceKeyValues( int iSequence )
{
	const char *szText = Studio_GetKeyValueText( GetModelPtr(), iSequence );

	if (szText)
	{
		KeyValues *seqKeyValues = new KeyValues("");
		if ( seqKeyValues->LoadFromBuffer( modelinfo->GetModelName( GetModel() ), szText ) )
		{
			return seqKeyValues;
		}
		seqKeyValues->deleteThis();
	}
	return NULL;
}
//-----------------------------------------------------------------------------
// Purpose: Parse our model and create the buildpoints in it
//-----------------------------------------------------------------------------
void CBaseObject::CreateBuildPoints( void )
{
	// Clear out any existing build points
	m_BuildPoints.RemoveAll();

	KeyValues * modelKeyValues = new KeyValues("");
	if ( !modelKeyValues->LoadFromBuffer( modelinfo->GetModelName( GetModel() ), modelinfo->GetModelKeyValueText( GetModel() ) ) )
	{
		return;
	}

	// Do we have a build point section?
	KeyValues *pkvAllBuildPoints = modelKeyValues->FindKey("build_points");
	if ( pkvAllBuildPoints )
	{
		KeyValues *pkvBuildPoint = pkvAllBuildPoints->GetFirstSubKey();
		while ( pkvBuildPoint )
		{
			// Find the attachment first
			const char *sAttachment = pkvBuildPoint->GetName();
			int iAttachmentNumber = LookupAttachment( sAttachment );
			if ( iAttachmentNumber )
			{
				AddAndParseBuildPoint( iAttachmentNumber, pkvBuildPoint );
			}
			else
			{
				Msg( "ERROR: Model %s specifies buildpoint %s, but has no attachment named %s.\n", STRING(GetModelName()), pkvBuildPoint->GetString(), pkvBuildPoint->GetString() );
			}

			pkvBuildPoint = pkvBuildPoint->GetNextKey();
		}
	}

	// Any virtual build points (build points that aren't on an attachment)?
	pkvAllBuildPoints = modelKeyValues->FindKey("virtual_build_points");
	if ( pkvAllBuildPoints )
	{
		KeyValues *pkvBuildPoint = pkvAllBuildPoints->GetFirstSubKey();
		while ( pkvBuildPoint )
		{
			AddAndParseBuildPoint( -1, pkvBuildPoint );
			pkvBuildPoint = pkvBuildPoint->GetNextKey();
		}
	}

	modelKeyValues->deleteThis();
}
//-----------------------------------------------------------------------------
// Main entry point for the unserialization
//-----------------------------------------------------------------------------
bool CImportKeyValueBase::Unserialize( CUtlBuffer &buf, const char *pEncodingName, int nEncodingVersion,
									   const char *pSourceFormatName, int nSourceFormatVersion,
									   DmFileId_t fileid, DmConflictResolution_t idConflictResolution, CDmElement **ppRoot )
{
	*ppRoot = NULL;
	m_pFileName = g_pDataModel->GetFileName( fileid );

	KeyValues *kv = new KeyValues( "dmx file" );
	if ( !kv )
		return false;

	bool bOk = kv->LoadFromBuffer( "dmx file", buf );
	if ( bOk )
	{
		*ppRoot = UnserializeFromKeyValues( kv );
	}

	kv->deleteThis();
	return bOk;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
bool CRagdollProp::HasPhysgunInteraction( const char *pszKeyName, const char *pszValue )
{
	KeyValues *modelKeyValues = new KeyValues("");
	if ( modelKeyValues->LoadFromBuffer( modelinfo->GetModelName( GetModel() ), modelinfo->GetModelKeyValueText( GetModel() ) ) )
	{
		KeyValues *pkvPropData = modelKeyValues->FindKey("physgun_interactions");
		if ( pkvPropData )
		{
			char const *pszBase = pkvPropData->GetString( pszKeyName );

			if ( pszBase && pszBase[0] && !stricmp( pszBase, pszValue ) )
			{
				modelKeyValues->deleteThis();
				return true;
			}
		}
	}

	modelKeyValues->deleteThis();
	return false;
}
	IMap<String> *PlayerBinder::_ParseKVToMap(const char *propertiesData) {
		KeyValues *keyValues = new KeyValues("Properties");
		keyValues->LoadFromBuffer("Properties", propertiesData);

		IMap<String> *properties = new Map<String>();

		KeyValues *subKey = keyValues->GetFirstSubKey();
				
		while(subKey != NULL) {
			const char *n = subKey->GetName();
			const char *v = subKey->GetString();
				
			properties->SetValue(n, v);

			subKey = subKey->GetNextKey();
		}

		keyValues->deleteThis();

		return properties;
	}
//-----------------------------------------------------------------------------
// Purpose: Parse this prop's data from the model, if it has a keyvalues section.
//			Returns true only if this prop is using a model that has a prop_data section that's invalid.
//-----------------------------------------------------------------------------
int C_PhysPropClientside::ParsePropData( void )
{
	KeyValues *modelKeyValues = new KeyValues("");
	if ( !modelKeyValues->LoadFromBuffer( modelinfo->GetModelName( GetModel() ), modelinfo->GetModelKeyValueText( GetModel() ) ) )
	{
		modelKeyValues->deleteThis();
		return PARSE_FAILED_NO_DATA;
	}

	// Do we have a props section?
	KeyValues *pkvPropData = modelKeyValues->FindKey("prop_data");
	if ( !pkvPropData )
	{
		modelKeyValues->deleteThis();
		return PARSE_FAILED_NO_DATA;
	}

	int iResult = g_PropDataSystem.ParsePropFromKV( this, pkvPropData, modelKeyValues );
	modelKeyValues->deleteThis();
	return iResult;
}
CRC32_t IFaceposerModels::CFacePoserModel::GetBitmapCRC( int sequence )
{
	CStudioHdr *hdr = m_pModel ? m_pModel->GetStudioHdr() : NULL;
	if ( !hdr )
		return (CRC32_t)-1;

	if ( sequence < 0 || sequence >= hdr->GetNumSeq() )
		return (CRC32_t)-1;

	mstudioseqdesc_t &seqdesc = hdr->pSeqdesc( sequence );

	CRC32_t crc;
	CRC32_Init( &crc );

	// For sequences, we'll checsum a bit of data

	CRC32_ProcessBuffer( &crc, (void *)seqdesc.pszLabel(), Q_strlen( seqdesc.pszLabel() ) );
	CRC32_ProcessBuffer( &crc, (void *)seqdesc.pszActivityName(), Q_strlen( seqdesc.pszActivityName() ) );
	CRC32_ProcessBuffer( &crc, (void *)&seqdesc.flags, sizeof( seqdesc.flags ) );
	//CRC32_ProcessBuffer( &crc, (void *)&seqdesc.numevents, sizeof( seqdesc.numevents ) );
	CRC32_ProcessBuffer( &crc, (void *)&seqdesc.numblends, sizeof( seqdesc.numblends ) );
	CRC32_ProcessBuffer( &crc, (void *)seqdesc.groupsize, sizeof( seqdesc.groupsize ) );

	KeyValues *seqKeyValues = new KeyValues("");
	if ( seqKeyValues->LoadFromBuffer( m_pModel->GetFileName( ), m_pModel->GetKeyValueText( sequence ) ) )
	{
		// Yuck, but I need it in a contiguous block of memory... oh well...
		CUtlBuffer buf;
		seqKeyValues->RecursiveSaveToFile( buf, 0 );
		CRC32_ProcessBuffer( &crc, ( void * )buf.Base(), buf.TellPut() );
	}

	seqKeyValues->deleteThis();

	CRC32_Final( &crc );

	return crc;
}
KeyValues* ReadKeyValuesFile( const char *pFilename )
{
	// Read in the gameinfo.txt file and null-terminate it.
	FILE *fp = fopen( pFilename, "rb" );
	if ( !fp )
		return NULL;
	CUtlVector<char> buf;
	fseek( fp, 0, SEEK_END );
	buf.SetSize( ftell( fp ) + 1 );
	fseek( fp, 0, SEEK_SET );
	fread( buf.Base(), 1, buf.Count()-1, fp );
	fclose( fp );
	buf[buf.Count()-1] = 0;

	KeyValues *kv = new KeyValues( "" );
	if ( !kv->LoadFromBuffer( pFilename, buf.Base() ) )
	{
		kv->deleteThis();
		return NULL;
	}
	
	return kv;
}
bool CEventPropertiesGestureDialog::CheckSequenceType( StudioModel *model, int iSequence, char *szType )
{
	KeyValues *seqKeyValues = new KeyValues("");
	bool isType = false;
	if ( seqKeyValues->LoadFromBuffer( model->GetFileName( ), model->GetKeyValueText( iSequence ) ) )
	{
		// Do we have a build point section?
		KeyValues *pkvAllFaceposer = seqKeyValues->FindKey("faceposer");
		if ( pkvAllFaceposer )
		{
			KeyValues *pkvType = pkvAllFaceposer->FindKey("type");

			if (pkvType)
			{
				isType = (stricmp( pkvType->GetString(), szType ) == 0) ? true : false;
			}
		}
	}

	seqKeyValues->deleteThis();

	return isType;
}
void CFolderMenu::Update()
{
	ReloadControlSettings(false, false);

	MoveToCenterOfScreen();

	Button *entry = dynamic_cast<Button *>(FindChildByName("ApproveButton"));
	if (entry)
		entry->SetVisible(true);

	C_SDKPlayer *pPlayer = C_SDKPlayer::GetLocalSDKPlayer();

	if (!pPlayer)
		return;

	if (pPlayer->HasCharacterBeenChosen())
		Q_strcpy(m_szCharacter, pPlayer->GetCharacter());
	else
		m_szCharacter[0] = '\0';

	if (ShouldShowCharacterOnly() && !ShouldShowTeams())
	{
		m_pProfileInfo->SetVisible(true);
		if (m_szPreviewCharacter[0])
			m_pProfileInfo->SetText((std::string("#DA_CharacterInfo_") + m_szPreviewCharacter).c_str());
		else if (m_szCharacter[0])
			m_pProfileInfo->SetText((std::string("#DA_CharacterInfo_") + m_szCharacter).c_str());
		else
			m_pProfileInfo->SetText("#DA_CharacterInfo_None");
	}
	else
		m_pProfileInfo->SetVisible(false);

	CFolderLabel *pCharacterName = dynamic_cast<CFolderLabel *>(FindChildByName("AgentName"));
	if (pCharacterName && !ShouldShowTeams())
	{
		std::string sCharacter;
		if (m_szPreviewCharacter[0])
			sCharacter = std::string("#DA_Character_") + m_szPreviewCharacter;
		else if (m_szCharacter[0])
			sCharacter = std::string("#DA_Character_") + m_szCharacter;

		std::wstring sLocalized;
		wchar_t* pszLocalized = g_pVGuiLocalize->Find( sCharacter.c_str() );

		if (pszLocalized)
			sLocalized += pszLocalized;

		if (pPlayer->m_Shared.m_iStyleSkill)
		{
			std::string sSkill = std::string("#DA_Skill_") + SkillIDToAlias((SkillID)pPlayer->m_Shared.m_iStyleSkill.Get()) + "_Adjective";

			pszLocalized = g_pVGuiLocalize->Find( sSkill.c_str() );

			if (pszLocalized)
				sLocalized += pszLocalized;
		}

		pCharacterName->SetText(sLocalized.c_str());
	}
	else
		pCharacterName->SetText("");

	CFolderLabel* pLabels[2];
	pLabels[0] = dynamic_cast<CFolderLabel *>(FindChildByName("RequestedArmament1"));
	pLabels[1] = dynamic_cast<CFolderLabel *>(FindChildByName("RequestedArmament2"));

	int iArmamentsOn1 = 0;

	std::wostringstream sLabel1;
	std::wostringstream sLabel2;

	SDKWeaponID eFirst = WEAPON_NONE;
	for (int i = 0; i < MAX_LOADOUT; i++)
	{
		if (!pPlayer->GetLoadoutWeaponCount((SDKWeaponID)i))
			continue;

		CSDKWeaponInfo* pWeaponInfo = CSDKWeaponInfo::GetWeaponInfo((SDKWeaponID)i);
		if (!pWeaponInfo)
			continue;

		if (!eFirst)
		{
			eFirst = (SDKWeaponID)i;

			if (pPlayer->GetLoadoutWeaponCount(eFirst) > 1)
			{
				CSDKWeaponInfo* pWeaponInfo = CSDKWeaponInfo::GetWeaponInfo(eFirst);
				if (pWeaponInfo && pWeaponInfo->m_szAkimbo[0])
				{
					// If we have two of this weapon and this weapon has an akimbo, use the akimbo instead.
					eFirst = AliasToWeaponID(pWeaponInfo->m_szAkimbo);
				}
			}
		}
		else
		{
			if (pPlayer->GetLoadoutWeaponCount((SDKWeaponID)i) > 1)
			{
				CSDKWeaponInfo* pWeaponInfo = CSDKWeaponInfo::GetWeaponInfo((SDKWeaponID)i);
				if (pWeaponInfo && pWeaponInfo->m_szAkimbo[0])
				{
					SDKWeaponID eAkimbo = AliasToWeaponID(pWeaponInfo->m_szAkimbo);
					if (eAkimbo < eFirst)
					{
						// If we have this akimbo and it's preferred to the current weapon, use it instead.
						// (Preferred means lower weapon ID.)
						eFirst = eAkimbo;
					}
				}
			}
		}

		std::wostringstream sLabel;

		const wchar_t *pchFmt = g_pVGuiLocalize->Find( pWeaponInfo->szPrintName );
		if ( pchFmt && pchFmt[0] )
			sLabel << pchFmt;
		else
			sLabel << pWeaponInfo->szPrintName;

		if (pPlayer->GetLoadoutWeaponCount((SDKWeaponID)i) > 1)
			sLabel << " x" << pPlayer->GetLoadoutWeaponCount((SDKWeaponID)i) << "\n";
		else
			sLabel << "\n";

		if (iArmamentsOn1 >= 2)
			sLabel2 << sLabel.str();
		else
			sLabel1 << sLabel.str();

		iArmamentsOn1++;
	}

	if (pLabels[0])
		pLabels[0]->SetText(sLabel1.str().c_str());

	if (pLabels[1])
		pLabels[1]->SetText(sLabel2.str().c_str());

	const char szPlayerPreviewTemplate[] =
		"	\"model\"\n"
		"	{\n"
		"		\"spotlight\"	\"1\"\n"
		"		\"modelname\"	\"models/player/frank.mdl\"\n"
		"		\"origin_z\"	\"-57\"\n"
		"		\"origin_y\"	\"10\"\n"
		"		\"origin_x\"	\"110\"\n"
		"		\"angles_y\"	\"180\"\n"

		"		\"animation\"\n"
		"		{\n"
		"			\"sequence\"		\"m1911_idle\"\n"
		"			\"pose_parameters\"\n"
		"			{\n"
		"				\"body_yaw\" \"25.0\"\n"
		"				\"body_pitch\" \"-30.0\"\n"
		"			}\n"
		"		}\n"
			
		"		\"attached_model\"\n"
		"		{\n"
		"			\"modelname\" \"models/weapons/m1911.mdl\"\n"
		"		}\n"
		"	}";

	CModelPanel *pPlayerPreview = dynamic_cast<CModelPanel *>(FindChildByName("player_preview"));
	CSDKWeaponInfo* pWeaponInfo = NULL;
	if (eFirst)
		pWeaponInfo = CSDKWeaponInfo::GetWeaponInfo(eFirst);

	if ((m_szCharacter[0] || m_szPreviewCharacter[0]) && pPlayerPreview && !ShouldShowTeams())
	{
		KeyValues* pValues = new KeyValues("preview");
		pValues->LoadFromBuffer("model", szPlayerPreviewTemplate);

		const char* pCharacter = m_szCharacter;
		if (m_szPreviewCharacter[0])
			pCharacter = m_szPreviewCharacter;

		pValues->SetString("modelname", VarArgs("models/player/%s.mdl", pCharacter));

		if (ShouldShowCharacterOnly() || ShouldShowCharacterAndWeapons())
		{
			pValues->SetFloat("origin_x", hud_characterpreview_x.GetFloat());
			pValues->SetFloat("origin_y", hud_characterpreview_y.GetFloat());
			pValues->SetFloat("origin_z", hud_characterpreview_z.GetFloat());
		}
		else
		{
			pValues->SetFloat("origin_x", hud_playerpreview_x.GetFloat());
			pValues->SetFloat("origin_y", hud_playerpreview_y.GetFloat());
			pValues->SetFloat("origin_z", hud_playerpreview_z.GetFloat());
		}

		if (m_pPage && FStrEq(m_pPage->GetName(), "class") && m_szPreviewSequence[0] && m_szPreviewWeaponModel[0] && !pPlayer->GetLoadoutWeight())
		{
			KeyValues* pAnimation = pValues->FindKey("animation");
			if (pAnimation)
				pAnimation->SetString("sequence", m_szPreviewSequence);

			KeyValues* pWeapon = pValues->FindKey("attached_model");
			if (pWeapon)
				pWeapon->SetString("modelname", m_szPreviewWeaponModel);
		}
		else if (pWeaponInfo)
		{
			KeyValues* pAnimation = pValues->FindKey("animation");
			if (pAnimation)
				pAnimation->SetString("sequence", VarArgs("%s_idle", WeaponIDToAlias(eFirst)));

			KeyValues* pWeapon = pValues->FindKey("attached_model");
			if (pWeapon)
				pWeapon->SetString("modelname", pWeaponInfo->szWorldModel);
		}
		else
		{
			KeyValues* pAnimation = pValues->FindKey("animation");
			if (pAnimation)
				pAnimation->SetString("sequence", "idle");

			KeyValues* pWeapon = pValues->FindKey("attached_model");
			if (pWeapon)
				pWeapon->SetString("modelname", "");
		}

		if (SDKGameRules()->IsTeamplay())
		{
			if (pPlayer->GetTeamNumber() == SDK_TEAM_BLUE)
				pValues->SetInt("skin", 1);
			else if (pPlayer->GetTeamNumber() == SDK_TEAM_RED)
				pValues->SetInt("skin", 2);
			else
				pValues->SetInt("skin", 0);
		}
		else
			pValues->SetInt("skin", 0);

		pPlayerPreview->ParseModelInfo(pValues);

		pValues->deleteThis();
	}
	else if (pPlayerPreview)
		pPlayerPreview->SwapModel("");

	for ( int i = 0; i < m_apWeaponIcons.Count(); i++)
	{
		if (m_apWeaponIcons[i].m_pWeaponName)
			m_apWeaponIcons[i].m_pWeaponName->DeletePanel();
	
		if (m_apWeaponIcons[i].m_pSlots)
			m_apWeaponIcons[i].m_pSlots->DeletePanel();

		if (m_apWeaponIcons[i].m_pImage)
			m_apWeaponIcons[i].m_pImage->DeletePanel();

		if (m_apWeaponIcons[i].m_pDelete)
			m_apWeaponIcons[i].m_pDelete->DeletePanel();
	}

	m_apWeaponIcons.RemoveAll();

	const char szWeaponPreviewTemplate[] =
		"	\"model\"\n"
		"	{\n"
		"		\"spotlight\"	\"1\"\n"
		"		\"modelname\"	\"models/weapons/beretta.mdl\"\n"
		"		\"origin_x\"	\"30\"\n"
		"		\"origin_y\"	\"3\"\n"
		"		\"origin_z\"	\"-3\"\n"
		"		\"angles_y\"	\"200\"\n"
		"	}";

	Panel *pWeaponIconArea = FindChildByName("WeaponIconArea");
	if ((ShouldShowCharacterAndWeapons() || ShouldShowEverything()) && pWeaponIconArea)
	{
		int iWeaponAreaX, iWeaponAreaY, iWeaponAreaW, iWeaponAreaH;
		pWeaponIconArea->GetPos(iWeaponAreaX, iWeaponAreaY);
		pWeaponIconArea->GetSize(iWeaponAreaW, iWeaponAreaH);

		int iMargin = 5;

		int iBoxSize = (iWeaponAreaW-5)/2;

		int iWeapon = 0;

		for (int i = 0; i < MAX_LOADOUT; i++)
		{
			if (!pPlayer->GetLoadoutWeaponCount((SDKWeaponID)i))
				continue;

			CSDKWeaponInfo* pWeaponInfo = CSDKWeaponInfo::GetWeaponInfo((SDKWeaponID)i);
			if (!pWeaponInfo)
				continue;

			for (int j = 0; j < pPlayer->GetLoadoutWeaponCount((SDKWeaponID)i); j++)
			{
				float flMoveRight = 0;
				if (iWeapon%2 == 1)
					flMoveRight = iBoxSize + iMargin;

				CWeaponIcon* pIcon = &m_apWeaponIcons[m_apWeaponIcons.AddToTail()];

				pIcon->m_pWeaponName = new CFolderLabel(this, NULL);
				pIcon->m_pWeaponName->SetText(VarArgs("#DA_Weapon_Obituary_%s", pWeaponInfo->szClassName+7)); // Use the obit version because it's shorter
				pIcon->m_pWeaponName->SetPos(iWeaponAreaX + flMoveRight, iWeaponAreaY + 10 + (iWeapon/2) * (iBoxSize+iMargin));
				pIcon->m_pWeaponName->SetSize(iBoxSize, 15);
				pIcon->m_pWeaponName->SetContentAlignment(Label::a_center);
				pIcon->m_pWeaponName->SetZPos(-5);
				pIcon->m_pWeaponName->SetFont(vgui::scheme()->GetIScheme(GetScheme())->GetFont("FolderLarge"));
				pIcon->m_pWeaponName->SetScheme("FolderScheme");

				std::wostringstream sSlotsLabel;

				if (pWeaponInfo->iWeight)
				{
					const wchar_t *pchFmt = g_pVGuiLocalize->Find( "#DA_BuyMenu_Weapon_Slots" );
					if ( pchFmt && pchFmt[0] )
						sSlotsLabel << pchFmt;
					else
						sSlotsLabel << "Slots: ";

					sSlotsLabel << pWeaponInfo->iWeight;

					pIcon->m_pSlots = new CFolderLabel(this, NULL);
					pIcon->m_pSlots->SetText(sSlotsLabel.str().c_str());
					pIcon->m_pSlots->SetPos(iWeaponAreaX + flMoveRight, iWeaponAreaY + iBoxSize - 10 + (iWeapon/2) * (iBoxSize+iMargin));
					pIcon->m_pSlots->SetSize(iBoxSize, 15);
					pIcon->m_pSlots->SetContentAlignment(Label::a_center);
					pIcon->m_pSlots->SetZPos(-5);
					pIcon->m_pSlots->SetFont(vgui::scheme()->GetIScheme(GetScheme())->GetFont("FolderSmall"));
					pIcon->m_pSlots->SetScheme("FolderScheme");
				}

				KeyValues* pValues = new KeyValues("preview");
				pValues->LoadFromBuffer("model", szWeaponPreviewTemplate);
				pValues->SetString("modelname", pWeaponInfo->szWorldModel);

				if (pWeaponInfo->m_eWeaponType == WT_PISTOL)
				{
					pValues->SetInt("origin_x", 20);
				}
				else if (pWeaponInfo->m_eWeaponType == WT_RIFLE)
				{
					pValues->SetInt("origin_x", 50);
					pValues->SetInt("angles_y", 210);
				}
				else if (pWeaponInfo->m_eWeaponType == WT_SHOTGUN)
				{
					pValues->SetInt("origin_x", 50);
					pValues->SetInt("origin_y", 10);
					pValues->SetInt("angles_y", 150);
				}
				else if (pWeaponInfo->m_eWeaponType == WT_SMG)
				{
				}
				else if (pWeaponInfo->m_eWeaponType == WT_GRENADE)
				{
					pValues->SetInt("origin_x", 20);
				}

				pIcon->m_pImage = new CModelPanel(this, NULL);
				pIcon->m_pImage->SetPos(iWeaponAreaX + flMoveRight, iWeaponAreaY + (iWeapon/2) * (iBoxSize+iMargin));
				pIcon->m_pImage->SetSize(iBoxSize, iBoxSize);
				pIcon->m_pImage->SetZPos(-15);
				pIcon->m_pImage->SetScheme("FolderScheme");
				pIcon->m_pImage->ParseModelInfo(pValues);

				pValues->deleteThis();

				pIcon->m_pDelete = new CImageButton(this, VarArgs("delete_%d", iWeapon));
				pIcon->m_pDelete->SetDimensions(iWeaponAreaX + iBoxSize - 8 + flMoveRight, iWeaponAreaY + 30 + (iWeapon/2) * (iBoxSize+iMargin), 12, 12);
				pIcon->m_pDelete->SetZPos(15);
				pIcon->m_pDelete->SetImage("folder_delete");
				pIcon->m_pDelete->SetPaintBorderEnabled(false);
				pIcon->m_pDelete->SetPaintBackgroundEnabled(true);
				pIcon->m_pDelete->SetCommand(VarArgs("buy remove %d", i));

				iWeapon++;
			}
		}
	}

	CFolderLabel* pWeaponTotalWeightNumber = dynamic_cast<CFolderLabel*>(FindChildByName("WeaponTotalWeightNumber"));
	CFolderLabel* pWeaponTotalWeight = dynamic_cast<CFolderLabel*>(FindChildByName("WeaponTotalWeight"));
	if ((ShouldShowCharacterAndWeapons() || ShouldShowEverything()) && pPlayer->GetLoadoutWeight())
	{
		if (pWeaponTotalWeightNumber)
		{
			wchar_t szText[20];
			_snwprintf( szText, ARRAYSIZE(szText) - 1, L"%d/%d", pPlayer->GetLoadoutWeight(), MAX_LOADOUT_WEIGHT );
			pWeaponTotalWeightNumber->SetText(szText);
			pWeaponTotalWeightNumber->SetVisible(true);
		}

		if (pWeaponTotalWeight)
			pWeaponTotalWeight->SetVisible(true);
	}
	else
	{
		if (pWeaponTotalWeightNumber)
			pWeaponTotalWeightNumber->SetVisible(false);

		if (pWeaponTotalWeight)
			pWeaponTotalWeight->SetVisible(false);
	}

	if (ShouldShowEverything())
	{
		CFolderLabel *pSkillInfo = dynamic_cast<CFolderLabel *>(FindChildByName("SkillInfo"));
		CPanelTexture *pSkillIcon = dynamic_cast<CPanelTexture *>(FindChildByName("SkillIcon"));

		if (pSkillInfo && pSkillIcon)
		{
			if (pPlayer->m_Shared.m_iStyleSkill)
			{
				pSkillInfo->SetText((std::string("#DA_SkillInfo_") + SkillIDToAlias((SkillID)pPlayer->m_Shared.m_iStyleSkill.Get())).c_str());
				pSkillIcon->SetImage(SkillIDToAlias((SkillID)pPlayer->m_Shared.m_iStyleSkill.Get()));
			}
			else
			{
				pSkillInfo->SetText("");
				pSkillIcon->SetImage("");
			}
		}
	}

	m_pSuicideOption->SetVisible(pPlayer->IsAlive() && !ShouldShowTeams());

	Button *pProceedButton = dynamic_cast<Button *>(FindChildByName("ProceedButton"));
	if (pProceedButton)
		pProceedButton->SetVisible(m_pPage && FStrEq(m_pPage->GetName(), PANEL_BUY));

	Button *pApproveButton = dynamic_cast<Button *>(FindChildByName("ApproveButton"));
	if (pApproveButton)
		pApproveButton->SetVisible(IsLoadoutComplete());

	Button *pAgentsTab = dynamic_cast<Button *>(FindChildByName("AgentsTab"));
	if (pAgentsTab)
		pAgentsTab->SetVisible(pPlayer->HasCharacterBeenChosen());

	Button *pWeaponsTab = dynamic_cast<Button *>(FindChildByName("WeaponsTab"));
	if (pWeaponsTab)
		pWeaponsTab->SetVisible(pPlayer->HasCharacterBeenChosen());

	Button *pSkillsTab = dynamic_cast<Button *>(FindChildByName("SkillsTab"));
	if (pSkillsTab)
		pSkillsTab->SetVisible(pPlayer->HasSkillsTabBeenSeen());

	Button *pChangeTeams = dynamic_cast<Button *>(FindChildByName("ChangeTeamsButton"));
	if (pChangeTeams)
		pChangeTeams->SetVisible(SDKGameRules()->IsTeamplay());
}
void IFaceposerModels::CFacePoserModel::CreateNewBitmap( char const *pchBitmapFilename, int sequence, int nSnapShotSize, bool bZoomInOnFace, CExpression *pExpression, mxbitmapdata_t *bitmap )
{
	MatSysWindow *pWnd = g_pMatSysWindow;
	if ( !pWnd ) 
		return;

	StudioModel *model = m_pModel;
	if ( !model )
		return;

	CStudioHdr *hdr = model->GetStudioHdr();
	if ( !hdr )
		return;
	if ( sequence < 0 || sequence >= hdr->GetNumSeq() )
		return;

	mstudioseqdesc_t &seqdesc = hdr->pSeqdesc( sequence );

	Con_ColorPrintf( FILE_COLOR, "Creating bitmap %s for sequence '%s'\n", pchBitmapFilename, seqdesc.pszLabel() );

	model->ClearOverlaysSequences();
	int iLayer = model->GetNewAnimationLayer();
	model->SetOverlaySequence( iLayer, sequence, 1.0 );
	model->SetOverlayRate( iLayer, FindPoseCycle( model, sequence ), 0.0 );

	for (int i = 0; i < hdr->GetNumPoseParameters(); i++)
	{
		model->SetPoseParameter( i, 0.0 );
	}

	float flexValues[ GLOBAL_STUDIO_FLEX_CONTROL_COUNT ] = { 0 };

	if ( pExpression )
	{
		float *settings = pExpression->GetSettings();
		float *weights = pExpression->GetWeights();

		// Save existing settings from model
		for ( LocalFlexController_t i = LocalFlexController_t(0); i < hdr->numflexcontrollers(); ++i )
		{
			int j = hdr->pFlexcontroller( i )->localToGlobal;
			if ( j == -1 )
				continue;
			flexValues[ i ] = model->GetFlexController( i );
			// Set Value from passed in settings
			model->SetFlexController( i, settings[ j ] * weights[ j ] );
		}
	}

	model->ClearLookTargets( );

	QAngle oldrot, oldLight;
	Vector oldtrans;
	
	VectorCopy( model->m_angles, oldrot );
	VectorCopy( model->m_origin, oldtrans );
	VectorCopy( g_viewerSettings.lightrot, oldLight );

	model->m_angles.Init();
	model->m_origin.Init();
	g_viewerSettings.lightrot.Init();

	g_viewerSettings.lightrot.y = -180;

	bool bSaveGround = g_viewerSettings.showGround;
	g_viewerSettings.showGround = false;

	if ( bZoomInOnFace )
	{
		Vector size;
		VectorSubtract( hdr->hull_max(), hdr->hull_min(), size );

		float eyeheight = hdr->hull_min().z + 0.9 * size.z;
		//	float width = ( size.x + size.y ) / 2.0f;

		model->m_origin.x = size.z * .6f;

		if ( hdr->GetNumAttachments() > 0 )
		{
			for (int i = 0; i < hdr->GetNumAttachments(); i++)
			{
				const mstudioattachment_t &attachment = hdr->pAttachment( i );
				int iBone = hdr->GetAttachmentBone( i );

				if ( Q_stricmp( attachment.pszName(), "eyes" ) )
					continue;

				mstudiobone_t *bone = hdr->pBone( iBone );
				if ( !bone )
					continue;

				matrix3x4_t boneToPose;
				MatrixInvert( bone->poseToBone, boneToPose );

				matrix3x4_t attachmentPoseToLocal;
				ConcatTransforms( boneToPose, attachment.local, attachmentPoseToLocal );

				Vector localSpaceEyePosition;
				VectorITransform( vec3_origin, attachmentPoseToLocal, localSpaceEyePosition );

				// Not sure why this must be negative?
				eyeheight = -localSpaceEyePosition.z + hdr->hull_min().z;
				break;
			}
		}

		KeyValues *seqKeyValues = new KeyValues("");
		if ( seqKeyValues->LoadFromBuffer( model->GetFileName( ), model->GetKeyValueText( sequence ) ) )
		{
			// Do we have a build point section?
			KeyValues *pkvAllFaceposer = seqKeyValues->FindKey("faceposer");
			if ( pkvAllFaceposer )
			{
				float flEyeheight = pkvAllFaceposer->GetFloat( "eye_height", -9999.0f );
				if ( flEyeheight != -9999.0f )
				{
					eyeheight = flEyeheight;
				}
			}
		}

		model->m_origin.z += eyeheight;
	}
	else
	{
		Vector mins, maxs;
		model->ExtractBbox(mins, maxs);
		Vector size;
		VectorSubtract( maxs, mins, size );

		float maxdim = size.x;
		if ( size.y > maxdim )
			maxdim = size.y;
		if ( size.z > maxdim )
			maxdim = size.z;

		float midpoint = mins.z + 0.5 * size.z;

		model->m_origin.x = 3 * maxdim;
		model->m_origin.z += midpoint;
	}

	pWnd->SuppressResize( true );

	RECT rcClient;
	HWND wnd = (HWND)pWnd->getHandle();

	WINDOWPLACEMENT wp;

	GetWindowPlacement( wnd, &wp );

	GetClientRect( wnd, &rcClient );

	MoveWindow( wnd, 0, 0, nSnapShotSize + 16, nSnapShotSize + 16, TRUE );

	// Snapshots are taken of the back buffer; 
	// we need to render to the back buffer but not move it to the front
	pWnd->SuppressBufferSwap( true );
	pWnd->redraw();
	pWnd->SuppressBufferSwap( false );

	// make it square, assumes w > h
	char fullpath[ 512 ];
	Q_snprintf( fullpath, sizeof( fullpath ), "%s%s", GetGameDirectory(), pchBitmapFilename );
	pWnd->TakeSnapshotRect( fullpath, 0, 0, nSnapShotSize, nSnapShotSize );

	// Move back to original position
	SetWindowPlacement( wnd, &wp );

	pWnd->SuppressResize( false );

	VectorCopy( oldrot, model->m_angles );
	VectorCopy( oldtrans, model->m_origin );
	VectorCopy( oldLight, g_viewerSettings.lightrot );

	g_viewerSettings.showGround = bSaveGround;

	if ( pExpression )
	{
		// Save existing settings from model
		for ( LocalFlexController_t i = LocalFlexController_t(0); i < hdr->numflexcontrollers(); ++i )
		{
			int j = hdr->pFlexcontroller( i )->localToGlobal;
			if ( j == -1 )
				continue;

			model->SetFlexController( i, flexValues[ i ] );
		}
	}

	model->ClearOverlaysSequences();
	
	if ( bitmap->valid )
	{
		DeleteObject( bitmap->image );
		bitmap->image = 0;
		bitmap->valid = false;
	}

	LoadBitmapFromFile( pchBitmapFilename, *bitmap );
}
int CPhysicsSurfaceProps::ParseSurfaceData(const char* pFilename, const char* pTextfile) {
	if (!AddFileToDatabase(pFilename)) return 0;

	KeyValues* surfprops = new KeyValues("");
	surfprops->LoadFromBuffer(pFilename, pTextfile);
	for (KeyValues* surface = surfprops; surface; surface = surface->GetNextKey()) {
		CSurface prop;
		int baseMaterial = GetSurfaceIndex("default");

		memset(&prop.data, 0, sizeof(prop.data));
		prop.m_name = m_strings->AddString(surface->GetName());
		prop.data.game.material = 0;
		prop.data.game.maxSpeedFactor = 1.0f;
		prop.data.game.jumpFactor = 1.0f;
		prop.data.game.climbable = 0.0f;
		CopyPhysicsProperties(&prop, baseMaterial);

		for (KeyValues* data = surface->GetFirstSubKey(); data; data = data->GetNextKey()) {
			const char* key = data->GetName();
			if (!strcmpi(key, "base")) {
				baseMaterial = GetSurfaceIndex(data->GetString());
				CopyPhysicsProperties(&prop, baseMaterial);
			} else if (!strcmpi(key, "thickness")) {
				prop.data.physics.thickness = data->GetFloat();
			} else if (!strcmpi(key, "density")) {
				prop.data.physics.density = data->GetFloat();
			} else if (!strcmpi(key, "elasticity")) {
				prop.data.physics.elasticity = data->GetFloat();
			} else if (!strcmpi(key, "friction")) {
				prop.data.physics.friction = data->GetFloat();
			} else if (!strcmpi(key, "dampening")) {
				prop.data.physics.dampening = data->GetFloat();
			} else if (!strcmpi(key, "audioreflectivity")) {
				prop.data.audio.reflectivity = data->GetFloat();
			} else if (!strcmpi(key, "audiohardnessfactor")) {
				prop.data.audio.hardnessFactor = data->GetFloat();
			} else if (!strcmpi(key, "audioroughnessfactor")) {
				prop.data.audio.roughnessFactor = data->GetFloat();
			} else if (!strcmpi(key, "scrapeRoughThreshold")) {
				prop.data.audio.roughThreshold = data->GetFloat();
			} else if (!strcmpi(key, "impactHardThreshold")) {
				prop.data.audio.hardThreshold = data->GetFloat();
			} else if (!strcmpi(key, "audioHardMinVelocity")) {
				prop.data.audio.hardVelocityThreshold = data->GetFloat();
			} else if (!strcmpi(key, "maxspeedfactor")) {
				prop.data.game.maxSpeedFactor = data->GetFloat();
			} else if (!strcmpi(key, "jumpfactor")) {
				prop.data.game.jumpFactor = data->GetFloat();
			} else if (!strcmpi(key, "climbable")) {
				prop.data.game.climbable = data->GetInt();
			} else if (!strcmpi(key, "gamematerial")) {
				if (data->GetDataType() == KeyValues::TYPE_STRING && strlen(data->GetString()) == 1) {
					prop.data.game.material = toupper(data->GetString()[0]);
				} else {
					prop.data.game.material = data->GetInt();
				}
			} else if (!strcmpi(key, "stepleft")) {
				CUtlSymbol sym = m_strings->AddString(data->GetString());
				prop.data.sounds.stepleft = m_soundList.AddToTail(sym);
			} else if (!strcmpi(key, "stepright")) {
				CUtlSymbol sym = m_strings->AddString(data->GetString());
				prop.data.sounds.stepright = m_soundList.AddToTail(sym);
			} else if (!strcmpi(key, "impactsoft")) {
				CUtlSymbol sym = m_strings->AddString(data->GetString());
				prop.data.sounds.impactSoft = m_soundList.AddToTail(sym);
			} else if (!strcmpi(key, "impacthard")) {
				CUtlSymbol sym = m_strings->AddString(data->GetString());
				prop.data.sounds.impactHard = m_soundList.AddToTail(sym);
			} else if (!strcmpi(key, "scrapesmooth")) {
				CUtlSymbol sym = m_strings->AddString(data->GetString());
				prop.data.sounds.scrapeSmooth = m_soundList.AddToTail(sym);
			} else if (!strcmpi(key, "scraperough")) {
				CUtlSymbol sym = m_strings->AddString(data->GetString());
				prop.data.sounds.scrapeRough = m_soundList.AddToTail(sym);
			} else if (!strcmpi(key, "bulletimpact")) {
				CUtlSymbol sym = m_strings->AddString(data->GetString());
				prop.data.sounds.bulletImpact = m_soundList.AddToTail(sym);
			} else if (!strcmpi(key, "break")) {
				CUtlSymbol sym = m_strings->AddString(data->GetString());
				prop.data.sounds.breakSound = m_soundList.AddToTail(sym);
			} else if (!strcmpi(key, "strain")) {
				CUtlSymbol sym = m_strings->AddString(data->GetString());
				prop.data.sounds.strainSound = m_soundList.AddToTail(sym);
			} else if (!strcmpi(key, "rolling")) {
				CUtlSymbol sym = m_strings->AddString(data->GetString());
				prop.data.sounds.rolling = m_soundList.AddToTail(sym);
			} else {
				AssertMsg2(0, "Bad surfaceprop key %s (%s)\n", key, data->GetString());
			}
		}
		if (GetSurfaceIndex(m_strings->String(prop.m_name)) >= 0) break;

		m_props.AddToTail(prop);
	}
	surfprops->deleteThis();
	return 0;
}
//-----------------------------------------------------------------------------
// The DX Support file is a very fat expensive KV file, causes a run-time startup slowdown.
// Becauase it normally lives in the game\bin directory, it can't be in the zip or preloaded.
// Thus, it gets reprocessed into just the trivial 360 portion and placed into the platform.zip
// Yes, it's evil.
//-----------------------------------------------------------------------------
bool ProcessDXSupportConfig( bool bWriteToZip )
{
	if ( !g_bIsPlatformZip )
	{
		// only relevant when building platform zip, otherwise no-op
		return false;
	}

	const char *pConfigName = "dxsupport.cfg";
	char szTempPath[MAX_PATH];
	char szSourcePath[MAX_PATH];
	V_ComposeFileName( g_szModPath, "../bin", szTempPath, sizeof( szTempPath ) );
	V_ComposeFileName( szTempPath, pConfigName, szSourcePath, sizeof( szSourcePath ) );

	CUtlBuffer sourceBuf( 0, 0, CUtlBuffer::TEXT_BUFFER );
	if ( !g_pFullFileSystem->ReadFile( szSourcePath, NULL, sourceBuf ) )
	{
		Msg( "Error! Couldn't open file '%s'!\n", pConfigName ); 
		return false;
	}

	KeyValues *pKV = new KeyValues( "" );
	if ( !pKV->LoadFromBuffer( "dxsupport.cfg", sourceBuf ) )
	{
		Msg( "Error! Couldn't parse config file '%s'!\n", pConfigName ); 
		pKV->deleteThis();
		return false;
	}

	// only care about the xbox specific dxlevel 98 block
	KeyValues *pXboxSubKey = NULL;
	for ( KeyValues *pSubKey = pKV->GetFirstSubKey(); pSubKey != NULL && pXboxSubKey == NULL; pSubKey = pSubKey->GetNextKey() )
	{
		// descend each sub block
		for ( KeyValues *pKey = pSubKey->GetFirstSubKey(); pKey != NULL && pXboxSubKey == NULL; pKey = pKey->GetNextKey() )
		{
			if ( !V_stricmp( pKey->GetName(), "name" ) && pKey->GetInt( (const char *)NULL ) == 98 )
			{
				pXboxSubKey = pSubKey;
			}
		}
	}
	
	if ( !pXboxSubKey )
	{
		Msg( "Error! Couldn't find expected dxlevel 98 in config file '%s'!\n", pConfigName ); 
		pKV->deleteThis();
		return false;
	}

	CUtlBuffer kvBuffer( 0, 0, CUtlBuffer::TEXT_BUFFER );
	kvBuffer.Printf( "\"dxsupport\"\n" );
	kvBuffer.Printf( "{\n" );
	kvBuffer.Printf( "\t\"0\"\n" );
	kvBuffer.Printf( "\t{\n" );
	for ( KeyValues *pKey = pXboxSubKey->GetFirstSubKey(); pKey != NULL; pKey = pKey->GetNextKey() )
	{
		kvBuffer.Printf( "\t\t\"%s\" \"%s\"\n", pKey->GetName(), pKey->GetString( (const char *)NULL ) );
	}
	kvBuffer.Printf( "\t}\n" );
	kvBuffer.Printf( "}\n" );

	CUtlBuffer targetBuf( 0, 0, CUtlBuffer::TEXT_BUFFER | CUtlBuffer::CONTAINS_CRLF );
	kvBuffer.ConvertCRLF( targetBuf );

	// only appears in zip file
	bool bSuccess = WriteBufferToFile( pConfigName, targetBuf, bWriteToZip, WRITE_TO_DISK_NEVER );

	pKV->deleteThis();

	return bSuccess;
}
void C_ASW_Medal_Store::LoadMedalStore()
{
#if defined(NO_STEAM)
	AssertMsg( false, "SteamCloud not available." );
#else
	ISteamRemoteStorage *pRemoteStorage = SteamClient() ? ( ISteamRemoteStorage * )SteamClient()->GetISteamGenericInterface(
		SteamAPI_GetHSteamUser(), SteamAPI_GetHSteamPipe(), STEAMREMOTESTORAGE_INTERFACE_VERSION ) : NULL;
	ISteamUser *pSteamUser = steamapicontext ? steamapicontext->SteamUser() : NULL;
	if ( !pSteamUser )
		return;

	char szMedalFile[ 256 ];
	Q_snprintf( szMedalFile, sizeof( szMedalFile ), "cfg/clientc_%I64u.dat", pSteamUser->GetSteamID().ConvertToUint64() );
	int len = Q_strlen( szMedalFile );
	for ( int i = 0; i < len; i++ )
	{
		if ( szMedalFile[ i ] == ':' )
			szMedalFile[i] = '_';
	}

	if ( asw_steam_cloud.GetBool() && pRemoteStorage )
	{
		if ( !GetFileFromRemoteStorage( pRemoteStorage, "PersistentMarines.dat", szMedalFile ) )
		{
#ifdef _DEBUG
			Warning( "Failed to get client.dat from Steam Cloud.\n" );
#endif
		}
	}
#endif

	// clear out the currently loaded medals, if any
	for (int i=0;i<ASW_NUM_MARINE_PROFILES;i++)
	{
		m_MarineMedals[i].Purge();
		m_OfflineMarineMedals[i].Purge();
	}
	m_PlayerMedals.Purge();
	m_OfflinePlayerMedals.Purge();

	m_bLoaded = true;

	FileHandle_t f = filesystem->Open( szMedalFile, "rb", "MOD" );
	if ( !f )
		return;		// if we get here, it means the player has no clientc.dat file and therefore no medals

	int fileSize = filesystem->Size(f);
	char *file_buffer = (char*)MemAllocScratch(fileSize + 1);
	Assert(file_buffer);
	filesystem->Read(file_buffer, fileSize, f); // read into local buffer
	file_buffer[fileSize] = 0; // null terminate file as EOF
	filesystem->Close( f );	// close file after reading

	UTIL_DecodeICE( (unsigned char*)file_buffer, fileSize, g_ucMedalStoreEncryptionKey );

	KeyValues *kv = new KeyValues( "CLIENTDAT" );
	if ( !kv->LoadFromBuffer( "CLIENTDAT", file_buffer, filesystem ) )
	{
		return;
	}

	MemFreeScratch();

	m_bFoundNewClientDat = true;

	// pull out missions/campaigns/kills
	m_iMissionsCompleted = kv->GetInt("MC");
	m_iCampaignsCompleted = kv->GetInt("CC");
	m_iAliensKilled = kv->GetInt("AK");

	m_iOfflineMissionsCompleted = kv->GetInt("OMC");
	m_iOfflineCampaignsCompleted = kv->GetInt("OCC");
	m_iOfflineAliensKilled = kv->GetInt("OAK");

	m_iXP = kv->GetInt( "LPL" );
	m_iPromotion = kv->GetInt( "LPP" );

	// new equip
	m_NewEquipment.Purge();
	KeyValues *pkvEquip = kv->FindKey("NEWEQUIP");
	char buffer[64];
	if ( pkvEquip )	
	{
		for ( KeyValues *pKey = pkvEquip->GetFirstSubKey(); pKey; pKey = pKey->GetNextKey() )
		{
			m_NewEquipment.AddToTail( pKey->GetInt() );
		}
	}
	
	// first subsection is player medals
	//KeyValues *pkvPlayerMedals = kv->GetFirstSubKey();
	KeyValues *pkvPlayerMedals = kv->FindKey("LP");
	int iMedalNum = 0;
	if (pkvPlayerMedals)	
	{
		int iMedal = 0;
		while (iMedal != -1)
		{
			Q_snprintf(buffer, sizeof(buffer), "M%d", iMedalNum);			
			iMedal = pkvPlayerMedals->GetInt(buffer, -1);
			if (iMedal != -1 && IsPlayerMedal(iMedal))
			{
				m_PlayerMedals.AddToTail(iMedal);
			}
			iMedalNum++;
		}
	}

	// now go through each marine
	for (int i=0;i<ASW_NUM_MARINE_PROFILES;i++)
	{
		Q_snprintf(buffer, sizeof(buffer), "LA%d", i);
		KeyValues *pkvMarineMedals = kv->FindKey(buffer);
		if (pkvMarineMedals)
		{
			iMedalNum = 0;
			int iMedal = 0;
			while (iMedal != -1)
			{
				Q_snprintf(buffer, sizeof(buffer), "M%d", iMedalNum);			
				iMedal = pkvMarineMedals->GetInt(buffer, -1);
				if (iMedal != -1 && !IsPlayerMedal(iMedal))
				{
					m_MarineMedals[i].AddToTail(iMedal);
				}
				iMedalNum++;
			}
		}
	}

	// offline medal store
	pkvPlayerMedals = kv->FindKey("FP");
	iMedalNum = 0;
	if (pkvPlayerMedals)	
	{
		int iMedal = 0;
		while (iMedal != -1)
		{
			Q_snprintf(buffer, sizeof(buffer), "M%d", iMedalNum);			
			iMedal = pkvPlayerMedals->GetInt(buffer, -1);
			if (iMedal != -1 && IsPlayerMedal(iMedal))
			{
				m_OfflinePlayerMedals.AddToTail(iMedal);
			}
			iMedalNum++;
		}
	}

	// now go through each marine
	for (int i=0;i<ASW_NUM_MARINE_PROFILES;i++)
	{
		Q_snprintf(buffer, sizeof(buffer), "FA%d", i);
		KeyValues *pkvMarineMedals = kv->FindKey(buffer);
		if (pkvMarineMedals)
		{
			iMedalNum = 0;
			int iMedal = 0;
			while (iMedal != -1)
			{
				Q_snprintf(buffer, sizeof(buffer), "M%d", iMedalNum);			
				iMedal = pkvMarineMedals->GetInt(buffer, -1);
				if (iMedal != -1 && !IsPlayerMedal(iMedal))
				{
					m_OfflineMarineMedals[i].AddToTail(iMedal);
				}
				iMedalNum++;
			}
		}
	}
}
void ControlPanel::CenterOnFace( void )
{
	if ( !models->GetActiveStudioModel() )
		return;

	StudioModel *mdl = models->GetActiveStudioModel();
	if ( !mdl )
		return;

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

	setSpeed( 1.0f );

	int oldSeq = models->GetActiveStudioModel()->GetSequence();

	int seq = models->GetActiveStudioModel()->LookupSequence( "idle_suble" );
	if ( seq == -1 )
		seq = 0;

	if ( seq != oldSeq )
	{
		Con_Printf( "Centering changed model sequence # to %d\n", seq );
	}

	setSequence( seq );
	initPoseParameters( );

	mdl->m_angles.Init();
	mdl->m_origin.Init();

	Vector size;
	VectorSubtract( hdr->hull_max(), hdr->hull_min(), size );

	float eyeheight = hdr->hull_min().z + 0.9 * size.z;

	if ( hdr->GetNumAttachments() > 0 )
	{
		for (int i = 0; i < hdr->GetNumAttachments(); i++)
		{
			const mstudioattachment_t &attachment = hdr->pAttachment( i );
			int iBone = hdr->GetAttachmentBone( i );

			if ( Q_stricmp( attachment.pszName(), "eyes" ) )
				continue;

			mstudiobone_t *bone = hdr->pBone( iBone );
			if ( !bone )
				continue;

			matrix3x4_t boneToPose;
			MatrixInvert( bone->poseToBone, boneToPose );

			matrix3x4_t attachmentPoseToLocal;
			ConcatTransforms( boneToPose, attachment.local, attachmentPoseToLocal );

			Vector localSpaceEyePosition;
			VectorITransform( vec3_origin, attachmentPoseToLocal, localSpaceEyePosition );

			// Not sure why this must be negative?
			eyeheight = -localSpaceEyePosition.z + hdr->hull_min().z;
			break;
		}
	}

	KeyValues *seqKeyValues = new KeyValues("");
	if ( seqKeyValues->LoadFromBuffer( mdl->GetFileName( ), mdl->GetKeyValueText( seq ) ) )
	{
		// Do we have a build point section?
		KeyValues *pkvAllFaceposer = seqKeyValues->FindKey("faceposer");
		if ( pkvAllFaceposer )
		{
			float flEyeheight = pkvAllFaceposer->GetFloat( "eye_height", -9999.0f );
			if ( flEyeheight != -9999.0f )
			{
				eyeheight = flEyeheight;
			}
		}
	}

	seqKeyValues->deleteThis();

	mdl->m_origin.x = size.z * .65f;
	mdl->m_origin.z += eyeheight;

	CUtlVector< StudioModel * > modellist;

	modellist.AddToTail( models->GetActiveStudioModel() );

	int i;
	if ( models->CountVisibleModels() > 0 )
	{
		modellist.RemoveAll();
		for ( i = 0; i < models->Count(); i++ )
		{
			if ( models->IsModelShownIn3DView( i ) )
			{
				modellist.AddToTail( models->GetStudioModel( i ) );
			}
		}
	}

	int modelcount = modellist.Count();
	int countover2 = modelcount / 2;
	int ydelta = GetModelGap();
	int yoffset = -countover2 * ydelta;
	for ( i = 0 ; i < modelcount; i++ )
	{
		if ( models->GetStudioHeader( i ) == hdr )
		{
			mdl->m_origin.y = -yoffset;
		}
		yoffset += ydelta;
	}

	g_pMatSysWindow->redraw();
}