source-engine/game/server/tf2/basecombatcharacter_tf2.cpp

250 lines
6.4 KiB
C++
Raw Normal View History

2020-04-22 16:56:21 +00:00
//========= 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;
}
}