Cleaned up the mess, at this time, only viable data get synced (_work directory for Gothic-data, miranda for mdc-scripts. Need to symlink files to a working directory.
383 lines
No EOL
13 KiB
D
383 lines
No EOL
13 KiB
D
/*
|
|
* sound.d
|
|
*
|
|
* Sound and music functions
|
|
*
|
|
* - Requires Ikarus, LeGo (Anim8), searchVobs.d, insertAnything.d
|
|
* - Compatible with Gothic 1 and Gothic 2
|
|
* - Initialization with restoreMasterVolumeSoundsToDefault() and/or restoreVolumeMusicToDefault() recommended
|
|
*
|
|
* When using the setVolumne-functions or fadeOut-functions, make sure to call
|
|
* restoreMasterVolumeSoundsToDefault() and/or restoreVolumeMusicToDefault()
|
|
* in Init_Global to restore the volume on loading/new game!
|
|
*
|
|
* The volumes will always be reset to their defaults after loading a game. Thus, this script does not take care of
|
|
* maintaining the volume over saving and loading a game.
|
|
*
|
|
* Keep in mind, that you cannot call the fadeOut-functions from startup. LeGo has to be initialized first. The LeGo
|
|
* package GameState can compensate for that.
|
|
*
|
|
*
|
|
* func void stopAllSounds()
|
|
* func void fadeOutAllSounds(int fadeOutMS, int waitMS, int fadeInMS, int killSounds)
|
|
* func int getMasterVolumeSounds()
|
|
* func void setMasterVolumeSounds(int volume)
|
|
* func void restoreMasterVolumeSoundsToDefault()
|
|
*
|
|
* func void stopMusic()
|
|
* func void fadeOutMusic(int fadeOutMS, int waitMS, int fadeInMS, int killMusic)
|
|
* func void playMusic(string music, int transition)
|
|
* func int getVolumeMusic()
|
|
* func void setVolumeMusic(int volume)
|
|
* func void restoreVolumeMusicToDefault()
|
|
*
|
|
* func void setMusicZoneTheme(string vobName, string musicTheme)
|
|
* func void setCurrentMusicZoneTheme(string musicTheme)
|
|
* func string getCurrentMusicZoneTheme()
|
|
* func void setAllMusicZoneThemes(string musicTheme)
|
|
*/
|
|
|
|
/*
|
|
* Stop all effect and speech sounds of the game instantly
|
|
*/
|
|
func void stopAllSounds() {
|
|
MEM_InitAll();
|
|
|
|
const int zsound_G1 = 9236044; //0x8CEE4C
|
|
const int zsound_G2 = 10072124; //0x99B03C
|
|
const int zCSndSys_MSS__RemoveAllActiveSounds_G1 = 5112224; //0x4E01A0
|
|
const int zCSndSys_MSS__RemoveAllActiveSounds_G2 = 5167008; //0x4ED7A0
|
|
|
|
var int zsoundPtr; zsoundPtr = MEM_ReadInt(MEMINT_SwitchG1G2(zsound_G1, zsound_G2));
|
|
const int call = 0;
|
|
if (CALL_Begin(call)) {
|
|
CALL__thiscall(_@(zsoundPtr), MEMINT_SwitchG1G2(zCSndSys_MSS__RemoveAllActiveSounds_G1,
|
|
zCSndSys_MSS__RemoveAllActiveSounds_G2));
|
|
call = CALL_End();
|
|
};
|
|
};
|
|
|
|
|
|
/*
|
|
* Get master volume sound
|
|
*/
|
|
func int getMasterVolumeSounds() {
|
|
const int zCSndSys_MSS__prefs_G1 = 8837192; //0x86D848
|
|
const int zCSndSys_MSS__prefs_G2 = 9249512; //0x8D22E8
|
|
return MEM_ReadInt(MEMINT_SwitchG1G2(zCSndSys_MSS__prefs_G1, zCSndSys_MSS__prefs_G2));
|
|
};
|
|
|
|
|
|
/*
|
|
* Backup default master volume sound
|
|
*/
|
|
func int getMasterVolumeSoundsDefault() {
|
|
const int soundDefVol = 0;
|
|
|
|
if (!soundDefVol) {
|
|
soundDefVol = getMasterVolumeSounds();
|
|
};
|
|
|
|
return soundDefVol;
|
|
};
|
|
|
|
|
|
/*
|
|
* Set master volume of sounds
|
|
* Caution: This control differs from the volume settings in the menu, be sure to always reset it!
|
|
*/
|
|
func void setMasterVolumeSounds(var int volume) {
|
|
const int zsound_G1 = 9236044; //0x8CEE4C
|
|
const int zsound_G2 = 10072124; //0x99B03C
|
|
const int zCSndSys_MSS__SetMasterVolume_G1 = 5112544; //0x4E02E0
|
|
const int zCSndSys_MSS__SetMasterVolume_G2 = 5167328; //0x4ED8E0
|
|
const int mss32_AILptr_G1 = 8838412; //0x86DD0C
|
|
const int mss32_AILptr_G2 = 9251444; //0x8D2A74
|
|
|
|
// Prevent crash by checking if sound was initialized (if sound is disabled)
|
|
if (!MEMINT_SwitchG1G2(MEM_ReadInt(mss32_AILptr_G1), MEM_ReadInt(mss32_AILptr_G2))) {
|
|
return;
|
|
};
|
|
|
|
// Backup default volume before changing it
|
|
var int i; i = getMasterVolumeSoundsDefault();
|
|
|
|
var int zsoundPtr; zsoundPtr = MEM_ReadInt(MEMINT_SwitchG1G2(zsound_G1, zsound_G2));
|
|
const int call = 0;
|
|
if (CALL_Begin(call)) {
|
|
CALL_FloatParam(_@(volume));
|
|
CALL__thiscall(_@(zsoundPtr), MEMINT_SwitchG1G2(zCSndSys_MSS__SetMasterVolume_G1,
|
|
zCSndSys_MSS__SetMasterVolume_G2));
|
|
call = CALL_End();
|
|
};
|
|
};
|
|
|
|
|
|
/*
|
|
* Restore default sound master volume
|
|
* Call this function from Init_Global to ensure working sound after loading
|
|
*/
|
|
func void restoreMasterVolumeSoundsToDefault() {
|
|
setMasterVolumeSounds(getMasterVolumeSoundsDefault());
|
|
};
|
|
|
|
|
|
/*
|
|
* Fade out all sounds
|
|
* Leave sound muted indefinitely by setting fadeInMS to -1
|
|
*/
|
|
func void fadeOutAllSounds(var int fadeOutMS, var int waitMS, var int fadeInMS, var int killSounds) {
|
|
// Retrieve and backup master volume
|
|
var int sVol; sVol = getMasterVolumeSounds();
|
|
|
|
// Start fade out
|
|
var int a8; a8 = Anim8_NewExt(sVol, soundFadeHandler, killSounds, TRUE);
|
|
Anim8_RemoveIfEmpty(a8, TRUE);
|
|
|
|
Anim8(a8, FLOATNULL, fadeOutMS, A8_SlowEnd);
|
|
Anim8q(a8, FLOATNULL, waitMS, A8_Wait);
|
|
if (fadeInMS != -1) {
|
|
Anim8q(a8, sVol, fadeInMS, A8_SlowStart);
|
|
};
|
|
};
|
|
func void soundFadeHandler(var int killSounds, var int value) {
|
|
// Once quiet: Kill all sounds if desired
|
|
if (!value) && (killSounds) {
|
|
stopAllSounds();
|
|
};
|
|
setMasterVolumeSounds(value);
|
|
};
|
|
|
|
|
|
/*
|
|
* Stop the music instantly
|
|
*/
|
|
func void stopMusic() {
|
|
MEM_InitAll();
|
|
|
|
const int zmusic_G1 = 8836220; //0x86D47C
|
|
const int zmusic_G2 = 9248532; //0x8D1F14
|
|
const int zCMusicSys_DirectMusic__Stop_G1 = 5098480; //0x4DCBF0
|
|
const int zCMusicSys_DirectMusic__Stop_G2 = 5152544; //0x4E9F20
|
|
const int zCMusicSystem__s_musicSystemDisabled_G1 = 8836224; //0x86D480
|
|
const int zCMusicSystem__s_musicSystemDisabled_G2 = 9248536; //0x8D1F18
|
|
|
|
// Prevent crash by checking if music system was initialized (if music is disabled)
|
|
if (MEMINT_SwitchG1G2(MEM_ReadInt(zCMusicSystem__s_musicSystemDisabled_G1),
|
|
MEM_ReadInt(zCMusicSystem__s_musicSystemDisabled_G2))) {
|
|
return;
|
|
};
|
|
|
|
var int zmusicPtr; zmusicPtr = MEMINT_SwitchG1G2(MEM_ReadInt(zmusic_G1), MEM_ReadInt(zmusic_G2));
|
|
const int call = 0;
|
|
if (CALL_Begin(call)) {
|
|
CALL__thiscall(_@(zmusicPtr), MEMINT_SwitchG1G2(zCMusicSys_DirectMusic__Stop_G1,
|
|
zCMusicSys_DirectMusic__Stop_G2));
|
|
call = CALL_End();
|
|
};
|
|
};
|
|
|
|
|
|
/*
|
|
* Get music volume
|
|
*/
|
|
func int getVolumeMusic() {
|
|
const int zmusic_G1 = 8836220; //0x86D47C
|
|
const int zmusic_G2 = 9248532; //0x8D1F14
|
|
const int zCMusicSys_DirectMusic_volume_offset = 12; //0Ch same for G1 and G2
|
|
|
|
var int zmusicPtr; zmusicPtr = MEMINT_SwitchG1G2(MEM_ReadInt(zmusic_G1), MEM_ReadInt(zmusic_G2));
|
|
return MEM_ReadInt(zmusicPtr+zCMusicSys_DirectMusic_volume_offset);
|
|
};
|
|
|
|
|
|
/*
|
|
* Backup default music volume
|
|
*/
|
|
func int getVolumeMusicDefault() {
|
|
const int musicDefVol = 0;
|
|
|
|
if (!musicDefVol) {
|
|
musicDefVol = getVolumeMusic();
|
|
};
|
|
|
|
return musicDefVol;
|
|
};
|
|
|
|
|
|
/*
|
|
* Set volume of music
|
|
* Caution: This control differs from the volume settings in the menu, be sure to always reset it!
|
|
*/
|
|
func void setVolumeMusic(var int volume) {
|
|
const int zmusic_G1 = 8836220; //0x86D47C
|
|
const int zmusic_G2 = 9248532; //0x8D1F14
|
|
const int zCMusicSys_DirectMusic__SetVolume_G1 = 5098624; //0x4DCC80
|
|
const int zCMusicSys_DirectMusic__SetVolume_G2 = 5152720; //0x4E9FD0
|
|
const int zCMusicSystem__s_musicSystemDisabled_G1 = 8836224; //0x86D480
|
|
const int zCMusicSystem__s_musicSystemDisabled_G2 = 9248536; //0x8D1F18
|
|
|
|
// Prevent crash by checking if music system was initialized (if music is disabled)
|
|
if (MEMINT_SwitchG1G2(MEM_ReadInt(zCMusicSystem__s_musicSystemDisabled_G1),
|
|
MEM_ReadInt(zCMusicSystem__s_musicSystemDisabled_G2))) {
|
|
return;
|
|
};
|
|
|
|
// Backup default volume before changing it
|
|
var int i; i = getVolumeMusicDefault();
|
|
|
|
var int zmusicPtr; zmusicPtr = MEMINT_SwitchG1G2(MEM_ReadInt(zmusic_G1), MEM_ReadInt(zmusic_G2));
|
|
const int call = 0;
|
|
if (CALL_Begin(call)) {
|
|
CALL_FloatParam(_@(volume));
|
|
CALL__thiscall(_@(zmusicPtr), MEMINT_SwitchG1G2(zCMusicSys_DirectMusic__SetVolume_G1,
|
|
zCMusicSys_DirectMusic__SetVolume_G2));
|
|
call = CALL_End();
|
|
};
|
|
};
|
|
|
|
|
|
/*
|
|
* Restore default music volume
|
|
* Call this function from Init_Global to ensure working music after loading
|
|
*/
|
|
func void restoreVolumeMusicToDefault() {
|
|
setVolumeMusic(getVolumeMusicDefault());
|
|
};
|
|
|
|
|
|
/*
|
|
* Fade out the music
|
|
* Leave music muted indefinitely by setting fadeInMS to -1
|
|
*/
|
|
func void fadeOutMusic(var int fadeOutMS, var int waitMS, var int fadeInMS, var int killMusic) {
|
|
// Retrieve and backup music volume
|
|
var int mVol; mVol = getVolumeMusic();
|
|
|
|
// Start fade out
|
|
var int a8; a8 = Anim8_NewExt(mVol, musicFadeHandler, killMusic, TRUE);
|
|
Anim8_RemoveIfEmpty(a8, TRUE);
|
|
|
|
Anim8(a8, FLOATNULL, fadeOutMS, A8_SlowEnd);
|
|
Anim8q(a8, FLOATNULL, waitMS, A8_Wait);
|
|
if (fadeInMS != -1) {
|
|
Anim8q(a8, mVol, fadeInMS, A8_SlowStart);
|
|
};
|
|
};
|
|
func void musicFadeHandler(var int killMusic, var int value) {
|
|
// Once quiet: Kill music if desired
|
|
if (!value) && (killMusic) {
|
|
stopMusic();
|
|
};
|
|
setVolumeMusic(value);
|
|
};
|
|
|
|
|
|
/*
|
|
* Play music by script instance, e.g. "XAR_Day_Std"
|
|
* The second argument may be either be 0 (musical transition?), 1 (?) or 2 (some thing like fade out/fade in?)
|
|
*/
|
|
func void playMusic(var string music, var int transition) {
|
|
const int zmusic_G1 = 8836220; //0x86D47C
|
|
const int zmusic_G2 = 9248532; //0x8D1F14
|
|
const int zCMusicSys_DirectMusic__PlayThemeByScript_G1 = 5093456; //0x4DB850
|
|
const int zCMusicSys_DirectMusic__PlayThemeByScript_G2 = 5147312; //0x4E8AB0
|
|
|
|
var int zmusicPtr; zmusicPtr = MEMINT_SwitchG1G2(MEM_ReadInt(zmusic_G1), MEM_ReadInt(zmusic_G2));
|
|
var int musicPtr; musicPtr = _@s(music);
|
|
|
|
var int zero;
|
|
const int call = 0;
|
|
if (CALL_Begin(call)) {
|
|
CALL_PtrParam(_@(zero)); // Some pointer
|
|
CALL_IntParam(_@(transition)); // zTMus_TransType: either 0, 1 or 2
|
|
CALL_PtrParam(_@(musicPtr));
|
|
CALL__thiscall(_@(zmusicPtr), MEMINT_SwitchG1G2(zCMusicSys_DirectMusic__PlayThemeByScript_G1,
|
|
zCMusicSys_DirectMusic__PlayThemeByScript_G2));
|
|
call = CALL_End();
|
|
};
|
|
};
|
|
|
|
|
|
/*
|
|
* Overwrite the music theme of a music zone
|
|
*
|
|
* This function will permanently change the music theme for a certain music zone. This change is preserved over
|
|
* saving/loading, but not across saves.
|
|
* The first parameter is the object name of the oCZoneMusic vob.
|
|
* The second parameter is the new post fix identifying the music theme, e.g. "XAR"
|
|
*
|
|
* The transition in music will be instant (given that the player is in the affected zone).
|
|
*/
|
|
func void setMusicZoneTheme(var string vobName, var string musicTheme) {
|
|
// Find all vobs of this zone, there are multiple!
|
|
var int arrPtr; arrPtr = MEM_SearchAllVobsByName(vobName);
|
|
|
|
// Build new vob name
|
|
var string newName; newName = ConcatStrings(STR_Prefix(vobName, STR_Len(vobName)-3), musicTheme);
|
|
|
|
// Iterate over all music zones and exchange their identifier
|
|
var zCArray arr; arr = _^(arrPtr);
|
|
repeat(j, arr.numInArray); var int j;
|
|
var int vobPtr; vobPtr = MEM_ArrayRead(arrPtr, j);
|
|
MEM_RenameVob(vobPtr, newName);
|
|
end;
|
|
|
|
// Free array
|
|
MEM_ArrayFree(arrPtr);
|
|
};
|
|
|
|
|
|
/*
|
|
* Overwrite the music theme of the current music zone
|
|
*/
|
|
func void setCurrentMusicZoneTheme(var string musicTheme) {
|
|
if (!MEM_ReadInt(oCZoneMusic__s_musiczone_Address)) {
|
|
MEM_Warn("No music zone active. No changes performed.");
|
|
return;
|
|
};
|
|
|
|
// Not only change the current oCZoneMusic, but all matching ones in the area
|
|
var zCObject vob; vob = _^(MEM_ReadInt(oCZoneMusic__s_musiczone_Address));
|
|
setMusicZoneTheme(vob.objectName, musicTheme);
|
|
};
|
|
|
|
|
|
/*
|
|
* Get music theme of current music zone (as a prior backup for setCurrentMusicZoneTheme above)
|
|
*/
|
|
func string getCurrentMusicZoneTheme() {
|
|
if (!MEM_ReadInt(oCZoneMusic__s_musiczone_Address)) {
|
|
MEM_Warn("No music zone active.");
|
|
return "";
|
|
};
|
|
|
|
var zCObject vob; vob = _^(MEM_ReadInt(oCZoneMusic__s_musiczone_Address));
|
|
return STR_SubStr(vob.objectName, STR_Len(vob.objectName)-3, 3);
|
|
};
|
|
|
|
|
|
/*
|
|
* Overwrite the music theme of all music zones
|
|
*/
|
|
func void setAllMusicZoneThemes(var string musicTheme) {
|
|
var int arrPtr; arrPtr = MEM_ArrayCreate();
|
|
if (SearchVobsByClass("oCZoneMusic", arrPtr)) {
|
|
// Iterate over all oCZoneMusic vobs
|
|
var zCArray arr; arr = _^(arrPtr);
|
|
repeat(i, arr.numInArray); var int i;
|
|
var int vobPtr; vobPtr = MEM_ArrayRead(arrPtr, i);
|
|
var zCObject vob; vob = _^(vobPtr);
|
|
|
|
// Build new vob name
|
|
var string vobName; vobName = vob.objectName;
|
|
var string newName; newName = ConcatStrings(STR_Prefix(vobName, STR_Len(vobName)-3), musicTheme);
|
|
|
|
// Exchange music theme identifier
|
|
MEM_RenameVob(vobPtr, newName);
|
|
end;
|
|
};
|
|
|
|
// Free array
|
|
MEM_ArrayFree(arrPtr);
|
|
}; |