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.

332 lines
8.8 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Entities relating to in-level sound effects.
  4. //
  5. // env_speaker: used for public address announcements over loudspeakers.
  6. // This tries not to drown out talking NPCs.
  7. //
  8. // env_soundscape: controls what sound script an area uses.
  9. //
  10. //=============================================================================//
  11. #include "cbase.h"
  12. #include "player.h"
  13. #include "mathlib/mathlib.h"
  14. #include "ai_speech.h"
  15. #include "stringregistry.h"
  16. #include "gamerules.h"
  17. #include "game.h"
  18. #include <ctype.h>
  19. #include "entitylist.h"
  20. #include "vstdlib/random.h"
  21. #include "engine/IEngineSound.h"
  22. #include "ndebugoverlay.h"
  23. #include "soundscape.h"
  24. #include "igamesystem.h"
  25. #include "keyvalues.h"
  26. #include "filesystem.h"
  27. #include "ambientgeneric.h"
  28. // memdbgon must be the last include file in a .cpp file!!!
  29. #include "tier0/memdbgon.h"
  30. // =================== ROOM SOUND FX ==========================================
  31. // ==================== SENTENCE GROUPS, UTILITY FUNCTIONS ======================================
  32. int fSentencesInit = false;
  33. // ===================== SENTENCE GROUPS, MAIN ROUTINES ========================
  34. // given sentence group index, play random sentence for given entity.
  35. // returns sentenceIndex - which sentence was picked
  36. // Ipick is only needed if you plan on stopping the sound before playback is done (see SENTENCEG_Stop).
  37. // sentenceIndex can be used to find the name/length of the sentence
  38. int SENTENCEG_PlayRndI(edict_t *entity, int isentenceg,
  39. float volume, soundlevel_t soundlevel, int flags, int pitch)
  40. {
  41. char name[64];
  42. int ipick;
  43. if (!fSentencesInit)
  44. return -1;
  45. name[0] = 0;
  46. ipick = engine->SentenceGroupPick( isentenceg, name, sizeof( name ) );
  47. if (ipick > 0 && name)
  48. {
  49. int sentenceIndex = SENTENCEG_Lookup( name );
  50. CPASAttenuationFilter filter( GetContainingEntity( entity ), soundlevel );
  51. CBaseEntity::EmitSentenceByIndex( filter, ENTINDEX(entity), CHAN_VOICE, sentenceIndex, volume, soundlevel, flags, pitch );
  52. return sentenceIndex;
  53. }
  54. return -1;
  55. }
  56. //-----------------------------------------------------------------------------
  57. // Picks a sentence, but doesn't play it
  58. //-----------------------------------------------------------------------------
  59. int SENTENCEG_PickRndSz(const char *szgroupname)
  60. {
  61. char name[64];
  62. int ipick;
  63. int isentenceg;
  64. if (!fSentencesInit)
  65. return -1;
  66. name[0] = 0;
  67. isentenceg = engine->SentenceGroupIndexFromName(szgroupname);
  68. if (isentenceg < 0)
  69. {
  70. Warning( "No such sentence group %s\n", szgroupname );
  71. return -1;
  72. }
  73. ipick = engine->SentenceGroupPick(isentenceg, name, sizeof( name ));
  74. if (ipick >= 0 && name[0])
  75. {
  76. return SENTENCEG_Lookup( name );
  77. }
  78. return -1;
  79. }
  80. //-----------------------------------------------------------------------------
  81. // Plays a sentence by sentence index
  82. //-----------------------------------------------------------------------------
  83. void SENTENCEG_PlaySentenceIndex( edict_t *entity, int iSentenceIndex, float volume, soundlevel_t soundlevel, int flags, int pitch )
  84. {
  85. if ( iSentenceIndex >= 0 )
  86. {
  87. CPASAttenuationFilter filter( GetContainingEntity( entity ), soundlevel );
  88. CBaseEntity::EmitSentenceByIndex( filter, ENTINDEX(entity), CHAN_VOICE, iSentenceIndex, volume, soundlevel, flags, pitch );
  89. }
  90. }
  91. int SENTENCEG_PlayRndSz(edict_t *entity, const char *szgroupname,
  92. float volume, soundlevel_t soundlevel, int flags, int pitch)
  93. {
  94. char name[64];
  95. int ipick;
  96. int isentenceg;
  97. if (!fSentencesInit)
  98. return -1;
  99. name[0] = 0;
  100. isentenceg = engine->SentenceGroupIndexFromName(szgroupname);
  101. if (isentenceg < 0)
  102. {
  103. Warning( "No such sentence group %s\n", szgroupname );
  104. return -1;
  105. }
  106. ipick = engine->SentenceGroupPick(isentenceg, name, sizeof( name ));
  107. if (ipick >= 0 && name[0])
  108. {
  109. int sentenceIndex = SENTENCEG_Lookup( name );
  110. CPASAttenuationFilter filter( GetContainingEntity( entity ), soundlevel );
  111. CBaseEntity::EmitSentenceByIndex( filter, ENTINDEX(entity), CHAN_VOICE, sentenceIndex, volume, soundlevel, flags, pitch );
  112. return sentenceIndex;
  113. }
  114. return -1;
  115. }
  116. // play sentences in sequential order from sentence group. Reset after last sentence.
  117. int SENTENCEG_PlaySequentialSz(edict_t *entity, const char *szgroupname,
  118. float volume, soundlevel_t soundlevel, int flags, int pitch, int ipick, int freset)
  119. {
  120. char name[64];
  121. int ipicknext;
  122. int isentenceg;
  123. if (!fSentencesInit)
  124. return -1;
  125. name[0] = 0;
  126. isentenceg = engine->SentenceGroupIndexFromName(szgroupname);
  127. if (isentenceg < 0)
  128. return -1;
  129. ipicknext = engine->SentenceGroupPickSequential(isentenceg, name, sizeof( name ), ipick, freset);
  130. if (ipicknext >= 0 && name[0])
  131. {
  132. int sentenceIndex = SENTENCEG_Lookup( name );
  133. CPASAttenuationFilter filter( GetContainingEntity( entity ), soundlevel );
  134. CBaseEntity::EmitSentenceByIndex( filter, ENTINDEX(entity), CHAN_VOICE, sentenceIndex, volume, soundlevel, flags, pitch );
  135. return sentenceIndex;
  136. }
  137. return -1;
  138. }
  139. #if 0
  140. // for this entity, for the given sentence within the sentence group, stop
  141. // the sentence.
  142. void SENTENCEG_Stop(edict_t *entity, int isentenceg, int ipick)
  143. {
  144. char buffer[64];
  145. char sznum[8];
  146. if (!fSentencesInit)
  147. return;
  148. if (isentenceg < 0 || ipick < 0)
  149. return;
  150. Q_snprintf(buffer,sizeof(buffer),"!%s%d", engine->SentenceGroupNameFromIndex( isentenceg ), ipick );
  151. UTIL_StopSound(entity, CHAN_VOICE, buffer);
  152. }
  153. #endif
  154. // open sentences.txt, scan for groups, build rgsentenceg
  155. // Should be called from world spawn, only works on the
  156. // first call and is ignored subsequently.
  157. void SENTENCEG_Init()
  158. {
  159. if (fSentencesInit)
  160. return;
  161. engine->PrecacheSentenceFile( "scripts/sentences.txt" );
  162. fSentencesInit = true;
  163. }
  164. // convert sentence (sample) name to !sentencenum, return !sentencenum
  165. int SENTENCEG_Lookup(const char *sample)
  166. {
  167. return engine->SentenceIndexFromName( sample + 1 );
  168. }
  169. int SENTENCEG_GetIndex(const char *szrootname)
  170. {
  171. return engine->SentenceGroupIndexFromName( szrootname );
  172. }
  173. void UTIL_RestartAmbientSounds( void )
  174. {
  175. CAmbientGeneric *pAmbient = NULL;
  176. while ( ( pAmbient = (CAmbientGeneric*) gEntList.FindEntityByClassname( pAmbient, "ambient_generic" ) ) != NULL )
  177. {
  178. if (pAmbient->m_fActive )
  179. {
  180. if ( strstr( STRING( pAmbient->m_iszSound ), "mp3" ) )
  181. {
  182. pAmbient->SendSound( SND_CHANGE_VOL ); // fake a change, so we don't create 2 sounds
  183. }
  184. pAmbient->SendSound( SND_CHANGE_VOL ); // fake a change, so we don't create 2 sounds
  185. }
  186. }
  187. }
  188. // play a specific sentence over the HEV suit speaker - just pass player entity, and !sentencename
  189. void UTIL_EmitSoundSuit(edict_t *entity, const char *sample)
  190. {
  191. float fvol;
  192. int pitch = PITCH_NORM;
  193. fvol = suitvolume.GetFloat();
  194. if (random->RandomInt(0,1))
  195. pitch = random->RandomInt(0,6) + 98;
  196. // If friendlies are talking, reduce the volume of the suit
  197. if ( !g_AIFriendliesTalkSemaphore.IsAvailable( GetContainingEntity( entity ) ) )
  198. {
  199. fvol *= 0.3;
  200. }
  201. if (fvol > 0.05)
  202. {
  203. CPASAttenuationFilter filter( GetContainingEntity( entity ) );
  204. filter.MakeReliable();
  205. EmitSound_t ep;
  206. ep.m_nChannel = CHAN_STATIC;
  207. ep.m_pSoundName = sample;
  208. ep.m_flVolume = fvol;
  209. ep.m_SoundLevel = SNDLVL_NORM;
  210. ep.m_nPitch = pitch;
  211. CBaseEntity::EmitSound( filter, ENTINDEX(entity), ep );
  212. }
  213. }
  214. // play a sentence, randomly selected from the passed in group id, over the HEV suit speaker
  215. int UTIL_EmitGroupIDSuit(edict_t *entity, int isentenceg)
  216. {
  217. float fvol;
  218. int pitch = PITCH_NORM;
  219. int sentenceIndex = -1;
  220. fvol = suitvolume.GetFloat();
  221. if (random->RandomInt(0,1))
  222. pitch = random->RandomInt(0,6) + 98;
  223. // If friendlies are talking, reduce the volume of the suit
  224. if ( !g_AIFriendliesTalkSemaphore.IsAvailable( GetContainingEntity( entity ) ) )
  225. {
  226. fvol *= 0.3;
  227. }
  228. if (fvol > 0.05)
  229. sentenceIndex = SENTENCEG_PlayRndI(entity, isentenceg, fvol, SNDLVL_NORM, 0, pitch);
  230. return sentenceIndex;
  231. }
  232. // play a sentence, randomly selected from the passed in groupname
  233. int UTIL_EmitGroupnameSuit(edict_t *entity, const char *groupname)
  234. {
  235. float fvol;
  236. int pitch = PITCH_NORM;
  237. int sentenceIndex = -1;
  238. fvol = suitvolume.GetFloat();
  239. if (random->RandomInt(0,1))
  240. pitch = random->RandomInt(0,6) + 98;
  241. // If friendlies are talking, reduce the volume of the suit
  242. if ( !g_AIFriendliesTalkSemaphore.IsAvailable( GetContainingEntity( entity ) ) )
  243. {
  244. fvol *= 0.3;
  245. }
  246. if (fvol > 0.05)
  247. sentenceIndex = SENTENCEG_PlayRndSz(entity, groupname, fvol, SNDLVL_NORM, 0, pitch);
  248. return sentenceIndex;
  249. }
  250. // ===================== MATERIAL TYPE DETECTION, MAIN ROUTINES ========================
  251. //
  252. // Used to detect the texture the player is standing on, map the
  253. // texture name to a material type. Play footstep sound based
  254. // on material type.
  255. char TEXTURETYPE_Find( trace_t *ptr )
  256. {
  257. const surfacedata_t *psurfaceData = physprops->GetSurfaceData( ptr->surface.surfaceProps );
  258. return psurfaceData->game.material;
  259. }