|
|
1.1 root 1:
2: //**************************************************************************
3: //**
4: //** sn_sonix.c : Heretic 2 : Raven Software, Corp.
5: //**
6: //** $RCSfile: sn_sonix.c,v $
7: //** $Revision: 1.17 $
8: //** $Date: 95/10/05 18:25:44 $
9: //** $Author: paul $
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;
154: int *tempDataPtr;
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.