From 3fb7f63beebf3ea490b559e9fa44fb4743e01ab4 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 3 Mar 2011 01:15:47 -0500 Subject: [PATCH 1/7] New branch: work on ComboSegments. The name of this branch is "combos". --- src/TimingData.h | 138 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 137 insertions(+), 1 deletion(-) diff --git a/src/TimingData.h b/src/TimingData.h index 9c2e0b9fe9..d2203d7698 100644 --- a/src/TimingData.h +++ b/src/TimingData.h @@ -476,6 +476,82 @@ struct TickcountSegment */ bool operator>=( const TickcountSegment &other ) const { return !operator<(other); } }; + +/** + * @brief Identifies when a chart is to have a different combo multiplier value. + * + * Admitedly, this would primarily be used for mission mode style charts. However, + * it can have its place during normal gameplay. + */ +struct ComboSegment +{ + /** + * @brief Creates a simple Combo Segment with default values. + * + * It is best to override the values as soon as possible. + */ + ComboSegment() : m_iStartRow(-1), m_iCombo(1) { } + /** + * @brief Creates a Combo Segment with the specified starting row and combo factor. + * @param s the starting row of this segment. + * @param t the amount the combo increases on a succesful hit. + */ + ComboSegment( int s, int t ){ m_iStartRow = max( 0, s ); m_iCombo = max( 1, t ); } + /** + * @brief The row in which the ComboSegment activates. + */ + int m_iStartRow; + /** + * @brief The amount the combo increases at this point. + */ + int m_iCombo; + + /** + * @brief Compares two ComboSegments to see if they are equal to each other. + * @param other the other ComboSegment to compare to. + * @return the equality of the two segments. + */ + bool operator==( const ComboSegment &other ) const + { + COMPARE( m_iStartRow ); + COMPARE( m_iCombo ); + return true; + } + /** + * @brief Compares two ComboSegments to see if they are not equal to each other. + * @param other the other ComboSegment to compare to. + * @return the inequality of the two segments. + */ + bool operator!=( const ComboSegment &other ) const { return !operator==(other); } + /** + * @brief Compares two ComboSegments to see if one is less than the other. + * @param other the other ComboSegment to compare to. + * @return the truth/falsehood of if the first is less than the second. + */ + bool operator<( const ComboSegment &other ) const { return m_iStartRow < other.m_iStartRow; } + /** + * @brief Compares two ComboSegments to see if one is less than or equal to the other. + * @param other the other ComboSegment to compare to. + * @return the truth/falsehood of if the first is less or equal to than the second. + */ + bool operator<=( const ComboSegment &other ) const + { + return ( operator<(other) || operator==(other) ); + } + /** + * @brief Compares two ComboSegments to see if one is greater than the other. + * @param other the other ComboSegment to compare to. + * @return the truth/falsehood of if the first is greater than the second. + */ + bool operator>( const ComboSegment &other ) const { return !operator<=(other); } + /** + * @brief Compares two ComboSegments to see if one is greater than or equal to the other. + * @param other the other ComboSegment to compare to. + * @return the truth/falsehood of if the first is greater than or equal to the second. + */ + bool operator>=( const ComboSegment &other ) const { return !operator<(other); } +}; + /** * @brief Holds data for translating beats<->seconds. */ @@ -870,6 +946,60 @@ public: */ void AddTickcountSegment( const TickcountSegment &seg ); + /** + * @brief Retrieve the Combo at the given row. + * @param iNoteRow the row in question. + * @return the Combo. + */ + int GetComboAtRow( int iNoteRow ) const; + /** + * @brief Retrieve the Combo at the given beat. + * @param fBeat the beat in question. + * @return the Combo. + */ + int GetComboAtBeat( float fBeat ) const { return GetComboAtRow( BeatToNoteRow(fBeat) ); } + /** + * @brief Set the row to have the new Combo. + * @param iNoteRow the row to have the new Combo. + * @param iTicks the Combo. + */ + void SetComboAtRow( int iNoteRow, int iCombo ); + /** + * @brief Set the beat to have the new Combo. + * @param fBeat the beat to have the new Combo. + * @param iTicks the Combo. + */ + void SetComboAtBeat( float fBeat, int iCombo ) { SetComboAtRow( BeatToNoteRow( fBeat ), iCombo ); } + /** + * @brief Retrieve the ComboSegment at the specified row. + * @param iNoteRow the row that has a ComboSegment. + * @return the ComboSegment in question. + */ + ComboSegment& GetComboSegmentAtRow( int iNoteRow ); + /** + * @brief Retrieve the ComboSegment at the specified beat. + * @param fBeat the beat that has a ComboSegment. + * @return the ComboSegment in question. + */ + ComboSegment& GetComboSegmentAtBeat( float fBeat ) { return GetComboSegmentAtRow( BeatToNoteRow(fBeat) ); } + /** + * @brief Retrieve the index of the ComboSegments at the specified row. + * @param iNoteRow the row that has a ComboSegment. + * @return the ComboSegment's index in question. + */ + int GetComboSegmentIndexAtRow( int iNoteRow ) const; + /** + * @brief Retrieve the index of the ComboSegments at the specified beat. + * @param fBeat the beat that has a ComboSegment. + * @return the ComboSegment's index in question. + */ + int GetComboSegmentIndexAtBeat( float fBeat ) const { return GetComboSegmentIndexAtRow( BeatToNoteRow(fBeat) ); } + /** + * @brief Add the ComboSegment to the TimingData. + * @param seg the new ComboSegment. + */ + void AddComboSegment( const ComboSegment &seg ); + void MultiplyBPMInBeatRange( int iStartIndex, int iEndIndex, float fFactor ); void NoteRowToMeasureAndBeat( int iNoteRow, int &iMeasureIndexOut, int &iBeatIndexOut, int &iRowsRemainder ) const; @@ -934,6 +1064,9 @@ public: COMPARE( m_TickcountSegments.size() ); for( unsigned i=0; i m_TickcountSegments; + /** + * @brief The collection of ComboSegments. + */ + vector m_ComboSegments; /** * @brief The initial offset of a song. */ @@ -997,7 +1134,6 @@ public: /** * @file * @author Chris Danford, Glenn Maynard (c) 2001-2004 - * * @section LICENSE * All rights reserved. * From 2f6b0614e9c5fa95b87fdd4d03e8c6a1563ff719 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 3 Mar 2011 01:30:57 -0500 Subject: [PATCH 2/7] combos branch: implement some header functions. --- src/TimingData.cpp | 90 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/src/TimingData.cpp b/src/TimingData.cpp index 7fb9f60786..7640cc94ad 100644 --- a/src/TimingData.cpp +++ b/src/TimingData.cpp @@ -52,6 +52,11 @@ void TimingData::AddTickcountSegment( const TickcountSegment &seg ) m_TickcountSegments.insert( upper_bound(m_TickcountSegments.begin(), m_TickcountSegments.end(), seg), seg ); } +void TimingData::AddComboSegment( const ComboSegment &seg ) +{ + m_ComboSegments.insert( upper_bound(m_ComboSegments.begin(), m_ComboSegments.end(), seg), seg ); +} + /* Change an existing BPM segment, merge identical segments together or insert a new one. */ void TimingData::SetBPMAtRow( int iNoteRow, float fBPM ) { @@ -176,6 +181,27 @@ void TimingData::SetTickcountAtRow( int iRow, int iTicks ) } } +void TimingData::SetComboAtRow( int iRow, int iCombo ) +{ + unsigned i; + for( i=0; i= iRow ) + break; + + if( i == m_ComboSegments.size() || m_ComboSegments[i].m_iStartRow != iRow ) + { + if( i == 0 || m_ComboSegments[i-1].m_iCombo != iCombo ) + AddComboSegment( ComboSegment(iRow, iCombo ) ); + } + else + { + if( i > 0 && m_ComboSegments[i-1].m_iCombo == iCombo ) + m_ComboSegments.erase( m_ComboSegments.begin()+i, m_ComboSegments.begin()+i+1 ); + else + m_ComboSegments[i].m_iCombo = iCombo; + } +} + float TimingData::GetStopAtRow( int iNoteRow, bool bDelay ) const { for( unsigned i=0; i iRow ) + break; + } + return (int)i; +} + BPMSegment& TimingData::GetBPMSegmentAtRow( int iNoteRow ) { static BPMSegment empty; @@ -319,6 +369,15 @@ BPMSegment& TimingData::GetBPMSegmentAtRow( int iNoteRow ) return m_BPMSegments[i]; } +ComboSegment& TimingData::GetComboSegmentAtRow( int iRow ) +{ + unsigned i; + for( i=0; i iRow ) + break; + return m_ComboSegments[i]; +} + StopSegment& TimingData::GetStopSegmentAtRow( int iNoteRow, bool bDelay ) { static StopSegment empty; @@ -487,16 +546,19 @@ void TimingData::GetBeatAndBPSFromElapsedTimeNoOffset( float fElapsedTime, float vector vWS = m_WarpSegments; vector vTSS = m_vTimeSignatureSegments; vector vTS = m_TickcountSegments; + vector vCS = m_ComboSegments; sort( vBPMS.begin(), vBPMS.end() ); sort( vSS.begin(), vSS.end() ); sort( vWS.begin(), vWS.end() ); sort( vTSS.begin(), vTSS.end() ); sort( vTS.begin(), vTS.end() ); + sort( vCS.begin(), vCS.end() ); ASSERT_M( vBPMS == m_BPMSegments, "The BPM segments were not sorted!" ); ASSERT_M( vSS == m_StopSegments, "The Stop segments were not sorted!" ); ASSERT_M( vWS == m_WarpSegments, "The Warp segments were not sorted!" ); ASSERT_M( vTSS == m_vTimeSignatureSegments, "The Time Signature segments were not sorted!" ); ASSERT_M( vTS == m_TickcountSegments, "The Tickcount segments were not sorted!" ); + ASSERT_M( vCS == m_ComboSegments, "The Combo segments were not sorted!" ); FAIL_M( ssprintf("Failed to find the appropriate segment for elapsed time %f.", fTime) ); } @@ -619,6 +681,14 @@ void TimingData::InsertRows( int iStartRow, int iRowsToAdd ) continue; tick.m_iStartRow += iRowsToAdd; } + + for( unsigned i = 0; i < m_ComboSegments.size(); i++ ) + { + ComboSegment &comb = m_ComboSegments[i]; + if( comb.m_iStartRow < iStartRow ) + continue; + comb.m_iStartRow += iRowsToAdd; + } if( iStartRow == 0 ) { @@ -720,6 +790,26 @@ void TimingData::DeleteRows( int iStartRow, int iRowsToDelete ) // After deleted region: tick.m_iStartRow -= iRowsToDelete; } + + for( unsigned i = 0; i < m_ComboSegments.size(); i++ ) + { + ComboSegment &comb = m_ComboSegments[i]; + + // Before deleted region: + if( comb.m_iStartRow < iStartRow ) + continue; + + // Inside deleted region: + if( comb.m_iStartRow < iStartRow+iRowsToDelete ) + { + m_ComboSegments.erase( m_ComboSegments.begin()+i, m_ComboSegments.begin()+i+1 ); + --i; + continue; + } + + // After deleted region: + comb.m_iStartRow -= iRowsToDelete; + } this->SetBPMAtRow( iStartRow, fNewBPM ); } From 25ce852eed440592f3209137a7ff55ce669e3e6d Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Thu, 3 Mar 2011 01:37:42 -0500 Subject: [PATCH 3/7] Get Loader and Writer set up for these segments. --- Docs/Changelog_SSCformat.txt | 3 +++ src/NotesLoaderSSC.cpp | 3 +-- src/NotesWriterSSC.cpp | 8 ++++---- src/Song.cpp | 11 ++++++++++- src/Song.h | 2 +- 5 files changed, 19 insertions(+), 8 deletions(-) diff --git a/Docs/Changelog_SSCformat.txt b/Docs/Changelog_SSCformat.txt index e79ec62e3d..dcba411279 100644 --- a/Docs/Changelog_SSCformat.txt +++ b/Docs/Changelog_SSCformat.txt @@ -9,6 +9,9 @@ change to JSON, but it is unsure if this will be done. Implement .ssc at your own risk. ________________________________________________________________________________ +[v0.55] - Wolfman2000 +* Add #COMBOS tag to the Song and Steps (does nothing here). + [v0.54] - Wolfman2000 * Add #ATTACKS tag to the Notedata sections. Right now it does nothing. diff --git a/src/NotesLoaderSSC.cpp b/src/NotesLoaderSSC.cpp index acc84c9292..7c84d9809f 100644 --- a/src/NotesLoaderSSC.cpp +++ b/src/NotesLoaderSSC.cpp @@ -565,7 +565,7 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach } else if( sValueName=="COMBOS" ) - {/* + { vector arrayComboExpressions; split( sParams[1], ",", arrayComboExpressions ); @@ -584,7 +584,6 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach ComboSegment new_seg( BeatToNoteRow( fComboBeat ), iCombos ); out.m_Timing.AddComboSegment( new_seg ); } - */ } /* The following are cache tags. Never fill their values diff --git a/src/NotesWriterSSC.cpp b/src/NotesWriterSSC.cpp index 083d0cfd37..1283d1351f 100644 --- a/src/NotesWriterSSC.cpp +++ b/src/NotesWriterSSC.cpp @@ -181,19 +181,19 @@ static void WriteGlobalTags( RageFile &f, const Song &out ) } f.PutLine( ";" ); - /* + ASSERT( !out.m_Timing.m_ComboSegments.empty() ); f.Write( "#COMBOS:" ); for( unsigned i=0; i asBPMValues; diff --git a/src/Song.cpp b/src/Song.cpp index 67b730ee61..cca9057216 100644 --- a/src/Song.cpp +++ b/src/Song.cpp @@ -41,7 +41,7 @@ * @brief The internal version of the cache for StepMania. * * Increment this value to invalidate the current cache. */ -const int FILE_CACHE_VERSION = 165; +const int FILE_CACHE_VERSION = 166; /** @brief How long does a song sample last by default? */ const float DEFAULT_MUSIC_SAMPLE_LENGTH = 12.f; @@ -782,6 +782,15 @@ void Song::TidyUpData() seg.m_iTicks = 2; m_Timing.m_TickcountSegments.push_back( seg ); } + + // Have a default combo segment of one just in case. + if( m_Timing.m_ComboSegments.empty() ) + { + ComboSegment seg; + seg.m_iStartRow = 0; + seg.m_iCombo = 1; + m_Timing.m_ComboSegments.push_back( seg ); + } } void Song::TranslateTitles() diff --git a/src/Song.h b/src/Song.h index 6c8fb81def..15148a06ab 100644 --- a/src/Song.h +++ b/src/Song.h @@ -17,7 +17,7 @@ struct lua_State; struct BackgroundChange; /** @brief The version of the .ssc file format. */ -const static float STEPFILE_VERSION_NUMBER = 0.54f; +const static float STEPFILE_VERSION_NUMBER = 0.55f; /** @brief How many edits for this song can each profile have? */ const int MAX_EDITS_PER_SONG_PER_PROFILE = 5; From 4a19be0d0587bc45432b0ff327eb28b2431271b6 Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Fri, 4 Mar 2011 23:12:16 -0500 Subject: [PATCH 4/7] Combos branch: allow for combo factors on hits. --- src/ScoreKeeperNormal.cpp | 19 ++++++++++++------- src/ScoreKeeperNormal.h | 4 ++-- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/ScoreKeeperNormal.cpp b/src/ScoreKeeperNormal.cpp index f36eb62510..9b616d7811 100644 --- a/src/ScoreKeeperNormal.cpp +++ b/src/ScoreKeeperNormal.cpp @@ -18,6 +18,7 @@ #include "Game.h" #include "Style.h" #include "Song.h" +#include "TimingData.h" #include "NoteDataWithScoring.h" @@ -593,7 +594,7 @@ void ScoreKeeperNormal::HandleTapNoteScoreInternal( TapNoteScore tns, TapNoteSco m_pPlayerStageStats->m_iCurPossibleDancePoints += TapNoteScoreToDancePoints( maximum ); } -void ScoreKeeperNormal::HandleComboInternal( int iNumHitContinueCombo, int iNumHitMaintainCombo, int iNumBreakCombo ) +void ScoreKeeperNormal::HandleComboInternal( int iNumHitContinueCombo, int iNumHitMaintainCombo, int iNumBreakCombo, int iRow ) { // Regular combo if( m_ComboIsPerRow ) @@ -610,7 +611,9 @@ void ScoreKeeperNormal::HandleComboInternal( int iNumHitContinueCombo, int iNumH if( iNumBreakCombo == 0 ) { - m_pPlayerStageStats->m_iCurCombo += iNumHitContinueCombo; + TimingData td = GAMESTATE->m_pCurSong->m_Timing; + int multiplier = ( iRow == -1 ? 1 : td.GetComboSegmentAtRow( iRow ).m_iCombo ); + m_pPlayerStageStats->m_iCurCombo += iNumHitContinueCombo * multiplier; } else { @@ -619,7 +622,7 @@ void ScoreKeeperNormal::HandleComboInternal( int iNumHitContinueCombo, int iNumH } } -void ScoreKeeperNormal::HandleRowComboInternal( TapNoteScore tns, int iNumTapsInRow ) +void ScoreKeeperNormal::HandleRowComboInternal( TapNoteScore tns, int iNumTapsInRow, int iRow ) { if( m_ComboIsPerRow ) { @@ -628,7 +631,9 @@ void ScoreKeeperNormal::HandleRowComboInternal( TapNoteScore tns, int iNumTapsIn if ( tns >= m_MinScoreToContinueCombo ) { m_pPlayerStageStats->m_iCurMissCombo = 0; - m_pPlayerStageStats->m_iCurCombo += iNumTapsInRow; + TimingData td = GAMESTATE->m_pCurSong->m_Timing; + int multiplier = ( iRow == -1 ? 1 : td.GetComboSegmentAtRow( iRow ).m_iCombo ); + m_pPlayerStageStats->m_iCurCombo += iNumTapsInRow * multiplier; } else if ( tns < m_MinScoreToMaintainCombo ) { @@ -673,14 +678,14 @@ void ScoreKeeperNormal::HandleTapRowScore( const NoteData &nd, int iRow ) TapNoteScore scoreOfLastTap = NoteDataWithScoring::LastTapNoteWithResult( nd, iRow ).result.tns; HandleTapNoteScoreInternal( scoreOfLastTap, TNS_W1 ); - + if ( GAMESTATE->GetCurrentGame()->m_bCountNotesSeparately ) { - HandleComboInternal( iNumHitContinueCombo, iNumHitMaintainCombo, iNumBreakCombo ); + HandleComboInternal( iNumHitContinueCombo, iNumHitMaintainCombo, iNumBreakCombo, iRow ); } else { - HandleRowComboInternal( scoreOfLastTap, iNumTapsInRow ); //This should work? + HandleRowComboInternal( scoreOfLastTap, iNumTapsInRow, iRow ); //This should work? } if( m_pPlayerState->m_PlayerNumber != PLAYER_INVALID ) diff --git a/src/ScoreKeeperNormal.h b/src/ScoreKeeperNormal.h index 902ab38f12..e98579656d 100644 --- a/src/ScoreKeeperNormal.h +++ b/src/ScoreKeeperNormal.h @@ -114,8 +114,8 @@ public: private: void HandleTapNoteScoreInternal( TapNoteScore tns, TapNoteScore maximum ); - void HandleComboInternal( int iNumHitContinueCombo, int iNumHitMaintainCombo, int iNumBreakCombo ); - void HandleRowComboInternal( TapNoteScore tns, int iNumTapsInRow ); + void HandleComboInternal( int iNumHitContinueCombo, int iNumHitMaintainCombo, int iNumBreakCombo, int iRow = -1 ); + void HandleRowComboInternal( TapNoteScore tns, int iNumTapsInRow, int iRow = -1 ); void GetRowCounts( const NoteData &nd, int iRow, int &iNumHitContinueCombo, int &iNumHitMaintainCombo, int &iNumBreakCombo ); }; From 994e7d9fa1e5b6d4ab69c689ff4d72fc19c3eeed Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sat, 5 Mar 2011 00:33:18 -0500 Subject: [PATCH 5/7] Combos branch: make checkpoints consistent. A combination of #COMBOS and #TICKCOUNTS will be needed to replicate some of the mission charts. --- src/ScoreKeeperNormal.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ScoreKeeperNormal.cpp b/src/ScoreKeeperNormal.cpp index 9b616d7811..109587ac00 100644 --- a/src/ScoreKeeperNormal.cpp +++ b/src/ScoreKeeperNormal.cpp @@ -578,7 +578,7 @@ void ScoreKeeperNormal::HandleHoldCheckpointScore( const NoteData &nd, int iRow, } HandleTapNoteScoreInternal( iNumHoldsMissedThisRow == 0? TNS_CheckpointHit:TNS_CheckpointMiss, TNS_CheckpointHit ); - HandleComboInternal( iNumHoldsHeldThisRow, 0, iNumHoldsMissedThisRow ); + HandleComboInternal( iNumHoldsHeldThisRow, 0, iNumHoldsMissedThisRow, iRow ); } void ScoreKeeperNormal::HandleTapNoteScoreInternal( TapNoteScore tns, TapNoteScore maximum ) From 6204de38a76ba7b7a1ea258a068a13f1b346ef5b Mon Sep 17 00:00:00 2001 From: Jason Felds Date: Sat, 5 Mar 2011 01:44:58 -0500 Subject: [PATCH 6/7] Combos branch: allow editing combo factor. Need to check something on the default branch before this gets pushed there: something may still be off. --- Themes/_fallback/Languages/en.ini | 2 ++ Themes/_fallback/metrics.ini | 3 +++ src/NoteField.cpp | 33 +++++++++++++++++++++++++++++++ src/NoteField.h | 1 + src/ScreenEdit.cpp | 23 ++++++++++++++++++++- src/ScreenEdit.h | 1 + src/TimingData.cpp | 9 +-------- 7 files changed, 63 insertions(+), 9 deletions(-) diff --git a/Themes/_fallback/Languages/en.ini b/Themes/_fallback/Languages/en.ini index 5f99159de5..fa9cb03999 100644 --- a/Themes/_fallback/Languages/en.ini +++ b/Themes/_fallback/Languages/en.ini @@ -842,6 +842,7 @@ Edit time signature=Edit time signature (not working yet) Edit time signature (top)=Edit time signature (beats per measure) Edit time signature (bottom)=Edit time signature (single beat note value) Edit tickcount=Edit tickcount +Edit combo=Edit combo Editor options=Options EditorShowBGChangesPlay=Show Backgrounds Effect=Effect @@ -1207,6 +1208,7 @@ Enter a new Delay value.=Enter a new Delay value. Enter a new Time Signature numerator value.=Enter the number of beats per measure. Enter a new Time Signature denominator value.=Enter the note value that represents one beat. Enter a new Tickcount value.=Enter a new Tickcount value. +Enter a new Combo value.=Enter a new Combo value. Enter a new artist transliteration.=Enter a new artist transliteration. Enter a new artist.=Enter a new artist. Enter a new genre.=Enter a new genre. diff --git a/Themes/_fallback/metrics.ini b/Themes/_fallback/metrics.ini index 572fe4f868..6b3767cb57 100644 --- a/Themes/_fallback/metrics.ini +++ b/Themes/_fallback/metrics.ini @@ -956,18 +956,21 @@ StopColor=color("0.8,0.8,0,1") DelayColor=color("0,0.8,0.8,1") TimeSignatureColor=color("1,0.55,0,1") TickcountColor=color("0,1,0,1") +ComboColor=color("0.55,1,0,1") # BPMIsLeftSide=true StopIsLeftSide=true DelayIsLeftSide=true TimeSignatureIsLeftSide=true TickcountIsLeftSide=false +ComboIsLeftSide=false # BPMOffsetX=60 StopOffsetX=10 DelayOffsetX=10 TimeSignatureOffsetX=30 TickcountOffsetX=10 +ComboOffsetX=30 [PlayerStageStats] # Original CVS Grading diff --git a/src/NoteField.cpp b/src/NoteField.cpp index d91cc5ca70..ed70b133be 100644 --- a/src/NoteField.cpp +++ b/src/NoteField.cpp @@ -424,16 +424,19 @@ static ThemeMetric STOP_COLOR ( "NoteField", "StopColor" ); static ThemeMetric DELAY_COLOR ( "NoteField", "DelayColor" ); static ThemeMetric TIME_SIGNATURE_COLOR ( "NoteField", "TimeSignatureColor" ); static ThemeMetric TICKCOUNT_COLOR ( "NoteField", "TickcountColor" ); +static ThemeMetric COMBO_COLOR ( "NoteField", "ComboColor" ); static ThemeMetric BPM_IS_LEFT_SIDE ( "NoteField", "BPMIsLeftSide" ); static ThemeMetric STOP_IS_LEFT_SIDE ( "NoteField", "StopIsLeftSide" ); static ThemeMetric DELAY_IS_LEFT_SIDE ( "NoteField", "DelayIsLeftSide" ); static ThemeMetric TIME_SIGNATURE_IS_LEFT_SIDE ( "NoteField", "TimeSignatureIsLeftSide" ); static ThemeMetric TICKCOUNT_IS_LEFT_SIDE ( "NoteField", "TickcountIsLeftSide" ); +static ThemeMetric COMBO_IS_LEFT_SIDE ( "NoteField", "ComboIsLeftSide" ); static ThemeMetric BPM_OFFSETX ( "NoteField", "BPMOffsetX" ); static ThemeMetric STOP_OFFSETX ( "NoteField", "StopOffsetX" ); static ThemeMetric DELAY_OFFSETX ( "NoteField", "DelayOffsetX" ); static ThemeMetric TIME_SIGNATURE_OFFSETX ( "NoteField", "TimeSignatureOffsetX" ); static ThemeMetric TICKCOUNT_OFFSETX ( "NoteField", "TickcountOffsetX" ); +static ThemeMetric COMBO_OFFSETX ( "NoteField", "ComboOffsetX" ); void NoteField::DrawBPMText( const float fBeat, const float fBPM ) { @@ -512,6 +515,23 @@ void NoteField::DrawTickcountText( const float fBeat, int iTicks ) m_textMeasureNumber.Draw(); } +void NoteField::DrawComboText( const float fBeat, int iCombo ) +{ + const float fYOffset = ArrowEffects::GetYOffset( m_pPlayerState, 0, fBeat ); + const float fYPos = ArrowEffects::GetYPos( m_pPlayerState, 0, fYOffset, m_fYReverseOffsetPixels ); + const float fZoom = ArrowEffects::GetZoom( m_pPlayerState ); + const float xBase = GetWidth()/2.f; + const float xOffset = COMBO_OFFSETX * fZoom; + + m_textMeasureNumber.SetZoom( fZoom ); + m_textMeasureNumber.SetHorizAlign( COMBO_IS_LEFT_SIDE ? align_right : align_left ); + m_textMeasureNumber.SetDiffuse( COMBO_COLOR ); + m_textMeasureNumber.SetGlow( RageColor(1,1,1,RageFastCos(RageTimer::GetTimeSinceStartFast()*2)/2+0.5f) ); + m_textMeasureNumber.SetText( ssprintf("%d", iCombo) ); + m_textMeasureNumber.SetXY( (COMBO_IS_LEFT_SIDE ? -xBase - xOffset : xBase + xOffset), fYPos ); + m_textMeasureNumber.Draw(); +} + void NoteField::DrawAttackText( const float fBeat, const Attack &attack ) { const float fYOffset = ArrowEffects::GetYOffset( m_pPlayerState, 0, fBeat ); @@ -776,6 +796,19 @@ void NoteField::DrawPrimitives() DrawTickcountText( fBeat, tTickcountSegments[i].m_iTicks ); } } + + // Combo text + const vector &tComboSegments = GAMESTATE->m_pCurSong->m_Timing.m_ComboSegments; + for( unsigned i=0; i= iFirstRowToDraw && + tComboSegments[i].m_iStartRow <= iLastRowToDraw) + { + float fBeat = NoteRowToBeat(tComboSegments[i].m_iStartRow); + if( IS_ON_SCREEN(fBeat) ) + DrawComboText( fBeat, tComboSegments[i].m_iCombo ); + } + } // todo: add warp text -aj diff --git a/src/NoteField.h b/src/NoteField.h index 4a9723288f..eade904c95 100644 --- a/src/NoteField.h +++ b/src/NoteField.h @@ -59,6 +59,7 @@ protected: void DrawFreezeText( const float fBeat, const float fBPM, const float bDelay ); void DrawTimeSignatureText( const float fBeat, int iNumerator, int iDenominator ); void DrawTickcountText( const float fBeat, int iTicks ); + void DrawComboText( const float fBeat, int iCombo ); void DrawAttackText( const float fBeat, const Attack &attack ); void DrawBGChangeText( const float fBeat, const RString sNewBGName ); float GetWidth() const; diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 8bad6e7fd9..5f6a366e9c 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -78,6 +78,7 @@ AutoScreenMessage( SM_BackFromDelayChange ); AutoScreenMessage( SM_BackFromTimeSignatureNumeratorChange ); AutoScreenMessage( SM_BackFromTimeSignatureDenominatorChange ); AutoScreenMessage( SM_BackFromTickcountChange ); +AutoScreenMessage( SM_BackFromComboChange ); AutoScreenMessage( SM_DoSaveAndExit ); AutoScreenMessage( SM_DoExit ); AutoScreenMessage( SM_SaveSuccessful ); @@ -578,7 +579,8 @@ static MenuDef g_TimingDataInformation( MenuRowDef( ScreenEdit::delay, "Edit delay", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::time_signature_numerator, "Edit time signature (top)", true, EditMode_Full, true, true, 0, NULL ), MenuRowDef( ScreenEdit::time_signature_denominator, "Edit time signature (bottom)", true, EditMode_Full, true, true, 0, NULL ), - MenuRowDef( ScreenEdit::tickcount, "Edit tickcount", true, EditMode_Full, true, true, 0, NULL ) + MenuRowDef( ScreenEdit::tickcount, "Edit tickcount", true, EditMode_Full, true, true, 0, NULL ), + MenuRowDef( ScreenEdit::combo, "Edit combo", true, EditMode_Full, true, true, 0, NULL ) ); enum { song_bganimation, song_movie, song_bitmap, global_bganimation, global_movie, global_movie_song_group, global_movie_song_group_and_genre, dynamic_random, baked_random, none }; @@ -2651,6 +2653,15 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) } SetDirty( true ); } + else if ( SM == SM_BackFromComboChange ) + { + int iCombo = atoi( ScreenTextEntry::s_sLastAnswer ); + if ( iCombo >= 0 ) + { + m_pSong->m_Timing.SetComboAtBeat( GAMESTATE->m_fSongBeat, iCombo ); + } + SetDirty( true ); + } else if( SM == SM_BackFromBGChange ) { HandleBGChangeChoice( (BGChangeChoice)ScreenMiniMenu::s_iLastRowCode, ScreenMiniMenu::s_viLastAnswers ); @@ -3169,6 +3180,7 @@ void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, const vector &iAns g_TimingDataInformation.rows[time_signature_numerator].SetOneUnthemedChoice( ssprintf("%d", pTime.GetTimeSignatureNumeratorAtBeat( fBeat ) ) ); g_TimingDataInformation.rows[time_signature_denominator].SetOneUnthemedChoice( ssprintf("%d", pTime.GetTimeSignatureDenominatorAtBeat( fBeat ) ) ); g_TimingDataInformation.rows[tickcount].SetOneUnthemedChoice( ssprintf("%d", pTime.GetTickcountAtBeat( fBeat ) ) ); + g_TimingDataInformation.rows[combo].SetOneUnthemedChoice( ssprintf("%d", pTime.GetComboAtBeat( fBeat ) ) ); EditMiniMenu( &g_TimingDataInformation, SM_BackFromTimingDataInformation ); } @@ -3620,6 +3632,7 @@ static LocalizedString ENTER_DELAY_VALUE ( "ScreenEdit", "Enter a new Delay va static LocalizedString ENTER_TIME_SIGNATURE_NUMERATOR_VALUE ( "ScreenEdit", "Enter a new Time Signature numerator value." ); static LocalizedString ENTER_TIME_SIGNATURE_DENOMINATOR_VALUE ( "ScreenEdit", "Enter a new Time Signature denominator value." ); static LocalizedString ENTER_TICKCOUNT_VALUE ( "ScreenEdit", "Enter a new Tickcount value." ); +static LocalizedString ENTER_COMBO_VALUE ( "ScreenEdit", "Enter a new Combo value." ); void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice c, const vector &iAnswers ) { switch( c ) @@ -3676,6 +3689,14 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice 2 ); break; + case combo: + ScreenTextEntry::TextEntry( + SM_BackFromComboChange, + ENTER_COMBO_VALUE, + ssprintf( "%d", m_pSong->m_Timing.GetComboAtBeat( GAMESTATE->m_fSongBeat ) ), + 4 + ); + break; } } diff --git a/src/ScreenEdit.h b/src/ScreenEdit.h index f4f38717f7..f32e6940ac 100644 --- a/src/ScreenEdit.h +++ b/src/ScreenEdit.h @@ -448,6 +448,7 @@ public: time_signature_numerator, time_signature_denominator, tickcount, + combo, NUM_TIMING_DATA_INFORMATION_CHOICES }; diff --git a/src/TimingData.cpp b/src/TimingData.cpp index c6dacd4c9d..3e03b64351 100644 --- a/src/TimingData.cpp +++ b/src/TimingData.cpp @@ -227,14 +227,7 @@ float TimingData::GetDelayAtRow( int iRow ) const int TimingData::GetComboAtRow( int iNoteRow ) const { - for( unsigned i=0; i Date: Sat, 5 Mar 2011 02:02:56 -0500 Subject: [PATCH 7/7] Combos branch: changelog to wrap this up. --- Docs/Changelog_sm-ssc.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Docs/Changelog_sm-ssc.txt b/Docs/Changelog_sm-ssc.txt index a44354a134..64ffa95a85 100644 --- a/Docs/Changelog_sm-ssc.txt +++ b/Docs/Changelog_sm-ssc.txt @@ -13,6 +13,10 @@ _____________________________________________________________________________ sm-ssc v1.2.3 | 201103?? -------------------------------------------------------------------------------- +20110305 +-------- +* Added #COMBOS tag to the .ssc format. [Wolfman2000] + 20110302 -------- * [ScreenGameplaySyncMachine] Allow themers to use either .ssc or .sm files. [AJ]