Counter Strike : Global Offensive Source Code
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.

182 lines
5.5 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #ifndef VPHYSICS_SOUND_H
  8. #define VPHYSICS_SOUND_H
  9. #ifdef _WIN32
  10. #pragma once
  11. #endif
  12. #include "SoundEmitterSystem/isoundemittersystembase.h"
  13. namespace physicssound
  14. {
  15. struct impactsound_t
  16. {
  17. void *pGameData;
  18. int entityIndex;
  19. int soundChannel;
  20. float volume;
  21. float impactSpeed;
  22. unsigned short surfaceProps;
  23. unsigned short surfacePropsHit;
  24. Vector origin;
  25. };
  26. // UNDONE: Use a sorted container and sort by volume/distance?
  27. struct soundlist_t
  28. {
  29. CUtlVector<impactsound_t> elements;
  30. impactsound_t &GetElement(int index) { return elements[index]; }
  31. impactsound_t &AddElement() { return elements[elements.AddToTail()]; }
  32. int Count() { return elements.Count(); }
  33. void RemoveAll() { elements.RemoveAll(); }
  34. };
  35. void PlayImpactSounds( soundlist_t &list )
  36. {
  37. for ( int i = list.Count()-1; i >= 0; --i )
  38. {
  39. impactsound_t &sound = list.GetElement(i);
  40. const surfacedata_t *psurf = physprops->GetSurfaceData( sound.surfaceProps );
  41. if ( psurf->sounds.impactHard )
  42. {
  43. const surfacedata_t *pHit = physprops->GetSurfaceData( sound.surfacePropsHit );
  44. unsigned short soundName = psurf->sounds.impactHard;
  45. if ( pHit && psurf->sounds.impactSoft )
  46. {
  47. if ( pHit->audio.hardnessFactor < psurf->audio.hardThreshold ||
  48. (psurf->audio.hardVelocityThreshold > 0 && psurf->audio.hardVelocityThreshold > sound.impactSpeed) )
  49. {
  50. soundName = psurf->sounds.impactSoft;
  51. }
  52. }
  53. const char *pSound = physprops->GetString( soundName );
  54. CSoundParameters params;
  55. if ( !CBaseEntity::GetParametersForSound( pSound, params, NULL ) )
  56. break;
  57. if ( sound.volume > 1 )
  58. sound.volume = 1;
  59. CBroadcastRecipientFilter filter;
  60. // JAY: If this entity gets deleted, the sound comes out at the world origin
  61. // this sounds bad! Play on ent 0 for now.
  62. EmitSound_t ep;
  63. ep.m_nChannel = sound.soundChannel;
  64. ep.m_pSoundName = params.soundname;
  65. ep.m_flVolume = params.volume * sound.volume;
  66. ep.m_SoundLevel = params.soundlevel;
  67. ep.m_nPitch = params.pitch;
  68. ep.m_pOrigin = &sound.origin;
  69. ep.m_hSoundScriptHash = params.m_hSoundScriptHash;
  70. ep.m_nSoundEntryVersion = params.m_nSoundEntryVersion;
  71. CBaseEntity::EmitSound( filter, 0 /*sound.entityIndex*/, ep );
  72. }
  73. }
  74. list.RemoveAll();
  75. }
  76. void AddImpactSound( soundlist_t &list, void *pGameData, int entityIndex, int soundChannel, IPhysicsObject *pObject, int surfaceProps, int surfacePropsHit, float volume, float impactSpeed )
  77. {
  78. impactSpeed += 1e-4;
  79. for ( int i = list.Count()-1; i >= 0; --i )
  80. {
  81. impactsound_t &sound = list.GetElement(i);
  82. // UNDONE: Compare entity or channel somehow?
  83. // UNDONE: Doing one slot per entity is too noisy. So now we use one slot per material
  84. // heuristic - after 4 impacts sounds in one frame, start merging everything
  85. if ( surfaceProps == sound.surfaceProps || list.Count() > 4 )
  86. {
  87. // UNDONE: Store instance volume separate from aggregate volume and compare that?
  88. if ( volume > sound.volume )
  89. {
  90. pObject->GetPosition( &sound.origin, NULL );
  91. sound.pGameData = pGameData;
  92. sound.entityIndex = entityIndex;
  93. sound.soundChannel = soundChannel;
  94. sound.surfacePropsHit = surfacePropsHit;
  95. }
  96. sound.volume += volume;
  97. sound.impactSpeed = MAX(impactSpeed,sound.impactSpeed);
  98. return;
  99. }
  100. }
  101. impactsound_t &sound = list.AddElement();
  102. sound.pGameData = pGameData;
  103. sound.entityIndex = entityIndex;
  104. sound.soundChannel = soundChannel;
  105. pObject->GetPosition( &sound.origin, NULL );
  106. sound.surfaceProps = surfaceProps;
  107. sound.surfacePropsHit = surfacePropsHit;
  108. sound.volume = volume;
  109. sound.impactSpeed = impactSpeed;
  110. }
  111. struct breaksound_t
  112. {
  113. Vector origin;
  114. int surfacePropsBreak;
  115. };
  116. void AddBreakSound( CUtlVector<breaksound_t> &list, const Vector &origin, unsigned short surfaceProps )
  117. {
  118. const surfacedata_t *psurf = physprops->GetSurfaceData( surfaceProps );
  119. if ( !psurf->sounds.breakSound )
  120. return;
  121. for ( int i = list.Count()-1; i >= 0; --i )
  122. {
  123. breaksound_t &sound = list.Element(i);
  124. // Allow 3 break sounds before you start merging anything.
  125. if ( list.Count() > 2 && surfaceProps == sound.surfacePropsBreak )
  126. {
  127. sound.origin = (sound.origin + origin) * 0.5f;
  128. return;
  129. }
  130. }
  131. breaksound_t sound;
  132. sound.origin = origin;
  133. sound.surfacePropsBreak = surfaceProps;
  134. list.AddToTail(sound);
  135. }
  136. void PlayBreakSounds( CUtlVector<breaksound_t> &list )
  137. {
  138. for ( int i = list.Count()-1; i >= 0; --i )
  139. {
  140. breaksound_t &sound = list.Element(i);
  141. const surfacedata_t *psurf = physprops->GetSurfaceData( sound.surfacePropsBreak );
  142. const char *pSound = physprops->GetString( psurf->sounds.breakSound );
  143. CSoundParameters params;
  144. if ( !CBaseEntity::GetParametersForSound( pSound, params, NULL ) )
  145. return;
  146. // Play from the world, because the entity is breaking, so it'll be destroyed soon
  147. CBroadcastRecipientFilter filter;
  148. EmitSound_t ep;
  149. ep.m_nChannel = CHAN_STATIC;
  150. ep.m_pSoundName = params.soundname;
  151. ep.m_flVolume = params.volume;
  152. ep.m_SoundLevel = params.soundlevel;
  153. ep.m_nPitch = params.pitch;
  154. ep.m_pOrigin = &sound.origin;
  155. ep.m_hSoundScriptHash = params.m_hSoundScriptHash;
  156. ep.m_nSoundEntryVersion = params.m_nSoundEntryVersion;
  157. CBaseEntity::EmitSound( filter, 0 /*sound.entityIndex*/, ep );
  158. }
  159. list.RemoveAll();
  160. }
  161. };
  162. #endif // VPHYSICS_SOUND_H