diff --git a/stepmania/src/Course.cpp b/stepmania/src/Course.cpp index 3e014b3ea6..2c723e3b6f 100644 --- a/stepmania/src/Course.cpp +++ b/stepmania/src/Course.cpp @@ -26,6 +26,11 @@ #include "GameState.h" #include "BannerCache.h" +/* Amount to increase meter ranges to make them difficult: */ +const int DIFFICULT_METER_CHANGE = 2; + +/* Maximum lower value of ranges when difficult: */ +const int MAX_BOTTOM_RANGE = 10; Course::Course() { @@ -343,13 +348,62 @@ void Course::AutogenNonstopFromGroup( CString sGroupName, vector &apSongs SetDefaultScore(); } - -bool Course::HasDifficult() const +/* + * Difficult courses do the following: + * + * For entries with a meter range, bump it up by DIFFICULT_METER_CHANGE; + * eg. 3..6 -> 5..8, with a minimum no higher than MAX_BOTTOM_RANGE. + * + * For entries with a difficulty class, use notes one class harder, if they + * exist. This way, if a static song entry points to a difficulty, we'll always + * play that song, even if we're on difficult and harder notes don't exist. (The + * exception is a static song entry with a meter range, but that's not very useful.) + */ +bool Course::HasDifficult( NotesType nt ) const { - for( unsigned i=0; i= DIFFICULTY_HARD ) - return false; - return true; + if( ContainsAnyMysterySongs() ) + { + for( unsigned i=0; im_bDifficultCourses; + + vector vSongs, vHardSongs; + vector vNotes, vHardNotes; + vector vsIgnore; + + GAMESTATE->m_bDifficultCourses = false; + GetStageInfo( vSongs, vNotes, vsIgnore, nt ); + GAMESTATE->m_bDifficultCourses = true; + GetStageInfo( vHardSongs, vHardNotes, vsIgnore, nt ); + GAMESTATE->m_bDifficultCourses = OldDifficulty; + + if( vSongs.size() != vHardSongs.size() ) + return true; /* it changed */ + + for( unsigned i=0; iGetNotes( nt, e.low_meter, e.high_meter, PREFSMAN->m_bAutogenMissingTypes ); + pNotes = pSong->GetNotes( nt, low_meter, high_meter, PREFSMAN->m_bAutogenMissingTypes ); else pNotes = pSong->GetNotes( nt, e.difficulty, PREFSMAN->m_bAutogenMissingTypes ); } @@ -418,7 +476,7 @@ void Course::GetStageInfo( continue; /* wrong group */ if( e.difficulty == DIFFICULTY_INVALID ) - pNotes = pSong->GetNotes( nt, e.low_meter, e.high_meter, PREFSMAN->m_bAutogenMissingTypes ); + pNotes = pSong->GetNotes( nt, low_meter, high_meter, PREFSMAN->m_bAutogenMissingTypes ); else pNotes = pSong->GetNotes( nt, e.difficulty, PREFSMAN->m_bAutogenMissingTypes ); @@ -469,7 +527,7 @@ void Course::GetStageInfo( } if( e.difficulty == DIFFICULTY_INVALID ) - pNotes = pSong->GetNotes( nt, e.low_meter, e.high_meter, PREFSMAN->m_bAutogenMissingTypes ); + pNotes = pSong->GetNotes( nt, low_meter, high_meter, PREFSMAN->m_bAutogenMissingTypes ); else pNotes = pSong->GetNotes( nt, e.difficulty, PREFSMAN->m_bAutogenMissingTypes ); @@ -484,7 +542,9 @@ void Course::GetStageInfo( if( !pSong || !pNotes ) continue; // this song entry isn't playable. Skip. - if(GAMESTATE->m_bDifficultCourses) + /* If e.difficulty == DIFFICULTY_INVALID, then we already increased difficulty + * based on meter. */ + if( GAMESTATE->m_bDifficultCourses && e.difficulty != DIFFICULTY_INVALID ) { /* See if we can find a NoteData that's one notch more difficult than * the one we found above. */ @@ -568,6 +628,13 @@ void Course::GetMeterRange( int stage, int& iMeterLowOut, int& iMeterHighOut ) c { iMeterLowOut = m_entries[stage].low_meter; iMeterHighOut = m_entries[stage].high_meter; + + if( m_entries[stage].difficulty == DIFFICULTY_INVALID && GAMESTATE->m_bDifficultCourses ) + { + iMeterHighOut += DIFFICULT_METER_CHANGE; + iMeterLowOut += DIFFICULT_METER_CHANGE; + iMeterLowOut = min( iMeterLowOut, MAX_BOTTOM_RANGE ); + } } bool Course::ContainsAnyMysterySongs() const diff --git a/stepmania/src/Course.h b/stepmania/src/Course.h index 3b6c0c67b3..4388f8607d 100644 --- a/stepmania/src/Course.h +++ b/stepmania/src/Course.h @@ -61,13 +61,13 @@ public: int m_iExtra; // extra stage number... // not used? -Chris int GetEstimatedNumStages() const { return m_entries.size(); } - bool HasDifficult() const; + bool HasDifficult( NotesType nt ) const; bool IsPlayableIn( NotesType nt ) const; void GetStageInfo( // Derefrences course_entries and returns only the playable Songs and Notes vector& vSongsOut, vector& vNotesOut, vector& vsModifiersOut, - NotesType nt ) const; // like EX's Standard/Difficult option for courses + NotesType nt ) const; bool GetFirstStageInfo( Song*& pSongOut, Notes*& pNotesOut, diff --git a/stepmania/src/ScreenPlayerOptions.cpp b/stepmania/src/ScreenPlayerOptions.cpp index da1faa7b41..7c17c5f0ce 100644 --- a/stepmania/src/ScreenPlayerOptions.cpp +++ b/stepmania/src/ScreenPlayerOptions.cpp @@ -108,7 +108,7 @@ void ScreenPlayerOptions::ImportOptions() if( GAMESTATE->m_pCurCourse ) // playing a course { m_OptionRow[PO_STEP].choices.push_back( "REGULAR" ); - if( GAMESTATE->m_pCurCourse->HasDifficult() ) + if( GAMESTATE->m_pCurCourse->HasDifficult( GAMESTATE->GetCurrentStyleDef()->m_NotesType ) ) m_OptionRow[PO_STEP].choices.push_back( "DIFFICULT" ); } else @@ -216,7 +216,8 @@ void ScreenPlayerOptions::ImportOptions() if( GAMESTATE->m_pCurCourse ) // playing a course { - if( GAMESTATE->m_bDifficultCourses ) + if( GAMESTATE->m_bDifficultCourses && + GAMESTATE->m_pCurCourse->HasDifficult( GAMESTATE->GetCurrentStyleDef()->m_NotesType ) ) m_iSelectedOption[p][PO_STEP] = 1; else m_iSelectedOption[p][PO_STEP] = 0;