diff --git a/stepmania/src/NoteDataWithScoring.cpp b/stepmania/src/NoteDataWithScoring.cpp index 7244280e4f..1c9cf7e0d5 100644 --- a/stepmania/src/NoteDataWithScoring.cpp +++ b/stepmania/src/NoteDataWithScoring.cpp @@ -100,7 +100,9 @@ int NoteDataWithScoring::GetNumHoldNotesWithScore( HoldNoteScore hns, const floa for( int i=0; i hn.iStartRow || hn.iEndRow > iEndIndex ) + continue; + if( GetHoldNoteScore(hn) == hns ) iNumSuccessfulHolds++; } return iNumSuccessfulHolds; @@ -315,29 +317,30 @@ void NoteDataWithScoring::SetTapNoteOffset(unsigned track, unsigned row, float o m_TapNoteOffset[track][row] = offset; } -HoldNoteScore NoteDataWithScoring::GetHoldNoteScore(unsigned h) const +/* We use the end row to index hold notes, instead of the start row, because the start row + * changes when hold notes are being stepped on, but end rows never change. */ +HoldNoteScore NoteDataWithScoring::GetHoldNoteScore( const HoldNote &hn ) const { - if(h >= m_HoldNoteScores.size()) + map::const_iterator it = m_HoldNoteScores.find( RowTrack(hn.iEndRow, hn.iTrack) ); + if( it == m_HoldNoteScores.end() ) return HNS_NONE; - return m_HoldNoteScores[h]; + return it->second; } -void NoteDataWithScoring::SetHoldNoteScore(unsigned h, HoldNoteScore hns) +void NoteDataWithScoring::SetHoldNoteScore( const HoldNote &hn, HoldNoteScore hns ) { - extend(m_HoldNoteScores, HNS_NONE, h); - m_HoldNoteScores[h] = hns; + m_HoldNoteScores[RowTrack(hn.iEndRow, hn.iTrack)] = hns; } -void NoteDataWithScoring::SetHoldNoteLife(unsigned h, float f) +void NoteDataWithScoring::SetHoldNoteLife( const HoldNote &hn, float f ) { - extend(m_fHoldNoteLife, 1.0f, h); - m_fHoldNoteLife[h] = f; + m_fHoldNoteLife[RowTrack(hn.iEndRow, hn.iTrack)] = f; } -float NoteDataWithScoring::GetHoldNoteLife(unsigned h) const +float NoteDataWithScoring::GetHoldNoteLife( const HoldNote &hn ) const { - // start with full life - if(h >= m_fHoldNoteLife.size()) + map::const_iterator it = m_fHoldNoteLife.find( RowTrack(hn.iEndRow, hn.iTrack) ); + if( it == m_fHoldNoteLife.end() ) return 1.0f; - return m_fHoldNoteLife[h]; + return it->second; } diff --git a/stepmania/src/NoteDataWithScoring.h b/stepmania/src/NoteDataWithScoring.h index e636d9539c..7f9ef29665 100644 --- a/stepmania/src/NoteDataWithScoring.h +++ b/stepmania/src/NoteDataWithScoring.h @@ -14,12 +14,14 @@ #include "GameConstantsAndTypes.h" #include "NoteData.h" #include "PlayerNumber.h" +#include class NoteDataWithScoring : public NoteData { // maintain this extra data in addition to the NoteData vector m_TapNoteScores[MAX_NOTE_TRACKS]; - vector m_HoldNoteScores; + typedef pair RowTrack; + map m_HoldNoteScores; /* Offset, in seconds, for each tap grade. Negative numbers mean the note * was hit early; positive numbers mean it was hit late. These values are @@ -30,7 +32,7 @@ class NoteDataWithScoring : public NoteData * 0.0 means this HoldNote is dead * When this value hits 0.0 for the first time, m_HoldScore becomes HSS_NG. * If the life is > 0.0 when the HoldNote ends, then m_HoldScore becomes HSS_OK. */ - vector m_fHoldNoteLife; + map m_fHoldNoteLife; public: NoteDataWithScoring(); @@ -46,10 +48,11 @@ public: void SetTapNoteScore(unsigned track, unsigned row, TapNoteScore tns); float GetTapNoteOffset(unsigned track, unsigned row) const; void SetTapNoteOffset(unsigned track, unsigned row, float offset); - HoldNoteScore GetHoldNoteScore(unsigned h) const; - void SetHoldNoteScore(unsigned h, HoldNoteScore hns); - float GetHoldNoteLife(unsigned h) const; - void SetHoldNoteLife(unsigned h, float f); + + HoldNoteScore GetHoldNoteScore( const HoldNote &hn ) const; + void SetHoldNoteScore( const HoldNote &hn, HoldNoteScore hns ); + float GetHoldNoteLife( const HoldNote &hn ) const; + void SetHoldNoteLife( const HoldNote &hn, float f ); bool IsRowCompletelyJudged(unsigned row) const; TapNoteScore MinTapNoteScore(unsigned row) const; diff --git a/stepmania/src/NoteField.cpp b/stepmania/src/NoteField.cpp index 250153aa13..d673a5882a 100644 --- a/stepmania/src/NoteField.cpp +++ b/stepmania/src/NoteField.cpp @@ -517,8 +517,8 @@ void NoteField::DrawPrimitives() for( i=0; i < GetNumHoldNotes(); i++ ) { const HoldNote &hn = GetHoldNote(i); - const HoldNoteScore hns = GetHoldNoteScore(i); - const float fLife = GetHoldNoteLife(i); + const HoldNoteScore hns = GetHoldNoteScore( hn ); + const float fLife = GetHoldNoteLife( hn ); const bool bIsHoldingNote = (i < int(m_bIsHoldingHoldNote.size()))? m_bIsHoldingHoldNote[i]: false; diff --git a/stepmania/src/Player.cpp b/stepmania/src/Player.cpp index f82974264f..33f72ce022 100644 --- a/stepmania/src/Player.cpp +++ b/stepmania/src/Player.cpp @@ -281,22 +281,25 @@ void PlayerMinus::Update( float fDeltaTime ) for( int i=0; i < GetNumHoldNotes(); i++ ) // for each HoldNote { const HoldNote &hn = GetHoldNote(i); - HoldNoteScore hns = GetHoldNoteScore(i); - float fLife = GetHoldNoteLife(i); - int iHoldStartIndex = hn.iStartRow; + HoldNoteScore hns = GetHoldNoteScore(hn); m_pNoteField->m_bIsHoldingHoldNote[i] = false; // set host flag so NoteField can do intelligent drawing if( hns != HNS_NONE ) // if this HoldNote already has a result continue; // we don't need to update the logic for this one + if( iSongRow < hn.iStartRow ) + continue; // hold hasn't happened yet + const StyleInput StyleI( m_PlayerNumber, hn.iTrack ); const GameInput GameI = GAMESTATE->GetCurrentStyleDef()->StyleInputToGameInput( StyleI ); // if they got a bad score or haven't stepped on the corresponding tap yet - const TapNoteScore tns = GetTapNoteScore(hn.iTrack, iHoldStartIndex); + const TapNoteScore tns = GetTapNoteScore( hn.iTrack, hn.iStartRow ); const bool bSteppedOnTapNote = tns != TNS_NONE && tns != TNS_MISS; // did they step on the start of this hold? + float fLife = GetHoldNoteLife(hn); + // If the song beat is in the range of this hold: if( hn.iStartRow <= iSongRow && iSongRow <= hn.iEndRow ) { @@ -312,12 +315,7 @@ void PlayerMinus::Update( float fDeltaTime ) if( bSteppedOnTapNote ) // this note is not judged and we stepped on its head { // Move the start of this Hold - // - // IMPORTANT: Every HoldNote::fStartBeat must be at least 1 index less than - // its HoldNote::fEndBeat. Otherwise, when HoldNotes are converted to the - // 4s representation, it disappears, which causes problems for the way we - // store HoldNote life (by index of the hold). - m_pNoteField->GetHoldNote(i).iStartRow = min( iSongRow, m_pNoteField->GetHoldNote(i).iEndRow-1 ); + m_pNoteField->GetHoldNote(i).iStartRow = min( iSongRow, m_pNoteField->GetHoldNote(i).iEndRow ); } if( bSteppedOnTapNote && bIsHoldingButton ) @@ -368,11 +366,11 @@ void PlayerMinus::Update( float fDeltaTime ) m_ProTimingDisplay.SetJudgment( ms_error, TNS_MISS ); } - m_pNoteField->SetHoldNoteLife(i, fLife); // update the NoteField display - m_pNoteField->SetHoldNoteScore(i, hns); // update the NoteField display + m_pNoteField->SetHoldNoteLife(hn, fLife); // update the NoteField display + m_pNoteField->SetHoldNoteScore(hn, hns); // update the NoteField display - SetHoldNoteLife(i, fLife); - SetHoldNoteScore(i, hns); + SetHoldNoteLife(hn, fLife); + SetHoldNoteScore(hn, hns); } // Why was this originally "BeatToNoteRowNotRounded"? It should be rounded. -Chris @@ -398,15 +396,6 @@ void PlayerMinus::Update( float fDeltaTime ) po.m_sNoteSkin = ""; po.FromString( mod.sModifier ); - /* Note that runtime effects like these currently must not change hold - * notes. CopyRange below converts through 4s, which means the hold note - * array will be reconstructed; if hold notes end up in a different order, - * they won't align with this->m_HoldNoteScores. */ - if( po.m_bTransforms[PlayerOptions::TRANSFORM_NOHOLDS] ) - RageException::Throw("Can't use NoHolds as a battle attack"); - if( po.m_bTransforms[PlayerOptions::TRANSFORM_NOMINES] ) - RageException::Throw("Can't use NoMines as a battle attack"); - float fStartBeat, fEndBeat; mod.GetAttackBeats( GAMESTATE->m_pCurSong, m_PlayerNumber, fStartBeat, fEndBeat ); fEndBeat = min( fEndBeat, GetMaxBeat() );