示例#1
0
KeyValues* VMFExporter::GetViewSettings()
{
    KeyValues *pKeys = new KeyValues( "viewsettings" );
    pKeys->SetBool( "bSnapToGrid", true );
    pKeys->SetBool( "bShowGrid", true );
    pKeys->SetBool( "bShowLogicalGrid", false );
    pKeys->SetInt( "nGridSpacing", ASW_TILE_SIZE );
    pKeys->SetBool( "bShow3DGrid", false );
    return pKeys;
}
示例#2
0
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CEditorSystem::CopySelection()
{
	ClearCopyCommands();

	if( !IsAnythingSelected() )
		return;

	Vector vCopyOffset(64.0f, 64.0f, 0.0f );
	for( int i = 0; i < m_hSelectedEntities.Count(); i++ )
	{
		if( !m_hSelectedEntities[i] )
			continue;

		CWarsFlora *pFlora = dynamic_cast<CWarsFlora *>( m_hSelectedEntities[i].Get() );
		if( pFlora )
		{
			KeyValues *pOperation = CreateFloraCreateCommand( pFlora, &vCopyOffset );
			pOperation->SetBool( "select", true );
			m_SelectionCopyCommands.AddToTail( pOperation );
		}
		else
		{
			Warning( "CEditorSystem::CopySelection: Trying to copy an unsupported entity\n" );
		}
	}
}
示例#3
0
//-----------------------------------------------------------------------------
// Purpose: Saves the version information chunk.
// Input  : *pFile -
// Output : Returns ChunkFile_Ok on success, an error code on failure.
//-----------------------------------------------------------------------------
KeyValues* VMFExporter::GetVersionInfo()
{
    KeyValues *pKeys = new KeyValues( "versioninfo" );
    pKeys->SetInt( "editorversion", 400 );
    pKeys->SetInt( "editorbuild", 3900 );
    pKeys->SetInt( "mapversion", 1 );
    pKeys->SetInt( "formatversion", 100 );
    pKeys->SetBool( "prefab", false );
    return pKeys;
}
示例#4
0
bool CLevelTheme::SaveTheme(const char *pszThemeName)
{
	char szFullFileName[MAX_PATH];
	Q_snprintf(szFullFileName, sizeof(szFullFileName), "tilegen/themes/%s.theme", pszThemeName);
	KeyValues *pThemeKeyValues = new KeyValues( pszThemeName );
	pThemeKeyValues->SetString("ThemeName", m_szName);
	pThemeKeyValues->SetString("ThemeDescription", m_szDescription);
	pThemeKeyValues->SetBool( "VMFTweak", m_bRequiresVMFTweak );
	pThemeKeyValues->SetBool( "SkipErrorCheck", m_bSkipErrorCheck );
	char buffer[128];
	Q_snprintf( buffer, sizeof( buffer ), "%f %f %f", m_vecAmbientLight.x, m_vecAmbientLight.y, m_vecAmbientLight.z );
	pThemeKeyValues->SetString( "AmbientLight", buffer );
	if (!pThemeKeyValues->SaveToFile(g_pFullFileSystem, szFullFileName, "GAME"))
	{
		Msg("Error: Failed to save theme %s\n", szFullFileName);
		return false;
	}
	// TODO: check the room templates folder for this theme exists
	return true;
}
示例#5
0
bool CRoomTemplate::SaveRoomTemplate()
{
    if (!m_pLevelTheme)
        return false;

    char szThemeDirName[MAX_PATH];
    Q_snprintf(szThemeDirName, sizeof(szThemeDirName), "tilegen/roomtemplates/%s", m_pLevelTheme->m_szName);
    g_pFullFileSystem->CreateDirHierarchy( szThemeDirName, "GAME" );

    char szFullFileName[MAX_PATH];
    Q_snprintf( szFullFileName, sizeof(szFullFileName), "tilegen/roomtemplates/%s/%s.roomtemplate", m_pLevelTheme->m_szName, m_FullName );
    KeyValues *pRoomTemplateKeyValues = new KeyValues( m_FullName );
    pRoomTemplateKeyValues->SetInt( "TilesX", m_nTilesX );
    pRoomTemplateKeyValues->SetInt( "TilesY", m_nTilesY );
    pRoomTemplateKeyValues->SetInt( "SpawnWeight", m_nSpawnWeight );
    pRoomTemplateKeyValues->SetString( "RoomTemplateDescription", m_Description );
    pRoomTemplateKeyValues->SetString( "Soundscape", m_Soundscape );
    pRoomTemplateKeyValues->SetInt( "TileType", m_nTileType );

    // exits
    int iExits = m_Exits.Count();
    for (int i=0; i<iExits; i++)
    {
        KeyValues *pkvSubSection = new KeyValues("EXIT");
        pkvSubSection->SetInt("XPos", m_Exits[i]->m_iXPos);
        pkvSubSection->SetInt("YPos", m_Exits[i]->m_iYPos);
        pkvSubSection->SetInt("ExitDirection", (int) m_Exits[i]->m_ExitDirection);
        pkvSubSection->SetInt("ZChange", m_Exits[i]->m_iZChange);
        pkvSubSection->SetString("ExitTag", m_Exits[i]->m_szExitTag);
        pkvSubSection->SetBool("ChokeGrow", m_Exits[i]->m_bChokepointGrowSource);

        pRoomTemplateKeyValues->AddSubKey(pkvSubSection);
    }

    // tags
    KeyValues *pkvSubSection = new KeyValues("Tags");
    for ( int i=0; i<GetNumTags(); i++ )
    {
        pkvSubSection->AddSubKey( new KeyValues( "tag", NULL, GetTag( i ) ) );
    }
    pRoomTemplateKeyValues->AddSubKey(pkvSubSection);

    if (!pRoomTemplateKeyValues->SaveToFile(g_pFullFileSystem, szFullFileName, "GAME"))
    {
        Msg("Error: Failed to save room template %s\n", szFullFileName);
        return false;
    }
    return true;
}
示例#6
0
void FinishClientPutInServer( CHL2MP_Player *pPlayer )
{
	pPlayer->InitialSpawn();
	//BB: we dont want players to spawn immediately when joining the server, we want them to auto spectate
	//pPlayer->Spawn();
	pPlayer->ChangeTeam( TEAM_SPECTATOR );


	char sName[128];
	Q_strncpy( sName, pPlayer->GetPlayerName(), sizeof( sName ) );
	
	// First parse the name and remove any %'s
	for ( char *pApersand = sName; pApersand != NULL && *pApersand != 0; pApersand++ )
	{
		// Replace it with a space
		if ( *pApersand == '%' )
				*pApersand = ' ';
	}

	// notify other clients of player joining the game
	UTIL_ClientPrintAll( HUD_PRINTNOTIFY, "#Game_connected", sName[0] != 0 ? sName : "<unconnected>" );

	if ( HL2MPRules()->IsTeamplay() == true )
	{
		ClientPrint( pPlayer, HUD_PRINTTALK, "You are on team %s1\n", pPlayer->GetTeam()->GetName() );
	}

	const ConVar *hostname = cvar->FindVar( "hostname" );
	const char *title = (hostname) ? hostname->GetString() : "MESSAGE OF THE DAY";

	KeyValues *data = new KeyValues("data");
	data->SetString( "title", title );		// info panel title
	data->SetString( "type", "1" );			// show userdata from stringtable entry
	data->SetString( "msg",	"motd" );		// use this stringtable entry
	data->SetBool( "unload", sv_motd_unload_on_dismissal.GetBool() );

	//BB: Display the team selection panel...
	pPlayer->ShowViewPortPanel( PANEL_TEAM, true, data );
	pPlayer->ShowViewPortPanel( PANEL_INFO, true, data );

	data->deleteThis();
}
示例#7
0
    // loop through all the maps checking filters
    FOR_EACH_VEC(m_vecMaps, i)
    {
        mapdisplay_t &map = m_vecMaps[i];
        mapstruct_t* mapinfo = &map.m_mMap;
        //DevLog("CURRENTLY FILTERING %s\n", mapinfo->m_szMapName);
        if (!CheckPrimaryFilters(*mapinfo) || !CheckSecondaryFilters(*mapinfo))//MOM_TODO: change this to just one filter check?
        {
            //Failed filters, remove the map
            map.m_bDoNotRefresh = true;
            if (m_pGameList->IsValidItemID(map.m_iListID))
            {
                m_pGameList->SetItemVisible(map.m_iListID, false);
            }
        }
        else if (BShowMap(map))
        {
            map.m_bDoNotRefresh = false;
            if (!m_pGameList->IsValidItemID(map.m_iListID))
            {
                //DevLog("ADDING MAP TO LIST! %s\n ", mapinfo->m_szMapName);
                KeyValues *kv = new KeyValues("Map");
                kv->SetString("name", mapinfo->m_szMapName);
                kv->SetString("map", mapinfo->m_szMapName);
                kv->SetInt("gamemode", mapinfo->m_iGameMode);
                kv->SetInt("difficulty", mapinfo->m_iDifficulty);
                kv->SetInt("MapLayout", ((int)mapinfo->m_bHasStages) + 2);//+ 2 so the picture sets correctly
                kv->SetBool("HasCompleted", mapinfo->m_bCompleted);
                kv->SetString("time", mapinfo->m_szBestTime);

                map.m_iListID = m_pGameList->AddItem(kv, NULL, false, false);
                kv->deleteThis();
            }
            // make sure the map is visible
            m_pGameList->SetItemVisible(map.m_iListID, true);
        }
    }
示例#8
0
static void saveZonFile(const char* szMapName)
{
    KeyValues* zoneKV = new KeyValues(szMapName);
    CBaseEntity* pEnt = gEntList.FindEntityByClassname(NULL, "trigger_momentum_*");
    while (pEnt)
    {
        KeyValues* subKey = NULL;
        if (pEnt->ClassMatches("trigger_momentum_timer_start"))
        {
            CTriggerTimerStart* pTrigger = dynamic_cast<CTriggerTimerStart*>(pEnt);
            subKey = new KeyValues("start");
            if (pTrigger)
            {
                subKey->SetFloat("leavespeed", pTrigger->GetMaxLeaveSpeed());
                subKey->SetBool("limitingspeed", pTrigger->IsLimitingSpeed());
            }
        }
        else if (pEnt->ClassMatches("trigger_momentum_timer_stop"))
        {
            subKey = new KeyValues("end");
        }
        else if (pEnt->ClassMatches("trigger_momentum_timer_checkpoint"))
        {
            CTriggerCheckpoint* pTrigger = dynamic_cast<CTriggerCheckpoint*>(pEnt);
            if (pTrigger)
            {
                subKey = new KeyValues("checkpoint");
                subKey->SetInt("number", pTrigger->GetCheckpointNumber());
            }
        }
        else if (pEnt->ClassMatches("trigger_momentum_onehop"))
        {
            CTriggerOnehop* pTrigger = dynamic_cast<CTriggerOnehop*>(pEnt);
            if (pTrigger)
            {
                subKey = new KeyValues("onehop");
                //subKey->SetInt("destination", pTrigger->GetDestinationIndex());
                subKey->SetBool("stop", pTrigger->ShouldStopPlayer());
                subKey->SetBool("resetang", pTrigger->ShouldResetAngles());
                subKey->SetFloat("hold", pTrigger->GetHoldTeleportTime());
                subKey->SetString("destinationname", pTrigger->m_target.ToCStr());
            }
        }
        else if (pEnt->ClassMatches("trigger_momentum_resetonehop"))
        {
            subKey = new KeyValues("resetonehop");
        }
        else if (pEnt->ClassMatches("trigger_momentum_teleport_checkpoint"))
        {

            CTriggerTeleportCheckpoint* pTrigger = dynamic_cast<CTriggerTeleportCheckpoint*>(pEnt);
            if (pTrigger)
            {
                subKey = new KeyValues("checkpoint_teleport");
                //subKey->SetInt("destination", pTrigger->GetDestinationCheckpointNumber());
                subKey->SetBool("stop", pTrigger->ShouldStopPlayer());
                subKey->SetBool("resetang", pTrigger->ShouldResetAngles());
                subKey->SetString("destinationname", pTrigger->m_target.ToCStr());
            }
        }
        else if (pEnt->ClassMatches("trigger_momentum_multihop"))
        {
            CTriggerMultihop* pTrigger = dynamic_cast<CTriggerMultihop*>(pEnt);
            if (pTrigger)
            {
                subKey = new KeyValues("multihop");
                //subKey->SetInt("destination", pTrigger->GetDestinationIndex());
                subKey->SetBool("stop", pTrigger->ShouldStopPlayer());
                subKey->SetFloat("hold", pTrigger->GetHoldTeleportTime());
                subKey->SetBool("resetang", pTrigger->ShouldResetAngles());
                subKey->SetString("destinationname", pTrigger->m_target.ToCStr());
            }
        }
        else if (pEnt->ClassMatches("trigger_momentum_timer_stage"))
        {
            CTriggerStage *pTrigger = dynamic_cast<CTriggerStage*>(pEnt);
            if (pTrigger)
            {
                subKey = new KeyValues("stage");
                subKey->SetInt("number", pTrigger->GetStageNumber());
            }
        }
        if (subKey)
        {
            subKey->SetFloat("xPos", pEnt->GetAbsOrigin().x);
            subKey->SetFloat("yPos", pEnt->GetAbsOrigin().y);
            subKey->SetFloat("zPos", pEnt->GetAbsOrigin().z);
            subKey->SetFloat("xRot", pEnt->GetAbsAngles().x);
            subKey->SetFloat("yRot", pEnt->GetAbsAngles().y);
            subKey->SetFloat("zRot", pEnt->GetAbsAngles().z);
            subKey->SetFloat("xScaleMins", pEnt->WorldAlignMins().x);
            subKey->SetFloat("yScaleMins", pEnt->WorldAlignMins().y);
            subKey->SetFloat("zScaleMins", pEnt->WorldAlignMins().z);
            subKey->SetFloat("xScaleMaxs", pEnt->WorldAlignMaxs().x);
            subKey->SetFloat("yScaleMaxs", pEnt->WorldAlignMaxs().y);
            subKey->SetFloat("zScaleMaxs", pEnt->WorldAlignMaxs().z);
            zoneKV->AddSubKey(subKey);
        }
        pEnt = gEntList.FindEntityByClassname(pEnt, "trigger_momentum_*");
    }
    if (zoneKV->GetFirstSubKey())//not empty 
    {
        char zoneFilePath[MAX_PATH];
        Q_strcpy(zoneFilePath, "maps/");
        Q_strcat(zoneFilePath, szMapName, MAX_PATH);
        Q_strncat(zoneFilePath, ".zon", MAX_PATH);
        zoneKV->SaveToFile(filesystem, zoneFilePath, "MOD");
        zoneKV->deleteThis();
    }
}
示例#9
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CEditorSystem::DoSelect( CHL2WarsPlayer *pPlayer )
{
#ifndef CLIENT_DLL
	// Sync from client
	return;
#endif // CLIENT_DLL

	Vector vPos = pPlayer->Weapon_ShootPosition();
	const Vector &vMouseAim = pPlayer->GetMouseAim();
	const Vector &vCamOffset = pPlayer->GetCameraOffset();

	Vector vStartPos, vEndPos;
	vStartPos = vPos + vCamOffset;
	vEndPos = vStartPos + (vMouseAim *  MAX_TRACE_LENGTH);

	//NDebugOverlay::Line( vStartPos, vEndPos, 0, 255, 0, true, 4.0f );

	Ray_t pickerRay;
	pickerRay.Init( vStartPos, vEndPos );

	CWarsFlora *pBest = NULL;
	float fBestDistance = 0;

#ifdef CLIENT_DLL
	for( CBaseEntity *pEntity = ClientEntityList().FirstBaseEntity(); pEntity; pEntity = ClientEntityList().NextBaseEntity( pEntity ) )
#else
	for( CBaseEntity *pEntity = gEntList.FirstEnt(); pEntity != NULL; pEntity = gEntList.NextEnt( pEntity ) )
#endif // CLIENT_DLL
	{
		CWarsFlora *pFlora = dynamic_cast<CWarsFlora *>( pEntity );
		if( pFlora )
		{
			// Prefer testing against hitboxes
			// If no hitboxes available, use the bounding box
			trace_t trace;
			bool bTestedHitBoxes = pFlora->TestHitboxes( pickerRay, MASK_SOLID, trace );
			if( bTestedHitBoxes )
			{
				if( trace.DidHit() )
				{
					float fDistance = trace.endpos.DistTo( vStartPos );
					if( !pBest || fDistance < fBestDistance )
					{
						pBest = pFlora;
						fBestDistance = fDistance;
					}
				}
			}
			else
			{
				CBaseTrace trace2;
				if ( IntersectRayWithBox( pickerRay,
					pFlora->GetAbsOrigin() + pFlora->CollisionProp()->OBBMins(), pFlora->GetAbsOrigin() + pFlora->CollisionProp()->OBBMaxs(),
					0.5f, &trace2 ) )
				{
					float fDistance = trace2.endpos.DistTo( vStartPos );
					if( !pBest || fDistance < fBestDistance )
					{
						pBest = pFlora;
						fBestDistance = fDistance;
					}
				}
			}
		}
	}

	if( pBest )
	{
		if( !IsSelected( pBest ) )
		{
			Select( pBest );

			KeyValues *pOperation = new KeyValues( "data" );
			pOperation->SetString("operation", "select");
			KeyValues *pFloraKey = new KeyValues( "flora", "uuid", pBest->GetFloraUUID() );
			pFloraKey->SetBool(  "select", true );
			pOperation->AddSubKey( pFloraKey );
			warseditorstorage->QueueServerCommand( pOperation );
		}
		else
		{
			Deselect( pBest );

			KeyValues *pOperation = new KeyValues( "data" );
			pOperation->SetString("operation", "select");
			KeyValues *pFloraKey = new KeyValues( "flora", "uuid", pBest->GetFloraUUID() );
			pFloraKey->SetBool(  "select", false );
			pOperation->AddSubKey( pFloraKey );
			warseditorstorage->QueueServerCommand( pOperation );
		}
		//NDebugOverlay::Box( pBest->GetAbsOrigin(), -Vector(8, 8, 8), Vector(8, 8, 8), 0, 255, 0, 255, 5.0f);
	}
}
示例#10
0
// saves current save data to a keyvalues file
bool CASW_Campaign_Save::SaveGameToFile(const char *szFileName)
{
	// make sure the path and extension are correct
	char szFullFileName[256];
	char tempbuffer[256];
	if (szFileName==NULL)
	{
		if (m_CurrentSaveFileName == NULL_STRING)
		{
			Msg("Error: Couldn't save game to file as we have no name already and you didn't supply one.\n");
			return false;
		}
		Q_snprintf(szFullFileName, sizeof(szFullFileName), "%s", STRING(m_CurrentSaveFileName));
	}
	else
	{
		Q_snprintf(tempbuffer, sizeof(tempbuffer), "%s", szFileName);	
		Q_SetExtension( tempbuffer, ".campaignsave", sizeof(tempbuffer) );
		const char *pszNoPathName = Q_UnqualifiedFileName(tempbuffer);	
		Q_snprintf(szFullFileName, sizeof(szFullFileName), "save/%s", pszNoPathName);
	}

	// before saving, check if this is actually a completed campaign
	if (ASWGameRules())
	{
		int iLeft = ASWGameRules()->CampaignMissionsLeft();
		if (iLeft <= 0)
		{
			Msg("Deleting completed campaign %s", szFullFileName);
			filesystem->RemoveFile( szFullFileName, "GAME" );
			
			// notify the local mission source that a save has been deleted
			if (missionchooser && missionchooser->LocalMissionSource())
			{
				const char *pszNoPathName = Q_UnqualifiedFileName(szFullFileName);
				missionchooser->LocalMissionSource()->NotifySaveDeleted(pszNoPathName);
			}
			return true;
		}
	}
	//  we don't want completed campaigns lingering on disk

	KeyValues *pSaveKeyValues = new KeyValues( "CAMPAIGNSAVE" );
	
	pSaveKeyValues->SetInt("Version", m_iVersion);
	pSaveKeyValues->SetInt("SkillLevel", m_iLowestSkillLevelPlayed);
	pSaveKeyValues->SetString("CampaignName", m_CampaignName.Get());
	pSaveKeyValues->SetInt("CurrentPosition", m_iCurrentPosition);
	pSaveKeyValues->SetInt("NumMissionsComplete", m_iNumMissionsComplete);
	pSaveKeyValues->SetInt("InitialNumMissionsComplete", m_iInitialNumMissionsComplete);
	pSaveKeyValues->SetInt("Multiplayer", m_bMultiplayerGame ? 1 : 0);
	pSaveKeyValues->SetInt( "NumDeaths", m_iNumDeaths );
	pSaveKeyValues->SetBool( "FixedSkillPoints", m_bFixedSkillPoints );

	// update date
	int year, month, dayOfWeek, day, hour, minute, second;
	missionchooser->GetCurrentTimeAndDate(&year, &month, &dayOfWeek, &day, &hour, &minute, &second);
	//year = month = dayOfWeek = day = hour = minute = second = 0;
	Q_snprintf(m_DateTime.GetForModify(), 255, "%02d/%02d/%d %02d:%02d", month, day, year, hour, minute);
	pSaveKeyValues->SetString("DateTime", m_DateTime.Get());
	
	// write out each mission's status
	KeyValues *pSubSection;
	for (int i=0; i<ASW_MAX_MISSIONS_PER_CAMPAIGN; i++)
	{
		pSubSection = new KeyValues("MISSION");
		pSubSection->SetInt("MissionID", i);
		pSubSection->SetInt("MissionComplete", m_MissionComplete[i]);
		pSubSection->SetInt("NumRetries", m_NumRetries[i]);
		pSaveKeyValues->AddSubKey(pSubSection);
	}

	// write out each marine's stats
	for (int MarineID=0; MarineID<ASW_NUM_MARINE_PROFILES; MarineID++)
	{
		pSubSection = new KeyValues("MARINE");
		pSubSection->SetInt("MarineID", MarineID);

		pSubSection->SetInt("SkillSlot0", m_iMarineSkill[MarineID][ASW_SKILL_SLOT_0]);
		pSubSection->SetInt("SkillSlot1", m_iMarineSkill[MarineID][ASW_SKILL_SLOT_1]);
		pSubSection->SetInt("SkillSlot2", m_iMarineSkill[MarineID][ASW_SKILL_SLOT_2]);
		pSubSection->SetInt("SkillSlot3", m_iMarineSkill[MarineID][ASW_SKILL_SLOT_3]);
		pSubSection->SetInt("SkillSlot4", m_iMarineSkill[MarineID][ASW_SKILL_SLOT_4]);
		pSubSection->SetInt("SkillSlotSpare", m_iMarineSkill[MarineID][ASW_SKILL_SLOT_SPARE]);

		pSubSection->SetInt("UndoSkillSlot0", m_iPreviousMarineSkill[MarineID][ASW_SKILL_SLOT_0]);
		pSubSection->SetInt("UndoSkillSlot1", m_iPreviousMarineSkill[MarineID][ASW_SKILL_SLOT_1]);
		pSubSection->SetInt("UndoSkillSlot2", m_iPreviousMarineSkill[MarineID][ASW_SKILL_SLOT_2]);
		pSubSection->SetInt("UndoSkillSlot3", m_iPreviousMarineSkill[MarineID][ASW_SKILL_SLOT_3]);
		pSubSection->SetInt("UndoSkillSlot4", m_iPreviousMarineSkill[MarineID][ASW_SKILL_SLOT_4]);
		pSubSection->SetInt("UndoSkillSlotSpare", m_iPreviousMarineSkill[MarineID][ASW_SKILL_SLOT_SPARE]);
		
		pSubSection->SetInt("ParasitesKilled", m_iParasitesKilled[MarineID]);
		pSubSection->SetString("MissionsCompleted", STRING(m_MissionsCompleteNames[MarineID]));
		pSubSection->SetString("Medals", STRING(m_Medals[MarineID]));

		int iWound = IsMarineWounded(MarineID) ? 1 : 0;		
		pSubSection->SetInt("Wounded", iWound);
		int iDead = IsMarineAlive(MarineID) ? 0 : 1;
		pSubSection->SetInt("Dead", iDead);

		pSaveKeyValues->AddSubKey(pSubSection);
	}

	// check for any new players to add to our list
	for ( int i = 1; i <= gpGlobals->maxClients; i++ )
	{
		CASW_Player* pPlayer = dynamic_cast<CASW_Player*>(UTIL_PlayerByIndex(i));

		if ( pPlayer )
		{
			// first check his network ID
			const char *pszNetworkID = pPlayer->GetASWNetworkID();
			// check if it's in our list
			bool bFound = false;
			for (int k=0;k<m_PlayerIDs.Count();k++)
			{
				const char *p = STRING(m_PlayerIDs[k]);
				if (!Q_strcmp(p, pszNetworkID))
					bFound = true;
			}
			if (!bFound)
			{
				// add it to the list
				string_t stringID = AllocPooledString(pszNetworkID);
				m_PlayerIDs.AddToTail(stringID);
			}

			// then check player name
			const char *pszPlayerName = pPlayer->GetPlayerName();
			bFound = false;
			for (int k=0;k<m_PlayerNames.Count();k++)
			{
				const char *p = STRING(m_PlayerNames[k]);
				if (!Q_strcmp(p, pszPlayerName))
					bFound = true;
			}
			if (!bFound)
			{
				// add it to the list
				string_t stringName = AllocPooledString(pszPlayerName);
				m_PlayerNames.AddToTail(stringName);				
			}
		}
	}

	pSaveKeyValues->SetInt("NumPlayers", m_PlayerNames.Count());	
	
	// write out player names
	for (int i=0; i<m_PlayerNames.Count(); i++)
	{
		pSubSection = new KeyValues("PLAYER");		
		pSubSection->SetString("PlayerName", STRING(m_PlayerNames[i]));
		pSaveKeyValues->AddSubKey(pSubSection);
	}
	// write out player IDs
	for (int i=0; i<m_PlayerIDs.Count(); i++)
	{
		pSubSection = new KeyValues("DATA");		
		pSubSection->SetString("DataBlock", STRING(m_PlayerIDs[i]));
		pSaveKeyValues->AddSubKey(pSubSection);
	}
	// write out last commanders section
	pSubSection = new KeyValues("COMM");
	for (int i=0;i<ASW_NUM_MARINE_PROFILES;i++)
	{
		char buffer[16];
		Q_snprintf(buffer, sizeof(buffer), "Comm%d", i);
		pSubSection->SetString(buffer, STRING(m_LastCommanders[i]));		
		Q_snprintf(buffer, sizeof(buffer), "Slot%d", i);
		pSubSection->SetInt( buffer, m_LastMarineResourceSlot[i] );
			
		//Ch1ckensCoop: Record which marine was primary for reservations.
		Q_snprintf(buffer, sizeof(buffer), "Primary%d", i);
		pSubSection->SetBool( buffer, m_LastPrimaryMarines[i] );
	}
	pSaveKeyValues->AddSubKey(pSubSection);

	if (pSaveKeyValues->SaveToFile(filesystem, szFullFileName))
	{
		if (missionchooser && missionchooser->LocalMissionSource())
		{
			const char *pszNoPathName = Q_UnqualifiedFileName(szFullFileName);
			missionchooser->LocalMissionSource()->OnSaveUpdated(pszNoPathName);
		}
		
		return true;
	}
	return false;
}