60 // SOUNDS |
60 // SOUNDS |
61 |
61 |
62 // Plays the sound snd [from a given voicepack], |
62 // Plays the sound snd [from a given voicepack], |
63 // if keepPlaying is given and true, |
63 // if keepPlaying is given and true, |
64 // then the sound's playback won't be interrupted if asked to play again. |
64 // then the sound's playback won't be interrupted if asked to play again. |
65 procedure PlaySound(snd: TSound); |
65 // Returns true if sound was found and is played, false otherwise. |
66 procedure PlaySound(snd: TSound; keepPlaying: boolean); |
66 function PlaySound(snd: TSound): boolean; |
67 procedure PlaySound(snd: TSound; keepPlaying: boolean; ignoreMask: boolean); |
67 function PlaySound(snd: TSound; keepPlaying: boolean): boolean; |
68 procedure PlaySound(snd: TSound; keepPlaying, ignoreMask, soundAsMusic: boolean); |
68 function PlaySound(snd: TSound; keepPlaying: boolean; ignoreMask: boolean): boolean; |
69 procedure PlaySoundV(snd: TSound; voicepack: PVoicepack); |
69 function PlaySound(snd: TSound; keepPlaying, ignoreMask, soundAsMusic: boolean): boolean; |
70 procedure PlaySoundV(snd: TSound; voicepack: PVoicepack; keepPlaying: boolean); |
70 function PlaySoundV(snd: TSound; voicepack: PVoicepack): boolean; |
71 procedure PlaySoundV(snd: TSound; voicepack: PVoicepack; keepPlaying, ignoreMask: boolean); |
71 function PlaySoundV(snd: TSound; voicepack: PVoicepack; keepPlaying: boolean): boolean; |
72 procedure PlaySoundV(snd: TSound; voicepack: PVoicepack; keepPlaying, ignoreMask, soundAsMusic: boolean); |
72 function PlaySoundV(snd: TSound; voicepack: PVoicepack; keepPlaying, ignoreMask: boolean): boolean; |
|
73 function PlaySoundV(snd: TSound; voicepack: PVoicepack; keepPlaying, ignoreMask, soundAsMusic: boolean): boolean; |
73 |
74 |
74 // Plays/stops a sound to replace the main background music temporarily. |
75 // Plays/stops a sound to replace the main background music temporarily. |
75 procedure PlayMusicSound(snd: TSound); |
76 procedure PlayMusicSound(snd: TSound); |
76 procedure StopMusicSound(snd: TSound); |
77 procedure StopMusicSound(snd: TSound); |
77 |
78 |
87 procedure StopSound(snd: TSound); |
88 procedure StopSound(snd: TSound); |
88 procedure StopSound(snd: TSound; soundAsMusic: boolean); |
89 procedure StopSound(snd: TSound; soundAsMusic: boolean); |
89 procedure StopSoundChan(chn: LongInt); |
90 procedure StopSoundChan(chn: LongInt); |
90 procedure StopSoundChan(chn, fadems: LongInt); |
91 procedure StopSoundChan(chn, fadems: LongInt); |
91 |
92 |
|
93 // Add voice to the voice queue |
92 procedure AddVoice(snd: TSound; voicepack: PVoicepack); |
94 procedure AddVoice(snd: TSound; voicepack: PVoicepack); |
93 procedure AddVoice(snd: TSound; voicepack: PVoicepack; ignoreMask: boolean); |
95 procedure AddVoice(snd: TSound; voicepack: PVoicepack; ignoreMask, isFallback: boolean); |
|
96 |
|
97 // Actually play next voice |
94 procedure PlayNextVoice; |
98 procedure PlayNextVoice; |
95 |
99 |
96 |
100 |
97 // GLOBAL FUNCTIONS |
101 // GLOBAL FUNCTIONS |
98 |
102 |
123 FallbackMusicFN: shortstring; // fallback music file name |
127 FallbackMusicFN: shortstring; // fallback music file name |
124 FallbackSDMusicFN: shortstring; // fallback SD music fille name |
128 FallbackSDMusicFN: shortstring; // fallback SD music fille name |
125 |
129 |
126 var Volume: LongInt; |
130 var Volume: LongInt; |
127 SoundTimerTicks: Longword; |
131 SoundTimerTicks: Longword; |
|
132 LastVoiceFailed: boolean; |
128 implementation |
133 implementation |
129 uses uVariables, uConsole, uCommands, uDebug, uPhysFSLayer; |
134 uses uVariables, uConsole, uCommands, uDebug, uPhysFSLayer; |
130 |
135 |
131 const chanTPU = 32; |
136 const chanTPU = 32; |
132 var cInitVolume: LongInt; |
137 var cInitVolume: LongInt; |
138 isMusicEnabled: boolean; |
143 isMusicEnabled: boolean; |
139 isSoundEnabled: boolean; |
144 isSoundEnabled: boolean; |
140 isAutoDampening: boolean; |
145 isAutoDampening: boolean; |
141 isSEBackup: boolean; |
146 isSEBackup: boolean; |
142 VoiceList : array[0..7] of TVoice = ( |
147 VoiceList : array[0..7] of TVoice = ( |
143 ( snd: sndNone; voicepack: nil), |
148 ( snd: sndNone; voicepack: nil; isFallback: false), |
144 ( snd: sndNone; voicepack: nil), |
149 ( snd: sndNone; voicepack: nil; isFallback: false), |
145 ( snd: sndNone; voicepack: nil), |
150 ( snd: sndNone; voicepack: nil; isFallback: false), |
146 ( snd: sndNone; voicepack: nil), |
151 ( snd: sndNone; voicepack: nil; isFallback: false), |
147 ( snd: sndNone; voicepack: nil), |
152 ( snd: sndNone; voicepack: nil; isFallback: false), |
148 ( snd: sndNone; voicepack: nil), |
153 ( snd: sndNone; voicepack: nil; isFallback: false), |
149 ( snd: sndNone; voicepack: nil), |
154 ( snd: sndNone; voicepack: nil; isFallback: false), |
150 ( snd: sndNone; voicepack: nil)); |
155 ( snd: sndNone; voicepack: nil; isFallback: false)); |
151 Soundz: array[TSound] of record |
156 Soundz: array[TSound] of record |
152 FileName: string[31]; |
157 FileName: string[31]; |
153 Path, AltPath : TPathType; |
158 Path, AltPath : TPathType; |
154 end = ( |
159 end = ( |
155 (FileName: ''; Path: ptNone; AltPath: ptNone),// sndNone |
160 (FileName: ''; Path: ptNone; AltPath: ptNone),// sndNone |
497 GetFallbackV := sndEnemyDown |
502 GetFallbackV := sndEnemyDown |
498 else |
503 else |
499 GetFallbackV := sndNone; |
504 GetFallbackV := sndNone; |
500 end; |
505 end; |
501 |
506 |
502 procedure PlaySound(snd: TSound); |
507 function PlaySound(snd: TSound): boolean; |
503 begin |
508 begin |
504 PlaySoundV(snd, nil, false, false, false); |
509 PlaySound:= PlaySoundV(snd, nil, false, false, false); |
505 end; |
510 end; |
506 |
511 |
507 procedure PlaySound(snd: TSound; keepPlaying: boolean); |
512 function PlaySound(snd: TSound; keepPlaying: boolean): boolean; |
508 begin |
513 begin |
509 PlaySoundV(snd, nil, keepPlaying, false, false); |
514 PlaySound:= PlaySoundV(snd, nil, keepPlaying, false, false); |
510 end; |
515 end; |
511 |
516 |
512 procedure PlaySound(snd: TSound; keepPlaying: boolean; ignoreMask: boolean); |
517 function PlaySound(snd: TSound; keepPlaying: boolean; ignoreMask: boolean): boolean; |
513 begin |
518 begin |
514 PlaySoundV(snd, nil, keepPlaying, ignoreMask, false); |
519 PlaySound:= PlaySoundV(snd, nil, keepPlaying, ignoreMask, false); |
515 end; |
520 end; |
516 |
521 |
517 procedure PlaySound(snd: TSound; keepPlaying: boolean; ignoreMask, soundAsMusic: boolean); |
522 function PlaySound(snd: TSound; keepPlaying: boolean; ignoreMask, soundAsMusic: boolean): boolean; |
518 begin |
523 begin |
519 PlaySoundV(snd, nil, keepPlaying, ignoreMask, soundAsMusic); |
524 PlaySound:= PlaySoundV(snd, nil, keepPlaying, ignoreMask, soundAsMusic); |
520 end; |
525 end; |
521 |
526 |
522 procedure PlaySoundV(snd: TSound; voicepack: PVoicepack); |
527 function PlaySoundV(snd: TSound; voicepack: PVoicepack): boolean; |
523 begin |
528 begin |
524 PlaySoundV(snd, voicepack, false, false, false); |
529 PlaySoundV:= PlaySoundV(snd, voicepack, false, false, false); |
525 end; |
530 end; |
526 |
531 |
527 procedure PlaySoundV(snd: TSound; voicepack: PVoicepack; keepPlaying: boolean); |
532 function PlaySoundV(snd: TSound; voicepack: PVoicepack; keepPlaying: boolean): boolean; |
528 begin |
533 begin |
529 PlaySoundV(snd, voicepack, keepPlaying, false, false); |
534 PlaySoundV:= PlaySoundV(snd, voicepack, keepPlaying, false, false); |
530 end; |
535 end; |
531 |
536 |
532 procedure PlaySoundV(snd: TSound; voicepack: PVoicepack; keepPlaying, ignoreMask: boolean); |
537 function PlaySoundV(snd: TSound; voicepack: PVoicepack; keepPlaying, ignoreMask: boolean): boolean; |
533 begin |
538 begin |
534 PlaySoundV(snd, voicepack, keepPlaying, ignoreMask, false); |
539 PlaySoundV:= PlaySoundV(snd, voicepack, keepPlaying, ignoreMask, false); |
535 end; |
540 end; |
536 |
541 |
537 procedure PlaySoundV(snd: TSound; voicepack: PVoicepack; keepPlaying, ignoreMask, soundAsMusic: boolean); |
542 function PlaySoundV(snd: TSound; voicepack: PVoicepack; keepPlaying, ignoreMask, soundAsMusic: boolean): boolean; |
538 var s:shortstring; |
543 var s:shortstring; |
539 rwops: PSDL_RWops; |
544 rwops: PSDL_RWops; |
540 begin |
545 begin |
|
546 s:= cPathz[Soundz[snd].Path] + '/' + voicepack^.name + '/' + Soundz[snd].FileName; |
|
547 PlaySoundV:= false; |
541 if ((not isSoundEnabled) and (not (soundAsMusic and isMusicEnabled))) or fastUntilLag then |
548 if ((not isSoundEnabled) and (not (soundAsMusic and isMusicEnabled))) or fastUntilLag then |
542 exit; |
549 exit; |
543 |
550 |
544 if keepPlaying and (lastChan[snd] <> -1) and (Mix_Playing(lastChan[snd]) <> 0) then |
551 if keepPlaying and (lastChan[snd] <> -1) and (Mix_Playing(lastChan[snd]) <> 0) then |
545 exit; |
552 exit; |
595 |
603 |
596 defVoicepack^.chunks[snd]:= Mix_LoadWAV_RW(rwops, 1); |
604 defVoicepack^.chunks[snd]:= Mix_LoadWAV_RW(rwops, 1); |
597 if SDLCheck(defVoicepack^.chunks[snd] <> nil, 'Mix_LoadWAV_RW', true) then exit; |
605 if SDLCheck(defVoicepack^.chunks[snd] <> nil, 'Mix_LoadWAV_RW', true) then exit; |
598 WriteLnToConsole(msgOK); |
606 WriteLnToConsole(msgOK); |
599 end; |
607 end; |
600 lastChan[snd]:= Mix_PlayChannelTimed(-1, defVoicepack^.chunks[snd], 0, -1) |
608 lastChan[snd]:= Mix_PlayChannelTimed(-1, defVoicepack^.chunks[snd], 0, -1); |
|
609 PlaySoundV:= true; |
601 end; |
610 end; |
602 end; |
611 end; |
603 |
612 |
604 procedure PlayMusicSound(snd: TSound); |
613 procedure PlayMusicSound(snd: TSound); |
605 begin |
614 begin |
613 ResumeMusic; |
622 ResumeMusic; |
614 end; |
623 end; |
615 |
624 |
616 procedure AddVoice(snd: TSound; voicepack: PVoicepack); |
625 procedure AddVoice(snd: TSound; voicepack: PVoicepack); |
617 begin |
626 begin |
618 AddVoice(snd, voicepack, false); |
627 AddVoice(snd, voicepack, false, false); |
619 end; |
628 end; |
620 |
629 |
621 procedure AddVoice(snd: TSound; voicepack: PVoicepack; ignoreMask: boolean); |
630 { |
|
631 AddVoice: Add a voice to the voice queue. |
|
632 * snd: Sound ID |
|
633 * voicepack: Hedgehog voicepack |
|
634 * ignoreMask: If true, the sound will be played anyway if masked by Lua |
|
635 * isFallback: If true, this sound is added as fallback if the sound previously added to the |
|
636 queue was not found. Useful to make sure a voice is always played, even if |
|
637 a voicepack is incomplete. |
|
638 Example: |
|
639 AddVoice(sndRevenge, voiceAttacker); |
|
640 AddVoice(sndRegret, voiceVictim, false, true); |
|
641 --> plays sndRegret if sndRevenge could not be played. |
|
642 } |
|
643 procedure AddVoice(snd: TSound; voicepack: PVoicepack; ignoreMask, isFallback: boolean); |
622 var i : LongInt; |
644 var i : LongInt; |
623 begin |
645 begin |
624 |
646 |
625 if (not isSoundEnabled) or fastUntilLag or ((LastVoice.snd = snd) and (LastVoice.voicepack = voicepack)) then |
647 if (not isSoundEnabled) or fastUntilLag or ((LastVoice.snd = snd) and (LastVoice.voicepack = voicepack)) then |
626 exit; |
648 exit; |
644 exit; |
666 exit; |
645 if(i <= High(VoiceList)) then |
667 if(i <= High(VoiceList)) then |
646 begin |
668 begin |
647 VoiceList[i].snd:= snd; |
669 VoiceList[i].snd:= snd; |
648 VoiceList[i].voicepack:= voicepack; |
670 VoiceList[i].voicepack:= voicepack; |
|
671 VoiceList[i].isFallback:= isFallback; |
649 end |
672 end |
650 end; |
673 end; |
651 |
674 |
652 procedure PlayNextVoice; |
675 procedure PlayNextVoice; |
653 var i : LongInt; |
676 var i : LongInt; |
|
677 played : boolean; |
654 begin |
678 begin |
655 if (not isSoundEnabled) or fastUntilLag or ((LastVoice.snd <> sndNone) and (lastChan[LastVoice.snd] <> -1) and (Mix_Playing(lastChan[LastVoice.snd]) <> 0)) then |
679 if (not isSoundEnabled) or fastUntilLag or ((LastVoice.snd <> sndNone) and (lastChan[LastVoice.snd] <> -1) and (Mix_Playing(lastChan[LastVoice.snd]) <> 0)) then |
656 exit; |
680 exit; |
657 i:= 0; |
681 i:= 0; |
658 while (i<High(VoiceList)) and (VoiceList[i].snd = sndNone) do |
682 while (i<High(VoiceList)) and (VoiceList[i].snd = sndNone) do |
659 inc(i); |
683 inc(i); |
660 |
684 |
661 if (VoiceList[i].snd <> sndNone) then |
685 played:= false; |
|
686 if (VoiceList[i].snd <> sndNone) and ((not VoiceList[i].isFallback) or LastVoiceFailed) then |
662 begin |
687 begin |
663 LastVoice.snd:= VoiceList[i].snd; |
688 LastVoice.snd:= VoiceList[i].snd; |
664 LastVoice.voicepack:= VoiceList[i].voicepack; |
689 LastVoice.voicepack:= VoiceList[i].voicepack; |
|
690 LastVoice.isFallback:= VoiceList[i].isFallback; |
665 VoiceList[i].snd:= sndNone; |
691 VoiceList[i].snd:= sndNone; |
666 PlaySoundV(LastVoice.snd, LastVoice.voicepack) |
692 played:= PlaySoundV(LastVoice.snd, LastVoice.voicepack); |
|
693 // Remember if sound was not played. |
|
694 LastVoiceFailed:= (not played); |
667 end |
695 end |
668 else LastVoice.snd:= sndNone; |
696 else |
|
697 LastVoice.snd:= sndNone; |
669 end; |
698 end; |
670 |
699 |
671 function LoopSound(snd: TSound): LongInt; |
700 function LoopSound(snd: TSound): LongInt; |
672 begin |
701 begin |
673 LoopSound:= LoopSoundV(snd, nil) |
702 LoopSound:= LoopSoundV(snd, nil) |