add fret/strum

add PlayerInitCommand
This commit is contained in:
Chris Danford
2006-10-27 10:19:08 +00:00
parent a1dac5f2fc
commit 17ca30a047
4 changed files with 133 additions and 25 deletions
+87 -18
View File
@@ -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 )
+7
View File
@@ -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;
+38 -7
View File
@@ -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;
}
}
}
}
+1
View File
@@ -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;