this is a big one...

[Player] fix a warning [shakesoda]
[Player] Change combo coloring logic in course mode:
"PERCENT_UNTIL_COLOR_COMBO refers to how long through the course the combo color
should appear (scaling to the number of songs). (This may not be desired behavior,
however.)" Let me know if I should add an alternate way to specify course combo
color logic.  -aj

[other files including Player.cpp]
Update warp note logic; It used to be WarpFromRow=WarpToRow, now it's WarpFromRow=WarpLengthBeats.
They still aren't functional but I'm getting closer. Negative Stops are still not converted.
This commit is contained in:
AJ Kelly
2010-08-15 16:12:30 -05:00
parent 0a1793c289
commit 26bd3d565b
9 changed files with 139 additions and 90 deletions
+7
View File
@@ -20,6 +20,13 @@ sm-ssc v1.0 Release Candidate 2 | 201008xx
* [ScreenNetEvaluation] add Score, Grade, PlayerOptions params to * [ScreenNetEvaluation] add Score, Grade, PlayerOptions params to
UpdateNetEvalStats message UpdateNetEvalStats message
* [PlayerState] add GetHealthState Lua binding * [PlayerState] add GetHealthState Lua binding
* [Player] fix a warning [shakesoda]
* [Player] Change combo coloring logic in course mode:
"PERCENT_UNTIL_COLOR_COMBO refers to how long through the course the combo
color should appear (scaling to the number of songs). (This may not be
desired behavior, however.)" Let me know if I should add an alternate way to
specify course combo color logic. -aj
* [ScreenRanking] Cleanup and un-hardcode shadowlength
20100814 20100814
-------- --------
+3 -3
View File
@@ -700,10 +700,10 @@ void BackgroundImpl::Layer::UpdateCurBGChange( const Song *pSong, float fLastMus
if( m_aBGChanges.size() == 0 ) if( m_aBGChanges.size() == 0 )
return; return;
float fBeat, fBPS; float fBeat, fBPS, fThrowAway;
bool bFreeze; bool bFreeze;
int iThrowAway1, iThrowAway2; int iThrowAway;
pSong->m_Timing.GetBeatAndBPSFromElapsedTime( fCurrentTime, fBeat, fBPS, bFreeze, bFreeze, iThrowAway1, iThrowAway2 ); pSong->m_Timing.GetBeatAndBPSFromElapsedTime( fCurrentTime, fBeat, fBPS, bFreeze, bFreeze, iThrowAway, fThrowAway );
/* Calls to Update() should *not* be scaled by music rate; fCurrentTime is. Undo it. */ /* Calls to Update() should *not* be scaled by music rate; fCurrentTime is. Undo it. */
const float fRate = GAMESTATE->m_SongOptions.GetCurrent().m_fMusicRate; const float fRate = GAMESTATE->m_SongOptions.GetCurrent().m_fMusicRate;
+8 -8
View File
@@ -896,7 +896,7 @@ void GameState::ResetMusicStatistics()
m_bFreeze = false; m_bFreeze = false;
m_bDelay = false; m_bDelay = false;
m_iWarpBeginRow = -1; // Set to -1 because some song may want to warp to row 0. -aj m_iWarpBeginRow = -1; // Set to -1 because some song may want to warp to row 0. -aj
m_iWarpEndRow = -1; // Set when a warp is encountered. also see above. -aj m_fWarpLength = -1; // Set when a warp is encountered. also see above. -aj
m_fMusicSecondsVisible = 0; m_fMusicSecondsVisible = 0;
m_fSongBeatVisible = 0; m_fSongBeatVisible = 0;
Actor::SetBGMTime( 0, 0, 0, 0 ); Actor::SetBGMTime( 0, 0, 0, 0 );
@@ -956,16 +956,16 @@ void GameState::UpdateSongPosition( float fPositionSeconds, const TimingData &ti
LOG->Trace( ssprintf("[GameState::UpdateSongPosition] cur BPS = %f, fPositionSeconds = %f",m_fCurBPS,fPositionSeconds) ); LOG->Trace( ssprintf("[GameState::UpdateSongPosition] cur BPS = %f, fPositionSeconds = %f",m_fCurBPS,fPositionSeconds) );
*/ */
timing.GetBeatAndBPSFromElapsedTime( fPositionSeconds, m_fSongBeat, m_fCurBPS, m_bFreeze, m_bDelay, m_iWarpBeginRow, m_iWarpEndRow ); timing.GetBeatAndBPSFromElapsedTime( fPositionSeconds, m_fSongBeat, m_fCurBPS, m_bFreeze, m_bDelay, m_iWarpBeginRow, m_fWarpLength );
// "Crash reason : -243478.890625 -48695.773438" // "Crash reason : -243478.890625 -48695.773438"
ASSERT_M( m_fSongBeat > -2000, ssprintf("Song beat %f at %f seconds", m_fSongBeat, fPositionSeconds) ); ASSERT_M( m_fSongBeat > -2000, ssprintf("Song beat %f at %f seconds", m_fSongBeat, fPositionSeconds) );
//if( m_iWarpBeginRow != -1 || m_iWarpEndRow == -1 ) //if( m_iWarpBeginRow != -1 || m_iWarpEndRow == -1 )
if( m_iWarpBeginRow != -1 && m_iWarpEndRow == -1 ) if( m_iWarpBeginRow != -1 && m_fWarpLength > 0.f )
{ {
// we got a warp in this section. // we got a warp in this section.
LOG->Trace("warp at %i jumps to %i",m_iWarpBeginRow,m_iWarpEndRow); LOG->Trace("warp at %i lasts for %f, jumps to %i",m_iWarpBeginRow,m_fWarpLength,m_iWarpBeginRow+BeatToNoteRow(m_fWarpLength));
// i hate this part because how the hell do i convert rows to seconds? //fPositionSeconds += (m_fWarpLength * m_fCurBPS);
} }
/* /*
// xxx testing: only do this on monotune survivor // xxx testing: only do this on monotune survivor
@@ -983,10 +983,10 @@ void GameState::UpdateSongPosition( float fPositionSeconds, const TimingData &ti
m_fSongBeatNoOffset = timing.GetBeatFromElapsedTimeNoOffset( fPositionSeconds ); m_fSongBeatNoOffset = timing.GetBeatFromElapsedTimeNoOffset( fPositionSeconds );
m_fMusicSecondsVisible = fPositionSeconds - g_fVisualDelaySeconds.Get(); m_fMusicSecondsVisible = fPositionSeconds - g_fVisualDelaySeconds.Get();
float fThrowAway; float fThrowAway, fThrowAway2;
bool bThrowAway; bool bThrowAway;
int iThrowAway1, iThrowAway2; int iThrowAway;
timing.GetBeatAndBPSFromElapsedTime( m_fMusicSecondsVisible, m_fSongBeatVisible, fThrowAway, bThrowAway, bThrowAway, iThrowAway1, iThrowAway2 ); timing.GetBeatAndBPSFromElapsedTime( m_fMusicSecondsVisible, m_fSongBeatVisible, fThrowAway, bThrowAway, bThrowAway, iThrowAway, fThrowAway2 );
/* /*
// xxx testing: only do this on monotune survivor // xxx testing: only do this on monotune survivor
+9 -1
View File
@@ -184,10 +184,18 @@ public:
//bool m_bStop; // in the middle of a stop (freeze or delay) //bool m_bStop; // in the middle of a stop (freeze or delay)
bool m_bFreeze; // in the middle of a freeze bool m_bFreeze; // in the middle of a freeze
bool m_bDelay; // in the middle of a delay bool m_bDelay; // in the middle of a delay
int m_iWarpBeginRow, m_iWarpEndRow; // used for warping // used for warping:
int m_iWarpBeginRow;
float m_fWarpLength;
RageTimer m_LastBeatUpdate; // time of last m_fSongBeat, etc. update RageTimer m_LastBeatUpdate; // time of last m_fSongBeat, etc. update
BroadcastOnChange<bool> m_bGameplayLeadIn; BroadcastOnChange<bool> m_bGameplayLeadIn;
// Metricable noteskin things
// void LoadNoteSkinMetrics( PlayerNumber pn );
// int m_iRowSpacing;
// int m_iColSpacing;
// int m_iArrowSize;
float m_fMusicSecondsVisible; float m_fMusicSecondsVisible;
float m_fSongBeatVisible; float m_fSongBeatVisible;
+19 -15
View File
@@ -208,12 +208,13 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out )
split( arrayBPMChangeExpressions[b+1], "=", arrayNextBPMChangeValues ); split( arrayBPMChangeExpressions[b+1], "=", arrayNextBPMChangeValues );
const float fNextPositiveBeat = StringToFloat( arrayNextBPMChangeValues[0] ); const float fNextPositiveBeat = StringToFloat( arrayNextBPMChangeValues[0] );
const float fNextPositiveBPM = StringToFloat( arrayNextBPMChangeValues[1] ); const float fNextPositiveBPM = StringToFloat( arrayNextBPMChangeValues[1] );
//LOG->Trace( ssprintf("String (%s) vs. BPM (%f)",arrayNextBPMChangeValues[1].c_str(),fNextPositiveBPM) );
// tJumpPos = (tPosBPS-abs(negBPS)) + (gPosBPMPosition - fNegPosition) // tJumpPos = (tPosBPS-abs(negBPS)) + (gPosBPMPosition - fNegPosition)
float fDeltaBeat = ((fNextPositiveBPM/60.0f)-abs(fNewBPM/60.0f)) + (fNextPositiveBeat-fBeat); float fDeltaBeat = ((fNextPositiveBPM/60.0f)-abs(fNewBPM/60.0f)) + (fNextPositiveBeat-fBeat);
float fWarpToBeat = fNextPositiveBeat + fDeltaBeat; //float fWarpLengthBeats = fNextPositiveBeat + fDeltaBeat;
WarpSegment wsTemp(BeatToNoteRow(fBeat),BeatToNoteRow(fWarpToBeat)); WarpSegment wsTemp(BeatToNoteRow(fBeat),fDeltaBeat);
arrayWarpsFromNegativeBPMs.push_back(wsTemp); arrayWarpsFromNegativeBPMs.push_back(wsTemp);
/* /*
LOG->Trace( ssprintf("==NotesLoSM negbpm==\nfnextposbeat = %f, fnextposbpm = %f,\nfdelta = %f, fwarpto = %f", LOG->Trace( ssprintf("==NotesLoSM negbpm==\nfnextposbeat = %f, fnextposbpm = %f,\nfdelta = %f, fwarpto = %f",
fNextPositiveBeat, fNextPositiveBeat,
@@ -236,6 +237,7 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out )
fDeltaBeat,(fNextPositiveBPM/60.0f),abs(fNewBPM/60.0f),BeatToNoteRow(fNextPositiveBeat),BeatToNoteRow(fBeat)) fDeltaBeat,(fNextPositiveBPM/60.0f),abs(fNewBPM/60.0f),BeatToNoteRow(fNextPositiveBeat),BeatToNoteRow(fBeat))
); );
*/ */
continue;
} }
else else
{ {
@@ -302,6 +304,7 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out )
} }
} }
// warps (replacement for Negative BPM and Negative Stops)
/* /*
else if( sValueName=="WARPS" ) else if( sValueName=="WARPS" )
{ {
@@ -320,27 +323,28 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out )
continue; continue;
} }
const float fWarpAt = StringToFloat( arrayWarpValues[0] ); const float fWarpStart = StringToFloat( arrayWarpValues[0] );
const float fWarpTo = StringToFloat( arrayWarpValues[1] ); const float fWarpBeats = StringToFloat( arrayWarpValues[1] );
if( fWarpAt > 0.0f && fWarpTo > 0.0f ) if( fWarpStart > 0.0f && fWarpBeats > 0.0f )
{ {
WarpSegment new_seg( BeatToNoteRow(fWarpAt), BeatToNoteRow(fWarpTo) ); WarpSegment new_seg( BeatToNoteRow(fWarpStart), fWarpBeats );
// LOG->Trace( "Adding a warp segment: starts at %f, jumps to %f", new_seg.m_iStartRow, new_seg.m_iEndRow );
out.AddWarpSegment( new_seg ); out.AddWarpSegment( new_seg );
} }
else else
{ {
// Disallow negative warps, to prevent the same kind of // Currently disallow negative warps, to prevent the same
// problem that happened when Negative/Subtractive BPMs // kind of problem that happened when Negative/Subtractive
// arrived on the StepMania scene. -aj // BPMs arrived on the StepMania scene. -aj
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid warp: from beat %f to beat %f.", fWarpAt, fWarpTo ); LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid warp at beat %f lasting %f beats.", fWarpStart, fWarpBeats );
} }
} }
} }
*/ */
// We should not support files that contain both Negative BPMs & Warps. // Note: Even though it is possible to have Negative BPMs and Stops in
// a song along with Warps, we should not support files that contain
// both styles of warp tricks (Negatives vs. #WARPS).
// If Warps have been populated from Negative BPMs, then go through that // If Warps have been populated from Negative BPMs, then go through that
// instead of using the data in the Warps tag. This should be above, // instead of using the data in the Warps tag. This should be above,
// but it breaks compiling so... // but it breaks compiling so...
@@ -351,9 +355,9 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out )
{ {
out.AddWarpSegment( arrayWarpsFromNegativeBPMs[i] ); out.AddWarpSegment( arrayWarpsFromNegativeBPMs[i] );
} }
// sorting will need to take place somewhere.
} }
// warp sorting will need to take place.
//sort(out.m_WarpSegments.begin(), out.m_WarpSegments.end());
} }
} }
+7 -12
View File
@@ -141,14 +141,11 @@ static void WriteGlobalTags( RageFile &f, const Song &out )
f.Write( "#WARPS:" ); f.Write( "#WARPS:" );
for( unsigned i=0; i<out.m_Timing.m_WarpSegments.size(); i++ ) for( unsigned i=0; i<out.m_Timing.m_WarpSegments.size(); i++ )
{ {
const WarpSegment &fs = out.m_Timing.m_WarpSegments[i]; const WarpSegment &ws = out.m_Timing.m_WarpSegments[i];
if( fs.m_bDelay ) f.PutLine( ssprintf( "%.6f=%.6f", NoteRowToBeat(ws.m_iStartRow), ws.m_fWarpBeats ) );
{ if( i != out.m_Timing.m_WarpSegments.size()-1 )
f.PutLine( ssprintf( "%.3f=%.3f", NoteRowToBeat(fs.m_iStartRow), fs.m_fStopSeconds ) ); f.Write( "," );
if( i != out.m_Timing.m_StopSegments.size()-1 )
f.Write( "," );
}
} }
f.PutLine( ";" ); f.PutLine( ";" );
*/ */
@@ -292,9 +289,7 @@ bool NotesWriterSM::Write( RString sPath, const Song &out, const vector<Steps*>&
f.PutLine( ssprintf( "// end cache tags" ) ); f.PutLine( ssprintf( "// end cache tags" ) );
} }
//
// Save specified Steps to this file // Save specified Steps to this file
//
FOREACH_CONST( Steps*, vpStepsToSave, s ) FOREACH_CONST( Steps*, vpStepsToSave, s )
{ {
const Steps* pSteps = *s; const Steps* pSteps = *s;
@@ -312,7 +307,7 @@ void NotesWriterSM::GetEditFileContents( const Song *pSong, const Steps *pSteps,
sOut = ""; sOut = "";
RString sDir = pSong->GetSongDir(); RString sDir = pSong->GetSongDir();
/* "Songs/foo/bar"; strip off "Songs/". */ // "Songs/foo/bar"; strip off "Songs/".
vector<RString> asParts; vector<RString> asParts;
split( sDir, "/", asParts ); split( sDir, "/", asParts );
if( asParts.size() ) if( asParts.size() )
@@ -323,7 +318,7 @@ void NotesWriterSM::GetEditFileContents( const Song *pSong, const Steps *pSteps,
RString NotesWriterSM::GetEditFileName( const Song *pSong, const Steps *pSteps ) RString NotesWriterSM::GetEditFileName( const Song *pSong, const Steps *pSteps )
{ {
/* Try to make a unique name. This isn't guaranteed. Edit descriptions are /* Try to make a unique name. This isn't guaranteed. Edit descriptions are
* case-sensitive, filenames on disk are usually not, and we decimate certain * case-sensitive, filenames on disk are usually not, and we decimate certain
* characters for FAT filesystems. */ * characters for FAT filesystems. */
RString sFile = pSong->GetTranslitFullTitle() + " - " + pSteps->GetDescription(); RString sFile = pSong->GetTranslitFullTitle() + " - " + pSteps->GetDescription();
@@ -372,7 +367,7 @@ bool NotesWriterSM::WriteEditFileToMachine( const Song *pSong, Steps *pSteps, RS
} }
/* If the file name of the edit has changed since the last save, then delete the old /* If the file name of the edit has changed since the last save, then delete the old
* file after saving the new one. If we delete it first, then we'll lose data on error. */ * file after saving the new one. If we delete it first, then we'll lose data on error. */
if( bFileNameChanging ) if( bFileNameChanging )
FILEMAN->Remove( pSteps->GetFilename() ); FILEMAN->Remove( pSteps->GetFilename() );
+45 -24
View File
@@ -850,7 +850,7 @@ void Player::Update( float fDeltaTime )
{ {
if( !vHoldNotesToGradeTogether.empty() ) if( !vHoldNotesToGradeTogether.empty() )
{ {
LOG->Trace( ssprintf("UpdateHoldNotes; %i != %i || !judge holds on same row together",iRow,iRowOfLastHoldNote) ); //LOG->Trace( ssprintf("UpdateHoldNotes; %i != %i || !judge holds on same row together",iRow,iRowOfLastHoldNote) );
UpdateHoldNotes( iSongRow, fDeltaTime, vHoldNotesToGradeTogether ); UpdateHoldNotes( iSongRow, fDeltaTime, vHoldNotesToGradeTogether );
vHoldNotesToGradeTogether.clear(); vHoldNotesToGradeTogether.clear();
} }
@@ -861,7 +861,7 @@ void Player::Update( float fDeltaTime )
if( !vHoldNotesToGradeTogether.empty() ) if( !vHoldNotesToGradeTogether.empty() )
{ {
LOG->Trace("UpdateHoldNotes since !vHoldNotesToGradeTogether.empty()"); //LOG->Trace("UpdateHoldNotes since !vHoldNotesToGradeTogether.empty()");
UpdateHoldNotes( iSongRow, fDeltaTime, vHoldNotesToGradeTogether ); UpdateHoldNotes( iSongRow, fDeltaTime, vHoldNotesToGradeTogether );
vHoldNotesToGradeTogether.clear(); vHoldNotesToGradeTogether.clear();
} }
@@ -913,8 +913,8 @@ void Player::UpdateHoldNotes( int iSongRow, float fDeltaTime, vector<TrackRowTap
{ {
ASSERT( !vTN.empty() ); ASSERT( !vTN.empty() );
//LOG->Trace("--------------------------------");
/* /*
LOG->Trace("--------------------------------");
LOG->Trace("[Player::UpdateHoldNotes] begins"); LOG->Trace("[Player::UpdateHoldNotes] begins");
LOG->Trace( ssprintf("song row %i, deltaTime = %f",iSongRow,fDeltaTime) ); LOG->Trace( ssprintf("song row %i, deltaTime = %f",iSongRow,fDeltaTime) );
*/ */
@@ -947,6 +947,7 @@ void Player::UpdateHoldNotes( int iSongRow, float fDeltaTime, vector<TrackRowTap
ASSERT( iFirstTrackWithMaxEndRow != -1 ); ASSERT( iFirstTrackWithMaxEndRow != -1 );
//LOG->Trace( ssprintf("start row: %i; max/end row: = %i",iStartRow,iMaxEndRow) ); //LOG->Trace( ssprintf("start row: %i; max/end row: = %i",iStartRow,iMaxEndRow) );
//LOG->Trace( ssprintf("first track with max end row = %i",iFirstTrackWithMaxEndRow) ); //LOG->Trace( ssprintf("first track with max end row = %i",iFirstTrackWithMaxEndRow) );
//LOG->Trace( ssprintf("max end row - start row (in beats) = %f",NoteRowToBeat(iMaxEndRow)-NoteRowToBeat(iStartRow)) );
FOREACH( TrackRowTapNote, vTN, trtn ) FOREACH( TrackRowTapNote, vTN, trtn )
{ {
@@ -1011,11 +1012,11 @@ void Player::UpdateHoldNotes( int iSongRow, float fDeltaTime, vector<TrackRowTap
bool bInitiatedNote; bool bInitiatedNote;
if( REQUIRE_STEP_ON_HOLD_HEADS ) if( REQUIRE_STEP_ON_HOLD_HEADS )
{ {
// XXX HACK: Miniholds (a 192nd length hold) will not always register // XXX HACK: Miniholds (a 64th or 192nd length hold) will not always
// as Held, even if you hit the note. This is considered a major // register as Held, even if you hit the note. This is considered a
// roadblock to adoption, so until a proper fix is found, // major roadblock to adoption, so until a proper fix is found,
// DON'T REMOVE THIS HACK! -aj // DON'T REMOVE THIS HACK! -aj
if( iMaxEndRow-iStartRow <= 1 ) if( iMaxEndRow-iStartRow <= 4 )
bInitiatedNote = true; bInitiatedNote = true;
else else
bInitiatedNote = bSteppedOnHead; bInitiatedNote = bSteppedOnHead;
@@ -2121,7 +2122,7 @@ void Player::StepStrumHopo( int col, int row, const RageTimer &tm, bool bHeld, b
// figure out overlap. // figure out overlap.
float fLowerBound = 0.0f; // negative upper limit float fLowerBound = 0.0f; // negative upper limit
float fUpperBound = 0.0f; // positive lower limit float fUpperBound = 0.0f; // positive lower limit
float fCompareWindow; // filled in here: float fCompareWindow = 0.0f; // filled in here:
if( score == TNS_W2 ) if( score == TNS_W2 )
{ {
fLowerBound = -fWindowW1; fLowerBound = -fWindowW1;
@@ -2483,8 +2484,9 @@ void Player::UpdateTapNotesMissedOlderThan( float fMissIfOlderThanSeconds )
bool bFreeze, bDelay; bool bFreeze, bDelay;
float fMissIfOlderThanThisBeat; float fMissIfOlderThanThisBeat;
float fThrowAway; float fThrowAway;
int iWarpBeginRow, iWarpEndRow; int iWarpBeginRow;
GAMESTATE->m_pCurSong->m_Timing.GetBeatAndBPSFromElapsedTime( fEarliestTime, fMissIfOlderThanThisBeat, fThrowAway, bFreeze, bDelay, iWarpBeginRow, iWarpEndRow ); float fWarpLength;
GAMESTATE->m_pCurSong->m_Timing.GetBeatAndBPSFromElapsedTime( fEarliestTime, fMissIfOlderThanThisBeat, fThrowAway, bFreeze, bDelay, iWarpBeginRow, fWarpLength );
iMissIfOlderThanThisRow = BeatToNoteRow( fMissIfOlderThanThisBeat ); iMissIfOlderThanThisRow = BeatToNoteRow( fMissIfOlderThanThisBeat );
if( bFreeze || bDelay ) if( bFreeze || bDelay )
@@ -2521,7 +2523,7 @@ void Player::UpdateTapNotesMissedOlderThan( float fMissIfOlderThanSeconds )
{ {
// warp hackery: don't score notes within the warp region. // warp hackery: don't score notes within the warp region.
// (Only useful when QuirksMode is enabled.) -aj // (Only useful when QuirksMode is enabled.) -aj
if( iter.Row() >= GAMESTATE->m_iWarpBeginRow && iter.Row() <= GAMESTATE->m_iWarpEndRow ) if( iter.Row() >= GAMESTATE->m_iWarpBeginRow && iter.Row() <= (GAMESTATE->m_iWarpBeginRow + BeatToNoteRow(GAMESTATE->m_fWarpLength)) )
continue; continue;
tn.result.tns = TNS_Miss; tn.result.tns = TNS_Miss;
@@ -2547,7 +2549,8 @@ void Player::UpdateJudgedRows()
iLastSeenRow = iRow; iLastSeenRow = iRow;
// if row is within a warp section, ignore it. -aj // if row is within a warp section, ignore it. -aj
if(iRow >= GAMESTATE->m_iWarpBeginRow && iRow <= GAMESTATE->m_iWarpEndRow) if( iRow >= GAMESTATE->m_iWarpBeginRow &&
iRow <= (GAMESTATE->m_iWarpBeginRow + BeatToNoteRow(GAMESTATE->m_fWarpLength)) )
continue; continue;
// crossed a nonempty row // crossed a nonempty row
@@ -2910,7 +2913,8 @@ void Player::HandleTapRowScore( unsigned row )
#endif #endif
// more warp hackery. -aj // more warp hackery. -aj
if(row >= (unsigned)GAMESTATE->m_iWarpBeginRow && row <= (unsigned)GAMESTATE->m_iWarpEndRow) if( row >= (unsigned)GAMESTATE->m_iWarpBeginRow &&
row <= (unsigned)(GAMESTATE->m_iWarpBeginRow + BeatToNoteRow(GAMESTATE->m_fWarpLength)) )
return; return;
if( GAMESTATE->m_bDemonstrationOrJukebox ) if( GAMESTATE->m_bDemonstrationOrJukebox )
@@ -2982,14 +2986,11 @@ void Player::HandleTapRowScore( unsigned row )
if( m_pPlayerStageStats ) if( m_pPlayerStageStats )
m_pPlayerStageStats->m_iMaxCombo = max(m_pPlayerStageStats->m_iMaxCombo, iCurCombo); m_pPlayerStageStats->m_iMaxCombo = max(m_pPlayerStageStats->m_iMaxCombo, iCurCombo);
/* /* Use the real current beat, not the beat we've been passed. That's because
* Use the real current beat, not the beat we've been passed. That's because we * we want to record the current life/combo to the current time; eg. if it's
* want to record the current life/combo to the current time; eg. if it's a MISS, * a MISS, the beat we're registering is in the past, but the life is changing
* the beat we're registering is in the past, but the life is changing now. * now. We need to include time from previous songs in a course, so we
* * can't use GAMESTATE->m_fMusicSeconds. Use fStepsSeconds instead. */
* We need to include time from previous songs in a course, so we can't use
* GAMESTATE->m_fMusicSeconds. Use fStepsSeconds instead.
*/
if( m_pPlayerStageStats ) if( m_pPlayerStageStats )
m_pPlayerStageStats->UpdateComboList( STATSMAN->m_CurStageStats.m_fStepsSeconds, false ); m_pPlayerStageStats->UpdateComboList( STATSMAN->m_CurStageStats.m_fStepsSeconds, false );
@@ -3188,9 +3189,29 @@ void Player::SetCombo( int iCombo, int iMisses )
if( b1000Milestone ) if( b1000Milestone )
this->PlayCommand( "ThousandMilestone" ); this->PlayCommand( "ThousandMilestone" );
// don't show a colored combo until 1/4 of the way through the song /* Colored combo logic differs between Songs and Courses.
bool bPastBeginning = (!GAMESTATE->IsCourseMode() || GAMESTATE->GetCourseSongIndex()>0) && * Songs:
GAMESTATE->m_fMusicSeconds > GAMESTATE->m_pCurSong->m_fMusicLengthSeconds * PERCENT_UNTIL_COLOR_COMBO; * The theme decides how far into the song the combo color should appear.
* (PERCENT_UNTIL_COLOR_COMBO)
*
* Courses:
* PERCENT_UNTIL_COLOR_COMBO refers to how long through the course the
* combo color should appear (scaling to the number of songs). This may
* not be desired behavior, however. -aj
*
* TODO: Add a metric that determines Course combo colors logic?
* Or possibly move the logic to a Lua function? -aj */
bool bPastBeginning = false;
if( GAMESTATE->IsCourseMode() )
{
int iSongIndexStartColoring = GAMESTATE->m_pCurCourse->GetEstimatedNumStages();
iSongIndexStartColoring = floor(iSongIndexStartColoring*PERCENT_UNTIL_COLOR_COMBO);
bPastBeginning = GAMESTATE->GetCourseSongIndex() >= iSongIndexStartColoring;
}
else
{
bPastBeginning = GAMESTATE->m_fMusicSeconds > GAMESTATE->m_pCurSong->m_fMusicLengthSeconds * PERCENT_UNTIL_COLOR_COMBO;
}
if( m_bSendJudgmentAndComboMessages ) if( m_bSendJudgmentAndComboMessages )
{ {
+27 -13
View File
@@ -110,7 +110,7 @@ void TimingData::SetDelayAtRow( int iRow, float fSeconds )
} }
/* /*
void TimingData::SetWarpAtRow( int iRowAt, int iRowTo ) void TimingData::SetWarpAtRow( int iRowAt, float fLengthBeats )
{ {
// todo: code this -aj // todo: code this -aj
} }
@@ -137,7 +137,7 @@ int TimingData::GetWarpToRow( int iWarpBeginRow ) const
{ {
if( m_WarpSegments[i].m_iStartRow == iWarpBeginRow ) if( m_WarpSegments[i].m_iStartRow == iWarpBeginRow )
{ {
return m_WarpSegments[i].m_iEndRow; return iWarpBeginRow + BeatToNoteRow(m_WarpSegments[i].m_fWarpBeats);
} }
} }
return 0; return 0;
@@ -223,14 +223,14 @@ BPMSegment& TimingData::GetBPMSegmentAtBeat( float fBeat )
return m_BPMSegments[i]; return m_BPMSegments[i];
} }
void TimingData::GetBeatAndBPSFromElapsedTime( float fElapsedTime, float &fBeatOut, float &fBPSOut, bool &bFreezeOut, bool &bDelayOut, int &iWarpBeginOut, int &iWarpEndOut ) const void TimingData::GetBeatAndBPSFromElapsedTime( float fElapsedTime, float &fBeatOut, float &fBPSOut, bool &bFreezeOut, bool &bDelayOut, int &iWarpBeginOut, float &fWarpLengthOut ) const
{ {
fElapsedTime += PREFSMAN->m_fGlobalOffsetSeconds; fElapsedTime += PREFSMAN->m_fGlobalOffsetSeconds;
GetBeatAndBPSFromElapsedTimeNoOffset( fElapsedTime, fBeatOut, fBPSOut, bFreezeOut, bDelayOut, iWarpBeginOut, iWarpEndOut ); GetBeatAndBPSFromElapsedTimeNoOffset( fElapsedTime, fBeatOut, fBPSOut, bFreezeOut, bDelayOut, iWarpBeginOut, fWarpLengthOut );
} }
void TimingData::GetBeatAndBPSFromElapsedTimeNoOffset( float fElapsedTime, float &fBeatOut, float &fBPSOut, bool &bFreezeOut, bool &bDelayOut, int &iWarpBeginOut, int &iWarpEndOut ) const void TimingData::GetBeatAndBPSFromElapsedTimeNoOffset( float fElapsedTime, float &fBeatOut, float &fBPSOut, bool &bFreezeOut, bool &bDelayOut, int &iWarpBeginOut, float &fWarpLengthOut ) const
{ {
// LOG->Trace( "GetBeatAndBPSFromElapsedTime( fElapsedTime = %f )", fElapsedTime ); // LOG->Trace( "GetBeatAndBPSFromElapsedTime( fElapsedTime = %f )", fElapsedTime );
const float fTime = fElapsedTime; const float fTime = fElapsedTime;
@@ -277,7 +277,7 @@ void TimingData::GetBeatAndBPSFromElapsedTimeNoOffset( float fElapsedTime, float
bFreezeOut = !bIsDelay; bFreezeOut = !bIsDelay;
bDelayOut = bIsDelay; bDelayOut = bIsDelay;
//iWarpBeginOut = -1; //iWarpBeginOut = -1;
//iWarpEndOut = -1; //fWarpLengthOut = -1;
return; return;
} }
} }
@@ -290,17 +290,31 @@ void TimingData::GetBeatAndBPSFromElapsedTimeNoOffset( float fElapsedTime, float
if( !bIsLastBPMSegment && m_WarpSegments[j].m_iStartRow > iStartRowNextSegment ) if( !bIsLastBPMSegment && m_WarpSegments[j].m_iStartRow > iStartRowNextSegment )
continue; continue;
// this warp lies within this BPMSegment. // are these wrong? am I second guessing myself?
iWarpBeginOut = m_WarpSegments[j].m_iStartRow;
iWarpEndOut = m_WarpSegments[j].m_iEndRow;
// this warp lies within this BPMSegment, and these are wrong
// huh? -aj
/* /*
const int iRowsBeatsSinceStartOfSegment = m_WarpSegments[j].m_iStartRow - iStartRowThisSegment; const int iRowsBeatsSinceStartOfSegment = m_WarpSegments[j].m_iStartRow - iStartRowThisSegment;
const float fBeatsSinceStartOfSegment = NoteRowToBeat(iRowsBeatsSinceStartOfSegment); const float fBeatsSinceStartOfSegment = NoteRowToBeat(iRowsBeatsSinceStartOfSegment);
const float fWarpStartSecond = fBeatsSinceStartOfSegment / fBPS; const float fWarpStartSecond = fBeatsSinceStartOfSegment / fBPS;
*/ */
// the freeze segment is <= current time
//fElapsedTime -= m_WarpSegments[j].m_fWarpBeats;
// this warp lies within this BPMSegment.
/*
if( fWarpStartSecond >= fElapsedTime )
{
// this WarpSegment IS the current segment.
// don't know how to properly handle beatout -aj
//fBeatOut = NoteRowToBeat(m_WarpSegments[j].m_iStartRow);
fBPSOut = m_BPMSegments[i+1].m_fBPS;
bFreezeOut = false;
bDelayOut = false;
iWarpBeginOut = m_WarpSegments[j].m_iStartRow;
fWarpLengthOut = m_WarpSegments[j].m_fWarpBeats;
return;
}
*/
} }
const float fBeatsInThisSegment = fStartBeatNextSegment - fStartBeatThisSegment; const float fBeatsInThisSegment = fStartBeatNextSegment - fStartBeatThisSegment;
@@ -320,7 +334,7 @@ void TimingData::GetBeatAndBPSFromElapsedTimeNoOffset( float fElapsedTime, float
bFreezeOut = false; bFreezeOut = false;
bDelayOut = false; bDelayOut = false;
//iWarpBeginOut; //iWarpBeginOut;
//iWarpEndOut; //fWarpLengthOut;
return; return;
} }
+12 -12
View File
@@ -91,15 +91,15 @@ struct TimeSignatureSegment
* both rows though.) */ * both rows though.) */
struct WarpSegment struct WarpSegment
{ {
WarpSegment() : m_iStartRow(-1), m_iEndRow(-1) { } WarpSegment() : m_iStartRow(-1), m_fWarpBeats(-1) { }
WarpSegment( int s, int e ){ m_iStartRow = max( 0, s ); m_iEndRow = max( 0, e ); } WarpSegment( int s, float b ){ m_iStartRow = max( 0, s ); m_fWarpBeats = max( 0, b ); }
int m_iStartRow; int m_iStartRow;
int m_iEndRow; float m_fWarpBeats;
bool operator==( const WarpSegment &other ) const bool operator==( const WarpSegment &other ) const
{ {
COMPARE( m_iStartRow ); COMPARE( m_iStartRow );
COMPARE( m_iEndRow ); COMPARE( m_fWarpBeats );
return true; return true;
} }
bool operator!=( const WarpSegment &other ) const { return !operator==(other); } bool operator!=( const WarpSegment &other ) const { return !operator==(other); }
@@ -132,24 +132,24 @@ public:
BPMSegment& GetBPMSegmentAtBeat( float fBeat ); BPMSegment& GetBPMSegmentAtBeat( float fBeat );
void NoteRowToMeasureAndBeat( int iNoteRow, int &iMeasureIndexOut, int &iBeatIndexOut, int &iRowsRemainder ) const; void NoteRowToMeasureAndBeat( int iNoteRow, int &iMeasureIndexOut, int &iBeatIndexOut, int &iRowsRemainder ) const;
void GetBeatAndBPSFromElapsedTime( float fElapsedTime, float &fBeatOut, float &fBPSOut, bool &bFreezeOut, bool &bDelayOut, int &iWarpBeginOut, int &iWarpEndOut ) const; void GetBeatAndBPSFromElapsedTime( float fElapsedTime, float &fBeatOut, float &fBPSOut, bool &bFreezeOut, bool &bDelayOut, int &iWarpBeginOut, float &fWarpLengthOut ) const;
float GetBeatFromElapsedTime( float fElapsedTime ) const // shortcut for places that care only about the beat float GetBeatFromElapsedTime( float fElapsedTime ) const // shortcut for places that care only about the beat
{ {
float fBeat, fThrowAway; float fBeat, fThrowAway, fThrowAway2;
bool bThrowAway, bThrowAway2; bool bThrowAway, bThrowAway2;
int iThrowAway, iThrowAway2; int iThrowAway;
GetBeatAndBPSFromElapsedTime( fElapsedTime, fBeat, fThrowAway, bThrowAway, bThrowAway2, iThrowAway, iThrowAway2 ); GetBeatAndBPSFromElapsedTime( fElapsedTime, fBeat, fThrowAway, bThrowAway, bThrowAway2, iThrowAway, fThrowAway2 );
return fBeat; return fBeat;
} }
float GetElapsedTimeFromBeat( float fBeat ) const; float GetElapsedTimeFromBeat( float fBeat ) const;
void GetBeatAndBPSFromElapsedTimeNoOffset( float fElapsedTime, float &fBeatOut, float &fBPSOut, bool &bFreezeOut, bool &bDelayOut, int &iWarpBeginOut, int &iWarpEndOut ) const; void GetBeatAndBPSFromElapsedTimeNoOffset( float fElapsedTime, float &fBeatOut, float &fBPSOut, bool &bFreezeOut, bool &bDelayOut, int &iWarpBeginOut, float &iWarpLengthOut ) const;
float GetBeatFromElapsedTimeNoOffset( float fElapsedTime ) const // shortcut for places that care only about the beat float GetBeatFromElapsedTimeNoOffset( float fElapsedTime ) const // shortcut for places that care only about the beat
{ {
float fBeat, fThrowAway; float fBeat, fThrowAway, fThrowAway2;
bool bThrowAway, bThrowAway2; bool bThrowAway, bThrowAway2;
int iThrowAway, iThrowAway2; int iThrowAway;
GetBeatAndBPSFromElapsedTimeNoOffset( fElapsedTime, fBeat, fThrowAway, bThrowAway, bThrowAway2, iThrowAway, iThrowAway2 ); GetBeatAndBPSFromElapsedTimeNoOffset( fElapsedTime, fBeat, fThrowAway, bThrowAway, bThrowAway2, iThrowAway, fThrowAway2 );
return fBeat; return fBeat;
} }
float GetElapsedTimeFromBeatNoOffset( float fBeat ) const; float GetElapsedTimeFromBeatNoOffset( float fBeat ) const;