allow per-player course difficulties (not well-tested yet, off by default)
This commit is contained in:
+14
-22
@@ -37,16 +37,6 @@ const int COURSE_DIFFICULTY_METER_CHANGE[NUM_COURSE_DIFFICULTIES] = { 0, 2 };
|
||||
const int MAX_BOTTOM_RANGE = 10;
|
||||
|
||||
|
||||
/* COURSE_DIFFICULTY_INVALID is the default parameter of a few Course calls;
|
||||
* leaving it out indicates to use GAMESTATE->m_CourseDifficulty. */
|
||||
static CourseDifficulty DerefDifficulty( CourseDifficulty d )
|
||||
{
|
||||
if( d == COURSE_DIFFICULTY_INVALID )
|
||||
return GAMESTATE->m_CourseDifficulty;
|
||||
else
|
||||
return d;
|
||||
}
|
||||
|
||||
Course::Course()
|
||||
{
|
||||
m_bIsAutogen = false;
|
||||
@@ -64,11 +54,16 @@ PlayMode Course::GetPlayMode() const
|
||||
return m_iLives > 0? PLAY_MODE_ONI:PLAY_MODE_NONSTOP;
|
||||
}
|
||||
|
||||
float Course::GetMeterForPlayer( PlayerNumber pn ) const
|
||||
{
|
||||
return GetMeter( GAMESTATE->m_CourseDifficulty[pn] );
|
||||
}
|
||||
|
||||
const int DifficultMeterRamp[NUM_COURSE_DIFFICULTIES] = { 0, 3 };
|
||||
float Course::GetMeter( CourseDifficulty cd ) const
|
||||
{
|
||||
if( m_iMeter != -1 )
|
||||
return float(m_iMeter + DifficultMeterRamp[DerefDifficulty(cd)]);
|
||||
return float( m_iMeter + DifficultMeterRamp[cd] );
|
||||
|
||||
/*LOG->Trace( "Course file '%s' contains a song '%s%s%s' that is not present",
|
||||
m_sPath.c_str(), sGroup.c_str(), sGroup.size()? "/":"", sSong.c_str());*/
|
||||
@@ -553,7 +548,7 @@ static vector<Song*> GetFilteredBestSongs( StepsType nt )
|
||||
* results. */
|
||||
void Course::GetCourseInfo( StepsType nt, vector<Course::Info> &ci, CourseDifficulty cd ) const
|
||||
{
|
||||
const InfoParams params( nt, DerefDifficulty(cd) );
|
||||
const InfoParams params( nt, cd );
|
||||
InfoCache::const_iterator it = m_InfoCache.find( params );
|
||||
if( it != m_InfoCache.end() )
|
||||
{
|
||||
@@ -690,12 +685,12 @@ void Course::GetCourseInfo( StepsType nt, vector<Course::Info> &ci, CourseDiffic
|
||||
|
||||
/* If e.difficulty == DIFFICULTY_INVALID, then we already increased difficulty
|
||||
* based on meter. */
|
||||
if( DerefDifficulty(cd) > COURSE_DIFFICULTY_REGULAR && e.difficulty != DIFFICULTY_INVALID )
|
||||
if( cd > COURSE_DIFFICULTY_REGULAR && e.difficulty != DIFFICULTY_INVALID )
|
||||
{
|
||||
/* See if we can find a NoteData that's one notch more difficult than
|
||||
* the one we found above. */
|
||||
Difficulty dc = pNotes->GetDifficulty();
|
||||
Difficulty new_dc = Difficulty(dc + DerefDifficulty(cd));
|
||||
Difficulty new_dc = Difficulty( dc + cd );
|
||||
if( new_dc < NUM_DIFFICULTIES )
|
||||
{
|
||||
Steps* pNewNotes = pSong->GetStepsByDifficulty( nt, new_dc, PREFSMAN->m_bAutogenMissingTypes );
|
||||
@@ -712,7 +707,7 @@ void Course::GetCourseInfo( StepsType nt, vector<Course::Info> &ci, CourseDiffic
|
||||
cinfo.Random = ( e.type == COURSE_ENTRY_RANDOM || e.type == COURSE_ENTRY_RANDOM_WITHIN_GROUP );
|
||||
cinfo.Mystery = e.mystery;
|
||||
cinfo.CourseIndex = i;
|
||||
cinfo.Difficulty = DerefDifficulty(cd);
|
||||
cinfo.Difficulty = cd;
|
||||
ci.push_back( cinfo );
|
||||
}
|
||||
|
||||
@@ -800,12 +795,9 @@ void Course::GetMeterRange( int stage, int& iMeterLowOut, int& iMeterHighOut, Co
|
||||
iMeterLowOut = m_entries[stage].low_meter;
|
||||
iMeterHighOut = m_entries[stage].high_meter;
|
||||
|
||||
if( m_entries[stage].difficulty == DIFFICULTY_INVALID )
|
||||
{
|
||||
iMeterHighOut += COURSE_DIFFICULTY_METER_CHANGE[ DerefDifficulty(cd) ];
|
||||
iMeterLowOut += COURSE_DIFFICULTY_METER_CHANGE[ DerefDifficulty(cd) ];
|
||||
iMeterLowOut = min( iMeterLowOut, MAX_BOTTOM_RANGE );
|
||||
}
|
||||
iMeterHighOut += COURSE_DIFFICULTY_METER_CHANGE[ cd ];
|
||||
iMeterLowOut += COURSE_DIFFICULTY_METER_CHANGE[ cd ];
|
||||
iMeterLowOut = min( iMeterLowOut, MAX_BOTTOM_RANGE );
|
||||
}
|
||||
|
||||
|
||||
@@ -1066,7 +1058,7 @@ void SortCoursePointerArrayByAvgDifficulty( vector<Course*> &apCourses )
|
||||
RageTimer foo;
|
||||
course_sort_val.clear();
|
||||
for(unsigned i = 0; i < apCourses.size(); ++i)
|
||||
course_sort_val[apCourses[i]] = apCourses[i]->GetMeter( COURSE_DIFFICULTY_REGULAR );
|
||||
course_sort_val[apCourses[i]] = apCourses[i]->GetMeter();
|
||||
sort( apCourses.begin(), apCourses.end(), CompareCoursePointersByTitle );
|
||||
stable_sort( apCourses.begin(), apCourses.end(), CompareCoursePointersBySortValueAscending );
|
||||
|
||||
|
||||
@@ -112,7 +112,7 @@ public:
|
||||
};
|
||||
|
||||
// Dereferences course_entries and returns only the playable Songs and Steps
|
||||
void GetCourseInfo( StepsType nt, vector<Info> &ci, CourseDifficulty cd = COURSE_DIFFICULTY_INVALID ) const;
|
||||
void GetCourseInfo( StepsType nt, vector<Info> &ci, CourseDifficulty cd = COURSE_DIFFICULTY_REGULAR ) const;
|
||||
|
||||
int GetEstimatedNumStages() const { return m_entries.size(); }
|
||||
bool HasCourseDifficulty( StepsType nt, CourseDifficulty cd ) const;
|
||||
@@ -127,7 +127,8 @@ public:
|
||||
bool IsOni() const { return GetPlayMode() == PLAY_MODE_ONI; }
|
||||
bool IsEndless() const { return GetPlayMode() == PLAY_MODE_ENDLESS; }
|
||||
PlayMode GetPlayMode() const;
|
||||
float GetMeter( CourseDifficulty cd = COURSE_DIFFICULTY_INVALID ) const;
|
||||
float GetMeter( CourseDifficulty cd = COURSE_DIFFICULTY_REGULAR ) const;
|
||||
float GetMeterForPlayer( PlayerNumber pn ) const;
|
||||
|
||||
bool IsFixed() const;
|
||||
|
||||
@@ -201,7 +202,7 @@ public:
|
||||
void ClearCache();
|
||||
|
||||
private:
|
||||
void GetMeterRange( int stage, int& iMeterLowOut, int& iMeterHighOut, CourseDifficulty cd = COURSE_DIFFICULTY_INVALID ) const;
|
||||
void GetMeterRange( int stage, int& iMeterLowOut, int& iMeterHighOut, CourseDifficulty cd ) const;
|
||||
|
||||
typedef pair<StepsType,CourseDifficulty> InfoParams;
|
||||
typedef vector<Info> InfoData;
|
||||
|
||||
@@ -60,7 +60,7 @@ void CourseContentsList::SetFromCourse( Course* pCourse )
|
||||
m_iNumContents = 0;
|
||||
|
||||
vector<Course::Info> ci;
|
||||
pCourse->GetCourseInfo( GAMESTATE->GetCurrentStyleDef()->m_StepsType, ci );
|
||||
pCourse->GetCourseInfo( GAMESTATE->GetCurrentStyleDef()->m_StepsType, ci, GAMESTATE->m_CourseDifficulty[GAMESTATE->m_MasterPlayerNumber] );
|
||||
|
||||
for( int i=0; i<min((int)ci.size(), MAX_TOTAL_CONTENTS); i++ )
|
||||
{
|
||||
|
||||
@@ -109,7 +109,7 @@ void DifficultyMeter::SetFromNotes( const Steps* pNotes )
|
||||
SetDifficulty( DifficultyToString( pNotes->GetDifficulty() ) );
|
||||
}
|
||||
|
||||
void DifficultyMeter::SetFromCourse( const Course* pCourse )
|
||||
void DifficultyMeter::SetFromCourse( const Course* pCourse, PlayerNumber pn )
|
||||
{
|
||||
if( pCourse == NULL )
|
||||
{
|
||||
@@ -117,7 +117,7 @@ void DifficultyMeter::SetFromCourse( const Course* pCourse )
|
||||
return;
|
||||
}
|
||||
|
||||
const int meter = (int) roundf(pCourse->GetMeter());
|
||||
const int meter = (int) roundf(pCourse->GetMeterForPlayer( pn ));
|
||||
|
||||
// XXX metrics
|
||||
Difficulty FakeDifficulty;
|
||||
@@ -150,7 +150,7 @@ void DifficultyMeter::SetFromGameState( PlayerNumber pn )
|
||||
if( GAMESTATE->m_pCurNotes[pn] )
|
||||
SetFromNotes( GAMESTATE->m_pCurNotes[pn] );
|
||||
else if( GAMESTATE->m_pCurCourse )
|
||||
SetFromCourse( GAMESTATE->m_pCurCourse );
|
||||
SetFromCourse( GAMESTATE->m_pCurCourse, pn );
|
||||
else
|
||||
Unset();
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ public:
|
||||
void Load();
|
||||
void SetFromGameState( PlayerNumber pn );
|
||||
void SetFromNotes( const Steps* pNotes );
|
||||
void SetFromCourse( const Course* pCourse );
|
||||
void SetFromCourse( const Course* pCourse, PlayerNumber pn );
|
||||
void Unset();
|
||||
|
||||
private:
|
||||
|
||||
@@ -86,7 +86,10 @@ void GameState::Reset()
|
||||
m_sPreferredGroup = GROUP_ALL_MUSIC;
|
||||
m_bChangedFailType = false;
|
||||
for( p=0; p<NUM_PLAYERS; p++ )
|
||||
{
|
||||
m_PreferredDifficulty[p] = DIFFICULTY_INVALID;
|
||||
m_CourseDifficulty[p] = COURSE_DIFFICULTY_REGULAR;
|
||||
}
|
||||
m_SongSortOrder = SORT_INVALID;
|
||||
m_PlayMode = PLAY_MODE_INVALID;
|
||||
m_bEditing = false;
|
||||
@@ -94,7 +97,6 @@ void GameState::Reset()
|
||||
m_bJukeboxUsesModifiers = false;
|
||||
m_iCurrentStageIndex = 0;
|
||||
m_bAllow2ndExtraStage = true;
|
||||
m_CourseDifficulty = COURSE_DIFFICULTY_REGULAR;
|
||||
m_BeatToNoteSkinRev = 0;
|
||||
|
||||
NOTESKIN->RefreshNoteSkinData( GAMESTATE->m_CurGame );
|
||||
@@ -1273,3 +1275,17 @@ bool GameState::IsTimeToPlayAttractSounds()
|
||||
return m_iNumTimesThroughAttract==0;
|
||||
}
|
||||
|
||||
bool GameState::ChangeCourseDifficulty( PlayerNumber pn, int dir )
|
||||
{
|
||||
CourseDifficulty diff = (CourseDifficulty)(m_CourseDifficulty[pn]+dir);
|
||||
if( diff < 0 || diff >= NUM_COURSE_DIFFICULTIES )
|
||||
return false;
|
||||
|
||||
GAMESTATE->m_CourseDifficulty[pn] = diff;
|
||||
if( PREFSMAN->m_bLockCourseDifficulties )
|
||||
for( int p = 0; p < NUM_PLAYERS; ++p )
|
||||
m_CourseDifficulty[p] = m_CourseDifficulty[pn];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,8 @@ public:
|
||||
int m_iCoins; // not "credits"
|
||||
PlayerNumber m_MasterPlayerNumber; // used in Styles where one player controls both sides
|
||||
bool m_bIsOnSystemMenu; // system screens will not be effected by the operator key -- Miryokuteki
|
||||
CourseDifficulty m_CourseDifficulty; // used in nonstop
|
||||
CourseDifficulty m_CourseDifficulty[NUM_PLAYERS]; // used in nonstop
|
||||
bool ChangeCourseDifficulty( PlayerNumber pn, int dir );
|
||||
time_t m_timeGameStarted; // from the moment the first player pressed Start
|
||||
|
||||
/* This is set to a random number per-game/round; it can be used for a random seed. */
|
||||
|
||||
@@ -82,7 +82,7 @@ bool ModeChoice::DescribesCurrentMode( PlayerNumber pn ) const
|
||||
return false;
|
||||
if( m_pCharacter && GAMESTATE->m_pCurCharacters[pn] != m_pCharacter )
|
||||
return false;
|
||||
if( m_CourseDifficulty != COURSE_DIFFICULTY_INVALID && GAMESTATE->m_CourseDifficulty != m_CourseDifficulty )
|
||||
if( m_CourseDifficulty != COURSE_DIFFICULTY_INVALID && GAMESTATE->m_CourseDifficulty[pn] != m_CourseDifficulty )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@@ -289,7 +289,12 @@ void ModeChoice::Apply( PlayerNumber pn ) const
|
||||
if( m_pCharacter )
|
||||
GAMESTATE->m_pCurCharacters[pn] = m_pCharacter;
|
||||
if( m_CourseDifficulty != COURSE_DIFFICULTY_INVALID )
|
||||
GAMESTATE->m_CourseDifficulty = m_CourseDifficulty;
|
||||
{
|
||||
GAMESTATE->m_CourseDifficulty[pn] = m_CourseDifficulty;
|
||||
if( PREFSMAN->m_bLockCourseDifficulties )
|
||||
for( int p = 0; p < NUM_PLAYERS; ++p )
|
||||
GAMESTATE->m_CourseDifficulty[p] = GAMESTATE->m_CourseDifficulty[pn];
|
||||
}
|
||||
|
||||
// HACK: Set life type to BATTERY just once here so it happens once and
|
||||
// we don't override the user's changes if they back out.
|
||||
|
||||
@@ -159,7 +159,7 @@ void PaneDisplay::SetContent( PaneContents c )
|
||||
else if( g_Contents[c].req&NEED_COURSE )
|
||||
{
|
||||
vector<Course::Info> ci;
|
||||
GAMESTATE->m_pCurCourse->GetCourseInfo( GAMESTATE->GetCurrentStyleDef()->m_StepsType, ci );
|
||||
GAMESTATE->m_pCurCourse->GetCourseInfo( GAMESTATE->GetCurrentStyleDef()->m_StepsType, ci, GAMESTATE->m_CourseDifficulty[m_PlayerNumber] );
|
||||
for( unsigned i = 0; i < ci.size(); ++i )
|
||||
{
|
||||
for( unsigned r = 0; r < NUM_RADAR_CATEGORIES; ++r )
|
||||
|
||||
@@ -174,10 +174,11 @@ ScreenGameplay::ScreenGameplay( CString sName, bool bDemonstration ) : Screen("S
|
||||
++GAMESTATE->m_pCurCourse->m_MemCardDatas[st][mc].iNumTimesPlayed;
|
||||
}
|
||||
|
||||
vector<Course::Info> ci;
|
||||
GAMESTATE->m_pCurCourse->GetCourseInfo( GAMESTATE->GetCurrentStyleDef()->m_StepsType, ci );
|
||||
for( int p=0; p<NUM_PLAYERS; p++ )
|
||||
{
|
||||
vector<Course::Info> ci;
|
||||
GAMESTATE->m_pCurCourse->GetCourseInfo( GAMESTATE->GetCurrentStyleDef()->m_StepsType, ci, GAMESTATE->m_CourseDifficulty[p] );
|
||||
|
||||
m_apNotesQueue[p].clear();
|
||||
m_asModifiersQueue[p].clear();
|
||||
for( unsigned c=0; c<ci.size(); ++c )
|
||||
@@ -187,10 +188,14 @@ ScreenGameplay::ScreenGameplay( CString sName, bool bDemonstration ) : Screen("S
|
||||
ci[c].GetAttackArray( a );
|
||||
m_asModifiersQueue[p].push_back( a );
|
||||
}
|
||||
|
||||
if( p == 0 )
|
||||
{
|
||||
m_apSongsQueue.clear();
|
||||
for( unsigned c=0; c<ci.size(); ++c )
|
||||
m_apSongsQueue.push_back( ci[c].pSong );
|
||||
}
|
||||
}
|
||||
m_apSongsQueue.clear();
|
||||
for( unsigned c=0; c<ci.size(); ++c )
|
||||
m_apSongsQueue.push_back( ci[c].pSong );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -259,20 +259,23 @@ void ScreenSelectCourse::Input( const DeviceInput& DeviceI, InputEventType type,
|
||||
return;
|
||||
}
|
||||
|
||||
if( CodeDetector::EnteredEasierDifficulty(GameI.controller) &&
|
||||
GAMESTATE->m_CourseDifficulty > 0 )
|
||||
PlayerNumber pn = GAMESTATE->GetCurrentStyleDef()->ControllerToPlayerNumber( GameI.controller );
|
||||
if( CodeDetector::EnteredEasierDifficulty(GameI.controller) )
|
||||
{
|
||||
m_soundChangeNotes.Play();
|
||||
GAMESTATE->m_CourseDifficulty = (CourseDifficulty)(GAMESTATE->m_CourseDifficulty-1);
|
||||
SCREENMAN->PostMessageToTopScreen(SM_SongChanged,0);
|
||||
if( GAMESTATE->ChangeCourseDifficulty( pn, +1 ) )
|
||||
{
|
||||
m_soundChangeNotes.Play();
|
||||
SCREENMAN->PostMessageToTopScreen(SM_SongChanged,0);
|
||||
}
|
||||
}
|
||||
|
||||
if( CodeDetector::EnteredHarderDifficulty(GameI.controller) &&
|
||||
GAMESTATE->m_CourseDifficulty < NUM_COURSE_DIFFICULTIES-1 )
|
||||
if( CodeDetector::EnteredHarderDifficulty(GameI.controller) )
|
||||
{
|
||||
m_soundChangeNotes.Play();
|
||||
GAMESTATE->m_CourseDifficulty = (CourseDifficulty)(GAMESTATE->m_CourseDifficulty+1);
|
||||
SCREENMAN->PostMessageToTopScreen(SM_SongChanged,0);
|
||||
if( GAMESTATE->ChangeCourseDifficulty( pn, -1 ) )
|
||||
{
|
||||
m_soundChangeNotes.Play();
|
||||
SCREENMAN->PostMessageToTopScreen(SM_SongChanged,0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -825,10 +825,9 @@ void ScreenSelectMusic::EasierDifficulty( PlayerNumber pn )
|
||||
|
||||
if( m_MusicWheel.GetSelectedType() == TYPE_COURSE )
|
||||
{
|
||||
if( GAMESTATE->m_CourseDifficulty > 0 )
|
||||
if( GAMESTATE->ChangeCourseDifficulty( pn, -1 ) )
|
||||
{
|
||||
m_soundDifficultyEasier.Play();
|
||||
GAMESTATE->m_CourseDifficulty = (CourseDifficulty)(GAMESTATE->m_CourseDifficulty-1);
|
||||
AfterMusicChange();
|
||||
}
|
||||
return;
|
||||
@@ -860,10 +859,9 @@ void ScreenSelectMusic::HarderDifficulty( PlayerNumber pn )
|
||||
|
||||
if( m_MusicWheel.GetSelectedType() == TYPE_COURSE )
|
||||
{
|
||||
if( GAMESTATE->m_CourseDifficulty < NUM_COURSE_DIFFICULTIES-1 )
|
||||
if( GAMESTATE->ChangeCourseDifficulty( pn, +1 ) )
|
||||
{
|
||||
m_soundDifficultyHarder.Play();
|
||||
GAMESTATE->m_CourseDifficulty = (CourseDifficulty)(GAMESTATE->m_CourseDifficulty+1);
|
||||
AfterMusicChange();
|
||||
}
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user