diff --git a/stepmania/Themes/default/metrics.ini b/stepmania/Themes/default/metrics.ini index f042ad1ebd..6b33a3d44c 100644 --- a/stepmania/Themes/default/metrics.ini +++ b/stepmania/Themes/default/metrics.ini @@ -111,20 +111,27 @@ ExplanationPage1X=170 ExplanationPage1Y=70 ExplanationPage2X=1100 ExplanationPage2Y=70 -BeginnerX=98 -BeginnerY=180 -EasyX=246 -EasyY=220 -MediumX=394 -MediumY=180 -HardX=542 -HardY=220 -NonstopX=760 -NonstopY=200 -OniX=960 -OniY=200 -EndlessX=1160 -EndlessY=200 +ChoicesOnPage1=Beginner,Easy,Medium,Hard +ChoicesOnPage2=Nonstop,Oni,Endless,Battle + +Page1Choice1X=98 +Page1Choice1Y=180 +Page1Choice2X=246 +Page1Choice2Y=220 +Page1Choice3X=394 +Page1Choice3Y=180 +Page1Choice4X=542 +Page1Choice4Y=220 +Page1Choice5X=542 +Page1Choice5Y=220 +Page2Choice1X=738 +Page2Choice1Y=180 +Page2Choice2X=886 +Page2Choice2Y=220 +Page2Choice3X=1034 +Page2Choice3Y=180 +Page2Choice4X=1182 +Page2Choice4Y=220 CursorOffsetP1X=-40 CursorOffsetP1Y=200 CursorOffsetP2X=+40 @@ -136,6 +143,7 @@ HelpText=Use &LEFT; &RIGHT; to select, then press START TimerSeconds=40 NextScreenArcade=ScreenSelectGroup NextScreenOni=ScreenInstructions +NextScreenBattle=ScreenInstructions [ScreenSelectDifficultyEX] DifficultyP1X=216 diff --git a/stepmania/src/Actor.cpp b/stepmania/src/Actor.cpp index 06c430cf93..1bff1410d0 100644 --- a/stepmania/src/Actor.cpp +++ b/stepmania/src/Actor.cpp @@ -118,14 +118,20 @@ void Actor::BeginDraw() // set the world matrix and calculate actor properties float fPercentThroughBounce = m_fSecsIntoEffect / m_fEffectPeriodSeconds; float fPercentOffset = sinf( fPercentThroughBounce*PI ); m_temp.pos += m_vectBounce * fPercentOffset; + m_temp.pos.x = roundf( m_temp.pos.x ); + m_temp.pos.y = roundf( m_temp.pos.y ); + m_temp.pos.z = roundf( m_temp.pos.z ); } break; case bobbing: { - float fPercentThroughBounce = m_fSecsIntoEffect / m_fEffectPeriodSeconds; - float fPercentOffset = sinf( fPercentThroughBounce*PI*2 ); - m_temp.pos += m_vectBounce * fPercentOffset; - } + float fPercentThroughBounce = m_fSecsIntoEffect / m_fEffectPeriodSeconds; + float fPercentOffset = sinf( fPercentThroughBounce*PI*2 ); + m_temp.pos += m_vectBounce * fPercentOffset; + m_temp.pos.x = roundf( m_temp.pos.x ); + m_temp.pos.y = roundf( m_temp.pos.y ); + m_temp.pos.z = roundf( m_temp.pos.z ); + } break; default: ASSERT(0); // invalid Effect @@ -515,12 +521,15 @@ void Actor::Fade( float fSleepSeconds, CString sFadeString, float fFadeSeconds, TweenState original = m_current; TweenState mod = m_current; -#define CONTAINS(needle) (-1!=sFadeString.Find(needle)) + CStringArray asBits; + split( sFadeString, " ", asBits ); + +#define CONTAINS(needle) (find( asBits.begin(), asBits.end(), needle ) != asBits.end()) TweenType tt; if( CONTAINS("linear") ) tt = TWEEN_LINEAR; - else if( CONTAINS("accelerate") ) tt = TWEEN_BIAS_BEGIN; - else if( CONTAINS("bounce") ) tt = TWEEN_BOUNCE_END; + else if( CONTAINS("accelerate") ) tt = bOnToScreenOrOffOfScreen ? TWEEN_BIAS_END : TWEEN_BIAS_BEGIN; + else if( CONTAINS("bounce") ) tt = bOnToScreenOrOffOfScreen ? TWEEN_BOUNCE_END : TWEEN_BOUNCE_BEGIN; else if( CONTAINS("spring") ) tt = TWEEN_SPRING; else tt = TWEEN_LINEAR; @@ -540,8 +549,8 @@ void Actor::Fade( float fSleepSeconds, CString sFadeString, float fFadeSeconds, mod.rotation.x += (CONTAINS("spinx")?-PI*2:0); mod.rotation.y += (CONTAINS("spiny")?-PI*2:0); mod.rotation.z += (CONTAINS("spinz")?-PI*2:0); - mod.scale.x *= (CONTAINS("foldx")?0:1) * (CONTAINS("zoomx")?3:1); - mod.scale.y *= (CONTAINS("foldy")?0:1) * (CONTAINS("zoomy")?3:1); + mod.scale.x *= (CONTAINS("foldx")?0:1) * (CONTAINS("zoomx")||CONTAINS("zoom")?3:1); + mod.scale.y *= (CONTAINS("foldy")?0:1) * (CONTAINS("zoomy")||CONTAINS("zoom")?3:1); for( int i=0; i<4; i++ ) { mod.diffuse[i] = GetDiffuse(); diff --git a/stepmania/src/GameConstantsAndTypes.cpp b/stepmania/src/GameConstantsAndTypes.cpp index 051a21666c..8902536494 100644 --- a/stepmania/src/GameConstantsAndTypes.cpp +++ b/stepmania/src/GameConstantsAndTypes.cpp @@ -49,10 +49,32 @@ Difficulty StringToDifficulty( CString sDC ) else if( sDC == "heavy" ) return DIFFICULTY_HARD; else if( sDC == "smaniac" ) return DIFFICULTY_CHALLENGE; else if( sDC == "challenge" ) return DIFFICULTY_CHALLENGE; - - return DIFFICULTY_INVALID; + else return DIFFICULTY_INVALID; } + +CString PlayModeToString( PlayMode pm ) +{ + switch( pm ) + { + case PLAY_MODE_ARCADE: return "arcade"; + case PLAY_MODE_ONI: return "oni"; + case PLAY_MODE_NONSTOP: return "nonstop"; + case PLAY_MODE_ENDLESS: return "endless"; + case PLAY_MODE_BATTLE: return "battle"; + default: ASSERT(0); return ""; + } +} + +PlayMode StringToPlayMode( CString s ) +{ + for( int i=0; iGetMetricF("ScreenSelectDifficulty",ssprintf("MorePage%dY",page+1)) #define EXPLANATION_X( page ) THEME->GetMetricF("ScreenSelectDifficulty",ssprintf("ExplanationPage%dX",page+1)) #define EXPLANATION_Y( page ) THEME->GetMetricF("ScreenSelectDifficulty",ssprintf("ExplanationPage%dY",page+1)) -#define BEGINNER_X() THEME->GetMetricF("ScreenSelectDifficulty","BeginnerX") -#define BEGINNER_Y() THEME->GetMetricF("ScreenSelectDifficulty","BeginnerY") -#define EASY_X() THEME->GetMetricF("ScreenSelectDifficulty","EasyX") -#define EASY_Y() THEME->GetMetricF("ScreenSelectDifficulty","EasyY") -#define MEDIUM_X() THEME->GetMetricF("ScreenSelectDifficulty","MediumX") -#define MEDIUM_Y() THEME->GetMetricF("ScreenSelectDifficulty","MediumY") -#define HARD_X() THEME->GetMetricF("ScreenSelectDifficulty","HardX") -#define HARD_Y() THEME->GetMetricF("ScreenSelectDifficulty","HardY") -#define NONSTOP_X() THEME->GetMetricF("ScreenSelectDifficulty","NonstopX") -#define NONSTOP_Y() THEME->GetMetricF("ScreenSelectDifficulty","NonstopY") -#define ONI_X() THEME->GetMetricF("ScreenSelectDifficulty","OniX") -#define ONI_Y() THEME->GetMetricF("ScreenSelectDifficulty","OniY") -#define ENDLESS_X() THEME->GetMetricF("ScreenSelectDifficulty","EndlessX") -#define ENDLESS_Y() THEME->GetMetricF("ScreenSelectDifficulty","EndlessY") +#define CHOICES_ON_PAGE( page ) THEME->GetMetric ("ScreenSelectDifficulty",ssprintf("ChoicesOnPage%d",page+1)) +#define CHOICE_X( page, choice ) THEME->GetMetricF("ScreenSelectDifficulty",ssprintf("Page%dChoice%dX",page+1,choice+1)) +#define CHOICE_Y( page, choice ) THEME->GetMetricF("ScreenSelectDifficulty",ssprintf("Page%dChoice%dY",page+1,choice+1)) #define CURSOR_OFFSET_X( p ) THEME->GetMetricF("ScreenSelectDifficulty",ssprintf("CursorOffsetP%dX",p+1)) #define CURSOR_OFFSET_Y( i ) THEME->GetMetricF("ScreenSelectDifficulty",ssprintf("CursorOffsetP%dY",i+1)) #define CURSOR_SHADOW_LENGTH_X THEME->GetMetricF("ScreenSelectDifficulty","CursorShadowLengthX") @@ -49,53 +38,13 @@ const float LOCK_INPUT_TIME = 0.30f; // lock input while waiting for tweening to #define INITIAL_CHOICE THEME->GetMetricI("ScreenSelectDifficulty","InitialChoice") #define HELP_TEXT THEME->GetMetric("ScreenSelectDifficulty","HelpText") #define TIMER_SECONDS THEME->GetMetricI("ScreenSelectDifficulty","TimerSeconds") -#define NEXT_SCREEN_ARCADE THEME->GetMetric("ScreenSelectDifficulty","NextScreenArcade") -#define NEXT_SCREEN_ONI THEME->GetMetric("ScreenSelectDifficulty","NextScreenOni") +#define NEXT_SCREEN_ARCADE THEME->GetMetric ("ScreenSelectDifficulty","NextScreenArcade") +#define NEXT_SCREEN_ONI THEME->GetMetric ("ScreenSelectDifficulty","NextScreenOni") +#define NEXT_SCREEN_BATTLE THEME->GetMetric ("ScreenSelectDifficulty","NextScreenBattle") -float CHOICE_X( int choice ) -{ - switch( choice ) - { - case 0: return BEGINNER_X(); - case 1: return EASY_X(); - case 2: return MEDIUM_X(); - case 3: return HARD_X(); - case 4: return NONSTOP_X(); - case 5: return ONI_X(); - case 6: return ENDLESS_X(); - default: ASSERT(0); return 0; - } -} - -float CHOICE_Y( int choice ) -{ - switch( choice ) - { - case 0: return BEGINNER_Y(); - case 1: return EASY_Y(); - case 2: return MEDIUM_Y(); - case 3: return HARD_Y(); - case 4: return NONSTOP_Y(); - case 5: return ONI_Y(); - case 6: return ENDLESS_Y(); - default: ASSERT(0); return 0; - } -} - -const CString CHOICE_TEXT[ScreenSelectDifficulty::NUM_CHOICES] = -{ - "beginner", - "easy", - "medium", - "hard", - "nonstop", - "oni", - "endless" -}; - -float CURSOR_X( int choice, int p ) { return CHOICE_X(choice) + CURSOR_OFFSET_X(p); } -float CURSOR_Y( int choice, int p ) { return CHOICE_Y(choice) + CURSOR_OFFSET_Y(p); } +float CURSOR_X( int page, int choice, int p ) { return CHOICE_X(page,choice) + CURSOR_OFFSET_X(p); } +float CURSOR_Y( int page, int choice, int p ) { return CHOICE_Y(page,choice) + CURSOR_OFFSET_Y(p); } const ScreenMessage SM_StartTweeningOffScreen = ScreenMessage(SM_User + 3); @@ -117,21 +66,68 @@ ScreenSelectDifficulty::ScreenSelectDifficulty() ); this->AddChild( &m_Menu ); - - for( unsigned c=0; c MAX_CHOICES_PER_PAGE ) + RageException::Throw( "Choices exceed max number of choices per page." ); - m_sprPicture[c].Load( THEME->GetPathTo("Graphics",sPictureFile) ); - m_sprPicture[c].SetXY( CHOICE_X(c), CHOICE_Y(c) ); - m_sprPicture[c].SetVertAlign( align_top ); - m_framePages.AddChild( &m_sprPicture[c] ); + for( unsigned choice=0; choicem_CurGame, + PLAY_MODE_ARCADE, + GAMESTATE->m_CurStyle, + dc, + "", + GAMESTATE->GetNumSidesJoined() }; + strcpy( mc.name, DifficultyToString(dc) ); + m_ModeChoices[page].push_back( mc ); + } + else if( pm!=PLAY_MODE_INVALID ) // valid play mode + { + ModeChoice mc = { + GAMESTATE->m_CurGame, + pm, + GAMESTATE->m_CurStyle, + DIFFICULTY_MEDIUM, + "", + GAMESTATE->GetNumSidesJoined() }; + strcpy( mc.name, PlayModeToString(pm) ); + m_ModeChoices[page].push_back( mc ); + } + else + RageException::Throw( "Invalid Page%dChoice%d value '%s'.", page+1, choice+1, asBits[choice].GetString() ); + } + } - m_sprHeader[c].Load( THEME->GetPathTo("Graphics",sHeaderFile) ); - m_sprHeader[c].SetXY( CHOICE_X(c), CHOICE_Y(c) ); - m_sprHeader[c].SetVertAlign( align_bottom ); - m_framePages.AddChild( &m_sprHeader[c] ); + for( int page=0; pageGetPathTo("Graphics",sPictureFile) ); + m_sprPicture[page][choice].SetXY( fChoiceX, fChoiceY ); + m_sprPicture[page][choice].SetVertAlign( align_top ); + m_framePages.AddChild( &m_sprPicture[page][choice] ); + + m_sprHeader[page][choice].Load( THEME->GetPathTo("Graphics",sHeaderFile) ); + m_sprHeader[page][choice].SetXY( fChoiceX, fChoiceY ); + m_sprHeader[page][choice].SetVertAlign( align_bottom ); + m_framePages.AddChild( &m_sprHeader[page][choice] ); + } } for( p=0; pIsPlayerEnabled((PlayerNumber)p) ) @@ -245,29 +242,9 @@ void ScreenSelectDifficulty::HandleScreenMessage( const ScreenMessage SM ) case SM_GoToNextScreen: for( p=0; pm_PreferredDifficulty[p] = DIFFICULTY_BEGINNER; break; - case CHOICE_EASY: GAMESTATE->m_PreferredDifficulty[p] = DIFFICULTY_EASY; break; - case CHOICE_NONSTOP: // need to set preferred difficulty even for courses - case CHOICE_ONI: - case CHOICE_ENDLESS: - case CHOICE_MEDIUM: GAMESTATE->m_PreferredDifficulty[p] = DIFFICULTY_MEDIUM; break; - case CHOICE_HARD: GAMESTATE->m_PreferredDifficulty[p] = DIFFICULTY_HARD; break; - default: ASSERT(0); - } - } - - switch( m_Choice[GAMESTATE->m_MasterPlayerNumber] ) - { - case CHOICE_BEGINNER: - case CHOICE_EASY: - case CHOICE_MEDIUM: - case CHOICE_HARD: GAMESTATE->m_PlayMode = PLAY_MODE_ARCADE; break; - case CHOICE_NONSTOP: GAMESTATE->m_PlayMode = PLAY_MODE_NONSTOP; break; - case CHOICE_ONI: GAMESTATE->m_PlayMode = PLAY_MODE_ONI; break; - case CHOICE_ENDLESS: GAMESTATE->m_PlayMode = PLAY_MODE_ENDLESS; break; - default: ASSERT(0); // bad selection + const ModeChoice& mc = m_ModeChoices[m_iCurrentPage][m_iChoiceOnPage[p]]; + GAMESTATE->m_PlayMode = mc.pm; + GAMESTATE->m_PreferredDifficulty[p] = mc.dc; } switch( GAMESTATE->m_PlayMode ) @@ -276,6 +253,7 @@ void ScreenSelectDifficulty::HandleScreenMessage( const ScreenMessage SM ) case PLAY_MODE_NONSTOP: case PLAY_MODE_ONI: case PLAY_MODE_ENDLESS: SCREENMAN->SetNewScreen( NEXT_SCREEN_ONI ); break; + case PLAY_MODE_BATTLE: SCREENMAN->SetNewScreen( NEXT_SCREEN_BATTLE ); break; default: ASSERT(0); } break; @@ -291,101 +269,74 @@ void ScreenSelectDifficulty::HandleScreenMessage( const ScreenMessage SM ) void ScreenSelectDifficulty::MenuLeft( PlayerNumber pn ) { - if( m_Choice[pn] == 0 ) // can't go left any more - return; if( m_bChosen[pn] ) return; - - ChangeTo( pn, m_Choice[pn], m_Choice[pn]-1 ); + if( m_iChoiceOnPage[pn] == 0 ) // can't go left any more + { + if( m_iCurrentPage > 0 ) + ChangePage( m_iCurrentPage-1 ); + } + else + ChangeWithinPage( pn, m_iChoiceOnPage[pn]-1, false ); } void ScreenSelectDifficulty::MenuRight( PlayerNumber pn ) { - if( m_Choice[pn] == NUM_CHOICES-1 ) // can't go right any more - return; if( m_bChosen[pn] ) return; - - ChangeTo( pn, m_Choice[pn], m_Choice[pn]+1 ); + if( m_iChoiceOnPage[pn] == (int)m_ModeChoices[m_iCurrentPage].size()-1 ) // can't go left any more + { + if( m_iCurrentPage < NUM_PAGES-1 ) + ChangePage( m_iCurrentPage+1 ); + } + else + ChangeWithinPage( pn, m_iChoiceOnPage[pn]+1, false ); } -bool ScreenSelectDifficulty::IsOnPage2( int iItemIndex ) -{ - ASSERT( iItemIndex >= 0 && iItemIndex < NUM_CHOICES ); - - return iItemIndex >= NUM_CHOICES_ON_PAGE_1; -} - -bool ScreenSelectDifficulty::SelectedSomethingOnPage2() +void ScreenSelectDifficulty::ChangePage( int iNewPage ) { + // If anyone has already chosen, don't allow changing of pages for( int p=0; pIsPlayerEnabled(p) && IsOnPage2(m_Choice[p]) ) - return true; - } - return false; -} - -void ScreenSelectDifficulty::ChangeTo( PlayerNumber pn, int iOldChoice, int iNewChoice ) -{ - bool bChangedPagesFrom1To2 = !IsOnPage2(iOldChoice) && IsOnPage2(iNewChoice); - bool bChangedPagesFrom2To1 = IsOnPage2(iOldChoice) && !IsOnPage2(iNewChoice); - bool bChangedPages = bChangedPagesFrom1To2 || bChangedPagesFrom2To1; - bool bSelectedSomethingOnPage1 = !IsOnPage2(iNewChoice); - bool bSelectedSomethingOnPage2 = IsOnPage2(iNewChoice); - - bool bSomeoneMadeAChoice = false; - int p; - for( p=0; pIsPlayerEnabled(p) && m_bChosen[p] ) - bSomeoneMadeAChoice = true; + return; - if( bSomeoneMadeAChoice && (bChangedPagesFrom1To2 || bChangedPagesFrom2To1) ) - return; // don't allow changing pages after one player has chosen + bool bPageIncreasing = iNewPage > m_iCurrentPage; + m_iCurrentPage = iNewPage; - if( bSelectedSomethingOnPage2 || bChangedPagesFrom2To1 ) - { - // change both players - for( int p=0; pPlayOnceFromDir( ANNOUNCER->GetPathTo("select difficulty comment beginner") ); break; - case 1: SOUNDMAN->PlayOnceFromDir( ANNOUNCER->GetPathTo("select difficulty comment easy") ); break; - case 2: SOUNDMAN->PlayOnceFromDir( ANNOUNCER->GetPathTo("select difficulty comment medium") ); break; - case 3: SOUNDMAN->PlayOnceFromDir( ANNOUNCER->GetPathTo("select difficulty comment hard") ); break; - case 4: SOUNDMAN->PlayOnceFromDir( ANNOUNCER->GetPathTo("select difficulty comment nonstop") ); break; - case 5: SOUNDMAN->PlayOnceFromDir( ANNOUNCER->GetPathTo("select difficulty comment oni") ); break; - case 6: SOUNDMAN->PlayOnceFromDir( ANNOUNCER->GetPathTo("select difficulty comment endless") ); break; - } + const ModeChoice& mc = m_ModeChoices[m_iCurrentPage][m_iChoiceOnPage[pn]]; + SOUNDMAN->PlayOnceFromDir( ANNOUNCER->GetPathTo(ssprintf("select difficulty comment %s",mc.name)) ); /* XXX: This will play the same announcer twice at the same time; that'll probably * result in an echo effect. */ - if( IsOnPage2(iSelection) ) // chose something on page 2 + if( m_iCurrentPage == PAGE_2 ) { // choose this for all the other players too for( int p=0; pStopTweening(); - for( p=0; pIsPlayerEnabled((PlayerNumber)p) ) continue; @@ -497,30 +436,17 @@ void ScreenSelectDifficulty::TweenOffScreen() m_sprJoinMessagehadow[p].SetTweenDiffuse( RageColor(0,0,0,0) ); } - for( unsigned c=0; cIsPlayerEnabled((PlayerNumber)p) ) continue; - int iSelection = m_Choice[p]; + float fCursorX = CURSOR_X(m_iCurrentPage,m_iChoiceOnPage[p],p); + float fCursorY = CURSOR_Y(m_iCurrentPage,m_iChoiceOnPage[p],p); - m_sprCursor[p].SetXY( CURSOR_X(iSelection,(PlayerNumber)p), CURSOR_Y(iSelection,(PlayerNumber)p) ); - /* - m_sprCursor[p].SetDiffuse( RageColor(1,1,1,0) ); - m_sprCursor[p].SetRotation( D3DX_PI ); - m_sprCursor[p].SetZoom( 2 ); - m_sprCursor[p].BeginTweening( 0.3f ); - m_sprCursor[p].SetTweenDiffuse( RageColor(1,1,1,1) ); - m_sprCursor[p].SetTweenRotationZ( 0 ); - m_sprCursor[p].SetTweenZoom( 1 ); - */ - m_sprCursor[p].FadeOn( 0, "SpinZ ZoomX ZoomY Fade", 0.3f ); - m_sprJoinMessagehadow[p].SetXY( CURSOR_X(iSelection,(PlayerNumber)p), CURSOR_Y(iSelection,(PlayerNumber)p) ); + m_sprCursor[p].SetXY( fCursorX, fCursorY ); + m_sprCursor[p].FadeOn( 0, "SpinZ Zoom Fade", 0.3f ); + + m_sprJoinMessagehadow[p].SetXY( fCursorX, fCursorY ); RageColor colorOriginal = m_sprJoinMessagehadow[p].GetDiffuse(); m_sprJoinMessagehadow[p].SetDiffuse( RageColor(0,0,0,0) ); m_sprJoinMessagehadow[p].BeginTweening( 0.3f ); m_sprJoinMessagehadow[p].SetTweenDiffuse( colorOriginal ); } - for( unsigned d=0; d m_ModeChoices[NUM_PAGES]; + + int m_iCurrentPage; + int m_iChoiceOnPage[NUM_PLAYERS]; bool m_bChosen[NUM_PLAYERS]; float m_fLockInputTime;