This commit is contained in:
Glenn Maynard
2004-01-25 16:24:34 +00:00
parent f116a3f4e8
commit e1b5bf9404
4 changed files with 112 additions and 114 deletions
+6 -5
View File
@@ -346,13 +346,14 @@ void MusicWheel::GetSongList(vector<Song*> &arraySongs, SongSortOrder so, CStrin
{ {
Song* pSong = apAllSongs[i]; Song* pSong = apAllSongs[i];
/* If we're on an extra stage, and this song is selected, ignore /* If we're on an extra stage, and this song is selected, ignore #SELECTABLE. */
* #SELECTABLE. */
if( pSong != GAMESTATE->m_pCurSong || if( pSong != GAMESTATE->m_pCurSong ||
(!GAMESTATE->IsExtraStage() && !GAMESTATE->IsExtraStage2()) ) { (!GAMESTATE->IsExtraStage() && !GAMESTATE->IsExtraStage2()) ) {
/* Hide songs that asked to be hidden via #SELECTABLE. */ /* Hide songs that asked to be hidden via #SELECTABLE. */
if( so!=SORT_ROULETTE && !pSong->NormallyDisplayed() ) if( so!=SORT_ROULETTE && !pSong->NormallyDisplayed() )
continue; continue;
/* Don't show in roulette if #SELECTABLE:NO unless some other song in the same
* roulette class has previously been unlocked. */
if( so==SORT_ROULETTE && !(pSong->RouletteDisplayed() if( so==SORT_ROULETTE && !(pSong->RouletteDisplayed()
|| UNLOCKSYS->SongIsRoulette( pSong )) ) || UNLOCKSYS->SongIsRoulette( pSong )) )
continue; continue;
@@ -1215,9 +1216,9 @@ bool MusicWheel::Select() // return true if this selection ends the screen
StartRandom(); StartRandom();
return false; return false;
case TYPE_SONG: case TYPE_SONG:
if (PREFSMAN->m_bUseUnlockSystem) if( !GAMESTATE->IsExtraStage() && !GAMESTATE->IsExtraStage2() )
UNLOCKSYS->RouletteUnlock( m_CurWheelItemData[m_iSelection]->m_pSong ); UNLOCKSYS->UnlockSong( m_CurWheelItemData[m_iSelection]->m_pSong );
// fall-through - we want to check for unlocking only if its a song return true;
case TYPE_COURSE: case TYPE_COURSE:
return true; return true;
case TYPE_SORT: case TYPE_SORT:
+3 -3
View File
@@ -86,7 +86,7 @@ ScreenUnlock::ScreenUnlock( CString sClassName ) : ScreenAttract( sClassName )
entry->Command(IconCommand); entry->Command(IconCommand);
Unlocks.push_back(entry); Unlocks.push_back(entry);
if ( !pSong->isLocked ) if ( !pSong->IsLocked() )
this->AddChild(Unlocks[Unlocks.size() - 1]); this->AddChild(Unlocks[Unlocks.size() - 1]);
} }
@@ -156,7 +156,7 @@ ScreenUnlock::ScreenUnlock( CString sClassName ) : ScreenAttract( sClassName )
if (pSong != NULL && pSong->m_pSong != NULL) if (pSong != NULL && pSong->m_pSong != NULL)
{ {
if( pSong->isLocked) // song is locked if( pSong->IsLocked() ) // song is locked
{ {
text->SetText("???"); text->SetText("???");
text->SetZoomX(1); text->SetZoomX(1);
@@ -215,7 +215,7 @@ ScreenUnlock::ScreenUnlock( CString sClassName ) : ScreenAttract( sClassName )
if (UNLOCK_TEXT_SCROLL == 3) if (UNLOCK_TEXT_SCROLL == 3)
{ {
if (!pSong->isLocked) if ( !pSong->IsLocked() )
LastUnlocks.push_back(i); LastUnlocks.push_back(i);
} }
} }
+89 -91
View File
@@ -25,7 +25,6 @@
UnlockSystem* UNLOCKSYS = NULL; // global and accessable from anywhere in our program UnlockSystem* UNLOCKSYS = NULL; // global and accessable from anywhere in our program
#define UNLOCKS_PATH "Data/Unlocks.dat" #define UNLOCKS_PATH "Data/Unlocks.dat"
#define MEMCARD_PATH "Data/MemCard.ini" #define MEMCARD_PATH "Data/MemCard.ini"
static const char *g_UnlockNames[NUM_UNLOCK_TYPES] = static const char *g_UnlockNames[NUM_UNLOCK_TYPES] =
@@ -41,32 +40,26 @@ static const char *g_UnlockNames[NUM_UNLOCK_TYPES] =
UnlockSystem::UnlockSystem() UnlockSystem::UnlockSystem()
{ {
UNLOCKSYS = this;
LoadFromDATFile(); LoadFromDATFile();
memset( m_fScores, 0, sizeof(m_fScores) ); memset( m_fScores, 0, sizeof(m_fScores) );
RouletteSeeds = "1"; ReadValues(); // in case its ever accessed,
ReadValues( MEMCARD_PATH ); // in case its ever accessed,
// we want the values to be available // we want the values to be available
WriteValues( MEMCARD_PATH ); // create if it does not exist WriteValues(); // create if it does not exist
} }
void UnlockSystem::RouletteUnlock( const Song *song ) void UnlockSystem::UnlockSong( const Song *song )
{ {
// if its an extra stage, don't count it const UnlockEntry *p = FindSong( song );
if( GAMESTATE->IsExtraStage() || GAMESTATE->IsExtraStage2() )
return;
UnlockEntry *p = FindSong( song );
if( !p ) if( !p )
return; // does not exist return; // does not exist
if( p->m_iRouletteSeed == 0 ) if( p->m_iCode == -1 )
return; // already unlocked return;
ASSERT( p->m_iRouletteSeed < (int) RouletteSeeds.size() ); UnlockCode( p->m_iCode );
RouletteSeeds[p->m_iRouletteSeed] = '1';
WriteValues( MEMCARD_PATH );
} }
bool UnlockSystem::CourseIsLocked( const Course *course ) bool UnlockSystem::CourseIsLocked( const Course *course )
@@ -78,8 +71,7 @@ bool UnlockSystem::CourseIsLocked( const Course *course )
if( p == NULL ) if( p == NULL )
return false; return false;
p->UpdateLocked(); return p->IsLocked();
return p->isLocked;
} }
bool UnlockSystem::SongIsLocked( const Song *song ) bool UnlockSystem::SongIsLocked( const Song *song )
@@ -91,21 +83,24 @@ bool UnlockSystem::SongIsLocked( const Song *song )
if( p == NULL ) if( p == NULL )
return false; return false;
p->UpdateLocked(); return p->IsLocked();
LOG->Trace( "current status: %slocked", p->isLocked? "":"un" );
return p->isLocked;
} }
/* Return true if the song is available in roulette (overriding #SELECTABLE). */
bool UnlockSystem::SongIsRoulette( const Song *song ) bool UnlockSystem::SongIsRoulette( const Song *song )
{ {
if( !PREFSMAN->m_bUseUnlockSystem ) if( !PREFSMAN->m_bUseUnlockSystem )
return false; return false;
const UnlockEntry *p = FindSong( song ); const UnlockEntry *p = FindSong( song );
if( !p )
return false;
return p && p->m_iRouletteSeed != 0; /* If the song is locked by a code, and it's a roulette code, honor IsLocked. */
if( p->m_iCode != -1 &&
m_RouletteCodes.find( p->m_iCode ) != m_RouletteCodes.end() )
return p->IsLocked();
return true;
} }
UnlockEntry *UnlockSystem::FindLockEntry( CString songname ) UnlockEntry *UnlockSystem::FindLockEntry( CString songname )
@@ -139,33 +134,23 @@ UnlockEntry *UnlockSystem::FindCourse( const Course *pCourse )
UnlockEntry::UnlockEntry() UnlockEntry::UnlockEntry()
{ {
memset( m_fRequired, 0, sizeof(m_fRequired) ); memset( m_fRequired, 0, sizeof(m_fRequired) );
m_iRouletteSeed = 0; m_iCode = -1;
m_pSong = NULL; m_pSong = NULL;
m_pCourse = NULL; m_pCourse = NULL;
isLocked = true;
} }
void UnlockEntry::UpdateLocked() bool UnlockEntry::IsLocked() const
{ {
if( !isLocked )
return;
isLocked = true;
for( int i = 0; i < NUM_UNLOCK_TYPES; ++i ) for( int i = 0; i < NUM_UNLOCK_TYPES; ++i )
if( m_fRequired[i] && UNLOCKSYS->m_fScores[i] >= m_fRequired[i] ) if( m_fRequired[i] && UNLOCKSYS->m_fScores[i] >= m_fRequired[i] )
isLocked = false; return false;
if ( m_iRouletteSeed ) if( m_iCode != -1 && UNLOCKSYS->m_UnlockedCodes.find(m_iCode) != UNLOCKSYS->m_UnlockedCodes.end() )
{ return false;
const CString &tmp = UNLOCKSYS->RouletteSeeds;
LOG->Trace("Seed in question: %d Roulette seeds: %s", m_iRouletteSeed, tmp.c_str() ); return true;
if( tmp[m_iRouletteSeed] == '1' )
isLocked = false;
}
} }
bool UnlockSystem::LoadFromDATFile() bool UnlockSystem::LoadFromDATFile()
@@ -179,7 +164,6 @@ bool UnlockSystem::LoadFromDATFile()
return false; return false;
} }
int MaxRouletteSlot = 0;
unsigned i, j; unsigned i, j;
for( i=0; i<msd.GetNumValues(); i++ ) for( i=0; i<msd.GetNumValues(); i++ )
@@ -194,6 +178,13 @@ bool UnlockSystem::LoadFromDATFile()
continue; continue;
} }
if( stricmp(sParams[0],"ROULETTE") )
{
for( unsigned j = 1; j < sParams.params.size(); ++j )
m_RouletteCodes.insert( atoi(sParams[j]) );
continue;
}
if( stricmp(sParams[0],"UNLOCK") ) if( stricmp(sParams[0],"UNLOCK") )
{ {
LOG->Warn("Unrecognized unlock tag \"%s\", ignored.", sValueName.c_str()); LOG->Warn("Unrecognized unlock tag \"%s\", ignored.", sValueName.c_str());
@@ -232,25 +223,24 @@ bool UnlockSystem::LoadFromDATFile()
current.m_fRequired[UNLOCK_TOASTY] = datavalue; current.m_fRequired[UNLOCK_TOASTY] = datavalue;
if( unlock_type == "CS" ) if( unlock_type == "CS" )
current.m_fRequired[UNLOCK_CLEARED] = datavalue; current.m_fRequired[UNLOCK_CLEARED] = datavalue;
if( unlock_type == "CODE" )
current.m_iCode = (int) datavalue;
if( unlock_type == "RO" ) if( unlock_type == "RO" )
{ {
current.m_iRouletteSeed = (int)datavalue; m_UnlockedCodes.insert( (int)datavalue );
MaxRouletteSlot = max( MaxRouletteSlot, (int) datavalue ); m_RouletteCodes.insert( (int)datavalue );
} }
} }
current.UpdateLocked();
m_SongEntries.push_back(current); m_SongEntries.push_back(current);
} }
InitRouletteSeeds( MaxRouletteSlot ); // resize roulette seeds for more efficient use of file
UpdateSongs(); UpdateSongs();
for(i=0; i < m_SongEntries.size(); i++) for(i=0; i < m_SongEntries.size(); i++)
{ {
CString tmp = " "; CString tmp = " ";
if (!m_SongEntries[i].isLocked) tmp = "un"; if (!m_SongEntries[i].IsLocked()) tmp = "un";
LOG->Trace( "UnlockSystem Entry %s", m_SongEntries[i].m_sSongName.c_str() ); LOG->Trace( "UnlockSystem Entry %s", m_SongEntries[i].m_sSongName.c_str() );
if (m_SongEntries[i].m_pSong != NULL) if (m_SongEntries[i].m_pSong != NULL)
@@ -259,7 +249,7 @@ bool UnlockSystem::LoadFromDATFile()
LOG->Trace( " DP %f", m_SongEntries[i].m_fRequired[UNLOCK_DANCE_POINTS] ); LOG->Trace( " DP %f", m_SongEntries[i].m_fRequired[UNLOCK_DANCE_POINTS] );
LOG->Trace( " SP %f", m_SongEntries[i].m_fRequired[UNLOCK_SONG_POINTS] ); LOG->Trace( " SP %f", m_SongEntries[i].m_fRequired[UNLOCK_SONG_POINTS] );
LOG->Trace( " CS %f", m_SongEntries[i].m_fRequired[UNLOCK_CLEARED] ); LOG->Trace( " CS %f", m_SongEntries[i].m_fRequired[UNLOCK_CLEARED] );
LOG->Trace( " RO %i", m_SongEntries[i].m_iRouletteSeed ); LOG->Trace( " CODE %i", m_SongEntries[i].m_iCode );
LOG->Trace( " Status %slocked", tmp.c_str() ); LOG->Trace( " Status %slocked", tmp.c_str() );
if (m_SongEntries[i].m_pSong) if (m_SongEntries[i].m_pSong)
LOG->Trace( " Found matching song entry" ); LOG->Trace( " Found matching song entry" );
@@ -298,56 +288,57 @@ void UnlockSystem::UpdateSongs()
if (m_SongEntries[i].m_pSong == NULL && if (m_SongEntries[i].m_pSong == NULL &&
m_SongEntries[i].m_pCourse == NULL) m_SongEntries[i].m_pCourse == NULL)
{ {
LOG->Warn("UnlockSystem::UpdateSongs(): Cannot find a " LOG->Warn("Unlock: Cannot find a matching entry for \"%s\"", m_SongEntries[i].m_sSongName.c_str() );
"matching entry for %s.\nPlease check the song title. "
"Song titles should include the title and song title, e.g. "
"Can't Stop Fallin' In Love -Speed Mix-.",
m_SongEntries[i].m_sSongName.c_str() );
m_SongEntries.erase(m_SongEntries.begin() + i); m_SongEntries.erase(m_SongEntries.begin() + i);
--i;
} }
} }
} }
// This is mainly to streamline the INI for unnecessary values. bool UnlockSystem::ReadValues()
void UnlockSystem::InitRouletteSeeds(int MaxRouletteSlot)
{
MaxRouletteSlot++; // we actually need one more
// Truncate the value if we have too many seeds:
if ( (int)RouletteSeeds.size() > MaxRouletteSlot )
RouletteSeeds = RouletteSeeds.Left( MaxRouletteSlot );
// Lengthen the value if we have too few seeds:
while ( (int)RouletteSeeds.size() < MaxRouletteSlot )
RouletteSeeds += "0";
}
bool UnlockSystem::ReadValues( CString filename)
{ {
IniFile data; IniFile data;
data.SetPath( filename ); data.SetPath( MEMCARD_PATH );
if( !data.ReadFile() ) if( !data.ReadFile() )
return false; return false;
for( int i = 0; i < NUM_UNLOCK_TYPES; ++i ) for( int i = 0; i < NUM_UNLOCK_TYPES; ++i )
data.GetValue( "Unlock", g_UnlockNames[i], m_fScores[i] ); data.GetValue( "Unlock", g_UnlockNames[i], m_fScores[i] );
data.GetValue ( "Unlock", "RouletteSeeds", RouletteSeeds );
m_UnlockedCodes.clear();
CString s;
if( data.GetValue( "Unlock", "UnlockedCodes", s ) )
{
vector<CString> sCodes;
split( s, ",", sCodes, true );
for( unsigned c = 0; c < sCodes.size(); ++c )
{
const int n = atoi( sCodes[c] );
m_UnlockedCodes.insert( n );
}
}
return true; return true;
} }
bool UnlockSystem::WriteValues( CString filename) bool UnlockSystem::WriteValues() const
{ {
IniFile data; IniFile data;
data.SetPath( filename ); data.SetPath( MEMCARD_PATH );
for( int i = 0; i < NUM_UNLOCK_TYPES; ++i ) for( int i = 0; i < NUM_UNLOCK_TYPES; ++i )
data.SetValue( "Unlock", g_UnlockNames[i], m_fScores[i] ); data.SetValue( "Unlock", g_UnlockNames[i], m_fScores[i] );
data.SetValue( "Unlock", "RouletteSeeds", RouletteSeeds );
vector<CString> sCodes;
for( set<int>::const_iterator it = m_UnlockedCodes.begin(); it != m_UnlockedCodes.end(); ++it )
sCodes.push_back( ssprintf("%i", *it) );
const CString list = join( ",", sCodes );
data.SetValue( "Unlock", "UnlockedCodes", list );
data.WriteFile(); data.WriteFile();
@@ -356,14 +347,14 @@ bool UnlockSystem::WriteValues( CString filename)
void UnlockSystem::UnlockAddAP(float credit) void UnlockSystem::UnlockAddAP(float credit)
{ {
ReadValues( MEMCARD_PATH ); ReadValues();
m_fScores[UNLOCK_ARCADE_POINTS] += credit; m_fScores[UNLOCK_ARCADE_POINTS] += credit;
WriteValues( MEMCARD_PATH ); WriteValues();
} }
void UnlockSystem::UnlockAddAP(Grade grade) void UnlockSystem::UnlockAddAP(Grade grade)
{ {
ReadValues( MEMCARD_PATH ); ReadValues();
switch( grade ) switch( grade )
{ {
case GRADE_FAILED: case GRADE_FAILED:
@@ -380,29 +371,29 @@ void UnlockSystem::UnlockAddAP(Grade grade)
m_fScores[UNLOCK_ARCADE_POINTS] += 1; m_fScores[UNLOCK_ARCADE_POINTS] += 1;
break; break;
} }
WriteValues( MEMCARD_PATH ); WriteValues();
} }
void UnlockSystem::UnlockAddDP(float credit) void UnlockSystem::UnlockAddDP(float credit)
{ {
ReadValues( MEMCARD_PATH ); ReadValues();
// we don't want to ever take away dance points // we don't want to ever take away dance points
if( credit > 0 ) if( credit > 0 )
m_fScores[UNLOCK_DANCE_POINTS] += credit; m_fScores[UNLOCK_DANCE_POINTS] += credit;
WriteValues( MEMCARD_PATH ); WriteValues();
} }
void UnlockSystem::UnlockAddSP(float credit) void UnlockSystem::UnlockAddSP(float credit)
{ {
ReadValues( MEMCARD_PATH ); ReadValues();
m_fScores[UNLOCK_SONG_POINTS] += credit; m_fScores[UNLOCK_SONG_POINTS] += credit;
WriteValues( MEMCARD_PATH ); WriteValues();
} }
void UnlockSystem::UnlockAddSP( Grade grade ) void UnlockSystem::UnlockAddSP( Grade grade )
{ {
ReadValues( MEMCARD_PATH ); ReadValues();
// TODO: move these to PREFS // TODO: move these to PREFS
switch( grade ) switch( grade )
@@ -416,35 +407,42 @@ void UnlockSystem::UnlockAddSP( Grade grade )
case GRADE_TIER_7:/*D*/ m_fScores[UNLOCK_SONG_POINTS] += 1; break; case GRADE_TIER_7:/*D*/ m_fScores[UNLOCK_SONG_POINTS] += 1; break;
} }
WriteValues( MEMCARD_PATH ); WriteValues();
} }
void UnlockSystem::UnlockClearExtraStage() void UnlockSystem::UnlockClearExtraStage()
{ {
ReadValues( MEMCARD_PATH ); ReadValues();
++m_fScores[UNLOCK_EXTRA_CLEARED]; ++m_fScores[UNLOCK_EXTRA_CLEARED];
WriteValues( MEMCARD_PATH ); WriteValues();
} }
void UnlockSystem::UnlockFailExtraStage() void UnlockSystem::UnlockFailExtraStage()
{ {
ReadValues( MEMCARD_PATH ); ReadValues();
++m_fScores[UNLOCK_EXTRA_FAILED]; ++m_fScores[UNLOCK_EXTRA_FAILED];
WriteValues( MEMCARD_PATH ); WriteValues();
} }
void UnlockSystem::UnlockClearStage() void UnlockSystem::UnlockClearStage()
{ {
ReadValues( MEMCARD_PATH ); ReadValues();
++m_fScores[UNLOCK_CLEARED]; ++m_fScores[UNLOCK_CLEARED];
WriteValues( MEMCARD_PATH ); WriteValues();
} }
void UnlockSystem::UnlockToasty() void UnlockSystem::UnlockToasty()
{ {
ReadValues( MEMCARD_PATH ); ReadValues();
++m_fScores[UNLOCK_TOASTY]; ++m_fScores[UNLOCK_TOASTY];
WriteValues( MEMCARD_PATH ); WriteValues();
}
void UnlockSystem::UnlockCode( int num )
{
ReadValues();
m_UnlockedCodes.insert( num );
WriteValues();
} }
int UnlockSystem::GetNumUnlocks() const int UnlockSystem::GetNumUnlocks() const
+13 -14
View File
@@ -2,6 +2,8 @@
#define UNLOCK_SYSTEM_H #define UNLOCK_SYSTEM_H
#include "Grade.h" #include "Grade.h"
#include <set>
/* /*
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
Class: UnlockSystem Class: UnlockSystem
@@ -40,14 +42,11 @@ struct UnlockEntry
Course *m_pCourse; Course *m_pCourse;
float m_fRequired[NUM_UNLOCK_TYPES]; float m_fRequired[NUM_UNLOCK_TYPES];
int m_iRouletteSeed; int m_iCode;
bool isLocked; // cached locked tag
bool IsCourse() const { return m_pCourse != NULL; } bool IsCourse() const { return m_pCourse != NULL; }
void UpdateLocked(); // updates isLocked bool IsLocked() const;
void UpdateData();
}; };
class UnlockSystem class UnlockSystem
@@ -87,12 +86,10 @@ public:
void UnlockClearStage(); void UnlockClearStage();
void UnlockToasty(); void UnlockToasty();
// unlocks given song in roulette void UnlockCode( int num );
void RouletteUnlock( const Song *song );
// read and write unlock in values // unlocks the song's code
bool ReadValues( CString filename); void UnlockSong( const Song *song );
bool WriteValues( CString filename);
UnlockEntry *FindLockEntry( CString lockname ); UnlockEntry *FindLockEntry( CString lockname );
@@ -100,15 +97,17 @@ public:
vector<UnlockEntry> m_SongEntries; vector<UnlockEntry> m_SongEntries;
private: private:
// read and write unlock in values
bool ReadValues();
bool WriteValues() const;
UnlockEntry *FindSong( const Song *pSong ); UnlockEntry *FindSong( const Song *pSong );
UnlockEntry *FindCourse( const Course *pCourse ); UnlockEntry *FindCourse( const Course *pCourse );
// makes RouletteSeeds more efficient
void InitRouletteSeeds(int MaxRouletteSlot);
// unlock values, cached // unlock values, cached
float m_fScores[NUM_UNLOCK_TYPES]; float m_fScores[NUM_UNLOCK_TYPES];
CString RouletteSeeds; set<int> m_UnlockedCodes;
set<int> m_RouletteCodes; // "codes" which are available in roulette and which unlock if rouletted
}; };
extern UnlockSystem* UNLOCKSYS; // global and accessable from anywhere in program extern UnlockSystem* UNLOCKSYS; // global and accessable from anywhere in program