diff --git a/stepmania/src/GameState.cpp b/stepmania/src/GameState.cpp index 2560f8147d..5d6c2ee165 100644 --- a/stepmania/src/GameState.cpp +++ b/stepmania/src/GameState.cpp @@ -252,7 +252,11 @@ void GameState::Reset() m_bJukeboxUsesModifiers = false; m_iCurrentStageIndex = 0; FOREACH_PlayerNumber( p ) - m_iPlayerCurrentStageIndexForCurrentCredit[p] = 0; + { + m_iPlayerStageTokens[p] = 0; + m_iAwardedExtraStages[p] = 0; + } + m_bGameplayLeadIn.Set( false ); m_iNumStagesOfThisSong = 0; m_bLoadingNextSong = false; @@ -324,7 +328,7 @@ void GameState::Reset() void GameState::JoinPlayer( PlayerNumber pn ) { m_bSideIsJoined[pn] = true; - m_iPlayerCurrentStageIndexForCurrentCredit[pn] = 0; + m_iPlayerStageTokens[pn] = PREFSMAN->m_iSongsPerPlay; if( m_MasterPlayerNumber == PLAYER_INVALID ) m_MasterPlayerNumber = pn; @@ -356,7 +360,7 @@ void GameState::UnjoinPlayer( PlayerNumber pn ) PROFILEMAN->UnloadProfile( pn ); m_bSideIsJoined[pn] = false; - m_iPlayerCurrentStageIndexForCurrentCredit[pn] = 0; + m_iPlayerStageTokens[pn] = 0; if( m_MasterPlayerNumber == pn ) m_MasterPlayerNumber = GAMESTATE->GetFirstHumanPlayer(); @@ -581,15 +585,6 @@ int GameState::GetNumStagesForCurrentSongAndStepsOrCourse() ASSERT( iNumStagesOfThisSong >= 1 && iNumStagesOfThisSong <= 3 ); - /* Never increment more than one past final stage. That is, if the current - * stage is the final stage, and we picked a stage that takes two songs, it - * only counts as one stage (so it doesn't bump us all the way to Ex2). - * One case where this happens is a long/marathon extra stage. Another is - * if a long/marathon song is selected explicitly in the theme with a GameCommand, - * and PREFSMAN->m_iNumArcadeStages is less than the number of stages that - * song takes. */ - int iNumStagesLeft = GAMESTATE->GetSmallestNumStagesLeftForAnyHumanPlayer(); - iNumStagesOfThisSong = min( iNumStagesOfThisSong, iNumStagesLeft ); iNumStagesOfThisSong = max( iNumStagesOfThisSong, 1 ); return iNumStagesOfThisSong; @@ -619,10 +614,16 @@ void GameState::BeginStage() STATSMAN->m_CurStageStats.m_fMusicRate = m_SongOptions.GetSong().m_fMusicRate; m_iNumStagesOfThisSong = GetNumStagesForCurrentSongAndStepsOrCourse(); ASSERT( m_iNumStagesOfThisSong != -1 ); + LOG->Trace( "BeginStage: sub %i (%i) (ex %i)", + m_iNumStagesOfThisSong, m_iPlayerStageTokens[0], m_iAwardedExtraStages[0] ); + FOREACH_EnabledPlayer( p ) + m_iPlayerStageTokens[p] -= m_iNumStagesOfThisSong; } void GameState::CancelStage() { + FOREACH_EnabledPlayer( p ) + m_iPlayerStageTokens[p] += m_iNumStagesOfThisSong; m_iNumStagesOfThisSong = 0; ResetStageStatistics(); } @@ -670,14 +671,25 @@ void GameState::FinishStage() const int iOldStageIndex = m_iCurrentStageIndex; ++m_iCurrentStageIndex; - FOREACH_EnabledPlayer( p ) - m_iPlayerCurrentStageIndexForCurrentCredit[p] += m_iNumStagesOfThisSong; m_iNumStagesOfThisSong = 0; // necessary so that bGaveUp is reset ResetStageStatistics(); + if( HasEarnedExtraStage() ) + { + LOG->Trace( "awarded extra stage" ); + FOREACH_HumanPlayer( p ) + { + if( m_iAwardedExtraStages[p] < 2 ) + { + ++m_iAwardedExtraStages[p]; + ++m_iPlayerStageTokens[p]; + } + } + } + if( m_bDemonstrationOrJukebox ) return; @@ -849,71 +861,34 @@ float GameState::GetSongPercent( float beat ) const return (beat - m_pCurSong->m_fFirstBeat) / m_pCurSong->m_fLastBeat; } -int GameState::GetLargestCurrentStageIndexForAnyHumanPlayer() const -{ - int iLargest = INT_MIN; - FOREACH_HumanPlayer( p ) - iLargest = max( iLargest, m_iPlayerCurrentStageIndexForCurrentCredit[p] ); - return iLargest; -} - int GameState::GetNumStagesLeft( PlayerNumber pn ) const { - return PREFSMAN->m_iSongsPerPlay - m_iPlayerCurrentStageIndexForCurrentCredit[pn]; + return m_iPlayerStageTokens[pn]; } int GameState::GetSmallestNumStagesLeftForAnyHumanPlayer() const { - if( IsAnExtraStage() ) - return 1; if( IsEventMode() ) return 999; int iSmallest = INT_MAX; FOREACH_HumanPlayer( p ) - iSmallest = min( iSmallest, GetNumStagesLeft(p) ); + iSmallest = min( iSmallest, m_iPlayerStageTokens[p] ); return iSmallest; } -int GameState::GetLargestNumStagesLeftForAnyHumanPlayer() const -{ - if( IsAnExtraStage() ) - return 1; - if( IsEventMode() ) - return 999; - int iLargest = INT_MIN; - FOREACH_HumanPlayer( p ) - iLargest = max( iLargest, GetNumStagesLeft(p) ); - return iLargest; -} - -bool GameState::IsFinalStage() const -{ - if( IsEventMode() ) - return false; - - if( IsCourseMode() ) - return true; - - /* This changes dynamically on ScreenSelectMusic as the wheel turns. */ - int iPredictedStageForCurSong = GetNumStagesForCurrentSongAndStepsOrCourse(); - if( iPredictedStageForCurSong == -1 ) - iPredictedStageForCurSong = 1; - return GetLargestCurrentStageIndexForAnyHumanPlayer() + iPredictedStageForCurSong == PREFSMAN->m_iSongsPerPlay; -} - bool GameState::IsAnExtraStage() const { - return !IsEventMode() && !IsCourseMode() && GetLargestCurrentStageIndexForAnyHumanPlayer() >= PREFSMAN->m_iSongsPerPlay; + return !IsEventMode() && !IsCourseMode() && m_iAwardedExtraStages[m_MasterPlayerNumber] > 0; } bool GameState::IsExtraStage() const { - return !IsEventMode() && !IsCourseMode() && GetLargestCurrentStageIndexForAnyHumanPlayer() == PREFSMAN->m_iSongsPerPlay; + return !IsEventMode() && !IsCourseMode() && m_iAwardedExtraStages[m_MasterPlayerNumber] == 1; } bool GameState::IsExtraStage2() const { - return !IsEventMode() && !IsCourseMode() && GetLargestCurrentStageIndexForAnyHumanPlayer() == PREFSMAN->m_iSongsPerPlay+1; + return !IsEventMode() && !IsCourseMode() && m_iAwardedExtraStages[m_MasterPlayerNumber] == 2; } Stage GameState::GetCurrentStage() const @@ -1148,7 +1123,10 @@ bool GameState::HasEarnedExtraStage() const if( m_bBackedOutOfFinalStage ) return false; - if( !IsFinalStage() && !IsExtraStage() ) + if( GetSmallestNumStagesLeftForAnyHumanPlayer() > 0 ) + return false; + + if( m_iAwardedExtraStages[m_MasterPlayerNumber] >= 2 ) return false; FOREACH_EnabledPlayer( pn ) @@ -1360,7 +1338,7 @@ SongOptions::FailType GameState::GetPlayerFailType( const PlayerState *pPlayerSt bool bFirstStageForAny = !IsEventMode(); FOREACH_HumanPlayer( p ) - bFirstStageForAny |= m_iPlayerCurrentStageIndexForCurrentCredit[p] == 0; + bFirstStageForAny |= m_iPlayerStageTokens[p] == PREFSMAN->m_iSongsPerPlay; // HACK /* Easy and beginner are never harder than FAIL_IMMEDIATE_CONTINUE. */ if( dc <= Difficulty_Easy ) @@ -2124,7 +2102,7 @@ public: DEFINE_METHOD( PlayerIsUsingModifier, PlayerIsUsingModifier(Enum::Check(L, 1), SArg(2)) ) DEFINE_METHOD( GetCourseSongIndex, GetCourseSongIndex() ) DEFINE_METHOD( GetLoadingCourseSongIndex, GetLoadingCourseSongIndex() ) - DEFINE_METHOD( IsFinalStage, IsFinalStage() ) + DEFINE_METHOD( GetSmallestNumStagesLeftForAnyHumanPlayer, GetSmallestNumStagesLeftForAnyHumanPlayer() ) DEFINE_METHOD( IsAnExtraStage, IsAnExtraStage() ) DEFINE_METHOD( IsExtraStage, IsExtraStage() ) DEFINE_METHOD( IsExtraStage2, IsExtraStage2() ) @@ -2292,7 +2270,7 @@ public: ADD_METHOD( PlayerIsUsingModifier ); ADD_METHOD( GetCourseSongIndex ); ADD_METHOD( GetLoadingCourseSongIndex ); - ADD_METHOD( IsFinalStage ); + ADD_METHOD( GetSmallestNumStagesLeftForAnyHumanPlayer ); ADD_METHOD( IsAnExtraStage ); ADD_METHOD( IsExtraStage ); ADD_METHOD( IsExtraStage2 ); diff --git a/stepmania/src/GameState.h b/stepmania/src/GameState.h index 90e78aa6b9..ecfb4bff4f 100644 --- a/stepmania/src/GameState.h +++ b/stepmania/src/GameState.h @@ -123,8 +123,9 @@ public: int m_iNumStagesOfThisSong; // Increases every stage, doesn't reset when player continues. It's cosmetic and not used in Stage or Screen branching logic. int m_iCurrentStageIndex; - // Num stages played since player joined or conintues by using a credit. Increases every stage if the player is joined. Resets when player joins/continues. - int m_iPlayerCurrentStageIndexForCurrentCredit[NUM_PLAYERS]; + // Num stages available for player. Resets when player joins/continues. + int m_iPlayerStageTokens[NUM_PLAYERS]; + int m_iAwardedExtraStages[NUM_PLAYERS]; static int GetNumStagesMultiplierForSong( const Song* pSong ); static int GetNumStagesForSongAndStyleType( const Song* pSong, StyleType st ); @@ -134,11 +135,8 @@ public: void CancelStage(); void CommitStageStats(); void FinishStage(); - int GetLargestCurrentStageIndexForAnyHumanPlayer() const; int GetNumStagesLeft( PlayerNumber pn ) const; int GetSmallestNumStagesLeftForAnyHumanPlayer() const; - int GetLargestNumStagesLeftForAnyHumanPlayer() const; - bool IsFinalStage() const; bool IsAnExtraStage() const; bool IsExtraStage() const; bool IsExtraStage2() const; diff --git a/stepmania/src/ScreenContinue.cpp b/stepmania/src/ScreenContinue.cpp index abee503402..8bd6aa3770 100644 --- a/stepmania/src/ScreenContinue.cpp +++ b/stepmania/src/ScreenContinue.cpp @@ -39,7 +39,7 @@ void ScreenContinue::BeginScreen() // unjoin all players with 0 stages left FOREACH_HumanPlayer( p ) { - bool bPlayerDone = GAMESTATE->m_iPlayerCurrentStageIndexForCurrentCredit[p] >= PREFSMAN->m_iSongsPerPlay; + bool bPlayerDone = GAMESTATE->m_iPlayerStageTokens[p] <= 0; if( !STATSMAN->m_vPlayedStageStats.empty() ) { const StageStats &ss = STATSMAN->m_vPlayedStageStats.back(); diff --git a/stepmania/src/ScreenEnding.cpp b/stepmania/src/ScreenEnding.cpp index 1859da5bd2..2b06af6810 100644 --- a/stepmania/src/ScreenEnding.cpp +++ b/stepmania/src/ScreenEnding.cpp @@ -43,7 +43,7 @@ ScreenEnding::ScreenEnding() : ScreenAttract( false/*dont reset GAMESTATE*/ ) PO_GROUP_ASSIGN( GAMESTATE->m_pPlayerState[PLAYER_2]->m_PlayerOptions, ModsLevel_Stage, m_fScrollSpeed, 2.0f ); GAMESTATE->m_iCurrentStageIndex = 0; FOREACH_ENUM( PlayerNumber, p ) - GAMESTATE->m_iPlayerCurrentStageIndexForCurrentCredit[p] = 0; + GAMESTATE->m_iPlayerStageTokens[p] = 1; PO_GROUP_CALL( GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions, ModsLevel_Stage, ChooseRandomModifiers ); PO_GROUP_CALL( GAMESTATE->m_pPlayerState[PLAYER_2]->m_PlayerOptions, ModsLevel_Stage, ChooseRandomModifiers ); diff --git a/stepmania/src/ScreenEvaluation.cpp b/stepmania/src/ScreenEvaluation.cpp index 7f2fa4d984..2e99c40c31 100644 --- a/stepmania/src/ScreenEvaluation.cpp +++ b/stepmania/src/ScreenEvaluation.cpp @@ -102,7 +102,7 @@ ScreenEvaluation::ScreenEvaluation() GAMESTATE->m_pCurCourse.Set( SONGMAN->GetRandomCourse() ); GAMESTATE->m_iCurrentStageIndex = 0; FOREACH_ENUM( PlayerNumber, p ) - GAMESTATE->m_iPlayerCurrentStageIndexForCurrentCredit[p] = 0; + GAMESTATE->m_iPlayerStageTokens[p] = 1; FOREACH_PlayerNumber( p ) { @@ -656,7 +656,7 @@ void ScreenEvaluation::Init() best_grade = min( best_grade, grade[p] ); if( PREFSMAN->m_bAllowExtraStage && - GAMESTATE->HasEarnedExtraStage() && + GAMESTATE->IsAnExtraStage() && !GAMESTATE->IsCourseMode() && !SUMMARY ) { diff --git a/stepmania/src/ScreenGameplay.cpp b/stepmania/src/ScreenGameplay.cpp index 81281d0355..b764d26d63 100644 --- a/stepmania/src/ScreenGameplay.cpp +++ b/stepmania/src/ScreenGameplay.cpp @@ -1999,7 +1999,7 @@ void ScreenGameplay::BeginBackingOutFromGameplay() this->ClearMessageQueue(); // If this is the final stage, don't allow extra stage - if( GAMESTATE->IsFinalStage() ) + if( GAMESTATE->GetSmallestNumStagesLeftForAnyHumanPlayer() == 0 ) GAMESTATE->m_bBackedOutOfFinalStage = true; // Disallow backing out of extra stage if( GAMESTATE->IsAnExtraStage() ) @@ -2270,7 +2270,7 @@ void ScreenGameplay::HandleScreenMessage( const ScreenMessage SM ) { if( GAMESTATE->IsAnExtraStage() ) SOUND->PlayOnceFromAnnouncer( "gameplay here we go extra" ); - else if( GAMESTATE->IsFinalStage() ) + else if( GAMESTATE->GetSmallestNumStagesLeftForAnyHumanPlayer() == 0 ) SOUND->PlayOnceFromAnnouncer( "gameplay here we go final" ); else SOUND->PlayOnceFromAnnouncer( "gameplay here we go normal" ); diff --git a/stepmania/src/ScreenGameplayLesson.cpp b/stepmania/src/ScreenGameplayLesson.cpp index 5ba722c5f1..84bbd624e4 100644 --- a/stepmania/src/ScreenGameplayLesson.cpp +++ b/stepmania/src/ScreenGameplayLesson.cpp @@ -58,7 +58,7 @@ void ScreenGameplayLesson::Init() // Reset stage number (not relevant in lessons) GAMESTATE->m_iCurrentStageIndex = 0; FOREACH_ENUM( PlayerNumber, p ) - GAMESTATE->m_iPlayerCurrentStageIndexForCurrentCredit[p] = 0; + GAMESTATE->m_iPlayerStageTokens[p] = 1; // Autoplay during demonstration FOREACH_EnabledPlayerInfo( m_vPlayerInfo, pi ) diff --git a/stepmania/src/ScreenNameEntryTraditional.cpp b/stepmania/src/ScreenNameEntryTraditional.cpp index 96e431fe38..81b6b467c8 100644 --- a/stepmania/src/ScreenNameEntryTraditional.cpp +++ b/stepmania/src/ScreenNameEntryTraditional.cpp @@ -79,7 +79,7 @@ void ScreenNameEntryTraditional::BeginScreen() vector aFeats; GAMESTATE->GetRankingFeats( pn, aFeats ); - bool bNoStagesLeft = GAMESTATE->m_iPlayerCurrentStageIndexForCurrentCredit[pn] >= PREFSMAN->m_iSongsPerPlay; + bool bNoStagesLeft = GAMESTATE->m_iPlayerStageTokens[pn] <= 0; m_bEnteringName[pn] = aFeats.size() > 0 && bNoStagesLeft; m_bFinalized[pn] = !m_bEnteringName[pn]; }