fix incorrect song counts for courses

cleanup: make StageStats hold a list of Songs and Steps that were played during the stage
This commit is contained in:
Chris Danford
2004-08-30 04:09:23 +00:00
parent 6ac1d7c449
commit 081c1e24b5
11 changed files with 157 additions and 132 deletions
+42 -49
View File
@@ -227,19 +227,6 @@ void GameState::BeginGame()
MEMCARDMAN->LockCards( false );
}
void CheckStageStats( const StageStats &ss, int p )
{
if( ss.pSong )
CHECKPOINT_M( ss.pSong->GetFullTranslitTitle() );
ASSERT( ss.pSteps[p] );
ASSERT_M( ss.playMode < NUM_PLAY_MODES, ssprintf("playmode %i", ss.playMode) );
ASSERT( ss.pStyle != NULL );
ASSERT_M( ss.pSteps[p]->GetDifficulty() < NUM_DIFFICULTIES, ssprintf("difficulty %i", ss.pSteps[p]->GetDifficulty()) );
/* Meter values can exceed MAX_METER; MAX_METER is just the highest meter value we
* display/track. */
// ASSERT_M( ss.iMeter[p] < MAX_METER+1, ssprintf("%i", ss.iMeter[p]) );
}
void GameState::PlayersFinalized()
{
if( m_bPlayersFinalized )
@@ -288,33 +275,43 @@ void GameState::PlayersFinalized()
}
/* This data is added to each player profile, and to the machine profile per-player. */
void AddPlayerStatsToProfile( Profile *pProfile, const StageStats &ss, PlayerNumber p )
void AddPlayerStatsToProfile( Profile *pProfile, const StageStats &ss, PlayerNumber pn )
{
CheckStageStats( ss, p );
ss.AssertValid( pn );
CHECKPOINT;
const int iMeter = clamp( ss.iMeter[p], 0, MAX_METER );
pProfile->m_iNumSongsPlayedByPlayMode[ss.playMode]++;
StyleID sID;
sID.FromStyle( ss.pStyle );
pProfile->m_iNumSongsPlayedByStyle[sID]++;
pProfile->m_iNumSongsPlayedByDifficulty[ss.pSteps[p]->GetDifficulty()]++;
pProfile->m_iNumSongsPlayedByMeter[iMeter]++;
pProfile->m_iTotalDancePoints += ss.iActualDancePoints[p];
ASSERT( ss.vpSongs.size() == ss.vpSteps[pn].size() );
for( unsigned i=0; i<ss.vpSongs.size(); i++ )
{
Song *pSong = ss.vpSongs[i];
Steps *pSteps = ss.vpSteps[pn][i];
pProfile->m_iNumSongsPlayedByPlayMode[ss.playMode]++;
pProfile->m_iNumSongsPlayedByStyle[sID] ++;
pProfile->m_iNumSongsPlayedByDifficulty[pSteps->GetDifficulty()] ++;
pProfile->m_iNumSongsPlayedByMeter[pSteps->GetMeter()] ++;
}
pProfile->m_iTotalDancePoints += ss.iActualDancePoints[pn];
if( ss.StageType == StageStats::STAGE_EXTRA || ss.StageType == StageStats::STAGE_EXTRA2 )
{
if( ss.bFailed[p] )
if( ss.bFailed[pn] )
++pProfile->m_iNumExtraStagesFailed;
else
++pProfile->m_iNumExtraStagesPassed;
}
if( !ss.bFailed[p] )
{
pProfile->m_iNumSongsPassedByPlayMode[ss.playMode]++;
pProfile->m_iNumSongsPassedByGrade[ss.GetGrade(p)]++;
}
// If you fail in a course, you passed all but the final song.
// FIXME: Not true. If playing with 2 players, one player could have failed earlier.
int iNumSongsPassed = ss.vpSongs.size();
if( ss.bFailed[pn] )
iNumSongsPassed -= 1;
pProfile->m_iNumSongsPassedByPlayMode[ss.playMode] += iNumSongsPassed;
pProfile->m_iNumSongsPassedByGrade[ss.GetGrade(pn)] += iNumSongsPassed;
}
void GameState::EndGame()
@@ -1013,9 +1010,9 @@ StageResult GameState::GetStageResult( PlayerNumber pn ) const
return win;
}
void GameState::GetFinalEvalStatsAndSongs( StageStats& statsOut, vector<Song*>& vSongsOut ) const
void GameState::GetFinalEvalStats( StageStats& statsOut ) const
{
statsOut = StageStats();
statsOut.Init();
// Show stats only for the latest 3 normal songs + passed extra stages
int PassedRegularSongsLeft = 3;
@@ -1035,11 +1032,9 @@ void GameState::GetFinalEvalStatsAndSongs( StageStats& statsOut, vector<Song*>&
}
statsOut.AddStats( s );
vSongsOut.insert( vSongsOut.begin(), s.pSong );
}
if(!vSongsOut.size()) return;
if( statsOut.vpSongs.empty() ) return; // don't divide by 0 below
/* Scale radar percentages back down to roughly 0..1. Don't scale RADAR_NUM_TAPS_AND_HOLDS
* and the rest, which are counters. */
@@ -1047,8 +1042,8 @@ void GameState::GetFinalEvalStatsAndSongs( StageStats& statsOut, vector<Song*>&
{
for( int r = 0; r < RADAR_NUM_TAPS_AND_HOLDS; r++)
{
statsOut.radarPossible[p][r] /= vSongsOut.size();
statsOut.radarActual[p][r] /= vSongsOut.size();
statsOut.radarPossible[p][r] /= statsOut.vpSongs.size();
statsOut.radarActual[p][r] /= statsOut.vpSongs.size();
}
}
}
@@ -1386,7 +1381,6 @@ void GameState::GetRankingFeats( PlayerNumber pn, vector<RankingFeat> &asFeatsOu
case PLAY_MODE_REGULAR:
{
CHECKPOINT;
unsigned i, j;
StepsType st = this->GetCurrentStyle()->m_StepsType;
@@ -1397,13 +1391,13 @@ void GameState::GetRankingFeats( PlayerNumber pn, vector<RankingFeat> &asFeatsOu
//
vector<SongAndSteps> vSongAndSteps;
for( i=0; i<g_vPlayedStageStats.size(); i++ )
for( unsigned i=0; i<g_vPlayedStageStats.size(); i++ )
{
CHECKPOINT_M( ssprintf("%u/%i", i, (int)g_vPlayedStageStats.size() ) );
SongAndSteps sas;
sas.pSong = g_vPlayedStageStats[i].pSong;
sas.pSong = g_vPlayedStageStats[i].vpSongs[0];
ASSERT( sas.pSong );
sas.pSteps = g_vPlayedStageStats[i].pSteps[pn];
sas.pSteps = g_vPlayedStageStats[i].vpSteps[pn][0];
ASSERT( sas.pSteps );
vSongAndSteps.push_back( sas );
}
@@ -1415,7 +1409,7 @@ void GameState::GetRankingFeats( PlayerNumber pn, vector<RankingFeat> &asFeatsOu
vSongAndSteps.erase(toDelete, vSongAndSteps.end());
CHECKPOINT;
for( i=0; i<vSongAndSteps.size(); i++ )
for( unsigned i=0; i<vSongAndSteps.size(); i++ )
{
Song* pSong = vSongAndSteps[i].pSong;
Steps* pSteps = vSongAndSteps[i].pSteps;
@@ -1423,7 +1417,7 @@ void GameState::GetRankingFeats( PlayerNumber pn, vector<RankingFeat> &asFeatsOu
// Find Machine Records
{
HighScoreList &hsl = PROFILEMAN->GetMachineProfile()->GetStepsHighScoreList(pSong,pSteps);
for( j=0; j<hsl.vHighScores.size(); j++ )
for( unsigned j=0; j<hsl.vHighScores.size(); j++ )
{
HighScore &hs = hsl.vHighScores[j];
@@ -1451,7 +1445,7 @@ void GameState::GetRankingFeats( PlayerNumber pn, vector<RankingFeat> &asFeatsOu
if( pProf )
{
HighScoreList &hsl = pProf->GetStepsHighScoreList(pSong,pSteps);
for( j=0; j<hsl.vHighScores.size(); j++ )
for( unsigned j=0; j<hsl.vHighScores.size(); j++ )
{
HighScore &hs = hsl.vHighScores[j];
@@ -1481,8 +1475,7 @@ void GameState::GetRankingFeats( PlayerNumber pn, vector<RankingFeat> &asFeatsOu
CHECKPOINT;
StageStats stats;
vector<Song*> vSongs;
GetFinalEvalStatsAndSongs( stats, vSongs );
GetFinalEvalStats( stats );
// Find Machine Category Records
@@ -1497,11 +1490,11 @@ void GameState::GetRankingFeats( PlayerNumber pn, vector<RankingFeat> &asFeatsOu
RankingFeat feat;
feat.Type = RankingFeat::CATEGORY;
feat.Feat = ssprintf("MR #%d in Type %c (%d)", j+1, 'A'+i, stats.iMeter[pn] );
feat.Feat = ssprintf("MR #%d in Type %c (%d)", j+1, 'A'+rc, stats.GetAverageMeter(pn) );
feat.pStringToFill = &hs.sName;
feat.grade = GRADE_NO_DATA;
feat.iScore = (int) hs.iScore;
feat.fPercentDP = (float) hs.fPercentDP;
feat.iScore = hs.iScore;
feat.fPercentDP = hs.fPercentDP;
asFeatsOut.push_back( feat );
}
}
@@ -1520,11 +1513,11 @@ void GameState::GetRankingFeats( PlayerNumber pn, vector<RankingFeat> &asFeatsOu
RankingFeat feat;
feat.Type = RankingFeat::CATEGORY;
feat.Feat = ssprintf("PR #%d in Type %c (%d)", j+1, 'A'+i, stats.iMeter[pn] );
feat.Feat = ssprintf("PR #%d in Type %c (%d)", j+1, 'A'+rc, stats.GetAverageMeter(pn) );
feat.pStringToFill = &hs.sName;
feat.grade = GRADE_NO_DATA;
feat.iScore = (int) hs.iScore;
feat.fPercentDP = (float) hs.fPercentDP;
feat.iScore = hs.iScore;
feat.fPercentDP = hs.fPercentDP;
asFeatsOut.push_back( feat );
}
}
+1 -1
View File
@@ -211,7 +211,7 @@ public:
StageResult GetStageResult( PlayerNumber pn ) const;
void ResetStageStatistics(); // Call this when it's time to play a new stage.
void GetFinalEvalStatsAndSongs( StageStats& statsOut, vector<Song*>& vSongsOut ) const; // shown on arcade final evaluation
void GetFinalEvalStats( StageStats& statsOut ) const; // shown on final evaluation
//
+2 -2
View File
@@ -338,11 +338,11 @@ void NetworkSyncManager::StartRequest(short position)
unsigned char ctr=0;
Steps * tSteps;
tSteps = g_CurStageStats.pSteps[PLAYER_1];
tSteps = g_CurStageStats.vpSteps[PLAYER_1].back();
if (tSteps!=NULL)
ctr = uint8_t(ctr+tSteps->GetMeter()*16);
tSteps = g_CurStageStats.pSteps[PLAYER_2];
tSteps = g_CurStageStats.vpSteps[PLAYER_2].back();
if (tSteps!=NULL)
ctr = uint8_t(ctr+tSteps->GetMeter());
+2 -2
View File
@@ -146,8 +146,8 @@ ScreenEnding::ScreenEnding( CString sClassName ) : ScreenAttract( sClassName, fa
GAMESTATE->m_pCurCourse = SONGMAN->GetRandomCourse();
GAMESTATE->m_pCurSteps[PLAYER_1] = GAMESTATE->m_pCurSong->GetAllSteps()[0];
GAMESTATE->m_pCurSteps[PLAYER_2] = GAMESTATE->m_pCurSong->GetAllSteps()[0];
g_CurStageStats.pSteps[PLAYER_1] = GAMESTATE->m_pCurSteps[PLAYER_1];
g_CurStageStats.pSteps[PLAYER_2] = GAMESTATE->m_pCurSteps[PLAYER_2];
g_CurStageStats.vpSteps[PLAYER_1].push_back( GAMESTATE->m_pCurSteps[PLAYER_1] );
g_CurStageStats.vpSteps[PLAYER_2].push_back( GAMESTATE->m_pCurSteps[PLAYER_2] );
GAMESTATE->m_PlayerOptions[PLAYER_1].m_fScrollSpeed = 2;
GAMESTATE->m_PlayerOptions[PLAYER_2].m_fScrollSpeed = 2;
GAMESTATE->m_iCurrentStageIndex = 0;
+8 -8
View File
@@ -109,8 +109,8 @@ void ScreenEvaluation::Init()
GAMESTATE->m_pCurCourse = SONGMAN->GetRandomCourse();
GAMESTATE->m_pCurSteps[PLAYER_1] = GAMESTATE->m_pCurSong->GetAllSteps()[0];
GAMESTATE->m_pCurSteps[PLAYER_2] = GAMESTATE->m_pCurSong->GetAllSteps()[0];
g_CurStageStats.pSteps[PLAYER_1] = GAMESTATE->m_pCurSteps[PLAYER_1];
g_CurStageStats.pSteps[PLAYER_2] = GAMESTATE->m_pCurSteps[PLAYER_2];
g_CurStageStats.vpSteps[PLAYER_1].push_back( GAMESTATE->m_pCurSteps[PLAYER_1] );
g_CurStageStats.vpSteps[PLAYER_2].push_back( GAMESTATE->m_pCurSteps[PLAYER_2] );
GAMESTATE->m_PlayerOptions[PLAYER_1].m_fScrollSpeed = 2;
GAMESTATE->m_PlayerOptions[PLAYER_2].m_fScrollSpeed = 2;
GAMESTATE->m_iCurrentStageIndex = 0;
@@ -189,12 +189,10 @@ void ScreenEvaluation::Init()
// Figure out which statistics and songs we're going to display
//
StageStats stageStats;
vector<Song*> vSongsToShow;
switch( m_Type )
{
case summary:
GAMESTATE->GetFinalEvalStatsAndSongs( stageStats, vSongsToShow );
GAMESTATE->GetFinalEvalStats( stageStats );
break;
case stage:
case course:
@@ -333,9 +331,11 @@ void ScreenEvaluation::Init()
break;
case summary:
{
for( unsigned i=0; i<vSongsToShow.size(); i++ )
for( unsigned i=0; i<stageStats.vpSongs.size(); i++ )
{
m_SmallBanner[i].LoadFromSong( vSongsToShow[i] );
Song *pSong = stageStats.vpSongs[i];
m_SmallBanner[i].LoadFromSong( pSong );
m_SmallBanner[i].ScaleToClipped( BANNER_WIDTH, BANNER_HEIGHT );
m_SmallBanner[i].SetName( ssprintf("SmallBanner%d",i+1) );
SET_XY_AND_ON_COMMAND( m_SmallBanner[i] );
@@ -959,7 +959,7 @@ void ScreenEvaluation::CommitScores(
if( stageStats.bFailed[p] )
continue;
float fAverageMeter = stageStats.iMeter[p] / (float)PREFSMAN->m_iNumArcadeStages;
float fAverageMeter = stageStats.GetAverageMeter(p);
rcOut[p] = AverageMeterToRankingCategory( fAverageMeter );
PROFILEMAN->AddCategoryScore( st, rcOut[p], p, hs, iPersonalHighScoreIndexOut[p], iMachineHighScoreIndexOut[p] );
+2 -5
View File
@@ -221,15 +221,12 @@ void ScreenGameplay::Init()
/* Called once per stage (single song or single course). */
GAMESTATE->BeginStage();
g_CurStageStats.pSong = NULL; // set in LoadNextSong
g_CurStageStats.playMode = GAMESTATE->m_PlayMode;
g_CurStageStats.pStyle = GAMESTATE->m_pCurStyle;
FOREACH_EnabledPlayer(p)
{
ASSERT( !m_vpStepsQueue[p].empty() );
g_CurStageStats.pSteps[p] = m_vpStepsQueue[p][0];
g_CurStageStats.iMeter[p] = m_vpStepsQueue[p][0]->GetMeter();
/* Record combo rollover. */
g_CurStageStats.UpdateComboList( p, 0, true );
@@ -877,7 +874,7 @@ void ScreenGameplay::LoadNextSong()
int iPlaySongIndex = GAMESTATE->GetCourseSongIndex();
iPlaySongIndex %= m_apSongsQueue.size();
GAMESTATE->m_pCurSong = m_apSongsQueue[iPlaySongIndex];
g_CurStageStats.pSong = GAMESTATE->m_pCurSong;
g_CurStageStats.vpSongs.push_back( GAMESTATE->m_pCurSong );
// No need to do this here. We do it in SongFinished().
//GAMESTATE->RemoveAllActiveAttacks();
@@ -899,7 +896,7 @@ void ScreenGameplay::LoadNextSong()
Song* pSong = GAMESTATE->m_pCurSong;
Steps* pSteps = GAMESTATE->m_pCurSteps[p];
g_CurStageStats.pSteps[p] = pSteps;
g_CurStageStats.vpSteps[p].push_back( pSteps );
ASSERT( GAMESTATE->m_pCurSteps[p] );
m_textStepsDescription[p].SetText( GAMESTATE->m_pCurSteps[p]->GetDescription() );
+16 -16
View File
@@ -136,32 +136,32 @@ ScreenNameEntryTraditional::ScreenNameEntryTraditional( CString sClassName ) : S
StageStats ss;
for( int z = 0; z < 3; ++z )
{
ss.pSong = SONGMAN->GetRandomSong();
ss.vpSongs.push_back( SONGMAN->GetRandomSong() );
ss.iPossibleDancePoints[PLAYER_1] = 100;
ss.iActualDancePoints[PLAYER_1] = 100;
ss.iScore[PLAYER_1] = 100;
ss.iPossibleDancePoints[PLAYER_2] = 100;
ss.iActualDancePoints[PLAYER_2] = 100;
ss.iScore[PLAYER_2] = 100;
ASSERT( ss.pSong );
ASSERT( ss.pSong->GetAllSteps().size() );
ASSERT( ss.vpSongs[0]->GetAllSteps().size() );
FOREACH_PlayerNumber( p )
{
GAMESTATE->m_pCurSteps[p] = ss.pSteps[p] = ss.pSong->GetAllSteps()[0];
ss.vpSteps[p].push_back( ss.vpSongs[0]->GetAllSteps()[0] );
GAMESTATE->m_pCurSteps[p] = ss.vpSteps[p][0];
ss.iPossibleDancePoints[p] = 1000;
ss.iActualDancePoints[p] = 985;
HighScore hs;
hs.grade = GRADE_TIER_3;
hs.fPercentDP = ss.GetPercentDancePoints((PlayerNumber)p);
hs.fPercentDP = ss.GetPercentDancePoints(p);
hs.iScore = ss.iScore[p];
StepsType st = GAMESTATE->GetCurrentStyle()->m_StepsType;
int a, b;
PROFILEMAN->AddStepsScore( ss.pSong, GAMESTATE->m_pCurSteps[p], (PlayerNumber)p, hs, a, b );
PROFILEMAN->AddStepsScore( ss.pSong, GAMESTATE->m_pCurSteps[p], (PlayerNumber)p, hs, a, b );
PROFILEMAN->AddStepsScore( ss.pSong, GAMESTATE->m_pCurSteps[p], (PlayerNumber)p, hs, a, b );
PROFILEMAN->AddStepsScore( ss.pSong, GAMESTATE->m_pCurSteps[p], (PlayerNumber)p, hs, a, b );
PROFILEMAN->AddStepsScore( ss.pSong, GAMESTATE->m_pCurSteps[p], (PlayerNumber)p, hs, a, b );
PROFILEMAN->AddStepsScore( ss.vpSongs[0], GAMESTATE->m_pCurSteps[p], p, hs, a, b );
PROFILEMAN->AddStepsScore( ss.vpSongs[0], GAMESTATE->m_pCurSteps[p], p, hs, a, b );
PROFILEMAN->AddStepsScore( ss.vpSongs[0], GAMESTATE->m_pCurSteps[p], p, hs, a, b );
PROFILEMAN->AddStepsScore( ss.vpSongs[0], GAMESTATE->m_pCurSteps[p], p, hs, a, b );
PROFILEMAN->AddStepsScore( ss.vpSongs[0], GAMESTATE->m_pCurSteps[p], p, hs, a, b );
PROFILEMAN->AddCategoryScore( st, RANKING_A, p, hs, a, b );
}
@@ -175,7 +175,7 @@ ScreenNameEntryTraditional::ScreenNameEntryTraditional( CString sClassName ) : S
FOREACH_PlayerNumber( p )
{
vector<GameState::RankingFeat> aFeats;
GAMESTATE->GetRankingFeats( (PlayerNumber)p, aFeats );
GAMESTATE->GetRankingFeats( p, aFeats );
m_bStillEnteringName[p] = aFeats.size()>0;
m_CurFeat[p] = 0;
}
@@ -265,7 +265,7 @@ ScreenNameEntryTraditional::ScreenNameEntryTraditional( CString sClassName ) : S
PositionCharsAndCursor( p );
// load last used ranking name if any
const Profile* pProfile = PROFILEMAN->GetProfile((PlayerNumber)p);
const Profile* pProfile = PROFILEMAN->GetProfile(p);
if( pProfile && !pProfile->m_sLastUsedHighScoreName.empty() )
{
m_sSelection[p] = CStringToWstring( pProfile->m_sLastUsedHighScoreName );
@@ -273,7 +273,7 @@ ScreenNameEntryTraditional::ScreenNameEntryTraditional( CString sClassName ) : S
m_sSelection[p].erase( MAX_RANKING_NAME_LENGTH );
ASSERT( (int) m_sSelection[p].size() <= MAX_RANKING_NAME_LENGTH );
if( m_sSelection[p].size() )
SelectChar( (PlayerNumber) p, CHAR_OK );
SelectChar( p, CHAR_OK );
}
UpdateSelectionText( p );
@@ -308,8 +308,8 @@ ScreenNameEntryTraditional::ScreenNameEntryTraditional( CString sClassName ) : S
for( unsigned i = 0; i < g_vPlayedStageStats.size(); ++i )
{
StageStats &ss = g_vPlayedStageStats[i];
Song* pSong = ss.pSong;
Steps* pSteps = ss.pSteps[p];
Song* pSong = ss.vpSongs[0];
Steps* pSteps = ss.vpSteps[p][0];
Course* pCourse = GAMESTATE->m_pCurCourse;
Trail* pTrail = GAMESTATE->m_pCurTrail[p];
@@ -536,7 +536,7 @@ void ScreenNameEntryTraditional::HandleScreenMessage( const ScreenMessage SM )
if( !m_Out.IsTransitioning() )
{
FOREACH_PlayerNumber( p )
Finish( (PlayerNumber)p );
Finish( p );
MenuStart( PLAYER_INVALID, IET_FIRST_PRESS );
}
break;
+1 -1
View File
@@ -1055,7 +1055,7 @@ void ScreenSelectMusic::MenuStart( PlayerNumber pn )
if( PREFSMAN->m_bEventMode )
i = max( 0, int(g_vPlayedStageStats.size())-5 );
for( ; i < (int)g_vPlayedStageStats.size(); ++i )
if( g_vPlayedStageStats[i].pSong == m_MusicWheel.GetSelectedSong() )
if( g_vPlayedStageStats[i].vpSongs.back() == m_MusicWheel.GetSelectedSong() )
bIsRepeat = true;
/* Don't complain about repeats if the user didn't get to pick. */
+29 -28
View File
@@ -695,24 +695,23 @@ void SongManager::RevertFromDisk( Song *pSong, bool bAllowNotesLoss )
// Fix GAMESTATE->m_CurSteps, g_CurStageStats, g_vPlayedStageStats[] after reloading.
/* XXX: This is very brittle. However, we must know about all globals uses of Steps*,
* so we can check to make sure we didn't lose any steps which are referenced ... */
StepsID OldCurSteps[NUM_PLAYERS];
StepsID OldCurStageStats[NUM_PLAYERS];
vector<StepsID> OldPlayedStageStats[NUM_PLAYERS];
FOREACH_PlayerNumber( p )
{
Steps* pCurSteps = GAMESTATE->m_pCurSteps[p];
Steps* pCurStageStats = g_CurStageStats.pSteps[p];
OldCurSteps[p].FromSteps( pCurSteps );
OldCurStageStats[p].FromSteps( pCurStageStats );
for( unsigned i = 0; i < g_vPlayedStageStats.size(); ++i )
{
const StageStats &ss = g_vPlayedStageStats[i];;
OldPlayedStageStats[p].push_back( StepsID() );
OldPlayedStageStats[p][i].FromSteps( ss.pSteps[p] );
}
//
// Save list of all old Steps pointers for the song
//
map<Steps*,StepsID> mapOldStepsToStepsID;
FOREACH_CONST( Steps*, pSong->GetAllSteps(), pSteps )
{
StepsID id;
id.FromSteps( *pSteps );
mapOldStepsToStepsID[*pSteps] = id;
}
//
// Reload the song
//
const CString dir = pSong->GetSongDir();
FILEMAN->FlushDirCache( dir );
@@ -734,21 +733,23 @@ void SongManager::RevertFromDisk( Song *pSong, bool bAllowNotesLoss )
StepsID::Invalidate( pSong );
#define CONVERT_STEPS_POINTER( pSteps ) { \
StepsID id = mapOldStepsToStepsID[pSteps]; /* this will always succeed */ \
pSteps = id.ToSteps( pSong, bAllowNotesLoss ); }
FOREACH_PlayerNumber( p )
{
CHECKPOINT;
if( GAMESTATE->m_pCurSong == pSong )
GAMESTATE->m_pCurSteps[p] = OldCurSteps[p].ToSteps( pSong, bAllowNotesLoss );
CHECKPOINT;
if( g_CurStageStats.pSong == pSong )
g_CurStageStats.pSteps[p] = OldCurStageStats[p].ToSteps( pSong, bAllowNotesLoss );
CHECKPOINT;
for( unsigned i = 0; i < g_vPlayedStageStats.size(); ++i )
{
CHECKPOINT_M(ssprintf("%i", i));
if( g_vPlayedStageStats[i].pSong == pSong )
g_vPlayedStageStats[i].pSteps[p] = OldPlayedStageStats[p][i].ToSteps( pSong, bAllowNotesLoss );
}
CONVERT_STEPS_POINTER( GAMESTATE->m_pCurSteps[p] );
FOREACH( Steps*, g_CurStageStats.vpSteps[p], pSteps )
CONVERT_STEPS_POINTER( *pSteps );
FOREACH( StageStats, g_vPlayedStageStats, ss )
FOREACH( Steps*, ss->vpSteps[p], pSteps )
CONVERT_STEPS_POINTER( *pSteps );
}
}
+48 -17
View File
@@ -5,6 +5,9 @@
#include "SongManager.h"
#include "RageUtil.h"
#include "PrefsManager.h"
#include "Foreach.h"
#include "Steps.h"
#include "Song.h"
StageStats g_CurStageStats;
vector<StageStats> g_vPlayedStageStats;
@@ -13,14 +16,13 @@ void StageStats::Init()
{
playMode = PLAY_MODE_INVALID;
pStyle = NULL;
pSong = NULL;
vpSongs.clear();
StageType = STAGE_INVALID;
fGameplaySeconds = 0;
FOREACH_PlayerNumber( p )
{
pSteps[p] = NULL;
iMeter[p] = 0;
vpSteps[p].clear();
fAliveSeconds[p] = 0;
bFailed[p] = bFailedEarlier[p] = false;
iPossibleDancePoints[p] = iActualDancePoints[p] = 0;
@@ -39,22 +41,53 @@ void StageStats::Init()
}
}
void StageStats::AssertValid( PlayerNumber pn ) const
{
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 )
{
pSong = NULL; // meaningless
ASSERT( !other.vpSongs.empty() );
FOREACH_CONST( Song*, other.vpSongs, s )
vpSongs.push_back( *s );
StageType = STAGE_INVALID; // meaningless
memset( fAliveSeconds, 0, sizeof(fAliveSeconds) ); // why? -Chris
memset( fAliveSeconds, 0, sizeof(fAliveSeconds) ); // why not accumulate? -Chris
// weight long and marathon songs
ASSERT( other.pSong );
const int iLengthMultiplier = SongManager::GetNumStagesForSong( other.pSong );
fGameplaySeconds += other.fGameplaySeconds;
FOREACH_PlayerNumber( p )
{
pSteps[p] = NULL;
iMeter[p] += other.iMeter[p] * iLengthMultiplier;
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];
@@ -496,22 +529,20 @@ Grade GetFinalGrade( PlayerNumber pn )
{
if( !GAMESTATE->IsHumanPlayer(pn) )
return GRADE_NO_DATA;
vector<Song*> vSongs;
StageStats stats;
GAMESTATE->GetFinalEvalStatsAndSongs( stats, vSongs );
GAMESTATE->GetFinalEvalStats( stats );
return stats.GetGrade( pn );
}
LuaFunction_PlayerNumber( GetFinalGrade, GetFinalGrade( pn ) );
LuaFunction_PlayerNumber( GetFinalGrade, GetFinalGrade(pn) );
Grade GetBestFinalGrade()
{
Grade top_grade = GRADE_FAILED;
vector<Song*> vSongs;
StageStats stats;
GAMESTATE->GetFinalEvalStatsAndSongs( stats, vSongs );
GAMESTATE->GetFinalEvalStats( stats );
FOREACH_PlayerNumber( p )
if( GAMESTATE->IsHumanPlayer(p) )
top_grade = min( top_grade, stats.GetGrade((PlayerNumber)p) );
top_grade = min( top_grade, stats.GetGrade(p) );
return top_grade;
}
LuaFunction_NoArgs( GetBestFinalGrade, GetBestFinalGrade() );
+6 -3
View File
@@ -16,6 +16,9 @@ struct StageStats
{
StageStats() { Init(); }
void Init();
void AssertValid( PlayerNumber pn ) const;
void AddStats( const StageStats& other ); // accumulate
Grade GetGrade( PlayerNumber pn ) const;
bool OnePassed() const;
@@ -25,10 +28,10 @@ struct StageStats
PlayMode playMode;
const Style* pStyle;
Song* pSong;
vector<Song*> vpSongs;
enum { STAGE_INVALID, STAGE_NORMAL, STAGE_EXTRA, STAGE_EXTRA2 } StageType;
Steps* pSteps[NUM_PLAYERS];
int iMeter[NUM_PLAYERS];
vector<Steps*> vpSteps[NUM_PLAYERS];
int GetAverageMeter( PlayerNumber pn ) const;
float fAliveSeconds[NUM_PLAYERS]; // how far into the music did they last before failing? Updated by Gameplay, scaled by music rate.
float fGameplaySeconds; // how many seconds before gameplay ended. Updated by Gameplay, not scaled by music rate.