diff --git a/stepmania/src/ScreenGameplay.cpp b/stepmania/src/ScreenGameplay.cpp index ebc0863955..853313ccee 100644 --- a/stepmania/src/ScreenGameplay.cpp +++ b/stepmania/src/ScreenGameplay.cpp @@ -1514,27 +1514,7 @@ void ScreenGameplay::Update( float fDeltaTime ) if( GAMESTATE->m_SongOptions.GetCurrent().m_fHaste != 0.0f ) { - float fLife = 0; - FOREACH_EnabledPlayerInfo( m_vPlayerInfo, pi ) - { - if( !GAMESTATE->IsHumanPlayer(pi->m_pn) ) - continue; - fLife = max( fLife, pi->m_pLifeMeter->GetLife() ); - } - - /* Scale the music nonlinearly. Only slow the song down below 0.25, so we - * don't drag the music out too long. Stick at 1x up to 0.5, so we start - * at 1x if the life meter defaults to 0.5. Increase gradually up to 0.9. - * Accelerate sharply above 0.9. */ - float fSpeed = 1.0f; - if( fLife < 0.25f ) - fSpeed = SCALE( fLife, 0.0f, 0.25f, 0.5f, 1.0f ); - else if( fLife > 0.5f && fLife < 0.9f ) - fSpeed = SCALE( fLife, 0.5f, 0.9f, 1.0f, 1.25f ); - else if( fLife >= 0.9f ) - fSpeed = SCALE( fLife, 0.9f, 1.0f, 1.25f, 2.5f ); - - fSpeed *= GAMESTATE->m_SongOptions.GetCurrent().m_fHaste; + float fSpeed = GetHasteRate(); fSpeed *= GAMESTATE->m_SongOptions.GetCurrent().m_fMusicRate; RageSoundParams p = m_pSoundMusic->GetParams(); @@ -1634,8 +1614,16 @@ void ScreenGameplay::Update( float fDeltaTime ) // update fGameplaySeconds STATSMAN->m_CurStageStats.m_fGameplaySeconds += fUnscaledDeltaTime; if( GAMESTATE->m_fSongBeat >= GAMESTATE->m_pCurSong->m_fFirstBeat && GAMESTATE->m_fSongBeat < GAMESTATE->m_pCurSong->m_fLastBeat ) + { STATSMAN->m_CurStageStats.m_fStepsSeconds += fUnscaledDeltaTime; + if( GAMESTATE->m_SongOptions.GetCurrent().m_fHaste != 0.0f ) + { + float fHasteRate = GetHasteRate(); + STATSMAN->m_CurStageStats.m_fAccumulatedHaste += (fUnscaledDeltaTime * fHasteRate) - fUnscaledDeltaTime; + } + } + // // Check for end of song // @@ -1790,6 +1778,40 @@ void ScreenGameplay::Update( float fDeltaTime ) } } +float ScreenGameplay::GetHasteRate() +{ + float fLife = 0; + FOREACH_EnabledPlayerInfo( m_vPlayerInfo, pi ) + { + if( !GAMESTATE->IsHumanPlayer(pi->m_pn) ) + continue; + fLife = max( fLife, pi->m_pLifeMeter->GetLife() ); + } + + /* Scale the music nonlinearly. Only slow the song down below 0.25, so we + * don't drag the music out too long. Stick at 1x up to 0.5, so we start + * at 1x if the life meter defaults to 0.5. Increase gradually up to 0.9. + * Accelerate sharply above 0.9. */ + float fSpeed = 1.0f; + if( fLife < 0.25f ) + fSpeed = SCALE( fLife, 0.0f, 0.25f, 0.5f, 1.0f ); + else if( fLife > 0.5f && fLife < 0.9f ) + fSpeed = SCALE( fLife, 0.5f, 0.9f, 1.0f, 1.25f ); + else if( fLife >= 0.9f ) + fSpeed = SCALE( fLife, 0.9f, 1.0f, 1.25f, 2.5f ); + fSpeed *= GAMESTATE->m_SongOptions.GetCurrent().m_fHaste; + + if( STATSMAN->m_CurStageStats.m_fAccumulatedHaste <= 1 ) + { + /* Only allow slowing down the song while the players have accumulated + * haste. This prevents dragging on the song by keeping the life meter + * nearly empty. */ + float fClamped = max( 1.0f, fSpeed ); + fSpeed = lerp( STATSMAN->m_CurStageStats.m_fAccumulatedHaste, fClamped, fSpeed ); + } + return fSpeed; +} + void ScreenGameplay::UpdateLights() { if( !LIGHTSMAN->IsEnabled() ) diff --git a/stepmania/src/ScreenGameplay.h b/stepmania/src/ScreenGameplay.h index 93824ee9c1..b520e4fc6b 100644 --- a/stepmania/src/ScreenGameplay.h +++ b/stepmania/src/ScreenGameplay.h @@ -159,6 +159,7 @@ protected: void UpdateLights(); void SendCrossedMessages(); void BeginBackingOutFromGameplay(); + float GetHasteRate(); void PlayTicks(); void UpdateSongPosition( float fDeltaTime ); diff --git a/stepmania/src/StageStats.cpp b/stepmania/src/StageStats.cpp index 85c90860ee..9aa5b9322d 100644 --- a/stepmania/src/StageStats.cpp +++ b/stepmania/src/StageStats.cpp @@ -28,6 +28,7 @@ StageStats::StageStats() m_fGameplaySeconds = 0; m_fStepsSeconds = 0; m_fMusicRate = 1; + m_fAccumulatedHaste = 0; } void StageStats::Init() diff --git a/stepmania/src/StageStats.h b/stepmania/src/StageStats.h index 7284afaed2..a64ed00d7b 100644 --- a/stepmania/src/StageStats.h +++ b/stepmania/src/StageStats.h @@ -41,6 +41,8 @@ public: float m_fStepsSeconds; // this is <= fGameplaySeconds unless the song has steps past the end float m_fMusicRate; + float m_fAccumulatedHaste; + // Total number of seconds between first beat and last beat for every song. float GetTotalPossibleStepsSeconds() const;