From e05738f7f7830ba99c0e4d84407b6a9b3e32e447 Mon Sep 17 00:00:00 2001 From: Chris Danford Date: Fri, 14 Feb 2003 21:42:44 +0000 Subject: [PATCH] working on course ranking scores and mem card saving --- stepmania/Themes/default/metrics.ini | 10 + stepmania/src/Course.cpp | 311 +++++++++++++------------ stepmania/src/Course.h | 68 +++--- stepmania/src/CourseContentsFrame.cpp | 36 +-- stepmania/src/GameConstantsAndTypes.h | 14 ++ stepmania/src/GameState.cpp | 9 + stepmania/src/GameState.h | 3 +- stepmania/src/MusicWheel.cpp | 12 +- stepmania/src/Notes.cpp | 24 +- stepmania/src/Notes.h | 9 +- stepmania/src/ScreenEvaluation.cpp | 48 ++-- stepmania/src/ScreenGameplay.cpp | 175 ++++++-------- stepmania/src/ScreenGameplay.h | 7 +- stepmania/src/ScreenLogo.cpp | 2 +- stepmania/src/ScreenNameEntry.cpp | 12 +- stepmania/src/ScreenRanking.cpp | 6 +- stepmania/src/ScreenSelectCourse.cpp | 19 +- stepmania/src/Song.cpp | 7 +- stepmania/src/SongManager.cpp | 315 ++++++++++++++++++++------ stepmania/src/SongManager.h | 5 + stepmania/src/song.h | 2 +- 21 files changed, 672 insertions(+), 422 deletions(-) diff --git a/stepmania/Themes/default/metrics.ini b/stepmania/Themes/default/metrics.ini index 1531077def..773498567c 100644 --- a/stepmania/Themes/default/metrics.ini +++ b/stepmania/Themes/default/metrics.ini @@ -934,3 +934,13 @@ TwoLinesArtistY=8 ThreeLinesTitleY=-10 ThreeLinesSubTitleY=0 ThreeLinesArtistY=10 + +[CourseContentDisplay] +TextBannerX=0 +TextBannerY=0 +NumberX=-118 +NumberY=0 +FootX=102 +FootY=8 +DifficultyX=120 +DifficultyY=8 diff --git a/stepmania/src/Course.cpp b/stepmania/src/Course.cpp index 9b34b44667..afdda26150 100644 --- a/stepmania/src/Course.cpp +++ b/stepmania/src/Course.cpp @@ -15,7 +15,6 @@ #include "Song.h" #include "GameManager.h" #include "SongManager.h" -#include "GameState.h" #include "RageException.h" #include "RageLog.h" #include "MsdFile.h" @@ -24,31 +23,31 @@ #include "RageUtil.h" #include "TitleSubstitution.h" + Course::Course() { + m_bIsAutoGen = false; m_bRepeat = false; m_bRandomize = false; m_iLives = -1; - m_iExtra = 0; - m_iNumTimesPlayed = 0; // // Init high scores // - unsigned i, j; - for( i=0; i &apSongs = SONGMAN->GetAllSongs(); @@ -156,21 +155,16 @@ void Course::LoadFromCRSFile( CString sPath ) else if( 0 == stricmp(sValueName, "SONG") ) { CString sSongDir = sParams[1]; - CString sNotesDescription = sParams[2]; + Difficulty dc = StringToDifficulty( sParams[2] ); CString sModifiers = sParams[3]; - if(!sSongDir.GetLength()) { + if( sSongDir.GetLength() == 0 ) { /* Err. */ LOG->Trace( "Course file '%s' has an empty #SONG. Ignored.", sPath.GetString(), sSongDir.GetString() ); continue; } - - Song *pSong = FindSong(sSongDir); - - if( pSong == NULL ) // we didn't find the Song - continue; // skip this song - AddStage( pSong, sNotesDescription, sModifiers ); + m_entries.push_back( course_entry(sSongDir, dc, sModifiers) ); } else @@ -184,8 +178,9 @@ void Course::LoadFromCRSFile( CString sPath ) } -void Course::CreateEndlessCourseFromGroupAndDifficulty( CString sGroupName, Difficulty dc, vector &apSongsInGroup ) +void Course::AutoGenEndlessFromGroupAndDifficulty( CString sGroupName, Difficulty dc, vector &apSongsInGroup ) { + m_bIsAutoGen = true; m_bRepeat = true; m_bRandomize = true; m_iLives = -1; @@ -213,162 +208,204 @@ void Course::CreateEndlessCourseFromGroupAndDifficulty( CString sGroupName, Diff for( unsigned s=0; sGetSongDir(), dc, "") ); } - Shuffle(); } -void Course::Shuffle() + +bool Course::HasDifficult() const { - /* Shuffle the list. */ - for( int i = 0; i < GetNumStages(); ++i) - swap(order[i], order[rand() % GetNumStages()]); + for( unsigned i=0; i= DIFFICULTY_HARD ) + return false; + return true; } -Notes* Course::GetNotesForStage( int iStage ) + +void Course::GetCourseInfo( + vector& vSongsOut, + vector& vNotesOut, + vector& vsModifiersOut, + NotesType nt, + bool bDifficult ) const { - Song* pSong = GetSong(iStage); - CString sDescription = entries[iStage].description; - - /* First, search for an exact description match. */ - unsigned i; - for( i=0; im_apNotes.size(); i++ ) + if( bDifficult ) + ASSERT( HasDifficult() ); + + + vector entries = m_entries; + + if( m_bRandomize ) + random_shuffle( entries.begin(), entries.end() ); + + for( unsigned i=0; im_apNotes[i]; + CString sSongDir = entries[i].songDir; - if( !GAMESTATE->GetCurrentStyleDef()->MatchesNotesType(pNotes->m_NotesType) ) - continue; + Song* pSong; + if( sSongDir.Left(strlen("PlayersBest")) == "PlayersBest" ) + { + int iNumber = atoi( sSongDir.Right(sSongDir.length()-strlen("PlayersBest")) ); + int index = iNumber - 1; + pSong = SONGMAN->GetPlayersBest( index ); + } + else if( sSongDir.Left(strlen("PlayersWorst")) == "PlayersWorst" ) + { + int iNumber = atoi( sSongDir.Right(sSongDir.length()-strlen("PlayersWorst")) ); + int index = iNumber - 1; + pSong = SONGMAN->GetPlayersWorst( index ); + } + else if( sSongDir.Right(1) == "*" ) + { + CStringArray asSongDirs; + GetDirListing( sSongDir, asSongDirs, true, true ); + if( asSongDirs.empty() ) + pSong = NULL; + else + pSong = FindSong( asSongDirs[rand()%asSongDirs.size()] ); + } + else + pSong = FindSong( sSongDir ); - if( !pNotes->GetDescription().CompareNoCase(sDescription) ) - return pNotes; - } - - /* If that failed, try to do a difficulty match. */ - Difficulty dc = StringToDifficulty(sDescription); - for( i=0; i < pSong->m_apNotes.size(); i++ ) - { - Notes* pNotes = pSong->m_apNotes[i]; - - if( !GAMESTATE->GetCurrentStyleDef()->MatchesNotesType(pNotes->m_NotesType) ) - continue; - - if(dc == pNotes->GetDifficulty()) - return pNotes; - } - - return NULL; -} - -Song *Course::GetSong( int iStage ) const -{ - return entries[iStage].song; -} - -CString Course::GetDescription( int iStage ) const -{ - return entries[iStage].description; -} - - -void Course::AddStage( Song* pSong, CString sDescription, CString sModifiers ) -{ - course_entry e; - e.song = pSong; - e.description = sDescription; - e.modifiers = sModifiers; - entries.push_back(e); - - order.push_back(order.size()); -} - -/* When bShuffled is true, returns courses in the song ordering list. */ -void Course::GetSongAndNotesForCurrentStyle( - vector& apSongsOut, - vector& apNotesOut, - CStringArray& asModifiersOut, - bool bShuffled ) -{ - for( int i=0; iHasMusic() ) + if( pSong == NULL ) continue; // skip + + + Difficulty dc = entries[i].difficulty; + if( bDifficult && dc != NUM_DIFFICULTIES-1 ) + dc = (Difficulty)(dc+1); + Notes* pNotes = pSong->GetNotes( nt, dc ); + if( pNotes == NULL ) continue; // skip - apSongsOut.push_back( pSong ); - apNotesOut.push_back( pNotes ); - asModifiersOut.push_back( sModifiers ); + + CString sModifiers = entries[i].modifiers; + + vSongsOut.push_back( pSong ); + vNotesOut.push_back( pNotes ); + vsModifiersOut.push_back( sModifiers ); } } -RageColor Course::GetColor() +bool Course::GetFirstStageInfo( + Song*& pSongOut, + Notes*& pNotesOut, + CString& sModifiersOut, + NotesType nt ) const +{ + vector vSongs; + vector vNotes; + vector vsModifiers; + + GetCourseInfo( + vSongs, + vNotes, + vsModifiers, + nt, + false ); + if( vSongs.empty() ) + return false; + + pSongOut = vSongs[0]; + pNotesOut = vNotes[0]; + sModifiersOut = vsModifiers[0]; + return true; +} + +RageColor Course::GetColor() const { // This could be made smarter - if( GetNumStages() >= 7 ) + if( m_entries.size() >= 7 ) return RageColor(1,0,0,1); // red - else if( GetNumStages() >= 4 ) + else if( m_entries.size() >= 4 ) return RageColor(1,0.5f,0,1); // orange else return RageColor(0,1,0,1); // green } -void Course::GetPlayerOptions( int iStage, PlayerOptions* pPO_out ) const +bool Course::IsMysterySong( int stage ) const { - pPO_out->FromString( entries[iStage].modifiers ); + CString sSongDir = m_entries[stage].songDir; + return sSongDir.Right(1) == "*"; } -void Course::GetSongOptions( SongOptions* pSO_out ) const +bool Course::ContainsAnyMysterySongs() const { - *pSO_out = SongOptions(); - //hack: The lifebar modifiers were not showing up (in the extra stages) - had to add it here. - if( entries.size() > 0 ) - pSO_out->FromString( entries[0].modifiers ); - pSO_out->m_LifeType = (m_iLives==-1) ? SongOptions::LIFE_BAR : SongOptions::LIFE_BATTERY; - if( m_iLives != -1 ) - pSO_out->m_iBatteryLives = m_iLives; + for( unsigned i=0; i vSongsOut; + vector vNotesOut; + vector vsModifiersOut; + GetCourseInfo( + vSongsOut, + vNotesOut, + vsModifiersOut, + NOTES_TYPE_DANCE_SINGLE, // doesn't matter + false ); // doesn't matter + + fSecondsOut = 0; + for( unsigned i=0; im_fMusicLengthSeconds; + return true; } -struct CourseScoreToInsert +struct RankingToInsert { PlayerNumber pn; int iDancePoints; float fSurviveTime; - static int CompareDescending( const CourseScoreToInsert &hs1, const CourseScoreToInsert &hs2 ) + static int CompareDescending( const RankingToInsert &hs1, const RankingToInsert &hs2 ) { if( hs1.iDancePoints > hs2.iDancePoints ) return -1; else if( hs1.iDancePoints == hs2.iDancePoints ) return 0; else return +1; } - static void SortDescending( vector& vHSout ) + static void SortDescending( vector& vHSout ) { sort( vHSout.begin(), vHSout.end(), CompareDescending ); } }; -void Course::AddMachineRecords( NotesType nt, int iDancePoints[NUM_PLAYERS], float fSurviveTime[NUM_PLAYERS], int iRankingIndexOut[NUM_PLAYERS] ) // set iNewRecordIndex = -1 if not a new record +void Course::AddScores( NotesType nt, bool bPlayerEnabled[NUM_PLAYERS], int iDancePoints[NUM_PLAYERS], float fSurviveTime[NUM_PLAYERS], int iRankingIndexOut[NUM_PLAYERS], bool bNewRecordOut[NUM_PLAYERS] ) { - vector vHS; + m_MemCardScores[MEMORY_CARD_MACHINE][nt].iNumTimesPlayed++; + + + vector vHS; for( int p=0; pIsPlayerEnabled(p) ) + if( !bPlayerEnabled[p] ) continue; // skip + - CourseScoreToInsert hs; + // Update memory card + m_MemCardScores[p][nt].iNumTimesPlayed++; + + if( iDancePoints[p] > m_MemCardScores[p][nt].iDancePoints ) + { + m_MemCardScores[p][nt].iDancePoints = iDancePoints[p]; + m_MemCardScores[p][nt].fSurviveTime = fSurviveTime[p]; + bNewRecordOut[p] = true; + } + + + // Update Ranking + RankingToInsert hs; hs.iDancePoints = iDancePoints[p]; hs.fSurviveTime = fSurviveTime[p]; hs.pn = (PlayerNumber)p; @@ -377,48 +414,36 @@ void Course::AddMachineRecords( NotesType nt, int iDancePoints[NUM_PLAYERS], flo // Sort descending before inserting. // This guarantees that a high score will not switch poitions on us when we later insert scores for the other player - CourseScoreToInsert::SortDescending( vHS ); + RankingToInsert::SortDescending( vHS ); for( unsigned i=0; i machineScores[i].iDancePoints ) + if( newHS.iDancePoints > rankingScores[i].iDancePoints ) { // We found the insert point. Shift down. for( int j=i+1; j hs.iDancePoints ) - { - hs.iDancePoints = iDancePoints; - hs.fSurviveTime = fSurviveTime; - return true; - } - return false; -} - // // Sorting stuff // static int CompareCoursePointersByDifficulty(const Course* pCourse1, const Course* pCourse2) { - return pCourse1->GetNumStages() < pCourse2->GetNumStages(); + return pCourse1->GetEstimatedNumStages() < pCourse2->GetEstimatedNumStages(); } void SortCoursePointerArrayByDifficulty( vector &apCourses ) diff --git a/stepmania/src/Course.h b/stepmania/src/Course.h index 9a02416d4b..07081a405c 100644 --- a/stepmania/src/Course.h +++ b/stepmania/src/Course.h @@ -21,63 +21,75 @@ struct Notes; class Course { struct course_entry { - CString description; // the Notes description - CString modifiers; // set player and song options from these - Song *song; + course_entry( CString dir, Difficulty dc, CString mod ) + { + songDir = dir; + difficulty = dc; + modifiers = mod; + } + + CString songDir; + Difficulty difficulty; // the Notes description + CString modifiers; // set player and song options from these }; - vector entries; - vector order; + vector m_entries; public: Course(); + bool m_bIsAutoGen; // was this created by AutoGen? CString m_sPath; CString m_sName; CString m_sBannerPath; CString m_sCDTitlePath; - bool m_bRepeat; // repeat after last song? + bool m_bRepeat; // repeat after last song? "Endless" bool m_bRandomize; // play the songs in a random order int m_iLives; // -1 means use bar life meter - int m_iExtra; // extra stage number... + int m_iExtra; // extra stage number... // not used? -Chris + + int GetEstimatedNumStages() const { return m_entries.size(); } + bool HasDifficult() const; + void GetCourseInfo( // Derefrences course_entries and returns only the playable Songs and Notes + vector& vSongsOut, + vector& vNotesOut, + vector& vsModifiersOut, + NotesType nt, + bool bDifficult ) const; // like EX's Standard/Difficult option for courses + bool GetFirstStageInfo( + Song*& pSongOut, + Notes*& pNotesOut, + CString& sModifiersOut, + NotesType nt ) const; + RageColor GetColor() const; + bool IsMysterySong( int stage ) const; + bool ContainsAnyMysterySongs() const; + bool GetTotalSeconds( float& fSecondsOut ) const; - Notes *GetNotesForStage( int iStage ); - Song *GetSong( int iStage ) const; - CString GetDescription( int iStage ) const; -// CString GetModifiers( int iStage ) const; // redundant. -Chris - void GetPlayerOptions( int iStage, PlayerOptions* pPO_out ) const; - void GetSongOptions( SongOptions* pSO_out) const; - int GetNumStages() const; void LoadFromCRSFile( CString sPath ); - void CreateEndlessCourseFromGroupAndDifficulty( CString sGroupName, Difficulty dc, vector &apSongsInGroup ); - void AddStage( Song* pSong, CString sDescription, CString sModifiers ); + void AutoGenEndlessFromGroupAndDifficulty( CString sGroupName, Difficulty dc, vector &apSongsInGroup ); - void GetSongAndNotesForCurrentStyle( vector& apSongsOut, vector& apNotesOut, CStringArray& asModifiersOut, bool bShuffled ); - RageColor GetColor(); // Statistics - int m_iNumTimesPlayed; - - struct MachineScore + struct RankingScore { int iDancePoints; float fSurviveTime; CString sName; - } m_MachineScores[NUM_NOTES_TYPES][NUM_RANKING_LINES]; // sorted highest to lowest by iDancePoints - void AddMachineRecords( NotesType nt, int iDancePoints[NUM_PLAYERS], float fSurviveTime[NUM_PLAYERS], int iLineIndexOut[NUM_PLAYERS] ); // set iNewRecordIndex = -1 if not a new record - + } m_RankingScores[NUM_NOTES_TYPES][NUM_RANKING_LINES]; // sorted highest to lowest by iDancePoints struct MemCardScore { + int iNumTimesPlayed; int iDancePoints; float fSurviveTime; - } m_MemCardScores[NUM_NOTES_TYPES][NUM_PLAYERS]; - bool AddMemCardRecord( PlayerNumber pn, NotesType nt, int iDancePoints, float fSurviveTime ); // return true if this is a new record + } m_MemCardScores[NUM_MEMORY_CARDS][NUM_NOTES_TYPES]; + + void AddScores( NotesType nt, bool bPlayerEnabled[NUM_PLAYERS], int iDancePoints[NUM_PLAYERS], float fSurviveTime[NUM_PLAYERS], int iRankingIndexOut[NUM_PLAYERS], bool bNewRecordOut[NUM_PLAYERS] ); // iNewRecordIndexOut[p] = -1 if not a new record private: - void Shuffle(); - Song *FindSong(CString sSongDir); + Song *FindSong(CString sSongDir) const; }; diff --git a/stepmania/src/CourseContentsFrame.cpp b/stepmania/src/CourseContentsFrame.cpp index 9c6c60970c..1a4b0b5326 100644 --- a/stepmania/src/CourseContentsFrame.cpp +++ b/stepmania/src/CourseContentsFrame.cpp @@ -22,19 +22,18 @@ #include "RageDisplay.h" #include "ThemeManager.h" #include "Notes.h" +#include "GameState.h" +#include "StyleDef.h" -const float TEXT_BANNER_X = 0; -const float TEXT_BANNER_Y = 0; - -const float NUMBER_X = -118; -const float NUMBER_Y = 0; - -const float FOOT_X = 102; -const float FOOT_Y = 8; - -const float DIFFICULTY_X = FOOT_X+18; -const float DIFFICULTY_Y = FOOT_Y; +#define TEXT_BANNER_X THEME->GetMetricF("CourseContentDisplay","TextBannerX") +#define TEXT_BANNER_Y THEME->GetMetricF("CourseContentDisplay","TextBannerY") +#define NUMBER_X THEME->GetMetricF("CourseContentDisplay","NumberX") +#define NUMBER_Y THEME->GetMetricF("CourseContentDisplay","NumberY") +#define FOOT_X THEME->GetMetricF("CourseContentDisplay","FootX") +#define FOOT_Y THEME->GetMetricF("CourseContentDisplay","FootY") +#define DIFFICULTY_X THEME->GetMetricF("CourseContentDisplay","DifficultyX") +#define DIFFICULTY_Y THEME->GetMetricF("CourseContentDisplay","DifficultyY") CourseContentDisplay::CourseContentDisplay() @@ -103,13 +102,16 @@ void CourseContentsFrame::SetFromCourse( Course* pCourse ) m_iNumContents = 0; - for( int i=0; iGetNumStages(), MAX_TOTAL_CONTENTS); i++ ) - { - Song* pSong = pCourse->GetSong(i); - Notes* pNotes = pCourse->GetNotesForStage(i); + vector vSongs; + vector vNotes; + vector vsModifiers; + pCourse->GetCourseInfo( vSongs, vNotes, vsModifiers, GAMESTATE->GetCurrentStyleDef()->m_NotesType, false ); - if( pNotes == NULL ) - continue; // skip + for( int i=0; iTrace( "Adding song '%s'\n", pSong->m_sMainTitle.GetString() ); m_CourseContentDisplays[m_iNumContents].Load( m_iNumContents+1, pSong, pNotes ); diff --git a/stepmania/src/GameConstantsAndTypes.h b/stepmania/src/GameConstantsAndTypes.h index e304fb34ef..ea504b898c 100644 --- a/stepmania/src/GameConstantsAndTypes.h +++ b/stepmania/src/GameConstantsAndTypes.h @@ -174,6 +174,18 @@ inline int HoldNoteScoreToDancePoints( HoldNoteScore hns ) } +// +// MemCard stuff +// +enum MemoryCard +{ + MEMORY_CARD_PLAYER_1, + MEMORY_CARD_PLAYER_2, + MEMORY_CARD_MACHINE, + NUM_MEMORY_CARDS +}; + + // // Ranking stuff // @@ -186,6 +198,8 @@ enum RankingCategory NUM_RANKING_CATEGORIES }; +const CString DEFAULT_RANKING_NAME = "STEP"; + RankingCategory AverageMeterToRankingCategory( float fAverageMeter ); const int NUM_RANKING_LINES = 5; diff --git a/stepmania/src/GameState.cpp b/stepmania/src/GameState.cpp index b04e2163f9..f687097003 100644 --- a/stepmania/src/GameState.cpp +++ b/stepmania/src/GameState.cpp @@ -199,6 +199,15 @@ RageColor GameState::GetStageColor() else return STAGE_COLOR( min(m_iCurrentStageIndex,4) ); } +int GameState::GetCourseSongIndex() +{ + int iSongIndex = 0; + for( int p=0; p &arrayWheelItemDatas Course* pCourse = apCourses[c]; // check that this course has at least one song playable in the current style - vector apSongs; - vector apNotes; - CStringArray asModifiers; - pCourse->GetSongAndNotesForCurrentStyle( apSongs, apNotes, asModifiers, false ); - - if( !apNotes.empty() ) - arrayWheelItemDatas.push_back( WheelItemData(TYPE_COURSE, NULL, "", pCourse, pCourse->GetColor()) ); + Song* pSongs; + Notes* pNotes; + CString sModifiers; + if( pCourse->GetFirstStageInfo(pSongs, pNotes, sModifiers, GAMESTATE->GetCurrentStyleDef()->m_NotesType) ) + arrayWheelItemDatas.push_back( WheelItemData(TYPE_COURSE, NULL, "", pCourse, pCourse->GetColor()) ); } } break; diff --git a/stepmania/src/Notes.cpp b/stepmania/src/Notes.cpp index c7c2dab555..9d83c52613 100644 --- a/stepmania/src/Notes.cpp +++ b/stepmania/src/Notes.cpp @@ -44,15 +44,15 @@ Notes::Notes() for(int i = 0; i < NUM_RADAR_CATEGORIES; ++i) m_fRadarValues[i] = -1; /* unknown */ - m_iNumTimesPlayed = 0; notes = NULL; notes_comp = NULL; parent = NULL; - for( int p=0; p m_MemCardScores[pn].fScore ) { m_MemCardScores[pn].fScore = fScore; m_MemCardScores[pn].grade = grade; - return true; + bNewRecordOut = true; + } + + if( fScore > m_MemCardScores[MEMORY_CARD_MACHINE].fScore ) + { + m_MemCardScores[MEMORY_CARD_MACHINE].fScore = fScore; + m_MemCardScores[MEMORY_CARD_MACHINE].grade = grade; } - return false; } diff --git a/stepmania/src/Notes.h b/stepmania/src/Notes.h index ff06d5220e..5bee5c7701 100644 --- a/stepmania/src/Notes.h +++ b/stepmania/src/Notes.h @@ -54,16 +54,15 @@ public: void CreateBlank( NotesType ntTo ); - // High scores; - int m_iNumTimesPlayed; - + // High scores struct MemCardScore { + int iNumTimesPlayed; Grade grade; float fScore; - } m_MemCardScores[NUM_PLAYERS]; + } m_MemCardScores[NUM_MEMORY_CARDS]; - bool AddMemCardRecord( PlayerNumber pn, Grade grade, float fScore ); // return true if new high score + void AddScore( PlayerNumber pn, Grade grade, float fScore, bool& bNewRecordOut ); void TidyUpData(); diff --git a/stepmania/src/ScreenEvaluation.cpp b/stepmania/src/ScreenEvaluation.cpp index 85e691386c..0188d02ae1 100644 --- a/stepmania/src/ScreenEvaluation.cpp +++ b/stepmania/src/ScreenEvaluation.cpp @@ -247,36 +247,28 @@ ScreenEvaluation::ScreenEvaluation( bool bSummary ) // // update persistent statistics // - bool bNewRecord[NUM_PLAYERS]; - memset( bNewRecord, 0, sizeof(bNewRecord) ); + bool bIsPlayerEnabled[NUM_PLAYERS]; for( p=0; pIsPlayerEnabled(p) || grade[p] == GRADE_E ) - continue; // can't be a new record + bIsPlayerEnabled[p] = GAMESTATE->IsPlayerEnabled(p); + int iRankingLine[NUM_PLAYERS] = { -1, -1 }; + bool bNewRecord[NUM_PLAYERS] = { false, false }; - switch( m_ResultMode ) - { - case RM_ARCADE_STAGE: - { - Notes* pNotes = GAMESTATE->m_pCurNotes[p]; - if( SONGMAN->IsUsingMemoryCard((PlayerNumber)p) ) - bNewRecord[p] = pNotes->AddMemCardRecord( (PlayerNumber)p, grade[p], stageStats.fScore[p] ); - } - break; - case RM_ARCADE_SUMMARY: - { - } - break; - case RM_COURSE: - { - Course* pCourse = GAMESTATE->m_pCurCourse; - NotesType nt = GAMESTATE->GetCurrentStyleDef()->m_NotesType; - pCourse->AddMemCardRecord( (PlayerNumber)p, nt, stageStats.iActualDancePoints[p], stageStats.fAliveSeconds[p] ); - } - break; - default: - ASSERT(0); - } + switch( m_ResultMode ) + { + case RM_ARCADE_STAGE: + for( int p=0; pIsPlayerEnabled(p) ) + GAMESTATE->m_pCurNotes[p]->AddScore( (PlayerNumber)p, grade[p], stageStats.fScore[p], bNewRecord[p] ); + break; + case RM_ARCADE_SUMMARY: + break; + case RM_COURSE: + NotesType nt; + nt = GAMESTATE->GetCurrentStyleDef()->m_NotesType; + GAMESTATE->m_pCurCourse->AddScores( nt, bIsPlayerEnabled, stageStats.iActualDancePoints, stageStats.fAliveSeconds, iRankingLine, bNewRecord ); + break; + default: + ASSERT(0); } m_bTryExtraStage = diff --git a/stepmania/src/ScreenGameplay.cpp b/stepmania/src/ScreenGameplay.cpp index db6f892ea0..8058fd5a5b 100644 --- a/stepmania/src/ScreenGameplay.cpp +++ b/stepmania/src/ScreenGameplay.cpp @@ -34,16 +34,16 @@ // // Defines // -#define SONGSEL_SCREEN THEME->GetMetric("ScreenGameplay","SongSelectScreen") -#define MAXCOMBO_X THEME->GetMetricF("ScreenGameplay","MAXCOMBOX") -#define MAXCOMBO_Y THEME->GetMetricF("ScreenGameplay","MAXCOMBOY") -#define MAXCOMBO_ZOOM THEME->GetMetricF("ScreenGameplay","MAXCOMBOZoom") -#define BPM_X THEME->GetMetricF("ScreenGameplay","BPMX") -#define BPM_Y THEME->GetMetricF("ScreenGameplay","BPMY") -#define BPM_ZOOM THEME->GetMetricF("ScreenGameplay","BPMZoom") -#define STAGENAME_X THEME->GetMetricF("ScreenGameplay","StagenameX") -#define STAGENAME_Y THEME->GetMetricF("ScreenGameplay","StagenameY") -#define STAGENAME_ZOOM THEME->GetMetricF("ScreenGameplay","StagenameZoom") +#define SONGSEL_SCREEN THEME->GetMetric("ScreenGameplay","SongSelectScreen") +#define MAXCOMBO_X THEME->GetMetricF("ScreenGameplay","MAXCOMBOX") // Please follow the capitalization conventions used everywhere else. This is case sensitive. -Chris +#define MAXCOMBO_Y THEME->GetMetricF("ScreenGameplay","MAXCOMBOY") +#define MAXCOMBO_ZOOM THEME->GetMetricF("ScreenGameplay","MAXCOMBOZoom") +#define BPM_X THEME->GetMetricF("ScreenGameplay","BPMX") +#define BPM_Y THEME->GetMetricF("ScreenGameplay","BPMY") +#define BPM_ZOOM THEME->GetMetricF("ScreenGameplay","BPMZoom") +#define STAGENAME_X THEME->GetMetricF("ScreenGameplay","StagenameX") +#define STAGENAME_Y THEME->GetMetricF("ScreenGameplay","StagenameY") +#define STAGENAME_ZOOM THEME->GetMetricF("ScreenGameplay","StagenameZoom") #define LIFE_FRAME_X THEME->GetMetricF("ScreenGameplay","LifeFrameX") #define LIFE_FRAME_Y( e ) THEME->GetMetricF("ScreenGameplay",ssprintf("LifeFrame%sY",e?"Extra":"")) #define SCORE_FRAME_X THEME->GetMetricF("ScreenGameplay","ScoreFrameX") @@ -106,64 +106,64 @@ ScreenGameplay::ScreenGameplay( bool bDemonstration ) if( GAMESTATE->m_pCurSong == NULL && GAMESTATE->m_pCurCourse == NULL ) return; // ScreenDemonstration will move us to the next scren. We just need to survive for one update without crashing. - int p; - - for( p=0; pStopMusic(); - GAMESTATE->m_CurStageStats = StageStats(); // clear values - + // Fill in m_CurStageStats - for( p=0; pm_PlayMode ) { - if( !GAMESTATE->IsPlayerEnabled(p) ) - continue; // skip - - NoteData notedata; - switch( GAMESTATE->m_PlayMode ) + case PLAY_MODE_ARCADE: { - case PLAY_MODE_ARCADE: GAMESTATE->m_CurStageStats.pSong = GAMESTATE->m_pCurSong; - GAMESTATE->m_CurStageStats.iMeter[p] = GAMESTATE->m_pCurNotes[p]->GetMeter(); - - GAMESTATE->m_pCurNotes[p]->GetNoteData( ¬edata ); - GAMESTATE->m_CurStageStats.iPossibleDancePoints[p] = notedata.GetPossibleDancePoints(); - break; - case PLAY_MODE_NONSTOP: - case PLAY_MODE_ONI: - case PLAY_MODE_ENDLESS: + for( int p=0; pm_CurStageStats.pSong = NULL; - GAMESTATE->m_CurStageStats.iMeter[p] = 0; - - GAMESTATE->m_CurStageStats.iPossibleDancePoints[p] = 0; - - Course* pCourse = GAMESTATE->m_pCurCourse; - vector apSongs; - vector apNotes; - CStringArray asModifiers; - pCourse->GetSongAndNotesForCurrentStyle( apSongs, apNotes, asModifiers, true ); - - for( unsigned i=0; im_CurStageStats.iMeter[p] += apNotes[i]->GetMeter(); - apNotes[i]->GetNoteData( ¬edata ); - int iPossibleDancePoints = notedata.GetPossibleDancePoints(); - GAMESTATE->m_CurStageStats.iPossibleDancePoints[p] += iPossibleDancePoints; - } + if( !GAMESTATE->IsPlayerEnabled(p) ) + continue; // skip + GAMESTATE->m_CurStageStats.iMeter[p] = GAMESTATE->m_pCurNotes[p]->GetMeter(); + GAMESTATE->m_pCurNotes[p]->GetNoteData( ¬edata ); + GAMESTATE->m_CurStageStats.iPossibleDancePoints[p] = notedata.GetPossibleDancePoints(); } - break; - default: - ASSERT(0); } + break; + case PLAY_MODE_NONSTOP: + case PLAY_MODE_ONI: + case PLAY_MODE_ENDLESS: + { + Course* pCourse = GAMESTATE->m_pCurCourse; + pCourse->GetCourseInfo( m_apCourseSongs, m_apCourseNotes, m_asCourseModifiers, GAMESTATE->GetCurrentStyleDef()->m_NotesType, false ); + + int iTotalMeter = 0; + int iTotalPossibleDancePoints = 0; + for( unsigned i=0; iGetMeter(); + m_apCourseNotes[i]->GetNoteData( ¬edata ); + iTotalPossibleDancePoints += notedata.GetPossibleDancePoints(); + } + + GAMESTATE->m_CurStageStats.pSong = NULL; + for( int p=0; pIsPlayerEnabled(p) ) + continue; // skip + GAMESTATE->m_CurStageStats.iMeter[p] = iTotalMeter; + GAMESTATE->m_CurStageStats.iPossibleDancePoints[p] = iTotalPossibleDancePoints; + } + } + break; + default: + ASSERT(0); } @@ -187,7 +187,7 @@ ScreenGameplay::ScreenGameplay( bool bDemonstration ) this->AddChild( &m_Background ); - for( p=0; pIsPlayerEnabled(PlayerNumber(p)) ) continue; @@ -495,23 +495,10 @@ bool ScreenGameplay::IsLastSong() case PLAY_MODE_ENDLESS: { Course* pCourse = GAMESTATE->m_pCurCourse; - if( pCourse->m_bRepeat ) return false; - - vector apSongs; - vector apNotes; - CStringArray asModifiers; - pCourse->GetSongAndNotesForCurrentStyle( apSongs, apNotes, asModifiers, true ); - - /* XXX: Should we really be using iSongsPassed to figure out what song we're - * on? Wouldn't m_iCurrentStageIndex be better for that? -glenn */ - int iPlaySongIndex = 0; - for( int p=0; pIsPlayerEnabled(p) ) - iPlaySongIndex = max( iPlaySongIndex, GAMESTATE->m_CurStageStats.iSongsPassed[p] ); - - return unsigned(iPlaySongIndex) >= apSongs.size(); // there are no more songs left + else + return GAMESTATE->GetCourseSongIndex() == (int)m_apCourseSongs.size(); } break; default: @@ -540,31 +527,18 @@ void ScreenGameplay::LoadNextSong() if( GAMESTATE->m_CurStageStats.iSongsPassed[p] == 0 ) GAMESTATE->m_SelectedOptions[p] = GAMESTATE->m_PlayerOptions[p]; } - Course* pCourse = GAMESTATE->m_pCurCourse; - vector apSongs; - vector apNotes; - CStringArray asModifiers; + int iPlaySongIndex = GAMESTATE->GetCourseSongIndex(); + iPlaySongIndex %= m_apCourseSongs.size(); + GAMESTATE->m_pCurSong = m_apCourseSongs[iPlaySongIndex]; - pCourse->GetSongAndNotesForCurrentStyle( apSongs, apNotes, asModifiers, true ); - - int iPlaySongIndex = 0; - for( p=0; pIsPlayerEnabled(p) ) - iPlaySongIndex = max( iPlaySongIndex, GAMESTATE->m_CurStageStats.iSongsPassed[p] ); - iPlaySongIndex %= apSongs.size(); - - GAMESTATE->m_pCurSong = apSongs[iPlaySongIndex]; for( p=0; pm_pCurNotes[p] = apNotes[iPlaySongIndex]; - // Wipe the options used on the last song (including course specified ones) - GAMESTATE->m_PlayerOptions[p].Init(); - // Now restore the player's originally selected options. + GAMESTATE->m_pCurNotes[p] = m_apCourseNotes[iPlaySongIndex]; + // Restore the player's originally selected options. GAMESTATE->m_PlayerOptions[p] = GAMESTATE->m_SelectedOptions[p]; - if( asModifiers[iPlaySongIndex] != "" ) // some modifiers specified - GAMESTATE->m_PlayerOptions[p].FromString( asModifiers[iPlaySongIndex] ); // put them into effect + // Put courses options into effect. + GAMESTATE->m_PlayerOptions[p].FromString( m_asCourseModifiers[iPlaySongIndex] ); } - } break; default: @@ -1070,7 +1044,7 @@ void SaveChanges() * playing out of a course, and use that here, so these things wouldn't need to * special case play modes. Need to make sure m_pCurCourse gets erased * correctly, though. -glenn */ - /* That's a very clever idea! I will look into this soon. -Chris */ + /* That's a very clever idea! I should look into this. -Chris */ switch( GAMESTATE->m_PlayMode ) { case PLAY_MODE_ARCADE: @@ -1080,11 +1054,9 @@ void SaveChanges() case PLAY_MODE_ONI: case PLAY_MODE_ENDLESS: { - for( int i=0; im_pCurCourse->GetNumStages(); i++ ) - { - Song* pSong = GAMESTATE->m_pCurCourse->GetSong(i); - pSong->Save(); - } + // FIXME + //for( int i=0; iSave(); } break; default: @@ -1105,11 +1077,12 @@ void DontSaveChanges() case PLAY_MODE_ONI: case PLAY_MODE_ENDLESS: { - for( int i=0; im_pCurCourse->GetNumStages(); i++ ) - { - Song* pSong = GAMESTATE->m_pCurCourse->GetSong(i); - ld.LoadFromSMFile( GAMESTATE->m_pCurSong->GetCacheFilePath(), *pSong ); - } + // FIXME +// for( int i=0; im_pCurCourse->GetNumStages(); i++ ) +// { +// Song* pSong = GAMESTATE->m_pCurCourse->GetSong(i); +// ld.LoadFromSMFile( GAMESTATE->m_pCurSong->GetCacheFilePath(), *pSong ); +// } } break; default: diff --git a/stepmania/src/ScreenGameplay.h b/stepmania/src/ScreenGameplay.h index f9f4ea06a5..f5ca28b0d8 100644 --- a/stepmania/src/ScreenGameplay.h +++ b/stepmania/src/ScreenGameplay.h @@ -77,8 +77,11 @@ protected: STATE_DANCING, STATE_OUTRO, // not allowed to press Back NUM_DANCING_STATES - }; - DancingState m_DancingState; + } m_DancingState; + vector m_apCourseSongs; // used only in a GameModes with courses + vector m_apCourseNotes; // used only in a GameModes with courses + CStringArray m_asCourseModifiers; // used only in a GameModes with courses + bool m_bChangedOffsetOrBPM; float m_fTimeLeftBeforeDancingComment; // this counter is only running while STATE_DANCING diff --git a/stepmania/src/ScreenLogo.cpp b/stepmania/src/ScreenLogo.cpp index 1a6fed7008..f0e2a0245d 100644 --- a/stepmania/src/ScreenLogo.cpp +++ b/stepmania/src/ScreenLogo.cpp @@ -49,7 +49,7 @@ ScreenLogo::ScreenLogo() : ScreenAttract("ScreenLogo","logo") m_textSongs.LoadFromFont( THEME->GetPathTo("Fonts","normal") ); m_textSongs.SetHorizAlign( Actor::align_left ); - m_textSongs.SetText( ssprintf("%d songs in %d groups", SONGMAN->GetNumSongs(), SONGMAN->GetNumGroups()) ); + m_textSongs.SetText( ssprintf("%d songs in %d groups, %d courses", SONGMAN->GetNumSongs(), SONGMAN->GetNumGroups(), SONGMAN->GetNumCourses()) ); m_textSongs.SetDiffuse( RageColor(0.6f,0.6f,0.6f,1) ); // light gray m_textSongs.SetXY( SONGS_X, SONGS_Y ); m_textSongs.SetZoom( 0.5f ); diff --git a/stepmania/src/ScreenNameEntry.cpp b/stepmania/src/ScreenNameEntry.cpp index a2374575a4..f440bcd9ca 100644 --- a/stepmania/src/ScreenNameEntry.cpp +++ b/stepmania/src/ScreenNameEntry.cpp @@ -163,17 +163,21 @@ ScreenNameEntry::ScreenNameEntry() Course* pCourse = GAMESTATE->m_pCurCourse; + bool bPlayerIsEnabled[NUM_PLAYERS]; int iDancePoints[NUM_PLAYERS]; float fAliveSeconds[NUM_PLAYERS]; - int iRankingIndex[NUM_PLAYERS]; for( int p=0; pIsPlayerEnabled(p); iDancePoints[p] = stageStats.iActualDancePoints[p]; fAliveSeconds[p] = stageStats.fAliveSeconds[p]; } + int iRankingIndex[NUM_PLAYERS]; + bool bNewRecord[NUM_PLAYERS]; + NotesType nt = GAMESTATE->GetCurrentStyleDef()->m_NotesType; - pCourse->AddMachineRecords( nt, iDancePoints, fAliveSeconds, iRankingIndex ); + pCourse->AddScores( nt, bPlayerIsEnabled, iDancePoints, fAliveSeconds, iRankingIndex, bNewRecord ); GAMESTATE->m_LastRankingNotesType = nt; GAMESTATE->m_pLastPlayedCourse = pCourse; @@ -409,7 +413,7 @@ void ScreenNameEntry::MenuStart( PlayerNumber pn ) TrimLeft( m_sSelectedName[pn], " " ); if( m_sSelectedName[pn] == "" ) - m_sSelectedName[pn] = "STEP"; + m_sSelectedName[pn] = DEFAULT_RANKING_NAME; switch( GAMESTATE->m_PlayMode ) @@ -420,7 +424,7 @@ void ScreenNameEntry::MenuStart( PlayerNumber pn ) case PLAY_MODE_NONSTOP: case PLAY_MODE_ONI: case PLAY_MODE_ENDLESS: - GAMESTATE->m_pLastPlayedCourse->m_MachineScores[GAMESTATE->m_LastRankingNotesType][GAMESTATE->m_iLastRankingIndex[pn]].sName = m_sSelectedName[pn]; + GAMESTATE->m_pLastPlayedCourse->m_RankingScores[GAMESTATE->m_LastRankingNotesType][GAMESTATE->m_iLastRankingIndex[pn]].sName = m_sSelectedName[pn]; break; default: ASSERT(0); diff --git a/stepmania/src/ScreenRanking.cpp b/stepmania/src/ScreenRanking.cpp index ea5470440d..4b5d7b9336 100644 --- a/stepmania/src/ScreenRanking.cpp +++ b/stepmania/src/ScreenRanking.cpp @@ -236,9 +236,9 @@ void ScreenRanking::SetPage( PageToShow pts ) for( int l=0; lm_MachineScores[pts.nt][l].sName; - int iDancePoints = pts.pCourse->m_MachineScores[pts.nt][l].iDancePoints; - float fSurviveTime = pts.pCourse->m_MachineScores[pts.nt][l].fSurviveTime; + CString sName = pts.pCourse->m_RankingScores[pts.nt][l].sName; + int iDancePoints = pts.pCourse->m_RankingScores[pts.nt][l].iDancePoints; + float fSurviveTime = pts.pCourse->m_RankingScores[pts.nt][l].fSurviveTime; m_textNames[l].SetText( sName ); m_textScores[l].SetText( "" ); m_textPoints[l].SetText( ssprintf("%04d",iDancePoints) ); diff --git a/stepmania/src/ScreenSelectCourse.cpp b/stepmania/src/ScreenSelectCourse.cpp index 968236a054..6bf49349fa 100644 --- a/stepmania/src/ScreenSelectCourse.cpp +++ b/stepmania/src/ScreenSelectCourse.cpp @@ -299,9 +299,13 @@ void ScreenSelectCourse::MenuStart( PlayerNumber pn ) Course* pCourse = m_MusicWheel.GetSelectedCourse(); GAMESTATE->m_pCurCourse = pCourse; + Song* pSong; + Notes* pNotes; + CString sModifiers; + pCourse->GetFirstStageInfo( pSong, pNotes, sModifiers, GAMESTATE->GetCurrentStyleDef()->m_NotesType ); for( int p=0; pGetPlayerOptions( 0, &GAMESTATE->m_PlayerOptions[p] ); - pCourse->GetSongOptions( &GAMESTATE->m_SongOptions ); + GAMESTATE->m_PlayerOptions[p].FromString( sModifiers ); + GAMESTATE->m_SongOptions.FromString( sModifiers ); m_Menu.StopTimer(); @@ -328,11 +332,12 @@ void ScreenSelectCourse::AfterCourseChange() { Course* pCourse = m_MusicWheel.GetSelectedCourse(); - m_textNumSongs.SetText( ssprintf("%d", pCourse->GetNumStages()) ); - float fTotalSeconds = 0; - for( int i=0; iGetNumStages(); i++ ) - fTotalSeconds += pCourse->GetSong(i)->m_fMusicLengthSeconds; - m_textTime.SetText( SecondsToTime(fTotalSeconds) ); + m_textNumSongs.SetText( ssprintf("%d", pCourse->GetEstimatedNumStages()) ); + float fTotalSeconds; + if( pCourse->GetTotalSeconds(fTotalSeconds) ) + m_textTime.SetText( SecondsToTime(fTotalSeconds) ); + else + m_textTime.SetText( "??:??:??" ); m_Banner.LoadFromCourse( pCourse ); diff --git a/stepmania/src/Song.cpp b/stepmania/src/Song.cpp index 9d38035af5..45b2d0643e 100644 --- a/stepmania/src/Song.cpp +++ b/stepmania/src/Song.cpp @@ -635,12 +635,13 @@ void Song::GetNotes( vector& arrayAddTo, NotesType nt, bool bIncludeAuto arrayAddTo.push_back( m_apNotes[i] ); } -Notes* Song::GetNotes( NotesType nt, Difficulty dc, bool bIncludeAutoGen ) const +Notes* Song::GetNotes( NotesType nt, Difficulty dc, bool bIncludeAutoGen, CString sDescription ) const { for( unsigned i=0; im_NotesType==nt && m_apNotes[i]->GetDifficulty()==dc ) if( bIncludeAutoGen || !m_apNotes[i]->IsAutogen() ) - return m_apNotes[i]; + if( sDescription.empty() || m_apNotes[i]->GetDescription()==sDescription ) + return m_apNotes[i]; return NULL; } @@ -1008,7 +1009,7 @@ int Song::GetNumTimesPlayed() const int iTotalNumTimesPlayed = 0; for( unsigned i=0; im_iNumTimesPlayed; + iTotalNumTimesPlayed += m_apNotes[i]->m_MemCardScores[MEMORY_CARD_MACHINE].iNumTimesPlayed; } return iTotalNumTimesPlayed; } diff --git a/stepmania/src/SongManager.cpp b/stepmania/src/SongManager.cpp index 2bafe02147..4a8c7077ad 100644 --- a/stepmania/src/SongManager.cpp +++ b/stepmania/src/SongManager.cpp @@ -28,10 +28,14 @@ SongManager* SONGMAN = NULL; // global and accessable from anywhere in our program -const CString CATEGORY_TOP_SCORE_FILE = "CategoryTopScores.dat"; -const CString COURSE_TOP_SCORE_FILE = "CourseTopScores.dat"; -const int CATEGORY_TOP_SCORE_VERSION = 1; -const int COURSE_TOP_SCORE_VERSION = 1; +const CString CATEGORY_RANKING_FILE = "CategoryRanking.dat"; +const CString COURSE_RANKING_FILE = "CourseRanking.dat"; +const CString NOTES_SCORES_FILE[NUM_MEMORY_CARDS] = { "Player1NotesScores.dat", "Player2NotesScores.dat", "MachineNotesScores.dat" }; +const CString COURSE_SCORES_FILE[NUM_MEMORY_CARDS] = { "Player1CourseScores.dat", "Player2CourseScores.dat", "MachineCourseScores.dat" }; +const int CATEGORY_RANKING_VERSION = 1; +const int COURSE_RANKING_VERSION = 1; +const int NOTES_SCORES_VERSION = 1; +const int COURSE_SCORES_VERSION = 1; #define NUM_GROUP_COLORS THEME->GetMetricI("SongManager","NumGroupColors") @@ -211,25 +215,25 @@ void SongManager::ReloadSongArray() void SongManager::InitMachineScoresFromDisk() { - // Init category top scores + // Init category ranking { for( int i=0; im_MachineScores[i][j].iDancePoints = iDancePoints; - pCourse->m_MachineScores[i][j].fSurviveTime = fSurviveTime; - pCourse->m_MachineScores[i][j].sName = szName; - } + pCourse->m_RankingScores[i][j].iDancePoints = iDancePoints; + pCourse->m_RankingScores[i][j].fSurviveTime = fSurviveTime; + pCourse->m_RankingScores[i][j].sName = szName; } + } } } fclose(fp); } } + + // notes scores + for( int c=0; cGetSongFromDir( szSongDir ); + + for( unsigned i=0; iGetNotes( nt, dc, true, szDescription ); + + int iNumTimesPlayed; + Grade grade; + float fScore; + fscanf(fp, "%d %d %f\n", &iNumTimesPlayed, &grade, &fScore ); + if( pNotes ) + { + pNotes->m_MemCardScores[c].iNumTimesPlayed = iNumTimesPlayed; + pNotes->m_MemCardScores[c].grade = grade; + pNotes->m_MemCardScores[c].fScore = fScore; + } + } + } + } + fclose(fp); + } + } + + // course scores + { + for( int c=0; cm_MemCardScores[c][i].iNumTimesPlayed = iNumTimesPlayed; + pCourse->m_MemCardScores[c][i].iDancePoints = iDancePoints; + pCourse->m_MemCardScores[c][i].fSurviveTime = fSurviveTime; + } + } + } + } + fclose(fp); + } + } + } } void SongManager::SaveMachineScoresToDisk() { - // Write category top scores + // category ranking { - FILE* fp = fopen( CATEGORY_TOP_SCORE_FILE, "w" ); + FILE* fp = fopen( CATEGORY_RANKING_FILE, "w" ); if( fp ) { - fprintf(fp,"%d\n",CATEGORY_TOP_SCORE_VERSION); + fprintf(fp,"%d\n",CATEGORY_RANKING_VERSION); for( int i=0; im_sPath.c_str()); + Course* pCourse = m_pCourses[c]; + if( pCourse->m_bIsAutoGen ) + fprintf(fp, "%s\n", pCourse->m_sName.c_str()); + else + fprintf(fp, "%s\n", pCourse->m_sPath.c_str()); for( int i=0; im_MachineScores[i][j].iDancePoints, - pCourse->m_MachineScores[i][j].fSurviveTime, - pCourse->m_MachineScores[i][j].sName.c_str()); + pCourse->m_RankingScores[i][j].iDancePoints, + pCourse->m_RankingScores[i][j].fSurviveTime, + pCourse->m_RankingScores[i][j].sName.c_str()); + } + + fclose(fp); + } + } + + // notes scores + for( int c=0; c vNotes = pSong->m_apNotes; + for( int n=(int)vNotes.size()-1; n>=0; n-- ) + if( vNotes[n]->m_MemCardScores[c].grade <= GRADE_E ) + vNotes.erase( vNotes.begin()+n ); + if( vNotes.size() == 0 ) + continue; // skip + + fprintf(fp, "%s\n%u\n", + pSong->GetSongDir().c_str(), + vNotes.size() ); + + for( unsigned i=0; im_NotesType, + pNotes->GetDifficulty(), + pNotes->GetDescription().c_str() ); + fprintf(fp, "%d %d %f\n", + pNotes->m_MemCardScores[c].iNumTimesPlayed, + pNotes->m_MemCardScores[c].grade, + pNotes->m_MemCardScores[c].fScore); + } + } + + fclose(fp); + } + } + + // course scores + { + for( int c=0; cm_bIsAutoGen ) + fprintf(fp, "%s\n", pCourse->m_sName.c_str()); + else + fprintf(fp, "%s\n", pCourse->m_sPath.c_str()); + + for( int i=0; im_MemCardScores[c][i].iNumTimesPlayed, + pCourse->m_MemCardScores[c][i].iDancePoints, + pCourse->m_MemCardScores[c][i].fSurviveTime); + } + + fclose(fp); } } - - if( fp ) - fclose(fp); } } @@ -392,6 +551,11 @@ int SongManager::GetNumGroups() const return m_arrayGroupNames.size(); } +int SongManager::GetNumCourses() const +{ + return m_pCourses.size(); +} + CString SongManager::ShortenGroupName( CString sLongGroupName ) { sLongGroupName.Replace( "Dance Dance Revolution", "DDR" ); @@ -434,10 +598,7 @@ void SongManager::InitCoursesFromDisk() { Course* pCourse = new Course; pCourse->LoadFromCRSFile( saCourseFiles[i] ); - if( pCourse->GetNumStages() > 0 ) - m_pCourses.push_back( pCourse ); - else - delete pCourse; + m_pCourses.push_back( pCourse ); } // @@ -455,12 +616,9 @@ void SongManager::InitCoursesFromDisk() for( Difficulty dc=DIFFICULTY_EASY; dc<=DIFFICULTY_HARD; dc=Difficulty(dc+1) ) // foreach Difficulty { Course* pCourse = new Course; - pCourse->CreateEndlessCourseFromGroupAndDifficulty( sGroupName, dc, apGroupSongs ); + pCourse->AutoGenEndlessFromGroupAndDifficulty( sGroupName, dc, apGroupSongs ); - if( pCourse->GetNumStages() > 0 ) - m_pCourses.push_back( pCourse ); - else - delete pCourse; + m_pCourses.push_back( pCourse ); } } } @@ -556,16 +714,17 @@ bool SongManager::GetExtraStageInfoFromCourse( bool bExtra2, CString sPreferredG Course course; course.LoadFromCRSFile( sCoursePath ); - if( course.GetNumStages() <= 0 ) return false; + if( course.GetEstimatedNumStages() <= 0 ) return false; - pSongOut = course.GetSong(0); - pNotesOut = course.GetNotesForStage( 0 ); - if( pNotesOut == NULL ) return false; - - course.GetPlayerOptions( 0, &po_out ); - course.GetSongOptions( &so_out ); - - return true; + CString sModifiers; + if( course.GetFirstStageInfo( pSongOut, pNotesOut, sModifiers, GAMESTATE->GetCurrentStyleDef()->m_NotesType ) ) + { + po_out.FromString( sModifiers ); + so_out.FromString( sModifiers ); + return true; + } + else + return false; } /* Return true if n1 < n2. */ @@ -670,6 +829,24 @@ Song* SongManager::GetRandomSong() return SONGMAN->m_pSongs[ rand()%m_pSongs.size() ]; } +Song* SongManager::GetPlayersBest( int index ) +{ + vector vSongs = m_pSongs; + if( (unsigned)index >= vSongs.size() ) + return NULL; + SortSongPointerArrayByMostPlayed( vSongs ); + return vSongs[index]; +} + +Song* SongManager::GetPlayersWorst( int index ) +{ + vector vSongs = m_pSongs; + if( (unsigned)index >= vSongs.size() ) + return NULL; + SortSongPointerArrayByMostPlayed( vSongs ); + return vSongs[vSongs.size()-1-index]; +} + Song* SongManager::GetSongFromDir( CString sDir ) { if( sDir[sDir.GetLength()-1] != '/' ) @@ -691,6 +868,16 @@ Course* SongManager::GetCourseFromPath( CString sPath ) return NULL; } +Course* SongManager::GetCourseFromName( CString sName ) +{ + for( unsigned int i=0; im_sName) == 0 ) + return m_pCourses[i]; + + return NULL; +} + + bool SongManager::IsUsingMemoryCard( PlayerNumber pn ) { return true; @@ -749,7 +936,7 @@ void SongManager::AddMachineRecords( NotesType nt, RankingCategory hsc[NUM_PLAYE machineScores[j] = machineScores[j-1]; // insert machineScores[i].fScore = newHS.fScore; - machineScores[i].sName = "STEP"; + machineScores[i].sName = DEFAULT_RANKING_NAME; iNewRecordIndexOut[newHS.pn] = i; break; } diff --git a/stepmania/src/SongManager.h b/stepmania/src/SongManager.h index 0570fef436..109e4bc6e7 100644 --- a/stepmania/src/SongManager.h +++ b/stepmania/src/SongManager.h @@ -58,7 +58,11 @@ public: void GetSongs( vector &AddTo ) const { GetSongs(AddTo,"",100000 /*inf*/ ); } int GetNumSongs() const; int GetNumGroups() const; + int GetNumCourses() const; Song* GetRandomSong(); + Song* GetPlayersBest( int index ); + Song* GetPlayersWorst( int index ); + void GetNonstopCourses( vector &AddTo ); // add to if life meter type is BAR. void GetOniCourses( vector &AddTo ); // add to if life meter type is BATTERY. @@ -69,6 +73,7 @@ public: Song* GetSongFromDir( CString sDir ); Course* GetCourseFromPath( CString sPath ); // path to .crs file, or path to song group dir + Course* GetCourseFromName( CString sName ); // diff --git a/stepmania/src/song.h b/stepmania/src/song.h index 2f47f495e7..0fbd18e8f7 100644 --- a/stepmania/src/song.h +++ b/stepmania/src/song.h @@ -206,7 +206,7 @@ public: bool SongHasNotesType( NotesType nt ) const; bool SongHasNotesTypeAndDifficulty( NotesType nt, Difficulty dc ) const; void GetNotes( vector& arrayAddTo, NotesType nt, bool bIncludeAutoGen = true ) const; - Notes* GetNotes( NotesType nt, Difficulty dc, bool bIncludeAutoGen = true ) const; + Notes* GetNotes( NotesType nt, Difficulty dc, bool bIncludeAutoGen = true, CString sDescription = "" ) const; void GetEdits( vector& arrayAddTo, NotesType nt, bool bIncludeAutoGen = true ) const; int GetNumTimesPlayed() const; bool IsNew() const;