/* Course - A queue of songs and notes. */ #ifndef COURSE_H #define COURSE_H #include "PlayerNumber.h" #include "GameConstantsAndTypes.h" #include "Attack.h" #include #include "Trail.h" #include #include "EnumHelper.h" struct PlayerOptions; struct SongOptions; class Song; class Steps; class Profile; struct lua_State; enum CourseType { COURSE_TYPE_NONSTOP, // if life meter type is BAR COURSE_TYPE_ONI, // if life meter type is BATTERY COURSE_TYPE_ENDLESS, // if set to REPEAT COURSE_TYPE_SURVIVAL, // if life meter type is TIME NUM_COURSE_TYPES }; #define FOREACH_CourseType( i ) FOREACH_ENUM( CourseType, NUM_COURSE_TYPES, i ) inline PlayMode CourseTypeToPlayMode( CourseType ct ) { return (PlayMode)(PLAY_MODE_NONSTOP+ct); } inline CourseType PlayModeToCourseType( PlayMode pm ) { return (CourseType)(pm-PLAY_MODE_NONSTOP); } enum SongSort { SongSort_Randomize, SongSort_MostPlays, SongSort_FewestPlays, SongSort_TopGrades, SongSort_LowestGrades, NUM_SongSort }; #define FOREACH_SongSort( i ) FOREACH_ENUM( SongSort, NUM_SongSort, i ) const CString& SongSortToString( SongSort ss ); const CString& SongSortToThemedString( SongSort ss ); class CourseEntry { public: bool bSecret; // show "??????" instead of an exact song // filter criteria, applied from top to bottom Song* pSong; // don't filter if NULL CString sSongGroup; // don't filter if empty Difficulty baseDifficulty; // don't filter if DIFFICULTY_INVALID bool bNoDifficult; // if true, CourseDifficulty doesn't affect this entry int iLowMeter; // don't filter if -1 int iHighMeter; // don't filter if -1 SongSort songSort; // sort by this after filtering int iChooseIndex; // CString sModifiers; // set player and song options using these AttackArray attacks; // timed sModifiers float fGainSeconds; // time gained back at the beginning of the song. LifeMeterTime only. CourseEntry() { bSecret = false; pSong = NULL; sSongGroup = ""; baseDifficulty = DIFFICULTY_INVALID; bNoDifficult = false; iLowMeter = -1; iHighMeter = -1; songSort = SongSort_Randomize; iChooseIndex = 0; sModifiers = ""; fGainSeconds = 0; } bool IsRandomSong() const { return iChooseIndex == -1 && pSong == NULL; } }; class Course { public: Course(); bool m_bIsAutogen; // was this created by AutoGen? CString m_sPath; private: CString m_sMainTitle, m_sMainTitleTranslit; CString m_sSubTitle, m_sSubTitleTranslit; public: bool HasBanner() const; CString m_sBannerPath; CString m_sCDTitlePath; CString m_sGroupName; bool m_bRepeat; // repeat after last song? "Endless" bool m_bRandomize; // play the songs in a random order int m_iLives; // -1 means use bar life meter int m_iCustomMeter[NUM_DIFFICULTIES]; // -1 = no meter specified bool m_bSortByMeter; vector m_vEntries; /* If PREFSMAN->m_bShowNative is off, these are the same as GetTranslit* below. * Otherwise, they return the main titles. */ CString GetDisplayMainTitle() const; CString GetDisplaySubTitle() const; /* Returns the transliterated titles, if any; otherwise returns the main titles. */ CString GetTranslitMainTitle() const { return m_sMainTitleTranslit.size()? m_sMainTitleTranslit: m_sMainTitle; } CString GetTranslitSubTitle() const { return m_sSubTitleTranslit.size()? m_sSubTitleTranslit: m_sSubTitle; } /* "title subtitle" */ CString GetDisplayFullTitle() const; CString GetTranslitFullTitle() const; // Dereferences course_entries and returns only the playable Songs and Steps Trail* GetTrail( StepsType st, CourseDifficulty cd=DIFFICULTY_MEDIUM ) const; void GetTrails( vector &AddTo, StepsType st ) const; void GetAllTrails( vector &AddTo ) const; float GetMeter( StepsType st, CourseDifficulty cd=DIFFICULTY_MEDIUM ) const; bool HasMods() const; bool AllSongsAreFixed() const; int GetEstimatedNumStages() const { return m_vEntries.size(); } bool IsPlayableIn( StepsType st ) const; bool CourseHasBestOrWorst() const; RageColor GetColor() const; bool GetTotalSeconds( StepsType st, float& fSecondsOut ) const; bool IsNonstop() const { return GetPlayMode() == PLAY_MODE_NONSTOP; } bool IsOni() const { return GetPlayMode() == PLAY_MODE_ONI; } bool IsEndless() const { return GetPlayMode() == PLAY_MODE_ENDLESS; } CourseType GetCourseType() const; PlayMode GetPlayMode() const; bool IsFixed() const; bool ShowInDemonstrationAndRanking() const; void LoadFromCRSFile( CString sPath ); void RevertFromDisk(); void Init(); void Save( CString sPath = "", bool bSavingCache=false ); /* default is source file */ void AutogenEndlessFromGroup( CString sGroupName, Difficulty dc ); void AutogenNonstopFromGroup( CString sGroupName, Difficulty dc ); void AutogenOniFromArtist( CString sArtistName, CString sArtistNameTranslit, vector aSongs, Difficulty dc ); // sorting values int m_SortOrder_TotalDifficulty; int m_SortOrder_Ranking; bool IsRanking() const; void UpdateCourseStats( StepsType st ); /* Call to regenerate Trails with random entries */ void RegenerateNonFixedTrails(); /* Call when a Song or its Steps are deleted/changed. */ void Invalidate( Song *pStaleSong ); void GetAllCachedTrails( vector &out ); CString GetCacheFilePath() const; const CourseEntry *FindFixedSong( const Song *pSong ) const; // Lua void PushSelf( lua_State *L ); private: void CalculateRadarValues(); bool GetTrailUnsorted( StepsType st, CourseDifficulty cd, Trail &trail ) const; bool GetTrailSorted( StepsType st, CourseDifficulty cd, Trail &trail ) const; typedef pair CacheEntry; struct CacheData { Trail trail; bool null; }; typedef map TrailCache_t; mutable TrailCache_t m_TrailCache; mutable int m_iTrailCacheSeed; typedef map RadarCache_t; RadarCache_t m_RadarCache; }; #endif /* * (c) 2001-2004 Chris Danford, Glenn Maynard * All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, and/or sell copies of the Software, and to permit persons to * whom the Software is furnished to do so, provided that the above * copyright notice(s) and this permission notice appear in all copies of * the Software and that both the above copyright notice(s) and this * permission notice appear in supporting documentation. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */