diff --git a/Makefile.mingw b/Makefile.mingw index c38d49f4d..ecdce9da3 100644 --- a/Makefile.mingw +++ b/Makefile.mingw @@ -179,6 +179,7 @@ OBJECTS += \ $(OBJDIR)/tempfiles.o \ $(OBJDIR)/thingdef.o \ $(OBJDIR)/thingdef_codeptr.o \ + $(OBJDIR)/thingdef_exp.o \ $(OBJDIR)/v_collection.o \ $(OBJDIR)/v_draw.o \ $(OBJDIR)/v_font.o \ @@ -222,7 +223,6 @@ OBJECTS += \ $(OBJDIR)/a_chicken.o \ $(OBJDIR)/a_clink.o \ $(OBJDIR)/a_dsparil.o \ - $(OBJDIR)/a_hereticambience.o \ $(OBJDIR)/a_hereticarmor.o \ $(OBJDIR)/a_hereticartifacts.o \ $(OBJDIR)/a_hereticdecorations.o \ @@ -344,6 +344,7 @@ OBJECTS += \ $(OBJDIR)/a_sharedmisc.o \ $(OBJDIR)/a_skies.o \ $(OBJDIR)/a_soundenvironment.o \ + $(OBJDIR)/a_soundsequence.o \ $(OBJDIR)/a_spark.o \ $(OBJDIR)/a_splashes.o \ $(OBJDIR)/a_waterzone.o \ diff --git a/default.cbd b/default.cbd index d1d5e4d46..a3e4d36dd 100644 --- a/default.cbd +++ b/default.cbd @@ -164,7 +164,7 @@ ${COMPILER} "autostart.cpp a.nas blocks.nas misc.nas tmap.nas tmap2.nas tmap3.na a_doomimp.cpp a_doomkeys.cpp a_doommisc.cpp a_doomplayer.cpp a_doomweaps.cpp \ a_fatso.cpp a_keen.cpp a_lostsoul.cpp a_painelemental.cpp a_possessed.cpp \ a_revenant.cpp a_scriptedmarine.cpp a_spidermaster.cpp doom_sbar.cpp a_beast.cpp \ - a_chicken.cpp a_clink.cpp a_dsparil.cpp a_hereticambience.cpp a_hereticarmor.cpp \ + a_chicken.cpp a_clink.cpp a_dsparil.cpp a_hereticarmor.cpp \ a_hereticartifacts.cpp a_hereticdecorations.cpp a_hereticimp.cpp a_heretickeys.cpp \ a_hereticmisc.cpp a_hereticplayer.cpp a_hereticweaps.cpp a_ironlich.cpp \ a_knight.cpp a_mummy.cpp a_snake.cpp a_wizard.cpp heretic_sbar.cpp a_bats.cpp \ @@ -190,7 +190,7 @@ ${COMPILER} "autostart.cpp a.nas blocks.nas misc.nas tmap.nas tmap2.nas tmap3.na a_camera.cpp a_debris.cpp a_decals.cpp a_flashfader.cpp a_fountain.cpp \ a_hatetarget.cpp a_keys.cpp a_lightning.cpp a_movingcamera.cpp a_pickups.cpp \ a_quake.cpp a_secrettrigger.cpp a_sectoraction.cpp a_sharedmisc.cpp a_skies.cpp \ - a_soundenvironment.cpp a_spark.cpp a_splashes.cpp a_waterzone.cpp a_weaponpiece.cpp a_weapons.cpp \ + a_soundenvironment.cpp a_soundsequence.cpp a_spark.cpp a_splashes.cpp a_waterzone.cpp a_weaponpiece.cpp a_weapons.cpp \ hudmessages.cpp shared_sbar.cpp fmopl.cpp mlkernel.cpp mlopl.cpp mlopl_io.cpp \ opl_mus_player.cpp fmodsound.cpp i_music.cpp i_sound.cpp music_cd.cpp \ music_flac.cpp music_midi_midiout.cpp music_midi_stream.cpp music_midi_timidity.cpp \ diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 1cc456792..8852b18de 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,55 @@ +April 20, 2006 +- Fixed compilation with mingw again. +- Added multiple-choice sound sequences. These overcome one of the major + deficiences of the Hexen-inherited SNDSEQ system while still being Hexen + compatible: Custom door sounds can now use different opening and closing + sequences, for both normal and blazing speeds. +- Moved the TArray serializer into farchive.h so that tarray.h doesn't need + farchive.h at all because GCC was much pickier than VC. Because of this, + I don't need the FArchive change I made yesterday that hid FArchive's + TArray usses behind pointers. +- Added a countof macro to doomtype.h. See the1's blog to find out why + it's implemented the way it is. + +- Added a new method to FRandom for getting random numbers larger than 255, + which lets me: +- Fixed: SNDSEQ delayrand commands could delay for no more than 255 tics. +- Fixed: If you're going to have sector_t.SoundTarget, then they need to + be included in the pointer cleanup scans. + +April 19, 2006 +- Added a serializer for TArray. This required I make a couple changes to + FArchive in order to avoid circular references between farchive.h and + tarray.h. +- Ported back newer name code from 2.1. +- Fixed: Using -warp with only one parameter in Doom and Heretic to + select a map on episode 1 no longer worked. +- New: Loading a multiplayer save now restores the players based on + their names rather than on their connection order. Using connection + order was sensible when -net was the only way to start a network game, + but with -host/-join, it's not so nice. Also, if there aren't enough + players in the save, then the extra players will be spawned normally, + so you can continue a saved game with more players than you started it + with. +- Added some new SNDSEQ commands to make it possible to define Heretic's + ambient sounds in SNDSEQ: volumerel, volumerand, slot, randomsequence, + delayonce, and restart. With these, it is basically possible to obsolete + all of the $ambient SNDINFO commands. +- Fixed: Sound sequences would only execute one command each time they were + ticked. +- Fixed: No bounds checking was done on the volume sound sequences played at. +- Fixed: The tic parameter to playloop was useless and caused it to + act like a redundant playrepeat. I have removed all the logic that + caused playloop to play repeating sounds, and now it acts like an + infinite sequence of play/delay commands until the sequence is + stopped. +- Fixed: Sound sequences were ticked every frame, not every tic, so all + the delay commands were timed incorrectly and varied depending on your + framerate. Since this is useful for restarting looping sounds that got + cut off, I have not changed this. Instead, the delay commands now + record the tic when execution should resume, not the number of tics + left to delay. + April 19, 2006 (Changes by Graf Zahl) - Fixed: Hexen's ammo display in the status bar cannot be refreshed partially because the background patch has to be drawn always to diff --git a/src/bbannouncer.cpp b/src/bbannouncer.cpp index 784a8c6ff..af9c5955c 100644 --- a/src/bbannouncer.cpp +++ b/src/bbannouncer.cpp @@ -248,13 +248,11 @@ bool AnnounceKill (AActor *killer, AActor *killee) { // Another player did the killing if (killee->player->userinfo.gender == GENDER_MALE) { // Only males can be castrated - choice = &KillSounds[rannum % - (sizeof(KillSounds)/sizeof(KillSounds[0]))]; + choice = &KillSounds[rannum % countof(KillSounds)]; } else { - choice = &KillSounds[rannum % - (sizeof(KillSounds)/sizeof(KillSounds[0])-1)]; + choice = &KillSounds[rannum % (countof(KillSounds) - 1)]; } killerName = killer->player->userinfo.netname; diff --git a/src/c_dispatch.cpp b/src/c_dispatch.cpp index 650532016..8243cf56c 100644 --- a/src/c_dispatch.cpp +++ b/src/c_dispatch.cpp @@ -422,7 +422,7 @@ void C_DoCommand (const char *cmd, int keynum) { int i; - for (i = sizeof(KeyConfCommands)/sizeof(KeyConfCommands[0])-1; i >= 0; --i) + for (i = countof(KeyConfCommands)-1; i >= 0; --i) { if (strnicmp (beg, KeyConfCommands[i], len) == 0 && KeyConfCommands[i][len] == 0) diff --git a/src/c_expr.cpp b/src/c_expr.cpp index 099637abf..b81e5dda8 100644 --- a/src/c_expr.cpp +++ b/src/c_expr.cpp @@ -179,7 +179,7 @@ static FProduction *ParseExpression (FCommandLine &argv, int &parsept) } else { - for (size_t i = 0; i < sizeof(Producers)/sizeof(Producers[0]); ++i) + for (size_t i = 0; i < countof(Producers); ++i) { if (strcmp (Producers[i].Token, token) == 0) { diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 04cbcadc3..db5c29437 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -1839,7 +1839,7 @@ static int PatchText (int oldSize) } // If this sprite is used by a pickup, then the DehackedPickup sprite map // needs to be updated too. - for (i = 0; (size_t)i < sizeof(DehSpriteMappings)/sizeof(DehSpriteMappings[0]); ++i) + for (i = 0; (size_t)i < countof(DehSpriteMappings); ++i) { if (strncmp (DehSpriteMappings[i].Sprite, oldStr, 4) == 0) { @@ -1853,7 +1853,7 @@ static int PatchText (int oldSize) swap (DehSpriteMappings[i-1], DehSpriteMappings[i]); --i; } - while ((size_t)i < sizeof(DehSpriteMappings)/sizeof(DehSpriteMappings[0])-1 && + while ((size_t)i < countof(DehSpriteMappings)-1 && strncmp (DehSpriteMappings[i+1].Sprite, newStr, 4) < 0) { swap (DehSpriteMappings[i+1], DehSpriteMappings[i]); @@ -2359,10 +2359,10 @@ static bool LoadDehSupp () else if (CompareLabel ("ACTF", supp)) { NumCodePtrs = GetWord (supp + 4); - if ((unsigned)NumCodePtrs != sizeof(CodePtrs)/sizeof(CodePtrs[0])) + if ((unsigned)NumCodePtrs != countof(CodePtrs)) { Printf ("DEHSUPP defines %d code pointers, but there should be %d\n", - NumCodePtrs, sizeof(CodePtrs)/sizeof(CodePtrs[0])); + NumCodePtrs, countof(CodePtrs)); return false; } CodePtrNames = (CodePtrMap *)GetWordSpace (supp + 6, NumCodePtrs*2); @@ -2670,7 +2670,7 @@ const TypeInfo *ADehackedPickup::DetermineType () // Look at the actor's current sprite to determine what kind of // item to pretend to me. int min = 0; - int max = sizeof(DehSpriteMappings)/sizeof(DehSpriteMappings[0]) - 1; + int max = countof(DehSpriteMappings) - 1; while (min <= max) { diff --git a/src/d_main.cpp b/src/d_main.cpp index 28a52f36a..5486bdbf4 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -2157,7 +2157,7 @@ void D_DoomMain (void) { ep = atoi (Args.GetArg(p+1)); map = p < Args.NumArgs() - 2 ? atoi (Args.GetArg(p+2)) : 10; - if ((unsigned)map > 9) + if (map < 1 || map > 9) { map = ep; ep = 1; diff --git a/src/d_netinfo.cpp b/src/d_netinfo.cpp index b34a94e69..e06b822a0 100644 --- a/src/d_netinfo.cpp +++ b/src/d_netinfo.cpp @@ -730,14 +730,12 @@ FArchive &operator<< (FArchive &arc, userinfo_t &info) if (arc.IsStoring ()) { arc.Write (&info.netname, sizeof(info.netname)); - arc.Write (&info.team, sizeof(info.team)); } else { arc.Read (&info.netname, sizeof(info.netname)); - arc.Read (&info.team, sizeof(info.team)); } - arc << info.aimdist << info.color << info.skin << info.gender << info.neverswitch; + arc << info.team << info.aimdist << info.color << info.skin << info.gender << info.neverswitch; return arc; } diff --git a/src/dobject.cpp b/src/dobject.cpp index 55eaad506..b8a6a4ec5 100644 --- a/src/dobject.cpp +++ b/src/dobject.cpp @@ -603,6 +603,14 @@ void DObject::PointerSubstitution (DObject *old, DObject *notOld) if (playeringame[i]) players[i].FixPointers (old, notOld); } + + for (i = 0; i < numsectors; ++i) + { + if (sectors[i].SoundTarget == old) + { + sectors[i].SoundTarget = static_cast(notOld); + } + } } // Search for references to a single object and NULL them. @@ -678,6 +686,18 @@ void DObject::DestroyScan () } while (++j); } } + + for (i = 0; i < numsectors; ++i) + { + j = destroycount; + do + { + if (sectors[i].SoundTarget == *(destroybase + j)) + { + sectors[i].SoundTarget = NULL; + } + } while (++j); + } } void STACK_ARGS DObject::StaticShutdown () diff --git a/src/doomtype.h b/src/doomtype.h index 23fb8b019..5422b6c2b 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -180,4 +180,9 @@ struct PalEntry #define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h #endif +template +char ( &_ArraySizeHelper( T (&array)[N] ))[N]; + +#define countof( array ) (sizeof( _ArraySizeHelper( array ) )) + #endif diff --git a/src/empty.cpp b/src/empty.cpp index d3128a26a..4c07e6072 100644 --- a/src/empty.cpp +++ b/src/empty.cpp @@ -3,7 +3,7 @@ ** ** **--------------------------------------------------------------------------- -** Copyright 1998-2001 Randy Heit +** Copyright 1998-2006 Randy Heit ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without diff --git a/src/farchive.cpp b/src/farchive.cpp index 49075aa43..853f46431 100644 --- a/src/farchive.cpp +++ b/src/farchive.cpp @@ -916,6 +916,21 @@ FArchive &FArchive::operator<< (double &w) return *this; } +FArchive &FArchive::operator<< (name &n) +{ // In an archive, a "name" is a string that might be stored multiple times, + // so it is only stored once. It is still treated as a normal string. In the + // rest of the game, a name is a unique identifier for a number. + if (m_Storing) + { + WriteName (n.GetChars()); + } + else + { + n = name(ReadName()); + } + return *this; +} + FArchive &FArchive::SerializePointer (void *ptrbase, BYTE **ptr, DWORD elemSize) { WORD w; diff --git a/src/farchive.h b/src/farchive.h index 278789c02..fbb7443b5 100644 --- a/src/farchive.h +++ b/src/farchive.h @@ -38,8 +38,7 @@ #include "doomtype.h" #include "dobject.h" #include "tarray.h" - -class DObject; +#include "name.h" class FFile { @@ -179,6 +178,7 @@ virtual void Read (void *mem, unsigned int len); FArchive& operator<< (float &f); FArchive& operator<< (double &d); FArchive& operator<< (char *&str); + FArchive& operator<< (name &n); FArchive& SerializePointer (void *ptrbase, BYTE **ptr, DWORD elemSize); FArchive& SerializeObject (DObject *&object, TypeInfo *type); FArchive& WriteObject (DObject *obj); @@ -280,12 +280,32 @@ inline FArchive &operator<< (FArchive &arc, PalEntry &p) #include "dobject.h" template -inline -FArchive &operator<< (FArchive &arc, T* &object) +inline FArchive &operator<< (FArchive &arc, T* &object) { return arc.SerializeObject ((DObject*&)object, RUNTIME_CLASS(T)); } FArchive &operator<< (FArchive &arc, const TypeInfo * &info); +template +inline FArchive &operator<< (FArchive &arc, TArray &self) +{ + unsigned int i; + + if (arc.IsStoring()) + { + arc.WriteCount(self.Count); + } + else + { + DWORD numStored = arc.ReadCount(); + self.Resize(numStored); + } + for (i = 0; i < self.Count; ++i) + { + arc << self.Array[i]; + } + return arc; +} + #endif //__FARCHIVE_H__ diff --git a/src/g_game.cpp b/src/g_game.cpp index 04452a9ee..8c08885ed 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -1620,8 +1620,14 @@ void G_DoLoadGame () { // Make a special case for the message printed for old savegames that don't // have this information. - if (engine == NULL) Printf ("Savegame is from an incompatible version\n"); - else Printf ("Savegame is from another ZDoom based engine\n"); + if (engine == NULL) + { + Printf ("Savegame is from an incompatible version\n"); + } + else + { + Printf ("Savegame is from another ZDoom-based engine\n"); + } delete png; fclose (stdfile); return; diff --git a/src/g_heretic/a_dsparil.cpp b/src/g_heretic/a_dsparil.cpp index 1a9f4295c..c3e1885b0 100644 --- a/src/g_heretic/a_dsparil.cpp +++ b/src/g_heretic/a_dsparil.cpp @@ -607,9 +607,9 @@ void A_Srcr2Decide (AActor *actor) }; unsigned int chanceindex = actor->health / (actor->GetDefault()->health/8); - if (chanceindex >= sizeof(chance)/sizeof(chance[0])) + if (chanceindex >= countof(chance)) { - chanceindex = sizeof(chance)/sizeof(chance[0])-1; + chanceindex = countof(chance) - 1; } if (pr_s2d() < chance[chanceindex]) diff --git a/src/g_heretic/a_hereticambience.cpp b/src/g_heretic/a_hereticambience.cpp deleted file mode 100644 index 1b0721885..000000000 --- a/src/g_heretic/a_hereticambience.cpp +++ /dev/null @@ -1,393 +0,0 @@ -#include - -#include "actor.h" -#include "info.h" -#include "s_sound.h" -#include "m_random.h" - -// I've had an instance where two machines got different values for -// this RNG. I don't know how, so I've just removed the name so that -// it won't count towards game consistancy. - -static FRandom pr_afx; - -// Scripted ambients -------------------------------------------------------- - -enum -{ - afxcmd_play, // (sound) - afxcmd_playabsvol, // (sound, volume) - afxcmd_playrelvol, // (sound, volume) - afxcmd_delay, // (ticks) - afxcmd_delayrand, // (andbits) - afxcmd_end // () -}; - -static ptrdiff_t AmbSndSeqInit[] = -{ // Startup - afxcmd_end -}; -static ptrdiff_t AmbSndSeq1[] = -{ // Scream - afxcmd_play, (ptrdiff_t)"world/amb1", - afxcmd_end -}; -static ptrdiff_t AmbSndSeq2[] = -{ // Squish - afxcmd_play, (ptrdiff_t)"world/amb2", - afxcmd_end -}; -static ptrdiff_t AmbSndSeq3[] = -{ // Drops - afxcmd_play, (ptrdiff_t)"world/amb3", - afxcmd_delay, 16, - afxcmd_delayrand, 31, - afxcmd_play, (ptrdiff_t)"world/amb7", - afxcmd_delay, 16, - afxcmd_delayrand, 31, - afxcmd_play, (ptrdiff_t)"world/amb3", - afxcmd_delay, 16, - afxcmd_delayrand, 31, - afxcmd_play, (ptrdiff_t)"world/amb7", - afxcmd_delay, 16, - afxcmd_delayrand, 31, - afxcmd_play, (ptrdiff_t)"world/amb3", - afxcmd_delay, 16, - afxcmd_delayrand, 31, - afxcmd_play, (ptrdiff_t)"world/amb7", - afxcmd_delay, 16, - afxcmd_delayrand, 31, - afxcmd_end -}; -static ptrdiff_t AmbSndSeq4[] = -{ // SlowFootSteps - afxcmd_play, (ptrdiff_t)"world/amb4", - afxcmd_delay, 15, - afxcmd_playrelvol, (ptrdiff_t)"world/amb11", -3, - afxcmd_delay, 15, - afxcmd_playrelvol, (ptrdiff_t)"world/amb4", -3, - afxcmd_delay, 15, - afxcmd_playrelvol, (ptrdiff_t)"world/amb11", -3, - afxcmd_delay, 15, - afxcmd_playrelvol, (ptrdiff_t)"world/amb4", -3, - afxcmd_delay, 15, - afxcmd_playrelvol, (ptrdiff_t)"world/amb11", -3, - afxcmd_delay, 15, - afxcmd_playrelvol, (ptrdiff_t)"world/amb4", -3, - afxcmd_delay, 15, - afxcmd_playrelvol, (ptrdiff_t)"world/amb11", -3, - afxcmd_end -}; -static ptrdiff_t AmbSndSeq5[] = -{ // Heartbeat - afxcmd_play, (ptrdiff_t)"world/amb5", - afxcmd_delay, 35, - afxcmd_play, (ptrdiff_t)"world/amb5", - afxcmd_delay, 35, - afxcmd_play, (ptrdiff_t)"world/amb5", - afxcmd_delay, 35, - afxcmd_play, (ptrdiff_t)"world/amb5", - afxcmd_end -}; -static ptrdiff_t AmbSndSeq6[] = -{ // Bells - afxcmd_play, (ptrdiff_t)"world/amb6", - afxcmd_delay, 17, - afxcmd_playrelvol, (ptrdiff_t)"world/amb6", -8, - afxcmd_delay, 17, - afxcmd_playrelvol, (ptrdiff_t)"world/amb6", -8, - afxcmd_delay, 17, - afxcmd_playrelvol, (ptrdiff_t)"world/amb6", -8, - afxcmd_end -}; -static ptrdiff_t AmbSndSeq7[] = -{ // Growl - afxcmd_play, (ptrdiff_t)"world/amb12", - afxcmd_end -}; -static ptrdiff_t AmbSndSeq8[] = -{ // Magic - afxcmd_play, (ptrdiff_t)"world/amb8", - afxcmd_end -}; -static ptrdiff_t AmbSndSeq9[] = -{ // Laughter - afxcmd_play, (ptrdiff_t)"world/amb9", - afxcmd_delay, 16, - afxcmd_playrelvol, (ptrdiff_t)"world/amb9", -4, - afxcmd_delay, 16, - afxcmd_playrelvol, (ptrdiff_t)"world/amb9", -4, - afxcmd_delay, 16, - afxcmd_playrelvol, (ptrdiff_t)"world/amb10", -4, - afxcmd_delay, 16, - afxcmd_playrelvol, (ptrdiff_t)"world/amb10", -4, - afxcmd_delay, 16, - afxcmd_playrelvol, (ptrdiff_t)"world/amb10", -4, - afxcmd_end -}; -static ptrdiff_t AmbSndSeq10[] = -{ // FastFootsteps - afxcmd_play, (ptrdiff_t)"world/amb4", - afxcmd_delay, 8, - afxcmd_playrelvol, (ptrdiff_t)"world/amb11", -3, - afxcmd_delay, 8, - afxcmd_playrelvol, (ptrdiff_t)"world/amb4", -3, - afxcmd_delay, 8, - afxcmd_playrelvol, (ptrdiff_t)"world/amb11", -3, - afxcmd_delay, 8, - afxcmd_playrelvol, (ptrdiff_t)"world/amb4", -3, - afxcmd_delay, 8, - afxcmd_playrelvol, (ptrdiff_t)"world/amb11", -3, - afxcmd_delay, 8, - afxcmd_playrelvol, (ptrdiff_t)"world/amb4", -3, - afxcmd_delay, 8, - afxcmd_playrelvol, (ptrdiff_t)"world/amb11", -3, - afxcmd_end -}; - -static ptrdiff_t *BaseAmbientSfx[] = -{ - AmbSndSeqInit, - AmbSndSeq1, // Scream - AmbSndSeq2, // Squish - AmbSndSeq3, // Drops - AmbSndSeq4, // SlowFootsteps - AmbSndSeq5, // Heartbeat - AmbSndSeq6, // Bells - AmbSndSeq7, // Growl - AmbSndSeq8, // Magic - AmbSndSeq9, // Laughter - AmbSndSeq10 // FastFootsteps -}; - -#define NUMSNDSEQ (sizeof(BaseAmbientSfx)/sizeof(BaseAmbientSfx[0])) - -// Master for all scripted ambient sounds on a level ------------------------ -// Only one ambient will ever play at a time. - -class AScriptedAmbientMaster : public AActor -{ - DECLARE_STATELESS_ACTOR (AScriptedAmbientMaster, AActor) -public: - void BeginPlay (); - void Tick (); - void AddAmbient (size_t sfx); - - void Serialize (FArchive &arc); -protected: - ptrdiff_t *AmbientSfx; - ptrdiff_t *AmbSfxPtr; - ptrdiff_t AmbSfxTics; - float AmbSfxVolume; - TArray LevelAmbientSfx; -private: - byte LocateSfx (ptrdiff_t *ptr); -}; - -IMPLEMENT_STATELESS_ACTOR (AScriptedAmbientMaster, Heretic, -1, 0) - PROP_Flags (MF_NOSECTOR|MF_NOBLOCKMAP) -END_DEFAULTS - -void AScriptedAmbientMaster::Serialize (FArchive &arc) -{ - byte seq; - byte ofs; - DWORD i; - DWORD numsfx; - - Super::Serialize (arc); - arc << AmbSfxTics << AmbSfxVolume; - - if (arc.IsStoring ()) - { - seq = LocateSfx (AmbientSfx); - ofs = (AmbSfxPtr && AmbientSfx) ? (BYTE)(AmbSfxPtr - AmbientSfx) : 255; - arc << seq << ofs; - - arc.WriteCount ((DWORD)LevelAmbientSfx.Size ()); - for (i = 0; i < LevelAmbientSfx.Size (); i++) - { - seq = LocateSfx (LevelAmbientSfx[i]); - arc << seq; - } - } - else - { - byte ofs; - - arc << seq << ofs; - if (seq >= NUMSNDSEQ) - { - AmbientSfx = AmbSfxPtr = AmbSndSeqInit; - } - else - { - AmbientSfx = BaseAmbientSfx[seq]; - AmbSfxPtr = ofs < 255 ? AmbientSfx + ofs : AmbSndSeqInit; - } - LevelAmbientSfx.Clear (); - numsfx = arc.ReadCount (); - for (i = 0; i < numsfx; i++) - { - arc << seq; - if (seq < NUMSNDSEQ) - { - ptrdiff_t *ptr = BaseAmbientSfx[seq]; - LevelAmbientSfx.Push (ptr); - } - } - } -} - -byte AScriptedAmbientMaster::LocateSfx (ptrdiff_t *ptr) -{ - size_t i; - - for (i = 0; i < NUMSNDSEQ; ++i) - { - if (BaseAmbientSfx[i] == ptr) - return (BYTE)i; - } - return 255; -} - -void AScriptedAmbientMaster::BeginPlay () -{ - Super::BeginPlay (); - AmbientSfx = AmbSfxPtr = AmbSndSeqInit; - AmbSfxTics = 10*TICRATE; - AmbSfxVolume = 0.f; - LevelAmbientSfx.Clear (); -} - -void AScriptedAmbientMaster::AddAmbient (size_t sfx) -{ - if (sfx >= NUMSNDSEQ) - return; - - ptrdiff_t *ptr = BaseAmbientSfx[sfx]; - - LevelAmbientSfx.Push (ptr); -} - -void AScriptedAmbientMaster::Tick () -{ - // No need to call Super::Tick(), because the only effect this - // actor has on the world is aural. - - ptrdiff_t cmd; - const char *sound; - bool done; - - if (LevelAmbientSfx.Size () == 0) - { // No ambient sound sequences on current level - Destroy (); - return; - } - if (--AmbSfxTics) - { - return; - } - done = false; - do - { - cmd = *AmbSfxPtr++; - switch (cmd) - { - case afxcmd_play: - sound = (const char *)(*AmbSfxPtr++); - AmbSfxVolume = (float)pr_afx() / 510.f; - S_Sound (this, CHAN_ITEM, sound, AmbSfxVolume, ATTN_NONE); - break; - - case afxcmd_playabsvol: - sound = (const char *)(*AmbSfxPtr++); - AmbSfxVolume = (float)*AmbSfxPtr++ / 127.f; - S_Sound (this, CHAN_ITEM, sound, AmbSfxVolume, ATTN_NONE); - break; - - case afxcmd_playrelvol: - sound = (const char *)(*AmbSfxPtr++); - AmbSfxVolume += (float)*AmbSfxPtr++ / 127.f; - if (AmbSfxVolume < 0.f) - { - AmbSfxVolume = 0.f; - } - else if (AmbSfxVolume > 1.f) - { - AmbSfxVolume = 1.f; - } - S_Sound (this, CHAN_ITEM, sound, AmbSfxVolume, ATTN_NONE); - break; - - case afxcmd_delay: - AmbSfxTics = *AmbSfxPtr++; - done = true; - break; - - case afxcmd_delayrand: - AmbSfxTics = pr_afx() & (*AmbSfxPtr++); - done = true; - break; - - case afxcmd_end: - AmbSfxTics = 6*TICRATE + pr_afx(); - AmbSfxPtr = LevelAmbientSfx[pr_afx() % LevelAmbientSfx.Size ()]; - done = true; - break; - - default: - DPrintf ("P_AmbientSound: Unknown afxcmd %ld", (long)cmd); - break; - } - } while (done == false); -} - -// Individual ambient sound things ------------------------------------------ -// They find a master (or create one if none found) and add the corresponding -// ambient sound to its list of effects and then destroy themselves. - -class AScriptedAmbient : public AActor -{ - DECLARE_STATELESS_ACTOR (AScriptedAmbient, AActor) -public: - void PostBeginPlay (); -}; - -IMPLEMENT_STATELESS_ACTOR (AScriptedAmbient, Heretic, -1, 0) - PROP_Flags (MF_NOSECTOR|MF_NOBLOCKMAP) -END_DEFAULTS - -void AScriptedAmbient::PostBeginPlay () -{ - const size_t ambientNum = health - 1200; - if (ambientNum < NUMSNDSEQ) - { - AScriptedAmbientMaster *master; - TThinkerIterator locater; - - master = locater.Next (); - if (master == NULL) - master = Spawn (0, 0, 0); - master->AddAmbient (ambientNum); - } - Destroy (); -} - -#define ADD_AMBIENT(x) \ - class AScriptedAmbient##x : public AScriptedAmbient { \ - DECLARE_STATELESS_ACTOR (AScriptedAmbient##x, AScriptedAmbient) };\ - IMPLEMENT_STATELESS_ACTOR (AScriptedAmbient##x, Heretic, 1199+x, 0) \ - PROP_SpawnHealth (1200+x) \ - END_DEFAULTS - -ADD_AMBIENT (1); -ADD_AMBIENT (2); -ADD_AMBIENT (3); -ADD_AMBIENT (4); -ADD_AMBIENT (5); -ADD_AMBIENT (6); -ADD_AMBIENT (7); -ADD_AMBIENT (8); -ADD_AMBIENT (9); -ADD_AMBIENT (10); diff --git a/src/g_hexen/a_centaur.cpp b/src/g_hexen/a_centaur.cpp index 83054379d..fafe5f6e7 100644 --- a/src/g_hexen/a_centaur.cpp +++ b/src/g_hexen/a_centaur.cpp @@ -303,7 +303,7 @@ void A_CentaurDropStuff (AActor *actor) RUNTIME_CLASS(ACentaurShield) }; - for (int i = sizeof(DropTypes)/sizeof(DropTypes[0])-1; i >= 0; --i) + for (int i = countof(DropTypes)-1; i >= 0; --i) { AActor *mo; diff --git a/src/g_hexen/a_serpent.cpp b/src/g_hexen/a_serpent.cpp index 07bb8210a..503ecd397 100644 --- a/src/g_hexen/a_serpent.cpp +++ b/src/g_hexen/a_serpent.cpp @@ -626,7 +626,7 @@ void A_SerpentSpawnGibs (AActor *actor) RUNTIME_CLASS(ASerpentGib1) }; - for (int i = sizeof(GibTypes)/sizeof(GibTypes[0])-1; i >= 0; --i) + for (int i = countof(GibTypes)-1; i >= 0; --i) { mo = Spawn (GibTypes[i], actor->x+((pr_serpentgibs()-128)<<12), diff --git a/src/infomacros.h b/src/infomacros.h index 32af1765c..3c088abf9 100644 --- a/src/infomacros.h +++ b/src/infomacros.h @@ -173,7 +173,7 @@ public: #define BEGIN_DEFAULTS(actor,game,ednum,spawnid) \ BEGIN_DEFAULTS_PRE(actor) \ - RUNTIME_CLASS(actor), &actor::States[0], NULL, NULL, sizeof(actor::States)/sizeof(actor::States[0]), \ + RUNTIME_CLASS(actor), &actor::States[0], NULL, NULL, countof(actor::States), \ BEGIN_DEFAULTS_POST(actor,game,ednum,spawnid) #define BEGIN_STATELESS_DEFAULTS(actor,game,ednum,spawnid) \ diff --git a/src/m_menu.cpp b/src/m_menu.cpp index aa63cff6a..d5c08ea5d 100644 --- a/src/m_menu.cpp +++ b/src/m_menu.cpp @@ -70,8 +70,6 @@ #define SELECTOR_XOFFSET (-28) #define SELECTOR_YOFFSET (-1) -#define NUM_MENU_ITEMS(m) (sizeof(m)/sizeof(m[0])) - // TYPES ------------------------------------------------------------------- struct FSaveGameNode : public Node @@ -250,7 +248,7 @@ static oldmenuitem_t MainMenu[]= static oldmenu_t MainDef = { - NUM_MENU_ITEMS (MainMenu), + countof(MainMenu), MainMenu, M_DrawMainMenu, 97,64, @@ -271,7 +269,7 @@ static oldmenuitem_t HereticMainMenu[] = static oldmenu_t HereticMainDef = { - NUM_MENU_ITEMS (HereticMainMenu), + countof(HereticMainMenu), HereticMainMenu, M_DrawHereticMainMenu, 110, 56, @@ -334,7 +332,7 @@ static oldmenuitem_t FilesItems[] = static oldmenu_t FilesMenu = { - NUM_MENU_ITEMS (FilesItems), + countof(FilesItems), FilesItems, M_DrawFiles, 110,60, @@ -355,7 +353,7 @@ static oldmenuitem_t NewGameMenu[]= static oldmenu_t NewDef = { - NUM_MENU_ITEMS (NewGameMenu), + countof(NewGameMenu), NewGameMenu, // oldmenuitem_t -> M_DrawNewGame, // drawing routine -> 48,63, // x,y @@ -376,7 +374,7 @@ static oldmenuitem_t HereticSkillItems[] = static oldmenu_t HereticSkillMenu = { - NUM_MENU_ITEMS (HereticSkillItems), + countof(HereticSkillItems), HereticSkillItems, M_DrawNewGame, 38, 30, @@ -421,7 +419,7 @@ static oldmenuitem_t PlayerSetupMenu[] = static oldmenu_t PSetupDef = { - NUM_MENU_ITEMS (PlayerSetupMenu), + countof(PlayerSetupMenu), PlayerSetupMenu, M_PlayerSetupDrawer, 48, 47, @@ -462,7 +460,7 @@ static oldmenuitem_t LoadMenu[]= static oldmenu_t LoadDef = { - NUM_MENU_ITEMS(LoadMenu), + countof(LoadMenu), LoadMenu, M_DrawLoad, 80,54, @@ -486,7 +484,7 @@ static oldmenuitem_t SaveMenu[] = static oldmenu_t SaveDef = { - NUM_MENU_ITEMS(LoadMenu), + countof(LoadMenu), SaveMenu, M_DrawSave, 80,54, diff --git a/src/m_options.cpp b/src/m_options.cpp index 137895113..cf829f684 100644 --- a/src/m_options.cpp +++ b/src/m_options.cpp @@ -160,7 +160,7 @@ static menuitem_t ConfirmItems[] = { static menu_t ConfirmMenu = { "PLEASE CONFIRM", 3, - sizeof(ConfirmItems)/sizeof(ConfirmItems[0]), + countof(ConfirmItems), 140, ConfirmItems, }; @@ -208,7 +208,7 @@ menu_t OptionMenu = { "OPTIONS", 0, - sizeof(OptionItems)/sizeof(OptionItems[0]), + countof(OptionItems), 0, OptionItems, }; @@ -253,7 +253,7 @@ menu_t MouseMenu = { "MOUSE OPTIONS", 0, - sizeof(MouseItems)/sizeof(MouseItems[0]), + countof(MouseItems), 0, MouseItems, }; @@ -349,7 +349,7 @@ menu_t JoystickMenu = { "JOYSTICK OPTIONS", 0, - sizeof(JoystickItems)/sizeof(JoystickItems[0]), + countof(JoystickItems), 0, JoystickItems, }; @@ -422,7 +422,7 @@ menu_t ControlsMenu = { "CUSTOMIZE CONTROLS", 3, - sizeof(ControlsItems)/sizeof(ControlsItems[0]), + countof(ControlsItems), 0, ControlsItems, 2, @@ -519,7 +519,7 @@ menu_t VideoMenu = { "DISPLAY OPTIONS", 0, - sizeof(VideoItems)/sizeof(VideoItems[0]), + countof(VideoItems), 0, VideoItems, }; @@ -573,7 +573,7 @@ menu_t AutomapMenu = { "AUTOMAP OPTIONS", 0, - sizeof(AutomapItems)/sizeof(AutomapItems[0]), + countof(AutomapItems), 0, AutomapItems, }; @@ -651,7 +651,7 @@ menu_t MapColorsMenu = { "CUSTOMIZE MAP COLORS", 0, - sizeof(MapColorsItems)/sizeof(MapColorsItems[0]), + countof(MapColorsItems), 48, MapColorsItems, }; @@ -699,7 +699,7 @@ menu_t ColorPickerMenu = { "SELECT COLOR", 2, - sizeof(ColorPickerItems)/sizeof(ColorPickerItems[0]), + countof(ColorPickerItems), 0, ColorPickerItems, }; @@ -931,7 +931,7 @@ static menu_t DMFlagsMenu = { "GAMEPLAY OPTIONS", 0, - sizeof(DMFlagsItems)/sizeof(DMFlagsItems[0]), + countof(DMFlagsItems), 0, DMFlagsItems, }; @@ -963,7 +963,7 @@ static menu_t CompatibilityMenu = { "COMPATIBILITY OPTIONS", 0, - sizeof(CompatibilityItems)/sizeof(CompatibilityItems[0]), + countof(CompatibilityItems), 0, CompatibilityItems, }; @@ -1044,7 +1044,7 @@ static menu_t SoundMenu = { "SOUND OPTIONS", 0, - sizeof(SoundItems)/sizeof(SoundItems[0]), + countof(SoundItems), 0, SoundItems, }; @@ -1106,7 +1106,7 @@ static menu_t AdvSoundMenu = { "ADVANCED SOUND OPTIONS", 1, - sizeof(AdvSoundItems)/sizeof(AdvSoundItems[0]), + countof(AdvSoundItems), 0, AdvSoundItems, }; @@ -2872,7 +2872,7 @@ void M_SaveCustomKeys (FConfigFile *config, char *section, char *subsection) return; // Start after the normal controls - unsigned int i = sizeof(ControlsItems)/sizeof(ControlsItems[0]); + unsigned int i = countof(ControlsItems); unsigned int most = CustomControlsItems.Size(); while (i < most) @@ -2903,7 +2903,7 @@ CCMD (addkeysection) return; } - const int numStdControls = sizeof(ControlsItems)/sizeof(ControlsItems[0]); + const int numStdControls = countof(ControlsItems); int i; if (ControlsMenu.items == ControlsItems) diff --git a/src/m_random.cpp b/src/m_random.cpp index 14963a7c9..fe4d10bce 100644 --- a/src/m_random.cpp +++ b/src/m_random.cpp @@ -127,17 +127,33 @@ int FRandom::operator() () return (UpdateSeed (Seed) >> 20) & 255; } +int FRandom::operator() (int mod) +{ + if (mod <= 256) + { // The mod is small enough, so a byte is enough to get a good number. + return (*this)() % mod; + } + else + { // For mods > 256, construct a 32-bit int and modulo that. + int num = (*this)(); + num = (num << 8) | (*this)(); + num = (num << 8) | (*this)(); + num = (num << 8) | (*this)(); + return num % mod; + } +} + int FRandom::Random2 () { - int t = (UpdateSeed (Seed) >> 20) & 255; - int u = (UpdateSeed (Seed) >> 20) & 255; + int t = (*this)(); + int u = (*this)(); return t - u; } int FRandom::Random2 (int mask) { - int t = (UpdateSeed (Seed) >> 20) & mask; - int u = (UpdateSeed (Seed) >> 20) & mask; + int t = (*this)(); + int u = (*this)(); return t - u; } diff --git a/src/m_random.h b/src/m_random.h index ba4be4f6d..2ad1ea50b 100644 --- a/src/m_random.h +++ b/src/m_random.h @@ -63,9 +63,10 @@ public: ~FRandom (); int operator() (); // Returns a random number in the range [0,255] + int operator() (int mod); // Returns a random number in the range [0,mod) int Random2(); // Returns rand# - rand# int Random2(int mask); // Returns (rand# & mask) - (rand# & mask) - int HitDice (int count); // HITDICE macro used in Heretic and Hexen + int HitDice(int count); // HITDICE macro used in Heretic and Hexen int Random() // synonym for () { diff --git a/src/name.cpp b/src/name.cpp index 98f90c51a..97563cbeb 100644 --- a/src/name.cpp +++ b/src/name.cpp @@ -2,6 +2,14 @@ #include "name.h" #include "c_dispatch.h" +// Define the predefined names. +static const char *PredefinedNames[] = +{ +#define xx(n) #n, +#include "namedef.h" +#undef xx +}; + int name::Buckets[name::HASH_SIZE]; TArray name::NameArray; bool name::Inited; @@ -14,6 +22,11 @@ int name::FindName (const char *text, bool noCreate) { if (!Inited) InitBuckets (); + if (text == NULL) + { + return 0; + } + int hash = MakeKey (text) % HASH_SIZE; int scanner = Buckets[hash]; @@ -44,10 +57,17 @@ int name::FindName (const char *text, bool noCreate) void name::InitBuckets () { + size_t i; + Inited = true; - for (int i = 0; i < HASH_SIZE; ++i) + for (i = 0; i < HASH_SIZE; ++i) { Buckets[i] = -1; } - name::FindName ("None", false); // 'None' is always name 0. + + // Register built-in names. 'None' must be name 0. + for (i = 0; i < countof(PredefinedNames); ++i) + { + FindName (PredefinedNames[i], false); + } } diff --git a/src/name.h b/src/name.h index 3909dcaae..9c6a01f7d 100644 --- a/src/name.h +++ b/src/name.h @@ -6,7 +6,9 @@ enum ENamedName { - NAME_None +#define xx(n) NAME_##n, +#include "namedef.h" +#undef xx }; class name diff --git a/src/namedef.h b/src/namedef.h new file mode 100644 index 000000000..50c1073bd --- /dev/null +++ b/src/namedef.h @@ -0,0 +1,113 @@ +// 'None' must always be the first name. +xx(None) + +// Hexen sound sequence names +xx(Platform) +xx(PlatformMetal) +xx(Silence) +xx(Lava) +xx(Water) +xx(Ice) +xx(Earth) +xx(PlatformMetal2) +xx(DoorNormal) +xx(DoorHeavy) +xx(DoorMetal) +xx(DoorCreak) +xx(DoorMetal2) +xx(Wind) + +#if 0 +xx(Super) +xx(Object) + +// Special bosses A_BossDeath knows about +xx(Fatso) +xx(Arachnotron) +xx(BaronOfHell) +xx(Cyberdemon) +xx(SpiderMastermind) +xx(Ironlich) +xx(Minotaur) +xx(Sorcerer2) + +// Standard player classes +xx(DoomPlayer) +xx(HereticPlayer) +xx(StrifePlayer) +xx(FighterPlayer) +xx(ClericPlayer) +xx(MagePlayer) + +// Weapon names for the Strife status bar +xx(StrifeCrossbow) +xx(AssaultGun) +xx(FlameThrower) +xx(MiniMissileLauncher) +xx(StrifeGrenadeLauncher) +xx(Mauler) + +// Flechette names for the different Hexen player classes +xx(ArtiPoisonBag1) +xx(ArtiPoisonBag2) +xx(ArtiPoisonBag3) + +// P_SpawnMapThing checks for these as health items (I smell a FIXME) +xx(Berserk) +xx(Soulsphere) +xx(Megasphere) // also counts as armor for P_SpawnMapThing + +// Standard animator names. +xx(Spawn) +xx(See) +xx(Pain) +xx(Melee) +xx(Missile) +xx(Crash) +xx(Death) +xx(Raise) +xx(Wound) + +// Weapon animator names. +xx(Up) +xx(Down) +xx(Ready) +xx(Flash) +xx(Attack) +xx(HoldAttack) +xx(AltAttack) +xx(AltHoldAttack) + +// Special death name for getting killed excessively. Could be used as +// a damage type if you wanted to force an extreme death. +xx(Extreme) + +// Damage types +xx(Fire) +xx(Ice) +xx(Disintegrate) +xx(Water) +xx(Slime) +xx(Crush) +xx(Telefrag) +xx(Falling) +xx(Suicide) +xx(Exit) +xx(Railgun) +xx(Poison) +xx(Electric) +xx(BFGSplash) +xx(DrainLife) // A weapon like the Sigil that drains your life away. +xx(Massacre) // For death by a cheater! +//(Melee) already defined above, so don't define it again + +// Compatible death names for the decorate parser. +xx(XDeath) +xx(BDeath) +xx(IDeath) +xx(EDeath) + +// State names used by ASwitchableDecoration +xx(Active) +xx(Inactive) +#endif diff --git a/src/p_acs.cpp b/src/p_acs.cpp index bbfcbb6bc..d862bf49d 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -1588,30 +1588,12 @@ void DLevelScript::PutFirst () int DLevelScript::Random (int min, int max) { - int num1, num2, num3, num4; - unsigned int num; - if (max < min) { swap (max, min); } - if (max - min > 255) - { - num1 = pr_acs(); - num2 = pr_acs(); - num3 = pr_acs(); - num4 = pr_acs(); - - num = ((num1 << 24) | (num2 << 16) | (num3 << 8) | num4); - } - else - { - num = pr_acs(); - } - num %= (max - min + 1); - num += min; - return (int)num; + return min + pr_acs(max - min + 1); } int DLevelScript::ThingCount (int type, int tid) @@ -3544,9 +3526,7 @@ int DLevelScript::RunScript () { if (activationline) { - SN_StartSequence ( - activationline->frontsector, - lookup); + SN_StartSequence (activationline->frontsector, lookup, 0); } } sp--; diff --git a/src/p_ceiling.cpp b/src/p_ceiling.cpp index bcebe2c75..ad528584f 100644 --- a/src/p_ceiling.cpp +++ b/src/p_ceiling.cpp @@ -63,16 +63,16 @@ void DCeiling::PlayCeilingSound () { if (m_Sector->seqType >= 0) { - SN_StartSequence (m_Sector, m_Sector->seqType, SEQ_PLATFORM); + SN_StartSequence (m_Sector, m_Sector->seqType, SEQ_PLATFORM, 0); } else { if (m_Silent == 2) - SN_StartSequence (m_Sector, "Silence"); + SN_StartSequence (m_Sector, "Silence", 0); else if (m_Silent == 1) - SN_StartSequence (m_Sector, "CeilingSemiSilent"); + SN_StartSequence (m_Sector, "CeilingSemiSilent", 0); else - SN_StartSequence (m_Sector, "CeilingNormal"); + SN_StartSequence (m_Sector, "CeilingNormal", 0); } } diff --git a/src/p_doors.cpp b/src/p_doors.cpp index 01b2b010f..ee811143a 100644 --- a/src/p_doors.cpp +++ b/src/p_doors.cpp @@ -205,94 +205,84 @@ void DDoor::Tick () // [RH] DoorSound: Plays door sound depending on direction and speed void DDoor::DoorSound (bool raise) const { - const char *snd = ""; + int choice; + + // For multiple-selection sound sequences, the following choices are used: + // 0 Opening + // 1 Closing + // 2 Opening fast + // 3 Closing fast + + choice = !raise; + + if (m_Speed >= FRACUNIT*8) + { + choice += 2; + } if (m_Sector->seqType >= 0) { - SN_StartSequence (m_Sector, m_Sector->seqType, SEQ_DOOR); + SN_StartSequence (m_Sector, m_Sector->seqType, SEQ_DOOR, choice); } else { - switch (gameinfo.gametype) - { - - default: - break; + const char *snd; - case GAME_Hexen: + switch (gameinfo.gametype) + { + default: /* Doom and Hexen */ snd = "DoorNormal"; break; case GAME_Heretic: - snd = raise ? "HereticDoorOpen" : "HereticDoorClose"; - break; - - case GAME_Doom: - if (m_Speed >= 8*FRACUNIT) - { - snd = raise ? "DoorOpenBlazing" : "DoorCloseBlazing"; - } - else - { - snd = raise ? "DoorOpenNormal" : "DoorCloseNormal"; - } + snd = "HereticDoor"; break; case GAME_Strife: - if (m_Speed >= FRACUNIT*8) - { - snd = raise ? "DoorOpenBlazing" : "DoorCloseBlazing"; - } - else - { - snd = raise ? "DoorOpenSmallMetal" : "DoorCloseSmallMetal"; + snd = "DoorSmallMetal"; - // Search the front top textures of 2-sided lines on the door sector - // for a door sound to use. - for (int i = 0; i < m_Sector->linecount; ++i) + // Search the front top textures of 2-sided lines on the door sector + // for a door sound to use. + for (int i = 0; i < m_Sector->linecount; ++i) + { + const char *texname; + line_t *line = m_Sector->lines[i]; + + if (line->backsector == NULL) + continue; + + texname = TexMan[sides[line->sidenum[0]].toptexture]->Name; + if (texname[0] == 'D' && texname[1] == 'O' && texname[2] == 'R') { - const char *texname; - line_t *line = m_Sector->lines[i]; - - if (line->backsector == NULL) - continue; - - texname = TexMan[sides[line->sidenum[0]].toptexture]->Name; - if (strncmp (texname, "DOR", 3) == 0) + switch (texname[3]) { - switch (texname[3]) + case 'S': + snd = "DoorStone"; + break; + + case 'M': + if (texname[4] == 'L') { - case 'S': - snd = raise ? "DoorOpenStone" : "DoorCloseStone"; - break; - - case 'M': - if (texname[4] == 'L') - { - snd = raise ? "DoorOpenLargeMetal" : "DoorCloseLargeMetal"; - } - break; - - case 'W': - if (texname[4] == 'L') - { - snd = raise ? "DoorOpenLargeWood" : "DoorCloseLargeWood"; - } - else - { - snd = raise ? "DoorOpenSmallWood" : "DoorCloseSmallWood"; - } - break; + snd = "DoorLargeMetal"; } + break; + + case 'W': + if (texname[4] == 'L') + { + snd = "DoorLargeWood"; + } + else + { + snd = "DoorSmallWood"; + } + break; } } } break; } - if (snd != NULL) - { - SN_StartSequence (m_Sector, snd); - } + SN_StartSequence (m_Sector, snd, choice); } } @@ -532,7 +522,7 @@ bool DAnimatedDoor::StartClosing () m_Line2->flags |= ML_BLOCKING; if (ani.CloseSound != NULL) { - SN_StartSequence (m_Sector, ani.CloseSound); + SN_StartSequence (m_Sector, ani.CloseSound, 1); } m_Status = Closing; @@ -713,7 +703,7 @@ DAnimatedDoor::DAnimatedDoor (sector_t *sec, line_t *line, int speed, int delay) MoveCeiling (2048*FRACUNIT, topdist, 1); if (DoorAnimations[m_WhichDoorIndex].OpenSound != NULL) { - SN_StartSequence (m_Sector, DoorAnimations[m_WhichDoorIndex].OpenSound); + SN_StartSequence (m_Sector, DoorAnimations[m_WhichDoorIndex].OpenSound, 1); } } diff --git a/src/p_floor.cpp b/src/p_floor.cpp index 866172354..f0f6082e6 100644 --- a/src/p_floor.cpp +++ b/src/p_floor.cpp @@ -280,11 +280,11 @@ static void StartFloorSound (sector_t *sec) { if (sec->seqType >= 0) { - SN_StartSequence (sec, sec->seqType, SEQ_PLATFORM); + SN_StartSequence (sec, sec->seqType, SEQ_PLATFORM, 0); } else { - SN_StartSequence (sec, "Floor"); + SN_StartSequence (sec, "Floor", 0); } } diff --git a/src/p_pillar.cpp b/src/p_pillar.cpp index db6953c5a..840a65fd4 100644 --- a/src/p_pillar.cpp +++ b/src/p_pillar.cpp @@ -167,9 +167,9 @@ DPillar::DPillar (sector_t *sector, EPillar type, fixed_t speed, } if (sector->seqType >= 0) - SN_StartSequence (sector, sector->seqType, SEQ_PLATFORM); + SN_StartSequence (sector, sector->seqType, SEQ_PLATFORM, 0); else - SN_StartSequence (sector, "Floor"); + SN_StartSequence (sector, "Floor", 0); } bool EV_DoPillar (DPillar::EPillar type, int tag, fixed_t speed, fixed_t height, diff --git a/src/p_plats.cpp b/src/p_plats.cpp index 270ba8548..d04437b7a 100644 --- a/src/p_plats.cpp +++ b/src/p_plats.cpp @@ -58,9 +58,9 @@ void DPlat::Serialize (FArchive &arc) void DPlat::PlayPlatSound (const char *sound) { if (m_Sector->seqType >= 0) - SN_StartSequence (m_Sector, m_Sector->seqType, SEQ_PLATFORM); + SN_StartSequence (m_Sector, m_Sector->seqType, SEQ_PLATFORM, 0); else - SN_StartSequence (m_Sector, sound); + SN_StartSequence (m_Sector, sound, 0); } // @@ -168,7 +168,7 @@ void DPlat::Tick () m_Status = down; if (m_Type == platToggle) - SN_StartSequence (m_Sector, "Silence"); + SN_StartSequence (m_Sector, "Silence", 0); else PlayPlatSound ("Platform"); } @@ -346,7 +346,7 @@ manual_plat: plat->m_Low = sec->floorplane.PointToDist (spot, newheight); plat->m_High = sec->floorplane.d; plat->m_Status = DPlat::down; - SN_StartSequence (sec, "Silence"); + SN_StartSequence (sec, "Silence", 0); break; case DPlat::platDownToNearestFloor: diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index 71257d1c3..9981010ff 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -46,21 +46,228 @@ #include "v_palette.h" #include "a_sharedglobal.h" +extern void P_SpawnPlayer (mapthing2_t *mthing); +static void CopyPlayer (player_t *dst, player_t *src, const char *name); +static void ReadOnePlayer (FArchive &arc); +static void ReadMultiplePlayers (FArchive &arc, int numPlayers, int numPlayersNow); +static void SpawnExtraPlayers (); // // P_ArchivePlayers // void P_SerializePlayers (FArchive &arc) { + BYTE numPlayers, numPlayersNow; int i; - for (i = 0; i < MAXPLAYERS; i++) + // Count the number of players present right now. + for (numPlayersNow = 0, i = 0; i < MAXPLAYERS; ++i) { - arc << playeringame[i]; if (playeringame[i]) { - players[i].Serialize (arc); + ++numPlayersNow; + } + } + + if (arc.IsStoring()) + { + // Record the number of players in this save. + arc << numPlayersNow; + + // Record each player's name, followed by their data. + for (i = 0; i < MAXPLAYERS; ++i) + { + if (playeringame[i]) + { + arc.WriteString (players[i].userinfo.netname); + players[i].Serialize (arc); + } + } + } + else + { + arc << numPlayers; + + // If there is only one player in the game, they go to the + // first player present, no matter what their name. + if (numPlayers == 1) + { + ReadOnePlayer (arc); + } + else + { + ReadMultiplePlayers (arc, numPlayers, numPlayersNow); + } + if (numPlayersNow > numPlayers) + { + SpawnExtraPlayers (); + } + } +} + +static void ReadOnePlayer (FArchive &arc) +{ + int i; + char *name = NULL; + bool didIt = false; + + arc << name; + + for (i = 0; i < MAXPLAYERS; ++i) + { + if (playeringame[i]) + { + if (!didIt) + { + didIt = true; + player_t playerTemp; + memset (&playerTemp, 0, sizeof(playerTemp)); + playerTemp.Serialize (arc); + CopyPlayer (&players[i], &playerTemp, name); + } + else + { + if (players[i].mo != NULL) + { + players[i].mo->Destroy(); + players[i].mo = NULL; + } + } + } + } + delete[] name; +} + +static void ReadMultiplePlayers (FArchive &arc, int numPlayers, int numPlayersNow) +{ + // For two or more players, read each player into a temporary array. + int i, j; + char **nametemp = new char *[numPlayers]; + player_t *playertemp = new player_t[numPlayers]; + BYTE *tempPlayerUsed = new BYTE[numPlayers]; + BYTE *playerUsed = new BYTE[MAXPLAYERS]; + + memset (playertemp, 0, numPlayers*sizeof(player_t)); + + for (i = 0; i < numPlayers; ++i) + { + nametemp[i] = NULL; + arc << nametemp[i]; + playertemp[i].Serialize (arc); + tempPlayerUsed[i] = 0; + } + for (i = 0; i < MAXPLAYERS; ++i) + { + playerUsed[i] = playeringame[i] ? 0 : 2; + } + + // Now try to match players from the savegame with players present + // based on their names. If two players in the savegame have the + // same name, then they are assigned to players in the current game + // on a first-come, first-served basis. + for (i = 0; i < numPlayers; ++i) + { + for (j = 0; j < MAXPLAYERS; ++j) + { + if (playerUsed[j] == 0 && stricmp(players[j].userinfo.netname, nametemp[i]) == 0) + { // Found a match, so copy our temp player to the real player + Printf ("Found player %d (%s) at %d\n", i, nametemp[i], j); + CopyPlayer (&players[j], &playertemp[i], nametemp[i]); + playerUsed[j] = 1; + tempPlayerUsed[i] = 1; + break; + } + } + } + + // Any players that didn't have matching names are assigned to existing + // players on a first-come, first-served basis. + for (i = 0; i < numPlayers; ++i) + { + if (tempPlayerUsed[i] == 0) + { + for (j = 0; j < MAXPLAYERS; ++j) + { + if (playerUsed[j] == 0) + { + Printf ("Assigned player %d (%s) to %d (%s)\n", i, nametemp[i], j, players[j].userinfo.netname); + CopyPlayer (&players[j], &playertemp[i], nametemp[i]); + playerUsed[j] = 1; + tempPlayerUsed[i] = 1; + break; + } + } + } + } + + // Make sure any extra players don't have actors spawned yet. + for (j = 0; j < MAXPLAYERS; ++j) + { + if (playerUsed[j] == 0) + { + if (players[j].mo != NULL) + { + players[j].mo->Destroy(); + players[j].mo = NULL; + } + } + } + + delete[] playerUsed; + delete[] tempPlayerUsed; + delete[] playertemp; + for (i = 0; i < numPlayers; ++i) + { + delete[] nametemp[i]; + } + delete[] nametemp; +} + +static void CopyPlayer (player_t *dst, player_t *src, const char *name) +{ + // The userinfo needs to be saved for real players, but it + // needs to come from the save for bots. + userinfo_t uibackup = dst->userinfo; + memcpy (dst, src, sizeof(player_t)); + + if (dst->isbot) + { + botinfo_t *thebot = bglobal.botinfo; + while (thebot && stricmp (name, thebot->name)) + { + thebot = thebot->next; + } + if (thebot) + { + thebot->inuse = true; + } + bglobal.botnum++; + bglobal.botingame[dst - players] = true; + } + else + { + dst->userinfo = uibackup; + } +} + +static void SpawnExtraPlayers () +{ + // If there are more players now than there were in the savegame, + // be sure to spawn the extra players. + int i; + + if (deathmatch) + { + return; + } + + for (i = 0; i < MAXPLAYERS; ++i) + { + if (playeringame[i] && players[i].mo == NULL) + { + players[i].playerstate = PST_ENTER; + P_SpawnPlayer (&playerstarts[i]); } } } diff --git a/src/p_user.cpp b/src/p_user.cpp index 93507dc75..7fe7b761e 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -1354,25 +1354,13 @@ void P_UnPredictPlayer () void player_s::Serialize (FArchive &arc) { int i; - userinfo_t *ui; - userinfo_t dummy; - if (arc.IsStoring ()) - { - arc.UserWriteClass (cls); - ui = &userinfo; - } - else - { - arc.UserReadClass (cls); - ui = &dummy; - } - - arc << mo + arc << cls + << mo << camera << playerstate << cmd - << *ui + << userinfo << DesiredFOV << FOV << viewz << viewheight @@ -1452,22 +1440,6 @@ void player_s::Serialize (FArchive &arc) << allround << oldx << oldy; - if (arc.IsLoading ()) - { - if (consoleplayer != this - players) - { - userinfo = *ui; - } - botinfo_t *thebot = bglobal.botinfo; - while (thebot && stricmp (userinfo.netname, thebot->name)) - thebot = thebot->next; - if (thebot) - { - thebot->inuse = true; - } - bglobal.botnum++; - bglobal.botingame[this - players] = true; - } } else { diff --git a/src/po_man.cpp b/src/po_man.cpp index 27b8c2b70..fabbea880 100644 --- a/src/po_man.cpp +++ b/src/po_man.cpp @@ -254,7 +254,7 @@ bool EV_RotatePoly (line_t *line, int polyNum, int speed, int byteAngle, } pe->m_Speed = (speed*direction*(ANGLE_90/64))>>3; poly->specialdata = pe; - SN_StartSequence (poly, poly->seqType, SEQ_DOOR); + SN_StartSequence (poly, poly->seqType, SEQ_DOOR, 0); while ( (mirror = GetPolyobjMirror( polyNum)) ) { @@ -287,7 +287,7 @@ bool EV_RotatePoly (line_t *line, int polyNum, int speed, int byteAngle, direction = -direction; pe->m_Speed = (speed*direction*(ANGLE_90/64))>>3; polyNum = mirror; - SN_StartSequence (poly, poly->seqType, SEQ_DOOR); + SN_StartSequence (poly, poly->seqType, SEQ_DOOR, 0); } return true; } @@ -360,7 +360,7 @@ bool EV_MovePoly (line_t *line, int polyNum, int speed, angle_t angle, pe->m_Angle = an>>ANGLETOFINESHIFT; pe->m_xSpeed = FixedMul (pe->m_Speed, finecosine[pe->m_Angle]); pe->m_ySpeed = FixedMul (pe->m_Speed, finesine[pe->m_Angle]); - SN_StartSequence (poly, poly->seqType, SEQ_DOOR); + SN_StartSequence (poly, poly->seqType, SEQ_DOOR, 0); // Do not interpolate very fast moving polyobjects. The minimum tic count is // 3 instead of 2, because the moving crate effect in Massmouth 2, Hostitality @@ -387,7 +387,7 @@ bool EV_MovePoly (line_t *line, int polyNum, int speed, angle_t angle, pe->m_xSpeed = FixedMul (pe->m_Speed, finecosine[pe->m_Angle]); pe->m_ySpeed = FixedMul (pe->m_Speed, finesine[pe->m_Angle]); polyNum = mirror; - SN_StartSequence (poly, poly->seqType, SEQ_DOOR); + SN_StartSequence (poly, poly->seqType, SEQ_DOOR, 0); if (dist/speed <= 2) { pe->StopInterpolation (); @@ -412,7 +412,7 @@ void DPolyDoor::Tick () if (!--m_Tics) { poly = GetPolyobj (m_PolyObj); - SN_StartSequence (poly, poly->seqType, SEQ_DOOR); + SN_StartSequence (poly, poly->seqType, SEQ_DOOR, m_Close); } return; } @@ -462,7 +462,7 @@ void DPolyDoor::Tick () m_xSpeed = -m_xSpeed; m_ySpeed = -m_ySpeed; m_Close = false; - SN_StartSequence (poly, poly->seqType, SEQ_DOOR); + SN_StartSequence (poly, poly->seqType, SEQ_DOOR, 0); } } break; @@ -509,7 +509,7 @@ void DPolyDoor::Tick () m_Dist = m_TotalDist - m_Dist; m_Speed = -m_Speed; m_Close = false; - SN_StartSequence (poly, poly->seqType, SEQ_DOOR); + SN_StartSequence (poly, poly->seqType, SEQ_DOOR, 0); } } break; @@ -552,7 +552,7 @@ bool EV_OpenPolyDoor (line_t *line, int polyNum, int speed, angle_t angle, pd->m_Direction = angle >> ANGLETOFINESHIFT; pd->m_xSpeed = FixedMul (pd->m_Speed, finecosine[pd->m_Direction]); pd->m_ySpeed = FixedMul (pd->m_Speed, finesine[pd->m_Direction]); - SN_StartSequence (poly, poly->seqType, SEQ_DOOR); + SN_StartSequence (poly, poly->seqType, SEQ_DOOR, 0); } else if (type == PODOOR_SWING) { @@ -560,7 +560,7 @@ bool EV_OpenPolyDoor (line_t *line, int polyNum, int speed, angle_t angle, pd->m_Direction = 1; // ADD: PODOOR_SWINGL, PODOOR_SWINGR pd->m_Speed = (speed*pd->m_Direction*(ANGLE_90/64))>>3; pd->m_Dist = pd->m_TotalDist = angle; - SN_StartSequence (poly, poly->seqType, SEQ_DOOR); + SN_StartSequence (poly, poly->seqType, SEQ_DOOR, 0); } poly->specialdata = pd; @@ -582,7 +582,7 @@ bool EV_OpenPolyDoor (line_t *line, int polyNum, int speed, angle_t angle, pd->m_Direction = (angle + ANGLE_180) >> ANGLETOFINESHIFT; // reverse the angle pd->m_xSpeed = FixedMul (pd->m_Speed, finecosine[pd->m_Direction]); pd->m_ySpeed = FixedMul (pd->m_Speed, finesine[pd->m_Direction]); - SN_StartSequence (poly, poly->seqType, SEQ_DOOR); + SN_StartSequence (poly, poly->seqType, SEQ_DOOR, 0); } else if (type == PODOOR_SWING) { @@ -590,7 +590,7 @@ bool EV_OpenPolyDoor (line_t *line, int polyNum, int speed, angle_t angle, pd->m_Direction = -1; // ADD: same as above pd->m_Speed = (speed*pd->m_Direction*(ANGLE_90/64))>>3; pd->m_Dist = pd->m_TotalDist = angle; - SN_StartSequence (poly, poly->seqType, SEQ_DOOR); + SN_StartSequence (poly, poly->seqType, SEQ_DOOR, 0); } polyNum = mirror; } diff --git a/src/r_data.cpp b/src/r_data.cpp index 9224ae221..ea84da9df 100644 --- a/src/r_data.cpp +++ b/src/r_data.cpp @@ -645,9 +645,9 @@ void FTextureManager::AddTexturesLump (const void *lumpdata, int lumpsize, int p // Check whether the amount of names reported is correct. int lumplength = Wads.LumpLength(patcheslump); - if (numpatches > (lumplength-4)/8) + if (numpatches > DWORD((lumplength-4)/8)) { - Printf("PNAMES lump is shorter than required (%ld entries reported but only %d bytes (%ld entries) long\n", + Printf("PNAMES lump is shorter than required (%ld entries reported but only %d bytes (%d entries) long\n", numpatches, lumplength, (lumplength-4)/8); // Truncate but continue reading. Who knows how many such lumps exist? numpatches = (lumplength-4)/8; @@ -3204,7 +3204,7 @@ static void R_InitPatches () int i, j; char name[9]; - for (i = sizeof(patches)/sizeof(patches[0]); i >= 0; --i) + for (i = countof(patches); i >= 0; --i) { TexMan.AddPatch (patches[i]); } @@ -3221,7 +3221,7 @@ static void R_InitPatches () } // Spinning power up icons for Heretic and Hexen - for (j = sizeof(spinners)/sizeof(spinners[0])-1; j >= 0; --j) + for (j = countof(spinners)-1; j >= 0; --j) { for (i = 0; i <= 15; ++i) { diff --git a/src/r_polymost.cpp b/src/r_polymost.cpp index f7f232daf..f280d538a 100644 --- a/src/r_polymost.cpp +++ b/src/r_polymost.cpp @@ -525,7 +525,7 @@ int PolyClipper::DoMost (float x0, float y0, float x1, float y1, pmostcallbackty CVAR(Bool, testpolymost, false, 0) static int pmx, pmy; static int pt, px0, py0, px1, py1; -static struct { float x, y; } polypts[80]; +static struct polypt { float x, y; } polypts[80]; static byte polysize[32]; static int numpoly, polypt; PolyClipper TestPoly; @@ -804,7 +804,7 @@ CCMD(initpolymosttest) static void testpolycallback (double *dpx, double *dpy, int n, void *foo) { if (numpoly == sizeof(polysize)) return; - if (size_t(polypt + n) > sizeof(polypts)/sizeof(polypts[0])) return; + if (size_t(polypt + n) > countof(polypts)) return; polysize[numpoly++] = n; for (int i = 0; i < n; ++i) { diff --git a/src/s_environment.cpp b/src/s_environment.cpp index 0f7d43b43..3333d187a 100644 --- a/src/s_environment.cpp +++ b/src/s_environment.cpp @@ -55,7 +55,7 @@ static const FEAXField EAXFields[] = { 0, 0, 0, 0, 6 }, { 0, 0, 0, 0, 7 } }; -#define NUM_EAX_FIELDS (int(sizeof(EAXFields)/sizeof(EAXFields[0]))) +#define NUM_EAX_FIELDS (int(countof(EAXFields))) static const char *EAXFieldNames[NUM_EAX_FIELDS+2] = { diff --git a/src/s_sndseq.cpp b/src/s_sndseq.cpp index f5c10588e..6b85a2b1a 100644 --- a/src/s_sndseq.cpp +++ b/src/s_sndseq.cpp @@ -24,18 +24,21 @@ #include "cmdlib.h" #include "p_local.h" #include "gi.h" +#include "templates.h" +#include "c_dispatch.h" // MACROS ------------------------------------------------------------------ -#define MAX_SEQSIZE 256 -#define GetCommand(a) ((a)>>24) -#define GetData(a) ( ((a) & 0xffffff) == 0xffffff ? ~0 : ((a) & 0xffffff) ) -#define MakeCommand(a,b) (((a) << 24)|((b) & 0xffffff)) +#define GetCommand(a) ((a) & 255) +#define GetData(a) (SDWORD(a) >> 8 ) +#define MakeCommand(a,b) ((a) | ((b) << 8)) #define HexenPlatSeq(a) (a) #define HexenDoorSeq(a) ((a) | 0x40) #define HexenEnvSeq(a) ((a) | 0x80) #define HexenLastSeq (0xff) +#define TIME_REFERENCE level.time + // TYPES ------------------------------------------------------------------- typedef enum @@ -46,15 +49,21 @@ typedef enum SS_STRING_PLAYREPEAT, SS_STRING_PLAYLOOP, SS_STRING_DELAY, + SS_STRING_DELAYONCE, SS_STRING_DELAYRAND, SS_STRING_VOLUME, + SS_STRING_VOLUMEREL, + SS_STRING_VOLUMERAND, SS_STRING_END, SS_STRING_STOPSOUND, SS_STRING_ATTENUATION, SS_STRING_DOOR, SS_STRING_PLATFORM, SS_STRING_ENVIRONMENT, - SS_STRING_NOSTOPCUTOFF + SS_STRING_NOSTOPCUTOFF, + SS_STRING_SLOT, + SS_STRING_RANDOMSEQUENCE, + SS_STRING_RESTART, } ssstrings_t; typedef enum @@ -68,14 +77,20 @@ typedef enum SS_CMD_DELAY, SS_CMD_DELAYRAND, SS_CMD_VOLUME, + SS_CMD_VOLUMEREL, + SS_CMD_VOLUMERAND, SS_CMD_STOPSOUND, SS_CMD_ATTENUATION, + SS_CMD_RANDOMSEQUENCE, + SS_CMD_BRANCH, + SS_CMD_LAST2NOP, + SS_CMD_SELECT, SS_CMD_END } sscmds_t; typedef struct { - const char *name; - byte seqs[4]; + ENamedName Name; + BYTE Seqs[4]; } hexenseq_t; class DSeqActorNode : public DSeqNode @@ -83,13 +98,14 @@ class DSeqActorNode : public DSeqNode DECLARE_CLASS (DSeqActorNode, DSeqNode) HAS_OBJECT_POINTERS public: - DSeqActorNode (AActor *actor, int sequence); + DSeqActorNode (AActor *actor, int sequence, int modenum); ~DSeqActorNode (); void Serialize (FArchive &arc); - void MakeSound () { S_SoundID (m_Actor, CHAN_BODY, m_CurrentSoundID, m_Volume, m_Atten); } - void MakeLoopedSound () { S_LoopedSoundID (m_Actor, CHAN_BODY, m_CurrentSoundID, m_Volume, m_Atten); } + void MakeSound () { S_SoundID (m_Actor, CHAN_BODY, m_CurrentSoundID, clamp(m_Volume, 0.f, 1.f), m_Atten); } + void MakeLoopedSound () { S_LoopedSoundID (m_Actor, CHAN_BODY, m_CurrentSoundID, clamp(m_Volume, 0.f, 1.f), m_Atten); } bool IsPlaying () { return S_GetSoundPlayingInfo (m_Actor, m_CurrentSoundID); } void *Source () { return m_Actor; } + DSeqNode *SpawnChild (int seqnum) { return SN_StartSequence (m_Actor, seqnum, SEQ_NOTRANS, m_ModeNum, true); } private: DSeqActorNode () {} AActor *m_Actor; @@ -99,13 +115,14 @@ class DSeqPolyNode : public DSeqNode { DECLARE_CLASS (DSeqPolyNode, DSeqNode) public: - DSeqPolyNode (polyobj_t *poly, int sequence); + DSeqPolyNode (polyobj_t *poly, int sequence, int modenum); ~DSeqPolyNode (); void Serialize (FArchive &arc); - void MakeSound () { S_SoundID (&m_Poly->startSpot[0], CHAN_BODY, m_CurrentSoundID, m_Volume, m_Atten); } - void MakeLoopedSound () { S_LoopedSoundID (&m_Poly->startSpot[0], CHAN_BODY, m_CurrentSoundID, m_Volume, m_Atten); } + void MakeSound () { S_SoundID (&m_Poly->startSpot[0], CHAN_BODY, m_CurrentSoundID, clamp(m_Volume, 0.f, 1.f), m_Atten); } + void MakeLoopedSound () { S_LoopedSoundID (&m_Poly->startSpot[0], CHAN_BODY, m_CurrentSoundID, clamp(m_Volume, 0.f, 1.f), m_Atten); } bool IsPlaying () { return S_GetSoundPlayingInfo (&m_Poly->startSpot[0], m_CurrentSoundID); } void *Source () { return m_Poly; } + DSeqNode *SpawnChild (int seqnum) { return SN_StartSequence (m_Poly, seqnum, SEQ_NOTRANS, m_ModeNum, true); } private: DSeqPolyNode () {} polyobj_t *m_Poly; @@ -115,13 +132,14 @@ class DSeqSectorNode : public DSeqNode { DECLARE_CLASS (DSeqSectorNode, DSeqNode) public: - DSeqSectorNode (sector_t *sec, int sequence); + DSeqSectorNode (sector_t *sec, int sequence, int modenum); ~DSeqSectorNode (); void Serialize (FArchive &arc); - void MakeSound () { S_SoundID (&m_Sector->soundorg[0], CHAN_BODY, m_CurrentSoundID, m_Volume, m_Atten); Looping = false; } - void MakeLoopedSound () { S_LoopedSoundID (&m_Sector->soundorg[0], CHAN_BODY, m_CurrentSoundID, m_Volume, m_Atten); Looping = true; } + void MakeSound () { S_SoundID (&m_Sector->soundorg[0], CHAN_BODY, m_CurrentSoundID, clamp(m_Volume, 0.f, 1.f), m_Atten); Looping = false; } + void MakeLoopedSound () { S_LoopedSoundID (&m_Sector->soundorg[0], CHAN_BODY, m_CurrentSoundID, clamp(m_Volume, 0.f, 1.f), m_Atten); Looping = true; } bool IsPlaying () { return S_GetSoundPlayingInfo (m_Sector->soundorg, m_CurrentSoundID); } void *Source () { return m_Sector; } + DSeqNode *SpawnChild (int seqnum) { return SN_StartSequence (m_Sector, seqnum, SEQ_NOTRANS, m_ModeNum, true); } bool Looping; private: DSeqSectorNode() {} @@ -130,15 +148,16 @@ private: // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- -static void VerifySeqPtr (int pos, int need); static void AssignTranslations (int seq, seqtype_t type); static void AssignHexenTranslations (void); +static void AddSequence (int curseq, name seqname, name slot, int stopsound, const TArray &ScriptTemp); +static int FindSequence (const char *searchname); +static int FindSequence (name seqname); +static bool TwiddleSeqNum (int &sequence, seqtype_t type); // PUBLIC DATA DEFINITIONS ------------------------------------------------- -sndseq_t **Sequences; -int NumSequences; -int MaxSequences; +TArray Sequences; int ActiveSequences; DSeqNode *DSeqNode::SequenceListHead; @@ -151,8 +170,11 @@ static const char *SSStrings[] = { "playrepeat", "playloop", "delay", + "delayonce", "delayrand", "volume", + "volumerel", + "volumerand", "end", "stopsound", "attenuation", @@ -160,6 +182,9 @@ static const char *SSStrings[] = { "platform", "environment", "nostopcutoff", + "slot", + "randomsequence", + "restart", NULL }; static const char *Attenuations[] = { @@ -171,28 +196,26 @@ static const char *Attenuations[] = { NULL }; static const hexenseq_t HexenSequences[] = { - { "Platform", { HexenPlatSeq(0), HexenPlatSeq(1), HexenPlatSeq(3), HexenLastSeq } }, - { "PlatformMetal", { HexenPlatSeq(2), HexenLastSeq } }, - { "Silence", { HexenPlatSeq(4), HexenDoorSeq(4), HexenLastSeq } }, - { "Lava", { HexenPlatSeq(5), HexenDoorSeq(5), HexenLastSeq } }, - { "Water", { HexenPlatSeq(6), HexenDoorSeq(6), HexenLastSeq } }, - { "Ice", { HexenPlatSeq(7), HexenDoorSeq(7), HexenLastSeq } }, - { "Earth", { HexenPlatSeq(8), HexenDoorSeq(8), HexenLastSeq } }, - { "PlatformMetal2", { HexenPlatSeq(9), HexenLastSeq } }, - { "DoorNormal", { HexenDoorSeq(0), HexenLastSeq } }, - { "DoorHeavy", { HexenDoorSeq(1), HexenLastSeq } }, - { "DoorMetal", { HexenDoorSeq(2), HexenLastSeq } }, - { "DoorCreak", { HexenDoorSeq(3), HexenLastSeq } }, - { "DoorMetal2", { HexenDoorSeq(9), HexenLastSeq } }, - { "Wind", { HexenEnvSeq(10), HexenLastSeq } }, - { NULL, } + { NAME_Platform, { HexenPlatSeq(0), HexenPlatSeq(1), HexenPlatSeq(3), HexenLastSeq } }, + { NAME_PlatformMetal, { HexenPlatSeq(2), HexenLastSeq } }, + { NAME_Silence, { HexenPlatSeq(4), HexenDoorSeq(4), HexenLastSeq } }, + { NAME_Lava, { HexenPlatSeq(5), HexenDoorSeq(5), HexenLastSeq } }, + { NAME_Water, { HexenPlatSeq(6), HexenDoorSeq(6), HexenLastSeq } }, + { NAME_Ice, { HexenPlatSeq(7), HexenDoorSeq(7), HexenLastSeq } }, + { NAME_Earth, { HexenPlatSeq(8), HexenDoorSeq(8), HexenLastSeq } }, + { NAME_PlatformMetal2, { HexenPlatSeq(9), HexenLastSeq } }, + { NAME_DoorNormal, { HexenDoorSeq(0), HexenLastSeq } }, + { NAME_DoorHeavy, { HexenDoorSeq(1), HexenLastSeq } }, + { NAME_DoorMetal, { HexenDoorSeq(2), HexenLastSeq } }, + { NAME_DoorCreak, { HexenDoorSeq(3), HexenLastSeq } }, + { NAME_DoorMetal2, { HexenDoorSeq(9), HexenLastSeq } }, + { NAME_Wind, { HexenEnvSeq(10), HexenLastSeq } }, + { NAME_None } }; static int SeqTrans[64*3]; -static unsigned int *ScriptTemp; -static int ScriptTempSize; -static FRandom pr_ssdelay ("SSDelay"); +static FRandom pr_sndseq ("SndSeq"); // CODE -------------------------------------------------------------------- @@ -208,62 +231,115 @@ void DSeqNode::SerializeSequences (FArchive &arc) IMPLEMENT_CLASS (DSeqNode) DSeqNode::DSeqNode () +: m_SequenceChoices(0) { - m_Next = m_Prev = NULL; + m_Next = m_Prev = m_ChildSeqNode = m_ParentSeqNode = NULL; } void DSeqNode::Serialize (FArchive &arc) { int seqOffset; + unsigned int i; Super::Serialize (arc); if (arc.IsStoring ()) { seqOffset = SN_GetSequenceOffset (m_Sequence, m_SequencePtr); arc << seqOffset - << m_DelayTics + << m_DelayUntilTic << m_Volume << m_Atten + << m_ModeNum << m_Next << m_Prev - << AR_SOUND(m_CurrentSoundID); - arc.WriteString (Sequences[m_Sequence]->name); + << m_ChildSeqNode + << m_ParentSeqNode + << AR_SOUND(m_CurrentSoundID) + << Sequences[m_Sequence]->SeqName; + + arc.WriteCount (m_SequenceChoices.Size()); + for (i = 0; i < m_SequenceChoices.Size(); ++i) + { + arc << Sequences[m_SequenceChoices[i]]->SeqName; + } } else { - char *seqName = NULL; + name seqName; int delayTics = 0, id; float volume; int atten = ATTN_NORM; + int seqnum; + unsigned int numchoices; arc << seqOffset << delayTics << volume << atten + << m_ModeNum << m_Next << m_Prev + << m_ChildSeqNode + << m_ParentSeqNode << AR_SOUND(id) << seqName; - int i; - - for (i = 0; i < NumSequences; i++) + seqnum = FindSequence (seqName); + if (seqnum >= 0) { - if (!stricmp (seqName, Sequences[i]->name)) - { - ActivateSequence (i); - break; - } + ActivateSequence (seqnum); + } + else + { + I_Error ("Unknown sound sequence '%s'\n", seqName.GetChars()); + // Can I just Destroy() here instead of erroring out? } - if (i == NumSequences) - I_Error ("Unknown sound sequence '%s'\n", seqName); - ChangeData (seqOffset, delayTics, volume, id); + ChangeData (seqOffset, delayTics - TIME_REFERENCE, volume, id); - delete[] seqName; + numchoices = arc.ReadCount(); + for (i = 0; i < numchoices; ++i) + { + arc << seqName; + m_SequenceChoices[i] = FindSequence (seqName); + } } } +void DSeqNode::Destroy() +{ + // If this sequence was launched by a parent sequence, advance that + // sequence now. + if (m_ParentSeqNode != NULL && m_ParentSeqNode->m_ChildSeqNode == this) + { + m_ParentSeqNode->m_SequencePtr++; + m_ParentSeqNode->m_ChildSeqNode = NULL; + m_ParentSeqNode = NULL; + } + Super::Destroy(); +} + +void DSeqNode::StopAndDestroy () +{ + if (m_ChildSeqNode != NULL) + { + m_ChildSeqNode->StopAndDestroy(); + } + Destroy(); +} + +void DSeqNode::AddChoice (int seqnum, seqtype_t type) +{ + if (TwiddleSeqNum (seqnum, type)) + { + m_SequenceChoices.Push (seqnum); + } +} + +name DSeqNode::GetSequenceName () const +{ + return Sequences[m_Sequence]->SeqName; +} IMPLEMENT_POINTY_CLASS (DSeqActorNode) DECLARE_POINTER (m_Actor) @@ -291,21 +367,6 @@ void DSeqSectorNode::Serialize (FArchive &arc) arc << m_Sector << Looping; } -//========================================================================== -// -// VerifySequencePtr -// -//========================================================================== - -static void VerifySeqPtr (int pos, int need) -{ - if (pos + need > ScriptTempSize) - { - ScriptTempSize *= 2; - ScriptTemp = (unsigned int *)Realloc (ScriptTemp, ScriptTempSize * sizeof(*ScriptTemp)); - } -} - //========================================================================== // // AssignTranslations @@ -335,30 +396,30 @@ static void AssignTranslations (int seq, seqtype_t type) static void AssignHexenTranslations (void) { - int i, j, seq; + unsigned int i, j, seq; - for (i = 0; HexenSequences[i].name; i++) + for (i = 0; HexenSequences[i].Name != NAME_None; i++) { - for (seq = 0; seq < NumSequences; seq++) + for (seq = 0; seq < Sequences.Size(); seq++) { - if (!stricmp (HexenSequences[i].name, Sequences[seq]->name)) + if (HexenSequences[i].Name == Sequences[seq]->SeqName) break; } - if (seq == NumSequences) + if (seq == Sequences.Size()) continue; - for (j = 0; j < 4 && HexenSequences[i].seqs[j] != HexenLastSeq; j++) + for (j = 0; j < 4 && HexenSequences[i].Seqs[j] != HexenLastSeq; j++) { int trans; - if (HexenSequences[i].seqs[j] & 0x40) + if (HexenSequences[i].Seqs[j] & 0x40) trans = 64; - else if (HexenSequences[i].seqs[j] & 0x80) + else if (HexenSequences[i].Seqs[j] & 0x80) trans = 64*2; else trans = 0; - SeqTrans[trans + (HexenSequences[i].seqs[j] & 0x3f)] = seq; + SeqTrans[trans + (HexenSequences[i].Seqs[j] & 0x3f)] = seq; } } } @@ -371,161 +432,192 @@ static void AssignHexenTranslations (void) void S_ParseSndSeq (int levellump) { + TArray ScriptTemp; int lastlump, lump; - char name[MAX_SNDNAME+1]; + char seqtype = ':'; + name seqname; + name slot; int stopsound; - int cursize; + int delaybase; + float volumebase; int curseq = -1; // First free the old SNDSEQ data. This allows us to reload this for each level // and specify a level specific SNDSEQ lump! - if (Sequences) + for (unsigned int i = 0; i < Sequences.Size(); i++) { - for (int i=0;iname, name) == 0) + if (Sequences[curseq]->SeqName == seqname) { free (Sequences[curseq]); Sequences[curseq] = NULL; break; } } - if (curseq == NumSequences) - NumSequences++; - if (NumSequences > MaxSequences) + if (curseq == (int)Sequences.Size()) { - MaxSequences = MaxSequences ? MaxSequences * 2 : 64; - Sequences = (sndseq_t **)Realloc (Sequences, MaxSequences * sizeof(*Sequences)); + Sequences.Push (NULL); } - memset (ScriptTemp, 0, sizeof(*ScriptTemp) * ScriptTempSize); + ScriptTemp.Clear(); stopsound = 0; - cursize = 0; + slot = NAME_None; + if (seqtype == '[') + { + SC_SetCMode (true); + ScriptTemp.Push (0); // to be filled when definition is complete + } continue; } if (curseq == -1) { continue; } + if (seqtype == '[') + { + if (sc_String[0] == ']') + { // End of this definition + ScriptTemp[0] = MakeCommand(SS_CMD_SELECT, (ScriptTemp.Size()-1)/2); + AddSequence (curseq, seqname, slot, stopsound, ScriptTemp); + curseq = -1; + SC_SetCMode (false); + } + else + { // Add a selection + SC_UnGet(); + SC_MustGetNumber(); + ScriptTemp.Push (sc_Number); + SC_MustGetString(); + ScriptTemp.Push (name(sc_String)); + } + continue; + } switch (SC_MustMatchString (SSStrings)) { case SS_STRING_PLAYUNTILDONE: - VerifySeqPtr (cursize, 2); SC_MustGetString (); - ScriptTemp[cursize++] = MakeCommand (SS_CMD_PLAY, S_FindSound (sc_String)); - ScriptTemp[cursize++] = SS_CMD_WAITUNTILDONE << 24; + ScriptTemp.Push(MakeCommand(SS_CMD_PLAY, S_FindSound (sc_String))); + ScriptTemp.Push(MakeCommand(SS_CMD_WAITUNTILDONE, 0)); break; case SS_STRING_PLAY: - VerifySeqPtr (cursize, 1); SC_MustGetString (); - ScriptTemp[cursize++] = MakeCommand (SS_CMD_PLAY, S_FindSound (sc_String)); + ScriptTemp.Push(MakeCommand(SS_CMD_PLAY, S_FindSound (sc_String))); break; case SS_STRING_PLAYTIME: - VerifySeqPtr (cursize, 2); SC_MustGetString (); - ScriptTemp[cursize++] = MakeCommand (SS_CMD_PLAY, S_FindSound (sc_String)); + ScriptTemp.Push(MakeCommand(SS_CMD_PLAY, S_FindSound (sc_String))); SC_MustGetNumber (); - ScriptTemp[cursize++] = MakeCommand (SS_CMD_DELAY, sc_Number); + ScriptTemp.Push(MakeCommand(SS_CMD_DELAY, sc_Number)); break; case SS_STRING_PLAYREPEAT: - VerifySeqPtr (cursize, 1); SC_MustGetString (); - ScriptTemp[cursize++] = MakeCommand (SS_CMD_PLAYREPEAT, S_FindSound (sc_String)); + ScriptTemp.Push(MakeCommand (SS_CMD_PLAYREPEAT, S_FindSound (sc_String))); break; case SS_STRING_PLAYLOOP: - VerifySeqPtr (cursize, 2); SC_MustGetString (); - ScriptTemp[cursize++] = MakeCommand (SS_CMD_PLAYLOOP, S_FindSound (sc_String)); + ScriptTemp.Push(MakeCommand (SS_CMD_PLAYLOOP, S_FindSound (sc_String))); SC_MustGetNumber (); - ScriptTemp[cursize++] = sc_Number; + ScriptTemp.Push(sc_Number); break; case SS_STRING_DELAY: - VerifySeqPtr (cursize, 1); SC_MustGetNumber (); - ScriptTemp[cursize++] = MakeCommand (SS_CMD_DELAY, sc_Number); + ScriptTemp.Push(MakeCommand(SS_CMD_DELAY, sc_Number)); + break; + + case SS_STRING_DELAYONCE: + SC_MustGetNumber (); + ScriptTemp.Push(MakeCommand(SS_CMD_DELAY, sc_Number)); + ScriptTemp.Push(MakeCommand(SS_CMD_LAST2NOP, 0)); break; case SS_STRING_DELAYRAND: - VerifySeqPtr (cursize, 2); SC_MustGetNumber (); - ScriptTemp[cursize++] = MakeCommand (SS_CMD_DELAYRAND, sc_Number); + delaybase = sc_Number; + ScriptTemp.Push(MakeCommand(SS_CMD_DELAYRAND, sc_Number)); SC_MustGetNumber (); - ScriptTemp[cursize++] = sc_Number; + ScriptTemp.Push(MAX(1, sc_Number - delaybase + 1)); break; - case SS_STRING_VOLUME: - VerifySeqPtr (cursize, 1); - SC_MustGetNumber (); - ScriptTemp[cursize++] = MakeCommand (SS_CMD_VOLUME, sc_Number); + case SS_STRING_VOLUME: // volume is in range 0..100 + SC_MustGetFloat (); + ScriptTemp.Push(MakeCommand(SS_CMD_VOLUME, int(sc_Float * (FRACUNIT/100.f)))); + break; + + case SS_STRING_VOLUMEREL: + SC_MustGetFloat (); + ScriptTemp.Push(MakeCommand(SS_CMD_VOLUMEREL, int(sc_Float * (FRACUNIT/100.f)))); + break; + + case SS_STRING_VOLUMERAND: + SC_MustGetFloat (); + volumebase = sc_Float; + ScriptTemp.Push(MakeCommand(SS_CMD_VOLUMERAND, int(sc_Float * (FRACUNIT/100.f)))); + SC_MustGetFloat (); + ScriptTemp.Push(int((sc_Float - volumebase) * (256/100.f))); break; case SS_STRING_STOPSOUND: - VerifySeqPtr (cursize, 1); SC_MustGetString (); stopsound = S_FindSound (sc_String); - ScriptTemp[cursize++] = SS_CMD_STOPSOUND << 24; + ScriptTemp.Push(MakeCommand(SS_CMD_STOPSOUND, 0)); break; case SS_STRING_NOSTOPCUTOFF: - VerifySeqPtr (cursize, 1); stopsound = -1; - ScriptTemp[cursize++] = SS_CMD_STOPSOUND << 24; + ScriptTemp.Push(MakeCommand(SS_CMD_STOPSOUND, 0)); break; case SS_STRING_ATTENUATION: - VerifySeqPtr (cursize, 1); SC_MustGetString (); - ScriptTemp[cursize++] = MakeCommand (SS_CMD_ATTENUATION, - SC_MustMatchString (Attenuations)); + ScriptTemp.Push(MakeCommand(SS_CMD_ATTENUATION, SC_MustMatchString(Attenuations))); + break; + + case SS_STRING_RANDOMSEQUENCE: + ScriptTemp.Push(MakeCommand(SS_CMD_RANDOMSEQUENCE, 0)); + break; + + case SS_STRING_RESTART: + ScriptTemp.Push(MakeCommand(SS_CMD_BRANCH, ScriptTemp.Size())); break; case SS_STRING_END: - Sequences[curseq] = (sndseq_t *)Malloc (sizeof(sndseq_t) + sizeof(int)*cursize); - strcpy (Sequences[curseq]->name, name); - memcpy (Sequences[curseq]->script, ScriptTemp, sizeof(int)*cursize); - Sequences[curseq]->script[cursize] = SS_CMD_END << 24; - Sequences[curseq]->stopsound = stopsound; + AddSequence (curseq, seqname, slot, stopsound, ScriptTemp); curseq = -1; break; @@ -540,17 +632,30 @@ void S_ParseSndSeq (int levellump) case SS_STRING_ENVIRONMENT: AssignTranslations (curseq, SEQ_ENVIRONMENT); break; + + case SS_STRING_SLOT: + SC_MustGetString(); + slot = sc_String; + break; } } SC_Close (); } - free (ScriptTemp); - if (gameinfo.gametype == GAME_Hexen) AssignHexenTranslations (); } +static void AddSequence (int curseq, name seqname, name slot, int stopsound, const TArray &ScriptTemp) +{ + Sequences[curseq] = (FSoundSequence *)Malloc (sizeof(FSoundSequence) + sizeof(DWORD)*ScriptTemp.Size()); + Sequences[curseq]->SeqName = seqname; + Sequences[curseq]->Slot = slot; + Sequences[curseq]->StopSound = stopsound; + memcpy (Sequences[curseq]->Script, &ScriptTemp[0], sizeof(int)*ScriptTemp.Size()); + Sequences[curseq]->Script[ScriptTemp.Size()] = MakeCommand(SS_CMD_END, 0); +} + DSeqNode::~DSeqNode () { if (SequenceListHead == this) @@ -562,7 +667,8 @@ DSeqNode::~DSeqNode () ActiveSequences--; } -DSeqNode::DSeqNode (int sequence) +DSeqNode::DSeqNode (int sequence, int modenum) +: m_ModeNum(modenum), m_SequenceChoices(0) { ActivateSequence (sequence); if (!SequenceListHead) @@ -577,14 +683,15 @@ DSeqNode::DSeqNode (int sequence) SequenceListHead = this; m_Prev = NULL; } + m_ParentSeqNode = m_ChildSeqNode = NULL; } void DSeqNode::ActivateSequence (int sequence) { - m_SequencePtr = Sequences[sequence]->script; + m_SequencePtr = Sequences[sequence]->Script; m_Sequence = sequence; - m_DelayTics = 0; - m_StopSound = Sequences[sequence]->stopsound; + m_DelayUntilTic = 0; + m_StopSound = Sequences[sequence]->StopSound; m_CurrentSoundID = 0; m_Volume = 1; // Start at max volume... m_Atten = ATTN_IDLE; // ...and idle attenuation @@ -592,20 +699,20 @@ void DSeqNode::ActivateSequence (int sequence) ActiveSequences++; } -DSeqActorNode::DSeqActorNode (AActor *actor, int sequence) - : DSeqNode (sequence), +DSeqActorNode::DSeqActorNode (AActor *actor, int sequence, int modenum) + : DSeqNode (sequence, modenum), m_Actor (actor) { } -DSeqPolyNode::DSeqPolyNode (polyobj_t *poly, int sequence) - : DSeqNode (sequence), +DSeqPolyNode::DSeqPolyNode (polyobj_t *poly, int sequence, int modenum) + : DSeqNode (sequence, modenum), m_Poly (poly) { } -DSeqSectorNode::DSeqSectorNode (sector_t *sec, int sequence) - : DSeqNode (sequence), +DSeqSectorNode::DSeqSectorNode (sector_t *sec, int sequence, int modenum) + : DSeqNode (sequence, modenum), Looping (false), m_Sector (sec) { @@ -639,25 +746,43 @@ static bool TwiddleSeqNum (int &sequence, seqtype_t type) return true; } -void SN_StartSequence (AActor *actor, int sequence, seqtype_t type) +DSeqNode *SN_StartSequence (AActor *actor, int sequence, seqtype_t type, int modenum, bool nostop) { - SN_StopSequence (actor); // Stop any previous sequence + if (!nostop) + { + SN_StopSequence (actor); // Stop any previous sequence + } if (TwiddleSeqNum (sequence, type)) - new DSeqActorNode (actor, sequence); + { + return new DSeqActorNode (actor, sequence, modenum); + } + return NULL; } -void SN_StartSequence (sector_t *sector, int sequence, seqtype_t type) +DSeqNode *SN_StartSequence (sector_t *sector, int sequence, seqtype_t type, int modenum, bool nostop) { - SN_StopSequence (sector); + if (!nostop) + { + SN_StopSequence (sector); + } if (TwiddleSeqNum (sequence, type)) - new DSeqSectorNode (sector, sequence); + { + return new DSeqSectorNode (sector, sequence, modenum); + } + return NULL; } -void SN_StartSequence (polyobj_t *poly, int sequence, seqtype_t type) +DSeqNode *SN_StartSequence (polyobj_t *poly, int sequence, seqtype_t type, int modenum, bool nostop) { - SN_StopSequence (poly); + if (!nostop) + { + SN_StopSequence (poly); + } if (TwiddleSeqNum (sequence, type)) - new DSeqPolyNode (poly, sequence); + { + return new DSeqPolyNode (poly, sequence, modenum); + } + return NULL; } //========================================================================== @@ -666,46 +791,69 @@ void SN_StartSequence (polyobj_t *poly, int sequence, seqtype_t type) // //========================================================================== -void SN_StartSequence (AActor *actor, const char *name) +DSeqNode *SN_StartSequence (AActor *actor, const char *seqname, int modenum) { - int i; - - for (i = 0; i < NumSequences; i++) + int seqnum = FindSequence (seqname); + if (seqnum >= 0) { - if (!stricmp (name, Sequences[i]->name)) - { - SN_StartSequence (actor, i, SEQ_NOTRANS); - return; - } + return SN_StartSequence (actor, seqnum, SEQ_NOTRANS, modenum); } + return NULL; } -void SN_StartSequence (sector_t *sec, const char *name) +DSeqNode *SN_StartSequence (AActor *actor, name seqname, int modenum) { - int i; - - for (i = 0; i < NumSequences; i++) + int seqnum = FindSequence (seqname); + if (seqnum >= 0) { - if (!stricmp (name, Sequences[i]->name)) - { - SN_StartSequence (sec, i, SEQ_NOTRANS); - return; - } + return SN_StartSequence (actor, seqnum, SEQ_NOTRANS, modenum); } + return NULL; } -void SN_StartSequence (polyobj_t *poly, const char *name) +DSeqNode *SN_StartSequence (sector_t *sec, const char *seqname, int modenum) +{ + int seqnum = FindSequence (seqname); + if (seqnum >= 0) + { + return SN_StartSequence (sec, seqnum, SEQ_NOTRANS, modenum); + } + return NULL; +} + +DSeqNode *SN_StartSequence (polyobj_t *poly, const char *seqname, int modenum) +{ + int seqnum = FindSequence (seqname); + if (seqnum >= 0) + { + return SN_StartSequence (poly, seqnum, SEQ_NOTRANS, modenum); + } + return NULL; +} + +static int FindSequence (const char *searchname) +{ + name seqname (searchname, true); + + if (seqname != NAME_None) + { + return FindSequence (seqname); + } + return -1; +} + +static int FindSequence (name seqname) { int i; - for (i = 0; i < NumSequences; i++) + for (i = Sequences.Size(); i-- > 0; ) { - if (!stricmp (name, Sequences[i]->name)) + if (seqname == Sequences[i]->SeqName) { - SN_StartSequence (poly, i, SEQ_NOTRANS); - return; + return i; } } + return -1; } //========================================================================== @@ -733,12 +881,12 @@ void SN_DoStop (void *source) { DSeqNode *node; - for (node = DSeqNode::FirstSequence (); node; ) + for (node = DSeqNode::FirstSequence(); node; ) { DSeqNode *next = node->NextSequence(); if (node->Source() == source) { - node->Destroy (); + node->StopAndDestroy (); } node = next; } @@ -798,86 +946,170 @@ bool SN_IsMakingLoopingSound (sector_t *sector) void DSeqNode::Tick () { - if (m_DelayTics > 0) + if (TIME_REFERENCE < m_DelayUntilTic) { - m_DelayTics--; return; } - bool sndPlaying = IsPlaying (); - if (m_DelayTics < 0 && sndPlaying) + for (;;) { - m_DelayTics++; - return; - } - switch (GetCommand(*m_SequencePtr)) - { - case SS_CMD_PLAY: - if (!sndPlaying) + switch (GetCommand(*m_SequencePtr)) { - m_CurrentSoundID = GetData(*m_SequencePtr); - MakeSound (); - } - m_SequencePtr++; - break; + case SS_CMD_NONE: + m_SequencePtr++; + break; - case SS_CMD_WAITUNTILDONE: - if (!sndPlaying) - { + case SS_CMD_PLAY: + if (!IsPlaying()) + { + m_CurrentSoundID = GetData(*m_SequencePtr); + MakeSound (); + } + m_SequencePtr++; + break; + + case SS_CMD_WAITUNTILDONE: + if (!IsPlaying()) + { + m_SequencePtr++; + m_CurrentSoundID = 0; + } + else + { + return; + } + break; + + case SS_CMD_PLAYREPEAT: + if (!IsPlaying()) + { + // Does not advance sequencePtr, so it will repeat as necessary. + m_CurrentSoundID = GetData(*m_SequencePtr); + MakeLoopedSound (); + } + return; + + case SS_CMD_PLAYLOOP: + // Like SS_CMD_PLAYREPEAT, sequencePtr is not advanced, so this + // command will repeat until the sequence is stopped. + m_CurrentSoundID = GetData(m_SequencePtr[0]); + MakeSound (); + m_DelayUntilTic = TIME_REFERENCE + m_SequencePtr[1]; + return; + + case SS_CMD_RANDOMSEQUENCE: + // If there's nothing to choose from, then there's nothing to do here. + if (m_SequenceChoices.Size() == 0) + { + m_SequencePtr++; + } + else if (m_ChildSeqNode == NULL) + { + int choice = pr_sndseq() % m_SequenceChoices.Size(); + m_ChildSeqNode = SpawnChild (m_SequenceChoices[choice]); + if (m_ChildSeqNode == NULL) + { // Failed, so skip to next instruction. + m_SequencePtr++; + } + else + { // Copy parameters to the child and link it to this one. + m_ChildSeqNode->m_Volume = m_Volume; + m_ChildSeqNode->m_Atten = m_Atten; + m_ChildSeqNode->m_ParentSeqNode = this; + return; + } + } + else + { + // If we get here, then the child sequence is playing, and it + // will advance our sequence pointer for us when it finishes. + return; + } + break; + + case SS_CMD_DELAY: + m_DelayUntilTic = TIME_REFERENCE + GetData(*m_SequencePtr); m_SequencePtr++; m_CurrentSoundID = 0; + return; + + case SS_CMD_DELAYRAND: + m_DelayUntilTic = TIME_REFERENCE + GetData(m_SequencePtr[0]) + pr_sndseq(m_SequencePtr[1]); + m_SequencePtr += 2; + m_CurrentSoundID = 0; + return; + + case SS_CMD_VOLUME: + m_Volume = GetData(*m_SequencePtr) / float(FRACUNIT); + m_SequencePtr++; + break; + + case SS_CMD_VOLUMEREL: + // like SS_CMD_VOLUME, but the new volume is added to the old volume + m_Volume += GetData(*m_SequencePtr) / float(FRACUNIT); + m_SequencePtr++; + break; + + case SS_CMD_VOLUMERAND: + // like SS_CMD_VOLUME, but the new volume is chosen randomly from a range + m_Volume = GetData(m_SequencePtr[0]) / float(FRACUNIT) + (pr_sndseq() % m_SequencePtr[1]) / 255.f; + m_SequencePtr += 2; + break; + + case SS_CMD_STOPSOUND: + // Wait until something else stops the sequence + return; + + case SS_CMD_ATTENUATION: + m_Atten = GetData(*m_SequencePtr); + m_SequencePtr++; + break; + + case SS_CMD_BRANCH: + m_SequencePtr -= GetData(*m_SequencePtr); + break; + + case SS_CMD_SELECT: + { // Completely transfer control to the choice matching m_ModeNum. + // If no match is found, then just advance to the next command + // in this sequence, which should be SS_CMD_END. + int numchoices = GetData(*m_SequencePtr++); + int i; + + for (i = 0; i < numchoices; ++i) + { + if (m_SequencePtr[i*2] == m_ModeNum) + { + int seqnum = FindSequence (ENamedName(m_SequencePtr[i*2+1])); + if (seqnum >= 0) + { // Found a match, and it's a good one too. + ActiveSequences--; + ActivateSequence (seqnum); + break; + } + } + } + if (i == numchoices) + { // No match (or no good match) was found. + m_SequencePtr += numchoices * 2; + } + } + break; + + case SS_CMD_LAST2NOP: + *(m_SequencePtr - 1) = MakeCommand(SS_CMD_NONE, 0); + *m_SequencePtr = MakeCommand(SS_CMD_NONE, 0); + m_SequencePtr++; + break; + + case SS_CMD_END: + Destroy (); + return; + + default: + Printf ("Corrupted sound sequence: %s\n", Sequences[m_Sequence]->SeqName.GetChars()); + Destroy (); + return; } - break; - - case SS_CMD_PLAYREPEAT: - if (!sndPlaying) - { - // Does not advance sequencePtr, so it will repeat - // as necessary - m_CurrentSoundID = GetData(*m_SequencePtr); - MakeLoopedSound (); - } - break; - - case SS_CMD_PLAYLOOP: - m_CurrentSoundID = GetData(*m_SequencePtr); - MakeLoopedSound (); - m_DelayTics = -(signed)GetData(*(m_SequencePtr+1)); - break; - - case SS_CMD_DELAY: - m_DelayTics = GetData(*m_SequencePtr); - m_SequencePtr++; - m_CurrentSoundID = 0; - break; - - case SS_CMD_DELAYRAND: - m_DelayTics = GetData(*m_SequencePtr)+ - pr_ssdelay()%(*(m_SequencePtr+1)-GetData(*m_SequencePtr)); - m_SequencePtr += 2; - m_CurrentSoundID = 0; - break; - - case SS_CMD_VOLUME: - // volume is in range 0..100 - m_Volume = GetData(*m_SequencePtr)/100.f; - m_SequencePtr++; - break; - - case SS_CMD_STOPSOUND: - // Wait until something else stops the sequence - break; - - case SS_CMD_ATTENUATION: - m_Atten = GetData(*m_SequencePtr); - m_SequencePtr++; - break; - - case SS_CMD_END: - Destroy (); - break; - - default: - break; } } @@ -920,9 +1152,24 @@ void SN_StopAllSequences (void) // //========================================================================== -ptrdiff_t SN_GetSequenceOffset (int sequence, unsigned int *sequencePtr) +ptrdiff_t SN_GetSequenceOffset (int sequence, SDWORD *sequencePtr) { - return sequencePtr - Sequences[sequence]->script; + return sequencePtr - Sequences[sequence]->Script; +} + +//========================================================================== +// +// SN_GetSequenceSlot +// +//========================================================================== + +name SN_GetSequenceSlot (int sequence, seqtype_t type) +{ + if (TwiddleSeqNum (sequence, type)) + { + return Sequences[sequence]->Slot; + } + return NAME_None; } //========================================================================== @@ -954,9 +1201,27 @@ void SN_ChangeNodeData (int nodeNum, int seqOffset, int delayTics, float volume, void DSeqNode::ChangeData (int seqOffset, int delayTics, float volume, int currentSoundID) { - m_DelayTics = delayTics; + m_DelayUntilTic = TIME_REFERENCE + delayTics; m_Volume = volume; m_SequencePtr += seqOffset; m_CurrentSoundID = currentSoundID; } +//========================================================================== +// +// CCMD playsequence +// +// Causes the player to play a sound sequence. +//========================================================================== + +CCMD(playsequence) +{ + if (argv.argc() < 2 || argv.argc() > 3) + { + Printf ("Usage: playsequence [choice number]\n"); + } + else + { + SN_StartSequence (players[consoleplayer].mo, argv[1], argv.argc() > 2 ? atoi(argv[2]) : 0); + } +} diff --git a/src/s_sndseq.h b/src/s_sndseq.h index 894a83bf0..79b1ed5fa 100644 --- a/src/s_sndseq.h +++ b/src/s_sndseq.h @@ -5,6 +5,7 @@ //#include "actor.h" #include "s_sound.h" #include "r_defs.h" +#include "name.h" typedef enum { SEQ_PLATFORM, @@ -16,52 +17,47 @@ typedef enum { struct sector_t; -void S_ParseSndSeq (int levellump); -void SN_StartSequence (AActor *mobj, int sequence, seqtype_t type); -void SN_StartSequence (AActor *mobj, const char *name); -void SN_StartSequence (sector_t *sector, int sequence, seqtype_t type); -void SN_StartSequence (sector_t *sector, const char *name); -void SN_StartSequence (fixed_t spot[3], int sequence, seqtype_t type); -void SN_StartSequence (fixed_t spot[3], const char *name); -void SN_StopSequence (AActor *mobj); -void SN_StopSequence (sector_t *sector); -void SN_StopSequence (fixed_t spot[3]); -void SN_UpdateActiveSequences (void); -void SN_StopAllSequences (void); -ptrdiff_t SN_GetSequenceOffset (int sequence, unsigned int *sequencePtr); -void SN_ChangeNodeData (int nodeNum, int seqOffset, int delayTics, - float volume, int currentSoundID); -bool SN_IsMakingLoopingSound (sector_t *sector); - class DSeqNode : public DObject { DECLARE_CLASS (DSeqNode, DObject) public: virtual ~DSeqNode (); void Serialize (FArchive &arc); + void StopAndDestroy (); + void Destroy (); + void Tick (); + void ChangeData (int seqOffset, int delayTics, float volume, int currentSoundID); + void AddChoice (int seqnum, seqtype_t type); + name GetSequenceName() const; + virtual void MakeSound () {} virtual void MakeLoopedSound () {} virtual void *Source () { return NULL; } virtual bool IsPlaying () { return false; } - void Tick (); + virtual DSeqNode *SpawnChild (int seqnum) { return NULL; } + inline static DSeqNode *FirstSequence() { return SequenceListHead; } inline DSeqNode *NextSequence() const { return m_Next; } - void ChangeData (int seqOffset, int delayTics, float volume, int currentSoundID); static void SerializeSequences (FArchive &arc); protected: DSeqNode (); - DSeqNode (int sequence); + DSeqNode (int sequence, int modenum); - unsigned int *m_SequencePtr; + SDWORD *m_SequencePtr; int m_Sequence; int m_CurrentSoundID; - int m_DelayTics; + int m_DelayUntilTic; float m_Volume; int m_StopSound; int m_Atten; + int m_ModeNum; + + TArray m_SequenceChoices; + DSeqNode *m_ChildSeqNode; + DSeqNode *m_ParentSeqNode; private: static DSeqNode *SequenceListHead; @@ -72,30 +68,31 @@ private: friend void SN_StopAllSequences (void); }; -typedef struct +struct FSoundSequence { - char name[MAX_SNDNAME+1]; - int stopsound; - unsigned int script[1]; // + more until end of sequence script -} sndseq_t; + name SeqName; + name Slot; + int StopSound; + SDWORD Script[1]; // + more until end of sequence script +}; -void SN_StartSequence (AActor *mobj, int sequence, seqtype_t type); -void SN_StartSequence (AActor *mobj, const char *name); -void SN_StartSequence (sector_t *sector, int sequence, seqtype_t type); -void SN_StartSequence (sector_t *sector, const char *name); -void SN_StartSequence (polyobj_t *poly, int sequence, seqtype_t type); -void SN_StartSequence (polyobj_t *poly, const char *name); +void S_ParseSndSeq (int levellump); +DSeqNode *SN_StartSequence (AActor *mobj, int sequence, seqtype_t type, int modenum, bool nostop=false); +DSeqNode *SN_StartSequence (AActor *mobj, const char *name, int modenum); +DSeqNode *SN_StartSequence (AActor *mobj, name seqname, int modenum); +DSeqNode *SN_StartSequence (sector_t *sector, int sequence, seqtype_t type, int modenum, bool nostop=false); +DSeqNode *SN_StartSequence (sector_t *sector, const char *name, int modenum); +DSeqNode *SN_StartSequence (polyobj_t *poly, int sequence, seqtype_t type, int modenum, bool nostop=false); +DSeqNode *SN_StartSequence (polyobj_t *poly, const char *name, int modenum); void SN_StopSequence (AActor *mobj); void SN_StopSequence (sector_t *sector); void SN_StopSequence (polyobj_t *poly); void SN_UpdateActiveSequences (void); -ptrdiff_t SN_GetSequenceOffset (int sequence, unsigned int *sequencePtr); +ptrdiff_t SN_GetSequenceOffset (int sequence, SDWORD *sequencePtr); void SN_DoStop (void *); void SN_ChangeNodeData (int nodeNum, int seqOffset, int delayTics, float volume, int currentSoundID); - -extern sndseq_t **Sequences; -extern int ActiveSequences; -extern int NumSequences; +name SN_GetSequenceSlot (int sequence, seqtype_t type); +bool SN_IsMakingLoopingSound (sector_t *sector); #endif //__S_SNDSEQ_H__ diff --git a/src/st_stuff.cpp b/src/st_stuff.cpp index 0ce821bd1..a619233a9 100644 --- a/src/st_stuff.cpp +++ b/src/st_stuff.cpp @@ -28,8 +28,6 @@ #include "d_event.h" #include "gi.h" -#define COUNT_CHEATS(l) (sizeof(l)/sizeof(l[0])) - EXTERN_CVAR (Bool, ticker); EXTERN_CVAR (Bool, noisedebug); EXTERN_CVAR (Int, am_cheat); @@ -241,22 +239,22 @@ BOOL ST_Responder (event_t *ev) { case GAME_Doom: cheats = DoomCheats; - numcheats = COUNT_CHEATS(DoomCheats); + numcheats = countof(DoomCheats); break; case GAME_Heretic: cheats = HereticCheats; - numcheats = COUNT_CHEATS(HereticCheats); + numcheats = countof(HereticCheats); break; case GAME_Hexen: cheats = HexenCheats; - numcheats = COUNT_CHEATS(HexenCheats); + numcheats = countof(HexenCheats); break; case GAME_Strife: cheats = StrifeCheats; - numcheats = COUNT_CHEATS(StrifeCheats); + numcheats = countof(StrifeCheats); break; default: diff --git a/src/thingdef.cpp b/src/thingdef.cpp index d46353dc8..be1c4001c 100644 --- a/src/thingdef.cpp +++ b/src/thingdef.cpp @@ -284,7 +284,7 @@ static int STACK_ARGS flagcmp (const void * a, const void * b) static flagdef *FindFlag (flagdef *flags, int numflags, const char *flag) { - int min = 0, max = numflags - 1;//sizeof(ActorFlags)/sizeof(ActorFlags[0])-1; + int min = 0, max = numflags - 1; while (min <= max) { @@ -697,11 +697,11 @@ static AFuncDesc * FindFunction(char * string) if (!funcsorted) { - qsort(AFTable, sizeof(AFTable)/sizeof(AFTable[0]), sizeof(AFTable[0]), funccmp); + qsort(AFTable, countof(AFTable), sizeof(AFTable[0]), funccmp); funcsorted=true; } - int min = 0, max = sizeof(AFTable)/sizeof(AFTable[0])-1; + int min = 0, max = countof(AFTable)-1; while (min <= max) { diff --git a/src/thingdef.h b/src/thingdef.h index 7789c8ca0..3f54d15e8 100644 --- a/src/thingdef.h +++ b/src/thingdef.h @@ -7,4 +7,4 @@ int EvalExpressionI (int id, AActor *self); float EvalExpressionF (int id, AActor *self); bool EvalExpressionN (int id, AActor *self); -#endif \ No newline at end of file +#endif diff --git a/src/w_wad.cpp b/src/w_wad.cpp index db2b320ea..7bcfe7424 100644 --- a/src/w_wad.cpp +++ b/src/w_wad.cpp @@ -182,9 +182,9 @@ void uppercopy (char *to, const char *from) } FWadCollection::FWadCollection () -: FirstLumpIndex(NULL), NextLumpIndex(NULL), LumpInfo(NULL), Wads(NULL), +: FirstLumpIndex(NULL), NextLumpIndex(NULL), FirstLumpIndex_FullName(NULL), NextLumpIndex_FullName(NULL), - NumLumps(0), NumWads(0) + LumpInfo(NULL), Wads(NULL), NumLumps(0), NumWads(0) { } @@ -650,13 +650,13 @@ void FWadCollection::AddFile (const char *filename, const char * data, int lengt sprintf(path, "%s:", filename); char * wadstr = path+strlen(path); - for(int i=0; i < EmbeddedWADs.Size(); i++) + for(unsigned int i = 0; i < EmbeddedWADs.Size(); i++) { FZipFileInfo * zip_fh = EmbeddedWADs[i]; FZipLocalHeader localHeader; *wadstr=0; - int len = LittleShort(zip_fh->wFileNameSize); + size_t len = LittleShort(zip_fh->wFileNameSize); if (len+strlen(path) > 255) len = 255-strlen(path); strncpy(wadstr, ((char*)zip_fh) + sizeof(FZipFileInfo), len); wadstr[len]=0; @@ -1851,7 +1851,7 @@ FWadCollection::WadFileRecord::WadFileRecord (FILE *file) } FWadCollection::WadFileRecord::WadFileRecord (const char * mem, int len) -: FileReader(), Name(NULL), FirstLump(0), LastLump(0), MemoryData(mem) +: FileReader(), MemoryData(mem), Name(NULL), FirstLump(0), LastLump(0) { Length = len; FilePos = StartPos = 0; diff --git a/src/w_zip.h b/src/w_zip.h index 647e7e8f8..ccfbe68f4 100644 --- a/src/w_zip.h +++ b/src/w_zip.h @@ -61,4 +61,4 @@ struct FZipLocalHeader // File header flags. #define ZF_ENCRYPTED 0x1 -#endif \ No newline at end of file +#endif diff --git a/src/win32/eaxedit.cpp b/src/win32/eaxedit.cpp index 5b31d588a..f27c3ef27 100644 --- a/src/win32/eaxedit.cpp +++ b/src/win32/eaxedit.cpp @@ -454,7 +454,7 @@ void SetupEnvControls (HWND hDlg) { size_t i; - for (i = 0; i < sizeof(EnvControls)/sizeof(EnvControls[0]); ++i) + for (i = 0; i < countof(EnvControls); ++i) { if (EnvControls[i].EditControl == 0) continue; @@ -469,7 +469,7 @@ void SetupEnvControls (HWND hDlg) SetWindowLongPtr (EnvControls[i].EditHWND, GWLP_USERDATA, (LONG_PTR)&EnvControls[i]); SetWindowLongPtr (EnvControls[i].SliderHWND, GWLP_USERDATA, (LONG_PTR)&EnvControls[i]); } - for (i = 0; i < sizeof(EnvFlags)/sizeof(EnvFlags[0]); ++i) + for (i = 0; i < countof(EnvFlags); ++i) { EnvFlags[i].CheckboxHWND = GetDlgItem (hDlg, EnvFlags[i].CheckboxControl); SetWindowLongPtr (EnvFlags[i].CheckboxHWND, GWLP_USERDATA, (LONG_PTR)&EnvFlags[i]); @@ -517,7 +517,7 @@ void UpdateControls (ReverbContainer *env, HWND hDlg) CurrentEnv = NULL; - for (i = 0; i < sizeof(EnvControls)/sizeof(EnvControls[0]); ++i) + for (i = 0; i < countof(EnvControls); ++i) { EnvControl *ctrl = &EnvControls[i]; @@ -533,7 +533,7 @@ void UpdateControls (ReverbContainer *env, HWND hDlg) EnableWindow (ctrl->EditHWND, !env->Builtin); EnableWindow (ctrl->SliderHWND, !env->Builtin); } - for (i = 0; i < sizeof(EnvFlags)/sizeof(EnvFlags[0]); ++i) + for (i = 0; i < countof(EnvFlags); ++i) { SendMessage (EnvFlags[i].CheckboxHWND, BM_SETCHECK, (env->Properties.Flags & EnvFlags[i].Flag) ? BST_CHECKED : BST_UNCHECKED, 0); @@ -631,7 +631,7 @@ INT_PTR CALLBACK EAXProp (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) case WM_COMMAND: if (HIWORD(wParam) == BN_CLICKED && CurrentEnv != NULL) { - for (size_t i = 0; i < sizeof(EnvFlags)/sizeof(EnvFlags[0]); ++i) + for (size_t i = 0; i < countof(EnvFlags); ++i) { if ((HWND)lParam == EnvFlags[i].CheckboxHWND) { @@ -1052,7 +1052,7 @@ retry: base = NULL; } fprintf (f, "\"%s\" %u %u\n{\n", env->Name, HIBYTE(env->ID), LOBYTE(env->ID)); - for (j = 0; j < sizeof(EnvControls)/sizeof(EnvControls[0]); ++j) + for (j = 0; j < countof(EnvControls); ++j) { const EnvControl *ctl = &EnvControls[j]; if (ctl->Name && @@ -1074,7 +1074,7 @@ retry: } } } - for (j = 0; j < sizeof(EnvFlags)/sizeof(EnvFlags[0]); ++j) + for (j = 0; j < countof(EnvFlags); ++j) { if (EnvFlags[j].Flag & (env->Properties.Flags ^ base->Properties.Flags)) { diff --git a/src/win32/i_input.cpp b/src/win32/i_input.cpp index 7ee2f4d1e..f562dcc38 100644 --- a/src/win32/i_input.cpp +++ b/src/win32/i_input.cpp @@ -1058,7 +1058,7 @@ void LoadJoystickConfig () { if (SetJoystickSection (false)) { - for (size_t i = 0; i < sizeof(JoyConfigVars)/sizeof(JoyConfigVars[0]); ++i) + for (size_t i = 0; i < countof(JoyConfigVars); ++i) { const char *val = GameConfig->GetValueForKey (JoyConfigVars[i]->GetName()); UCVarValue cval; @@ -1077,7 +1077,7 @@ void SaveJoystickConfig () if (SetJoystickSection (true)) { GameConfig->ClearCurrentSection (); - for (size_t i = 0; i < sizeof(JoyConfigVars)/sizeof(JoyConfigVars[0]); ++i) + for (size_t i = 0; i < countof(JoyConfigVars); ++i) { UCVarValue cval = JoyConfigVars[i]->GetGenericRep (CVAR_String); GameConfig->SetValueForKey (JoyConfigVars[i]->GetName(), cval.String); diff --git a/wadsrc/sndseq.txt b/wadsrc/sndseq.txt index 0438e94b3..38c0dcc55 100644 --- a/wadsrc/sndseq.txt +++ b/wadsrc/sndseq.txt @@ -20,6 +20,13 @@ end nostopcutoff end +[DoorNormal + 0 DoorOpenNormal + 1 DoorCloseNormal + 2 DoorOpenBlazing + 3 DoorCloseBlazing +] + // Heretic Doors ------------------------------ :HereticDoorOpen @@ -32,6 +39,13 @@ end stopsound doors/dr1_clos end +[HereticDoor + 0 HereticDoorOpen + 1 HereticDoorClose + 2 HereticDoorOpen + 3 HereticDoorClose +] + // Strife Doors ------------------------------- :DoorOpenStone @@ -104,10 +118,59 @@ end nostopcutoff end + +[DoorStone + 0 DoorOpenStone + 1 DoorCloseStone + 2 DoorOpenBlazing + 3 DoorCloseBlazing +] + +[DoorLargeMetal + 0 DoorOpenLargeMetal + 1 DoorCloseLargeMetal + 2 DoorOpenBlazing + 3 DoorCloseBlazing +] + +[DoorSmallMetal + 0 DoorOpenSmallMetal + 1 DoorCloseSmallMetal + 2 DoorOpenBlazing + 3 DoorCloseBlazing +] + +[DoorLargeWood + 0 DoorOpenLargeWood + 1 DoorCloseLargeWood + 2 DoorOpenBlazing + 3 DoorCloseBlazing +] + +[DoorSmallWood + 0 DoorOpenSmallWood + 1 DoorCloseSmallWood + 2 DoorOpenBlazing + 3 DoorCloseBlazing +] + +[DoorAirlock + 0 DoorOpenAirlock + 1 DoorCloseAirlock + 2 DoorOpenBlazing + 3 DoorCloseBlazing +] + +[DoorChain + 0 DoorOpenChain + 1 DoorCloseChain + 2 DoorOpenBlazing + 3 DoorCloseBlazing +] + // Not Doors ---------------------------------- :CeilingNormal -// playloop plats/pt1_mid 8 playrepeat plats/pt1_mid end @@ -116,16 +179,161 @@ end end :Floor -// playloop plats/pt1_mid 8 playrepeat plats/pt1_mid stopsound plats/pt1_stop end :Platform playuntildone plats/pt1_strt -// playloop plats/pt1_mid 8 stopsound plats/pt1_stop end :Silence end + +// Heretic Ambience --------------------------- + +:HereticAmbience + // Heretic waits 10 seconds after level load before it starts + // playing any sounds. + delayonce 350 + + volumerand 0 50 + attenuation none + randomsequence + delayrand 210 465 + restart +end + +// To be 100% correct, these sequences shouldn't actually wait for +// the last sound to stop playing, but I thought it would be nice +// to make them stand-alone so you don't always have to play them +// from inside HereticAmbience. + +:AFX_Scream + environment 0 + slot HereticAmbience + + playuntildone world/amb1 +end + +:AFX_Squish + environment 1 + slot HereticAmbience + + playuntildone world/amb2 +end + +:AFX_Drops + environment 2 + slot HereticAmbience + + play world/amb3 + delayrand 16 47 + play world/amb7 + delayrand 16 47 + play world/amb3 + delayrand 16 47 + play world/amb7 + delayrand 16 47 + play world/amb3 + delayrand 16 47 + play world/amb7 + delayrand 16 47 +end + +:AFX_SlowFootsteps + environment 3 + slot HereticAmbience + + playtime world/amb4 15 + volumerel -2.36 + playtime world/amb11 15 + volumerel -2.36 + playtime world/amb4 15 + volumerel -2.36 + playtime world/amb11 15 + volumerel -2.36 + playtime world/amb4 15 + volumerel -2.36 + playtime world/amb11 15 + volumerel -2.36 + playtime world/amb4 15 + volumerel -2.36 + playuntildone world/amb11 +end + +:AFX_Heartbeat + environment 4 + slot HereticAmbience + + playtime world/amb5 35 + playtime world/amb5 35 + playtime world/amb5 35 + playuntildone world/amb5 +end + +:AFX_Bells + environment 5 + slot HereticAmbience + + playtime world/amb6 17 + volumerel -6.3 + playtime world/amb6 17 + volumerel -6.3 + playtime world/amb6 17 + volumerel -6.3 + playuntildone world/amb6 +end + +:AFX_Growl + environment 6 + slot HereticAmbience + + playuntildone world/amb12 +end + +:AFX_Magic + environment 7 + slot HereticAmbience + + playuntildone world/amb8 +end + +:AFX_Laughter + environment 8 + slot HereticAmbience + + playtime world/amb9 16 + volumerel -3.15 + playtime world/amb9 16 + volumerel -3.15 + playtime world/amb9 16 + volumerel -3.15 + playtime world/amb10 16 + volumerel -3.15 + playtime world/amb10 16 + volumerel -3.15 + playuntildone world/amb10 +end + +:AFX_FastFootsteps + environment 9 + slot HereticAmbience + + playtime world/amb4 8 + volumerel -2.36 + playtime world/amb11 8 + volumerel -2.36 + playtime world/amb4 8 + volumerel -2.36 + playtime world/amb11 8 + volumerel -2.36 + playtime world/amb4 8 + volumerel -2.36 + playtime world/amb11 8 + volumerel -2.36 + playtime world/amb4 8 + volumerel -2.36 + playuntildone world/amb11 +end diff --git a/zdoom.sln b/zdoom.sln index d523a0494..f785d407a 100644 --- a/zdoom.sln +++ b/zdoom.sln @@ -1,6 +1,7 @@ Microsoft Visual Studio Solution File, Format Version 8.00 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = " zdoom", "zdoom.vcproj", "{8049475B-5C87-46F9-9358-635218A4EF18}" ProjectSection(ProjectDependencies) = postProject + {1D179D4B-F008-431B-8C72-111F8372584F} = {1D179D4B-F008-431B-8C72-111F8372584F} {F9D9E7D4-E1A2-4866-9E85-B1B14137EE63} = {F9D9E7D4-E1A2-4866-9E85-B1B14137EE63} {873F2EEA-24DF-454C-B245-CB9738BA993E} = {873F2EEA-24DF-454C-B245-CB9738BA993E} EndProjectSection diff --git a/zdoom.vcproj b/zdoom.vcproj index d403d8066..97de4b450 100644 --- a/zdoom.vcproj +++ b/zdoom.vcproj @@ -1987,6 +1987,9 @@ + + @@ -2687,6 +2690,9 @@ + + - - - - - - - -