From 09d018444ef7ea2c441db45c171145fa78ecf9c7 Mon Sep 17 00:00:00 2001 From: Chris Danford Date: Mon, 20 Dec 2004 10:47:41 +0000 Subject: [PATCH] split StageStats into player-specific and non-player-specific structs --- stepmania/src/Combo.cpp | 6 +- stepmania/src/ComboGraph.cpp | 20 +- stepmania/src/ConditionalBGA.cpp | 28 +- stepmania/src/ConditionalBGA.h | 3 +- stepmania/src/DancingCharacters.cpp | 2 +- stepmania/src/GameState.cpp | 75 ++-- stepmania/src/GraphDisplay.cpp | 2 +- stepmania/src/Inventory.cpp | 4 +- stepmania/src/LifeMeterBar.cpp | 4 +- stepmania/src/LifeMeterBattery.cpp | 8 +- stepmania/src/NetworkSyncManager.cpp | 4 +- stepmania/src/NoteDataWithScoring.cpp | 8 +- stepmania/src/PercentageDisplay.cpp | 4 +- stepmania/src/Player.cpp | 154 ++++--- stepmania/src/PlayerState.h | 35 ++ stepmania/src/ScoreDisplayOni.cpp | 2 +- stepmania/src/ScoreKeeperMAX2.cpp | 38 +- stepmania/src/ScreenEnding.cpp | 44 +- stepmania/src/ScreenEvaluation.cpp | 164 +++---- stepmania/src/ScreenNameEntryTraditional.cpp | 32 +- stepmania/src/SongManager.cpp | 4 +- stepmania/src/StageStats.cpp | 428 ++++++++++--------- stepmania/src/StageStats.h | 116 ++--- 23 files changed, 638 insertions(+), 547 deletions(-) diff --git a/stepmania/src/Combo.cpp b/stepmania/src/Combo.cpp index d3cfae50bc..da25a5af46 100644 --- a/stepmania/src/Combo.cpp +++ b/stepmania/src/Combo.cpp @@ -100,17 +100,17 @@ void Combo::SetCombo( int iCombo, int iMisses ) if( bPastMidpoint ) { - if( g_CurStageStats.FullComboOfScore(m_PlayerNumber,TNS_MARVELOUS) ) + if( g_CurStageStats.m_player[m_PlayerNumber].FullComboOfScore(TNS_MARVELOUS) ) { sprLabel.RunCommands( FULL_COMBO_MARVELOUSES_COMMAND ); m_textNumber.RunCommands( FULL_COMBO_MARVELOUSES_COMMAND ); } - else if( bPastMidpoint && g_CurStageStats.FullComboOfScore(m_PlayerNumber,TNS_PERFECT) ) + else if( bPastMidpoint && g_CurStageStats.m_player[m_PlayerNumber].FullComboOfScore(TNS_PERFECT) ) { sprLabel.RunCommands( FULL_COMBO_PERFECTS_COMMAND ); m_textNumber.RunCommands( FULL_COMBO_PERFECTS_COMMAND ); } - else if( bPastMidpoint && g_CurStageStats.FullComboOfScore(m_PlayerNumber,TNS_GREAT) ) + else if( bPastMidpoint && g_CurStageStats.m_player[m_PlayerNumber].FullComboOfScore(TNS_GREAT) ) { sprLabel.RunCommands( FULL_COMBO_GREATS_COMMAND ); m_textNumber.RunCommands( FULL_COMBO_GREATS_COMMAND ); diff --git a/stepmania/src/ComboGraph.cpp b/stepmania/src/ComboGraph.cpp index f63642fbb5..65f0f7aca7 100644 --- a/stepmania/src/ComboGraph.cpp +++ b/stepmania/src/ComboGraph.cpp @@ -14,13 +14,13 @@ void ComboGraph::Load( CString Path, const StageStats &s, PlayerNumber pn ) /* Find the largest combo. */ int MaxComboSize = 0; - for( unsigned i = 0; i < s.ComboList[pn].size(); ++i ) - MaxComboSize = max( MaxComboSize, s.ComboList[pn][i].GetStageCnt() ); + for( unsigned i = 0; i < s.m_player[pn].ComboList.size(); ++i ) + MaxComboSize = max( MaxComboSize, s.m_player[pn].ComboList[i].GetStageCnt() ); float width = -1; - for( unsigned i = 0; i < s.ComboList[pn].size(); ++i ) + for( unsigned i = 0; i < s.m_player[pn].ComboList.size(); ++i ) { - const StageStats::Combo_t &combo = s.ComboList[pn][i]; + const PlayerStageStats::Combo_t &combo = s.m_player[pn].ComboList[i]; if( combo.GetStageCnt() < MinComboSizeToShow ) continue; /* too small */ @@ -32,8 +32,8 @@ void ComboGraph::Load( CString Path, const StageStats &s, PlayerNumber pn ) const CString path = ssprintf( "%s %s", Path.c_str(), IsMax? "max":"normal" ); sprite->Load( THEME->GetPathToG(path) ); - const float start = SCALE( combo.fStartSecond, s.fFirstSecond[pn], s.fLastSecond[pn], 0.0f, 1.0f ); - const float size = SCALE( combo.fSizeSeconds, 0, s.fLastSecond[pn]-s.fFirstSecond[pn], 0.0f, 1.0f ); + const float start = SCALE( combo.fStartSecond, s.m_player[pn].fFirstSecond, s.m_player[pn].fLastSecond, 0.0f, 1.0f ); + const float size = SCALE( combo.fSizeSeconds, 0, s.m_player[pn].fLastSecond-s.m_player[pn].fFirstSecond, 0.0f, 1.0f ); sprite->SetCropLeft ( SCALE( size, 0.0f, 1.0f, 0.5f, 0.0f ) ); sprite->SetCropRight( SCALE( size, 0.0f, 1.0f, 0.5f, 0.0f ) ); @@ -48,9 +48,9 @@ void ComboGraph::Load( CString Path, const StageStats &s, PlayerNumber pn ) this->AddChild( sprite ); } - for( unsigned i = 0; i < s.ComboList[pn].size(); ++i ) + for( unsigned i = 0; i < s.m_player[pn].ComboList.size(); ++i ) { - const StageStats::Combo_t &combo = s.ComboList[pn][i]; + const PlayerStageStats::Combo_t &combo = s.m_player[pn].ComboList[i]; if( combo.GetStageCnt() < MinComboSizeToShow ) continue; /* too small */ @@ -65,8 +65,8 @@ void ComboGraph::Load( CString Path, const StageStats &s, PlayerNumber pn ) text->SetName( "ComboMaxNumber" ); text->LoadFromFont( THEME->GetPathToF(Path) ); - const float start = SCALE( combo.fStartSecond, s.fFirstSecond[pn], s.fLastSecond[pn], 0.0f, 1.0f ); - const float size = SCALE( combo.fSizeSeconds, 0, s.fLastSecond[pn]-s.fFirstSecond[pn], 0.0f, 1.0f ); + const float start = SCALE( combo.fStartSecond, s.m_player[pn].fFirstSecond, s.m_player[pn].fLastSecond, 0.0f, 1.0f ); + const float size = SCALE( combo.fSizeSeconds, 0, s.m_player[pn].fLastSecond-s.m_player[pn].fFirstSecond, 0.0f, 1.0f ); const float CenterPercent = start + size/2; const float CenterXPos = SCALE( CenterPercent, 0.0f, 1.0f, -width/2.0f, width/2.0f ); diff --git a/stepmania/src/ConditionalBGA.cpp b/stepmania/src/ConditionalBGA.cpp index 9ada1936b6..c925ad2458 100644 --- a/stepmania/src/ConditionalBGA.cpp +++ b/stepmania/src/ConditionalBGA.cpp @@ -1,13 +1,14 @@ +// TODO: Remove this class in favor and merge its functionality into the Lua +// conditions already present in BGA. #include "global.h" +#include "ConditionalBGA.h" #include - #include "GameState.h" #include "GameManager.h" #include "song.h" #include "GameConstantsAndTypes.h" #include "RageLog.h" #include "BGAnimation.h" -#include "ConditionalBGA.h" #include "ThemeManager.h" #include "RageUtil.h" #include "RageFile.h" @@ -501,7 +502,7 @@ void ConditionalBGA::CheckBgaRequirements(BgaCondInfo info) bool foundaplayerwithgrade = false; FOREACH_EnabledPlayer( pn ) { - if(g_CurStageStats.GetGrade(pn) == info.grades[0]) + if(g_CurStageStats.m_player[pn].GetGrade() == info.grades[0]) { LOG->Info("Found Valid Grade"); foundaplayerwithgrade = true; @@ -524,16 +525,13 @@ void ConditionalBGA::CheckBgaRequirements(BgaCondInfo info) { if(d>g) ASSERT(0); // this should never happen. - for(unsigned pn=0; pnIsPlayerEnabled((PlayerNumber)pn)) + LOG->Info("Player%d Grade: %d :: Expected Grade: %d",pn,g_vPlayedStageStats[g].m_player[pn].GetGrade(),info.grades[d]); + if(g_vPlayedStageStats[g].m_player[pn].GetGrade() == info.grades[d]) { - LOG->Info("Player%d Grade: %d :: Expected Grade: %d",pn,g_vPlayedStageStats[g].GetGrade((PlayerNumber)pn),info.grades[d]); - if(g_vPlayedStageStats[g].GetGrade((PlayerNumber)pn) == info.grades[d]) - { - LOG->Info("One Valid Grade"); - foundavalidgradeforstage = true; - } + LOG->Info("One Valid Grade"); + foundavalidgradeforstage = true; } } } @@ -610,20 +608,24 @@ void ConditionalBGA::CheckBgaRequirements(BgaCondInfo info) else if(info.cleared == CBGA_CSMAXCOMBO) { FOREACH_EnabledPlayer( pn ) - if(g_CurStageStats.FullCombo((PlayerNumber)pn)) + { + if(g_CurStageStats.m_player[pn].FullCombo()) { foundclearcond = true; LOG->Info("MaxCombo Condition"); } + } } else if(info.cleared == CBGA_CSBROKECOMBO) { FOREACH_EnabledPlayer( pn ) - if(!g_CurStageStats.FullCombo((PlayerNumber)pn)) + { + if(!g_CurStageStats.m_player[pn].FullCombo()) { LOG->Info("BrokenCombo Condition"); foundclearcond = true; } + } } valid = foundclearcond; diff --git a/stepmania/src/ConditionalBGA.h b/stepmania/src/ConditionalBGA.h index ccdff1584e..89acfca8bb 100644 --- a/stepmania/src/ConditionalBGA.h +++ b/stepmania/src/ConditionalBGA.h @@ -4,7 +4,8 @@ #include "PlayerOptions.h" #include "GameConstantsAndTypes.h" #include "BGAnimation.h" -//#include "Style.h" + +class Style; enum CBGACLEAREDSTATES { diff --git a/stepmania/src/DancingCharacters.cpp b/stepmania/src/DancingCharacters.cpp index 526f66fe48..1e8a9ae166 100644 --- a/stepmania/src/DancingCharacters.cpp +++ b/stepmania/src/DancingCharacters.cpp @@ -342,7 +342,7 @@ void DancingCharacters::DrawPrimitives() continue; } - bool bFailed = g_CurStageStats.bFailed[p]; + bool bFailed = g_CurStageStats.m_player[p].bFailed; bool bDanger = m_bDrawDangerLight; DISPLAY->SetLighting( true ); diff --git a/stepmania/src/GameState.cpp b/stepmania/src/GameState.cpp index ebbb240612..1e86e08537 100644 --- a/stepmania/src/GameState.cpp +++ b/stepmania/src/GameState.cpp @@ -156,7 +156,7 @@ void GameState::Reset() m_pPosition = new NoteFieldPositioning("Positioning.ini"); FOREACH_PlayerNumber( p ) - m_pPlayerState[p]->m_bAttackBeganThisUpdate = false; + m_pPlayerState[p]->Reset(); ResetMusicStatistics(); ResetStageStatistics(); @@ -170,12 +170,6 @@ void GameState::Reset() g_vPlayedStageStats.clear(); - FOREACH_PlayerNumber( p ) - { - m_pPlayerState[p]->m_CurrentPlayerOptions.Init(); - m_pPlayerState[p]->m_PlayerOptions.Init(); - m_pPlayerState[p]->m_StoredPlayerOptions.Init(); - } m_SongOptions.Init(); FOREACH_PlayerNumber(p) @@ -200,13 +194,6 @@ void GameState::Reset() ASSERT( m_pCurCharacters[p] ); } - FOREACH_PlayerNumber(p) - { - m_pPlayerState[p]->m_fSuperMeterGrowthScale = 1; - m_pPlayerState[p]->m_iCpuSkill = 5; - } - - LIGHTSMAN->SetLightsMode( LIGHTSMODE_ATTRACT ); ApplyCmdline(); @@ -301,10 +288,10 @@ void AddPlayerStatsToProfile( Profile *pProfile, const StageStats &ss, PlayerNum StyleID sID; sID.FromStyle( ss.pStyle ); - ASSERT( ss.vpSongs.size() == ss.vpSteps[pn].size() ); + ASSERT( ss.vpSongs.size() == ss.m_player[pn].vpSteps.size() ); for( unsigned i=0; im_iNumSongsPlayedByPlayMode[ss.playMode]++; pProfile->m_iNumSongsPlayedByStyle[sID] ++; @@ -312,11 +299,11 @@ void AddPlayerStatsToProfile( Profile *pProfile, const StageStats &ss, PlayerNum pProfile->m_iNumSongsPlayedByMeter[pSteps->GetMeter()] ++; } - pProfile->m_iTotalDancePoints += ss.iActualDancePoints[pn]; + pProfile->m_iTotalDancePoints += ss.m_player[pn].iActualDancePoints; if( ss.StageType == StageStats::STAGE_EXTRA || ss.StageType == StageStats::STAGE_EXTRA2 ) { - if( ss.bFailed[pn] ) + if( ss.m_player[pn].bFailed ) ++pProfile->m_iNumExtraStagesFailed; else ++pProfile->m_iNumExtraStagesPassed; @@ -324,10 +311,10 @@ void AddPlayerStatsToProfile( Profile *pProfile, const StageStats &ss, PlayerNum // If you fail in a course, you passed all but the final song. // FIXME: Not true. If playing with 2 players, one player could have failed earlier. - if( !ss.bFailed[pn] ) + if( !ss.m_player[pn].bFailed ) { pProfile->m_iNumStagesPassedByPlayMode[ss.playMode] ++; - pProfile->m_iNumStagesPassedByGrade[ss.GetGrade(pn)] ++; + pProfile->m_iNumStagesPassedByGrade[ss.m_player[pn].GetGrade()] ++; } } @@ -524,14 +511,17 @@ void GameState::ResetStageStatistics() { FOREACH_PlayerNumber( p ) { - Profile* pProfile = PROFILEMAN->GetProfile((PlayerNumber)p); + Profile* pProfile = PROFILEMAN->GetProfile(p); if( pProfile ) - g_CurStageStats.iCurCombo[p] = pProfile->m_iCurrentCombo; + g_CurStageStats.m_player[p].iCurCombo = pProfile->m_iCurrentCombo; } } else // GetStageIndex() > 0 { - memcpy( g_CurStageStats.iCurCombo, OldStats.iCurCombo, sizeof(OldStats.iCurCombo) ); + FOREACH_PlayerNumber( p ) + { + g_CurStageStats.m_player[p].iCurCombo = OldStats.m_player[p].iCurCombo; + } } } @@ -656,11 +646,11 @@ void GameState::FinishStage() // FOREACH_HumanPlayer( pn ) { - int iNumTapsAndHolds = (int) g_CurStageStats.radarActual[pn][RADAR_NUM_TAPS_AND_HOLDS]; - int iNumJumps = (int) g_CurStageStats.radarActual[pn][RADAR_NUM_JUMPS]; - int iNumHolds = (int) g_CurStageStats.radarActual[pn][RADAR_NUM_HOLDS]; - int iNumMines = (int) g_CurStageStats.radarActual[pn][RADAR_NUM_MINES]; - int iNumHands = (int) g_CurStageStats.radarActual[pn][RADAR_NUM_HANDS]; + int iNumTapsAndHolds = (int) g_CurStageStats.m_player[pn].radarActual[RADAR_NUM_TAPS_AND_HOLDS]; + int iNumJumps = (int) g_CurStageStats.m_player[pn].radarActual[RADAR_NUM_JUMPS]; + int iNumHolds = (int) g_CurStageStats.m_player[pn].radarActual[RADAR_NUM_HOLDS]; + int iNumMines = (int) g_CurStageStats.m_player[pn].radarActual[RADAR_NUM_MINES]; + int iNumHands = (int) g_CurStageStats.m_player[pn].radarActual[RADAR_NUM_HANDS]; PROFILEMAN->AddStepTotals( pn, iNumTapsAndHolds, iNumJumps, iNumHolds, iNumMines, iNumHands ); } @@ -684,7 +674,7 @@ void GameState::FinishStage() pPlayerProfile->m_iTotalGameplaySeconds += iGameplaySeconds; pPlayerProfile->m_iCurrentCombo = PREFSMAN->m_bComboContinuesBetweenSongs ? - g_CurStageStats.iCurCombo[p] : + g_CurStageStats.m_player[p].iCurCombo : 0; } @@ -787,7 +777,7 @@ int GameState::GetCourseSongIndex() const /* iSongsPlayed includes the current song, so it's 1-based; subtract one. */ FOREACH_PlayerNumber( p ) if( IsPlayerEnabled(p) ) - iSongIndex = max( iSongIndex, g_CurStageStats.iSongsPlayed[p]-1 ); + iSongIndex = max( iSongIndex, g_CurStageStats.m_player[p].iSongsPlayed-1 ); return iSongIndex; } @@ -985,11 +975,8 @@ bool GameState::HasEarnedExtraStage() const if( (this->IsFinalStage() || this->IsExtraStage()) ) { - FOREACH_PlayerNumber( p ) + FOREACH_EnabledPlayer( p ) { - if( !this->IsPlayerEnabled(p) ) - continue; // skip - if( this->m_pCurSteps[p]->GetDifficulty() != DIFFICULTY_HARD && this->m_pCurSteps[p]->GetDifficulty() != DIFFICULTY_CHALLENGE ) continue; /* not hard enough! */ @@ -999,7 +986,7 @@ bool GameState::HasEarnedExtraStage() const if( PREFSMAN->m_bPickExtraStage && this->IsExtraStage() && !this->m_bAllow2ndExtraStage ) continue; - if( g_CurStageStats.GetGrade((PlayerNumber)p) <= GRADE_TIER_3 ) + if( g_CurStageStats.m_player[p].GetGrade() <= GRADE_TIER_3 ) return true; } } @@ -1008,9 +995,9 @@ bool GameState::HasEarnedExtraStage() const PlayerNumber GameState::GetBestPlayer() const { - for( int p=PLAYER_1; p g_CurStageStats.iActualDancePoints[pn] ) + if( g_CurStageStats.m_player[p].iActualDancePoints > g_CurStageStats.m_player[pn].iActualDancePoints ) return RESULT_LOSE; } return win; @@ -1081,8 +1068,8 @@ void GameState::GetFinalEvalStats( StageStats& statsOut ) const { for( int r = 0; r < RADAR_NUM_TAPS_AND_HOLDS; r++) { - statsOut.radarPossible[p][r] /= statsOut.vpSongs.size(); - statsOut.radarActual[p][r] /= statsOut.vpSongs.size(); + statsOut.m_player[p].radarPossible[r] /= statsOut.vpSongs.size(); + statsOut.m_player[p].radarActual[r] /= statsOut.vpSongs.size(); } } } @@ -1440,7 +1427,7 @@ void GameState::GetRankingFeats( PlayerNumber pn, vector &asFeatsOu SongAndSteps sas; sas.pSong = g_vPlayedStageStats[i].vpSongs[0]; ASSERT( sas.pSong ); - sas.pSteps = g_vPlayedStageStats[i].vpSteps[pn][0]; + sas.pSteps = g_vPlayedStageStats[i].m_player[pn].vpSteps[0]; ASSERT( sas.pSteps ); vSongAndSteps.push_back( sas ); } @@ -1702,7 +1689,7 @@ bool GameState::AllAreDead() const bool GameState::AllHaveComboOf30OrMoreMisses() const { FOREACH_EnabledPlayer( p ) - if( g_CurStageStats.iCurMissCombo[p] < 30 ) + if( g_CurStageStats.m_player[p].iCurMissCombo < 30 ) return false; return true; } diff --git a/stepmania/src/GraphDisplay.cpp b/stepmania/src/GraphDisplay.cpp index 15ad4e9afe..298737bbb8 100644 --- a/stepmania/src/GraphDisplay.cpp +++ b/stepmania/src/GraphDisplay.cpp @@ -43,7 +43,7 @@ void GraphDisplay::LoadFromStageStats( const StageStats &s, PlayerNumber pn ) { memcpy( m_LastValues, m_CurValues, sizeof(m_CurValues) ); m_Position = 0; - s.GetLifeRecord( pn, m_DestValues, VALUE_RESOLUTION ); + s.m_player[pn].GetLifeRecord( m_DestValues, VALUE_RESOLUTION ); for( unsigned i=0; im_PlayerNumber; // check to see if they deserve a new item - if( g_CurStageStats.iCurCombo[pn] != m_iLastSeenCombo ) + if( g_CurStageStats.m_player[pn].iCurCombo != m_iLastSeenCombo ) { int iOldCombo = m_iLastSeenCombo; - m_iLastSeenCombo = g_CurStageStats.iCurCombo[pn]; + m_iLastSeenCombo = g_CurStageStats.m_player[pn].iCurCombo; int iNewCombo = m_iLastSeenCombo; #define CROSSED(i) (iOldCombo=i) diff --git a/stepmania/src/LifeMeterBar.cpp b/stepmania/src/LifeMeterBar.cpp index b5eec87107..83f67169ac 100644 --- a/stepmania/src/LifeMeterBar.cpp +++ b/stepmania/src/LifeMeterBar.cpp @@ -403,7 +403,7 @@ void LifeMeterBar::ChangeLife( float fDeltaLife ) } /* If we've already failed, there's no point in letting them fill up the bar again. */ - if( g_CurStageStats.bFailed[m_PlayerNumber] ) + if( g_CurStageStats.m_player[m_PlayerNumber].bFailed ) fDeltaLife = 0; switch( GAMESTATE->m_SongOptions.m_DrainType ) @@ -432,7 +432,7 @@ void LifeMeterBar::ChangeLife( float fDeltaLife ) CLAMP( m_fLifePercentage, 0, 1 ); if( m_fLifePercentage <= FAIL_THRESHOLD ) - g_CurStageStats.bFailedEarlier[m_PlayerNumber] = true; + g_CurStageStats.m_player[m_PlayerNumber].bFailedEarlier = true; m_fLifeVelocity += fDeltaLife; } diff --git a/stepmania/src/LifeMeterBattery.cpp b/stepmania/src/LifeMeterBattery.cpp index 49850e03e5..26e4e9c30e 100644 --- a/stepmania/src/LifeMeterBattery.cpp +++ b/stepmania/src/LifeMeterBattery.cpp @@ -64,7 +64,7 @@ void LifeMeterBattery::Load( PlayerNumber pn ) void LifeMeterBattery::OnSongEnded() { - if( g_CurStageStats.bFailedEarlier[m_PlayerNumber] ) + if( g_CurStageStats.m_player[m_PlayerNumber].bFailedEarlier ) return; if( m_iLivesLeft < GAMESTATE->m_SongOptions.m_iBatteryLives ) @@ -81,7 +81,7 @@ void LifeMeterBattery::OnSongEnded() void LifeMeterBattery::ChangeLife( TapNoteScore score ) { - if( g_CurStageStats.bFailedEarlier[m_PlayerNumber] ) + if( g_CurStageStats.m_player[m_PlayerNumber].bFailedEarlier ) return; switch( score ) @@ -108,7 +108,7 @@ void LifeMeterBattery::ChangeLife( TapNoteScore score ) ASSERT(0); } if( m_iLivesLeft == 0 ) - g_CurStageStats.bFailedEarlier[m_PlayerNumber] = true; + g_CurStageStats.m_player[m_PlayerNumber].bFailedEarlier = true; } void LifeMeterBattery::ChangeLife( HoldNoteScore score, TapNoteScore tscore ) @@ -151,7 +151,7 @@ bool LifeMeterBattery::IsHot() const bool LifeMeterBattery::IsFailing() const { - return g_CurStageStats.bFailedEarlier[m_PlayerNumber]; + return g_CurStageStats.m_player[m_PlayerNumber].bFailedEarlier; } float LifeMeterBattery::GetLife() const diff --git a/stepmania/src/NetworkSyncManager.cpp b/stepmania/src/NetworkSyncManager.cpp index 0ab9e800d8..6438678196 100644 --- a/stepmania/src/NetworkSyncManager.cpp +++ b/stepmania/src/NetworkSyncManager.cpp @@ -283,9 +283,9 @@ void NetworkSyncManager::ReportScore(int playerID, int step, int score, int comb uint8_t ctr = (uint8_t) (playerID * 16 + step - 1); m_packet.Write1(ctr); - ctr = uint8_t( g_CurStageStats.GetGrade((PlayerNumber)playerID)*16 ); + ctr = uint8_t( g_CurStageStats.m_player[playerID].GetGrade()*16 ); - if ( g_CurStageStats.bFailedEarlier[(PlayerNumber)playerID] ) + if ( g_CurStageStats.m_player[playerID].bFailedEarlier ) ctr = uint8_t( 112 ); //Code for failed (failed constant seems not to work) m_packet.Write1(ctr); diff --git a/stepmania/src/NoteDataWithScoring.cpp b/stepmania/src/NoteDataWithScoring.cpp index f50c27129f..00af78bb83 100644 --- a/stepmania/src/NoteDataWithScoring.cpp +++ b/stepmania/src/NoteDataWithScoring.cpp @@ -290,8 +290,8 @@ float NoteDataWithScoring::GetActualVoltageRadarValue( float fSongSeconds, Playe * might be on, and the way combo is counted varies depending on the mode and score * keeper. Instead, let's use the length of the longest recorded combo. This is * only subtly different: it's the percent of the song the longest combo took to get. */ - const StageStats::Combo_t MaxCombo = g_CurStageStats.GetMaxCombo( pn ); - float fComboPercent = SCALE( MaxCombo.fSizeSeconds, 0, g_CurStageStats.fLastSecond[pn]-g_CurStageStats.fFirstSecond[pn], 0.0f, 1.0f ); + const PlayerStageStats::Combo_t MaxCombo = g_CurStageStats.m_player[pn].GetMaxCombo(); + float fComboPercent = SCALE( MaxCombo.fSizeSeconds, 0, g_CurStageStats.m_player[pn].fLastSecond-g_CurStageStats.m_player[pn].fFirstSecond, 0.0f, 1.0f ); return clamp( fComboPercent, 0.0f, 1.0f ); } @@ -308,11 +308,11 @@ float NoteDataWithScoring::GetActualAirRadarValue( float fSongSeconds, PlayerNum float NoteDataWithScoring::GetActualChaosRadarValue( float fSongSeconds, PlayerNumber pn ) const { - const int PossibleDP = g_CurStageStats.iPossibleDancePoints[pn]; + const int PossibleDP = g_CurStageStats.m_player[pn].iPossibleDancePoints; if ( PossibleDP == 0 ) return 1; - const int ActualDP = g_CurStageStats.iActualDancePoints[pn]; + const int ActualDP = g_CurStageStats.m_player[pn].iActualDancePoints; return clamp( float(ActualDP)/PossibleDP, 0.0f, 1.0f ); } diff --git a/stepmania/src/PercentageDisplay.cpp b/stepmania/src/PercentageDisplay.cpp index a231448192..6ae877da24 100644 --- a/stepmania/src/PercentageDisplay.cpp +++ b/stepmania/src/PercentageDisplay.cpp @@ -64,7 +64,7 @@ void PercentageDisplay::Update( float fDeltaTime ) void PercentageDisplay::Refresh() { - const int iActualDancePoints = m_pSource->iActualDancePoints[m_PlayerNumber]; + const int iActualDancePoints = m_pSource->m_player[m_PlayerNumber].iActualDancePoints; if( iActualDancePoints == m_Last ) return; @@ -77,7 +77,7 @@ void PercentageDisplay::Refresh() } else { - float fPercentDancePoints = m_pSource->GetPercentDancePoints( m_PlayerNumber ); + float fPercentDancePoints = m_pSource->m_player[m_PlayerNumber].GetPercentDancePoints(); // clamp percentage - feedback is that negative numbers look weird here. CLAMP( fPercentDancePoints, 0.f, 1.f ); diff --git a/stepmania/src/Player.cpp b/stepmania/src/Player.cpp index baba98feba..b61154a035 100644 --- a/stepmania/src/Player.cpp +++ b/stepmania/src/Player.cpp @@ -127,7 +127,7 @@ void PlayerMinus::Load( // init steps m_NoteData.Init(); - bool bOniDead = GAMESTATE->m_SongOptions.m_LifeType == SongOptions::LIFE_BATTERY && g_CurStageStats.bFailed[pn]; + bool bOniDead = GAMESTATE->m_SongOptions.m_LifeType == SongOptions::LIFE_BATTERY && g_CurStageStats.m_player[pn].bFailed; if( !bOniDead ) m_NoteData.CopyAll( noteData ); @@ -137,7 +137,7 @@ void PlayerMinus::Load( m_Judgment.StopTweening(); // m_Combo.Reset(); // don't reset combos between songs in a course! m_Combo.Init( pn ); - m_Combo.SetCombo( g_CurStageStats.iCurCombo[pn], g_CurStageStats.iCurMissCombo[pn] ); // combo can persist between songs and games + m_Combo.SetCombo( g_CurStageStats.m_player[pn].iCurCombo, g_CurStageStats.m_player[pn].iCurMissCombo ); // combo can persist between songs and games m_AttackDisplay.Init( m_pPlayerState ); m_Judgment.Reset(); @@ -188,9 +188,11 @@ void PlayerMinus::Load( float fNoteFieldMidde = (GRAY_ARROWS_Y_STANDARD+GRAY_ARROWS_Y_REVERSE)/2; - m_pNoteField->SetY( fNoteFieldMidde ); + if( m_pNoteField ) + m_pNoteField->SetY( fNoteFieldMidde ); m_fNoteFieldHeight = GRAY_ARROWS_Y_REVERSE-GRAY_ARROWS_Y_STANDARD; - m_pNoteField->Load( &m_NoteData, m_pPlayerState, iStartDrawingAtPixels, iStopDrawingAtPixels, m_fNoteFieldHeight ); + if( m_pNoteField ) + m_pNoteField->Load( &m_NoteData, m_pPlayerState, iStartDrawingAtPixels, iStopDrawingAtPixels, m_fNoteFieldHeight ); m_ArrowBackdrop.SetPlayer( pn ); const bool bReverse = GAMESTATE->m_pPlayerState[pn]->m_PlayerOptions.GetReversePercentForColumn(0) == 1; @@ -278,7 +280,8 @@ void PlayerMinus::Update( float fDeltaTime ) const float fSongBeat = GAMESTATE->m_fSongBeat; const int iSongRow = BeatToNoteRow( fSongBeat ); - m_pNoteField->Update( fDeltaTime ); + if( m_pNoteField ) + m_pNoteField->Update( fDeltaTime ); // // Update Y positions @@ -304,12 +307,14 @@ void PlayerMinus::Update( float fDeltaTime ) m_ArrowBackdrop.SetY( fGrayYPos ); // NoteField accounts for reverse on its own now. -// m_pNoteField->SetY( fGrayYPos ); + //if( m_pNoteField ) + // m_pNoteField->SetY( fGrayYPos ); float fMiniPercent = m_pPlayerState->m_CurrentPlayerOptions.m_fEffects[PlayerOptions::EFFECT_MINI]; float fNoteFieldZoom = 1 - fMiniPercent*0.5f; float fJudgmentZoom = 1 - fMiniPercent*0.25f; - m_pNoteField->SetZoom( fNoteFieldZoom ); + if( m_pNoteField ) + m_pNoteField->SetZoom( fNoteFieldZoom ); m_Judgment.SetZoom( fJudgmentZoom ); // @@ -333,7 +338,8 @@ void PlayerMinus::Update( float fDeltaTime ) bool bIsHoldingButton = INPUTMAPPER->IsButtonDown( GameI ); // TODO: Make this work for non-human-controlled players if( bIsHoldingButton && !GAMESTATE->m_bDemonstrationOrJukebox && m_pPlayerState->m_PlayerController==PC_HUMAN ) - m_pNoteField->SetPressed( col ); + if( m_pNoteField ) + m_pNoteField->SetPressed( col ); } // @@ -344,8 +350,11 @@ void PlayerMinus::Update( float fDeltaTime ) const HoldNote &hn = m_NoteData.GetHoldNote(i); HoldNoteScore hns = m_NoteData.GetHoldNoteScore(hn); - m_pNoteField->m_HeldHoldNotes[hn] = false; // set hold flag so NoteField can do intelligent drawing - m_pNoteField->m_ActiveHoldNotes[hn] = false; // set hold flag so NoteField can do intelligent drawing + if( m_pNoteField ) + { + m_pNoteField->m_HeldHoldNotes[hn] = false; // set hold flag so NoteField can do intelligent drawing + m_pNoteField->m_ActiveHoldNotes[hn] = false; // set hold flag so NoteField can do intelligent drawing + } if( hns != HNS_NONE ) // if this HoldNote already has a result @@ -375,15 +384,23 @@ void PlayerMinus::Update( float fDeltaTime ) bIsHoldingButton = true; // set hold flag so NoteField can do intelligent drawing - m_pNoteField->m_HeldHoldNotes[hn] = bIsHoldingButton && bSteppedOnTapNote; - m_pNoteField->m_ActiveHoldNotes[hn] = bSteppedOnTapNote; + if( m_pNoteField ) + { + m_pNoteField->m_HeldHoldNotes[hn] = bIsHoldingButton && bSteppedOnTapNote; + m_pNoteField->m_ActiveHoldNotes[hn] = bSteppedOnTapNote; + } if( bSteppedOnTapNote ) { /* This hold note is not judged and we stepped on its head. Update * iLastHeldRow. */ - HoldNoteResult *hnr = m_pNoteField->CreateHoldNoteResult( hn ); - hnr->iLastHeldRow = min( iSongRow, hn.iEndRow ); + HoldNoteResult *hnr = NULL; + + if( m_pNoteField ) + { + hnr = m_pNoteField->CreateHoldNoteResult( hn ); + hnr->iLastHeldRow = min( iSongRow, hn.iEndRow ); + } hnr = m_NoteData.CreateHoldNoteResult( hn ); hnr->iLastHeldRow = min( iSongRow, hn.iEndRow ); @@ -395,7 +412,8 @@ void PlayerMinus::Update( float fDeltaTime ) // Increase life fLife = 1; - m_pNoteField->DidHoldNote( hn.iTrack ); // update the "electric ghost" effect + if( m_pNoteField ) + m_pNoteField->DidHoldNote( hn.iTrack ); // update the "electric ghost" effect } else { @@ -422,7 +440,8 @@ void PlayerMinus::Update( float fDeltaTime ) { fLife = 1; hns = HNS_OK; - m_pNoteField->DidTapNote( StyleI.col, TNS_PERFECT, true ); // bright ghost flash + if( m_pNoteField ) + m_pNoteField->DidTapNote( StyleI.col, TNS_PERFECT, true ); // bright ghost flash } if( hns != HNS_NONE ) @@ -436,13 +455,16 @@ void PlayerMinus::Update( float fDeltaTime ) // TODO: Remove use of PlayerNumber. PlayerNumber pn = m_pPlayerState->m_PlayerNumber; - g_CurStageStats.iTotalError[pn] += ms_error; + g_CurStageStats.m_player[pn].iTotalError += ms_error; if( hns == HNS_NG ) /* don't show a 0 for an OK */ m_ProTimingDisplay.SetJudgment( ms_error, TNS_MISS ); } - m_pNoteField->SetHoldNoteLife(hn, fLife); // update the NoteField display - m_pNoteField->SetHoldNoteScore(hn, hns); // update the NoteField display + if( m_pNoteField ) + { + m_pNoteField->SetHoldNoteLife(hn, fLife); // update the NoteField display + m_pNoteField->SetHoldNoteScore(hn, hns); // update the NoteField display + } m_NoteData.SetHoldNoteLife(hn, fLife); m_NoteData.SetHoldNoteScore(hn, hns); @@ -486,7 +508,8 @@ void PlayerMinus::Update( float fDeltaTime ) /* Cache any newly-used note skins. Normally, the only new skins cached now are * when we're adding course modifiers at the start of a song. If this is spending * time loading skins in the middle of a song, something is wrong. */ - m_pNoteField->CacheAllUsedNoteSkins(); + if( m_pNoteField ) + m_pNoteField->CacheAllUsedNoteSkins(); ActorFrame::Update( fDeltaTime ); } @@ -512,13 +535,17 @@ void PlayerMinus::ApplyWaitingTransforms() GAMESTATE->SetNoteSkinForBeatRange( m_pPlayerState, po.m_sNoteSkin, fStartBeat, fEndBeat ); NoteDataUtil::TransformNoteData( m_NoteData, po, GAMESTATE->GetCurrentStyle()->m_StepsType, fStartBeat, fEndBeat ); - m_pNoteField->CopyRange( m_NoteData, BeatToNoteRow(fStartBeat), BeatToNoteRow(fEndBeat), BeatToNoteRow(fStartBeat) ); + if( m_pNoteField ) + m_pNoteField->CopyRange( m_NoteData, BeatToNoteRow(fStartBeat), BeatToNoteRow(fEndBeat), BeatToNoteRow(fStartBeat) ); } m_pPlayerState->m_ModsToApply.clear(); } void PlayerMinus::DrawPrimitives() { + if( m_pNoteField == NULL ) + return; + // TODO: Remove use of PlayerNumber. PlayerNumber pn = m_pPlayerState->m_PlayerNumber; @@ -673,7 +700,7 @@ void PlayerMinus::Step( int col, RageTimer tm ) // TODO: Remove use of PlayerNumber. PlayerNumber pn = m_pPlayerState->m_PlayerNumber; - if( GAMESTATE->m_SongOptions.m_LifeType == SongOptions::LIFE_BATTERY && g_CurStageStats.bFailed[pn] ) // Oni dead + if( GAMESTATE->m_SongOptions.m_LifeType == SongOptions::LIFE_BATTERY && g_CurStageStats.m_player[pn].bFailed ) // Oni dead return; // do nothing //LOG->Trace( "PlayerMinus::HandlePlayerStep()" ); @@ -745,8 +772,11 @@ void PlayerMinus::Step( int col, RageTimer tm ) if( m_pCombinedLifeMeter ) m_pCombinedLifeMeter->ChangeLifeMine( pn ); - m_pNoteField->SetTapNote(col, iIndexOverlappingNote, TAP_EMPTY); // remove from NoteField - m_pNoteField->DidTapNote( col, score, false ); + if( m_pNoteField ) + { + m_pNoteField->SetTapNote(col, iIndexOverlappingNote, TAP_EMPTY); // remove from NoteField + m_pNoteField->DidTapNote( col, score, false ); + } } break; @@ -778,7 +808,8 @@ void PlayerMinus::Step( int col, RageTimer tm ) if( tn.type == TapNote::attack ) { m_NoteData.SetTapNote(col, iIndexOverlappingNote, TAP_EMPTY); // remove from NoteField - m_pNoteField->SetTapNote(col, iIndexOverlappingNote, TAP_EMPTY); // remove from NoteField + if( m_pNoteField ) + m_pNoteField->SetTapNote(col, iIndexOverlappingNote, TAP_EMPTY); // remove from NoteField } } } @@ -840,8 +871,11 @@ void PlayerMinus::Step( int col, RageTimer tm ) if( m_pCombinedLifeMeter ) m_pCombinedLifeMeter->ChangeLifeMine( pn ); - m_pNoteField->SetTapNote(col, iIndexOverlappingNote, TAP_EMPTY); // remove from NoteField - m_pNoteField->DidTapNote( col, score, false ); + if( m_pNoteField ) + { + m_pNoteField->SetTapNote(col, iIndexOverlappingNote, TAP_EMPTY); // remove from NoteField + m_pNoteField->DidTapNote( col, score, false ); + } } } @@ -880,7 +914,8 @@ void PlayerMinus::Step( int col, RageTimer tm ) if( tn.type == TapNote::attack ) { m_NoteData.SetTapNote(col, iIndexOverlappingNote, TAP_EMPTY); // remove from NoteField - m_pNoteField->SetTapNote(col, iIndexOverlappingNote, TAP_EMPTY); // remove from NoteField + if( m_pNoteField ) + m_pNoteField->SetTapNote(col, iIndexOverlappingNote, TAP_EMPTY); // remove from NoteField } } } @@ -912,7 +947,7 @@ void PlayerMinus::Step( int col, RageTimer tm ) // TODO: Remove use of PlayerNumber. PlayerNumber pn = m_pPlayerState->m_PlayerNumber; - g_CurStageStats.iTotalError[pn] += ms_error; + g_CurStageStats.m_player[pn].iTotalError += ms_error; if (!m_pPlayerState->m_PlayerOptions.m_fBlind) m_ProTimingDisplay.SetJudgment( ms_error, score ); } @@ -969,11 +1004,13 @@ void PlayerMinus::Step( int col, RageTimer tm ) m_iDCState = AS2D_FEVER; // super celebrate time :) } } - m_pNoteField->Step( col, score ); + if( m_pNoteField ) + m_pNoteField->Step( col, score ); } else { - m_pNoteField->Step( col, TNS_NONE ); + if( m_pNoteField ) + m_pNoteField->Step( col, TNS_NONE ); } /* Search for keyed sounds separately. If we can't find a nearby note, search @@ -1046,18 +1083,23 @@ void PlayerMinus::OnRowCompletelyJudged( int iIndexThatWasSteppedOn ) // If the score is great or better, remove the note from the screen to // indicate success. (Or always if blind is on.) if( score >= TNS_GREAT || m_pPlayerState->m_PlayerOptions.m_fBlind ) - m_pNoteField->SetTapNote(c, iIndexThatWasSteppedOn, TAP_EMPTY); + if( m_pNoteField ) + m_pNoteField->SetTapNote(c, iIndexThatWasSteppedOn, TAP_EMPTY); // show the ghost arrow for this column if (m_pPlayerState->m_PlayerOptions.m_fBlind) - m_pNoteField->DidTapNote( c, TNS_MARVELOUS, false ); + { + if( m_pNoteField ) + m_pNoteField->DidTapNote( c, TNS_MARVELOUS, false ); + } else { // TODO: Remove use of PlayerNumber. PlayerNumber pn = m_pPlayerState->m_PlayerNumber; - bool bBright = g_CurStageStats.iCurCombo[pn]>(int)BRIGHT_GHOST_COMBO_THRESHOLD; - m_pNoteField->DidTapNote( c, score, bBright ); + bool bBright = g_CurStageStats.m_player[pn].iCurCombo>(int)BRIGHT_GHOST_COMBO_THRESHOLD; + if( m_pNoteField ) + m_pNoteField->DidTapNote( c, score, bBright ); } } @@ -1118,7 +1160,7 @@ void PlayerMinus::UpdateTapNotesMissedOlderThan( float fMissIfOlderThanSeconds ) // TODO: Remove use of PlayerNumber. PlayerNumber pn = m_pPlayerState->m_PlayerNumber; - g_CurStageStats.iTotalError[pn] += MAX_PRO_TIMING_ERROR; + g_CurStageStats.m_player[pn].iTotalError += MAX_PRO_TIMING_ERROR; m_ProTimingDisplay.SetJudgment( MAX_PRO_TIMING_ERROR, TNS_MISS ); } } @@ -1219,10 +1261,13 @@ void PlayerMinus::RandomizeNotes( int iNoteRow ) m_NoteData.SetTapNote( t, iNewNoteRow, t2 ); m_NoteData.SetTapNote( iSwapWith, iNewNoteRow, t1 ); - const TapNote nft1 = m_pNoteField->GetTapNote( t, iNewNoteRow ); - const TapNote nft2 = m_pNoteField->GetTapNote( iSwapWith, iNewNoteRow ); - m_pNoteField->SetTapNote( t, iNewNoteRow, nft2 ); - m_pNoteField->SetTapNote( iSwapWith, iNewNoteRow, nft1 ); + if( m_pNoteField ) + { + const TapNote nft1 = m_pNoteField->GetTapNote( t, iNewNoteRow ); + const TapNote nft2 = m_pNoteField->GetTapNote( iSwapWith, iNewNoteRow ); + m_pNoteField->SetTapNote( t, iNewNoteRow, nft2 ); + m_pNoteField->SetTapNote( iSwapWith, iNewNoteRow, nft1 ); + } } } @@ -1247,18 +1292,18 @@ void PlayerMinus::HandleTapRowScore( unsigned row ) PlayerNumber pn = m_pPlayerState->m_PlayerNumber; /* Update miss combo, and handle "combo stopped" messages. */ - int &iCurCombo = g_CurStageStats.iCurCombo[pn]; + int &iCurCombo = g_CurStageStats.m_player[pn].iCurCombo; switch( scoreOfLastTap ) { case TNS_MARVELOUS: case TNS_PERFECT: case TNS_GREAT: - g_CurStageStats.iCurMissCombo[pn] = 0; + g_CurStageStats.m_player[pn].iCurMissCombo = 0; SCREENMAN->PostMessageToTopScreen( SM_MissComboAborted, 0 ); break; case TNS_MISS: - ++g_CurStageStats.iCurMissCombo[pn]; + ++g_CurStageStats.m_player[pn].iCurMissCombo; m_iDCState = AS2D_MISS; // update dancing 2d characters that may have missed a note case TNS_GOOD: case TNS_BOO: @@ -1272,14 +1317,14 @@ void PlayerMinus::HandleTapRowScore( unsigned row ) } /* The score keeper updates the hit combo. Remember the old combo for handling announcers. */ - const int iOldCombo = g_CurStageStats.iCurCombo[pn]; + const int iOldCombo = g_CurStageStats.m_player[pn].iCurCombo; if(m_pPrimaryScoreKeeper) m_pPrimaryScoreKeeper->HandleTapRowScore(scoreOfLastTap, iNumTapsInRow ); if(m_pSecondaryScoreKeeper) m_pSecondaryScoreKeeper->HandleTapRowScore(scoreOfLastTap, iNumTapsInRow ); - m_Combo.SetCombo( g_CurStageStats.iCurCombo[pn], g_CurStageStats.iCurMissCombo[pn] ); + m_Combo.SetCombo( g_CurStageStats.m_player[pn].iCurCombo, g_CurStageStats.m_player[pn].iCurMissCombo ); #define CROSSED( x ) (iOldCombo=x) if ( CROSSED(100) ) @@ -1307,16 +1352,18 @@ void PlayerMinus::HandleTapRowScore( unsigned row ) #undef CROSSED // new max combo - g_CurStageStats.iMaxCombo[pn] = max(g_CurStageStats.iMaxCombo[pn], iCurCombo); + g_CurStageStats.m_player[pn].iMaxCombo = max(g_CurStageStats.m_player[pn].iMaxCombo, iCurCombo); /* Use the real current beat, not the beat we've been passed. That's because we * want to record the current life/combo to the current time; eg. if it's a MISS, * the beat we're registering is in the past, but the life is changing now. */ - g_CurStageStats.UpdateComboList( pn, g_CurStageStats.fAliveSeconds[pn], false ); + g_CurStageStats.m_player[pn].UpdateComboList( g_CurStageStats.m_player[pn].fAliveSeconds, false ); float life = -1; if( m_pLifeMeter ) + { life = m_pLifeMeter->GetLife(); + } else if( m_pCombinedLifeMeter ) { life = GAMESTATE->m_fTugLifePercentP1; @@ -1324,12 +1371,12 @@ void PlayerMinus::HandleTapRowScore( unsigned row ) life = 1.0f - life; } if( life != -1 ) - g_CurStageStats.SetLifeRecordAt( pn, life, g_CurStageStats.fAliveSeconds[pn] ); + g_CurStageStats.m_player[pn].SetLifeRecordAt( life, g_CurStageStats.m_player[pn].fAliveSeconds ); if (m_pScoreDisplay) - m_pScoreDisplay->SetScore(g_CurStageStats.iScore[pn]); + m_pScoreDisplay->SetScore(g_CurStageStats.m_player[pn].iScore); if (m_pSecondaryScoreDisplay) - m_pSecondaryScoreDisplay->SetScore(g_CurStageStats.iScore[pn]); + m_pSecondaryScoreDisplay->SetScore(g_CurStageStats.m_player[pn].iScore); if( m_pLifeMeter ) { m_pLifeMeter->ChangeLife( scoreOfLastTap ); @@ -1364,9 +1411,9 @@ void PlayerMinus::HandleHoldScore( HoldNoteScore holdScore, TapNoteScore tapScor PlayerNumber pn = m_pPlayerState->m_PlayerNumber; if (m_pScoreDisplay) - m_pScoreDisplay->SetScore(g_CurStageStats.iScore[pn]); + m_pScoreDisplay->SetScore(g_CurStageStats.m_player[pn].iScore); if (m_pSecondaryScoreDisplay) - m_pSecondaryScoreDisplay->SetScore(g_CurStageStats.iScore[pn]); + m_pSecondaryScoreDisplay->SetScore(g_CurStageStats.m_player[pn].iScore); if( m_pLifeMeter ) { @@ -1387,7 +1434,8 @@ float PlayerMinus::GetMaxStepDistanceSeconds() void PlayerMinus::FadeToFail() { - m_pNoteField->FadeToFail(); + if( m_pNoteField ) + m_pNoteField->FadeToFail(); } /* XXX: Why's m_NoteField in a separate class, again? Is that still needed? */ diff --git a/stepmania/src/PlayerState.h b/stepmania/src/PlayerState.h index 0d814d4f21..52574aab08 100644 --- a/stepmania/src/PlayerState.h +++ b/stepmania/src/PlayerState.h @@ -10,6 +10,41 @@ struct PlayerState { + PlayerState() + { + m_PlayerNumber = PLAYER_INVALID; + Reset(); + } + void Reset() + { + m_CurrentPlayerOptions.Init(); + m_PlayerOptions.Init(); + m_StoredPlayerOptions.Init(); + + m_BeatToNoteSkin.clear(); + m_fLastDrawnBeat = -100; + + m_HealthState = ALIVE; + + m_PlayerController = PC_HUMAN; + + m_iCpuSkill = 5; + + m_iLastPositiveSumOfAttackLevels = 0; + m_fSecondsUntilAttacksPhasedOut = 0; + m_bAttackBeganThisUpdate = false; + m_bAttackEndedThisUpdate = false; + m_ActiveAttacks.clear(); + m_ModsToApply.clear(); + + m_fSuperMeter = 0; // between 0 and NUM_ATTACK_LEVELS + m_fSuperMeterGrowthScale = 1; + + for( int i=0; iIsPlayerEnabled(pn) ) - fSecsIntoPlay = g_CurStageStats.fAliveSeconds[pn]; + fSecsIntoPlay = g_CurStageStats.m_player[pn].fAliveSeconds; m_text.SetText( SecondsToMMSSMsMs(fSecsIntoPlay) ); } diff --git a/stepmania/src/ScoreKeeperMAX2.cpp b/stepmania/src/ScoreKeeperMAX2.cpp index cfeded18ad..57c15bff2d 100644 --- a/stepmania/src/ScoreKeeperMAX2.cpp +++ b/stepmania/src/ScoreKeeperMAX2.cpp @@ -66,7 +66,7 @@ ScoreKeeperMAX2::ScoreKeeperMAX2( const vector& apSongs, const vectorm_PlayerNumber; - g_CurStageStats.iPossibleDancePoints[pn] = iTotalPossibleDancePoints; + g_CurStageStats.m_player[pn].iPossibleDancePoints = iTotalPossibleDancePoints; } @@ -206,7 +206,7 @@ void ScoreKeeperMAX2::AddScore( TapNoteScore score ) { // TODO: Move StageStats numbers into PlayerState. PlayerNumber pn = m_pPlayerState->m_PlayerNumber; - int &iScore = g_CurStageStats.iScore[pn]; + int &iScore = g_CurStageStats.m_player[pn].iScore; /* http://www.aaroninjapan.com/ddr2.html @@ -266,7 +266,7 @@ void ScoreKeeperMAX2::AddScore( TapNoteScore score ) const int B = m_iMaxPossiblePoints/10; // Don't use a multiplier if the player has failed - if( g_CurStageStats.bFailedEarlier[pn] ) + if( g_CurStageStats.m_player[pn].bFailedEarlier ) { iScore += p; // make score evenly divisible by 5 @@ -279,8 +279,8 @@ void ScoreKeeperMAX2::AddScore( TapNoteScore score ) else { iScore += GetScore(p, B, sum, m_iTapNotesHit); - const int &iCurrentCombo = g_CurStageStats.iCurCombo[pn]; - g_CurStageStats.iBonus[pn] += m_ComboBonusFactor[score] * iCurrentCombo; + const int &iCurrentCombo = g_CurStageStats.m_player[pn].iCurCombo; + g_CurStageStats.m_player[pn].iBonus += m_ComboBonusFactor[score] * iCurrentCombo; } /* Subtract the maximum this step could have been worth from the bonus. */ @@ -288,7 +288,7 @@ void ScoreKeeperMAX2::AddScore( TapNoteScore score ) if ( m_iTapNotesHit == m_iNumTapsAndHolds && score >= TNS_PERFECT ) { - if (!g_CurStageStats.bFailedEarlier[pn]) + if (!g_CurStageStats.m_player[pn].bFailedEarlier) iScore += m_iPointBonus; if ( m_bIsLastSongInCourse ) { @@ -320,8 +320,8 @@ void ScoreKeeperMAX2::HandleTapScore( TapNoteScore score ) if( score == TNS_HIT_MINE ) { if( m_pPlayerState->m_HealthState != PlayerState::DEAD ) - g_CurStageStats.iActualDancePoints[pn] += TapNoteScoreToDancePoints( TNS_HIT_MINE ); - g_CurStageStats.iTapNoteScores[pn][TNS_HIT_MINE] += 1; + g_CurStageStats.m_player[pn].iActualDancePoints += TapNoteScoreToDancePoints( TNS_HIT_MINE ); + g_CurStageStats.m_player[pn].iTapNoteScores[TNS_HIT_MINE] += 1; } } @@ -334,9 +334,9 @@ void ScoreKeeperMAX2::HandleTapRowScore( TapNoteScore scoreOfLastTap, int iNumTa // Update dance points. if( m_pPlayerState->m_HealthState != PlayerState::DEAD ) - g_CurStageStats.iActualDancePoints[pn] += TapNoteScoreToDancePoints( scoreOfLastTap ); + g_CurStageStats.m_player[pn].iActualDancePoints += TapNoteScoreToDancePoints( scoreOfLastTap ); // update judged row totals - g_CurStageStats.iTapNoteScores[pn][scoreOfLastTap] += 1; + g_CurStageStats.m_player[pn].iTapNoteScores[scoreOfLastTap] += 1; // // Regular combo @@ -367,7 +367,7 @@ void ScoreKeeperMAX2::HandleTapRowScore( TapNoteScore scoreOfLastTap, int iNumTa TapNoteScore MinScoreToContinueCombo = GAMESTATE->m_PlayMode == PLAY_MODE_ONI? TNS_PERFECT:TNS_GREAT; if( scoreOfLastTap >= MinScoreToContinueCombo ) - g_CurStageStats.iCurCombo[pn] += ComboCountIfHit; + g_CurStageStats.m_player[pn].iCurCombo += ComboCountIfHit; AddScore( scoreOfLastTap ); // only score once per row @@ -409,8 +409,8 @@ void ScoreKeeperMAX2::HandleTapRowScore( TapNoteScore scoreOfLastTap, int iNumTa // TODO: Remove indexing with PlayerNumber NSMAN->ReportScore(pn, scoreOfLastTap, - g_CurStageStats.iScore[pn], - g_CurStageStats.iCurCombo[pn]); + g_CurStageStats.m_player[pn].iScore, + g_CurStageStats.m_player[pn].iCurCombo); } @@ -421,15 +421,17 @@ void ScoreKeeperMAX2::HandleHoldScore( HoldNoteScore holdScore, TapNoteScore tap // update dance points totals if( m_pPlayerState->m_HealthState != PlayerState::DEAD ) - g_CurStageStats.iActualDancePoints[pn] += HoldNoteScoreToDancePoints( holdScore ); - g_CurStageStats.iHoldNoteScores[pn][holdScore] ++; + g_CurStageStats.m_player[pn].iActualDancePoints += HoldNoteScoreToDancePoints( holdScore ); + g_CurStageStats.m_player[pn].iHoldNoteScores[holdScore] ++; if( holdScore == HNS_OK ) AddScore( TNS_MARVELOUS ); - NSMAN->ReportScore(pn, holdScore+7, - g_CurStageStats.iScore[pn], - g_CurStageStats.iCurCombo[pn]); + NSMAN->ReportScore( + pn, + holdScore+7, + g_CurStageStats.m_player[pn].iScore, + g_CurStageStats.m_player[pn].iCurCombo ); } diff --git a/stepmania/src/ScreenEnding.cpp b/stepmania/src/ScreenEnding.cpp index 93ac44d2e7..88759916dd 100644 --- a/stepmania/src/ScreenEnding.cpp +++ b/stepmania/src/ScreenEnding.cpp @@ -151,8 +151,8 @@ ScreenEnding::ScreenEnding( CString sClassName ) : ScreenAttract( sClassName, fa GAMESTATE->m_pCurCourse = SONGMAN->GetRandomCourse(); GAMESTATE->m_pCurSteps[PLAYER_1] = GAMESTATE->m_pCurSong->GetAllSteps()[0]; GAMESTATE->m_pCurSteps[PLAYER_2] = GAMESTATE->m_pCurSong->GetAllSteps()[0]; - g_CurStageStats.vpSteps[PLAYER_1].push_back( GAMESTATE->m_pCurSteps[PLAYER_1] ); - g_CurStageStats.vpSteps[PLAYER_2].push_back( GAMESTATE->m_pCurSteps[PLAYER_2] ); + g_CurStageStats.m_player[PLAYER_1].vpSteps.push_back( GAMESTATE->m_pCurSteps[PLAYER_1] ); + g_CurStageStats.m_player[PLAYER_2].vpSteps.push_back( GAMESTATE->m_pCurSteps[PLAYER_2] ); GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions.m_fScrollSpeed = 2; GAMESTATE->m_pPlayerState[PLAYER_2]->m_PlayerOptions.m_fScrollSpeed = 2; GAMESTATE->m_iCurrentStageIndex = 0; @@ -162,29 +162,29 @@ ScreenEnding::ScreenEnding( CString sClassName ) : ScreenAttract( sClassName, fa for( float f = 0; f < 100.0f; f += 1.0f ) { float fP1 = fmodf(f/100*4+.3f,1); - g_CurStageStats.SetLifeRecordAt( PLAYER_1, fP1, f ); - g_CurStageStats.SetLifeRecordAt( PLAYER_2, 1-fP1, f ); + g_CurStageStats.m_player[PLAYER_1].SetLifeRecordAt( fP1, f ); + g_CurStageStats.m_player[PLAYER_2].SetLifeRecordAt( 1-fP1, f ); } - g_CurStageStats.iActualDancePoints[PLAYER_1] = rand()%3; - g_CurStageStats.iPossibleDancePoints[PLAYER_1] = 2; - g_CurStageStats.iActualDancePoints[PLAYER_2] = rand()%2; - g_CurStageStats.iPossibleDancePoints[PLAYER_2] = 1; - g_CurStageStats.iCurCombo[PLAYER_1] = 0; - g_CurStageStats.UpdateComboList( PLAYER_1, 0, false ); - g_CurStageStats.iCurCombo[PLAYER_1] = 1; - g_CurStageStats.UpdateComboList( PLAYER_1, 1, false ); - g_CurStageStats.iCurCombo[PLAYER_1] = 50; - g_CurStageStats.UpdateComboList( PLAYER_1, 25, false ); - g_CurStageStats.iCurCombo[PLAYER_1] = 250; - g_CurStageStats.UpdateComboList( PLAYER_1, 100, false ); + g_CurStageStats.m_player[PLAYER_1].iActualDancePoints = rand()%3; + g_CurStageStats.m_player[PLAYER_1].iPossibleDancePoints = 2; + g_CurStageStats.m_player[PLAYER_2].iActualDancePoints = rand()%2; + g_CurStageStats.m_player[PLAYER_2].iPossibleDancePoints = 1; + g_CurStageStats.m_player[PLAYER_1].iCurCombo = 0; + g_CurStageStats.m_player[PLAYER_1].UpdateComboList( 0, false ); + g_CurStageStats.m_player[PLAYER_1].iCurCombo = 1; + g_CurStageStats.m_player[PLAYER_1].UpdateComboList( 1, false ); + g_CurStageStats.m_player[PLAYER_1].iCurCombo = 50; + g_CurStageStats.m_player[PLAYER_1].UpdateComboList( 25, false ); + g_CurStageStats.m_player[PLAYER_1].iCurCombo = 250; + g_CurStageStats.m_player[PLAYER_1].UpdateComboList( 100, false ); - g_CurStageStats.iTapNoteScores[PLAYER_1][TNS_MARVELOUS] = rand()%2; - g_CurStageStats.iTapNoteScores[PLAYER_1][TNS_PERFECT] = rand()%2; - g_CurStageStats.iTapNoteScores[PLAYER_1][TNS_GREAT] = rand()%2; - g_CurStageStats.iTapNoteScores[PLAYER_2][TNS_MARVELOUS] = rand()%2; - g_CurStageStats.iTapNoteScores[PLAYER_2][TNS_PERFECT] = rand()%2; - g_CurStageStats.iTapNoteScores[PLAYER_2][TNS_GREAT] = rand()%2; + g_CurStageStats.m_player[PLAYER_1].iTapNoteScores[TNS_MARVELOUS] = rand()%2; + g_CurStageStats.m_player[PLAYER_1].iTapNoteScores[TNS_PERFECT] = rand()%2; + g_CurStageStats.m_player[PLAYER_1].iTapNoteScores[TNS_GREAT] = rand()%2; + g_CurStageStats.m_player[PLAYER_2].iTapNoteScores[TNS_MARVELOUS] = rand()%2; + g_CurStageStats.m_player[PLAYER_2].iTapNoteScores[TNS_PERFECT] = rand()%2; + g_CurStageStats.m_player[PLAYER_2].iTapNoteScores[TNS_GREAT] = rand()%2; g_vPlayedStageStats.clear(); } diff --git a/stepmania/src/ScreenEvaluation.cpp b/stepmania/src/ScreenEvaluation.cpp index 04544714fd..059f0cb12c 100644 --- a/stepmania/src/ScreenEvaluation.cpp +++ b/stepmania/src/ScreenEvaluation.cpp @@ -112,8 +112,8 @@ void ScreenEvaluation::Init() GAMESTATE->m_pCurCourse = SONGMAN->GetRandomCourse(); GAMESTATE->m_pCurSteps[PLAYER_1] = GAMESTATE->m_pCurSong->GetAllSteps()[0]; GAMESTATE->m_pCurSteps[PLAYER_2] = GAMESTATE->m_pCurSong->GetAllSteps()[0]; - g_CurStageStats.vpSteps[PLAYER_1].push_back( GAMESTATE->m_pCurSteps[PLAYER_1] ); - g_CurStageStats.vpSteps[PLAYER_2].push_back( GAMESTATE->m_pCurSteps[PLAYER_2] ); + g_CurStageStats.m_player[PLAYER_1].vpSteps.push_back( GAMESTATE->m_pCurSteps[PLAYER_1] ); + g_CurStageStats.m_player[PLAYER_2].vpSteps.push_back( GAMESTATE->m_pCurSteps[PLAYER_2] ); GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions.m_fScrollSpeed = 2; GAMESTATE->m_pPlayerState[PLAYER_2]->m_PlayerOptions.m_fScrollSpeed = 2; GAMESTATE->m_iCurrentStageIndex = 0; @@ -123,47 +123,47 @@ void ScreenEvaluation::Init() for( float f = 0; f < 100.0f; f += 1.0f ) { float fP1 = fmodf(f/100*4+.3f,1); - g_CurStageStats.SetLifeRecordAt( PLAYER_1, fP1, f ); - g_CurStageStats.SetLifeRecordAt( PLAYER_2, 1-fP1, f ); + g_CurStageStats.m_player[PLAYER_1].SetLifeRecordAt( fP1, f ); + g_CurStageStats.m_player[PLAYER_2].SetLifeRecordAt( 1-fP1, f ); } - g_CurStageStats.iActualDancePoints[PLAYER_1] = rand()%3; - g_CurStageStats.iPossibleDancePoints[PLAYER_1] = 2; - g_CurStageStats.iActualDancePoints[PLAYER_2] = rand()%2; - g_CurStageStats.iPossibleDancePoints[PLAYER_2] = 1; - g_CurStageStats.iCurCombo[PLAYER_1] = 0; - g_CurStageStats.UpdateComboList( PLAYER_1, 0, false ); - g_CurStageStats.iCurCombo[PLAYER_1] = 1; - g_CurStageStats.UpdateComboList( PLAYER_1, 1, false ); - g_CurStageStats.iCurCombo[PLAYER_1] = 50; - g_CurStageStats.UpdateComboList( PLAYER_1, 25, false ); - g_CurStageStats.iCurCombo[PLAYER_1] = 250; - g_CurStageStats.UpdateComboList( PLAYER_1, 100, false ); + g_CurStageStats.m_player[PLAYER_1].iActualDancePoints = rand()%3; + g_CurStageStats.m_player[PLAYER_1].iPossibleDancePoints = 2; + g_CurStageStats.m_player[PLAYER_2].iActualDancePoints = rand()%2; + g_CurStageStats.m_player[PLAYER_2].iPossibleDancePoints = 1; + g_CurStageStats.m_player[PLAYER_1].iCurCombo = 0; + g_CurStageStats.m_player[PLAYER_1].UpdateComboList( 0, false ); + g_CurStageStats.m_player[PLAYER_1].iCurCombo = 1; + g_CurStageStats.m_player[PLAYER_1].UpdateComboList( 1, false ); + g_CurStageStats.m_player[PLAYER_1].iCurCombo = 50; + g_CurStageStats.m_player[PLAYER_1].UpdateComboList( 25, false ); + g_CurStageStats.m_player[PLAYER_1].iCurCombo = 250; + g_CurStageStats.m_player[PLAYER_1].UpdateComboList( 100, false ); if( rand()%2 ) { - g_CurStageStats.iCurCombo[PLAYER_1] = rand()%11000; - g_CurStageStats.UpdateComboList( PLAYER_1, 110, false ); + g_CurStageStats.m_player[PLAYER_1].iCurCombo = rand()%11000; + g_CurStageStats.m_player[PLAYER_1].UpdateComboList( 110, false ); } - g_CurStageStats.iCurCombo[PLAYER_2] = 0; - g_CurStageStats.UpdateComboList( PLAYER_2, 0, false ); - g_CurStageStats.iCurCombo[PLAYER_2] = 1; - g_CurStageStats.UpdateComboList( PLAYER_2, 1, false ); - g_CurStageStats.iCurCombo[PLAYER_2] = 50; - g_CurStageStats.UpdateComboList( PLAYER_2, 25, false ); - g_CurStageStats.iCurCombo[PLAYER_2] = 250; - g_CurStageStats.UpdateComboList( PLAYER_2, 100, false ); + g_CurStageStats.m_player[PLAYER_2].iCurCombo = 0; + g_CurStageStats.m_player[PLAYER_2].UpdateComboList( 0, false ); + g_CurStageStats.m_player[PLAYER_2].iCurCombo = 1; + g_CurStageStats.m_player[PLAYER_2].UpdateComboList( 1, false ); + g_CurStageStats.m_player[PLAYER_2].iCurCombo = 50; + g_CurStageStats.m_player[PLAYER_2].UpdateComboList( 25, false ); + g_CurStageStats.m_player[PLAYER_2].iCurCombo = 250; + g_CurStageStats.m_player[PLAYER_2].UpdateComboList( 100, false ); if( rand()%2 ) { - g_CurStageStats.iCurCombo[PLAYER_2] = rand()%11000; - g_CurStageStats.UpdateComboList( PLAYER_2, 110, false ); + g_CurStageStats.m_player[PLAYER_2].iCurCombo = rand()%11000; + g_CurStageStats.m_player[PLAYER_2].UpdateComboList( 110, false ); } - g_CurStageStats.iTapNoteScores[PLAYER_1][TNS_MARVELOUS] = rand()%3; - g_CurStageStats.iTapNoteScores[PLAYER_1][TNS_PERFECT] = rand()%3; - g_CurStageStats.iTapNoteScores[PLAYER_1][TNS_GREAT] = rand()%3; - g_CurStageStats.iTapNoteScores[PLAYER_2][TNS_MARVELOUS] = rand()%3; - g_CurStageStats.iTapNoteScores[PLAYER_2][TNS_PERFECT] = rand()%3; - g_CurStageStats.iTapNoteScores[PLAYER_2][TNS_GREAT] = rand()%3; + g_CurStageStats.m_player[PLAYER_1].iTapNoteScores[TNS_MARVELOUS] = rand()%3; + g_CurStageStats.m_player[PLAYER_1].iTapNoteScores[TNS_PERFECT] = rand()%3; + g_CurStageStats.m_player[PLAYER_1].iTapNoteScores[TNS_GREAT] = rand()%3; + g_CurStageStats.m_player[PLAYER_2].iTapNoteScores[TNS_MARVELOUS] = rand()%3; + g_CurStageStats.m_player[PLAYER_2].iTapNoteScores[TNS_PERFECT] = rand()%3; + g_CurStageStats.m_player[PLAYER_2].iTapNoteScores[TNS_GREAT] = rand()%3; g_vPlayedStageStats.clear(); } @@ -205,7 +205,7 @@ void ScreenEvaluation::Init() ASSERT(0); } - LOG->Trace( "total error: %i, %i", stageStats.iTotalError[0], stageStats.iTotalError[1] ); + LOG->Trace( "total error: %i, %i", stageStats.m_player[PLAYER_1].iTotalError, stageStats.m_player[PLAYER_2].iTotalError ); /* // @@ -229,7 +229,7 @@ void ScreenEvaluation::Init() FOREACH_PlayerNumber( p ) { if( GAMESTATE->IsPlayerEnabled(p) ) - grade[p] = stageStats.GetGrade( p ); + grade[p] = stageStats.m_player[p].GetGrade(); else grade[p] = GRADE_FAILED; @@ -238,8 +238,8 @@ void ScreenEvaluation::Init() const int ScoreBonuses[] = { 10000000, 10000000, 1000000, 100000, 10000, 1000, 100 }; if( grade[p] < (int) ARRAYSIZE(ScoreBonuses) ) { - g_CurStageStats.iBonus[p] += ScoreBonuses[(int)grade[p] ]; - stageStats.iBonus[p] += ScoreBonuses[(int)grade[p] ]; + g_CurStageStats.m_player[p].iBonus += ScoreBonuses[(int)grade[p] ]; + stageStats.m_player[p].iBonus += ScoreBonuses[(int)grade[p] ]; } } } @@ -536,14 +536,14 @@ void ScreenEvaluation::Init() for( int r=0; rGetPathToG(ssprintf("ScreenEvaluation bar possible p%d",p+1)) ); - m_sprPossibleBar[p][r].SetWidth( m_sprPossibleBar[p][r].GetUnzoomedWidth() * stageStats.radarPossible[p][r] ); + m_sprPossibleBar[p][r].SetWidth( m_sprPossibleBar[p][r].GetUnzoomedWidth() * stageStats.m_player[p].radarPossible[r] ); m_sprPossibleBar[p][r].SetName( ssprintf("BarPossible%dP%d",r+1,p+1) ); SET_XY_AND_ON_COMMAND( m_sprPossibleBar[p][r] ); this->AddChild( &m_sprPossibleBar[p][r] ); m_sprActualBar[p][r].Load( THEME->GetPathToG(ssprintf("ScreenEvaluation bar actual p%d",p+1)) ); // should be out of the possible bar, not actual (whatever value that is at) - m_sprActualBar[p][r].SetWidth( m_sprPossibleBar[p][r].GetUnzoomedWidth() * stageStats.radarActual[p][r] ); + m_sprActualBar[p][r].SetWidth( m_sprPossibleBar[p][r].GetUnzoomedWidth() * stageStats.m_player[p].radarActual[r] ); float value = (float)100 * m_sprActualBar[p][r].GetUnzoomedWidth() / m_sprPossibleBar[p][r].GetUnzoomedWidth(); LOG->Trace("Radar bar %d of 5 - %f percent", r, value); @@ -552,7 +552,7 @@ void ScreenEvaluation::Init() SET_XY_AND_ON_COMMAND( m_sprActualBar[p][r] ); // .99999 is fairly close to 1.00, so we use that - if( stageStats.radarActual[p][r] > 0.99999f ) + if( stageStats.m_player[p].radarActual[r] > 0.99999f ) m_sprActualBar[p][r].RunCommands( BAR_ACTUAL_MAX_COMMAND ); this->AddChild( &m_sprActualBar[p][r] ); } @@ -575,7 +575,7 @@ void ScreenEvaluation::Init() m_textSurvivedNumber[p].SetShadowLength( 0 ); // curewater: edited the "# stages cleared" text so it deducts one if you failed. // Should be accurate, but I'm not sure if its "standard" that (bool)true = 1. (assumption) - m_textSurvivedNumber[p].SetText( ssprintf("%02d", stageStats.iSongsPlayed[p] - (int)stageStats.bFailed[p]) ); + m_textSurvivedNumber[p].SetText( ssprintf("%02d", stageStats.m_player[p].iSongsPlayed - (int)stageStats.m_player[p].bFailed) ); m_textSurvivedNumber[p].SetName( ssprintf("SurvivedNumberP%d",p+1) ); SET_XY_AND_ON_COMMAND( m_textSurvivedNumber[p] ); this->AddChild( &m_textSurvivedNumber[p] ); @@ -634,15 +634,15 @@ void ScreenEvaluation::Init() int iValue; switch( l ) { - case marvelous: iValue = stageStats.iTapNoteScores[p][TNS_MARVELOUS]; break; - case perfect: iValue = stageStats.iTapNoteScores[p][TNS_PERFECT]; break; - case great: iValue = stageStats.iTapNoteScores[p][TNS_GREAT]; break; - case good: iValue = stageStats.iTapNoteScores[p][TNS_GOOD]; break; - case boo: iValue = stageStats.iTapNoteScores[p][TNS_BOO]; break; - case miss: iValue = stageStats.iTapNoteScores[p][TNS_MISS]; break; - case ok: iValue = stageStats.iHoldNoteScores[p][HNS_OK]; break; - case max_combo: iValue = stageStats.GetMaxCombo(p).cnt; break; - case error: iValue = stageStats.iTotalError[p]; break; + case marvelous: iValue = stageStats.m_player[p].iTapNoteScores[TNS_MARVELOUS]; break; + case perfect: iValue = stageStats.m_player[p].iTapNoteScores[TNS_PERFECT]; break; + case great: iValue = stageStats.m_player[p].iTapNoteScores[TNS_GREAT]; break; + case good: iValue = stageStats.m_player[p].iTapNoteScores[TNS_GOOD]; break; + case boo: iValue = stageStats.m_player[p].iTapNoteScores[TNS_BOO]; break; + case miss: iValue = stageStats.m_player[p].iTapNoteScores[TNS_MISS]; break; + case ok: iValue = stageStats.m_player[p].iHoldNoteScores[HNS_OK]; break; + case max_combo: iValue = stageStats.m_player[p].GetMaxCombo().cnt; break; + case error: iValue = stageStats.m_player[p].iTotalError; break; default: iValue = 0; ASSERT(0); } @@ -677,8 +677,8 @@ void ScreenEvaluation::Init() RADAR_NUM_JUMPS, RADAR_NUM_HOLDS, RADAR_NUM_MINES, RADAR_NUM_HANDS }; const int ind = indeces[l]; - const int iActual = (int) roundf(stageStats.radarActual[p][ind]); - const int iPossible = (int) roundf(stageStats.radarPossible[p][ind]); + const int iActual = (int) roundf(stageStats.m_player[p].radarActual[ind]); + const int iPossible = (int) roundf(stageStats.m_player[p].radarPossible[ind]); m_textStatsText[l][p].SetText( ssprintf("%3d/%3d",iActual,iPossible) ); } @@ -701,7 +701,7 @@ void ScreenEvaluation::Init() m_textScore[p].SetDiffuse( PlayerToColor(p) ); m_textScore[p].SetName( ssprintf("ScoreNumberP%d",p+1) ); SET_XY_AND_ON_COMMAND( m_textScore[p] ); - m_textScore[p].SetText( ssprintf("%*.0i", NUM_SCORE_DIGITS, stageStats.iScore[p]) ); + m_textScore[p].SetText( ssprintf("%*.0i", NUM_SCORE_DIGITS, stageStats.m_player[p].iScore) ); this->AddChild( &m_textScore[p] ); } } @@ -717,9 +717,9 @@ void ScreenEvaluation::Init() { int iTotalScore=0; for( unsigned i=0; iGetPathF(m_sName, "totalscore") ); m_textTotalScore[p].SetShadowLength( 0 ); @@ -749,7 +749,7 @@ void ScreenEvaluation::Init() m_textTime[p].SetDiffuse( PlayerToColor(p) ); m_textTime[p].SetName( ssprintf("TimeNumberP%d",p+1) ); SET_XY_AND_ON_COMMAND( m_textTime[p] ); - m_textTime[p].SetText( SecondsToMMSSMsMs(stageStats.fAliveSeconds[p]) ); + m_textTime[p].SetText( SecondsToMMSSMsMs(stageStats.m_player[p].fAliveSeconds) ); this->AddChild( &m_textTime[p] ); } } @@ -927,18 +927,18 @@ void ScreenEvaluation::CommitScores( HighScore &hs = m_HighScore[p]; hs.sName = RANKING_TO_FILL_IN_MARKER[p]; - hs.grade = stageStats.GetGrade( p ); - hs.iScore = stageStats.iScore[p]; - hs.fPercentDP = stageStats.GetPercentDancePoints( p ); - hs.fSurviveSeconds = stageStats.fAliveSeconds[p]; + hs.grade = stageStats.m_player[p].GetGrade(); + hs.iScore = stageStats.m_player[p].iScore; + hs.fPercentDP = stageStats.m_player[p].GetPercentDancePoints(); + hs.fSurviveSeconds = stageStats.m_player[p].fAliveSeconds; hs.sModifiers = GAMESTATE->m_pPlayerState[p]->m_PlayerOptions.GetString(); hs.dateTime = DateTime::GetNowDateTime(); hs.sPlayerGuid = PROFILEMAN->IsUsingProfile(p) ? PROFILEMAN->GetProfile(p)->m_sGuid : CString(""); hs.sMachineGuid = PROFILEMAN->GetMachineProfile()->m_sGuid; hs.iProductID = PREFSMAN->m_iProductID; - memcpy( hs.iTapNoteScores, stageStats.iTapNoteScores[p], sizeof(hs.iTapNoteScores) ); - memcpy( hs.iHoldNoteScores, stageStats.iHoldNoteScores[p], sizeof(hs.iHoldNoteScores) ); - hs.radarValues = stageStats.radarActual[p]; + memcpy( hs.iTapNoteScores, stageStats.m_player[p].iTapNoteScores, sizeof(hs.iTapNoteScores) ); + memcpy( hs.iHoldNoteScores, stageStats.m_player[p].iHoldNoteScores, sizeof(hs.iHoldNoteScores) ); + hs.radarValues = stageStats.m_player[p].radarActual; StepsType st = GAMESTATE->GetCurrentStyle()->m_StepsType; @@ -947,7 +947,7 @@ void ScreenEvaluation::CommitScores( case stage: { // don't save scores for a failed song - if( stageStats.bFailed[p] ) + if( stageStats.m_player[p].bFailed ) continue; ASSERT( pSteps ); @@ -959,7 +959,7 @@ void ScreenEvaluation::CommitScores( case summary: { // don't save scores if any stage was failed - if( stageStats.bFailed[p] ) + if( stageStats.m_player[p].bFailed ) continue; int iAverageMeter = stageStats.GetAverageMeter(p); @@ -1055,23 +1055,23 @@ void ScreenEvaluation::CommitScores( // don't give per-difficutly awards if using easy mods if( !GAMESTATE->IsDisqualified(p) ) { - if( stageStats.FullComboOfScore( p, TNS_GREAT ) ) + if( stageStats.m_player[p].FullComboOfScore( TNS_GREAT ) ) vPdas.push_back( AWARD_FULL_COMBO_GREATS ); - if( stageStats.SingleDigitsOfScore( p, TNS_GREAT ) ) + if( stageStats.m_player[p].SingleDigitsOfScore( TNS_GREAT ) ) vPdas.push_back( AWARD_SINGLE_DIGIT_GREATS ); - if( stageStats.FullComboOfScore( p, TNS_PERFECT ) ) + if( stageStats.m_player[p].FullComboOfScore( TNS_PERFECT ) ) vPdas.push_back( AWARD_FULL_COMBO_PERFECTS ); - if( stageStats.SingleDigitsOfScore( p, TNS_PERFECT ) ) + if( stageStats.m_player[p].SingleDigitsOfScore( TNS_PERFECT ) ) vPdas.push_back( AWARD_SINGLE_DIGIT_PERFECTS ); - if( stageStats.FullComboOfScore( p, TNS_MARVELOUS ) ) + if( stageStats.m_player[p].FullComboOfScore( TNS_MARVELOUS ) ) vPdas.push_back( AWARD_FULL_COMBO_MARVELOUSES ); - if( stageStats.OneOfScore( p, TNS_GREAT ) ) + if( stageStats.m_player[p].OneOfScore( TNS_GREAT ) ) vPdas.push_back( AWARD_ONE_GREAT ); - if( stageStats.OneOfScore( p, TNS_PERFECT ) ) + if( stageStats.m_player[p].OneOfScore( TNS_PERFECT ) ) vPdas.push_back( AWARD_ONE_PERFECT ); - float fPercentGreats = stageStats.GetPercentageOfTaps(p, TNS_GREAT); + float fPercentGreats = stageStats.m_player[p].GetPercentageOfTaps( TNS_GREAT ); if( fPercentGreats >= 0.8f ) vPdas.push_back( AWARD_GREATS_80_PERCENT ); if( fPercentGreats >= 0.9f ) @@ -1091,8 +1091,8 @@ void ScreenEvaluation::CommitScores( LOG->Trace( "done with per difficulty awards" ); // DO give peak combo awards if using easy mods - int iComboAtStartOfStage = stageStats.GetComboAtStartOfStage( p ); - int iPeakCombo = stageStats.GetMaxCombo(p).cnt; + int iComboAtStartOfStage = stageStats.m_player[p].GetComboAtStartOfStage(); + int iPeakCombo = stageStats.m_player[p].GetMaxCombo().cnt; FOREACH_PeakComboAward( pca ) { @@ -1307,7 +1307,7 @@ void ScreenEvaluation::Update( float fDeltaTime ) FOREACH_EnabledPlayer( p ) { - if( g_CurStageStats.iBonus[p] == 0 ) + if( g_CurStageStats.m_player[p].iBonus == 0 ) continue; if( GAMESTATE->IsCourseMode() ) @@ -1317,16 +1317,16 @@ void ScreenEvaluation::Update( float fDeltaTime ) if( RageTimer::GetTimeSinceStart() - m_fScreenCreateTime < 1.5f ) continue; - int increment = g_CurStageStats.iBonus[p]/10; + int increment = g_CurStageStats.m_player[p].iBonus/10; /* XXX: What's this supposed to do? If i < 1, then min(i, 1024) is i ... */ if( increment < 1 ) - increment = min( 1024, g_CurStageStats.iBonus[p] ); + increment = min( 1024, g_CurStageStats.m_player[p].iBonus ); - g_CurStageStats.iBonus[p] -= increment; - g_CurStageStats.iScore[p] += increment; + g_CurStageStats.m_player[p].iBonus -= increment; + g_CurStageStats.m_player[p].iScore += increment; if( SHOW_SCORE_AREA ) - m_textScore[p].SetText( ssprintf("%*.0i", NUM_SCORE_DIGITS, g_CurStageStats.iScore[p]) ); + m_textScore[p].SetText( ssprintf("%*.0i", NUM_SCORE_DIGITS, g_CurStageStats.m_player[p].iScore) ); } } diff --git a/stepmania/src/ScreenNameEntryTraditional.cpp b/stepmania/src/ScreenNameEntryTraditional.cpp index b905c97990..f24edc2033 100644 --- a/stepmania/src/ScreenNameEntryTraditional.cpp +++ b/stepmania/src/ScreenNameEntryTraditional.cpp @@ -140,24 +140,24 @@ ScreenNameEntryTraditional::ScreenNameEntryTraditional( CString sClassName ) : S for( int z = 0; z < 3; ++z ) { ss.vpSongs.push_back( SONGMAN->GetRandomSong() ); - ss.iPossibleDancePoints[PLAYER_1] = 100; - ss.iActualDancePoints[PLAYER_1] = 100; - ss.iScore[PLAYER_1] = 100; - ss.iPossibleDancePoints[PLAYER_2] = 100; - ss.iActualDancePoints[PLAYER_2] = 100; - ss.iScore[PLAYER_2] = 100; + ss.m_player[PLAYER_1].iPossibleDancePoints = 100; + ss.m_player[PLAYER_1].iActualDancePoints = 100; + ss.m_player[PLAYER_1].iScore = 100; + ss.m_player[PLAYER_2].iPossibleDancePoints = 100; + ss.m_player[PLAYER_2].iActualDancePoints = 100; + ss.m_player[PLAYER_2].iScore = 100; ASSERT( ss.vpSongs[0]->GetAllSteps().size() ); FOREACH_PlayerNumber( p ) { - ss.vpSteps[p].push_back( ss.vpSongs[0]->GetAllSteps()[0] ); - GAMESTATE->m_pCurSteps[p] = ss.vpSteps[p][0]; - ss.iPossibleDancePoints[p] = 1000; - ss.iActualDancePoints[p] = 985; + ss.m_player[p].vpSteps.push_back( ss.vpSongs[0]->GetAllSteps()[0] ); + GAMESTATE->m_pCurSteps[p] = ss.m_player[p].vpSteps[0]; + ss.m_player[p].iPossibleDancePoints = 1000; + ss.m_player[p].iActualDancePoints = 985; HighScore hs; hs.grade = GRADE_TIER_3; - hs.fPercentDP = ss.GetPercentDancePoints(p); - hs.iScore = ss.iScore[p]; + hs.fPercentDP = ss.m_player[p].GetPercentDancePoints(); + hs.iScore = ss.m_player[p].iScore; StepsType st = GAMESTATE->GetCurrentStyle()->m_StepsType; int a, b; PROFILEMAN->AddStepsScore( ss.vpSongs[0], GAMESTATE->m_pCurSteps[p], p, hs, a, b ); @@ -311,14 +311,14 @@ ScreenNameEntryTraditional::ScreenNameEntryTraditional( CString sClassName ) : S { StageStats &ss = g_vPlayedStageStats[i]; Song* pSong = ss.vpSongs[0]; - Steps* pSteps = ss.vpSteps[p][0]; + Steps* pSteps = ss.m_player[p].vpSteps[0]; Course* pCourse = GAMESTATE->m_pCurCourse; Trail* pTrail = GAMESTATE->m_pCurTrail[p]; int iHighScoreIndex = -1; // -1 means "out of ranking" - Grade grade = ss.GetGrade( p ); - int iScore = ss.iScore[p]; - float fPercentDP = ss.GetPercentDancePoints( p ); + Grade grade = ss.m_player[p].GetGrade(); + int iScore = ss.m_player[p].iScore; + float fPercentDP = ss.m_player[p].GetPercentDancePoints(); // If this is a SHOW_NEVER song, then it's probably a training. // Don't show a high score diff --git a/stepmania/src/SongManager.cpp b/stepmania/src/SongManager.cpp index 9c8d277579..2a859ea3fa 100644 --- a/stepmania/src/SongManager.cpp +++ b/stepmania/src/SongManager.cpp @@ -804,11 +804,11 @@ void SongManager::RevertFromDisk( Song *pSong, bool bAllowNotesLoss ) { CONVERT_STEPS_POINTER( GAMESTATE->m_pCurSteps[p] ); - FOREACH( Steps*, g_CurStageStats.vpSteps[p], pSteps ) + FOREACH( Steps*, g_CurStageStats.m_player[p].vpSteps, pSteps ) CONVERT_STEPS_POINTER( *pSteps ); FOREACH( StageStats, g_vPlayedStageStats, ss ) - FOREACH( Steps*, ss->vpSteps[p], pSteps ) + FOREACH( Steps*, ss->m_player[p].vpSteps, pSteps ) CONVERT_STEPS_POINTER( *pSteps ); } } diff --git a/stepmania/src/StageStats.cpp b/stepmania/src/StageStats.cpp index cf20eaad92..c1323d5557 100644 --- a/stepmania/src/StageStats.cpp +++ b/stepmania/src/StageStats.cpp @@ -12,149 +12,94 @@ StageStats g_CurStageStats; vector g_vPlayedStageStats; -void StageStats::Init() +void PlayerStageStats::Init() { - playMode = PLAY_MODE_INVALID; - pStyle = NULL; - vpSongs.clear(); - StageType = STAGE_INVALID; - fGameplaySeconds = 0; + vpSteps.clear(); + fAliveSeconds = 0; + bFailed = bFailedEarlier = false; + iPossibleDancePoints = iActualDancePoints = 0; + iCurCombo = iMaxCombo = iCurMissCombo = iScore = iBonus = 0; + fSecondsBeforeFail = 0; + iSongsPassed = iSongsPlayed = 0; + iTotalError = 0; - FOREACH_PlayerNumber( p ) - { - vpSteps[p].clear(); - fAliveSeconds[p] = 0; - bFailed[p] = bFailedEarlier[p] = false; - iPossibleDancePoints[p] = iActualDancePoints[p] = 0; - iCurCombo[p] = iMaxCombo[p] = iCurMissCombo[p] = iScore[p] = iBonus[p] = 0; - fSecondsBeforeFail[p] = 0; - iSongsPassed[p] = iSongsPlayed[p] = 0; - iTotalError[p] = 0; + ZERO( iTapNoteScores ); + ZERO( iHoldNoteScores ); + radarPossible.Zero(); + radarActual.Zero(); - ZERO( iTapNoteScores[p] ); - ZERO( iHoldNoteScores[p] ); - radarPossible[p].Zero(); - radarActual[p].Zero(); - - fFirstSecond[p] = 999999; - fLastSecond[p] = 0; - } + fFirstSecond = 999999; + fLastSecond = 0; } -void StageStats::AssertValid( PlayerNumber pn ) const +void PlayerStageStats::AddStats( const PlayerStageStats& other ) { - if( vpSongs[0] ) - CHECKPOINT_M( vpSongs[0]->GetFullTranslitTitle() ); - ASSERT( vpSteps[pn][0] ); - ASSERT_M( playMode < NUM_PLAY_MODES, ssprintf("playmode %i", playMode) ); - ASSERT( pStyle != NULL ); - ASSERT_M( vpSteps[pn][0]->GetDifficulty() < NUM_DIFFICULTIES, ssprintf("difficulty %i", vpSteps[pn][0]->GetDifficulty()) ); - ASSERT( vpSongs.size() == vpSteps[pn].size() ); -} - - -int StageStats::GetAverageMeter( PlayerNumber pn ) const -{ - int iTotalMeter = 0; - int iTotalCount = 0; - ASSERT( vpSongs.size() == vpSteps[pn].size() ); - - for( unsigned i=0; iGetMeter(); - - iTotalMeter += iMeter; - iTotalCount += iWeight; - } - return iTotalMeter / iTotalCount; // round down -} - -void StageStats::AddStats( const StageStats& other ) -{ - ASSERT( !other.vpSongs.empty() ); - FOREACH_CONST( Song*, other.vpSongs, s ) - vpSongs.push_back( *s ); - StageType = STAGE_INVALID; // meaningless - memset( fAliveSeconds, 0, sizeof(fAliveSeconds) ); // why not accumulate? -Chris + FOREACH_CONST( Steps*, other.vpSteps, s ) + vpSteps.push_back( *s ); + fAliveSeconds += other.fAliveSeconds; + bFailed |= other.bFailed; + bFailedEarlier |= other.bFailedEarlier; + iPossibleDancePoints += other.iPossibleDancePoints; + iActualDancePoints += other.iActualDancePoints; - fGameplaySeconds += other.fGameplaySeconds; + for( int t=0; t::const_iterator it; + for( it = other.fLifeRecord.begin(); it != other.fLifeRecord.end(); ++it ) { - FOREACH_CONST( Steps*, other.vpSteps[p], s ) - vpSteps[p].push_back( *s ); - fAliveSeconds[p] += other.fAliveSeconds[p]; - bFailed[p] |= other.bFailed[p]; - bFailedEarlier[p] |= other.bFailedEarlier[p]; - iPossibleDancePoints[p] += other.iPossibleDancePoints[p]; - iActualDancePoints[p] += other.iActualDancePoints[p]; - - for( int t=0; tfirst; + const float life = it->second; + fLifeRecord[fOtherFirstSecond+pos] = life; + } - const float fOtherFirstSecond = other.fFirstSecond[p] + fLastSecond[p]; - const float fOtherLastSecond = other.fLastSecond[p] + fLastSecond[p]; - fLastSecond[p] = fOtherLastSecond; + for( unsigned i=0; i::const_iterator it; - for( it = other.fLifeRecord[p].begin(); it != other.fLifeRecord[p].end(); ++it ) - { - const float pos = it->first; - const float life = it->second; - fLifeRecord[p][fOtherFirstSecond+pos] = life; - } + Combo_t newcombo(combo); + newcombo.fStartSecond += fOtherFirstSecond; + ComboList.push_back( newcombo ); + } - for( unsigned i=0; i 0.001 ) + continue; - Combo_t newcombo(combo); - newcombo.fStartSecond += fOtherFirstSecond; - ComboList[p].push_back( newcombo ); - } - - /* Merge identical combos. This normally only happens in course mode, when a combo - * continues between songs. */ - for( unsigned i=1; i 0.001 ) - continue; - - /* These are really the same combo. */ - prevcombo.fSizeSeconds += combo.fSizeSeconds; - prevcombo.cnt += combo.cnt; - ComboList[p].erase( ComboList[p].begin()+i ); - --i; - } + /* These are really the same combo. */ + prevcombo.fSizeSeconds += combo.fSizeSeconds; + prevcombo.cnt += combo.cnt; + ComboList.erase( ComboList.begin()+i ); + --i; } } -Grade StageStats::GetGrade( PlayerNumber pn ) const +Grade PlayerStageStats::GetGrade() const { - ASSERT( GAMESTATE->IsPlayerEnabled(pn) ); // shouldn't be calling this is player isn't joined! - - if( bFailedEarlier[pn] ) + if( bFailedEarlier ) return GRADE_FAILED; /* XXX: This entire calculation should be in ScoreKeeper, but final evaluation @@ -177,8 +122,8 @@ Grade StageStats::GetGrade( PlayerNumber pn ) const case TNS_MARVELOUS: iTapScoreValue = PREFSMAN->m_iGradeWeightMarvelous; break; default: FAIL_M( ssprintf("%i", tns) ); break; } - Actual += iTapNoteScores[pn][tns] * iTapScoreValue; - Possible += iTapNoteScores[pn][tns] * PREFSMAN->m_iGradeWeightMarvelous; + Actual += iTapNoteScores[tns] * iTapScoreValue; + Possible += iTapNoteScores[tns] * PREFSMAN->m_iGradeWeightMarvelous; } FOREACH_HoldNoteScore( hns ) @@ -191,8 +136,8 @@ Grade StageStats::GetGrade( PlayerNumber pn ) const case HNS_OK: iHoldScoreValue = PREFSMAN->m_iGradeWeightOK; break; default: FAIL_M( ssprintf("%i", hns) ); break; } - Actual += iHoldNoteScores[pn][hns] * iHoldScoreValue; - Possible += iHoldNoteScores[pn][hns] * PREFSMAN->m_iGradeWeightOK; + Actual += iHoldNoteScores[hns] * iHoldScoreValue; + Possible += iHoldNoteScores[hns] * PREFSMAN->m_iGradeWeightOK; } LOG->Trace( "GetGrade: Actual: %f, Possible: %f", Actual, Possible ); @@ -213,23 +158,23 @@ Grade StageStats::GetGrade( PlayerNumber pn ) const LOG->Trace( "GetGrade: Grade: %s, %i", GradeToString(grade).c_str(), PREFSMAN->m_bGradeTier02IsAllPerfects ); if( PREFSMAN->m_bGradeTier02IsAllPerfects ) { - if( iTapNoteScores[pn][TNS_MARVELOUS] > 0 && - iTapNoteScores[pn][TNS_PERFECT] == 0 && - iTapNoteScores[pn][TNS_GREAT] == 0 && - iTapNoteScores[pn][TNS_GOOD] == 0 && - iTapNoteScores[pn][TNS_BOO] == 0 && - iTapNoteScores[pn][TNS_MISS] == 0 && - iTapNoteScores[pn][TNS_HIT_MINE] == 0 && - iHoldNoteScores[pn][HNS_NG] == 0 ) + if( iTapNoteScores[TNS_MARVELOUS] > 0 && + iTapNoteScores[TNS_PERFECT] == 0 && + iTapNoteScores[TNS_GREAT] == 0 && + iTapNoteScores[TNS_GOOD] == 0 && + iTapNoteScores[TNS_BOO] == 0 && + iTapNoteScores[TNS_MISS] == 0 && + iTapNoteScores[TNS_HIT_MINE] == 0 && + iHoldNoteScores[HNS_NG] == 0 ) return GRADE_TIER_1; - if( iTapNoteScores[pn][TNS_PERFECT] > 0 && - iTapNoteScores[pn][TNS_GREAT] == 0 && - iTapNoteScores[pn][TNS_GOOD] == 0 && - iTapNoteScores[pn][TNS_BOO] == 0 && - iTapNoteScores[pn][TNS_MISS] == 0 && - iTapNoteScores[pn][TNS_HIT_MINE] == 0 && - iHoldNoteScores[pn][HNS_NG] == 0 ) + if( iTapNoteScores[TNS_PERFECT] > 0 && + iTapNoteScores[TNS_GREAT] == 0 && + iTapNoteScores[TNS_GOOD] == 0 && + iTapNoteScores[TNS_BOO] == 0 && + iTapNoteScores[TNS_MISS] == 0 && + iTapNoteScores[TNS_HIT_MINE] == 0 && + iHoldNoteScores[HNS_NG] == 0 ) return GRADE_TIER_2; return max( grade, GRADE_TIER_3 ); @@ -238,87 +183,144 @@ Grade StageStats::GetGrade( PlayerNumber pn ) const return grade; } + +void StageStats::Init() +{ + playMode = PLAY_MODE_INVALID; + pStyle = NULL; + vpSongs.clear(); + StageType = STAGE_INVALID; + fGameplaySeconds = 0; +} + +void StageStats::AssertValid( PlayerNumber pn ) const +{ + if( vpSongs[0] ) + CHECKPOINT_M( vpSongs[0]->GetFullTranslitTitle() ); + ASSERT( m_player[pn].vpSteps[0] ); + ASSERT_M( playMode < NUM_PLAY_MODES, ssprintf("playmode %i", playMode) ); + ASSERT( pStyle != NULL ); + ASSERT_M( m_player[pn].vpSteps[0]->GetDifficulty() < NUM_DIFFICULTIES, ssprintf("difficulty %i", m_player[pn].vpSteps[0]->GetDifficulty()) ); + ASSERT( vpSongs.size() == m_player[pn].vpSteps.size() ); +} + + +int StageStats::GetAverageMeter( PlayerNumber pn ) const +{ + int iTotalMeter = 0; + int iTotalCount = 0; + ASSERT( vpSongs.size() == m_player[pn].vpSteps.size() ); + + for( unsigned i=0; iGetMeter(); + + iTotalMeter += iMeter; + iTotalCount += iWeight; + } + return iTotalMeter / iTotalCount; // round down +} + +void StageStats::AddStats( const StageStats& other ) +{ + ASSERT( !other.vpSongs.empty() ); + FOREACH_CONST( Song*, other.vpSongs, s ) + vpSongs.push_back( *s ); + StageType = STAGE_INVALID; // meaningless + + fGameplaySeconds += other.fGameplaySeconds; + + FOREACH_PlayerNumber( p ) + { + m_player[p].AddStats( other.m_player[p] ); + } +} + bool StageStats::OnePassed() const { FOREACH_PlayerNumber( p ) - if( GAMESTATE->IsHumanPlayer(p) && !bFailed[p] ) + if( GAMESTATE->IsHumanPlayer(p) && !m_player[p].bFailed ) return true; return false; } bool StageStats::AllFailed() const { - FOREACH_PlayerNumber( pn ) - if( GAMESTATE->IsPlayerEnabled(pn) ) - if( !bFailed[pn] ) - return false; + FOREACH_EnabledPlayer( pn ) + if( !m_player[pn].bFailed ) + return false; return true; } bool StageStats::AllFailedEarlier() const { - FOREACH_PlayerNumber( p ) - if( GAMESTATE->IsPlayerEnabled(p) && !bFailedEarlier[p] ) + FOREACH_EnabledPlayer( p ) + if( !m_player[p].bFailedEarlier ) return false; return true; } -float StageStats::GetPercentDancePoints( PlayerNumber pn ) const +float PlayerStageStats::GetPercentDancePoints() const { - if( iPossibleDancePoints[pn] == 0 ) + if( iPossibleDancePoints == 0 ) return 0; // div/0 - if( iActualDancePoints[pn] == iPossibleDancePoints[pn] ) + if( iActualDancePoints == iPossibleDancePoints ) return 1; // correct for rounding error /* This can happen in battle, with transform attacks. */ - //ASSERT_M( iActualDancePoints[pn] <= iPossibleDancePoints[pn], ssprintf("%i/%i", iActualDancePoints[pn], iPossibleDancePoints[pn]) ); + //ASSERT_M( iActualDancePoints <= iPossibleDancePoints, ssprintf("%i/%i", iActualDancePoints, iPossibleDancePoints) ); - float fPercentDancePoints = iActualDancePoints[pn] / (float)iPossibleDancePoints[pn]; + float fPercentDancePoints = iActualDancePoints / (float)iPossibleDancePoints; return fPercentDancePoints; } -void StageStats::SetLifeRecordAt( PlayerNumber pn, float fLife, float fSecond ) +void PlayerStageStats::SetLifeRecordAt( float fLife, float fSecond ) { if( fSecond < 0 ) return; - fFirstSecond[pn] = min( fSecond, fFirstSecond[pn] ); - fLastSecond[pn] = max( fSecond, fLastSecond[pn] ); - //LOG->Trace( "fLastSecond = %f", fLastSecond[pn] ); + fFirstSecond = min( fSecond, fFirstSecond ); + fLastSecond = max( fSecond, fLastSecond ); + //LOG->Trace( "fLastSecond = %f", fLastSecond ); - if( !fLifeRecord[pn].empty() ) + if( !fLifeRecord.empty() ) { - const float old = GetLifeRecordAt( pn, fSecond ); + const float old = GetLifeRecordAt( fSecond ); if( fabsf(old-fSecond) < 0.001f ) return; /* no change */ } - fLifeRecord[pn][fSecond] = fLife; + fLifeRecord[fSecond] = fLife; } -float StageStats::GetLifeRecordAt( PlayerNumber pn, float fSecond ) const +float PlayerStageStats::GetLifeRecordAt( float fSecond ) const { /* Find the first element whose key is not less than k. */ - map::const_iterator it = fLifeRecord[pn].lower_bound( fSecond ); + map::const_iterator it = fLifeRecord.lower_bound( fSecond ); /* Find the first element whose key is less than k. */ - if( it != fLifeRecord[pn].begin() ) + if( it != fLifeRecord.begin() ) --it; return it->second; } -float StageStats::GetLifeRecordLerpAt( PlayerNumber pn, float fSecond ) const +float PlayerStageStats::GetLifeRecordLerpAt( float fSecond ) const { /* Find the first element whose key is not less than k. */ - map::const_iterator later = fLifeRecord[pn].lower_bound( fSecond ); + map::const_iterator later = fLifeRecord.lower_bound( fSecond ); /* Find the first element whose key is less than k. */ map::const_iterator earlier = later; - if( earlier != fLifeRecord[pn].begin() ) + if( earlier != fLifeRecord.begin() ) --earlier; if( earlier->first == later->first ) @@ -330,39 +332,39 @@ float StageStats::GetLifeRecordLerpAt( PlayerNumber pn, float fSecond ) const } -void StageStats::GetLifeRecord( PlayerNumber pn, float *fLifeOut, int iNumSamples ) const +void PlayerStageStats::GetLifeRecord( float *fLifeOut, int iNumSamples ) const { for( int i = 0; i < iNumSamples; ++i ) { - float from = SCALE( i, 0, (float)iNumSamples, fFirstSecond[pn], fLastSecond[pn] ); - fLifeOut[i] = GetLifeRecordLerpAt( pn, from ); + float from = SCALE( i, 0, (float)iNumSamples, fFirstSecond, fLastSecond ); + fLifeOut[i] = GetLifeRecordLerpAt( from ); } } /* If "rollover" is true, we're being called before gameplay begins, so we can record * the amount of the first combo that comes from the previous song. */ -void StageStats::UpdateComboList( PlayerNumber pn, float fSecond, bool rollover ) +void PlayerStageStats::UpdateComboList( float fSecond, bool rollover ) { if( fSecond < 0 ) return; if( !rollover ) { - fFirstSecond[pn] = min( fSecond, fFirstSecond[pn] ); - fLastSecond[pn] = max( fSecond, fLastSecond[pn] ); - //LOG->Trace( "fLastSecond = %f", fLastSecond[pn] ); + fFirstSecond = min( fSecond, fFirstSecond ); + fLastSecond = max( fSecond, fLastSecond ); + //LOG->Trace( "fLastSecond = %f", fLastSecond ); } - int cnt = iCurCombo[pn]; + int cnt = iCurCombo; if( !cnt ) return; /* no combo */ - if( ComboList[pn].size() == 0 || ComboList[pn].back().cnt >= cnt ) + if( ComboList.size() == 0 || ComboList.back().cnt >= cnt ) { /* If the previous combo (if any) starts on -9999, then we rolled over some * combo, but missed the first step. Remove it. */ - if( ComboList[pn].size() && ComboList[pn].back().fStartSecond == -9999 ) - ComboList[pn].erase( ComboList[pn].begin()+ComboList[pn].size()-1, ComboList[pn].end() ); + if( ComboList.size() && ComboList.back().fStartSecond == -9999 ) + ComboList.erase( ComboList.begin()+ComboList.size()-1, ComboList.end() ); /* This is a new combo. */ Combo_t NewCombo; @@ -374,10 +376,10 @@ void StageStats::UpdateComboList( PlayerNumber pn, float fSecond, bool rollover NewCombo.fStartSecond = -9999; else NewCombo.fStartSecond = fSecond; - ComboList[pn].push_back( NewCombo ); + ComboList.push_back( NewCombo ); } - Combo_t &combo = ComboList[pn].back(); + Combo_t &combo = ComboList.back(); combo.fSizeSeconds = fSecond - combo.fStartSecond; combo.cnt = cnt; if( !rollover && combo.fStartSecond == -9999 ) @@ -389,82 +391,82 @@ void StageStats::UpdateComboList( PlayerNumber pn, float fSecond, bool rollover /* This returns the largest combo contained within the song, as if * m_bComboContinuesBetweenSongs is turned off. */ -StageStats::Combo_t StageStats::GetMaxCombo( PlayerNumber pn ) const +PlayerStageStats::Combo_t PlayerStageStats::GetMaxCombo() const { - if( ComboList[pn].size() == 0 ) + if( ComboList.size() == 0 ) return Combo_t(); int m = 0; - for( unsigned i = 1; i < ComboList[pn].size(); ++i ) + for( unsigned i = 1; i < ComboList.size(); ++i ) { - if( ComboList[pn][i].cnt > ComboList[pn][m].cnt ) + if( ComboList[i].cnt > ComboList[m].cnt ) m = i; } - return ComboList[pn][m]; + return ComboList[m]; } -int StageStats::GetComboAtStartOfStage( PlayerNumber pn ) const +int PlayerStageStats::GetComboAtStartOfStage() const { - if( ComboList[pn].empty() ) + if( ComboList.empty() ) return 0; else - return ComboList[pn][0].rollover; + return ComboList[0].rollover; } -bool StageStats::FullComboOfScore( PlayerNumber pn, TapNoteScore tnsAllGreaterOrEqual ) const +bool PlayerStageStats::FullComboOfScore( TapNoteScore tnsAllGreaterOrEqual ) const { ASSERT( tnsAllGreaterOrEqual >= TNS_GREAT ); ASSERT( tnsAllGreaterOrEqual <= TNS_MARVELOUS ); - if( iHoldNoteScores[pn][HNS_NG] > 0 ) + if( iHoldNoteScores[HNS_NG] > 0 ) return false; for( int i=TNS_MISS; i 0 ) + if( iTapNoteScores[i] > 0 ) return false; } return true; } -bool StageStats::SingleDigitsOfScore( PlayerNumber pn, TapNoteScore tnsAllGreaterOrEqual ) const +bool PlayerStageStats::SingleDigitsOfScore( TapNoteScore tnsAllGreaterOrEqual ) const { - return FullComboOfScore( pn, tnsAllGreaterOrEqual ) && - iTapNoteScores[pn][tnsAllGreaterOrEqual] < 10; + return FullComboOfScore( tnsAllGreaterOrEqual ) && + iTapNoteScores[tnsAllGreaterOrEqual] < 10; } -bool StageStats::OneOfScore( PlayerNumber pn, TapNoteScore tnsAllGreaterOrEqual ) const +bool PlayerStageStats::OneOfScore( TapNoteScore tnsAllGreaterOrEqual ) const { - return FullComboOfScore( pn, tnsAllGreaterOrEqual ) && - iTapNoteScores[pn][tnsAllGreaterOrEqual] == 1; + return FullComboOfScore( tnsAllGreaterOrEqual ) && + iTapNoteScores[tnsAllGreaterOrEqual] == 1; } -int StageStats::GetTotalTaps( PlayerNumber pn ) const +int PlayerStageStats::GetTotalTaps() const { int iTotalTaps = 0; for( int i=TNS_MISS; iGetGrade( pn ); + return pStats->m_player[pn].GetGrade(); } bool OneGotGrade( int n, Grade g ) @@ -524,7 +526,7 @@ Grade GetFinalGrade( PlayerNumber pn ) return GRADE_NO_DATA; StageStats stats; GAMESTATE->GetFinalEvalStats( stats ); - return stats.GetGrade( pn ); + return stats.m_player[pn].GetGrade(); } LuaFunction_PlayerNumber( GetFinalGrade, GetFinalGrade(pn) ); @@ -535,7 +537,7 @@ Grade GetBestFinalGrade() GAMESTATE->GetFinalEvalStats( stats ); FOREACH_PlayerNumber( p ) if( GAMESTATE->IsHumanPlayer(p) ) - top_grade = min( top_grade, stats.GetGrade(p) ); + top_grade = min( top_grade, stats.m_player[p].GetGrade() ); return top_grade; } LuaFunction_NoArgs( GetBestFinalGrade, GetBestFinalGrade() ); diff --git a/stepmania/src/StageStats.h b/stepmania/src/StageStats.h index 58d2d988e0..03034700ea 100644 --- a/stepmania/src/StageStats.h +++ b/stepmania/src/StageStats.h @@ -12,59 +12,48 @@ class Song; class Steps; class Style; -struct StageStats +struct PlayerStageStats { - StageStats() { Init(); } + PlayerStageStats() { Init(); } void Init(); - void AssertValid( PlayerNumber pn ) const; - - void AddStats( const StageStats& other ); // accumulate - Grade GetGrade( PlayerNumber pn ) const; - bool OnePassed() const; - bool AllFailed() const; - bool AllFailedEarlier() const; - float GetPercentDancePoints( PlayerNumber pn ) const; + void AddStats( const PlayerStageStats& other ); // accumulate - PlayMode playMode; - const Style* pStyle; - vector vpSongs; - enum { STAGE_INVALID, STAGE_NORMAL, STAGE_EXTRA, STAGE_EXTRA2 } StageType; - vector vpSteps[NUM_PLAYERS]; - int GetAverageMeter( PlayerNumber pn ) const; - float fAliveSeconds[NUM_PLAYERS]; // how far into the music did they last before failing? Updated by Gameplay, scaled by music rate. - float fGameplaySeconds; // how many seconds before gameplay ended. Updated by Gameplay, not scaled by music rate. + Grade GetGrade() const; + float GetPercentDancePoints() const; + vector vpSteps; + float fAliveSeconds; // how far into the music did they last before failing? Updated by Gameplay, scaled by music rate. /* Set if the player actually failed at any point during the song. This is always * false in FAIL_OFF. If recovery is enabled and two players are playing, * this is only set if both players were failing at the same time. */ - bool bFailed[NUM_PLAYERS]; + bool bFailed; /* This indicates whether the player bottomed out his bar/ran out of lives at some * point during the song. It's set in all fail modes. */ - bool bFailedEarlier[NUM_PLAYERS]; - 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 iCurCombo[NUM_PLAYERS]; - int iMaxCombo[NUM_PLAYERS]; - int iCurMissCombo[NUM_PLAYERS]; - int iScore[NUM_PLAYERS]; - int iBonus[NUM_PLAYERS]; // bonus to be added on screeneval - RadarValues radarPossible[NUM_PLAYERS]; // filled in by ScreenGameplay on start of notes - RadarValues radarActual[NUM_PLAYERS]; - float fSecondsBeforeFail[NUM_PLAYERS]; // -1 means didn't/hasn't failed + bool bFailedEarlier; + int iPossibleDancePoints; + int iActualDancePoints; + int iTapNoteScores[NUM_TAP_NOTE_SCORES]; + int iHoldNoteScores[NUM_HOLD_NOTE_SCORES]; + int iCurCombo; + int iMaxCombo; + int iCurMissCombo; + int iScore; + int iBonus; // bonus to be added on screeneval + RadarValues radarPossible; // filled in by ScreenGameplay on start of notes + RadarValues radarActual; + float fSecondsBeforeFail; // -1 means didn't/hasn't failed /* The number of songs played and passed, respectively. */ - int iSongsPassed[NUM_PLAYERS]; - int iSongsPlayed[NUM_PLAYERS]; - int iTotalError[NUM_PLAYERS]; + int iSongsPassed; + int iSongsPlayed; + int iTotalError; - map fLifeRecord[NUM_PLAYERS]; - void SetLifeRecordAt( PlayerNumber pn, float fLife, float fSecond ); - void GetLifeRecord( PlayerNumber pn, float *fLifeOut, int iNumSamples ) const; - float GetLifeRecordAt( PlayerNumber pn, float fSecond ) const; - float GetLifeRecordLerpAt( PlayerNumber pn, float fSecond ) const; + map fLifeRecord; + void SetLifeRecordAt( float fLife, float fSecond ); + void GetLifeRecord( float *fLifeOut, int iNumSamples ) const; + float GetLifeRecordAt( float fSecond ) const; + float GetLifeRecordLerpAt( float fSecond ) const; struct Combo_t { @@ -85,18 +74,43 @@ struct StageStats Combo_t(): fStartSecond(0), fSizeSeconds(0), cnt(0), rollover(0) { } bool IsZero() const { return fStartSecond < 0; } }; - vector ComboList[NUM_PLAYERS]; - float fFirstSecond[NUM_PLAYERS], fLastSecond[NUM_PLAYERS]; + vector ComboList; + float fFirstSecond; + float fLastSecond; - int GetComboAtStartOfStage( PlayerNumber pn ) const; - bool FullComboOfScore( PlayerNumber pn, TapNoteScore tnsAllGreaterOrEqual ) const; - bool FullCombo( PlayerNumber pn ) const { return FullComboOfScore(pn,TNS_GREAT); } - bool SingleDigitsOfScore( PlayerNumber pn, TapNoteScore tnsAllGreaterOrEqual ) const; - bool OneOfScore( PlayerNumber pn, TapNoteScore tnsAllGreaterOrEqual ) const; - int GetTotalTaps( PlayerNumber pn ) const; - float GetPercentageOfTaps( PlayerNumber pn, TapNoteScore tns ) const; - void UpdateComboList( PlayerNumber pn, float fSecond, bool rollover ); - Combo_t GetMaxCombo( PlayerNumber pn ) const; + int GetComboAtStartOfStage() const; + bool FullComboOfScore( TapNoteScore tnsAllGreaterOrEqual ) const; + bool FullCombo() const { return FullComboOfScore(TNS_GREAT); } + bool SingleDigitsOfScore( TapNoteScore tnsAllGreaterOrEqual ) const; + bool OneOfScore( TapNoteScore tnsAllGreaterOrEqual ) const; + int GetTotalTaps() const; + float GetPercentageOfTaps( TapNoteScore tns ) const; + void UpdateComboList( float fSecond, bool rollover ); + Combo_t GetMaxCombo() const; +}; + +struct StageStats +{ + StageStats() { Init(); } + void Init(); + + void AssertValid( PlayerNumber pn ) const; + + void AddStats( const StageStats& other ); // accumulate + + bool OnePassed() const; + bool AllFailed() const; + bool AllFailedEarlier() const; + + int GetAverageMeter( PlayerNumber pn ) const; + + PlayMode playMode; + const Style* pStyle; + vector vpSongs; + enum { STAGE_INVALID, STAGE_NORMAL, STAGE_EXTRA, STAGE_EXTRA2 } StageType; + float fGameplaySeconds; // how many seconds before gameplay ended. Updated by Gameplay, not scaled by music rate. + + PlayerStageStats m_player[NUM_PLAYERS]; }; /*