From 7e7ab6b4ec46eb7baaa18f4ec5cfd6574957b83b Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 21 Apr 2006 01:22:55 +0000 Subject: [PATCH] - 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. - Added a serializer for TArray. - 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. - 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. SVN r57 (trunk) --- Makefile.mingw | 3 +- default.cbd | 4 +- docs/rh-log.txt | 52 ++ src/bbannouncer.cpp | 6 +- src/c_dispatch.cpp | 2 +- src/c_expr.cpp | 2 +- src/d_dehacked.cpp | 10 +- src/d_main.cpp | 2 +- src/d_netinfo.cpp | 4 +- src/dobject.cpp | 20 + src/doomtype.h | 5 + src/empty.cpp | 2 +- src/farchive.cpp | 15 + src/farchive.h | 28 +- src/g_game.cpp | 10 +- src/g_heretic/a_dsparil.cpp | 4 +- src/g_heretic/a_hereticambience.cpp | 393 -------------- src/g_hexen/a_centaur.cpp | 2 +- src/g_hexen/a_serpent.cpp | 2 +- src/infomacros.h | 2 +- src/m_menu.cpp | 18 +- src/m_options.cpp | 30 +- src/m_random.cpp | 24 +- src/m_random.h | 3 +- src/name.cpp | 24 +- src/name.h | 4 +- src/namedef.h | 113 ++++ src/p_acs.cpp | 24 +- src/p_ceiling.cpp | 8 +- src/p_doors.cpp | 122 ++--- src/p_floor.cpp | 4 +- src/p_pillar.cpp | 4 +- src/p_plats.cpp | 8 +- src/p_saveg.cpp | 213 +++++++- src/p_user.cpp | 34 +- src/po_man.cpp | 22 +- src/r_data.cpp | 8 +- src/r_polymost.cpp | 4 +- src/s_environment.cpp | 2 +- src/s_sndseq.cpp | 787 +++++++++++++++++++--------- src/s_sndseq.h | 73 ++- src/st_stuff.cpp | 10 +- src/thingdef.cpp | 6 +- src/thingdef.h | 2 +- src/w_wad.cpp | 10 +- src/w_zip.h | 2 +- src/win32/eaxedit.cpp | 14 +- src/win32/i_input.cpp | 4 +- wadsrc/sndseq.txt | 214 +++++++- zdoom.sln | 1 + zdoom.vcproj | 21 +- 51 files changed, 1431 insertions(+), 950 deletions(-) delete mode 100644 src/g_heretic/a_hereticambience.cpp create mode 100644 src/namedef.h 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 @@ + + - - - - - - - -