You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
263 lines
7.2 KiB
263 lines
7.2 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
// $NoKeywords: $ |
|
//=============================================================================// |
|
|
|
#include "cbase.h" |
|
#include "tempent.h" |
|
#include "c_tf_passtime_logic.h" |
|
#include "tf_hud_passtime_reticle.h" |
|
#include "passtime_convars.h" |
|
#include "passtime_game_events.h" |
|
#include "tf_shareddefs.h" |
|
#include "tf_classdata.h" |
|
#include "c_tf_player.h" |
|
#include "c_func_passtime_goal.h" |
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include "tier0/memdbgon.h" |
|
|
|
void C_TFPasstimeLogic::PostDataUpdate( DataUpdateType_t updateType ) |
|
{ |
|
BaseClass::PostDataUpdate( updateType ); |
|
|
|
if ( updateType == DATA_UPDATE_CREATED ) |
|
{ |
|
SetNextClientThink( CLIENT_THINK_ALWAYS ); |
|
m_pBallReticle = new C_PasstimeBallReticle(); |
|
m_pPassReticle = new C_PasstimePassReticle(); |
|
for( auto *pGoal : C_FuncPasstimeGoal::GetAutoList() ) |
|
{ |
|
m_pGoalReticles.AddToTail( new C_PasstimeGoalReticle( |
|
static_cast<C_FuncPasstimeGoal*>( pGoal ) ) ); |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
C_TFPasstimeLogic* g_pPasstimeLogic; |
|
extern ConVar hud_fastswitch; |
|
|
|
//----------------------------------------------------------------------------- |
|
IMPLEMENT_CLIENTCLASS_DT( C_TFPasstimeLogic, DT_TFPasstimeLogic, CTFPasstimeLogic ) |
|
RecvPropEHandle( RECVINFO( m_hBall ) ), |
|
RecvPropArray( RecvPropVector( RECVINFO( m_trackPoints[0] ) ), m_trackPoints ), |
|
RecvPropInt( RECVINFO( m_iNumSections ) ), |
|
RecvPropInt( RECVINFO( m_iCurrentSection ) ), |
|
RecvPropFloat( RECVINFO( m_flMaxPassRange ) ), |
|
RecvPropInt( RECVINFO( m_iBallPower ), 8 ), |
|
RecvPropFloat( RECVINFO( m_flPackSpeed ) ), |
|
RecvPropArray3( RECVINFO_ARRAY( m_bPlayerIsPackMember ), RecvPropInt( RECVINFO( m_bPlayerIsPackMember[0] ) ) ), |
|
END_RECV_TABLE() |
|
|
|
LINK_ENTITY_TO_CLASS( passtime_logic, C_TFPasstimeLogic ); |
|
|
|
//----------------------------------------------------------------------------- |
|
C_TFPasstimeLogic::C_TFPasstimeLogic() |
|
{ |
|
m_pBallReticle = nullptr; |
|
m_pPassReticle = nullptr; |
|
memset( m_apPackBeams, 0, sizeof( m_apPackBeams ) ); |
|
memset( m_bPlayerIsPackMember, 0, sizeof( m_bPlayerIsPackMember ) ); |
|
for( int i = 0; i < m_trackPoints.Count(); ++i ) |
|
{ |
|
m_trackPoints.GetForModify(i).Zero(); |
|
} |
|
|
|
g_pPasstimeLogic = this; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
C_TFPasstimeLogic::~C_TFPasstimeLogic() |
|
{ |
|
delete m_pBallReticle; |
|
m_pGoalReticles.PurgeAndDeleteElements(); |
|
delete m_pPassReticle; |
|
|
|
// Don't set g_pPasstimeLogic to null here because sometimes this destructor |
|
// happens after the contructor of the new object |
|
// FIXME: what's the right way to do this? |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void C_TFPasstimeLogic::Spawn() |
|
{ |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void C_TFPasstimeLogic::ClientThink() |
|
{ |
|
BaseClass::ClientThink(); |
|
|
|
SetNextClientThink( CLIENT_THINK_ALWAYS ); |
|
m_pBallReticle->OnClientThink(); |
|
for ( auto *pGoal : m_pGoalReticles ) |
|
{ |
|
pGoal->OnClientThink(); |
|
} |
|
m_pPassReticle->OnClientThink(); |
|
UpdateBeams(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void C_TFPasstimeLogic::DestroyBeams( C_PasstimeBall *pBall ) |
|
{ |
|
for ( CNewParticleEffect *pBeam : m_apPackBeams ) |
|
{ |
|
if ( pBeam ) |
|
{ |
|
pBall->ParticleProp()->StopEmission( pBeam ); |
|
} |
|
} |
|
memset( m_apPackBeams, 0, sizeof( m_apPackBeams ) ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void C_TFPasstimeLogic::DestroyBeam( int i, C_PasstimeBall *pBall ) |
|
{ |
|
CNewParticleEffect *pBeam = m_apPackBeams[i]; |
|
if ( pBeam ) |
|
{ |
|
pBall->ParticleProp()->StopEmissionAndDestroyImmediately( pBeam ); |
|
m_apPackBeams[i] = nullptr; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void C_TFPasstimeLogic::UpdateBeams() |
|
{ |
|
C_PasstimeBall *pBall = GetBall(); |
|
if ( !pBall ) |
|
{ |
|
return; |
|
} |
|
|
|
C_TFPlayer *pCarrier = pBall->GetCarrier(); |
|
if ( !pCarrier ) |
|
{ |
|
DestroyBeams( pBall ); |
|
return; |
|
} |
|
|
|
const char *pEffectName = "passtime_beam"; |
|
CParticleProperty *pParticles = pBall->ParticleProp(); |
|
|
|
for ( int i = 1; i <= MAX_PLAYERS; ++i ) |
|
{ |
|
if ( !m_bPlayerIsPackMember[i] ) |
|
{ |
|
DestroyBeam( i, pBall ); |
|
continue; |
|
} |
|
|
|
CTFPlayer *pPlayer = (CTFPlayer*) UTIL_PlayerByIndex( i ); |
|
if ( !pPlayer || ( pPlayer == pCarrier ) || !pPlayer->IsAlive() ) |
|
{ |
|
DestroyBeam( i, pBall ); |
|
continue; |
|
} |
|
|
|
if ( !m_apPackBeams[i] ) |
|
{ |
|
CNewParticleEffect *pBeam = pParticles->Create( pEffectName, PATTACH_ABSORIGIN_FOLLOW ); |
|
pParticles->AddControlPoint( pBeam, 1, pPlayer, PATTACH_ABSORIGIN_FOLLOW, 0, Vector(0,0,16) ); |
|
m_apPackBeams[i] = pBeam; |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void C_TFPasstimeLogic::GetTrackPoints( Vector (&points)[16] ) |
|
{ |
|
memcpy( points, m_trackPoints.Base(), sizeof(points) ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
bool C_TFPasstimeLogic::GetImportantEntities( C_PasstimeBall **ppBall, C_TFPlayer **ppCarrier, C_TFPlayer **ppHomingTarget ) const |
|
{ |
|
C_PasstimeBall *pBall = GetBall(); |
|
if ( !pBall ) |
|
{ |
|
return false; |
|
} |
|
|
|
if ( ppBall ) |
|
{ |
|
*ppBall = pBall; |
|
} |
|
|
|
if ( ppCarrier ) |
|
{ |
|
*ppCarrier = pBall->GetCarrier(); |
|
} |
|
|
|
if ( ppHomingTarget ) |
|
{ |
|
*ppHomingTarget = ToTFPlayer( pBall->GetHomingTarget() ); |
|
} |
|
|
|
return true; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
bool C_TFPasstimeLogic::GetBallReticleTarget( C_BaseEntity **ppEnt, bool *bHomingActive ) const |
|
{ |
|
Assert( ppEnt ); |
|
if ( !ppEnt ) |
|
{ |
|
return false; |
|
} |
|
|
|
C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer(); |
|
if ( !pLocalPlayer ) |
|
{ |
|
return false; |
|
} |
|
|
|
C_PasstimeBall *pBall = 0; |
|
C_TFPlayer *pCarrier = 0, *pHomingTarget = 0; |
|
if ( !GetImportantEntities( &pBall, &pCarrier, &pHomingTarget ) ) |
|
{ |
|
return false; |
|
} |
|
|
|
C_BaseEntity *pEnt = pCarrier ? pCarrier : (C_BaseEntity*)pBall; |
|
if ( !pEnt |
|
|| (pEnt == pLocalPlayer) |
|
|| (pEnt->GetEffects() & EF_NODRAW) |
|
|| ((pEnt->GetTeamNumber() != TEAM_UNASSIGNED) |
|
&& (pEnt->GetTeamNumber() != pLocalPlayer->GetTeamNumber())) |
|
|| (pLocalPlayer->IsObserver() && (GetSpectatorMode() != OBS_MODE_ROAMING) && (GetSpectatorTarget() == pEnt->index)) ) |
|
{ |
|
return false; |
|
} |
|
|
|
*ppEnt = pEnt; |
|
if ( bHomingActive ) |
|
{ |
|
*bHomingActive = pHomingTarget != 0; |
|
} |
|
|
|
return true; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
bool C_TFPasstimeLogic::BCanPlayerPickUpBall( C_TFPlayer *pPlayer ) const |
|
{ |
|
return pPlayer |
|
&& pPlayer->IsAllowedToPickUpFlag() |
|
&& pPlayer->IsAlive() // NOTE: it's possible to be alive and dead at the same time |
|
&& !pPlayer->m_Shared.InCond( TF_COND_INVULNERABLE ) |
|
&& !pPlayer->m_Shared.InCond( TF_COND_PHASE ) |
|
&& !pPlayer->m_Shared.InCond( TF_COND_INVULNERABLE_WEARINGOFF ) |
|
&& !pPlayer->m_Shared.InCond( TF_COND_SELECTED_TO_TELEPORT ) |
|
&& !pPlayer->m_Shared.InCond( TF_COND_STEALTHED_BLINK ) |
|
&& !pPlayer->m_Shared.InCond( TF_COND_TAUNTING ) |
|
&& !pPlayer->m_Shared.InCond( TF_COND_HALLOWEEN_GHOST_MODE ) |
|
&& !pPlayer->m_Shared.IsControlStunned() |
|
&& !pPlayer->m_Shared.IsStealthed() |
|
&& !pPlayer->m_Shared.IsCarryingObject(); |
|
} |
|
|
|
|