From f515939fde8964199524420e81c04c5f055e74ea Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 20 Nov 2022 08:10:15 +0100 Subject: [PATCH] - scriptified the sound controller. --- source/core/namedef_custom.h | 1 + source/core/vmexports.cpp | 22 +++++ source/games/duke/src/actors.cpp | 67 +------------- source/games/duke/src/funct.h | 1 - source/games/duke/src/inlines.h | 5 ++ source/games/duke/src/sectors.cpp | 2 +- source/games/duke/src/sounds.cpp | 10 +-- source/games/duke/src/spawn_d.cpp | 2 - source/games/duke/src/spawn_r.cpp | 2 - source/games/duke/src/vmexports.cpp | 28 +++++- wadsrc/static/filter/duke/engine/engine.def | 3 +- .../static/filter/redneck/engine/engine.def | 3 +- wadsrc/static/zscript.txt | 1 + .../games/duke/actors/soundcontroller.zs | 87 +++++++++++++++++++ wadsrc/static/zscript/games/duke/dukeactor.zs | 32 ++++++- wadsrc/static/zscript/games/duke/dukegame.zs | 13 +++ wadsrc/static/zscript/razebase.zs | 3 + 17 files changed, 202 insertions(+), 80 deletions(-) create mode 100644 wadsrc/static/zscript/games/duke/actors/soundcontroller.zs diff --git a/source/core/namedef_custom.h b/source/core/namedef_custom.h index 4c989ff5d..007149db0 100644 --- a/source/core/namedef_custom.h +++ b/source/core/namedef_custom.h @@ -14,3 +14,4 @@ xx(AltHud) // internal Duke actor classes that need direct checking xx(DukeMasterSwitch) xx(DukeTouchplate) +xx(DukeSoundController) diff --git a/source/core/vmexports.cpp b/source/core/vmexports.cpp index 4e0ff8081..3b4d44f61 100644 --- a/source/core/vmexports.cpp +++ b/source/core/vmexports.cpp @@ -36,6 +36,7 @@ #include "maptypes.h" #include "vm.h" #include "gamefuncs.h" +#include "raze_sound.h" sectortype* Raze_updatesector(double x, double y, sectortype* sec, double dist) { @@ -53,6 +54,27 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Raze, updatesector, Raze_updatesector) ACTION_RETURN_POINTER(Raze_updatesector(x, y, s, dist)); } +DEFINE_ACTION_FUNCTION_NATIVE(_Raze, SoundEnabled, SoundEnabled) +{ + ACTION_RETURN_INT(SoundEnabled()); +} + +DEFINE_ACTION_FUNCTION_NATIVE(_Raze, SetReverb, FX_SetReverb) +{ + PARAM_PROLOGUE; + PARAM_INT(i); + FX_SetReverb(i); + return 0; +} + +DEFINE_ACTION_FUNCTION_NATIVE(_Raze, SetReverbDelay, FX_SetReverbDelay) +{ + PARAM_PROLOGUE; + PARAM_INT(i); + FX_SetReverbDelay(i); + return 0; +} + //============================================================================= // // internal sector struct - no longer identical with on-disk format diff --git a/source/games/duke/src/actors.cpp b/source/games/duke/src/actors.cpp index a8174b91e..e6debe155 100644 --- a/source/games/duke/src/actors.cpp +++ b/source/games/duke/src/actors.cpp @@ -86,9 +86,6 @@ void RANDOMSCRAP(DDukeActor* origin) void deletesprite(DDukeActor *const actor) { - if (actor->spr.picnum == MUSICANDSFX && actor->temp_data[0] == 1) - S_StopSound(actor->spr.lotag, actor); - actor->Destroy(); } @@ -532,13 +529,15 @@ void moveplayers(void) void movefx(void) { - int p; - DukeStatIterator iti(STAT_FX); while (auto act = iti.Next()) { switch (act->spr.picnum) { + default: + CallTick(act); + break; + case RESPAWN: if (act->spr.extra == 66) { @@ -556,64 +555,6 @@ void movefx(void) act->spr.extra++; break; - case MUSICANDSFX: - { - double maxdist = act->spr.hitag * maptoworld; - - if (act->temp_data[1] != (int)SoundEnabled()) - { - act->temp_data[1] = SoundEnabled(); - act->temp_data[0] = 0; - } - - if (act->spr.lotag >= 1000 && act->spr.lotag < 2000) - { - double dist = (ps[screenpeek].GetActor()->spr.pos.XY() - act->spr.pos.XY()).Length(); - if (dist < maxdist && act->temp_data[0] == 0) - { - FX_SetReverb(act->spr.lotag - 1100); - act->temp_data[0] = 1; - } - if (dist >= maxdist && act->temp_data[0] == 1) - { - FX_SetReverb(0); - FX_SetReverbDelay(0); - act->temp_data[0] = 0; - } - } - else if (act->spr.lotag < 999 && (unsigned)act->sector()->lotag < ST_9_SLIDING_ST_DOOR && snd_ambience && act->sector()->floorz != act->sector()->ceilingz) - { - int flags = S_GetUserFlags(act->spr.lotag); - if (flags & SF_MSFX) - { - double distance = (ps[screenpeek].GetActor()->spr.pos - act->spr.pos).Length(); - - if (distance < maxdist && act->temp_data[0] == 0) - { - // Start playing an ambience sound. - S_PlayActorSound(act->spr.lotag, act, CHAN_AUTO, CHANF_LOOP); - act->temp_data[0] = 1; // AMBIENT_SFX_PLAYING - } - else if (distance >= maxdist && act->temp_data[0] == 1) - { - // Stop playing ambience sound because we're out of its range. - S_StopSound(act->spr.lotag, act); - } - } - - if ((flags & (SF_GLOBAL | SF_DTAG)) == SF_GLOBAL) - { - if (act->temp_data[4] > 0) act->temp_data[4]--; - else for (p = connecthead; p >= 0; p = connectpoint2[p]) - if (p == myconnectindex && ps[p].cursector == act->sector()) - { - S_PlaySound(act->spr.lotag + (unsigned)global_random % (act->spr.hitag + 1)); - act->temp_data[4] = 26 * 40 + (global_random % (26 * 40)); - } - } - } - break; - } } } } diff --git a/source/games/duke/src/funct.h b/source/games/duke/src/funct.h index fe8fb0f1a..9bce831b4 100644 --- a/source/games/duke/src/funct.h +++ b/source/games/duke/src/funct.h @@ -32,7 +32,6 @@ void movefta(); void clearcameras(player_struct* p); void RANDOMSCRAP(DDukeActor* i); void detonate(DDukeActor* i, int explosion); -void movecanwithsomething(DDukeActor* i); void bounce(DDukeActor* i); void movetongue(DDukeActor* i, int tongue, int jaw); void rpgexplode(DDukeActor* i, int j, const DVector3& pos, int EXPLOSION2, int EXPLOSIONBOT2, int newextra, int playsound); diff --git a/source/games/duke/src/inlines.h b/source/games/duke/src/inlines.h index 6e52ff5b7..6eb37ee70 100644 --- a/source/games/duke/src/inlines.h +++ b/source/games/duke/src/inlines.h @@ -19,6 +19,11 @@ inline int ismasterswitch(DDukeActor* actor) return actor->GetClass()->TypeName == NAME_DukeMasterSwitch && actor->spr.statnum != STAT_REMOVED; } +inline int issoundcontroller(DDukeActor* actor) +{ + return actor->GetClass()->TypeName == NAME_DukeSoundController; +} + inline int badguypic(int const tileNum) { return ((gs.actorinfo[tileNum].flags & (SFLAG_INTERNAL_BADGUY | SFLAG_BADGUY)) != 0); diff --git a/source/games/duke/src/sectors.cpp b/source/games/duke/src/sectors.cpp index a63e69c86..6307d0633 100644 --- a/source/games/duke/src/sectors.cpp +++ b/source/games/duke/src/sectors.cpp @@ -62,7 +62,7 @@ int callsound(sectortype* sn, DDukeActor* whatsprite, bool endstate) DukeSectIterator it(sn); while (auto act = it.Next()) { - if (act->spr.picnum == MUSICANDSFX && act->spr.lotag < 1000) + if (issoundcontroller(act) && act->spr.lotag < 1000) { if (whatsprite == nullptr) whatsprite = act; diff --git a/source/games/duke/src/sounds.cpp b/source/games/duke/src/sounds.cpp index 663b12889..3b2bbd7f8 100644 --- a/source/games/duke/src/sounds.cpp +++ b/source/games/duke/src/sounds.cpp @@ -244,7 +244,7 @@ int S_DefineSound(unsigned index, const char *filename, int minpitch, int maxpit inline bool S_IsAmbientSFX(DDukeActor* actor) { - return (actor->spr.picnum == MUSICANDSFX && actor->spr.lotag < 999); + return (issoundcontroller(actor) && actor->spr.lotag < 999); } //========================================================================== @@ -271,14 +271,14 @@ static int GetPositionInfo(DDukeActor* actor, int soundNum, sectortype* sect, { orgsndist = sndist = int(16 * (sndorg - campos).Length()); - if ((userflags & (SF_GLOBAL | SF_DTAG)) != SF_GLOBAL && actor->spr.picnum == MUSICANDSFX && actor->spr.lotag < 999 && (actor->sector()->lotag & 0xff) < ST_9_SLIDING_ST_DOOR) + if ((userflags & (SF_GLOBAL | SF_DTAG)) != SF_GLOBAL && issoundcontroller(actor) && actor->spr.lotag < 999 && (actor->sector()->lotag & 0xff) < ST_9_SLIDING_ST_DOOR) sndist = DivScale(sndist, actor->spr.hitag + 1, 14); } sndist += dist_adjust; if (sndist < 0) sndist = 0; - if (sect!= nullptr && sndist && actor->spr.picnum != MUSICANDSFX && !cansee(cam.plusZ(-24), sect, actor->spr.pos.plusZ(-24), actor->sector())) + if (sect!= nullptr && sndist && !issoundcontroller(actor) && !cansee(cam.plusZ(-24), sect, actor->spr.pos.plusZ(-24), actor->sector())) sndist += sndist >> (isRR() ? 2 : 5); // Here the sound distance was clamped to a minimum of 144*4. @@ -471,7 +471,7 @@ int S_PlaySound3D(int sndnum, DDukeActor* actor, const DVector3& pos, int channe } else { - if (sndist > 32767 && actor->spr.picnum != MUSICANDSFX && (userflags & (SF_LOOP | SF_MSFX)) == 0) + if (sndist > 32767 && !issoundcontroller(actor) && (userflags & (SF_LOOP | SF_MSFX)) == 0) return -1; if (underwater && (userflags & SF_TALK) == 0) @@ -479,7 +479,7 @@ int S_PlaySound3D(int sndnum, DDukeActor* actor, const DVector3& pos, int channe } bool is_playing = soundEngine->GetSoundPlayingInfo(SOURCE_Any, nullptr, sndnum+1); - if (is_playing && actor->spr.picnum != MUSICANDSFX) + if (is_playing && !issoundcontroller(actor)) S_StopSound(sndnum, actor); int const repeatp = (userflags & SF_LOOP); diff --git a/source/games/duke/src/spawn_d.cpp b/source/games/duke/src/spawn_d.cpp index 9f5e0c8b1..d623c3d87 100644 --- a/source/games/duke/src/spawn_d.cpp +++ b/source/games/duke/src/spawn_d.cpp @@ -522,8 +522,6 @@ DDukeActor* spawninit_d(DDukeActor* actj, DDukeActor* act, TArray* case RESPAWN: act->spr.extra = 66 - 13; - [[fallthrough]]; - case MUSICANDSFX: if (ud.multimode < 2 && act->spr.pal == 1) { act->spr.scale = DVector2(0, 0); diff --git a/source/games/duke/src/spawn_r.cpp b/source/games/duke/src/spawn_r.cpp index daaaec894..82f35afae 100644 --- a/source/games/duke/src/spawn_r.cpp +++ b/source/games/duke/src/spawn_r.cpp @@ -571,8 +571,6 @@ DDukeActor* spawninit_r(DDukeActor* actj, DDukeActor* act, TArray* break; case RESPAWN: act->spr.extra = 66 - 13; - [[fallthrough]]; - case MUSICANDSFX: if (ud.multimode < 2 && act->spr.pal == 1) { act->spr.scale = DVector2(0, 0); diff --git a/source/games/duke/src/vmexports.cpp b/source/games/duke/src/vmexports.cpp index 3e04867d1..b5c7adc2a 100644 --- a/source/games/duke/src/vmexports.cpp +++ b/source/games/duke/src/vmexports.cpp @@ -107,6 +107,13 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Duke, global_random, duke_global_random) ACTION_RETURN_INT(global_random); } +DEFINE_ACTION_FUNCTION_NATIVE(_Duke, GetSoundFlags, S_GetUserFlags) +{ + PARAM_PROLOGUE; + PARAM_INT(snd); + ACTION_RETURN_INT(S_GetUserFlags(snd)); +} + DEFINE_GLOBAL_UNSIZED(dlevel) DEFINE_GLOBAL(camsprite) @@ -215,16 +222,31 @@ DEFINE_ACTION_FUNCTION_NATIVE(DDukeActor, domove, ssp) ACTION_RETURN_INT(ssp(self, clipmask)); } -int DukeActor_PlayActorSound(DDukeActor* self, int snd) +int DukeActor_PlayActorSound(DDukeActor* self, int snd, int chan, int flags) { - return S_PlayActorSound(snd, self); + return S_PlayActorSound(snd, self, chan, EChanFlags::FromInt(flags)); } DEFINE_ACTION_FUNCTION_NATIVE(DDukeActor, PlayActorSound, DukeActor_PlayActorSound) { PARAM_SELF_PROLOGUE(DDukeActor); PARAM_INT(snd); - ACTION_RETURN_INT(DukeActor_PlayActorSound(self, snd)); + PARAM_INT(chan); + PARAM_INT(flags); + ACTION_RETURN_INT(DukeActor_PlayActorSound(self, snd, chan, flags)); +} + +int DukeActor_StopSound(DDukeActor* self, int snd, int chan) +{ + return S_PlayActorSound(snd, self, chan); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DDukeActor, StopSound, DukeActor_StopSound) +{ + PARAM_SELF_PROLOGUE(DDukeActor); + PARAM_INT(snd); + PARAM_INT(chan); + ACTION_RETURN_INT(DukeActor_StopSound(self, snd, chan)); } DDukeActor* DukeActor_Spawn(DDukeActor* origin, int intname) diff --git a/wadsrc/static/filter/duke/engine/engine.def b/wadsrc/static/filter/duke/engine/engine.def index 574f04db3..97fbd892e 100644 --- a/wadsrc/static/filter/duke/engine/engine.def +++ b/wadsrc/static/filter/duke/engine/engine.def @@ -1,7 +1,8 @@ spawnclasses { - 8 = DukeMasterSwitch 3 = DukeTouchplate + 5 = DukeSoundController + 8 = DukeMasterSwitch 1221 = DukeCranePole 1222 = DukeCrane diff --git a/wadsrc/static/filter/redneck/engine/engine.def b/wadsrc/static/filter/redneck/engine/engine.def index a97d41568..6d83591b8 100644 --- a/wadsrc/static/filter/redneck/engine/engine.def +++ b/wadsrc/static/filter/redneck/engine/engine.def @@ -1,7 +1,8 @@ spawnclasses { - 8 = DukeMasterSwitch 3 = DukeTouchplate + 5 = DukeSoundController + 8 = DukeMasterSwitch 1298 = DukeCranePole 1299 = DukeCrane diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 8040abcfd..97fc45717 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -52,6 +52,7 @@ version "4.10" #include "zscript/games/duke/ui/menu.zs" #include "zscript/games/duke/actors/masterswitch.zs" #include "zscript/games/duke/actors/touchplate.zs" +#include "zscript/games/duke/actors/soundcontroller.zs" #include "zscript/games/duke/actors/crane.zs" #include "zscript/games/duke/actors/waterfountain.zs" #include "zscript/games/duke/actors/flammables.zs" diff --git a/wadsrc/static/zscript/games/duke/actors/soundcontroller.zs b/wadsrc/static/zscript/games/duke/actors/soundcontroller.zs new file mode 100644 index 000000000..154c17dd9 --- /dev/null +++ b/wadsrc/static/zscript/games/duke/actors/soundcontroller.zs @@ -0,0 +1,87 @@ + + +class DukeSoundController : DukeActor +{ + default + { + statnum STAT_FX; + } + + override void Initialize() + { + if (ud.multimode < 2 && self.pal == 1) + { + self.scale = (0, 0); + self.ChangeStat(STAT_MISC); + return; + } + self.cstat = CSTAT_SPRITE_INVISIBLE; + } + + override void Tick() + { + double maxdist = self.hitag * maptoworld; + + if (self.temp_data[1] != Raze.SoundEnabled()) + { + self.temp_data[1] = Raze.SoundEnabled(); + self.temp_data[0] = 0; + } + + if (self.lotag >= 1000 && self.lotag < 2000) + { + double dist = (Duke.GetViewPlayer().actor.pos.XY - self.pos.XY).LengthSquared(); + if (dist < maxdist * maxdist && self.temp_data[0] == 0) + { + Raze.SetReverb(self.lotag - 1100); + self.temp_data[0] = 1; + } + if (dist >= maxdist * maxdist && self.temp_data[0] == 1) + { + Raze.SetReverb(0); + Raze.SetReverbDelay(0); + self.temp_data[0] = 0; + } + } + else + { + let sec = self.sector; + if (self.lotag < 999 && sec.lotag >= 0 && sec.lotag < ST_9_SLIDING_ST_DOOR && snd_ambience && sec.floorz != sec.ceilingz) + { + int flags = Duke.GetSoundFlags(self.lotag); + if (flags & Duke.SF_MSFX) + { + double distance = (Duke.GetViewPlayer().actor.pos - self.pos).Length(); + + if (distance < maxdist && self.temp_data[0] == 0) + { + // Start playing an ambience sound. + self.PlayActorSound(self.lotag, CHAN_AUTO, CHANF_LOOP); + self.temp_data[0] = 1; // AMBIENT_SFX_PLAYING + } + else if (distance >= maxdist && self.temp_data[0] == 1) + { + // Stop playing ambience sound because we're out of its range. + self.StopSound(self.lotag); + } + } + + if ((flags & (Duke.SF_GLOBAL | Duke.SF_DTAG)) == Duke.SF_GLOBAL) + { + if (self.temp_data[4] > 0) self.temp_data[4]--; + else + { + Duke.PlaySound(self.lotag + uint(Duke.global_random()) % uint(self.hitag + 1)); + self.temp_data[4] = 26 * 40 + (Duke.global_random() % (26 * 40)); + } + } + } + } + } + + override void OnDestroy() + { + if (self.temp_data[0] == 1) + self.StopSound(self.lotag); + } +} diff --git a/wadsrc/static/zscript/games/duke/dukeactor.zs b/wadsrc/static/zscript/games/duke/dukeactor.zs index 40fcc6a1d..2b906f37b 100644 --- a/wadsrc/static/zscript/games/duke/dukeactor.zs +++ b/wadsrc/static/zscript/games/duke/dukeactor.zs @@ -49,6 +49,35 @@ enum EEffectorTypes SE_156_CONVEYOR_NOSCROLL = 156, }; +enum ESectorTriggers +{ + ST_0_NO_EFFECT = 0, + ST_1_ABOVE_WATER = 1, + ST_2_UNDERWATER = 2, + ST_3 = 3, + // ^^^ maybe not complete substitution in code + ST_9_SLIDING_ST_DOOR = 9, + ST_15_WARP_ELEVATOR = 15, + ST_16_PLATFORM_DOWN = 16, + ST_17_PLATFORM_UP = 17, + ST_18_ELEVATOR_DOWN = 18, + ST_19_ELEVATOR_UP = 19, + ST_20_CEILING_DOOR = 20, + ST_21_FLOOR_DOOR = 21, + ST_22_SPLITTING_DOOR = 22, + ST_23_SWINGING_DOOR = 23, + ST_25_SLIDING_DOOR = 25, + ST_26_SPLITTING_ST_DOOR = 26, + ST_27_STRETCH_BRIDGE = 27, + ST_28_DROP_FLOOR = 28, + ST_29_TEETH_DOOR = 29, + ST_30_ROTATE_RISE_BRIDGE = 30, + ST_31_TWO_WAY_TRAIN = 31, + + ST_41_JAILDOOR = 41, + ST_42_MINECART = 42, + // left: ST 32767, 65534, 65535 +}; class DukeActor : CoreActor native { @@ -126,7 +155,8 @@ class DukeActor : CoreActor native native DukePlayer, double findplayer(); native int ifhitbyweapon(); native int domove(int clipmask); - native void PlayActorSound(int snd); + native void PlayActorSound(int snd, int chan = CHAN_AUTO, int flags = 0); + native void StopSound(int snd, int chan = -1); native DukeActor spawn(Name type); native DukeActor spawnsprite(int type); // for cases where the map has a picnum stored. Avoid when possible. native DukeActor spawnweaponorammo(int type); diff --git a/wadsrc/static/zscript/games/duke/dukegame.zs b/wadsrc/static/zscript/games/duke/dukegame.zs index b2cf9ce02..82b09cb4b 100644 --- a/wadsrc/static/zscript/games/duke/dukegame.zs +++ b/wadsrc/static/zscript/games/duke/dukegame.zs @@ -77,6 +77,18 @@ struct Duke native TFLAG_SLIME = 16, }; + enum ESoundFlags + { + SF_LOOP = 1, + SF_MSFX = 2, + SF_TALK = 4, + SF_ADULT = 8, + SF_GLOBAL = 16, + SF_ONEINST_INTERNAL = 32, + + SF_DTAG = 128, + }; + native static void PlaySpecialMusic(int which); native static int PlaySound(int num, int channel = CHAN_AUTO, int flags = 0, float vol =0.8f); @@ -87,6 +99,7 @@ struct Duke native native static DukePlayer checkcursectnums(sectortype sect); native static int floorflags(sectortype s); native static int global_random(); + native static int GetSoundFlags(int sound); static void PlayBonusMusic() { diff --git a/wadsrc/static/zscript/razebase.zs b/wadsrc/static/zscript/razebase.zs index 708d5cd27..d27ce4be5 100644 --- a/wadsrc/static/zscript/razebase.zs +++ b/wadsrc/static/zscript/razebase.zs @@ -149,6 +149,9 @@ struct Raze native static int GetBuildTime(); native static Font PickBigFont(String cmptext = ""); native static Font PickSmallFont(String cmptext = ""); + native static int SoundEnabled(); + native static void SetReverb(int r); + native static void SetReverbDelay(int d); native static sectortype updatesector(Vector2 pos, sectortype lastsect, double maxdist = 96);