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.
482 lines
13 KiB
482 lines
13 KiB
![]()
4 years ago
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
//
|
||
|
// Purpose: Combine guard gun, strider destroyer
|
||
|
//
|
||
|
// $NoKeywords: $
|
||
|
//=============================================================================//
|
||
|
|
||
|
#include "cbase.h"
|
||
|
#include "basehlcombatweapon.h"
|
||
|
#include "basecombatcharacter.h"
|
||
|
#include "player.h"
|
||
|
#include "grenade_ar2.h"
|
||
|
#include "soundent.h"
|
||
|
#include "explode.h"
|
||
|
#include "shake.h"
|
||
|
#include "energy_wave.h"
|
||
|
#include "te_particlesystem.h"
|
||
|
#include "ndebugoverlay.h"
|
||
|
|
||
|
// memdbgon must be the last include file in a .cpp file!!!
|
||
|
#include "tier0/memdbgon.h"
|
||
|
|
||
|
//Concussive explosion entity
|
||
|
|
||
|
class CTEConcussiveExplosion : public CTEParticleSystem
|
||
|
{
|
||
|
public:
|
||
|
DECLARE_CLASS( CTEConcussiveExplosion, CTEParticleSystem );
|
||
|
DECLARE_SERVERCLASS();
|
||
|
|
||
|
CTEConcussiveExplosion( const char *name );
|
||
|
virtual ~CTEConcussiveExplosion( void );
|
||
|
|
||
|
CNetworkVector( m_vecNormal );
|
||
|
CNetworkVar( float, m_flScale );
|
||
|
CNetworkVar( int, m_nRadius );
|
||
|
CNetworkVar( int, m_nMagnitude );
|
||
|
};
|
||
|
|
||
|
IMPLEMENT_SERVERCLASS_ST( CTEConcussiveExplosion, DT_TEConcussiveExplosion )
|
||
|
SendPropVector( SENDINFO(m_vecNormal), -1, SPROP_COORD ),
|
||
|
SendPropFloat( SENDINFO(m_flScale), 0, SPROP_NOSCALE ),
|
||
|
SendPropInt( SENDINFO(m_nRadius), 32, SPROP_UNSIGNED ),
|
||
|
SendPropInt( SENDINFO(m_nMagnitude), 32, SPROP_UNSIGNED ),
|
||
|
END_SEND_TABLE()
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Constructor
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CTEConcussiveExplosion::CTEConcussiveExplosion( const char *name ) : BaseClass( name )
|
||
|
{
|
||
|
m_nRadius = 0;
|
||
|
m_nMagnitude = 0;
|
||
|
m_flScale = 0.0f;
|
||
|
|
||
|
m_vecNormal.Init();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Destructor
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CTEConcussiveExplosion::~CTEConcussiveExplosion( void )
|
||
|
{
|
||
|
}
|
||
|
|
||
|
|
||
|
// Singleton to fire TEExplosion objects
|
||
|
static CTEConcussiveExplosion g_TEConcussiveExplosion( "ConcussiveExplosion" );
|
||
|
|
||
|
void TE_ConcussiveExplosion( IRecipientFilter& filter, float delay,
|
||
|
const Vector* pos, float scale, int radius, int magnitude, const Vector* normal )
|
||
|
{
|
||
|
g_TEConcussiveExplosion.m_vecOrigin = *pos;
|
||
|
g_TEConcussiveExplosion.m_flScale = scale;
|
||
|
g_TEConcussiveExplosion.m_nRadius = radius;
|
||
|
g_TEConcussiveExplosion.m_nMagnitude = magnitude;
|
||
|
|
||
|
if ( normal )
|
||
|
g_TEConcussiveExplosion.m_vecNormal = *normal;
|
||
|
else
|
||
|
g_TEConcussiveExplosion.m_vecNormal = Vector(0,0,1);
|
||
|
|
||
|
// Send it over the wire
|
||
|
g_TEConcussiveExplosion.Create( filter, delay );
|
||
|
}
|
||
|
|
||
|
//Temp ent for the blast
|
||
|
|
||
|
class CConcussiveBlast : public CBaseEntity
|
||
|
{
|
||
|
DECLARE_DATADESC();
|
||
|
public:
|
||
|
DECLARE_CLASS( CConcussiveBlast, CBaseEntity );
|
||
|
|
||
|
int m_spriteTexture;
|
||
|
|
||
|
CConcussiveBlast( void ) {}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
// Output :
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void Precache( void )
|
||
|
{
|
||
|
m_spriteTexture = PrecacheModel( "sprites/lgtning.vmt" );
|
||
|
|
||
|
BaseClass::Precache();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
// Output :
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
void Explode( float magnitude )
|
||
|
{
|
||
|
//Create a concussive explosion
|
||
|
CPASFilter filter( GetAbsOrigin() );
|
||
|
|
||
|
Vector vecForward;
|
||
|
AngleVectors( GetAbsAngles(), &vecForward );
|
||
|
TE_ConcussiveExplosion( filter, 0.0,
|
||
|
&GetAbsOrigin(),//position
|
||
|
1.0f, //scale
|
||
|
256*magnitude, //radius
|
||
|
175*magnitude, //magnitude
|
||
|
&vecForward ); //normal
|
||
|
|
||
|
int colorRamp = random->RandomInt( 128, 255 );
|
||
|
|
||
|
//Shockring
|
||
|
CBroadcastRecipientFilter filter2;
|
||
|
te->BeamRingPoint( filter2, 0,
|
||
|
GetAbsOrigin(), //origin
|
||
|
16, //start radius
|
||
|
300*magnitude, //end radius
|
||
|
m_spriteTexture, //texture
|
||
|
0, //halo index
|
||
|
0, //start frame
|
||
|
2, //framerate
|
||
|
0.3f, //life
|
||
|
128, //width
|
||
|
16, //spread
|
||
|
0, //amplitude
|
||
|
colorRamp, //r
|
||
|
colorRamp, //g
|
||
|
255, //g
|
||
|
24, //a
|
||
|
128 //speed
|
||
|
);
|
||
|
|
||
|
//Do the radius damage
|
||
|
RadiusDamage( CTakeDamageInfo( this, GetOwnerEntity(), 200, DMG_BLAST|DMG_DISSOLVE ), GetAbsOrigin(), 256, CLASS_NONE, NULL );
|
||
|
|
||
|
UTIL_Remove( this );
|
||
|
}
|
||
|
};
|
||
|
|
||
|
LINK_ENTITY_TO_CLASS( concussiveblast, CConcussiveBlast );
|
||
|
|
||
|
//---------------------------------------------------------
|
||
|
// Save/Restore
|
||
|
//---------------------------------------------------------
|
||
|
BEGIN_DATADESC( CConcussiveBlast )
|
||
|
|
||
|
// DEFINE_FIELD( m_spriteTexture, FIELD_INTEGER ),
|
||
|
|
||
|
END_DATADESC()
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Create a concussive blast entity and detonate it
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CreateConcussiveBlast( const Vector &origin, const Vector &surfaceNormal, CBaseEntity *pOwner, float magnitude )
|
||
|
{
|
||
|
QAngle angles;
|
||
|
VectorAngles( surfaceNormal, angles );
|
||
|
CConcussiveBlast *pBlast = (CConcussiveBlast *) CBaseEntity::Create( "concussiveblast", origin, angles, pOwner );
|
||
|
|
||
|
if ( pBlast )
|
||
|
{
|
||
|
pBlast->Explode( magnitude );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Combine Guard weapon
|
||
|
|
||
|
#if 0
|
||
|
|
||
|
class CWeaponCGuard : public CBaseHLCombatWeapon
|
||
|
{
|
||
|
DECLARE_DATADESC();
|
||
|
public:
|
||
|
DECLARE_CLASS( CWeaponCGuard, CBaseHLCombatWeapon );
|
||
|
|
||
|
DECLARE_SERVERCLASS();
|
||
|
|
||
|
CWeaponCGuard( void );
|
||
|
|
||
|
void Precache( void );
|
||
|
void PrimaryAttack( void );
|
||
|
void AddViewKick( void );
|
||
|
void DelayedFire( void );
|
||
|
void ItemPostFrame( void );
|
||
|
void AlertTargets( void );
|
||
|
void UpdateLasers( void );
|
||
|
|
||
|
int CapabilitiesGet( void ) { return bits_CAP_WEAPON_RANGE_ATTACK1; }
|
||
|
|
||
|
DECLARE_ACTTABLE();
|
||
|
|
||
|
protected:
|
||
|
float m_flChargeTime;
|
||
|
bool m_bFired;
|
||
|
|
||
|
int m_beamIndex;
|
||
|
int m_haloIndex;
|
||
|
};
|
||
|
|
||
|
|
||
|
IMPLEMENT_SERVERCLASS_ST(CWeaponCGuard, DT_WeaponCGuard)
|
||
|
END_SEND_TABLE()
|
||
|
|
||
|
LINK_ENTITY_TO_CLASS( weapon_cguard, CWeaponCGuard );
|
||
|
PRECACHE_WEAPON_REGISTER( weapon_cguard );
|
||
|
|
||
|
|
||
|
//---------------------------------------------------------
|
||
|
// Save/Restore
|
||
|
//---------------------------------------------------------
|
||
|
BEGIN_DATADESC( CWeaponCGuard )
|
||
|
|
||
|
DEFINE_FIELD( m_flChargeTime, FIELD_TIME ),
|
||
|
DEFINE_FIELD( m_bFired, FIELD_BOOLEAN ),
|
||
|
// DEFINE_FIELD( m_beamIndex, FIELD_INTEGER ),
|
||
|
// DEFINE_FIELD( m_haloIndex, FIELD_INTEGER ),
|
||
|
|
||
|
END_DATADESC()
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Maps base activities to weapons-specific ones so our characters do the right things.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
acttable_t CWeaponCGuard::m_acttable[] =
|
||
|
{
|
||
|
{ ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SNIPER_RIFLE, true }
|
||
|
};
|
||
|
|
||
|
IMPLEMENT_ACTTABLE( CWeaponCGuard );
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Constructor
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CWeaponCGuard::CWeaponCGuard( void )
|
||
|
{
|
||
|
m_flNextPrimaryAttack = gpGlobals->curtime;
|
||
|
m_flChargeTime = gpGlobals->curtime;
|
||
|
m_bFired = true;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeaponCGuard::Precache( void )
|
||
|
{
|
||
|
UTIL_PrecacheOther( "concussiveblast" );
|
||
|
|
||
|
m_beamIndex = PrecacheModel( "sprites/bluelaser1.vmt" );
|
||
|
m_haloIndex = PrecacheModel( "sprites/blueshaft1.vmt" );
|
||
|
|
||
|
BaseClass::Precache();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeaponCGuard::AlertTargets( void )
|
||
|
{
|
||
|
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
|
||
|
|
||
|
if ( pPlayer == NULL )
|
||
|
return;
|
||
|
|
||
|
// Fire the bullets
|
||
|
Vector vecSrc = pPlayer->Weapon_ShootPosition( );
|
||
|
Vector vecAiming = pPlayer->GetRadialAutoVector( NEW_AUTOAIM_RADIUS, NEW_AUTOAIM_DIST );
|
||
|
|
||
|
Vector impactPoint = vecSrc + ( vecAiming * MAX_TRACE_LENGTH );
|
||
|
|
||
|
trace_t tr;
|
||
|
|
||
|
UTIL_TraceLine( vecSrc, impactPoint, MASK_SHOT, pPlayer, COLLISION_GROUP_NONE, &tr );
|
||
|
|
||
|
if ( (vecSrc-tr.endpos).Length() > 1024 )
|
||
|
return;
|
||
|
|
||
|
CSoundEnt::InsertSound( SOUND_DANGER, tr.endpos, 128, 0.5f );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeaponCGuard::UpdateLasers( void )
|
||
|
{
|
||
|
//Only update the lasers whilst charging
|
||
|
if ( ( m_flChargeTime < gpGlobals->curtime ) || ( m_bFired ) )
|
||
|
return;
|
||
|
|
||
|
Vector start, end, v_forward, v_right, v_up;
|
||
|
|
||
|
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
|
||
|
|
||
|
if ( pPlayer == NULL )
|
||
|
return;
|
||
|
|
||
|
pPlayer->GetVectors( &v_forward, &v_right, &v_up );
|
||
|
|
||
|
//Get the position of the laser
|
||
|
start = pPlayer->Weapon_ShootPosition( );
|
||
|
|
||
|
start += ( v_forward * 8.0f ) + ( v_right * 3.0f ) + ( v_up * -2.0f );
|
||
|
|
||
|
end = start + ( v_forward * MAX_TRACE_LENGTH );
|
||
|
|
||
|
float angleOffset = ( 1.0f - ( m_flChargeTime - gpGlobals->curtime ) ) / 1.0f;
|
||
|
Vector offset[4];
|
||
|
|
||
|
offset[0] = Vector( 0.0f, 0.5f, -0.5f );
|
||
|
offset[1] = Vector( 0.0f, 0.5f, 0.5f );
|
||
|
offset[2] = Vector( 0.0f, -0.5f, -0.5f );
|
||
|
offset[3] = Vector( 0.0f, -0.5f, 0.5f );
|
||
|
|
||
|
QAngle v_ang;
|
||
|
Vector v_dir;
|
||
|
|
||
|
angleOffset *= 2.0f;
|
||
|
|
||
|
if ( angleOffset > 1.0f )
|
||
|
angleOffset = 1.0f;
|
||
|
|
||
|
for ( int i = 0; i < 4; i++ )
|
||
|
{
|
||
|
Vector ofs = start + ( v_forward * offset[i][0] ) + ( v_right * offset[i][1] ) + ( v_up * offset[i][2] );
|
||
|
|
||
|
float hScale = ( offset[i][1] <= 0.0f ) ? 1.0f : -1.0f;
|
||
|
float vScale = ( offset[i][2] <= 0.0f ) ? 1.0f : -1.0f;
|
||
|
|
||
|
VectorAngles( v_forward, v_ang );
|
||
|
v_ang[PITCH] = UTIL_AngleMod( v_ang[PITCH] + ( (1.0f-angleOffset) * 15.0f * vScale ) );
|
||
|
v_ang[YAW] = UTIL_AngleMod( v_ang[YAW] + ( (1.0f-angleOffset) * 15.0f * hScale ) );
|
||
|
|
||
|
AngleVectors( v_ang, &v_dir );
|
||
|
|
||
|
trace_t tr;
|
||
|
UTIL_TraceLine( ofs, ofs + ( v_dir * MAX_TRACE_LENGTH ), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr );
|
||
|
|
||
|
UTIL_Beam( ofs, tr.endpos, m_beamIndex, 0, 0, 2.0f, 0.1f, 2, 0, 1, 0, 255, 255, 255, 32, 100 );
|
||
|
|
||
|
UTIL_Beam( ofs, tr.endpos, m_haloIndex, 0, 0, 2.0f, 0.1f, 4, 0, 1, 16, 255, 255, 255, 8, 100 );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeaponCGuard::PrimaryAttack( void )
|
||
|
{
|
||
|
if ( m_flChargeTime >= gpGlobals->curtime )
|
||
|
return;
|
||
|
|
||
|
AlertTargets();
|
||
|
|
||
|
WeaponSound( SPECIAL1 );
|
||
|
|
||
|
//UTIL_ScreenShake( GetAbsOrigin(), 10.0f, 100.0f, 2.0f, 128, SHAKE_START, false );
|
||
|
|
||
|
m_flChargeTime = gpGlobals->curtime + 1.0f;
|
||
|
m_bFired = false;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeaponCGuard::ItemPostFrame( void )
|
||
|
{
|
||
|
//FIXME: UpdateLasers();
|
||
|
|
||
|
if ( ( m_flChargeTime < gpGlobals->curtime ) && ( m_bFired == false ) )
|
||
|
{
|
||
|
DelayedFire();
|
||
|
}
|
||
|
|
||
|
BaseClass::ItemPostFrame();
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeaponCGuard::DelayedFire( void )
|
||
|
{
|
||
|
if ( m_flChargeTime >= gpGlobals->curtime )
|
||
|
return;
|
||
|
|
||
|
if ( m_bFired )
|
||
|
return;
|
||
|
|
||
|
m_bFired = true;
|
||
|
|
||
|
// Only the player fires this way so we can cast
|
||
|
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
|
||
|
|
||
|
if ( pPlayer == NULL )
|
||
|
return;
|
||
|
|
||
|
// Abort here to handle burst and auto fire modes
|
||
|
if ( (GetMaxClip1() != -1 && m_iClip1 == 0) || (GetMaxClip1() == -1 && !pPlayer->GetAmmoCount(m_iPrimaryAmmoType) ) )
|
||
|
return;
|
||
|
|
||
|
// MUST call sound before removing a round from the clip of a CMachineGun
|
||
|
WeaponSound(SINGLE);
|
||
|
|
||
|
pPlayer->DoMuzzleFlash();
|
||
|
|
||
|
// To make the firing framerate independent, we may have to fire more than one bullet here on low-framerate systems,
|
||
|
// especially if the weapon we're firing has a really fast rate of fire.
|
||
|
if ( GetSequence() != SelectWeightedSequence( ACT_VM_PRIMARYATTACK ) )
|
||
|
{
|
||
|
m_flNextPrimaryAttack = gpGlobals->curtime;
|
||
|
}
|
||
|
|
||
|
// Make sure we don't fire more than the amount in the clip, if this weapon uses clips
|
||
|
if ( UsesClipsForAmmo1() )
|
||
|
{
|
||
|
m_iClip1 = m_iClip1 - 1;
|
||
|
}
|
||
|
|
||
|
// Fire the bullets
|
||
|
Vector vecSrc = pPlayer->Weapon_ShootPosition( );
|
||
|
Vector vecAiming = pPlayer->GetRadialAutoVector( NEW_AUTOAIM_RADIUS, NEW_AUTOAIM_DIST );
|
||
|
|
||
|
//Factor in the view kick
|
||
|
AddViewKick();
|
||
|
|
||
|
Vector impactPoint = vecSrc + ( vecAiming * MAX_TRACE_LENGTH );
|
||
|
|
||
|
trace_t tr;
|
||
|
UTIL_TraceHull( vecSrc, impactPoint, Vector( -2, -2, -2 ), Vector( 2, 2, 2 ), MASK_SHOT, pPlayer, COLLISION_GROUP_NONE, &tr );
|
||
|
|
||
|
CreateConcussiveBlast( tr.endpos, tr.plane.normal, this, 1.0 );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeaponCGuard::AddViewKick( void )
|
||
|
{
|
||
|
//Get the view kick
|
||
|
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
|
||
|
|
||
|
if ( pPlayer == NULL )
|
||
|
return;
|
||
|
|
||
|
color32 white = {255, 255, 255, 64};
|
||
|
UTIL_ScreenFade( pPlayer, white, 0.1, 0, FFADE_IN );
|
||
|
|
||
|
//Disorient the player
|
||
|
QAngle angles = pPlayer->GetLocalAngles();
|
||
|
|
||
|
angles.x += random->RandomInt( -5, 5 );
|
||
|
angles.y += random->RandomInt( -8, 8 );
|
||
|
angles.z = 0.0f;
|
||
|
|
||
|
SetLocalAngles( angles );
|
||
|
|
||
|
pPlayer->SnapEyeAngles( angles );
|
||
|
|
||
|
pPlayer->ViewPunch( QAngle( random->RandomInt( -8, -12 ), random->RandomInt( -2, 2 ), random->RandomInt( -8, 8 ) ) );
|
||
|
}
|
||
|
|
||
|
#endif
|