- Fixed: ACS improperly calculated the address of local variables when

returning from one function to another function when the function that
  was called was used as part of an expression.
- Fixed: Using Thing_Hate with arg0 (hater) set to 0 from an open script
  could crash.
- Fixed: Some items along ledges in Hexen's MAP32 (Orchard of Lamentations)
  appeared at the bottom of the ledge (and consequently inside it) instead
  of on top of it because the items were placed directly on the lines.
  AActor::LinkToWorldForMapThing() needs to use the original R_PointOnLineSide()
  code to handle situations like this. Previously, it just used the original
  code for straight horizontal/vertical lines and used the new code for
  diagonal lines.
- Fixed: FWadCollection::MergeLumps() used in incorrect realloc.
- Fixed: FPlayList::NextLine() did not properly handle blank lines in the
  playlist.
- Changed: Decals now use lightweight thinkers instead of actors. (76 bytes
  versus 396, so you save 320k if you have 1024 decals present.)
- Fixed: Wads added with pullin were loaded immediately after the IWAD.
  Exec files are now processed immediately before -file but after autoloading
  wads in D_DoomMain().
- Fixed: sdl/i_system.h unconditionally defined SHARE_DIR, preventing
  redefinition from the command line.
- Fixed: The standard way to include SDL.h is <SDL.h>, not <SDL/SDL.h>.
- Fixed: Returned FActiveInterpolation::HashKey()'s return type to size_t,
  avoiding a pointer truncation warning.


SVN r30 (trunk)
This commit is contained in:
Randy Heit 2006-04-12 01:50:09 +00:00
parent d15325e282
commit e815474cbe
29 changed files with 610 additions and 507 deletions

View file

@ -1,3 +1,30 @@
April 11, 2006
- Fixed: ACS improperly calculated the address of local variables when
returning from one function to another function when the function that
was called was used as part of an expression.
- Fixed: Using Thing_Hate with arg0 (hater) set to 0 from an open script
could crash.
- Fixed: Some items along ledges in Hexen's MAP32 (Orchard of Lamentations)
appeared at the bottom of the ledge (and consequently inside it) instead
of on top of it because the items were placed directly on the lines.
AActor::LinkToWorldForMapThing() needs to use the original R_PointOnLineSide()
code to handle situations like this. Previously, it just used the original
code for straight horizontal/vertical lines and used the new code for
diagonal lines.
- Fixed: FWadCollection::MergeLumps() used in incorrect realloc.
- Fixed: FPlayList::NextLine() did not properly handle blank lines in the
playlist.
- Changed: Decals now use lightweight thinkers instead of actors. (76 bytes
versus 396, so you save 320k if you have 1024 decals present.)
- Fixed: Wads added with pullin were loaded immediately after the IWAD.
Exec files are now processed immediately before -file but after autoloading
wads in D_DoomMain().
- Fixed: sdl/i_system.h unconditionally defined SHARE_DIR, preventing
redefinition from the command line.
- Fixed: The standard way to include SDL.h is <SDL.h>, not <SDL/SDL.h>.
- Fixed: Returned FActiveInterpolation::HashKey()'s return type to size_t,
avoiding a pointer truncation warning.
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.

View file

@ -803,10 +803,10 @@ static int PatchThing (int thingy)
else if (stricmp (Line1, "Decal") == 0)
{
stripwhite (Line2);
const FDecal *decal = DecalLibrary.GetDecalByName (Line2);
const FDecalTemplate *decal = DecalLibrary.GetDecalByName (Line2);
if (decal != NULL)
{
info->DecalGenerator = const_cast <FDecal *>(decal);
info->DecalGenerator = const_cast <FDecalTemplate *>(decal);
}
else
{
@ -1429,10 +1429,10 @@ static int PatchWeapon (int weapNum)
else if (stricmp (Line1, "Decal") == 0)
{
stripwhite (Line2);
const FDecal *decal = DecalLibrary.GetDecalByName (Line2);
const FDecalTemplate *decal = DecalLibrary.GetDecalByName (Line2);
if (decal != NULL)
{
info->DecalGenerator = const_cast <FDecal *>(decal);
info->DecalGenerator = const_cast <FDecalTemplate *>(decal);
}
else
{

View file

@ -1919,19 +1919,6 @@ void D_DoomMain (void)
I_SetTitleString (IWADTypeNames[IdentifyVersion ()]);
GameConfig->DoGameSetup (GameNames[gameinfo.gametype]);
// Run automatically executed files
execFiles = new DArgs;
GameConfig->AddAutoexec (execFiles, GameNames[gameinfo.gametype]);
D_MultiExec (execFiles, true);
delete execFiles;
// Run .cfg files at the start of the command line.
execFiles = Args.GatherFiles (NULL, ".cfg", false);
D_MultiExec (execFiles, true);
delete execFiles;
C_ExecCmdLineParams (); // [RH] do all +set commands on the command line
// [RH] zvox.wad - A wad I had intended to be automatically generated
// from Q2's pak0.pak so the female and cyborg player could have
// voices. I never got around to writing the utility to do it, though.
@ -1965,6 +1952,19 @@ void D_DoomMain (void)
D_AddConfigWads (file);
}
// Run automatically executed files
execFiles = new DArgs;
GameConfig->AddAutoexec (execFiles, GameNames[gameinfo.gametype]);
D_MultiExec (execFiles, true);
delete execFiles;
// Run .cfg files at the start of the command line.
execFiles = Args.GatherFiles (NULL, ".cfg", false);
D_MultiExec (execFiles, true);
delete execFiles;
C_ExecCmdLineParams (); // [RH] do all +set commands on the command line
DArgs *files = Args.GatherFiles ("-file", ".wad", true);
if (files->NumArgs() > 0)
{

View file

@ -43,6 +43,7 @@
#include "statnums.h"
#include "templates.h"
#include "r_draw.h"
#include "a_sharedglobal.h"
FDecalLib DecalLibrary;
@ -65,7 +66,7 @@ class FDecalGroup : public FDecalBase
public:
FDecalGroup () : Choices (pr_decalchoice) {}
const FDecal *GetDecal () const;
const FDecalTemplate *GetDecal () const;
void AddDecal (FDecalBase *decal, WORD weight)
{
Choices.AddEntry (decal, weight);
@ -89,7 +90,7 @@ struct FDecalAnimator
{
FDecalAnimator (const char *name);
virtual ~FDecalAnimator ();
virtual DThinker *CreateThinker (AActor *actor) const = 0;
virtual DThinker *CreateThinker (DBaseDecal *actor) const = 0;
char *Name;
};
@ -101,9 +102,9 @@ struct DDecalThinker : public DThinker
DECLARE_CLASS (DDecalThinker, DThinker)
HAS_OBJECT_POINTERS
public:
DDecalThinker (AActor *decal) : DThinker (STAT_DECALTHINKER), TheDecal (decal) {}
DDecalThinker (DBaseDecal *decal) : DThinker (STAT_DECALTHINKER), TheDecal (decal) {}
void Serialize (FArchive &arc);
AActor *TheDecal;
DBaseDecal *TheDecal;
protected:
DDecalThinker () : DThinker (STAT_DECALTHINKER) {}
};
@ -121,7 +122,7 @@ void DDecalThinker::Serialize (FArchive &arc)
struct FDecalFaderAnim : public FDecalAnimator
{
FDecalFaderAnim (const char *name) : FDecalAnimator (name) {}
DThinker *CreateThinker (AActor *actor) const;
DThinker *CreateThinker (DBaseDecal *actor) const;
int DecayStart;
int DecayTime;
@ -131,7 +132,7 @@ class DDecalFader : public DDecalThinker
{
DECLARE_CLASS (DDecalFader, DDecalThinker)
public:
DDecalFader (AActor *decal) : DDecalThinker (decal) {}
DDecalFader (DBaseDecal *decal) : DDecalThinker (decal) {}
void Serialize (FArchive &arc);
void Tick ();
@ -145,7 +146,7 @@ private:
struct FDecalColorerAnim : public FDecalAnimator
{
FDecalColorerAnim (const char *name) : FDecalAnimator (name) {}
DThinker *CreateThinker (AActor *actor) const;
DThinker *CreateThinker (DBaseDecal *actor) const;
int DecayStart;
int DecayTime;
@ -156,7 +157,7 @@ class DDecalColorer : public DDecalThinker
{
DECLARE_CLASS (DDecalColorer, DDecalThinker)
public:
DDecalColorer (AActor *decal) : DDecalThinker (decal) {}
DDecalColorer (DBaseDecal *decal) : DDecalThinker (decal) {}
void Serialize (FArchive &arc);
void Tick ();
@ -171,7 +172,7 @@ private:
struct FDecalStretcherAnim : public FDecalAnimator
{
FDecalStretcherAnim (const char *name) : FDecalAnimator (name) {}
DThinker *CreateThinker (AActor *actor) const;
DThinker *CreateThinker (DBaseDecal *actor) const;
int StretchStart;
int StretchTime;
@ -182,7 +183,7 @@ class DDecalStretcher : public DDecalThinker
{
DECLARE_CLASS (DDecalStretcher, DDecalThinker)
public:
DDecalStretcher (AActor *decal) : DDecalThinker (decal) {}
DDecalStretcher (DBaseDecal *decal) : DDecalThinker (decal) {}
void Serialize (FArchive &arc);
void Tick ();
@ -202,7 +203,7 @@ private:
struct FDecalSliderAnim : public FDecalAnimator
{
FDecalSliderAnim (const char *name) : FDecalAnimator (name) {}
DThinker *CreateThinker (AActor *actor) const;
DThinker *CreateThinker (DBaseDecal *actor) const;
int SlideStart;
int SlideTime;
@ -213,7 +214,7 @@ class DDecalSlider : public DDecalThinker
{
DECLARE_CLASS (DDecalSlider, DDecalThinker)
public:
DDecalSlider (AActor *decal) : DDecalThinker (decal) {}
DDecalSlider (DBaseDecal *decal) : DDecalThinker (decal) {}
void Serialize (FArchive &arc);
void Tick ();
@ -231,7 +232,7 @@ private:
struct FDecalCombinerAnim : public FDecalAnimator
{
FDecalCombinerAnim (const char *name) : FDecalAnimator (name) {}
DThinker *CreateThinker (AActor *actor) const;
DThinker *CreateThinker (DBaseDecal *actor) const;
int FirstAnimator;
int NumAnimators;
@ -282,7 +283,7 @@ enum
DECAL_LOWERDECAL
};
const FDecal *FDecalBase::GetDecal () const
const FDecalTemplate *FDecalBase::GetDecal () const
{
return NULL;
}
@ -420,7 +421,7 @@ void FDecalLib::ParseDecal ()
{
char decalName[64];
byte decalNum;
FDecal newdecal;
FDecalTemplate newdecal;
int code, picnum;
SC_MustGetString ();
@ -488,11 +489,11 @@ void FDecalLib::ParseDecal ()
break;
case DECAL_RANDOMFLIPX:
newdecal.RenderFlags |= FDecal::DECAL_RandomFlipX;
newdecal.RenderFlags |= FDecalTemplate::DECAL_RandomFlipX;
break;
case DECAL_RANDOMFLIPY:
newdecal.RenderFlags |= FDecal::DECAL_RandomFlipY;
newdecal.RenderFlags |= FDecalTemplate::DECAL_RandomFlipY;
break;
case DECAL_FULLBRIGHT:
@ -826,9 +827,9 @@ void FDecalLib::ParseCombiner ()
}
}
void FDecalLib::AddDecal (const char *name, byte num, const FDecal &decal)
void FDecalLib::AddDecal (const char *name, byte num, const FDecalTemplate &decal)
{
FDecal *newDecal = new FDecal;
FDecalTemplate *newDecal = new FDecalTemplate;
*newDecal = decal;
newDecal->Name = copystring (name);
@ -895,7 +896,7 @@ void FDecalLib::AddDecal (FDecalBase *decal)
}
}
const FDecal *FDecalLib::GetDecalByNum (byte num) const
const FDecalTemplate *FDecalLib::GetDecalByNum (byte num) const
{
if (num == 0)
{
@ -909,7 +910,7 @@ const FDecal *FDecalLib::GetDecalByNum (byte num) const
return NULL;
}
const FDecal *FDecalLib::GetDecalByName (const char *name) const
const FDecalTemplate *FDecalLib::GetDecalByName (const char *name) const
{
if (name == NULL)
{
@ -918,7 +919,7 @@ const FDecal *FDecalLib::GetDecalByName (const char *name) const
FDecalBase *base = ScanTreeForName (name, Root);
if (base != NULL)
{
return static_cast<FDecal *>(base);
return static_cast<FDecalTemplate *>(base);
}
return NULL;
}
@ -992,23 +993,23 @@ FDecalBase::~FDecalBase ()
delete[] Name;
}
void FDecal::ApplyToActor (AActor *actor) const
void FDecalTemplate::ApplyToDecal (DBaseDecal *actor) const
{
if (RenderStyle == STYLE_Shaded)
{
actor->SetShade (ShadeColor);
}
actor->Translation = Translation;
actor->xscale = ScaleX;
actor->yscale = ScaleY;
actor->picnum = PicNum;
actor->alpha = Alpha << 1;
actor->XScale = ScaleX;
actor->YScale = ScaleY;
actor->PicNum = PicNum;
actor->Alpha = Alpha << 1;
actor->RenderStyle = RenderStyle;
actor->renderflags = (RenderFlags & ~(DECAL_RandomFlipX|DECAL_RandomFlipY)) |
(actor->renderflags & (RF_RELMASK|RF_CLIPMASK|RF_INVISIBLE|RF_ONESIDED));
actor->RenderFlags = (RenderFlags & ~(DECAL_RandomFlipX|DECAL_RandomFlipY)) |
(actor->RenderFlags & (RF_RELMASK|RF_CLIPMASK|RF_INVISIBLE|RF_ONESIDED));
if (RenderFlags & (DECAL_RandomFlipX|DECAL_RandomFlipY))
{
actor->renderflags ^= pr_decal() &
actor->RenderFlags ^= pr_decal() &
((RenderFlags & (DECAL_RandomFlipX|DECAL_RandomFlipY)) >> 8);
}
if (Animator != NULL)
@ -1017,7 +1018,7 @@ void FDecal::ApplyToActor (AActor *actor) const
}
}
const FDecal *FDecal::GetDecal () const
const FDecalTemplate *FDecalTemplate::GetDecal () const
{
return this;
}
@ -1080,7 +1081,7 @@ FDecalLib::FTranslation *FDecalLib::FTranslation::LocateTranslation (DWORD start
return trans;
}
const FDecal *FDecalGroup::GetDecal () const
const FDecalTemplate *FDecalGroup::GetDecal () const
{
const FDecalBase *decal = Choices.PickEntry ();
const FDecalBase *remember;
@ -1092,7 +1093,7 @@ const FDecal *FDecalGroup::GetDecal () const
remember = decal;
decal = decal->GetDecal ();
} while (decal != remember);
return static_cast<const FDecal *>(decal);
return static_cast<const FDecalTemplate *>(decal);
}
FDecalAnimator::FDecalAnimator (const char *name)
@ -1136,12 +1137,12 @@ void DDecalFader::Tick ()
}
if (StartTrans == -1)
{
StartTrans = TheDecal->alpha;
StartTrans = TheDecal->Alpha;
}
int distanceToEnd = TimeToEndDecay - level.maptime;
int fadeDistance = TimeToEndDecay - TimeToStartDecay;
TheDecal->alpha = Scale (StartTrans, distanceToEnd, fadeDistance);
TheDecal->Alpha = Scale (StartTrans, distanceToEnd, fadeDistance);
if (TheDecal->RenderStyle < STYLE_Translucent)
{
@ -1150,7 +1151,7 @@ void DDecalFader::Tick ()
}
}
DThinker *FDecalFaderAnim::CreateThinker (AActor *actor) const
DThinker *FDecalFaderAnim::CreateThinker (DBaseDecal *actor) const
{
DDecalFader *fader = new DDecalFader (actor);
@ -1176,7 +1177,7 @@ void DDecalStretcher::Serialize (FArchive &arc)
<< bStarted;
}
DThinker *FDecalStretcherAnim::CreateThinker (AActor *actor) const
DThinker *FDecalStretcherAnim::CreateThinker (DBaseDecal *actor) const
{
DDecalStretcher *thinker = new DDecalStretcher (actor);
@ -1219,11 +1220,11 @@ void DDecalStretcher::Tick ()
{
if (bStretchX)
{
TheDecal->xscale = GoalX;
TheDecal->XScale = GoalX;
}
if (bStretchY)
{
TheDecal->yscale = GoalY;
TheDecal->YScale = GoalY;
}
Destroy ();
return;
@ -1231,19 +1232,19 @@ void DDecalStretcher::Tick ()
if (!bStarted)
{
bStarted = true;
StartX = TheDecal->xscale;
StartY = TheDecal->yscale;
StartX = TheDecal->XScale;
StartY = TheDecal->YScale;
}
int distance = level.maptime - TimeToStart;
int maxDistance = TimeToStop - TimeToStart;
if (bStretchX)
{
TheDecal->xscale = StartX + Scale (GoalX - StartX, distance, maxDistance);
TheDecal->XScale = StartX + Scale (GoalX - StartX, distance, maxDistance);
}
if (bStretchY)
{
TheDecal->yscale = StartY + Scale (GoalY - StartY, distance, maxDistance);
TheDecal->YScale = StartY + Scale (GoalY - StartY, distance, maxDistance);
}
}
@ -1261,7 +1262,7 @@ void DDecalSlider::Serialize (FArchive &arc)
<< bStarted;
}
DThinker *FDecalSliderAnim::CreateThinker (AActor *actor) const
DThinker *FDecalSliderAnim::CreateThinker (DBaseDecal *actor) const
{
DDecalSlider *thinker = new DDecalSlider (actor);
@ -1304,7 +1305,7 @@ void DDecalSlider::Tick ()
TheDecal->z = StartY + Scale (DistY, distance, maxDistance);
}
DThinker *FDecalCombinerAnim::CreateThinker (AActor *actor) const
DThinker *FDecalCombinerAnim::CreateThinker (DBaseDecal *actor) const
{
DThinker *thinker = NULL;
@ -1357,7 +1358,7 @@ void DDecalColorer::Tick ()
}
if (StartColor.a == 255)
{
StartColor = TheDecal->alphacolor & 0xffffff;
StartColor = TheDecal->AlphaColor & 0xffffff;
if (StartColor == GoalColor)
{
Destroy ();
@ -1378,7 +1379,7 @@ void DDecalColorer::Tick ()
}
}
DThinker *FDecalColorerAnim::CreateThinker (AActor *actor) const
DThinker *FDecalColorerAnim::CreateThinker (DBaseDecal *actor) const
{
DDecalColorer *Colorer = new DDecalColorer (actor);

View file

@ -40,15 +40,16 @@
#include "tarray.h"
class AActor;
class FDecal;
class FDecalTemplate;
struct FDecalAnimator;
struct TypeInfo;
class DBaseDecal;
class FDecalBase
{
friend class FDecalLib;
public:
virtual const FDecal *GetDecal () const;
virtual const FDecalTemplate *GetDecal () const;
protected:
FDecalBase ();
@ -60,14 +61,14 @@ protected:
TArray<const TypeInfo *> Users; // Which actors generate this decal
};
class FDecal : public FDecalBase
class FDecalTemplate : public FDecalBase
{
friend class FDecalLib;
public:
FDecal () : Translation (0) {}
FDecalTemplate () : Translation (0) {}
void ApplyToActor (AActor *actor) const;
const FDecal *GetDecal () const;
void ApplyToDecal (DBaseDecal *actor) const;
const FDecalTemplate *GetDecal () const;
DWORD ShadeColor;
WORD Translation;
@ -92,8 +93,8 @@ public:
void ReadDecals (); // SC_Open() should have just been called
void ReadAllDecals ();
const FDecal *GetDecalByNum (byte num) const;
const FDecal *GetDecalByName (const char *name) const;
const FDecalTemplate *GetDecalByNum (byte num) const;
const FDecalTemplate *GetDecalByName (const char *name) const;
private:
struct FTranslation;
@ -102,7 +103,7 @@ private:
static FDecalBase *ScanTreeForNum (const BYTE num, FDecalBase *root);
static FDecalBase *ScanTreeForName (const char *name, FDecalBase *root);
FTranslation *GenerateTranslation (DWORD start, DWORD end);
void AddDecal (const char *name, byte num, const FDecal &decal);
void AddDecal (const char *name, byte num, const FDecalTemplate &decal);
void AddDecal (FDecalBase *decal);
FDecalAnimator *FindAnimator (const char *name);

View file

@ -3,7 +3,7 @@
** Implements the actor that represents decals in the level
**
**---------------------------------------------------------------------------
** Copyright 1998-2005 Randy Heit
** Copyright 1998-2006 Randy Heit
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
@ -42,35 +42,91 @@
#include "statnums.h"
#include "c_dispatch.h"
// Decals overload snext and sprev to keep a list of decals attached to a wall.
static fixed_t DecalWidth, DecalLeft, DecalRight;
static fixed_t SpreadZ;
static const DBaseDecal *SpreadSource;
static const FDecalTemplate *SpreadTemplate;
static TArray<side_t *> SpreadStack;
static int ImpactCount;
static DImpactDecal *FirstImpact; // (but not the Second or Third Impact :-)
static DImpactDecal *LastImpact;
CVAR (Bool, cl_spreaddecals, true, CVAR_ARCHIVE)
// They also overload floorclip to be the fractional distance from the
// left edge of the side. This distance is stored as a 2.30 fixed pt number.
IMPLEMENT_STATELESS_ACTOR (ADecal, Any, 9200, 0)
PROP_Flags (MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOGRAVITY)
END_DEFAULTS
IMPLEMENT_CLASS (DBaseDecal)
IMPLEMENT_CLASS (DImpactDecal)
void ADecal::Destroy ()
DBaseDecal::DBaseDecal ()
: DThinker(STAT_DECAL),
WallNext(0), WallPrev(0), x(0), y(0), z(0), AlphaColor(0), Translation(0), PicNum(0xFFFF),
RenderFlags(0), XScale(8), YScale(8), RenderStyle(0), LeftDistance(0), Alpha(0)
{
}
DBaseDecal::DBaseDecal (fixed_t x, fixed_t y, fixed_t z)
: DThinker(STAT_DECAL),
WallNext(0), WallPrev(0), x(x), y(y), z(z), AlphaColor(0), Translation(0), PicNum(0xFFFF),
RenderFlags(0), XScale(8), YScale(8), RenderStyle(0), LeftDistance(0), Alpha(0)
{
}
DBaseDecal::DBaseDecal (const AActor *basis)
: DThinker(STAT_DECAL),
WallNext(0), WallPrev(0), x(basis->x), y(basis->y), z(basis->z), AlphaColor(basis->alphacolor),
Translation(basis->Translation), PicNum(basis->picnum), RenderFlags(basis->renderflags),
XScale(basis->xscale), YScale(basis->yscale), RenderStyle(basis->RenderStyle), LeftDistance(0),
Alpha(basis->alpha)
{
}
DBaseDecal::DBaseDecal (const DBaseDecal *basis)
: DThinker(STAT_DECAL),
WallNext(0), WallPrev(0), x(basis->x), y(basis->y), z(basis->z), AlphaColor(basis->AlphaColor),
Translation(basis->Translation), PicNum(basis->PicNum), RenderFlags(basis->RenderFlags),
XScale(basis->XScale), YScale(basis->YScale), RenderStyle(basis->RenderStyle), LeftDistance(0),
Alpha(basis->Alpha)
{
}
void DBaseDecal::Destroy ()
{
Remove ();
Super::Destroy ();
}
void ADecal::Remove ()
void DBaseDecal::Remove ()
{
AActor **prev = sprev;
AActor *next = snext;
DBaseDecal **prev = WallPrev;
DBaseDecal *next = WallNext;
if (prev && (*prev = next))
next->sprev = prev;
sprev = NULL;
snext = NULL;
next->WallPrev = prev;
WallPrev = NULL;
WallNext = NULL;
}
void ADecal::SerializeChain (FArchive &arc, ADecal **first)
void DBaseDecal::Serialize (FArchive &arc)
{
Super::Serialize (arc);
arc << x << y << z
<< AlphaColor
<< Translation
<< PicNum
<< RenderFlags
<< XScale << YScale
<< RenderStyle
<< LeftDistance
<< Alpha;
}
void DBaseDecal::SerializeChain (FArchive &arc, DBaseDecal **first)
{
DWORD numInChain;
AActor *fresh;
AActor **firstptr = (AActor **)first;
DBaseDecal *fresh;
DBaseDecal **firstptr = first;
if (arc.IsLoading ())
{
@ -80,8 +136,8 @@ void ADecal::SerializeChain (FArchive &arc, ADecal **first)
{
arc << fresh;
*firstptr = fresh;
fresh->sprev = firstptr;
firstptr = &fresh->snext;
fresh->WallPrev = firstptr;
firstptr = &fresh->WallNext;
}
}
else
@ -90,7 +146,7 @@ void ADecal::SerializeChain (FArchive &arc, ADecal **first)
fresh = *firstptr;
while (fresh != NULL)
{
fresh = fresh->snext;
fresh = fresh->WallNext;
++numInChain;
}
arc.WriteCount (numInChain);
@ -98,24 +154,24 @@ void ADecal::SerializeChain (FArchive &arc, ADecal **first)
while (numInChain--)
{
arc << fresh;
fresh = fresh->snext;
fresh = fresh->WallNext;
}
}
}
void ADecal::MoveChain (ADecal *first, fixed_t x, fixed_t y)
void DBaseDecal::MoveChain (DBaseDecal *first, fixed_t x, fixed_t y)
{
while (first != NULL)
{
first->x += x;
first->y += y;
first = (ADecal *)first->snext;
first = (DBaseDecal *)first->WallNext;
}
}
void ADecal::FixForSide (side_t *wall)
void DBaseDecal::FixForSide (side_t *wall)
{
AActor *decal = wall->BoundActors;
DBaseDecal *decal = wall->AttachedDecals;
line_t *line = &lines[wall->linenum];
int wallnum = int(wall - sides);
vertex_t *v1, *v2;
@ -136,83 +192,45 @@ void ADecal::FixForSide (side_t *wall)
while (decal != NULL)
{
decal->x = v1->x + MulScale2 (decal->floorclip, dx);
decal->y = v1->y + MulScale2 (decal->floorclip, dy);
decal = decal->snext;
decal->x = v1->x + MulScale2 (decal->LeftDistance, dx);
decal->y = v1->y + MulScale2 (decal->LeftDistance, dy);
decal = decal->WallNext;
}
}
void ADecal::BeginPlay ()
void DBaseDecal::SetShade (DWORD rgb)
{
Super::BeginPlay ();
// Decals do not think.
ChangeStatNum (STAT_DECAL);
// Find a wall to attach to, and set renderflags to keep
// the decal at its current height. If the decal cannot find a wall
// within 64 units, it destroys itself.
//
// Subclasses can set special1 if they don't want this sticky logic.
if (special1 == 0)
{
DoTrace ();
PalEntry *entry = (PalEntry *)&rgb;
AlphaColor = rgb | (ColorMatcher.Pick (entry->r, entry->g, entry->b) << 24);
}
if (args[0] != 0)
void DBaseDecal::SetShade (int r, int g, int b)
{
const FDecal *decal = DecalLibrary.GetDecalByNum (args[0]);
if (decal != NULL)
{
decal->ApplyToActor (this);
}
}
}
void ADecal::DoTrace ()
{
FTraceResults trace;
Trace (x, y, z, Sector,
finecosine[(angle+ANGLE_180)>>ANGLETOFINESHIFT],
finesine[(angle+ANGLE_180)>>ANGLETOFINESHIFT], 0,
64*FRACUNIT, 0, 0, NULL, trace, TRACE_NoSky);
if (trace.HitType == TRACE_HitWall)
{
x = trace.X;
y = trace.Y;
StickToWall (sides + trace.Line->sidenum[trace.Side]);
}
else
{
Destroy ();
}
AlphaColor = MAKEARGB(ColorMatcher.Pick (r, g, b), r, g, b);
}
// Returns the texture the decal stuck to.
int ADecal::StickToWall (side_t *wall)
int DBaseDecal::StickToWall (side_t *wall)
{
// Stick the decal at the end of the chain so it appears on top
AActor *next, **prev;
DBaseDecal *next, **prev;
prev = (AActor **)&wall->BoundActors;
prev = &wall->AttachedDecals;
while (*prev != NULL)
{
next = *prev;
prev = &next->snext;
prev = &next->WallNext;
}
*prev = this;
snext = NULL;
sprev = prev;
WallNext = NULL;
WallPrev = prev;
/*
snext = wall->BoundActors;
sprev = &wall->BoundActors;
if (snext)
snext->sprev = &snext;
wall->BoundActors = this;
WallNext = wall->AttachedDecals;
WallPrev = &wall->AttachedDecals;
if (WallNext)
WallNext->WallPrev = &WallNext;
wall->AttachedDecals = this;
*/
sector_t *front, *back;
line_t *line;
@ -231,7 +249,7 @@ int ADecal::StickToWall (side_t *wall)
}
if (back == NULL)
{
renderflags |= RF_RELMID;
RenderFlags |= RF_RELMID;
if (line->flags & ML_DONTPEGBOTTOM)
z -= front->floortexz;
else
@ -240,7 +258,7 @@ int ADecal::StickToWall (side_t *wall)
}
else if (back->floorplane.ZatPoint (x, y) >= z)
{
renderflags |= RF_RELLOWER|RF_CLIPLOWER;
RenderFlags |= RF_RELLOWER|RF_CLIPLOWER;
if (line->flags & ML_DONTPEGBOTTOM)
z -= front->ceilingtexz;
else
@ -249,7 +267,7 @@ int ADecal::StickToWall (side_t *wall)
}
else
{
renderflags |= RF_RELUPPER|RF_CLIPUPPER;
RenderFlags |= RF_RELUPPER|RF_CLIPUPPER;
if (line->flags & ML_DONTPEGTOP)
z -= front->ceilingtexz;
else
@ -259,21 +277,10 @@ int ADecal::StickToWall (side_t *wall)
CalcFracPos (wall);
// Face the decal away from the wall
angle = R_PointToAngle2 (0, 0, line->dx, line->dy);
if (line->frontsector == front)
{
angle -= ANGLE_90;
}
else
{
angle += ANGLE_90;
}
return tex;
}
fixed_t ADecal::GetRealZ (const side_t *wall) const
fixed_t DBaseDecal::GetRealZ (const side_t *wall) const
{
const line_t *line = &lines[wall->linenum];
const sector_t *front, *back;
@ -293,7 +300,7 @@ fixed_t ADecal::GetRealZ (const side_t *wall) const
back = front;
}
switch (renderflags & RF_RELMASK)
switch (RenderFlags & RF_RELMASK)
{
default:
return z;
@ -327,16 +334,7 @@ fixed_t ADecal::GetRealZ (const side_t *wall) const
}
}
void ADecal::Relocate (fixed_t ix, fixed_t iy, fixed_t iz)
{
Remove ();
x = ix;
y = iy;
z = iz;
DoTrace ();
}
void ADecal::CalcFracPos (side_t *wall)
void DBaseDecal::CalcFracPos (side_t *wall)
{
line_t *line = &lines[wall->linenum];
int wallnum = int(wall - sides);
@ -358,123 +356,18 @@ void ADecal::CalcFracPos (side_t *wall)
if (abs(dx) > abs(dy))
{
floorclip = SafeDivScale2 (x - v1->x, dx);
LeftDistance = SafeDivScale2 (x - v1->x, dx);
}
else if (dy != 0)
{
floorclip = SafeDivScale2 (y - v1->y, dy);
LeftDistance = SafeDivScale2 (y - v1->y, dy);
}
else
{
floorclip = 0;
LeftDistance = 0;
}
}
static int ImpactCount;
static AActor *FirstImpact; // (but not the Second or Third Impact :-)
static AActor *LastImpact;
CVAR (Bool, cl_spreaddecals, true, CVAR_ARCHIVE)
CUSTOM_CVAR (Int, cl_maxdecals, 1024, CVAR_ARCHIVE)
{
if (self < 0)
{
self = 0;
}
else
{
while (ImpactCount > self)
{
FirstImpact->Destroy ();
}
}
}
// Uses: target points to previous impact decal
// tracer points to next impact decal
//
// Note that this means we can't simply serialize an impact decal as-is
// because doing so when many are present in a level could result in
// a lot of recursion and we would run out of stack. Not nice. So instead,
// the save game code calls AImpactDecal::SerializeAll to serialize a
// list of impact decals.
IMPLEMENT_STATELESS_ACTOR (AImpactDecal, Any, -1, 0)
END_DEFAULTS
void AImpactDecal::SerializeTime (FArchive &arc)
{
if (arc.IsLoading ())
{
ImpactCount = 0;
FirstImpact = LastImpact = NULL;
}
}
void AImpactDecal::Serialize (FArchive &arc)
{
if (arc.IsStoring ())
{
// NULL the next pointer so that the serializer will not follow it
// and possibly run out of stack space. NULLing target isn't
// required; it just makes the archive smaller.
AActor *saved1 = tracer, *saved2 = target;
tracer = NULL;
target = NULL;
Super::Serialize (arc);
tracer = saved1;
target = saved2;
}
else
{
Super::Serialize (arc);
ImpactCount++;
target = LastImpact;
if (target != NULL)
{
target->tracer = this;
}
else
{
FirstImpact = this;
}
LastImpact = this;
}
}
void AImpactDecal::BeginPlay ()
{
special1 = 1; // Don't want ADecal to find a wall to stick to
Super::BeginPlay ();
target = LastImpact;
if (target != NULL)
{
target->tracer = this;
}
else
{
FirstImpact = this;
}
LastImpact = this;
}
AImpactDecal *AImpactDecal::StaticCreate (const char *name, fixed_t x, fixed_t y, fixed_t z, side_t *wall, PalEntry color)
{
if (cl_maxdecals > 0)
{
const FDecal *decal = DecalLibrary.GetDecalByName (name);
if (decal != NULL && (decal = decal->GetDecal()) != NULL)
{
return StaticCreate (decal, x, y, z, wall, color);
}
}
return NULL;
}
static void GetWallStuff (side_t *wall, vertex_t *&v1, fixed_t &ldx, fixed_t &ldy)
{
line_t *line = &lines[wall->linenum];
@ -516,13 +409,7 @@ static side_t *NextWall (const side_t *wall)
return NULL;
}
static fixed_t DecalWidth, DecalLeft, DecalRight;
static fixed_t SpreadZ;
static const AImpactDecal *SpreadSource;
static const FDecal *SpreadDecal;
static TArray<side_t *> SpreadStack;
void AImpactDecal::SpreadLeft (fixed_t r, vertex_t *v1, side_t *feelwall)
void DBaseDecal::SpreadLeft (fixed_t r, vertex_t *v1, side_t *feelwall)
{
fixed_t ldx, ldy;
@ -542,7 +429,7 @@ void AImpactDecal::SpreadLeft (fixed_t r, vertex_t *v1, side_t *feelwall)
x += Scale (r, ldx, wallsize);
y += Scale (r, ldy, wallsize);
r = wallsize + startr;
SpreadSource->CloneSelf (SpreadDecal, x, y, SpreadZ, feelwall);
SpreadSource->CloneSelf (SpreadTemplate, x, y, SpreadZ, feelwall);
SpreadStack.Push (feelwall);
side_t *nextwall = NextWall (feelwall);
@ -566,7 +453,7 @@ void AImpactDecal::SpreadLeft (fixed_t r, vertex_t *v1, side_t *feelwall)
}
}
void AImpactDecal::SpreadRight (fixed_t r, side_t *feelwall, fixed_t wallsize)
void DBaseDecal::SpreadRight (fixed_t r, side_t *feelwall, fixed_t wallsize)
{
vertex_t *v1;
fixed_t x, y, ldx, ldy;
@ -601,47 +488,14 @@ void AImpactDecal::SpreadRight (fixed_t r, side_t *feelwall, fixed_t wallsize)
x -= Scale (r, ldx, wallsize);
y -= Scale (r, ldy, wallsize);
r = DecalRight - r;
SpreadSource->CloneSelf (SpreadDecal, x, y, SpreadZ, feelwall);
SpreadSource->CloneSelf (SpreadTemplate, x, y, SpreadZ, feelwall);
SpreadStack.Push (feelwall);
}
}
AImpactDecal *AImpactDecal::StaticCreate (const FDecal *decal, fixed_t x, fixed_t y, fixed_t z, side_t *wall, PalEntry color)
void DBaseDecal::Spread (const FDecalTemplate *tpl, side_t *wall)
{
AImpactDecal *actor = NULL;
if (decal != NULL && cl_maxdecals > 0 &&
!(wall->Flags & WALLF_NOAUTODECALS))
{
if (decal->LowerDecal)
{
StaticCreate (decal->LowerDecal->GetDecal(), x, y, z, wall);
}
if (ImpactCount >= cl_maxdecals)
{
FirstImpact->Destroy ();
}
ImpactCount++;
actor = Spawn<AImpactDecal> (x, y, z);
if (actor == NULL)
return NULL;
int stickypic = actor->StickToWall (wall);
FTexture *tex = TexMan[stickypic];
if (tex != NULL && tex->bNoDecals)
{
actor->Destroy ();
return NULL;
}
decal->ApplyToActor (actor);
if (color != 0) actor->SetShade (color.r, color.g, color.b);
if (!cl_spreaddecals || actor->picnum == 0xffff)
return actor;
// Spread decal to nearby walls if it does not all fit on this one
FTexture *tex;
vertex_t *v1;
fixed_t rorg, ldx, ldy;
int xscale, yscale;
@ -649,17 +503,17 @@ AImpactDecal *AImpactDecal::StaticCreate (const FDecal *decal, fixed_t x, fixed_
GetWallStuff (wall, v1, ldx, ldy);
rorg = Length (x - v1->x, y - v1->y);
tex = TexMan[actor->picnum];
tex = TexMan[PicNum];
int dwidth = tex->GetWidth ();
xscale = (actor->xscale + 1) << (FRACBITS - 6);
yscale = (actor->yscale + 1) << (FRACBITS - 6);
xscale = (XScale + 1) << (FRACBITS - 6);
yscale = (YScale + 1) << (FRACBITS - 6);
DecalWidth = dwidth * xscale;
DecalLeft = tex->LeftOffset * xscale;
DecalRight = DecalWidth - DecalLeft;
SpreadSource = actor;
SpreadDecal = decal;
SpreadSource = this;
SpreadTemplate = tpl;
SpreadZ = z;
@ -672,49 +526,182 @@ AImpactDecal *AImpactDecal::StaticCreate (const FDecal *decal, fixed_t x, fixed_
Length (lines[wall->linenum].dx, lines[wall->linenum].dy));
SpreadStack.Clear ();
}
return actor;
DBaseDecal *DBaseDecal::CloneSelf (const FDecalTemplate *tpl, fixed_t ix, fixed_t iy, fixed_t iz, side_t *wall) const
{
DBaseDecal *decal = new DBaseDecal(ix, iy, iz);
if (decal != NULL)
{
decal->StickToWall (wall);
tpl->ApplyToDecal (decal);
decal->AlphaColor = AlphaColor;
decal->RenderFlags = (decal->RenderFlags & RF_DECALMASK) |
(this->RenderFlags & ~RF_DECALMASK);
}
return decal;
}
AImpactDecal *AImpactDecal::CloneSelf (const FDecal *decal, fixed_t ix, fixed_t iy, fixed_t iz, side_t *wall) const
CUSTOM_CVAR (Int, cl_maxdecals, 1024, CVAR_ARCHIVE)
{
if (self < 0)
{
self = 0;
}
else
{
while (ImpactCount > self)
{
FirstImpact->Destroy ();
}
}
}
// Uses: target points to previous impact decal
// tracer points to next impact decal
//
// Note that this means we can't simply serialize an impact decal as-is
// because doing so when many are present in a level could result in
// a lot of recursion and we would run out of stack. Not nice. So instead,
// the save game code calls DImpactDecal::SerializeAll to serialize a
// list of impact decals.
void DImpactDecal::SerializeTime (FArchive &arc)
{
if (arc.IsLoading ())
{
ImpactCount = 0;
FirstImpact = LastImpact = NULL;
}
}
void DImpactDecal::Serialize (FArchive &arc)
{
Super::Serialize (arc);
}
DImpactDecal::DImpactDecal ()
: ImpactNext(0), ImpactPrev(0)
{
Link();
}
DImpactDecal::DImpactDecal (fixed_t x, fixed_t y, fixed_t z)
: DBaseDecal (x, y, z),
ImpactNext(0), ImpactPrev(0)
{
Link();
}
void DImpactDecal::Link ()
{
AImpactDecal *actor = NULL;
// [SO] We used to have an 'else' here -- but that means we create an actor without increasing the
// count!!!
// [RH] Moved this before the destroy, just so it can't go negative temporarily.
ImpactCount++;
ImpactPrev = LastImpact;
if (ImpactPrev != NULL)
{
ImpactPrev->ImpactNext = this;
}
else
{
FirstImpact = this;
}
LastImpact = this;
}
DImpactDecal *DImpactDecal::StaticCreate (const char *name, fixed_t x, fixed_t y, fixed_t z, side_t *wall, PalEntry color)
{
if (cl_maxdecals > 0)
{
const FDecalTemplate *tpl = DecalLibrary.GetDecalByName (name);
if (tpl != NULL && (tpl = tpl->GetDecal()) != NULL)
{
return StaticCreate (tpl, x, y, z, wall, color);
}
}
return NULL;
}
DImpactDecal *DImpactDecal::StaticCreate (const FDecalTemplate *tpl, fixed_t x, fixed_t y, fixed_t z, side_t *wall, PalEntry color)
{
DImpactDecal *decal = NULL;
if (tpl != NULL && cl_maxdecals > 0 && !(wall->Flags & WALLF_NOAUTODECALS))
{
if (tpl->LowerDecal)
{
StaticCreate (tpl->LowerDecal->GetDecal(), x, y, z, wall);
}
if (ImpactCount >= cl_maxdecals)
{
FirstImpact->Destroy ();
}
actor = Spawn<AImpactDecal> (ix, iy, iz);
if (actor != NULL)
decal = new DImpactDecal (x, y, z);
int stickypic = decal->StickToWall (wall);
FTexture *tex = TexMan[stickypic];
if (tex != NULL && tex->bNoDecals)
{
actor->StickToWall (wall);
decal->ApplyToActor (actor);
actor->alphacolor = alphacolor;
actor->renderflags = (actor->renderflags & RF_DECALMASK) |
(this->renderflags & ~RF_DECALMASK);
}
return actor;
return NULL;
}
void AImpactDecal::Destroy ()
if (decal == NULL)
{
if (target != NULL)
{
target->tracer = tracer;
return NULL;
}
if (tracer != NULL)
tpl->ApplyToDecal (decal);
if (color != 0)
{
tracer->target = target;
decal->SetShade (color.r, color.g, color.b);
}
if (!cl_spreaddecals || decal->PicNum == 0xffff)
{
return decal;
}
// Spread decal to nearby walls if it does not all fit on this one
decal->Spread (tpl, wall);
}
return decal;
}
DBaseDecal *DImpactDecal::CloneSelf (const FDecalTemplate *tpl, fixed_t ix, fixed_t iy, fixed_t iz, side_t *wall) const
{
if (ImpactCount >= cl_maxdecals)
{
FirstImpact->Destroy ();
}
DImpactDecal *decal = new DImpactDecal(ix, iy, iz);
if (decal != NULL)
{
decal->StickToWall (wall);
tpl->ApplyToDecal (decal);
decal->AlphaColor = AlphaColor;
decal->RenderFlags = (decal->RenderFlags & RF_DECALMASK) |
(this->RenderFlags & ~RF_DECALMASK);
}
return decal;
}
void DImpactDecal::Destroy ()
{
if (ImpactPrev != NULL)
{
ImpactPrev->ImpactNext = ImpactNext;
}
if (ImpactNext != NULL)
{
ImpactNext->ImpactPrev = ImpactPrev;
}
if (LastImpact == this)
{
LastImpact = target;
LastImpact = ImpactPrev;
}
if (FirstImpact == this)
{
FirstImpact = tracer;
FirstImpact = ImpactNext;
}
ImpactCount--;
@ -728,7 +715,7 @@ CCMD (countdecals)
CCMD (countdecalsreal)
{
TThinkerIterator<AImpactDecal> iterator (STAT_DECAL);
TThinkerIterator<DImpactDecal> iterator (STAT_DECAL);
int count = 0;
while (iterator.Next())
@ -761,9 +748,67 @@ CCMD (spray)
{
if (trace.HitType == TRACE_HitWall)
{
AImpactDecal::StaticCreate (argv[1],
DImpactDecal::StaticCreate (argv[1],
trace.X, trace.Y, trace.Z,
sides + trace.Line->sidenum[trace.Side]);
}
}
}
class ADecal : public AActor
{
DECLARE_STATELESS_ACTOR (ADecal, AActor);
public:
void BeginPlay ();
bool DoTrace (DBaseDecal *decal, angle_t angle, sector_t *sec);
};
IMPLEMENT_STATELESS_ACTOR (ADecal, Any, 9200, 0)
END_DEFAULTS
void ADecal::BeginPlay ()
{
Super::BeginPlay ();
// Find a wall to attach to, and set RenderFlags to keep
// the decal at its current height. If the decal cannot find a wall
// within 64 units, it destroys itself.
//
// Subclasses can set special1 if they don't want this sticky logic.
DBaseDecal *decal = new DBaseDecal (this);
if (!DoTrace (decal, angle, Sector))
{
decal->Destroy();
return;
}
if (args[0] != 0)
{
const FDecalTemplate *tpl = DecalLibrary.GetDecalByNum (args[0]);
if (tpl != NULL)
{
tpl->ApplyToDecal (decal);
}
}
}
bool ADecal::DoTrace (DBaseDecal *decal, angle_t angle, sector_t *sec)
{
FTraceResults trace;
Trace (x, y, z, sec,
finecosine[(angle+ANGLE_180)>>ANGLETOFINESHIFT],
finesine[(angle+ANGLE_180)>>ANGLETOFINESHIFT], 0,
64*FRACUNIT, 0, 0, NULL, trace, TRACE_NoSky);
if (trace.HitType == TRACE_HitWall)
{
decal->x = trace.X;
decal->y = trace.Y;
decal->StickToWall (sides + trace.Line->sidenum[trace.Side]);
return true;
}
return false;
}

View file

@ -5,7 +5,7 @@
#include "info.h"
#include "actor.h"
class FDecal;
class FDecalTemplate;
struct vertex_s;
struct side_s;
@ -50,32 +50,57 @@ class ARealGibs : public AActor
struct side_s;
class ADecal : public AActor
class DBaseDecal : public DThinker
{
DECLARE_STATELESS_ACTOR (ADecal, AActor)
DECLARE_CLASS (DBaseDecal, DThinker)
public:
void BeginPlay ();
DBaseDecal ();
DBaseDecal (fixed_t x, fixed_t y, fixed_t z);
DBaseDecal (const AActor *actor);
DBaseDecal (const DBaseDecal *basis);
void Serialize (FArchive &arc);
void Destroy ();
int StickToWall (side_s *wall);
void Relocate (fixed_t x, fixed_t y, fixed_t z);
fixed_t GetRealZ (const side_s *wall) const;
void SetShade (DWORD rgb);
void SetShade (int r, int g, int b);
void Spread (const FDecalTemplate *tpl, side_s *wall);
static void SerializeChain (FArchive &arc, ADecal **firstptr);
static void MoveChain (ADecal *first, fixed_t x, fixed_t y);
static void SerializeChain (FArchive &arc, DBaseDecal **firstptr);
static void MoveChain (DBaseDecal *first, fixed_t x, fixed_t y);
static void FixForSide (side_s *side);
DBaseDecal *WallNext, **WallPrev;
fixed_t x, y, z;
DWORD AlphaColor;
WORD Translation;
WORD PicNum;
WORD RenderFlags;
BYTE XScale, YScale;
BYTE RenderStyle;
fixed_t LeftDistance;
fixed_t Alpha;
protected:
virtual DBaseDecal *CloneSelf (const FDecalTemplate *tpl, fixed_t x, fixed_t y, fixed_t z, side_s *wall) const;
void CalcFracPos (side_s *wall);
void DoTrace ();
void Remove ();
static void SpreadLeft (fixed_t r, vertex_s *v1, side_s *feelwall);
static void SpreadRight (fixed_t r, side_s *feelwall, fixed_t wallsize);
};
class AImpactDecal : public ADecal
class DImpactDecal : public DBaseDecal
{
DECLARE_STATELESS_ACTOR (AImpactDecal, ADecal)
DECLARE_CLASS (DImpactDecal, DBaseDecal)
public:
static AImpactDecal *StaticCreate (const char *name, fixed_t x, fixed_t y, fixed_t z, side_s *wall, PalEntry color=0);
static AImpactDecal *StaticCreate (const FDecal *decal, fixed_t x, fixed_t y, fixed_t z, side_s *wall, PalEntry color=0);
DImpactDecal (fixed_t x, fixed_t y, fixed_t z);
DImpactDecal (side_s *wall, const FDecalTemplate *templ);
static DImpactDecal *StaticCreate (const char *name, fixed_t x, fixed_t y, fixed_t z, side_s *wall, PalEntry color=0);
static DImpactDecal *StaticCreate (const FDecalTemplate *tpl, fixed_t x, fixed_t y, fixed_t z, side_s *wall, PalEntry color=0);
void BeginPlay ();
void Destroy ();
@ -83,10 +108,14 @@ public:
void Serialize (FArchive &arc);
static void SerializeTime (FArchive &arc);
DImpactDecal *ImpactNext, *ImpactPrev;
protected:
AImpactDecal *CloneSelf (const FDecal *decal, fixed_t x, fixed_t y, fixed_t z, side_s *wall) const;
static void SpreadLeft (fixed_t r, vertex_s *v1, side_s *feelwall);
static void SpreadRight (fixed_t r, side_s *feelwall, fixed_t wallsize);
DBaseDecal *CloneSelf (const FDecalTemplate *tpl, fixed_t x, fixed_t y, fixed_t z, side_s *wall) const;
private:
DImpactDecal();
void Link();
};
class AWaterSplashBase : public AActor

View file

@ -77,11 +77,11 @@ FRandom pr_acs ("ACS");
struct CallReturn
{
int ReturnAddress;
ScriptFunction *ReturnFunction;
FBehavior *ReturnModule;
BYTE bDiscardResult;
BYTE Pad[3];
SDWORD *ReturnLocals;
int ReturnAddress;
int bDiscardResult;
};
static SDWORD Stack[STACK_SIZE];
@ -2330,6 +2330,7 @@ int DLevelScript::RunScript ()
int i;
ScriptFunction *func;
FBehavior *module = activeBehavior;
SDWORD *mylocals;
funcnum = NEXTBYTE;
func = activeBehavior->GetFunction (funcnum, module);
@ -2345,6 +2346,7 @@ int DLevelScript::RunScript ()
state = SCRIPT_PleaseRemove;
break;
}
mylocals = locals;
// The function's first argument is also its first local variable.
locals = &Stack[sp - func->ArgCount];
// Make space on the stack for any other variables the function uses.
@ -2356,6 +2358,7 @@ int DLevelScript::RunScript ()
((CallReturn *)&Stack[sp])->ReturnAddress = activeBehavior->PC2Ofs (pc);
((CallReturn *)&Stack[sp])->ReturnFunction = activeFunction;
((CallReturn *)&Stack[sp])->ReturnModule = activeBehavior;
((CallReturn *)&Stack[sp])->ReturnLocals = mylocals;
((CallReturn *)&Stack[sp])->bDiscardResult = (pcd == PCD_CALLDISCARD);
sp += sizeof(CallReturn)/sizeof(int);
pc = module->Ofs2PC (func->Address);
@ -2381,19 +2384,12 @@ int DLevelScript::RunScript ()
}
sp -= sizeof(CallReturn)/sizeof(int);
retState = (CallReturn *)&Stack[sp];
sp = locals - Stack;
pc = retState->ReturnModule->Ofs2PC (retState->ReturnAddress);
sp -= activeFunction->ArgCount + activeFunction->LocalCount;
activeFunction = retState->ReturnFunction;
activeBehavior = retState->ReturnModule;
fmt = activeBehavior->GetFormat();
if (activeFunction == NULL)
{
locals = localvars;
}
else
{
locals = &Stack[sp - activeFunction->ArgCount - activeFunction->LocalCount - sizeof(CallReturn)/sizeof(int)];
}
locals = retState->ReturnLocals;
if (!retState->bDiscardResult)
{
Stack[sp++] = value;
@ -3393,7 +3389,7 @@ int DLevelScript::RunScript ()
static const char logbar[] = "\n<------------------------------->\n";
workreal[0] = '\x1c';
workreal[1] = color >= CR_BRICK && color <= CR_YELLOW ? 'A' + color : '-';
workreal[1] = color >= CR_BRICK && color <= CR_YELLOW ? color + 'A' : '-';
AddToConsole (-1, bar);
AddToConsole (-1, workreal);
AddToConsole (-1, bar);

View file

@ -1137,7 +1137,7 @@ FUNC(LS_Thing_Hate)
if (arg0 == 0)
{
if (it->player)
if (it != NULL && it->player != NULL)
{
// Players cannot have their attitudes set
return false;

View file

@ -2860,7 +2860,7 @@ void P_TraceBleed (int damage, fixed_t x, fixed_t y, fixed_t z, AActor *actor, a
bloodcolor.a=1;
}
AImpactDecal::StaticCreate (bloodType,
DImpactDecal::StaticCreate (bloodType,
bleedtrace.X, bleedtrace.Y, bleedtrace.Z,
sides + bleedtrace.Line->sidenum[bleedtrace.Side],
bloodcolor);
@ -4492,7 +4492,7 @@ void SpawnShootDecal (AActor *t1, const FTraceResults &trace)
}
if (decalbase != NULL)
{
AImpactDecal::StaticCreate (decalbase->GetDecal (),
DImpactDecal::StaticCreate (decalbase->GetDecal (),
trace.X, trace.Y, trace.Z, sides + trace.Line->sidenum[trace.Side]);
}
}

View file

@ -434,12 +434,59 @@ void AActor::LinkToWorld (sector_t *sec)
// Emulate buggy PointOnLineSide and fix actors that lie on
// lines to compensate for some IWAD maps.
//
static int R_PointOnSideSlow (fixed_t x, fixed_t y, node_t *node)
{
// [RH] This might have been faster than two multiplies and an
// add on a 386/486, but it certainly isn't on anything newer than that.
fixed_t dx;
fixed_t dy;
fixed_t left;
fixed_t right;
if (!node->dx)
{
if (x <= node->x)
return node->dy > 0;
return node->dy < 0;
}
if (!node->dy)
{
if (y <= node->y)
return node->dx < 0;
return node->dx > 0;
}
dx = (x - node->x);
dy = (y - node->y);
// Try to quickly decide by looking at sign bits.
if ( (node->dy ^ node->dx ^ dx ^ dy)&0x80000000 )
{
if ( (node->dy ^ dx) & 0x80000000 )
{
// (left is negative)
return 1;
}
return 0;
}
left = FixedMul ( node->dy>>FRACBITS , dx );
right = FixedMul ( dy , node->dx>>FRACBITS );
if (right < left)
{
// front side
return 0;
}
// back side
return 1;
}
sector_t *AActor::LinkToWorldForMapThing ()
{
node_t *node;
int side;
node = nodes + numnodes - 1;
node_t *node = nodes + numnodes - 1;
do
{
@ -451,25 +498,7 @@ sector_t *AActor::LinkToWorldForMapThing ()
// that lies directly on a line should always be
// considered as "in front" of the line. The orientation
// of the line should be irrelevant.
if (node->dx == 0)
{
if (x <= node->x)
side = node->dy > 0;
else
side = node->dy < 0;
}
else if (node->dy == 0)
{
if (y <= node->y)
side = node->dx < 0;
else
side = node->dx > 0;
}
else
{
side = R_PointOnSide (x, y, node);
}
node = (node_t *)node->children[side];
node = (node_t *)node->children[R_PointOnSideSlow (x, y, node)];
}
while (!((size_t)node & 1));

View file

@ -986,7 +986,7 @@ void P_ExplodeMissile (AActor *mo, line_t *line)
y = line->v1->y + MulScale30 (line->dy, frac);
z = mo->z;
AImpactDecal::StaticCreate (base->GetDecal (),
DImpactDecal::StaticCreate (base->GetDecal (),
x, y, z, sides + line->sidenum[side]);
}
}

View file

@ -179,7 +179,7 @@ void P_SerializeWorld (FArchive &arc)
<< si->Flags
<< si->LeftSide
<< si->RightSide;
ADecal::SerializeChain (arc, &si->BoundActors);
DBaseDecal::SerializeChain (arc, &si->AttachedDecals);
}
}
@ -212,7 +212,7 @@ void P_SerializeWorld (FArchive &arc)
void P_SerializeThinkers (FArchive &arc, bool hubLoad)
{
AImpactDecal::SerializeTime (arc);
DImpactDecal::SerializeTime (arc);
DThinker::SerializeAll (arc, hubLoad);
}

View file

@ -610,7 +610,7 @@ static bool DoGroupForOne (AActor *victim, AActor *source, AActor *dest, bool fl
}
#if 0
static void MoveTheDecal (ADecal *decal, fixed_t z, AActor *source, AActor *dest)
static void MoveTheDecal (DBaseDecal *decal, fixed_t z, AActor *source, AActor *dest)
{
int an = (dest->angle - source->angle) >> ANGLETOFINESHIFT;
fixed_t offX = decal->x - source->x;

View file

@ -821,9 +821,9 @@ void DoMovePolyobj (polyobj_t *po, int x, int y)
linedef->bbox[BOXLEFT] += x;
linedef->bbox[BOXRIGHT] += x;
if (linedef->sidenum[0] != NO_SIDE)
ADecal::MoveChain (sides[linedef->sidenum[0]].BoundActors, x, y);
DBaseDecal::MoveChain (sides[linedef->sidenum[0]].AttachedDecals, x, y);
if (linedef->sidenum[1] != NO_SIDE)
ADecal::MoveChain (sides[linedef->sidenum[1]].BoundActors, x, y);
DBaseDecal::MoveChain (sides[linedef->sidenum[1]].AttachedDecals, x, y);
linedef->validcount = validcount;
}
for (veryTempSeg = po->segs; veryTempSeg != segList; veryTempSeg++)
@ -910,9 +910,9 @@ BOOL PO_RotatePolyobj (int num, angle_t angle)
UpdateSegBBox(*segList);
line_t *line = (*segList)->linedef;
if (line->sidenum[0] != NO_SIDE)
ADecal::FixForSide (&sides[line->sidenum[0]]);
DBaseDecal::FixForSide (&sides[line->sidenum[0]]);
if (line->sidenum[1] != NO_SIDE)
ADecal::FixForSide (&sides[line->sidenum[1]]);
DBaseDecal::FixForSide (&sides[line->sidenum[1]]);
line->validcount = validcount;
}
}
@ -934,9 +934,9 @@ BOOL PO_RotatePolyobj (int num, angle_t angle)
UpdateSegBBox(*segList);
line_t *line = (*segList)->linedef;
if (line->sidenum[0] != NO_SIDE)
ADecal::FixForSide (&sides[line->sidenum[0]]);
DBaseDecal::FixForSide (&sides[line->sidenum[0]]);
if (line->sidenum[1] != NO_SIDE)
ADecal::FixForSide (&sides[line->sidenum[1]]);
DBaseDecal::FixForSide (&sides[line->sidenum[1]]);
line->validcount = validcount;
}
}

View file

@ -379,7 +379,7 @@ struct zone_t
// The SideDef.
//
class ADecal;
class DBaseDecal;
enum
{
@ -394,7 +394,7 @@ struct side_s
fixed_t textureoffset; // add this to the calculated texture column
fixed_t rowoffset; // add this to the calculated texture top
sector_t* sector; // Sector the SideDef is facing.
ADecal* BoundActors; // [RH] Decals bound to the wall
DBaseDecal* AttachedDecals; // [RH] Decals bound to the wall
short toptexture, bottomtexture, midtexture; // texture indices
WORD linenum;
DWORD LeftSide, RightSide; // [RH] Group walls into loops

View file

@ -1774,9 +1774,9 @@ void FActiveInterpolation::DoAnInterpolation (fixed_t smoothratio)
*adr2 = oldipos[1] + FixedMul (pos - oldipos[1], smoothratio);
}
unsigned FActiveInterpolation::HashKey (EInterpType type, void *interptr)
size_t FActiveInterpolation::HashKey (EInterpType type, void *interptr)
{
return (unsigned)type * ((unsigned)interptr>>5);
return (size_t)type * ((size_t)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)
{
unsigned hash = HashKey (type, interptr) % INTERPOLATION_BUCKETS;
size_t 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 unsigned HashKey(EInterpType type, void *interptr);
static size_t HashKey(EInterpType type, void *interptr);
static FActiveInterpolation *FindInterpolation(EInterpType, void *interptr, FActiveInterpolation **&interp_p);
friend void updateinterpolations();

View file

@ -43,6 +43,7 @@
#include "m_swap.h"
#include "w_wad.h"
#include "stats.h"
#include "a_sharedglobal.h"
#define WALLYREPEAT 8
@ -123,7 +124,7 @@ FTexture *rw_pic;
static short *maskedtexturecol;
static FTexture *WallSpriteTile;
static void R_RenderBoundWallSprite (AActor *first, drawseg_t *clipper, int pass);
static void R_RenderDecal (DBaseDecal *first, drawseg_t *clipper, int pass);
static void WallSpriteColumn (void (*drawfunc)(const BYTE *column, const FTexture::Span *spans));
//=============================================================================
@ -1333,11 +1334,9 @@ void R_StoreWallRange (int start, int stop)
}
// [RH] Draw any decals bound to the seg
AActor *decal = (AActor *)curline->sidedef->BoundActors;
while (decal != NULL)
for (DBaseDecal *decal = curline->sidedef->AttachedDecals; decal != NULL; decal = decal->WallNext)
{
R_RenderBoundWallSprite (decal, ds_p, 0);
decal = decal->snext;
R_RenderDecal (decal, ds_p, 0);
}
ds_p++;
@ -1767,9 +1766,7 @@ void PrepLWall (fixed_t *lwall, fixed_t walxrepeat)
// = 1: drawing masked textures (including sprites)
// Currently, only pass = 0 is done or used
static AActor *DecalActorForDebug;
static void R_RenderBoundWallSprite (AActor *actor, drawseg_t *clipper, int pass)
static void R_RenderDecal (DBaseDecal *decal, drawseg_t *clipper, int pass)
{
fixed_t lx, ly, lx2, ly2;
int x1, x2;
@ -1780,72 +1777,62 @@ static void R_RenderBoundWallSprite (AActor *actor, drawseg_t *clipper, int pass
int needrepeat = 0;
sector_t *front, *back;
if (actor->renderflags & RF_INVISIBLE || !viewactive)
if (decal->RenderFlags & RF_INVISIBLE || !viewactive || decal->PicNum == 0xFFFF)
return;
DecalActorForDebug = actor;
// Determine actor z
zpos = actor->z;
zpos = decal->z;
front = curline->frontsector;
back = (curline->backsector != NULL) ? curline->backsector : curline->frontsector;
switch (actor->renderflags & RF_RELMASK)
switch (decal->RenderFlags & RF_RELMASK)
{
default:
zpos = actor->z;
zpos = decal->z;
break;
case RF_RELUPPER:
if (curline->linedef->flags & ML_DONTPEGTOP)
{
zpos = actor->z + front->ceilingtexz;
zpos = decal->z + front->ceilingtexz;
}
else
{
zpos = actor->z + back->ceilingtexz;
zpos = decal->z + back->ceilingtexz;
}
break;
case RF_RELLOWER:
if (curline->linedef->flags & ML_DONTPEGBOTTOM)
{
zpos = actor->z + front->ceilingtexz;
zpos = decal->z + front->ceilingtexz;
}
else
{
zpos = actor->z + back->floortexz;
zpos = decal->z + back->floortexz;
}
break;
case RF_RELMID:
if (curline->linedef->flags & ML_DONTPEGBOTTOM)
{
zpos = actor->z + front->floortexz;
zpos = decal->z + front->floortexz;
}
else
{
zpos = actor->z + front->ceilingtexz;
zpos = decal->z + front->ceilingtexz;
}
}
xscale = actor->xscale + 1;
yscale = actor->yscale + 1;
xscale = decal->XScale + 1;
yscale = decal->YScale + 1;
WallSpriteTile = TexMan(decal->PicNum);
flipx = decal->RenderFlags & RF_XFLIP;
if (actor->picnum != 0xffff)
{
WallSpriteTile = TexMan(actor->picnum);
flipx = actor->renderflags & RF_XFLIP;
}
else
{
//WallSpriteTile = SpriteFrames[sprites[actor->sprite].spriteframes + actor->frame].lump[0];
//flipx = SpriteFrames[sprites[actor->sprite].spriteframes + actor->frame].flip & 1;
return;
}
if (WallSpriteTile->UseType == FTexture::TEX_Null)
{
return;
}
// Determine left and right edges of sprite. Since this sprite is bound
// to a wall, we use the wall's angle instead of the actor's. This is
// to a wall, we use the wall's angle instead of the decal's. This is
// pretty much the same as what R_AddLine() does.
x2 = WallSpriteTile->GetWidth();
@ -1856,10 +1843,10 @@ static void R_RenderBoundWallSprite (AActor *actor, drawseg_t *clipper, int pass
x2 *= xscale;
angle_t ang = R_PointToAngle2 (curline->v1->x, curline->v1->y, curline->v2->x, curline->v2->y) >> ANGLETOFINESHIFT;
lx = actor->x - MulScale6 (x1, finecosine[ang]) - viewx;
lx2 = actor->x + MulScale6 (x2, finecosine[ang]) - viewx;
ly = actor->y - MulScale6 (x1, finesine[ang]) - viewy;
ly2 = actor->y + MulScale6 (x2, finesine[ang]) - viewy;
lx = decal->x - MulScale6 (x1, finecosine[ang]) - viewx;
lx2 = decal->x + MulScale6 (x2, finecosine[ang]) - viewx;
ly = decal->y - MulScale6 (x1, finesine[ang]) - viewy;
ly2 = decal->y + MulScale6 (x2, finesine[ang]) - viewy;
WallTX1 = DMulScale20 (lx, viewsin, -ly, viewcos);
WallTX2 = DMulScale20 (lx2, viewsin, -ly2, viewcos);
@ -1933,7 +1920,7 @@ static void R_RenderBoundWallSprite (AActor *actor, drawseg_t *clipper, int pass
WallDepthOrg = -WallUoverZstep * WallTMapScale2;
// Get the top and bottom clipping arrays
switch (actor->renderflags & RF_CLIPMASK)
switch (decal->RenderFlags & RF_CLIPMASK)
{
case RF_CLIPFULL:
if (curline->backsector == NULL)
@ -2031,13 +2018,13 @@ static void R_RenderBoundWallSprite (AActor *actor, drawseg_t *clipper, int pass
dc_colormap = basecolormap + fixedlightlev;
else if (fixedcolormap)
dc_colormap = fixedcolormap;
else if (!foggy && (actor->renderflags & RF_FULLBRIGHT))
else if (!foggy && (decal->RenderFlags & RF_FULLBRIGHT))
dc_colormap = basecolormap;
else
calclighting = true;
// Draw it
if (actor->renderflags & RF_YFLIP)
if (decal->RenderFlags & RF_YFLIP)
{
sprflipvert = true;
yscale = -yscale;
@ -2055,7 +2042,7 @@ static void R_RenderBoundWallSprite (AActor *actor, drawseg_t *clipper, int pass
dc_x = x1;
ESPSResult mode;
mode = R_SetPatchStyle (actor->RenderStyle, actor->alpha, actor->Translation, actor->alphacolor);
mode = R_SetPatchStyle (decal->RenderStyle, decal->Alpha, decal->Translation, decal->AlphaColor);
if (mode == DontDraw)
{
@ -2130,23 +2117,6 @@ static void R_RenderBoundWallSprite (AActor *actor, drawseg_t *clipper, int pass
static void WallSpriteColumn (void (*drawfunc)(const BYTE *column, const FTexture::Span *spans))
{
unsigned int texturecolumn = lwall[dc_x] >> FRACBITS;
#if 0
if (texturecolumn >= (unsigned)WallSpriteTile->GetWidth())
{
I_FatalError ("WallSpriteColumn tried to draw part of a decal that didn't exist.\n"
"Please report all of the following information, because\n"
"I want to get this fixed, yet I just can't get it happen to me:\n\n"
"%d->%d/%d"
" %s %04x %d\n"
"%d %d %d\n"
"%d %d %d %u\n",
dc_x, texturecolumn, TileCache[WallSpriteTile]->width,
WallSpriteTile->Name, DecalActorForDebug->renderflags, DecalActorForDebug->RenderStyle,
DecalActorForDebug->x, DecalActorForDebug->y, DecalActorForDebug->z,
viewx, viewy, viewz, viewangle);
texturecolumn = TileCache[WallSpriteTile]->width-1;
}
#endif
dc_iscale = MulScale16 (swall[dc_x], rw_offset);
spryscale = SafeDivScale32 (1, dc_iscale);
if (sprflipvert)

View file

@ -119,7 +119,7 @@ bool FPlayList::NextLine (FILE *file, char *buffer, int n)
if (NULL == fgets (buffer, n, file))
return false;
for (skipper = buffer; *skipper <= ' '; skipper++)
for (skipper = buffer; *skipper != 0 && *skipper <= ' '; skipper++)
;
} while (*skipper == '#' || *skipper == 0);
@ -161,6 +161,7 @@ int FPlayList::SetPosition (int position)
{
Position = position;
}
DPrintf ("Playlist position set to %d\n", Position);
return Position;
}
@ -175,6 +176,7 @@ int FPlayList::Advance ()
{
Position = 0;
}
DPrintf ("Playlist advanced to song %d\n", Position);
return Position;
}
@ -184,6 +186,7 @@ int FPlayList::Backup ()
{
Position = NumSongs - 1;
}
DPrintf ("Playlist backed up to song %d\n", Position);
return Position;
}

View file

@ -32,7 +32,7 @@
**
*/
#include <SDL/SDL.h>
#include <SDL.h>
#include "hardware.h"
#include "i_video.h"

View file

@ -1,4 +1,4 @@
#include <SDL/SDL.h>
#include <SDL.h>
#include "doomtype.h"
#include "c_dispatch.h"
#include "doomdef.h"

View file

@ -20,7 +20,7 @@
//
//-----------------------------------------------------------------------------
#include <SDL/SDL.h>
#include <SDL.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>

View file

@ -41,7 +41,7 @@
#include "doomerrors.h"
#include <math.h>
#include "SDL/SDL.h"
#include "SDL.h"
#include "doomtype.h"
#include "version.h"
#include "doomdef.h"

View file

@ -30,7 +30,9 @@
#include "d_ticcmd.h"
#include "d_event.h"
#ifndef SHARE_DIR
#define SHARE_DIR "/usr/local/share/"
#endif
// Index values into the LanguageIDs array
enum

View file

@ -12,7 +12,7 @@
#include "sdlvideo.h"
#include <SDL/SDL.h>
#include <SDL.h>
// MACROS ------------------------------------------------------------------

View file

@ -414,7 +414,7 @@ bool TimiditySong::LaunchTimidity ()
// Tell Timidity whether it should loop or not
CommandLine[LoopPos] = m_Looping ? 'l' : ' ';
DPrintf ("cmd: \x1cG%s\n", CommandLine);
DPrintf ("cmd: \x1cG%s\n", CommandLine.GetChars());
#ifdef _WIN32
STARTUPINFO startup = { sizeof(startup), };

View file

@ -44,12 +44,12 @@ enum { GAMEVERSION = 205 };
// Note that SAVEVER is not directly comparable to VERSION.
// SAVESIG should match SAVEVER.
#define SAVEVER 231
#define SAVESIG "ZDOOMSAVE231"
#define SAVESIG "ZDOOMSAVE232"
// 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 231 // Used by 2.0.99
#define MINSAVEVER 232 // Used by 2.0.99
// The maximum length of one save game description for the menus.
#define SAVESTRINGSIZE 24

View file

@ -968,8 +968,8 @@ int FWadCollection::MergeLumps (const char *start, const char *end, int space)
if (newlumps)
{
if (size_t(oldlumps + newlumps) > NumLumps)
LumpInfo = (LumpRecord *)Realloc (LumpInfo, oldlumps + newlumps);
if (size_t(oldlumps + newlumps) >= NumLumps)
LumpInfo = (LumpRecord *)Realloc (LumpInfo, (oldlumps + newlumps + 1) * sizeof(LumpRecord));
memcpy (LumpInfo + oldlumps, newlumpinfos, sizeof(LumpRecord) * newlumps);
markerpos = oldlumps;