Refactor.
Finding out which songs were random was broken: if a non-static
song (eg. player's best) was missing ("BEST99999"), m_entries
doesn't necessarily match one-to-one with the results of GetStageInfo.
This commit is contained in:
@@ -178,23 +178,22 @@ void BPMDisplay::SetBPM( const Song* pSong )
|
||||
void BPMDisplay::SetBPM( const Course* pCourse )
|
||||
{
|
||||
ASSERT( pCourse );
|
||||
vector<Song*> vSongs;
|
||||
vector<Notes*> vNotes;
|
||||
vector<CString> vsModifiers;
|
||||
pCourse->GetStageInfo( vSongs, vNotes, vsModifiers, GAMESTATE->GetCurrentStyleDef()->m_NotesType );
|
||||
|
||||
ASSERT( vSongs.size() );
|
||||
vector<Course::Info> ci;
|
||||
pCourse->GetCourseInfo( GAMESTATE->GetCurrentStyleDef()->m_NotesType, ci );
|
||||
|
||||
ASSERT( ci.size() );
|
||||
|
||||
vector<float> BPMS;
|
||||
for( unsigned i = 0; i < vSongs.size(); ++i )
|
||||
for( unsigned i = 0; i < ci.size(); ++i )
|
||||
{
|
||||
if( pCourse->IsMysterySong(i) )
|
||||
if( ci[i].Random )
|
||||
{
|
||||
BPMS.push_back( -1 );
|
||||
continue;
|
||||
}
|
||||
|
||||
Song *pSong = vSongs[i];
|
||||
Song *pSong = ci[i].Song;
|
||||
ASSERT( pSong );
|
||||
switch( pSong->m_DisplayBPMType )
|
||||
{
|
||||
|
||||
+76
-128
@@ -370,82 +370,98 @@ void Course::AutogenNonstopFromGroup( CString sGroupName, vector<Song*> &apSongs
|
||||
*/
|
||||
bool Course::HasDifficult( NotesType nt ) const
|
||||
{
|
||||
if( ContainsAnyMysterySongs() )
|
||||
{
|
||||
for( unsigned i=0; i<m_entries.size(); i++ )
|
||||
{
|
||||
if( m_entries[i].type != Entry::random && m_entries[i].type != Entry::random_within_group )
|
||||
continue;
|
||||
|
||||
/* CHALLENGE doesn't get any harder. */
|
||||
if( m_entries[i].difficulty == DIFFICULTY_CHALLENGE )
|
||||
continue;
|
||||
|
||||
/* 10..10 doesn't get any harder. */
|
||||
if( m_entries[i].difficulty == DIFFICULTY_INVALID &&
|
||||
m_entries[i].low_meter == MAX_BOTTOM_RANGE &&
|
||||
m_entries[i].high_meter == MAX_BOTTOM_RANGE )
|
||||
continue;
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* We don't have any random songs. Check to see if any songs would change
|
||||
* if difficult. */
|
||||
/* Check to see if any songs would change if difficult. */
|
||||
const bool OldDifficulty = GAMESTATE->m_bDifficultCourses;
|
||||
|
||||
vector<Song*> vSongs, vHardSongs;
|
||||
vector<Notes*> vNotes, vHardNotes;
|
||||
vector<CString> vsIgnore;
|
||||
vector<Info> Normal, Hard;
|
||||
|
||||
GAMESTATE->m_bDifficultCourses = false;
|
||||
GetStageInfo( vSongs, vNotes, vsIgnore, nt );
|
||||
GetCourseInfo( nt, Normal );
|
||||
GAMESTATE->m_bDifficultCourses = true;
|
||||
GetStageInfo( vHardSongs, vHardNotes, vsIgnore, nt );
|
||||
GetCourseInfo( nt, Hard );
|
||||
GAMESTATE->m_bDifficultCourses = OldDifficulty;
|
||||
|
||||
if( vSongs.size() != vHardSongs.size() )
|
||||
if( Normal.size() != Hard.size() )
|
||||
return true; /* it changed */
|
||||
|
||||
for( unsigned i=0; i<vSongs.size(); i++ )
|
||||
if( vSongs[i] != vHardSongs[i] || vNotes[i] != vHardNotes[i] )
|
||||
for( unsigned i=0; i<Normal.size(); i++ )
|
||||
{
|
||||
if( Normal[i].CourseIndex != Hard[i].CourseIndex )
|
||||
return true; /* it changed */
|
||||
|
||||
if( Normal[i].Random )
|
||||
{
|
||||
const Entry &e = m_entries[ Normal[i].CourseIndex ];
|
||||
|
||||
/* Difficulties under CHALLENGE change by getting harder. */
|
||||
if( e.difficulty < DIFFICULTY_CHALLENGE )
|
||||
return true;
|
||||
|
||||
/* Meters under MAX_BOTTOM_RANGE..MAX_BOTTOM_RANGE change by getting harder. */
|
||||
if( e.difficulty != DIFFICULTY_INVALID &&
|
||||
e.low_meter < MAX_BOTTOM_RANGE &&
|
||||
e.high_meter < MAX_BOTTOM_RANGE )
|
||||
return true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( Normal[i].Song != Hard[i].Song || Normal[i].Notes != Hard[i].Notes )
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Course::IsPlayableIn( NotesType nt ) const
|
||||
{
|
||||
/* XXX: Is this good enough? This needs to be guaranteed: if we say
|
||||
* a course is playable and it's not, we'll crash in ScreenGameplay. */
|
||||
|
||||
vector<Song*> vSongs;
|
||||
vector<Notes*> vNotes;
|
||||
vector<CString> vsModifiers;
|
||||
GetStageInfo( vSongs, vNotes, vsModifiers, nt);
|
||||
|
||||
return vNotes.size() > 0;
|
||||
vector<Info> ci;
|
||||
GetCourseInfo( nt, ci );
|
||||
return ci.size() > 0;
|
||||
}
|
||||
|
||||
|
||||
void Course::GetStageInfo(
|
||||
vector<Song*>& vSongsOut,
|
||||
vector<Notes*>& vNotesOut,
|
||||
vector<CString>& vsModifiersOut,
|
||||
bool Course::GetFirstStageInfo(
|
||||
Song*& pSongOut,
|
||||
Notes*& pNotesOut,
|
||||
CString& sModifiersOut,
|
||||
NotesType nt ) const
|
||||
{
|
||||
vector<Info> ci;
|
||||
GetCourseInfo( nt, ci );
|
||||
|
||||
if( ci.empty() )
|
||||
return false;
|
||||
|
||||
pSongOut = ci[0].Song;
|
||||
pNotesOut = ci[0].Notes;
|
||||
sModifiersOut = ci[0].Modifiers;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Course::GetCourseInfo( NotesType nt, vector<Course::Info> &ci ) const
|
||||
{
|
||||
vector<Entry> entries = m_entries;
|
||||
|
||||
if( m_bRandomize )
|
||||
random_shuffle( entries.begin(), entries.end() );
|
||||
|
||||
vector<Song*> vSongsByMostPlayed;
|
||||
vector<Song*> vSongsByMostPlayed = SONGMAN->GetBestSongs();
|
||||
// filter out songs that don't have both medium and hard steps and long ver sons
|
||||
for( int j=vSongsByMostPlayed.size()-1; j>=0; j-- )
|
||||
{
|
||||
Song* pSong = vSongsByMostPlayed[j];
|
||||
if( pSong->m_fMusicLengthSeconds > PREFSMAN->m_fLongVerSongSeconds ||
|
||||
pSong->m_fMusicLengthSeconds > PREFSMAN->m_fMarathonVerSongSeconds ||
|
||||
!pSong->GetNotes(nt, DIFFICULTY_MEDIUM, PREFSMAN->m_bAutogenMissingTypes) ||
|
||||
!pSong->GetNotes(nt, DIFFICULTY_HARD, PREFSMAN->m_bAutogenMissingTypes) )
|
||||
vSongsByMostPlayed.erase( vSongsByMostPlayed.begin()+j );
|
||||
}
|
||||
|
||||
vector<Song*> AllSongsShuffled = SONGMAN->GetAllSongs();
|
||||
random_shuffle( AllSongsShuffled.begin(), AllSongsShuffled.end() );
|
||||
int CurSong = 0; /* Current offset into AllSongsShuffled */
|
||||
|
||||
ci.clear();
|
||||
|
||||
for( unsigned i=0; i<entries.size(); i++ )
|
||||
{
|
||||
const Entry& e = entries[i];
|
||||
@@ -500,26 +516,6 @@ void Course::GetStageInfo(
|
||||
case Entry::best:
|
||||
case Entry::worst:
|
||||
{
|
||||
if(vSongsByMostPlayed.size() == 0)
|
||||
{
|
||||
/* Probably the first time getting here; fill it in just once. */
|
||||
/* XXX: This is still expensive enough to cause a noticable
|
||||
* frame drop when scrolling over best/worst entries. */
|
||||
vSongsByMostPlayed = SONGMAN->GetAllSongs();
|
||||
SortSongPointerArrayByMostPlayed( vSongsByMostPlayed );
|
||||
|
||||
// filter out songs that don't have both medium and hard steps and long ver sons
|
||||
for( int j=vSongsByMostPlayed.size()-1; j>=0; j-- )
|
||||
{
|
||||
Song* pSong = vSongsByMostPlayed[j];
|
||||
if( pSong->m_fMusicLengthSeconds > PREFSMAN->m_fLongVerSongSeconds ||
|
||||
pSong->m_fMusicLengthSeconds > PREFSMAN->m_fMarathonVerSongSeconds ||
|
||||
!pSong->GetNotes(nt, DIFFICULTY_MEDIUM, PREFSMAN->m_bAutogenMissingTypes) ||
|
||||
!pSong->GetNotes(nt, DIFFICULTY_HARD, PREFSMAN->m_bAutogenMissingTypes) )
|
||||
vSongsByMostPlayed.erase( vSongsByMostPlayed.begin()+j );
|
||||
}
|
||||
}
|
||||
|
||||
if( e.players_index >= (int)vSongsByMostPlayed.size() )
|
||||
break;
|
||||
|
||||
@@ -567,36 +563,13 @@ void Course::GetStageInfo(
|
||||
}
|
||||
}
|
||||
|
||||
vSongsOut.push_back( pSong );
|
||||
vNotesOut.push_back( pNotes );
|
||||
vsModifiersOut.push_back( e.modifiers );
|
||||
Info cinfo;
|
||||
cinfo.Song = pSong;
|
||||
cinfo.Notes = pNotes;
|
||||
cinfo.Modifiers = e.modifiers;
|
||||
cinfo.Random = ( e.type == Entry::random || e.type == Entry::random_within_group );
|
||||
ci.push_back( cinfo );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
bool Course::GetFirstStageInfo(
|
||||
Song*& pSongOut,
|
||||
Notes*& pNotesOut,
|
||||
CString& sModifiersOut,
|
||||
NotesType nt ) const
|
||||
{
|
||||
vector<Song*> vSongs;
|
||||
vector<Notes*> vNotes;
|
||||
vector<CString> vsModifiers;
|
||||
|
||||
GetStageInfo(
|
||||
vSongs,
|
||||
vNotes,
|
||||
vsModifiers,
|
||||
nt );
|
||||
if( vSongs.empty() )
|
||||
return false;
|
||||
|
||||
pSongOut = vSongs[0];
|
||||
pNotesOut = vNotes[0];
|
||||
sModifiersOut = vsModifiers[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
RageColor Course::GetColor() const
|
||||
@@ -610,18 +583,6 @@ RageColor Course::GetColor() const
|
||||
return RageColor(0,1,0,1); // green
|
||||
}
|
||||
|
||||
bool Course::IsMysterySong( int stage ) const
|
||||
{
|
||||
switch( m_entries[stage].type )
|
||||
{
|
||||
case Entry::fixed: return false;
|
||||
case Entry::random: return true;
|
||||
case Entry::random_within_group: return true;
|
||||
case Entry::best: return false;
|
||||
case Entry::worst: return false;
|
||||
default: ASSERT(0); return true;
|
||||
}
|
||||
}
|
||||
|
||||
Difficulty Course::GetDifficulty( int stage ) const
|
||||
{
|
||||
@@ -646,31 +607,18 @@ void Course::GetMeterRange( int stage, int& iMeterLowOut, int& iMeterHighOut ) c
|
||||
}
|
||||
}
|
||||
|
||||
bool Course::ContainsAnyMysterySongs() const
|
||||
{
|
||||
for( unsigned i=0; i<m_entries.size(); i++ )
|
||||
if( IsMysterySong(i) )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Course::GetTotalSeconds( float& fSecondsOut ) const
|
||||
{
|
||||
if( ContainsAnyMysterySongs() )
|
||||
return false;
|
||||
|
||||
vector<Song*> vSongsOut;
|
||||
vector<Notes*> vNotesOut;
|
||||
vector<CString> vsModifiersOut;
|
||||
GetStageInfo(
|
||||
vSongsOut,
|
||||
vNotesOut,
|
||||
vsModifiersOut,
|
||||
NOTES_TYPE_DANCE_SINGLE ); // doesn't matter
|
||||
vector<Info> ci;
|
||||
GetCourseInfo( NOTES_TYPE_DANCE_SINGLE, ci );
|
||||
|
||||
fSecondsOut = 0;
|
||||
for( unsigned i=0; i<vSongsOut.size(); i++ )
|
||||
fSecondsOut += vSongsOut[i]->m_fMusicLengthSeconds;
|
||||
for( unsigned i=0; i<ci.size(); i++ )
|
||||
{
|
||||
if( ci[i].Random )
|
||||
return false;
|
||||
fSecondsOut += ci[i].Song->m_fMusicLengthSeconds;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+14
-3
@@ -59,10 +59,23 @@ public:
|
||||
bool m_bDifficult; // only make something difficult once
|
||||
int m_iLives; // -1 means use bar life meter
|
||||
|
||||
struct Info
|
||||
{
|
||||
Info(): Song(NULL), Notes(NULL), Random(false) { }
|
||||
Song* Song;
|
||||
Notes* Notes;
|
||||
CString Modifiers;
|
||||
bool Random;
|
||||
/* Corresponding entry in m_entries: */
|
||||
int CourseIndex;
|
||||
};
|
||||
// Dereferences course_entries and returns only the playable Songs and Notes
|
||||
void GetCourseInfo( NotesType nt, vector<Info> &ci ) const;
|
||||
|
||||
int GetEstimatedNumStages() const { return m_entries.size(); }
|
||||
bool HasDifficult( NotesType nt ) const;
|
||||
bool IsPlayableIn( NotesType nt ) const;
|
||||
void GetStageInfo( // Derefrences course_entries and returns only the playable Songs and Notes
|
||||
void GetStageInfo(
|
||||
vector<Song*>& vSongsOut,
|
||||
vector<Notes*>& vNotesOut,
|
||||
vector<CString>& vsModifiersOut,
|
||||
@@ -73,10 +86,8 @@ public:
|
||||
CString& sModifiersOut,
|
||||
NotesType nt ) const;
|
||||
RageColor GetColor() const;
|
||||
bool IsMysterySong( int stage ) const;
|
||||
Difficulty GetDifficulty( int stage ) const;
|
||||
void GetMeterRange( int stage, int& iMeterLowOut, int& iMeterHighOut ) const;
|
||||
bool ContainsAnyMysterySongs() const;
|
||||
bool GetTotalSeconds( float& fSecondsOut ) const;
|
||||
|
||||
bool IsNonstop() const { return !m_bRepeat && m_iLives <= 0; } // use bar life meter
|
||||
|
||||
@@ -54,32 +54,27 @@ void CourseContentsList::SetFromCourse( Course* pCourse )
|
||||
|
||||
m_iNumContents = 0;
|
||||
|
||||
vector<Song*> vSongs;
|
||||
vector<Notes*> vNotes;
|
||||
vector<CString> vsModifiers;
|
||||
pCourse->GetStageInfo( vSongs, vNotes, vsModifiers, GAMESTATE->GetCurrentStyleDef()->m_NotesType );
|
||||
vector<Course::Info> ci;
|
||||
pCourse->GetCourseInfo( GAMESTATE->GetCurrentStyleDef()->m_NotesType, ci );
|
||||
|
||||
for( int i=0; i<min((int)vSongs.size(), MAX_TOTAL_CONTENTS); i++ )
|
||||
for( int i=0; i<min((int)ci.size(), MAX_TOTAL_CONTENTS); i++ )
|
||||
{
|
||||
CourseEntryDisplay& display = m_CourseContentDisplays[m_iNumContents];
|
||||
|
||||
if( pCourse->IsMysterySong(i) )
|
||||
if( ci[i].Random )
|
||||
{
|
||||
Difficulty dc = pCourse->GetDifficulty(i);
|
||||
int iMeterLow, iMeterHigh;
|
||||
pCourse->GetMeterRange(i, iMeterLow, iMeterHigh);
|
||||
|
||||
if( dc == DIFFICULTY_INVALID )
|
||||
display.LoadFromMeterRange( m_iNumContents+1, iMeterLow, iMeterHigh, vsModifiers[i] );
|
||||
display.LoadFromMeterRange( m_iNumContents+1, iMeterLow, iMeterHigh, ci[i].Modifiers );
|
||||
else
|
||||
display.LoadFromDifficulty( m_iNumContents+1, dc, vsModifiers[i] );
|
||||
display.LoadFromDifficulty( m_iNumContents+1, dc, ci[i].Modifiers );
|
||||
}
|
||||
else
|
||||
{
|
||||
Song* pSong = vSongs[i];
|
||||
Notes* pNotes = vNotes[i];
|
||||
CString sModifiers = vsModifiers[i];
|
||||
display.LoadFromSongAndNotes( m_iNumContents+1, pSong, pNotes, vsModifiers[i] );
|
||||
display.LoadFromSongAndNotes( m_iNumContents+1, ci[i].Song, ci[i].Notes, ci[i].Modifiers );
|
||||
}
|
||||
|
||||
m_iNumContents ++;
|
||||
|
||||
@@ -145,12 +145,17 @@ ScreenGameplay::ScreenGameplay( bool bDemonstration ) : Screen("ScreenGameplay")
|
||||
//
|
||||
if( GAMESTATE->IsCourseMode() )
|
||||
{
|
||||
Course* pCourse = GAMESTATE->m_pCurCourse;
|
||||
pCourse->GetStageInfo( m_apSongsQueue, m_apNotesQueue[0], m_asModifiersQueue[0], GAMESTATE->GetCurrentStyleDef()->m_NotesType );
|
||||
for( int p=1; p<NUM_PLAYERS; p++ )
|
||||
vector<Course::Info> ci;
|
||||
GAMESTATE->m_pCurCourse->GetCourseInfo( GAMESTATE->GetCurrentStyleDef()->m_NotesType, ci );
|
||||
for( int p=0; p<NUM_PLAYERS; p++ )
|
||||
{
|
||||
m_apNotesQueue[p] = m_apNotesQueue[0];
|
||||
m_asModifiersQueue[p] = m_asModifiersQueue[0];
|
||||
m_apNotesQueue[p].clear();
|
||||
m_asModifiersQueue[p].clear();
|
||||
for( unsigned c=0; c<ci.size(); ++c )
|
||||
{
|
||||
m_apNotesQueue[p].push_back( ci[c].Notes );
|
||||
m_asModifiersQueue[p].push_back( ci[c].Modifiers );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user