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.

224 lines
5.0 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "sdk_fx_shared.h"
  8. #include "weapon_sdkbase.h"
  9. #ifndef CLIENT_DLL
  10. #include "ilagcompensationmanager.h"
  11. #endif
  12. #ifdef CLIENT_DLL
  13. #include "fx_impact.h"
  14. #include "c_sdk_player.h"
  15. // this is a cheap ripoff from CBaseCombatWeapon::WeaponSound():
  16. void FX_WeaponSound(
  17. int iPlayerIndex,
  18. WeaponSound_t sound_type,
  19. const Vector &vOrigin,
  20. CSDKWeaponInfo *pWeaponInfo )
  21. {
  22. // If we have some sounds from the weapon classname.txt file, play a random one of them
  23. const char *shootsound = pWeaponInfo->aShootSounds[ sound_type ];
  24. if ( !shootsound || !shootsound[0] )
  25. return;
  26. CBroadcastRecipientFilter filter; // this is client side only
  27. if ( !te->CanPredict() )
  28. return;
  29. CBaseEntity::EmitSound( filter, iPlayerIndex, shootsound, &vOrigin );
  30. }
  31. class CGroupedSound
  32. {
  33. public:
  34. string_t m_SoundName;
  35. Vector m_vPos;
  36. };
  37. CUtlVector<CGroupedSound> g_GroupedSounds;
  38. // Called by the ImpactSound function.
  39. void ShotgunImpactSoundGroup( const char *pSoundName, const Vector &vEndPos )
  40. {
  41. // Don't play the sound if it's too close to another impact sound.
  42. for ( int i=0; i < g_GroupedSounds.Count(); i++ )
  43. {
  44. CGroupedSound *pSound = &g_GroupedSounds[i];
  45. if ( vEndPos.DistToSqr( pSound->m_vPos ) < 300*300 )
  46. {
  47. if ( Q_stricmp( pSound->m_SoundName, pSoundName ) == 0 )
  48. return;
  49. }
  50. }
  51. // Ok, play the sound and add it to the list.
  52. CLocalPlayerFilter filter;
  53. C_BaseEntity::EmitSound( filter, NULL, pSoundName, &vEndPos );
  54. int j = g_GroupedSounds.AddToTail();
  55. g_GroupedSounds[j].m_SoundName = pSoundName;
  56. g_GroupedSounds[j].m_vPos = vEndPos;
  57. }
  58. void StartGroupingSounds()
  59. {
  60. Assert( g_GroupedSounds.Count() == 0 );
  61. SetImpactSoundRoute( ShotgunImpactSoundGroup );
  62. }
  63. void EndGroupingSounds()
  64. {
  65. g_GroupedSounds.Purge();
  66. SetImpactSoundRoute( NULL );
  67. }
  68. #else
  69. #include "sdk_player.h"
  70. #include "te_firebullets.h"
  71. // Server doesn't play sounds anyway.
  72. void StartGroupingSounds() {}
  73. void EndGroupingSounds() {}
  74. void FX_WeaponSound ( int iPlayerIndex,
  75. WeaponSound_t sound_type,
  76. const Vector &vOrigin,
  77. CSDKWeaponInfo *pWeaponInfo ) {};
  78. #endif
  79. // This runs on both the client and the server.
  80. // On the server, it only does the damage calculations.
  81. // On the client, it does all the effects.
  82. void FX_FireBullets(
  83. int iPlayerIndex,
  84. const Vector &vOrigin,
  85. const QAngle &vAngles,
  86. int iWeaponID,
  87. int iMode,
  88. int iSeed,
  89. float flSpread
  90. )
  91. {
  92. bool bDoEffects = true;
  93. #ifdef CLIENT_DLL
  94. C_SDKPlayer *pPlayer = ToSDKPlayer( ClientEntityList().GetBaseEntity( iPlayerIndex ) );
  95. #else
  96. CSDKPlayer *pPlayer = ToSDKPlayer( UTIL_PlayerByIndex( iPlayerIndex) );
  97. #endif
  98. const char * weaponAlias = WeaponIDToAlias( iWeaponID );
  99. if ( !weaponAlias )
  100. {
  101. DevMsg("FX_FireBullets: weapon alias for ID %i not found\n", iWeaponID );
  102. return;
  103. }
  104. char wpnName[128];
  105. Q_snprintf( wpnName, sizeof( wpnName ), "weapon_%s", weaponAlias );
  106. WEAPON_FILE_INFO_HANDLE hWpnInfo = LookupWeaponInfoSlot( wpnName );
  107. if ( hWpnInfo == GetInvalidWeaponInfoHandle() )
  108. {
  109. DevMsg("FX_FireBullets: LookupWeaponInfoSlot failed for weapon %s\n", wpnName );
  110. return;
  111. }
  112. CSDKWeaponInfo *pWeaponInfo = static_cast< CSDKWeaponInfo* >( GetFileWeaponInfoFromHandle( hWpnInfo ) );
  113. #ifdef CLIENT_DLL
  114. // Do the firing animation event.
  115. if ( pPlayer && !pPlayer->IsDormant() )
  116. {
  117. if ( iMode == Primary_Mode )
  118. pPlayer->m_PlayerAnimState->DoAnimationEvent( PLAYERANIMEVENT_FIRE_GUN_PRIMARY );
  119. else
  120. pPlayer->m_PlayerAnimState->DoAnimationEvent( PLAYERANIMEVENT_FIRE_GUN_SECONDARY );
  121. }
  122. #else
  123. // if this is server code, send the effect over to client as temp entity
  124. // Dispatch one message for all the bullet impacts and sounds.
  125. TE_FireBullets(
  126. iPlayerIndex,
  127. vOrigin,
  128. vAngles,
  129. iWeaponID,
  130. iMode,
  131. iSeed,
  132. flSpread
  133. );
  134. bDoEffects = false; // no effects on server
  135. #endif
  136. iSeed++;
  137. int iDamage = pWeaponInfo->m_iDamage;
  138. int iAmmoType = pWeaponInfo->iAmmoType;
  139. WeaponSound_t sound_type = SINGLE;
  140. if ( bDoEffects)
  141. {
  142. FX_WeaponSound( iPlayerIndex, sound_type, vOrigin, pWeaponInfo );
  143. }
  144. // Fire bullets, calculate impacts & effects
  145. if ( !pPlayer )
  146. return;
  147. StartGroupingSounds();
  148. #if !defined (CLIENT_DLL)
  149. // Move other players back to history positions based on local player's lag
  150. lagcompensation->StartLagCompensation( pPlayer, pPlayer->GetCurrentCommand() );
  151. #endif
  152. for ( int iBullet=0; iBullet < pWeaponInfo->m_iBullets; iBullet++ )
  153. {
  154. RandomSeed( iSeed ); // init random system with this seed
  155. // Get circular gaussian spread.
  156. float x, y;
  157. x = RandomFloat( -0.5, 0.5 ) + RandomFloat( -0.5, 0.5 );
  158. y = RandomFloat( -0.5, 0.5 ) + RandomFloat( -0.5, 0.5 );
  159. iSeed++; // use new seed for next bullet
  160. pPlayer->FireBullet(
  161. vOrigin,
  162. vAngles,
  163. flSpread,
  164. iDamage,
  165. iAmmoType,
  166. pPlayer,
  167. bDoEffects,
  168. x,y );
  169. }
  170. #if !defined (CLIENT_DLL)
  171. lagcompensation->FinishLagCompensation( pPlayer );
  172. #endif
  173. EndGroupingSounds();
  174. }