working on course ranking scores and mem card saving

This commit is contained in:
Chris Danford
2003-02-14 21:42:44 +00:00
parent b47254c32b
commit e05738f7f7
21 changed files with 672 additions and 422 deletions
+10
View File
@@ -934,3 +934,13 @@ TwoLinesArtistY=8
ThreeLinesTitleY=-10
ThreeLinesSubTitleY=0
ThreeLinesArtistY=10
[CourseContentDisplay]
TextBannerX=0
TextBannerY=0
NumberX=-118
NumberY=0
FootX=102
FootY=8
DifficultyX=120
DifficultyY=8
+168 -143
View File
@@ -15,7 +15,6 @@
#include "Song.h"
#include "GameManager.h"
#include "SongManager.h"
#include "GameState.h"
#include "RageException.h"
#include "RageLog.h"
#include "MsdFile.h"
@@ -24,31 +23,31 @@
#include "RageUtil.h"
#include "TitleSubstitution.h"
Course::Course()
{
m_bIsAutoGen = false;
m_bRepeat = false;
m_bRandomize = false;
m_iLives = -1;
m_iExtra = 0;
m_iNumTimesPlayed = 0;
//
// Init high scores
//
unsigned i, j;
for( i=0; i<NUM_NOTES_TYPES; i++ )
for( j=0; j<NUM_RANKING_LINES; j++ )
for( unsigned i=0; i<NUM_NOTES_TYPES; i++ )
for( unsigned j=0; j<NUM_RANKING_LINES; j++ )
{
m_MachineScores[i][j].iDancePoints = 573;
m_MachineScores[i][j].fSurviveTime = 57.3f;
m_MachineScores[i][j].sName = "STEP";
m_RankingScores[i][j].iDancePoints = 573;
m_RankingScores[i][j].fSurviveTime = 57.3f;
m_RankingScores[i][j].sName = DEFAULT_RANKING_NAME;
}
for( i=0; i<NUM_NOTES_TYPES; i++ )
for( j=0; j<NUM_PLAYERS; j++ )
for( unsigned m=0; m<NUM_MEMORY_CARDS; m++ )
for( unsigned i=0; i<NUM_NOTES_TYPES; i++ )
{
m_MemCardScores[i][j].iDancePoints = 0;
m_MemCardScores[i][j].fSurviveTime = 0;
m_MemCardScores[m][i].iNumTimesPlayed = 0;
m_MemCardScores[m][i].iDancePoints = 0;
m_MemCardScores[m][i].fSurviveTime = 0;
}
}
@@ -69,7 +68,7 @@ Course::Course()
* songs in "Songs"; we don't want that.
*/
Song *Course::FindSong(CString sSongDir)
Song *Course::FindSong(CString sSongDir) const
{
const vector<Song*> &apSongs = SONGMAN->GetAllSongs();
@@ -156,21 +155,16 @@ void Course::LoadFromCRSFile( CString sPath )
else if( 0 == stricmp(sValueName, "SONG") )
{
CString sSongDir = sParams[1];
CString sNotesDescription = sParams[2];
Difficulty dc = StringToDifficulty( sParams[2] );
CString sModifiers = sParams[3];
if(!sSongDir.GetLength()) {
if( sSongDir.GetLength() == 0 ) {
/* Err. */
LOG->Trace( "Course file '%s' has an empty #SONG. Ignored.", sPath.GetString(), sSongDir.GetString() );
continue;
}
Song *pSong = FindSong(sSongDir);
if( pSong == NULL ) // we didn't find the Song
continue; // skip this song
AddStage( pSong, sNotesDescription, sModifiers );
m_entries.push_back( course_entry(sSongDir, dc, sModifiers) );
}
else
@@ -184,8 +178,9 @@ void Course::LoadFromCRSFile( CString sPath )
}
void Course::CreateEndlessCourseFromGroupAndDifficulty( CString sGroupName, Difficulty dc, vector<Song*> &apSongsInGroup )
void Course::AutoGenEndlessFromGroupAndDifficulty( CString sGroupName, Difficulty dc, vector<Song*> &apSongsInGroup )
{
m_bIsAutoGen = true;
m_bRepeat = true;
m_bRandomize = true;
m_iLives = -1;
@@ -213,162 +208,204 @@ void Course::CreateEndlessCourseFromGroupAndDifficulty( CString sGroupName, Diff
for( unsigned s=0; s<apSongsInGroup.size(); s++ )
{
Song* pSong = apSongsInGroup[s];
AddStage( pSong, DifficultyToString(dc), "" );
m_entries.push_back( course_entry(pSong->GetSongDir(), dc, "") );
}
Shuffle();
}
void Course::Shuffle()
bool Course::HasDifficult() const
{
/* Shuffle the list. */
for( int i = 0; i < GetNumStages(); ++i)
swap(order[i], order[rand() % GetNumStages()]);
for( unsigned i=0; i<m_entries.size(); i++ )
if( m_entries[i].difficulty >= DIFFICULTY_HARD )
return false;
return true;
}
Notes* Course::GetNotesForStage( int iStage )
void Course::GetCourseInfo(
vector<Song*>& vSongsOut,
vector<Notes*>& vNotesOut,
vector<CString>& vsModifiersOut,
NotesType nt,
bool bDifficult ) const
{
Song* pSong = GetSong(iStage);
CString sDescription = entries[iStage].description;
/* First, search for an exact description match. */
unsigned i;
for( i=0; i<pSong->m_apNotes.size(); i++ )
if( bDifficult )
ASSERT( HasDifficult() );
vector<course_entry> entries = m_entries;
if( m_bRandomize )
random_shuffle( entries.begin(), entries.end() );
for( unsigned i=0; i<entries.size(); i++ )
{
Notes* pNotes = pSong->m_apNotes[i];
CString sSongDir = entries[i].songDir;
if( !GAMESTATE->GetCurrentStyleDef()->MatchesNotesType(pNotes->m_NotesType) )
continue;
Song* pSong;
if( sSongDir.Left(strlen("PlayersBest")) == "PlayersBest" )
{
int iNumber = atoi( sSongDir.Right(sSongDir.length()-strlen("PlayersBest")) );
int index = iNumber - 1;
pSong = SONGMAN->GetPlayersBest( index );
}
else if( sSongDir.Left(strlen("PlayersWorst")) == "PlayersWorst" )
{
int iNumber = atoi( sSongDir.Right(sSongDir.length()-strlen("PlayersWorst")) );
int index = iNumber - 1;
pSong = SONGMAN->GetPlayersWorst( index );
}
else if( sSongDir.Right(1) == "*" )
{
CStringArray asSongDirs;
GetDirListing( sSongDir, asSongDirs, true, true );
if( asSongDirs.empty() )
pSong = NULL;
else
pSong = FindSong( asSongDirs[rand()%asSongDirs.size()] );
}
else
pSong = FindSong( sSongDir );
if( !pNotes->GetDescription().CompareNoCase(sDescription) )
return pNotes;
}
/* If that failed, try to do a difficulty match. */
Difficulty dc = StringToDifficulty(sDescription);
for( i=0; i < pSong->m_apNotes.size(); i++ )
{
Notes* pNotes = pSong->m_apNotes[i];
if( !GAMESTATE->GetCurrentStyleDef()->MatchesNotesType(pNotes->m_NotesType) )
continue;
if(dc == pNotes->GetDifficulty())
return pNotes;
}
return NULL;
}
Song *Course::GetSong( int iStage ) const
{
return entries[iStage].song;
}
CString Course::GetDescription( int iStage ) const
{
return entries[iStage].description;
}
void Course::AddStage( Song* pSong, CString sDescription, CString sModifiers )
{
course_entry e;
e.song = pSong;
e.description = sDescription;
e.modifiers = sModifiers;
entries.push_back(e);
order.push_back(order.size());
}
/* When bShuffled is true, returns courses in the song ordering list. */
void Course::GetSongAndNotesForCurrentStyle(
vector<Song*>& apSongsOut,
vector<Notes*>& apNotesOut,
CStringArray& asModifiersOut,
bool bShuffled )
{
for( int i=0; i<GetNumStages(); i++ )
{
int num = bShuffled? order[i]:i;
Song* pSong = GetSong(num);
Notes* pNotes = GetNotesForStage( num );
CString sModifiers = entries[num].modifiers;
if( !pSong->HasMusic() )
if( pSong == NULL )
continue; // skip
Difficulty dc = entries[i].difficulty;
if( bDifficult && dc != NUM_DIFFICULTIES-1 )
dc = (Difficulty)(dc+1);
Notes* pNotes = pSong->GetNotes( nt, dc );
if( pNotes == NULL )
continue; // skip
apSongsOut.push_back( pSong );
apNotesOut.push_back( pNotes );
asModifiersOut.push_back( sModifiers );
CString sModifiers = entries[i].modifiers;
vSongsOut.push_back( pSong );
vNotesOut.push_back( pNotes );
vsModifiersOut.push_back( sModifiers );
}
}
RageColor Course::GetColor()
bool Course::GetFirstStageInfo(
Song*& pSongOut,
Notes*& pNotesOut,
CString& sModifiersOut,
NotesType nt ) const
{
vector<Song*> vSongs;
vector<Notes*> vNotes;
vector<CString> vsModifiers;
GetCourseInfo(
vSongs,
vNotes,
vsModifiers,
nt,
false );
if( vSongs.empty() )
return false;
pSongOut = vSongs[0];
pNotesOut = vNotes[0];
sModifiersOut = vsModifiers[0];
return true;
}
RageColor Course::GetColor() const
{
// This could be made smarter
if( GetNumStages() >= 7 )
if( m_entries.size() >= 7 )
return RageColor(1,0,0,1); // red
else if( GetNumStages() >= 4 )
else if( m_entries.size() >= 4 )
return RageColor(1,0.5f,0,1); // orange
else
return RageColor(0,1,0,1); // green
}
void Course::GetPlayerOptions( int iStage, PlayerOptions* pPO_out ) const
bool Course::IsMysterySong( int stage ) const
{
pPO_out->FromString( entries[iStage].modifiers );
CString sSongDir = m_entries[stage].songDir;
return sSongDir.Right(1) == "*";
}
void Course::GetSongOptions( SongOptions* pSO_out ) const
bool Course::ContainsAnyMysterySongs() const
{
*pSO_out = SongOptions();
//hack: The lifebar modifiers were not showing up (in the extra stages) - had to add it here.
if( entries.size() > 0 )
pSO_out->FromString( entries[0].modifiers );
pSO_out->m_LifeType = (m_iLives==-1) ? SongOptions::LIFE_BAR : SongOptions::LIFE_BATTERY;
if( m_iLives != -1 )
pSO_out->m_iBatteryLives = m_iLives;
for( unsigned i=0; i<m_entries.size(); i++ )
if( IsMysterySong(i) )
return true;
return false;
}
int Course::GetNumStages() const
bool Course::GetTotalSeconds( float& fSecondsOut ) const
{
return entries.size();
if( ContainsAnyMysterySongs() )
return false;
vector<Song*> vSongsOut;
vector<Notes*> vNotesOut;
vector<CString> vsModifiersOut;
GetCourseInfo(
vSongsOut,
vNotesOut,
vsModifiersOut,
NOTES_TYPE_DANCE_SINGLE, // doesn't matter
false ); // doesn't matter
fSecondsOut = 0;
for( unsigned i=0; i<vSongsOut.size(); i++ )
fSecondsOut += vSongsOut[i]->m_fMusicLengthSeconds;
return true;
}
struct CourseScoreToInsert
struct RankingToInsert
{
PlayerNumber pn;
int iDancePoints;
float fSurviveTime;
static int CompareDescending( const CourseScoreToInsert &hs1, const CourseScoreToInsert &hs2 )
static int CompareDescending( const RankingToInsert &hs1, const RankingToInsert &hs2 )
{
if( hs1.iDancePoints > hs2.iDancePoints ) return -1;
else if( hs1.iDancePoints == hs2.iDancePoints ) return 0;
else return +1;
}
static void SortDescending( vector<CourseScoreToInsert>& vHSout )
static void SortDescending( vector<RankingToInsert>& vHSout )
{
sort( vHSout.begin(), vHSout.end(), CompareDescending );
}
};
void Course::AddMachineRecords( NotesType nt, int iDancePoints[NUM_PLAYERS], float fSurviveTime[NUM_PLAYERS], int iRankingIndexOut[NUM_PLAYERS] ) // set iNewRecordIndex = -1 if not a new record
void Course::AddScores( NotesType nt, bool bPlayerEnabled[NUM_PLAYERS], int iDancePoints[NUM_PLAYERS], float fSurviveTime[NUM_PLAYERS], int iRankingIndexOut[NUM_PLAYERS], bool bNewRecordOut[NUM_PLAYERS] )
{
vector<CourseScoreToInsert> vHS;
m_MemCardScores[MEMORY_CARD_MACHINE][nt].iNumTimesPlayed++;
vector<RankingToInsert> vHS;
for( int p=0; p<NUM_PLAYERS; p++ )
{
iRankingIndexOut[p] = -1;
bNewRecordOut = false;
if( !GAMESTATE->IsPlayerEnabled(p) )
if( !bPlayerEnabled[p] )
continue; // skip
CourseScoreToInsert hs;
// Update memory card
m_MemCardScores[p][nt].iNumTimesPlayed++;
if( iDancePoints[p] > m_MemCardScores[p][nt].iDancePoints )
{
m_MemCardScores[p][nt].iDancePoints = iDancePoints[p];
m_MemCardScores[p][nt].fSurviveTime = fSurviveTime[p];
bNewRecordOut[p] = true;
}
// Update Ranking
RankingToInsert hs;
hs.iDancePoints = iDancePoints[p];
hs.fSurviveTime = fSurviveTime[p];
hs.pn = (PlayerNumber)p;
@@ -377,48 +414,36 @@ void Course::AddMachineRecords( NotesType nt, int iDancePoints[NUM_PLAYERS], flo
// Sort descending before inserting.
// This guarantees that a high score will not switch poitions on us when we later insert scores for the other player
CourseScoreToInsert::SortDescending( vHS );
RankingToInsert::SortDescending( vHS );
for( unsigned i=0; i<vHS.size(); i++ )
{
CourseScoreToInsert& newHS = vHS[i];
MachineScore* machineScores = m_MachineScores[nt];
RankingToInsert& newHS = vHS[i];
RankingScore* rankingScores = m_RankingScores[nt];
for( int i=0; i<NUM_RANKING_LINES; i++ )
{
if( newHS.iDancePoints > machineScores[i].iDancePoints )
if( newHS.iDancePoints > rankingScores[i].iDancePoints )
{
// We found the insert point. Shift down.
for( int j=i+1; j<NUM_RANKING_LINES; j++ )
machineScores[j] = machineScores[j-1];
rankingScores[j] = rankingScores[j-1];
// insert
machineScores[i].fSurviveTime = newHS.fSurviveTime;
machineScores[i].iDancePoints = newHS.iDancePoints;
machineScores[i].sName = "STEP";
rankingScores[i].fSurviveTime = newHS.fSurviveTime;
rankingScores[i].iDancePoints = newHS.iDancePoints;
rankingScores[i].sName = DEFAULT_RANKING_NAME;
iRankingIndexOut[newHS.pn] = i;
}
}
}
}
bool Course::AddMemCardRecord( PlayerNumber pn, NotesType nt, int iDancePoints, float fSurviveTime ) // return true if new record
{
MemCardScore& hs = m_MemCardScores[nt][pn];
if( iDancePoints > hs.iDancePoints )
{
hs.iDancePoints = iDancePoints;
hs.fSurviveTime = fSurviveTime;
return true;
}
return false;
}
//
// Sorting stuff
//
static int CompareCoursePointersByDifficulty(const Course* pCourse1, const Course* pCourse2)
{
return pCourse1->GetNumStages() < pCourse2->GetNumStages();
return pCourse1->GetEstimatedNumStages() < pCourse2->GetEstimatedNumStages();
}
void SortCoursePointerArrayByDifficulty( vector<Course*> &apCourses )
+40 -28
View File
@@ -21,63 +21,75 @@ struct Notes;
class Course
{
struct course_entry {
CString description; // the Notes description
CString modifiers; // set player and song options from these
Song *song;
course_entry( CString dir, Difficulty dc, CString mod )
{
songDir = dir;
difficulty = dc;
modifiers = mod;
}
CString songDir;
Difficulty difficulty; // the Notes description
CString modifiers; // set player and song options from these
};
vector<course_entry> entries;
vector<int> order;
vector<course_entry> m_entries;
public:
Course();
bool m_bIsAutoGen; // was this created by AutoGen?
CString m_sPath;
CString m_sName;
CString m_sBannerPath;
CString m_sCDTitlePath;
bool m_bRepeat; // repeat after last song?
bool m_bRepeat; // repeat after last song? "Endless"
bool m_bRandomize; // play the songs in a random order
int m_iLives; // -1 means use bar life meter
int m_iExtra; // extra stage number...
int m_iExtra; // extra stage number... // not used? -Chris
int GetEstimatedNumStages() const { return m_entries.size(); }
bool HasDifficult() const;
void GetCourseInfo( // Derefrences course_entries and returns only the playable Songs and Notes
vector<Song*>& vSongsOut,
vector<Notes*>& vNotesOut,
vector<CString>& vsModifiersOut,
NotesType nt,
bool bDifficult ) const; // like EX's Standard/Difficult option for courses
bool GetFirstStageInfo(
Song*& pSongOut,
Notes*& pNotesOut,
CString& sModifiersOut,
NotesType nt ) const;
RageColor GetColor() const;
bool IsMysterySong( int stage ) const;
bool ContainsAnyMysterySongs() const;
bool GetTotalSeconds( float& fSecondsOut ) const;
Notes *GetNotesForStage( int iStage );
Song *GetSong( int iStage ) const;
CString GetDescription( int iStage ) const;
// CString GetModifiers( int iStage ) const; // redundant. -Chris
void GetPlayerOptions( int iStage, PlayerOptions* pPO_out ) const;
void GetSongOptions( SongOptions* pSO_out) const;
int GetNumStages() const;
void LoadFromCRSFile( CString sPath );
void CreateEndlessCourseFromGroupAndDifficulty( CString sGroupName, Difficulty dc, vector<Song*> &apSongsInGroup );
void AddStage( Song* pSong, CString sDescription, CString sModifiers );
void AutoGenEndlessFromGroupAndDifficulty( CString sGroupName, Difficulty dc, vector<Song*> &apSongsInGroup );
void GetSongAndNotesForCurrentStyle( vector<Song*>& apSongsOut, vector<Notes*>& apNotesOut, CStringArray& asModifiersOut, bool bShuffled );
RageColor GetColor();
// Statistics
int m_iNumTimesPlayed;
struct MachineScore
struct RankingScore
{
int iDancePoints;
float fSurviveTime;
CString sName;
} m_MachineScores[NUM_NOTES_TYPES][NUM_RANKING_LINES]; // sorted highest to lowest by iDancePoints
void AddMachineRecords( NotesType nt, int iDancePoints[NUM_PLAYERS], float fSurviveTime[NUM_PLAYERS], int iLineIndexOut[NUM_PLAYERS] ); // set iNewRecordIndex = -1 if not a new record
} m_RankingScores[NUM_NOTES_TYPES][NUM_RANKING_LINES]; // sorted highest to lowest by iDancePoints
struct MemCardScore
{
int iNumTimesPlayed;
int iDancePoints;
float fSurviveTime;
} m_MemCardScores[NUM_NOTES_TYPES][NUM_PLAYERS];
bool AddMemCardRecord( PlayerNumber pn, NotesType nt, int iDancePoints, float fSurviveTime ); // return true if this is a new record
} m_MemCardScores[NUM_MEMORY_CARDS][NUM_NOTES_TYPES];
void AddScores( NotesType nt, bool bPlayerEnabled[NUM_PLAYERS], int iDancePoints[NUM_PLAYERS], float fSurviveTime[NUM_PLAYERS], int iRankingIndexOut[NUM_PLAYERS], bool bNewRecordOut[NUM_PLAYERS] ); // iNewRecordIndexOut[p] = -1 if not a new record
private:
void Shuffle();
Song *FindSong(CString sSongDir);
Song *FindSong(CString sSongDir) const;
};
+19 -17
View File
@@ -22,19 +22,18 @@
#include "RageDisplay.h"
#include "ThemeManager.h"
#include "Notes.h"
#include "GameState.h"
#include "StyleDef.h"
const float TEXT_BANNER_X = 0;
const float TEXT_BANNER_Y = 0;
const float NUMBER_X = -118;
const float NUMBER_Y = 0;
const float FOOT_X = 102;
const float FOOT_Y = 8;
const float DIFFICULTY_X = FOOT_X+18;
const float DIFFICULTY_Y = FOOT_Y;
#define TEXT_BANNER_X THEME->GetMetricF("CourseContentDisplay","TextBannerX")
#define TEXT_BANNER_Y THEME->GetMetricF("CourseContentDisplay","TextBannerY")
#define NUMBER_X THEME->GetMetricF("CourseContentDisplay","NumberX")
#define NUMBER_Y THEME->GetMetricF("CourseContentDisplay","NumberY")
#define FOOT_X THEME->GetMetricF("CourseContentDisplay","FootX")
#define FOOT_Y THEME->GetMetricF("CourseContentDisplay","FootY")
#define DIFFICULTY_X THEME->GetMetricF("CourseContentDisplay","DifficultyX")
#define DIFFICULTY_Y THEME->GetMetricF("CourseContentDisplay","DifficultyY")
CourseContentDisplay::CourseContentDisplay()
@@ -103,13 +102,16 @@ void CourseContentsFrame::SetFromCourse( Course* pCourse )
m_iNumContents = 0;
for( int i=0; i<min(pCourse->GetNumStages(), MAX_TOTAL_CONTENTS); i++ )
{
Song* pSong = pCourse->GetSong(i);
Notes* pNotes = pCourse->GetNotesForStage(i);
vector<Song*> vSongs;
vector<Notes*> vNotes;
vector<CString> vsModifiers;
pCourse->GetCourseInfo( vSongs, vNotes, vsModifiers, GAMESTATE->GetCurrentStyleDef()->m_NotesType, false );
if( pNotes == NULL )
continue; // skip
for( int i=0; i<min((int)vSongs.size(), MAX_TOTAL_CONTENTS); i++ )
{
Song* pSong = vSongs[i];
Notes* pNotes = vNotes[i];
CString sModifiers = vsModifiers[i];
LOG->Trace( "Adding song '%s'\n", pSong->m_sMainTitle.GetString() );
m_CourseContentDisplays[m_iNumContents].Load( m_iNumContents+1, pSong, pNotes );
+14
View File
@@ -174,6 +174,18 @@ inline int HoldNoteScoreToDancePoints( HoldNoteScore hns )
}
//
// MemCard stuff
//
enum MemoryCard
{
MEMORY_CARD_PLAYER_1,
MEMORY_CARD_PLAYER_2,
MEMORY_CARD_MACHINE,
NUM_MEMORY_CARDS
};
//
// Ranking stuff
//
@@ -186,6 +198,8 @@ enum RankingCategory
NUM_RANKING_CATEGORIES
};
const CString DEFAULT_RANKING_NAME = "STEP";
RankingCategory AverageMeterToRankingCategory( float fAverageMeter );
const int NUM_RANKING_LINES = 5;
+9
View File
@@ -199,6 +199,15 @@ RageColor GameState::GetStageColor()
else return STAGE_COLOR( min(m_iCurrentStageIndex,4) );
}
int GameState::GetCourseSongIndex()
{
int iSongIndex = 0;
for( int p=0; p<NUM_PLAYERS; p++ )
if( IsPlayerEnabled(p) )
iSongIndex = max( iSongIndex, m_CurStageStats.iSongsPassed[p] );
return iSongIndex;
}
GameDef* GameState::GetCurrentGameDef()
{
ASSERT( m_CurGame != GAME_INVALID ); // the game must be set before calling this
+2 -1
View File
@@ -69,7 +69,7 @@ public:
bool m_bEditing; // NoteField does special stuff when this is true
bool m_bDemonstration; // ScreenGameplay does special stuff when this is true
bool m_bJukeboxUsesModifiers;
int m_iCurrentStageIndex; // incremented on Eval screen
int m_iCurrentStageIndex; // incremented on Eval screen. For a Course, this is always 0
int GetStageIndex();
int GetNumStagesLeft();
@@ -78,6 +78,7 @@ public:
bool IsExtraStage2();
CString GetStageText();
RageColor GetStageColor();
int GetCourseSongIndex();
//
// State Info used during gameplay
+5 -7
View File
@@ -447,13 +447,11 @@ void MusicWheel::BuildWheelItemDatas( vector<WheelItemData> &arrayWheelItemDatas
Course* pCourse = apCourses[c];
// check that this course has at least one song playable in the current style
vector<Song*> apSongs;
vector<Notes*> apNotes;
CStringArray asModifiers;
pCourse->GetSongAndNotesForCurrentStyle( apSongs, apNotes, asModifiers, false );
if( !apNotes.empty() )
arrayWheelItemDatas.push_back( WheelItemData(TYPE_COURSE, NULL, "", pCourse, pCourse->GetColor()) );
Song* pSongs;
Notes* pNotes;
CString sModifiers;
if( pCourse->GetFirstStageInfo(pSongs, pNotes, sModifiers, GAMESTATE->GetCurrentStyleDef()->m_NotesType) )
arrayWheelItemDatas.push_back( WheelItemData(TYPE_COURSE, NULL, "", pCourse, pCourse->GetColor()) );
}
}
break;
+17 -7
View File
@@ -44,15 +44,15 @@ Notes::Notes()
for(int i = 0; i < NUM_RADAR_CATEGORIES; ++i)
m_fRadarValues[i] = -1; /* unknown */
m_iNumTimesPlayed = 0;
notes = NULL;
notes_comp = NULL;
parent = NULL;
for( int p=0; p<NUM_PLAYERS; p++ )
for( int m=0; m<NUM_MEMORY_CARDS; m++ )
{
m_MemCardScores[p].grade = GRADE_NO_DATA;
m_MemCardScores[p].fScore = 0;
m_MemCardScores[m].iNumTimesPlayed = 0;
m_MemCardScores[m].grade = GRADE_NO_DATA;
m_MemCardScores[m].fScore = 0;
}
}
@@ -332,13 +332,23 @@ void Notes::SetRadarValue(int r, float val)
m_fRadarValues[r] = val;
}
bool Notes::AddMemCardRecord( PlayerNumber pn, Grade grade, float fScore ) // return true if new high score
void Notes::AddScore( PlayerNumber pn, Grade grade, float fScore, bool& bNewRecordOut )
{
bNewRecordOut = false;
m_MemCardScores[MEMORY_CARD_MACHINE].iNumTimesPlayed++;
m_MemCardScores[pn].iNumTimesPlayed++;
if( fScore > m_MemCardScores[pn].fScore )
{
m_MemCardScores[pn].fScore = fScore;
m_MemCardScores[pn].grade = grade;
return true;
bNewRecordOut = true;
}
if( fScore > m_MemCardScores[MEMORY_CARD_MACHINE].fScore )
{
m_MemCardScores[MEMORY_CARD_MACHINE].fScore = fScore;
m_MemCardScores[MEMORY_CARD_MACHINE].grade = grade;
}
return false;
}
+4 -5
View File
@@ -54,16 +54,15 @@ public:
void CreateBlank( NotesType ntTo );
// High scores;
int m_iNumTimesPlayed;
// High scores
struct MemCardScore
{
int iNumTimesPlayed;
Grade grade;
float fScore;
} m_MemCardScores[NUM_PLAYERS];
} m_MemCardScores[NUM_MEMORY_CARDS];
bool AddMemCardRecord( PlayerNumber pn, Grade grade, float fScore ); // return true if new high score
void AddScore( PlayerNumber pn, Grade grade, float fScore, bool& bNewRecordOut );
void TidyUpData();
+20 -28
View File
@@ -247,36 +247,28 @@ ScreenEvaluation::ScreenEvaluation( bool bSummary )
//
// update persistent statistics
//
bool bNewRecord[NUM_PLAYERS];
memset( bNewRecord, 0, sizeof(bNewRecord) );
bool bIsPlayerEnabled[NUM_PLAYERS];
for( p=0; p<NUM_PLAYERS; p++ )
{
if( !GAMESTATE->IsPlayerEnabled(p) || grade[p] == GRADE_E )
continue; // can't be a new record
bIsPlayerEnabled[p] = GAMESTATE->IsPlayerEnabled(p);
int iRankingLine[NUM_PLAYERS] = { -1, -1 };
bool bNewRecord[NUM_PLAYERS] = { false, false };
switch( m_ResultMode )
{
case RM_ARCADE_STAGE:
{
Notes* pNotes = GAMESTATE->m_pCurNotes[p];
if( SONGMAN->IsUsingMemoryCard((PlayerNumber)p) )
bNewRecord[p] = pNotes->AddMemCardRecord( (PlayerNumber)p, grade[p], stageStats.fScore[p] );
}
break;
case RM_ARCADE_SUMMARY:
{
}
break;
case RM_COURSE:
{
Course* pCourse = GAMESTATE->m_pCurCourse;
NotesType nt = GAMESTATE->GetCurrentStyleDef()->m_NotesType;
pCourse->AddMemCardRecord( (PlayerNumber)p, nt, stageStats.iActualDancePoints[p], stageStats.fAliveSeconds[p] );
}
break;
default:
ASSERT(0);
}
switch( m_ResultMode )
{
case RM_ARCADE_STAGE:
for( int p=0; p<NUM_PLAYERS; p++ )
if( GAMESTATE->IsPlayerEnabled(p) )
GAMESTATE->m_pCurNotes[p]->AddScore( (PlayerNumber)p, grade[p], stageStats.fScore[p], bNewRecord[p] );
break;
case RM_ARCADE_SUMMARY:
break;
case RM_COURSE:
NotesType nt;
nt = GAMESTATE->GetCurrentStyleDef()->m_NotesType;
GAMESTATE->m_pCurCourse->AddScores( nt, bIsPlayerEnabled, stageStats.iActualDancePoints, stageStats.fAliveSeconds, iRankingLine, bNewRecord );
break;
default:
ASSERT(0);
}
m_bTryExtraStage =
+74 -101
View File
@@ -34,16 +34,16 @@
//
// Defines
//
#define SONGSEL_SCREEN THEME->GetMetric("ScreenGameplay","SongSelectScreen")
#define MAXCOMBO_X THEME->GetMetricF("ScreenGameplay","MAXCOMBOX")
#define MAXCOMBO_Y THEME->GetMetricF("ScreenGameplay","MAXCOMBOY")
#define MAXCOMBO_ZOOM THEME->GetMetricF("ScreenGameplay","MAXCOMBOZoom")
#define BPM_X THEME->GetMetricF("ScreenGameplay","BPMX")
#define BPM_Y THEME->GetMetricF("ScreenGameplay","BPMY")
#define BPM_ZOOM THEME->GetMetricF("ScreenGameplay","BPMZoom")
#define STAGENAME_X THEME->GetMetricF("ScreenGameplay","StagenameX")
#define STAGENAME_Y THEME->GetMetricF("ScreenGameplay","StagenameY")
#define STAGENAME_ZOOM THEME->GetMetricF("ScreenGameplay","StagenameZoom")
#define SONGSEL_SCREEN THEME->GetMetric("ScreenGameplay","SongSelectScreen")
#define MAXCOMBO_X THEME->GetMetricF("ScreenGameplay","MAXCOMBOX") // Please follow the capitalization conventions used everywhere else. This is case sensitive. -Chris
#define MAXCOMBO_Y THEME->GetMetricF("ScreenGameplay","MAXCOMBOY")
#define MAXCOMBO_ZOOM THEME->GetMetricF("ScreenGameplay","MAXCOMBOZoom")
#define BPM_X THEME->GetMetricF("ScreenGameplay","BPMX")
#define BPM_Y THEME->GetMetricF("ScreenGameplay","BPMY")
#define BPM_ZOOM THEME->GetMetricF("ScreenGameplay","BPMZoom")
#define STAGENAME_X THEME->GetMetricF("ScreenGameplay","StagenameX")
#define STAGENAME_Y THEME->GetMetricF("ScreenGameplay","StagenameY")
#define STAGENAME_ZOOM THEME->GetMetricF("ScreenGameplay","StagenameZoom")
#define LIFE_FRAME_X THEME->GetMetricF("ScreenGameplay","LifeFrameX")
#define LIFE_FRAME_Y( e ) THEME->GetMetricF("ScreenGameplay",ssprintf("LifeFrame%sY",e?"Extra":""))
#define SCORE_FRAME_X THEME->GetMetricF("ScreenGameplay","ScoreFrameX")
@@ -106,64 +106,64 @@ ScreenGameplay::ScreenGameplay( bool bDemonstration )
if( GAMESTATE->m_pCurSong == NULL && GAMESTATE->m_pCurCourse == NULL )
return; // ScreenDemonstration will move us to the next scren. We just need to survive for one update without crashing.
int p;
for( p=0; p<NUM_PLAYERS; p++ )
{
m_pLifeMeter[p] = NULL;
m_pScoreDisplay[p] = NULL;
for( int p=0; p<NUM_PLAYERS; p++ )
{
m_pLifeMeter[p] = NULL;
m_pScoreDisplay[p] = NULL;
}
}
g_fTickEarlySecondsCache = TICK_EARLY_SECONDS;
SOUNDMAN->StopMusic();
GAMESTATE->m_CurStageStats = StageStats(); // clear values
// Fill in m_CurStageStats
for( p=0; p<NUM_PLAYERS; p++ )
NoteData notedata;
switch( GAMESTATE->m_PlayMode )
{
if( !GAMESTATE->IsPlayerEnabled(p) )
continue; // skip
NoteData notedata;
switch( GAMESTATE->m_PlayMode )
case PLAY_MODE_ARCADE:
{
case PLAY_MODE_ARCADE:
GAMESTATE->m_CurStageStats.pSong = GAMESTATE->m_pCurSong;
GAMESTATE->m_CurStageStats.iMeter[p] = GAMESTATE->m_pCurNotes[p]->GetMeter();
GAMESTATE->m_pCurNotes[p]->GetNoteData( &notedata );
GAMESTATE->m_CurStageStats.iPossibleDancePoints[p] = notedata.GetPossibleDancePoints();
break;
case PLAY_MODE_NONSTOP:
case PLAY_MODE_ONI:
case PLAY_MODE_ENDLESS:
for( int p=0; p<NUM_PLAYERS; p++ )
{
GAMESTATE->m_CurStageStats.pSong = NULL;
GAMESTATE->m_CurStageStats.iMeter[p] = 0;
GAMESTATE->m_CurStageStats.iPossibleDancePoints[p] = 0;
Course* pCourse = GAMESTATE->m_pCurCourse;
vector<Song*> apSongs;
vector<Notes*> apNotes;
CStringArray asModifiers;
pCourse->GetSongAndNotesForCurrentStyle( apSongs, apNotes, asModifiers, true );
for( unsigned i=0; i<apNotes.size(); i++ )
{
GAMESTATE->m_CurStageStats.iMeter[p] += apNotes[i]->GetMeter();
apNotes[i]->GetNoteData( &notedata );
int iPossibleDancePoints = notedata.GetPossibleDancePoints();
GAMESTATE->m_CurStageStats.iPossibleDancePoints[p] += iPossibleDancePoints;
}
if( !GAMESTATE->IsPlayerEnabled(p) )
continue; // skip
GAMESTATE->m_CurStageStats.iMeter[p] = GAMESTATE->m_pCurNotes[p]->GetMeter();
GAMESTATE->m_pCurNotes[p]->GetNoteData( &notedata );
GAMESTATE->m_CurStageStats.iPossibleDancePoints[p] = notedata.GetPossibleDancePoints();
}
break;
default:
ASSERT(0);
}
break;
case PLAY_MODE_NONSTOP:
case PLAY_MODE_ONI:
case PLAY_MODE_ENDLESS:
{
Course* pCourse = GAMESTATE->m_pCurCourse;
pCourse->GetCourseInfo( m_apCourseSongs, m_apCourseNotes, m_asCourseModifiers, GAMESTATE->GetCurrentStyleDef()->m_NotesType, false );
int iTotalMeter = 0;
int iTotalPossibleDancePoints = 0;
for( unsigned i=0; i<m_apCourseNotes.size(); i++ )
{
iTotalMeter += m_apCourseNotes[i]->GetMeter();
m_apCourseNotes[i]->GetNoteData( &notedata );
iTotalPossibleDancePoints += notedata.GetPossibleDancePoints();
}
GAMESTATE->m_CurStageStats.pSong = NULL;
for( int p=0; p<NUM_PLAYERS; p++ )
{
if( !GAMESTATE->IsPlayerEnabled(p) )
continue; // skip
GAMESTATE->m_CurStageStats.iMeter[p] = iTotalMeter;
GAMESTATE->m_CurStageStats.iPossibleDancePoints[p] = iTotalPossibleDancePoints;
}
}
break;
default:
ASSERT(0);
}
@@ -187,7 +187,7 @@ ScreenGameplay::ScreenGameplay( bool bDemonstration )
this->AddChild( &m_Background );
for( p=0; p<NUM_PLAYERS; p++ )
for( int p=0; p<NUM_PLAYERS; p++ )
{
if( !GAMESTATE->IsPlayerEnabled(PlayerNumber(p)) )
continue;
@@ -495,23 +495,10 @@ bool ScreenGameplay::IsLastSong()
case PLAY_MODE_ENDLESS:
{
Course* pCourse = GAMESTATE->m_pCurCourse;
if( pCourse->m_bRepeat )
return false;
vector<Song*> apSongs;
vector<Notes*> apNotes;
CStringArray asModifiers;
pCourse->GetSongAndNotesForCurrentStyle( apSongs, apNotes, asModifiers, true );
/* XXX: Should we really be using iSongsPassed to figure out what song we're
* on? Wouldn't m_iCurrentStageIndex be better for that? -glenn */
int iPlaySongIndex = 0;
for( int p=0; p<NUM_PLAYERS; p++ )
if( GAMESTATE->IsPlayerEnabled(p) )
iPlaySongIndex = max( iPlaySongIndex, GAMESTATE->m_CurStageStats.iSongsPassed[p] );
return unsigned(iPlaySongIndex) >= apSongs.size(); // there are no more songs left
else
return GAMESTATE->GetCourseSongIndex() == (int)m_apCourseSongs.size();
}
break;
default:
@@ -540,31 +527,18 @@ void ScreenGameplay::LoadNextSong()
if( GAMESTATE->m_CurStageStats.iSongsPassed[p] == 0 )
GAMESTATE->m_SelectedOptions[p] = GAMESTATE->m_PlayerOptions[p];
}
Course* pCourse = GAMESTATE->m_pCurCourse;
vector<Song*> apSongs;
vector<Notes*> apNotes;
CStringArray asModifiers;
int iPlaySongIndex = GAMESTATE->GetCourseSongIndex();
iPlaySongIndex %= m_apCourseSongs.size();
GAMESTATE->m_pCurSong = m_apCourseSongs[iPlaySongIndex];
pCourse->GetSongAndNotesForCurrentStyle( apSongs, apNotes, asModifiers, true );
int iPlaySongIndex = 0;
for( p=0; p<NUM_PLAYERS; p++ )
if( GAMESTATE->IsPlayerEnabled(p) )
iPlaySongIndex = max( iPlaySongIndex, GAMESTATE->m_CurStageStats.iSongsPassed[p] );
iPlaySongIndex %= apSongs.size();
GAMESTATE->m_pCurSong = apSongs[iPlaySongIndex];
for( p=0; p<NUM_PLAYERS; p++ )
{
GAMESTATE->m_pCurNotes[p] = apNotes[iPlaySongIndex];
// Wipe the options used on the last song (including course specified ones)
GAMESTATE->m_PlayerOptions[p].Init();
// Now restore the player's originally selected options.
GAMESTATE->m_pCurNotes[p] = m_apCourseNotes[iPlaySongIndex];
// Restore the player's originally selected options.
GAMESTATE->m_PlayerOptions[p] = GAMESTATE->m_SelectedOptions[p];
if( asModifiers[iPlaySongIndex] != "" ) // some modifiers specified
GAMESTATE->m_PlayerOptions[p].FromString( asModifiers[iPlaySongIndex] ); // put them into effect
// Put courses options into effect.
GAMESTATE->m_PlayerOptions[p].FromString( m_asCourseModifiers[iPlaySongIndex] );
}
}
break;
default:
@@ -1070,7 +1044,7 @@ void SaveChanges()
* playing out of a course, and use that here, so these things wouldn't need to
* special case play modes. Need to make sure m_pCurCourse gets erased
* correctly, though. -glenn */
/* That's a very clever idea! I will look into this soon. -Chris */
/* That's a very clever idea! I should look into this. -Chris */
switch( GAMESTATE->m_PlayMode )
{
case PLAY_MODE_ARCADE:
@@ -1080,11 +1054,9 @@ void SaveChanges()
case PLAY_MODE_ONI:
case PLAY_MODE_ENDLESS:
{
for( int i=0; i<GAMESTATE->m_pCurCourse->GetNumStages(); i++ )
{
Song* pSong = GAMESTATE->m_pCurCourse->GetSong(i);
pSong->Save();
}
// FIXME
//for( int i=0; i<m_apCourseSongs.size(); i++ )
// m_apCourseSongs[i]->Save();
}
break;
default:
@@ -1105,11 +1077,12 @@ void DontSaveChanges()
case PLAY_MODE_ONI:
case PLAY_MODE_ENDLESS:
{
for( int i=0; i<GAMESTATE->m_pCurCourse->GetNumStages(); i++ )
{
Song* pSong = GAMESTATE->m_pCurCourse->GetSong(i);
ld.LoadFromSMFile( GAMESTATE->m_pCurSong->GetCacheFilePath(), *pSong );
}
// FIXME
// for( int i=0; i<GAMESTATE->m_pCurCourse->GetNumStages(); i++ )
// {
// Song* pSong = GAMESTATE->m_pCurCourse->GetSong(i);
// ld.LoadFromSMFile( GAMESTATE->m_pCurSong->GetCacheFilePath(), *pSong );
// }
}
break;
default:
+5 -2
View File
@@ -77,8 +77,11 @@ protected:
STATE_DANCING,
STATE_OUTRO, // not allowed to press Back
NUM_DANCING_STATES
};
DancingState m_DancingState;
} m_DancingState;
vector<Song*> m_apCourseSongs; // used only in a GameModes with courses
vector<Notes*> m_apCourseNotes; // used only in a GameModes with courses
CStringArray m_asCourseModifiers; // used only in a GameModes with courses
bool m_bChangedOffsetOrBPM;
float m_fTimeLeftBeforeDancingComment; // this counter is only running while STATE_DANCING
+1 -1
View File
@@ -49,7 +49,7 @@ ScreenLogo::ScreenLogo() : ScreenAttract("ScreenLogo","logo")
m_textSongs.LoadFromFont( THEME->GetPathTo("Fonts","normal") );
m_textSongs.SetHorizAlign( Actor::align_left );
m_textSongs.SetText( ssprintf("%d songs in %d groups", SONGMAN->GetNumSongs(), SONGMAN->GetNumGroups()) );
m_textSongs.SetText( ssprintf("%d songs in %d groups, %d courses", SONGMAN->GetNumSongs(), SONGMAN->GetNumGroups(), SONGMAN->GetNumCourses()) );
m_textSongs.SetDiffuse( RageColor(0.6f,0.6f,0.6f,1) ); // light gray
m_textSongs.SetXY( SONGS_X, SONGS_Y );
m_textSongs.SetZoom( 0.5f );
+8 -4
View File
@@ -163,17 +163,21 @@ ScreenNameEntry::ScreenNameEntry()
Course* pCourse = GAMESTATE->m_pCurCourse;
bool bPlayerIsEnabled[NUM_PLAYERS];
int iDancePoints[NUM_PLAYERS];
float fAliveSeconds[NUM_PLAYERS];
int iRankingIndex[NUM_PLAYERS];
for( int p=0; p<NUM_PLAYERS; p++ )
{
bPlayerIsEnabled[p] = GAMESTATE->IsPlayerEnabled(p);
iDancePoints[p] = stageStats.iActualDancePoints[p];
fAliveSeconds[p] = stageStats.fAliveSeconds[p];
}
int iRankingIndex[NUM_PLAYERS];
bool bNewRecord[NUM_PLAYERS];
NotesType nt = GAMESTATE->GetCurrentStyleDef()->m_NotesType;
pCourse->AddMachineRecords( nt, iDancePoints, fAliveSeconds, iRankingIndex );
pCourse->AddScores( nt, bPlayerIsEnabled, iDancePoints, fAliveSeconds, iRankingIndex, bNewRecord );
GAMESTATE->m_LastRankingNotesType = nt;
GAMESTATE->m_pLastPlayedCourse = pCourse;
@@ -409,7 +413,7 @@ void ScreenNameEntry::MenuStart( PlayerNumber pn )
TrimLeft( m_sSelectedName[pn], " " );
if( m_sSelectedName[pn] == "" )
m_sSelectedName[pn] = "STEP";
m_sSelectedName[pn] = DEFAULT_RANKING_NAME;
switch( GAMESTATE->m_PlayMode )
@@ -420,7 +424,7 @@ void ScreenNameEntry::MenuStart( PlayerNumber pn )
case PLAY_MODE_NONSTOP:
case PLAY_MODE_ONI:
case PLAY_MODE_ENDLESS:
GAMESTATE->m_pLastPlayedCourse->m_MachineScores[GAMESTATE->m_LastRankingNotesType][GAMESTATE->m_iLastRankingIndex[pn]].sName = m_sSelectedName[pn];
GAMESTATE->m_pLastPlayedCourse->m_RankingScores[GAMESTATE->m_LastRankingNotesType][GAMESTATE->m_iLastRankingIndex[pn]].sName = m_sSelectedName[pn];
break;
default:
ASSERT(0);
+3 -3
View File
@@ -236,9 +236,9 @@ void ScreenRanking::SetPage( PageToShow pts )
for( int l=0; l<NUM_RANKING_LINES; l++ )
{
m_sprBullets[l].SetDiffuse( RageColor(1,1,1,1) );
CString sName = pts.pCourse->m_MachineScores[pts.nt][l].sName;
int iDancePoints = pts.pCourse->m_MachineScores[pts.nt][l].iDancePoints;
float fSurviveTime = pts.pCourse->m_MachineScores[pts.nt][l].fSurviveTime;
CString sName = pts.pCourse->m_RankingScores[pts.nt][l].sName;
int iDancePoints = pts.pCourse->m_RankingScores[pts.nt][l].iDancePoints;
float fSurviveTime = pts.pCourse->m_RankingScores[pts.nt][l].fSurviveTime;
m_textNames[l].SetText( sName );
m_textScores[l].SetText( "" );
m_textPoints[l].SetText( ssprintf("%04d",iDancePoints) );
+12 -7
View File
@@ -299,9 +299,13 @@ void ScreenSelectCourse::MenuStart( PlayerNumber pn )
Course* pCourse = m_MusicWheel.GetSelectedCourse();
GAMESTATE->m_pCurCourse = pCourse;
Song* pSong;
Notes* pNotes;
CString sModifiers;
pCourse->GetFirstStageInfo( pSong, pNotes, sModifiers, GAMESTATE->GetCurrentStyleDef()->m_NotesType );
for( int p=0; p<NUM_PLAYERS; p++ )
pCourse->GetPlayerOptions( 0, &GAMESTATE->m_PlayerOptions[p] );
pCourse->GetSongOptions( &GAMESTATE->m_SongOptions );
GAMESTATE->m_PlayerOptions[p].FromString( sModifiers );
GAMESTATE->m_SongOptions.FromString( sModifiers );
m_Menu.StopTimer();
@@ -328,11 +332,12 @@ void ScreenSelectCourse::AfterCourseChange()
{
Course* pCourse = m_MusicWheel.GetSelectedCourse();
m_textNumSongs.SetText( ssprintf("%d", pCourse->GetNumStages()) );
float fTotalSeconds = 0;
for( int i=0; i<pCourse->GetNumStages(); i++ )
fTotalSeconds += pCourse->GetSong(i)->m_fMusicLengthSeconds;
m_textTime.SetText( SecondsToTime(fTotalSeconds) );
m_textNumSongs.SetText( ssprintf("%d", pCourse->GetEstimatedNumStages()) );
float fTotalSeconds;
if( pCourse->GetTotalSeconds(fTotalSeconds) )
m_textTime.SetText( SecondsToTime(fTotalSeconds) );
else
m_textTime.SetText( "??:??:??" );
m_Banner.LoadFromCourse( pCourse );
+4 -3
View File
@@ -635,12 +635,13 @@ void Song::GetNotes( vector<Notes*>& arrayAddTo, NotesType nt, bool bIncludeAuto
arrayAddTo.push_back( m_apNotes[i] );
}
Notes* Song::GetNotes( NotesType nt, Difficulty dc, bool bIncludeAutoGen ) const
Notes* Song::GetNotes( NotesType nt, Difficulty dc, bool bIncludeAutoGen, CString sDescription ) const
{
for( unsigned i=0; i<m_apNotes.size(); i++ ) // for each of the Song's Notes
if( m_apNotes[i]->m_NotesType==nt && m_apNotes[i]->GetDifficulty()==dc )
if( bIncludeAutoGen || !m_apNotes[i]->IsAutogen() )
return m_apNotes[i];
if( sDescription.empty() || m_apNotes[i]->GetDescription()==sDescription )
return m_apNotes[i];
return NULL;
}
@@ -1008,7 +1009,7 @@ int Song::GetNumTimesPlayed() const
int iTotalNumTimesPlayed = 0;
for( unsigned i=0; i<m_apNotes.size(); i++ )
{
iTotalNumTimesPlayed += m_apNotes[i]->m_iNumTimesPlayed;
iTotalNumTimesPlayed += m_apNotes[i]->m_MemCardScores[MEMORY_CARD_MACHINE].iNumTimesPlayed;
}
return iTotalNumTimesPlayed;
}
+251 -64
View File
@@ -28,10 +28,14 @@
SongManager* SONGMAN = NULL; // global and accessable from anywhere in our program
const CString CATEGORY_TOP_SCORE_FILE = "CategoryTopScores.dat";
const CString COURSE_TOP_SCORE_FILE = "CourseTopScores.dat";
const int CATEGORY_TOP_SCORE_VERSION = 1;
const int COURSE_TOP_SCORE_VERSION = 1;
const CString CATEGORY_RANKING_FILE = "CategoryRanking.dat";
const CString COURSE_RANKING_FILE = "CourseRanking.dat";
const CString NOTES_SCORES_FILE[NUM_MEMORY_CARDS] = { "Player1NotesScores.dat", "Player2NotesScores.dat", "MachineNotesScores.dat" };
const CString COURSE_SCORES_FILE[NUM_MEMORY_CARDS] = { "Player1CourseScores.dat", "Player2CourseScores.dat", "MachineCourseScores.dat" };
const int CATEGORY_RANKING_VERSION = 1;
const int COURSE_RANKING_VERSION = 1;
const int NOTES_SCORES_VERSION = 1;
const int COURSE_SCORES_VERSION = 1;
#define NUM_GROUP_COLORS THEME->GetMetricI("SongManager","NumGroupColors")
@@ -211,25 +215,25 @@ void SongManager::ReloadSongArray()
void SongManager::InitMachineScoresFromDisk()
{
// Init category top scores
// Init category ranking
{
for( int i=0; i<NUM_NOTES_TYPES; i++ )
for( int j=0; j<NUM_RANKING_CATEGORIES; j++ )
for( int k=0; k<NUM_RANKING_LINES; k++ )
{
m_MachineScores[i][j][k].fScore = 573000;
m_MachineScores[i][j][k].sName = "STEP";
m_MachineScores[i][j][k].sName = DEFAULT_RANKING_NAME;
}
}
// Read category top scores
// category ranking
{
FILE* fp = fopen( CATEGORY_TOP_SCORE_FILE, "r" );
FILE* fp = fopen( CATEGORY_RANKING_FILE, "r" );
if( fp )
{
int version;
fscanf(fp, "%d\n", &version );
if( version == CATEGORY_TOP_SCORE_VERSION )
if( version == CATEGORY_RANKING_VERSION )
{
for( int i=0; i<NUM_NOTES_TYPES; i++ )
for( int j=0; j<NUM_RANKING_CATEGORIES; j++ )
@@ -245,52 +249,137 @@ void SongManager::InitMachineScoresFromDisk()
}
}
// Read course top scores
// course ranking
{
FILE* fp = fopen( COURSE_TOP_SCORE_FILE, "r" );
FILE* fp = fopen( COURSE_RANKING_FILE, "r" );
if( fp )
{
int version;
fscanf(fp, "%d\n", &version );
if( version == COURSE_TOP_SCORE_VERSION )
fscanf(fp, "%[^\n]\n", &version );
if( version == COURSE_RANKING_VERSION )
{
while( fp && !feof(fp) )
{
char szPath[256];
fscanf(fp, "%s\n", szPath);
Course* pCourse = GetCourseFromPath( szPath );
char szPath[256];
fscanf(fp, "%s\n", szPath);
Course* pCourse = GetCourseFromPath( szPath );
if( pCourse == NULL )
pCourse = GetCourseFromName( szPath );
for( int i=0; i<NUM_NOTES_TYPES; i++ )
for( int j=0; j<NUM_RANKING_LINES; j++ )
if( fp && !feof(fp) )
for( int j=0; j<NUM_RANKING_LINES; j++ )
if( fp && !feof(fp) )
{
int iDancePoints;
float fSurviveTime;
char szName[256];
fscanf(fp, "%d %f %[^\n]\n", &iDancePoints, &fSurviveTime, szName);
if( pCourse )
{
int iDancePoints;
float fSurviveTime;
char szName[256];
fscanf(fp, "%d %f %[^\n]\n", &iDancePoints, &fSurviveTime, szName);
if( pCourse )
{
pCourse->m_MachineScores[i][j].iDancePoints = iDancePoints;
pCourse->m_MachineScores[i][j].fSurviveTime = fSurviveTime;
pCourse->m_MachineScores[i][j].sName = szName;
}
pCourse->m_RankingScores[i][j].iDancePoints = iDancePoints;
pCourse->m_RankingScores[i][j].fSurviveTime = fSurviveTime;
pCourse->m_RankingScores[i][j].sName = szName;
}
}
}
}
fclose(fp);
}
}
// notes scores
for( int c=0; c<NUM_MEMORY_CARDS; c++ )
{
FILE* fp = fopen( NOTES_SCORES_FILE[c], "r" );
if( fp )
{
int version;
fscanf(fp, "%d\n", &version );
if( version == COURSE_SCORES_VERSION )
{
while( fp && !feof(fp) )
{
char szSongDir[256];
unsigned uNumNotes;
fscanf(fp, "%[^\n]\n%u\n", szSongDir, &uNumNotes);
Song* pSong = this->GetSongFromDir( szSongDir );
for( unsigned i=0; i<uNumNotes; i++ )
{
NotesType nt;
Difficulty dc;
char szDescription[256];
fscanf(fp, "[%d\n%d\n%[^\n]\n", &nt, &dc, szDescription);
Notes* pNotes = !pSong ? NULL : pSong->GetNotes( nt, dc, true, szDescription );
int iNumTimesPlayed;
Grade grade;
float fScore;
fscanf(fp, "%d %d %f\n", &iNumTimesPlayed, &grade, &fScore );
if( pNotes )
{
pNotes->m_MemCardScores[c].iNumTimesPlayed = iNumTimesPlayed;
pNotes->m_MemCardScores[c].grade = grade;
pNotes->m_MemCardScores[c].fScore = fScore;
}
}
}
}
fclose(fp);
}
}
// course scores
{
for( int c=0; c<NUM_MEMORY_CARDS; c++ )
{
FILE* fp = fopen( COURSE_SCORES_FILE[c], "r" );
if( fp )
{
int version;
fscanf(fp, "%d\n", &version );
if( version == COURSE_SCORES_VERSION )
{
while( fp && !feof(fp) )
{
char szPath[256];
fscanf(fp, "%[^\n]\n", szPath);
Course* pCourse = GetCourseFromPath( szPath );
if( pCourse == NULL )
pCourse = GetCourseFromName( szPath );
for( int i=0; i<NUM_NOTES_TYPES; i++ )
if( fp && !feof(fp) )
{
int iNumTimesPlayed;
int iDancePoints;
float fSurviveTime;
fscanf(fp, "%d %d %f\n", &iNumTimesPlayed, &iDancePoints, &fSurviveTime);
if( pCourse )
{
pCourse->m_MemCardScores[c][i].iNumTimesPlayed = iNumTimesPlayed;
pCourse->m_MemCardScores[c][i].iDancePoints = iDancePoints;
pCourse->m_MemCardScores[c][i].fSurviveTime = fSurviveTime;
}
}
}
}
fclose(fp);
}
}
}
}
void SongManager::SaveMachineScoresToDisk()
{
// Write category top scores
// category ranking
{
FILE* fp = fopen( CATEGORY_TOP_SCORE_FILE, "w" );
FILE* fp = fopen( CATEGORY_RANKING_FILE, "w" );
if( fp )
{
fprintf(fp,"%d\n",CATEGORY_TOP_SCORE_VERSION);
fprintf(fp,"%d\n",CATEGORY_RANKING_VERSION);
for( int i=0; i<NUM_NOTES_TYPES; i++ )
for( int j=0; j<NUM_RANKING_CATEGORIES; j++ )
for( int k=0; k<NUM_RANKING_LINES; k++ )
@@ -300,30 +389,100 @@ void SongManager::SaveMachineScoresToDisk()
}
}
// Write course top scores
// course ranking
{
FILE* fp = fopen( COURSE_TOP_SCORE_FILE, "w" );
FILE* fp = fopen( COURSE_RANKING_FILE, "w" );
if( fp )
{
fprintf(fp,"%d",COURSE_TOP_SCORE_VERSION);
for( unsigned i=0; i<m_pCourses.size(); i++ ) // foreach course
fprintf(fp,"%d\n",COURSE_RANKING_VERSION);
for( unsigned c=0; c<m_pCourses.size(); c++ ) // foreach course
{
Course* pCourse = m_pCourses[i];
fprintf(fp, "%s\n", pCourse->m_sPath.c_str());
Course* pCourse = m_pCourses[c];
if( pCourse->m_bIsAutoGen )
fprintf(fp, "%s\n", pCourse->m_sName.c_str());
else
fprintf(fp, "%s\n", pCourse->m_sPath.c_str());
for( int i=0; i<NUM_NOTES_TYPES; i++ )
for( int j=0; j<NUM_RANKING_LINES; j++ )
fprintf(fp, "%d %f %s\n",
pCourse->m_MachineScores[i][j].iDancePoints,
pCourse->m_MachineScores[i][j].fSurviveTime,
pCourse->m_MachineScores[i][j].sName.c_str());
pCourse->m_RankingScores[i][j].iDancePoints,
pCourse->m_RankingScores[i][j].fSurviveTime,
pCourse->m_RankingScores[i][j].sName.c_str());
}
fclose(fp);
}
}
// notes scores
for( int c=0; c<NUM_MEMORY_CARDS; c++ )
{
FILE* fp = fopen( NOTES_SCORES_FILE[c], "w" );
if( fp )
{
fprintf(fp,"%d\n",NOTES_SCORES_VERSION);
for( unsigned s=0; s<m_pSongs.size(); s++ ) // foreach song
{
Song* pSong = m_pSongs[s];
vector<Notes*> vNotes = pSong->m_apNotes;
for( int n=(int)vNotes.size()-1; n>=0; n-- )
if( vNotes[n]->m_MemCardScores[c].grade <= GRADE_E )
vNotes.erase( vNotes.begin()+n );
if( vNotes.size() == 0 )
continue; // skip
fprintf(fp, "%s\n%u\n",
pSong->GetSongDir().c_str(),
vNotes.size() );
for( unsigned i=0; i<vNotes.size(); i++ )
{
Notes* pNotes = vNotes[i];
fprintf(fp, "%d\n%d\n%s\n",
pNotes->m_NotesType,
pNotes->GetDifficulty(),
pNotes->GetDescription().c_str() );
fprintf(fp, "%d %d %f\n",
pNotes->m_MemCardScores[c].iNumTimesPlayed,
pNotes->m_MemCardScores[c].grade,
pNotes->m_MemCardScores[c].fScore);
}
}
fclose(fp);
}
}
// course scores
{
for( int c=0; c<NUM_MEMORY_CARDS; c++ )
{
FILE* fp = fopen( COURSE_SCORES_FILE[c], "w" );
if( fp )
{
fprintf(fp,"%d\n",COURSE_SCORES_VERSION);
for( unsigned c=0; c<m_pCourses.size(); c++ ) // foreach song
{
Course* pCourse = m_pCourses[c];
if( pCourse->m_bIsAutoGen )
fprintf(fp, "%s\n", pCourse->m_sName.c_str());
else
fprintf(fp, "%s\n", pCourse->m_sPath.c_str());
for( int i=0; i<NUM_NOTES_TYPES; i++ )
fprintf(fp, "%d %d %f\n",
pCourse->m_MemCardScores[c][i].iNumTimesPlayed,
pCourse->m_MemCardScores[c][i].iDancePoints,
pCourse->m_MemCardScores[c][i].fSurviveTime);
}
fclose(fp);
}
}
if( fp )
fclose(fp);
}
}
@@ -392,6 +551,11 @@ int SongManager::GetNumGroups() const
return m_arrayGroupNames.size();
}
int SongManager::GetNumCourses() const
{
return m_pCourses.size();
}
CString SongManager::ShortenGroupName( CString sLongGroupName )
{
sLongGroupName.Replace( "Dance Dance Revolution", "DDR" );
@@ -434,10 +598,7 @@ void SongManager::InitCoursesFromDisk()
{
Course* pCourse = new Course;
pCourse->LoadFromCRSFile( saCourseFiles[i] );
if( pCourse->GetNumStages() > 0 )
m_pCourses.push_back( pCourse );
else
delete pCourse;
m_pCourses.push_back( pCourse );
}
//
@@ -455,12 +616,9 @@ void SongManager::InitCoursesFromDisk()
for( Difficulty dc=DIFFICULTY_EASY; dc<=DIFFICULTY_HARD; dc=Difficulty(dc+1) ) // foreach Difficulty
{
Course* pCourse = new Course;
pCourse->CreateEndlessCourseFromGroupAndDifficulty( sGroupName, dc, apGroupSongs );
pCourse->AutoGenEndlessFromGroupAndDifficulty( sGroupName, dc, apGroupSongs );
if( pCourse->GetNumStages() > 0 )
m_pCourses.push_back( pCourse );
else
delete pCourse;
m_pCourses.push_back( pCourse );
}
}
}
@@ -556,16 +714,17 @@ bool SongManager::GetExtraStageInfoFromCourse( bool bExtra2, CString sPreferredG
Course course;
course.LoadFromCRSFile( sCoursePath );
if( course.GetNumStages() <= 0 ) return false;
if( course.GetEstimatedNumStages() <= 0 ) return false;
pSongOut = course.GetSong(0);
pNotesOut = course.GetNotesForStage( 0 );
if( pNotesOut == NULL ) return false;
course.GetPlayerOptions( 0, &po_out );
course.GetSongOptions( &so_out );
return true;
CString sModifiers;
if( course.GetFirstStageInfo( pSongOut, pNotesOut, sModifiers, GAMESTATE->GetCurrentStyleDef()->m_NotesType ) )
{
po_out.FromString( sModifiers );
so_out.FromString( sModifiers );
return true;
}
else
return false;
}
/* Return true if n1 < n2. */
@@ -670,6 +829,24 @@ Song* SongManager::GetRandomSong()
return SONGMAN->m_pSongs[ rand()%m_pSongs.size() ];
}
Song* SongManager::GetPlayersBest( int index )
{
vector<Song*> vSongs = m_pSongs;
if( (unsigned)index >= vSongs.size() )
return NULL;
SortSongPointerArrayByMostPlayed( vSongs );
return vSongs[index];
}
Song* SongManager::GetPlayersWorst( int index )
{
vector<Song*> vSongs = m_pSongs;
if( (unsigned)index >= vSongs.size() )
return NULL;
SortSongPointerArrayByMostPlayed( vSongs );
return vSongs[vSongs.size()-1-index];
}
Song* SongManager::GetSongFromDir( CString sDir )
{
if( sDir[sDir.GetLength()-1] != '/' )
@@ -691,6 +868,16 @@ Course* SongManager::GetCourseFromPath( CString sPath )
return NULL;
}
Course* SongManager::GetCourseFromName( CString sName )
{
for( unsigned int i=0; i<m_pCourses.size(); i++ )
if( sName.CompareNoCase(m_pCourses[i]->m_sName) == 0 )
return m_pCourses[i];
return NULL;
}
bool SongManager::IsUsingMemoryCard( PlayerNumber pn )
{
return true;
@@ -749,7 +936,7 @@ void SongManager::AddMachineRecords( NotesType nt, RankingCategory hsc[NUM_PLAYE
machineScores[j] = machineScores[j-1];
// insert
machineScores[i].fScore = newHS.fScore;
machineScores[i].sName = "STEP";
machineScores[i].sName = DEFAULT_RANKING_NAME;
iNewRecordIndexOut[newHS.pn] = i;
break;
}
+5
View File
@@ -58,7 +58,11 @@ public:
void GetSongs( vector<Song*> &AddTo ) const { GetSongs(AddTo,"",100000 /*inf*/ ); }
int GetNumSongs() const;
int GetNumGroups() const;
int GetNumCourses() const;
Song* GetRandomSong();
Song* GetPlayersBest( int index );
Song* GetPlayersWorst( int index );
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.
@@ -69,6 +73,7 @@ public:
Song* GetSongFromDir( CString sDir );
Course* GetCourseFromPath( CString sPath ); // path to .crs file, or path to song group dir
Course* GetCourseFromName( CString sName );
//
+1 -1
View File
@@ -206,7 +206,7 @@ public:
bool SongHasNotesType( NotesType nt ) const;
bool SongHasNotesTypeAndDifficulty( NotesType nt, Difficulty dc ) const;
void GetNotes( vector<Notes*>& arrayAddTo, NotesType nt, bool bIncludeAutoGen = true ) const;
Notes* GetNotes( NotesType nt, Difficulty dc, bool bIncludeAutoGen = true ) const;
Notes* GetNotes( NotesType nt, Difficulty dc, bool bIncludeAutoGen = true, CString sDescription = "" ) const;
void GetEdits( vector<Notes*>& arrayAddTo, NotesType nt, bool bIncludeAutoGen = true ) const;
int GetNumTimesPlayed() const;
bool IsNew() const;