⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 weapon_repairgun.cpp

📁 hl2 source code. Do not use it illegal.
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//=========== (C) Copyright 2000 Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// Purpose:			The Medic's Medikit weapon
//					
//
// $Workfile:     $
// $Date:         $
// $NoKeywords: $
//=============================================================================
#include "cbase.h"
#include "basetfplayer_shared.h"
#include "in_buttons.h"
#include "weapon_combatshield.h"
#include "engine/ienginesound.h"
#include "grenade_base_empable.h"
#include "basetfvehicle.h"
#include "tf_gamerules.h"

//#define REPAIR_GUN_DISABLES_GRENADES	// Uncomment if you want the repair gun to disable grenades.

#if defined( CLIENT_DLL )
#include "particles_simple.h"
#else
#include "ndebugoverlay.h"
#endif

#include "weapon_repairgun.h"

// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"

// Buff ranges
ConVar weapon_repairgun_target_range( "weapon_repairgun_target_range", "450", FCVAR_REPLICATED, "The farthest away you can be for the repair gun to initially lock onto a player." );
ConVar weapon_repairgun_stick_range( "weapon_repairgun_stick_range", "512", FCVAR_REPLICATED, "How far away the repair gun can stay locked onto someone." );
ConVar weapon_repairgun_rate( "weapon_repairgun_rate", "12", FCVAR_REPLICATED, "Health healed per second by the repair gun." );
ConVar weapon_repairgun_damage_modifier( "weapon_repairgun_damage_modifier", "1.5", FCVAR_REPLICATED, "Scales the damage a player does while being healed with the repair gun." );
ConVar weapon_repairgun_debug( "weapon_repairgun_debug", "0", FCVAR_REPLICATED, "Show debugging info for the repair gun." );
ConVar weapon_repairgun_construction_rate( "weapon_repairgun_construction_rate", "10", FCVAR_REPLICATED, "Constructing object health healed per second by the repair gun." );

LINK_ENTITY_TO_CLASS( weapon_repairgun, CWeaponRepairGun );

PRECACHE_WEAPON_REGISTER( weapon_repairgun );

IMPLEMENT_NETWORKCLASS_ALIASED( WeaponRepairGun, DT_WeaponRepairGun )

BEGIN_NETWORK_TABLE( CWeaponRepairGun, DT_WeaponRepairGun )
#if !defined( CLIENT_DLL )
	SendPropInt( SENDINFO( m_bHealing ), 1, SPROP_UNSIGNED ),
	SendPropInt( SENDINFO( m_bAttacking ), 1, SPROP_UNSIGNED ),
	SendPropEHandle( SENDINFO( m_hHealingTarget ) ),
#else
	RecvPropInt( RECVINFO( m_bAttacking ) ),
	RecvPropInt( RECVINFO( m_bHealing ) ),
	RecvPropEHandle( RECVINFO(m_hHealingTarget) ),
#endif
END_NETWORK_TABLE()

BEGIN_PREDICTION_DATA( CWeaponRepairGun  )

	DEFINE_PRED_FIELD( CWeaponRepairGun, m_bHealing, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
	DEFINE_PRED_FIELD( CWeaponRepairGun, m_bAttacking, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
	DEFINE_PRED_FIELD( CWeaponRepairGun, m_hHealingTarget, FIELD_EHANDLE, FTYPEDESC_INSENDTABLE ),

	DEFINE_FIELD( CWeaponRepairGun, m_flHealEffectLifetime, FIELD_FLOAT ),

//	DEFINE_PRED_FIELD( CWeaponRepairGun, m_pEmitter, FIELD_POINTER ),
//	DEFINE_PRED_FIELD( CWeaponRepairGun, m_hParticleMaterial, FIELD_???,  ),
//	DEFINE_PRED_FIELD( CWeaponRepairGun, m_PathParticleEvent, FIELD_???,  ),
//	DEFINE_PRED_FIELD( CWeaponRepairGun, m_bPlayingSound, FIELD_BOOLEAN ),

END_PREDICTION_DATA()

#define PARTICLE_PATH_VEL				140.0
#define NUM_PATH_PARTICLES_PER_SEC		600.0f
#define NUM_TARGET_PARTICLES_PER_SEC	720.0f

#define NUM_REPAIRGUN_PATH_POINTS		8

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
CWeaponRepairGun::CWeaponRepairGun( void )
{
	m_flHealEffectLifetime = 0;

	m_bHealing = false;
	m_bAttacking = false;

	m_flNextBuzzTime = 0;

#if defined( CLIENT_DLL )
	m_pEmitter = NULL;
	m_hParticleMaterial = INVALID_MATERIAL_HANDLE;
	m_PathParticleEvent.Init( NUM_PATH_PARTICLES_PER_SEC );
	m_bPlayingSound = false;
#endif

	SetPredictionEligible( true );
}


//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
bool CWeaponRepairGun::Holster( CBaseCombatWeapon *pSwitchingTo )
{
	RemoveHealingTarget();
	m_bAttacking = false;

	return BaseClass::Holster( pSwitchingTo );
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
float CWeaponRepairGun::GetTargetRange( void )
{
	return weapon_repairgun_target_range.GetFloat();
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
float CWeaponRepairGun::GetStickRange( void )
{
	return weapon_repairgun_stick_range.GetFloat();
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
float CWeaponRepairGun::GetHealRate( void )
{
	return weapon_repairgun_rate.GetFloat();
}

// Now make sure there isn't something other than team players in the way.
class CRepairFilter : public CTraceFilterSimple
{
public:
	CRepairFilter( CBaseEntity *pShooter ) : CTraceFilterSimple( pShooter, TFCOLLISION_GROUP_WEAPON )
	{
		m_pShooter = pShooter;
	}

	virtual bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask )
	{
		// If it hit an edict the isn't the target and is on our team, then the ray is blocked.
		CBaseEntity *pEnt = static_cast<CBaseEntity*>(pHandleEntity);

		// Ignore collisions with the shooter
		if ( pEnt == m_pShooter )
			return false;
		
		// You can't heal a vehicle you are sitting in.

		if( ((CBaseTFPlayer*)m_pShooter)->IsInAVehicle() )
		{

			CBaseEntity* pVehicle = ((CBaseTFPlayer*)m_pShooter)->GetVehicle()->GetVehicleEnt();		
			if( pVehicle == pEnt )
			{
				return false;
			}
		}

#ifdef REPAIR_GUN_DISABLES_GRENADES 

			// Repairgun can also disable enemy grenades
			CBaseEMPableGrenade *pGrenade = dynamic_cast<CBaseEMPableGrenade*>(pEnt);

			// Ignore collisions with teammates, or friendly grenades
			if ( !pGrenade )
			{
				if ( pEnt->GetTeam() == m_pShooter->GetTeam() )
					return false;
			}
#else
			if ( pEnt->GetTeam() == m_pShooter->GetTeam() )
				return false;
#endif

		return CTraceFilterSimple::ShouldHitEntity( pHandleEntity, contentsMask );
	}

	CBaseEntity	*m_pShooter;
};

//-----------------------------------------------------------------------------
// Purpose: Vehicle checking to see if we should switch targets from a player 
//			to a vehicle, or vice versa.
//-----------------------------------------------------------------------------
CBaseEntity *CWeaponRepairGun::CheckVehicleTargets( CBaseEntity *pCurHealing )
{
	// Unable to switch to/from players?
	if ( !TargetsPlayers() )
		return pCurHealing;

	CBaseTFVehicle *pTargetVehicle = NULL;

	// If we're a fully healed player sitting in a vehicle, see if the vehicle needs healing instead
	if ( pCurHealing->IsPlayer() && pCurHealing->GetHealth() >= pCurHealing->GetMaxHealth() )
	{
		CBaseTFPlayer *pPlayer = (CBaseTFPlayer*)pCurHealing;
		if ( !pPlayer->IsInAVehicle() )
			return pCurHealing;

		pTargetVehicle = (CBaseTFVehicle*)(pPlayer->GetVehicle()->GetVehicleEnt());
		if ( pTargetVehicle->GetHealth() < pTargetVehicle->GetMaxHealth() )
			return pTargetVehicle;
	}
	else
	{
		// If the entity is a vehicle, and it's fully healed, heal any players in it instead
		pTargetVehicle = dynamic_cast<CBaseTFVehicle *>(pCurHealing);
	}

	// Is the vehicle fully healed?
	if ( pTargetVehicle && pTargetVehicle->GetHealth() >= pTargetVehicle->GetMaxHealth() )
	{
		CBaseTFPlayer *pUnhurtPlayer = NULL;
		CBaseTFPlayer *pHurtPlayer = NULL;

		// Go through all players in the vehicle
		int iMax = pTargetVehicle->GetMaxPassengerCount();
		for ( int i = 0; i < iMax; i++ )
		{
			CBaseTFPlayer *pPlayer = (CBaseTFPlayer *)pTargetVehicle->GetPassenger(i);
			if ( pPlayer )
			{
				if ( pPlayer->GetHealth() < pPlayer->GetMaxHealth() )
				{
					pUnhurtPlayer = pPlayer;
				}
				else
				{
					pHurtPlayer = pPlayer;
				}
			}
		}

		// Heal hurt players first
		if ( pHurtPlayer )
			return pHurtPlayer;

		if ( pUnhurtPlayer )
			return pUnhurtPlayer;
	}

	return pCurHealing;
}

//-----------------------------------------------------------------------------
// Purpose: Returns a pointer to a healable target
//-----------------------------------------------------------------------------
CBaseEntity *CWeaponRepairGun::GetTargetToHeal( CBaseEntity *pCurHealing )
{
	CBaseTFPlayer *pOwner = ToBaseTFPlayer( GetOwner() );
	if ( !pOwner )
		return NULL;

	Vector vecSrc = pOwner->Weapon_ShootPosition( );
	

	// If we're already healing someone, stick onto them as long as possible.
	// Even if we can't heal them at the moment, lock onto them until they release the buttom.
	CBaseEntity* pTarget = pCurHealing;
	CBaseEntity* pVehicle = NULL;	// Vehicle the owner is in, or NULL.

	// You can't heal a vehicle you are sitting in, make sure we aren't healing a vehicle right after we've gotten in.
	if( ((CBaseTFPlayer*)pOwner)->IsInAVehicle() )
	{

		pVehicle = ((CBaseTFPlayer*)pOwner)->GetVehicle()->GetVehicleEnt();		
		if( pVehicle == pTarget )
		{
			pTarget = NULL;
		}
	}

	if ( pTarget && pTarget->IsAlive() && (pTarget->GetTeam() == pOwner->GetTeam()) )
	{

		// Make sure the guy didn't go out of range.
		Vector vecTargetPoint = pTarget->WorldSpaceCenter();
		Vector vecPoint;
		// If it's brush built, use absmins/absmaxs
		CalcClosestPointOnAABB( pTarget->GetAbsMins(), pTarget->GetAbsMaxs(), vecSrc, vecPoint );
#ifndef CLIENT_DLL
		//NDebugOverlay::Box( vecPoint, Vector(-2,-2,-2), Vector(2,2,2), 255,0,0, 8, 0.1 );
#endif

		float flDistance = (vecPoint - vecSrc).Length();
		if ( flDistance < GetStickRange() )
		{
			trace_t tr;
			CRepairFilter drainFilter( pOwner );
			UTIL_TraceLine( vecSrc, vecTargetPoint, MASK_SHOT, &drainFilter, &tr );
			
			if (( tr.fraction == 1.0f) || (tr.m_pEnt == pTarget))
				return CheckVehicleTargets( pTarget );
		}

		// Return null so we can't heal this player but m_hHealingPlayer stays set to them.
		return NULL;
	}
	else
	{	
		// Ok, try to find a new player to heal.
		// Get the target point and location
		Vector vecAiming;
		pOwner->EyeVectors( &vecAiming );

		// Find a player in range of this player, and make sure they're healable.
		Vector vecEnd = vecSrc + vecAiming * GetTargetRange();
		trace_t tr;

		// Use WeaponTraceLine so shields are tested...
		TFGameRules()->WeaponTraceLine( vecSrc, vecEnd, (MASK_SHOT & ~CONTENTS_HITBOX), pOwner, DMG_PROBE, &tr );

#ifndef CLIENT_DLL
		//NDebugOverlay::Box( vecSrc, Vector(-2,-2,-2), Vector(2,2,2), 192,192,0, 8, 10 );
		//NDebugOverlay::Box( vecEnd, Vector(-2,-2,-2), Vector(2,2,2), 0,255,0, 8, 10 );
		//NDebugOverlay::Box( tr.endpos, Vector(-2,-2,-2), Vector(2,2,2), 0,0,255, 8, 10 );
#endif
		
		if ( tr.fraction != 1.0 )
		{
			CBaseEntity *pEntity = tr.m_pEnt;
			if ( pEntity )
			{
				// Repairgun can also disable enemy grenades
#ifdef REPAIR_GUN_DISABLES_GRENADES 

				CBaseEMPableGrenade *pGrenade = dynamic_cast<CBaseEMPableGrenade*>(pEntity);
				if ( pGrenade && !pGrenade->InSameTeam( pOwner ) )
					return pGrenade;
#endif

				// Only target players if I'm allowed to
				if ( !TargetsPlayers() && pEntity->IsPlayer() )
					return NULL;

				// You can't heal a vehicle you are sitting in.
				if ( pVehicle && ( pVehicle == pEntity ) )
					return NULL;

				if ( (pEntity != pOwner) && pEntity->IsAlive() && pEntity->CanBePoweredUp() )
				{
					// Target needs to be on the same team
					if ( pEntity->InSameTeam( pOwner ) )
						return CheckVehicleTargets( pEntity );
				}
			}
		}

		if ( weapon_repairgun_debug.GetBool() )
		{
			ClientPrint( pOwner, HUD_PRINTCENTER, "REPAIRGUN: no target found\n" );
		}

		return NULL;
	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -