Team Fortress 2 Source Code as on 22/4/2020
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.

481 lines
13 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Combine guard gun, strider destroyer
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "basehlcombatweapon.h"
  9. #include "basecombatcharacter.h"
  10. #include "player.h"
  11. #include "grenade_ar2.h"
  12. #include "soundent.h"
  13. #include "explode.h"
  14. #include "shake.h"
  15. #include "energy_wave.h"
  16. #include "te_particlesystem.h"
  17. #include "ndebugoverlay.h"
  18. // memdbgon must be the last include file in a .cpp file!!!
  19. #include "tier0/memdbgon.h"
  20. //Concussive explosion entity
  21. class CTEConcussiveExplosion : public CTEParticleSystem
  22. {
  23. public:
  24. DECLARE_CLASS( CTEConcussiveExplosion, CTEParticleSystem );
  25. DECLARE_SERVERCLASS();
  26. CTEConcussiveExplosion( const char *name );
  27. virtual ~CTEConcussiveExplosion( void );
  28. CNetworkVector( m_vecNormal );
  29. CNetworkVar( float, m_flScale );
  30. CNetworkVar( int, m_nRadius );
  31. CNetworkVar( int, m_nMagnitude );
  32. };
  33. IMPLEMENT_SERVERCLASS_ST( CTEConcussiveExplosion, DT_TEConcussiveExplosion )
  34. SendPropVector( SENDINFO(m_vecNormal), -1, SPROP_COORD ),
  35. SendPropFloat( SENDINFO(m_flScale), 0, SPROP_NOSCALE ),
  36. SendPropInt( SENDINFO(m_nRadius), 32, SPROP_UNSIGNED ),
  37. SendPropInt( SENDINFO(m_nMagnitude), 32, SPROP_UNSIGNED ),
  38. END_SEND_TABLE()
  39. //-----------------------------------------------------------------------------
  40. // Purpose: Constructor
  41. //-----------------------------------------------------------------------------
  42. CTEConcussiveExplosion::CTEConcussiveExplosion( const char *name ) : BaseClass( name )
  43. {
  44. m_nRadius = 0;
  45. m_nMagnitude = 0;
  46. m_flScale = 0.0f;
  47. m_vecNormal.Init();
  48. }
  49. //-----------------------------------------------------------------------------
  50. // Purpose: Destructor
  51. //-----------------------------------------------------------------------------
  52. CTEConcussiveExplosion::~CTEConcussiveExplosion( void )
  53. {
  54. }
  55. // Singleton to fire TEExplosion objects
  56. static CTEConcussiveExplosion g_TEConcussiveExplosion( "ConcussiveExplosion" );
  57. void TE_ConcussiveExplosion( IRecipientFilter& filter, float delay,
  58. const Vector* pos, float scale, int radius, int magnitude, const Vector* normal )
  59. {
  60. g_TEConcussiveExplosion.m_vecOrigin = *pos;
  61. g_TEConcussiveExplosion.m_flScale = scale;
  62. g_TEConcussiveExplosion.m_nRadius = radius;
  63. g_TEConcussiveExplosion.m_nMagnitude = magnitude;
  64. if ( normal )
  65. g_TEConcussiveExplosion.m_vecNormal = *normal;
  66. else
  67. g_TEConcussiveExplosion.m_vecNormal = Vector(0,0,1);
  68. // Send it over the wire
  69. g_TEConcussiveExplosion.Create( filter, delay );
  70. }
  71. //Temp ent for the blast
  72. class CConcussiveBlast : public CBaseEntity
  73. {
  74. DECLARE_DATADESC();
  75. public:
  76. DECLARE_CLASS( CConcussiveBlast, CBaseEntity );
  77. int m_spriteTexture;
  78. CConcussiveBlast( void ) {}
  79. //-----------------------------------------------------------------------------
  80. // Purpose:
  81. // Output :
  82. //-----------------------------------------------------------------------------
  83. void Precache( void )
  84. {
  85. m_spriteTexture = PrecacheModel( "sprites/lgtning.vmt" );
  86. BaseClass::Precache();
  87. }
  88. //-----------------------------------------------------------------------------
  89. // Purpose:
  90. // Output :
  91. //-----------------------------------------------------------------------------
  92. void Explode( float magnitude )
  93. {
  94. //Create a concussive explosion
  95. CPASFilter filter( GetAbsOrigin() );
  96. Vector vecForward;
  97. AngleVectors( GetAbsAngles(), &vecForward );
  98. TE_ConcussiveExplosion( filter, 0.0,
  99. &GetAbsOrigin(),//position
  100. 1.0f, //scale
  101. 256*magnitude, //radius
  102. 175*magnitude, //magnitude
  103. &vecForward ); //normal
  104. int colorRamp = random->RandomInt( 128, 255 );
  105. //Shockring
  106. CBroadcastRecipientFilter filter2;
  107. te->BeamRingPoint( filter2, 0,
  108. GetAbsOrigin(), //origin
  109. 16, //start radius
  110. 300*magnitude, //end radius
  111. m_spriteTexture, //texture
  112. 0, //halo index
  113. 0, //start frame
  114. 2, //framerate
  115. 0.3f, //life
  116. 128, //width
  117. 16, //spread
  118. 0, //amplitude
  119. colorRamp, //r
  120. colorRamp, //g
  121. 255, //g
  122. 24, //a
  123. 128 //speed
  124. );
  125. //Do the radius damage
  126. RadiusDamage( CTakeDamageInfo( this, GetOwnerEntity(), 200, DMG_BLAST|DMG_DISSOLVE ), GetAbsOrigin(), 256, CLASS_NONE, NULL );
  127. UTIL_Remove( this );
  128. }
  129. };
  130. LINK_ENTITY_TO_CLASS( concussiveblast, CConcussiveBlast );
  131. //---------------------------------------------------------
  132. // Save/Restore
  133. //---------------------------------------------------------
  134. BEGIN_DATADESC( CConcussiveBlast )
  135. // DEFINE_FIELD( m_spriteTexture, FIELD_INTEGER ),
  136. END_DATADESC()
  137. //-----------------------------------------------------------------------------
  138. // Purpose: Create a concussive blast entity and detonate it
  139. //-----------------------------------------------------------------------------
  140. void CreateConcussiveBlast( const Vector &origin, const Vector &surfaceNormal, CBaseEntity *pOwner, float magnitude )
  141. {
  142. QAngle angles;
  143. VectorAngles( surfaceNormal, angles );
  144. CConcussiveBlast *pBlast = (CConcussiveBlast *) CBaseEntity::Create( "concussiveblast", origin, angles, pOwner );
  145. if ( pBlast )
  146. {
  147. pBlast->Explode( magnitude );
  148. }
  149. }
  150. // Combine Guard weapon
  151. #if 0
  152. class CWeaponCGuard : public CBaseHLCombatWeapon
  153. {
  154. DECLARE_DATADESC();
  155. public:
  156. DECLARE_CLASS( CWeaponCGuard, CBaseHLCombatWeapon );
  157. DECLARE_SERVERCLASS();
  158. CWeaponCGuard( void );
  159. void Precache( void );
  160. void PrimaryAttack( void );
  161. void AddViewKick( void );
  162. void DelayedFire( void );
  163. void ItemPostFrame( void );
  164. void AlertTargets( void );
  165. void UpdateLasers( void );
  166. int CapabilitiesGet( void ) { return bits_CAP_WEAPON_RANGE_ATTACK1; }
  167. DECLARE_ACTTABLE();
  168. protected:
  169. float m_flChargeTime;
  170. bool m_bFired;
  171. int m_beamIndex;
  172. int m_haloIndex;
  173. };
  174. IMPLEMENT_SERVERCLASS_ST(CWeaponCGuard, DT_WeaponCGuard)
  175. END_SEND_TABLE()
  176. LINK_ENTITY_TO_CLASS( weapon_cguard, CWeaponCGuard );
  177. PRECACHE_WEAPON_REGISTER( weapon_cguard );
  178. //---------------------------------------------------------
  179. // Save/Restore
  180. //---------------------------------------------------------
  181. BEGIN_DATADESC( CWeaponCGuard )
  182. DEFINE_FIELD( m_flChargeTime, FIELD_TIME ),
  183. DEFINE_FIELD( m_bFired, FIELD_BOOLEAN ),
  184. // DEFINE_FIELD( m_beamIndex, FIELD_INTEGER ),
  185. // DEFINE_FIELD( m_haloIndex, FIELD_INTEGER ),
  186. END_DATADESC()
  187. //-----------------------------------------------------------------------------
  188. // Maps base activities to weapons-specific ones so our characters do the right things.
  189. //-----------------------------------------------------------------------------
  190. acttable_t CWeaponCGuard::m_acttable[] =
  191. {
  192. { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SNIPER_RIFLE, true }
  193. };
  194. IMPLEMENT_ACTTABLE( CWeaponCGuard );
  195. //-----------------------------------------------------------------------------
  196. // Constructor
  197. //-----------------------------------------------------------------------------
  198. CWeaponCGuard::CWeaponCGuard( void )
  199. {
  200. m_flNextPrimaryAttack = gpGlobals->curtime;
  201. m_flChargeTime = gpGlobals->curtime;
  202. m_bFired = true;
  203. }
  204. //-----------------------------------------------------------------------------
  205. // Purpose:
  206. //-----------------------------------------------------------------------------
  207. void CWeaponCGuard::Precache( void )
  208. {
  209. UTIL_PrecacheOther( "concussiveblast" );
  210. m_beamIndex = PrecacheModel( "sprites/bluelaser1.vmt" );
  211. m_haloIndex = PrecacheModel( "sprites/blueshaft1.vmt" );
  212. BaseClass::Precache();
  213. }
  214. //-----------------------------------------------------------------------------
  215. // Purpose:
  216. //-----------------------------------------------------------------------------
  217. void CWeaponCGuard::AlertTargets( void )
  218. {
  219. CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
  220. if ( pPlayer == NULL )
  221. return;
  222. // Fire the bullets
  223. Vector vecSrc = pPlayer->Weapon_ShootPosition( );
  224. Vector vecAiming = pPlayer->GetRadialAutoVector( NEW_AUTOAIM_RADIUS, NEW_AUTOAIM_DIST );
  225. Vector impactPoint = vecSrc + ( vecAiming * MAX_TRACE_LENGTH );
  226. trace_t tr;
  227. UTIL_TraceLine( vecSrc, impactPoint, MASK_SHOT, pPlayer, COLLISION_GROUP_NONE, &tr );
  228. if ( (vecSrc-tr.endpos).Length() > 1024 )
  229. return;
  230. CSoundEnt::InsertSound( SOUND_DANGER, tr.endpos, 128, 0.5f );
  231. }
  232. //-----------------------------------------------------------------------------
  233. // Purpose:
  234. //-----------------------------------------------------------------------------
  235. void CWeaponCGuard::UpdateLasers( void )
  236. {
  237. //Only update the lasers whilst charging
  238. if ( ( m_flChargeTime < gpGlobals->curtime ) || ( m_bFired ) )
  239. return;
  240. Vector start, end, v_forward, v_right, v_up;
  241. CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
  242. if ( pPlayer == NULL )
  243. return;
  244. pPlayer->GetVectors( &v_forward, &v_right, &v_up );
  245. //Get the position of the laser
  246. start = pPlayer->Weapon_ShootPosition( );
  247. start += ( v_forward * 8.0f ) + ( v_right * 3.0f ) + ( v_up * -2.0f );
  248. end = start + ( v_forward * MAX_TRACE_LENGTH );
  249. float angleOffset = ( 1.0f - ( m_flChargeTime - gpGlobals->curtime ) ) / 1.0f;
  250. Vector offset[4];
  251. offset[0] = Vector( 0.0f, 0.5f, -0.5f );
  252. offset[1] = Vector( 0.0f, 0.5f, 0.5f );
  253. offset[2] = Vector( 0.0f, -0.5f, -0.5f );
  254. offset[3] = Vector( 0.0f, -0.5f, 0.5f );
  255. QAngle v_ang;
  256. Vector v_dir;
  257. angleOffset *= 2.0f;
  258. if ( angleOffset > 1.0f )
  259. angleOffset = 1.0f;
  260. for ( int i = 0; i < 4; i++ )
  261. {
  262. Vector ofs = start + ( v_forward * offset[i][0] ) + ( v_right * offset[i][1] ) + ( v_up * offset[i][2] );
  263. float hScale = ( offset[i][1] <= 0.0f ) ? 1.0f : -1.0f;
  264. float vScale = ( offset[i][2] <= 0.0f ) ? 1.0f : -1.0f;
  265. VectorAngles( v_forward, v_ang );
  266. v_ang[PITCH] = UTIL_AngleMod( v_ang[PITCH] + ( (1.0f-angleOffset) * 15.0f * vScale ) );
  267. v_ang[YAW] = UTIL_AngleMod( v_ang[YAW] + ( (1.0f-angleOffset) * 15.0f * hScale ) );
  268. AngleVectors( v_ang, &v_dir );
  269. trace_t tr;
  270. UTIL_TraceLine( ofs, ofs + ( v_dir * MAX_TRACE_LENGTH ), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr );
  271. UTIL_Beam( ofs, tr.endpos, m_beamIndex, 0, 0, 2.0f, 0.1f, 2, 0, 1, 0, 255, 255, 255, 32, 100 );
  272. UTIL_Beam( ofs, tr.endpos, m_haloIndex, 0, 0, 2.0f, 0.1f, 4, 0, 1, 16, 255, 255, 255, 8, 100 );
  273. }
  274. }
  275. //-----------------------------------------------------------------------------
  276. // Purpose:
  277. //-----------------------------------------------------------------------------
  278. void CWeaponCGuard::PrimaryAttack( void )
  279. {
  280. if ( m_flChargeTime >= gpGlobals->curtime )
  281. return;
  282. AlertTargets();
  283. WeaponSound( SPECIAL1 );
  284. //UTIL_ScreenShake( GetAbsOrigin(), 10.0f, 100.0f, 2.0f, 128, SHAKE_START, false );
  285. m_flChargeTime = gpGlobals->curtime + 1.0f;
  286. m_bFired = false;
  287. }
  288. //-----------------------------------------------------------------------------
  289. // Purpose:
  290. //-----------------------------------------------------------------------------
  291. void CWeaponCGuard::ItemPostFrame( void )
  292. {
  293. //FIXME: UpdateLasers();
  294. if ( ( m_flChargeTime < gpGlobals->curtime ) && ( m_bFired == false ) )
  295. {
  296. DelayedFire();
  297. }
  298. BaseClass::ItemPostFrame();
  299. }
  300. //-----------------------------------------------------------------------------
  301. // Purpose:
  302. //-----------------------------------------------------------------------------
  303. void CWeaponCGuard::DelayedFire( void )
  304. {
  305. if ( m_flChargeTime >= gpGlobals->curtime )
  306. return;
  307. if ( m_bFired )
  308. return;
  309. m_bFired = true;
  310. // Only the player fires this way so we can cast
  311. CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
  312. if ( pPlayer == NULL )
  313. return;
  314. // Abort here to handle burst and auto fire modes
  315. if ( (GetMaxClip1() != -1 && m_iClip1 == 0) || (GetMaxClip1() == -1 && !pPlayer->GetAmmoCount(m_iPrimaryAmmoType) ) )
  316. return;
  317. // MUST call sound before removing a round from the clip of a CMachineGun
  318. WeaponSound(SINGLE);
  319. pPlayer->DoMuzzleFlash();
  320. // To make the firing framerate independent, we may have to fire more than one bullet here on low-framerate systems,
  321. // especially if the weapon we're firing has a really fast rate of fire.
  322. if ( GetSequence() != SelectWeightedSequence( ACT_VM_PRIMARYATTACK ) )
  323. {
  324. m_flNextPrimaryAttack = gpGlobals->curtime;
  325. }
  326. // Make sure we don't fire more than the amount in the clip, if this weapon uses clips
  327. if ( UsesClipsForAmmo1() )
  328. {
  329. m_iClip1 = m_iClip1 - 1;
  330. }
  331. // Fire the bullets
  332. Vector vecSrc = pPlayer->Weapon_ShootPosition( );
  333. Vector vecAiming = pPlayer->GetRadialAutoVector( NEW_AUTOAIM_RADIUS, NEW_AUTOAIM_DIST );
  334. //Factor in the view kick
  335. AddViewKick();
  336. Vector impactPoint = vecSrc + ( vecAiming * MAX_TRACE_LENGTH );
  337. trace_t tr;
  338. UTIL_TraceHull( vecSrc, impactPoint, Vector( -2, -2, -2 ), Vector( 2, 2, 2 ), MASK_SHOT, pPlayer, COLLISION_GROUP_NONE, &tr );
  339. CreateConcussiveBlast( tr.endpos, tr.plane.normal, this, 1.0 );
  340. }
  341. //-----------------------------------------------------------------------------
  342. // Purpose:
  343. //-----------------------------------------------------------------------------
  344. void CWeaponCGuard::AddViewKick( void )
  345. {
  346. //Get the view kick
  347. CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
  348. if ( pPlayer == NULL )
  349. return;
  350. color32 white = {255, 255, 255, 64};
  351. UTIL_ScreenFade( pPlayer, white, 0.1, 0, FFADE_IN );
  352. //Disorient the player
  353. QAngle angles = pPlayer->GetLocalAngles();
  354. angles.x += random->RandomInt( -5, 5 );
  355. angles.y += random->RandomInt( -8, 8 );
  356. angles.z = 0.0f;
  357. SetLocalAngles( angles );
  358. pPlayer->SnapEyeAngles( angles );
  359. pPlayer->ViewPunch( QAngle( random->RandomInt( -8, -12 ), random->RandomInt( -2, 2 ), random->RandomInt( -8, 8 ) ) );
  360. }
  361. #endif