diff --git a/stepmania/src/Course.cpp b/stepmania/src/Course.cpp index ba1cbb5f6d..1a84dadf2c 100644 --- a/stepmania/src/Course.cpp +++ b/stepmania/src/Course.cpp @@ -16,6 +16,8 @@ #include "Steps.h" #include "ThemeManager.h" #include "UnlockManager.h" +#include "Game.h" +#include "Style.h" static Preference MAX_SONGS_IN_EDIT_COURSE( "MaxSongsInEditCourse", -1 ); @@ -711,6 +713,20 @@ bool Course::AllSongsAreFixed() const return true; } +const Style *Course::GetCourseStyle( const Game *pGame ) const +{ + for( int s=0; pGame->m_apStyles[s]; ++s ) + { + const Style *pStyle = pGame->m_apStyles[s]; + FOREACHS_CONST( RString, m_setStyles, style ) + { + if( !style->CompareNoCase(pStyle->m_szName) ) + return pStyle; + } + } + return NULL; +} + void Course::Invalidate( const Song *pStaleSong ) { FOREACH_CONST( CourseEntry, m_vEntries, e ) diff --git a/stepmania/src/Course.h b/stepmania/src/Course.h index 50478175a6..c91c648295 100644 --- a/stepmania/src/Course.h +++ b/stepmania/src/Course.h @@ -14,6 +14,8 @@ #include struct lua_State; +class Style; +class Game; const int MAX_EDIT_COURSE_TITLE_LENGTH = 12; @@ -122,6 +124,7 @@ public: int GetMeter( StepsType st, CourseDifficulty cd=Difficulty_Medium ) const; bool HasMods() const; bool AllSongsAreFixed() const; + const Style *GetCourseStyle( const Game *pGame ) const; int GetEstimatedNumStages() const { return m_vEntries.size(); } bool IsPlayableIn( StepsType st ) const; @@ -208,6 +211,9 @@ public: typedef map RadarCache_t; RadarCache_t m_RadarCache; + + /* Preferred styles: */ + set m_setStyles; }; #endif diff --git a/stepmania/src/CourseLoaderCRS.cpp b/stepmania/src/CourseLoaderCRS.cpp index a84079dd46..4d1c2a782c 100644 --- a/stepmania/src/CourseLoaderCRS.cpp +++ b/stepmania/src/CourseLoaderCRS.cpp @@ -282,6 +282,15 @@ bool CourseLoaderCRS::LoadFromMsd( const RString &sPath, const MsdFile &msd, Cou rv.FromString( sParams[3] ); out.m_RadarCache[Course::CacheEntry(st, cd)] = rv; } + else if( 0 == stricmp(sValueName, "STYLE") ) + { + RString sStyles = sParams[1]; + vector asStyles; + split( sStyles, ",", asStyles ); + FOREACH( RString, asStyles, s ) + out.m_setStyles.insert( *s ); + + } else { LOG->UserLog( "Course file", sPath, "contains an unexpected value named \"%s\"", sValueName.c_str() ); diff --git a/stepmania/src/CourseWriterCRS.cpp b/stepmania/src/CourseWriterCRS.cpp index abd2633e18..51fdfcd8d5 100644 --- a/stepmania/src/CourseWriterCRS.cpp +++ b/stepmania/src/CourseWriterCRS.cpp @@ -44,6 +44,12 @@ bool CourseWriterCRS::Write( const Course &course, RageFileBasic &f, bool bSavin f.PutLine( "#REPEAT:YES;" ); if( course.m_iLives != -1 ) f.PutLine( ssprintf("#LIVES:%i;", course.m_iLives) ); + if( !course.m_setStyles.empty() ) + { + vector asStyles; + asStyles.insert( asStyles.begin(), course.m_setStyles.begin(), course.m_setStyles.end() ); + f.PutLine( ssprintf("#STYLE:%i;", join( ",", asStyles ).c_str()) ); + } FOREACH_ENUM( CourseDifficulty,cd ) { diff --git a/stepmania/src/MusicWheel.cpp b/stepmania/src/MusicWheel.cpp index 504defb7fe..0ae69ec1fc 100644 --- a/stepmania/src/MusicWheel.cpp +++ b/stepmania/src/MusicWheel.cpp @@ -19,6 +19,7 @@ #include "Foreach.h" #include "Style.h" #include "PlayerState.h" +#include "CommonMetrics.h" static Preference g_bMoveRandomToEnd( "MoveRandomToEnd", false ); @@ -981,8 +982,13 @@ void MusicWheel::SetOpenGroup( RString group ) if( !m_CurWheelItemData.empty() ) old = GetCurWheelItemData(m_iSelection); + vector vpPossibleStyles; + if( CommonMetrics::AUTO_SET_STYLE ) + GAMEMAN->GetCompatibleStyles( GAMESTATE->m_pCurGame, GAMESTATE->GetNumPlayersEnabled(), vpPossibleStyles ); + m_CurWheelItemData.clear(); vector &from = m_WheelItemDatas[GAMESTATE->m_SortOrder]; + m_CurWheelItemData.reserve( from.size() ); for( unsigned i = 0; i < from.size(); ++i ) { WheelItemData &d = *from[i]; @@ -990,6 +996,17 @@ void MusicWheel::SetOpenGroup( RString group ) d.m_sText != group ) continue; + /* If AUTO_SET_STYLE, hide courses that prefer a style that isn't available. */ + if( d.m_Type == TYPE_COURSE && CommonMetrics::AUTO_SET_STYLE ) + { + const Style *pStyle = d.m_pCourse->GetCourseStyle( GAMESTATE->m_pCurGame ); + if( pStyle ) + { + if( find( vpPossibleStyles.begin(), vpPossibleStyles.end(), pStyle ) == vpPossibleStyles.end() ) + continue; + } + } + /* Only show tutorial songs in arcade */ if( GAMESTATE->m_PlayMode!=PLAY_MODE_REGULAR && d.m_pSong && @@ -1017,6 +1034,12 @@ void MusicWheel::SetOpenGroup( RString group ) RebuildWheelItems(); } +/* Called on late join. Selectable courses may have changed; reopen the section. */ +void MusicWheel::PlayerJoined() +{ + SetOpenGroup( m_sExpandedSectionName ); +} + bool MusicWheel::IsRouletting() const { return m_WheelState == STATE_ROULETTE_SPINNING || m_WheelState == STATE_ROULETTE_SLOWING_DOWN || diff --git a/stepmania/src/MusicWheel.h b/stepmania/src/MusicWheel.h index a5b942ed6c..98bc6a6369 100644 --- a/stepmania/src/MusicWheel.h +++ b/stepmania/src/MusicWheel.h @@ -43,6 +43,7 @@ public: SortOrder GetSortOrder() const { return m_SortOrder; } virtual void ChangeMusic( int dist ); /* +1 or -1 */ //CHECK THIS void FinishChangingSorts(); + void PlayerJoined(); protected: MusicWheelItem *MakeItem(); diff --git a/stepmania/src/ScreenSelectMusic.cpp b/stepmania/src/ScreenSelectMusic.cpp index da895078d9..b162f734a2 100644 --- a/stepmania/src/ScreenSelectMusic.cpp +++ b/stepmania/src/ScreenSelectMusic.cpp @@ -106,14 +106,6 @@ void ScreenSelectMusic::Init() m_TexturePreload.Load( Banner::SongBannerTexture(THEME->GetPathG("Banner","mode")) ); } - if( CommonMetrics::AUTO_SET_STYLE ) - { - vector vst; - GAMEMAN->GetStepsTypesForGame( GAMESTATE->m_pCurGame, vst ); - const Style *pStyle = GAMEMAN->GetFirstCompatibleStyle( GAMESTATE->m_pCurGame, GAMESTATE->GetNumSidesJoined(), vst[0] ); - GAMESTATE->SetCurrentStyle( pStyle ); - } - /* Load low-res banners, if needed. */ BANNERCACHE->Demand(); @@ -188,6 +180,14 @@ void ScreenSelectMusic::BeginScreen() LIGHTSMAN->SetLightsMode( LIGHTSMODE_MENU ); + if( CommonMetrics::AUTO_SET_STYLE ) + { + vector vst; + GAMEMAN->GetStepsTypesForGame( GAMESTATE->m_pCurGame, vst ); + const Style *pStyle = GAMEMAN->GetFirstCompatibleStyle( GAMESTATE->m_pCurGame, GAMESTATE->GetNumSidesJoined(), vst[0] ); + GAMESTATE->SetCurrentStyle( pStyle ); + } + if( GAMESTATE->GetCurrentStyle() == NULL ) RageException::Throw( "The Style has not been set. A theme must set the Style before loading ScreenSelectMusic." ); @@ -347,6 +347,10 @@ void ScreenSelectMusic::Input( const InputEventPlus &input ) FOREACH_ENUM( PlayerNumber, p ) GAMESTATE->m_pCurSteps[p].SetWithoutBroadcast( NULL ); + /* If a course is selected, it may no longer be playable. Let MusicWheel know + * about the late join. */ + m_MusicWheel.PlayerJoined(); + AfterMusicChange(); int iSel = 0; @@ -888,14 +892,20 @@ void ScreenSelectMusic::MenuStart( const InputEventPlus &input ) if( CommonMetrics::AUTO_SET_STYLE ) { /* Now that Steps have been chosen, set a Style that can play them. */ - StepsType stCurrent; - PlayerNumber pn = GAMESTATE->m_MasterPlayerNumber; + const Style *pStyle = NULL; if( GAMESTATE->IsCourseMode() ) - stCurrent = GAMESTATE->m_pCurTrail[pn]->m_StepsType; - else - stCurrent = GAMESTATE->m_pCurSteps[pn]->m_StepsType; - vector vst; - const Style *pStyle = GAMEMAN->GetFirstCompatibleStyle( GAMESTATE->m_pCurGame, GAMESTATE->GetNumSidesJoined(), stCurrent ); + pStyle = GAMESTATE->m_pCurCourse->GetCourseStyle( GAMESTATE->m_pCurGame ); + if( pStyle == NULL ) + { + StepsType stCurrent; + PlayerNumber pn = GAMESTATE->m_MasterPlayerNumber; + if( GAMESTATE->IsCourseMode() ) + stCurrent = GAMESTATE->m_pCurTrail[pn]->m_StepsType; + else + stCurrent = GAMESTATE->m_pCurSteps[pn]->m_StepsType; + vector vst; + pStyle = GAMEMAN->GetFirstCompatibleStyle( GAMESTATE->m_pCurGame, GAMESTATE->GetNumSidesJoined(), stCurrent ); + } GAMESTATE->SetCurrentStyle( pStyle ); } @@ -1160,12 +1170,13 @@ void ScreenSelectMusic::AfterMusicChange() case TYPE_COURSE: { - Course* pCourse = m_MusicWheel.GetSelectedCourse(); - StepsType st = GAMESTATE->GetCurrentStyle()->m_StepsType; - Trail *pTrail = pCourse->GetTrail( st ); - ASSERT( pTrail ); - - pCourse->GetTrails( m_vpTrails, GAMESTATE->GetCurrentStyle()->m_StepsType ); + const Course *pCourse = m_MusicWheel.GetSelectedCourse(); + const Style *pStyle = NULL; + if( CommonMetrics::AUTO_SET_STYLE ) + pStyle = pCourse->GetCourseStyle( GAMESTATE->m_pCurGame ); + if( pStyle == NULL ) + pStyle = GAMESTATE->GetCurrentStyle(); + pCourse->GetTrails( m_vpTrails, pStyle->m_StepsType ); m_sSampleMusicToPlay = m_sCourseMusicPath; m_fSampleStartSeconds = 0;