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.

216 lines
5.5 KiB

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