- 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.
    <http://blogs.msdn.com/the1/articles/210011.aspx>
- 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)
This commit is contained in:
Randy Heit 2006-04-21 01:22:55 +00:00
parent 66c663e9d8
commit 7e7ab6b4ec
51 changed files with 1431 additions and 950 deletions

View file

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

View file

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

View file

@ -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.
<http://blogs.msdn.com/the1/articles/210011.aspx>
- 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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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<AActor *>(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 ()

View file

@ -180,4 +180,9 @@ struct PalEntry
#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h
#endif
template <typename T, size_t N>
char ( &_ArraySizeHelper( T (&array)[N] ))[N];
#define countof( array ) (sizeof( _ArraySizeHelper( array ) ))
#endif

View file

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

View file

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

View file

@ -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<class T>
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<class T>
inline FArchive &operator<< (FArchive &arc, TArray<T> &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__

View file

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

View file

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

View file

@ -1,393 +0,0 @@
#include <stddef.h>
#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<ptrdiff_t *> 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<AScriptedAmbientMaster> locater;
master = locater.Next ();
if (master == NULL)
master = Spawn<AScriptedAmbientMaster> (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);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -6,7 +6,9 @@
enum ENamedName
{
NAME_None
#define xx(n) NAME_##n,
#include "namedef.h"
#undef xx
};
class name

113
src/namedef.h Normal file
View file

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

View file

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

View file

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

View file

@ -205,47 +205,41 @@ 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
{
const char *snd;
switch (gameinfo.gametype)
{
default:
break;
case GAME_Hexen:
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.
@ -258,41 +252,37 @@ void DDoor::DoorSound (bool raise) const
continue;
texname = TexMan[sides[line->sidenum[0]].toptexture]->Name;
if (strncmp (texname, "DOR", 3) == 0)
if (texname[0] == 'D' && texname[1] == 'O' && texname[2] == 'R')
{
switch (texname[3])
{
case 'S':
snd = raise ? "DoorOpenStone" : "DoorCloseStone";
snd = "DoorStone";
break;
case 'M':
if (texname[4] == 'L')
{
snd = raise ? "DoorOpenLargeMetal" : "DoorCloseLargeMetal";
snd = "DoorLargeMetal";
}
break;
case 'W':
if (texname[4] == 'L')
{
snd = raise ? "DoorOpenLargeWood" : "DoorCloseLargeWood";
snd = "DoorLargeWood";
}
else
{
snd = raise ? "DoorOpenSmallWood" : "DoorCloseSmallWood";
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);
}
}

View file

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

View file

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

View file

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

View file

@ -46,23 +46,230 @@
#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])
{
++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]);
}
}
}
//

View file

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

View file

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

View file

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

View file

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

View file

@ -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] =
{

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1987,6 +1987,9 @@
<File
RelativePath=".\src\name.h">
</File>
<File
RelativePath=".\src\namedef.h">
</File>
<File
RelativePath=".\src\nodebuild.h">
</File>
@ -2687,6 +2690,9 @@
<File
RelativePath="src\g_shared\a_soundenvironment.cpp">
</File>
<File
RelativePath=".\src\g_shared\a_soundsequence.cpp">
</File>
<File
RelativePath=".\src\g_shared\a_spark.cpp">
<FileConfiguration
@ -3329,21 +3335,6 @@
AdditionalOptions="&quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; "/>
</FileConfiguration>
</File>
<File
RelativePath=".\src\g_heretic\a_hereticambience.cpp">
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="&quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; "/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="&quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; "/>
</FileConfiguration>
</File>
<File
RelativePath=".\src\g_heretic\a_hereticarmor.cpp">
<FileConfiguration