cleanup of statistics, saving of high scores

This commit is contained in:
Chris Danford
2003-01-24 02:43:07 +00:00
parent c187098400
commit cf8c4f884f
25 changed files with 611 additions and 503 deletions
+2
View File
@@ -2,6 +2,8 @@
Fix Fix
///////////////////////// /////////////////////////
change space so gray arrows aren't so small
groove radar goes wild when random selected groove radar goes wild when random selected
take out "it's a new record" take out "it's a new record"
+82 -2
View File
@@ -50,7 +50,6 @@ Course::Course()
{ {
m_MemCardScores[i][j][k].iDancePoints = 0; m_MemCardScores[i][j][k].iDancePoints = 0;
m_MemCardScores[i][j][k].fSurviveTime = 0; m_MemCardScores[i][j][k].fSurviveTime = 0;
m_MemCardScores[i][j][k].sName = "STEP";
} }
} }
@@ -302,10 +301,91 @@ int Course::GetNumStages() const
return entries.size(); return entries.size();
} }
bool Course::IsNewMachineRecord( PlayerNumber pn, int iDancePoints, float fSurviveTime ) const // return true if this would be a new machine record
{
for( int i=0; i<NUM_HIGH_SCORE_LINES; i++ )
{
const MachineScore& hs = m_MachineScores[GAMESTATE->m_CurStyle][GAMESTATE->m_PreferredDifficulty[pn]][i];
if( iDancePoints > hs.iDancePoints )
return true;
}
return false;
}
struct MachineScoreAndPlayerNumber : public Course::MachineScore
{
PlayerNumber pn;
static int CompareDescending( const MachineScoreAndPlayerNumber &hs1, const MachineScoreAndPlayerNumber &hs2 )
{
if( hs1.iDancePoints > hs2.iDancePoints ) return -1;
else if( hs1.iDancePoints == hs2.iDancePoints ) return 0;
else return +1;
}
static void SortDescending( vector<MachineScoreAndPlayerNumber>& vHSout )
{
sort( vHSout.begin(), vHSout.end(), CompareDescending );
}
};
void Course::AddMachineRecord( int iDancePoints[NUM_PLAYERS], float fSurviveTime[NUM_PLAYERS], int iNewRecordIndexOut[NUM_PLAYERS] ) // set iNewRecordIndex = -1 if not a new record
{
vector<MachineScoreAndPlayerNumber> vHS;
for( int p=0; p<NUM_PLAYERS; p++ )
{
iNewRecordIndexOut[p] = -1;
if( !GAMESTATE->IsPlayerEnabled(p) )
continue; // skip
MachineScoreAndPlayerNumber hs;
hs.iDancePoints = iDancePoints[p];
hs.fSurviveTime = fSurviveTime[p];
hs.sName = ""; // this must be filled in later!
hs.pn = (PlayerNumber)p;
vHS.push_back( hs );
}
// 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
MachineScoreAndPlayerNumber::SortDescending( vHS );
for( unsigned i=0; i<vHS.size(); i++ )
{
MachineScoreAndPlayerNumber& newHS = vHS[i];
MachineScore* machineScores = m_MachineScores[GAMESTATE->m_CurStyle][GAMESTATE->m_PreferredDifficulty[newHS.pn]];
for( int i=0; i<NUM_HIGH_SCORE_LINES; i++ )
{
if( newHS.iDancePoints > machineScores[i].iDancePoints )
{
// We found the insert point. Shift down.
for( int j=i+1; j<NUM_HIGH_SCORE_LINES; j++ )
machineScores[j] = machineScores[j-1];
// insert
machineScores[i] = newHS;
iNewRecordIndexOut[newHS.pn] = i;
}
}
}
}
bool Course::AddMemCardRecord( PlayerNumber pn, int iDancePoints, float fSurviveTime ) // return true if new record
{
MemCardScore& hs = m_MemCardScores[GAMESTATE->m_CurStyle][GAMESTATE->m_PreferredDifficulty[pn]][pn];
if( iDancePoints > hs.iDancePoints )
{
hs.iDancePoints = iDancePoints;
hs.fSurviveTime = fSurviveTime;
return true;
}
return false;
}
// //
// Sorting stuff // Sorting stuff
// //
static int CompareCoursePointersByDifficulty(const Course* pCourse1, const Course* pCourse2) static int CompareCoursePointersByDifficulty(const Course* pCourse1, const Course* pCourse2)
{ {
return pCourse1->GetNumStages() < pCourse2->GetNumStages(); return pCourse1->GetNumStages() < pCourse2->GetNumStages();
+14 -4
View File
@@ -60,14 +60,24 @@ public:
// Statistics // Statistics
int m_iNumTimesPlayed; int m_iNumTimesPlayed;
struct HighScore struct MachineScore
{ {
int iDancePoints; int iDancePoints;
float fSurviveTime; float fSurviveTime;
CString sName; CString sName;
}; } m_MachineScores[NUM_STYLES][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_STYLES][NUM_DIFFICULTIES][NUM_PLAYERS]; bool IsNewMachineRecord( PlayerNumber pn, int iDancePoints, float fSurviveTime ) const; // return true if this is would be a new machine record
void AddMachineRecord( int iDancePoints[NUM_PLAYERS], float fSurviveTime[NUM_PLAYERS], int iNewRecordIndexOut[NUM_PLAYERS] ); // set iNewRecordIndex = -1 if not a new record
struct MemCardScore
{
int iDancePoints;
float fSurviveTime;
} m_MemCardScores[NUM_STYLES][NUM_DIFFICULTIES][NUM_PLAYERS];
bool AddMemCardRecord( PlayerNumber pn, int iDancePoints, float fSurviveTime ); // return true if this is a new record
private: private:
void Shuffle(); void Shuffle();
+12
View File
@@ -55,3 +55,15 @@ RageColor PlayerToColor( int p )
{ {
return PlayerToColor( (PlayerNumber)p ); return PlayerToColor( (PlayerNumber)p );
} }
HighScoreCategory AverageMeterToHighScoreCategory( float fAverageMeter )
{
if( fAverageMeter <= 3 ) return CATEGORY_A;
else if( fAverageMeter <= 6 ) return CATEGORY_B;
else if( fAverageMeter <= 9 ) return CATEGORY_C;
else return CATEGORY_D;
}
+8 -5
View File
@@ -116,9 +116,9 @@ enum SongSortOrder {
}; };
/////////////////////////// //
// Scoring stuff // Scoring stuff
/////////////////////////// //
enum TapNoteScore { enum TapNoteScore {
TNS_NONE, TNS_NONE,
@@ -174,16 +174,19 @@ inline int HoldNoteScoreToDancePoints( HoldNoteScore hns )
// //
// High Score types // High Score stuff
// //
enum SongHighScoreCategory enum HighScoreCategory
{ {
CATEGORY_A, // 1-3 meter per song avg. CATEGORY_A, // 1-3 meter per song avg.
CATEGORY_B, // 4-6 meter per song avg. CATEGORY_B, // 4-6 meter per song avg.
CATEGORY_C, // 7-9 meter per song avg. CATEGORY_C, // 7-9 meter per song avg.
CATEGORY_D, // 10+ meter per song avg. CATEGORY_D, // 10+ meter per song avg. // doesn't count extra stage!
NUM_HIGH_SCORE_CATEGORIES NUM_HIGH_SCORE_CATEGORIES
}; };
HighScoreCategory AverageMeterToHighScoreCategory( float fAverageMeter );
const int NUM_HIGH_SCORE_LINES = 5; const int NUM_HIGH_SCORE_LINES = 5;
#endif #endif
+31 -151
View File
@@ -67,68 +67,18 @@ void GameState::Reset()
m_bDemonstration = false; m_bDemonstration = false;
m_iCurrentStageIndex = 0; m_iCurrentStageIndex = 0;
m_pCurSong = NULL; m_pCurSong = NULL;
for( p=0; p<NUM_PLAYERS; p++ ) for( p=0; p<NUM_PLAYERS; p++ )
m_pCurNotes[p] = NULL; m_pCurNotes[p] = NULL;
m_pCurCourse = NULL; m_pCurCourse = NULL;
m_fMusicSeconds = 0; m_fMusicSeconds = 0;
m_fSongBeat = 0; m_fSongBeat = 0;
m_fCurBPS = 0; m_fCurBPS = 0;
m_bFreeze = 0; m_bFreeze = 0;
m_CurStageStats = StageStats();
m_apSongsPlayed.clear(); m_vPassedStageStats.clear();
m_iSongsIntoCourse = 0;
for( p=0; p<NUM_PLAYERS; p++ )
{
m_fSecondsBeforeFail[p] = -1;
m_iSongsBeforeFail[p] = 0;
}
for( p=0; p<NUM_PLAYERS; p++ )
{
int s;
m_iPossibleDancePoints[p] = 0;
m_iActualDancePoints[p] = 0;
for( s=0; s<NUM_TAP_NOTE_SCORES; s++ )
m_TapNoteScores[p][s] = 0;
for( s=0; s<NUM_HOLD_NOTE_SCORES; s++ )
m_HoldNoteScores[p][s] = 0;
m_iMaxCombo[p] = 0;
m_fScore[p] = 0;
for( int r=0; r<NUM_RADAR_VALUES; r++ )
{
m_fRadarPossible[p][r] = 0;
m_fRadarActual[p][r] = 0;
}
}
for( p=0; p<NUM_PLAYERS; p++ )
{
int s;
m_iAccumPossibleDancePoints[p] = 0;
m_iAccumActualDancePoints[p] = 0;
for( s=0; s<NUM_TAP_NOTE_SCORES; s++ )
m_AccumTapNoteScores[p][s] = 0;
for( s=0; s<NUM_HOLD_NOTE_SCORES; s++ )
m_AccumHoldNoteScores[p][s] = 0;
m_iAccumMaxCombo[p] = 0;
m_fAccumScore[p] = 0;
for( int r=0; r<NUM_RADAR_VALUES; r++ )
{
m_fAccumRadarPossible[p][r] = 0;
m_fAccumRadarActual[p][r] = 0;
}
}
for( p=0; p<NUM_PLAYERS; p++ ) for( p=0; p<NUM_PLAYERS; p++ )
m_PlayerOptions[p] = PlayerOptions(); m_PlayerOptions[p] = PlayerOptions();
@@ -143,65 +93,6 @@ void GameState::ResetMusicStatistics()
m_bFreeze = false; m_bFreeze = false;
} }
void GameState::AccumulateStageStatistics()
{
for( int p=0; p<NUM_PLAYERS; p++ )
{
int s;
m_iAccumPossibleDancePoints[p] += m_iPossibleDancePoints[p];
m_iAccumActualDancePoints[p] += m_iActualDancePoints[p];
for( s=0; s<NUM_TAP_NOTE_SCORES; s++ )
m_AccumTapNoteScores[p][s] += m_TapNoteScores[p][s];
for( s=0; s<NUM_HOLD_NOTE_SCORES; s++ )
m_AccumHoldNoteScores[p][s] += m_HoldNoteScores[p][s];
m_iAccumMaxCombo[p] += m_iMaxCombo[p];
m_fAccumScore[p] += m_fScore[p];
for( int r=0; r<NUM_RADAR_VALUES; r++ )
{
m_fAccumRadarPossible[p][r] = m_fRadarPossible[p][r];
m_fAccumRadarActual[p][r] = m_fRadarActual[p][r];
}
}
}
void GameState::ResetStageStatistics()
{
m_iSongsIntoCourse = 0;
switch( m_PlayMode )
{
case PLAY_MODE_NONSTOP:
case PLAY_MODE_ONI:
case PLAY_MODE_ENDLESS:
m_apSongsPlayed.clear();
break;
}
for( int p=0; p<NUM_PLAYERS; p++ )
{
int s;
m_iSongsBeforeFail[p] = 0;
m_fSecondsBeforeFail[p] = -1;
m_iPossibleDancePoints[p] = 0;
m_iActualDancePoints[p] = 0;
for( s=0; s<NUM_TAP_NOTE_SCORES; s++ )
m_TapNoteScores[p][s] = 0;
for( s=0; s<NUM_HOLD_NOTE_SCORES; s++ )
m_HoldNoteScores[p][s] = 0;
m_iMaxCombo[p] = 0;
m_fScore[p] = 0;
for( int r=0; r<NUM_RADAR_VALUES; r++ )
{
m_fRadarPossible[p][r] = 0;
m_fRadarActual[p][r] = 0;
}
}
}
int GameState::GetStageIndex() int GameState::GetStageIndex()
{ {
return m_iCurrentStageIndex; return m_iCurrentStageIndex;
@@ -299,38 +190,11 @@ bool GameState::IsPlayerEnabled( PlayerNumber pn )
} }
} }
float GameState::GetElapsedSeconds()
{
switch( m_PlayMode )
{
case PLAY_MODE_ARCADE:
return max( 0, m_fMusicSeconds );
case PLAY_MODE_ONI:
case PLAY_MODE_ENDLESS:
{
float fSecondsTotal = 0;
for( unsigned i=0; i<m_apSongsPlayed.size(); i++ )
fSecondsTotal += m_apSongsPlayed[i]->m_fMusicLengthSeconds;
fSecondsTotal += max( 0, m_fMusicSeconds );
return fSecondsTotal;
}
default:
ASSERT(0);
return 0;
}
}
float GameState::GetPlayerSurviveTime( PlayerNumber pn )
{
if( m_fSecondsBeforeFail[pn] == -1 ) // haven't failed yet
return GetElapsedSeconds();
else
return m_fSecondsBeforeFail[pn];
}
Grade GameState::GetCurrentGrade( PlayerNumber pn ) Grade GameState::GetCurrentGrade( PlayerNumber pn )
{ {
if( !GAMESTATE->IsPlayerEnabled(pn) || GAMESTATE->m_fSecondsBeforeFail[pn] != -1 ) ASSERT( GAMESTATE->IsPlayerEnabled(pn) ); // should be calling this is player isn't joined!
if( m_CurStageStats.bFailed[pn] )
return GRADE_E; return GRADE_E;
/* Based on the percentage of your total "Dance Points" to the maximum /* Based on the percentage of your total "Dance Points" to the maximum
@@ -344,19 +208,19 @@ Grade GameState::GetCurrentGrade( PlayerNumber pn )
* Less - D * Less - D
* Fail - E * Fail - E
*/ */
float fPercentDancePoints = m_iActualDancePoints[pn] / (float)m_iPossibleDancePoints[pn]; float fPercentDancePoints = m_CurStageStats.iActualDancePoints[pn] / (float)m_CurStageStats.iPossibleDancePoints[pn];
fPercentDancePoints = max( fPercentDancePoints, 0 ); fPercentDancePoints = max( 0, fPercentDancePoints );
LOG->Trace( "iActualDancePoints: %i", m_iActualDancePoints[pn] ); LOG->Trace( "iActualDancePoints: %i", m_CurStageStats.iActualDancePoints[pn] );
LOG->Trace( "iPossibleDancePoints: %i", m_iPossibleDancePoints[pn] ); LOG->Trace( "iPossibleDancePoints: %i", m_CurStageStats.iPossibleDancePoints[pn] );
LOG->Trace( "fPercentDancePoints: %f", fPercentDancePoints ); LOG->Trace( "fPercentDancePoints: %f", fPercentDancePoints );
// check for "AAAA" // check for "AAAA"
if( m_TapNoteScores[pn][TNS_MARVELOUS] > 0 && if( m_CurStageStats.iTapNoteScores[pn][TNS_MARVELOUS] > 0 &&
m_TapNoteScores[pn][TNS_PERFECT] == 0 && m_CurStageStats.iTapNoteScores[pn][TNS_PERFECT] == 0 &&
m_TapNoteScores[pn][TNS_GREAT] == 0 && m_CurStageStats.iTapNoteScores[pn][TNS_GREAT] == 0 &&
m_TapNoteScores[pn][TNS_GOOD] == 0 && m_CurStageStats.iTapNoteScores[pn][TNS_GOOD] == 0 &&
m_TapNoteScores[pn][TNS_BOO] == 0 && m_CurStageStats.iTapNoteScores[pn][TNS_BOO] == 0 &&
m_TapNoteScores[pn][TNS_MISS] == 0 ) m_CurStageStats.iTapNoteScores[pn][TNS_MISS] == 0 )
return GRADE_AAAA; return GRADE_AAAA;
if ( fPercentDancePoints == 1.00 ) return GRADE_AAA; if ( fPercentDancePoints == 1.00 ) return GRADE_AAA;
@@ -366,3 +230,19 @@ Grade GameState::GetCurrentGrade( PlayerNumber pn )
else if( fPercentDancePoints >= 0.45 ) return GRADE_C; else if( fPercentDancePoints >= 0.45 ) return GRADE_C;
else return GRADE_D; else return GRADE_D;
} }
bool GameState::HasEarnedExtraStage()
{
if( (GAMESTATE->IsFinalStage() || GAMESTATE->IsExtraStage()) )
{
for( int p=0; p<NUM_PLAYERS; p++ )
{
if( !GAMESTATE->IsPlayerEnabled(p) )
continue; // skip
if( GAMESTATE->m_pCurNotes[p]->GetDifficulty()==DIFFICULTY_HARD && GetCurrentGrade((PlayerNumber)p)==GRADE_AA )
return true;
}
}
return false;
}
+18 -56
View File
@@ -17,6 +17,7 @@
#include "Game.h" #include "Game.h"
#include "Style.h" #include "Style.h"
#include "Grade.h" #include "Grade.h"
#include "StageStats.h"
class Song; class Song;
@@ -39,13 +40,13 @@ public:
Game m_CurGame; Game m_CurGame;
Style m_CurStyle; Style m_CurStyle;
bool m_bPlayersCanJoin; // true if it's not too late for a player to join - this only has an effect on the credits message bool m_bPlayersCanJoin; // true if it's not too late for a player to join - this only has an effect on the credits message
bool m_bSideIsJoined[2]; // left side, right side bool m_bSideIsJoined[NUM_PLAYERS]; // left side, right side
int m_iCoins; int m_iCoins; // not "credits"
PlayerNumber m_MasterPlayerNumber; PlayerNumber m_MasterPlayerNumber; // used in Styles where one player controls both sides
int GetNumSidesJoined() int GetNumSidesJoined()
{ {
int iNumSidesJoined = 0; int iNumSidesJoined = 0;
for( int c=0; c<2; c++ ) for( int c=0; c<NUM_PLAYERS; c++ )
if( m_bSideIsJoined[c] ) if( m_bSideIsJoined[c] )
iNumSidesJoined++; // left side, and right side iNumSidesJoined++; // left side, and right side
return iNumSidesJoined; return iNumSidesJoined;
@@ -58,11 +59,11 @@ public:
bool IsPlayerEnabled( PlayerNumber pn ); bool IsPlayerEnabled( PlayerNumber pn );
bool IsPlayerEnabled( int p ) { return IsPlayerEnabled( (PlayerNumber)p ); }; // for those too lasy to cast all those p's to a PlayerNumber bool IsPlayerEnabled( int p ) { return IsPlayerEnabled( (PlayerNumber)p ); }; // for those too lasy to cast all those p's to a PlayerNumber
CString m_sLoadingMessage; CString m_sLoadingMessage; // used in loading screen
CString m_sPreferredGroup; CString m_sPreferredGroup; // "ALL MUSIC" denotes no preferred group
Difficulty m_PreferredDifficulty[NUM_PLAYERS]; Difficulty m_PreferredDifficulty[NUM_PLAYERS];
SongSortOrder m_SongSortOrder; // used by MusicWheel SongSortOrder m_SongSortOrder; // used by MusicWheel
PlayMode m_PlayMode; PlayMode m_PlayMode; // many screen display different info depending on this value
bool m_bEditing; // NoteField does special stuff when this is true bool m_bEditing; // NoteField does special stuff when this is true
bool m_bDemonstration; // ScreenGameplay does special stuff when this is true bool m_bDemonstration; // ScreenGameplay does special stuff when this is true
int m_iCurrentStageIndex; // incremented on Eval screen int m_iCurrentStageIndex; // incremented on Eval screen
@@ -83,7 +84,7 @@ public:
// //
// Music statistic: Arcade: the current stage (one song). Oni/Endles: a single song in a course // Music statistics: Arcade: the current stage (one song). Oni/Endles: a single song in a course
// //
// Let a lot of classes access this info here so the don't have to keep their own copies. // Let a lot of classes access this info here so the don't have to keep their own copies.
// //
@@ -95,55 +96,16 @@ public:
void ResetMusicStatistics(); // Call this when it's time to play a new song. Clears the values above. void ResetMusicStatistics(); // Call this when it's time to play a new song. Clears the values above.
// //
// Stage Statistics: Arcade: for the current stage (one song). Oni/Endless: for current course (multiple songs) // Stage Statistics:
// Arcade: for the current stage (one song).
// Nonstop/Oni/Endless: for current course (which usually contains multiple songs)
// //
int m_iPossibleDancePoints[NUM_PLAYERS]; StageStats m_CurStageStats; // current stage (not necessarily passed if Extra Stage)
int m_iActualDancePoints[NUM_PLAYERS]; vector<StageStats> m_vPassedStageStats; // Only useful in Arcade for final evaluation
int m_TapNoteScores[NUM_PLAYERS][NUM_TAP_NOTE_SCORES]; // A song is only inserted here if at least one player passed.
int m_HoldNoteScores[NUM_PLAYERS][NUM_HOLD_NOTE_SCORES]; // StageStats are added by the Evaluation screen
int m_iMaxCombo[NUM_PLAYERS]; Grade GetCurrentGrade( PlayerNumber pn ); // grade so far
float m_fScore[NUM_PLAYERS];
float m_fRadarPossible[NUM_PLAYERS][NUM_RADAR_VALUES]; // filled in by ScreenGameplay on end of notes
float m_fRadarActual[NUM_PLAYERS][NUM_RADAR_VALUES]; // filled in by ScreenGameplay on end of notes
float GetElapsedSeconds(); // Arcade: time into current song. Oni/Endless: time into current course
Grade GetCurrentGrade( PlayerNumber pn );
int m_iSongsIntoCourse; // In Arcade, this value is meaningless.
// In Oni and Endless, this is the number of songs played in the current course.
int m_iSongsBeforeFail[NUM_PLAYERS]; // In Arcade, this value is meaningless.
// In Oni and Endless, this is the number of songs played before failing.
float m_fSecondsBeforeFail[NUM_PLAYERS];// -1 means not yet failed
// In Arcade, is the time into the current stage before failing.
// In Oni and Endless this is the time into the current course before failing
float GetPlayerSurviveTime( PlayerNumber pn ); // Returns time player has survived
void AccumulateStageStatistics(); // Call this before clearing values. Accumulate values above into the Session values below.
void ResetStageStatistics(); // Clears the values above
//
// Session Statistics: Arcade: 3 songs. Oni/Endless: one course.
//
vector<Song*> m_apSongsPlayed; // an array of completed songs.
// This is useful for the final evaluation screen,
// and used to calculate the time into a course
// Only used in final evaluation screen in play mode Arcade.
// Before being displayed, these values should be normalized by dividing by number of stages
int m_iAccumPossibleDancePoints[NUM_PLAYERS];
int m_iAccumActualDancePoints[NUM_PLAYERS];
int m_AccumTapNoteScores[NUM_PLAYERS][NUM_TAP_NOTE_SCORES];
int m_AccumHoldNoteScores[NUM_PLAYERS][NUM_HOLD_NOTE_SCORES];
int m_iAccumMaxCombo[NUM_PLAYERS];
float m_fAccumScore[NUM_PLAYERS];
float m_fAccumRadarPossible[NUM_PLAYERS][NUM_RADAR_VALUES];
float m_fAccumRadarActual[NUM_PLAYERS][NUM_RADAR_VALUES];
// Session statistics are cleared by calling Reset()
PlayerOptions m_PlayerOptions[NUM_PLAYERS]; // The currently active options PlayerOptions m_PlayerOptions[NUM_PLAYERS]; // The currently active options
PlayerOptions m_SelectedOptions[NUM_PLAYERS]; // Keep track of player-selected options for PlayerOptions m_SelectedOptions[NUM_PLAYERS]; // Keep track of player-selected options for
@@ -151,7 +113,7 @@ public:
SongOptions m_SongOptions; SongOptions m_SongOptions;
vector<CString> m_asNetworkNames; bool HasEarnedExtraStage();
}; };
+1 -1
View File
@@ -27,7 +27,7 @@ public:
virtual void Load( PlayerNumber pn ) { m_PlayerNumber = pn; } virtual void Load( PlayerNumber pn ) { m_PlayerNumber = pn; }
virtual void Update( float fDeltaTime ) { ActorFrame::Update(fDeltaTime); }; virtual void Update( float fDeltaTime ) { ActorFrame::Update(fDeltaTime); };
virtual void SongEnded() {}; virtual void OnSongEnded() {};
/* Change life after receiving a tap note grade. This *is* called for /* Change life after receiving a tap note grade. This *is* called for
* the head of hold notes. */ * the head of hold notes. */
virtual void ChangeLife( TapNoteScore score ) = 0; virtual void ChangeLife( TapNoteScore score ) = 0;
+3 -3
View File
@@ -83,7 +83,7 @@ void LifeMeterBattery::Load( PlayerNumber pn )
Refresh(); Refresh();
} }
void LifeMeterBattery::SongEnded() void LifeMeterBattery::OnSongEnded()
{ {
if( m_bFailedEarlier ) if( m_bFailedEarlier )
return; return;
@@ -145,8 +145,8 @@ void LifeMeterBattery::ChangeLife( HoldNoteScore score, TapNoteScore tscore )
void LifeMeterBattery::OnDancePointsChange() void LifeMeterBattery::OnDancePointsChange()
{ {
int iActualDancePoints = GAMESTATE->m_iActualDancePoints[m_PlayerNumber]; int iActualDancePoints = GAMESTATE->m_CurStageStats.iActualDancePoints[m_PlayerNumber];
int iPossibleDancePoints = GAMESTATE->m_iPossibleDancePoints[m_PlayerNumber]; int iPossibleDancePoints = GAMESTATE->m_CurStageStats.iPossibleDancePoints[m_PlayerNumber];
iPossibleDancePoints = max( 1, iPossibleDancePoints ); iPossibleDancePoints = max( 1, iPossibleDancePoints );
float fPercentDancePoints = iActualDancePoints / (float)iPossibleDancePoints + 0.00001f; // correct for rounding errors float fPercentDancePoints = iActualDancePoints / (float)iPossibleDancePoints + 0.00001f; // correct for rounding errors
+1 -1
View File
@@ -27,7 +27,7 @@ public:
virtual void Update( float fDeltaTime ); virtual void Update( float fDeltaTime );
virtual void SongEnded(); virtual void OnSongEnded();
virtual void ChangeLife( TapNoteScore score ); virtual void ChangeLife( TapNoteScore score );
virtual void ChangeLife( HoldNoteScore score, TapNoteScore tscore ); virtual void ChangeLife( HoldNoteScore score, TapNoteScore tscore );
virtual void OnDancePointsChange(); // look in GAMESTATE and update the display virtual void OnDancePointsChange(); // look in GAMESTATE and update the display
+4 -4
View File
@@ -52,7 +52,7 @@ Notes::Notes()
for( int p=0; p<NUM_PLAYERS; p++ ) for( int p=0; p<NUM_PLAYERS; p++ )
{ {
m_MemCardScores[p].grade = GRADE_NO_DATA; m_MemCardScores[p].grade = GRADE_NO_DATA;
m_MemCardScores[p].iScore = 0; m_MemCardScores[p].fScore = 0;
} }
} }
@@ -313,11 +313,11 @@ 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 bool Notes::AddMemCardRecord( PlayerNumber pn, Grade grade, float fScore ) // return true if new high score
{ {
if( iScore > m_MemCardScores[pn].iScore ) if( fScore > m_MemCardScores[pn].fScore )
{ {
m_MemCardScores[pn].iScore = iScore; m_MemCardScores[pn].fScore = fScore;
m_MemCardScores[pn].grade = grade; m_MemCardScores[pn].grade = grade;
return true; return true;
} }
+4 -5
View File
@@ -52,14 +52,13 @@ public:
// High scores; // High scores;
int m_iNumTimesPlayed; int m_iNumTimesPlayed;
struct HighScore struct MemCardScore
{ {
Grade grade; Grade grade;
int iScore; float fScore;
}; } m_MemCardScores[NUM_PLAYERS];
HighScore m_MemCardScores[NUM_PLAYERS];
bool AddMemCardScore( PlayerNumber pn, Grade grade, int iScore ); // return true if new high score bool AddMemCardRecord( PlayerNumber pn, Grade grade, float fScore ); // return true if new high score
void TidyUpData(); void TidyUpData();
+5 -5
View File
@@ -136,7 +136,7 @@ void Player::Load( PlayerNumber pn, NoteData* pNoteData, LifeMeter* pLM, ScoreDi
// copy note data // copy note data
this->CopyAll( pNoteData ); this->CopyAll( pNoteData );
if( GAMESTATE->m_SongOptions.m_LifeType == SongOptions::LIFE_BATTERY && GAMESTATE->m_fSecondsBeforeFail[m_PlayerNumber] != -1 ) // Oni dead if( GAMESTATE->m_SongOptions.m_LifeType == SongOptions::LIFE_BATTERY && GAMESTATE->m_CurStageStats.bFailed ) // Oni dead
this->ClearAll(); this->ClearAll();
/* The editor reuses Players ... so we really need to make sure everything /* The editor reuses Players ... so we really need to make sure everything
@@ -341,7 +341,7 @@ void Player::DrawPrimitives()
void Player::Step( int col ) void Player::Step( int col )
{ {
if( GAMESTATE->m_SongOptions.m_LifeType == SongOptions::LIFE_BATTERY && GAMESTATE->m_fSecondsBeforeFail[m_PlayerNumber] != -1 ) // Oni dead if( GAMESTATE->m_SongOptions.m_LifeType == SongOptions::LIFE_BATTERY && GAMESTATE->m_CurStageStats.bFailed[m_PlayerNumber] ) // Oni dead
return; // do nothing return; // do nothing
//LOG->Trace( "Player::HandlePlayerStep()" ); //LOG->Trace( "Player::HandlePlayerStep()" );
@@ -518,7 +518,7 @@ void Player::OnRowDestroyed( int iIndexThatWasSteppedOn )
{ {
HandleNoteScore( score, iNumNotesInThisRow ); // update score HandleNoteScore( score, iNumNotesInThisRow ); // update score
m_Combo.UpdateScore( score, iNumNotesInThisRow ); m_Combo.UpdateScore( score, iNumNotesInThisRow );
GAMESTATE->m_iMaxCombo[m_PlayerNumber] = max( GAMESTATE->m_iMaxCombo[m_PlayerNumber], m_Combo.GetCurrentCombo() ); GAMESTATE->m_CurStageStats.iMaxCombo[m_PlayerNumber] = max( GAMESTATE->m_CurStageStats.iMaxCombo[m_PlayerNumber], m_Combo.GetCurrentCombo() );
} }
// update the judgement, score, and life // update the judgement, score, and life
@@ -616,7 +616,7 @@ void Player::HandleNoteScore( TapNoteScore score, int iNumTapsInRow )
m_ScoreKeeper->HandleNoteScore(score, iNumTapsInRow); m_ScoreKeeper->HandleNoteScore(score, iNumTapsInRow);
if (m_pScore) if (m_pScore)
m_pScore->SetScore(GAMESTATE->m_fScore[m_PlayerNumber]); m_pScore->SetScore(GAMESTATE->m_CurStageStats.fScore[m_PlayerNumber]);
if( m_pLifeMeter ) { if( m_pLifeMeter ) {
m_pLifeMeter->ChangeLife( score ); m_pLifeMeter->ChangeLife( score );
@@ -636,7 +636,7 @@ void Player::HandleHoldNoteScore( HoldNoteScore score, TapNoteScore TapNoteScore
} }
if (m_pScore) if (m_pScore)
m_pScore->SetScore(GAMESTATE->m_fScore[m_PlayerNumber]); m_pScore->SetScore(GAMESTATE->m_CurStageStats.fScore[m_PlayerNumber]);
if( m_pLifeMeter ) { if( m_pLifeMeter ) {
if( score == HNS_NG ) { if( score == HNS_NG ) {
+9 -5
View File
@@ -54,11 +54,11 @@ PrefsManager::PrefsManager()
m_iNumArcadeStages = 3; m_iNumArcadeStages = 3;
m_bAutoPlay = false; m_bAutoPlay = false;
m_fJudgeWindowScale = 1.0f; m_fJudgeWindowScale = 1.0f;
m_fJudgeWindowMarvelousSeconds = 0.023f; m_fJudgeWindowMarvelousSeconds = 0.025f;
m_fJudgeWindowPerfectSeconds = 0.043f; m_fJudgeWindowPerfectSeconds = 0.05f;
m_fJudgeWindowGreatSeconds = 0.086f; m_fJudgeWindowGreatSeconds = 0.10f;
m_fJudgeWindowGoodSeconds = 0.129f; m_fJudgeWindowGoodSeconds = 0.15f;
m_fJudgeWindowBooSeconds = 0.172f; m_fJudgeWindowBooSeconds = 0.2f;
m_fLifeDifficultyScale = 1.0f; m_fLifeDifficultyScale = 1.0f;
m_iMovieDecodeMS = 2; m_iMovieDecodeMS = 2;
m_bUseBGIfNoBanner = false; m_bUseBGIfNoBanner = false;
@@ -119,9 +119,11 @@ void PrefsManager::ReadGlobalPrefsFromDisk( bool bSwitchToLastPlayedGame )
ini.GetValueI( "Options", "NumArcadeStages", m_iNumArcadeStages ); ini.GetValueI( "Options", "NumArcadeStages", m_iNumArcadeStages );
ini.GetValueB( "Options", "AutoPlay", m_bAutoPlay ); ini.GetValueB( "Options", "AutoPlay", m_bAutoPlay );
ini.GetValueF( "Options", "JudgeWindowScale", m_fJudgeWindowScale ); ini.GetValueF( "Options", "JudgeWindowScale", m_fJudgeWindowScale );
ini.GetValueF( "Options", "JudgeWindowMarvelousSeconds",m_fJudgeWindowMarvelousSeconds );
ini.GetValueF( "Options", "JudgeWindowPerfectSeconds", m_fJudgeWindowPerfectSeconds ); ini.GetValueF( "Options", "JudgeWindowPerfectSeconds", m_fJudgeWindowPerfectSeconds );
ini.GetValueF( "Options", "JudgeWindowGreatSeconds", m_fJudgeWindowGreatSeconds ); ini.GetValueF( "Options", "JudgeWindowGreatSeconds", m_fJudgeWindowGreatSeconds );
ini.GetValueF( "Options", "JudgeWindowGoodSeconds", m_fJudgeWindowGoodSeconds ); ini.GetValueF( "Options", "JudgeWindowGoodSeconds", m_fJudgeWindowGoodSeconds );
ini.GetValueF( "Options", "JudgeWindowBooSeconds", m_fJudgeWindowBooSeconds );
ini.GetValueF( "Options", "LifeDifficultyScale", m_fLifeDifficultyScale ); ini.GetValueF( "Options", "LifeDifficultyScale", m_fLifeDifficultyScale );
ini.GetValueI( "Options", "MovieDecodeMS", m_iMovieDecodeMS ); ini.GetValueI( "Options", "MovieDecodeMS", m_iMovieDecodeMS );
ini.GetValueB( "Options", "UseBGIfNoBanner", m_bUseBGIfNoBanner ); ini.GetValueB( "Options", "UseBGIfNoBanner", m_bUseBGIfNoBanner );
@@ -184,9 +186,11 @@ void PrefsManager::SaveGlobalPrefsToDisk()
ini.SetValueI( "Options", "NumArcadeStages", m_iNumArcadeStages ); ini.SetValueI( "Options", "NumArcadeStages", m_iNumArcadeStages );
ini.SetValueB( "Options", "AutoPlay", m_bAutoPlay ); ini.SetValueB( "Options", "AutoPlay", m_bAutoPlay );
ini.SetValueF( "Options", "JudgeWindowScale", m_fJudgeWindowScale ); ini.SetValueF( "Options", "JudgeWindowScale", m_fJudgeWindowScale );
ini.SetValueF( "Options", "JudgeWindowMarvelousSeconds",m_fJudgeWindowMarvelousSeconds );
ini.SetValueF( "Options", "JudgeWindowPerfectSeconds", m_fJudgeWindowPerfectSeconds ); ini.SetValueF( "Options", "JudgeWindowPerfectSeconds", m_fJudgeWindowPerfectSeconds );
ini.SetValueF( "Options", "JudgeWindowGreatSeconds", m_fJudgeWindowGreatSeconds ); ini.SetValueF( "Options", "JudgeWindowGreatSeconds", m_fJudgeWindowGreatSeconds );
ini.SetValueF( "Options", "JudgeWindowGoodSeconds", m_fJudgeWindowGoodSeconds ); ini.SetValueF( "Options", "JudgeWindowGoodSeconds", m_fJudgeWindowGoodSeconds );
ini.SetValueF( "Options", "JudgeWindowBooSeconds", m_fJudgeWindowBooSeconds );
ini.SetValueF( "Options", "LifeDifficultyScale", m_fLifeDifficultyScale ); ini.SetValueF( "Options", "LifeDifficultyScale", m_fLifeDifficultyScale );
ini.SetValueI( "Options", "MovieDecodeMS", m_iMovieDecodeMS ); ini.SetValueI( "Options", "MovieDecodeMS", m_iMovieDecodeMS );
ini.SetValueB( "Options", "UseBGIfNoBanner", m_bUseBGIfNoBanner ); ini.SetValueB( "Options", "UseBGIfNoBanner", m_bUseBGIfNoBanner );
+1 -1
View File
@@ -50,7 +50,7 @@ void ScoreDisplayOni::Draw()
{ {
float fSecsIntoPlay; float fSecsIntoPlay;
if( GAMESTATE->IsPlayerEnabled(m_PlayerNumber) ) if( GAMESTATE->IsPlayerEnabled(m_PlayerNumber) )
fSecsIntoPlay = GAMESTATE->GetPlayerSurviveTime(m_PlayerNumber); fSecsIntoPlay = GAMESTATE->m_CurStageStats.fAliveSeconds[m_PlayerNumber];
else else
fSecsIntoPlay = 0; fSecsIntoPlay = 0;
+5 -5
View File
@@ -42,7 +42,7 @@ void ScoreKeeperMAX2::AddScore( TapNoteScore score )
ASSERT(m_lScore >= 0); ASSERT(m_lScore >= 0);
GAMESTATE->m_fScore[m_PlayerNumber] = m_lScore * m_fScoreMultiplier; GAMESTATE->m_CurStageStats.fScore[m_PlayerNumber] = m_lScore * m_fScoreMultiplier;
} }
void ScoreKeeperMAX2::HandleNoteScore( TapNoteScore score, int iNumTapsInRow ) void ScoreKeeperMAX2::HandleNoteScore( TapNoteScore score, int iNumTapsInRow )
@@ -52,8 +52,8 @@ void ScoreKeeperMAX2::HandleNoteScore( TapNoteScore score, int iNumTapsInRow )
ASSERT( iNumTapsInRow >= 1 ); ASSERT( iNumTapsInRow >= 1 );
// update dance points for Oni lifemeter // update dance points for Oni lifemeter
GAMESTATE->m_iActualDancePoints[m_PlayerNumber] += iNumTapsInRow * TapNoteScoreToDancePoints( score ); GAMESTATE->m_CurStageStats.iActualDancePoints[m_PlayerNumber] += iNumTapsInRow * TapNoteScoreToDancePoints( score );
GAMESTATE->m_TapNoteScores[m_PlayerNumber][score] += iNumTapsInRow; GAMESTATE->m_CurStageStats.iTapNoteScores[m_PlayerNumber][score] += iNumTapsInRow;
/* /*
A single step's points are calculated as follows: A single step's points are calculated as follows:
@@ -100,8 +100,8 @@ void ScoreKeeperMAX2::HandleNoteScore( TapNoteScore score, int iNumTapsInRow )
void ScoreKeeperMAX2::HandleHoldNoteScore( HoldNoteScore score, TapNoteScore TapNoteScore ) void ScoreKeeperMAX2::HandleHoldNoteScore( HoldNoteScore score, TapNoteScore TapNoteScore )
{ {
// update dance points totals // update dance points totals
GAMESTATE->m_HoldNoteScores[m_PlayerNumber][score] ++; GAMESTATE->m_CurStageStats.iHoldNoteScores[m_PlayerNumber][score] ++;
GAMESTATE->m_iActualDancePoints[m_PlayerNumber] += HoldNoteScoreToDancePoints( score ); GAMESTATE->m_CurStageStats.iActualDancePoints[m_PlayerNumber] += HoldNoteScoreToDancePoints( score );
if( score == HNS_OK ) if( score == HNS_OK )
AddScore( TNS_PERFECT ); AddScore( TNS_PERFECT );
+123 -146
View File
@@ -115,12 +115,9 @@ ScreenEvaluation::ScreenEvaluation( bool bSummary )
{ {
LOG->Trace( "ScreenEvaluation::ScreenEvaluation()" ); LOG->Trace( "ScreenEvaluation::ScreenEvaluation()" );
int l, p; // for counting //
// Set m_ResultMode. This enum will make our life easier later when we init different pieces.
//
///////////////////////////
// Set m_ResultMode. This enum will make our life easier later when we init different pieces depending on context.
///////////////////////////
switch( GAMESTATE->m_PlayMode ) switch( GAMESTATE->m_PlayMode )
{ {
case PLAY_MODE_ARCADE: case PLAY_MODE_ARCADE:
@@ -129,54 +126,42 @@ ScreenEvaluation::ScreenEvaluation( bool bSummary )
case PLAY_MODE_NONSTOP: case PLAY_MODE_NONSTOP:
case PLAY_MODE_ONI: case PLAY_MODE_ONI:
case PLAY_MODE_ENDLESS: case PLAY_MODE_ENDLESS:
m_ResultMode = RM_ONI; m_ResultMode = RM_COURSE;
break; break;
default: default:
ASSERT(0); ASSERT(0);
} }
/////////////////////////// //
// Figure out which statistics we're going to display // Figure out which statistics and songs we're going to display
/////////////////////////// //
int iPossibleDancePoints[NUM_PLAYERS]; StageStats stageStats;
int iActualDancePoints[NUM_PLAYERS]; vector<Song*> vSongsToShow;
int iTapNoteScores[NUM_PLAYERS][NUM_TAP_NOTE_SCORES];
int iHoldNoteScores[NUM_PLAYERS][NUM_HOLD_NOTE_SCORES];
int iMaxCombo[NUM_PLAYERS];
float fScore[NUM_PLAYERS];
float fPossibleRadarValues[NUM_PLAYERS][NUM_RADAR_CATEGORIES];
float fActualRadarValues[NUM_PLAYERS][NUM_RADAR_CATEGORIES];
switch( m_ResultMode ) switch( m_ResultMode )
{ {
case RM_ARCADE_SUMMARY: case RM_ARCADE_SUMMARY:
COPY( iPossibleDancePoints, GAMESTATE->m_iAccumPossibleDancePoints ); {
COPY( iActualDancePoints, GAMESTATE->m_iAccumActualDancePoints ); // Show stats only for the latest 3 normal songs + passed extra stages
COPY( iTapNoteScores, GAMESTATE->m_AccumTapNoteScores ); int iNumSongsToThrowAway = max( 0, PREFSMAN->m_iNumArcadeStages-3 );
COPY( iHoldNoteScores, GAMESTATE->m_AccumHoldNoteScores ); for( unsigned i=iNumSongsToThrowAway; i<GAMESTATE->m_vPassedStageStats.size(); i++ )
COPY( iMaxCombo, GAMESTATE->m_iAccumMaxCombo ); {
COPY( fScore, GAMESTATE->m_fAccumScore ); stageStats += GAMESTATE->m_vPassedStageStats[i];
COPY( fPossibleRadarValues, GAMESTATE->m_fAccumRadarPossible ); vSongsToShow.push_back( GAMESTATE->m_vPassedStageStats[i].pSong );
COPY( fActualRadarValues, GAMESTATE->m_fAccumRadarActual ); }
}
break; break;
case RM_ARCADE_STAGE: case RM_ARCADE_STAGE:
case RM_ONI: case RM_COURSE:
COPY( iPossibleDancePoints, GAMESTATE->m_iPossibleDancePoints ); stageStats = GAMESTATE->m_CurStageStats;
COPY( iActualDancePoints, GAMESTATE->m_iActualDancePoints );
COPY( iTapNoteScores, GAMESTATE->m_TapNoteScores );
COPY( iHoldNoteScores, GAMESTATE->m_HoldNoteScores );
COPY( iMaxCombo, GAMESTATE->m_iMaxCombo );
COPY( fScore, GAMESTATE->m_fScore );
COPY( fPossibleRadarValues, GAMESTATE->m_fRadarPossible );
COPY( fActualRadarValues, GAMESTATE->m_fRadarActual );
break; break;
default:
ASSERT(0);
} }
/////////////////////////// //
// Init the song banners depending on m_ResultMode // Init the song banners depending on m_ResultMode
/////////////////////////// //
// EZ2 should hide these things by placing them off screen with theme metrics
switch( m_ResultMode ) switch( m_ResultMode )
{ {
case RM_ARCADE_STAGE: case RM_ARCADE_STAGE:
@@ -205,31 +190,23 @@ ScreenEvaluation::ScreenEvaluation( bool bSummary )
break; break;
case RM_ARCADE_SUMMARY: case RM_ARCADE_SUMMARY:
{ {
// crop down to 3 for( unsigned i=0; i<vSongsToShow.size(); i++ )
for( int p=0; p<NUM_PLAYERS; p++ )
{ {
if( GAMESTATE->m_apSongsPlayed.size() > STAGES_TO_SHOW_IN_SUMMARY ) m_BannerWithFrame[i].LoadFromSong( vSongsToShow[i] );
GAMESTATE->m_apSongsPlayed.erase( GAMESTATE->m_apSongsPlayed.begin(), GAMESTATE->m_apSongsPlayed.begin() + (GAMESTATE->m_apSongsPlayed.size() - STAGES_TO_SHOW_IN_SUMMARY) ); float fBannerOffset = i - (vSongsToShow.size()-1)/2.0f;
}
const unsigned iSongsToShow = GAMESTATE->m_apSongsPlayed.size();
ASSERT( iSongsToShow > 0 );
for( unsigned i=0; i<iSongsToShow; i++ )
{
m_BannerWithFrame[i].LoadFromSong( GAMESTATE->m_apSongsPlayed[i] );
float fBannerOffset = i - (iSongsToShow-1)/2.0f;
m_BannerWithFrame[i].SetXY( BANNER_X + fBannerOffset*32, BANNER_Y + fBannerOffset*16 ); m_BannerWithFrame[i].SetXY( BANNER_X + fBannerOffset*32, BANNER_Y + fBannerOffset*16 );
m_BannerWithFrame[i].SetZoom( 0.70f ); m_BannerWithFrame[i].SetZoom( 0.70f );
this->AddChild( &m_BannerWithFrame[i] ); this->AddChild( &m_BannerWithFrame[i] );
} }
} }
break; break;
case RM_ONI: case RM_COURSE:
m_BannerWithFrame[0].LoadFromCourse( GAMESTATE->m_pCurCourse ); m_BannerWithFrame[0].LoadFromCourse( GAMESTATE->m_pCurCourse );
m_BannerWithFrame[0].SetXY( BANNER_X, BANNER_Y ); m_BannerWithFrame[0].SetXY( BANNER_X, BANNER_Y );
this->AddChild( &m_BannerWithFrame[0] ); this->AddChild( &m_BannerWithFrame[0] );
break; break;
default:
ASSERT(0);
} }
@@ -243,7 +220,7 @@ ScreenEvaluation::ScreenEvaluation( bool bSummary )
); );
this->AddChild( &m_Menu ); this->AddChild( &m_Menu );
for( p=0; p<NUM_PLAYERS; p++ ) for( int p=0; p<NUM_PLAYERS; p++ )
{ {
if( !GAMESTATE->IsPlayerEnabled( (PlayerNumber)p ) ) // If EZ2 wants to hide this graphic, place it somewhere off screen using theme metrics if( !GAMESTATE->IsPlayerEnabled( (PlayerNumber)p ) ) // If EZ2 wants to hide this graphic, place it somewhere off screen using theme metrics
continue; // skip continue; // skip
@@ -256,18 +233,15 @@ ScreenEvaluation::ScreenEvaluation( bool bSummary )
} }
// //
// Calculate grades // Calculate grades
// //
Grade grade[NUM_PLAYERS]; Grade grade[NUM_PLAYERS];
for( p=0; p<NUM_PLAYERS; p++ ) for( p=0; p<NUM_PLAYERS; p++ )
{ {
if( !GAMESTATE->IsPlayerEnabled(p) || GAMESTATE->m_fSecondsBeforeFail[p] != -1 ) if( !GAMESTATE->IsPlayerEnabled(p) || GAMESTATE->m_CurStageStats.bFailed[p] )
{
grade[p] = GRADE_E; grade[p] = GRADE_E;
continue; else
}
grade[p] = GAMESTATE->GetCurrentGrade( (PlayerNumber)p ); grade[p] = GAMESTATE->GetCurrentGrade( (PlayerNumber)p );
} }
@@ -276,52 +250,53 @@ ScreenEvaluation::ScreenEvaluation( bool bSummary )
max_grade = max( max_grade, grade[p] ); max_grade = max( max_grade, grade[p] );
//////////////////////// //
// update persistent statistics // update persistent statistics
//////////////////////// //
bool bNewRecord[NUM_PLAYERS]; bool bNewRecord[NUM_PLAYERS];
for( p=0; p<NUM_PLAYERS; p++ ) memset( bNewRecord, 0, sizeof(bNewRecord) );
bNewRecord[p] = false; m_bGoToNameEntry = false;
for( int p=0; p<NUM_PLAYERS; p++ )
for( p=0; p<NUM_PLAYERS; p++ )
{ {
if( !GAMESTATE->IsPlayerEnabled(p) ) if( !GAMESTATE->IsPlayerEnabled(p) || grade[p] == GRADE_E )
continue; continue; // can't be a new record
if( grade[p] == GRADE_E )
continue;
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];
if( SONGMAN->IsUsingMemoryCard((PlayerNumber)p) ) if( SONGMAN->IsUsingMemoryCard((PlayerNumber)p) )
bNewRecord[p] = pNotes->AddMemCardScore( (PlayerNumber)p, grade[p], (int)fScore[p] ); bNewRecord[p] = pNotes->AddMemCardRecord( (PlayerNumber)p, grade[p], stageStats.fScore[p] );
}
break; break;
} case RM_ARCADE_SUMMARY:
}
m_bTryExtraStage = false;
if( (GAMESTATE->IsFinalStage() || GAMESTATE->IsExtraStage()) && m_ResultMode==RM_ARCADE_STAGE )
{ {
for( p=0; p<NUM_PLAYERS; p++ ) float fAverageMeter = stageStats.iMeter[p] / (float)PREFSMAN->m_iNumArcadeStages; // intentional: doesn't count extra stage
HighScoreCategory hsc = AverageMeterToHighScoreCategory( fAverageMeter );
m_bGoToNameEntry |= SONGMAN->IsNewMachineRecord( hsc, stageStats.fScore[p] );
}
break;
case RM_COURSE:
{ {
if( !GAMESTATE->IsPlayerEnabled( (PlayerNumber)p ) ) Course* pCourse = GAMESTATE->m_pCurCourse;
continue; // skip pCourse->IsNewMachineRecord( (PlayerNumber)p, stageStats.iActualDancePoints[p], stageStats.fAliveSeconds[p] );
m_bGoToNameEntry |= true;
if( GAMESTATE->m_pCurNotes[p]->GetDifficulty() == DIFFICULTY_HARD && grade[p] >= GRADE_AA ) }
m_bTryExtraStage = true; break;
default:
ASSERT(0);
} }
} }
if( PREFSMAN->m_bEventMode )
m_bTryExtraStage = false;
m_bTryExtraStage =
GAMESTATE->HasEarnedExtraStage() &&
m_ResultMode==RM_ARCADE_STAGE &&
!PREFSMAN->m_bEventMode;
///////////////////////////////// //
// Init ResultMode-specific displays // Init ResultMode-specific displays
///////////////////////////////// //
for( p=0; p<NUM_PLAYERS; p++ ) for( p=0; p<NUM_PLAYERS; p++ )
{ {
if( !GAMESTATE->IsPlayerEnabled( (PlayerNumber)p ) ) if( !GAMESTATE->IsPlayerEnabled( (PlayerNumber)p ) )
@@ -331,7 +306,7 @@ ScreenEvaluation::ScreenEvaluation( bool bSummary )
switch( m_ResultMode ) switch( m_ResultMode )
{ {
case RM_ONI: case RM_COURSE:
{ {
m_sprPercentFrame[p].Load( THEME->GetPathTo("Graphics","evaluation percent frame") ); m_sprPercentFrame[p].Load( THEME->GetPathTo("Graphics","evaluation percent frame") );
m_sprPercentFrame[p].StopAnimating(); m_sprPercentFrame[p].StopAnimating();
@@ -356,8 +331,8 @@ ScreenEvaluation::ScreenEvaluation( bool bSummary )
m_textOniPercentSmall[p].SetEffectGlowing( 1.0f ); m_textOniPercentSmall[p].SetEffectGlowing( 1.0f );
this->AddChild( &m_textOniPercentSmall[p] ); this->AddChild( &m_textOniPercentSmall[p] );
iPossibleDancePoints[p] = max( 1, iPossibleDancePoints[p] ); stageStats.iPossibleDancePoints[p] = max( 1, stageStats.iPossibleDancePoints[p] );
float fPercentDancePoints = iActualDancePoints[p] / (float)iPossibleDancePoints[p] + 0.0001f; // correct for rounding errors float fPercentDancePoints = stageStats.iActualDancePoints[p] / (float)stageStats.iPossibleDancePoints[p] + 0.0001f; // correct for rounding errors
fPercentDancePoints = max( fPercentDancePoints, 0 ); fPercentDancePoints = max( fPercentDancePoints, 0 );
int iPercentDancePointsLarge = int(fPercentDancePoints*100); int iPercentDancePointsLarge = int(fPercentDancePoints*100);
int iPercentDancePointsSmall = int( (fPercentDancePoints*100 - int(fPercentDancePoints*100)) * 10 ); int iPercentDancePointsSmall = int( (fPercentDancePoints*100 - int(fPercentDancePoints*100)) * 10 );
@@ -374,7 +349,7 @@ ScreenEvaluation::ScreenEvaluation( bool bSummary )
m_textSongsSurvived[p].LoadFromNumbers( THEME->GetPathTo("Numbers","evaluation stage numbers") ); m_textSongsSurvived[p].LoadFromNumbers( THEME->GetPathTo("Numbers","evaluation stage numbers") );
m_textSongsSurvived[p].TurnShadowOff(); m_textSongsSurvived[p].TurnShadowOff();
m_textSongsSurvived[p].SetXY( SONGS_SURVIVED_X(p), SONGS_SURVIVED_Y ); m_textSongsSurvived[p].SetXY( SONGS_SURVIVED_X(p), SONGS_SURVIVED_Y );
m_textSongsSurvived[p].SetText( ssprintf("%02d", GAMESTATE->m_iSongsBeforeFail[p]) ); m_textSongsSurvived[p].SetText( ssprintf("%02d", stageStats.iSongsPassed[p]+1) );
this->AddChild( &m_textSongsSurvived[p] ); this->AddChild( &m_textSongsSurvived[p] );
} }
break; break;
@@ -405,42 +380,41 @@ ScreenEvaluation::ScreenEvaluation( bool bSummary )
m_sprBonusFrame[p].SetXY( BONUS_X(p), BONUS_Y ); m_sprBonusFrame[p].SetXY( BONUS_X(p), BONUS_Y );
this->AddChild( &m_sprBonusFrame[p] ); this->AddChild( &m_sprBonusFrame[p] );
for( int l=0; l<NUM_RADAR_VALUES; l++ ) // foreach line for( int r=0; r<NUM_RADAR_VALUES; r++ ) // foreach line
{ {
m_sprPossibleBar[p][l].Load( THEME->GetPathTo("Graphics","evaluation bars possible 1x2") ); m_sprPossibleBar[p][r].Load( THEME->GetPathTo("Graphics","evaluation bars possible 1x2") );
m_sprPossibleBar[p][l].SetState( p ); m_sprPossibleBar[p][r].SetState( p );
m_sprPossibleBar[p][l].SetHorizAlign( Actor::align_left ); m_sprPossibleBar[p][r].SetHorizAlign( Actor::align_left );
m_sprPossibleBar[p][l].SetX( BAR_BASE_X(p) ); m_sprPossibleBar[p][r].SetX( BAR_BASE_X(p) );
m_sprPossibleBar[p][l].SetY( BAR_START_Y + BAR_SPACING_Y*l ); m_sprPossibleBar[p][r].SetY( BAR_START_Y + BAR_SPACING_Y*r );
m_sprPossibleBar[p][l].SetRotation( BAR_ROTATION(p) ); m_sprPossibleBar[p][r].SetRotation( BAR_ROTATION(p) );
m_sprPossibleBar[p][l].SetZoomX( 0 ); m_sprPossibleBar[p][r].SetZoomX( 0 );
m_sprPossibleBar[p][l].ZoomToHeight( BAR_HEIGHT ); m_sprPossibleBar[p][r].ZoomToHeight( BAR_HEIGHT );
m_sprPossibleBar[p][l].BeginTweening( 0.2f + l*0.1f ); // sleep m_sprPossibleBar[p][r].BeginTweening( 0.2f + r*0.1f ); // sleep
m_sprPossibleBar[p][l].BeginTweening( 0.5f ); // tween m_sprPossibleBar[p][r].BeginTweening( 0.5f ); // tween
m_sprPossibleBar[p][l].SetTweenZoomToWidth( BAR_WIDTH*fPossibleRadarValues[p][l] ); m_sprPossibleBar[p][r].SetTweenZoomToWidth( BAR_WIDTH*stageStats.fRadarPossible[p][r] );
this->AddChild( &m_sprPossibleBar[p][l] ); this->AddChild( &m_sprPossibleBar[p][r] );
m_sprActualBar[p][l].Load( THEME->GetPathTo("Graphics","evaluation bars actual 1x2") ); m_sprActualBar[p][r].Load( THEME->GetPathTo("Graphics","evaluation bars actual 1x2") );
m_sprActualBar[p][l].SetState( p ); m_sprActualBar[p][r].SetState( p );
m_sprActualBar[p][l].StopAnimating(); m_sprActualBar[p][r].StopAnimating();
m_sprActualBar[p][l].SetHorizAlign( Actor::align_left ); m_sprActualBar[p][r].SetHorizAlign( Actor::align_left );
m_sprActualBar[p][l].SetX( BAR_BASE_X(p) ); m_sprActualBar[p][r].SetX( BAR_BASE_X(p) );
m_sprActualBar[p][l].SetY( BAR_START_Y + BAR_SPACING_Y*l ); m_sprActualBar[p][r].SetY( BAR_START_Y + BAR_SPACING_Y*r );
m_sprActualBar[p][l].SetRotation( BAR_ROTATION(p) ); m_sprActualBar[p][r].SetRotation( BAR_ROTATION(p) );
m_sprActualBar[p][l].SetZoomX( 0 ); m_sprActualBar[p][r].SetZoomX( 0 );
m_sprActualBar[p][l].ZoomToHeight( BAR_HEIGHT ); m_sprActualBar[p][r].ZoomToHeight( BAR_HEIGHT );
m_sprActualBar[p][l].BeginTweening( 1.0f + l*0.2f ); // sleep m_sprActualBar[p][r].BeginTweening( 1.0f + r*0.2f ); // sleep
m_sprActualBar[p][l].BeginTweening( 1.0f ); // tween m_sprActualBar[p][r].BeginTweening( 1.0f ); // tween
m_sprActualBar[p][l].SetTweenZoomToWidth( BAR_WIDTH*fActualRadarValues[p][l] ); m_sprActualBar[p][r].SetTweenZoomToWidth( BAR_WIDTH*stageStats.fRadarActual[p][r] );
if( fActualRadarValues[p][l] == fPossibleRadarValues[p][l] ) if( stageStats.fRadarActual[p][r] == stageStats.fRadarPossible[p][r] )
m_sprActualBar[p][l].SetEffectGlowing(); m_sprActualBar[p][r].SetEffectGlowing();
this->AddChild( &m_sprActualBar[p][l] ); this->AddChild( &m_sprActualBar[p][r] );
} }
break; break;
} }
} }
// Chris: If EZ2 wants to hide these things, place them off screen using theme metrics
if( bNewRecord[p] ) if( bNewRecord[p] )
{ {
m_sprNewRecord[p].Load( THEME->GetPathTo("Graphics","evaluation new record") ); m_sprNewRecord[p].Load( THEME->GetPathTo("Graphics","evaluation new record") );
@@ -450,12 +424,12 @@ ScreenEvaluation::ScreenEvaluation( bool bSummary )
} }
} }
////////////////////////// //
// Init non-ResultMode specific displays. // Init non-ResultMode specific displays.
// Do this after Result-specific displays so that the text will draw on top of // Do this after Result-specific displays so that the text will draw on top of
// the bonus frame. // the bonus frame.
////////////////////////// //
for( l=0; l<NUM_JUDGE_LINES; l++ ) for( int l=0; l<NUM_JUDGE_LINES; l++ )
{ {
// EZ2 should hide these things by placing them off screen with theme metrics // EZ2 should hide these things by placing them off screen with theme metrics
m_sprJudgeLabels[l].Load( THEME->GetPathTo("Graphics","evaluation judge labels 1x8") ); m_sprJudgeLabels[l].Load( THEME->GetPathTo("Graphics","evaluation judge labels 1x8") );
@@ -467,7 +441,7 @@ ScreenEvaluation::ScreenEvaluation( bool bSummary )
} }
m_sprScoreLabel.Load( THEME->GetPathTo("Graphics","evaluation score labels") ); m_sprScoreLabel.Load( THEME->GetPathTo("Graphics","evaluation score labels") );
m_sprScoreLabel.SetState( m_ResultMode==RM_ONI ? 1 : 0 ); m_sprScoreLabel.SetState( m_ResultMode==RM_COURSE ? 1 : 0 );
m_sprScoreLabel.StopAnimating(); m_sprScoreLabel.StopAnimating();
m_sprScoreLabel.SetXY( SCORE_LABELS_X, SCORE_Y ); m_sprScoreLabel.SetXY( SCORE_LABELS_X, SCORE_Y );
m_sprScoreLabel.SetZoom( 1.0f ); m_sprScoreLabel.SetZoom( 1.0f );
@@ -483,26 +457,26 @@ ScreenEvaluation::ScreenEvaluation( bool bSummary )
{ {
m_textJudgeNumbers[l][p].LoadFromNumbers( THEME->GetPathTo("Numbers","evaluation judge numbers") ); m_textJudgeNumbers[l][p].LoadFromNumbers( THEME->GetPathTo("Numbers","evaluation judge numbers") );
m_textJudgeNumbers[l][p].TurnShadowOff(); m_textJudgeNumbers[l][p].TurnShadowOff();
m_textJudgeNumbers[l][p].SetXY( JUDGE_X(m_ResultMode==RM_ONI,p,l), JUDGE_Y(l) ); m_textJudgeNumbers[l][p].SetXY( JUDGE_X(m_ResultMode==RM_COURSE,p,l), JUDGE_Y(l) );
m_textJudgeNumbers[l][p].SetZoom( 1.0f ); m_textJudgeNumbers[l][p].SetZoom( 1.0f );
m_textJudgeNumbers[l][p].SetDiffuse( PlayerToColor(p) ); m_textJudgeNumbers[l][p].SetDiffuse( PlayerToColor(p) );
this->AddChild( &m_textJudgeNumbers[l][p] ); this->AddChild( &m_textJudgeNumbers[l][p] );
} }
m_textJudgeNumbers[0][p].SetText( ssprintf("%4d", iTapNoteScores[p][TNS_MARVELOUS]) ); m_textJudgeNumbers[0][p].SetText( ssprintf("%4d", stageStats.iTapNoteScores[p][TNS_MARVELOUS]) );
m_textJudgeNumbers[1][p].SetText( ssprintf("%4d", iTapNoteScores[p][TNS_PERFECT]) ); m_textJudgeNumbers[1][p].SetText( ssprintf("%4d", stageStats.iTapNoteScores[p][TNS_PERFECT]) );
m_textJudgeNumbers[2][p].SetText( ssprintf("%4d", iTapNoteScores[p][TNS_GREAT]) ); m_textJudgeNumbers[2][p].SetText( ssprintf("%4d", stageStats.iTapNoteScores[p][TNS_GREAT]) );
m_textJudgeNumbers[3][p].SetText( ssprintf("%4d", iTapNoteScores[p][TNS_GOOD]) ); m_textJudgeNumbers[3][p].SetText( ssprintf("%4d", stageStats.iTapNoteScores[p][TNS_GOOD]) );
m_textJudgeNumbers[4][p].SetText( ssprintf("%4d", iTapNoteScores[p][TNS_BOO]) ); m_textJudgeNumbers[4][p].SetText( ssprintf("%4d", stageStats.iTapNoteScores[p][TNS_BOO]) );
m_textJudgeNumbers[5][p].SetText( ssprintf("%4d", iTapNoteScores[p][TNS_MISS]) ); m_textJudgeNumbers[5][p].SetText( ssprintf("%4d", stageStats.iTapNoteScores[p][TNS_MISS]) );
m_textJudgeNumbers[6][p].SetText( ssprintf("%4d", iHoldNoteScores[p][HNS_OK]) ); m_textJudgeNumbers[6][p].SetText( ssprintf("%4d", stageStats.iHoldNoteScores[p][HNS_OK]) );
m_textJudgeNumbers[7][p].SetText( ssprintf("%4d", iMaxCombo[p]) ); m_textJudgeNumbers[7][p].SetText( ssprintf("%4d", stageStats.iMaxCombo[p]) );
if( m_ResultMode==RM_ONI ) if( m_ResultMode==RM_COURSE )
m_ScoreDisplay[p].SetText( SecondsToTime(GAMESTATE->GetPlayerSurviveTime( (PlayerNumber)p )) ); m_ScoreDisplay[p].SetText( SecondsToTime(stageStats.fAliveSeconds[p]) );
else else
m_ScoreDisplay[p].SetScore( fScore[p] ); m_ScoreDisplay[p].SetScore( stageStats.fScore[p] );
} }
@@ -546,7 +520,7 @@ ScreenEvaluation::ScreenEvaluation( bool bSummary )
ASSERT(0); // invalid grade ASSERT(0); // invalid grade
} }
break; break;
case RM_ONI: case RM_COURSE:
case RM_ARCADE_SUMMARY: case RM_ARCADE_SUMMARY:
switch( max_grade ) switch( max_grade )
{ {
@@ -594,7 +568,7 @@ void ScreenEvaluation::TweenOnScreen()
float fOriginalX, fOriginalY; float fOriginalX, fOriginalY;
for( i=0; i<STAGES_TO_SHOW_IN_SUMMARY; i++ ) for( i=0; i<MAX_SONGS_TO_SHOW; i++ )
{ {
fOriginalY = m_BannerWithFrame[i].GetY(); fOriginalY = m_BannerWithFrame[i].GetY();
m_BannerWithFrame[i].SetY( fOriginalY + SCREEN_HEIGHT ); m_BannerWithFrame[i].SetY( fOriginalY + SCREEN_HEIGHT );
@@ -695,7 +669,7 @@ void ScreenEvaluation::TweenOffScreen()
{ {
int i, p; int i, p;
for( i=0; i<STAGES_TO_SHOW_IN_SUMMARY; i++ ) for( i=0; i<MAX_SONGS_TO_SHOW; i++ )
m_BannerWithFrame[i].FadeOff( 0, "foldy", MENU_ELEMENTS_TWEEN_TIME ); m_BannerWithFrame[i].FadeOff( 0, "foldy", MENU_ELEMENTS_TWEEN_TIME );
m_textStage.FadeOff( 0, "foldy", MENU_ELEMENTS_TWEEN_TIME ); m_textStage.FadeOff( 0, "foldy", MENU_ELEMENTS_TWEEN_TIME );
@@ -797,12 +771,16 @@ void ScreenEvaluation::HandleScreenMessage( const ScreenMessage SM )
void ScreenEvaluation::MenuLeft( PlayerNumber pn ) void ScreenEvaluation::MenuLeft( PlayerNumber pn )
{ {
m_Grades[pn].SettleQuickly(); // What is the purpose of this? I keep my feet on the pads and
// was wondering why the grades weren't spinning. -Chris
//m_Grades[pn].SettleQuickly();
} }
void ScreenEvaluation::MenuRight( PlayerNumber pn ) void ScreenEvaluation::MenuRight( PlayerNumber pn )
{ {
m_Grades[pn].SettleQuickly(); // What is the purpose of this? I keep my feet on the pads and
// was wondering why the grades weren't spinning. -Chris
//m_Grades[pn].SettleQuickly();
} }
void ScreenEvaluation::MenuBack( PlayerNumber pn ) void ScreenEvaluation::MenuBack( PlayerNumber pn )
@@ -851,9 +829,8 @@ void ScreenEvaluation::MenuStart( PlayerNumber pn )
m_Menu.TweenOffScreenToBlack( SM_GoToMusicScroll, false ); m_Menu.TweenOffScreenToBlack( SM_GoToMusicScroll, false );
} }
// GAMESTATE->m_iCurrentStageIndex++; // Increment the stage counter.
// Increment the stage counter.
// GAMESTATE->m_vPassedStageStats.push_back( GAMESTATE->m_CurStageStats ); // Save this stage's stats
GAMESTATE->m_iCurrentStageIndex++;
} }
+5 -3
View File
@@ -22,7 +22,7 @@
const int NUM_JUDGE_LINES = 8; // marvelous, perfect, great, good, boo, miss, ok, max_combo const int NUM_JUDGE_LINES = 8; // marvelous, perfect, great, good, boo, miss, ok, max_combo
const int STAGES_TO_SHOW_IN_SUMMARY = 3; // only show the latest three stages in a summary const int MAX_SONGS_TO_SHOW = 5; // In summary, we show last 3 stages, plus extra stages if passed
class ScreenEvaluation : public Screen class ScreenEvaluation : public Screen
@@ -42,12 +42,12 @@ public:
virtual void MenuStart( PlayerNumber pn ); virtual void MenuStart( PlayerNumber pn );
protected: protected:
enum ResultMode { RM_ARCADE_STAGE, RM_ARCADE_SUMMARY, RM_ONI }; enum ResultMode { RM_ARCADE_STAGE, RM_ARCADE_SUMMARY, RM_COURSE };
ResultMode m_ResultMode; ResultMode m_ResultMode;
MenuElements m_Menu; MenuElements m_Menu;
BannerWithFrame m_BannerWithFrame[STAGES_TO_SHOW_IN_SUMMARY]; BannerWithFrame m_BannerWithFrame[MAX_SONGS_TO_SHOW];
BitmapText m_textStage; BitmapText m_textStage;
DifficultyIcon m_DifficultyIcon[NUM_PLAYERS]; DifficultyIcon m_DifficultyIcon[NUM_PLAYERS];
@@ -78,6 +78,8 @@ protected:
Sprite m_sprNewRecord[NUM_PLAYERS]; Sprite m_sprNewRecord[NUM_PLAYERS];
bool m_bGoToNameEntry;
bool m_bTryExtraStage; bool m_bTryExtraStage;
Sprite m_sprTryExtraStage; Sprite m_sprTryExtraStage;
}; };
+44 -50
View File
@@ -116,10 +116,9 @@ ScreenGameplay::ScreenGameplay( bool bDemonstration )
SOUNDMAN->StopMusic(); SOUNDMAN->StopMusic();
/* It's OK to operate on GAMESTATE here, but not in the constructor */ GAMESTATE->m_CurStageStats = StageStats(); // clear values
GAMESTATE->ResetStageStatistics(); // clear values
// Update possible dance points // Fill in m_CurStageStats
for( p=0; p<NUM_PLAYERS; p++ ) for( p=0; p<NUM_PLAYERS; p++ )
{ {
if( !GAMESTATE->IsPlayerEnabled(p) ) if( !GAMESTATE->IsPlayerEnabled(p) )
@@ -129,14 +128,20 @@ ScreenGameplay::ScreenGameplay( bool bDemonstration )
switch( GAMESTATE->m_PlayMode ) 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_pCurNotes[p]->GetNoteData( &notedata );
GAMESTATE->m_iPossibleDancePoints[p] = notedata.GetPossibleDancePoints(); GAMESTATE->m_CurStageStats.iPossibleDancePoints[p] = notedata.GetPossibleDancePoints();
break; break;
case PLAY_MODE_NONSTOP: case PLAY_MODE_NONSTOP:
case PLAY_MODE_ONI: case PLAY_MODE_ONI:
case PLAY_MODE_ENDLESS: case PLAY_MODE_ENDLESS:
{ {
GAMESTATE->m_iPossibleDancePoints[p] = 0; GAMESTATE->m_CurStageStats.pSong = NULL;
GAMESTATE->m_CurStageStats.iMeter[p] = 0;
GAMESTATE->m_CurStageStats.iPossibleDancePoints[p] = 0;
Course* pCourse = GAMESTATE->m_pCurCourse; Course* pCourse = GAMESTATE->m_pCurCourse;
vector<Song*> apSongs; vector<Song*> apSongs;
@@ -146,9 +151,10 @@ ScreenGameplay::ScreenGameplay( bool bDemonstration )
for( unsigned i=0; i<apNotes.size(); i++ ) for( unsigned i=0; i<apNotes.size(); i++ )
{ {
GAMESTATE->m_CurStageStats.iMeter[p] += apNotes[i]->GetMeter();
apNotes[i]->GetNoteData( &notedata ); apNotes[i]->GetNoteData( &notedata );
int iPossibleDancePoints = notedata.GetPossibleDancePoints(); int iPossibleDancePoints = notedata.GetPossibleDancePoints();
GAMESTATE->m_iPossibleDancePoints[p] += iPossibleDancePoints; GAMESTATE->m_CurStageStats.iPossibleDancePoints[p] += iPossibleDancePoints;
} }
} }
break; break;
@@ -499,7 +505,7 @@ bool ScreenGameplay::IsLastSong()
CStringArray asModifiers; CStringArray asModifiers;
pCourse->GetSongAndNotesForCurrentStyle( apSongs, apNotes, asModifiers, true ); pCourse->GetSongAndNotesForCurrentStyle( apSongs, apNotes, asModifiers, true );
return unsigned(GAMESTATE->m_iSongsIntoCourse) >= apSongs.size(); // there are no more songs left return unsigned(GAMESTATE->m_CurStageStats.iSongsPassed) >= apSongs.size(); // there are no more songs left
} }
break; break;
default: default:
@@ -523,9 +529,9 @@ void ScreenGameplay::LoadNextSong( bool bFirstLoad )
int p; int p;
for( p=0; p<NUM_PLAYERS; p++ ) for( p=0; p<NUM_PLAYERS; p++ )
{ {
m_textCourseSongNumber[p].SetText( ssprintf("%d", GAMESTATE->m_iSongsBeforeFail[p]+1) ); m_textCourseSongNumber[p].SetText( ssprintf("%d", GAMESTATE->m_CurStageStats.iSongsPassed[p]+1) );
// If it's the first song, record the options the player selected for later. // If it's the first song, record the options the player selected for later.
if (GAMESTATE->m_iSongsIntoCourse == 0) if( GAMESTATE->m_CurStageStats.iSongsPassed[p] == 0 )
GAMESTATE->m_SelectedOptions[p] = GAMESTATE->m_PlayerOptions[p]; GAMESTATE->m_SelectedOptions[p] = GAMESTATE->m_PlayerOptions[p];
} }
Course* pCourse = GAMESTATE->m_pCurCourse; Course* pCourse = GAMESTATE->m_pCurCourse;
@@ -535,7 +541,10 @@ void ScreenGameplay::LoadNextSong( bool bFirstLoad )
pCourse->GetSongAndNotesForCurrentStyle( apSongs, apNotes, asModifiers, true ); pCourse->GetSongAndNotesForCurrentStyle( apSongs, apNotes, asModifiers, true );
int iPlaySongIndex = GAMESTATE->m_iSongsIntoCourse; 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(); iPlaySongIndex %= apSongs.size();
GAMESTATE->m_pCurSong = apSongs[iPlaySongIndex]; GAMESTATE->m_pCurSong = apSongs[iPlaySongIndex];
@@ -572,7 +581,7 @@ void ScreenGameplay::LoadNextSong( bool bFirstLoad )
m_sprOniGameOver[p].SetY( SCREEN_TOP - m_sprOniGameOver[p].GetZoomedHeight()/2 ); m_sprOniGameOver[p].SetY( SCREEN_TOP - m_sprOniGameOver[p].GetZoomedHeight()/2 );
m_sprOniGameOver[p].SetDiffuse( RageColor(1,1,1,0) ); // 0 alpha so we don't waste time drawing while not visible m_sprOniGameOver[p].SetDiffuse( RageColor(1,1,1,0) ); // 0 alpha so we don't waste time drawing while not visible
if( GAMESTATE->m_SongOptions.m_LifeType == SongOptions::LIFE_BATTERY && GAMESTATE->m_fSecondsBeforeFail[p] != -1 ) // already failed if( GAMESTATE->m_SongOptions.m_LifeType==SongOptions::LIFE_BATTERY && GAMESTATE->m_CurStageStats.bFailed[p] ) // already failed
ShowOniGameOver((PlayerNumber)p); ShowOniGameOver((PlayerNumber)p);
@@ -732,6 +741,13 @@ void ScreenGameplay::Update( float fDeltaTime )
{ {
case STATE_DANCING: case STATE_DANCING:
//
// Update players' alive time
//
for( int p=0; p<NUM_PLAYERS; p++ )
if( GAMESTATE->IsPlayerEnabled(p) )
GAMESTATE->m_CurStageStats.fAliveSeconds[p] += fDeltaTime;
// //
// Check for end of song // Check for end of song
// //
@@ -758,8 +774,8 @@ void ScreenGameplay::Update( float fDeltaTime )
// check for individual fail // check for individual fail
for ( pn=0; pn<NUM_PLAYERS; pn++ ) for ( pn=0; pn<NUM_PLAYERS; pn++ )
{ {
if ( m_pLifeMeter[pn]->IsFailing() && GAMESTATE->m_fSecondsBeforeFail[pn] == -1) if ( m_pLifeMeter[pn]->IsFailing() && !GAMESTATE->m_CurStageStats.bFailed[pn] )
GAMESTATE->m_fSecondsBeforeFail[pn] = GAMESTATE->GetElapsedSeconds(); GAMESTATE->m_CurStageStats.bFailed[pn] = true; // fail
} }
break; break;
@@ -769,19 +785,19 @@ void ScreenGameplay::Update( float fDeltaTime )
else m_Background.TurnDangerOff(); else m_Background.TurnDangerOff();
// check for individual fail // check for individual fail
for( pn=0; pn<NUM_PLAYERS; pn++ ) { for( pn=0; pn<NUM_PLAYERS; pn++ )
{
if( !GAMESTATE->IsPlayerEnabled(pn) ) if( !GAMESTATE->IsPlayerEnabled(pn) )
continue; continue;
if( !m_pLifeMeter[pn]->IsFailing()) if( !m_pLifeMeter[pn]->IsFailing())
continue; /* hasn't failed */ continue; /* isn't failing */
if( GAMESTATE->m_CurStageStats.bFailed[pn] )
if( GAMESTATE->m_fSecondsBeforeFail[pn] != -1 )
continue; /* failed and is already dead */ continue; /* failed and is already dead */
if( !AllFailedEarlier() ) // if not the last one to fail if( !AllFailedEarlier() ) // if not the last one to fail
{ {
// kill them! // kill them!
GAMESTATE->m_fSecondsBeforeFail[pn] = GAMESTATE->GetElapsedSeconds(); GAMESTATE->m_CurStageStats.bFailed[pn] = true;
m_soundOniDie.PlayRandom(); m_soundOniDie.PlayRandom();
ShowOniGameOver((PlayerNumber)pn); ShowOniGameOver((PlayerNumber)pn);
m_Player[pn].Init(); // remove all notes and scoring m_Player[pn].Init(); // remove all notes and scoring
@@ -1169,38 +1185,29 @@ void ScreenGameplay::HandleScreenMessage( const ScreenMessage SM )
for( int r=0; r<NUM_RADAR_CATEGORIES; r++ ) for( int r=0; r<NUM_RADAR_CATEGORIES; r++ )
{ {
RadarCategory rc = (RadarCategory)r; RadarCategory rc = (RadarCategory)r;
GAMESTATE->m_fRadarPossible[p][r] = NoteDataUtil::GetRadarValue( m_Player[p], rc, GAMESTATE->m_pCurSong->m_fMusicLengthSeconds ); GAMESTATE->m_CurStageStats.fRadarPossible[p][r] = NoteDataUtil::GetRadarValue( m_Player[p], rc, GAMESTATE->m_pCurSong->m_fMusicLengthSeconds );
GAMESTATE->m_fRadarActual[p][r] = m_Player[p].GetActualRadarValue( rc, GAMESTATE->m_pCurSong->m_fMusicLengthSeconds ); GAMESTATE->m_CurStageStats.fRadarActual[p][r] = m_Player[p].GetActualRadarValue( rc, GAMESTATE->m_pCurSong->m_fMusicLengthSeconds );
} }
} }
} }
GAMESTATE->m_apSongsPlayed.push_back( GAMESTATE->m_pCurSong );
GAMESTATE->m_iSongsIntoCourse++;
for( p=0; p<NUM_PLAYERS; p++ ) for( p=0; p<NUM_PLAYERS; p++ )
if( GAMESTATE->IsPlayerEnabled(p) ) if( GAMESTATE->IsPlayerEnabled(p) && !GAMESTATE->m_CurStageStats.bFailed[p] )
if( !m_pLifeMeter[p]->FailedEarlier() ) GAMESTATE->m_CurStageStats.iSongsPassed[p]++;
GAMESTATE->m_iSongsBeforeFail[p]++;
if( !IsLastSong() ) if( !IsLastSong() )
{ {
for( int p=0; p<NUM_PLAYERS; p++ ) for( int p=0; p<NUM_PLAYERS; p++ )
if( GAMESTATE->IsPlayerEnabled(p) ) if( GAMESTATE->IsPlayerEnabled(p) && !GAMESTATE->m_CurStageStats.bFailed[p] )
if( !m_pLifeMeter[p]->FailedEarlier() ) m_pLifeMeter[p]->OnSongEnded(); // give a little life back between stages
m_pLifeMeter[p]->SongEnded(); // let the oni life meter give them back a life
m_OniFade.CloseWipingRight( SM_BeginLoadingNextSong ); m_OniFade.CloseWipingRight( SM_BeginLoadingNextSong );
} }
else // IsLastSong else // IsLastSong
{ {
if( m_DancingState == STATE_OUTRO ) // gameplay already ended if( m_DancingState == STATE_OUTRO ) // gameplay already ended
return; // ignore return; // ignore
m_DancingState = STATE_OUTRO; m_DancingState = STATE_OUTRO;
GAMESTATE->AccumulateStageStatistics(); // accumulate values for final evaluation
if( GAMESTATE->m_SongOptions.m_FailType == SongOptions::FAIL_END_OF_SONG && AllFailedEarlier() ) if( GAMESTATE->m_SongOptions.m_FailType == SongOptions::FAIL_END_OF_SONG && AllFailedEarlier() )
{ {
this->SendScreenMessage( SM_BeginFailed, 0 ); this->SendScreenMessage( SM_BeginFailed, 0 );
@@ -1210,23 +1217,10 @@ void ScreenGameplay::HandleScreenMessage( const ScreenMessage SM )
m_StarWipe.CloseWipingRight( SM_None ); m_StarWipe.CloseWipingRight( SM_None );
// do they deserve an extra stage? // do they deserve an extra stage?
bool bTryExtraStage = GAMESTATE->HasEarnedExtraStage();
bool bTryExtraStage = false;
if( (GAMESTATE->IsFinalStage() || GAMESTATE->IsExtraStage()) )
{
for( p=0; p<NUM_PLAYERS; p++ )
{
if( !GAMESTATE->IsPlayerEnabled( (PlayerNumber)p ) )
continue; // skip
if( GAMESTATE->m_pCurNotes[p]->GetDifficulty() == DIFFICULTY_HARD && GAMESTATE->GetCurrentGrade((PlayerNumber)p) >= GRADE_AA )
bTryExtraStage = true;
}
}
if( PREFSMAN->m_bEventMode ) if( PREFSMAN->m_bEventMode )
bTryExtraStage = false; bTryExtraStage = false;
if( bTryExtraStage ) if( bTryExtraStage )
{ {
this->SendScreenMessage( SM_ShowTryExtraStage, 1 ); this->SendScreenMessage( SM_ShowTryExtraStage, 1 );
@@ -1458,11 +1452,11 @@ void ScreenGameplay::HandleScreenMessage( const ScreenMessage SM )
// show the survive time if extra stage // show the survive time if extra stage
if( GAMESTATE->IsExtraStage() || GAMESTATE->IsExtraStage2() ) if( GAMESTATE->IsExtraStage() || GAMESTATE->IsExtraStage2() )
{ {
float fMaxSurviveSeconds = -1; float fMaxSurviveSeconds = 0;
for( int p=0; p<NUM_PLAYERS; p++ ) for( int p=0; p<NUM_PLAYERS; p++ )
if( GAMESTATE->IsPlayerEnabled(p) ) if( GAMESTATE->IsPlayerEnabled(p) )
fMaxSurviveSeconds = max( fMaxSurviveSeconds, GAMESTATE->GetPlayerSurviveTime((PlayerNumber)p) ); fMaxSurviveSeconds = max( fMaxSurviveSeconds, GAMESTATE->m_CurStageStats.fAliveSeconds[p] );
ASSERT( fMaxSurviveSeconds != -1 ); ASSERT( fMaxSurviveSeconds > 0 );
m_textSurviveTime.SetText( "TIME " + SecondsToTime(fMaxSurviveSeconds) ); m_textSurviveTime.SetText( "TIME " + SecondsToTime(fMaxSurviveSeconds) );
m_textSurviveTime.BeginTweening( 0.3f ); // sleep m_textSurviveTime.BeginTweening( 0.3f ); // sleep
m_textSurviveTime.BeginTweening( 0.3f ); // fade in m_textSurviveTime.BeginTweening( 0.3f ); // fade in
+1 -1
View File
@@ -701,7 +701,7 @@ void ScreenSelectMusic::AfterNotesChange( PlayerNumber pn )
Notes* m_pNotes = GAMESTATE->m_pCurNotes[pn]; Notes* m_pNotes = GAMESTATE->m_pCurNotes[pn];
if( m_pNotes && SONGMAN->IsUsingMemoryCard(pn) ) if( m_pNotes && SONGMAN->IsUsingMemoryCard(pn) )
m_HighScore[pn].SetScore( (float)m_pNotes->m_MemCardScores[pn].iScore ); m_HighScore[pn].SetScore( m_pNotes->m_MemCardScores[pn].fScore );
m_DifficultyIcon[pn].SetFromNotes( pn, pNotes ); m_DifficultyIcon[pn].SetFromNotes( pn, pNotes );
if( pNotes && pNotes->IsAutogen() ) if( pNotes && pNotes->IsAutogen() )
+94 -11
View File
@@ -30,6 +30,8 @@ SongManager* SONGMAN = NULL; // global and accessable from anywhere in our progr
const CString CATEGORY_TOP_SCORE_FILE = "CategoryTopScores.dat"; const CString CATEGORY_TOP_SCORE_FILE = "CategoryTopScores.dat";
const CString COURSE_TOP_SCORE_FILE = "CourseTopScores.dat"; const CString COURSE_TOP_SCORE_FILE = "CourseTopScores.dat";
const int CATEGORY_TOP_SCORE_VERSION = 1;
const int COURSE_TOP_SCORE_VERSION = 1;
#define NUM_GROUP_COLORS THEME->GetMetricI("SongManager","NumGroupColors") #define NUM_GROUP_COLORS THEME->GetMetricI("SongManager","NumGroupColors")
@@ -210,7 +212,7 @@ void SongManager::InitMachineScoresFromDisk()
for( int j=0; j<NUM_HIGH_SCORE_CATEGORIES; j++ ) for( int j=0; j<NUM_HIGH_SCORE_CATEGORIES; j++ )
for( int k=0; k<NUM_HIGH_SCORE_LINES; k++ ) for( int k=0; k<NUM_HIGH_SCORE_LINES; k++ )
{ {
m_MachineScores[i][j][k].iScore = 573000; m_MachineScores[i][j][k].fScore = 573000;
m_MachineScores[i][j][k].sName = "STEP"; m_MachineScores[i][j][k].sName = "STEP";
} }
} }
@@ -218,25 +220,36 @@ void SongManager::InitMachineScoresFromDisk()
// Read category top scores // Read category top scores
{ {
FILE* fp = fopen( CATEGORY_TOP_SCORE_FILE, "r" ); FILE* fp = fopen( CATEGORY_TOP_SCORE_FILE, "r" );
if( fp )
{
int version;
fscanf(fp, "%d\n", &version );
if( version == CATEGORY_TOP_SCORE_VERSION )
{
for( int i=0; i<NUM_STYLES; i++ ) for( int i=0; i<NUM_STYLES; i++ )
for( int j=0; j<NUM_HIGH_SCORE_CATEGORIES; j++ ) for( int j=0; j<NUM_HIGH_SCORE_CATEGORIES; j++ )
for( int k=0; k<NUM_HIGH_SCORE_LINES; k++ ) for( int k=0; k<NUM_HIGH_SCORE_LINES; k++ )
if( fp && !feof(fp) ) if( fp && !feof(fp) )
{ {
char szName[256]; char szName[256];
fscanf(fp, "%d %[^\n]\n", &m_MachineScores[i][j][k].iScore, szName); fscanf(fp, "%f %[^\n]\n", &m_MachineScores[i][j][k].fScore, szName);
m_MachineScores[i][j][k].sName = szName; m_MachineScores[i][j][k].sName = szName;
} }
}
if( fp )
fclose(fp); fclose(fp);
} }
}
// Read course top scores // Read course top scores
{ {
FILE* fp = fopen( COURSE_TOP_SCORE_FILE, "r" ); FILE* fp = fopen( COURSE_TOP_SCORE_FILE, "r" );
if( fp )
{
int version;
fscanf(fp, "%d\n", &version );
if( version == COURSE_TOP_SCORE_VERSION )
{
while( fp && !feof(fp) ) while( fp && !feof(fp) )
{ {
char szPath[256]; char szPath[256];
@@ -260,10 +273,10 @@ void SongManager::InitMachineScoresFromDisk()
} }
} }
} }
}
if( fp )
fclose(fp); fclose(fp);
} }
}
} }
void SongManager::SaveMachineScoresToDisk() void SongManager::SaveMachineScoresToDisk()
@@ -271,16 +284,17 @@ void SongManager::SaveMachineScoresToDisk()
// Write category top scores // Write category top scores
{ {
FILE* fp = fopen( CATEGORY_TOP_SCORE_FILE, "w" ); FILE* fp = fopen( CATEGORY_TOP_SCORE_FILE, "w" );
if( fp )
{
fprintf(fp,"%d",CATEGORY_TOP_SCORE_VERSION);
for( int i=0; i<NUM_STYLES; i++ ) for( int i=0; i<NUM_STYLES; i++ )
for( int j=0; j<NUM_HIGH_SCORE_CATEGORIES; j++ ) for( int j=0; j<NUM_HIGH_SCORE_CATEGORIES; j++ )
for( int k=0; k<NUM_HIGH_SCORE_LINES; k++ ) for( int k=0; k<NUM_HIGH_SCORE_LINES; k++ )
if( fp ) if( fp )
fprintf(fp, "%d %s\n", m_MachineScores[i][j][k].iScore, m_MachineScores[i][j][k].sName.c_str()); fprintf(fp, "%f %s\n", m_MachineScores[i][j][k].fScore, m_MachineScores[i][j][k].sName.c_str());
if( fp )
fclose(fp); fclose(fp);
} }
}
// Write course top scores // Write course top scores
{ {
@@ -288,6 +302,7 @@ void SongManager::SaveMachineScoresToDisk()
if( fp ) if( fp )
{ {
fprintf(fp,"%d",COURSE_TOP_SCORE_VERSION);
for( unsigned i=0; i<m_pCourses.size(); i++ ) // foreach course for( unsigned i=0; i<m_pCourses.size(); i++ ) // foreach course
{ {
Course* pCourse = m_pCourses[i]; Course* pCourse = m_pCourses[i];
@@ -616,3 +631,71 @@ bool SongManager::IsUsingMemoryCard( PlayerNumber pn )
{ {
return true; return true;
} }
bool SongManager::IsNewMachineRecord( HighScoreCategory hsc, float fScore ) const // return true if this is would be a new machine record
{
for( int i=0; i<NUM_HIGH_SCORE_LINES; i++ )
{
const MachineScore& hs = m_MachineScores[GAMESTATE->m_CurStyle][hsc][i];
if( fScore > hs.fScore )
return true;
}
return false;
}
struct MachineScoreAndPlayerNumber : public SongManager::MachineScore
{
PlayerNumber pn;
static int CompareDescending( const MachineScoreAndPlayerNumber &hs1, const MachineScoreAndPlayerNumber &hs2 )
{
if( hs1.fScore > hs2.fScore ) return -1;
else if( hs1.fScore == hs2.fScore ) return 0;
else return +1;
}
static void SortDescending( vector<MachineScoreAndPlayerNumber>& vHSout )
{
sort( vHSout.begin(), vHSout.end(), CompareDescending );
}
};
void SongManager::AddMachineRecord( HighScoreCategory hsc, float fScore[NUM_PLAYERS], int iNewRecordIndexOut[NUM_PLAYERS] ) // set iNewRecordIndex = -1 if not a new record
{
vector<MachineScoreAndPlayerNumber> vHS;
for( int p=0; p<NUM_PLAYERS; p++ )
{
iNewRecordIndexOut[p] = -1;
if( !GAMESTATE->IsPlayerEnabled(p) )
continue; // skip
MachineScoreAndPlayerNumber hs;
hs.fScore = fScore[p];
hs.sName = ""; // this must be filled in later!
hs.pn = (PlayerNumber)p;
vHS.push_back( hs );
}
// 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
MachineScoreAndPlayerNumber::SortDescending( vHS );
for( unsigned i=0; i<vHS.size(); i++ )
{
MachineScoreAndPlayerNumber& newHS = vHS[i];
MachineScore* machineScores = m_MachineScores[GAMESTATE->m_CurStyle][GAMESTATE->m_PreferredDifficulty[newHS.pn]];
for( int i=0; i<NUM_HIGH_SCORE_LINES; i++ )
{
if( newHS.fScore > machineScores[i].fScore )
{
// We found the insert point. Shift down.
for( int j=i+1; j<NUM_HIGH_SCORE_LINES; j++ )
machineScores[j] = machineScores[j-1];
// insert
machineScores[i] = newHS;
iNewRecordIndexOut[newHS.pn] = i;
}
}
}
}
+13 -7
View File
@@ -71,18 +71,24 @@ public:
// //
// High scores // High scores
// //
struct HighScore
{
int iScore;
CString sName;
};
HighScore m_MachineScores[NUM_STYLES][NUM_HIGH_SCORE_CATEGORIES][NUM_HIGH_SCORE_LINES];
void InitMachineScoresFromDisk(); void InitMachineScoresFromDisk();
void SaveMachineScoresToDisk(); void SaveMachineScoresToDisk();
bool MemoryCardIsInserted( PlayerNumber pn );
bool IsUsingMemoryCard( PlayerNumber pn ); bool IsUsingMemoryCard( PlayerNumber pn );
void LoadMemoryCardScores( PlayerNumber pn );
void SaveMemoryCardScores( PlayerNumber pn );
struct MachineScore
{
float fScore;
CString sName;
} m_MachineScores[NUM_STYLES][NUM_HIGH_SCORE_CATEGORIES][NUM_HIGH_SCORE_LINES];
bool IsNewMachineRecord( HighScoreCategory hsc, float fScore ) const; // return true if this is would be a new machine record
void AddMachineRecord( HighScoreCategory hsc, float fScore[NUM_PLAYERS], int iNewRecordIndexOut[NUM_PLAYERS] ); // set iNewRecordIndex = -1 if not a new record
protected: protected:
void LoadStepManiaSongDir( CString sDir, LoadingWindow *ld ); void LoadStepManiaSongDir( CString sDir, LoadingWindow *ld );
void LoadDWISongDir( CString sDir ); void LoadDWISongDir( CString sDir );
+48
View File
@@ -0,0 +1,48 @@
#include "stdafx.h"
/*
-----------------------------------------------------------------------------
Class: StageStats
Desc: See header.
Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved.
Chris Danford
-----------------------------------------------------------------------------
*/
#include "StageStats.h"
StageStats::StageStats()
{
memset( this, 0, sizeof(StageStats) );
}
void StageStats::operator+=( const StageStats& other )
{
pSong = NULL; // meaningless
memset( fAliveSeconds, 0, sizeof(fAliveSeconds) );
for( int p=0; p<NUM_PLAYERS; p++ )
{
iMeter[p] += other.iMeter[p];
fAliveSeconds[p] += other.fAliveSeconds[p];
bFailed[p] |= other.bFailed[p];
iPossibleDancePoints[p] += other.iPossibleDancePoints[p];
iActualDancePoints[p] += other.iPossibleDancePoints[p];
for( int t=0; t<NUM_TAP_NOTE_SCORES; t++ )
iTapNoteScores[p][t] += other.iTapNoteScores[p][t];
for( int h=0; h<NUM_HOLD_NOTE_SCORES; h++ )
iHoldNoteScores[p][h] += iHoldNoteScores[p][h];
iMaxCombo[p] += other.iMaxCombo[p];
fScore[p] += other.fScore[p];
for( int r=0; r<NUM_RADAR_VALUES; r++ )
{
fRadarPossible[p][r] += other.fRadarPossible[p][r];
fRadarActual[p][r] += other.fRadarActual[p][r];
}
fSecondsBeforeFail[p] += other.fSecondsBeforeFail[p];
iSongsPassed[p] += other.iSongsPassed[p];
}
}
+40
View File
@@ -0,0 +1,40 @@
#ifndef StageStats_H
#define StageStats_H
/*
-----------------------------------------------------------------------------
Class: StageStats
Desc: Contains statistics for one stage of play - either one song, or a whole course.
Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved.
Chris Danford
-----------------------------------------------------------------------------
*/
#include "GameConstantsAndTypes.h" // for NUM_PLAYERS
class Song;
struct StageStats
{
StageStats();
void operator+=( const StageStats& other ); // accumulate
Song* pSong;
int iMeter[NUM_PLAYERS];
float fAliveSeconds[NUM_PLAYERS]; // how far into the music did they last before failing? Updated by Gameplay.
bool bFailed[NUM_PLAYERS]; // true if they have failed at any point during the song
int iPossibleDancePoints[NUM_PLAYERS];
int iActualDancePoints[NUM_PLAYERS];
int iTapNoteScores[NUM_PLAYERS][NUM_TAP_NOTE_SCORES];
int iHoldNoteScores[NUM_PLAYERS][NUM_HOLD_NOTE_SCORES];
int iMaxCombo[NUM_PLAYERS];
float fScore[NUM_PLAYERS];
float fRadarPossible[NUM_PLAYERS][NUM_RADAR_VALUES]; // filled in by ScreenGameplay on start of notes
float fRadarActual[NUM_PLAYERS][NUM_RADAR_VALUES]; // filled in by ScreenGameplay on start of notes
float fSecondsBeforeFail[NUM_PLAYERS]; // -1 means didn't/hasn't failed
int iSongsPassed[NUM_PLAYERS]; // For course, this is the number of songs that the player has passed
};
#endif
+6
View File
@@ -604,6 +604,12 @@ cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\
<File <File
RelativePath="SongOptions.h"> RelativePath="SongOptions.h">
</File> </File>
<File
RelativePath="StageStats.cpp">
</File>
<File
RelativePath="StageStats.h">
</File>
<File <File
RelativePath="Style.h"> RelativePath="Style.h">
</File> </File>