mahlendur/_work/Data/Scripts/Content/Misc/sound.d
Daniel Heße 892a40ff0f Initial commit with Subversion-codebase from 13/05/2022.
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.
2022-05-13 17:38:52 +02:00

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);
};