SVN r27 (trunk)

This commit is contained in:
Christoph Oelckers 2006-04-11 16:27:41 +00:00
parent e06ba32525
commit 25f90d6221
74 changed files with 1133 additions and 235 deletions

View file

@ -1,4 +1,98 @@
April 11, 2006 (Changes by Graf Zahl)
- Fixed: Strife's dialogs don't give weapons to the player he already has.
- Fixed: The INDIANA cheat in Hexen gives 25 of each item, not just 1.
- Fixed: The stair builder's compatibility mode must do a linear search
for sectors. Searching the hasch chain doesn't work here.
- Fixed: Any monster with a TakeSpecialDamage method should call the
super class's method instead of simply returning the damage amount.
- Fixed: Hexen's mash monsters cannot be frozen. No matter how you kill
them they just vanish. This means they need the NOICEDEATH flag.
- Fixed: Morphing a monster must also copy its translucency settings.
- Fixed: The first Macil must react to weapon fire, even though he
doesn't get hurt by it.
- Fixed: Anything with a raise state needs the MF_CORPSE flag when dying
because otherwise it can't be revived.
- Fixed: Player names in Heretic, Hexen nand Strife could only be 13
characters because the input routine did an unnecessary font size check.
- Added: After saving the game the savegame should be checked
and in case of an error an appropriate message be output.
- Fixed: The pig player had an initial health of 100, not 30.
- Fixed: Morphing a player removes the armor after transferring the
inventory to the morphed version - but it tried to remove it from the
unmorphed player instead.
- Fixed: Heretic uses Backspace to activate the Tome of Power by default.
- Fixed: 'Use all' should not try to use puzzle items.
- Made FileReader's methods virtual. Right now this isn't important
but when ZIP support will be added it is needed. Also added a
MemoryReader class that derives from FileReader.
- Added a pointer check to DI_Acquire and DI_Unacquire. GZDoom definitely
had problems with that so it might be a good idea to always check these
pointers.
- Added an engine signature to the savegame. The inability to distinguish
between ZDoom and GZDoom savegames constantly forced me to use some ugly
tricks which broke the versioning system. This may also be useful for
other derivates that have to save additional data in a savegame.
- Due to the savegame version bump I removed all compatibility code.
- I had to bump the minimum savegame version because I got some strange
effects with old savegames. On the positive side, this allows me to
do a few more radical changes to the savegame code. ;)
- Fixed: CanvasTextures weren't saved in a savegame.
- Fixed: Multiple warp commands for the same texture were cumulative.
- Changed FPatchTexture::MakeTexture and FIMGZTexture::MakeTexture so they
don't re-initialize the texture's size information repeatedly. This can
cause problems if code was added that manipulates these values after loading
the textures.
- Changed FPatchTexture::GetDimensions to use ReopenLumpNum instead of
OpenLumpNum. Once ZIP handling is added the current code won't work anymore
without adding a highly expensive copy operator to FWadLump.
- Added Transfer_WallLight special. This is similar to Transfer_Floor/Ceilinglight
but affects walls instead.
- Fixed: P_TestActivateLine must check whether a valid actor is trying
to activate the line.
- Added a check for MF2_NOTELEPORT to the special activation check for
Booms generic triggers. This excludes most items from activating these
lines that are not supposed to do that.
- Added a sv_dropstyle CVAR so that the way items are dropped is no longer
dependent on the game being played.
- Added MF4_FRIGHTENED flag from .96x.
- Added a CVAR that disables the automap background graphic in Heretic
and Hexen.
- Added more color options to the automap, including the option to show
secrets.
- Added menu option for the monster movement interpolation CVAR.
- Fixed: Strife's grenades don't make bouncing sounds.
- Fixed: Strife's grenades lose 50% of their momentum when bouncing,
not 30% like in Hexen.
- Fixed: HexenHack must be reset for each MAPINFO lump being parsed.
- Turned monster falling damage into a level flag so that it can be
used in all games, not just Hexen.
- Added the map's lump name to the savegame information. This is useful
for those who remember maps by their lump name and not the description.
- Added a total game time counter and made the total time display on
the intermission screen operrable. Also added an optional total time
display for the automap.
- Added support for full hub intermission statistics. To make this work
properly level.time is now being reset after changing hubs.
- Added GZDoom's local SNDINFO/SNDSEQ code. This was supposed to be in
.96x but that was cancelled before I had the chance.
- Made DCanvas::FlatFill virtual so it can be overridden by other
types of canvases (e.g. OpenGL.)
- Fixed: CR_UNTRANSLATED was uninitialized for FON2 fonts
- Fixed: Hexen uses a view height of 48, not 41.
- Changed: Multiplayer weapons will be spawned in coop games now
unless the player explicitly disables this. There are many WADs
out there that need the additional weapons in coop games.
- Added code that remaps MF_NOSECTOR to RF_INVISIBLE for all items
touched by Dehacked and for ABossEye. MF_NOSECTOR makes any
item completely deaf so it is very dangerous to use with monsters
or other things that depend on their sound target.
- Fixed: The Dehacked code cleared one of the translation flags.
- Fixed: The dehacked parser must set EnglishStrings to NULL after
freeing the memory.
- Copied a fix for restoring the weapon slots from 2.1.0.
- Fixed: APathFollower::Interpolate needs some NULL pointer checks.
- Added MF2_NOTELEPORT to ABlood and AIceChunk. Teleporting blood can
seriously mess up one-time teleporters - plus it looks just weird.
- Fixed: It was possible to use things through closed walls when the wall
was further away than 64 map units.
- Added a check for MF3_BLOODLESSIMPACT to P_LineAttack so that bloodless

View file

@ -270,6 +270,8 @@ enum
MF4_ALLOWPARTICLES = 0x08000000, // this puff type can be replaced by particles
MF4_NOEXTREMEDEATH = 0x10000000, // this projectile or weapon never gibs its victim
MF4_EXTREMEDEATH = 0x20000000, // this projectile or weapon always gibs its victim
MF4_FRIGHTENED = 0x40000000, // Monster runs away from player
MF4_NOBOUNCESOUND = 0x80000000, // Strife's grenades don't make a bouncing sound.
// --- mobj.renderflags ---
@ -633,6 +635,7 @@ public:
BYTE MinMissileChance;// [RH] If a random # is > than this, then missile attack.
WORD SpawnFlags;
fixed_t meleerange;
fixed_t bouncefactor; // Strife's grenades use 50%, Hexen's Flechettes 70.
// a linked list of sectors where this object appears
struct msecnode_s *touching_sectorlist; // phares 3/14/98

View file

@ -53,11 +53,13 @@
static int Background, YourColor, WallColor, TSWallColor,
FDWallColor, CDWallColor, ThingColor,
ThingColor_Item, ThingColor_Monster, ThingColor_Friend,
SecretWallColor, GridColor, XHairColor,
NotSeenColor,
LockedColor,
AlmostBackground,
IntraTeleportColor, InterTeleportColor;
IntraTeleportColor, InterTeleportColor,
SecretSectorColor;
static int DoomColors[11];
static byte DoomPaletteVals[11*3] =
@ -100,6 +102,7 @@ CVAR (Bool, am_showsecrets, true, CVAR_ARCHIVE);
CVAR (Bool, am_showmonsters, true, CVAR_ARCHIVE);
CVAR (Bool, am_showitems, false, CVAR_ARCHIVE);
CVAR (Bool, am_showtime, true, CVAR_ARCHIVE);
CVAR (Bool, am_showtotaltime, false, CVAR_ARCHIVE);
CVAR (Bool, am_usecustomcolors, true, CVAR_ARCHIVE);
CVAR (Float, am_ovtrans, 1.f, CVAR_ARCHIVE);
CVAR (Color, am_backcolor, 0x6c5440, CVAR_ARCHIVE);
@ -122,6 +125,15 @@ CVAR (Color, am_ovunseencolor, 0x00226e, CVAR_ARCHIVE);
CVAR (Color, am_ovtelecolor, 0xffff00, CVAR_ARCHIVE);
CVAR (Color, am_intralevelcolor, 0x0000ff, CVAR_ARCHIVE);
CVAR (Color, am_interlevelcolor, 0xff0000, CVAR_ARCHIVE);
CVAR (Color, am_secretsectorcolor, 0xff00ff, CVAR_ARCHIVE);
CVAR (Int, am_map_secrets, 1, CVAR_ARCHIVE);
CVAR (Bool, am_drawmapback, true, CVAR_ARCHIVE);
CVAR (Color, am_thingcolor_friend, 0xfcfcfc, CVAR_ARCHIVE);
CVAR (Color, am_thingcolor_monster, 0xfcfcfc, CVAR_ARCHIVE);
CVAR (Color, am_thingcolor_item, 0xfcfcfc, CVAR_ARCHIVE);
CVAR (Color, am_ovthingcolor_friend, 0xe88800, CVAR_ARCHIVE);
CVAR (Color, am_ovthingcolor_monster, 0xe88800, CVAR_ARCHIVE);
CVAR (Color, am_ovthingcolor_item, 0xe88800, CVAR_ARCHIVE);
// drawing stuff
#define AM_PANDOWNKEY KEY_DOWNARROW
@ -370,6 +382,11 @@ void AM_getIslope (mline_t *ml, islope_t *is)
}
*/
void AM_GetPosition(fixed_t & x, fixed_t & y)
{
x = (m_x + m_w/2) << FRACTOMAPBITS;
y = (m_y + m_h/2) << FRACTOMAPBITS;
}
//
//
//
@ -635,7 +652,10 @@ static void AM_initColors (BOOL overlayed)
if (overlayed)
{
YourColor = am_ovyourcolor.GetIndex ();
SecretWallColor = WallColor = am_ovwallcolor.GetIndex ();
SecretSectorColor = SecretWallColor = WallColor = am_ovwallcolor.GetIndex ();
ThingColor_Item = am_ovthingcolor_item.GetIndex();
ThingColor_Friend = am_ovthingcolor_friend.GetIndex();
ThingColor_Monster = am_ovthingcolor_monster.GetIndex();
ThingColor = am_ovthingcolor.GetIndex ();
FDWallColor = CDWallColor = LockedColor = am_ovotherwallscolor.GetIndex ();
NotSeenColor = TSWallColor = am_ovunseencolor.GetIndex ();
@ -651,6 +671,9 @@ static void AM_initColors (BOOL overlayed)
TSWallColor = am_tswallcolor.GetIndex ();
FDWallColor = am_fdwallcolor.GetIndex ();
CDWallColor = am_cdwallcolor.GetIndex ();
ThingColor_Item = am_thingcolor_item.GetIndex();
ThingColor_Friend = am_thingcolor_friend.GetIndex();
ThingColor_Monster = am_thingcolor_monster.GetIndex();
ThingColor = am_thingcolor.GetIndex ();
GridColor = am_gridcolor.GetIndex ();
XHairColor = am_xhaircolor.GetIndex ();
@ -658,6 +681,7 @@ static void AM_initColors (BOOL overlayed)
LockedColor = am_lockedcolor.GetIndex ();
InterTeleportColor = am_interlevelcolor.GetIndex ();
IntraTeleportColor = am_intralevelcolor.GetIndex ();
SecretSectorColor = am_secretsectorcolor.GetIndex ();
DWORD ba = am_backcolor;
@ -679,13 +703,17 @@ static void AM_initColors (BOOL overlayed)
Background = DoomColors[0];
YourColor = DoomColors[1];
AlmostBackground = DoomColors[2];
SecretWallColor =
SecretSectorColor =
SecretWallColor =
WallColor = DoomColors[3];
TSWallColor = DoomColors[4];
FDWallColor = DoomColors[5];
LockedColor =
CDWallColor = DoomColors[6];
ThingColor = DoomColors[7];
ThingColor_Item =
ThingColor_Friend =
ThingColor_Monster =
ThingColor = DoomColors[7];
GridColor = DoomColors[8];
XHairColor = DoomColors[9];
NotSeenColor = DoomColors[10];
@ -1079,7 +1107,7 @@ void AM_Ticker ()
//
void AM_clearFB (int color)
{
if (mapback == NULL)
if (mapback == NULL || !am_drawmapback)
{
screen->Clear (0, 0, f_w, f_h, color);
}
@ -1798,9 +1826,19 @@ void AM_drawWalls (bool allmap)
{
if ((lines[i].flags & ML_DONTDRAW) && am_cheat == 0)
continue;
if (!lines[i].backsector)
{
AM_drawMline(&l, WallColor);
if (lines[i].frontsector->oldspecial &&
(am_map_secrets==2 || (am_map_secrets==1 && !(lines[i].frontsector->special&SECRET_MASK))))
{
// map secret sectors like Boom
AM_drawMline(&l, SecretSectorColor);
}
else
{
AM_drawMline(&l, WallColor);
}
}
else
{
@ -1828,9 +1866,30 @@ void AM_drawWalls (bool allmap)
AM_drawMline(&l, WallColor);
}
else if (lines[i].special == Door_LockedRaise ||
lines[i].special == ACS_LockedExecute)
lines[i].special == ACS_LockedExecute ||
(lines[i].special == Generic_Door && lines[i].args[4]!=0))
{
AM_drawMline (&l, LockedColor); // locked special
if (am_usecustomcolors)
{
int P_GetMapColorForLock(int lock);
int lock;
if (lines[i].special==Door_LockedRaise) lock=lines[i].args[3];
else lock=lines[i].args[4];
int color = P_GetMapColorForLock(lock);
if (color > 0)
{
color = ColorMatcher.Pick(RPART(color), GPART(color), BPART(color));
}
else color = LockedColor;
AM_drawMline (&l, color);
}
else
AM_drawMline (&l, LockedColor); // locked special
}
else if (lines[i].backsector->floorplane
!= lines[i].frontsector->floorplane)
@ -2001,8 +2060,9 @@ void AM_drawPlayers ()
}
}
void AM_drawThings (int color)
void AM_drawThings (int _color)
{
int color;
int i;
AActor* t;
mpoint_t p;
@ -2023,6 +2083,16 @@ void AM_drawThings (int color)
angle += ANG90 - players[consoleplayer].camera->angle;
}
color = ThingColor;
// use separate colors for special thing types
if (t->flags3&MF3_ISMONSTER && !(t->flags&MF_CORPSE))
{
if (t->flags & MF_FRIENDLY || !(t->flags & MF_COUNTKILL)) color = ThingColor_Friend;
else color = ThingColor_Monster;
}
else if (t->flags&MF_SPECIAL) color = ThingColor_Item;
AM_drawLineCharacter
(thintriangle_guy, NUMTHINTRIANGLEGUYLINES,
16<<MAPBITS, angle, color, p.x, p.y);

View file

@ -124,6 +124,12 @@ static const FBinding DefRavenBindings[] =
{ NULL }
};
static const FBinding DefHereticBindings[] =
{
{ "backspace", "use ArtiTomeOfPower" },
{ NULL }
};
static const FBinding DefHexenBindings[] =
{
{ "/", "+jump" },
@ -491,6 +497,11 @@ void C_BindDefaults ()
SetBinds (DefRavenBindings);
}
if (gameinfo.gametype == GAME_Heretic)
{
SetBinds (DefHereticBindings);
}
if (gameinfo.gametype == GAME_Hexen)
{
SetBinds (DefHexenBindings);

View file

@ -62,6 +62,7 @@
#include "decallib.h"
#include "r_draw.h"
#include "v_palette.h"
#include "a_sharedglobal.h"
// [SO] Just the way Randy said to do it :)
// [RH] Made this CVAR_SERVERINFO
@ -915,7 +916,7 @@ static int PatchThing (int thingy)
// Force the top 4 bits to 0 so that the user is forced
// to use the mnemonics to change them. And MF_SLIDE doesn't
// exist anymore, so 0 that too.
value[0] |= atoi(strval) & 0x07ffdfff;
value[0] |= atoi(strval) & 0x0fffdfff;
vchanged[0] = true;
}
else
@ -2289,6 +2290,7 @@ static void UnloadDehSupp ()
if (EnglishStrings != NULL)
{
delete EnglishStrings;
EnglishStrings = NULL;
}
}
}
@ -2531,6 +2533,43 @@ void FinishDehPatch ()
}
}
void HandleNoSector()
{
// MF_NOSECTOR is causing problems with monsters so remap it to RF_INVISIBLE
// which in most cases is what this is used for anyway.
// Do this for all actors touched by DEHACKED actors except the teleport spot.
unsigned int touchedIndex;
for (touchedIndex = 0; touchedIndex < TouchedActors.Size(); ++touchedIndex)
{
TypeInfo *ti = TouchedActors[touchedIndex];
if (ti!=NULL && ti->ActorInfo!=NULL && !ti->IsDescendantOf(RUNTIME_CLASS(ATeleportDest)))
{
AActor * def = GetDefaultByType(ti);
if (def->flags&MF_NOSECTOR)
{
def->flags&=~MF_NOSECTOR;
def->renderflags|=RF_INVISIBLE;
}
}
}
// The BossEye must be handled even without any Dehacked interference
// because otherwise it would not react to sound.
const TypeInfo * ti = TypeInfo::FindType("BossEye");
if (ti!=NULL)
{
AActor * def = GetDefaultByType(ti);
if (def->flags&MF_NOSECTOR)
{
def->flags&=~MF_NOSECTOR;
def->renderflags|=RF_INVISIBLE;
}
}
}
void A_SpawnDehackedPickup (AActor *actor)
{
if ((size_t)actor->health < DehackedPickups.Size())

View file

@ -36,5 +36,6 @@
void DoDehPatch (const char *patchfile, BOOL autoloading);
void FinishDehPatch ();
void HandleNoSector();
#endif //__D_DEHACK_H__

View file

@ -355,6 +355,7 @@ CVAR (Flag, sv_nojump, dmflags, DF_NO_JUMP);
CVAR (Flag, sv_nofreelook, dmflags, DF_NO_FREELOOK);
CVAR (Flag, sv_respawnsuper, dmflags, DF_RESPAWN_SUPER);
CVAR (Flag, sv_nofov, dmflags, DF_NO_FOV);
CVAR (Flag, sv_noweaponspawn, dmflags, DF_NO_COOP_WEAPON_SPAWN);
//==========================================================================
//
@ -2048,6 +2049,7 @@ void D_DoomMain (void)
DoDehPatch (NULL, true); // See if there's a patch in a PWAD
FinishDehPatch (); // Create replacements for dehacked pickups
}
HandleNoSector (); // clear NOSECTOR flag off all actors modified by Dehacked and the BossEye.
FActorInfo::StaticSetActorNums ();

View file

@ -2060,7 +2060,7 @@ void Net_DoCommand (int type, byte **stream, int player)
while (item != NULL)
{
AInventory *next = item->Inventory;
if (item->ItemFlags & IF_INVBAR)
if (item->ItemFlags & IF_INVBAR && !(item->IsKindOf(RUNTIME_CLASS(APuzzleItem))))
{
players[player].mo->UseInventory (item);
}

View file

@ -170,6 +170,7 @@ public:
float FOV; // current field of vision
fixed_t viewz; // focal origin above r.z
fixed_t viewheight; // base height above floor for viewz
fixed_t defaultviewheight; // The normal view height when standing
fixed_t deltaviewheight; // squat speed.
fixed_t bob; // bounded/scaled total momentum
@ -275,6 +276,12 @@ public:
float BlendA;
char *LogText; // [RH] Log for Strife
fixed_t GetDeltaViewHeight() const
{
return (defaultviewheight - viewheight) >> 3;
}
};
typedef player_s player_t;

View file

@ -219,6 +219,7 @@ enum
DF_NO_FREELOOK = 1 << 17, // Don't allow freelook
DF_RESPAWN_SUPER = 1 << 18, // Respawn invulnerability and invisibility
DF_NO_FOV = 1 << 19, // Only let the arbitrator set FOV (for all players)
DF_NO_COOP_WEAPON_SPAWN = 1 << 20, // Don't spawn multiplayer weapons in coop games
};
// [BC] More dmflags. w00p!
@ -260,7 +261,7 @@ enum
COMPATF_NOTOSSDROPS = 1 << 7, // Spawn dropped items directly on the floor?
COMPATF_USEBLOCKING = 1 << 8, // Any special line can block a use line
COMPATF_NODOORLIGHT = 1 << 9, // Don't do the BOOM local door light effect
COMPATF_RAVENSCROLL = 1 << 10, // Raven's scrollers user their original carrying speed
COMPATF_RAVENSCROLL = 1 << 10, // Raven's scrollers use their original carrying speed
};
// phares 3/20/98:

View file

@ -1,5 +1,6 @@
#include "files.h"
#include "i_system.h"
#include "templates.h"
FileReader::FileReader ()
: File(NULL), Length(0), CloseOnDestruct(false)
@ -100,7 +101,7 @@ long FileReader::CalcFileLen() const
// Now for the zlib wrapper -------------------------------------------------
FileReaderZ::FileReaderZ (FileReader &file)
FileReaderZ::FileReaderZ (FileReader &file, bool zip)
: File(file), SawEOF(false)
{
int err;
@ -110,7 +111,9 @@ FileReaderZ::FileReaderZ (FileReader &file)
Stream.zalloc = Z_NULL;
Stream.zfree = Z_NULL;
err = inflateInit (&Stream);
if (!zip) err = inflateInit (&Stream);
else err = inflateInit2 (&Stream, -MAX_WBITS);
if (err != Z_OK)
{
I_Error ("FileReaderZ: inflateInit failed: %d\n", err);
@ -162,3 +165,45 @@ void FileReaderZ::FillBuffer ()
Stream.next_in = InBuff;
Stream.avail_in = numread;
}
MemoryReader::MemoryReader (const char *buffer, long length)
{
bufptr=buffer;
Length=length;
FilePos=0;
}
MemoryReader::~MemoryReader ()
{
}
long MemoryReader::Tell () const
{
return FilePos;
}
long MemoryReader::Seek (long offset, int origin)
{
switch (origin)
{
case SEEK_CUR:
offset+=FilePos;
break;
case SEEK_END:
offset+=Length;
break;
}
FilePos=clamp<long>(offset,0,Length-1);
return 0;
}
long MemoryReader::Read (void *buffer, long len)
{
if (len>Length-FilePos) len=Length-FilePos;
if (len<0) len=0;
memcpy(buffer,bufptr+FilePos,len);
FilePos+=len;
return len;
}

View file

@ -12,11 +12,11 @@ public:
FileReader (const char *filename);
FileReader (FILE *file);
FileReader (FILE *file, long length);
~FileReader ();
virtual ~FileReader ();
long Tell () const;
long Seek (long offset, int origin);
long Read (void *buffer, long len);
virtual long Tell () const;
virtual long Seek (long offset, int origin);
virtual long Read (void *buffer, long len);
long GetLength () const { return Length; }
// If you use the underlying FILE without going through this class,
@ -69,6 +69,7 @@ protected:
private:
long CalcFileLen () const;
protected:
bool CloseOnDestruct;
};
@ -76,7 +77,7 @@ private:
class FileReaderZ
{
public:
FileReaderZ (FileReader &file);
FileReaderZ (FileReader &file, bool zip=false);
~FileReaderZ ();
long Read (void *buffer, long len);
@ -132,4 +133,21 @@ private:
void FillBuffer ();
};
class MemoryReader : public FileReader
{
public:
MemoryReader (const char *buffer, long length);
~MemoryReader ();
virtual long Tell () const;
virtual long Seek (long offset, int origin);
virtual long Read (void *buffer, long len);
protected:
const char * bufptr;
};
#endif

View file

@ -75,6 +75,9 @@
#include <zlib.h>
#include "g_hub.h"
static FRandom pr_dmspawn ("DMSpawn");
const int SAVEPICWIDTH = 216;
@ -1607,6 +1610,21 @@ void G_DoLoadGame ()
SaveVersion = 0;
// Check whether this savegame actually has been created by a compatible engine.
// Since there are ZDoom derivates using the exact same savegame format but
// with mutual incompatibilities this check simplifies things significantly.
char * engine = M_GetPNGText (png, "Engine");
if (engine == NULL || 0 != strcmp (engine, GAMESIG))
{
// 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");
delete png;
fclose (stdfile);
return;
}
if (!M_GetPNGText (png, "ZDoom Save Version", sigcheck, 16) ||
0 != strncmp (sigcheck, SAVESIG, 9) || // ZDOOMSAVE is the first 9 chars
(SaveVersion = atoi (sigcheck+9)) < MINSAVEVER)
@ -1631,6 +1649,9 @@ void G_DoLoadGame ()
return;
}
// Read intermission data for hubs
G_ReadHubInfo(png);
bglobal.RemoveAllBots (true);
text = M_GetPNGText (png, "Important CVARs");
@ -1642,7 +1663,7 @@ void G_DoLoadGame ()
}
// dearchive all the modifications
if (M_FindPNGChunk (png, MAKE_ID('p','t','I','c') == 8))
if (M_FindPNGChunk (png, MAKE_ID('p','t','I','c')) == 8)
{
DWORD time[2];
fread (&time, 8, 1, stdfile);
@ -1825,7 +1846,8 @@ static void PutSaveComment (FILE *file)
M_AppendPNGText (file, "Creation Time", comment);
// Get level name
strcpy (comment, level.level_name);
//strcpy (comment, level.level_name);
sprintf(comment, "%s - %s", level.mapname, level.level_name);
len = (WORD)strlen (comment);
comment[len] = '\n';
@ -1944,12 +1966,16 @@ void G_DoSaveGame (bool okForQuicksave)
SaveVersion = SAVEVER;
PutSavePic (stdfile, SAVEPICWIDTH, SAVEPICHEIGHT);
M_AppendPNGText (stdfile, "Software", "ZDoom " DOTVERSIONSTR);
M_AppendPNGText (stdfile, "Engine", GAMESIG);
M_AppendPNGText (stdfile, "ZDoom Save Version", SAVESIG);
M_AppendPNGText (stdfile, "Title", savedescription);
M_AppendPNGText (stdfile, "Current Map", level.mapname);
PutSaveWads (stdfile);
PutSaveComment (stdfile);
// Intermission stats for hubs
G_WriteHubInfo(stdfile);
{
byte vars[4096], *vars_p;
vars_p = vars;
@ -1986,7 +2012,21 @@ void G_DoSaveGame (bool okForQuicksave)
M_FinishPNG (stdfile);
fclose (stdfile);
Printf ("%s\n", GStrings("GGSAVED"));
// Check whether the file is ok.
bool success = false;
stdfile = fopen (savegamefile.GetChars(), "rb");
if (stdfile != NULL)
{
PNGHandle * pngh = M_VerifyPNG(stdfile);
if (pngh != NULL)
{
success=true;
delete pngh;
}
fclose(stdfile);
}
if (success) Printf ("%s\n", GStrings("GGSAVED"));
else Printf(PRINT_HIGH, "Save failed\n");
BackupSaveName = savegamefile;
savegamefile = "";

View file

@ -145,6 +145,7 @@ IMPLEMENT_STATELESS_ACTOR (ACentaurMash, Hexen, -1, 103)
PROP_FlagsSet (MF_NOBLOOD)
PROP_Flags2Set (MF2_BLASTED)
PROP_Flags2Clear (MF2_TELESTOMP)
PROP_Flags4Set(MF4_NOICEDEATH)
PROP_RenderStyle (STYLE_Translucent)
PROP_Alpha (HX_ALTSHADOW)

View file

@ -118,6 +118,7 @@ IMPLEMENT_STATELESS_ACTOR (ADemon1Mash, Hexen, -1, 100)
PROP_FlagsSet (MF_NOBLOOD)
PROP_Flags2Set (MF2_BLASTED)
PROP_Flags2Clear (MF2_TELESTOMP)
PROP_Flags4Set(MF4_NOICEDEATH)
PROP_RenderStyle (STYLE_Translucent)
PROP_Alpha (HX_ALTSHADOW)
@ -373,6 +374,7 @@ IMPLEMENT_STATELESS_ACTOR (ADemon2Mash, Hexen, -1, 101)
PROP_FlagsSet (MF_NOBLOOD)
PROP_Flags2Set (MF2_BLASTED)
PROP_Flags2Clear (MF2_TELESTOMP)
PROP_Flags4Set(MF4_NOICEDEATH)
PROP_RenderStyle (STYLE_Translucent)
PROP_Alpha (HX_ALTSHADOW)

View file

@ -144,6 +144,7 @@ class AEttinMash : public AEttin
IMPLEMENT_STATELESS_ACTOR (AEttinMash, Hexen, -1, 102)
PROP_FlagsSet (MF_NOBLOOD)
PROP_Flags2Set (MF2_FLOORCLIP|MF2_PASSMOBJ|MF2_MCROSS|MF2_PUSHWALL|MF2_BLASTED)
PROP_Flags4Set(MF4_NOICEDEATH)
PROP_RenderStyle (STYLE_Translucent)
PROP_Alpha (HX_ALTSHADOW)

View file

@ -130,7 +130,7 @@ FState APigPlayer::States[] =
};
IMPLEMENT_ACTOR (APigPlayer, Hexen, -1, 0)
PROP_SpawnHealth (100)
PROP_SpawnHealth (30)
PROP_ReactionTime (0)
PROP_PainChance (255)
PROP_RadiusFixed (16)

151
src/g_hub.cpp Normal file
View file

@ -0,0 +1,151 @@
/*
** g_hub.cpp
**
** Intermission stats for hubs
**
**---------------------------------------------------------------------------
** Copyright 2005 Christoph Oelckers
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
#include "doomstat.h"
#include "g_hub.h"
#include "tarray.h"
#include "g_level.h"
#include "g_game.h"
#include "gi.h"
#include "files.h"
#include "m_png.h"
//==========================================================================
//
// Player is leaving the current level
//
//==========================================================================
TArray<wbstartstruct_t> hubdata;
void G_LeavingHub(int mode, cluster_info_t * cluster, wbstartstruct_t * wbs)
{
unsigned int i,j;
if (cluster->flags & CLUSTER_HUB)
{
for(i=0;i<hubdata.Size();i++)
{
if (hubdata[i].finished_ep==level.levelnum)
{
hubdata[i]=*wbs;
break;
}
}
if (i==hubdata.Size())
{
hubdata.Push(*wbs);
}
hubdata[i].finished_ep=level.levelnum;
if (!multiplayer && !deathmatch)
{
// The player counters don't work in hubs!
hubdata[i].plyr[0].skills=level.killed_monsters;
hubdata[i].plyr[0].sitems=level.found_items;
hubdata[i].plyr[0].ssecret=level.found_secrets;
}
if (mode!=FINISH_SameHub)
{
wbs->maxkills=wbs->maxitems=wbs->maxsecret=0;
for(i=0;i<MAXPLAYERS;i++)
{
wbs->plyr[i].sitems=wbs->plyr[i].skills=wbs->plyr[i].ssecret=0;
}
for(i=0;i<hubdata.Size();i++)
{
wbs->maxkills += hubdata[i].maxkills;
wbs->maxitems += hubdata[i].maxitems;
wbs->maxsecret += hubdata[i].maxsecret;
for(j=0;j<MAXPLAYERS;j++)
{
wbs->plyr[j].sitems += hubdata[i].plyr[j].sitems;
wbs->plyr[j].skills += hubdata[i].plyr[j].skills;
wbs->plyr[j].ssecret += hubdata[i].plyr[j].ssecret;
}
}
if (cluster->clustername)
{
strncpy(level.level_name, cluster->clustername, 64);
level.level_name[63]=0;
}
}
}
if (mode!=FINISH_SameHub) hubdata.Clear();
}
//==========================================================================
//
// Serialize intermission info for hubs
//
//==========================================================================
#define HUBS_ID MAKE_ID('h','u','B','s')
static void G_SerializeHub(FArchive & arc)
{
int i=hubdata.Size();
arc << i;
if (i>0)
{
if (arc.IsStoring()) arc.Write(&hubdata[0], i * sizeof(wbstartstruct_t));
else
{
hubdata.Resize(i);
arc.Read(&hubdata[0], i * sizeof(wbstartstruct_t));
}
}
else hubdata.Clear();
}
void G_WriteHubInfo (FILE *file)
{
FPNGChunkArchive arc(file, HUBS_ID);
G_SerializeHub(arc);
}
void G_ReadHubInfo (PNGHandle *png)
{
int chunklen;
if ((chunklen = M_FindPNGChunk (png, HUBS_ID)) != 0)
{
FPNGChunkArchive arc (png->File->GetFile(), HUBS_ID, chunklen);
G_SerializeHub(arc);
}
}

14
src/g_hub.h Normal file
View file

@ -0,0 +1,14 @@
#ifndef __G_HUB_H
#define __G_HUB_H
#include <stdio.h>
//#include <m_png.h>
#include "g_level.h"
#include "wi_stuff.h"
void G_WriteHubInfo (FILE *file);
void G_ReadHubInfo (PNGHandle *png);
void G_LeavingHub(int mode, cluster_info_t * cluster, struct wbstartstruct_s * wbs);
#endif

View file

@ -74,6 +74,7 @@
#include "gi.h"
#include "g_hub.h"
EXTERN_CVAR (Float, sv_gravity)
EXTERN_CVAR (Float, sv_aircontrol)
@ -234,6 +235,11 @@ static const char *MapInfoMapLevel[] =
"airsupply",
"specialaction",
"keepfullinventory",
"monsterfallingdamage",
"nomonsterfallingdamage",
"sndseq",
"sndinfo",
"soundinfo",
NULL
};
@ -340,6 +346,11 @@ MapHandlers[] =
{ MITYPE_INT, lioffset(airsupply), 0 },
{ MITYPE_SPECIALACTION, lioffset(specialactions), 0 },
{ MITYPE_SETFLAG, LEVEL_KEEPFULLINVENTORY, 0 },
{ MITYPE_SETFLAG, LEVEL_MONSTERFALLINGDAMAGE, 0 },
{ MITYPE_CLRFLAG, LEVEL_MONSTERFALLINGDAMAGE, 0 },
{ MITYPE_LUMPNAME, lioffset(sndseq), 0 },
{ MITYPE_LUMPNAME, lioffset(soundinfo), 0 },
{ MITYPE_LUMPNAME, lioffset(soundinfo), 0 },
};
static const char *MapInfoClusterLevel[] =
@ -354,6 +365,7 @@ static const char *MapInfoClusterLevel[] =
"cdid",
"entertextislump",
"exittextislump",
"name",
NULL
};
@ -368,7 +380,8 @@ MapInfoHandler ClusterHandlers[] =
{ MITYPE_INT, cioffset(cdtrack), 0 },
{ MITYPE_HEX, cioffset(cdid), 0 },
{ MITYPE_SETFLAG, CLUSTER_ENTERTEXTINLUMP, 0 },
{ MITYPE_SETFLAG, CLUSTER_EXITTEXTINLUMP, 0 }
{ MITYPE_SETFLAG, CLUSTER_EXITTEXTINLUMP, 0 },
{ MITYPE_STRING, cioffset(clustername), 0 },
};
static void ParseMapInfoLower (MapInfoHandler *handlers,
@ -414,6 +427,10 @@ static void SetLevelDefaults (level_info_t *levelinfo)
// For maps without a BEHAVIOR, this will be cleared.
levelinfo->flags |= LEVEL_LAXMONSTERACTIVATION;
}
else
{
levelinfo->flags |= LEVEL_MONSTERFALLINGDAMAGE;
}
levelinfo->airsupply = 10;
}
@ -487,6 +504,7 @@ static void G_DoParseMapInfo (int lump)
SetLevelDefaults (&defaultinfo);
SC_OpenLumpNum (lump, "MAPINFO");
HexenHack=false;
while (SC_GetString ())
{
@ -1328,6 +1346,7 @@ void G_InitNew (char *mapname, bool bTitleLevel)
}
level.time = 0;
level.maptime = 0;
level.totaltime = 0;
if (!multiplayer || !deathmatch)
{
@ -1496,6 +1515,7 @@ void G_DoCompleted (void)
wminfo.partime = TICRATE * level.partime;
wminfo.sucktime = level.sucktime;
wminfo.pnum = consoleplayer;
wminfo.totaltime = level.totaltime;
for (i=0 ; i<MAXPLAYERS ; i++)
{
@ -1535,6 +1555,9 @@ void G_DoCompleted (void)
mode = FINISH_SameHub;
}
// Intermission stats for entire hubs
G_LeavingHub(mode, thiscluster, &wminfo);
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i])
@ -1559,7 +1582,9 @@ void G_DoCompleted (void)
ACS_WorldArrays[i].Clear ();
}
}
else if (mode == FINISH_NoHub)
// With hub statistics the time should be per hub.
// Additionally there is a global time counter now so nothing is missed by changing it
//else if (mode == FINISH_NoHub)
{ // Reset time to zero if not entering/staying in a hub.
level.time = 0;
}
@ -1629,9 +1654,9 @@ void G_DoLoadLevel (int position, bool autosave)
Printf (
"\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36"
"\36\36\36\36\36\36\36\36\36\36\36\36\37\n"
TEXTCOLOR_BOLD "%s\n\n",
level.level_name);
"\36\36\36\36\36\36\36\36\36\36\36\36\37\n\n"
TEXTCOLOR_BOLD "%s - %s\n\n",
level.mapname, level.level_name);
if (wipegamestate == GS_LEVEL)
wipegamestate = GS_FORCEWIPE;
@ -2268,17 +2293,16 @@ void G_SerializeLevel (FArchive &arc, bool hubLoad)
<< level.found_items
<< level.killed_monsters
<< level.gravity
<< level.aircontrol;
if (SaveVersion >= 230)
arc << level.maptime;
<< level.aircontrol
<< level.maptime
<< level.totaltime;
if (arc.IsStoring ())
{
arc.WriteName (level.skypic1);
arc.WriteName (level.skypic2);
}
else if (SaveVersion >= 225)
else
{
strncpy (level.skypic1, arc.ReadName(), 8);
strncpy (level.skypic2, arc.ReadName(), 8);
@ -2360,6 +2384,10 @@ void G_SerializeLevel (FArchive &arc, bool hubLoad)
arc << t;
}
}
// This must be saved, too, of course!
FCanvasTextureInfo::Serialize (arc);
if (!hubLoad)
{
P_SerializePlayers (arc);

View file

@ -98,6 +98,7 @@
#define LEVEL_KEEPFULLINVENTORY UCONST64(0x4000000000) // doesn't reduce the amount of inventory items to 1
#define LEVEL_MONSTERFALLINGDAMAGE UCONST64(0x10000000000)
struct acsdefered_s;
class FBehavior;
@ -150,6 +151,8 @@ struct level_info_s
char exitpic[9];
char intermusic[9];
char soundinfo[9];
char sndseq[9];
FSpecialAction * specialactions;
};
typedef struct level_info_s level_info_t;
@ -165,8 +168,9 @@ struct level_locals_s
void Tick ();
void AddScroller (DScroller *, int secnum);
int time;
int maptime;
int time; // time in the hub
int maptime; // time in the map
int totaltime; // time in the game
int starttime;
int partime;
int sucktime;
@ -252,6 +256,7 @@ struct cluster_info_s
int musicorder;
int flags;
int cdtrack;
char *clustername;
unsigned int cdid;
};
typedef struct cluster_info_s cluster_info_t;

View file

@ -80,7 +80,7 @@ bool P_MorphPlayer (player_t *p, const TypeInfo *spawntype)
p->momx = p->momy = 0;
morphed->ObtainInventory (actor);
// Remove all armor
for (item = actor->Inventory; item != NULL; )
for (item = morphed->Inventory; item != NULL; )
{
AInventory *next = item->Inventory;
if (item->IsKindOf (RUNTIME_CLASS(AArmor)))
@ -209,6 +209,9 @@ bool P_MorphMonster (AActor *actor, const TypeInfo *spawntype)
morphed->tid = actor->tid;
morphed->angle = actor->angle;
morphed->tracer = actor;
morphed->alpha = actor->alpha;
morphed->RenderStyle = actor->RenderStyle;
morphed->special1 = MORPHTICS + pr_morphmonst();
morphed->special2 = actor->flags & ~MF_JUSTHIT;
//morphed->special = actor->special;

View file

@ -34,7 +34,7 @@ IMPLEMENT_ACTOR (AIceChunk, Any, -1, 0)
PROP_RadiusFixed (3)
PROP_HeightFixed (4)
PROP_Flags (MF_DROPOFF)
PROP_Flags2 (MF2_LOGRAV|MF2_CANNOTPUSH|MF2_FLOORCLIP)
PROP_Flags2 (MF2_LOGRAV|MF2_CANNOTPUSH|MF2_FLOORCLIP|MF2_NOTELEPORT)
PROP_SpawnState (0)
END_DEFAULTS
@ -222,7 +222,7 @@ void A_FreezeDeathChunks (AActor *actor)
}
if (actor->player)
{ // attach the player's view to a chunk of ice
AIceChunkHead *head = Spawn<AIceChunkHead> (actor->x, actor->y, actor->z+VIEWHEIGHT);
AIceChunkHead *head = Spawn<AIceChunkHead> (actor->x, actor->y, actor->z + actor->player->defaultviewheight);
head->momz = FixedDiv(head->z-actor->z, actor->height)<<2;
head->momx = pr_freeze.Random2 () << (FRACBITS-7);
head->momy = pr_freeze.Random2 () << (FRACBITS-7);

View file

@ -71,10 +71,7 @@ void APowerupGiver::Serialize (FArchive &arc)
{
Super::Serialize (arc);
arc << PowerupType;
if (SaveVersion >= 223)
{
arc << EffectTics << BlendColor;
}
arc << EffectTics << BlendColor;
}
// Powerup -------------------------------------------------------------------

View file

@ -54,7 +54,7 @@ FState AHateTarget::States[] =
IMPLEMENT_ACTOR (AHateTarget, Any, 9076, 0)
PROP_RadiusFixed (20)
PROP_HeightFixed (56)
PROP_Flags (MF_SHOOTABLE|MF_NOSECTOR|MF_NOGRAVITY|MF_NOBLOOD)
PROP_Flags (MF_SHOOTABLE|MF_NOGRAVITY|MF_NOBLOOD)
PROP_SpawnState (0)
PROP_MassLong (INT_MAX)
END_DEFAULTS

View file

@ -377,6 +377,8 @@ bool APathFollower::Interpolate ()
dz = z;
}
if (CurrNode->Next==NULL) return false;
UnlinkFromWorld ();
if (args[2] & 1)
{ // linear
@ -386,6 +388,8 @@ bool APathFollower::Interpolate ()
}
else
{ // spline
if (CurrNode->Next->Next==NULL) return false;
x = FLOAT2FIXED(Splerp (FIXED2FLOAT(PrevNode->x), FIXED2FLOAT(CurrNode->x),
FIXED2FLOAT(CurrNode->Next->x), FIXED2FLOAT(CurrNode->Next->Next->x)));
y = FLOAT2FIXED(Splerp (FIXED2FLOAT(PrevNode->y), FIXED2FLOAT(CurrNode->y),

View file

@ -28,10 +28,7 @@ END_DEFAULTS
void AAmmo::Serialize (FArchive &arc)
{
Super::Serialize (arc);
if (SaveVersion >= 223)
{
arc << BackpackAmount << BackpackMaxAmount;
}
arc << BackpackAmount << BackpackMaxAmount;
}
//===========================================================================
@ -476,10 +473,7 @@ void AInventory::Serialize (FArchive &arc)
{
Icon = TexMan.ReadTexture (arc);
}
if (SaveVersion >= 226)
{
arc << AR_SOUNDW(PickupSound);
}
arc << AR_SOUNDW(PickupSound);
}
//===========================================================================
@ -1281,10 +1275,7 @@ void ABasicArmorPickup::Serialize (FArchive &arc)
{
Super::Serialize (arc);
arc << SavePercent << SaveAmount;
if (SaveVersion >= 222)
{
arc << DropTime;
}
arc << DropTime;
}
//===========================================================================
@ -1558,13 +1549,10 @@ void ABasicArmor::AbsorbDamage (int damage, int damageType, int &newdamage)
void AHexenArmor::Serialize (FArchive &arc)
{
Super::Serialize (arc);
arc << Slots[0] << Slots[1] << Slots[2] << Slots[3];
if (SaveVersion >= 224)
{
arc << Slots[4]
<< SlotsIncrement[0] << SlotsIncrement[1] << SlotsIncrement[2]
<< SlotsIncrement[3];
}
arc << Slots[0] << Slots[1] << Slots[2] << Slots[3]
<< Slots[4]
<< SlotsIncrement[0] << SlotsIncrement[1] << SlotsIncrement[2]
<< SlotsIncrement[3];
}
//===========================================================================
@ -1842,10 +1830,7 @@ bool AHealthPickup::Use (bool pickup)
void ABackpack::Serialize (FArchive &arc)
{
Super::Serialize (arc);
if (SaveVersion >= 227)
{
arc << bDepleted;
}
arc << bDepleted;
}
//===========================================================================

View file

@ -53,7 +53,7 @@ struct FWeaponSlots
void Clear ();
bool LocateWeapon (const TypeInfo *type, int *const slot, int *const index);
ESlotDef AddDefaultWeapon (int slot, const TypeInfo *type);
void RestoreSlots (FConfigFile &config);
int RestoreSlots (FConfigFile &config);
void SaveSlots (FConfigFile &config);
};

View file

@ -64,6 +64,7 @@ FState ABlood::States[] =
IMPLEMENT_ACTOR (ABlood, Any, -1, 130)
PROP_Flags (MF_NOBLOCKMAP)
PROP_Flags2 (MF2_NOTELEPORT)
PROP_Mass (5)
END_DEFAULTS

View file

@ -926,11 +926,12 @@ CCMD (addslotdefault)
}
}
void FWeaponSlots::RestoreSlots (FConfigFile &config)
int FWeaponSlots::RestoreSlots (FConfigFile &config)
{
char buff[MAX_WEAPONS_PER_SLOT*64];
const char *key, *value;
int slot;
int slotsread = 0;
buff[sizeof(buff)-1] = 0;
@ -960,7 +961,9 @@ void FWeaponSlots::RestoreSlots (FConfigFile &config)
Slots[slot].AddWeapon (tok);
tok = strtok (NULL, " ");
}
slotsread++;
}
return slotsread;
}
void FWeaponSlots::SaveSlots (FConfigFile &config)

View file

@ -209,14 +209,15 @@ protected:
void DrBNumberOuterFont (signed int val, int x, int y, int w=3) const;
void DrSmallNumberOuter (int val, int x, int y, bool center) const;
void DrawCrosshair ();
void RefreshBackground () const;
void GetCurrentAmmo (AAmmo *&ammo1, AAmmo *&ammo2, int &ammocount1, int &ammocount2) const;
AInventory *ValidateInvFirst (int numVisible) const;
static void AddBlend (float r, float g, float b, float a, float v_blend[4]);
public:
AInventory *ValidateInvFirst (int numVisible) const;
void DrawCrosshair ();
int ST_X, ST_Y;
int RelTop;

View file

@ -56,6 +56,7 @@ EXTERN_CVAR (Bool, am_showmonsters)
EXTERN_CVAR (Bool, am_showsecrets)
EXTERN_CVAR (Bool, am_showitems)
EXTERN_CVAR (Bool, am_showtime)
EXTERN_CVAR (Bool, am_showtotaltime)
EXTERN_CVAR (Bool, noisedebug)
EXTERN_CVAR (Bool, hud_scale)
@ -1146,16 +1147,24 @@ void FBaseStatusBar::Draw (EHudState state)
else if (automapactive)
{
int y, i, time = level.time / TICRATE, height;
int totaltime = level.totaltime / TICRATE;
EColorRange highlight = (gameinfo.gametype == GAME_Doom) ?
CR_UNTRANSLATED : CR_YELLOW;
height = screen->Font->GetHeight () * CleanYfac;
// Draw timer
y = 8;
if (am_showtime)
{
sprintf (line, "%02d:%02d:%02d", time/3600, (time%3600)/60, time%60); // Time
screen->DrawText (CR_GREY, SCREENWIDTH - 80*CleanXfac, 8, line, DTA_CleanNoMove, true, TAG_DONE);
screen->DrawText (CR_GREY, SCREENWIDTH - 80*CleanXfac, y, line, DTA_CleanNoMove, true, TAG_DONE);
y+=8*CleanYfac;
}
if (am_showtotaltime)
{
sprintf (line, "%02d:%02d:%02d", totaltime/3600, (totaltime%3600)/60, totaltime%60); // Total time
screen->DrawText (CR_GREY, SCREENWIDTH - 80*CleanXfac, y, line, DTA_CleanNoMove, true, TAG_DONE);
}
// Draw map name

View file

@ -316,6 +316,7 @@ IMPLEMENT_ACTOR (AAcolyteToBe, Strife, 201, 0)
PROP_RadiusFixed (20)
PROP_HeightFixed (56)
PROP_StrifeType (29)
PROP_Tag ("PEASANT")
PROP_DeathSound ("becoming/death")
END_DEFAULTS

View file

@ -123,6 +123,11 @@ void AMacil1::NoBlockingSet ()
int AMacil1::TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, int damagetype)
{
target = source;
if (PainState != NULL)
{
SetState (PainState);
}
return -1;
}
@ -178,5 +183,5 @@ int AMacil2::TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, i
{
if (inflictor->IsKindOf (RUNTIME_CLASS(ASpectralLightningV1)))
return -1;
return damage;
return Super::TakeSpecialDamage(inflictor, source, damage, damagetype);
}

View file

@ -83,5 +83,5 @@ int AOracle::TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, i
{
if (inflictor->IsKindOf (RUNTIME_CLASS(ASpectralLightningV1)))
return -1;
return damage;
return Super::TakeSpecialDamage(inflictor, source, damage, damagetype);
}

View file

@ -1512,9 +1512,10 @@ IMPLEMENT_ACTOR (AHEGrenade, Strife, -1, 0)
PROP_Flags (MF_NOBLOCKMAP|MF_DROPOFF|MF_MISSILE)
PROP_Flags2 (MF2_FLOORCLIP|MF2_NOTELEPORT|MF2_PCROSS|MF2_IMPACT|MF2_DOOMBOUNCE)
PROP_Flags3 (MF3_CANBOUNCEWATER)
PROP_Flags4 (MF4_STRIFEDAMAGE)
PROP_Flags4 (MF4_STRIFEDAMAGE|MF4_NOBOUNCESOUND)
PROP_MaxStepHeight (4)
PROP_StrifeType (106)
PROP_BounceFactor((FRACUNIT*5/10))
PROP_SeeSound ("weapons/hegrenadeshoot")
PROP_DeathSound ("weapons/hegrenadebang")
END_DEFAULTS
@ -1560,9 +1561,10 @@ IMPLEMENT_ACTOR (APhosphorousGrenade, Strife, -1, 0)
PROP_Flags (MF_NOBLOCKMAP|MF_DROPOFF|MF_MISSILE)
PROP_Flags2 (MF2_FLOORCLIP|MF2_NOTELEPORT|MF2_PCROSS|MF2_IMPACT|MF2_DOOMBOUNCE)
PROP_Flags3 (MF3_CANBOUNCEWATER)
PROP_Flags4 (MF4_STRIFEDAMAGE)
PROP_Flags4 (MF4_STRIFEDAMAGE|MF4_NOBOUNCESOUND)
PROP_MaxStepHeight (4)
PROP_StrifeType (107)
PROP_BounceFactor((FRACUNIT*5/10))
PROP_SeeSound ("weapons/phgrenadeshoot")
PROP_DeathSound ("weapons/phgrenadebang")
END_DEFAULTS
@ -1666,9 +1668,19 @@ void A_Burnination (AActor *self)
yofs = clamp (yofs, 12, 31);
}
fixed_t x = self->x + (xofs << FRACBITS);
fixed_t y = self->y + (yofs << FRACBITS);
sector_t * sector = R_PointInSubsector(x, y)->sector;
// The sector's floor is too high so spawn the flame elsewhere.
if (sector->floorplane.ZatPoint(x, y) > self->z + self->MaxStepHeight)
{
x = self->x;
y = self->y;
}
AActor *drop = Spawn<APhosphorousFire> (
self->x + (xofs << FRACBITS),
self->y + (yofs << FRACBITS),
x, y,
self->z + 4*FRACUNIT);
if (drop != NULL)
{

View file

@ -395,11 +395,7 @@ void FGameConfigFile::DoGameSetup (const char *gamename)
}
strcpy (subsection, "WeaponSlots");
if (SetSection (section))
{
LocalWeapons.RestoreSlots (*this);
}
else
if (!SetSection (section) || !LocalWeapons.RestoreSlots (*this))
{
SetupWeaponList (gamename);
}

View file

@ -271,6 +271,7 @@ enum
ADEF_MeleeRange,
ADEF_MaxDropOffHeight,
ADEF_MaxStepHeight,
ADEF_BounceFactor,
ADEF_SpawnState,
ADEF_SeeState,
@ -313,9 +314,6 @@ enum
ADEF_Powerup_Color,
ADEF_PowerupGiver_EffectTics,
ADEF_Key_KeyNumber,
ADEF_Key_AltKeyNumber,
ADEF_Ammo_BackpackAmount,
ADEF_Ammo_BackpackMaxAmount,

View file

@ -210,6 +210,7 @@ static void ApplyActorDefault (int defnum, const char *datastr, int dataint)
case ADEF_MeleeRange: actor->meleerange = dataint; break;
case ADEF_MaxDropOffHeight: actor->MaxDropOffHeight = dataint; break;
case ADEF_MaxStepHeight: actor->MaxStepHeight = dataint; break;
case ADEF_BounceFactor: actor->bouncefactor = dataint; break;
case ADEF_SpawnState: actor->SpawnState = datastate; break;
case ADEF_SeeState: actor->SeeState = datastate; break;
@ -265,9 +266,6 @@ static void ApplyActorDefault (int defnum, const char *datastr, int dataint)
case ADEF_Powerup_EffectTics: power->EffectTics = dataint; break;
case ADEF_Powerup_Color: power->BlendColor = dataint; break;
case ADEF_Key_KeyNumber: key->KeyNumber = dataint; break;
case ADEF_Key_AltKeyNumber: key->AltKeyNumber = dataint; break;
case ADEF_Ammo_BackpackAmount: ammo->BackpackAmount = dataint; break;
case ADEF_Ammo_BackpackMaxAmount:ammo->BackpackMaxAmount = dataint; break;

View file

@ -253,6 +253,7 @@ public:
#define PROP_MeleeRange(x) ADD_FIXD_PROP(ADEF_MeleeRange,x)
#define PROP_MaxDropOffHeight(x) ADD_FIXD_PROP(ADEF_MaxDropOffHeight,x)
#define PROP_MaxStepHeight(x) ADD_FIXD_PROP(ADEF_MaxStepHeight,x)
#define PROP_BounceFactor(x) ADD_LONG_PROP(ADEF_BounceFactor,x)
#define PROP_SpawnState(x) ADD_BYTE_PROP(ADEF_SpawnState,x)
#define PROP_SeeState(x) ADD_BYTE_PROP(ADEF_SeeState,x)
@ -297,9 +298,6 @@ public:
#define PROP_Powerup_EffectTics(x) ADD_LONG_PROP(ADEF_Powerup_EffectTics,x)
#define PROP_Powerup_Color(a,r,g,b) ADD_LONG_PROP(ADEF_Powerup_Color,((a)<<24)|((r)<<16)|((g)<<8)|(b))
#define PROP_Key_KeyNumber(x) ADD_BYTE_PROP(ADEF_Key_KeyNumber,x)
#define PROP_Key_AltKeyNumber(x) ADD_BYTE_PROP(ADEF_Key_AltKeyNumber,x)
#define PROP_Ammo_BackpackAmount(x) ADD_WORD_PROP(ADEF_Ammo_BackpackAmount,x)
#define PROP_Ammo_BackpackMaxAmount(x) ADD_WORD_PROP(ADEF_Ammo_BackpackMaxAmount,x)

View file

@ -311,7 +311,10 @@ void cht_DoCheat (player_t *player, int cheat)
break;
case CHT_ALLARTI:
cht_Give (player, "artifacts");
for (int i=0;i<25;i++)
{
cht_Give (player, "artifacts");
}
msg = GStrings("TXT_CHEATARTIFACTS3");
break;

View file

@ -645,6 +645,7 @@ void M_ReadSaveStrings ()
if (NULL != (png = M_VerifyPNG (file)))
{
char *ver = M_GetPNGText (png, "ZDoom Save Version");
char *engine = M_GetPNGText (png, "Engine");
if (ver != NULL)
{
if (!M_GetPNGText (png, "Title", title, SAVESTRINGSIZE))
@ -652,7 +653,8 @@ void M_ReadSaveStrings ()
strncpy (title, I_FindName(&c_file), SAVESTRINGSIZE);
}
if (strncmp (ver, SAVESIG, 9) == 0 &&
atoi (ver+9) >= MINSAVEVER)
atoi (ver+9) >= MINSAVEVER &&
engine != NULL)
{
// Was saved with a compatible ZDoom version,
// so check if it's for the current game.
@ -2278,7 +2280,7 @@ static void M_ChangeAutoAim (int choice)
static void M_EditPlayerName (int choice)
{
// we are going to be intercepting all chars
genStringEnter = 1;
genStringEnter = 2;
genStringEnd = M_PlayerNameChanged;
genStringLen = MAXPLAYERNAME;
@ -2477,7 +2479,7 @@ BOOL M_Responder (event_t *ev)
{
ch = ev->data1;
if (saveCharIndex < genStringLen &&
(size_t)SmallFont->StringWidth (savegamestring) < (genStringLen-1)*8)
(genStringEnter==2 || (size_t)SmallFont->StringWidth (savegamestring) < (genStringLen-1)*8))
{
savegamestring[saveCharIndex] = ch;
savegamestring[++saveCharIndex] = 0;

View file

@ -311,7 +311,7 @@ string GetUserFile (string file, bool nodir)
if (!nodir)
{
struct stat info;
if (stat (path, &info) == -1)
if (stat (path.GetChars(), &info) == -1)
{
if (mkdir (path.GetChars(), S_IRUSR | S_IWUSR | S_IXUSR) == -1)
{
@ -346,6 +346,7 @@ void STACK_ARGS M_SaveDefaults ()
}
GameConfig->WriteConfigFile ();
delete GameConfig;
GameConfig = NULL;
}

View file

@ -79,6 +79,7 @@
// Data.
#include "m_menu.h"
EXTERN_CVAR(Bool, nomonsterinterpolation)
//
// defaulted values
//
@ -537,12 +538,21 @@ EXTERN_CVAR (Bool, am_showitems)
EXTERN_CVAR (Bool, am_showmonsters)
EXTERN_CVAR (Bool, am_showsecrets)
EXTERN_CVAR (Bool, am_showtime)
EXTERN_CVAR (Int, am_map_secrets)
EXTERN_CVAR (Bool, am_showtotaltime)
EXTERN_CVAR (Bool, am_drawmapback)
static value_t MapColorTypes[] = {
{ 1, "Custom" },
{ 0, "Traditional Doom" }
};
static value_t SecretTypes[] = {
{ 0, "Never" },
{ 1, "Only when found" },
{ 2, "Always" },
};
static menuitem_t AutomapItems[] = {
{ discrete, "Map color set", {&am_usecustomcolors}, {2.0}, {0.0}, {0.0}, {MapColorTypes} },
{ more, "Set custom colors", {NULL}, {0.0}, {0.0}, {0.0}, {(value_t*)StartMapColorsMenu} },
@ -554,6 +564,9 @@ static menuitem_t AutomapItems[] = {
{ discrete, "Show monster counts", {&am_showmonsters}, {2.0}, {0.0}, {0.0}, {OnOff} },
{ discrete, "Show secret counts", {&am_showsecrets}, {2.0}, {0.0}, {0.0}, {OnOff} },
{ discrete, "Show time elapsed", {&am_showtime}, {2.0}, {0.0}, {0.0}, {OnOff} },
{ discrete, "Show total time elapsed", {&am_showtotaltime}, {2.0}, {0.0}, {0.0}, {OnOff} },
{ discrete, "Show secrets on map", {&am_map_secrets}, {3.0}, {0.0}, {0.0}, {SecretTypes} },
{ discrete, "Draw automap background", {&am_drawmapback}, {2.0}, {0.0}, {0.0}, {OnOff} },
};
menu_t AutomapMenu =
@ -592,6 +605,13 @@ EXTERN_CVAR (Color, am_ovunseencolor)
EXTERN_CVAR (Color, am_ovtelecolor)
EXTERN_CVAR (Color, am_intralevelcolor)
EXTERN_CVAR (Color, am_interlevelcolor)
EXTERN_CVAR (Color, am_secretsectorcolor)
EXTERN_CVAR (Color, am_thingcolor_friend)
EXTERN_CVAR (Color, am_thingcolor_monster)
EXTERN_CVAR (Color, am_thingcolor_item)
EXTERN_CVAR (Color, am_ovthingcolor_friend)
EXTERN_CVAR (Color, am_ovthingcolor_monster)
EXTERN_CVAR (Color, am_ovthingcolor_item)
static menuitem_t MapColorsItems[] = {
{ rsafemore, "Restore default custom colors", {NULL}, {0}, {0}, {0}, {(value_t*)DefaultCustomColors} },
@ -607,10 +627,14 @@ static menuitem_t MapColorsItems[] = {
{ colorpicker, "Locked doors", {&am_lockedcolor}, {0}, {0}, {0}, {0} },
{ colorpicker, "Teleporter to the same map", {&am_intralevelcolor}, {0}, {0}, {0}, {0} },
{ colorpicker, "Teleporter to a different map", {&am_interlevelcolor}, {0}, {0}, {0}, {0} },
{ colorpicker, "Secret sector", {&am_secretsectorcolor}, {0}, {0}, {0}, {0} },
{ redtext, " ", {NULL}, {0}, {0}, {0}, {0} },
{ colorpicker, "Invisible 2-sided walls (for cheat)", {&am_tswallcolor}, {0}, {0}, {0}, {0} },
{ colorpicker, "Secret walls (for cheat)", {&am_secretwallcolor}, {0}, {0}, {0}, {0} },
{ colorpicker, "Actors (for cheat)", {&am_thingcolor}, {0}, {0}, {0}, {0} },
{ colorpicker, "Monsters (for cheat)", {&am_thingcolor_monster}, {0}, {0}, {0}, {0} },
{ colorpicker, "Friends (for cheat)", {&am_thingcolor_friend}, {0}, {0}, {0}, {0} },
{ colorpicker, "Items (for cheat)", {&am_thingcolor_item}, {0}, {0}, {0}, {0} },
{ redtext, " ", {NULL}, {0}, {0}, {0}, {0} },
{ colorpicker, "You (overlay)", {&am_ovyourcolor}, {0}, {0}, {0}, {0} },
{ colorpicker, "1-sided walls (overlay)", {&am_ovwallcolor}, {0}, {0}, {0}, {0} },
@ -618,6 +642,9 @@ static menuitem_t MapColorsItems[] = {
{ colorpicker, "Not-yet-seen walls (overlay)", {&am_ovunseencolor}, {0}, {0}, {0}, {0} },
{ colorpicker, "Teleporter (overlay)", {&am_ovtelecolor}, {0}, {0}, {0}, {0} },
{ colorpicker, "Actors (overlay) (for cheat)", {&am_ovthingcolor}, {0}, {0}, {0}, {0} },
{ colorpicker, "Monsters (overlay) (for cheat)", {&am_ovthingcolor_monster}, {0}, {0}, {0}, {0} },
{ colorpicker, "Friends (overlay) (for cheat)", {&am_ovthingcolor_friend}, {0}, {0}, {0}, {0} },
{ colorpicker, "Items (overlay) (for cheat)", {&am_ovthingcolor_item}, {0}, {0}, {0}, {0} },
};
menu_t MapColorsMenu =
@ -625,7 +652,7 @@ menu_t MapColorsMenu =
"CUSTOMIZE MAP COLORS",
0,
sizeof(MapColorsItems)/sizeof(MapColorsItems[0]),
42,
48,
MapColorsItems,
};
@ -896,7 +923,8 @@ static menuitem_t DMFlagsItems[] = {
{ bitflag, "Allow jump", {&dmflags}, {1}, {0}, {0}, {(value_t *)DF_NO_JUMP} },
{ bitflag, "Allow freelook", {&dmflags}, {1}, {0}, {0}, {(value_t *)DF_NO_FREELOOK} },
{ bitflag, "Allow FOV", {&dmflags}, {1}, {0}, {0}, {(value_t *)DF_NO_FOV} },
{ bitflag, "Allow BFG aiming", {&dmflags2}, {1}, {0}, {0}, {(value_t *)DF2_NO_FREEAIMBFG} }
{ bitflag, "Allow BFG aiming", {&dmflags2}, {1}, {0}, {0}, {(value_t *)DF2_NO_FREEAIMBFG} },
{ bitflag, "Multi. weapons in coop", {&dmflags}, {1}, {0}, {0}, {(value_t *)DF_NO_COOP_WEAPON_SPAWN} },
};
static menu_t DMFlagsMenu =
@ -925,7 +953,8 @@ static menuitem_t CompatibilityItems[] = {
{ bitflag, "Spawn item drops on the floor", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_NOTOSSDROPS} },
{ bitflag, "All special lines can block <use>", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_USEBLOCKING} },
{ bitflag, "Disable BOOM door light effect", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_NODOORLIGHT} },
{ bitflag, "Raven scroll types use original speed", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_RAVENSCROLL} },
{ bitflag, "Raven scrollers use original speed", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_RAVENSCROLL} },
{ discrete, "Interpolate monster movement", {&nomonsterinterpolation}, {2.0}, {0.0}, {0.0}, {NoYes} },
};
static menu_t CompatibilityMenu =

View file

@ -957,18 +957,29 @@ static void PickConversationReply ()
takestuff = true;
if (reply->GiveType != NULL)
{
AInventory *item = static_cast<AInventory *> (Spawn (reply->GiveType, 0, 0, 0));
// Items given here should not count as items!
if (item->flags & MF_COUNTITEM)
if (reply->GiveType->IsDescendantOf(RUNTIME_CLASS(AWeapon)))
{
level.total_items--;
item->flags &= ~MF_COUNTITEM;
if (players[consoleplayer].mo->FindInventory(reply->GiveType) != NULL)
{
takestuff = false;
}
}
item->flags |= MF_DROPPED;
if (!item->TryPickup (players[consoleplayer].mo))
if (takestuff)
{
item->Destroy ();
takestuff = false;
AInventory *item = static_cast<AInventory *> (Spawn (reply->GiveType, 0, 0, 0));
// Items given here should not count as items!
if (item->flags & MF_COUNTITEM)
{
level.total_items--;
item->flags &= ~MF_COUNTITEM;
}
item->flags |= MF_DROPPED;
if (!item->TryPickup (players[consoleplayer].mo))
{
item->Destroy ();
takestuff = false;
}
}
}

View file

@ -631,12 +631,6 @@ DAnimatedDoor::DAnimatedDoor (sector_t *sec)
void DAnimatedDoor::Serialize (FArchive &arc)
{
// If you have a pre-224 savegame with an active animated door, then you're out
// of luck.
if (SaveVersion < 224)
{
I_Error ("Can't load pre-2.0.93 savegames with active animated doors.\n");
}
Super::Serialize (arc);
arc << m_Line1 << m_Line2
<< m_Frame

View file

@ -543,8 +543,9 @@ void P_NewChaseDir (AActor *actor)
deltay = actor->target->y - actor->y;
// [RH] Make monsters run away from frightening players
if (actor->target->player != NULL &&
(actor->target->player->cheats & CF_FRIGHTENING))
if ((actor->target->player != NULL &&
(actor->target->player->cheats & CF_FRIGHTENING)) ||
actor->flags4 & MF4_FRIGHTENED)
{
deltax = -deltax;
deltay = -deltay;
@ -1709,6 +1710,11 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi
}
actor->target = NULL;
actor->flags |= MF_JUSTATTACKED;
if (actor->goal != NULL && actor->goal->args[1] != 0)
{
actor->flags4 |= MF4_INCOMBAT;
actor->SetState (actor->SpawnState);
}
actor->flags &= ~MF_INCHASE;
return;
}
@ -1749,8 +1755,9 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi
}
// [RH] Scared monsters attack less frequently
if (actor->target->player == NULL ||
!(actor->target->player->cheats & CF_FRIGHTENING) ||
if (((actor->target->player == NULL ||
!(actor->target->player->cheats & CF_FRIGHTENING)) &&
!(actor->flags4 & MF4_FRIGHTENED)) ||
pr_scaredycat() < 43)
{
// check for melee attack
@ -1969,6 +1976,7 @@ void A_XXScream (AActor *actor)
// PROC P_DropItem
//
//---------------------------------------------------------------------------
CVAR(Int, sv_dropstyle, 0, CVAR_SERVERINFO | CVAR_ARCHIVE);
AInventory *P_DropItem (AActor *source, const TypeInfo *type, int special, int chance)
{
@ -1980,7 +1988,10 @@ AInventory *P_DropItem (AActor *source, const TypeInfo *type, int special, int c
spawnz = source->z;
if (!(compatflags & COMPATF_NOTOSSDROPS))
{
if (gameinfo.gametype == GAME_Strife)
int style = sv_dropstyle;
if (style==0) style= (gameinfo.gametype == GAME_Strife)? 2:1;
if (style==2)
{
spawnz += 24*FRACUNIT;
}
@ -2031,7 +2042,10 @@ AInventory *P_DropItem (AActor *source, const TypeInfo *type, int special, int c
void P_TossItem (AActor *item)
{
if (gameinfo.gametype == GAME_Strife)
int style = sv_dropstyle;
if (style==0) style= (gameinfo.gametype == GAME_Strife)? 2:1;
if (style==2)
{
item->momx += pr_dropitem.Random2(7) << FRACBITS;
item->momy += pr_dropitem.Random2(7) << FRACBITS;

View file

@ -654,6 +654,15 @@ bool EV_DoChange (line_t *line, EChange changetype, int tag)
}
static int P_FindSectorFromTagLinear (int tag, int start)
{
for (int i=start+1;i<numsectors;i++)
{
if (sectors[i].tag == tag) return i;
}
return -1;
}
//
// BUILD A STAIRCASE!
// [RH] Added stairsize, srcspeed, delay, reset, igntxt, usespecials parameters
@ -698,8 +707,14 @@ bool EV_BuildStairs (int tag, DFloor::EStair type, line_t *line,
goto manual_stair;
}
// The compatibility mode doesn't work with a hashing algorithm.
// It needs the original linear search method. This was broken in Boom.
int (* FindSector) (int tag, int start) =
(compatflags & COMPATF_STAIRINDEX)? P_FindSectorFromTagLinear : P_FindSectorFromTag;
secnum = -1;
while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0)
while ((secnum = FindSector (tag, secnum)) >= 0)
{
sec = &sectors[secnum];

View file

@ -372,8 +372,10 @@ void AActor::Die (AActor *source, AActor *inflictor)
flags &= ~(MF_SHOOTABLE|MF_FLOAT|MF_SKULLFLY);
if (!(flags4 & MF4_DONTFALL)) flags&=~MF_NOGRAVITY;
flags |= MF_DROPOFF;
if (flags3 & MF3_ISMONSTER)
{ // [RH] Only monsters get to be corpses.
if ((flags3 & MF3_ISMONSTER) || RaiseState != NULL)
{ // [RH] Only monsters get to be corpses.
// Objects with a raise state should get the flag as well so they can
// be revived by an Arch-Vile. Batman Doom needs this.
flags |= MF_CORPSE;
}
// [RH] Allow the death height to be overridden using metadata.

View file

@ -56,6 +56,7 @@ typedef enum {
Door_Animated = 14,
Autosave = 15, // [RH] Save the game *now*
Transfer_WallLight = 16,
Floor_LowerByValue = 20,
Floor_LowerToLowest = 21,

View file

@ -35,7 +35,6 @@
#define MAXHEALTH (deh.MaxHealth) //100
#define MAXMORPHHEALTH 30
#define VIEWHEIGHT (41*FRACUNIT)
#define BONUSADD 6

View file

@ -241,10 +241,7 @@ void AActor::Serialize (FArchive &arc)
{
picnum = TexMan.ReadTexture (arc);
}
if (SaveVersion >= 227)
{
floorpic = TexMan.ReadTexture (arc);
}
floorpic = TexMan.ReadTexture (arc);
}
arc << TIDtoHate;
if (TIDtoHate == 0)
@ -264,12 +261,8 @@ void AActor::Serialize (FArchive &arc)
<< floorz
<< ceilingz
<< dropoffz
<< floorsector;
if (SaveVersion < 227)
{
arc << floorpic;
}
arc << radius
<< floorsector
<< radius
<< height
<< momx
<< momy
@ -330,24 +323,18 @@ void AActor::Serialize (FArchive &arc)
<< IDeathState
<< EDeathState
<< RaiseState
<< WoundState;
if (SaveVersion >= 230)
{
arc << MaxDropOffHeight << MaxStepHeight;
}
if (SaveVersion >= 229)
{
arc << HealState
<< YesState
<< NoState
<< GreetingsState
<< meleerange
<< CrushState;
}
if (SaveVersion >= 224)
{
arc << DamageType;
}
<< WoundState
<< HealState
<< YesState
<< NoState
<< GreetingsState
<< CrushState
<< MaxDropOffHeight
<< MaxStepHeight
<< bouncefactor
<< meleerange
<< DamageType;
if (arc.IsStoring ())
{
int convnum = 0;
@ -355,8 +342,6 @@ void AActor::Serialize (FArchive &arc)
if (Conversation != NULL)
{
if (strcmp (Conversation->SpeakerName, "RICHTER") == 0)
Conversation = Conversation;
for (i = 0; i < StrifeDialogues.Size(); ++i)
{
if (StrifeDialogues[i] == GetDefault()->Conversation)
@ -1080,12 +1065,13 @@ bool AActor::FloorBounceMissile (secplane_t &plane)
}
// The reflected velocity keeps only about 70% of its original speed
momx = MulScale30 (momx - MulScale15 (plane.a, dot), 751619277);
momy = MulScale30 (momy - MulScale15 (plane.b, dot), 751619277);
momz = MulScale30 (momz - MulScale15 (plane.c, dot), 751619277);
long bouncescale = 0x4000 * bouncefactor;
momx = MulScale30 (momx - MulScale15 (plane.a, dot), bouncescale);
momy = MulScale30 (momy - MulScale15 (plane.b, dot), bouncescale);
momz = MulScale30 (momz - MulScale15 (plane.c, dot), bouncescale);
angle = R_PointToAngle2 (0, 0, momx, momy);
if (SeeSound)
if (SeeSound && !(flags4 & MF4_NOBOUNCESOUND))
{
S_SoundID (this, CHAN_VOICE, SeeSound, 1, ATTN_IDLE);
}
@ -1703,7 +1689,7 @@ void P_MonsterFallingDamage (AActor *mo)
int damage;
int mom;
if (gameinfo.gametype != GAME_Hexen)
if (!(level.flags&LEVEL_MONSTERFALLINGDAMAGE))
return;
mom = abs(mo->momz);
@ -1734,7 +1720,7 @@ void P_ZMovement (AActor *mo)
if (mo->player && mo->player->mo == mo && mo->z < mo->floorz)
{
mo->player->viewheight -= mo->floorz - mo->z;
mo->player->deltaviewheight = (VIEWHEIGHT - mo->player->viewheight)>>3;
mo->player->deltaviewheight = mo->player->GetDeltaViewHeight();
}
if (!(mo->flags2&MF2_FLOATBOB)) mo->z += mo->momz;
@ -2730,7 +2716,7 @@ void AActor::Tick ()
if (player && player->mo == this)
{
player->viewheight -= onmo->z + onmo->height - z;
fixed_t deltaview = (VIEWHEIGHT - player->viewheight)>>3;
fixed_t deltaview = player->GetDeltaViewHeight();
if (deltaview > player->deltaviewheight)
{
player->deltaviewheight = deltaview;
@ -2935,6 +2921,7 @@ BEGIN_DEFAULTS (AActor, Any, -1, 0)
PROP_MeleeRange(44) // MELEERANGE(64) - 20
PROP_MaxDropOffHeight(24)
PROP_MaxStepHeight(24)
PROP_BounceFactor(FRACUNIT*7/10)
END_DEFAULTS
//==========================================================================
@ -3222,7 +3209,7 @@ void AActor::AdjustFloorClip ()
if (player && player->mo == this && oldclip != floorclip)
{
player->viewheight -= oldclip - floorclip;
player->deltaviewheight = (VIEWHEIGHT - player->viewheight) >> 3;
player->deltaviewheight = player->GetDeltaViewHeight();
}
}
@ -3349,7 +3336,7 @@ void P_SpawnPlayer (mapthing2_t *mthing)
p->morphTics = 0;
p->extralight = 0;
p->fixedcolormap = 0;
p->viewheight = VIEWHEIGHT;
p->viewheight = p->defaultviewheight = gameinfo.gametype == GAME_Hexen? 48*FRACUNIT : 41*FRACUNIT;
p->inconsistant = 0;
p->attacker = NULL;
p->spreecount = 0;
@ -3666,8 +3653,8 @@ void P_SpawnMapThing (mapthing2_t *mthing, int position)
if (deathmatch && info->flags & MF_NOTDMATCH)
return;
// [RH] don't spawn extra weapons in coop
if (multiplayer && !deathmatch)
// [RH] don't spawn extra weapons in coop if so desired
if (multiplayer && !deathmatch && (dmflags&DF_NO_COOP_WEAPON_SPAWN))
{
if (i->IsDescendantOf (RUNTIME_CLASS(AWeapon)))
{

View file

@ -126,7 +126,8 @@ void P_SerializeWorld (FArchive &arc)
<< sec->sky
<< sec->MoreFlags
<< sec->FloorSkyBox << sec->CeilingSkyBox
<< sec->ZoneNumber;
<< sec->ZoneNumber
<< sec->oldspecial;
if (arc.IsStoring ())
{
arc << sec->ColorMap->Color

View file

@ -822,6 +822,7 @@ void P_LoadSectors (int lump)
ss->special = LittleShort(ms->special);
else // [RH] Translate to new sector special
ss->special = P_TranslateSectorSpecial (LittleShort(ms->special));
ss->oldspecial = !!(ss->special&SECRET_MASK);
ss->tag = LittleShort(ms->tag);
ss->thinglist = NULL;
ss->touching_thinglist = NULL; // phares 3/14/98

View file

@ -93,14 +93,6 @@ void DScroller::Serialize (FArchive &arc)
<< m_LastHeight
<< m_vdx << m_vdy
<< m_Accel;
if (SaveVersion < 228)
{
if (m_Type == sc_carry)
{
m_dx = FixedDiv (m_dx, CARRYFACTOR);
m_dy = FixedDiv (m_dy, CARRYFACTOR);
}
}
}
DPusher::DPusher ()
@ -218,14 +210,21 @@ static void P_InitAnimDefs ()
int picnum = TexMan.CheckForTexture (sc_String, isflat ? FTexture::TEX_Flat : FTexture::TEX_Wall, texflags);
if (picnum != -1)
{
FTexture *warper;
if (type2) // [GRB]
warper = new FWarp2Texture (TexMan[picnum]);
else
warper = new FWarpTexture (TexMan[picnum]);
TexMan.ReplaceTexture (picnum, warper, false);
FTexture * warper = TexMan[picnum];
// No decals on warping textures, by default
// don't warp a texture more than once
if (!warper->bWarped)
{
if (type2) // [GRB]
warper = new FWarp2Texture (warper);
else
warper = new FWarpTexture (warper);
TexMan.ReplaceTexture (picnum, warper, false);
}
// No decals on warping textures, by default.
// Warping information is taken from the last warp
// definition for this texture.
warper->bNoDecals = true;
if (SC_GetString ())
{
@ -818,7 +817,7 @@ BOOL P_TestActivateLine (line_t *line, AActor *mo, int side, int activationType)
if (activationType == SPAC_OTHERCROSS)
{
if (lineActivation == SPAC_CROSS && line->special >= Generic_Floor &&
line->special <= Generic_Crusher)
line->special <= Generic_Crusher && !(mo->flags2&MF2_NOTELEPORT))
{
return (line->flags & ML_MONSTERSCANACTIVATE) != 0;
}
@ -829,7 +828,7 @@ BOOL P_TestActivateLine (line_t *line, AActor *mo, int side, int activationType)
{
return false;
}
if (!mo->player &&
if (mo && !mo->player &&
!(mo->flags & MF_MISSILE) &&
!(line->flags & ML_MONSTERSCANACTIVATE) &&
(activationType != SPAC_MCROSS || lineActivation != SPAC_MCROSS))
@ -1302,6 +1301,95 @@ void DLightTransfer::DoTransfer (BYTE level, int target, bool floor)
}
}
class DWallLightTransfer : public DThinker
{
enum
{
WLF_SIDE1=1,
WLF_SIDE2=2,
WLF_NOFAKECONTRAST=4
};
DECLARE_ACTOR (DWallLightTransfer, DThinker)
public:
DWallLightTransfer (sector_t *srcSec, int target, BYTE flags);
void Serialize (FArchive &arc);
void Tick ();
protected:
static void DoTransfer (BYTE level, int target, BYTE flags);
BYTE LastLight;
BYTE Flags;
sector_t *Source;
int TargetID;
};
IMPLEMENT_CLASS (DWallLightTransfer)
void DWallLightTransfer::Serialize (FArchive &arc)
{
Super::Serialize (arc);
arc << LastLight << Source << TargetID << Flags;
}
DWallLightTransfer::DWallLightTransfer (sector_t *srcSec, int target, BYTE flags)
{
int linenum;
int wallflags;
Source = srcSec;
TargetID = target;
Flags = flags;
DoTransfer (LastLight = srcSec->lightlevel, target, Flags);
if (!(flags&WLF_NOFAKECONTRAST)) wallflags = WALLF_AUTOCONTRAST|WALLF_ABSLIGHTING;
else wallflags = WALLF_ABSLIGHTING;
for (linenum = -1; (linenum = P_FindLineFromID (target, linenum)) >= 0; )
{
if (flags & WLF_SIDE1 && lines[linenum].sidenum[0]!=NO_SIDE)
sides[lines[linenum].sidenum[0]].Flags |= wallflags;
if (flags & WLF_SIDE2 && lines[linenum].sidenum[1]!=NO_SIDE)
sides[lines[linenum].sidenum[1]].Flags |= wallflags;
}
ChangeStatNum(STAT_LIGHTTRANSFER);
}
void DWallLightTransfer::Tick ()
{
BYTE light = Source->lightlevel;
if (light != LastLight)
{
LastLight = light;
DoTransfer (light, TargetID, Flags);
}
}
void DWallLightTransfer::DoTransfer (BYTE lightlevel, int target, BYTE flags)
{
int linenum;
for (linenum = -1; (linenum = P_FindLineFromID (target, linenum)) >= 0; )
{
line_t * line = &lines[linenum];
if (flags & WLF_SIDE1 && line->sidenum[0]!=NO_SIDE)
{
sides[line->sidenum[0]].Light = (BYTE)lightlevel;
}
if (flags & WLF_SIDE2 && line->sidenum[1]!=NO_SIDE)
{
sides[line->sidenum[1]].Light = (BYTE)lightlevel;
}
}
}
//
// P_SpawnSpecials
//
@ -1503,6 +1591,12 @@ void P_SpawnSpecials (void)
new DLightTransfer (sides[*lines[i].sidenum].sector, lines[i].args[0], false);
break;
// [Graf Zahl] Add support for setting lighting
// per wall independently
case Transfer_WallLight:
new DWallLightTransfer (sides[*lines[i].sidenum].sector, lines[i].args[0], lines[i].args[1]);
break;
// [RH] ZDoom Static_Init settings
case Static_Init:
switch (lines[i].args[1])

View file

@ -89,4 +89,5 @@ void P_Ticker (void)
// for par times
level.time++;
level.maptime++;
level.totaltime++;
}

View file

@ -108,8 +108,12 @@ void player_s::SetLogNumber (int num)
}
else
{
FMemLump data = Wads.ReadLump (lumpnum);
SetLogText ((char *)data.GetMem());
int length=Wads.LumpLength(lumpnum);
char *data= new char[length+1];
Wads.ReadLump (lumpnum, data);
data[length]=0;
SetLogText (data);
delete[] data;
// Print log text to console
AddToConsole(-1, TEXTCOLOR_GOLD);
@ -130,10 +134,7 @@ void APlayerPawn::Serialize (FArchive &arc)
{
Super::Serialize (arc);
if (SaveVersion >= 229)
{
arc << JumpZ;
}
arc << JumpZ;
}
void APlayerPawn::BeginPlay ()
@ -144,6 +145,9 @@ void APlayerPawn::BeginPlay ()
void APlayerPawn::AddInventory (AInventory *item)
{
// Don't add to the inventory of dead players.
if (health<=0) return;
// Adding inventory to a voodoo doll should add it to the real player instead.
if (player != NULL && player->mo != this)
{
@ -551,9 +555,11 @@ void P_CalcHeight (player_t *player)
}
}
fixed_t defaultviewheight = player->defaultviewheight;
if (player->cheats & CF_NOMOMENTUM)
{
player->viewz = player->mo->z + VIEWHEIGHT;
player->viewz = player->mo->z + defaultviewheight;
if (player->viewz > player->mo->ceilingz-4*FRACUNIT)
player->viewz = player->mo->ceilingz-4*FRACUNIT;
@ -585,14 +591,14 @@ void P_CalcHeight (player_t *player)
{
player->viewheight += player->deltaviewheight;
if (player->viewheight > VIEWHEIGHT)
if (player->viewheight > defaultviewheight)
{
player->viewheight = VIEWHEIGHT;
player->viewheight = defaultviewheight;
player->deltaviewheight = 0;
}
else if (player->viewheight < VIEWHEIGHT/2)
else if (player->viewheight < (defaultviewheight>>1))
{
player->viewheight = VIEWHEIGHT/2;
player->viewheight = defaultviewheight>>1;
if (player->deltaviewheight <= 0)
player->deltaviewheight = 1;
}
@ -1370,6 +1376,7 @@ void player_s::Serialize (FArchive &arc)
<< DesiredFOV << FOV
<< viewz
<< viewheight
<< defaultviewheight
<< deltaviewheight
<< bob
<< momx
@ -1415,6 +1422,7 @@ void player_s::Serialize (FArchive &arc)
<< BlendA
<< accuracy << stamina
<< LogText;
for (i = 0; i < MAXPLAYERS; i++)
arc << frags[i];
for (i = 0; i < NUMPSPRITES; i++)
@ -1472,3 +1480,4 @@ void player_s::Serialize (FArchive &arc)
oldbuttons = ~0;
}
}

View file

@ -189,12 +189,12 @@ void DRotatePoly::Tick ()
{
unsigned int absSpeed = abs (m_Speed);
if ((unsigned int)m_Dist == ~0u)
if (m_Dist == -1)
{ // perpetual polyobj
return;
}
m_Dist -= absSpeed;
if (m_Dist == 0)
if (m_Dist <= 0 && m_Dist+absSpeed>0)
{
polyobj_t *poly = GetPolyobj (m_PolyObj);
if (poly->specialdata == this)
@ -471,7 +471,7 @@ void DPolyDoor::Tick ()
if (PO_RotatePolyobj (m_PolyObj, m_Speed))
{
absSpeed = abs (m_Speed);
if (m_Dist == ~0u)
if (m_Dist == -1)
{ // perpetual polyobj
return;
}

View file

@ -746,9 +746,10 @@ FTexture::FTexture ()
: LeftOffset(0), TopOffset(0),
WidthBits(0), HeightBits(0), ScaleX(8), ScaleY(8),
UseType(TEX_Any), bNoDecals(false), bNoRemap0(false), bWorldPanning(false),
bMasked(true), bAlphaTexture(false), bHasCanvas(false),
bMasked(true), bAlphaTexture(false), bHasCanvas(false), bWarped(0),
Rotations(0xFFFF), Width(0xFFFF), Height(0), WidthMask(0)
{
*Name=0;
}
FTexture::~FTexture ()
@ -1127,22 +1128,26 @@ const BYTE *FPatchTexture::GetColumn (unsigned int column, const Span **spans_ou
void FPatchTexture::GetDimensions ()
{
FWadLump lump = Wads.OpenLumpNum (SourceLump);
// Wads.OpenLumpNum cannot be used here once Zip support has been added.
// To work correctly it needs an assignment operator which
// would cause considerable overhead elsewhere where it isn't needed.
FWadLump * lump = Wads.ReopenLumpNum (SourceLump);
patch_t dummy;
lump >> dummy.width >> dummy.height;
(*lump) >> dummy.width >> dummy.height;
if (dummy.width <= 0 || dummy.height <= 0 || dummy.width > 2048 || dummy.height > 2048)
{
lump = Wads.OpenLumpName ("-BADPATC");
lump >> dummy.width >> dummy.height;
lump = Wads.ReopenLumpNum ( Wads.GetNumForName("-BADPATC") );
(*lump) >> dummy.width >> dummy.height;
}
lump >> dummy.leftoffset >> dummy.topoffset;
(*lump) >> dummy.leftoffset >> dummy.topoffset;
Width = dummy.width;
Height = dummy.height;
LeftOffset = dummy.leftoffset;
TopOffset = dummy.topoffset;
delete lump;
CalcBitSize ();
}
@ -1175,10 +1180,13 @@ void FPatchTexture::MakeTexture ()
Printf (PRINT_BOLD, "Patch %s is too big.\n", Name);
}
Width = LittleShort(patch->width);
Height = LittleShort(patch->height);
LeftOffset = LittleShort(patch->leftoffset);
TopOffset = LittleShort(patch->topoffset);
if (Width == 0xFFFF)
{
Width = LittleShort(patch->width);
Height = LittleShort(patch->height);
LeftOffset = LittleShort(patch->leftoffset);
TopOffset = LittleShort(patch->topoffset);
}
CalcBitSize ();
// Add a little extra space at the end if the texture's height is not
@ -1643,10 +1651,13 @@ void FIMGZTexture::MakeTexture ()
const ImageHeader *imgz = (const ImageHeader *)lump.GetMem();
const BYTE *data = (const BYTE *)&imgz[1];
Width = LittleShort(imgz->Width);
Height = LittleShort(imgz->Height);
LeftOffset = LittleShort(imgz->LeftOffset);
TopOffset = LittleShort(imgz->TopOffset);
if (Width != 0xFFFF)
{
Width = LittleShort(imgz->Width);
Height = LittleShort(imgz->Height);
LeftOffset = LittleShort(imgz->LeftOffset);
TopOffset = LittleShort(imgz->TopOffset);
}
BYTE *dest_p;
int dest_adv = Height;
@ -2331,6 +2342,7 @@ FWarpTexture::FWarpTexture (FTexture *source)
ScaleY = source->ScaleY;
bNoDecals = source->bNoDecals;
Rotations = source->Rotations;
bWarped = 1;
}
FWarpTexture::~FWarpTexture ()
@ -2454,6 +2466,7 @@ void FWarpTexture::MakeTexture (DWORD time)
FWarp2Texture::FWarp2Texture (FTexture *source)
: FWarpTexture (source)
{
bWarped = 2;
}
void FWarp2Texture::MakeTexture (DWORD time)

View file

@ -365,6 +365,7 @@ struct sector_t
FExtraLight *ExtraLights;
vertex_t *Triangle[3]; // Three points that can define a plane
short oldspecial; //jff 2/16/98 remembers if sector WAS secret (automap)
};
struct ReverbContainer;
@ -385,6 +386,7 @@ enum
WALLF_ABSLIGHTING = 1, // Light is absolute instead of relative
WALLF_NOAUTODECALS = 2, // Do not attach impact decals to this wall
WALLF_ADDTRANS = 4, // Use additive instead of normal translucency
WALLF_AUTOCONTRAST = 8, // Automatically handle fake contrast in side_s::GetLightLevel
};
struct side_s
@ -607,6 +609,7 @@ public:
BYTE bMasked:1; // Texture (might) have holes
BYTE bAlphaTexture:1; // Texture is an alpha channel without color information
BYTE bHasCanvas:1; // Texture is based off FCanvasTexture
BYTE bWarped:2; // This is a warped texture. Used to avoid multiple warps on one texture
WORD Rotations;

View file

@ -1774,9 +1774,9 @@ void FActiveInterpolation::DoAnInterpolation (fixed_t smoothratio)
*adr2 = oldipos[1] + FixedMul (pos - oldipos[1], smoothratio);
}
size_t FActiveInterpolation::HashKey (EInterpType type, void *interptr)
unsigned FActiveInterpolation::HashKey (EInterpType type, void *interptr)
{
return ((size_t)(interptr))>>5;
return (unsigned)type * ((unsigned)interptr>>5);
}
int FActiveInterpolation::CountInterpolations ()
@ -1823,7 +1823,7 @@ int FActiveInterpolation::CountInterpolations (int *usedbuckets, int *minbucketf
FActiveInterpolation *FActiveInterpolation::FindInterpolation (EInterpType type, void *interptr, FActiveInterpolation **&interp_p)
{
size_t hash = HashKey (type, interptr) % INTERPOLATION_BUCKETS;
unsigned hash = HashKey (type, interptr) % INTERPOLATION_BUCKETS;
FActiveInterpolation *probe, **probe_p;
for (probe_p = &curiposhash[hash], probe = *probe_p;

View file

@ -229,7 +229,7 @@ private:
void CopyBakToInterp();
void DoAnInterpolation(fixed_t smoothratio);
static size_t HashKey(EInterpType type, void *interptr);
static unsigned HashKey(EInterpType type, void *interptr);
static FActiveInterpolation *FindInterpolation(EInterpType, void *interptr, FActiveInterpolation **&interp_p);
friend void updateinterpolations();

View file

@ -1066,7 +1066,7 @@ void R_NewWall (bool needlights)
int side_s::GetLightLevel (bool foggy, int baselight) const
{
// [RH] Get wall light level
if (this->Flags & WALLF_ABSLIGHTING)
if (this->Flags & WALLF_ABSLIGHTING && (!(this->Flags & WALLF_AUTOCONTRAST) || foggy))
{
return (BYTE)this->Light;
}
@ -1074,7 +1074,19 @@ int side_s::GetLightLevel (bool foggy, int baselight) const
{
if (!foggy) // Don't do relative lighting in foggy sectors
{
baselight += this->Light * 2;
int rellight;
if (this->Flags & WALLF_AUTOCONTRAST)
{
baselight = (BYTE)this->Light;
rellight = linedef->dx==0? level.WallVertLight : linedef->dy==0 ? level.WallHorizLight : 0;
}
else
{
rellight = this->Light;
}
baselight += rellight * 2;
}
return baselight;
}

View file

@ -520,6 +520,47 @@ int S_DupPlayerSound (const char *pclass, int gender, int refid, int aliasref)
return S_AddPlayerSoundExisting (pclass, gender, refid, aliasto);
}
//==========================================================================
//
// S_ClearSoundData
//
// clears all sound tables
// When we want to allow level specific SNDINFO lumps this has to
// be cleared for each level
//==========================================================================
static void S_ClearSoundData()
{
int i;
S_sfx.Clear();
for(i=0;i<256;i++)
{
if (Ambients[i]) delete Ambients[i];
Ambients[i]=NULL;
}
for(i=0;i<S_rnd.Size();i++)
{
delete[] S_rnd[i].Sounds;
}
while (MusicVolumes != NULL)
{
FMusicVolume * me = MusicVolumes;
MusicVolumes = me->Next;
delete me;
}
S_rnd.Clear();
DoneReserving=false;
NumPlayerReserves=0;
PlayerClassesIsSorted=false;
PlayerClasses.Clear();
PlayerSounds.Clear();
DefPlayerClass=0;
*DefPlayerClassName=0;
}
//==========================================================================
//
// S_ParseSndInfo
@ -532,6 +573,8 @@ void S_ParseSndInfo ()
{
int lump;
S_ClearSoundData(); // remove old sound data first!
CurrentPitchMask = 0;
S_AddSound ("{ no sound }", "DSEMPTY"); // Sound 0 is no sound at all
for (lump = 0; lump < Wads.GetNumLumps(); ++lump)
@ -576,6 +619,26 @@ void S_ParseSndInfo ()
sfx_empty = Wads.CheckNumForName ("dsempty");
}
//==========================================================================
//
// Adds a level specific SNDINFO lump
//
//==========================================================================
void S_AddLocalSndInfo(int lump)
{
S_AddSNDINFO(lump);
S_HashSounds ();
S_sfx.ShrinkToFit ();
if (S_rnd.Size() > 0)
{
S_rnd.ShrinkToFit ();
}
S_ShrinkPlayerSoundLists ();
}
//==========================================================================
//
// S_AddSNDINFO

View file

@ -369,7 +369,7 @@ static void AssignHexenTranslations (void)
//
//==========================================================================
void S_ParseSndSeq (void)
void S_ParseSndSeq (int levellump)
{
int lastlump, lump;
char name[MAX_SNDNAME+1];
@ -377,6 +377,20 @@ void S_ParseSndSeq (void)
int cursize;
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 (int i=0;i<NumSequences;i++)
{
if (Sequences[i]) free(Sequences[i]);
}
free(Sequences);
}
NumSequences=MaxSequences=0;
Sequences=NULL; // must be reinitialized every level!
// be gone, compiler warnings
cursize = 0;
stopsound = 0;
@ -387,8 +401,13 @@ void S_ParseSndSeq (void)
ScriptTemp = (unsigned int *)Malloc (MAX_SEQSIZE * sizeof(*ScriptTemp));
ScriptTempSize = MAX_SEQSIZE;
while ((lump = Wads.FindLump ("SNDSEQ", &lastlump)) != -1)
while (((lump = Wads.FindLump ("SNDSEQ", &lastlump)) != -1 || levellump!=-1) && levellump!=-2)
{
if (lump==-1)
{
lump=levellump;
levellump=-2;
}
SC_OpenLumpNum (lump, "SNDSEQ");
while (SC_GetString ())
{
@ -940,3 +959,4 @@ void DSeqNode::ChangeData (int seqOffset, int delayTics, float volume, int curre
m_SequencePtr += seqOffset;
m_CurrentSoundID = currentSoundID;
}

View file

@ -2,7 +2,7 @@
#define __S_SNDSEQ_H__
#include <stddef.h>
#include "actor.h"
//#include "actor.h"
#include "s_sound.h"
#include "r_defs.h"
@ -16,7 +16,7 @@ typedef enum {
struct sector_t;
void S_ParseSndSeq (void);
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);

View file

@ -50,6 +50,7 @@
#include "vectors.h"
#include "gi.h"
#include "templates.h"
#include "zstring.h"
// MACROS ------------------------------------------------------------------
@ -264,6 +265,10 @@ void S_NoiseDebug (void)
BorderNeedRefresh = screen->GetPageCount ();
}
static string LastLocalSndInfo = "";
static string LastLocalSndSeq = "";
void S_AddLocalSndInfo(int lump);
//==========================================================================
//
// S_Init
@ -279,6 +284,10 @@ void S_Init ()
Printf ("S_Init\n");
// remove old data (S_Init can be called multiple times!)
LastLocalSndInfo = LastLocalSndSeq = "";
if (SoundCurve) delete [] SoundCurve;
// Heretic and Hexen have sound curve lookup tables. Doom does not.
curvelump = Wads.CheckNumForName ("SNDCURVE");
if (curvelump >= 0)
@ -305,7 +314,7 @@ void S_Init ()
}
// [RH] Read in sound sequences
S_ParseSndSeq ();
S_ParseSndSeq (-1);
// Allocating the virtual channels
numChannels = GSnd ? GSnd->SetChannels (snd_channels) : 0;
@ -345,13 +354,59 @@ void S_Start ()
{
int cnum;
// kill all playing sounds at start of level (trust me - a good idea)
for (cnum = 0; cnum < numChannels; cnum++)
if (GSnd)
{
if (Channel[cnum].sfxinfo)
// kill all playing sounds at start of level (trust me - a good idea)
for (cnum = 0; cnum < numChannels; cnum++)
{
S_StopChannel (cnum);
if (Channel[cnum].sfxinfo)
{
S_StopChannel (cnum);
}
}
// Check for local sound definitions. Only reload if they differ
// from the previous ones.
// To be certain better check whether level is valid!
char * LocalSndInfo= level.info? level.info->soundinfo : (char*)"";
char * LocalSndSeq = level.info? level.info->sndseq : (char*)"";
bool parse_ss=false;
// This level uses a different local SNDINFO
if (LastLocalSndInfo.CompareNoCase(LocalSndInfo) != 0 || !level.info)
{
// First delete the old sound list
for(unsigned i=1;i<S_sfx.Size();i++)
{
GSnd->UnloadSound(&S_sfx[i]);
}
// Parse the global SNDINFO
S_ParseSndInfo();
if (*LocalSndInfo)
{
// Now parse the local SNDINFO
int j = Wads.CheckNumForName(LocalSndInfo);
if (j>=0) S_AddLocalSndInfo(j);
}
// Also reload the SNDSEQ if the SNDINFO was replaced!
parse_ss=true;
}
else if (LastLocalSndSeq.CompareNoCase(LocalSndSeq) != 0)
{
parse_ss=true;
}
if (parse_ss)
{
S_ParseSndSeq(*LocalSndSeq? Wads.CheckNumForName(LocalSndSeq) : -1);
}
else
LastLocalSndInfo = LocalSndInfo;
LastLocalSndSeq = LocalSndSeq;
}
// start new music for the level

View file

@ -210,6 +210,8 @@ static flagdef ActorFlags[]=
DEFINE_FLAG(MF4, ALLOWPARTICLES, AActor, flags4),
DEFINE_FLAG(MF4, EXTREMEDEATH, AActor, flags4),
DEFINE_FLAG(MF4, NOEXTREMEDEATH, AActor, flags4),
DEFINE_FLAG(MF4, FRIGHTENED, AActor, flags4),
DEFINE_FLAG(MF4, NOBOUNCESOUND, AActor, flags4),
// Effect flags
DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects),
@ -2665,6 +2667,15 @@ static void ActorBloodColor (AActor *defaults, Baggage &bag)
}
//==========================================================================
//
//==========================================================================
static void ActorBounceFactor (AActor *defaults, Baggage &bag)
{
SC_MustGetFloat ();
defaults->bouncefactor = sc_Float * FRACUNIT;
}
//==========================================================================
//
//==========================================================================
@ -3227,6 +3238,7 @@ static const ActorProps props[] =
{ "armor.savepercent", (apf)ArmorSavePercent, RUNTIME_CLASS(AActor) },
{ "attacksound", ActorAttackSound, RUNTIME_CLASS(AActor) },
{ "bloodcolor", ActorBloodColor, RUNTIME_CLASS(AActor) },
{ "bouncefactor", ActorBounceFactor, RUNTIME_CLASS(AActor) },
{ "burn", ActorBurnState, RUNTIME_CLASS(AActor) },
{ "burnheight", ActorBurnHeight, RUNTIME_CLASS(AActor) },
{ "clearflags", ActorClearFlags, RUNTIME_CLASS(AActor) },
@ -3424,3 +3436,5 @@ void FinishThingdef()
}
}
}

View file

@ -358,7 +358,7 @@ int FFont::SimpleTranslation (byte *colorsused, byte *translation, byte *reverse
memset (translation, 0, 256);
reverse[0] = 0;
for (i = 0, j = 1; i < 256; i++)
for (i = 1, j = 1; i < 256; i++)
{
if (colorsused[i])
{
@ -384,7 +384,7 @@ int FFont::SimpleTranslation (byte *colorsused, byte *translation, byte *reverse
min = (*luminosity)[i];
}
diver = 1.0 / (max - min);
for (i = 0; i < j; i++)
for (i = 1; i < j; i++)
{
(*luminosity)[i] = ((*luminosity)[i] - min) * diver;
}
@ -872,6 +872,8 @@ void FSingleLumpFont::BuildTranslations2 ()
*range++ = ColorMatcher.Pick (r, g, b);
}
}
// Make CR_UNTRANSLATED a valid translation!
memcpy(range, range-ActiveColors, ActiveColors);
}
FFontChar1::FFontChar1 (int sourcelump, const BYTE *sourceremap)

View file

@ -155,7 +155,7 @@ public:
virtual void Dim (PalEntry color, float amount, int x1, int y1, int w, int h) const;
// Fill an area with a texture
void FlatFill (int left, int top, int right, int bottom, FTexture *src);
virtual void FlatFill (int left, int top, int right, int bottom, FTexture *src);
// Set an area to a specified color
virtual void Clear (int left, int top, int right, int bottom, int color) const;

View file

@ -43,11 +43,13 @@ enum { GAMEVERSION = 205 };
// SAVEVER is the version of the information stored in level snapshots.
// Note that SAVEVER is not directly comparable to VERSION.
// SAVESIG should match SAVEVER.
#define SAVEVER 230
#define SAVESIG "ZDOOMSAVE230"
#define SAVEVER 231
#define SAVESIG "ZDOOMSAVE231"
// This is so that derivates can use the same savegame versions without worrying about engine compatibility
#define GAMESIG "ZDOOM"
// MINSAVEVER is the minimum level snapshot version that can be loaded.
#define MINSAVEVER 221 // Used by 2.0.90
#define MINSAVEVER 231 // Used by 2.0.99
// The maximum length of one save game description for the menus.
#define SAVESTRINGSIZE 24

View file

@ -1265,13 +1265,13 @@ static HRESULT InitJoystick ()
static void DI_Acquire (LPDIRECTINPUTDEVICE8 mouse)
{
mouse->Acquire ();
if (mouse) mouse->Acquire ();
SetCursorState (NativeMouse);
}
static void DI_Unacquire (LPDIRECTINPUTDEVICE8 mouse)
{
mouse->Unacquire ();
if (mouse) mouse->Unacquire ();
SetCursorState (TRUE);
}

View file

@ -24,7 +24,7 @@ QLPROMPT = "VOULEZ-VOUS CHARGER LA SAUVEGARDE"
NEWGAME = "VOUS NE POUVEZ PAS LANCER\n"
"UN NOUVEAU JEU SUR RESEAU.\n\nAPPUYEZ SUR UNE TOUCHE.";
NIGHTMARE = "VOUS CONFIRMEZ? CE NIVEAU EST\n"
"VRAIMENT IMPITOYABLE!nAPPUYEZ SUR Y OU N";
"VRAIMENT IMPITOYABLE!\nAPPUYEZ SUR Y OU N";
SWSTRING = "CECI EST UNE VERSION SHAREWARE DE DOOM.\n\n"
"VOUS DEVRIEZ COMMANDER LA TRILOGIE COMPLETE.\n\nAPPUYEZ SUR UNE TOUCHE.";
MSGOFF = "MESSAGES OFF";

View file

@ -692,6 +692,9 @@
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_hub.cpp">
</File>
<File
RelativePath=".\src\g_level.cpp">
<FileConfiguration
@ -1894,6 +1897,9 @@
<File
RelativePath=".\src\g_game.h">
</File>
<File
RelativePath=".\src\g_hub.h">
</File>
<File
RelativePath=".\src\g_level.h">
</File>