- 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) April 11, 2006 (Changes by Graf Zahl)
- Fixed: Strife's dialogs don't give weapons to the player he already has. - 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 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) else if (stricmp (Line1, "Decal") == 0)
{ {
stripwhite (Line2); stripwhite (Line2);
const FDecal *decal = DecalLibrary.GetDecalByName (Line2); const FDecalTemplate *decal = DecalLibrary.GetDecalByName (Line2);
if (decal != NULL) if (decal != NULL)
{ {
info->DecalGenerator = const_cast <FDecal *>(decal); info->DecalGenerator = const_cast <FDecalTemplate *>(decal);
} }
else else
{ {
@ -1429,10 +1429,10 @@ static int PatchWeapon (int weapNum)
else if (stricmp (Line1, "Decal") == 0) else if (stricmp (Line1, "Decal") == 0)
{ {
stripwhite (Line2); stripwhite (Line2);
const FDecal *decal = DecalLibrary.GetDecalByName (Line2); const FDecalTemplate *decal = DecalLibrary.GetDecalByName (Line2);
if (decal != NULL) if (decal != NULL)
{ {
info->DecalGenerator = const_cast <FDecal *>(decal); info->DecalGenerator = const_cast <FDecalTemplate *>(decal);
} }
else else
{ {

View file

@ -1919,19 +1919,6 @@ void D_DoomMain (void)
I_SetTitleString (IWADTypeNames[IdentifyVersion ()]); I_SetTitleString (IWADTypeNames[IdentifyVersion ()]);
GameConfig->DoGameSetup (GameNames[gameinfo.gametype]); 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 // [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 // 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. // voices. I never got around to writing the utility to do it, though.
@ -1965,6 +1952,19 @@ void D_DoomMain (void)
D_AddConfigWads (file); 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); DArgs *files = Args.GatherFiles ("-file", ".wad", true);
if (files->NumArgs() > 0) if (files->NumArgs() > 0)
{ {

View file

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

View file

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

View file

@ -3,7 +3,7 @@
** Implements the actor that represents decals in the level ** Implements the actor that represents decals in the level
** **
**--------------------------------------------------------------------------- **---------------------------------------------------------------------------
** Copyright 1998-2005 Randy Heit ** Copyright 1998-2006 Randy Heit
** All rights reserved. ** All rights reserved.
** **
** Redistribution and use in source and binary forms, with or without ** Redistribution and use in source and binary forms, with or without
@ -42,35 +42,91 @@
#include "statnums.h" #include "statnums.h"
#include "c_dispatch.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 // 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. // left edge of the side. This distance is stored as a 2.30 fixed pt number.
IMPLEMENT_STATELESS_ACTOR (ADecal, Any, 9200, 0) IMPLEMENT_CLASS (DBaseDecal)
PROP_Flags (MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOGRAVITY) IMPLEMENT_CLASS (DImpactDecal)
END_DEFAULTS
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 (); Remove ();
Super::Destroy (); Super::Destroy ();
} }
void ADecal::Remove () void DBaseDecal::Remove ()
{ {
AActor **prev = sprev; DBaseDecal **prev = WallPrev;
AActor *next = snext; DBaseDecal *next = WallNext;
if (prev && (*prev = next)) if (prev && (*prev = next))
next->sprev = prev; next->WallPrev = prev;
sprev = NULL; WallPrev = NULL;
snext = 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; DWORD numInChain;
AActor *fresh; DBaseDecal *fresh;
AActor **firstptr = (AActor **)first; DBaseDecal **firstptr = first;
if (arc.IsLoading ()) if (arc.IsLoading ())
{ {
@ -80,8 +136,8 @@ void ADecal::SerializeChain (FArchive &arc, ADecal **first)
{ {
arc << fresh; arc << fresh;
*firstptr = fresh; *firstptr = fresh;
fresh->sprev = firstptr; fresh->WallPrev = firstptr;
firstptr = &fresh->snext; firstptr = &fresh->WallNext;
} }
} }
else else
@ -90,7 +146,7 @@ void ADecal::SerializeChain (FArchive &arc, ADecal **first)
fresh = *firstptr; fresh = *firstptr;
while (fresh != NULL) while (fresh != NULL)
{ {
fresh = fresh->snext; fresh = fresh->WallNext;
++numInChain; ++numInChain;
} }
arc.WriteCount (numInChain); arc.WriteCount (numInChain);
@ -98,24 +154,24 @@ void ADecal::SerializeChain (FArchive &arc, ADecal **first)
while (numInChain--) while (numInChain--)
{ {
arc << fresh; 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) while (first != NULL)
{ {
first->x += x; first->x += x;
first->y += y; 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]; line_t *line = &lines[wall->linenum];
int wallnum = int(wall - sides); int wallnum = int(wall - sides);
vertex_t *v1, *v2; vertex_t *v1, *v2;
@ -136,83 +192,45 @@ void ADecal::FixForSide (side_t *wall)
while (decal != NULL) while (decal != NULL)
{ {
decal->x = v1->x + MulScale2 (decal->floorclip, dx); decal->x = v1->x + MulScale2 (decal->LeftDistance, dx);
decal->y = v1->y + MulScale2 (decal->floorclip, dy); decal->y = v1->y + MulScale2 (decal->LeftDistance, dy);
decal = decal->snext; decal = decal->WallNext;
} }
} }
void ADecal::BeginPlay () void DBaseDecal::SetShade (DWORD rgb)
{ {
Super::BeginPlay (); PalEntry *entry = (PalEntry *)&rgb;
AlphaColor = rgb | (ColorMatcher.Pick (entry->r, entry->g, entry->b) << 24);
// 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 ();
}
if (args[0] != 0)
{
const FDecal *decal = DecalLibrary.GetDecalByNum (args[0]);
if (decal != NULL)
{
decal->ApplyToActor (this);
}
}
} }
void ADecal::DoTrace () void DBaseDecal::SetShade (int r, int g, int b)
{ {
FTraceResults trace; AlphaColor = MAKEARGB(ColorMatcher.Pick (r, g, b), r, g, b);
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 ();
}
} }
// Returns the texture the decal stuck to. // 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 // 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) while (*prev != NULL)
{ {
next = *prev; next = *prev;
prev = &next->snext; prev = &next->WallNext;
} }
*prev = this; *prev = this;
snext = NULL; WallNext = NULL;
sprev = prev; WallPrev = prev;
/* /*
snext = wall->BoundActors; WallNext = wall->AttachedDecals;
sprev = &wall->BoundActors; WallPrev = &wall->AttachedDecals;
if (snext) if (WallNext)
snext->sprev = &snext; WallNext->WallPrev = &WallNext;
wall->BoundActors = this; wall->AttachedDecals = this;
*/ */
sector_t *front, *back; sector_t *front, *back;
line_t *line; line_t *line;
@ -231,7 +249,7 @@ int ADecal::StickToWall (side_t *wall)
} }
if (back == NULL) if (back == NULL)
{ {
renderflags |= RF_RELMID; RenderFlags |= RF_RELMID;
if (line->flags & ML_DONTPEGBOTTOM) if (line->flags & ML_DONTPEGBOTTOM)
z -= front->floortexz; z -= front->floortexz;
else else
@ -240,7 +258,7 @@ int ADecal::StickToWall (side_t *wall)
} }
else if (back->floorplane.ZatPoint (x, y) >= z) else if (back->floorplane.ZatPoint (x, y) >= z)
{ {
renderflags |= RF_RELLOWER|RF_CLIPLOWER; RenderFlags |= RF_RELLOWER|RF_CLIPLOWER;
if (line->flags & ML_DONTPEGBOTTOM) if (line->flags & ML_DONTPEGBOTTOM)
z -= front->ceilingtexz; z -= front->ceilingtexz;
else else
@ -249,7 +267,7 @@ int ADecal::StickToWall (side_t *wall)
} }
else else
{ {
renderflags |= RF_RELUPPER|RF_CLIPUPPER; RenderFlags |= RF_RELUPPER|RF_CLIPUPPER;
if (line->flags & ML_DONTPEGTOP) if (line->flags & ML_DONTPEGTOP)
z -= front->ceilingtexz; z -= front->ceilingtexz;
else else
@ -259,21 +277,10 @@ int ADecal::StickToWall (side_t *wall)
CalcFracPos (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; 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 line_t *line = &lines[wall->linenum];
const sector_t *front, *back; const sector_t *front, *back;
@ -293,7 +300,7 @@ fixed_t ADecal::GetRealZ (const side_t *wall) const
back = front; back = front;
} }
switch (renderflags & RF_RELMASK) switch (RenderFlags & RF_RELMASK)
{ {
default: default:
return z; 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) void DBaseDecal::CalcFracPos (side_t *wall)
{
Remove ();
x = ix;
y = iy;
z = iz;
DoTrace ();
}
void ADecal::CalcFracPos (side_t *wall)
{ {
line_t *line = &lines[wall->linenum]; line_t *line = &lines[wall->linenum];
int wallnum = int(wall - sides); int wallnum = int(wall - sides);
@ -358,123 +356,18 @@ void ADecal::CalcFracPos (side_t *wall)
if (abs(dx) > abs(dy)) if (abs(dx) > abs(dy))
{ {
floorclip = SafeDivScale2 (x - v1->x, dx); LeftDistance = SafeDivScale2 (x - v1->x, dx);
} }
else if (dy != 0) else if (dy != 0)
{ {
floorclip = SafeDivScale2 (y - v1->y, dy); LeftDistance = SafeDivScale2 (y - v1->y, dy);
} }
else 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) static void GetWallStuff (side_t *wall, vertex_t *&v1, fixed_t &ldx, fixed_t &ldy)
{ {
line_t *line = &lines[wall->linenum]; line_t *line = &lines[wall->linenum];
@ -516,13 +409,7 @@ static side_t *NextWall (const side_t *wall)
return NULL; return NULL;
} }
static fixed_t DecalWidth, DecalLeft, DecalRight; void DBaseDecal::SpreadLeft (fixed_t r, vertex_t *v1, side_t *feelwall)
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)
{ {
fixed_t ldx, ldy; 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); x += Scale (r, ldx, wallsize);
y += Scale (r, ldy, wallsize); y += Scale (r, ldy, wallsize);
r = wallsize + startr; r = wallsize + startr;
SpreadSource->CloneSelf (SpreadDecal, x, y, SpreadZ, feelwall); SpreadSource->CloneSelf (SpreadTemplate, x, y, SpreadZ, feelwall);
SpreadStack.Push (feelwall); SpreadStack.Push (feelwall);
side_t *nextwall = NextWall (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; vertex_t *v1;
fixed_t x, y, ldx, ldy; fixed_t x, y, ldx, ldy;
@ -601,120 +488,220 @@ void AImpactDecal::SpreadRight (fixed_t r, side_t *feelwall, fixed_t wallsize)
x -= Scale (r, ldx, wallsize); x -= Scale (r, ldx, wallsize);
y -= Scale (r, ldy, wallsize); y -= Scale (r, ldy, wallsize);
r = DecalRight - r; r = DecalRight - r;
SpreadSource->CloneSelf (SpreadDecal, x, y, SpreadZ, feelwall); SpreadSource->CloneSelf (SpreadTemplate, x, y, SpreadZ, feelwall);
SpreadStack.Push (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; FTexture *tex;
if (decal != NULL && cl_maxdecals > 0 && vertex_t *v1;
!(wall->Flags & WALLF_NOAUTODECALS)) fixed_t rorg, ldx, ldy;
int xscale, yscale;
GetWallStuff (wall, v1, ldx, ldy);
rorg = Length (x - v1->x, y - v1->y);
tex = TexMan[PicNum];
int dwidth = tex->GetWidth ();
xscale = (XScale + 1) << (FRACBITS - 6);
yscale = (YScale + 1) << (FRACBITS - 6);
DecalWidth = dwidth * xscale;
DecalLeft = tex->LeftOffset * xscale;
DecalRight = DecalWidth - DecalLeft;
SpreadSource = this;
SpreadTemplate = tpl;
SpreadZ = z;
// Try spreading left first
SpreadLeft (rorg - DecalLeft, v1, wall);
SpreadStack.Clear ();
// Then try spreading right
SpreadRight (rorg + DecalRight, wall,
Length (lines[wall->linenum].dx, lines[wall->linenum].dy));
SpreadStack.Clear ();
}
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)
{ {
if (decal->LowerDecal) decal->StickToWall (wall);
tpl->ApplyToDecal (decal);
decal->AlphaColor = AlphaColor;
decal->RenderFlags = (decal->RenderFlags & RF_DECALMASK) |
(this->RenderFlags & ~RF_DECALMASK);
}
return decal;
}
CUSTOM_CVAR (Int, cl_maxdecals, 1024, CVAR_ARCHIVE)
{
if (self < 0)
{
self = 0;
}
else
{
while (ImpactCount > self)
{ {
StaticCreate (decal->LowerDecal->GetDecal(), x, y, z, wall); 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 ()
{
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) if (ImpactCount >= cl_maxdecals)
{ {
FirstImpact->Destroy (); FirstImpact->Destroy ();
} }
ImpactCount++;
actor = Spawn<AImpactDecal> (x, y, z);
if (actor == NULL) decal = new DImpactDecal (x, y, z);
return NULL;
int stickypic = actor->StickToWall (wall); int stickypic = decal->StickToWall (wall);
FTexture *tex = TexMan[stickypic]; FTexture *tex = TexMan[stickypic];
if (tex != NULL && tex->bNoDecals) if (tex != NULL && tex->bNoDecals)
{ {
actor->Destroy ();
return NULL; return NULL;
} }
decal->ApplyToActor (actor); if (decal == NULL)
if (color != 0) actor->SetShade (color.r, color.g, color.b); {
return NULL;
}
if (!cl_spreaddecals || actor->picnum == 0xffff) tpl->ApplyToDecal (decal);
return actor; if (color != 0)
{
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 // Spread decal to nearby walls if it does not all fit on this one
vertex_t *v1; decal->Spread (tpl, wall);
fixed_t rorg, ldx, ldy;
int xscale, yscale;
GetWallStuff (wall, v1, ldx, ldy);
rorg = Length (x - v1->x, y - v1->y);
tex = TexMan[actor->picnum];
int dwidth = tex->GetWidth ();
xscale = (actor->xscale + 1) << (FRACBITS - 6);
yscale = (actor->yscale + 1) << (FRACBITS - 6);
DecalWidth = dwidth * xscale;
DecalLeft = tex->LeftOffset * xscale;
DecalRight = DecalWidth - DecalLeft;
SpreadSource = actor;
SpreadDecal = decal;
SpreadZ = z;
// Try spreading left first
SpreadLeft (rorg - DecalLeft, v1, wall);
SpreadStack.Clear ();
// Then try spreading right
SpreadRight (rorg + DecalRight, wall,
Length (lines[wall->linenum].dx, lines[wall->linenum].dy));
SpreadStack.Clear ();
} }
return actor; return decal;
} }
AImpactDecal *AImpactDecal::CloneSelf (const FDecal *decal, fixed_t ix, fixed_t iy, fixed_t iz, side_t *wall) const DBaseDecal *DImpactDecal::CloneSelf (const FDecalTemplate *tpl, fixed_t ix, fixed_t iy, fixed_t iz, side_t *wall) const
{ {
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++;
if (ImpactCount >= cl_maxdecals) if (ImpactCount >= cl_maxdecals)
{ {
FirstImpact->Destroy (); FirstImpact->Destroy ();
} }
actor = Spawn<AImpactDecal> (ix, iy, iz); DImpactDecal *decal = new DImpactDecal(ix, iy, iz);
if (actor != NULL) if (decal != NULL)
{ {
actor->StickToWall (wall); decal->StickToWall (wall);
decal->ApplyToActor (actor); tpl->ApplyToDecal (decal);
actor->alphacolor = alphacolor; decal->AlphaColor = AlphaColor;
actor->renderflags = (actor->renderflags & RF_DECALMASK) | decal->RenderFlags = (decal->RenderFlags & RF_DECALMASK) |
(this->renderflags & ~RF_DECALMASK); (this->RenderFlags & ~RF_DECALMASK);
} }
return actor; return decal;
} }
void AImpactDecal::Destroy () void DImpactDecal::Destroy ()
{ {
if (target != NULL) if (ImpactPrev != NULL)
{ {
target->tracer = tracer; ImpactPrev->ImpactNext = ImpactNext;
} }
if (tracer != NULL) if (ImpactNext != NULL)
{ {
tracer->target = target; ImpactNext->ImpactPrev = ImpactPrev;
} }
if (LastImpact == this) if (LastImpact == this)
{ {
LastImpact = target; LastImpact = ImpactPrev;
} }
if (FirstImpact == this) if (FirstImpact == this)
{ {
FirstImpact = tracer; FirstImpact = ImpactNext;
} }
ImpactCount--; ImpactCount--;
@ -728,7 +715,7 @@ CCMD (countdecals)
CCMD (countdecalsreal) CCMD (countdecalsreal)
{ {
TThinkerIterator<AImpactDecal> iterator (STAT_DECAL); TThinkerIterator<DImpactDecal> iterator (STAT_DECAL);
int count = 0; int count = 0;
while (iterator.Next()) while (iterator.Next())
@ -761,9 +748,67 @@ CCMD (spray)
{ {
if (trace.HitType == TRACE_HitWall) if (trace.HitType == TRACE_HitWall)
{ {
AImpactDecal::StaticCreate (argv[1], DImpactDecal::StaticCreate (argv[1],
trace.X, trace.Y, trace.Z, trace.X, trace.Y, trace.Z,
sides + trace.Line->sidenum[trace.Side]); 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 "info.h"
#include "actor.h" #include "actor.h"
class FDecal; class FDecalTemplate;
struct vertex_s; struct vertex_s;
struct side_s; struct side_s;
@ -50,32 +50,57 @@ class ARealGibs : public AActor
struct side_s; struct side_s;
class ADecal : public AActor class DBaseDecal : public DThinker
{ {
DECLARE_STATELESS_ACTOR (ADecal, AActor) DECLARE_CLASS (DBaseDecal, DThinker)
public: 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 (); void Destroy ();
int StickToWall (side_s *wall); int StickToWall (side_s *wall);
void Relocate (fixed_t x, fixed_t y, fixed_t z);
fixed_t GetRealZ (const side_s *wall) const; 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 SerializeChain (FArchive &arc, DBaseDecal **firstptr);
static void MoveChain (ADecal *first, fixed_t x, fixed_t y); static void MoveChain (DBaseDecal *first, fixed_t x, fixed_t y);
static void FixForSide (side_s *side); 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: 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 CalcFracPos (side_s *wall);
void DoTrace ();
void Remove (); 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: public:
static AImpactDecal *StaticCreate (const char *name, 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);
static AImpactDecal *StaticCreate (const FDecal *decal, fixed_t x, fixed_t y, fixed_t z, side_s *wall, PalEntry color=0); 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 BeginPlay ();
void Destroy (); void Destroy ();
@ -83,10 +108,14 @@ public:
void Serialize (FArchive &arc); void Serialize (FArchive &arc);
static void SerializeTime (FArchive &arc); static void SerializeTime (FArchive &arc);
DImpactDecal *ImpactNext, *ImpactPrev;
protected: protected:
AImpactDecal *CloneSelf (const FDecal *decal, fixed_t x, fixed_t y, fixed_t z, side_s *wall) const; DBaseDecal *CloneSelf (const FDecalTemplate *tpl, 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); private:
DImpactDecal();
void Link();
}; };
class AWaterSplashBase : public AActor class AWaterSplashBase : public AActor

View file

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

View file

@ -1137,7 +1137,7 @@ FUNC(LS_Thing_Hate)
if (arg0 == 0) if (arg0 == 0)
{ {
if (it->player) if (it != NULL && it->player != NULL)
{ {
// Players cannot have their attitudes set // Players cannot have their attitudes set
return false; 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; bloodcolor.a=1;
} }
AImpactDecal::StaticCreate (bloodType, DImpactDecal::StaticCreate (bloodType,
bleedtrace.X, bleedtrace.Y, bleedtrace.Z, bleedtrace.X, bleedtrace.Y, bleedtrace.Z,
sides + bleedtrace.Line->sidenum[bleedtrace.Side], sides + bleedtrace.Line->sidenum[bleedtrace.Side],
bloodcolor); bloodcolor);
@ -4492,7 +4492,7 @@ void SpawnShootDecal (AActor *t1, const FTraceResults &trace)
} }
if (decalbase != NULL) if (decalbase != NULL)
{ {
AImpactDecal::StaticCreate (decalbase->GetDecal (), DImpactDecal::StaticCreate (decalbase->GetDecal (),
trace.X, trace.Y, trace.Z, sides + trace.Line->sidenum[trace.Side]); 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 // Emulate buggy PointOnLineSide and fix actors that lie on
// lines to compensate for some IWAD maps. // 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 () sector_t *AActor::LinkToWorldForMapThing ()
{ {
node_t *node; node_t *node = nodes + numnodes - 1;
int side;
node = nodes + numnodes - 1;
do do
{ {
@ -451,25 +498,7 @@ sector_t *AActor::LinkToWorldForMapThing ()
// that lies directly on a line should always be // that lies directly on a line should always be
// considered as "in front" of the line. The orientation // considered as "in front" of the line. The orientation
// of the line should be irrelevant. // of the line should be irrelevant.
if (node->dx == 0) node = (node_t *)node->children[R_PointOnSideSlow (x, y, node)];
{
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];
} }
while (!((size_t)node & 1)); 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); y = line->v1->y + MulScale30 (line->dy, frac);
z = mo->z; z = mo->z;
AImpactDecal::StaticCreate (base->GetDecal (), DImpactDecal::StaticCreate (base->GetDecal (),
x, y, z, sides + line->sidenum[side]); x, y, z, sides + line->sidenum[side]);
} }
} }

View file

@ -179,7 +179,7 @@ void P_SerializeWorld (FArchive &arc)
<< si->Flags << si->Flags
<< si->LeftSide << si->LeftSide
<< si->RightSide; << 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) void P_SerializeThinkers (FArchive &arc, bool hubLoad)
{ {
AImpactDecal::SerializeTime (arc); DImpactDecal::SerializeTime (arc);
DThinker::SerializeAll (arc, hubLoad); DThinker::SerializeAll (arc, hubLoad);
} }

View file

@ -610,7 +610,7 @@ static bool DoGroupForOne (AActor *victim, AActor *source, AActor *dest, bool fl
} }
#if 0 #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; int an = (dest->angle - source->angle) >> ANGLETOFINESHIFT;
fixed_t offX = decal->x - source->x; 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[BOXLEFT] += x;
linedef->bbox[BOXRIGHT] += x; linedef->bbox[BOXRIGHT] += x;
if (linedef->sidenum[0] != NO_SIDE) 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) 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; linedef->validcount = validcount;
} }
for (veryTempSeg = po->segs; veryTempSeg != segList; veryTempSeg++) for (veryTempSeg = po->segs; veryTempSeg != segList; veryTempSeg++)
@ -910,9 +910,9 @@ BOOL PO_RotatePolyobj (int num, angle_t angle)
UpdateSegBBox(*segList); UpdateSegBBox(*segList);
line_t *line = (*segList)->linedef; line_t *line = (*segList)->linedef;
if (line->sidenum[0] != NO_SIDE) if (line->sidenum[0] != NO_SIDE)
ADecal::FixForSide (&sides[line->sidenum[0]]); DBaseDecal::FixForSide (&sides[line->sidenum[0]]);
if (line->sidenum[1] != NO_SIDE) if (line->sidenum[1] != NO_SIDE)
ADecal::FixForSide (&sides[line->sidenum[1]]); DBaseDecal::FixForSide (&sides[line->sidenum[1]]);
line->validcount = validcount; line->validcount = validcount;
} }
} }
@ -934,9 +934,9 @@ BOOL PO_RotatePolyobj (int num, angle_t angle)
UpdateSegBBox(*segList); UpdateSegBBox(*segList);
line_t *line = (*segList)->linedef; line_t *line = (*segList)->linedef;
if (line->sidenum[0] != NO_SIDE) if (line->sidenum[0] != NO_SIDE)
ADecal::FixForSide (&sides[line->sidenum[0]]); DBaseDecal::FixForSide (&sides[line->sidenum[0]]);
if (line->sidenum[1] != NO_SIDE) if (line->sidenum[1] != NO_SIDE)
ADecal::FixForSide (&sides[line->sidenum[1]]); DBaseDecal::FixForSide (&sides[line->sidenum[1]]);
line->validcount = validcount; line->validcount = validcount;
} }
} }

View file

@ -379,7 +379,7 @@ struct zone_t
// The SideDef. // The SideDef.
// //
class ADecal; class DBaseDecal;
enum enum
{ {
@ -394,7 +394,7 @@ struct side_s
fixed_t textureoffset; // add this to the calculated texture column fixed_t textureoffset; // add this to the calculated texture column
fixed_t rowoffset; // add this to the calculated texture top fixed_t rowoffset; // add this to the calculated texture top
sector_t* sector; // Sector the SideDef is facing. 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 short toptexture, bottomtexture, midtexture; // texture indices
WORD linenum; WORD linenum;
DWORD LeftSide, RightSide; // [RH] Group walls into loops 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); *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 () int FActiveInterpolation::CountInterpolations ()
@ -1823,7 +1823,7 @@ int FActiveInterpolation::CountInterpolations (int *usedbuckets, int *minbucketf
FActiveInterpolation *FActiveInterpolation::FindInterpolation (EInterpType type, void *interptr, FActiveInterpolation **&interp_p) 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; FActiveInterpolation *probe, **probe_p;
for (probe_p = &curiposhash[hash], probe = *probe_p; for (probe_p = &curiposhash[hash], probe = *probe_p;

View file

@ -229,7 +229,7 @@ private:
void CopyBakToInterp(); void CopyBakToInterp();
void DoAnInterpolation(fixed_t smoothratio); 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); static FActiveInterpolation *FindInterpolation(EInterpType, void *interptr, FActiveInterpolation **&interp_p);
friend void updateinterpolations(); friend void updateinterpolations();

View file

@ -43,6 +43,7 @@
#include "m_swap.h" #include "m_swap.h"
#include "w_wad.h" #include "w_wad.h"
#include "stats.h" #include "stats.h"
#include "a_sharedglobal.h"
#define WALLYREPEAT 8 #define WALLYREPEAT 8
@ -123,7 +124,7 @@ FTexture *rw_pic;
static short *maskedtexturecol; static short *maskedtexturecol;
static FTexture *WallSpriteTile; 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)); 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 // [RH] Draw any decals bound to the seg
AActor *decal = (AActor *)curline->sidedef->BoundActors; for (DBaseDecal *decal = curline->sidedef->AttachedDecals; decal != NULL; decal = decal->WallNext)
while (decal != NULL)
{ {
R_RenderBoundWallSprite (decal, ds_p, 0); R_RenderDecal (decal, ds_p, 0);
decal = decal->snext;
} }
ds_p++; ds_p++;
@ -1767,9 +1766,7 @@ void PrepLWall (fixed_t *lwall, fixed_t walxrepeat)
// = 1: drawing masked textures (including sprites) // = 1: drawing masked textures (including sprites)
// Currently, only pass = 0 is done or used // Currently, only pass = 0 is done or used
static AActor *DecalActorForDebug; static void R_RenderDecal (DBaseDecal *decal, drawseg_t *clipper, int pass)
static void R_RenderBoundWallSprite (AActor *actor, drawseg_t *clipper, int pass)
{ {
fixed_t lx, ly, lx2, ly2; fixed_t lx, ly, lx2, ly2;
int x1, x2; int x1, x2;
@ -1780,72 +1777,62 @@ static void R_RenderBoundWallSprite (AActor *actor, drawseg_t *clipper, int pass
int needrepeat = 0; int needrepeat = 0;
sector_t *front, *back; sector_t *front, *back;
if (actor->renderflags & RF_INVISIBLE || !viewactive) if (decal->RenderFlags & RF_INVISIBLE || !viewactive || decal->PicNum == 0xFFFF)
return; return;
DecalActorForDebug = actor;
// Determine actor z // Determine actor z
zpos = actor->z; zpos = decal->z;
front = curline->frontsector; front = curline->frontsector;
back = (curline->backsector != NULL) ? curline->backsector : curline->frontsector; back = (curline->backsector != NULL) ? curline->backsector : curline->frontsector;
switch (actor->renderflags & RF_RELMASK) switch (decal->RenderFlags & RF_RELMASK)
{ {
default: default:
zpos = actor->z; zpos = decal->z;
break; break;
case RF_RELUPPER: case RF_RELUPPER:
if (curline->linedef->flags & ML_DONTPEGTOP) if (curline->linedef->flags & ML_DONTPEGTOP)
{ {
zpos = actor->z + front->ceilingtexz; zpos = decal->z + front->ceilingtexz;
} }
else else
{ {
zpos = actor->z + back->ceilingtexz; zpos = decal->z + back->ceilingtexz;
} }
break; break;
case RF_RELLOWER: case RF_RELLOWER:
if (curline->linedef->flags & ML_DONTPEGBOTTOM) if (curline->linedef->flags & ML_DONTPEGBOTTOM)
{ {
zpos = actor->z + front->ceilingtexz; zpos = decal->z + front->ceilingtexz;
} }
else else
{ {
zpos = actor->z + back->floortexz; zpos = decal->z + back->floortexz;
} }
break; break;
case RF_RELMID: case RF_RELMID:
if (curline->linedef->flags & ML_DONTPEGBOTTOM) if (curline->linedef->flags & ML_DONTPEGBOTTOM)
{ {
zpos = actor->z + front->floortexz; zpos = decal->z + front->floortexz;
} }
else else
{ {
zpos = actor->z + front->ceilingtexz; zpos = decal->z + front->ceilingtexz;
} }
} }
xscale = actor->xscale + 1; xscale = decal->XScale + 1;
yscale = actor->yscale + 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) if (WallSpriteTile->UseType == FTexture::TEX_Null)
{ {
return; return;
} }
// Determine left and right edges of sprite. Since this sprite is bound // 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. // pretty much the same as what R_AddLine() does.
x2 = WallSpriteTile->GetWidth(); x2 = WallSpriteTile->GetWidth();
@ -1856,10 +1843,10 @@ static void R_RenderBoundWallSprite (AActor *actor, drawseg_t *clipper, int pass
x2 *= xscale; x2 *= xscale;
angle_t ang = R_PointToAngle2 (curline->v1->x, curline->v1->y, curline->v2->x, curline->v2->y) >> ANGLETOFINESHIFT; 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; lx = decal->x - MulScale6 (x1, finecosine[ang]) - viewx;
lx2 = actor->x + MulScale6 (x2, finecosine[ang]) - viewx; lx2 = decal->x + MulScale6 (x2, finecosine[ang]) - viewx;
ly = actor->y - MulScale6 (x1, finesine[ang]) - viewy; ly = decal->y - MulScale6 (x1, finesine[ang]) - viewy;
ly2 = actor->y + MulScale6 (x2, finesine[ang]) - viewy; ly2 = decal->y + MulScale6 (x2, finesine[ang]) - viewy;
WallTX1 = DMulScale20 (lx, viewsin, -ly, viewcos); WallTX1 = DMulScale20 (lx, viewsin, -ly, viewcos);
WallTX2 = DMulScale20 (lx2, viewsin, -ly2, 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; WallDepthOrg = -WallUoverZstep * WallTMapScale2;
// Get the top and bottom clipping arrays // Get the top and bottom clipping arrays
switch (actor->renderflags & RF_CLIPMASK) switch (decal->RenderFlags & RF_CLIPMASK)
{ {
case RF_CLIPFULL: case RF_CLIPFULL:
if (curline->backsector == NULL) if (curline->backsector == NULL)
@ -2031,13 +2018,13 @@ static void R_RenderBoundWallSprite (AActor *actor, drawseg_t *clipper, int pass
dc_colormap = basecolormap + fixedlightlev; dc_colormap = basecolormap + fixedlightlev;
else if (fixedcolormap) else if (fixedcolormap)
dc_colormap = fixedcolormap; dc_colormap = fixedcolormap;
else if (!foggy && (actor->renderflags & RF_FULLBRIGHT)) else if (!foggy && (decal->RenderFlags & RF_FULLBRIGHT))
dc_colormap = basecolormap; dc_colormap = basecolormap;
else else
calclighting = true; calclighting = true;
// Draw it // Draw it
if (actor->renderflags & RF_YFLIP) if (decal->RenderFlags & RF_YFLIP)
{ {
sprflipvert = true; sprflipvert = true;
yscale = -yscale; yscale = -yscale;
@ -2055,7 +2042,7 @@ static void R_RenderBoundWallSprite (AActor *actor, drawseg_t *clipper, int pass
dc_x = x1; dc_x = x1;
ESPSResult mode; 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) 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)) static void WallSpriteColumn (void (*drawfunc)(const BYTE *column, const FTexture::Span *spans))
{ {
unsigned int texturecolumn = lwall[dc_x] >> FRACBITS; 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); dc_iscale = MulScale16 (swall[dc_x], rw_offset);
spryscale = SafeDivScale32 (1, dc_iscale); spryscale = SafeDivScale32 (1, dc_iscale);
if (sprflipvert) if (sprflipvert)

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -414,7 +414,7 @@ bool TimiditySong::LaunchTimidity ()
// Tell Timidity whether it should loop or not // Tell Timidity whether it should loop or not
CommandLine[LoopPos] = m_Looping ? 'l' : ' '; CommandLine[LoopPos] = m_Looping ? 'l' : ' ';
DPrintf ("cmd: \x1cG%s\n", CommandLine); DPrintf ("cmd: \x1cG%s\n", CommandLine.GetChars());
#ifdef _WIN32 #ifdef _WIN32
STARTUPINFO startup = { sizeof(startup), }; STARTUPINFO startup = { sizeof(startup), };
@ -496,7 +496,7 @@ bool TimiditySong::LaunchTimidity ()
freopen ("/dev/null", "r", stdin); freopen ("/dev/null", "r", stdin);
freopen ("/dev/null", "w", stderr); freopen ("/dev/null", "w", stderr);
close (WavePipe[1]); close (WavePipe[1]);
printf ("exec %s\n", words.we_wordv[0]); printf ("exec %s\n", words.we_wordv[0]);
execvp (words.we_wordv[0], words.we_wordv); execvp (words.we_wordv[0], words.we_wordv);
exit (0); // if execvp succeeds, we never get here exit (0); // if execvp succeeds, we never get here

View file

@ -44,12 +44,12 @@ enum { GAMEVERSION = 205 };
// Note that SAVEVER is not directly comparable to VERSION. // Note that SAVEVER is not directly comparable to VERSION.
// SAVESIG should match SAVEVER. // SAVESIG should match SAVEVER.
#define SAVEVER 231 #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 // This is so that derivates can use the same savegame versions without worrying about engine compatibility
#define GAMESIG "ZDOOM" #define GAMESIG "ZDOOM"
// MINSAVEVER is the minimum level snapshot version that can be loaded. // 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. // The maximum length of one save game description for the menus.
#define SAVESTRINGSIZE 24 #define SAVESTRINGSIZE 24

View file

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