refactor Course: move some responsibilities to Trail
This commit is contained in:
@@ -91,9 +91,11 @@ void BPMDisplay::Update( float fDeltaTime )
|
||||
}
|
||||
|
||||
|
||||
void BPMDisplay::SetBPMRange( const vector<float> &BPMS )
|
||||
void BPMDisplay::SetBPMRange( const DisplayBpms &bpms )
|
||||
{
|
||||
ASSERT( BPMS.size() );
|
||||
ASSERT( !bpms.vfBpms.empty() );
|
||||
|
||||
const vector<float> &BPMS = bpms.vfBpms;
|
||||
|
||||
unsigned i;
|
||||
bool AllIdentical = true;
|
||||
@@ -159,9 +161,9 @@ void BPMDisplay::SetBPMRange( const vector<float> &BPMS )
|
||||
|
||||
void BPMDisplay::CycleRandomly()
|
||||
{
|
||||
vector<float> BPMS;
|
||||
BPMS.push_back(-1);
|
||||
SetBPMRange( BPMS );
|
||||
DisplayBpms bpms;
|
||||
bpms.Add(-1);
|
||||
SetBPMRange( bpms );
|
||||
|
||||
m_fCycleTime = 0.2f;
|
||||
}
|
||||
@@ -183,12 +185,9 @@ void BPMDisplay::SetBPM( const Song* pSong )
|
||||
case Song::DISPLAY_ACTUAL:
|
||||
case Song::DISPLAY_SPECIFIED:
|
||||
{
|
||||
float fMinBPM, fMaxBPM;
|
||||
pSong->GetDisplayBPM( fMinBPM, fMaxBPM );
|
||||
vector<float> BPMS;
|
||||
BPMS.push_back(fMinBPM);
|
||||
BPMS.push_back(fMaxBPM);
|
||||
SetBPMRange( BPMS );
|
||||
DisplayBpms bpms;
|
||||
pSong->GetDisplayBpms( bpms );
|
||||
SetBPMRange( bpms );
|
||||
m_fCycleTime = 1.0f;
|
||||
}
|
||||
break;
|
||||
@@ -204,43 +203,14 @@ void BPMDisplay::SetBPM( const Course* pCourse )
|
||||
{
|
||||
ASSERT( pCourse );
|
||||
|
||||
vector<Course::Info> ci;
|
||||
pCourse->GetCourseInfo( GAMESTATE->GetCurrentStyleDef()->m_StepsType, ci );
|
||||
Trail *pTrail = pCourse->GetTrail( GAMESTATE->GetCurrentStyleDef()->m_StepsType, COURSE_DIFFICULTY_REGULAR );
|
||||
|
||||
ASSERT( ci.size() );
|
||||
ASSERT( pTrail->m_vEntries.size() );
|
||||
|
||||
vector<float> BPMS;
|
||||
for( unsigned i = 0; i < ci.size(); ++i )
|
||||
{
|
||||
if( ci[i].Mystery )
|
||||
{
|
||||
BPMS.push_back( -1 );
|
||||
continue;
|
||||
}
|
||||
|
||||
Song *pSong = ci[i].pSong;
|
||||
ASSERT( pSong );
|
||||
switch( pSong->m_DisplayBPMType )
|
||||
{
|
||||
case Song::DISPLAY_ACTUAL:
|
||||
case Song::DISPLAY_SPECIFIED:
|
||||
{
|
||||
float fMinBPM, fMaxBPM;
|
||||
pSong->GetDisplayBPM( fMinBPM, fMaxBPM );
|
||||
BPMS.push_back( fMinBPM );
|
||||
if( fMinBPM != fMaxBPM )
|
||||
BPMS.push_back( fMaxBPM );
|
||||
}
|
||||
break;
|
||||
case Song::DISPLAY_RANDOM:
|
||||
BPMS.push_back( -1 );
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
}
|
||||
}
|
||||
DisplayBpms bpms;
|
||||
pTrail->GetDisplayBpms( bpms );
|
||||
|
||||
SetBPMRange( BPMS );
|
||||
SetBPMRange( bpms );
|
||||
m_fCycleTime = 0.2f;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ public:
|
||||
|
||||
protected:
|
||||
float GetActiveBPM() const;
|
||||
void SetBPMRange( const vector<float> &m_BPMS );
|
||||
void SetBPMRange( const DisplayBpms &bpms );
|
||||
|
||||
BitmapText m_textBPM;
|
||||
AutoActor m_sprLabel;
|
||||
|
||||
+72
-193
@@ -15,6 +15,7 @@
|
||||
#include "song.h"
|
||||
#include "GameManager.h"
|
||||
#include "SongManager.h"
|
||||
#include "GameState.h"
|
||||
#include "RageException.h"
|
||||
#include "RageLog.h"
|
||||
#include "MsdFile.h"
|
||||
@@ -23,7 +24,6 @@
|
||||
#include "RageUtil.h"
|
||||
#include "TitleSubstitution.h"
|
||||
#include "Steps.h"
|
||||
#include "GameState.h"
|
||||
#include "BannerCache.h"
|
||||
#include "RageFile.h"
|
||||
#include "arch/arch.h"
|
||||
@@ -40,7 +40,7 @@ const int MAX_BOTTOM_RANGE = 10;
|
||||
|
||||
Course::Course()
|
||||
{
|
||||
Unload();
|
||||
Init();
|
||||
}
|
||||
|
||||
PlayMode Course::GetPlayMode() const
|
||||
@@ -50,60 +50,11 @@ PlayMode Course::GetPlayMode() const
|
||||
return m_iLives > 0? PLAY_MODE_ONI:PLAY_MODE_NONSTOP;
|
||||
}
|
||||
|
||||
float Course::GetMeterForPlayer( PlayerNumber pn ) const
|
||||
{
|
||||
return GetMeter( GAMESTATE->m_PreferredCourseDifficulty[pn] );
|
||||
}
|
||||
|
||||
float Course::GetMeter( CourseDifficulty cd ) const
|
||||
{
|
||||
/* If we have a meter for this difficulty, use it. */
|
||||
if( m_iMeter[cd] != -1 )
|
||||
return float( m_iMeter[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());*/
|
||||
vector<Info> ci;
|
||||
GetCourseInfo( GAMESTATE->GetCurrentStyleDef()->m_StepsType, ci, cd );
|
||||
|
||||
if( ci.size() == 0 )
|
||||
return 0;
|
||||
|
||||
/* Take the average meter. */
|
||||
float fTotalMeter = 0;
|
||||
for( unsigned c = 0; c < ci.size(); ++c )
|
||||
{
|
||||
if( ci[c].Mystery )
|
||||
{
|
||||
switch( GetDifficulty(ci[c]) )
|
||||
{
|
||||
case DIFFICULTY_INVALID:
|
||||
{
|
||||
int iMeterLow, iMeterHigh;
|
||||
GetMeterRange(ci[c], iMeterLow, iMeterHigh );
|
||||
fTotalMeter += (iMeterLow + iMeterHigh) / 2.0f;
|
||||
break;
|
||||
}
|
||||
/* XXX? */
|
||||
case DIFFICULTY_BEGINNER: fTotalMeter += 1; break;
|
||||
case DIFFICULTY_EASY: fTotalMeter += 2; break;
|
||||
case DIFFICULTY_MEDIUM: fTotalMeter += 5; break;
|
||||
case DIFFICULTY_HARD: fTotalMeter += 7; break;
|
||||
case DIFFICULTY_CHALLENGE: fTotalMeter += 9; break;
|
||||
}
|
||||
}
|
||||
else
|
||||
fTotalMeter += ci[c].pNotes->GetMeter();
|
||||
}
|
||||
// LOG->Trace("Course '%s': %f", m_sName.c_str(), fTotalMeter/ci.size() );
|
||||
return fTotalMeter / ci.size();
|
||||
}
|
||||
|
||||
void Course::LoadFromCRSFile( CString sPath )
|
||||
{
|
||||
LOG->Trace( "Course::LoadFromCRSFile( '%s' )", sPath.c_str() );
|
||||
|
||||
Unload();
|
||||
Init();
|
||||
|
||||
m_sPath = sPath; // save path
|
||||
|
||||
@@ -152,7 +103,7 @@ void Course::LoadFromCRSFile( CString sPath )
|
||||
else if( 0 == stricmp(sValueName, "METER") )
|
||||
{
|
||||
if( sParams.params.size() == 2 )
|
||||
m_iMeter[COURSE_DIFFICULTY_REGULAR] = atoi( sParams[1] ); /* compat */
|
||||
m_iCustomMeter[COURSE_DIFFICULTY_REGULAR] = atoi( sParams[1] ); /* compat */
|
||||
else if( sParams.params.size() == 3 )
|
||||
{
|
||||
const CourseDifficulty cd = StringToCourseDifficulty( sParams[1] );
|
||||
@@ -162,7 +113,7 @@ void Course::LoadFromCRSFile( CString sPath )
|
||||
m_sPath.c_str(), sParams[1].c_str() );
|
||||
continue;
|
||||
}
|
||||
m_iMeter[cd] = atoi( sParams[2] );
|
||||
m_iCustomMeter[cd] = atoi( sParams[2] );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -314,13 +265,13 @@ void Course::LoadFromCRSFile( CString sPath )
|
||||
ignore, ignore, ignore);
|
||||
}
|
||||
|
||||
void Course::Unload()
|
||||
void Course::Init()
|
||||
{
|
||||
m_bIsAutogen = false;
|
||||
m_bRepeat = false;
|
||||
m_bRandomize = false;
|
||||
m_iLives = -1;
|
||||
m_iMeter[0] = m_iMeter[1] = -1;
|
||||
ZERO( m_iCustomMeter );
|
||||
m_entries.clear();
|
||||
m_sPath = m_sName = m_sTranslitName = m_sBannerPath = m_sCDTitlePath = "";
|
||||
}
|
||||
@@ -343,9 +294,9 @@ void Course::Save()
|
||||
f.PutLine( ssprintf("#LIVES:%i;", m_iLives) );
|
||||
FOREACH_CourseDifficulty( cd )
|
||||
{
|
||||
if( m_iMeter[cd] == -1 )
|
||||
if( m_iCustomMeter[cd] == -1 )
|
||||
continue;
|
||||
f.PutLine( ssprintf("#METER:%s:%i;", CourseDifficultyToString(cd).c_str(), m_iMeter[cd]) );
|
||||
f.PutLine( ssprintf("#METER:%s:%i;", CourseDifficultyToString(cd).c_str(), m_iCustomMeter[cd]) );
|
||||
}
|
||||
|
||||
for( unsigned i=0; i<m_entries.size(); i++ )
|
||||
@@ -435,7 +386,7 @@ void Course::AutogenEndlessFromGroup( CString sGroupName, Difficulty diff )
|
||||
m_bRepeat = true;
|
||||
m_bRandomize = true;
|
||||
m_iLives = -1;
|
||||
m_iMeter[0] = m_iMeter[1] = -1;
|
||||
m_iCustomMeter[0] = m_iCustomMeter[1] = -1;
|
||||
|
||||
if( sGroupName == "" )
|
||||
{
|
||||
@@ -502,58 +453,20 @@ bool Course::HasCourseDifficulty( StepsType nt, CourseDifficulty cd ) const
|
||||
{
|
||||
/* Check to see if any songs would change if difficult. */
|
||||
|
||||
/* COURSE_DIFFICULTY_REGULAR is always available (provided IsPlayableIn). */
|
||||
/* COURSE_DIFFICULTY_REGULAR is always available (if IsPlayableIn == true). */
|
||||
if( cd == COURSE_DIFFICULTY_REGULAR )
|
||||
return true;
|
||||
|
||||
vector<Info> Normal, Hard;
|
||||
GetCourseInfo( nt, Normal, COURSE_DIFFICULTY_REGULAR );
|
||||
GetCourseInfo( nt, Hard, cd );
|
||||
Trail *Regular = GetTrail( nt, COURSE_DIFFICULTY_REGULAR );
|
||||
Trail *Other = GetTrail( nt, cd );
|
||||
|
||||
if( Normal.size() != Hard.size() )
|
||||
return true; /* it changed */
|
||||
|
||||
for( unsigned i=0; i<Normal.size(); i++ )
|
||||
{
|
||||
if( Normal[i].CourseIndex != Hard[i].CourseIndex )
|
||||
return true; /* it changed */
|
||||
|
||||
if( Normal[i].Mystery )
|
||||
{
|
||||
const CourseEntry &e = m_entries[ Normal[i].CourseIndex ];
|
||||
|
||||
if( e.difficulty != DIFFICULTY_INVALID )
|
||||
{
|
||||
/* Check if the song's difficulty class will actually change. */
|
||||
Difficulty dc = (Difficulty) (e.difficulty + COURSE_DIFFICULTY_CLASS_CHANGE[cd]);
|
||||
dc = clamp( dc, DIFFICULTY_BEGINNER, DIFFICULTY_CHALLENGE );
|
||||
if( dc != e.difficulty )
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Meters under MAX_BOTTOM_RANGE..MAX_BOTTOM_RANGE change by getting harder. */
|
||||
if( e.difficulty == DIFFICULTY_INVALID )
|
||||
{
|
||||
/* Check if the meter will actually change. */
|
||||
int iNewLowMeter = clamp( 1, e.low_meter + COURSE_DIFFICULTY_METER_CHANGE[cd], MAX_BOTTOM_RANGE );
|
||||
int iNewHighMeter = clamp( 1, e.high_meter + COURSE_DIFFICULTY_METER_CHANGE[cd], MAX_BOTTOM_RANGE );
|
||||
if( iNewLowMeter != e.low_meter || iNewHighMeter != e.high_meter )
|
||||
return true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if( Normal[i].pSong != Hard[i].pSong || Normal[i].pNotes != Hard[i].pNotes )
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return Regular != Other;
|
||||
}
|
||||
|
||||
bool Course::IsPlayableIn( StepsType nt ) const
|
||||
{
|
||||
vector<Info> ci;
|
||||
GetCourseInfo( nt, ci );
|
||||
return ci.size() > 0;
|
||||
Trail* pTrail = GetTrail( nt, COURSE_DIFFICULTY_REGULAR );
|
||||
return !pTrail->m_vEntries.empty();
|
||||
}
|
||||
|
||||
static vector<Song*> GetFilteredBestSongs( StepsType nt )
|
||||
@@ -597,16 +510,22 @@ static vector<Song*> GetFilteredBestSongs( StepsType nt )
|
||||
/* This is called by many simple functions, like Course::GetTotalSeconds, and may
|
||||
* be called on all songs to sort. It can take time to execute, so we cache the
|
||||
* results. */
|
||||
void Course::GetCourseInfo( StepsType nt, vector<Course::Info> &ci, CourseDifficulty cd ) const
|
||||
Trail* Course::GetTrail( StepsType nt, CourseDifficulty cd ) const
|
||||
{
|
||||
const InfoParams params( nt, cd );
|
||||
InfoCache::const_iterator it = m_InfoCache.find( params );
|
||||
if( it != m_InfoCache.end() )
|
||||
//
|
||||
// Look in the Trail cache
|
||||
//
|
||||
const TrailParams params( nt, cd );
|
||||
TrailCache::iterator it = m_TrailCache.find( params );
|
||||
if( it != m_TrailCache.end() )
|
||||
{
|
||||
ci = it->second;
|
||||
return;
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Construct a new Trail, add it to the cache, then return it.
|
||||
//
|
||||
/* Different seed for each course, but the same for the whole round: */
|
||||
RandomGen rnd( GAMESTATE->m_iRoundSeed + GetHashForString(m_sName) );
|
||||
|
||||
@@ -630,7 +549,8 @@ void Course::GetCourseInfo( StepsType nt, vector<Course::Info> &ci, CourseDiffic
|
||||
vector<Song*> AllSongsShuffled;
|
||||
|
||||
int CurSong = 0; /* Current offset into AllSongsShuffled */
|
||||
ci.clear();
|
||||
|
||||
Trail trail;
|
||||
|
||||
for( unsigned i=0; i<entries.size(); i++ )
|
||||
{
|
||||
@@ -754,20 +674,20 @@ void Course::GetCourseInfo( StepsType nt, vector<Course::Info> &ci, CourseDiffic
|
||||
}
|
||||
}
|
||||
|
||||
Info cinfo;
|
||||
cinfo.pSong = pSong;
|
||||
cinfo.pNotes = pNotes;
|
||||
cinfo.Modifiers = e.modifiers;
|
||||
cinfo.Attacks = e.attacks;
|
||||
cinfo.Random = ( e.type == COURSE_ENTRY_RANDOM || e.type == COURSE_ENTRY_RANDOM_WITHIN_GROUP );
|
||||
cinfo.Mystery = e.mystery;
|
||||
cinfo.CourseIndex = i;
|
||||
cinfo.Difficulty = entry_difficulty;
|
||||
ci.push_back( cinfo );
|
||||
TrailEntry te;
|
||||
te.pSong = pSong;
|
||||
te.pNotes = pNotes;
|
||||
te.Modifiers = e.modifiers;
|
||||
te.Attacks = e.attacks;
|
||||
te.bMystery = e.mystery;
|
||||
te.iLowMeter = low_meter;
|
||||
te.iHighMeter = high_meter;
|
||||
trail.m_vEntries.push_back( te );
|
||||
}
|
||||
|
||||
/* Cache results. */
|
||||
m_InfoCache[params] = ci;
|
||||
m_TrailCache[params] = trail;
|
||||
return &m_TrailCache[params];
|
||||
}
|
||||
|
||||
bool Course::HasMods() const
|
||||
@@ -793,11 +713,14 @@ bool Course::AllSongsAreFixed() const
|
||||
|
||||
void Course::ClearCache()
|
||||
{
|
||||
m_InfoCache.clear();
|
||||
m_TrailCache.clear();
|
||||
}
|
||||
|
||||
RageColor Course::GetColor() const
|
||||
{
|
||||
// FIXME: These colors shouldn't be hard-coded
|
||||
int iMeter = 5;
|
||||
|
||||
switch (PREFSMAN->m_iCourseSortOrder)
|
||||
{
|
||||
case PrefsManager::COURSE_SORT_SONGS:
|
||||
@@ -813,31 +736,31 @@ RageColor Course::GetColor() const
|
||||
case PrefsManager::COURSE_SORT_METER:
|
||||
if ( !IsFixed() )
|
||||
return RageColor(0,0,1,1); // blue
|
||||
if (GetMeter() > 8.5)
|
||||
if (iMeter > 8.5)
|
||||
return RageColor(1,0,0,1); // red
|
||||
if (GetMeter() >= 7)
|
||||
if (iMeter >= 7)
|
||||
return RageColor(1,0.5f,0,1); // orange
|
||||
if (GetMeter() >= 5)
|
||||
if (iMeter >= 5)
|
||||
return RageColor(1,1,0,1); // yellow
|
||||
return RageColor(0,1,0,1); // green
|
||||
|
||||
case PrefsManager::COURSE_SORT_METER_SUM:
|
||||
if ( !IsFixed() )
|
||||
return RageColor(0,0,1,1); // blue
|
||||
if (SortOrder_TotalDifficulty >= 40)
|
||||
if (m_SortOrder_TotalDifficulty >= 40)
|
||||
return RageColor(1,0,0,1); // red
|
||||
if (SortOrder_TotalDifficulty >= 30)
|
||||
if (m_SortOrder_TotalDifficulty >= 30)
|
||||
return RageColor(1,0.5f,0,1); // orange
|
||||
if (SortOrder_TotalDifficulty >= 20)
|
||||
if (m_SortOrder_TotalDifficulty >= 20)
|
||||
return RageColor(1,1,0,1); // yellow
|
||||
return RageColor(0,1,0,1); // green
|
||||
|
||||
case PrefsManager::COURSE_SORT_RANK:
|
||||
if (SortOrder_Ranking == 3)
|
||||
if (m_SortOrder_Ranking == 3)
|
||||
return RageColor(0,0,1,1); // blue
|
||||
if (SortOrder_Ranking == 2)
|
||||
if (m_SortOrder_Ranking == 2)
|
||||
return RageColor(1,0.5f,0,1); // orange
|
||||
if (SortOrder_Ranking == 1)
|
||||
if (m_SortOrder_Ranking == 1)
|
||||
return RageColor(0,1,0,1); // green
|
||||
return RageColor(1,1,0,1); // yellow, never should get here
|
||||
default:
|
||||
@@ -859,14 +782,6 @@ bool Course::IsFixed() const
|
||||
return true;
|
||||
}
|
||||
|
||||
Difficulty Course::GetDifficulty( const Info &stage ) const
|
||||
{
|
||||
Difficulty dc = m_entries[stage.CourseIndex].difficulty;
|
||||
Difficulty new_dc = Difficulty( dc + COURSE_DIFFICULTY_CLASS_CHANGE[stage.Difficulty] );
|
||||
new_dc = clamp( new_dc, DIFFICULTY_BEGINNER, DIFFICULTY_CHALLENGE );
|
||||
return new_dc;
|
||||
}
|
||||
|
||||
void Course::GetMeterRange( int stage, int& iMeterLowOut, int& iMeterHighOut, CourseDifficulty cd ) const
|
||||
{
|
||||
iMeterLowOut = m_entries[stage].low_meter;
|
||||
@@ -878,23 +793,14 @@ void Course::GetMeterRange( int stage, int& iMeterLowOut, int& iMeterHighOut, Co
|
||||
}
|
||||
|
||||
|
||||
void Course::GetMeterRange( const Info &stage, int& iMeterLowOut, int& iMeterHighOut ) const
|
||||
bool Course::GetTotalSeconds( StepsType st, float& fSecondsOut ) const
|
||||
{
|
||||
GetMeterRange( stage.CourseIndex, iMeterLowOut, iMeterHighOut, stage.Difficulty );
|
||||
}
|
||||
if( !IsFixed() )
|
||||
return false;
|
||||
|
||||
bool Course::GetTotalSeconds( float& fSecondsOut ) const
|
||||
{
|
||||
vector<Info> ci;
|
||||
GetCourseInfo( STEPS_TYPE_DANCE_SINGLE, ci );
|
||||
Trail* pTrail = GetTrail( st, COURSE_DIFFICULTY_REGULAR );
|
||||
|
||||
fSecondsOut = 0;
|
||||
for( unsigned i=0; i<ci.size(); i++ )
|
||||
{
|
||||
if( ci[i].Mystery )
|
||||
return false;
|
||||
fSecondsOut += ci[i].pSong->m_fMusicLengthSeconds;
|
||||
}
|
||||
fSecondsOut = pTrail->GetLengthSeconds();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -918,9 +824,9 @@ bool Course::HasBanner() const
|
||||
return m_sBannerPath != "" && IsAFile(m_sBannerPath);
|
||||
}
|
||||
|
||||
void Course::UpdateCourseStats()
|
||||
void Course::UpdateCourseStats( StepsType st )
|
||||
{
|
||||
SortOrder_TotalDifficulty = 0;
|
||||
m_SortOrder_TotalDifficulty = 0;
|
||||
|
||||
unsigned i;
|
||||
|
||||
@@ -930,17 +836,15 @@ void Course::UpdateCourseStats()
|
||||
if ( m_entries[i].type == COURSE_ENTRY_FIXED )
|
||||
continue;
|
||||
|
||||
if ( SortOrder_Ranking == 2 )
|
||||
SortOrder_Ranking = 3;
|
||||
SortOrder_TotalDifficulty = 999999; // large number
|
||||
if ( m_SortOrder_Ranking == 2 )
|
||||
m_SortOrder_Ranking = 3;
|
||||
m_SortOrder_TotalDifficulty = 999999; // large number
|
||||
return;
|
||||
}
|
||||
|
||||
vector<Info> ci;
|
||||
GetCourseInfo( GAMESTATE->GetCurrentStyleDef()->m_StepsType, ci );
|
||||
Trail* pTrail = GetTrail( st, COURSE_DIFFICULTY_REGULAR );
|
||||
|
||||
for( i = 0; i < ci.size(); i++ )
|
||||
SortOrder_TotalDifficulty += ci[i].pNotes->GetMeter();
|
||||
m_SortOrder_TotalDifficulty += pTrail->GetTotalMeter();
|
||||
|
||||
// OPTIMIZATION: Ranking info isn't dependant on style, so
|
||||
// call it sparingly. Its handled on startup and when
|
||||
@@ -948,23 +852,7 @@ void Course::UpdateCourseStats()
|
||||
|
||||
LOG->Trace("%s: Total feet: %d",
|
||||
this->m_sName.c_str(),
|
||||
SortOrder_TotalDifficulty );
|
||||
}
|
||||
|
||||
void Course::Info::GetAttackArray( AttackArray &out ) const
|
||||
{
|
||||
if( !Modifiers.empty() )
|
||||
{
|
||||
Attack a;
|
||||
a.fStartSecond = 0;
|
||||
a.fSecsRemaining = 10000; /* whole song */
|
||||
a.level = ATTACK_LEVEL_1;
|
||||
a.sModifier = Modifiers;
|
||||
|
||||
out.push_back( a );
|
||||
}
|
||||
|
||||
out.insert( out.end(), Attacks.begin(), Attacks.end() );
|
||||
m_SortOrder_TotalDifficulty );
|
||||
}
|
||||
|
||||
bool Course::IsRanking() const
|
||||
@@ -980,20 +868,11 @@ bool Course::IsRanking() const
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
RadarValues Course::GetRadarValues( StepsType st, CourseDifficulty cd ) const
|
||||
float Course::GetMeter( StepsType nt, CourseDifficulty cd ) const
|
||||
{
|
||||
RadarValues rv;
|
||||
/* If we have a manually-entered meter for this difficulty, use it. */
|
||||
if( m_iCustomMeter[cd] != -1 )
|
||||
return m_iCustomMeter[cd];
|
||||
|
||||
vector<Course::Info> ci;
|
||||
this->GetCourseInfo( st, ci, cd );
|
||||
for( unsigned i = 0; i < ci.size(); ++i )
|
||||
{
|
||||
const Steps *pNotes = ci[i].pNotes;
|
||||
ASSERT( pNotes );
|
||||
rv += pNotes->GetRadarValues();
|
||||
}
|
||||
|
||||
return rv;
|
||||
return roundf( GetTrail(nt,cd)->GetAverageMeter() );
|
||||
}
|
||||
|
||||
|
||||
+12
-32
@@ -15,6 +15,7 @@
|
||||
#include "GameConstantsAndTypes.h"
|
||||
#include "Attack.h"
|
||||
#include <map>
|
||||
#include "Trail.h"
|
||||
|
||||
struct PlayerOptions;
|
||||
struct SongOptions;
|
||||
@@ -93,28 +94,14 @@ public:
|
||||
bool m_bRepeat; // repeat after last song? "Endless"
|
||||
bool m_bRandomize; // play the songs in a random order
|
||||
int m_iLives; // -1 means use bar life meter
|
||||
int m_iMeter[NUM_COURSE_DIFFICULTIES]; // -1 autogens
|
||||
int m_iCustomMeter[NUM_COURSE_DIFFICULTIES]; // -1 = no meter specified
|
||||
|
||||
vector<CourseEntry> m_entries;
|
||||
|
||||
struct Info
|
||||
{
|
||||
Info(): pSong(NULL), pNotes(NULL), Random(false), Difficulty(COURSE_DIFFICULTY_INVALID) { }
|
||||
void GetAttackArray( AttackArray &out ) const;
|
||||
|
||||
Song* pSong;
|
||||
Steps* pNotes;
|
||||
CString Modifiers;
|
||||
AttackArray Attacks;
|
||||
bool Random;
|
||||
bool Mystery;
|
||||
CourseDifficulty Difficulty;
|
||||
/* Corresponding entry in m_entries: */
|
||||
int CourseIndex;
|
||||
};
|
||||
|
||||
// Dereferences course_entries and returns only the playable Songs and Steps
|
||||
void GetCourseInfo( StepsType nt, vector<Info> &ci, CourseDifficulty cd = COURSE_DIFFICULTY_REGULAR ) const;
|
||||
Trail* GetTrail( StepsType nt, CourseDifficulty cd ) const;
|
||||
float GetMeter( StepsType nt, CourseDifficulty cd ) const;
|
||||
bool HasMods() const;
|
||||
bool AllSongsAreFixed() const;
|
||||
|
||||
@@ -123,33 +110,27 @@ public:
|
||||
bool IsPlayableIn( StepsType nt ) const;
|
||||
bool CourseHasBestOrWorst() const;
|
||||
RageColor GetColor() const;
|
||||
Difficulty GetDifficulty( const Info &stage ) const;
|
||||
void GetMeterRange( const Info &stage, int& iMeterLowOut, int& iMeterHighOut ) const;
|
||||
bool GetTotalSeconds( float& fSecondsOut ) const;
|
||||
bool GetTotalSeconds( StepsType st, float& fSecondsOut ) const;
|
||||
|
||||
bool IsNonstop() const { return GetPlayMode() == PLAY_MODE_NONSTOP; }
|
||||
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_REGULAR ) const;
|
||||
float GetMeterForPlayer( PlayerNumber pn ) const;
|
||||
|
||||
bool IsFixed() const;
|
||||
|
||||
void LoadFromCRSFile( CString sPath );
|
||||
void Unload();
|
||||
void Init();
|
||||
void Save();
|
||||
void AutogenEndlessFromGroup( CString sGroupName, Difficulty diff );
|
||||
void AutogenNonstopFromGroup( CString sGroupName, Difficulty diff );
|
||||
|
||||
RadarValues GetRadarValues( StepsType st, CourseDifficulty cd ) const;
|
||||
|
||||
// sorting values
|
||||
int SortOrder_TotalDifficulty;
|
||||
int SortOrder_Ranking;
|
||||
int m_SortOrder_TotalDifficulty;
|
||||
int m_SortOrder_Ranking;
|
||||
bool IsRanking() const;
|
||||
|
||||
void UpdateCourseStats();
|
||||
void UpdateCourseStats( StepsType st );
|
||||
|
||||
/* Call per-screen, and if song or notes pointers change: */
|
||||
void ClearCache();
|
||||
@@ -158,10 +139,9 @@ private:
|
||||
CString GetAutogenDifficultySuffix( Difficulty diff ) const;
|
||||
void GetMeterRange( int stage, int& iMeterLowOut, int& iMeterHighOut, CourseDifficulty cd ) const;
|
||||
|
||||
typedef pair<StepsType,CourseDifficulty> InfoParams;
|
||||
typedef vector<Info> InfoData;
|
||||
typedef map<InfoParams, InfoData> InfoCache;
|
||||
mutable InfoCache m_InfoCache;
|
||||
typedef pair<StepsType,CourseDifficulty> TrailParams;
|
||||
typedef map<TrailParams, Trail> TrailCache;
|
||||
mutable TrailCache m_TrailCache;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -56,17 +56,25 @@ void CourseContentsList::SetFromCourse( const Course* pCourse )
|
||||
return;
|
||||
}
|
||||
|
||||
vector<Course::Info> ci[NUM_PLAYERS];
|
||||
for( int pn = 0; pn < NUM_PLAYERS; ++pn )
|
||||
pCourse->GetCourseInfo( GAMESTATE->GetCurrentStyleDef()->m_StepsType, ci[pn], GAMESTATE->m_PreferredCourseDifficulty[pn] );
|
||||
Trail* pTrail[NUM_PLAYERS];
|
||||
FOREACH_PlayerNumber(pn)
|
||||
{
|
||||
pTrail[pn] = pCourse->GetTrail( GAMESTATE->GetCurrentStyleDef()->m_StepsType, GAMESTATE->m_PreferredCourseDifficulty[pn] );
|
||||
}
|
||||
|
||||
m_iNumContents = 0;
|
||||
for( int i=0; i<min((int)ci[0].size(), MAX_TOTAL_CONTENTS); i++ )
|
||||
// FIXME: Is there a better way to handle when players don't have
|
||||
// the same number of TrailEntries?
|
||||
|
||||
m_iNumContents = 0;
|
||||
|
||||
for( int i=0; i<min((int)pTrail[0]->m_vEntries.size(), MAX_TOTAL_CONTENTS); i++ )
|
||||
{
|
||||
CourseEntryDisplay& display = m_CourseContentDisplays[m_iNumContents];
|
||||
|
||||
const Course::Info pci[NUM_PLAYERS] = { ci[0][i], ci[1][i] };
|
||||
display.LoadFromCourseInfo( m_iNumContents+1, pCourse, pci );
|
||||
TrailEntry* pte[NUM_PLAYERS];
|
||||
FOREACH_EnabledPlayer(pn)
|
||||
pte[pn] = &pTrail[0]->m_vEntries[i];
|
||||
display.LoadFromTrailEntry( m_iNumContents+1, pCourse, pte );
|
||||
|
||||
m_iNumContents++;
|
||||
}
|
||||
|
||||
@@ -87,24 +87,24 @@ void CourseEntryDisplay::SetDifficulty( PlayerNumber pn, const CString &text, Ra
|
||||
m_textFoot[pn].SetDiffuse( c );
|
||||
}
|
||||
|
||||
void CourseEntryDisplay::LoadFromCourseInfo( int iNum, const Course *pCourse, const Course::Info pci[NUM_PLAYERS] )
|
||||
void CourseEntryDisplay::LoadFromTrailEntry( int iNum, const Course *pCourse, TrailEntry *tes[NUM_PLAYERS] )
|
||||
{
|
||||
const Course::Info &ci = pci[GAMESTATE->m_MasterPlayerNumber];
|
||||
|
||||
if( ci.Mystery )
|
||||
TrailEntry *te = tes[GAMESTATE->m_MasterPlayerNumber];
|
||||
bool bMystery = te->bMystery;
|
||||
if( bMystery )
|
||||
{
|
||||
for( int pn = 0; pn < NUM_PLAYERS; ++pn )
|
||||
FOREACH_EnabledPlayer(pn)
|
||||
{
|
||||
Difficulty dc = pCourse->GetDifficulty( pci[pn] );
|
||||
TrailEntry *te = tes[pn];
|
||||
Difficulty dc = te->pNotes->GetDifficulty();
|
||||
if( dc == DIFFICULTY_INVALID )
|
||||
{
|
||||
int iLow, iHigh;
|
||||
pCourse->GetMeterRange(pci[pn], iLow, iHigh);
|
||||
|
||||
SetDifficulty( (PlayerNumber)pn, ssprintf(iLow==iHigh?"%d":"%d-%d", iLow, iHigh), RageColor(1,1,1,1) );
|
||||
int iLow = te->iLowMeter;
|
||||
int iHigh = te->iHighMeter;
|
||||
SetDifficulty( pn, ssprintf(iLow==iHigh?"%d":"%d-%d", iLow, iHigh), RageColor(1,1,1,1) );
|
||||
}
|
||||
else
|
||||
SetDifficulty( (PlayerNumber)pn, "?", SONGMAN->GetDifficultyColor( dc ) );
|
||||
SetDifficulty( pn, "?", SONGMAN->GetDifficultyColor( dc ) );
|
||||
}
|
||||
|
||||
m_TextBanner.LoadFromString( "??????????", "??????????", "", "", "", "" );
|
||||
@@ -112,17 +112,18 @@ void CourseEntryDisplay::LoadFromCourseInfo( int iNum, const Course *pCourse, co
|
||||
}
|
||||
else
|
||||
{
|
||||
for( int pn = 0; pn < NUM_PLAYERS; ++pn )
|
||||
FOREACH_EnabledPlayer(pn)
|
||||
{
|
||||
RageColor colorNotes = SONGMAN->GetDifficultyColor( pci[pn].pNotes->GetDifficulty() );
|
||||
SetDifficulty( (PlayerNumber)pn, ssprintf("%d", pci[pn].pNotes->GetMeter()), colorNotes );
|
||||
TrailEntry *te = tes[pn];
|
||||
RageColor colorNotes = SONGMAN->GetDifficultyColor( te->pNotes->GetDifficulty() );
|
||||
SetDifficulty( pn, ssprintf("%d", te->pNotes->GetMeter()), colorNotes );
|
||||
}
|
||||
|
||||
m_TextBanner.LoadFromSong( ci.pSong );
|
||||
m_TextBanner.SetDiffuse( SONGMAN->GetSongColor( ci.pSong ) );
|
||||
m_TextBanner.LoadFromSong( te->pSong );
|
||||
m_TextBanner.SetDiffuse( SONGMAN->GetSongColor( te->pSong ) );
|
||||
}
|
||||
|
||||
m_textNumber.SetText( ssprintf("%d", iNum) );
|
||||
|
||||
m_textModifiers.SetText( ci.Modifiers );
|
||||
m_textModifiers.SetText( te->Modifiers );
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ class CourseEntryDisplay : public ActorFrame
|
||||
public:
|
||||
void Load();
|
||||
|
||||
void LoadFromCourseInfo( int iNum, const Course *pCourse, const Course::Info ci[NUM_PLAYERS] );
|
||||
void LoadFromTrailEntry( int iNum, const Course *pCourse, TrailEntry *te[NUM_PLAYERS] );
|
||||
|
||||
private:
|
||||
void SetDifficulty( PlayerNumber pn, const CString &text, RageColor c );
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
#include "ProfileManager.h"
|
||||
#include "SongManager.h"
|
||||
#include "XmlFile.h"
|
||||
#include "GameState.h"
|
||||
#include "StyleDef.h"
|
||||
|
||||
|
||||
//
|
||||
@@ -64,8 +66,8 @@ static bool CompareCoursePointersByDifficulty(const Course* pCourse1, const Cour
|
||||
|
||||
static bool CompareCoursePointersByTotalDifficulty(const Course* pCourse1, const Course* pCourse2)
|
||||
{
|
||||
int iNum1 = pCourse1->SortOrder_TotalDifficulty;
|
||||
int iNum2 = pCourse2->SortOrder_TotalDifficulty;
|
||||
int iNum1 = pCourse1->m_SortOrder_TotalDifficulty;
|
||||
int iNum2 = pCourse2->m_SortOrder_TotalDifficulty;
|
||||
|
||||
if( iNum1 == iNum2 )
|
||||
return CompareCoursePointersByAutogen( pCourse1, pCourse2 );
|
||||
@@ -93,8 +95,8 @@ static bool CompareRandom( const Course* pCourse1, const Course* pCourse2 )
|
||||
|
||||
static bool CompareCoursePointersByRanking(const Course* pCourse1, const Course* pCourse2)
|
||||
{
|
||||
int iNum1 = pCourse1->SortOrder_Ranking;
|
||||
int iNum2 = pCourse2->SortOrder_Ranking;
|
||||
int iNum1 = pCourse1->m_SortOrder_Ranking;
|
||||
int iNum2 = pCourse2->m_SortOrder_Ranking;
|
||||
|
||||
if( iNum1 == iNum2 )
|
||||
return CompareCoursePointersByAutogen( pCourse1, pCourse2 );
|
||||
@@ -109,14 +111,14 @@ void CourseUtil::SortCoursePointerArrayByDifficulty( vector<Course*> &apCourses
|
||||
void CourseUtil::SortCoursePointerArrayByRanking( vector<Course*> &apCourses )
|
||||
{
|
||||
for(unsigned i=0; i<apCourses.size(); i++)
|
||||
apCourses[i]->UpdateCourseStats();
|
||||
apCourses[i]->UpdateCourseStats( GAMESTATE->GetCurrentStyleDef()->m_StepsType );
|
||||
sort( apCourses.begin(), apCourses.end(), CompareCoursePointersByRanking );
|
||||
}
|
||||
|
||||
void CourseUtil::SortCoursePointerArrayByTotalDifficulty( vector<Course*> &apCourses )
|
||||
{
|
||||
for(unsigned i=0; i<apCourses.size(); i++)
|
||||
apCourses[i]->UpdateCourseStats();
|
||||
apCourses[i]->UpdateCourseStats( GAMESTATE->GetCurrentStyleDef()->m_StepsType );
|
||||
sort( apCourses.begin(), apCourses.end(), CompareCoursePointersByTotalDifficulty );
|
||||
}
|
||||
|
||||
@@ -157,7 +159,7 @@ void CourseUtil::SortCoursePointerArrayByAvgDifficulty( vector<Course*> &apCours
|
||||
RageTimer foo;
|
||||
course_sort_val.clear();
|
||||
for(unsigned i = 0; i < apCourses.size(); ++i)
|
||||
course_sort_val[apCourses[i]] = apCourses[i]->GetMeter();
|
||||
course_sort_val[apCourses[i]] = apCourses[i]->GetMeter( GAMESTATE->GetCurrentStyleDef()->m_StepsType, COURSE_DIFFICULTY_REGULAR );
|
||||
sort( apCourses.begin(), apCourses.end(), CompareCoursePointersByTitle );
|
||||
stable_sort( apCourses.begin(), apCourses.end(), CompareCoursePointersBySortValueAscending );
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "Course.h"
|
||||
#include "SongManager.h"
|
||||
#include "ActorUtil.h"
|
||||
#include "StyleDef.h"
|
||||
|
||||
|
||||
#define NUM_FEET_IN_METER THEME->GetMetricI(m_sName,"NumFeetInMeter")
|
||||
@@ -117,7 +118,9 @@ void DifficultyMeter::SetFromCourse( const Course* pCourse, PlayerNumber pn )
|
||||
return;
|
||||
}
|
||||
|
||||
const int meter = (int) roundf(pCourse->GetMeterForPlayer( pn ));
|
||||
StepsType st = GAMESTATE->GetCurrentStyleDef()->m_StepsType;
|
||||
CourseDifficulty cd = GAMESTATE->m_PreferredCourseDifficulty[pn];
|
||||
const int meter = (int) roundf( pCourse->GetMeter(st,cd) );
|
||||
|
||||
// XXX metrics
|
||||
Difficulty FakeDifficulty;
|
||||
|
||||
@@ -33,58 +33,4 @@ static const CString EMPTY_STRING;
|
||||
return (X)(i+1); /*invalid*/ \
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// An enum class with reflection-like functionality.
|
||||
// String literals are stored in GetString instead of a static member so that
|
||||
// the literals can be defined in the header.
|
||||
//
|
||||
#define BEGIN_ENUM( name ) \
|
||||
class name { \
|
||||
public: \
|
||||
enum Value { \
|
||||
|
||||
#define MIDDLE_ENUM( name ) \
|
||||
NUM, \
|
||||
INVALID = -1, \
|
||||
}; \
|
||||
protected: \
|
||||
Value m_value; \
|
||||
CCStringRef GetString(int i) const { \
|
||||
const CString s[NUM] = { \
|
||||
|
||||
#define END_ENUM( name ) \
|
||||
}; return s[i]; } \
|
||||
public: \
|
||||
name( Value value ) { m_value=value; } \
|
||||
name() { MakeInvalid(); } \
|
||||
name( int value ) { m_value=(Value)value; } \
|
||||
operator int&() { return (int&)m_value; } \
|
||||
operator size_t() const { return (size_t)m_value; } \
|
||||
static size_t Num() { return (size_t)NUM; } \
|
||||
name& operator=(Value val) { m_value = val; return *this; } \
|
||||
bool operator<(const name& other) const { return m_value < other.m_value; } \
|
||||
void MakeInvalid() { m_value=INVALID; } \
|
||||
bool IsValid() const { return m_value>=0 && m_value<NUM; } \
|
||||
CCStringRef ToString() const { ASSERT(IsValid()); return GetString(m_value); } \
|
||||
CString ToThemedString() const { return GetThemedString(#name,ToString()); } \
|
||||
void FromString( CString s ) \
|
||||
{ \
|
||||
for( int i=0; i<NUM; i++ ) \
|
||||
{ \
|
||||
if( stricmp(s,GetString(i))==0 ) \
|
||||
{ \
|
||||
m_value = (Value)i; \
|
||||
return; \
|
||||
} \
|
||||
} \
|
||||
MakeInvalid(); \
|
||||
} \
|
||||
}; \
|
||||
|
||||
#define FOREACH( name, var ) for( name var(0); (int)var<(int)name::NUM; var++ )
|
||||
|
||||
CString GetThemedString( CCStringRef sClass, CCStringRef sValue );
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
#ifndef Foreach_H
|
||||
#define Foreach_H
|
||||
|
||||
|
||||
#define FOREACH( elemType, vect, var ) for( vector<elemType>::iterator var = vect.begin(); var != vect.end(); var++ )
|
||||
#define FOREACH_CONST( elemType, vect, var ) for( vector<elemType>::const_iterator var = vect.begin(); var != vect.end(); var++ )
|
||||
|
||||
|
||||
#endif
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "RageUtil.h"
|
||||
#include "ThemeManager.h"
|
||||
#include "EnumHelper.h"
|
||||
#include "Foreach.h"
|
||||
|
||||
|
||||
static const CString RadarCategoryNames[NUM_RADAR_CATEGORIES] = {
|
||||
@@ -170,3 +171,49 @@ LuaFunction_Str( StringTo##X, LuaStringTo##X(str) ); /* register it */
|
||||
|
||||
LuaXToString( Difficulty );
|
||||
LuaStringToX( Difficulty );
|
||||
|
||||
|
||||
void DisplayBpms::Add( float f )
|
||||
{
|
||||
vfBpms.push_back( f );
|
||||
}
|
||||
|
||||
float DisplayBpms::GetMin()
|
||||
{
|
||||
float fMin = 99999;
|
||||
FOREACH_CONST( float, vfBpms, f )
|
||||
{
|
||||
if( *f != -1 )
|
||||
fMin = min( fMin, *f );
|
||||
}
|
||||
if( fMin == 99999 )
|
||||
return 0;
|
||||
else
|
||||
return fMin;
|
||||
}
|
||||
|
||||
float DisplayBpms::GetMax()
|
||||
{
|
||||
float fMax = 0;
|
||||
FOREACH_CONST( float, vfBpms, f )
|
||||
{
|
||||
if( *f != -1 )
|
||||
fMax = max( fMax, *f );
|
||||
}
|
||||
return fMax;
|
||||
}
|
||||
|
||||
bool DisplayBpms::BpmIsConstant()
|
||||
{
|
||||
return GetMin() == GetMax();
|
||||
}
|
||||
|
||||
bool DisplayBpms::IsMystery()
|
||||
{
|
||||
FOREACH_CONST( float, vfBpms, f )
|
||||
{
|
||||
if( *f == -1 )
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -363,4 +363,14 @@ CString PeakComboAwardToThemedString( PeakComboAward pma );
|
||||
PeakComboAward StringToPeakComboAward( const CString& pma );
|
||||
|
||||
|
||||
struct DisplayBpms
|
||||
{
|
||||
void Add( float f );
|
||||
float GetMin();
|
||||
float GetMax();
|
||||
bool BpmIsConstant();
|
||||
bool IsMystery();
|
||||
vector<float> vfBpms;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -66,7 +66,8 @@ ProfileHtml.cpp ProfileHtml.h RandomSample.cpp RandomSample.h ScoreKeeper.h Scor
|
||||
ScoreKeeperRave.cpp ScoreKeeperRave.h Song.cpp song.h SongCacheIndex.cpp SongCacheIndex.h \
|
||||
SongOptions.cpp SongOptions.h SongUtil.cpp SongUtil.h StageStats.cpp StageStats.h Steps.cpp Steps.h \
|
||||
StepsUtil.cpp StepsUtil.h Style.h StyleDef.cpp StyleDef.h \
|
||||
StyleInput.h TimeConstants.cpp TimeConstants.h TimingData.cpp TimingData.h TitleSubstitution.cpp TitleSubstitution.h
|
||||
StyleInput.h TimeConstants.cpp TimeConstants.h TimingData.cpp TimingData.h \
|
||||
Trail.cpp Trail.h TitleSubstitution.cpp TitleSubstitution.h
|
||||
|
||||
FileTypes = IniFile.cpp IniFile.h \
|
||||
MsdFile.cpp MsdFile.h \
|
||||
|
||||
@@ -157,10 +157,9 @@ void PaneDisplay::SetContent( PaneContents c )
|
||||
rv = GAMESTATE->m_pCurNotes[m_PlayerNumber]->GetRadarValues();
|
||||
else if( g_Contents[c].req&NEED_COURSE )
|
||||
{
|
||||
vector<Course::Info> ci;
|
||||
CourseDifficulty cd = GAMESTATE->m_PreferredCourseDifficulty[m_PlayerNumber];
|
||||
StepsType st = GAMESTATE->GetCurrentStyleDef()->m_StepsType;
|
||||
rv = GAMESTATE->m_pCurCourse->GetRadarValues( st, cd );
|
||||
rv = GAMESTATE->m_pCurCourse->GetTrail(st,cd)->GetRadarValues();
|
||||
}
|
||||
|
||||
const Song *pSong = GAMESTATE->m_pCurSong;
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "Course.h"
|
||||
#include "Steps.h"
|
||||
#include "ThemeManager.h"
|
||||
#include "Foreach.h"
|
||||
|
||||
#define ONE( arr ) { for( unsigned Z = 0; Z < ARRAYSIZE(arr); ++Z ) arr[Z]=1.0f; }
|
||||
|
||||
@@ -573,13 +574,11 @@ bool PlayerOptions::IsEasierForSongAndSteps( Song* pSong, Steps* pSteps )
|
||||
|
||||
bool PlayerOptions::IsEasierForCourse( Course* pCourse, StepsType st, CourseDifficulty cd )
|
||||
{
|
||||
vector<Course::Info> ci;
|
||||
pCourse->GetCourseInfo( st, ci, cd );
|
||||
Trail *pTrail = pCourse->GetTrail( st, cd );
|
||||
|
||||
for( unsigned i=0; i<ci.size(); i++ )
|
||||
FOREACH_CONST( TrailEntry, pTrail->m_vEntries, e )
|
||||
{
|
||||
const Course::Info& info = ci[i];
|
||||
if( info.pSong && IsEasierForSongAndSteps(info.pSong, info.pNotes) )
|
||||
if( e->pSong && IsEasierForSongAndSteps(e->pSong, e->pNotes) )
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -307,7 +307,7 @@ int Profile::GetPossibleCourseDancePointsForStepsType( StepsType st ) const
|
||||
if( !pCourse->HasCourseDifficulty(st,cd) )
|
||||
continue;
|
||||
|
||||
const RadarValues& fRadars = pCourse->GetRadarValues(st,cd);
|
||||
const RadarValues& fRadars = pCourse->GetTrail(st,cd)->GetRadarValues();
|
||||
iTotal += ScoreKeeperMAX2::GetPossibleDancePoints( fRadars );
|
||||
}
|
||||
}
|
||||
@@ -342,7 +342,7 @@ int Profile::GetActualCourseDancePointsForStepsType( StepsType st ) const
|
||||
FOREACH_ShownCourseDifficulty( cd )
|
||||
{
|
||||
const HighScoreList& hs = h.hs[st][cd];
|
||||
const RadarValues& fRadars = pCourse->GetRadarValues(st,cd);
|
||||
const RadarValues& fRadars = pCourse->GetTrail(st,cd)->GetRadarValues();
|
||||
int iPossibleDP = ScoreKeeperMAX2::GetPossibleDancePoints( fRadars );
|
||||
iTotal += (int)truncf( hs.GetTopScore().fPercentDP * iPossibleDP );
|
||||
}
|
||||
|
||||
@@ -894,7 +894,8 @@ bool PrintPercentCompleteForStepsType( RageFile &f, const Profile *pProfile, Ste
|
||||
* style is set. */
|
||||
if( GAMESTATE->m_CurStyle == STYLE_INVALID )
|
||||
GAMESTATE->m_CurStyle = STYLE_DANCE_SINGLE;
|
||||
TranslatedWrite(f, ssprintf("(%.2f)",pCourse->GetMeter(cd)) );
|
||||
float fMeter = pCourse->GetMeter(st,cd);
|
||||
TranslatedWrite(f, ssprintf("(%.2f)",fMeter) );
|
||||
HighScore hs = pProfile->GetCourseHighScoreList(pCourse, st, cd).GetTopScore();
|
||||
Grade grade = hs.grade;
|
||||
if( grade != GRADE_NO_DATA )
|
||||
@@ -1011,9 +1012,9 @@ bool PrintCatalogForSong( RageFile &f, const Profile *pProfile, Song* pSong )
|
||||
BEGIN_TABLE(2);
|
||||
TABLE_LINE2( "Artist", pSong->GetDisplayArtist() );
|
||||
TABLE_LINE2( "GroupName", pSong->m_sGroupName );
|
||||
float fMinBPM, fMaxBPM;
|
||||
pSong->GetDisplayBPM( fMinBPM, fMaxBPM );
|
||||
CString sBPM = (fMinBPM==fMaxBPM) ? ssprintf("%.1f",fMinBPM) : ssprintf("%.1f - %.1f",fMinBPM,fMaxBPM);
|
||||
DisplayBpms bpms;
|
||||
pSong->GetDisplayBpms( bpms );
|
||||
CString sBPM = (bpms.BpmIsConstant()) ? ssprintf("%.1f",bpms.GetMin()) : ssprintf("%.1f - %.1f",bpms.GetMin(),bpms.GetMax());
|
||||
TABLE_LINE2( "BPM", sBPM );
|
||||
TABLE_LINE2( "Credit", pSong->m_sCredit );
|
||||
TABLE_LINE2( "MusicLength", SecondsToMMSSMsMs(pSong->m_fMusicLengthSeconds) );
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
#include "StageStats.h"
|
||||
#include "PlayerAI.h" // for NUM_SKILL_LEVELS
|
||||
#include "NetworkSyncManager.h"
|
||||
#include "Foreach.h"
|
||||
|
||||
//
|
||||
// Defines
|
||||
@@ -182,37 +183,36 @@ void ScreenGameplay::Init()
|
||||
//
|
||||
if( GAMESTATE->IsCourseMode() )
|
||||
{
|
||||
Course* pCourse = GAMESTATE->m_pCurCourse;
|
||||
const StepsType st = GAMESTATE->GetCurrentStyleDef()->m_StepsType;
|
||||
|
||||
/* Increment the play count. */
|
||||
if( !m_bDemonstration )
|
||||
FOREACH_EnabledPlayer(p)
|
||||
PROFILEMAN->IncrementCoursePlayCount( GAMESTATE->m_pCurCourse, st, GAMESTATE->m_PreferredCourseDifficulty[p], (PlayerNumber)p );
|
||||
PROFILEMAN->IncrementCoursePlayCount( pCourse, st, GAMESTATE->m_PreferredCourseDifficulty[p], (PlayerNumber)p );
|
||||
|
||||
m_apSongsQueue.clear();
|
||||
PlayerNumber pnMaster = GAMESTATE->m_MasterPlayerNumber;
|
||||
Trail *pTrail = pCourse->GetTrail( st, GAMESTATE->m_PreferredCourseDifficulty[pnMaster] );
|
||||
FOREACH_CONST( TrailEntry, pTrail->m_vEntries, e )
|
||||
{
|
||||
m_apSongsQueue.push_back( e->pSong );
|
||||
}
|
||||
|
||||
FOREACH_PlayerNumber(p)
|
||||
{
|
||||
vector<Course::Info> ci;
|
||||
GAMESTATE->m_pCurCourse->GetCourseInfo( GAMESTATE->GetCurrentStyleDef()->m_StepsType, ci, GAMESTATE->m_PreferredCourseDifficulty[p] );
|
||||
Trail *pTrail = pCourse->GetTrail( st, GAMESTATE->m_PreferredCourseDifficulty[p] );
|
||||
|
||||
m_apNotesQueue[p].clear();
|
||||
m_asModifiersQueue[p].clear();
|
||||
for( unsigned c=0; c<ci.size(); ++c )
|
||||
FOREACH_CONST( TrailEntry, pTrail->m_vEntries, e )
|
||||
{
|
||||
m_apNotesQueue[p].push_back( ci[c].pNotes );
|
||||
m_apNotesQueue[p].push_back( e->pNotes );
|
||||
AttackArray a;
|
||||
ci[c].GetAttackArray( a );
|
||||
e->GetAttackArray( a );
|
||||
m_asModifiersQueue[p].push_back( a );
|
||||
|
||||
const CString path = THEME->GetPathToG( ssprintf("ScreenGameplay course song %i", c+1), true );
|
||||
if( path != "" )
|
||||
TEXTUREMAN->CacheTexture( path );
|
||||
}
|
||||
|
||||
if( p == 0 )
|
||||
{
|
||||
m_apSongsQueue.clear();
|
||||
for( unsigned c=0; c<ci.size(); ++c )
|
||||
m_apSongsQueue.push_back( ci[c].pSong );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -535,57 +535,26 @@ CString ScreenOptions::GetExplanationTitle( int iRow ) const
|
||||
{
|
||||
if( SHOW_BPM_IN_SPEED_TITLE )
|
||||
{
|
||||
DisplayBpms bpms;
|
||||
if( GAMESTATE->m_pCurSong )
|
||||
{
|
||||
float fMinBpm, fMaxBpm;
|
||||
GAMESTATE->m_pCurSong->GetDisplayBPM( fMinBpm, fMaxBpm );
|
||||
if( fMinBpm == fMaxBpm )
|
||||
sTitle += ssprintf( " (%.0f)", fMinBpm );
|
||||
else
|
||||
sTitle += ssprintf( " (%.0f-%.0f)", fMinBpm, fMaxBpm );
|
||||
Song* pSong = GAMESTATE->m_pCurSong;
|
||||
pSong->GetDisplayBpms( bpms );
|
||||
}
|
||||
else if( GAMESTATE->m_pCurCourse )
|
||||
{
|
||||
float fTotalMinBpm = -1, fTotalMaxBpm = -1; // -1 == no marker
|
||||
vector<Course::Info> ci;
|
||||
GAMESTATE->m_pCurCourse->GetCourseInfo( GAMESTATE->GetCurrentStyleDef()->m_StepsType, ci );
|
||||
|
||||
ASSERT( ci.size() );
|
||||
|
||||
for( unsigned i = 0; i < ci.size(); ++i )
|
||||
{
|
||||
if( ci[i].Mystery )
|
||||
continue;
|
||||
|
||||
Song *pSong = ci[i].pSong;
|
||||
ASSERT( pSong );
|
||||
switch( pSong->m_DisplayBPMType )
|
||||
{
|
||||
case Song::DISPLAY_ACTUAL:
|
||||
case Song::DISPLAY_SPECIFIED:
|
||||
{
|
||||
float fMinBpm, fMaxBpm;
|
||||
pSong->GetDisplayBPM( fMinBpm, fMaxBpm );
|
||||
if( fTotalMinBpm == -1 ) fTotalMinBpm = fMinBpm;
|
||||
else fTotalMinBpm = min( fTotalMinBpm, fMinBpm );
|
||||
if( fTotalMaxBpm == -1 ) fTotalMaxBpm = fMaxBpm;
|
||||
else fTotalMaxBpm = max( fTotalMaxBpm, fMaxBpm );
|
||||
}
|
||||
break;
|
||||
case Song::DISPLAY_RANDOM:
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
if( fTotalMinBpm == -1 || fTotalMaxBpm == -1 )
|
||||
sTitle += ssprintf( " (??" "?)" ); /* split so gcc doesn't think this is a trigraph */
|
||||
else if( fTotalMinBpm == fTotalMaxBpm )
|
||||
sTitle += ssprintf( " (%.0f)", fTotalMinBpm );
|
||||
else
|
||||
sTitle += ssprintf( " (%.0f-%.0f)", fTotalMinBpm, fTotalMaxBpm );
|
||||
Course *pCourse = GAMESTATE->m_pCurCourse;
|
||||
StepsType st = GAMESTATE->GetCurrentStyleDef()->m_StepsType;
|
||||
Trail* pTrail = pCourse->GetTrail(st,COURSE_DIFFICULTY_REGULAR);
|
||||
pTrail->GetDisplayBpms( bpms );
|
||||
}
|
||||
|
||||
if( bpms.IsMystery() )
|
||||
sTitle += ssprintf( " (??" "?)" ); /* split so gcc doesn't think this is a trigraph */
|
||||
else if( bpms.BpmIsConstant() )
|
||||
sTitle += ssprintf( " (%.0f)", bpms.GetMin() );
|
||||
else
|
||||
sTitle += ssprintf( " (%.0f-%.0f)", bpms.GetMin(), bpms.GetMax() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -385,11 +385,11 @@ void ScreenSelectCourse::AfterCourseChange()
|
||||
case TYPE_COURSE:
|
||||
{
|
||||
Course* pCourse = m_MusicWheel.GetSelectedCourse();
|
||||
const StepsType &st = GAMESTATE->GetCurrentStyleDef()->m_StepsType;
|
||||
StepsType st = GAMESTATE->GetCurrentStyleDef()->m_StepsType;
|
||||
|
||||
m_textNumSongs.SetText( ssprintf("%d", pCourse->GetEstimatedNumStages()) );
|
||||
float fTotalSeconds;
|
||||
if( pCourse->GetTotalSeconds(fTotalSeconds) )
|
||||
if( pCourse->GetTotalSeconds(st, fTotalSeconds) )
|
||||
m_textTime.SetText( SecondsToMMSSMsMs(fTotalSeconds) );
|
||||
else
|
||||
m_textTime.SetText( "xx:xx.xx" ); // The numbers format doesn't have a '?'. Is there a better solution?
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "LightsManager.h"
|
||||
#include "StageStats.h"
|
||||
#include "StepsUtil.h"
|
||||
#include "Foreach.h"
|
||||
|
||||
|
||||
const int NUM_SCORE_DIGITS = 9;
|
||||
@@ -1479,6 +1480,8 @@ void ScreenSelectMusic::AfterMusicChange()
|
||||
case TYPE_COURSE:
|
||||
{
|
||||
Course* pCourse = m_MusicWheel.GetSelectedCourse();
|
||||
StepsType st = GAMESTATE->GetCurrentStyleDef()->m_StepsType;
|
||||
Trail *pTrail = pCourse->GetTrail( st, COURSE_DIFFICULTY_REGULAR );
|
||||
|
||||
SampleMusicToPlay = THEME->GetPathS(m_sName,"course music");
|
||||
m_fSampleStartSeconds = 0;
|
||||
@@ -1486,7 +1489,7 @@ void ScreenSelectMusic::AfterMusicChange()
|
||||
|
||||
m_textNumSongs.SetText( ssprintf("%d", pCourse->GetEstimatedNumStages()) );
|
||||
float fTotalSeconds;
|
||||
if( pCourse->GetTotalSeconds(fTotalSeconds) )
|
||||
if( pCourse->GetTotalSeconds(st,fTotalSeconds) )
|
||||
m_textTotalTime.SetText( SecondsToMMSSMsMs(fTotalSeconds) );
|
||||
else
|
||||
m_textTotalTime.SetText( "xx:xx.xx" ); // The numbers format doesn't have a '?'. Is there a better solution?
|
||||
@@ -1498,18 +1501,15 @@ void ScreenSelectMusic::AfterMusicChange()
|
||||
m_CourseContentsFrame.TweenInAfterChangedCourse();
|
||||
m_DifficultyDisplay.UnsetDifficulties();
|
||||
|
||||
vector<Course::Info> ci;
|
||||
pCourse->GetCourseInfo( GAMESTATE->GetCurrentStyleDef()->m_StepsType, ci );
|
||||
|
||||
for( unsigned i = 0; i < ci.size(); ++i )
|
||||
FOREACH_CONST( TrailEntry, pTrail->m_vEntries, e )
|
||||
{
|
||||
if( ci[i].Mystery )
|
||||
if( e->bMystery )
|
||||
{
|
||||
m_Artists.push_back( "???" );
|
||||
m_AltArtists.push_back( "???" );
|
||||
} else {
|
||||
m_Artists.push_back( ci[i].pSong->GetDisplayArtist() );
|
||||
m_AltArtists.push_back( ci[i].pSong->GetTranslitArtist() );
|
||||
m_Artists.push_back( e->pSong->GetDisplayArtist() );
|
||||
m_AltArtists.push_back( e->pSong->GetTranslitArtist() );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1556,9 +1556,9 @@ void ScreenSelectMusic::AfterMusicChange()
|
||||
|
||||
m_Artist.SetTips( m_Artists, m_AltArtists );
|
||||
|
||||
for( int p=0; p<NUM_PLAYERS; p++ )
|
||||
FOREACH_PlayerNumber( p )
|
||||
{
|
||||
AfterNotesChange( (PlayerNumber)p );
|
||||
AfterNotesChange( p );
|
||||
}
|
||||
|
||||
/* Make sure we never start the sample when moving fast. */
|
||||
|
||||
@@ -132,16 +132,19 @@ void Song::AddLyricSegment( LyricSegment seg )
|
||||
m_LyricSegments.push_back( seg );
|
||||
}
|
||||
|
||||
void Song::GetDisplayBPM( float &fMinBPMOut, float &fMaxBPMOut ) const
|
||||
void Song::GetDisplayBpms( DisplayBpms &AddTo ) const
|
||||
{
|
||||
if( m_DisplayBPMType == DISPLAY_SPECIFIED )
|
||||
{
|
||||
fMinBPMOut = m_fSpecifiedBPMMin;
|
||||
fMaxBPMOut = m_fSpecifiedBPMMax;
|
||||
AddTo.Add( m_fSpecifiedBPMMin );
|
||||
AddTo.Add( m_fSpecifiedBPMMax );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Timing.GetActualBPM( fMinBPMOut, fMaxBPMOut );
|
||||
float fMinBPM, fMaxBPM;
|
||||
m_Timing.GetActualBPM( fMinBPM, fMaxBPM );
|
||||
AddTo.Add( fMinBPM );
|
||||
AddTo.Add( fMaxBPM );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -665,18 +665,17 @@ bool SongManager::GetExtraStageInfoFromCourse( bool bExtra2, CString sPreferredG
|
||||
course.LoadFromCRSFile( sCoursePath );
|
||||
if( course.GetEstimatedNumStages() <= 0 ) return false;
|
||||
|
||||
vector<Course::Info> ci;
|
||||
course.GetCourseInfo( GAMESTATE->GetCurrentStyleDef()->m_StepsType, ci );
|
||||
if( ci.empty() )
|
||||
Trail *pTrail = course.GetTrail( GAMESTATE->GetCurrentStyleDef()->m_StepsType, COURSE_DIFFICULTY_REGULAR );
|
||||
if( pTrail->m_vEntries.empty() )
|
||||
return false;
|
||||
|
||||
po_out.Init();
|
||||
po_out.FromString( ci[0].Modifiers );
|
||||
po_out.FromString( pTrail->m_vEntries[0].Modifiers );
|
||||
so_out.Init();
|
||||
so_out.FromString( ci[0].Modifiers );
|
||||
so_out.FromString( pTrail->m_vEntries[0].Modifiers );
|
||||
|
||||
pSongOut = ci[0].pSong;
|
||||
pNotesOut = ci[0].pNotes;
|
||||
pSongOut = pTrail->m_vEntries[0].pSong;
|
||||
pNotesOut = pTrail->m_vEntries[0].pNotes;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -949,13 +948,13 @@ void SongManager::UpdateRankingCourses()
|
||||
for(unsigned i=0; i < m_pCourses.size(); i++)
|
||||
{
|
||||
if (m_pCourses[i]->GetEstimatedNumStages() > 7)
|
||||
m_pCourses[i]->SortOrder_Ranking = 3;
|
||||
m_pCourses[i]->m_SortOrder_Ranking = 3;
|
||||
else
|
||||
m_pCourses[i]->SortOrder_Ranking = 2;
|
||||
m_pCourses[i]->m_SortOrder_Ranking = 2;
|
||||
|
||||
for(unsigned j = 0; j < RankingCourses.size(); j++)
|
||||
if (!RankingCourses[j].CompareNoCase(m_pCourses[i]->m_sPath))
|
||||
m_pCourses[i]->SortOrder_Ranking = 1;
|
||||
m_pCourses[i]->m_SortOrder_Ranking = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -118,13 +118,13 @@ void SongUtil::SortSongPointerArrayByDifficulty( vector<Song*> &arraySongPointer
|
||||
|
||||
bool CompareSongPointersByBPM(const Song *pSong1, const Song *pSong2)
|
||||
{
|
||||
float fMinBPM1, fMaxBPM1, fMinBPM2, fMaxBPM2;
|
||||
pSong1->GetDisplayBPM( fMinBPM1, fMaxBPM1 );
|
||||
pSong2->GetDisplayBPM( fMinBPM2, fMaxBPM2 );
|
||||
DisplayBpms bpms1, bpms2;
|
||||
pSong1->GetDisplayBpms( bpms1 );
|
||||
pSong2->GetDisplayBpms( bpms2 );
|
||||
|
||||
if( fMaxBPM1 < fMaxBPM2 )
|
||||
if( bpms1.GetMax() < bpms2.GetMax() )
|
||||
return true;
|
||||
if( fMaxBPM1 > fMaxBPM2 )
|
||||
if( bpms1.GetMax() > bpms2.GetMax() )
|
||||
return false;
|
||||
|
||||
return CompareCStringsAsc( pSong1->GetSongFilePath(), pSong2->GetSongFilePath() );
|
||||
@@ -267,9 +267,9 @@ CString SongUtil::GetSectionNameFromSongAndSort( const Song* pSong, SortOrder so
|
||||
case SORT_BPM:
|
||||
{
|
||||
const int iBPMGroupSize = 20;
|
||||
float fMinBPM, fMaxBPM;
|
||||
pSong->GetDisplayBPM( fMinBPM, fMaxBPM );
|
||||
int iMaxBPM = (int)fMaxBPM;
|
||||
DisplayBpms bpms;
|
||||
pSong->GetDisplayBpms( bpms );
|
||||
int iMaxBPM = (int)bpms.GetMax();
|
||||
iMaxBPM += iBPMGroupSize - (iMaxBPM%iBPMGroupSize) - 1;
|
||||
return ssprintf("%03d-%03d",iMaxBPM-(iBPMGroupSize-1), iMaxBPM);
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ IntDir=.\../Debug6
|
||||
TargetDir=\stepmania\stepmania\Program
|
||||
TargetName=StepMania-debug
|
||||
SOURCE="$(InputPath)"
|
||||
PreLink_Cmds=disasm\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\
|
||||
PreLink_Cmds=disasm\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\
|
||||
PostBuild_Cmds=disasm\mapconv $(IntDir)\$(TargetName).map $(TargetDir)\StepMania.vdi
|
||||
# End Special Build Tool
|
||||
|
||||
@@ -142,7 +142,7 @@ IntDir=.\../Release6
|
||||
TargetDir=\stepmania\stepmania\Program
|
||||
TargetName=StepMania
|
||||
SOURCE="$(InputPath)"
|
||||
PreLink_Cmds=disasm\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\
|
||||
PreLink_Cmds=disasm\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\
|
||||
PostBuild_Cmds=disasm\mapconv $(IntDir)\$(TargetName).map $(TargetDir)\StepMania.vdi
|
||||
# End Special Build Tool
|
||||
|
||||
@@ -1435,7 +1435,7 @@ SOURCE=.\FontCharmaps.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ForeachEnum.h
|
||||
SOURCE=.\Foreach.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
@@ -2213,6 +2213,25 @@ SOURCE=.\TitleSubstitution.cpp
|
||||
|
||||
SOURCE=.\TitleSubstitution.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Trail.cpp
|
||||
|
||||
!IF "$(CFG)" == "StepMania - Win32 Debug"
|
||||
|
||||
!ELSEIF "$(CFG)" == "StepMania - Xbox Debug"
|
||||
|
||||
!ELSEIF "$(CFG)" == "StepMania - Win32 Release"
|
||||
|
||||
!ELSEIF "$(CFG)" == "StepMania - Xbox Release"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Trail.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "File Types"
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@ cl /Zl /nologo /c verstub.cpp /Fo"$(IntDir)"\
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalOptions="/MACHINE:I386 "$(intdir)\verstub.obj""
|
||||
OutputFile="../Program/StepMania.exe"
|
||||
OutputFile="../../itg/itg/Program/StepMania.exe"
|
||||
LinkIncremental="1"
|
||||
SuppressStartupBanner="TRUE"
|
||||
AdditionalLibraryDirectories=""
|
||||
@@ -899,6 +899,12 @@ cl /Zl /nologo /c verstub.cpp /Fo"$(IntDir)"\
|
||||
<File
|
||||
RelativePath="TitleSubstitution.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="Trail.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="Trail.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="File Types"
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
#include "global.h"
|
||||
/*
|
||||
-----------------------------------------------------------------------------
|
||||
Class: Trail
|
||||
|
||||
Desc: See header.
|
||||
|
||||
Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved.
|
||||
Chris Danford
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "Trail.h"
|
||||
#include "Foreach.h"
|
||||
#include "Steps.h"
|
||||
#include "Song.h"
|
||||
|
||||
void TrailEntry::GetAttackArray( AttackArray &out ) const
|
||||
{
|
||||
if( !Modifiers.empty() )
|
||||
{
|
||||
Attack a;
|
||||
a.fStartSecond = 0;
|
||||
a.fSecsRemaining = 10000; /* whole song */
|
||||
a.level = ATTACK_LEVEL_1;
|
||||
a.sModifier = Modifiers;
|
||||
|
||||
out.push_back( a );
|
||||
}
|
||||
|
||||
out.insert( out.end(), Attacks.begin(), Attacks.end() );
|
||||
}
|
||||
|
||||
RadarValues Trail::GetRadarValues() const
|
||||
{
|
||||
RadarValues rv;
|
||||
|
||||
FOREACH_CONST( TrailEntry, m_vEntries, e )
|
||||
{
|
||||
const Steps *pNotes = e->pNotes;
|
||||
ASSERT( pNotes );
|
||||
rv += pNotes->GetRadarValues();
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
float Trail::GetAverageMeter() const
|
||||
{
|
||||
if( m_vEntries.empty() )
|
||||
return 0;
|
||||
|
||||
return GetTotalMeter() / (float)m_vEntries.size();
|
||||
}
|
||||
|
||||
int Trail::GetTotalMeter() const
|
||||
{
|
||||
int iTotalMeter = 0;
|
||||
FOREACH_CONST( TrailEntry, m_vEntries, e )
|
||||
{
|
||||
iTotalMeter += e->pNotes->GetMeter();
|
||||
}
|
||||
|
||||
return iTotalMeter;
|
||||
}
|
||||
|
||||
float Trail::GetLengthSeconds() const
|
||||
{
|
||||
float fSecs = 0;
|
||||
FOREACH_CONST( TrailEntry, m_vEntries, e )
|
||||
{
|
||||
fSecs += e->pSong->m_fMusicLengthSeconds;
|
||||
}
|
||||
return fSecs;
|
||||
}
|
||||
|
||||
void Trail::GetDisplayBpms( DisplayBpms &AddTo )
|
||||
{
|
||||
FOREACH_CONST( TrailEntry, m_vEntries, e )
|
||||
{
|
||||
if( e->bMystery )
|
||||
{
|
||||
AddTo.Add( -1 );
|
||||
continue;
|
||||
}
|
||||
|
||||
Song *pSong = e->pSong;
|
||||
ASSERT( pSong );
|
||||
switch( pSong->m_DisplayBPMType )
|
||||
{
|
||||
case Song::DISPLAY_ACTUAL:
|
||||
case Song::DISPLAY_SPECIFIED:
|
||||
{
|
||||
pSong->GetDisplayBpms( AddTo );
|
||||
}
|
||||
break;
|
||||
case Song::DISPLAY_RANDOM:
|
||||
AddTo.Add( -1 );
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
#ifndef Trail_H
|
||||
#define Trail_H
|
||||
|
||||
#include "Attack.h"
|
||||
|
||||
class Song;
|
||||
class Steps;
|
||||
|
||||
struct TrailEntry
|
||||
{
|
||||
TrailEntry():
|
||||
pSong(NULL),
|
||||
pNotes(NULL),
|
||||
bMystery(false),
|
||||
iLowMeter(-1),
|
||||
iHighMeter(-1)
|
||||
{
|
||||
}
|
||||
void GetAttackArray( AttackArray &out ) const;
|
||||
|
||||
Song* pSong;
|
||||
Steps* pNotes;
|
||||
CString Modifiers;
|
||||
AttackArray Attacks;
|
||||
bool bMystery;
|
||||
int iLowMeter;
|
||||
int iHighMeter;
|
||||
};
|
||||
|
||||
class Trail
|
||||
{
|
||||
public:
|
||||
StepsType m_st;
|
||||
CourseDifficulty m_cd;
|
||||
vector<TrailEntry> m_vEntries;
|
||||
|
||||
Trail()
|
||||
{
|
||||
m_st = STEPS_TYPE_INVALID;
|
||||
m_cd = COURSE_DIFFICULTY_INVALID;
|
||||
}
|
||||
|
||||
RadarValues GetRadarValues() const;
|
||||
float GetAverageMeter() const;
|
||||
int GetTotalMeter() const;
|
||||
float GetLengthSeconds() const;
|
||||
void GetDisplayBpms( DisplayBpms &AddTo );
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -168,7 +168,7 @@ public:
|
||||
void AddForegroundChange( BackgroundChange seg );
|
||||
void AddLyricSegment( LyricSegment seg );
|
||||
|
||||
void GetDisplayBPM( float &fMinBPMOut, float &fMaxBPMOut ) const;
|
||||
void GetDisplayBpms( DisplayBpms &AddTo ) const;
|
||||
CString GetBackgroundAtBeat( float fBeat ) const;
|
||||
|
||||
float GetBPMAtBeat( float fBeat ) const { return m_Timing.GetBPMAtBeat( fBeat ); }
|
||||
|
||||
Reference in New Issue
Block a user