fix combo and life history don't accumulate correctly in courses

change combo and life history position units to Seconds from Beats
This commit is contained in:
Chris Danford
2004-07-24 18:11:04 +00:00
parent fa6f155c70
commit 05257b050c
7 changed files with 59 additions and 60 deletions
+5 -5
View File
@@ -27,14 +27,14 @@ void ComboGraph::Load( CString Path, const StageStats &s, PlayerNumber pn )
const bool IsMax = (combo.GetStageCnt() == MaxComboSize); const bool IsMax = (combo.GetStageCnt() == MaxComboSize);
LOG->Trace("combo %i is %f+%f", i, combo.start, combo.size); LOG->Trace("combo %i is %f+%f", i, combo.fStartSecond, combo.fSizeSeconds);
Sprite *sprite = new Sprite; Sprite *sprite = new Sprite;
sprite->SetName( "ComboBar" ); sprite->SetName( "ComboBar" );
const CString path = ssprintf( "%s %s", Path.c_str(), IsMax? "max":"normal" ); const CString path = ssprintf( "%s %s", Path.c_str(), IsMax? "max":"normal" );
sprite->Load( THEME->GetPathToG(path) ); sprite->Load( THEME->GetPathToG(path) );
const float start = SCALE( combo.start, s.fFirstPos[pn], s.fLastPos[pn], 0.0f, 1.0f ); const float start = SCALE( combo.fStartSecond, s.fFirstSecond[pn], s.fLastSecond[pn], 0.0f, 1.0f );
const float size = SCALE( combo.size, 0, s.fLastPos[pn]-s.fFirstPos[pn], 0.0f, 1.0f ); const float size = SCALE( combo.fSizeSeconds, 0, s.fLastSecond[pn]-s.fFirstSecond[pn], 0.0f, 1.0f );
sprite->SetCropLeft ( SCALE( size, 0.0f, 1.0f, 0.5f, 0.0f ) ); sprite->SetCropLeft ( SCALE( size, 0.0f, 1.0f, 0.5f, 0.0f ) );
sprite->SetCropRight( SCALE( size, 0.0f, 1.0f, 0.5f, 0.0f ) ); sprite->SetCropRight( SCALE( size, 0.0f, 1.0f, 0.5f, 0.0f ) );
@@ -66,8 +66,8 @@ void ComboGraph::Load( CString Path, const StageStats &s, PlayerNumber pn )
text->SetName( "ComboMaxNumber" ); text->SetName( "ComboMaxNumber" );
text->LoadFromFont( THEME->GetPathToF(Path) ); text->LoadFromFont( THEME->GetPathToF(Path) );
const float start = SCALE( combo.start, s.fFirstPos[pn], s.fLastPos[pn], 0.0f, 1.0f ); const float start = SCALE( combo.fStartSecond, s.fFirstSecond[pn], s.fLastSecond[pn], 0.0f, 1.0f );
const float size = SCALE( combo.size, 0, s.fLastPos[pn]-s.fFirstPos[pn], 0.0f, 1.0f ); const float size = SCALE( combo.fSizeSeconds, 0, s.fLastSecond[pn]-s.fFirstSecond[pn], 0.0f, 1.0f );
const float CenterPercent = start + size/2; const float CenterPercent = start + size/2;
const float CenterXPos = SCALE( CenterPercent, 0.0f, 1.0f, -width/2.0f, width/2.0f ); const float CenterXPos = SCALE( CenterPercent, 0.0f, 1.0f, -width/2.0f, width/2.0f );
+1 -1
View File
@@ -289,7 +289,7 @@ float NoteDataWithScoring::GetActualVoltageRadarValue( float fSongSeconds, Playe
* keeper. Instead, let's use the length of the longest recorded combo. This is * keeper. Instead, let's use the length of the longest recorded combo. This is
* only subtly different: it's the percent of the song the longest combo took to get. */ * only subtly different: it's the percent of the song the longest combo took to get. */
const StageStats::Combo_t MaxCombo = g_CurStageStats.GetMaxCombo( pn ); const StageStats::Combo_t MaxCombo = g_CurStageStats.GetMaxCombo( pn );
float fComboPercent = SCALE( MaxCombo.size, 0, g_CurStageStats.fLastPos[pn]-g_CurStageStats.fFirstPos[pn], 0.0f, 1.0f ); float fComboPercent = SCALE( MaxCombo.fSizeSeconds, 0, g_CurStageStats.fLastSecond[pn]-g_CurStageStats.fFirstSecond[pn], 0.0f, 1.0f );
return clamp( fComboPercent, 0.0f, 1.0f ); return clamp( fComboPercent, 0.0f, 1.0f );
} }
+2 -2
View File
@@ -1177,7 +1177,7 @@ void PlayerMinus::HandleTapRowScore( unsigned row )
/* Use the real current beat, not the beat we've been passed. That's because we /* Use the real current beat, not the beat we've been passed. That's because we
* want to record the current life/combo to the current time; eg. if it's a MISS, * want to record the current life/combo to the current time; eg. if it's a MISS,
* the beat we're registering is in the past, but the life is changing now. */ * the beat we're registering is in the past, but the life is changing now. */
g_CurStageStats.UpdateComboList( m_PlayerNumber, GAMESTATE->m_fSongBeat, false ); g_CurStageStats.UpdateComboList( m_PlayerNumber, g_CurStageStats.fAliveSeconds[m_PlayerNumber], false );
float life = -1; float life = -1;
if( m_pLifeMeter ) if( m_pLifeMeter )
@@ -1189,7 +1189,7 @@ void PlayerMinus::HandleTapRowScore( unsigned row )
life = 1.0f - life; life = 1.0f - life;
} }
if( life != -1 ) if( life != -1 )
g_CurStageStats.SetLifeRecord( m_PlayerNumber, life, GAMESTATE->m_fSongBeat ); g_CurStageStats.SetLifeRecordAt( m_PlayerNumber, life, g_CurStageStats.fAliveSeconds[m_PlayerNumber] );
if (m_pScoreDisplay) if (m_pScoreDisplay)
m_pScoreDisplay->SetScore(g_CurStageStats.iScore[m_PlayerNumber]); m_pScoreDisplay->SetScore(g_CurStageStats.iScore[m_PlayerNumber]);
+2 -2
View File
@@ -121,8 +121,8 @@ ScreenEnding::ScreenEnding( CString sClassName ) : ScreenAttract( sClassName, fa
for( float f = 0; f < 100.0f; f += 1.0f ) for( float f = 0; f < 100.0f; f += 1.0f )
{ {
float fP1 = fmodf(f/100*4+.3f,1); float fP1 = fmodf(f/100*4+.3f,1);
g_CurStageStats.SetLifeRecord( PLAYER_1, fP1, f ); g_CurStageStats.SetLifeRecordAt( PLAYER_1, fP1, f );
g_CurStageStats.SetLifeRecord( PLAYER_2, 1-fP1, f ); g_CurStageStats.SetLifeRecordAt( PLAYER_2, 1-fP1, f );
} }
g_CurStageStats.iActualDancePoints[PLAYER_1] = rand()%3; g_CurStageStats.iActualDancePoints[PLAYER_1] = rand()%3;
+2 -2
View File
@@ -120,8 +120,8 @@ void ScreenEvaluation::Init()
for( float f = 0; f < 100.0f; f += 1.0f ) for( float f = 0; f < 100.0f; f += 1.0f )
{ {
float fP1 = fmodf(f/100*4+.3f,1); float fP1 = fmodf(f/100*4+.3f,1);
g_CurStageStats.SetLifeRecord( PLAYER_1, fP1, f ); g_CurStageStats.SetLifeRecordAt( PLAYER_1, fP1, f );
g_CurStageStats.SetLifeRecord( PLAYER_2, 1-fP1, f ); g_CurStageStats.SetLifeRecordAt( PLAYER_2, 1-fP1, f );
} }
g_CurStageStats.iActualDancePoints[PLAYER_1] = rand()%3; g_CurStageStats.iActualDancePoints[PLAYER_1] = rand()%3;
+38 -38
View File
@@ -28,15 +28,14 @@ void StageStats::Init()
fSecondsBeforeFail[p] = 0; fSecondsBeforeFail[p] = 0;
iSongsPassed[p] = iSongsPlayed[p] = 0; iSongsPassed[p] = iSongsPlayed[p] = 0;
iTotalError[p] = 0; iTotalError[p] = 0;
fFirstPos[p] = fLastPos[p] = 0;
memset( iTapNoteScores[p], 0, sizeof(iTapNoteScores[p]) ); memset( iTapNoteScores[p], 0, sizeof(iTapNoteScores[p]) );
memset( iHoldNoteScores[p], 0, sizeof(iHoldNoteScores[p]) ); memset( iHoldNoteScores[p], 0, sizeof(iHoldNoteScores[p]) );
radarPossible[p].Init(); radarPossible[p].Init();
radarActual[p].Init(); radarActual[p].Init();
fFirstPos[p] = 999999; fFirstSecond[p] = 999999;
fLastPos[p] = 0; fLastSecond[p] = 0;
} }
} }
@@ -77,15 +76,16 @@ void StageStats::AddStats( const StageStats& other )
iSongsPlayed[p] += other.iSongsPlayed[p]; iSongsPlayed[p] += other.iSongsPlayed[p];
iTotalError[p] += other.iTotalError[p]; iTotalError[p] += other.iTotalError[p];
const float fOtherFirst = other.fFirstPos[p] + fLastPos[p]; const float fOtherFirstSecond = other.fFirstSecond[p] + fLastSecond[p];
const float fOtherLast = other.fLastPos[p] + fLastPos[p]; const float fOtherLastSecond = other.fLastSecond[p] + fLastSecond[p];
fLastSecond[p] = fOtherLastSecond;
map<float,float>::const_iterator it; map<float,float>::const_iterator it;
for( it = other.fLifeRecord[p].begin(); it != other.fLifeRecord[p].end(); ++it ) for( it = other.fLifeRecord[p].begin(); it != other.fLifeRecord[p].end(); ++it )
{ {
const float pos = it->first; const float pos = it->first;
const float life = it->second; const float life = it->second;
fLifeRecord[p][fOtherFirst+pos] = life; fLifeRecord[p][fOtherFirstSecond+pos] = life;
} }
unsigned i; unsigned i;
@@ -94,7 +94,7 @@ void StageStats::AddStats( const StageStats& other )
const Combo_t &combo = other.ComboList[p][i]; const Combo_t &combo = other.ComboList[p][i];
Combo_t newcombo(combo); Combo_t newcombo(combo);
newcombo.start += fOtherFirst; newcombo.fStartSecond += fOtherFirstSecond;
ComboList[p].push_back( newcombo ); ComboList[p].push_back( newcombo );
} }
@@ -104,19 +104,17 @@ void StageStats::AddStats( const StageStats& other )
{ {
Combo_t &prevcombo = ComboList[p][i-1]; Combo_t &prevcombo = ComboList[p][i-1];
Combo_t &combo = ComboList[p][i]; Combo_t &combo = ComboList[p][i];
const float PrevComboEnd = prevcombo.start + prevcombo.size; const float PrevComboEnd = prevcombo.fStartSecond + prevcombo.fSizeSeconds;
const float ThisComboStart = combo.start; const float ThisComboStart = combo.fStartSecond;
if( fabsf(PrevComboEnd - ThisComboStart) > 0.001 ) if( fabsf(PrevComboEnd - ThisComboStart) > 0.001 )
continue; continue;
/* These are really the same combo. */ /* These are really the same combo. */
prevcombo.size += combo.size; prevcombo.fSizeSeconds += combo.fSizeSeconds;
prevcombo.cnt += combo.cnt; prevcombo.cnt += combo.cnt;
ComboList[p].erase( ComboList[p].begin()+i ); ComboList[p].erase( ComboList[p].begin()+i );
--i; --i;
} }
fLastPos[p] = fOtherLast;
} }
} }
@@ -248,28 +246,29 @@ float StageStats::GetPercentDancePoints( PlayerNumber pn ) const
return fPercentDancePoints; return fPercentDancePoints;
} }
void StageStats::SetLifeRecord( PlayerNumber pn, float life, float pos ) void StageStats::SetLifeRecordAt( PlayerNumber pn, float fLife, float fSecond )
{ {
if( pos < 0 ) if( fSecond < 0 )
return; return;
fFirstPos[pn] = min( pos, fFirstPos[pn] ); fFirstSecond[pn] = min( fSecond, fFirstSecond[pn] );
fLastPos[pn] = max( pos, fLastPos[pn] ); fLastSecond[pn] = max( fSecond, fLastSecond[pn] );
LOG->Trace( "fLastSecond = %f", fLastSecond[pn] );
if( !fLifeRecord[pn].empty() ) if( !fLifeRecord[pn].empty() )
{ {
const float old = GetLifeRecordAt( pn, pos ); const float old = GetLifeRecordAt( pn, fSecond );
if( fabsf(old-pos) < 0.001f ) if( fabsf(old-fSecond) < 0.001f )
return; /* no change */ return; /* no change */
} }
fLifeRecord[pn][pos] = life; fLifeRecord[pn][fSecond] = fLife;
} }
float StageStats::GetLifeRecordAt( PlayerNumber pn, float pos ) const float StageStats::GetLifeRecordAt( PlayerNumber pn, float fSecond ) const
{ {
/* Find the first element whose key is not less than k. */ /* Find the first element whose key is not less than k. */
map<float,float>::const_iterator it = fLifeRecord[pn].lower_bound( pos ); map<float,float>::const_iterator it = fLifeRecord[pn].lower_bound( fSecond );
/* Find the first element whose key is less than k. */ /* Find the first element whose key is less than k. */
if( it != fLifeRecord[pn].begin() ) if( it != fLifeRecord[pn].begin() )
@@ -279,10 +278,10 @@ float StageStats::GetLifeRecordAt( PlayerNumber pn, float pos ) const
} }
float StageStats::GetLifeRecordLerpAt( PlayerNumber pn, float pos ) const float StageStats::GetLifeRecordLerpAt( PlayerNumber pn, float fSecond ) const
{ {
/* Find the first element whose key is not less than k. */ /* Find the first element whose key is not less than k. */
map<float,float>::const_iterator later = fLifeRecord[pn].lower_bound( pos ); map<float,float>::const_iterator later = fLifeRecord[pn].lower_bound( fSecond );
/* Find the first element whose key is less than k. */ /* Find the first element whose key is less than k. */
map<float,float>::const_iterator earlier = later; map<float,float>::const_iterator earlier = later;
@@ -293,31 +292,32 @@ float StageStats::GetLifeRecordLerpAt( PlayerNumber pn, float pos ) const
return earlier->second; return earlier->second;
/* earlier <= pos <= later */ /* earlier <= pos <= later */
const float f = SCALE( pos, earlier->first, later->first, 1, 0 ); const float f = SCALE( fSecond, earlier->first, later->first, 1, 0 );
return earlier->second * f + later->second * (1-f); return earlier->second * f + later->second * (1-f);
} }
void StageStats::GetLifeRecord( PlayerNumber pn, float *life, int nout ) const void StageStats::GetLifeRecord( PlayerNumber pn, float *fLifeOut, int iNumSamples ) const
{ {
for( int i = 0; i < nout; ++i ) for( int i = 0; i < iNumSamples; ++i )
{ {
float from = SCALE( i, 0, (float)nout, fFirstPos[pn], fLastPos[pn] ); float from = SCALE( i, 0, (float)iNumSamples, fFirstSecond[pn], fLastSecond[pn] );
life[i] = GetLifeRecordLerpAt( (PlayerNumber)pn, from ); fLifeOut[i] = GetLifeRecordLerpAt( pn, from );
} }
} }
/* If "rollover" is true, we're being called before gameplay begins, so we can record /* 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. */ * the amount of the first combo that comes from the previous song. */
void StageStats::UpdateComboList( PlayerNumber pn, float pos, bool rollover ) void StageStats::UpdateComboList( PlayerNumber pn, float fSecond, bool rollover )
{ {
if( pos < 0 ) if( fSecond < 0 )
return; return;
if( !rollover ) if( !rollover )
{ {
fFirstPos[pn] = min( pos, fFirstPos[pn] ); fFirstSecond[pn] = min( fSecond, fFirstSecond[pn] );
fLastPos[pn] = max( pos, fLastPos[pn] ); fLastSecond[pn] = max( fSecond, fLastSecond[pn] );
LOG->Trace( "fLastSecond = %f", fLastSecond[pn] );
} }
int cnt = iCurCombo[pn]; int cnt = iCurCombo[pn];
@@ -328,7 +328,7 @@ void StageStats::UpdateComboList( PlayerNumber pn, float pos, bool rollover )
{ {
/* If the previous combo (if any) starts on -9999, then we rolled over some /* If the previous combo (if any) starts on -9999, then we rolled over some
* combo, but missed the first step. Remove it. */ * combo, but missed the first step. Remove it. */
if( ComboList[pn].size() && ComboList[pn].back().start == -9999 ) if( ComboList[pn].size() && ComboList[pn].back().fStartSecond == -9999 )
ComboList[pn].erase( ComboList[pn].begin()+ComboList[pn].size()-1, ComboList[pn].end() ); ComboList[pn].erase( ComboList[pn].begin()+ComboList[pn].size()-1, ComboList[pn].end() );
/* This is a new combo. */ /* This is a new combo. */
@@ -338,17 +338,17 @@ void StageStats::UpdateComboList( PlayerNumber pn, float pos, bool rollover )
* a placeholder in and set it on the next call. (Otherwise, start will be less * a placeholder in and set it on the next call. (Otherwise, start will be less
* than fFirstPos.) */ * than fFirstPos.) */
if( rollover ) if( rollover )
NewCombo.start = -9999; NewCombo.fStartSecond = -9999;
else else
NewCombo.start = pos; NewCombo.fStartSecond = fSecond;
ComboList[pn].push_back( NewCombo ); ComboList[pn].push_back( NewCombo );
} }
Combo_t &combo = ComboList[pn].back(); Combo_t &combo = ComboList[pn].back();
combo.size = pos - combo.start; combo.fSizeSeconds = fSecond - combo.fStartSecond;
combo.cnt = cnt; combo.cnt = cnt;
if( !rollover && combo.start == -9999 ) if( !rollover && combo.fStartSecond == -9999 )
combo.start = pos; combo.fStartSecond = fSecond;
if( rollover ) if( rollover )
combo.rollover = cnt; combo.rollover = cnt;
+9 -10
View File
@@ -58,17 +58,16 @@ struct StageStats
int iTotalError[NUM_PLAYERS]; int iTotalError[NUM_PLAYERS];
map<float,float> fLifeRecord[NUM_PLAYERS]; map<float,float> fLifeRecord[NUM_PLAYERS];
void SetLifeRecord( PlayerNumber pn, float life, float pos ); void SetLifeRecordAt( PlayerNumber pn, float fLife, float fSecond );
void GetLifeRecord( PlayerNumber pn, float *life, int nout ) const; void GetLifeRecord( PlayerNumber pn, float *fLifeOut, int iNumSamples ) const;
float GetLifeRecordAt( PlayerNumber pn, float pos ) const; float GetLifeRecordAt( PlayerNumber pn, float fSecond ) const;
float GetLifeRecordLerpAt( PlayerNumber pn, float pos ) const; float GetLifeRecordLerpAt( PlayerNumber pn, float fSecond ) const;
/* pos,combo */
struct Combo_t struct Combo_t
{ {
/* Start and size of this combo, in the same scale as the combo list mapping and /* Start and size of this combo, in the same scale as the combo list mapping and
* the life record. */ * the life record. */
float start, size; float fStartSecond, fSizeSeconds;
/* Combo size, in steps. */ /* Combo size, in steps. */
int cnt; int cnt;
@@ -80,11 +79,11 @@ struct StageStats
/* Get the size of the combo that came from this song. */ /* Get the size of the combo that came from this song. */
int GetStageCnt() const { return cnt - rollover; } int GetStageCnt() const { return cnt - rollover; }
Combo_t(): start(0), size(0), cnt(0), rollover(0) { } Combo_t(): fStartSecond(0), fSizeSeconds(0), cnt(0), rollover(0) { }
bool IsZero() const { return start < 0; } bool IsZero() const { return fStartSecond < 0; }
}; };
vector<Combo_t> ComboList[NUM_PLAYERS]; vector<Combo_t> ComboList[NUM_PLAYERS];
float fFirstPos[NUM_PLAYERS], fLastPos[NUM_PLAYERS]; float fFirstSecond[NUM_PLAYERS], fLastSecond[NUM_PLAYERS];
int GetComboAtStartOfStage( PlayerNumber pn ) const; int GetComboAtStartOfStage( PlayerNumber pn ) const;
bool FullComboOfScore( PlayerNumber pn, TapNoteScore tnsAllGreaterOrEqual ) const; bool FullComboOfScore( PlayerNumber pn, TapNoteScore tnsAllGreaterOrEqual ) const;
@@ -93,7 +92,7 @@ struct StageStats
bool OneOfScore( PlayerNumber pn, TapNoteScore tnsAllGreaterOrEqual ) const; bool OneOfScore( PlayerNumber pn, TapNoteScore tnsAllGreaterOrEqual ) const;
int GetTotalTaps( PlayerNumber pn ) const; int GetTotalTaps( PlayerNumber pn ) const;
float GetPercentageOfTaps( PlayerNumber pn, TapNoteScore tns ) const; float GetPercentageOfTaps( PlayerNumber pn, TapNoteScore tns ) const;
void UpdateComboList( PlayerNumber pn, float pos, bool rollover ); void UpdateComboList( PlayerNumber pn, float fSecond, bool rollover );
Combo_t GetMaxCombo( PlayerNumber pn ) const; Combo_t GetMaxCombo( PlayerNumber pn ) const;
}; };