diff --git a/stepmania/src/ArrowEffects.h b/stepmania/src/ArrowEffects.h index 05b6589382..c020a8c74b 100644 --- a/stepmania/src/ArrowEffects.h +++ b/stepmania/src/ArrowEffects.h @@ -20,30 +20,30 @@ // fYOffset is a vertical position in pixels relative to the center. // (positive if has not yet been stepped on, negative if has already passed). // The ArrowEffect is applied in this stage. -float ArrowGetYOffset( const PlayerOptions& po, float fStepIndex, float fSongBeat ); +float ArrowGetYOffset( const PlayerNumber pn, float fStepIndex ); // fXPos is a horizontal position in pixels relative to the center of the field. // This depends on the column of the arrow and possibly the Arrow effect and // fYOffset (in the case of EFFECT_DRUNK). -float ArrowGetXPos( const PlayerOptions& po, int iCol, float fYOffset, float fSongBeat ); +float ArrowGetXPos( const PlayerNumber pn, int iCol, float fYOffset ); // fRotation is Z rotation of an arrow. This will depend on the column of // the arrow and possibly the Arrow effect and the fYOffset (in the case of // EFFECT_DIZZY). -float ArrowGetRotation( const PlayerOptions& po, int iCol, float fYOffset ); +float ArrowGetRotation( const PlayerNumber pn, int iCol, float fYOffset ); // fYPos is the position of the note in pixels relative to the center. // (positive if has not yet been stepped on, negative if has already passed). // This value is fYOffset with bReverseScroll and fScrollSpeed factored in. -float ArrowGetYPos( const PlayerOptions& po, float fYOffset ); +float ArrowGetYPos( const PlayerNumber pn, float fYOffset ); // fAlpha is the transparency of the arrow. It depends on fYPos and the // ArrowAppearance. -float ArrowGetAlpha( const PlayerOptions& po, float fYPos ); +float ArrowGetAlpha( const PlayerNumber pn, float fYPos ); #endif diff --git a/stepmania/src/Course.cpp b/stepmania/src/Course.cpp index a6b8da1a55..34ae62c51c 100644 --- a/stepmania/src/Course.cpp +++ b/stepmania/src/Course.cpp @@ -19,6 +19,8 @@ #include "RageException.h" #include "RageLog.h" #include "MsdFile.h" +#include "PlayerOptions.h" +#include "SongOptions.h" void Course::LoadFromCRSFile( CString sPath, CArray &apSongs ) @@ -161,6 +163,19 @@ D3DXCOLOR Course::GetColor() return D3DXCOLOR(0,1,0,1); // green } +void Course::GetPlayerOptions( PlayerOptions* pPO_out ) +{ + *pPO_out = PlayerOptions(); +} + +void Course::GetSongOptions( SongOptions* pSO_out ) +{ + *pSO_out = SongOptions(); + pSO_out->m_LifeType = (m_iLives==-1) ? SongOptions::LIFE_BAR : SongOptions::LIFE_BATTERY; + if( m_iLives != -1 ) + pSO_out->m_iBatteryLives = m_iLives; +} + // // Sorting stuff // diff --git a/stepmania/src/Course.h b/stepmania/src/Course.h index 5635a93ec5..ef398c9bab 100644 --- a/stepmania/src/Course.h +++ b/stepmania/src/Course.h @@ -11,7 +11,8 @@ */ #include "GameConstantsAndTypes.h" -#include "PlayerOptions.h" +struct PlayerOptions; +struct SongOptions; class Song; struct Notes; @@ -40,8 +41,9 @@ public: bool m_bRepeat; // repeat after last song? int m_iLives; // -1 means use bar life meter CString m_sModifiers; // contains player options and song options -// PlayerOptions m_PlayerOptions; + void GetPlayerOptions( PlayerOptions* pPO_out ); + void GetSongOptions( SongOptions* pSO_out); void LoadFromCRSFile( CString sPath, CArray &apSongs ); void CreateFromGroupAndDifficultyClass( CString sGroupName, DifficultyClass dc, CArray &apSongsInGroup ); diff --git a/stepmania/src/GameConstantsAndTypes.h b/stepmania/src/GameConstantsAndTypes.h index c769f66124..c746e063e3 100644 --- a/stepmania/src/GameConstantsAndTypes.h +++ b/stepmania/src/GameConstantsAndTypes.h @@ -413,14 +413,6 @@ inline NotesType StyleToNotesType ( Style s ) */ -/////////////////////////// -// Options stuff -/////////////////////////// - - - - - /////////////////////////// // Scoring stuff @@ -432,7 +424,8 @@ enum TapNoteScore { TNS_BOO, TNS_GOOD, TNS_GREAT, - TNS_PERFECT, + TNS_PERFECT, + NUM_TAP_NOTE_SCORES }; inline int TapNoteScoreToDancePoints( TapNoteScore tns ) @@ -460,7 +453,8 @@ enum HoldNoteScore { HNS_NONE, // this HoldNote has not been scored yet HNS_OK, // the HoldNote has passed and was successfully held all the way through - HNS_NG // the HoldNote has passed and they missed it + HNS_NG, // the HoldNote has passed and they missed it + NUM_HOLD_NOTE_SCORES }; diff --git a/stepmania/src/GameState.h b/stepmania/src/GameState.h index c3688517d5..c4f1c21b70 100644 --- a/stepmania/src/GameState.h +++ b/stepmania/src/GameState.h @@ -11,7 +11,6 @@ */ #include "GameConstantsAndTypes.h" -#include "GameplayStatistics.h" #include "PlayerOptions.h" #include "SongOptions.h" @@ -30,23 +29,9 @@ public: ~GameState(); void Reset(); - Song* m_pCurSong; - Notes* m_pCurNotes[NUM_PLAYERS]; - Course* m_pCurCourse; - int m_iCoursePossibleDancePoints; - - // Info used during gameplay - // Let lots of classes access the music beat here so we don't have to pass it around everywhere - float m_fMusicSeconds; - float m_fMusicBeat; - float m_fCurBPS; - bool m_bFreeze; - - CArray m_aGameplayStatistics; // for passing from Dancing to Results - GameplayStatistics& GetLatestGameplayStatistics(); - - - + // + // Main State Info + // Game m_CurGame; Style m_CurStyle; PlayerNumber m_MasterPlayerNumber; @@ -57,13 +42,13 @@ public: bool IsPlayerEnabled( PlayerNumber pn ); bool IsPlayerEnabled( int p ) { return IsPlayerEnabled( (PlayerNumber)p ); }; // for those too lasy to cast all those p's to a PlayerNumber - CString m_sLoadingMessage; CString m_sPreferredGroup; DifficultyClass m_PreferredDifficultyClass[NUM_PLAYERS]; SongSortOrder m_SongSortOrder; // used by MusicWheel PlayMode m_PlayMode; - int m_iCurrentStageIndex; // starts at 0, and is incremented with each Stage Clear + bool m_bEditing; + int m_iCurrentStageIndex; // incremented after a song ends int GetStageIndex(); bool IsFinalStage(); @@ -72,6 +57,64 @@ public: CString GetStageText(); D3DXCOLOR GetStageColor(); + // + // State Info used during gameplay + // + Song* m_pCurSong; + Notes* m_pCurNotes[NUM_PLAYERS]; + Course* m_pCurCourse; + + + // + // Let a lot of classes access this info here so the don't have to keep their own copies + float m_fMusicSeconds; // time into the current song + float m_fSongBeat; + float m_fCurBPS; + bool m_bFreeze; // in the middle of a freeze + + void ResetMusicStatistics(); // Clear the values above + + CArray m_apSongsPlayed; // an array of completed songs. + // This is useful for the final evaluation screen, + // and used to calculate the time into a course + float GetElapsedSeconds(); // Arcade: time into current song. Oni/Endless: time into current course + + float m_fSecondsBeforeFail[NUM_PLAYERS];// -1 means not yet failed + // In Arcade, is the time into the current stage before failing. + // In Oni and Endless this is the time into the current course before failing + int m_iStagesIntoCourse[NUM_PLAYERS]; // In Arcade, this value is meaningless. + // In Oni and Endless, this is the number of songs played before failing. + bool m_bUsedAutoPlayer; // Used autoplayer at any time during any stage/course/song + + float GetPlayerSurviveTime( PlayerNumber p ); + + // + // Statistics for: Arcade: for the current stage. Oni/Endless: for current course + // + int m_iPossibleDancePoints[NUM_PLAYERS]; + int m_iActualDancePoints[NUM_PLAYERS]; // In Endless, possible dance points is -1. + int m_TapNoteScores[NUM_PLAYERS][NUM_TAP_NOTE_SCORES]; + int m_HoldNoteScores[NUM_PLAYERS][NUM_HOLD_NOTE_SCORES]; + int m_iMaxCombo[NUM_PLAYERS]; + float m_fScore[NUM_PLAYERS]; + float m_fRadarPossible[NUM_PLAYERS][NUM_RADAR_VALUES]; // filled in by ScreenGameplay on end of notes + float m_fRadarActual[NUM_PLAYERS][NUM_RADAR_VALUES]; // filled in by ScreenGameplay on end of notes + + void ResetStageStatistics(); // Clear the values above + void AccumulateStageStatistics(); // Accumulate values above into the values below + + // Only used in final evaluation screen in play mode Arcade. + // Before being displayed, these values should be normalized by dividing by number of stages + int m_iAccumPossibleDancePoints[NUM_PLAYERS]; + int m_iAccumActualDancePoints[NUM_PLAYERS]; // In Endless, possible dance points is -1. + int m_AccumTapNoteScores[NUM_PLAYERS][NUM_TAP_NOTE_SCORES]; + int m_AccumHoldNoteScores[NUM_PLAYERS][NUM_HOLD_NOTE_SCORES]; + int m_iAccumMaxCombo[NUM_PLAYERS]; + float m_fAccumScore[NUM_PLAYERS]; + float m_fAccumRadarPossible[NUM_PLAYERS][NUM_RADAR_VALUES]; + float m_fAccumRadarActual[NUM_PLAYERS][NUM_RADAR_VALUES]; + + PlayerOptions m_PlayerOptions[NUM_PLAYERS]; SongOptions m_SongOptions; diff --git a/stepmania/src/GhostArrow.cpp b/stepmania/src/GhostArrow.cpp index 789b29fc0c..d4d4815909 100644 --- a/stepmania/src/GhostArrow.cpp +++ b/stepmania/src/GhostArrow.cpp @@ -26,11 +26,6 @@ void GhostArrow::Update( float fDeltaTime ) Sprite::Update( fDeltaTime ); } -void GhostArrow::SetBeat( const float fSongBeat ) -{ - //SetState( fmodf(fSongBeat,1)<0.25 ? 1 : 0 ); -} - void GhostArrow::Step( TapNoteScore score ) { switch( score ) @@ -47,5 +42,4 @@ void GhostArrow::Step( TapNoteScore score ) D3DXCOLOR colorTween = GetDiffuseColor(); colorTween.a = 0; SetTweenDiffuseColor( colorTween ); - } diff --git a/stepmania/src/GhostArrow.h b/stepmania/src/GhostArrow.h index fb29e88e64..b990116412 100644 --- a/stepmania/src/GhostArrow.h +++ b/stepmania/src/GhostArrow.h @@ -22,9 +22,6 @@ public: virtual void Update( float fDeltaTime ); - void SetBeat( const float fSongBeat ); void Step( TapNoteScore score ); - - float m_fVisibilityCountdown; }; diff --git a/stepmania/src/GhostArrowBright.cpp b/stepmania/src/GhostArrowBright.cpp index cc218f3344..9cc262c01c 100644 --- a/stepmania/src/GhostArrowBright.cpp +++ b/stepmania/src/GhostArrowBright.cpp @@ -1,8 +1,15 @@ #include "stdafx.h" -// -// GhostArrowBright.cpp: implementation of the GhostArrowBright class. -// -////////////////////////////////////////////////////////////////////// +/* +----------------------------------------------------------------------------- + Class: GhostArrowBright + + Desc: See header. + + Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved. + Ben Nordstrom + Chris Danford +----------------------------------------------------------------------------- +*/ #include "GhostArrowBright.h" #include "PrefsManager.h" @@ -11,10 +18,6 @@ const float GRAY_ARROW_TWEEN_TIME = 0.5f; -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// - GhostArrowBright::GhostArrowBright() { // Load( THEME->GetPathTo(GRAPHIC_BRIGHT_GHOST_ARROW) ); @@ -22,9 +25,9 @@ GhostArrowBright::GhostArrowBright() TurnShadowOff(); } -void GhostArrowBright::SetBeat( const float fSongBeat ) +void GhostArrowBright::Update( float fDeltaTime ) { - //SetState( fmodf(fSongBeat,1)<0.25 ? 1 : 0 ); + Sprite::Update( fDeltaTime ); } void GhostArrowBright::Step( TapNoteScore score ) @@ -44,5 +47,4 @@ void GhostArrowBright::Step( TapNoteScore score ) D3DXCOLOR colorTween = GetDiffuseColor(); colorTween.a = 0; SetTweenDiffuseColor( colorTween ); - } diff --git a/stepmania/src/GhostArrowBright.h b/stepmania/src/GhostArrowBright.h index 3988f53a79..463cb39617 100644 --- a/stepmania/src/GhostArrowBright.h +++ b/stepmania/src/GhostArrowBright.h @@ -1,33 +1,28 @@ +#pragma once /* ----------------------------------------------------------------------------- - File: GhostArrowBright.h + Class: GhostArrowBright - Desc: Class used to represent a color arrow on the screen. + Desc: Ghost arrow used when over 100 combo. - Copyright (c) 2001 Ben Norstrom. All rights reserved. + Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved. + Ben Nordstrom + Chris Danford ----------------------------------------------------------------------------- */ - -class GhostArrowBright; - -#ifndef _GhostArrowBright_H_ -#define _GhostArrowBright_H_ - - #include "Sprite.h" -#include "Notes.h" - +#include "GameConstantsAndTypes.h" class GhostArrowBright : public Sprite { public: GhostArrowBright(); - void SetBeat( const float fSongBeat ); + virtual void Update( float fDeltaTime ); + void Step( TapNoteScore score ); - float m_fVisibilityCountdown; -}; +protected: -#endif +}; diff --git a/stepmania/src/GhostArrowRow.cpp b/stepmania/src/GhostArrowRow.cpp index e03f47d3b3..7693d12b02 100644 --- a/stepmania/src/GhostArrowRow.cpp +++ b/stepmania/src/GhostArrowRow.cpp @@ -25,11 +25,12 @@ GhostArrowRow::GhostArrowRow() m_iNumCols = 0; } -void GhostArrowRow::Load( PlayerNumber pn, StyleDef* pStyleDef, PlayerOptions po ) +void GhostArrowRow::Load( PlayerNumber pn ) { - m_PlayerOptions = po; + m_PlayerNumber = pn; GameDef* pGameDef = GAMESTATE->GetCurrentGameDef(); + StyleDef* pStyleDef = GAMESTATE->GetCurrentStyleDef(); m_iNumCols = pStyleDef->m_iColsPerPlayer; @@ -47,19 +48,13 @@ void GhostArrowRow::Load( PlayerNumber pn, StyleDef* pStyleDef, PlayerOptions po } -void GhostArrowRow::Update( float fDeltaTime, float fSongBeat ) +void GhostArrowRow::Update( float fDeltaTime ) { - m_fSongBeat = fSongBeat; - for( int c=0; cm_fSongBeat,1) * Sprite::GetNumStates() ); if( iNewState < 0 ) iNewState += Sprite::GetNumStates(); SetState( iNewState ); diff --git a/stepmania/src/GrayArrow.h b/stepmania/src/GrayArrow.h index 8a3e907b5a..9cb39f5a39 100644 --- a/stepmania/src/GrayArrow.h +++ b/stepmania/src/GrayArrow.h @@ -23,7 +23,7 @@ class GrayArrow : public Sprite public: GrayArrow(); - virtual void SetBeat( const float fSongBeat ); + virtual void Update( float fDeltaTime ); void Step(); }; diff --git a/stepmania/src/GrayArrowRow.cpp b/stepmania/src/GrayArrowRow.cpp index a24604ba45..9251718d8c 100644 --- a/stepmania/src/GrayArrowRow.cpp +++ b/stepmania/src/GrayArrowRow.cpp @@ -26,11 +26,12 @@ GrayArrowRow::GrayArrowRow() m_iNumCols = 0; } -void GrayArrowRow::Load( PlayerNumber pn, StyleDef* pStyleDef, PlayerOptions po ) +void GrayArrowRow::Load( PlayerNumber pn ) { - m_PlayerOptions = po; + m_PlayerNumber = pn; GameDef* pGameDef = GAMESTATE->GetCurrentGameDef(); + StyleDef* pStyleDef = GAMESTATE->GetCurrentStyleDef(); m_iNumCols = pStyleDef->m_iColsPerPlayer; @@ -42,26 +43,23 @@ void GrayArrowRow::Load( PlayerNumber pn, StyleDef* pStyleDef, PlayerOptions po } -void GrayArrowRow::Update( float fDeltaTime, float fSongBeat ) +void GrayArrowRow::Update( float fDeltaTime ) { - m_fSongBeat = fSongBeat; - for( int c=0; cm_PlayerOptions[m_PlayerNumber].m_bDark ) return; for( int c=0; cGetPathTo(GRAPHIC_HOLD_GHOST_ARROW) ); SetDiffuseColor( D3DXCOLOR(1,1,1,1) ); - SetZoom( 1.1f ); +// SetZoom( 1.1f ); } void HoldGhostArrow::Update( float fDeltaTime ) @@ -32,17 +34,13 @@ void HoldGhostArrow::Update( float fDeltaTime ) Sprite::Update( fDeltaTime ); if( m_bWasSteppedOnLastFrame ) - { m_fHeatLevel += fDeltaTime * 4; - if( m_fHeatLevel >= 1 ) - m_fHeatLevel = 1; - } else - { m_fHeatLevel -= fDeltaTime * 4; - if( m_fHeatLevel < 0 ) - m_fHeatLevel = 0; - } + + CLAMP( m_fHeatLevel, 0, 1 ); +// if( m_fHeatLevel > 0 ) +// printf( "m_fHeatLevel = %f\n", m_fHeatLevel ); int iStateNum = (int)min( m_fHeatLevel * GetNumStates(), GetNumStates()-1 ); SetState( iStateNum ); @@ -60,9 +58,9 @@ void HoldGhostArrow::Update( float fDeltaTime ) m_bWasSteppedOnLastFrame = false; // reset for next frame } -void HoldGhostArrow::SetBeat( const float fSongBeat ) +void HoldGhostArrow::DrawPrimitives() { - //SetState( fmod(fSongBeat,1)<0.25 ? 1 : 0 ); + Sprite::DrawPrimitives(); } void HoldGhostArrow::Step() diff --git a/stepmania/src/HoldGhostArrow.h b/stepmania/src/HoldGhostArrow.h index baf936789c..f53f8210d5 100644 --- a/stepmania/src/HoldGhostArrow.h +++ b/stepmania/src/HoldGhostArrow.h @@ -1,23 +1,17 @@ +#pragma once /* ----------------------------------------------------------------------------- - File: HoldGhostArrow.h + Class: HoldGhostArrow - Desc: Class used to represent a color arrow on the screen. + Desc: The "electricity around the stationary arrow as it's pressing a HoldNote. - Copyright (c) 2001 Ben Norstrom. All rights reserved. + Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved. + Ben Nordstrom + Chris Danford ----------------------------------------------------------------------------- */ - -class HoldGhostArrow; - -#ifndef _HoldGhostArrow_H_ -#define _HoldGhostArrow_H_ - - #include "Sprite.h" -#include "Notes.h" - class HoldGhostArrow : public Sprite { @@ -25,12 +19,11 @@ public: HoldGhostArrow(); virtual void Update( float fDeltaTime ); + virtual void DrawPrimitives(); - void SetBeat( const float fSongBeat ); void Step(); bool m_bWasSteppedOnLastFrame; - float m_fHeatLevel; // effects brightness of electricity - between 0 and 1 + float m_fHeatLevel; // brightness - between 0 and 1 }; -#endif diff --git a/stepmania/src/LifeMeter.h b/stepmania/src/LifeMeter.h index febc6bdf8a..e70ae50662 100644 --- a/stepmania/src/LifeMeter.h +++ b/stepmania/src/LifeMeter.h @@ -21,21 +21,20 @@ class Song; class LifeMeter : public ActorFrame { public: - LifeMeter() { m_fSongBeat = 0; }; + LifeMeter() {}; virtual ~LifeMeter() {}; - virtual void Load( PlayerNumber p, const PlayerOptions &po ) { m_PlayerNumber = p; m_po = po; } - virtual void SetBeat( float fSongBeat ) { m_fSongBeat = fSongBeat; }; + virtual void Load( PlayerNumber p ) { m_PlayerNumber = p; } + virtual void Update( float fDeltaTime ) { ActorFrame::Update(fDeltaTime); }; - virtual void NextSong( Song* pSong ) {}; + virtual void SongEnded() {}; virtual void ChangeLife( TapNoteScore score ) = 0; + virtual void OnDancePointsChange() = 0; // look in GAMESTATE and update the display virtual bool IsInDanger() = 0; virtual bool IsHot() = 0; virtual bool IsFailing() = 0; virtual bool FailedEarlier() = 0; protected: - float m_fSongBeat; PlayerNumber m_PlayerNumber; - PlayerOptions m_po; }; diff --git a/stepmania/src/LifeMeterBar.cpp b/stepmania/src/LifeMeterBar.cpp index cefaddbd08..b72a5c0f17 100644 --- a/stepmania/src/LifeMeterBar.cpp +++ b/stepmania/src/LifeMeterBar.cpp @@ -57,11 +57,11 @@ LifeMeterBar::LifeMeterBar() ResetBarVelocity(); } -void LifeMeterBar::Load( PlayerNumber p, const PlayerOptions &po ) +void LifeMeterBar::Load( PlayerNumber pn ) { - LifeMeter::Load( p, po ); + LifeMeter::Load( pn ); - if( p == PLAYER_2 ) + if( pn == PLAYER_2 ) m_frame.SetZoomX( -1 ); } @@ -139,7 +139,7 @@ bool LifeMeterBar::FailedEarlier() void LifeMeterBar::Update( float fDeltaTime ) { - ActorFrame::Update( fDeltaTime ); + LifeMeter::Update( fDeltaTime ); float fDelta = m_fLifePercentage - m_fTrailingLifePercentage; m_fLifeVelocity += fDelta * fDeltaTime; // accelerate diff --git a/stepmania/src/LifeMeterBar.h b/stepmania/src/LifeMeterBar.h index 6bc1958dbf..476b52a5f5 100644 --- a/stepmania/src/LifeMeterBar.h +++ b/stepmania/src/LifeMeterBar.h @@ -20,12 +20,13 @@ class LifeMeterBar : public LifeMeter public: LifeMeterBar(); - virtual void Load( PlayerNumber p, const PlayerOptions &po ); + virtual void Load( PlayerNumber pn ); virtual void Update( float fDeltaTime ); virtual void DrawPrimitives(); virtual void ChangeLife( TapNoteScore score ); + virtual void OnDancePointsChange() {}; // this life meter doesn't care virtual bool IsInDanger(); virtual bool IsHot(); virtual bool IsFailing(); @@ -41,8 +42,6 @@ private: Sprite m_sprStreamHot; Sprite m_sprFrame; - PlayerOptions m_PlayerOptions; - float m_fLifePercentage; float m_fTrailingLifePercentage; // this approaches m_fLifePercentage float m_fLifeVelocity; // how m_fTrailingLifePercentage approaches m_fLifePercentage diff --git a/stepmania/src/LifeMeterBattery.cpp b/stepmania/src/LifeMeterBattery.cpp index 2d352a80f8..11a0fa7574 100644 --- a/stepmania/src/LifeMeterBattery.cpp +++ b/stepmania/src/LifeMeterBattery.cpp @@ -20,7 +20,7 @@ const float BATTERY_X[NUM_PLAYERS] = { -92, +92 }; const float NUM_X[NUM_PLAYERS] = { BATTERY_X[0], BATTERY_X[1] }; const float NUM_Y = +2; -const float PERCENT_X[NUM_PLAYERS] = { +28, -28 }; +const float PERCENT_X[NUM_PLAYERS] = { +20, -20 }; const float PERCENT_Y = 0; const float BATTERY_BLINK_TIME = 1.2f; @@ -28,8 +28,8 @@ const float BATTERY_BLINK_TIME = 1.2f; LifeMeterBattery::LifeMeterBattery() { - m_iMaxLives = 3; - m_iLivesLeft = m_iMaxLives; + m_iLivesLeft = GAMESTATE->m_SongOptions.m_iBatteryLives; + m_iTrailingLivesLeft = m_iLivesLeft; m_bFailedEarlier = false; m_fBatteryBlinkTime = 0; @@ -59,52 +59,41 @@ LifeMeterBattery::LifeMeterBattery() Refresh(); } -void LifeMeterBattery::Load( PlayerNumber p, const PlayerOptions &po ) +void LifeMeterBattery::Load( PlayerNumber pn ) { - LifeMeter::Load( p, po ); + LifeMeter::Load( pn ); - m_sprFrame.SetZoomX( p==PLAYER_1 ? 1.0f : -1.0f ); - m_sprBattery.SetZoomX( p==PLAYER_1 ? 1.0f : -1.0f ); - m_sprBattery.SetX( BATTERY_X[p] ); - m_textNumLives.SetX( NUM_X[p] ); + m_sprFrame.SetZoomX( pn==PLAYER_1 ? 1.0f : -1.0f ); + m_sprBattery.SetZoomX( pn==PLAYER_1 ? 1.0f : -1.0f ); + m_sprBattery.SetX( BATTERY_X[pn] ); + m_textNumLives.SetX( NUM_X[pn] ); m_textNumLives.SetY( NUM_Y ); - m_textPercent.SetX( PERCENT_X[p] ); + m_textPercent.SetX( PERCENT_X[pn] ); m_textPercent.SetY( PERCENT_Y ); - m_textPercent.SetDiffuseColor( PlayerToColor(p) ); // light blue + m_textPercent.SetDiffuseColor( PlayerToColor(pn) ); // light blue } -void LifeMeterBattery::NextSong( Song* pSong ) +void LifeMeterBattery::SongEnded() { if( m_bFailedEarlier ) return; - m_iLivesLeft++; + m_iTrailingLivesLeft = m_iLivesLeft; + m_iLivesLeft += ( GAMESTATE->m_pCurNotes[m_PlayerNumber]->m_iMeter>=8 ? 2 : 1 ); + m_iLivesLeft = min( m_iLivesLeft, GAMESTATE->m_SongOptions.m_iBatteryLives ); m_soundGainLife.Play(); Refresh(); } + void LifeMeterBattery::ChangeLife( TapNoteScore score ) { if( m_bFailedEarlier ) return; - if( GAMESTATE->m_aGameplayStatistics.GetSize() > 0 ) - { - int iActualDancePoints = 0; - for( int i=0; im_aGameplayStatistics.GetSize(); i++ ) - iActualDancePoints += GAMESTATE->m_aGameplayStatistics[i].iActualDancePoints[m_PlayerNumber]; - int iPossibleDancePoints = GAMESTATE->m_iCoursePossibleDancePoints; - float fPercentDancePoints = iActualDancePoints / (float)iPossibleDancePoints + 0.001f; // correct for rounding errors - float fNumToDisplay = fPercentDancePoints*100; - CString sNumToDisplay = ssprintf("%03.1f", fNumToDisplay); - if( sNumToDisplay.GetLength() == 3 ) - sNumToDisplay = "0" + sNumToDisplay; - m_textPercent.SetText( sNumToDisplay ); - } - switch( score ) { case TNS_PERFECT: @@ -113,16 +102,35 @@ void LifeMeterBattery::ChangeLife( TapNoteScore score ) case TNS_GOOD: case TNS_BOO: case TNS_MISS: + m_iTrailingLivesLeft = m_iLivesLeft; m_iLivesLeft--; m_soundLoseLife.Play(); Refresh(); m_fBatteryBlinkTime = BATTERY_BLINK_TIME; break; } - if( m_iLivesLeft == -1 ) + if( m_iLivesLeft == 0 ) m_bFailedEarlier = true; } +void LifeMeterBattery::OnDancePointsChange() +{ + int iActualDancePoints = GAMESTATE->m_iActualDancePoints[m_PlayerNumber]; + int iPossibleDancePoints = GAMESTATE->m_iPossibleDancePoints[m_PlayerNumber]; + float fPercentDancePoints = iActualDancePoints / (float)iPossibleDancePoints + 0.00001f; // correct for rounding errors + + printf( "Actual %d, Possible %d, Percent %f\n", iActualDancePoints, iPossibleDancePoints, fPercentDancePoints ); + + float fNumToDisplay = MAX( 0, fPercentDancePoints*100 ); + CString sNumToDisplay = ssprintf("%03.1f", fNumToDisplay); + if( sNumToDisplay.GetLength() == 3 ) + sNumToDisplay = "0" + sNumToDisplay; + if( iPossibleDancePoints == -1 ) + sNumToDisplay = "??.?"; + m_textPercent.SetText( sNumToDisplay ); +} + + bool LifeMeterBattery::IsInDanger() { return false; @@ -145,36 +153,41 @@ bool LifeMeterBattery::FailedEarlier() void LifeMeterBattery::Refresh() { - if( m_iLivesLeft <= 3 ) + if( m_iLivesLeft <= 4 ) { m_textNumLives.SetText( "" ); - m_sprBattery.SetState( max(m_iLivesLeft,0) ); + m_sprBattery.SetState( max(m_iLivesLeft-1,0) ); } else { m_textNumLives.SetText( ssprintf("x%d", m_iLivesLeft) ); + m_textNumLives.SetZoom( 1.5f ); + m_textNumLives.BeginTweening( 0.15f ); + m_textNumLives.SetTweenZoom( 1.1f ); m_sprBattery.SetState( 3 ); } } void LifeMeterBattery::Update( float fDeltaTime ) { - if( m_iLivesLeft == -1 ) - { - m_sprBattery.SetState( 0 ); - } - else if( m_fBatteryBlinkTime > 0 ) + LifeMeter::Update( fDeltaTime ); + + if( m_fBatteryBlinkTime > 0 ) { m_fBatteryBlinkTime -= fDeltaTime; - int iFrameNo = m_iLivesLeft + int(m_fBatteryBlinkTime*15)%2; + int iFrame1 = m_iLivesLeft-1; + int iFrame2 = m_iTrailingLivesLeft-1; + + int iFrameNo = (int(m_fBatteryBlinkTime*15)%2) ? iFrame1 : iFrame2; CLAMP( iFrameNo, 0, 3 ); m_sprBattery.SetState( iFrameNo ); - - if( m_fBatteryBlinkTime < 0 ) - { - m_fBatteryBlinkTime = 0; - m_sprBattery.SetState( max(m_iLivesLeft,0) ); - } + } + else + { + m_fBatteryBlinkTime = 0; + int iFrameNo = m_iLivesLeft-1; + CLAMP( iFrameNo, 0, 3 ); + m_sprBattery.SetState( iFrameNo ); } } \ No newline at end of file diff --git a/stepmania/src/LifeMeterBattery.h b/stepmania/src/LifeMeterBattery.h index 86c3d8c75a..2bdf207f2f 100644 --- a/stepmania/src/LifeMeterBattery.h +++ b/stepmania/src/LifeMeterBattery.h @@ -22,12 +22,13 @@ class LifeMeterBattery : public LifeMeter public: LifeMeterBattery(); - virtual void Load( PlayerNumber p, const PlayerOptions &po ); + virtual void Load( PlayerNumber pn ); virtual void Update( float fDeltaTime ); - virtual void NextSong( Song* pSong ); + virtual void SongEnded(); virtual void ChangeLife( TapNoteScore score ); + virtual void OnDancePointsChange(); // look in GAMESTATE and update the display virtual bool IsInDanger(); virtual bool IsHot(); virtual bool IsFailing(); @@ -36,8 +37,8 @@ public: void Refresh(); private: - int m_iLivesLeft; - int m_iMaxLives; + int m_iLivesLeft; // dead when 0 + int m_iTrailingLivesLeft; // lags m_iLivesLeft bool m_bFailedEarlier; float m_fBatteryBlinkTime; // if > 0 battery is blinking diff --git a/stepmania/src/MenuElements.cpp b/stepmania/src/MenuElements.cpp index e375cc8bc8..fc59e5db17 100644 --- a/stepmania/src/MenuElements.cpp +++ b/stepmania/src/MenuElements.cpp @@ -142,12 +142,12 @@ void MenuElements::Load( CString sBackgroundPath, CString sTopEdgePath, CString void MenuElements::TweenTopLayerOnScreen() { m_frameTopBar.SetXY( CENTER_X+SCREEN_WIDTH, m_sprTopEdge.GetZoomedHeight()/2 ); - m_frameTopBar.BeginTweening( MENU_ELEMENTS_TWEEN_TIME*2, TWEEN_SPRING ); + m_frameTopBar.BeginTweening( MENU_ELEMENTS_TWEEN_TIME, TWEEN_SPRING ); m_frameTopBar.SetTweenX( CENTER_X ); float fOriginalZoom = m_textHelp.GetZoomY(); m_textHelp.SetZoomY( 0 ); - m_textHelp.BeginTweening( MENU_ELEMENTS_TWEEN_TIME ); + m_textHelp.BeginTweening( MENU_ELEMENTS_TWEEN_TIME/2 ); m_textHelp.SetTweenZoomY( fOriginalZoom ); } @@ -160,10 +160,10 @@ void MenuElements::TweenOnScreenFromMenu( ScreenMessage smSendWhenDone ) void MenuElements::TweenTopLayerOffScreen() { - m_frameTopBar.BeginTweening( MENU_ELEMENTS_TWEEN_TIME*2, TWEEN_BIAS_END ); + m_frameTopBar.BeginTweening( MENU_ELEMENTS_TWEEN_TIME, TWEEN_BIAS_END ); m_frameTopBar.SetTweenX( SCREEN_WIDTH*1.5f ); - m_textHelp.BeginTweening( MENU_ELEMENTS_TWEEN_TIME ); + m_textHelp.BeginTweening( MENU_ELEMENTS_TWEEN_TIME/2 ); m_textHelp.SetTweenZoomY( 0 ); } @@ -178,22 +178,24 @@ void MenuElements::TweenOffScreenToMenu( ScreenMessage smSendWhenDone ) void MenuElements::TweenBottomLayerOnScreen() { m_frameBottomBar.SetXY( CENTER_X, SCREEN_HEIGHT + m_sprBottomEdge.GetZoomedHeight()/2 ); - m_frameBottomBar.BeginTweening( MENU_ELEMENTS_TWEEN_TIME ); + m_frameBottomBar.BeginTweening( MENU_ELEMENTS_TWEEN_TIME/2 ); m_frameBottomBar.SetTweenY( SCREEN_HEIGHT - m_sprBottomEdge.GetZoomedHeight()/2 ); m_sprBG.SetDiffuseColor( D3DXCOLOR(0,0,0,1) ); - m_sprBG.BeginTweening( MENU_ELEMENTS_TWEEN_TIME ); + m_sprBG.BeginTweening( MENU_ELEMENTS_TWEEN_TIME/2 ); m_sprBG.SetTweenDiffuseColor( D3DXCOLOR(1,1,1,1) ); } void MenuElements::TweenBottomLayerOffScreen() { - m_frameBottomBar.BeginTweening( MENU_ELEMENTS_TWEEN_TIME ); + m_frameBottomBar.BeginTweening( MENU_ELEMENTS_TWEEN_TIME/2 ); m_frameBottomBar.SetTweenY( SCREEN_HEIGHT + m_sprTopEdge.GetZoomedHeight() ); m_sprBG.SetDiffuseColor( D3DXCOLOR(1,1,1,1) ); - m_sprBG.BeginTweening( MENU_ELEMENTS_TWEEN_TIME ); + m_sprBG.StopTweening(); + m_sprBG.BeginTweeningQueued( MENU_ELEMENTS_TWEEN_TIME*3/2.0f ); // sleep + m_sprBG.BeginTweeningQueued( MENU_ELEMENTS_TWEEN_TIME/2 ); // fade m_sprBG.SetTweenDiffuseColor( D3DXCOLOR(0,0,0,1) ); } @@ -211,6 +213,7 @@ void MenuElements::TweenOffScreenToBlack( ScreenMessage smSendWhenDone, bool bPl { TweenTopLayerOffScreen(); TweenBottomLayerOffScreen(); + m_Invisible.SetTransitionTime( MENU_ELEMENTS_TWEEN_TIME*2 ); m_Invisible.CloseWipingRight( smSendWhenDone ); } else diff --git a/stepmania/src/MenuElements.h b/stepmania/src/MenuElements.h index be2e3cf32f..62edb2d23f 100644 --- a/stepmania/src/MenuElements.h +++ b/stepmania/src/MenuElements.h @@ -24,7 +24,7 @@ #include "TipDisplay.h" -const float MENU_ELEMENTS_TWEEN_TIME = 0.30f; +const float MENU_ELEMENTS_TWEEN_TIME = 0.5f; class MenuElements : public ActorFrame diff --git a/stepmania/src/NoteData.cpp b/stepmania/src/NoteData.cpp index 73ca83f286..5e9aecd436 100644 --- a/stepmania/src/NoteData.cpp +++ b/stepmania/src/NoteData.cpp @@ -40,6 +40,10 @@ NoteData::~NoteData() void NoteData::LoadFromSMNoteDataString( CString sSMNoteData ) { + int iNumTracks = m_iNumTracks; + NoteData::Init(); + m_iNumTracks = iNumTracks; + // strip comments out of sSMNoteData while( sSMNoteData.Find("//") != -1 ) { @@ -780,7 +784,7 @@ float NoteData::GetAirRadarValue( float fSongSeconds ) float NoteData::GetChaosRadarValue( float fSongSeconds ) { - // count number of triplets + // count number of triplets or 16ths int iNumChaosNotes = 0; for( int r=0; r= NOTE_12TH ) + if( IsRowComplete(r) && GetNoteType(r) >= NOTE_12TH ) iNumChaosNotesCompleted++; } diff --git a/stepmania/src/NoteField.cpp b/stepmania/src/NoteField.cpp index 35424df127..a94c40dbb3 100644 --- a/stepmania/src/NoteField.cpp +++ b/stepmania/src/NoteField.cpp @@ -36,20 +36,19 @@ NoteField::NoteField() m_rectMarkerBar.TurnShadowOff(); m_rectMarkerBar.SetEffectGlowing(); - m_Mode = MODE_DANCING; - m_fBeginMarker = m_fEndMarker = -1; m_fOverrideAdd = -1; } -void NoteField::Load( NoteData* pNoteData, PlayerNumber p, StyleDef* pStyleDef, PlayerOptions po, int iPixelsToDrawBehind, int iPixelsToDrawAhead, NoteFieldMode mode ) +void NoteField::Load( NoteData* pNoteData, PlayerNumber pn, int iPixelsToDrawBehind, int iPixelsToDrawAhead ) { - m_PlayerOptions = po; + m_PlayerNumber = pn; m_iPixelsToDrawBehind = iPixelsToDrawBehind; m_iPixelsToDrawAhead = iPixelsToDrawAhead; - m_Mode = mode; + + StyleDef* pStyleDef = GAMESTATE->GetCurrentStyleDef(); this->CopyAll( pNoteData ); @@ -59,7 +58,7 @@ void NoteField::Load( NoteData* pNoteData, PlayerNumber p, StyleDef* pStyleDef, CArray arrayTweenColors; GAMEMAN->GetTweenColors( c, arrayTweenColors ); - m_ColorNote[c].Load( c, p ); + m_ColorNote[c].Load( c, pn ); } @@ -70,9 +69,8 @@ void NoteField::Load( NoteData* pNoteData, PlayerNumber p, StyleDef* pStyleDef, ASSERT( m_iNumTracks == GAMESTATE->GetCurrentStyleDef()->m_iColsPerPlayer ); } -void NoteField::Update( float fDeltaTime, float fSongBeat ) +void NoteField::Update( float fDeltaTime ) { - m_fSongBeat = fSongBeat; m_rectMarkerBar.Update( fDeltaTime ); } @@ -81,22 +79,22 @@ void NoteField::Update( float fDeltaTime, float fSongBeat ) void NoteField::CreateTapNoteInstance( ColorNoteInstance &cni, const int iCol, const float fIndex, const D3DXCOLOR color ) { - const float fYOffset = ArrowGetYOffset( m_PlayerOptions, fIndex, m_fSongBeat ); - const float fYPos = ArrowGetYPos( m_PlayerOptions, fYOffset ); - const float fRotation = ArrowGetRotation( m_PlayerOptions, iCol, fYOffset ); - const float fXPos = ArrowGetXPos( m_PlayerOptions, iCol, fYOffset, m_fSongBeat ); - const float fAlpha = ArrowGetAlpha( m_PlayerOptions, fYPos ); + const float fYOffset = ArrowGetYOffset( m_PlayerNumber, fIndex ); + const float fYPos = ArrowGetYPos( m_PlayerNumber, fYOffset ); + const float fRotation = ArrowGetRotation( m_PlayerNumber, iCol, fYOffset ); + const float fXPos = ArrowGetXPos( m_PlayerNumber, iCol, fYOffset ); + const float fAlpha = ArrowGetAlpha( m_PlayerNumber, fYPos ); D3DXCOLOR colorLeading, colorTrailing; // of the color part. Alpha here be overwritten with fAlpha! if( color.a == -1 ) // indicated "NULL" - m_ColorNote[iCol].GetEdgeColorsFromIndexAndBeat( roundf(fIndex), m_fSongBeat, m_PlayerOptions.m_ColorType, colorLeading, colorTrailing ); + m_ColorNote[iCol].GetEdgeColorsFromIndexAndBeat( roundf(fIndex), colorLeading, colorTrailing ); else colorLeading = colorTrailing = color; float fAddAlpha = m_ColorNote[iCol].GetAddAlphaFromDiffuseAlpha( fAlpha ); if( m_fOverrideAdd != -1 ) fAddAlpha = m_fOverrideAdd; - int iGrayPartFrameNo = m_ColorNote[iCol].GetGrayPartFrameNoFromIndexAndBeat( roundf(fIndex), m_fSongBeat ); + int iGrayPartFrameNo = m_ColorNote[iCol].GetGrayPartFrameNoFromIndexAndBeat( roundf(fIndex), GAMESTATE->m_fSongBeat ); ColorNoteInstance instance = { fXPos, fYPos, fRotation, fAlpha, colorLeading, colorTrailing, fAddAlpha, iGrayPartFrameNo }; @@ -107,14 +105,14 @@ void NoteField::CreateHoldNoteInstance( ColorNoteInstance &cni, const bool bActi { const int iCol = hn.m_iTrack; - const float fYOffset = ArrowGetYOffset( m_PlayerOptions, fIndex, m_fSongBeat ); - const float fYPos = ArrowGetYPos( m_PlayerOptions, fYOffset ); - const float fRotation = ArrowGetRotation( m_PlayerOptions, iCol, fYOffset ); - const float fXPos = ArrowGetXPos( m_PlayerOptions, iCol, fYOffset, m_fSongBeat ); - const float fAlpha = ArrowGetAlpha( m_PlayerOptions, fYPos ); + const float fYOffset = ArrowGetYOffset( m_PlayerNumber, fIndex ); + const float fYPos = ArrowGetYPos( m_PlayerNumber, fYOffset ); + const float fRotation = ArrowGetRotation( m_PlayerNumber, iCol, fYOffset ); + const float fXPos = ArrowGetXPos( m_PlayerNumber, iCol, fYOffset ); + const float fAlpha = ArrowGetAlpha( m_PlayerNumber, fYPos ); int iGrayPartFrameNo; - if( bActive && m_Mode == MODE_DANCING ) + if( bActive ) iGrayPartFrameNo = m_ColorNote[iCol].GetGrayPartFrameNoFull(); else iGrayPartFrameNo = m_ColorNote[iCol].GetGrayPartFrameNoClear(); @@ -135,8 +133,8 @@ void NoteField::CreateHoldNoteInstance( ColorNoteInstance &cni, const bool bActi void NoteField::DrawMeasureBar( const int iIndex, const int iMeasureNo ) { - const float fYOffset = ArrowGetYOffset( m_PlayerOptions, (float)iIndex, m_fSongBeat ); - const float fYPos = ArrowGetYPos( m_PlayerOptions, fYOffset ); + const float fYOffset = ArrowGetYOffset( m_PlayerNumber, (float)iIndex ); + const float fYPos = ArrowGetYPos( m_PlayerNumber, fYOffset ); m_rectMeasureBar.SetXY( 0, fYPos ); m_rectMeasureBar.SetWidth( (float)(m_iNumTracks+1) * ARROW_SIZE ); @@ -153,8 +151,8 @@ void NoteField::DrawMeasureBar( const int iIndex, const int iMeasureNo ) void NoteField::DrawMarkerBar( const int iIndex ) { - const float fYOffset = ArrowGetYOffset( m_PlayerOptions, (float)iIndex, m_fSongBeat ); - const float fYPos = ArrowGetYPos( m_PlayerOptions, fYOffset ); + const float fYOffset = ArrowGetYOffset( m_PlayerNumber, (float)iIndex ); + const float fYPos = ArrowGetYPos( m_PlayerNumber, fYOffset ); m_rectMarkerBar.SetXY( 0, fYPos ); m_rectMarkerBar.SetWidth( (float)(m_iNumTracks+1) * ARROW_SIZE ); @@ -165,8 +163,8 @@ void NoteField::DrawMarkerBar( const int iIndex ) void NoteField::DrawBPMText( const int iIndex, const float fBPM ) { - const float fYOffset = ArrowGetYOffset( m_PlayerOptions, (float)iIndex, m_fSongBeat ); - const float fYPos = ArrowGetYPos( m_PlayerOptions, fYOffset ); + const float fYOffset = ArrowGetYOffset( m_PlayerNumber, (float)iIndex ); + const float fYPos = ArrowGetYPos( m_PlayerNumber, fYOffset ); m_textMeasureNumber.SetDiffuseColor( D3DXCOLOR(1,0,0,1) ); m_textMeasureNumber.SetAddColor( D3DXCOLOR(1,1,1,cosf(TIMER->GetTimeSinceStart()*2)/2+0.5f) ); @@ -177,8 +175,8 @@ void NoteField::DrawBPMText( const int iIndex, const float fBPM ) void NoteField::DrawFreezeText( const int iIndex, const float fSecs ) { - const float fYOffset = ArrowGetYOffset( m_PlayerOptions, (float)iIndex, m_fSongBeat ); - const float fYPos = ArrowGetYPos( m_PlayerOptions, fYOffset ); + const float fYOffset = ArrowGetYOffset( m_PlayerNumber, (float)iIndex ); + const float fYPos = ArrowGetYPos( m_PlayerNumber, fYOffset ); m_textMeasureNumber.SetDiffuseColor( D3DXCOLOR(0.8f,0.8f,0,1) ); m_textMeasureNumber.SetAddColor( D3DXCOLOR(1,1,1,cosf(TIMER->GetTimeSinceStart()*2)/2+0.5f) ); @@ -191,19 +189,18 @@ void NoteField::DrawPrimitives() { //LOG->WriteLine( "NoteField::DrawPrimitives()" ); - if( m_fSongBeat < 0 ) - m_fSongBeat = 0; + float fSongBeat = max( 0, GAMESTATE->m_fSongBeat ); - int iBaseFrameNo = (int)(m_fSongBeat*2.5) % NUM_FRAMES_IN_COLOR_ARROW_SPRITE; // 2.5 is a "fudge number" :-) This should be based on BPM + int iBaseFrameNo = (int)(fSongBeat*2.5) % NUM_FRAMES_IN_COLOR_ARROW_SPRITE; // 2.5 is a "fudge number" :-) This should be based on BPM - const float fBeatsToDrawBehind = m_iPixelsToDrawBehind * (1/(float)ARROW_SIZE) * (1/m_PlayerOptions.m_fArrowScrollSpeed); - const float fBeatsToDrawAhead = m_iPixelsToDrawAhead * (1/(float)ARROW_SIZE) * (1/m_PlayerOptions.m_fArrowScrollSpeed); - const int iIndexFirstArrowToDraw = max( 0, BeatToNoteRow( m_fSongBeat - fBeatsToDrawBehind ) ); - const int iIndexLastArrowToDraw = BeatToNoteRow( m_fSongBeat + fBeatsToDrawAhead ); + const float fBeatsToDrawBehind = m_iPixelsToDrawBehind * (1/(float)ARROW_SIZE) * (1/GAMESTATE->m_PlayerOptions[m_PlayerNumber].m_fArrowScrollSpeed); + const float fBeatsToDrawAhead = m_iPixelsToDrawAhead * (1/(float)ARROW_SIZE) * (1/GAMESTATE->m_PlayerOptions[m_PlayerNumber].m_fArrowScrollSpeed); + const int iIndexFirstArrowToDraw = max( 0, BeatToNoteRow( fSongBeat - fBeatsToDrawBehind ) ); + const int iIndexLastArrowToDraw = BeatToNoteRow( fSongBeat + fBeatsToDrawAhead ); //LOG->WriteLine( "Drawing elements %d through %d", iIndexFirstArrowToDraw, iIndexLastArrowToDraw ); - if( m_Mode == MODE_EDITING ) + if( GAMESTATE->m_bEditing ) { // // Draw measure bars @@ -284,25 +281,25 @@ void NoteField::DrawPrimitives() // If this note was in the past and has life > 0, then it was completed and don't draw it! - if( hn.m_iEndIndex < BeatToNoteRow(m_fSongBeat) && fLife > 0 ) + if( hn.m_iEndIndex < BeatToNoteRow(fSongBeat) && fLife > 0 ) continue; // skip const int iCol = hn.m_iTrack; const float fHoldNoteLife = m_HoldNoteLife[i]; - const bool bActive = NoteRowToBeat(hn.m_iStartIndex-1) <= m_fSongBeat && m_fSongBeat <= NoteRowToBeat(hn.m_iEndIndex); // hack: added -1 because hn.m_iStartIndex changes as note is held + const bool bActive = NoteRowToBeat(hn.m_iStartIndex-1) <= fSongBeat && fSongBeat <= NoteRowToBeat(hn.m_iEndIndex); // hack: added -1 because hn.m_iStartIndex changes as note is held // parts of the hold - const float fStartDrawingAtBeat = froundf( (float)hn.m_iStartIndex, ROWS_BETWEEN_HOLD_BITS/m_PlayerOptions.m_fArrowScrollSpeed ); + const float fStartDrawingAtBeat = froundf( (float)hn.m_iStartIndex, ROWS_BETWEEN_HOLD_BITS/GAMESTATE->m_PlayerOptions[m_PlayerNumber].m_fArrowScrollSpeed ); for( float j=fStartDrawingAtBeat; j<=hn.m_iEndIndex; - j+=ROWS_BETWEEN_HOLD_BITS/m_PlayerOptions.m_fArrowScrollSpeed ) // for each bit of the hold + j+=ROWS_BETWEEN_HOLD_BITS/GAMESTATE->m_PlayerOptions[m_PlayerNumber].m_fArrowScrollSpeed ) // for each bit of the hold { // check if this arrow is off the the screen if( j < iIndexFirstArrowToDraw || iIndexLastArrowToDraw < j) continue; // skip this arrow - if( fLife > 0 && NoteRowToBeat(j) < m_fSongBeat ) + if( fLife > 0 && NoteRowToBeat(j) < fSongBeat ) continue; CreateHoldNoteInstance( instances[iCount++], bActive, (float)j, hn, fHoldNoteLife ); @@ -310,7 +307,7 @@ void NoteField::DrawPrimitives() } - const bool bDrawAddPass = m_PlayerOptions.m_AppearanceType != PlayerOptions::APPEARANCE_VISIBLE; + const bool bDrawAddPass = GAMESTATE->m_PlayerOptions[m_PlayerNumber].m_AppearanceType != PlayerOptions::APPEARANCE_VISIBLE; if( iCount > 0 ) m_ColorNote[c].DrawList( iCount, instances, bDrawAddPass ); diff --git a/stepmania/src/NoteField.h b/stepmania/src/NoteField.h index e7e201ce5a..e1c83e0eb0 100644 --- a/stepmania/src/NoteField.h +++ b/stepmania/src/NoteField.h @@ -29,15 +29,10 @@ class NoteField : public NoteData, public ActorFrame { public: NoteField(); - virtual void Update( float fDeltaTime, float fSongBeat ); + virtual void Update( float fDeltaTime ); virtual void DrawPrimitives(); - - enum NoteFieldMode { - MODE_DANCING, - MODE_EDITING, - }; - void Load( NoteData* pNoteData, PlayerNumber p, StyleDef* pStyleDef, PlayerOptions po, int iPixelsToDrawBehind, int iPixelsToDrawAhead, NoteFieldMode mode ); + void Load( NoteData* pNoteData, PlayerNumber pn, int iPixelsToDrawBehind, int iPixelsToDrawAhead ); void RemoveTapNoteRow( int iIndex ); void SetHoldNoteLife( int iIndex, float fLife ); @@ -55,16 +50,10 @@ protected: inline void DrawBPMText( const int iIndex, const float fBPM ); inline void DrawFreezeText( const int iIndex, const float fBPM ); - PlayerOptions m_PlayerOptions; - + PlayerNumber m_PlayerNumber; int m_iPixelsToDrawBehind; int m_iPixelsToDrawAhead; - float m_fSongBeat; - - - NoteFieldMode m_Mode; - // color arrows ColorNote m_ColorNote[MAX_NOTE_TRACKS]; diff --git a/stepmania/src/Player.cpp b/stepmania/src/Player.cpp index e564ef5acf..4e629b7ee3 100644 --- a/stepmania/src/Player.cpp +++ b/stepmania/src/Player.cpp @@ -21,6 +21,7 @@ #include "InputMapper.h" #include "SongManager.h" #include "GameState.h" +#include "RageLog.h" // these two items are in the @@ -28,6 +29,8 @@ const float FRAME_JUDGE_AND_COMBO_Y = CENTER_Y; const float JUDGEMENT_Y_OFFSET = -26; const float COMBO_Y_OFFSET = +26; +const float FRAME_JUDGE_AND_COMBO_BEAT_TIME = 0.2f; + const float ARROWS_Y = SCREEN_TOP + ARROW_SIZE * 1.5f; const float HOLD_JUDGEMENT_Y = ARROWS_Y + 80; @@ -36,8 +39,6 @@ const float HOLD_ARROW_NG_TIME = 0.18f; Player::Player() { - - m_fSongBeat = 0; m_PlayerNumber = PLAYER_INVALID; m_pLifeMeter = NULL; @@ -58,58 +59,69 @@ Player::Player() } -void Player::Load( PlayerNumber player_no, StyleDef* pStyleDef, NoteData* pNoteData, const PlayerOptions& po, LifeMeter* pLM, ScoreDisplay* pScore, int iOriginalNumNotes, int iNotesMeter ) +void Player::Load( PlayerNumber pn, NoteData* pNoteData, LifeMeter* pLM, ScoreDisplay* pScore ) { //LOG->WriteLine( "Player::Load()", ); + + m_PlayerNumber = pn; + m_pLifeMeter = pLM; + m_pScore = pScore; + + StyleDef* pStyleDef = GAMESTATE->GetCurrentStyleDef(); + + // copy note data this->CopyAll( pNoteData ); + + + m_iNumTapNotes = pNoteData->GetNumTapNotes(); + m_iTapNotesHit = 0; + m_iMeter = GAMESTATE->m_pCurNotes[m_PlayerNumber]->m_iMeter; + + // init scoring NoteDataWithScoring::Init(); for( int i=0; iInit( player_no, m_PlayerOptions, iOriginalNumNotes, iNotesMeter ); + m_pScore->Init( pn ); - if( !po.m_bHoldNotes ) + if( !GAMESTATE->m_PlayerOptions[pn].m_bHoldNotes ) this->RemoveHoldNotes(); - this->Turn( po.m_TurnType ); + this->Turn( GAMESTATE->m_PlayerOptions[pn].m_TurnType ); - if( po.m_bLittle ) + if( GAMESTATE->m_PlayerOptions[pn].m_bLittle ) this->MakeLittle(); int iPixelsToDrawBefore = 64; int iPixelsToDrawAfter = 320; - switch( po.m_EffectType ) + switch( GAMESTATE->m_PlayerOptions[pn].m_EffectType ) { case PlayerOptions::EFFECT_MINI: iPixelsToDrawBefore *= 2; iPixelsToDrawAfter *= 2; break; case PlayerOptions::EFFECT_SPACE: iPixelsToDrawBefore *= 2; iPixelsToDrawAfter *= 2; break; } - m_NoteField.Load( (NoteData*)this, player_no, pStyleDef, po, iPixelsToDrawBefore, iPixelsToDrawAfter, NoteField::MODE_DANCING ); + m_NoteField.Load( (NoteData*)this, pn, iPixelsToDrawBefore, iPixelsToDrawAfter ); - m_GrayArrowRow.Load( player_no, pStyleDef, po ); - m_GhostArrowRow.Load( player_no, pStyleDef, po ); + m_GrayArrowRow.Load( pn ); + m_GhostArrowRow.Load( pn ); m_frameJudgement.SetY( FRAME_JUDGE_AND_COMBO_Y ); m_frameCombo.SetY( FRAME_JUDGE_AND_COMBO_Y ); - m_Combo.SetY( po.m_bReverseScroll ? -COMBO_Y_OFFSET : COMBO_Y_OFFSET ); - m_Judgement.SetY( po.m_bReverseScroll ? -JUDGEMENT_Y_OFFSET : JUDGEMENT_Y_OFFSET ); + m_Combo.SetY( GAMESTATE->m_PlayerOptions[pn].m_bReverseScroll ? -COMBO_Y_OFFSET : COMBO_Y_OFFSET ); + m_Judgement.SetY( GAMESTATE->m_PlayerOptions[pn].m_bReverseScroll ? -JUDGEMENT_Y_OFFSET : JUDGEMENT_Y_OFFSET ); for( int c=0; cm_iColsPerPlayer; c++ ) - m_HoldJudgement[c].SetY( po.m_bReverseScroll ? SCREEN_HEIGHT - HOLD_JUDGEMENT_Y : HOLD_JUDGEMENT_Y ); + m_HoldJudgement[c].SetY( GAMESTATE->m_PlayerOptions[pn].m_bReverseScroll ? SCREEN_HEIGHT - HOLD_JUDGEMENT_Y : HOLD_JUDGEMENT_Y ); for( c=0; cm_iColsPerPlayer; c++ ) - m_HoldJudgement[c].SetX( (float)pStyleDef->m_ColumnInfo[player_no][c].fXOffset ); + m_HoldJudgement[c].SetX( (float)pStyleDef->m_ColumnInfo[pn][c].fXOffset ); - m_NoteField.SetY( po.m_bReverseScroll ? SCREEN_HEIGHT - ARROWS_Y : ARROWS_Y ); - m_GrayArrowRow.SetY( po.m_bReverseScroll ? SCREEN_HEIGHT - ARROWS_Y : ARROWS_Y ); - m_GhostArrowRow.SetY( po.m_bReverseScroll ? SCREEN_HEIGHT - ARROWS_Y : ARROWS_Y ); + m_NoteField.SetY( GAMESTATE->m_PlayerOptions[pn].m_bReverseScroll ? SCREEN_HEIGHT - ARROWS_Y : ARROWS_Y ); + m_GrayArrowRow.SetY( GAMESTATE->m_PlayerOptions[pn].m_bReverseScroll ? SCREEN_HEIGHT - ARROWS_Y : ARROWS_Y ); + m_GhostArrowRow.SetY( GAMESTATE->m_PlayerOptions[pn].m_bReverseScroll ? SCREEN_HEIGHT - ARROWS_Y : ARROWS_Y ); - if( po.m_EffectType == PlayerOptions::EFFECT_MINI ) + if( GAMESTATE->m_PlayerOptions[pn].m_EffectType == PlayerOptions::EFFECT_MINI ) { m_NoteField.SetZoom( 0.5f ); m_GrayArrowRow.SetZoom( 0.5f ); @@ -117,16 +129,16 @@ void Player::Load( PlayerNumber player_no, StyleDef* pStyleDef, NoteData* pNoteD } } -void Player::Update( float fDeltaTime, float fSongBeat, float fMaxBeatDifference ) +void Player::Update( float fDeltaTime ) { - //LOG->WriteLine( "Player::Update(%f, %f, %f)", fDeltaTime, fSongBeat, fMaxBeatDifference ); + //LOG->WriteLine( "Player::Update(%f)", fDeltaTime ); - m_fSongBeat = fSongBeat; // save song beat + const float fSongBeat = GAMESTATE->m_fSongBeat; // // Check for TapNote misses // - UpdateTapNotesMissedOlderThan( m_fSongBeat-fMaxBeatDifference ); + UpdateTapNotesMissedOlderThan( GAMESTATE->m_fSongBeat - GetMaxBeatDifference() ); // @@ -149,7 +161,7 @@ void Player::Update( float fDeltaTime, float fSongBeat, float fMaxBeatDifference // update the life - if( fStartBeat < m_fSongBeat && m_fSongBeat < fEndBeat ) // if the song beat is in the range of this hold + if( fStartBeat < fSongBeat && fSongBeat < fEndBeat ) // if the song beat is in the range of this hold { const bool bIsHoldingButton = INPUTMAPPER->IsButtonDown( GameI ) || PREFSMAN->m_bAutoPlay; // if they got a bad score or haven't stepped on the corresponding tap yet @@ -162,13 +174,13 @@ void Player::Update( float fDeltaTime, float fSongBeat, float fMaxBeatDifference fLife += fDeltaTime/HOLD_ARROW_NG_TIME; fLife = min( fLife, 1 ); // clamp - m_NoteField.m_HoldNotes[i].m_iStartIndex = BeatToNoteRow( m_fSongBeat ); // move the start of this Hold + m_NoteField.m_HoldNotes[i].m_iStartIndex = BeatToNoteRow( fSongBeat ); // move the start of this Hold m_GhostArrowRow.HoldNote( hn.m_iTrack ); // update the "electric ghost" effect } else // !bIsHoldingButton { - if( m_fSongBeat-fStartBeat > fMaxBeatDifference ) + if( fSongBeat-fStartBeat > GetMaxBeatDifference() ) { // Decrease life fLife -= fDeltaTime/HOLD_ARROW_NG_TIME; @@ -182,18 +194,18 @@ void Player::Update( float fDeltaTime, float fSongBeat, float fMaxBeatDifference if( fLife == 0 ) // the player has not pressed the button for a long time! { hns = HNS_NG; - GAMESTATE->GetLatestGameplayStatistics().iActualDancePoints[m_PlayerNumber] += HoldNoteScoreToDancePoints( hns ); + HandleNoteScore( hns ); m_Combo.EndCombo(); m_HoldJudgement[hn.m_iTrack].SetHoldJudgement( HNS_NG ); } // check for OK - if( m_fSongBeat > fEndBeat ) // if this HoldNote is in the past + if( fSongBeat > fEndBeat ) // if this HoldNote is in the past { // At this point fLife > 0, or else we would have marked it NG above fLife = 1; hns = HNS_OK; - GAMESTATE->GetLatestGameplayStatistics().iActualDancePoints[m_PlayerNumber] += HoldNoteScoreToDancePoints( hns ); + HandleNoteScore( hns ); m_HoldJudgement[hn.m_iTrack].SetHoldJudgement( HNS_OK ); m_NoteField.SetHoldNoteLife( i, fLife ); // update the NoteField display } @@ -202,23 +214,13 @@ void Player::Update( float fDeltaTime, float fSongBeat, float fMaxBeatDifference ActorFrame::Update( fDeltaTime ); - - m_frameJudgement.Update( fDeltaTime ); - m_frameCombo.Update( fDeltaTime ); - - if( m_pLifeMeter ) - m_pLifeMeter->SetBeat( fSongBeat ); - - m_GrayArrowRow.Update( fDeltaTime, fSongBeat ); - m_NoteField.Update( fDeltaTime, fSongBeat ); - m_GhostArrowRow.Update( fDeltaTime, fSongBeat ); } void Player::DrawPrimitives() { D3DXMATRIX matOldView, matOldProj; - if( m_PlayerOptions.m_EffectType == PlayerOptions::EFFECT_SPACE ) + if( GAMESTATE->m_PlayerOptions[m_PlayerNumber].m_EffectType == PlayerOptions::EFFECT_SPACE ) { // save old view and projection DISPLAY->GetDevice()->GetTransform( D3DTS_VIEW, &matOldView ); @@ -227,7 +229,7 @@ void Player::DrawPrimitives() // construct view and project matrix D3DXMATRIX matNewView; - if( m_PlayerOptions.m_bReverseScroll ) + if( GAMESTATE->m_PlayerOptions[m_PlayerNumber].m_bReverseScroll ) D3DXMatrixLookAtLH( &matNewView, &D3DXVECTOR3( CENTER_X, GetY()-300.0f, 400.0f ), @@ -255,7 +257,7 @@ void Player::DrawPrimitives() m_NoteField.Draw(); m_GhostArrowRow.Draw(); - if( m_PlayerOptions.m_EffectType == PlayerOptions::EFFECT_SPACE ) + if( GAMESTATE->m_PlayerOptions[m_PlayerNumber].m_EffectType == PlayerOptions::EFFECT_SPACE ) { // restire old view and projection DISPLAY->GetDevice()->SetTransform( D3DTS_VIEW, &matOldView ); @@ -268,16 +270,17 @@ void Player::DrawPrimitives() m_HoldJudgement[c].Draw(); } -void Player::HandlePlayerStep( float fSongBeat, int col, float fMaxBeatDiff ) +void Player::Step( int col ) { //LOG->WriteLine( "Player::HandlePlayerStep()" ); ASSERT( col >= 0 && col <= m_iNumTracks ); + const float fSongBeat = GAMESTATE->m_fSongBeat; // look for the closest matching step - int iIndexStartLookingAt = BeatToNoteRow( fSongBeat ); - int iNumElementsToExamine = BeatToNoteRow( fMaxBeatDiff ); // number of elements to examine on either end of iIndexStartLookingAt + int iIndexStartLookingAt = BeatToNoteRow( GAMESTATE->m_fSongBeat ); + int iNumElementsToExamine = BeatToNoteRow( GetMaxBeatDifference() ); // number of elements to examine on either end of iIndexStartLookingAt //LOG->WriteLine( "iIndexStartLookingAt = %d, iNumElementsToExamine = %d", iIndexStartLookingAt, iNumElementsToExamine ); @@ -324,7 +327,7 @@ void Player::HandlePlayerStep( float fSongBeat, int col, float fMaxBeatDiff ) // compute the score for this hit const float fStepBeat = NoteRowToBeat( (float)iIndexOverlappingNote ); const float fBeatsUntilStep = fStepBeat - fSongBeat; - const float fPercentFromPerfect = fabsf( fBeatsUntilStep / fMaxBeatDiff ); + const float fPercentFromPerfect = fabsf( fBeatsUntilStep / GetMaxBeatDifference() ); TapNoteScore &score = m_TapNoteScores[col][iIndexOverlappingNote]; @@ -347,14 +350,14 @@ void Player::HandlePlayerStep( float fSongBeat, int col, float fMaxBeatDiff ) } } if( bRowDestroyed ) - OnRowDestroyed( fSongBeat, col, fMaxBeatDiff, iIndexOverlappingNote ); + OnRowDestroyed( col, iIndexOverlappingNote ); } if( !bDestroyedNote ) m_GrayArrowRow.Step( col ); } -void Player::OnRowDestroyed( float fSongBeat, int col, float fMaxBeatDiff, int iIndexThatWasSteppedOn ) +void Player::OnRowDestroyed( int col, int iIndexThatWasSteppedOn ) { //LOG->WriteLine( "fBeatsUntilStep: %f, fPercentFromPerfect: %f", // fBeatsUntilStep, fPercentFromPerfect ); @@ -365,12 +368,6 @@ void Player::OnRowDestroyed( float fSongBeat, int col, float fMaxBeatDiff, int i if( m_TapNoteScores[t][iIndexThatWasSteppedOn] >= TNS_BOO ) score = min( score, m_TapNoteScores[t][iIndexThatWasSteppedOn] ); - // update the judgement, score, and life - m_Judgement.SetJudgement( score ); - if( m_pLifeMeter ) - m_pLifeMeter->ChangeLife( score ); - - // remove this row from the NoteField if ( ( score == TNS_PERFECT ) || ( score == TNS_GREAT ) ) m_NoteField.RemoveTapNoteRow( iIndexThatWasSteppedOn ); @@ -381,12 +378,7 @@ void Player::OnRowDestroyed( float fSongBeat, int col, float fMaxBeatDiff, int i { m_GhostArrowRow.TapNote( c, score, m_Combo.GetCurrentCombo()>100 ); // show the ghost arrow for this column - if( m_pScore ) - m_pScore->AddToScore( score, m_Combo.GetCurrentCombo() ); // update score - called once per note in this row - - // update dance points for Oni lifemeter - if( GAMESTATE->m_aGameplayStatistics.GetSize() > 0 ) - GAMESTATE->GetLatestGameplayStatistics().iActualDancePoints[m_PlayerNumber] += TapNoteScoreToDancePoints( score ); + HandleNoteScore( score ); // update score - called once per note in this row // update combo - called once per note in this row switch( score ) @@ -394,6 +386,7 @@ void Player::OnRowDestroyed( float fSongBeat, int col, float fMaxBeatDiff, int i case TNS_PERFECT: case TNS_GREAT: m_Combo.ContinueCombo(); + GAMESTATE->m_iMaxCombo[m_PlayerNumber] = max( GAMESTATE->m_iMaxCombo[m_PlayerNumber], m_Combo.GetCurrentCombo() ); break; case TNS_GOOD: case TNS_BOO: @@ -403,21 +396,26 @@ void Player::OnRowDestroyed( float fSongBeat, int col, float fMaxBeatDiff, int i } } + // update the judgement, score, and life + m_Judgement.SetJudgement( score ); + if( m_pLifeMeter ) + m_pLifeMeter->ChangeLife( score ); + // zoom the judgement and combo like a heart beat float fStartZoom; switch( score ) { - case TNS_PERFECT: fStartZoom = 1.5f; break; - case TNS_GREAT: fStartZoom = 1.3f; break; - case TNS_GOOD: fStartZoom = 1.2f; break; + case TNS_PERFECT: fStartZoom = 1.3f; break; + case TNS_GREAT: fStartZoom = 1.2f; break; + case TNS_GOOD: fStartZoom = 1.1f; break; case TNS_BOO: fStartZoom = 1.0f; break; } m_frameJudgement.SetZoom( fStartZoom ); - m_frameJudgement.BeginTweening( 0.2f ); + m_frameJudgement.BeginTweening( 0.1f ); m_frameJudgement.SetTweenZoom( 1 ); m_frameCombo.SetZoom( fStartZoom ); - m_frameCombo.BeginTweening( 0.2f ); + m_frameCombo.BeginTweening( 0.1f ); m_frameCombo.SetTweenZoom( 1 ); } @@ -444,6 +442,7 @@ int Player::UpdateTapNotesMissedOlderThan( float fMissIfOlderThanThisBeat ) m_TapNoteScores[t][r] = TNS_MISS; iNumMissesFound++; bFoundAMissInThisRow = true; + HandleNoteScore( TNS_MISS ); } if( bFoundAMissInThisRow ) if( m_pLifeMeter ) @@ -461,7 +460,7 @@ int Player::UpdateTapNotesMissedOlderThan( float fMissIfOlderThanThisBeat ) } -void Player::CrossedRow( int iNoteRow, float fSongBeat, float fMaxBeatDiff ) +void Player::CrossedRow( int iNoteRow ) { if( PREFSMAN->m_bAutoPlay ) { @@ -469,59 +468,94 @@ void Player::CrossedRow( int iNoteRow, float fSongBeat, float fMaxBeatDiff ) for( int t=0; tHandlePlayerStep( fSongBeat, t, fMaxBeatDiff ); + this->Step( t ); } } } -void Player::SaveGameplayStatistics() +void Player::HandleNoteScore( TapNoteScore score ) { - GameplayStatistics& GS = GAMESTATE->m_aGameplayStatistics[GAMESTATE->m_aGameplayStatistics.GetSize()-1]; - int p = m_PlayerNumber; + // update dance points for Oni lifemeter + GAMESTATE->m_iActualDancePoints[m_PlayerNumber] += TapNoteScoreToDancePoints( score ); + GAMESTATE->m_TapNoteScores[m_PlayerNumber][score]++; + if( m_pLifeMeter ) + m_pLifeMeter->OnDancePointsChange(); - GS.iActualDancePoints[p] = 0; - for( int t=0; tGetScore() : 0; + + int N = m_iNumTapNotes; + int n = m_iTapNotesHit+1; + int B = m_iMeter * 1000000; + float S = (1+N)*N/2.0f; - GS.failed[p] = m_pLifeMeter ? m_pLifeMeter->FailedEarlier() : false; + printf( "m_iNumTapNotes %d, m_iTapNotesHit %d\n", m_iNumTapNotes, m_iTapNotesHit ); - for( int r=0; rGetActualRadarValue( (RadarCategory)r, GAMESTATE->m_pCurSong->m_fMusicLengthSeconds ); - CLAMP( GS.fRadarActual[p][r], 0, 1 ); - } + float one_step_score = p * (B/S) * n; + + float& fScore = GAMESTATE->m_fScore[m_PlayerNumber]; + ASSERT( fScore >= 0 ); + + fScore += one_step_score; + + m_iTapNotesHit++; + ASSERT( m_iTapNotesHit <= m_iNumTapNotes ); + + // HACK: Correct for rounding errors that cause a 100% perfect score to be slightly off + if( m_iTapNotesHit == m_iNumTapNotes && + fabsf( fScore - froundf(fScore,1000000) ) < 50.0f ) // close to a multiple of 1,000,000 + fScore = froundf(fScore,1000000); + + if( m_pScore ) + m_pScore->SetScore( fScore ); } + +void Player::HandleNoteScore( HoldNoteScore score ) +{ + // update dance points for Oni lifemeter + GAMESTATE->m_iActualDancePoints[m_PlayerNumber] += HoldNoteScoreToDancePoints( score ); + GAMESTATE->m_HoldNoteScores[m_PlayerNumber][score]++; + if( m_pLifeMeter ) + m_pLifeMeter->OnDancePointsChange(); + + // HoldNoteScores don't effect m_fScore +} +float Player::GetMaxBeatDifference() +{ + return GAMESTATE->m_fCurBPS * PREFSMAN->m_fJudgeWindow * GAMESTATE->m_SongOptions.m_fMusicRate; +} \ No newline at end of file diff --git a/stepmania/src/Player.h b/stepmania/src/Player.h index c065509086..99981abb87 100644 --- a/stepmania/src/Player.h +++ b/stepmania/src/Player.h @@ -34,32 +34,31 @@ #include "NoteDataWithScoring.h" -struct GameplayStatistics; - class Player : public NoteDataWithScoring, public ActorFrame { public: Player(); - void Update( float fDeltaTime, float fSongBeat, float fMaxBeatDifference ); - void DrawPrimitives(); + virtual void Update( float fDeltaTime ); + virtual void DrawPrimitives(); - void Load( PlayerNumber player_no, StyleDef *pStyleDef, NoteData* pNoteData, const PlayerOptions& po, LifeMeter* pLM, ScoreDisplay* pScore, int iOriginalNumNotes, int iNotesMeter ); - void CrossedRow( int iNoteRow, float fSongBeat, float fMaxBeatDiff ); - void HandlePlayerStep( float fSongBeat, int col, float fMaxBeatDiff ); - int UpdateTapNotesMissedOlderThan( float fMissIfOlderThanThisBeat ); + void Load( PlayerNumber player_no, NoteData* pNoteData, LifeMeter* pLM, ScoreDisplay* pScore ); + void CrossedRow( int iNoteRow ); + void Step( int col ); - void SaveGameplayStatistics(); void SetOverrideAdd( float fAdd ) { m_NoteField.m_fOverrideAdd = fAdd; }; float GetOverrideAdd() { return m_NoteField.m_fOverrideAdd; }; protected: - void OnRowDestroyed( float fSongBeat, int col, float fMaxBeatDiff, int iStepIndex ); + int UpdateTapNotesMissedOlderThan( float fMissIfOlderThanThisBeat ); + void OnRowDestroyed( int col, int iStepIndex ); + void HandleNoteScore( TapNoteScore score ); + void HandleNoteScore( HoldNoteScore score ); + + static float GetMaxBeatDifference(); - float m_fSongBeat; PlayerNumber m_PlayerNumber; - PlayerOptions m_PlayerOptions; float m_fHoldNoteLife[MAX_TAP_NOTE_ROWS]; // 1.0 means this HoldNote has full life. // 0.0 means this HoldNote is dead @@ -67,7 +66,9 @@ protected: // m_HoldScore becomes HSS_NG. // If the life is > 0.0 when the HoldNote ends, then // m_HoldScore becomes HSS_OK. - + int m_iNumTapNotes; // num of TapNotes for the current notes needed by scoring + int m_iTapNotesHit; // number of notes judged so far, needed by scoring + int m_iMeter; // meter of current steps, needed by scoring GrayArrowRow m_GrayArrowRow; NoteField m_NoteField; diff --git a/stepmania/src/PrefsManager.h b/stepmania/src/PrefsManager.h index 313e89fce0..cf5116b859 100644 --- a/stepmania/src/PrefsManager.h +++ b/stepmania/src/PrefsManager.h @@ -49,11 +49,6 @@ public: void SaveGlobalPrefsToDisk(); - // AppearanceOptions (ARE saved between sessions, and saved per game) -// CString m_sAnnouncer; // need to make sure to call ANNOUNCER->SwitchAnnouncer() when this changes -// CString m_sTheme; // need to make sure to call THEME->SwitchTheme() when this changes -// CString m_sNoteSkin; - void ReadGamePrefsFromDisk(); void SaveGamePrefsToDisk(); }; diff --git a/stepmania/src/RageSound.cpp b/stepmania/src/RageSound.cpp index 5eaf67dd2f..9e59cf506c 100644 --- a/stepmania/src/RageSound.cpp +++ b/stepmania/src/RageSound.cpp @@ -1,11 +1,12 @@ #include "stdafx.h" /* ----------------------------------------------------------------------------- - File: RageSound.cpp + Class: RageSound - Desc: Sound effects library (currently a wrapper around Bass Sound Library). + Desc: See header. Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved. + Chris Danford ----------------------------------------------------------------------------- */ diff --git a/stepmania/src/RageUtil.h b/stepmania/src/RageUtil.h index 2a6abcb887..5e298624f3 100644 --- a/stepmania/src/RageUtil.h +++ b/stepmania/src/RageUtil.h @@ -19,6 +19,7 @@ #define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } #define ZERO(x) memset(&x, 0, sizeof(x)) +#define COPY(a,b) { ASSERT(sizeof(a)==sizeof(b)); memcpy(&a, &b, sizeof(a)); } #define RECTWIDTH(rect) ((rect).right - (rect).left) #define RECTHEIGHT(rect) ((rect).bottom - (rect).top) @@ -33,6 +34,14 @@ inline int RECTCENTERY(RECT rect) { return rect.top + (rect.bottom-rect.top)/2; #define min(a,b) (((a) < (b)) ? (a) : (b)) #endif +#ifndef MAX +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#endif + +#ifndef MIN +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#endif + #define clamp(val,low,high) ( max( (low), min((val),(high)) ) ) #define PI D3DX_PI diff --git a/stepmania/src/ScoreDisplay.h b/stepmania/src/ScoreDisplay.h index 453031135d..d64e69b86d 100644 --- a/stepmania/src/ScoreDisplay.h +++ b/stepmania/src/ScoreDisplay.h @@ -21,14 +21,13 @@ class ScoreDisplay : public BitmapText { public: - virtual void Init( PlayerNumber pn, PlayerOptions po, int iOriginalNumNotes, int iNotesMeter ) = 0; - - virtual void SetScore( float fNewScore ) = 0; - virtual int GetScore() = 0; - virtual void AddToScore( TapNoteScore score, int iCurCombo ) = 0; + virtual void Init( PlayerNumber pn ) { m_PlayerNumber = pn; }; virtual void Update( float fDeltaTime ) = 0; virtual void Draw() = 0; + virtual void SetScore( float fNewScore ) = 0; + protected: + PlayerNumber m_PlayerNumber; // needed to look up statistics in GAMESTATE }; diff --git a/stepmania/src/ScoreDisplayNormal.cpp b/stepmania/src/ScoreDisplayNormal.cpp index 2a5a4edfe7..8d02aed8c6 100644 --- a/stepmania/src/ScoreDisplayNormal.cpp +++ b/stepmania/src/ScoreDisplayNormal.cpp @@ -35,15 +35,11 @@ ScoreDisplayNormal::ScoreDisplayNormal() } -void ScoreDisplayNormal::Init( PlayerNumber pn, PlayerOptions po, int iOriginalNumNotes, int iNotesMeter ) +void ScoreDisplayNormal::Init( PlayerNumber pn ) { m_PlayerNumber = pn; - m_PlayerOptions = po; - m_iTotalNotes = iOriginalNumNotes; - m_iNotesMeter = iNotesMeter; - //for( int i=0; im_fScore[pn] ); } void ScoreDisplayNormal::SetScore( float fNewScore ) @@ -55,105 +51,28 @@ void ScoreDisplayNormal::SetScore( float fNewScore ) m_fScoreVelocity = fDelta / SCORE_TWEEN_TIME; // in score units per second } - -int ScoreDisplayNormal::GetScore() -{ - return (int)m_fScore; -} - - void ScoreDisplayNormal::Update( float fDeltaTime ) { BitmapText::Update( fDeltaTime ); - float fDeltaBefore = (float)m_fScore - m_fTrailingScore; - m_fTrailingScore += m_fScoreVelocity * fDeltaTime; - float fDeltaAfter = (float)m_fScore - m_fTrailingScore; - - if( fDeltaBefore * fDeltaAfter < 0 ) // the sign changed + if( m_fTrailingScore != m_fScore ) { - m_fTrailingScore = (float)m_fScore; - m_fScoreVelocity = 0; - } + float fDeltaBefore = (float)m_fScore - m_fTrailingScore; + m_fTrailingScore += m_fScoreVelocity * fDeltaTime; + float fDeltaAfter = (float)m_fScore - m_fTrailingScore; + if( fDeltaBefore * fDeltaAfter < 0 ) // the sign changed + { + m_fTrailingScore = (float)m_fScore; + m_fScoreVelocity = 0; + } + + CString sFormat = ssprintf( "%%%d.0f", NUM_SCORE_DIGITS ); + SetText( ssprintf(sFormat, m_fTrailingScore) ); + } } void ScoreDisplayNormal::Draw() { - if( m_fScore == 0 ) - { - CString sFormat = ssprintf( "%%%d.0d", NUM_SCORE_DIGITS ); - SetText( ssprintf(sFormat, 0) ); - } - else - { - CString sFormat = ssprintf( "%%%d.0f", NUM_SCORE_DIGITS ); - SetText( ssprintf(sFormat, m_fTrailingScore) ); - } - BitmapText::Draw(); } - - -void ScoreDisplayNormal::AddToScore( TapNoteScore score, int iCurCombo ) -{ -//A single step's points are calculated as follows: -// -//Let p = score multiplier (Perfect = 10, Great = 5, other = 0) -//N = total number of steps and freeze steps -//n = number of the current step or freeze step (varies from 1 to N) -//B = Base value of the song (1,000,000 X the number of feet difficulty) - All edit data is rated as 5 feet -//So, the score for one step is: -//one_step_score = p * (B/S) * n -//Where S = The sum of all integers from 1 to N (the total number of steps/freeze steps) -// -//*IMPORTANT* : Double steps (U+L, D+R, etc.) count as two steps instead of one, so if you get a double L+R on the 112th step of a song, you score is calculated with a Perfect/Great/whatever for both the 112th and 113th steps. Got it? Now, through simple algebraic manipulation -//S = 1+...+N = (1+N)*N/2 (1 through N added together) -//Okay, time for an example: -// -//So, for example, suppose we wanted to calculate the step score of a "Great" on the 57th step of a 441 step, 8-foot difficulty song (I'm just making this one up): -// -//S = (1 + 441)*441 / 2 -//= 194,222 / 2 -//= 97,461 -//StepScore = p * (B/S) * n -//= 5 * (8,000,000 / 97,461) * 57 -//= 5 * (82) * 57 (The 82 is rounded down from 82.08411...) -//= 23,370 -//Remember this is just the score for the step, not the cumulative score up to the 57th step. Also, please note that I am currently checking into rounding errors with the system and if there are any, how they are resolved in the system. -// -//Note: if you got all Perfect on this song, you would get (p=10)*B, which is 80,000,000. In fact, the maximum possible score for any song is the number of feet difficulty X 10,000,000. - - if( PREFSMAN->m_bAutoPlay ) - return; // No Scoring on Autoplay! - - - static int iNumTimesCalled = 0; - iNumTimesCalled ++; - LOG->WriteLine("Called %d times - param %d.",iNumTimesCalled, iCurCombo); - - - int p; // score multiplier - switch( score ) - { - case TNS_PERFECT: p = 10; break; - case TNS_GREAT: p = 5; break; - default: p = 0; break; - } - - int N = m_iTotalNotes; - int n = iCurCombo+1; - int B = m_iNotesMeter * 1000000; - float S = (1+N)*N/2.0f; - - int one_step_score = roundf( p * (B/S) * n ); - - m_fScore += one_step_score; - ASSERT( m_fScore >= 0 ); - - // HACK: The final total is slightly off because of rounding errors - if( fabsf(m_fScore-B*10) < 100.0f ) - m_fScore = (float)B*10; - - this->SetScore( m_fScore ); -} diff --git a/stepmania/src/ScoreDisplayNormal.h b/stepmania/src/ScoreDisplayNormal.h index dd2a1461d6..73e9f9aa3f 100644 --- a/stepmania/src/ScoreDisplayNormal.h +++ b/stepmania/src/ScoreDisplayNormal.h @@ -3,7 +3,7 @@ ----------------------------------------------------------------------------- Class: ScoreDisplayNormal - Desc: A graphic displayed in the ScoreDisplayNormal during Dancing. + Desc: Shows point score during gameplay and used in some menus. Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved. Chris Danford @@ -21,23 +21,15 @@ class ScoreDisplayNormal : public ScoreDisplay public: ScoreDisplayNormal(); - virtual void Init( PlayerNumber pn, PlayerOptions po, int iOriginalNumNotes, int iNotesMeter ); - - virtual void SetScore( float fNewScore ); - virtual int GetScore(); - virtual void AddToScore( TapNoteScore score, int iCurCombo ); + virtual void Init( PlayerNumber pn ); virtual void Update( float fDeltaTime ); virtual void Draw(); + virtual void SetScore( float fNewScore ); + protected: - PlayerNumber m_PlayerNumber; - PlayerOptions m_PlayerOptions; - int m_iTotalNotes; - int m_iNotesMeter; - - float m_fScore; - - float m_fTrailingScore; - float m_fScoreVelocity; + float m_fScore; // the actual score + float m_fTrailingScore; // what is displayed temporarily + float m_fScoreVelocity; // how fast trailing approaches real score }; diff --git a/stepmania/src/ScoreDisplayOni.cpp b/stepmania/src/ScoreDisplayOni.cpp index 588d0ee51b..e60d6e9a99 100644 --- a/stepmania/src/ScoreDisplayOni.cpp +++ b/stepmania/src/ScoreDisplayOni.cpp @@ -28,61 +28,27 @@ ScoreDisplayOni::ScoreDisplayOni() // init the text Load( THEME->GetPathTo(FONT_SCORE_NUMBERS) ); TurnShadowOff(); - - m_fTrailingScore = 0; - - SetScore( 0 ); } -void ScoreDisplayOni::Init( PlayerNumber pn, PlayerOptions po, int iOriginalNumNotes, int iNotesMeter ) +void ScoreDisplayOni::Init( PlayerNumber pn ) { m_PlayerNumber = pn; - m_PlayerOptions = po; - m_iTotalNotes = iOriginalNumNotes; - m_iNotesMeter = iNotesMeter; - - //for( int i=0; im_aGameplayStatistics.GetSize(); i++ ) - fSecsIntoPlay += GAMESTATE->m_aGameplayStatistics[i].fSecsIntoPlay[m_PlayerNumber]; + float fSecsIntoPlay = GAMESTATE->GetPlayerSurviveTime(m_PlayerNumber); + int iMinsDisplay = (int)fSecsIntoPlay/60; int iSecsDisplay = (int)fSecsIntoPlay - iMinsDisplay*60; int iLeftoverDisplay = int( (fSecsIntoPlay - iMinsDisplay*60 - iSecsDisplay) * 100 ); @@ -90,63 +56,3 @@ void ScoreDisplayOni::Draw() BitmapText::Draw(); } - - -void ScoreDisplayOni::AddToScore( TapNoteScore score, int iCurCombo ) -{ -//A single step's points are calculated as follows: -// -//Let p = score multiplier (Perfect = 10, Great = 5, other = 0) -//N = total number of steps and freeze steps -//n = number of the current step or freeze step (varies from 1 to N) -//B = Base value of the song (1,000,000 X the number of feet difficulty) - All edit data is rated as 5 feet -//So, the score for one step is: -//one_step_score = p * (B/S) * n -//Where S = The sum of all integers from 1 to N (the total number of steps/freeze steps) -// -//*IMPORTANT* : Double steps (U+L, D+R, etc.) count as two steps instead of one, so if you get a double L+R on the 112th step of a song, you score is calculated with a Perfect/Great/whatever for both the 112th and 113th steps. Got it? Now, through simple algebraic manipulation -//S = 1+...+N = (1+N)*N/2 (1 through N added together) -//Okay, time for an example: -// -//So, for example, suppose we wanted to calculate the step score of a "Great" on the 57th step of a 441 step, 8-foot difficulty song (I'm just making this one up): -// -//S = (1 + 441)*441 / 2 -//= 194,222 / 2 -//= 97,461 -//StepScore = p * (B/S) * n -//= 5 * (8,000,000 / 97,461) * 57 -//= 5 * (82) * 57 (The 82 is rounded down from 82.08411...) -//= 23,370 -//Remember this is just the score for the step, not the cumulative score up to the 57th step. Also, please note that I am currently checking into rounding errors with the system and if there are any, how they are resolved in the system. -// -//Note: if you got all Perfect on this song, you would get (p=10)*B, which is 80,000,000. In fact, the maximum possible score for any song is the number of feet difficulty X 10,000,000. - - static int iNumTimesCalled = 0; - iNumTimesCalled ++; - LOG->WriteLine("Called %d times - param %d.",iNumTimesCalled, iCurCombo); - - - int p; // score multiplier - switch( score ) - { - case TNS_PERFECT: p = 10; break; - case TNS_GREAT: p = 5; break; - default: p = 0; break; - } - - int N = m_iTotalNotes; - int n = iCurCombo+1; - int B = m_iNotesMeter * 1000000; - float S = (1+N)*N/2.0f; - - int one_step_score = roundf( p * (B/S) * n ); - - m_fScore += one_step_score; - ASSERT( m_fScore >= 0 ); - - // HACK: The final total is slightly off because of rounding errors - if( fabsf(m_fScore-B*10) < 100.0f ) - m_fScore = (float)B*10; - - this->SetScore( m_fScore ); -} diff --git a/stepmania/src/ScoreDisplayOni.h b/stepmania/src/ScoreDisplayOni.h index a54f560127..d3c04c3410 100644 --- a/stepmania/src/ScoreDisplayOni.h +++ b/stepmania/src/ScoreDisplayOni.h @@ -3,7 +3,7 @@ ----------------------------------------------------------------------------- Class: ScoreDisplayOni - Desc: A graphic displayed in the ScoreDisplayOni during Dancing. + Desc: Shows time into course. Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved. Chris Danford @@ -20,23 +20,12 @@ class ScoreDisplayOni : public ScoreDisplay public: ScoreDisplayOni(); - virtual void Init( PlayerNumber pn, PlayerOptions po, int iOriginalNumNotes, int iNotesMeter ); - - virtual void SetScore( float fNewScore ); - virtual int GetScore(); - virtual void AddToScore( TapNoteScore score, int iCurCombo ); + virtual void Init( PlayerNumber pn ); virtual void Update( float fDeltaTime ); virtual void Draw(); + virtual void SetScore( float fNewScore ); + protected: - PlayerNumber m_PlayerNumber; - PlayerOptions m_PlayerOptions; - int m_iTotalNotes; - int m_iNotesMeter; - - float m_fScore; - - float m_fTrailingScore; - float m_fScoreVelocity; }; diff --git a/stepmania/src/ScreenEdit.cpp b/stepmania/src/ScreenEdit.cpp index 328d5fe56c..479b72f7a1 100644 --- a/stepmania/src/ScreenEdit.cpp +++ b/stepmania/src/ScreenEdit.cpp @@ -118,14 +118,15 @@ ScreenEdit::ScreenEdit() m_pNotes->GetNoteData( ¬eData ); - m_Mode = MODE_EDIT; + m_EditMode = MODE_EDITING; + + GAMESTATE->m_bEditing = true; m_fBeat = 0.0f; - m_fTrailingBeat = m_fBeat; + GAMESTATE->m_fSongBeat = m_fBeat; - m_PlayerOptions.m_fArrowScrollSpeed = 1; - m_PlayerOptions.m_ColorType = PlayerOptions::COLOR_NOTE; -// m_PlayerOptions.m_bShowMeasureBars = true; + GAMESTATE->m_PlayerOptions[PLAYER_1].m_fArrowScrollSpeed = 1; + GAMESTATE->m_PlayerOptions[PLAYER_1].m_ColorType = PlayerOptions::COLOR_NOTE; m_sprBackground.Load( THEME->GetPathTo( GRAPHIC_EDIT_BACKGROUND ) ); m_sprBackground.StretchTo( CRect(SCREEN_LEFT,SCREEN_TOP,SCREEN_RIGHT,SCREEN_BOTTOM) ); @@ -136,27 +137,27 @@ ScreenEdit::ScreenEdit() m_GranularityIndicator.SetZoom( 0.5f ); m_GrayArrowRowEdit.SetXY( EDIT_X, EDIT_GRAY_Y ); - m_GrayArrowRowEdit.Load( PLAYER_1, GAMESTATE->GetCurrentStyleDef(), m_PlayerOptions ); + m_GrayArrowRowEdit.Load( PLAYER_1 ); m_GrayArrowRowEdit.SetZoom( 0.5f ); m_NoteFieldEdit.SetXY( EDIT_X, EDIT_GRAY_Y ); m_NoteFieldEdit.SetZoom( 0.5f ); - m_NoteFieldEdit.Load( ¬eData, PLAYER_1, GAMESTATE->GetCurrentStyleDef(), m_PlayerOptions, 10, 12, NoteField::MODE_EDITING ); + m_NoteFieldEdit.Load( ¬eData, PLAYER_1, 200, 800 ); m_rectRecordBack.StretchTo( CRect(SCREEN_LEFT, SCREEN_TOP, SCREEN_RIGHT, SCREEN_BOTTOM) ); m_rectRecordBack.SetDiffuseColor( D3DXCOLOR(0,0,0,0) ); m_GrayArrowRowRecord.SetXY( EDIT_X, EDIT_GRAY_Y ); - m_GrayArrowRowRecord.Load( PLAYER_1, GAMESTATE->GetCurrentStyleDef(), m_PlayerOptions ); + m_GrayArrowRowRecord.Load( PLAYER_1 ); m_GrayArrowRowRecord.SetZoom( 1.0f ); m_NoteFieldRecord.SetXY( EDIT_X, EDIT_GRAY_Y ); m_NoteFieldRecord.SetZoom( 1.0f ); - m_NoteFieldRecord.Load( ¬eData, PLAYER_1, GAMESTATE->GetCurrentStyleDef(), m_PlayerOptions, 2, 5, NoteField::MODE_EDITING ); + m_NoteFieldRecord.Load( ¬eData, PLAYER_1, 60, 300 ); m_Clipboard.m_iNumTracks = m_NoteFieldEdit.m_iNumTracks; - m_Player.Load( PLAYER_1, GAMESTATE->GetCurrentStyleDef(), ¬eData, PlayerOptions(), NULL, NULL, 1, 1 ); + m_Player.Load( PLAYER_1, ¬eData, NULL, NULL ); m_Player.SetXY( PLAYER_X, PLAYER_Y ); m_Fade.SetClosed(); @@ -204,46 +205,46 @@ void ScreenEdit::Update( float fDeltaTime ) bool bFreeze; m_pSong->GetBeatAndBPSFromElapsedTime( fPositionSeconds, fSongBeat, fBPS, bFreeze ); - if( m_Mode == MODE_RECORD || m_Mode == MODE_PLAY ) + if( m_EditMode == MODE_RECORDING || m_EditMode == MODE_PLAYING ) { m_fBeat = fSongBeat; if( m_fBeat > m_NoteFieldEdit.m_fEndMarker ) { - if( m_Mode == MODE_RECORD ) + if( m_EditMode == MODE_RECORDING ) { TransitionToEditFromRecord(); } - else if( m_Mode == MODE_PLAY ) + else if( m_EditMode == MODE_PLAYING ) { m_soundMusic.Stop(); - m_Mode = MODE_EDIT; + m_EditMode = MODE_EDITING; } } } m_sprBackground.Update( fDeltaTime ); m_GranularityIndicator.Update( fDeltaTime ); - m_GrayArrowRowEdit.Update( fDeltaTime, m_fBeat ); - m_NoteFieldEdit.Update( fDeltaTime, m_fBeat ); + m_GrayArrowRowEdit.Update( fDeltaTime ); + m_NoteFieldEdit.Update( fDeltaTime ); m_Fade.Update( fDeltaTime ); m_textHelp.Update( fDeltaTime ); m_textInfo.Update( fDeltaTime ); - if( m_Mode == MODE_RECORD || m_Mode == MODE_PLAY ) + if( m_EditMode == MODE_RECORDING || m_EditMode == MODE_PLAYING ) { m_rectRecordBack.Update( fDeltaTime ); } - if( m_Mode == MODE_RECORD ) + if( m_EditMode == MODE_RECORDING ) { - m_GrayArrowRowRecord.Update( fDeltaTime, m_fBeat ); - m_NoteFieldRecord.Update( fDeltaTime, m_fBeat ); + m_GrayArrowRowRecord.Update( fDeltaTime ); + m_NoteFieldRecord.Update( fDeltaTime ); } - if( m_Mode == MODE_PLAY ) + if( m_EditMode == MODE_PLAYING ) { - m_Player.Update( fDeltaTime, m_fBeat, 0.35f ); + m_Player.Update( fDeltaTime ); } //LOG->WriteLine( "ScreenEdit::Update(%f)", fDeltaTime ); @@ -251,11 +252,12 @@ void ScreenEdit::Update( float fDeltaTime ) // Update trailing beat - float fDelta = m_fBeat - m_fTrailingBeat; + float fDelta = m_fBeat - GAMESTATE->m_fSongBeat; + if( fabsf(fDelta) < 0.01 ) { - m_fTrailingBeat = m_fBeat; // snap + GAMESTATE->m_fSongBeat = m_fBeat; // snap } else { @@ -263,10 +265,10 @@ void ScreenEdit::Update( float fDeltaTime ) float fMoveDelta = fSign*fDeltaTime*40; if( fabsf(fMoveDelta) > fabsf(fDelta) ) fMoveDelta = fDelta; - m_fTrailingBeat += fMoveDelta; + GAMESTATE->m_fSongBeat += fMoveDelta; if( fabsf(fDelta) > 10 ) - m_fTrailingBeat += fDelta * fDeltaTime*5; + GAMESTATE->m_fSongBeat += fDelta * fDeltaTime*5; } @@ -278,7 +280,7 @@ void ScreenEdit::Update( float fDeltaTime ) // LOG->WriteLine( "fPositionSeconds = %f, fSongBeat = %f, fBPS = %f", fPositionSeconds, fSongBeat, fBPS ); - m_NoteFieldEdit.Update( fDeltaTime, m_fTrailingBeat ); + m_NoteFieldEdit.Update( fDeltaTime ); int iIndexNow = BeatToNoteRowNotRounded( m_fBeat ); @@ -334,18 +336,18 @@ void ScreenEdit::DrawPrimitives() m_textInfo.Draw(); m_Fade.Draw(); - if( m_Mode == MODE_RECORD || m_Mode == MODE_PLAY ) + if( m_EditMode == MODE_RECORDING || m_EditMode == MODE_PLAYING ) { m_rectRecordBack.Draw(); } - if( m_Mode == MODE_RECORD ) + if( m_EditMode == MODE_RECORDING ) { m_GrayArrowRowRecord.Draw(); m_NoteFieldRecord.Draw(); } - if( m_Mode == MODE_PLAY ) + if( m_EditMode == MODE_PLAYING ) { m_Player.Draw(); } @@ -357,11 +359,11 @@ void ScreenEdit::Input( const DeviceInput& DeviceI, const InputEventType type, c { //LOG->WriteLine( "ScreenEdit::Input()" ); - switch( m_Mode ) + switch( m_EditMode ) { - case MODE_EDIT: InputEdit( DeviceI, type, GameI, MenuI, StyleI ); break; - case MODE_RECORD: InputRecord( DeviceI, type, GameI, MenuI, StyleI ); break; - case MODE_PLAY: InputPlay( DeviceI, type, GameI, MenuI, StyleI ); break; + case MODE_EDITING: InputEdit( DeviceI, type, GameI, MenuI, StyleI ); break; + case MODE_RECORDING: InputRecord( DeviceI, type, GameI, MenuI, StyleI ); break; + case MODE_PLAYING: InputPlay( DeviceI, type, GameI, MenuI, StyleI ); break; } } @@ -568,9 +570,9 @@ void ScreenEdit::InputEdit( const DeviceInput& DeviceI, const InputEventType typ m_fBeat = m_NoteFieldEdit.m_fBeginMarker; - m_Mode = MODE_PLAY; + m_EditMode = MODE_PLAYING; - m_Player.Load( PLAYER_1, GAMESTATE->GetCurrentStyleDef(), (NoteData*)&m_NoteFieldEdit, PlayerOptions(), NULL, NULL, 1, 1 ); + m_Player.Load( PLAYER_1, (NoteData*)&m_NoteFieldEdit, NULL, NULL ); m_rectRecordBack.BeginTweening( 0.5f ); m_rectRecordBack.SetTweenDiffuseColor( D3DXCOLOR(0,0,0,0.5f) ); @@ -598,7 +600,7 @@ void ScreenEdit::InputEdit( const DeviceInput& DeviceI, const InputEventType typ m_NoteFieldRecord.m_fEndMarker = m_NoteFieldEdit.m_fEndMarker; - m_Mode = MODE_RECORD; + m_EditMode = MODE_RECORDING; m_rectRecordBack.BeginTweening( 0.5f ); m_rectRecordBack.SetTweenDiffuseColor( D3DXCOLOR(0,0,0,0.5f) ); @@ -874,7 +876,7 @@ void ScreenEdit::InputPlay( const DeviceInput& DeviceI, const InputEventType typ switch( DeviceI.button ) { case DIK_ESCAPE: - m_Mode = MODE_EDIT; + m_EditMode = MODE_EDITING; m_soundMusic.Stop(); m_fBeat = froundf( m_fBeat, NoteTypeToBeat(m_GranularityIndicator.GetSnapMode()) ); @@ -890,7 +892,7 @@ void ScreenEdit::InputPlay( const DeviceInput& DeviceI, const InputEventType typ switch( StyleI.player ) { case PLAYER_1: - m_Player.HandlePlayerStep( m_fBeat, StyleI.col, fMaxBeatDifference ); + m_Player.Step( StyleI.col ); return; } @@ -899,7 +901,7 @@ void ScreenEdit::InputPlay( const DeviceInput& DeviceI, const InputEventType typ void ScreenEdit::TransitionToEditFromRecord() { - m_Mode = MODE_EDIT; + m_EditMode = MODE_EDITING; m_soundMusic.Stop(); int iNoteIndexBegin = BeatToNoteRow( m_NoteFieldEdit.m_fBeginMarker ); diff --git a/stepmania/src/ScreenEdit.h b/stepmania/src/ScreenEdit.h index ed741ee122..a34d28ceb3 100644 --- a/stepmania/src/ScreenEdit.h +++ b/stepmania/src/ScreenEdit.h @@ -41,14 +41,12 @@ protected: void OnSnapModeChange(); - enum EditMode { MODE_EDIT, MODE_RECORD, MODE_PLAY }; - EditMode m_Mode; + enum EditMode { MODE_EDITING, MODE_RECORDING, MODE_PLAYING }; + EditMode m_EditMode; Song* m_pSong; Notes* m_pNotes; - PlayerOptions m_PlayerOptions; - Sprite m_sprBackground; NoteField m_NoteFieldEdit; @@ -59,8 +57,7 @@ protected: BitmapText m_textHelp; // keep track of where we are and what we're doing - float m_fTrailingBeat; // this approaches m_fBeat - float m_fBeat; + float m_fBeat; // make GAMESTATE->m_fSongBeat approach this NoteData m_Clipboard; diff --git a/stepmania/src/ScreenEvaluation.cpp b/stepmania/src/ScreenEvaluation.cpp index 55acb59a32..9c4a3403b5 100644 --- a/stepmania/src/ScreenEvaluation.cpp +++ b/stepmania/src/ScreenEvaluation.cpp @@ -73,6 +73,7 @@ ScreenEvaluation::ScreenEvaluation( bool bSummary ) m_ResultMode = bSummary ? RM_ARCADE_SUMMARY : RM_ARCADE_STAGE; break; case PLAY_MODE_ONI: + case PLAY_MODE_ENDLESS: m_ResultMode = RM_ONI; break; default: @@ -80,65 +81,55 @@ ScreenEvaluation::ScreenEvaluation( bool bSummary ) } + /////////////////////////// + // Figure out which statistics we're going to display + /////////////////////////// + int iPossibleDancePoints[NUM_PLAYERS]; + int iActualDancePoints[NUM_PLAYERS]; + int iTapNoteScores[NUM_PLAYERS][NUM_TAP_NOTE_SCORES]; + int iHoldNoteScores[NUM_PLAYERS][NUM_HOLD_NOTE_SCORES]; + int iMaxCombo[NUM_PLAYERS]; + float fScore[NUM_PLAYERS]; + float fPossibleRadarValues[NUM_PLAYERS][NUM_RADAR_CATEGORIES]; + float fActualRadarValues[NUM_PLAYERS][NUM_RADAR_CATEGORIES]; - /////////////////////////// - // Calculate total statistics depending on m_ResultMode - /////////////////////////// - GameplayStatistics totalGS; switch( m_ResultMode ) { - case RM_ARCADE_STAGE: - { - // take the latest GameplayStatistics - totalGS = GAMESTATE->m_aGameplayStatistics[GAMESTATE->m_aGameplayStatistics.GetSize()-1]; - } - break; case RM_ARCADE_SUMMARY: + COPY( iPossibleDancePoints, GAMESTATE->m_iAccumPossibleDancePoints ); + COPY( iActualDancePoints, GAMESTATE->m_iAccumActualDancePoints ); + COPY( iTapNoteScores, GAMESTATE->m_AccumTapNoteScores ); + COPY( iHoldNoteScores, GAMESTATE->m_AccumHoldNoteScores ); + COPY( iMaxCombo, GAMESTATE->m_iAccumMaxCombo ); + COPY( fScore, GAMESTATE->m_fAccumScore ); + COPY( fPossibleRadarValues, GAMESTATE->m_fAccumRadarPossible ); + COPY( fActualRadarValues, GAMESTATE->m_fAccumRadarActual ); + break; + case RM_ARCADE_STAGE: case RM_ONI: - { - int iFirstToTakeFrom; - switch( m_ResultMode ) - { - case RM_ARCADE_SUMMARY: - iFirstToTakeFrom = max( 0, GAMESTATE->m_aGameplayStatistics.GetSize()-STAGES_TO_SHOW_IN_SUMMARY ); - break; - case RM_ONI: - iFirstToTakeFrom = 0; - break; - default: - ASSERT(0); - } - - for( int i=iFirstToTakeFrom; im_aGameplayStatistics.GetSize(); i++ ) - totalGS += GAMESTATE->m_aGameplayStatistics[i]; - - // Chris: - // ugly... GameplayStatistics::operator+= simply sums the radar values, so we need - // to divide by the number of stages taken from to normalize the values. - int iNumTakenFrom = GAMESTATE->m_aGameplayStatistics.GetSize() - iFirstToTakeFrom; - - for( int p=0; pm_iPossibleDancePoints ); + COPY( iActualDancePoints, GAMESTATE->m_iActualDancePoints ); + COPY( iTapNoteScores, GAMESTATE->m_TapNoteScores ); + COPY( iHoldNoteScores, GAMESTATE->m_HoldNoteScores ); + COPY( iMaxCombo, GAMESTATE->m_iMaxCombo ); + COPY( fScore, GAMESTATE->m_fScore ); + COPY( fPossibleRadarValues, GAMESTATE->m_fRadarPossible ); + COPY( fActualRadarValues, GAMESTATE->m_fRadarActual ); break; } + + /////////////////////////// // Andy: // Fake COOL! / GOOD / OOPS for Ez2dancer using the DDR Rankings. if( GAMESTATE->m_CurGame == GAME_EZ2 ) { for( int p=0; pm_aGameplayStatistics.GetSize() > STAGES_TO_SHOW_IN_SUMMARY ) - GAMESTATE->m_aGameplayStatistics.RemoveAt( 0, GAMESTATE->m_aGameplayStatistics.GetSize() - STAGES_TO_SHOW_IN_SUMMARY ); + if( GAMESTATE->m_apSongsPlayed.GetSize() > STAGES_TO_SHOW_IN_SUMMARY ) + GAMESTATE->m_apSongsPlayed.RemoveAt( 0, GAMESTATE->m_apSongsPlayed.GetSize() - STAGES_TO_SHOW_IN_SUMMARY ); } - const int iSongsToShow = GAMESTATE->m_aGameplayStatistics.GetSize(); + const int iSongsToShow = GAMESTATE->m_apSongsPlayed.GetSize(); ASSERT( iSongsToShow > 0 ); for( int i=0; im_aGameplayStatistics[i]; - m_BannerWithFrame[i].LoadFromSong( GS.pSong ); + m_BannerWithFrame[i].LoadFromSong( GAMESTATE->m_apSongsPlayed[i] ); float fBannerOffset = i - (iSongsToShow-1)/2.0f; m_BannerWithFrame[i].SetXY( BANNER_X + fBannerOffset*32, BANNER_Y + fBannerOffset*16 ); m_BannerWithFrame[i].SetZoom( 0.70f ); @@ -193,7 +183,7 @@ ScreenEvaluation::ScreenEvaluation( bool bSummary ) m_Menu.Load( THEME->GetPathTo(GRAPHIC_EVALUATION_BACKGROUND), m_ResultMode==RM_ARCADE_SUMMARY ? THEME->GetPathTo(GRAPHIC_EVALUATION_SUMMARY_TOP_EDGE) : THEME->GetPathTo(GRAPHIC_EVALUATION_TOP_EDGE), - "Press START to continue.", + "Press START to continue", false, true, 40 ); this->AddSubActor( &m_Menu ); @@ -257,6 +247,7 @@ ScreenEvaluation::ScreenEvaluation( bool bSummary ) if (GAMESTATE->m_CurGame != GAME_EZ2) { m_sprScoreLabel.Load( THEME->GetPathTo(GRAPHIC_EVALUATION_SCORE_LABELS) ); + m_sprScoreLabel.SetState( m_ResultMode==RM_ONI ? 1 : 0 ); m_sprScoreLabel.StopAnimating(); m_sprScoreLabel.SetXY( SCORE_LABEL_X, SCORE_Y ); m_sprScoreLabel.SetZoom( 1.0f ); @@ -280,14 +271,38 @@ ScreenEvaluation::ScreenEvaluation( bool bSummary ) // Calculate grades // Grade grade[NUM_PLAYERS]; - Grade max_grade = GRADE_NO_DATA; for( p=0; pIsPlayerEnabled(pn) ? GRADE_NO_DATA : totalGS.GetGrade(pn); - max_grade = max( max_grade, grade[p] ); + if( !GAMESTATE->IsPlayerEnabled(p) || GAMESTATE->m_bUsedAutoPlayer || GAMESTATE->m_fSecondsBeforeFail[p] != -1 ) + { + grade[p] = GRADE_E; + } + else + { +//Based on the percentage of your total "Dance Points" to the maximum possible number, the following rank is assigned: +// +//100% - AAA +//93 % - AA +//80 % - A +//65 % - B +//45 % - C +//Less - D +//Fail - E + float fPercentDancePoints = iActualDancePoints[p] / (float)iPossibleDancePoints[p]; + + if ( fPercentDancePoints >= 1.00 ) grade[p] = GRADE_AAA; + else if( fPercentDancePoints >= 0.93 ) grade[p] = GRADE_AA; + else if( fPercentDancePoints >= 0.80 ) grade[p] = GRADE_A; + else if( fPercentDancePoints >= 0.65 ) grade[p] = GRADE_B; + else if( fPercentDancePoints >= 0.45 ) grade[p] = GRADE_C; + else grade[p] = GRADE_D; + } } + Grade max_grade = GRADE_NO_DATA; + for( p=0; pIsPlayerEnabled( (PlayerNumber)p ) ) continue; // skip - m_textJudgeNumbers[0][p].SetText( ssprintf("%4d", totalGS.perfect[p]) ); - m_textJudgeNumbers[1][p].SetText( ssprintf("%4d", totalGS.great[p]) ); - m_textJudgeNumbers[2][p].SetText( ssprintf("%4d", totalGS.good[p]) ); - m_textJudgeNumbers[3][p].SetText( ssprintf("%4d", totalGS.boo[p]) ); - m_textJudgeNumbers[4][p].SetText( ssprintf("%4d", totalGS.miss[p]) ); - m_textJudgeNumbers[5][p].SetText( ssprintf("%4d", totalGS.ok[p]) ); + m_textJudgeNumbers[0][p].SetText( ssprintf("%4d", iTapNoteScores[p][TNS_PERFECT]) ); + m_textJudgeNumbers[1][p].SetText( ssprintf("%4d", iTapNoteScores[p][TNS_GREAT]) ); + m_textJudgeNumbers[2][p].SetText( ssprintf("%4d", iTapNoteScores[p][TNS_GOOD]) ); + m_textJudgeNumbers[3][p].SetText( ssprintf("%4d", iTapNoteScores[p][TNS_BOO]) ); + m_textJudgeNumbers[4][p].SetText( ssprintf("%4d", iTapNoteScores[p][TNS_MISS]) ); + m_textJudgeNumbers[5][p].SetText( ssprintf("%4d", iHoldNoteScores[p][HNS_OK]) ); - m_ScoreDisplay[p].SetScore( (float)totalGS.max_combo[p] * 1000 ); - m_ScoreDisplay[p].SetScore( (float)totalGS.score[p] ); + if( m_ResultMode==RM_ONI ) + { + const float fSurviveSeconds = GAMESTATE->GetPlayerSurviveTime( (PlayerNumber)p ); + int iMinsDisplay = (int)fSurviveSeconds/60; + int iSecsDisplay = (int)fSurviveSeconds - iMinsDisplay*60; + int iLeftoverDisplay = int( (fSurviveSeconds - iMinsDisplay*60 - iSecsDisplay) * 100 ); + m_ScoreDisplay[p].SetText( ssprintf( "%02d:%02d:%02d", iMinsDisplay, iSecsDisplay, iLeftoverDisplay ) ); + } + else + { + m_ScoreDisplay[p].SetScore( fScore[p] ); + } // SNEAKY! We take the max combo, and put it into element 5, because Ez2dancer // doesn't care for OK's and plus this text element is already nicely aligned =) if (GAMESTATE->m_CurGame == GAME_EZ2) { - m_textJudgeNumbers[5][p].SetText( ssprintf("%4d", totalGS.max_combo[p]) ); + m_textJudgeNumbers[5][p].SetText( ssprintf("%4d", iMaxCombo[p]) ); } - m_ScoreDisplay[p].SetScore( (float)totalGS.max_combo[p] * 1000 ); - m_ScoreDisplay[p].SetScore( (float)totalGS.score[p] ); + m_BonusInfoFrame[p].SetBonusInfo( (PlayerNumber)p, fPossibleRadarValues[p], fActualRadarValues[p], iMaxCombo[p] ); + m_StageBox[p].SetStageInfo( (PlayerNumber)p, GAMESTATE->m_iStagesIntoCourse[p] ); + } - m_BonusInfoFrame[p].SetBonusInfo( (PlayerNumber)p, totalGS.fRadarPossible[p], totalGS.fRadarActual[p], totalGS.max_combo[p] ); + //////////////////////// + // update persistent statistics + //////////////////////// + for( p=0; pIsPlayerEnabled(p) ) + continue; switch( m_ResultMode ) { case RM_ARCADE_STAGE: - //////////////////////// - // update song stats - //////////////////////// Notes* pNotes = GAMESTATE->m_pCurNotes[p]; pNotes->m_iNumTimesPlayed++; - if( totalGS.max_combo[p] > pNotes->m_iMaxCombo ) - pNotes->m_iMaxCombo = totalGS.max_combo[p]; + if( iMaxCombo[p] > pNotes->m_iMaxCombo ) + pNotes->m_iMaxCombo = iMaxCombo[p]; - if( totalGS.score[p] > pNotes->m_iTopScore ) + if( fScore[p] > pNotes->m_iTopScore ) { - pNotes->m_iTopScore = (int)totalGS.score[p]; + pNotes->m_iTopScore = (int)fScore[p]; m_bNewRecord[p] = true; } @@ -390,13 +419,12 @@ ScreenEvaluation::ScreenEvaluation( bool bSummary ) m_textOniPercent[p].SetZoomY( 2.5f ); m_textOniPercent[p].SetEffectGlowing( 1.0f ); - int iActualDancePoints = 0; - for( int i=0; im_aGameplayStatistics.GetSize(); i++ ) - iActualDancePoints += GAMESTATE->m_aGameplayStatistics[i].iActualDancePoints[p]; - int iPossibleDancePoints = GAMESTATE->m_iCoursePossibleDancePoints; - float fPercentDancePoints = iActualDancePoints / (float)iPossibleDancePoints + 0.0001f; // correct for rounding errors + float fPercentDancePoints = iActualDancePoints[p] / (float)iPossibleDancePoints[p] + 0.0001f; // correct for rounding errors m_textOniPercent[p].SetText( ssprintf("%.1f%%", fPercentDancePoints*100) ); this->AddSubActor( &m_textOniPercent[p] ); + + m_StageBox[p].SetXY( BONUS_FRAME_X[p], BONUS_FRAME_Y ); + this->AddSubActor( &m_StageBox[p] ); } break; case RM_ARCADE_STAGE: @@ -408,6 +436,9 @@ ScreenEvaluation::ScreenEvaluation( bool bSummary ) m_Grades[p].SetZoom( 1.0f ); m_Grades[p].SetEffectGlowing( 1.0f ); m_Grades[p].SpinAndSettleOn( grade[p] ); + + m_BonusInfoFrame[p].SetXY( BONUS_FRAME_X[p], BONUS_FRAME_Y ); + this->AddSubActor( &m_BonusInfoFrame[p] ); } else // Ez2dancer Style Grade Display. { @@ -433,9 +464,6 @@ ScreenEvaluation::ScreenEvaluation( bool bSummary ) if ( GAMESTATE->m_CurGame == GAME_EZ2) continue; - m_BonusInfoFrame[p].SetXY( BONUS_FRAME_X[p], BONUS_FRAME_Y ); - this->AddSubActor( &m_BonusInfoFrame[p] ); - m_bNewRecord[p] = false; if( m_bNewRecord[p] ) @@ -574,6 +602,12 @@ void ScreenEvaluation::TweenOnScreen() m_BonusInfoFrame[p].BeginTweeningQueued( MENU_ELEMENTS_TWEEN_TIME, Actor::TWEEN_BIAS_BEGIN ); m_BonusInfoFrame[p].SetTweenX( fOriginalX ); + fOriginalX = m_StageBox[p].GetX(); + m_StageBox[p].SetX( fOriginalX + SCREEN_WIDTH/2*(p==PLAYER_1 ? 1 : -1) ); + m_StageBox[p].BeginTweeningQueued( 0.2f + 0.1f*i ); + m_StageBox[p].BeginTweeningQueued( MENU_ELEMENTS_TWEEN_TIME, Actor::TWEEN_BIAS_BEGIN ); + m_StageBox[p].SetTweenX( fOriginalX ); + m_sprGradeFrame[p].BeginTweening( MENU_ELEMENTS_TWEEN_TIME ); m_sprGradeFrame[p].SetTweenZoomY( 0 ); @@ -634,6 +668,9 @@ void ScreenEvaluation::TweenOffScreen() m_BonusInfoFrame[p].BeginTweeningQueued( MENU_ELEMENTS_TWEEN_TIME, Actor::TWEEN_BIAS_END ); m_BonusInfoFrame[p].SetTweenZoomY( 0 ); + m_StageBox[p].BeginTweeningQueued( MENU_ELEMENTS_TWEEN_TIME, Actor::TWEEN_BIAS_END ); + m_StageBox[p].SetTweenZoomY( 0 ); + m_sprGradeFrame[p].BeginTweening( MENU_ELEMENTS_TWEEN_TIME ); m_sprGradeFrame[p].SetTweenZoomY( 0 ); @@ -704,7 +741,7 @@ void ScreenEvaluation::MenuStart( const PlayerNumber p ) if( PREFSMAN->m_bEventMode ) { - GAMESTATE->m_iCurrentStageIndex++; +// GAMESTATE->m_iCurrentStageIndex++; m_Menu.TweenOffScreenToMenu( SM_GoToSelectMusic ); return; } @@ -717,7 +754,7 @@ void ScreenEvaluation::MenuStart( const PlayerNumber p ) case RM_ARCADE_STAGE: if( m_bTryExtraStage ) { - GAMESTATE->m_iCurrentStageIndex++; +// GAMESTATE->m_iCurrentStageIndex++; m_Menu.TweenOffScreenToMenu( SM_GoToSelectMusic ); } else if( @@ -729,7 +766,7 @@ void ScreenEvaluation::MenuStart( const PlayerNumber p ) } else { - GAMESTATE->m_iCurrentStageIndex++; +// GAMESTATE->m_iCurrentStageIndex++; m_Menu.TweenOffScreenToMenu( SM_GoToSelectMusic ); } diff --git a/stepmania/src/ScreenEvaluation.h b/stepmania/src/ScreenEvaluation.h index a65efdab38..be6ee3be41 100644 --- a/stepmania/src/ScreenEvaluation.h +++ b/stepmania/src/ScreenEvaluation.h @@ -19,6 +19,7 @@ #include "Banner.h" #include "ScoreDisplayNormal.h" #include "BonusInfoFrame.h" +#include "StageBox.h" #include "BannerWithFrame.h" @@ -51,7 +52,8 @@ protected: GradeDisplay m_Grades[NUM_PLAYERS]; BitmapText m_textOniPercent[NUM_PLAYERS]; - BonusInfoFrame m_BonusInfoFrame[NUM_PLAYERS]; + BonusInfoFrame m_BonusInfoFrame[NUM_PLAYERS]; // used in arcade + StageBox m_StageBox[NUM_PLAYERS]; // used in Oni Sprite m_sprJudgeLabels[NUM_JUDGE_LINES]; BitmapText m_textJudgeNumbers[NUM_JUDGE_LINES][NUM_PLAYERS]; diff --git a/stepmania/src/ScreenGameplay.cpp b/stepmania/src/ScreenGameplay.cpp index e13f491cdd..d34b8865d3 100644 --- a/stepmania/src/ScreenGameplay.cpp +++ b/stepmania/src/ScreenGameplay.cpp @@ -83,42 +83,51 @@ ScreenGameplay::ScreenGameplay() { LOG->WriteLine( "ScreenGameplay::ScreenGameplay()" ); - m_bAutoPlayerWasOn = PREFSMAN->m_bAutoPlay; - m_bChangedOffsetOrBPM = false; - switch( GAMESTATE->m_PlayMode ) + GAMESTATE->ResetStageStatistics(); // clear values + // Update possible dance points + for( int p=0; pIsPlayerEnabled(p) ) + continue; // skip + + NoteData notedata; + switch( GAMESTATE->m_PlayMode ) { - m_apSongQueue.Add( GAMESTATE->m_pCurSong ); - for( int p=0; pm_pCurNotes[p] ); - } - break; - case PLAY_MODE_ONI: - { - Course* pCourse = GAMESTATE->m_pCurCourse; - ASSERT( pCourse != NULL ); - - m_apSongQueue.RemoveAll(); - for( int p=0; pGetSongAndNotesForCurrentStyle( m_apSongQueue, m_apNotesQueue ); - - // store possible dance points in GAMESTATE - GAMESTATE->m_iCoursePossibleDancePoints = 0; - for( int i=0; im_pCurNotes[p]->GetNoteData( ¬edata ); + GAMESTATE->m_iPossibleDancePoints[p] = notedata.GetPossibleDancePoints(); + break; + case PLAY_MODE_ENDLESS: + GAMESTATE->m_iPossibleDancePoints[p] = -1; + break; + case PLAY_MODE_ONI: { - NoteData nd; - m_apNotesQueue[PLAYER_1][i]->GetNoteData( &nd ); - GAMESTATE->m_iCoursePossibleDancePoints += nd.GetPossibleDancePoints(); + GAMESTATE->m_iPossibleDancePoints[p] = 0; + + Course* pCourse = GAMESTATE->m_pCurCourse; + CArray apSongs; + CArray apNotes[NUM_PLAYERS]; + pCourse->GetSongAndNotesForCurrentStyle( apSongs, apNotes ); + + for( int i=0; iGetNoteData( ¬edata ); + int iPossibleDancePoints = notedata.GetPossibleDancePoints(); + GAMESTATE->m_iPossibleDancePoints[p] += iPossibleDancePoints; + } } + break; } - break; + } + + GAMESTATE->m_bUsedAutoPlayer &= PREFSMAN->m_bAutoPlay; + m_bChangedOffsetOrBPM = false; + + m_DancingState = STATE_INTRO; m_fTimeLeftBeforeDancingComment = TIME_BETWEEN_DANCING_COMMENTS; @@ -128,7 +137,7 @@ ScreenGameplay::ScreenGameplay() - for( int p=0; pIsPlayerEnabled(PlayerNumber(p)) ) continue; @@ -145,19 +154,19 @@ ScreenGameplay::ScreenGameplay() for( p=0; pm_PlayMode ) + switch( GAMESTATE->m_SongOptions.m_LifeType ) { - case PLAY_MODE_ARCADE: + case SongOptions::LIFE_BAR: m_pLifeMeter[p] = new LifeMeterBar; break; - case PLAY_MODE_ONI: + case SongOptions::LIFE_BATTERY: m_pLifeMeter[p] = new LifeMeterBattery; break; default: ASSERT(0); } - m_pLifeMeter[p]->Load( (PlayerNumber)p, GAMESTATE->m_PlayerOptions[p] ); + m_pLifeMeter[p]->Load( (PlayerNumber)p ); m_pLifeMeter[p]->SetXY( LIFE_LOCAL_X[p], LIFE_LOCAL_Y[p] ); m_frameTop.AddSubActor( m_pLifeMeter[p] ); @@ -220,6 +229,7 @@ ScreenGameplay::ScreenGameplay() switch( GAMESTATE->m_PlayMode ) { case PLAY_MODE_ARCADE: + case PLAY_MODE_ENDLESS: m_pScoreDisplay[p] = new ScoreDisplayNormal; break; case PLAY_MODE_ONI: @@ -229,7 +239,7 @@ ScreenGameplay::ScreenGameplay() ASSERT(0); } - m_pScoreDisplay[p]->Init( (PlayerNumber)p, GAMESTATE->m_PlayerOptions[p], 100, 7 ); + m_pScoreDisplay[p]->Init( (PlayerNumber)p ); m_pScoreDisplay[p]->SetXY( SCORE_LOCAL_X[p], SCORE_LOCAL_Y[p] ); m_pScoreDisplay[p]->SetZoom( 0.8f ); m_pScoreDisplay[p]->SetDiffuseColor( PlayerToColor(p) ); @@ -350,7 +360,7 @@ ScreenGameplay::ScreenGameplay() m_soundAssistTick.Load( THEME->GetPathTo(SOUND_GAMEPLAY_ASSIST_TICK) ); - LoadNextSong( false ); + LoadNextSong( true ); // Send some messages every have second to we can get the introduction rolling for( int i=0; i<30; i++ ) @@ -370,37 +380,62 @@ ScreenGameplay::~ScreenGameplay() m_soundMusic.Stop(); } - -void ScreenGameplay::LoadNextSong( bool bPlayMusic ) +bool ScreenGameplay::IsLastSong() { - if( m_apSongQueue.GetSize() == 0 ) + switch( GAMESTATE->m_PlayMode ) { - this->SendScreenMessage( SM_LastNotesEnded, 0 ); - return; + case PLAY_MODE_ARCADE: + return true; + case PLAY_MODE_ONI: + case PLAY_MODE_ENDLESS: + { + Course* pCourse = GAMESTATE->m_pCurCourse; + CArray apSongs; + CArray apNotes[NUM_PLAYERS]; + pCourse->GetSongAndNotesForCurrentStyle( apSongs, apNotes ); + + return GAMESTATE->m_iCurrentStageIndex >= apSongs.GetSize(); // there are no more songs left + } + break; + default: + ASSERT(0); + return true; + } +} + +void ScreenGameplay::LoadNextSong( bool bFirstLoad ) +{ + GAMESTATE->ResetMusicStatistics(); + + switch( GAMESTATE->m_PlayMode ) + { + case PLAY_MODE_ARCADE: + break; + case PLAY_MODE_ONI: + case PLAY_MODE_ENDLESS: + { + Course* pCourse = GAMESTATE->m_pCurCourse; + CArray apSongs; + CArray apNotes[NUM_PLAYERS]; + pCourse->GetSongAndNotesForCurrentStyle( apSongs, apNotes ); + + GAMESTATE->m_pCurSong = apSongs[GAMESTATE->m_iCurrentStageIndex]; + for( int p=0; pm_pCurNotes[p] = apNotes[p][GAMESTATE->m_iCurrentStageIndex]; + } + break; + default: + ASSERT(0); + break; } + m_textStageNumber.SetText( GAMESTATE->GetStageText() ); - int p; - // add a new GameplayStatistic for this song - GAMESTATE->m_aGameplayStatistics.Add( GameplayStatistics() ); - GAMESTATE->m_pCurSong = m_apSongQueue[0]; - m_apSongQueue.RemoveAt(0); - - for( p=0; pm_pCurNotes[p] = m_apNotesQueue[p][0]; - m_apNotesQueue[p].RemoveAt(0); - } - - - // Get the current StyleDef definition (used below) - StyleDef* pStyleDef = GAMESTATE->GetCurrentStyleDef(); - - for( p=0; pIsPlayerEnabled(PlayerNumber(p)) ) + if( !GAMESTATE->IsPlayerEnabled(p) ) continue; m_DifficultyBanner[p].SetFromNotes( PlayerNumber(p), GAMESTATE->m_pCurNotes[p] ); @@ -409,27 +444,11 @@ void ScreenGameplay::LoadNextSong( bool bPlayMusic ) NoteData originalNoteData; GAMESTATE->m_pCurNotes[p]->GetNoteData( &originalNoteData ); + StyleDef* pStyleDef = GAMESTATE->GetCurrentStyleDef(); NoteData newNoteData; pStyleDef->GetTransformedNoteDataForStyle( (PlayerNumber)p, &originalNoteData, &newNoteData ); - - // Fill in info about these notes in the latest GameplayStatistics - GAMESTATE->GetLatestGameplayStatistics().dc[p] = GAMESTATE->m_pCurNotes[p]->m_DifficultyClass; - GAMESTATE->GetLatestGameplayStatistics().meter[p] = GAMESTATE->m_pCurNotes[p]->m_iMeter; - GAMESTATE->GetLatestGameplayStatistics().iPossibleDancePoints[p] = newNoteData.GetPossibleDancePoints(); - for( int r=0; rGetLatestGameplayStatistics().fRadarPossible[p][r] = newNoteData.GetRadarValue( (RadarCategory)r, GAMESTATE->m_pCurSong->m_fMusicLengthSeconds ); - - m_Player[p].Load( - (PlayerNumber)p, - GAMESTATE->GetCurrentStyleDef(), - &newNoteData, - GAMESTATE->m_PlayerOptions[p], - m_pLifeMeter[p], - m_pScoreDisplay[p], - originalNoteData.GetNumTapNotes(), - GAMESTATE->m_pCurNotes[p]->m_iMeter - ); + m_Player[p].Load( (PlayerNumber)p, &newNoteData, m_pLifeMeter[p], m_pScoreDisplay[p] ); } @@ -442,13 +461,8 @@ void ScreenGameplay::LoadNextSong( bool bPlayMusic ) float fStartSeconds = min( 0, -4+GAMESTATE->m_pCurSong->GetElapsedTimeFromBeat(GAMESTATE->m_pCurSong->m_fFirstBeat) ); m_soundMusic.SetPositionSeconds( fStartSeconds ); m_soundMusic.SetPlaybackRate( GAMESTATE->m_SongOptions.m_fMusicRate ); - if( bPlayMusic ) + if( !bFirstLoad ) m_soundMusic.Play(); - - if( bPlayMusic ) - for( int p=0; pIsPlayerEnabled(PlayerNumber(p)) ) - m_pLifeMeter[p]->NextSong( NULL ); } bool ScreenGameplay::OneIsHot() @@ -507,30 +521,15 @@ void ScreenGameplay::Update( float fDeltaTime ) // update the global music statistics for other classes to access GAMESTATE->m_fMusicSeconds = fPositionSeconds; - GAMESTATE->m_fMusicBeat = fSongBeat; + GAMESTATE->m_fSongBeat = fSongBeat; GAMESTATE->m_fCurBPS = fBPS; GAMESTATE->m_bFreeze = bFreeze; m_Background.SetSongBeat( fSongBeat, bFreeze, fPositionSeconds ); - //LOG->WriteLine( "m_fOffsetInBeats = %f, m_fBeatsPerSecond = %f, m_Music.GetPositionSeconds = %f", m_fOffsetInBeats, m_fBeatsPerSecond, m_Music.GetPositionSeconds() ); - const float fMaxBeatDifference = fBPS * PREFSMAN->m_fJudgeWindow * GAMESTATE->m_SongOptions.m_fMusicRate; - - for( int p=0; pIsPlayerEnabled(PlayerNumber(p)) ) - continue; - m_Player[p].Update( fDeltaTime, fSongBeat, fMaxBeatDifference ); - } - - // update seconds into play - for( p=0; pIsPlayerEnabled((PlayerNumber)p) && !m_pLifeMeter[p]->FailedEarlier() ) - GAMESTATE->GetLatestGameplayStatistics().fSecsIntoPlay[p] = max( GAMESTATE->GetLatestGameplayStatistics().fSecsIntoPlay[p], GAMESTATE->m_fMusicSeconds ); - switch( m_DancingState ) { @@ -586,16 +585,16 @@ void ScreenGameplay::Update( float fDeltaTime ) // Send crossed row messages to Player // int iRowNow = BeatToNoteRowNotRounded( fSongBeat ); + CLAMP( iRowNow, 0, MAX_TAP_NOTE_ROWS-1 ); static int iRowLastCrossed = 0; + CLAMP( iRowLastCrossed, 0, MAX_TAP_NOTE_ROWS-1 ); for( int r=iRowLastCrossed+1; r<=iRowNow; r++ ) // for each index we crossed since the last update { for( int p=0; pIsPlayerEnabled( (PlayerNumber)p ) ) - continue; // skip - - m_Player[p].CrossedRow( r, fSongBeat, fMaxBeatDifference ); + if( GAMESTATE->IsPlayerEnabled(p) ) + m_Player[p].CrossedRow( r ); } } @@ -626,7 +625,7 @@ void ScreenGameplay::Update( float fDeltaTime ) if( !GAMESTATE->IsPlayerEnabled( (PlayerNumber)p ) ) continue; // skip - m_Player[p].CrossedRow( r, fSongBeat, fMaxBeatDifference ); + m_Player[p].CrossedRow( r ); bAnyoneHasANote |= m_Player[p].IsThereANoteAtRow( r ); break; // this will only play the tick for the first player that is joined } @@ -663,7 +662,7 @@ void ScreenGameplay::Input( const DeviceInput& DeviceI, const InputEventType typ { case DIK_F8: PREFSMAN->m_bAutoPlay = !PREFSMAN->m_bAutoPlay; - m_bAutoPlayerWasOn &= PREFSMAN->m_bAutoPlay; + GAMESTATE->m_bUsedAutoPlayer &= PREFSMAN->m_bAutoPlay; m_textDebug.SetText( ssprintf("Autoplayer %s.", (PREFSMAN->m_bAutoPlay ? "ON" : "OFF")) ); m_textDebug.SetDiffuseColor( D3DXCOLOR(1,1,1,1) ); m_textDebug.StopTweening(); @@ -725,8 +724,13 @@ void ScreenGameplay::Input( const DeviceInput& DeviceI, const InputEventType typ } } - if( MenuI.IsValid() && MenuI.button == MENU_BUTTON_BACK && type == IET_SLOW_REPEAT ) + if( MenuI.IsValid() && + MenuI.button == MENU_BUTTON_BACK && + type == IET_SLOW_REPEAT && + m_DancingState != STATE_OUTRO && + !m_Fade.IsClosing() ) { + SOUND->PlayOnceStreamed( THEME->GetPathTo(SOUND_MENU_BACK) ); m_soundMusic.Stop(); this->ClearMessageQueue(); m_Fade.CloseWipingLeft( SM_GoToScreenAfterBack ); @@ -744,7 +748,7 @@ void ScreenGameplay::Input( const DeviceInput& DeviceI, const InputEventType typ if( StyleI.IsValid() ) { if( GAMESTATE->IsPlayerEnabled( StyleI.player ) ) - m_Player[StyleI.player].HandlePlayerStep( fSongBeat, StyleI.col, fMaxBeatDifference ); + m_Player[StyleI.player].Step( StyleI.col ); } } } @@ -752,16 +756,75 @@ void ScreenGameplay::Input( const DeviceInput& DeviceI, const InputEventType typ void SaveChanges( void* pContext ) { - GAMESTATE->m_pCurSong->SaveToSMFile(); + switch( GAMESTATE->m_PlayMode ) + { + case PLAY_MODE_ARCADE: + GAMESTATE->m_pCurSong->SaveToSMFile(); + break; + case PLAY_MODE_ONI: + case PLAY_MODE_ENDLESS: + { + for( int i=0; im_pCurCourse->m_iStages; i++ ) + { + Song* pSong = GAMESTATE->m_pCurCourse->m_apSongs[i]; + pSong->SaveToSMFile(); + } + } + break; + default: + ASSERT(0); + } } void DontSaveChanges( void* pContext ) { - GAMESTATE->m_pCurSong->LoadFromSMFile( GAMESTATE->m_pCurSong->GetCacheFilePath() ); + switch( GAMESTATE->m_PlayMode ) + { + case PLAY_MODE_ARCADE: + GAMESTATE->m_pCurSong->LoadFromSMFile( GAMESTATE->m_pCurSong->GetCacheFilePath() ); + break; + case PLAY_MODE_ONI: + case PLAY_MODE_ENDLESS: + { + for( int i=0; im_pCurCourse->m_iStages; i++ ) + { + Song* pSong = GAMESTATE->m_pCurCourse->m_apSongs[i]; + pSong->LoadFromSMFile( GAMESTATE->m_pCurSong->GetCacheFilePath() ); + } + } + break; + default: + ASSERT(0); + } } void ShowSavePrompt( ScreenMessage SM_SendWhenDone ) { + CString sMessage; + switch( GAMESTATE->m_PlayMode ) + { + case PLAY_MODE_ARCADE: + sMessage = ssprintf( + "You have changed the offset or BPM of\n" + "%s.\n" + "Would you like to save these changes back\n" + "to the song file?\n" + "Choosing NO will disgard your changes.", + GAMESTATE->m_pCurSong->GetFullTitle() ); + break; + case PLAY_MODE_ONI: + case PLAY_MODE_ENDLESS: + sMessage = ssprintf( + "You have changed the offset or BPM of\n" + "one or more songs in this course.\n" + "Would you like to save these changes back\n" + "to the song file(s)?\n" + "Choosing NO will disgard your changes." ); + break; + default: + ASSERT(0); + } + SCREENMAN->AddScreenToTop( new ScreenPrompt( SM_SendWhenDone, ssprintf( @@ -820,28 +883,48 @@ void ScreenGameplay::HandleScreenMessage( const ScreenMessage SM ) // received while STATE_DANCING case SM_NotesEnded: { + // save any statistics for( int p=0; pIsPlayerEnabled( (PlayerNumber)p ) ) - m_Player[p].SaveGameplayStatistics(); - GAMESTATE->GetLatestGameplayStatistics().bAutoPlayerWasOn = m_bAutoPlayerWasOn; - LoadNextSong( true ); - } - break; - case SM_LastNotesEnded: - { - if( m_DancingState == STATE_OUTRO ) // gameplay already ended - return; // ignore - - m_DancingState = STATE_OUTRO; - - if( GAMESTATE->m_SongOptions.m_FailType == SongOptions::FAIL_END_OF_SONG && AllFailedEarlier() ) { - this->SendScreenMessage( SM_BeginFailed, 0 ); + if( GAMESTATE->IsPlayerEnabled(p) ) + { + m_pLifeMeter[p]->SongEnded(); // let the oni life meter give them back a life + + for( int r=0; rm_fRadarPossible[p][r] = m_Player[p].GetRadarValue( rc, GAMESTATE->m_pCurSong->m_fMusicLengthSeconds ); + GAMESTATE->m_fRadarActual[p][r] = m_Player[p].GetActualRadarValue( rc, GAMESTATE->m_pCurSong->m_fMusicLengthSeconds ); + } + } } - else + + GAMESTATE->m_apSongsPlayed.Add( GAMESTATE->m_pCurSong ); + + GAMESTATE->m_iCurrentStageIndex++; + + if( !IsLastSong() ) { - m_StarWipe.CloseWipingRight( SM_ShowCleared ); - m_announcerCleared.PlayRandom(); // crowd cheer + LoadNextSong( false ); + } + else // IsLastSong + { + if( m_DancingState == STATE_OUTRO ) // gameplay already ended + return; // ignore + + m_DancingState = STATE_OUTRO; + + GAMESTATE->AccumulateStageStatistics(); // accumulate values for final evaluation + + if( GAMESTATE->m_SongOptions.m_FailType == SongOptions::FAIL_END_OF_SONG && AllFailedEarlier() ) + { + this->SendScreenMessage( SM_BeginFailed, 0 ); + } + else + { + m_StarWipe.CloseWipingRight( SM_ShowCleared ); + m_announcerCleared.PlayRandom(); // crowd cheer + } } } break; diff --git a/stepmania/src/ScreenGameplay.h b/stepmania/src/ScreenGameplay.h index 1cd9270be2..2158119708 100644 --- a/stepmania/src/ScreenGameplay.h +++ b/stepmania/src/ScreenGameplay.h @@ -56,7 +56,8 @@ private: void TweenOnScreen(); void TweenOffScreen(); - void LoadNextSong( bool bPlayMusic ); + bool IsLastSong(); + void LoadNextSong( bool bFirstLoad ); bool OneIsHot(); bool AllAreInDanger(); @@ -70,12 +71,8 @@ private: NUM_DANCING_STATES }; DancingState m_DancingState; - bool m_bAutoPlayerWasOn; bool m_bChangedOffsetOrBPM; - CArray m_apSongQueue; // nearest songs are on back of queue - CArray m_apNotesQueue[NUM_PLAYERS]; // nearest notes are on back of queue - float m_fTimeLeftBeforeDancingComment; // this counter is only running while STATE_DANCING diff --git a/stepmania/src/ScreenMusicScroll.cpp b/stepmania/src/ScreenMusicScroll.cpp index 860b70c8ac..4d0740318f 100644 --- a/stepmania/src/ScreenMusicScroll.cpp +++ b/stepmania/src/ScreenMusicScroll.cpp @@ -114,8 +114,7 @@ const CString CREDIT_LINES[] = "", "", "", - "Please, join the StepMania team and help us out!" - " -Chris" + "Please, join the StepMania team and help us out!", }; const int NUM_CREDIT_LINES = sizeof(CREDIT_LINES) / sizeof(CString); diff --git a/stepmania/src/ScreenSelectCourse.cpp b/stepmania/src/ScreenSelectCourse.cpp index 576178e4c5..d0747ee342 100644 --- a/stepmania/src/ScreenSelectCourse.cpp +++ b/stepmania/src/ScreenSelectCourse.cpp @@ -151,6 +151,9 @@ void ScreenSelectCourse::Input( const DeviceInput& DeviceI, const InputEventType return; } + if( m_bMadeChoice ) + return; + Screen::Input( DeviceI, type, GameI, MenuI, StyleI ); // default input handler } @@ -235,7 +238,11 @@ void ScreenSelectCourse::MenuStart( const PlayerNumber p ) m_Menu.TweenOffScreenToBlack( SM_None, false ); - GAMESTATE->m_pCurCourse = m_MusicWheel.GetSelectedCourse(); + Course* pCourse = m_MusicWheel.GetSelectedCourse(); + GAMESTATE->m_pCurCourse = pCourse; + for( int p=0; pGetPlayerOptions( &GAMESTATE->m_PlayerOptions[p] ); + pCourse->GetSongOptions( &GAMESTATE->m_SongOptions ); this->SendScreenMessage( SM_GoToNextState, 2.5f ); diff --git a/stepmania/src/ScreenSelectDifficulty.cpp b/stepmania/src/ScreenSelectDifficulty.cpp index d7797e7d90..3aa578a44f 100644 --- a/stepmania/src/ScreenSelectDifficulty.cpp +++ b/stepmania/src/ScreenSelectDifficulty.cpp @@ -63,9 +63,10 @@ const float DIFFICULTY_ARROW_X[NUM_DIFFICULTY_ITEMS][NUM_PLAYERS] = { }; - const float ARROW_SHADOW_OFFSET = 10; +const float LOCK_INPUT_TIME = 0.75f; // lock input while waiting for tweening to complete + const ScreenMessage SM_GoToPrevState = ScreenMessage(SM_User + 1); const ScreenMessage SM_GoToNextState = ScreenMessage(SM_User + 2); @@ -176,6 +177,8 @@ ScreenSelectDifficulty::ScreenSelectDifficulty() m_Menu.TweenOnScreenFromMenu( SM_None ); TweenOnScreen(); + + m_fLockInputTime = LOCK_INPUT_TIME; } @@ -193,9 +196,18 @@ void ScreenSelectDifficulty::Input( const DeviceInput& DeviceI, const InputEvent if( m_Menu.IsClosing() ) return; + if( m_fLockInputTime > 0 ) + return; + Screen::Input( DeviceI, type, GameI, MenuI, StyleI ); // default input handler } +void ScreenSelectDifficulty::Update( float fDeltaTime ) +{ + Screen::Update( fDeltaTime ); + m_fLockInputTime = max( m_fLockInputTime-fDeltaTime, 0 ); +} + void ScreenSelectDifficulty::DrawPrimitives() { m_Menu.DrawBottomLayer(); diff --git a/stepmania/src/ScreenSelectDifficulty.h b/stepmania/src/ScreenSelectDifficulty.h index 825efd4af7..afb801cd7c 100644 --- a/stepmania/src/ScreenSelectDifficulty.h +++ b/stepmania/src/ScreenSelectDifficulty.h @@ -26,6 +26,7 @@ public: ScreenSelectDifficulty(); virtual ~ScreenSelectDifficulty(); + virtual void Update( float fDeltaTime ); virtual void DrawPrimitives(); virtual void Input( const DeviceInput& DeviceI, const InputEventType type, const GameInput &GameI, const MenuInput &MenuI, const StyleInput &StyleI ); virtual void HandleScreenMessage( const ScreenMessage SM ); @@ -64,6 +65,8 @@ private: int m_iSelection[NUM_PLAYERS]; bool m_bChosen[NUM_PLAYERS]; + + float m_fLockInputTime; }; diff --git a/stepmania/src/ScreenSelectMusic.cpp b/stepmania/src/ScreenSelectMusic.cpp index e1b737c6e9..20edcc99a6 100644 --- a/stepmania/src/ScreenSelectMusic.cpp +++ b/stepmania/src/ScreenSelectMusic.cpp @@ -338,6 +338,8 @@ void ScreenSelectMusic::MenuLeft( const PlayerNumber p, const InputEventType typ if( type >= IET_SLOW_REPEAT && INPUTMAPPER->IsButtonDown( MenuInput(p, MENU_BUTTON_RIGHT) ) ) return; // ignore + MUSIC->Stop(); + m_MusicWheel.PrevMusic(); } @@ -347,6 +349,8 @@ void ScreenSelectMusic::MenuRight( const PlayerNumber p, const InputEventType ty if( type >= IET_SLOW_REPEAT && INPUTMAPPER->IsButtonDown( MenuInput(p, MENU_BUTTON_LEFT) ) ) return; // ignore + MUSIC->Stop(); + m_MusicWheel.NextMusic(); } diff --git a/stepmania/src/ScreenStage.cpp b/stepmania/src/ScreenStage.cpp index b8d5b6ad2a..33997b6ddf 100644 --- a/stepmania/src/ScreenStage.cpp +++ b/stepmania/src/ScreenStage.cpp @@ -34,6 +34,8 @@ const ScreenMessage SM_GoToNextState = ScreenMessage(SM_User + 3); ScreenStage::ScreenStage() { + MUSIC->Stop(); + m_pNextScreen = NULL; m_textStage.Load( THEME->GetPathTo(FONT_STAGE) ); diff --git a/stepmania/src/SongManager.h b/stepmania/src/SongManager.h index 269f66cf0d..dadc23f1d4 100644 --- a/stepmania/src/SongManager.h +++ b/stepmania/src/SongManager.h @@ -14,7 +14,6 @@ #include "Song.h" #include "Course.h" -#include "GameplayStatistics.h" //#include // for D3DXCOLOR const int MAX_SONG_QUEUE_SIZE = 400; // this has to be gigantic to fit an "endless" number of songs diff --git a/stepmania/src/SongOptions.h b/stepmania/src/SongOptions.h index f8e9bdce05..9fb7bd059e 100644 --- a/stepmania/src/SongOptions.h +++ b/stepmania/src/SongOptions.h @@ -14,7 +14,7 @@ struct SongOptions { - enum LifeType { LIFE_BAR_NORMAL=0, LIFE_BATTERY }; + enum LifeType { LIFE_BAR=0, LIFE_BATTERY }; LifeType m_LifeType; enum DrainType { DRAIN_NORMAL, DRAIN_NO_RECOVER, DRAIN_SUDDEN_DEATH }; DrainType m_DrainType; // only used with LifeBar @@ -26,7 +26,8 @@ struct SongOptions float m_fMusicRate; SongOptions() { - m_LifeType = LIFE_BAR_NORMAL; + m_LifeType = LIFE_BAR; + m_DrainType = DRAIN_NORMAL; m_iBatteryLives = 4; m_FailType = FAIL_ARCADE; m_AssistType = ASSIST_NONE; diff --git a/stepmania/src/StageBox.cpp b/stepmania/src/StageBox.cpp new file mode 100644 index 0000000000..6be6ea2262 --- /dev/null +++ b/stepmania/src/StageBox.cpp @@ -0,0 +1,55 @@ +#include "stdafx.h" +/* +----------------------------------------------------------------------------- + Class: StageBox + + Desc: See header. + + Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved. + Chris Danford +----------------------------------------------------------------------------- +*/ + +#include "StageBox.h" +#include "RageUtil.h" +#include "GameConstantsAndTypes.h" +#include "PrefsManager.h" +#include "RageLog.h" + +const float NUMBER_X = 16; +const float NUMBER_Y = 24; + +const float ST_X = NUMBER_X+4; +const float ST_Y = NUMBER_Y; + + +StageBox::StageBox() +{ + this->AddSubActor( &m_sprBox ); + + m_textNumber.Load( THEME->GetPathTo(FONT_HEADER1) ); + m_textNumber.TurnShadowOff(); + m_textNumber.SetHorizAlign( Actor::align_right ); + m_textNumber.SetVertAlign( Actor::align_top ); + m_textNumber.SetZoom( 2.0f ); + m_textNumber.SetXY( NUMBER_X, NUMBER_Y ); + this->AddSubActor( &m_textNumber ); + + m_textST.Load( THEME->GetPathTo(FONT_HEADER1) ); + m_textST.TurnShadowOff(); + m_textST.SetHorizAlign( Actor::align_left ); + m_textST.SetVertAlign( Actor::align_top ); + m_textST.SetZoom( 1 ); + m_textST.SetXY( ST_X, ST_Y ); + this->AddSubActor( &m_textST ); +} + +void StageBox::SetStageInfo( PlayerNumber p, int iNumStagesCompleted ) +{ + m_sprBox.Load( THEME->GetPathTo(p==PLAYER_1 ? GRAPHIC_EVALUATION_STAGE_FRAME_P1 : GRAPHIC_EVALUATION_STAGE_FRAME_P2) ); + m_sprBox.StopAnimating(); + + m_textNumber.SetText( ssprintf("%2d", iNumStagesCompleted) ); + + m_textST.SetText( "ST." ); +} diff --git a/stepmania/src/StageBox.h b/stepmania/src/StageBox.h new file mode 100644 index 0000000000..37f025253a --- /dev/null +++ b/stepmania/src/StageBox.h @@ -0,0 +1,33 @@ +#pragma once +/* +----------------------------------------------------------------------------- + Class: StageBox + + Desc: bonus meters and max combo number. + + Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved. + Chris Danford +----------------------------------------------------------------------------- +*/ + +#include "ActorFrame.h" +#include "Sprite.h" +#include "BitmapText.h" +#include "Quad.h" +#include "GameConstantsAndTypes.h" + + +class StageBox : public ActorFrame +{ +public: + StageBox(); + + void SetStageInfo( PlayerNumber p, int iNumStagesCompleted ); + +protected: + + Sprite m_sprBox; + BitmapText m_textTime; + BitmapText m_textNumber; + BitmapText m_textST; +}; diff --git a/stepmania/src/StepMania.dsp b/stepmania/src/StepMania.dsp index 38ab5c8dd1..da2db7d5d6 100644 --- a/stepmania/src/StepMania.dsp +++ b/stepmania/src/StepMania.dsp @@ -248,14 +248,6 @@ SOURCE=.\GameInput.h # End Source File # Begin Source File -SOURCE=.\GameplayStatistics.cpp -# End Source File -# Begin Source File - -SOURCE=.\GameplayStatistics.h -# End Source File -# Begin Source File - SOURCE=.\GameTypes.h # End Source File # Begin Source File @@ -688,6 +680,14 @@ SOURCE=.\SongInfoFrame.h # End Source File # Begin Source File +SOURCE=.\StageBox.cpp +# End Source File +# Begin Source File + +SOURCE=.\StageBox.h +# End Source File +# Begin Source File + SOURCE=.\TextBanner.cpp # End Source File # Begin Source File diff --git a/stepmania/src/StepMania.vcproj b/stepmania/src/StepMania.vcproj index 31c8828e97..8f6d857e17 100644 --- a/stepmania/src/StepMania.vcproj +++ b/stepmania/src/StepMania.vcproj @@ -357,12 +357,6 @@ - - - - @@ -658,6 +652,12 @@ + + + + diff --git a/stepmania/src/ThemeManager.cpp b/stepmania/src/ThemeManager.cpp index e43469dc20..db0efe4c68 100644 --- a/stepmania/src/ThemeManager.cpp +++ b/stepmania/src/ThemeManager.cpp @@ -144,6 +144,8 @@ CString ThemeManager::GetPathTo( ThemeElement te, CString sThemeName ) case GRAPHIC_EVALUATION_BANNER_FRAME: sAssetPrefix = "Graphics\\evaluation banner frame"; break; case GRAPHIC_EVALUATION_BONUS_FRAME_P1: sAssetPrefix = "Graphics\\evaluation bonus frame p1"; break; case GRAPHIC_EVALUATION_BONUS_FRAME_P2: sAssetPrefix = "Graphics\\evaluation bonus frame p2"; break; + case GRAPHIC_EVALUATION_STAGE_FRAME_P1: sAssetPrefix = "Graphics\\evaluation stage frame p1"; break; + case GRAPHIC_EVALUATION_STAGE_FRAME_P2: sAssetPrefix = "Graphics\\evaluation stage frame p2"; break; case GRAPHIC_EVALUATION_GRADE_FRAME: sAssetPrefix = "Graphics\\evaluation grade frame 1x2"; break; case GRAPHIC_EVALUATION_GRADES: sAssetPrefix = "Graphics\\evaluation grades 1x7"; break; case GRAPHIC_EVALUATION_JUDGE_LABELS: sAssetPrefix = "Graphics\\evaluation judge labels 1x6"; break; diff --git a/stepmania/src/ThemeManager.h b/stepmania/src/ThemeManager.h index fa6bb02824..2cd871eb31 100644 --- a/stepmania/src/ThemeManager.h +++ b/stepmania/src/ThemeManager.h @@ -68,6 +68,8 @@ enum ThemeElement { GRAPHIC_EVALUATION_BANNER_FRAME, GRAPHIC_EVALUATION_BONUS_FRAME_P1, GRAPHIC_EVALUATION_BONUS_FRAME_P2, + GRAPHIC_EVALUATION_STAGE_FRAME_P1, + GRAPHIC_EVALUATION_STAGE_FRAME_P2, GRAPHIC_EVALUATION_GRADE_FRAME, GRAPHIC_EVALUATION_GRADES, GRAPHIC_EVALUATION_JUDGE_LABELS,