add fret/strum
add PlayerInitCommand
This commit is contained in:
+87
-18
@@ -311,6 +311,10 @@ void Player::Init(
|
||||
m_fNoteFieldHeight = GRAY_ARROWS_Y_REVERSE-GRAY_ARROWS_Y_STANDARD;
|
||||
if( m_pNoteField )
|
||||
m_pNoteField->Init( m_pPlayerState, m_fNoteFieldHeight );
|
||||
|
||||
m_vbFretIsDown.resize( GAMESTATE->GetCurrentStyle()->m_iColsPerPlayer );
|
||||
FOREACH( bool, m_vbFretIsDown, b )
|
||||
*b = false;
|
||||
}
|
||||
|
||||
void Player::Load()
|
||||
@@ -918,14 +922,74 @@ int Player::GetClosestNote( int col, int iNoteRow, int iMaxRowsAhead, int iMaxRo
|
||||
return iNextIndex;
|
||||
}
|
||||
|
||||
void Player::Step( int col, int row, const RageTimer &tm, bool bHeld, bool bRelease )
|
||||
int Player::GetClosestNonEmptyRowDirectional( int iStartRow, int iEndRow, bool bAllowGraded, bool bForward ) const
|
||||
{
|
||||
if( bForward )
|
||||
{
|
||||
NoteData::all_tracks_iterator iter = m_NoteData.GetTapNoteRangeAllTracks( iStartRow, iEndRow );
|
||||
|
||||
while( !iter.IsAtEnd() )
|
||||
{
|
||||
//NoteDataWithScoring::IsRowCompletelyJudged(m_NoteData, iRowOfClosestNonEmptyRow, pn) )
|
||||
return iter.Row();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NoteData::all_tracks_reverse_iterator iter = m_NoteData.GetTapNoteRangeAllTracksReverse( iStartRow, iEndRow );
|
||||
|
||||
while( !iter.IsAtEnd() )
|
||||
{
|
||||
//NoteDataWithScoring::IsRowCompletelyJudged(m_NoteData, iRowOfClosestNonEmptyRow, pn) )
|
||||
return iter.Row();
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Find the closest note to fBeat. */
|
||||
int Player::GetClosestNonEmptyRow( int iNoteRow, int iMaxRowsAhead, int iMaxRowsBehind, bool bAllowGraded ) const
|
||||
{
|
||||
// Start at iIndexStartLookingAt and search outward.
|
||||
int iNextRow = GetClosestNonEmptyRowDirectional( iNoteRow, iNoteRow+iMaxRowsAhead, bAllowGraded, true );
|
||||
int iPrevRow = GetClosestNonEmptyRowDirectional( iNoteRow-iMaxRowsBehind, iNoteRow, bAllowGraded, false );
|
||||
|
||||
if( iNextRow == -1 && iPrevRow == -1 )
|
||||
return -1;
|
||||
if( iNextRow == -1 )
|
||||
return iPrevRow;
|
||||
if( iPrevRow == -1 )
|
||||
return iNextRow;
|
||||
|
||||
/* Figure out which row is closer. */
|
||||
if( abs(iNoteRow-iNextRow) > abs(iNoteRow-iPrevRow) )
|
||||
return iPrevRow;
|
||||
else
|
||||
return iNextRow;
|
||||
}
|
||||
|
||||
bool Player::IsOniDead() const
|
||||
{
|
||||
// If we're playing on oni and we've died, do nothing.
|
||||
if( GAMESTATE->m_SongOptions.GetCurrent().m_LifeType == SongOptions::LIFE_BATTERY && m_pPlayerStageStats && m_pPlayerStageStats->bFailed )
|
||||
return GAMESTATE->m_SongOptions.GetCurrent().m_LifeType == SongOptions::LIFE_BATTERY && m_pPlayerStageStats && m_pPlayerStageStats->bFailed;
|
||||
}
|
||||
|
||||
void Player::Fret( int col, int row, const RageTimer &tm, bool bHeld, bool bRelease )
|
||||
{
|
||||
if( IsOniDead() )
|
||||
return;
|
||||
|
||||
DEBUG_ASSERT_M( col >= 0 && col <= m_NoteData.GetNumTracks(), ssprintf("%i, %i", col, m_NoteData.GetNumTracks()) );
|
||||
|
||||
m_vbFretIsDown[ col ] = !bRelease;
|
||||
}
|
||||
|
||||
void Player::Step( int col, int row, const RageTimer &tm, bool bHeld, bool bRelease )
|
||||
{
|
||||
if( IsOniDead() )
|
||||
return;
|
||||
|
||||
|
||||
const float fPositionSeconds = GAMESTATE->m_fMusicSeconds - tm.Ago();
|
||||
const float fSongBeat = GAMESTATE->m_pCurSong ? GAMESTATE->m_pCurSong->GetBeatFromElapsedTime( fPositionSeconds ) : GAMESTATE->m_fSongBeat;
|
||||
@@ -1047,17 +1111,17 @@ void Player::Step( int col, int row, const RageTimer &tm, bool bHeld, bool bRele
|
||||
* Either option would fundamentally change the grading of two quick notes "jack hammers." Hmm.
|
||||
*/
|
||||
const int iStepSearchRows = BeatToNoteRow( StepSearchDistance * GAMESTATE->m_fCurBPS * GAMESTATE->m_SongOptions.GetCurrent().m_fMusicRate );
|
||||
int iIndexOverlappingNote = row == -1 ? GetClosestNote( col, BeatToNoteRow(fSongBeat), iStepSearchRows, iStepSearchRows, false ) : row;
|
||||
int iRowOfOverlappingNote = row == -1 ? GetClosestNote( col, BeatToNoteRow(fSongBeat), iStepSearchRows, iStepSearchRows, false ) : row;
|
||||
|
||||
// calculate TapNoteScore
|
||||
TapNoteScore score = TNS_None;
|
||||
|
||||
if( iIndexOverlappingNote != -1 )
|
||||
if( iRowOfOverlappingNote != -1 )
|
||||
{
|
||||
// compute the score for this hit
|
||||
float fNoteOffset = 0.0f;
|
||||
// we need this later if we are autosyncing
|
||||
const float fStepBeat = NoteRowToBeat( iIndexOverlappingNote );
|
||||
const float fStepBeat = NoteRowToBeat( iRowOfOverlappingNote );
|
||||
const float fStepSeconds = GAMESTATE->m_pCurSong->GetElapsedTimeFromBeat(fStepBeat);
|
||||
|
||||
if( row == -1 )
|
||||
@@ -1081,7 +1145,7 @@ void Player::Step( int col, int row, const RageTimer &tm, bool bHeld, bool bRele
|
||||
|
||||
const float fSecondsFromExact = fabsf( fNoteOffset );
|
||||
|
||||
NoteData::iterator iter = m_NoteData.FindTapNote( col, iIndexOverlappingNote );
|
||||
NoteData::iterator iter = m_NoteData.FindTapNote( col, iRowOfOverlappingNote );
|
||||
|
||||
DEBUG_ASSERT( iter!= m_NoteData.end(col) );
|
||||
TapNote &tn = iter->second;
|
||||
@@ -1140,13 +1204,13 @@ void Player::Step( int col, int row, const RageTimer &tm, bool bHeld, bool bRele
|
||||
// there are are no mines to the left of us.
|
||||
for( int t=0; t<col; t++ )
|
||||
{
|
||||
if( m_NoteData.GetTapNote(t,iIndexOverlappingNote).type == TapNote::mine ) // there's a mine to the left of us
|
||||
if( m_NoteData.GetTapNote(t,iRowOfOverlappingNote).type == TapNote::mine ) // there's a mine to the left of us
|
||||
return; // avoid
|
||||
}
|
||||
|
||||
// The CPU hits a lot of mines. Make it less likely to hit
|
||||
// mines that don't have a tap note on the same row.
|
||||
bool bTapsOnRow = m_NoteData.IsThereATapOrHoldHeadAtRow( iIndexOverlappingNote );
|
||||
bool bTapsOnRow = m_NoteData.IsThereATapOrHoldHeadAtRow( iRowOfOverlappingNote );
|
||||
TapNoteScore get_to_avoid = bTapsOnRow ? TNS_W3 : TNS_W4;
|
||||
|
||||
if( score >= get_to_avoid )
|
||||
@@ -1201,9 +1265,9 @@ void Player::Step( int col, int row, const RageTimer &tm, bool bHeld, bool bRele
|
||||
// remove all TapAttacks on this row
|
||||
for( int t=0; t<m_NoteData.GetNumTracks(); t++ )
|
||||
{
|
||||
const TapNote &tn = m_NoteData.GetTapNote( t, iIndexOverlappingNote );
|
||||
const TapNote &tn = m_NoteData.GetTapNote( t, iRowOfOverlappingNote );
|
||||
if( tn.type == TapNote::attack )
|
||||
HideNote( t, iIndexOverlappingNote );
|
||||
HideNote( t, iRowOfOverlappingNote );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1232,12 +1296,12 @@ void Player::Step( int col, int row, const RageTimer &tm, bool bHeld, bool bRele
|
||||
if( m_pNoteField )
|
||||
m_pNoteField->DidTapNote( col, score, bBright );
|
||||
if( score >= TNS_W3 || bBlind )
|
||||
HideNote( col, iIndexOverlappingNote );
|
||||
HideNote( col, iRowOfOverlappingNote );
|
||||
}
|
||||
}
|
||||
else if( NoteDataWithScoring::IsRowCompletelyJudged(m_NoteData, iIndexOverlappingNote, pn) )
|
||||
else if( NoteDataWithScoring::IsRowCompletelyJudged(m_NoteData, iRowOfOverlappingNote, pn) )
|
||||
{
|
||||
FlashGhostRow( iIndexOverlappingNote, pn );
|
||||
FlashGhostRow( iRowOfOverlappingNote, pn );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1245,18 +1309,18 @@ void Player::Step( int col, int row, const RageTimer &tm, bool bHeld, bool bRele
|
||||
{
|
||||
/* Search for keyed sounds separately. If we can't find a nearby note, search
|
||||
* backwards indefinitely, and ignore grading. */
|
||||
/* XXX: This isn't quite right. As per the above XXX for iIndexOverlappingNote, if iIndexOverlappingNote
|
||||
/* XXX: This isn't quite right. As per the above XXX for iRowOfOverlappingNote, if iRowOfOverlappingNote
|
||||
* is set to a previous note, the keysound could have changed and this would cause the wrong one to play,
|
||||
* in essence playing two sounds in the opposite order. Maybe this should always perform the search. Still,
|
||||
* even that doesn't seem quite right since it would then play the same (new) keysound twice which would
|
||||
* sound wrong even though the notes were judged as being correct, above. Fixing the above problem would
|
||||
* fix this one as well. */
|
||||
if( iIndexOverlappingNote == -1 )
|
||||
iIndexOverlappingNote = GetClosestNote( col, BeatToNoteRow(fSongBeat),
|
||||
if( iRowOfOverlappingNote == -1 )
|
||||
iRowOfOverlappingNote = GetClosestNote( col, BeatToNoteRow(fSongBeat),
|
||||
iStepSearchRows, MAX_NOTE_ROW, true );
|
||||
if( iIndexOverlappingNote != -1 )
|
||||
if( iRowOfOverlappingNote != -1 )
|
||||
{
|
||||
const TapNote &tn = m_NoteData.GetTapNote( col, iIndexOverlappingNote );
|
||||
const TapNote &tn = m_NoteData.GetTapNote( col, iRowOfOverlappingNote );
|
||||
if( tn.iKeysoundIndex >= 0 && tn.iKeysoundIndex < (int) m_vKeysounds.size() )
|
||||
m_vKeysounds[tn.iKeysoundIndex].Play();
|
||||
}
|
||||
@@ -1270,6 +1334,11 @@ void Player::Step( int col, int row, const RageTimer &tm, bool bHeld, bool bRele
|
||||
}
|
||||
}
|
||||
|
||||
void Player::Strum( int col, int row, const RageTimer &tm, bool bHeld, bool bRelease )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static bool Unjudged( const TapNote &tn )
|
||||
{
|
||||
if( tn.result.tns != TNS_None )
|
||||
|
||||
@@ -113,6 +113,9 @@ public:
|
||||
void Load();
|
||||
void CrossedRow( int iNoteRow, const RageTimer &now );
|
||||
void CrossedMineRow( int iNoteRow, const RageTimer &now );
|
||||
bool IsOniDead() const;
|
||||
void Fret( int col, int row, const RageTimer &tm, bool bHeld, bool bRelease );
|
||||
void Strum( int col, int row, const RageTimer &tm, bool bHeld, bool bRelease );
|
||||
void Step( int col, int row, const RageTimer &tm, bool bHeld, bool bRelease );
|
||||
void RandomizeNotes( int iNoteRow );
|
||||
void FadeToFail();
|
||||
@@ -138,6 +141,8 @@ protected:
|
||||
|
||||
int GetClosestNoteDirectional( int col, int iStartRow, int iMaxRowsAhead, bool bAllowGraded, bool bForward ) const;
|
||||
int GetClosestNote( int col, int iNoteRow, int iMaxRowsAhead, int iMaxRowsBehind, bool bAllowGraded ) const;
|
||||
int GetClosestNonEmptyRowDirectional( int iStartRow, int iMaxRowsAhead, bool bAllowGraded, bool bForward ) const;
|
||||
int GetClosestNonEmptyRow( int iNoteRow, int iMaxRowsAhead, int iMaxRowsBehind, bool bAllowGraded ) const;
|
||||
|
||||
bool IsPlayingBeginner() const;
|
||||
inline void HideNote( int col, int row )
|
||||
@@ -186,6 +191,8 @@ protected:
|
||||
RageSound m_soundAttackLaunch;
|
||||
RageSound m_soundAttackEnding;
|
||||
|
||||
vector<bool> m_vbFretIsDown;
|
||||
|
||||
vector<RageSound> m_vKeysounds;
|
||||
|
||||
RString m_sMessageToSendOnStep;
|
||||
|
||||
@@ -329,6 +329,7 @@ ScreenGameplay::ScreenGameplay()
|
||||
void ScreenGameplay::Init()
|
||||
{
|
||||
PLAYER_TYPE.Load( m_sName, "PlayerType" );
|
||||
PLAYER_INIT_COMMAND.Load( m_sName, "PlayerInitCommand" );
|
||||
GIVE_UP_START_TEXT.Load( m_sName, "GiveUpStartText" );
|
||||
GIVE_UP_BACK_TEXT.Load( m_sName, "GiveUpBackText" );
|
||||
GIVE_UP_ABORTED_TEXT.Load( m_sName, "GiveUpAbortedText" );
|
||||
@@ -460,7 +461,8 @@ void ScreenGameplay::Init()
|
||||
if( Center1Player() )
|
||||
fPlayerX = SCREEN_CENTER_X;
|
||||
|
||||
pi->m_pPlayer->SetXY( fPlayerX, SCREEN_CENTER_Y );
|
||||
pi->m_pPlayer->SetX( fPlayerX );
|
||||
pi->m_pPlayer->RunCommands( PLAYER_INIT_COMMAND );
|
||||
this->AddChild( pi->m_pPlayer );
|
||||
}
|
||||
|
||||
@@ -2139,7 +2141,13 @@ void ScreenGameplay::Input( const InputEventPlus &input )
|
||||
|
||||
/* Only handle MENU_BUTTON_BACK as a regular BACK button if BACK_GIVES_UP is
|
||||
* disabled. */
|
||||
if( input.MenuI == MENU_BUTTON_BACK && !BACK_GIVES_UP )
|
||||
bool bHoldingBack = false;
|
||||
if( GAMESTATE->GetCurrentStyle()->GameInputToColumn(input.GameI) == Column_Invalid )
|
||||
{
|
||||
bHoldingBack |= input.MenuI == MENU_BUTTON_BACK && !BACK_GIVES_UP;
|
||||
}
|
||||
|
||||
if( bHoldingBack )
|
||||
{
|
||||
if( ((!PREFSMAN->m_bDelayedBack && input.type==IET_FIRST_PRESS) ||
|
||||
(input.DeviceI.device==DEVICE_KEYBOARD && input.type==IET_REPEAT) ||
|
||||
@@ -2171,10 +2179,19 @@ void ScreenGameplay::Input( const InputEventPlus &input )
|
||||
bool bRelease = input.type == IET_RELEASE;
|
||||
const int iCol = GAMESTATE->GetCurrentStyle()->GameInputToColumn( input.GameI );
|
||||
|
||||
// Don't pass on any inputs to Player that aren't a press or a release.
|
||||
switch( input.type )
|
||||
{
|
||||
case IET_FIRST_PRESS:
|
||||
case IET_RELEASE:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if( GAMESTATE->m_bMultiplayer )
|
||||
{
|
||||
if( input.mp != MultiPlayer_Invalid &&
|
||||
input.type==IET_FIRST_PRESS &&
|
||||
iCol != Column_Invalid &&
|
||||
GAMESTATE->IsMultiPlayerEnabled(input.mp) )
|
||||
{
|
||||
@@ -2186,16 +2203,30 @@ void ScreenGameplay::Input( const InputEventPlus &input )
|
||||
//
|
||||
// handle a step or battle item activate
|
||||
//
|
||||
if( input.type==IET_FIRST_PRESS &&
|
||||
iCol != Column_Invalid &&
|
||||
GAMESTATE->IsHumanPlayer( input.pn ) )
|
||||
if( GAMESTATE->IsHumanPlayer( input.pn ) )
|
||||
{
|
||||
AbortGiveUp( true );
|
||||
|
||||
if( PREFSMAN->m_AutoPlay == PC_HUMAN )
|
||||
{
|
||||
PlayerInfo& pi = GetPlayerInfoForInput( input );
|
||||
pi.m_pPlayer->Step( iCol, -1, input.DeviceI.ts, false, bRelease );
|
||||
|
||||
ASSERT( input.GameI.IsValid() );
|
||||
|
||||
GameButtonType gbt = INPUTMAPPER->GetInputScheme()->m_GameButtonInfo[input.GameI.button].m_gbt;
|
||||
switch( gbt )
|
||||
{
|
||||
DEFAULT_FAIL( gbt );
|
||||
case GameButtonType_Step:
|
||||
pi.m_pPlayer->Step( iCol, -1, input.DeviceI.ts, false, bRelease );
|
||||
break;
|
||||
case GameButtonType_Fret:
|
||||
pi.m_pPlayer->Fret( iCol, -1, input.DeviceI.ts, false, bRelease );
|
||||
break;
|
||||
case GameButtonType_Strum:
|
||||
pi.m_pPlayer->Strum( iCol, -1, input.DeviceI.ts, false, bRelease );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,6 +124,7 @@ protected:
|
||||
virtual bool UseSongBackgroundAndForeground() const { return true; }
|
||||
|
||||
ThemeMetric<RString> PLAYER_TYPE;
|
||||
ThemeMetric<apActorCommands> PLAYER_INIT_COMMAND;
|
||||
LocalizedString GIVE_UP_START_TEXT;
|
||||
LocalizedString GIVE_UP_BACK_TEXT;
|
||||
LocalizedString GIVE_UP_ABORTED_TEXT;
|
||||
|
||||
Reference in New Issue
Block a user