source-engine/game/server/tf2/tf_player_death.cpp
FluorescentCIAAfricanAmerican 3bf9df6b27 1
2020-04-22 12:56:21 -04:00

231 lines
5.9 KiB
C++

//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: CBaseTFPlayer functions dealing with death and reinforcement
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "player.h"
#include "tf_player.h"
#include "gamerules.h"
#include "basecombatweapon.h"
#include "EntityList.h"
#include "tf_shareddefs.h"
#include "tf_team.h"
#include "baseviewmodel.h"
#include "tf_class_infiltrator.h"
#include "in_buttons.h"
#include "globals.h"
int g_iNumberOfCorpses;
//-----------------------------------------------------------------------------
// Purpose: The player was just killed
//-----------------------------------------------------------------------------
void CBaseTFPlayer::Event_Killed( const CTakeDamageInfo &info )
{
// TODO don't use temp entities to transmit messages
CPASFilter filter( GetLocalOrigin() );
te->KillPlayerAttachments( filter, 0.0, entindex() );
// Remove the player from any vehicle they're in
if ( IsInAVehicle() )
{
LeaveVehicle();
}
// Holster weapon immediately, to allow it to cleanup
if (GetActiveWeapon())
{
GetActiveWeapon()->Holster( );
}
// Stop attaching sappers
if ( IsAttachingSapper() )
{
StopAttaching();
}
// stop them touching anything
AddFlag( FL_DONTTOUCH );
g_pGameRules->PlayerKilled( this, info );
ClearUseEntity();
// If I'm ragdolling due to a knockdown, don't play any animations
if ( m_hRagdollShadow == NULL )
{
if ( PlayerClass() != TFCLASS_INFILTRATOR )
{
// Calculate death force
Vector forceVector = CalcDamageForceVector( info );
BecomeRagdollOnClient( forceVector );
}
else
{
SetAnimation( PLAYER_DIE );
}
}
DeathSound( info );
SetViewOffset( VEC_DEAD_VIEWHEIGHT_SCALED( this ) );
m_lifeState = LIFE_DYING;
pl.deadflag = true;
// Enter dying state
AddSolidFlags( FSOLID_NOT_SOLID );
SetMoveType( MOVETYPE_NONE );
QAngle angles = GetLocalAngles();
angles.x = angles.z = 0;
SetLocalAngles( angles );
m_takedamage = DAMAGE_NO;
// clear out the suit message cache so we don't keep chattering
SetSuitUpdate(NULL, false, 0);
// reset FOV
SetFOV( this, 0 );
// Setup for respawn
m_flTimeOfDeath = gpGlobals->curtime;
SetThink(TFPlayerDeathThink);
SetNextThink( gpGlobals->curtime + 0.1f );
SetPowerup(POWERUP_EMP,false);
// Tell the playerclass that the player died
if ( GetPlayerClass() )
{
GetPlayerClass()->PlayerDied( info.GetAttacker() );
}
// Tell the attacker's playerclass that he killed someone
if ( info.GetAttacker() && info.GetAttacker()->IsPlayer() )
{
CBaseTFPlayer *pPlayerAttacker = (CBaseTFPlayer*)info.GetAttacker();
pPlayerAttacker->KilledPlayer( this );
}
DropAllResourceChunks();
// Tell all teams to update their orders
COrderEvent_PlayerKilled order( this );
GlobalOrderEvent( &order );
}
//-----------------------------------------------------------------------------
// Purpose: Think function for dead/dying players.
// Play their death animation, then set up for reinforcement.
//-----------------------------------------------------------------------------
void CBaseTFPlayer::TFPlayerDeathThink(void)
{
float flForward;
SetNextThink( gpGlobals->curtime + 0.1f );
if ( GetFlags() & FL_ONGROUND )
{
flForward = GetAbsVelocity().Length() - 20;
if (flForward <= 0)
{
SetAbsVelocity( vec3_origin );
}
else
{
Vector vecNewVelocity = GetAbsVelocity();
VectorNormalize( vecNewVelocity );
vecNewVelocity *= flForward;
SetAbsVelocity( vecNewVelocity );
}
}
StudioFrameAdvance();
if (GetModelIndex() && (!IsSequenceFinished()) && (m_lifeState == LIFE_DYING))
{
m_iRespawnFrames++;
if ( m_iRespawnFrames < 60 ) // animations should be no longer than this
return;
}
// Start looping dying state
SetAnimation( PLAYER_DIE );
// ROBIN: Everyone respawns immediately now. Maps will define respawns in the future.
if ( (gpGlobals->curtime - m_flTimeOfDeath) < 3 )
return;
m_lifeState = LIFE_RESPAWNABLE;
// Respawn on button press, but not if they're checking the scores
// Also respawn if they're not looking at scores, and they've been dead for over 5 seconds
bool bButtonDown = (m_nButtons & ~IN_SCORE) > 0;
if ( (bButtonDown || (gpGlobals->curtime - m_flTimeOfDeath) > 5 ) )
{
PlayerRespawn();
}
/*
// Aliens become respawnable immediately, because they're waiting for a reinforcement wave.
// Humans have to wait a short time.
if ( (GetTeamNumber() == TEAM_HUMANS) && (gpGlobals->curtime - m_flTimeOfDeath) < 3 )
return;
if ( (GetTeamNumber() == TEAM_ALIENS) && (gpGlobals->curtime - m_flTimeOfDeath) < 1 )
return;
// Humans can respawn, Aliens can't (reinforcement wave for their kind)
// Aliens stop thinking now and wait for the reinforcement wave
if ( GetTeamNumber() == TEAM_ALIENS )
{
m_lifeState = LIFE_RESPAWNABLE;
SetThink( NULL );
}
else
{
m_lifeState = LIFE_RESPAWNABLE;
// Respawn on button press
if ( m_nButtons & ~IN_SCORE )
{
PlayerRespawn();
}
}
*/
}
//-----------------------------------------------------------------------------
// Purpose: Return true if this player is ready to reinforce
//-----------------------------------------------------------------------------
bool CBaseTFPlayer::IsReadyToReinforce( void )
{
// Only Aliens reinforce in waves, humans respawn normally
if ( (GetTeamNumber() == TEAM_ALIENS) && (m_lifeState == LIFE_RESPAWNABLE) )
return true;
return false;
}
//-----------------------------------------------------------------------------
// Purpose: Bring the player back to life in a reinforcement wave
//-----------------------------------------------------------------------------
void CBaseTFPlayer::Reinforce( void )
{
// Tell all teams to update their orders
COrderEvent_PlayerRespawned order( this );
GlobalOrderEvent( &order );
StopAnimation();
IncrementInterpolationFrame();
m_flPlaybackRate = 0.0;
PlayerRespawn();
}