home *** CD-ROM | disk | FTP | other *** search
/ GameStar 2006 March / Gamestar_82_2006-03_dvd.iso / DVDStar / Editace / quake4_sdkv10.exe / source / game / Sound.cpp < prev    next >
C/C++ Source or Header  |  2005-11-14  |  9KB  |  372 lines

  1.  
  2. #include "../idlib/precompiled.h"
  3. #pragma hdrstop
  4.  
  5. #include "Game_local.h"
  6.  
  7. /*
  8. ===============================================================================
  9.  
  10.   SOUND
  11.  
  12. ===============================================================================
  13. */
  14.  
  15. const idEventDef EV_Speaker_On( "On", NULL );
  16. const idEventDef EV_Speaker_Off( "Off", NULL );
  17. const idEventDef EV_Speaker_Timer( "<timer>", NULL );
  18.  
  19. CLASS_DECLARATION( idEntity, idSound )
  20.     EVENT( EV_Activate,                idSound::Event_Trigger )
  21.     EVENT( EV_Speaker_On,            idSound::Event_On )
  22.     EVENT( EV_Speaker_Off,            idSound::Event_Off )
  23.     EVENT( EV_Speaker_Timer,        idSound::Event_Timer )
  24. END_CLASS
  25.  
  26.  
  27. /*
  28. ================
  29. idSound::idSound
  30. ================
  31. */
  32. idSound::idSound( void ) {
  33.     lastSoundVol = 0.0f;
  34.     soundVol = 0.0f;
  35.     shakeTranslate.Zero();
  36.     shakeRotate.Zero();
  37.     random = 0.0f;
  38.     wait = 0.0f;
  39.     timerOn = false;
  40.     playingUntilTime = 0;
  41. }
  42.  
  43. /*
  44. ================
  45. idSound::Save
  46. ================
  47. */
  48. void idSound::Save( idSaveGame *savefile ) const {
  49.     savefile->WriteFloat( lastSoundVol );
  50.     savefile->WriteFloat( soundVol );
  51.     savefile->WriteFloat( random );
  52.     savefile->WriteFloat( wait );
  53.     savefile->WriteBool( timerOn );
  54.     savefile->WriteVec3( shakeTranslate );
  55.     savefile->WriteAngles( shakeRotate );
  56.     savefile->WriteInt( playingUntilTime );
  57. }
  58.  
  59. /*
  60. ================
  61. idSound::Restore
  62. ================
  63. */
  64. void idSound::Restore( idRestoreGame *savefile ) {
  65.     savefile->ReadFloat( lastSoundVol );
  66.     savefile->ReadFloat( soundVol );
  67.     savefile->ReadFloat( random );
  68.     savefile->ReadFloat( wait );
  69.     savefile->ReadBool( timerOn );
  70.     savefile->ReadVec3( shakeTranslate );
  71.     savefile->ReadAngles( shakeRotate );
  72.     savefile->ReadInt( playingUntilTime );
  73. }
  74.  
  75. /*
  76. ================
  77. idSound::Spawn
  78. ================
  79. */
  80. void idSound::Spawn( void ) {
  81.     spawnArgs.GetVector( "move", "0 0 0", shakeTranslate );
  82.     spawnArgs.GetAngles( "rotate", "0 0 0", shakeRotate );
  83.     spawnArgs.GetFloat( "random", "0", random );
  84.     spawnArgs.GetFloat( "wait", "0", wait );
  85.  
  86.     if ( ( wait > 0.0f ) && ( random >= wait ) ) {
  87.         random = wait - 0.001;
  88.         gameLocal.Warning( "speaker '%s' at (%s) has random >= wait", name.c_str(), GetPhysics()->GetOrigin().ToString(0) );
  89.     }
  90.  
  91.     soundVol        = 0.0f;
  92.     lastSoundVol    = 0.0f;
  93.  
  94.     if ( ( shakeRotate != ang_zero ) || ( shakeTranslate != vec3_zero ) ) {
  95.         BecomeActive( TH_THINK );
  96.     }
  97.  
  98.     if ( !refSound.waitfortrigger && ( wait > 0.0f ) ) {
  99.         timerOn = true;
  100.         PostEventSec( &EV_Speaker_Timer, wait + gameLocal.random.CRandomFloat() * random );
  101.     } else {
  102.         timerOn = false;
  103.     }
  104.  
  105. }
  106.  
  107. /*
  108. ================
  109. idSound::Event_Trigger
  110.  
  111. this will toggle the idle idSound on and off
  112. ================
  113. */
  114. void idSound::Event_Trigger( idEntity *activator ) {
  115.     if ( wait > 0.0f ) {
  116.         if ( timerOn ) {
  117.             timerOn = false;
  118.             CancelEvents( &EV_Speaker_Timer );
  119.         } else {
  120.             timerOn = true;
  121.             DoSound( true );
  122.             PostEventSec( &EV_Speaker_Timer, wait + gameLocal.random.CRandomFloat() * random );
  123.         }
  124.     } else {
  125.         if ( gameLocal.isMultiplayer ) {
  126. // RAVEN BEGIN
  127.             idSoundEmitter *emitter = soundSystem->EmitterForIndex( SOUNDWORLD_GAME, refSound.referenceSoundHandle );
  128.             if ( emitter && ( gameLocal.time < playingUntilTime ) ) {
  129. // RAVEN END
  130.                 DoSound( false );
  131.             } else {
  132.                 DoSound( true );
  133.             }
  134.         } else {
  135. // RAVEN BEGIN
  136.             idSoundEmitter *emitter = soundSystem->EmitterForIndex( SOUNDWORLD_GAME, refSound.referenceSoundHandle );
  137.             if ( emitter && emitter->CurrentlyPlaying() ) {
  138. // RAVEN END
  139.                 DoSound( false );
  140.             } else {
  141.                 DoSound( true );
  142.             }
  143.         }
  144.     }
  145. }
  146.  
  147. /*
  148. ================
  149. idSound::Event_Timer
  150. ================
  151. */
  152. void idSound::Event_Timer( void ) {
  153.     DoSound( true );
  154.     PostEventSec( &EV_Speaker_Timer, wait + gameLocal.random.CRandomFloat() * random );
  155. }
  156.  
  157. /*
  158. ================
  159. idSound::Think
  160. ================
  161. */
  162. void idSound::Think( void ) {
  163.     idAngles    ang;
  164.  
  165.     // run physics
  166.     RunPhysics();
  167.  
  168.     // clear out our update visuals think flag since we never call Present
  169.     BecomeInactive( TH_UPDATEVISUALS );
  170. }
  171.  
  172. /*
  173. ===============
  174. idSound::UpdateChangableSpawnArgs
  175. ===============
  176. */
  177. void idSound::UpdateChangeableSpawnArgs( const idDict *source ) {
  178.  
  179.     idEntity::UpdateChangeableSpawnArgs( source );
  180.  
  181.     if ( source ) {
  182.         FreeSoundEmitter( true );
  183.         refSound.referenceSoundHandle = soundSystem->AllocSoundEmitter( SOUNDWORLD_GAME );
  184.  
  185.         spawnArgs.Copy( *source );
  186.         gameEdit->ParseSpawnArgsToRefSound( &spawnArgs, &refSound );
  187.  
  188.         idVec3 origin;
  189.         idMat3 axis;
  190.  
  191.         if ( GetPhysicsToSoundTransform( origin, axis ) ) {
  192.             refSound.origin = GetPhysics()->GetOrigin() + origin * axis;
  193.         } else {
  194.             refSound.origin = GetPhysics()->GetOrigin();
  195.         }
  196.  
  197.         spawnArgs.GetFloat( "random", "0", random );
  198.         spawnArgs.GetFloat( "wait", "0", wait );
  199.  
  200.         if ( ( wait > 0.0f ) && ( random >= wait ) ) {
  201.             random = wait - 0.001;
  202.             gameLocal.Warning( "speaker '%s' at (%s) has random >= wait", name.c_str(), GetPhysics()->GetOrigin().ToString(0) );
  203.         }
  204.  
  205.         if ( !refSound.waitfortrigger && ( wait > 0.0f ) ) {
  206.             timerOn = true;
  207.             DoSound( false );
  208.             CancelEvents( &EV_Speaker_Timer );
  209.             PostEventSec( &EV_Speaker_Timer, wait + gameLocal.random.CRandomFloat() * random );
  210. // RAVEN BEGIN
  211.         } else  if ( !refSound.waitfortrigger ) {
  212.  
  213.             idSoundEmitter *emitter = soundSystem->EmitterForIndex( SOUNDWORLD_GAME, refSound.referenceSoundHandle );
  214.             if( !( emitter && emitter->CurrentlyPlaying() ) ) {
  215. // RAVEN END
  216.                 // start it if it isn't already playing, and we aren't waitForTrigger
  217.                 DoSound( true );
  218.                 timerOn = false;
  219.             }
  220.         }
  221.     }
  222. }
  223.  
  224. /*
  225. ===============
  226. idSound::SetSound
  227. ===============
  228. */
  229. void idSound::SetSound( const char *sound, int channel ) {
  230.     const idSoundShader *shader = declManager->FindSound( sound );
  231.     if ( shader != refSound.shader ) {
  232.         FreeSoundEmitter( true );
  233.     }
  234.     gameEdit->ParseSpawnArgsToRefSound(&spawnArgs, &refSound);
  235.     refSound.shader = shader;
  236. // RAVEN BEGIN
  237.     // start it if it isn't already playing, and we aren't waitForTrigger
  238.     idSoundEmitter *emitter = soundSystem->EmitterForIndex( SOUNDWORLD_GAME, refSound.referenceSoundHandle );
  239.     if ( !refSound.waitfortrigger && !( emitter && emitter->CurrentlyPlaying() ) ) {
  240. // RAVEN END
  241.         DoSound( true );
  242.     }
  243.  
  244. }
  245.  
  246. /*
  247. ================
  248. idSound::DoSound
  249. ================
  250. */
  251. void idSound::DoSound( bool play ) {
  252.     if ( play ) {
  253.         StartSoundShader( refSound.shader, SND_CHANNEL_ANY, refSound.parms.soundShaderFlags, true, &playingUntilTime );
  254.         playingUntilTime += gameLocal.time;
  255.     } else {
  256.         StopSound( SND_CHANNEL_ANY, true );
  257.         playingUntilTime = 0;
  258.     }
  259. }
  260.  
  261. /*
  262. ================
  263. idSound::Event_On
  264. ================
  265. */
  266. void idSound::Event_On( void ) {
  267.     if ( wait > 0.0f ) {
  268.         timerOn = true;
  269.         PostEventSec( &EV_Speaker_Timer, wait + gameLocal.random.CRandomFloat() * random );
  270.     }
  271.     DoSound( true );
  272. }
  273.  
  274. /*
  275. ================
  276. idSound::Event_Off
  277. ================
  278. */
  279. void idSound::Event_Off( void ) {
  280.     if ( timerOn ) {
  281.         timerOn = false;
  282.         CancelEvents( &EV_Speaker_Timer );
  283.     }
  284.     DoSound( false );
  285. }
  286.  
  287. // RAVEN BEGIN
  288. // abahr: so we only set the referenceSounds on our targets once
  289. /*
  290. ================
  291. idSound::FindTargets
  292. ================
  293. */
  294. void idSound::FindTargets() {
  295.     idEntity::FindTargets();
  296.  
  297.     if( !targets.Num() ) {// I don't think we ever get in here unless we have targets
  298.         return;
  299.     }
  300.  
  301.     idSoundEmitter *emitter = soundSystem->EmitterForIndex( SOUNDWORLD_GAME, refSound.referenceSoundHandle );
  302.     if ( !emitter ) { 
  303.         // if we have targets lets get an emitter
  304.         refSound.referenceSoundHandle = soundSystem->AllocSoundEmitter( SOUNDWORLD_GAME );
  305.     }
  306.  
  307.     SetTargetSoundHandles();
  308. }
  309. // RAVEN END
  310.  
  311. /*
  312. ===============
  313. idSound::ShowEditingDialog
  314. ===============
  315. */
  316. void idSound::ShowEditingDialog( void ) {
  317.     common->InitTool( EDITOR_SOUND, &spawnArgs );
  318. }
  319.  
  320. // RAVEN BEGIN
  321. // jshepard: Allow speakers to target lights and have those lights use this speaker's refSound
  322. /*
  323. ===============
  324. idSound::SetSoundHandles
  325. ===============
  326. */
  327. void idSound::SetTargetSoundHandles( void ) {
  328. //this code is mostly boosted from a similar function in light.cpp
  329.     int i;
  330.     idEntity *targetEnt;
  331.  
  332.     //is this check really necessary? We are a speaker after all...
  333.     if ( !soundSystem->EmitterForIndex( SOUNDWORLD_GAME, refSound.referenceSoundHandle ) ) {
  334.         return;
  335.     }
  336.     
  337.     for ( i = 0; i < targets.Num(); i++ ) {
  338.         targetEnt = targets[ i ].GetEntity();
  339. // RAVEN BEGIN
  340. // jnewquist: Use accessor for static class type 
  341.         if ( targetEnt && targetEnt->IsType( idLight::GetClassType() ) ) {
  342. // RAVEN END
  343.             idLight    *light = static_cast<idLight*>(targetEnt);
  344.  
  345.             //no need to make this speaker a lightparent....
  346.             //light->lightParent = this;
  347.  
  348.             // explicitly delete any sounds on the entity
  349.             light->FreeSoundEmitter( true );
  350.  
  351.             // manually set the refSound to this light's refSound
  352.             light->SetRefSound(refSound.referenceSoundHandle);
  353.  
  354.             // update the renderEntity to the renderer
  355.             light->UpdateVisuals();
  356.         }
  357.     }    
  358. }
  359.  
  360. // abahr:
  361. /*
  362. ================
  363. idSound::GetPhysicsToSoundTransform
  364. ================
  365. */
  366. bool idSound::GetPhysicsToSoundTransform( idVec3 &origin, idMat3 &axis ) {
  367.     origin = shakeTranslate.Random( spawnArgs.GetVector("move_random_delta"), gameLocal.random );
  368.     axis = shakeRotate.Random( spawnArgs.GetVector("shake_random_delta"), gameLocal.random ).ToMat3();
  369.     return true;
  370. }
  371. // RAVEN END
  372.