implement rolls in gameplay
This commit is contained in:
+113
-12
@@ -433,23 +433,40 @@ void Player::Update( float fDeltaTime )
|
|||||||
// If the song beat is in the range of this hold:
|
// If the song beat is in the range of this hold:
|
||||||
if( iRow <= iSongRow && iRow <= iEndRow )
|
if( iRow <= iSongRow && iRow <= iEndRow )
|
||||||
{
|
{
|
||||||
// set hold flag so NoteField can do intelligent drawing
|
switch( tn.subType )
|
||||||
tn.HoldResult.bHeld = bIsHoldingButton && bSteppedOnTapNote;
|
|
||||||
tn.HoldResult.bActive = bSteppedOnTapNote;
|
|
||||||
|
|
||||||
if( bSteppedOnTapNote && bIsHoldingButton )
|
|
||||||
{
|
{
|
||||||
// Increase life
|
case TapNote::hold_head_hold:
|
||||||
fLife = 1;
|
// set hold flag so NoteField can do intelligent drawing
|
||||||
|
tn.HoldResult.bHeld = bIsHoldingButton && bSteppedOnTapNote;
|
||||||
|
tn.HoldResult.bActive = bSteppedOnTapNote;
|
||||||
|
|
||||||
|
if( bSteppedOnTapNote && bIsHoldingButton )
|
||||||
|
{
|
||||||
|
// Increase life
|
||||||
|
fLife = 1;
|
||||||
|
|
||||||
|
if( m_pNoteField )
|
||||||
|
m_pNoteField->DidHoldNote( iTrack ); // update the "electric ghost" effect
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Decrease life
|
||||||
|
fLife -= fDeltaTime/ADJUSTED_WINDOW(OK);
|
||||||
|
fLife = max( fLife, 0 ); // clamp
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TapNote::hold_head_roll:
|
||||||
|
tn.HoldResult.bHeld = true;
|
||||||
|
tn.HoldResult.bActive = bSteppedOnTapNote;
|
||||||
|
|
||||||
|
// give positive life in Step(), not here.
|
||||||
|
|
||||||
if( m_pNoteField )
|
|
||||||
m_pNoteField->DidHoldNote( iTrack ); // update the "electric ghost" effect
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Decrease life
|
// Decrease life
|
||||||
fLife -= fDeltaTime/ADJUSTED_WINDOW(OK);
|
fLife -= fDeltaTime/ADJUSTED_WINDOW(OK);
|
||||||
fLife = max( fLife, 0 ); // clamp
|
fLife = max( fLife, 0 ); // clamp
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ASSERT(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1006,6 +1023,90 @@ void Player::HandleStep( int col, const RageTimer &tm, bool bHeld )
|
|||||||
if( tn.bKeysound && tn.iKeysoundIndex < (int) m_vKeysounds.size() )
|
if( tn.bKeysound && tn.iKeysoundIndex < (int) m_vKeysounds.size() )
|
||||||
m_vKeysounds[tn.iKeysoundIndex].Play();
|
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
|
||||||
|
|
||||||
|
// TODO: Remove use of PlayerNumber.
|
||||||
|
PlayerNumber pn = m_pPlayerState->m_PlayerNumber;
|
||||||
|
|
||||||
|
// 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 )
|
||||||
|
{
|
||||||
|
/* 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 );
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
fLife = 1;
|
||||||
|
LOG->Trace( "rolling" );
|
||||||
|
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;
|
||||||
|
if( m_pNoteField )
|
||||||
|
m_pNoteField->DidTapNote( col, TNS_PERFECT, true ); // bright ghost flash
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::HandleAutosync(float fNoteOffset)
|
void Player::HandleAutosync(float fNoteOffset)
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ PrefsManager::PrefsManager() :
|
|||||||
m_fJudgeWindowSecondsGood ( Options, "JudgeWindowSecondsGood", 0.135f ),
|
m_fJudgeWindowSecondsGood ( Options, "JudgeWindowSecondsGood", 0.135f ),
|
||||||
m_fJudgeWindowSecondsBoo ( Options, "JudgeWindowSecondsBoo", 0.180f ),
|
m_fJudgeWindowSecondsBoo ( Options, "JudgeWindowSecondsBoo", 0.180f ),
|
||||||
m_fJudgeWindowSecondsOK ( Options, "JudgeWindowSecondsOK", 0.250f ), // allow enough time to take foot off and put back on
|
m_fJudgeWindowSecondsOK ( Options, "JudgeWindowSecondsOK", 0.250f ), // allow enough time to take foot off and put back on
|
||||||
|
m_fJudgeWindowSecondsRoll ( Options, "JudgeWindowSecondsRoll", 0.350f ),
|
||||||
m_fJudgeWindowSecondsMine ( Options, "JudgeWindowSecondsMine", 0.090f ), // same as great
|
m_fJudgeWindowSecondsMine ( Options, "JudgeWindowSecondsMine", 0.090f ), // same as great
|
||||||
m_fJudgeWindowSecondsAttack ( Options, "JudgeWindowSecondsAttack", 0.135f ),
|
m_fJudgeWindowSecondsAttack ( Options, "JudgeWindowSecondsAttack", 0.135f ),
|
||||||
|
|
||||||
@@ -576,6 +577,7 @@ void PrefsManager::SaveGlobalPrefsToIni( IniFile &ini ) const
|
|||||||
ini.SetValue( "Options", "JudgeWindowSecondsGood", m_fJudgeWindowSecondsGood );
|
ini.SetValue( "Options", "JudgeWindowSecondsGood", m_fJudgeWindowSecondsGood );
|
||||||
ini.SetValue( "Options", "JudgeWindowSecondsBoo", m_fJudgeWindowSecondsBoo );
|
ini.SetValue( "Options", "JudgeWindowSecondsBoo", m_fJudgeWindowSecondsBoo );
|
||||||
ini.SetValue( "Options", "JudgeWindowSecondsOK", m_fJudgeWindowSecondsOK );
|
ini.SetValue( "Options", "JudgeWindowSecondsOK", m_fJudgeWindowSecondsOK );
|
||||||
|
ini.SetValue( "Options", "JudgeWindowSecondsRoll", m_fJudgeWindowSecondsRoll );
|
||||||
ini.SetValue( "Options", "JudgeWindowSecondsMine", m_fJudgeWindowSecondsMine );
|
ini.SetValue( "Options", "JudgeWindowSecondsMine", m_fJudgeWindowSecondsMine );
|
||||||
ini.SetValue( "Options", "JudgeWindowSecondsAttack", m_fJudgeWindowSecondsAttack );
|
ini.SetValue( "Options", "JudgeWindowSecondsAttack", m_fJudgeWindowSecondsAttack );
|
||||||
ini.SetValue( "Options", "LifeDifficultyScale", m_fLifeDifficultyScale );
|
ini.SetValue( "Options", "LifeDifficultyScale", m_fLifeDifficultyScale );
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ public:
|
|||||||
Preference<float> m_fJudgeWindowSecondsGood;
|
Preference<float> m_fJudgeWindowSecondsGood;
|
||||||
Preference<float> m_fJudgeWindowSecondsBoo;
|
Preference<float> m_fJudgeWindowSecondsBoo;
|
||||||
Preference<float> m_fJudgeWindowSecondsOK;
|
Preference<float> m_fJudgeWindowSecondsOK;
|
||||||
|
Preference<float> m_fJudgeWindowSecondsRoll;
|
||||||
Preference<float> m_fJudgeWindowSecondsMine;
|
Preference<float> m_fJudgeWindowSecondsMine;
|
||||||
Preference<float> m_fJudgeWindowSecondsAttack;
|
Preference<float> m_fJudgeWindowSecondsAttack;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user