]> icculus.org git repositories - icculus/iodoom3.git/blob - neo/game/Sound.cpp
hello world
[icculus/iodoom3.git] / neo / game / Sound.cpp
1 /*
2 ===========================================================================
3
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. 
6
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).  
8
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.
13
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.
18
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/>.
21
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.
23
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.
25
26 ===========================================================================
27 */
28
29 #include "../idlib/precompiled.h"
30 #pragma hdrstop
31
32 #include "Game_local.h"
33
34 /*
35 ===============================================================================
36
37   SOUND
38
39 ===============================================================================
40 */
41
42 const idEventDef EV_Speaker_On( "On", NULL );
43 const idEventDef EV_Speaker_Off( "Off", NULL );
44 const idEventDef EV_Speaker_Timer( "<timer>", NULL );
45
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 )
51 END_CLASS
52
53
54 /*
55 ================
56 idSound::idSound
57 ================
58 */
59 idSound::idSound( void ) {
60         lastSoundVol = 0.0f;
61         soundVol = 0.0f;
62         shakeTranslate.Zero();
63         shakeRotate.Zero();
64         random = 0.0f;
65         wait = 0.0f;
66         timerOn = false;
67         playingUntilTime = 0;
68 }
69
70 /*
71 ================
72 idSound::Save
73 ================
74 */
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 );
84 }
85
86 /*
87 ================
88 idSound::Restore
89 ================
90 */
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 );
100 }
101
102 /*
103 ================
104 idSound::Spawn
105 ================
106 */
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 );
112
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) );
116         }
117
118         soundVol                = 0.0f;
119         lastSoundVol    = 0.0f;
120
121         if ( ( shakeRotate != ang_zero ) || ( shakeTranslate != vec3_zero ) ) {
122                 BecomeActive( TH_THINK );
123         }
124
125         if ( !refSound.waitfortrigger && ( wait > 0.0f ) ) {
126                 timerOn = true;
127                 PostEventSec( &EV_Speaker_Timer, wait + gameLocal.random.CRandomFloat() * random );
128         } else {
129                 timerOn = false;
130         }
131 }
132
133 /*
134 ================
135 idSound::Event_Trigger
136
137 this will toggle the idle idSound on and off
138 ================
139 */
140 void idSound::Event_Trigger( idEntity *activator ) {
141         if ( wait > 0.0f ) {
142                 if ( timerOn ) {
143                         timerOn = false;
144                         CancelEvents( &EV_Speaker_Timer );
145                 } else {
146                         timerOn = true;
147                         DoSound( true );
148                         PostEventSec( &EV_Speaker_Timer, wait + gameLocal.random.CRandomFloat() * random );
149                 }
150         } else {
151                 if ( gameLocal.isMultiplayer ) {
152                         if ( refSound.referenceSound && ( gameLocal.time < playingUntilTime ) ) {
153                                 DoSound( false );
154                         } else {
155                                 DoSound( true );
156                         }
157                 } else {
158                         if ( refSound.referenceSound && refSound.referenceSound->CurrentlyPlaying() ) {
159                                 DoSound( false );
160                         } else {
161                                 DoSound( true );
162                         }
163                 }
164         }
165 }
166
167 /*
168 ================
169 idSound::Event_Timer
170 ================
171 */
172 void idSound::Event_Timer( void ) {
173         DoSound( true );
174         PostEventSec( &EV_Speaker_Timer, wait + gameLocal.random.CRandomFloat() * random );
175 }
176
177 /*
178 ================
179 idSound::Think
180 ================
181 */
182 void idSound::Think( void ) {
183         idAngles        ang;
184
185         // run physics
186         RunPhysics();
187
188         // clear out our update visuals think flag since we never call Present
189         BecomeInactive( TH_UPDATEVISUALS );
190 }
191
192 /*
193 ===============
194 idSound::UpdateChangableSpawnArgs
195 ===============
196 */
197 void idSound::UpdateChangeableSpawnArgs( const idDict *source ) {
198
199         idEntity::UpdateChangeableSpawnArgs( source );
200
201         if ( source ) {
202                 FreeSoundEmitter( true );
203                 spawnArgs.Copy( *source );
204                 idSoundEmitter *saveRef = refSound.referenceSound;
205                 gameEdit->ParseSpawnArgsToRefSound( &spawnArgs, &refSound );
206                 refSound.referenceSound = saveRef;
207
208                 idVec3 origin;
209                 idMat3 axis;
210
211                 if ( GetPhysicsToSoundTransform( origin, axis ) ) {
212                         refSound.origin = GetPhysics()->GetOrigin() + origin * axis;
213                 } else {
214                         refSound.origin = GetPhysics()->GetOrigin();
215                 }
216
217                 spawnArgs.GetFloat( "random", "0", random );
218                 spawnArgs.GetFloat( "wait", "0", wait );
219
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) );
223                 }
224
225                 if ( !refSound.waitfortrigger && ( wait > 0.0f ) ) {
226                         timerOn = true;
227                         DoSound( false );
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
232                         DoSound( true );
233                         timerOn = false;
234                 }
235         }
236 }
237
238 /*
239 ===============
240 idSound::SetSound
241 ===============
242 */
243 void idSound::SetSound( const char *sound, int channel ) {
244         const idSoundShader *shader = declManager->FindSound( sound );
245         if ( shader != refSound.shader ) {
246                 FreeSoundEmitter( true );
247         }
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() ) ) {
252                 DoSound( true );
253         }
254 }
255
256 /*
257 ================
258 idSound::DoSound
259 ================
260 */
261 void idSound::DoSound( bool play ) {
262         if ( play ) {
263                 StartSoundShader( refSound.shader, SND_CHANNEL_ANY, refSound.parms.soundShaderFlags, true, &playingUntilTime );
264                 playingUntilTime += gameLocal.time;
265         } else {
266                 StopSound( SND_CHANNEL_ANY, true );
267                 playingUntilTime = 0;
268         }
269 }
270
271 /*
272 ================
273 idSound::Event_On
274 ================
275 */
276 void idSound::Event_On( void ) {
277         if ( wait > 0.0f ) {
278                 timerOn = true;
279                 PostEventSec( &EV_Speaker_Timer, wait + gameLocal.random.CRandomFloat() * random );
280         }
281         DoSound( true );
282 }
283
284 /*
285 ================
286 idSound::Event_Off
287 ================
288 */
289 void idSound::Event_Off( void ) {
290         if ( timerOn ) {
291                 timerOn = false;
292                 CancelEvents( &EV_Speaker_Timer );
293         }
294         DoSound( false );
295 }
296
297 /*
298 ===============
299 idSound::ShowEditingDialog
300 ===============
301 */
302 void idSound::ShowEditingDialog( void ) {
303         common->InitTool( EDITOR_SOUND, &spawnArgs );
304 }
305