]> icculus.org git repositories - theoddone33/hhexen.git/blob - base/sn_sonix.c
Add alt-enter fullscreen toggle
[theoddone33/hhexen.git] / base / sn_sonix.c
1
2 //**************************************************************************
3 //**
4 //** sn_sonix.c : Heretic 2 : Raven Software, Corp.
5 //**
6 //** $RCSfile$
7 //** $Revision$
8 //** $Date$
9 //** $Author$
10 //**
11 //**************************************************************************
12
13 // HEADER FILES ------------------------------------------------------------
14
15 #include <string.h>
16 #include "h2def.h"
17 #include "soundst.h"
18
19 // MACROS ------------------------------------------------------------------
20
21 #define SS_MAX_SCRIPTS  64
22 #define SS_TEMPBUFFER_SIZE      1024
23 #define SS_SEQUENCE_NAME_LENGTH 32
24
25 #define SS_SCRIPT_NAME "SNDSEQ"
26 #define SS_STRING_PLAY                  "play"
27 #define SS_STRING_PLAYUNTILDONE "playuntildone"
28 #define SS_STRING_PLAYTIME              "playtime"
29 #define SS_STRING_PLAYREPEAT    "playrepeat"
30 #define SS_STRING_DELAY                 "delay"
31 #define SS_STRING_DELAYRAND             "delayrand"
32 #define SS_STRING_VOLUME                "volume"
33 #define SS_STRING_END                   "end"
34 #define SS_STRING_STOPSOUND             "stopsound"
35
36 // TYPES -------------------------------------------------------------------
37
38 typedef enum
39 {
40         SS_CMD_NONE,
41         SS_CMD_PLAY,
42         SS_CMD_WAITUNTILDONE, // used by PLAYUNTILDONE
43         SS_CMD_PLAYTIME,
44         SS_CMD_PLAYREPEAT,
45         SS_CMD_DELAY,
46         SS_CMD_DELAYRAND,
47         SS_CMD_VOLUME,
48         SS_CMD_STOPSOUND,
49         SS_CMD_END
50 } sscmds_t;
51
52 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
53
54 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
55
56 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
57
58 static void VerifySequencePtr(int *base, int *ptr);
59 static int GetSoundOffset(char *name);
60
61 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
62
63 extern sfxinfo_t S_sfx[];
64
65 // PUBLIC DATA DEFINITIONS -------------------------------------------------
66
67 // PRIVATE DATA DEFINITIONS ------------------------------------------------
68
69 static struct
70 {
71         char name[SS_SEQUENCE_NAME_LENGTH];
72         int scriptNum;
73         int stopSound;
74 } SequenceTranslate[SEQ_NUMSEQ] =
75 {
76         { "Platform", 0, 0 },
77         { "Platform", 0, 0 },           // a 'heavy' platform is just a platform
78         { "PlatformMetal", 0, 0 },      
79         { "Platform", 0, 0 },           // same with a 'creak' platform
80         { "Silence", 0, 0 },
81         { "Lava", 0, 0 },
82         { "Water", 0, 0 },
83         { "Ice", 0, 0 },
84         { "Earth", 0, 0 },
85         { "PlatformMetal2", 0, 0 },
86         { "DoorNormal", 0, 0 },
87         { "DoorHeavy", 0, 0 },
88         { "DoorMetal", 0, 0 },
89         { "DoorCreak", 0, 0 },
90         { "Silence", 0, 0 },
91         { "Lava", 0, 0 },
92         { "Water", 0, 0},
93         { "Ice", 0, 0 },
94         { "Earth", 0, 0},
95         { "DoorMetal2", 0, 0 },
96         { "Wind", 0, 0 }
97 };
98
99 static int *SequenceData[SS_MAX_SCRIPTS];
100
101 int ActiveSequences;
102 seqnode_t *SequenceListHead;
103
104 // CODE --------------------------------------------------------------------
105
106 //==========================================================================
107 //
108 // VerifySequencePtr
109 //
110 //   Verifies the integrity of the temporary ptr, and ensures that the ptr
111 //              isn't exceeding the size of the temporary buffer
112 //==========================================================================
113
114 static void VerifySequencePtr(int *base, int *ptr)
115 {
116         if(ptr-base > SS_TEMPBUFFER_SIZE)
117         {
118                 I_Error("VerifySequencePtr:  tempPtr >= %d\n", SS_TEMPBUFFER_SIZE);
119         }
120 }
121
122 //==========================================================================
123 //
124 // GetSoundOffset
125 //
126 //==========================================================================
127
128 static int GetSoundOffset(char *name)
129 {
130         int i;
131         
132         for(i = 0; i < NUMSFX; i++)
133         {
134                 if(!strcasecmp(name, S_sfx[i].tagName))
135                 {
136                         return i;
137                 }
138         }
139         SC_ScriptError("GetSoundOffset:  Unknown sound name\n");
140         return 0;
141 }
142
143 //==========================================================================
144 //
145 // SN_InitSequenceScript
146 //
147 //==========================================================================
148
149 void SN_InitSequenceScript(void)
150 {
151         int i, j;
152         int inSequence;
153         int *tempDataStart = NULL; /* jim added initialiser */
154         int *tempDataPtr   = NULL; /* jim added initialiser */
155
156         inSequence = -1;
157         ActiveSequences = 0;
158         for(i = 0; i < SS_MAX_SCRIPTS; i++)
159         {
160                 SequenceData[i] = NULL;
161         } 
162         SC_Open(SS_SCRIPT_NAME);
163         while(SC_GetString())
164         {
165                 if(*sc_String == ':')
166                 {
167                         if(inSequence != -1)
168                         {
169                                 SC_ScriptError("SN_InitSequenceScript:  Nested Script Error");
170                         }
171                         tempDataStart = (int *)Z_Malloc(SS_TEMPBUFFER_SIZE, 
172                                 PU_STATIC, NULL);
173                         memset(tempDataStart, 0, SS_TEMPBUFFER_SIZE);
174                         tempDataPtr = tempDataStart;
175                         for(i = 0; i < SS_MAX_SCRIPTS; i++)
176                         {
177                                 if(SequenceData[i] == NULL)
178                                 {
179                                         break;
180                                 }
181                         }
182                         if(i == SS_MAX_SCRIPTS)
183                         {
184                                 I_Error("Number of SS Scripts >= SS_MAX_SCRIPTS");
185                         }
186                         for(j = 0; j < SEQ_NUMSEQ; j++)
187                         {
188                                 if(!strcasecmp(SequenceTranslate[j].name, sc_String+1))
189                                 {
190                                         SequenceTranslate[j].scriptNum = i;
191                                         inSequence = j;
192                                         break;
193                                 }
194                         }                                       
195                         continue; // parse the next command
196                 }
197                 if(inSequence == -1)
198                 {
199                         continue;
200                 }
201                 if(SC_Compare(SS_STRING_PLAYUNTILDONE))
202                 {
203                         VerifySequencePtr(tempDataStart, tempDataPtr);
204                         SC_MustGetString();
205                         *tempDataPtr++ = SS_CMD_PLAY;
206                         *tempDataPtr++ = GetSoundOffset(sc_String);
207                         *tempDataPtr++ = SS_CMD_WAITUNTILDONE;          
208                 }
209                 else if(SC_Compare(SS_STRING_PLAY))
210                 {
211                         VerifySequencePtr(tempDataStart, tempDataPtr);
212                         SC_MustGetString();
213                         *tempDataPtr++ = SS_CMD_PLAY;
214                         *tempDataPtr++ = GetSoundOffset(sc_String);
215                 }
216                 else if(SC_Compare(SS_STRING_PLAYTIME))
217                 {
218                         VerifySequencePtr(tempDataStart, tempDataPtr);
219                         SC_MustGetString();
220                         *tempDataPtr++ = SS_CMD_PLAY;
221                         *tempDataPtr++ = GetSoundOffset(sc_String);
222                         SC_MustGetNumber();
223                         *tempDataPtr++ = SS_CMD_DELAY;  
224                         *tempDataPtr++ = sc_Number;
225                 }
226                 else if(SC_Compare(SS_STRING_PLAYREPEAT))
227                 {
228                         VerifySequencePtr(tempDataStart, tempDataPtr);
229                         SC_MustGetString();
230                         *tempDataPtr++ = SS_CMD_PLAYREPEAT;
231                         *tempDataPtr++ = GetSoundOffset(sc_String);
232                 }
233                 else if(SC_Compare(SS_STRING_DELAY))
234                 {
235                         VerifySequencePtr(tempDataStart, tempDataPtr);
236                         *tempDataPtr++ = SS_CMD_DELAY;
237                         SC_MustGetNumber();
238                         *tempDataPtr++ = sc_Number;
239                 }
240                 else if(SC_Compare(SS_STRING_DELAYRAND))
241                 {
242                         VerifySequencePtr(tempDataStart, tempDataPtr);
243                         *tempDataPtr++ = SS_CMD_DELAYRAND;
244                         SC_MustGetNumber();
245                         *tempDataPtr++ = sc_Number;
246                         SC_MustGetNumber();
247                         *tempDataPtr++ = sc_Number;
248                 }
249                 else if(SC_Compare(SS_STRING_VOLUME))
250                 {
251                         VerifySequencePtr(tempDataStart, tempDataPtr);
252                         *tempDataPtr++ = SS_CMD_VOLUME;
253                         SC_MustGetNumber();
254                         *tempDataPtr++ = sc_Number;
255                 }
256                 else if(SC_Compare(SS_STRING_END))
257                 {
258                         int dataSize;
259
260                         *tempDataPtr++ = SS_CMD_END;
261                         dataSize = (tempDataPtr-tempDataStart)*sizeof(int);
262                         SequenceData[i] = (int *)Z_Malloc(dataSize, PU_STATIC,
263                                 NULL);
264                         memcpy(SequenceData[i], tempDataStart, dataSize);
265                         Z_Free(tempDataStart);
266                         inSequence = -1;
267                 }
268                 else if(SC_Compare(SS_STRING_STOPSOUND))
269                 {
270                         SC_MustGetString();
271                         SequenceTranslate[inSequence].stopSound =
272                                 GetSoundOffset(sc_String);
273                         *tempDataPtr++ = SS_CMD_STOPSOUND;
274                 }
275                 else
276                 {
277                         SC_ScriptError("SN_InitSequenceScript:  Unknown commmand.\n");
278                 }
279         }
280 }
281
282 //==========================================================================
283 //
284 //  SN_StartSequence
285 //
286 //==========================================================================
287
288 void SN_StartSequence(mobj_t *mobj, int sequence)
289 {
290         seqnode_t *node;
291         
292         SN_StopSequence(mobj); // Stop any previous sequence
293         node = (seqnode_t *)Z_Malloc(sizeof(seqnode_t), PU_STATIC, NULL);
294         node->sequencePtr = SequenceData[SequenceTranslate[sequence].scriptNum];
295         node->sequence = sequence;
296         node->mobj = mobj;
297         node->delayTics = 0;
298         node->stopSound = SequenceTranslate[sequence].stopSound;
299         node->volume = 127; // Start at max volume
300
301         if(!SequenceListHead)
302         {
303                 SequenceListHead = node;
304                 node->next = node->prev = NULL;
305         }
306         else
307         {
308                 SequenceListHead->prev = node;
309                 node->next = SequenceListHead;
310                 node->prev = NULL;
311                 SequenceListHead = node;
312         }
313         ActiveSequences++;
314         return;
315 }
316
317 //==========================================================================
318 //
319 //  SN_StartSequenceName
320 //
321 //==========================================================================
322
323 void SN_StartSequenceName(mobj_t *mobj, char *name)
324 {
325         int i;
326
327         for(i = 0; i < SEQ_NUMSEQ; i++)
328         {
329                 if(!strcmp(name, SequenceTranslate[i].name))
330                 {
331                         SN_StartSequence(mobj, i);
332                         return;
333                 }
334         }
335 }
336
337 //==========================================================================
338 //
339 //  SN_StopSequence
340 //
341 //==========================================================================
342
343 void SN_StopSequence(mobj_t *mobj)
344 {
345         seqnode_t *node;
346
347         for(node = SequenceListHead; node; node = node->next)
348         {
349                 if(node->mobj == mobj)
350                 {
351                         S_StopSound(mobj);
352                         if(node->stopSound)
353                         {
354                                 S_StartSoundAtVolume(mobj, node->stopSound, node->volume);
355                         }
356                         if(SequenceListHead == node)
357                         {
358                                 SequenceListHead = node->next;
359                         }
360                         if(node->prev)
361                         {
362                                 node->prev->next = node->next;
363                         }
364                         if(node->next)
365                         {
366                                 node->next->prev = node->prev;
367                         }
368                         Z_Free(node);
369                         ActiveSequences--;
370                 }
371         }
372 }
373
374 //==========================================================================
375 //
376 //  SN_UpdateActiveSequences
377 //
378 //==========================================================================
379
380 void SN_UpdateActiveSequences(void)
381 {
382         seqnode_t *node;
383         boolean sndPlaying;
384
385         if(!ActiveSequences || paused)
386         { // No sequences currently playing/game is paused
387                 return;
388         }
389         for(node = SequenceListHead; node; node = node->next)
390         {
391                 if(node->delayTics)
392                 {
393                         node->delayTics--;
394                         continue;
395                 }
396                 sndPlaying = S_GetSoundPlayingInfo(node->mobj, node->currentSoundID);
397                 switch(*node->sequencePtr)
398                 {
399                         case SS_CMD_PLAY:
400                                 if(!sndPlaying)
401                                 {
402                                         node->currentSoundID = *(node->sequencePtr+1);
403                                         S_StartSoundAtVolume(node->mobj, node->currentSoundID,
404                                                 node->volume);
405                                 }
406                                 node->sequencePtr += 2;
407                                 break;
408                         case SS_CMD_WAITUNTILDONE:
409                                 if(!sndPlaying)
410                                 {
411                                         node->sequencePtr++;
412                                         node->currentSoundID = 0;
413                                 }
414                                 break;
415                         case SS_CMD_PLAYREPEAT:
416                                 if(!sndPlaying)
417                                 {
418                                         node->currentSoundID = *(node->sequencePtr+1);
419                                         S_StartSoundAtVolume(node->mobj, node->currentSoundID,
420                                                 node->volume);
421                                 }
422                                 break;
423                         case SS_CMD_DELAY:
424                                 node->delayTics = *(node->sequencePtr+1);
425                                 node->sequencePtr += 2;
426                                 node->currentSoundID = 0;
427                                 break;
428                         case SS_CMD_DELAYRAND:
429                                 node->delayTics = *(node->sequencePtr+1)+
430                                         M_Random()%(*(node->sequencePtr+2)-*(node->sequencePtr+1));
431                                 node->sequencePtr += 2;
432                                 node->currentSoundID = 0;
433                                 break;
434                         case SS_CMD_VOLUME:
435                                 node->volume = (127*(*(node->sequencePtr+1)))/100;
436                                 node->sequencePtr += 2;
437                                 break;
438                         case SS_CMD_STOPSOUND:
439                                 // Wait until something else stops the sequence
440                                 break;
441                         case SS_CMD_END:
442                                 SN_StopSequence(node->mobj);
443                                 break;
444                         default:        
445                                 break;
446                 }
447         }
448 }
449
450 //==========================================================================
451 //
452 //  SN_StopAllSequences
453 //
454 //==========================================================================
455
456 void SN_StopAllSequences(void)
457 {
458         seqnode_t *node;
459
460         for(node = SequenceListHead; node; node = node->next)
461         {
462                 node->stopSound = 0; // don't play any stop sounds
463                 SN_StopSequence(node->mobj);
464         }
465 }
466         
467 //==========================================================================
468 //
469 //  SN_GetSequenceOffset
470 //
471 //==========================================================================
472
473 int SN_GetSequenceOffset(int sequence, int *sequencePtr)
474 {
475         return (sequencePtr-SequenceData[SequenceTranslate[sequence].scriptNum]);
476 }
477
478 //==========================================================================
479 //
480 //  SN_ChangeNodeData
481 //
482 //      nodeNum zero is the first node
483 //==========================================================================
484
485 void SN_ChangeNodeData(int nodeNum, int seqOffset, int delayTics, int volume,
486         int currentSoundID)
487 {
488         int i;
489         seqnode_t *node;
490
491         i = 0;
492         node = SequenceListHead;
493         while(node && i < nodeNum)
494         {
495                 node = node->next;
496                 i++;
497         }
498         if(!node)
499         { // reach the end of the list before finding the nodeNum-th node
500                 return;
501         }
502         node->delayTics = delayTics;
503         node->volume = volume;
504         node->sequencePtr += seqOffset;
505         node->currentSoundID = currentSoundID;
506 }
507