more on high score work
This commit is contained in:
@@ -29,6 +29,29 @@ Course::Course()
|
|||||||
m_bRandomize = false;
|
m_bRandomize = false;
|
||||||
m_iLives = 4;
|
m_iLives = 4;
|
||||||
m_iExtra = 0;
|
m_iExtra = 0;
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Init high scores
|
||||||
|
//
|
||||||
|
unsigned i, j, k;
|
||||||
|
for( i=0; i<NUM_STYLES; i++ )
|
||||||
|
for( j=0; j<NUM_DIFFICULTIES; j++ )
|
||||||
|
for( k=0; k<NUM_HIGH_SCORE_LINES; k++ )
|
||||||
|
{
|
||||||
|
m_MachineScores[i][j][k].iDancePoints = 0;
|
||||||
|
m_MachineScores[i][j][k].fSurviveTime = 0;
|
||||||
|
m_MachineScores[i][j][k].sName = "STEP";
|
||||||
|
}
|
||||||
|
|
||||||
|
for( i=0; i<NUM_STYLES; i++ )
|
||||||
|
for( j=0; j<NUM_DIFFICULTIES; j++ )
|
||||||
|
for( k=0; k<NUM_PLAYERS; k++ )
|
||||||
|
{
|
||||||
|
m_MemCardScores[i][j][k].iDancePoints = 0;
|
||||||
|
m_MemCardScores[i][j][k].fSurviveTime = 0;
|
||||||
|
m_MemCardScores[i][j][k].sName = "STEP";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Course::LoadFromCRSFile( CString sPath, vector<Song*> &apSongs )
|
void Course::LoadFromCRSFile( CString sPath, vector<Song*> &apSongs )
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "GameConstantsAndTypes.h"
|
#include "GameConstantsAndTypes.h"
|
||||||
|
#include "Style.h" // for NUM_STYLES
|
||||||
|
|
||||||
struct PlayerOptions;
|
struct PlayerOptions;
|
||||||
struct SongOptions;
|
struct SongOptions;
|
||||||
@@ -20,8 +21,6 @@ struct Notes;
|
|||||||
|
|
||||||
class Course
|
class Course
|
||||||
{
|
{
|
||||||
int m_iStages;
|
|
||||||
|
|
||||||
struct course_entry {
|
struct course_entry {
|
||||||
CString description; // the Notes description
|
CString description; // the Notes description
|
||||||
CString modifiers; // set player and song options from these
|
CString modifiers; // set player and song options from these
|
||||||
@@ -59,14 +58,16 @@ public:
|
|||||||
RageColor GetColor();
|
RageColor GetColor();
|
||||||
|
|
||||||
// Statistics
|
// Statistics
|
||||||
|
int m_iNumTimesPlayed;
|
||||||
|
|
||||||
struct HighScore
|
struct HighScore
|
||||||
{
|
{
|
||||||
int iDancePoints;
|
int iDancePoints;
|
||||||
float fSurviveTime;
|
float fSurviveTime;
|
||||||
CString sName;
|
CString sName;
|
||||||
};
|
};
|
||||||
HighScore m_MachineScores[NUM_DIFFICULTIES][NUM_HIGH_SCORE_LINES]; // sorted highest to lowest by iDancePoints
|
HighScore m_MachineScores[NUM_STYLES][NUM_DIFFICULTIES][NUM_HIGH_SCORE_LINES]; // sorted highest to lowest by iDancePoints
|
||||||
HighScore m_MemCardScores[NUM_DIFFICULTIES][NUM_PLAYERS];
|
HighScore m_MemCardScores[NUM_STYLES][NUM_DIFFICULTIES][NUM_PLAYERS];
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Shuffle();
|
void Shuffle();
|
||||||
|
|||||||
@@ -172,6 +172,18 @@ inline int HoldNoteScoreToDancePoints( HoldNoteScore hns )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// High Score types
|
||||||
|
//
|
||||||
|
enum SongHighScoreCategory
|
||||||
|
{
|
||||||
|
CATEGORY_A, // 1-3 meter per song avg.
|
||||||
|
CATEGORY_B, // 4-6 meter per song avg.
|
||||||
|
CATEGORY_C, // 7-9 meter per song avg.
|
||||||
|
CATEGORY_D, // 10+ meter per song avg.
|
||||||
|
NUM_HIGH_SCORE_CATEGORIES
|
||||||
|
};
|
||||||
const int NUM_HIGH_SCORE_LINES = 5;
|
const int NUM_HIGH_SCORE_LINES = 5;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -338,7 +338,7 @@ void MusicBannerWheel::BannersLeft()
|
|||||||
void MusicBannerWheel::BannersRight()
|
void MusicBannerWheel::BannersRight()
|
||||||
{
|
{
|
||||||
StopBouncing();
|
StopBouncing();
|
||||||
if(currentPos>=arraySongs.size()-1)
|
if((unsigned)currentPos>=arraySongs.size()-1)
|
||||||
currentPos=0;
|
currentPos=0;
|
||||||
else
|
else
|
||||||
currentPos++;
|
currentPos++;
|
||||||
|
|||||||
@@ -185,30 +185,21 @@ void WheelItemDisplay::RefreshGrades()
|
|||||||
// Refresh Grades
|
// Refresh Grades
|
||||||
for( int p=0; p<NUM_PLAYERS; p++ )
|
for( int p=0; p<NUM_PLAYERS; p++ )
|
||||||
{
|
{
|
||||||
if( !GAMESTATE->IsPlayerEnabled( (PlayerNumber)p ) )
|
if( !data->m_pSong || // this isn't a song display
|
||||||
|
!GAMESTATE->IsPlayerEnabled(p) ||
|
||||||
|
!SONGMAN->IsUsingMemoryCard((PlayerNumber)p) )
|
||||||
{
|
{
|
||||||
m_GradeDisplay[p].SetDiffuse( RageColor(1,1,1,0) );
|
m_GradeDisplay[p].SetDiffuse( RageColor(1,1,1,0) );
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( data->m_pSong ) // this is a song display
|
Difficulty dc;
|
||||||
{
|
if( GAMESTATE->m_pCurNotes[p] )
|
||||||
if( data->m_pSong == GAMESTATE->m_pCurSong )
|
dc = GAMESTATE->m_pCurNotes[p]->GetDifficulty();
|
||||||
{
|
else
|
||||||
Notes* pNotes = GAMESTATE->m_pCurNotes[p];
|
dc = GAMESTATE->m_PreferredDifficulty[p];
|
||||||
m_GradeDisplay[p].SetGrade( (PlayerNumber)p, pNotes ? pNotes->m_TopGrade : GRADE_NO_DATA );
|
const Grade grade = data->m_pSong->GetGradeForDifficulty( GAMESTATE->GetCurrentStyleDef(), (PlayerNumber)p, dc );
|
||||||
}
|
m_GradeDisplay[p].SetGrade( (PlayerNumber)p, grade );
|
||||||
else
|
|
||||||
{
|
|
||||||
const Difficulty dc = GAMESTATE->m_PreferredDifficulty[p];
|
|
||||||
const Grade grade = data->m_pSong->GetGradeForDifficulty( GAMESTATE->GetCurrentStyleDef(), p, dc );
|
|
||||||
m_GradeDisplay[p].SetGrade( (PlayerNumber)p, grade );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else // this is a section display
|
|
||||||
{
|
|
||||||
m_GradeDisplay[p].SetGrade( (PlayerNumber)p, GRADE_NO_DATA );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-3
@@ -45,12 +45,15 @@ Notes::Notes()
|
|||||||
m_fRadarValues[i] = -1; /* unknown */
|
m_fRadarValues[i] = -1; /* unknown */
|
||||||
|
|
||||||
m_iNumTimesPlayed = 0;
|
m_iNumTimesPlayed = 0;
|
||||||
m_iMaxCombo = 0;
|
|
||||||
m_iTopScore = 0;
|
|
||||||
m_TopGrade = GRADE_NO_DATA;
|
|
||||||
notes = NULL;
|
notes = NULL;
|
||||||
notes_comp = NULL;
|
notes_comp = NULL;
|
||||||
parent = NULL;
|
parent = NULL;
|
||||||
|
|
||||||
|
for( int p=0; p<NUM_PLAYERS; p++ )
|
||||||
|
{
|
||||||
|
m_MemCardScores[p].grade = GRADE_NO_DATA;
|
||||||
|
m_MemCardScores[p].iScore = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Notes::~Notes()
|
Notes::~Notes()
|
||||||
@@ -310,3 +313,13 @@ void Notes::SetRadarValue(int r, float val)
|
|||||||
m_fRadarValues[r] = val;
|
m_fRadarValues[r] = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Notes::AddMemCardScore( PlayerNumber pn, Grade grade, int iScore ) // return true if new high score
|
||||||
|
{
|
||||||
|
if( iScore > m_MemCardScores[pn].iScore )
|
||||||
|
{
|
||||||
|
m_MemCardScores[pn].iScore = iScore;
|
||||||
|
m_MemCardScores[pn].grade = grade;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|||||||
+12
-4
@@ -48,12 +48,20 @@ public:
|
|||||||
void AutogenFrom( Notes *parent, NotesType ntTo );
|
void AutogenFrom( Notes *parent, NotesType ntTo );
|
||||||
RageColor GetColor() const; // a function of difficulty
|
RageColor GetColor() const; // a function of difficulty
|
||||||
|
|
||||||
// Statistics
|
|
||||||
Grade m_TopGrade;
|
// High scores;
|
||||||
int m_iTopScore;
|
|
||||||
int m_iMaxCombo;
|
|
||||||
int m_iNumTimesPlayed;
|
int m_iNumTimesPlayed;
|
||||||
|
|
||||||
|
struct HighScore
|
||||||
|
{
|
||||||
|
Grade grade;
|
||||||
|
int iScore;
|
||||||
|
};
|
||||||
|
HighScore m_MemCardScores[NUM_PLAYERS];
|
||||||
|
|
||||||
|
bool AddMemCardScore( PlayerNumber pn, Grade grade, int iScore ); // return true if new high score
|
||||||
|
|
||||||
|
|
||||||
void TidyUpData();
|
void TidyUpData();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -294,25 +294,12 @@ ScreenEvaluation::ScreenEvaluation( bool bSummary )
|
|||||||
switch( m_ResultMode )
|
switch( m_ResultMode )
|
||||||
{
|
{
|
||||||
case RM_ARCADE_STAGE:
|
case RM_ARCADE_STAGE:
|
||||||
|
|
||||||
Notes* pNotes = GAMESTATE->m_pCurNotes[p];
|
Notes* pNotes = GAMESTATE->m_pCurNotes[p];
|
||||||
pNotes->m_iNumTimesPlayed++;
|
if( SONGMAN->IsUsingMemoryCard((PlayerNumber)p) )
|
||||||
|
bNewRecord[p] = pNotes->AddMemCardScore( (PlayerNumber)p, grade[p], (int)fScore[p] );
|
||||||
if( iMaxCombo[p] > pNotes->m_iMaxCombo )
|
|
||||||
pNotes->m_iMaxCombo = iMaxCombo[p];
|
|
||||||
|
|
||||||
if( fScore[p] > pNotes->m_iTopScore )
|
|
||||||
{
|
|
||||||
pNotes->m_iTopScore = (int)fScore[p];
|
|
||||||
bNewRecord[p] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( grade[p] > pNotes->m_TopGrade )
|
|
||||||
pNotes->m_TopGrade = grade[p];
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SONGMAN->SaveStatisticsToDisk();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -238,6 +238,7 @@ void ScreenMusicScroll::HandleScreenMessage( const ScreenMessage SM )
|
|||||||
m_Fade.CloseWipingRight( SM_GoToNextScreen );
|
m_Fade.CloseWipingRight( SM_GoToNextScreen );
|
||||||
break;
|
break;
|
||||||
case SM_GoToNextScreen:
|
case SM_GoToNextScreen:
|
||||||
|
SONGMAN->SaveMachineScoresToDisk();
|
||||||
SCREENMAN->SetNewScreen( "ScreenCompany" );
|
SCREENMAN->SetNewScreen( "ScreenCompany" );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -700,8 +700,8 @@ void ScreenSelectMusic::AfterNotesChange( PlayerNumber pn )
|
|||||||
|
|
||||||
Notes* m_pNotes = GAMESTATE->m_pCurNotes[pn];
|
Notes* m_pNotes = GAMESTATE->m_pCurNotes[pn];
|
||||||
|
|
||||||
if( m_pNotes )
|
if( m_pNotes && SONGMAN->IsUsingMemoryCard(pn) )
|
||||||
m_HighScore[pn].SetScore( (float)m_pNotes->m_iTopScore );
|
m_HighScore[pn].SetScore( (float)m_pNotes->m_MemCardScores[pn].iScore );
|
||||||
|
|
||||||
m_DifficultyIcon[pn].SetFromNotes( pn, pNotes );
|
m_DifficultyIcon[pn].SetFromNotes( pn, pNotes );
|
||||||
if( pNotes && pNotes->IsAutogen() )
|
if( pNotes && pNotes->IsAutogen() )
|
||||||
|
|||||||
@@ -897,7 +897,7 @@ void Song::AutoGen( NotesType ntTo, NotesType ntFrom )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Grade Song::GetGradeForDifficulty( const StyleDef *st, int p, Difficulty dc ) const
|
Grade Song::GetGradeForDifficulty( const StyleDef *st, PlayerNumber pn, Difficulty dc ) const
|
||||||
{
|
{
|
||||||
// return max grade of notes in difficulty class
|
// return max grade of notes in difficulty class
|
||||||
vector<Notes*> aNotes;
|
vector<Notes*> aNotes;
|
||||||
@@ -910,7 +910,7 @@ Grade Song::GetGradeForDifficulty( const StyleDef *st, int p, Difficulty dc ) co
|
|||||||
{
|
{
|
||||||
const Notes* pNotes = aNotes[i];
|
const Notes* pNotes = aNotes[i];
|
||||||
if( pNotes->GetDifficulty() == dc )
|
if( pNotes->GetDifficulty() == dc )
|
||||||
grade = max( grade, pNotes->m_TopGrade );
|
grade = max( grade, pNotes->m_MemCardScores[pn].grade );
|
||||||
}
|
}
|
||||||
return grade;
|
return grade;
|
||||||
}
|
}
|
||||||
|
|||||||
+125
-217
@@ -28,7 +28,9 @@
|
|||||||
SongManager* SONGMAN = NULL; // global and accessable from anywhere in our program
|
SongManager* SONGMAN = NULL; // global and accessable from anywhere in our program
|
||||||
|
|
||||||
|
|
||||||
const CString g_sStatisticsFileName = "statistics.ini";
|
const CString CATEGORY_TOP_SCORE_FILE = "CategoryTopScores.dat";
|
||||||
|
const CString COURSE_TOP_SCORE_FILE = "CourseTopScores.dat";
|
||||||
|
|
||||||
|
|
||||||
#define NUM_GROUP_COLORS THEME->GetMetricI("SongManager","NumGroupColors")
|
#define NUM_GROUP_COLORS THEME->GetMetricI("SongManager","NumGroupColors")
|
||||||
#define GROUP_COLOR( i ) THEME->GetMetricC("SongManager",ssprintf("GroupColor%d",i+1))
|
#define GROUP_COLOR( i ) THEME->GetMetricC("SongManager",ssprintf("GroupColor%d",i+1))
|
||||||
@@ -45,14 +47,14 @@ SongManager::SongManager( LoadingWindow *ld )
|
|||||||
g_ExtraColor = EXTRA_COLOR;
|
g_ExtraColor = EXTRA_COLOR;
|
||||||
|
|
||||||
InitSongArrayFromDisk( ld );
|
InitSongArrayFromDisk( ld );
|
||||||
ReadStatisticsFromDisk();
|
InitMachineScoresFromDisk();
|
||||||
|
|
||||||
InitCoursesFromDisk();
|
InitCoursesFromDisk();
|
||||||
}
|
}
|
||||||
|
|
||||||
SongManager::~SongManager()
|
SongManager::~SongManager()
|
||||||
{
|
{
|
||||||
SaveStatisticsToDisk();
|
SaveMachineScoresToDisk();
|
||||||
FreeSongArray();
|
FreeSongArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,64 +180,6 @@ void SongManager::LoadStepManiaSongDir( CString sDir, LoadingWindow *ld )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
void SongManager::LoadDWISongDir( CString DWIHome )
|
|
||||||
{
|
|
||||||
// trim off the trailing slash if any
|
|
||||||
TrimRight( DWIHome, "/\\" );
|
|
||||||
|
|
||||||
// this has to be fixed, DWI doesn't put files
|
|
||||||
// in it's DWI folder. It puts them in Songs/<MIX>/<SONGNAME>
|
|
||||||
// so what we have to do, is go to the DWI directory (which will
|
|
||||||
// be changeable by the user so they don't have to copy everything
|
|
||||||
// over and have two copies of everything
|
|
||||||
// Find all directories in "DWIs" folder
|
|
||||||
CStringArray arrayDirs;
|
|
||||||
CStringArray MixDirs;
|
|
||||||
// now we've got the listing of the mix directories
|
|
||||||
// and we need to use THOSE directories to find our
|
|
||||||
// dwis
|
|
||||||
GetDirListing( ssprintf("%s\\Songs\\*.*", DWIHome ), MixDirs.GetString(), true );
|
|
||||||
SortCStringArray( MixDirs );
|
|
||||||
|
|
||||||
for( unsigned i=0; i< MixDirs.size(); i++ ) // for each dir in /Songs/
|
|
||||||
{
|
|
||||||
// the dir name will most likely be something like
|
|
||||||
// Dance Dance Revolution 4th Mix, etc.
|
|
||||||
CString sDirName = MixDirs[i];
|
|
||||||
sDirName.MakeLower();
|
|
||||||
if( sDirName == "cvs" ) // ignore the directory called "CVS"
|
|
||||||
continue;
|
|
||||||
GetDirListing( ssprintf("%s\\Songs\\%s\\*.*", DWIHome.GetString(), MixDirs[i].GetString()), arrayDirs, true);
|
|
||||||
SortCStringArray(arrayDirs, true);
|
|
||||||
|
|
||||||
for( unsigned b = 0; b < arrayDirs.size(); b++)
|
|
||||||
{
|
|
||||||
// Find all DWIs in this directory
|
|
||||||
CStringArray arrayDWIFiles;
|
|
||||||
GetDirListing( ssprintf("%s\\Songs\\%s\\%s\\*.dwi", DWIHome.GetString(), MixDirs[i].GetString(), arrayDirs[b].GetString()), arrayDWIFiles, false);
|
|
||||||
SortCStringArray( arrayDWIFiles );
|
|
||||||
|
|
||||||
for( unsigned j=0; j< arrayDWIFiles.size(); j++ ) // for each DWI file
|
|
||||||
{
|
|
||||||
CString sDWIFileName = arrayDWIFiles[j];
|
|
||||||
sDWIFileName.MakeLower();
|
|
||||||
|
|
||||||
// load DWIs from the sub dirs
|
|
||||||
DWILoader ld;
|
|
||||||
Song* pNewSong = new Song;
|
|
||||||
ld.LoadFromDWIFile(
|
|
||||||
ssprintf("%s\\Songs\\%s\\%s\\%s", DWIHome.GetString(), MixDirs[i].GetString(), arrayDirs[b].GetString(), sDWIFileName.GetString()),
|
|
||||||
*pNewSong);
|
|
||||||
m_pSongs.push_back( pNewSong );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
void SongManager::FreeSongArray()
|
void SongManager::FreeSongArray()
|
||||||
{
|
{
|
||||||
for( unsigned i=0; i<m_pSongs.size(); i++ )
|
for( unsigned i=0; i<m_pSongs.size(); i++ )
|
||||||
@@ -254,159 +198,112 @@ void SongManager::ReloadSongArray()
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void SongManager::ReadStatisticsFromDisk()
|
void SongManager::InitMachineScoresFromDisk()
|
||||||
{
|
{
|
||||||
IniFile ini;
|
|
||||||
ini.SetPath( g_sStatisticsFileName );
|
|
||||||
if( !ini.ReadFile() ) {
|
|
||||||
LOG->Trace( "WARNING: Could not read config file '%s'.", g_sStatisticsFileName.GetString() );
|
|
||||||
return; // load nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Init category top scores
|
||||||
// load song statistics
|
|
||||||
const IniFile::key *pSongsKey = ini.GetKey( "Statistics" );
|
|
||||||
if( pSongsKey )
|
|
||||||
{
|
{
|
||||||
for( IniFile::key::const_iterator i = pSongsKey->begin(); i != pSongsKey->end(); ++i )
|
for( int i=0; i<NUM_STYLES; i++ )
|
||||||
{
|
for( int j=0; j<NUM_HIGH_SCORE_CATEGORIES; j++ )
|
||||||
CString name = i->first;
|
for( int k=0; k<NUM_HIGH_SCORE_LINES; k++ )
|
||||||
CString value = i->second;
|
|
||||||
|
|
||||||
// Each value has the format "SongName::StepsName=TimesPlayed::TopGrade::TopScore::MaxCombo".
|
|
||||||
char szSongDir[256];
|
|
||||||
char szNotesType[256];
|
|
||||||
char szNotesDescription[256];
|
|
||||||
int iRetVal;
|
|
||||||
unsigned i;
|
|
||||||
|
|
||||||
// Parse for Song name and Notes name
|
|
||||||
iRetVal = sscanf( name.c_str(), "%[^:]::%[^:]::%[^\n]", szSongDir, szNotesType, szNotesDescription );
|
|
||||||
if( iRetVal != 3 )
|
|
||||||
continue; // this line doesn't match what is expected
|
|
||||||
|
|
||||||
NotesType notesType = GameManager::StringToNotesType( szNotesType );
|
|
||||||
|
|
||||||
// Search for the corresponding Song pointer.
|
|
||||||
Song* pSong = NULL;
|
|
||||||
for( i=0; i<m_pSongs.size(); i++ )
|
|
||||||
{
|
|
||||||
if( m_pSongs[i]->GetSongDir() == szSongDir ) // match!
|
|
||||||
{
|
{
|
||||||
pSong = m_pSongs[i];
|
m_MachineScores[i][j][k].iScore = 573000;
|
||||||
break;
|
m_MachineScores[i][j][k].sName = "STEP";
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if( pSong == NULL ) // didn't find a match
|
|
||||||
continue; // skip this entry
|
|
||||||
|
|
||||||
|
|
||||||
// Search for the corresponding Notes pointer.
|
|
||||||
Notes* pNotes = NULL;
|
|
||||||
for( i=0; i<pSong->m_apNotes.size(); i++ )
|
|
||||||
{
|
|
||||||
if( pSong->m_apNotes[i]->m_NotesType == notesType &&
|
|
||||||
pSong->m_apNotes[i]->GetDescription() == szNotesDescription ) // match!
|
|
||||||
{
|
|
||||||
pNotes = pSong->m_apNotes[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if( pNotes == NULL ) // didn't find a match
|
|
||||||
continue; // skip this entry
|
|
||||||
|
|
||||||
|
|
||||||
// Parse the Notes statistics.
|
|
||||||
char szGradeLetters[10]; // longest possible string is "AAA"
|
|
||||||
|
|
||||||
iRetVal = sscanf(
|
|
||||||
value.c_str(),
|
|
||||||
"%d::%[^:]::%d::%d",
|
|
||||||
&pNotes->m_iNumTimesPlayed,
|
|
||||||
szGradeLetters,
|
|
||||||
&pNotes->m_iTopScore,
|
|
||||||
&pNotes->m_iMaxCombo
|
|
||||||
);
|
|
||||||
if( iRetVal != 4 )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
pNotes->m_TopGrade = StringToGrade( szGradeLetters );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// load course statistics
|
// Read category top scores
|
||||||
const IniFile::key *pCoursesKey = ini.GetKey( "Courses" );
|
|
||||||
if( pCoursesKey )
|
|
||||||
{
|
{
|
||||||
for( IniFile::key::const_iterator i = pCoursesKey->begin(); i != pCoursesKey->end(); ++i )
|
FILE* fp = fopen( CATEGORY_TOP_SCORE_FILE, "r" );
|
||||||
{
|
|
||||||
CString name = i->first;
|
|
||||||
CString value = i->second;
|
|
||||||
|
|
||||||
// Each value has the format "CoursePath,Difficulty,Slot=DancePoints,SurviveTime,sName"
|
for( int i=0; i<NUM_STYLES; i++ )
|
||||||
|
for( int j=0; j<NUM_HIGH_SCORE_CATEGORIES; j++ )
|
||||||
|
for( int k=0; k<NUM_HIGH_SCORE_LINES; k++ )
|
||||||
|
if( fp && !feof(fp) )
|
||||||
|
{
|
||||||
|
char szName[256];
|
||||||
|
fscanf(fp, "%d %[^\n]\n", &m_MachineScores[i][j][k].iScore, szName);
|
||||||
|
m_MachineScores[i][j][k].sName = szName;
|
||||||
|
}
|
||||||
|
|
||||||
// Parse left hand side
|
if( fp )
|
||||||
char szCoursePath[256];
|
fclose(fp);
|
||||||
Difficulty difficulty;
|
|
||||||
int iSlot;
|
|
||||||
int iDancePoints;
|
|
||||||
float fSurviveTime;
|
|
||||||
char szName[256];
|
|
||||||
|
|
||||||
int iRetVal;
|
|
||||||
iRetVal = sscanf( name.c_str(), "%[^,],%d,%d", szCoursePath, &difficulty, &iSlot );
|
|
||||||
if( iRetVal != 3 )
|
|
||||||
continue; // line doesn't match what is expected
|
|
||||||
iRetVal = sscanf( value.c_str(), "%d,%f,%d[^\n]", &iDancePoints, &fSurviveTime, &szName );
|
|
||||||
if( iRetVal != 3 )
|
|
||||||
continue; // line doesn't match what is expected
|
|
||||||
|
|
||||||
|
|
||||||
// Search for the corresponding Course pointer.
|
|
||||||
Course* pCourse = SONGMAN->GetCourseFromPath( szCoursePath );
|
|
||||||
if( pCourse == NULL ) // didn't find a match
|
|
||||||
continue; // skip this entry
|
|
||||||
|
|
||||||
// pCourse->m_TopGrade = StringToGrade( szGradeLetters );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read course top scores
|
||||||
|
{
|
||||||
|
FILE* fp = fopen( COURSE_TOP_SCORE_FILE, "r" );
|
||||||
|
|
||||||
|
while( fp && !feof(fp) )
|
||||||
|
{
|
||||||
|
char szPath[256];
|
||||||
|
fscanf(fp, "%s\n", szPath);
|
||||||
|
Course* pCourse = GetCourseFromPath( szPath );
|
||||||
|
|
||||||
|
for( int i=0; i<NUM_STYLES; i++ )
|
||||||
|
for( int j=0; j<NUM_HIGH_SCORE_CATEGORIES; j++ )
|
||||||
|
for( int k=0; k<NUM_HIGH_SCORE_LINES; k++ )
|
||||||
|
if( fp && !feof(fp) )
|
||||||
|
{
|
||||||
|
int iDancePoints;
|
||||||
|
float fSurviveTime;
|
||||||
|
char szName[256];
|
||||||
|
fscanf(fp, "%d %f %[^\n]\n", &iDancePoints, &fSurviveTime, szName);
|
||||||
|
if( pCourse )
|
||||||
|
{
|
||||||
|
pCourse->m_MachineScores[i][j][k].iDancePoints = iDancePoints;
|
||||||
|
pCourse->m_MachineScores[i][j][k].fSurviveTime = fSurviveTime;
|
||||||
|
pCourse->m_MachineScores[i][j][k].sName = szName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( fp )
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SongManager::SaveStatisticsToDisk()
|
void SongManager::SaveMachineScoresToDisk()
|
||||||
{
|
{
|
||||||
IniFile ini;
|
// Write category top scores
|
||||||
ini.SetPath( g_sStatisticsFileName );
|
|
||||||
|
|
||||||
// save song statistics
|
|
||||||
for( unsigned i=0; i<m_pSongs.size(); i++ ) // for each Song
|
|
||||||
{
|
{
|
||||||
Song* pSong = m_pSongs[i];
|
FILE* fp = fopen( CATEGORY_TOP_SCORE_FILE, "w" );
|
||||||
|
|
||||||
for( unsigned j=0; j<pSong->m_apNotes.size(); j++ ) // for each Notes
|
for( int i=0; i<NUM_STYLES; i++ )
|
||||||
{
|
for( int j=0; j<NUM_HIGH_SCORE_CATEGORIES; j++ )
|
||||||
Notes* pNotes = pSong->m_apNotes[j];
|
for( int k=0; k<NUM_HIGH_SCORE_LINES; k++ )
|
||||||
|
if( fp )
|
||||||
|
fprintf(fp, "%d %s\n", m_MachineScores[i][j][k].iScore, m_MachineScores[i][j][k].sName.c_str());
|
||||||
|
|
||||||
if( pNotes->m_TopGrade == GRADE_NO_DATA )
|
if( fp )
|
||||||
continue; // skip
|
fclose(fp);
|
||||||
|
|
||||||
// Each value has the format "SongName::NotesName=TimesPlayed::TopGrade::TopScore::MaxCombo".
|
|
||||||
|
|
||||||
CString sName = ssprintf( "%s::%s::%s", pSong->GetSongDir().GetString(), GameManager::NotesTypeToString(pNotes->m_NotesType).GetString(), pNotes->GetDescription().GetString() );
|
|
||||||
CString sValue = ssprintf(
|
|
||||||
"%d::%s::%d::%d",
|
|
||||||
pNotes->m_iNumTimesPlayed,
|
|
||||||
GradeToString( pNotes->m_TopGrade ).GetString(),
|
|
||||||
pNotes->m_iTopScore,
|
|
||||||
pNotes->m_iMaxCombo
|
|
||||||
);
|
|
||||||
|
|
||||||
ini.SetValue( "Statistics", sName, sValue );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ini.WriteFile();
|
// Write course top scores
|
||||||
|
{
|
||||||
|
FILE* fp = fopen( COURSE_TOP_SCORE_FILE, "w" );
|
||||||
|
|
||||||
|
if( fp )
|
||||||
|
{
|
||||||
|
for( unsigned i=0; i<m_pCourses.size(); i++ ) // foreach course
|
||||||
|
{
|
||||||
|
Course* pCourse = m_pCourses[i];
|
||||||
|
|
||||||
|
fprintf(fp, "%s\n", pCourse->m_sPath.c_str());
|
||||||
|
|
||||||
|
for( int i=0; i<NUM_STYLES; i++ )
|
||||||
|
for( int j=0; j<NUM_DIFFICULTIES; j++ )
|
||||||
|
for( int k=0; k<NUM_HIGH_SCORE_LINES; k++ )
|
||||||
|
fprintf(fp, "%d %f %s\n",
|
||||||
|
pCourse->m_MachineScores[i][j][k].iDancePoints,
|
||||||
|
pCourse->m_MachineScores[i][j][k].fSurviveTime,
|
||||||
|
pCourse->m_MachineScores[i][j][k].sName.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( fp )
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -495,10 +392,12 @@ void SongManager::InitCoursesFromDisk()
|
|||||||
GetDirListing( "Courses\\*.crs", saCourseFiles );
|
GetDirListing( "Courses\\*.crs", saCourseFiles );
|
||||||
for( unsigned i=0; i<saCourseFiles.size(); i++ )
|
for( unsigned i=0; i<saCourseFiles.size(); i++ )
|
||||||
{
|
{
|
||||||
Course course;
|
Course* pCourse = new Course;
|
||||||
course.LoadFromCRSFile( "Courses\\" + saCourseFiles[i], m_pSongs );
|
pCourse->LoadFromCRSFile( "Courses\\" + saCourseFiles[i], m_pSongs );
|
||||||
if( course.GetNumStages() > 0 )
|
if( pCourse->GetNumStages() > 0 )
|
||||||
m_Courses.push_back( course );
|
m_pCourses.push_back( pCourse );
|
||||||
|
else
|
||||||
|
delete pCourse;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -515,18 +414,22 @@ void SongManager::InitCoursesFromDisk()
|
|||||||
|
|
||||||
for( Difficulty dc=DIFFICULTY_EASY; dc<=DIFFICULTY_HARD; dc=Difficulty(dc+1) ) // foreach Difficulty
|
for( Difficulty dc=DIFFICULTY_EASY; dc<=DIFFICULTY_HARD; dc=Difficulty(dc+1) ) // foreach Difficulty
|
||||||
{
|
{
|
||||||
Course course;
|
Course* pCourse = new Course;
|
||||||
course.CreateEndlessCourseFromGroupAndDifficulty( sGroupName, dc, apGroupSongs );
|
pCourse->CreateEndlessCourseFromGroupAndDifficulty( sGroupName, dc, apGroupSongs );
|
||||||
|
|
||||||
if( course.GetNumStages() > 0 )
|
if( pCourse->GetNumStages() > 0 )
|
||||||
m_Courses.push_back( course );
|
m_pCourses.push_back( pCourse );
|
||||||
|
else
|
||||||
|
delete pCourse;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SongManager::ReloadCourses()
|
void SongManager::FreeCourses()
|
||||||
{
|
{
|
||||||
|
for( unsigned i=0; i<m_pCourses.size(); i++ )
|
||||||
|
delete m_pCourses[i];
|
||||||
|
m_pCourses.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Called periodically to wipe out cached NoteData. This is called when we change
|
/* Called periodically to wipe out cached NoteData. This is called when we change
|
||||||
@@ -545,37 +448,37 @@ void SongManager::CleanCourses()
|
|||||||
void SongManager::GetNonstopCourses( vector<Course*> AddTo )
|
void SongManager::GetNonstopCourses( vector<Course*> AddTo )
|
||||||
{
|
{
|
||||||
PlayerOptions po;
|
PlayerOptions po;
|
||||||
for( unsigned i=0; i<m_Courses.size(); i++ )
|
for( unsigned i=0; i<m_pCourses.size(); i++ )
|
||||||
{
|
{
|
||||||
if( m_Courses[i].m_bRepeat )
|
if( m_pCourses[i]->m_bRepeat )
|
||||||
continue; // skip
|
continue; // skip
|
||||||
if( m_Courses[i].m_iLives > 0 ) // use battery life meter
|
if( m_pCourses[i]->m_iLives > 0 ) // use battery life meter
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
AddTo.push_back( &m_Courses[i] );
|
AddTo.push_back( m_pCourses[i] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SongManager::GetOniCourses( vector<Course*> AddTo )
|
void SongManager::GetOniCourses( vector<Course*> AddTo )
|
||||||
{
|
{
|
||||||
PlayerOptions po;
|
PlayerOptions po;
|
||||||
for( unsigned i=0; i<m_Courses.size(); i++ )
|
for( unsigned i=0; i<m_pCourses.size(); i++ )
|
||||||
{
|
{
|
||||||
if( m_Courses[i].m_bRepeat )
|
if( m_pCourses[i]->m_bRepeat )
|
||||||
continue; // skip
|
continue; // skip
|
||||||
if( m_Courses[i].m_iLives <= 0 ) // use bar life meter
|
if( m_pCourses[i]->m_iLives <= 0 ) // use bar life meter
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
AddTo.push_back( &m_Courses[i] );
|
AddTo.push_back( m_pCourses[i] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SongManager::GetEndlessCourses( vector<Course*> AddTo )
|
void SongManager::GetEndlessCourses( vector<Course*> AddTo )
|
||||||
{
|
{
|
||||||
for( unsigned i=0; i<m_Courses.size(); i++ )
|
for( unsigned i=0; i<m_pCourses.size(); i++ )
|
||||||
{
|
{
|
||||||
if( m_Courses[i].m_bRepeat )
|
if( m_pCourses[i]->m_bRepeat )
|
||||||
AddTo.push_back( &m_Courses[i] );
|
AddTo.push_back( m_pCourses[i] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -699,9 +602,14 @@ Song* SongManager::GetSongFromDir( CString sDir )
|
|||||||
|
|
||||||
Course* SongManager::GetCourseFromPath( CString sPath )
|
Course* SongManager::GetCourseFromPath( CString sPath )
|
||||||
{
|
{
|
||||||
for( unsigned int i=0; i<m_Courses.size(); i++ )
|
for( unsigned int i=0; i<m_pCourses.size(); i++ )
|
||||||
if( sPath.CompareNoCase(m_Courses[i].m_sPath) == 0 )
|
if( sPath.CompareNoCase(m_pCourses[i]->m_sPath) == 0 )
|
||||||
return &m_Courses[i];
|
return m_pCourses[i];
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SongManager::IsUsingMemoryCard( PlayerNumber pn )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -32,9 +32,6 @@ public:
|
|||||||
void FreeSongArray();
|
void FreeSongArray();
|
||||||
void ReloadSongArray();
|
void ReloadSongArray();
|
||||||
|
|
||||||
void ReadStatisticsFromDisk();
|
|
||||||
void SaveStatisticsToDisk();
|
|
||||||
|
|
||||||
|
|
||||||
CString GetGroupBannerPath( CString sGroupName );
|
CString GetGroupBannerPath( CString sGroupName );
|
||||||
void GetGroupNames( CStringArray &AddTo );
|
void GetGroupNames( CStringArray &AddTo );
|
||||||
@@ -43,31 +40,49 @@ public:
|
|||||||
|
|
||||||
static CString ShortenGroupName( const CString &sOrigGroupName );
|
static CString ShortenGroupName( const CString &sOrigGroupName );
|
||||||
|
|
||||||
void GetSongsInGroup( const CString sGroupName, vector<Song*> &AddTo );
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Courses for Nonstop, Oni, and Endless
|
// Courses for Nonstop, Oni, and Endless
|
||||||
//
|
//
|
||||||
vector<Course> m_Courses;
|
vector<Course*> m_pCourses;
|
||||||
|
|
||||||
void InitCoursesFromDisk();
|
void InitCoursesFromDisk();
|
||||||
void ReloadCourses();
|
void FreeCourses();
|
||||||
void CleanCourses();
|
void CleanCourses();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Lookup
|
||||||
|
void GetSongsInGroup( const CString sGroupName, vector<Song*> &AddTo );
|
||||||
|
Song* GetRandomSong();
|
||||||
|
|
||||||
void GetNonstopCourses( vector<Course*> AddTo ); // add to if life meter type is BAR.
|
void GetNonstopCourses( vector<Course*> AddTo ); // add to if life meter type is BAR.
|
||||||
void GetOniCourses( vector<Course*> AddTo ); // add to if life meter type is BATTERY.
|
void GetOniCourses( vector<Course*> AddTo ); // add to if life meter type is BATTERY.
|
||||||
void GetEndlessCourses( vector<Course*> AddTo ); // add to if set to REPEAT.
|
void GetEndlessCourses( vector<Course*> AddTo ); // add to if set to REPEAT.
|
||||||
|
|
||||||
|
|
||||||
void GetExtraStageInfo( bool bExtra2, CString sPreferredGroup, const StyleDef *s,
|
void GetExtraStageInfo( bool bExtra2, CString sPreferredGroup, const StyleDef *s,
|
||||||
Song*& pSongOut, Notes*& pNotesOut, PlayerOptions& po_out, SongOptions& so_out );
|
Song*& pSongOut, Notes*& pNotesOut, PlayerOptions& po_out, SongOptions& so_out );
|
||||||
|
|
||||||
Song* GetRandomSong();
|
|
||||||
|
|
||||||
Song* GetSongFromDir( CString sDir );
|
Song* GetSongFromDir( CString sDir );
|
||||||
Course* GetCourseFromPath( CString sPath ); // path to .crs file, or path to song group dir
|
Course* GetCourseFromPath( CString sPath ); // path to .crs file, or path to song group dir
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// High scores
|
||||||
|
//
|
||||||
|
struct HighScore
|
||||||
|
{
|
||||||
|
int iScore;
|
||||||
|
CString sName;
|
||||||
|
};
|
||||||
|
HighScore m_MachineScores[NUM_STYLES][NUM_HIGH_SCORE_CATEGORIES][NUM_HIGH_SCORE_LINES];
|
||||||
|
|
||||||
|
void InitMachineScoresFromDisk();
|
||||||
|
void SaveMachineScoresToDisk();
|
||||||
|
|
||||||
|
bool IsUsingMemoryCard( PlayerNumber pn );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void LoadStepManiaSongDir( CString sDir, LoadingWindow *ld );
|
void LoadStepManiaSongDir( CString sDir, LoadingWindow *ld );
|
||||||
void LoadDWISongDir( CString sDir );
|
void LoadDWISongDir( CString sDir );
|
||||||
|
|||||||
@@ -198,7 +198,7 @@ public:
|
|||||||
int GetNumTimesPlayed() const;
|
int GetNumTimesPlayed() const;
|
||||||
bool IsNew() const;
|
bool IsNew() const;
|
||||||
bool IsEasy( NotesType nt ) const;
|
bool IsEasy( NotesType nt ) const;
|
||||||
Grade GetGradeForDifficulty( const StyleDef *s, int p, Difficulty dc ) const;
|
Grade GetGradeForDifficulty( const StyleDef *s, PlayerNumber pn, Difficulty dc ) const;
|
||||||
bool NormallyDisplayed() const;
|
bool NormallyDisplayed() const;
|
||||||
bool RouletteDisplayed() const;
|
bool RouletteDisplayed() const;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user