Attempted fix of Tick Holds
NoteDataUtil::GetTotalHoldTicks() was not counting the last tick of holds which ended on the last row of the song. Extended the range to include the last row. NoteDataUtil::GetTotalHoldTicks() was counting number of rows held, when it should only count 1 regardless of number( at least to mimic pump ) Player::CrossedRows() was assuming a constant tick rate over the crossed rows, leading to potentially inaccurate tick counts. Pump holds were counting "HoldNote_Held" due to capitalization in the metrics. Fixed metrics and made "IsGame" function case insensitive.
This commit is contained in:
@@ -8,7 +8,7 @@ local function CurGameName()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Check the active game mode against a string. Cut down typing this in metrics.
|
-- Check the active game mode against a string. Cut down typing this in metrics.
|
||||||
function IsGame(str) return CurGameName() == str end
|
function IsGame(str) return CurGameName():lower() == str:lower() end
|
||||||
|
|
||||||
-- GetExtraColorThreshold()
|
-- GetExtraColorThreshold()
|
||||||
-- [en] returns the difficulty threshold in meter
|
-- [en] returns the difficulty threshold in meter
|
||||||
|
|||||||
@@ -642,8 +642,8 @@ LifePercentChangeW4=0.000
|
|||||||
LifePercentChangeW5=-0.040
|
LifePercentChangeW5=-0.040
|
||||||
LifePercentChangeMiss=-0.080
|
LifePercentChangeMiss=-0.080
|
||||||
LifePercentChangeHitMine=-0.160
|
LifePercentChangeHitMine=-0.160
|
||||||
LifePercentChangeHeld=IsGame("Pump") and 0.000 or 0.008
|
LifePercentChangeHeld=IsGame("pump") and 0.000 or 0.008
|
||||||
LifePercentChangeLetGo=IsGame("Pump") and 0.000 or -0.080
|
LifePercentChangeLetGo=IsGame("pump") and 0.000 or -0.080
|
||||||
LifePercentChangeMissedHold=0.000
|
LifePercentChangeMissedHold=0.000
|
||||||
LifePercentChangeCheckpointMiss=-0.080
|
LifePercentChangeCheckpointMiss=-0.080
|
||||||
LifePercentChangeCheckpointHit=0.008
|
LifePercentChangeCheckpointHit=0.008
|
||||||
@@ -1337,7 +1337,7 @@ FrameOverP2OffCommand=
|
|||||||
[ScoreKeeperNormal]
|
[ScoreKeeperNormal]
|
||||||
PercentScoreWeightCheckpointHit=3
|
PercentScoreWeightCheckpointHit=3
|
||||||
PercentScoreWeightCheckpointMiss=0
|
PercentScoreWeightCheckpointMiss=0
|
||||||
PercentScoreWeightHeld=IsGame("Pump") and 0 or 3
|
PercentScoreWeightHeld=IsGame("pump") and 0 or 3
|
||||||
PercentScoreWeightHitMine=-2
|
PercentScoreWeightHitMine=-2
|
||||||
PercentScoreWeightMissedHold=0
|
PercentScoreWeightMissedHold=0
|
||||||
PercentScoreWeightLetGo=0
|
PercentScoreWeightLetGo=0
|
||||||
@@ -1349,7 +1349,7 @@ PercentScoreWeightW4=0
|
|||||||
PercentScoreWeightW5=0
|
PercentScoreWeightW5=0
|
||||||
GradeWeightCheckpointHit=2
|
GradeWeightCheckpointHit=2
|
||||||
GradeWeightCheckpointMiss=-8
|
GradeWeightCheckpointMiss=-8
|
||||||
GradeWeightHeld=IsGame("Pump") and 0 or 6
|
GradeWeightHeld=IsGame("pump") and 0 or 6
|
||||||
GradeWeightHitMine=-8
|
GradeWeightHitMine=-8
|
||||||
GradeWeightMissedHold=0
|
GradeWeightMissedHold=0
|
||||||
GradeWeightLetGo=0
|
GradeWeightLetGo=0
|
||||||
|
|||||||
@@ -2616,7 +2616,8 @@ void NoteDataUtil::SetHopoPossibleFlags( const Song *pSong, NoteData& ndInOut )
|
|||||||
unsigned int NoteDataUtil::GetTotalHoldTicks( NoteData* nd, const TimingData* td )
|
unsigned int NoteDataUtil::GetTotalHoldTicks( NoteData* nd, const TimingData* td )
|
||||||
{
|
{
|
||||||
unsigned int ret = 0;
|
unsigned int ret = 0;
|
||||||
int end = nd->GetLastRow();
|
// Last row must be included. -- Matt
|
||||||
|
int end = nd->GetLastRow()+1;
|
||||||
vector<TimingSegment*> segments = td->GetTimingSegments( SEGMENT_TICKCOUNT );
|
vector<TimingSegment*> segments = td->GetTimingSegments( SEGMENT_TICKCOUNT );
|
||||||
// We start with the LAST TimingSegment and work our way backwards.
|
// We start with the LAST TimingSegment and work our way backwards.
|
||||||
// This way we can continually update end instead of having to lookup when
|
// This way we can continually update end instead of having to lookup when
|
||||||
@@ -2627,9 +2628,10 @@ unsigned int NoteDataUtil::GetTotalHoldTicks( NoteData* nd, const TimingData* td
|
|||||||
if( ts->GetTicks() > 0)
|
if( ts->GetTicks() > 0)
|
||||||
{
|
{
|
||||||
// Jump to each point where holds would tick and add the number of holds there to ret.
|
// Jump to each point where holds would tick and add the number of holds there to ret.
|
||||||
// XXX: Assuming each segment starts on the beat
|
|
||||||
for(int j = ts->GetRow(); j < end; j += ROWS_PER_BEAT / ts->GetTicks() )
|
for(int j = ts->GetRow(); j < end; j += ROWS_PER_BEAT / ts->GetTicks() )
|
||||||
ret += nd->GetNumTracksHeldAtRow(j);
|
// 1 tick per row.
|
||||||
|
if( nd->GetNumTracksHeldAtRow(j) > 0 )
|
||||||
|
ret++;
|
||||||
}
|
}
|
||||||
end = ts->GetRow();
|
end = ts->GetRow();
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-34
@@ -1289,7 +1289,7 @@ void Player::UpdateHoldNotes( int iSongRow, float fDeltaTime, vector<TrackRowTap
|
|||||||
// For tickholds, the concept of "life" doesn't really apply.
|
// For tickholds, the concept of "life" doesn't really apply.
|
||||||
// XXX: if IMMEDIATE_HOLD_LET_GO this will kill holds if it's EVER let go,
|
// XXX: if IMMEDIATE_HOLD_LET_GO this will kill holds if it's EVER let go,
|
||||||
// not just at the first missed checkpoint.
|
// not just at the first missed checkpoint.
|
||||||
if( GAMESTATE->GetCurrentGame()->m_bTickHolds ) fLife = 0.0;
|
if( m_bTickHolds ) fLife = 0.0;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Decrease life
|
// Decrease life
|
||||||
@@ -3022,23 +3022,16 @@ void Player::CrossedRows( int iLastRowCrossed, const RageTimer &now )
|
|||||||
* TODO: Move this to a separate function. */
|
* TODO: Move this to a separate function. */
|
||||||
if( m_bTickHolds && m_pPlayerState->m_PlayerController != PC_AUTOPLAY )
|
if( m_bTickHolds && m_pPlayerState->m_PlayerController != PC_AUTOPLAY )
|
||||||
{
|
{
|
||||||
int tickCurrent = m_Timing->GetTickcountAtRow( iLastRowCrossed );
|
// Few rows typically cross per update. Easier to check all crossed rows
|
||||||
// There are some charts that don't want tickcounts involved at all.
|
// than to calculate from timing segments.
|
||||||
int iCheckpointFrequencyRows = ( tickCurrent > 0 ? ROWS_PER_BEAT / tickCurrent : 0 );
|
for( int r = m_iFirstUncrossedRow; r <= iLastRowCrossed; ++r )
|
||||||
|
|
||||||
if( iCheckpointFrequencyRows > 0 )
|
|
||||||
{
|
{
|
||||||
// "the first row after the start of the range that lands on a beat"
|
int tickCurrent = m_Timing->GetTickcountAtRow( r );
|
||||||
int iFirstCheckpointInRange = ((m_iFirstUncrossedRow+iCheckpointFrequencyRows-1)
|
|
||||||
/iCheckpointFrequencyRows) * iCheckpointFrequencyRows;
|
|
||||||
|
|
||||||
// "the last row or first row earlier that lands on a beat"
|
// There is a tick count at this row
|
||||||
int iLastCheckpointInRange = ((iLastRowCrossed)/iCheckpointFrequencyRows)
|
if( tickCurrent > 0 && r % ( ROWS_PER_BEAT / tickCurrent ) == 0 )
|
||||||
* iCheckpointFrequencyRows;
|
|
||||||
|
|
||||||
for( int r = iFirstCheckpointInRange; r <= iLastCheckpointInRange; r += iCheckpointFrequencyRows )
|
|
||||||
{
|
{
|
||||||
//LOG->Trace( "%d...", r );
|
|
||||||
vector<int> viColsWithHold;
|
vector<int> viColsWithHold;
|
||||||
int iNumHoldsHeldThisRow = 0;
|
int iNumHoldsHeldThisRow = 0;
|
||||||
int iNumHoldsMissedThisRow = 0;
|
int iNumHoldsMissedThisRow = 0;
|
||||||
@@ -3051,25 +3044,7 @@ void Player::CrossedRows( int iLastRowCrossed, const RageTimer &now )
|
|||||||
if( tn.type != TapNote::hold_head )
|
if( tn.type != TapNote::hold_head )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int iStartRow = nIter.Row();
|
|
||||||
int iEndRow = iStartRow + tn.iDuration;
|
|
||||||
int iTrack = nIter.Track();
|
int iTrack = nIter.Track();
|
||||||
|
|
||||||
// "the first row after the hold head that lands on a beat"
|
|
||||||
int iFirstCheckpointOfHold = ((iStartRow+iCheckpointFrequencyRows)/iCheckpointFrequencyRows)
|
|
||||||
* iCheckpointFrequencyRows;
|
|
||||||
|
|
||||||
// "the end row or the first earlier row that lands on a beat"
|
|
||||||
int iLastCheckpointOfHold = ((iEndRow)/iCheckpointFrequencyRows)
|
|
||||||
* iCheckpointFrequencyRows;
|
|
||||||
|
|
||||||
// count the end of the hold as a checkpoint
|
|
||||||
bool bHoldOverlapsRow = iFirstCheckpointOfHold <= r && r <= iLastCheckpointOfHold;
|
|
||||||
if( !bHoldOverlapsRow )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
viColsWithHold.push_back( iTrack );
|
viColsWithHold.push_back( iTrack );
|
||||||
|
|
||||||
if( tn.HoldResult.fLife > 0 )
|
if( tn.HoldResult.fLife > 0 )
|
||||||
@@ -3086,7 +3061,7 @@ void Player::CrossedRows( int iLastRowCrossed, const RageTimer &now )
|
|||||||
GAMESTATE->SetProcessedTimingData(this->m_Timing);
|
GAMESTATE->SetProcessedTimingData(this->m_Timing);
|
||||||
|
|
||||||
// TODO: Find a better way of handling hold checkpoints with other taps.
|
// TODO: Find a better way of handling hold checkpoints with other taps.
|
||||||
if( !viColsWithHold.empty() && ( CHECKPOINTS_TAPS_SEPARATE_JUDGMENT || m_NoteData.GetNumTapNotesInRow( iLastRowCrossed ) == 0 ) )
|
if( !viColsWithHold.empty() && ( CHECKPOINTS_TAPS_SEPARATE_JUDGMENT || m_NoteData.GetNumTapNotesInRow( r ) == 0 ) )
|
||||||
{
|
{
|
||||||
HandleHoldCheckpoint(r,
|
HandleHoldCheckpoint(r,
|
||||||
iNumHoldsHeldThisRow,
|
iNumHoldsHeldThisRow,
|
||||||
|
|||||||
Reference in New Issue
Block a user