summaryrefslogtreecommitdiff
path: root/game/server/tf2/basecombatcharacter_tf2.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'game/server/tf2/basecombatcharacter_tf2.cpp')
-rw-r--r--game/server/tf2/basecombatcharacter_tf2.cpp249
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;
+ }
+}
+