diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/shared/tf/tf_revive.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'game/shared/tf/tf_revive.cpp')
| -rw-r--r-- | game/shared/tf/tf_revive.cpp | 461 |
1 files changed, 461 insertions, 0 deletions
diff --git a/game/shared/tf/tf_revive.cpp b/game/shared/tf/tf_revive.cpp new file mode 100644 index 0000000..b1a41e1 --- /dev/null +++ b/game/shared/tf/tf_revive.cpp @@ -0,0 +1,461 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Revive +// +// $NoKeywords: $ +//============================================================================= +#include "cbase.h" +#include "tf_revive.h" +#include "tf_gamerules.h" +#ifdef CLIENT_DLL +#include "tf_hud_target_id.h" +#include "view.h" +#include "tf_hud_mediccallers.h" +#else +#include "tf_gamestats.h" +#include "particle_parse.h" +#include "world.h" +#include "collisionutils.h" +#include "triggers.h" +#endif // CLIENT_DLL + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +#define MARKER_MODEL "models/props_mvm/mvm_revive_tombstone.mdl" + +static const int REVIVE_EASY_LIMIT = 4; +static const int REVIVE_MEDIUM_LIMIT = 8; + +#ifdef GAME_DLL +#ifdef STAGING_ONLY +CON_COMMAND_F ( tf_test_revive_spawnmarker, "Crude way to spawn a marker for testing", FCVAR_CHEAT ) +{ + CBasePlayer *pLocalPlayer = UTIL_PlayerByIndex( 1 ); + if ( !pLocalPlayer ) + return; + + CTFPlayer *pPlayer = ToTFPlayer( pLocalPlayer ); + if ( !pPlayer ) + return; + + CTFReviveMarker::Create( pPlayer ); +} +#endif // STAGING_ONLY +extern void HandleRageGain( CTFPlayer *pPlayer, unsigned int iRequiredBuffFlags, float flDamage, float fInverseRageGainScale ); +#else +extern void AddMedicCaller( C_BaseEntity *pEntity, float flDuration, Vector &vecOffset, bool bAutoCaller = false ); +#endif // GAME_DLL + + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +IMPLEMENT_NETWORKCLASS_ALIASED( TFReviveMarker, DT_TFReviveMarker ) + +BEGIN_NETWORK_TABLE( CTFReviveMarker, DT_TFReviveMarker ) +#ifdef GAME_DLL + SendPropEHandle( SENDINFO( m_hOwner ) ), + SendPropInt( SENDINFO( m_iHealth ), -1, SPROP_VARINT | SPROP_CHANGES_OFTEN ), + SendPropInt( SENDINFO( m_iMaxHealth ), -1, SPROP_VARINT ), + SendPropInt( SENDINFO( m_nRevives ), -1, SPROP_VARINT | SPROP_UNSIGNED ), +#else + RecvPropEHandle( RECVINFO( m_hOwner ) ), + RecvPropInt( RECVINFO( m_iHealth ) ), + RecvPropInt( RECVINFO( m_iMaxHealth ) ), + RecvPropInt( RECVINFO( m_nRevives ) ), +#endif +END_NETWORK_TABLE() + +LINK_ENTITY_TO_CLASS( entity_revive_marker, CTFReviveMarker ); +PRECACHE_REGISTER( entity_revive_marker ); + +BEGIN_DATADESC( CTFReviveMarker ) +#ifdef GAME_DLL + DEFINE_THINKFUNC( ReviveThink ), +#endif // GAME_DLL +END_DATADESC() + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +CTFReviveMarker::CTFReviveMarker() +{ +#ifdef GAME_DLL + m_flHealAccumulator = 0.f; + m_flLastHealTime = 0.f; + m_bOwnerPromptedToRevive = false; + m_bOnGround = false; +#else + m_iMaxHealth = 1; + m_bCalledForMedic = false; +#endif // GAME_DLL + m_nRevives = 0; + + UseClientSideAnimation(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTFReviveMarker::Precache() +{ + BaseClass::Precache(); + + PrecacheModel( MARKER_MODEL ); + PrecacheScriptSound( "MVM.PlayerRevived" ); + PrecacheParticleSystem( "speech_revivecall" ); + PrecacheParticleSystem( "speech_revivecall_medium" ); + PrecacheParticleSystem( "speech_revivecall_hard" ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTFReviveMarker::Spawn( void ) +{ + Precache(); + + BaseClass::Spawn(); + + SetHealth( 1 ); + SetModel( MARKER_MODEL ); + SetSolid( SOLID_BBOX ); + SetSolidFlags( FSOLID_TRIGGER ); + SetCollisionGroup( COLLISION_GROUP_DEBRIS ); + SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE ); + // SetCollisionBounds( VEC_HULL_MIN, VEC_HULL_MAX ); + SetBlocksLOS( false ); + AddEffects( EF_NOSHADOW ); + ResetSequence( LookupSequence( "idle" ) ); + +#ifdef GAME_DLL + m_takedamage = DAMAGE_NO; + + SetThink( &CTFReviveMarker::ReviveThink ); + SetNextThink( gpGlobals->curtime ); +#endif // GAME_DLL +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : collisionGroup - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool CTFReviveMarker::ShouldCollide( int collisionGroup, int contentsMask ) const +{ + if ( collisionGroup == COLLISION_GROUP_PLAYER_MOVEMENT ) + return false; + + if ( collisionGroup == COLLISION_GROUP_PROJECTILE ) + return false; + + if ( collisionGroup == TFCOLLISION_GROUP_ROCKETS ) + return false; + + return BaseClass::ShouldCollide( collisionGroup, contentsMask ); +} + +#ifdef CLIENT_DLL +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTFReviveMarker::OnDataChanged( DataUpdateType_t updateType ) +{ + // Call for medic once the server's set maxhealth + if ( !m_bCalledForMedic && m_iMaxHealth > 1 ) + { + MedicCallerType nType = CALLER_TYPE_REVIVE_EASY; + if ( m_nRevives >= REVIVE_EASY_LIMIT && m_nRevives < REVIVE_MEDIUM_LIMIT ) + { + nType = CALLER_TYPE_REVIVE_MEDIUM; + } + else if ( m_nRevives >= REVIVE_MEDIUM_LIMIT ) + { + nType = CALLER_TYPE_REVIVE_HARD; + } + + Vector vecPos; + if ( GetAttachmentLocal( LookupAttachment( "mediccall" ), vecPos ) ) + { + CTFMedicCallerPanel::AddMedicCaller( this, 5.0, vecPos, nType ); + } + + m_bCalledForMedic = true; + } + + BaseClass::OnDataChanged( updateType ); +} +#endif // CLIENT_DLL + +#ifdef GAME_DLL +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CTFReviveMarker *CTFReviveMarker::Create( CTFPlayer *pOwner ) +{ + if ( pOwner ) + { + CTFReviveMarker *pMarker = static_cast< CTFReviveMarker* >( CBaseEntity::Create( "entity_revive_marker", pOwner->GetAbsOrigin() + Vector( 0, 0, 50 ), pOwner->GetAbsAngles() ) ); + if ( pMarker ) + { + pMarker->SetOwner( pOwner ); + pMarker->ChangeTeam( pOwner->GetTeamNumber() ); + + return pMarker; + } + } + + return NULL; +} + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +int CTFReviveMarker::UpdateTransmitState( void ) +{ + return SetTransmitState( FL_EDICT_FULLCHECK ); +} + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +int CTFReviveMarker::ShouldTransmit( const CCheckTransmitInfo *pInfo ) +{ + return FL_EDICT_ALWAYS; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTFReviveMarker::ReviveThink( void ) +{ + if ( !m_hOwner || !InSameTeam( m_hOwner ) ) + { + UTIL_Remove( this ); + return; + } + + if ( !GetMaxHealth() ) + { + // Set health of marker based on class, and number of previous revives + float flHealth = m_hOwner->GetMaxHealth() / 2; + Assert( flHealth > 0.f ); + PlayerStats_t *pPlayerStats = CTF_GameStats.FindPlayerStats( m_hOwner ); + if ( pPlayerStats ) + { + m_nRevives.Set( pPlayerStats->statsCurrentRound.m_iStat[TFSTAT_REVIVED] ); + flHealth += ( (float)m_nRevives * 10.f ); + } + SetMaxHealth( flHealth ); + } + + // At rest? + if ( !m_bOnGround && ( GetFlags() & FL_ONGROUND ) ) + { + SetMoveType( MOVETYPE_NONE ); + m_bOnGround = true; + + // See if we've in a trigger_hurt + for ( int i = 0; i < ITriggerHurtAutoList::AutoList().Count(); i++ ) + { + CTriggerHurt *pTrigger = static_cast<CTriggerHurt*>( ITriggerHurtAutoList::AutoList()[i] ); + if ( !pTrigger->m_bDisabled ) + { + Vector vecMins, vecMaxs; + pTrigger->GetCollideable()->WorldSpaceSurroundingBounds( &vecMins, &vecMaxs ); + if ( IsPointInBox( GetCollideable()->GetCollisionOrigin(), vecMins, vecMaxs ) ) + { + UTIL_Remove( this ); + return; + } + } + } + + // Different particle based on difficulty of this revive + const char *pszParticle = NULL; + if ( m_nRevives < REVIVE_EASY_LIMIT ) + { + pszParticle = "speech_revivecall"; + } + else if ( m_nRevives < REVIVE_MEDIUM_LIMIT ) + { + pszParticle = "speech_revivecall_medium"; + } + else + { + pszParticle = "speech_revivecall_hard"; + } + + // DispatchParticleEffect( pszParticle, GetAbsOrigin() + Vector( 0, 0, 80 ), vec3_angle ); + DispatchParticleEffect( pszParticle, PATTACH_POINT_FOLLOW, this, "mediccall" ); + EmitSound( "Medic.AutoCallerAnnounce" ); + } + + // Close revive prompt if no longer being revived + if ( HasOwnerBeenPrompted() && !IsReviveInProgress() ) + { + IGameEvent *event = gameeventmanager->CreateEvent( "revive_player_stopped" ); + if ( event ) + { + event->SetInt( "entindex", m_hOwner->entindex() ); + gameeventmanager->FireEvent( event ); + + SetOwnerHasBeenPrompted( false ); + } + } + + SetNextThink( gpGlobals->curtime + 0.1f ); +} +#endif // GAME_DLL + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +void CTFReviveMarker::SetOwner( CTFPlayer *pPlayer ) +{ +#ifdef GAME_DLL + if ( !pPlayer ) + return; + + m_hOwner = pPlayer; + ChangeTeam( m_hOwner->GetTeamNumber() ); + + // Determine bodygroup based on class + SetBodygroup( 1, m_hOwner->GetPlayerClass()->GetClassIndex() - 1 ); + + SetAbsAngles( m_hOwner->GetAbsAngles() ); +#endif // GAME_DLL +} + +#ifdef GAME_DLL +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +void CTFReviveMarker::AddMarkerHealth( float flAmount ) +{ + CTFPlayer *pReviver = GetReviver(); + if ( !pReviver ) + return; + + CTFPlayer *pOwner = GetOwner(); + if ( !pOwner ) + return; + + if ( !GetMaxHealth() ) + return; + + HandleRageGain( pReviver, kRageBuffFlag_OnHeal, flAmount * 2, 1.f ); + + m_flHealAccumulator += flAmount; + if ( m_flHealAccumulator >= 1.f ) + { + float flHealthToAdd = floor( m_flHealAccumulator ); + m_flHealAccumulator -= flHealthToAdd; + m_iHealth += flHealthToAdd; + m_flLastHealTime = gpGlobals->curtime; + } + + if ( m_iHealth >= GetMaxHealth() ) + { + ReviveOwner(); + + // Give points + CTF_GameStats.Event_PlayerAwardBonusPoints( pReviver, pOwner, 50 ); + } +} + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +bool CTFReviveMarker::IsReviveInProgress( void ) +{ + float flTimeSinceHeal = gpGlobals->curtime - m_flLastHealTime; + return ( m_flLastHealTime && flTimeSinceHeal <= 2.f ); +} + +//----------------------------------------------------------------------------- +// Returns true if the player was spawned at their marker +//----------------------------------------------------------------------------- +bool CTFReviveMarker::ReviveOwner( void ) +{ + if ( !m_hOwner ) + return false; + + m_hOwner->ForceRespawn(); + + // Increment stat + CTF_GameStats.Event_PlayerRevived( m_hOwner ); + + // If the medic's gone, or dead, stay in the spawn room + if ( !m_pReviver || !m_pReviver->IsAlive() ) + return false; + + // See if their marker is clear + Vector vecTeleportPos = GetAbsOrigin(); + trace_t tr; + CTraceFilterIgnoreTeammatesAndTeamObjects filter( m_hOwner, COLLISION_GROUP_NONE, m_hOwner->GetTeamNumber() ); + UTIL_TraceHull( vecTeleportPos, vecTeleportPos, VEC_HULL_MIN_SCALED( m_hOwner ), VEC_HULL_MAX_SCALED( m_hOwner ), ( MASK_SOLID | CONTENTS_PLAYERCLIP ), &filter, &tr ); + + // If not, try the medic's location + if ( tr.fraction < 1.f ) + { + if ( !m_pReviver ) + // They'll appear in their spawn room. + return false; + + vecTeleportPos = m_pReviver->GetAbsOrigin(); + } + else + { + // Use the angles that were stored when the marker was spawned + m_hOwner->SetAbsAngles( GetAbsAngles() ); + } + + // Magic + color32 fadeColor = { 50, 50, 50, 200 }; + UTIL_ScreenFade( m_hOwner, fadeColor, 0.5, 0.4, FFADE_IN ); + + m_hOwner->Teleport( &vecTeleportPos, &m_hOwner->GetAbsAngles(), &vec3_origin ); + m_hOwner->EmitSound( "MVM.PlayerRevived" ); + + if ( m_pReviver ) + { + IGameEvent *event = gameeventmanager->CreateEvent( "revive_player_complete" ); + if ( event ) + { + event->SetInt( "entindex", m_pReviver->entindex() ); + gameeventmanager->FireEvent( event ); + } + } + + m_hOwner->SpeakConceptIfAllowed( MP_CONCEPT_RESURRECTED ); + + return true; +} + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +void CTFReviveMarker::PromptOwner( void ) +{ + if ( !m_hOwner ) + { + UTIL_Remove( this ); + return; + } + + if ( HasOwnerBeenPrompted() ) + return; + + IGameEvent *event = gameeventmanager->CreateEvent( "revive_player_notify" ); + if ( event ) + { + event->SetInt( "entindex", m_hOwner->entindex() ); + event->SetInt( "marker_entindex", entindex() ); + gameeventmanager->FireEvent( event ); + + SetOwnerHasBeenPrompted( true ); + } +} +#endif // GAME_DLL |