2003-02-16 04:01:45 +00:00
#include "global.h"
2002-02-28 19:40:40 +00:00
/*
-----------------------------------------------------------------------------
Class: SongManager
Desc: See header.
2002-05-19 01:59:48 +00:00
Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved.
2002-02-28 19:40:40 +00:00
Chris Danford
-----------------------------------------------------------------------------
*/
#include "SongManager.h"
#include "IniFile.h"
2002-05-01 19:14:55 +00:00
#include "RageLog.h"
2002-09-10 07:05:14 +00:00
#include "NotesLoaderDWI.h"
2002-06-14 22:25:22 +00:00
2002-07-23 01:41:40 +00:00
#include "GameState.h"
2002-05-29 09:47:24 +00:00
#include "PrefsManager.h"
2002-07-27 19:29:51 +00:00
#include "RageException.h"
#include "RageTimer.h"
2002-11-18 21:37:58 +00:00
#include "arch/LoadingWindow/LoadingWindow.h"
2002-02-28 19:40:40 +00:00
2002-11-11 04:53:31 +00:00
#include "AnnouncerManager.h"
#include "ThemeManager.h"
#include "GameManager.h"
2003-03-27 21:23:56 +00:00
#include <fstream>
2002-05-19 01:59:48 +00:00
SongManager * SONGMAN = NULL ; // global and accessable from anywhere in our program
2002-02-28 19:40:40 +00:00
2003-04-19 17:53:40 +00:00
const CString CATEGORY_RANKING_FILE = "data/CategoryRanking.dat" ;
const CString COURSE_RANKING_FILE = "data/CourseRanking.dat" ;
const CString NOTES_SCORES_FILE [ NUM_MEMORY_CARDS ] = { "data/Player1NotesScores.dat" , "data/Player2NotesScores.dat" , "data/MachineNotesScores.dat" };
const CString COURSE_SCORES_FILE [ NUM_MEMORY_CARDS ] = { "data/Player1CourseScores.dat" , "data/Player2CourseScores.dat" , "data/MachineCourseScores.dat" };
2003-02-14 21:42:44 +00:00
const int CATEGORY_RANKING_VERSION = 1 ;
const int COURSE_RANKING_VERSION = 1 ;
2003-03-27 21:23:56 +00:00
const int NOTES_SCORES_VERSION = 2 ;
2003-02-14 21:42:44 +00:00
const int COURSE_SCORES_VERSION = 1 ;
2003-01-22 05:29:27 +00:00
2002-02-28 19:40:40 +00:00
2002-09-03 06:33:08 +00:00
#define NUM_GROUP_COLORS THEME->GetMetricI("SongManager","NumGroupColors")
#define GROUP_COLOR( i ) THEME->GetMetricC("SongManager",ssprintf("GroupColor%d",i+1))
2003-02-16 10:12:03 +00:00
#define BEGINNER_COLOR THEME->GetMetricC("SongManager","BeginnerColor")
#define EASY_COLOR THEME->GetMetricC("SongManager","EasyColor")
#define MEDIUM_COLOR THEME->GetMetricC("SongManager","MediumColor")
#define HARD_COLOR THEME->GetMetricC("SongManager","HardColor")
#define CHALLENGE_COLOR THEME->GetMetricC("SongManager","ChallengeColor")
2002-08-28 22:42:40 +00:00
#define EXTRA_COLOR THEME->GetMetricC("SongManager","ExtraColor")
2002-08-27 23:31:41 +00:00
2003-02-03 05:53:59 +00:00
vector < RageColor > g_vGroupColors ;
2002-10-28 05:30:45 +00:00
RageColor g_ExtraColor ;
2002-04-16 17:31:00 +00:00
2002-02-28 19:40:40 +00:00
2002-11-17 09:13:35 +00:00
SongManager :: SongManager ( LoadingWindow * ld )
2002-02-28 19:40:40 +00:00
{
2003-02-05 19:16:00 +00:00
/* We initialize things that assume they can get at SONGMAN; we only
* init one of these, so hook us up to it immediately. */
SONGMAN = this ;
2003-02-16 05:10:08 +00:00
try
{
g_vGroupColors . clear ();
for ( int i = 0 ; i < NUM_GROUP_COLORS ; i ++ )
g_vGroupColors . push_back ( GROUP_COLOR ( i ) );
g_ExtraColor = EXTRA_COLOR ;
2003-02-05 19:16:00 +00:00
2003-02-16 05:10:08 +00:00
InitSongArrayFromDisk ( ld );
2003-03-27 01:56:21 +00:00
InitCoursesFromDisk ();
InitAutogenCourses ();
2003-02-16 05:10:08 +00:00
InitMachineScoresFromDisk ();
2002-08-27 23:31:41 +00:00
2003-02-16 05:10:08 +00:00
} catch (...) {
SONGMAN = NULL ;
throw ;
}
2002-02-28 19:40:40 +00:00
}
SongManager ::~ SongManager ()
{
2003-01-22 05:29:27 +00:00
SaveMachineScoresToDisk ();
2002-06-14 22:25:22 +00:00
FreeSongArray ();
2002-02-28 19:40:40 +00:00
}
2002-11-17 09:13:35 +00:00
void SongManager :: InitSongArrayFromDisk ( LoadingWindow * ld )
2002-05-29 09:47:24 +00:00
{
2002-11-17 09:13:35 +00:00
LoadStepManiaSongDir ( "Songs" , ld );
2002-06-27 17:49:10 +00:00
2002-10-31 02:46:42 +00:00
for ( unsigned i = 0 ; i < PREFSMAN -> m_asAdditionalSongFolders . size (); i ++ )
2002-11-17 09:13:35 +00:00
LoadStepManiaSongDir ( PREFSMAN -> m_asAdditionalSongFolders [ i ], ld );
2002-04-16 17:31:00 +00:00
2002-09-10 08:38:46 +00:00
if ( PREFSMAN -> m_DWIPath != "" )
2003-02-14 08:15:15 +00:00
LoadStepManiaSongDir ( PREFSMAN -> m_DWIPath + "/Songs" , ld );
2002-09-10 08:38:46 +00:00
2002-10-31 02:46:42 +00:00
LOG -> Trace ( "Found %d Songs." , m_pSongs . size () );
2002-03-06 08:25:09 +00:00
}
2002-09-10 07:05:14 +00:00
void SongManager :: SanityCheckGroupDir ( CString sDir ) const
{
// Check to see if they put a song directly inside the group folder.
CStringArray arrayFiles ;
2003-02-14 08:15:15 +00:00
GetDirListing ( sDir + "/*.mp3" , arrayFiles );
GetDirListing ( sDir + "/*.ogg" , arrayFiles );
GetDirListing ( sDir + "/*.wav" , arrayFiles );
2002-10-31 02:46:42 +00:00
if ( ! arrayFiles . empty () )
2002-12-21 19:34:02 +00:00
RageException :: Throw (
2002-10-29 07:58:44 +00:00
"The folder '%s' contains music files. \n\n "
"This means that you have a music outside of a song folder. \n "
2003-02-14 08:15:15 +00:00
"All song folders must reside in a group folder. For example, 'Songs/DDR 4th Mix/B4U'. \n "
2002-10-29 07:58:44 +00:00
"See the StepMania readme for more info." ,
sDir . GetString ()
2002-09-10 07:05:14 +00:00
);
}
2002-09-10 07:11:29 +00:00
void SongManager :: AddGroup ( CString sDir , CString sGroupDirName )
{
2002-10-31 02:46:42 +00:00
unsigned j ;
for ( j = 0 ; j < m_arrayGroupNames . size (); ++ j )
2002-09-10 07:11:29 +00:00
if ( sGroupDirName == m_arrayGroupNames [ j ] ) break ;
2002-10-31 02:46:42 +00:00
if ( j != m_arrayGroupNames . size () )
2002-09-10 07:11:29 +00:00
return ; /* the group is already added */
// Look for a group banner in this group folder
CStringArray arrayGroupBanners ;
2003-01-23 04:43:22 +00:00
GetDirListing ( sDir + sGroupDirName + "/*.png" , arrayGroupBanners );
GetDirListing ( sDir + sGroupDirName + "/*.jpg" , arrayGroupBanners );
GetDirListing ( sDir + sGroupDirName + "/*.gif" , arrayGroupBanners );
GetDirListing ( sDir + sGroupDirName + "/*.bmp" , arrayGroupBanners );
2002-09-10 07:11:29 +00:00
CString sBannerPath ;
2002-10-31 02:46:42 +00:00
if ( ! arrayGroupBanners . empty () )
2002-09-10 07:11:29 +00:00
{
2003-01-23 04:43:22 +00:00
sBannerPath = sDir + sGroupDirName + "/" + arrayGroupBanners [ 0 ] ;
2002-10-29 07:58:44 +00:00
LOG -> Trace ( "Group banner for '%s' is '%s'." , sGroupDirName . GetString (), sBannerPath . GetString () );
2002-09-10 07:11:29 +00:00
}
2002-10-31 04:23:39 +00:00
m_arrayGroupNames . push_back ( sGroupDirName );
m_GroupBannerPaths . push_back ( sBannerPath );
2002-09-10 07:11:29 +00:00
}
2002-11-17 09:13:35 +00:00
void SongManager :: LoadStepManiaSongDir ( CString sDir , LoadingWindow * ld )
2002-03-06 08:25:09 +00:00
{
2003-01-23 04:43:22 +00:00
/* Make sure sDir has a trailing slash. */
2002-10-31 08:05:13 +00:00
TrimRight ( sDir , "/ \\ " );
2003-01-23 04:43:22 +00:00
sDir += "/" ;
2002-03-06 08:25:09 +00:00
// Find all group directories in "Songs" folder
CStringArray arrayGroupDirs ;
2003-01-23 04:43:22 +00:00
GetDirListing ( sDir + "*" , arrayGroupDirs , true );
2002-03-06 08:25:09 +00:00
SortCStringArray ( arrayGroupDirs );
2002-10-31 02:46:42 +00:00
for ( unsigned i = 0 ; i < arrayGroupDirs . size (); i ++ ) // for each dir in /Songs/
2002-03-06 08:25:09 +00:00
{
CString sGroupDirName = arrayGroupDirs [ i ];
if ( 0 == stricmp ( sGroupDirName , "cvs" ) ) // the directory called "CVS"
continue ; // ignore it
2003-01-23 04:43:22 +00:00
SanityCheckGroupDir ( sDir + sGroupDirName );
2002-09-10 07:05:14 +00:00
2002-03-06 08:25:09 +00:00
// Find all Song folders in this group directory
CStringArray arraySongDirs ;
2003-01-23 04:43:22 +00:00
GetDirListing ( sDir + sGroupDirName + "/*" , arraySongDirs , true , true );
2002-03-06 08:25:09 +00:00
SortCStringArray ( arraySongDirs );
2002-10-31 02:46:42 +00:00
unsigned j ;
2002-09-09 02:23:47 +00:00
int loaded = 0 ;
2002-10-31 02:46:42 +00:00
for ( j = 0 ; j < arraySongDirs . size (); j ++ ) // for each song dir
2002-03-06 08:25:09 +00:00
{
CString sSongDirName = arraySongDirs [ j ];
2003-01-23 04:43:22 +00:00
if ( 0 == stricmp ( Basename ( sSongDirName ), "cvs" ) ) // the directory called "CVS"
2002-03-06 08:25:09 +00:00
continue ; // ignore it
// this is a song directory. Load a new song!
2002-11-17 09:13:35 +00:00
if ( ld ) {
2003-01-23 04:43:22 +00:00
ld -> SetText ( ssprintf ( "Loading songs... \n %s \n %s" ,
Basename ( sGroupDirName ). GetString (),
Basename ( sSongDirName ). GetString ()));
2002-11-17 09:13:35 +00:00
ld -> Paint ();
}
2002-03-06 08:25:09 +00:00
Song * pNewSong = new Song ;
2003-01-23 04:43:22 +00:00
if ( ! pNewSong -> LoadFromSongDir ( sSongDirName ) ) {
2002-09-10 22:55:12 +00:00
/* The song failed to load. */
delete pNewSong ;
continue ;
}
2002-10-31 04:23:39 +00:00
m_pSongs . push_back ( pNewSong );
2002-09-09 02:23:47 +00:00
loaded ++ ;
}
/* Don't add the group name if we didn't load any songs in this group. */
if ( ! loaded ) continue ;
/* Add this group to the group array. */
2002-09-10 07:11:29 +00:00
AddGroup ( sDir , sGroupDirName );
2002-03-06 08:25:09 +00:00
}
2002-11-17 09:13:35 +00:00
if ( ld ) {
ld -> Paint ();
ld -> SetText ( "Done loading songs." );
}
2002-03-06 08:25:09 +00:00
}
2002-06-14 22:25:22 +00:00
void SongManager :: FreeSongArray ()
2002-02-28 19:40:40 +00:00
{
2002-10-31 02:46:42 +00:00
for ( unsigned i = 0 ; i < m_pSongs . size (); i ++ )
2002-02-28 19:40:40 +00:00
SAFE_DELETE ( m_pSongs [ i ] );
2002-10-24 20:15:24 +00:00
m_pSongs . clear ();
2002-06-14 22:25:22 +00:00
2002-10-24 20:15:24 +00:00
m_GroupBannerPaths . clear ();
2002-02-28 19:40:40 +00:00
}
void SongManager :: ReloadSongArray ()
{
2002-07-23 01:41:40 +00:00
InitSongArrayFromDisk ( NULL );
2002-06-14 22:25:22 +00:00
FreeSongArray ();
2002-02-28 19:40:40 +00:00
}
2003-01-22 05:29:27 +00:00
void SongManager :: InitMachineScoresFromDisk ()
2002-02-28 19:40:40 +00:00
{
2003-02-14 21:42:44 +00:00
// Init category ranking
2003-01-21 05:14:59 +00:00
{
2003-01-26 07:33:03 +00:00
for ( int i = 0 ; i < NUM_NOTES_TYPES ; i ++ )
for ( int j = 0 ; j < NUM_RANKING_CATEGORIES ; j ++ )
2003-01-27 02:00:38 +00:00
for ( int k = 0 ; k < NUM_RANKING_LINES ; k ++ )
2003-01-22 05:29:27 +00:00
{
2003-01-24 02:43:07 +00:00
m_MachineScores [ i ][ j ][ k ]. fScore = 573000 ;
2003-02-14 21:42:44 +00:00
m_MachineScores [ i ][ j ][ k ]. sName = DEFAULT_RANKING_NAME ;
2003-01-22 05:29:27 +00:00
}
2003-01-21 05:14:59 +00:00
}
2003-02-14 21:42:44 +00:00
// category ranking
2003-01-22 05:29:27 +00:00
{
2003-02-14 21:42:44 +00:00
FILE * fp = fopen ( CATEGORY_RANKING_FILE , "r" );
2003-01-22 05:29:27 +00:00
if ( fp )
2003-01-24 02:43:07 +00:00
{
int version ;
fscanf ( fp , "%d \n " , & version );
2003-02-14 21:42:44 +00:00
if ( version == CATEGORY_RANKING_VERSION )
2003-01-24 02:43:07 +00:00
{
2003-01-26 07:33:03 +00:00
for ( int i = 0 ; i < NUM_NOTES_TYPES ; i ++ )
for ( int j = 0 ; j < NUM_RANKING_CATEGORIES ; j ++ )
2003-01-27 02:00:38 +00:00
for ( int k = 0 ; k < NUM_RANKING_LINES ; k ++ )
2003-01-24 02:43:07 +00:00
if ( fp && ! feof ( fp ) )
{
char szName [ 256 ];
fscanf ( fp , "%f %[^ \n ] \n " , & m_MachineScores [ i ][ j ][ k ]. fScore , szName );
m_MachineScores [ i ][ j ][ k ]. sName = szName ;
}
}
2003-01-22 05:29:27 +00:00
fclose ( fp );
2003-01-24 02:43:07 +00:00
}
2003-01-22 05:29:27 +00:00
}
2003-02-14 21:42:44 +00:00
// course ranking
2003-01-22 05:29:27 +00:00
{
2003-02-14 21:42:44 +00:00
FILE * fp = fopen ( COURSE_RANKING_FILE , "r" );
2003-01-22 05:29:27 +00:00
if ( fp )
2003-01-24 02:43:07 +00:00
{
int version ;
2003-02-17 20:43:23 +00:00
fscanf ( fp , "%i \n " , & version );
2003-02-14 21:42:44 +00:00
if ( version == COURSE_RANKING_VERSION )
2003-01-24 02:43:07 +00:00
{
while ( fp && ! feof ( fp ) )
{
2003-02-14 21:42:44 +00:00
char szPath [ 256 ];
fscanf ( fp , "%s \n " , szPath );
Course * pCourse = GetCourseFromPath ( szPath );
if ( pCourse == NULL )
pCourse = GetCourseFromName ( szPath );
2003-01-26 07:33:03 +00:00
for ( int i = 0 ; i < NUM_NOTES_TYPES ; i ++ )
2003-02-14 21:42:44 +00:00
for ( int j = 0 ; j < NUM_RANKING_LINES ; j ++ )
if ( fp && ! feof ( fp ) )
{
int iDancePoints ;
float fSurviveTime ;
char szName [ 256 ];
fscanf ( fp , "%d %f %[^ \n ] \n " , & iDancePoints , & fSurviveTime , szName );
if ( pCourse )
2003-01-26 07:33:03 +00:00
{
2003-02-14 21:42:44 +00:00
pCourse -> m_RankingScores [ i ][ j ]. iDancePoints = iDancePoints ;
pCourse -> m_RankingScores [ i ][ j ]. fSurviveTime = fSurviveTime ;
pCourse -> m_RankingScores [ i ][ j ]. sName = szName ;
2003-01-26 07:33:03 +00:00
}
2003-02-14 21:42:44 +00:00
}
2003-01-24 02:43:07 +00:00
}
}
2003-01-22 05:29:27 +00:00
fclose ( fp );
2003-01-24 02:43:07 +00:00
}
2003-01-22 05:29:27 +00:00
}
2003-02-14 21:42:44 +00:00
// notes scores
for ( int c = 0 ; c < NUM_MEMORY_CARDS ; c ++ )
{
2003-03-27 21:23:56 +00:00
ifstream f ( NOTES_SCORES_FILE [ c ]);
if ( f . good () )
2003-02-14 21:42:44 +00:00
{
2003-03-27 21:23:56 +00:00
CString line ;
getline ( f , line );
2003-02-14 21:42:44 +00:00
int version ;
2003-03-27 21:23:56 +00:00
sscanf ( line . GetString (), "%i" , & version );
2003-03-11 19:07:41 +00:00
if ( version == NOTES_SCORES_VERSION )
2003-02-14 21:42:44 +00:00
{
2003-03-27 21:23:56 +00:00
while ( f && ! f . eof () )
2003-02-14 21:42:44 +00:00
{
2003-03-27 21:23:56 +00:00
CString sSongDir ;
getline ( f , sSongDir );
getline ( f , line );
2003-02-14 21:42:44 +00:00
unsigned uNumNotes ;
2003-03-27 21:23:56 +00:00
sscanf ( line . GetString (), "%u" , & uNumNotes );
Song * pSong = this -> GetSongFromDir ( sSongDir );
2003-02-14 21:42:44 +00:00
for ( unsigned i = 0 ; i < uNumNotes ; i ++ )
{
NotesType nt ;
Difficulty dc ;
2003-03-27 21:23:56 +00:00
getline ( f , line );
sscanf ( line . GetString (), "%d %d" , & nt , & dc );
CString sDescription ;
getline ( f , sDescription );
2003-02-16 10:12:03 +00:00
Notes * pNotes = NULL ;
if ( pSong )
2003-03-27 21:23:56 +00:00
{
2003-02-16 10:12:03 +00:00
if ( dc == DIFFICULTY_INVALID )
2003-03-27 21:23:56 +00:00
pNotes = pSong -> GetNotes ( nt , sDescription );
2003-02-16 10:12:03 +00:00
else
pNotes = pSong -> GetNotes ( nt , dc );
2003-03-27 21:23:56 +00:00
}
getline ( f , line );
2003-02-14 21:42:44 +00:00
if ( pNotes )
{
2003-03-28 00:34:59 +00:00
sscanf ( line . GetString (), "%d %d %f \n " ,
& pNotes -> m_MemCardScores [ c ]. iNumTimesPlayed ,
& pNotes -> m_MemCardScores [ c ]. grade ,
& pNotes -> m_MemCardScores [ c ]. fScore );
2003-02-14 21:42:44 +00:00
}
}
}
}
}
}
// course scores
{
for ( int c = 0 ; c < NUM_MEMORY_CARDS ; c ++ )
{
FILE * fp = fopen ( COURSE_SCORES_FILE [ c ], "r" );
if ( fp )
{
int version ;
fscanf ( fp , "%d \n " , & version );
if ( version == COURSE_SCORES_VERSION )
{
while ( fp && ! feof ( fp ) )
{
char szPath [ 256 ];
fscanf ( fp , "%[^ \n ] \n " , szPath );
Course * pCourse = GetCourseFromPath ( szPath );
if ( pCourse == NULL )
pCourse = GetCourseFromName ( szPath );
for ( int i = 0 ; i < NUM_NOTES_TYPES ; i ++ )
if ( fp && ! feof ( fp ) )
{
int iNumTimesPlayed ;
int iDancePoints ;
float fSurviveTime ;
fscanf ( fp , "%d %d %f \n " , & iNumTimesPlayed , & iDancePoints , & fSurviveTime );
if ( pCourse )
{
pCourse -> m_MemCardScores [ c ][ i ]. iNumTimesPlayed = iNumTimesPlayed ;
pCourse -> m_MemCardScores [ c ][ i ]. iDancePoints = iDancePoints ;
pCourse -> m_MemCardScores [ c ][ i ]. fSurviveTime = fSurviveTime ;
}
}
}
}
fclose ( fp );
}
}
}
2002-02-28 19:40:40 +00:00
}
2003-01-22 05:29:27 +00:00
void SongManager :: SaveMachineScoresToDisk ()
2002-02-28 19:40:40 +00:00
{
2003-02-14 21:42:44 +00:00
// category ranking
2003-02-22 21:59:21 +00:00
LOG -> Trace ( "Writing category ranking" );
2002-02-28 19:40:40 +00:00
{
2003-02-14 21:42:44 +00:00
FILE * fp = fopen ( CATEGORY_RANKING_FILE , "w" );
2003-01-22 05:29:27 +00:00
if ( fp )
2003-01-24 02:43:07 +00:00
{
2003-02-14 21:42:44 +00:00
fprintf ( fp , "%d \n " , CATEGORY_RANKING_VERSION );
2003-01-26 07:33:03 +00:00
for ( int i = 0 ; i < NUM_NOTES_TYPES ; i ++ )
for ( int j = 0 ; j < NUM_RANKING_CATEGORIES ; j ++ )
2003-01-27 02:00:38 +00:00
for ( int k = 0 ; k < NUM_RANKING_LINES ; k ++ )
2003-01-24 02:43:07 +00:00
if ( fp )
fprintf ( fp , "%f %s \n " , m_MachineScores [ i ][ j ][ k ]. fScore , m_MachineScores [ i ][ j ][ k ]. sName . c_str ());
2003-01-22 05:29:27 +00:00
fclose ( fp );
2003-01-24 02:43:07 +00:00
}
2002-02-28 19:40:40 +00:00
}
2003-02-14 21:42:44 +00:00
// course ranking
2003-02-22 21:59:21 +00:00
LOG -> Trace ( "Writing course ranking" );
2003-01-22 05:29:27 +00:00
{
2003-02-14 21:42:44 +00:00
FILE * fp = fopen ( COURSE_RANKING_FILE , "w" );
2003-01-22 05:29:27 +00:00
if ( fp )
{
2003-02-14 21:42:44 +00:00
fprintf ( fp , "%d \n " , COURSE_RANKING_VERSION );
for ( unsigned c = 0 ; c < m_pCourses . size (); c ++ ) // foreach course
2003-01-22 05:29:27 +00:00
{
2003-02-14 21:42:44 +00:00
Course * pCourse = m_pCourses [ c ];
2003-02-22 21:59:21 +00:00
ASSERT ( pCourse );
2003-02-23 06:25:43 +00:00
2003-03-27 01:56:21 +00:00
if ( pCourse -> m_bIsAutogen )
2003-02-23 06:56:02 +00:00
fprintf ( fp , "%s \n " , pCourse -> m_sName . c_str ());
2003-02-14 21:42:44 +00:00
else
2003-02-23 06:56:02 +00:00
fprintf ( fp , "%s \n " , pCourse -> m_sPath . c_str ());
2003-01-22 05:29:27 +00:00
2003-01-26 07:33:03 +00:00
for ( int i = 0 ; i < NUM_NOTES_TYPES ; i ++ )
2003-01-27 02:00:38 +00:00
for ( int j = 0 ; j < NUM_RANKING_LINES ; j ++ )
2003-02-22 21:59:21 +00:00
{
2003-01-26 07:33:03 +00:00
fprintf ( fp , "%d %f %s \n " ,
2003-02-14 21:42:44 +00:00
pCourse -> m_RankingScores [ i ][ j ]. iDancePoints ,
pCourse -> m_RankingScores [ i ][ j ]. fSurviveTime ,
pCourse -> m_RankingScores [ i ][ j ]. sName . c_str ());
2003-02-22 21:59:21 +00:00
}
2003-02-14 21:42:44 +00:00
}
fclose ( fp );
}
}
// notes scores
2003-02-22 21:59:21 +00:00
LOG -> Trace ( "Writing note scores" );
2003-02-14 21:42:44 +00:00
for ( int c = 0 ; c < NUM_MEMORY_CARDS ; c ++ )
{
FILE * fp = fopen ( NOTES_SCORES_FILE [ c ], "w" );
if ( fp )
{
fprintf ( fp , "%d \n " , NOTES_SCORES_VERSION );
for ( unsigned s = 0 ; s < m_pSongs . size (); s ++ ) // foreach song
{
Song * pSong = m_pSongs [ s ];
2003-02-22 21:59:21 +00:00
ASSERT ( pSong );
2003-02-23 06:25:43 +00:00
2003-02-14 21:42:44 +00:00
vector < Notes *> vNotes = pSong -> m_apNotes ;
2003-03-06 23:06:21 +00:00
/* This prevents the play count from being saved for songs that havn't
* been passed. Though, it seems we only increment this when it's
* passed, anyway ...
2003-02-14 21:42:44 +00:00
for( int n=(int)vNotes.size()-1; n>=0; n-- )
2003-02-22 21:59:21 +00:00
{
2003-02-14 21:42:44 +00:00
if( vNotes[n]->m_MemCardScores[c].grade <= GRADE_E )
vNotes.erase( vNotes.begin()+n );
2003-02-22 21:59:21 +00:00
}
2003-03-06 23:06:21 +00:00
*/
2003-02-14 21:42:44 +00:00
if ( vNotes . size () == 0 )
continue ; // skip
fprintf ( fp , "%s \n %u \n " ,
pSong -> GetSongDir (). c_str (),
vNotes . size () );
for ( unsigned i = 0 ; i < vNotes . size (); i ++ )
{
Notes * pNotes = vNotes [ i ];
2003-02-22 21:59:21 +00:00
ASSERT ( pNotes );
2003-02-23 06:25:43 +00:00
2003-03-27 21:23:56 +00:00
fprintf ( fp , "%d %d \n %s \n " ,
2003-02-14 21:42:44 +00:00
pNotes -> m_NotesType ,
pNotes -> GetDifficulty (),
pNotes -> GetDescription (). c_str () );
2003-02-23 06:25:43 +00:00
2003-02-14 21:42:44 +00:00
fprintf ( fp , "%d %d %f \n " ,
pNotes -> m_MemCardScores [ c ]. iNumTimesPlayed ,
pNotes -> m_MemCardScores [ c ]. grade ,
pNotes -> m_MemCardScores [ c ]. fScore );
}
}
fclose ( fp );
}
}
// course scores
2003-02-22 21:59:21 +00:00
LOG -> Trace ( "Writing course scores" );
2003-02-14 21:42:44 +00:00
{
for ( int c = 0 ; c < NUM_MEMORY_CARDS ; c ++ )
{
FILE * fp = fopen ( COURSE_SCORES_FILE [ c ], "w" );
if ( fp )
{
fprintf ( fp , "%d \n " , COURSE_SCORES_VERSION );
2003-02-24 00:47:13 +00:00
for ( unsigned i = 0 ; i < m_pCourses . size (); i ++ ) // foreach song
2003-02-14 21:42:44 +00:00
{
2003-02-24 00:47:13 +00:00
Course * pCourse = m_pCourses [ i ];
2003-02-22 21:59:21 +00:00
ASSERT ( pCourse );
2003-02-23 06:25:43 +00:00
2003-03-27 01:56:21 +00:00
if ( pCourse -> m_bIsAutogen )
2003-02-14 21:42:44 +00:00
fprintf ( fp , "%s \n " , pCourse -> m_sName . c_str ());
2003-02-23 06:25:43 +00:00
else
2003-02-14 21:42:44 +00:00
fprintf ( fp , "%s \n " , pCourse -> m_sPath . c_str ());
2003-02-24 00:47:13 +00:00
for ( int nt = 0 ; nt < NUM_NOTES_TYPES ; nt ++ )
2003-02-14 21:42:44 +00:00
fprintf ( fp , "%d %d %f \n " ,
2003-02-24 00:47:13 +00:00
pCourse -> m_MemCardScores [ c ][ nt ]. iNumTimesPlayed ,
pCourse -> m_MemCardScores [ c ][ nt ]. iDancePoints ,
pCourse -> m_MemCardScores [ c ][ nt ]. fSurviveTime );
2003-02-14 21:42:44 +00:00
}
fclose ( fp );
2003-01-22 05:29:27 +00:00
}
}
}
2002-03-06 08:25:09 +00:00
}
2002-03-19 07:09:49 +00:00
CString SongManager :: GetGroupBannerPath ( CString sGroupName )
2002-03-06 08:25:09 +00:00
{
2002-10-31 02:46:42 +00:00
unsigned i ;
for ( i = 0 ; i < m_arrayGroupNames . size (); ++ i )
2002-09-07 07:24:44 +00:00
if ( sGroupName == m_arrayGroupNames [ i ] ) break ;
2002-03-06 08:25:09 +00:00
2002-10-31 02:46:42 +00:00
if ( i == m_arrayGroupNames . size () )
2002-03-06 08:25:09 +00:00
return "" ;
2002-09-07 07:24:44 +00:00
return m_GroupBannerPaths [ i ];
2002-03-06 08:25:09 +00:00
}
2002-04-01 02:04:43 +00:00
void SongManager :: GetGroupNames ( CStringArray & AddTo )
{
2002-10-24 19:55:09 +00:00
AddTo . insert ( AddTo . end (), m_arrayGroupNames . begin (), m_arrayGroupNames . end () );
2002-04-16 17:31:00 +00:00
}
2002-04-01 02:04:43 +00:00
2003-02-16 23:54:30 +00:00
bool SongManager :: DoesGroupExist ( CString sGroupName )
{
return find ( m_arrayGroupNames . begin (), m_arrayGroupNames . end (), sGroupName ) != m_arrayGroupNames . end ();
}
2002-10-28 05:30:45 +00:00
RageColor SongManager :: GetGroupColor ( const CString & sGroupName )
2002-04-16 17:31:00 +00:00
{
// search for the group index
2002-10-31 02:46:42 +00:00
unsigned i ;
for ( i = 0 ; i < m_arrayGroupNames . size (); i ++ )
2002-04-01 02:04:43 +00:00
{
2002-04-16 17:31:00 +00:00
if ( m_arrayGroupNames [ i ] == sGroupName )
break ;
2002-04-01 02:04:43 +00:00
}
2002-10-31 02:46:42 +00:00
ASSERT ( i != m_arrayGroupNames . size () ); // this is not a valid group
2002-04-16 17:31:00 +00:00
2003-02-03 05:53:59 +00:00
return g_vGroupColors [ i % g_vGroupColors . size ()];
2002-04-01 02:04:43 +00:00
}
2002-12-17 05:22:32 +00:00
RageColor SongManager :: GetSongColor ( const Song * pSong )
2002-08-27 23:31:41 +00:00
{
ASSERT ( pSong );
2002-10-31 02:46:42 +00:00
for ( unsigned i = 0 ; i < pSong -> m_apNotes . size (); i ++ )
2002-08-27 23:31:41 +00:00
{
2002-12-17 05:22:32 +00:00
const Notes * pNotes = pSong -> m_apNotes [ i ];
2003-01-23 21:51:35 +00:00
if ( pNotes -> GetMeter () >= 10 )
2002-08-27 23:31:41 +00:00
return EXTRA_COLOR ;
}
return GetGroupColor ( pSong -> m_sGroupName );
}
2003-02-16 10:12:03 +00:00
RageColor SongManager :: GetDifficultyColor ( Difficulty dc )
{
switch ( dc )
{
case DIFFICULTY_BEGINNER : return BEGINNER_COLOR ;
case DIFFICULTY_EASY : return EASY_COLOR ;
case DIFFICULTY_MEDIUM : return MEDIUM_COLOR ;
case DIFFICULTY_HARD : return HARD_COLOR ;
case DIFFICULTY_CHALLENGE : return CHALLENGE_COLOR ;
default : ASSERT ( 0 ); return CHALLENGE_COLOR ;
}
}
2003-02-10 05:30:12 +00:00
void SongManager :: GetSongs ( vector < Song *> & AddTo , CString sGroupName , int iMaxStages ) const
2002-04-01 02:04:43 +00:00
{
2003-02-03 05:53:59 +00:00
AddTo . clear ();
2002-10-31 02:46:42 +00:00
for ( unsigned i = 0 ; i < m_pSongs . size (); i ++ )
2003-02-10 05:30:12 +00:00
if ( sGroupName == "" || sGroupName == m_pSongs [ i ] -> m_sGroupName )
if ( GetNumStagesForSong ( m_pSongs [ i ]) <= iMaxStages )
AddTo . push_back ( m_pSongs [ i ] );
2002-04-01 02:04:43 +00:00
}
2002-04-16 17:31:00 +00:00
2003-02-05 18:34:27 +00:00
int SongManager :: GetNumSongs () const
2003-02-03 05:53:59 +00:00
{
return m_pSongs . size ();
}
2003-02-05 18:34:27 +00:00
int SongManager :: GetNumGroups () const
2003-02-03 05:53:59 +00:00
{
return m_arrayGroupNames . size ();
}
2003-02-14 21:42:44 +00:00
int SongManager :: GetNumCourses () const
{
return m_pCourses . size ();
}
2003-02-10 05:30:12 +00:00
CString SongManager :: ShortenGroupName ( CString sLongGroupName )
2002-04-16 17:31:00 +00:00
{
2003-02-10 05:30:12 +00:00
sLongGroupName . Replace ( "Dance Dance Revolution" , "DDR" );
sLongGroupName . Replace ( "dance dance revolution" , "DDR" );
sLongGroupName . Replace ( "DANCE DANCE REVOLUTION" , "DDR" );
sLongGroupName . Replace ( "Pump It Up" , "PIU" );
sLongGroupName . Replace ( "pump it up" , "PIU" );
sLongGroupName . Replace ( "PUMP IT UP" , "PIU" );
sLongGroupName . Replace ( "ParaParaParadise" , "PPP" );
sLongGroupName . Replace ( "paraparaparadise" , "PPP" );
sLongGroupName . Replace ( "PARAPARAPARADISE" , "PPP" );
sLongGroupName . Replace ( "Para Para Paradise" , "PPP" );
sLongGroupName . Replace ( "para para paradise" , "PPP" );
sLongGroupName . Replace ( "PARA PARA PARADISE" , "PPP" );
sLongGroupName . Replace ( "Dancing Stage" , "DS" );
sLongGroupName . Replace ( "Dancing Stage" , "DS" );
sLongGroupName . Replace ( "Dancing Stage" , "DS" );
return sLongGroupName ;
}
int SongManager :: GetNumStagesForSong ( const Song * pSong )
{
ASSERT ( pSong );
if ( pSong -> m_fMusicLengthSeconds > PREFSMAN -> m_fMarathonVerSongSeconds )
return 3 ;
if ( pSong -> m_fMusicLengthSeconds > PREFSMAN -> m_fLongVerSongSeconds )
return 2 ;
else
return 1 ;
2002-04-16 17:31:00 +00:00
}
2002-06-14 22:25:22 +00:00
void SongManager :: InitCoursesFromDisk ()
{
2003-04-11 00:29:44 +00:00
unsigned i ;
2002-07-02 17:34:20 +00:00
//
2003-04-11 00:29:44 +00:00
// Load courses from in Courses dir
2002-07-02 17:34:20 +00:00
//
CStringArray saCourseFiles ;
2003-02-05 18:34:27 +00:00
GetDirListing ( "Courses/*.crs" , saCourseFiles , false , true );
2003-04-11 00:29:44 +00:00
for ( i = 0 ; i < saCourseFiles . size (); i ++ )
2002-07-02 17:34:20 +00:00
{
2003-01-22 05:29:27 +00:00
Course * pCourse = new Course ;
2003-02-05 19:16:00 +00:00
pCourse -> LoadFromCRSFile ( saCourseFiles [ i ] );
2003-02-14 21:42:44 +00:00
m_pCourses . push_back ( pCourse );
2002-07-02 17:34:20 +00:00
}
2003-04-11 00:29:44 +00:00
// Find all group directories in Courses dir
CStringArray arrayGroupDirs ;
GetDirListing ( "Courses/*" , arrayGroupDirs , true );
SortCStringArray ( arrayGroupDirs );
for ( i = 0 ; i < arrayGroupDirs . size (); i ++ ) // for each dir in /Courses/
{
CString sGroupDirName = arrayGroupDirs [ i ];
if ( 0 == stricmp ( sGroupDirName , "cvs" ) ) // the directory called "CVS"
continue ; // ignore it
// Find all CRS files in this group directory
CStringArray arrayCoursePaths ;
GetDirListing ( "Courses/" + sGroupDirName + "/*.crs" , arrayCoursePaths , false , true );
SortCStringArray ( arrayCoursePaths );
for ( unsigned j = 0 ; j < arrayCoursePaths . size (); j ++ )
{
Course * pCourse = new Course ;
pCourse -> LoadFromCRSFile ( arrayCoursePaths [ j ] );
m_pCourses . push_back ( pCourse );
}
}
2003-03-27 01:56:21 +00:00
}
2002-07-31 04:06:34 +00:00
2003-03-27 01:56:21 +00:00
void SongManager :: InitAutogenCourses ()
{
2002-07-02 17:34:20 +00:00
//
2003-01-21 05:14:59 +00:00
// Create group courses for Endless and Nonstop
2002-07-02 17:34:20 +00:00
//
2002-06-14 22:25:22 +00:00
CStringArray saGroupNames ;
this -> GetGroupNames ( saGroupNames );
2002-10-31 02:46:42 +00:00
unsigned g ;
for ( g = 0 ; g < saGroupNames . size (); g ++ ) // foreach Group
2002-06-14 22:25:22 +00:00
{
CString sGroupName = saGroupNames [ g ];
2003-01-03 05:56:28 +00:00
vector < Song *> apGroupSongs ;
2003-02-10 05:30:12 +00:00
GetSongs ( apGroupSongs , sGroupName );
2002-06-14 22:25:22 +00:00
2003-03-27 01:56:21 +00:00
Course * pCourse ;
2002-07-04 21:05:18 +00:00
2003-03-27 01:56:21 +00:00
pCourse = new Course ;
pCourse -> AutogenEndlessFromGroup ( sGroupName , apGroupSongs );
m_pCourses . push_back ( pCourse );
pCourse = new Course ;
pCourse -> AutogenNonstopFromGroup ( sGroupName , apGroupSongs );
m_pCourses . push_back ( pCourse );
2002-06-14 22:25:22 +00:00
}
}
2003-03-27 01:56:21 +00:00
2003-01-22 05:29:27 +00:00
void SongManager :: FreeCourses ()
2002-06-14 22:25:22 +00:00
{
2003-01-22 05:29:27 +00:00
for ( unsigned i = 0 ; i < m_pCourses . size (); i ++ )
delete m_pCourses [ i ];
m_pCourses . clear ();
2002-06-14 22:25:22 +00:00
}
2002-08-01 13:42:56 +00:00
2002-12-21 18:23:37 +00:00
/* Called periodically to wipe out cached NoteData. This is called when we change
* screens. */
2003-01-27 23:10:44 +00:00
void SongManager :: CleanData ()
2002-12-21 18:23:37 +00:00
{
for ( unsigned i = 0 ; i < m_pSongs . size (); i ++ )
{
for ( unsigned n = 0 ; n < m_pSongs [ i ] -> m_apNotes . size (); n ++ )
{
m_pSongs [ i ] -> m_apNotes [ n ] -> Compress ();
}
}
}
2003-03-27 01:56:21 +00:00
void SongManager :: GetNonstopCourses ( vector < Course *> & AddTo , bool bIncludeAutogen )
2003-01-21 05:14:59 +00:00
{
2003-01-22 05:29:27 +00:00
for ( unsigned i = 0 ; i < m_pCourses . size (); i ++ )
2003-02-16 10:12:03 +00:00
if ( ! m_pCourses [ i ] -> m_bRepeat && m_pCourses [ i ] -> m_iLives <= 0 ) // use bar life meter
2003-03-27 01:56:21 +00:00
if ( bIncludeAutogen || ! m_pCourses [ i ] -> m_bIsAutogen )
AddTo . push_back ( m_pCourses [ i ] );
2003-01-21 05:14:59 +00:00
}
2003-03-27 01:56:21 +00:00
void SongManager :: GetOniCourses ( vector < Course *> & AddTo , bool bIncludeAutogen )
2003-01-21 05:14:59 +00:00
{
2003-01-22 05:29:27 +00:00
for ( unsigned i = 0 ; i < m_pCourses . size (); i ++ )
2003-02-16 10:12:03 +00:00
if ( ! m_pCourses [ i ] -> m_bRepeat && m_pCourses [ i ] -> m_iLives > 0 ) // use battery life meter
2003-03-27 01:56:21 +00:00
if ( bIncludeAutogen || ! m_pCourses [ i ] -> m_bIsAutogen )
AddTo . push_back ( m_pCourses [ i ] );
2003-01-21 05:14:59 +00:00
}
2003-03-27 01:56:21 +00:00
void SongManager :: GetEndlessCourses ( vector < Course *> & AddTo , bool bIncludeAutogen )
2003-01-21 05:14:59 +00:00
{
2003-01-22 05:29:27 +00:00
for ( unsigned i = 0 ; i < m_pCourses . size (); i ++ )
if ( m_pCourses [ i ] -> m_bRepeat )
2003-03-27 01:56:21 +00:00
if ( bIncludeAutogen || ! m_pCourses [ i ] -> m_bIsAutogen )
AddTo . push_back ( m_pCourses [ i ] );
2003-01-21 05:14:59 +00:00
}
2002-08-30 20:49:56 +00:00
bool SongManager :: GetExtraStageInfoFromCourse ( bool bExtra2 , CString sPreferredGroup ,
Song *& pSongOut , Notes *& pNotesOut , PlayerOptions & po_out , SongOptions & so_out )
{
2003-02-28 08:42:02 +00:00
const CString sCourseSuffix = sPreferredGroup + "/" + ( bExtra2 ? "extra2" : "extra1" ) + ".crs" ;
CString sCoursePath = "Songs/" + sCourseSuffix ;
2003-02-05 03:24:47 +00:00
if ( ! DoesFileExist ( sCoursePath ) )
{
/* try alternative song folders */
for ( unsigned i = 0 ; i < PREFSMAN -> m_asAdditionalSongFolders . size (); i ++ )
{
2003-02-28 08:42:02 +00:00
sCoursePath = PREFSMAN -> m_asAdditionalSongFolders [ i ] + "/" + sCourseSuffix ;
2003-02-05 03:24:47 +00:00
if ( DoesFileExist ( sCoursePath ) )
break ;
}
2003-02-28 08:42:02 +00:00
}
2003-02-05 03:24:47 +00:00
2003-02-28 08:42:02 +00:00
if ( ! DoesFileExist ( sCoursePath ) && PREFSMAN -> m_DWIPath . size () )
sCoursePath = PREFSMAN -> m_DWIPath + "/Songs/" + sCourseSuffix ;
2003-02-05 03:24:47 +00:00
2003-02-28 08:42:02 +00:00
/* Couldn't find course in DWI path or alternative song folders */
if ( ! DoesFileExist ( sCoursePath ) )
return false ;
2002-08-30 20:49:56 +00:00
Course course ;
2003-02-05 19:16:00 +00:00
course . LoadFromCRSFile ( sCoursePath );
2003-02-14 21:42:44 +00:00
if ( course . GetEstimatedNumStages () <= 0 ) return false ;
2002-08-30 20:49:56 +00:00
2003-02-14 21:42:44 +00:00
CString sModifiers ;
if ( course . GetFirstStageInfo ( pSongOut , pNotesOut , sModifiers , GAMESTATE -> GetCurrentStyleDef () -> m_NotesType ) )
{
2003-02-22 21:59:21 +00:00
po_out . Init ();
2003-02-14 21:42:44 +00:00
po_out . FromString ( sModifiers );
2003-02-22 21:59:21 +00:00
so_out . Init ();
2003-02-14 21:42:44 +00:00
so_out . FromString ( sModifiers );
return true ;
}
else
return false ;
2002-08-30 20:49:56 +00:00
}
2002-08-01 13:42:56 +00:00
2003-02-05 00:33:14 +00:00
/* Return true if n1 < n2. */
bool CompareNotesPointersForExtra ( const Notes * n1 , const Notes * n2 )
{
/* Equate CHALLENGE to HARD. */
Difficulty d1 = min ( n1 -> GetDifficulty (), DIFFICULTY_HARD );
Difficulty d2 = min ( n2 -> GetDifficulty (), DIFFICULTY_HARD );
if ( d1 < d2 ) return true ;
if ( d1 > d2 ) return false ;
/* n1 difficulty == n2 difficulty */
if ( CompareNotesPointersByMeter ( n1 , n2 )) return true ;
if ( CompareNotesPointersByMeter ( n2 , n1 )) return false ;
/* n1 meter == n2 meter */
return CompareNotesPointersByRadarValues ( n1 , n2 );
}
2002-09-06 08:56:28 +00:00
void SongManager :: GetExtraStageInfo ( bool bExtra2 , CString sPreferredGroup , const StyleDef * sd ,
2002-08-01 13:42:56 +00:00
Song *& pSongOut , Notes *& pNotesOut , PlayerOptions & po_out , SongOptions & so_out )
{
2003-04-19 22:24:01 +00:00
CString Group = GAMESTATE -> m_sPreferredGroup ;
if ( Group == GROUP_ALL_MUSIC )
{
ASSERT ( GAMESTATE -> m_pCurSong );
Group = GAMESTATE -> m_pCurSong -> m_sGroupName ;
}
ASSERT ( Group != "" );
if ( GetExtraStageInfoFromCourse ( bExtra2 , Group , pSongOut , pNotesOut , po_out , so_out ))
2002-08-01 13:42:56 +00:00
return ;
// Choose a hard song for the extra stage
Song * pExtra1Song = NULL ; // the absolute hardest Song and Notes. Use this for extra stage 1.
Notes * pExtra1Notes = NULL ;
Song * pExtra2Song = NULL ; // a medium-hard Song and Notes. Use this for extra stage 2.
Notes * pExtra2Notes = NULL ;
2003-01-03 05:56:28 +00:00
vector < Song *> apSongs ;
2003-02-25 00:33:42 +00:00
CString sGroup = GAMESTATE -> m_sPreferredGroup == GROUP_ALL_MUSIC ? GAMESTATE -> m_pCurSong -> m_sGroupName : GAMESTATE -> m_sPreferredGroup ;
2003-02-10 05:30:12 +00:00
SONGMAN -> GetSongs ( apSongs , sGroup );
2002-10-31 02:46:42 +00:00
for ( unsigned s = 0 ; s < apSongs . size (); s ++ ) // foreach song
2002-08-01 13:42:56 +00:00
{
Song * pSong = apSongs [ s ];
2003-01-03 05:56:28 +00:00
vector < Notes *> apNotes ;
2003-02-10 05:30:12 +00:00
pSong -> GetNotes ( apNotes , sd -> m_NotesType );
2002-10-31 02:46:42 +00:00
for ( unsigned n = 0 ; n < apNotes . size (); n ++ ) // foreach Notes
2002-08-01 13:42:56 +00:00
{
Notes * pNotes = apNotes [ n ];
2003-02-05 00:33:14 +00:00
if ( pExtra1Notes == NULL || CompareNotesPointersForExtra ( pExtra1Notes , pNotes ) ) // pNotes is harder than pHardestNotes
2002-08-01 13:42:56 +00:00
{
pExtra1Song = pSong ;
pExtra1Notes = pNotes ;
}
// for extra 2, we don't want to choose the hardest notes possible. So, we'll disgard Notes with meter > 8
2003-01-02 22:10:51 +00:00
if ( bExtra2 && pNotes -> GetMeter () > 8 )
2002-08-01 13:42:56 +00:00
continue ; // skip
2003-02-05 00:33:14 +00:00
if ( pExtra2Notes == NULL || CompareNotesPointersForExtra ( pExtra2Notes , pNotes ) ) // pNotes is harder than pHardestNotes
2002-08-01 13:42:56 +00:00
{
pExtra2Song = pSong ;
pExtra2Notes = pNotes ;
}
}
}
if ( pExtra2Song == NULL && pExtra1Song != NULL )
{
pExtra2Song = pExtra1Song ;
pExtra2Notes = pExtra1Notes ;
}
// If there are any notes at all that match this NotesType, everything should be filled out.
// Also, it's guaranteed that there is at least one Notes that matches the NotesType because the player
// had to play something before reaching the extra stage!
ASSERT ( pExtra2Song && pExtra1Song && pExtra2Notes && pExtra1Notes );
pSongOut = ( bExtra2 ? pExtra2Song : pExtra1Song );
pNotesOut = ( bExtra2 ? pExtra2Notes : pExtra1Notes );
po_out . Init ();
so_out . Init ();
2003-02-26 23:26:57 +00:00
po_out . m_fReverseScroll = 1 ;
2003-01-25 11:05:12 +00:00
po_out . m_fScrollSpeed = 1.5f ;
2002-08-01 13:42:56 +00:00
so_out . m_DrainType = ( bExtra2 ? SongOptions :: DRAIN_SUDDEN_DEATH : SongOptions :: DRAIN_NO_RECOVER );
2003-04-01 19:31:27 +00:00
po_out . m_fDark = 1 ;
2002-08-01 13:42:56 +00:00
}
2002-08-20 20:38:40 +00:00
2003-01-10 02:22:07 +00:00
Song * SongManager :: GetRandomSong ()
2002-08-20 20:38:40 +00:00
{
2003-01-10 02:22:07 +00:00
if ( m_pSongs . empty () )
return NULL ;
2002-08-20 20:38:40 +00:00
2003-01-10 02:22:07 +00:00
return SONGMAN -> m_pSongs [ rand () % m_pSongs . size () ];
2002-08-20 20:38:40 +00:00
}
2002-11-08 08:17:59 +00:00
2002-12-02 05:25:44 +00:00
Song * SongManager :: GetSongFromDir ( CString sDir )
2002-11-08 08:17:59 +00:00
{
2003-02-14 08:15:15 +00:00
if ( sDir [ sDir . GetLength () - 1 ] != '/' )
sDir += '/' ;
2002-12-02 05:25:44 +00:00
2002-11-08 08:17:59 +00:00
for ( unsigned int i = 0 ; i < m_pSongs . size (); i ++ )
2002-12-02 05:25:44 +00:00
if ( sDir . CompareNoCase ( m_pSongs [ i ] -> GetSongDir ()) == 0 )
2002-11-08 08:17:59 +00:00
return m_pSongs [ i ];
return NULL ;
}
2003-01-21 05:14:59 +00:00
Course * SongManager :: GetCourseFromPath ( CString sPath )
{
2003-01-22 05:29:27 +00:00
for ( unsigned int i = 0 ; i < m_pCourses . size (); i ++ )
if ( sPath . CompareNoCase ( m_pCourses [ i ] -> m_sPath ) == 0 )
return m_pCourses [ i ];
2003-01-21 05:14:59 +00:00
return NULL ;
}
2003-01-22 05:29:27 +00:00
2003-02-14 21:42:44 +00:00
Course * SongManager :: GetCourseFromName ( CString sName )
{
for ( unsigned int i = 0 ; i < m_pCourses . size (); i ++ )
if ( sName . CompareNoCase ( m_pCourses [ i ] -> m_sName ) == 0 )
return m_pCourses [ i ];
return NULL ;
}
2003-01-22 05:29:27 +00:00
bool SongManager :: IsUsingMemoryCard ( PlayerNumber pn )
{
return true ;
}
2003-01-24 02:43:07 +00:00
2003-01-27 02:00:38 +00:00
struct CategoryScoreToInsert
2003-01-24 02:43:07 +00:00
{
PlayerNumber pn ;
2003-01-27 02:00:38 +00:00
RankingCategory cat ;
float fScore ;
2003-01-24 02:43:07 +00:00
2003-01-27 02:00:38 +00:00
static int CompareDescending ( const CategoryScoreToInsert & hs1 , const CategoryScoreToInsert & hs2 )
2003-01-24 02:43:07 +00:00
{
if ( hs1 . fScore > hs2 . fScore ) return - 1 ;
else if ( hs1 . fScore == hs2 . fScore ) return 0 ;
else return + 1 ;
}
2003-01-27 02:00:38 +00:00
static void SortDescending ( vector < CategoryScoreToInsert >& vHSout )
2003-01-24 02:43:07 +00:00
{
sort ( vHSout . begin (), vHSout . end (), CompareDescending );
}
};
2003-02-16 10:12:03 +00:00
void SongManager :: AddScores ( NotesType nt , bool bPlayerEnabled [ NUM_PLAYERS ], RankingCategory hsc [ NUM_PLAYERS ], float fScore [ NUM_PLAYERS ], int iNewRecordIndexOut [ NUM_PLAYERS ] ) // set iNewRecordIndex = -1 if not a new record
2003-01-24 02:43:07 +00:00
{
2003-01-27 02:00:38 +00:00
vector < CategoryScoreToInsert > vHS ;
2003-01-24 02:43:07 +00:00
for ( int p = 0 ; p < NUM_PLAYERS ; p ++ )
{
iNewRecordIndexOut [ p ] = - 1 ;
2003-02-16 10:12:03 +00:00
if ( ! bPlayerEnabled [ p ] )
2003-01-24 02:43:07 +00:00
continue ; // skip
2003-01-27 02:00:38 +00:00
CategoryScoreToInsert hs ;
2003-01-24 02:43:07 +00:00
hs . pn = ( PlayerNumber ) p ;
2003-01-27 02:00:38 +00:00
hs . cat = hsc [ p ];
hs . fScore = fScore [ p ];
2003-01-24 02:43:07 +00:00
vHS . push_back ( hs );
}
// Sort descending before inserting.
// This guarantees that a high score will not switch poitions on us when we later insert scores for the other player
2003-01-27 02:00:38 +00:00
CategoryScoreToInsert :: SortDescending ( vHS );
2003-01-24 02:43:07 +00:00
for ( unsigned i = 0 ; i < vHS . size (); i ++ )
{
2003-01-27 02:00:38 +00:00
CategoryScoreToInsert & newHS = vHS [ i ];
MachineScore * machineScores = m_MachineScores [ nt ][ newHS . cat ];
for ( int i = 0 ; i < NUM_RANKING_LINES ; i ++ )
2003-01-24 02:43:07 +00:00
{
if ( newHS . fScore > machineScores [ i ]. fScore )
{
// We found the insert point. Shift down.
2003-02-03 05:53:59 +00:00
for ( int j = NUM_RANKING_LINES - 1 ; j > i ; j -- )
2003-01-24 02:43:07 +00:00
machineScores [ j ] = machineScores [ j - 1 ];
// insert
2003-01-27 02:00:38 +00:00
machineScores [ i ]. fScore = newHS . fScore ;
2003-02-14 21:42:44 +00:00
machineScores [ i ]. sName = DEFAULT_RANKING_NAME ;
2003-01-24 02:43:07 +00:00
iNewRecordIndexOut [ newHS . pn ] = i ;
2003-01-27 02:00:38 +00:00
break ;
2003-01-24 02:43:07 +00:00
}
}
}
}
2003-02-03 05:53:59 +00:00