diff --git a/stepmania/NEWS b/stepmania/NEWS index cdaeae138f..bac82be42e 100644 --- a/stepmania/NEWS +++ b/stepmania/NEWS @@ -25,9 +25,12 @@ NEW FEATURE: Added SKIPPY transform BUG FIX: Fixed song seeking in editor at non 1x music rates NEW FEATURE: More complete controls for BackgroundChanges in editor NEW FEATURE: Shift+P in editor for "play current beat until end" +NEW FEATURE: Select between Normal and Difficult in Nonstop and Endless mode CHANGE: Nonstop and Oni scoring and combo counter behave exactly like DDREX CHANGE: HoldNote life snaps to full when button is pressed (instead of refilling slowly) ala DDR +NEW FEATURE: Toggle for Autogen of missing steps +NEW FEATURE: Toggle for Autogen of group Nonstop and Endless Courses ----------------------- Version 3.01 --------------------------- CHANGE: Simplified NoteSkin tap graphic format. Old NoteSkins will need to diff --git a/stepmania/Themes/default/metrics.ini b/stepmania/Themes/default/metrics.ini index 7069cab0fa..3eaa0f58fd 100644 --- a/stepmania/Themes/default/metrics.ini +++ b/stepmania/Themes/default/metrics.ini @@ -1075,6 +1075,11 @@ WheelSections=ALWAYS means sections in group + ABC; NEVER means no sections;::AB Translations=Choose whether to displays song titles in their native::language (日本語), or to transliterate when possible Lyrics=Choose whether to show lyrics if a song::has them available (LRC File) +[ScreenAutogenOptions] +HelpText=&UP; &DOWN; to change line &LEFT; &RIGHT; to select between options::START to accept changes BACK to discard changes +AutogenMissingTypes=Show steps for songs that were created by Autogen. +AutogenGroupCourses=Show group Nonstop and Endless courses that::were created by Autogen. + [ScreenUnlock] NextScreen=ScreenRanking @@ -1205,6 +1210,7 @@ GraphicOptions= GameplayOptions= AppearanceOptions= SoundOptions= +AutogenOptions= [TextBanner] Width=180 diff --git a/stepmania/src/Course.cpp b/stepmania/src/Course.cpp index d6cc1125be..fcd983cc8d 100644 --- a/stepmania/src/Course.cpp +++ b/stepmania/src/Course.cpp @@ -26,7 +26,7 @@ Course::Course() { - m_bIsAutoGen = false; + m_bIsAutogen = false; m_bRepeat = false; m_bRandomize = false; m_bDifficult = false; @@ -240,9 +240,9 @@ void Course::LoadFromCRSFile( CString sPath ) } -void Course::AutoGenEndlessFromGroupAndDifficulty( CString sGroupName, Difficulty dc, vector &apSongsInGroup ) +void Course::AutogenEndlessFromGroup( CString sGroupName, vector &apSongsInGroup ) { - m_bIsAutoGen = true; + m_bIsAutogen = true; m_bRepeat = true; m_bRandomize = true; m_iLives = -1; @@ -255,26 +255,15 @@ void Course::AutoGenEndlessFromGroupAndDifficulty( CString sGroupName, Difficult if( !asPossibleBannerPaths.empty() ) m_sBannerPath = asPossibleBannerPaths[0]; - CString sShortGroupName = SONGMAN->ShortenGroupName( sGroupName ); + m_sName = SONGMAN->ShortenGroupName( sGroupName ); - m_sName = sShortGroupName + " "; - switch( dc ) - { - case DIFFICULTY_EASY: m_sName += "Easy"; break; - case DIFFICULTY_MEDIUM: m_sName += "Medium"; break; - case DIFFICULTY_HARD: m_sName += "Hard"; break; - default: - ASSERT(0); - } - - // only need one song because it repeats // We want multiple songs, so we can try to prevent repeats during // gameplay. (We might still get a repeat at the repeat boundary, // but that'd be rare.) -glenn Entry e; e.type = Entry::random_within_group; e.group_name = sGroupName; - e.difficulty = dc; + e.difficulty = DIFFICULTY_MEDIUM; vector vSongs; SONGMAN->GetSongs( vSongs, e.group_name ); @@ -282,6 +271,21 @@ void Course::AutoGenEndlessFromGroupAndDifficulty( CString sGroupName, Difficult m_entries.push_back( e ); } +void Course::AutogenNonstopFromGroup( CString sGroupName, vector &apSongsInGroup ) +{ + AutogenEndlessFromGroup( sGroupName, apSongsInGroup ); + + m_bRepeat = false; + + m_sName += " Random"; + + // resize to 4 + while( m_entries.size() < 4 ) + m_entries.push_back( m_entries[0] ); + while( m_entries.size() > 4 ) + m_entries.pop_back(); +} + bool Course::HasDifficult() const { @@ -644,6 +648,35 @@ bool Course::MakeDifficult() // // Sorting stuff // +static bool CompareCoursePointersByName(const Course* pCourse1, const Course* pCourse2) +{ + // HACK: strcmp and other string comparators appear to eat whitespace. + // For example, the string "Players Best 13-16" is sorted between + // "Players Best 1-4" and "Players Best 5-8". Replace the string " " + // with " 0" for comparison only. + + // XXX: That doesn't happen to me, and it shouldn't (strcmp is strictly + // a byte sort, though CompareNoCase doesn't use strcmp). Are you sure + // you didn't have only one space before? -glenn + CString sName1 = pCourse1->m_sName; + CString sName2 = pCourse2->m_sName; + sName1.Replace( " " , " 0" ); + sName2.Replace( " " , " 0" ); + return sName1.CompareNoCase( sName2 ) == -1; +} + +static bool CompareCoursePointersByAutogen(const Course* pCourse1, const Course* pCourse2) +{ + int b1 = pCourse1->m_bIsAutogen; + int b2 = pCourse2->m_bIsAutogen; + if( b1 < b2 ) + return true; + else if( b1 > b2 ) + return false; + else + return CompareCoursePointersByName(pCourse1,pCourse2); +} + static bool CompareCoursePointersByDifficulty(const Course* pCourse1, const Course* pCourse2) { int iNum1 = pCourse1->GetEstimatedNumStages(); @@ -653,21 +686,7 @@ static bool CompareCoursePointersByDifficulty(const Course* pCourse1, const Cour else if( iNum1 > iNum2 ) return false; else // iNum1 == iNum2 - { - // HACK: strcmp and other string comparators appear to eat whitespace. - // For example, the string "Players Best 13-16" is sorted between - // "Players Best 1-4" and "Players Best 5-8". Replace the string " " - // with " 0" for comparison only. - - // XXX: That doesn't happen to me, and it shouldn't (strcmp is strictly - // a byte sort, though CompareNoCase doesn't use strcmp). Are you sure - // you didn't have only one space before? -glenn - CString sName1 = pCourse1->m_sName; - CString sName2 = pCourse2->m_sName; - sName1.Replace( " " , " 0" ); - sName2.Replace( " " , " 0" ); - return sName1.CompareNoCase( sName2 ) == -1; - } + return CompareCoursePointersByAutogen( pCourse1, pCourse2 ); } void SortCoursePointerArrayByDifficulty( vector &apCourses ) diff --git a/stepmania/src/Course.h b/stepmania/src/Course.h index d27f0ddeca..0a230371e1 100644 --- a/stepmania/src/Course.h +++ b/stepmania/src/Course.h @@ -44,7 +44,7 @@ class Course public: Course(); - bool m_bIsAutoGen; // was this created by AutoGen? + bool m_bIsAutogen; // was this created by AutoGen? CString m_sPath; CString m_sName; CString m_sBannerPath; @@ -81,7 +81,8 @@ public: void LoadFromCRSFile( CString sPath ); - void AutoGenEndlessFromGroupAndDifficulty( CString sGroupName, Difficulty dc, vector &apSongsInGroup ); + void AutogenEndlessFromGroup( CString sGroupName, vector &apSongsInGroup ); + void AutogenNonstopFromGroup( CString sGroupName, vector &apSongsInGroup ); // Statistics diff --git a/stepmania/src/MusicWheel.cpp b/stepmania/src/MusicWheel.cpp index ade222ac34..012103bd5f 100644 --- a/stepmania/src/MusicWheel.cpp +++ b/stepmania/src/MusicWheel.cpp @@ -265,7 +265,7 @@ void MusicWheel::GetSongList(vector &arraySongs, bool bRoulette ) } vector arraySteps; - pSong->GetNotes( arraySteps, GAMESTATE->GetCurrentStyleDef()->m_NotesType ); + pSong->GetNotes( arraySteps, GAMESTATE->GetCurrentStyleDef()->m_NotesType, DIFFICULTY_INVALID, -1, -1, "", PREFSMAN->m_bAutogenMissingTypes ); if( !arraySteps.empty() ) arraySongs.push_back( pSong ); @@ -453,9 +453,9 @@ void MusicWheel::BuildWheelItemDatas( vector &arrayWheelItemDatas vector apCourses; switch( GAMESTATE->m_PlayMode ) { - case PLAY_MODE_NONSTOP: SONGMAN->GetNonstopCourses( apCourses ); break; - case PLAY_MODE_ONI: SONGMAN->GetOniCourses( apCourses ); break; - case PLAY_MODE_ENDLESS: SONGMAN->GetEndlessCourses( apCourses ); break; + case PLAY_MODE_NONSTOP: SONGMAN->GetNonstopCourses( apCourses, PREFSMAN->m_bAutogenGroupCourses ); break; + case PLAY_MODE_ONI: SONGMAN->GetOniCourses( apCourses, PREFSMAN->m_bAutogenGroupCourses ); break; + case PLAY_MODE_ENDLESS: SONGMAN->GetEndlessCourses( apCourses, PREFSMAN->m_bAutogenGroupCourses ); break; default: ASSERT(0); } diff --git a/stepmania/src/PrefsManager.cpp b/stepmania/src/PrefsManager.cpp index 5fba814153..dd04813367 100644 --- a/stepmania/src/PrefsManager.cpp +++ b/stepmania/src/PrefsManager.cpp @@ -89,6 +89,8 @@ PrefsManager::PrefsManager() m_bDancePointsForOni = false; //DDR-Extreme style dance points instead of max2 percent m_bTimestamping = false; m_bShowLyrics = true; + m_bAutogenMissingTypes = true; + m_bAutogenGroupCourses = true; /* DDR Extreme-style extra stage support. * Default off so people used to the current behavior (or those with extra @@ -183,9 +185,10 @@ void PrefsManager::ReadGlobalPrefsFromDisk( bool bSwitchToLastPlayedGame ) ini.GetValueB( "Options", "SoloSingle", m_bSoloSingle ); ini.GetValueB( "Options", "DancePointsForOni", m_bDancePointsForOni ); ini.GetValueB( "Options", "ShowLyrics", m_bShowLyrics ); + ini.GetValueB( "Options", "AutogenMissingTypes", m_bAutogenMissingTypes ); + ini.GetValueB( "Options", "AutogenGroupCourses", m_bAutogenGroupCourses ); ini.GetValueB( "Options", "Timestamping", m_bTimestamping ); - m_asAdditionalSongFolders.clear(); CString sAdditionalSongFolders; ini.GetValue( "Options", "AdditionalSongFolders", sAdditionalSongFolders ); @@ -261,6 +264,8 @@ void PrefsManager::SaveGlobalPrefsToDisk() ini.SetValueB( "Options", "SoloSingle", m_bSoloSingle ); ini.SetValueB( "Options", "DancePointsForOni", m_bDancePointsForOni ); ini.SetValueB( "Options", "ShowLyrics", m_bShowLyrics ); + ini.SetValueB( "Options", "AutogenMissingTypes", m_bAutogenMissingTypes ); + ini.SetValueB( "Options", "AutogenGroupCourses", m_bAutogenGroupCourses ); ini.SetValueB( "Options", "Timestamping", m_bTimestamping ); diff --git a/stepmania/src/PrefsManager.h b/stepmania/src/PrefsManager.h index 2b2ffb6db6..7a8e3f8ba0 100644 --- a/stepmania/src/PrefsManager.h +++ b/stepmania/src/PrefsManager.h @@ -74,6 +74,8 @@ public: bool m_bDancePointsForOni; bool m_bTimestamping; bool m_bShowLyrics; + bool m_bAutogenMissingTypes; + bool m_bAutogenGroupCourses; /* 0 = no; 1 = yes; -1 = auto (do whatever is appropriate for the arch). */ int m_iBoostAppPriority; diff --git a/stepmania/src/Screen.cpp b/stepmania/src/Screen.cpp index b81a24e8a6..65f360e996 100644 --- a/stepmania/src/Screen.cpp +++ b/stepmania/src/Screen.cpp @@ -270,6 +270,7 @@ void Screen::ClearMessageQueue( const ScreenMessage SM ) #include "ScreenOptionsMenu.h" #include "ScreenGameplayOptions.h" #include "ScreenStyleSplash.h" +#include "ScreenAutogenOptions.h" Screen* Screen::Create( CString sClassName ) { @@ -301,7 +302,7 @@ Screen* Screen::Create( CString sClassName ) else if( 0==stricmp(sClassName, "ScreenSelectGroup") ) ret = new ScreenSelectGroup; else if( 0==stricmp(sClassName, "ScreenSelectMusic") ) ret = new ScreenSelectMusic; else if( 0==stricmp(sClassName, "ScreenSelectStyle5th") ) ret = new ScreenSelectStyle5th; - else if( 0==stricmp(sClassName, "ScreenSelectStyle") ) ret = new ScreenSelectStyle; + else if( 0==stricmp(sClassName, "ScreenSelectStyle") ) ret = new ScreenSelectStyle; else if( 0==stricmp(sClassName, "ScreenSongOptions") ) ret = new ScreenSongOptions; else if( 0==stricmp(sClassName, "ScreenStage") ) ret = new ScreenStage; else if( 0==stricmp(sClassName, "ScreenTest") ) ret = new ScreenTest; @@ -326,6 +327,7 @@ Screen* Screen::Create( CString sClassName ) else if( 0==stricmp(sClassName, "ScreenSoundOptions") ) ret = new ScreenSoundOptions; else if( 0==stricmp(sClassName, "ScreenGameplayOptions") ) ret = new ScreenGameplayOptions; else if( 0==stricmp(sClassName, "ScreenStyleSplash") ) ret = new ScreenStyleSplash; + else if( 0==stricmp(sClassName, "ScreenAutogenOptions") ) ret = new ScreenAutogenOptions; else RageException::Throw( "Invalid Screen class name '%s'", sClassName.GetString() ); return ret; diff --git a/stepmania/src/ScreenMachineOptions.cpp b/stepmania/src/ScreenMachineOptions.cpp index cef33f9710..019242a238 100644 --- a/stepmania/src/ScreenMachineOptions.cpp +++ b/stepmania/src/ScreenMachineOptions.cpp @@ -36,8 +36,7 @@ enum { MO_SHOW_SONG_OPTIONS, NUM_MACHINE_OPTIONS_LINES }; -/* Hmm. Ignore JoyAxes and Back Delayed probably belong in "input options", - * preferably alongside button configuration. */ + OptionRow g_MachineOptionsLines[NUM_MACHINE_OPTIONS_LINES] = { OptionRow( "Menu\nTimer", "OFF","ON" ), OptionRow( "Arcade\nStages", "1","2","3","4","5","6","7","UNLIMITED" ), diff --git a/stepmania/src/ScreenMachineOptions.h b/stepmania/src/ScreenMachineOptions.h index 0e1978f740..95f2b7dc2a 100644 --- a/stepmania/src/ScreenMachineOptions.h +++ b/stepmania/src/ScreenMachineOptions.h @@ -1,3 +1,5 @@ +#ifndef SCREENMACHINEOPTIONS_H +#define SCREENMACHINEOPTIONS_H /* ----------------------------------------------------------------------------- File: ScreenMachineOptions @@ -8,8 +10,6 @@ Chris Danford ----------------------------------------------------------------------------- */ -#ifndef SCREEN_MACHINE_OPTIONS_H -#define SCREEN_MACHINE_OPTIONS_H #include "ScreenOptions.h" diff --git a/stepmania/src/ScreenOptionsMenu.cpp b/stepmania/src/ScreenOptionsMenu.cpp index 8444160868..5828476f29 100644 --- a/stepmania/src/ScreenOptionsMenu.cpp +++ b/stepmania/src/ScreenOptionsMenu.cpp @@ -24,11 +24,11 @@ #include "GameManager.h" #include "GameState.h" #include "ThemeManager.h" -#include "ScreenMiniMenu.h" enum { - OM_APPEARANCE = 0, + OM_APPEARANCE, + OM_AUTOGEN, OM_CONFIG_KEY_JOY, OM_INPUT, OM_GAMEPLAY, @@ -40,6 +40,7 @@ enum { OptionRow g_OptionsMenuLines[NUM_OPTIONS_MENU_LINES] = { OptionRow( "", "Appearance Options" ), + OptionRow( "", "Autogen Options" ), OptionRow( "", "Config Key/Joy Mappings" ), OptionRow( "", "Input Options" ), OptionRow( "", "Gameplay Options" ), @@ -75,7 +76,6 @@ void ScreenOptionsMenu::ImportOptions() void ScreenOptionsMenu::ExportOptions() { - } void ScreenOptionsMenu::GoToPrevState() @@ -88,6 +88,7 @@ void ScreenOptionsMenu::GoToNextState() switch( this->m_iCurrentRow[0] ) { case OM_APPEARANCE: SCREENMAN->SetNewScreen("ScreenAppearanceOptions"); break; + case OM_AUTOGEN: SCREENMAN->SetNewScreen("ScreenAutogenOptions"); break; case OM_CONFIG_KEY_JOY: SCREENMAN->SetNewScreen("ScreenMapControllers"); break; case OM_GAMEPLAY: SCREENMAN->SetNewScreen("ScreenGameplayOptions"); break; case OM_GRAPHIC: SCREENMAN->SetNewScreen("ScreenGraphicOptions"); break; diff --git a/stepmania/src/SongManager.cpp b/stepmania/src/SongManager.cpp index d6a43f5692..d3d53e43c3 100644 --- a/stepmania/src/SongManager.cpp +++ b/stepmania/src/SongManager.cpp @@ -64,9 +64,10 @@ SongManager::SongManager( LoadingWindow *ld ) g_ExtraColor = EXTRA_COLOR; InitSongArrayFromDisk( ld ); + InitCoursesFromDisk(); + InitAutogenCourses(); InitMachineScoresFromDisk(); - InitCoursesFromDisk(); } catch(...) { SONGMAN = NULL; throw; @@ -418,7 +419,7 @@ void SongManager::SaveMachineScoresToDisk() Course* pCourse = m_pCourses[c]; ASSERT(pCourse); - if( pCourse->m_bIsAutoGen ) + if( pCourse->m_bIsAutogen ) fprintf(fp, "%s\n", pCourse->m_sName.c_str()); else fprintf(fp, "%s\n", pCourse->m_sPath.c_str()); @@ -504,7 +505,7 @@ void SongManager::SaveMachineScoresToDisk() Course* pCourse = m_pCourses[i]; ASSERT(pCourse); - if( pCourse->m_bIsAutoGen ) + if( pCourse->m_bIsAutogen ) fprintf(fp, "%s\n", pCourse->m_sName.c_str()); else fprintf(fp, "%s\n", pCourse->m_sPath.c_str()); @@ -654,7 +655,10 @@ void SongManager::InitCoursesFromDisk() pCourse->LoadFromCRSFile( saCourseFiles[i] ); m_pCourses.push_back( pCourse ); } +} +void SongManager::InitAutogenCourses() +{ // // Create group courses for Endless and Nonstop // @@ -667,16 +671,19 @@ void SongManager::InitCoursesFromDisk() vector apGroupSongs; GetSongs( apGroupSongs, sGroupName ); - for( Difficulty dc=DIFFICULTY_EASY; dc<=DIFFICULTY_HARD; dc=Difficulty(dc+1) ) // foreach Difficulty - { - Course* pCourse = new Course; - pCourse->AutoGenEndlessFromGroupAndDifficulty( sGroupName, dc, apGroupSongs ); + Course* pCourse; - m_pCourses.push_back( pCourse ); - } + pCourse = new Course; + pCourse->AutogenEndlessFromGroup( sGroupName, apGroupSongs ); + m_pCourses.push_back( pCourse ); + + pCourse = new Course; + pCourse->AutogenNonstopFromGroup( sGroupName, apGroupSongs ); + m_pCourses.push_back( pCourse ); } } + void SongManager::FreeCourses() { for( unsigned i=0; i &AddTo ) +void SongManager::GetNonstopCourses( vector &AddTo, bool bIncludeAutogen ) { for( unsigned i=0; im_bRepeat && m_pCourses[i]->m_iLives <= 0 ) // use bar life meter - AddTo.push_back( m_pCourses[i] ); - } + if( bIncludeAutogen || !m_pCourses[i]->m_bIsAutogen ) + AddTo.push_back( m_pCourses[i] ); } -void SongManager::GetOniCourses( vector &AddTo ) +void SongManager::GetOniCourses( vector &AddTo, bool bIncludeAutogen ) { for( unsigned i=0; im_bRepeat && m_pCourses[i]->m_iLives > 0 ) // use battery life meter - AddTo.push_back( m_pCourses[i] ); - } + if( bIncludeAutogen || !m_pCourses[i]->m_bIsAutogen ) + AddTo.push_back( m_pCourses[i] ); } -void SongManager::GetEndlessCourses( vector &AddTo ) +void SongManager::GetEndlessCourses( vector &AddTo, bool bIncludeAutogen ) { for( unsigned i=0; im_bRepeat ) - AddTo.push_back( m_pCourses[i] ); - } + if( bIncludeAutogen || !m_pCourses[i]->m_bIsAutogen ) + AddTo.push_back( m_pCourses[i] ); } diff --git a/stepmania/src/SongManager.h b/stepmania/src/SongManager.h index a83dc128c8..fb773f588f 100644 --- a/stepmania/src/SongManager.h +++ b/stepmania/src/SongManager.h @@ -49,6 +49,7 @@ public: vector m_pCourses; void InitCoursesFromDisk(); + void InitAutogenCourses(); void FreeCourses(); void CleanData(); @@ -65,9 +66,9 @@ public: 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 GetNonstopCourses( vector &AddTo, bool bIncludeAutogen ); // add to if life meter type is BAR. + void GetOniCourses( vector &AddTo, bool bIncludeAutogen ); // add to if life meter type is BATTERY. + void GetEndlessCourses( vector &AddTo, bool bIncludeAutogen ); // 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 );