2003-02-16 04:01:45 +00:00
|
|
|
#include "global.h"
|
2002-07-23 01:41:40 +00:00
|
|
|
#include "GameState.h"
|
|
|
|
|
#include "GameManager.h"
|
|
|
|
|
#include "PrefsManager.h"
|
2003-02-16 04:28:17 +00:00
|
|
|
#include "song.h"
|
2003-10-14 01:23:16 +00:00
|
|
|
#include "Course.h"
|
2002-09-10 01:13:45 +00:00
|
|
|
#include "RageLog.h"
|
2003-02-06 07:32:57 +00:00
|
|
|
#include "RageUtil.h"
|
2003-02-10 05:30:12 +00:00
|
|
|
#include "SongManager.h"
|
2005-07-01 05:07:22 +00:00
|
|
|
#include "SongUtil.h"
|
2003-08-03 00:13:55 +00:00
|
|
|
#include "Steps.h"
|
2005-07-01 05:07:22 +00:00
|
|
|
#include "HighScore.h"
|
2003-02-22 00:12:45 +00:00
|
|
|
#include "NoteSkinManager.h"
|
2004-12-02 06:29:20 +00:00
|
|
|
#include "GameCommand.h"
|
2003-06-09 19:22:04 +00:00
|
|
|
#include "Character.h"
|
2005-02-21 06:22:46 +00:00
|
|
|
#include "UnlockManager.h"
|
2003-07-10 03:36:41 +00:00
|
|
|
#include "AnnouncerManager.h"
|
2003-09-08 03:26:58 +00:00
|
|
|
#include "ProfileManager.h"
|
2005-07-01 05:07:22 +00:00
|
|
|
#include "Profile.h"
|
2003-10-09 03:38:02 +00:00
|
|
|
#include "ThemeManager.h"
|
2003-11-16 04:45:12 +00:00
|
|
|
#include "LightsManager.h"
|
2003-11-30 06:20:25 +00:00
|
|
|
#include "RageFile.h"
|
2003-12-07 20:29:42 +00:00
|
|
|
#include "Bookkeeper.h"
|
2003-12-19 04:52:07 +00:00
|
|
|
#include "MemoryCardManager.h"
|
2005-02-16 03:25:45 +00:00
|
|
|
#include "StatsManager.h"
|
2004-03-13 22:18:09 +00:00
|
|
|
#include "GameConstantsAndTypes.h"
|
2004-07-17 22:15:39 +00:00
|
|
|
#include "CommonMetrics.h"
|
2004-10-28 02:17:50 +00:00
|
|
|
#include "Actor.h"
|
2004-12-20 06:25:59 +00:00
|
|
|
#include "PlayerState.h"
|
2005-01-15 02:01:26 +00:00
|
|
|
#include "Style.h"
|
2005-02-23 17:39:57 +00:00
|
|
|
#include "MessageManager.h"
|
2005-03-10 19:57:43 +00:00
|
|
|
#include "CommonMetrics.h"
|
2005-03-18 04:04:59 +00:00
|
|
|
#include "Foreach.h"
|
2005-03-18 22:47:44 +00:00
|
|
|
#include "LuaReference.h"
|
2005-03-24 21:44:03 +00:00
|
|
|
#include "CommonMetrics.h"
|
2005-08-14 12:06:40 +00:00
|
|
|
#include "CharacterManager.h"
|
2005-10-28 01:44:19 +00:00
|
|
|
#include "Game.h"
|
2006-02-06 01:23:25 +00:00
|
|
|
#include "AdjustSync.h"
|
2004-04-30 07:48:02 +00:00
|
|
|
|
|
|
|
|
#include <ctime>
|
2004-05-20 22:23:44 +00:00
|
|
|
#include <set>
|
2002-07-23 01:41:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
GameState* GAMESTATE = NULL; // global and accessable from anywhere in our program
|
|
|
|
|
|
2005-11-07 05:45:48 +00:00
|
|
|
#define NAME_BLACKLIST_FILE "/Data/NamesBlacklist.txt"
|
2005-04-03 06:48:26 +00:00
|
|
|
|
|
|
|
|
ThemeMetric<bool> USE_NAME_BLACKLIST("GameState","UseNameBlacklist");
|
2002-07-23 01:41:40 +00:00
|
|
|
|
2006-01-22 01:00:06 +00:00
|
|
|
ThemeMetric<RString> DEFAULT_SORT ("GameState","DefaultSort");
|
2005-06-12 03:44:13 +00:00
|
|
|
SortOrder GetDefaultSort()
|
|
|
|
|
{
|
|
|
|
|
return StringToSortOrder( DEFAULT_SORT );
|
|
|
|
|
}
|
2006-01-22 01:00:06 +00:00
|
|
|
ThemeMetric<RString> DEFAULT_SONG ("GameState","DefaultSong");
|
2005-08-03 03:28:13 +00:00
|
|
|
Song* GameState::GetDefaultSong() const
|
2005-06-12 03:44:13 +00:00
|
|
|
{
|
|
|
|
|
SongID sid;
|
|
|
|
|
sid.LoadFromDir( DEFAULT_SONG );
|
|
|
|
|
return sid.ToSong();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2005-02-25 05:27:28 +00:00
|
|
|
GameState::GameState() :
|
2006-02-14 11:35:00 +00:00
|
|
|
m_pCurGame( Message_CurrentGameChanged ),
|
|
|
|
|
m_pCurStyle( Message_CurrentStyleChanged ),
|
|
|
|
|
m_PlayMode( Message_PlayModeChanged ),
|
|
|
|
|
m_sPreferredSongGroup( Message_PreferredSongGroupChanged ),
|
|
|
|
|
m_sPreferredCourseGroup( Message_PreferredCourseGroupChanged ),
|
|
|
|
|
m_PreferredDifficulty( Message_PreferredDifficultyP1Changed ),
|
|
|
|
|
m_PreferredCourseDifficulty( Message_PreferredCourseDifficultyP1Changed ),
|
2005-08-24 20:42:14 +00:00
|
|
|
m_SortOrder( Message_SortOrderChanged ),
|
2006-02-14 11:35:00 +00:00
|
|
|
m_pCurSong( Message_CurrentSongChanged ),
|
2005-08-14 07:29:48 +00:00
|
|
|
m_pCurSteps( Message_CurrentStepsP1Changed ),
|
2006-02-14 11:35:00 +00:00
|
|
|
m_pCurCourse( Message_CurrentCourseChanged ),
|
2005-08-14 07:29:48 +00:00
|
|
|
m_pCurTrail( Message_CurrentTrailP1Changed ),
|
2005-10-10 04:36:04 +00:00
|
|
|
m_bGameplayLeadIn( Message_GameplayLeadInChanged ),
|
2006-02-14 11:35:00 +00:00
|
|
|
m_stEdit( Message_EditStepsTypeChanged ),
|
2006-02-21 11:43:20 +00:00
|
|
|
m_cdEdit( Message_EditCourseDifficultyChanged ),
|
2006-02-14 11:35:00 +00:00
|
|
|
m_pEditSourceSteps( Message_EditSourceStepsChanged ),
|
2005-08-14 07:29:48 +00:00
|
|
|
m_stEditSource( Message_EditSourceStepsTypeChanged ),
|
2006-02-14 11:35:00 +00:00
|
|
|
m_iEditCourseEntryIndex( Message_EditCourseEntryIndexChanged ),
|
|
|
|
|
m_sEditLocalProfileID( Message_EditLocalProfileIDChanged )
|
2002-07-23 01:41:40 +00:00
|
|
|
{
|
2005-05-07 08:34:20 +00:00
|
|
|
m_pCurStyle.Set( NULL );
|
2004-01-21 04:59:15 +00:00
|
|
|
|
2005-10-28 01:44:19 +00:00
|
|
|
m_pCurGame.Set( NULL );
|
2003-01-19 04:44:22 +00:00
|
|
|
m_iCoins = 0;
|
2004-02-22 23:26:46 +00:00
|
|
|
m_timeGameStarted.SetZero();
|
2005-06-23 00:15:19 +00:00
|
|
|
m_bDemonstrationOrJukebox = false;
|
2003-02-03 05:53:59 +00:00
|
|
|
|
2004-03-20 19:15:06 +00:00
|
|
|
m_iNumTimesThroughAttract = -1; // initial screen will bump this up to 0
|
2005-03-11 18:09:34 +00:00
|
|
|
m_iStageSeed = m_iGameSeed = 0;
|
2004-01-21 04:59:15 +00:00
|
|
|
|
2005-07-25 03:59:24 +00:00
|
|
|
m_PlayMode.Set( PLAY_MODE_INVALID ); // used by IsPlayerEnabled before the first screen
|
2004-08-22 01:11:17 +00:00
|
|
|
FOREACH_PlayerNumber( p )
|
|
|
|
|
m_bSideIsJoined[p] = false; // used by GetNumSidesJoined before the first screen
|
|
|
|
|
|
2004-12-20 06:25:59 +00:00
|
|
|
FOREACH_PlayerNumber( p )
|
|
|
|
|
{
|
|
|
|
|
m_pPlayerState[p] = new PlayerState;
|
|
|
|
|
m_pPlayerState[p]->m_PlayerNumber = p;
|
|
|
|
|
}
|
2005-08-23 20:55:58 +00:00
|
|
|
FOREACH_MultiPlayer( p )
|
|
|
|
|
{
|
|
|
|
|
m_pMultiPlayerState[p] = new PlayerState;
|
|
|
|
|
m_pMultiPlayerState[p]->m_PlayerNumber = PLAYER_1;
|
|
|
|
|
m_pMultiPlayerState[p]->m_mp = p;
|
|
|
|
|
}
|
2004-12-20 06:25:59 +00:00
|
|
|
|
2005-03-18 22:47:44 +00:00
|
|
|
m_Environment = new LuaTable;
|
2005-01-31 02:00:00 +00:00
|
|
|
|
2004-01-21 04:59:15 +00:00
|
|
|
/* Don't reset yet; let the first screen do it, so we can
|
|
|
|
|
* use PREFSMAN and THEME. */
|
|
|
|
|
// Reset();
|
2002-07-23 01:41:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GameState::~GameState()
|
|
|
|
|
{
|
2004-12-20 06:25:59 +00:00
|
|
|
FOREACH_PlayerNumber( p )
|
|
|
|
|
SAFE_DELETE( m_pPlayerState[p] );
|
2005-08-23 20:55:58 +00:00
|
|
|
FOREACH_MultiPlayer( p )
|
|
|
|
|
SAFE_DELETE( m_pMultiPlayerState[p] );
|
2005-03-18 22:47:44 +00:00
|
|
|
|
2005-05-19 23:29:39 +00:00
|
|
|
SAFE_DELETE( m_Environment );
|
2002-07-23 01:41:40 +00:00
|
|
|
}
|
|
|
|
|
|
2006-01-22 01:00:06 +00:00
|
|
|
void GameState::ApplyGameCommand( const RString &sCommand, PlayerNumber pn )
|
2005-02-16 06:24:33 +00:00
|
|
|
{
|
|
|
|
|
GameCommand m;
|
|
|
|
|
m.Load( 0, ParseCommands(sCommand) );
|
|
|
|
|
|
2006-01-22 01:00:06 +00:00
|
|
|
RString sWhy;
|
2005-02-16 06:24:33 +00:00
|
|
|
if( !m.IsPlayable(&sWhy) )
|
|
|
|
|
RageException::Throw( "Can't apply mode \"%s\": %s", sCommand.c_str(), sWhy.c_str() );
|
|
|
|
|
|
|
|
|
|
if( pn == PLAYER_INVALID )
|
|
|
|
|
m.ApplyToAllPlayers();
|
|
|
|
|
else
|
|
|
|
|
m.Apply( pn );
|
|
|
|
|
}
|
|
|
|
|
|
2004-04-30 07:48:02 +00:00
|
|
|
void GameState::ApplyCmdline()
|
|
|
|
|
{
|
2004-05-03 20:14:52 +00:00
|
|
|
/* We need to join players before we can set the style. */
|
2006-01-22 01:00:06 +00:00
|
|
|
RString sPlayer;
|
2004-09-21 07:53:39 +00:00
|
|
|
for( int i = 0; GetCommandlineArgument( "player", &sPlayer, i ); ++i )
|
2004-04-30 07:48:02 +00:00
|
|
|
{
|
|
|
|
|
int pn = atoi( sPlayer )-1;
|
|
|
|
|
if( !IsAnInt( sPlayer ) || pn < 0 || pn >= NUM_PLAYERS )
|
|
|
|
|
RageException::Throw( "Invalid argument \"--player=%s\"", sPlayer.c_str() );
|
|
|
|
|
|
|
|
|
|
this->JoinPlayer( (PlayerNumber) pn );
|
|
|
|
|
}
|
|
|
|
|
|
2006-01-22 01:00:06 +00:00
|
|
|
RString sMode;
|
2004-09-21 07:53:39 +00:00
|
|
|
for( int i = 0; GetCommandlineArgument( "mode", &sMode, i ); ++i )
|
2004-04-30 07:48:02 +00:00
|
|
|
{
|
2005-02-16 06:24:33 +00:00
|
|
|
ApplyGameCommand( sMode );
|
2004-04-30 07:48:02 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2002-07-23 01:41:40 +00:00
|
|
|
void GameState::Reset()
|
|
|
|
|
{
|
2004-05-25 06:01:52 +00:00
|
|
|
EndGame();
|
2003-12-08 04:02:43 +00:00
|
|
|
|
2003-10-09 03:38:02 +00:00
|
|
|
ASSERT( THEME );
|
|
|
|
|
|
2004-02-22 23:26:46 +00:00
|
|
|
m_timeGameStarted.SetZero();
|
2005-05-07 08:34:20 +00:00
|
|
|
m_pCurStyle.Set( NULL );
|
2004-05-24 08:16:17 +00:00
|
|
|
FOREACH_PlayerNumber( p )
|
2003-01-19 04:44:22 +00:00
|
|
|
m_bSideIsJoined[p] = false;
|
2005-08-20 22:51:43 +00:00
|
|
|
FOREACH_MultiPlayer( p )
|
2006-04-21 00:43:32 +00:00
|
|
|
m_MultiPlayerStatus[p] = MultiPlayerStatus_NotJoined;
|
2005-02-06 05:08:46 +00:00
|
|
|
MEMCARDMAN->UnlockCards();
|
2003-01-19 04:44:22 +00:00
|
|
|
// m_iCoins = 0; // don't reset coin count!
|
2002-08-20 21:00:56 +00:00
|
|
|
m_MasterPlayerNumber = PLAYER_INVALID;
|
2005-08-23 20:55:58 +00:00
|
|
|
m_bMultiplayer = false;
|
2006-01-13 21:49:35 +00:00
|
|
|
*m_Environment = LuaTable();
|
2005-06-24 06:06:16 +00:00
|
|
|
m_sPreferredSongGroup.Set( GROUP_ALL );
|
|
|
|
|
m_sPreferredCourseGroup.Set( GROUP_ALL );
|
2005-04-05 08:30:57 +00:00
|
|
|
m_bChangedFailTypeOnScreenSongOptions = false;
|
2004-05-24 08:16:17 +00:00
|
|
|
FOREACH_PlayerNumber( p )
|
2004-01-21 01:35:54 +00:00
|
|
|
{
|
2005-02-26 08:32:49 +00:00
|
|
|
m_PreferredDifficulty[p].Set( DIFFICULTY_INVALID );
|
|
|
|
|
m_PreferredCourseDifficulty[p].Set( DIFFICULTY_MEDIUM );
|
2004-01-21 01:35:54 +00:00
|
|
|
}
|
2005-08-24 20:42:14 +00:00
|
|
|
m_SortOrder.Set( SORT_INVALID );
|
2005-06-12 03:44:13 +00:00
|
|
|
m_PreferredSortOrder = GetDefaultSort();
|
2005-07-25 03:59:24 +00:00
|
|
|
m_PlayMode.Set( PLAY_MODE_INVALID );
|
2005-12-06 23:44:01 +00:00
|
|
|
m_EditMode = EditMode_INVALID;
|
2003-03-09 00:55:49 +00:00
|
|
|
m_bDemonstrationOrJukebox = false;
|
2003-02-11 02:20:38 +00:00
|
|
|
m_bJukeboxUsesModifiers = false;
|
2002-07-29 03:06:55 +00:00
|
|
|
m_iCurrentStageIndex = 0;
|
2005-10-10 04:50:53 +00:00
|
|
|
m_bGameplayLeadIn.Set( false );
|
2004-01-24 19:09:51 +00:00
|
|
|
m_iNumStagesOfThisSong = 0;
|
2006-04-29 02:03:08 +00:00
|
|
|
m_bLoadingNextSong = false;
|
2002-07-29 03:06:55 +00:00
|
|
|
|
2004-07-25 04:27:20 +00:00
|
|
|
NOTESKIN->RefreshNoteSkinData( this->m_pCurGame );
|
2003-09-12 04:18:43 +00:00
|
|
|
|
2003-07-30 20:34:16 +00:00
|
|
|
m_iGameSeed = rand();
|
2005-03-11 18:09:34 +00:00
|
|
|
m_iStageSeed = rand();
|
2003-07-30 20:34:16 +00:00
|
|
|
|
2005-06-12 03:44:13 +00:00
|
|
|
m_pCurSong.Set( GetDefaultSong() );
|
2004-05-26 05:50:22 +00:00
|
|
|
m_pPreferredSong = NULL;
|
2004-05-24 03:32:56 +00:00
|
|
|
FOREACH_PlayerNumber( p )
|
2005-02-25 18:17:26 +00:00
|
|
|
m_pCurSteps[p].Set( NULL );
|
2005-05-18 07:14:19 +00:00
|
|
|
m_pCurCourse.Set( NULL );
|
2004-05-26 05:50:22 +00:00
|
|
|
m_pPreferredCourse = NULL;
|
2004-05-24 04:26:54 +00:00
|
|
|
FOREACH_PlayerNumber( p )
|
2005-05-18 07:14:19 +00:00
|
|
|
m_pCurTrail[p].Set( NULL );
|
2002-07-23 01:41:40 +00:00
|
|
|
|
2004-05-24 08:16:17 +00:00
|
|
|
FOREACH_PlayerNumber( p )
|
2004-12-20 10:47:41 +00:00
|
|
|
m_pPlayerState[p]->Reset();
|
2005-08-23 20:55:58 +00:00
|
|
|
FOREACH_MultiPlayer( p )
|
|
|
|
|
m_pMultiPlayerState[p]->Reset();
|
2003-11-30 23:13:38 +00:00
|
|
|
|
2003-01-25 11:05:12 +00:00
|
|
|
ResetMusicStatistics();
|
2003-07-03 06:38:57 +00:00
|
|
|
ResetStageStatistics();
|
2005-02-06 05:08:46 +00:00
|
|
|
|
|
|
|
|
FOREACH_PlayerNumber( pn )
|
2005-02-06 09:58:50 +00:00
|
|
|
PROFILEMAN->UnloadProfile( pn );
|
2005-02-06 05:08:46 +00:00
|
|
|
|
2006-03-20 01:04:46 +00:00
|
|
|
SONGMAN->UpdatePopular();
|
2004-02-27 21:28:15 +00:00
|
|
|
SONGMAN->UpdateShuffled();
|
2003-01-25 11:05:12 +00:00
|
|
|
|
2004-06-04 06:18:30 +00:00
|
|
|
/* We may have cached trails from before everything was loaded (eg. from before
|
2006-03-20 01:04:46 +00:00
|
|
|
* SongManager::UpdatePopular could be called). Erase the cache. */
|
2004-07-24 06:40:51 +00:00
|
|
|
SONGMAN->RegenerateNonFixedCourses();
|
2004-06-04 06:18:30 +00:00
|
|
|
|
2005-03-26 17:30:37 +00:00
|
|
|
STATSMAN->Reset();
|
2002-07-29 03:06:55 +00:00
|
|
|
|
2005-10-27 07:51:37 +00:00
|
|
|
GAMESTATE->GetDefaultSongOptions( m_SongOptions );
|
2003-04-21 23:43:51 +00:00
|
|
|
|
2004-05-16 02:51:55 +00:00
|
|
|
FOREACH_PlayerNumber(p)
|
2003-10-09 03:38:02 +00:00
|
|
|
{
|
2004-02-04 07:58:02 +00:00
|
|
|
// I can't think of a good reason to have both game-specific
|
|
|
|
|
// default mods and theme specific default mods. We should choose
|
|
|
|
|
// one or the other. -Chris
|
2004-02-05 21:32:50 +00:00
|
|
|
// Having default modifiers in prefs is needed for several things.
|
|
|
|
|
// The theme setting is for eg. BM being reverse by default. (This
|
2004-12-02 06:29:20 +00:00
|
|
|
// could be done in the title menu GameCommand, but then it wouldn't
|
2004-02-05 21:32:50 +00:00
|
|
|
// affect demo, and other non-gameplay things ...) -glenn
|
2005-10-27 07:51:37 +00:00
|
|
|
|
|
|
|
|
GAMESTATE->GetDefaultPlayerOptions( GAMESTATE->m_pPlayerState[p]->m_PlayerOptions );
|
2003-10-09 03:38:02 +00:00
|
|
|
}
|
2003-04-21 02:41:10 +00:00
|
|
|
|
2004-05-16 02:51:55 +00:00
|
|
|
FOREACH_PlayerNumber(p)
|
2003-06-27 08:06:22 +00:00
|
|
|
{
|
2005-09-29 06:30:09 +00:00
|
|
|
if( PREFSMAN->m_ShowDancingCharacters == PrefsManager::SDC_Random )
|
2005-08-14 12:06:40 +00:00
|
|
|
m_pCurCharacters[p] = CHARMAN->GetRandomCharacter();
|
2003-06-27 08:06:22 +00:00
|
|
|
else
|
2005-08-14 12:06:40 +00:00
|
|
|
m_pCurCharacters[p] = CHARMAN->GetDefaultCharacter();
|
2004-01-21 04:59:15 +00:00
|
|
|
ASSERT( m_pCurCharacters[p] );
|
2003-06-27 08:06:22 +00:00
|
|
|
}
|
|
|
|
|
|
2005-02-21 17:29:49 +00:00
|
|
|
m_bTemporaryEventMode = false;
|
2005-02-23 19:18:11 +00:00
|
|
|
m_bStatsCommitted = false;
|
2005-02-21 17:29:49 +00:00
|
|
|
|
2004-03-23 06:11:10 +00:00
|
|
|
LIGHTSMAN->SetLightsMode( LIGHTSMODE_ATTRACT );
|
2005-02-24 11:36:19 +00:00
|
|
|
|
2005-02-25 05:27:28 +00:00
|
|
|
m_stEdit.Set( STEPS_TYPE_INVALID );
|
|
|
|
|
m_pEditSourceSteps.Set( NULL );
|
|
|
|
|
m_stEditSource.Set( STEPS_TYPE_INVALID );
|
2005-06-26 21:31:07 +00:00
|
|
|
m_iEditCourseEntryIndex.Set( -1 );
|
2005-08-04 21:13:29 +00:00
|
|
|
m_sEditLocalProfileID.Set( "" );
|
2005-06-29 07:57:15 +00:00
|
|
|
|
|
|
|
|
m_bBackedOutOfFinalStage = false;
|
2004-04-30 07:48:02 +00:00
|
|
|
|
|
|
|
|
ApplyCmdline();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GameState::JoinPlayer( PlayerNumber pn )
|
|
|
|
|
{
|
|
|
|
|
this->m_bSideIsJoined[pn] = true;
|
2005-08-14 07:29:48 +00:00
|
|
|
MESSAGEMAN->Broadcast( (Message)(Message_SideJoinedP1+pn) );
|
2005-05-07 00:27:31 +00:00
|
|
|
|
2004-04-30 07:48:02 +00:00
|
|
|
if( this->m_MasterPlayerNumber == PLAYER_INVALID )
|
|
|
|
|
this->m_MasterPlayerNumber = pn;
|
|
|
|
|
|
|
|
|
|
// if first player to join, set start time
|
|
|
|
|
if( this->GetNumSidesJoined() == 1 )
|
|
|
|
|
this->BeginGame();
|
2003-12-08 04:02:43 +00:00
|
|
|
}
|
|
|
|
|
|
2005-05-07 00:27:31 +00:00
|
|
|
int GameState::GetCoinsNeededToJoin() const
|
|
|
|
|
{
|
|
|
|
|
int iCoinsToCharge = 0;
|
|
|
|
|
|
2005-05-20 17:45:44 +00:00
|
|
|
if( GAMESTATE->GetCoinMode() == COIN_MODE_PAY )
|
2005-05-07 00:27:31 +00:00
|
|
|
iCoinsToCharge = PREFSMAN->m_iCoinsPerCredit;
|
|
|
|
|
|
|
|
|
|
// If joint premium don't take away a credit for the 2nd join.
|
|
|
|
|
if( GAMESTATE->GetPremium() == PREMIUM_JOINT &&
|
|
|
|
|
GAMESTATE->GetNumSidesJoined() == 1 )
|
|
|
|
|
iCoinsToCharge = 0;
|
|
|
|
|
|
|
|
|
|
return iCoinsToCharge;
|
|
|
|
|
}
|
|
|
|
|
|
2005-02-23 03:40:47 +00:00
|
|
|
/*
|
|
|
|
|
* Game flow:
|
|
|
|
|
*
|
|
|
|
|
* BeginGame() - the first player has joined; the game is starting.
|
|
|
|
|
*
|
|
|
|
|
* PlayersFinalized() - no more players may join (because the style is set)
|
|
|
|
|
*
|
|
|
|
|
* BeginStage() - gameplay is beginning
|
|
|
|
|
*
|
|
|
|
|
* optional: CancelStage() - gameplay aborted (Back pressed), undo BeginStage and back up
|
|
|
|
|
*
|
2005-02-23 19:18:11 +00:00
|
|
|
* CommitStageStats() - gameplay is finished
|
|
|
|
|
* Saves STATSMAN->m_CurStageStats to the profiles, so profile information
|
|
|
|
|
* is up-to-date for Evaluation.
|
|
|
|
|
*
|
2005-02-23 03:40:47 +00:00
|
|
|
* FinishStage() - gameplay and evaluation is finished
|
2005-02-23 19:18:11 +00:00
|
|
|
* Clears data which was stored by CommitStageStats.
|
2005-02-23 03:40:47 +00:00
|
|
|
*
|
|
|
|
|
* EndGame() - the game is finished
|
|
|
|
|
*
|
|
|
|
|
*/
|
2003-12-08 04:02:43 +00:00
|
|
|
void GameState::BeginGame()
|
|
|
|
|
{
|
2004-02-22 23:26:46 +00:00
|
|
|
m_timeGameStarted.Touch();
|
2003-12-28 08:20:48 +00:00
|
|
|
|
|
|
|
|
m_vpsNamesThatWereFilled.clear();
|
2003-12-28 19:46:50 +00:00
|
|
|
|
2004-08-09 08:09:20 +00:00
|
|
|
// Play attract on the ending screen, then on the ranking screen
|
|
|
|
|
// even if attract sounds are set to off.
|
|
|
|
|
m_iNumTimesThroughAttract = -1;
|
2004-08-09 05:01:24 +00:00
|
|
|
|
2005-01-27 19:42:34 +00:00
|
|
|
MEMCARDMAN->UnlockCards();
|
2003-12-08 04:02:43 +00:00
|
|
|
}
|
|
|
|
|
|
2004-02-08 01:05:53 +00:00
|
|
|
void GameState::PlayersFinalized()
|
|
|
|
|
{
|
2005-07-07 21:24:59 +00:00
|
|
|
// If cards are already locked, this was already called.
|
2005-02-06 08:48:55 +00:00
|
|
|
if( MEMCARDMAN->GetCardsLocked() )
|
2004-04-23 02:08:11 +00:00
|
|
|
return;
|
|
|
|
|
|
2005-08-14 07:29:48 +00:00
|
|
|
MESSAGEMAN->Broadcast( Message_PlayersFinalized );
|
2005-05-07 08:34:20 +00:00
|
|
|
|
2005-01-27 19:50:11 +00:00
|
|
|
MEMCARDMAN->LockCards();
|
2005-01-27 22:57:18 +00:00
|
|
|
|
2004-03-13 12:27:24 +00:00
|
|
|
// apply saved default modifiers if any
|
|
|
|
|
FOREACH_HumanPlayer( pn )
|
|
|
|
|
{
|
2005-01-28 00:12:09 +00:00
|
|
|
MEMCARDMAN->MountCard( pn );
|
2005-01-28 00:04:22 +00:00
|
|
|
|
2004-08-09 05:01:24 +00:00
|
|
|
PROFILEMAN->LoadFirstAvailableProfile( pn ); // load full profile
|
2004-03-29 06:47:10 +00:00
|
|
|
|
2005-02-07 03:37:43 +00:00
|
|
|
MEMCARDMAN->UnmountCard( pn );
|
|
|
|
|
|
2005-05-09 08:44:01 +00:00
|
|
|
if( !PROFILEMAN->IsPersistentProfile(pn) )
|
2004-03-13 19:20:24 +00:00
|
|
|
continue; // skip
|
|
|
|
|
|
|
|
|
|
Profile* pProfile = PROFILEMAN->GetProfile(pn);
|
|
|
|
|
|
2006-01-22 01:00:06 +00:00
|
|
|
RString sModifiers;
|
2004-11-14 05:24:37 +00:00
|
|
|
if( pProfile->GetDefaultModifiers( this->m_pCurGame, sModifiers ) )
|
2004-03-13 12:27:24 +00:00
|
|
|
{
|
2004-11-14 05:24:37 +00:00
|
|
|
/* We don't save negative preferences (eg. "no reverse"). If the theme
|
|
|
|
|
* sets a default of "reverse", and the player turns it off, we should
|
|
|
|
|
* set it off. However, don't reset modifiers that aren't saved by the
|
|
|
|
|
* profile, so we don't ignore unsaved modifiers when a profile is in use. */
|
2004-12-20 06:25:59 +00:00
|
|
|
GAMESTATE->m_pPlayerState[pn]->m_PlayerOptions.ResetSavedPrefs();
|
2004-11-14 05:24:37 +00:00
|
|
|
GAMESTATE->ApplyModifiers( pn, sModifiers );
|
2004-03-13 12:27:24 +00:00
|
|
|
}
|
2004-12-02 06:29:20 +00:00
|
|
|
// Only set the sort order if it wasn't already set by a GameCommand (or by an earlier profile)
|
2005-01-29 20:46:08 +00:00
|
|
|
if( m_PreferredSortOrder == SORT_INVALID && pProfile->m_SortOrder != SORT_INVALID )
|
|
|
|
|
m_PreferredSortOrder = pProfile->m_SortOrder;
|
2004-03-25 09:54:28 +00:00
|
|
|
if( pProfile->m_LastDifficulty != DIFFICULTY_INVALID )
|
2005-02-26 08:32:49 +00:00
|
|
|
m_PreferredDifficulty[pn].Set( pProfile->m_LastDifficulty );
|
2004-06-04 02:05:56 +00:00
|
|
|
if( pProfile->m_LastCourseDifficulty != DIFFICULTY_INVALID )
|
2005-02-26 08:32:49 +00:00
|
|
|
m_PreferredCourseDifficulty[pn].Set( pProfile->m_LastCourseDifficulty );
|
2004-08-14 06:41:24 +00:00
|
|
|
if( m_pPreferredSong == NULL )
|
|
|
|
|
m_pPreferredSong = pProfile->m_lastSong.ToSong();
|
|
|
|
|
if( m_pPreferredCourse == NULL )
|
|
|
|
|
m_pPreferredCourse = pProfile->m_lastCourse.ToCourse();
|
2004-03-13 12:27:24 +00:00
|
|
|
}
|
2004-04-23 06:35:24 +00:00
|
|
|
|
2005-07-07 08:41:19 +00:00
|
|
|
FOREACH_PotentialCpuPlayer( pn )
|
2005-10-27 05:16:19 +00:00
|
|
|
ApplyModifiers( pn, CommonMetrics::DEFAULT_CPU_MODIFIERS );
|
2004-02-08 01:05:53 +00:00
|
|
|
}
|
|
|
|
|
|
2003-12-08 04:02:43 +00:00
|
|
|
void GameState::EndGame()
|
|
|
|
|
{
|
2004-05-04 05:51:18 +00:00
|
|
|
LOG->Trace( "GameState::EndGame" );
|
|
|
|
|
|
2004-08-30 23:59:02 +00:00
|
|
|
if( m_bDemonstrationOrJukebox )
|
|
|
|
|
return;
|
2005-02-16 03:25:45 +00:00
|
|
|
if( m_timeGameStarted.IsZero() || !STATSMAN->m_vPlayedStageStats.size() ) // we were in the middle of a game and played at least one song
|
2004-05-25 06:01:52 +00:00
|
|
|
return;
|
|
|
|
|
|
2004-05-24 01:28:28 +00:00
|
|
|
/* Finish the final stage. */
|
|
|
|
|
FinishStage();
|
|
|
|
|
|
2004-08-29 19:10:25 +00:00
|
|
|
|
|
|
|
|
// Update totalPlaySeconds stat
|
2004-02-22 23:26:46 +00:00
|
|
|
int iPlaySeconds = max( 0, (int) m_timeGameStarted.PeekDeltaTime() );
|
2003-12-08 04:02:43 +00:00
|
|
|
|
2003-12-08 06:41:30 +00:00
|
|
|
Profile* pMachineProfile = PROFILEMAN->GetMachineProfile();
|
2003-12-09 10:20:18 +00:00
|
|
|
pMachineProfile->m_iTotalPlaySeconds += iPlaySeconds;
|
|
|
|
|
pMachineProfile->m_iTotalPlays++;
|
|
|
|
|
|
2004-03-20 19:15:06 +00:00
|
|
|
FOREACH_HumanPlayer( p )
|
2003-12-08 04:02:43 +00:00
|
|
|
{
|
2004-03-20 19:15:06 +00:00
|
|
|
Profile* pPlayerProfile = PROFILEMAN->GetProfile( p );
|
2003-12-08 06:41:30 +00:00
|
|
|
if( pPlayerProfile )
|
2003-12-09 10:20:18 +00:00
|
|
|
{
|
2003-12-08 06:41:30 +00:00
|
|
|
pPlayerProfile->m_iTotalPlaySeconds += iPlaySeconds;
|
|
|
|
|
pPlayerProfile->m_iTotalPlays++;
|
2004-02-22 02:16:02 +00:00
|
|
|
}
|
2004-08-29 19:10:25 +00:00
|
|
|
}
|
2004-01-05 20:09:59 +00:00
|
|
|
|
2003-12-07 20:29:42 +00:00
|
|
|
BOOKKEEPER->WriteToDisk();
|
2004-02-08 01:05:53 +00:00
|
|
|
|
2004-03-13 19:20:24 +00:00
|
|
|
FOREACH_HumanPlayer( pn )
|
2004-02-08 01:05:53 +00:00
|
|
|
{
|
2005-05-09 08:44:01 +00:00
|
|
|
if( !PROFILEMAN->IsPersistentProfile(pn) )
|
2004-03-13 19:20:24 +00:00
|
|
|
continue;
|
|
|
|
|
|
2005-02-07 03:39:51 +00:00
|
|
|
bool bWasMemoryCard = PROFILEMAN->ProfileWasLoadedFromMemoryCard(pn);
|
|
|
|
|
if( bWasMemoryCard )
|
2005-01-28 00:12:09 +00:00
|
|
|
MEMCARDMAN->MountCard( pn );
|
2005-01-28 00:04:22 +00:00
|
|
|
PROFILEMAN->SaveProfile( pn );
|
2005-02-07 03:39:51 +00:00
|
|
|
if( bWasMemoryCard )
|
|
|
|
|
MEMCARDMAN->UnmountCard( pn );
|
2005-01-28 00:04:22 +00:00
|
|
|
|
2004-03-13 19:20:24 +00:00
|
|
|
PROFILEMAN->UnloadProfile( pn );
|
2004-02-08 01:05:53 +00:00
|
|
|
}
|
|
|
|
|
|
2005-01-28 00:04:22 +00:00
|
|
|
PROFILEMAN->SaveMachineProfile();
|
|
|
|
|
|
2004-08-29 19:10:25 +00:00
|
|
|
// make sure we don't execute EndGame twice.
|
|
|
|
|
m_timeGameStarted.SetZero();
|
2003-02-03 05:53:59 +00:00
|
|
|
}
|
2003-01-26 02:21:47 +00:00
|
|
|
|
2005-02-23 03:40:47 +00:00
|
|
|
static int GetNumStagesForCurrentSong()
|
|
|
|
|
{
|
|
|
|
|
int iNumStagesOfThisSong = 1;
|
|
|
|
|
if( GAMESTATE->m_pCurSong )
|
|
|
|
|
iNumStagesOfThisSong = SongManager::GetNumStagesForSong( GAMESTATE->m_pCurSong );
|
|
|
|
|
else if( GAMESTATE->m_pCurCourse )
|
|
|
|
|
iNumStagesOfThisSong = 1;
|
|
|
|
|
else
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
ASSERT( iNumStagesOfThisSong >= 1 && iNumStagesOfThisSong <= 3 );
|
|
|
|
|
|
|
|
|
|
/* Never increment more than one past final stage. That is, if the current
|
|
|
|
|
* stage is the final stage, and we picked a stage that takes two songs, it
|
|
|
|
|
* only counts as one stage (so it doesn't bump us all the way to Ex2).
|
|
|
|
|
* One case where this happens is a long/marathon extra stage. Another is
|
|
|
|
|
* if a long/marathon song is selected explicitly in the theme with a GameCommand,
|
|
|
|
|
* and PREFSMAN->m_iNumArcadeStages is less than the number of stages that
|
|
|
|
|
* song takes. */
|
2005-04-28 08:27:40 +00:00
|
|
|
int iNumStagesLeft = PREFSMAN->m_iSongsPerPlay - GAMESTATE->m_iCurrentStageIndex;
|
2005-02-23 03:40:47 +00:00
|
|
|
iNumStagesOfThisSong = min( iNumStagesOfThisSong, iNumStagesLeft );
|
|
|
|
|
iNumStagesOfThisSong = max( iNumStagesOfThisSong, 1 );
|
|
|
|
|
|
|
|
|
|
return iNumStagesOfThisSong;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Called by ScreenGameplay. Set the length of the current song. */
|
|
|
|
|
void GameState::BeginStage()
|
|
|
|
|
{
|
|
|
|
|
if( m_bDemonstrationOrJukebox )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* This should only be called once per stage. */
|
|
|
|
|
if( m_iNumStagesOfThisSong != 0 )
|
|
|
|
|
LOG->Warn( "XXX: m_iNumStagesOfThisSong == %i?", m_iNumStagesOfThisSong );
|
|
|
|
|
|
|
|
|
|
/* Finish the last stage (if any), if we havn't already. (For example, we might
|
|
|
|
|
* have, for some reason, gone from gameplay to evaluation straight back to gameplay.) */
|
|
|
|
|
FinishStage();
|
|
|
|
|
|
2005-02-23 04:46:05 +00:00
|
|
|
GAMESTATE->ResetStageStatistics();
|
|
|
|
|
|
2005-02-23 03:40:47 +00:00
|
|
|
m_iNumStagesOfThisSong = GetNumStagesForCurrentSong();
|
|
|
|
|
ASSERT( m_iNumStagesOfThisSong != -1 );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GameState::CancelStage()
|
|
|
|
|
{
|
|
|
|
|
m_iNumStagesOfThisSong = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2005-02-23 19:18:11 +00:00
|
|
|
void GameState::CommitStageStats()
|
|
|
|
|
{
|
|
|
|
|
/* Don't commit stats twice. */
|
|
|
|
|
if( m_bStatsCommitted || m_bDemonstrationOrJukebox )
|
|
|
|
|
return;
|
|
|
|
|
m_bStatsCommitted = true;
|
|
|
|
|
|
|
|
|
|
STATSMAN->CommitStatsToProfiles();
|
|
|
|
|
}
|
|
|
|
|
|
2005-02-23 03:40:47 +00:00
|
|
|
/* Called by ScreenSelectMusic (etc). Increment the stage counter if we just played a
|
|
|
|
|
* song. Might be called more than once. */
|
|
|
|
|
void GameState::FinishStage()
|
|
|
|
|
{
|
|
|
|
|
/* If m_iNumStagesOfThisSong is 0, we've been called more than once before calling
|
|
|
|
|
* BeginStage. This can happen when backing out of the player options screen. */
|
|
|
|
|
if( m_iNumStagesOfThisSong == 0 )
|
|
|
|
|
return;
|
|
|
|
|
|
2005-02-23 19:18:11 +00:00
|
|
|
/* If we havn't committed stats yet, do so. */
|
2005-08-28 18:29:01 +00:00
|
|
|
if( !m_bMultiplayer ) // no saved stats in multiplayer
|
|
|
|
|
CommitStageStats();
|
2005-02-23 19:18:11 +00:00
|
|
|
|
2005-11-02 20:02:47 +00:00
|
|
|
RestoreSelectedOptions();
|
|
|
|
|
|
2005-02-23 19:18:11 +00:00
|
|
|
m_bStatsCommitted = false;
|
|
|
|
|
|
2005-02-23 03:40:47 +00:00
|
|
|
// Increment the stage counter.
|
|
|
|
|
ASSERT( m_iNumStagesOfThisSong >= 1 && m_iNumStagesOfThisSong <= 3 );
|
|
|
|
|
const int iOldStageIndex = m_iCurrentStageIndex;
|
|
|
|
|
m_iCurrentStageIndex += m_iNumStagesOfThisSong;
|
|
|
|
|
|
|
|
|
|
m_iNumStagesOfThisSong = 0;
|
|
|
|
|
|
|
|
|
|
if( m_bDemonstrationOrJukebox )
|
|
|
|
|
return;
|
|
|
|
|
|
2005-04-05 08:30:57 +00:00
|
|
|
if( GAMESTATE->IsEventMode() )
|
2005-02-23 03:40:47 +00:00
|
|
|
{
|
|
|
|
|
const int iSaveProfileEvery = 3;
|
|
|
|
|
if( iOldStageIndex/iSaveProfileEvery < m_iCurrentStageIndex/iSaveProfileEvery )
|
|
|
|
|
{
|
|
|
|
|
LOG->Trace( "Played %i stages; saving profiles ...", iSaveProfileEvery );
|
|
|
|
|
PROFILEMAN->SaveAllProfiles();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-03-30 03:55:54 +00:00
|
|
|
void GameState::SaveCurrentSettingsToProfile( PlayerNumber pn )
|
|
|
|
|
{
|
2005-05-09 08:44:01 +00:00
|
|
|
if( !PROFILEMAN->IsPersistentProfile(pn) )
|
2004-03-30 03:55:54 +00:00
|
|
|
return;
|
2004-08-30 23:59:02 +00:00
|
|
|
if( m_bDemonstrationOrJukebox )
|
|
|
|
|
return;
|
2004-03-30 03:55:54 +00:00
|
|
|
|
|
|
|
|
Profile* pProfile = PROFILEMAN->GetProfile(pn);
|
|
|
|
|
|
2004-12-20 06:25:59 +00:00
|
|
|
pProfile->SetDefaultModifiers( this->m_pCurGame, m_pPlayerState[pn]->m_PlayerOptions.GetSavedPrefsString() );
|
2005-01-29 20:46:08 +00:00
|
|
|
if( IsSongSort(m_PreferredSortOrder) )
|
|
|
|
|
pProfile->m_SortOrder = m_PreferredSortOrder;
|
2004-03-30 03:55:54 +00:00
|
|
|
if( m_PreferredDifficulty[pn] != DIFFICULTY_INVALID )
|
|
|
|
|
pProfile->m_LastDifficulty = m_PreferredDifficulty[pn];
|
2004-06-04 02:05:56 +00:00
|
|
|
if( m_PreferredCourseDifficulty[pn] != DIFFICULTY_INVALID )
|
2004-03-30 03:55:54 +00:00
|
|
|
pProfile->m_LastCourseDifficulty = m_PreferredCourseDifficulty[pn];
|
2004-05-26 05:50:22 +00:00
|
|
|
if( m_pPreferredSong )
|
2004-08-14 06:41:24 +00:00
|
|
|
pProfile->m_lastSong.FromSong( m_pPreferredSong );
|
2004-05-26 05:50:22 +00:00
|
|
|
if( m_pPreferredCourse )
|
2004-08-14 06:41:24 +00:00
|
|
|
pProfile->m_lastCourse.FromCourse( m_pPreferredCourse );
|
2004-03-30 03:55:54 +00:00
|
|
|
}
|
|
|
|
|
|
2003-02-26 23:26:57 +00:00
|
|
|
void GameState::Update( float fDelta )
|
|
|
|
|
{
|
2004-05-24 06:10:11 +00:00
|
|
|
FOREACH_PlayerNumber( p )
|
2003-04-07 03:25:44 +00:00
|
|
|
{
|
2005-04-07 18:32:19 +00:00
|
|
|
m_pPlayerState[p]->Update( fDelta );
|
2003-04-02 21:57:05 +00:00
|
|
|
|
2005-04-09 09:34:54 +00:00
|
|
|
if( !m_bGoalComplete[p] && IsGoalComplete(p) )
|
|
|
|
|
{
|
|
|
|
|
m_bGoalComplete[p] = true;
|
2005-08-14 07:29:48 +00:00
|
|
|
MESSAGEMAN->Broadcast( (Message)(Message_GoalCompleteP1+p) );
|
2005-04-09 09:34:54 +00:00
|
|
|
}
|
2003-04-07 03:25:44 +00:00
|
|
|
}
|
|
|
|
|
}
|
2003-02-26 23:26:57 +00:00
|
|
|
|
2005-10-28 01:44:19 +00:00
|
|
|
void GameState::SetCurGame( const Game *pGame )
|
|
|
|
|
{
|
|
|
|
|
m_pCurGame.Set( pGame );
|
2006-01-22 01:00:06 +00:00
|
|
|
RString sGame = pGame ? RString(pGame->m_szName) : RString();
|
2005-11-09 10:55:30 +00:00
|
|
|
PREFSMAN->SetCurrentGame( sGame );
|
2005-10-28 01:44:19 +00:00
|
|
|
}
|
|
|
|
|
|
2003-02-07 23:49:07 +00:00
|
|
|
const float GameState::MUSIC_SECONDS_INVALID = -5000.0f;
|
|
|
|
|
|
2002-07-29 03:06:55 +00:00
|
|
|
void GameState::ResetMusicStatistics()
|
|
|
|
|
{
|
2004-01-29 20:58:11 +00:00
|
|
|
m_fMusicSeconds = 0; // MUSIC_SECONDS_INVALID;
|
2002-07-29 03:06:55 +00:00
|
|
|
m_fSongBeat = 0;
|
2006-04-09 15:54:53 +00:00
|
|
|
m_fSongBeatNoOffset = 0;
|
2002-07-29 03:06:55 +00:00
|
|
|
m_fCurBPS = 10;
|
|
|
|
|
m_bFreeze = false;
|
2004-10-16 01:29:25 +00:00
|
|
|
Actor::SetBGMTime( 0, 0 );
|
2003-07-03 06:38:57 +00:00
|
|
|
}
|
2003-05-13 13:35:32 +00:00
|
|
|
|
2003-07-03 06:38:57 +00:00
|
|
|
void GameState::ResetStageStatistics()
|
|
|
|
|
{
|
2005-02-16 03:25:45 +00:00
|
|
|
StageStats OldStats = STATSMAN->m_CurStageStats;
|
|
|
|
|
STATSMAN->m_CurStageStats = StageStats();
|
2003-12-08 04:39:29 +00:00
|
|
|
if( PREFSMAN->m_bComboContinuesBetweenSongs )
|
|
|
|
|
{
|
|
|
|
|
if( GetStageIndex() == 0 )
|
|
|
|
|
{
|
2004-05-24 06:10:11 +00:00
|
|
|
FOREACH_PlayerNumber( p )
|
2003-12-08 04:39:29 +00:00
|
|
|
{
|
2004-12-20 10:47:41 +00:00
|
|
|
Profile* pProfile = PROFILEMAN->GetProfile(p);
|
2005-05-01 06:42:30 +00:00
|
|
|
STATSMAN->m_CurStageStats.m_player[p].iCurCombo = pProfile->m_iCurrentCombo;
|
2003-12-08 04:39:29 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else // GetStageIndex() > 0
|
|
|
|
|
{
|
2004-12-20 10:47:41 +00:00
|
|
|
FOREACH_PlayerNumber( p )
|
|
|
|
|
{
|
2005-02-16 03:25:45 +00:00
|
|
|
STATSMAN->m_CurStageStats.m_player[p].iCurCombo = OldStats.m_player[p].iCurCombo;
|
2004-12-20 10:47:41 +00:00
|
|
|
}
|
2003-12-08 04:39:29 +00:00
|
|
|
}
|
|
|
|
|
}
|
2003-09-06 04:18:08 +00:00
|
|
|
|
2003-07-03 06:38:57 +00:00
|
|
|
RemoveAllActiveAttacks();
|
2006-01-13 06:35:46 +00:00
|
|
|
FOREACH_PlayerNumber( p )
|
|
|
|
|
m_pPlayerState[p]->RemoveAllInventory();
|
2003-05-13 13:35:32 +00:00
|
|
|
m_fOpponentHealthPercent = 1;
|
2003-07-03 06:38:57 +00:00
|
|
|
m_fTugLifePercentP1 = 0.5f;
|
2004-05-24 06:10:11 +00:00
|
|
|
FOREACH_PlayerNumber( p )
|
2003-12-07 20:29:42 +00:00
|
|
|
{
|
2004-12-20 06:25:59 +00:00
|
|
|
m_pPlayerState[p]->m_fSuperMeter = 0;
|
|
|
|
|
m_pPlayerState[p]->m_HealthState = PlayerState::ALIVE;
|
2004-01-12 03:47:55 +00:00
|
|
|
|
2004-12-20 06:25:59 +00:00
|
|
|
m_pPlayerState[p]->m_iLastPositiveSumOfAttackLevels = 0;
|
|
|
|
|
m_pPlayerState[p]->m_fSecondsUntilAttacksPhasedOut = 0; // PlayerAI not affected
|
2005-04-09 09:34:54 +00:00
|
|
|
|
|
|
|
|
m_bGoalComplete[p] = false;
|
2003-12-07 20:29:42 +00:00
|
|
|
}
|
2004-03-07 04:34:49 +00:00
|
|
|
|
|
|
|
|
|
2004-08-30 06:07:14 +00:00
|
|
|
FOREACH_PlayerNumber( p )
|
2004-03-07 04:34:49 +00:00
|
|
|
{
|
2004-08-30 06:07:14 +00:00
|
|
|
m_vLastPerDifficultyAwards[p].clear();
|
|
|
|
|
m_vLastPeakComboAwards[p].clear();
|
2004-03-07 04:34:49 +00:00
|
|
|
}
|
2005-03-11 07:22:37 +00:00
|
|
|
|
|
|
|
|
// Reset the round seed. Do this here and not in FinishStage so that players
|
|
|
|
|
// get new shuffle patterns if they Back out of gameplay and play again.
|
2005-03-11 18:09:34 +00:00
|
|
|
GAMESTATE->m_iStageSeed = rand();
|
2005-05-19 23:29:39 +00:00
|
|
|
|
2006-02-06 01:23:25 +00:00
|
|
|
AdjustSync::ResetOriginalSyncData();
|
2002-07-29 03:06:55 +00:00
|
|
|
}
|
|
|
|
|
|
2004-01-18 04:43:56 +00:00
|
|
|
void GameState::UpdateSongPosition( float fPositionSeconds, const TimingData &timing, const RageTimer ×tamp )
|
2003-02-06 17:40:06 +00:00
|
|
|
{
|
2004-01-18 04:43:56 +00:00
|
|
|
if( !timestamp.IsZero() )
|
|
|
|
|
m_LastBeatUpdate = timestamp;
|
|
|
|
|
else
|
|
|
|
|
m_LastBeatUpdate.Touch();
|
|
|
|
|
timing.GetBeatAndBPSFromElapsedTime( fPositionSeconds, m_fSongBeat, m_fCurBPS, m_bFreeze );
|
2004-06-16 00:38:31 +00:00
|
|
|
ASSERT_M( m_fSongBeat > -2000, ssprintf("%f %f", m_fSongBeat, fPositionSeconds) );
|
2004-01-12 01:10:25 +00:00
|
|
|
|
2004-01-18 04:43:56 +00:00
|
|
|
m_fMusicSeconds = fPositionSeconds;
|
2005-05-10 03:37:30 +00:00
|
|
|
m_fLightSongBeat = timing.GetBeatFromElapsedTime( fPositionSeconds + g_fLightsAheadSeconds );
|
2004-07-07 21:17:47 +00:00
|
|
|
|
2006-04-09 15:54:53 +00:00
|
|
|
m_fSongBeatNoOffset = timing.GetBeatFromElapsedTimeNoOffset( fPositionSeconds );
|
|
|
|
|
Actor::SetBGMTime( fPositionSeconds, m_fSongBeatNoOffset );
|
2004-07-07 21:17:47 +00:00
|
|
|
|
2003-05-27 05:27:38 +00:00
|
|
|
// LOG->Trace( "m_fMusicSeconds = %f, m_fSongBeat = %f, m_fCurBPS = %f, m_bFreeze = %f", m_fMusicSeconds, m_fSongBeat, m_fCurBPS, m_bFreeze );
|
2003-02-06 17:40:06 +00:00
|
|
|
}
|
|
|
|
|
|
2003-10-23 06:16:29 +00:00
|
|
|
float GameState::GetSongPercent( float beat ) const
|
|
|
|
|
{
|
|
|
|
|
/* 0 = first step; 1 = last step */
|
|
|
|
|
return (beat - m_pCurSong->m_fFirstBeat) / m_pCurSong->m_fLastBeat;
|
|
|
|
|
}
|
|
|
|
|
|
2004-01-22 02:15:55 +00:00
|
|
|
int GameState::GetStageIndex() const
|
2002-07-23 01:41:40 +00:00
|
|
|
{
|
|
|
|
|
return m_iCurrentStageIndex;
|
|
|
|
|
}
|
|
|
|
|
|
2004-01-22 02:15:55 +00:00
|
|
|
int GameState::GetNumStagesLeft() const
|
2003-02-10 05:30:12 +00:00
|
|
|
{
|
2004-01-22 02:15:55 +00:00
|
|
|
if( IsExtraStage() || IsExtraStage2() )
|
2003-02-12 20:56:19 +00:00
|
|
|
return 1;
|
2005-04-05 08:30:57 +00:00
|
|
|
if( GAMESTATE->IsEventMode() )
|
2003-02-14 08:15:42 +00:00
|
|
|
return 999;
|
2005-04-28 08:27:40 +00:00
|
|
|
return PREFSMAN->m_iSongsPerPlay - m_iCurrentStageIndex;
|
2003-02-10 05:30:12 +00:00
|
|
|
}
|
|
|
|
|
|
2004-01-22 02:15:55 +00:00
|
|
|
bool GameState::IsFinalStage() const
|
2002-07-23 01:41:40 +00:00
|
|
|
{
|
2005-04-05 08:30:57 +00:00
|
|
|
if( GAMESTATE->IsEventMode() )
|
2002-07-23 01:41:40 +00:00
|
|
|
return false;
|
2004-01-22 03:11:40 +00:00
|
|
|
|
2004-03-21 18:59:55 +00:00
|
|
|
if( this->IsCourseMode() )
|
|
|
|
|
return true;
|
|
|
|
|
|
2004-01-22 03:11:40 +00:00
|
|
|
/* This changes dynamically on ScreenSelectMusic as the wheel turns. */
|
2004-05-11 02:16:23 +00:00
|
|
|
int iPredictedStageForCurSong = GetNumStagesForCurrentSong();
|
|
|
|
|
if( iPredictedStageForCurSong == -1 )
|
|
|
|
|
iPredictedStageForCurSong = 1;
|
2005-04-28 08:27:40 +00:00
|
|
|
return m_iCurrentStageIndex + iPredictedStageForCurSong == PREFSMAN->m_iSongsPerPlay;
|
2002-07-23 01:41:40 +00:00
|
|
|
}
|
|
|
|
|
|
2004-01-22 02:15:55 +00:00
|
|
|
bool GameState::IsExtraStage() const
|
2002-07-23 01:41:40 +00:00
|
|
|
{
|
2005-04-05 08:30:57 +00:00
|
|
|
if( GAMESTATE->IsEventMode() )
|
2002-07-23 01:41:40 +00:00
|
|
|
return false;
|
2005-04-28 08:27:40 +00:00
|
|
|
return m_iCurrentStageIndex == PREFSMAN->m_iSongsPerPlay;
|
2002-07-23 01:41:40 +00:00
|
|
|
}
|
|
|
|
|
|
2004-01-22 02:15:55 +00:00
|
|
|
bool GameState::IsExtraStage2() const
|
2002-07-23 01:41:40 +00:00
|
|
|
{
|
2005-04-05 08:30:57 +00:00
|
|
|
if( GAMESTATE->IsEventMode() )
|
2002-07-23 01:41:40 +00:00
|
|
|
return false;
|
2005-04-28 08:27:40 +00:00
|
|
|
return m_iCurrentStageIndex == PREFSMAN->m_iSongsPerPlay+1;
|
2002-07-23 01:41:40 +00:00
|
|
|
}
|
|
|
|
|
|
2005-05-06 10:48:32 +00:00
|
|
|
Stage GameState::GetCurrentStage() const
|
2002-07-23 01:41:40 +00:00
|
|
|
{
|
2005-05-06 10:48:32 +00:00
|
|
|
if( m_bDemonstrationOrJukebox ) return STAGE_DEMO;
|
2005-03-27 10:16:47 +00:00
|
|
|
// "event" has precedence
|
2005-05-06 10:48:32 +00:00
|
|
|
else if( GAMESTATE->IsEventMode() ) return STAGE_EVENT;
|
|
|
|
|
else if( m_PlayMode == PLAY_MODE_ONI ) return STAGE_ONI;
|
|
|
|
|
else if( m_PlayMode == PLAY_MODE_NONSTOP ) return STAGE_NONSTOP;
|
|
|
|
|
else if( m_PlayMode == PLAY_MODE_ENDLESS ) return STAGE_ENDLESS;
|
|
|
|
|
else if( IsFinalStage() ) return STAGE_FINAL;
|
|
|
|
|
else if( IsExtraStage() ) return STAGE_EXTRA1;
|
|
|
|
|
else if( IsExtraStage2() ) return STAGE_EXTRA2;
|
|
|
|
|
else return (Stage)(STAGE_1+m_iCurrentStageIndex);
|
2002-07-23 01:41:40 +00:00
|
|
|
}
|
|
|
|
|
|
2006-01-13 21:49:35 +00:00
|
|
|
// Return true if it's possible for GetCurrentStage() to return the given stage.
|
2005-09-08 05:52:37 +00:00
|
|
|
bool GameState::IsStagePossible( Stage s ) const
|
2003-10-09 04:20:24 +00:00
|
|
|
{
|
2005-09-08 19:59:07 +00:00
|
|
|
/* HACK: Find out what the stage would be without long or marathon.
|
|
|
|
|
* This should never change during a screen. */
|
|
|
|
|
Song *pSong = GAMESTATE->m_pCurSong;
|
|
|
|
|
GAMESTATE->m_pCurSong.SetWithoutBroadcast( NULL );
|
|
|
|
|
Stage actual = GetCurrentStage();
|
|
|
|
|
GAMESTATE->m_pCurSong.SetWithoutBroadcast( pSong );
|
|
|
|
|
|
|
|
|
|
/* Check long/marathon, which can change the stage to FINAL. */
|
|
|
|
|
if( s == STAGE_FINAL && actual >= STAGE_1 && actual <= STAGE_FINAL )
|
|
|
|
|
{
|
|
|
|
|
Stage max_actual = actual;
|
|
|
|
|
if( PREFSMAN->m_fMarathonVerSongSeconds < 9999 )
|
|
|
|
|
enum_add( max_actual, +2 );
|
|
|
|
|
else if( PREFSMAN->m_fLongVerSongSeconds < 9999 )
|
|
|
|
|
enum_add( max_actual, +1 );
|
|
|
|
|
|
|
|
|
|
if( max_actual >= STAGE_FINAL )
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return s == actual;
|
2003-10-09 04:20:24 +00:00
|
|
|
}
|
|
|
|
|
|
2004-01-22 02:15:55 +00:00
|
|
|
int GameState::GetCourseSongIndex() const
|
2003-02-14 21:42:44 +00:00
|
|
|
{
|
|
|
|
|
int iSongIndex = 0;
|
2003-02-25 21:23:21 +00:00
|
|
|
/* iSongsPlayed includes the current song, so it's 1-based; subtract one. */
|
2005-01-03 21:16:20 +00:00
|
|
|
FOREACH_EnabledPlayer( pn )
|
2005-02-16 03:25:45 +00:00
|
|
|
iSongIndex = max( iSongIndex, STATSMAN->m_CurStageStats.m_player[pn].iSongsPlayed-1 );
|
2003-02-14 21:42:44 +00:00
|
|
|
return iSongIndex;
|
|
|
|
|
}
|
|
|
|
|
|
2006-04-29 02:03:08 +00:00
|
|
|
/* Hack: when we're loading a new course song, we want to display the new song number, even
|
|
|
|
|
* though we havn't started that song yet. */
|
|
|
|
|
int GameState::GetLoadingCourseSongIndex() const
|
|
|
|
|
{
|
|
|
|
|
int iIndex = GetCourseSongIndex();
|
|
|
|
|
if( m_bLoadingNextSong )
|
|
|
|
|
++iIndex;
|
|
|
|
|
return iIndex;
|
|
|
|
|
}
|
|
|
|
|
|
2006-01-08 22:58:43 +00:00
|
|
|
static LocalizedString PLAYER1 ("GameState","Player 1");
|
|
|
|
|
static LocalizedString PLAYER2 ("GameState","Player 2");
|
|
|
|
|
static LocalizedString CPU ("GameState","CPU");
|
2006-01-22 01:00:06 +00:00
|
|
|
RString GameState::GetPlayerDisplayName( PlayerNumber pn ) const
|
2004-05-16 02:51:55 +00:00
|
|
|
{
|
|
|
|
|
ASSERT( IsPlayerEnabled(pn) );
|
2006-01-08 22:58:43 +00:00
|
|
|
const LocalizedString *pDefaultNames[] = { &PLAYER1, &PLAYER2 };
|
2004-05-16 02:51:55 +00:00
|
|
|
if( IsHumanPlayer(pn) )
|
|
|
|
|
{
|
|
|
|
|
if( !PROFILEMAN->GetPlayerName(pn).empty() )
|
|
|
|
|
return PROFILEMAN->GetPlayerName(pn);
|
|
|
|
|
else
|
2006-01-12 19:40:41 +00:00
|
|
|
return pDefaultNames[pn]->GetValue();
|
2004-05-16 02:51:55 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2006-01-12 19:40:41 +00:00
|
|
|
return CPU.GetValue();
|
2004-05-16 02:51:55 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2003-11-10 16:48:22 +00:00
|
|
|
bool GameState::PlayersCanJoin() const
|
|
|
|
|
{
|
2004-06-28 07:26:00 +00:00
|
|
|
return GetNumSidesJoined() == 0 || this->m_pCurStyle == NULL; // selecting a style finalizes the players
|
2004-03-30 08:03:00 +00:00
|
|
|
}
|
|
|
|
|
|
2003-11-10 16:48:22 +00:00
|
|
|
int GameState::GetNumSidesJoined() const
|
|
|
|
|
{
|
|
|
|
|
int iNumSidesJoined = 0;
|
2005-08-14 04:33:13 +00:00
|
|
|
FOREACH_PlayerNumber( p )
|
|
|
|
|
if( m_bSideIsJoined[p] )
|
2003-11-10 16:48:22 +00:00
|
|
|
iNumSidesJoined++; // left side, and right side
|
|
|
|
|
return iNumSidesJoined;
|
|
|
|
|
}
|
|
|
|
|
|
2004-07-25 17:07:32 +00:00
|
|
|
const Game* GameState::GetCurrentGame()
|
2002-07-23 01:41:40 +00:00
|
|
|
{
|
2004-07-25 04:27:20 +00:00
|
|
|
ASSERT( m_pCurGame != NULL ); // the game must be set before calling this
|
|
|
|
|
return m_pCurGame;
|
2002-07-23 01:41:40 +00:00
|
|
|
}
|
|
|
|
|
|
2004-06-28 07:26:00 +00:00
|
|
|
const Style* GameState::GetCurrentStyle() const
|
2002-07-23 01:41:40 +00:00
|
|
|
{
|
2004-06-28 07:26:00 +00:00
|
|
|
return m_pCurStyle;
|
2002-07-23 01:41:40 +00:00
|
|
|
}
|
|
|
|
|
|
2003-03-02 01:43:33 +00:00
|
|
|
|
2004-01-22 02:15:55 +00:00
|
|
|
bool GameState::IsPlayerEnabled( PlayerNumber pn ) const
|
2002-07-23 01:41:40 +00:00
|
|
|
{
|
2003-05-13 05:24:30 +00:00
|
|
|
// In rave, all players are present. Non-human players are CPU controlled.
|
2003-08-19 04:27:50 +00:00
|
|
|
switch( m_PlayMode )
|
|
|
|
|
{
|
|
|
|
|
case PLAY_MODE_BATTLE:
|
|
|
|
|
case PLAY_MODE_RAVE:
|
2003-04-07 05:14:27 +00:00
|
|
|
return true;
|
2003-08-19 04:27:50 +00:00
|
|
|
}
|
|
|
|
|
|
2003-04-07 03:25:44 +00:00
|
|
|
return IsHumanPlayer( pn );
|
|
|
|
|
}
|
2002-07-23 01:41:40 +00:00
|
|
|
|
2005-08-23 20:55:58 +00:00
|
|
|
bool GameState::IsMultiPlayerEnabled( MultiPlayer mp ) const
|
|
|
|
|
{
|
2006-04-21 00:43:32 +00:00
|
|
|
return m_MultiPlayerStatus[ mp ] == MultiPlayerStatus_Joined;
|
2005-08-23 20:55:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool GameState::IsPlayerEnabled( const PlayerState* pPlayerState ) const
|
|
|
|
|
{
|
|
|
|
|
if( pPlayerState->m_mp != MultiPlayer_INVALID )
|
2006-04-21 00:43:32 +00:00
|
|
|
return IsMultiPlayerEnabled( pPlayerState->m_mp );
|
2005-08-23 20:55:58 +00:00
|
|
|
if( pPlayerState->m_PlayerNumber != PLAYER_INVALID )
|
|
|
|
|
return IsPlayerEnabled( pPlayerState->m_PlayerNumber );
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2004-01-22 02:15:55 +00:00
|
|
|
int GameState::GetNumPlayersEnabled() const
|
|
|
|
|
{
|
|
|
|
|
int count = 0;
|
2005-01-03 21:16:20 +00:00
|
|
|
FOREACH_EnabledPlayer( pn )
|
|
|
|
|
count++;
|
2004-01-22 02:15:55 +00:00
|
|
|
return count;
|
|
|
|
|
}
|
|
|
|
|
|
2004-03-20 17:53:04 +00:00
|
|
|
bool GameState::PlayerUsingBothSides() const
|
|
|
|
|
{
|
2005-01-04 01:47:11 +00:00
|
|
|
ASSERT( this->GetCurrentStyle() != NULL );
|
2004-11-07 05:49:06 +00:00
|
|
|
return this->GetCurrentStyle()->m_StyleType == ONE_PLAYER_TWO_SIDES;
|
2004-03-20 17:53:04 +00:00
|
|
|
}
|
|
|
|
|
|
2004-01-22 02:15:55 +00:00
|
|
|
bool GameState::IsHumanPlayer( PlayerNumber pn ) const
|
2003-04-07 03:25:44 +00:00
|
|
|
{
|
2004-06-28 07:26:00 +00:00
|
|
|
if( m_pCurStyle == NULL ) // no style chosen
|
2004-06-27 06:52:49 +00:00
|
|
|
{
|
2003-11-10 16:48:22 +00:00
|
|
|
if( this->PlayersCanJoin() )
|
2003-03-16 22:35:04 +00:00
|
|
|
return m_bSideIsJoined[pn]; // only allow input from sides that have already joined
|
|
|
|
|
else
|
|
|
|
|
return true; // if we can't join, then we're on a screen like MusicScroll or GameOver
|
2004-06-27 06:52:49 +00:00
|
|
|
}
|
2003-03-09 03:28:34 +00:00
|
|
|
|
2004-06-28 07:26:00 +00:00
|
|
|
switch( GetCurrentStyle()->m_StyleType )
|
2002-08-13 23:26:46 +00:00
|
|
|
{
|
2004-11-07 05:49:06 +00:00
|
|
|
case TWO_PLAYERS_TWO_SIDES:
|
2002-08-13 23:26:46 +00:00
|
|
|
return true;
|
2004-11-07 05:49:06 +00:00
|
|
|
case ONE_PLAYER_ONE_SIDE:
|
|
|
|
|
case ONE_PLAYER_TWO_SIDES:
|
2002-08-20 21:00:56 +00:00
|
|
|
return pn == m_MasterPlayerNumber;
|
2002-08-13 23:26:46 +00:00
|
|
|
default:
|
2002-08-20 21:00:56 +00:00
|
|
|
ASSERT(0); // invalid style type
|
2002-08-13 23:26:46 +00:00
|
|
|
return false;
|
|
|
|
|
}
|
2002-07-29 03:06:55 +00:00
|
|
|
}
|
|
|
|
|
|
2004-03-20 17:45:34 +00:00
|
|
|
int GameState::GetNumHumanPlayers() const
|
|
|
|
|
{
|
|
|
|
|
int count = 0;
|
2005-01-03 21:16:20 +00:00
|
|
|
FOREACH_HumanPlayer( pn )
|
|
|
|
|
count++;
|
2004-03-20 17:45:34 +00:00
|
|
|
return count;
|
|
|
|
|
}
|
|
|
|
|
|
2004-01-22 02:15:55 +00:00
|
|
|
PlayerNumber GameState::GetFirstHumanPlayer() const
|
2003-04-07 21:24:14 +00:00
|
|
|
{
|
2005-01-03 21:16:20 +00:00
|
|
|
FOREACH_HumanPlayer( pn )
|
|
|
|
|
return pn;
|
2003-04-07 21:24:14 +00:00
|
|
|
ASSERT(0); // there must be at least 1 human player
|
|
|
|
|
return PLAYER_INVALID;
|
|
|
|
|
}
|
|
|
|
|
|
2004-12-01 20:42:15 +00:00
|
|
|
PlayerNumber GameState::GetFirstDisabledPlayer() const
|
|
|
|
|
{
|
2005-01-03 21:16:20 +00:00
|
|
|
FOREACH_PlayerNumber( pn )
|
|
|
|
|
if( !IsPlayerEnabled(pn) )
|
|
|
|
|
return pn;
|
2004-12-01 20:42:15 +00:00
|
|
|
return PLAYER_INVALID;
|
|
|
|
|
}
|
|
|
|
|
|
2004-01-22 02:15:55 +00:00
|
|
|
bool GameState::IsCpuPlayer( PlayerNumber pn ) const
|
2003-04-07 03:25:44 +00:00
|
|
|
{
|
|
|
|
|
return IsPlayerEnabled(pn) && !IsHumanPlayer(pn);
|
|
|
|
|
}
|
|
|
|
|
|
2004-01-22 02:15:55 +00:00
|
|
|
bool GameState::AnyPlayersAreCpu() const
|
|
|
|
|
{
|
2005-01-03 21:16:20 +00:00
|
|
|
FOREACH_CpuPlayer( pn )
|
|
|
|
|
return true;
|
2004-01-22 02:15:55 +00:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2003-04-07 03:25:44 +00:00
|
|
|
|
2003-02-28 07:26:43 +00:00
|
|
|
bool GameState::IsCourseMode() const
|
|
|
|
|
{
|
|
|
|
|
switch(m_PlayMode)
|
|
|
|
|
{
|
|
|
|
|
case PLAY_MODE_ONI:
|
|
|
|
|
case PLAY_MODE_NONSTOP:
|
|
|
|
|
case PLAY_MODE_ENDLESS:
|
|
|
|
|
return true;
|
|
|
|
|
default:
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2003-07-09 20:23:44 +00:00
|
|
|
bool GameState::IsBattleMode() const
|
|
|
|
|
{
|
2004-02-07 22:14:36 +00:00
|
|
|
switch( this->m_PlayMode )
|
2003-07-09 20:23:44 +00:00
|
|
|
{
|
2003-08-19 04:27:50 +00:00
|
|
|
case PLAY_MODE_BATTLE:
|
2003-07-09 20:23:44 +00:00
|
|
|
return true;
|
|
|
|
|
default:
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-07 22:14:36 +00:00
|
|
|
bool GameState::HasEarnedExtraStage() const
|
2003-01-24 02:43:07 +00:00
|
|
|
{
|
2005-04-05 08:30:57 +00:00
|
|
|
if( GAMESTATE->IsEventMode() )
|
2003-02-04 21:44:58 +00:00
|
|
|
return false;
|
|
|
|
|
|
2003-10-17 08:03:46 +00:00
|
|
|
if( !PREFSMAN->m_bAllowExtraStage )
|
|
|
|
|
return false;
|
|
|
|
|
|
2004-06-11 06:05:35 +00:00
|
|
|
if( this->m_PlayMode != PLAY_MODE_REGULAR )
|
2003-02-05 18:24:36 +00:00
|
|
|
return false;
|
2005-06-29 07:57:15 +00:00
|
|
|
|
|
|
|
|
if( m_bBackedOutOfFinalStage )
|
|
|
|
|
return false;
|
2003-02-05 18:24:36 +00:00
|
|
|
|
2005-09-03 04:10:52 +00:00
|
|
|
/* If PickExtraStage, allow EX2 if the chosen song was correct. */
|
|
|
|
|
if( PREFSMAN->m_bPickExtraStage && this->IsExtraStage() )
|
|
|
|
|
{
|
|
|
|
|
Song* pSong;
|
|
|
|
|
Steps* pSteps;
|
|
|
|
|
SONGMAN->GetExtraStageInfo( false, GAMESTATE->GetCurrentStyle(), pSong, pSteps, NULL, NULL );
|
|
|
|
|
ASSERT(pSong);
|
|
|
|
|
|
|
|
|
|
const StageStats &stats = STATSMAN->m_CurStageStats;
|
|
|
|
|
return stats.vpPlayedSongs.size() && stats.vpPlayedSongs.back() == pSong;
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-07 22:14:36 +00:00
|
|
|
if( (this->IsFinalStage() || this->IsExtraStage()) )
|
2003-01-24 02:43:07 +00:00
|
|
|
{
|
2005-01-03 21:16:20 +00:00
|
|
|
FOREACH_EnabledPlayer( pn )
|
2003-01-24 02:43:07 +00:00
|
|
|
{
|
2005-01-03 21:16:20 +00:00
|
|
|
if( this->m_pCurSteps[pn]->GetDifficulty() != DIFFICULTY_HARD &&
|
|
|
|
|
this->m_pCurSteps[pn]->GetDifficulty() != DIFFICULTY_CHALLENGE )
|
2003-02-04 21:44:58 +00:00
|
|
|
continue; /* not hard enough! */
|
|
|
|
|
|
2005-08-14 11:38:31 +00:00
|
|
|
if( STATSMAN->m_CurStageStats.m_player[pn].GetGrade() <= Grade_Tier03 )
|
2003-01-24 02:43:07 +00:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
2003-01-27 02:00:38 +00:00
|
|
|
}
|
|
|
|
|
|
2004-02-07 22:14:36 +00:00
|
|
|
PlayerNumber GameState::GetBestPlayer() const
|
2003-04-15 02:47:24 +00:00
|
|
|
{
|
2005-01-03 21:16:20 +00:00
|
|
|
FOREACH_PlayerNumber( pn )
|
|
|
|
|
if( GetStageResult(pn) == RESULT_WIN )
|
|
|
|
|
return pn;
|
2003-12-02 21:32:04 +00:00
|
|
|
return PLAYER_INVALID; // draw
|
2003-04-15 02:47:24 +00:00
|
|
|
}
|
|
|
|
|
|
2004-02-07 22:14:36 +00:00
|
|
|
StageResult GameState::GetStageResult( PlayerNumber pn ) const
|
2003-04-21 02:41:10 +00:00
|
|
|
{
|
2004-02-07 22:14:36 +00:00
|
|
|
switch( this->m_PlayMode )
|
2003-05-13 13:35:32 +00:00
|
|
|
{
|
2003-08-19 04:27:50 +00:00
|
|
|
case PLAY_MODE_BATTLE:
|
2003-07-03 06:38:57 +00:00
|
|
|
case PLAY_MODE_RAVE:
|
2003-12-02 21:32:04 +00:00
|
|
|
if( fabsf(m_fTugLifePercentP1 - 0.5f) < 0.0001f )
|
|
|
|
|
return RESULT_DRAW;
|
2003-07-03 06:38:57 +00:00
|
|
|
switch( pn )
|
|
|
|
|
{
|
|
|
|
|
case PLAYER_1: return (m_fTugLifePercentP1>=0.5f)?RESULT_WIN:RESULT_LOSE;
|
|
|
|
|
case PLAYER_2: return (m_fTugLifePercentP1<0.5f)?RESULT_WIN:RESULT_LOSE;
|
|
|
|
|
default: ASSERT(0); return RESULT_LOSE;
|
|
|
|
|
}
|
2003-05-13 13:35:32 +00:00
|
|
|
}
|
2003-12-02 21:32:04 +00:00
|
|
|
|
|
|
|
|
StageResult win = RESULT_WIN;
|
2005-01-03 21:16:20 +00:00
|
|
|
FOREACH_PlayerNumber( p )
|
2003-12-02 21:32:04 +00:00
|
|
|
{
|
|
|
|
|
if( p == pn )
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
/* If anyone did just as well, at best it's a draw. */
|
2005-02-16 03:25:45 +00:00
|
|
|
if( STATSMAN->m_CurStageStats.m_player[p].iActualDancePoints == STATSMAN->m_CurStageStats.m_player[pn].iActualDancePoints )
|
2003-12-02 21:32:04 +00:00
|
|
|
win = RESULT_DRAW;
|
|
|
|
|
|
|
|
|
|
/* If anyone did better, we lost. */
|
2005-02-16 03:25:45 +00:00
|
|
|
if( STATSMAN->m_CurStageStats.m_player[p].iActualDancePoints > STATSMAN->m_CurStageStats.m_player[pn].iActualDancePoints )
|
2003-12-02 21:32:04 +00:00
|
|
|
return RESULT_LOSE;
|
|
|
|
|
}
|
|
|
|
|
return win;
|
2003-04-21 02:41:10 +00:00
|
|
|
}
|
|
|
|
|
|
2003-02-24 03:26:00 +00:00
|
|
|
|
2003-03-26 23:08:05 +00:00
|
|
|
|
2005-10-27 07:51:37 +00:00
|
|
|
void GameState::GetDefaultPlayerOptions( PlayerOptions &po )
|
|
|
|
|
{
|
|
|
|
|
po.Init();
|
2005-11-09 10:55:30 +00:00
|
|
|
po.FromString( PREFSMAN->m_sDefaultModifiers );
|
2005-10-27 07:51:37 +00:00
|
|
|
po.FromString( CommonMetrics::DEFAULT_MODIFIERS );
|
2006-02-22 17:15:13 +00:00
|
|
|
if( po.m_sNoteSkin.empty() )
|
2006-05-20 09:00:09 +00:00
|
|
|
po.m_sNoteSkin = NOTESKIN->GAME_BASE_NOTESKIN_NAME;
|
2005-10-27 07:51:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GameState::GetDefaultSongOptions( SongOptions &so )
|
|
|
|
|
{
|
|
|
|
|
so.Init();
|
2005-11-09 10:55:30 +00:00
|
|
|
so.FromString( PREFSMAN->m_sDefaultModifiers );
|
2005-10-27 07:51:37 +00:00
|
|
|
so.FromString( CommonMetrics::DEFAULT_MODIFIERS );
|
|
|
|
|
}
|
|
|
|
|
|
2006-01-22 01:00:06 +00:00
|
|
|
void GameState::ApplyModifiers( PlayerNumber pn, RString sModifiers )
|
2003-04-21 23:43:51 +00:00
|
|
|
{
|
2004-12-20 06:25:59 +00:00
|
|
|
m_pPlayerState[pn]->m_PlayerOptions.FromString( sModifiers );
|
2003-04-21 23:43:51 +00:00
|
|
|
m_SongOptions.FromString( sModifiers );
|
|
|
|
|
}
|
|
|
|
|
|
2003-02-24 03:26:00 +00:00
|
|
|
/* Store the player's preferred options. This is called at the very beginning
|
|
|
|
|
* of gameplay. */
|
|
|
|
|
void GameState::StoreSelectedOptions()
|
|
|
|
|
{
|
2005-01-03 21:16:20 +00:00
|
|
|
FOREACH_PlayerNumber( pn )
|
|
|
|
|
m_pPlayerState[pn]->m_StoredPlayerOptions = m_pPlayerState[pn]->m_PlayerOptions;
|
2006-03-26 17:48:39 +00:00
|
|
|
m_StoredSongOptions = m_SongOptions;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GameState::StoreStageOptions()
|
|
|
|
|
{
|
|
|
|
|
FOREACH_PlayerNumber( pn )
|
2005-11-02 20:02:47 +00:00
|
|
|
m_pPlayerState[pn]->m_StagePlayerOptions = m_pPlayerState[pn]->m_PlayerOptions;
|
2003-03-26 23:08:05 +00:00
|
|
|
m_StoredSongOptions = m_SongOptions;
|
2003-02-24 03:26:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Restore the preferred options. This is called after a song ends, before
|
|
|
|
|
* setting new course options, so options from one song don't carry into the
|
|
|
|
|
* next and we default back to the preferred options. This is also called
|
|
|
|
|
* at the end of gameplay to restore options. */
|
|
|
|
|
void GameState::RestoreSelectedOptions()
|
|
|
|
|
{
|
2005-01-03 21:16:20 +00:00
|
|
|
FOREACH_PlayerNumber( pn )
|
|
|
|
|
m_pPlayerState[pn]->m_PlayerOptions = m_pPlayerState[pn]->m_StoredPlayerOptions;
|
2003-03-26 23:08:05 +00:00
|
|
|
m_SongOptions = m_StoredSongOptions;
|
2003-02-24 03:26:00 +00:00
|
|
|
}
|
2003-04-07 03:25:44 +00:00
|
|
|
|
2005-11-02 20:02:47 +00:00
|
|
|
void GameState::RestoreStageOptions()
|
|
|
|
|
{
|
|
|
|
|
FOREACH_PlayerNumber( pn )
|
|
|
|
|
m_pPlayerState[pn]->m_PlayerOptions = m_pPlayerState[pn]->m_StagePlayerOptions;
|
|
|
|
|
m_SongOptions = m_StoredSongOptions;
|
|
|
|
|
}
|
|
|
|
|
|
2005-03-31 21:25:15 +00:00
|
|
|
void GameState::ResetCurrentOptions()
|
|
|
|
|
{
|
|
|
|
|
FOREACH_PlayerNumber( p )
|
2005-10-27 07:51:37 +00:00
|
|
|
GetDefaultPlayerOptions( m_pPlayerState[p]->m_PlayerOptions );
|
|
|
|
|
GetDefaultSongOptions( m_SongOptions );
|
2005-03-31 21:25:15 +00:00
|
|
|
}
|
|
|
|
|
|
2004-03-09 08:19:55 +00:00
|
|
|
bool GameState::IsDisqualified( PlayerNumber pn )
|
|
|
|
|
{
|
2004-03-28 20:08:43 +00:00
|
|
|
if( !PREFSMAN->m_bDisqualification )
|
|
|
|
|
return false;
|
|
|
|
|
|
2005-10-15 02:20:44 +00:00
|
|
|
if( !GAMESTATE->IsHumanPlayer(pn) )
|
|
|
|
|
return false;
|
|
|
|
|
|
2006-04-25 00:40:16 +00:00
|
|
|
if( STATSMAN->m_CurStageStats.bGaveUp )
|
|
|
|
|
return true;
|
|
|
|
|
|
2006-04-25 02:35:55 +00:00
|
|
|
#ifndef DEBUG
|
|
|
|
|
if( STATSMAN->m_CurStageStats.bUsedAutoplay )
|
|
|
|
|
return true;
|
|
|
|
|
#endif //DEBUG
|
|
|
|
|
|
2006-03-26 17:48:39 +00:00
|
|
|
const PlayerOptions &po = GAMESTATE->m_pPlayerState[pn]->m_StoredPlayerOptions;
|
|
|
|
|
|
|
|
|
|
// Check the stored player options for disqualify. Don't disqualify because
|
|
|
|
|
// of mods that were forced.
|
2004-03-09 08:19:55 +00:00
|
|
|
if( GAMESTATE->IsCourseMode() )
|
2004-03-25 05:38:04 +00:00
|
|
|
{
|
2006-03-26 17:48:39 +00:00
|
|
|
return po.IsEasierForCourseAndTrail(
|
2004-03-25 05:38:04 +00:00
|
|
|
GAMESTATE->m_pCurCourse,
|
2004-06-03 08:22:02 +00:00
|
|
|
GAMESTATE->m_pCurTrail[pn] );
|
2004-03-25 05:38:04 +00:00
|
|
|
}
|
2004-03-09 08:19:55 +00:00
|
|
|
else
|
2004-03-25 05:38:04 +00:00
|
|
|
{
|
2006-03-26 17:48:39 +00:00
|
|
|
return po.IsEasierForSongAndSteps(
|
2004-03-25 05:38:04 +00:00
|
|
|
GAMESTATE->m_pCurSong,
|
2004-05-24 06:12:17 +00:00
|
|
|
GAMESTATE->m_pCurSteps[pn] );
|
2004-03-25 05:38:04 +00:00
|
|
|
}
|
2004-03-09 08:19:55 +00:00
|
|
|
}
|
|
|
|
|
|
2006-01-22 01:00:06 +00:00
|
|
|
void GameState::GetAllUsedNoteSkins( vector<RString> &out ) const
|
2003-10-24 09:35:56 +00:00
|
|
|
{
|
2004-09-06 00:35:52 +00:00
|
|
|
FOREACH_EnabledPlayer( pn )
|
2003-10-24 09:35:56 +00:00
|
|
|
{
|
2004-12-20 06:25:59 +00:00
|
|
|
out.push_back( m_pPlayerState[pn]->m_PlayerOptions.m_sNoteSkin );
|
2003-10-24 09:35:56 +00:00
|
|
|
|
2005-03-18 04:04:59 +00:00
|
|
|
/* Add note skins that are used in courses. */
|
|
|
|
|
if( this->IsCourseMode() )
|
|
|
|
|
{
|
2006-01-12 19:22:08 +00:00
|
|
|
const Trail *pTrail = this->m_pCurTrail[pn];
|
|
|
|
|
ASSERT( pTrail );
|
|
|
|
|
|
|
|
|
|
FOREACH_CONST( TrailEntry, pTrail->m_vEntries, e )
|
2005-03-18 04:04:59 +00:00
|
|
|
{
|
2006-01-12 19:22:08 +00:00
|
|
|
PlayerOptions po;
|
|
|
|
|
po.FromString( e->Modifiers );
|
2006-02-22 17:15:13 +00:00
|
|
|
if( !po.m_sNoteSkin.empty() )
|
|
|
|
|
out.push_back( po.m_sNoteSkin );
|
2003-10-24 09:35:56 +00:00
|
|
|
}
|
|
|
|
|
}
|
2005-03-18 04:04:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Remove duplicates. */
|
|
|
|
|
sort( out.begin(), out.end() );
|
|
|
|
|
out.erase( unique( out.begin(), out.end() ), out.end() );
|
2003-10-24 09:35:56 +00:00
|
|
|
}
|
|
|
|
|
|
2004-01-22 02:15:55 +00:00
|
|
|
void GameState::RemoveAllActiveAttacks() // called on end of song
|
|
|
|
|
{
|
2004-05-24 06:10:11 +00:00
|
|
|
FOREACH_PlayerNumber( p )
|
2006-01-13 06:35:46 +00:00
|
|
|
m_pPlayerState[p]->RemoveActiveAttacks();
|
2004-01-22 02:15:55 +00:00
|
|
|
}
|
|
|
|
|
|
2003-07-24 03:54:34 +00:00
|
|
|
template<class T>
|
|
|
|
|
void setmin( T &a, const T &b )
|
|
|
|
|
{
|
|
|
|
|
a = min(a, b);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
|
void setmax( T &a, const T &b )
|
|
|
|
|
{
|
|
|
|
|
a = max(a, b);
|
|
|
|
|
}
|
|
|
|
|
|
2005-08-23 20:55:58 +00:00
|
|
|
SongOptions::FailType GameState::GetPlayerFailType( const PlayerState *pPlayerState ) const
|
2003-07-24 03:54:34 +00:00
|
|
|
{
|
2005-08-23 20:55:58 +00:00
|
|
|
PlayerNumber pn = pPlayerState->m_PlayerNumber;
|
2005-04-05 08:30:57 +00:00
|
|
|
SongOptions::FailType ft = m_SongOptions.m_FailType;
|
2003-07-28 23:13:00 +00:00
|
|
|
|
2003-07-24 03:54:34 +00:00
|
|
|
/* If the player changed the fail mode explicitly, leave it alone. */
|
2005-04-05 08:30:57 +00:00
|
|
|
if( this->m_bChangedFailTypeOnScreenSongOptions )
|
|
|
|
|
return ft;
|
2003-07-24 03:54:34 +00:00
|
|
|
|
2005-06-16 22:09:03 +00:00
|
|
|
if( GAMESTATE->IsCourseMode() )
|
2005-04-05 08:30:57 +00:00
|
|
|
{
|
2005-06-16 22:09:03 +00:00
|
|
|
if( PREFSMAN->m_bMinimum1FullSongInCourses && GAMESTATE->GetCourseSongIndex()==0 )
|
2005-04-27 06:34:53 +00:00
|
|
|
ft = max( ft, SongOptions::FAIL_END_OF_SONG ); // take the least harsh of the two FailTypes
|
2005-04-05 08:30:57 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Difficulty dc = DIFFICULTY_INVALID;
|
|
|
|
|
if( m_pCurSteps[pn] )
|
|
|
|
|
dc = m_pCurSteps[pn]->GetDifficulty();
|
2003-07-24 03:54:34 +00:00
|
|
|
|
2005-04-05 08:30:57 +00:00
|
|
|
bool bFirstStage = !GAMESTATE->IsEventMode() && m_iCurrentStageIndex == 0;
|
2003-07-24 03:54:34 +00:00
|
|
|
|
2005-04-05 08:30:57 +00:00
|
|
|
/* Easy and beginner are never harder than FAIL_END_OF_SONG. */
|
|
|
|
|
if( dc <= DIFFICULTY_EASY )
|
|
|
|
|
setmax( ft, SongOptions::FAIL_END_OF_SONG );
|
2003-07-24 03:54:34 +00:00
|
|
|
|
2005-04-05 08:30:57 +00:00
|
|
|
if( dc <= DIFFICULTY_EASY && bFirstStage && PREFSMAN->m_bFailOffForFirstStageEasy )
|
|
|
|
|
setmax( ft, SongOptions::FAIL_OFF );
|
|
|
|
|
|
|
|
|
|
/* If beginner's steps were chosen, and this is the first stage,
|
|
|
|
|
* turn off failure completely. */
|
|
|
|
|
if( dc == DIFFICULTY_BEGINNER && bFirstStage )
|
|
|
|
|
setmax( ft, SongOptions::FAIL_OFF );
|
|
|
|
|
|
|
|
|
|
if( dc == DIFFICULTY_BEGINNER && PREFSMAN->m_bFailOffInBeginner )
|
|
|
|
|
setmax( ft, SongOptions::FAIL_OFF );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ft;
|
2003-07-24 03:54:34 +00:00
|
|
|
}
|
2003-07-25 08:05:29 +00:00
|
|
|
|
2005-10-09 04:30:59 +00:00
|
|
|
bool GameState::ShowW1() const
|
2003-07-25 08:05:29 +00:00
|
|
|
{
|
2005-10-09 04:30:59 +00:00
|
|
|
switch( PREFSMAN->m_AllowW1 )
|
2005-04-27 07:50:38 +00:00
|
|
|
{
|
2005-10-09 04:30:59 +00:00
|
|
|
case PrefsManager::ALLOW_W1_NEVER: return false;
|
|
|
|
|
case PrefsManager::ALLOW_W1_COURSES_ONLY: return IsCourseMode();
|
|
|
|
|
case PrefsManager::ALLOW_W1_EVERYWHERE: return true;
|
2005-04-27 07:50:38 +00:00
|
|
|
default: ASSERT(0);
|
|
|
|
|
}
|
2003-08-10 03:23:17 +00:00
|
|
|
}
|
2003-09-25 04:22:51 +00:00
|
|
|
|
2003-10-19 21:38:11 +00:00
|
|
|
struct SongAndSteps
|
|
|
|
|
{
|
|
|
|
|
Song* pSong;
|
|
|
|
|
Steps* pSteps;
|
2003-10-21 06:12:06 +00:00
|
|
|
bool operator==( const SongAndSteps& other ) const { return pSong==other.pSong && pSteps==other.pSteps; }
|
|
|
|
|
bool operator<( const SongAndSteps& other ) const { return pSong<=other.pSong && pSteps<=other.pSteps; }
|
2003-10-19 21:38:11 +00:00
|
|
|
};
|
|
|
|
|
|
2004-03-08 02:21:22 +00:00
|
|
|
void GameState::GetRankingFeats( PlayerNumber pn, vector<RankingFeat> &asFeatsOut ) const
|
2003-10-14 17:06:30 +00:00
|
|
|
{
|
2003-10-15 01:09:29 +00:00
|
|
|
if( !IsHumanPlayer(pn) )
|
|
|
|
|
return;
|
|
|
|
|
|
2004-02-09 20:46:39 +00:00
|
|
|
Profile *pProf = PROFILEMAN->GetProfile(pn);
|
|
|
|
|
|
2005-06-27 05:24:31 +00:00
|
|
|
// Check for feats even if the PlayMode is rave or battle because the player may have
|
|
|
|
|
// made high scores then switched modes.
|
2005-08-19 21:55:46 +00:00
|
|
|
CHECKPOINT_M(ssprintf("PlayMode %i", int(this->m_PlayMode)));
|
2004-02-07 22:14:36 +00:00
|
|
|
switch( this->m_PlayMode )
|
2003-10-14 17:06:30 +00:00
|
|
|
{
|
2004-06-11 06:05:35 +00:00
|
|
|
case PLAY_MODE_REGULAR:
|
2005-06-27 05:24:31 +00:00
|
|
|
case PLAY_MODE_BATTLE:
|
|
|
|
|
case PLAY_MODE_RAVE:
|
2003-10-14 17:06:30 +00:00
|
|
|
{
|
2003-12-02 19:13:30 +00:00
|
|
|
CHECKPOINT;
|
2003-10-14 17:06:30 +00:00
|
|
|
|
2004-06-28 07:26:00 +00:00
|
|
|
StepsType st = this->GetCurrentStyle()->m_StepsType;
|
2003-10-19 21:38:11 +00:00
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Find unique Song and Steps combinations that were played.
|
|
|
|
|
// We must keep only the unique combination or else we'll double-count
|
|
|
|
|
// high score markers.
|
|
|
|
|
//
|
|
|
|
|
vector<SongAndSteps> vSongAndSteps;
|
|
|
|
|
|
2005-02-16 03:25:45 +00:00
|
|
|
for( unsigned i=0; i<STATSMAN->m_vPlayedStageStats.size(); i++ )
|
2003-10-14 17:06:30 +00:00
|
|
|
{
|
2005-02-16 03:25:45 +00:00
|
|
|
CHECKPOINT_M( ssprintf("%u/%i", i, (int)STATSMAN->m_vPlayedStageStats.size() ) );
|
2003-10-19 21:38:11 +00:00
|
|
|
SongAndSteps sas;
|
2005-04-20 06:13:06 +00:00
|
|
|
sas.pSong = STATSMAN->m_vPlayedStageStats[i].vpPlayedSongs[0];
|
2003-10-19 21:38:11 +00:00
|
|
|
ASSERT( sas.pSong );
|
2005-04-20 06:13:06 +00:00
|
|
|
sas.pSteps = STATSMAN->m_vPlayedStageStats[i].m_player[pn].vpPlayedSteps[0];
|
2003-10-19 21:38:11 +00:00
|
|
|
ASSERT( sas.pSteps );
|
|
|
|
|
vSongAndSteps.push_back( sas );
|
|
|
|
|
}
|
2003-12-30 05:53:22 +00:00
|
|
|
CHECKPOINT;
|
2003-10-19 21:38:11 +00:00
|
|
|
|
|
|
|
|
sort( vSongAndSteps.begin(), vSongAndSteps.end() );
|
|
|
|
|
|
|
|
|
|
vector<SongAndSteps>::iterator toDelete = unique( vSongAndSteps.begin(), vSongAndSteps.end() );
|
|
|
|
|
vSongAndSteps.erase(toDelete, vSongAndSteps.end());
|
|
|
|
|
|
2003-12-02 19:13:30 +00:00
|
|
|
CHECKPOINT;
|
2004-08-30 04:09:23 +00:00
|
|
|
for( unsigned i=0; i<vSongAndSteps.size(); i++ )
|
2003-10-19 21:38:11 +00:00
|
|
|
{
|
|
|
|
|
Song* pSong = vSongAndSteps[i].pSong;
|
|
|
|
|
Steps* pSteps = vSongAndSteps[i].pSteps;
|
|
|
|
|
|
|
|
|
|
// Find Machine Records
|
2003-10-14 17:06:30 +00:00
|
|
|
{
|
2004-04-18 18:42:42 +00:00
|
|
|
HighScoreList &hsl = PROFILEMAN->GetMachineProfile()->GetStepsHighScoreList(pSong,pSteps);
|
2004-08-30 04:09:23 +00:00
|
|
|
for( unsigned j=0; j<hsl.vHighScores.size(); j++ )
|
2004-02-09 06:26:13 +00:00
|
|
|
{
|
|
|
|
|
HighScore &hs = hsl.vHighScores[j];
|
2003-10-14 23:29:34 +00:00
|
|
|
|
2005-08-12 01:52:01 +00:00
|
|
|
if( hs.GetName() != RANKING_TO_FILL_IN_MARKER[pn] )
|
2004-02-09 06:26:13 +00:00
|
|
|
continue;
|
2003-10-15 20:26:53 +00:00
|
|
|
|
2004-03-08 02:21:22 +00:00
|
|
|
RankingFeat feat;
|
|
|
|
|
feat.Type = RankingFeat::SONG;
|
|
|
|
|
feat.pSong = pSong;
|
|
|
|
|
feat.pSteps = pSteps;
|
2004-02-09 06:26:13 +00:00
|
|
|
feat.Feat = ssprintf("MR #%d in %s %s", j+1, pSong->GetTranslitMainTitle().c_str(), DifficultyToString(pSteps->GetDifficulty()).c_str() );
|
2005-08-12 01:52:01 +00:00
|
|
|
feat.pStringToFill = hs.GetNameMutable();
|
2005-08-12 02:19:08 +00:00
|
|
|
feat.grade = hs.GetGrade();
|
2005-08-12 02:46:58 +00:00
|
|
|
feat.fPercentDP = hs.GetPercentDP();
|
2005-08-12 02:37:04 +00:00
|
|
|
feat.iScore = hs.GetScore();
|
2003-10-15 01:09:29 +00:00
|
|
|
|
2004-02-09 06:26:13 +00:00
|
|
|
if( pSong->HasBanner() )
|
|
|
|
|
feat.Banner = pSong->GetBannerPath();
|
|
|
|
|
|
|
|
|
|
asFeatsOut.push_back( feat );
|
|
|
|
|
}
|
2003-10-14 17:06:30 +00:00
|
|
|
}
|
2003-10-19 21:38:11 +00:00
|
|
|
|
|
|
|
|
// Find Personal Records
|
2004-02-09 20:46:39 +00:00
|
|
|
if( pProf )
|
2003-10-19 21:38:11 +00:00
|
|
|
{
|
2004-04-18 18:42:42 +00:00
|
|
|
HighScoreList &hsl = pProf->GetStepsHighScoreList(pSong,pSteps);
|
2004-08-30 04:09:23 +00:00
|
|
|
for( unsigned j=0; j<hsl.vHighScores.size(); j++ )
|
2004-02-09 06:26:13 +00:00
|
|
|
{
|
|
|
|
|
HighScore &hs = hsl.vHighScores[j];
|
2003-10-19 21:38:11 +00:00
|
|
|
|
2005-08-12 01:52:01 +00:00
|
|
|
if( hs.GetName() != RANKING_TO_FILL_IN_MARKER[pn] )
|
2004-02-09 06:26:13 +00:00
|
|
|
continue;
|
2003-10-19 21:38:11 +00:00
|
|
|
|
2004-03-08 02:21:22 +00:00
|
|
|
RankingFeat feat;
|
|
|
|
|
feat.pSong = pSong;
|
|
|
|
|
feat.pSteps = pSteps;
|
|
|
|
|
feat.Type = RankingFeat::SONG;
|
2004-02-09 06:26:13 +00:00
|
|
|
feat.Feat = ssprintf("PR #%d in %s %s", j+1, pSong->GetTranslitMainTitle().c_str(), DifficultyToString(pSteps->GetDifficulty()).c_str() );
|
2005-08-12 01:52:01 +00:00
|
|
|
feat.pStringToFill = hs.GetNameMutable();
|
2005-08-12 02:19:08 +00:00
|
|
|
feat.grade = hs.GetGrade();
|
2005-08-12 02:46:58 +00:00
|
|
|
feat.fPercentDP = hs.GetPercentDP();
|
2005-08-12 02:37:04 +00:00
|
|
|
feat.iScore = hs.GetScore();
|
2004-02-09 06:26:13 +00:00
|
|
|
|
|
|
|
|
// XXX: temporary hack
|
|
|
|
|
if( pSong->HasBackground() )
|
|
|
|
|
feat.Banner = pSong->GetBackgroundPath();
|
|
|
|
|
// if( pSong->HasBanner() )
|
|
|
|
|
// feat.Banner = pSong->GetBannerPath();
|
|
|
|
|
|
|
|
|
|
asFeatsOut.push_back( feat );
|
|
|
|
|
}
|
2003-10-19 21:38:11 +00:00
|
|
|
}
|
2003-10-14 17:06:30 +00:00
|
|
|
}
|
|
|
|
|
|
2003-12-02 19:13:30 +00:00
|
|
|
CHECKPOINT;
|
2003-10-14 17:06:30 +00:00
|
|
|
StageStats stats;
|
2005-02-16 19:40:09 +00:00
|
|
|
STATSMAN->GetFinalEvalStageStats( stats );
|
2003-10-14 17:06:30 +00:00
|
|
|
|
|
|
|
|
|
2004-02-09 06:26:13 +00:00
|
|
|
// Find Machine Category Records
|
2004-05-24 03:32:56 +00:00
|
|
|
FOREACH_RankingCategory( rc )
|
2003-10-14 17:06:30 +00:00
|
|
|
{
|
2004-05-24 03:32:56 +00:00
|
|
|
HighScoreList &hsl = PROFILEMAN->GetMachineProfile()->GetCategoryHighScoreList( st, rc );
|
2004-02-09 06:26:13 +00:00
|
|
|
for( unsigned j=0; j<hsl.vHighScores.size(); j++ )
|
2003-10-14 17:06:30 +00:00
|
|
|
{
|
2004-02-09 06:26:13 +00:00
|
|
|
HighScore &hs = hsl.vHighScores[j];
|
2005-08-12 01:52:01 +00:00
|
|
|
if( hs.GetName() != RANKING_TO_FILL_IN_MARKER[pn] )
|
2003-12-07 20:29:42 +00:00
|
|
|
continue;
|
|
|
|
|
|
2004-03-08 02:21:22 +00:00
|
|
|
RankingFeat feat;
|
|
|
|
|
feat.Type = RankingFeat::CATEGORY;
|
2004-08-30 04:09:23 +00:00
|
|
|
feat.Feat = ssprintf("MR #%d in Type %c (%d)", j+1, 'A'+rc, stats.GetAverageMeter(pn) );
|
2005-08-12 01:52:01 +00:00
|
|
|
feat.pStringToFill = hs.GetNameMutable();
|
2005-08-14 11:38:31 +00:00
|
|
|
feat.grade = Grade_NoData;
|
2005-08-12 02:37:04 +00:00
|
|
|
feat.iScore = hs.GetScore();
|
2005-08-12 02:46:58 +00:00
|
|
|
feat.fPercentDP = hs.GetPercentDP();
|
2003-12-07 20:29:42 +00:00
|
|
|
asFeatsOut.push_back( feat );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-09 06:26:13 +00:00
|
|
|
// Find Personal Category Records
|
2004-05-24 03:32:56 +00:00
|
|
|
FOREACH_RankingCategory( rc )
|
2003-12-07 20:29:42 +00:00
|
|
|
{
|
2004-02-09 20:46:39 +00:00
|
|
|
if( pProf )
|
2003-12-07 20:29:42 +00:00
|
|
|
{
|
2004-05-24 03:32:56 +00:00
|
|
|
HighScoreList &hsl = pProf->GetCategoryHighScoreList( st, rc );
|
2004-02-09 20:46:39 +00:00
|
|
|
for( unsigned j=0; j<hsl.vHighScores.size(); j++ )
|
|
|
|
|
{
|
|
|
|
|
HighScore &hs = hsl.vHighScores[j];
|
2005-08-12 01:52:01 +00:00
|
|
|
if( hs.GetName() != RANKING_TO_FILL_IN_MARKER[pn] )
|
2004-02-09 20:46:39 +00:00
|
|
|
continue;
|
2003-12-07 20:29:42 +00:00
|
|
|
|
2004-03-08 02:21:22 +00:00
|
|
|
RankingFeat feat;
|
|
|
|
|
feat.Type = RankingFeat::CATEGORY;
|
2004-08-30 04:09:23 +00:00
|
|
|
feat.Feat = ssprintf("PR #%d in Type %c (%d)", j+1, 'A'+rc, stats.GetAverageMeter(pn) );
|
2005-08-12 01:52:01 +00:00
|
|
|
feat.pStringToFill = hs.GetNameMutable();
|
2005-08-14 11:38:31 +00:00
|
|
|
feat.grade = Grade_NoData;
|
2005-08-12 02:37:04 +00:00
|
|
|
feat.iScore = hs.GetScore();
|
2005-08-12 02:46:58 +00:00
|
|
|
feat.fPercentDP = hs.GetPercentDP();
|
2004-02-09 20:46:39 +00:00
|
|
|
asFeatsOut.push_back( feat );
|
|
|
|
|
}
|
2003-10-14 17:06:30 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case PLAY_MODE_NONSTOP:
|
|
|
|
|
case PLAY_MODE_ONI:
|
|
|
|
|
case PLAY_MODE_ENDLESS:
|
|
|
|
|
{
|
2003-12-02 19:13:30 +00:00
|
|
|
CHECKPOINT;
|
2004-06-03 08:22:02 +00:00
|
|
|
Course* pCourse = m_pCurCourse;
|
2003-12-02 19:13:30 +00:00
|
|
|
ASSERT( pCourse );
|
2004-06-03 08:22:02 +00:00
|
|
|
Trail *pTrail = m_pCurTrail[pn];
|
|
|
|
|
ASSERT( pTrail );
|
|
|
|
|
CourseDifficulty cd = pTrail->m_CourseDifficulty;
|
2003-12-21 04:19:51 +00:00
|
|
|
|
|
|
|
|
// Find Machine Records
|
2003-10-14 17:06:30 +00:00
|
|
|
{
|
2004-02-09 06:26:13 +00:00
|
|
|
Profile* pProfile = PROFILEMAN->GetMachineProfile();
|
2004-05-23 09:17:10 +00:00
|
|
|
HighScoreList &hsl = pProfile->GetCourseHighScoreList( pCourse, pTrail );
|
2004-02-09 06:26:13 +00:00
|
|
|
for( unsigned i=0; i<hsl.vHighScores.size(); i++ )
|
2003-12-21 04:19:51 +00:00
|
|
|
{
|
2004-02-09 06:26:13 +00:00
|
|
|
HighScore &hs = hsl.vHighScores[i];
|
2005-08-12 01:52:01 +00:00
|
|
|
if( hs.GetName() != RANKING_TO_FILL_IN_MARKER[pn] )
|
2003-12-21 04:19:51 +00:00
|
|
|
continue;
|
|
|
|
|
|
2004-03-08 02:21:22 +00:00
|
|
|
RankingFeat feat;
|
|
|
|
|
feat.Type = RankingFeat::COURSE;
|
|
|
|
|
feat.pCourse = pCourse;
|
2005-05-23 00:38:09 +00:00
|
|
|
feat.Feat = ssprintf("MR #%d in %s", i+1, pCourse->GetDisplayFullTitle().c_str() );
|
2004-06-04 02:05:56 +00:00
|
|
|
if( cd != DIFFICULTY_MEDIUM )
|
2006-01-07 04:11:29 +00:00
|
|
|
feat.Feat += " " + CourseDifficultyToLocalizedString(cd);
|
2005-08-12 01:52:01 +00:00
|
|
|
feat.pStringToFill = hs.GetNameMutable();
|
2005-08-14 11:38:31 +00:00
|
|
|
feat.grade = Grade_NoData;
|
2005-08-12 02:37:04 +00:00
|
|
|
feat.iScore = hs.GetScore();
|
2005-08-12 02:46:58 +00:00
|
|
|
feat.fPercentDP = hs.GetPercentDP();
|
2003-12-21 04:19:51 +00:00
|
|
|
if( pCourse->HasBanner() )
|
|
|
|
|
feat.Banner = pCourse->m_sBannerPath;
|
|
|
|
|
asFeatsOut.push_back( feat );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Find Personal Records
|
2005-05-09 08:44:01 +00:00
|
|
|
if( PROFILEMAN->IsPersistentProfile( pn ) )
|
2003-12-21 04:19:51 +00:00
|
|
|
{
|
2004-05-23 09:17:10 +00:00
|
|
|
HighScoreList &hsl = pProf->GetCourseHighScoreList( pCourse, pTrail );
|
2004-02-09 06:26:13 +00:00
|
|
|
for( unsigned i=0; i<hsl.vHighScores.size(); i++ )
|
2003-12-21 04:19:51 +00:00
|
|
|
{
|
2004-02-09 06:26:13 +00:00
|
|
|
HighScore& hs = hsl.vHighScores[i];
|
2005-08-12 01:52:01 +00:00
|
|
|
if( hs.GetName() != RANKING_TO_FILL_IN_MARKER[pn] )
|
2003-12-21 04:19:51 +00:00
|
|
|
continue;
|
2003-10-14 23:29:34 +00:00
|
|
|
|
2004-03-08 02:21:22 +00:00
|
|
|
RankingFeat feat;
|
|
|
|
|
feat.Type = RankingFeat::COURSE;
|
|
|
|
|
feat.pCourse = pCourse;
|
2005-05-23 00:38:09 +00:00
|
|
|
feat.Feat = ssprintf("PR #%d in %s", i+1, pCourse->GetDisplayFullTitle().c_str() );
|
2005-08-12 01:52:01 +00:00
|
|
|
feat.pStringToFill = hs.GetNameMutable();
|
2005-08-14 11:38:31 +00:00
|
|
|
feat.grade = Grade_NoData;
|
2005-08-12 02:37:04 +00:00
|
|
|
feat.iScore = hs.GetScore();
|
2005-08-12 02:46:58 +00:00
|
|
|
feat.fPercentDP = hs.GetPercentDP();
|
2003-12-21 04:19:51 +00:00
|
|
|
if( pCourse->HasBanner() )
|
|
|
|
|
feat.Banner = pCourse->m_sBannerPath;
|
|
|
|
|
asFeatsOut.push_back( feat );
|
|
|
|
|
}
|
2003-10-14 17:06:30 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
ASSERT(0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2005-03-21 12:21:58 +00:00
|
|
|
bool GameState::AnyPlayerHasRankingFeats() const
|
|
|
|
|
{
|
|
|
|
|
vector<RankingFeat> vFeats;
|
|
|
|
|
FOREACH_PlayerNumber( p )
|
|
|
|
|
{
|
|
|
|
|
GetRankingFeats( p, vFeats );
|
|
|
|
|
if( !vFeats.empty() )
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2006-01-22 01:00:06 +00:00
|
|
|
void GameState::StoreRankingName( PlayerNumber pn, RString sName )
|
2004-05-31 22:42:12 +00:00
|
|
|
{
|
2006-01-13 05:16:04 +00:00
|
|
|
sName.MakeUpper();
|
2005-04-03 06:48:26 +00:00
|
|
|
|
|
|
|
|
if( USE_NAME_BLACKLIST )
|
2003-12-10 06:49:27 +00:00
|
|
|
{
|
2005-04-03 06:48:26 +00:00
|
|
|
RageFile file;
|
|
|
|
|
if( file.Open(NAME_BLACKLIST_FILE) )
|
2003-10-22 10:49:58 +00:00
|
|
|
{
|
2006-01-22 01:00:06 +00:00
|
|
|
RString sLine;
|
2005-04-03 06:48:26 +00:00
|
|
|
|
2006-01-13 05:16:04 +00:00
|
|
|
while( !file.AtEOF() )
|
2004-06-06 21:04:48 +00:00
|
|
|
{
|
2006-01-13 05:16:04 +00:00
|
|
|
if( file.GetLine(sLine) == -1 )
|
2005-04-03 06:48:26 +00:00
|
|
|
{
|
|
|
|
|
LOG->Warn( "Error reading \"%s\": %s", NAME_BLACKLIST_FILE, file.GetError().c_str() );
|
|
|
|
|
break;
|
|
|
|
|
}
|
2004-06-06 21:04:48 +00:00
|
|
|
|
2006-01-13 05:16:04 +00:00
|
|
|
sLine.MakeUpper();
|
|
|
|
|
if( !sLine.empty() && sName.find(sLine) != string::npos ) // name contains a bad word
|
2005-04-03 06:48:26 +00:00
|
|
|
{
|
2006-01-13 05:16:04 +00:00
|
|
|
LOG->Trace( "entered '%s' matches blacklisted item '%s'", sName.c_str(), sLine.c_str() );
|
|
|
|
|
sName = "";
|
2005-04-03 06:48:26 +00:00
|
|
|
break;
|
|
|
|
|
}
|
2003-12-15 07:35:40 +00:00
|
|
|
}
|
2003-10-22 10:49:58 +00:00
|
|
|
}
|
2003-12-10 06:49:27 +00:00
|
|
|
}
|
2003-10-22 10:49:58 +00:00
|
|
|
|
2004-03-08 02:21:22 +00:00
|
|
|
vector<RankingFeat> aFeats;
|
2003-10-15 01:09:29 +00:00
|
|
|
GetRankingFeats( pn, aFeats );
|
|
|
|
|
|
|
|
|
|
for( unsigned i=0; i<aFeats.size(); i++ )
|
2003-10-14 17:06:30 +00:00
|
|
|
{
|
2006-01-13 05:16:04 +00:00
|
|
|
*aFeats[i].pStringToFill = sName;
|
2003-12-28 08:20:48 +00:00
|
|
|
|
|
|
|
|
// save name pointers as we fill them
|
|
|
|
|
m_vpsNamesThatWereFilled.push_back( aFeats[i].pStringToFill );
|
2003-10-14 17:06:30 +00:00
|
|
|
}
|
2005-04-25 09:03:24 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
Profile *pProfile = PROFILEMAN->GetMachineProfile();
|
|
|
|
|
|
|
|
|
|
if( !PREFSMAN->m_bAllowMultipleHighScoreWithSameName )
|
|
|
|
|
{
|
|
|
|
|
//
|
|
|
|
|
// erase all but the highest score for each name
|
|
|
|
|
//
|
|
|
|
|
FOREACHM( SongID, Profile::HighScoresForASong, pProfile->m_SongHighScores, iter )
|
|
|
|
|
FOREACHM( StepsID, Profile::HighScoresForASteps, iter->second.m_StepsHighScores, iter2 )
|
|
|
|
|
iter2->second.hsl.RemoveAllButOneOfEachName();
|
|
|
|
|
|
|
|
|
|
FOREACHM( CourseID, Profile::HighScoresForACourse, pProfile->m_CourseHighScores, iter )
|
|
|
|
|
FOREACHM( TrailID, Profile::HighScoresForATrail, iter->second.m_TrailHighScores, iter2 )
|
|
|
|
|
iter2->second.hsl.RemoveAllButOneOfEachName();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// clamp high score sizes
|
|
|
|
|
//
|
|
|
|
|
FOREACHM( SongID, Profile::HighScoresForASong, pProfile->m_SongHighScores, iter )
|
|
|
|
|
FOREACHM( StepsID, Profile::HighScoresForASteps, iter->second.m_StepsHighScores, iter2 )
|
|
|
|
|
iter2->second.hsl.ClampSize( true );
|
|
|
|
|
|
|
|
|
|
FOREACHM( CourseID, Profile::HighScoresForACourse, pProfile->m_CourseHighScores, iter )
|
|
|
|
|
FOREACHM( TrailID, Profile::HighScoresForATrail, iter->second.m_TrailHighScores, iter2 )
|
|
|
|
|
iter2->second.hsl.ClampSize( true );
|
2003-10-14 17:06:30 +00:00
|
|
|
}
|
2003-12-07 20:29:42 +00:00
|
|
|
|
|
|
|
|
bool GameState::AllAreInDangerOrWorse() const
|
|
|
|
|
{
|
2004-07-31 19:14:53 +00:00
|
|
|
FOREACH_EnabledPlayer( p )
|
2004-12-20 06:25:59 +00:00
|
|
|
if( m_pPlayerState[p]->m_HealthState < PlayerState::DANGER )
|
2004-07-31 19:14:53 +00:00
|
|
|
return false;
|
2003-12-07 20:29:42 +00:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool GameState::AllAreDead() const
|
|
|
|
|
{
|
2004-07-31 19:14:53 +00:00
|
|
|
FOREACH_EnabledPlayer( p )
|
2004-12-20 06:25:59 +00:00
|
|
|
if( m_pPlayerState[p]->m_HealthState < PlayerState::DEAD )
|
2004-07-31 19:14:53 +00:00
|
|
|
return false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2005-05-09 14:22:21 +00:00
|
|
|
bool GameState::AllHumanHaveComboOf30OrMoreMisses() const
|
2004-07-31 19:14:53 +00:00
|
|
|
{
|
2005-05-09 14:22:21 +00:00
|
|
|
FOREACH_HumanPlayer( p )
|
2005-02-16 03:25:45 +00:00
|
|
|
if( STATSMAN->m_CurStageStats.m_player[p].iCurMissCombo < 30 )
|
2004-07-31 19:14:53 +00:00
|
|
|
return false;
|
2003-12-07 20:29:42 +00:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool GameState::OneIsHot() const
|
|
|
|
|
{
|
2004-07-31 19:14:53 +00:00
|
|
|
FOREACH_EnabledPlayer( p )
|
2004-12-20 06:25:59 +00:00
|
|
|
if( m_pPlayerState[p]->m_HealthState == PlayerState::HOT )
|
2004-07-31 19:14:53 +00:00
|
|
|
return true;
|
2003-12-07 20:29:42 +00:00
|
|
|
return false;
|
|
|
|
|
}
|
2003-12-28 19:46:50 +00:00
|
|
|
|
2005-10-04 06:51:06 +00:00
|
|
|
bool GameState::IsTimeToPlayAttractSounds() const
|
2003-12-28 19:46:50 +00:00
|
|
|
{
|
2005-06-12 04:22:16 +00:00
|
|
|
// m_iNumTimesThroughAttract will be -1 from the first attract screen after
|
|
|
|
|
// the end of a game until the next time FIRST_ATTRACT_SCREEN is reached.
|
|
|
|
|
// Play attract sounds for this sort span of time regardless of
|
|
|
|
|
// m_AttractSoundFrequency because it's awkward to have the machine go
|
|
|
|
|
// silent immediately after the end of a game.
|
|
|
|
|
if( m_iNumTimesThroughAttract == -1 )
|
|
|
|
|
return true;
|
|
|
|
|
|
2005-06-11 10:53:16 +00:00
|
|
|
if( PREFSMAN->m_AttractSoundFrequency == PrefsManager::ASF_NEVER )
|
2003-12-28 19:46:50 +00:00
|
|
|
return false;
|
2004-03-13 10:12:59 +00:00
|
|
|
|
|
|
|
|
// play attract sounds once every m_iAttractSoundFrequency times through
|
2005-06-11 10:53:16 +00:00
|
|
|
if( (m_iNumTimesThroughAttract % PREFSMAN->m_AttractSoundFrequency)==0 )
|
2004-03-13 10:12:59 +00:00
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
return false;
|
2004-01-15 00:49:59 +00:00
|
|
|
}
|
|
|
|
|
|
2006-01-22 01:00:06 +00:00
|
|
|
void GameState::VisitAttractScreen( const RString sScreenName )
|
2005-06-11 11:25:34 +00:00
|
|
|
{
|
2005-10-27 05:16:19 +00:00
|
|
|
if( sScreenName == CommonMetrics::FIRST_ATTRACT_SCREEN.GetValue() )
|
2005-06-12 04:22:16 +00:00
|
|
|
m_iNumTimesThroughAttract++;
|
2005-06-11 11:25:34 +00:00
|
|
|
}
|
|
|
|
|
|
2004-05-07 04:37:47 +00:00
|
|
|
bool GameState::DifficultiesLocked()
|
|
|
|
|
{
|
2004-06-03 08:22:02 +00:00
|
|
|
if( GAMESTATE->m_PlayMode == PLAY_MODE_RAVE )
|
|
|
|
|
return true;
|
|
|
|
|
if( IsCourseMode() )
|
|
|
|
|
return PREFSMAN->m_bLockCourseDifficulties;
|
2005-10-02 20:17:19 +00:00
|
|
|
if( GAMESTATE->GetCurrentStyle()->m_bLockDifficulties )
|
|
|
|
|
return true;
|
2004-06-03 08:22:02 +00:00
|
|
|
return false;
|
2004-05-07 04:37:47 +00:00
|
|
|
}
|
|
|
|
|
|
2004-06-03 08:22:02 +00:00
|
|
|
bool GameState::ChangePreferredDifficulty( PlayerNumber pn, Difficulty dc )
|
2004-05-07 04:37:47 +00:00
|
|
|
{
|
2005-02-26 08:32:49 +00:00
|
|
|
m_PreferredDifficulty[pn].Set( dc );
|
2004-05-07 04:37:47 +00:00
|
|
|
if( DifficultiesLocked() )
|
2004-06-06 20:57:13 +00:00
|
|
|
FOREACH_PlayerNumber( p )
|
2005-02-26 08:32:49 +00:00
|
|
|
if( p != pn )
|
|
|
|
|
m_PreferredDifficulty[p].Set( m_PreferredDifficulty[pn] );
|
2004-05-07 04:37:47 +00:00
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2006-03-29 02:54:11 +00:00
|
|
|
/* When only displaying difficulties in DIFFICULTIES_TO_SHOW, use GetClosestShownDifficulty
|
|
|
|
|
* to find which difficulty to show, and ChangePreferredDifficulty(pn, dir) to change
|
|
|
|
|
* difficulty. */
|
2004-07-11 01:58:55 +00:00
|
|
|
bool GameState::ChangePreferredDifficulty( PlayerNumber pn, int dir )
|
|
|
|
|
{
|
2005-10-27 05:16:19 +00:00
|
|
|
const vector<Difficulty> &v = CommonMetrics::DIFFICULTIES_TO_SHOW.GetValue();
|
2004-05-07 04:37:47 +00:00
|
|
|
|
2006-03-29 02:54:11 +00:00
|
|
|
Difficulty d = GAMESTATE->GetClosestShownDifficulty(pn);
|
2004-07-11 01:58:55 +00:00
|
|
|
while( 1 )
|
|
|
|
|
{
|
|
|
|
|
d = (Difficulty)(d+dir);
|
2006-01-07 04:11:29 +00:00
|
|
|
if( d < 0 || d >= NUM_Difficulty )
|
2004-07-11 01:58:55 +00:00
|
|
|
return false;
|
2005-04-03 09:48:15 +00:00
|
|
|
if( find(v.begin(), v.end(), d) != v.end() )
|
|
|
|
|
break; // found
|
2004-07-11 01:58:55 +00:00
|
|
|
}
|
2004-05-07 02:53:07 +00:00
|
|
|
|
2004-07-11 01:58:55 +00:00
|
|
|
return ChangePreferredDifficulty( pn, d );
|
2004-05-07 02:53:07 +00:00
|
|
|
}
|
|
|
|
|
|
2006-03-29 02:54:11 +00:00
|
|
|
/* The user may be set to prefer a difficulty that isn't always shown; typically,
|
|
|
|
|
* DIFFICULTY_EDIT. Return the closest shown difficulty <= m_PreferredDifficulty. */
|
|
|
|
|
Difficulty GameState::GetClosestShownDifficulty( PlayerNumber pn ) const
|
|
|
|
|
{
|
|
|
|
|
const vector<Difficulty> &v = CommonMetrics::DIFFICULTIES_TO_SHOW.GetValue();
|
|
|
|
|
|
|
|
|
|
Difficulty iClosest = (Difficulty) 0;
|
|
|
|
|
int iClosestDist = -1;
|
|
|
|
|
FOREACH_CONST( Difficulty, v, dc )
|
|
|
|
|
{
|
|
|
|
|
int iDist = m_PreferredDifficulty[pn] - *dc;
|
|
|
|
|
if( iDist < 0 )
|
|
|
|
|
continue;
|
|
|
|
|
if( iClosestDist != -1 && iDist > iClosestDist )
|
|
|
|
|
continue;
|
|
|
|
|
iClosestDist = iDist;
|
|
|
|
|
iClosest = *dc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return iClosest;
|
|
|
|
|
}
|
|
|
|
|
|
2004-06-03 08:22:02 +00:00
|
|
|
bool GameState::ChangePreferredCourseDifficulty( PlayerNumber pn, CourseDifficulty cd )
|
|
|
|
|
{
|
2005-02-26 08:32:49 +00:00
|
|
|
m_PreferredCourseDifficulty[pn].Set( cd );
|
2004-06-03 08:22:02 +00:00
|
|
|
|
|
|
|
|
if( PREFSMAN->m_bLockCourseDifficulties )
|
2004-06-06 20:57:13 +00:00
|
|
|
FOREACH_PlayerNumber( p )
|
2005-02-26 08:32:49 +00:00
|
|
|
if( p != pn )
|
|
|
|
|
m_PreferredCourseDifficulty[p].Set( m_PreferredCourseDifficulty[pn] );
|
2004-06-03 08:22:02 +00:00
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool GameState::ChangePreferredCourseDifficulty( PlayerNumber pn, int dir )
|
2004-01-21 01:35:54 +00:00
|
|
|
{
|
2004-06-03 21:33:37 +00:00
|
|
|
/* If we have a course selected, only choose among difficulties available in the course. */
|
|
|
|
|
const Course *pCourse = this->m_pCurCourse;
|
|
|
|
|
|
2005-10-27 05:16:19 +00:00
|
|
|
const vector<CourseDifficulty> &v = CommonMetrics::COURSE_DIFFICULTIES_TO_SHOW.GetValue();
|
2004-05-20 22:23:44 +00:00
|
|
|
|
|
|
|
|
CourseDifficulty cd = m_PreferredCourseDifficulty[pn];
|
2004-06-03 21:33:37 +00:00
|
|
|
while( 1 )
|
|
|
|
|
{
|
2004-05-20 22:23:44 +00:00
|
|
|
cd = (CourseDifficulty)(cd+dir);
|
2006-01-07 04:11:29 +00:00
|
|
|
if( cd < 0 || cd >= NUM_Difficulty )
|
2004-05-20 22:23:44 +00:00
|
|
|
return false;
|
2005-03-24 21:44:03 +00:00
|
|
|
if( find(v.begin(),v.end(),cd) == v.end() )
|
2004-06-03 21:33:37 +00:00
|
|
|
continue; /* not available */
|
2004-06-28 07:26:00 +00:00
|
|
|
if( !pCourse || pCourse->GetTrail( GAMESTATE->GetCurrentStyle()->m_StepsType, cd ) )
|
2004-06-03 21:33:37 +00:00
|
|
|
break;
|
|
|
|
|
}
|
2004-05-20 22:23:44 +00:00
|
|
|
|
2004-06-03 08:22:02 +00:00
|
|
|
return ChangePreferredCourseDifficulty( pn, cd );
|
2004-01-21 01:35:54 +00:00
|
|
|
}
|
|
|
|
|
|
2004-05-20 22:23:44 +00:00
|
|
|
bool GameState::IsCourseDifficultyShown( CourseDifficulty cd )
|
|
|
|
|
{
|
2005-10-27 05:16:19 +00:00
|
|
|
const vector<CourseDifficulty> &v = CommonMetrics::COURSE_DIFFICULTIES_TO_SHOW.GetValue();
|
2005-03-24 21:44:03 +00:00
|
|
|
return find(v.begin(), v.end(), cd) != v.end();
|
2004-05-20 22:23:44 +00:00
|
|
|
}
|
|
|
|
|
|
2005-04-24 10:47:44 +00:00
|
|
|
Difficulty GameState::GetEasiestStepsDifficulty() const
|
2004-05-11 06:11:08 +00:00
|
|
|
{
|
|
|
|
|
Difficulty dc = DIFFICULTY_INVALID;
|
|
|
|
|
FOREACH_HumanPlayer( p )
|
|
|
|
|
{
|
2004-05-24 06:12:17 +00:00
|
|
|
if( this->m_pCurSteps[p] == NULL )
|
2004-05-11 06:11:08 +00:00
|
|
|
{
|
|
|
|
|
LOG->Warn( "GetEasiestNotesDifficulty called but p%i hasn't chosen notes", p+1 );
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2004-05-24 06:12:17 +00:00
|
|
|
dc = min( dc, this->m_pCurSteps[p]->GetDifficulty() );
|
2004-05-11 06:11:08 +00:00
|
|
|
}
|
|
|
|
|
return dc;
|
|
|
|
|
}
|
|
|
|
|
|
2005-04-05 08:30:57 +00:00
|
|
|
bool GameState::IsEventMode() const
|
2004-02-14 23:26:32 +00:00
|
|
|
{
|
2005-02-21 17:29:49 +00:00
|
|
|
return m_bTemporaryEventMode || PREFSMAN->m_bEventMode;
|
|
|
|
|
}
|
2004-02-14 23:26:32 +00:00
|
|
|
|
2005-02-21 17:29:49 +00:00
|
|
|
CoinMode GameState::GetCoinMode()
|
|
|
|
|
{
|
2005-05-20 17:45:44 +00:00
|
|
|
if( IsEventMode() && PREFSMAN->m_CoinMode == COIN_MODE_PAY )
|
|
|
|
|
return COIN_MODE_FREE;
|
2005-02-21 17:29:49 +00:00
|
|
|
else
|
|
|
|
|
return PREFSMAN->m_CoinMode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Premium GameState::GetPremium()
|
|
|
|
|
{
|
2005-04-05 08:30:57 +00:00
|
|
|
if( IsEventMode() )
|
2005-02-21 17:29:49 +00:00
|
|
|
return PREMIUM_NONE;
|
|
|
|
|
else
|
|
|
|
|
return PREFSMAN->m_Premium;
|
2004-02-14 23:26:32 +00:00
|
|
|
}
|
|
|
|
|
|
2005-08-23 20:55:58 +00:00
|
|
|
bool GameState::IsPlayerInDanger( const PlayerState *pPlayerState ) const
|
2005-04-05 08:30:57 +00:00
|
|
|
{
|
2005-08-23 20:55:58 +00:00
|
|
|
if( GAMESTATE->GetPlayerFailType(pPlayerState) == SongOptions::FAIL_OFF )
|
2005-04-05 08:30:57 +00:00
|
|
|
return false;
|
|
|
|
|
if( !PREFSMAN->m_bShowDanger )
|
|
|
|
|
return false;
|
2005-08-23 20:55:58 +00:00
|
|
|
return pPlayerState->m_HealthState == PlayerState::DANGER;
|
2005-04-05 08:30:57 +00:00
|
|
|
}
|
|
|
|
|
|
2005-08-23 20:55:58 +00:00
|
|
|
bool GameState::IsPlayerDead( const PlayerState *pPlayerState ) const
|
2005-04-05 08:30:57 +00:00
|
|
|
{
|
2005-08-23 20:55:58 +00:00
|
|
|
if( GAMESTATE->GetPlayerFailType(pPlayerState) == SongOptions::FAIL_OFF )
|
2005-04-05 08:30:57 +00:00
|
|
|
return false;
|
2005-08-23 20:55:58 +00:00
|
|
|
return pPlayerState->m_HealthState == PlayerState::DEAD;
|
2005-04-05 08:30:57 +00:00
|
|
|
}
|
2005-02-12 21:07:13 +00:00
|
|
|
|
2005-04-09 09:34:54 +00:00
|
|
|
float GameState::GetGoalPercentComplete( PlayerNumber pn )
|
|
|
|
|
{
|
|
|
|
|
const Profile *pProfile = PROFILEMAN->GetProfile(pn);
|
|
|
|
|
const StageStats &ssAccum = STATSMAN->GetAccumStageStats();
|
|
|
|
|
const StageStats &ssCurrent = STATSMAN->m_CurStageStats;
|
|
|
|
|
const PlayerStageStats &pssAccum = ssAccum.m_player[pn];
|
|
|
|
|
const PlayerStageStats &pssCurrent = ssCurrent.m_player[pn];
|
|
|
|
|
|
|
|
|
|
float fActual = 0;
|
|
|
|
|
float fGoal = 0;
|
|
|
|
|
switch( pProfile->m_GoalType )
|
|
|
|
|
{
|
|
|
|
|
case GOAL_CALORIES:
|
|
|
|
|
fActual = pssAccum.fCaloriesBurned + pssCurrent.fCaloriesBurned;
|
2005-04-10 04:47:57 +00:00
|
|
|
fGoal = (float)pProfile->m_iGoalCalories;
|
2005-04-09 09:34:54 +00:00
|
|
|
break;
|
|
|
|
|
case GOAL_TIME:
|
|
|
|
|
fActual = ssAccum.fGameplaySeconds + ssCurrent.fGameplaySeconds;
|
2005-04-10 04:47:57 +00:00
|
|
|
fGoal = (float)pProfile->m_iGoalSeconds;
|
2005-04-09 09:34:54 +00:00
|
|
|
break;
|
2005-04-19 22:31:35 +00:00
|
|
|
case GOAL_NONE:
|
|
|
|
|
return 0; // never complete
|
|
|
|
|
default:
|
|
|
|
|
ASSERT(0);
|
2005-04-09 09:34:54 +00:00
|
|
|
}
|
2005-04-19 22:31:35 +00:00
|
|
|
if( fGoal == 0 )
|
|
|
|
|
return 0;
|
|
|
|
|
else
|
|
|
|
|
return fActual / fGoal;
|
2005-04-09 09:34:54 +00:00
|
|
|
}
|
2005-02-12 21:07:13 +00:00
|
|
|
|
2006-01-22 01:00:06 +00:00
|
|
|
bool GameState::PlayerIsUsingModifier( PlayerNumber pn, const RString &sModifier )
|
2005-04-15 09:07:57 +00:00
|
|
|
{
|
|
|
|
|
PlayerOptions po = GAMESTATE->m_pPlayerState[pn]->m_PlayerOptions;
|
|
|
|
|
SongOptions so = GAMESTATE->m_SongOptions;
|
|
|
|
|
po.FromString( sModifier );
|
|
|
|
|
so.FromString( sModifier );
|
|
|
|
|
|
|
|
|
|
return po == GAMESTATE->m_pPlayerState[pn]->m_PlayerOptions && so == GAMESTATE->m_SongOptions;
|
|
|
|
|
}
|
|
|
|
|
|
2005-08-04 21:13:29 +00:00
|
|
|
Profile* GameState::GetEditLocalProfile()
|
|
|
|
|
{
|
|
|
|
|
if( m_sEditLocalProfileID.Get().empty() )
|
|
|
|
|
return NULL;
|
2005-08-14 01:52:01 +00:00
|
|
|
return PROFILEMAN->GetLocalProfile( m_sEditLocalProfileID );
|
2005-08-04 21:13:29 +00:00
|
|
|
}
|
|
|
|
|
|
2005-02-12 21:07:13 +00:00
|
|
|
|
|
|
|
|
// lua start
|
|
|
|
|
#include "LuaBinding.h"
|
2005-06-25 03:30:20 +00:00
|
|
|
#include "Game.h"
|
2005-02-12 21:07:13 +00:00
|
|
|
|
2005-06-20 05:02:03 +00:00
|
|
|
class LunaGameState: public Luna<GameState>
|
2005-02-12 21:07:13 +00:00
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
LunaGameState() { LUA->Register( Register ); }
|
|
|
|
|
|
2005-09-10 02:47:04 +00:00
|
|
|
DEFINE_METHOD( IsPlayerEnabled, IsPlayerEnabled((PlayerNumber)IArg(1)) )
|
|
|
|
|
DEFINE_METHOD( IsHumanPlayer, IsHumanPlayer((PlayerNumber)IArg(1)) )
|
2006-04-21 00:43:32 +00:00
|
|
|
DEFINE_METHOD( GetPlayerDisplayName, GetPlayerDisplayName((PlayerNumber)IArg(1)) )
|
|
|
|
|
DEFINE_METHOD( GetMasterPlayerNumber, m_MasterPlayerNumber )
|
2005-09-10 02:47:04 +00:00
|
|
|
DEFINE_METHOD( GetMultiplayer, m_bMultiplayer )
|
|
|
|
|
static int GetPlayerState( T* p, lua_State *L )
|
|
|
|
|
{
|
2005-08-30 01:59:15 +00:00
|
|
|
PlayerNumber pn = (PlayerNumber)IArg(1);
|
2005-09-10 02:47:04 +00:00
|
|
|
p->m_pPlayerState[pn]->PushSelf(L);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2006-04-21 00:43:32 +00:00
|
|
|
static int GetMultiPlayerState( T* p, lua_State *L )
|
|
|
|
|
{
|
|
|
|
|
MultiPlayer mp = (MultiPlayer)IArg(1);
|
|
|
|
|
p->m_pMultiPlayerState[mp]->PushSelf(L);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2005-02-16 06:24:33 +00:00
|
|
|
static int ApplyGameCommand( T* p, lua_State *L )
|
|
|
|
|
{
|
|
|
|
|
PlayerNumber pn = PLAYER_INVALID;
|
|
|
|
|
if( lua_gettop(L) >= 2 && !lua_isnil(L,2) )
|
2006-03-14 03:10:43 +00:00
|
|
|
pn = (PlayerNumber)IArg(2);
|
2005-02-16 06:24:33 +00:00
|
|
|
p->ApplyGameCommand(SArg(1),pn);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2005-02-22 23:06:51 +00:00
|
|
|
static int GetCurrentSong( T* p, lua_State *L ) { if(p->m_pCurSong) p->m_pCurSong->PushSelf(L); else lua_pushnil(L); return 1; }
|
2005-02-22 23:08:46 +00:00
|
|
|
static int SetCurrentSong( T* p, lua_State *L )
|
|
|
|
|
{
|
2005-02-24 12:27:30 +00:00
|
|
|
if( lua_isnil(L,1) ) { p->m_pCurSong.Set( NULL ); }
|
|
|
|
|
else { Song *pS = Luna<Song>::check(L,1); p->m_pCurSong.Set( pS ); }
|
2005-02-22 23:08:46 +00:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
static int GetCurrentSteps( T* p, lua_State *L )
|
|
|
|
|
{
|
|
|
|
|
PlayerNumber pn = (PlayerNumber)IArg(1);
|
|
|
|
|
Steps *pSteps = p->m_pCurSteps[pn];
|
|
|
|
|
if( pSteps ) { pSteps->PushSelf(L); }
|
|
|
|
|
else { lua_pushnil(L); }
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
static int SetCurrentSteps( T* p, lua_State *L )
|
|
|
|
|
{
|
|
|
|
|
PlayerNumber pn = (PlayerNumber)IArg(1);
|
2005-02-25 18:17:26 +00:00
|
|
|
if( lua_isnil(L,2) ) { p->m_pCurSteps[pn].Set( NULL ); }
|
|
|
|
|
else { Steps *pS = Luna<Steps>::check(L,2); p->m_pCurSteps[pn].Set( pS ); }
|
2005-08-14 07:29:48 +00:00
|
|
|
MESSAGEMAN->Broadcast( (Message)(Message_CurrentStepsP1Changed+pn) );
|
2005-02-22 23:08:46 +00:00
|
|
|
return 0;
|
|
|
|
|
}
|
2005-02-21 17:29:49 +00:00
|
|
|
static int GetCurrentCourse( T* p, lua_State *L ) { if(p->m_pCurCourse) p->m_pCurCourse->PushSelf(L); else lua_pushnil(L); return 1; }
|
2005-02-22 23:08:46 +00:00
|
|
|
static int SetCurrentCourse( T* p, lua_State *L )
|
|
|
|
|
{
|
2005-05-18 07:14:19 +00:00
|
|
|
if( lua_isnil(L,1) ) { p->m_pCurCourse.Set( NULL ); }
|
|
|
|
|
else { Course *pC = Luna<Course>::check(L,1); p->m_pCurCourse.Set( pC ); }
|
2005-02-22 23:08:46 +00:00
|
|
|
return 0;
|
|
|
|
|
}
|
2005-05-06 13:24:11 +00:00
|
|
|
static int GetCurrentTrail( T* p, lua_State *L )
|
|
|
|
|
{
|
|
|
|
|
PlayerNumber pn = (PlayerNumber)IArg(1);
|
|
|
|
|
Trail *pTrail = p->m_pCurTrail[pn];
|
|
|
|
|
if( pTrail ) { pTrail->PushSelf(L); }
|
|
|
|
|
else { lua_pushnil(L); }
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2005-10-31 03:34:48 +00:00
|
|
|
static int SetCurrentTrail( T* p, lua_State *L )
|
|
|
|
|
{
|
|
|
|
|
PlayerNumber pn = (PlayerNumber)IArg(1);
|
|
|
|
|
if( lua_isnil(L,2) ) { p->m_pCurTrail[pn].Set( NULL ); }
|
|
|
|
|
else { Trail *pS = Luna<Trail>::check(L,2); p->m_pCurTrail[pn].Set( pS ); }
|
|
|
|
|
MESSAGEMAN->Broadcast( (Message)(Message_CurrentTrailP1Changed+pn) );
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2005-04-24 01:33:32 +00:00
|
|
|
static int GetPreferredSong( T* p, lua_State *L ) { if(p->m_pPreferredSong) p->m_pPreferredSong->PushSelf(L); else lua_pushnil(L); return 1; }
|
|
|
|
|
static int SetPreferredSong( T* p, lua_State *L )
|
|
|
|
|
{
|
|
|
|
|
if( lua_isnil(L,1) ) { p->m_pPreferredSong = NULL; }
|
|
|
|
|
else { Song *pS = Luna<Song>::check(L,1); p->m_pPreferredSong = pS; }
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2005-02-21 17:29:49 +00:00
|
|
|
static int SetTemporaryEventMode( T* p, lua_State *L ) { p->m_bTemporaryEventMode = BArg(1); return 0; }
|
2005-03-18 22:47:44 +00:00
|
|
|
static int Env( T* p, lua_State *L ) { p->m_Environment->PushSelf(L); return 1; }
|
2006-01-13 21:49:35 +00:00
|
|
|
static int SetEnv( T* p, lua_State *L )
|
|
|
|
|
{
|
|
|
|
|
int iTop = lua_gettop(L);
|
|
|
|
|
p->m_Environment->PushSelf(L);
|
|
|
|
|
lua_pushvalue( L, iTop-1 );
|
|
|
|
|
lua_pushvalue( L, iTop );
|
|
|
|
|
lua_settable( L, -3 );
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2005-02-23 17:39:57 +00:00
|
|
|
static int GetEnv( T* p, lua_State *L )
|
|
|
|
|
{
|
2006-01-13 21:49:35 +00:00
|
|
|
int iTop = lua_gettop(L);
|
|
|
|
|
p->m_Environment->PushSelf(L);
|
|
|
|
|
lua_pushvalue( L, iTop );
|
|
|
|
|
lua_gettable( L, -2 );
|
2005-02-23 17:39:57 +00:00
|
|
|
return 1;
|
|
|
|
|
}
|
2005-02-25 05:27:28 +00:00
|
|
|
static int GetEditSourceSteps( T* p, lua_State *L )
|
|
|
|
|
{
|
|
|
|
|
Steps *pSteps = p->m_pEditSourceSteps;
|
|
|
|
|
if( pSteps ) { pSteps->PushSelf(L); }
|
|
|
|
|
else { lua_pushnil(L); }
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2006-03-18 22:15:26 +00:00
|
|
|
static int GetPreferredDifficulty( T* p, lua_State *L ) { lua_pushnumber(L, p->m_PreferredDifficulty[IArg(1)] ); return 1; }
|
2005-03-21 12:21:58 +00:00
|
|
|
static int AnyPlayerHasRankingFeats( T* p, lua_State *L ) { lua_pushboolean(L, p->AnyPlayerHasRankingFeats() ); return 1; }
|
2005-05-06 08:10:39 +00:00
|
|
|
static int IsCourseMode( T* p, lua_State *L ) { lua_pushboolean(L, p->IsCourseMode() ); return 1; }
|
2005-05-29 21:46:57 +00:00
|
|
|
static int IsDemonstration( T* p, lua_State *L ) { lua_pushboolean(L, p->m_bDemonstrationOrJukebox ); return 1; }
|
2005-04-15 13:41:02 +00:00
|
|
|
static int GetPlayMode( T* p, lua_State *L ) { lua_pushnumber(L, p->m_PlayMode ); return 1; }
|
|
|
|
|
static int GetSortOrder( T* p, lua_State *L ) { lua_pushnumber(L, p->m_SortOrder ); return 1; }
|
2005-05-30 00:37:24 +00:00
|
|
|
static int StageIndex( T* p, lua_State *L ) { lua_pushnumber(L, p->GetStageIndex() ); return 1; }
|
2005-04-15 13:41:02 +00:00
|
|
|
static int IsGoalComplete( T* p, lua_State *L ) { lua_pushboolean(L, p->IsGoalComplete((PlayerNumber)IArg(1)) ); return 1; }
|
2006-03-18 22:15:26 +00:00
|
|
|
static int PlayerIsUsingModifier( T* p, lua_State *L ) { lua_pushboolean(L, p->PlayerIsUsingModifier((PlayerNumber)IArg(1),SArg(2)) ); return 1; }
|
2005-04-15 13:41:02 +00:00
|
|
|
static int GetCourseSongIndex( T* p, lua_State *L ) { lua_pushnumber(L, p->GetCourseSongIndex() ); return 1; }
|
2006-04-29 02:03:08 +00:00
|
|
|
static int GetLoadingCourseSongIndex( T* p, lua_State *L ) { lua_pushnumber(L, p->GetLoadingCourseSongIndex() ); return 1; }
|
2005-07-12 21:41:42 +00:00
|
|
|
static int IsFinalStage( T* p, lua_State *L ) { lua_pushboolean(L, p->IsFinalStage() ); return 1; }
|
2005-04-23 01:41:42 +00:00
|
|
|
static int IsExtraStage( T* p, lua_State *L ) { lua_pushboolean(L, p->IsExtraStage() ); return 1; }
|
|
|
|
|
static int IsExtraStage2( T* p, lua_State *L ) { lua_pushboolean(L, p->IsExtraStage2() ); return 1; }
|
2005-09-08 06:08:08 +00:00
|
|
|
static int GetCurrentStage( T* p, lua_State *L ) { lua_pushnumber(L, p->GetCurrentStage() ); return 1; }
|
2006-03-18 22:15:26 +00:00
|
|
|
static int IsStagePossible( T* p, lua_State *L ) { lua_pushboolean(L, p->IsStagePossible((Stage)IArg(1)) ); return 1; }
|
|
|
|
|
static int HasEarnedExtraStage( T* p, lua_State *L ) { lua_pushboolean(L, p->HasEarnedExtraStage() ); return 1; }
|
|
|
|
|
static int GetEasiestStepsDifficulty( T* p, lua_State *L ) { lua_pushnumber(L, p->GetEasiestStepsDifficulty() ); return 1; }
|
2005-04-26 03:32:30 +00:00
|
|
|
static int IsEventMode( T* p, lua_State *L ) { lua_pushboolean(L, p->IsEventMode() ); return 1; }
|
2006-03-18 22:15:26 +00:00
|
|
|
static int GetNumPlayersEnabled( T* p, lua_State *L ) { lua_pushnumber(L, p->GetNumPlayersEnabled() ); return 1; }
|
2005-04-30 03:03:57 +00:00
|
|
|
static int GetSongBeat( T* p, lua_State *L ) { lua_pushnumber(L, p->m_fSongBeat ); return 1; }
|
2006-03-18 22:15:26 +00:00
|
|
|
static int GetGameplayLeadIn( T* p, lua_State *L ) { lua_pushnumber(L, p->m_bGameplayLeadIn ); return 1; }
|
|
|
|
|
static int PlayerUsingBothSides( T* p, lua_State *L ) { lua_pushboolean(L, p->PlayerUsingBothSides() ); return 1; }
|
|
|
|
|
static int GetCoins( T* p, lua_State *L ) { lua_pushnumber(L, p->m_iCoins ); return 1; }
|
2005-05-07 00:27:31 +00:00
|
|
|
static int IsSideJoined( T* p, lua_State *L ) { lua_pushboolean(L, p->m_bSideIsJoined[(PlayerNumber)IArg(1)] ); return 1; }
|
2006-03-18 22:15:26 +00:00
|
|
|
static int GetCoinsNeededToJoin( T* p, lua_State *L ) { lua_pushnumber(L, p->GetCoinsNeededToJoin() ); return 1; }
|
2005-05-07 08:34:20 +00:00
|
|
|
static int PlayersCanJoin( T* p, lua_State *L ) { lua_pushboolean(L, p->PlayersCanJoin() ); return 1; }
|
2005-05-08 04:04:56 +00:00
|
|
|
static int GetNumSidesJoined( T* p, lua_State *L ) { lua_pushnumber(L, p->GetNumSidesJoined() ); return 1; }
|
|
|
|
|
static int GetCoinMode( T* p, lua_State *L ) { lua_pushnumber(L, p->GetCoinMode() ); return 1; }
|
2006-03-18 22:15:26 +00:00
|
|
|
static int GetPremium( T* p, lua_State *L ) { lua_pushnumber(L, p->GetPremium() ); return 1; }
|
|
|
|
|
static int GetSongOptionsString( T* p, lua_State *L ) { lua_pushstring(L, p->m_SongOptions.GetString() ); return 1; }
|
2005-05-29 01:19:02 +00:00
|
|
|
static int IsWinner( T* p, lua_State *L )
|
|
|
|
|
{
|
|
|
|
|
PlayerNumber pn = (PlayerNumber)IArg(1);
|
|
|
|
|
lua_pushboolean(L, p->GetStageResult(pn)==RESULT_WIN); return 1;
|
|
|
|
|
}
|
2005-09-10 18:32:40 +00:00
|
|
|
static int IsDraw( T* p, lua_State *L )
|
|
|
|
|
{
|
|
|
|
|
lua_pushboolean(L, p->GetStageResult(PLAYER_1)==RESULT_DRAW); return 1;
|
|
|
|
|
}
|
2005-08-30 02:52:38 +00:00
|
|
|
static int IsDisqualified( T* p, lua_State *L )
|
|
|
|
|
{
|
|
|
|
|
PlayerNumber pn = (PlayerNumber)IArg(1);
|
|
|
|
|
lua_pushboolean(L, p->IsDisqualified(pn)); return 1;
|
|
|
|
|
}
|
2005-06-25 03:30:20 +00:00
|
|
|
static int GetCurrentGame( T* p, lua_State *L ) { const_cast<Game*>(p->GetCurrentGame())->PushSelf( L ); return 1; }
|
2005-07-30 19:34:23 +00:00
|
|
|
static int GetEditCourseEntryIndex( T* p, lua_State *L ) { lua_pushnumber(L, p->m_iEditCourseEntryIndex ); return 1; }
|
2005-08-06 05:33:29 +00:00
|
|
|
static int GetEditLocalProfileID( T* p, lua_State *L ) { lua_pushstring(L, p->m_sEditLocalProfileID.Get() ); return 1; }
|
2005-08-04 21:13:29 +00:00
|
|
|
static int GetEditLocalProfile( T* p, lua_State *L )
|
|
|
|
|
{
|
|
|
|
|
Profile *pProfile = p->GetEditLocalProfile();
|
|
|
|
|
if( pProfile )
|
|
|
|
|
pProfile->PushSelf(L);
|
|
|
|
|
else
|
|
|
|
|
lua_pushnil( L );
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2005-07-30 19:34:23 +00:00
|
|
|
|
2005-10-15 04:44:31 +00:00
|
|
|
static int GetCurrentStepsCredits( T* p, lua_State *L )
|
|
|
|
|
{
|
|
|
|
|
const Song* pSong = p->m_pCurSong;
|
|
|
|
|
if( pSong == NULL )
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
// use a vector and not a set so that ordering is maintained
|
2005-10-31 03:34:05 +00:00
|
|
|
vector<const Steps*> vpStepsToShow;
|
2005-10-15 04:44:31 +00:00
|
|
|
FOREACH_HumanPlayer( p )
|
|
|
|
|
{
|
2005-10-31 03:34:05 +00:00
|
|
|
const Steps* pSteps = GAMESTATE->m_pCurSteps[p];
|
2005-10-15 04:44:31 +00:00
|
|
|
bool bAlreadyAdded = find( vpStepsToShow.begin(), vpStepsToShow.end(), pSteps ) != vpStepsToShow.end();
|
|
|
|
|
if( !bAlreadyAdded )
|
|
|
|
|
vpStepsToShow.push_back( pSteps );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for( unsigned i=0; i<vpStepsToShow.size(); i++ )
|
|
|
|
|
{
|
|
|
|
|
const Steps* pSteps = vpStepsToShow[i];
|
2006-01-22 01:00:06 +00:00
|
|
|
RString sDifficulty = DifficultyToLocalizedString( pSteps->GetDifficulty() );
|
2005-10-15 04:44:31 +00:00
|
|
|
|
2005-10-31 03:34:05 +00:00
|
|
|
lua_pushstring( L, sDifficulty );
|
|
|
|
|
lua_pushstring( L, pSteps->GetDescription() );
|
2005-10-15 04:44:31 +00:00
|
|
|
}
|
|
|
|
|
|
2005-10-31 03:34:05 +00:00
|
|
|
return vpStepsToShow.size()*2;
|
2005-10-15 04:44:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2005-02-12 21:07:13 +00:00
|
|
|
static void Register(lua_State *L)
|
|
|
|
|
{
|
2005-09-10 02:47:04 +00:00
|
|
|
ADD_METHOD( IsPlayerEnabled );
|
|
|
|
|
ADD_METHOD( IsHumanPlayer );
|
|
|
|
|
ADD_METHOD( GetPlayerDisplayName );
|
|
|
|
|
ADD_METHOD( GetMasterPlayerNumber );
|
|
|
|
|
ADD_METHOD( GetMultiplayer );
|
|
|
|
|
ADD_METHOD( GetPlayerState );
|
2006-04-21 00:43:32 +00:00
|
|
|
ADD_METHOD( GetMultiPlayerState );
|
2005-09-10 02:47:04 +00:00
|
|
|
ADD_METHOD( ApplyGameCommand );
|
|
|
|
|
ADD_METHOD( GetCurrentSong );
|
|
|
|
|
ADD_METHOD( SetCurrentSong );
|
|
|
|
|
ADD_METHOD( GetCurrentSteps );
|
|
|
|
|
ADD_METHOD( SetCurrentSteps );
|
|
|
|
|
ADD_METHOD( GetCurrentCourse );
|
|
|
|
|
ADD_METHOD( SetCurrentCourse );
|
|
|
|
|
ADD_METHOD( GetCurrentTrail );
|
2005-10-31 03:34:48 +00:00
|
|
|
ADD_METHOD( SetCurrentTrail );
|
2005-09-10 02:47:04 +00:00
|
|
|
ADD_METHOD( SetPreferredSong );
|
|
|
|
|
ADD_METHOD( GetPreferredSong );
|
|
|
|
|
ADD_METHOD( SetTemporaryEventMode );
|
|
|
|
|
ADD_METHOD( Env );
|
|
|
|
|
ADD_METHOD( SetEnv );
|
|
|
|
|
ADD_METHOD( GetEnv );
|
|
|
|
|
ADD_METHOD( GetEditSourceSteps );
|
|
|
|
|
ADD_METHOD( GetPreferredDifficulty );
|
|
|
|
|
ADD_METHOD( AnyPlayerHasRankingFeats );
|
|
|
|
|
ADD_METHOD( IsCourseMode );
|
|
|
|
|
ADD_METHOD( IsDemonstration );
|
|
|
|
|
ADD_METHOD( GetPlayMode );
|
|
|
|
|
ADD_METHOD( GetSortOrder );
|
|
|
|
|
ADD_METHOD( StageIndex );
|
|
|
|
|
ADD_METHOD( IsGoalComplete );
|
|
|
|
|
ADD_METHOD( PlayerIsUsingModifier );
|
|
|
|
|
ADD_METHOD( GetCourseSongIndex );
|
2006-04-29 02:03:08 +00:00
|
|
|
ADD_METHOD( GetLoadingCourseSongIndex );
|
2005-09-10 02:47:04 +00:00
|
|
|
ADD_METHOD( IsFinalStage );
|
|
|
|
|
ADD_METHOD( IsExtraStage );
|
|
|
|
|
ADD_METHOD( IsExtraStage2 );
|
|
|
|
|
ADD_METHOD( GetCurrentStage );
|
|
|
|
|
ADD_METHOD( IsStagePossible );
|
|
|
|
|
ADD_METHOD( HasEarnedExtraStage );
|
|
|
|
|
ADD_METHOD( GetEasiestStepsDifficulty );
|
|
|
|
|
ADD_METHOD( IsEventMode );
|
|
|
|
|
ADD_METHOD( GetNumPlayersEnabled );
|
|
|
|
|
ADD_METHOD( GetSongBeat );
|
2005-10-10 04:50:53 +00:00
|
|
|
ADD_METHOD( GetGameplayLeadIn );
|
2005-09-10 02:47:04 +00:00
|
|
|
ADD_METHOD( PlayerUsingBothSides );
|
|
|
|
|
ADD_METHOD( GetCoins );
|
|
|
|
|
ADD_METHOD( IsSideJoined );
|
|
|
|
|
ADD_METHOD( GetCoinsNeededToJoin );
|
|
|
|
|
ADD_METHOD( PlayersCanJoin );
|
|
|
|
|
ADD_METHOD( GetNumSidesJoined );
|
|
|
|
|
ADD_METHOD( GetCoinMode );
|
|
|
|
|
ADD_METHOD( GetPremium );
|
|
|
|
|
ADD_METHOD( GetSongOptionsString );
|
|
|
|
|
ADD_METHOD( IsWinner );
|
2005-09-10 18:32:40 +00:00
|
|
|
ADD_METHOD( IsDraw );
|
2005-09-10 02:47:04 +00:00
|
|
|
ADD_METHOD( IsDisqualified );
|
|
|
|
|
ADD_METHOD( GetCurrentGame );
|
|
|
|
|
ADD_METHOD( GetEditCourseEntryIndex );
|
|
|
|
|
ADD_METHOD( GetEditLocalProfileID );
|
|
|
|
|
ADD_METHOD( GetEditLocalProfile );
|
2005-10-15 04:44:31 +00:00
|
|
|
ADD_METHOD( GetCurrentStepsCredits );
|
2005-04-15 09:07:57 +00:00
|
|
|
|
2005-02-12 21:07:13 +00:00
|
|
|
Luna<T>::Register( L );
|
|
|
|
|
|
2005-02-23 17:39:57 +00:00
|
|
|
// Add global singleton if constructed already. If it's not constructed yet,
|
|
|
|
|
// then we'll register it later when we reinit Lua just before
|
|
|
|
|
// initializing the display.
|
|
|
|
|
if( GAMESTATE )
|
|
|
|
|
{
|
|
|
|
|
lua_pushstring(L, "GAMESTATE");
|
2005-06-16 03:20:59 +00:00
|
|
|
GAMESTATE->PushSelf( L );
|
2005-02-23 17:39:57 +00:00
|
|
|
lua_settable(L, LUA_GLOBALSINDEX);
|
|
|
|
|
}
|
2005-02-12 21:07:13 +00:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
LUA_REGISTER_CLASS( GameState )
|
|
|
|
|
// lua end
|
|
|
|
|
|
2004-06-08 01:24:17 +00:00
|
|
|
/*
|
|
|
|
|
* (c) 2001-2004 Chris Danford, Glenn Maynard, Chris Gomez
|
|
|
|
|
* 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.
|
|
|
|
|
*/
|