2024-08-29 19:18:30 -04:00
# include "qlimits.h"
# include "tier1/strtools.h"
# include "tier1/utlvector.h"
# include "asw_mission_chooser_source_local.h"
# include "KeyValues.h"
# include "filesystem.h"
# include "convar.h"
# include "asw_system.h"
// memdbgon must be the last include file in a .cpp file!!!
# include "tier0/memdbgon.h"
static FileFindHandle_t g_hmapfind = FILESYSTEM_INVALID_FIND_HANDLE ;
static FileFindHandle_t g_hcampaignfind = FILESYSTEM_INVALID_FIND_HANDLE ;
static FileFindHandle_t g_hsavedfind = FILESYSTEM_INVALID_FIND_HANDLE ;
# define ASW_SKILL_POINTS_PER_MISSION 2 // keep in sync with asw_shareddefs.h (we need a h shared between missionchooser and game dlls...)
ConVar asw_max_saves ( " asw_max_saves " , " 200 " , FCVAR_ARCHIVE , " Maximum number of multiplayer saves that will be stored on this server. " ) ;
namespace
{
//-----------------------------------------------------------------------------
// Purpose: Slightly modified strtok. Does not modify the input string. Does
// not skip over more than one separator at a time. This allows parsing
// strings where tokens between separators may or may not be present:
//
// Door01,,,0 would be parsed as "Door01" "" "" "0"
// Door01,Open,,0 would be parsed as "Door01" "Open" "" "0"
//
// Input : token - Returns with a token, or zero length if the token was missing.
// str - String to parse.
// sep - Character to use as separator. UNDONE: allow multiple separator chars
// Output : Returns a pointer to the next token to be parsed.
//-----------------------------------------------------------------------------
const char * nexttoken ( char * token , const char * str , char sep )
{
if ( ( str = = NULL ) | | ( * str = = ' \0 ' ) )
{
* token = ' \0 ' ;
return ( NULL ) ;
}
//
// Copy everything up to the first separator into the return buffer.
// Do not include separators in the return buffer.
//
while ( ( * str ! = sep ) & & ( * str ! = ' \0 ' ) )
{
* token + + = * str + + ;
}
* token = ' \0 ' ;
//
// Advance the pointer unless we hit the end of the input string.
//
if ( * str = = ' \0 ' )
{
return ( str ) ;
}
return ( + + str ) ;
}
} ;
CASW_Mission_Chooser_Source_Local : : CASW_Mission_Chooser_Source_Local ( )
{
for ( int i = 0 ; i < ASW_SAVES_PER_PAGE ; i + + ) // this array needs to be large enough for either ASW_SAVES_PER_PAGE (for when showing save games), or ASW_MISSIONS_PER_PAGE (for when showing missions) or ASW_CAMPAIGNS_PER_SCREEN (for when showing campaigns)
{
Q_snprintf ( m_missions [ i ] . m_szMissionName , sizeof ( m_missions [ i ] . m_szMissionName ) , " " ) ;
}
m_bBuiltMapList = false ;
m_bBuiltCampaignList = false ;
m_bBuiltSavedCampaignList = false ;
m_bBuildingMapList = false ;
m_bBuildingCampaignList = false ;
m_bBuildingSavedCampaignList = false ;
m_pszMapFind = NULL ;
m_pszCampaignFind = NULL ;
m_pszSavedFind = NULL ;
}
CASW_Mission_Chooser_Source_Local : : ~ CASW_Mission_Chooser_Source_Local ( )
{
m_MissionDetails . PurgeAndDeleteElements ( ) ;
m_CampaignDetails . PurgeAndDeleteElements ( ) ;
}
void CASW_Mission_Chooser_Source_Local : : OnSaveDeleted ( const char * szSaveName )
{
char fixedname [ 256 ] ;
Q_strncpy ( fixedname , szSaveName , sizeof ( fixedname ) ) ;
Q_SetExtension ( fixedname , " .campaignsave " , sizeof ( fixedname ) ) ;
// check if this save is in the list of summaries, if so, remove it
for ( int i = 0 ; i < m_SavedCampaignList . Count ( ) ; i + + )
{
if ( ! Q_stricmp ( m_SavedCampaignList [ i ] . m_szSaveName , fixedname ) )
{
m_SavedCampaignList . Remove ( i ) ;
return ;
}
}
}
void CASW_Mission_Chooser_Source_Local : : OnSaveUpdated ( const char * szSaveName )
{
// if we haven't started scanning for saves yet, don't worry about it
if ( ! m_bBuiltSavedCampaignList & & ! m_bBuildingSavedCampaignList )
return ;
// make sure it has the campaignsave extension
char stripped [ 256 ] ;
V_StripExtension ( szSaveName , stripped , sizeof ( stripped ) ) ;
char szWithExtension [ 256 ] ;
Q_snprintf ( szWithExtension , sizeof ( szWithExtension ) , " %s.campaignsave " , stripped ) ;
// check it's not already in the saved list
for ( int i = 0 ; i < m_SavedCampaignList . Count ( ) ; i + + )
{
if ( ! Q_strcmp ( m_SavedCampaignList [ i ] . m_szSaveName , szWithExtension ) )
{
m_SavedCampaignList . Remove ( i ) ;
break ;
}
}
Msg ( " Updating save game summary %s \n " , szSaveName ) ;
AddToSavedCampaignList ( szWithExtension ) ;
}
void CASW_Mission_Chooser_Source_Local : : RefreshSavedCampaigns ( )
{
m_bBuildingSavedCampaignList = false ;
m_bBuiltSavedCampaignList = false ;
BuildSavedCampaignList ( ) ;
}
void CASW_Mission_Chooser_Source_Local : : ClearMapList ( )
{
m_Items . Purge ( ) ;
}
void CASW_Mission_Chooser_Source_Local : : AddToMapList ( const char * szMapName )
{
MapListName item ;
Q_snprintf ( item . szMapName , sizeof ( item . szMapName ) , " %s " , szMapName ) ;
m_Items . Insert ( item ) ;
// check if it has an overview txt
char stripped [ MAX_PATH ] ;
V_StripExtension ( szMapName , stripped , MAX_PATH ) ;
char tempfile [ MAX_PATH ] ;
Q_snprintf ( tempfile , sizeof ( tempfile ) , " resource/overviews/%s.txt " , stripped ) ;
bool bHasOverviewOnHost = ( g_pFullFileSystem - > FileExists ( tempfile ) ) ;
//bool bNoOverview = false;
if ( ! bHasOverviewOnHost )
{
// try to load it directly from the maps folder
Q_snprintf ( tempfile , sizeof ( tempfile ) , " maps/%s.txt " , stripped ) ;
bHasOverviewOnHost = ( g_pFullFileSystem - > FileExists ( tempfile ) ) ;
}
// add it to our overview list if it has an overview
if ( bHasOverviewOnHost )
{
m_OverviewItems . Insert ( item ) ;
}
}
void CASW_Mission_Chooser_Source_Local : : BuildMapList ( )
{
if ( m_bBuildingMapList | | m_bBuiltMapList ) // already building
return ;
ClearMapList ( ) ;
m_bBuildingMapList = true ;
// Search the directory structure.
char mapwild [ MAX_QPATH ] ;
2024-08-29 19:27:02 -04:00
Q_strncpy ( mapwild , " maps/*.bsp " , sizeof ( mapwild ) ) ;
2024-08-29 19:18:30 -04:00
m_pszMapFind = Sys_FindFirst ( g_hmapfind , mapwild , NULL , 0 ) ;
// think will continue the search
}
void CASW_Mission_Chooser_Source_Local : : Think ( )
{
// if we're building the map list, continue our search of files
if ( m_bBuildingMapList )
{
if ( m_pszMapFind )
{
//Msg("Adding map: %s\n", m_pszMapFind);
AddToMapList ( m_pszMapFind ) ;
m_pszMapFind = Sys_FindNext ( g_hmapfind , NULL , 0 ) ;
}
else
{
//Msg("Ending search for maps\n");
Sys_FindClose ( g_hmapfind ) ;
m_bBuildingMapList = false ;
m_bBuiltMapList = true ;
}
}
// if we're building the campaign list, continue our search of files
if ( m_bBuildingCampaignList )
{
if ( m_pszCampaignFind )
{
//Msg("Adding campaign: %s\n", m_pszCampaignFind);
AddToCampaignList ( m_pszCampaignFind ) ;
m_pszCampaignFind = Sys_FindNext ( g_hcampaignfind , NULL , 0 ) ;
}
else
{
//Msg("Ending search for campaigns\n");
Sys_FindClose ( g_hcampaignfind ) ;
m_bBuildingCampaignList = false ;
m_bBuiltCampaignList = true ;
}
}
// if we're building the saved campaign list, continue our search of files
if ( m_bBuildingSavedCampaignList )
{
if ( m_pszSavedFind )
{
//Msg("Adding saved campaign: %s\n", m_pszSavedFind);
AddToSavedCampaignList ( m_pszSavedFind ) ;
m_pszSavedFind = Sys_FindNext ( g_hsavedfind , NULL , 0 ) ;
}
else
{
//Msg("Ending search for saved campaigns\n");
Sys_FindClose ( g_hsavedfind ) ;
m_bBuildingSavedCampaignList = false ;
m_bBuiltSavedCampaignList = true ;
}
}
}
// called when server is in a relatively idle state (like during the briefing)
// we can use this time to scan for missions if we need to
void CASW_Mission_Chooser_Source_Local : : IdleThink ( )
{
// if we're not currently building any lists, try to start building one
if ( ! m_bBuildingMapList & & ! m_bBuildingCampaignList & & ! m_bBuildingSavedCampaignList )
{
if ( ! m_bBuiltMapList )
{
BuildMapList ( ) ;
}
else
{
if ( ! m_bBuiltCampaignList )
{
BuildCampaignList ( ) ;
}
else if ( ! m_bBuiltSavedCampaignList )
{
BuildSavedCampaignList ( ) ;
}
}
}
Think ( ) ;
}
void CASW_Mission_Chooser_Source_Local : : FindMissionsInCampaign ( int iCampaignIndex , int nMissionOffset , int iNumSlots )
{
if ( ! m_bBuiltMapList )
BuildMapList ( ) ;
ASW_Mission_Chooser_Mission * pCampaign = GetCampaign ( iCampaignIndex ) ;
if ( ! pCampaign )
return ;
KeyValues * pCampaignDetails = GetCampaignDetails ( pCampaign - > m_szMissionName ) ;
if ( ! pCampaignDetails )
return ;
CUtlVector < KeyValues * > aMissionKeys ;
bool bSkippedFirst = false ;
for ( KeyValues * pMission = pCampaignDetails - > GetFirstSubKey ( ) ; pMission ; pMission = pMission - > GetNextKey ( ) )
{
if ( ! Q_stricmp ( pMission - > GetName ( ) , " MISSION " ) )
{
if ( ! bSkippedFirst )
{
bSkippedFirst = true ;
}
else
{
aMissionKeys . AddToTail ( pMission ) ;
}
}
}
int max_items = aMissionKeys . Count ( ) ;
for ( int stored = 0 ; stored < iNumSlots ; stored + + )
{
int realoffset = nMissionOffset ;
if ( realoffset > = max_items | | realoffset < 0 )
{
// no more missions...
Q_snprintf ( m_missions [ stored ] . m_szMissionName , sizeof ( m_missions [ stored ] . m_szMissionName ) , " " ) ;
}
else
{
Q_snprintf ( m_missions [ stored ] . m_szMissionName , sizeof ( m_missions [ stored ] . m_szMissionName ) , " %s " , aMissionKeys [ realoffset ] - > GetString ( " MapName " ) ) ;
}
nMissionOffset + + ;
}
}
int CASW_Mission_Chooser_Source_Local : : GetNumMissionsInCampaign ( int iCampaignIndex )
{
if ( ! m_bBuiltMapList )
BuildMapList ( ) ;
ASW_Mission_Chooser_Mission * pCampaign = GetCampaign ( iCampaignIndex ) ;
if ( ! pCampaign )
return 0 ;
KeyValues * pCampaignDetails = GetCampaignDetails ( pCampaign - > m_szMissionName ) ;
if ( ! pCampaignDetails )
return 0 ;
CUtlVector < KeyValues * > aMissionKeys ;
bool bSkippedFirst = false ;
for ( KeyValues * pMission = pCampaignDetails - > GetFirstSubKey ( ) ; pMission ; pMission = pMission - > GetNextKey ( ) )
{
if ( ! Q_stricmp ( pMission - > GetName ( ) , " MISSION " ) )
{
if ( ! bSkippedFirst )
{
bSkippedFirst = true ;
}
else
{
aMissionKeys . AddToTail ( pMission ) ;
}
}
}
return aMissionKeys . Count ( ) ;
}
void CASW_Mission_Chooser_Source_Local : : FindMissions ( int nMissionOffset , int iNumSlots , bool bRequireOverview )
{
if ( ! m_bBuiltMapList )
BuildMapList ( ) ;
int max_items = bRequireOverview ? m_OverviewItems . Count ( ) : m_Items . Count ( ) ;
for ( int stored = 0 ; stored < iNumSlots ; stored + + )
{
int realoffset = nMissionOffset ;
if ( realoffset > = max_items | | realoffset < 0 )
{
// no more missions...
Q_snprintf ( m_missions [ stored ] . m_szMissionName , sizeof ( m_missions [ stored ] . m_szMissionName ) , " " ) ;
}
else
{
if ( bRequireOverview )
{
Q_snprintf ( m_missions [ stored ] . m_szMissionName , sizeof ( m_missions [ stored ] . m_szMissionName ) , " %s " , m_OverviewItems [ realoffset ] . szMapName ) ;
}
else
{
Q_snprintf ( m_missions [ stored ] . m_szMissionName , sizeof ( m_missions [ stored ] . m_szMissionName ) , " %s " , m_Items [ realoffset ] . szMapName ) ;
}
}
nMissionOffset + + ;
}
}
// pass an array of mission names back
ASW_Mission_Chooser_Mission * CASW_Mission_Chooser_Source_Local : : GetMissions ( )
{
return m_missions ;
}
ASW_Mission_Chooser_Mission * CASW_Mission_Chooser_Source_Local : : GetMission ( int nIndex , bool bRequireOverview )
{
if ( ! m_bBuiltMapList )
BuildMapList ( ) ;
int max_items = bRequireOverview ? m_OverviewItems . Count ( ) : m_Items . Count ( ) ;
static ASW_Mission_Chooser_Mission mission ;
if ( nIndex > = max_items | | nIndex < 0 )
{
// no more missions...
Q_snprintf ( mission . m_szMissionName , sizeof ( mission . m_szMissionName ) , " " ) ;
}
else
{
if ( bRequireOverview )
{
Q_snprintf ( mission . m_szMissionName , sizeof ( mission . m_szMissionName ) , " %s " , m_OverviewItems [ nIndex ] . szMapName ) ;
}
else
{
Q_snprintf ( mission . m_szMissionName , sizeof ( mission . m_szMissionName ) , " %s " , m_Items [ nIndex ] . szMapName ) ;
}
}
return & mission ;
}
int CASW_Mission_Chooser_Source_Local : : GetNumMissions ( bool bRequireOverview )
{
if ( ! m_bBuiltMapList )
BuildMapList ( ) ;
if ( bRequireOverview )
return m_OverviewItems . Count ( ) ;
return m_Items . Count ( ) ;
}
void CASW_Mission_Chooser_Source_Local : : ClearCampaignList ( )
{
m_CampaignList . Purge ( ) ;
}
void CASW_Mission_Chooser_Source_Local : : AddToCampaignList ( const char * szCampaignName )
{
MapListName item ;
Q_snprintf ( item . szMapName , sizeof ( item . szMapName ) , " %s " , szCampaignName ) ;
m_CampaignList . Insert ( item ) ;
}
void CASW_Mission_Chooser_Source_Local : : BuildCampaignList ( )
{
if ( m_bBuildingCampaignList | | m_bBuiltCampaignList ) // already building
return ;
ClearCampaignList ( ) ;
m_bBuildingCampaignList = true ;
// Search the directory structure.
char mapwild [ MAX_QPATH ] ;
Q_strncpy ( mapwild , " resource/campaigns/*.txt " , sizeof ( mapwild ) ) ;
m_pszCampaignFind = Sys_FindFirst ( g_hcampaignfind , mapwild , NULL , 0 ) ;
// think will continue the search
}
void CASW_Mission_Chooser_Source_Local : : FindCampaigns ( int nCampaignOffset , int iNumSlots )
{
if ( ! m_bBuiltCampaignList )
BuildCampaignList ( ) ;
int max_items = m_CampaignList . Count ( ) ;
for ( int stored = 0 ; stored < iNumSlots ; stored + + )
{
int realoffset = nCampaignOffset ;
if ( stored < ASW_CAMPAIGNS_PER_PAGE )
{
if ( realoffset > = max_items | | realoffset < 0 )
{
Q_snprintf ( m_campaigns [ stored ] . m_szMissionName , sizeof ( m_campaigns [ stored ] . m_szMissionName ) , " " ) ;
}
else
{
Q_snprintf ( m_campaigns [ stored ] . m_szMissionName , sizeof ( m_campaigns [ stored ] . m_szMissionName ) , " %s " , m_CampaignList [ realoffset ] . szMapName ) ;
}
nCampaignOffset + + ;
}
}
}
// Passes an array of campaign names back
ASW_Mission_Chooser_Mission * CASW_Mission_Chooser_Source_Local : : GetCampaigns ( )
{
if ( ! m_bBuiltCampaignList )
BuildCampaignList ( ) ;
return m_campaigns ;
}
ASW_Mission_Chooser_Mission * CASW_Mission_Chooser_Source_Local : : GetCampaign ( int nIndex )
{
if ( ! m_bBuiltCampaignList )
BuildCampaignList ( ) ;
static ASW_Mission_Chooser_Mission campaign ;
int max_items = m_CampaignList . Count ( ) ;
if ( nIndex > = max_items | | nIndex < 0 )
{
Q_snprintf ( campaign . m_szMissionName , sizeof ( campaign . m_szMissionName ) , " " ) ;
}
else
{
Q_snprintf ( campaign . m_szMissionName , sizeof ( campaign . m_szMissionName ) , " %s " , m_CampaignList [ nIndex ] . szMapName ) ;
}
return & campaign ;
}
int CASW_Mission_Chooser_Source_Local : : GetNumCampaigns ( )
{
if ( ! m_bBuiltCampaignList )
BuildCampaignList ( ) ;
return m_CampaignList . Count ( ) ;
}
// todo: accept a steam ID and only find saves from that person?
void CASW_Mission_Chooser_Source_Local : : FindSavedCampaigns ( int nSaveOffset , int iNumSlots , bool bMultiplayer , const char * szFilterID )
{
if ( ! m_bBuiltSavedCampaignList )
BuildSavedCampaignList ( ) ;
int skip_entries = nSaveOffset ; // how many filter matching entries we're skipping
int max_items = m_SavedCampaignList . Count ( ) ;
int stored = 0 ;
int offset = 0 ;
// count the offset up until we've skipped the desired number of filter matching entries
while ( skip_entries > 0 & & offset < max_items )
{
if ( bMultiplayer = = m_SavedCampaignList [ offset ] . m_bMultiplayer & & SavePassesFilter ( & m_SavedCampaignList [ offset ] , szFilterID ) )
{
skip_entries - - ;
}
offset + + ;
}
while ( stored < iNumSlots & & offset < max_items )
{
//Msg("testing save %d multi = %d we want multi = %d\n", offset, m_SavedCampaignList[offset].m_bMultiplayer, bMultiplayer);
if ( bMultiplayer = = m_SavedCampaignList [ offset ] . m_bMultiplayer & & SavePassesFilter ( & m_SavedCampaignList [ offset ] , szFilterID ) )
{
Q_snprintf ( m_savedcampaigns [ stored ] . m_szSaveName , sizeof ( m_savedcampaigns [ stored ] . m_szSaveName ) , " %s " , m_SavedCampaignList [ offset ] . m_szSaveName ) ;
Q_snprintf ( m_savedcampaigns [ stored ] . m_szCampaignName , sizeof ( m_savedcampaigns [ stored ] . m_szCampaignName ) , " %s " , m_SavedCampaignList [ offset ] . m_szCampaignName ) ;
Q_snprintf ( m_savedcampaigns [ stored ] . m_szDateTime , sizeof ( m_savedcampaigns [ stored ] . m_szDateTime ) , " %s " , m_SavedCampaignList [ offset ] . m_szDateTime ) ;
Q_snprintf ( m_savedcampaigns [ stored ] . m_szPlayerNames , sizeof ( m_savedcampaigns [ stored ] . m_szPlayerNames ) , " %s " , m_SavedCampaignList [ offset ] . m_szPlayerNames ) ;
m_savedcampaigns [ stored ] . m_iMissionsComplete = m_SavedCampaignList [ offset ] . m_iMissionsComplete ;
stored + + ;
}
offset + + ;
}
// blank out any slots that didn't get filled
for ( int i = stored ; i < iNumSlots ; i + + )
{
Q_snprintf ( m_savedcampaigns [ i ] . m_szSaveName , sizeof ( m_savedcampaigns [ i ] . m_szSaveName ) , " " ) ;
Q_snprintf ( m_savedcampaigns [ i ] . m_szCampaignName , sizeof ( m_savedcampaigns [ i ] . m_szCampaignName ) , " " ) ;
Q_snprintf ( m_savedcampaigns [ i ] . m_szDateTime , sizeof ( m_savedcampaigns [ i ] . m_szDateTime ) , " " ) ;
Q_snprintf ( m_savedcampaigns [ i ] . m_szPlayerNames , sizeof ( m_savedcampaigns [ i ] . m_szPlayerNames ) , " " ) ;
m_savedcampaigns [ i ] . m_iMissionsComplete = 0 ;
}
}
ASW_Mission_Chooser_Saved_Campaign * CASW_Mission_Chooser_Source_Local : : GetSavedCampaigns ( )
{
if ( ! m_bBuiltSavedCampaignList )
BuildSavedCampaignList ( ) ;
return m_savedcampaigns ;
}
ASW_Mission_Chooser_Saved_Campaign * CASW_Mission_Chooser_Source_Local : : GetSavedCampaign ( int nIndex , bool bMultiplayer , const char * szFilterID )
{
if ( ! m_bBuiltSavedCampaignList )
BuildSavedCampaignList ( ) ;
int skip_entries = nIndex ; // how many filter matching entries we're skipping
int max_items = m_SavedCampaignList . Count ( ) ;
int offset = 0 ;
// count the offset up until we've skipped the desired number of filter matching entries
while ( skip_entries > 0 & & offset < max_items )
{
if ( bMultiplayer = = m_SavedCampaignList [ offset ] . m_bMultiplayer & & SavePassesFilter ( & m_SavedCampaignList [ offset ] , szFilterID ) )
{
skip_entries - - ;
}
offset + + ;
}
static ASW_Mission_Chooser_Saved_Campaign save ;
Q_snprintf ( save . m_szSaveName , sizeof ( save . m_szSaveName ) , " %s " , m_SavedCampaignList [ offset ] . m_szSaveName ) ;
Q_snprintf ( save . m_szCampaignName , sizeof ( save . m_szCampaignName ) , " %s " , m_SavedCampaignList [ offset ] . m_szCampaignName ) ;
Q_snprintf ( save . m_szDateTime , sizeof ( save . m_szDateTime ) , " %s " , m_SavedCampaignList [ offset ] . m_szDateTime ) ;
Q_snprintf ( save . m_szPlayerNames , sizeof ( save . m_szPlayerNames ) , " %s " , m_SavedCampaignList [ offset ] . m_szPlayerNames ) ;
save . m_iMissionsComplete = m_SavedCampaignList [ offset ] . m_iMissionsComplete ;
return & save ;
}
bool CASW_Mission_Chooser_Source_Local : : SavePassesFilter ( ASW_Mission_Chooser_Saved_Campaign * pSaved , const char * szFilterID )
{
if ( ! pSaved )
return false ;
if ( ! szFilterID | | Q_strlen ( szFilterID ) < 1 )
return true ;
// check our filterID is present in the playerids with this save
const char * p = pSaved - > m_szPlayerIDs ;
char token [ 128 ] ;
p = nexttoken ( token , p , ' ' ) ;
while ( Q_strlen ( token ) > 0 )
{
// found a match
if ( ! Q_stricmp ( szFilterID , token ) )
return true ;
if ( p )
p = nexttoken ( token , p , ' ' ) ;
else
token [ 0 ] = ' \0 ' ;
}
return false ;
}
int CASW_Mission_Chooser_Source_Local : : GetNumSavedCampaigns ( bool bMultiplayer , const char * szFilterID )
{
int iNumSaves = 0 ;
for ( int i = 0 ; i < m_SavedCampaignList . Count ( ) ; i + + )
{
if ( m_SavedCampaignList [ i ] . m_bMultiplayer = = bMultiplayer & & SavePassesFilter ( & m_SavedCampaignList [ i ] , szFilterID ) )
{
iNumSaves + + ;
}
}
return iNumSaves ;
}
void CASW_Mission_Chooser_Source_Local : : ClearSavedCampaignList ( )
{
m_SavedCampaignList . Purge ( ) ;
}
void CASW_Mission_Chooser_Source_Local : : AddToSavedCampaignList ( const char * szSaveName )
{
// find out what campaign this save is for
char szFullFileName [ 256 ] ;
Q_snprintf ( szFullFileName , sizeof ( szFullFileName ) , " save/%s " , szSaveName ) ;
KeyValues * pSaveKeyValues = new KeyValues ( szSaveName ) ;
if ( pSaveKeyValues - > LoadFromFile ( g_pFullFileSystem , szFullFileName ) )
{
const char * pCampaignName = pSaveKeyValues - > GetString ( " CampaignName " ) ;
// check the campaign exists
char tempfile [ MAX_PATH ] ;
Q_snprintf ( tempfile , sizeof ( tempfile ) , " resource/campaigns/%s.txt " , pCampaignName ) ;
if ( g_pFullFileSystem - > FileExists ( tempfile ) )
{
ASW_Mission_Chooser_Saved_Campaign item ;
Q_snprintf ( item . m_szSaveName , sizeof ( item . m_szSaveName ) , " %s " , szSaveName ) ;
Q_snprintf ( item . m_szCampaignName , sizeof ( item . m_szCampaignName ) , " %s " , pCampaignName ) ;
Q_snprintf ( item . m_szDateTime , sizeof ( item . m_szDateTime ) , " %s " , pSaveKeyValues - > GetString ( " DateTime " ) ) ;
//Msg("save %s multiplayer %d\n", szSaveName, pSaveKeyValues->GetInt("Multiplayer"));
item . m_bMultiplayer = ( pSaveKeyValues - > GetInt ( " Multiplayer " ) > 0 ) ;
//Msg("item multiplayer = %d\n", item.m_bMultiplayer);
// check subsections for player names and player IDs, concat them into two strings
char namebuffer [ 256 ] ;
char idbuffer [ 512 ] ;
namebuffer [ 0 ] = ' \0 ' ;
idbuffer [ 0 ] = ' \0 ' ;
int namepos = 0 ;
int idpos = 0 ;
KeyValues * pkvSubSection = pSaveKeyValues - > GetFirstSubKey ( ) ;
while ( pkvSubSection )
{
if ( ( Q_stricmp ( pkvSubSection - > GetName ( ) , " PLAYER " ) = = 0 ) & & namepos < 253 )
{
const char * pName = pkvSubSection - > GetString ( " PlayerName " ) ;
if ( pName & & pName [ 0 ] ! = ' \0 ' )
{
int namelength = Q_strlen ( pName ) ;
for ( int charcopy = 0 ; charcopy < namelength & & namepos < 253 ; charcopy + + )
{
namebuffer [ namepos ] = pName [ charcopy ] ;
namepos + + ;
}
namebuffer [ namepos ] = ' ' ; namepos + + ;
namebuffer [ namepos ] = ' \0 ' ;
}
}
if ( ( Q_stricmp ( pkvSubSection - > GetName ( ) , " DATA " ) = = 0 ) & & idpos < 253 )
{
const char * pID = pkvSubSection - > GetString ( " DataBlock " ) ;
if ( pID & & pID [ 0 ] ! = ' \0 ' )
{
int idlength = Q_strlen ( pID ) ;
for ( int charcopy = 0 ; charcopy < idlength & & idpos < 253 ; charcopy + + )
{
idbuffer [ idpos ] = pID [ charcopy ] ;
idpos + + ;
}
idbuffer [ idpos ] = ' ' ; idpos + + ;
idbuffer [ idpos ] = ' \0 ' ;
}
}
pkvSubSection = pkvSubSection - > GetNextKey ( ) ;
}
Q_snprintf ( item . m_szPlayerNames , sizeof ( item . m_szPlayerNames ) , " %s " , namebuffer ) ;
Q_snprintf ( item . m_szPlayerIDs , sizeof ( item . m_szPlayerIDs ) , " %s " , idbuffer ) ;
item . m_iMissionsComplete = pSaveKeyValues - > GetInt ( " NumMissionsComplete " ) ;
m_SavedCampaignList . Insert ( item ) ;
}
}
pSaveKeyValues - > deleteThis ( ) ;
// check if there's now too many save games
int iNumMultiplayer = GetNumSavedCampaigns ( true , NULL ) ;
if ( iNumMultiplayer > asw_max_saves . GetInt ( ) )
{
// find the oldest one
ASW_Mission_Chooser_Saved_Campaign * pChosen = false ;
int iChosen = - 1 ;
for ( int i = m_SavedCampaignList . Count ( ) - 1 ; i > = 0 ; i - - )
{
if ( m_SavedCampaignList [ i ] . m_bMultiplayer )
{
pChosen = & m_SavedCampaignList [ i ] ;
iChosen = i ;
break ;
}
}
// delete if found
if ( iChosen ! = - 1 & & pChosen )
{
char buffer [ MAX_PATH ] ;
Q_snprintf ( buffer , sizeof ( buffer ) , " save/%s " , pChosen - > m_szSaveName ) ;
Msg ( " Deleting save %s as we have too many \n " , buffer ) ;
g_pFullFileSystem - > RemoveFile ( buffer , " GAME " ) ;
m_SavedCampaignList . Remove ( iChosen ) ;
}
}
}
void CASW_Mission_Chooser_Source_Local : : BuildSavedCampaignList ( )
{
// don't start searching for saves until we've loaded in all the campaigns
if ( ! m_bBuiltCampaignList )
{
BuildCampaignList ( ) ;
return ;
}
if ( m_bBuildingSavedCampaignList | | m_bBuiltSavedCampaignList )
return ;
ClearSavedCampaignList ( ) ;
m_bBuildingSavedCampaignList = true ;
if ( m_CampaignList . Count ( ) < = 0 )
{
//Msg("Error: Cannot build saved campaign list until the campaign list is built\n");
return ;
}
// Search the directory structure for save games
char mapwild [ MAX_QPATH ] ;
Q_strncpy ( mapwild , " save/*.campaignsave " , sizeof ( mapwild ) ) ;
m_pszSavedFind = Sys_FindFirst ( g_hsavedfind , mapwild , NULL , 0 ) ;
// think will continue the search
}
bool CASW_Mission_Chooser_Source_Local : : MissionExists ( const char * szMapName , bool bRequireOverview )
{
if ( ! szMapName )
return false ;
// check it has an overview txt
char stripped [ MAX_PATH ] ;
V_StripExtension ( szMapName , stripped , MAX_PATH ) ;
char tempfile [ MAX_PATH ] ;
if ( bRequireOverview )
{
Q_snprintf ( tempfile , sizeof ( tempfile ) , " resource/overviews/%s.txt " , stripped ) ;
if ( ! g_pFullFileSystem - > FileExists ( tempfile ) )
return false ;
}
// check the map exists
Q_snprintf ( tempfile , sizeof ( tempfile ) , " maps/%s.bsp " , stripped ) ;
return ( g_pFullFileSystem - > FileExists ( tempfile ) ) ;
}
bool CASW_Mission_Chooser_Source_Local : : CampaignExists ( const char * szCampaignName )
{
if ( ! szCampaignName )
return false ;
// check the campaign txt exists
char stripped [ MAX_PATH ] ;
V_StripExtension ( szCampaignName , stripped , MAX_PATH ) ;
char tempfile [ MAX_PATH ] ;
Q_snprintf ( tempfile , sizeof ( tempfile ) , " resource/campaigns/%s.txt " , stripped ) ;
return ( g_pFullFileSystem - > FileExists ( tempfile ) ) ;
}
bool CASW_Mission_Chooser_Source_Local : : SavedCampaignExists ( const char * szSaveName )
{
// check the save file exists
char stripped [ MAX_PATH ] ;
V_StripExtension ( szSaveName , stripped , MAX_PATH ) ;
char tempfile [ MAX_PATH ] ;
Q_snprintf ( tempfile , sizeof ( tempfile ) , " save/%s.campaignsave " , stripped ) ;
return ( g_pFullFileSystem - > FileExists ( tempfile ) ) ;
}
int CASW_Mission_Chooser_Source_Local : : GetNumMissionsCompleted ( const char * szSaveName )
{
Msg ( " GetNumMissionsCompleted %s \n " , szSaveName ) ;
// check the save file exists
char stripped [ MAX_PATH ] ;
V_StripExtension ( szSaveName , stripped , MAX_PATH ) ;
Msg ( " stripped = %s \n " , stripped ) ;
char tempfile [ MAX_PATH ] ;
Q_snprintf ( tempfile , sizeof ( tempfile ) , " save/%s.campaignsave " , stripped ) ;
Msg ( " tempfile = %s \n " , tempfile ) ;
Q_strlower ( tempfile ) ;
Msg ( " tempfile lowered = %s \n " , tempfile ) ;
if ( ! g_pFullFileSystem - > FileExists ( tempfile ) )
{
Msg ( " this save doesn't exist! returning -1 missions \n " ) ;
return - 1 ;
}
KeyValues * pSaveKeyValues = new KeyValues ( szSaveName ) ;
if ( pSaveKeyValues - > LoadFromFile ( g_pFullFileSystem , tempfile ) )
{
int iMissions = pSaveKeyValues - > GetInt ( " NumMissionsComplete " ) ;
pSaveKeyValues - > deleteThis ( ) ;
Msg ( " loaded keyvalues from file and it thinks num missions is %d \n " , iMissions ) ;
return iMissions ;
}
Msg ( " Couldn't load save keyvalues from file, returning -1 \n " ) ;
if ( pSaveKeyValues - > LoadFromFile ( g_pFullFileSystem , tempfile , " MOD " ) )
Msg ( " but it loaded if we use the MOD path \n " ) ;
else if ( pSaveKeyValues - > LoadFromFile ( g_pFullFileSystem , tempfile , " GAME " ) )
Msg ( " but it loaded if we use the GAME path \n " ) ;
pSaveKeyValues - > deleteThis ( ) ;
return - 1 ;
}
const char * CASW_Mission_Chooser_Source_Local : : GetPrettyMissionName ( const char * szMapName )
{
static char szPrettyName [ 64 ] ;
szPrettyName [ 0 ] = ' \0 ' ;
char stripped [ MAX_PATH ] ;
V_StripExtension ( szMapName , stripped , MAX_PATH ) ;
char tempfile [ MAX_PATH ] ;
Q_snprintf ( tempfile , sizeof ( tempfile ) , " resource/overviews/%s.txt " , stripped ) ;
KeyValues * pOverviewKeyValues = new KeyValues ( szMapName ) ;
if ( pOverviewKeyValues - > LoadFromFile ( g_pFullFileSystem , tempfile ) )
{
Q_snprintf ( szPrettyName , sizeof ( szPrettyName ) , " %s " , pOverviewKeyValues - > GetString ( " missiontitle " ) ) ;
}
pOverviewKeyValues - > deleteThis ( ) ;
return szPrettyName ;
}
const char * CASW_Mission_Chooser_Source_Local : : GetPrettyCampaignName ( const char * szCampaignName )
{
static char szPrettyName [ 64 ] ;
szPrettyName [ 0 ] = ' \0 ' ;
char stripped [ MAX_PATH ] ;
V_StripExtension ( szCampaignName , stripped , MAX_PATH ) ;
char tempfile [ MAX_PATH ] ;
Q_snprintf ( tempfile , sizeof ( tempfile ) , " resource/campaigns/%s.txt " , stripped ) ;
KeyValues * pCampaignKeyValues = new KeyValues ( szCampaignName ) ;
if ( pCampaignKeyValues - > LoadFromFile ( g_pFullFileSystem , tempfile ) )
{
Q_snprintf ( szPrettyName , sizeof ( szPrettyName ) , " %s " , pCampaignKeyValues - > GetString ( " CampaignName " ) ) ;
}
pCampaignKeyValues - > deleteThis ( ) ;
return szPrettyName ;
}
const char * CASW_Mission_Chooser_Source_Local : : GetPrettySavedCampaignName ( const char * szSaveName )
{
static char szPrettyName [ 256 ] ;
szPrettyName [ 0 ] = ' \0 ' ;
char stripped [ MAX_PATH ] ;
V_StripExtension ( szSaveName , stripped , MAX_PATH ) ;
char tempfile [ MAX_PATH ] ;
Q_snprintf ( tempfile , sizeof ( tempfile ) , " save/%s.campaignsave " , stripped ) ;
KeyValues * pSaveKeyValues = new KeyValues ( szSaveName ) ;
if ( pSaveKeyValues - > LoadFromFile ( g_pFullFileSystem , tempfile ) )
{
const char * szCampaignName = pSaveKeyValues - > GetString ( " CampaignName " ) ;
const char * szPrettyCampaignName = szCampaignName ;
if ( szCampaignName & & Q_strlen ( szCampaignName ) > 0 )
{
szPrettyCampaignName = GetPrettyCampaignName ( szCampaignName ) ;
}
const char * szDate = pSaveKeyValues - > GetString ( " DateTime " ) ;
char namebuffer [ 256 ] ;
namebuffer [ 0 ] = ' \0 ' ;
int namepos = 0 ;
KeyValues * pkvSubSection = pSaveKeyValues - > GetFirstSubKey ( ) ;
while ( pkvSubSection & & namepos < 253 )
{
if ( Q_stricmp ( pkvSubSection - > GetName ( ) , " PLAYER " ) = = 0 )
{
const char * pName = pkvSubSection - > GetString ( " PlayerName " ) ;
if ( pName & & pName [ 0 ] ! = ' \0 ' )
{
if ( namepos ! = 0 )
{
namebuffer [ namepos ] = ' ' ; namepos + + ;
}
int namelength = Q_strlen ( pName ) ;
for ( int charcopy = 0 ; charcopy < namelength & & namepos < 253 ; charcopy + + )
{
namebuffer [ namepos ] = pName [ charcopy ] ;
namepos + + ;
}
namebuffer [ namepos ] = ' \0 ' ;
}
}
pkvSubSection = pkvSubSection - > GetNextKey ( ) ;
}
Q_snprintf ( szPrettyName , sizeof ( szPrettyName ) ,
" %s (%s) (%s) " ,
szPrettyCampaignName , szDate , namebuffer ) ;
}
pSaveKeyValues - > deleteThis ( ) ;
return szPrettyName ;
}
// a new save has been created, add it to our summary list
void CASW_Mission_Chooser_Source_Local : : NotifyNewSave ( const char * szSaveName )
{
// if we haven't started scanning for saves yet, don't worry about it
if ( ! m_bBuiltSavedCampaignList & & ! m_bBuildingSavedCampaignList )
return ;
// make sure it has the campaignsave extension
char stripped [ 256 ] ;
V_StripExtension ( szSaveName , stripped , sizeof ( stripped ) ) ;
char szWithExtension [ 256 ] ;
Q_snprintf ( szWithExtension , sizeof ( szWithExtension ) , " %s.campaignsave " , stripped ) ;
// check it's not already in the saved list
for ( int i = 0 ; i < m_SavedCampaignList . Count ( ) ; i + + )
{
if ( ! Q_strcmp ( m_SavedCampaignList [ i ] . m_szSaveName , szWithExtension ) )
return ;
}
Msg ( " New save created, adding it to the list of saved campaigns: %s \n " , szSaveName ) ;
AddToSavedCampaignList ( szWithExtension ) ;
}
// a new save has been created, add it to our summary list
void CASW_Mission_Chooser_Source_Local : : NotifySaveDeleted ( const char * szSaveName )
{
// if we haven't started scanning for saves yet, don't worry about it
if ( ! m_bBuiltSavedCampaignList & & ! m_bBuildingSavedCampaignList )
return ;
// make sure it has the campaignsave extension
char stripped [ 256 ] ;
V_StripExtension ( szSaveName , stripped , sizeof ( stripped ) ) ;
char szWithExtension [ 256 ] ;
Q_snprintf ( szWithExtension , sizeof ( szWithExtension ) , " %s.campaignsave " , stripped ) ;
// find it in the list
for ( int i = 0 ; i < m_SavedCampaignList . Count ( ) ; i + + )
{
if ( ! Q_strcmp ( m_SavedCampaignList [ i ] . m_szSaveName , szWithExtension ) )
{
m_SavedCampaignList . Remove ( i ) ;
return ;
}
}
}
// !!NOTE!! - these numbers are from asw_campaign_save.h. Duplicated constants for the lose.
# define ASW_MAX_PLAYERS_PER_SAVE 10
# define ASW_MAX_MISSIONS_PER_CAMPAIGN 32
# define ASW_CURRENT_SAVE_VERSION 1
# define ASW_NUM_MARINE_PROFILES 9 // from asw_shareddefs.h
bool CASW_Mission_Chooser_Source_Local : : ASW_Campaign_CreateNewSaveGame ( char * szFileName , int iFileNameMaxLen , const char * szCampaignName , bool bMultiplayerGame , const char * szStartingMission ) // szFileName arg is the desired filename or NULL for an autogenerated one. Function sets szFileName with the filename used.
{
if ( ! szFileName )
return false ;
char stripped [ MAX_PATH ] ;
V_StripExtension ( szCampaignName , stripped , MAX_PATH ) ;
char szStartingMissionStripped [ 64 ] ;
if ( szStartingMission )
{
V_StripExtension ( szStartingMission , szStartingMissionStripped , sizeof ( szStartingMissionStripped ) ) ;
}
else
{
szStartingMissionStripped [ 0 ] = 0 ;
}
// check the campaign file exists
char campbuffer [ MAX_PATH ] ;
Q_snprintf ( campbuffer , sizeof ( campbuffer ) , " resource/campaigns/%s.txt " , stripped ) ;
if ( ! g_pFullFileSystem - > FileExists ( campbuffer ) )
{
Msg ( " No such campaign: %s \n " , campbuffer ) ;
return false ;
}
// Get the current time and date as a string
char szDateTime [ 256 ] ;
int year , month , dayOfWeek , day , hour , minute , second ;
ASW_System_GetCurrentTimeAndDate ( & year , & month , & dayOfWeek , & day , & hour , & minute , & second ) ;
Q_snprintf ( szDateTime , sizeof ( szDateTime ) , " %02d/%02d/%02d %02d:%02d " , month , day , year , hour , minute ) ;
if ( szFileName [ 0 ] = = ' \0 ' )
{
// autogenerate a filename based on the current time and date
Q_snprintf ( szFileName , iFileNameMaxLen , " %s_save_%02d_%02d_%02d_%02d_%02d_%02d " , stripped , year , month , day , hour , minute , second ) ;
}
// make sure the path and extension are correct
Q_SetExtension ( szFileName , " .campaignsave " , iFileNameMaxLen ) ;
char tempbuffer [ 256 ] ;
Q_snprintf ( tempbuffer , sizeof ( tempbuffer ) , " %s " , szFileName ) ;
const char * pszNoPathName = Q_UnqualifiedFileName ( tempbuffer ) ;
Msg ( " Unqualified = %s \n " , pszNoPathName ) ;
char szFullFileName [ 256 ] ;
Q_snprintf ( szFullFileName , sizeof ( szFullFileName ) , " save/%s " , pszNoPathName ) ;
Msg ( " Creating new save with filename: %s \n " , szFullFileName ) ;
KeyValues * pSaveKeyValues = new KeyValues ( pszNoPathName ) ;
int nMissionsComplete = 0 ;
if ( szStartingMission & & szStartingMission [ 0 ] )
{
KeyValues * pCampaignDetails = GetCampaignDetails ( stripped ) ;
if ( pCampaignDetails )
{
int nMissionSections = 0 ;
for ( KeyValues * pMission = pCampaignDetails - > GetFirstSubKey ( ) ; pMission ; pMission = pMission - > GetNextKey ( ) )
{
if ( ! Q_stricmp ( pMission - > GetName ( ) , " MISSION " ) )
{
if ( ! Q_stricmp ( pMission - > GetString ( " MapName " , " " ) , szStartingMissionStripped ) )
{
nMissionsComplete = nMissionSections - 1 ; // skip first dummy mission
break ;
}
nMissionSections + + ;
}
}
}
}
pSaveKeyValues - > SetInt ( " Version " , ASW_CURRENT_SAVE_VERSION ) ;
pSaveKeyValues - > SetString ( " CampaignName " , stripped ) ;
pSaveKeyValues - > SetInt ( " CurrentPosition " , nMissionsComplete + 1 ) ; // position squad on the first uncompleted mission
pSaveKeyValues - > SetInt ( " NumMissionsComplete " , nMissionsComplete ) ;
pSaveKeyValues - > SetInt ( " InitialNumMissionsComplete " , nMissionsComplete ) ;
pSaveKeyValues - > SetInt ( " Multiplayer " , bMultiplayerGame ? 1 : 0 ) ;
pSaveKeyValues - > SetString ( " DateTime " , szDateTime ) ;
pSaveKeyValues - > SetInt ( " NumPlayers " , 0 ) ;
// 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 ) ;
bool bComplete = ( i ! = 0 ) & & ( i < = nMissionsComplete ) ;
pSubSection - > SetInt ( " MissionComplete " , bComplete ? 1 : 0 ) ;
pSaveKeyValues - > AddSubKey ( pSubSection ) ;
}
const int nInitialSkillPoints = 0 ;
// write out each marine's stats
for ( int i = 0 ; i < ASW_NUM_MARINE_PROFILES ; i + + )
{
pSubSection = new KeyValues ( " MARINE " ) ;
pSubSection - > SetInt ( " MarineID " , i ) ;
pSubSection - > SetInt ( " SkillSlot0 " , 0 ) ;
pSubSection - > SetInt ( " SkillSlot1 " , 0 ) ;
pSubSection - > SetInt ( " SkillSlot2 " , 0 ) ;
pSubSection - > SetInt ( " SkillSlot3 " , 0 ) ;
pSubSection - > SetInt ( " SkillSlot4 " , 0 ) ;
pSubSection - > SetInt ( " SkillSlotSpare " , nInitialSkillPoints + nMissionsComplete * ASW_SKILL_POINTS_PER_MISSION ) ;
pSubSection - > SetInt ( " UndoSkillSlot0 " , 0 ) ;
pSubSection - > SetInt ( " UndoSkillSlot1 " , 0 ) ;
pSubSection - > SetInt ( " UndoSkillSlot2 " , 0 ) ;
pSubSection - > SetInt ( " UndoSkillSlot3 " , 0 ) ;
pSubSection - > SetInt ( " UndoSkillSlot4 " , 0 ) ;
pSubSection - > SetInt ( " UndoSkillSlotSpare " , nInitialSkillPoints + nMissionsComplete * ASW_SKILL_POINTS_PER_MISSION ) ;
pSubSection - > SetString ( " MissionsCompleted " , " " ) ;
pSubSection - > SetString ( " Medals " , " " ) ;
pSubSection - > SetInt ( " Wounded " , 0 ) ;
pSubSection - > SetInt ( " Dead " , 0 ) ;
pSubSection - > SetInt ( " ParasitesKilled " , 0 ) ;
pSaveKeyValues - > AddSubKey ( pSubSection ) ;
}
// players section is empty at first
// Create the save sub-directory
if ( ! g_pFullFileSystem - > IsDirectory ( " save " , " MOD " ) )
{
g_pFullFileSystem - > CreateDirHierarchy ( " save " , " MOD " ) ;
}
// save it
if ( pSaveKeyValues - > SaveToFile ( g_pFullFileSystem , szFullFileName ) )
{
// make sure our save summary list adds this to it, if needed
Msg ( " New save created: %s \n " , szFullFileName ) ;
NotifyNewSave ( pszNoPathName ) ;
return true ;
}
Msg ( " Save to file failed. Filename=%s \n " , szFullFileName ) ;
return false ;
}
// normal alphabetical sorting for map/campaigns
bool CASW_Mission_Chooser_Source_Local : : MapNameLess : : Less ( MapListName const & src1 , MapListName const & src2 , void * pCtx )
{
return ! ! Q_strcmp ( src1 . szMapName , src2 . szMapName ) ;
}
// sort by the datetime string
bool CASW_Mission_Chooser_Source_Local : : SavedCampaignLess : : Less ( ASW_Mission_Chooser_Saved_Campaign const & src1 , ASW_Mission_Chooser_Saved_Campaign const & src2 , void * pCtx )
{
int month , day , year , hour , minute ;
int month2 , day2 , year2 , hour2 , minute2 ;
if ( sscanf ( src1 . m_szDateTime , " %d/%d/%d %d:%d " , & month , & day , & year , & hour , & minute ) ! = 5 )
return false ;
if ( sscanf ( src2 . m_szDateTime , " %d/%d/%d %d:%d " , & month2 , & day2 , & year2 , & hour2 , & minute2 ) ! = 5 )
return false ;
//Msg("src1 month:%d day:%d year:%d hour:%d minute:%d\n", month, day, year, hour, minute);
//Msg("src2 month:%d day:%d year:%d hour:%d minute:%d\n", month2, day2, year2, hour2, minute2);
if ( year > year2 )
{
//Msg("src1 is newer because of year\n");
return true ;
}
else if ( year < year2 )
{
//Msg("src2 is newer because of year\n");
return false ;
}
if ( month > month2 )
{
//Msg("src1 is newer because of month\n");
return true ;
}
else if ( month < month2 )
{
//Msg("src2 is newer because of month\n");
return false ;
}
if ( day > day2 )
{
//Msg("src1 is newer because of day\n");
return true ;
}
else if ( day < day2 )
{
//Msg("src2 is newer because of day\n");
return false ;
}
if ( hour > hour2 )
{
//Msg("src1 is newer because of hour\n");
return true ;
}
else if ( hour < hour2 )
{
//Msg("src2 is newer because of hour\n");
return false ;
}
if ( minute > minute2 )
{
//Msg("src1 is newer because of minute\n");
return true ;
}
else if ( minute < minute2 )
{
//Msg("src2 is newer because of minute\n");
return false ;
}
//if ((year > year2) || (month > month2) || (day > day2) || (hour > hour2) || (minute > minute2))
//return true;
//Msg("neither is newer\n");
return false ;
}
# define ASW_DEFAULT_INTRO_MAP "intro_jacob"
const char * CASW_Mission_Chooser_Source_Local : : GetCampaignSaveIntroMap ( const char * szSaveName )
{
// check the save file exists
char stripped [ MAX_PATH ] ;
V_StripExtension ( szSaveName , stripped , MAX_PATH ) ;
char tempfile [ MAX_PATH ] ;
Q_snprintf ( tempfile , sizeof ( tempfile ) , " save/%s.campaignsave " , stripped ) ;
if ( ! g_pFullFileSystem - > FileExists ( tempfile ) )
return ASW_DEFAULT_INTRO_MAP ;
KeyValues * pSaveKeyValues = new KeyValues ( szSaveName ) ;
const char * pszCampaign = NULL ;
if ( pSaveKeyValues - > LoadFromFile ( g_pFullFileSystem , tempfile ) )
{
pszCampaign = pSaveKeyValues - > GetString ( " CampaignName " ) ;
}
if ( ! pszCampaign )
{
pSaveKeyValues - > deleteThis ( ) ;
return ASW_DEFAULT_INTRO_MAP ;
}
char ctempfile [ MAX_PATH ] ;
Q_snprintf ( ctempfile , sizeof ( ctempfile ) , " resource/campaigns/%s.txt " , pszCampaign ) ;
if ( ! g_pFullFileSystem - > FileExists ( ctempfile ) ) /// check it exists
{
pSaveKeyValues - > deleteThis ( ) ;
return ASW_DEFAULT_INTRO_MAP ;
}
// now read in the campaign txt and find the intro map name
KeyValues * pCampaignKeyValues = new KeyValues ( pszCampaign ) ;
if ( pCampaignKeyValues - > LoadFromFile ( g_pFullFileSystem , ctempfile ) )
{
static char s_introname [ 128 ] ;
Q_strncpy ( s_introname , pCampaignKeyValues - > GetString ( " IntroMap " ) , 128 ) ;
// check we actually got a valid intro map name string
if ( Q_strlen ( s_introname ) > 5 & & ! Q_strnicmp ( s_introname , " intro " , 5 ) )
{
pSaveKeyValues - > deleteThis ( ) ;
pCampaignKeyValues - > deleteThis ( ) ;
return s_introname ;
}
}
pSaveKeyValues - > deleteThis ( ) ;
pCampaignKeyValues - > deleteThis ( ) ;
return ASW_DEFAULT_INTRO_MAP ;
}
KeyValues * CASW_Mission_Chooser_Source_Local : : GetMissionDetails ( const char * szMissionName )
{
// see if we have this cached already
for ( int i = 0 ; i < m_MissionDetails . Count ( ) ; i + + )
{
if ( ! Q_stricmp ( m_MissionDetails [ i ] - > szMissionName , szMissionName ) )
{
return m_MissionDetails [ i ] - > m_pMissionKeys ;
}
}
// strip off the extension
char stripped [ MAX_PATH ] ;
V_StripExtension ( szMissionName , stripped , MAX_PATH ) ;
KeyValues * pMissionKeys = new KeyValues ( stripped ) ;
char tempfile [ MAX_PATH ] ;
Q_snprintf ( tempfile , sizeof ( tempfile ) , " resource/overviews/%s.txt " , stripped ) ;
bool bNoOverview = false ;
if ( ! pMissionKeys - > LoadFromFile ( g_pFullFileSystem , tempfile , " GAME " ) )
{
// try to load it directly from the maps folder
Q_snprintf ( tempfile , sizeof ( tempfile ) , " maps/%s.txt " , stripped ) ;
if ( ! pMissionKeys - > LoadFromFile ( g_pFullFileSystem , tempfile , " GAME " ) )
{
bNoOverview = true ;
}
}
MissionDetails_t * pDetails = new MissionDetails_t ;
pDetails - > m_pMissionKeys = pMissionKeys ;
Q_snprintf ( pDetails - > szMissionName , sizeof ( pDetails - > szMissionName ) , " %s " , szMissionName ) ;
m_MissionDetails . AddToTail ( pDetails ) ;
return pMissionKeys ;
}
KeyValues * CASW_Mission_Chooser_Source_Local : : GetCampaignDetails ( const char * szCampaignName )
{
// see if we have this cached already
for ( int i = 0 ; i < m_CampaignDetails . Count ( ) ; i + + )
{
if ( ! Q_stricmp ( m_CampaignDetails [ i ] - > szCampaignName , szCampaignName ) )
{
return m_CampaignDetails [ i ] - > m_pCampaignKeys ;
}
}
// strip off the extension
char stripped [ MAX_PATH ] ;
V_StripExtension ( szCampaignName , stripped , MAX_PATH ) ;
KeyValues * pCampaignKeys = new KeyValues ( stripped ) ;
char tempfile [ MAX_PATH ] ;
Q_snprintf ( tempfile , sizeof ( tempfile ) , " resource/campaigns/%s.txt " , stripped ) ;
bool bNoOverview = false ;
if ( ! pCampaignKeys - > LoadFromFile ( g_pFullFileSystem , tempfile , " GAME " ) )
{
// try to load it directly from the maps folder
Q_snprintf ( tempfile , sizeof ( tempfile ) , " maps/%s.txt " , stripped ) ;
if ( ! pCampaignKeys - > LoadFromFile ( g_pFullFileSystem , tempfile , " GAME " ) )
{
bNoOverview = true ;
}
}
CampaignDetails_t * pDetails = new CampaignDetails_t ;
pDetails - > m_pCampaignKeys = pCampaignKeys ;
Q_snprintf ( pDetails - > szCampaignName , sizeof ( pDetails - > szCampaignName ) , " %s " , szCampaignName ) ;
m_CampaignDetails . AddToTail ( pDetails ) ;
return pCampaignKeys ;
}