diff --git a/stepmania/src/Judgment.cpp b/stepmania/src/Judgment.cpp index 165970746c..a183590388 100644 --- a/stepmania/src/Judgment.cpp +++ b/stepmania/src/Judgment.cpp @@ -32,8 +32,12 @@ static ThemeMetric MISS_EVEN_COMMAND ("Judgment","MissEvenComm Judgment::Judgment() { m_iCount = 0; +} - m_sprJudgment.Load( THEME->GetPathG("Judgment","label 1x6") ); +void Judgment::Load( bool bBeginner ) +{ + m_sprJudgment.Load( THEME->GetPathG("Judgment",bBeginner?"BeginnerLabel":"label") ); + ASSERT( m_sprJudgment.GetNumStates() == 6 || m_sprJudgment.GetNumStates() == 12 ); m_sprJudgment.StopAnimating(); Reset(); this->AddChild( &m_sprJudgment ); @@ -48,7 +52,7 @@ void Judgment::Reset() m_sprJudgment.SetHidden( true ); } -void Judgment::SetJudgment( TapNoteScore score ) +void Judgment::SetJudgment( TapNoteScore score, bool bEarly ) { //LOG->Trace( "Judgment::SetJudgment()" ); @@ -56,35 +60,38 @@ void Judgment::SetJudgment( TapNoteScore score ) m_sprJudgment.SetHidden( false ); + int iStateMult = (m_sprJudgment.GetNumStates()==12) ? 2 : 0; + int iStateAdd = bEarly ? 0 : 1; + switch( score ) { case TNS_MARVELOUS: - m_sprJudgment.SetState( 0 ); + m_sprJudgment.SetState( 0 * iStateMult + iStateAdd ); m_sprJudgment.RunCommands( (m_iCount%2) ? MARVELOUS_ODD_COMMAND : MARVELOUS_EVEN_COMMAND ); m_sprJudgment.RunCommands( MARVELOUS_COMMAND ); break; case TNS_PERFECT: - m_sprJudgment.SetState( 1 ); + m_sprJudgment.SetState( 1 * iStateMult + iStateAdd ); m_sprJudgment.RunCommands( (m_iCount%2) ? PERFECT_ODD_COMMAND : PERFECT_EVEN_COMMAND ); m_sprJudgment.RunCommands( PERFECT_COMMAND ); break; case TNS_GREAT: - m_sprJudgment.SetState( 2 ); + m_sprJudgment.SetState( 2 * iStateMult + iStateAdd ); m_sprJudgment.RunCommands( (m_iCount%2) ? GREAT_ODD_COMMAND : GREAT_EVEN_COMMAND ); m_sprJudgment.RunCommands( GREAT_COMMAND ); break; case TNS_GOOD: - m_sprJudgment.SetState( 3 ); + m_sprJudgment.SetState( 3 * iStateMult + iStateAdd ); m_sprJudgment.RunCommands( (m_iCount%2) ? GOOD_ODD_COMMAND : GOOD_EVEN_COMMAND ); m_sprJudgment.RunCommands( GOOD_COMMAND ); break; case TNS_BOO: - m_sprJudgment.SetState( 4 ); + m_sprJudgment.SetState( 4 * iStateMult + iStateAdd ); m_sprJudgment.RunCommands( (m_iCount%2) ? BOO_ODD_COMMAND : BOO_EVEN_COMMAND ); m_sprJudgment.RunCommands( BOO_COMMAND ); break; case TNS_MISS: - m_sprJudgment.SetState( 5 ); + m_sprJudgment.SetState( 5 * iStateMult + iStateAdd ); m_sprJudgment.RunCommands( (m_iCount%2) ? MISS_ODD_COMMAND : MISS_EVEN_COMMAND ); m_sprJudgment.RunCommands( MISS_COMMAND ); break; diff --git a/stepmania/src/Judgment.h b/stepmania/src/Judgment.h index 36b0d76117..af217cc3ea 100644 --- a/stepmania/src/Judgment.h +++ b/stepmania/src/Judgment.h @@ -13,9 +13,9 @@ class Judgment : public ActorFrame { public: Judgment(); - + void Load( bool bAlternateLabel ); void Reset(); - void SetJudgment( TapNoteScore score ); + void SetJudgment( TapNoteScore score, bool bEarly ); protected: Sprite m_sprJudgment; diff --git a/stepmania/src/NoteDataWithScoring.cpp b/stepmania/src/NoteDataWithScoring.cpp index dc68c1d35e..6e8babbac9 100644 --- a/stepmania/src/NoteDataWithScoring.cpp +++ b/stepmania/src/NoteDataWithScoring.cpp @@ -30,7 +30,7 @@ int GetNumNWithScore( const NoteData &in, TapNoteScore tns, int MinTaps, int iSt FOREACH_NONEMPTY_ROW_ALL_TRACKS_RANGE( in, r, iStartRow, iEndRow ) { int iNumNotesInRow = in.GetNumTracksWithTapOrHoldHead( r ); - TapNoteScore tnsRow = NoteDataWithScoring::LastTapNoteScore( in, r ); + TapNoteScore tnsRow = NoteDataWithScoring::LastTapNoteResult( in, r ).tns; if( iNumNotesInRow >= MinTaps && tnsRow >= tns ) iNumSuccessfulDoubles++; @@ -156,12 +156,13 @@ int LastTapNoteScoreTrack( const NoteData &in, unsigned iRow ) } } -TapNoteScore NoteDataWithScoring::LastTapNoteScore( const NoteData &in, unsigned iRow ) + +TapNoteResult NoteDataWithScoring::LastTapNoteResult( const NoteData &in, unsigned iRow ) { int iTrack = LastTapNoteScoreTrack( in, iRow ); if( iTrack == -1 ) - return TNS_NONE; - return in.GetTapNote(iTrack, iRow).result.tns; + return TapNoteResult(); + return in.GetTapNote(iTrack, iRow).result; } diff --git a/stepmania/src/NoteDataWithScoring.h b/stepmania/src/NoteDataWithScoring.h index 34033ecfe9..968a4eeed9 100644 --- a/stepmania/src/NoteDataWithScoring.h +++ b/stepmania/src/NoteDataWithScoring.h @@ -5,6 +5,7 @@ #include "GameConstantsAndTypes.h" #include "PlayerNumber.h" +#include "NoteTypes.h" #include struct RadarValues; @@ -13,7 +14,7 @@ namespace NoteDataWithScoring { bool IsRowCompletelyJudged( const NoteData &in, unsigned iRow ); TapNoteScore MinTapNoteScore( const NoteData &in, unsigned iRow ); - TapNoteScore LastTapNoteScore( const NoteData &in, unsigned iRow ); + TapNoteResult LastTapNoteResult( const NoteData &in, unsigned iRow ); void GetActualRadarValues( const NoteData &in, PlayerNumber pn, float fSongSeconds, RadarValues& out ); }; diff --git a/stepmania/src/Player.cpp b/stepmania/src/Player.cpp index dca83f0154..fd57839a12 100644 --- a/stepmania/src/Player.cpp +++ b/stepmania/src/Player.cpp @@ -45,8 +45,13 @@ CString ATTACK_DISPLAY_X_NAME( size_t p, size_t both_sides ){ return "AttackDisp /* Distance to search for a note in Step(), in seconds. */ static const float StepSearchDistance = 1.0f; -#define ADJUSTED_WINDOW( judge ) ((PREFSMAN->m_fJudgeWindowSeconds##judge * PREFSMAN->m_fJudgeWindowScale) + PREFSMAN->m_fJudgeWindowAdd) +#define ADJUSTED_WINDOW_HOLD( judge ) ( \ + (PREFSMAN->m_fJudgeWindowSeconds##judge * PREFSMAN->m_fJudgeWindowScale) + \ + PREFSMAN->m_fJudgeWindowAdd ) +#define ADJUSTED_WINDOW_TAP( judge, tns ) ( \ + ADJUSTED_WINDOW_HOLD( judge ) + \ + ((PREFSMAN->m_bMercifulBeginner && (tns==TNS_MISS||tns==TNS_BOO) && IsPlayingBeginner()) ? 0.5f : 0) ) Player::Player() { @@ -164,6 +169,7 @@ void Player::Init( ActorUtil::OnCommand( m_Combo, sType ); m_Judgment.SetName( "Judgment" ); + m_Judgment.Load( IsPlayingBeginner() ); ActorUtil::OnCommand( m_Judgment, sType ); m_fNoteFieldHeight = GRAY_ARROWS_Y_REVERSE-GRAY_ARROWS_Y_STANDARD; @@ -462,7 +468,7 @@ void Player::Update( float fDeltaTime ) else { // Decrease life - fLife -= fDeltaTime/ADJUSTED_WINDOW(OK); + fLife -= fDeltaTime/ADJUSTED_WINDOW_HOLD(OK); fLife = max( fLife, 0 ); // clamp } break; @@ -473,7 +479,7 @@ void Player::Update( float fDeltaTime ) // give positive life in Step(), not here. // Decrease life - fLife -= fDeltaTime/ADJUSTED_WINDOW(Roll); + fLife -= fDeltaTime/ADJUSTED_WINDOW_HOLD(Roll); fLife = max( fLife, 0 ); // clamp break; default: @@ -850,20 +856,20 @@ void Player::HandleStep( int col, const RageTimer &tm, bool bHeld ) { case TapNote::mine: // stepped too close to mine? - if( fSecondsFromPerfect <= ADJUSTED_WINDOW(Mine) ) + if( fSecondsFromPerfect <= ADJUSTED_WINDOW_TAP(Mine,TNS_HIT_MINE) ) score = TNS_HIT_MINE; break; case TapNote::attack: - if( fSecondsFromPerfect <= ADJUSTED_WINDOW(Attack) && !tn.result.bHidden ) + if( fSecondsFromPerfect <= ADJUSTED_WINDOW_TAP(Attack,TNS_NONE) && !tn.result.bHidden ) score = TNS_PERFECT; /* sentinel */ break; default: - if( fSecondsFromPerfect <= ADJUSTED_WINDOW(Marvelous) ) score = TNS_MARVELOUS; - else if( fSecondsFromPerfect <= ADJUSTED_WINDOW(Perfect) ) score = TNS_PERFECT; - else if( fSecondsFromPerfect <= ADJUSTED_WINDOW(Great) ) score = TNS_GREAT; - else if( fSecondsFromPerfect <= ADJUSTED_WINDOW(Good) ) score = TNS_GOOD; - else if( fSecondsFromPerfect <= ADJUSTED_WINDOW(Boo) ) score = TNS_BOO; + if( fSecondsFromPerfect <= ADJUSTED_WINDOW_TAP(Marvelous, TNS_MARVELOUS) ) score = TNS_MARVELOUS; + else if( fSecondsFromPerfect <= ADJUSTED_WINDOW_TAP(Perfect, TNS_PERFECT) ) score = TNS_PERFECT; + else if( fSecondsFromPerfect <= ADJUSTED_WINDOW_TAP(Great, TNS_GREAT) ) score = TNS_GREAT; + else if( fSecondsFromPerfect <= ADJUSTED_WINDOW_TAP(Good, TNS_GOOD) ) score = TNS_GOOD; + else if( fSecondsFromPerfect <= ADJUSTED_WINDOW_TAP(Boo, TNS_BOO) ) score = TNS_BOO; else score = TNS_NONE; break; } @@ -1180,8 +1186,9 @@ void Player::OnRowCompletelyJudged( int iIndexThatWasSteppedOn ) * the 2nd step of the jump, it sets another column's timer then AND's the jump * columns with the "was pressed recently" columns to see whether or not you hit * all the columns of the jump. -Chris */ -// TapNoteScore score = NoteDataWithScoring::MinTapNoteScore( m_NoteData, iIndexThatWasSteppedOn ); - TapNoteScore score = NoteDataWithScoring::LastTapNoteScore( m_NoteData, iIndexThatWasSteppedOn ); + TapNoteResult tnr = NoteDataWithScoring::LastTapNoteResult( m_NoteData, iIndexThatWasSteppedOn ); + TapNoteScore score = tnr.tns; + ASSERT(score != TNS_NONE); ASSERT(score != TNS_HIT_MINE); ASSERT(score != TNS_AVOIDED_MINE); @@ -1221,7 +1228,7 @@ void Player::OnRowCompletelyJudged( int iIndexThatWasSteppedOn ) HandleTapRowScore( iIndexThatWasSteppedOn ); // update score - m_Judgment.SetJudgment( score ); + m_Judgment.SetJudgment( score, tnr.fTapNoteOffset < 0 ); } @@ -1295,7 +1302,7 @@ void Player::UpdateTapNotesMissedOlderThan( float fMissIfOlderThanSeconds ) } if( iNumMissesFound > 0 ) - m_Judgment.SetJudgment( TNS_MISS ); + m_Judgment.SetJudgment( TNS_MISS, false ); } @@ -1380,7 +1387,7 @@ void Player::RandomizeNotes( int iNoteRow ) void Player::HandleTapRowScore( unsigned row ) { - TapNoteScore scoreOfLastTap = NoteDataWithScoring::LastTapNoteScore( m_NoteData, row ); + TapNoteScore scoreOfLastTap = NoteDataWithScoring::LastTapNoteResult( m_NoteData, row ).tns; int iNumTapsInRow = m_NoteData.GetNumTracksWithTapOrHoldHead(row); ASSERT(iNumTapsInRow > 0); @@ -1569,7 +1576,7 @@ void Player::HandleHoldScore( HoldNoteScore holdScore, TapNoteScore tapScore ) float Player::GetMaxStepDistanceSeconds() { - return GAMESTATE->m_SongOptions.m_fMusicRate * ADJUSTED_WINDOW(Boo); + return GAMESTATE->m_SongOptions.m_fMusicRate * ADJUSTED_WINDOW_TAP(Boo,TNS_BOO); } void Player::FadeToFail() @@ -1578,6 +1585,22 @@ void Player::FadeToFail() m_pNoteField->FadeToFail(); } +bool Player::IsPlayingBeginner() const +{ + if( !m_pPlayerStageStats->vpPossibleSteps.empty() ) + { + Steps *pSteps = m_pPlayerStageStats->vpPossibleSteps[0]; + return pSteps->GetDifficulty() == DIFFICULTY_BEGINNER; + } + else + { + if( m_pPlayerState->m_PlayerNumber == PLAYER_INVALID ) + return false; + Steps *pSteps = GAMESTATE->m_pCurSteps[ m_pPlayerState->m_PlayerNumber ]; + return pSteps && pSteps->GetDifficulty() == DIFFICULTY_BEGINNER; + } +} + /* * (c) 2001-2004 Chris Danford * All rights reserved. diff --git a/stepmania/src/Player.h b/stepmania/src/Player.h index ffcdb9cde5..fb6f68ca2f 100644 --- a/stepmania/src/Player.h +++ b/stepmania/src/Player.h @@ -53,7 +53,7 @@ public: void ApplyWaitingTransforms(); void SetPaused( bool bPaused ) { m_bPaused = bPaused; } - static float GetMaxStepDistanceSeconds(); + float GetMaxStepDistanceSeconds(); NoteData m_NoteData; @@ -70,6 +70,8 @@ protected: int GetClosestNoteDirectional( int col, int iStartRow, int iMaxRowsAhead, bool bAllowGraded, bool bForward ) const; int GetClosestNote( int col, int iNoteRow, int iMaxRowsAhead, int iMaxRowsBehind, bool bAllowGraded ) const; + bool IsPlayingBeginner() const; + PlayerState* m_pPlayerState; PlayerStageStats* m_pPlayerStageStats; float m_fNoteFieldHeight; diff --git a/stepmania/src/PrefsManager.h b/stepmania/src/PrefsManager.h index 76c280ceb5..46109c1f52 100644 --- a/stepmania/src/PrefsManager.h +++ b/stepmania/src/PrefsManager.h @@ -99,7 +99,7 @@ public: Preference m_bMinimum1FullSongInCourses; // FEoS for 1st song, FailImmediate thereafter Preference m_bFailOffInBeginner; Preference m_bFailOffForFirstStageEasy; - Preference m_bMercifulBeginner; // don't subtract from percent score or grade DP + Preference m_bMercifulBeginner; // don't subtract from percent score or grade DP, larger boo window // percent score (the number that is shown on the screen and saved to memory card) Preference m_iPercentScoreWeightMarvelous; diff --git a/stepmania/src/ScreenGameplay.cpp b/stepmania/src/ScreenGameplay.cpp index ab3da921b1..106d737ddd 100644 --- a/stepmania/src/ScreenGameplay.cpp +++ b/stepmania/src/ScreenGameplay.cpp @@ -1461,7 +1461,7 @@ void ScreenGameplay::Update( float fDeltaTime ) float fSecondsToStop = GAMESTATE->m_pCurSong->GetElapsedTimeFromBeat( GAMESTATE->m_pCurSong->m_fLastBeat ); /* Make sure we keep going long enough to register a miss for the last note. */ - fSecondsToStop += Player::GetMaxStepDistanceSeconds(); + fSecondsToStop += m_Player[GAMESTATE->m_MasterPlayerNumber].GetMaxStepDistanceSeconds(); if( GAMESTATE->m_fMusicSeconds > fSecondsToStop && !m_SongFinished.IsTransitioning() && !m_NextSong.IsTransitioning() ) m_SongFinished.StartTransitioning( SM_NotesEnded ); diff --git a/stepmania/src/ScreenGameplayMultiplayer.cpp b/stepmania/src/ScreenGameplayMultiplayer.cpp index decb9705b4..4bf1a769dd 100644 --- a/stepmania/src/ScreenGameplayMultiplayer.cpp +++ b/stepmania/src/ScreenGameplayMultiplayer.cpp @@ -483,7 +483,7 @@ void ScreenGameplayMultiplayer::Update( float fDeltaTime ) float fSecondsToStop = GAMESTATE->m_pCurSong->GetElapsedTimeFromBeat( GAMESTATE->m_pCurSong->m_fLastBeat ); /* Make sure we keep going long enough to register a miss for the last note. */ - fSecondsToStop += Player::GetMaxStepDistanceSeconds(); + fSecondsToStop += m_AutoPlayer.GetMaxStepDistanceSeconds(); if( GAMESTATE->m_fMusicSeconds > fSecondsToStop && !m_Out.IsTransitioning() ) this->HandleScreenMessage( SM_NotesEnded );