- scriptified the sound controller.

This commit is contained in:
Christoph Oelckers 2022-11-20 08:10:15 +01:00
parent 714a2ef70e
commit f515939fde
17 changed files with 202 additions and 80 deletions

View file

@ -14,3 +14,4 @@ xx(AltHud)
// internal Duke actor classes that need direct checking
xx(DukeMasterSwitch)
xx(DukeTouchplate)
xx(DukeSoundController)

View file

@ -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

View file

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

View file

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

View file

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

View file

@ -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;

View file

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

View file

@ -522,8 +522,6 @@ DDukeActor* spawninit_d(DDukeActor* actj, DDukeActor* act, TArray<DDukeActor*>*
case RESPAWN:
act->spr.extra = 66 - 13;
[[fallthrough]];
case MUSICANDSFX:
if (ud.multimode < 2 && act->spr.pal == 1)
{
act->spr.scale = DVector2(0, 0);

View file

@ -571,8 +571,6 @@ DDukeActor* spawninit_r(DDukeActor* actj, DDukeActor* act, TArray<DDukeActor*>*
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);

View file

@ -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)

View file

@ -1,7 +1,8 @@
spawnclasses
{
8 = DukeMasterSwitch
3 = DukeTouchplate
5 = DukeSoundController
8 = DukeMasterSwitch
1221 = DukeCranePole
1222 = DukeCrane

View file

@ -1,7 +1,8 @@
spawnclasses
{
8 = DukeMasterSwitch
3 = DukeTouchplate
5 = DukeSoundController
8 = DukeMasterSwitch
1298 = DukeCranePole
1299 = DukeCrane

View file

@ -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"

View file

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

View file

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

View file

@ -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()
{

View file

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