Don't judge rolls inside of HandleStep. It's redundant because all holds and rolls are judged in Update.

Move calls to Step for autoplay of rolls outside the HoldNote update loop to fix double-grading.
This commit is contained in:
Chris Danford
2005-06-16 21:36:58 +00:00
parent 0f291512e2
commit fb003c3189
+105 -101
View File
@@ -417,6 +417,42 @@ void Player::Update( float fDeltaTime )
m_pNoteField->SetPressed( col );
}
//
// handle Autoplay for rolls
//
{
const int iStartCheckingAt = max( 0, iSongRow-BeatToNoteRow(1) );
for( int iTrack=0; iTrack<m_NoteData.GetNumTracks(); ++iTrack )
{
// Since this is being called every frame, let's not check the whole array every time.
// Instead, only check 1 beat back. Even 1 is overkill.
NoteData::iterator begin, end;
m_NoteData.GetTapNoteRangeInclusive( iTrack, iStartCheckingAt, iSongRow+1, begin, end );
for( ; begin != end; ++begin )
{
TapNote &tn = begin->second;
if( tn.type != TapNote::hold_head )
continue;
HoldNoteScore hns = tn.HoldResult.hns;
if( hns != HNS_NONE ) // if this HoldNote already has a result
continue; // we don't need to update the logic for this one
if( m_pPlayerState->m_PlayerController != PC_HUMAN )
{
// TODO: Make the CPU miss sometimes.
if( tn.subType == TapNote::hold_head_roll && tn.HoldResult.fLife < 0.5f )
{
RageTimer now;
Step( iTrack, now, false );
}
}
}
}
}
//
// update HoldNotes logic
//
@@ -453,21 +489,7 @@ void Player::Update( float fDeltaTime )
if( m_pPlayerState->m_PlayerController != PC_HUMAN )
{
// TODO: Make the CPU miss sometimes.
switch( tn.subType )
{
case TapNote::hold_head_hold:
bIsHoldingButton = true;
break;
case TapNote::hold_head_roll:
if( tn.HoldResult.fLife < 0.5f )
{
RageTimer now;
Step( iTrack, now, false );
}
break;
default:
ASSERT(0);
}
bIsHoldingButton = true;
}
else
{
@@ -790,7 +812,6 @@ void Player::Step( int col, const RageTimer &tm, bool bHeld )
void Player::HandleStep( int col, const RageTimer &tm, bool bHeld )
{
//LOG->Trace( "Player::HandlePlayerStep()" );
ASSERT_M( col >= 0 && col <= m_NoteData.GetNumTracks(), ssprintf("%i, %i", col, m_NoteData.GetNumTracks()) );
@@ -841,6 +862,8 @@ void Player::HandleStep( int col, const RageTimer &tm, bool bHeld )
fPositionSeconds -= tm.Ago();
const float fSongBeat = GAMESTATE->m_pCurSong ? GAMESTATE->m_pCurSong->GetBeatFromElapsedTime( fPositionSeconds ) : GAMESTATE->m_fSongBeat;
//
// Check for step on a TapNote
//
@@ -1075,106 +1098,87 @@ void Player::HandleStep( int col, const RageTimer &tm, bool bHeld )
}
}
if( m_pNoteField )
m_pNoteField->Step( col, score );
/* Search for keyed sounds separately. If we can't find a nearby note, search
* backwards indefinitely, and ignore grading. */
if( iIndexOverlappingNote == -1 )
iIndexOverlappingNote = GetClosestNote( col, BeatToNoteRow(fSongBeat),
iStepSearchRows, MAX_NOTE_ROW, true );
if( iIndexOverlappingNote != -1 )
bool bSteppedOnATap = score != TNS_NONE;
if( bSteppedOnATap )
{
TapNote tn = m_NoteData.GetTapNote( col, iIndexOverlappingNote );
if( tn.bKeysound && tn.iKeysoundIndex < (int) m_vKeysounds.size() )
m_vKeysounds[tn.iKeysoundIndex].Play();
/* Search for keyed sounds separately. If we can't find a nearby note, search
* backwards indefinitely, and ignore grading. */
if( iIndexOverlappingNote == -1 )
iIndexOverlappingNote = GetClosestNote( col, BeatToNoteRow(fSongBeat),
iStepSearchRows, MAX_NOTE_ROW, true );
if( iIndexOverlappingNote != -1 )
{
TapNote tn = m_NoteData.GetTapNote( col, iIndexOverlappingNote );
if( tn.bKeysound && tn.iKeysoundIndex < (int) m_vKeysounds.size() )
m_vKeysounds[tn.iKeysoundIndex].Play();
}
}
// Update roll life
// Let's not check the whole array every time.
// Instead, only check 1 beat back. Even 1 is overkill.
const int iSongRow = BeatToNoteRow(fSongBeat);
const int iStartCheckingAt = max( 0, iSongRow-BeatToNoteRow(1) );
NoteData::iterator begin, end;
m_NoteData.GetTapNoteRangeInclusive( col, iStartCheckingAt, iSongRow+1, begin, end );
for( ; begin != end; ++begin )
{
TapNote &tn = begin->second;
if( tn.type != TapNote::hold_head )
continue;
int iRow = begin->first;
HoldNoteScore hns = tn.HoldResult.hns;
if( hns != HNS_NONE ) // if this HoldNote already has a result
continue; // we don't need to update the logic for this one
// if they got a bad score or haven't stepped on the corresponding tap yet
const TapNoteScore tns = tn.result.tns;
const bool bSteppedOnTapNote = tns != TNS_NONE && tns != TNS_MISS; // did they step on the start of this roll?
int iEndRow = iRow + tn.iDuration;
float fLife = tn.HoldResult.fLife;
if( bSteppedOnTapNote && fLife != 0 )
// Update roll life
// Let's not check the whole array every time.
// Instead, only check 1 beat back. Even 1 is overkill.
// Just update the life here and let Update judge the roll.
const int iSongRow = BeatToNoteRow(fSongBeat);
const int iStartCheckingAt = max( 0, iSongRow-BeatToNoteRow(1) );
NoteData::iterator begin, end;
m_NoteData.GetTapNoteRangeInclusive( col, iStartCheckingAt, iSongRow+1, begin, end );
for( ; begin != end; ++begin )
{
/* This hold note is not judged and we stepped on its head. Update iLastHeldRow.
* Do this even if we're a little beyond the end of the hold note, to make sure
* iLastHeldRow is clamped to iEndRow if the hold note is held all the way. */
tn.HoldResult.iLastHeldRow = min( iSongRow, iEndRow );
}
TapNote &tn = begin->second;
if( tn.type != TapNote::hold_head )
continue;
int iRow = begin->first;
// If the song beat is in the range of this hold:
if( iRow <= iSongRow && iRow <= iEndRow )
{
switch( tn.subType )
HoldNoteScore hns = tn.HoldResult.hns;
if( hns != HNS_NONE ) // if this HoldNote already has a result
continue; // we don't need to update the logic for this one
// if they got a bad score or haven't stepped on the corresponding tap yet
const TapNoteScore tns = tn.result.tns;
const bool bSteppedOnTapNote = tns != TNS_NONE && tns != TNS_MISS; // did they step on the start of this roll?
int iEndRow = iRow + tn.iDuration;
if( bSteppedOnTapNote && tn.HoldResult.fLife != 0 )
{
case TapNote::hold_head_hold:
// this is handled in Update
break;
case TapNote::hold_head_roll:
{
// Increase life
fLife = 1;
/* This hold note is not judged and we stepped on its head. Update iLastHeldRow.
* Do this even if we're a little beyond the end of the hold note, to make sure
* iLastHeldRow is clamped to iEndRow if the hold note is held all the way. */
tn.HoldResult.iLastHeldRow = min( iSongRow, iEndRow );
}
bool bBright = m_pPlayerStageStats && m_pPlayerStageStats->iCurCombo>(int)BRIGHT_GHOST_COMBO_THRESHOLD;
if( m_pNoteField )
m_pNoteField->DidHoldNote( col, HNS_OK, bBright );
// If the song beat is in the range of this hold:
if( iRow <= iSongRow && iRow <= iEndRow )
{
switch( tn.subType )
{
case TapNote::hold_head_hold:
// this is handled in Update
break;
case TapNote::hold_head_roll:
{
// Increase life
tn.HoldResult.fLife = 1;
bool bBright = m_pPlayerStageStats && m_pPlayerStageStats->iCurCombo>(int)BRIGHT_GHOST_COMBO_THRESHOLD;
if( m_pNoteField )
m_pNoteField->DidHoldNote( col, HNS_OK, bBright );
}
break;
default:
ASSERT(0);
}
break;
default:
ASSERT(0);
}
}
/* check for NG. If the head was missed completely, don't count an NG. */
if( bSteppedOnTapNote && fLife == 0 ) // the player has not pressed the button for a long time!
hns = HNS_NG;
// check for OK
if( iSongRow >= iEndRow && bSteppedOnTapNote && fLife > 0 ) // if this HoldNote is in the past
{
fLife = 1;
hns = HNS_OK;
bool bBright = m_pPlayerStageStats && m_pPlayerStageStats->iCurCombo>(int)BRIGHT_GHOST_COMBO_THRESHOLD;
if( m_pNoteField )
m_pNoteField->DidHoldNote( col, HNS_OK, bBright );
}
if( hns != HNS_NONE )
{
/* this note has been judged */
HandleHoldScore( hns, tns );
m_HoldJudgment[col].SetHoldJudgment( hns );
int ms_error = (hns == HNS_OK)? 0:MAX_PRO_TIMING_ERROR;
if( m_pPlayerStageStats )
m_pPlayerStageStats->iTotalError += ms_error;
}
tn.HoldResult.fLife = fLife;
tn.HoldResult.hns = hns;
}
}