save per-difficulty course scores

This commit is contained in:
Chris Danford
2004-02-22 06:04:01 +00:00
parent a381630ac2
commit 69600d9d80
11 changed files with 84 additions and 55 deletions
+3 -2
View File
@@ -1249,11 +1249,12 @@ void GameState::GetRankingFeats( PlayerNumber pn, vector<RankingFeats> &asFeatsO
StepsType nt = this->GetCurrentStyleDef()->m_StepsType; StepsType nt = this->GetCurrentStyleDef()->m_StepsType;
Course* pCourse = this->m_pCurCourse; Course* pCourse = this->m_pCurCourse;
ASSERT( pCourse ); ASSERT( pCourse );
CourseDifficulty cd = this->m_CourseDifficulty[pn];
// Find Machine Records // Find Machine Records
{ {
Profile* pProfile = PROFILEMAN->GetMachineProfile(); Profile* pProfile = PROFILEMAN->GetMachineProfile();
HighScoreList &hsl = pProfile->GetCourseHighScoreList( pCourse, nt ); HighScoreList &hsl = pProfile->GetCourseHighScoreList( pCourse, nt, cd );
for( unsigned i=0; i<hsl.vHighScores.size(); i++ ) for( unsigned i=0; i<hsl.vHighScores.size(); i++ )
{ {
HighScore &hs = hsl.vHighScores[i]; HighScore &hs = hsl.vHighScores[i];
@@ -1276,7 +1277,7 @@ void GameState::GetRankingFeats( PlayerNumber pn, vector<RankingFeats> &asFeatsO
// Find Personal Records // Find Personal Records
if( PROFILEMAN->IsUsingProfile( pn ) ) if( PROFILEMAN->IsUsingProfile( pn ) )
{ {
HighScoreList &hsl = pProf->GetCourseHighScoreList( pCourse, nt ); HighScoreList &hsl = pProf->GetCourseHighScoreList( pCourse, nt, cd );
for( unsigned i=0; i<hsl.vHighScores.size(); i++ ) for( unsigned i=0; i<hsl.vHighScores.size(); i++ )
{ {
HighScore& hs = hsl.vHighScores[i]; HighScore& hs = hsl.vHighScores[i];
+4 -3
View File
@@ -174,6 +174,7 @@ void PaneDisplay::SetContent( PaneContents c )
const Steps *pSteps = GAMESTATE->m_pCurNotes[m_PlayerNumber]; const Steps *pSteps = GAMESTATE->m_pCurNotes[m_PlayerNumber];
StepsType st = GAMESTATE->GetCurrentStyleDef()->m_StepsType; StepsType st = GAMESTATE->GetCurrentStyleDef()->m_StepsType;
const Course *pCourse = GAMESTATE->m_pCurCourse; const Course *pCourse = GAMESTATE->m_pCurCourse;
const CourseDifficulty cd = GAMESTATE->m_CourseDifficulty[m_PlayerNumber];
float val = 0; float val = 0;
CString str; CString str;
@@ -225,7 +226,7 @@ void PaneDisplay::SetContent( PaneContents c )
case COURSE_MACHINE_HIGH_NAME: /* set val for color */ case COURSE_MACHINE_HIGH_NAME: /* set val for color */
case COURSE_MACHINE_HIGH_SCORE: case COURSE_MACHINE_HIGH_SCORE:
val = 100.0f * PROFILEMAN->GetMachineProfile()->GetCourseHighScoreList(pCourse,st).GetTopScore().fPercentDP; val = 100.0f * PROFILEMAN->GetMachineProfile()->GetCourseHighScoreList(pCourse,st,cd).GetTopScore().fPercentDP;
break; break;
case COURSE_MACHINE_NUM_PLAYS: case COURSE_MACHINE_NUM_PLAYS:
@@ -241,7 +242,7 @@ void PaneDisplay::SetContent( PaneContents c )
break; break;
case COURSE_PROFILE_HIGH_SCORE: case COURSE_PROFILE_HIGH_SCORE:
val = 100.0f * PROFILEMAN->GetProfile(m_PlayerNumber)->GetCourseHighScoreList(pCourse,st).GetTopScore().fPercentDP; val = 100.0f * PROFILEMAN->GetProfile(m_PlayerNumber)->GetCourseHighScoreList(pCourse,st,cd).GetTopScore().fPercentDP;
break; break;
case COURSE_PROFILE_NUM_PLAYS: case COURSE_PROFILE_NUM_PLAYS:
val = (float) PROFILEMAN->GetProfile(m_PlayerNumber)->GetCourseNumTimesPlayed( pCourse ); val = (float) PROFILEMAN->GetProfile(m_PlayerNumber)->GetCourseNumTimesPlayed( pCourse );
@@ -274,7 +275,7 @@ void PaneDisplay::SetContent( PaneContents c )
str = PROFILEMAN->GetMachineProfile()->GetStepsHighScoreList(pSteps).GetTopScore().sName; str = PROFILEMAN->GetMachineProfile()->GetStepsHighScoreList(pSteps).GetTopScore().sName;
break; break;
case COURSE_MACHINE_HIGH_NAME: case COURSE_MACHINE_HIGH_NAME:
str = PROFILEMAN->GetMachineProfile()->GetCourseHighScoreList(pCourse, st).GetTopScore().sName; str = PROFILEMAN->GetMachineProfile()->GetCourseHighScoreList(pCourse,st,cd).GetTopScore().sName;
break; break;
case SONG_MACHINE_HIGH_SCORE: case SONG_MACHINE_HIGH_SCORE:
+47 -21
View File
@@ -187,27 +187,27 @@ void Profile::IncrementStepsPlayCount( const Steps* pSteps )
// //
// Course high scores // Course high scores
// //
void Profile::AddCourseHighScore( const Course* pCourse, StepsType st, HighScore hs, int &iIndexOut ) void Profile::AddCourseHighScore( const Course* pCourse, StepsType st, CourseDifficulty cd, HighScore hs, int &iIndexOut )
{ {
std::map<const Course*,HighScoresForACourse>::iterator iter = m_CourseHighScores.find( pCourse ); std::map<const Course*,HighScoresForACourse>::iterator iter = m_CourseHighScores.find( pCourse );
if( iter == m_CourseHighScores.end() ) if( iter == m_CourseHighScores.end() )
m_CourseHighScores[pCourse].hs[st].AddHighScore( hs, iIndexOut ); // operator[] inserts into map m_CourseHighScores[pCourse].hs[st][cd].AddHighScore( hs, iIndexOut ); // operator[] inserts into map
else else
iter->second.hs[st].AddHighScore( hs, iIndexOut ); iter->second.hs[st][cd].AddHighScore( hs, iIndexOut );
} }
const HighScoreList& Profile::GetCourseHighScoreList( const Course* pCourse, StepsType st ) const const HighScoreList& Profile::GetCourseHighScoreList( const Course* pCourse, StepsType st, CourseDifficulty cd ) const
{ {
return ((Profile *)this)->m_CourseHighScores[pCourse].hs[st]; return ((Profile *)this)->m_CourseHighScores[pCourse].hs[st][cd];
} }
HighScoreList& Profile::GetCourseHighScoreList( const Course* pCourse, StepsType st ) HighScoreList& Profile::GetCourseHighScoreList( const Course* pCourse, StepsType st, CourseDifficulty cd )
{ {
std::map<const Course*,HighScoresForACourse>::iterator iter = m_CourseHighScores.find( pCourse ); std::map<const Course*,HighScoresForACourse>::iterator iter = m_CourseHighScores.find( pCourse );
if( iter == m_CourseHighScores.end() ) if( iter == m_CourseHighScores.end() )
return m_CourseHighScores[pCourse].hs[st]; // operator[] inserts into map return m_CourseHighScores[pCourse].hs[st][cd]; // operator[] inserts into map
else else
return iter->second.hs[st]; return iter->second.hs[st][cd];
} }
int Profile::GetCourseNumTimesPlayed( const Course* pCourse ) const int Profile::GetCourseNumTimesPlayed( const Course* pCourse ) const
@@ -221,14 +221,15 @@ int Profile::GetCourseNumTimesPlayed( const Course* pCourse ) const
{ {
int iTotalNumTimesPlayed = 0; int iTotalNumTimesPlayed = 0;
for( unsigned st = 0; st < NUM_STEPS_TYPES; ++st ) for( unsigned st = 0; st < NUM_STEPS_TYPES; ++st )
iTotalNumTimesPlayed += iter->second.hs[st].iNumTimesPlayed; FOREACH_CourseDifficulty( cd )
iTotalNumTimesPlayed += iter->second.hs[st][cd].iNumTimesPlayed;
return iTotalNumTimesPlayed; return iTotalNumTimesPlayed;
} }
} }
void Profile::IncrementCoursePlayCount( const Course* pCourse, StepsType st ) void Profile::IncrementCoursePlayCount( const Course* pCourse, StepsType st, CourseDifficulty cd )
{ {
GetCourseHighScoreList(pCourse,st).iNumTimesPlayed++; GetCourseHighScoreList(pCourse,st,cd).iNumTimesPlayed++;
} }
// //
@@ -960,7 +961,7 @@ void Profile::LoadCourseScoresFromDirSM390a12( CString sDir )
if( !FileRead(f, iNumTimesPlayed) ) if( !FileRead(f, iNumTimesPlayed) )
WARN_AND_RETURN; WARN_AND_RETURN;
HighScoreList &hsl = pProfile->GetCourseHighScoreList( pCourse, (StepsType)st ); HighScoreList &hsl = pProfile->GetCourseHighScoreList( pCourse, (StepsType)st, COURSE_DIFFICULTY_REGULAR );
if( pCourse ) if( pCourse )
hsl.iNumTimesPlayed = iNumTimesPlayed; hsl.iNumTimesPlayed = iNumTimesPlayed;
@@ -1029,16 +1030,28 @@ XNode* Profile::SaveCourseScoresCreateNode() const
for( StepsType st=(StepsType)0; st<NUM_STEPS_TYPES; ((int&)st)++ ) for( StepsType st=(StepsType)0; st<NUM_STEPS_TYPES; ((int&)st)++ )
{ {
// skip course/steps types that have never been played // TRICKY: Only append this node if one we have at least one child.
if( pProfile->GetCourseHighScoreList(pCourse, st).iNumTimesPlayed == 0 ) // There's no point to saving a bunch of empty StepsType nodes.
continue; LPXNode pStepsTypeNode = new XNode;
pStepsTypeNode->name = "StepsType";
LPXNode pStepsTypeNode = pCourseNode->AppendChild( "StepsType" );
pStepsTypeNode->AppendAttr( "Type", GameManager::NotesTypeToString(st) ); pStepsTypeNode->AppendAttr( "Type", GameManager::NotesTypeToString(st) );
const HighScoreList &hsl = pProfile->GetCourseHighScoreList( pCourse, st ); FOREACH_CourseDifficulty( cd )
{
// skip course/steps types that have never been played
if( pProfile->GetCourseHighScoreList(pCourse, st, cd).iNumTimesPlayed == 0 )
continue;
pStepsTypeNode->AppendChild( hsl.CreateNode() ); LPXNode pCourseDifficultyNode = pStepsTypeNode->AppendChild( "CourseDifficulty" );
pCourseDifficultyNode->AppendAttr( "Type", CourseDifficultyToString(cd) );
const HighScoreList &hsl = pProfile->GetCourseHighScoreList( pCourse, st, cd );
pCourseDifficultyNode->AppendChild( hsl.CreateNode() );
}
if( !pStepsTypeNode->childs.empty() )
pCourseNode->AppendChild( pStepsTypeNode );
} }
} }
@@ -1082,14 +1095,27 @@ void Profile::LoadCourseScoresFromNode( const XNode* pNode )
if( st == STEPS_TYPE_INVALID ) if( st == STEPS_TYPE_INVALID )
WARN_AND_CONTINUE; WARN_AND_CONTINUE;
XNode *pHighScoreListNode = (*stepsType)->GetChild("HighScoreList"); for( XNodes::iterator courseDifficulty = (*stepsType)->childs.begin();
courseDifficulty != (*stepsType)->childs.end();
courseDifficulty++ )
{
const LPXAttr TypeAttr = (*courseDifficulty)->GetAttr( "Type" );
if( TypeAttr == NULL )
WARN_AND_CONTINUE;
CourseDifficulty cd = StringToCourseDifficulty( TypeAttr->value );
if( cd == COURSE_DIFFICULTY_INVALID )
WARN_AND_CONTINUE;
XNode *pHighScoreListNode = (*courseDifficulty)->GetChild("HighScoreList");
if( pHighScoreListNode == NULL ) if( pHighScoreListNode == NULL )
WARN_AND_CONTINUE; WARN_AND_CONTINUE;
HighScoreList &hsl = this->GetCourseHighScoreList( pCourse, st ); HighScoreList &hsl = this->GetCourseHighScoreList( pCourse, st, cd );
hsl.LoadFromNode( pHighScoreListNode ); hsl.LoadFromNode( pHighScoreListNode );
} }
} }
}
} }
XNode* Profile::SaveCategoryScoresCreateNode() const XNode* Profile::SaveCategoryScoresCreateNode() const
+5 -5
View File
@@ -117,15 +117,15 @@ public:
// in processing the templates for map::operator[]. // in processing the templates for map::operator[].
struct HighScoresForACourse struct HighScoresForACourse
{ {
HighScoreList hs[NUM_STEPS_TYPES]; HighScoreList hs[NUM_STEPS_TYPES][NUM_COURSE_DIFFICULTIES];
}; };
std::map<const Course*,HighScoresForACourse> m_CourseHighScores; std::map<const Course*,HighScoresForACourse> m_CourseHighScores;
void AddCourseHighScore( const Course* pCourse, StepsType st, HighScore hs, int &iIndexOut ); void AddCourseHighScore( const Course* pCourse, StepsType st, CourseDifficulty cd, HighScore hs, int &iIndexOut );
HighScoreList& GetCourseHighScoreList( const Course* pCourse, StepsType st ); HighScoreList& GetCourseHighScoreList( const Course* pCourse, StepsType st, CourseDifficulty cd );
const HighScoreList& GetCourseHighScoreList( const Course* pCourse, StepsType st ) const; const HighScoreList& GetCourseHighScoreList( const Course* pCourse, StepsType st, CourseDifficulty cd ) const;
int GetCourseNumTimesPlayed( const Course* pCourse ) const; int GetCourseNumTimesPlayed( const Course* pCourse ) const;
void IncrementCoursePlayCount( const Course* pCourse, StepsType st ); void IncrementCoursePlayCount( const Course* pCourse, StepsType st, CourseDifficulty cd );
// //
+6 -6
View File
@@ -471,21 +471,21 @@ HighScore ProfileManager::GetHighScoreForDifficulty( const Song *s, const StyleD
// //
// Course stats // Course stats
// //
void ProfileManager::AddCourseHighScore( const Course* pCourse, StepsType st, PlayerNumber pn, HighScore hs, int &iPersonalIndexOut, int &iMachineIndexOut ) void ProfileManager::AddCourseHighScore( const Course* pCourse, StepsType st, CourseDifficulty cd, PlayerNumber pn, HighScore hs, int &iPersonalIndexOut, int &iMachineIndexOut )
{ {
hs.sName = RANKING_TO_FILL_IN_MARKER[pn]; hs.sName = RANKING_TO_FILL_IN_MARKER[pn];
if( PROFILEMAN->IsUsingProfile(pn) ) if( PROFILEMAN->IsUsingProfile(pn) )
PROFILEMAN->GetProfile(pn)->AddCourseHighScore( pCourse, st, hs, iPersonalIndexOut ); PROFILEMAN->GetProfile(pn)->AddCourseHighScore( pCourse, st, cd, hs, iPersonalIndexOut );
else else
iPersonalIndexOut = -1; iPersonalIndexOut = -1;
PROFILEMAN->GetMachineProfile()->AddCourseHighScore( pCourse, st, hs, iMachineIndexOut ); PROFILEMAN->GetMachineProfile()->AddCourseHighScore( pCourse, st, cd, hs, iMachineIndexOut );
} }
void ProfileManager::IncrementCoursePlayCount( const Course* pCourse, StepsType st, PlayerNumber pn ) void ProfileManager::IncrementCoursePlayCount( const Course* pCourse, StepsType st, CourseDifficulty cd, PlayerNumber pn )
{ {
if( PROFILEMAN->IsUsingProfile(pn) ) if( PROFILEMAN->IsUsingProfile(pn) )
PROFILEMAN->GetProfile(pn)->IncrementCoursePlayCount( pCourse, st ); PROFILEMAN->GetProfile(pn)->IncrementCoursePlayCount( pCourse, st, cd );
PROFILEMAN->GetMachineProfile()->IncrementCoursePlayCount( pCourse, st ); PROFILEMAN->GetMachineProfile()->IncrementCoursePlayCount( pCourse, st, cd );
} }
+2 -2
View File
@@ -84,8 +84,8 @@ public:
// //
// Course stats // Course stats
// //
void AddCourseHighScore( const Course* pCourse, StepsType st, PlayerNumber pn, HighScore hs, int &iPersonalIndexOut, int &iMachineIndexOut ); void AddCourseHighScore( const Course* pCourse, StepsType st, CourseDifficulty cd, PlayerNumber pn, HighScore hs, int &iPersonalIndexOut, int &iMachineIndexOut );
void IncrementCoursePlayCount( const Course* pCourse, StepsType st, PlayerNumber pn ); void IncrementCoursePlayCount( const Course* pCourse, StepsType st, CourseDifficulty cd, PlayerNumber pn );
// //
// Category stats // Category stats
+2 -1
View File
@@ -949,6 +949,7 @@ void ScreenEvaluation::CommitScores( const StageStats &stageStats, int iPersonal
case course: case course:
{ {
Course* pCourse = GAMESTATE->m_pCurCourse; Course* pCourse = GAMESTATE->m_pCurCourse;
CourseDifficulty cd = GAMESTATE->m_CourseDifficulty[p];
if( pCourse ) if( pCourse )
{ {
// don't save scores for a failed Nonstop // don't save scores for a failed Nonstop
@@ -957,7 +958,7 @@ void ScreenEvaluation::CommitScores( const StageStats &stageStats, int iPersonal
continue; continue;
if( hs.fPercentDP > PREFSMAN->m_fMinPercentageForHighScore ) if( hs.fPercentDP > PREFSMAN->m_fMinPercentageForHighScore )
PROFILEMAN->AddCourseHighScore( pCourse, nt, (PlayerNumber)p, hs, iPersonalHighScoreIndex[p], iMachineHighScoreIndex[p] ); PROFILEMAN->AddCourseHighScore( pCourse, nt, cd, (PlayerNumber)p, hs, iPersonalHighScoreIndex[p], iMachineHighScoreIndex[p] );
} }
} }
break; break;
+1 -1
View File
@@ -176,7 +176,7 @@ void ScreenGameplay::Init()
if( !m_bDemonstration ) if( !m_bDemonstration )
for( p=0; p<NUM_PLAYERS; p++ ) for( p=0; p<NUM_PLAYERS; p++ )
if( GAMESTATE->IsPlayerEnabled(p) ) if( GAMESTATE->IsPlayerEnabled(p) )
PROFILEMAN->IncrementCoursePlayCount( GAMESTATE->m_pCurCourse, st, (PlayerNumber)p ); PROFILEMAN->IncrementCoursePlayCount( GAMESTATE->m_pCurCourse, st, GAMESTATE->m_CourseDifficulty[p], (PlayerNumber)p );
for( int p=0; p<NUM_PLAYERS; p++ ) for( int p=0; p<NUM_PLAYERS; p++ )
{ {
+5 -7
View File
@@ -318,6 +318,7 @@ ScreenRanking::ScreenRanking( CString sClassName ) : ScreenAttract( sClassName )
pts.colorIndex = i; pts.colorIndex = i;
pts.nt = aStepsTypesToShow[i]; pts.nt = aStepsTypesToShow[i];
pts.pCourse = SONGMAN->GetCourseFromPath( asCoursePaths[c] ); pts.pCourse = SONGMAN->GetCourseFromPath( asCoursePaths[c] );
pts.cd = COURSE_DIFFICULTY_REGULAR;
if( pts.pCourse ) if( pts.pCourse )
m_vPagesToShow.push_back( pts ); m_vPagesToShow.push_back( pts );
} }
@@ -712,7 +713,7 @@ float ScreenRanking::SetPage( PageToShow pts )
m_Banner.LoadFromCourse( pts.pCourse ); m_Banner.LoadFromCourse( pts.pCourse );
m_textStepsType.SetText( GameManager::NotesTypeToString(pts.nt) ); m_textStepsType.SetText( GameManager::NotesTypeToString(pts.nt) );
const HighScoreList &hsl = PROFILEMAN->GetMachineProfile()->GetCourseHighScoreList( pts.pCourse, pts.nt ); const HighScoreList &hsl = PROFILEMAN->GetMachineProfile()->GetCourseHighScoreList( pts.pCourse, pts.nt, pts.cd );
for( int l=0; l<NUM_RANKING_LINES; l++ ) for( int l=0; l<NUM_RANKING_LINES; l++ )
{ {
HighScore hs; HighScore hs;
@@ -817,13 +818,10 @@ float ScreenRanking::SetPage( PageToShow pts )
const Course* pCourse = pCourseScoreRowItem->m_pCourse; const Course* pCourse = pCourseScoreRowItem->m_pCourse;
pCourseScoreRowItem->m_textSongTitle.SetText( pCourse->m_sName ); pCourseScoreRowItem->m_textSongTitle.SetText( pCourse->m_sName );
const HighScoreList &hsl = PROFILEMAN->GetMachineProfile()->GetCourseHighScoreList( pCourse, pts.nt ); FOREACH_CourseDifficulty( cd )
for( int d=0; d<NUM_COURSE_DIFFICULTIES; d++ )
{ {
// const HighScoreList &hsl = PROFILEMAN->GetMachineProfile()->GetCourseHighScoreList( pCourse, pts.nt, cd );
// FIXME: have separate high scores for each difficulty BitmapText* pTextStepsScore = &pCourseScoreRowItem->m_textStepsScore[cd];
//
BitmapText* pTextStepsScore = &pCourseScoreRowItem->m_textStepsScore[d];
HighScore hs; HighScore hs;
bool bRecentHighScore = false; bool bRecentHighScore = false;
+1
View File
@@ -37,6 +37,7 @@ protected:
StepsType nt; StepsType nt;
RankingCategory category; RankingCategory category;
Course* pCourse; Course* pCourse;
CourseDifficulty cd;
PageToShow(): pCourse(NULL) { } PageToShow(): pCourse(NULL) { }
}; };
+3 -2
View File
@@ -398,6 +398,7 @@ void ScreenSelectCourse::AfterCourseChange()
case TYPE_COURSE: case TYPE_COURSE:
{ {
Course* pCourse = m_MusicWheel.GetSelectedCourse(); Course* pCourse = m_MusicWheel.GetSelectedCourse();
const StepsType &st = GAMESTATE->GetCurrentStyleDef()->m_StepsType;
m_textNumSongs.SetText( ssprintf("%d", pCourse->GetEstimatedNumStages()) ); m_textNumSongs.SetText( ssprintf("%d", pCourse->GetEstimatedNumStages()) );
float fTotalSeconds; float fTotalSeconds;
@@ -414,7 +415,7 @@ void ScreenSelectCourse::AfterCourseChange()
ASSERT(pCourse); ASSERT(pCourse);
for( int p=0; p<NUM_PLAYERS; p++ ) for( int p=0; p<NUM_PLAYERS; p++ )
{ {
const StepsType &st = GAMESTATE->GetCurrentStyleDef()->m_StepsType; CourseDifficulty cd = GAMESTATE->m_CourseDifficulty[p];
Profile* pProfile; Profile* pProfile;
if( PROFILEMAN->IsUsingProfile( (PlayerNumber)p ) ) if( PROFILEMAN->IsUsingProfile( (PlayerNumber)p ) )
@@ -428,7 +429,7 @@ void ScreenSelectCourse::AfterCourseChange()
* have an opinion on which should be used here for * have an opinion on which should be used here for
* each of oni, endless, nonstop -- * each of oni, endless, nonstop --
* should this choice be an option or a metric? */ * should this choice be an option or a metric? */
const HighScoreList& hsl = pProfile->GetCourseHighScoreList( pCourse, st ); const HighScoreList& hsl = pProfile->GetCourseHighScoreList( pCourse, st, cd );
if ( pCourse->IsOni() || pCourse->IsEndless() ) if ( pCourse->IsOni() || pCourse->IsEndless() )
{ {
/* use survive time */ /* use survive time */