fix uninitialized StageStats.pSteps causes crash on Song::RevertFromDisk
This commit is contained in:
@@ -838,12 +838,10 @@ void ScreenGameplay::LoadNextSong()
|
||||
{
|
||||
GAMESTATE->ResetMusicStatistics();
|
||||
|
||||
FOREACH_EnabledPlayer( p )
|
||||
{
|
||||
FOREACH_EnabledPlayer( p )
|
||||
{
|
||||
g_CurStageStats.iSongsPlayed[p]++;
|
||||
m_textCourseSongNumber[p].SetText( ssprintf("%d", g_CurStageStats.iSongsPlayed[p]) );
|
||||
}
|
||||
g_CurStageStats.iSongsPlayed[p]++;
|
||||
m_textCourseSongNumber[p].SetText( ssprintf("%d", g_CurStageStats.iSongsPlayed[p]) );
|
||||
}
|
||||
|
||||
LoadCourseSongNumber( GetMaxSongsPlayed() );
|
||||
@@ -851,7 +849,6 @@ void ScreenGameplay::LoadNextSong()
|
||||
int iPlaySongIndex = GAMESTATE->GetCourseSongIndex();
|
||||
iPlaySongIndex %= m_apSongsQueue.size();
|
||||
GAMESTATE->m_pCurSong = m_apSongsQueue[iPlaySongIndex];
|
||||
|
||||
g_CurStageStats.pSong = GAMESTATE->m_pCurSong;
|
||||
|
||||
// Restore the player's originally selected options.
|
||||
@@ -861,76 +858,75 @@ void ScreenGameplay::LoadNextSong()
|
||||
m_textSongOptions.SetText( GAMESTATE->m_SongOptions.GetString() );
|
||||
|
||||
|
||||
FOREACH_EnabledPlayer( p )
|
||||
{
|
||||
FOREACH_EnabledPlayer( p )
|
||||
SetupSong( p, iPlaySongIndex );
|
||||
|
||||
Song* pSong = GAMESTATE->m_pCurSong;
|
||||
Steps* pSteps = GAMESTATE->m_pCurSteps[p];
|
||||
g_CurStageStats.pSteps[p] = pSteps;
|
||||
|
||||
ASSERT( GAMESTATE->m_pCurSteps[p] );
|
||||
m_textStepsDescription[p].SetText( GAMESTATE->m_pCurSteps[p]->GetDescription() );
|
||||
|
||||
/* Increment the play count even if the player fails. (It's still popular,
|
||||
* even if the people playing it aren't good at it.) */
|
||||
if( !m_bDemonstration )
|
||||
PROFILEMAN->IncrementStepsPlayCount( pSong, pSteps, p );
|
||||
|
||||
m_textPlayerOptions[p].SetText( GAMESTATE->m_PlayerOptions[p].GetString() );
|
||||
|
||||
// reset oni game over graphic
|
||||
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 && g_CurStageStats.bFailed[p] ) // already failed
|
||||
ShowOniGameOver((PlayerNumber)p);
|
||||
|
||||
if( GAMESTATE->m_SongOptions.m_LifeType==SongOptions::LIFE_BAR && GAMESTATE->m_PlayMode == PLAY_MODE_ARCADE && !PREFSMAN->m_bEventMode && !m_bDemonstration)
|
||||
{
|
||||
SetupSong( p, iPlaySongIndex );
|
||||
|
||||
Song* pSong = GAMESTATE->m_pCurSong;
|
||||
Steps* pSteps = GAMESTATE->m_pCurSteps[p];
|
||||
|
||||
ASSERT( GAMESTATE->m_pCurSteps[p] );
|
||||
m_textStepsDescription[p].SetText( GAMESTATE->m_pCurSteps[p]->GetDescription() );
|
||||
|
||||
/* Increment the play count even if the player fails. (It's still popular,
|
||||
* even if the people playing it aren't good at it.) */
|
||||
if( !m_bDemonstration )
|
||||
PROFILEMAN->IncrementStepsPlayCount( pSong, pSteps, p );
|
||||
|
||||
m_textPlayerOptions[p].SetText( GAMESTATE->m_PlayerOptions[p].GetString() );
|
||||
|
||||
// reset oni game over graphic
|
||||
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 && g_CurStageStats.bFailed[p] ) // already failed
|
||||
ShowOniGameOver((PlayerNumber)p);
|
||||
|
||||
if( GAMESTATE->m_SongOptions.m_LifeType==SongOptions::LIFE_BAR && GAMESTATE->m_PlayMode == PLAY_MODE_ARCADE && !PREFSMAN->m_bEventMode && !m_bDemonstration)
|
||||
{
|
||||
m_pLifeMeter[p]->UpdateNonstopLifebar(
|
||||
GAMESTATE->GetStageIndex(),
|
||||
PREFSMAN->m_iNumArcadeStages,
|
||||
PREFSMAN->m_iProgressiveStageLifebar);
|
||||
}
|
||||
if( GAMESTATE->m_SongOptions.m_LifeType==SongOptions::LIFE_BAR && GAMESTATE->m_PlayMode == PLAY_MODE_NONSTOP )
|
||||
{
|
||||
m_pLifeMeter[p]->UpdateNonstopLifebar(
|
||||
GAMESTATE->GetCourseSongIndex(),
|
||||
GAMESTATE->m_pCurCourse->GetEstimatedNumStages(),
|
||||
PREFSMAN->m_iProgressiveNonstopLifebar);
|
||||
}
|
||||
|
||||
m_DifficultyIcon[p].SetFromSteps( p, GAMESTATE->m_pCurSteps[p] );
|
||||
|
||||
m_DifficultyMeter[p].SetName( m_sName + ssprintf(" DifficultyMeterP%d",p+1) );
|
||||
m_DifficultyMeter[p].SetFromSteps( GAMESTATE->m_pCurSteps[p] );
|
||||
|
||||
/* The actual note data for scoring is the base class of Player. This includes
|
||||
* transforms, like Wide. Otherwise, the scoring will operate on the wrong data. */
|
||||
m_pPrimaryScoreKeeper[p]->OnNextSong( GAMESTATE->GetCourseSongIndex(), GAMESTATE->m_pCurSteps[p], &m_Player[p] );
|
||||
if( m_pSecondaryScoreKeeper[p] )
|
||||
m_pSecondaryScoreKeeper[p]->OnNextSong( GAMESTATE->GetCourseSongIndex(), GAMESTATE->m_pCurSteps[p], &m_Player[p] );
|
||||
|
||||
if( m_bDemonstration )
|
||||
{
|
||||
GAMESTATE->m_PlayerController[p] = PC_CPU;
|
||||
GAMESTATE->m_iCpuSkill[p] = 5;
|
||||
}
|
||||
else if( GAMESTATE->IsCpuPlayer(p) )
|
||||
{
|
||||
GAMESTATE->m_PlayerController[p] = PC_CPU;
|
||||
int iMeter = GAMESTATE->m_pCurSteps[p]->GetMeter();
|
||||
int iNewSkill = SCALE( iMeter, MIN_METER, MAX_METER, 0, NUM_SKILL_LEVELS-1 );
|
||||
/* Watch out: songs aren't actually bound by MAX_METER. */
|
||||
iNewSkill = clamp( iNewSkill, 0, NUM_SKILL_LEVELS-1 );
|
||||
GAMESTATE->m_iCpuSkill[p] = iNewSkill;
|
||||
}
|
||||
else if( PREFSMAN->m_bAutoPlay )
|
||||
GAMESTATE->m_PlayerController[p] = PC_AUTOPLAY;
|
||||
else
|
||||
GAMESTATE->m_PlayerController[p] = PC_HUMAN;
|
||||
m_pLifeMeter[p]->UpdateNonstopLifebar(
|
||||
GAMESTATE->GetStageIndex(),
|
||||
PREFSMAN->m_iNumArcadeStages,
|
||||
PREFSMAN->m_iProgressiveStageLifebar);
|
||||
}
|
||||
if( GAMESTATE->m_SongOptions.m_LifeType==SongOptions::LIFE_BAR && GAMESTATE->m_PlayMode == PLAY_MODE_NONSTOP )
|
||||
{
|
||||
m_pLifeMeter[p]->UpdateNonstopLifebar(
|
||||
GAMESTATE->GetCourseSongIndex(),
|
||||
GAMESTATE->m_pCurCourse->GetEstimatedNumStages(),
|
||||
PREFSMAN->m_iProgressiveNonstopLifebar);
|
||||
}
|
||||
|
||||
m_DifficultyIcon[p].SetFromSteps( p, GAMESTATE->m_pCurSteps[p] );
|
||||
|
||||
m_DifficultyMeter[p].SetName( m_sName + ssprintf(" DifficultyMeterP%d",p+1) );
|
||||
m_DifficultyMeter[p].SetFromSteps( GAMESTATE->m_pCurSteps[p] );
|
||||
|
||||
/* The actual note data for scoring is the base class of Player. This includes
|
||||
* transforms, like Wide. Otherwise, the scoring will operate on the wrong data. */
|
||||
m_pPrimaryScoreKeeper[p]->OnNextSong( GAMESTATE->GetCourseSongIndex(), GAMESTATE->m_pCurSteps[p], &m_Player[p] );
|
||||
if( m_pSecondaryScoreKeeper[p] )
|
||||
m_pSecondaryScoreKeeper[p]->OnNextSong( GAMESTATE->GetCourseSongIndex(), GAMESTATE->m_pCurSteps[p], &m_Player[p] );
|
||||
|
||||
if( m_bDemonstration )
|
||||
{
|
||||
GAMESTATE->m_PlayerController[p] = PC_CPU;
|
||||
GAMESTATE->m_iCpuSkill[p] = 5;
|
||||
}
|
||||
else if( GAMESTATE->IsCpuPlayer(p) )
|
||||
{
|
||||
GAMESTATE->m_PlayerController[p] = PC_CPU;
|
||||
int iMeter = GAMESTATE->m_pCurSteps[p]->GetMeter();
|
||||
int iNewSkill = SCALE( iMeter, MIN_METER, MAX_METER, 0, NUM_SKILL_LEVELS-1 );
|
||||
/* Watch out: songs aren't actually bound by MAX_METER. */
|
||||
iNewSkill = clamp( iNewSkill, 0, NUM_SKILL_LEVELS-1 );
|
||||
GAMESTATE->m_iCpuSkill[p] = iNewSkill;
|
||||
}
|
||||
else if( PREFSMAN->m_bAutoPlay )
|
||||
GAMESTATE->m_PlayerController[p] = PC_AUTOPLAY;
|
||||
else
|
||||
GAMESTATE->m_PlayerController[p] = PC_HUMAN;
|
||||
}
|
||||
|
||||
m_textSongTitle.SetText( GAMESTATE->m_pCurSong->m_sMainTitle );
|
||||
|
||||
+11
-7
@@ -280,20 +280,24 @@ bool Song::LoadFromSongDir( CString sDir )
|
||||
void Song::RevertFromDisk( bool bAllowNotesLoss )
|
||||
{
|
||||
// Ugly: When we re-load the song, the Steps* will change.
|
||||
// Fix GAMESTATE->m_CurNotes, g_CurStageStats, g_vPlayedStageStats[] after reloading.
|
||||
// Fix GAMESTATE->m_CurSteps, g_CurStageStats, g_vPlayedStageStats[] after reloading.
|
||||
/* XXX: This is very brittle. However, we must know about all globals uses of Steps*,
|
||||
* so we can check to make sure we didn't lose any steps which are referenced ... */
|
||||
StepsID OldCurNotes[NUM_PLAYERS];
|
||||
StepsID OldCurSteps[NUM_PLAYERS];
|
||||
StepsID OldCurStageStats[NUM_PLAYERS];
|
||||
vector<StepsID> OldPlayedStageStats[NUM_PLAYERS];
|
||||
FOREACH_PlayerNumber( p )
|
||||
{
|
||||
OldCurNotes[p].FromSteps( GAMESTATE->m_pCurSteps[p] );
|
||||
OldCurStageStats[p].FromSteps( g_CurStageStats.pSteps[p] );
|
||||
Steps* pCurSteps = GAMESTATE->m_pCurSteps[p];
|
||||
Steps* pCurStageStats = g_CurStageStats.pSteps[p];
|
||||
|
||||
OldCurSteps[p].FromSteps( pCurSteps );
|
||||
OldCurStageStats[p].FromSteps( pCurStageStats );
|
||||
for( unsigned i = 0; i < g_vPlayedStageStats.size(); ++i )
|
||||
{
|
||||
const StageStats &ss = g_vPlayedStageStats[i];;
|
||||
OldPlayedStageStats[p].push_back( StepsID() );
|
||||
OldPlayedStageStats[p][i].FromSteps( g_vPlayedStageStats[i].pSteps[p] );
|
||||
OldPlayedStageStats[p][i].FromSteps( ss.pSteps[p] );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -316,14 +320,14 @@ void Song::RevertFromDisk( bool bAllowNotesLoss )
|
||||
{
|
||||
CHECKPOINT;
|
||||
if( GAMESTATE->m_pCurSong == this )
|
||||
GAMESTATE->m_pCurSteps[p] = OldCurNotes[p].ToSteps( this, bAllowNotesLoss );
|
||||
GAMESTATE->m_pCurSteps[p] = OldCurSteps[p].ToSteps( this, bAllowNotesLoss );
|
||||
CHECKPOINT;
|
||||
if( g_CurStageStats.pSong == this )
|
||||
g_CurStageStats.pSteps[p] = OldCurStageStats[p].ToSteps( this, bAllowNotesLoss );
|
||||
CHECKPOINT;
|
||||
for( unsigned i = 0; i < g_vPlayedStageStats.size(); ++i )
|
||||
{
|
||||
CHECKPOINT_M(ssprintf("%i", i));
|
||||
CHECKPOINT_M(ssprintf("%i", i));
|
||||
if( g_vPlayedStageStats[i].pSong == this )
|
||||
g_vPlayedStageStats[i].pSteps[p] = OldPlayedStageStats[p][i].ToSteps( this, bAllowNotesLoss );
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
StageStats g_CurStageStats;
|
||||
vector<StageStats> g_vPlayedStageStats;
|
||||
|
||||
StageStats::StageStats()
|
||||
void StageStats::Init()
|
||||
{
|
||||
playMode = PLAY_MODE_INVALID;
|
||||
style = STYLE_INVALID;
|
||||
|
||||
Reference in New Issue
Block a user