modified haste mechanics
This commit is contained in:
@@ -795,6 +795,9 @@ void GameState::ResetStageStatistics()
|
|||||||
FOREACH_PlayerNumber( p )
|
FOREACH_PlayerNumber( p )
|
||||||
m_pPlayerState[p]->RemoveAllInventory();
|
m_pPlayerState[p]->RemoveAllInventory();
|
||||||
m_fOpponentHealthPercent = 1;
|
m_fOpponentHealthPercent = 1;
|
||||||
|
m_fHasteRate = 0;
|
||||||
|
m_fLastHasteUpdateMusicSeconds = 0;
|
||||||
|
m_fAccumulatedHasteSeconds = 0;
|
||||||
m_fTugLifePercentP1 = 0.5f;
|
m_fTugLifePercentP1 = 0.5f;
|
||||||
FOREACH_PlayerNumber( p )
|
FOREACH_PlayerNumber( p )
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -193,6 +193,13 @@ public:
|
|||||||
bool AllAreInDangerOrWorse() const;
|
bool AllAreInDangerOrWorse() const;
|
||||||
bool OneIsHot() const;
|
bool OneIsHot() const;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Haste
|
||||||
|
//
|
||||||
|
float m_fHasteRate; // [-1,+1]; 0 = normal speed
|
||||||
|
float m_fLastHasteUpdateMusicSeconds;
|
||||||
|
float m_fAccumulatedHasteSeconds;
|
||||||
|
|
||||||
// used in PLAY_MODE_BATTLE
|
// used in PLAY_MODE_BATTLE
|
||||||
float m_fOpponentHealthPercent;
|
float m_fOpponentHealthPercent;
|
||||||
|
|
||||||
|
|||||||
@@ -1091,6 +1091,19 @@ void Player::ChangeLife( TapNoteScore tns )
|
|||||||
m_pCombinedLifeMeter->ChangeLife( pn, tns );
|
m_pCombinedLifeMeter->ChangeLife( pn, tns );
|
||||||
|
|
||||||
ChangeLifeRecord();
|
ChangeLifeRecord();
|
||||||
|
|
||||||
|
switch( tns )
|
||||||
|
{
|
||||||
|
case TNS_None:
|
||||||
|
case TNS_Miss:
|
||||||
|
case TNS_CheckpointMiss:
|
||||||
|
case TNS_HitMine:
|
||||||
|
++m_pPlayerState->m_iTapsMissedSinceLastHasteUpdate;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
++m_pPlayerState->m_iTapsHitSinceLastHasteUpdate;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::ChangeLife( HoldNoteScore hns, TapNoteScore tns )
|
void Player::ChangeLife( HoldNoteScore hns, TapNoteScore tns )
|
||||||
|
|||||||
@@ -33,6 +33,9 @@ void PlayerState::Reset()
|
|||||||
m_ActiveAttacks.clear();
|
m_ActiveAttacks.clear();
|
||||||
m_ModsToApply.clear();
|
m_ModsToApply.clear();
|
||||||
|
|
||||||
|
m_iTapsHitSinceLastHasteUpdate = 0;
|
||||||
|
m_iTapsMissedSinceLastHasteUpdate = 0;
|
||||||
|
|
||||||
m_fSuperMeter = 0; // between 0 and NUM_ATTACK_LEVELS
|
m_fSuperMeter = 0; // between 0 and NUM_ATTACK_LEVELS
|
||||||
m_fSuperMeterGrowthScale = 1;
|
m_fSuperMeterGrowthScale = 1;
|
||||||
|
|
||||||
|
|||||||
@@ -68,6 +68,12 @@ public:
|
|||||||
AttackArray m_ActiveAttacks;
|
AttackArray m_ActiveAttacks;
|
||||||
vector<Attack> m_ModsToApply;
|
vector<Attack> m_ModsToApply;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Haste
|
||||||
|
//
|
||||||
|
int m_iTapsHitSinceLastHasteUpdate;
|
||||||
|
int m_iTapsMissedSinceLastHasteUpdate;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Used in Rave
|
// Used in Rave
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1613,7 +1613,7 @@ void ScreenGameplay::Update( float fDeltaTime )
|
|||||||
if( GAMESTATE->m_SongOptions.GetCurrent().m_fHaste != 0.0f )
|
if( GAMESTATE->m_SongOptions.GetCurrent().m_fHaste != 0.0f )
|
||||||
{
|
{
|
||||||
float fHasteRate = GetHasteRate();
|
float fHasteRate = GetHasteRate();
|
||||||
STATSMAN->m_CurStageStats.m_fAccumulatedHaste += (fUnscaledDeltaTime * fHasteRate) - fUnscaledDeltaTime;
|
GAMESTATE->m_fAccumulatedHasteSeconds += (fUnscaledDeltaTime * fHasteRate) - fUnscaledDeltaTime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1775,33 +1775,57 @@ void ScreenGameplay::Update( float fDeltaTime )
|
|||||||
|
|
||||||
float ScreenGameplay::GetHasteRate()
|
float ScreenGameplay::GetHasteRate()
|
||||||
{
|
{
|
||||||
float fLife = 0;
|
if( GAMESTATE->m_fMusicSeconds < GAMESTATE->m_fLastHasteUpdateMusicSeconds || // new song
|
||||||
|
GAMESTATE->m_fMusicSeconds > GAMESTATE->m_fLastHasteUpdateMusicSeconds + 4 )
|
||||||
|
{
|
||||||
|
bool bAnyPlayerHitAllNotes = false;
|
||||||
|
FOREACH_EnabledPlayerInfo( m_vPlayerInfo, pi )
|
||||||
|
{
|
||||||
|
if( !GAMESTATE->IsHumanPlayer(pi->m_pn) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
PlayerState *pPS = pi->GetPlayerState();
|
||||||
|
if( pPS->m_iTapsHitSinceLastHasteUpdate > 0 &&
|
||||||
|
pPS->m_iTapsMissedSinceLastHasteUpdate == 0 )
|
||||||
|
bAnyPlayerHitAllNotes = true;
|
||||||
|
|
||||||
|
pPS->m_iTapsHitSinceLastHasteUpdate = 0;
|
||||||
|
pPS->m_iTapsMissedSinceLastHasteUpdate = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( bAnyPlayerHitAllNotes )
|
||||||
|
GAMESTATE->m_fHasteRate += 0.05f;
|
||||||
|
CLAMP( GAMESTATE->m_fHasteRate, -1.0f, +2.0f );
|
||||||
|
|
||||||
|
GAMESTATE->m_fLastHasteUpdateMusicSeconds = GAMESTATE->m_fMusicSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the life meter is less than half full, push the haste rate down to let
|
||||||
|
* the player use his accumulated haste time. */
|
||||||
|
float fMaxLife = 0;
|
||||||
FOREACH_EnabledPlayerInfo( m_vPlayerInfo, pi )
|
FOREACH_EnabledPlayerInfo( m_vPlayerInfo, pi )
|
||||||
{
|
{
|
||||||
if( !GAMESTATE->IsHumanPlayer(pi->m_pn) )
|
if( !GAMESTATE->IsHumanPlayer(pi->m_pn) )
|
||||||
continue;
|
continue;
|
||||||
fLife = max( fLife, pi->m_pLifeMeter->GetLife() );
|
fMaxLife = max( fMaxLife, pi->m_pLifeMeter->GetLife() );
|
||||||
}
|
}
|
||||||
|
if( fMaxLife < 0.5f )
|
||||||
|
GAMESTATE->m_fHasteRate = SCALE( fMaxLife, 0.0f, 0.5f, -1.0f, 0.0f );
|
||||||
|
|
||||||
/* Scale the music nonlinearly. Stick at 1x up to 0.5, so we start at 1x
|
|
||||||
* if the life meter defaults to 0.5. Increase gradually up to 0.9.
|
|
||||||
* Accelerate sharply above 0.9. */
|
|
||||||
float fSpeed = 1.0f;
|
float fSpeed = 1.0f;
|
||||||
if( fLife < 0.50f )
|
if( GAMESTATE->m_fHasteRate < 0 )
|
||||||
fSpeed = SCALE( fLife, 0.0f, 0.50f, 0.5f, 1.0f );
|
fSpeed = SCALE( GAMESTATE->m_fHasteRate, -1.0f, 0.0f, 0.5f, 1.0f );
|
||||||
else if( fLife > 0.5f && fLife < 0.9f )
|
else
|
||||||
fSpeed = SCALE( fLife, 0.5f, 0.9f, 1.0f, 1.25f );
|
fSpeed = SCALE( GAMESTATE->m_fHasteRate, 0.0f, 1.0f, 1.0f, 1.6f );
|
||||||
else if( fLife >= 0.9f )
|
|
||||||
fSpeed = SCALE( fLife, 0.9f, 1.0f, 1.25f, 2.0f );
|
|
||||||
fSpeed *= GAMESTATE->m_SongOptions.GetCurrent().m_fHaste;
|
fSpeed *= GAMESTATE->m_SongOptions.GetCurrent().m_fHaste;
|
||||||
|
|
||||||
if( STATSMAN->m_CurStageStats.m_fAccumulatedHaste <= 1 )
|
if( GAMESTATE->m_fAccumulatedHasteSeconds <= 1 )
|
||||||
{
|
{
|
||||||
/* Only allow slowing down the song while the players have accumulated
|
/* Only allow slowing down the song while the players have accumulated
|
||||||
* haste. This prevents dragging on the song by keeping the life meter
|
* haste. This prevents dragging on the song by keeping the life meter
|
||||||
* nearly empty. */
|
* nearly empty. */
|
||||||
float fClamped = max( 1.0f, fSpeed );
|
float fClamped = max( 1.0f, fSpeed );
|
||||||
fSpeed = lerp( STATSMAN->m_CurStageStats.m_fAccumulatedHaste, fClamped, fSpeed );
|
fSpeed = lerp( GAMESTATE->m_fAccumulatedHasteSeconds, fClamped, fSpeed );
|
||||||
}
|
}
|
||||||
return fSpeed;
|
return fSpeed;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ StageStats::StageStats()
|
|||||||
m_fGameplaySeconds = 0;
|
m_fGameplaySeconds = 0;
|
||||||
m_fStepsSeconds = 0;
|
m_fStepsSeconds = 0;
|
||||||
m_fMusicRate = 1;
|
m_fMusicRate = 1;
|
||||||
m_fAccumulatedHaste = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void StageStats::Init()
|
void StageStats::Init()
|
||||||
|
|||||||
@@ -42,8 +42,6 @@ public:
|
|||||||
float m_fStepsSeconds; // this is <= fGameplaySeconds unless the song has steps past the end
|
float m_fStepsSeconds; // this is <= fGameplaySeconds unless the song has steps past the end
|
||||||
float m_fMusicRate;
|
float m_fMusicRate;
|
||||||
|
|
||||||
float m_fAccumulatedHaste;
|
|
||||||
|
|
||||||
// Total number of seconds between first beat and last beat for every song.
|
// Total number of seconds between first beat and last beat for every song.
|
||||||
float GetTotalPossibleStepsSeconds() const;
|
float GetTotalPossibleStepsSeconds() const;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user