move stage logic out of SongManager

allow selecting between multiple StepsTypes on ScreenSelectMusic (ala Pump's combined single/double list)
This commit is contained in:
Chris Danford
2007-02-23 21:13:45 +00:00
parent b407c58176
commit 9061e2c1c1
16 changed files with 198 additions and 61 deletions
+1
View File
@@ -23,6 +23,7 @@ ThemeMetric<RString> CommonMetrics::DEFAULT_NOTESKIN_NAME ("Common","DefaultN
ThemeMetricDifficultiesToShow CommonMetrics::DIFFICULTIES_TO_SHOW ("Common","DifficultiesToShow");
ThemeMetricCourseDifficultiesToShow CommonMetrics::COURSE_DIFFICULTIES_TO_SHOW ("Common","CourseDifficultiesToShow");
ThemeMetricStepsTypesToShow CommonMetrics::STEPS_TYPES_TO_SHOW ("Common","StepsTypesToHide");
ThemeMetric<bool> CommonMetrics::ALL_STEPS_TYPES_IN_ONE_LIST ("Common","AllStepsTypeInOneList");
ThemeMetricDifficultiesToShow::ThemeMetricDifficultiesToShow( const RString& sGroup, const RString& sName ) :
+1
View File
@@ -62,6 +62,7 @@ namespace CommonMetrics
extern ThemeMetricDifficultiesToShow DIFFICULTIES_TO_SHOW;
extern ThemeMetricCourseDifficultiesToShow COURSE_DIFFICULTIES_TO_SHOW;
extern ThemeMetricStepsTypesToShow STEPS_TYPES_TO_SHOW;
extern ThemeMetric<bool> ALL_STEPS_TYPES_IN_ONE_LIST;
RString LocalizeOptionItem( const RString &s, bool bOptional );
};
+1 -1
View File
@@ -462,7 +462,7 @@ bool Course::GetTrailUnsorted( StepsType st, CourseDifficulty cd, Trail &trail )
soc.m_Tutorial = SongCriteria::Tutorial_No;
soc.m_Locked = SongCriteria::Locked_Unlocked;
if( !soc.m_bUseSongAllowedList )
soc.m_iStagesForSong = 1;
soc.m_iMaxStagesForSong = 1;
StepsCriteria stc = e->stepsCriteria;
stc.m_st = st;
+5 -8
View File
@@ -282,19 +282,16 @@ void DifficultyList::SetFromGameState()
}
else
{
vector<Steps*> CurSteps;
SongUtil::GetSteps( pSong, CurSteps, GAMESTATE->GetCurrentStyle()->m_StepsType );
vector<Steps*> vpSteps;
SongUtil::GetPossibleSteps( pSong, vpSteps );
/* Should match the sort in ScreenSelectMusic::AfterMusicChange. */
StepsUtil::RemoveLockedSteps( pSong, CurSteps );
StepsUtil::SortNotesArrayByDifficulty( CurSteps );
m_Rows.resize( CurSteps.size() );
for( unsigned i = 0; i < CurSteps.size(); ++i )
m_Rows.resize( vpSteps.size() );
for( unsigned i = 0; i < vpSteps.size(); ++i )
{
Row &row = m_Rows[i];
row.m_Steps = CurSteps[i];
row.m_Steps = vpSteps[i];
m_Lines[i].m_Meter.SetFromSteps( m_Rows[i].m_Steps );
+47
View File
@@ -10,6 +10,7 @@
#include "LightsManager.h" // for NUM_CabinetLight
#include "Game.h"
#include "Style.h"
#include "Foreach.h"
GameManager* GAMEMAN = NULL; // global and accessable from anywhere in our program
@@ -2335,6 +2336,52 @@ const Style* GameManager::GetHowToPlayStyleForGame( const Game *pGame ) const
return NULL;
}
void GameManager::GetCompatibleStyles( const Game *pGame, int iNumPlayers, vector<const Style*> &vpStylesOut ) const
{
FOREACH_ENUM( StyleType, styleType )
{
switch( styleType )
{
DEFAULT_FAIL( styleType );
case StyleType_OnePlayerOneSide:
case StyleType_OnePlayerTwoSides:
if( iNumPlayers != 1 )
continue;
break;
case StyleType_TwoPlayersTwoSides:
case StyleType_TwoPlayersSharedSides:
if( iNumPlayers != 2 )
continue;
break;
}
for( unsigned s=0; s<NUM_STYLES; s++ )
{
const Style* style = &g_Styles[s];
if( style->m_pGame != pGame )
continue;
if( style->m_StyleType != styleType )
continue;
if( !style->m_bUsedForGameplay )
continue;
vpStylesOut.push_back( style );
}
}
}
const Style *GameManager::GetFirstCompatibleStyle( const Game *pGame, int iNumPlayers, StepsType st ) const
{
vector<const Style*> vpStyles;
GetCompatibleStyles( pGame, iNumPlayers, vpStyles );
FOREACH_CONST( const Style*, vpStyles, s )
if( (*s)->m_StepsType == st )
return *s;
FAIL_M("");
return NULL;
}
void GameManager::GetEnabledGames( vector<const Game*>& aGamesOut ) const
{
for( size_t g=0; g<ARRAYSIZE(g_Games); ++g )
+6 -4
View File
@@ -16,11 +16,13 @@ public:
GameManager();
~GameManager();
void GetStylesForGame( const Game* pGame, vector<const Style*>& aStylesAddTo, bool editor=false ) const;
void GetStepsTypesForGame( const Game* pGame, vector<StepsType>& aStepsTypeAddTo ) const;
const Style* GetEditorStyleForStepsType( StepsType st ) const;
void GetStylesForGame( const Game* pGame, vector<const Style*>& aStylesAddTo, bool editor=false ) const;
void GetStepsTypesForGame( const Game* pGame, vector<StepsType>& aStepsTypeAddTo ) const;
const Style *GetEditorStyleForStepsType( StepsType st ) const;
void GetDemonstrationStylesForGame( const Game *pGame, vector<const Style*> &vpStylesOut ) const;
const Style* GetHowToPlayStyleForGame( const Game* pGame ) const;
const Style *GetHowToPlayStyleForGame( const Game* pGame ) const;
void GameManager::GetCompatibleStyles( const Game *pGame, int iNumPlayers, vector<const Style*> &vpStylesOut ) const;
const Style *GameManager::GetFirstCompatibleStyle( const Game *pGame, int iNumPlayers, StepsType st ) const;
void GetEnabledGames( vector<const Game*>& aGamesOut ) const;
const Game* GetDefaultGame() const;
+37 -4
View File
@@ -505,11 +505,44 @@ void GameState::EndGame()
m_timeGameStarted.SetZero();
}
static int GetNumStagesForCurrentSong()
int GameState::GetNumStagesForSong( const Song* pSong )
{
int iNumStages = 1;
ASSERT( pSong );
if( pSong->IsMarathon() )
iNumStages *= 3;
if( pSong->IsLong() )
iNumStages *= 2;
return iNumStages;
}
int GameState::GetNumStagesForSongAndStyle( const Song* pSong, const Style *pStyle )
{
int iNumStages = GetNumStagesForSong( pSong );
// One player, two-sides styles cost extra
switch( pStyle->m_StyleType )
{
DEFAULT_FAIL( pStyle->m_StyleType );
case StyleType_OnePlayerOneSide:
iNumStages *= 2;
break;
case StyleType_TwoPlayersTwoSides:
case StyleType_OnePlayerTwoSides:
case StyleType_TwoPlayersSharedSides:
break;
}
return iNumStages;
}
static int GetNumStagesForCurrentSongOrCourse()
{
int iNumStagesOfThisSong = 1;
if( GAMESTATE->m_pCurSong )
iNumStagesOfThisSong = SongManager::GetNumStagesForSong( GAMESTATE->m_pCurSong );
iNumStagesOfThisSong = GameState::GetNumStagesForSong( GAMESTATE->m_pCurSong );
else if( GAMESTATE->m_pCurCourse )
iNumStagesOfThisSong = 1;
else
@@ -553,7 +586,7 @@ void GameState::BeginStage()
m_SongOptions.Assign( ModsLevel_Stage, m_SongOptions.GetPreferred() );
STATSMAN->m_CurStageStats.m_fMusicRate = m_SongOptions.GetSong().m_fMusicRate;
m_iNumStagesOfThisSong = GetNumStagesForCurrentSong();
m_iNumStagesOfThisSong = GetNumStagesForCurrentSongOrCourse();
ASSERT( m_iNumStagesOfThisSong != -1 );
}
@@ -771,7 +804,7 @@ bool GameState::IsFinalStage() const
return true;
/* This changes dynamically on ScreenSelectMusic as the wheel turns. */
int iPredictedStageForCurSong = GetNumStagesForCurrentSong();
int iPredictedStageForCurSong = GetNumStagesForCurrentSongOrCourse();
if( iPredictedStageForCurSong == -1 )
iPredictedStageForCurSong = 1;
return m_iCurrentStageIndex + iPredictedStageForCurSong == PREFSMAN->m_iSongsPerPlay;
+3
View File
@@ -118,6 +118,9 @@ public:
int m_iNumStagesOfThisSong;
int m_iCurrentStageIndex;
static int GetNumStagesForSong( const Song* pSong );
static int GetNumStagesForSongAndStyle( const Song* pSong, const Style *pStyle );
int GetStageIndex() const;
void BeginStage();
void CancelStage();
+11 -2
View File
@@ -57,9 +57,18 @@ MusicBannerWheel::MusicBannerWheel()
this->AddChild( &m_ScrollingList );
if( GAMESTATE->m_sPreferredSongGroup == GROUP_ALL )
SONGMAN->GetSongs( arraySongs, GAMESTATE->GetNumStagesLeft() );
SONGMAN->GetSongs( arraySongs );
else // Get the Group They Want
SONGMAN->GetSongs( arraySongs, GAMESTATE->m_sPreferredSongGroup, GAMESTATE->GetNumStagesLeft() );
SONGMAN->GetSongs( arraySongs, GAMESTATE->m_sPreferredSongGroup );
// filter songs that we don't have enough stages to play
{
vector<Song*> vTempSongs;
SongCriteria sc;
sc.m_iMaxStagesForSong = GAMESTATE->GetNumStagesLeft();
SongUtil::FilterSongs( sc, arraySongs, vTempSongs );
arraySongs = vTempSongs;
}
//Detect autogenned songs
if ( !PREFSMAN->m_bAutogenSteps )
+30 -11
View File
@@ -155,18 +155,28 @@ void MusicWheel::BeginScreen()
if( GAMESTATE->m_PreferredSortOrder == SortOrder_Invalid )
GAMESTATE->m_PreferredSortOrder = GAMESTATE->m_SortOrder;
// HACK: invalidate currently selected song in the case that it
// cannot be played due to lack of stages remaining
// checking for event mode shouldn't be necessary here
// but someone mentioned it does it sometimes.
/* Invalidate current Song if it can't be played
* because there are not enough stages remaining. */
if( GAMESTATE->m_pCurSong != NULL &&
SongManager::GetNumStagesForSong( GAMESTATE->m_pCurSong ) + GAMESTATE->m_iCurrentStageIndex > PREFSMAN->m_iSongsPerPlay
&& !GAMESTATE->IsEventMode()
&& !GAMESTATE->IsAnExtraStage() )
GameState::GetNumStagesForSong( GAMESTATE->m_pCurSong ) > GAMESTATE->GetNumStagesLeft() )
{
GAMESTATE->m_pCurSong.Set( NULL );
}
/* Invalidate current Steps if it can't be played
* because there are not enough stages remaining. */
FOREACH_ENUM( PlayerNumber, p )
{
if( GAMESTATE->m_pCurSteps[p] != NULL )
{
vector<Steps*> vpPossibleSteps;
SongUtil::GetPossibleSteps( GAMESTATE->m_pCurSong, vpPossibleSteps );
bool bStepsIsPossible = find( vpPossibleSteps.begin(), vpPossibleSteps.end(), GAMESTATE->m_pCurSteps[p] ) == vpPossibleSteps.end();
if( !bStepsIsPossible )
GAMESTATE->m_pCurSteps[p].Set( NULL );
}
}
// Select the the previously selected song (if any)
if( !SelectSongOrCourse() )
SetOpenGroup("");
@@ -316,16 +326,25 @@ void MusicWheel::GetSongList( vector<Song*> &arraySongs, SortOrder so, const RSt
switch( so )
{
case SORT_PREFERRED:
SONGMAN->GetPreferredSortSongs( apAllSongs, GAMESTATE->GetNumStagesLeft() );
SONGMAN->GetPreferredSortSongs( apAllSongs );
break;
case SORT_POPULARITY:
SONGMAN->GetPopularSongs( apAllSongs, GAMESTATE->m_sPreferredSongGroup, GAMESTATE->GetNumStagesLeft() );
SONGMAN->GetPopularSongs( apAllSongs, GAMESTATE->m_sPreferredSongGroup );
break;
default:
SONGMAN->GetSongs( apAllSongs, GAMESTATE->m_sPreferredSongGroup, GAMESTATE->GetNumStagesLeft() );
SONGMAN->GetSongs( apAllSongs, GAMESTATE->m_sPreferredSongGroup );
break;
}
// filter songs that we don't have enough stages to play
{
vector<Song*> vTempSongs;
SongCriteria sc;
sc.m_iMaxStagesForSong = GAMESTATE->GetNumStagesLeft();
SongUtil::FilterSongs( sc, apAllSongs, vTempSongs );
apAllSongs = vTempSongs;
}
// copy only songs that have at least one Steps for the current GameMode
for( unsigned i=0; i<apAllSongs.size(); i++ )
{
@@ -678,7 +697,7 @@ void MusicWheel::BuildWheelItemDatas( vector<WheelItemData *> &arrayWheelItemDat
{
WID.m_Flags.bHasBeginnerOr1Meter = WID.m_pSong->IsEasy( GAMESTATE->GetCurrentStyle()->m_StepsType );
WID.m_Flags.bEdits = WID.m_pSong->HasEdits( GAMESTATE->GetCurrentStyle()->m_StepsType );
WID.m_Flags.iStagesForSong = SongManager::GetNumStagesForSong( WID.m_pSong );
WID.m_Flags.iStagesForSong = GameState::GetNumStagesForSong( WID.m_pSong );
}
else if( WID.m_pCourse != NULL )
{
+1 -1
View File
@@ -206,7 +206,7 @@ void ScoreKeeperNormal::OnNextSong( int iSongInCourseIndex, const Steps* pSteps,
const int iMeter = clamp( pSteps->GetMeter(), 1, 10 );
// long ver and marathon ver songs have higher max possible scores
int iLengthMultiplier = SongManager::GetNumStagesForSong( GAMESTATE->m_pCurSong );
int iLengthMultiplier = GameState::GetNumStagesForSong( GAMESTATE->m_pCurSong );
switch( PREFSMAN->m_ScoringType )
{
case SCORING_NEW:
+9 -3
View File
@@ -273,6 +273,14 @@ void ScreenSelectMusic::Input( const InputEventPlus &input )
{
// LOG->Trace( "ScreenSelectMusic::Input()" );
// temp Chris debug
if( input.DeviceI.device == DEVICE_KEYBOARD && input.DeviceI.button == KEY_F8 )
{
if( input.type != IET_FIRST_PRESS )
return;
MESSAGEMAN->Broadcast("SongChosen");
}
// debugging?
// I just like being able to see untransliterated titles occasionally.
if( input.DeviceI.device == DEVICE_KEYBOARD && input.DeviceI.button == KEY_F9 )
@@ -932,9 +940,7 @@ void ScreenSelectMusic::AfterMusicChange()
m_fSampleStartSeconds = pSong->m_fMusicSampleStartSeconds;
m_fSampleLengthSeconds = pSong->m_fMusicSampleLengthSeconds;
SongUtil::GetSteps( pSong, m_vpSteps, GAMESTATE->GetCurrentStyle()->m_StepsType );
StepsUtil::RemoveLockedSteps( pSong, m_vpSteps );
StepsUtil::SortNotesArrayByDifficulty( m_vpSteps );
SongUtil::GetPossibleSteps( pSong, m_vpSteps );
if ( PREFSMAN->m_bShowBanners )
g_sBannerPath = pSong->GetBannerPath();
+9 -21
View File
@@ -514,31 +514,30 @@ RageColor SongManager::GetCourseColor( const Course* pCourse )
}
}
static void GetSongsFromVector( const vector<Song*> &Songs, vector<Song*> &AddTo, RString sGroupName, int iMaxStages )
static void GetSongsFromVector( const vector<Song*> &Songs, vector<Song*> &vOut, RString sGroupName )
{
AddTo.clear();
vOut.clear();
for( unsigned i=0; i<Songs.size(); i++ )
if( sGroupName==GROUP_ALL || sGroupName==Songs[i]->m_sGroupName )
if( SongManager::GetNumStagesForSong(Songs[i]) <= iMaxStages )
AddTo.push_back( Songs[i] );
vOut.push_back( Songs[i] );
}
void SongManager::GetSongs( vector<Song*> &AddTo, RString sGroupName, int iMaxStages ) const
void SongManager::GetSongs( vector<Song*> &AddTo, RString sGroupName ) const
{
GetSongsFromVector( m_pSongs, AddTo, sGroupName, iMaxStages );
GetSongsFromVector( m_pSongs, AddTo, sGroupName );
}
void SongManager::GetPopularSongs( vector<Song*> &AddTo, RString sGroupName, int iMaxStages, ProfileSlot slot ) const
void SongManager::GetPopularSongs( vector<Song*> &AddTo, RString sGroupName, ProfileSlot slot ) const
{
GetSongsFromVector( m_pPopularSongs[slot], AddTo, sGroupName, iMaxStages );
GetSongsFromVector( m_pPopularSongs[slot], AddTo, sGroupName );
}
void SongManager::GetPreferredSortSongs( vector<Song*> &AddTo, int iMaxStages ) const
void SongManager::GetPreferredSortSongs( vector<Song*> &AddTo ) const
{
if( m_vPreferredSongSort.empty() )
{
GetSongs( AddTo, iMaxStages );
GetSongs( AddTo );
return;
}
@@ -661,17 +660,6 @@ RString SongManager::ShortenGroupName( RString sLongGroupName )
return title.Title;
}
int SongManager::GetNumStagesForSong( const Song* pSong )
{
ASSERT( pSong );
if( pSong->IsMarathon() )
return 3;
if( pSong->IsLong() )
return 2;
else
return 1;
}
static LocalizedString LOADING_COURSES ( "SongManager", "Loading courses..." );
void SongManager::InitCoursesFromDisk( LoadingWindow *ld )
{
+4 -6
View File
@@ -69,18 +69,16 @@ public:
RageColor GetCourseColor( const Course* pCourse );
static RString ShortenGroupName( RString sLongGroupName );
static int GetNumStagesForSong( const Song* pSong ); // LongVer songs take 2 stages, MarathonVer take 3
// Lookup
const vector<Song*> &GetAllSongs() const { return m_pSongs; }
void GetPopularSongs( vector<Song*> &AddTo, RString sGroupName, int iMaxStages = INT_MAX, ProfileSlot slot=ProfileSlot_Machine ) const;
void GetPreferredSortSongs( vector<Song*> &AddTo, int iMaxStages = INT_MAX ) const;
void GetPopularSongs( vector<Song*> &AddTo, RString sGroupName, ProfileSlot slot=ProfileSlot_Machine ) const;
void GetPreferredSortSongs( vector<Song*> &AddTo ) const;
const vector<Song*> &GetPopularSongs( ProfileSlot slot=ProfileSlot_Machine ) const { return m_pPopularSongs[slot]; }
const vector<Course*> &GetPopularCourses( CourseType ct, ProfileSlot slot=ProfileSlot_Machine ) const { return m_pPopularCourses[slot][ct]; }
void GetSongs( vector<Song*> &AddTo, RString sGroupName, int iMaxStages = INT_MAX ) const;
void GetSongs( vector<Song*> &AddTo, int iMaxStages ) const { GetSongs(AddTo,GROUP_ALL,iMaxStages); }
void GetSongs( vector<Song*> &AddTo ) const { GetSongs(AddTo,GROUP_ALL,INT_MAX); }
void GetSongs( vector<Song*> &AddTo, RString sGroupName ) const;
void GetSongs( vector<Song*> &AddTo ) const { GetSongs(AddTo,GROUP_ALL); }
Song *FindSong( RString sPath );
Song *FindSong( RString sGroup, RString sSong );
Course *FindCourse( RString sPath );
+31
View File
@@ -14,6 +14,8 @@
#include "ThemeMetric.h"
#include "LocalizedString.h"
#include "RageLog.h"
#include "GameManager.h"
#include "CommonMetrics.h"
bool SongCriteria::Matches( const Song *pSong ) const
{
@@ -808,6 +810,35 @@ void SongUtil::FilterSongs( const SongCriteria &sc, const vector<Song*> &in, vec
}
}
void SongUtil::GetPossibleSteps( const Song *pSong, vector<Steps*> &vOut )
{
vector<const Style*> vpPossibleStyles;
if( CommonMetrics::ALL_STEPS_TYPES_IN_ONE_LIST )
GAMEMAN->GetCompatibleStyles( GAMESTATE->m_pCurGame, GAMESTATE->GetNumPlayersEnabled(), vpPossibleStyles );
else
vpPossibleStyles.push_back( GAMESTATE->m_pCurStyle );
set<StepsType> vStepsType;
FOREACH( const Style*, vpPossibleStyles, s )
vStepsType.insert( (*s)->m_StepsType );
FOREACHS( StepsType, vStepsType, st )
SongUtil::GetSteps( pSong, vOut, *st );
StepsUtil::RemoveLockedSteps( pSong, vOut );
StepsUtil::SortNotesArrayByDifficulty( vOut );
StepsUtil::SortStepsByTypeAndDifficulty( vOut );
// remove steps that we don't have enough stages left to play
for( int i=vOut.size()-1; i>=0; i-- )
{
Steps *pSteps = vOut[i];
StepsType st = pSteps->m_StepsType;
const Style *pStyle = GAMEMAN->GetFirstCompatibleStyle( GAMESTATE->m_pCurGame, GAMESTATE->GetNumPlayersEnabled(), st );
if( GAMESTATE->GetNumStagesForSongAndStyle(pSong,pStyle) > GAMESTATE->GetNumStagesLeft() )
vOut.erase( vOut.begin() + i );
}
}
//////////////////////////////////
// SongID
+2
View File
@@ -109,6 +109,8 @@ namespace SongUtil
void GetAllSongGenres( vector<RString> &vsOut );
void FilterSongs( const SongCriteria &sc, const vector<Song*> &in, vector<Song*> &out );
void GetPossibleSteps( const Song *pSong, vector<Steps*> &vOut );
}
class SongID