diff options
Diffstat (limited to 'game/server/hl2/weapon_cguard.cpp')
| -rw-r--r-- | game/server/hl2/weapon_cguard.cpp | 481 |
1 files changed, 481 insertions, 0 deletions
diff --git a/game/server/hl2/weapon_cguard.cpp b/game/server/hl2/weapon_cguard.cpp new file mode 100644 index 0000000..572a90c --- /dev/null +++ b/game/server/hl2/weapon_cguard.cpp @@ -0,0 +1,481 @@ +//========= 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 |