From 081c1e24b594924a0550a694200418895ec0c3ad Mon Sep 17 00:00:00 2001 From: Chris Danford Date: Mon, 30 Aug 2004 04:09:23 +0000 Subject: [PATCH] fix incorrect song counts for courses cleanup: make StageStats hold a list of Songs and Steps that were played during the stage --- stepmania/src/GameState.cpp | 91 +++++++++----------- stepmania/src/GameState.h | 2 +- stepmania/src/NetworkSyncManager.cpp | 4 +- stepmania/src/ScreenEnding.cpp | 4 +- stepmania/src/ScreenEvaluation.cpp | 16 ++-- stepmania/src/ScreenGameplay.cpp | 7 +- stepmania/src/ScreenNameEntryTraditional.cpp | 32 +++---- stepmania/src/ScreenSelectMusic.cpp | 2 +- stepmania/src/SongManager.cpp | 57 ++++++------ stepmania/src/StageStats.cpp | 65 ++++++++++---- stepmania/src/StageStats.h | 9 +- 11 files changed, 157 insertions(+), 132 deletions(-) diff --git a/stepmania/src/GameState.cpp b/stepmania/src/GameState.cpp index f51f3acb57..769b4d9c2d 100644 --- a/stepmania/src/GameState.cpp +++ b/stepmania/src/GameState.cpp @@ -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; im_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& 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& } 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& { 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 &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 &asFeatsOu // vector vSongAndSteps; - for( i=0; i &asFeatsOu vSongAndSteps.erase(toDelete, vSongAndSteps.end()); CHECKPOINT; - for( i=0; i &asFeatsOu // Find Machine Records { HighScoreList &hsl = PROFILEMAN->GetMachineProfile()->GetStepsHighScoreList(pSong,pSteps); - for( j=0; j &asFeatsOu if( pProf ) { HighScoreList &hsl = pProf->GetStepsHighScoreList(pSong,pSteps); - for( j=0; j &asFeatsOu CHECKPOINT; StageStats stats; - vector vSongs; - GetFinalEvalStatsAndSongs( stats, vSongs ); + GetFinalEvalStats( stats ); // Find Machine Category Records @@ -1497,11 +1490,11 @@ void GameState::GetRankingFeats( PlayerNumber pn, vector &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 &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 ); } } diff --git a/stepmania/src/GameState.h b/stepmania/src/GameState.h index 7ac6ffaee0..ea014be3e9 100644 --- a/stepmania/src/GameState.h +++ b/stepmania/src/GameState.h @@ -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& vSongsOut ) const; // shown on arcade final evaluation + void GetFinalEvalStats( StageStats& statsOut ) const; // shown on final evaluation // diff --git a/stepmania/src/NetworkSyncManager.cpp b/stepmania/src/NetworkSyncManager.cpp index a12630e614..57e172f43c 100644 --- a/stepmania/src/NetworkSyncManager.cpp +++ b/stepmania/src/NetworkSyncManager.cpp @@ -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()); diff --git a/stepmania/src/ScreenEnding.cpp b/stepmania/src/ScreenEnding.cpp index 398d02acc2..aaa8a83de9 100644 --- a/stepmania/src/ScreenEnding.cpp +++ b/stepmania/src/ScreenEnding.cpp @@ -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; diff --git a/stepmania/src/ScreenEvaluation.cpp b/stepmania/src/ScreenEvaluation.cpp index 1f4b0132b2..22a655f035 100644 --- a/stepmania/src/ScreenEvaluation.cpp +++ b/stepmania/src/ScreenEvaluation.cpp @@ -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 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; im_iNumArcadeStages; + float fAverageMeter = stageStats.GetAverageMeter(p); rcOut[p] = AverageMeterToRankingCategory( fAverageMeter ); PROFILEMAN->AddCategoryScore( st, rcOut[p], p, hs, iPersonalHighScoreIndexOut[p], iMachineHighScoreIndexOut[p] ); diff --git a/stepmania/src/ScreenGameplay.cpp b/stepmania/src/ScreenGameplay.cpp index 24a7d88ced..f960009f9f 100644 --- a/stepmania/src/ScreenGameplay.cpp +++ b/stepmania/src/ScreenGameplay.cpp @@ -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() ); diff --git a/stepmania/src/ScreenNameEntryTraditional.cpp b/stepmania/src/ScreenNameEntryTraditional.cpp index a9862bd729..e7e54631aa 100644 --- a/stepmania/src/ScreenNameEntryTraditional.cpp +++ b/stepmania/src/ScreenNameEntryTraditional.cpp @@ -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 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; diff --git a/stepmania/src/ScreenSelectMusic.cpp b/stepmania/src/ScreenSelectMusic.cpp index 9054474b74..eaf4e08459 100644 --- a/stepmania/src/ScreenSelectMusic.cpp +++ b/stepmania/src/ScreenSelectMusic.cpp @@ -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. */ diff --git a/stepmania/src/SongManager.cpp b/stepmania/src/SongManager.cpp index 981b77af89..2abeda011a 100644 --- a/stepmania/src/SongManager.cpp +++ b/stepmania/src/SongManager.cpp @@ -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 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 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 ); } } diff --git a/stepmania/src/StageStats.cpp b/stepmania/src/StageStats.cpp index ed358f0a5b..e20cbe54ec 100644 --- a/stepmania/src/StageStats.cpp +++ b/stepmania/src/StageStats.cpp @@ -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 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; iGetMeter(); + + 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 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 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() ); diff --git a/stepmania/src/StageStats.h b/stepmania/src/StageStats.h index 9867da254c..58d2d988e0 100644 --- a/stepmania/src/StageStats.h +++ b/stepmania/src/StageStats.h @@ -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 vpSongs; enum { STAGE_INVALID, STAGE_NORMAL, STAGE_EXTRA, STAGE_EXTRA2 } StageType; - Steps* pSteps[NUM_PLAYERS]; - int iMeter[NUM_PLAYERS]; + vector 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.