diff options
Diffstat (limited to 'game/server/tf2/basecombatcharacter_tf2.cpp')
| -rw-r--r-- | game/server/tf2/basecombatcharacter_tf2.cpp | 249 |
1 files changed, 249 insertions, 0 deletions
diff --git a/game/server/tf2/basecombatcharacter_tf2.cpp b/game/server/tf2/basecombatcharacter_tf2.cpp new file mode 100644 index 0000000..453856a --- /dev/null +++ b/game/server/tf2/basecombatcharacter_tf2.cpp @@ -0,0 +1,249 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: TF2 specific CBaseCombatCharacter code. +// +//=============================================================================// +#include "cbase.h" +#include "basecombatcharacter.h" +#include "engine/IEngineSound.h" +#include "tf_player.h" +#include "tf_stats.h" + +extern char *g_pszEMPPulseStart; + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CBaseCombatCharacter::HasPowerup( int iPowerup ) +{ + Assert( iPowerup >= 0 && iPowerup < MAX_POWERUPS ); + return ( m_iPowerups & (1 << iPowerup) ) != 0; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CBaseCombatCharacter::CanPowerupEver( int iPowerup ) +{ + Assert( iPowerup >= 0 && iPowerup < MAX_POWERUPS ); + + // Only objects use power + if ( iPowerup == POWERUP_POWER ) + return false; + + // Accept everything else + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CBaseCombatCharacter::CanPowerupNow( int iPowerup ) +{ + Assert( iPowerup >= 0 && iPowerup < MAX_POWERUPS ); + + if ( !CanPowerupEver(iPowerup) ) + return false; + + switch( iPowerup ) + { + case POWERUP_BOOST: + { + // Am I taking EMP damage, or is a technician trying to drain me? + if ( HasPowerup( POWERUP_EMP ) || ( (m_flPowerupAttemptTimes[POWERUP_EMP] + 0.5) > gpGlobals->curtime ) ) + { + // Reduce EMP time + m_flPowerupEndTimes[POWERUP_EMP] -= 0.05; + + // Don't apply any boost effects + return false; + } + } + break; + + case POWERUP_EMP: + { + // Was I just boosted? If so, I don't take EMP damage for a bit + if ( (m_flPowerupAttemptTimes[POWERUP_BOOST] + 0.5) > gpGlobals->curtime ) + return false; + } + break; + + default: + break; + } + + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CBaseCombatCharacter::SetPowerup( int iPowerup, bool bState, float flTime, float flAmount, CBaseEntity *pAttacker, CDamageModifier *pDamageModifier ) +{ + Assert( iPowerup >= 0 && iPowerup < MAX_POWERUPS ); + + // Some powerups trigger their on state continuously, as opposed to turning it on for some time. + bool bTriggerStart = ( bState && !HasPowerup( iPowerup ) ); + if ( bState && iPowerup == POWERUP_BOOST ) + { + // Health boost always triggers + bTriggerStart = true; + } + + bool bHadPowerup = false; + if ( HasPowerup( iPowerup ) && !bState ) + { + bHadPowerup = true; + } + + if ( bState ) + { + m_iPowerups |= (1 << iPowerup); + } + else + { + m_iPowerups &= ~(1 << iPowerup); + } + + // Fire start/end triggers + if ( bTriggerStart ) + { + PowerupStart( iPowerup, flAmount, pAttacker, pDamageModifier ); + } + else if ( bHadPowerup ) + { + PowerupEnd( iPowerup ); + } + + // If we've got an active powerup, keep thinking + if ( m_iPowerups ) + { + SetContextThink( PowerupThink, gpGlobals->curtime + 0.1, POWERUP_THINK_CONTEXT ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CBaseCombatCharacter::PowerupThink( void ) +{ + // If we don't have any powerups, stop thinking + if ( !m_iPowerups ) + return; + + // Check all the powerups + for ( int i = 0; i < MAX_POWERUPS; i++ ) + { + // Don't check power, because it never runs out naturally + if ( i == POWERUP_POWER ) + continue; + + if ( m_iPowerups & (1 << i) ) + { + // Should it finish now? + if ( m_flPowerupEndTimes[i] < gpGlobals->curtime ) + { + SetPowerup( i, false ); + } + } + } + + SetNextThink( gpGlobals->curtime + 0.1, POWERUP_THINK_CONTEXT ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CBaseCombatCharacter::AttemptToPowerup( int iPowerup, float flTime, float flAmount, CBaseEntity *pAttacker, CDamageModifier *pDamageModifier ) +{ + Assert( iPowerup >= 0 && iPowerup < MAX_POWERUPS ); + + // Ignore it if I'm dead + if ( !IsAlive() ) + return false; + + m_flPowerupAttemptTimes[iPowerup] = gpGlobals->curtime; + + // If we can't be powerup this type, abort + if ( !CanPowerupNow( iPowerup ) ) + return false; + + // Get the correct duration + flTime = PowerupDuration( iPowerup, flTime ); + m_flPowerupEndTimes[iPowerup] = MAX( m_flPowerupEndTimes[iPowerup], gpGlobals->curtime + flTime ); + + // Turn it on + SetPowerup( iPowerup, true, flTime, flAmount, pAttacker, pDamageModifier ); + + // Add the damage modifier to the player + if ( pDamageModifier ) + { + pDamageModifier->AddModifierToEntity( this ); + } + + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: Powerup has just started +//----------------------------------------------------------------------------- +void CBaseCombatCharacter::PowerupStart( int iPowerup, float flAmount, CBaseEntity *pAttacker, CDamageModifier *pDamageModifier ) +{ + Assert( iPowerup >= 0 && iPowerup < MAX_POWERUPS ); + + switch( iPowerup ) + { + case POWERUP_BOOST: + { + // Players can be boosted over their max + int iMaxBoostedHealth; + if ( IsPlayer() ) + { + iMaxBoostedHealth = GetMaxHealth() + GetMaxHealth() / 2; + } + else + { + iMaxBoostedHealth = GetMaxHealth(); + } + + // Can we boost health further? + if ( GetHealth() < iMaxBoostedHealth ) + { + int maxHealthToAdd = iMaxBoostedHealth - GetHealth(); + + // It uses floating point in here so it doesn't lose the fractional healing part on small frame times. + float flHealthToAdd = flAmount + m_flFractionalBoost; + int nHealthToAdd = (int)flHealthToAdd; + m_flFractionalBoost = flHealthToAdd - nHealthToAdd; + if ( nHealthToAdd ) + { + int nHealthAdded = MIN( nHealthToAdd, maxHealthToAdd ); + if ( IsPlayer() ) + { + ((CBaseTFPlayer*)this)->TakeHealthBoost( nHealthAdded, GetMaxHealth(), 25 ); + } + else + { + TakeHealth( nHealthAdded, DMG_GENERIC ); + } + + TFStats()->IncrementPlayerStat( pAttacker, TF_PLAYER_STAT_HEALTH_GIVEN, nHealthAdded ); + } + } + } + break; + + case POWERUP_EMP: + { + // EMP removes adrenalin rush + SetPowerup( POWERUP_RUSH, false ); + } + break; + + default: + break; + } +} + |