2002-02-28 19:40:40 +00:00
# include "stdafx.h"
/*
-----------------------------------------------------------------------------
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"
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-01-22 05:29:27 +00:00
const CString CATEGORY_TOP_SCORE_FILE = " CategoryTopScores.dat " ;
const CString COURSE_TOP_SCORE_FILE = " CourseTopScores.dat " ;
2003-01-24 02:43:07 +00:00
const int CATEGORY_TOP_SCORE_VERSION = 1 ;
const int COURSE_TOP_SCORE_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))
2002-08-28 22:42:40 +00:00
# define EXTRA_COLOR THEME->GetMetricC("SongManager","ExtraColor")
2002-08-27 23:31:41 +00:00
2002-10-28 05:30:45 +00:00
RageColor g_GroupColors [ 30 ] ;
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
{
2002-09-03 22:31:06 +00:00
for ( int i = 0 ; i < NUM_GROUP_COLORS ; i + + )
g_GroupColors [ i ] = GROUP_COLOR ( i ) ;
2002-08-27 23:31:41 +00:00
g_ExtraColor = EXTRA_COLOR ;
2002-11-17 09:13:35 +00:00
InitSongArrayFromDisk ( ld ) ;
2003-01-22 05:29:27 +00:00
InitMachineScoresFromDisk ( ) ;
2002-06-14 22:25:22 +00:00
InitCoursesFromDisk ( ) ;
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-02-28 19:40:40 +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 ! = " " )
2002-11-17 09:13:35 +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 ;
2002-10-29 07:58:44 +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 "
" All song folders must reside in a group folder. For example, 'Songs \\ DDR 4th Mix \\ B4U'. \n "
" 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-01-22 05:29:27 +00:00
// Init category top scores
{
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 + + )
2002-02-28 19:40:40 +00:00
{
2003-01-24 02:43:07 +00:00
m_MachineScores [ i ] [ j ] [ k ] . fScore = 573000 ;
2003-01-22 05:29:27 +00:00
m_MachineScores [ i ] [ j ] [ k ] . sName = " STEP " ;
2002-02-28 19:40:40 +00:00
}
2003-01-22 05:29:27 +00:00
}
2002-02-28 19:40:40 +00:00
2003-01-22 05:29:27 +00:00
// Read category top scores
{
FILE * fp = fopen ( CATEGORY_TOP_SCORE_FILE , " r " ) ;
if ( fp )
2003-01-24 02:43:07 +00:00
{
int version ;
fscanf ( fp , " %d \n " , & version ) ;
if ( version = = CATEGORY_TOP_SCORE_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 & & ! 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
}
2002-02-28 19:40:40 +00:00
}
2003-01-21 05:14:59 +00:00
2003-01-22 05:29:27 +00:00
// Read course top scores
2003-01-21 05:14:59 +00:00
{
2003-01-22 05:29:27 +00:00
FILE * fp = fopen ( COURSE_TOP_SCORE_FILE , " r " ) ;
2003-01-21 05:14:59 +00:00
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 ) ;
if ( version = = COURSE_TOP_SCORE_VERSION )
{
while ( fp & & ! feof ( fp ) )
{
char szPath [ 256 ] ;
fscanf ( fp , " %s \n " , szPath ) ;
Course * pCourse = GetCourseFromPath ( szPath ) ;
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-01-26 07:33:03 +00:00
if ( fp & & ! feof ( fp ) )
{
int iDancePoints ;
float fSurviveTime ;
char szName [ 256 ] ;
fscanf ( fp , " %d %f %[^ \n ] \n " , & iDancePoints , & fSurviveTime , szName ) ;
if ( pCourse )
2003-01-24 02:43:07 +00:00
{
2003-01-26 07:33:03 +00:00
pCourse - > m_MachineScores [ i ] [ j ] . iDancePoints = iDancePoints ;
pCourse - > m_MachineScores [ i ] [ j ] . fSurviveTime = fSurviveTime ;
pCourse - > m_MachineScores [ i ] [ j ] . sName = szName ;
2003-01-24 02:43:07 +00:00
}
2003-01-26 07:33:03 +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
}
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-01-22 05:29:27 +00:00
// Write category top scores
2002-02-28 19:40:40 +00:00
{
2003-01-22 05:29:27 +00:00
FILE * fp = fopen ( CATEGORY_TOP_SCORE_FILE , " w " ) ;
if ( fp )
2003-01-24 02:43:07 +00:00
{
fprintf ( fp , " %d " , CATEGORY_TOP_SCORE_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
}
2003-01-22 05:29:27 +00:00
}
2002-02-28 19:40:40 +00:00
2003-01-22 05:29:27 +00:00
// Write course top scores
{
FILE * fp = fopen ( COURSE_TOP_SCORE_FILE , " w " ) ;
2002-02-28 19:40:40 +00:00
2003-01-22 05:29:27 +00:00
if ( fp )
{
2003-01-24 02:43:07 +00:00
fprintf ( fp , " %d " , COURSE_TOP_SCORE_VERSION ) ;
2003-01-22 05:29:27 +00:00
for ( unsigned i = 0 ; i < m_pCourses . size ( ) ; i + + ) // foreach course
{
Course * pCourse = m_pCourses [ i ] ;
fprintf ( fp , " %s \n " , pCourse - > m_sPath . c_str ( ) ) ;
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-01-26 07:33:03 +00:00
fprintf ( fp , " %d %f %s \n " ,
pCourse - > m_MachineScores [ i ] [ j ] . iDancePoints ,
pCourse - > m_MachineScores [ i ] [ j ] . fSurviveTime ,
pCourse - > m_MachineScores [ i ] [ j ] . sName . c_str ( ) ) ;
2003-01-22 05:29:27 +00:00
}
2002-02-28 19:40:40 +00:00
}
2003-01-22 05:29:27 +00:00
if ( fp )
fclose ( fp ) ;
}
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
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
2002-09-03 22:31:06 +00:00
return g_GroupColors [ i % NUM_GROUP_COLORS ] ;
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-01-03 05:56:28 +00:00
void SongManager : : GetSongsInGroup ( const CString sGroupName , vector < Song * > & AddTo )
2002-04-01 02:04:43 +00:00
{
2002-10-31 02:46:42 +00:00
for ( unsigned i = 0 ; i < m_pSongs . size ( ) ; i + + )
2002-04-01 02:04:43 +00:00
{
Song * pSong = m_pSongs [ i ] ;
2002-06-29 11:59:09 +00:00
if ( sGroupName = = m_pSongs [ i ] - > m_sGroupName )
2002-10-31 04:23:39 +00:00
AddTo . push_back ( pSong ) ;
2002-04-01 02:04:43 +00:00
}
}
2002-04-16 17:31:00 +00:00
CString SongManager : : ShortenGroupName ( const CString & sOrigGroupName )
{
CString sShortName = sOrigGroupName ;
sShortName . Replace ( " Dance Dance Revolution " , " DDR " ) ;
sShortName . Replace ( " dance dance revolution " , " DDR " ) ;
sShortName . Replace ( " DANCE DANCE REVOLUTION " , " DDR " ) ;
2002-09-29 23:29:01 +00:00
sShortName . Replace ( " Pump It Up " , " PIU " ) ;
sShortName . Replace ( " pump it up " , " PIU " ) ;
sShortName . Replace ( " PUMP IT UP " , " PIU " ) ;
2002-10-05 23:10:23 +00:00
sShortName . Replace ( " ParaParaParadise " , " PPP " ) ;
sShortName . Replace ( " paraparaparadise " , " PPP " ) ;
2003-01-23 19:44:13 +00:00
sShortName . Replace ( " PARAPARAPARADISE " , " PPP " ) ;
2002-10-05 23:10:23 +00:00
sShortName . Replace ( " Para Para Paradise " , " PPP " ) ;
sShortName . Replace ( " para para paradise " , " PPP " ) ;
2003-01-23 19:44:13 +00:00
sShortName . Replace ( " PARA PARA PARADISE " , " PPP " ) ;
2002-10-05 23:10:23 +00:00
sShortName . Replace ( " Dancing Stage " , " DS " ) ;
sShortName . Replace ( " Dancing Stage " , " DS " ) ;
sShortName . Replace ( " Dancing Stage " , " DS " ) ;
2002-04-16 17:31:00 +00:00
return sShortName ;
}
2002-06-14 22:25:22 +00:00
void SongManager : : InitCoursesFromDisk ( )
{
2002-07-02 17:34:20 +00:00
//
// Load courses from CRS files
//
CStringArray saCourseFiles ;
GetDirListing ( " Courses \\ *.crs " , saCourseFiles ) ;
2002-10-31 02:46:42 +00:00
for ( unsigned 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 ;
pCourse - > LoadFromCRSFile ( " Courses \\ " + saCourseFiles [ i ] , m_pSongs ) ;
if ( pCourse - > GetNumStages ( ) > 0 )
m_pCourses . push_back ( pCourse ) ;
else
delete pCourse ;
2002-07-02 17:34:20 +00:00
}
2002-07-31 04:06:34 +00:00
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 ;
2002-07-23 01:41:40 +00:00
GetSongsInGroup ( sGroupName , apGroupSongs ) ;
2002-06-14 22:25:22 +00:00
2002-09-29 05:06:18 +00:00
for ( Difficulty dc = DIFFICULTY_EASY ; dc < = DIFFICULTY_HARD ; dc = Difficulty ( dc + 1 ) ) // foreach Difficulty
2002-07-04 21:05:18 +00:00
{
2003-01-22 05:29:27 +00:00
Course * pCourse = new Course ;
pCourse - > CreateEndlessCourseFromGroupAndDifficulty ( sGroupName , dc , apGroupSongs ) ;
2002-07-04 21:05:18 +00:00
2003-01-22 05:29:27 +00:00
if ( pCourse - > GetNumStages ( ) > 0 )
m_pCourses . push_back ( pCourse ) ;
else
delete pCourse ;
2002-06-14 22:25:22 +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. */
void SongManager : : CleanCourses ( )
{
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-01-21 05:14:59 +00:00
}
2002-12-21 18:23:37 +00:00
2003-01-26 09:40:30 +00:00
void SongManager : : GetNonstopCourses ( vector < Course * > & AddTo )
2003-01-21 05:14:59 +00:00
{
PlayerOptions po ;
2003-01-22 05:29:27 +00:00
for ( unsigned i = 0 ; i < m_pCourses . size ( ) ; i + + )
2003-01-21 05:14:59 +00:00
{
2003-01-22 05:29:27 +00:00
if ( m_pCourses [ i ] - > m_bRepeat )
2003-01-21 05:14:59 +00:00
continue ; // skip
2003-01-22 05:29:27 +00:00
if ( m_pCourses [ i ] - > m_iLives > 0 ) // use battery life meter
2003-01-21 05:14:59 +00:00
continue ;
2003-01-22 05:29:27 +00:00
AddTo . push_back ( m_pCourses [ i ] ) ;
2003-01-21 05:14:59 +00:00
}
2002-12-21 18:23:37 +00:00
}
2003-01-26 09:40:30 +00:00
void SongManager : : GetOniCourses ( vector < Course * > & AddTo )
2003-01-21 05:14:59 +00:00
{
PlayerOptions po ;
2003-01-22 05:29:27 +00:00
for ( unsigned i = 0 ; i < m_pCourses . size ( ) ; i + + )
2003-01-21 05:14:59 +00:00
{
2003-01-22 05:29:27 +00:00
if ( m_pCourses [ i ] - > m_bRepeat )
2003-01-21 05:14:59 +00:00
continue ; // skip
2003-01-22 05:29:27 +00:00
if ( m_pCourses [ i ] - > m_iLives < = 0 ) // use bar life meter
2003-01-21 05:14:59 +00:00
continue ;
2003-01-22 05:29:27 +00:00
AddTo . push_back ( m_pCourses [ i ] ) ;
2003-01-21 05:14:59 +00:00
}
}
2003-01-26 09:40:30 +00:00
void SongManager : : GetEndlessCourses ( vector < Course * > & AddTo )
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-01-21 05:14:59 +00:00
{
2003-01-22 05:29:27 +00:00
if ( m_pCourses [ i ] - > m_bRepeat )
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 )
{
CString sCoursePath = " Songs \\ " + sPreferredGroup + " \\ " + ( bExtra2 ? " extra2 " : " extra1 " ) + " .crs " ;
if ( ! DoesFileExist ( sCoursePath ) ) return false ;
Course course ;
course . LoadFromCRSFile ( sCoursePath , m_pSongs ) ;
2002-12-17 05:29:50 +00:00
if ( course . GetNumStages ( ) < = 0 ) return false ;
2002-08-30 20:49:56 +00:00
2002-12-17 05:09:36 +00:00
pSongOut = course . GetSong ( 0 ) ;
2002-08-30 20:49:56 +00:00
pNotesOut = course . GetNotesForStage ( 0 ) ;
if ( pNotesOut = = NULL ) return false ;
2003-01-21 05:14:59 +00:00
course . GetPlayerOptions ( 0 , & po_out ) ;
course . GetSongOptions ( & so_out ) ;
2002-08-30 20:49:56 +00:00
return true ;
}
2002-08-01 13:42:56 +00:00
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 )
{
2002-08-30 20:49:56 +00:00
if ( GetExtraStageInfoFromCourse ( bExtra2 , sPreferredGroup ,
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 ;
2002-08-01 13:42:56 +00:00
SONGMAN - > GetSongsInGroup ( GAMESTATE - > m_sPreferredGroup , apSongs ) ;
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 ;
2002-10-14 00:28:27 +00:00
pSong - > GetNotesThatMatch ( sd - > m_NotesType , apNotes ) ;
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 ] ;
2002-10-24 08:17:09 +00:00
if ( pExtra1Notes = = NULL | | CompareNotesPointersByDifficulty ( 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
2002-10-24 08:17:09 +00:00
if ( pExtra2Notes = = NULL | | CompareNotesPointersByDifficulty ( 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 ( ) ;
po_out . m_bReverseScroll = true ;
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 ) ;
// should we do something fancy here, like turn on different effects?
2002-12-13 23:41:11 +00:00
int iSongHash = GetHashForString ( pSongOut - > GetSongDir ( ) ) ;
2003-01-27 05:11:59 +00:00
switch ( ( ( UINT ) iSongHash ) % 5 )
2002-08-01 13:42:56 +00:00
{
2002-09-30 02:19:02 +00:00
case 0 : po_out . m_bEffects [ PlayerOptions : : EFFECT_DIZZY ] = true ; break ;
case 1 : po_out . m_bDark = true ; break ;
case 2 : po_out . m_bEffects [ PlayerOptions : : EFFECT_DRUNK ] = true ; break ;
case 3 : po_out . m_bEffects [ PlayerOptions : : EFFECT_MINI ] = true ; break ;
case 4 : po_out . m_bEffects [ PlayerOptions : : EFFECT_SPACE ] = true ; break ;
2002-08-01 13:42:56 +00:00
default : ASSERT ( 0 ) ;
}
}
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
{
2002-12-02 05:25:44 +00:00
if ( sDir [ sDir . GetLength ( ) - 1 ] ! = ' \\ ' )
sDir + = ' \\ ' ;
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
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-01-27 02:00:38 +00:00
void SongManager : : AddMachineRecords ( NotesType nt , 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 ;
if ( ! GAMESTATE - > IsPlayerEnabled ( p ) )
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-01-27 02:00:38 +00:00
for ( int j = i + 1 ; j < NUM_RANKING_LINES ; 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 ;
machineScores [ i ] . sName = " STEP " ;
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
}
}
}
}