diff --git a/Docs/Changelog_sm5.txt b/Docs/Changelog_sm5.txt index 64fdd5115f..1887d83591 100644 --- a/Docs/Changelog_sm5.txt +++ b/Docs/Changelog_sm5.txt @@ -15,6 +15,34 @@ ________________________________________________________________________________ * [Player] "ComboBreakOnImmediateHoldLetGo" theme metric added. [sillybear] * [PlayerState] ApplyPreferredOptionsToOtherLevels function added. [kyzentun] +2014/12/07 +---------- +* [Game] GetSeparateStyles function added. Use this to detect whether a game + allows the players to play different styles. [kyzentun] (used by kickbox) +* [GameManager] Lua Scripts/ folders are now reloaded when the Game mode is + changed. [kyzentun] +* [GameState] CanSafelyEnterGameplay function added. [kyzentun] + In kickbox game mode, players can have different styles set, pass a + PlayerNumber when using SetCurrentStyle or GetCurrentStyle. +* [kickbox] New game mode with 4 styles. [kyzentun] +* [ScreenGameplay] Notefield positioning is handled a bit differently now. + See comments in _fallback/metrics.ini above the [ScreenGameplay] + MarginFunction metric. Basically, you can define a lua function that + returns the space you want at the edges and in the center instead of + setting position metrics. Do NOT use Style:GetWidth to calculate the + margins your function returns. + ScreenGameplay now handles zooming the notefield to fit in the space + instead of using the NeedsZoomOutWith2Players flag in the style. + If the notefield doesn't fit in the space between the margins, and there is + only one player, the player will be centered even if the Center1Player pref + is false. [kyzentun] +* [Style] NeedsZoomOutWith2Players decapitated. Always returns false now. + GetWidth added. [kyzentun] +* [techno] Techno game mode no longer has special column width for versus. + Techno was the only game mode that used the NeedsZoomOutWith2Players flag, + and the zoom factor it applied was 0.6, and the special versus column width + was 0.6*normal, so this should make no difference. [kyzentun] + 2014/12/03 ---------- * [command line arg] --game command line arg added for setting the game type @@ -68,6 +96,10 @@ ________________________________________________________________________________ ---------- * [RollingNumbers] Cropping and color during tweens fixed. [kyzentun] +2014/10/27 +---------- +* [Changelog] Vospi read the release notes. + 2014/10/23 ---------- * [Global] approach, multiapproach, lerp, and lerp_color lua functions added. [kyzentun] diff --git a/Docs/Luadoc/Lua.xml b/Docs/Luadoc/Lua.xml index 0500f90ab0..156b39ba02 100644 --- a/Docs/Luadoc/Lua.xml +++ b/Docs/Luadoc/Lua.xml @@ -702,6 +702,7 @@ + @@ -750,6 +751,7 @@ + @@ -1659,6 +1661,7 @@ + diff --git a/Docs/Luadoc/LuaDocumentation.xml b/Docs/Luadoc/LuaDocumentation.xml index 421749d111..7f37c5e4a2 100644 --- a/Docs/Luadoc/LuaDocumentation.xml +++ b/Docs/Luadoc/LuaDocumentation.xml @@ -2131,6 +2131,9 @@ save yourself some time, copy this for undocumented things: Returns the name of the game such as "dance" or "pump". + + Returns whether this game allows the players to have separate styles. + @@ -2270,6 +2273,16 @@ save yourself some time, copy this for undocumented things: The second argument is optional. Apply the GameCommand represented by sCommand for pn, if given. See . + + Checks various things to determine whether the game will crash when gameplay starts. Returns false and a string if gameplay cannot be entered safely.
+ Might not work in all cases, but will catch things like a player not having + steps set or no current song or style. Mainly exists for people with a custom ScreenSelectMusic replacement.
+ Example:
+ local can, reason= GAMESTATE:CanSafelyEnterGameplay()
+ if not can then
+ lua.ReportScriptError("Cannot safely enter gameplay: " .. tostring(reason))
+ end
+
Removes any stage modifiers that are illegal for course play. @@ -4716,11 +4729,14 @@ save yourself some time, copy this for undocumented things: Returns the draw order of the column. + + Returns the width of the notefield for the given player with this style. + Returns true if this style locks the difficulty for both players. - Returns true if the Style needs to be zoomed out with two players. + Deprecated. Always returns false.
diff --git a/Themes/_fallback/Scripts/03 Gameplay.lua b/Themes/_fallback/Scripts/03 Gameplay.lua index aefe34ac87..339a3c0bd8 100644 --- a/Themes/_fallback/Scripts/03 Gameplay.lua +++ b/Themes/_fallback/Scripts/03 Gameplay.lua @@ -27,6 +27,55 @@ function GetExtraColorThreshold() return Modes[CurGameName()] or 10 end +-- GameplayMargins exists to provide a layer of backwards compatibility for +-- people using the X position metrics to set where the notefields are. +-- This makes it somewhat complex. +-- Rather than trying to understand how it works, you can simply do this: +-- (example values in parentheses) +-- 1. Decide how much space you want in the center between notefields. (80) +-- 2. Decide how much space you want on each side. (40) +-- 3. Write a simple function that just returns those numbers: +-- function GameplayMargins() return 40, 80, 40 end +-- Then the engine does the work of figuring out where each notefield should +-- be centered. +function GameplayMargins(enabled_players, styletype) + local other= {[PLAYER_1]= PLAYER_2, [PLAYER_2]= PLAYER_1} + local margins= {[PLAYER_1]= {40, 40}, [PLAYER_2]= {40, 40}} + -- Use a fake style width because calculating the real style width throws off + -- the code in the engine. + local fake_style_width= 272 + -- Handle the case of a single player that is centered first because it's + -- simpler. + if Center1Player() then + local pn= enabled_players[1] + fake_style_width= 544 + local center= _screen.cx + local left= center - (fake_style_width / 2) + local right= _screen.w - center - (fake_style_width / 2) + -- center margin width will be ignored. + return left, 80, right + end + local half_screen= _screen.w / 2 + local left= {[PLAYER_1]= 0, [PLAYER_2]= half_screen} + for i, pn in ipairs(enabled_players) do + local edge= left[pn] + local center= THEME:GetMetric("ScreenGameplay", + "Player"..ToEnumShortString(pn)..ToEnumShortString(styletype).."X") + -- Adjust for the p2 center being on the right side. + center= center - edge + margins[pn][1]= center - (fake_style_width / 2) + margins[pn][2]= half_screen - center - (fake_style_width / 2) + if #enabled_players == 1 then + margins[other[pn]][1]= margins[pn][2] + margins[other[pn]][2]= margins[pn][1] + end + end + local left= margins[PLAYER_1][1] + local center= margins[PLAYER_1][2] + margins[PLAYER_2][1] + local right= margins[PLAYER_2][2] + return left, center, right +end + -- AllowOptionsMenu() -- [en] returns if you are able to select options -- on ScreenSelectMusic. diff --git a/Themes/_fallback/metrics.ini b/Themes/_fallback/metrics.ini index 81cbcf0444..3b10eb0549 100644 --- a/Themes/_fallback/metrics.ini +++ b/Themes/_fallback/metrics.ini @@ -1130,7 +1130,7 @@ AttackDisplayXOffsetOneSideP2=0 AttackDisplayXOffsetBothSides=0 AttackDisplayY=-70 AttackDisplayYReverse=70 -; HACK: These shouldn't go to the render pipe at all if IsGame("pump") +# HACK: These shouldn't go to the render pipe at all if IsGame("pump") HoldJudgmentYStandard=IsGame("pump") and -99999 or -90 HoldJudgmentYReverse=IsGame("pump") and -99999 or 90 BrightGhostComboThreshold=100 @@ -3413,7 +3413,25 @@ MusicFadeOutSeconds=0.5 OutTransitionLength=5 CourseTransitionLength=0.5 BeginFailedDelay=1.0 -# +# New way to control where the notefields are on gameplay. +# The MarginFunction will be passed GAMESTATE:EnabledPlayers() and the +# current styletype. The function must return three values: +# Left margin width, center margin width, right margin width. +# The engine will then position the notefields and adjust their size to fit +# in the space not occupied by the margins. If there is only one player and +# that player would normally be centered (OnePlayerTwoSides or +# TwoPlayersSharedSides, or the Center1Player preference), then the center +# margin value will be ignored. +# Mods applied to the player may still move the notefield into the margin, +# this is just for controlling its initial position and size. +# The purpose of this is to allow the engine more flexibility in styles, +# for example, one player playing dance-solo while the other plays +# dance-single. +MarginFunction=GameplayMargins +# These X values for each player and styletype are deprecated in favor of +# writing a MarginFunction that returns the margin sizes you prefer. +# The MarginFunction supplied by _fallback will use these metrics for +# backwards compatibility. PlayerP1OnePlayerOneSideX=math.floor(scale((0.85/3),0,1,SCREEN_LEFT,SCREEN_RIGHT)) PlayerP2OnePlayerOneSideX=math.floor(scale((2.15/3),0,1,SCREEN_LEFT,SCREEN_RIGHT)) PlayerP1TwoPlayersTwoSidesX=math.floor(scale((0.85/3),0,1,SCREEN_LEFT,SCREEN_RIGHT)) diff --git a/src/ArrowEffects.cpp b/src/ArrowEffects.cpp index 76f2a17d94..ae0ee06754 100644 --- a/src/ArrowEffects.cpp +++ b/src/ArrowEffects.cpp @@ -82,16 +82,16 @@ namespace void ArrowEffects::Update() { - const Style* pStyle = GAMESTATE->GetCurrentStyle(); - static float fLastTime = 0; float fTime = RageTimer::GetTimeSinceStartFast(); FOREACH_EnabledPlayer( pn ) { + const Style* pStyle = GAMESTATE->GetCurrentStyle(pn); const Style::ColumnInfo* pCols = pStyle->m_ColumnInfo[pn]; const SongPosition &position = GAMESTATE->m_bIsUsingStepTiming ? GAMESTATE->m_pPlayerState[pn]->m_Position : GAMESTATE->m_Position; + const float field_zoom= GAMESTATE->m_pPlayerState[pn]->m_NotefieldZoom; PerPlayerData &data = g_EffectData[pn]; @@ -127,8 +127,8 @@ void ArrowEffects::Update() for( int i=iStartCol; i<=iEndCol; i++ ) { - data.m_fMinTornadoX[iColNum] = min( data.m_fMinTornadoX[iColNum], pCols[i].fXOffset ); - data.m_fMaxTornadoX[iColNum] = max( data.m_fMaxTornadoX[iColNum], pCols[i].fXOffset ); + data.m_fMinTornadoX[iColNum] = min( data.m_fMinTornadoX[iColNum], pCols[i].fXOffset * field_zoom ); + data.m_fMaxTornadoX[iColNum] = max( data.m_fMaxTornadoX[iColNum], pCols[i].fXOffset * field_zoom); } } @@ -439,7 +439,7 @@ float ArrowEffects::GetXPos( const PlayerState* pPlayerState, int iColNum, float { float fPixelOffsetFromCenter = 0; // fill this in below - const Style* pStyle = GAMESTATE->GetCurrentStyle(); + const Style* pStyle = GAMESTATE->GetCurrentStyle(pPlayerState->m_PlayerNumber); const float* fEffects = pPlayerState->m_PlayerOptions.GetCurrent().m_fEffects; // TODO: Don't index by PlayerNumber. @@ -448,7 +448,7 @@ float ArrowEffects::GetXPos( const PlayerState* pPlayerState, int iColNum, float if( fEffects[PlayerOptions::EFFECT_TORNADO] != 0 ) { - const float fRealPixelOffset = pCols[iColNum].fXOffset; + const float fRealPixelOffset = pCols[iColNum].fXOffset * pPlayerState->m_NotefieldZoom; const float fPositionBetween = SCALE( fRealPixelOffset, data.m_fMinTornadoX[iColNum], data.m_fMaxTornadoX[iColNum], TORNADO_POSITION_SCALE_TO_LOW, TORNADO_POSITION_SCALE_TO_HIGH ); float fRads = acosf( fPositionBetween ); @@ -469,8 +469,8 @@ float ArrowEffects::GetXPos( const PlayerState* pPlayerState, int iColNum, float const int iFirstCol = 0; const int iLastCol = pStyle->m_iColsPerPlayer-1; const int iNewCol = SCALE( iColNum, iFirstCol, iLastCol, iLastCol, iFirstCol ); - const float fOldPixelOffset = pCols[iColNum].fXOffset; - const float fNewPixelOffset = pCols[iNewCol].fXOffset; + const float fOldPixelOffset = pCols[iColNum].fXOffset * pPlayerState->m_NotefieldZoom; + const float fNewPixelOffset = pCols[iNewCol].fXOffset * pPlayerState->m_NotefieldZoom; const float fDistance = fNewPixelOffset - fOldPixelOffset; fPixelOffsetFromCenter += fDistance * fEffects[PlayerOptions::EFFECT_FLIP]; } @@ -515,7 +515,7 @@ float ArrowEffects::GetXPos( const PlayerState* pPlayerState, int iColNum, float } } - fPixelOffsetFromCenter += pCols[iColNum].fXOffset; + fPixelOffsetFromCenter += pCols[iColNum].fXOffset * pPlayerState->m_NotefieldZoom; if( fEffects[PlayerOptions::EFFECT_TINY] != 0 ) { @@ -764,10 +764,11 @@ bool ArrowEffects::NeedZBuffer( const PlayerState* pPlayerState ) float ArrowEffects::GetZoom( const PlayerState* pPlayerState ) { float fZoom = 1.0f; - // FIXME: Move the zoom values into Style - if( GAMESTATE->GetCurrentStyle()->m_bNeedsZoomOutWith2Players && - (GAMESTATE->GetNumSidesJoined()==2 || GAMESTATE->AnyPlayersAreCpu()) ) - fZoom *= 0.6f; + // Design change: Instead of having a flag in the style that toggles a + // fixed zoom (0.6) that is only applied to the columns, ScreenGameplay now + // calculates a zoom factor to apply to the notefield and puts it in the + // PlayerState. -Kyz + fZoom*= pPlayerState->m_NotefieldZoom; float fTinyPercent = pPlayerState->m_PlayerOptions.GetCurrent().m_fEffects[PlayerOptions::EFFECT_TINY]; if( fTinyPercent != 0 ) diff --git a/src/BPMDisplay.cpp b/src/BPMDisplay.cpp index 3e138d9155..1f10ccbadc 100644 --- a/src/BPMDisplay.cpp +++ b/src/BPMDisplay.cpp @@ -213,9 +213,9 @@ void BPMDisplay::SetBpmFromSteps( const Steps* pSteps ) void BPMDisplay::SetBpmFromCourse( const Course* pCourse ) { ASSERT( pCourse != NULL ); - ASSERT( GAMESTATE->GetCurrentStyle() != NULL ); + ASSERT( GAMESTATE->GetCurrentStyle(PLAYER_INVALID) != NULL ); - StepsType st = GAMESTATE->GetCurrentStyle()->m_StepsType; + StepsType st = GAMESTATE->GetCurrentStyle(PLAYER_INVALID)->m_StepsType; Trail *pTrail = pCourse->GetTrail( st ); // GetTranslitFullTitle because "Crashinfo.txt is garbled because of the ANSI output as usual." -f ASSERT_M( pTrail != NULL, ssprintf("Course '%s' has no trail for StepsType '%s'", pCourse->GetTranslitFullTitle().c_str(), StringConversion::ToString(st).c_str() ) ); @@ -259,7 +259,7 @@ void BPMDisplay::SetFromGameState() } if( GAMESTATE->m_pCurCourse.Get() ) { - if( GAMESTATE->GetCurrentStyle() == NULL ) + if( GAMESTATE->GetCurrentStyle(PLAYER_INVALID) == NULL ) ; // This is true when backing out from ScreenSelectCourse to ScreenTitleMenu. So, don't call SetBpmFromCourse where an assert will fire. else SetBpmFromCourse( GAMESTATE->m_pCurCourse ); diff --git a/src/Background.cpp b/src/Background.cpp index d607a20122..e70e86e6e9 100644 --- a/src/Background.cpp +++ b/src/Background.cpp @@ -205,7 +205,7 @@ void BackgroundImpl::Init() { bOneOrMoreChars = true; // Disable dancing characters if Beginner Helper will be showing. - if( PREFSMAN->m_bShowBeginnerHelper && BeginnerHelper::CanUse() && + if( PREFSMAN->m_bShowBeginnerHelper && BeginnerHelper::CanUse(p) && GAMESTATE->m_pCurSteps[p] && GAMESTATE->m_pCurSteps[p]->GetDifficulty() == Difficulty_Beginner ) bShowingBeginnerHelper = true; } diff --git a/src/BeginnerHelper.cpp b/src/BeginnerHelper.cpp index 5c6f2968ee..f43bf118c1 100644 --- a/src/BeginnerHelper.cpp +++ b/src/BeginnerHelper.cpp @@ -78,7 +78,7 @@ BeginnerHelper::~BeginnerHelper() bool BeginnerHelper::Init( int iDancePadType ) { ASSERT( !m_bInitialized ); - if( !CanUse() ) + if( !CanUse(PLAYER_INVALID) ) return false; // If no players were successfully added, bail. @@ -200,7 +200,7 @@ void BeginnerHelper::AddPlayer( PlayerNumber pn, const NoteData &ns ) ASSERT( pn >= 0 && pn < NUM_PLAYERS ); ASSERT( GAMESTATE->IsHumanPlayer(pn) ); - if( !CanUse() ) + if( !CanUse(pn) ) return; const Character *Character = GAMESTATE->m_pCurCharacters[pn]; @@ -212,13 +212,20 @@ void BeginnerHelper::AddPlayer( PlayerNumber pn, const NoteData &ns ) m_bPlayerEnabled[pn] = true; } -bool BeginnerHelper::CanUse() +bool BeginnerHelper::CanUse(PlayerNumber pn) { for (int i=0; iGetCurrentStyle()->m_bCanUseBeginnerHelper; + // This does not pass PLAYER_INVALID to GetCurrentStyle because that would + // only check the first non-NULL style. Both styles need to be checked. -Kyz + if(pn == PLAYER_INVALID) + { + return GAMESTATE->GetCurrentStyle(PLAYER_1)->m_bCanUseBeginnerHelper || + GAMESTATE->GetCurrentStyle(PLAYER_2)->m_bCanUseBeginnerHelper; + } + return GAMESTATE->GetCurrentStyle(pn)->m_bCanUseBeginnerHelper; } void BeginnerHelper::DrawPrimitives() diff --git a/src/BeginnerHelper.h b/src/BeginnerHelper.h index a5941e7e85..38bb8b144a 100644 --- a/src/BeginnerHelper.h +++ b/src/BeginnerHelper.h @@ -18,7 +18,7 @@ public: bool Init( int iDancePadType ); bool IsInitialized() { return m_bInitialized; } - static bool CanUse(); + static bool CanUse(PlayerNumber pn); void AddPlayer( PlayerNumber pn, const NoteData &nd ); void ShowStepCircle( PlayerNumber pn, int CSTEP ); bool m_bShowBackground; diff --git a/src/CourseUtil.cpp b/src/CourseUtil.cpp index 44ed9212c4..5c67882ed6 100644 --- a/src/CourseUtil.cpp +++ b/src/CourseUtil.cpp @@ -95,14 +95,14 @@ void CourseUtil::SortCoursePointerArrayByDifficulty( vector &vpCoursesI void CourseUtil::SortCoursePointerArrayByRanking( vector &vpCoursesInOut ) { for( unsigned i=0; iUpdateCourseStats( GAMESTATE->GetCurrentStyle()->m_StepsType ); + vpCoursesInOut[i]->UpdateCourseStats( GAMESTATE->GetCurrentStyle(PLAYER_INVALID)->m_StepsType ); sort( vpCoursesInOut.begin(), vpCoursesInOut.end(), CompareCoursePointersByRanking ); } void CourseUtil::SortCoursePointerArrayByTotalDifficulty( vector &vpCoursesInOut ) { for( unsigned i=0; iUpdateCourseStats( GAMESTATE->GetCurrentStyle()->m_StepsType ); + vpCoursesInOut[i]->UpdateCourseStats( GAMESTATE->GetCurrentStyle(PLAYER_INVALID)->m_StepsType ); sort( vpCoursesInOut.begin(), vpCoursesInOut.end(), CompareCoursePointersByTotalDifficulty ); } @@ -176,7 +176,7 @@ void CourseUtil::SortCoursePointerArrayByAvgDifficulty( vector &vpCours course_sort_val.clear(); for( unsigned i = 0; i < vpCoursesInOut.size(); ++i ) { - int iMeter = vpCoursesInOut[i]->GetMeter( GAMESTATE->GetCurrentStyle()->m_StepsType, Difficulty_Medium ); + int iMeter = vpCoursesInOut[i]->GetMeter( GAMESTATE->GetCurrentStyle(PLAYER_INVALID)->m_StepsType, Difficulty_Medium ); course_sort_val[vpCoursesInOut[i]] = ssprintf( "%06i", iMeter ); } sort( vpCoursesInOut.begin(), vpCoursesInOut.end(), CompareCoursePointersByTitle ); @@ -448,8 +448,8 @@ bool EditCourseUtil::ValidateEditCourseName( const RString &sAnswer, RString &sE void EditCourseUtil::UpdateAndSetTrail() { - ASSERT( GAMESTATE->m_pCurStyle != NULL ); - StepsType st = GAMESTATE->m_pCurStyle->m_StepsType; + ASSERT( GAMESTATE->GetCurrentStyle(PLAYER_INVALID) != NULL ); + StepsType st = GAMESTATE->GetCurrentStyle(PLAYER_INVALID)->m_StepsType; Trail *pTrail = NULL; if( GAMESTATE->m_pCurCourse ) pTrail = GAMESTATE->m_pCurCourse->GetTrailForceRegenCache( st ); diff --git a/src/DifficultyList.cpp b/src/DifficultyList.cpp index a3ce25a8a9..192931c37e 100644 --- a/src/DifficultyList.cpp +++ b/src/DifficultyList.cpp @@ -277,7 +277,7 @@ void StepsDisplayList::SetFromGameState() FOREACH_CONST( Difficulty, difficulties, d ) { m_Rows[i].m_dc = *d; - m_Lines[i].m_Meter.SetFromStepsTypeAndMeterAndDifficultyAndCourseType( GAMESTATE->m_pCurStyle->m_StepsType, 0, *d, CourseType_Invalid ); + m_Lines[i].m_Meter.SetFromStepsTypeAndMeterAndDifficultyAndCourseType( GAMESTATE->GetCurrentStyle(PLAYER_INVALID)->m_StepsType, 0, *d, CourseType_Invalid ); ++i; } } diff --git a/src/Game.cpp b/src/Game.cpp index 07aac354c4..12763ed4ff 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -62,12 +62,14 @@ public: static int GetName( T* p, lua_State *L ) { lua_pushstring( L, p->m_szName ); return 1; } static int CountNotesSeparately( T* p, lua_State *L ) { lua_pushboolean( L, p->m_bCountNotesSeparately ); return 1; } DEFINE_METHOD( GetMapJudgmentTo, GetMapJudgmentTo(Enum::Check(L, 1)) ) + DEFINE_METHOD(GetSeparateStyles, m_PlayersHaveSeparateStyles); LunaGame() { ADD_METHOD( GetName ); ADD_METHOD( CountNotesSeparately ); ADD_METHOD( GetMapJudgmentTo ); + ADD_METHOD( GetSeparateStyles ); } }; diff --git a/src/Game.h b/src/Game.h index e3d1eb3e39..2f06b933a7 100644 --- a/src/Game.h +++ b/src/Game.h @@ -34,6 +34,7 @@ struct Game /** @brief Do we count multiple notes in a row as separate notes, or as one note? */ bool m_bCountNotesSeparately; bool m_bTickHolds; + bool m_PlayersHaveSeparateStyles; InputScheme m_InputScheme; diff --git a/src/GameCommand.cpp b/src/GameCommand.cpp index 60d788df96..83da0bb0a5 100644 --- a/src/GameCommand.cpp +++ b/src/GameCommand.cpp @@ -84,7 +84,7 @@ bool GameCommand::DescribesCurrentMode( PlayerNumber pn ) const { if( m_pm != PlayMode_Invalid && GAMESTATE->m_PlayMode != m_pm ) return false; - if( m_pStyle && GAMESTATE->GetCurrentStyle() != m_pStyle ) + if( m_pStyle && GAMESTATE->GetCurrentStyle(pn) != m_pStyle ) return false; // HACK: don't compare m_dc if m_pSteps is set. This causes problems // in ScreenSelectOptionsMaster::ImportOptions if m_PreferredDifficulty @@ -289,7 +289,7 @@ void GameCommand::LoadOne( const Command& cmd ) if( !m_bInvalid ) { Song *pSong = (m_pSong != NULL)? m_pSong:GAMESTATE->m_pCurSong; - const Style *pStyle = m_pStyle ? m_pStyle : GAMESTATE->GetCurrentStyle(); + const Style *pStyle = m_pStyle ? m_pStyle : GAMESTATE->GetCurrentStyle(GAMESTATE->GetMasterPlayerNumber()); if( pSong == NULL || pStyle == NULL ) { MAKE_INVALID("Must set Song and Style to set Steps."); @@ -327,7 +327,7 @@ void GameCommand::LoadOne( const Command& cmd ) if( !m_bInvalid ) { Course *pCourse = (m_pCourse != NULL)? m_pCourse:GAMESTATE->m_pCurCourse; - const Style *pStyle = m_pStyle ? m_pStyle : GAMESTATE->GetCurrentStyle(); + const Style *pStyle = m_pStyle ? m_pStyle : GAMESTATE->GetCurrentStyle(GAMESTATE->GetMasterPlayerNumber()); if( pCourse == NULL || pStyle == NULL ) { MAKE_INVALID("Must set Course and Style to set Trail."); @@ -598,7 +598,7 @@ bool GameCommand::IsPlayable( RString *why ) const if( m_pm != PlayMode_Invalid || m_pStyle != NULL ) { const PlayMode pm = (m_pm != PlayMode_Invalid) ? m_pm : GAMESTATE->m_PlayMode; - const Style *style = (m_pStyle != NULL)? m_pStyle: GAMESTATE->GetCurrentStyle(); + const Style *style = (m_pStyle != NULL)? m_pStyle: GAMESTATE->GetCurrentStyle(GAMESTATE->GetMasterPlayerNumber()); if( !AreStyleAndPlayModeCompatible( style, pm ) ) { if( why ) @@ -705,7 +705,7 @@ void GameCommand::ApplySelf( const vector &vpns ) const if( m_pStyle != NULL ) { - GAMESTATE->SetCurrentStyle( m_pStyle ); + GAMESTATE->SetCurrentStyle( m_pStyle, GAMESTATE->GetMasterPlayerNumber() ); // 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 diff --git a/src/GameLoop.cpp b/src/GameLoop.cpp index 98976a2d91..7b1366e46a 100644 --- a/src/GameLoop.cpp +++ b/src/GameLoop.cpp @@ -239,6 +239,7 @@ namespace * case going from theme to theme, but if it was, it should be fixed * now. There's probably be a better way to do it, but I'm not sure * what it'd be. -aj */ + THEME->UpdateLuaGlobals(); THEME->ReloadMetrics(); g_NewGame= RString(); g_NewTheme= RString(); diff --git a/src/GameManager.cpp b/src/GameManager.cpp index d2472ec585..5ae0657765 100644 --- a/src/GameManager.cpp +++ b/src/GameManager.cpp @@ -170,7 +170,6 @@ static const Style g_Style_Dance_Single = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0, 1, 2, 3 }, - false, // m_bNeedsZoomOutWith2Players true, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -206,7 +205,6 @@ static const Style g_Style_Dance_Versus = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0, 1, 2, 3 }, - false, // m_bNeedsZoomOutWith2Players true, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -250,7 +248,6 @@ static const Style g_Style_Dance_Double = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0,1,2,3,4,5,6,7 }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -286,7 +283,6 @@ static const Style g_Style_Dance_Couple = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0,1,2,3 }, - false, // m_bNeedsZoomOutWith2Players true, // m_bCanUseBeginnerHelper true, // m_bLockDifficulties }; @@ -326,7 +322,6 @@ static const Style g_Style_Dance_Solo = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0,1,2,3,4,5 }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -370,7 +365,6 @@ static const Style g_Style_Dance_Couple_Edit = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0,1,2,3,4,5,6,7 }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -405,7 +399,6 @@ static const Style g_Style_Dance_ThreePanel = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0,1,2 }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -443,7 +436,6 @@ static const Style g_Style_Dance_Solo_Versus = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0,5,1,4,2,3 // outside in }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; */ @@ -487,10 +479,8 @@ static const Style g_Style_Dance_Routine = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0,1,2,3,4,5,6,7 }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper true, // m_bLockDifficulties - }; static const Style *g_apGame_Dance_Styles[] = @@ -512,6 +502,7 @@ static const Game g_Game_Dance = g_apGame_Dance_Styles, // m_apStyles false, // m_bCountNotesSeparately false, // m_bTickHolds + false, // m_PlayersHaveSeparateStyles { // m_InputScheme "dance", // m_szName NUM_DANCE_BUTTONS, // m_iButtonsPerController @@ -600,7 +591,6 @@ static const Style g_Style_Pump_Single = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 2,1,3,0,4 }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -638,7 +628,6 @@ static const Style g_Style_Pump_Versus = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 2,1,3,0,4 }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -678,7 +667,6 @@ static const Style g_Style_Pump_HalfDouble = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 2,3,1,4,0,5 }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -726,7 +714,6 @@ static const Style g_Style_Pump_Double = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 2,1,3,0,4, 2+5,1+5,3+5,0+5,4+5 }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -764,7 +751,6 @@ static const Style g_Style_Pump_Couple = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 2,1,3,0,4 }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper true, // m_bLockDifficulties }; @@ -812,7 +798,6 @@ static const Style g_Style_Pump_Couple_Edit = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 2,1,3,0,4, 2+5,1+5,3+5,0+5,4+5 }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -860,7 +845,6 @@ static const Style g_Style_Pump_Routine = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 2,1,3,0,4,7,6,8,5,9 }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper true, // m_bLockDifficulties }; @@ -883,6 +867,7 @@ static const Game g_Game_Pump = g_apGame_Pump_Styles, // m_apStyles false, // m_bCountNotesSeparately true, // m_bTickHolds + false, // m_PlayersHaveSeparateStyles { // m_InputScheme "pump", // m_szName NUM_PUMP_BUTTONS, // m_iButtonsPerController @@ -961,7 +946,6 @@ static const Style g_Style_KB7_Single = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0,1,2,3,4,5,6 // doesn't work? }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -1005,7 +989,6 @@ static const Style g_Style_KB7_Small = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0,1,2,3,4,5,6 // doesn't work? }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; */ @@ -1047,7 +1030,6 @@ static const Style g_Style_KB7_Versus = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0,1,2,3,4,5,6 }, - true, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -1066,6 +1048,7 @@ static const Game g_Game_KB7 = g_apGame_KB7_Styles, // m_apStyles true, // m_bCountNotesSeparately false, // m_bTickHolds + false, // m_PlayersHaveSeparateStyles { // m_InputScheme "kb7", // m_szName NUM_KB7_BUTTONS, // m_iButtonsPerController @@ -1134,7 +1117,6 @@ static const Style g_Style_Ez2_Single = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 2,0,4,1,3 // This should be from back to front: Down, UpLeft, UpRight, Upper Left Hand, Upper Right Hand }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -1176,7 +1158,6 @@ static const Style g_Style_Ez2_Real = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 3,0,6,1,5,2,4 // This should be from back to front: Down, UpLeft, UpRight, Lower Left Hand, Lower Right Hand, Upper Left Hand, Upper Right Hand }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -1214,7 +1195,6 @@ static const Style g_Style_Ez2_Single_Versus = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 2,0,4,1,3 // This should be from back to front: Down, UpLeft, UpRight, Upper Left Hand, Upper Right Hand }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -1256,7 +1236,6 @@ static const Style g_Style_Ez2_Real_Versus = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 3,0,6,2,4,1,5 // This should be from back to front: Down, UpLeft, UpRight, Lower Left Hand, Lower Right Hand, Upper Left Hand, Upper Right Hand }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -1304,7 +1283,6 @@ static const Style g_Style_Ez2_Double = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 2,0,4,1,3,7,5,9,6,8 // This should be from back to front: Down, UpLeft, UpRight, Upper Left Hand, Upper Right Hand }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -1338,6 +1316,7 @@ static const Game g_Game_Ez2 = g_apGame_Ez2_Styles, // m_apStyles true, // m_bCountNotesSeparately false, // m_bTickHolds + false, // m_PlayersHaveSeparateStyles { // m_InputScheme "ez2", // m_szName NUM_EZ2_BUTTONS, // m_iButtonsPerController @@ -1404,7 +1383,6 @@ static const Style g_Style_Para_Single = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 2,0,4,1,3 }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -1442,7 +1420,6 @@ static const Style g_Style_Para_Versus = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 2,0,4,1,3 }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -1471,6 +1448,7 @@ static const Game g_Game_Para = g_apGame_Para_Styles, // m_apStyles false, // m_bCountNotesSeparately false, // m_bTickHolds + false, // m_PlayersHaveSeparateStyles { // m_InputScheme "para", // m_szName NUM_PARA_BUTTONS, // m_iButtonsPerController @@ -1538,7 +1516,6 @@ static const Style g_Style_DS3DDX_Single = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0,1,2,3,4,5,6,7 }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -1569,6 +1546,7 @@ static const Game g_Game_DS3DDX = g_apGame_DS3DDX_Styles, // m_apStyles false, // m_bCountNotesSeparately false, // m_bTickHolds + false, // m_PlayersHaveSeparateStyles { // m_InputScheme "ds3ddx", // m_szName NUM_DS3DDX_BUTTONS, // m_iButtonsPerController @@ -1638,7 +1616,6 @@ static const Style g_Style_Beat_Single5 = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0,1,2,3,4,5 }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -1678,7 +1655,6 @@ static const Style g_Style_Beat_Versus5 = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0,1,2,3,4,5 }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -1730,7 +1706,6 @@ static const Style g_Style_Beat_Double5 = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0,1,2,3,4,5,6,7,8,9,10,11 }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -1774,7 +1749,6 @@ static const Style g_Style_Beat_Single7 = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0,1,2,3,4,5,6,7 }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -1818,7 +1792,6 @@ static const Style g_Style_Beat_Versus7 = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0,1,2,3,4,5,6,7 }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -1879,7 +1852,6 @@ static const Style g_Style_Beat_Double7 = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -1915,6 +1887,7 @@ static const Game g_Game_Beat = g_apGame_Beat_Styles, // m_apStyles true, // m_bCountNotesSeparately false, // m_bTickHolds + false, // m_PlayersHaveSeparateStyles { // m_InputScheme "beat", // m_szName NUM_BEAT_BUTTONS, // m_iButtonsPerController @@ -1982,7 +1955,6 @@ static const Style g_Style_Maniax_Single = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0, 1, 2, 3 }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -2018,7 +1990,6 @@ static const Style g_Style_Maniax_Versus = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0, 1, 2, 3 }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -2062,7 +2033,6 @@ static const Style g_Style_Maniax_Double = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0,1,2,3,4,5,6,7 }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -2095,6 +2065,7 @@ static const Game g_Game_Maniax = g_apGame_Maniax_Styles, // m_apStyles false, // m_bCountNotesSeparately false, // m_bTickHolds + false, // m_PlayersHaveSeparateStyles { // m_InputScheme "maniax", // m_szName NUM_MANIAX_BUTTONS, // m_iButtonsPerController @@ -2124,7 +2095,6 @@ static const Game g_Game_Maniax = //ThemeMetric TECHNO_COL_SPACING ("ColumnSpacing","Techno"); static const int TECHNO_COL_SPACING = 56; //ThemeMetric TECHNO_VERSUS_COL_SPACING ("ColumnSpacing","TechnoVersus"); -static const int TECHNO_VERSUS_COL_SPACING = 33; static const Style g_Style_Techno_Single4 = { // STYLE_TECHNO_SINGLE4 true, // m_bUsedForGameplay @@ -2156,7 +2126,6 @@ static const Style g_Style_Techno_Single4 = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0,1,2,3 }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -2196,7 +2165,6 @@ static const Style g_Style_Techno_Single5 = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0,1,2,3,4 }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -2240,7 +2208,6 @@ static const Style g_Style_Techno_Single8 = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0,1,2,3,4,5,6,7 }, - true, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -2276,7 +2243,6 @@ static const Style g_Style_Techno_Versus4 = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0,1,2,3 }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -2316,7 +2282,6 @@ static const Style g_Style_Techno_Versus5 = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0,1,2,3,4 }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -2333,24 +2298,24 @@ static const Style g_Style_Techno_Versus8 = 8, // m_iColsPerPlayer { // m_ColumnInfo[NUM_PLAYERS][MAX_COLS_PER_PLAYER]; { // PLAYER_1 - { TRACK_1, -TECHNO_VERSUS_COL_SPACING*3.5f, NULL }, - { TRACK_2, -TECHNO_VERSUS_COL_SPACING*2.5f, NULL }, - { TRACK_3, -TECHNO_VERSUS_COL_SPACING*1.5f, NULL }, - { TRACK_4, -TECHNO_VERSUS_COL_SPACING*0.5f, NULL }, - { TRACK_5, +TECHNO_VERSUS_COL_SPACING*0.5f, NULL }, - { TRACK_6, +TECHNO_VERSUS_COL_SPACING*1.5f, NULL }, - { TRACK_7, +TECHNO_VERSUS_COL_SPACING*2.5f, NULL }, - { TRACK_8, +TECHNO_VERSUS_COL_SPACING*3.5f, NULL }, + { TRACK_1, -TECHNO_COL_SPACING*3.5f, NULL }, + { TRACK_2, -TECHNO_COL_SPACING*2.5f, NULL }, + { TRACK_3, -TECHNO_COL_SPACING*1.5f, NULL }, + { TRACK_4, -TECHNO_COL_SPACING*0.5f, NULL }, + { TRACK_5, +TECHNO_COL_SPACING*0.5f, NULL }, + { TRACK_6, +TECHNO_COL_SPACING*1.5f, NULL }, + { TRACK_7, +TECHNO_COL_SPACING*2.5f, NULL }, + { TRACK_8, +TECHNO_COL_SPACING*3.5f, NULL }, }, { // PLAYER_2 - { TRACK_1, -TECHNO_VERSUS_COL_SPACING*3.5f, NULL }, - { TRACK_2, -TECHNO_VERSUS_COL_SPACING*2.5f, NULL }, - { TRACK_3, -TECHNO_VERSUS_COL_SPACING*1.5f, NULL }, - { TRACK_4, -TECHNO_VERSUS_COL_SPACING*0.5f, NULL }, - { TRACK_5, +TECHNO_VERSUS_COL_SPACING*0.5f, NULL }, - { TRACK_6, +TECHNO_VERSUS_COL_SPACING*1.5f, NULL }, - { TRACK_7, +TECHNO_VERSUS_COL_SPACING*2.5f, NULL }, - { TRACK_8, +TECHNO_VERSUS_COL_SPACING*3.5f, NULL }, + { TRACK_1, -TECHNO_COL_SPACING*3.5f, NULL }, + { TRACK_2, -TECHNO_COL_SPACING*2.5f, NULL }, + { TRACK_3, -TECHNO_COL_SPACING*1.5f, NULL }, + { TRACK_4, -TECHNO_COL_SPACING*0.5f, NULL }, + { TRACK_5, +TECHNO_COL_SPACING*0.5f, NULL }, + { TRACK_6, +TECHNO_COL_SPACING*1.5f, NULL }, + { TRACK_7, +TECHNO_COL_SPACING*2.5f, NULL }, + { TRACK_8, +TECHNO_COL_SPACING*3.5f, NULL }, }, }, { // m_iInputColumn[NUM_GameController][NUM_GameButton] @@ -2362,7 +2327,6 @@ static const Style g_Style_Techno_Versus8 = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0,1,2,3,4,5,6,7 }, - true, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -2406,7 +2370,6 @@ static const Style g_Style_Techno_Double4 = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0,1,2,3,4,5,6,7 }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -2466,7 +2429,6 @@ static const Style g_Style_Techno_Double5 = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0,1,2,3,4,5,6,7,8,9 }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -2483,40 +2445,40 @@ static const Style g_Style_Techno_Double8 = 16, // m_iColsPerPlayer { // m_ColumnInfo[NUM_PLAYERS][MAX_COLS_PER_PLAYER]; { // PLAYER_1 - { TRACK_1, -TECHNO_VERSUS_COL_SPACING*7.5f, NULL }, - { TRACK_2, -TECHNO_VERSUS_COL_SPACING*6.5f, NULL }, - { TRACK_3, -TECHNO_VERSUS_COL_SPACING*5.5f, NULL }, - { TRACK_4, -TECHNO_VERSUS_COL_SPACING*4.5f, NULL }, - { TRACK_5, -TECHNO_VERSUS_COL_SPACING*3.5f, NULL }, - { TRACK_6, -TECHNO_VERSUS_COL_SPACING*2.5f, NULL }, - { TRACK_7, -TECHNO_VERSUS_COL_SPACING*1.5f, NULL }, - { TRACK_8, -TECHNO_VERSUS_COL_SPACING*0.5f, NULL }, - { TRACK_9, +TECHNO_VERSUS_COL_SPACING*0.5f, NULL }, - { TRACK_10, +TECHNO_VERSUS_COL_SPACING*1.5f, NULL }, - { TRACK_11, +TECHNO_VERSUS_COL_SPACING*2.5f, NULL }, - { TRACK_12, +TECHNO_VERSUS_COL_SPACING*3.5f, NULL }, - { TRACK_13, +TECHNO_VERSUS_COL_SPACING*4.5f, NULL }, - { TRACK_14, +TECHNO_VERSUS_COL_SPACING*5.5f, NULL }, - { TRACK_15, +TECHNO_VERSUS_COL_SPACING*6.5f, NULL }, - { TRACK_16, +TECHNO_VERSUS_COL_SPACING*7.5f, NULL }, + { TRACK_1, -TECHNO_COL_SPACING*7.5f, NULL }, + { TRACK_2, -TECHNO_COL_SPACING*6.5f, NULL }, + { TRACK_3, -TECHNO_COL_SPACING*5.5f, NULL }, + { TRACK_4, -TECHNO_COL_SPACING*4.5f, NULL }, + { TRACK_5, -TECHNO_COL_SPACING*3.5f, NULL }, + { TRACK_6, -TECHNO_COL_SPACING*2.5f, NULL }, + { TRACK_7, -TECHNO_COL_SPACING*1.5f, NULL }, + { TRACK_8, -TECHNO_COL_SPACING*0.5f, NULL }, + { TRACK_9, +TECHNO_COL_SPACING*0.5f, NULL }, + { TRACK_10, +TECHNO_COL_SPACING*1.5f, NULL }, + { TRACK_11, +TECHNO_COL_SPACING*2.5f, NULL }, + { TRACK_12, +TECHNO_COL_SPACING*3.5f, NULL }, + { TRACK_13, +TECHNO_COL_SPACING*4.5f, NULL }, + { TRACK_14, +TECHNO_COL_SPACING*5.5f, NULL }, + { TRACK_15, +TECHNO_COL_SPACING*6.5f, NULL }, + { TRACK_16, +TECHNO_COL_SPACING*7.5f, NULL }, }, { // PLAYER_2 - { TRACK_1, -TECHNO_VERSUS_COL_SPACING*7.5f, NULL }, - { TRACK_2, -TECHNO_VERSUS_COL_SPACING*6.5f, NULL }, - { TRACK_3, -TECHNO_VERSUS_COL_SPACING*5.5f, NULL }, - { TRACK_4, -TECHNO_VERSUS_COL_SPACING*4.5f, NULL }, - { TRACK_5, -TECHNO_VERSUS_COL_SPACING*3.5f, NULL }, - { TRACK_6, -TECHNO_VERSUS_COL_SPACING*2.5f, NULL }, - { TRACK_7, -TECHNO_VERSUS_COL_SPACING*1.5f, NULL }, - { TRACK_8, -TECHNO_VERSUS_COL_SPACING*0.5f, NULL }, - { TRACK_9, +TECHNO_VERSUS_COL_SPACING*0.5f, NULL }, - { TRACK_10, +TECHNO_VERSUS_COL_SPACING*1.5f, NULL }, - { TRACK_11, +TECHNO_VERSUS_COL_SPACING*2.5f, NULL }, - { TRACK_12, +TECHNO_VERSUS_COL_SPACING*3.5f, NULL }, - { TRACK_13, +TECHNO_VERSUS_COL_SPACING*4.5f, NULL }, - { TRACK_14, +TECHNO_VERSUS_COL_SPACING*5.5f, NULL }, - { TRACK_15, +TECHNO_VERSUS_COL_SPACING*6.5f, NULL }, - { TRACK_16, +TECHNO_VERSUS_COL_SPACING*7.5f, NULL }, + { TRACK_1, -TECHNO_COL_SPACING*7.5f, NULL }, + { TRACK_2, -TECHNO_COL_SPACING*6.5f, NULL }, + { TRACK_3, -TECHNO_COL_SPACING*5.5f, NULL }, + { TRACK_4, -TECHNO_COL_SPACING*4.5f, NULL }, + { TRACK_5, -TECHNO_COL_SPACING*3.5f, NULL }, + { TRACK_6, -TECHNO_COL_SPACING*2.5f, NULL }, + { TRACK_7, -TECHNO_COL_SPACING*1.5f, NULL }, + { TRACK_8, -TECHNO_COL_SPACING*0.5f, NULL }, + { TRACK_9, +TECHNO_COL_SPACING*0.5f, NULL }, + { TRACK_10, +TECHNO_COL_SPACING*1.5f, NULL }, + { TRACK_11, +TECHNO_COL_SPACING*2.5f, NULL }, + { TRACK_12, +TECHNO_COL_SPACING*3.5f, NULL }, + { TRACK_13, +TECHNO_COL_SPACING*4.5f, NULL }, + { TRACK_14, +TECHNO_COL_SPACING*5.5f, NULL }, + { TRACK_15, +TECHNO_COL_SPACING*6.5f, NULL }, + { TRACK_16, +TECHNO_COL_SPACING*7.5f, NULL }, }, }, { // m_iInputColumn[NUM_GameController][NUM_GameButton] @@ -2526,7 +2488,6 @@ static const Style g_Style_Techno_Double8 = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -2575,6 +2536,7 @@ static const Game g_Game_Techno = g_apGame_Techno_Styles, // m_apStyles false, // m_bCountNotesSeparately false, // m_bTickHolds + false, // m_PlayersHaveSeparateStyles { // m_InputScheme "techno", // m_szName NUM_TECHNO_BUTTONS, // m_iButtonsPerController @@ -2647,7 +2609,6 @@ static const Style g_Style_Popn_Five = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0,1,2,3,4 }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -2693,7 +2654,6 @@ static const Style g_Style_Popn_Nine = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0,1,2,3,4,5,6,7,8 }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -2726,6 +2686,7 @@ static const Game g_Game_Popn = g_apGame_Popn_Styles, // m_apStyles true, // m_bCountNotesSeparately false, // m_bTickHolds + false, // m_PlayersHaveSeparateStyles { // m_InputScheme "popn", // m_szName NUM_POPN_BUTTONS, // m_iButtonsPerController @@ -2815,7 +2776,6 @@ static const Style g_Style_Lights_Cabinet = { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0,1,2,3,4,5,6,7 }, - false, // m_bNeedsZoomOutWith2Players false, // m_bCanUseBeginnerHelper false, // m_bLockDifficulties }; @@ -2832,6 +2792,7 @@ static const Game g_Game_Lights = g_apGame_Lights_Styles, // m_apStyles false, // m_bCountNotesSeparately false, // m_bTickHolds + false, // m_PlayersHaveSeparateStyles { // m_InputScheme "lights", // m_szName NUM_LIGHTS_BUTTONS, // m_iButtonsPerController @@ -2897,14 +2858,14 @@ static const int KICKBOX_COL_SPACING= 64; static const Style g_Style_Kickbox_Human= { - true, // Used for gameplay - true, // Used for edit - true, // Used for demonstration - true, // Used for how to play - "human", // name - StepsType_kickbox_human, // stepstype - StyleType_OnePlayerOneSide, // styletype - 4, // cols per player + true, // m_bUsedForGameplay + true, // m_bUsedForEdit + true, // m_bUsedForDemonstration + true, // m_bUsedForHowToPlay + "human", // m_szName + StepsType_kickbox_human, // m_StepsType + StyleType_OnePlayerOneSide, // m_StyleType + 4, // m_iColsPerPlayer { // m_ColumnInfo[NUM_PLAYERS][MAX_COLS_PER_PLAYER]; { // PLAYER_1 { TRACK_1, -KICKBOX_COL_SPACING*1.5f, NULL }, @@ -2926,21 +2887,20 @@ static const Style g_Style_Kickbox_Human= { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0, 1, 2, 3 }, - false, // needs zoom out with 2 players - false, // can use beginner helper - false, // lock difficulties + false, // m_bCanUseBeginnerHelper + false, // m_bLockDifficulties }; static const Style g_Style_Kickbox_Human_Versus= { - true, // Used for gameplay - false, // Used for edit - true, // Used for demonstration - false, // Used for how to play - "hversus", // name - StepsType_kickbox_human, // stepstype - StyleType_TwoPlayersTwoSides, // styletype - 4, // cols per player + true, // m_bUsedForGameplay + false, // m_bUsedForEdit + true, // m_bUsedForDemonstration + false, // m_bUsedForHowToPlay + "hversus", // m_szName + StepsType_kickbox_human, // m_StepsType + StyleType_TwoPlayersTwoSides, // m_StyleType + 4, // m_iColsPerPlayer { // m_ColumnInfo[NUM_PLAYERS][MAX_COLS_PER_PLAYER]; { // PLAYER_1 { TRACK_1, -KICKBOX_COL_SPACING*1.5f, NULL }, @@ -2962,21 +2922,20 @@ static const Style g_Style_Kickbox_Human_Versus= { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0, 1, 2, 3 }, - false, // needs zoom out with 2 players - false, // can use beginner helper - false, // lock difficulties + false, // m_bCanUseBeginnerHelper + false, // m_bLockDifficulties }; static const Style g_Style_Kickbox_Quadarm= { - true, // Used for gameplay - true, // Used for edit - true, // Used for demonstration - true, // Used for how to play - "quadarm", // name - StepsType_kickbox_quadarm, // stepstype - StyleType_OnePlayerOneSide, // styletype - 4, // cols per player + true, // m_bUsedForGameplay + true, // m_bUsedForEdit + true, // m_bUsedForDemonstration + true, // m_bUsedForHowToPlay + "quadarm", // m_szName + StepsType_kickbox_quadarm, // m_StepsType + StyleType_OnePlayerOneSide, // m_StyleType + 4, // m_iColsPerPlayer { // m_ColumnInfo[NUM_PLAYERS][MAX_COLS_PER_PLAYER]; { // PLAYER_1 { TRACK_1, -KICKBOX_COL_SPACING*1.5f, NULL }, @@ -2998,21 +2957,20 @@ static const Style g_Style_Kickbox_Quadarm= { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0, 1, 2, 3 }, - false, // needs zoom out with 2 players - false, // can use beginner helper - false, // lock difficulties + false, // m_bCanUseBeginnerHelper + false, // m_bLockDifficulties }; static const Style g_Style_Kickbox_Quadarm_Versus= { - true, // Used for gameplay - false, // Used for edit - true, // Used for demonstration - false, // Used for how to play - "qversus", // name - StepsType_kickbox_quadarm, // stepstype - StyleType_TwoPlayersTwoSides, // styletype - 4, // cols per player + true, // m_bUsedForGameplay + false, // m_bUsedForEdit + true, // m_bUsedForDemonstration + false, // m_bUsedForHowToPlay + "qversus", // m_szName + StepsType_kickbox_quadarm, // m_StepsType + StyleType_TwoPlayersTwoSides, // m_StyleType + 4, // m_iColsPerPlayer { // m_ColumnInfo[NUM_PLAYERS][MAX_COLS_PER_PLAYER]; { // PLAYER_1 { TRACK_1, -KICKBOX_COL_SPACING*1.5f, NULL }, @@ -3034,21 +2992,20 @@ static const Style g_Style_Kickbox_Quadarm_Versus= { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0, 1, 2, 3 }, - false, // needs zoom out with 2 players - false, // can use beginner helper - false, // lock difficulties + false, // m_bCanUseBeginnerHelper + false, // m_bLockDifficulties }; static const Style g_Style_Kickbox_Insect= { - true, // Used for gameplay - true, // Used for edit - true, // Used for demonstration - true, // Used for how to play - "insect", // name - StepsType_kickbox_insect, // stepstype - StyleType_OnePlayerOneSide, // styletype - 6, // cols per player + true, // m_bUsedForGameplay + true, // m_bUsedForEdit + true, // m_bUsedForDemonstration + true, // m_bUsedForHowToPlay + "insect", // m_szName + StepsType_kickbox_insect, // m_StepsType + StyleType_OnePlayerOneSide, // m_StyleType + 6, // m_iColsPerPlayer { // m_ColumnInfo[NUM_PLAYERS][MAX_COLS_PER_PLAYER]; { // PLAYER_1 { TRACK_1, -KICKBOX_COL_SPACING*2.5f, NULL }, @@ -3074,21 +3031,20 @@ static const Style g_Style_Kickbox_Insect= { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0, 1, 2, 3, 4, 5 }, - false, // needs zoom out with 2 players - false, // can use beginner helper - false, // lock difficulties + false, // m_bCanUseBeginnerHelper + false, // m_bLockDifficulties }; static const Style g_Style_Kickbox_Insect_Versus= { - true, // Used for gameplay - false, // Used for edit - true, // Used for demonstration - false, // Used for how to play - "iversus", // name - StepsType_kickbox_insect, // stepstype - StyleType_TwoPlayersTwoSides, // styletype - 6, // cols per player + true, // m_bUsedForGameplay + false, // m_bUsedForEdit + true, // m_bUsedForDemonstration + false, // m_bUsedForHowToPlay + "iversus", // m_szName + StepsType_kickbox_insect, // m_StepsType + StyleType_TwoPlayersTwoSides, // m_StyleType + 6, // m_iColsPerPlayer { // m_ColumnInfo[NUM_PLAYERS][MAX_COLS_PER_PLAYER]; { // PLAYER_1 { TRACK_1, -KICKBOX_COL_SPACING*2.5f, NULL }, @@ -3114,21 +3070,20 @@ static const Style g_Style_Kickbox_Insect_Versus= { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0, 1, 2, 3, 4, 5 }, - false, // needs zoom out with 2 players - false, // can use beginner helper - false, // lock difficulties + false, // m_bCanUseBeginnerHelper + false, // m_bLockDifficulties }; static const Style g_Style_Kickbox_Arachnid= { - true, // Used for gameplay - true, // Used for edit - true, // Used for demonstration - true, // Used for how to play - "arachnid", // name - StepsType_kickbox_arachnid, // stepstype - StyleType_OnePlayerOneSide, // styletype - 8, // cols per player + true, // m_bUsedForGameplay + true, // m_bUsedForEdit + true, // m_bUsedForDemonstration + true, // m_bUsedForHowToPlay + "arachnid", // m_szName + StepsType_kickbox_arachnid, // m_StepsType + StyleType_OnePlayerOneSide, // m_StyleType + 8, // m_iColsPerPlayer { // m_ColumnInfo[NUM_PLAYERS][MAX_COLS_PER_PLAYER]; { // PLAYER_1 { TRACK_1, -KICKBOX_COL_SPACING*3.5f, NULL }, @@ -3158,21 +3113,20 @@ static const Style g_Style_Kickbox_Arachnid= { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0, 1, 2, 3, 4, 5, 6, 7 }, - false, // needs zoom out with 2 players - false, // can use beginner helper - false, // lock difficulties + false, // m_bCanUseBeginnerHelper + false, // m_bLockDifficulties }; static const Style g_Style_Kickbox_Arachnid_Versus= { - true, // Used for gameplay - false, // Used for edit - true, // Used for demonstration - false, // Used for how to play - "aversus", // name - StepsType_kickbox_arachnid, // stepstype - StyleType_TwoPlayersTwoSides, // styletype - 8, // cols per player + true, // m_bUsedForGameplay + false, // m_bUsedForEdit + true, // m_bUsedForDemonstration + false, // m_bUsedForHowToPlay + "aversus", // m_szName + StepsType_kickbox_arachnid, // m_StepsType + StyleType_TwoPlayersTwoSides, // m_StyleType + 8, // m_iColsPerPlayer { // m_ColumnInfo[NUM_PLAYERS][MAX_COLS_PER_PLAYER]; { // PLAYER_1 { TRACK_1, -KICKBOX_COL_SPACING*3.5f, NULL }, @@ -3202,9 +3156,8 @@ static const Style g_Style_Kickbox_Arachnid_Versus= { // m_iColumnDrawOrder[MAX_COLS_PER_PLAYER]; 0, 1, 2, 3, 4, 5, 6, 7 }, - true, // needs zoom out with 2 players - false, // can use beginner helper - false, // lock difficulties + false, // m_bCanUseBeginnerHelper + false, // m_bLockDifficulties }; static const Style* g_apGame_Kickbox_Styles[] = @@ -3222,14 +3175,15 @@ static const Style* g_apGame_Kickbox_Styles[] = static const Game g_Game_Kickbox = { - "kickbox", // name - g_apGame_Kickbox_Styles, // styles - true, // count notes separately - false, // tick holds - { // input scheme - "kickbox", - NUM_KICKBOX_BUTTONS, // buttons per controller - { // button names + "kickbox", // m_szName + g_apGame_Kickbox_Styles, // m_apStyles + true, // m_bCountNotesSeparately + false, // m_bTickHolds + true, // m_PlayersHaveSeparateStyles + { // m_InputScheme + "kickbox", // m_szName + NUM_KICKBOX_BUTTONS, // m_iButtonsPerController + { // m_szButtonNames { "DownLeftFoot", GameButton_Invalid }, { "UpLeftFoot", GameButton_Invalid }, { "UpLeftFist", GAME_BUTTON_LEFT }, diff --git a/src/GameState.cpp b/src/GameState.cpp index 8444616d4a..cac1631f9a 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -20,6 +20,7 @@ #include "LuaReference.h" #include "MessageManager.h" #include "MemoryCardManager.h" +#include "NoteData.h" #include "NoteSkinManager.h" #include "PlayerState.h" #include "PrefsManager.h" @@ -136,7 +137,11 @@ GameState::GameState() : { g_pImpl = new GameStateImpl; - SetCurrentStyle( NULL ); + m_pCurStyle.Set(NULL); + FOREACH_PlayerNumber(rpn) + { + m_SeparatedStyles[rpn]= NULL; + } m_pCurGame.Set( NULL ); m_iCoins.Set( 0 ); @@ -153,12 +158,12 @@ GameState::GameState() : FOREACH_PlayerNumber( p ) { m_pPlayerState[p] = new PlayerState; - m_pPlayerState[p]->m_PlayerNumber = p; + m_pPlayerState[p]->SetPlayerNumber(p); } FOREACH_MultiPlayer( p ) { m_pMultiPlayerState[p] = new PlayerState; - m_pMultiPlayerState[p]->m_PlayerNumber = PLAYER_1; + m_pMultiPlayerState[p]->SetPlayerNumber(PLAYER_1); m_pMultiPlayerState[p]->m_mp = p; } @@ -285,7 +290,7 @@ void GameState::Reset() ASSERT( THEME != NULL ); m_timeGameStarted.SetZero(); - SetCurrentStyle( NULL ); + SetCurrentStyle( NULL, PLAYER_INVALID ); FOREACH_MultiPlayer( p ) m_MultiPlayerStatus[p] = MultiPlayerStatus_NotJoined; FOREACH_PlayerNumber( pn ) @@ -391,23 +396,23 @@ void GameState::JoinPlayer( PlayerNumber pn ) } // Set the current style to something appropriate for the new number of joined players. - if( ALLOW_LATE_JOIN && m_pCurStyle != NULL ) + if( ALLOW_LATE_JOIN && GetCurrentStyle(PLAYER_INVALID) != NULL ) { const Style *pStyle; // Only use one player for StyleType_OnePlayerTwoSides and StepsTypes // that can only be played by one player (e.g. dance-solo, // dance-threepanel, popn-nine). -aj // XXX?: still shows joined player as "Insert Card". May not be an issue? -aj - if( m_pCurStyle->m_StyleType == StyleType_OnePlayerTwoSides || - m_pCurStyle->m_StepsType == StepsType_dance_solo || - m_pCurStyle->m_StepsType == StepsType_dance_threepanel || - m_pCurStyle->m_StepsType == StepsType_popn_nine ) - pStyle = GAMEMAN->GetFirstCompatibleStyle( m_pCurGame, 1, m_pCurStyle->m_StepsType ); + if( GetCurrentStyle(PLAYER_INVALID)->m_StyleType == StyleType_OnePlayerTwoSides || + GetCurrentStyle(PLAYER_INVALID)->m_StepsType == StepsType_dance_solo || + GetCurrentStyle(PLAYER_INVALID)->m_StepsType == StepsType_dance_threepanel || + GetCurrentStyle(PLAYER_INVALID)->m_StepsType == StepsType_popn_nine ) + pStyle = GAMEMAN->GetFirstCompatibleStyle( m_pCurGame, 1, GetCurrentStyle(PLAYER_INVALID)->m_StepsType ); else - pStyle = GAMEMAN->GetFirstCompatibleStyle( m_pCurGame, GetNumSidesJoined(), m_pCurStyle->m_StepsType ); + pStyle = GAMEMAN->GetFirstCompatibleStyle( m_pCurGame, GetNumSidesJoined(), GetCurrentStyle(PLAYER_INVALID)->m_StepsType ); // use SetCurrentStyle in case of StyleType_OnePlayerTwoSides - SetCurrentStyle( pStyle ); + SetCurrentStyle( pStyle, pn ); } Message msg( MessageIDToString(Message_PlayerJoined) ); @@ -657,7 +662,7 @@ int GameState::GetNumStagesForCurrentSongAndStepsOrCourse() const int iNumStagesOfThisSong = 1; if( m_pCurSong ) { - const Style *pStyle = m_pCurStyle; + const Style *pStyle = GetCurrentStyle(PLAYER_INVALID); int numSidesJoined = GetNumSidesJoined(); if( pStyle == NULL ) { @@ -894,6 +899,86 @@ void GameState::SaveCurrentSettingsToProfile( PlayerNumber pn ) pProfile->m_lastCourse.FromCourse( m_pPreferredCourse ); } +bool GameState::CanSafelyEnterGameplay(RString& reason) +{ + if(!IsCourseMode()) + { + Song const* song= m_pCurSong; + if(song == NULL) + { + reason= "Current song is NULL."; + return false; + } + } + else + { + Course const* song= m_pCurCourse; + if(song == NULL) + { + reason= "Current course is NULL."; + return false; + } + } + FOREACH_EnabledPlayer(pn) + { + Style const* style= GetCurrentStyle(pn); + if(style == NULL) + { + reason= ssprintf("Style for player %d is NULL.", pn+1); + return false; + } + if(!IsCourseMode()) + { + Steps const* steps= m_pCurSteps[pn]; + if(steps == NULL) + { + reason= ssprintf("Steps for player %d is NULL.", pn+1); + return false; + } + if(steps->m_StepsType != style->m_StepsType) + { + reason= ssprintf("Player %d StepsType %s for steps does not equal " + "StepsType %s for style.", pn+1, + GAMEMAN->GetStepsTypeInfo(steps->m_StepsType).szName, + GAMEMAN->GetStepsTypeInfo(style->m_StepsType).szName); + return false; + } + if(steps->m_pSong != m_pCurSong) + { + reason= ssprintf("Steps for player %d are not for the current song.", + pn+1); + return false; + } + NoteData ndtemp; + steps->GetNoteData(ndtemp); + if(ndtemp.GetNumTracks() != style->m_iColsPerPlayer) + { + reason= ssprintf("Steps for player %d have %d columns, style has %d " + "columns.", pn+1, ndtemp.GetNumTracks(), style->m_iColsPerPlayer); + return false; + } + } + else + { + Trail const* steps= m_pCurTrail[pn]; + if(steps == NULL) + { + reason= ssprintf("Steps for player %d is NULL.", pn+1); + return false; + } + if(steps->m_StepsType != style->m_StepsType) + { + reason= ssprintf("Player %d StepsType %s for steps does not equal " + "StepsType %s for style.", pn+1, + GAMEMAN->GetStepsTypeInfo(steps->m_StepsType).szName, + GAMEMAN->GetStepsTypeInfo(style->m_StepsType).szName); + return false; + } + } + } + return true; +} + void GameState::Update( float fDelta ) { m_SongOptions.Update( fDelta ); @@ -1197,7 +1282,7 @@ RString GameState::GetPlayerDisplayName( PlayerNumber pn ) const bool GameState::PlayersCanJoin() const { - bool b = GetNumSidesJoined() == 0 || GetCurrentStyle() == NULL; // selecting a style finalizes the players + bool b = GetNumSidesJoined() == 0 || GetCurrentStyle(PLAYER_INVALID) == NULL; // selecting a style finalizes the players if( ALLOW_LATE_JOIN.IsLoaded() && ALLOW_LATE_JOIN ) { Screen *pScreen = SCREENMAN->GetTopScreen(); @@ -1216,39 +1301,66 @@ int GameState::GetNumSidesJoined() const return iNumSidesJoined; } -const Game* GameState::GetCurrentGame() +const Game* GameState::GetCurrentGame() const { ASSERT( m_pCurGame != NULL ); // the game must be set before calling this return m_pCurGame; } -const Style* GameState::GetCurrentStyle() const +const Style* GameState::GetCurrentStyle(PlayerNumber pn) const { - return m_pCurStyle; -} - -void GameState::SetCurrentStyle( const Style *pStyle ) -{ - m_pCurStyle.Set( pStyle ); - if( INPUTMAPPER ) + if(GetCurrentGame() == NULL) { return NULL; } + if(!GetCurrentGame()->m_PlayersHaveSeparateStyles) { - if( GetCurrentStyle() && GetCurrentStyle()->m_StyleType == StyleType_OnePlayerTwoSides ) - INPUTMAPPER->SetJoinControllers( this->GetMasterPlayerNumber() ); - else - INPUTMAPPER->SetJoinControllers( PLAYER_INVALID ); + return m_pCurStyle; + } + else + { + if(pn >= NUM_PLAYERS) + { + return m_SeparatedStyles[PLAYER_1] == NULL ? m_SeparatedStyles[PLAYER_2] + : m_SeparatedStyles[PLAYER_1]; + } + return m_SeparatedStyles[pn]; } } -bool GameState::SetCompatibleStyle(StepsType stype) +void GameState::SetCurrentStyle(const Style *style, PlayerNumber pn) +{ + if(!GetCurrentGame()->m_PlayersHaveSeparateStyles) + { + m_pCurStyle.Set(style); + } + else + { + m_SeparatedStyles[pn]= style; + if(pn == PLAYER_INVALID) + { + FOREACH_PlayerNumber(rpn) + { + m_SeparatedStyles[rpn]= style; + } + } + } + if(INPUTMAPPER) + { + if(GetCurrentStyle(pn) && GetCurrentStyle(pn)->m_StyleType == StyleType_OnePlayerTwoSides) + INPUTMAPPER->SetJoinControllers(this->GetMasterPlayerNumber()); + else + INPUTMAPPER->SetJoinControllers(PLAYER_INVALID); + } +} + +bool GameState::SetCompatibleStyle(StepsType stype, PlayerNumber pn) { bool style_incompatible= false; - if(!m_pCurStyle) + if(!GetCurrentStyle(pn)) { style_incompatible= true; } else { - style_incompatible= stype != m_pCurStyle->m_StepsType; + style_incompatible= stype != GetCurrentStyle(pn)->m_StepsType; } if(CommonMetrics::AUTO_SET_STYLE && style_incompatible) { @@ -1258,9 +1370,9 @@ bool GameState::SetCompatibleStyle(StepsType stype) { return false; } - SetCurrentStyle(compatible_style); + SetCurrentStyle(compatible_style, pn); } - return stype == m_pCurStyle->m_StepsType; + return stype == GetCurrentStyle(pn)->m_StepsType; } bool GameState::IsPlayerEnabled( PlayerNumber pn ) const @@ -1303,7 +1415,7 @@ bool GameState::IsHumanPlayer( PlayerNumber pn ) const if( pn == PLAYER_INVALID ) return false; - if( GetCurrentStyle() == NULL ) // no style chosen + if( GetCurrentStyle(pn) == NULL ) // no style chosen { if( PlayersCanJoin() ) return m_bSideIsJoined[pn]; // only allow input from sides that have already joined @@ -1311,7 +1423,7 @@ bool GameState::IsHumanPlayer( PlayerNumber pn ) const return true; // if we can't join, then we're on a screen like MusicScroll or GameOver } - StyleType type = GetCurrentStyle()->m_StyleType; + StyleType type = GetCurrentStyle(pn)->m_StyleType; switch( type ) { case StyleType_TwoPlayersTwoSides: @@ -1669,7 +1781,7 @@ void GameState::GetRankingFeats( PlayerNumber pn, vector &asFeatsOu { CHECKPOINT; - StepsType st = GetCurrentStyle()->m_StepsType; + StepsType st = GetCurrentStyle(pn)->m_StepsType; // Find unique Song and Steps combinations that were played. // We must keep only the unique combination or else we'll double-count @@ -2012,7 +2124,7 @@ bool GameState::DifficultiesLocked() const return true; if( IsCourseMode() ) return PREFSMAN->m_bLockCourseDifficulties; - if( GetCurrentStyle()->m_bLockDifficulties ) + if( GetCurrentStyle(PLAYER_INVALID)->m_bLockDifficulties ) return true; return false; } @@ -2099,7 +2211,7 @@ bool GameState::ChangePreferredCourseDifficulty( PlayerNumber pn, int dir ) return false; if( find(v.begin(),v.end(),cd) == v.end() ) continue; /* not available */ - if( !pCourse || pCourse->GetTrail( GetCurrentStyle()->m_StepsType, cd ) ) + if( !pCourse || pCourse->GetTrail( GetCurrentStyle(pn)->m_StepsType, cd ) ) break; } @@ -2319,13 +2431,21 @@ public: else { Song *pS = Luna::check( L, 1, true ); p->m_pCurSong.Set( pS ); } COMMON_RETURN_SELF; } - static void SetCompatibleStyleOrError(T* p, lua_State* L, StepsType stype) + static int CanSafelyEnterGameplay(T* p, lua_State* L) { - if(!p->SetCompatibleStyle(stype)) + RString reason; + bool can= p->CanSafelyEnterGameplay(reason); + lua_pushboolean(L, can); + LuaHelpers::Push(L, reason); + return 2; + } + static void SetCompatibleStyleOrError(T* p, lua_State* L, StepsType stype, PlayerNumber pn) + { + if(!p->SetCompatibleStyle(stype, pn)) { luaL_error(L, "No compatible style for steps/trail."); } - if(!p->m_pCurStyle) + if(!p->GetCurrentStyle(pn)) { luaL_error(L, "No style set and AutoSetStyle is false, cannot set steps/trail."); } @@ -2348,7 +2468,7 @@ public: else { Steps *pS = Luna::check(L,2); - SetCompatibleStyleOrError(p, L, pS->m_StepsType); + SetCompatibleStyleOrError(p, L, pS->m_StepsType, pn); p->m_pCurSteps[pn].Set(pS); } COMMON_RETURN_SELF; @@ -2378,7 +2498,7 @@ public: else { Trail *pS = Luna::check(L,2); - SetCompatibleStyleOrError(p, L, pS->m_StepsType); + SetCompatibleStyleOrError(p, L, pS->m_StepsType, pn); p->m_pCurTrail[pn].Set(pS); } COMMON_RETURN_SELF; @@ -2579,7 +2699,8 @@ public: } static int GetCurrentStyle( T* p, lua_State *L ) { - Style *pStyle = const_cast