Files
itgmania212121/stepmania/src/SongManager.cpp
T

645 lines
18 KiB
C++
Raw Normal View History

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"
#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"
#include "arch/LoadingWindow/LoadingWindow.h"
2002-02-28 19:40:40 +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
const CString g_sStatisticsFileName = "statistics.ini";
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")
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
{
for( int i=0; i<NUM_GROUP_COLORS; i++ )
g_GroupColors[i] = GROUP_COLOR( i );
g_ExtraColor = EXTRA_COLOR;
2002-11-17 09:13:35 +00:00
InitSongArrayFromDisk( ld );
2002-02-28 19:40:40 +00:00
ReadStatisticsFromDisk();
2002-06-14 22:25:22 +00:00
InitCoursesFromDisk();
2002-02-28 19:40:40 +00:00
}
SongManager::~SongManager()
{
SaveStatisticsToDisk();
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
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
LOG->Trace( "Found %d Songs.", m_pSongs.size() );
2002-03-06 08:25:09 +00:00
}
void SongManager::SanityCheckGroupDir( CString sDir ) const
{
// Check to see if they put a song directly inside the group folder.
CStringArray arrayFiles;
GetDirListing( sDir + "\\*.mp3", arrayFiles );
GetDirListing( sDir + "\\*.ogg", arrayFiles );
GetDirListing( sDir + "\\*.wav", arrayFiles );
if( !arrayFiles.empty() )
2002-12-21 19:34:02 +00:00
RageException::Throw(
"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:11:29 +00:00
void SongManager::AddGroup( CString sDir, CString sGroupDirName )
{
unsigned j;
for(j = 0; j < m_arrayGroupNames.size(); ++j)
2002-09-10 07:11:29 +00:00
if( sGroupDirName == m_arrayGroupNames[j] ) break;
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;
GetDirListing( ssprintf("%s\\%s\\*.png", sDir.GetString(), sGroupDirName.GetString()), arrayGroupBanners );
GetDirListing( ssprintf("%s\\%s\\*.jpg", sDir.GetString(), sGroupDirName.GetString()), arrayGroupBanners );
GetDirListing( ssprintf("%s\\%s\\*.gif", sDir.GetString(), sGroupDirName.GetString()), arrayGroupBanners );
GetDirListing( ssprintf("%s\\%s\\*.bmp", sDir.GetString(), sGroupDirName.GetString()), arrayGroupBanners );
2002-09-10 07:11:29 +00:00
CString sBannerPath;
if( !arrayGroupBanners.empty() )
2002-09-10 07:11:29 +00:00
{
sBannerPath = ssprintf("%s\\%s\\%s", sDir.GetString(), sGroupDirName.GetString(), arrayGroupBanners[0].GetString() );
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
{
// trim off the trailing slash if any
2002-10-31 08:05:13 +00:00
TrimRight( sDir, "/\\" );
2002-03-06 08:25:09 +00:00
// Find all group directories in "Songs" folder
CStringArray arrayGroupDirs;
GetDirListing( sDir+"\\*.*", arrayGroupDirs, true );
SortCStringArray( arrayGroupDirs );
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
SanityCheckGroupDir(sDir+"\\"+sGroupDirName);
2002-03-06 08:25:09 +00:00
// Find all Song folders in this group directory
CStringArray arraySongDirs;
GetDirListing( ssprintf("%s\\%s\\*.*", sDir.GetString(), sGroupDirName.GetString()), arraySongDirs, true );
2002-03-06 08:25:09 +00:00
SortCStringArray( arraySongDirs );
unsigned j;
2002-09-09 02:23:47 +00:00
int loaded = 0;
for( j=0; j< arraySongDirs.size(); j++ ) // for each song dir
2002-03-06 08:25:09 +00:00
{
CString sSongDirName = arraySongDirs[j];
if( 0 == stricmp( sSongDirName, "cvs" ) ) // the directory called "CVS"
continue; // ignore it
// this is a song directory. Load a new song!
2002-11-17 09:13:35 +00:00
if( ld ) {
ld->SetText( ssprintf("Loading songs...\n%s\n%s", sGroupDirName.GetString(), sSongDirName.GetString()));
ld->Paint();
}
2002-03-06 08:25:09 +00:00
Song* pNewSong = new Song;
if( !pNewSong->LoadFromSongDir( ssprintf("%s\\%s\\%s", sDir.GetString(), sGroupDirName.GetString(), sSongDirName.GetString()) ) ) {
/* 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-05-19 01:59:48 +00:00
/*
2002-04-28 20:42:32 +00:00
void SongManager::LoadDWISongDir( CString DWIHome )
2002-03-06 08:25:09 +00:00
{
// trim off the trailing slash if any
2002-10-31 08:05:13 +00:00
TrimRight( DWIHome, "/\\" );
2002-02-28 19:40:40 +00:00
2002-04-28 20:42:32 +00:00
// this has to be fixed, DWI doesn't put files
// in it's DWI folder. It puts them in Songs/<MIX>/<SONGNAME>
// so what we have to do, is go to the DWI directory (which will
// be changeable by the user so they don't have to copy everything
// over and have two copies of everything
2002-02-28 19:40:40 +00:00
// Find all directories in "DWIs" folder
CStringArray arrayDirs;
2002-04-28 20:42:32 +00:00
CStringArray MixDirs;
// now we've got the listing of the mix directories
// and we need to use THOSE directories to find our
// dwis
GetDirListing( ssprintf("%s\\Songs\\*.*", DWIHome ), MixDirs.GetString(), true );
2002-04-28 20:42:32 +00:00
SortCStringArray( MixDirs );
2002-02-28 19:40:40 +00:00
for( unsigned i=0; i< MixDirs.size(); i++ ) // for each dir in /Songs/
2002-02-28 19:40:40 +00:00
{
2002-04-28 20:42:32 +00:00
// the dir name will most likely be something like
// Dance Dance Revolution 4th Mix, etc.
CString sDirName = MixDirs[i];
2002-02-28 19:40:40 +00:00
sDirName.MakeLower();
if( sDirName == "cvs" ) // ignore the directory called "CVS"
continue;
GetDirListing( ssprintf("%s\\Songs\\%s\\*.*", DWIHome.GetString(), MixDirs[i].GetString()), arrayDirs, true);
2002-04-28 20:42:32 +00:00
SortCStringArray(arrayDirs, true);
2002-02-28 19:40:40 +00:00
for( unsigned b = 0; b < arrayDirs.size(); b++)
2002-02-28 19:40:40 +00:00
{
2002-04-28 20:42:32 +00:00
// Find all DWIs in this directory
CStringArray arrayDWIFiles;
GetDirListing( ssprintf("%s\\Songs\\%s\\%s\\*.dwi", DWIHome.GetString(), MixDirs[i].GetString(), arrayDirs[b].GetString()), arrayDWIFiles, false);
2002-04-28 20:42:32 +00:00
SortCStringArray( arrayDWIFiles );
2002-02-28 19:40:40 +00:00
for( unsigned j=0; j< arrayDWIFiles.size(); j++ ) // for each DWI file
2002-04-28 20:42:32 +00:00
{
CString sDWIFileName = arrayDWIFiles[j];
sDWIFileName.MakeLower();
// load DWIs from the sub dirs
DWILoader ld;
2002-04-28 20:42:32 +00:00
Song* pNewSong = new Song;
ld.LoadFromDWIFile(
ssprintf("%s\\Songs\\%s\\%s\\%s", DWIHome.GetString(), MixDirs[i].GetString(), arrayDirs[b].GetString(), sDWIFileName.GetString()),
*pNewSong);
2002-10-31 04:23:39 +00:00
m_pSongs.push_back( pNewSong );
2002-04-28 20:42:32 +00:00
}
2002-02-28 19:40:40 +00:00
}
}
}
2002-05-19 01:59:48 +00:00
*/
2002-02-28 19:40:40 +00:00
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
{
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
}
void SongManager::ReadStatisticsFromDisk()
{
IniFile ini;
ini.SetPath( g_sStatisticsFileName );
if( !ini.ReadFile() ) {
LOG->Trace( "WARNING: Could not read config file '%s'.", g_sStatisticsFileName.GetString() );
2002-02-28 19:40:40 +00:00
return; // load nothing
}
// load song statistics
2003-01-03 22:37:44 +00:00
const IniFile::key *Key = ini.GetKey( "Statistics" );
if( Key )
2002-02-28 19:40:40 +00:00
{
2003-01-03 22:37:44 +00:00
for( IniFile::key::const_iterator i = Key->begin();
i != Key->end(); ++i )
2002-02-28 19:40:40 +00:00
{
2002-10-24 23:08:18 +00:00
CString name = i->first;
CString value = i->second;
2002-02-28 19:40:40 +00:00
// Each value has the format "SongName::StepsName=TimesPlayed::TopGrade::TopScore::MaxCombo".
2002-06-29 11:59:09 +00:00
char szSongDir[256];
char szNotesType[256];
char szNotesDescription[256];
2002-02-28 19:40:40 +00:00
int iRetVal;
unsigned i;
2002-02-28 19:40:40 +00:00
2002-05-19 01:59:48 +00:00
// Parse for Song name and Notes name
iRetVal = sscanf( name, "%[^:]::%[^:]::%[^\n]", szSongDir, szNotesType, szNotesDescription );
if( iRetVal != 3 )
2002-02-28 19:40:40 +00:00
continue; // this line doesn't match what is expected
NotesType notesType = GameManager::StringToNotesType( szNotesType );
2002-02-28 19:40:40 +00:00
// Search for the corresponding Song pointer.
Song* pSong = NULL;
for( i=0; i<m_pSongs.size(); i++ )
2002-02-28 19:40:40 +00:00
{
2002-12-13 23:41:11 +00:00
if( m_pSongs[i]->GetSongDir() == szSongDir ) // match!
2002-02-28 19:40:40 +00:00
{
pSong = m_pSongs[i];
break;
}
}
if( pSong == NULL ) // didn't find a match
continue; // skip this entry
2002-05-19 01:59:48 +00:00
// Search for the corresponding Notes pointer.
Notes* pNotes = NULL;
for( i=0; i<pSong->m_apNotes.size(); i++ )
2002-02-28 19:40:40 +00:00
{
if( pSong->m_apNotes[i]->m_NotesType == notesType &&
2003-01-02 22:10:51 +00:00
pSong->m_apNotes[i]->GetDescription() == szNotesDescription ) // match!
2002-02-28 19:40:40 +00:00
{
2002-07-11 19:02:26 +00:00
pNotes = pSong->m_apNotes[i];
2002-02-28 19:40:40 +00:00
break;
}
}
2002-05-19 01:59:48 +00:00
if( pNotes == NULL ) // didn't find a match
2002-02-28 19:40:40 +00:00
continue; // skip this entry
2002-05-19 01:59:48 +00:00
// Parse the Notes statistics.
2002-02-28 19:40:40 +00:00
char szGradeLetters[10]; // longest possible string is "AAA"
iRetVal = sscanf(
2002-07-23 01:41:40 +00:00
value,
2002-02-28 19:40:40 +00:00
"%d::%[^:]::%d::%d",
2002-05-19 01:59:48 +00:00
&pNotes->m_iNumTimesPlayed,
2002-02-28 19:40:40 +00:00
szGradeLetters,
2002-05-19 01:59:48 +00:00
&pNotes->m_iTopScore,
&pNotes->m_iMaxCombo
2002-02-28 19:40:40 +00:00
);
if( iRetVal != 4 )
continue;
2002-05-19 01:59:48 +00:00
pNotes->m_TopGrade = StringToGrade( szGradeLetters );
2002-02-28 19:40:40 +00:00
}
}
}
void SongManager::SaveStatisticsToDisk()
{
IniFile ini;
ini.SetPath( g_sStatisticsFileName );
// save song statistics
for( unsigned i=0; i<m_pSongs.size(); i++ ) // for each Song
2002-02-28 19:40:40 +00:00
{
Song* pSong = m_pSongs[i];
for( unsigned j=0; j<pSong->m_apNotes.size(); j++ ) // for each Notes
2002-02-28 19:40:40 +00:00
{
2002-07-11 19:02:26 +00:00
Notes* pNotes = pSong->m_apNotes[j];
2002-02-28 19:40:40 +00:00
2002-05-19 01:59:48 +00:00
if( pNotes->m_TopGrade == GRADE_NO_DATA )
continue; // skip
2002-02-28 19:40:40 +00:00
2002-05-19 01:59:48 +00:00
// Each value has the format "SongName::NotesName=TimesPlayed::TopGrade::TopScore::MaxCombo".
2002-02-28 19:40:40 +00:00
2003-01-02 22:10:51 +00:00
CString sName = ssprintf( "%s::%s::%s", pSong->GetSongDir().GetString(), GameManager::NotesTypeToString(pNotes->m_NotesType).GetString(), pNotes->GetDescription().GetString() );
2002-02-28 19:40:40 +00:00
CString sValue = ssprintf(
"%d::%s::%d::%d",
2002-05-19 01:59:48 +00:00
pNotes->m_iNumTimesPlayed,
GradeToString( pNotes->m_TopGrade ).GetString(),
2002-05-19 01:59:48 +00:00
pNotes->m_iTopScore,
pNotes->m_iMaxCombo
2002-02-28 19:40:40 +00:00
);
ini.SetValue( "Statistics", sName, sValue );
}
}
ini.WriteFile();
2002-03-06 08:25:09 +00:00
}
CString SongManager::GetGroupBannerPath( CString sGroupName )
2002-03-06 08:25:09 +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
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
RageColor SongManager::GetGroupColor( const CString &sGroupName )
2002-04-16 17:31:00 +00:00
{
// search for the group index
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
}
ASSERT( i != m_arrayGroupNames.size() ); // this is not a valid group
2002-04-16 17:31:00 +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 )
{
ASSERT( pSong );
for( unsigned i=0; i<pSong->m_apNotes.size(); i++ )
{
2002-12-17 05:22:32 +00:00
const Notes* pNotes = pSong->m_apNotes[i];
2003-01-02 22:10:51 +00:00
if( pNotes->GetMeter() == 10 )
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
{
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" );
sShortName.Replace( "Pump It Up", "PIU" );
sShortName.Replace( "pump it up", "PIU" );
sShortName.Replace( "PUMP IT UP", "PIU" );
sShortName.Replace( "ParaParaParadise", "PPP" );
sShortName.Replace( "paraparaparadise", "PPP" );
sShortName.Replace( "PARAPARAPARADUSE", "PPP" );
sShortName.Replace( "Para Para Paradise", "PPP" );
sShortName.Replace( "para para paradise", "PPP" );
sShortName.Replace( "PARA PARA PARADUSE", "PPP" );
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 );
for( unsigned i=0; i<saCourseFiles.size(); i++ )
2002-07-02 17:34:20 +00:00
{
Course course;
course.LoadFromCRSFile( "Courses\\" + saCourseFiles[i], m_pSongs );
2002-12-17 05:29:50 +00:00
if( course.GetNumStages() > 0 )
2002-10-31 04:23:39 +00:00
m_aOniCourses.push_back( course );
2002-07-02 17:34:20 +00:00
}
2002-07-02 17:34:20 +00:00
//
2002-07-29 03:06:55 +00:00
// Create endless courses
2002-07-02 17:34:20 +00:00
//
2002-06-14 22:25:22 +00:00
CStringArray saGroupNames;
this->GetGroupNames( saGroupNames );
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
{
Course course;
2002-09-29 05:06:18 +00:00
course.CreateEndlessCourseFromGroupAndDifficulty( sGroupName, dc, apGroupSongs );
2002-07-04 21:05:18 +00:00
2002-12-17 05:29:50 +00:00
if( course.GetNumStages() > 0 )
2002-10-31 04:23:39 +00:00
m_aEndlessCourses.push_back( course );
2002-06-14 22:25:22 +00:00
}
}
//
// Load extra stages
//
for( g=0; g<saGroupNames.size(); g++ ) // foreach Group
{
CString sGroupName = saGroupNames[g];
2002-10-08 23:39:18 +00:00
CStringArray saCoursePaths;
GetDirListing( "Songs\\" + sGroupName + "\\*.crs", saCoursePaths, false, true );
for( unsigned i=0; i<saCoursePaths.size(); i++ )
{
Course course;
2002-10-08 23:39:18 +00:00
course.LoadFromCRSFile( saCoursePaths[i], m_pSongs );
2002-12-17 05:29:50 +00:00
if( course.GetNumStages() > 0 )
2002-10-31 04:23:39 +00:00
m_aExtraCourses.push_back( course );
}
}
2002-06-14 22:25:22 +00:00
}
void SongManager::ReloadCourses()
{
}
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();
}
}
}
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;
2002-12-17 05:09:36 +00:00
po_out.FromString( course.GetModifiers(0) );
so_out.FromString( course.GetModifiers(0) );
2002-08-30 20:49:56 +00:00
return true;
}
2002-08-01 13:42:56 +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 );
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;
pSong->GetNotesThatMatch( sd->m_NotesType, apNotes );
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;
po_out.m_fArrowScrollSpeed = 1.5f;
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() );
2002-08-20 21:00:56 +00:00
switch( ((UINT)iSongHash) % 6 )
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;
case 5: po_out.m_bEffects[PlayerOptions::EFFECT_WAVE] = true; break;
2002-08-01 13:42:56 +00:00
default: ASSERT(0);
}
}
Song* SongManager::GetRandomSong()
{
if( m_pSongs.empty() )
return NULL;
return SONGMAN->m_pSongs[ rand()%m_pSongs.size() ];
}
2002-12-02 05:25:44 +00:00
Song* SongManager::GetSongFromDir( CString sDir )
{
2002-12-02 05:25:44 +00:00
if( sDir[sDir.GetLength()-1] != '\\' )
sDir += '\\';
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 )
return m_pSongs[i];
return NULL;
}