Files
itgmania212121/stepmania/src/GameCommand.cpp
T

759 lines
20 KiB
C++
Raw Normal View History

#include "global.h"
2004-12-02 06:29:20 +00:00
#include "GameCommand.h"
#include "RageUtil.h"
#include "RageLog.h"
#include "GameManager.h"
#include "GameState.h"
#include "RageDisplay.h"
#include "AnnouncerManager.h"
#include "ProfileManager.h"
2003-09-27 01:45:46 +00:00
#include "StepMania.h"
#include "ScreenManager.h"
#include "SongManager.h"
#include "PrefsManager.h"
#include "arch/ArchHooks/ArchHooks.h"
#include "MemoryCardManager.h"
2004-02-01 02:41:23 +00:00
#include "song.h"
2004-07-25 17:07:32 +00:00
#include "Game.h"
#include "Style.h"
#include "Foreach.h"
2004-12-03 05:37:21 +00:00
#include "Command.h"
2004-12-04 21:14:46 +00:00
#include "arch/Dialog/Dialog.h"
2004-12-04 23:24:14 +00:00
#include "Bookkeeper.h"
2004-12-05 11:54:43 +00:00
#include "UnlockSystem.h"
#include "GameSoundManager.h"
#include "ThemeManager.h"
#include "PlayerState.h"
2004-12-02 06:29:20 +00:00
void GameCommand::Init()
{
2004-01-14 05:10:24 +00:00
m_sName = "";
m_bInvalid = true;
2003-09-25 05:56:38 +00:00
m_iIndex = -1;
2004-07-25 17:07:32 +00:00
m_pGame = NULL;
2004-06-28 07:26:00 +00:00
m_pStyle = NULL;
2003-09-25 05:56:38 +00:00
m_pm = PLAY_MODE_INVALID;
m_dc = DIFFICULTY_INVALID;
m_CourseDifficulty = DIFFICULTY_INVALID;
2003-09-27 08:01:17 +00:00
m_sModifiers = "";
2003-09-25 05:56:38 +00:00
m_sAnnouncer = "";
2003-09-27 01:45:46 +00:00
m_sScreen = "";
2004-01-25 16:48:09 +00:00
m_pSong = NULL;
2004-01-14 05:10:24 +00:00
m_pSteps = NULL;
2004-04-30 07:46:46 +00:00
m_pCourse = NULL;
2004-06-03 08:22:02 +00:00
m_pTrail = NULL;
2004-01-14 05:10:24 +00:00
m_pCharacter = NULL;
2004-12-04 22:33:55 +00:00
m_SortOrder = SORT_INVALID;
2004-12-05 11:54:43 +00:00
m_iUnlockIndex = -1;
m_sSoundPath = "";
m_vsScreensToPrepare.clear();
m_bDeletePreparedScreens = false;
2004-12-04 23:24:14 +00:00
m_bClearBookkeepingData = false;
m_bClearMachineStats = false;
2005-01-01 10:27:16 +00:00
m_bTransferStatsFromMachine = false;
m_bTransferStatsToMachine = false;
2004-12-04 23:24:14 +00:00
m_bInsertCredit = false;
m_bResetToFactoryDefaults = false;
2004-12-30 01:17:52 +00:00
m_bStopMusic = false;
m_bApplyDefaultOptions = false;
}
2003-09-27 19:23:34 +00:00
bool CompareSongOptions( const SongOptions &so1, const SongOptions &so2 );
2004-12-02 06:29:20 +00:00
bool GameCommand::DescribesCurrentModeForAllPlayers() const
2003-09-27 19:23:34 +00:00
{
FOREACH_HumanPlayer( pn )
2004-06-03 08:22:02 +00:00
if( !DescribesCurrentMode(pn) )
2003-09-27 19:23:34 +00:00
return false;
return true;
}
2004-12-02 06:29:20 +00:00
bool GameCommand::DescribesCurrentMode( PlayerNumber pn ) const
2003-07-20 07:32:26 +00:00
{
2004-07-25 17:07:32 +00:00
if( m_pGame != NULL && m_pGame != GAMESTATE->m_pCurGame )
2003-07-20 07:32:26 +00:00
return false;
2003-09-25 05:56:38 +00:00
if( m_pm != PLAY_MODE_INVALID && GAMESTATE->m_PlayMode != m_pm )
2003-07-20 07:32:26 +00:00
return false;
2004-06-28 07:26:00 +00:00
if( m_pStyle && GAMESTATE->m_pCurStyle != m_pStyle )
2003-07-20 07:32:26 +00:00
return false;
// HACK: don't compare m_dc if m_pSteps is set. This causes problems
// in ScreenSelectOptionsMaster::ImportOptions if m_PreferredDifficulty
// doesn't match the difficulty of m_pCurSteps.
if( m_pSteps == NULL && m_dc != DIFFICULTY_INVALID )
2003-07-20 07:32:26 +00:00
{
// Why is this checking for all players?
FOREACH_PlayerNumber( pn )
2003-09-25 05:56:38 +00:00
if( GAMESTATE->IsHumanPlayer(pn) && GAMESTATE->m_PreferredDifficulty[pn] != m_dc )
2003-07-20 07:32:26 +00:00
return false;
}
2003-09-25 05:56:38 +00:00
if( m_sAnnouncer != "" && m_sAnnouncer != ANNOUNCER->GetCurAnnouncerName() )
2003-07-20 07:32:26 +00:00
return false;
2003-09-27 19:23:34 +00:00
if( m_sModifiers != "" )
{
/* Apply modifiers. */
PlayerOptions po = GAMESTATE->m_pPlayerState[pn]->m_PlayerOptions;
SongOptions so = GAMESTATE->m_SongOptions;
po.FromString( m_sModifiers );
so.FromString( m_sModifiers );
2003-09-27 19:23:34 +00:00
if( po != GAMESTATE->m_pPlayerState[pn]->m_PlayerOptions )
2004-01-11 04:33:21 +00:00
return false;
if( so != GAMESTATE->m_SongOptions )
2003-09-27 19:23:34 +00:00
return false;
}
2004-01-25 16:48:09 +00:00
if( m_pSong && GAMESTATE->m_pCurSong != m_pSong )
return false;
2004-05-24 06:12:17 +00:00
if( m_pSteps && GAMESTATE->m_pCurSteps[pn] != m_pSteps )
2004-01-14 05:10:24 +00:00
return false;
if( m_pCharacter && GAMESTATE->m_pCurCharacters[pn] != m_pCharacter )
return false;
2004-06-03 08:22:02 +00:00
if( m_pTrail && GAMESTATE->m_pCurTrail[pn] != m_pTrail )
return false;
if( m_SortOrder != SORT_INVALID && GAMESTATE->m_SortOrder != m_SortOrder )
2004-12-04 22:33:55 +00:00
return false;
2004-01-14 05:10:24 +00:00
2003-07-20 07:32:26 +00:00
return true;
}
2004-12-03 05:37:21 +00:00
void GameCommand::Load( int iIndex, const Commands& cmds )
{
2003-09-25 05:56:38 +00:00
m_iIndex = iIndex;
2003-09-25 06:44:25 +00:00
m_bInvalid = false;
2004-02-01 02:41:23 +00:00
CString sSteps;
2004-12-03 05:37:21 +00:00
FOREACH_CONST( Command, cmds.v, command )
{
2004-12-03 05:37:21 +00:00
CString sName = command->GetName();
if( sName.empty() )
continue;
2003-09-21 20:10:15 +00:00
2004-12-03 05:37:21 +00:00
CString sValue = join( ",", command->m_vsArgs.begin()+1, command->m_vsArgs.end() );
2003-09-21 20:10:15 +00:00
if( sName == "game" )
{
2004-07-25 17:07:32 +00:00
const Game* pGame = GAMEMAN->StringToGameType( sValue );
if( pGame != NULL )
2004-07-25 17:07:32 +00:00
m_pGame = pGame;
2003-09-21 20:10:15 +00:00
else
2003-09-25 05:56:38 +00:00
m_bInvalid |= true;
2003-09-21 20:10:15 +00:00
}
else if( sName == "style" )
{
const Style* style = GAMEMAN->GameAndStringToStyle( GAMESTATE->m_pCurGame, sValue );
if( style )
2004-06-28 07:26:00 +00:00
m_pStyle = style;
2003-09-21 20:10:15 +00:00
else
2003-09-25 05:56:38 +00:00
m_bInvalid |= true;
}
else if( sName == "playmode" )
{
2003-09-21 20:10:15 +00:00
PlayMode pm = StringToPlayMode( sValue );
if( pm != PLAY_MODE_INVALID )
2003-09-25 05:56:38 +00:00
m_pm = pm;
2003-09-21 20:10:15 +00:00
else
2003-09-25 05:56:38 +00:00
m_bInvalid |= true;
}
else if( sName == "difficulty" )
{
2003-09-21 20:10:15 +00:00
Difficulty dc = StringToDifficulty( sValue );
if( dc != DIFFICULTY_INVALID )
2003-09-25 05:56:38 +00:00
m_dc = dc;
2003-09-21 20:10:15 +00:00
else
2003-09-25 05:56:38 +00:00
m_bInvalid |= true;
}
else if( sName == "announcer" )
{
2003-09-25 05:56:38 +00:00
m_sAnnouncer = sValue;
}
else if( sName == "name" )
{
2003-09-25 21:27:14 +00:00
m_sName = sValue;
}
2003-09-27 01:45:46 +00:00
else if( sName == "mod" )
2003-09-27 01:45:46 +00:00
{
2003-09-27 08:01:17 +00:00
if( m_sModifiers != "" )
m_sModifiers += ",";
m_sModifiers += sValue;
2003-09-27 03:06:35 +00:00
}
2003-09-27 08:01:17 +00:00
else if( sName == "song" )
2004-01-25 16:48:09 +00:00
{
m_pSong = SONGMAN->FindSong( sValue );
if( m_pSong == NULL )
2004-04-30 07:46:46 +00:00
{
m_sInvalidReason = ssprintf( "Song \"%s\" not found", sValue.c_str() );
2004-01-25 16:48:09 +00:00
m_bInvalid |= true;
2004-04-30 07:46:46 +00:00
}
2004-01-25 16:48:09 +00:00
}
else if( sName == "steps" )
2004-02-01 02:41:23 +00:00
{
/* Save the name of the steps, and set this later, since we want to process
* any "song" and "style" commands first. */
sSteps = sValue;
}
else if( sName == "course" )
2004-04-30 07:46:46 +00:00
{
m_pCourse = SONGMAN->FindCourse( sValue );
if( m_pCourse == NULL )
{
m_sInvalidReason = ssprintf( "Course \"%s\" not found", sValue.c_str() );
m_bInvalid |= true;
}
}
else if( sName == "screen" )
{
2003-09-27 08:01:17 +00:00
m_sScreen = sValue;
}
else if( sName == "setenv" )
{
2004-12-03 05:37:21 +00:00
if( command->m_vsArgs.size() == 3 )
m_SetEnv[ command->m_vsArgs[1] ] = command->m_vsArgs[2];
}
else if( sName == "songgroup" )
{
m_sSongGroup = sValue;
}
2004-12-04 21:14:46 +00:00
2004-12-04 22:33:55 +00:00
else if( sName == "sort" )
{
m_SortOrder = StringToSortOrder( sValue );
if( m_SortOrder == SORT_INVALID )
{
m_sInvalidReason = ssprintf( "SortOrder \"%s\" is not valid.", sValue.c_str() );
m_bInvalid |= true;
}
}
2004-12-04 23:24:14 +00:00
2004-12-05 11:54:43 +00:00
else if( sName == "unlock" )
{
m_iUnlockIndex = atoi( sValue );
}
else if( sName == "sound" )
{
m_sSoundPath = sValue;
}
else if( sName == "preparescreen" )
{
m_vsScreensToPrepare.push_back( sValue );
}
else if( sName == "deletepreparedscreens" )
{
m_bDeletePreparedScreens = true;
}
2004-12-05 11:54:43 +00:00
else if( sName == "clearbookkeepingdata" )
2004-12-04 23:24:14 +00:00
{
m_bClearBookkeepingData = true;
}
2004-12-05 11:54:43 +00:00
else if( sName == "clearmachinestats" )
2004-12-04 23:24:14 +00:00
{
m_bClearMachineStats = true;
}
2005-01-01 10:27:16 +00:00
else if( sName == "transferstatsfrommachine" )
2004-12-04 23:24:14 +00:00
{
2005-01-01 10:27:16 +00:00
m_bTransferStatsFromMachine = true;
}
else if( sName == "transferstatstomachine" )
{
m_bTransferStatsToMachine = true;
2004-12-04 23:24:14 +00:00
}
2004-12-05 11:54:43 +00:00
else if( sName == "insertcredit" )
2004-12-04 23:24:14 +00:00
{
m_bInsertCredit = true;
}
2004-12-05 11:54:43 +00:00
else if( sName == "resettofactorydefaults" )
2004-12-04 23:24:14 +00:00
{
m_bResetToFactoryDefaults = true;
}
2004-12-30 01:17:52 +00:00
else if( sName == "stopmusic" )
{
m_bStopMusic = true;
}
else if( sName == "applydefaultoptions" )
{
m_bApplyDefaultOptions = true;
}
2004-12-04 22:33:55 +00:00
2004-12-04 21:14:46 +00:00
else
{
CString sWarning = ssprintf( "Command '%s' is not valid.", command->GetOriginalCommandString().c_str() );
LOG->Warn( sWarning );
2004-12-04 21:17:04 +00:00
Dialog::OK( sWarning, "INVALID_GAME_COMMAND" );
2004-12-04 21:14:46 +00:00
}
2003-09-27 03:06:35 +00:00
}
2004-02-01 02:41:23 +00:00
if( !m_bInvalid && sSteps != "" )
{
2004-04-30 07:46:46 +00:00
Song *pSong = (m_pSong != NULL)? m_pSong:GAMESTATE->m_pCurSong;
2004-06-28 07:26:00 +00:00
const Style *style = m_pStyle ? m_pStyle : GAMESTATE->m_pCurStyle;
if( pSong == NULL || style == NULL )
2004-02-01 02:41:23 +00:00
RageException::Throw( "Must set Song and Style to set Steps" );
2004-04-30 07:46:46 +00:00
Difficulty dc = StringToDifficulty( sSteps );
if( dc != DIFFICULTY_EDIT )
2004-06-28 07:26:00 +00:00
m_pSteps = pSong->GetStepsByDifficulty( m_pStyle->m_StepsType, dc );
2004-04-30 07:46:46 +00:00
else
2004-06-28 07:26:00 +00:00
m_pSteps = pSong->GetStepsByDescription( m_pStyle->m_StepsType, sSteps );
2004-02-01 02:41:23 +00:00
if( m_pSteps == NULL )
2004-04-30 07:46:46 +00:00
{
m_sInvalidReason = "steps not found";
2004-02-01 02:41:23 +00:00
m_bInvalid |= true;
2004-04-30 07:46:46 +00:00
}
2004-02-01 02:41:23 +00:00
}
2003-09-27 03:06:35 +00:00
}
2003-09-27 01:45:46 +00:00
2004-06-04 21:12:03 +00:00
int GetNumCreditsPaid()
{
int iNumCreditsPaid = GAMESTATE->GetNumSidesJoined();
// players other than the first joined for free
if( PREFSMAN->GetPremium() == PREMIUM_JOINT )
2004-06-04 21:12:03 +00:00
iNumCreditsPaid = min( iNumCreditsPaid, 1 );
return iNumCreditsPaid;
}
2004-06-28 07:26:00 +00:00
int GetCreditsRequiredToPlayStyle( const Style *style )
2003-11-07 20:14:29 +00:00
{
if( PREFSMAN->GetPremium() == PREMIUM_JOINT )
return 1;
switch( style->m_StyleType )
2003-11-07 20:14:29 +00:00
{
case ONE_PLAYER_ONE_SIDE:
2003-11-07 20:14:29 +00:00
return 1;
case TWO_PLAYERS_TWO_SIDES:
2003-11-07 20:14:29 +00:00
return 2;
case ONE_PLAYER_TWO_SIDES:
return (PREFSMAN->GetPremium() == PREMIUM_DOUBLES) ? 1 : 2;
2003-11-07 20:14:29 +00:00
default:
ASSERT(0);
return 1;
}
}
2004-06-28 07:26:00 +00:00
static bool AreStyleAndPlayModeCompatible( const Style *style, PlayMode pm )
2004-03-20 18:11:17 +00:00
{
if( style == NULL || pm == PLAY_MODE_INVALID )
2004-03-20 18:11:17 +00:00
return true;
switch( pm )
{
case PLAY_MODE_BATTLE:
case PLAY_MODE_RAVE:
// Can't play rave if there isn't enough room for two players.
// This is correct for dance (ie, no rave for solo and doubles),
// and should be okay for pump .. not sure about other game types.
// Techno Motion scales down versus arrows, though, so allow this.
if( style->m_iColsPerPlayer >= 6 && CString(GAMESTATE->m_pCurGame->m_szName) != "techno" )
2004-03-20 18:11:17 +00:00
return false;
/* Don't allow battle modes if the style takes both sides. */
if( style->m_StyleType==ONE_PLAYER_TWO_SIDES )
2004-03-20 18:11:17 +00:00
return false;
}
return true;
}
2004-12-02 06:29:20 +00:00
bool GameCommand::IsPlayable( CString *why ) const
2003-09-27 03:06:35 +00:00
{
if( m_bInvalid )
2004-04-30 07:46:46 +00:00
{
2004-05-16 12:05:51 +00:00
if( why )
2004-04-30 07:46:46 +00:00
*why = m_sInvalidReason;
2003-09-27 03:06:35 +00:00
return false;
2004-04-30 07:46:46 +00:00
}
2003-09-27 03:06:35 +00:00
2004-06-28 07:26:00 +00:00
if ( m_pStyle )
2003-09-27 03:06:35 +00:00
{
2004-05-07 08:08:11 +00:00
int iCredits = GAMESTATE->m_iCoins / PREFSMAN->m_iCoinsPerCredit;
const int iNumCreditsPaid = GetNumCreditsPaid();
2004-06-28 07:26:00 +00:00
const int iNumCreditsRequired = GetCreditsRequiredToPlayStyle(m_pStyle);
switch( PREFSMAN->GetCoinMode() )
{
case COIN_HOME:
case COIN_FREE:
iCredits = NUM_PLAYERS; /* not iNumCreditsPaid */
}
/* With PREFSMAN->m_bDelayedCreditsReconcile disabled, enough credits must be
* paid. (This means that enough sides must be joined.) Enabled, simply having
* enough credits lying in the machine is sufficient; we'll deduct the extra in
* Apply(). */
int iNumCreditsAvailable = iNumCreditsPaid;
2004-05-07 08:08:11 +00:00
if( PREFSMAN->m_bDelayedCreditsReconcile )
iNumCreditsAvailable += iCredits;
if( iNumCreditsAvailable < iNumCreditsRequired )
{
if( why )
*why = ssprintf( "need %i credits, have %i", iNumCreditsRequired, iNumCreditsAvailable );
return false;
}
/* If you've paid too much already, don't allow the mode. (If we allow this,
* the credits will be "refunded" in Apply(), but that's confusing.) */
/* Do allow the mode if they've already joined in more credits than
* are required. Otherwise, people who put in two credits to play
* doubles on a doubles-premium machiune will get locked out.
* the refund logic isn't that awkward because you never see the
* credits number jump up - the credits display is hidden if both
* sides are joined. -Chris */
//if( PREFSMAN->m_iCoinMode == COIN_PAY && iNumCreditsPaid > iNumCreditsRequired )
//{
// if( why )
// *why = ssprintf( "too many credits paid (%i > %i)", iNumCreditsPaid, iNumCreditsRequired );
// return false;
//}
2004-05-07 08:08:11 +00:00
/* If both sides are joined, disallow singles modes, since easy to select them
* accidentally, instead of versus mode. */
if( m_pStyle->m_StyleType == ONE_PLAYER_ONE_SIDE &&
GAMESTATE->GetNumSidesJoined() > 1 )
{
if( why )
*why = "too many players joined for ONE_PLAYER_ONE_CREDIT";
2003-11-09 01:09:35 +00:00
return false;
}
2003-09-27 03:06:35 +00:00
}
/* Don't allow a PlayMode that's incompatible with our current Style (if set),
* and vice versa. */
2004-06-28 07:26:00 +00:00
if( m_pm != PLAY_MODE_INVALID || m_pStyle != NULL )
2003-09-27 03:06:35 +00:00
{
const PlayMode pm = (m_pm != PLAY_MODE_INVALID) ? m_pm : GAMESTATE->m_PlayMode;
2004-06-28 07:26:00 +00:00
const Style *style = (m_pStyle != NULL)? m_pStyle: GAMESTATE->m_pCurStyle;
2004-03-20 18:11:17 +00:00
if( !AreStyleAndPlayModeCompatible( style, pm ) )
{
if( why )
*why = ssprintf("mode %s is incompatible with style %s",
PlayModeToString(pm).c_str(), style->m_szName );
2004-03-20 18:11:17 +00:00
return false;
}
}
2003-09-27 03:06:35 +00:00
if( !m_sScreen.CompareNoCase("ScreenEditCoursesMenu") )
{
vector<Course*> vCourses;
SONGMAN->GetAllCourses( vCourses, false );
if( vCourses.size() == 0 )
{
if( why )
*why = "No courses are installed";
return false;
}
}
if( !m_sScreen.CompareNoCase("ScreenJukeboxMenu") ||
!m_sScreen.CompareNoCase("ScreenEditMenu") ||
!m_sScreen.CompareNoCase("ScreenEditCoursesMenu") )
{
if( SONGMAN->GetNumSongs() == 0 )
{
if( why )
*why = "No songs are installed";
return false;
}
}
return true;
}
2004-12-02 06:29:20 +00:00
void GameCommand::ApplyToAllPlayers() const
{
vector<PlayerNumber> vpns;
FOREACH_HumanPlayer( pn )
vpns.push_back( pn );
2003-09-27 01:45:46 +00:00
Apply( vpns );
}
2004-12-02 06:29:20 +00:00
void GameCommand::Apply( PlayerNumber pn ) const
{
2003-11-08 15:49:48 +00:00
if( !GAMESTATE->IsHumanPlayer(pn) )
return;
vector<PlayerNumber> vpns;
vpns.push_back( pn );
Apply( vpns );
}
void GameCommand::Apply( const vector<PlayerNumber> &vpns ) const
{
const PlayMode OldPlayMode = GAMESTATE->m_PlayMode;
2004-07-25 17:07:32 +00:00
if( m_pGame != NULL )
GAMESTATE->m_pCurGame = m_pGame;
2003-09-25 05:56:38 +00:00
if( m_pm != PLAY_MODE_INVALID )
GAMESTATE->m_PlayMode = m_pm;
2004-06-28 07:26:00 +00:00
if( m_pStyle != NULL )
{
2004-06-28 07:26:00 +00:00
GAMESTATE->m_pCurStyle = m_pStyle;
2004-05-07 08:08:11 +00:00
// It's possible to choose a style that didn't have enough
// players joined. If enough players aren't joined, then
// we need to subtract credits for the sides that will be
// joined as a result of applying this option.
if( PREFSMAN->m_CoinMode == COIN_PAY )
{
int iNumCreditsRequired = GetCreditsRequiredToPlayStyle(m_pStyle);
int iNumCreditsPaid = GetNumCreditsPaid();
int iNumCreditsOwed = iNumCreditsRequired - iNumCreditsPaid;
GAMESTATE->m_iCoins -= iNumCreditsOwed * PREFSMAN->m_iCoinsPerCredit;
LOG->Trace( "Deducted %i coins, %i remaining",
iNumCreditsOwed * PREFSMAN->m_iCoinsPerCredit, GAMESTATE->m_iCoins );
}
2004-05-07 08:08:11 +00:00
// If only one side is joined and we picked a style
// that requires both sides, join the other side.
2004-06-28 07:26:00 +00:00
switch( m_pStyle->m_StyleType )
{
case ONE_PLAYER_ONE_SIDE:
break;
case TWO_PLAYERS_TWO_SIDES:
case ONE_PLAYER_TWO_SIDES:
2004-05-07 08:08:11 +00:00
{
FOREACH_PlayerNumber( p )
GAMESTATE->m_bSideIsJoined[p] = true;
}
break;
default:
ASSERT(0);
}
}
if( m_dc != DIFFICULTY_INVALID )
FOREACH_CONST( PlayerNumber, vpns, pn )
GAMESTATE->ChangePreferredDifficulty( *pn, m_dc );
2003-09-25 05:56:38 +00:00
if( m_sAnnouncer != "" )
ANNOUNCER->SwitchAnnouncer( m_sAnnouncer );
2003-09-27 08:01:17 +00:00
if( m_sModifiers != "" )
FOREACH_CONST( PlayerNumber, vpns, pn )
GAMESTATE->ApplyModifiers( *pn, m_sModifiers );
if( m_sScreen != "" )
SCREENMAN->SetNewScreen( m_sScreen );
2004-01-25 16:48:09 +00:00
if( m_pSong )
{
2004-01-25 16:48:09 +00:00
GAMESTATE->m_pCurSong = m_pSong;
GAMESTATE->m_pPreferredSong = m_pSong;
}
2004-01-14 05:10:24 +00:00
if( m_pSteps )
FOREACH_CONST( PlayerNumber, vpns, pn )
GAMESTATE->m_pCurSteps[*pn] = m_pSteps;
2004-04-30 07:46:46 +00:00
if( m_pCourse )
{
2004-04-30 07:46:46 +00:00
GAMESTATE->m_pCurCourse = m_pCourse;
GAMESTATE->m_pPreferredCourse = m_pCourse;
}
2004-06-03 08:22:02 +00:00
if( m_pTrail )
FOREACH_CONST( PlayerNumber, vpns, pn )
GAMESTATE->m_pCurTrail[*pn] = m_pTrail;
if( m_CourseDifficulty != DIFFICULTY_INVALID )
FOREACH_CONST( PlayerNumber, vpns, pn )
GAMESTATE->ChangePreferredCourseDifficulty( *pn, m_CourseDifficulty );
2004-01-14 05:10:24 +00:00
if( m_pCharacter )
FOREACH_CONST( PlayerNumber, vpns, pn )
GAMESTATE->m_pCurCharacters[*pn] = m_pCharacter;
for( map<CString,CString>::const_iterator i = m_SetEnv.begin(); i != m_SetEnv.end(); i++ )
GAMESTATE->m_mapEnv[ i->first ] = i->second;
if( !m_sSongGroup.empty() )
GAMESTATE->m_sPreferredSongGroup = m_sSongGroup;
2004-12-04 22:33:55 +00:00
if( m_SortOrder != SORT_INVALID )
GAMESTATE->m_SortOrder = m_SortOrder;
2004-12-05 11:54:43 +00:00
if( m_iUnlockIndex != -1 )
UNLOCKMAN->UnlockCode( m_iUnlockIndex );
if( m_sSoundPath != "" )
SOUND->PlayOnce( THEME->GetPathToS( m_sSoundPath ) );
2005-01-05 03:46:09 +00:00
/* If we're going to stop music, do so before preparing new screens, so we don't
* stop music between preparing screens and loading screens. */
if( m_bStopMusic )
SOUND->StopMusic();
FOREACH_CONST( CString, m_vsScreensToPrepare, s )
SCREENMAN->PrepareScreen( *s );
if( m_bDeletePreparedScreens )
SCREENMAN->DeletePreparedScreens();
2004-12-04 23:24:14 +00:00
if( m_bClearBookkeepingData )
{
BOOKKEEPER->ClearAll();
BOOKKEEPER->WriteToDisk();
SCREENMAN->SystemMessage( "Bookkeeping data cleared." );
}
if( m_bClearMachineStats )
{
Profile* pProfile = PROFILEMAN->GetMachineProfile();
// don't reset the Guid
CString sGuid = pProfile->m_sGuid;
pProfile->InitAll();
pProfile->m_sGuid = sGuid;
PROFILEMAN->SaveMachineProfile();
SCREENMAN->SystemMessage( "Machine stats cleared." );
}
2005-01-01 10:27:16 +00:00
if( m_bTransferStatsFromMachine )
2004-12-04 23:24:14 +00:00
{
MEMCARDMAN->TryMountAllCards();
2005-01-01 10:27:16 +00:00
bool bTriedToSave = false;
2004-12-04 23:24:14 +00:00
FOREACH_PlayerNumber( pn )
{
if( MEMCARDMAN->GetCardState(pn) != MEMORY_CARD_STATE_READY )
continue; // skip
2005-01-01 10:27:16 +00:00
bTriedToSave = true;
2004-12-04 23:24:14 +00:00
CString sDir = MEM_CARD_MOUNT_POINT[pn];
sDir += "MachineProfile/";
bool bSaved = PROFILEMAN->GetMachineProfile()->SaveAllToDir( sDir, PREFSMAN->m_bSignProfileData );
if( bSaved )
SCREENMAN->SystemMessage( ssprintf("Machine stats saved to P%d card.",pn+1) );
else
2005-01-01 10:27:16 +00:00
SCREENMAN->SystemMessage( ssprintf("Error saving machine stats to P%d card.",pn+1) );
break;
2004-12-04 23:24:14 +00:00
}
2005-01-01 10:27:16 +00:00
if( !bTriedToSave )
SCREENMAN->SystemMessage( "Stats not saved - No memory cards ready." );
2004-12-04 23:24:14 +00:00
MEMCARDMAN->FlushAndReset();
2005-01-01 10:27:16 +00:00
}
if( m_bTransferStatsToMachine )
{
MEMCARDMAN->TryMountAllCards();
bool bTriedToLoad = false;
FOREACH_PlayerNumber( pn )
{
if( MEMCARDMAN->GetCardState(pn) != MEMORY_CARD_STATE_READY )
continue; // skip
2004-12-04 23:24:14 +00:00
2005-01-01 10:27:16 +00:00
bTriedToLoad = true;
CString sDir = MEM_CARD_MOUNT_POINT[pn];
sDir += "MachineProfile/";
Profile backup = *PROFILEMAN->GetMachineProfile();
Profile::LoadResult lr = PROFILEMAN->GetMachineProfile()->LoadAllFromDir( sDir, PREFSMAN->m_bSignProfileData );
switch( lr )
{
case Profile::success:
SCREENMAN->SystemMessage( ssprintf("Machine stats loaded from P%d card.",pn+1) );
break;
case Profile::failed_no_profile:
SCREENMAN->SystemMessage( ssprintf("There is no profile on P%d card.",pn+1) );
*PROFILEMAN->GetMachineProfile() = backup;
break;
case Profile::failed_tampered:
SCREENMAN->SystemMessage( ssprintf("The profile on P%d card contains tampered data.",pn+1) );
*PROFILEMAN->GetMachineProfile() = backup;
break;
default:
ASSERT(0);
}
break;
}
if( !bTriedToLoad )
SCREENMAN->SystemMessage( "Stats not loaded - No memory cards ready." );
MEMCARDMAN->FlushAndReset();
2004-12-04 23:24:14 +00:00
}
if( m_bInsertCredit )
{
InsertCredit();
}
if( m_bResetToFactoryDefaults )
{
PREFSMAN->ResetToFactoryDefaults();
SCREENMAN->SystemMessage( "All options reset to factory defaults." );
}
if( m_bApplyDefaultOptions )
{
FOREACH_PlayerNumber( p )
GAMESTATE->m_pPlayerState[p]->m_PlayerOptions.FromString( PREFSMAN->m_sDefaultModifiers );
GAMESTATE->m_SongOptions.FromString( PREFSMAN->m_sDefaultModifiers );
}
// HACK: Set life type to BATTERY just once here so it happens once and
// we don't override the user's changes if they back out.
if( GAMESTATE->m_PlayMode == PLAY_MODE_ONI && GAMESTATE->m_PlayMode != OldPlayMode )
GAMESTATE->m_SongOptions.m_LifeType = SongOptions::LIFE_BATTERY;
}
2003-09-29 08:56:33 +00:00
2004-12-02 06:29:20 +00:00
bool GameCommand::IsZero() const
2003-09-29 08:56:33 +00:00
{
2004-07-25 17:07:32 +00:00
if( m_pGame != NULL ||
2003-09-29 08:56:33 +00:00
m_pm != PLAY_MODE_INVALID ||
2004-06-28 07:26:00 +00:00
m_pStyle != NULL ||
2003-09-29 08:56:33 +00:00
m_dc != DIFFICULTY_INVALID ||
m_sAnnouncer != "" ||
m_sModifiers != "" ||
2004-01-25 16:48:09 +00:00
m_pSong != NULL ||
m_pSteps != NULL ||
2004-06-03 20:25:29 +00:00
m_pCourse != NULL ||
m_pTrail != NULL ||
m_pCharacter != NULL ||
2004-12-04 22:33:55 +00:00
m_CourseDifficulty != DIFFICULTY_INVALID ||
m_SortOrder != SORT_INVALID
)
2003-09-29 08:56:33 +00:00
return false;
return true;
}
2004-05-31 22:42:12 +00:00
/*
* (c) 2001-2004 Chris Danford, Glenn Maynard
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, and/or sell copies of the Software, and to permit persons to
* whom the Software is furnished to do so, provided that the above
* copyright notice(s) and this permission notice appear in all copies of
* the Software and that both the above copyright notice(s) and this
* permission notice appear in supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/