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.

222 lines
5.7 KiB

  1. //====== Copyright � 1996-2005, Valve Corporation, All rights reserved. =======
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "cbase.h"
  7. #include "ModelSoundsCache.h"
  8. #include "studio.h"
  9. #include "eventlist.h"
  10. #include "scriptevent.h"
  11. // NOTE: This has to be the last file included!
  12. #include "tier0/memdbgon.h"
  13. extern ISoundEmitterSystemBase *soundemitterbase;
  14. CStudioHdr *ModelSoundsCache_LoadModel( char const *filename );
  15. void ModelSoundsCache_PrecacheScriptSound( const char *soundname );
  16. void ModelSoundsCache_FinishModel( CStudioHdr *hdr );
  17. //-----------------------------------------------------------------------------
  18. // Purpose:
  19. // Input : *hdr -
  20. // Output : static void
  21. //-----------------------------------------------------------------------------
  22. void VerifySequenceIndex( CStudioHdr *pstudiohdr );
  23. // HACK: This must match the #define in cl_animevent.h in the client .dll code!!!
  24. #define CL_EVENT_SOUND 5004
  25. #define CL_EVENT_FOOTSTEP_LEFT 6004
  26. #define CL_EVENT_FOOTSTEP_RIGHT 6005
  27. #define CL_EVENT_MFOOTSTEP_LEFT 6006
  28. #define CL_EVENT_MFOOTSTEP_RIGHT 6007
  29. extern ISoundEmitterSystemBase *soundemitterbase;
  30. CModelSoundsCache::CModelSoundsCache()
  31. {
  32. }
  33. CModelSoundsCache::CModelSoundsCache( const CModelSoundsCache& src )
  34. {
  35. sounds = src.sounds;
  36. }
  37. char const *CModelSoundsCache::GetSoundName( int index )
  38. {
  39. return soundemitterbase->GetSoundName( sounds[ index ] );
  40. }
  41. void CModelSoundsCache::Save( CUtlBuffer& buf )
  42. {
  43. buf.PutShort( sounds.Count() );
  44. for ( int i = 0; i < sounds.Count(); ++i )
  45. {
  46. buf.PutString( GetSoundName( i ) );
  47. }
  48. }
  49. void CModelSoundsCache::Restore( CUtlBuffer& buf )
  50. {
  51. MEM_ALLOC_CREDIT();
  52. unsigned short c;
  53. c = (unsigned short)buf.GetShort();
  54. for ( int i = 0; i < c; ++i )
  55. {
  56. char soundname[ 512 ];
  57. buf.GetString( soundname, sizeof( soundname ) );
  58. int idx = soundemitterbase->GetSoundIndex( soundname );
  59. if ( soundemitterbase->IsValidIndex( idx ) )
  60. {
  61. if ( sounds.Find( idx ) == sounds.InvalidIndex() )
  62. {
  63. sounds.Insert( idx );
  64. }
  65. }
  66. }
  67. }
  68. void CModelSoundsCache::Rebuild( char const *filename )
  69. {
  70. sounds.RemoveAll();
  71. CStudioHdr *hdr = ModelSoundsCache_LoadModel( filename );
  72. if ( hdr )
  73. {
  74. // Precache all sounds referenced in animation events
  75. BuildAnimationEventSoundList( hdr, sounds );
  76. ModelSoundsCache_FinishModel( hdr );
  77. }
  78. }
  79. void CModelSoundsCache::PrecacheSoundList()
  80. {
  81. for ( int i = 0; i < sounds.Count(); ++i )
  82. {
  83. ModelSoundsCache_PrecacheScriptSound( GetSoundName( i ) );
  84. }
  85. }
  86. //-----------------------------------------------------------------------------
  87. // Purpose: Static method
  88. // Input : sounds -
  89. // *soundname -
  90. //-----------------------------------------------------------------------------
  91. void CModelSoundsCache::FindOrAddScriptSound( CUtlSortVector< int, CModelSoundsCacheListLess >& sounds, char const *soundname )
  92. {
  93. int soundindex = soundemitterbase->GetSoundIndex( soundname );
  94. if ( soundemitterbase->IsValidIndex( soundindex ) )
  95. {
  96. // Only add it once per model...
  97. if ( sounds.Find( soundindex ) == sounds.InvalidIndex() )
  98. {
  99. MEM_ALLOC_CREDIT();
  100. sounds.Insert( soundindex );
  101. }
  102. }
  103. }
  104. //-----------------------------------------------------------------------------
  105. // Purpose: Static method
  106. // Input : *hdr -
  107. // sounds -
  108. //-----------------------------------------------------------------------------
  109. void CModelSoundsCache::BuildAnimationEventSoundList( CStudioHdr *hdr, CUtlSortVector< int, CModelSoundsCacheListLess >& sounds )
  110. {
  111. Assert( hdr );
  112. // force animation event resolution!!!
  113. VerifySequenceIndex( hdr );
  114. // Find all animation events which fire off sound script entries...
  115. for ( int iSeq=0; iSeq < hdr->GetNumSeq(); iSeq++ )
  116. {
  117. mstudioseqdesc_t *pSeq = &hdr->pSeqdesc( iSeq );
  118. // Now read out all the sound events with their timing
  119. for ( int iEvent=0; iEvent < (int)pSeq->numevents; iEvent++ )
  120. {
  121. mstudioevent_t *pEvent = (mstudioevent_for_client_server_t*)pSeq->pEvent( iEvent );
  122. int nEvent = pEvent->Event();
  123. switch ( nEvent )
  124. {
  125. default:
  126. {
  127. if ( pEvent->type & AE_TYPE_NEWEVENTSYSTEM )
  128. {
  129. if ( nEvent == AE_SV_PLAYSOUND )
  130. {
  131. FindOrAddScriptSound( sounds, pEvent->pszOptions() );
  132. }
  133. }
  134. }
  135. break;
  136. // Old-style client .dll animation event
  137. case CL_EVENT_SOUND:
  138. {
  139. FindOrAddScriptSound( sounds, pEvent->pszOptions() );
  140. }
  141. break;
  142. case CL_EVENT_FOOTSTEP_LEFT:
  143. case CL_EVENT_FOOTSTEP_RIGHT:
  144. {
  145. char soundname[256];
  146. char const *options = pEvent->pszOptions();
  147. if ( !options || !options[0] )
  148. {
  149. options = "NPC_CombineS";
  150. }
  151. Q_snprintf( soundname, 256, "%s.RunFootstepLeft", options );
  152. FindOrAddScriptSound( sounds, soundname );
  153. Q_snprintf( soundname, 256, "%s.RunFootstepRight", options );
  154. FindOrAddScriptSound( sounds, soundname );
  155. Q_snprintf( soundname, 256, "%s.FootstepLeft", options );
  156. FindOrAddScriptSound( sounds, soundname );
  157. Q_snprintf( soundname, 256, "%s.FootstepRight", options );
  158. FindOrAddScriptSound( sounds, soundname );
  159. }
  160. break;
  161. case AE_CL_PLAYSOUND:
  162. {
  163. if ( !( pEvent->type & AE_TYPE_CLIENT ) )
  164. break;
  165. if ( pEvent->pszOptions()[0] )
  166. {
  167. FindOrAddScriptSound( sounds, pEvent->pszOptions() );
  168. }
  169. else
  170. {
  171. Warning( "-- Error --: empty soundname, .qc error on AE_CL_PLAYSOUND in model %s, sequence %s, animevent # %i\n",
  172. hdr->pszName(), pSeq->pszLabel(), iEvent+1 );
  173. }
  174. }
  175. break;
  176. case SCRIPT_EVENT_SOUND:
  177. {
  178. FindOrAddScriptSound( sounds, pEvent->pszOptions() );
  179. }
  180. break;
  181. case SCRIPT_EVENT_SOUND_VOICE:
  182. {
  183. FindOrAddScriptSound( sounds, pEvent->pszOptions() );
  184. }
  185. break;
  186. }
  187. }
  188. }
  189. }