From ad5c70f7dfc796550141200f280dcf096bd92239 Mon Sep 17 00:00:00 2001 From: Chris Danford Date: Sun, 24 Apr 2005 19:41:52 +0000 Subject: [PATCH] add unlockable steps --- stepmania/src/ScreenReloadSongs.cpp | 2 +- stepmania/src/ScreenUnlock.cpp | 112 ++++++++++++++-------------- stepmania/src/UnlockManager.cpp | 77 ++++++++++++------- stepmania/src/UnlockManager.h | 24 ++++-- 4 files changed, 123 insertions(+), 92 deletions(-) diff --git a/stepmania/src/ScreenReloadSongs.cpp b/stepmania/src/ScreenReloadSongs.cpp index 7901d0d6ba..e2b6b6cd34 100644 --- a/stepmania/src/ScreenReloadSongs.cpp +++ b/stepmania/src/ScreenReloadSongs.cpp @@ -81,7 +81,7 @@ void ScreenReloadSongs::Update( float fDeltaTime ) ASSERT( !IsFirstUpdate() ); SONGMAN->Reload( m_LoadingWindow ); - UNLOCKMAN->UpdateSongs(); + UNLOCKMAN->UpdateCachedPointers(); SCREENMAN->SetNewScreen( NEXT_SCREEN ); } diff --git a/stepmania/src/ScreenUnlock.cpp b/stepmania/src/ScreenUnlock.cpp index cae2209d1a..3514c6aaa4 100644 --- a/stepmania/src/ScreenUnlock.cpp +++ b/stepmania/src/ScreenUnlock.cpp @@ -51,30 +51,25 @@ void ScreenUnlock::Init() for( unsigned i=1; i <= NumUnlocks; i++ ) { // get pertaining UnlockEntry - CString SongTitle = UNLOCKMAN->m_UnlockEntries[i-1].m_sName; - LOG->Trace("UnlockScreen: Searching for %s", SongTitle.c_str()); - - const UnlockEntry *pSong = UNLOCKMAN->FindLockEntry( SongTitle ); + const UnlockEntry &entry = UNLOCKMAN->m_UnlockEntries[i-1]; + const Song *pSong = entry.m_pSong; if( pSong == NULL) - { - LOG->Trace("Can't find song %s", SongTitle.c_str()); continue; - } - Sprite* entry = new Sprite; + Sprite* pSpr = new Sprite; // new unlock graphic - entry->Load( THEME->GetPathG("ScreenUnlock",ssprintf("%d icon", i)) ); + pSpr->Load( THEME->GetPathG("ScreenUnlock",ssprintf("%d icon", i)) ); // set graphic location - entry->SetName( ssprintf("Unlock%d",i) ); - SET_XY( *entry ); + pSpr->SetName( ssprintf("Unlock%d",i) ); + SET_XY( pSpr ); - entry->RunCommands(IconCommand); - Unlocks.push_back(entry); + pSpr->RunCommands(IconCommand); + Unlocks.push_back(pSpr); - if ( !pSong->IsLocked() ) + if ( !entry.IsLocked() ) this->AddChild(Unlocks[Unlocks.size() - 1]); } @@ -101,57 +96,61 @@ void ScreenUnlock::Init() for(unsigned i = 1; i <= NumUnlocks; i++) { - CString DisplayedSong = UNLOCKMAN->m_UnlockEntries[i-1].m_sName; + const UnlockEntry &entry = UNLOCKMAN->m_UnlockEntries[i-1]; - DisplayedSong.MakeUpper(); - const UnlockEntry *pSong = UNLOCKMAN->FindLockEntry(DisplayedSong); - if ( pSong == NULL ) // no such song - continue; - BitmapText* text = new BitmapText; text->LoadFromFont( THEME->GetPathF("ScreenUnlock","text") ); text->SetHorizAlign( Actor::align_left ); text->SetZoom(ScrollingTextZoom); - if (pSong && pSong->m_pSong != NULL) + switch( entry.m_Type ) { - CString title = pSong->m_pSong->GetDisplayMainTitle(); - CString subtitle = pSong->m_pSong->GetDisplaySubTitle(); - if( subtitle != "" ) - title = title + "\n" + subtitle; - text->SetMaxWidth( MaxWidth ); - text->SetText( title ); - } - else // song is missing, might be a course - { - Course *crs = SONGMAN->FindCourse( DisplayedSong ); - if (crs != NULL) + case UnlockEntry::TYPE_SONG: { + const Song *pSong = entry.m_pSong; + ASSERT( pSong ); + + CString title = pSong->GetDisplayMainTitle(); + CString subtitle = pSong->GetDisplaySubTitle(); + if( subtitle != "" ) + title = title + "\n" + subtitle; text->SetMaxWidth( MaxWidth ); - text->SetText( crs->GetFullDisplayTitle() ); + text->SetText( title ); + } + break; + case UnlockEntry::TYPE_COURSE: + { + const Course *pCourse = entry.m_pCourse; + ASSERT( pCourse ); + + text->SetMaxWidth( MaxWidth ); + text->SetText( pCourse->GetFullDisplayTitle() ); text->SetDiffuse( RageColor(0,1,0,1) ); } - else // entry isn't a song or course - { - text->SetText( "" ); - text->SetDiffuse( RageColor(0.5,0,0,1) ); - } + break; + default: + text->SetText( "" ); + text->SetDiffuse( RageColor(0.5,0,0,1) ); + break; } - if (pSong != NULL && pSong->m_pSong != NULL) + if( entry.IsLocked() ) { - if( pSong->IsLocked() ) // song is locked - { - text->SetText("???"); - text->SetZoomX(1); - } else { // song is unlocked, change color - RageColor color = SONGMAN->GetGroupColor(pSong->m_pSong->m_sGroupName); - text->SetGlobalDiffuseColor(color); - } + text->SetText("???"); + text->SetZoomX(1); + } + else + { + // unlocked. change color + const Song *pSong = entry.m_pSong; + RageColor color = RageColor(1,1,1,1); + if( pSong ) + color = SONGMAN->GetGroupColor(pSong->m_sGroupName); + text->SetGlobalDiffuseColor(color); } - text->SetXY(ScrollingTextX, ScrollingTextStartY); + text->SetXY( ScrollingTextX, ScrollingTextStartY ); if (UNLOCK_TEXT_SCROLL == 3 && UNLOCK_TEXT_SCROLL_ROWS + i > NumUnlocks) { // special command for last unlocks when extreme-style scrolling is in effect @@ -208,7 +207,7 @@ void ScreenUnlock::Init() if (UNLOCK_TEXT_SCROLL == 3) { - if ( !pSong->IsLocked() ) + if ( !entry.IsLocked() ) LastUnlocks.push_back(i); } } @@ -232,12 +231,9 @@ void ScreenUnlock::Init() unsigned NextIcon = LastUnlocks[LastUnlocks.size() - i]; - CString DisplayedSong = UNLOCKMAN->m_UnlockEntries[NextIcon-1].m_sName; - - DisplayedSong.MakeUpper(); - const UnlockEntry *pSong = UNLOCKMAN->FindLockEntry(DisplayedSong); - - if (pSong->m_pSong == NULL) + const UnlockEntry &entry = UNLOCKMAN->m_UnlockEntries[NextIcon-1]; + const Song *pSong = entry.m_pSong; + if( pSong == NULL ) continue; BitmapText* NewText = new BitmapText; @@ -245,8 +241,8 @@ void ScreenUnlock::Init() NewText->LoadFromFont( THEME->GetPathF("ScreenUnlock","text") ); NewText->SetHorizAlign( Actor::align_left ); - CString title = pSong->m_pSong->GetDisplayMainTitle(); - CString subtitle = pSong->m_pSong->GetDisplaySubTitle(); + CString title = pSong->GetDisplayMainTitle(); + CString subtitle = pSong->GetDisplaySubTitle(); if( subtitle != "" ) title = title + "\n" + subtitle; @@ -254,7 +250,7 @@ void ScreenUnlock::Init() NewText->SetMaxWidth( MaxWidth ); NewText->SetText( title ); - RageColor color = SONGMAN->GetGroupColor(pSong->m_pSong->m_sGroupName); + RageColor color = SONGMAN->GetGroupColor(pSong->m_sGroupName); NewText->SetGlobalDiffuseColor(color); NewText->SetXY(ScrollingTextX, ScrollingTextStartY); diff --git a/stepmania/src/UnlockManager.cpp b/stepmania/src/UnlockManager.cpp index d80b927a46..781794d4d4 100644 --- a/stepmania/src/UnlockManager.cpp +++ b/stepmania/src/UnlockManager.cpp @@ -10,6 +10,7 @@ #include "ProfileManager.h" #include "ThemeManager.h" #include "Foreach.h" +#include "Steps.h" #include UnlockManager* UNLOCKMAN = NULL; // global and accessable from anywhere in our program @@ -103,7 +104,7 @@ bool UnlockManager::SongIsRouletteOnly( const Song *song ) const return false; const UnlockEntry *p = FindSong( song ); - if( !p ) + if( p == NULL ) return false; /* If the song is locked by a code, and it's a roulette code, honor IsLocked. */ @@ -113,6 +114,18 @@ bool UnlockManager::SongIsRouletteOnly( const Song *song ) const return p->IsLocked(); } +bool UnlockManager::StepsIsLocked( const Song *pSong, const Steps *pSteps ) const +{ + if( !PREFSMAN->m_bUseUnlockSystem ) + return false; + + const UnlockEntry *p = FindSteps( pSong, pSteps ); + if( p == NULL ) + return false; + + return p->IsLocked(); +} + bool UnlockManager::ModifierIsLocked( const CString &sOneMod ) const { if( !PREFSMAN->m_bUseUnlockSystem ) @@ -125,19 +138,18 @@ bool UnlockManager::ModifierIsLocked( const CString &sOneMod ) const return p->IsLocked(); } - -const UnlockEntry *UnlockManager::FindLockEntry( CString songname ) const +const UnlockEntry *UnlockManager::FindSong( const Song *pSong ) const { FOREACH_CONST( UnlockEntry, m_UnlockEntries, e ) - if( !songname.CompareNoCase(e->m_sName) ) + if( e->m_pSong == pSong && e->m_dc == DIFFICULTY_INVALID ) return &(*e); return NULL; } -const UnlockEntry *UnlockManager::FindSong( const Song *pSong ) const +const UnlockEntry *UnlockManager::FindSteps( const Song *pSong, const Steps *pSteps ) const { FOREACH_CONST( UnlockEntry, m_UnlockEntries, e ) - if( e->m_pSong == pSong ) + if( e->m_pSong == pSong && e->m_dc == pSteps->GetDifficulty() ) return &(*e); return NULL; } @@ -153,21 +165,11 @@ const UnlockEntry *UnlockManager::FindCourse( const Course *pCourse ) const const UnlockEntry *UnlockManager::FindModifier( const CString &sOneMod ) const { FOREACH_CONST( UnlockEntry, m_UnlockEntries, e ) - if( e->m_sName.CompareNoCase(sOneMod) == 0 ) + if( e->m_cmd.GetArg(1).s.CompareNoCase(sOneMod) == 0 ) return &(*e); return NULL; } - -UnlockEntry::UnlockEntry() -{ - memset( m_fRequired, 0, sizeof(m_fRequired) ); - m_iCode = -1; - - m_pSong = NULL; - m_pCourse = NULL; -} - static float GetArcadePoints( const Profile *pProfile ) { float fAP = 0; @@ -292,17 +294,22 @@ void UnlockManager::Load() if( sName == "song" ) { current.m_Type = UnlockEntry::TYPE_SONG; - current.m_sName = (CString) cmd.GetArg(1); + current.m_cmd = cmd; + } + if( sName == "steps" ) + { + current.m_Type = UnlockEntry::TYPE_STEPS; + current.m_cmd = cmd; } if( sName == "course" ) { current.m_Type = UnlockEntry::TYPE_COURSE; - current.m_sName = (CString) cmd.GetArg(1); + current.m_cmd = cmd; } if( sName == "mod" ) { current.m_Type = UnlockEntry::TYPE_MODIFIER; - current.m_sName = (CString) cmd.GetArg(1); + current.m_cmd = cmd; } else if( sName == "code" ) { @@ -329,11 +336,11 @@ void UnlockManager::Load() m_UnlockEntries.push_back( current ); } - UpdateSongs(); + UpdateCachedPointers(); FOREACH_CONST( UnlockEntry, m_UnlockEntries, e ) { - CString str = ssprintf( "Unlock: %s; ", e->m_sName.c_str() ); + CString str = ssprintf( "Unlock: %s; ", join("\n",e->m_cmd.m_vsArgs).c_str() ); FOREACH_UnlockType(j) if( e->m_fRequired[j] ) str += ssprintf( "%s = %f; ", UnlockTypeToString(j).c_str(), e->m_fRequired[j] ); @@ -367,21 +374,37 @@ float UnlockManager::PointsUntilNextUnlock( UnlockType t ) const /* Update the cached pointers. Only call this when it's likely to have changed, * such as on load, or when a song title changes in the editor. */ -void UnlockManager::UpdateSongs() +void UnlockManager::UpdateCachedPointers() { FOREACH( UnlockEntry, m_UnlockEntries, e ) { switch( e->m_Type ) { case UnlockEntry::TYPE_SONG: - e->m_pSong = SONGMAN->FindSong( e->m_sName ); + e->m_pSong = SONGMAN->FindSong( e->m_cmd.GetArg(1) ); if( e->m_pSong == NULL ) - LOG->Warn( "Unlock: Cannot find song matching \"%s\"", e->m_sName.c_str() ); + LOG->Warn( "Unlock: Cannot find song matching \"%s\"", e->m_cmd.GetArg(1).s.c_str() ); + break; + case UnlockEntry::TYPE_STEPS: + e->m_pSong = SONGMAN->FindSong( e->m_cmd.GetArg(1) ); + if( e->m_pSong == NULL ) + { + LOG->Warn( "Unlock: Cannot find song matching \"%s\"", e->m_cmd.GetArg(1).s.c_str() ); + break; + } + + e->m_dc = StringToDifficulty( e->m_cmd.GetArg(2) ); + if( e->m_dc == DIFFICULTY_INVALID ) + { + LOG->Warn( "Unlock: Invalid difficulty \"%s\"", e->m_cmd.GetArg(2).s.c_str() ); + break; + } + break; case UnlockEntry::TYPE_COURSE: - e->m_pCourse = SONGMAN->FindCourse( e->m_sName ); + e->m_pCourse = SONGMAN->FindCourse( e->m_cmd.GetArg(1) ); if( e->m_pCourse == NULL ) - LOG->Warn( "Unlock: Cannot find course matching \"%s\"", e->m_sName.c_str() ); + LOG->Warn( "Unlock: Cannot find course matching \"%s\"", e->m_cmd.GetArg(1).s.c_str() ); break; case UnlockEntry::TYPE_MODIFIER: // nothing to cache diff --git a/stepmania/src/UnlockManager.h b/stepmania/src/UnlockManager.h index ba5f11fdec..af95cbb910 100644 --- a/stepmania/src/UnlockManager.h +++ b/stepmania/src/UnlockManager.h @@ -4,6 +4,7 @@ #define UNLOCK_SYSTEM_H #include "Grade.h" +#include "Command.h" #include class Song; @@ -26,15 +27,26 @@ enum UnlockType struct UnlockEntry { - UnlockEntry(); + UnlockEntry() + { + m_Type = TYPE_INVALID; - enum Type { TYPE_SONG, TYPE_COURSE, TYPE_MODIFIER }; + m_pSong = NULL; + m_dc = DIFFICULTY_INVALID; + m_pCourse = NULL; + + ZERO( m_fRequired ); + m_iCode = -1; + } + + enum Type { TYPE_SONG, TYPE_STEPS, TYPE_COURSE, TYPE_MODIFIER, NUM_TYPES, TYPE_INVALID }; Type m_Type; - CString m_sName; + Command m_cmd; /* A cached pointer to the song or course this entry refers to. Only one of * these will be non-NULL. */ Song *m_pSong; + Difficulty m_dc; Course *m_pCourse; float m_fRequired[NUM_UNLOCK_TYPES]; @@ -59,14 +71,13 @@ public: // Used on select screens: bool SongIsLocked( const Song *song ) const; bool SongIsRouletteOnly( const Song *song ) const; + bool StepsIsLocked( const Song *pSong, const Steps *pSteps ) const; bool CourseIsLocked( const Course *course ) const; bool ModifierIsLocked( const CString &sOneMod ) const; // Gets number of unlocks for title screen int GetNumUnlocks() const; - const UnlockEntry *FindLockEntry( CString lockname ) const; - void GetPoints( const Profile *pProfile, float fScores[NUM_UNLOCK_TYPES] ) const; // Unlock an entry by code. @@ -88,7 +99,7 @@ public: vector m_UnlockEntries; // If global song or course points change, call to update - void UpdateSongs(); + void UpdateCachedPointers(); // Lua void PushSelf( lua_State *L ); @@ -98,6 +109,7 @@ private: void Load(); const UnlockEntry *FindSong( const Song *pSong ) const; + const UnlockEntry *FindSteps( const Song *pSong, const Steps *pSteps ) const; const UnlockEntry *FindCourse( const Course *pCourse ) const; const UnlockEntry *FindModifier( const CString &sOneMod ) const;