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.
323 lines
9.7 KiB
323 lines
9.7 KiB
5 years ago
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
// $NoKeywords: $
|
||
|
//=============================================================================//
|
||
|
#include "cbase.h"
|
||
|
#include "basetfplayer_shared.h"
|
||
|
#include "in_buttons.h"
|
||
|
#include "tf_gamerules.h"
|
||
|
#include "weapon_combatshield.h"
|
||
|
|
||
|
#if defined( CLIENT_DLL )
|
||
|
|
||
|
#include "particles_simple.h"
|
||
|
#include "fx.h"
|
||
|
#include "fx_quad.h"
|
||
|
#include "clienteffectprecachesystem.h"
|
||
|
|
||
|
#define CWeaponArcWelder C_WeaponArcWelder
|
||
|
#else
|
||
|
#endif
|
||
|
|
||
|
#include "weapon_repairgun.h"
|
||
|
|
||
|
// memdbgon must be the last include file in a .cpp file!!!
|
||
|
#include "tier0/memdbgon.h"
|
||
|
|
||
|
|
||
|
|
||
|
// Buff ranges
|
||
|
ConVar weapon_arcwelder_target_range( "weapon_arcwelder_target_range", "90", FCVAR_REPLICATED, "The farthest away you can be for the arcwelder to initially lock onto a target." );
|
||
|
ConVar weapon_arcwelder_stick_range( "weapon_arcwelder_stick_range", "100", FCVAR_REPLICATED, "How far away the arcwelder can stay locked onto someone." );
|
||
|
ConVar weapon_arcwelder_rate( "weapon_arcwelder_rate", "15", FCVAR_REPLICATED );
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
class CWeaponArcWelder : public CWeaponRepairGun
|
||
|
{
|
||
|
DECLARE_CLASS( CWeaponArcWelder, CWeaponRepairGun );
|
||
|
public:
|
||
|
DECLARE_NETWORKCLASS();
|
||
|
DECLARE_PREDICTABLE();
|
||
|
|
||
|
CWeaponArcWelder( void );
|
||
|
|
||
|
virtual void Precache();
|
||
|
|
||
|
virtual float GetTargetRange( void );
|
||
|
virtual float GetStickRange( void );
|
||
|
virtual float GetHealRate( void );
|
||
|
virtual bool AppliesModifier( void ) { return false; }
|
||
|
virtual bool TargetsPlayers( void ) { return false; }
|
||
|
virtual CBaseEntity *GetTargetToHeal( CBaseEntity *pCurHealing );
|
||
|
|
||
|
// All predicted weapons need to implement and return true
|
||
|
virtual bool IsPredicted( void ) const
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
#if defined( CLIENT_DLL )
|
||
|
virtual void ClientThink( void );
|
||
|
virtual bool OnFireEvent( C_BaseViewModel *pViewModel, const Vector& origin, const QAngle& angles, int event, const char *options );
|
||
|
virtual void ViewModelDrawn( C_BaseViewModel *pViewModel );
|
||
|
|
||
|
virtual bool ShouldPredict( void )
|
||
|
{
|
||
|
if ( GetOwner() == C_BasePlayer::GetLocalPlayer() )
|
||
|
return true;
|
||
|
|
||
|
return BaseClass::ShouldPredict();
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
private:
|
||
|
bool m_bWelding;
|
||
|
|
||
|
#if defined( CLIENT_DLL )
|
||
|
float m_flNextEffectTime;
|
||
|
#endif
|
||
|
|
||
|
private:
|
||
|
CWeaponArcWelder( const CWeaponArcWelder & );
|
||
|
};
|
||
|
|
||
|
LINK_ENTITY_TO_CLASS( weapon_arcwelder, CWeaponArcWelder );
|
||
|
|
||
|
PRECACHE_WEAPON_REGISTER( weapon_arcwelder );
|
||
|
|
||
|
IMPLEMENT_NETWORKCLASS_ALIASED( WeaponArcWelder, DT_WeaponArcWelder )
|
||
|
|
||
|
BEGIN_NETWORK_TABLE( CWeaponArcWelder, DT_WeaponArcWelder )
|
||
|
END_NETWORK_TABLE()
|
||
|
|
||
|
BEGIN_PREDICTION_DATA( CWeaponArcWelder )
|
||
|
END_PREDICTION_DATA()
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CWeaponArcWelder::CWeaponArcWelder()
|
||
|
{
|
||
|
SetPredictionEligible( true );
|
||
|
m_bWelding = false;
|
||
|
#ifdef CLIENT_DLL
|
||
|
m_flNextEffectTime = 0;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
void CWeaponArcWelder::Precache()
|
||
|
{
|
||
|
BaseClass::Precache();
|
||
|
|
||
|
PrecacheScriptSound( "WeaponRepairGun.Healing" );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
float CWeaponArcWelder::GetTargetRange( void )
|
||
|
{
|
||
|
return weapon_arcwelder_target_range.GetFloat();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
float CWeaponArcWelder::GetStickRange( void )
|
||
|
{
|
||
|
return weapon_arcwelder_target_range.GetFloat();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
float CWeaponArcWelder::GetHealRate( void )
|
||
|
{
|
||
|
return weapon_arcwelder_rate.GetFloat();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Returns a pointer to a healable target
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CBaseEntity *CWeaponArcWelder::GetTargetToHeal( CBaseEntity *pCurHealing )
|
||
|
{
|
||
|
CBaseEntity *pTarget = BaseClass::GetTargetToHeal(pCurHealing);
|
||
|
if ( !pTarget )
|
||
|
return pTarget;
|
||
|
|
||
|
// Make sure the target is within our field of view
|
||
|
CBaseTFPlayer *pOwner = ToBaseTFPlayer( GetOwner() );
|
||
|
if ( !pOwner )
|
||
|
return NULL;
|
||
|
|
||
|
Vector vecAiming;
|
||
|
pOwner->EyeVectors( &vecAiming );
|
||
|
|
||
|
// Find a player in range of this player, and make sure they're healable.
|
||
|
Vector vecSrc = pOwner->Weapon_ShootPosition( );
|
||
|
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 );
|
||
|
if ( tr.fraction != 1.0 && tr.m_pEnt == pTarget )
|
||
|
return pTarget;
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
#ifdef CLIENT_DLL
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeaponArcWelder::ClientThink( void )
|
||
|
{
|
||
|
CBasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
|
||
|
if ( !pPlayer )
|
||
|
return;
|
||
|
|
||
|
if ( m_hHealingTarget == NULL )
|
||
|
return;
|
||
|
|
||
|
// Don't show it while the player is dead. Ideally, we'd respond to m_bHealing in OnDataChanged,
|
||
|
// but it stops sending the weapon when it's holstered, and it gets holstered when the player dies.
|
||
|
C_BasePlayer *pFiringPlayer = dynamic_cast< C_BasePlayer* >( GetOwner() );
|
||
|
if ( !pFiringPlayer || pFiringPlayer->IsPlayerDead() )
|
||
|
{
|
||
|
ClientThinkList()->SetNextClientThink( GetClientHandle(), CLIENT_THINK_NEVER );
|
||
|
m_bPlayingSound = false;
|
||
|
StopRepairSound();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Start playing the heal sound, if we're not already
|
||
|
if ( !m_bPlayingSound )
|
||
|
{
|
||
|
m_bPlayingSound = true;
|
||
|
CLocalPlayerFilter filter;
|
||
|
EmitSound( filter, entindex(), "WeaponRepairGun.Healing" );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CWeaponArcWelder::OnFireEvent( C_BaseViewModel *pViewModel, const Vector& origin, const QAngle& angles, int event, const char *options )
|
||
|
{
|
||
|
CBaseTFPlayer *pPlayer = static_cast<CBaseTFPlayer*>( GetOwner() );
|
||
|
if ( !pPlayer )
|
||
|
return true;
|
||
|
|
||
|
switch ( event )
|
||
|
{
|
||
|
case 7001:
|
||
|
m_bWelding = true;
|
||
|
return true;
|
||
|
case 7002:
|
||
|
m_bWelding = false;
|
||
|
return true;
|
||
|
default:
|
||
|
break;
|
||
|
};
|
||
|
|
||
|
return BaseClass::OnFireEvent( pViewModel, origin, angles, event, options );
|
||
|
}
|
||
|
|
||
|
CLIENTEFFECT_REGISTER_BEGIN( PrecacheArcWelderEffect )
|
||
|
CLIENTEFFECT_MATERIAL( "particle/smoke_arcwelder" )
|
||
|
CLIENTEFFECT_MATERIAL( "effects/spark2" )
|
||
|
CLIENTEFFECT_MATERIAL( "effects/blueflare" )
|
||
|
CLIENTEFFECT_MATERIAL( "effects/blueflare2" )
|
||
|
CLIENTEFFECT_REGISTER_END()
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeaponArcWelder::ViewModelDrawn( C_BaseViewModel *pViewModel )
|
||
|
{
|
||
|
if ( !m_bWelding || !m_hHealingTarget.Get() )
|
||
|
return;
|
||
|
|
||
|
if ( m_flNextEffectTime > gpGlobals->curtime )
|
||
|
return;
|
||
|
m_flNextEffectTime = gpGlobals->curtime + 0.1;
|
||
|
|
||
|
// Get our weldpoint
|
||
|
Vector attachOrigin;
|
||
|
QAngle attachAngles;
|
||
|
pViewModel->GetAttachment( pViewModel->LookupAttachment("muzzle"), attachOrigin, attachAngles );
|
||
|
Vector vecEnd = m_hHealingTarget->WorldSpaceCenter();
|
||
|
trace_t tr;
|
||
|
|
||
|
// Use WeaponTraceLine so shields are tested...
|
||
|
TFGameRules()->WeaponTraceLine( attachOrigin, vecEnd, (MASK_SHOT & ~CONTENTS_HITBOX), GetOwner(), DMG_PROBE, &tr );
|
||
|
|
||
|
// Smoke
|
||
|
unsigned char color[3];
|
||
|
int iColOff = random->RandomInt(-16,16);
|
||
|
color[0] = 120 + iColOff;
|
||
|
color[1] = 230 + iColOff;
|
||
|
color[2] = 235 + iColOff;
|
||
|
/*
|
||
|
// Pull out from the target a bit
|
||
|
Vector vecOrigin = vecEnd;
|
||
|
Vector vecFromTarget = (vecEnd - attachOrigin);
|
||
|
VectorNormalize( vecFromTarget );
|
||
|
vecOrigin -= (vecFromTarget * 24);
|
||
|
*/
|
||
|
|
||
|
Vector vecOrigin = attachOrigin;
|
||
|
// Velocity
|
||
|
Vector vecVelocity = tr.plane.normal;
|
||
|
vecVelocity.z += random->RandomFloat( 8, 12 );
|
||
|
// Add it
|
||
|
CSmartPtr<CSimpleEmitter> pSimple = FX_Smoke( vecOrigin, vecVelocity,
|
||
|
random->RandomFloat( 4, 8 ), // Scale
|
||
|
1,
|
||
|
random->RandomFloat( 0.5, 3.0 ), // Dietime
|
||
|
color,
|
||
|
random->RandomInt( 64, 200 ), // Alpha
|
||
|
"particle/smoke_arcwelder",
|
||
|
random->RandomInt(0,255), // Roll
|
||
|
0 ); // Rolldelta
|
||
|
|
||
|
// Sparks
|
||
|
FX_Sparks( vecOrigin, 1, 4, tr.plane.normal, 2.5, 8, 64, "effects/spark2" );
|
||
|
|
||
|
// Bright Glow
|
||
|
SimpleParticle *sParticle;
|
||
|
sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), pSimple->GetPMaterial( "effects/blueflare" ), vecOrigin );
|
||
|
if ( sParticle == NULL )
|
||
|
return;
|
||
|
sParticle->m_flLifetime = 0.0f;
|
||
|
sParticle->m_flDieTime = 0.5f;
|
||
|
sParticle->m_vecVelocity.Init();
|
||
|
sParticle->m_uchColor[0] = 255;
|
||
|
sParticle->m_uchColor[1] = 255;
|
||
|
sParticle->m_uchColor[2] = 255;
|
||
|
sParticle->m_uchStartSize = random->RandomInt(5,7);
|
||
|
sParticle->m_uchEndSize = sParticle->m_uchStartSize;
|
||
|
sParticle->m_flRoll = random->RandomInt(0,360);
|
||
|
sParticle->m_flRollDelta = 0;
|
||
|
|
||
|
// Dull Glow
|
||
|
sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), pSimple->GetPMaterial( "effects/blueflare2" ), vecOrigin );
|
||
|
if ( sParticle == NULL )
|
||
|
return;
|
||
|
sParticle->m_flLifetime = 0.0f;
|
||
|
sParticle->m_flDieTime = 0.2f;
|
||
|
sParticle->m_vecVelocity.Init();
|
||
|
sParticle->m_uchColor[0] = 255;
|
||
|
sParticle->m_uchColor[1] = 255;
|
||
|
sParticle->m_uchColor[2] = 255;
|
||
|
sParticle->m_uchStartSize = random->RandomInt(15,20);
|
||
|
sParticle->m_uchEndSize = sParticle->m_uchStartSize;
|
||
|
sParticle->m_flRoll = random->RandomInt(0,360);
|
||
|
sParticle->m_flRollDelta = 0;
|
||
|
}
|
||
|
#endif
|