2003-09-08 03:26:58 +00:00
|
|
|
#include "global.h"
|
|
|
|
|
#include "ProfileManager.h"
|
2005-07-01 04:46:32 +00:00
|
|
|
#include "Profile.h"
|
2003-09-08 03:26:58 +00:00
|
|
|
#include "RageUtil.h"
|
|
|
|
|
#include "PrefsManager.h"
|
|
|
|
|
#include "RageLog.h"
|
2003-12-05 00:07:18 +00:00
|
|
|
#include "RageFile.h"
|
|
|
|
|
#include "RageFileManager.h"
|
2003-09-08 03:26:58 +00:00
|
|
|
#include "IniFile.h"
|
2003-09-08 07:21:41 +00:00
|
|
|
#include "GameConstantsAndTypes.h"
|
|
|
|
|
#include "SongManager.h"
|
2003-11-10 04:32:12 +00:00
|
|
|
#include "GameState.h"
|
2003-12-07 07:09:13 +00:00
|
|
|
#include "song.h"
|
2003-12-18 03:40:57 +00:00
|
|
|
#include "Steps.h"
|
2003-12-07 07:09:13 +00:00
|
|
|
#include "Course.h"
|
|
|
|
|
#include "GameManager.h"
|
|
|
|
|
#include "ProductInfo.h"
|
2003-12-07 08:19:10 +00:00
|
|
|
#include "RageUtil.h"
|
2003-12-08 10:27:45 +00:00
|
|
|
#include "ThemeManager.h"
|
2003-12-19 08:17:44 +00:00
|
|
|
#include "MemoryCardManager.h"
|
2004-02-09 08:10:01 +00:00
|
|
|
#include "XmlFile.h"
|
2004-04-18 07:34:37 +00:00
|
|
|
#include "StepsUtil.h"
|
2004-09-12 05:56:24 +00:00
|
|
|
#include "Style.h"
|
2005-07-01 05:06:00 +00:00
|
|
|
#include "HighScore.h"
|
2005-08-13 01:47:56 +00:00
|
|
|
#include "Character.h"
|
2005-08-14 12:06:40 +00:00
|
|
|
#include "CharacterManager.h"
|
2003-09-08 03:26:58 +00:00
|
|
|
|
2003-11-14 17:17:36 +00:00
|
|
|
|
2003-09-08 03:26:58 +00:00
|
|
|
ProfileManager* PROFILEMAN = NULL; // global and accessable from anywhere in our program
|
|
|
|
|
|
2004-01-07 02:56:47 +00:00
|
|
|
#define NEW_MEM_CARD_NAME ""
|
2005-08-14 11:09:23 +00:00
|
|
|
#define USER_PROFILES_DIR "/Data/LocalProfiles/"
|
|
|
|
|
#define MACHINE_PROFILE_DIR "/Data/MachineProfile/"
|
|
|
|
|
const CString LAST_GOOD_SUBDIR = "LastGood/";
|
2003-12-07 07:09:13 +00:00
|
|
|
|
2005-07-05 23:13:49 +00:00
|
|
|
|
2005-04-24 19:18:46 +00:00
|
|
|
// Directories to search for a profile if m_sMemoryCardProfileSubdir doesn't
|
|
|
|
|
// exist, separated by ";":
|
2005-05-19 01:25:38 +00:00
|
|
|
static Preference<CString> g_sMemoryCardProfileImportSubdirs( "MemoryCardProfileImportSubdirs", "" );
|
2005-04-24 19:18:46 +00:00
|
|
|
|
2005-08-14 23:01:34 +00:00
|
|
|
static CString LocalProfileIDToDir( const CString &sProfileID ) { return USER_PROFILES_DIR + sProfileID + "/"; }
|
|
|
|
|
static CString LocalProfileDirToID( const CString &sDir ) { return Basename( sDir ); }
|
2005-07-12 20:19:52 +00:00
|
|
|
|
2005-08-14 01:59:46 +00:00
|
|
|
struct DirAndProfile
|
|
|
|
|
{
|
|
|
|
|
CString sDir;
|
|
|
|
|
Profile profile;
|
|
|
|
|
};
|
|
|
|
|
static vector<DirAndProfile> g_vLocalProfile;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static ThemeMetric<bool> FIXED_PROFILES( "ProfileManager", "FixedProfiles" );
|
|
|
|
|
static ThemeMetric<int> NUM_FIXED_PROFILES( "ProfileManager", "NumFixedProfiles" );
|
|
|
|
|
#define FIXED_PROFILE_CHARACTER_ID( i ) THEME->GetMetric( "ProfileManager", ssprintf("FixedProfileCharacterID%d",int(i+1)) )
|
2005-07-12 20:19:52 +00:00
|
|
|
|
2005-04-24 19:18:46 +00:00
|
|
|
|
2003-09-08 03:26:58 +00:00
|
|
|
ProfileManager::ProfileManager()
|
|
|
|
|
{
|
2005-07-01 04:46:32 +00:00
|
|
|
m_pMachineProfile = new Profile;
|
|
|
|
|
FOREACH_PlayerNumber(pn)
|
2005-07-13 19:15:31 +00:00
|
|
|
m_pMemoryCardProfile[pn] = new Profile;
|
2003-09-08 03:26:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ProfileManager::~ProfileManager()
|
|
|
|
|
{
|
2005-07-12 20:19:52 +00:00
|
|
|
SAFE_DELETE( m_pMachineProfile );
|
2005-07-01 04:46:32 +00:00
|
|
|
FOREACH_PlayerNumber(pn)
|
2005-07-13 19:15:31 +00:00
|
|
|
SAFE_DELETE( m_pMemoryCardProfile[pn] );
|
2003-09-08 03:26:58 +00:00
|
|
|
}
|
|
|
|
|
|
2004-05-25 05:52:57 +00:00
|
|
|
void ProfileManager::Init()
|
|
|
|
|
{
|
|
|
|
|
FOREACH_PlayerNumber( p )
|
2004-10-06 08:39:38 +00:00
|
|
|
{
|
2004-05-25 05:52:57 +00:00
|
|
|
m_bWasLoadedFromMemoryCard[p] = false;
|
2004-10-06 08:39:38 +00:00
|
|
|
m_bLastLoadWasTamperedOrCorrupt[p] = false;
|
2004-10-07 19:57:51 +00:00
|
|
|
m_bLastLoadWasFromLastGood[p] = false;
|
2005-09-29 00:33:22 +00:00
|
|
|
m_bNeedToBackUpLastLoad[p] = false;
|
2004-10-06 08:39:38 +00:00
|
|
|
}
|
2004-05-25 05:52:57 +00:00
|
|
|
|
|
|
|
|
LoadMachineProfile();
|
2005-07-05 23:13:49 +00:00
|
|
|
|
2005-07-13 19:15:31 +00:00
|
|
|
RefreshLocalProfilesFromDisk();
|
2005-08-14 01:59:46 +00:00
|
|
|
|
|
|
|
|
if( FIXED_PROFILES )
|
|
|
|
|
{
|
|
|
|
|
// resize to the fixed number
|
|
|
|
|
if( (int)g_vLocalProfile.size() > NUM_FIXED_PROFILES )
|
|
|
|
|
g_vLocalProfile.erase( g_vLocalProfile.begin()+NUM_FIXED_PROFILES, g_vLocalProfile.end() );
|
|
|
|
|
|
|
|
|
|
for( int i=g_vLocalProfile.size(); i<NUM_FIXED_PROFILES; i++ )
|
|
|
|
|
{
|
|
|
|
|
CString sCharacterID = FIXED_PROFILE_CHARACTER_ID( i );
|
2005-08-14 12:06:40 +00:00
|
|
|
Character *pCharacter = CHARMAN->GetCharacterFromID( sCharacterID );
|
2005-08-30 14:10:24 +00:00
|
|
|
ASSERT_M( pCharacter, sCharacterID );
|
2005-08-14 20:31:20 +00:00
|
|
|
CString sProfileID;
|
|
|
|
|
CreateLocalProfile( pCharacter->GetDisplayName(), sProfileID );
|
|
|
|
|
Profile* pProfile = GetLocalProfile( sProfileID );
|
|
|
|
|
pProfile->m_sCharacterID = sCharacterID;
|
|
|
|
|
SaveLocalProfile( sProfileID );
|
2005-08-14 01:59:46 +00:00
|
|
|
}
|
|
|
|
|
|
2005-08-14 11:09:23 +00:00
|
|
|
ASSERT( (int)g_vLocalProfile.size() == NUM_FIXED_PROFILES );
|
2005-08-14 01:59:46 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ProfileManager::FixedProfiles() const
|
|
|
|
|
{
|
|
|
|
|
return FIXED_PROFILES;
|
2005-07-05 23:13:49 +00:00
|
|
|
}
|
2003-09-08 07:21:41 +00:00
|
|
|
|
2005-08-13 06:59:27 +00:00
|
|
|
ProfileLoadResult ProfileManager::LoadProfile( PlayerNumber pn, CString sProfileDir, bool bIsMemCard )
|
2003-09-08 03:26:58 +00:00
|
|
|
{
|
2005-07-01 04:46:32 +00:00
|
|
|
LOG->Trace( "LoadingProfile P%d, %s, %d", pn+1, sProfileDir.c_str(), bIsMemCard );
|
2004-06-05 19:40:53 +00:00
|
|
|
|
2003-11-01 22:04:43 +00:00
|
|
|
ASSERT( !sProfileDir.empty() );
|
2003-12-10 09:26:05 +00:00
|
|
|
ASSERT( sProfileDir.Right(1) == "/" );
|
2003-09-08 03:26:58 +00:00
|
|
|
|
2004-06-06 02:41:16 +00:00
|
|
|
|
2003-11-01 22:04:43 +00:00
|
|
|
m_sProfileDir[pn] = sProfileDir;
|
2004-01-03 03:42:40 +00:00
|
|
|
m_bWasLoadedFromMemoryCard[pn] = bIsMemCard;
|
2004-10-07 19:57:51 +00:00
|
|
|
m_bLastLoadWasFromLastGood[pn] = false;
|
2005-09-29 00:33:22 +00:00
|
|
|
m_bNeedToBackUpLastLoad[pn] = false;
|
2003-11-01 19:36:52 +00:00
|
|
|
|
2004-10-07 19:57:51 +00:00
|
|
|
// Try to load the original, non-backup data.
|
2005-08-13 06:59:27 +00:00
|
|
|
ProfileLoadResult lr = GetProfile(pn)->LoadAllFromDir( m_sProfileDir[pn], PREFSMAN->m_bSignProfileData );
|
2004-10-07 19:57:51 +00:00
|
|
|
|
2005-08-14 11:09:23 +00:00
|
|
|
CString sBackupDir = m_sProfileDir[pn] + LAST_GOOD_SUBDIR;
|
2004-10-06 08:39:38 +00:00
|
|
|
|
2005-08-13 06:59:27 +00:00
|
|
|
if( lr == ProfileLoadResult_Success )
|
2004-10-06 08:39:38 +00:00
|
|
|
{
|
2005-10-09 04:30:59 +00:00
|
|
|
/* Next time the profile is written, move this good profile into LastGood. */
|
2005-09-29 00:33:22 +00:00
|
|
|
m_bNeedToBackUpLastLoad[pn] = true;
|
2004-10-06 08:39:38 +00:00
|
|
|
}
|
2003-09-08 03:26:58 +00:00
|
|
|
|
2005-08-13 06:59:27 +00:00
|
|
|
m_bLastLoadWasTamperedOrCorrupt[pn] = lr == ProfileLoadResult_FailedTampered;
|
2004-06-05 19:40:53 +00:00
|
|
|
|
2005-07-01 04:46:32 +00:00
|
|
|
//
|
2004-10-07 19:57:51 +00:00
|
|
|
// Try to load from the backup if the original data fails to load
|
|
|
|
|
//
|
2005-08-13 06:59:27 +00:00
|
|
|
if( lr == ProfileLoadResult_FailedTampered )
|
2004-10-07 19:57:51 +00:00
|
|
|
{
|
2005-07-13 19:15:31 +00:00
|
|
|
lr = GetProfile(pn)->LoadAllFromDir( sBackupDir, PREFSMAN->m_bSignProfileData );
|
2005-08-13 06:59:27 +00:00
|
|
|
m_bLastLoadWasFromLastGood[pn] = lr == ProfileLoadResult_Success;
|
2005-05-03 04:03:11 +00:00
|
|
|
|
|
|
|
|
/* If the LastGood profile doesn't exist at all, and the actual profile was failed_tampered,
|
|
|
|
|
* then the error should be failed_tampered and not failed_no_profile. */
|
2005-08-13 06:59:27 +00:00
|
|
|
if( lr == ProfileLoadResult_FailedNoProfile )
|
2005-05-03 04:03:11 +00:00
|
|
|
{
|
2005-08-13 06:59:27 +00:00
|
|
|
LOG->Trace( "Profile was corrupt and LastGood for %s doesn't exist; error is ProfileLoadResult_FailedTampered",
|
2005-05-03 04:03:11 +00:00
|
|
|
sProfileDir.c_str() );
|
2005-08-13 06:59:27 +00:00
|
|
|
lr = ProfileLoadResult_FailedTampered;
|
2005-05-03 04:03:11 +00:00
|
|
|
}
|
2004-10-07 19:57:51 +00:00
|
|
|
}
|
2003-11-01 22:04:43 +00:00
|
|
|
|
2004-10-07 19:57:51 +00:00
|
|
|
LOG->Trace( "Done loading profile - result %d", lr );
|
2003-11-01 22:04:43 +00:00
|
|
|
|
2005-04-24 19:18:46 +00:00
|
|
|
return lr;
|
2003-11-01 22:04:43 +00:00
|
|
|
}
|
|
|
|
|
|
2004-08-09 05:01:24 +00:00
|
|
|
bool ProfileManager::LoadLocalProfileFromMachine( PlayerNumber pn )
|
2003-11-01 22:04:43 +00:00
|
|
|
{
|
2005-05-16 09:36:32 +00:00
|
|
|
CString sProfileID = PREFSMAN->GetDefaultLocalProfileID(pn);
|
2003-11-01 22:04:43 +00:00
|
|
|
if( sProfileID.empty() )
|
|
|
|
|
{
|
|
|
|
|
m_sProfileDir[pn] = "";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2005-08-14 23:01:34 +00:00
|
|
|
m_sProfileDir[pn] = LocalProfileIDToDir( sProfileID );
|
2005-07-18 17:34:47 +00:00
|
|
|
m_bWasLoadedFromMemoryCard[pn] = false;
|
|
|
|
|
m_bLastLoadWasFromLastGood[pn] = false;
|
|
|
|
|
|
2005-08-14 01:59:46 +00:00
|
|
|
if( GetLocalProfile(sProfileID) == NULL )
|
2005-07-18 17:34:47 +00:00
|
|
|
{
|
|
|
|
|
m_sProfileDir[pn] = "";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2003-11-01 22:04:43 +00:00
|
|
|
|
2005-07-18 17:34:47 +00:00
|
|
|
return true;
|
2003-11-01 22:04:43 +00:00
|
|
|
}
|
|
|
|
|
|
2005-04-24 23:23:32 +00:00
|
|
|
void ProfileManager::GetMemoryCardProfileDirectoriesToTry( vector<CString> &asDirsToTry ) const
|
2005-04-24 19:39:54 +00:00
|
|
|
{
|
|
|
|
|
/* Try to load the preferred profile. */
|
|
|
|
|
asDirsToTry.push_back( PREFSMAN->m_sMemoryCardProfileSubdir );
|
|
|
|
|
|
|
|
|
|
/* If that failed, try loading from all fallback directories. */
|
|
|
|
|
split( g_sMemoryCardProfileImportSubdirs, ";", asDirsToTry, true );
|
|
|
|
|
}
|
|
|
|
|
|
2004-08-09 05:01:24 +00:00
|
|
|
bool ProfileManager::LoadProfileFromMemoryCard( PlayerNumber pn )
|
2003-11-01 22:04:43 +00:00
|
|
|
{
|
2004-01-03 03:42:40 +00:00
|
|
|
UnloadProfile( pn );
|
2004-08-09 05:01:24 +00:00
|
|
|
|
2004-03-14 01:40:24 +00:00
|
|
|
// mount slot
|
2005-04-22 04:28:46 +00:00
|
|
|
if( MEMCARDMAN->GetCardState(pn) != MEMORY_CARD_STATE_READY )
|
|
|
|
|
return false;
|
2004-10-07 19:57:51 +00:00
|
|
|
|
2005-04-24 19:18:46 +00:00
|
|
|
vector<CString> asDirsToTry;
|
2005-04-24 19:39:54 +00:00
|
|
|
GetMemoryCardProfileDirectoriesToTry( asDirsToTry );
|
2005-04-24 19:18:46 +00:00
|
|
|
|
|
|
|
|
for( unsigned i = 0; i < asDirsToTry.size(); ++i )
|
|
|
|
|
{
|
|
|
|
|
const CString &sSubdir = asDirsToTry[i];
|
|
|
|
|
CString sDir = MEM_CARD_MOUNT_POINT[pn] + sSubdir + "/";
|
|
|
|
|
|
2005-08-13 06:59:27 +00:00
|
|
|
/* If the load fails with ProfileLoadResult_FailedNoProfile, keep searching. However,
|
2005-04-24 19:18:46 +00:00
|
|
|
* if it fails with failed_tampered, data existed but couldn't be loaded;
|
|
|
|
|
* we don't want to mess with it, since it's confusing and may wipe out
|
|
|
|
|
* recoverable backup data. The only time we really want to import data
|
|
|
|
|
* is on the very first use, when the new profile doesn't exist at all,
|
|
|
|
|
* but we also want to import scores in the case where the player created
|
|
|
|
|
* a directory for edits before playing, so keep searching if the directory
|
|
|
|
|
* exists with exists with no scores. */
|
2005-08-13 06:59:27 +00:00
|
|
|
ProfileLoadResult res = LoadProfile( pn, sDir, true );
|
|
|
|
|
if( res == ProfileLoadResult_Success )
|
2005-05-03 04:03:11 +00:00
|
|
|
{
|
2005-08-11 23:57:20 +00:00
|
|
|
/* If importing, store the directory we imported from, for display purposes. */
|
|
|
|
|
if( i > 0 )
|
|
|
|
|
m_sProfileDirImportedFrom[pn] = asDirsToTry[i];
|
2005-05-03 04:03:11 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2005-08-13 06:59:27 +00:00
|
|
|
if( res == ProfileLoadResult_FailedTampered )
|
2005-04-24 19:18:46 +00:00
|
|
|
break;
|
|
|
|
|
}
|
2004-01-03 03:42:40 +00:00
|
|
|
|
2005-04-24 19:18:46 +00:00
|
|
|
/* If we imported a profile fallback directory, change the memory card
|
|
|
|
|
* directory back to the preferred directory: never write over imported
|
|
|
|
|
* scores. */
|
2005-04-28 08:27:40 +00:00
|
|
|
m_sProfileDir[pn] = MEM_CARD_MOUNT_POINT[pn] + (CString)PREFSMAN->m_sMemoryCardProfileSubdir + "/";
|
2004-10-07 19:57:51 +00:00
|
|
|
|
2005-04-25 00:32:08 +00:00
|
|
|
/* Load edits from all fallback directories, newest first. */
|
|
|
|
|
for( unsigned i = 0; i < asDirsToTry.size(); ++i )
|
|
|
|
|
{
|
|
|
|
|
const CString &sSubdir = asDirsToTry[i];
|
|
|
|
|
CString sDir = MEM_CARD_MOUNT_POINT[pn] + sSubdir + "/";
|
|
|
|
|
|
2005-04-25 00:36:26 +00:00
|
|
|
SONGMAN->LoadAllFromProfileDir( sDir, (ProfileSlot) pn );
|
2005-04-25 00:32:08 +00:00
|
|
|
}
|
|
|
|
|
|
2005-04-22 04:28:46 +00:00
|
|
|
return true; // If a card is inserted, we want to use the memory card to save - even if the Profile load failed.
|
2003-11-01 22:04:43 +00:00
|
|
|
}
|
2003-11-09 21:39:54 +00:00
|
|
|
|
2004-08-09 05:01:24 +00:00
|
|
|
bool ProfileManager::LoadFirstAvailableProfile( PlayerNumber pn )
|
2004-02-22 03:44:04 +00:00
|
|
|
{
|
2004-08-09 05:01:24 +00:00
|
|
|
if( LoadProfileFromMemoryCard(pn) )
|
2004-02-22 03:44:04 +00:00
|
|
|
return true;
|
|
|
|
|
|
2004-08-09 05:01:24 +00:00
|
|
|
if( LoadLocalProfileFromMachine(pn) )
|
2004-02-22 03:44:04 +00:00
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2003-11-01 22:04:43 +00:00
|
|
|
|
2005-04-24 23:06:15 +00:00
|
|
|
|
|
|
|
|
bool ProfileManager::FastLoadProfileNameFromMemoryCard( CString sRootDir, CString &sName ) const
|
|
|
|
|
{
|
2005-04-24 23:23:32 +00:00
|
|
|
vector<CString> asDirsToTry;
|
|
|
|
|
GetMemoryCardProfileDirectoriesToTry( asDirsToTry );
|
|
|
|
|
|
|
|
|
|
for( unsigned i = 0; i < asDirsToTry.size(); ++i )
|
|
|
|
|
{
|
|
|
|
|
const CString &sSubdir = asDirsToTry[i];
|
|
|
|
|
CString sDir = sRootDir + sSubdir + "/";
|
2005-04-24 23:06:15 +00:00
|
|
|
|
2005-04-24 23:23:32 +00:00
|
|
|
Profile profile;
|
2005-08-13 06:59:27 +00:00
|
|
|
ProfileLoadResult res = profile.LoadEditableDataFromDir( sDir );
|
|
|
|
|
if( res == ProfileLoadResult_Success )
|
2005-04-24 23:23:32 +00:00
|
|
|
{
|
2005-07-13 18:49:49 +00:00
|
|
|
sName = profile.GetDisplayNameOrHighScoreName();
|
2005-04-24 23:23:32 +00:00
|
|
|
return true;
|
|
|
|
|
}
|
2005-08-13 06:59:27 +00:00
|
|
|
else if( res != ProfileLoadResult_FailedNoProfile )
|
2005-04-24 23:23:32 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
2005-04-24 23:06:15 +00:00
|
|
|
}
|
|
|
|
|
|
2004-07-20 01:31:23 +00:00
|
|
|
void ProfileManager::SaveAllProfiles() const
|
|
|
|
|
{
|
|
|
|
|
this->SaveMachineProfile();
|
|
|
|
|
|
|
|
|
|
FOREACH_HumanPlayer( pn )
|
|
|
|
|
{
|
2005-05-09 08:44:01 +00:00
|
|
|
if( !IsPersistentProfile(pn) )
|
2004-07-20 01:31:23 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
this->SaveProfile( pn );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-22 02:01:40 +00:00
|
|
|
bool ProfileManager::SaveProfile( PlayerNumber pn ) const
|
2003-09-08 03:26:58 +00:00
|
|
|
{
|
|
|
|
|
if( m_sProfileDir[pn].empty() )
|
2003-11-01 19:36:52 +00:00
|
|
|
return false;
|
2003-09-08 03:26:58 +00:00
|
|
|
|
2005-09-29 00:33:22 +00:00
|
|
|
/*
|
|
|
|
|
* If the profile we're writing was loaded from the primary (non-backup)
|
2005-10-09 04:30:59 +00:00
|
|
|
* data, then we've validated it and know it's good. Before writing our
|
|
|
|
|
* new data, move the old, good data to the backup. (Only do this once;
|
2005-09-29 00:33:22 +00:00
|
|
|
* if we save the profile more than once, we havn't re-validated the
|
|
|
|
|
* newly written data.)
|
|
|
|
|
*/
|
|
|
|
|
if( m_bNeedToBackUpLastLoad[pn] )
|
|
|
|
|
{
|
|
|
|
|
m_bNeedToBackUpLastLoad[pn] = false;
|
2005-09-29 06:19:45 +00:00
|
|
|
CString sBackupDir = m_sProfileDir[pn] + LAST_GOOD_SUBDIR;
|
2005-09-29 00:33:22 +00:00
|
|
|
Profile::MoveBackupToDir( m_sProfileDir[pn], sBackupDir );
|
|
|
|
|
}
|
|
|
|
|
|
2005-07-13 19:15:31 +00:00
|
|
|
bool b = GetProfile(pn)->SaveAllToDir( m_sProfileDir[pn], PREFSMAN->m_bSignProfileData );
|
2004-06-06 02:41:16 +00:00
|
|
|
|
|
|
|
|
return b;
|
2003-11-01 19:36:52 +00:00
|
|
|
}
|
2003-09-14 20:34:33 +00:00
|
|
|
|
2005-08-05 04:20:46 +00:00
|
|
|
bool ProfileManager::SaveLocalProfile( CString sProfileID )
|
|
|
|
|
{
|
2005-08-14 01:59:46 +00:00
|
|
|
Profile *pProfile = GetLocalProfile( sProfileID );
|
|
|
|
|
ASSERT( pProfile != NULL );
|
2005-08-14 23:01:34 +00:00
|
|
|
CString sDir = LocalProfileIDToDir( sProfileID );
|
2005-08-14 01:59:46 +00:00
|
|
|
bool b = pProfile->SaveAllToDir( sDir, PREFSMAN->m_bSignProfileData );
|
2005-08-05 04:20:46 +00:00
|
|
|
return b;
|
|
|
|
|
}
|
|
|
|
|
|
2003-11-01 19:36:52 +00:00
|
|
|
void ProfileManager::UnloadProfile( PlayerNumber pn )
|
|
|
|
|
{
|
|
|
|
|
m_sProfileDir[pn] = "";
|
2005-04-24 19:39:54 +00:00
|
|
|
m_sProfileDirImportedFrom[pn] = "";
|
2004-01-03 03:42:40 +00:00
|
|
|
m_bWasLoadedFromMemoryCard[pn] = false;
|
2004-10-06 08:39:38 +00:00
|
|
|
m_bLastLoadWasTamperedOrCorrupt[pn] = false;
|
2004-10-07 19:57:51 +00:00
|
|
|
m_bLastLoadWasFromLastGood[pn] = false;
|
2005-09-29 00:33:22 +00:00
|
|
|
m_bNeedToBackUpLastLoad[pn] = false;
|
2005-07-13 19:15:31 +00:00
|
|
|
m_pMemoryCardProfile[pn]->InitAll();
|
2005-04-25 00:25:04 +00:00
|
|
|
SONGMAN->FreeAllLoadedFromProfile( (ProfileSlot) pn );
|
2003-09-08 07:21:41 +00:00
|
|
|
}
|
|
|
|
|
|
2004-02-10 10:06:34 +00:00
|
|
|
const Profile* ProfileManager::GetProfile( PlayerNumber pn ) const
|
2003-09-08 07:21:41 +00:00
|
|
|
{
|
2005-07-13 19:15:31 +00:00
|
|
|
ASSERT( pn >= 0 && pn < NUM_PLAYERS );
|
2004-02-23 08:16:40 +00:00
|
|
|
|
2005-08-03 03:23:21 +00:00
|
|
|
if( m_sProfileDir[pn].empty() )
|
|
|
|
|
{
|
|
|
|
|
// return an empty profile
|
|
|
|
|
return m_pMemoryCardProfile[pn];
|
|
|
|
|
}
|
|
|
|
|
else if( ProfileWasLoadedFromMemoryCard(pn) )
|
2005-07-18 17:34:47 +00:00
|
|
|
{
|
2005-07-13 19:15:31 +00:00
|
|
|
return m_pMemoryCardProfile[pn];
|
2005-07-18 17:34:47 +00:00
|
|
|
}
|
2005-07-13 19:15:31 +00:00
|
|
|
else
|
2005-07-18 17:34:47 +00:00
|
|
|
{
|
2005-08-14 23:01:34 +00:00
|
|
|
CString sProfileID = LocalProfileDirToID( m_sProfileDir[pn] );
|
2005-08-14 01:59:46 +00:00
|
|
|
return GetLocalProfile( sProfileID );
|
2005-07-18 17:34:47 +00:00
|
|
|
}
|
2003-09-08 07:21:41 +00:00
|
|
|
}
|
2003-09-08 03:26:58 +00:00
|
|
|
|
2004-02-22 02:01:40 +00:00
|
|
|
CString ProfileManager::GetPlayerName( PlayerNumber pn ) const
|
2003-12-17 09:42:31 +00:00
|
|
|
{
|
2004-02-22 02:01:40 +00:00
|
|
|
const Profile *prof = GetProfile( pn );
|
2005-07-13 19:15:31 +00:00
|
|
|
return prof ? prof->GetDisplayNameOrHighScoreName() : CString();
|
2003-12-17 09:42:31 +00:00
|
|
|
}
|
|
|
|
|
|
2003-09-08 07:21:41 +00:00
|
|
|
|
2005-08-11 23:06:01 +00:00
|
|
|
void ProfileManager::UnloadAllLocalProfiles()
|
2005-07-12 20:19:52 +00:00
|
|
|
{
|
2005-08-14 01:59:46 +00:00
|
|
|
g_vLocalProfile.clear();
|
2005-08-11 23:06:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ProfileManager::RefreshLocalProfilesFromDisk()
|
|
|
|
|
{
|
|
|
|
|
UnloadAllLocalProfiles();
|
2005-07-13 19:15:31 +00:00
|
|
|
|
2005-07-12 20:19:52 +00:00
|
|
|
vector<CString> vsProfileID;
|
2005-08-14 01:59:46 +00:00
|
|
|
GetDirListing( USER_PROFILES_DIR "*", vsProfileID, true, true );
|
|
|
|
|
FOREACH_CONST( CString, vsProfileID, p )
|
2005-07-12 20:19:52 +00:00
|
|
|
{
|
2005-08-14 01:59:46 +00:00
|
|
|
g_vLocalProfile.push_back( DirAndProfile() );
|
|
|
|
|
DirAndProfile &dap = g_vLocalProfile.back();
|
2005-08-14 11:09:23 +00:00
|
|
|
dap.sDir = *p + "/";
|
2005-08-14 20:31:20 +00:00
|
|
|
dap.profile.LoadAllFromDir( dap.sDir, PREFSMAN->m_bSignProfileData );
|
2005-07-12 20:19:52 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2005-08-14 01:59:46 +00:00
|
|
|
const Profile *ProfileManager::GetLocalProfile( const CString &sProfileID ) const
|
2005-07-12 20:19:52 +00:00
|
|
|
{
|
2005-08-14 23:01:34 +00:00
|
|
|
CString sDir = LocalProfileIDToDir( sProfileID );
|
2005-08-14 01:59:46 +00:00
|
|
|
FOREACH_CONST( DirAndProfile, g_vLocalProfile, dap )
|
2005-07-12 20:19:52 +00:00
|
|
|
{
|
2005-08-14 11:09:23 +00:00
|
|
|
const CString &sOther = dap->sDir;
|
|
|
|
|
if( sOther == sDir )
|
2005-08-14 01:59:46 +00:00
|
|
|
return &dap->profile;
|
2005-07-12 20:19:52 +00:00
|
|
|
}
|
|
|
|
|
|
2005-08-14 01:59:46 +00:00
|
|
|
return NULL;
|
2005-07-12 20:19:52 +00:00
|
|
|
}
|
|
|
|
|
|
2005-07-16 05:28:34 +00:00
|
|
|
bool ProfileManager::CreateLocalProfile( CString sName, CString &sProfileIDOut )
|
2003-09-08 07:21:41 +00:00
|
|
|
{
|
2003-12-07 08:19:10 +00:00
|
|
|
ASSERT( !sName.empty() );
|
2003-11-01 22:04:43 +00:00
|
|
|
|
2003-09-08 07:21:41 +00:00
|
|
|
//
|
2005-08-05 10:01:10 +00:00
|
|
|
// Find a directory directory name that's a number greater than all
|
|
|
|
|
// existing numbers. This preserves the "order by create date".
|
2003-09-08 07:21:41 +00:00
|
|
|
//
|
2005-08-05 10:01:10 +00:00
|
|
|
int iMaxProfileNumber = -1;
|
|
|
|
|
vector<CString> vs;
|
|
|
|
|
GetLocalProfileIDs( vs );
|
|
|
|
|
FOREACH_CONST( CString, vs, s )
|
|
|
|
|
iMaxProfileNumber = atoi( *s );
|
|
|
|
|
|
|
|
|
|
int iProfileNumber = iMaxProfileNumber + 1;
|
|
|
|
|
CString sProfileID = ssprintf( "%08d", iProfileNumber );
|
2003-09-08 07:21:41 +00:00
|
|
|
|
2005-08-13 01:47:56 +00:00
|
|
|
//
|
|
|
|
|
// Create the new profile.
|
|
|
|
|
//
|
|
|
|
|
Profile *pProfile = new Profile;
|
|
|
|
|
pProfile->m_sDisplayName = sName;
|
2005-08-14 12:06:40 +00:00
|
|
|
pProfile->m_sCharacterID = CHARMAN->GetRandomCharacter()->m_sCharacterID;
|
2005-08-13 01:47:56 +00:00
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Save it to disk.
|
|
|
|
|
//
|
2005-08-14 23:01:34 +00:00
|
|
|
CString sProfileDir = LocalProfileIDToDir( sProfileID );
|
2005-08-13 01:47:56 +00:00
|
|
|
if( !pProfile->SaveAllToDir(sProfileDir, PREFSMAN->m_bSignProfileData) )
|
2005-08-11 23:10:44 +00:00
|
|
|
{
|
2005-08-13 01:47:56 +00:00
|
|
|
delete pProfile;
|
2005-07-16 05:28:34 +00:00
|
|
|
sProfileIDOut = "";
|
2005-08-11 23:10:44 +00:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2005-08-13 01:47:56 +00:00
|
|
|
AddLocalProfileByID( pProfile, sProfileID );
|
|
|
|
|
|
2005-08-11 23:10:44 +00:00
|
|
|
sProfileIDOut = sProfileID;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2005-08-13 01:47:56 +00:00
|
|
|
void ProfileManager::AddLocalProfileByID( Profile *pProfile, CString sProfileID )
|
2005-08-11 23:10:44 +00:00
|
|
|
{
|
2005-08-14 01:59:46 +00:00
|
|
|
// make sure this id doesn't already exist
|
|
|
|
|
ASSERT_M( GetLocalProfile(sProfileID) == NULL,
|
2005-08-12 19:05:38 +00:00
|
|
|
ssprintf("creating \"%s\" \"%s\" that already exists",
|
2005-08-13 01:47:56 +00:00
|
|
|
pProfile->m_sDisplayName.c_str(), sProfileID.c_str()) );
|
2005-08-11 23:10:44 +00:00
|
|
|
|
2005-08-14 01:59:46 +00:00
|
|
|
// insert
|
|
|
|
|
g_vLocalProfile.push_back( DirAndProfile() );
|
|
|
|
|
DirAndProfile &dap = g_vLocalProfile.back();
|
2005-08-14 23:01:34 +00:00
|
|
|
dap.sDir = LocalProfileIDToDir( sProfileID );
|
2005-08-14 01:59:46 +00:00
|
|
|
dap.profile = *pProfile;
|
2005-08-11 23:14:32 +00:00
|
|
|
}
|
|
|
|
|
|
2003-12-07 08:19:10 +00:00
|
|
|
bool ProfileManager::RenameLocalProfile( CString sProfileID, CString sNewName )
|
2003-11-01 19:36:52 +00:00
|
|
|
{
|
|
|
|
|
ASSERT( !sProfileID.empty() );
|
|
|
|
|
|
2005-08-14 01:59:46 +00:00
|
|
|
Profile *pProfile = ProfileManager::GetLocalProfile( sProfileID );
|
|
|
|
|
ASSERT( pProfile );
|
|
|
|
|
pProfile->m_sDisplayName = sNewName;
|
2003-11-01 19:36:52 +00:00
|
|
|
|
2005-08-14 23:01:34 +00:00
|
|
|
CString sProfileDir = LocalProfileIDToDir( sProfileID );
|
2005-08-14 01:59:46 +00:00
|
|
|
return pProfile->SaveAllToDir( sProfileDir, PREFSMAN->m_bSignProfileData );
|
2003-09-08 03:26:58 +00:00
|
|
|
}
|
2003-11-01 19:36:52 +00:00
|
|
|
|
2003-12-07 08:19:10 +00:00
|
|
|
bool ProfileManager::DeleteLocalProfile( CString sProfileID )
|
2003-11-01 19:36:52 +00:00
|
|
|
{
|
2005-08-14 01:59:46 +00:00
|
|
|
Profile *pProfile = ProfileManager::GetLocalProfile( sProfileID );
|
|
|
|
|
ASSERT( pProfile );
|
2005-08-14 23:01:34 +00:00
|
|
|
CString sProfileDir = LocalProfileIDToDir( sProfileID );
|
2005-07-12 20:19:52 +00:00
|
|
|
|
2005-08-14 01:59:46 +00:00
|
|
|
FOREACH( DirAndProfile, g_vLocalProfile, i )
|
|
|
|
|
{
|
|
|
|
|
if( i->sDir == sProfileDir )
|
|
|
|
|
{
|
|
|
|
|
if( DeleteRecursive(sProfileDir) )
|
|
|
|
|
{
|
|
|
|
|
g_vLocalProfile.erase( i );
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2005-08-12 19:12:20 +00:00
|
|
|
|
2005-08-14 01:59:46 +00:00
|
|
|
LOG->Warn( "DeleteLocalProfile: ProfileID '%s' doesn't exist", sProfileID.c_str() );
|
|
|
|
|
return false;
|
2003-11-01 23:43:22 +00:00
|
|
|
}
|
2003-12-07 07:09:13 +00:00
|
|
|
|
2004-07-20 01:31:23 +00:00
|
|
|
void ProfileManager::SaveMachineProfile() const
|
2003-12-07 07:09:13 +00:00
|
|
|
{
|
2004-02-16 05:35:06 +00:00
|
|
|
// If the machine name has changed, make sure we use the new name.
|
|
|
|
|
// It's important that this name be applied before the Player profiles
|
|
|
|
|
// are saved, so that the Player's profiles show the right machine name.
|
2005-07-01 04:46:32 +00:00
|
|
|
const_cast<ProfileManager *> (this)->m_pMachineProfile->m_sDisplayName = PREFSMAN->m_sMachineName;
|
2004-02-16 05:35:06 +00:00
|
|
|
|
2005-07-01 04:46:32 +00:00
|
|
|
m_pMachineProfile->SaveAllToDir( MACHINE_PROFILE_DIR, false ); /* don't sign machine profiles */
|
2003-12-07 07:09:13 +00:00
|
|
|
}
|
|
|
|
|
|
2004-02-16 05:35:06 +00:00
|
|
|
void ProfileManager::LoadMachineProfile()
|
2003-12-07 07:09:13 +00:00
|
|
|
{
|
2005-08-13 06:59:27 +00:00
|
|
|
ProfileLoadResult lr = m_pMachineProfile->LoadAllFromDir(MACHINE_PROFILE_DIR, false);
|
|
|
|
|
if( lr == ProfileLoadResult_FailedNoProfile )
|
2003-12-08 06:41:30 +00:00
|
|
|
{
|
2005-08-13 01:38:35 +00:00
|
|
|
m_pMachineProfile->InitAll();
|
|
|
|
|
m_pMachineProfile->SaveAllToDir( MACHINE_PROFILE_DIR, PREFSMAN->m_bSignProfileData );
|
2003-12-08 06:41:30 +00:00
|
|
|
}
|
2004-02-16 05:35:06 +00:00
|
|
|
|
|
|
|
|
// If the machine name has changed, make sure we use the new name
|
2005-07-01 04:46:32 +00:00
|
|
|
m_pMachineProfile->m_sDisplayName = PREFSMAN->m_sMachineName;
|
2005-04-25 00:32:08 +00:00
|
|
|
|
2005-04-28 06:17:17 +00:00
|
|
|
SONGMAN->FreeAllLoadedFromProfile( PROFILE_SLOT_MACHINE );
|
2005-04-25 00:36:26 +00:00
|
|
|
SONGMAN->LoadAllFromProfileDir( MACHINE_PROFILE_DIR, PROFILE_SLOT_MACHINE );
|
2003-12-07 07:09:13 +00:00
|
|
|
}
|
|
|
|
|
|
2004-02-22 02:01:40 +00:00
|
|
|
bool ProfileManager::ProfileWasLoadedFromMemoryCard( PlayerNumber pn ) const
|
2004-01-03 03:42:40 +00:00
|
|
|
{
|
2005-07-13 19:15:31 +00:00
|
|
|
return !m_sProfileDir[pn].empty() && m_bWasLoadedFromMemoryCard[pn];
|
2004-01-03 03:42:40 +00:00
|
|
|
}
|
2004-02-08 01:05:53 +00:00
|
|
|
|
2004-10-06 08:39:38 +00:00
|
|
|
bool ProfileManager::LastLoadWasTamperedOrCorrupt( PlayerNumber pn ) const
|
|
|
|
|
{
|
2005-07-13 19:15:31 +00:00
|
|
|
return !m_sProfileDir[pn].empty() && m_bLastLoadWasTamperedOrCorrupt[pn];
|
2004-10-06 08:39:38 +00:00
|
|
|
}
|
|
|
|
|
|
2004-10-07 19:57:51 +00:00
|
|
|
bool ProfileManager::LastLoadWasFromLastGood( PlayerNumber pn ) const
|
|
|
|
|
{
|
2005-07-13 19:15:31 +00:00
|
|
|
return !m_sProfileDir[pn].empty() && m_bLastLoadWasFromLastGood[pn];
|
2004-10-07 19:57:51 +00:00
|
|
|
}
|
|
|
|
|
|
2004-02-22 02:01:40 +00:00
|
|
|
CString ProfileManager::GetProfileDir( ProfileSlot slot ) const
|
2004-02-08 01:05:53 +00:00
|
|
|
{
|
|
|
|
|
switch( slot )
|
|
|
|
|
{
|
|
|
|
|
case PROFILE_SLOT_PLAYER_1:
|
|
|
|
|
case PROFILE_SLOT_PLAYER_2:
|
|
|
|
|
return m_sProfileDir[slot];
|
|
|
|
|
case PROFILE_SLOT_MACHINE:
|
|
|
|
|
return MACHINE_PROFILE_DIR;
|
|
|
|
|
default:
|
|
|
|
|
ASSERT(0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2005-04-24 19:39:54 +00:00
|
|
|
CString ProfileManager::GetProfileDirImportedFrom( ProfileSlot slot ) const
|
|
|
|
|
{
|
|
|
|
|
switch( slot )
|
|
|
|
|
{
|
|
|
|
|
case PROFILE_SLOT_PLAYER_1:
|
|
|
|
|
case PROFILE_SLOT_PLAYER_2:
|
|
|
|
|
return m_sProfileDirImportedFrom[slot];
|
|
|
|
|
case PROFILE_SLOT_MACHINE:
|
2005-09-02 00:14:07 +00:00
|
|
|
return NULL;
|
2005-04-24 19:39:54 +00:00
|
|
|
default:
|
|
|
|
|
ASSERT(0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-10 10:06:34 +00:00
|
|
|
const Profile* ProfileManager::GetProfile( ProfileSlot slot ) const
|
2004-02-09 06:26:13 +00:00
|
|
|
{
|
|
|
|
|
switch( slot )
|
|
|
|
|
{
|
|
|
|
|
case PROFILE_SLOT_PLAYER_1:
|
|
|
|
|
case PROFILE_SLOT_PLAYER_2:
|
2005-07-18 17:34:47 +00:00
|
|
|
return GetProfile( (PlayerNumber)slot );
|
2004-02-09 06:26:13 +00:00
|
|
|
case PROFILE_SLOT_MACHINE:
|
2005-07-01 04:46:32 +00:00
|
|
|
return m_pMachineProfile;
|
2004-02-09 06:26:13 +00:00
|
|
|
default:
|
|
|
|
|
ASSERT(0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-22 08:16:49 +00:00
|
|
|
//
|
|
|
|
|
// General
|
|
|
|
|
//
|
|
|
|
|
void ProfileManager::IncrementToastiesCount( PlayerNumber pn )
|
|
|
|
|
{
|
2005-05-09 08:44:01 +00:00
|
|
|
if( PROFILEMAN->IsPersistentProfile(pn) )
|
2004-02-22 08:16:49 +00:00
|
|
|
++PROFILEMAN->GetProfile(pn)->m_iNumToasties;
|
|
|
|
|
++PROFILEMAN->GetMachineProfile()->m_iNumToasties;
|
|
|
|
|
}
|
2004-02-09 06:26:13 +00:00
|
|
|
|
2005-04-25 11:42:19 +00:00
|
|
|
void ProfileManager::AddStepTotals( PlayerNumber pn, int iNumTapsAndHolds, int iNumJumps, int iNumHolds, int iNumRolls, int iNumMines, int iNumHands, float fCaloriesBurned )
|
2004-02-22 19:51:46 +00:00
|
|
|
{
|
2005-05-09 08:44:01 +00:00
|
|
|
if( PROFILEMAN->IsPersistentProfile(pn) )
|
2005-04-25 11:42:19 +00:00
|
|
|
PROFILEMAN->GetProfile(pn)->AddStepTotals( iNumTapsAndHolds, iNumJumps, iNumHolds, iNumRolls, iNumMines, iNumHands, fCaloriesBurned );
|
|
|
|
|
PROFILEMAN->GetMachineProfile()->AddStepTotals( iNumTapsAndHolds, iNumJumps, iNumHolds, iNumRolls, iNumMines, iNumHands, fCaloriesBurned );
|
2004-02-22 19:51:46 +00:00
|
|
|
}
|
|
|
|
|
|
2004-02-09 06:26:13 +00:00
|
|
|
//
|
|
|
|
|
// Song stats
|
|
|
|
|
//
|
2004-02-10 10:06:34 +00:00
|
|
|
int ProfileManager::GetSongNumTimesPlayed( const Song* pSong, ProfileSlot slot ) const
|
2004-02-09 06:26:13 +00:00
|
|
|
{
|
2004-02-10 09:42:01 +00:00
|
|
|
return GetProfile(slot)->GetSongNumTimesPlayed( pSong );
|
2004-02-09 06:26:13 +00:00
|
|
|
}
|
|
|
|
|
|
2005-07-01 05:06:00 +00:00
|
|
|
void ProfileManager::AddStepsScore( const Song* pSong, const Steps* pSteps, PlayerNumber pn, const HighScore &hs_, int &iPersonalIndexOut, int &iMachineIndexOut )
|
2004-02-09 06:26:13 +00:00
|
|
|
{
|
2005-07-01 05:06:00 +00:00
|
|
|
HighScore hs = hs_;
|
2005-08-12 02:46:58 +00:00
|
|
|
hs.SetPercentDP( max(0, hs.GetPercentDP()) ); // bump up negative scores
|
2004-06-26 21:38:38 +00:00
|
|
|
|
2004-06-09 08:25:08 +00:00
|
|
|
iPersonalIndexOut = -1;
|
|
|
|
|
iMachineIndexOut = -1;
|
|
|
|
|
|
|
|
|
|
// In event mode, set the score's name immediately to the Profile's last
|
2004-07-11 05:21:19 +00:00
|
|
|
// used name. If no profile last used name exists, use "EVNT".
|
2005-04-05 08:30:57 +00:00
|
|
|
if( GAMESTATE->IsEventMode() )
|
2004-06-09 08:25:08 +00:00
|
|
|
{
|
|
|
|
|
Profile* pProfile = PROFILEMAN->GetProfile(pn);
|
|
|
|
|
if( pProfile && !pProfile->m_sLastUsedHighScoreName.empty() )
|
2005-08-12 01:52:01 +00:00
|
|
|
hs.SetName( pProfile->m_sLastUsedHighScoreName );
|
2004-06-09 08:25:08 +00:00
|
|
|
else
|
2005-08-12 01:52:01 +00:00
|
|
|
hs.SetName( "EVNT" );
|
2004-06-09 08:25:08 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2005-08-12 01:52:01 +00:00
|
|
|
hs.SetName( RANKING_TO_FILL_IN_MARKER[pn] );
|
2004-06-09 08:25:08 +00:00
|
|
|
}
|
|
|
|
|
|
2004-08-21 15:51:33 +00:00
|
|
|
//
|
|
|
|
|
// save high score
|
|
|
|
|
//
|
2005-06-16 02:50:37 +00:00
|
|
|
if( PROFILEMAN->IsPersistentProfile(pn) )
|
|
|
|
|
PROFILEMAN->GetProfile(pn)->AddStepsHighScore( pSong, pSteps, hs, iPersonalIndexOut );
|
|
|
|
|
|
2005-08-12 02:46:58 +00:00
|
|
|
if( hs.GetPercentDP() >= PREFSMAN->m_fMinPercentageForMachineSongHighScore )
|
2004-04-22 22:01:38 +00:00
|
|
|
{
|
2005-06-15 09:25:33 +00:00
|
|
|
// don't leave machine high scores for edits loaded from the player's card
|
|
|
|
|
if( !pSteps->IsAPlayerEdit() )
|
2004-04-23 02:19:45 +00:00
|
|
|
PROFILEMAN->GetMachineProfile()->AddStepsHighScore( pSong, pSteps, hs, iMachineIndexOut );
|
2004-04-22 22:01:38 +00:00
|
|
|
}
|
|
|
|
|
|
2004-08-21 15:51:33 +00:00
|
|
|
//
|
|
|
|
|
// save recent score
|
|
|
|
|
//
|
2005-05-09 08:44:01 +00:00
|
|
|
if( PROFILEMAN->IsPersistentProfile(pn) )
|
2004-05-08 10:12:10 +00:00
|
|
|
PROFILEMAN->GetProfile(pn)->AddStepsRecentScore( pSong, pSteps, hs );
|
|
|
|
|
PROFILEMAN->GetMachineProfile()->AddStepsRecentScore( pSong, pSteps, hs );
|
2004-02-09 06:26:13 +00:00
|
|
|
}
|
|
|
|
|
|
2004-04-18 18:42:42 +00:00
|
|
|
void ProfileManager::IncrementStepsPlayCount( const Song* pSong, const Steps* pSteps, PlayerNumber pn )
|
2004-02-09 06:26:13 +00:00
|
|
|
{
|
2005-05-09 08:44:01 +00:00
|
|
|
if( PROFILEMAN->IsPersistentProfile(pn) )
|
2004-04-18 18:42:42 +00:00
|
|
|
PROFILEMAN->GetProfile(pn)->IncrementStepsPlayCount( pSong, pSteps );
|
|
|
|
|
PROFILEMAN->GetMachineProfile()->IncrementStepsPlayCount( pSong, pSteps );
|
2004-02-09 06:26:13 +00:00
|
|
|
}
|
|
|
|
|
|
2005-07-01 05:06:00 +00:00
|
|
|
void ProfileManager::GetHighScoreForDifficulty( const Song *s, const Style *st, ProfileSlot slot, Difficulty dc, HighScore &hsOut ) const
|
2004-02-09 06:26:13 +00:00
|
|
|
{
|
|
|
|
|
// return max grade of notes in difficulty class
|
|
|
|
|
vector<Steps*> aNotes;
|
|
|
|
|
s->GetSteps( aNotes, st->m_StepsType );
|
2004-04-18 07:34:37 +00:00
|
|
|
StepsUtil::SortNotesArrayByDifficulty( aNotes );
|
2004-02-09 06:26:13 +00:00
|
|
|
|
2004-02-22 02:01:40 +00:00
|
|
|
const Steps* pSteps = s->GetStepsByDifficulty( st->m_StepsType, dc );
|
2004-02-09 06:26:13 +00:00
|
|
|
|
2005-05-09 08:44:01 +00:00
|
|
|
if( pSteps && PROFILEMAN->IsPersistentProfile(slot) )
|
2005-07-01 05:06:00 +00:00
|
|
|
hsOut = PROFILEMAN->GetProfile(slot)->GetStepsHighScoreList(s,pSteps).GetTopScore();
|
2004-02-09 06:26:13 +00:00
|
|
|
else
|
2005-07-01 05:06:00 +00:00
|
|
|
hsOut = HighScore();
|
2004-02-09 06:26:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Course stats
|
|
|
|
|
//
|
2005-07-01 05:06:00 +00:00
|
|
|
void ProfileManager::AddCourseScore( const Course* pCourse, const Trail* pTrail, PlayerNumber pn, const HighScore &hs_, int &iPersonalIndexOut, int &iMachineIndexOut )
|
2004-02-09 06:26:13 +00:00
|
|
|
{
|
2005-07-01 05:06:00 +00:00
|
|
|
HighScore hs = hs_;
|
2005-08-12 02:46:58 +00:00
|
|
|
hs.SetPercentDP(max( 0, hs.GetPercentDP()) ); // bump up negative scores
|
2004-06-26 21:38:38 +00:00
|
|
|
|
2004-06-09 08:25:08 +00:00
|
|
|
iPersonalIndexOut = -1;
|
|
|
|
|
iMachineIndexOut = -1;
|
|
|
|
|
|
|
|
|
|
// In event mode, set the score's name immediately to the Profile's last
|
2004-07-11 05:21:19 +00:00
|
|
|
// used name. If no profile last used name exists, use "EVNT".
|
2005-04-05 08:30:57 +00:00
|
|
|
if( GAMESTATE->IsEventMode() )
|
2004-06-09 08:25:08 +00:00
|
|
|
{
|
|
|
|
|
Profile* pProfile = PROFILEMAN->GetProfile(pn);
|
|
|
|
|
if( pProfile && !pProfile->m_sLastUsedHighScoreName.empty() )
|
2005-08-12 01:52:01 +00:00
|
|
|
hs.SetName( pProfile->m_sLastUsedHighScoreName );
|
2004-06-09 08:25:08 +00:00
|
|
|
else
|
2005-08-12 01:52:01 +00:00
|
|
|
hs.SetName( "EVNT" );
|
2004-06-09 08:25:08 +00:00
|
|
|
}
|
|
|
|
|
else
|
2004-04-22 22:01:38 +00:00
|
|
|
{
|
2005-08-12 01:52:01 +00:00
|
|
|
hs.SetName( RANKING_TO_FILL_IN_MARKER[pn] );
|
2004-06-09 08:25:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2004-08-21 15:51:33 +00:00
|
|
|
//
|
|
|
|
|
// save high score
|
|
|
|
|
//
|
2005-06-16 02:50:37 +00:00
|
|
|
if( PROFILEMAN->IsPersistentProfile(pn) )
|
|
|
|
|
PROFILEMAN->GetProfile(pn)->AddCourseHighScore( pCourse, pTrail, hs, iPersonalIndexOut );
|
2005-08-12 02:46:58 +00:00
|
|
|
if( hs.GetPercentDP() >= PREFSMAN->m_fMinPercentageForMachineCourseHighScore )
|
2004-05-23 09:17:10 +00:00
|
|
|
PROFILEMAN->GetMachineProfile()->AddCourseHighScore( pCourse, pTrail, hs, iMachineIndexOut );
|
2004-04-22 22:01:38 +00:00
|
|
|
|
2004-08-21 15:51:33 +00:00
|
|
|
//
|
|
|
|
|
// save recent score
|
|
|
|
|
//
|
2005-05-09 08:44:01 +00:00
|
|
|
if( PROFILEMAN->IsPersistentProfile(pn) )
|
2004-05-23 09:17:10 +00:00
|
|
|
PROFILEMAN->GetProfile(pn)->AddCourseRecentScore( pCourse, pTrail, hs );
|
|
|
|
|
PROFILEMAN->GetMachineProfile()->AddCourseRecentScore( pCourse, pTrail, hs );
|
2004-02-09 06:26:13 +00:00
|
|
|
}
|
|
|
|
|
|
2004-05-23 09:17:10 +00:00
|
|
|
void ProfileManager::IncrementCoursePlayCount( const Course* pCourse, const Trail* pTrail, PlayerNumber pn )
|
2004-02-09 06:26:13 +00:00
|
|
|
{
|
2005-05-09 08:44:01 +00:00
|
|
|
if( PROFILEMAN->IsPersistentProfile(pn) )
|
2004-05-23 09:17:10 +00:00
|
|
|
PROFILEMAN->GetProfile(pn)->IncrementCoursePlayCount( pCourse, pTrail );
|
|
|
|
|
PROFILEMAN->GetMachineProfile()->IncrementCoursePlayCount( pCourse, pTrail );
|
2004-02-09 06:26:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Category stats
|
|
|
|
|
//
|
2005-07-01 05:06:00 +00:00
|
|
|
void ProfileManager::AddCategoryScore( StepsType st, RankingCategory rc, PlayerNumber pn, const HighScore &hs_, int &iPersonalIndexOut, int &iMachineIndexOut )
|
2004-02-09 06:26:13 +00:00
|
|
|
{
|
2005-07-01 05:06:00 +00:00
|
|
|
HighScore hs = hs_;
|
2005-08-12 01:52:01 +00:00
|
|
|
hs.SetName( RANKING_TO_FILL_IN_MARKER[pn] );
|
2005-06-16 02:50:37 +00:00
|
|
|
if( PROFILEMAN->IsPersistentProfile(pn) )
|
|
|
|
|
PROFILEMAN->GetProfile(pn)->AddCategoryHighScore( st, rc, hs, iPersonalIndexOut );
|
2005-08-12 02:46:58 +00:00
|
|
|
if( hs.GetPercentDP() > PREFSMAN->m_fMinPercentageForMachineSongHighScore )
|
2004-04-22 22:01:38 +00:00
|
|
|
PROFILEMAN->GetMachineProfile()->AddCategoryHighScore( st, rc, hs, iMachineIndexOut );
|
2004-02-09 06:26:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ProfileManager::IncrementCategoryPlayCount( StepsType st, RankingCategory rc, PlayerNumber pn )
|
|
|
|
|
{
|
2005-05-09 08:44:01 +00:00
|
|
|
if( PROFILEMAN->IsPersistentProfile(pn) )
|
2004-02-09 06:26:13 +00:00
|
|
|
PROFILEMAN->GetProfile(pn)->IncrementCategoryPlayCount( st, rc );
|
|
|
|
|
PROFILEMAN->GetMachineProfile()->IncrementCategoryPlayCount( st, rc );
|
|
|
|
|
}
|
|
|
|
|
|
2005-05-09 08:44:01 +00:00
|
|
|
bool ProfileManager::IsPersistentProfile( ProfileSlot slot ) const
|
2004-04-23 02:01:44 +00:00
|
|
|
{
|
|
|
|
|
switch( slot )
|
|
|
|
|
{
|
|
|
|
|
case PROFILE_SLOT_PLAYER_1:
|
|
|
|
|
case PROFILE_SLOT_PLAYER_2:
|
|
|
|
|
return GAMESTATE->IsHumanPlayer((PlayerNumber)slot) && !m_sProfileDir[slot].empty();
|
|
|
|
|
case PROFILE_SLOT_MACHINE:
|
|
|
|
|
return true;
|
|
|
|
|
default:
|
|
|
|
|
ASSERT(0);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2005-07-12 20:19:52 +00:00
|
|
|
void ProfileManager::GetLocalProfileIDs( vector<CString> &vsProfileIDsOut ) const
|
|
|
|
|
{
|
|
|
|
|
vsProfileIDsOut.clear();
|
2005-08-14 01:59:46 +00:00
|
|
|
FOREACH_CONST( DirAndProfile, g_vLocalProfile, i)
|
2005-08-05 10:01:10 +00:00
|
|
|
{
|
2005-08-14 23:01:34 +00:00
|
|
|
CString sID = LocalProfileDirToID( i->sDir );
|
2005-08-05 10:01:10 +00:00
|
|
|
vsProfileIDsOut.push_back( sID );
|
|
|
|
|
}
|
2005-07-12 20:19:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ProfileManager::GetLocalProfileDisplayNames( vector<CString> &vsProfileDisplayNamesOut ) const
|
|
|
|
|
{
|
|
|
|
|
vsProfileDisplayNamesOut.clear();
|
2005-08-14 01:59:46 +00:00
|
|
|
FOREACH_CONST( DirAndProfile, g_vLocalProfile, i)
|
|
|
|
|
vsProfileDisplayNamesOut.push_back( i->profile.m_sDisplayName );
|
2005-07-13 19:15:31 +00:00
|
|
|
}
|
|
|
|
|
|
2005-08-14 20:31:20 +00:00
|
|
|
int ProfileManager::GetLocalProfileIndexFromID( CString sProfileID ) const
|
2005-08-06 05:34:06 +00:00
|
|
|
{
|
2005-08-14 23:01:34 +00:00
|
|
|
CString sDir = LocalProfileIDToDir( sProfileID );
|
2005-08-14 01:59:46 +00:00
|
|
|
FOREACH_CONST( DirAndProfile, g_vLocalProfile, i )
|
2005-08-06 05:34:06 +00:00
|
|
|
{
|
2005-08-14 01:59:46 +00:00
|
|
|
if( i->sDir == sProfileID )
|
|
|
|
|
return i - g_vLocalProfile.begin();
|
2005-08-06 05:34:06 +00:00
|
|
|
}
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2005-08-14 23:01:34 +00:00
|
|
|
CString ProfileManager::GetLocalProfileIDFromIndex( int iIndex )
|
|
|
|
|
{
|
|
|
|
|
CString sID = LocalProfileDirToID( g_vLocalProfile[iIndex].sDir );
|
|
|
|
|
return sID;
|
|
|
|
|
}
|
|
|
|
|
|
2005-08-14 20:31:20 +00:00
|
|
|
Profile *ProfileManager::GetLocalProfileFromIndex( int iIndex )
|
|
|
|
|
{
|
|
|
|
|
return &g_vLocalProfile[iIndex].profile;
|
|
|
|
|
}
|
|
|
|
|
|
2005-08-05 10:01:10 +00:00
|
|
|
int ProfileManager::GetNumLocalProfiles() const
|
|
|
|
|
{
|
2005-08-14 01:59:46 +00:00
|
|
|
return g_vLocalProfile.size();
|
2005-08-05 10:01:10 +00:00
|
|
|
}
|
|
|
|
|
|
2005-07-12 20:19:52 +00:00
|
|
|
|
2005-02-13 01:16:17 +00:00
|
|
|
// lua start
|
|
|
|
|
#include "LuaBinding.h"
|
|
|
|
|
|
2005-06-20 05:02:03 +00:00
|
|
|
class LunaProfileManager: public Luna<ProfileManager>
|
2005-02-13 01:16:17 +00:00
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
LunaProfileManager() { LUA->Register( Register ); }
|
|
|
|
|
|
2005-05-09 08:44:01 +00:00
|
|
|
static int IsPersistentProfile( T* p, lua_State *L ) { lua_pushboolean(L, p->IsPersistentProfile((PlayerNumber)IArg(1)) ); return 1; }
|
|
|
|
|
static int GetProfile( T* p, lua_State *L ) { PlayerNumber pn = (PlayerNumber)IArg(1); Profile* pP = p->GetProfile(pn); ASSERT(pP); pP->PushSelf(L); return 1; }
|
|
|
|
|
static int GetMachineProfile( T* p, lua_State *L ) { p->GetMachineProfile()->PushSelf(L); return 1; }
|
2005-09-03 23:43:16 +00:00
|
|
|
static int SaveMachineProfile( T* p, lua_State *L ) { p->SaveMachineProfile(); return 0; }
|
2005-08-14 01:59:46 +00:00
|
|
|
static int GetLocalProfile( T* p, lua_State *L )
|
|
|
|
|
{
|
|
|
|
|
Profile *pProfile = p->GetLocalProfile(SArg(1));
|
|
|
|
|
if( pProfile )
|
|
|
|
|
pProfile->PushSelf(L);
|
|
|
|
|
else
|
|
|
|
|
lua_pushnil(L );
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2005-08-14 20:31:20 +00:00
|
|
|
static int GetLocalProfileFromIndex( T* p, lua_State *L ) { Profile *pProfile = p->GetLocalProfileFromIndex(IArg(1)); ASSERT(pProfile); pProfile->PushSelf(L); return 1; }
|
2005-08-14 23:01:34 +00:00
|
|
|
static int GetLocalProfileIDFromIndex( T* p, lua_State *L ) { lua_pushstring(L, p->GetLocalProfileIDFromIndex(IArg(1)) ); return 1; }
|
2005-08-14 20:31:20 +00:00
|
|
|
static int GetLocalProfileIndexFromID( T* p, lua_State *L ) { lua_pushnumber(L, p->GetLocalProfileIndexFromID(SArg(1)) ); return 1; }
|
2005-08-06 05:34:06 +00:00
|
|
|
static int GetNumLocalProfiles( T* p, lua_State *L ) { lua_pushnumber(L, p->GetNumLocalProfiles() ); return 1; }
|
2005-02-13 01:16:17 +00:00
|
|
|
|
|
|
|
|
static void Register(lua_State *L)
|
|
|
|
|
{
|
2005-09-10 02:47:04 +00:00
|
|
|
ADD_METHOD( IsPersistentProfile );
|
|
|
|
|
ADD_METHOD( GetProfile );
|
|
|
|
|
ADD_METHOD( GetMachineProfile );
|
|
|
|
|
ADD_METHOD( SaveMachineProfile );
|
|
|
|
|
ADD_METHOD( GetLocalProfile );
|
|
|
|
|
ADD_METHOD( GetLocalProfileFromIndex );
|
|
|
|
|
ADD_METHOD( GetLocalProfileIDFromIndex );
|
|
|
|
|
ADD_METHOD( GetLocalProfileIndexFromID );
|
|
|
|
|
ADD_METHOD( GetNumLocalProfiles );
|
|
|
|
|
|
2005-02-13 01:16:17 +00:00
|
|
|
Luna<T>::Register( L );
|
|
|
|
|
|
|
|
|
|
// Add global singleton if constructed already. If it's not constructed yet,
|
2005-02-16 00:16:14 +00:00
|
|
|
// then we'll register it later when we reinit Lua just before
|
2005-02-13 01:16:17 +00:00
|
|
|
// initializing the display.
|
|
|
|
|
if( PROFILEMAN )
|
|
|
|
|
{
|
|
|
|
|
lua_pushstring(L, "PROFILEMAN");
|
2005-06-15 02:21:24 +00:00
|
|
|
PROFILEMAN->PushSelf( L );
|
2005-02-13 01:16:17 +00:00
|
|
|
lua_settable(L, LUA_GLOBALSINDEX);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
LUA_REGISTER_CLASS( ProfileManager )
|
|
|
|
|
// lua end
|
|
|
|
|
|
2004-06-08 01:24:17 +00:00
|
|
|
/*
|
|
|
|
|
* (c) 2003-2004 Chris Danford
|
|
|
|
|
* All rights reserved.
|
|
|
|
|
*
|
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
|
* copy of this software and associated documentation files (the
|
|
|
|
|
* "Software"), to deal in the Software without restriction, including
|
|
|
|
|
* without limitation the rights to use, copy, modify, merge, publish,
|
|
|
|
|
* distribute, and/or sell copies of the Software, and to permit persons to
|
|
|
|
|
* whom the Software is furnished to do so, provided that the above
|
|
|
|
|
* copyright notice(s) and this permission notice appear in all copies of
|
|
|
|
|
* the Software and that both the above copyright notice(s) and this
|
|
|
|
|
* permission notice appear in supporting documentation.
|
|
|
|
|
*
|
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
|
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
|
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
|
|
|
|
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
|
|
|
|
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
|
|
|
|
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
|
|
|
|
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
|
|
|
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
|
|
|
* PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
|
*/
|