Use a map for hold grades, so it doesn't get desynced if the number
of hold notes changes.
This commit is contained in:
@@ -100,7 +100,9 @@ int NoteDataWithScoring::GetNumHoldNotesWithScore( HoldNoteScore hns, const floa
|
|||||||
for( int i=0; i<GetNumHoldNotes(); i++ )
|
for( int i=0; i<GetNumHoldNotes(); i++ )
|
||||||
{
|
{
|
||||||
const HoldNote &hn = GetHoldNote(i);
|
const HoldNote &hn = GetHoldNote(i);
|
||||||
if( iStartIndex <= hn.iStartRow && hn.iEndRow <= iEndIndex && m_HoldNoteScores[i] == hns )
|
if( iStartIndex > hn.iStartRow || hn.iEndRow > iEndIndex )
|
||||||
|
continue;
|
||||||
|
if( GetHoldNoteScore(hn) == hns )
|
||||||
iNumSuccessfulHolds++;
|
iNumSuccessfulHolds++;
|
||||||
}
|
}
|
||||||
return iNumSuccessfulHolds;
|
return iNumSuccessfulHolds;
|
||||||
@@ -315,29 +317,30 @@ void NoteDataWithScoring::SetTapNoteOffset(unsigned track, unsigned row, float o
|
|||||||
m_TapNoteOffset[track][row] = offset;
|
m_TapNoteOffset[track][row] = offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
HoldNoteScore NoteDataWithScoring::GetHoldNoteScore(unsigned h) const
|
/* We use the end row to index hold notes, instead of the start row, because the start row
|
||||||
|
* changes when hold notes are being stepped on, but end rows never change. */
|
||||||
|
HoldNoteScore NoteDataWithScoring::GetHoldNoteScore( const HoldNote &hn ) const
|
||||||
{
|
{
|
||||||
if(h >= m_HoldNoteScores.size())
|
map<RowTrack, HoldNoteScore>::const_iterator it = m_HoldNoteScores.find( RowTrack(hn.iEndRow, hn.iTrack) );
|
||||||
|
if( it == m_HoldNoteScores.end() )
|
||||||
return HNS_NONE;
|
return HNS_NONE;
|
||||||
return m_HoldNoteScores[h];
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NoteDataWithScoring::SetHoldNoteScore(unsigned h, HoldNoteScore hns)
|
void NoteDataWithScoring::SetHoldNoteScore( const HoldNote &hn, HoldNoteScore hns )
|
||||||
{
|
{
|
||||||
extend(m_HoldNoteScores, HNS_NONE, h);
|
m_HoldNoteScores[RowTrack(hn.iEndRow, hn.iTrack)] = hns;
|
||||||
m_HoldNoteScores[h] = hns;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NoteDataWithScoring::SetHoldNoteLife(unsigned h, float f)
|
void NoteDataWithScoring::SetHoldNoteLife( const HoldNote &hn, float f )
|
||||||
{
|
{
|
||||||
extend(m_fHoldNoteLife, 1.0f, h);
|
m_fHoldNoteLife[RowTrack(hn.iEndRow, hn.iTrack)] = f;
|
||||||
m_fHoldNoteLife[h] = f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float NoteDataWithScoring::GetHoldNoteLife(unsigned h) const
|
float NoteDataWithScoring::GetHoldNoteLife( const HoldNote &hn ) const
|
||||||
{
|
{
|
||||||
// start with full life
|
map<RowTrack, float>::const_iterator it = m_fHoldNoteLife.find( RowTrack(hn.iEndRow, hn.iTrack) );
|
||||||
if(h >= m_fHoldNoteLife.size())
|
if( it == m_fHoldNoteLife.end() )
|
||||||
return 1.0f;
|
return 1.0f;
|
||||||
return m_fHoldNoteLife[h];
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,12 +14,14 @@
|
|||||||
#include "GameConstantsAndTypes.h"
|
#include "GameConstantsAndTypes.h"
|
||||||
#include "NoteData.h"
|
#include "NoteData.h"
|
||||||
#include "PlayerNumber.h"
|
#include "PlayerNumber.h"
|
||||||
|
#include <map>
|
||||||
|
|
||||||
class NoteDataWithScoring : public NoteData
|
class NoteDataWithScoring : public NoteData
|
||||||
{
|
{
|
||||||
// maintain this extra data in addition to the NoteData
|
// maintain this extra data in addition to the NoteData
|
||||||
vector<TapNoteScore> m_TapNoteScores[MAX_NOTE_TRACKS];
|
vector<TapNoteScore> m_TapNoteScores[MAX_NOTE_TRACKS];
|
||||||
vector<HoldNoteScore> m_HoldNoteScores;
|
typedef pair<int,int> RowTrack;
|
||||||
|
map<RowTrack, HoldNoteScore> m_HoldNoteScores;
|
||||||
|
|
||||||
/* Offset, in seconds, for each tap grade. Negative numbers mean the note
|
/* Offset, in seconds, for each tap grade. Negative numbers mean the note
|
||||||
* was hit early; positive numbers mean it was hit late. These values are
|
* was hit early; positive numbers mean it was hit late. These values are
|
||||||
@@ -30,7 +32,7 @@ class NoteDataWithScoring : public NoteData
|
|||||||
* 0.0 means this HoldNote is dead
|
* 0.0 means this HoldNote is dead
|
||||||
* When this value hits 0.0 for the first time, m_HoldScore becomes HSS_NG.
|
* When this value hits 0.0 for the first time, m_HoldScore becomes HSS_NG.
|
||||||
* If the life is > 0.0 when the HoldNote ends, then m_HoldScore becomes HSS_OK. */
|
* If the life is > 0.0 when the HoldNote ends, then m_HoldScore becomes HSS_OK. */
|
||||||
vector<float> m_fHoldNoteLife;
|
map<RowTrack, float> m_fHoldNoteLife;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NoteDataWithScoring();
|
NoteDataWithScoring();
|
||||||
@@ -46,10 +48,11 @@ public:
|
|||||||
void SetTapNoteScore(unsigned track, unsigned row, TapNoteScore tns);
|
void SetTapNoteScore(unsigned track, unsigned row, TapNoteScore tns);
|
||||||
float GetTapNoteOffset(unsigned track, unsigned row) const;
|
float GetTapNoteOffset(unsigned track, unsigned row) const;
|
||||||
void SetTapNoteOffset(unsigned track, unsigned row, float offset);
|
void SetTapNoteOffset(unsigned track, unsigned row, float offset);
|
||||||
HoldNoteScore GetHoldNoteScore(unsigned h) const;
|
|
||||||
void SetHoldNoteScore(unsigned h, HoldNoteScore hns);
|
HoldNoteScore GetHoldNoteScore( const HoldNote &hn ) const;
|
||||||
float GetHoldNoteLife(unsigned h) const;
|
void SetHoldNoteScore( const HoldNote &hn, HoldNoteScore hns );
|
||||||
void SetHoldNoteLife(unsigned h, float f);
|
float GetHoldNoteLife( const HoldNote &hn ) const;
|
||||||
|
void SetHoldNoteLife( const HoldNote &hn, float f );
|
||||||
|
|
||||||
bool IsRowCompletelyJudged(unsigned row) const;
|
bool IsRowCompletelyJudged(unsigned row) const;
|
||||||
TapNoteScore MinTapNoteScore(unsigned row) const;
|
TapNoteScore MinTapNoteScore(unsigned row) const;
|
||||||
|
|||||||
@@ -517,8 +517,8 @@ void NoteField::DrawPrimitives()
|
|||||||
for( i=0; i < GetNumHoldNotes(); i++ )
|
for( i=0; i < GetNumHoldNotes(); i++ )
|
||||||
{
|
{
|
||||||
const HoldNote &hn = GetHoldNote(i);
|
const HoldNote &hn = GetHoldNote(i);
|
||||||
const HoldNoteScore hns = GetHoldNoteScore(i);
|
const HoldNoteScore hns = GetHoldNoteScore( hn );
|
||||||
const float fLife = GetHoldNoteLife(i);
|
const float fLife = GetHoldNoteLife( hn );
|
||||||
const bool bIsHoldingNote = (i < int(m_bIsHoldingHoldNote.size()))?
|
const bool bIsHoldingNote = (i < int(m_bIsHoldingHoldNote.size()))?
|
||||||
m_bIsHoldingHoldNote[i]: false;
|
m_bIsHoldingHoldNote[i]: false;
|
||||||
|
|
||||||
|
|||||||
+12
-23
@@ -281,22 +281,25 @@ void PlayerMinus::Update( float fDeltaTime )
|
|||||||
for( int i=0; i < GetNumHoldNotes(); i++ ) // for each HoldNote
|
for( int i=0; i < GetNumHoldNotes(); i++ ) // for each HoldNote
|
||||||
{
|
{
|
||||||
const HoldNote &hn = GetHoldNote(i);
|
const HoldNote &hn = GetHoldNote(i);
|
||||||
HoldNoteScore hns = GetHoldNoteScore(i);
|
HoldNoteScore hns = GetHoldNoteScore(hn);
|
||||||
float fLife = GetHoldNoteLife(i);
|
|
||||||
int iHoldStartIndex = hn.iStartRow;
|
|
||||||
|
|
||||||
m_pNoteField->m_bIsHoldingHoldNote[i] = false; // set host flag so NoteField can do intelligent drawing
|
m_pNoteField->m_bIsHoldingHoldNote[i] = false; // set host flag so NoteField can do intelligent drawing
|
||||||
|
|
||||||
|
|
||||||
if( hns != HNS_NONE ) // if this HoldNote already has a result
|
if( hns != HNS_NONE ) // if this HoldNote already has a result
|
||||||
continue; // we don't need to update the logic for this one
|
continue; // we don't need to update the logic for this one
|
||||||
|
if( iSongRow < hn.iStartRow )
|
||||||
|
continue; // hold hasn't happened yet
|
||||||
|
|
||||||
const StyleInput StyleI( m_PlayerNumber, hn.iTrack );
|
const StyleInput StyleI( m_PlayerNumber, hn.iTrack );
|
||||||
const GameInput GameI = GAMESTATE->GetCurrentStyleDef()->StyleInputToGameInput( StyleI );
|
const GameInput GameI = GAMESTATE->GetCurrentStyleDef()->StyleInputToGameInput( StyleI );
|
||||||
|
|
||||||
// if they got a bad score or haven't stepped on the corresponding tap yet
|
// if they got a bad score or haven't stepped on the corresponding tap yet
|
||||||
const TapNoteScore tns = GetTapNoteScore(hn.iTrack, iHoldStartIndex);
|
const TapNoteScore tns = GetTapNoteScore( hn.iTrack, hn.iStartRow );
|
||||||
const bool bSteppedOnTapNote = tns != TNS_NONE && tns != TNS_MISS; // did they step on the start of this hold?
|
const bool bSteppedOnTapNote = tns != TNS_NONE && tns != TNS_MISS; // did they step on the start of this hold?
|
||||||
|
|
||||||
|
float fLife = GetHoldNoteLife(hn);
|
||||||
|
|
||||||
// If the song beat is in the range of this hold:
|
// If the song beat is in the range of this hold:
|
||||||
if( hn.iStartRow <= iSongRow && iSongRow <= hn.iEndRow )
|
if( hn.iStartRow <= iSongRow && iSongRow <= hn.iEndRow )
|
||||||
{
|
{
|
||||||
@@ -312,12 +315,7 @@ void PlayerMinus::Update( float fDeltaTime )
|
|||||||
if( bSteppedOnTapNote ) // this note is not judged and we stepped on its head
|
if( bSteppedOnTapNote ) // this note is not judged and we stepped on its head
|
||||||
{
|
{
|
||||||
// Move the start of this Hold
|
// Move the start of this Hold
|
||||||
//
|
m_pNoteField->GetHoldNote(i).iStartRow = min( iSongRow, m_pNoteField->GetHoldNote(i).iEndRow );
|
||||||
// IMPORTANT: Every HoldNote::fStartBeat must be at least 1 index less than
|
|
||||||
// its HoldNote::fEndBeat. Otherwise, when HoldNotes are converted to the
|
|
||||||
// 4s representation, it disappears, which causes problems for the way we
|
|
||||||
// store HoldNote life (by index of the hold).
|
|
||||||
m_pNoteField->GetHoldNote(i).iStartRow = min( iSongRow, m_pNoteField->GetHoldNote(i).iEndRow-1 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( bSteppedOnTapNote && bIsHoldingButton )
|
if( bSteppedOnTapNote && bIsHoldingButton )
|
||||||
@@ -368,11 +366,11 @@ void PlayerMinus::Update( float fDeltaTime )
|
|||||||
m_ProTimingDisplay.SetJudgment( ms_error, TNS_MISS );
|
m_ProTimingDisplay.SetJudgment( ms_error, TNS_MISS );
|
||||||
}
|
}
|
||||||
|
|
||||||
m_pNoteField->SetHoldNoteLife(i, fLife); // update the NoteField display
|
m_pNoteField->SetHoldNoteLife(hn, fLife); // update the NoteField display
|
||||||
m_pNoteField->SetHoldNoteScore(i, hns); // update the NoteField display
|
m_pNoteField->SetHoldNoteScore(hn, hns); // update the NoteField display
|
||||||
|
|
||||||
SetHoldNoteLife(i, fLife);
|
SetHoldNoteLife(hn, fLife);
|
||||||
SetHoldNoteScore(i, hns);
|
SetHoldNoteScore(hn, hns);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Why was this originally "BeatToNoteRowNotRounded"? It should be rounded. -Chris
|
// Why was this originally "BeatToNoteRowNotRounded"? It should be rounded. -Chris
|
||||||
@@ -398,15 +396,6 @@ void PlayerMinus::Update( float fDeltaTime )
|
|||||||
po.m_sNoteSkin = "";
|
po.m_sNoteSkin = "";
|
||||||
po.FromString( mod.sModifier );
|
po.FromString( mod.sModifier );
|
||||||
|
|
||||||
/* Note that runtime effects like these currently must not change hold
|
|
||||||
* notes. CopyRange below converts through 4s, which means the hold note
|
|
||||||
* array will be reconstructed; if hold notes end up in a different order,
|
|
||||||
* they won't align with this->m_HoldNoteScores. */
|
|
||||||
if( po.m_bTransforms[PlayerOptions::TRANSFORM_NOHOLDS] )
|
|
||||||
RageException::Throw("Can't use NoHolds as a battle attack");
|
|
||||||
if( po.m_bTransforms[PlayerOptions::TRANSFORM_NOMINES] )
|
|
||||||
RageException::Throw("Can't use NoMines as a battle attack");
|
|
||||||
|
|
||||||
float fStartBeat, fEndBeat;
|
float fStartBeat, fEndBeat;
|
||||||
mod.GetAttackBeats( GAMESTATE->m_pCurSong, m_PlayerNumber, fStartBeat, fEndBeat );
|
mod.GetAttackBeats( GAMESTATE->m_pCurSong, m_PlayerNumber, fStartBeat, fEndBeat );
|
||||||
fEndBeat = min( fEndBeat, GetMaxBeat() );
|
fEndBeat = min( fEndBeat, GetMaxBeat() );
|
||||||
|
|||||||
Reference in New Issue
Block a user