diff --git a/stepmania/src/GameState.cpp b/stepmania/src/GameState.cpp index 0cc58ebb1a..b2edce369f 100644 --- a/stepmania/src/GameState.cpp +++ b/stepmania/src/GameState.cpp @@ -516,7 +516,7 @@ void GameState::EndGame() m_timeGameStarted.SetZero(); } -int GameState::GetNumStagesForSong( const Song* pSong ) +int GameState::GetNumStagesMultiplierForSong( const Song* pSong ) { int iNumStages = 1; @@ -531,7 +531,7 @@ int GameState::GetNumStagesForSong( const Song* pSong ) int GameState::GetNumStagesForSongAndStyle( const Song* pSong, const Style *pStyle ) { - int iNumStages = GetNumStagesForSong( pSong ); + int iNumStages = GetNumStagesMultiplierForSong( pSong ); // One player, two-sides styles cost extra switch( pStyle->m_StyleType ) diff --git a/stepmania/src/GameState.h b/stepmania/src/GameState.h index 02cdf80558..61f3cb0a3c 100644 --- a/stepmania/src/GameState.h +++ b/stepmania/src/GameState.h @@ -118,7 +118,7 @@ public: int m_iNumStagesOfThisSong; int m_iCurrentStageIndex; - static int GetNumStagesForSong( const Song* pSong ); + static int GetNumStagesMultiplierForSong( const Song* pSong ); static int GetNumStagesForSongAndStyle( const Song* pSong, const Style *pStyle ); static int GetNumStagesForCurrentSongAndStepsOrCourse(); diff --git a/stepmania/src/MusicWheel.cpp b/stepmania/src/MusicWheel.cpp index ce6d2f1f9e..aed83b711b 100644 --- a/stepmania/src/MusicWheel.cpp +++ b/stepmania/src/MusicWheel.cpp @@ -159,7 +159,7 @@ void MusicWheel::BeginScreen() /* Invalidate current Song if it can't be played * because there are not enough stages remaining. */ if( GAMESTATE->m_pCurSong != NULL && - GameState::GetNumStagesForSong( GAMESTATE->m_pCurSong ) > GAMESTATE->GetNumStagesLeft() ) + GameState::GetNumStagesMultiplierForSong( GAMESTATE->m_pCurSong ) > GAMESTATE->GetNumStagesLeft() ) { GAMESTATE->m_pCurSong.Set( NULL ); } @@ -698,7 +698,7 @@ void MusicWheel::BuildWheelItemDatas( vector &arrayWheelItemDat { WID.m_Flags.bHasBeginnerOr1Meter = WID.m_pSong->IsEasy( GAMESTATE->GetCurrentStyle()->m_StepsType ); WID.m_Flags.bEdits = WID.m_pSong->HasEdits( GAMESTATE->GetCurrentStyle()->m_StepsType ); - WID.m_Flags.iStagesForSong = GameState::GetNumStagesForSong( WID.m_pSong ); + WID.m_Flags.iStagesForSong = GameState::GetNumStagesMultiplierForSong( WID.m_pSong ); } else if( WID.m_pCourse != NULL ) { diff --git a/stepmania/src/ScoreKeeperNormal.cpp b/stepmania/src/ScoreKeeperNormal.cpp index 82ed2a1ae0..4da8668254 100644 --- a/stepmania/src/ScoreKeeperNormal.cpp +++ b/stepmania/src/ScoreKeeperNormal.cpp @@ -206,7 +206,7 @@ void ScoreKeeperNormal::OnNextSong( int iSongInCourseIndex, const Steps* pSteps, const int iMeter = clamp( pSteps->GetMeter(), 1, 10 ); // long ver and marathon ver songs have higher max possible scores - int iLengthMultiplier = GameState::GetNumStagesForSong( GAMESTATE->m_pCurSong ); + int iLengthMultiplier = GameState::GetNumStagesMultiplierForSong( GAMESTATE->m_pCurSong ); switch( PREFSMAN->m_ScoringType ) { case SCORING_NEW: diff --git a/stepmania/src/ScreenSelectMusic.cpp b/stepmania/src/ScreenSelectMusic.cpp index 5f3f015a7a..c1a797a2e2 100644 --- a/stepmania/src/ScreenSelectMusic.cpp +++ b/stepmania/src/ScreenSelectMusic.cpp @@ -321,7 +321,7 @@ void ScreenSelectMusic::Input( const InputEventPlus &input ) // TODO: Invalidate the CurSteps only if they are no longer playable. That way, // after music change will clamp to the nearest in the DifficultyList. FOREACH_ENUM( PlayerNumber, p ) - GAMESTATE->m_pCurSteps[p].Set( NULL ); + GAMESTATE->m_pCurSteps[p].SetWithoutBroadcast( NULL ); AfterMusicChange(); diff --git a/stepmania/src/SongUtil.cpp b/stepmania/src/SongUtil.cpp index 7e1c548c20..df5bfb31bb 100644 --- a/stepmania/src/SongUtil.cpp +++ b/stepmania/src/SongUtil.cpp @@ -51,7 +51,7 @@ bool SongCriteria::Matches( const Song *pSong ) const return false; } - if( m_iMaxStagesForSong != -1 && GAMESTATE->GetNumStagesForSong(pSong) > m_iMaxStagesForSong ) + if( m_iMaxStagesForSong != -1 && GAMESTATE->GetNumStagesMultiplierForSong(pSong) > m_iMaxStagesForSong ) return false; switch( m_Tutorial ) @@ -812,7 +812,7 @@ void SongUtil::FilterSongs( const SongCriteria &sc, const vector &in, vec } } -static void GetPlayableStepsTypes( set &vOut ) +static void GetPlayableStepsTypes( const Song *pSong, set &vOut ) { vector vpPossibleStyles; if( CommonMetrics::AUTO_SET_STYLE ) @@ -823,11 +823,16 @@ static void GetPlayableStepsTypes( set &vOut ) vOut.insert( (*s)->m_StepsType ); // filter out hidden StepsTypes + // remove steps that we don't have enough stages left to play const vector &vstToShow = CommonMetrics::STEPS_TYPES_TO_SHOW.GetValue(); FOREACHS( StepsType, vOut, st ) { - bool bShowThis = find( vstToShow.begin(), vstToShow.end(), *st ) != vstToShow.end(); - if( !bShowThis ) + bool bShowThisStepsType = find( vstToShow.begin(), vstToShow.end(), *st ) != vstToShow.end(); + + const Style *pStyle = GAMEMAN->GetFirstCompatibleStyle( GAMESTATE->m_pCurGame, GAMESTATE->GetNumPlayersEnabled(), *st ); + bool bEnoughStages = GAMESTATE->GetNumStagesLeft() >= GAMESTATE->GetNumStagesForSongAndStyle(pSong,pStyle); + + if( !bShowThisStepsType || !bEnoughStages ) { set::iterator to_erase = st; ++st; @@ -840,7 +845,7 @@ static void GetPlayableStepsTypes( set &vOut ) void SongUtil::GetPlayableSteps( const Song *pSong, vector &vOut ) { set vStepsType; - GetPlayableStepsTypes( vStepsType ); + GetPlayableStepsTypes( pSong, vStepsType ); FOREACHS( StepsType, vStepsType, st ) SongUtil::GetSteps( pSong, vOut, *st ); @@ -848,25 +853,23 @@ void SongUtil::GetPlayableSteps( const Song *pSong, vector &vOut ) StepsUtil::RemoveLockedSteps( pSong, vOut ); StepsUtil::SortNotesArrayByDifficulty( vOut ); StepsUtil::SortStepsByTypeAndDifficulty( vOut ); - - // remove steps that we don't have enough stages left to play - for( int i=vOut.size()-1; i>=0; i-- ) - { - Steps *pSteps = vOut[i]; - StepsType st = pSteps->m_StepsType; - const Style *pStyle = GAMEMAN->GetFirstCompatibleStyle( GAMESTATE->m_pCurGame, GAMESTATE->GetNumPlayersEnabled(), st ); - if( GAMESTATE->GetNumStagesForSongAndStyle(pSong,pStyle) > GAMESTATE->GetNumStagesLeft() ) - vOut.erase( vOut.begin() + i ); - } } -bool SongUtil::IsStepsTypePlayable( StepsType st ) +bool SongUtil::IsStepsTypePlayable( Song *pSong, StepsType st ) { + void GetPlayableSteps( const Song *pSong, vector &vOut ); set vStepsType; - GetPlayableStepsTypes( vStepsType ); + GetPlayableStepsTypes( pSong, vStepsType ); return vStepsType.find( st ) != vStepsType.end(); } +bool SongUtil::IsStepsPlayable( Song *pSong, Steps *pSteps ) +{ + vector vpSteps; + GetPlayableSteps( pSong, vpSteps ); + return find( vpSteps.begin(), vpSteps.end(), pSteps ) != vpSteps.end(); +} + ////////////////////////////////// // SongID ////////////////////////////////// @@ -927,8 +930,17 @@ namespace { int IsStepsTypePlayable( lua_State *L ) { - StepsType st = Enum::Check(L, 1); - bool b = SongUtil::IsStepsTypePlayable( st ); + Song *pSong = Luna::check( L, 1, true ); + StepsType st = Enum::Check(L, 2); + bool b = SongUtil::IsStepsTypePlayable( pSong, st ); + LuaHelpers::Push( L, b ); + return 1; + } + int IsStepsPlayable( lua_State *L ) + { + Song *pSong = Luna::check( L, 1, true ); + Steps *pSteps = Luna::check( L, 2, true ); + bool b = SongUtil::IsStepsPlayable( pSong, pSteps ); LuaHelpers::Push( L, b ); return 1; } @@ -936,6 +948,7 @@ namespace const luaL_Reg SongUtilTable[] = { LIST_METHOD( IsStepsTypePlayable ), + LIST_METHOD( IsStepsPlayable ), { NULL, NULL } }; } diff --git a/stepmania/src/SongUtil.h b/stepmania/src/SongUtil.h index 2a2f1e6178..f109fff905 100644 --- a/stepmania/src/SongUtil.h +++ b/stepmania/src/SongUtil.h @@ -111,7 +111,8 @@ namespace SongUtil void FilterSongs( const SongCriteria &sc, const vector &in, vector &out ); void GetPlayableSteps( const Song *pSong, vector &vOut ); - bool IsStepsTypePlayable( StepsType st ); + bool IsStepsTypePlayable( Song *pSong, StepsType st ); + bool IsStepsPlayable( Song *pSong, Steps *pSteps ); } class SongID