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
/////////////////////////
change space so gray arrows aren't so small
groove radar goes wild when random selected
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].fSurviveTime = 0;
m_MemCardScores[i][j][k].sName = "STEP";
}
}
@@ -302,10 +301,91 @@ int Course::GetNumStages() const
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
//
static int CompareCoursePointersByDifficulty(const Course* pCourse1, const Course* pCourse2)
{
return pCourse1->GetNumStages() < pCourse2->GetNumStages();
+14 -4
View File
@@ -60,14 +60,24 @@ public:
// Statistics
int m_iNumTimesPlayed;
struct HighScore
struct MachineScore
{
int iDancePoints;
float fSurviveTime;
CString sName;
};
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];
} m_MachineScores[NUM_STYLES][NUM_DIFFICULTIES][NUM_HIGH_SCORE_LINES]; // sorted highest to lowest by iDancePoints
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:
void Shuffle();
+12
View File
@@ -55,3 +55,15 @@ RageColor PlayerToColor( int 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
///////////////////////////
//
enum TapNoteScore {
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_B, // 4-6 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
};
HighScoreCategory AverageMeterToHighScoreCategory( float fAverageMeter );
const int NUM_HIGH_SCORE_LINES = 5;
#endif
+31 -151
View File
@@ -67,68 +67,18 @@ void GameState::Reset()
m_bDemonstration = false;
m_iCurrentStageIndex = 0;
m_pCurSong = NULL;
for( p=0; p<NUM_PLAYERS; p++ )
m_pCurNotes[p] = NULL;
m_pCurCourse = NULL;
m_fMusicSeconds = 0;
m_fSongBeat = 0;
m_fCurBPS = 0;
m_bFreeze = 0;
m_apSongsPlayed.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;
}
}
m_CurStageStats = StageStats();
m_vPassedStageStats.clear();
for( p=0; p<NUM_PLAYERS; p++ )
m_PlayerOptions[p] = PlayerOptions();
@@ -143,65 +93,6 @@ void GameState::ResetMusicStatistics()
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()
{
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 )
{
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;
/* Based on the percentage of your total "Dance Points" to the maximum
@@ -344,19 +208,19 @@ Grade GameState::GetCurrentGrade( PlayerNumber pn )
* Less - D
* Fail - E
*/
float fPercentDancePoints = m_iActualDancePoints[pn] / (float)m_iPossibleDancePoints[pn];
fPercentDancePoints = max( fPercentDancePoints, 0 );
LOG->Trace( "iActualDancePoints: %i", m_iActualDancePoints[pn] );
LOG->Trace( "iPossibleDancePoints: %i", m_iPossibleDancePoints[pn] );
float fPercentDancePoints = m_CurStageStats.iActualDancePoints[pn] / (float)m_CurStageStats.iPossibleDancePoints[pn];
fPercentDancePoints = max( 0, fPercentDancePoints );
LOG->Trace( "iActualDancePoints: %i", m_CurStageStats.iActualDancePoints[pn] );
LOG->Trace( "iPossibleDancePoints: %i", m_CurStageStats.iPossibleDancePoints[pn] );
LOG->Trace( "fPercentDancePoints: %f", fPercentDancePoints );
// check for "AAAA"
if( m_TapNoteScores[pn][TNS_MARVELOUS] > 0 &&
m_TapNoteScores[pn][TNS_PERFECT] == 0 &&
m_TapNoteScores[pn][TNS_GREAT] == 0 &&
m_TapNoteScores[pn][TNS_GOOD] == 0 &&
m_TapNoteScores[pn][TNS_BOO] == 0 &&
m_TapNoteScores[pn][TNS_MISS] == 0 )
if( m_CurStageStats.iTapNoteScores[pn][TNS_MARVELOUS] > 0 &&
m_CurStageStats.iTapNoteScores[pn][TNS_PERFECT] == 0 &&
m_CurStageStats.iTapNoteScores[pn][TNS_GREAT] == 0 &&
m_CurStageStats.iTapNoteScores[pn][TNS_GOOD] == 0 &&
m_CurStageStats.iTapNoteScores[pn][TNS_BOO] == 0 &&
m_CurStageStats.iTapNoteScores[pn][TNS_MISS] == 0 )
return GRADE_AAAA;
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 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 "Style.h"
#include "Grade.h"
#include "StageStats.h"
class Song;
@@ -39,13 +40,13 @@ public:
Game m_CurGame;
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_bSideIsJoined[2]; // left side, right side
int m_iCoins;
PlayerNumber m_MasterPlayerNumber;
bool m_bSideIsJoined[NUM_PLAYERS]; // left side, right side
int m_iCoins; // not "credits"
PlayerNumber m_MasterPlayerNumber; // used in Styles where one player controls both sides
int GetNumSidesJoined()
{
int iNumSidesJoined = 0;
for( int c=0; c<2; c++ )
for( int c=0; c<NUM_PLAYERS; c++ )
if( m_bSideIsJoined[c] )
iNumSidesJoined++; // left side, and right side
return iNumSidesJoined;
@@ -58,11 +59,11 @@ public:
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
CString m_sLoadingMessage;
CString m_sPreferredGroup;
CString m_sLoadingMessage; // used in loading screen
CString m_sPreferredGroup; // "ALL MUSIC" denotes no preferred group
Difficulty m_PreferredDifficulty[NUM_PLAYERS];
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_bDemonstration; // ScreenGameplay does special stuff when this is true
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.
//
@@ -95,55 +96,16 @@ public:
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];
int m_iActualDancePoints[NUM_PLAYERS];
int m_TapNoteScores[NUM_PLAYERS][NUM_TAP_NOTE_SCORES];
int m_HoldNoteScores[NUM_PLAYERS][NUM_HOLD_NOTE_SCORES];
int m_iMaxCombo[NUM_PLAYERS];
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
StageStats m_CurStageStats; // current stage (not necessarily passed if Extra Stage)
vector<StageStats> m_vPassedStageStats; // Only useful in Arcade for final evaluation
// A song is only inserted here if at least one player passed.
// StageStats are added by the Evaluation screen
Grade GetCurrentGrade( PlayerNumber pn ); // grade so far
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_SelectedOptions[NUM_PLAYERS]; // Keep track of player-selected options for
@@ -151,7 +113,7 @@ public:
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 Update( float fDeltaTime ) { ActorFrame::Update(fDeltaTime); };
virtual void SongEnded() {};
virtual void OnSongEnded() {};
/* Change life after receiving a tap note grade. This *is* called for
* the head of hold notes. */
virtual void ChangeLife( TapNoteScore score ) = 0;
+3 -3
View File
@@ -83,7 +83,7 @@ void LifeMeterBattery::Load( PlayerNumber pn )
Refresh();
}
void LifeMeterBattery::SongEnded()
void LifeMeterBattery::OnSongEnded()
{
if( m_bFailedEarlier )
return;
@@ -145,8 +145,8 @@ void LifeMeterBattery::ChangeLife( HoldNoteScore score, TapNoteScore tscore )
void LifeMeterBattery::OnDancePointsChange()
{
int iActualDancePoints = GAMESTATE->m_iActualDancePoints[m_PlayerNumber];
int iPossibleDancePoints = GAMESTATE->m_iPossibleDancePoints[m_PlayerNumber];
int iActualDancePoints = GAMESTATE->m_CurStageStats.iActualDancePoints[m_PlayerNumber];
int iPossibleDancePoints = GAMESTATE->m_CurStageStats.iPossibleDancePoints[m_PlayerNumber];
iPossibleDancePoints = max( 1, iPossibleDancePoints );
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 SongEnded();
virtual void OnSongEnded();
virtual void ChangeLife( TapNoteScore score );
virtual void ChangeLife( HoldNoteScore score, TapNoteScore tscore );
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++ )
{
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;
}
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;
return true;
}
+4 -5
View File
@@ -52,14 +52,13 @@ public:
// High scores;
int m_iNumTimesPlayed;
struct HighScore
struct MemCardScore
{
Grade grade;
int iScore;
};
HighScore m_MemCardScores[NUM_PLAYERS];
float fScore;
} 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();
+5 -5
View File
@@ -136,7 +136,7 @@ void Player::Load( PlayerNumber pn, NoteData* pNoteData, LifeMeter* pLM, ScoreDi
// copy note data
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();
/* The editor reuses Players ... so we really need to make sure everything
@@ -341,7 +341,7 @@ void Player::DrawPrimitives()
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
//LOG->Trace( "Player::HandlePlayerStep()" );
@@ -518,7 +518,7 @@ void Player::OnRowDestroyed( int iIndexThatWasSteppedOn )
{
HandleNoteScore( score, iNumNotesInThisRow ); // update score
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
@@ -616,7 +616,7 @@ void Player::HandleNoteScore( TapNoteScore score, int iNumTapsInRow )
m_ScoreKeeper->HandleNoteScore(score, iNumTapsInRow);
if (m_pScore)
m_pScore->SetScore(GAMESTATE->m_fScore[m_PlayerNumber]);
m_pScore->SetScore(GAMESTATE->m_CurStageStats.fScore[m_PlayerNumber]);
if( m_pLifeMeter ) {
m_pLifeMeter->ChangeLife( score );
@@ -636,7 +636,7 @@ void Player::HandleHoldNoteScore( HoldNoteScore score, TapNoteScore TapNoteScore
}
if (m_pScore)
m_pScore->SetScore(GAMESTATE->m_fScore[m_PlayerNumber]);
m_pScore->SetScore(GAMESTATE->m_CurStageStats.fScore[m_PlayerNumber]);
if( m_pLifeMeter ) {
if( score == HNS_NG ) {
+9 -5
View File
@@ -54,11 +54,11 @@ PrefsManager::PrefsManager()
m_iNumArcadeStages = 3;
m_bAutoPlay = false;
m_fJudgeWindowScale = 1.0f;
m_fJudgeWindowMarvelousSeconds = 0.023f;
m_fJudgeWindowPerfectSeconds = 0.043f;
m_fJudgeWindowGreatSeconds = 0.086f;
m_fJudgeWindowGoodSeconds = 0.129f;
m_fJudgeWindowBooSeconds = 0.172f;
m_fJudgeWindowMarvelousSeconds = 0.025f;
m_fJudgeWindowPerfectSeconds = 0.05f;
m_fJudgeWindowGreatSeconds = 0.10f;
m_fJudgeWindowGoodSeconds = 0.15f;
m_fJudgeWindowBooSeconds = 0.2f;
m_fLifeDifficultyScale = 1.0f;
m_iMovieDecodeMS = 2;
m_bUseBGIfNoBanner = false;
@@ -119,9 +119,11 @@ void PrefsManager::ReadGlobalPrefsFromDisk( bool bSwitchToLastPlayedGame )
ini.GetValueI( "Options", "NumArcadeStages", m_iNumArcadeStages );
ini.GetValueB( "Options", "AutoPlay", m_bAutoPlay );
ini.GetValueF( "Options", "JudgeWindowScale", m_fJudgeWindowScale );
ini.GetValueF( "Options", "JudgeWindowMarvelousSeconds",m_fJudgeWindowMarvelousSeconds );
ini.GetValueF( "Options", "JudgeWindowPerfectSeconds", m_fJudgeWindowPerfectSeconds );
ini.GetValueF( "Options", "JudgeWindowGreatSeconds", m_fJudgeWindowGreatSeconds );
ini.GetValueF( "Options", "JudgeWindowGoodSeconds", m_fJudgeWindowGoodSeconds );
ini.GetValueF( "Options", "JudgeWindowBooSeconds", m_fJudgeWindowBooSeconds );
ini.GetValueF( "Options", "LifeDifficultyScale", m_fLifeDifficultyScale );
ini.GetValueI( "Options", "MovieDecodeMS", m_iMovieDecodeMS );
ini.GetValueB( "Options", "UseBGIfNoBanner", m_bUseBGIfNoBanner );
@@ -184,9 +186,11 @@ void PrefsManager::SaveGlobalPrefsToDisk()
ini.SetValueI( "Options", "NumArcadeStages", m_iNumArcadeStages );
ini.SetValueB( "Options", "AutoPlay", m_bAutoPlay );
ini.SetValueF( "Options", "JudgeWindowScale", m_fJudgeWindowScale );
ini.SetValueF( "Options", "JudgeWindowMarvelousSeconds",m_fJudgeWindowMarvelousSeconds );
ini.SetValueF( "Options", "JudgeWindowPerfectSeconds", m_fJudgeWindowPerfectSeconds );
ini.SetValueF( "Options", "JudgeWindowGreatSeconds", m_fJudgeWindowGreatSeconds );
ini.SetValueF( "Options", "JudgeWindowGoodSeconds", m_fJudgeWindowGoodSeconds );
ini.SetValueF( "Options", "JudgeWindowBooSeconds", m_fJudgeWindowBooSeconds );
ini.SetValueF( "Options", "LifeDifficultyScale", m_fLifeDifficultyScale );
ini.SetValueI( "Options", "MovieDecodeMS", m_iMovieDecodeMS );
ini.SetValueB( "Options", "UseBGIfNoBanner", m_bUseBGIfNoBanner );
+1 -1
View File
@@ -50,7 +50,7 @@ void ScoreDisplayOni::Draw()
{
float fSecsIntoPlay;
if( GAMESTATE->IsPlayerEnabled(m_PlayerNumber) )
fSecsIntoPlay = GAMESTATE->GetPlayerSurviveTime(m_PlayerNumber);
fSecsIntoPlay = GAMESTATE->m_CurStageStats.fAliveSeconds[m_PlayerNumber];
else
fSecsIntoPlay = 0;
+5 -5
View File
@@ -42,7 +42,7 @@ void ScoreKeeperMAX2::AddScore( TapNoteScore score )
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 )
@@ -52,8 +52,8 @@ void ScoreKeeperMAX2::HandleNoteScore( TapNoteScore score, int iNumTapsInRow )
ASSERT( iNumTapsInRow >= 1 );
// update dance points for Oni lifemeter
GAMESTATE->m_iActualDancePoints[m_PlayerNumber] += iNumTapsInRow * TapNoteScoreToDancePoints( score );
GAMESTATE->m_TapNoteScores[m_PlayerNumber][score] += iNumTapsInRow;
GAMESTATE->m_CurStageStats.iActualDancePoints[m_PlayerNumber] += iNumTapsInRow * TapNoteScoreToDancePoints( score );
GAMESTATE->m_CurStageStats.iTapNoteScores[m_PlayerNumber][score] += iNumTapsInRow;
/*
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 )
{
// update dance points totals
GAMESTATE->m_HoldNoteScores[m_PlayerNumber][score] ++;
GAMESTATE->m_iActualDancePoints[m_PlayerNumber] += HoldNoteScoreToDancePoints( score );
GAMESTATE->m_CurStageStats.iHoldNoteScores[m_PlayerNumber][score] ++;
GAMESTATE->m_CurStageStats.iActualDancePoints[m_PlayerNumber] += HoldNoteScoreToDancePoints( score );
if( score == HNS_OK )
AddScore( TNS_PERFECT );
+128 -151
View File
@@ -115,12 +115,9 @@ ScreenEvaluation::ScreenEvaluation( bool bSummary )
{
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 depending on context.
///////////////////////////
//
// Set m_ResultMode. This enum will make our life easier later when we init different pieces.
//
switch( GAMESTATE->m_PlayMode )
{
case PLAY_MODE_ARCADE:
@@ -129,54 +126,42 @@ ScreenEvaluation::ScreenEvaluation( bool bSummary )
case PLAY_MODE_NONSTOP:
case PLAY_MODE_ONI:
case PLAY_MODE_ENDLESS:
m_ResultMode = RM_ONI;
m_ResultMode = RM_COURSE;
break;
default:
ASSERT(0);
}
///////////////////////////
// Figure out which statistics we're going to display
///////////////////////////
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 fPossibleRadarValues[NUM_PLAYERS][NUM_RADAR_CATEGORIES];
float fActualRadarValues[NUM_PLAYERS][NUM_RADAR_CATEGORIES];
//
// Figure out which statistics and songs we're going to display
//
StageStats stageStats;
vector<Song*> vSongsToShow;
switch( m_ResultMode )
{
case RM_ARCADE_SUMMARY:
COPY( iPossibleDancePoints, GAMESTATE->m_iAccumPossibleDancePoints );
COPY( iActualDancePoints, GAMESTATE->m_iAccumActualDancePoints );
COPY( iTapNoteScores, GAMESTATE->m_AccumTapNoteScores );
COPY( iHoldNoteScores, GAMESTATE->m_AccumHoldNoteScores );
COPY( iMaxCombo, GAMESTATE->m_iAccumMaxCombo );
COPY( fScore, GAMESTATE->m_fAccumScore );
COPY( fPossibleRadarValues, GAMESTATE->m_fAccumRadarPossible );
COPY( fActualRadarValues, GAMESTATE->m_fAccumRadarActual );
{
// Show stats only for the latest 3 normal songs + passed extra stages
int iNumSongsToThrowAway = max( 0, PREFSMAN->m_iNumArcadeStages-3 );
for( unsigned i=iNumSongsToThrowAway; i<GAMESTATE->m_vPassedStageStats.size(); i++ )
{
stageStats += GAMESTATE->m_vPassedStageStats[i];
vSongsToShow.push_back( GAMESTATE->m_vPassedStageStats[i].pSong );
}
}
break;
case RM_ARCADE_STAGE:
case RM_ONI:
COPY( iPossibleDancePoints, GAMESTATE->m_iPossibleDancePoints );
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 );
case RM_COURSE:
stageStats = GAMESTATE->m_CurStageStats;
break;
default:
ASSERT(0);
}
///////////////////////////
//
// Init the song banners depending on m_ResultMode
///////////////////////////
// EZ2 should hide these things by placing them off screen with theme metrics
//
switch( m_ResultMode )
{
case RM_ARCADE_STAGE:
@@ -205,31 +190,23 @@ ScreenEvaluation::ScreenEvaluation( bool bSummary )
break;
case RM_ARCADE_SUMMARY:
{
// crop down to 3
for( int p=0; p<NUM_PLAYERS; p++ )
for( unsigned i=0; i<vSongsToShow.size(); i++ )
{
if( GAMESTATE->m_apSongsPlayed.size() > STAGES_TO_SHOW_IN_SUMMARY )
GAMESTATE->m_apSongsPlayed.erase( GAMESTATE->m_apSongsPlayed.begin(), GAMESTATE->m_apSongsPlayed.begin() + (GAMESTATE->m_apSongsPlayed.size() - STAGES_TO_SHOW_IN_SUMMARY) );
}
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].LoadFromSong( vSongsToShow[i] );
float fBannerOffset = i - (vSongsToShow.size()-1)/2.0f;
m_BannerWithFrame[i].SetXY( BANNER_X + fBannerOffset*32, BANNER_Y + fBannerOffset*16 );
m_BannerWithFrame[i].SetZoom( 0.70f );
this->AddChild( &m_BannerWithFrame[i] );
}
}
break;
case RM_ONI:
case RM_COURSE:
m_BannerWithFrame[0].LoadFromCourse( GAMESTATE->m_pCurCourse );
m_BannerWithFrame[0].SetXY( BANNER_X, BANNER_Y );
this->AddChild( &m_BannerWithFrame[0] );
break;
default:
ASSERT(0);
}
@@ -243,7 +220,7 @@ ScreenEvaluation::ScreenEvaluation( bool bSummary )
);
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
continue; // skip
@@ -256,19 +233,16 @@ ScreenEvaluation::ScreenEvaluation( bool bSummary )
}
//
// Calculate grades
//
Grade grade[NUM_PLAYERS];
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;
continue;
}
grade[p] = GAMESTATE->GetCurrentGrade( (PlayerNumber)p );
else
grade[p] = GAMESTATE->GetCurrentGrade( (PlayerNumber)p );
}
Grade max_grade = GRADE_NO_DATA;
@@ -276,52 +250,53 @@ ScreenEvaluation::ScreenEvaluation( bool bSummary )
max_grade = max( max_grade, grade[p] );
////////////////////////
//
// update persistent statistics
////////////////////////
//
bool bNewRecord[NUM_PLAYERS];
for( p=0; p<NUM_PLAYERS; p++ )
bNewRecord[p] = false;
for( p=0; p<NUM_PLAYERS; p++ )
memset( bNewRecord, 0, sizeof(bNewRecord) );
m_bGoToNameEntry = false;
for( int p=0; p<NUM_PLAYERS; p++ )
{
if( !GAMESTATE->IsPlayerEnabled(p) )
continue;
if( grade[p] == GRADE_E )
continue;
if( !GAMESTATE->IsPlayerEnabled(p) || grade[p] == GRADE_E )
continue; // can't be a new record
switch( m_ResultMode )
{
case RM_ARCADE_STAGE:
Notes* pNotes = GAMESTATE->m_pCurNotes[p];
if( SONGMAN->IsUsingMemoryCard((PlayerNumber)p) )
bNewRecord[p] = pNotes->AddMemCardScore( (PlayerNumber)p, grade[p], (int)fScore[p] );
{
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:
{
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:
{
Course* pCourse = GAMESTATE->m_pCurCourse;
pCourse->IsNewMachineRecord( (PlayerNumber)p, stageStats.iActualDancePoints[p], stageStats.fAliveSeconds[p] );
m_bGoToNameEntry |= true;
}
break;
default:
ASSERT(0);
}
}
m_bTryExtraStage =
GAMESTATE->HasEarnedExtraStage() &&
m_ResultMode==RM_ARCADE_STAGE &&
!PREFSMAN->m_bEventMode;
m_bTryExtraStage = false;
if( (GAMESTATE->IsFinalStage() || GAMESTATE->IsExtraStage()) && m_ResultMode==RM_ARCADE_STAGE )
{
for( p=0; p<NUM_PLAYERS; p++ )
{
if( !GAMESTATE->IsPlayerEnabled( (PlayerNumber)p ) )
continue; // skip
if( GAMESTATE->m_pCurNotes[p]->GetDifficulty() == DIFFICULTY_HARD && grade[p] >= GRADE_AA )
m_bTryExtraStage = true;
}
}
if( PREFSMAN->m_bEventMode )
m_bTryExtraStage = false;
/////////////////////////////////
//
// Init ResultMode-specific displays
/////////////////////////////////
//
for( p=0; p<NUM_PLAYERS; p++ )
{
if( !GAMESTATE->IsPlayerEnabled( (PlayerNumber)p ) )
@@ -331,7 +306,7 @@ ScreenEvaluation::ScreenEvaluation( bool bSummary )
switch( m_ResultMode )
{
case RM_ONI:
case RM_COURSE:
{
m_sprPercentFrame[p].Load( THEME->GetPathTo("Graphics","evaluation percent frame") );
m_sprPercentFrame[p].StopAnimating();
@@ -356,8 +331,8 @@ ScreenEvaluation::ScreenEvaluation( bool bSummary )
m_textOniPercentSmall[p].SetEffectGlowing( 1.0f );
this->AddChild( &m_textOniPercentSmall[p] );
iPossibleDancePoints[p] = max( 1, iPossibleDancePoints[p] );
float fPercentDancePoints = iActualDancePoints[p] / (float)iPossibleDancePoints[p] + 0.0001f; // correct for rounding errors
stageStats.iPossibleDancePoints[p] = max( 1, stageStats.iPossibleDancePoints[p] );
float fPercentDancePoints = stageStats.iActualDancePoints[p] / (float)stageStats.iPossibleDancePoints[p] + 0.0001f; // correct for rounding errors
fPercentDancePoints = max( fPercentDancePoints, 0 );
int iPercentDancePointsLarge = int(fPercentDancePoints*100);
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].TurnShadowOff();
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] );
}
break;
@@ -405,42 +380,41 @@ ScreenEvaluation::ScreenEvaluation( bool bSummary )
m_sprBonusFrame[p].SetXY( BONUS_X(p), BONUS_Y );
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][l].SetState( p );
m_sprPossibleBar[p][l].SetHorizAlign( Actor::align_left );
m_sprPossibleBar[p][l].SetX( BAR_BASE_X(p) );
m_sprPossibleBar[p][l].SetY( BAR_START_Y + BAR_SPACING_Y*l );
m_sprPossibleBar[p][l].SetRotation( BAR_ROTATION(p) );
m_sprPossibleBar[p][l].SetZoomX( 0 );
m_sprPossibleBar[p][l].ZoomToHeight( BAR_HEIGHT );
m_sprPossibleBar[p][l].BeginTweening( 0.2f + l*0.1f ); // sleep
m_sprPossibleBar[p][l].BeginTweening( 0.5f ); // tween
m_sprPossibleBar[p][l].SetTweenZoomToWidth( BAR_WIDTH*fPossibleRadarValues[p][l] );
this->AddChild( &m_sprPossibleBar[p][l] );
m_sprPossibleBar[p][r].Load( THEME->GetPathTo("Graphics","evaluation bars possible 1x2") );
m_sprPossibleBar[p][r].SetState( p );
m_sprPossibleBar[p][r].SetHorizAlign( Actor::align_left );
m_sprPossibleBar[p][r].SetX( BAR_BASE_X(p) );
m_sprPossibleBar[p][r].SetY( BAR_START_Y + BAR_SPACING_Y*r );
m_sprPossibleBar[p][r].SetRotation( BAR_ROTATION(p) );
m_sprPossibleBar[p][r].SetZoomX( 0 );
m_sprPossibleBar[p][r].ZoomToHeight( BAR_HEIGHT );
m_sprPossibleBar[p][r].BeginTweening( 0.2f + r*0.1f ); // sleep
m_sprPossibleBar[p][r].BeginTweening( 0.5f ); // tween
m_sprPossibleBar[p][r].SetTweenZoomToWidth( BAR_WIDTH*stageStats.fRadarPossible[p][r] );
this->AddChild( &m_sprPossibleBar[p][r] );
m_sprActualBar[p][l].Load( THEME->GetPathTo("Graphics","evaluation bars actual 1x2") );
m_sprActualBar[p][l].SetState( p );
m_sprActualBar[p][l].StopAnimating();
m_sprActualBar[p][l].SetHorizAlign( Actor::align_left );
m_sprActualBar[p][l].SetX( BAR_BASE_X(p) );
m_sprActualBar[p][l].SetY( BAR_START_Y + BAR_SPACING_Y*l );
m_sprActualBar[p][l].SetRotation( BAR_ROTATION(p) );
m_sprActualBar[p][l].SetZoomX( 0 );
m_sprActualBar[p][l].ZoomToHeight( BAR_HEIGHT );
m_sprActualBar[p][l].BeginTweening( 1.0f + l*0.2f ); // sleep
m_sprActualBar[p][l].BeginTweening( 1.0f ); // tween
m_sprActualBar[p][l].SetTweenZoomToWidth( BAR_WIDTH*fActualRadarValues[p][l] );
if( fActualRadarValues[p][l] == fPossibleRadarValues[p][l] )
m_sprActualBar[p][l].SetEffectGlowing();
this->AddChild( &m_sprActualBar[p][l] );
m_sprActualBar[p][r].Load( THEME->GetPathTo("Graphics","evaluation bars actual 1x2") );
m_sprActualBar[p][r].SetState( p );
m_sprActualBar[p][r].StopAnimating();
m_sprActualBar[p][r].SetHorizAlign( Actor::align_left );
m_sprActualBar[p][r].SetX( BAR_BASE_X(p) );
m_sprActualBar[p][r].SetY( BAR_START_Y + BAR_SPACING_Y*r );
m_sprActualBar[p][r].SetRotation( BAR_ROTATION(p) );
m_sprActualBar[p][r].SetZoomX( 0 );
m_sprActualBar[p][r].ZoomToHeight( BAR_HEIGHT );
m_sprActualBar[p][r].BeginTweening( 1.0f + r*0.2f ); // sleep
m_sprActualBar[p][r].BeginTweening( 1.0f ); // tween
m_sprActualBar[p][r].SetTweenZoomToWidth( BAR_WIDTH*stageStats.fRadarActual[p][r] );
if( stageStats.fRadarActual[p][r] == stageStats.fRadarPossible[p][r] )
m_sprActualBar[p][r].SetEffectGlowing();
this->AddChild( &m_sprActualBar[p][r] );
}
break;
}
}
// Chris: If EZ2 wants to hide these things, place them off screen using theme metrics
if( bNewRecord[p] )
{
m_sprNewRecord[p].Load( THEME->GetPathTo("Graphics","evaluation new record") );
@@ -450,12 +424,12 @@ ScreenEvaluation::ScreenEvaluation( bool bSummary )
}
}
//////////////////////////
//
// Init non-ResultMode specific displays.
// Do this after Result-specific displays so that the text will draw on top of
// 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
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.SetState( m_ResultMode==RM_ONI ? 1 : 0 );
m_sprScoreLabel.SetState( m_ResultMode==RM_COURSE ? 1 : 0 );
m_sprScoreLabel.StopAnimating();
m_sprScoreLabel.SetXY( SCORE_LABELS_X, SCORE_Y );
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].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].SetDiffuse( PlayerToColor(p) );
this->AddChild( &m_textJudgeNumbers[l][p] );
}
m_textJudgeNumbers[0][p].SetText( ssprintf("%4d", iTapNoteScores[p][TNS_MARVELOUS]) );
m_textJudgeNumbers[1][p].SetText( ssprintf("%4d", iTapNoteScores[p][TNS_PERFECT]) );
m_textJudgeNumbers[2][p].SetText( ssprintf("%4d", iTapNoteScores[p][TNS_GREAT]) );
m_textJudgeNumbers[3][p].SetText( ssprintf("%4d", iTapNoteScores[p][TNS_GOOD]) );
m_textJudgeNumbers[4][p].SetText( ssprintf("%4d", iTapNoteScores[p][TNS_BOO]) );
m_textJudgeNumbers[5][p].SetText( ssprintf("%4d", iTapNoteScores[p][TNS_MISS]) );
m_textJudgeNumbers[6][p].SetText( ssprintf("%4d", iHoldNoteScores[p][HNS_OK]) );
m_textJudgeNumbers[7][p].SetText( ssprintf("%4d", iMaxCombo[p]) );
m_textJudgeNumbers[0][p].SetText( ssprintf("%4d", stageStats.iTapNoteScores[p][TNS_MARVELOUS]) );
m_textJudgeNumbers[1][p].SetText( ssprintf("%4d", stageStats.iTapNoteScores[p][TNS_PERFECT]) );
m_textJudgeNumbers[2][p].SetText( ssprintf("%4d", stageStats.iTapNoteScores[p][TNS_GREAT]) );
m_textJudgeNumbers[3][p].SetText( ssprintf("%4d", stageStats.iTapNoteScores[p][TNS_GOOD]) );
m_textJudgeNumbers[4][p].SetText( ssprintf("%4d", stageStats.iTapNoteScores[p][TNS_BOO]) );
m_textJudgeNumbers[5][p].SetText( ssprintf("%4d", stageStats.iTapNoteScores[p][TNS_MISS]) );
m_textJudgeNumbers[6][p].SetText( ssprintf("%4d", stageStats.iHoldNoteScores[p][HNS_OK]) );
m_textJudgeNumbers[7][p].SetText( ssprintf("%4d", stageStats.iMaxCombo[p]) );
if( m_ResultMode==RM_ONI )
m_ScoreDisplay[p].SetText( SecondsToTime(GAMESTATE->GetPlayerSurviveTime( (PlayerNumber)p )) );
if( m_ResultMode==RM_COURSE )
m_ScoreDisplay[p].SetText( SecondsToTime(stageStats.fAliveSeconds[p]) );
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
}
break;
case RM_ONI:
case RM_COURSE:
case RM_ARCADE_SUMMARY:
switch( max_grade )
{
@@ -594,7 +568,7 @@ void ScreenEvaluation::TweenOnScreen()
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();
m_BannerWithFrame[i].SetY( fOriginalY + SCREEN_HEIGHT );
@@ -695,7 +669,7 @@ void ScreenEvaluation::TweenOffScreen()
{
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_textStage.FadeOff( 0, "foldy", MENU_ELEMENTS_TWEEN_TIME );
@@ -797,12 +771,16 @@ void ScreenEvaluation::HandleScreenMessage( const ScreenMessage SM )
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 )
{
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 )
@@ -851,9 +829,8 @@ void ScreenEvaluation::MenuStart( PlayerNumber pn )
m_Menu.TweenOffScreenToBlack( SM_GoToMusicScroll, false );
}
//
// Increment the stage counter.
//
GAMESTATE->m_iCurrentStageIndex++;
GAMESTATE->m_iCurrentStageIndex++; // Increment the stage counter.
GAMESTATE->m_vPassedStageStats.push_back( GAMESTATE->m_CurStageStats ); // Save this stage's stats
}
+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 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
@@ -42,12 +42,12 @@ public:
virtual void MenuStart( PlayerNumber pn );
protected:
enum ResultMode { RM_ARCADE_STAGE, RM_ARCADE_SUMMARY, RM_ONI };
enum ResultMode { RM_ARCADE_STAGE, RM_ARCADE_SUMMARY, RM_COURSE };
ResultMode m_ResultMode;
MenuElements m_Menu;
BannerWithFrame m_BannerWithFrame[STAGES_TO_SHOW_IN_SUMMARY];
BannerWithFrame m_BannerWithFrame[MAX_SONGS_TO_SHOW];
BitmapText m_textStage;
DifficultyIcon m_DifficultyIcon[NUM_PLAYERS];
@@ -78,6 +78,8 @@ protected:
Sprite m_sprNewRecord[NUM_PLAYERS];
bool m_bGoToNameEntry;
bool m_bTryExtraStage;
Sprite m_sprTryExtraStage;
};
+44 -50
View File
@@ -116,10 +116,9 @@ ScreenGameplay::ScreenGameplay( bool bDemonstration )
SOUNDMAN->StopMusic();
/* It's OK to operate on GAMESTATE here, but not in the constructor */
GAMESTATE->ResetStageStatistics(); // clear values
GAMESTATE->m_CurStageStats = StageStats(); // clear values
// Update possible dance points
// Fill in m_CurStageStats
for( p=0; p<NUM_PLAYERS; p++ )
{
if( !GAMESTATE->IsPlayerEnabled(p) )
@@ -129,14 +128,20 @@ ScreenGameplay::ScreenGameplay( bool bDemonstration )
switch( GAMESTATE->m_PlayMode )
{
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_iPossibleDancePoints[p] = notedata.GetPossibleDancePoints();
GAMESTATE->m_CurStageStats.iPossibleDancePoints[p] = notedata.GetPossibleDancePoints();
break;
case PLAY_MODE_NONSTOP:
case PLAY_MODE_ONI:
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;
vector<Song*> apSongs;
@@ -146,9 +151,10 @@ ScreenGameplay::ScreenGameplay( bool bDemonstration )
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_iPossibleDancePoints[p] += iPossibleDancePoints;
GAMESTATE->m_CurStageStats.iPossibleDancePoints[p] += iPossibleDancePoints;
}
}
break;
@@ -499,7 +505,7 @@ bool ScreenGameplay::IsLastSong()
CStringArray asModifiers;
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;
default:
@@ -523,9 +529,9 @@ void ScreenGameplay::LoadNextSong( bool bFirstLoad )
int 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 (GAMESTATE->m_iSongsIntoCourse == 0)
if( GAMESTATE->m_CurStageStats.iSongsPassed[p] == 0 )
GAMESTATE->m_SelectedOptions[p] = GAMESTATE->m_PlayerOptions[p];
}
Course* pCourse = GAMESTATE->m_pCurCourse;
@@ -535,7 +541,10 @@ void ScreenGameplay::LoadNextSong( bool bFirstLoad )
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();
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].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);
@@ -732,6 +741,13 @@ void ScreenGameplay::Update( float fDeltaTime )
{
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
//
@@ -758,8 +774,8 @@ void ScreenGameplay::Update( float fDeltaTime )
// check for individual fail
for ( pn=0; pn<NUM_PLAYERS; pn++ )
{
if ( m_pLifeMeter[pn]->IsFailing() && GAMESTATE->m_fSecondsBeforeFail[pn] == -1)
GAMESTATE->m_fSecondsBeforeFail[pn] = GAMESTATE->GetElapsedSeconds();
if ( m_pLifeMeter[pn]->IsFailing() && !GAMESTATE->m_CurStageStats.bFailed[pn] )
GAMESTATE->m_CurStageStats.bFailed[pn] = true; // fail
}
break;
@@ -769,19 +785,19 @@ void ScreenGameplay::Update( float fDeltaTime )
else m_Background.TurnDangerOff();
// check for individual fail
for( pn=0; pn<NUM_PLAYERS; pn++ ) {
for( pn=0; pn<NUM_PLAYERS; pn++ )
{
if( !GAMESTATE->IsPlayerEnabled(pn) )
continue;
if( !m_pLifeMeter[pn]->IsFailing())
continue; /* hasn't failed */
if( GAMESTATE->m_fSecondsBeforeFail[pn] != -1 )
continue; /* isn't failing */
if( GAMESTATE->m_CurStageStats.bFailed[pn] )
continue; /* failed and is already dead */
if( !AllFailedEarlier() ) // if not the last one to fail
{
// kill them!
GAMESTATE->m_fSecondsBeforeFail[pn] = GAMESTATE->GetElapsedSeconds();
GAMESTATE->m_CurStageStats.bFailed[pn] = true;
m_soundOniDie.PlayRandom();
ShowOniGameOver((PlayerNumber)pn);
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++ )
{
RadarCategory rc = (RadarCategory)r;
GAMESTATE->m_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.fRadarPossible[p][r] = NoteDataUtil::GetRadarValue( m_Player[p], 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++ )
if( GAMESTATE->IsPlayerEnabled(p) )
if( !m_pLifeMeter[p]->FailedEarlier() )
GAMESTATE->m_iSongsBeforeFail[p]++;
if( GAMESTATE->IsPlayerEnabled(p) && !GAMESTATE->m_CurStageStats.bFailed[p] )
GAMESTATE->m_CurStageStats.iSongsPassed[p]++;
if( !IsLastSong() )
{
for( int p=0; p<NUM_PLAYERS; p++ )
if( GAMESTATE->IsPlayerEnabled(p) )
if( !m_pLifeMeter[p]->FailedEarlier() )
m_pLifeMeter[p]->SongEnded(); // let the oni life meter give them back a life
if( GAMESTATE->IsPlayerEnabled(p) && !GAMESTATE->m_CurStageStats.bFailed[p] )
m_pLifeMeter[p]->OnSongEnded(); // give a little life back between stages
m_OniFade.CloseWipingRight( SM_BeginLoadingNextSong );
}
else // IsLastSong
{
if( m_DancingState == STATE_OUTRO ) // gameplay already ended
return; // ignore
m_DancingState = STATE_OUTRO;
GAMESTATE->AccumulateStageStatistics(); // accumulate values for final evaluation
if( GAMESTATE->m_SongOptions.m_FailType == SongOptions::FAIL_END_OF_SONG && AllFailedEarlier() )
{
this->SendScreenMessage( SM_BeginFailed, 0 );
@@ -1210,23 +1217,10 @@ void ScreenGameplay::HandleScreenMessage( const ScreenMessage SM )
m_StarWipe.CloseWipingRight( SM_None );
// do they deserve an extra stage?
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;
}
}
bool bTryExtraStage = GAMESTATE->HasEarnedExtraStage();
if( PREFSMAN->m_bEventMode )
bTryExtraStage = false;
if( bTryExtraStage )
{
this->SendScreenMessage( SM_ShowTryExtraStage, 1 );
@@ -1458,11 +1452,11 @@ void ScreenGameplay::HandleScreenMessage( const ScreenMessage SM )
// show the survive time if extra stage
if( GAMESTATE->IsExtraStage() || GAMESTATE->IsExtraStage2() )
{
float fMaxSurviveSeconds = -1;
float fMaxSurviveSeconds = 0;
for( int p=0; p<NUM_PLAYERS; p++ )
if( GAMESTATE->IsPlayerEnabled(p) )
fMaxSurviveSeconds = max( fMaxSurviveSeconds, GAMESTATE->GetPlayerSurviveTime((PlayerNumber)p) );
ASSERT( fMaxSurviveSeconds != -1 );
fMaxSurviveSeconds = max( fMaxSurviveSeconds, GAMESTATE->m_CurStageStats.fAliveSeconds[p] );
ASSERT( fMaxSurviveSeconds > 0 );
m_textSurviveTime.SetText( "TIME " + SecondsToTime(fMaxSurviveSeconds) );
m_textSurviveTime.BeginTweening( 0.3f ); // sleep
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];
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 );
if( pNotes && pNotes->IsAutogen() )
+126 -43
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 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")
@@ -210,7 +212,7 @@ void SongManager::InitMachineScoresFromDisk()
for( int j=0; j<NUM_HIGH_SCORE_CATEGORIES; j++ )
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";
}
}
@@ -218,51 +220,62 @@ void SongManager::InitMachineScoresFromDisk()
// Read category top scores
{
FILE* fp = fopen( CATEGORY_TOP_SCORE_FILE, "r" );
for( int i=0; i<NUM_STYLES; i++ )
for( int j=0; j<NUM_HIGH_SCORE_CATEGORIES; j++ )
for( int k=0; k<NUM_HIGH_SCORE_LINES; k++ )
if( fp && !feof(fp) )
{
char szName[256];
fscanf(fp, "%d %[^\n]\n", &m_MachineScores[i][j][k].iScore, szName);
m_MachineScores[i][j][k].sName = szName;
}
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 j=0; j<NUM_HIGH_SCORE_CATEGORIES; j++ )
for( int k=0; k<NUM_HIGH_SCORE_LINES; k++ )
if( fp && !feof(fp) )
{
char szName[256];
fscanf(fp, "%f %[^\n]\n", &m_MachineScores[i][j][k].fScore, szName);
m_MachineScores[i][j][k].sName = szName;
}
}
fclose(fp);
}
}
// Read course top scores
{
FILE* fp = fopen( COURSE_TOP_SCORE_FILE, "r" );
while( fp && !feof(fp) )
{
char szPath[256];
fscanf(fp, "%s\n", szPath);
Course* pCourse = GetCourseFromPath( szPath );
for( int i=0; i<NUM_STYLES; i++ )
for( int j=0; j<NUM_HIGH_SCORE_CATEGORIES; j++ )
for( int k=0; k<NUM_HIGH_SCORE_LINES; k++ )
if( fp && !feof(fp) )
{
int iDancePoints;
float fSurviveTime;
char szName[256];
fscanf(fp, "%d %f %[^\n]\n", &iDancePoints, &fSurviveTime, szName);
if( pCourse )
{
pCourse->m_MachineScores[i][j][k].iDancePoints = iDancePoints;
pCourse->m_MachineScores[i][j][k].fSurviveTime = fSurviveTime;
pCourse->m_MachineScores[i][j][k].sName = szName;
}
}
}
if( fp )
{
int version;
fscanf(fp, "%d\n", &version );
if( version == COURSE_TOP_SCORE_VERSION )
{
while( fp && !feof(fp) )
{
char szPath[256];
fscanf(fp, "%s\n", szPath);
Course* pCourse = GetCourseFromPath( szPath );
for( int i=0; i<NUM_STYLES; i++ )
for( int j=0; j<NUM_HIGH_SCORE_CATEGORIES; j++ )
for( int k=0; k<NUM_HIGH_SCORE_LINES; k++ )
if( fp && !feof(fp) )
{
int iDancePoints;
float fSurviveTime;
char szName[256];
fscanf(fp, "%d %f %[^\n]\n", &iDancePoints, &fSurviveTime, szName);
if( pCourse )
{
pCourse->m_MachineScores[i][j][k].iDancePoints = iDancePoints;
pCourse->m_MachineScores[i][j][k].fSurviveTime = fSurviveTime;
pCourse->m_MachineScores[i][j][k].sName = szName;
}
}
}
}
fclose(fp);
}
}
}
@@ -271,15 +284,16 @@ void SongManager::SaveMachineScoresToDisk()
// Write category top scores
{
FILE* fp = fopen( CATEGORY_TOP_SCORE_FILE, "w" );
for( int i=0; i<NUM_STYLES; i++ )
for( int j=0; j<NUM_HIGH_SCORE_CATEGORIES; j++ )
for( int k=0; k<NUM_HIGH_SCORE_LINES; k++ )
if( fp )
fprintf(fp, "%d %s\n", m_MachineScores[i][j][k].iScore, m_MachineScores[i][j][k].sName.c_str());
if( fp )
{
fprintf(fp,"%d",CATEGORY_TOP_SCORE_VERSION);
for( int i=0; i<NUM_STYLES; i++ )
for( int j=0; j<NUM_HIGH_SCORE_CATEGORIES; j++ )
for( int k=0; k<NUM_HIGH_SCORE_LINES; k++ )
if( fp )
fprintf(fp, "%f %s\n", m_MachineScores[i][j][k].fScore, m_MachineScores[i][j][k].sName.c_str());
fclose(fp);
}
}
// Write course top scores
@@ -288,6 +302,7 @@ void SongManager::SaveMachineScoresToDisk()
if( fp )
{
fprintf(fp,"%d",COURSE_TOP_SCORE_VERSION);
for( unsigned i=0; i<m_pCourses.size(); i++ ) // foreach course
{
Course* pCourse = m_pCourses[i];
@@ -616,3 +631,71 @@ bool SongManager::IsUsingMemoryCard( PlayerNumber pn )
{
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
//
struct HighScore
{
int iScore;
CString sName;
};
HighScore m_MachineScores[NUM_STYLES][NUM_HIGH_SCORE_CATEGORIES][NUM_HIGH_SCORE_LINES];
void InitMachineScoresFromDisk();
void SaveMachineScoresToDisk();
bool MemoryCardIsInserted( 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:
void LoadStepManiaSongDir( CString sDir, LoadingWindow *ld );
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
RelativePath="SongOptions.h">
</File>
<File
RelativePath="StageStats.cpp">
</File>
<File
RelativePath="StageStats.h">
</File>
<File
RelativePath="Style.h">
</File>