diff --git a/stepmania/src/ModeChoice.cpp b/stepmania/src/ModeChoice.cpp index 05bb65c874..0ae51b4ecf 100644 --- a/stepmania/src/ModeChoice.cpp +++ b/stepmania/src/ModeChoice.cpp @@ -219,6 +219,21 @@ void ModeChoice::Load( int iIndex, CString sChoice ) } int GetSidesRequiredToPlayStyle( Style style ) +{ + switch( GAMEMAN->GetStyleDefForStyle(style)->m_StyleType ) + { + case StyleDef::ONE_PLAYER_ONE_CREDIT: + return 1; + case StyleDef::TWO_PLAYERS_TWO_CREDITS: + case StyleDef::ONE_PLAYER_TWO_CREDITS: + return 2; + default: + ASSERT(0); + return 1; + } +} + +int GetCreditsRequiredToPlayStyle( Style style ) { switch( GAMEMAN->GetStyleDefForStyle(style)->m_StyleType ) { @@ -270,9 +285,20 @@ bool ModeChoice::IsPlayable( CString *why ) const if ( m_style != STYLE_INVALID ) { int iNumSidesJoined = GAMESTATE->GetNumSidesJoined(); + int iCredits = GAMESTATE->m_iCoins / PREFSMAN->m_iCoinsPerCredit; + int iNumSidesPlusCredits = iNumSidesJoined + iCredits; + CLAMP( iNumSidesPlusCredits, 0, NUM_PLAYERS ); + if( PREFSMAN->m_iCoinMode != COIN_PAY ) + iNumSidesPlusCredits = NUM_PLAYERS; + int iNumSidesRequired = GetSidesRequiredToPlayStyle(m_style); + int iNumCreditsRequired = GetCreditsRequiredToPlayStyle(m_style); - if( iNumSidesRequired != iNumSidesJoined ) + bool bPlayable = iNumSidesJoined == iNumSidesRequired; + if( PREFSMAN->m_bDelayedCreditsReconcile ) + bPlayable |= iNumSidesJoined < iNumSidesRequired && iNumSidesPlusCredits >= iNumCreditsRequired; + + if( !bPlayable ) { if( why ) *why = ssprintf( "need %i sides, have %i", iNumSidesRequired, iNumSidesJoined ); @@ -349,6 +375,16 @@ void ModeChoice::Apply( PlayerNumber pn ) const { GAMESTATE->m_CurStyle = m_style; + // It's possible to choose a style that didn't have enough + // players joined. If enough players aren't joined, then + // we need to subtract credits for the sides that will be + // joined as a result of applying this option. + int iNumCreditsRequired = GetCreditsRequiredToPlayStyle(m_style); + int iNumCreditsPaid = GAMESTATE->GetNumSidesJoined(); + int iNumCreditsOwed = iNumCreditsRequired - iNumCreditsPaid; + GAMESTATE->m_iCoins -= iNumCreditsOwed * PREFSMAN->m_iCoinsPerCredit; + + // If only one side is joined and we picked a style // that requires both sides, join the other side. switch( GAMEMAN->GetStyleDefForStyle(m_style)->m_StyleType ) @@ -357,9 +393,10 @@ void ModeChoice::Apply( PlayerNumber pn ) const break; case StyleDef::TWO_PLAYERS_TWO_CREDITS: case StyleDef::ONE_PLAYER_TWO_CREDITS: - int p; - for( p=0; pm_bSideIsJoined[p] = true; + { + FOREACH_PlayerNumber( p ) + GAMESTATE->m_bSideIsJoined[p] = true; + } break; default: ASSERT(0); diff --git a/stepmania/src/PrefsManager.cpp b/stepmania/src/PrefsManager.cpp index bde5769b5e..7de5ca087f 100644 --- a/stepmania/src/PrefsManager.cpp +++ b/stepmania/src/PrefsManager.cpp @@ -157,6 +157,7 @@ PrefsManager::PrefsManager() m_iCoinMode = COIN_HOME; m_iCoinsPerCredit = 1; m_Premium = NO_PREMIUM; + m_bDelayedCreditsReconcile = false; m_iBoostAppPriority = -1; m_bSmoothLines = false; m_ShowSongOptions = YES; @@ -432,6 +433,7 @@ void PrefsManager::ReadGlobalPrefsFromDisk() ini.GetValue( "Options", "CoinMode", m_iCoinMode ); ini.GetValue( "Options", "CoinsPerCredit", m_iCoinsPerCredit ); ini.GetValue( "Options", "Premium", (int&)m_Premium ); + ini.GetValue( "Options", "DelayedCreditsReconcile", m_bDelayedCreditsReconcile ); ini.GetValue( "Options", "BoostAppPriority", m_iBoostAppPriority ); ini.GetValue( "Options", "PickExtraStage", m_bPickExtraStage ); ini.GetValue( "Options", "ComboContinuesBetweenSongs", m_bComboContinuesBetweenSongs ); @@ -655,6 +657,7 @@ void PrefsManager::SaveGlobalPrefsToDisk() const ini.SetValue( "Options", "CoinMode", m_iCoinMode ); ini.SetValue( "Options", "CoinsPerCredit", m_iCoinsPerCredit ); ini.SetValue( "Options", "Premium", m_Premium ); + ini.SetValue( "Options", "DelayedCreditsReconcile", m_bDelayedCreditsReconcile ); ini.SetValue( "Options", "BoostAppPriority", m_iBoostAppPriority ); ini.SetValue( "Options", "PickExtraStage", m_bPickExtraStage ); ini.SetValue( "Options", "ComboContinuesBetweenSongs", m_bComboContinuesBetweenSongs ); diff --git a/stepmania/src/PrefsManager.h b/stepmania/src/PrefsManager.h index f5024ce92d..6945935f78 100644 --- a/stepmania/src/PrefsManager.h +++ b/stepmania/src/PrefsManager.h @@ -147,6 +147,7 @@ public: int m_iCoinsPerCredit; enum Premium { NO_PREMIUM, DOUBLES_PREMIUM, JOINT_PREMIUM }; Premium m_Premium; + bool m_bDelayedCreditsReconcile; bool m_bPickExtraStage; bool m_bComboContinuesBetweenSongs; float m_fLongVerSongSeconds; diff --git a/stepmania/src/ScreenSelect.cpp b/stepmania/src/ScreenSelect.cpp index 67e23b01b3..7b43aaea1c 100644 --- a/stepmania/src/ScreenSelect.cpp +++ b/stepmania/src/ScreenSelect.cpp @@ -144,7 +144,8 @@ void ScreenSelect::Input( const DeviceInput& DeviceI, const InputEventType type, { // LOG->Trace( "ScreenSelect::Input()" ); - if( Screen::JoinInput(DeviceI, type, GameI, MenuI, StyleI) ) + if( MenuI.button == MENU_BUTTON_COIN || + Screen::JoinInput(DeviceI, type, GameI, MenuI, StyleI) ) { this->UpdateSelectableChoices(); return; // don't let the screen handle the MENU_START press