From 711726a8d6367484b6df829d279d76dbe92a5279 Mon Sep 17 00:00:00 2001 From: teejusb <5017202+teejusb@users.noreply.github.com> Date: Fri, 22 Oct 2021 17:01:41 -0700 Subject: [PATCH 1/9] Add player based visual delay to PlayerOptions --- src/PlayerOptions.cpp | 21 +++++++++++++++++++++ src/PlayerOptions.h | 4 ++++ 2 files changed, 25 insertions(+) diff --git a/src/PlayerOptions.cpp b/src/PlayerOptions.cpp index 193dab8abd..3389efc132 100644 --- a/src/PlayerOptions.cpp +++ b/src/PlayerOptions.cpp @@ -95,6 +95,7 @@ void PlayerOptions::Init() m_bZBuffer = false; m_bCosecant = false; m_sNoteSkin = ""; + m_fVisualDelay = 0.0f; ZERO( m_fMovesX ); ONE( m_SpeedfMovesX ); ZERO( m_fMovesY ); ONE( m_SpeedfMovesY ); ZERO( m_fMovesZ ); ONE( m_SpeedfMovesZ ); @@ -185,6 +186,7 @@ void PlayerOptions::Approach( const PlayerOptions& other, float fDeltaSeconds ) DO_COPY( m_FailType ); DO_COPY( m_MinTNSToHideNotes ); DO_COPY( m_sNoteSkin ); + DO_COPY( m_fVisualDelay ); #undef APPROACH #undef DO_COPY } @@ -555,6 +557,12 @@ void PlayerOptions::GetMods( vector &AddTo, bool bForceNoteSkin ) const Capitalize( s ); AddTo.push_back( s ); } + + if ( fabsf(m_fVisualDelay) > 0.0001f ) { + // Format the string to be something like "10ms VisualDelay". + // Note that we don't process sub-millisecond visual delay. + AddTo.push_back( ssprintf("%ldms VisualDelay")) ); + } } /* Options are added to the current settings; call Init() beforehand if @@ -599,6 +607,12 @@ bool PlayerOptions::FromOneModString( const RString &sOneMod, RString &sErrorOut { level = 0; } + else if ( EndsWith(s, "ms") ) + { + // Strip off the "ms" before parsing. + RString ms_value = s.substr( s.size()-2 ); + level = StringToFlot( ms_value ); + } else if( isdigit(s[0]) || s[0] == '-' ) { /* If the last character is a *, they probably said "123*" when @@ -1126,6 +1140,7 @@ bool PlayerOptions::FromOneModString( const RString &sOneMod, RString &sErrorOut } else if( sBit == "zbuffer" ) m_bZBuffer = on; else if( sBit == "cosecant" ) m_bCosecant = on; + else if( sBit == "visualdelay" ) m_fVisualDelay = level * 1.0f; // deprecated mods/left in for compatibility else if( sBit == "converge" ) SET_FLOAT( fScrolls[SCROLL_CENTERED] ) // end of the list @@ -1378,6 +1393,7 @@ bool PlayerOptions::operator==( const PlayerOptions &other ) const { return false; } + COMPARE(m_fVisualDelay); for( int i = 0; i < PlayerOptions::NUM_ACCELS; ++i ) COMPARE(m_fAccels[i]); for( int i = 0; i < PlayerOptions::NUM_EFFECTS; ++i ) @@ -1443,6 +1459,7 @@ PlayerOptions& PlayerOptions::operator=(PlayerOptions const& other) CPY(m_bDizzyHolds); CPY(m_bZBuffer); CPY(m_bCosecant); + CPY(m_fVisualDelay); CPY_SPEED(fDark); CPY_SPEED(fBlind); CPY_SPEED(fCover); @@ -1674,6 +1691,7 @@ RString PlayerOptions::GetSavedPrefsString() const SAVE( m_bTransforms[TRANSFORM_NOFAKES] ); SAVE( m_bMuteOnError ); SAVE( m_sNoteSkin ); + SAVE( m_fVisualDelay ); #undef SAVE return po_prefs.GetString(); } @@ -1721,6 +1739,7 @@ void PlayerOptions::ResetPrefs( ResetPrefsType type ) CPY( m_bTransforms[TRANSFORM_NOFAKES] ); // Don't clear this. // CPY( m_sNoteSkin ); + CPY(m_fVisualDelay); #undef CPY } @@ -1969,6 +1988,8 @@ public: ENUM_INTERFACE(FailSetting, FailType, FailType); ENUM_INTERFACE(MinTNSToHideNotes, MinTNSToHideNotes, TapNoteScore); + FLOAT_NO_SPEED_INTERFACE(VisualDelay, VisualDelay, true); + // NoteSkins static int NoteSkin(T* p, lua_State* L) { diff --git a/src/PlayerOptions.h b/src/PlayerOptions.h index 78c89da400..9413e379b3 100644 --- a/src/PlayerOptions.h +++ b/src/PlayerOptions.h @@ -87,6 +87,7 @@ public: m_MinTNSToHideNotes(PREFSMAN->m_MinTNSToHideNotes) { m_sNoteSkin = ""; + m_fVisualDelay = 0.0f; ZERO( m_fAccels ); ONE( m_SpeedfAccels ); ZERO( m_fEffects ); ONE( m_SpeedfEffects ); ZERO( m_fAppearances ); ONE( m_SpeedfAppearances ); @@ -394,6 +395,9 @@ public: * If an empty string, it means to not change from the default. */ RString m_sNoteSkin; + /** @brief The Visual Delay additionally applied on a per-player basis in ms. */ + int m_fVisualDelay; + void NextAccel(); void NextEffect(); void NextAppearance(); From e0abda3d24110ba9673f862529b26a3bc3473ffd Mon Sep 17 00:00:00 2001 From: teejusb <5017202+teejusb@users.noreply.github.com> Date: Fri, 22 Oct 2021 17:17:48 -0700 Subject: [PATCH 2/9] Make use of the m_fVisualDelay value --- src/GameState.cpp | 3 ++- src/SongPosition.cpp | 4 ++-- src/SongPosition.h | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/GameState.cpp b/src/GameState.cpp index 51852c9a51..148e8e0562 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -1271,7 +1271,8 @@ void GameState::UpdateSongPosition( float fPositionSeconds, const TimingData &ti { if( m_pCurSteps[pn] ) { - m_pPlayerState[pn]->m_Position.UpdateSongPosition( fPositionSeconds, *m_pCurSteps[pn]->GetTimingData(), timestamp ); + float fAdditionalVisualDelay = m_pPlayerState[pn]->m_PlayerOptions.GetPreferred().m_fVisualDelay; + m_pPlayerState[pn]->m_Position.UpdateSongPosition( fPositionSeconds, *m_pCurSteps[pn]->GetTimingData(), timestamp, fAdditionalVisualDelay ); Actor::SetPlayerBGMBeat( pn, m_pPlayerState[pn]->m_Position.m_fSongBeatVisible, m_pPlayerState[pn]->m_Position.m_fSongBeatNoOffset ); } } diff --git a/src/SongPosition.cpp b/src/SongPosition.cpp index 2668d0043a..4804bb29da 100644 --- a/src/SongPosition.cpp +++ b/src/SongPosition.cpp @@ -3,7 +3,7 @@ static Preference g_fVisualDelaySeconds( "VisualDelaySeconds", 0.0f ); -void SongPosition::UpdateSongPosition( float fPositionSeconds, const TimingData &timing, const RageTimer ×tamp ) +void SongPosition::UpdateSongPosition( float fPositionSeconds, const TimingData &timing, const RageTimer ×tamp, float fAdditionalVisualDelay ) { if( !timestamp.IsZero() ) @@ -31,7 +31,7 @@ void SongPosition::UpdateSongPosition( float fPositionSeconds, const TimingData m_fSongBeatNoOffset = timing.GetBeatFromElapsedTimeNoOffset( fPositionSeconds ); - m_fMusicSecondsVisible = fPositionSeconds - g_fVisualDelaySeconds.Get(); + m_fMusicSecondsVisible = fPositionSeconds - g_fVisualDelaySeconds.Get() - fAdditionalVisualDelay; beat_info.elapsed_time= m_fMusicSecondsVisible; timing.GetBeatAndBPSFromElapsedTime(beat_info); m_fSongBeatVisible= beat_info.beat; diff --git a/src/SongPosition.h b/src/SongPosition.h index 314629b702..fa8f39d57b 100644 --- a/src/SongPosition.h +++ b/src/SongPosition.h @@ -34,7 +34,7 @@ public: float m_fSongBeatVisible; void Reset(); - void UpdateSongPosition( float fPositionSeconds, const TimingData &timing, const RageTimer ×tamp = RageZeroTimer ); + void UpdateSongPosition( float fPositionSeconds, const TimingData &timing, const RageTimer ×tamp = RageZeroTimer, float fAdditionalVisualDelay = 0.0f ); // Lua void PushSelf( lua_State *L ); From b371a4d9c4a865b078467d67e88217e3f326b3ef Mon Sep 17 00:00:00 2001 From: teejusb <5017202+teejusb@users.noreply.github.com> Date: Fri, 22 Oct 2021 17:22:21 -0700 Subject: [PATCH 3/9] Fix typo in StringToFloat --- src/PlayerOptions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PlayerOptions.cpp b/src/PlayerOptions.cpp index 3389efc132..68d28b56a3 100644 --- a/src/PlayerOptions.cpp +++ b/src/PlayerOptions.cpp @@ -611,7 +611,7 @@ bool PlayerOptions::FromOneModString( const RString &sOneMod, RString &sErrorOut { // Strip off the "ms" before parsing. RString ms_value = s.substr( s.size()-2 ); - level = StringToFlot( ms_value ); + level = StringToFloat( ms_value ); } else if( isdigit(s[0]) || s[0] == '-' ) { From ef3b2142af1c59236fe114a30c91d48a576fba6d Mon Sep 17 00:00:00 2001 From: teejusb <5017202+teejusb@users.noreply.github.com> Date: Fri, 22 Oct 2021 17:28:48 -0700 Subject: [PATCH 4/9] Fix some brackets --- src/PlayerOptions.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/PlayerOptions.cpp b/src/PlayerOptions.cpp index 68d28b56a3..bfea99f970 100644 --- a/src/PlayerOptions.cpp +++ b/src/PlayerOptions.cpp @@ -558,10 +558,11 @@ void PlayerOptions::GetMods( vector &AddTo, bool bForceNoteSkin ) const AddTo.push_back( s ); } - if ( fabsf(m_fVisualDelay) > 0.0001f ) { + if ( fabsf(m_fVisualDelay) > 0.0001f ) + { // Format the string to be something like "10ms VisualDelay". // Note that we don't process sub-millisecond visual delay. - AddTo.push_back( ssprintf("%ldms VisualDelay")) ); + AddTo.push_back( ssprintf("%ldms VisualDelay") ); } } From 547b379765f8e78559cc31ff22a49ed155bf7e89 Mon Sep 17 00:00:00 2001 From: teejusb <5017202+teejusb@users.noreply.github.com> Date: Fri, 22 Oct 2021 18:18:15 -0700 Subject: [PATCH 5/9] Type and parsing fixes. --- src/PlayerOptions.cpp | 4 ++-- src/PlayerOptions.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/PlayerOptions.cpp b/src/PlayerOptions.cpp index bfea99f970..acc5ad1fa8 100644 --- a/src/PlayerOptions.cpp +++ b/src/PlayerOptions.cpp @@ -611,7 +611,7 @@ bool PlayerOptions::FromOneModString( const RString &sOneMod, RString &sErrorOut else if ( EndsWith(s, "ms") ) { // Strip off the "ms" before parsing. - RString ms_value = s.substr( s.size()-2 ); + RString ms_value = s.substr(0, s.size()-2 ); level = StringToFloat( ms_value ); } else if( isdigit(s[0]) || s[0] == '-' ) @@ -1141,7 +1141,7 @@ bool PlayerOptions::FromOneModString( const RString &sOneMod, RString &sErrorOut } else if( sBit == "zbuffer" ) m_bZBuffer = on; else if( sBit == "cosecant" ) m_bCosecant = on; - else if( sBit == "visualdelay" ) m_fVisualDelay = level * 1.0f; + else if( sBit == "visualdelay" ) m_fVisualDelay = level; // deprecated mods/left in for compatibility else if( sBit == "converge" ) SET_FLOAT( fScrolls[SCROLL_CENTERED] ) // end of the list diff --git a/src/PlayerOptions.h b/src/PlayerOptions.h index 9413e379b3..b2ea2931bf 100644 --- a/src/PlayerOptions.h +++ b/src/PlayerOptions.h @@ -396,7 +396,7 @@ public: RString m_sNoteSkin; /** @brief The Visual Delay additionally applied on a per-player basis in ms. */ - int m_fVisualDelay; + float m_fVisualDelay; void NextAccel(); void NextEffect(); From 6dc0ec5258c700096eadba793a131ce3ceea5748 Mon Sep 17 00:00:00 2001 From: teejusb <5017202+teejusb@users.noreply.github.com> Date: Fri, 22 Oct 2021 18:33:13 -0700 Subject: [PATCH 6/9] Woops, actually store the value of the visual delay. --- src/PlayerOptions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PlayerOptions.cpp b/src/PlayerOptions.cpp index acc5ad1fa8..1badc2c757 100644 --- a/src/PlayerOptions.cpp +++ b/src/PlayerOptions.cpp @@ -562,7 +562,7 @@ void PlayerOptions::GetMods( vector &AddTo, bool bForceNoteSkin ) const { // Format the string to be something like "10ms VisualDelay". // Note that we don't process sub-millisecond visual delay. - AddTo.push_back( ssprintf("%ldms VisualDelay") ); + AddTo.push_back( ssprintf("%.0fms VisualDelay", m_fVisualDelay) ); } } From 8edca26493aa28bcca11103460350e20ed387b1b Mon Sep 17 00:00:00 2001 From: teejusb <5017202+teejusb@users.noreply.github.com> Date: Fri, 22 Oct 2021 18:54:54 -0700 Subject: [PATCH 7/9] Always use PlayerState's own timing because of visual delay. --- src/PlayerState.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/PlayerState.cpp b/src/PlayerState.cpp index 5ed8c66210..5cef47dedb 100644 --- a/src/PlayerState.cpp +++ b/src/PlayerState.cpp @@ -196,9 +196,8 @@ int PlayerState::GetSumOfActiveAttackLevels() const const SongPosition &PlayerState::GetDisplayedPosition() const { - if( GAMESTATE->m_bIsUsingStepTiming ) - return m_Position; - return GAMESTATE->m_Position; + // Player state should always use its own timing because of custom Visual Delay options. + return m_Position; } const TimingData &PlayerState::GetDisplayedTiming() const From 02105d57ddede0003ba364337165b446261a06f8 Mon Sep 17 00:00:00 2001 From: teejusb <5017202+teejusb@users.noreply.github.com> Date: Fri, 22 Oct 2021 18:58:22 -0700 Subject: [PATCH 8/9] Revert "Always use PlayerState's own timing because of visual delay." This reverts commit 8edca26493aa28bcca11103460350e20ed387b1b. --- src/PlayerState.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/PlayerState.cpp b/src/PlayerState.cpp index 5cef47dedb..5ed8c66210 100644 --- a/src/PlayerState.cpp +++ b/src/PlayerState.cpp @@ -196,8 +196,9 @@ int PlayerState::GetSumOfActiveAttackLevels() const const SongPosition &PlayerState::GetDisplayedPosition() const { - // Player state should always use its own timing because of custom Visual Delay options. - return m_Position; + if( GAMESTATE->m_bIsUsingStepTiming ) + return m_Position; + return GAMESTATE->m_Position; } const TimingData &PlayerState::GetDisplayedTiming() const From 8673c28161f2ffc7af58cafdfe2032852fce773f Mon Sep 17 00:00:00 2001 From: teejusb <5017202+teejusb@users.noreply.github.com> Date: Tue, 26 Oct 2021 21:22:17 -0700 Subject: [PATCH 9/9] Convert ms to seconds. Use the PlayerState's m_Position in ArrowEffects so it actually works. --- src/ArrowEffects.cpp | 2 +- src/PlayerOptions.cpp | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/ArrowEffects.cpp b/src/ArrowEffects.cpp index e5938722f4..c7fae1de4c 100644 --- a/src/ArrowEffects.cpp +++ b/src/ArrowEffects.cpp @@ -488,7 +488,7 @@ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float if( curr_options->m_fTimeSpacing != 0.0f ) { - float fSongSeconds = GAMESTATE->m_Position.m_fMusicSecondsVisible; + float fSongSeconds = pPlayerState->m_Position.m_fMusicSecondsVisible; float fNoteSeconds = pCurSteps->GetTimingData()->GetElapsedTimeFromBeat(fNoteBeat); float fSecondsUntilStep = fNoteSeconds - fSongSeconds; float fBPM = curr_options->m_fScrollBPM; diff --git a/src/PlayerOptions.cpp b/src/PlayerOptions.cpp index 1badc2c757..1cc9a27456 100644 --- a/src/PlayerOptions.cpp +++ b/src/PlayerOptions.cpp @@ -562,7 +562,7 @@ void PlayerOptions::GetMods( vector &AddTo, bool bForceNoteSkin ) const { // Format the string to be something like "10ms VisualDelay". // Note that we don't process sub-millisecond visual delay. - AddTo.push_back( ssprintf("%.0fms VisualDelay", m_fVisualDelay) ); + AddTo.push_back( ssprintf("%.0fms VisualDelay", m_fVisualDelay * 1000.0f) ); } } @@ -608,17 +608,17 @@ bool PlayerOptions::FromOneModString( const RString &sOneMod, RString &sErrorOut { level = 0; } - else if ( EndsWith(s, "ms") ) - { - // Strip off the "ms" before parsing. - RString ms_value = s.substr(0, s.size()-2 ); - level = StringToFloat( ms_value ); - } else if( isdigit(s[0]) || s[0] == '-' ) { + if ( EndsWith(s, "ms") ) + { + // Strip off the "ms" before parsing and convert to seconds. + RString ms_value = s.substr(0, s.size()-2 ); + level = StringToFloat( ms_value ) / 1000.0f; + } /* If the last character is a *, they probably said "123*" when * they meant "*123". */ - if( s.Right(1) == "*" ) + else if( s.Right(1) == "*" ) { // XXX: We know what they want, is there any reason not to handle it? // Yes. We should be strict in handling the format. -Chris