split StageStats into player-specific and non-player-specific structs
This commit is contained in:
+215
-213
@@ -12,149 +12,94 @@
|
||||
StageStats g_CurStageStats;
|
||||
vector<StageStats> g_vPlayedStageStats;
|
||||
|
||||
void StageStats::Init()
|
||||
void PlayerStageStats::Init()
|
||||
{
|
||||
playMode = PLAY_MODE_INVALID;
|
||||
pStyle = NULL;
|
||||
vpSongs.clear();
|
||||
StageType = STAGE_INVALID;
|
||||
fGameplaySeconds = 0;
|
||||
vpSteps.clear();
|
||||
fAliveSeconds = 0;
|
||||
bFailed = bFailedEarlier = false;
|
||||
iPossibleDancePoints = iActualDancePoints = 0;
|
||||
iCurCombo = iMaxCombo = iCurMissCombo = iScore = iBonus = 0;
|
||||
fSecondsBeforeFail = 0;
|
||||
iSongsPassed = iSongsPlayed = 0;
|
||||
iTotalError = 0;
|
||||
|
||||
FOREACH_PlayerNumber( p )
|
||||
{
|
||||
vpSteps[p].clear();
|
||||
fAliveSeconds[p] = 0;
|
||||
bFailed[p] = bFailedEarlier[p] = false;
|
||||
iPossibleDancePoints[p] = iActualDancePoints[p] = 0;
|
||||
iCurCombo[p] = iMaxCombo[p] = iCurMissCombo[p] = iScore[p] = iBonus[p] = 0;
|
||||
fSecondsBeforeFail[p] = 0;
|
||||
iSongsPassed[p] = iSongsPlayed[p] = 0;
|
||||
iTotalError[p] = 0;
|
||||
ZERO( iTapNoteScores );
|
||||
ZERO( iHoldNoteScores );
|
||||
radarPossible.Zero();
|
||||
radarActual.Zero();
|
||||
|
||||
ZERO( iTapNoteScores[p] );
|
||||
ZERO( iHoldNoteScores[p] );
|
||||
radarPossible[p].Zero();
|
||||
radarActual[p].Zero();
|
||||
|
||||
fFirstSecond[p] = 999999;
|
||||
fLastSecond[p] = 0;
|
||||
}
|
||||
fFirstSecond = 999999;
|
||||
fLastSecond = 0;
|
||||
}
|
||||
|
||||
void StageStats::AssertValid( PlayerNumber pn ) const
|
||||
void PlayerStageStats::AddStats( const PlayerStageStats& other )
|
||||
{
|
||||
if( vpSongs[0] )
|
||||
CHECKPOINT_M( vpSongs[0]->GetFullTranslitTitle() );
|
||||
ASSERT( vpSteps[pn][0] );
|
||||
ASSERT_M( playMode < NUM_PLAY_MODES, ssprintf("playmode %i", playMode) );
|
||||
ASSERT( pStyle != NULL );
|
||||
ASSERT_M( vpSteps[pn][0]->GetDifficulty() < NUM_DIFFICULTIES, ssprintf("difficulty %i", vpSteps[pn][0]->GetDifficulty()) );
|
||||
ASSERT( vpSongs.size() == vpSteps[pn].size() );
|
||||
}
|
||||
|
||||
|
||||
int StageStats::GetAverageMeter( PlayerNumber pn ) const
|
||||
{
|
||||
int iTotalMeter = 0;
|
||||
int iTotalCount = 0;
|
||||
ASSERT( vpSongs.size() == vpSteps[pn].size() );
|
||||
|
||||
for( unsigned i=0; i<vpSongs.size(); i++ )
|
||||
{
|
||||
Song* pSong = vpSongs[i];
|
||||
Steps* pSteps = vpSteps[pn][i];
|
||||
|
||||
// weight long and marathon songs
|
||||
int iWeight = SongManager::GetNumStagesForSong( pSong );
|
||||
int iMeter = pSteps->GetMeter();
|
||||
|
||||
iTotalMeter += iMeter;
|
||||
iTotalCount += iWeight;
|
||||
}
|
||||
return iTotalMeter / iTotalCount; // round down
|
||||
}
|
||||
|
||||
void StageStats::AddStats( const StageStats& other )
|
||||
{
|
||||
ASSERT( !other.vpSongs.empty() );
|
||||
FOREACH_CONST( Song*, other.vpSongs, s )
|
||||
vpSongs.push_back( *s );
|
||||
StageType = STAGE_INVALID; // meaningless
|
||||
memset( fAliveSeconds, 0, sizeof(fAliveSeconds) ); // why not accumulate? -Chris
|
||||
FOREACH_CONST( Steps*, other.vpSteps, s )
|
||||
vpSteps.push_back( *s );
|
||||
fAliveSeconds += other.fAliveSeconds;
|
||||
bFailed |= other.bFailed;
|
||||
bFailedEarlier |= other.bFailedEarlier;
|
||||
iPossibleDancePoints += other.iPossibleDancePoints;
|
||||
iActualDancePoints += other.iActualDancePoints;
|
||||
|
||||
fGameplaySeconds += other.fGameplaySeconds;
|
||||
for( int t=0; t<NUM_TAP_NOTE_SCORES; t++ )
|
||||
iTapNoteScores[t] += other.iTapNoteScores[t];
|
||||
for( int h=0; h<NUM_HOLD_NOTE_SCORES; h++ )
|
||||
iHoldNoteScores[h] += other.iHoldNoteScores[h];
|
||||
iCurCombo += other.iCurCombo;
|
||||
iMaxCombo += other.iMaxCombo;
|
||||
iCurMissCombo += other.iCurMissCombo;
|
||||
iScore += other.iScore;
|
||||
radarPossible += other.radarPossible;
|
||||
radarActual += other.radarActual;
|
||||
fSecondsBeforeFail += other.fSecondsBeforeFail;
|
||||
iSongsPassed += other.iSongsPassed;
|
||||
iSongsPlayed += other.iSongsPlayed;
|
||||
iTotalError += other.iTotalError;
|
||||
|
||||
FOREACH_PlayerNumber( p )
|
||||
const float fOtherFirstSecond = other.fFirstSecond + fLastSecond;
|
||||
const float fOtherLastSecond = other.fLastSecond + fLastSecond;
|
||||
fLastSecond = fOtherLastSecond;
|
||||
|
||||
map<float,float>::const_iterator it;
|
||||
for( it = other.fLifeRecord.begin(); it != other.fLifeRecord.end(); ++it )
|
||||
{
|
||||
FOREACH_CONST( Steps*, other.vpSteps[p], s )
|
||||
vpSteps[p].push_back( *s );
|
||||
fAliveSeconds[p] += other.fAliveSeconds[p];
|
||||
bFailed[p] |= other.bFailed[p];
|
||||
bFailedEarlier[p] |= other.bFailedEarlier[p];
|
||||
iPossibleDancePoints[p] += other.iPossibleDancePoints[p];
|
||||
iActualDancePoints[p] += other.iActualDancePoints[p];
|
||||
|
||||
for( int t=0; t<NUM_TAP_NOTE_SCORES; t++ )
|
||||
iTapNoteScores[p][t] += other.iTapNoteScores[p][t];
|
||||
for( int h=0; h<NUM_HOLD_NOTE_SCORES; h++ )
|
||||
iHoldNoteScores[p][h] += other.iHoldNoteScores[p][h];
|
||||
iCurCombo[p] += other.iCurCombo[p];
|
||||
iMaxCombo[p] += other.iMaxCombo[p];
|
||||
iCurMissCombo[p] += other.iCurMissCombo[p];
|
||||
iScore[p] += other.iScore[p];
|
||||
radarPossible[p] += other.radarPossible[p];
|
||||
radarActual[p] += other.radarActual[p];
|
||||
fSecondsBeforeFail[p] += other.fSecondsBeforeFail[p];
|
||||
iSongsPassed[p] += other.iSongsPassed[p];
|
||||
iSongsPlayed[p] += other.iSongsPlayed[p];
|
||||
iTotalError[p] += other.iTotalError[p];
|
||||
const float pos = it->first;
|
||||
const float life = it->second;
|
||||
fLifeRecord[fOtherFirstSecond+pos] = life;
|
||||
}
|
||||
|
||||
const float fOtherFirstSecond = other.fFirstSecond[p] + fLastSecond[p];
|
||||
const float fOtherLastSecond = other.fLastSecond[p] + fLastSecond[p];
|
||||
fLastSecond[p] = fOtherLastSecond;
|
||||
for( unsigned i=0; i<other.ComboList.size(); ++i )
|
||||
{
|
||||
const Combo_t &combo = other.ComboList[i];
|
||||
|
||||
map<float,float>::const_iterator it;
|
||||
for( it = other.fLifeRecord[p].begin(); it != other.fLifeRecord[p].end(); ++it )
|
||||
{
|
||||
const float pos = it->first;
|
||||
const float life = it->second;
|
||||
fLifeRecord[p][fOtherFirstSecond+pos] = life;
|
||||
}
|
||||
Combo_t newcombo(combo);
|
||||
newcombo.fStartSecond += fOtherFirstSecond;
|
||||
ComboList.push_back( newcombo );
|
||||
}
|
||||
|
||||
for( unsigned i=0; i<other.ComboList[p].size(); ++i )
|
||||
{
|
||||
const Combo_t &combo = other.ComboList[p][i];
|
||||
/* Merge identical combos. This normally only happens in course mode, when a combo
|
||||
* continues between songs. */
|
||||
for( unsigned i=1; i<ComboList.size(); ++i )
|
||||
{
|
||||
Combo_t &prevcombo = ComboList[i-1];
|
||||
Combo_t &combo = ComboList[i];
|
||||
const float PrevComboEnd = prevcombo.fStartSecond + prevcombo.fSizeSeconds;
|
||||
const float ThisComboStart = combo.fStartSecond;
|
||||
if( fabsf(PrevComboEnd - ThisComboStart) > 0.001 )
|
||||
continue;
|
||||
|
||||
Combo_t newcombo(combo);
|
||||
newcombo.fStartSecond += fOtherFirstSecond;
|
||||
ComboList[p].push_back( newcombo );
|
||||
}
|
||||
|
||||
/* Merge identical combos. This normally only happens in course mode, when a combo
|
||||
* continues between songs. */
|
||||
for( unsigned i=1; i<ComboList[p].size(); ++i )
|
||||
{
|
||||
Combo_t &prevcombo = ComboList[p][i-1];
|
||||
Combo_t &combo = ComboList[p][i];
|
||||
const float PrevComboEnd = prevcombo.fStartSecond + prevcombo.fSizeSeconds;
|
||||
const float ThisComboStart = combo.fStartSecond;
|
||||
if( fabsf(PrevComboEnd - ThisComboStart) > 0.001 )
|
||||
continue;
|
||||
|
||||
/* These are really the same combo. */
|
||||
prevcombo.fSizeSeconds += combo.fSizeSeconds;
|
||||
prevcombo.cnt += combo.cnt;
|
||||
ComboList[p].erase( ComboList[p].begin()+i );
|
||||
--i;
|
||||
}
|
||||
/* These are really the same combo. */
|
||||
prevcombo.fSizeSeconds += combo.fSizeSeconds;
|
||||
prevcombo.cnt += combo.cnt;
|
||||
ComboList.erase( ComboList.begin()+i );
|
||||
--i;
|
||||
}
|
||||
}
|
||||
|
||||
Grade StageStats::GetGrade( PlayerNumber pn ) const
|
||||
Grade PlayerStageStats::GetGrade() const
|
||||
{
|
||||
ASSERT( GAMESTATE->IsPlayerEnabled(pn) ); // shouldn't be calling this is player isn't joined!
|
||||
|
||||
if( bFailedEarlier[pn] )
|
||||
if( bFailedEarlier )
|
||||
return GRADE_FAILED;
|
||||
|
||||
/* XXX: This entire calculation should be in ScoreKeeper, but final evaluation
|
||||
@@ -177,8 +122,8 @@ Grade StageStats::GetGrade( PlayerNumber pn ) const
|
||||
case TNS_MARVELOUS: iTapScoreValue = PREFSMAN->m_iGradeWeightMarvelous; break;
|
||||
default: FAIL_M( ssprintf("%i", tns) ); break;
|
||||
}
|
||||
Actual += iTapNoteScores[pn][tns] * iTapScoreValue;
|
||||
Possible += iTapNoteScores[pn][tns] * PREFSMAN->m_iGradeWeightMarvelous;
|
||||
Actual += iTapNoteScores[tns] * iTapScoreValue;
|
||||
Possible += iTapNoteScores[tns] * PREFSMAN->m_iGradeWeightMarvelous;
|
||||
}
|
||||
|
||||
FOREACH_HoldNoteScore( hns )
|
||||
@@ -191,8 +136,8 @@ Grade StageStats::GetGrade( PlayerNumber pn ) const
|
||||
case HNS_OK: iHoldScoreValue = PREFSMAN->m_iGradeWeightOK; break;
|
||||
default: FAIL_M( ssprintf("%i", hns) ); break;
|
||||
}
|
||||
Actual += iHoldNoteScores[pn][hns] * iHoldScoreValue;
|
||||
Possible += iHoldNoteScores[pn][hns] * PREFSMAN->m_iGradeWeightOK;
|
||||
Actual += iHoldNoteScores[hns] * iHoldScoreValue;
|
||||
Possible += iHoldNoteScores[hns] * PREFSMAN->m_iGradeWeightOK;
|
||||
}
|
||||
|
||||
LOG->Trace( "GetGrade: Actual: %f, Possible: %f", Actual, Possible );
|
||||
@@ -213,23 +158,23 @@ Grade StageStats::GetGrade( PlayerNumber pn ) const
|
||||
LOG->Trace( "GetGrade: Grade: %s, %i", GradeToString(grade).c_str(), PREFSMAN->m_bGradeTier02IsAllPerfects );
|
||||
if( PREFSMAN->m_bGradeTier02IsAllPerfects )
|
||||
{
|
||||
if( iTapNoteScores[pn][TNS_MARVELOUS] > 0 &&
|
||||
iTapNoteScores[pn][TNS_PERFECT] == 0 &&
|
||||
iTapNoteScores[pn][TNS_GREAT] == 0 &&
|
||||
iTapNoteScores[pn][TNS_GOOD] == 0 &&
|
||||
iTapNoteScores[pn][TNS_BOO] == 0 &&
|
||||
iTapNoteScores[pn][TNS_MISS] == 0 &&
|
||||
iTapNoteScores[pn][TNS_HIT_MINE] == 0 &&
|
||||
iHoldNoteScores[pn][HNS_NG] == 0 )
|
||||
if( iTapNoteScores[TNS_MARVELOUS] > 0 &&
|
||||
iTapNoteScores[TNS_PERFECT] == 0 &&
|
||||
iTapNoteScores[TNS_GREAT] == 0 &&
|
||||
iTapNoteScores[TNS_GOOD] == 0 &&
|
||||
iTapNoteScores[TNS_BOO] == 0 &&
|
||||
iTapNoteScores[TNS_MISS] == 0 &&
|
||||
iTapNoteScores[TNS_HIT_MINE] == 0 &&
|
||||
iHoldNoteScores[HNS_NG] == 0 )
|
||||
return GRADE_TIER_1;
|
||||
|
||||
if( iTapNoteScores[pn][TNS_PERFECT] > 0 &&
|
||||
iTapNoteScores[pn][TNS_GREAT] == 0 &&
|
||||
iTapNoteScores[pn][TNS_GOOD] == 0 &&
|
||||
iTapNoteScores[pn][TNS_BOO] == 0 &&
|
||||
iTapNoteScores[pn][TNS_MISS] == 0 &&
|
||||
iTapNoteScores[pn][TNS_HIT_MINE] == 0 &&
|
||||
iHoldNoteScores[pn][HNS_NG] == 0 )
|
||||
if( iTapNoteScores[TNS_PERFECT] > 0 &&
|
||||
iTapNoteScores[TNS_GREAT] == 0 &&
|
||||
iTapNoteScores[TNS_GOOD] == 0 &&
|
||||
iTapNoteScores[TNS_BOO] == 0 &&
|
||||
iTapNoteScores[TNS_MISS] == 0 &&
|
||||
iTapNoteScores[TNS_HIT_MINE] == 0 &&
|
||||
iHoldNoteScores[HNS_NG] == 0 )
|
||||
return GRADE_TIER_2;
|
||||
|
||||
return max( grade, GRADE_TIER_3 );
|
||||
@@ -238,87 +183,144 @@ Grade StageStats::GetGrade( PlayerNumber pn ) const
|
||||
return grade;
|
||||
}
|
||||
|
||||
|
||||
void StageStats::Init()
|
||||
{
|
||||
playMode = PLAY_MODE_INVALID;
|
||||
pStyle = NULL;
|
||||
vpSongs.clear();
|
||||
StageType = STAGE_INVALID;
|
||||
fGameplaySeconds = 0;
|
||||
}
|
||||
|
||||
void StageStats::AssertValid( PlayerNumber pn ) const
|
||||
{
|
||||
if( vpSongs[0] )
|
||||
CHECKPOINT_M( vpSongs[0]->GetFullTranslitTitle() );
|
||||
ASSERT( m_player[pn].vpSteps[0] );
|
||||
ASSERT_M( playMode < NUM_PLAY_MODES, ssprintf("playmode %i", playMode) );
|
||||
ASSERT( pStyle != NULL );
|
||||
ASSERT_M( m_player[pn].vpSteps[0]->GetDifficulty() < NUM_DIFFICULTIES, ssprintf("difficulty %i", m_player[pn].vpSteps[0]->GetDifficulty()) );
|
||||
ASSERT( vpSongs.size() == m_player[pn].vpSteps.size() );
|
||||
}
|
||||
|
||||
|
||||
int StageStats::GetAverageMeter( PlayerNumber pn ) const
|
||||
{
|
||||
int iTotalMeter = 0;
|
||||
int iTotalCount = 0;
|
||||
ASSERT( vpSongs.size() == m_player[pn].vpSteps.size() );
|
||||
|
||||
for( unsigned i=0; i<vpSongs.size(); i++ )
|
||||
{
|
||||
Song* pSong = vpSongs[i];
|
||||
Steps* pSteps = m_player[pn].vpSteps[i];
|
||||
|
||||
// weight long and marathon songs
|
||||
int iWeight = SongManager::GetNumStagesForSong( pSong );
|
||||
int iMeter = pSteps->GetMeter();
|
||||
|
||||
iTotalMeter += iMeter;
|
||||
iTotalCount += iWeight;
|
||||
}
|
||||
return iTotalMeter / iTotalCount; // round down
|
||||
}
|
||||
|
||||
void StageStats::AddStats( const StageStats& other )
|
||||
{
|
||||
ASSERT( !other.vpSongs.empty() );
|
||||
FOREACH_CONST( Song*, other.vpSongs, s )
|
||||
vpSongs.push_back( *s );
|
||||
StageType = STAGE_INVALID; // meaningless
|
||||
|
||||
fGameplaySeconds += other.fGameplaySeconds;
|
||||
|
||||
FOREACH_PlayerNumber( p )
|
||||
{
|
||||
m_player[p].AddStats( other.m_player[p] );
|
||||
}
|
||||
}
|
||||
|
||||
bool StageStats::OnePassed() const
|
||||
{
|
||||
FOREACH_PlayerNumber( p )
|
||||
if( GAMESTATE->IsHumanPlayer(p) && !bFailed[p] )
|
||||
if( GAMESTATE->IsHumanPlayer(p) && !m_player[p].bFailed )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool StageStats::AllFailed() const
|
||||
{
|
||||
FOREACH_PlayerNumber( pn )
|
||||
if( GAMESTATE->IsPlayerEnabled(pn) )
|
||||
if( !bFailed[pn] )
|
||||
return false;
|
||||
FOREACH_EnabledPlayer( pn )
|
||||
if( !m_player[pn].bFailed )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool StageStats::AllFailedEarlier() const
|
||||
{
|
||||
FOREACH_PlayerNumber( p )
|
||||
if( GAMESTATE->IsPlayerEnabled(p) && !bFailedEarlier[p] )
|
||||
FOREACH_EnabledPlayer( p )
|
||||
if( !m_player[p].bFailedEarlier )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
float StageStats::GetPercentDancePoints( PlayerNumber pn ) const
|
||||
float PlayerStageStats::GetPercentDancePoints() const
|
||||
{
|
||||
if( iPossibleDancePoints[pn] == 0 )
|
||||
if( iPossibleDancePoints == 0 )
|
||||
return 0; // div/0
|
||||
|
||||
if( iActualDancePoints[pn] == iPossibleDancePoints[pn] )
|
||||
if( iActualDancePoints == iPossibleDancePoints )
|
||||
return 1; // correct for rounding error
|
||||
|
||||
/* This can happen in battle, with transform attacks. */
|
||||
//ASSERT_M( iActualDancePoints[pn] <= iPossibleDancePoints[pn], ssprintf("%i/%i", iActualDancePoints[pn], iPossibleDancePoints[pn]) );
|
||||
//ASSERT_M( iActualDancePoints <= iPossibleDancePoints, ssprintf("%i/%i", iActualDancePoints, iPossibleDancePoints) );
|
||||
|
||||
float fPercentDancePoints = iActualDancePoints[pn] / (float)iPossibleDancePoints[pn];
|
||||
float fPercentDancePoints = iActualDancePoints / (float)iPossibleDancePoints;
|
||||
|
||||
return fPercentDancePoints;
|
||||
}
|
||||
|
||||
void StageStats::SetLifeRecordAt( PlayerNumber pn, float fLife, float fSecond )
|
||||
void PlayerStageStats::SetLifeRecordAt( float fLife, float fSecond )
|
||||
{
|
||||
if( fSecond < 0 )
|
||||
return;
|
||||
|
||||
fFirstSecond[pn] = min( fSecond, fFirstSecond[pn] );
|
||||
fLastSecond[pn] = max( fSecond, fLastSecond[pn] );
|
||||
//LOG->Trace( "fLastSecond = %f", fLastSecond[pn] );
|
||||
fFirstSecond = min( fSecond, fFirstSecond );
|
||||
fLastSecond = max( fSecond, fLastSecond );
|
||||
//LOG->Trace( "fLastSecond = %f", fLastSecond );
|
||||
|
||||
if( !fLifeRecord[pn].empty() )
|
||||
if( !fLifeRecord.empty() )
|
||||
{
|
||||
const float old = GetLifeRecordAt( pn, fSecond );
|
||||
const float old = GetLifeRecordAt( fSecond );
|
||||
if( fabsf(old-fSecond) < 0.001f )
|
||||
return; /* no change */
|
||||
}
|
||||
|
||||
fLifeRecord[pn][fSecond] = fLife;
|
||||
fLifeRecord[fSecond] = fLife;
|
||||
}
|
||||
|
||||
float StageStats::GetLifeRecordAt( PlayerNumber pn, float fSecond ) const
|
||||
float PlayerStageStats::GetLifeRecordAt( float fSecond ) const
|
||||
{
|
||||
/* Find the first element whose key is not less than k. */
|
||||
map<float,float>::const_iterator it = fLifeRecord[pn].lower_bound( fSecond );
|
||||
map<float,float>::const_iterator it = fLifeRecord.lower_bound( fSecond );
|
||||
|
||||
/* Find the first element whose key is less than k. */
|
||||
if( it != fLifeRecord[pn].begin() )
|
||||
if( it != fLifeRecord.begin() )
|
||||
--it;
|
||||
|
||||
return it->second;
|
||||
|
||||
}
|
||||
|
||||
float StageStats::GetLifeRecordLerpAt( PlayerNumber pn, float fSecond ) const
|
||||
float PlayerStageStats::GetLifeRecordLerpAt( float fSecond ) const
|
||||
{
|
||||
/* Find the first element whose key is not less than k. */
|
||||
map<float,float>::const_iterator later = fLifeRecord[pn].lower_bound( fSecond );
|
||||
map<float,float>::const_iterator later = fLifeRecord.lower_bound( fSecond );
|
||||
|
||||
/* Find the first element whose key is less than k. */
|
||||
map<float,float>::const_iterator earlier = later;
|
||||
if( earlier != fLifeRecord[pn].begin() )
|
||||
if( earlier != fLifeRecord.begin() )
|
||||
--earlier;
|
||||
|
||||
if( earlier->first == later->first )
|
||||
@@ -330,39 +332,39 @@ float StageStats::GetLifeRecordLerpAt( PlayerNumber pn, float fSecond ) const
|
||||
}
|
||||
|
||||
|
||||
void StageStats::GetLifeRecord( PlayerNumber pn, float *fLifeOut, int iNumSamples ) const
|
||||
void PlayerStageStats::GetLifeRecord( float *fLifeOut, int iNumSamples ) const
|
||||
{
|
||||
for( int i = 0; i < iNumSamples; ++i )
|
||||
{
|
||||
float from = SCALE( i, 0, (float)iNumSamples, fFirstSecond[pn], fLastSecond[pn] );
|
||||
fLifeOut[i] = GetLifeRecordLerpAt( pn, from );
|
||||
float from = SCALE( i, 0, (float)iNumSamples, fFirstSecond, fLastSecond );
|
||||
fLifeOut[i] = GetLifeRecordLerpAt( from );
|
||||
}
|
||||
}
|
||||
|
||||
/* If "rollover" is true, we're being called before gameplay begins, so we can record
|
||||
* the amount of the first combo that comes from the previous song. */
|
||||
void StageStats::UpdateComboList( PlayerNumber pn, float fSecond, bool rollover )
|
||||
void PlayerStageStats::UpdateComboList( float fSecond, bool rollover )
|
||||
{
|
||||
if( fSecond < 0 )
|
||||
return;
|
||||
|
||||
if( !rollover )
|
||||
{
|
||||
fFirstSecond[pn] = min( fSecond, fFirstSecond[pn] );
|
||||
fLastSecond[pn] = max( fSecond, fLastSecond[pn] );
|
||||
//LOG->Trace( "fLastSecond = %f", fLastSecond[pn] );
|
||||
fFirstSecond = min( fSecond, fFirstSecond );
|
||||
fLastSecond = max( fSecond, fLastSecond );
|
||||
//LOG->Trace( "fLastSecond = %f", fLastSecond );
|
||||
}
|
||||
|
||||
int cnt = iCurCombo[pn];
|
||||
int cnt = iCurCombo;
|
||||
if( !cnt )
|
||||
return; /* no combo */
|
||||
|
||||
if( ComboList[pn].size() == 0 || ComboList[pn].back().cnt >= cnt )
|
||||
if( ComboList.size() == 0 || ComboList.back().cnt >= cnt )
|
||||
{
|
||||
/* If the previous combo (if any) starts on -9999, then we rolled over some
|
||||
* combo, but missed the first step. Remove it. */
|
||||
if( ComboList[pn].size() && ComboList[pn].back().fStartSecond == -9999 )
|
||||
ComboList[pn].erase( ComboList[pn].begin()+ComboList[pn].size()-1, ComboList[pn].end() );
|
||||
if( ComboList.size() && ComboList.back().fStartSecond == -9999 )
|
||||
ComboList.erase( ComboList.begin()+ComboList.size()-1, ComboList.end() );
|
||||
|
||||
/* This is a new combo. */
|
||||
Combo_t NewCombo;
|
||||
@@ -374,10 +376,10 @@ void StageStats::UpdateComboList( PlayerNumber pn, float fSecond, bool rollover
|
||||
NewCombo.fStartSecond = -9999;
|
||||
else
|
||||
NewCombo.fStartSecond = fSecond;
|
||||
ComboList[pn].push_back( NewCombo );
|
||||
ComboList.push_back( NewCombo );
|
||||
}
|
||||
|
||||
Combo_t &combo = ComboList[pn].back();
|
||||
Combo_t &combo = ComboList.back();
|
||||
combo.fSizeSeconds = fSecond - combo.fStartSecond;
|
||||
combo.cnt = cnt;
|
||||
if( !rollover && combo.fStartSecond == -9999 )
|
||||
@@ -389,82 +391,82 @@ void StageStats::UpdateComboList( PlayerNumber pn, float fSecond, bool rollover
|
||||
|
||||
/* This returns the largest combo contained within the song, as if
|
||||
* m_bComboContinuesBetweenSongs is turned off. */
|
||||
StageStats::Combo_t StageStats::GetMaxCombo( PlayerNumber pn ) const
|
||||
PlayerStageStats::Combo_t PlayerStageStats::GetMaxCombo() const
|
||||
{
|
||||
if( ComboList[pn].size() == 0 )
|
||||
if( ComboList.size() == 0 )
|
||||
return Combo_t();
|
||||
|
||||
int m = 0;
|
||||
for( unsigned i = 1; i < ComboList[pn].size(); ++i )
|
||||
for( unsigned i = 1; i < ComboList.size(); ++i )
|
||||
{
|
||||
if( ComboList[pn][i].cnt > ComboList[pn][m].cnt )
|
||||
if( ComboList[i].cnt > ComboList[m].cnt )
|
||||
m = i;
|
||||
}
|
||||
|
||||
return ComboList[pn][m];
|
||||
return ComboList[m];
|
||||
}
|
||||
|
||||
int StageStats::GetComboAtStartOfStage( PlayerNumber pn ) const
|
||||
int PlayerStageStats::GetComboAtStartOfStage() const
|
||||
{
|
||||
if( ComboList[pn].empty() )
|
||||
if( ComboList.empty() )
|
||||
return 0;
|
||||
else
|
||||
return ComboList[pn][0].rollover;
|
||||
return ComboList[0].rollover;
|
||||
}
|
||||
|
||||
bool StageStats::FullComboOfScore( PlayerNumber pn, TapNoteScore tnsAllGreaterOrEqual ) const
|
||||
bool PlayerStageStats::FullComboOfScore( TapNoteScore tnsAllGreaterOrEqual ) const
|
||||
{
|
||||
ASSERT( tnsAllGreaterOrEqual >= TNS_GREAT );
|
||||
ASSERT( tnsAllGreaterOrEqual <= TNS_MARVELOUS );
|
||||
|
||||
if( iHoldNoteScores[pn][HNS_NG] > 0 )
|
||||
if( iHoldNoteScores[HNS_NG] > 0 )
|
||||
return false;
|
||||
|
||||
for( int i=TNS_MISS; i<tnsAllGreaterOrEqual; i++ )
|
||||
{
|
||||
if( iTapNoteScores[pn][i] > 0 )
|
||||
if( iTapNoteScores[i] > 0 )
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool StageStats::SingleDigitsOfScore( PlayerNumber pn, TapNoteScore tnsAllGreaterOrEqual ) const
|
||||
bool PlayerStageStats::SingleDigitsOfScore( TapNoteScore tnsAllGreaterOrEqual ) const
|
||||
{
|
||||
return FullComboOfScore( pn, tnsAllGreaterOrEqual ) &&
|
||||
iTapNoteScores[pn][tnsAllGreaterOrEqual] < 10;
|
||||
return FullComboOfScore( tnsAllGreaterOrEqual ) &&
|
||||
iTapNoteScores[tnsAllGreaterOrEqual] < 10;
|
||||
}
|
||||
|
||||
bool StageStats::OneOfScore( PlayerNumber pn, TapNoteScore tnsAllGreaterOrEqual ) const
|
||||
bool PlayerStageStats::OneOfScore( TapNoteScore tnsAllGreaterOrEqual ) const
|
||||
{
|
||||
return FullComboOfScore( pn, tnsAllGreaterOrEqual ) &&
|
||||
iTapNoteScores[pn][tnsAllGreaterOrEqual] == 1;
|
||||
return FullComboOfScore( tnsAllGreaterOrEqual ) &&
|
||||
iTapNoteScores[tnsAllGreaterOrEqual] == 1;
|
||||
}
|
||||
|
||||
int StageStats::GetTotalTaps( PlayerNumber pn ) const
|
||||
int PlayerStageStats::GetTotalTaps() const
|
||||
{
|
||||
int iTotalTaps = 0;
|
||||
for( int i=TNS_MISS; i<NUM_TAP_NOTE_SCORES; i++ )
|
||||
{
|
||||
iTotalTaps += iTapNoteScores[pn][i];
|
||||
iTotalTaps += iTapNoteScores[i];
|
||||
}
|
||||
return iTotalTaps;
|
||||
}
|
||||
|
||||
float StageStats::GetPercentageOfTaps( PlayerNumber pn, TapNoteScore tns ) const
|
||||
float PlayerStageStats::GetPercentageOfTaps( TapNoteScore tns ) const
|
||||
{
|
||||
int iTotalTaps = 0;
|
||||
for( int i=TNS_MISS; i<NUM_TAP_NOTE_SCORES; i++ )
|
||||
{
|
||||
iTotalTaps += iTapNoteScores[pn][i];
|
||||
iTotalTaps += iTapNoteScores[i];
|
||||
}
|
||||
return iTapNoteScores[pn][tns] / (float)iTotalTaps;
|
||||
return iTapNoteScores[tns] / (float)iTotalTaps;
|
||||
}
|
||||
|
||||
static Grade GetBestGrade()
|
||||
{
|
||||
Grade g = NUM_GRADES;
|
||||
FOREACH_EnabledPlayer( pn )
|
||||
g = min( g, g_CurStageStats.GetGrade( pn ) );
|
||||
g = min( g, g_CurStageStats.m_player[pn].GetGrade() );
|
||||
return g;
|
||||
}
|
||||
|
||||
@@ -472,7 +474,7 @@ static Grade GetWorstGrade()
|
||||
{
|
||||
Grade g = GRADE_TIER_1;
|
||||
FOREACH_EnabledPlayer( pn )
|
||||
g = max( g, g_CurStageStats.GetGrade( pn ) );
|
||||
g = max( g, g_CurStageStats.m_player[pn].GetGrade() );
|
||||
return g;
|
||||
}
|
||||
|
||||
@@ -481,9 +483,9 @@ LuaFunction_NoArgs( GetStagesPlayed, (int) g_vPlayedStageStats.size() );
|
||||
LuaFunction_NoArgs( GetBestGrade, GetBestGrade() );
|
||||
LuaFunction_NoArgs( GetWorstGrade, GetWorstGrade() );
|
||||
LuaFunction_NoArgs( OnePassed, g_CurStageStats.OnePassed() );
|
||||
LuaFunction_PlayerNumber( FullCombo, g_CurStageStats.FullCombo(pn) )
|
||||
LuaFunction_PlayerNumber( MaxCombo, g_CurStageStats.GetMaxCombo(pn).cnt )
|
||||
LuaFunction_PlayerNumber( GetGrade, g_CurStageStats.GetGrade(pn) )
|
||||
LuaFunction_PlayerNumber( FullCombo, g_CurStageStats.m_player[pn].FullCombo() )
|
||||
LuaFunction_PlayerNumber( MaxCombo, g_CurStageStats.m_player[pn].GetMaxCombo().cnt )
|
||||
LuaFunction_PlayerNumber( GetGrade, g_CurStageStats.m_player[pn].GetGrade() )
|
||||
LuaFunction_Str( Grade, StringToGrade(str) );
|
||||
|
||||
const StageStats *GetStageStatsN( int n )
|
||||
@@ -503,7 +505,7 @@ Grade GetGrade( int n, PlayerNumber pn )
|
||||
const StageStats *pStats = GetStageStatsN( n );
|
||||
if( pStats == NULL )
|
||||
return GRADE_NO_DATA;
|
||||
return pStats->GetGrade( pn );
|
||||
return pStats->m_player[pn].GetGrade();
|
||||
}
|
||||
|
||||
bool OneGotGrade( int n, Grade g )
|
||||
@@ -524,7 +526,7 @@ Grade GetFinalGrade( PlayerNumber pn )
|
||||
return GRADE_NO_DATA;
|
||||
StageStats stats;
|
||||
GAMESTATE->GetFinalEvalStats( stats );
|
||||
return stats.GetGrade( pn );
|
||||
return stats.m_player[pn].GetGrade();
|
||||
}
|
||||
LuaFunction_PlayerNumber( GetFinalGrade, GetFinalGrade(pn) );
|
||||
|
||||
@@ -535,7 +537,7 @@ Grade GetBestFinalGrade()
|
||||
GAMESTATE->GetFinalEvalStats( stats );
|
||||
FOREACH_PlayerNumber( p )
|
||||
if( GAMESTATE->IsHumanPlayer(p) )
|
||||
top_grade = min( top_grade, stats.GetGrade(p) );
|
||||
top_grade = min( top_grade, stats.m_player[p].GetGrade() );
|
||||
return top_grade;
|
||||
}
|
||||
LuaFunction_NoArgs( GetBestFinalGrade, GetBestFinalGrade() );
|
||||
|
||||
Reference in New Issue
Block a user