diff --git a/stepmania/src/ActiveAttackList.cpp b/stepmania/src/ActiveAttackList.cpp index 8e7abee4ef..db2656afed 100644 --- a/stepmania/src/ActiveAttackList.cpp +++ b/stepmania/src/ActiveAttackList.cpp @@ -4,23 +4,25 @@ #include "GameState.h" #include "Inventory.h" #include "RageTimer.h" +#include "PlayerOptions.h" +#include "PlayerState.h" ActiveAttackList::ActiveAttackList() { } -void ActiveAttackList::Init( PlayerNumber pn ) +void ActiveAttackList::Init( const PlayerState* pPlayerState ) { - m_PlayerNumber = pn; + m_pPlayerState = pPlayerState; } void ActiveAttackList::Update( float fDelta ) { bool bTimeToRefresh = IsFirstUpdate() || // check this before running Actor::Update() - GAMESTATE->m_bAttackBeganThisUpdate[m_PlayerNumber] || - GAMESTATE->m_bAttackEndedThisUpdate[m_PlayerNumber]; + m_pPlayerState->m_bAttackBeganThisUpdate || + m_pPlayerState->m_bAttackEndedThisUpdate; BitmapText::Update( fDelta ); @@ -32,7 +34,7 @@ void ActiveAttackList::Refresh() { CString s; - const AttackArray& attacks = GAMESTATE->m_ActiveAttacks[m_PlayerNumber]; // NUM_INVENTORY_SLOTS + const AttackArray& attacks = m_pPlayerState->m_ActiveAttacks; // clear all lines, then add all active attacks for( unsigned i=0; im_CurrentPlayerOptions[pn].m_fPerspectiveTilt)*200; + return SCREEN_HEIGHT + fabsf(pPlayerState->m_CurrentPlayerOptions.m_fPerspectiveTilt)*200; } /* For visibility testing: if bAbsolute is false, random modifiers must return the * minimum possible scroll speed. */ -float ArrowGetYOffset( PlayerNumber pn, int iCol, float fNoteBeat, bool bAbsolute ) +float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float fNoteBeat, bool bAbsolute ) { float fYOffset = 0; /* Usually, fTimeSpacing is 0 or 1, in which case we use entirely beat spacing or * entirely time spacing (respectively). Occasionally, we tween between them. */ - if( GAMESTATE->m_CurrentPlayerOptions[pn].m_fTimeSpacing != 1.0f ) + if( pPlayerState->m_CurrentPlayerOptions.m_fTimeSpacing != 1.0f ) { float fSongBeat = GAMESTATE->m_fSongBeat; float fBeatsUntilStep = fNoteBeat - fSongBeat; float fYOffsetBeatSpacing = fBeatsUntilStep * ARROW_SPACING; - fYOffset += fYOffsetBeatSpacing * (1-GAMESTATE->m_CurrentPlayerOptions[pn].m_fTimeSpacing); + fYOffset += fYOffsetBeatSpacing * (1-pPlayerState->m_CurrentPlayerOptions.m_fTimeSpacing); } - if( GAMESTATE->m_CurrentPlayerOptions[pn].m_fTimeSpacing != 0.0f ) + if( pPlayerState->m_CurrentPlayerOptions.m_fTimeSpacing != 0.0f ) { float fSongSeconds = GAMESTATE->m_fMusicSeconds; float fNoteSeconds = GAMESTATE->m_pCurSong->GetElapsedTimeFromBeat(fNoteBeat); float fSecondsUntilStep = fNoteSeconds - fSongSeconds; - float fBPM = GAMESTATE->m_CurrentPlayerOptions[pn].m_fScrollBPM; + float fBPM = pPlayerState->m_CurrentPlayerOptions.m_fScrollBPM; float fBPS = fBPM/60.f; float fYOffsetTimeSpacing = fSecondsUntilStep * fBPS * ARROW_SPACING; - fYOffset += fYOffsetTimeSpacing * GAMESTATE->m_CurrentPlayerOptions[pn].m_fTimeSpacing; + fYOffset += fYOffsetTimeSpacing * pPlayerState->m_CurrentPlayerOptions.m_fTimeSpacing; } // don't mess with the arrows after they've crossed 0 if( fYOffset < 0 ) - return fYOffset * GAMESTATE->m_CurrentPlayerOptions[pn].m_fScrollSpeed; + return fYOffset * pPlayerState->m_CurrentPlayerOptions.m_fScrollSpeed; - const float* fAccels = GAMESTATE->m_CurrentPlayerOptions[pn].m_fAccels; - //const float* fEffects = GAMESTATE->m_CurrentPlayerOptions[pn].m_fEffects; + const float* fAccels = pPlayerState->m_CurrentPlayerOptions.m_fAccels; + //const float* fEffects = pPlayerState->m_CurrentPlayerOptions.m_fEffects; float fYAdjust = 0; // fill this in depending on PlayerOptions if( fAccels[PlayerOptions::ACCEL_BOOST] > 0 ) { - float fEffectHeight = GetNoteFieldHeight(pn); + float fEffectHeight = GetNoteFieldHeight(pPlayerState); float fNewYOffset = fYOffset * 1.5f / ((fYOffset+fEffectHeight/1.2f)/fEffectHeight); float fAccelYAdjust = fAccels[PlayerOptions::ACCEL_BOOST] * (fNewYOffset - fYOffset); // TRICKY: Clamp this value, or else BOOST+BOOMERANG will draw a ton of arrows on the screen. @@ -68,7 +70,7 @@ float ArrowGetYOffset( PlayerNumber pn, int iCol, float fNoteBeat, bool bAbsolut } if( fAccels[PlayerOptions::ACCEL_BRAKE] > 0 ) { - float fEffectHeight = GetNoteFieldHeight(pn); + float fEffectHeight = GetNoteFieldHeight(pPlayerState); float fScale = SCALE( fYOffset, 0.f, fEffectHeight, 0, 1.f ); float fNewYOffset = fYOffset * fScale; float fBrakeYAdjust = fAccels[PlayerOptions::ACCEL_BRAKE] * (fNewYOffset - fYOffset); @@ -84,8 +86,8 @@ float ArrowGetYOffset( PlayerNumber pn, int iCol, float fNoteBeat, bool bAbsolut if( fAccels[PlayerOptions::ACCEL_BOOMERANG] > 0 ) fYOffset += fAccels[PlayerOptions::ACCEL_BOOMERANG] * (fYOffset * SCALE( fYOffset, 0.f, SCREEN_HEIGHT, 1.5f, 0.5f )- fYOffset); - float fScrollSpeed = GAMESTATE->m_CurrentPlayerOptions[pn].m_fScrollSpeed; - if( GAMESTATE->m_CurrentPlayerOptions[pn].m_fRandomSpeed > 0 && !bAbsolute ) + float fScrollSpeed = pPlayerState->m_CurrentPlayerOptions.m_fScrollSpeed; + if( pPlayerState->m_CurrentPlayerOptions.m_fRandomSpeed > 0 && !bAbsolute ) { int seed = GAMESTATE->m_iRoundSeed + ( BeatToNoteRow( fNoteBeat ) << 8 ) + (iCol * 100); @@ -99,7 +101,7 @@ float ArrowGetYOffset( PlayerNumber pn, int iCol, float fNoteBeat, bool bAbsolut fScrollSpeed *= SCALE( fRandom, 0.0f, 1.0f, - 1.0f, GAMESTATE->m_CurrentPlayerOptions[pn].m_fRandomSpeed + 1.0f ); + 1.0f, pPlayerState->m_CurrentPlayerOptions.m_fRandomSpeed + 1.0f ); } @@ -121,50 +123,50 @@ float ArrowGetYOffset( PlayerNumber pn, int iCol, float fNoteBeat, bool bAbsolut } -static void ArrowGetReverseShiftAndScale( PlayerNumber pn, int iCol, float fYReverseOffsetPixels, float &fShiftOut, float &fScaleOut ) +void ArrowGetReverseShiftAndScale( const PlayerState* pPlayerState, int iCol, float fYReverseOffsetPixels, float &fShiftOut, float &fScaleOut ) { /* XXX: Hack: we need to scale the reverse shift by the zoom. */ - float fMiniPercent = GAMESTATE->m_CurrentPlayerOptions[pn].m_fEffects[PlayerOptions::EFFECT_MINI]; + float fMiniPercent = pPlayerState->m_CurrentPlayerOptions.m_fEffects[PlayerOptions::EFFECT_MINI]; float fZoom = 1 - fMiniPercent*0.5f; - float fPercentReverse = GAMESTATE->m_CurrentPlayerOptions[pn].GetReversePercentForColumn(iCol); + float fPercentReverse = pPlayerState->m_CurrentPlayerOptions.GetReversePercentForColumn(iCol); fShiftOut = SCALE( fPercentReverse, 0.f, 1.f, -fYReverseOffsetPixels/fZoom/2, fYReverseOffsetPixels/fZoom/2 ); - float fPercentCentered = GAMESTATE->m_CurrentPlayerOptions[pn].m_fScrolls[PlayerOptions::SCROLL_CENTERED]; + float fPercentCentered = pPlayerState->m_CurrentPlayerOptions.m_fScrolls[PlayerOptions::SCROLL_CENTERED]; fShiftOut = SCALE( fPercentCentered, 0.f, 1.f, fShiftOut, 0.5f ); fScaleOut = SCALE( fPercentReverse, 0.f, 1.f, 1.f, -1.f); } -float ArrowGetYPos( PlayerNumber pn, int iCol, float fYOffset, float fYReverseOffsetPixels, bool WithReverse ) +float ArrowEffects::GetYPos( const PlayerState* pPlayerState, int iCol, float fYOffset, float fYReverseOffsetPixels, bool WithReverse ) { float f = fYOffset; if( WithReverse ) { float fShift, fScale; - ArrowGetReverseShiftAndScale( pn, iCol, fYReverseOffsetPixels, fShift, fScale ); + ArrowGetReverseShiftAndScale( pPlayerState, iCol, fYReverseOffsetPixels, fShift, fScale ); f *= fScale; f += fShift; } - const float* fEffects = GAMESTATE->m_CurrentPlayerOptions[pn].m_fEffects; + const float* fEffects = pPlayerState->m_CurrentPlayerOptions.m_fEffects; if( fEffects[PlayerOptions::EFFECT_TIPSY] > 0 ) f += fEffects[PlayerOptions::EFFECT_TIPSY] * ( cosf( RageTimer::GetTimeSinceStart()*1.2f + iCol*1.8f) * ARROW_SIZE*0.4f ); return f; } -float ArrowGetYOffsetFromYPos( PlayerNumber pn, int iCol, float YPos, float fYReverseOffsetPixels ) +float ArrowEffects::GetYOffsetFromYPos( const PlayerState* pPlayerState, int iCol, float YPos, float fYReverseOffsetPixels ) { float f = YPos; - const float* fEffects = GAMESTATE->m_CurrentPlayerOptions[pn].m_fEffects; + const float* fEffects = pPlayerState->m_CurrentPlayerOptions.m_fEffects; if( fEffects[PlayerOptions::EFFECT_TIPSY] > 0 ) f -= fEffects[PlayerOptions::EFFECT_TIPSY] * ( cosf( RageTimer::GetTimeSinceStart()*1.2f + iCol*2.f) * ARROW_SIZE*0.4f ); float fShift, fScale; - ArrowGetReverseShiftAndScale( pn, iCol, fYReverseOffsetPixels, fShift, fScale ); + ArrowGetReverseShiftAndScale( pPlayerState, iCol, fYReverseOffsetPixels, fShift, fScale ); f -= fShift; if( fScale ) @@ -173,11 +175,11 @@ float ArrowGetYOffsetFromYPos( PlayerNumber pn, int iCol, float YPos, float fYRe return f; } -float ArrowGetXPos( PlayerNumber pn, int iColNum, float fYOffset ) +float ArrowEffects::GetXPos( const PlayerState* pPlayerState, int iColNum, float fYOffset ) { float fPixelOffsetFromCenter = 0; - const float* fEffects = GAMESTATE->m_CurrentPlayerOptions[pn].m_fEffects; + const float* fEffects = pPlayerState->m_CurrentPlayerOptions.m_fEffects; if( fEffects[PlayerOptions::EFFECT_TORNADO] > 0 ) { @@ -195,6 +197,10 @@ float ArrowGetXPos( PlayerNumber pn, int iColNum, float fYOffset ) float fMinX = +100000; float fMaxX = -100000; + + // TODO: Don't index by PlayerNumber. + PlayerNumber pn = pPlayerState->m_PlayerNumber; + for( int i=iStartCol; i<=iEndCol; i++ ) { fMinX = min( fMinX, pStyle->m_ColumnInfo[pn][i].fXOffset ); @@ -215,6 +221,9 @@ float ArrowGetXPos( PlayerNumber pn, int iColNum, float fYOffset ) fPixelOffsetFromCenter += fEffects[PlayerOptions::EFFECT_DRUNK] * ( cosf( RageTimer::GetTimeSinceStart() + iColNum*0.2f + fYOffset*10/SCREEN_HEIGHT) * ARROW_SIZE*0.5f ); if( fEffects[PlayerOptions::EFFECT_FLIP] > 0 ) { + // TODO: Don't index by PlayerNumber. + PlayerNumber pn = pPlayerState->m_PlayerNumber; + // fPixelOffsetFromCenter *= SCALE(fEffects[PlayerOptions::EFFECT_FLIP], 0.f, 1.f, 1.f, -1.f); const float fRealPixelOffset = GAMESTATE->GetCurrentStyle()->m_ColumnInfo[pn][iColNum].fXOffset; const float fDistance = -fRealPixelOffset * 2; @@ -268,13 +277,13 @@ float ArrowGetXPos( PlayerNumber pn, int iColNum, float fYOffset ) return fPixelOffsetFromCenter; } -float ArrowGetRotation( PlayerNumber pn, float fNoteBeat ) +float ArrowEffects::GetRotation( const PlayerState* pPlayerState, float fNoteBeat ) { - if( GAMESTATE->m_CurrentPlayerOptions[pn].m_fEffects[PlayerOptions::EFFECT_DIZZY] > 0 ) + if( pPlayerState->m_CurrentPlayerOptions.m_fEffects[PlayerOptions::EFFECT_DIZZY] > 0 ) { const float fSongBeat = GAMESTATE->m_fSongBeat; float fDizzyRotation = fNoteBeat - fSongBeat; - fDizzyRotation *= GAMESTATE->m_CurrentPlayerOptions[pn].m_fEffects[PlayerOptions::EFFECT_DIZZY]; + fDizzyRotation *= pPlayerState->m_CurrentPlayerOptions.m_fEffects[PlayerOptions::EFFECT_DIZZY]; fDizzyRotation = fmodf( fDizzyRotation, 2*PI ); fDizzyRotation *= 180/PI; return fDizzyRotation; @@ -287,9 +296,9 @@ float ArrowGetRotation( PlayerNumber pn, float fNoteBeat ) #define CENTER_LINE_Y 160 // from fYOffset == 0 #define FADE_DIST_Y 40 -static float GetCenterLine( PlayerNumber pn ) +static float GetCenterLine( const PlayerState* pPlayerState ) { - const float fMiniPercent = GAMESTATE->m_CurrentPlayerOptions[pn].m_fEffects[PlayerOptions::EFFECT_MINI]; + const float fMiniPercent = pPlayerState->m_CurrentPlayerOptions.m_fEffects[PlayerOptions::EFFECT_MINI]; const float fZoom = 1 - fMiniPercent*0.5f; /* Another mini hack: if EFFECT_MINI is on, then our center line is at eg. 320, @@ -297,9 +306,9 @@ static float GetCenterLine( PlayerNumber pn ) return CENTER_LINE_Y / fZoom; } -static float GetHiddenSudden( PlayerNumber pn ) +static float GetHiddenSudden( const PlayerState* pPlayerState ) { - const float* fAppearances = GAMESTATE->m_CurrentPlayerOptions[pn].m_fAppearances; + const float* fAppearances = pPlayerState->m_CurrentPlayerOptions.m_fAppearances; return fAppearances[PlayerOptions::APPEARANCE_HIDDEN] * fAppearances[PlayerOptions::APPEARANCE_SUDDEN]; } @@ -316,50 +325,50 @@ static float GetHiddenSudden( PlayerNumber pn ) // ...invisible... // // TRICKY: We fudge hidden and sudden to be farther apart if they're both on. -static float GetHiddenEndLine( PlayerNumber pn ) +static float GetHiddenEndLine( const PlayerState* pPlayerState ) { - return GetCenterLine( pn ) + FADE_DIST_Y * SCALE( GetHiddenSudden(pn), 0.f, 1.f, -1.0f, -1.25f ); + return GetCenterLine( pPlayerState ) + FADE_DIST_Y * SCALE( GetHiddenSudden(pPlayerState), 0.f, 1.f, -1.0f, -1.25f ); } -static float GetHiddenStartLine( PlayerNumber pn ) +static float GetHiddenStartLine( const PlayerState* pPlayerState ) { - return GetCenterLine( pn ) + FADE_DIST_Y * SCALE( GetHiddenSudden(pn), 0.f, 1.f, +0.0f, -0.25f ); + return GetCenterLine( pPlayerState ) + FADE_DIST_Y * SCALE( GetHiddenSudden(pPlayerState), 0.f, 1.f, +0.0f, -0.25f ); } -static float GetSuddenEndLine( PlayerNumber pn ) +static float GetSuddenEndLine( const PlayerState* pPlayerState ) { - return GetCenterLine( pn ) + FADE_DIST_Y * SCALE( GetHiddenSudden(pn), 0.f, 1.f, -0.0f, +0.25f ); + return GetCenterLine( pPlayerState ) + FADE_DIST_Y * SCALE( GetHiddenSudden(pPlayerState), 0.f, 1.f, -0.0f, +0.25f ); } -static float GetSuddenStartLine( PlayerNumber pn ) +static float GetSuddenStartLine( const PlayerState* pPlayerState ) { - return GetCenterLine( pn ) + FADE_DIST_Y * SCALE( GetHiddenSudden(pn), 0.f, 1.f, +1.0f, +1.25f ); + return GetCenterLine( pPlayerState ) + FADE_DIST_Y * SCALE( GetHiddenSudden(pPlayerState), 0.f, 1.f, +1.0f, +1.25f ); } // used by ArrowGetAlpha and ArrowGetGlow below -static float ArrowGetPercentVisible( PlayerNumber pn, int iCol, float fYOffset, float fYReverseOffsetPixels ) +float ArrowGetPercentVisible( const PlayerState* pPlayerState, int iCol, float fYOffset, float fYReverseOffsetPixels ) { /* Get the YPos without reverse (that is, factor in EFFECT_TIPSY). */ - float fYPos = ArrowGetYPos( pn, iCol, fYOffset, fYReverseOffsetPixels, false ); + float fYPos = ArrowEffects::GetYPos( pPlayerState, iCol, fYOffset, fYReverseOffsetPixels, false ); - const float fDistFromCenterLine = fYPos - GetCenterLine( pn ); + const float fDistFromCenterLine = fYPos - GetCenterLine( pPlayerState ); if( fYPos < 0 ) // past Gray Arrows return 1; // totally visible - const float* fAppearances = GAMESTATE->m_CurrentPlayerOptions[pn].m_fAppearances; + const float* fAppearances = pPlayerState->m_CurrentPlayerOptions.m_fAppearances; float fVisibleAdjust = 0; if( fAppearances[PlayerOptions::APPEARANCE_HIDDEN] > 0 ) { - float fHiddenVisibleAdjust = SCALE( fYPos, GetHiddenStartLine(pn), GetHiddenEndLine(pn), 0, -1 ); + float fHiddenVisibleAdjust = SCALE( fYPos, GetHiddenStartLine(pPlayerState), GetHiddenEndLine(pPlayerState), 0, -1 ); CLAMP( fHiddenVisibleAdjust, -1, 0 ); fVisibleAdjust += fAppearances[PlayerOptions::APPEARANCE_HIDDEN] * fHiddenVisibleAdjust; } if( fAppearances[PlayerOptions::APPEARANCE_SUDDEN] > 0 ) { - float fSuddenVisibleAdjust = SCALE( fYPos, GetSuddenStartLine(pn), GetSuddenEndLine(pn), -1, 0 ); + float fSuddenVisibleAdjust = SCALE( fYPos, GetSuddenStartLine(pPlayerState), GetSuddenEndLine(pPlayerState), -1, 0 ); CLAMP( fSuddenVisibleAdjust, -1, 0 ); fVisibleAdjust += fAppearances[PlayerOptions::APPEARANCE_SUDDEN] * fSuddenVisibleAdjust; } @@ -382,9 +391,9 @@ static float ArrowGetPercentVisible( PlayerNumber pn, int iCol, float fYOffset, return clamp( 1+fVisibleAdjust, 0, 1 ); } -float ArrowGetAlpha( PlayerNumber pn, int iCol, float fYOffset, float fPercentFadeToFail, float fYReverseOffsetPixels ) +float ArrowEffects::GetAlpha( const PlayerState* pPlayerState, int iCol, float fYOffset, float fPercentFadeToFail, float fYReverseOffsetPixels ) { - float fPercentVisible = ArrowGetPercentVisible(pn,iCol,fYOffset,fYReverseOffsetPixels); + float fPercentVisible = ArrowGetPercentVisible(pPlayerState,iCol,fYOffset,fYReverseOffsetPixels); if( fPercentFadeToFail != -1 ) fPercentVisible = 1 - fPercentFadeToFail; @@ -392,9 +401,9 @@ float ArrowGetAlpha( PlayerNumber pn, int iCol, float fYOffset, float fPercentFa return (fPercentVisible>0.5f) ? 1.0f : 0.0f; } -float ArrowGetGlow( PlayerNumber pn, int iCol, float fYOffset, float fPercentFadeToFail, float fYReverseOffsetPixels ) +float ArrowEffects::GetGlow( const PlayerState* pPlayerState, int iCol, float fYOffset, float fPercentFadeToFail, float fYReverseOffsetPixels ) { - float fPercentVisible = ArrowGetPercentVisible(pn,iCol,fYOffset,fYReverseOffsetPixels); + float fPercentVisible = ArrowGetPercentVisible(pPlayerState,iCol,fYOffset,fYReverseOffsetPixels); if( fPercentFadeToFail != -1 ) fPercentVisible = 1 - fPercentFadeToFail; @@ -403,7 +412,7 @@ float ArrowGetGlow( PlayerNumber pn, int iCol, float fYOffset, float fPercentFad return SCALE( fDistFromHalf, 0, 0.5f, 1.3f, 0 ); } -float ArrowGetBrightness( PlayerNumber pn, float fNoteBeat ) +float ArrowEffects::GetBrightness( const PlayerState* pPlayerState, float fNoteBeat ) { if( GAMESTATE->m_bEditing ) return 1; @@ -417,10 +426,10 @@ float ArrowGetBrightness( PlayerNumber pn, float fNoteBeat ) } -float ArrowGetZPos( PlayerNumber pn, int iCol, float fYOffset ) +float ArrowEffects::GetZPos( const PlayerState* pPlayerState, int iCol, float fYOffset ) { float fZPos=0; - const float* fEffects = GAMESTATE->m_CurrentPlayerOptions[pn].m_fEffects; + const float* fEffects = pPlayerState->m_CurrentPlayerOptions.m_fEffects; if( fEffects[PlayerOptions::EFFECT_BUMPY] > 0 ) fZPos += fEffects[PlayerOptions::EFFECT_BUMPY] * 40*sinf( fYOffset/16.0f ); @@ -428,16 +437,16 @@ float ArrowGetZPos( PlayerNumber pn, int iCol, float fYOffset ) return fZPos; } -bool ArrowsNeedZBuffer( PlayerNumber pn ) +bool ArrowEffects::NeedZBuffer( const PlayerState* pPlayerState ) { - const float* fEffects = GAMESTATE->m_CurrentPlayerOptions[pn].m_fEffects; + const float* fEffects = pPlayerState->m_CurrentPlayerOptions.m_fEffects; if( fEffects[PlayerOptions::EFFECT_BUMPY] > 0 ) return true; return false; } -float ArrowGetZoom( PlayerNumber pn ) +float ArrowEffects::GetZoom( const PlayerState* pPlayerState ) { // FIXME: Move the zoom values into Style if( GAMESTATE->m_pCurStyle->m_bNeedsZoomOutWith2Players && diff --git a/stepmania/src/ArrowEffects.h b/stepmania/src/ArrowEffects.h index 471358b062..2a277a9be2 100644 --- a/stepmania/src/ArrowEffects.h +++ b/stepmania/src/ArrowEffects.h @@ -3,56 +3,58 @@ #ifndef ARROWEFFECTS_H #define ARROWEFFECTS_H +struct PlayerState; -#include "GameConstantsAndTypes.h" -#include "Style.h" +class ArrowEffects +{ +public: + + // 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 and ScrollSpeed is applied in this stage. + static float GetYOffset( const PlayerState* pPlayerState, int iCol, float fNoteBeat, bool bAbsolute=false ); + + /* Actual display position, with reverse and post-reverse-effects factored in + * (fYOffset -> YPos). */ + static float GetYPos( const PlayerState* pPlayerState, int iCol, float fYOffset, float fYReverseOffsetPixels, bool WithReverse = true ); + + // Inverse of ArrowGetYPos (YPos -> fYOffset). + static float GetYOffsetFromYPos( const PlayerState* pPlayerState, int iCol, float YPos, float fYReverseOffsetPixels ); -// 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 and ScrollSpeed is applied in this stage. -float ArrowGetYOffset( PlayerNumber pn, int iCol, float fNoteBeat, bool bAbsolute=false ); - -/* Actual display position, with reverse and post-reverse-effects factored in - * (fYOffset -> YPos). */ -float ArrowGetYPos( PlayerNumber pn, int iCol, float fYOffset, float fYReverseOffsetPixels, bool WithReverse = true ); - -// Inverse of ArrowGetYPos (YPos -> fYOffset). -float ArrowGetYOffsetFromYPos( PlayerNumber pn, int iCol, float YPos, float fYReverseOffsetPixels ); + // 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). + static float GetRotation( const PlayerState* pPlayerState, float fNoteBeat ); -// 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( PlayerNumber pn, float fNoteBeat ); + // 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 + // fYPos (in the case of EFFECT_DRUNK). + static float GetXPos( const PlayerState* pPlayerState, int iCol, float fYOffset ); + + // Z position; normally 0. Only visible in perspective modes. + static float GetZPos( const PlayerState* pPlayerState, int iCol, float fYPos ); + + // Enable this if any ZPos effects are enabled. + static bool NeedZBuffer( const PlayerState* pPlayerState ); + + // fAlpha is the transparency of the arrow. It depends on fYPos and the + // AppearanceType. + static float GetAlpha( const PlayerState* pPlayerState, int iCol, float fYPos, float fPercentFadeToFail, float fYReverseOffsetPixels ); -// 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 -// fYPos (in the case of EFFECT_DRUNK). -float ArrowGetXPos( PlayerNumber pn, int iCol, float fYOffset ); - -// Z position; normally 0. Only visible in perspective modes. -float ArrowGetZPos( PlayerNumber pn, int iCol, float fYPos ); - -// Enable this if any ZPos effects are enabled. -bool ArrowsNeedZBuffer( PlayerNumber pn ); - -// fAlpha is the transparency of the arrow. It depends on fYPos and the -// AppearanceType. -float ArrowGetAlpha( PlayerNumber pn, int iCol, float fYPos, float fPercentFadeToFail, float fYReverseOffsetPixels ); + // fAlpha is the transparency of the arrow. It depends on fYPos and the + // AppearanceType. + static float GetGlow( const PlayerState* pPlayerState, int iCol, float fYPos, float fPercentFadeToFail, float fYReverseOffsetPixels ); -// fAlpha is the transparency of the arrow. It depends on fYPos and the -// AppearanceType. -float ArrowGetGlow( PlayerNumber pn, int iCol, float fYPos, float fPercentFadeToFail, float fYReverseOffsetPixels ); + // Depends on fYOffset. + static float GetBrightness( const PlayerState* pPlayerState, float fNoteBeat ); - -// Depends on fYOffset. -float ArrowGetBrightness( PlayerNumber pn, float fNoteBeat ); - -// This is the zoom of the individual tracks, not of the whole Player. -float ArrowGetZoom( PlayerNumber pn ); + // This is the zoom of the individual tracks, not of the whole Player. + static float GetZoom( const PlayerState* pPlayerState ); +}; #endif diff --git a/stepmania/src/Attack.cpp b/stepmania/src/Attack.cpp index 07f2f33914..f58b4b1787 100644 --- a/stepmania/src/Attack.cpp +++ b/stepmania/src/Attack.cpp @@ -4,8 +4,9 @@ #include "RageUtil.h" #include "song.h" #include "Foreach.h" +#include "PlayerOptions.h" -void Attack::GetAttackBeats( const Song *song, PlayerNumber pn, float &fStartBeat, float &fEndBeat ) const +void Attack::GetAttackBeats( const Song *song, const PlayerState* pPlayerState, float &fStartBeat, float &fEndBeat ) const { ASSERT( song ); @@ -14,17 +15,21 @@ void Attack::GetAttackBeats( const Song *song, PlayerNumber pn, float &fStartBea CHECKPOINT; fStartBeat = song->GetBeatFromElapsedTime( fStartSecond ); fEndBeat = song->GetBeatFromElapsedTime( fStartSecond+fSecsRemaining ); - } else { + } + else + { CHECKPOINT; /* If fStartSecond < 0, then the attack starts right off the screen; this requires * that a song actually be playing. Pre-queued course attacks must always have * fStartSecond >= 0. */ ASSERT( GAMESTATE->m_pCurSong ); + ASSERT( pPlayerState ); + /* We're setting this effect on the fly. If it's an arrow-changing effect * (transform or note skin), apply it in the future, after what's currently on * screen, so new arrows will scroll on screen with this effect. */ - GAMESTATE->GetUndisplayedBeats( pn, fSecsRemaining, fStartBeat, fEndBeat ); + GAMESTATE->GetUndisplayedBeats( pPlayerState, fSecsRemaining, fStartBeat, fEndBeat ); } ASSERT_M( fEndBeat >= fStartBeat, ssprintf("%f >= %f", fEndBeat, fStartBeat) ); diff --git a/stepmania/src/Attack.h b/stepmania/src/Attack.h index 0e3cf82ec3..e3bcb7f0fe 100644 --- a/stepmania/src/Attack.h +++ b/stepmania/src/Attack.h @@ -4,6 +4,7 @@ #include "GameConstantsAndTypes.h" #include "PlayerNumber.h" class Song; +struct PlayerState; struct Attack { @@ -32,8 +33,8 @@ struct Attack bGlobal = bGlobal_; } - void GetAttackBeats( const Song *song, PlayerNumber pn, float &fStartBeat, float &fEndBeat ) const; - bool IsBlank() { return sModifier.empty(); } + void GetAttackBeats( const Song *song, const PlayerState* pPlayerState, float &fStartBeat, float &fEndBeat ) const; + bool IsBlank() const { return sModifier.empty(); } bool operator== ( const Attack &rhs ) const; bool ContainsTransformOrTurn() const; }; diff --git a/stepmania/src/AttackDisplay.cpp b/stepmania/src/AttackDisplay.cpp index bccacd6f19..853ead5cfe 100644 --- a/stepmania/src/AttackDisplay.cpp +++ b/stepmania/src/AttackDisplay.cpp @@ -7,6 +7,7 @@ #include "RageLog.h" #include "RageTextureManager.h" #include +#include "PlayerState.h" CString GetAttackPath( const CString &sAttack ) { @@ -25,14 +26,17 @@ AttackDisplay::AttackDisplay() GAMESTATE->m_PlayMode != PLAY_MODE_RAVE ) return; - m_sprAttack.SetName( ssprintf("TextP%d",m_PlayerNumber+1) ); m_sprAttack.SetDiffuseAlpha( 0 ); // invisible this->AddChild( &m_sprAttack ); } -void AttackDisplay::Init( PlayerNumber pn ) +void AttackDisplay::Init( const PlayerState* pPlayerState ) { - m_PlayerNumber = pn; + m_pPlayerState = pPlayerState; + + // TODO: Remove use of PlayerNumber. + PlayerNumber pn = m_pPlayerState->m_PlayerNumber; + m_sprAttack.SetName( ssprintf("TextP%d",pn+1) ); if( GAMESTATE->m_PlayMode != PLAY_MODE_BATTLE && GAMESTATE->m_PlayMode != PLAY_MODE_RAVE ) @@ -71,22 +75,24 @@ void AttackDisplay::Update( float fDelta ) GAMESTATE->m_PlayMode != PLAY_MODE_RAVE ) return; - if( !GAMESTATE->m_bAttackBeganThisUpdate[m_PlayerNumber] ) + if( !m_pPlayerState->m_bAttackBeganThisUpdate ) return; // don't handle this again - for( unsigned s=0; sm_ActiveAttacks[m_PlayerNumber].size(); s++ ) + for( unsigned s=0; sm_ActiveAttacks.size(); s++ ) { - if( GAMESTATE->m_ActiveAttacks[m_PlayerNumber][s].fStartSecond >= 0 ) + const Attack& attack = m_pPlayerState->m_ActiveAttacks[s]; + + if( attack.fStartSecond >= 0 ) continue; /* hasn't started yet */ - if( GAMESTATE->m_ActiveAttacks[m_PlayerNumber][s].fSecsRemaining <= 0 ) + if( attack.fSecsRemaining <= 0 ) continue; /* ended already */ - if( GAMESTATE->m_ActiveAttacks[m_PlayerNumber][s].IsBlank() ) + if( attack.IsBlank() ) continue; - SetAttack( GAMESTATE->m_ActiveAttacks[m_PlayerNumber][s].sModifier ); + SetAttack( attack.sModifier ); break; } } @@ -99,7 +105,11 @@ void AttackDisplay::SetAttack( const CString &sText ) m_sprAttack.SetDiffuseAlpha( 1 ); m_sprAttack.Load( path ); - const CString sName = ssprintf( "%sP%i", sText.c_str(), m_PlayerNumber+1 ); + + // TODO: Remove use of PlayerNumber. + PlayerNumber pn = m_pPlayerState->m_PlayerNumber; + + const CString sName = ssprintf( "%sP%i", sText.c_str(), pn+1 ); m_sprAttack.RunCommands( THEME->GetMetricA("AttackDisplay", sName + "OnCommand" ) ); } diff --git a/stepmania/src/AttackDisplay.h b/stepmania/src/AttackDisplay.h index 38af2339dc..a8baa091f4 100644 --- a/stepmania/src/AttackDisplay.h +++ b/stepmania/src/AttackDisplay.h @@ -3,22 +3,22 @@ #include "ActorFrame.h" #include "Sprite.h" -#include "PlayerNumber.h" #include "GameConstantsAndTypes.h" // for TapNoteScore +struct PlayerState; class AttackDisplay : public ActorFrame { public: AttackDisplay(); - void Init( PlayerNumber pn ); + void Init( const PlayerState* pPlayerState ); void SetAttack( const CString &mod ); virtual void Update( float fDelta ); protected: - PlayerNumber m_PlayerNumber; + const PlayerState* m_pPlayerState; Sprite m_sprAttack; }; diff --git a/stepmania/src/Background.cpp b/stepmania/src/Background.cpp index 970b91fb31..d1ab3c6ff1 100644 --- a/stepmania/src/Background.cpp +++ b/stepmania/src/Background.cpp @@ -16,6 +16,7 @@ #include "StageStats.h" #include "ScreenDimensions.h" #include "ThemeMetric.h" +#include "PlayerState.h" #include @@ -632,14 +633,14 @@ bool Background::IsDangerPlayerVisible( PlayerNumber pn ) return false; if( !PREFSMAN->m_bShowDanger ) return false; - return GAMESTATE->m_HealthState[pn] == GameState::DANGER; + return GAMESTATE->m_pPlayerState[pn]->m_HealthState == PlayerState::DANGER; } bool Background::IsDeadPlayerVisible( PlayerNumber pn ) { if( GAMESTATE->m_SongOptions.m_FailType == SongOptions::FAIL_OFF ) return false; - return GAMESTATE->m_HealthState[pn] == GameState::DEAD; + return GAMESTATE->m_pPlayerState[pn]->m_HealthState == PlayerState::DEAD; } @@ -670,8 +671,8 @@ void BrightnessOverlay::Update( float fDeltaTime ) void BrightnessOverlay::SetActualBrightness() { - float fLeftBrightness = 1-GAMESTATE->m_PlayerOptions[PLAYER_1].m_fCover; - float fRightBrightness = 1-GAMESTATE->m_PlayerOptions[PLAYER_2].m_fCover; + float fLeftBrightness = 1-GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions.m_fCover; + float fRightBrightness = 1-GAMESTATE->m_pPlayerState[PLAYER_2]->m_PlayerOptions.m_fCover; fLeftBrightness *= PREFSMAN->m_fBGBrightness; fRightBrightness *= PREFSMAN->m_fBGBrightness; diff --git a/stepmania/src/CodeDetector.cpp b/stepmania/src/CodeDetector.cpp index 10fd1518f2..057b2df21d 100644 --- a/stepmania/src/CodeDetector.cpp +++ b/stepmania/src/CodeDetector.cpp @@ -10,6 +10,7 @@ #include "Style.h" #include "RageUtil.h" #include "PrefsManager.h" +#include "PlayerState.h" const CString g_sCodeNames[CodeDetector::NUM_CODES] = { "Easier1", @@ -220,8 +221,8 @@ bool CodeDetector::EnteredModeMenu( GameController controller ) #define INCREMENT_SCROLL_SPEED(s) (s==0.5f) ? s=0.75f : (s==0.75f) ? s=1.0f : (s==1.0f) ? s=1.5f : (s==1.5f) ? s=2.0f : (s==2.0f) ? s=3.0f : (s==3.0f) ? s=4.0f : (s==4.0f) ? s=5.0f : (s==5.0f) ? s=8.0f : s=0.5f; #define DECREMENT_SCROLL_SPEED(s) (s==0.75f) ? s=0.5f : (s==1.0f) ? s=0.75f : (s==1.5f) ? s=1.0f : (s==2.0f) ? s=1.5f : (s==3.0f) ? s=2.0f : (s==4.0f) ? s=3.0f : (s==5.0f) ? s=4.0f : (s==8.0f) ? s=4.0f : s=8.0f; -#define TOGGLE_HIDDEN ZERO(GAMESTATE->m_PlayerOptions[pn].m_fAppearances); GAMESTATE->m_PlayerOptions[pn].m_fAppearances[PlayerOptions::APPEARANCE_HIDDEN] = 1; -#define TOGGLE_RANDOMVANISH ZERO(GAMESTATE->m_PlayerOptions[pn].m_fAppearances); GAMESTATE->m_PlayerOptions[pn].m_fAppearances[PlayerOptions::APPEARANCE_RANDOMVANISH] = 1; +#define TOGGLE_HIDDEN ZERO(GAMESTATE->m_pPlayerState[pn]->m_PlayerOptions.m_fAppearances); GAMESTATE->m_pPlayerState[pn]->m_PlayerOptions.m_fAppearances[PlayerOptions::APPEARANCE_HIDDEN] = 1; +#define TOGGLE_RANDOMVANISH ZERO(GAMESTATE->m_pPlayerState[pn]->m_PlayerOptions.m_fAppearances); GAMESTATE->m_pPlayerState[pn]->m_PlayerOptions.m_fAppearances[PlayerOptions::APPEARANCE_RANDOMVANISH] = 1; bool CodeDetector::DetectAndAdjustMusicOptions( GameController controller ) { @@ -232,32 +233,34 @@ bool CodeDetector::DetectAndAdjustMusicOptions( GameController controller ) { Code code = (Code)c; + PlayerOptions& po = GAMESTATE->m_pPlayerState[pn]->m_PlayerOptions; + if( EnteredCode(controller,code) ) { switch( code ) { - case CODE_MIRROR: GAMESTATE->m_PlayerOptions[pn].ToggleOneTurn( PlayerOptions::TURN_MIRROR ); break; - case CODE_LEFT: GAMESTATE->m_PlayerOptions[pn].ToggleOneTurn( PlayerOptions::TURN_LEFT ); break; - case CODE_RIGHT: GAMESTATE->m_PlayerOptions[pn].ToggleOneTurn( PlayerOptions::TURN_RIGHT ); break; - case CODE_SHUFFLE: GAMESTATE->m_PlayerOptions[pn].ToggleOneTurn( PlayerOptions::TURN_SHUFFLE ); break; - case CODE_SUPER_SHUFFLE: GAMESTATE->m_PlayerOptions[pn].ToggleOneTurn( PlayerOptions::TURN_SUPER_SHUFFLE ); break; - case CODE_NEXT_TRANSFORM: GAMESTATE->m_PlayerOptions[pn].NextTransform(); break; - case CODE_NEXT_SCROLL_SPEED:INCREMENT_SCROLL_SPEED( GAMESTATE->m_PlayerOptions[pn].m_fScrollSpeed ); break; - case CODE_PREVIOUS_SCROLL_SPEED:DECREMENT_SCROLL_SPEED( GAMESTATE->m_PlayerOptions[pn].m_fScrollSpeed ); break; - case CODE_NEXT_ACCEL: GAMESTATE->m_PlayerOptions[pn].NextAccel(); break; - case CODE_NEXT_EFFECT: GAMESTATE->m_PlayerOptions[pn].NextEffect(); break; - case CODE_NEXT_APPEARANCE: GAMESTATE->m_PlayerOptions[pn].NextAppearance(); break; - case CODE_NEXT_TURN: GAMESTATE->m_PlayerOptions[pn].NextTurn(); break; - case CODE_REVERSE: GAMESTATE->m_PlayerOptions[pn].NextScroll(); break; - case CODE_HOLDS: TOGGLE( GAMESTATE->m_PlayerOptions[pn].m_bTransforms[PlayerOptions::TRANSFORM_NOHOLDS], true, false ); break; - case CODE_MINES: TOGGLE( GAMESTATE->m_PlayerOptions[pn].m_bTransforms[PlayerOptions::TRANSFORM_NOMINES], true, false ); break; - case CODE_DARK: FLOAT_TOGGLE( GAMESTATE->m_PlayerOptions[pn].m_fDark ); break; - case CODE_CANCEL_ALL: GAMESTATE->m_PlayerOptions[pn].Init(); - GAMESTATE->m_PlayerOptions[pn].FromString( PREFSMAN->m_sDefaultModifiers ); break; - case CODE_HIDDEN: TOGGLE_HIDDEN; break; - case CODE_RANDOMVANISH: TOGGLE_RANDOMVANISH; break; + case CODE_MIRROR: po.ToggleOneTurn( PlayerOptions::TURN_MIRROR ); break; + case CODE_LEFT: po.ToggleOneTurn( PlayerOptions::TURN_LEFT ); break; + case CODE_RIGHT: po.ToggleOneTurn( PlayerOptions::TURN_RIGHT ); break; + case CODE_SHUFFLE: po.ToggleOneTurn( PlayerOptions::TURN_SHUFFLE ); break; + case CODE_SUPER_SHUFFLE: po.ToggleOneTurn( PlayerOptions::TURN_SUPER_SHUFFLE ); break; + case CODE_NEXT_TRANSFORM: po.NextTransform(); break; + case CODE_NEXT_SCROLL_SPEED: INCREMENT_SCROLL_SPEED( po.m_fScrollSpeed ); break; + case CODE_PREVIOUS_SCROLL_SPEED: DECREMENT_SCROLL_SPEED( po.m_fScrollSpeed ); break; + case CODE_NEXT_ACCEL: po.NextAccel(); break; + case CODE_NEXT_EFFECT: po.NextEffect(); break; + case CODE_NEXT_APPEARANCE: po.NextAppearance(); break; + case CODE_NEXT_TURN: po.NextTurn(); break; + case CODE_REVERSE: po.NextScroll(); break; + case CODE_HOLDS: TOGGLE( po.m_bTransforms[PlayerOptions::TRANSFORM_NOHOLDS], true, false ); break; + case CODE_MINES: TOGGLE( po.m_bTransforms[PlayerOptions::TRANSFORM_NOMINES], true, false ); break; + case CODE_DARK: FLOAT_TOGGLE( po.m_fDark ); break; + case CODE_CANCEL_ALL: po.Init(); + po.FromString( PREFSMAN->m_sDefaultModifiers ); break; + case CODE_HIDDEN: TOGGLE_HIDDEN; break; + case CODE_RANDOMVANISH: TOGGLE_RANDOMVANISH; break; - // GAMESTATE->m_PlayerOptions[pn].SetOneAppearance(GAMESTATE->m_PlayerOptions[pn].GetFirstAppearance()); break; + // po.SetOneAppearance(po.GetFirstAppearance()); break; default: ; } return true; // don't check any more diff --git a/stepmania/src/ConditionalBGA.cpp b/stepmania/src/ConditionalBGA.cpp index c093c4564e..9ada1936b6 100644 --- a/stepmania/src/ConditionalBGA.cpp +++ b/stepmania/src/ConditionalBGA.cpp @@ -13,6 +13,7 @@ #include "RageFile.h" #include "StageStats.h" #include "Steps.h" +#include "PlayerState.h" ConditionalBGA::ConditionalBGA() { @@ -397,7 +398,7 @@ void ConditionalBGA::CheckBgaRequirements(BgaCondInfo info) unsigned md; for(md=0;mdm_PlayerOptions[pn].m_fAccels[md] != 0.0f) + if(po.m_fAccels[md] != 0.0f && GAMESTATE->m_pPlayerState[pn]->m_PlayerOptions.m_fAccels[md] != 0.0f) { bModsValid=false; LOG->Info("Found Invalid Accel Mod"); @@ -405,7 +406,7 @@ void ConditionalBGA::CheckBgaRequirements(BgaCondInfo info) } for(md=0;mdm_PlayerOptions[pn].m_fEffects[md] != 0.0f) + if(po.m_fEffects[md] != 0.0f && GAMESTATE->m_pPlayerState[pn]->m_PlayerOptions.m_fEffects[md] != 0.0f) { bModsValid=false; LOG->Info("Found Invalid Effect Mod"); @@ -413,7 +414,7 @@ void ConditionalBGA::CheckBgaRequirements(BgaCondInfo info) } for(md=0;mdm_PlayerOptions[pn].m_fAppearances[md] != 0.0f) + if(po.m_fAppearances[md] != 0.0f && GAMESTATE->m_pPlayerState[pn]->m_PlayerOptions.m_fAppearances[md] != 0.0f) { bModsValid=false; LOG->Info("Found Invalid Appearance Mod"); @@ -421,7 +422,7 @@ void ConditionalBGA::CheckBgaRequirements(BgaCondInfo info) } for(md=0;mdm_PlayerOptions[pn].m_bTurns[md] != 0.0f) + if(po.m_bTurns[md] != 0.0f && GAMESTATE->m_pPlayerState[pn]->m_PlayerOptions.m_bTurns[md] != 0.0f) { bModsValid=false; LOG->Info("Found Invalid Turn Mod"); @@ -429,7 +430,7 @@ void ConditionalBGA::CheckBgaRequirements(BgaCondInfo info) } for(md=0;mdm_PlayerOptions[pn].m_bTransforms[md] != 0.0f) + if(po.m_bTransforms[md] != 0.0f && GAMESTATE->m_pPlayerState[pn]->m_PlayerOptions.m_bTransforms[md] != 0.0f) { bModsValid=false; LOG->Info("Found Invalid Transform Mod"); diff --git a/stepmania/src/EditCoursesMenu.cpp b/stepmania/src/EditCoursesMenu.cpp index f82d8ef432..b1e1e2cd5c 100644 --- a/stepmania/src/EditCoursesMenu.cpp +++ b/stepmania/src/EditCoursesMenu.cpp @@ -10,6 +10,7 @@ #include "Course.h" #include "ScreenMiniMenu.h" #include "ScreenManager.h" +#include "PlayerState.h" // // Defines specific to EditCoursesMenu @@ -326,8 +327,8 @@ void EditCoursesMenu::Start() case ROW_ENTRY_PLAYER_OPTIONS: SCREENMAN->PlayStartSound(); - GAMESTATE->m_PlayerOptions[PLAYER_1] = PlayerOptions(); - GAMESTATE->m_PlayerOptions[PLAYER_1].FromString( pEntry->modifiers ); + GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions = PlayerOptions(); + GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions.FromString( pEntry->modifiers ); SCREENMAN->AddNewScreenToTop( "ScreenPlayerOptions", SM_BackFromPlayerOptions ); break; @@ -365,7 +366,7 @@ void EditCoursesMenu::HandleScreenMessage( const ScreenMessage SM ) case SM_BackFromPlayerOptions: case SM_BackFromSongOptions: // coming back from PlayerOptions or SongOptions - pEntry->modifiers = GAMESTATE->m_PlayerOptions[PLAYER_1].GetString() + "," + GAMESTATE->m_SongOptions.GetString(); + pEntry->modifiers = GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions.GetString() + "," + GAMESTATE->m_SongOptions.GetString(); OnRowValueChanged( ROW_ENTRY_PLAYER_OPTIONS ); break; } diff --git a/stepmania/src/GameCommand.cpp b/stepmania/src/GameCommand.cpp index 4915bdb6d4..c5bfd1fae2 100644 --- a/stepmania/src/GameCommand.cpp +++ b/stepmania/src/GameCommand.cpp @@ -23,6 +23,7 @@ #include "UnlockSystem.h" #include "GameSoundManager.h" #include "ThemeManager.h" +#include "PlayerState.h" void GameCommand::Init() { @@ -91,12 +92,12 @@ bool GameCommand::DescribesCurrentMode( PlayerNumber pn ) const if( m_sModifiers != "" ) { /* Apply modifiers. */ - PlayerOptions po = GAMESTATE->m_PlayerOptions[pn]; + PlayerOptions po = GAMESTATE->m_pPlayerState[pn]->m_PlayerOptions; SongOptions so = GAMESTATE->m_SongOptions; po.FromString( m_sModifiers ); so.FromString( m_sModifiers ); - if( po != GAMESTATE->m_PlayerOptions[pn] ) + if( po != GAMESTATE->m_pPlayerState[pn]->m_PlayerOptions ) return false; if( so != GAMESTATE->m_SongOptions ) return false; diff --git a/stepmania/src/GameState.cpp b/stepmania/src/GameState.cpp index 6285596514..ebbb240612 100644 --- a/stepmania/src/GameState.cpp +++ b/stepmania/src/GameState.cpp @@ -28,6 +28,7 @@ #include "StepMania.h" #include "CommonMetrics.h" #include "Actor.h" +#include "PlayerState.h" #include #include @@ -57,6 +58,12 @@ GameState::GameState() FOREACH_PlayerNumber( p ) m_bSideIsJoined[p] = false; // used by GetNumSidesJoined before the first screen + FOREACH_PlayerNumber( p ) + { + m_pPlayerState[p] = new PlayerState; + m_pPlayerState[p]->m_PlayerNumber = p; + } + /* Don't reset yet; let the first screen do it, so we can * use PREFSMAN and THEME. */ // Reset(); @@ -64,9 +71,12 @@ GameState::GameState() GameState::~GameState() { - delete m_pPosition; + SAFE_DELETE( m_pPosition ); for( unsigned i=0; im_bAttackBeganThisUpdate = false; ResetMusicStatistics(); ResetStageStatistics(); @@ -162,9 +172,9 @@ void GameState::Reset() FOREACH_PlayerNumber( p ) { - m_CurrentPlayerOptions[p].Init(); - m_PlayerOptions[p].Init(); - m_StoredPlayerOptions[p].Init(); + m_pPlayerState[p]->m_CurrentPlayerOptions.Init(); + m_pPlayerState[p]->m_PlayerOptions.Init(); + m_pPlayerState[p]->m_StoredPlayerOptions.Init(); } m_SongOptions.Init(); @@ -192,8 +202,8 @@ void GameState::Reset() FOREACH_PlayerNumber(p) { - m_fSuperMeterGrowthScale[p] = 1; - m_iCpuSkill[p] = 5; + m_pPlayerState[p]->m_fSuperMeterGrowthScale = 1; + m_pPlayerState[p]->m_iCpuSkill = 5; } @@ -253,7 +263,7 @@ void GameState::PlayersFinalized() * sets a default of "reverse", and the player turns it off, we should * set it off. However, don't reset modifiers that aren't saved by the * profile, so we don't ignore unsaved modifiers when a profile is in use. */ - GAMESTATE->m_PlayerOptions[pn].ResetSavedPrefs(); + GAMESTATE->m_pPlayerState[pn]->m_PlayerOptions.ResetSavedPrefs(); GAMESTATE->ApplyModifiers( pn, sModifiers ); } // Only set the sort order if it wasn't already set by a GameCommand (or by an earlier profile) @@ -391,7 +401,7 @@ void GameState::SaveCurrentSettingsToProfile( PlayerNumber pn ) Profile* pProfile = PROFILEMAN->GetProfile(pn); - pProfile->SetDefaultModifiers( this->m_pCurGame, m_PlayerOptions[pn].GetSavedPrefsString() ); + pProfile->SetDefaultModifiers( this->m_pCurGame, m_pPlayerState[pn]->m_PlayerOptions.GetSavedPrefsString() ); if( IsSongSort(m_SortOrder) ) pProfile->m_SortOrder = m_SortOrder; if( m_PreferredDifficulty[pn] != DIFFICULTY_INVALID ) @@ -408,19 +418,19 @@ void GameState::Update( float fDelta ) { FOREACH_PlayerNumber( p ) { - m_CurrentPlayerOptions[p].Approach( m_PlayerOptions[p], fDelta ); + m_pPlayerState[p]->m_CurrentPlayerOptions.Approach( m_pPlayerState[p]->m_PlayerOptions, fDelta ); // TRICKY: GAMESTATE->Update is run before any of the Screen update's, // so we'll clear these flags here and let them get turned on later - m_bAttackBeganThisUpdate[p] = false; - m_bAttackEndedThisUpdate[p] = false; + m_pPlayerState[p]->m_bAttackBeganThisUpdate = false; + m_pPlayerState[p]->m_bAttackEndedThisUpdate = false; bool bRebuildPlayerOptions = false; /* See if any delayed attacks are starting or ending. */ - for( unsigned s=0; sm_ActiveAttacks.size(); s++ ) { - Attack &attack = m_ActiveAttacks[p][s]; + Attack &attack = m_pPlayerState[p]->m_ActiveAttacks[s]; // -1 is the "starts now" sentinel value. You must add the attack // by calling GameState::LaunchAttack, or else the -1 won't be @@ -432,24 +442,24 @@ void GameState::Update( float fDelta ) ( attack.fStartSecond < this->m_fMusicSeconds && m_fMusicSeconds < attack.fStartSecond+attack.fSecsRemaining ); - if( m_ActiveAttacks[p][s].bOn == bCurrentlyEnabled ) + if( m_pPlayerState[p]->m_ActiveAttacks[s].bOn == bCurrentlyEnabled ) continue; /* OK */ - if( m_ActiveAttacks[p][s].bOn && !bCurrentlyEnabled ) - m_bAttackEndedThisUpdate[p] = true; - else if( !m_ActiveAttacks[p][s].bOn && bCurrentlyEnabled ) - m_bAttackBeganThisUpdate[p] = true; + if( m_pPlayerState[p]->m_ActiveAttacks[s].bOn && !bCurrentlyEnabled ) + m_pPlayerState[p]->m_bAttackEndedThisUpdate = true; + else if( !m_pPlayerState[p]->m_ActiveAttacks[s].bOn && bCurrentlyEnabled ) + m_pPlayerState[p]->m_bAttackBeganThisUpdate = true; bRebuildPlayerOptions = true; - m_ActiveAttacks[p][s].bOn = bCurrentlyEnabled; + m_pPlayerState[p]->m_ActiveAttacks[s].bOn = bCurrentlyEnabled; } if( bRebuildPlayerOptions ) RebuildPlayerOptionsFromActiveAttacks( (PlayerNumber)p ); - if( m_fSecondsUntilAttacksPhasedOut[p] > 0 ) - m_fSecondsUntilAttacksPhasedOut[p] = max( 0, m_fSecondsUntilAttacksPhasedOut[p] - fDelta ); + if( m_pPlayerState[p]->m_fSecondsUntilAttacksPhasedOut > 0 ) + m_pPlayerState[p]->m_fSecondsUntilAttacksPhasedOut = max( 0, m_pPlayerState[p]->m_fSecondsUntilAttacksPhasedOut - fDelta ); } } @@ -531,11 +541,11 @@ void GameState::ResetStageStatistics() m_fTugLifePercentP1 = 0.5f; FOREACH_PlayerNumber( p ) { - m_fSuperMeter[p] = 0; - m_HealthState[p] = ALIVE; + m_pPlayerState[p]->m_fSuperMeter = 0; + m_pPlayerState[p]->m_HealthState = PlayerState::ALIVE; - m_iLastPositiveSumOfAttackLevels[p] = 0; - m_fSecondsUntilAttacksPhasedOut[p] = 0; // PlayerAI not affected + m_pPlayerState[p]->m_iLastPositiveSumOfAttackLevels = 0; + m_pPlayerState[p]->m_fSecondsUntilAttacksPhasedOut = 0; // PlayerAI not affected } @@ -1082,7 +1092,7 @@ void GameState::ApplyModifiers( PlayerNumber pn, CString sModifiers ) { const SongOptions::FailType ft = this->m_SongOptions.m_FailType; - m_PlayerOptions[pn].FromString( sModifiers ); + m_pPlayerState[pn]->m_PlayerOptions.FromString( sModifiers ); m_SongOptions.FromString( sModifiers ); if( ft != this->m_SongOptions.m_FailType ) @@ -1094,7 +1104,7 @@ void GameState::ApplyModifiers( PlayerNumber pn, CString sModifiers ) void GameState::StoreSelectedOptions() { FOREACH_PlayerNumber( p ) - this->m_StoredPlayerOptions[p] = this->m_PlayerOptions[p]; + m_pPlayerState[p]->m_StoredPlayerOptions = m_pPlayerState[p]->m_PlayerOptions; m_StoredSongOptions = m_SongOptions; } @@ -1105,7 +1115,7 @@ void GameState::StoreSelectedOptions() void GameState::RestoreSelectedOptions() { FOREACH_PlayerNumber( p ) - this->m_PlayerOptions[p] = this->m_StoredPlayerOptions[p]; + m_pPlayerState[p]->m_PlayerOptions = m_pPlayerState[p]->m_StoredPlayerOptions; m_SongOptions = m_StoredSongOptions; } @@ -1116,13 +1126,13 @@ bool GameState::IsDisqualified( PlayerNumber pn ) if( GAMESTATE->IsCourseMode() ) { - return GAMESTATE->m_PlayerOptions[pn].IsEasierForCourseAndTrail( + return GAMESTATE->m_pPlayerState[pn]->m_PlayerOptions.IsEasierForCourseAndTrail( GAMESTATE->m_pCurCourse, GAMESTATE->m_pCurTrail[pn] ); } else { - return GAMESTATE->m_PlayerOptions[pn].IsEasierForSongAndSteps( + return GAMESTATE->m_pPlayerState[pn]->m_PlayerOptions.IsEasierForSongAndSteps( GAMESTATE->m_pCurSong, GAMESTATE->m_pCurSteps[pn] ); } @@ -1138,8 +1148,8 @@ void GameState::ResetNoteSkins() void GameState::ResetNoteSkinsForPlayer( PlayerNumber pn ) { - m_BeatToNoteSkin[pn].clear(); - m_BeatToNoteSkin[pn][-1000] = this->m_PlayerOptions[pn].m_sNoteSkin; + m_pPlayerState[pn]->m_BeatToNoteSkin.clear(); + m_pPlayerState[pn]->m_BeatToNoteSkin[-1000] = m_pPlayerState[pn]->m_PlayerOptions.m_sNoteSkin; ++m_BeatToNoteSkinRev; } @@ -1148,7 +1158,7 @@ void GameState::GetAllUsedNoteSkins( vector &out ) const { FOREACH_EnabledPlayer( pn ) { - out.push_back( this->m_PlayerOptions[pn].m_sNoteSkin ); + out.push_back( m_pPlayerState[pn]->m_PlayerOptions.m_sNoteSkin ); switch( this->m_PlayMode ) { @@ -1171,18 +1181,18 @@ void GameState::GetAllUsedNoteSkins( vector &out ) const } } - for( map::const_iterator it = m_BeatToNoteSkin[pn].begin(); - it != m_BeatToNoteSkin[pn].end(); ++it ) + for( map::const_iterator it = m_pPlayerState[pn]->m_BeatToNoteSkin.begin(); + it != m_pPlayerState[pn]->m_BeatToNoteSkin.end(); ++it ) out.push_back( it->second ); } } /* From NoteField: */ -void GameState::GetUndisplayedBeats( PlayerNumber pn, float TotalSeconds, float &StartBeat, float &EndBeat ) const +void GameState::GetUndisplayedBeats( const PlayerState* pPlayerState, float TotalSeconds, float &StartBeat, float &EndBeat ) const { /* If reasonable, push the attack forward so notes on screen don't change suddenly. */ - StartBeat = min( this->m_fSongBeat+BEATS_PER_MEASURE*2, m_fLastDrawnBeat[pn] ); + StartBeat = min( m_fSongBeat+BEATS_PER_MEASURE*2, pPlayerState->m_fLastDrawnBeat ); StartBeat = truncf(StartBeat)+1; const float StartSecond = this->m_pCurSong->GetElapsedTimeFromBeat( StartBeat ); @@ -1192,9 +1202,9 @@ void GameState::GetUndisplayedBeats( PlayerNumber pn, float TotalSeconds, float } -void GameState::SetNoteSkinForBeatRange( PlayerNumber pn, CString sNoteSkin, float StartBeat, float EndBeat ) +void GameState::SetNoteSkinForBeatRange( PlayerState* pPlayerState, const CString& sNoteSkin, float StartBeat, float EndBeat ) { - map &BeatToNoteSkin = m_BeatToNoteSkin[pn]; + map &BeatToNoteSkin = pPlayerState->m_BeatToNoteSkin; /* Erase any other note skin settings in this range. */ map::iterator it = BeatToNoteSkin.lower_bound( StartBeat ); @@ -1213,7 +1223,7 @@ void GameState::SetNoteSkinForBeatRange( PlayerNumber pn, CString sNoteSkin, flo BeatToNoteSkin[StartBeat] = sNoteSkin; /* Return to the default note skin after the duration. */ - BeatToNoteSkin[EndBeat] = m_StoredPlayerOptions[pn].m_sNoteSkin; + BeatToNoteSkin[EndBeat] = pPlayerState->m_StoredPlayerOptions.m_sNoteSkin; ++m_BeatToNoteSkinRev; } @@ -1230,21 +1240,21 @@ void GameState::LaunchAttack( PlayerNumber target, const Attack& a ) * mark the real time it's starting (now), so Update() can know when the attack started * so it can be removed later. For m_ModsToApply, leave the -1 in, so Player::Update * knows to apply attack transforms correctly. (yuck) */ - m_ModsToApply[target].push_back( attack ); + m_pPlayerState[target]->m_ModsToApply.push_back( attack ); if( attack.fStartSecond == -1 ) attack.fStartSecond = this->m_fMusicSeconds; - m_ActiveAttacks[target].push_back( attack ); + m_pPlayerState[target]->m_ActiveAttacks.push_back( attack ); this->RebuildPlayerOptionsFromActiveAttacks( target ); } void GameState::RemoveActiveAttacksForPlayer( PlayerNumber pn, AttackLevel al ) { - for( unsigned s=0; sm_ActiveAttacks.size(); s++ ) { - if( al != NUM_ATTACK_LEVELS && al != m_ActiveAttacks[pn][s].level ) + if( al != NUM_ATTACK_LEVELS && al != m_pPlayerState[pn]->m_ActiveAttacks[s].level ) continue; - m_ActiveAttacks[pn].erase( m_ActiveAttacks[pn].begin()+s, m_ActiveAttacks[pn].begin()+s+1 ); + m_pPlayerState[pn]->m_ActiveAttacks.erase( m_pPlayerState[pn]->m_ActiveAttacks.begin()+s, m_pPlayerState[pn]->m_ActiveAttacks.begin()+s+1 ); --s; } RebuildPlayerOptionsFromActiveAttacks( pn ); @@ -1253,36 +1263,38 @@ void GameState::RemoveActiveAttacksForPlayer( PlayerNumber pn, AttackLevel al ) void GameState::RemoveAllInventory() { FOREACH_PlayerNumber( p ) + { for( int s=0; sm_Inventory[s].fSecsRemaining = 0; + m_pPlayerState[p]->m_Inventory[s].sModifier = ""; } + } } void GameState::RebuildPlayerOptionsFromActiveAttacks( PlayerNumber pn ) { // rebuild player options - PlayerOptions po = m_StoredPlayerOptions[pn]; - for( unsigned s=0; sm_StoredPlayerOptions; + for( unsigned s=0; sm_ActiveAttacks.size(); s++ ) { - if( !m_ActiveAttacks[pn][s].bOn ) + if( !m_pPlayerState[pn]->m_ActiveAttacks[s].bOn ) continue; /* hasn't started yet */ - po.FromString( m_ActiveAttacks[pn][s].sModifier ); + po.FromString( m_pPlayerState[pn]->m_ActiveAttacks[s].sModifier ); } - m_PlayerOptions[pn] = po; + m_pPlayerState[pn]->m_PlayerOptions = po; int iSumOfAttackLevels = GetSumOfActiveAttackLevels( pn ); if( iSumOfAttackLevels > 0 ) { - m_iLastPositiveSumOfAttackLevels[pn] = iSumOfAttackLevels; - m_fSecondsUntilAttacksPhasedOut[pn] = 10000; // any positive number that won't run out before the attacks + m_pPlayerState[pn]->m_iLastPositiveSumOfAttackLevels = iSumOfAttackLevels; + m_pPlayerState[pn]->m_fSecondsUntilAttacksPhasedOut = 10000; // any positive number that won't run out before the attacks } else { // don't change! m_iLastPositiveSumOfAttackLevels[p] = iSumOfAttackLevels; - m_fSecondsUntilAttacksPhasedOut[pn] = 2; // 2 seconds to phase out + m_pPlayerState[pn]->m_fSecondsUntilAttacksPhasedOut = 2; // 2 seconds to phase out } } @@ -1296,9 +1308,9 @@ int GameState::GetSumOfActiveAttackLevels( PlayerNumber pn ) const { int iSum = 0; - for( unsigned s=0; s 0 && m_ActiveAttacks[pn][s].level != NUM_ATTACK_LEVELS ) - iSum += m_ActiveAttacks[pn][s].level; + for( unsigned s=0; sm_ActiveAttacks.size(); s++ ) + if( m_pPlayerState[pn]->m_ActiveAttacks[s].fSecsRemaining > 0 && m_pPlayerState[pn]->m_ActiveAttacks[s].level != NUM_ATTACK_LEVELS ) + iSum += m_pPlayerState[pn]->m_ActiveAttacks[s].level; return iSum; } @@ -1674,7 +1686,7 @@ void GameState::StoreRankingName( PlayerNumber pn, CString name ) bool GameState::AllAreInDangerOrWorse() const { FOREACH_EnabledPlayer( p ) - if( m_HealthState[p] < DANGER ) + if( m_pPlayerState[p]->m_HealthState < PlayerState::DANGER ) return false; return true; } @@ -1682,7 +1694,7 @@ bool GameState::AllAreInDangerOrWorse() const bool GameState::AllAreDead() const { FOREACH_EnabledPlayer( p ) - if( m_HealthState[p] < DEAD ) + if( m_pPlayerState[p]->m_HealthState < PlayerState::DEAD ) return false; return true; } @@ -1698,7 +1710,7 @@ bool GameState::AllHaveComboOf30OrMoreMisses() const bool GameState::OneIsHot() const { FOREACH_EnabledPlayer( p ) - if( m_HealthState[p] == HOT ) + if( m_pPlayerState[p]->m_HealthState == PlayerState::HOT ) return true; return false; } @@ -1870,12 +1882,12 @@ Difficulty GameState::GetEasiestNotesDifficulty() const bool PlayerIsUsingModifier( PlayerNumber pn, const CString sModifier ) { - PlayerOptions po = GAMESTATE->m_PlayerOptions[pn]; + PlayerOptions po = GAMESTATE->m_pPlayerState[pn]->m_PlayerOptions; SongOptions so = GAMESTATE->m_SongOptions; po.FromString( sModifier ); so.FromString( sModifier ); - return po == GAMESTATE->m_PlayerOptions[pn] && so == GAMESTATE->m_SongOptions; + return po == GAMESTATE->m_pPlayerState[pn]->m_PlayerOptions && so == GAMESTATE->m_SongOptions; } #include "LuaFunctions.h" diff --git a/stepmania/src/GameState.h b/stepmania/src/GameState.h index 10991dbf2b..66e28424a5 100644 --- a/stepmania/src/GameState.h +++ b/stepmania/src/GameState.h @@ -4,7 +4,6 @@ #define GAMESTATE_H #include "GameConstantsAndTypes.h" -#include "PlayerOptions.h" #include "SongOptions.h" #include "Grade.h" #include "Attack.h" @@ -24,6 +23,7 @@ class NoteFieldPositioning; class Character; class TimingData; struct StageStats; +struct PlayerState; class GameState { @@ -89,13 +89,6 @@ public: Character* GameState::GetRandomCharacter(); Character* GameState::GetDefaultCharacter(); - PlayerController m_PlayerController[NUM_PLAYERS]; - - // Used in Battle and Rave - int m_iCpuSkill[NUM_PLAYERS]; // only used when m_PlayerController is PC_CPU - // Used in Rave - float m_fSuperMeterGrowthScale[NUM_PLAYERS]; - bool IsCourseMode() const; bool IsBattleMode() const; /* not Rave */ @@ -155,9 +148,7 @@ public: bool m_bFreeze; // in the middle of a freeze RageTimer m_LastBeatUpdate; // time of last m_fSongBeat, etc. update bool m_bPastHereWeGo; - float m_fLastDrawnBeat[NUM_PLAYERS]; // set by NoteField - map m_BeatToNoteSkin[NUM_PLAYERS]; int m_BeatToNoteSkinRev; /* hack: incremented whenever m_BeatToNoteSkin changes */ void ResetNoteSkins(); void ResetNoteSkinsForPlayer( PlayerNumber pn ); @@ -169,36 +160,21 @@ public: void UpdateSongPosition( float fPositionSeconds, const TimingData &timing, const RageTimer ×tamp = RageZeroTimer ); float GetSongPercent( float beat ) const; - enum HealthState { HOT, ALIVE, DANGER, DEAD }; - HealthState m_HealthState[NUM_PLAYERS]; bool AllAreInDangerOrWorse() const; bool AllAreDead() const; bool AllHaveComboOf30OrMoreMisses() const; bool OneIsHot() const; // used in PLAY_MODE_BATTLE and PLAY_MODE_RAVE - AttackArray m_ActiveAttacks[NUM_PLAYERS]; - - // Attacks take a while to transition out of use. Account for this in PlayerAI - // by still penalizing it for 1 second after the player options are rebuilt. - int m_iLastPositiveSumOfAttackLevels[NUM_PLAYERS]; - float m_fSecondsUntilAttacksPhasedOut[NUM_PLAYERS]; // positive means PlayerAI is still affected - - vector m_ModsToApply[NUM_PLAYERS]; - - void SetNoteSkinForBeatRange( PlayerNumber pn, CString sNoteSkin, float StartBeat, float EndBeat ); + void SetNoteSkinForBeatRange( PlayerState* pPlayerState, const CString& sNoteSkin, float StartBeat, float EndBeat ); // used in PLAY_MODE_BATTLE - Attack m_Inventory[NUM_PLAYERS][NUM_INVENTORY_SLOTS]; float m_fOpponentHealthPercent; // used in PLAY_MODE_RAVE float m_fTugLifePercentP1; - float m_fSuperMeter[NUM_PLAYERS]; // between 0 and NUM_ATTACK_LEVELS - bool m_bAttackBeganThisUpdate[NUM_PLAYERS]; // flag for other objects to watch (play sounds) - bool m_bAttackEndedThisUpdate[NUM_PLAYERS]; // flag for other objects to watch (play sounds) - void GetUndisplayedBeats( PlayerNumber pn, float TotalSeconds, float &StartBeat, float &EndBeat ) const; // only meaningful when a NoteField is in use + void GetUndisplayedBeats( const PlayerState* pPlayerState, float TotalSeconds, float &StartBeat, float &EndBeat ) const; // only meaningful when a NoteField is in use void LaunchAttack( PlayerNumber target, const Attack& a ); void RebuildPlayerOptionsFromActiveAttacks( PlayerNumber pn ); void RemoveAllActiveAttacks(); // called on end of song @@ -216,9 +192,6 @@ public: // Options stuff // - PlayerOptions m_CurrentPlayerOptions[NUM_PLAYERS]; // current approaches destination - PlayerOptions m_PlayerOptions[NUM_PLAYERS]; // change this, and current will move gradually toward it - PlayerOptions m_StoredPlayerOptions[NUM_PLAYERS]; // user's choices on the PlayerOptions screen SongOptions m_SongOptions; SongOptions m_StoredSongOptions; @@ -292,6 +265,11 @@ public: // void GetDifficultiesToShow( set &AddTo ); void GetCourseDifficultiesToShow( set &AddTo ); + + // + // PlayerState + // + PlayerState* m_pPlayerState[NUM_PLAYERS]; }; diff --git a/stepmania/src/GhostArrowRow.cpp b/stepmania/src/GhostArrowRow.cpp index a01088edb9..bb6847ca69 100644 --- a/stepmania/src/GhostArrowRow.cpp +++ b/stepmania/src/GhostArrowRow.cpp @@ -9,6 +9,7 @@ #include "PrefsManager.h" #include "NoteFieldPositioning.h" #include "Game.h" +#include "PlayerState.h" GhostArrowRow::GhostArrowRow() @@ -16,11 +17,11 @@ GhostArrowRow::GhostArrowRow() m_iNumCols = 0; } #include "RageLog.h" -void GhostArrowRow::Load( PlayerNumber pn, CString NoteSkin, float fYReverseOffset ) +void GhostArrowRow::Load( const PlayerState* pPlayerState, CString NoteSkin, float fYReverseOffset ) { Unload(); - m_PlayerNumber = pn; + m_pPlayerState = pPlayerState; m_fYReverseOffsetPixels = fYReverseOffset; const Style* pStyle = GAMESTATE->GetCurrentStyle(); @@ -30,6 +31,8 @@ void GhostArrowRow::Load( PlayerNumber pn, CString NoteSkin, float fYReverseOffs // init arrows for( int c=0; cm_PlayerNumber; NoteFieldMode &mode = g_NoteFieldMode[pn]; CString Button = mode.GhostButtonNames[c]; if( Button == "" ) @@ -78,9 +81,9 @@ void GhostArrowRow::Update( float fDeltaTime ) m_GhostBright[c]->Update( fDeltaTime ); m_HoldGhost[c]->Update( fDeltaTime ); - const float fX = ArrowGetXPos( m_PlayerNumber, c, 0 ); - const float fY = ArrowGetYPos( m_PlayerNumber, c, 0, m_fYReverseOffsetPixels ); - const float fZ = ArrowGetZPos( m_PlayerNumber, c, 0 ); + const float fX = ArrowEffects::GetXPos( m_pPlayerState, c, 0 ); + const float fY = ArrowEffects::GetYPos( m_pPlayerState, c, 0, m_fYReverseOffsetPixels ); + const float fZ = ArrowEffects::GetZPos( m_pPlayerState, c, 0 ); m_GhostDim[c]->SetX( fX ); m_GhostBright[c]->SetX( fX ); @@ -94,7 +97,7 @@ void GhostArrowRow::Update( float fDeltaTime ) m_GhostBright[c]->SetZ( fZ ); m_HoldGhost[c]->SetZ( fZ ); - const float fZoom = ArrowGetZoom( m_PlayerNumber ); + const float fZoom = ArrowEffects::GetZoom( m_pPlayerState ); m_GhostDim[c]->SetZoom( fZoom ); m_GhostBright[c]->SetZoom( fZoom ); m_HoldGhost[c]->SetZoom( fZoom ); @@ -105,13 +108,16 @@ void GhostArrowRow::DrawPrimitives() { for( int c=0; cm_PlayerNumber; + + g_NoteFieldMode[pn].BeginDrawTrack(c); m_GhostDim[c]->Draw(); m_GhostBright[c]->Draw(); m_HoldGhost[c]->Draw(); - g_NoteFieldMode[m_PlayerNumber].EndDrawTrack(c); + g_NoteFieldMode[pn].EndDrawTrack(c); } } diff --git a/stepmania/src/GhostArrowRow.h b/stepmania/src/GhostArrowRow.h index 4bb347347e..a7be2a53bd 100644 --- a/stepmania/src/GhostArrowRow.h +++ b/stepmania/src/GhostArrowRow.h @@ -7,9 +7,8 @@ #include "GhostArrow.h" #include "HoldGhostArrow.h" #include "GameConstantsAndTypes.h" -#include "Style.h" - +struct PlayerState; class GhostArrowRow : public ActorFrame { @@ -20,7 +19,7 @@ public: virtual void DrawPrimitives(); virtual void CopyTweening( const GhostArrowRow &from ); - void Load( PlayerNumber pn, CString NoteSkin, float fYReverseOffset ); + void Load( const PlayerState* pPlayerState, CString NoteSkin, float fYReverseOffset ); void Unload(); void DidTapNote( int iCol, TapNoteScore score, bool bBright ); @@ -29,7 +28,7 @@ public: protected: int m_iNumCols; float m_fYReverseOffsetPixels; - PlayerNumber m_PlayerNumber; + const PlayerState* m_pPlayerState; vector m_GhostDim; vector m_GhostBright; diff --git a/stepmania/src/Inventory.cpp b/stepmania/src/Inventory.cpp index b4102f4d8d..904b6c7c06 100644 --- a/stepmania/src/Inventory.cpp +++ b/stepmania/src/Inventory.cpp @@ -10,6 +10,7 @@ #include "ScreenGameplay.h" #include "StageStats.h" #include "ThemeMetric.h" +#include "PlayerState.h" #define NUM_ITEM_TYPES THEME->GetMetricF("Inventory","NumItemTypes") @@ -61,11 +62,11 @@ Inventory::~Inventory() m_vpSoundUseItem.clear(); } -void Inventory::Load( PlayerNumber pn ) +void Inventory::Load( PlayerState* pPlayerState ) { ReloadItems(); - m_PlayerNumber = pn; + m_pPlayerState = pPlayerState; m_iLastSeenCombo = 0; // don't load battle sounds if they're not going to be used @@ -87,10 +88,11 @@ void Inventory::Load( PlayerNumber pn ) void Inventory::Update( float fDelta ) { - if( GAMESTATE->m_bAttackEndedThisUpdate[m_PlayerNumber] ) + if( m_pPlayerState->m_bAttackEndedThisUpdate ) m_soundItemEnding.Play(); - PlayerNumber pn = m_PlayerNumber; + // TODO: remove use of PlayerNumber + PlayerNumber pn = m_pPlayerState->m_PlayerNumber; // check to see if they deserve a new item if( g_CurStageStats.iCurCombo[pn] != m_iLastSeenCombo ) @@ -120,7 +122,7 @@ void Inventory::Update( float fDelta ) // use items if this player is CPU-controlled - if( GAMESTATE->m_PlayerController[m_PlayerNumber] != PC_HUMAN && + if( m_pPlayerState->m_PlayerController != PC_HUMAN && GAMESTATE->m_fSongBeat < GAMESTATE->m_pCurSong->m_fLastBeat ) { // every 1 seconds, try to use an item @@ -129,7 +131,7 @@ void Inventory::Update( float fDelta ) if( iLastSecond != iThisSecond ) { for( int s=0; sm_Inventory[m_PlayerNumber][s].IsBlank() ) + if( !m_pPlayerState->m_Inventory[s].IsBlank() ) if( randomf(0,1) < ITEM_USE_PROBABILITY ) UseItem( s ); } @@ -140,25 +142,29 @@ void Inventory::AwardItem( int iItemIndex ) { // CPU player is vanity only. It should have no effect on gameplay // and should not aquire/launch attacks. - if( GAMESTATE->IsCpuPlayer(m_PlayerNumber) ) + if( m_pPlayerState->m_PlayerController == PC_CPU ) return; // search for the first open slot int iOpenSlot = -1; - Attack* asInventory = GAMESTATE->m_Inventory[m_PlayerNumber]; //[NUM_INVENTORY_SLOTS] + Attack* pInventory = m_pPlayerState->m_Inventory; //[NUM_INVENTORY_SLOTS] - if( asInventory[NUM_INVENTORY_SLOTS/2].IsBlank() ) + if( pInventory[NUM_INVENTORY_SLOTS/2].IsBlank() ) + { iOpenSlot = NUM_INVENTORY_SLOTS/2; + } else { for( int s=0; sm_Inventory[m_PlayerNumber]; //[NUM_INVENTORY_SLOTS] + Attack* pInventory = m_pPlayerState->m_Inventory; //[NUM_INVENTORY_SLOTS] - if( asInventory[iSlot].IsBlank() ) + if( pInventory[iSlot].IsBlank() ) return; - PlayerNumber pnToAttack = OPPOSITE_PLAYER[m_PlayerNumber]; - Attack a = asInventory[iSlot]; + PlayerNumber pn = m_pPlayerState->m_PlayerNumber; + PlayerNumber pnToAttack = OPPOSITE_PLAYER[pn]; + Attack a = pInventory[iSlot]; // remove the item - asInventory[iSlot].MakeBlank(); + pInventory[iSlot].MakeBlank(); m_vpSoundUseItem[a.level]->Play(); GAMESTATE->LaunchAttack( pnToAttack, a ); diff --git a/stepmania/src/Inventory.h b/stepmania/src/Inventory.h index cb07e71a4f..d17a7e4686 100644 --- a/stepmania/src/Inventory.h +++ b/stepmania/src/Inventory.h @@ -7,13 +7,14 @@ #include "PlayerNumber.h" #include "RageSound.h" +struct PlayerState; class Inventory : public Actor { public: Inventory(); ~Inventory(); - void Load( PlayerNumber pn ); + void Load( PlayerState* pPlayerState ); virtual void Update( float fDelta ); virtual void DrawPrimitives() {}; @@ -23,7 +24,7 @@ public: protected: void AwardItem( int iItemIndex ); - PlayerNumber m_PlayerNumber; + PlayerState* m_pPlayerState; int m_iLastSeenCombo; RageSound m_soundAcquireItem; diff --git a/stepmania/src/LifeMeterBar.cpp b/stepmania/src/LifeMeterBar.cpp index 5afa881f40..b5eec87107 100644 --- a/stepmania/src/LifeMeterBar.cpp +++ b/stepmania/src/LifeMeterBar.cpp @@ -9,6 +9,7 @@ #include "song.h" #include "StageStats.h" #include "ThemeMetric.h" +#include "PlayerState.h" static ThemeMetric METER_WIDTH ("LifeMeterBar","MeterWidth"); @@ -466,9 +467,9 @@ void LifeMeterBar::AfterLifeChanged() bool LifeMeterBar::IsPastPassmark() const { - if( GAMESTATE->m_PlayerOptions[m_PlayerNumber].m_fPassmark > 0 ) + if( GAMESTATE->m_pPlayerState[m_PlayerNumber]->m_PlayerOptions.m_fPassmark > 0 ) { - return m_fLifePercentage >= GAMESTATE->m_PlayerOptions[m_PlayerNumber].m_fPassmark; + return m_fLifePercentage >= GAMESTATE->m_pPlayerState[m_PlayerNumber]->m_PlayerOptions.m_fPassmark; } else { diff --git a/stepmania/src/Makefile.am b/stepmania/src/Makefile.am index 01d51d16f7..0ecc41d545 100644 --- a/stepmania/src/Makefile.am +++ b/stepmania/src/Makefile.am @@ -65,7 +65,7 @@ NoteFieldPositioning.cpp NoteFieldPositioning.h NoteTypes.cpp NoteTypes.h NotesL NotesLoaderBMS.cpp NotesLoaderBMS.h NotesLoaderDWI.cpp NotesLoaderDWI.h NotesLoaderKSF.cpp NotesLoaderKSF.h \ NotesLoaderSM.cpp NotesLoaderSM.h NotesWriterDWI.cpp NotesWriterDWI.h NotesWriterSM.cpp NotesWriterSM.h \ PlayerAI.cpp PlayerAI.h PlayerNumber.cpp PlayerNumber.h PlayerOptions.cpp PlayerOptions.h \ -Preference.cpp Preference.h Profile.cpp Profile.h \ +PlayerState.cpp PlayerState.h Preference.cpp Preference.h Profile.cpp Profile.h \ RandomSample.cpp RandomSample.h RadarValues.cpp RadarValues.h ScreenDimensions.h ScreenDimensions.cpp \ ScoreKeeper.h ScoreKeeperMAX2.cpp ScoreKeeperMAX2.h \ ScoreKeeperRave.cpp ScoreKeeperRave.h Song.cpp song.h SongCacheIndex.cpp SongCacheIndex.h \ diff --git a/stepmania/src/MusicWheel.cpp b/stepmania/src/MusicWheel.cpp index 6b26aeec52..ce43f1ef63 100644 --- a/stepmania/src/MusicWheel.cpp +++ b/stepmania/src/MusicWheel.cpp @@ -24,6 +24,7 @@ #include "Foreach.h" #include "Style.h" #include "ThemeMetric.h" +#include "PlayerState.h" #define FADE_SECONDS THEME->GetMetricF("MusicWheel","FadeSeconds") @@ -142,14 +143,11 @@ void MusicWheel::Load() po, so ); GAMESTATE->m_pCurSong = GAMESTATE->m_pPreferredSong = pSong; - FOREACH_PlayerNumber( p ) + FOREACH_HumanPlayer( p ) { - if( GAMESTATE->IsHumanPlayer(p) ) - { - GAMESTATE->m_pCurSteps[p] = pSteps; - GAMESTATE->m_PlayerOptions[p] = po; - GAMESTATE->m_PreferredDifficulty[p] = pSteps->GetDifficulty(); - } + GAMESTATE->m_pCurSteps[p] = pSteps; + GAMESTATE->m_pPlayerState[p]->m_PlayerOptions = po; + GAMESTATE->m_PreferredDifficulty[p] = pSteps->GetDifficulty(); } GAMESTATE->m_SongOptions = so; } diff --git a/stepmania/src/NetworkSyncManager.cpp b/stepmania/src/NetworkSyncManager.cpp index 05af2ea40d..0ab9e800d8 100644 --- a/stepmania/src/NetworkSyncManager.cpp +++ b/stepmania/src/NetworkSyncManager.cpp @@ -39,6 +39,7 @@ void NetworkSyncManager::SelectUserSong() { } #include "ScreenMessage.h" #include "GameManager.h" #include "arch/LoadingWindow/LoadingWindow.h" +#include "PlayerState.h" const ScreenMessage SM_AddToChat = ScreenMessage(SM_User+4); const ScreenMessage SM_ChangeSong = ScreenMessage(SM_User+5); @@ -418,7 +419,7 @@ void NetworkSyncManager::StartRequest(short position) FOREACH_PlayerNumber (p) { ++players; - m_packet.WriteNT(GAMESTATE->m_PlayerOptions[p].GetString()); + m_packet.WriteNT(GAMESTATE->m_pPlayerState[p]->m_PlayerOptions.GetString()); } for (int i=0; i<2-players; ++i) m_packet.WriteNT(""); //Write a NULL if no player @@ -697,7 +698,7 @@ void NetworkSyncManager::ReportPlayerOptions() m_packet.ClearPacket(); m_packet.Write1( NSCUPOpts ); FOREACH_PlayerNumber (pn) - m_packet.WriteNT( GAMESTATE->m_PlayerOptions[pn].GetString() ); + m_packet.WriteNT( GAMESTATE->m_pPlayerState[pn]->m_PlayerOptions.GetString() ); NetPlayerClient->SendPack((char*)&m_packet.Data, m_packet.Position); } diff --git a/stepmania/src/NoteDataUtil.cpp b/stepmania/src/NoteDataUtil.cpp index fa2f60057f..a40465d7cf 100644 --- a/stepmania/src/NoteDataUtil.cpp +++ b/stepmania/src/NoteDataUtil.cpp @@ -1580,7 +1580,7 @@ void NoteDataUtil::TransformNoteData( NoteData &nd, const AttackArray &aa, Steps if( po.ContainsTransformOrTurn() ) { float fStartBeat, fEndBeat; - a->GetAttackBeats( pSong, PLAYER_INVALID, fStartBeat, fEndBeat ); + a->GetAttackBeats( pSong, NULL, fStartBeat, fEndBeat ); NoteDataUtil::TransformNoteData( nd, po, st, fStartBeat, fEndBeat ); } diff --git a/stepmania/src/NoteDisplay.cpp b/stepmania/src/NoteDisplay.cpp index 4a77515cf6..247b87ee85 100644 --- a/stepmania/src/NoteDisplay.cpp +++ b/stepmania/src/NoteDisplay.cpp @@ -13,6 +13,7 @@ #include "ActorUtil.h" #include "NoteDataWithScoring.h" #include "Game.h" +#include "PlayerState.h" enum part { @@ -224,12 +225,14 @@ NoteDisplay::~NoteDisplay() delete cache; } -void NoteDisplay::Load( int iColNum, PlayerNumber pn, CString NoteSkin, float fYReverseOffsetPixels ) +void NoteDisplay::Load( int iColNum, const PlayerState* pPlayerState, CString NoteSkin, float fYReverseOffsetPixels ) { - m_PlayerNumber = pn; + m_pPlayerState = pPlayerState; m_fYReverseOffsetPixels = fYReverseOffsetPixels; /* Normally, this is empty and we use the style table entry via ColToButtonName. */ + // TODO: Remove indexing with PlayerNumber. + PlayerNumber pn = m_pPlayerState->m_PlayerNumber; NoteFieldMode &mode = g_NoteFieldMode[pn]; CString Button = mode.NoteButtonNames[iColNum]; if( Button == "" ) @@ -555,12 +558,12 @@ Actor* NoteDisplay::GetHoldTailActor( float fNoteBeat, bool bIsBeingHeld ) return pActorOut; } -static float ArrowGetAlphaOrGlow( bool bGlow, PlayerNumber pn, int iCol, float fYOffset, float fPercentFadeToFail, float fYReverseOffsetPixels ) +static float ArrowGetAlphaOrGlow( bool bGlow, const PlayerState* pPlayerState, int iCol, float fYOffset, float fPercentFadeToFail, float fYReverseOffsetPixels ) { if( bGlow ) - return ArrowGetGlow( pn, iCol, fYOffset, fPercentFadeToFail, fYReverseOffsetPixels ); + return ArrowEffects::GetGlow( pPlayerState, iCol, fYOffset, fPercentFadeToFail, fYReverseOffsetPixels ); else - return ArrowGetAlpha( pn, iCol, fYOffset, fPercentFadeToFail, fYReverseOffsetPixels ); + return ArrowEffects::GetAlpha( pPlayerState, iCol, fYOffset, fPercentFadeToFail, fYReverseOffsetPixels ); } struct StripBuffer @@ -590,7 +593,7 @@ void NoteDisplay::DrawHoldTopCap( const HoldNote& hn, const bool bIsBeingHeld, f Sprite* pSprTopCap = GetHoldTopCapSprite( hn.GetStartBeat(), bIsBeingHeld ); - pSprTopCap->SetZoom( ArrowGetZoom( m_PlayerNumber ) ); + pSprTopCap->SetZoom( ArrowEffects::GetZoom( m_pPlayerState ) ); // draw manually in small segments RageTexture* pTexture = pSprTopCap->GetTexture(); @@ -622,16 +625,16 @@ void NoteDisplay::DrawHoldTopCap( const HoldNote& hn, const bool bIsBeingHeld, f bLast = true; } - const float fYOffset = ArrowGetYOffsetFromYPos( m_PlayerNumber, iCol, fY, m_fYReverseOffsetPixels ); - const float fZ = ArrowGetZPos( m_PlayerNumber, iCol, fYOffset ); - const float fX = ArrowGetXPos( m_PlayerNumber, iCol, fYOffset ); + const float fYOffset = ArrowEffects::GetYOffsetFromYPos( m_pPlayerState, iCol, fY, m_fYReverseOffsetPixels ); + const float fZ = ArrowEffects::GetZPos( m_pPlayerState, iCol, fYOffset ); + const float fX = ArrowEffects::GetXPos( m_pPlayerState, iCol, fYOffset ); const float fXLeft = fX - fFrameWidth/2; const float fXRight = fX + fFrameWidth/2; const float fTopDistFromHeadTop = fY - fYCapTop; const float fTexCoordTop = SCALE( fTopDistFromHeadTop, 0, fFrameHeight, pRect->top, pRect->bottom ); const float fTexCoordLeft = pRect->left; const float fTexCoordRight = pRect->right; - const float fAlpha = ArrowGetAlphaOrGlow( bGlow, m_PlayerNumber, iCol, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels ); + const float fAlpha = ArrowGetAlphaOrGlow( bGlow, m_pPlayerState, iCol, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels ); const RageColor color = RageColor(fColorScale,fColorScale,fColorScale,fAlpha); if( fAlpha > 0 ) @@ -665,7 +668,7 @@ void NoteDisplay::DrawHoldBody( const HoldNote& hn, const bool bIsBeingHeld, flo Sprite* pSprBody = GetHoldBodySprite( hn.GetStartBeat(), bIsBeingHeld ); - pSprBody->SetZoom( ArrowGetZoom( m_PlayerNumber ) ); + pSprBody->SetZoom( ArrowEffects::GetZoom( m_pPlayerState ) ); // draw manually in small segments RageTexture* pTexture = pSprBody->GetTexture(); @@ -682,7 +685,7 @@ void NoteDisplay::DrawHoldBody( const HoldNote& hn, const bool bIsBeingHeld, flo const float fYBodyTop = fYHead + cache->m_iStartDrawingHoldBodyOffsetFromHead; const float fYBodyBottom = fYTail + cache->m_iStopDrawingHoldBodyOffsetFromTail; - const bool bReverse = GAMESTATE->m_CurrentPlayerOptions[m_PlayerNumber].GetReversePercentForColumn(iCol) > 0.5; + const bool bReverse = m_pPlayerState->m_CurrentPlayerOptions.GetReversePercentForColumn(iCol) > 0.5; bool bAnchorToBottom = bReverse && cache->m_bFlipHeadAndTailWhenReverse; if( bGlow ) @@ -699,9 +702,9 @@ void NoteDisplay::DrawHoldBody( const HoldNote& hn, const bool bIsBeingHeld, flo bLast = true; } - const float fYOffset = ArrowGetYOffsetFromYPos( m_PlayerNumber, iCol, fY, m_fYReverseOffsetPixels ); - const float fZ = ArrowGetZPos( m_PlayerNumber, iCol, fYOffset ); - const float fX = ArrowGetXPos( m_PlayerNumber, iCol, fYOffset ); + const float fYOffset = ArrowEffects::GetYOffsetFromYPos( m_pPlayerState, iCol, fY, m_fYReverseOffsetPixels ); + const float fZ = ArrowEffects::GetZPos( m_pPlayerState, iCol, fYOffset ); + const float fX = ArrowEffects::GetXPos( m_pPlayerState, iCol, fYOffset ); const float fXLeft = fX - fFrameWidth/2; const float fXRight = fX + fFrameWidth/2; const float fDistFromBodyBottom = fYBodyBottom - fY; @@ -709,7 +712,7 @@ void NoteDisplay::DrawHoldBody( const HoldNote& hn, const bool bIsBeingHeld, flo const float fTexCoordTop = SCALE( bAnchorToBottom ? fDistFromBodyTop : fDistFromBodyBottom, 0, fFrameHeight, pRect->bottom, pRect->top ); const float fTexCoordLeft = pRect->left; const float fTexCoordRight = pRect->right; - const float fAlpha = ArrowGetAlphaOrGlow( bGlow, m_PlayerNumber, iCol, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels ); + const float fAlpha = ArrowGetAlphaOrGlow( bGlow, m_pPlayerState, iCol, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels ); const RageColor color = RageColor(fColorScale,fColorScale,fColorScale,fAlpha); if( fAlpha > 0 ) @@ -743,7 +746,7 @@ void NoteDisplay::DrawHoldBottomCap( const HoldNote& hn, const bool bIsBeingHeld Sprite* pBottomCap = GetHoldBottomCapSprite( hn.GetStartBeat(), bIsBeingHeld ); - pBottomCap->SetZoom( ArrowGetZoom( m_PlayerNumber ) ); + pBottomCap->SetZoom( ArrowEffects::GetZoom( m_pPlayerState ) ); // draw manually in small segments RageTexture* pTexture = pBottomCap->GetTexture(); @@ -774,16 +777,16 @@ void NoteDisplay::DrawHoldBottomCap( const HoldNote& hn, const bool bIsBeingHeld bLast = true; } - const float fYOffset = ArrowGetYOffsetFromYPos( m_PlayerNumber, iCol, fY, m_fYReverseOffsetPixels ); - const float fZ = ArrowGetZPos( m_PlayerNumber, iCol, fYOffset ); - const float fX = ArrowGetXPos( m_PlayerNumber, iCol, fYOffset ); + const float fYOffset = ArrowEffects::GetYOffsetFromYPos( m_pPlayerState, iCol, fY, m_fYReverseOffsetPixels ); + const float fZ = ArrowEffects::GetZPos( m_pPlayerState, iCol, fYOffset ); + const float fX = ArrowEffects::GetXPos( m_pPlayerState, iCol, fYOffset ); const float fXLeft = fX - fFrameWidth/2; const float fXRight = fX + fFrameWidth/2; const float fTopDistFromTail = fY - fYCapTop; const float fTexCoordTop = SCALE( fTopDistFromTail, 0, fFrameHeight, pRect->top, pRect->bottom ); const float fTexCoordLeft = pRect->left; const float fTexCoordRight = pRect->right; - const float fAlpha = ArrowGetAlphaOrGlow( bGlow, m_PlayerNumber, iCol, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels ); + const float fAlpha = ArrowGetAlphaOrGlow( bGlow, m_pPlayerState, iCol, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels ); const RageColor color = RageColor(fColorScale,fColorScale,fColorScale,fAlpha); if( fAlpha > 0 ) @@ -814,14 +817,14 @@ void NoteDisplay::DrawHoldTail( const HoldNote& hn, bool bIsBeingHeld, float fYT // Actor* pSprTail = GetHoldTailActor( hn.GetStartBeat(), bIsBeingHeld ); - pSprTail->SetZoom( ArrowGetZoom( m_PlayerNumber ) ); + pSprTail->SetZoom( ArrowEffects::GetZoom( m_pPlayerState ) ); const float fY = fYTail; - const float fYOffset = ArrowGetYOffsetFromYPos( m_PlayerNumber, iCol, fY, m_fYReverseOffsetPixels ); - const float fX = ArrowGetXPos( m_PlayerNumber, iCol, fYOffset ); - const float fZ = ArrowGetZPos( m_PlayerNumber, iCol, fYOffset ); - const float fAlpha = ArrowGetAlpha( m_PlayerNumber, iCol, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels ); - const float fGlow = ArrowGetGlow( m_PlayerNumber, iCol, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels ); + const float fYOffset = ArrowEffects::GetYOffsetFromYPos( m_pPlayerState, iCol, fY, m_fYReverseOffsetPixels ); + const float fX = ArrowEffects::GetXPos( m_pPlayerState, iCol, fYOffset ); + const float fZ = ArrowEffects::GetZPos( m_pPlayerState, iCol, fYOffset ); + const float fAlpha = ArrowEffects::GetAlpha( m_pPlayerState, iCol, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels ); + const float fGlow = ArrowEffects::GetGlow( m_pPlayerState, iCol, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels ); const RageColor colorDiffuse= RageColor(fColorScale,fColorScale,fColorScale,fAlpha); const RageColor colorGlow = RageColor(1,1,1,fGlow); @@ -866,15 +869,15 @@ void NoteDisplay::DrawHoldHead( const HoldNote& hn, bool bIsBeingHeld, float fYH // Actor* pActor = GetHoldHeadActor( hn.GetStartBeat(), bIsBeingHeld ); - pActor->SetZoom( ArrowGetZoom( m_PlayerNumber ) ); + pActor->SetZoom( ArrowEffects::GetZoom( m_pPlayerState ) ); // draw with normal Sprite const float fY = fYHead; - const float fYOffset = ArrowGetYOffsetFromYPos( m_PlayerNumber, iCol, fY, m_fYReverseOffsetPixels ); - const float fX = ArrowGetXPos( m_PlayerNumber, iCol, fYOffset ); - const float fZ = ArrowGetZPos( m_PlayerNumber, iCol, fYOffset ); - const float fAlpha = ArrowGetAlpha( m_PlayerNumber, iCol, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels ); - const float fGlow = ArrowGetGlow( m_PlayerNumber, iCol, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels ); + const float fYOffset = ArrowEffects::GetYOffsetFromYPos( m_pPlayerState, iCol, fY, m_fYReverseOffsetPixels ); + const float fX = ArrowEffects::GetXPos( m_pPlayerState, iCol, fYOffset ); + const float fZ = ArrowEffects::GetZPos( m_pPlayerState, iCol, fYOffset ); + const float fAlpha = ArrowEffects::GetAlpha( m_pPlayerState, iCol, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels ); + const float fGlow = ArrowEffects::GetGlow( m_pPlayerState, iCol, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels ); const RageColor colorDiffuse= RageColor(fColorScale,fColorScale,fColorScale,fAlpha); const RageColor colorGlow = RageColor(1,1,1,fGlow); @@ -917,23 +920,23 @@ void NoteDisplay::DrawHold( const HoldNote& hn, bool bIsBeingHeld, bool bIsActiv { // bDrawGlowOnly is a little hacky. We need to draw the diffuse part and the glow part one pass at a time to minimize state changes - int iCol = hn.iTrack; - bool bReverse = GAMESTATE->m_CurrentPlayerOptions[m_PlayerNumber].GetReversePercentForColumn(iCol) > 0.5; - float fStartYOffset = ArrowGetYOffset( m_PlayerNumber, iCol, Result.GetLastHeldBeat() ); + int iCol = hn.iTrack; + bool bReverse = m_pPlayerState->m_CurrentPlayerOptions.GetReversePercentForColumn(iCol) > 0.5; + float fStartYOffset = ArrowEffects::GetYOffset( m_pPlayerState, iCol, Result.GetLastHeldBeat() ); // HACK: If active, don't allow the top of the hold to go above the receptor if( bIsActive ) fStartYOffset = 0; - float fStartYPos = ArrowGetYPos( m_PlayerNumber, iCol, fStartYOffset, fReverseOffsetPixels ); - float fEndYOffset = ArrowGetYOffset( m_PlayerNumber, iCol, hn.GetEndBeat() ); - float fEndYPos = ArrowGetYPos( m_PlayerNumber, iCol, fEndYOffset, fReverseOffsetPixels ); + float fStartYPos = ArrowEffects::GetYPos( m_pPlayerState, iCol, fStartYOffset, fReverseOffsetPixels ); + float fEndYOffset = ArrowEffects::GetYOffset( m_pPlayerState, iCol, hn.GetEndBeat() ); + float fEndYPos = ArrowEffects::GetYPos( m_pPlayerState, iCol, fEndYOffset, fReverseOffsetPixels ); const float fYHead = bReverse ? fEndYPos : fStartYPos; // the center of the head const float fYTail = bReverse ? fStartYPos : fEndYPos; // the center the tail // const bool bWavy = GAMESTATE->m_PlayerOptions[m_PlayerNumber].m_fEffects[PlayerOptions::EFFECT_DRUNK] > 0; - const bool WavyPartsNeedZBuffer = ArrowsNeedZBuffer( m_PlayerNumber ); + const bool WavyPartsNeedZBuffer = ArrowEffects::NeedZBuffer( m_pPlayerState ); /* Hack: Z effects need a finer grain step. */ const int fYStep = WavyPartsNeedZBuffer? 4: 16; //bWavy ? 16 : 128; // use small steps only if wavy @@ -974,15 +977,15 @@ void NoteDisplay::DrawHold( const HoldNote& hn, bool bIsBeingHeld, bool bIsActiv void NoteDisplay::DrawActor( Actor* pActor, int iCol, float fBeat, float fPercentFadeToFail, float fLife, float fReverseOffsetPixels, bool bUseLighting ) { - const float fYOffset = ArrowGetYOffset( m_PlayerNumber, iCol, fBeat ); - const float fYPos = ArrowGetYPos( m_PlayerNumber, iCol, fYOffset, fReverseOffsetPixels ); - const float fRotation = ArrowGetRotation( m_PlayerNumber, fBeat ); - const float fXPos = ArrowGetXPos( m_PlayerNumber, iCol, fYOffset ); - const float fZPos = ArrowGetZPos( m_PlayerNumber, iCol, fYOffset ); - const float fAlpha = ArrowGetAlpha( m_PlayerNumber, iCol, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels ); - const float fGlow = ArrowGetGlow( m_PlayerNumber, iCol, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels ); - const float fColorScale = ArrowGetBrightness( m_PlayerNumber, fBeat ) * SCALE(fLife,0,1,0.2f,1); - const float fZoom = ArrowGetZoom( m_PlayerNumber ); + const float fYOffset = ArrowEffects::GetYOffset( m_pPlayerState, iCol, fBeat ); + const float fYPos = ArrowEffects::GetYPos( m_pPlayerState, iCol, fYOffset, fReverseOffsetPixels ); + const float fRotation = ArrowEffects::GetRotation( m_pPlayerState, fBeat ); + const float fXPos = ArrowEffects::GetXPos( m_pPlayerState, iCol, fYOffset ); + const float fZPos = ArrowEffects::GetZPos( m_pPlayerState, iCol, fYOffset ); + const float fAlpha = ArrowEffects::GetAlpha( m_pPlayerState, iCol, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels ); + const float fGlow = ArrowEffects::GetGlow( m_pPlayerState, iCol, fYOffset, fPercentFadeToFail, m_fYReverseOffsetPixels ); + const float fColorScale = ArrowEffects::GetBrightness( m_pPlayerState, fBeat ) * SCALE(fLife,0,1,0.2f,1); + const float fZoom = ArrowEffects::GetZoom( m_pPlayerState ); RageColor diffuse = RageColor(fColorScale,fColorScale,fColorScale,fAlpha); RageColor glow = RageColor(1,1,1,fGlow); diff --git a/stepmania/src/NoteDisplay.h b/stepmania/src/NoteDisplay.h index c157376e15..2da6fe0b2d 100644 --- a/stepmania/src/NoteDisplay.h +++ b/stepmania/src/NoteDisplay.h @@ -6,10 +6,10 @@ #include "Sprite.h" class Model; #include "NoteTypes.h" -#include "PlayerNumber.h" struct HoldNoteResult; struct NoteMetricCache_t; +struct PlayerState; class NoteDisplay { @@ -17,7 +17,7 @@ public: NoteDisplay(); ~NoteDisplay(); - void Load( int iColNum, PlayerNumber pn, CString NoteSkin, float fYReverseOffsetPixels ); + void Load( int iColNum, const PlayerState* pPlayerState, CString NoteSkin, float fYReverseOffsetPixels ); static void Update( float fDeltaTime ); @@ -42,7 +42,7 @@ protected: void DrawHoldTail( const HoldNote& hn, const bool bIsBeingHeld, float fYTail, int iCol, float fPercentFadeToFail, float fColorScale, bool bGlow ); void DrawHoldHead( const HoldNote& hn, const bool bIsBeingHeld, float fYHead, int iCol, float fPercentFadeToFail, float fColorScale, bool bGlow ); - PlayerNumber m_PlayerNumber; // to look up PlayerOptions + const PlayerState* m_pPlayerState; // to look up PlayerOptions struct NoteMetricCache_t *cache; diff --git a/stepmania/src/NoteField.cpp b/stepmania/src/NoteField.cpp index 5e4f9c4af4..1f2799cf51 100644 --- a/stepmania/src/NoteField.cpp +++ b/stepmania/src/NoteField.cpp @@ -15,6 +15,7 @@ #include "NoteSkinManager.h" #include "song.h" #include "ScreenDimensions.h" +#include "PlayerState.h" NoteField::NoteField() { @@ -55,9 +56,9 @@ void NoteField::CacheNoteSkin( CString skin ) LOG->Trace("NoteField::CacheNoteSkin: cache %s", skin.c_str() ); NoteDisplayCols *nd = new NoteDisplayCols( GetNumTracks() ); for( int c=0; cdisplay[c].Load( c, m_PlayerNumber, skin, m_fYReverseOffsetPixels ); - nd->m_ReceptorArrowRow.Load( m_PlayerNumber, skin, m_fYReverseOffsetPixels ); - nd->m_GhostArrowRow.Load( m_PlayerNumber, skin, m_fYReverseOffsetPixels ); + nd->display[c].Load( c, m_pPlayerState, skin, m_fYReverseOffsetPixels ); + nd->m_ReceptorArrowRow.Load( m_pPlayerState, skin, m_fYReverseOffsetPixels ); + nd->m_GhostArrowRow.Load( m_pPlayerState, skin, m_fYReverseOffsetPixels ); m_NoteDisplays[ skin ] = nd; } @@ -71,11 +72,16 @@ void NoteField::CacheAllUsedNoteSkins() CacheNoteSkin( skins[i] ); } -void NoteField::Load( const NoteData* pNoteData, PlayerNumber pn, int iFirstPixelToDraw, int iLastPixelToDraw, float fYReverseOffsetPixels ) +void NoteField::Load( + const NoteData* pNoteData, + const PlayerState* pPlayerState, + int iFirstPixelToDraw, + int iLastPixelToDraw, + float fYReverseOffsetPixels ) { Unload(); - m_PlayerNumber = pn; + m_pPlayerState = pPlayerState; m_iStartDrawingPixel = iFirstPixelToDraw; m_iEndDrawingPixel = iLastPixelToDraw; m_fYReverseOffsetPixels = fYReverseOffsetPixels; @@ -103,16 +109,17 @@ void NoteField::RefreshBeatToNoteSkin() m_LastSeenBeatToNoteSkinRev = GAMESTATE->m_BeatToNoteSkinRev; /* Set by GameState::ResetNoteSkins(): */ - ASSERT( !GAMESTATE->m_BeatToNoteSkin[m_PlayerNumber].empty() ); + ASSERT( !m_pPlayerState->m_BeatToNoteSkin.empty() ); m_BeatToNoteDisplays.clear(); /* GAMESTATE->m_BeatToNoteSkin[pn] maps from song beats to note skins. Maintain * m_BeatToNoteDisplays, to map from song beats to NoteDisplay*s, so we don't * have to do it while rendering. */ - map::iterator it; - for( it = GAMESTATE->m_BeatToNoteSkin[m_PlayerNumber].begin(); - it != GAMESTATE->m_BeatToNoteSkin[m_PlayerNumber].end(); ++it ) + + for( map::const_iterator it = m_pPlayerState->m_BeatToNoteSkin.begin(); + it != m_pPlayerState->m_BeatToNoteSkin.end(); + ++it ) { const float Beat = it->first; const CString &Skin = it->second; @@ -169,7 +176,9 @@ void NoteField::Update( float fDeltaTime ) * Update all NoteDisplays. Hack: We need to call this once per frame, not * once per player. */ - if( m_PlayerNumber == GAMESTATE->m_MasterPlayerNumber ) + // TODO: Remove use of PlayerNumber. + PlayerNumber pn = m_pPlayerState->m_PlayerNumber; + if( pn == GAMESTATE->m_MasterPlayerNumber ) NoteDisplay::Update( fDeltaTime ); } @@ -177,7 +186,8 @@ float NoteField::GetWidth() { const Style* pStyle = GAMESTATE->GetCurrentStyle(); float fMinX, fMaxX; - pStyle->GetMinAndMaxColX( m_PlayerNumber, fMinX, fMaxX ); + // TODO: Remove use of PlayerNumber. + pStyle->GetMinAndMaxColX( m_pPlayerState->m_PlayerNumber, fMinX, fMaxX ); return fMaxX - fMinX + ARROW_SIZE; } @@ -190,8 +200,8 @@ void NoteField::DrawBeatBar( const float fBeat ) NoteType nt = BeatToNoteType( fBeat ); - const float fYOffset = ArrowGetYOffset( m_PlayerNumber, 0, fBeat ); - const float fYPos = ArrowGetYPos( m_PlayerNumber, 0, fYOffset, m_fYReverseOffsetPixels ); + const float fYOffset = ArrowEffects::GetYOffset( m_pPlayerState, 0, fBeat ); + const float fYPos = ArrowEffects::GetYPos( m_pPlayerState, 0, fYOffset, m_fYReverseOffsetPixels ); float fAlpha; int iState; @@ -203,7 +213,7 @@ void NoteField::DrawBeatBar( const float fBeat ) } else { - float fScrollSpeed = GAMESTATE->m_CurrentPlayerOptions[m_PlayerNumber].m_fScrollSpeed; + float fScrollSpeed = m_pPlayerState->m_CurrentPlayerOptions.m_fScrollSpeed; switch( nt ) { default: ASSERT(0); @@ -239,8 +249,8 @@ void NoteField::DrawBeatBar( const float fBeat ) void NoteField::DrawMarkerBar( const float fBeat ) { - const float fYOffset = ArrowGetYOffset( m_PlayerNumber, 0, fBeat ); - const float fYPos = ArrowGetYPos( m_PlayerNumber, 0, fYOffset, m_fYReverseOffsetPixels ); + const float fYOffset = ArrowEffects::GetYOffset( m_pPlayerState, 0, fBeat ); + const float fYPos = ArrowEffects::GetYPos( m_pPlayerState, 0, fYOffset, m_fYReverseOffsetPixels ); m_rectMarkerBar.StretchTo( RectF(-GetWidth()/2, fYPos-ARROW_SIZE/2, GetWidth()/2, fYPos+ARROW_SIZE/2) ); @@ -249,10 +259,10 @@ void NoteField::DrawMarkerBar( const float fBeat ) void NoteField::DrawAreaHighlight( const float fStartBeat, const float fEndBeat ) { - float fYStartOffset = ArrowGetYOffset( m_PlayerNumber, 0, fStartBeat ); - float fYStartPos = ArrowGetYPos( m_PlayerNumber, 0, fYStartOffset, m_fYReverseOffsetPixels ); - float fYEndOffset = ArrowGetYOffset( m_PlayerNumber, 0, fEndBeat ); - float fYEndPos = ArrowGetYPos( m_PlayerNumber, 0, fYEndOffset, m_fYReverseOffsetPixels ); + float fYStartOffset = ArrowEffects::GetYOffset( m_pPlayerState, 0, fStartBeat ); + float fYStartPos = ArrowEffects::GetYPos( m_pPlayerState, 0, fYStartOffset, m_fYReverseOffsetPixels ); + float fYEndOffset = ArrowEffects::GetYOffset( m_pPlayerState, 0, fEndBeat ); + float fYEndPos = ArrowEffects::GetYPos( m_pPlayerState, 0, fYEndOffset, m_fYReverseOffsetPixels ); // Something in OpenGL crashes if this is values are too large. Strange. -Chris fYStartPos = max( fYStartPos, -1000 ); @@ -267,8 +277,8 @@ void NoteField::DrawAreaHighlight( const float fStartBeat, const float fEndBeat void NoteField::DrawBPMText( const float fBeat, const float fBPM ) { - const float fYOffset = ArrowGetYOffset( m_PlayerNumber, 0, fBeat ); - const float fYPos = ArrowGetYPos( m_PlayerNumber, 0, fYOffset, m_fYReverseOffsetPixels ); + const float fYOffset = ArrowEffects::GetYOffset( m_pPlayerState, 0, fBeat ); + const float fYPos = ArrowEffects::GetYPos( m_pPlayerState, 0, fYOffset, m_fYReverseOffsetPixels ); m_textMeasureNumber.SetHorizAlign( Actor::align_right ); m_textMeasureNumber.SetDiffuse( RageColor(1,0,0,1) ); @@ -280,8 +290,8 @@ void NoteField::DrawBPMText( const float fBeat, const float fBPM ) void NoteField::DrawFreezeText( const float fBeat, const float fSecs ) { - const float fYOffset = ArrowGetYOffset( m_PlayerNumber, 0, fBeat ); - const float fYPos = ArrowGetYPos( m_PlayerNumber, 0, fYOffset, m_fYReverseOffsetPixels ); + const float fYOffset = ArrowEffects::GetYOffset( m_pPlayerState, 0, fBeat ); + const float fYPos = ArrowEffects::GetYPos( m_pPlayerState, 0, fYOffset, m_fYReverseOffsetPixels ); m_textMeasureNumber.SetHorizAlign( Actor::align_right ); m_textMeasureNumber.SetDiffuse( RageColor(0.8f,0.8f,0,1) ); @@ -293,8 +303,8 @@ void NoteField::DrawFreezeText( const float fBeat, const float fSecs ) void NoteField::DrawBGChangeText( const float fBeat, const CString sNewBGName ) { - const float fYOffset = ArrowGetYOffset( m_PlayerNumber, 0, fBeat ); - const float fYPos = ArrowGetYPos( m_PlayerNumber, 0, fYOffset, m_fYReverseOffsetPixels ); + const float fYOffset = ArrowEffects::GetYOffset( m_pPlayerState, 0, fBeat ); + const float fYPos = ArrowEffects::GetYPos( m_pPlayerState, 0, fYOffset, m_fYReverseOffsetPixels ); m_textMeasureNumber.SetHorizAlign( Actor::align_left ); m_textMeasureNumber.SetDiffuse( RageColor(0,1,0,1) ); @@ -348,13 +358,13 @@ NoteField::NoteDisplayCols *NoteField::SearchForBeat( float Beat ) // CPU OPTIMIZATION OPPORTUNITY: // change this probing to binary search -float FindFirstDisplayedBeat( PlayerNumber pn, int iFirstPixelToDraw ) +float FindFirstDisplayedBeat( const PlayerState* pPlayerState, int iFirstPixelToDraw ) { float fFirstBeatToDraw = GAMESTATE->m_fSongBeat-4; // Adjust to balance off performance and showing enough notes. while( fFirstBeatToDraw < GAMESTATE->m_fSongBeat ) { - float fYOffset = ArrowGetYOffset( pn, 0, fFirstBeatToDraw, true ); + float fYOffset = ArrowEffects::GetYOffset( pPlayerState, 0, fFirstBeatToDraw, true ); if( fYOffset < iFirstPixelToDraw ) // off screen fFirstBeatToDraw += 0.1f; // move toward fSongBeat else // on screen @@ -364,7 +374,7 @@ float FindFirstDisplayedBeat( PlayerNumber pn, int iFirstPixelToDraw ) return fFirstBeatToDraw; } -float FindLastDisplayedBeat( PlayerNumber pn, int iLastPixelToDraw ) +float FindLastDisplayedBeat( const PlayerState* pPlayerState, int iLastPixelToDraw ) { // // Probe for last note to draw. @@ -378,7 +388,7 @@ float FindLastDisplayedBeat( PlayerNumber pn, int iLastPixelToDraw ) for( int i=0; i iLastPixelToDraw ) // off screen fLastBeatToDraw -= fSearchDistance; @@ -402,7 +412,7 @@ void NoteField::DrawPrimitives() NoteDisplayCols *cur = SearchForSongBeat(); cur->m_ReceptorArrowRow.Draw(); - const PlayerOptions ¤t_po = GAMESTATE->m_CurrentPlayerOptions[m_PlayerNumber]; + const PlayerOptions ¤t_po = m_pPlayerState->m_CurrentPlayerOptions; // // Adjust draw range depending on some effects @@ -420,18 +430,20 @@ void NoteField::DrawPrimitives() fDrawScale *= 1 + 0.5f * fabsf( current_po.m_fPerspectiveTilt ); fDrawScale *= 1 + fabsf( current_po.m_fEffects[PlayerOptions::EFFECT_MINI] ); - float fFirstDrawScale = g_NoteFieldMode[m_PlayerNumber].m_fFirstPixelToDrawScale; - float fLastDrawScale = g_NoteFieldMode[m_PlayerNumber].m_fLastPixelToDrawScale; + // TODO: Remove use of PlayerNumber. + PlayerNumber pn = m_pPlayerState->m_PlayerNumber; + float fFirstDrawScale = g_NoteFieldMode[pn].m_fFirstPixelToDrawScale; + float fLastDrawScale = g_NoteFieldMode[pn].m_fLastPixelToDrawScale; iFirstPixelToDraw = (int)(iFirstPixelToDraw * fFirstDrawScale * fDrawScale); iLastPixelToDraw = (int)(iLastPixelToDraw * fLastDrawScale * fDrawScale); // Probe for first and last notes on the screen - float fFirstBeatToDraw = FindFirstDisplayedBeat( m_PlayerNumber, iFirstPixelToDraw ); - float fLastBeatToDraw = FindLastDisplayedBeat( m_PlayerNumber, iLastPixelToDraw ); + float fFirstBeatToDraw = FindFirstDisplayedBeat( m_pPlayerState, iFirstPixelToDraw ); + float fLastBeatToDraw = FindLastDisplayedBeat( m_pPlayerState, iLastPixelToDraw ); - GAMESTATE->m_fLastDrawnBeat[m_PlayerNumber] = fLastBeatToDraw; + m_pPlayerState->m_fLastDrawnBeat = fLastBeatToDraw; const int iFirstIndexToDraw = BeatToNoteRow(fFirstBeatToDraw); const int iLastIndexToDraw = BeatToNoteRow(fLastBeatToDraw); @@ -518,7 +530,9 @@ void NoteField::DrawPrimitives() for( int c=0; cm_PlayerNumber; + g_NoteFieldMode[pn].BeginDrawTrack(c); // // Draw all HoldNotes in this column (so that they appear under the tap notes) @@ -543,8 +557,8 @@ void NoteField::DrawPrimitives() // TRICKY: If boomerang is on, then all notes in the range // [iFirstIndexToDraw,iLastIndexToDraw] aren't necessarily visible. // Test every note to make sure it's on screen before drawing - float fYStartOffset = ArrowGetYOffset( m_PlayerNumber, c, NoteRowToBeat(hn.iStartRow) ); - float fYEndOffset = ArrowGetYOffset( m_PlayerNumber, c, NoteRowToBeat(hn.iEndRow) ); + float fYStartOffset = ArrowEffects::GetYOffset( m_pPlayerState, c, NoteRowToBeat(hn.iStartRow) ); + float fYEndOffset = ArrowEffects::GetYOffset( m_pPlayerState, c, NoteRowToBeat(hn.iEndRow) ); if( !( iFirstPixelToDraw <= fYEndOffset && fYEndOffset <= iLastPixelToDraw || iFirstPixelToDraw <= fYStartOffset && fYStartOffset <= iLastPixelToDraw || fYStartOffset < iFirstPixelToDraw && fYEndOffset > iLastPixelToDraw ) ) @@ -588,7 +602,7 @@ void NoteField::DrawPrimitives() // TRICKY: If boomerang is on, then all notes in the range // [iFirstIndexToDraw,iLastIndexToDraw] aren't necessarily visible. // Test every note to make sure it's on screen before drawing - float fYOffset = ArrowGetYOffset( m_PlayerNumber, c, NoteRowToBeat(i) ); + float fYOffset = ArrowEffects::GetYOffset( m_pPlayerState, c, NoteRowToBeat(i) ); if( fYOffset > iLastPixelToDraw ) // off screen continue; // skip if( fYOffset < iFirstPixelToDraw ) // off screen @@ -633,7 +647,7 @@ void NoteField::DrawPrimitives() } - g_NoteFieldMode[m_PlayerNumber].EndDrawTrack(c); + g_NoteFieldMode[pn].EndDrawTrack(c); } cur->m_GhostArrowRow.Draw(); diff --git a/stepmania/src/NoteField.h b/stepmania/src/NoteField.h index 3a33670773..73f29906cb 100644 --- a/stepmania/src/NoteField.h +++ b/stepmania/src/NoteField.h @@ -5,7 +5,6 @@ #include "ActorFrame.h" #include "BitmapText.h" #include "PrefsManager.h" -#include "Style.h" #include "BitmapText.h" #include "Quad.h" #include "NoteDataWithScoring.h" @@ -24,7 +23,12 @@ public: virtual void Update( float fDeltaTime ); virtual void DrawPrimitives(); - virtual void Load( const NoteData* pNoteData, PlayerNumber pn, int iStartDrawingPixel, int iEndDrawingPixel, float fYReverseOffsetPixels ); + virtual void Load( + const NoteData* pNoteData, + const PlayerState* pPlayerState, + int iStartDrawingPixel, + int iEndDrawingPixel, + float fYReverseOffsetPixels ); virtual void Unload(); void RemoveTapNoteRow( int iIndex ); @@ -56,7 +60,7 @@ protected: float m_fPercentFadeToFail; // -1 of not fading to fail - PlayerNumber m_PlayerNumber; + const PlayerState* m_pPlayerState; int m_iStartDrawingPixel; // this should be a negative number int m_iEndDrawingPixel; // this should be a positive number float m_fYReverseOffsetPixels; diff --git a/stepmania/src/NoteFieldPositioning.cpp b/stepmania/src/NoteFieldPositioning.cpp index 6457e59861..ff8253a3e4 100644 --- a/stepmania/src/NoteFieldPositioning.cpp +++ b/stepmania/src/NoteFieldPositioning.cpp @@ -11,6 +11,7 @@ #include "IniFile.h" #include "Game.h" #include "ScreenDimensions.h" +#include "PlayerState.h" /* Copies of the current mode. Update this by calling Load. */ NoteFieldMode g_NoteFieldMode[NUM_PLAYERS]; @@ -134,7 +135,7 @@ void NoteFieldPositioning::Load(PlayerNumber pn) } /* Is there a custom mode with the current name that fits the current game? */ - const int ModeNum = GetID(GAMESTATE->m_PlayerOptions[pn].m_sPositioning); + const int ModeNum = GetID(GAMESTATE->m_pPlayerState[pn]->m_PlayerOptions.m_sPositioning); if(ModeNum == -1) return; /* No, only use the style table settings. */ diff --git a/stepmania/src/OptionIconRow.cpp b/stepmania/src/OptionIconRow.cpp index c12de37d81..d42bec938e 100644 --- a/stepmania/src/OptionIconRow.cpp +++ b/stepmania/src/OptionIconRow.cpp @@ -4,6 +4,7 @@ #include "PlayerOptions.h" #include "GameState.h" #include "RageLog.h" +#include "PlayerState.h" #define SPACING_X THEME->GetMetricF("OptionIconRow","SpacingX") @@ -95,7 +96,7 @@ void OptionIconRow::Refresh() for( unsigned i=0; im_PlayerOptions[m_PlayerNumber].GetString(); + CString sOptions = GAMESTATE->m_pPlayerState[m_PlayerNumber]->m_PlayerOptions.GetString(); CStringArray asOptions; split( sOptions, ", ", asOptions, true ); diff --git a/stepmania/src/Player.cpp b/stepmania/src/Player.cpp index fa2201d448..baba98feba 100644 --- a/stepmania/src/Player.cpp +++ b/stepmania/src/Player.cpp @@ -30,6 +30,7 @@ #include "ScreenDimensions.h" #include "RageSoundManager.h" #include "ThemeMetric.h" +#include "PlayerState.h" ThemeMetric GRAY_ARROWS_Y_STANDARD ("Player","ReceptorArrowsYStandard"); ThemeMetric GRAY_ARROWS_Y_REVERSE ("Player","ReceptorArrowsYReverse"); @@ -59,7 +60,7 @@ static const float StepSearchDistance = 1.0f; PlayerMinus::PlayerMinus() { - m_PlayerNumber = PLAYER_INVALID; + m_pPlayerState = NULL; m_fNoteFieldHeight = 0; m_pLifeMeter = NULL; @@ -89,7 +90,7 @@ PlayerMinus::~PlayerMinus() } void PlayerMinus::Load( - PlayerNumber pn, + PlayerState* pPlayerState, const NoteData& noteData, LifeMeter* pLM, CombinedLifeMeter* pCombinedLM, @@ -102,9 +103,7 @@ void PlayerMinus::Load( { m_iDCState = AS2D_IDLE; - GAMESTATE->ResetNoteSkinsForPlayer( pn ); - - m_PlayerNumber = pn; + m_pPlayerState = pPlayerState; m_pLifeMeter = pLM; m_pCombinedLifeMeter = pCombinedLM; m_pScoreDisplay = pScoreDisplay; @@ -116,9 +115,14 @@ void PlayerMinus::Load( m_iRowLastCrossed = BeatToNoteRowNotRounded( GAMESTATE->m_fSongBeat ) - 1; // why this? m_iMineRowLastCrossed = BeatToNoteRowNotRounded( GAMESTATE->m_fSongBeat ) - 1; // why this? + // TODO: Remove use of PlayerNumber. + PlayerNumber pn = pPlayerState->m_PlayerNumber; + + GAMESTATE->ResetNoteSkinsForPlayer( pn ); + /* Ensure that this is up-to-date. */ GAMESTATE->m_pPosition->Load(pn); - + const Style* pStyle = GAMESTATE->GetCurrentStyle(); // init steps @@ -133,8 +137,8 @@ void PlayerMinus::Load( m_Judgment.StopTweening(); // m_Combo.Reset(); // don't reset combos between songs in a course! m_Combo.Init( pn ); - m_Combo.SetCombo( g_CurStageStats.iCurCombo[m_PlayerNumber], g_CurStageStats.iCurMissCombo[m_PlayerNumber] ); // combo can persist between songs and games - m_AttackDisplay.Init( pn ); + m_Combo.SetCombo( g_CurStageStats.iCurCombo[pn], g_CurStageStats.iCurMissCombo[pn] ); // combo can persist between songs and games + m_AttackDisplay.Init( m_pPlayerState ); m_Judgment.Reset(); /* Don't re-init this; that'll reload graphics. Add a separate Reset() call @@ -143,7 +147,7 @@ void PlayerMinus::Load( // m_pScore->Init( pn ); /* Apply transforms. */ - NoteDataUtil::TransformNoteData( m_NoteData, GAMESTATE->m_PlayerOptions[pn], GAMESTATE->GetCurrentStyle()->m_StepsType ); + NoteDataUtil::TransformNoteData( m_NoteData, GAMESTATE->m_pPlayerState[pn]->m_PlayerOptions, GAMESTATE->GetCurrentStyle()->m_StepsType ); switch( GAMESTATE->m_PlayMode ) { @@ -151,7 +155,7 @@ void PlayerMinus::Load( case PLAY_MODE_BATTLE: { // ugly, ugly, ugly. Works only w/ dance. - NoteDataUtil::TransformNoteData( m_NoteData, GAMESTATE->m_PlayerOptions[pn], GAMESTATE->GetCurrentStyle()->m_StepsType ); + NoteDataUtil::TransformNoteData( m_NoteData, GAMESTATE->m_pPlayerState[pn]->m_PlayerOptions, GAMESTATE->GetCurrentStyle()->m_StepsType ); // shuffle either p1 or p2 static int count = 0; @@ -186,18 +190,18 @@ void PlayerMinus::Load( m_pNoteField->SetY( fNoteFieldMidde ); m_fNoteFieldHeight = GRAY_ARROWS_Y_REVERSE-GRAY_ARROWS_Y_STANDARD; - m_pNoteField->Load( &m_NoteData, pn, iStartDrawingAtPixels, iStopDrawingAtPixels, m_fNoteFieldHeight ); + m_pNoteField->Load( &m_NoteData, m_pPlayerState, iStartDrawingAtPixels, iStopDrawingAtPixels, m_fNoteFieldHeight ); m_ArrowBackdrop.SetPlayer( pn ); - const bool bReverse = GAMESTATE->m_PlayerOptions[pn].GetReversePercentForColumn(0) == 1; + const bool bReverse = GAMESTATE->m_pPlayerState[pn]->m_PlayerOptions.GetReversePercentForColumn(0) == 1; bool bPlayerUsingBothSides = GAMESTATE->GetCurrentStyle()->m_StyleType==ONE_PLAYER_TWO_SIDES; - m_Combo.SetX( COMBO_X(m_PlayerNumber,bPlayerUsingBothSides) ); + m_Combo.SetX( COMBO_X(pn,bPlayerUsingBothSides) ); m_Combo.SetY( bReverse ? COMBO_Y_REVERSE : COMBO_Y ); - m_AttackDisplay.SetX( ATTACK_DISPLAY_X(m_PlayerNumber,bPlayerUsingBothSides) - 40 ); + m_AttackDisplay.SetX( ATTACK_DISPLAY_X(pn,bPlayerUsingBothSides) - 40 ); m_AttackDisplay.SetY( bReverse ? ATTACK_DISPLAY_Y_REVERSE : ATTACK_DISPLAY_Y ); - m_Judgment.SetX( JUDGMENT_X(m_PlayerNumber,bPlayerUsingBothSides) ); + m_Judgment.SetX( JUDGMENT_X(pn,bPlayerUsingBothSides) ); m_Judgment.SetY( bReverse ? JUDGMENT_Y_REVERSE : JUDGMENT_Y ); - m_ProTimingDisplay.SetX( JUDGMENT_X(m_PlayerNumber,bPlayerUsingBothSides) ); + m_ProTimingDisplay.SetX( JUDGMENT_X(pn,bPlayerUsingBothSides) ); m_ProTimingDisplay.SetY( bReverse ? SCREEN_BOTTOM-JUDGMENT_Y : SCREEN_TOP+JUDGMENT_Y ); /* These commands add to the above positioning, and are usually empty. */ @@ -236,7 +240,7 @@ void PlayerMinus::Load( if( GAMESTATE->GetNumPlayersEnabled() == 2 ) { /* Two players are active. Play sounds on this player's side. */ - p.m_Balance = (m_PlayerNumber == PLAYER_1)? -1.0f:1.0f; + p.m_Balance = (pn == PLAYER_1)? -1.0f:1.0f; } m_soundMine.SetParams( p ); m_soundAttackLaunch.SetParams( p ); @@ -265,9 +269,9 @@ void PlayerMinus::Update( float fDeltaTime ) if( GAMESTATE->m_pCurSong==NULL ) return; - if( GAMESTATE->m_bAttackBeganThisUpdate[m_PlayerNumber] ) + if( m_pPlayerState->m_bAttackBeganThisUpdate ) m_soundAttackLaunch.Play(); - if( GAMESTATE->m_bAttackEndedThisUpdate[m_PlayerNumber] ) + if( m_pPlayerState->m_bAttackEndedThisUpdate ) m_soundAttackEnding.Play(); @@ -282,12 +286,12 @@ void PlayerMinus::Update( float fDeltaTime ) { for( int c=0; cGetCurrentStyle()->m_iColsPerPlayer; c++ ) { - float fPercentReverse = GAMESTATE->m_CurrentPlayerOptions[m_PlayerNumber].GetReversePercentForColumn(c); + float fPercentReverse = m_pPlayerState->m_CurrentPlayerOptions.GetReversePercentForColumn(c); float fHoldJudgeYPos = SCALE( fPercentReverse, 0.f, 1.f, HOLD_JUDGMENT_Y_STANDARD, HOLD_JUDGMENT_Y_REVERSE ); // float fGrayYPos = SCALE( fPercentReverse, 0.f, 1.f, GRAY_ARROWS_Y_STANDARD, GRAY_ARROWS_Y_REVERSE ); - const float fX = ArrowGetXPos( m_PlayerNumber, c, 0 ); - const float fZ = ArrowGetZPos( m_PlayerNumber, c, 0 ); + const float fX = ArrowEffects::GetXPos( m_pPlayerState, c, 0 ); + const float fZ = ArrowEffects::GetZPos( m_pPlayerState, c, 0 ); m_HoldJudgment[c].SetX( fX ); m_HoldJudgment[c].SetY( fHoldJudgeYPos ); @@ -295,14 +299,14 @@ void PlayerMinus::Update( float fDeltaTime ) } } - float fPercentReverse = GAMESTATE->m_CurrentPlayerOptions[m_PlayerNumber].GetReversePercentForColumn(0); + float fPercentReverse = m_pPlayerState->m_CurrentPlayerOptions.GetReversePercentForColumn(0); float fGrayYPos = SCALE( fPercentReverse, 0.f, 1.f, GRAY_ARROWS_Y_STANDARD, GRAY_ARROWS_Y_REVERSE ); m_ArrowBackdrop.SetY( fGrayYPos ); // NoteField accounts for reverse on its own now. // m_pNoteField->SetY( fGrayYPos ); - float fMiniPercent = GAMESTATE->m_CurrentPlayerOptions[m_PlayerNumber].m_fEffects[PlayerOptions::EFFECT_MINI]; + float fMiniPercent = m_pPlayerState->m_CurrentPlayerOptions.m_fEffects[PlayerOptions::EFFECT_MINI]; float fNoteFieldZoom = 1 - fMiniPercent*0.5f; float fJudgmentZoom = 1 - fMiniPercent*0.25f; m_pNoteField->SetZoom( fNoteFieldZoom ); @@ -320,12 +324,15 @@ void PlayerMinus::Update( float fDeltaTime ) ASSERT_M( iNumCols < MAX_COLS_PER_PLAYER, ssprintf("%i >= %i", iNumCols, MAX_COLS_PER_PLAYER) ); for( int col=0; col < iNumCols; ++col ) { + // TODO: Remove use of PlayerNumber. + PlayerNumber pn = m_pPlayerState->m_PlayerNumber; + CHECKPOINT_M( ssprintf("%i %i", col, iNumCols) ); - const StyleInput StyleI( m_PlayerNumber, col ); + const StyleInput StyleI( pn, col ); const GameInput GameI = GAMESTATE->GetCurrentStyle()->StyleInputToGameInput( StyleI ); bool bIsHoldingButton = INPUTMAPPER->IsButtonDown( GameI ); // TODO: Make this work for non-human-controlled players - if( bIsHoldingButton && !GAMESTATE->m_bDemonstrationOrJukebox && GAMESTATE->m_PlayerController[m_PlayerNumber]==PC_HUMAN ) + if( bIsHoldingButton && !GAMESTATE->m_bDemonstrationOrJukebox && m_pPlayerState->m_PlayerController==PC_HUMAN ) m_pNoteField->SetPressed( col ); } @@ -346,7 +353,10 @@ void PlayerMinus::Update( float fDeltaTime ) if( iSongRow < hn.iStartRow ) continue; // hold hasn't happened yet - const StyleInput StyleI( m_PlayerNumber, hn.iTrack ); + // TODO: Remove use of PlayerNumber. + PlayerNumber pn = m_pPlayerState->m_PlayerNumber; + + const StyleInput StyleI( pn, hn.iTrack ); const GameInput GameI = GAMESTATE->GetCurrentStyle()->StyleInputToGameInput( StyleI ); // if they got a bad score or haven't stepped on the corresponding tap yet @@ -361,7 +371,7 @@ void PlayerMinus::Update( float fDeltaTime ) bool bIsHoldingButton = INPUTMAPPER->IsButtonDown( GameI ); // TODO: Make the CPU miss sometimes. - if( GAMESTATE->m_PlayerController[m_PlayerNumber] != PC_HUMAN ) + if( m_pPlayerState->m_PlayerController != PC_HUMAN ) bIsHoldingButton = true; // set hold flag so NoteField can do intelligent drawing @@ -423,7 +433,10 @@ void PlayerMinus::Update( float fDeltaTime ) int ms_error = (hns == HNS_OK)? 0:MAX_PRO_TIMING_ERROR; - g_CurStageStats.iTotalError[m_PlayerNumber] += ms_error; + // TODO: Remove use of PlayerNumber. + PlayerNumber pn = m_pPlayerState->m_PlayerNumber; + + g_CurStageStats.iTotalError[pn] += ms_error; if( hns == HNS_NG ) /* don't show a 0 for an OK */ m_ProTimingDisplay.SetJudgment( ms_error, TNS_MISS ); } @@ -435,6 +448,9 @@ void PlayerMinus::Update( float fDeltaTime ) m_NoteData.SetHoldNoteScore(hn, hns); } + // TODO: Remove use of PlayerNumber. + PlayerNumber pn = m_pPlayerState->m_PlayerNumber; + { // Why was this originally "BeatToNoteRowNotRounded"? It should be rounded. -Chris /* We want to send the crossed row message exactly when we cross the row--not @@ -444,7 +460,7 @@ void PlayerMinus::Update( float fDeltaTime ) if( iRowNow >= 0 ) { for( ; m_iRowLastCrossed <= iRowNow; m_iRowLastCrossed++ ) // for each index we crossed since the last update - if( GAMESTATE->IsPlayerEnabled(m_PlayerNumber) ) + if( GAMESTATE->IsPlayerEnabled(pn) ) CrossedRow( m_iRowLastCrossed ); } } @@ -458,7 +474,7 @@ void PlayerMinus::Update( float fDeltaTime ) if( iRowNow >= 0 ) { for( ; m_iMineRowLastCrossed <= iRowNow; m_iMineRowLastCrossed++ ) // for each index we crossed since the last update - if( GAMESTATE->IsPlayerEnabled(m_PlayerNumber) ) + if( GAMESTATE->IsPlayerEnabled(pn) ) CrossedMineRow( m_iMineRowLastCrossed ); } } @@ -477,9 +493,9 @@ void PlayerMinus::Update( float fDeltaTime ) void PlayerMinus::ApplyWaitingTransforms() { - for( unsigned j=0; jm_ModsToApply[m_PlayerNumber].size(); j++ ) + for( unsigned j=0; jm_ModsToApply.size(); j++ ) { - const Attack &mod = GAMESTATE->m_ModsToApply[m_PlayerNumber][j]; + const Attack &mod = m_pPlayerState->m_ModsToApply[j]; PlayerOptions po; /* Should this default to "" always? need it blank so we know if mod.sModifier * changes the note skin. */ @@ -487,31 +503,34 @@ void PlayerMinus::ApplyWaitingTransforms() po.FromString( mod.sModifier ); float fStartBeat, fEndBeat; - mod.GetAttackBeats( GAMESTATE->m_pCurSong, m_PlayerNumber, fStartBeat, fEndBeat ); + mod.GetAttackBeats( GAMESTATE->m_pCurSong, m_pPlayerState, fStartBeat, fEndBeat ); fEndBeat = min( fEndBeat, m_NoteData.GetLastBeat() ); LOG->Trace( "Applying transform '%s' from %f to %f to '%s'", mod.sModifier.c_str(), fStartBeat, fEndBeat, GAMESTATE->m_pCurSong->GetTranslitMainTitle().c_str() ); if( po.m_sNoteSkin != "" ) - GAMESTATE->SetNoteSkinForBeatRange( m_PlayerNumber, po.m_sNoteSkin, fStartBeat, fEndBeat ); + GAMESTATE->SetNoteSkinForBeatRange( m_pPlayerState, po.m_sNoteSkin, fStartBeat, fEndBeat ); NoteDataUtil::TransformNoteData( m_NoteData, po, GAMESTATE->GetCurrentStyle()->m_StepsType, fStartBeat, fEndBeat ); m_pNoteField->CopyRange( m_NoteData, BeatToNoteRow(fStartBeat), BeatToNoteRow(fEndBeat), BeatToNoteRow(fStartBeat) ); } - GAMESTATE->m_ModsToApply[m_PlayerNumber].clear(); + m_pPlayerState->m_ModsToApply.clear(); } void PlayerMinus::DrawPrimitives() { + // TODO: Remove use of PlayerNumber. + PlayerNumber pn = m_pPlayerState->m_PlayerNumber; + // May have both players in doubles (for battle play); only draw primary player. if( GAMESTATE->GetCurrentStyle()->m_StyleType == ONE_PLAYER_TWO_SIDES && - m_PlayerNumber != GAMESTATE->m_MasterPlayerNumber ) + pn != GAMESTATE->m_MasterPlayerNumber ) return; // Draw these below everything else. m_ArrowBackdrop.Draw(); - if( GAMESTATE->m_PlayerOptions[m_PlayerNumber].m_fBlind == 0 ) + if( m_pPlayerState->m_PlayerOptions.m_fBlind == 0 ) m_Combo.Draw(); m_AttackDisplay.Draw(); @@ -522,9 +541,9 @@ void PlayerMinus::DrawPrimitives() if( HOLD_JUDGMENTS_UNDER_FIELD ) DrawHoldJudgments(); - float fTilt = GAMESTATE->m_CurrentPlayerOptions[m_PlayerNumber].m_fPerspectiveTilt; - float fSkew = GAMESTATE->m_CurrentPlayerOptions[m_PlayerNumber].m_fSkew; - bool bReverse = GAMESTATE->m_CurrentPlayerOptions[m_PlayerNumber].GetReversePercentForColumn(0)>0.5; + float fTilt = m_pPlayerState->m_CurrentPlayerOptions.m_fPerspectiveTilt; + float fSkew = m_pPlayerState->m_CurrentPlayerOptions.m_fSkew; + bool bReverse = m_pPlayerState->m_CurrentPlayerOptions.GetReversePercentForColumn(0)>0.5; DISPLAY->CameraPushMatrix(); @@ -539,7 +558,7 @@ void PlayerMinus::DrawPrimitives() float fTiltDegrees = SCALE(fTilt,-1.f,+1.f,+30,-30) * (bReverse?-1:1); - float fZoom = SCALE( GAMESTATE->m_CurrentPlayerOptions[m_PlayerNumber].m_fEffects[PlayerOptions::EFFECT_MINI], 0.f, 1.f, 1.f, 0.5f ); + float fZoom = SCALE( m_pPlayerState->m_CurrentPlayerOptions.m_fEffects[PlayerOptions::EFFECT_MINI], 0.f, 1.f, 1.f, 0.5f ); if( fTilt > 0 ) fZoom *= SCALE( fTilt, 0.f, 1.f, 1.f, 0.9f ); else @@ -571,10 +590,10 @@ void PlayerMinus::DrawPrimitives() void PlayerMinus::DrawTapJudgments() { - if( GAMESTATE->m_PlayerOptions[m_PlayerNumber].m_fBlind > 0 ) + if( m_pPlayerState->m_PlayerOptions.m_fBlind > 0 ) return; - if( GAMESTATE->m_PlayerOptions[m_PlayerNumber].m_bProTiming ) + if( m_pPlayerState->m_PlayerOptions.m_bProTiming ) m_ProTimingDisplay.Draw(); else m_Judgment.Draw(); @@ -582,16 +601,19 @@ void PlayerMinus::DrawTapJudgments() void PlayerMinus::DrawHoldJudgments() { - if( GAMESTATE->m_PlayerOptions[m_PlayerNumber].m_fBlind > 0 ) + if( m_pPlayerState->m_PlayerOptions.m_fBlind > 0 ) return; + // TODO: Remove use of PlayerNumber. + PlayerNumber pn = m_pPlayerState->m_PlayerNumber; + for( int c=0; cm_SongOptions.m_LifeType == SongOptions::LIFE_BATTERY && g_CurStageStats.bFailed[m_PlayerNumber] ) // Oni dead + // TODO: Remove use of PlayerNumber. + PlayerNumber pn = m_pPlayerState->m_PlayerNumber; + + if( GAMESTATE->m_SongOptions.m_LifeType == SongOptions::LIFE_BATTERY && g_CurStageStats.bFailed[pn] ) // Oni dead return; // do nothing //LOG->Trace( "PlayerMinus::HandlePlayerStep()" ); @@ -699,7 +724,7 @@ void PlayerMinus::Step( int col, RageTimer tm ) TapNote tn = m_NoteData.GetTapNote( col, iIndexOverlappingNote ); - switch( GAMESTATE->m_PlayerController[m_PlayerNumber] ) + switch( m_pPlayerState->m_PlayerController ) { case PC_HUMAN: @@ -714,8 +739,12 @@ void PlayerMinus::Step( int col, RageTimer tm ) if( m_pLifeMeter ) m_pLifeMeter->ChangeLifeMine(); + + // TODO: Remove use of PlayerNumber. + PlayerNumber pn = m_pPlayerState->m_PlayerNumber; + if( m_pCombinedLifeMeter ) - m_pCombinedLifeMeter->ChangeLifeMine(m_PlayerNumber); + m_pCombinedLifeMeter->ChangeLifeMine( pn ); m_pNoteField->SetTapNote(col, iIndexOverlappingNote, TAP_EMPTY); // remove from NoteField m_pNoteField->DidTapNote( col, score, false ); } @@ -736,7 +765,11 @@ void PlayerMinus::Step( int col, RageTimer tm ) true, false ); - GAMESTATE->LaunchAttack( OPPOSITE_PLAYER[m_PlayerNumber], attack ); + + // TODO: Remove use of PlayerNumber + PlayerNumber pn = m_pPlayerState->m_PlayerNumber; + + GAMESTATE->LaunchAttack( OPPOSITE_PLAYER[pn], attack ); // remove all TapAttacks on this row for( int t=0; tm_PlayerController[m_PlayerNumber] ) + switch( m_pPlayerState->m_PlayerController ) { case PC_CPU: - score = PlayerAI::GetTapNoteScore( m_PlayerNumber ); + score = PlayerAI::GetTapNoteScore( m_pPlayerState ); break; case PC_AUTOPLAY: score = TNS_MARVELOUS; @@ -801,8 +834,12 @@ void PlayerMinus::Step( int col, RageTimer tm ) m_soundMine.Play(); if( m_pLifeMeter ) m_pLifeMeter->ChangeLifeMine(); + + // Remove use of PlayerNumber. + PlayerNumber pn = m_pPlayerState->m_PlayerNumber; + if( m_pCombinedLifeMeter ) - m_pCombinedLifeMeter->ChangeLifeMine(m_PlayerNumber); + m_pCombinedLifeMeter->ChangeLifeMine( pn ); m_pNoteField->SetTapNote(col, iIndexOverlappingNote, TAP_EMPTY); // remove from NoteField m_pNoteField->DidTapNote( col, score, false ); } @@ -830,7 +867,11 @@ void PlayerMinus::Step( int col, RageTimer tm ) true, false ); - GAMESTATE->LaunchAttack( OPPOSITE_PLAYER[m_PlayerNumber], attack ); + + // TODO: Remove use of PlayerNumber. + PlayerNumber pn = m_pPlayerState->m_PlayerNumber; + + GAMESTATE->LaunchAttack( OPPOSITE_PLAYER[pn], attack ); // remove all TapAttacks on this row for( int t=0; tm_PlayerOptions[m_PlayerNumber].m_fBlind) + // TODO: Remove use of PlayerNumber. + PlayerNumber pn = m_pPlayerState->m_PlayerNumber; + + g_CurStageStats.iTotalError[pn] += ms_error; + if (!m_pPlayerState->m_PlayerOptions.m_fBlind) m_ProTimingDisplay.SetJudgment( ms_error, score ); } @@ -885,12 +929,15 @@ void PlayerMinus::Step( int col, RageTimer tm ) if( score != TNS_NONE ) m_NoteData.SetTapNoteOffset(col, iIndexOverlappingNote, -fNoteOffset); - if( GAMESTATE->m_PlayerController[m_PlayerNumber] == PC_HUMAN && + if( m_pPlayerState->m_PlayerController == PC_HUMAN && score >= TNS_GREAT ) HandleAutosync(fNoteOffset); + // TODO: Remove use of PlayerNumber. + PlayerNumber pn = m_pPlayerState->m_PlayerNumber; + //Keep this here so we get the same data as Autosync - NSMAN->ReportTiming(fNoteOffset,m_PlayerNumber); + NSMAN->ReportTiming(fNoteOffset,pn); if( m_pPrimaryScoreKeeper ) m_pPrimaryScoreKeeper->HandleTapScore( score ); @@ -998,15 +1045,18 @@ void PlayerMinus::OnRowCompletelyJudged( int iIndexThatWasSteppedOn ) // If the score is great or better, remove the note from the screen to // indicate success. (Or always if blind is on.) - if( score >= TNS_GREAT || GAMESTATE->m_PlayerOptions[m_PlayerNumber].m_fBlind ) + if( score >= TNS_GREAT || m_pPlayerState->m_PlayerOptions.m_fBlind ) m_pNoteField->SetTapNote(c, iIndexThatWasSteppedOn, TAP_EMPTY); // show the ghost arrow for this column - if (GAMESTATE->m_PlayerOptions[m_PlayerNumber].m_fBlind) + if (m_pPlayerState->m_PlayerOptions.m_fBlind) m_pNoteField->DidTapNote( c, TNS_MARVELOUS, false ); else { - bool bBright = g_CurStageStats.iCurCombo[m_PlayerNumber]>(int)BRIGHT_GHOST_COMBO_THRESHOLD; + // TODO: Remove use of PlayerNumber. + PlayerNumber pn = m_pPlayerState->m_PlayerNumber; + + bool bBright = g_CurStageStats.iCurCombo[pn]>(int)BRIGHT_GHOST_COMBO_THRESHOLD; m_pNoteField->DidTapNote( c, score, bBright ); } } @@ -1064,7 +1114,11 @@ void PlayerMinus::UpdateTapNotesMissedOlderThan( float fMissIfOlderThanSeconds ) // A normal note. Penalize for not stepping on it. MissedNoteOnThisRow = true; m_NoteData.SetTapNoteScore( t, r, TNS_MISS ); - g_CurStageStats.iTotalError[m_PlayerNumber] += MAX_PRO_TIMING_ERROR; + + // TODO: Remove use of PlayerNumber. + PlayerNumber pn = m_pPlayerState->m_PlayerNumber; + + g_CurStageStats.iTotalError[pn] += MAX_PRO_TIMING_ERROR; m_ProTimingDisplay.SetJudgment( MAX_PRO_TIMING_ERROR, TNS_MISS ); } } @@ -1084,12 +1138,12 @@ void PlayerMinus::UpdateTapNotesMissedOlderThan( float fMissIfOlderThanSeconds ) void PlayerMinus::CrossedRow( int iNoteRow ) { // If we're doing random vanish, randomise notes on the fly. - if(GAMESTATE->m_CurrentPlayerOptions[m_PlayerNumber].m_fAppearances[PlayerOptions::APPEARANCE_RANDOMVANISH]==1) + if(m_pPlayerState->m_CurrentPlayerOptions.m_fAppearances[PlayerOptions::APPEARANCE_RANDOMVANISH]==1) RandomizeNotes( iNoteRow ); // check to see if there's a note at the crossed row RageTimer now; - if( GAMESTATE->m_PlayerController[m_PlayerNumber] != PC_HUMAN ) + if( m_pPlayerState->m_PlayerController != PC_HUMAN ) { for( int t=0; tm_PlayerNumber; + + const StyleInput StyleI( pn, t ); const GameInput GameI = GAMESTATE->GetCurrentStyle()->StyleInputToGameInput( StyleI ); if( PREFSMAN->m_fPadStickSeconds > 0 ) { @@ -1132,7 +1189,7 @@ void PlayerMinus::RandomizeNotes( int iNoteRow ) /* This is incorrect: if m_fScrollSpeed is 0.5, we'll never change * any odd rows, and if it's 2, we'll shuffle each row twice. */ int iNewNoteRow = iNoteRow + ROWS_PER_BEAT*2; - iNewNoteRow = int( iNewNoteRow / GAMESTATE->m_PlayerOptions[m_PlayerNumber].m_fScrollSpeed ); + iNewNoteRow = int( iNewNoteRow / m_pPlayerState->m_PlayerOptions.m_fScrollSpeed ); int iNumOfTracks = m_NoteData.GetNumTracks(); for( int t=0; t+1 < iNumOfTracks; t++ ) @@ -1183,22 +1240,25 @@ void PlayerMinus::HandleTapRowScore( unsigned row ) if(GAMESTATE->m_bDemonstrationOrJukebox) NoCheating = false; // don't accumulate points if AutoPlay is on. - if( NoCheating && GAMESTATE->m_PlayerController[m_PlayerNumber] == PC_AUTOPLAY ) + if( NoCheating && m_pPlayerState->m_PlayerController == PC_AUTOPLAY ) return; + // TODO: Remove use of PlayerNumber. + PlayerNumber pn = m_pPlayerState->m_PlayerNumber; + /* Update miss combo, and handle "combo stopped" messages. */ - int &iCurCombo = g_CurStageStats.iCurCombo[m_PlayerNumber]; + int &iCurCombo = g_CurStageStats.iCurCombo[pn]; switch( scoreOfLastTap ) { case TNS_MARVELOUS: case TNS_PERFECT: case TNS_GREAT: - g_CurStageStats.iCurMissCombo[m_PlayerNumber] = 0; + g_CurStageStats.iCurMissCombo[pn] = 0; SCREENMAN->PostMessageToTopScreen( SM_MissComboAborted, 0 ); break; case TNS_MISS: - ++g_CurStageStats.iCurMissCombo[m_PlayerNumber]; + ++g_CurStageStats.iCurMissCombo[pn]; m_iDCState = AS2D_MISS; // update dancing 2d characters that may have missed a note case TNS_GOOD: case TNS_BOO: @@ -1212,14 +1272,14 @@ void PlayerMinus::HandleTapRowScore( unsigned row ) } /* The score keeper updates the hit combo. Remember the old combo for handling announcers. */ - const int iOldCombo = g_CurStageStats.iCurCombo[m_PlayerNumber]; + const int iOldCombo = g_CurStageStats.iCurCombo[pn]; if(m_pPrimaryScoreKeeper) m_pPrimaryScoreKeeper->HandleTapRowScore(scoreOfLastTap, iNumTapsInRow ); if(m_pSecondaryScoreKeeper) m_pSecondaryScoreKeeper->HandleTapRowScore(scoreOfLastTap, iNumTapsInRow ); - m_Combo.SetCombo( g_CurStageStats.iCurCombo[m_PlayerNumber], g_CurStageStats.iCurMissCombo[m_PlayerNumber] ); + m_Combo.SetCombo( g_CurStageStats.iCurCombo[pn], g_CurStageStats.iCurMissCombo[pn] ); #define CROSSED( x ) (iOldCombo=x) if ( CROSSED(100) ) @@ -1247,12 +1307,12 @@ void PlayerMinus::HandleTapRowScore( unsigned row ) #undef CROSSED // new max combo - g_CurStageStats.iMaxCombo[m_PlayerNumber] = max(g_CurStageStats.iMaxCombo[m_PlayerNumber], iCurCombo); + g_CurStageStats.iMaxCombo[pn] = max(g_CurStageStats.iMaxCombo[pn], iCurCombo); /* Use the real current beat, not the beat we've been passed. That's because we * want to record the current life/combo to the current time; eg. if it's a MISS, * the beat we're registering is in the past, but the life is changing now. */ - g_CurStageStats.UpdateComboList( m_PlayerNumber, g_CurStageStats.fAliveSeconds[m_PlayerNumber], false ); + g_CurStageStats.UpdateComboList( pn, g_CurStageStats.fAliveSeconds[pn], false ); float life = -1; if( m_pLifeMeter ) @@ -1260,24 +1320,24 @@ void PlayerMinus::HandleTapRowScore( unsigned row ) else if( m_pCombinedLifeMeter ) { life = GAMESTATE->m_fTugLifePercentP1; - if( m_PlayerNumber == PLAYER_2 ) + if( pn == PLAYER_2 ) life = 1.0f - life; } if( life != -1 ) - g_CurStageStats.SetLifeRecordAt( m_PlayerNumber, life, g_CurStageStats.fAliveSeconds[m_PlayerNumber] ); + g_CurStageStats.SetLifeRecordAt( pn, life, g_CurStageStats.fAliveSeconds[pn] ); if (m_pScoreDisplay) - m_pScoreDisplay->SetScore(g_CurStageStats.iScore[m_PlayerNumber]); + m_pScoreDisplay->SetScore(g_CurStageStats.iScore[pn]); if (m_pSecondaryScoreDisplay) - m_pSecondaryScoreDisplay->SetScore(g_CurStageStats.iScore[m_PlayerNumber]); + m_pSecondaryScoreDisplay->SetScore(g_CurStageStats.iScore[pn]); if( m_pLifeMeter ) { m_pLifeMeter->ChangeLife( scoreOfLastTap ); m_pLifeMeter->OnDancePointsChange(); // update oni life meter } if( m_pCombinedLifeMeter ) { - m_pCombinedLifeMeter->ChangeLife( m_PlayerNumber, scoreOfLastTap ); - m_pCombinedLifeMeter->OnDancePointsChange( m_PlayerNumber ); // update oni life meter + m_pCombinedLifeMeter->ChangeLife( pn, scoreOfLastTap ); + m_pCombinedLifeMeter->OnDancePointsChange( pn ); // update oni life meter } } @@ -1292,7 +1352,7 @@ void PlayerMinus::HandleHoldScore( HoldNoteScore holdScore, TapNoteScore tapScor if(GAMESTATE->m_bDemonstrationOrJukebox) NoCheating = false; // don't accumulate points if AutoPlay is on. - if( NoCheating && GAMESTATE->m_PlayerController[m_PlayerNumber] == PC_AUTOPLAY ) + if( NoCheating && m_pPlayerState->m_PlayerController == PC_AUTOPLAY ) return; if(m_pPrimaryScoreKeeper) @@ -1300,18 +1360,23 @@ void PlayerMinus::HandleHoldScore( HoldNoteScore holdScore, TapNoteScore tapScor if(m_pSecondaryScoreKeeper) m_pSecondaryScoreKeeper->HandleHoldScore(holdScore, tapScore ); - if (m_pScoreDisplay) - m_pScoreDisplay->SetScore(g_CurStageStats.iScore[m_PlayerNumber]); - if (m_pSecondaryScoreDisplay) - m_pSecondaryScoreDisplay->SetScore(g_CurStageStats.iScore[m_PlayerNumber]); + // TODO: Remove use of PlayerNumber. + PlayerNumber pn = m_pPlayerState->m_PlayerNumber; - if( m_pLifeMeter ) { + if (m_pScoreDisplay) + m_pScoreDisplay->SetScore(g_CurStageStats.iScore[pn]); + if (m_pSecondaryScoreDisplay) + m_pSecondaryScoreDisplay->SetScore(g_CurStageStats.iScore[pn]); + + if( m_pLifeMeter ) + { m_pLifeMeter->ChangeLife( holdScore, tapScore ); m_pLifeMeter->OnDancePointsChange(); } - if( m_pCombinedLifeMeter ) { - m_pCombinedLifeMeter->ChangeLife( m_PlayerNumber, holdScore, tapScore ); - m_pCombinedLifeMeter->OnDancePointsChange( m_PlayerNumber ); + if( m_pCombinedLifeMeter ) + { + m_pCombinedLifeMeter->ChangeLife( pn, holdScore, tapScore ); + m_pCombinedLifeMeter->OnDancePointsChange( pn ); } } @@ -1328,7 +1393,7 @@ void PlayerMinus::FadeToFail() /* XXX: Why's m_NoteField in a separate class, again? Is that still needed? */ /* It was used to have an invisible computer player in PLAY_MODE_BATTLE. -Chris */ void Player::Load( - PlayerNumber player_no, + PlayerState* pPlayerState, const NoteData& noteData, LifeMeter* pLM, CombinedLifeMeter* pCombinedLM, @@ -1339,7 +1404,7 @@ void Player::Load( ScoreKeeper* pSecondaryScoreKeeper ) { PlayerMinus::Load( - player_no, + pPlayerState, noteData, pLM, pCombinedLM, diff --git a/stepmania/src/Player.h b/stepmania/src/Player.h index 4c3b345330..bf0e732f63 100644 --- a/stepmania/src/Player.h +++ b/stepmania/src/Player.h @@ -39,7 +39,7 @@ public: virtual void DrawPrimitives(); void Load( - PlayerNumber player_no, + PlayerState* pPlayerState, const NoteData& noteData, LifeMeter* pLM, CombinedLifeMeter* pCombinedLM, @@ -74,7 +74,7 @@ protected: int GetClosestNoteDirectional( int col, int iStartRow, int iMaxRowsAhead, bool bAllowGraded, bool bForward ) const; int GetClosestNote( int col, float fBeat, float fMaxBeatsAhead, float fMaxBeatsBehind, bool bAllowGraded ) const; - PlayerNumber m_PlayerNumber; + PlayerState* m_pPlayerState; float m_fNoteFieldHeight; float m_fOffset[SAMPLE_COUNT]; // for AutoSync @@ -93,20 +93,20 @@ protected: AttackDisplay m_AttackDisplay; int m_iDCState; - LifeMeter* m_pLifeMeter; - CombinedLifeMeter* m_pCombinedLifeMeter; - ScoreDisplay* m_pScoreDisplay; - ScoreDisplay* m_pSecondaryScoreDisplay; - ScoreKeeper* m_pPrimaryScoreKeeper; - ScoreKeeper* m_pSecondaryScoreKeeper; - Inventory* m_pInventory; + LifeMeter* m_pLifeMeter; + CombinedLifeMeter* m_pCombinedLifeMeter; + ScoreDisplay* m_pScoreDisplay; + ScoreDisplay* m_pSecondaryScoreDisplay; + ScoreKeeper* m_pPrimaryScoreKeeper; + ScoreKeeper* m_pSecondaryScoreKeeper; + Inventory* m_pInventory; - int m_iRowLastCrossed; - int m_iMineRowLastCrossed; + int m_iRowLastCrossed; + int m_iMineRowLastCrossed; - RageSound m_soundMine; - RageSound m_soundAttackLaunch; - RageSound m_soundAttackEnding; + RageSound m_soundMine; + RageSound m_soundAttackLaunch; + RageSound m_soundAttackEnding; vector m_vKeysounds; }; @@ -115,7 +115,7 @@ class Player : public PlayerMinus { public: void Load( - PlayerNumber player_no, + PlayerState* pPlayerState, const NoteData& noteData, LifeMeter* pLM, CombinedLifeMeter* pCombinedLM, diff --git a/stepmania/src/PlayerAI.cpp b/stepmania/src/PlayerAI.cpp index cc91e20c06..7e9e8b3cd1 100644 --- a/stepmania/src/PlayerAI.cpp +++ b/stepmania/src/PlayerAI.cpp @@ -5,6 +5,7 @@ #include "RageException.h" #include "GameState.h" #include "arch/arch.h" +#include "PlayerState.h" #define AI_PATH "Data/AI.ini" @@ -60,17 +61,16 @@ void PlayerAI::InitFromDisk() } -TapNoteScore PlayerAI::GetTapNoteScore( PlayerNumber pn ) +TapNoteScore PlayerAI::GetTapNoteScore( const PlayerState* pPlayerState ) { - - int iCpuSkill = GAMESTATE->m_iCpuSkill[pn]; + int iCpuSkill = pPlayerState->m_iCpuSkill; int iSumOfAttackLevels = - GAMESTATE->m_fSecondsUntilAttacksPhasedOut[pn] > 0 ? - GAMESTATE->m_iLastPositiveSumOfAttackLevels[pn] : + pPlayerState->m_fSecondsUntilAttacksPhasedOut > 0 ? + pPlayerState->m_iLastPositiveSumOfAttackLevels : 0; ASSERT_M( iCpuSkill>=0 && iCpuSkillm_PlayerController[pn] == PC_CPU, ssprintf("%i", GAMESTATE->m_PlayerController[pn]) ); + ASSERT_M( pPlayerState->m_PlayerController == PC_CPU, ssprintf("%i", pPlayerState->m_PlayerController) ); iCpuSkill -= iSumOfAttackLevels*3; CLAMP( iCpuSkill, 0, NUM_SKILL_LEVELS-1 ); diff --git a/stepmania/src/PlayerAI.h b/stepmania/src/PlayerAI.h index 8c1de95e27..930850a617 100644 --- a/stepmania/src/PlayerAI.h +++ b/stepmania/src/PlayerAI.h @@ -3,6 +3,8 @@ #include "GameConstantsAndTypes.h" +struct PlayerState; + const int NUM_SKILL_LEVELS = 6; // 0-5 class PlayerAI @@ -10,7 +12,7 @@ class PlayerAI public: static void InitFromDisk(); - static TapNoteScore GetTapNoteScore( PlayerNumber pn ); + static TapNoteScore GetTapNoteScore( const PlayerState* pPlayerState ); }; diff --git a/stepmania/src/PlayerOptions.cpp b/stepmania/src/PlayerOptions.cpp index 3cc3794dd9..8cd03e2519 100644 --- a/stepmania/src/PlayerOptions.cpp +++ b/stepmania/src/PlayerOptions.cpp @@ -484,7 +484,7 @@ void PlayerOptions::ToggleOneTurn( Turn t ) m_bTurns[t] = !bWasOn; } -float PlayerOptions::GetReversePercentForColumn( int iCol ) +float PlayerOptions::GetReversePercentForColumn( int iCol ) const { float f = 0; int iNumCols = GAMESTATE->GetCurrentStyle()->m_iColsPerPlayer; diff --git a/stepmania/src/PlayerOptions.h b/stepmania/src/PlayerOptions.h index 75c6ada01a..a73d95948e 100644 --- a/stepmania/src/PlayerOptions.h +++ b/stepmania/src/PlayerOptions.h @@ -92,7 +92,7 @@ struct PlayerOptions SCROLL_CENTERED, NUM_SCROLLS }; - float GetReversePercentForColumn( int iCol ); // accounts for all Directions + float GetReversePercentForColumn( int iCol ) const; // accounts for all Directions /* All floats have a corresponding speed setting, which determines how fast * PlayerOptions::Approach approaches. */ diff --git a/stepmania/src/PlayerState.cpp b/stepmania/src/PlayerState.cpp new file mode 100644 index 0000000000..53b43ce3fe --- /dev/null +++ b/stepmania/src/PlayerState.cpp @@ -0,0 +1,28 @@ +#include "global.h" +#include "PlayerState.h" + + +/* + * (c) 2001-2004 Chris Danford, Chris Gomez + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, and/or sell copies of the Software, and to permit persons to + * whom the Software is furnished to do so, provided that the above + * copyright notice(s) and this permission notice appear in all copies of + * the Software and that both the above copyright notice(s) and this + * permission notice appear in supporting documentation. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF + * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS + * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT + * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ diff --git a/stepmania/src/PlayerState.h b/stepmania/src/PlayerState.h new file mode 100644 index 0000000000..0d814d4f21 --- /dev/null +++ b/stepmania/src/PlayerState.h @@ -0,0 +1,84 @@ +/* PlayerNumber */ + +#ifndef PlayerState_H +#define PlayerState_H + +#include "PlayerNumber.h" +#include "PlayerOptions.h" +#include +#include "Attack.h" + +struct PlayerState +{ + // TODO: Remove use of PlayerNumber. All data about the player should live + // in PlayerState and callers should not use PlayerNumber to index into + // GameState. + PlayerNumber m_PlayerNumber; + + + PlayerOptions m_CurrentPlayerOptions; // current approaches destination + PlayerOptions m_PlayerOptions; // change this, and current will move gradually toward it + PlayerOptions m_StoredPlayerOptions; // user's choices on the PlayerOptions screen + + // + // Used in Gameplay + // + map m_BeatToNoteSkin; + mutable float m_fLastDrawnBeat; // Set by NoteField. Used to push NoteSkin-changing modifers back so that the NoteSkin doesn't pop. + + enum HealthState { HOT, ALIVE, DANGER, DEAD }; + HealthState m_HealthState; + + PlayerController m_PlayerController; + + // + // Used in Battle and Rave + // + int m_iCpuSkill; // only used when m_PlayerController is PC_CPU + // Attacks take a while to transition out of use. Account for this in PlayerAI + // by still penalizing it for 1 second after the player options are rebuilt. + int m_iLastPositiveSumOfAttackLevels; + float m_fSecondsUntilAttacksPhasedOut; // positive means PlayerAI is still affected + bool m_bAttackBeganThisUpdate; // flag for other objects to watch (play sounds) + bool m_bAttackEndedThisUpdate; // flag for other objects to watch (play sounds) + AttackArray m_ActiveAttacks; + vector m_ModsToApply; + + // + // Used in Rave + // + float m_fSuperMeter; // between 0 and NUM_ATTACK_LEVELS + float m_fSuperMeterGrowthScale; + + // + // Used in Battle + // + Attack m_Inventory[NUM_INVENTORY_SLOTS]; +}; + +#endif + +/* + * (c) 2001-2004 Chris Danford, Chris Gomez + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, and/or sell copies of the Software, and to permit persons to + * whom the Software is furnished to do so, provided that the above + * copyright notice(s) and this permission notice appear in all copies of + * the Software and that both the above copyright notice(s) and this + * permission notice appear in supporting documentation. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF + * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS + * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT + * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ diff --git a/stepmania/src/ReceptorArrow.cpp b/stepmania/src/ReceptorArrow.cpp index 9fc29d234f..ca9385ac3a 100644 --- a/stepmania/src/ReceptorArrow.cpp +++ b/stepmania/src/ReceptorArrow.cpp @@ -8,6 +8,7 @@ #include "RageLog.h" #include "RageUtil.h" #include "Game.h" +#include "PlayerState.h" ReceptorArrow::ReceptorArrow() @@ -16,11 +17,14 @@ ReceptorArrow::ReceptorArrow() StopAnimating(); } -bool ReceptorArrow::Load( CString NoteSkin, PlayerNumber pn, int iColNo ) +bool ReceptorArrow::Load( CString NoteSkin, const PlayerState* pPlayerState, int iColNo ) { - m_PlayerNumber = pn; + m_pPlayerState = pPlayerState; m_iColNo = iColNo; + // TODO: Remove use of PlayerNumber. + PlayerNumber pn = m_pPlayerState->m_PlayerNumber; + NoteFieldMode &mode = g_NoteFieldMode[pn]; CString sButton = mode.GrayButtonNames[iColNo]; if( sButton == "" ) @@ -55,7 +59,7 @@ void ReceptorArrow::Update( float fDeltaTime ) ActorFrame::Update( fDeltaTime ); // update pressblock alignment based on scroll direction - bool bReverse = GAMESTATE->m_PlayerOptions[m_PlayerNumber].GetReversePercentForColumn(m_iColNo) > 0.5; + bool bReverse = m_pPlayerState->m_PlayerOptions.GetReversePercentForColumn(m_iColNo) > 0.5; m_pPressBlock->SetVertAlign( bReverse ? Actor::align_bottom : Actor::align_top ); } diff --git a/stepmania/src/ReceptorArrow.h b/stepmania/src/ReceptorArrow.h index a389f4e3f7..6c84b783e4 100644 --- a/stepmania/src/ReceptorArrow.h +++ b/stepmania/src/ReceptorArrow.h @@ -8,11 +8,13 @@ #include "PlayerNumber.h" #include "GameConstantsAndTypes.h" +struct PlayerState; + class ReceptorArrow : public ActorFrame { public: ReceptorArrow(); - bool Load( CString NoteSkin, PlayerNumber pn, int iColNo ); + bool Load( CString NoteSkin, const PlayerState* pPlayerState, int iColNo ); virtual void DrawPrimitives(); virtual void Update( float fDeltaTime ); @@ -20,7 +22,7 @@ public: void SetPressed() { m_bIsPressed = true; }; private: - PlayerNumber m_PlayerNumber; + const PlayerState* m_pPlayerState; int m_iColNo; AutoActor m_pReceptorWaiting; diff --git a/stepmania/src/ReceptorArrowRow.cpp b/stepmania/src/ReceptorArrowRow.cpp index 62d74fbc38..ee71e077cf 100644 --- a/stepmania/src/ReceptorArrowRow.cpp +++ b/stepmania/src/ReceptorArrowRow.cpp @@ -7,6 +7,7 @@ #include "GameState.h" #include "PrefsManager.h" #include "NoteFieldPositioning.h" +#include "PlayerState.h" ReceptorArrowRow::ReceptorArrowRow() @@ -14,9 +15,9 @@ ReceptorArrowRow::ReceptorArrowRow() m_iNumCols = 0; } -void ReceptorArrowRow::Load( PlayerNumber pn, CString NoteSkin, float fYReverseOffset ) +void ReceptorArrowRow::Load( const PlayerState* pPlayerState, CString NoteSkin, float fYReverseOffset ) { - m_PlayerNumber = pn; + m_pPlayerState = pPlayerState; m_fYReverseOffsetPixels = fYReverseOffset; const Style* pStyle = GAMESTATE->GetCurrentStyle(); @@ -26,7 +27,7 @@ void ReceptorArrowRow::Load( PlayerNumber pn, CString NoteSkin, float fYReverseO for( int c=0; cm_CurrentPlayerOptions[m_PlayerNumber].m_fDark) ); + m_ReceptorArrow[c].SetDiffuse( RageColor(1,1,1,1 - m_pPlayerState->m_CurrentPlayerOptions.m_fDark) ); // set arrow XYZ - const float fX = ArrowGetXPos( m_PlayerNumber, c, 0 ); - const float fY = ArrowGetYPos( m_PlayerNumber, c, 0, m_fYReverseOffsetPixels ); - const float fZ = ArrowGetZPos( m_PlayerNumber, c, 0 ); + const float fX = ArrowEffects::GetXPos( m_pPlayerState, c, 0 ); + const float fY = ArrowEffects::GetYPos( m_pPlayerState, c, 0, m_fYReverseOffsetPixels ); + const float fZ = ArrowEffects::GetZPos( m_pPlayerState, c, 0 ); m_ReceptorArrow[c].SetX( fX ); m_ReceptorArrow[c].SetY( fY ); m_ReceptorArrow[c].SetZ( fZ ); - const float fZoom = ArrowGetZoom( m_PlayerNumber ); + const float fZoom = ArrowEffects::GetZoom( m_pPlayerState ); m_ReceptorArrow[c].SetZoom( fZoom ); } } void ReceptorArrowRow::DrawPrimitives() { + // TODO: Remove use of PlayerNumber. + PlayerNumber pn = m_pPlayerState->m_PlayerNumber; + for( int c=0; cGetMetricF("ScoreDisplayBattle",ssprintf("Item%dX",i+1)) #define ITEM_Y( i ) THEME->GetMetricF("ScoreDisplayBattle",ssprintf("Item%dY",i+1)) @@ -31,9 +32,9 @@ ScoreDisplayBattle::ScoreDisplayBattle() TEXTUREMAN->CacheTexture( asIconPaths[j] ); } -void ScoreDisplayBattle::Init( PlayerNumber pn ) +void ScoreDisplayBattle::Init( const PlayerState* pPlayerState ) { - ScoreDisplay::Init( pn ); + ScoreDisplay::Init( pPlayerState ); } void ScoreDisplayBattle::Update( float fDelta ) @@ -42,7 +43,7 @@ void ScoreDisplayBattle::Update( float fDelta ) for( int s=0; sm_Inventory[m_PlayerNumber][s]; + const Attack& attack = m_pPlayerState->m_Inventory[s]; CString sNewModifier = attack.sModifier; if( sNewModifier != m_iLastSeenInventory[s] ) diff --git a/stepmania/src/ScoreDisplayBattle.h b/stepmania/src/ScoreDisplayBattle.h index 20d000e7ea..7e9493ac1f 100644 --- a/stepmania/src/ScoreDisplayBattle.h +++ b/stepmania/src/ScoreDisplayBattle.h @@ -10,7 +10,7 @@ class ScoreDisplayBattle : public ScoreDisplay { public: ScoreDisplayBattle(); - virtual void Init( PlayerNumber pn ); + virtual void Init( const PlayerState* pPlayerState ); virtual void Update( float fDelta ); diff --git a/stepmania/src/ScoreDisplayNormal.cpp b/stepmania/src/ScoreDisplayNormal.cpp index 818cec4ea1..79bad6316c 100644 --- a/stepmania/src/ScoreDisplayNormal.cpp +++ b/stepmania/src/ScoreDisplayNormal.cpp @@ -5,6 +5,7 @@ #include "PrefsManager.h" #include "GameState.h" #include "ThemeManager.h" +#include "PlayerState.h" const float SCORE_TWEEN_TIME = 0.2f; @@ -33,9 +34,13 @@ ScoreDisplayNormal::ScoreDisplayNormal() this->AddChild( &m_text ); } -void ScoreDisplayNormal::Init( PlayerNumber pn ) +void ScoreDisplayNormal::Init( const PlayerState* pPlayerState ) { - ScoreDisplay::Init( pn ); + ScoreDisplay::Init( pPlayerState ); + + // TODO: Remove use of PlayerNumber. + PlayerNumber pn = pPlayerState->m_PlayerNumber; + m_text.SetDiffuse( PlayerToColor(pn) ); } diff --git a/stepmania/src/ScoreDisplayNormal.h b/stepmania/src/ScoreDisplayNormal.h index f3c8d021f2..58905600d5 100644 --- a/stepmania/src/ScoreDisplayNormal.h +++ b/stepmania/src/ScoreDisplayNormal.h @@ -13,7 +13,7 @@ class ScoreDisplayNormal : public ScoreDisplay public: ScoreDisplayNormal(); - virtual void Init( PlayerNumber pn ); + virtual void Init( const PlayerState* pPlayerState ); virtual void Update( float fDeltaTime ); diff --git a/stepmania/src/ScoreDisplayOni.cpp b/stepmania/src/ScoreDisplayOni.cpp index b3b43862de..7dc55d0f42 100644 --- a/stepmania/src/ScoreDisplayOni.cpp +++ b/stepmania/src/ScoreDisplayOni.cpp @@ -7,6 +7,7 @@ #include "GameState.h" #include "ThemeManager.h" #include "StageStats.h" +#include "PlayerState.h" ScoreDisplayOni::ScoreDisplayOni() @@ -22,9 +23,13 @@ ScoreDisplayOni::ScoreDisplayOni() this->AddChild( &m_text ); } -void ScoreDisplayOni::Init( PlayerNumber pn ) +void ScoreDisplayOni::Init( const PlayerState* pPlayerState ) { - ScoreDisplay::Init( pn ); + ScoreDisplay::Init( pPlayerState ); + + // TODO: Remove use of PlayerNumber. + PlayerNumber pn = pPlayerState->m_PlayerNumber; + m_text.SetDiffuse( PlayerToColor(pn) ); } @@ -33,9 +38,12 @@ void ScoreDisplayOni::Update( float fDelta ) { ScoreDisplay::Update( fDelta ); + // TODO: Remove use of PlayerNumber. + PlayerNumber pn = m_pPlayerState->m_PlayerNumber; + float fSecsIntoPlay = 0; - if( GAMESTATE->IsPlayerEnabled(m_PlayerNumber) ) - fSecsIntoPlay = g_CurStageStats.fAliveSeconds[m_PlayerNumber]; + if( GAMESTATE->IsPlayerEnabled(pn) ) + fSecsIntoPlay = g_CurStageStats.fAliveSeconds[pn]; m_text.SetText( SecondsToMMSSMsMs(fSecsIntoPlay) ); } diff --git a/stepmania/src/ScoreDisplayOni.h b/stepmania/src/ScoreDisplayOni.h index e45ed8c880..4745c360a0 100644 --- a/stepmania/src/ScoreDisplayOni.h +++ b/stepmania/src/ScoreDisplayOni.h @@ -12,7 +12,7 @@ class ScoreDisplayOni : public ScoreDisplay public: ScoreDisplayOni(); - virtual void Init( PlayerNumber pn ); + virtual void Init( const PlayerState* pPlayerState ); virtual void Update( float fDelta ); diff --git a/stepmania/src/ScoreDisplayPercentage.cpp b/stepmania/src/ScoreDisplayPercentage.cpp index cafbedff36..2b6dce0b98 100644 --- a/stepmania/src/ScoreDisplayPercentage.cpp +++ b/stepmania/src/ScoreDisplayPercentage.cpp @@ -3,6 +3,7 @@ #include "ScoreDisplayPercentage.h" #include "ThemeManager.h" #include "StageStats.h" +#include "PlayerState.h" ScoreDisplayPercentage::ScoreDisplayPercentage() { @@ -13,9 +14,9 @@ ScoreDisplayPercentage::ScoreDisplayPercentage() this->AddChild( &m_Percent ); } -void ScoreDisplayPercentage::Init( PlayerNumber pn ) +void ScoreDisplayPercentage::Init( const PlayerState* pPlayerState ) { - m_Percent.Load( pn, &g_CurStageStats, true ); + m_Percent.Load( pPlayerState->m_PlayerNumber, &g_CurStageStats, true ); } /* diff --git a/stepmania/src/ScoreDisplayPercentage.h b/stepmania/src/ScoreDisplayPercentage.h index 16e9979c66..c72cf03ff3 100644 --- a/stepmania/src/ScoreDisplayPercentage.h +++ b/stepmania/src/ScoreDisplayPercentage.h @@ -8,7 +8,7 @@ class ScoreDisplayPercentage : public ScoreDisplay { public: ScoreDisplayPercentage(); - void Init( PlayerNumber pn ); + void Init( const PlayerState* pPlayerState ); private: PercentageDisplay m_Percent; diff --git a/stepmania/src/ScoreDisplayRave.cpp b/stepmania/src/ScoreDisplayRave.cpp index 0ba63400a0..538cebbbc1 100644 --- a/stepmania/src/ScoreDisplayRave.cpp +++ b/stepmania/src/ScoreDisplayRave.cpp @@ -7,6 +7,7 @@ #include "GameState.h" #include "ThemeManager.h" #include "ActorUtil.h" +#include "PlayerState.h" ScoreDisplayRave::ScoreDisplayRave() @@ -34,9 +35,11 @@ ScoreDisplayRave::ScoreDisplayRave() this->AddChild( &m_textLevel ); } -void ScoreDisplayRave::Init( PlayerNumber pn ) +void ScoreDisplayRave::Init( const PlayerState* pPlayerState ) { - ScoreDisplay::Init( pn ); + ScoreDisplay::Init( pPlayerState ); + + PlayerNumber pn = pPlayerState->m_PlayerNumber; m_sprFrameBase.Load( THEME->GetPathToG(ssprintf("ScoreDisplayRave frame base p%d",pn+1)) ); m_sprFrameOverlay.Load( THEME->GetPathToG(ssprintf("ScoreDisplayRave frame overlay p%d",pn+1)) ); @@ -55,7 +58,9 @@ void ScoreDisplayRave::Update( float fDelta ) { ScoreDisplay::Update( fDelta ); - float fLevel = GAMESTATE->m_fSuperMeter[m_PlayerNumber]; + PlayerNumber pn = m_pPlayerState->m_PlayerNumber; + + float fLevel = m_pPlayerState->m_fSuperMeter; AttackLevel level = (AttackLevel)(int)fLevel; if( level != m_lastLevelSeen ) diff --git a/stepmania/src/ScoreDisplayRave.h b/stepmania/src/ScoreDisplayRave.h index b7d4eb7735..92a6a9742e 100644 --- a/stepmania/src/ScoreDisplayRave.h +++ b/stepmania/src/ScoreDisplayRave.h @@ -11,7 +11,7 @@ class ScoreDisplayRave : public ScoreDisplay { public: ScoreDisplayRave(); - virtual void Init( PlayerNumber pn ); + virtual void Init( const PlayerState* pPlayerState ); virtual void Update( float fDelta ); diff --git a/stepmania/src/ScoreKeeper.h b/stepmania/src/ScoreKeeper.h index 0f4de86c4b..f7e4ade22c 100644 --- a/stepmania/src/ScoreKeeper.h +++ b/stepmania/src/ScoreKeeper.h @@ -12,17 +12,17 @@ */ #include "Actor.h" -#include "PlayerNumber.h" #include "GameConstantsAndTypes.h" // for TapNoteScore and HoldNoteScore class NoteData; class Inventory; class Steps; +struct PlayerState; class ScoreKeeper: public Actor { protected: - PlayerNumber m_PlayerNumber; + PlayerState* m_pPlayerState; /* Common toggles that this class handles directly: */ @@ -31,7 +31,7 @@ protected: // bool Stats_DoublesCount; public: - ScoreKeeper(PlayerNumber pn) { m_PlayerNumber=pn; } + ScoreKeeper(PlayerState* pPlayerState) { m_pPlayerState=pPlayerState; } virtual void DrawPrimitives() { } virtual void Update( float fDelta ) { } diff --git a/stepmania/src/ScoreKeeperMAX2.cpp b/stepmania/src/ScoreKeeperMAX2.cpp index 249965630c..cfeded18ad 100644 --- a/stepmania/src/ScoreKeeperMAX2.cpp +++ b/stepmania/src/ScoreKeeperMAX2.cpp @@ -14,9 +14,11 @@ #include "StageStats.h" #include "ProfileManager.h" #include "NetworkSyncManager.h" +#include "PlayerState.h" +#include "Style.h" -ScoreKeeperMAX2::ScoreKeeperMAX2( const vector& apSongs, const vector& apSteps_, const vector &asModifiers, PlayerNumber pn_ ): - ScoreKeeper(pn_), apSteps(apSteps_) +ScoreKeeperMAX2::ScoreKeeperMAX2( const vector& apSongs, const vector& apSteps_, const vector &asModifiers, PlayerState* pPlayerState ): + ScoreKeeper(pPlayerState), apSteps(apSteps_) { ASSERT( apSongs.size() == apSteps_.size() ); ASSERT( apSongs.size() == asModifiers.size() ); @@ -37,7 +39,7 @@ ScoreKeeperMAX2::ScoreKeeperMAX2( const vector& apSongs, const vectorGetCurrentStyle(); NoteData nd; - pStyle->GetTransformedNoteDataForStyle( pn_, ndTemp, nd ); + pStyle->GetTransformedNoteDataForStyle( pPlayerState->m_PlayerNumber, ndTemp, nd ); /* Compute RadarValues before applying any user-selected mods. Apply * Course mods and count them in the "pre" RadarValues because they're @@ -54,13 +56,18 @@ ScoreKeeperMAX2::ScoreKeeperMAX2( const vector& apSongs, const vectorGetOptionsForCourse(po,so,pn) to get options based on * the last call to StoreSelectedOptions and the modifiers list, but that'd * mean moving the queues in ScreenGameplay to GameState ... */ - NoteDataUtil::TransformNoteData( nd, GAMESTATE->m_PlayerOptions[pn_], pSteps->m_StepsType ); + NoteDataUtil::TransformNoteData( nd, pPlayerState->m_PlayerOptions, pSteps->m_StepsType ); RadarValues rvPost; NoteDataUtil::GetRadarValues( nd, pSong->m_fMusicLengthSeconds, rvPost ); iTotalPossibleDancePoints += this->GetPossibleDancePoints( rvPre, rvPost ); } - g_CurStageStats.iPossibleDancePoints[pn_] = iTotalPossibleDancePoints; + + // TODO: Move StageStats numbers into PlayerState. + { + PlayerNumber pn = m_pPlayerState->m_PlayerNumber; + g_CurStageStats.iPossibleDancePoints[pn] = iTotalPossibleDancePoints; + } m_iScoreRemainder = 0; @@ -197,7 +204,9 @@ static int GetScore(int p, int B, int S, int n) void ScoreKeeperMAX2::AddScore( TapNoteScore score ) { - int &iScore = g_CurStageStats.iScore[m_PlayerNumber]; + // TODO: Move StageStats numbers into PlayerState. + PlayerNumber pn = m_pPlayerState->m_PlayerNumber; + int &iScore = g_CurStageStats.iScore[pn]; /* http://www.aaroninjapan.com/ddr2.html @@ -257,7 +266,7 @@ void ScoreKeeperMAX2::AddScore( TapNoteScore score ) const int B = m_iMaxPossiblePoints/10; // Don't use a multiplier if the player has failed - if( g_CurStageStats.bFailedEarlier[m_PlayerNumber] ) + if( g_CurStageStats.bFailedEarlier[pn] ) { iScore += p; // make score evenly divisible by 5 @@ -270,8 +279,8 @@ void ScoreKeeperMAX2::AddScore( TapNoteScore score ) else { iScore += GetScore(p, B, sum, m_iTapNotesHit); - const int &iCurrentCombo = g_CurStageStats.iCurCombo[m_PlayerNumber]; - g_CurStageStats.iBonus[m_PlayerNumber] += m_ComboBonusFactor[score] * iCurrentCombo; + const int &iCurrentCombo = g_CurStageStats.iCurCombo[pn]; + g_CurStageStats.iBonus[pn] += m_ComboBonusFactor[score] * iCurrentCombo; } /* Subtract the maximum this step could have been worth from the bonus. */ @@ -279,7 +288,7 @@ void ScoreKeeperMAX2::AddScore( TapNoteScore score ) if ( m_iTapNotesHit == m_iNumTapsAndHolds && score >= TNS_PERFECT ) { - if (!g_CurStageStats.bFailedEarlier[m_PlayerNumber]) + if (!g_CurStageStats.bFailedEarlier[pn]) iScore += m_iPointBonus; if ( m_bIsLastSongInCourse ) { @@ -305,11 +314,14 @@ void ScoreKeeperMAX2::AddScore( TapNoteScore score ) void ScoreKeeperMAX2::HandleTapScore( TapNoteScore score ) { + // TODO: Move StageStats numbers into PlayerState. + PlayerNumber pn = m_pPlayerState->m_PlayerNumber; + if( score == TNS_HIT_MINE ) { - if( GAMESTATE->m_HealthState[m_PlayerNumber] != GameState::DEAD ) - g_CurStageStats.iActualDancePoints[m_PlayerNumber] += TapNoteScoreToDancePoints( TNS_HIT_MINE ); - g_CurStageStats.iTapNoteScores[m_PlayerNumber][TNS_HIT_MINE] += 1; + if( m_pPlayerState->m_HealthState != PlayerState::DEAD ) + g_CurStageStats.iActualDancePoints[pn] += TapNoteScoreToDancePoints( TNS_HIT_MINE ); + g_CurStageStats.iTapNoteScores[pn][TNS_HIT_MINE] += 1; } } @@ -317,11 +329,14 @@ void ScoreKeeperMAX2::HandleTapRowScore( TapNoteScore scoreOfLastTap, int iNumTa { ASSERT( iNumTapsInRow >= 1 ); + // TODO: Move StageStats numbers into PlayerState. + PlayerNumber pn = m_pPlayerState->m_PlayerNumber; + // Update dance points. - if( GAMESTATE->m_HealthState[m_PlayerNumber] != GameState::DEAD ) - g_CurStageStats.iActualDancePoints[m_PlayerNumber] += TapNoteScoreToDancePoints( scoreOfLastTap ); + if( m_pPlayerState->m_HealthState != PlayerState::DEAD ) + g_CurStageStats.iActualDancePoints[pn] += TapNoteScoreToDancePoints( scoreOfLastTap ); // update judged row totals - g_CurStageStats.iTapNoteScores[m_PlayerNumber][scoreOfLastTap] += 1; + g_CurStageStats.iTapNoteScores[pn][scoreOfLastTap] += 1; // // Regular combo @@ -352,7 +367,7 @@ void ScoreKeeperMAX2::HandleTapRowScore( TapNoteScore scoreOfLastTap, int iNumTa TapNoteScore MinScoreToContinueCombo = GAMESTATE->m_PlayMode == PLAY_MODE_ONI? TNS_PERFECT:TNS_GREAT; if( scoreOfLastTap >= MinScoreToContinueCombo ) - g_CurStageStats.iCurCombo[m_PlayerNumber] += ComboCountIfHit; + g_CurStageStats.iCurCombo[pn] += ComboCountIfHit; AddScore( scoreOfLastTap ); // only score once per row @@ -381,7 +396,9 @@ void ScoreKeeperMAX2::HandleTapRowScore( TapNoteScore scoreOfLastTap, int iNumTa !GAMESTATE->m_bDemonstrationOrJukebox ) { SCREENMAN->PostMessageToTopScreen( SM_PlayToasty, 0 ); - PROFILEMAN->IncrementToastiesCount( m_PlayerNumber ); + + // TODO: keep a pointer to the Profile. Don't index with m_PlayerNumber + PROFILEMAN->IncrementToastiesCount( m_pPlayerState->m_PlayerNumber ); } break; default: @@ -390,25 +407,29 @@ void ScoreKeeperMAX2::HandleTapRowScore( TapNoteScore scoreOfLastTap, int iNumTa } - NSMAN->ReportScore(m_PlayerNumber, scoreOfLastTap, - g_CurStageStats.iScore[m_PlayerNumber], - g_CurStageStats.iCurCombo[m_PlayerNumber]); + // TODO: Remove indexing with PlayerNumber + NSMAN->ReportScore(pn, scoreOfLastTap, + g_CurStageStats.iScore[pn], + g_CurStageStats.iCurCombo[pn]); } void ScoreKeeperMAX2::HandleHoldScore( HoldNoteScore holdScore, TapNoteScore tapScore ) { + // TODO: Move StageStats numbers into PlayerState. + PlayerNumber pn = m_pPlayerState->m_PlayerNumber; + // update dance points totals - if( GAMESTATE->m_HealthState[m_PlayerNumber] != GameState::DEAD ) - g_CurStageStats.iActualDancePoints[m_PlayerNumber] += HoldNoteScoreToDancePoints( holdScore ); - g_CurStageStats.iHoldNoteScores[m_PlayerNumber][holdScore] ++; + if( m_pPlayerState->m_HealthState != PlayerState::DEAD ) + g_CurStageStats.iActualDancePoints[pn] += HoldNoteScoreToDancePoints( holdScore ); + g_CurStageStats.iHoldNoteScores[pn][holdScore] ++; if( holdScore == HNS_OK ) AddScore( TNS_MARVELOUS ); - NSMAN->ReportScore(m_PlayerNumber, holdScore+7, - g_CurStageStats.iScore[m_PlayerNumber], - g_CurStageStats.iCurCombo[m_PlayerNumber]); + NSMAN->ReportScore(pn, holdScore+7, + g_CurStageStats.iScore[pn], + g_CurStageStats.iCurCombo[pn]); } diff --git a/stepmania/src/ScoreKeeperMAX2.h b/stepmania/src/ScoreKeeperMAX2.h index 9a8d4ce07a..39ed80d4eb 100644 --- a/stepmania/src/ScoreKeeperMAX2.h +++ b/stepmania/src/ScoreKeeperMAX2.h @@ -29,7 +29,7 @@ class ScoreKeeperMAX2: public ScoreKeeper int m_ComboBonusFactor[NUM_TAP_NOTE_SCORES]; public: - ScoreKeeperMAX2( const vector& apSongs, const vector& apSteps, const vector &asModifiers, PlayerNumber pn); + ScoreKeeperMAX2( const vector& apSongs, const vector& apSteps, const vector &asModifiers, PlayerState* pPlayerState); // before a song plays (called multiple times if course) void OnNextSong( int iSongInCourseIndex, const Steps* pSteps, const NoteData* pNoteData ); diff --git a/stepmania/src/ScoreKeeperRave.cpp b/stepmania/src/ScoreKeeperRave.cpp index 97ee469b70..9ee8ef2bd7 100644 --- a/stepmania/src/ScoreKeeperRave.cpp +++ b/stepmania/src/ScoreKeeperRave.cpp @@ -7,11 +7,13 @@ #include "ScreenManager.h" #include "PrefsManager.h" #include "ThemeMetric.h" +#include "PlayerState.h" + ThemeMetric ATTACK_DURATION_SECONDS ("ScoreKeeperRave","AttackDurationSeconds"); -ScoreKeeperRave::ScoreKeeperRave(PlayerNumber pn) : ScoreKeeper(pn) +ScoreKeeperRave::ScoreKeeperRave( PlayerState* pPlayerState ) : ScoreKeeper(pPlayerState) { } @@ -63,7 +65,7 @@ void ScoreKeeperRave::AddSuperMeterDelta( float fUnscaledPercentChange ) { if( PREFSMAN->m_bMercifulDrain && fUnscaledPercentChange<0 ) { - float fSuperPercentage = GAMESTATE->m_fSuperMeter[m_PlayerNumber] / NUM_ATTACK_LEVELS; + float fSuperPercentage = m_pPlayerState->m_fSuperMeter / NUM_ATTACK_LEVELS; fUnscaledPercentChange *= SCALE( fSuperPercentage, 0.f, 1.f, 0.5f, 1.f); } @@ -71,7 +73,7 @@ void ScoreKeeperRave::AddSuperMeterDelta( float fUnscaledPercentChange ) if( PREFSMAN->m_bMercifulSuperMeter ) { float fLifePercentage = 0; - switch( m_PlayerNumber ) + switch( m_pPlayerState->m_PlayerNumber ) { case PLAYER_1: fLifePercentage = GAMESTATE->m_fTugLifePercentP1; break; case PLAYER_2: fLifePercentage = 1 - GAMESTATE->m_fTugLifePercentP1; break; @@ -87,35 +89,35 @@ void ScoreKeeperRave::AddSuperMeterDelta( float fUnscaledPercentChange ) // mercy: drop super meter faster if at a higher level if( fUnscaledPercentChange < 0 ) - fUnscaledPercentChange *= SCALE( GAMESTATE->m_fSuperMeter[m_PlayerNumber], 0.f, 1.f, 0.01f, 1.f ); + fUnscaledPercentChange *= SCALE( m_pPlayerState->m_fSuperMeter, 0.f, 1.f, 0.01f, 1.f ); - AttackLevel oldAL = (AttackLevel)(int)GAMESTATE->m_fSuperMeter[m_PlayerNumber]; + AttackLevel oldAL = (AttackLevel)(int)m_pPlayerState->m_fSuperMeter; float fPercentToMove = fUnscaledPercentChange; - GAMESTATE->m_fSuperMeter[m_PlayerNumber] += fPercentToMove * GAMESTATE->m_fSuperMeterGrowthScale[m_PlayerNumber]; - CLAMP( GAMESTATE->m_fSuperMeter[m_PlayerNumber], 0.f, NUM_ATTACK_LEVELS ); + m_pPlayerState->m_fSuperMeter += fPercentToMove * m_pPlayerState->m_fSuperMeterGrowthScale; + CLAMP( m_pPlayerState->m_fSuperMeter, 0.f, NUM_ATTACK_LEVELS ); - AttackLevel newAL = (AttackLevel)(int)GAMESTATE->m_fSuperMeter[m_PlayerNumber]; + AttackLevel newAL = (AttackLevel)(int)m_pPlayerState->m_fSuperMeter; if( newAL > oldAL ) { LaunchAttack( oldAL ); if( newAL == NUM_ATTACK_LEVELS ) // hit upper bounds of meter - GAMESTATE->m_fSuperMeter[m_PlayerNumber] -= 1.f; + m_pPlayerState->m_fSuperMeter -= 1.f; } // mercy: if losing remove attacks on life drain if( fUnscaledPercentChange < 0 ) { bool bWinning; - switch( m_PlayerNumber ) + switch( m_pPlayerState->m_PlayerNumber ) { case PLAYER_1: bWinning = GAMESTATE->m_fTugLifePercentP1 > 0.5f; break; case PLAYER_2: bWinning = GAMESTATE->m_fTugLifePercentP1 < 0.5f; break; default: ASSERT(0); } if( !bWinning ) - GAMESTATE->RemoveActiveAttacksForPlayer( m_PlayerNumber ); + GAMESTATE->RemoveActiveAttacksForPlayer( m_pPlayerState->m_PlayerNumber ); } } @@ -126,10 +128,12 @@ void ScoreKeeperRave::Update( float fDelta ) void ScoreKeeperRave::LaunchAttack( AttackLevel al ) { - CString* asAttacks = GAMESTATE->m_pCurCharacters[m_PlayerNumber]->m_sAttacks[al]; // [NUM_ATTACKS_PER_LEVEL] + PlayerNumber pn = m_pPlayerState->m_PlayerNumber; + + CString* asAttacks = GAMESTATE->m_pCurCharacters[pn]->m_sAttacks[al]; // [NUM_ATTACKS_PER_LEVEL] CString sAttackToGive; - if (GAMESTATE->m_pCurCharacters[m_PlayerNumber] != NULL) + if (GAMESTATE->m_pCurCharacters[pn] != NULL) sAttackToGive = asAttacks[ rand()%NUM_ATTACKS_PER_LEVEL ]; else { @@ -138,7 +142,7 @@ void ScoreKeeperRave::LaunchAttack( AttackLevel al ) sAttackToGive = DefaultAttacks[ rand()%8 ]; } - PlayerNumber pnToAttack = OPPOSITE_PLAYER[m_PlayerNumber]; + PlayerNumber pnToAttack = OPPOSITE_PLAYER[pn]; Attack a; a.level = al; diff --git a/stepmania/src/ScoreKeeperRave.h b/stepmania/src/ScoreKeeperRave.h index 830c03ee39..24cbf6c7be 100644 --- a/stepmania/src/ScoreKeeperRave.h +++ b/stepmania/src/ScoreKeeperRave.h @@ -11,7 +11,7 @@ class ScoreKeeperRave : public ScoreKeeper { public: // Overrides - ScoreKeeperRave(PlayerNumber pn); + ScoreKeeperRave( PlayerState* pPlayerState ); void Update( float fDelta ); void OnNextSong( int iSongInCourseIndex, const Steps* pSteps, const NoteData* pNoteData ); // before a song plays (called multiple times if course) void HandleTapScore( TapNoteScore score ); diff --git a/stepmania/src/ScreenEdit.cpp b/stepmania/src/ScreenEdit.cpp index 5d5793f465..cd86896355 100644 --- a/stepmania/src/ScreenEdit.cpp +++ b/stepmania/src/ScreenEdit.cpp @@ -25,6 +25,7 @@ #include "Foreach.h" #include "ScreenDimensions.h" #include "ThemeMetric.h" +#include "PlayerState.h" const float RECORD_HOLD_SECONDS = 0.3f; @@ -404,11 +405,11 @@ ScreenEdit::ScreenEdit( CString sName ) : Screen( sName ) GAMESTATE->m_fSongBeat = 0; m_fTrailingBeat = GAMESTATE->m_fSongBeat; - GAMESTATE->m_PlayerOptions[PLAYER_1].m_fScrollSpeed = 1; + GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions.m_fScrollSpeed = 1; GAMESTATE->m_SongOptions.m_fMusicRate = 1; /* Not all games have a noteskin named "note" ... */ if( NOTESKIN->DoesNoteSkinExist("note") ) - GAMESTATE->m_PlayerOptions[PLAYER_1].m_sNoteSkin = "note"; // change noteskin before loading all of the edit Actors + GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions.m_sNoteSkin = "note"; // change noteskin before loading all of the edit Actors GAMESTATE->ResetNoteSkins(); GAMESTATE->StoreSelectedOptions(); @@ -421,29 +422,29 @@ ScreenEdit::ScreenEdit( CString sName ) : Screen( sName ) m_NoteFieldEdit.SetXY( EDIT_X, PLAYER_Y ); m_NoteFieldEdit.SetZoom( 0.5f ); - m_NoteFieldEdit.Load( ¬eData, PLAYER_1, -240, 800, PLAYER_HEIGHT*2 ); + m_NoteFieldEdit.Load( ¬eData, GAMESTATE->m_pPlayerState[PLAYER_1], -240, 800, PLAYER_HEIGHT*2 ); m_rectRecordBack.StretchTo( RectF(SCREEN_LEFT, SCREEN_TOP, SCREEN_RIGHT, SCREEN_BOTTOM) ); m_rectRecordBack.SetDiffuse( RageColor(0,0,0,0) ); m_NoteFieldRecord.SetXY( EDIT_X, PLAYER_Y ); m_NoteFieldRecord.SetZoom( 1.0f ); - m_NoteFieldRecord.Load( ¬eData, PLAYER_1, -150, 350, 350 ); + m_NoteFieldRecord.Load( ¬eData, GAMESTATE->m_pPlayerState[PLAYER_1], -150, 350, 350 ); m_Clipboard.SetNumTracks( m_NoteFieldEdit.GetNumTracks() ); - GAMESTATE->m_PlayerOptions[PLAYER_1].Init(); // don't allow weird options in editor. It doesn't handle reverse well. + GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions.Init(); // don't allow weird options in editor. It doesn't handle reverse well. // Set NoteSkin to note if available. // Change noteskin back to default before loading player. if( NOTESKIN->DoesNoteSkinExist("note") ) - GAMESTATE->m_PlayerOptions[PLAYER_1].m_sNoteSkin = "note"; + GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions.m_sNoteSkin = "note"; GAMESTATE->ResetNoteSkins(); /* XXX: Do we actually have to send real note data here, and to m_NoteFieldRecord? * (We load again on play/record.) */ - m_Player.Load( PLAYER_1, noteData, NULL, NULL, NULL, NULL, NULL, NULL, NULL ); - GAMESTATE->m_PlayerController[PLAYER_1] = PC_HUMAN; + m_Player.Load( GAMESTATE->m_pPlayerState[PLAYER_1], noteData, NULL, NULL, NULL, NULL, NULL, NULL, NULL ); + GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerController = PC_HUMAN; m_Player.SetXY( PLAYER_X, PLAYER_Y ); m_In.Load( THEME->GetPathToB("ScreenEdit in") ); @@ -636,7 +637,7 @@ void ScreenEdit::Update( float fDeltaTime ) else { float fSign = fDelta / fabsf(fDelta); - float fMoveDelta = fSign*fDeltaTime*40 / GAMESTATE->m_CurrentPlayerOptions[PLAYER_1].m_fScrollSpeed; + float fMoveDelta = fSign*fDeltaTime*40 / GAMESTATE->m_pPlayerState[PLAYER_1]->m_CurrentPlayerOptions.m_fScrollSpeed; if( fabsf(fMoveDelta) > fabsf(fDelta) ) fMoveDelta = fDelta; m_fTrailingBeat += fMoveDelta; @@ -884,7 +885,7 @@ void ScreenEdit::InputEdit( const DeviceInput& DeviceI, const InputEventType typ if(lIsHeld) #endif { - float& fScrollSpeed = GAMESTATE->m_PlayerOptions[PLAYER_1].m_fScrollSpeed; + float& fScrollSpeed = GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions.m_fScrollSpeed; float fNewScrollSpeed = fScrollSpeed; if( DeviceI.button == KEY_UP ) @@ -1399,9 +1400,8 @@ void ScreenEdit::InputPlay( const DeviceInput& DeviceI, const InputEventType typ case KEY_F8: { PREFSMAN->m_bAutoPlay = !PREFSMAN->m_bAutoPlay; - FOREACH_PlayerNumber( p ) - if( GAMESTATE->IsHumanPlayer(p) ) - GAMESTATE->m_PlayerController[p] = PREFSMAN->m_bAutoPlay?PC_AUTOPLAY:PC_HUMAN; + FOREACH_HumanPlayer( p ) + GAMESTATE->m_pPlayerState[p]->m_PlayerController = PREFSMAN->m_bAutoPlay?PC_AUTOPLAY:PC_HUMAN; } break; case KEY_F11: @@ -1466,7 +1466,7 @@ void ScreenEdit::TransitionToEdit() /* Stop displaying course attacks, if any. */ GAMESTATE->RemoveAllActiveAttacks(); GAMESTATE->RebuildPlayerOptionsFromActiveAttacks( PLAYER_1 ); - GAMESTATE->m_CurrentPlayerOptions[PLAYER_1] = GAMESTATE->m_PlayerOptions[PLAYER_1]; + GAMESTATE->m_pPlayerState[PLAYER_1]->m_CurrentPlayerOptions = GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions; } void ScreenEdit::TransitionFromRecordToEdit() @@ -1553,7 +1553,7 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM ) break; case SM_BackFromInsertAttackModifiers: { - PlayerOptions poChosen = GAMESTATE->m_PlayerOptions[PLAYER_1]; + PlayerOptions poChosen = GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions; CString sMods = poChosen.GetString(); const int row = BeatToNoteRow( GAMESTATE->m_fSongBeat ); @@ -2095,8 +2095,8 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, int* iAnswers ) SetupCourseAttacks(); - m_Player.Load( PLAYER_1, m_NoteFieldEdit, NULL, NULL, NULL, NULL, NULL, NULL, NULL ); - GAMESTATE->m_PlayerController[PLAYER_1] = PREFSMAN->m_bAutoPlay?PC_AUTOPLAY:PC_HUMAN; + m_Player.Load( GAMESTATE->m_pPlayerState[PLAYER_1], m_NoteFieldEdit, NULL, NULL, NULL, NULL, NULL, NULL, NULL ); + GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerController = PREFSMAN->m_bAutoPlay?PC_AUTOPLAY:PC_HUMAN; m_rectRecordBack.StopTweening(); m_rectRecordBack.BeginTweening( 0.5f ); @@ -2141,7 +2141,7 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, int* iAnswers ) GAMESTATE->ResetNoteSkins(); // initialize m_NoteFieldRecord - m_NoteFieldRecord.Load( &m_NoteFieldEdit, PLAYER_1, -150, 350, 350 ); + m_NoteFieldRecord.Load( &m_NoteFieldEdit, GAMESTATE->m_pPlayerState[PLAYER_1], -150, 350, 350 ); m_NoteFieldRecord.SetNumTracks( m_NoteFieldEdit.GetNumTracks() ); m_rectRecordBack.StopTweening(); @@ -2350,10 +2350,10 @@ void ScreenEdit::SetupCourseAttacks() { /* This is the first beat that can be changed without it being visible. Until * we draw for the first time, any beat can be changed. */ - GAMESTATE->m_fLastDrawnBeat[PLAYER_1] = -100; + GAMESTATE->m_pPlayerState[PLAYER_1]->m_fLastDrawnBeat = -100; // Put course options into effect. - GAMESTATE->m_ModsToApply[PLAYER_1].clear(); + GAMESTATE->m_pPlayerState[PLAYER_1]->m_ModsToApply.clear(); GAMESTATE->RemoveActiveAttacksForPlayer( PLAYER_1 ); diff --git a/stepmania/src/ScreenEnding.cpp b/stepmania/src/ScreenEnding.cpp index 536bd51937..93ac44d2e7 100644 --- a/stepmania/src/ScreenEnding.cpp +++ b/stepmania/src/ScreenEnding.cpp @@ -16,6 +16,7 @@ #include "ScreenManager.h" #include "PrefsManager.h" #include "StageStats.h" +#include "PlayerState.h" #define SCROLL_DELAY THEME->GetMetricF("ScreenEnding","ScrollDelay") @@ -152,11 +153,11 @@ ScreenEnding::ScreenEnding( CString sClassName ) : ScreenAttract( sClassName, fa GAMESTATE->m_pCurSteps[PLAYER_2] = GAMESTATE->m_pCurSong->GetAllSteps()[0]; g_CurStageStats.vpSteps[PLAYER_1].push_back( GAMESTATE->m_pCurSteps[PLAYER_1] ); g_CurStageStats.vpSteps[PLAYER_2].push_back( GAMESTATE->m_pCurSteps[PLAYER_2] ); - GAMESTATE->m_PlayerOptions[PLAYER_1].m_fScrollSpeed = 2; - GAMESTATE->m_PlayerOptions[PLAYER_2].m_fScrollSpeed = 2; + GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions.m_fScrollSpeed = 2; + GAMESTATE->m_pPlayerState[PLAYER_2]->m_PlayerOptions.m_fScrollSpeed = 2; GAMESTATE->m_iCurrentStageIndex = 0; - GAMESTATE->m_PlayerOptions[PLAYER_1].ChooseRandomMofifiers(); - GAMESTATE->m_PlayerOptions[PLAYER_2].ChooseRandomMofifiers(); + GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions.ChooseRandomMofifiers(); + GAMESTATE->m_pPlayerState[PLAYER_2]->m_PlayerOptions.ChooseRandomMofifiers(); for( float f = 0; f < 100.0f; f += 1.0f ) { diff --git a/stepmania/src/ScreenEvaluation.cpp b/stepmania/src/ScreenEvaluation.cpp index 55f2fa066f..04544714fd 100644 --- a/stepmania/src/ScreenEvaluation.cpp +++ b/stepmania/src/ScreenEvaluation.cpp @@ -28,6 +28,7 @@ #include "CryptManager.h" #include "Style.h" #include "MemoryCardManager.h" +#include "PlayerState.h" const int NUM_SCORE_DIGITS = 9; @@ -113,11 +114,11 @@ void ScreenEvaluation::Init() GAMESTATE->m_pCurSteps[PLAYER_2] = GAMESTATE->m_pCurSong->GetAllSteps()[0]; g_CurStageStats.vpSteps[PLAYER_1].push_back( GAMESTATE->m_pCurSteps[PLAYER_1] ); g_CurStageStats.vpSteps[PLAYER_2].push_back( GAMESTATE->m_pCurSteps[PLAYER_2] ); - GAMESTATE->m_PlayerOptions[PLAYER_1].m_fScrollSpeed = 2; - GAMESTATE->m_PlayerOptions[PLAYER_2].m_fScrollSpeed = 2; + GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions.m_fScrollSpeed = 2; + GAMESTATE->m_pPlayerState[PLAYER_2]->m_PlayerOptions.m_fScrollSpeed = 2; GAMESTATE->m_iCurrentStageIndex = 0; - GAMESTATE->m_PlayerOptions[PLAYER_1].ChooseRandomMofifiers(); - GAMESTATE->m_PlayerOptions[PLAYER_2].ChooseRandomMofifiers(); + GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions.ChooseRandomMofifiers(); + GAMESTATE->m_pPlayerState[PLAYER_2]->m_PlayerOptions.ChooseRandomMofifiers(); for( float f = 0; f < 100.0f; f += 1.0f ) { @@ -410,7 +411,7 @@ void ScreenEvaluation::Init() this->AddChild( &m_DifficultyMeter[p] ); m_textPlayerOptions[p].LoadFromFont( THEME->GetPathToF("Common normal") ); - CString sPO = GAMESTATE->m_PlayerOptions[p].GetThemedString(); + CString sPO = GAMESTATE->m_pPlayerState[p]->m_PlayerOptions.GetThemedString(); sPO.Replace( ", ", PLAYER_OPTIONS_SEPARATOR ); m_textPlayerOptions[p].SetName( ssprintf("PlayerOptionsP%d",p+1) ); SET_XY_AND_ON_COMMAND( m_textPlayerOptions[p] ); @@ -930,7 +931,7 @@ void ScreenEvaluation::CommitScores( hs.iScore = stageStats.iScore[p]; hs.fPercentDP = stageStats.GetPercentDancePoints( p ); hs.fSurviveSeconds = stageStats.fAliveSeconds[p]; - hs.sModifiers = GAMESTATE->m_PlayerOptions[p].GetString(); + hs.sModifiers = GAMESTATE->m_pPlayerState[p]->m_PlayerOptions.GetString(); hs.dateTime = DateTime::GetNowDateTime(); hs.sPlayerGuid = PROFILEMAN->IsUsingProfile(p) ? PROFILEMAN->GetProfile(p)->m_sGuid : CString(""); hs.sMachineGuid = PROFILEMAN->GetMachineProfile()->m_sGuid; diff --git a/stepmania/src/ScreenEz2SelectMusic.cpp b/stepmania/src/ScreenEz2SelectMusic.cpp index 55dec8c163..9feefbc73d 100644 --- a/stepmania/src/ScreenEz2SelectMusic.cpp +++ b/stepmania/src/ScreenEz2SelectMusic.cpp @@ -17,6 +17,7 @@ #include "MenuTimer.h" #include "StepsUtil.h" #include "ScreenDimensions.h" +#include "PlayerState.h" #define SCROLLING_LIST_X THEME->GetMetricF("ScreenEz2SelectMusic","ScrollingListX") #define SCROLLING_LIST_Y THEME->GetMetricF("ScreenEz2SelectMusic","ScrollingListY") @@ -309,7 +310,7 @@ void ScreenEz2SelectMusic::Input( const DeviceInput& DeviceI, const InputEventTy void ScreenEz2SelectMusic::UpdateOptions(PlayerNumber pn, int nosound) { - sOptions = GAMESTATE->m_PlayerOptions[pn].GetString(); + sOptions = GAMESTATE->m_pPlayerState[pn]->m_PlayerOptions.GetString(); #ifdef DEBUG m_debugtext.SetText( "DEBUG: " + sOptions ); diff --git a/stepmania/src/ScreenHowToPlay.cpp b/stepmania/src/ScreenHowToPlay.cpp index 0f0b47c301..0791e1dfc9 100644 --- a/stepmania/src/ScreenHowToPlay.cpp +++ b/stepmania/src/ScreenHowToPlay.cpp @@ -13,6 +13,7 @@ #include "GameSoundManager.h" #include "Model.h" #include "ThemeMetric.h" +#include "PlayerState.h" static const ThemeMetric SECONDS_TO_SHOW ("ScreenHowToPlay","SecondsToShow"); static const ThemeMetric STEPFILE ("ScreenHowToPlay","Stepfile"); @@ -147,16 +148,16 @@ ScreenHowToPlay::ScreenHowToPlay( CString sName ) : ScreenAttract( sName ) GAMESTATE->m_pCurSong = &m_Song; GAMESTATE->m_bPastHereWeGo = true; - GAMESTATE->m_PlayerController[PLAYER_1] = PC_AUTOPLAY; + GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerController = PC_AUTOPLAY; m_pPlayer = new Player; - m_pPlayer->Load( PLAYER_1, m_NoteData, m_pLifeMeterBar, NULL, NULL, NULL, NULL, NULL, NULL ); + m_pPlayer->Load( GAMESTATE->m_pPlayerState[PLAYER_1], m_NoteData, m_pLifeMeterBar, NULL, NULL, NULL, NULL, NULL, NULL ); m_pPlayer->SetName( "Player" ); this->AddChild( m_pPlayer ); SET_XY_AND_ON_COMMAND( m_pPlayer ); // Don't show judgement - GAMESTATE->m_PlayerOptions[PLAYER_1].m_fBlind = 1; + GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions.m_fBlind = 1; GAMESTATE->m_MasterPlayerNumber = PLAYER_1; GAMESTATE->m_bDemonstrationOrJukebox = true; } @@ -250,7 +251,7 @@ void ScreenHowToPlay::Update( float fDelta ) // switch the controller to HUMAN. since we aren't taking input, // the steps will always be misses. if(m_iPerfects > m_iNumPerfects) - GAMESTATE->m_PlayerController[PLAYER_1] = PC_HUMAN; + GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerController = PC_HUMAN; if ( m_pmCharacter ) { diff --git a/stepmania/src/ScreenJukebox.cpp b/stepmania/src/ScreenJukebox.cpp index bbb826ecd8..c836265049 100644 --- a/stepmania/src/ScreenJukebox.cpp +++ b/stepmania/src/ScreenJukebox.cpp @@ -14,6 +14,8 @@ #include "UnlockSystem.h" #include "Course.h" #include "ThemeManager.h" +#include "Style.h" +#include "PlayerState.h" // HACK: This belongs in ScreenDemonstration #define DIFFICULTIES_TO_SHOW THEME->GetMetric ("ScreenDemonstration","DifficultiesToShow") @@ -133,10 +135,10 @@ bool ScreenJukebox::PrepareForJukebox( bool bDemonstration ) // always return t /* Lots and lots of arrows. This might even bias to arrows a little * too much. */ - GAMESTATE->m_PlayerOptions[p] = PlayerOptions(); - GAMESTATE->m_PlayerOptions[p].m_fScrollSpeed = .25f; - GAMESTATE->m_PlayerOptions[p].m_fPerspectiveTilt = -1; - GAMESTATE->m_PlayerOptions[p].m_fEffects[ PlayerOptions::EFFECT_MINI ] = 1; + GAMESTATE->m_pPlayerState[p]->m_PlayerOptions = PlayerOptions(); + GAMESTATE->m_pPlayerState[p]->m_PlayerOptions.m_fScrollSpeed = .25f; + GAMESTATE->m_pPlayerState[p]->m_PlayerOptions.m_fPerspectiveTilt = -1; + GAMESTATE->m_pPlayerState[p]->m_PlayerOptions.m_fEffects[ PlayerOptions::EFFECT_MINI ] = 1; } GAMESTATE->m_SongOptions.m_LifeType = SongOptions::LIFE_BATTERY; GAMESTATE->m_SongOptions.m_FailType = SongOptions::FAIL_OFF; @@ -149,9 +151,9 @@ bool ScreenJukebox::PrepareForJukebox( bool bDemonstration ) // always return t if( GAMESTATE->m_bJukeboxUsesModifiers ) { - GAMESTATE->m_PlayerOptions[p].Init(); - GAMESTATE->m_PlayerOptions[p].FromString( PREFSMAN->m_sDefaultModifiers ); - GAMESTATE->m_PlayerOptions[p].ChooseRandomMofifiers(); + GAMESTATE->m_pPlayerState[p]->m_PlayerOptions.Init(); + GAMESTATE->m_pPlayerState[p]->m_PlayerOptions.FromString( PREFSMAN->m_sDefaultModifiers ); + GAMESTATE->m_pPlayerState[p]->m_PlayerOptions.ChooseRandomMofifiers(); } } diff --git a/stepmania/src/ScreenNameEntry.cpp b/stepmania/src/ScreenNameEntry.cpp index 0f79f7a77f..a0c789f1ce 100644 --- a/stepmania/src/ScreenNameEntry.cpp +++ b/stepmania/src/ScreenNameEntry.cpp @@ -18,6 +18,7 @@ #include "StageStats.h" #include "Game.h" #include "ScreenDimensions.h" +#include "PlayerState.h" // @@ -123,7 +124,7 @@ ScreenNameEntry::ScreenNameEntry( CString sClassName ) : Screen( sClassName ) // reset Player and Song Options { FOREACH_PlayerNumber( p ) - GAMESTATE->m_PlayerOptions[p] = PlayerOptions(); + GAMESTATE->m_pPlayerState[p]->m_PlayerOptions = PlayerOptions(); GAMESTATE->m_SongOptions = SongOptions(); } @@ -173,7 +174,7 @@ ScreenNameEntry::ScreenNameEntry( CString sClassName ) : Screen( sClassName ) continue; // skip // remove modifiers that may have been on the last song - GAMESTATE->m_PlayerOptions[p] = PlayerOptions(); + GAMESTATE->m_pPlayerState[p]->m_PlayerOptions = PlayerOptions(); ASSERT( GAMESTATE->IsHumanPlayer(p) ); // they better be enabled if they made a high score! @@ -182,7 +183,7 @@ ScreenNameEntry::ScreenNameEntry( CString sClassName ) : Screen( sClassName ) float fPlayerX = PLAYER_X(p,GAMESTATE->GetCurrentStyle()->m_StyleType); - m_ReceptorArrowRow[p].Load( p, GAMESTATE->m_PlayerOptions[p].m_sNoteSkin, 0 ); + m_ReceptorArrowRow[p].Load( GAMESTATE->m_pPlayerState[p], GAMESTATE->m_pPlayerState[p]->m_PlayerOptions.m_sNoteSkin, 0 ); m_ReceptorArrowRow[p].SetX( fPlayerX ); m_ReceptorArrowRow[p].SetY( SCREEN_TOP + 100 ); this->AddChild( &m_ReceptorArrowRow[p] ); diff --git a/stepmania/src/ScreenPlayerOptions.cpp b/stepmania/src/ScreenPlayerOptions.cpp index 51d0cf4aa9..1606344526 100644 --- a/stepmania/src/ScreenPlayerOptions.cpp +++ b/stepmania/src/ScreenPlayerOptions.cpp @@ -11,6 +11,7 @@ #include "CodeDetector.h" #include "ScreenDimensions.h" #include "Style.h" +#include "PlayerState.h" #define PREV_SCREEN THEME->GetMetric ("ScreenPlayerOptions","PrevScreen") @@ -123,8 +124,8 @@ void ScreenPlayerOptions::Input( const DeviceInput& DeviceI, const InputEventTyp SOUND->PlayOnce( THEME->GetPathToS("ScreenPlayerOptions cancel all") ); // apply the game default mods, but not the Profile saved mods - GAMESTATE->m_PlayerOptions[pn].Init(); - GAMESTATE->m_PlayerOptions[pn].FromString( PREFSMAN->m_sDefaultModifiers ); + GAMESTATE->m_pPlayerState[pn]->m_PlayerOptions.Init(); + GAMESTATE->m_pPlayerState[pn]->m_PlayerOptions.FromString( PREFSMAN->m_sDefaultModifiers ); UtilCommand( m_sprCancelAll[pn], m_sName, "Show" ); @@ -176,7 +177,7 @@ void ScreenPlayerOptions::UpdateDisqualified() FOREACH_PlayerNumber( p ) { - po[p] = GAMESTATE->m_PlayerOptions[p]; + po[p] = GAMESTATE->m_pPlayerState[p]->m_PlayerOptions; } // export the currently selection options, which will fill GAMESTATE->m_PlayerOptions @@ -189,7 +190,7 @@ void ScreenPlayerOptions::UpdateDisqualified() m_sprDisqualify[p]->SetHidden( !bIsHandicap ); // restore previous player options in case the user escapes back after this - GAMESTATE->m_PlayerOptions[p] = po[p]; + GAMESTATE->m_pPlayerState[p]->m_PlayerOptions = po[p]; } } diff --git a/stepmania/src/ScreenSelectMusic.cpp b/stepmania/src/ScreenSelectMusic.cpp index 588d4ca708..1ba78d668e 100644 --- a/stepmania/src/ScreenSelectMusic.cpp +++ b/stepmania/src/ScreenSelectMusic.cpp @@ -24,6 +24,7 @@ #include "StepsUtil.h" #include "Foreach.h" #include "Style.h" +#include "PlayerState.h" const int NUM_SCORE_DIGITS = 9; @@ -1727,7 +1728,7 @@ void ScreenSelectMusic::UpdateOptionsDisplays() { m_OptionIconRow[p].Refresh(); - CString s = GAMESTATE->m_PlayerOptions[p].GetString(); + CString s = GAMESTATE->m_pPlayerState[p]->m_PlayerOptions.GetString(); s.Replace( ", ", "\n" ); // m_textPlayerOptions[p].SetText( s ); } diff --git a/stepmania/src/ScreenTitleMenu.cpp b/stepmania/src/ScreenTitleMenu.cpp index 15e29dceb2..bedaf6f5d0 100644 --- a/stepmania/src/ScreenTitleMenu.cpp +++ b/stepmania/src/ScreenTitleMenu.cpp @@ -23,6 +23,7 @@ #include "CommonMetrics.h" #include "Game.h" #include "ScreenOptionsMasterPrefs.h" +#include "PlayerState.h" #define LOGO_ON_COMMAND THEME->GetMetricA("ScreenTitleMenu","LogoOnCommand") @@ -362,7 +363,7 @@ void ScreenTitleMenu::HandleScreenMessage( const ScreenMessage SM ) { // apply default options FOREACH_PlayerNumber( p ) - GAMESTATE->m_PlayerOptions[p].FromString( PREFSMAN->m_sDefaultModifiers ); + GAMESTATE->m_pPlayerState[p]->m_PlayerOptions.FromString( PREFSMAN->m_sDefaultModifiers ); GAMESTATE->m_SongOptions.FromString( PREFSMAN->m_sDefaultModifiers ); } m_aGameCommands[m_Choice].ApplyToAllPlayers(); diff --git a/stepmania/src/StepMania.dsp b/stepmania/src/StepMania.dsp index 169b9e4363..6944d38a49 100644 --- a/stepmania/src/StepMania.dsp +++ b/stepmania/src/StepMania.dsp @@ -62,7 +62,7 @@ IntDir=.\../Debug6 TargetDir=\stepmania\stepmania\Program TargetName=StepMania-debug SOURCE="$(InputPath)" -PreLink_Cmds=archutils\Win32\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\ +PreLink_Cmds=archutils\Win32\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\ PostBuild_Cmds=archutils\Win32\mapconv $(IntDir)\$(TargetName).map $(TargetDir)\StepMania.vdi # End Special Build Tool @@ -99,7 +99,7 @@ IntDir=.\../Release6 TargetDir=\stepmania\stepmania\Program TargetName=StepMania SOURCE="$(InputPath)" -PreLink_Cmds=archutils\Win32\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\ +PreLink_Cmds=archutils\Win32\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\ PostBuild_Cmds=archutils\Win32\mapconv $(IntDir)\$(TargetName).map $(TargetDir)\StepMania.vdi # End Special Build Tool @@ -964,6 +964,14 @@ SOURCE=.\PlayerOptions.h # End Source File # Begin Source File +SOURCE=.\PlayerState.cpp +# End Source File +# Begin Source File + +SOURCE=.\PlayerState.h +# End Source File +# Begin Source File + SOURCE=.\Preference.cpp # End Source File # Begin Source File diff --git a/stepmania/src/StepMania.vcproj b/stepmania/src/StepMania.vcproj index 0ad59ff49c..cf9830d27c 100644 --- a/stepmania/src/StepMania.vcproj +++ b/stepmania/src/StepMania.vcproj @@ -797,6 +797,12 @@ cl /Zl /nologo /c verstub.cpp /Fo"$(IntDir)"\ + + + +