2 ===========================================================================
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
26 ===========================================================================
29 #include "../idlib/precompiled.h"
32 #include "Game_local.h"
35 ===============================================================================
39 ===============================================================================
42 const idEventDef EV_Speaker_On( "On", NULL );
43 const idEventDef EV_Speaker_Off( "Off", NULL );
44 const idEventDef EV_Speaker_Timer( "<timer>", NULL );
46 CLASS_DECLARATION( idEntity, idSound )
47 EVENT( EV_Activate, idSound::Event_Trigger )
48 EVENT( EV_Speaker_On, idSound::Event_On )
49 EVENT( EV_Speaker_Off, idSound::Event_Off )
50 EVENT( EV_Speaker_Timer, idSound::Event_Timer )
59 idSound::idSound( void ) {
62 shakeTranslate.Zero();
75 void idSound::Save( idSaveGame *savefile ) const {
76 savefile->WriteFloat( lastSoundVol );
77 savefile->WriteFloat( soundVol );
78 savefile->WriteFloat( random );
79 savefile->WriteFloat( wait );
80 savefile->WriteBool( timerOn );
81 savefile->WriteVec3( shakeTranslate );
82 savefile->WriteAngles( shakeRotate );
83 savefile->WriteInt( playingUntilTime );
91 void idSound::Restore( idRestoreGame *savefile ) {
92 savefile->ReadFloat( lastSoundVol );
93 savefile->ReadFloat( soundVol );
94 savefile->ReadFloat( random );
95 savefile->ReadFloat( wait );
96 savefile->ReadBool( timerOn );
97 savefile->ReadVec3( shakeTranslate );
98 savefile->ReadAngles( shakeRotate );
99 savefile->ReadInt( playingUntilTime );
107 void idSound::Spawn( void ) {
108 spawnArgs.GetVector( "move", "0 0 0", shakeTranslate );
109 spawnArgs.GetAngles( "rotate", "0 0 0", shakeRotate );
110 spawnArgs.GetFloat( "random", "0", random );
111 spawnArgs.GetFloat( "wait", "0", wait );
113 if ( ( wait > 0.0f ) && ( random >= wait ) ) {
114 random = wait - 0.001;
115 gameLocal.Warning( "speaker '%s' at (%s) has random >= wait", name.c_str(), GetPhysics()->GetOrigin().ToString(0) );
121 if ( ( shakeRotate != ang_zero ) || ( shakeTranslate != vec3_zero ) ) {
122 BecomeActive( TH_THINK );
125 if ( !refSound.waitfortrigger && ( wait > 0.0f ) ) {
127 PostEventSec( &EV_Speaker_Timer, wait + gameLocal.random.CRandomFloat() * random );
135 idSound::Event_Trigger
137 this will toggle the idle idSound on and off
140 void idSound::Event_Trigger( idEntity *activator ) {
144 CancelEvents( &EV_Speaker_Timer );
148 PostEventSec( &EV_Speaker_Timer, wait + gameLocal.random.CRandomFloat() * random );
151 if ( gameLocal.isMultiplayer ) {
152 if ( refSound.referenceSound && ( gameLocal.time < playingUntilTime ) ) {
158 if ( refSound.referenceSound && refSound.referenceSound->CurrentlyPlaying() ) {
172 void idSound::Event_Timer( void ) {
174 PostEventSec( &EV_Speaker_Timer, wait + gameLocal.random.CRandomFloat() * random );
182 void idSound::Think( void ) {
188 // clear out our update visuals think flag since we never call Present
189 BecomeInactive( TH_UPDATEVISUALS );
194 idSound::UpdateChangableSpawnArgs
197 void idSound::UpdateChangeableSpawnArgs( const idDict *source ) {
199 idEntity::UpdateChangeableSpawnArgs( source );
202 FreeSoundEmitter( true );
203 spawnArgs.Copy( *source );
204 idSoundEmitter *saveRef = refSound.referenceSound;
205 gameEdit->ParseSpawnArgsToRefSound( &spawnArgs, &refSound );
206 refSound.referenceSound = saveRef;
211 if ( GetPhysicsToSoundTransform( origin, axis ) ) {
212 refSound.origin = GetPhysics()->GetOrigin() + origin * axis;
214 refSound.origin = GetPhysics()->GetOrigin();
217 spawnArgs.GetFloat( "random", "0", random );
218 spawnArgs.GetFloat( "wait", "0", wait );
220 if ( ( wait > 0.0f ) && ( random >= wait ) ) {
221 random = wait - 0.001;
222 gameLocal.Warning( "speaker '%s' at (%s) has random >= wait", name.c_str(), GetPhysics()->GetOrigin().ToString(0) );
225 if ( !refSound.waitfortrigger && ( wait > 0.0f ) ) {
228 CancelEvents( &EV_Speaker_Timer );
229 PostEventSec( &EV_Speaker_Timer, wait + gameLocal.random.CRandomFloat() * random );
230 } else if ( !refSound.waitfortrigger && !(refSound.referenceSound && refSound.referenceSound->CurrentlyPlaying() ) ) {
231 // start it if it isn't already playing, and we aren't waitForTrigger
243 void idSound::SetSound( const char *sound, int channel ) {
244 const idSoundShader *shader = declManager->FindSound( sound );
245 if ( shader != refSound.shader ) {
246 FreeSoundEmitter( true );
248 gameEdit->ParseSpawnArgsToRefSound(&spawnArgs, &refSound);
249 refSound.shader = shader;
250 // start it if it isn't already playing, and we aren't waitForTrigger
251 if ( !refSound.waitfortrigger && !(refSound.referenceSound && refSound.referenceSound->CurrentlyPlaying() ) ) {
261 void idSound::DoSound( bool play ) {
263 StartSoundShader( refSound.shader, SND_CHANNEL_ANY, refSound.parms.soundShaderFlags, true, &playingUntilTime );
264 playingUntilTime += gameLocal.time;
266 StopSound( SND_CHANNEL_ANY, true );
267 playingUntilTime = 0;
276 void idSound::Event_On( void ) {
279 PostEventSec( &EV_Speaker_Timer, wait + gameLocal.random.CRandomFloat() * random );
289 void idSound::Event_Off( void ) {
292 CancelEvents( &EV_Speaker_Timer );
299 idSound::ShowEditingDialog
302 void idSound::ShowEditingDialog( void ) {
303 common->InitTool( EDITOR_SOUND, &spawnArgs );