From 221b51c2b40d4eaf7cd3a07a391cdcf47258e26a Mon Sep 17 00:00:00 2001 From: Chris Danford Date: Sun, 8 Feb 2004 01:05:53 +0000 Subject: [PATCH] add loading of edits from a profile --- ...creenEvaluation difficulty icons 1x6.redir | 1 + .../ScreenGameplay difficulty icons 2x6.png | Bin 0 -> 28521 bytes ...ScreenSelectMusic difficulty icons 1x6.png | Bin 0 -> 13951 bytes stepmania/Themes/default/metrics.ini | 2 + stepmania/src/Course.cpp | 6 +- stepmania/src/Course.h | 14 +- stepmania/src/DifficultyDisplay.cpp | 2 +- stepmania/src/DifficultyIcon.cpp | 18 +- stepmania/src/DifficultyList.cpp | 6 +- stepmania/src/GameConstantsAndTypes.cpp | 2 + stepmania/src/GameConstantsAndTypes.h | 14 +- stepmania/src/GameState.cpp | 25 ++- stepmania/src/GameState.h | 1 + stepmania/src/MemoryCardManager.h | 2 +- stepmania/src/ModeChoice.cpp | 2 +- stepmania/src/MusicWheelItem.cpp | 6 +- stepmania/src/NotesLoaderSM.cpp | 67 +++++++ stepmania/src/NotesLoaderSM.h | 1 + stepmania/src/PaneDisplay.cpp | 22 +-- stepmania/src/ProfileManager.cpp | 187 ++++++++++-------- stepmania/src/ProfileManager.h | 19 +- stepmania/src/ScreenGameplay.cpp | 6 +- stepmania/src/ScreenRanking.cpp | 24 +-- stepmania/src/ScreenSelectCourse.cpp | 2 +- stepmania/src/ScreenSelectMusic.cpp | 10 +- stepmania/src/Song.cpp | 20 +- stepmania/src/SongManager.cpp | 57 +++++- stepmania/src/SongManager.h | 11 +- stepmania/src/Steps.cpp | 15 +- stepmania/src/Steps.h | 18 +- stepmania/src/song.h | 9 +- 31 files changed, 370 insertions(+), 199 deletions(-) create mode 100644 stepmania/Themes/default/Graphics/ScreenEvaluation difficulty icons 1x6.redir create mode 100644 stepmania/Themes/default/Graphics/ScreenGameplay difficulty icons 2x6.png create mode 100644 stepmania/Themes/default/Graphics/ScreenSelectMusic difficulty icons 1x6.png diff --git a/stepmania/Themes/default/Graphics/ScreenEvaluation difficulty icons 1x6.redir b/stepmania/Themes/default/Graphics/ScreenEvaluation difficulty icons 1x6.redir new file mode 100644 index 0000000000..353f649648 --- /dev/null +++ b/stepmania/Themes/default/Graphics/ScreenEvaluation difficulty icons 1x6.redir @@ -0,0 +1 @@ +ScreenSelectMusic difficulty icons 1x6 diff --git a/stepmania/Themes/default/Graphics/ScreenGameplay difficulty icons 2x6.png b/stepmania/Themes/default/Graphics/ScreenGameplay difficulty icons 2x6.png new file mode 100644 index 0000000000000000000000000000000000000000..39525cdec759f9af27887131772fd3951ee899a8 GIT binary patch literal 28521 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 F{U1UdHT3`h literal 0 HcmV?d00001 diff --git a/stepmania/Themes/default/metrics.ini b/stepmania/Themes/default/metrics.ini index c4e530e524..ef934e5a27 100644 --- a/stepmania/Themes/default/metrics.ini +++ b/stepmania/Themes/default/metrics.ini @@ -2911,6 +2911,7 @@ EasyColor=0.9,0.9,0,1 // yellow MediumColor=1,0.1,0.1,1 // light red HardColor=0.2,1,0.2,1 // light green ChallengeColor=0.2,0.6,1.0,1 // blue +EditColor=0.8,0.8,0.8,1 // gray ExtraColor=1.0,0.0,0.0,1.0 // red ExtraColorMeter=10 @@ -3079,6 +3080,7 @@ EasyColor=0,0,0,0 MediumColor=0,0,0,0 HardColor=0,0,0,0 ChallengeColor=0,0,0,0 +EditColor=0,0,0,0 ShowStream= ShowVoltage= ShowAir= diff --git a/stepmania/src/Course.cpp b/stepmania/src/Course.cpp index 5bfea013fb..6317cf36a4 100644 --- a/stepmania/src/Course.cpp +++ b/stepmania/src/Course.cpp @@ -1036,10 +1036,10 @@ void Course::AddHighScore( StepsType st, PlayerNumber pn, MemCardData::HighScore m_MemCardDatas[st][pn].AddHighScore( hs, iPersonalIndexOut ); else iPersonalIndexOut = -1; - m_MemCardDatas[st][MEMORY_CARD_MACHINE].AddHighScore( hs, iMachineIndexOut ); + m_MemCardDatas[st][PROFILE_SLOT_MACHINE].AddHighScore( hs, iMachineIndexOut ); } -int Course::GetNumTimesPlayed( MemoryCard card ) const +int Course::GetNumTimesPlayed( ProfileSlot card ) const { int iTotalNumTimesPlayed = 0; for( unsigned i = 0; i < NUM_STEPS_TYPES; ++i ) @@ -1077,7 +1077,7 @@ void SortCoursePointerArrayByAvgDifficulty( vector &apCourses ) } -void SortCoursePointerArrayByMostPlayed( vector &arrayCoursePointers, MemoryCard card ) +void SortCoursePointerArrayByMostPlayed( vector &arrayCoursePointers, ProfileSlot card ) { for(unsigned i = 0; i < arrayCoursePointers.size(); ++i) course_sort_val[arrayCoursePointers[i]] = (float) arrayCoursePointers[i]->GetNumTimesPlayed( card ); diff --git a/stepmania/src/Course.h b/stepmania/src/Course.h index bc1e8aaf01..9632753333 100644 --- a/stepmania/src/Course.h +++ b/stepmania/src/Course.h @@ -176,21 +176,21 @@ public: return vHighScores[0]; } - } m_MemCardDatas[NUM_STEPS_TYPES][NUM_MEMORY_CARDS]; + } m_MemCardDatas[NUM_STEPS_TYPES][NUM_PROFILE_SLOTS]; void AddHighScore( StepsType st, PlayerNumber pn, MemCardData::HighScore hs, int &iPersonalIndexOut, int &iMachineIndexOut ); - MemCardData::HighScore GetTopScore( StepsType st, MemoryCard card ) + MemCardData::HighScore GetTopScore( StepsType st, ProfileSlot slot ) { - return m_MemCardDatas[st][card].GetTopScore(); + return m_MemCardDatas[st][slot].GetTopScore(); } - int GetNumTimesPlayed( StepsType st, MemoryCard card ) const + int GetNumTimesPlayed( StepsType st, ProfileSlot slot ) const { - return m_MemCardDatas[st][card].iNumTimesPlayed; + return m_MemCardDatas[st][slot].iNumTimesPlayed; } - int GetNumTimesPlayed( MemoryCard card ) const; + int GetNumTimesPlayed( ProfileSlot slot ) const; // sorting values int SortOrder_TotalDifficulty; @@ -217,7 +217,7 @@ void SortCoursePointerArrayByType( vector &apCourses ); void SortCoursePointerArrayByAvgDifficulty( vector &apCourses ); void SortCoursePointerArrayByTotalDifficulty( vector &apCourses ); void SortCoursePointerArrayByRanking( vector &apCourses ); -void SortCoursePointerArrayByMostPlayed( vector &arrayCoursePointers, MemoryCard card ); +void SortCoursePointerArrayByMostPlayed( vector &arrayCoursePointers, ProfileSlot slot ); void MoveRandomToEnd( vector &apCourses ); diff --git a/stepmania/src/DifficultyDisplay.cpp b/stepmania/src/DifficultyDisplay.cpp index 07a998746a..702ba8512e 100644 --- a/stepmania/src/DifficultyDisplay.cpp +++ b/stepmania/src/DifficultyDisplay.cpp @@ -14,7 +14,7 @@ DifficultyDisplay::DifficultyDisplay() int diff; for( diff = DIFFICULTY_BEGINNER; diff <= DIFFICULTY_CHALLENGE; ++diff ) { - m_difficulty[diff].Load( THEME->GetPathToG("DifficultyDisplay bar 5x1") ); + m_difficulty[diff].Load( THEME->GetPathToG(ssprintf("DifficultyDisplay bar %dx1",NUM_DIFFICULTIES)) ); m_difficulty[diff].SetState(diff); m_difficulty[diff].StopAnimating(); this->AddChild( &m_difficulty[diff] ); diff --git a/stepmania/src/DifficultyIcon.cpp b/stepmania/src/DifficultyIcon.cpp index b8ba2961c3..63c65dbccf 100644 --- a/stepmania/src/DifficultyIcon.cpp +++ b/stepmania/src/DifficultyIcon.cpp @@ -26,8 +26,16 @@ bool DifficultyIcon::Load( CString sPath ) { Sprite::Load( sPath ); int iStates = GetNumStates(); - if( iStates != 5 && iStates != 10 ) - HOOKS->MessageBoxOK( ssprintf("The difficulty icon graphic '%s' must have 5 or 10 frames. It has %d states.", sPath.c_str(), iStates) ); + if( iStates != NUM_DIFFICULTIES && iStates != NUM_DIFFICULTIES*2 ) + { + CString sError = ssprintf( + "The difficulty icon graphic '%s' must have %d or %d frames. It has %d states.", + sPath.c_str(), + NUM_DIFFICULTIES, + NUM_DIFFICULTIES*2, + iStates ); + HOOKS->MessageBoxOK( sError ); + } StopAnimating(); return true; } @@ -47,9 +55,9 @@ void DifficultyIcon::SetFromNotes( PlayerNumber pn, Steps* pNotes ) switch( GetNumStates() ) { - case 5: SetState( iStateNo ); break; - case 10: SetState( iStateNo*2+pn ); break; - default: SetState( 0 ); break; + case NUM_DIFFICULTIES: SetState( iStateNo ); break; + case NUM_DIFFICULTIES*2: SetState( iStateNo*2+pn ); break; + default: SetState( 0 ); break; } } } diff --git a/stepmania/src/DifficultyList.cpp b/stepmania/src/DifficultyList.cpp index d5ff91d5a2..d716439d90 100644 --- a/stepmania/src/DifficultyList.cpp +++ b/stepmania/src/DifficultyList.cpp @@ -305,7 +305,11 @@ void DifficultyList::SetFromGameState() Difficulty dc = row.m_Steps->GetDifficulty(); - CString s = SONGMAN->GetDifficultyThemeName(dc); + CString s; + if( row.m_Steps->GetDifficulty() == DIFFICULTY_EDIT ) + s = row.m_Steps->GetDescription(); + else + s = SONGMAN->GetDifficultyThemeName(dc); m_Descriptions[i].SetMaxWidth( DESCRIPTION_MAX_WIDTH ); m_Descriptions[i].SetText( s ); /* Don't mess with alpha; it might be fading on. */ diff --git a/stepmania/src/GameConstantsAndTypes.cpp b/stepmania/src/GameConstantsAndTypes.cpp index 5828c0e0e8..b7c2894dd7 100644 --- a/stepmania/src/GameConstantsAndTypes.cpp +++ b/stepmania/src/GameConstantsAndTypes.cpp @@ -41,6 +41,7 @@ CString DifficultyToString( Difficulty dc ) case DIFFICULTY_MEDIUM: return "medium"; case DIFFICULTY_HARD: return "hard"; case DIFFICULTY_CHALLENGE: return "challenge"; + case DIFFICULTY_EDIT: return "edit"; default: ASSERT(0); return ""; // invalid Difficulty } } @@ -67,6 +68,7 @@ Difficulty StringToDifficulty( CString sDC ) else if( sDC == "challenge" ) return DIFFICULTY_CHALLENGE; else if( sDC == "expert" ) return DIFFICULTY_CHALLENGE; else if( sDC == "oni" ) return DIFFICULTY_CHALLENGE; + else if( sDC == "edit" ) return DIFFICULTY_EDIT; else return DIFFICULTY_INVALID; } diff --git a/stepmania/src/GameConstantsAndTypes.h b/stepmania/src/GameConstantsAndTypes.h index f70c5ddd51..65fc2e7f9d 100644 --- a/stepmania/src/GameConstantsAndTypes.h +++ b/stepmania/src/GameConstantsAndTypes.h @@ -66,6 +66,7 @@ enum Difficulty DIFFICULTY_MEDIUM, // corresponds to Trick, Another, Standard, Normal DIFFICULTY_HARD, // corresponds to Maniac, SSR, Heavy, Crazy DIFFICULTY_CHALLENGE, // corresponds to 5th SMANIAC, MAX2 Challenge, EX Challenge + DIFFICULTY_EDIT, NUM_DIFFICULTIES, DIFFICULTY_INVALID }; @@ -200,14 +201,15 @@ enum HoldNoteScore // -// MemCard stuff +// Profile and MemCard stuff // -enum MemoryCard +enum ProfileSlot { - MEMORY_CARD_PLAYER_1, - MEMORY_CARD_PLAYER_2, - MEMORY_CARD_MACHINE, - NUM_MEMORY_CARDS + PROFILE_SLOT_PLAYER_1, + PROFILE_SLOT_PLAYER_2, + PROFILE_SLOT_MACHINE, + NUM_PROFILE_SLOTS, + PROFILE_SLOT_INVALID }; enum MemoryCardState diff --git a/stepmania/src/GameState.cpp b/stepmania/src/GameState.cpp index fa094b07eb..5256f61da2 100644 --- a/stepmania/src/GameState.cpp +++ b/stepmania/src/GameState.cpp @@ -161,11 +161,6 @@ void GameState::Reset() m_iCpuSkill[p] = 5; } - for( p=0; pSaveProfile( (PlayerNumber)p ); - PROFILEMAN->UnloadProfile( (PlayerNumber)p ); - } MEMCARDMAN->LockCards( false ); LIGHTSMAN->SetLightMode( LIGHTMODE_ATTRACT ); @@ -192,6 +187,12 @@ void CheckStageStats( const StageStats &ss, int p ) // RAGE_ASSERT_M( ss.iMeter[p] < MAX_METER+1, ssprintf("%i", ss.iMeter[p]) ); } +void GameState::PlayersFinalized() +{ + MEMCARDMAN->LockCards( true ); + SONGMAN->LoadAllFromProfiles(); +} + void GameState::EndGame() { // Update profile stats @@ -265,6 +266,14 @@ void GameState::EndGame() BOOKKEEPER->WriteToDisk(); PROFILEMAN->SaveMachineScoresToDisk(); + + for( p=0; pSaveProfile( (PlayerNumber)p ); + PROFILEMAN->UnloadProfile( (PlayerNumber)p ); + } + + SONGMAN->FreeAllLoadedFromProfiles(); } void GameState::Update( float fDelta ) @@ -1122,7 +1131,7 @@ void GameState::GetRankingFeats( PlayerNumber pn, vector &asFeatsO Steps* pSteps = vSongAndSteps[i].pSteps; // Find Machine Records - vector &vMachineHighScores = pSteps->m_MemCardDatas[MEMORY_CARD_MACHINE].vHighScores; + vector &vMachineHighScores = pSteps->m_MemCardDatas[PROFILE_SLOT_MACHINE].vHighScores; for( j=0; j &asFeatsO // Find Machine Records for( i=0; i &vHighScores = PROFILEMAN->m_CategoryDatas[MEMORY_CARD_MACHINE][nt][i].vHighScores; + vector &vHighScores = PROFILEMAN->m_CategoryDatas[PROFILE_SLOT_MACHINE][nt][i].vHighScores; for( unsigned j=0; j &asFeatsO // Find Machine Records { - vector &vHighScores = pCourse->m_MemCardDatas[nt][MEMORY_CARD_MACHINE].vHighScores; + vector &vHighScores = pCourse->m_MemCardDatas[nt][PROFILE_SLOT_MACHINE].vHighScores; for( unsigned i=0; iLockCards( true ); + GAMESTATE->PlayersFinalized(); } } diff --git a/stepmania/src/MusicWheelItem.cpp b/stepmania/src/MusicWheelItem.cpp index e7376e2528..8e58ba5f2e 100644 --- a/stepmania/src/MusicWheelItem.cpp +++ b/stepmania/src/MusicWheelItem.cpp @@ -186,7 +186,7 @@ void MusicWheelItem::LoadFromWheelItemData( WheelItemData* pWID ) ASSERT( 0 ); // invalid type } } -Steps::MemCardData::HighScore GetHighScoreForDifficulty( const Song *s, const StyleDef *st, MemoryCard card, Difficulty dc ); +Steps::MemCardData::HighScore GetHighScoreForDifficulty( const Song *s, const StyleDef *st, ProfileSlot card, Difficulty dc ); void MusicWheelItem::RefreshGrades() { @@ -207,9 +207,9 @@ void MusicWheelItem::RefreshGrades() dc = GAMESTATE->m_PreferredDifficulty[p]; Grade grade; if( PROFILEMAN->IsUsingProfile((PlayerNumber)p) ) - grade = GetHighScoreForDifficulty( data->m_pSong, GAMESTATE->GetCurrentStyleDef(), (MemoryCard)p, dc ).grade; + grade = GetHighScoreForDifficulty( data->m_pSong, GAMESTATE->GetCurrentStyleDef(), (ProfileSlot)p, dc ).grade; else - grade = GetHighScoreForDifficulty( data->m_pSong, GAMESTATE->GetCurrentStyleDef(), MEMORY_CARD_MACHINE, dc ).grade; + grade = GetHighScoreForDifficulty( data->m_pSong, GAMESTATE->GetCurrentStyleDef(), PROFILE_SLOT_MACHINE, dc ).grade; m_GradeDisplay[p].SetGrade( (PlayerNumber)p, grade ); } diff --git a/stepmania/src/NotesLoaderSM.cpp b/stepmania/src/NotesLoaderSM.cpp index 3638ac5ee7..cd543c74a3 100644 --- a/stepmania/src/NotesLoaderSM.cpp +++ b/stepmania/src/NotesLoaderSM.cpp @@ -6,6 +6,7 @@ #include "MsdFile.h" #include "RageLog.h" #include "RageUtil.h" +#include "SongManager.h" void SMLoader::LoadFromSMTokens( CString sNotesType, @@ -378,3 +379,69 @@ bool SMLoader::LoadFromDir( CString sPath, Song &out ) return LoadFromSMFile( sPath + aFileNames[0], out ); } +bool SMLoader::LoadEdit( CString sEditFilePath ) +{ + LOG->Trace( "Song::LoadEdit(%s)", sEditFilePath.c_str() ); + + MsdFile msd; + bool bResult = msd.ReadFile( sEditFilePath ); + if( !bResult ) + RageException::Throw( "Error opening file '%s'.", sEditFilePath.c_str() ); + + Song* pSong = NULL; + + for( unsigned i=0; iWarn( "The edit file '%s' has more than one #SONG tag.", sEditFilePath.c_str() ); + return false; + } + + CString& sSongFullTitle = sParams[1]; + sSongFullTitle.Replace( '\\', '/' ); + + pSong = SONGMAN->FindSong( sSongFullTitle ); + if( pSong == NULL ) + { + LOG->Warn( "The edit file '%s' required a song '%s' that isn't present.", sEditFilePath.c_str(), sSongFullTitle.c_str() ); + return false; + } + } + + else if( 0==stricmp(sValueName,"NOTES") ) + { + if( pSong == NULL ) + { + LOG->Warn( "The edit file '%s' has doesn't have a #SONG tag preceeding the first #NOTES tag.", sEditFilePath.c_str() ); + return false; + } + + Steps* pNewNotes = new Steps; + ASSERT( pNewNotes ); + pSong->m_apNotes.push_back( pNewNotes ); + + if( iNumParams < 7 ) + { + LOG->Trace( "The song file '%s' is has %d fields in a #NOTES tag, but should have at least %d.", sEditFilePath.c_str(), iNumParams, 7 ); + continue; + } + + LoadFromSMTokens( + sParams[1], sParams[2], sParams[3], sParams[4], sParams[5], sParams[6], (iNumParams>=8)?sParams[7]:"", + *pNewNotes); + } + else + LOG->Trace( "Unexpected value named '%s'", sValueName.c_str() ); + } + + return true; + +} diff --git a/stepmania/src/NotesLoaderSM.h b/stepmania/src/NotesLoaderSM.h index 44f00ac9d9..6a544090c2 100644 --- a/stepmania/src/NotesLoaderSM.h +++ b/stepmania/src/NotesLoaderSM.h @@ -33,6 +33,7 @@ public: bool LoadFromDir( CString sPath, Song &out ); static bool LoadTimingFromFile( const CString &fn, TimingData &out ); static void LoadTimingFromSMFile( const MsdFile &msd, TimingData &out ); + static bool LoadEdit( CString sEditFilePath ); }; #endif diff --git a/stepmania/src/PaneDisplay.cpp b/stepmania/src/PaneDisplay.cpp index d9c0c96b0e..6ab9c72fa3 100644 --- a/stepmania/src/PaneDisplay.cpp +++ b/stepmania/src/PaneDisplay.cpp @@ -68,13 +68,13 @@ static const PaneModes PaneMode[NUM_PANES] = // PANEMODE_COURSE }; -static MemoryCard PlayerMemCard( PlayerNumber pn ) +static ProfileSlot PlayerMemCard( PlayerNumber pn ) { switch( pn ) { - case PLAYER_1: return MEMORY_CARD_PLAYER_1; - default: ASSERT(0); - case PLAYER_2: return MEMORY_CARD_PLAYER_2; + case PLAYER_1: return PROFILE_SLOT_PLAYER_1; + case PLAYER_2: return PROFILE_SLOT_PLAYER_2; + default: ASSERT(0); return PROFILE_SLOT_MACHINE; }; } @@ -198,12 +198,12 @@ void PaneDisplay::SetContent( PaneContents c ) case SONG_MACHINE_HIGH_NAME: /* set val for color */ case SONG_MACHINE_HIGH_SCORE: - val = 100.0f * GAMESTATE->m_pCurNotes[m_PlayerNumber]->GetTopScore( MEMORY_CARD_MACHINE ).fPercentDP; + val = 100.0f * GAMESTATE->m_pCurNotes[m_PlayerNumber]->GetTopScore( PROFILE_SLOT_MACHINE ).fPercentDP; break; case SONG_MACHINE_RANK: { - const vector best = SONGMAN->GetBestSongs( MEMORY_CARD_MACHINE ); + const vector best = SONGMAN->GetBestSongs( PROFILE_SLOT_MACHINE ); val = (float) FindIndex( best.begin(), best.end(), GAMESTATE->m_pCurSong ); val += 1; break; @@ -219,16 +219,16 @@ void PaneDisplay::SetContent( PaneContents c ) case COURSE_MACHINE_HIGH_NAME: /* set val for color */ case COURSE_MACHINE_HIGH_SCORE: - val = 100.0f * GAMESTATE->m_pCurCourse->GetTopScore( GAMESTATE->GetCurrentStyleDef()->m_StepsType, MEMORY_CARD_MACHINE ).fPercentDP; + val = 100.0f * GAMESTATE->m_pCurCourse->GetTopScore( GAMESTATE->GetCurrentStyleDef()->m_StepsType, PROFILE_SLOT_MACHINE ).fPercentDP; break; case COURSE_MACHINE_NUM_PLAYS: - val = (float) GAMESTATE->m_pCurCourse->GetNumTimesPlayed( MEMORY_CARD_MACHINE ); + val = (float) GAMESTATE->m_pCurCourse->GetNumTimesPlayed( PROFILE_SLOT_MACHINE ); break; case COURSE_MACHINE_RANK: { - const vector best = SONGMAN->GetBestCourses( MEMORY_CARD_MACHINE ); + const vector best = SONGMAN->GetBestCourses( PROFILE_SLOT_MACHINE ); val = (float) FindIndex( best.begin(), best.end(), GAMESTATE->m_pCurCourse ); val += 1; } @@ -265,10 +265,10 @@ void PaneDisplay::SetContent( PaneContents c ) switch( c ) { case SONG_MACHINE_HIGH_NAME: - str = GAMESTATE->m_pCurNotes[m_PlayerNumber]->GetTopScore( MEMORY_CARD_MACHINE ).sName; + str = GAMESTATE->m_pCurNotes[m_PlayerNumber]->GetTopScore( PROFILE_SLOT_MACHINE ).sName; break; case COURSE_MACHINE_HIGH_NAME: - str = GAMESTATE->m_pCurCourse->GetTopScore( GAMESTATE->GetCurrentStyleDef()->m_StepsType, MEMORY_CARD_MACHINE ).sName; + str = GAMESTATE->m_pCurCourse->GetTopScore( GAMESTATE->GetCurrentStyleDef()->m_StepsType, PROFILE_SLOT_MACHINE ).sName; break; case SONG_MACHINE_HIGH_SCORE: diff --git a/stepmania/src/ProfileManager.cpp b/stepmania/src/ProfileManager.cpp index ec19076ae9..d07b2a9602 100644 --- a/stepmania/src/ProfileManager.cpp +++ b/stepmania/src/ProfileManager.cpp @@ -141,9 +141,9 @@ bool ProfileManager::LoadProfile( PlayerNumber pn, CString sProfileDir, bool bIs return false; } - ReadCategoryScoresFromDir( m_sProfileDir[pn], (MemoryCard)pn ); - ReadSongScoresFromDir( m_sProfileDir[pn], (MemoryCard)pn ); - ReadCourseScoresFromDir( m_sProfileDir[pn], (MemoryCard)pn ); + ReadCategoryScoresFromDir( m_sProfileDir[pn], (ProfileSlot)pn ); + ReadSongScoresFromDir( m_sProfileDir[pn], (ProfileSlot)pn ); + ReadCourseScoresFromDir( m_sProfileDir[pn], (ProfileSlot)pn ); // apply saved default modifiers if any if( m_Profile[pn].m_bUsingProfileDefaultModifiers ) @@ -245,10 +245,10 @@ bool ProfileManager::SaveProfile( PlayerNumber pn ) m_Profile[pn].SaveToIni( m_sProfileDir[pn]+PROFILE_FILE ); - SaveCategoryScoresToDir( m_sProfileDir[pn], (MemoryCard)pn ); - SaveSongScoresToDir( m_sProfileDir[pn], (MemoryCard)pn ); - SaveCourseScoresToDir( m_sProfileDir[pn], (MemoryCard)pn ); - SaveStatsWebPageToDir( m_sProfileDir[pn], (MemoryCard)pn ); + SaveCategoryScoresToDir( m_sProfileDir[pn], (ProfileSlot)pn ); + SaveSongScoresToDir( m_sProfileDir[pn], (ProfileSlot)pn ); + SaveCourseScoresToDir( m_sProfileDir[pn], (ProfileSlot)pn ); + SaveStatsWebPageToDir( m_sProfileDir[pn], (ProfileSlot)pn ); return true; } @@ -414,10 +414,10 @@ void ProfileManager::SaveMachineScoresToDisk() { m_MachineProfile.SaveToIni( MACHINE_PROFILE_DIR PROFILE_FILE ); - SaveCategoryScoresToDir( MACHINE_PROFILE_DIR, MEMORY_CARD_MACHINE ); - SaveSongScoresToDir( MACHINE_PROFILE_DIR, MEMORY_CARD_MACHINE ); - SaveCourseScoresToDir( MACHINE_PROFILE_DIR, MEMORY_CARD_MACHINE ); - SaveStatsWebPageToDir( MACHINE_PROFILE_DIR, MEMORY_CARD_MACHINE ); + SaveCategoryScoresToDir( MACHINE_PROFILE_DIR, PROFILE_SLOT_MACHINE ); + SaveSongScoresToDir( MACHINE_PROFILE_DIR, PROFILE_SLOT_MACHINE ); + SaveCourseScoresToDir( MACHINE_PROFILE_DIR, PROFILE_SLOT_MACHINE ); + SaveStatsWebPageToDir( MACHINE_PROFILE_DIR, PROFILE_SLOT_MACHINE ); } void ProfileManager::CategoryData::AddHighScore( HighScore hs, int &iIndexOut ) @@ -440,7 +440,7 @@ void ProfileManager::CategoryData::AddHighScore( HighScore hs, int &iIndexOut ) #define WARN_AND_RETURN { LOG->Warn("Error parsing file '%s' at %s:%d",fn.c_str(),__FILE__,__LINE__); return; } -void ProfileManager::ReadSongScoresFromDir( CString sDir, MemoryCard mc ) +void ProfileManager::ReadSongScoresFromDir( CString sDir, ProfileSlot slot ) { CString fn = sDir + SONG_SCORES_FILE; @@ -503,14 +503,14 @@ void ProfileManager::ReadSongScoresFromDir( CString sDir, MemoryCard mc ) WARN_AND_RETURN; if( pNotes ) - pNotes->m_MemCardDatas[mc].iNumTimesPlayed = iNumTimesPlayed; + pNotes->m_MemCardDatas[slot].iNumTimesPlayed = iNumTimesPlayed; int iNumHighScores; if( !FileRead(f, iNumHighScores) ) WARN_AND_RETURN; if( pNotes ) - pNotes->m_MemCardDatas[mc].vHighScores.resize( iNumHighScores ); + pNotes->m_MemCardDatas[slot].vHighScores.resize( iNumHighScores ); int l; for( l=0; lm_MemCardDatas[mc].vHighScores[l].sName = sName; - pNotes->m_MemCardDatas[mc].vHighScores[l].grade = grade; - pNotes->m_MemCardDatas[mc].vHighScores[l].iScore = iScore; - pNotes->m_MemCardDatas[mc].vHighScores[l].fPercentDP = fPercentDP; + pNotes->m_MemCardDatas[slot].vHighScores[l].sName = sName; + pNotes->m_MemCardDatas[slot].vHighScores[l].grade = grade; + pNotes->m_MemCardDatas[slot].vHighScores[l].iScore = iScore; + pNotes->m_MemCardDatas[slot].vHighScores[l].fPercentDP = fPercentDP; } // ignore all high scores that are 0 for( l=0; lm_MemCardDatas[mc].vHighScores[l].iScore <= 0 ) + if( pNotes && pNotes->m_MemCardDatas[slot].vHighScores[l].iScore <= 0 ) { - pNotes->m_MemCardDatas[mc].vHighScores.resize(l); + pNotes->m_MemCardDatas[slot].vHighScores.resize(l); break; } } @@ -555,7 +555,7 @@ void ProfileManager::ReadSongScoresFromDir( CString sDir, MemoryCard mc ) } -void ProfileManager::ReadCategoryScoresFromDir( CString sDir, MemoryCard mc ) +void ProfileManager::ReadCategoryScoresFromDir( CString sDir, ProfileSlot slot ) { CString fn = sDir + CATEGORY_SCORES_FILE; @@ -580,7 +580,7 @@ void ProfileManager::ReadCategoryScoresFromDir( CString sDir, MemoryCard mc ) if( !FileRead(f, iNumHighScores) ) WARN_AND_RETURN; - m_CategoryDatas[mc][st][rc].vHighScores.resize( iNumHighScores ); + m_CategoryDatas[slot][st][rc].vHighScores.resize( iNumHighScores ); for( int l=0; lm_MemCardDatas[st][mc].iNumTimesPlayed = iNumTimesPlayed; + pCourse->m_MemCardDatas[st][slot].iNumTimesPlayed = iNumTimesPlayed; int iNumHighScores; if( !FileRead(f, iNumHighScores) ) WARN_AND_RETURN; if( pCourse ) - pCourse->m_MemCardDatas[st][mc].vHighScores.resize(iNumHighScores); + pCourse->m_MemCardDatas[st][slot].vHighScores.resize(iNumHighScores); for( int l=0; lm_MemCardDatas[st][mc].vHighScores[l].sName = sName; - pCourse->m_MemCardDatas[st][mc].vHighScores[l].iScore = iScore; - pCourse->m_MemCardDatas[st][mc].vHighScores[l].fPercentDP = fPercentDP; - pCourse->m_MemCardDatas[st][mc].vHighScores[l].fSurviveTime = fSurviveTime; + pCourse->m_MemCardDatas[st][slot].vHighScores[l].sName = sName; + pCourse->m_MemCardDatas[st][slot].vHighScores[l].iScore = iScore; + pCourse->m_MemCardDatas[st][slot].vHighScores[l].fPercentDP = fPercentDP; + pCourse->m_MemCardDatas[st][slot].vHighScores[l].fSurviveTime = fSurviveTime; } } } @@ -697,9 +697,9 @@ void ProfileManager::InitMachineScoresFromDisk() ReadSM300NoteScores(); // category ranking - ReadCategoryScoresFromDir( MACHINE_PROFILE_DIR, MEMORY_CARD_MACHINE ); - ReadSongScoresFromDir( MACHINE_PROFILE_DIR, MEMORY_CARD_MACHINE ); - ReadCourseScoresFromDir( MACHINE_PROFILE_DIR, MEMORY_CARD_MACHINE ); + ReadCategoryScoresFromDir( MACHINE_PROFILE_DIR, PROFILE_SLOT_MACHINE ); + ReadSongScoresFromDir( MACHINE_PROFILE_DIR, PROFILE_SLOT_MACHINE ); + ReadCourseScoresFromDir( MACHINE_PROFILE_DIR, PROFILE_SLOT_MACHINE ); if( !m_MachineProfile.LoadFromIni(MACHINE_PROFILE_DIR PROFILE_FILE) ) { @@ -758,26 +758,26 @@ void ProfileManager::ReadSM300NoteScores() char szGradeLetters[10]; // longest possible string is "AAA" int iMaxCombo; // throw away - pNotes->m_MemCardDatas[MEMORY_CARD_MACHINE].vHighScores.resize(1); + pNotes->m_MemCardDatas[PROFILE_SLOT_MACHINE].vHighScores.resize(1); iRetVal = sscanf( value, "%d::%[^:]::%d::%d", - &pNotes->m_MemCardDatas[MEMORY_CARD_MACHINE].iNumTimesPlayed, + &pNotes->m_MemCardDatas[PROFILE_SLOT_MACHINE].iNumTimesPlayed, szGradeLetters, - &pNotes->m_MemCardDatas[MEMORY_CARD_MACHINE].vHighScores[0].iScore, + &pNotes->m_MemCardDatas[PROFILE_SLOT_MACHINE].vHighScores[0].iScore, &iMaxCombo ); if( iRetVal != 4 ) continue; - pNotes->m_MemCardDatas[MEMORY_CARD_MACHINE].vHighScores[0].grade = StringToGrade( szGradeLetters ); + pNotes->m_MemCardDatas[PROFILE_SLOT_MACHINE].vHighScores[0].grade = StringToGrade( szGradeLetters ); } } } -void ProfileManager::SaveCategoryScoresToDir( CString sDir, MemoryCard mc ) +void ProfileManager::SaveCategoryScoresToDir( CString sDir, ProfileSlot slot ) { CString fn = sDir + CATEGORY_SCORES_FILE; @@ -796,23 +796,23 @@ void ProfileManager::SaveCategoryScoresToDir( CString sDir, MemoryCard mc ) { for( int rc=0; rcm_MemCardDatas[st][mc].iNumTimesPlayed ) + if( pCourse->m_MemCardDatas[st][slot].iNumTimesPlayed ) ++NumStepsPlayed; FileWrite( f, NumStepsPlayed ); for( st=0; stm_MemCardDatas[st][mc].iNumTimesPlayed ) + if( !pCourse->m_MemCardDatas[st][slot].iNumTimesPlayed ) continue; --NumStepsPlayed; FileWrite( f, st ); - FileWrite( f, pCourse->m_MemCardDatas[st][mc].iNumTimesPlayed ); - FileWrite( f, pCourse->m_MemCardDatas[st][mc].vHighScores.size() ); - for( unsigned l=0; lm_MemCardDatas[st][mc].vHighScores.size(); l++ ) + FileWrite( f, pCourse->m_MemCardDatas[st][slot].iNumTimesPlayed ); + FileWrite( f, pCourse->m_MemCardDatas[st][slot].vHighScores.size() ); + for( unsigned l=0; lm_MemCardDatas[st][slot].vHighScores.size(); l++ ) { // tricky: wipe out "name to fill in" markers - if( IsRankingToFillIn(pCourse->m_MemCardDatas[st][mc].vHighScores[l].sName) ) - pCourse->m_MemCardDatas[st][mc].vHighScores[l].sName = ""; + if( IsRankingToFillIn(pCourse->m_MemCardDatas[st][slot].vHighScores[l].sName) ) + pCourse->m_MemCardDatas[st][slot].vHighScores[l].sName = ""; - FileWrite( f, pCourse->m_MemCardDatas[st][mc].vHighScores[l].sName ); - FileWrite( f, pCourse->m_MemCardDatas[st][mc].vHighScores[l].iScore ); - FileWrite( f, pCourse->m_MemCardDatas[st][mc].vHighScores[l].fPercentDP ); - FileWrite( f, pCourse->m_MemCardDatas[st][mc].vHighScores[l].fSurviveTime ); + FileWrite( f, pCourse->m_MemCardDatas[st][slot].vHighScores[l].sName ); + FileWrite( f, pCourse->m_MemCardDatas[st][slot].vHighScores[l].iScore ); + FileWrite( f, pCourse->m_MemCardDatas[st][slot].vHighScores[l].fPercentDP ); + FileWrite( f, pCourse->m_MemCardDatas[st][slot].vHighScores[l].fSurviveTime ); } } ASSERT( !NumStepsPlayed ); } } -void ProfileManager::SaveSongScoresToDir( CString sDir, MemoryCard mc ) +void ProfileManager::SaveSongScoresToDir( CString sDir, ProfileSlot slot ) { CString fn = sDir + SONG_SCORES_FILE; @@ -905,7 +905,7 @@ void ProfileManager::SaveSongScoresToDir( CString sDir, MemoryCard mc ) for( unsigned i=0; im_apNotes.size(); ++i ) { Steps* pNotes = pSong->m_apNotes[i]; - if( pNotes->m_MemCardDatas[mc].iNumTimesPlayed == 0 && pNotes->m_MemCardDatas[mc].vHighScores.empty() ) + if( pNotes->m_MemCardDatas[slot].iNumTimesPlayed == 0 && pNotes->m_MemCardDatas[slot].vHighScores.empty() ) continue; vNotes.push_back( pNotes ); } @@ -924,20 +924,20 @@ void ProfileManager::SaveSongScoresToDir( CString sDir, MemoryCard mc ) FileWrite( f, pNotes->m_StepsType ); FileWrite( f, pNotes->GetDifficulty() ); FileWrite( f, pNotes->GetDescription() ); - FileWrite( f, pNotes->m_MemCardDatas[mc].iNumTimesPlayed ); + FileWrite( f, pNotes->m_MemCardDatas[slot].iNumTimesPlayed ); - FileWrite( f, pNotes->m_MemCardDatas[mc].vHighScores.size() ); + FileWrite( f, pNotes->m_MemCardDatas[slot].vHighScores.size() ); - for( int l=0; l<(int)pNotes->m_MemCardDatas[mc].vHighScores.size(); l++ ) + for( int l=0; l<(int)pNotes->m_MemCardDatas[slot].vHighScores.size(); l++ ) { // tricky: wipe out "name to fill in" markers - if( IsRankingToFillIn(pNotes->m_MemCardDatas[mc].vHighScores[l].sName) ) - pNotes->m_MemCardDatas[mc].vHighScores[l].sName = ""; + if( IsRankingToFillIn(pNotes->m_MemCardDatas[slot].vHighScores[l].sName) ) + pNotes->m_MemCardDatas[slot].vHighScores[l].sName = ""; - FileWrite( f, pNotes->m_MemCardDatas[mc].vHighScores[l].sName ); - FileWrite( f, pNotes->m_MemCardDatas[mc].vHighScores[l].grade ); - FileWrite( f, pNotes->m_MemCardDatas[mc].vHighScores[l].iScore ); - FileWrite( f, pNotes->m_MemCardDatas[mc].vHighScores[l].fPercentDP ); + FileWrite( f, pNotes->m_MemCardDatas[slot].vHighScores[l].sName ); + FileWrite( f, pNotes->m_MemCardDatas[slot].vHighScores[l].grade ); + FileWrite( f, pNotes->m_MemCardDatas[slot].vHighScores[l].iScore ); + FileWrite( f, pNotes->m_MemCardDatas[slot].vHighScores[l].fPercentDP ); } } } @@ -949,7 +949,7 @@ void ProfileManager::SaveSongScoresToDir( CString sDir, MemoryCard mc ) return str; } */ -void ProfileManager::SaveStatsWebPageToDir( CString sDir, MemoryCard mc ) +void ProfileManager::SaveStatsWebPageToDir( CString sDir, ProfileSlot slot ) { CString fn = sDir + STATS_HTML_FILE; @@ -958,10 +958,10 @@ void ProfileManager::SaveStatsWebPageToDir( CString sDir, MemoryCard mc ) // Get Profile // Profile* pProfile; - if( mc == MEMORY_CARD_MACHINE ) + if( slot == PROFILE_SLOT_MACHINE ) pProfile = GetMachineProfile(); else - pProfile = GetProfile( (PlayerNumber)mc ); + pProfile = GetProfile( (PlayerNumber)slot ); ASSERT(pProfile); // @@ -1150,12 +1150,12 @@ void ProfileManager::SaveStatsWebPageToDir( CString sDir, MemoryCard mc ) { unsigned uNumToShow = min( vpSongs.size(), (unsigned)100 ); - SortSongPointerArrayByMostPlayed( vpSongs, mc ); + SortSongPointerArrayByMostPlayed( vpSongs, slot ); PRINT_DIV_START( "Songs by Popularity" ); for( unsigned i=0; iGetFullDisplayTitle(), ssprintf("#%u",(unsigned)pSong).c_str(), pSong->GetNumTimesPlayed(mc) ); + PRINT_LINE_RANK_LINK( i+1, pSong->GetFullDisplayTitle(), ssprintf("#%u",(unsigned)pSong).c_str(), pSong->GetNumTimesPlayed(slot) ); } PRINT_DIV_END; } @@ -1164,7 +1164,7 @@ void ProfileManager::SaveStatsWebPageToDir( CString sDir, MemoryCard mc ) { unsigned uNumToShow = min( vpAllSteps.size(), (unsigned)100 ); - SortStepsPointerArrayByMostPlayed( vpAllSteps, mc ); + SortStepsPointerArrayByMostPlayed( vpAllSteps, slot ); PRINT_DIV_START( "Steps by Popularity" ); for( unsigned i=0; iNotesTypeToString(pSteps->m_StepsType); s += " "; s += DifficultyToString(pSteps->GetDifficulty()); - PRINT_LINE_RANK_LINK( i+1, s, ssprintf("#%u",(unsigned)pSteps).c_str(), pSteps->GetNumTimesPlayed(mc) ); + PRINT_LINE_RANK_LINK( i+1, s, ssprintf("#%u",(unsigned)pSteps).c_str(), pSteps->GetNumTimesPlayed(slot) ); } PRINT_DIV_END; } @@ -1185,12 +1185,12 @@ void ProfileManager::SaveStatsWebPageToDir( CString sDir, MemoryCard mc ) { unsigned uNumToShow = min( vpCourses.size(), (unsigned)100 ); - SortCoursePointerArrayByMostPlayed( vpCourses, mc ); + SortCoursePointerArrayByMostPlayed( vpCourses, slot ); PRINT_DIV_START( "Courses by Popularity" ); for( unsigned i=0; im_sName, ssprintf("#%u",(unsigned)pCourse).c_str(), pCourse->GetNumTimesPlayed(mc) ); + PRINT_LINE_RANK_LINK( i+1, pCourse->m_sName, ssprintf("#%u",(unsigned)pCourse).c_str(), pCourse->GetNumTimesPlayed(slot) ); } PRINT_DIV_END; } @@ -1240,13 +1240,13 @@ void ProfileManager::SaveStatsWebPageToDir( CString sDir, MemoryCard mc ) if( pSteps ) { CString sHighScore; - if( !pSteps->m_MemCardDatas[mc].vHighScores.empty() ) + if( !pSteps->m_MemCardDatas[slot].vHighScores.empty() ) { - sHighScore += pSteps->m_MemCardDatas[mc].vHighScores[0].sName; + sHighScore += pSteps->m_MemCardDatas[slot].vHighScores[0].sName; sHighScore += "
"; - sHighScore += GradeToString( pSteps->m_MemCardDatas[mc].vHighScores[0].grade ); + sHighScore += GradeToString( pSteps->m_MemCardDatas[slot].vHighScores[0].grade ); sHighScore += "
"; - sHighScore += ssprintf("%d",pSteps->m_MemCardDatas[mc].vHighScores[0].iScore); + sHighScore += ssprintf("%d",pSteps->m_MemCardDatas[slot].vHighScores[0].iScore); } f.PutLine( ssprintf("

%s

", (unsigned)pSteps, // use pointer value as the hash @@ -1352,7 +1352,7 @@ void ProfileManager::SaveStatsWebPageToDir( CString sDir, MemoryCard mc ) pSong->GetDisplayBPM( fMinBPM, fMaxBPM ); CString sBPM = (fMinBPM==fMaxBPM) ? ssprintf("%.1f",fMinBPM) : ssprintf("%.1f - %.1f",fMinBPM,fMaxBPM); PRINT_LINE_S( "BPM", sBPM ); - PRINT_LINE_I( "NumTimesPlayed", pSong->GetNumTimesPlayed(mc) ); + PRINT_LINE_I( "NumTimesPlayed", pSong->GetNumTimesPlayed(slot) ); PRINT_LINE_S( "Credit", pSong->m_sCredit ); PRINT_LINE_S( "MusicLength", SecondsToTime(pSong->m_fMusicLengthSeconds) ); PRINT_LINE_B( "Lyrics", !pSong->m_sLyricsFile.empty() ); @@ -1371,9 +1371,9 @@ void ProfileManager::SaveStatsWebPageToDir( CString sDir, MemoryCard mc ) " - " + DifficultyToString(pSteps->GetDifficulty()); PRINT_DIV2_START_ANCHOR( /*Steps primary key*/pSteps, s.c_str() ); // use pointer value as the hash - PRINT_LINE_I( "NumTimesPlayed", pSteps->m_MemCardDatas[mc].iNumTimesPlayed ); + PRINT_LINE_I( "NumTimesPlayed", pSteps->m_MemCardDatas[slot].iNumTimesPlayed ); - vector& vHighScores = pSteps->m_MemCardDatas[mc].vHighScores; + vector& vHighScores = pSteps->m_MemCardDatas[slot].vHighScores; for( unsigned i=0; im_pCurCourse->m_MemCardDatas[st][mc].iNumTimesPlayed; } @@ -592,7 +592,7 @@ ScreenGameplay::ScreenGameplay( CString sName, bool bDemonstration ) : Screen("S if( !GAMESTATE->IsPlayerEnabled(p) ) continue; - m_DifficultyIcon[p].Load( THEME->GetPathToG("ScreenGameplay difficulty icons 2x5") ); + m_DifficultyIcon[p].Load( THEME->GetPathToG(ssprintf("ScreenGameplay difficulty icons 2x%d",NUM_DIFFICULTIES)) ); /* Position it in LoadNextSong. */ this->AddChild( &m_DifficultyIcon[p] ); @@ -873,7 +873,7 @@ void ScreenGameplay::LoadNextSong() * even if the people playing it aren't good at it.) */ if( !m_bDemonstration ) { - for( int mc = 0; mc < NUM_MEMORY_CARDS; ++mc ) + for( int mc = 0; mc < NUM_PROFILE_SLOTS; ++mc ) ++GAMESTATE->m_pCurNotes[p]->m_MemCardDatas[mc].iNumTimesPlayed; } diff --git a/stepmania/src/ScreenRanking.cpp b/stepmania/src/ScreenRanking.cpp index df8e6b61e9..06cd0f8e40 100644 --- a/stepmania/src/ScreenRanking.cpp +++ b/stepmania/src/ScreenRanking.cpp @@ -673,10 +673,10 @@ float ScreenRanking::SetPage( PageToShow pts ) { ProfileManager::CategoryData::HighScore hs; bool bRecentHighScore = false; - if( l < (int)PROFILEMAN->m_CategoryDatas[MEMORY_CARD_MACHINE][pts.nt][pts.category].vHighScores.size() ) + if( l < (int)PROFILEMAN->m_CategoryDatas[PROFILE_SLOT_MACHINE][pts.nt][pts.category].vHighScores.size() ) { - hs = PROFILEMAN->m_CategoryDatas[MEMORY_CARD_MACHINE][pts.nt][pts.category].vHighScores[l]; - CString *psName = &PROFILEMAN->m_CategoryDatas[MEMORY_CARD_MACHINE][pts.nt][pts.category].vHighScores[l].sName; + hs = PROFILEMAN->m_CategoryDatas[PROFILE_SLOT_MACHINE][pts.nt][pts.category].vHighScores[l]; + CString *psName = &PROFILEMAN->m_CategoryDatas[PROFILE_SLOT_MACHINE][pts.nt][pts.category].vHighScores[l].sName; bRecentHighScore = find( GAMESTATE->m_vpsNamesThatWereFilled.begin(), GAMESTATE->m_vpsNamesThatWereFilled.end(), psName ) != GAMESTATE->m_vpsNamesThatWereFilled.end(); } else @@ -714,10 +714,10 @@ float ScreenRanking::SetPage( PageToShow pts ) { Course::MemCardData::HighScore hs; bool bRecentHighScore = false; - if( l < (int)pts.pCourse->m_MemCardDatas[pts.nt][MEMORY_CARD_MACHINE].vHighScores.size() ) + if( l < (int)pts.pCourse->m_MemCardDatas[pts.nt][PROFILE_SLOT_MACHINE].vHighScores.size() ) { - hs = pts.pCourse->m_MemCardDatas[pts.nt][MEMORY_CARD_MACHINE].vHighScores[l]; - CString *psName = &pts.pCourse->m_MemCardDatas[pts.nt][MEMORY_CARD_MACHINE].vHighScores[l].sName; + hs = pts.pCourse->m_MemCardDatas[pts.nt][PROFILE_SLOT_MACHINE].vHighScores[l]; + CString *psName = &pts.pCourse->m_MemCardDatas[pts.nt][PROFILE_SLOT_MACHINE].vHighScores[l].sName; bRecentHighScore = find( GAMESTATE->m_vpsNamesThatWereFilled.begin(), GAMESTATE->m_vpsNamesThatWereFilled.end(), psName ) != GAMESTATE->m_vpsNamesThatWereFilled.end(); } else @@ -780,10 +780,10 @@ float ScreenRanking::SetPage( PageToShow pts ) { Steps::MemCardData::HighScore hs; bool bRecentHighScore = false; - if( !pSteps->m_MemCardDatas[MEMORY_CARD_MACHINE].vHighScores.empty() ) + if( !pSteps->m_MemCardDatas[PROFILE_SLOT_MACHINE].vHighScores.empty() ) { - hs = pSteps->m_MemCardDatas[MEMORY_CARD_MACHINE].vHighScores[0]; - const CString *psName = &pSteps->m_MemCardDatas[MEMORY_CARD_MACHINE].vHighScores[0].sName; + hs = pSteps->m_MemCardDatas[PROFILE_SLOT_MACHINE].vHighScores[0]; + const CString *psName = &pSteps->m_MemCardDatas[PROFILE_SLOT_MACHINE].vHighScores[0].sName; bRecentHighScore = find( GAMESTATE->m_vpsNamesThatWereFilled.begin(), GAMESTATE->m_vpsNamesThatWereFilled.end(), psName ) != GAMESTATE->m_vpsNamesThatWereFilled.end(); } else @@ -818,10 +818,10 @@ float ScreenRanking::SetPage( PageToShow pts ) Course::MemCardData::HighScore hs; bool bRecentHighScore = false; - if( !pCourse->m_MemCardDatas[pts.nt][MEMORY_CARD_MACHINE].vHighScores.empty() ) + if( !pCourse->m_MemCardDatas[pts.nt][PROFILE_SLOT_MACHINE].vHighScores.empty() ) { - hs = pCourse->m_MemCardDatas[pts.nt][MEMORY_CARD_MACHINE].vHighScores[0]; - const CString *psName = &pCourse->m_MemCardDatas[pts.nt][MEMORY_CARD_MACHINE].vHighScores[0].sName; + hs = pCourse->m_MemCardDatas[pts.nt][PROFILE_SLOT_MACHINE].vHighScores[0]; + const CString *psName = &pCourse->m_MemCardDatas[pts.nt][PROFILE_SLOT_MACHINE].vHighScores[0].sName; bRecentHighScore = find( GAMESTATE->m_vpsNamesThatWereFilled.begin(), GAMESTATE->m_vpsNamesThatWereFilled.end(), psName ) != GAMESTATE->m_vpsNamesThatWereFilled.end(); } else diff --git a/stepmania/src/ScreenSelectCourse.cpp b/stepmania/src/ScreenSelectCourse.cpp index 0316630a14..c76746ae64 100644 --- a/stepmania/src/ScreenSelectCourse.cpp +++ b/stepmania/src/ScreenSelectCourse.cpp @@ -416,7 +416,7 @@ void ScreenSelectCourse::AfterCourseChange() { const StepsType &st = GAMESTATE->GetCurrentStyleDef()->m_StepsType; - int mc = MEMORY_CARD_MACHINE; + int mc = PROFILE_SLOT_MACHINE; if( PROFILEMAN->IsUsingProfile( (PlayerNumber)p ) ) mc = p; diff --git a/stepmania/src/ScreenSelectMusic.cpp b/stepmania/src/ScreenSelectMusic.cpp index 06c8839023..be41c56323 100644 --- a/stepmania/src/ScreenSelectMusic.cpp +++ b/stepmania/src/ScreenSelectMusic.cpp @@ -241,7 +241,7 @@ ScreenSelectMusic::ScreenSelectMusic( CString sClassName ) : Screen( sClassName this->AddChild( &m_sprDifficultyFrame[p] ); m_DifficultyIcon[p].SetName( ssprintf("DifficultyIconP%d",p+1) ); - m_DifficultyIcon[p].Load( THEME->GetPathToG("ScreenSelectMusic difficulty icons 1x5") ); + m_DifficultyIcon[p].Load( THEME->GetPathToG(ssprintf("ScreenSelectMusic difficulty icons 1x%d",NUM_DIFFICULTIES)) ); SET_XY( m_DifficultyIcon[p] ); this->AddChild( &m_DifficultyIcon[p] ); @@ -1151,8 +1151,8 @@ void ScreenSelectMusic::AfterNotesChange( PlayerNumber pn ) } else { - if( !pNotes->m_MemCardDatas[MEMORY_CARD_MACHINE].vHighScores.empty() ) - iScore = pNotes->m_MemCardDatas[MEMORY_CARD_MACHINE].vHighScores[0].iScore; + if( !pNotes->m_MemCardDatas[PROFILE_SLOT_MACHINE].vHighScores.empty() ) + iScore = pNotes->m_MemCardDatas[PROFILE_SLOT_MACHINE].vHighScores[0].iScore; } m_textHighScore[pn].SetText( ssprintf("%*i", NUM_SCORE_DIGITS, iScore) ); } @@ -1316,7 +1316,7 @@ void ScreenSelectMusic::AfterMusicChange() TEXTUREMAN->EnableOddDimensionWarning(); FlipSpriteHorizontally(m_sprCDTitleBack); - const vector best = SONGMAN->GetBestSongs( MEMORY_CARD_MACHINE ); + const vector best = SONGMAN->GetBestSongs( PROFILE_SLOT_MACHINE ); const int index = FindIndex( best.begin(), best.end(), pSong ); if( index != -1 ) m_MachineRank.SetText( ssprintf("%i", index+1) ); @@ -1416,7 +1416,7 @@ void ScreenSelectMusic::AfterMusicChange() } } - const vector best = SONGMAN->GetBestCourses( MEMORY_CARD_MACHINE ); + const vector best = SONGMAN->GetBestCourses( PROFILE_SLOT_MACHINE ); const int index = FindCourseIndexOfSameMode( best.begin(), best.end(), pCourse ); if( index != -1 ) m_MachineRank.SetText( ssprintf("%i", index+1) ); diff --git a/stepmania/src/Song.cpp b/stepmania/src/Song.cpp index f9ff953d8f..8f858d3fab 100644 --- a/stepmania/src/Song.cpp +++ b/stepmania/src/Song.cpp @@ -72,6 +72,7 @@ void SortBackgroundChangesArray( vector &arrayBackgroundChange ////////////////////////////// Song::Song() { + m_LoadedFromProfile = PROFILE_SLOT_INVALID; m_bChangedSinceSave = false; m_fMusicSampleStartSeconds = -1; m_fMusicSampleLengthSeconds = DEFAULT_MUSIC_SAMPLE_LENGTH; @@ -1114,7 +1115,7 @@ void Song::RemoveAutoGenNotes() } -Steps::MemCardData::HighScore GetHighScoreForDifficulty( const Song *s, const StyleDef *st, MemoryCard card, Difficulty dc ) +Steps::MemCardData::HighScore GetHighScoreForDifficulty( const Song *s, const StyleDef *st, ProfileSlot card, Difficulty dc ) { // return max grade of notes in difficulty class vector aNotes; @@ -1132,7 +1133,7 @@ Steps::MemCardData::HighScore GetHighScoreForDifficulty( const Song *s, const St bool Song::IsNew() const { - return GetNumTimesPlayed(MEMORY_CARD_MACHINE) == 0; + return GetNumTimesPlayed(PROFILE_SLOT_MACHINE) == 0; } bool Song::IsEasy( StepsType nt ) const @@ -1386,7 +1387,7 @@ bool CompareSongPointersBySortValueDescending(const Song *pSong1, const Song *pS return song_sort_val[pSong1] > song_sort_val[pSong2]; } -void SortSongPointerArrayByMostPlayed( vector &arraySongPointers, MemoryCard card ) +void SortSongPointerArrayByMostPlayed( vector &arraySongPointers, ProfileSlot card ) { for(unsigned i = 0; i < arraySongPointers.size(); ++i) song_sort_val[arraySongPointers[i]] = ssprintf("%9i", arraySongPointers[i]->GetNumTimesPlayed(card)); @@ -1552,7 +1553,7 @@ bool Song::HasBackground() const {return m_sBackgroundFile != "" && IsAFile(G bool Song::HasCDTitle() const {return m_sCDTitleFile != "" && IsAFile(GetCDTitlePath()); } bool Song::HasBGChanges() const {return !m_BackgroundChanges.empty(); } -int Song::GetNumTimesPlayed( MemoryCard card ) const +int Song::GetNumTimesPlayed( ProfileSlot card ) const { int iTotalNumTimesPlayed = 0; for( unsigned i=0; iGetTopScore(MEMORY_CARD_MACHINE).grade == g ) + if( pSteps->GetTopScore(PROFILE_SLOT_MACHINE).grade == g ) iCount++; } return iCount; @@ -1699,3 +1700,12 @@ bool Song::Matches(CString sGroup, CString sSong) const return false; } +void Song::FreeAllLoadedFromProfiles() +{ + for( unsigned s=0; sWasLoadedFromProfile() ) + this->RemoveNotes( pSteps ); + } +} diff --git a/stepmania/src/SongManager.cpp b/stepmania/src/SongManager.cpp index 16f1402323..9d6e077e6a 100644 --- a/stepmania/src/SongManager.cpp +++ b/stepmania/src/SongManager.cpp @@ -31,6 +31,8 @@ #include "RageTextureManager.h" #include "Banner.h" #include "ProfileManager.h" +#include "MemoryCardManager.h" +#include "NotesLoaderSM.h" SongManager* SONGMAN = NULL; // global and accessable from anywhere in our program @@ -45,6 +47,7 @@ CachedThemeMetricC EASY_COLOR ("SongManager","EasyColor"); CachedThemeMetricC MEDIUM_COLOR ("SongManager","MediumColor"); CachedThemeMetricC HARD_COLOR ("SongManager","HardColor"); CachedThemeMetricC CHALLENGE_COLOR ("SongManager","ChallengeColor"); +CachedThemeMetricC EDIT_COLOR ("SongManager","EditColor"); CachedThemeMetricC EXTRA_COLOR ("SongManager","ExtraColor"); CachedThemeMetricI EXTRA_COLOR_METER ("SongManager","ExtraColorMeter"); @@ -66,6 +69,7 @@ static void UpdateMetrics() MEDIUM_COLOR.Refresh(); HARD_COLOR.Refresh(); CHALLENGE_COLOR.Refresh(); + EDIT_COLOR.Refresh(); EXTRA_COLOR.Refresh(); EXTRA_COLOR_METER.Refresh(); } @@ -397,7 +401,8 @@ RageColor SongManager::GetDifficultyColor( Difficulty dc ) const case DIFFICULTY_MEDIUM: return MEDIUM_COLOR; case DIFFICULTY_HARD: return HARD_COLOR; case DIFFICULTY_CHALLENGE: return CHALLENGE_COLOR; - default: ASSERT(0); return CHALLENGE_COLOR; + case DIFFICULTY_EDIT: return EDIT_COLOR; + default: ASSERT(0); return EDIT_COLOR; } } @@ -777,6 +782,8 @@ Song* SongManager::GetSongFromDir( CString sDir ) if( sDir.Right(1) != "/" ) sDir += "/"; + sDir.Replace( '\\', '/' ); + for( unsigned int i=0; iGetSongDir()) == 0 ) return m_pSongs[i]; @@ -822,7 +829,7 @@ Course* SongManager::GetCourseFromName( CString sName ) Song *SongManager::FindSong( CString sPath ) { - sPath.Replace( "\\", "/" ); + sPath.Replace( '\\', '/' ); CStringArray bits; split( sPath, "/", bits ); @@ -860,13 +867,13 @@ Course *SongManager::FindCourse( CString sName ) void SongManager::UpdateBestAndShuffled() { // update players best - for( int i = 0; i < NUM_MEMORY_CARDS; ++i ) + for( int i = 0; i < NUM_PROFILE_SLOTS; ++i ) { m_pBestSongs[i] = m_pSongs; - SortSongPointerArrayByMostPlayed( m_pBestSongs[i], (MemoryCard) i ); + SortSongPointerArrayByMostPlayed( m_pBestSongs[i], (ProfileSlot) i ); m_pBestCourses[i] = m_pCourses; - SortCoursePointerArrayByMostPlayed( m_pBestCourses[i], (MemoryCard) i ); + SortCoursePointerArrayByMostPlayed( m_pBestCourses[i], (ProfileSlot) i ); } // update shuffled @@ -899,3 +906,43 @@ void SongManager::UpdateRankingCourses() } } +void SongManager::LoadAllFromProfiles() +{ + for( int s=0; sGetProfileDir( (ProfileSlot)s ); + if( sProfileDir.empty() ) + continue; // skip + // + // Load all edits. Edits are dangling .sm files in the Edits folder + // + { + CString sEditsDir = sProfileDir+"Edits/"; + CStringArray asEditsFilesWithPath; + GetDirListing( sEditsDir+"*.sm", asEditsFilesWithPath, false, true ); + + for( unsigned i=0; iFreeAllLoadedFromProfiles(); + } +} + diff --git a/stepmania/src/SongManager.h b/stepmania/src/SongManager.h index 51eb52bf96..b5f6b7c606 100644 --- a/stepmania/src/SongManager.h +++ b/stepmania/src/SongManager.h @@ -36,6 +36,9 @@ public: void FreeSongs(); void Cleanup(); + void LoadAllFromProfiles(); // song, edits + void FreeAllLoadedFromProfiles(); + void LoadGroupSymLinks( CString sDir, CString sGroupFolder ); void InitCoursesFromDisk( LoadingWindow *ld ); @@ -61,8 +64,8 @@ public: // Lookup const vector &GetAllSongs() const { return m_pSongs; } - const vector &GetBestSongs( MemoryCard card=MEMORY_CARD_MACHINE ) const { return m_pBestSongs[MEMORY_CARD_MACHINE]; } - const vector &GetBestCourses( MemoryCard card=MEMORY_CARD_MACHINE ) const { return m_pBestCourses[MEMORY_CARD_MACHINE]; } + const vector &GetBestSongs( ProfileSlot slot=PROFILE_SLOT_MACHINE ) const { return m_pBestSongs[PROFILE_SLOT_MACHINE]; } + const vector &GetBestCourses( ProfileSlot slot=PROFILE_SLOT_MACHINE ) const { return m_pBestCourses[PROFILE_SLOT_MACHINE]; } void GetSongs( vector &AddTo, CString sGroupName, int iMaxStages = 100000 /*inf*/ ) const; void GetSongs( vector &AddTo, int iMaxStages ) const { GetSongs(AddTo,"",iMaxStages); } void GetSongs( vector &AddTo ) const { GetSongs(AddTo,"",100000 /*inf*/ ); } @@ -103,12 +106,12 @@ protected: Song *FindSong( CString sGroup, CString sSong ); vector m_pSongs; // all songs that can be played - vector m_pBestSongs[NUM_MEMORY_CARDS]; + vector m_pBestSongs[NUM_PROFILE_SLOTS]; vector m_pShuffledSongs; // used by GetRandomSong CStringArray m_sGroupNames; CStringArray m_sGroupBannerPaths; // each song group may have a banner associated with it vector m_pCourses; - vector m_pBestCourses[NUM_MEMORY_CARDS]; + vector m_pBestCourses[NUM_PROFILE_SLOTS]; vector m_pShuffledCourses; // used by GetRandomCourse }; diff --git a/stepmania/src/Steps.cpp b/stepmania/src/Steps.cpp index 23e4a722f9..80458b4e26 100644 --- a/stepmania/src/Steps.cpp +++ b/stepmania/src/Steps.cpp @@ -36,7 +36,7 @@ Steps::Steps() * until after b6 to do this. -glenn */ /* Yep, it should be STEPS_TYPE_INVALID. -Chris */ m_StepsType = STEPS_TYPE_INVALID; - m_bIsAnEdit = false; + m_LoadedFromProfile = PROFILE_SLOT_INVALID; m_Difficulty = DIFFICULTY_INVALID; m_iMeter = 0; for(int i = 0; i < NUM_RADAR_CATEGORIES; ++i) @@ -127,7 +127,7 @@ float Steps::PredictMeter() const const float DifficultyCoeffs[NUM_DIFFICULTIES] = { - -0.877f, -0.877f, 0, 0.722f, 0.722f + -0.877f, -0.877f, 0, 0.722f, 0.722f, 0 }; pMeter += DifficultyCoeffs[this->GetDifficulty()]; @@ -233,7 +233,6 @@ void Steps::DeAutogen() Decompress(); // fills in notes with sliding window transform - m_bIsAnEdit = Real()->m_bIsAnEdit; m_sDescription = Real()->m_sDescription; m_Difficulty = Real()->m_Difficulty; m_iMeter = Real()->m_iMeter; @@ -287,12 +286,6 @@ bool Steps::IsAutogen() const return parent != NULL; } -void Steps::SetIsAnEdit(bool b) -{ - DeAutogen(); - m_bIsAnEdit = b; -} - void Steps::SetDescription(CString desc) { DeAutogen(); @@ -334,7 +327,7 @@ bool CompareStepsPointersBySortValueDescending(const Steps *pSteps1, const Steps return steps_sort_val[pSteps1] > steps_sort_val[pSteps2]; } -void SortStepsPointerArrayByMostPlayed( vector &vStepsPointers, MemoryCard card ) +void SortStepsPointerArrayByMostPlayed( vector &vStepsPointers, ProfileSlot card ) { for(unsigned i = 0; i < vStepsPointers.size(); ++i) steps_sort_val[vStepsPointers[i]] = ssprintf("%9i", vStepsPointers[i]->GetNumTimesPlayed(card)); @@ -434,6 +427,6 @@ void Steps::AddHighScore( PlayerNumber pn, MemCardData::HighScore hs, int &iPers m_MemCardDatas[pn].AddHighScore( hs, iPersonalIndexOut ); else iPersonalIndexOut = -1; - m_MemCardDatas[MEMORY_CARD_MACHINE].AddHighScore( hs, iMachineIndexOut ); + m_MemCardDatas[PROFILE_SLOT_MACHINE].AddHighScore( hs, iMachineIndexOut ); } diff --git a/stepmania/src/Steps.h b/stepmania/src/Steps.h index 3e15821d3f..ab843a3abd 100644 --- a/stepmania/src/Steps.h +++ b/stepmania/src/Steps.h @@ -33,12 +33,14 @@ public: void Decompress() const; void DeAutogen(); /* If this Steps is autogenerated, make it a real Steps. */ + // Use a special value of difficulty + bool IsAnEdit() const { return m_Difficulty == DIFFICULTY_EDIT; } + bool WasLoadedFromProfile() const { return m_LoadedFromProfile != PROFILE_SLOT_INVALID; } CString GetDescription() const { return Real()->m_sDescription; } Difficulty GetDifficulty() const { return Real()->m_Difficulty; } int GetMeter() const { return Real()->m_iMeter; } const float *GetRadarValues() const { return Real()->m_fRadarValues; } - void SetIsAnEdit(bool b); void SetDescription(CString desc); void SetDifficulty(Difficulty d); void SetMeter(int meter); @@ -91,18 +93,18 @@ public: return vHighScores[0]; } - } m_MemCardDatas[NUM_MEMORY_CARDS]; + } m_MemCardDatas[NUM_PROFILE_SLOTS]; void AddHighScore( PlayerNumber pn, MemCardData::HighScore hs, int &iPersonalIndexOut, int &iMachineIndexOut ); - MemCardData::HighScore GetTopScore( MemoryCard card ) + MemCardData::HighScore GetTopScore( ProfileSlot slot ) { - return m_MemCardDatas[card].GetTopScore(); + return m_MemCardDatas[slot].GetTopScore(); } - int GetNumTimesPlayed( MemoryCard card ) + int GetNumTimesPlayed( ProfileSlot slot ) { - return m_MemCardDatas[card].iNumTimesPlayed; + return m_MemCardDatas[slot].iNumTimesPlayed; } void TidyUpData(); @@ -125,7 +127,7 @@ protected: const Steps *Real() const; /* These values are pulled from the autogen source first, if there is one. */ - bool m_bIsAnEdit; // true if this was loaded from a memory card + ProfileSlot m_LoadedFromProfile; // PROFILE_SLOT_INVALID if wasn't loaded from a profile CString m_sDescription; // Step author, edit name, or something meaningful Difficulty m_Difficulty; // difficulty classification int m_iMeter; // difficulty rating from MIN_METER to MAX_METER @@ -139,6 +141,6 @@ bool CompareNotesPointersByDifficulty(const Steps *pNotes1, const Steps *pNotes2 void SortNotesArrayByDifficulty( vector &arrayNotess ); bool CompareStepsPointersByTypeAndDifficulty(const Steps *pStep1, const Steps *pStep2); void SortStepsByTypeAndDifficulty( vector &arraySongPointers ); -void SortStepsPointerArrayByMostPlayed( vector &vStepsPointers, MemoryCard card ); +void SortStepsPointerArrayByMostPlayed( vector &vStepsPointers, ProfileSlot slot ); #endif diff --git a/stepmania/src/song.h b/stepmania/src/song.h index 1ded5acbcb..a57e43839d 100644 --- a/stepmania/src/song.h +++ b/stepmania/src/song.h @@ -94,7 +94,7 @@ public: CString m_sGroupName; - + ProfileSlot m_LoadedFromProfile; // PROFILE_SLOT_INVALID if wasn't loaded from a profile bool m_bChangedSinceSave; bool m_bIsSymLink; @@ -188,7 +188,7 @@ public: Steps* GetStepsByDescription( StepsType nt, CString sDescription, bool bIncludeAutoGen = true ) const; Steps* GetClosestNotes( StepsType nt, Difficulty dc, bool bIncludeAutoGen = true ) const; void GetEdits( vector& arrayAddTo, StepsType nt, bool bIncludeAutoGen = true ) const; - int GetNumTimesPlayed( MemoryCard card ) const; + int GetNumTimesPlayed( ProfileSlot slot ) const; bool IsNew() const; bool IsEasy( StepsType nt ) const; bool HasEdits( StepsType nt ) const; @@ -198,6 +198,9 @@ public: void AddNotes( Steps* pNotes ); // we are responsible for deleting the memory pointed to by pNotes! void RemoveNotes( const Steps* pNotes ); + + void FreeAllLoadedFromProfiles(); + bool WasLoadedFromProfile() const { return m_LoadedFromProfile != PROFILE_SLOT_INVALID; } }; CString MakeSortString( CString s ); @@ -208,7 +211,7 @@ void SortSongPointerArrayByGrade( vector &arraySongPointers ); void SortSongPointerArrayByArtist( vector &arraySongPointers ); void SortSongPointerArrayByGroupAndDifficulty( vector &arraySongPointers ); void SortSongPointerArrayByGroupAndTitle( vector &arraySongPointers ); -void SortSongPointerArrayByMostPlayed( vector &arraySongPointers, MemoryCard card ); +void SortSongPointerArrayByMostPlayed( vector &arraySongPointers, ProfileSlot slot ); void SortSongPointerArrayByMeter( vector &arraySongPointers, Difficulty dc ); CString GetSectionNameFromSongAndSort( const Song* pSong, SongSortOrder so ); void SortSongPointerArrayBySectionName( vector &arraySongPointers, SongSortOrder so );