diff --git a/stepmania/src/Course.cpp b/stepmania/src/Course.cpp index 4a9df007da..622a4ebb2d 100644 --- a/stepmania/src/Course.cpp +++ b/stepmania/src/Course.cpp @@ -29,6 +29,29 @@ Course::Course() m_bRandomize = false; m_iLives = 4; m_iExtra = 0; + + + // + // Init high scores + // + unsigned i, j, k; + for( i=0; i &apSongs ) diff --git a/stepmania/src/Course.h b/stepmania/src/Course.h index d710aa2811..e5aa4a05f4 100644 --- a/stepmania/src/Course.h +++ b/stepmania/src/Course.h @@ -12,6 +12,7 @@ */ #include "GameConstantsAndTypes.h" +#include "Style.h" // for NUM_STYLES struct PlayerOptions; struct SongOptions; @@ -20,8 +21,6 @@ struct Notes; class Course { - int m_iStages; - struct course_entry { CString description; // the Notes description CString modifiers; // set player and song options from these @@ -59,14 +58,16 @@ public: RageColor GetColor(); // Statistics + int m_iNumTimesPlayed; + struct HighScore { int iDancePoints; float fSurviveTime; CString sName; }; - HighScore m_MachineScores[NUM_DIFFICULTIES][NUM_HIGH_SCORE_LINES]; // sorted highest to lowest by iDancePoints - HighScore m_MemCardScores[NUM_DIFFICULTIES][NUM_PLAYERS]; + HighScore m_MachineScores[NUM_STYLES][NUM_DIFFICULTIES][NUM_HIGH_SCORE_LINES]; // sorted highest to lowest by iDancePoints + HighScore m_MemCardScores[NUM_STYLES][NUM_DIFFICULTIES][NUM_PLAYERS]; private: void Shuffle(); diff --git a/stepmania/src/GameConstantsAndTypes.h b/stepmania/src/GameConstantsAndTypes.h index 7fe9111a99..7b19bb74b6 100644 --- a/stepmania/src/GameConstantsAndTypes.h +++ b/stepmania/src/GameConstantsAndTypes.h @@ -172,6 +172,18 @@ inline int HoldNoteScoreToDancePoints( HoldNoteScore hns ) } } + +// +// High Score types +// +enum SongHighScoreCategory +{ + CATEGORY_A, // 1-3 meter per song avg. + CATEGORY_B, // 4-6 meter per song avg. + CATEGORY_C, // 7-9 meter per song avg. + CATEGORY_D, // 10+ meter per song avg. + NUM_HIGH_SCORE_CATEGORIES +}; const int NUM_HIGH_SCORE_LINES = 5; #endif diff --git a/stepmania/src/MusicBannerWheel.cpp b/stepmania/src/MusicBannerWheel.cpp index b7d9989289..44d4945404 100644 --- a/stepmania/src/MusicBannerWheel.cpp +++ b/stepmania/src/MusicBannerWheel.cpp @@ -338,7 +338,7 @@ void MusicBannerWheel::BannersLeft() void MusicBannerWheel::BannersRight() { StopBouncing(); - if(currentPos>=arraySongs.size()-1) + if((unsigned)currentPos>=arraySongs.size()-1) currentPos=0; else currentPos++; diff --git a/stepmania/src/MusicWheel.cpp b/stepmania/src/MusicWheel.cpp index 4f3dff1601..b437b94305 100644 --- a/stepmania/src/MusicWheel.cpp +++ b/stepmania/src/MusicWheel.cpp @@ -185,30 +185,21 @@ void WheelItemDisplay::RefreshGrades() // Refresh Grades for( int p=0; pIsPlayerEnabled( (PlayerNumber)p ) ) + if( !data->m_pSong || // this isn't a song display + !GAMESTATE->IsPlayerEnabled(p) || + !SONGMAN->IsUsingMemoryCard((PlayerNumber)p) ) { m_GradeDisplay[p].SetDiffuse( RageColor(1,1,1,0) ); continue; } - if( data->m_pSong ) // this is a song display - { - if( data->m_pSong == GAMESTATE->m_pCurSong ) - { - Notes* pNotes = GAMESTATE->m_pCurNotes[p]; - m_GradeDisplay[p].SetGrade( (PlayerNumber)p, pNotes ? pNotes->m_TopGrade : GRADE_NO_DATA ); - } - else - { - const Difficulty dc = GAMESTATE->m_PreferredDifficulty[p]; - const Grade grade = data->m_pSong->GetGradeForDifficulty( GAMESTATE->GetCurrentStyleDef(), p, dc ); - m_GradeDisplay[p].SetGrade( (PlayerNumber)p, grade ); - } - } - else // this is a section display - { - m_GradeDisplay[p].SetGrade( (PlayerNumber)p, GRADE_NO_DATA ); - } + Difficulty dc; + if( GAMESTATE->m_pCurNotes[p] ) + dc = GAMESTATE->m_pCurNotes[p]->GetDifficulty(); + else + dc = GAMESTATE->m_PreferredDifficulty[p]; + const Grade grade = data->m_pSong->GetGradeForDifficulty( GAMESTATE->GetCurrentStyleDef(), (PlayerNumber)p, dc ); + m_GradeDisplay[p].SetGrade( (PlayerNumber)p, grade ); } } diff --git a/stepmania/src/Notes.cpp b/stepmania/src/Notes.cpp index 2ce3fae122..d3aeb9736c 100644 --- a/stepmania/src/Notes.cpp +++ b/stepmania/src/Notes.cpp @@ -45,12 +45,15 @@ Notes::Notes() m_fRadarValues[i] = -1; /* unknown */ m_iNumTimesPlayed = 0; - m_iMaxCombo = 0; - m_iTopScore = 0; - m_TopGrade = GRADE_NO_DATA; notes = NULL; notes_comp = NULL; parent = NULL; + + for( int p=0; p m_MemCardScores[pn].iScore ) + { + m_MemCardScores[pn].iScore = iScore; + m_MemCardScores[pn].grade = grade; + return true; + } + return false; +} diff --git a/stepmania/src/Notes.h b/stepmania/src/Notes.h index 20ca933193..f9fecba0ca 100644 --- a/stepmania/src/Notes.h +++ b/stepmania/src/Notes.h @@ -48,12 +48,20 @@ public: void AutogenFrom( Notes *parent, NotesType ntTo ); RageColor GetColor() const; // a function of difficulty - // Statistics - Grade m_TopGrade; - int m_iTopScore; - int m_iMaxCombo; + + // High scores; int m_iNumTimesPlayed; + struct HighScore + { + Grade grade; + int iScore; + }; + HighScore m_MemCardScores[NUM_PLAYERS]; + + bool AddMemCardScore( PlayerNumber pn, Grade grade, int iScore ); // return true if new high score + + void TidyUpData(); protected: diff --git a/stepmania/src/ScreenEvaluation.cpp b/stepmania/src/ScreenEvaluation.cpp index d7dd05a2ac..380ad89a94 100644 --- a/stepmania/src/ScreenEvaluation.cpp +++ b/stepmania/src/ScreenEvaluation.cpp @@ -294,25 +294,12 @@ ScreenEvaluation::ScreenEvaluation( bool bSummary ) switch( m_ResultMode ) { case RM_ARCADE_STAGE: - Notes* pNotes = GAMESTATE->m_pCurNotes[p]; - pNotes->m_iNumTimesPlayed++; - - if( iMaxCombo[p] > pNotes->m_iMaxCombo ) - pNotes->m_iMaxCombo = iMaxCombo[p]; - - if( fScore[p] > pNotes->m_iTopScore ) - { - pNotes->m_iTopScore = (int)fScore[p]; - bNewRecord[p] = true; - } - - if( grade[p] > pNotes->m_TopGrade ) - pNotes->m_TopGrade = grade[p]; + if( SONGMAN->IsUsingMemoryCard((PlayerNumber)p) ) + bNewRecord[p] = pNotes->AddMemCardScore( (PlayerNumber)p, grade[p], (int)fScore[p] ); break; } } - SONGMAN->SaveStatisticsToDisk(); diff --git a/stepmania/src/ScreenMusicScroll.cpp b/stepmania/src/ScreenMusicScroll.cpp index 0be7eb37bc..509dc59866 100644 --- a/stepmania/src/ScreenMusicScroll.cpp +++ b/stepmania/src/ScreenMusicScroll.cpp @@ -238,6 +238,7 @@ void ScreenMusicScroll::HandleScreenMessage( const ScreenMessage SM ) m_Fade.CloseWipingRight( SM_GoToNextScreen ); break; case SM_GoToNextScreen: + SONGMAN->SaveMachineScoresToDisk(); SCREENMAN->SetNewScreen( "ScreenCompany" ); break; } diff --git a/stepmania/src/ScreenSelectMusic.cpp b/stepmania/src/ScreenSelectMusic.cpp index 0444e842f4..ea9abb6e30 100644 --- a/stepmania/src/ScreenSelectMusic.cpp +++ b/stepmania/src/ScreenSelectMusic.cpp @@ -700,8 +700,8 @@ void ScreenSelectMusic::AfterNotesChange( PlayerNumber pn ) Notes* m_pNotes = GAMESTATE->m_pCurNotes[pn]; - if( m_pNotes ) - m_HighScore[pn].SetScore( (float)m_pNotes->m_iTopScore ); + if( m_pNotes && SONGMAN->IsUsingMemoryCard(pn) ) + m_HighScore[pn].SetScore( (float)m_pNotes->m_MemCardScores[pn].iScore ); m_DifficultyIcon[pn].SetFromNotes( pn, pNotes ); if( pNotes && pNotes->IsAutogen() ) diff --git a/stepmania/src/Song.cpp b/stepmania/src/Song.cpp index b4454a01c9..faf9fdb1e0 100644 --- a/stepmania/src/Song.cpp +++ b/stepmania/src/Song.cpp @@ -897,7 +897,7 @@ void Song::AutoGen( NotesType ntTo, NotesType ntFrom ) } } -Grade Song::GetGradeForDifficulty( const StyleDef *st, int p, Difficulty dc ) const +Grade Song::GetGradeForDifficulty( const StyleDef *st, PlayerNumber pn, Difficulty dc ) const { // return max grade of notes in difficulty class vector aNotes; @@ -910,7 +910,7 @@ Grade Song::GetGradeForDifficulty( const StyleDef *st, int p, Difficulty dc ) co { const Notes* pNotes = aNotes[i]; if( pNotes->GetDifficulty() == dc ) - grade = max( grade, pNotes->m_TopGrade ); + grade = max( grade, pNotes->m_MemCardScores[pn].grade ); } return grade; } diff --git a/stepmania/src/SongManager.cpp b/stepmania/src/SongManager.cpp index 7e5680b056..79810a73e4 100644 --- a/stepmania/src/SongManager.cpp +++ b/stepmania/src/SongManager.cpp @@ -28,7 +28,9 @@ SongManager* SONGMAN = NULL; // global and accessable from anywhere in our program -const CString g_sStatisticsFileName = "statistics.ini"; +const CString CATEGORY_TOP_SCORE_FILE = "CategoryTopScores.dat"; +const CString COURSE_TOP_SCORE_FILE = "CourseTopScores.dat"; + #define NUM_GROUP_COLORS THEME->GetMetricI("SongManager","NumGroupColors") #define GROUP_COLOR( i ) THEME->GetMetricC("SongManager",ssprintf("GroupColor%d",i+1)) @@ -45,14 +47,14 @@ SongManager::SongManager( LoadingWindow *ld ) g_ExtraColor = EXTRA_COLOR; InitSongArrayFromDisk( ld ); - ReadStatisticsFromDisk(); + InitMachineScoresFromDisk(); InitCoursesFromDisk(); } SongManager::~SongManager() { - SaveStatisticsToDisk(); + SaveMachineScoresToDisk(); FreeSongArray(); } @@ -178,64 +180,6 @@ void SongManager::LoadStepManiaSongDir( CString sDir, LoadingWindow *ld ) } } -/* - -void SongManager::LoadDWISongDir( CString DWIHome ) -{ - // trim off the trailing slash if any - TrimRight( DWIHome, "/\\" ); - - // this has to be fixed, DWI doesn't put files - // in it's DWI folder. It puts them in Songs// - // so what we have to do, is go to the DWI directory (which will - // be changeable by the user so they don't have to copy everything - // over and have two copies of everything - // Find all directories in "DWIs" folder - CStringArray arrayDirs; - CStringArray MixDirs; - // now we've got the listing of the mix directories - // and we need to use THOSE directories to find our - // dwis - GetDirListing( ssprintf("%s\\Songs\\*.*", DWIHome ), MixDirs.GetString(), true ); - SortCStringArray( MixDirs ); - - for( unsigned i=0; i< MixDirs.size(); i++ ) // for each dir in /Songs/ - { - // the dir name will most likely be something like - // Dance Dance Revolution 4th Mix, etc. - CString sDirName = MixDirs[i]; - sDirName.MakeLower(); - if( sDirName == "cvs" ) // ignore the directory called "CVS" - continue; - GetDirListing( ssprintf("%s\\Songs\\%s\\*.*", DWIHome.GetString(), MixDirs[i].GetString()), arrayDirs, true); - SortCStringArray(arrayDirs, true); - - for( unsigned b = 0; b < arrayDirs.size(); b++) - { - // Find all DWIs in this directory - CStringArray arrayDWIFiles; - GetDirListing( ssprintf("%s\\Songs\\%s\\%s\\*.dwi", DWIHome.GetString(), MixDirs[i].GetString(), arrayDirs[b].GetString()), arrayDWIFiles, false); - SortCStringArray( arrayDWIFiles ); - - for( unsigned j=0; j< arrayDWIFiles.size(); j++ ) // for each DWI file - { - CString sDWIFileName = arrayDWIFiles[j]; - sDWIFileName.MakeLower(); - - // load DWIs from the sub dirs - DWILoader ld; - Song* pNewSong = new Song; - ld.LoadFromDWIFile( - ssprintf("%s\\Songs\\%s\\%s\\%s", DWIHome.GetString(), MixDirs[i].GetString(), arrayDirs[b].GetString(), sDWIFileName.GetString()), - *pNewSong); - m_pSongs.push_back( pNewSong ); - } - } - } -} -*/ - - void SongManager::FreeSongArray() { for( unsigned i=0; iTrace( "WARNING: Could not read config file '%s'.", g_sStatisticsFileName.GetString() ); - return; // load nothing - } - - - // load song statistics - const IniFile::key *pSongsKey = ini.GetKey( "Statistics" ); - if( pSongsKey ) - { - for( IniFile::key::const_iterator i = pSongsKey->begin(); i != pSongsKey->end(); ++i ) - { - CString name = i->first; - CString value = i->second; - - // Each value has the format "SongName::StepsName=TimesPlayed::TopGrade::TopScore::MaxCombo". - char szSongDir[256]; - char szNotesType[256]; - char szNotesDescription[256]; - int iRetVal; - unsigned i; - - // Parse for Song name and Notes name - iRetVal = sscanf( name.c_str(), "%[^:]::%[^:]::%[^\n]", szSongDir, szNotesType, szNotesDescription ); - if( iRetVal != 3 ) - continue; // this line doesn't match what is expected - NotesType notesType = GameManager::StringToNotesType( szNotesType ); - - // Search for the corresponding Song pointer. - Song* pSong = NULL; - for( i=0; iGetSongDir() == szSongDir ) // match! - { - pSong = m_pSongs[i]; - break; - } - } - if( pSong == NULL ) // didn't find a match - continue; // skip this entry - - - // Search for the corresponding Notes pointer. - Notes* pNotes = NULL; - for( i=0; im_apNotes.size(); i++ ) - { - if( pSong->m_apNotes[i]->m_NotesType == notesType && - pSong->m_apNotes[i]->GetDescription() == szNotesDescription ) // match! - { - pNotes = pSong->m_apNotes[i]; - break; - } - } - if( pNotes == NULL ) // didn't find a match - continue; // skip this entry - - - // Parse the Notes statistics. - char szGradeLetters[10]; // longest possible string is "AAA" - - iRetVal = sscanf( - value.c_str(), - "%d::%[^:]::%d::%d", - &pNotes->m_iNumTimesPlayed, - szGradeLetters, - &pNotes->m_iTopScore, - &pNotes->m_iMaxCombo - ); - if( iRetVal != 4 ) - continue; - - pNotes->m_TopGrade = StringToGrade( szGradeLetters ); - } - } - - // load course statistics - const IniFile::key *pCoursesKey = ini.GetKey( "Courses" ); - if( pCoursesKey ) + // Init category top scores { - for( IniFile::key::const_iterator i = pCoursesKey->begin(); i != pCoursesKey->end(); ++i ) - { - CString name = i->first; - CString value = i->second; - - // Each value has the format "CoursePath,Difficulty,Slot=DancePoints,SurviveTime,sName" - - // Parse left hand side - char szCoursePath[256]; - Difficulty difficulty; - int iSlot; - int iDancePoints; - float fSurviveTime; - char szName[256]; - - int iRetVal; - iRetVal = sscanf( name.c_str(), "%[^,],%d,%d", szCoursePath, &difficulty, &iSlot ); - if( iRetVal != 3 ) - continue; // line doesn't match what is expected - iRetVal = sscanf( value.c_str(), "%d,%f,%d[^\n]", &iDancePoints, &fSurviveTime, &szName ); - if( iRetVal != 3 ) - continue; // line doesn't match what is expected - - - // Search for the corresponding Course pointer. - Course* pCourse = SONGMAN->GetCourseFromPath( szCoursePath ); - if( pCourse == NULL ) // didn't find a match - continue; // skip this entry - -// pCourse->m_TopGrade = StringToGrade( szGradeLetters ); - } + for( int i=0; im_MachineScores[i][j][k].iDancePoints = iDancePoints; + pCourse->m_MachineScores[i][j][k].fSurviveTime = fSurviveTime; + pCourse->m_MachineScores[i][j][k].sName = szName; + } + } + } + + if( fp ) + fclose(fp); + } } -void SongManager::SaveStatisticsToDisk() +void SongManager::SaveMachineScoresToDisk() { - IniFile ini; - ini.SetPath( g_sStatisticsFileName ); - - // save song statistics - for( unsigned i=0; im_apNotes.size(); j++ ) // for each Notes - { - Notes* pNotes = pSong->m_apNotes[j]; + for( int i=0; im_TopGrade == GRADE_NO_DATA ) - continue; // skip - - // Each value has the format "SongName::NotesName=TimesPlayed::TopGrade::TopScore::MaxCombo". - - CString sName = ssprintf( "%s::%s::%s", pSong->GetSongDir().GetString(), GameManager::NotesTypeToString(pNotes->m_NotesType).GetString(), pNotes->GetDescription().GetString() ); - CString sValue = ssprintf( - "%d::%s::%d::%d", - pNotes->m_iNumTimesPlayed, - GradeToString( pNotes->m_TopGrade ).GetString(), - pNotes->m_iTopScore, - pNotes->m_iMaxCombo - ); - - ini.SetValue( "Statistics", sName, sValue ); - } + if( fp ) + fclose(fp); } - ini.WriteFile(); + // Write course top scores + { + FILE* fp = fopen( COURSE_TOP_SCORE_FILE, "w" ); + + if( fp ) + { + for( unsigned i=0; im_sPath.c_str()); + + for( int i=0; im_MachineScores[i][j][k].iDancePoints, + pCourse->m_MachineScores[i][j][k].fSurviveTime, + pCourse->m_MachineScores[i][j][k].sName.c_str()); + } + } + + if( fp ) + fclose(fp); + } } @@ -495,10 +392,12 @@ void SongManager::InitCoursesFromDisk() GetDirListing( "Courses\\*.crs", saCourseFiles ); for( unsigned i=0; i 0 ) - m_Courses.push_back( course ); + Course* pCourse = new Course; + pCourse->LoadFromCRSFile( "Courses\\" + saCourseFiles[i], m_pSongs ); + if( pCourse->GetNumStages() > 0 ) + m_pCourses.push_back( pCourse ); + else + delete pCourse; } // @@ -515,18 +414,22 @@ void SongManager::InitCoursesFromDisk() for( Difficulty dc=DIFFICULTY_EASY; dc<=DIFFICULTY_HARD; dc=Difficulty(dc+1) ) // foreach Difficulty { - Course course; - course.CreateEndlessCourseFromGroupAndDifficulty( sGroupName, dc, apGroupSongs ); + Course* pCourse = new Course; + pCourse->CreateEndlessCourseFromGroupAndDifficulty( sGroupName, dc, apGroupSongs ); - if( course.GetNumStages() > 0 ) - m_Courses.push_back( course ); + if( pCourse->GetNumStages() > 0 ) + m_pCourses.push_back( pCourse ); + else + delete pCourse; } } } -void SongManager::ReloadCourses() +void SongManager::FreeCourses() { - + for( unsigned i=0; i AddTo ) { PlayerOptions po; - for( unsigned i=0; im_bRepeat ) continue; // skip - if( m_Courses[i].m_iLives > 0 ) // use battery life meter + if( m_pCourses[i]->m_iLives > 0 ) // use battery life meter continue; - AddTo.push_back( &m_Courses[i] ); + AddTo.push_back( m_pCourses[i] ); } } void SongManager::GetOniCourses( vector AddTo ) { PlayerOptions po; - for( unsigned i=0; im_bRepeat ) continue; // skip - if( m_Courses[i].m_iLives <= 0 ) // use bar life meter + if( m_pCourses[i]->m_iLives <= 0 ) // use bar life meter continue; - AddTo.push_back( &m_Courses[i] ); + AddTo.push_back( m_pCourses[i] ); } } void SongManager::GetEndlessCourses( vector AddTo ) { - for( unsigned i=0; im_bRepeat ) + AddTo.push_back( m_pCourses[i] ); } } @@ -699,9 +602,14 @@ Song* SongManager::GetSongFromDir( CString sDir ) Course* SongManager::GetCourseFromPath( CString sPath ) { - for( unsigned int i=0; im_sPath) == 0 ) + return m_pCourses[i]; return NULL; } + +bool SongManager::IsUsingMemoryCard( PlayerNumber pn ) +{ + return true; +} diff --git a/stepmania/src/SongManager.h b/stepmania/src/SongManager.h index 65ee82b233..c506d9f011 100644 --- a/stepmania/src/SongManager.h +++ b/stepmania/src/SongManager.h @@ -32,9 +32,6 @@ public: void FreeSongArray(); void ReloadSongArray(); - void ReadStatisticsFromDisk(); - void SaveStatisticsToDisk(); - CString GetGroupBannerPath( CString sGroupName ); void GetGroupNames( CStringArray &AddTo ); @@ -43,31 +40,49 @@ public: static CString ShortenGroupName( const CString &sOrigGroupName ); - void GetSongsInGroup( const CString sGroupName, vector &AddTo ); // // Courses for Nonstop, Oni, and Endless // - vector m_Courses; + vector m_pCourses; void InitCoursesFromDisk(); - void ReloadCourses(); + void FreeCourses(); void CleanCourses(); + + + // Lookup + void GetSongsInGroup( const CString sGroupName, vector &AddTo ); + Song* GetRandomSong(); + void GetNonstopCourses( vector AddTo ); // add to if life meter type is BAR. void GetOniCourses( vector AddTo ); // add to if life meter type is BATTERY. void GetEndlessCourses( vector AddTo ); // add to if set to REPEAT. - void GetExtraStageInfo( bool bExtra2, CString sPreferredGroup, const StyleDef *s, Song*& pSongOut, Notes*& pNotesOut, PlayerOptions& po_out, SongOptions& so_out ); - Song* GetRandomSong(); - Song* GetSongFromDir( CString sDir ); Course* GetCourseFromPath( CString sPath ); // path to .crs file, or path to song group dir + + // + // High scores + // + struct HighScore + { + int iScore; + CString sName; + }; + HighScore m_MachineScores[NUM_STYLES][NUM_HIGH_SCORE_CATEGORIES][NUM_HIGH_SCORE_LINES]; + + void InitMachineScoresFromDisk(); + void SaveMachineScoresToDisk(); + + bool IsUsingMemoryCard( PlayerNumber pn ); + protected: void LoadStepManiaSongDir( CString sDir, LoadingWindow *ld ); void LoadDWISongDir( CString sDir ); diff --git a/stepmania/src/song.h b/stepmania/src/song.h index 8dfbee017b..2e12a8b110 100644 --- a/stepmania/src/song.h +++ b/stepmania/src/song.h @@ -198,7 +198,7 @@ public: int GetNumTimesPlayed() const; bool IsNew() const; bool IsEasy( NotesType nt ) const; - Grade GetGradeForDifficulty( const StyleDef *s, int p, Difficulty dc ) const; + Grade GetGradeForDifficulty( const StyleDef *s, PlayerNumber pn, Difficulty dc ) const; bool NormallyDisplayed() const; bool RouletteDisplayed() const; };