diff --git a/docs/rh-log.txt b/docs/rh-log.txt
index a778feae..72765813 100644
--- a/docs/rh-log.txt
+++ b/docs/rh-log.txt
@@ -1,4 +1,80 @@
+September 22, 2008 (Changes by Graf Zahl)
+- Used the one unused byte in the state structure as a flag to tell what type
+ the NextState parameter is. The code did some rather unsafe checks with it
+ to determine its type.
+- moved all state related code into a new file: p_states.cpp.
+- merged all FindState functions. All the different variations are now inlined
+ and call the same function to do the real work.
+
+September 21, 2008 (Changes by Graf Zahl)
+- did some code cleanup and reorganization in thingdef.cpp.
+- Replaced the translation parser for TEXTURES with FRemapTable::AddToTranslation.
+- To get the game name the screenshot code might as well use the globally
+ available GameNames array instead of creating its own list.
+- Moved backpack names for cheat into gameinfo.
+- Fixed: SNDINFO must be loaded before the textures. However, this required
+ some changes to the MAPINFO parser which tried to access the texture manager
+ to check if the level name patches exist. That check had to be moved to
+ where the intermission screen is set up.
+- Fixed: 'bloodcolor' ignored the first parameter value when given a list
+ of integers.
+ Please note that this creates an incompatibility between old and new
+ versions so if you want to create something that works with both 2.2.0
+ and current versions better use the string format version for the color
+ parameter!
+- Rewrote the DECORATE property parser so that the parser is completely
+ separated from the property handlers. This should allow reuse of all
+ the handler code for a new format if Doomscript requires one.
+- Fixed: PClass::InitializeActorInfo copied too many bytes if a subclass's
+ defaults were larger than the parent's.
+- Moved A_ChangeFlag to thingdef_codeptr.cpp.
+- Moved translation related code from thingdef_properties.cpp to r_translate.cpp
+ and rewrote the translation parser to use FScanner instead of strtol.
+- replaced DECORATE's 'alpha default' by 'defaultalpha' for consistency.
+ Since this was never used outside zdoom.pk3 it's not critical.
+- Removed support for game specific pickup messages because the only thing
+ this was ever used for - Raven's invulnerability item - has already been
+ split up into a Heretic and Hexen version.
+
+September 20, 2008
+- Fixed: The Timidity config parser always tried to process the note number,
+ even if it wasn't specified.
+
+September 19, 2008
+- Fixed: When UpdateJoystickMenu() modifies the menu items for different
+ controllers, the joystick axis selectors need to NULL the d.graycheck
+ field, since this is shared by the axis sensitivity sliders' step values.
+
+September 19, 2008 (Changes by Graf Zahl)
+- Fixed: The crosshair must be initialized after the texture manager because
+ on the fly texture creation for graphics patches is no longer supported.
+- Fixed a few Linux compile errors.
+
+September 16, 2008 (Changes by Graf Zahl)
+- Changed: Replaced weapons should not be given by generic cheats, only
+ when explicitly giving them.
+- Changed 'give weapon' cheat so that in single player it only gives weapons
+ belonging to the current game or are placed in a weapon slot to avoid
+ giving the Chex Quest weapons in Doom and vice versa.
+- Fixed: The texture manager must be the first thing to be initialized
+ because MAPINFO and DECORATE both can reference textures and letting them
+ create their own textures is not safe.
+
+September 15, 2008 (Changes by Graf Zahl)
+- Separated low level sound code from all high level dependencies.
+- Separated low level sound channel class from high level class which now
+ is just a subclass of the low level class.
+- Moved some more high level sound logic out of FMODSoundRenderer:
+ The rolloff and channel ended callbacks now call functions in s_sound.cpp
+ instead of working on the data itself and GSnd->StopSound has been replaced
+ with S_StopChannel.
+- Changed compilation for g_doom, g_heretic, g_hexen and g_strife folders so
+ that all files are included by a central one instead of compiling each one
+ separately. This speeds up the compilation process by 25% when doing a
+ complete rebuild in Visual C.
+
September 14, 2008 (Changes by Graf Zahl)
+- Cleaned up some include dependencies.
- fixed: For Chex Quest some CVars were initialized to Heretic's default.
- fixed pickup message for LargeZorchPack.
diff --git a/gzdoom.vcproj b/gzdoom.vcproj
index be880673..1690763c 100644
--- a/gzdoom.vcproj
+++ b/gzdoom.vcproj
@@ -845,6 +845,10 @@
RelativePath=".\src\p_spec.cpp"
>
+
+
@@ -1072,6 +1076,10 @@
RelativePath=".\src\thingdef\thingdef_main.cpp"
>
+
+
@@ -1563,6 +1571,16 @@
Outputs="$(IntDir)\$(InputName).obj"
/>
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
@@ -1805,14 +1821,6 @@
Outputs="$(IntDir)/$(InputName).obj"
/>
-
-
-
@@ -1986,14 +1994,6 @@
Outputs="$(IntDir)\$(InputName).obj"
/>
-
-
-
@@ -2004,6 +2004,14 @@
Outputs="$(IntDir)\$(InputName).obj"
/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{
+public:
+ ~FDropItemPtrArray();
+};
+
+extern FDropItemPtrArray DropItemList;
+
+void FreeDropItemChain(FDropItem *chain);
+int StoreDropItemChain(FDropItem *chain);
+
+
+
// Map Object definition.
class AActor : public DThinker
{
@@ -451,6 +472,7 @@ public:
return (AActor *)(RUNTIME_TYPE(this)->Defaults);
}
+ FDropItem *GetDropItems();
// Return true if the monster should use a missile attack, false for melee
bool SuggestMissileAttack (fixed_t dist);
@@ -766,14 +788,20 @@ public:
bool isFast();
void SetIdle();
- FState *FindState (FName label) const;
- FState *FindState (FName label, FName sublabel, bool exact = false) const;
+ FState *FindState (FName label) const
+ {
+ return GetClass()->ActorInfo->FindState(1, &label);
+ }
+
+ FState *FindState (FName label, FName sublabel, bool exact = false) const
+ {
+ FName names[]={label, sublabel};
+ return GetClass()->ActorInfo->FindState(2, &label, exact);
+ }
+
+
bool HasSpecialDeathStates () const;
- static FState States[];
-
- enum { S_NULL = 2, S_GENERICFREEZEDEATH = 3 };
-
TArray > dynamiclights;
void * lightassociations;
bool hasmodel;
diff --git a/src/autosegs.h b/src/autosegs.h
index 0f5fd0c0..c4b9c896 100644
--- a/src/autosegs.h
+++ b/src/autosegs.h
@@ -50,7 +50,7 @@
#define REGMARKER(x) (x)
typedef void *REGINFO;
-// List of ActorInfos and the TypeInfos they belong to
+// List of Action functons
extern REGINFO ARegHead;
extern REGINFO ARegTail;
@@ -58,6 +58,10 @@ extern REGINFO ARegTail;
extern REGINFO CRegHead;
extern REGINFO CRegTail;
+// List of properties
+extern REGINFO GRegHead;
+extern REGINFO GRegTail;
+
template
class TAutoSegIteratorNoArrow
{
diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp
index 3d23baf0..4a857219 100644
--- a/src/d_dehacked.cpp
+++ b/src/d_dehacked.cpp
@@ -682,6 +682,7 @@ static int PatchThing (int thingy)
bool hadHeight = false;
bool hadTranslucency = false;
bool hadStyle = false;
+ FStateDefinitions statedef;
bool patchedStates = false;
int oldflags;
const PClass *type;
@@ -813,36 +814,36 @@ static int PatchThing (int thingy)
if (type != NULL && !patchedStates)
{
- MakeStateDefines(type->ActorInfo->StateList);
+ statedef.MakeStateDefines(type);
patchedStates = true;
}
if (!strnicmp (Line1, "Initial", 7))
- AddState("Spawn", state ? state : GetDefault()->SpawnState);
+ statedef.AddState("Spawn", state ? state : GetDefault()->SpawnState);
else if (!strnicmp (Line1, "First moving", 12))
- AddState("See", state);
+ statedef.AddState("See", state);
else if (!strnicmp (Line1, "Injury", 6))
- AddState("Pain", state);
+ statedef.AddState("Pain", state);
else if (!strnicmp (Line1, "Close attack", 12))
{
if (thingy != 1) // Not for players!
{
- AddState("Melee", state);
+ statedef.AddState("Melee", state);
}
}
else if (!strnicmp (Line1, "Far attack", 10))
{
if (thingy != 1) // Not for players!
{
- AddState("Missile", state);
+ statedef.AddState("Missile", state);
}
}
else if (!strnicmp (Line1, "Death", 5))
- AddState("Death", state);
+ statedef.AddState("Death", state);
else if (!strnicmp (Line1, "Exploding", 9))
- AddState("XDeath", state);
+ statedef.AddState("XDeath", state);
else if (!strnicmp (Line1, "Respawn", 7))
- AddState("Raise", state);
+ statedef.AddState("Raise", state);
}
else if (stricmp (Line1 + linelen - 6, " sound") == 0)
{
@@ -1048,7 +1049,7 @@ static int PatchThing (int thingy)
}
if (patchedStates)
{
- InstallStates(type->ActorInfo, info);
+ statedef.InstallStates(type->ActorInfo, info);
}
}
@@ -1359,6 +1360,7 @@ static int PatchWeapon (int weapNum)
AWeapon *info;
BYTE dummy[sizeof(AWeapon)];
bool patchedStates = false;
+ FStateDefinitions statedef;
if (weapNum >= 0 && weapNum < 9)
{
@@ -1385,20 +1387,20 @@ static int PatchWeapon (int weapNum)
if (type != NULL && !patchedStates)
{
- MakeStateDefines(type->ActorInfo->StateList);
+ statedef.MakeStateDefines(type);
patchedStates = true;
}
if (strnicmp (Line1, "Deselect", 8) == 0)
- AddState("Select", state);
+ statedef.AddState("Select", state);
else if (strnicmp (Line1, "Select", 6) == 0)
- AddState("Deselect", state);
+ statedef.AddState("Deselect", state);
else if (strnicmp (Line1, "Bobbing", 7) == 0)
- AddState("Ready", state);
+ statedef.AddState("Ready", state);
else if (strnicmp (Line1, "Shooting", 8) == 0)
- AddState("Fire", state);
+ statedef.AddState("Fire", state);
else if (strnicmp (Line1, "Firing", 6) == 0)
- AddState("Flash", state);
+ statedef.AddState("Flash", state);
}
else if (stricmp (Line1, "Ammo type") == 0)
{
@@ -1455,7 +1457,7 @@ static int PatchWeapon (int weapNum)
if (patchedStates)
{
- InstallStates(type->ActorInfo, info);
+ statedef.InstallStates(type->ActorInfo, info);
}
return result;
@@ -1697,18 +1699,22 @@ static int PatchMisc (int dummy)
{
player->health = deh.StartHealth;
- FDropItem * di = GetDropItems(PClass::FindClass(NAME_DoomPlayer));
- while (di != NULL)
+ // Hm... I'm not sure that this is the right way to change this info...
+ unsigned int index = PClass::FindClass(NAME_DoomPlayer)->Meta.GetMetaInt (ACMETA_DropItems) - 1;
+ if (index >= 0 && index < DropItemList.Size())
{
- if (di->Name == NAME_Clip)
+ FDropItem * di = DropItemList[index];
+ while (di != NULL)
{
- di->amount = deh.StartBullets;
+ if (di->Name == NAME_Clip)
+ {
+ di->amount = deh.StartBullets;
+ }
+ di = di->Next;
}
- di = di->Next;
}
}
-
// 0xDD means "enable infighting"
if (infighting == 0xDD)
{
@@ -2195,14 +2201,6 @@ void DoDehPatch (const char *patchfile, bool autoloading, int lump)
PatchFile[filelen] = 0;
dversion = pversion = -1;
-/*
- if (gameinfo.gametype != GAME_Doom)
- {
- Printf ("DeHackEd/BEX patches are only supported for DOOM mode\n");
- delete[] PatchFile;
- return;
- }
-*/
cont = 0;
if (0 == strncmp (PatchFile, "Patch File for DeHackEd v", 25))
{
@@ -2586,13 +2584,14 @@ void FinishDehPatch ()
memcpy (defaults2, defaults1, sizeof(AActor));
// Make a copy the state labels
- MakeStateDefines(type->ActorInfo->StateList);
if (!type->IsDescendantOf(RUNTIME_CLASS(AInventory)))
{
// If this is a hacked non-inventory item we must also copy AInventory's special states
- AddStateDefines(RUNTIME_CLASS(AInventory)->ActorInfo->StateList);
+ FStateDefinitions statedef;
+ statedef.MakeStateDefines(type);
+ statedef.AddStateDefines(RUNTIME_CLASS(AInventory)->ActorInfo->StateList);
+ statedef.InstallStates(subclass->ActorInfo, defaults2);
}
- InstallStates(subclass->ActorInfo, defaults2);
// Use the DECORATE replacement feature to redirect all spawns
// of the original class to the new one.
diff --git a/src/d_main.cpp b/src/d_main.cpp
index 257650d6..ce8aef51 100644
--- a/src/d_main.cpp
+++ b/src/d_main.cpp
@@ -2489,6 +2489,13 @@ void D_DoomMain (void)
Printf ("S_InitData: Load sound definitions.\n");
S_InitData ();
+
+ Printf ("Texman.Init: Init texture manager.\n");
+ TexMan.Init();
+
+ // Now that all textues have been loaded the crosshair can be initialized.
+ crosshair.Callback ();
+
// [CW] Parse any TEAMINFO lumps
Printf ("TEAMINFO_Init: Load team definitions.\n");
TEAMINFO_Init ();
diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp
index 73c66da9..2bd670b0 100644
--- a/src/dobjtype.cpp
+++ b/src/dobjtype.cpp
@@ -297,7 +297,7 @@ void PClass::InitializeActorInfo ()
Defaults = new BYTE[Size];
if (ParentClass->Defaults != NULL)
{
- memcpy (Defaults, ParentClass->Defaults, Size);
+ memcpy (Defaults, ParentClass->Defaults, ParentClass->Size);
if (Size > ParentClass->Size)
{
memset (Defaults + ParentClass->Size, 0, Size - ParentClass->Size);
diff --git a/src/doomtype.h b/src/doomtype.h
index d7ea6ec7..72feddbc 100644
--- a/src/doomtype.h
+++ b/src/doomtype.h
@@ -170,6 +170,14 @@ struct PalEntry
#endif
};
+// Screenshot buffer image data types
+enum ESSType
+{
+ SS_PAL,
+ SS_RGB,
+ SS_BGRA
+};
+
#ifndef M_PI
#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h
#endif
diff --git a/src/g_doom/a_bossbrain.cpp b/src/g_doom/a_bossbrain.cpp
index 6cf9146c..2c7e3e86 100644
--- a/src/g_doom/a_bossbrain.cpp
+++ b/src/g_doom/a_bossbrain.cpp
@@ -165,7 +165,7 @@ static void SpawnFly(AActor *self, const PClass *spawntype, FSoundID sound)
FDropItem *drop; // while drop stays as the reference point.
int n=0;
- drop = di = GetDropItems(self->master->GetClass());
+ drop = di = self->master->GetDropItems();
if (di != NULL)
{
while (di != NULL)
diff --git a/src/g_level.cpp b/src/g_level.cpp
index 005b741d..b00a9a36 100644
--- a/src/g_level.cpp
+++ b/src/g_level.cpp
@@ -848,13 +848,15 @@ static void G_DoParseMapInfo (int lump)
strcpy (levelinfo->skypic2, levelinfo->skypic1);
}
SetLevelNum (levelinfo, levelinfo->levelnum); // Wipe out matching levelnums from other maps.
+ /* can't do this here.
if (levelinfo->pname[0] != 0)
{
- if (!TexMan.AddPatch(levelinfo->pname).Exists())
+ if (!TexMan.CheckForTexture(levelinfo->pname, FTexture::TEX_MiscPatch).Exists())
{
levelinfo->pname[0] = 0;
}
}
+ */
break;
}
@@ -1722,7 +1724,7 @@ void G_InitNew (const char *mapname, bool bTitleLevel)
{
int cstype = SBarInfoScript->GetGameType();
- if(cstype == GAME_Doom || cstype == GAME_Chex) //Did the user specify a "base"
+ if(cstype & GAME_DoomChex) //Did the user specify a "base"
{
StatusBar = CreateDoomStatusBar ();
}
@@ -1854,7 +1856,7 @@ void G_InitNew (const char *mapname, bool bTitleLevel)
//
// G_DoCompleted
//
-static char nextlevel[9];
+static FString nextlevel;
static int startpos; // [RH] Support for multiple starts per level
extern int NoWipe; // [RH] Don't wipe when travelling in hubs
static bool startkeepfacing; // [RH] Support for keeping your facing angle
@@ -1866,7 +1868,7 @@ static bool g_nomonsters;
// match the first parameter of the single player start spots
// that should appear in the next map.
-void G_ChangeLevel(const char * levelname, int position, bool keepFacing, int nextSkill,
+void G_ChangeLevel(const char *levelname, int position, bool keepFacing, int nextSkill,
bool nointermission, bool resetinv, bool nomonsters)
{
if (unloading)
@@ -1875,15 +1877,14 @@ void G_ChangeLevel(const char * levelname, int position, bool keepFacing, int ne
return;
}
- strncpy (nextlevel, levelname, 8);
- nextlevel[8] = 0;
+ nextlevel = levelname;
- if (strncmp(nextlevel, "enDSeQ", 6))
+ if (strncmp(levelname, "enDSeQ", 6))
{
level_info_t *nextinfo = CheckLevelRedirect (FindLevelInfo (nextlevel));
if (nextinfo)
{
- strncpy(nextlevel, nextinfo->mapname, 8);
+ nextlevel = nextinfo->mapname;
}
}
@@ -1983,7 +1984,7 @@ void G_DoCompleted (void)
if (gamestate == GS_TITLELEVEL)
{
- strncpy (level.mapname, nextlevel, 8);
+ strncpy (level.mapname, nextlevel, 255);
G_DoLoadLevel (startpos, false);
startpos = 0;
viewactive = true;
@@ -1998,7 +1999,7 @@ void G_DoCompleted (void)
AM_Stop ();
wminfo.finished_ep = level.cluster - 1;
- wminfo.lname0 = level.info->pname;
+ wminfo.LName0 = TexMan[TexMan.CheckForTexture(level.info->pname, FTexture::TEX_MiscPatch)];
wminfo.current = level.mapname;
if (deathmatch &&
@@ -2006,26 +2007,27 @@ void G_DoCompleted (void)
!(level.flags & LEVEL_CHANGEMAPCHEAT))
{
wminfo.next = level.mapname;
- wminfo.lname1 = level.info->pname;
+ wminfo.LName1 = wminfo.LName0;
}
else
{
if (strncmp (nextlevel, "enDSeQ", 6) == 0)
{
wminfo.next = FString(nextlevel, 8);
- wminfo.lname1 = "";
+ wminfo.LName1 = NULL;
}
else
{
level_info_t *nextinfo = FindLevelInfo (nextlevel);
wminfo.next = nextinfo->mapname;
- wminfo.lname1 = nextinfo->pname;
+ wminfo.LName1 = TexMan[TexMan.CheckForTexture(nextinfo->pname, FTexture::TEX_MiscPatch)];
}
}
CheckWarpTransMap (wminfo.next, true);
+ nextlevel = wminfo.next;
- wminfo.next_ep = FindLevelInfo (nextlevel)->cluster - 1;
+ wminfo.next_ep = FindLevelInfo (wminfo.next)->cluster - 1;
wminfo.maxkills = level.total_monsters;
wminfo.maxitems = level.total_items;
wminfo.maxsecret = level.total_secrets;
@@ -2357,7 +2359,7 @@ void G_DoWorldDone (void)
}
else
{
- strncpy (level.mapname, nextlevel, 8);
+ strncpy (level.mapname, nextlevel, 255);
}
G_StartTravel ();
G_DoLoadLevel (startpos, true);
diff --git a/src/g_shared/a_action.cpp b/src/g_shared/a_action.cpp
index d38a1b06..399a3d14 100644
--- a/src/g_shared/a_action.cpp
+++ b/src/g_shared/a_action.cpp
@@ -81,7 +81,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_NoBlocking)
// If the self has attached metadata for items to drop, drop those.
if (!self->IsKindOf (RUNTIME_CLASS (APlayerPawn))) // [GRB]
{
- FDropItem *di = GetDropItems(RUNTIME_TYPE(self));
+ FDropItem *di = self->GetDropItems();
if (di != NULL)
{
diff --git a/src/g_shared/a_keys.cpp b/src/g_shared/a_keys.cpp
index 33988bec..e9298e8f 100644
--- a/src/g_shared/a_keys.cpp
+++ b/src/g_shared/a_keys.cpp
@@ -394,6 +394,7 @@ bool P_CheckKeys (AActor *owner, int keynum, bool remote)
const char *failtext = NULL;
FSoundID failsound;
+ if (owner == NULL) return false;
if (keynum<=0 || keynum>255) return true;
// Just a safety precaution. The messages should have been initialized upon game start.
if (!keysdone) P_InitKeyMessages();
diff --git a/src/g_shared/a_randomspawner.cpp b/src/g_shared/a_randomspawner.cpp
index 4581b9c9..e54f3175 100644
--- a/src/g_shared/a_randomspawner.cpp
+++ b/src/g_shared/a_randomspawner.cpp
@@ -23,14 +23,14 @@ class ARandomSpawner : public AActor
void PostBeginPlay()
{
- AActor *newmobj;
+ AActor *newmobj = NULL;
FDropItem *di; // di will be our drop item list iterator
FDropItem *drop; // while drop stays as the reference point.
int n=0;
Super::PostBeginPlay();
- drop = di = GetDropItems(RUNTIME_TYPE(this));
+ drop = di = GetDropItems();
if (di != NULL)
{
while (di != NULL)
diff --git a/src/g_shared/a_weapons.cpp b/src/g_shared/a_weapons.cpp
index a9b49024..33f27930 100644
--- a/src/g_shared/a_weapons.cpp
+++ b/src/g_shared/a_weapons.cpp
@@ -587,7 +587,7 @@ IMPLEMENT_CLASS(AWeaponGiver)
bool AWeaponGiver::TryPickup(AActor *&toucher)
{
- FDropItem *di = GetDropItems(GetClass());
+ FDropItem *di = GetDropItems();
if (di != NULL)
{
@@ -737,8 +737,8 @@ bool FWeaponSlots::LocateWeapon (const PClass *type, int *const slot, int *const
{
if (Slots[i].Weapons[j] == type)
{
- *slot = i;
- *index = j;
+ if (slot != NULL) *slot = i;
+ if (index != NULL) *index = j;
return true;
}
else if (Slots[i].Weapons[j] == NULL)
diff --git a/src/g_shared/shared_sbar.cpp b/src/g_shared/shared_sbar.cpp
index f72ef095..133dd011 100644
--- a/src/g_shared/shared_sbar.cpp
+++ b/src/g_shared/shared_sbar.cpp
@@ -94,7 +94,7 @@ CUSTOM_CVAR (Bool, st_scale, true, CVAR_ARCHIVE)
}
}
-CUSTOM_CVAR (Int, crosshair, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
+CUSTOM_CVAR (Int, crosshair, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL)
{
int num = self;
char name[16], size;
@@ -123,7 +123,7 @@ CUSTOM_CVAR (Int, crosshair, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
strcpy (name, "XHAIRS1");
}
}
- CrosshairImage = TexMan[TexMan.AddPatch (name)];
+ CrosshairImage = TexMan[TexMan.CheckForTexture(name, FTexture::TEX_MiscPatch)];
}
CVAR (Color, crosshaircolor, 0xff0000, CVAR_ARCHIVE|CVAR_GLOBALCONFIG);
diff --git a/src/gi.cpp b/src/gi.cpp
index 088c1a69..d26733e2 100644
--- a/src/gi.cpp
+++ b/src/gi.cpp
@@ -100,6 +100,7 @@ gameinfo_t HexenGameInfo =
{ "mapinfo/hexen.txt", NULL },
MAKERGB(104,0,0),
MAKERGB(255,0,0),
+ "BagOfHolding", // Hexen doesn't have a backpack so use Heretic's.
};
gameinfo_t HexenDKGameInfo =
@@ -132,6 +133,7 @@ gameinfo_t HexenDKGameInfo =
{ "mapinfo/hexen.txt", NULL },
MAKERGB(104,0,0),
MAKERGB(255,0,0),
+ "BagOfHolding",
};
gameinfo_t HereticGameInfo =
@@ -164,6 +166,7 @@ gameinfo_t HereticGameInfo =
{ "mapinfo/heretic.txt", NULL },
MAKERGB(104,0,0),
MAKERGB(255,0,0),
+ "BagOfHolding",
};
gameinfo_t HereticSWGameInfo =
@@ -196,6 +199,7 @@ gameinfo_t HereticSWGameInfo =
{ "mapinfo/heretic.txt", NULL },
MAKERGB(104,0,0),
MAKERGB(255,0,0),
+ "BagOfHolding",
};
gameinfo_t SharewareGameInfo =
@@ -228,6 +232,7 @@ gameinfo_t SharewareGameInfo =
{ "mapinfo/doomcommon.txt", "mapinfo/doom1.txt" },
MAKERGB(104,0,0),
MAKERGB(255,0,0),
+ "Backpack",
};
gameinfo_t RegisteredGameInfo =
@@ -260,6 +265,7 @@ gameinfo_t RegisteredGameInfo =
{ "mapinfo/doomcommon.txt", "mapinfo/doom1.txt" },
MAKERGB(104,0,0),
MAKERGB(255,0,0),
+ "Backpack",
};
gameinfo_t ChexGameInfo =
@@ -292,6 +298,7 @@ gameinfo_t ChexGameInfo =
{ "mapinfo/chex.txt", NULL },
MAKERGB(63,125,57),
MAKERGB(95,175,87),
+ "ZorchPack",
};
gameinfo_t Chex3GameInfo =
@@ -324,6 +331,7 @@ gameinfo_t Chex3GameInfo =
{ "mapinfo/chex.txt", NULL },
MAKERGB(63,125,57),
MAKERGB(95,175,87),
+ "ZorchPack",
};
gameinfo_t RetailGameInfo =
@@ -356,6 +364,7 @@ gameinfo_t RetailGameInfo =
{ "mapinfo/doomcommon.txt", "mapinfo/doom1.txt" },
MAKERGB(104,0,0),
MAKERGB(255,0,0),
+ "Backpack",
};
gameinfo_t CommercialGameInfo =
@@ -388,6 +397,7 @@ gameinfo_t CommercialGameInfo =
{ "mapinfo/doomcommon.txt", "mapinfo/doom2.txt" },
MAKERGB(104,0,0),
MAKERGB(255,0,0),
+ "Backpack",
};
gameinfo_t PlutoniaGameInfo =
@@ -420,6 +430,7 @@ gameinfo_t PlutoniaGameInfo =
{ "mapinfo/doomcommon.txt", "mapinfo/plutonia.txt" },
MAKERGB(104,0,0),
MAKERGB(255,0,0),
+ "Backpack",
};
gameinfo_t TNTGameInfo =
@@ -452,6 +463,7 @@ gameinfo_t TNTGameInfo =
{ "mapinfo/doomcommon.txt", "mapinfo/tnt.txt" },
MAKERGB(104,0,0),
MAKERGB(255,0,0),
+ "Backpack",
};
gameinfo_t StrifeGameInfo =
@@ -484,6 +496,7 @@ gameinfo_t StrifeGameInfo =
{ "mapinfo/strife.txt", NULL },
MAKERGB(104,0,0),
MAKERGB(255,0,0),
+ "AmmoSatchel",
};
gameinfo_t StrifeTeaserGameInfo =
@@ -516,6 +529,7 @@ gameinfo_t StrifeTeaserGameInfo =
{ "mapinfo/strife.txt", NULL },
MAKERGB(104,0,0),
MAKERGB(255,0,0),
+ "AmmoSatchel",
};
gameinfo_t StrifeTeaser2GameInfo =
@@ -548,4 +562,5 @@ gameinfo_t StrifeTeaser2GameInfo =
{ "mapinfo/strife.txt", NULL },
MAKERGB(104,0,0),
MAKERGB(255,0,0),
+ "AmmoSatchel",
};
diff --git a/src/gi.h b/src/gi.h
index 26514d2c..9ef71f8a 100644
--- a/src/gi.h
+++ b/src/gi.h
@@ -121,6 +121,7 @@ typedef struct
const char *mapinfo[2];
DWORD defaultbloodcolor;
DWORD defaultbloodparticlecolor;
+ const char *backpacktype;
} gameinfo_t;
extern gameinfo_t gameinfo;
diff --git a/src/info.cpp b/src/info.cpp
index 61eb767f..4487d7ac 100644
--- a/src/info.cpp
+++ b/src/info.cpp
@@ -51,122 +51,6 @@
extern void LoadDecorations ();
-// Each state is owned by an actor. Actors can own any number of
-// states, but a single state cannot be owned by more than one
-// actor. States are archived by recording the actor they belong
-// to and the index into that actor's list of states.
-
-// For NULL states, which aren't owned by any actor, the owner
-// is recorded as AActor with the following state. AActor should
-// never actually have this many states of its own, so this
-// is (relatively) safe.
-
-#define NULL_STATE_INDEX 127
-
-//==========================================================================
-//
-//
-//==========================================================================
-
-FArchive &operator<< (FArchive &arc, FState *&state)
-{
- const PClass *info;
-
- if (arc.IsStoring ())
- {
- if (state == NULL)
- {
- arc.UserWriteClass (RUNTIME_CLASS(AActor));
- arc.WriteCount (NULL_STATE_INDEX);
- return arc;
- }
-
- info = FState::StaticFindStateOwner (state);
-
- if (info != NULL)
- {
- arc.UserWriteClass (info);
- arc.WriteCount ((DWORD)(state - info->ActorInfo->OwnedStates));
- }
- else
- {
- /* this was never working as intended.
- I_Error ("Cannot find owner for state %p:\n"
- "%s %c%c %3d [%p] -> %p", state,
- sprites[state->sprite].name,
- state->GetFrame() + 'A',
- state->GetFullbright() ? '*' : ' ',
- state->GetTics(),
- state->GetAction(),
- state->GetNextState());
- */
- }
- }
- else
- {
- const PClass *info;
- DWORD ofs;
-
- arc.UserReadClass (info);
- ofs = arc.ReadCount ();
- if (ofs == NULL_STATE_INDEX && info == RUNTIME_CLASS(AActor))
- {
- state = NULL;
- }
- else if (info->ActorInfo != NULL)
- {
- state = info->ActorInfo->OwnedStates + ofs;
- }
- else
- {
- state = NULL;
- }
- }
- return arc;
-}
-
-//==========================================================================
-//
-// Find the actor that a state belongs to.
-//
-//==========================================================================
-
-const PClass *FState::StaticFindStateOwner (const FState *state)
-{
- for (unsigned int i = 0; i < PClass::m_RuntimeActors.Size(); ++i)
- {
- FActorInfo *info = PClass::m_RuntimeActors[i]->ActorInfo;
- if (state >= info->OwnedStates &&
- state < info->OwnedStates + info->NumOwnedStates)
- {
- return info->Class;
- }
- }
-
- return NULL;
-}
-
-//==========================================================================
-//
-// Find the actor that a state belongs to, but restrict the search to
-// the specified type and its ancestors.
-//
-//==========================================================================
-
-const PClass *FState::StaticFindStateOwner (const FState *state, const FActorInfo *info)
-{
- while (info != NULL)
- {
- if (state >= info->OwnedStates &&
- state < info->OwnedStates + info->NumOwnedStates)
- {
- return info->Class;
- }
- info = info->Class->ParentClass->ActorInfo;
- }
- return NULL;
-}
-
//==========================================================================
//
//
@@ -174,16 +58,23 @@ const PClass *FState::StaticFindStateOwner (const FState *state, const FActorInf
int GetSpriteIndex(const char * spritename)
{
+ // Make sure that the string is upper case and 4 characters long
+ char upper[5];
+ for (int i = 0; spritename[i] != 0 && i < 4; i++)
+ {
+ upper[i] = toupper (spritename[i]);
+ }
+ upper[4] = 0;
+
for (unsigned i = 0; i < sprites.Size (); ++i)
{
- if (strncmp (sprites[i].name, spritename, 4) == 0)
+ if (strcmp (sprites[i].name, spritename) == 0)
{
return (int)i;
}
}
spritedef_t temp;
- strncpy (temp.name, spritename, 4);
- temp.name[4] = 0;
+ strcpy (temp.name, upper);
temp.numframes = 0;
temp.spriteframes = 0;
return (int)sprites.Push (temp);
@@ -337,209 +228,6 @@ void FActorInfo::SetPainChance(FName type, int chance)
}
}
-//==========================================================================
-//
-//
-//==========================================================================
-
-FStateLabel *FStateLabels::FindLabel (FName label)
-{
- return const_cast(BinarySearch (Labels, NumLabels, &FStateLabel::Label, label));
-}
-
-void FStateLabels::Destroy ()
-{
- for(int i=0; iDestroy();
- free (Labels[i].Children); // These are malloc'd, not new'd!
- Labels[i].Children=NULL;
- }
- }
-}
-
-
-//===========================================================================
-//
-// HasStates
-//
-// Checks whether the actor has special death states.
-//
-//===========================================================================
-
-bool AActor::HasSpecialDeathStates () const
-{
- const FActorInfo *info = GetClass()->ActorInfo;
-
- if (info->StateList != NULL)
- {
- FStateLabel *slabel = info->StateList->FindLabel (NAME_Death);
- if (slabel != NULL && slabel->Children != NULL)
- {
- for(int i=0;iChildren->NumLabels;i++)
- {
- if (slabel->Children->Labels[i].State != NULL) return true;
- }
- }
- }
- return false;
-}
-
-//===========================================================================
-//
-// FindState (one name version)
-//
-// Finds a state with the exact specified name.
-//
-//===========================================================================
-
-FState *AActor::FindState (FName label) const
-{
- const FActorInfo *info = GetClass()->ActorInfo;
-
- if (info->StateList != NULL)
- {
- FStateLabel *slabel = info->StateList->FindLabel (label);
- if (slabel != NULL)
- {
- return slabel->State;
- }
- }
- return NULL;
-}
-
-//===========================================================================
-//
-// FindState (two name version)
-//
-//===========================================================================
-
-FState *AActor::FindState (FName label, FName sublabel, bool exact) const
-{
- const FActorInfo *info = GetClass()->ActorInfo;
-
- if (info->StateList != NULL)
- {
- FStateLabel *slabel = info->StateList->FindLabel (label);
- if (slabel != NULL)
- {
- if (slabel->Children != NULL)
- {
- FStateLabel *slabel2 = slabel->Children->FindLabel(sublabel);
- if (slabel2 != NULL)
- {
- return slabel2->State;
- }
- }
- if (!exact) return slabel->State;
- }
- }
- return NULL;
-}
-
-//===========================================================================
-//
-// FindState (multiple names version)
-//
-// Finds a state that matches as many of the supplied names as possible.
-// A state with more names than those provided does not match.
-// A state with fewer names can match if there are no states with the exact
-// same number of names.
-//
-// The search proceeds like this. For the current class, keeping matching
-// names until there are no more. If both the argument list and the state
-// are out of names, it's an exact match, so return it. If the state still
-// has names, ignore it. If the argument list still has names, remember it.
-//
-//===========================================================================
-FState *FActorInfo::FindState (FName name) const
-{
- return FindState(1, &name);
-}
-
-FState *FActorInfo::FindState (int numnames, FName *names, bool exact) const
-{
- FStateLabels *labels = StateList;
- FState *best = NULL;
-
- if (labels != NULL)
- {
- int count = 0;
- FStateLabel *slabel = NULL;
- FName label;
-
- // Find the best-matching label for this class.
- while (labels != NULL && count < numnames)
- {
- label = *names++;
- slabel = labels->FindLabel (label);
-
- if (slabel != NULL)
- {
- count++;
- labels = slabel->Children;
- best = slabel->State;
- }
- else
- {
- break;
- }
- }
- if (count < numnames && exact) return NULL;
- }
- return best;
-}
-
-//==========================================================================
-//
-// Creates a list of names from a string. Dots are used as separator
-//
-//==========================================================================
-
-void MakeStateNameList(const char * fname, TArray * out)
-{
- FName firstpart, secondpart;
- char * c;
-
- // Handle the old names for the existing death states
- char * name = copystring(fname);
- firstpart = strtok(name, ".");
- switch (firstpart)
- {
- case NAME_Burn:
- firstpart = NAME_Death;
- secondpart = NAME_Fire;
- break;
- case NAME_Ice:
- firstpart = NAME_Death;
- secondpart = NAME_Ice;
- break;
- case NAME_Disintegrate:
- firstpart = NAME_Death;
- secondpart = NAME_Disintegrate;
- break;
- case NAME_XDeath:
- firstpart = NAME_Death;
- secondpart = NAME_Extreme;
- break;
- }
-
- out->Clear();
- out->Push(firstpart);
- if (secondpart!=NAME_None) out->Push(secondpart);
-
- while ((c = strtok(NULL, "."))!=NULL)
- {
- FName cc = c;
- out->Push(cc);
- }
- delete [] name;
-}
-
-
-
//==========================================================================
//
//
diff --git a/src/info.h b/src/info.h
index f7e9212d..07b6650d 100644
--- a/src/info.h
+++ b/src/info.h
@@ -89,6 +89,7 @@ struct FState
SBYTE Misc1;
BYTE Misc2;
BYTE Frame;
+ BYTE DefineFlags; // Unused byte so let's use it during state creation.
FState *NextState;
actionf_p ActionFunc;
int ParameterIndex;
@@ -204,8 +205,12 @@ struct FActorInfo
void SetDamageFactor(FName type, fixed_t factor);
void SetPainChance(FName type, int chance);
- FState *FindState (FName name) const;
FState *FindState (int numnames, FName *names, bool exact=false) const;
+ FState *FindStateByString(const char *name, bool exact=false);
+ FState *FindState (FName name) const
+ {
+ return FindState(1, &name);
+ }
FActorInfo *GetReplacement ();
FActorInfo *GetReplacee ();
@@ -252,6 +257,6 @@ private:
extern FDoomEdMap DoomEdMap;
int GetSpriteIndex(const char * spritename);
-void MakeStateNameList(const char * fname, TArray * out);
+TArray &MakeStateNameList(const char * fname);
#endif // __INFO_H__
diff --git a/src/m_cheat.cpp b/src/m_cheat.cpp
index 10ae08d5..1a276216 100644
--- a/src/m_cheat.cpp
+++ b/src/m_cheat.cpp
@@ -43,6 +43,8 @@
#include "r_translate.h"
#include "g_level.h"
#include "d_net.h"
+#include "d_dehacked.h"
+#include "gi.h"
// [RH] Actually handle the cheat. The cheat code in st_stuff.c now just
// writes some bytes to the network data stream, and the network code
@@ -629,26 +631,7 @@ void cht_Give (player_t *player, const char *name, int amount)
if (giveall || stricmp (name, "backpack") == 0)
{
// Select the correct type of backpack based on the game
- if (gameinfo.gametype == GAME_Heretic)
- {
- type = PClass::FindClass ("BagOfHolding");
- }
- else if (gameinfo.gametype == GAME_Strife)
- {
- type = PClass::FindClass ("AmmoSatchel");
- }
- else if (gameinfo.gametype == GAME_Doom)
- {
- type = PClass::FindClass ("Backpack");
- }
- else if (gameinfo.gametype == GAME_Chex)
- {
- type = PClass::FindClass ("Zorchpack");
- }
- else
- { // Hexen doesn't have a backpack, foo!
- type = NULL;
- }
+ type = PClass::FindClass(gameinfo.backpacktype);
if (type != NULL)
{
GiveSpawner (player, type, 1);
@@ -743,13 +726,26 @@ void cht_Give (player_t *player, const char *name, int amount)
for (unsigned int i = 0; i < PClass::m_Types.Size(); ++i)
{
type = PClass::m_Types[i];
+ // Don't give replaced weapons unless the replacement was done by Dehacked.
if (type != RUNTIME_CLASS(AWeapon) &&
- type->IsDescendantOf (RUNTIME_CLASS(AWeapon)))
+ type->IsDescendantOf (RUNTIME_CLASS(AWeapon)) &&
+ (type->ActorInfo->GetReplacement() == type->ActorInfo ||
+ type->ActorInfo->GetReplacement()->Class->IsDescendantOf(RUNTIME_CLASS(ADehackedPickup))))
+
{
- AWeapon *def = (AWeapon*)GetDefaultByType (type);
- if (!(def->WeaponFlags & WIF_CHEATNOTWEAPON))
+ // Give the weapon only if it belongs to the current game or
+ // is in a weapon slot. Unfortunately this check only works in
+ // singleplayer games because the weapon slots are stored locally.
+ // In multiplayer games all weapons must be given.
+ if (multiplayer || type->ActorInfo->GameFilter == GAME_Any ||
+ (type->ActorInfo->GameFilter & gameinfo.gametype) ||
+ LocalWeapons.LocateWeapon(type, NULL, NULL))
{
- GiveSpawner (player, type, 1);
+ AWeapon *def = (AWeapon*)GetDefaultByType (type);
+ if (!(def->WeaponFlags & WIF_CHEATNOTWEAPON))
+ {
+ GiveSpawner (player, type, 1);
+ }
}
}
}
@@ -860,33 +856,17 @@ void cht_Take (player_t *player, const char *name, int amount)
if (takeall || stricmp (name, "backpack") == 0)
{
- // Select the correct type of backpack based on the game
- if (gameinfo.gametype == GAME_Heretic)
+ // Take away all types of backpacks the player might own.
+ for (unsigned int i = 0; i < PClass::m_Types.Size(); ++i)
{
- type = PClass::FindClass ("BagOfHolding");
- }
- else if (gameinfo.gametype == GAME_Strife)
- {
- type = PClass::FindClass ("AmmoSatchel");
- }
- else if (gameinfo.gametype == GAME_Doom)
- {
- type = PClass::FindClass ("Backpack");
- }
- else if (gameinfo.gametype == GAME_Chex)
- {
- type = PClass::FindClass ("Zorchpack");
- }
- else
- { // Hexen doesn't have a backpack, foo!
- type = NULL;
- }
- if (type != NULL)
- {
- AActor *backpack = player->mo->FindInventory (type);
+ const PClass *type = PClass::m_Types[i];
- if (backpack)
- backpack->Destroy ();
+ if (type->IsDescendantOf(RUNTIME_CLASS (ABackpackItem)))
+ {
+ AInventory *pack = player->mo->FindInventory (type);
+
+ if (pack) pack->Destroy();
+ }
}
if (!takeall)
diff --git a/src/m_misc.cpp b/src/m_misc.cpp
index 381656e0..a7ef11e3 100644
--- a/src/m_misc.cpp
+++ b/src/m_misc.cpp
@@ -596,17 +596,7 @@ static bool FindFreeName (FString &fullname, const char *extension)
for (i = 0; i <= 9999; i++)
{
- const char *gamename;
-
- switch (gameinfo.gametype)
- {
- case GAME_Doom: gamename = "Doom_"; break;
- case GAME_Heretic: gamename = "Heretic_"; break;
- case GAME_Hexen: gamename = "Hexen_"; break;
- case GAME_Strife: gamename = "Strife_"; break;
- case GAME_Chex: gamename = "Chex_"; break;
- default: gamename = ""; break;
- }
+ const char *gamename = GameNames[gameinfo.gametype];
time_t now;
tm *tm;
@@ -616,18 +606,18 @@ static bool FindFreeName (FString &fullname, const char *extension)
if (tm == NULL)
{
- lbmname.Format ("%sScreenshot_%s%04d.%s", fullname.GetChars(), gamename, i, extension);
+ lbmname.Format ("%sScreenshot_%s_%04d.%s", fullname.GetChars(), gamename, i, extension);
}
else if (i == 0)
{
- lbmname.Format ("%sScreenshot_%s%04d%02d%02d_%02d%02d%02d.%s", fullname.GetChars(), gamename,
+ lbmname.Format ("%sScreenshot_%s_%04d%02d%02d_%02d%02d%02d.%s", fullname.GetChars(), gamename,
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec,
extension);
}
else
{
- lbmname.Format ("%sScreenshot_%s%04d%02d%02d_%02d%02d%02d_%02d.%s", fullname.GetChars(), gamename,
+ lbmname.Format ("%sScreenshot_%s_%04d%02d%02d_%02d%02d%02d_%02d.%s", fullname.GetChars(), gamename,
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec,
i, extension);
diff --git a/src/m_options.cpp b/src/m_options.cpp
index c4201947..78a336e1 100644
--- a/src/m_options.cpp
+++ b/src/m_options.cpp
@@ -1392,7 +1392,7 @@ static BYTE BitTranslate[32];
void M_OptInit (void)
{
- if (gameinfo.gametype == GAME_Doom)
+ if (gameinfo.gametype & GAME_DoomChex)
{
LabelColor = CR_UNTRANSLATED;
ValueColor = CR_GRAY;
@@ -2999,6 +2999,7 @@ void UpdateJoystickMenu ()
JoystickItems[line].type = discrete;
JoystickItems[line].a.intcvar = cvars[i];
JoystickItems[line].b.numvalues = 6.f;
+ JoystickItems[line].d.graycheck = NULL;
JoystickItems[line].e.values = JoyAxisMapNames;
line++;
}
diff --git a/src/m_png.h b/src/m_png.h
index 8dd7c01a..7815369c 100644
--- a/src/m_png.h
+++ b/src/m_png.h
@@ -35,8 +35,7 @@
#include
#include "doomtype.h"
-
-enum ESSType;
+#include "v_video.h"
// PNG Writing --------------------------------------------------------------
@@ -116,4 +115,4 @@ class FTexture;
FTexture *PNGTexture_CreateFromFile(PNGHandle *png, const FString &filename);
-#endif
\ No newline at end of file
+#endif
diff --git a/src/p_acs.cpp b/src/p_acs.cpp
index b64ce92a..9949f7a4 100644
--- a/src/p_acs.cpp
+++ b/src/p_acs.cpp
@@ -5230,16 +5230,13 @@ int DLevelScript::RunScript ()
case PCD_SETACTORSTATE:
{
const char *statename = FBehavior::StaticLookupString (STACK(2));
- TArray statelist;
FState *state;
- MakeStateNameList(statename, &statelist);
-
if (STACK(3) == 0)
{
if (activator != NULL)
{
- state = activator->GetClass()->ActorInfo->FindState (statelist.Size(), &statelist[0], !!STACK(1));
+ state = activator->GetClass()->ActorInfo->FindStateByString (statename, !!STACK(1));
if (state != NULL)
{
activator->SetState (state);
@@ -5259,7 +5256,7 @@ int DLevelScript::RunScript ()
while ( (actor = iterator.Next ()) )
{
- state = actor->GetClass()->ActorInfo->FindState (statelist.Size(), &statelist[0], !!STACK(1));
+ state = actor->GetClass()->ActorInfo->FindStateByString (statename, !!STACK(1));
if (state != NULL)
{
actor->SetState (state);
diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp
index e7d88183..e053efe7 100644
--- a/src/p_mobj.cpp
+++ b/src/p_mobj.cpp
@@ -4968,10 +4968,6 @@ int AActor::DoSpecialDamage (AActor *target, int damage)
int AActor::TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FName damagetype)
{
- // If the actor does not have a corresponding death state, then it does not take damage.
- // Note that DeathState matches every kind of damagetype, so if an actor has that, it can
- // be hurt with any type of damage. Exception: Massacre damage always succeeds, because
- // it needs to work.
FState *death;
if (flags5 & MF5_NODAMAGE)
@@ -4985,7 +4981,7 @@ int AActor::TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FN
// it needs to work.
// Always kill if there is a regular death state or no death states at all.
- if (FindState (NAME_Death) != NULL || !HasSpecialDeathStates())
+ if (FindState (NAME_Death) != NULL || !HasSpecialDeathStates() || damagetype == NAME_Massacre)
{
return damage;
}
@@ -5044,3 +5040,45 @@ void AActor::SetIdle()
if (idle == NULL) idle = SpawnState;
SetState(idle);
}
+
+FDropItem *AActor::GetDropItems()
+{
+ unsigned int index = GetClass()->Meta.GetMetaInt (ACMETA_DropItems) - 1;
+
+ if (index >= 0 && index < DropItemList.Size())
+ {
+ return DropItemList[index];
+ }
+ return NULL;
+}
+
+//----------------------------------------------------------------------------
+//
+// DropItem handling
+//
+//----------------------------------------------------------------------------
+FDropItemPtrArray DropItemList;
+
+void FreeDropItemChain(FDropItem *chain)
+{
+ while (chain != NULL)
+ {
+ FDropItem *next = chain->Next;
+ delete chain;
+ chain = next;
+ }
+}
+
+FDropItemPtrArray::~FDropItemPtrArray()
+{
+ for (unsigned int i = 0; i < Size(); ++i)
+ {
+ FreeDropItemChain ((*this)[i]);
+ }
+}
+
+int StoreDropItemChain(FDropItem *chain)
+{
+ return DropItemList.Push (chain) + 1;
+}
+
diff --git a/src/p_states.cpp b/src/p_states.cpp
new file mode 100644
index 00000000..0bda6dca
--- /dev/null
+++ b/src/p_states.cpp
@@ -0,0 +1,814 @@
+/*
+** p_states.cpp
+** state management
+**
+**---------------------------------------------------------------------------
+** Copyright 1998-2008 Randy Heit
+** Copyright 2006-2008 Christoph Oelckers
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+**
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**---------------------------------------------------------------------------
+**
+**
+*/
+#include "actor.h"
+#include "farchive.h"
+#include "templates.h"
+#include "cmdlib.h"
+#include "i_system.h"
+#include "thingdef/thingdef.h"
+
+// Each state is owned by an actor. Actors can own any number of
+// states, but a single state cannot be owned by more than one
+// actor. States are archived by recording the actor they belong
+// to and the index into that actor's list of states.
+
+// For NULL states, which aren't owned by any actor, the owner
+// is recorded as AActor with the following state. AActor should
+// never actually have this many states of its own, so this
+// is (relatively) safe.
+
+#define NULL_STATE_INDEX 127
+
+TArray JumpParameters;
+
+//==========================================================================
+//
+//
+//==========================================================================
+
+FArchive &operator<< (FArchive &arc, FState *&state)
+{
+ const PClass *info;
+
+ if (arc.IsStoring ())
+ {
+ if (state == NULL)
+ {
+ arc.UserWriteClass (RUNTIME_CLASS(AActor));
+ arc.WriteCount (NULL_STATE_INDEX);
+ return arc;
+ }
+
+ info = FState::StaticFindStateOwner (state);
+
+ if (info != NULL)
+ {
+ arc.UserWriteClass (info);
+ arc.WriteCount ((DWORD)(state - info->ActorInfo->OwnedStates));
+ }
+ else
+ {
+ /* this was never working as intended.
+ I_Error ("Cannot find owner for state %p:\n"
+ "%s %c%c %3d [%p] -> %p", state,
+ sprites[state->sprite].name,
+ state->GetFrame() + 'A',
+ state->GetFullbright() ? '*' : ' ',
+ state->GetTics(),
+ state->GetAction(),
+ state->GetNextState());
+ */
+ }
+ }
+ else
+ {
+ const PClass *info;
+ DWORD ofs;
+
+ arc.UserReadClass (info);
+ ofs = arc.ReadCount ();
+ if (ofs == NULL_STATE_INDEX && info == RUNTIME_CLASS(AActor))
+ {
+ state = NULL;
+ }
+ else if (info->ActorInfo != NULL)
+ {
+ state = info->ActorInfo->OwnedStates + ofs;
+ }
+ else
+ {
+ state = NULL;
+ }
+ }
+ return arc;
+}
+
+//==========================================================================
+//
+// Find the actor that a state belongs to.
+//
+//==========================================================================
+
+const PClass *FState::StaticFindStateOwner (const FState *state)
+{
+ for (unsigned int i = 0; i < PClass::m_RuntimeActors.Size(); ++i)
+ {
+ FActorInfo *info = PClass::m_RuntimeActors[i]->ActorInfo;
+ if (state >= info->OwnedStates &&
+ state < info->OwnedStates + info->NumOwnedStates)
+ {
+ return info->Class;
+ }
+ }
+
+ return NULL;
+}
+
+//==========================================================================
+//
+// Find the actor that a state belongs to, but restrict the search to
+// the specified type and its ancestors.
+//
+//==========================================================================
+
+const PClass *FState::StaticFindStateOwner (const FState *state, const FActorInfo *info)
+{
+ while (info != NULL)
+ {
+ if (state >= info->OwnedStates &&
+ state < info->OwnedStates + info->NumOwnedStates)
+ {
+ return info->Class;
+ }
+ info = info->Class->ParentClass->ActorInfo;
+ }
+ return NULL;
+}
+
+
+//==========================================================================
+//
+//
+//==========================================================================
+
+FStateLabel *FStateLabels::FindLabel (FName label)
+{
+ return const_cast(BinarySearch (Labels, NumLabels, &FStateLabel::Label, label));
+}
+
+void FStateLabels::Destroy ()
+{
+ for(int i=0; iDestroy();
+ free (Labels[i].Children); // These are malloc'd, not new'd!
+ Labels[i].Children=NULL;
+ }
+ }
+}
+
+
+//===========================================================================
+//
+// HasStates
+//
+// Checks whether the actor has special death states.
+//
+//===========================================================================
+
+bool AActor::HasSpecialDeathStates () const
+{
+ const FActorInfo *info = GetClass()->ActorInfo;
+
+ if (info->StateList != NULL)
+ {
+ FStateLabel *slabel = info->StateList->FindLabel (NAME_Death);
+ if (slabel != NULL && slabel->Children != NULL)
+ {
+ for(int i=0;iChildren->NumLabels;i++)
+ {
+ if (slabel->Children->Labels[i].State != NULL) return true;
+ }
+ }
+ }
+ return false;
+}
+
+//==========================================================================
+//
+// Resolves a label parameter
+//
+//==========================================================================
+
+FState *P_GetState(AActor *self, FState *CallingState, int offset)
+{
+ if (offset == 0 || offset == INT_MIN)
+ {
+ return NULL; // 0 means 'no state'
+ }
+ else if (offset>0)
+ {
+ if (CallingState == NULL) return NULL;
+ return CallingState + offset;
+ }
+ else if (self != NULL)
+ {
+ FName *params = &JumpParameters[-offset];
+
+ FName classname = params[0];
+ const PClass *cls;
+ cls = classname==NAME_None? RUNTIME_TYPE(self) : PClass::FindClass(classname);
+ if (cls==NULL || cls->ActorInfo==NULL) return NULL; // shouldn't happen
+
+ int numnames = (int)params[1];
+ FState *jumpto = cls->ActorInfo->FindState(numnames, ¶ms[2]);
+ if (jumpto == NULL)
+ {
+ const char *dot="";
+ Printf("Jump target '");
+ if (classname != NAME_None) Printf("%s::", classname.GetChars());
+ for (int i=0;iGetClass()->TypeName.GetChars());
+ }
+ return jumpto;
+ }
+ else return NULL;
+}
+
+//==========================================================================
+//
+// Creates a list of names from a string. Dots are used as separator
+//
+//==========================================================================
+
+TArray &MakeStateNameList(const char * fname)
+{
+ static TArray namelist(3);
+ FName firstpart, secondpart;
+ char * c;
+
+ // Handle the old names for the existing death states
+ char * name = copystring(fname);
+ firstpart = strtok(name, ".");
+ switch (firstpart)
+ {
+ case NAME_Burn:
+ firstpart = NAME_Death;
+ secondpart = NAME_Fire;
+ break;
+ case NAME_Ice:
+ firstpart = NAME_Death;
+ secondpart = NAME_Ice;
+ break;
+ case NAME_Disintegrate:
+ firstpart = NAME_Death;
+ secondpart = NAME_Disintegrate;
+ break;
+ case NAME_XDeath:
+ firstpart = NAME_Death;
+ secondpart = NAME_Extreme;
+ break;
+ }
+
+ namelist.Clear();
+ namelist.Push(firstpart);
+ if (secondpart!=NAME_None) namelist.Push(secondpart);
+
+ while ((c = strtok(NULL, "."))!=NULL)
+ {
+ FName cc = c;
+ namelist.Push(cc);
+ }
+ delete [] name;
+ return namelist;
+}
+
+//===========================================================================
+//
+// FindState (multiple names version)
+//
+// Finds a state that matches as many of the supplied names as possible.
+// A state with more names than those provided does not match.
+// A state with fewer names can match if there are no states with the exact
+// same number of names.
+//
+// The search proceeds like this. For the current class, keeping matching
+// names until there are no more. If both the argument list and the state
+// are out of names, it's an exact match, so return it. If the state still
+// has names, ignore it. If the argument list still has names, remember it.
+//
+//===========================================================================
+FState *FActorInfo::FindState (int numnames, FName *names, bool exact) const
+{
+ FStateLabels *labels = StateList;
+ FState *best = NULL;
+
+ if (labels != NULL)
+ {
+ int count = 0;
+ FStateLabel *slabel = NULL;
+ FName label;
+
+ // Find the best-matching label for this class.
+ while (labels != NULL && count < numnames)
+ {
+ label = *names++;
+ slabel = labels->FindLabel (label);
+
+ if (slabel != NULL)
+ {
+ count++;
+ labels = slabel->Children;
+ best = slabel->State;
+ }
+ else
+ {
+ break;
+ }
+ }
+ if (count < numnames && exact) return NULL;
+ }
+ return best;
+}
+
+//==========================================================================
+//
+// Finds the state associated with the given string
+//
+//==========================================================================
+
+FState *FActorInfo::FindStateByString(const char *name, bool exact)
+{
+ TArray &namelist = MakeStateNameList(name);
+ return FindState(namelist.Size(), &namelist[0], exact);
+}
+
+
+
+
+//==========================================================================
+//
+// Search one list of state definitions for the given name
+//
+//==========================================================================
+
+FStateDefine *FStateDefinitions::FindStateLabelInList(TArray & list, FName name, bool create)
+{
+ for(unsigned i = 0; i &namelist = MakeStateNameList(name);
+
+ TArray * statelist = &StateLabels;
+ for(unsigned i=0;iChildren;
+ }
+ return statedef;
+}
+
+//==========================================================================
+//
+// Adds a new state tp the curremt list
+//
+//==========================================================================
+
+void FStateDefinitions::AddState (const char *statename, FState *state, BYTE defflags)
+{
+ FStateDefine *std = FindStateAddress(statename);
+ std->State = state;
+ std->DefineFlags = defflags;
+}
+
+//==========================================================================
+//
+// Finds the state associated with the given name
+// returns NULL if none found
+//
+//==========================================================================
+
+FState * FStateDefinitions::FindState(const char * name)
+{
+ FStateDefine * statedef=NULL;
+
+ TArray &namelist = MakeStateNameList(name);
+
+ TArray * statelist = &StateLabels;
+ for(unsigned i=0;iChildren;
+ }
+ return statedef? statedef->State : NULL;
+}
+
+//==========================================================================
+//
+// Creates the final list of states from the state definitions
+//
+//==========================================================================
+
+static int STACK_ARGS labelcmp(const void * a, const void * b)
+{
+ FStateLabel * A = (FStateLabel *)a;
+ FStateLabel * B = (FStateLabel *)b;
+ return ((int)A->Label - (int)B->Label);
+}
+
+FStateLabels * FStateDefinitions::CreateStateLabelList(TArray & statelist)
+{
+ // First delete all empty labels from the list
+ for (int i=statelist.Size()-1;i>=0;i--)
+ {
+ if (statelist[i].Label == NAME_None || (statelist[i].State == NULL && statelist[i].Children.Size() == 0))
+ {
+ statelist.Delete(i);
+ }
+ }
+
+ int count=statelist.Size();
+
+ if (count == 0) return NULL;
+
+ FStateLabels * list = (FStateLabels*)M_Malloc(sizeof(FStateLabels)+(count-1)*sizeof(FStateLabel));
+ list->NumLabels = count;
+
+ for (int i=0;iLabels[i].Label = statelist[i].Label;
+ list->Labels[i].State = statelist[i].State;
+ list->Labels[i].Children = CreateStateLabelList(statelist[i].Children);
+ }
+ qsort(list->Labels, count, sizeof(FStateLabel), labelcmp);
+ return list;
+}
+
+//===========================================================================
+//
+// InstallStates
+//
+// Creates the actor's state list from the current definition
+//
+//===========================================================================
+
+void FStateDefinitions::InstallStates(FActorInfo *info, AActor *defaults)
+{
+ // First ensure we have a valid spawn state.
+ FState *state = FindState("Spawn");
+
+ if (state == NULL)
+ {
+ // A NULL spawn state will crash the engine so set it to something valid.
+ AddState("Spawn", GetDefault()->SpawnState);
+ }
+
+ if (info->StateList != NULL)
+ {
+ info->StateList->Destroy();
+ M_Free(info->StateList);
+ }
+ info->StateList = CreateStateLabelList(StateLabels);
+
+ // Cache these states as member veriables.
+ defaults->SpawnState = info->FindState(NAME_Spawn);
+ defaults->SeeState = info->FindState(NAME_See);
+ // Melee and Missile states are manipulated by the scripted marines so they
+ // have to be stored locally
+ defaults->MeleeState = info->FindState(NAME_Melee);
+ defaults->MissileState = info->FindState(NAME_Missile);
+}
+
+//===========================================================================
+//
+// MakeStateDefines
+//
+// Creates a list of state definitions from an existing actor
+// Used by Dehacked to modify an actor's state list
+//
+//===========================================================================
+
+void FStateDefinitions::MakeStateList(const FStateLabels *list, TArray &dest)
+{
+ dest.Clear();
+ if (list != NULL) for(int i=0;iNumLabels;i++)
+ {
+ FStateDefine def;
+
+ def.Label = list->Labels[i].Label;
+ def.State = list->Labels[i].State;
+ dest.Push(def);
+ if (list->Labels[i].Children != NULL)
+ {
+ MakeStateList(list->Labels[i].Children, dest[dest.Size()-1].Children);
+ }
+ }
+}
+
+void FStateDefinitions::MakeStateDefines(const PClass *cls)
+{
+ if (cls->ActorInfo && cls->ActorInfo->StateList)
+ {
+ MakeStateList(cls->ActorInfo->StateList, StateLabels);
+ }
+ else
+ {
+ ClearStateLabels();
+ }
+}
+
+//===========================================================================
+//
+// AddStateDefines
+//
+// Adds a list of states to the current definitions
+//
+//===========================================================================
+
+void FStateDefinitions::AddStateDefines(const FStateLabels *list)
+{
+ if (list != NULL) for(int i=0;iNumLabels;i++)
+ {
+ if (list->Labels[i].Children == NULL)
+ {
+ if (!FindStateLabelInList(StateLabels, list->Labels[i].Label, false))
+ {
+ FStateDefine def;
+
+ def.Label = list->Labels[i].Label;
+ def.State = list->Labels[i].State;
+ StateLabels.Push(def);
+ }
+ }
+ }
+}
+
+//==========================================================================
+//
+// RetargetState(Pointer)s
+//
+// These functions are used when a goto follows one or more labels.
+// Because multiple labels are permitted to occur consecutively with no
+// intervening states, it is not enough to remember the last label defined
+// and adjust it. So these functions search for all labels that point to
+// the current position in the state array and give them a copy of the
+// target string instead.
+//
+//==========================================================================
+
+void FStateDefinitions::RetargetStatePointers (intptr_t count, const char *target, TArray & statelist)
+{
+ for(unsigned i = 0;i 0)
+ {
+ RetargetStatePointers(count, target, statelist[i].Children);
+ }
+ }
+}
+
+void FStateDefinitions::RetargetStates (intptr_t count, const char *target)
+{
+ RetargetStatePointers(count, target, StateLabels);
+}
+
+
+//==========================================================================
+//
+// ResolveGotoLabel
+//
+// Resolves any strings being stored in a state's NextState field
+//
+//==========================================================================
+
+FState *FStateDefinitions::ResolveGotoLabel (AActor *actor, const PClass *mytype, char *name)
+{
+ const PClass *type=mytype;
+ FState *state;
+ char *namestart = name;
+ char *label, *offset, *pt;
+ int v;
+
+ // Check for classname
+ if ((pt = strstr (name, "::")) != NULL)
+ {
+ const char *classname = name;
+ *pt = '\0';
+ name = pt + 2;
+
+ // The classname may either be "Super" to identify this class's immediate
+ // superclass, or it may be the name of any class that this one derives from.
+ if (stricmp (classname, "Super") == 0)
+ {
+ type = type->ParentClass;
+ actor = GetDefaultByType (type);
+ }
+ else
+ {
+ // first check whether a state of the desired name exists
+ const PClass *stype = PClass::FindClass (classname);
+ if (stype == NULL)
+ {
+ I_Error ("%s is an unknown class.", classname);
+ }
+ if (!stype->IsDescendantOf (RUNTIME_CLASS(AActor)))
+ {
+ I_Error ("%s is not an actor class, so it has no states.", stype->TypeName.GetChars());
+ }
+ if (!stype->IsAncestorOf (type))
+ {
+ I_Error ("%s is not derived from %s so cannot access its states.",
+ type->TypeName.GetChars(), stype->TypeName.GetChars());
+ }
+ if (type != stype)
+ {
+ type = stype;
+ actor = GetDefaultByType (type);
+ }
+ }
+ }
+ label = name;
+ // Check for offset
+ offset = NULL;
+ if ((pt = strchr (name, '+')) != NULL)
+ {
+ *pt = '\0';
+ offset = pt + 1;
+ }
+ v = offset ? strtol (offset, NULL, 0) : 0;
+
+ // Get the state's address.
+ if (type==mytype) state = FindState (label);
+ else state = type->ActorInfo->FindStateByString(label, true);
+
+ if (state != NULL)
+ {
+ state += v;
+ }
+ else if (v != 0)
+ {
+ I_Error ("Attempt to get invalid state %s from actor %s.", label, type->TypeName.GetChars());
+ }
+ delete[] namestart; // free the allocated string buffer
+ return state;
+}
+
+//==========================================================================
+//
+// FixStatePointers
+//
+// Fixes an actor's default state pointers.
+//
+//==========================================================================
+
+void FStateDefinitions::FixStatePointers (FActorInfo *actor, TArray & list)
+{
+ for(unsigned i=0;i= 1 && v < 0x10000)
+ {
+ list[i].State = actor->OwnedStates + v - 1;
+ }
+ if (list[i].Children.Size() > 0) FixStatePointers(actor, list[i].Children);
+ }
+}
+
+//==========================================================================
+//
+// ResolveGotoLabels
+//
+// Resolves an actor's state pointers that were specified as jumps.
+//
+//==========================================================================
+
+void FStateDefinitions::ResolveGotoLabels (FActorInfo *actor, AActor *defaults, TArray & list)
+{
+ for(unsigned i=0;iClass, (char *)list[i].State);
+ list[i].DefineFlags = SDF_STATE;
+ }
+ if (list[i].Children.Size() > 0) ResolveGotoLabels(actor, defaults, list[i].Children);
+ }
+}
+
+
+//==========================================================================
+//
+// FinishStates
+// copies a state block and fixes all state links using the current list of labels
+//
+//==========================================================================
+
+int FStateDefinitions::FinishStates (FActorInfo *actor, AActor *defaults, TArray &StateArray)
+{
+ static int c=0;
+ int count = StateArray.Size();
+
+ if (count > 0)
+ {
+ FState *realstates = new FState[count];
+ int i;
+ int currange;
+
+ memcpy(realstates, &StateArray[0], count*sizeof(FState));
+ actor->OwnedStates = realstates;
+ actor->NumOwnedStates = count;
+
+ // adjust the state pointers
+ // In the case new states are added these must be adjusted, too!
+ FixStatePointers (actor, StateLabels);
+
+ for(i = currange = 0; i < count; i++)
+ {
+ // resolve labels and jumps
+ switch(realstates[i].DefineFlags)
+ {
+ case SDF_STOP: // stop
+ realstates[i].NextState = NULL;
+ break;
+
+ case SDF_WAIT: // wait
+ realstates[i].NextState = &realstates[i];
+ break;
+
+ case SDF_NEXT: // next
+ realstates[i].NextState = (i < count-1 ? &realstates[i+1] : &realstates[0]);
+ break;
+
+ case SDF_INDEX: // loop
+ realstates[i].NextState = &realstates[(size_t)realstates[i].NextState-1];
+ break;
+
+ case SDF_LABEL:
+ realstates[i].NextState = ResolveGotoLabel (defaults, actor->Class, (char *)realstates[i].NextState);
+ break;
+ }
+ }
+ }
+
+ // Fix state pointers that are gotos
+ ResolveGotoLabels (actor, defaults, StateLabels);
+
+ return count;
+}
+
diff --git a/src/p_teleport.cpp b/src/p_teleport.cpp
index c1b3bb35..b60fe0bd 100644
--- a/src/p_teleport.cpp
+++ b/src/p_teleport.cpp
@@ -80,47 +80,15 @@ void P_SpawnTeleportFog(fixed_t x, fixed_t y, fixed_t z, int spawnid)
{
fog = SpawnableThings[spawnid];
}
- /* if (fog != NULL && level.info->teleportfog != NAME_None)
- {
- fog = PClass::FindClass(level.info->teleportfog);
- }
- */
if (fog == NULL)
{
AActor *mo = Spawn ("TeleportFog", x, y, z + TELEFOGHEIGHT, ALLOW_REPLACE);
- if (mo != NULL)
- {
- FState * state = NULL;
-
- switch(gameinfo.gametype)
- {
- default:
- case GAME_Doom:
- state = mo->FindState(NAME_Doom);
- break;
-
- case GAME_Heretic:
- state = mo->FindState(NAME_Heretic);
- break;
-
- case GAME_Hexen:
- state = mo->FindState(NAME_Hexen);
- break;
-
- case GAME_Strife:
- state = mo->FindState(NAME_Strife);
- break;
- }
- if (state == NULL) state = mo->SpawnState; // allow execution of code pointers in the spawn state
-
- mo->SetState(state);
- }
}
else
{
AActor *mo = Spawn (fog, x, y, z, ALLOW_REPLACE);
- if (mo != NULL) mo->SetState(mo->SpawnState);
+ if (mo != NULL) S_Sound(mo, CHAN_BODY, mo->SeeSound, 1.f, ATTN_NORM);
}
}
diff --git a/src/p_udmf.cpp b/src/p_udmf.cpp
index 7cfc8ddc..da34393b 100644
--- a/src/p_udmf.cpp
+++ b/src/p_udmf.cpp
@@ -1124,6 +1124,7 @@ struct UDMFParser
{
default: // Shh, GCC
case GAME_Doom:
+ case GAME_Chex:
namespace_bits = Dm;
P_LoadTranslator("xlat/doom_base.txt");
break;
diff --git a/src/p_user.cpp b/src/p_user.cpp
index 1ed9270a..49a2e716 100644
--- a/src/p_user.cpp
+++ b/src/p_user.cpp
@@ -227,8 +227,8 @@ player_t::player_t()
momy(0),
centering(0),
turnticks(0),
- oldbuttons(0),
attackdown(0),
+ oldbuttons(0),
health(0),
inventorytics(0),
CurrentPlayerClass(0),
@@ -988,7 +988,7 @@ void APlayerPawn::GiveDefaultInventory ()
AddInventory (barmor);
// Now add the items from the DECORATE definition
- FDropItem *di = GetDropItems(RUNTIME_TYPE(this));
+ FDropItem *di = GetDropItems();
while (di)
{
diff --git a/src/r_data.cpp b/src/r_data.cpp
index f382b9a2..b999b641 100644
--- a/src/r_data.cpp
+++ b/src/r_data.cpp
@@ -265,9 +265,7 @@ DWORD R_BlendForColormap (DWORD map)
void R_InitData ()
{
- FTexture::InitGrayMap();
StartScreen->Progress();
- TexMan.Init();
V_InitFonts();
StartScreen->Progress();
diff --git a/src/r_main.h b/src/r_main.h
index 049f1213..515f7717 100644
--- a/src/r_main.h
+++ b/src/r_main.h
@@ -54,8 +54,8 @@ extern bool LocalKeyboardTurner; // [RH] The local player used the keyboard t
extern float WallTMapScale;
extern float WallTMapScale2;
-extern int viewwidth;
-extern int viewheight;
+extern "C" int viewwidth;
+extern "C" int viewheight;
extern int viewwindowx;
extern int viewwindowy;
diff --git a/src/r_translate.cpp b/src/r_translate.cpp
index f6ec46c2..4a048128 100644
--- a/src/r_translate.cpp
+++ b/src/r_translate.cpp
@@ -43,6 +43,9 @@
#include "colormatcher.h"
#include "d_netinf.h"
#include "v_palette.h"
+#include "sc_man.h"
+#include "doomerrors.h"
+#include "i_system.h"
#include "gi.h"
#include "stats.h"
@@ -82,11 +85,23 @@ FRemapTable::FRemapTable(int count)
// the caller will do that next, if only by calling MakeIdentity().
}
+//----------------------------------------------------------------------------
+//
+//
+//
+//----------------------------------------------------------------------------
+
FRemapTable::~FRemapTable()
{
Free();
}
+//----------------------------------------------------------------------------
+//
+//
+//
+//----------------------------------------------------------------------------
+
void FRemapTable::Alloc(int count)
{
Remap = (BYTE *)M_Malloc(count*sizeof(*Remap) + count*sizeof(*Palette));
@@ -96,6 +111,12 @@ void FRemapTable::Alloc(int count)
NumEntries = count;
}
+//----------------------------------------------------------------------------
+//
+//
+//
+//----------------------------------------------------------------------------
+
void FRemapTable::Free()
{
KillNative();
@@ -108,6 +129,12 @@ void FRemapTable::Free()
}
}
+//----------------------------------------------------------------------------
+//
+//
+//
+//----------------------------------------------------------------------------
+
FRemapTable::FRemapTable(const FRemapTable &o)
{
Remap = NULL;
@@ -116,6 +143,12 @@ FRemapTable::FRemapTable(const FRemapTable &o)
operator= (o);
}
+//----------------------------------------------------------------------------
+//
+//
+//
+//----------------------------------------------------------------------------
+
FRemapTable &FRemapTable::operator=(const FRemapTable &o)
{
if (&o == this)
@@ -134,6 +167,12 @@ FRemapTable &FRemapTable::operator=(const FRemapTable &o)
return *this;
}
+//----------------------------------------------------------------------------
+//
+//
+//
+//----------------------------------------------------------------------------
+
bool FRemapTable::operator==(const FRemapTable &o)
{
// Two translations are identical when they have the same amount of colors
@@ -143,6 +182,12 @@ bool FRemapTable::operator==(const FRemapTable &o)
return !memcmp(o.Palette, Palette, NumEntries * sizeof(*Palette));
}
+//----------------------------------------------------------------------------
+//
+//
+//
+//----------------------------------------------------------------------------
+
void FRemapTable::Serialize(FArchive &arc)
{
int n = NumEntries;
@@ -167,6 +212,11 @@ void FRemapTable::Serialize(FArchive &arc)
}
}
+//----------------------------------------------------------------------------
+//
+//
+//
+//----------------------------------------------------------------------------
void FRemapTable::MakeIdentity()
{
@@ -186,6 +236,12 @@ void FRemapTable::MakeIdentity()
}
}
+//----------------------------------------------------------------------------
+//
+//
+//
+//----------------------------------------------------------------------------
+
bool FRemapTable::IsIdentity() const
{
for (int j = 0; j < 256; ++j)
@@ -198,6 +254,12 @@ bool FRemapTable::IsIdentity() const
return true;
}
+//----------------------------------------------------------------------------
+//
+//
+//
+//----------------------------------------------------------------------------
+
void FRemapTable::KillNative()
{
if (Native != NULL)
@@ -207,6 +269,12 @@ void FRemapTable::KillNative()
}
}
+//----------------------------------------------------------------------------
+//
+//
+//
+//----------------------------------------------------------------------------
+
void FRemapTable::UpdateNative()
{
if (Native != NULL)
@@ -215,6 +283,12 @@ void FRemapTable::UpdateNative()
}
}
+//----------------------------------------------------------------------------
+//
+//
+//
+//----------------------------------------------------------------------------
+
FNativePalette *FRemapTable::GetNative()
{
if (Native == NULL)
@@ -224,6 +298,12 @@ FNativePalette *FRemapTable::GetNative()
return Native;
}
+//----------------------------------------------------------------------------
+//
+//
+//
+//----------------------------------------------------------------------------
+
void FRemapTable::AddIndexRange(int start, int end, int pal1, int pal2)
{
fixed_t palcol, palstep;
@@ -250,6 +330,12 @@ void FRemapTable::AddIndexRange(int start, int end, int pal1, int pal2)
}
}
+//----------------------------------------------------------------------------
+//
+//
+//
+//----------------------------------------------------------------------------
+
void FRemapTable::AddColorRange(int start, int end, int _r1,int _g1, int _b1, int _r2, int _g2, int _b2)
{
fixed_t r1 = _r1 << FRACBITS;
@@ -304,6 +390,160 @@ void FRemapTable::AddColorRange(int start, int end, int _r1,int _g1, int _b1, in
}
}
+//----------------------------------------------------------------------------
+//
+//
+//
+//----------------------------------------------------------------------------
+
+void FRemapTable::AddToTranslation(const char * range)
+{
+ int start,end;
+ FScanner sc;
+
+ sc.OpenMem("translation", range, int(strlen(range)));
+ sc.SetCMode(true);
+
+ try
+ {
+ sc.MustGetToken(TK_IntConst);
+ start = sc.Number;
+ sc.MustGetToken(':');
+ sc.MustGetToken(TK_IntConst);
+ end = sc.Number;
+ sc.MustGetToken('=');
+ if (!sc.CheckToken('['))
+ {
+ int pal1,pal2;
+
+ sc.MustGetToken(TK_IntConst);
+ pal1 = sc.Number;
+ sc.MustGetToken(':');
+ sc.MustGetToken(TK_IntConst);
+ pal2 = sc.Number;
+ AddIndexRange(start, end, pal1, pal2);
+ }
+ else
+ {
+ // translation using RGB values
+ int r1,g1,b1,r2,g2,b2;
+
+ sc.MustGetToken(TK_IntConst);
+ r1 = sc.Number;
+ sc.MustGetToken(',');
+
+ sc.MustGetToken(TK_IntConst);
+ g1 = sc.Number;
+ sc.MustGetToken(',');
+
+ sc.MustGetToken(TK_IntConst);
+ b1 = sc.Number;
+ sc.MustGetToken(']');
+ sc.MustGetToken(':');
+ sc.MustGetToken('[');
+
+ sc.MustGetToken(TK_IntConst);
+ r2 = sc.Number;
+ sc.MustGetToken(',');
+
+ sc.MustGetToken(TK_IntConst);
+ g2 = sc.Number;
+ sc.MustGetToken(',');
+
+ sc.MustGetToken(TK_IntConst);
+ b2 = sc.Number;
+ sc.MustGetToken(']');
+
+ AddColorRange(start, end, r1, g1, b1, r2, g2, b2);
+ }
+ }
+ catch (CRecoverableError &err)
+ {
+ Printf("Error in translation '%s':\n%s\n", err.GetMessage());
+ }
+}
+
+//----------------------------------------------------------------------------
+//
+// Stores a copy of this translation in the DECORATE translation table
+//
+//----------------------------------------------------------------------------
+
+int FRemapTable::StoreTranslation()
+{
+ unsigned int i;
+
+ for (i = 0; i < translationtables[TRANSLATION_Decorate].Size(); i++)
+ {
+ if (*this == *translationtables[TRANSLATION_Decorate][i])
+ {
+ // A duplicate of this translation already exists
+ return TRANSLATION(TRANSLATION_Decorate, i);
+ }
+ }
+ if (translationtables[TRANSLATION_Decorate].Size() >= MAX_DECORATE_TRANSLATIONS)
+ {
+ I_Error("Too many DECORATE translations");
+ }
+ FRemapTable *newtrans = new FRemapTable;
+ *newtrans = *this;
+ i = translationtables[TRANSLATION_Decorate].Push(newtrans);
+ return TRANSLATION(TRANSLATION_Decorate, i);
+}
+
+
+//----------------------------------------------------------------------------
+//
+//
+//
+//----------------------------------------------------------------------------
+
+TArray BloodTranslationColors;
+
+int CreateBloodTranslation(PalEntry color)
+{
+ unsigned int i;
+
+ if (BloodTranslationColors.Size() == 0)
+ {
+ // Don't use the first slot.
+ translationtables[TRANSLATION_Blood].Push(NULL);
+ BloodTranslationColors.Push(0);
+ }
+
+ for (i = 1; i < BloodTranslationColors.Size(); i++)
+ {
+ if (color.r == BloodTranslationColors[i].r &&
+ color.g == BloodTranslationColors[i].g &&
+ color.b == BloodTranslationColors[i].b)
+ {
+ // A duplicate of this translation already exists
+ return i;
+ }
+ }
+ if (BloodTranslationColors.Size() >= MAX_DECORATE_TRANSLATIONS)
+ {
+ I_Error("Too many blood colors");
+ }
+ FRemapTable *trans = new FRemapTable;
+ for (i = 0; i < 256; i++)
+ {
+ int bright = MAX(MAX(GPalette.BaseColors[i].r, GPalette.BaseColors[i].g), GPalette.BaseColors[i].b);
+ PalEntry pe = PalEntry(color.r*bright/255, color.g*bright/255, color.b*bright/255);
+ int entry = ColorMatcher.Pick(pe.r, pe.g, pe.b);
+
+ trans->Palette[i] = pe;
+ trans->Remap[i] = entry;
+ }
+ translationtables[TRANSLATION_Blood].Push(trans);
+ return BloodTranslationColors.Push(color);
+}
+
+//----------------------------------------------------------------------------
+//
+//
+//
+//----------------------------------------------------------------------------
FRemapTable *TranslationToTable(int translation)
{
@@ -323,6 +563,12 @@ FRemapTable *TranslationToTable(int translation)
return slots->operator[](index);
}
+//----------------------------------------------------------------------------
+//
+//
+//
+//----------------------------------------------------------------------------
+
static void PushIdentityTable(int slot)
{
FRemapTable *table = new FRemapTable;
@@ -330,11 +576,14 @@ static void PushIdentityTable(int slot)
translationtables[slot].Push(table);
}
+//----------------------------------------------------------------------------
//
// R_InitTranslationTables
// Creates the translation tables to map the green color ramp to gray,
// brown, red. Assumes a given structure of the PLAYPAL.
//
+//----------------------------------------------------------------------------
+
void R_InitTranslationTables ()
{
int i, j;
@@ -508,6 +757,12 @@ void R_InitTranslationTables ()
}
}
+//----------------------------------------------------------------------------
+//
+//
+//
+//----------------------------------------------------------------------------
+
void R_DeinitTranslationTables()
{
for (int i = 0; i < NUM_TRANSLATION_TABLES; ++i)
@@ -523,8 +778,13 @@ void R_DeinitTranslationTables()
}
}
+//----------------------------------------------------------------------------
+//
// [RH] Create a player's translation table based on a given mid-range color.
// [GRB] Split to 2 functions (because of player setup menu)
+//
+//----------------------------------------------------------------------------
+
static void SetRemap(FRemapTable *table, int i, float r, float g, float b)
{
int ir = clamp (int(r * 255.f), 0, 255);
@@ -534,6 +794,12 @@ static void SetRemap(FRemapTable *table, int i, float r, float g, float b)
table->Palette[i] = PalEntry(255, ir, ig, ib);
}
+//----------------------------------------------------------------------------
+//
+//
+//
+//----------------------------------------------------------------------------
+
static void R_CreatePlayerTranslation (float h, float s, float v, FPlayerSkin *skin, FRemapTable *table, FRemapTable *alttable)
{
int i;
@@ -675,6 +941,12 @@ static void R_CreatePlayerTranslation (float h, float s, float v, FPlayerSkin *s
table->UpdateNative();
}
+//----------------------------------------------------------------------------
+//
+//
+//
+//----------------------------------------------------------------------------
+
void R_BuildPlayerTranslation (int player)
{
float h, s, v;
@@ -687,6 +959,12 @@ void R_BuildPlayerTranslation (int player)
translationtables[TRANSLATION_PlayersExtra][player]);
}
+//----------------------------------------------------------------------------
+//
+//
+//
+//----------------------------------------------------------------------------
+
void R_GetPlayerTranslation (int color, FPlayerSkin *skin, FRemapTable *table)
{
float h, s, v;
@@ -696,3 +974,4 @@ void R_GetPlayerTranslation (int color, FPlayerSkin *skin, FRemapTable *table)
R_CreatePlayerTranslation (h, s, v, skin, table, NULL);
}
+
diff --git a/src/r_translate.h b/src/r_translate.h
index 84e481b0..098edb69 100644
--- a/src/r_translate.h
+++ b/src/r_translate.h
@@ -38,6 +38,8 @@ struct FRemapTable
void Serialize(FArchive &ar);
void AddIndexRange(int start, int end, int pal1, int pal2);
void AddColorRange(int start, int end, int r1,int g1, int b1, int r2, int g2, int b2);
+ void AddToTranslation(const char * range);
+ int StoreTranslation();
BYTE *Remap; // For the software renderer
PalEntry *Palette; // The ideal palette this maps to
@@ -99,6 +101,10 @@ void R_BuildPlayerTranslation (int player);
extern const BYTE IcePalette[16][3];
+extern TArray BloodTranslationColors;
+
+int CreateBloodTranslation(PalEntry color);
+
#endif // __R_TRANSLATE_H
diff --git a/src/s_advsound.cpp b/src/s_advsound.cpp
index 3bc4e993..4117930b 100644
--- a/src/s_advsound.cpp
+++ b/src/s_advsound.cpp
@@ -342,7 +342,10 @@ int S_PickReplacement (int refid)
unsigned int S_GetMSLength(FSoundID sound)
{
- if (sound < 0 || sound >= S_sfx.Size()) return 0;
+ if ((unsigned int)sound >= S_sfx.Size())
+ {
+ return 0;
+ }
sfxinfo_t *sfx = &S_sfx[sound];
diff --git a/src/s_sound.cpp b/src/s_sound.cpp
index 31f2ca25..96f5e807 100644
--- a/src/s_sound.cpp
+++ b/src/s_sound.cpp
@@ -1478,6 +1478,7 @@ void S_RelinkSound (AActor *from, AActor *to)
}
else
{
+ chan->Actor = NULL;
S_StopChannel(chan);
}
}
@@ -1778,7 +1779,7 @@ static void S_SetListener(SoundListener &listener, AActor *listenactor)
//
//==========================================================================
-float S_GetRolloff(FRolloffInfo *rolloff, float distance)
+float S_GetRolloff(FRolloffInfo *rolloff, float distance, bool logarithmic)
{
if (rolloff == NULL)
{
@@ -1803,13 +1804,27 @@ float S_GetRolloff(FRolloffInfo *rolloff, float distance)
{
volume = S_SoundCurve[int(S_SoundCurveSize * (1 - volume))] / 127.f;
}
- if (rolloff->RolloffType == ROLLOFF_Linear)
+ if (logarithmic)
{
- return volume;
+ if (rolloff->RolloffType == ROLLOFF_Linear)
+ {
+ return volume;
+ }
+ else
+ {
+ return float((powf(10.f, volume) - 1.) / 9.);
+ }
}
else
{
- return (powf(10.f, volume) - 1.f) / 9.f;
+ if (rolloff->RolloffType == ROLLOFF_Linear)
+ {
+ return float(log10(9. * volume + 1.));
+ }
+ else
+ {
+ return volume;
+ }
}
}
diff --git a/src/sc_man.cpp b/src/sc_man.cpp
index cf0622a7..6a228cf8 100644
--- a/src/sc_man.cpp
+++ b/src/sc_man.cpp
@@ -192,7 +192,7 @@ void FScanner::OpenFile (const char *name)
//
//==========================================================================
-void FScanner::OpenMem (const char *name, char *buffer, int size)
+void FScanner::OpenMem (const char *name, const char *buffer, int size)
{
Close ();
ScriptBuffer = FString(buffer, size);
diff --git a/src/sc_man.h b/src/sc_man.h
index 81061b9c..fba8275f 100644
--- a/src/sc_man.h
+++ b/src/sc_man.h
@@ -20,7 +20,7 @@ public:
void Open(const char *lumpname);
void OpenFile(const char *filename);
- void OpenMem(const char *name, char *buffer, int size);
+ void OpenMem(const char *name, const char *buffer, int size);
void OpenLumpNum(int lump);
void Close();
diff --git a/src/sdl/i_input.cpp b/src/sdl/i_input.cpp
index a22adafc..2f8ba9c6 100644
--- a/src/sdl/i_input.cpp
+++ b/src/sdl/i_input.cpp
@@ -9,6 +9,7 @@
#include "v_video.h"
#include "d_main.h"
+#include "d_event.h"
#include "d_gui.h"
#include "c_console.h"
#include "c_cvars.h"
diff --git a/src/sdl/i_main.cpp b/src/sdl/i_main.cpp
index f49c9bbd..5650c078 100644
--- a/src/sdl/i_main.cpp
+++ b/src/sdl/i_main.cpp
@@ -54,6 +54,11 @@
#include "errors.h"
#include "version.h"
#include "w_wad.h"
+#include "g_level.h"
+#include "r_state.h"
+#include "cmdlib.h"
+#include "r_main.h"
+#include "doomstat.h"
// MACROS ------------------------------------------------------------------
@@ -180,7 +185,7 @@ static int DoomSpecificInfo (char *buffer, char *end)
if (!viewactive)
{
- buffer += snprintf (buffer+p, size-p, "\n\nView not active.");
+ p += snprintf (buffer+p, size-p, "\n\nView not active.");
}
else
{
diff --git a/src/sdl/i_system.cpp b/src/sdl/i_system.cpp
index 9fb86414..78318b10 100644
--- a/src/sdl/i_system.cpp
+++ b/src/sdl/i_system.cpp
@@ -40,6 +40,7 @@
#include "SDL.h"
#include "doomtype.h"
+#include "doomstat.h"
#include "version.h"
#include "doomdef.h"
#include "cmdlib.h"
@@ -61,6 +62,9 @@
#include "hardware.h"
#include "gameconfigfile.h"
+#include "m_fixed.h"
+#include "g_level.h"
+
EXTERN_CVAR (String, language)
extern "C"
diff --git a/src/sdl/sdlvideo.cpp b/src/sdl/sdlvideo.cpp
index 7227ccef..b028aafa 100644
--- a/src/sdl/sdlvideo.cpp
+++ b/src/sdl/sdlvideo.cpp
@@ -9,7 +9,7 @@
#include "v_video.h"
#include "v_pfx.h"
#include "stats.h"
-
+#include "v_palette.h"
#include "sdlvideo.h"
#include
diff --git a/src/sdl/st_start.cpp b/src/sdl/st_start.cpp
index 7cb64ca9..81e50d23 100644
--- a/src/sdl/st_start.cpp
+++ b/src/sdl/st_start.cpp
@@ -42,6 +42,7 @@
#include "st_start.h"
#include "doomdef.h"
#include "i_system.h"
+#include "c_cvars.h"
// MACROS ------------------------------------------------------------------
diff --git a/src/sound/fmodsound.cpp b/src/sound/fmodsound.cpp
index dc29295e..9946edaf 100644
--- a/src/sound/fmodsound.cpp
+++ b/src/sound/fmodsound.cpp
@@ -44,6 +44,7 @@ extern HWND Window;
#define FALSE 0
#define TRUE 1
#endif
+#include
#include "templates.h"
#include "fmodsound.h"
@@ -2039,11 +2040,11 @@ float F_CALLBACK FMODSoundRenderer::RolloffCallback(FMOD_CHANNEL *channel, float
if (GRolloff != NULL)
{
- return S_GetRolloff(GRolloff, distance * GDistScale);
+ return S_GetRolloff(GRolloff, distance * GDistScale, true);
}
else if (chan->getUserData((void **)&schan) == FMOD_OK && schan != NULL)
{
- return S_GetRolloff(&schan->Rolloff, distance * schan->DistanceScale);
+ return S_GetRolloff(&schan->Rolloff, distance * schan->DistanceScale, true);
}
else
{
diff --git a/src/sound/i_sound.h b/src/sound/i_sound.h
index d7c07129..6844a754 100644
--- a/src/sound/i_sound.h
+++ b/src/sound/i_sound.h
@@ -141,7 +141,7 @@ void I_InitSound ();
void I_ShutdownSound ();
void S_ChannelEnded(FISoundChannel *schan);
-float S_GetRolloff(FRolloffInfo *rolloff, float distance);
+float S_GetRolloff(FRolloffInfo *rolloff, float distance, bool logarithmic);
FISoundChannel *S_GetChannel(void *syschan);
extern ReverbContainer *DefaultEnvironments[26];
diff --git a/src/sound/music_mus_midiout.cpp b/src/sound/music_mus_midiout.cpp
index d3872932..fd46dcdf 100644
--- a/src/sound/music_mus_midiout.cpp
+++ b/src/sound/music_mus_midiout.cpp
@@ -33,6 +33,7 @@
// HEADER FILES ------------------------------------------------------------
+#include
#include "i_musicinterns.h"
#include "templates.h"
#include "doomdef.h"
diff --git a/src/st_stuff.cpp b/src/st_stuff.cpp
index af728787..f0ee5ba8 100644
--- a/src/st_stuff.cpp
+++ b/src/st_stuff.cpp
@@ -346,7 +346,7 @@ bool ST_Responder (event_t *ev)
static int counts[] = { countof(DoomCheats), countof(HereticCheats), countof(HexenCheats),
countof(StrifeCheats), countof(ChexCheats), countof(SpecialCheats) };
- for (int i=0; iAddIndexRange(start, end, pal1, pal2);
- }
- else
- {
- // translation using RGB values
- int r1,g1,b1,r2,g2,b2;
-
- r1=strtol(range, &range, 10);
- if (!Check(range, ',')) return;
- g1=strtol(range, &range, 10);
- if (!Check(range, ',')) return;
- b1=strtol(range, &range, 10);
- if (!Check(range, ']')) return;
- if (!Check(range, ':')) return;
- if (!Check(range, '[')) return;
- r2=strtol(range, &range, 10);
- if (!Check(range, ',')) return;
- g2=strtol(range, &range, 10);
- if (!Check(range, ',')) return;
- b2=strtol(range, &range, 10);
- if (!Check(range, ']')) return;
-
- part.Translation->AddColorRange(start, end, r1, g1, b1, r2, g2, b2);
- }
+ part.Translation->AddToTranslation(sc.String);
}
while (sc.CheckString(","));
}
@@ -1161,6 +1117,11 @@ void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part)
}
}
+//==========================================================================
+//
+// Constructor for text based multipatch definitions
+//
+//==========================================================================
FMultiPatchTexture::FMultiPatchTexture (FScanner &sc, int usetype)
: Pixels (0), Spans(0), Parts(0), bRedirect(false), bTranslucentPatches(false)
diff --git a/src/textures/texturemanager.cpp b/src/textures/texturemanager.cpp
index 69828593..6ea67e54 100644
--- a/src/textures/texturemanager.cpp
+++ b/src/textures/texturemanager.cpp
@@ -330,33 +330,6 @@ void FTextureManager::ReplaceTexture (FTextureID picnum, FTexture *newtexture, b
}
}
-//==========================================================================
-//
-// FTextureManager :: AddPatch
-//
-//==========================================================================
-
-FTextureID FTextureManager::AddPatch (const char *patchname, int namespc, bool tryany)
-{
- if (patchname == NULL)
- {
- return FTextureID(-1);
- }
- FTextureID texnum = CheckForTexture (patchname, FTexture::TEX_MiscPatch, tryany);
-
- if (texnum.Exists())
- {
- return texnum;
- }
- int lumpnum = Wads.CheckNumForName (patchname, namespc==ns_global? ns_graphics:namespc);
- if (lumpnum < 0)
- {
- return FTextureID(-1);
- }
-
- return CreateTexture (lumpnum, FTexture::TEX_MiscPatch);
-}
-
//==========================================================================
//
// FTextureManager :: AddGroup
@@ -440,11 +413,6 @@ void FTextureManager::AddHiresTextures (int wadnum)
{
int amount = ListTextures(name, tlist);
if (amount == 0)
- {
- FTextureID oldtex = AddPatch(name);
- if (oldtex.Exists()) tlist.Push(oldtex);
- }
- if (tlist.Size() == 0)
{
// A texture with this name does not yet exist
FTexture * newtex = FTexture::CreateTexture (firsttx, FTexture::TEX_Any);
@@ -519,11 +487,6 @@ void FTextureManager::LoadTextureDefs(int wadnum, const char *lumpname)
tlist.Clear();
int amount = ListTextures(sc.String, tlist);
- if (amount == 0)
- {
- FTextureID oldtex = AddPatch(sc.String);
- if (oldtex.Exists()) tlist.Push(FTextureID(oldtex));
- }
FName texname = sc.String;
sc.MustGetString();
@@ -624,6 +587,10 @@ void FTextureManager::LoadTextureDefs(int wadnum, const char *lumpname)
{
ParseXTexture(sc, FTexture::TEX_Flat);
}
+ else if (sc.Compare("graphic"))
+ {
+ ParseXTexture(sc, FTexture::TEX_MiscPatch);
+ }
}
}
}
@@ -843,6 +810,8 @@ void FTextureManager::SortTexturesByType(int start, int end)
void FTextureManager::Init()
{
+ FTexture::InitGrayMap();
+
int wadcnt = Wads.GetNumWads();
for(int i = 0; i< wadcnt; i++)
{
diff --git a/src/textures/warptexture.cpp b/src/textures/warptexture.cpp
index 82ad00d3..6e30e036 100644
--- a/src/textures/warptexture.cpp
+++ b/src/textures/warptexture.cpp
@@ -41,7 +41,7 @@
FWarpTexture::FWarpTexture (FTexture *source)
-: SourcePic (source), Pixels (0), Spans (0), GenTime (0), Speed (1.f)
+: GenTime (0), SourcePic (source), Pixels (0), Spans (0), Speed (1.f)
{
CopySize(source);
bNoDecals = source->bNoDecals;
diff --git a/src/thingdef/olddecorations.cpp b/src/thingdef/olddecorations.cpp
index 8e25f764..6772e291 100644
--- a/src/thingdef/olddecorations.cpp
+++ b/src/thingdef/olddecorations.cpp
@@ -103,8 +103,8 @@ PSymbolActionFunction *FindGlobalActionFunction(const char *name);
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
-static void ParseInsideDecoration (FActorInfo *info, AActor *defaults,
- TArray &states, FExtraInfo &extra, EDefinitionType def, FScanner &sc);
+static void ParseInsideDecoration (Baggage &bag, AActor *defaults,
+ FExtraInfo &extra, EDefinitionType def, FScanner &sc);
static void ParseSpriteFrames (FActorInfo *info, TArray &states, FScanner &sc);
// PRIVATE DATA DEFINITIONS ------------------------------------------------
@@ -123,97 +123,6 @@ static const char *RenderStyles[] =
NULL
};
-static const char *FlagNames1[] =
-{
- "*",
- "Solid",
- "*",
- "NoSector",
-
- "NoBlockmap",
- "*",
- "*",
- "*",
-
- "SpawnCeiling",
- "NoGravity",
- "*",
- "*",
-
- "*",
- "*",
- "*",
- "*",
-
- "*",
- "*",
- "Shadow",
- "NoBlood",
-
- "*",
- "*",
- "*",
- "CountItem",
- NULL
-};
-
-static const char *FlagNames2[] =
-{
- "LowGravity",
- "WindThrust",
- "*",
- "*",
-
- "*",
- "FloorClip",
- "SpawnFloat",
- "NoTeleport",
-
- "Ripper",
- "Pushable",
- "SlidesOnWalls",
- "*",
-
- "CanPass",
- "CannotPush",
- "ThruGhost",
- "*",
-
- "FireDamage",
- "NoDamageThrust",
- "Telestomp",
- "FloatBob",
-
- "*",
- "ActivateImpact",
- "CanPushWalls",
- "ActivateMCross",
-
- "ActivatePCross",
- "*",
- "*",
- "*",
-
- "*",
- "*",
- "*",
- "Reflective",
- NULL
-};
-
-static const char *FlagNames3[] =
-{
- "FloorHugger",
- "CeilingHugger",
- "*",
- "*",
-
- "*",
- "*",
- "DontSplash",
- NULL
-};
-
// CODE --------------------------------------------------------------------
//==========================================================================
@@ -226,11 +135,11 @@ static const char *FlagNames3[] =
void ParseOldDecoration(FScanner &sc, EDefinitionType def)
{
- TArray states;
+ Baggage bag;
FExtraInfo extra;
+ FActorInfo *info;
PClass *type;
PClass *parent;
- FActorInfo *info;
FName typeName;
if (def == DEF_Pickup) parent = RUNTIME_CLASS(AFakeInventory);
@@ -239,76 +148,17 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def)
sc.MustGetString();
typeName = FName(sc.String);
type = parent->CreateDerivedClass (typeName, parent->Size);
- info = type->ActorInfo;
- info->GameFilter = 0x80;
- MakeStateDefines(parent->ActorInfo->StateList);
+ ResetBaggage(&bag, parent);
+ info = bag.Info = type->ActorInfo;
- // There isn't a single WAD out there which uses game filters with old style
- // decorations so this may as well be disabled. Without this option is is much
- // easier to detect incorrect declarations
-#if 0
- sc.MustGetString ();
- while (!sc.Compare ("{"))
- {
- if (sc.Compare ("Doom"))
- {
- info->GameFilter |= GAME_Doom;
- }
- else if (sc.Compare ("Heretic"))
- {
- info->GameFilter |= GAME_Heretic;
- }
- else if (sc.Compare ("Hexen"))
- {
- info->GameFilter |= GAME_Hexen;
- }
- else if (sc.Compare ("Raven"))
- {
- info->GameFilter |= GAME_Raven;
- }
- else if (sc.Compare ("Strife"))
- {
- info->GameFilter |= GAME_Strife;
- }
- else if (sc.Compare ("Any"))
- {
- info->GameFilter = GAME_Any;
- }
- else
- {
- if (def != DEF_Decoration || info->GameFilter != 0x80)
- {
- sc.ScriptError ("Unknown game type %s in %s", sc.String, typeName.GetChars());
- }
- else
- {
- // If this is a regular decoration (without preceding keyword) and no game
- // filters defined this is more likely a general syntax error so output a
- // more meaningful message.
- sc.ScriptError ("Syntax error: Unknown identifier '%s'", typeName.GetChars());
- }
- }
- sc.MustGetString ();
- }
- if (info->GameFilter == 0x80)
- {
- info->GameFilter = GAME_Any;
- }
- else
- {
- info->GameFilter &= ~0x80;
- }
-#else
info->GameFilter = GAME_Any;
sc.MustGetStringName("{");
-#endif
- states.Clear ();
memset (&extra, 0, sizeof(extra));
- ParseInsideDecoration (info, (AActor *)(type->Defaults), states, extra, def, sc);
+ ParseInsideDecoration (bag, (AActor *)(type->Defaults), extra, def, sc);
- info->NumOwnedStates = states.Size();
- if (info->NumOwnedStates == 0)
+ bag.Info->NumOwnedStates = bag.StateArray.Size();
+ if (bag.Info->NumOwnedStates == 0)
{
sc.ScriptError ("%s does not define any animation frames", typeName.GetChars() );
}
@@ -328,13 +178,13 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def)
if (extra.IceDeathEnd != 0)
{
// Make a copy of the final frozen frame for A_FreezeDeathChunks
- FState icecopy = states[extra.IceDeathEnd-1];
- states.Push (icecopy);
+ FState icecopy = bag.StateArray[extra.IceDeathEnd-1];
+ bag.StateArray.Push (icecopy);
info->NumOwnedStates += 1;
}
info->OwnedStates = new FState[info->NumOwnedStates];
- memcpy (info->OwnedStates, &states[0], info->NumOwnedStates * sizeof(info->OwnedStates[0]));
+ memcpy (info->OwnedStates, &bag.StateArray[0], info->NumOwnedStates * sizeof(info->OwnedStates[0]));
if (info->NumOwnedStates == 1)
{
info->OwnedStates->Tics = -1;
@@ -395,7 +245,7 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def)
if (extra.DeathHeight == 0) extra.DeathHeight = ((AActor*)(type->Defaults))->height;
info->Class->Meta.SetMetaFixed (AMETA_DeathHeight, extra.DeathHeight);
}
- AddState("Death", &info->OwnedStates[extra.DeathStart]);
+ bag.statedef.AddState("Death", &info->OwnedStates[extra.DeathStart]);
}
// Burn states are the same as death states, except they can optionally terminate
@@ -433,7 +283,7 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def)
if (extra.BurnHeight == 0) extra.BurnHeight = ((AActor*)(type->Defaults))->height;
type->Meta.SetMetaFixed (AMETA_BurnHeight, extra.BurnHeight);
- AddState("Burn", &info->OwnedStates[extra.FireDeathStart]);
+ bag.statedef.AddState("Burn", &info->OwnedStates[extra.FireDeathStart]);
}
// Ice states are similar to burn and death, except their final frame enters
@@ -454,11 +304,11 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def)
info->OwnedStates[i].Tics = 1;
info->OwnedStates[i].Misc1 = 0;
info->OwnedStates[i].SetAction(FindGlobalActionFunction("A_FreezeDeathChunks"));
- AddState("Ice", &info->OwnedStates[extra.IceDeathStart]);
+ bag.statedef.AddState("Ice", &info->OwnedStates[extra.IceDeathStart]);
}
else if (extra.bGenericIceDeath)
{
- AddState("Ice", RUNTIME_CLASS(AActor)->ActorInfo->FindState(NAME_GenericFreezeDeath));
+ bag.statedef.AddState("Ice", RUNTIME_CLASS(AActor)->ActorInfo->FindState(NAME_GenericFreezeDeath));
}
}
if (def == DEF_BreakableDecoration)
@@ -469,8 +319,8 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def)
{
((AActor *)(type->Defaults))->flags |= MF_DROPOFF|MF_MISSILE;
}
- AddState("Spawn", &info->OwnedStates[extra.SpawnStart]);
- InstallStates (info, ((AActor *)(type->Defaults)));
+ bag.statedef.AddState("Spawn", &info->OwnedStates[extra.SpawnStart]);
+ bag.statedef.InstallStates (info, ((AActor *)(type->Defaults)));
}
//==========================================================================
@@ -481,8 +331,8 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def)
//
//==========================================================================
-static void ParseInsideDecoration (FActorInfo *info, AActor *defaults,
- TArray &states, FExtraInfo &extra, EDefinitionType def, FScanner &sc)
+static void ParseInsideDecoration (Baggage &bag, AActor *defaults,
+ FExtraInfo &extra, EDefinitionType def, FScanner &sc)
{
AFakeInventory *const inv = static_cast(defaults);
char sprite[5] = "TNT1";
@@ -497,7 +347,7 @@ static void ParseInsideDecoration (FActorInfo *info, AActor *defaults,
{
sc.ScriptError ("DoomEdNum must be in the range [-1,32767]");
}
- info->DoomEdNum = (SWORD)sc.Number;
+ bag.Info->DoomEdNum = (SWORD)sc.Number;
}
else if (sc.Compare ("SpawnNum"))
{
@@ -506,7 +356,7 @@ static void ParseInsideDecoration (FActorInfo *info, AActor *defaults,
{
sc.ScriptError ("SpawnNum must be in the range [0,255]");
}
- info->SpawnID = (BYTE)sc.Number;
+ bag.Info->SpawnID = (BYTE)sc.Number;
}
else if (sc.Compare ("Sprite") || (
(def == DEF_BreakableDecoration || def == DEF_Projectile) &&
@@ -531,31 +381,31 @@ static void ParseInsideDecoration (FActorInfo *info, AActor *defaults,
else if (sc.Compare ("Frames"))
{
sc.MustGetString ();
- extra.SpawnStart = states.Size();
- ParseSpriteFrames (info, states, sc);
- extra.SpawnEnd = states.Size();
+ extra.SpawnStart = bag.StateArray.Size();
+ ParseSpriteFrames (bag.Info, bag.StateArray, sc);
+ extra.SpawnEnd = bag.StateArray.Size();
}
else if ((def == DEF_BreakableDecoration || def == DEF_Projectile) &&
sc.Compare ("DeathFrames"))
{
sc.MustGetString ();
- extra.DeathStart = states.Size();
- ParseSpriteFrames (info, states, sc);
- extra.DeathEnd = states.Size();
+ extra.DeathStart = bag.StateArray.Size();
+ ParseSpriteFrames (bag.Info, bag.StateArray, sc);
+ extra.DeathEnd = bag.StateArray.Size();
}
else if (def == DEF_BreakableDecoration && sc.Compare ("IceDeathFrames"))
{
sc.MustGetString ();
- extra.IceDeathStart = states.Size();
- ParseSpriteFrames (info, states, sc);
- extra.IceDeathEnd = states.Size();
+ extra.IceDeathStart = bag.StateArray.Size();
+ ParseSpriteFrames (bag.Info, bag.StateArray, sc);
+ extra.IceDeathEnd = bag.StateArray.Size();
}
else if (def == DEF_BreakableDecoration && sc.Compare ("BurnDeathFrames"))
{
sc.MustGetString ();
- extra.FireDeathStart = states.Size();
- ParseSpriteFrames (info, states, sc);
- extra.FireDeathEnd = states.Size();
+ extra.FireDeathStart = bag.StateArray.Size();
+ ParseSpriteFrames (bag.Info, bag.StateArray, sc);
+ extra.FireDeathEnd = bag.StateArray.Size();
}
else if (def == DEF_BreakableDecoration && sc.Compare ("GenericIceDeath"))
{
@@ -612,18 +462,18 @@ static void ParseInsideDecoration (FActorInfo *info, AActor *defaults,
else if (def == DEF_Projectile && sc.Compare ("ExplosionRadius"))
{
sc.MustGetNumber ();
- info->Class->Meta.SetMetaInt(ACMETA_ExplosionRadius, sc.Number);
+ bag.Info->Class->Meta.SetMetaInt(ACMETA_ExplosionRadius, sc.Number);
extra.bExplosive = true;
}
else if (def == DEF_Projectile && sc.Compare ("ExplosionDamage"))
{
sc.MustGetNumber ();
- info->Class->Meta.SetMetaInt(ACMETA_ExplosionDamage, sc.Number);
+ bag.Info->Class->Meta.SetMetaInt(ACMETA_ExplosionDamage, sc.Number);
extra.bExplosive = true;
}
else if (def == DEF_Projectile && sc.Compare ("DoNotHurtShooter"))
{
- info->Class->Meta.SetMetaInt(ACMETA_DontHurtShooter, true);
+ bag.Info->Class->Meta.SetMetaInt(ACMETA_DontHurtShooter, true);
}
else if (def == DEF_Projectile && sc.Compare ("Damage"))
{
@@ -708,7 +558,7 @@ static void ParseInsideDecoration (FActorInfo *info, AActor *defaults,
else if (def == DEF_Pickup && sc.Compare ("PickupMessage"))
{
sc.MustGetString ();
- info->Class->Meta.SetMetaString(AIMETA_PickupMessage, sc.String);
+ bag.Info->Class->Meta.SetMetaString(AIMETA_PickupMessage, sc.String);
}
else if (def == DEF_Pickup && sc.Compare ("Respawns"))
{
@@ -724,23 +574,7 @@ static void ParseInsideDecoration (FActorInfo *info, AActor *defaults,
}
else if (sc.String[0] != '*')
{
- int bit = sc.MatchString (FlagNames1);
- if (bit != -1)
- {
- defaults->flags |= 1 << bit;
- }
- else if ((bit = sc.MatchString (FlagNames2)) != -1)
- {
- defaults->flags2 |= 1 << bit;
- }
- else if ((bit = sc.MatchString (FlagNames3)) != -1)
- {
- defaults->flags3 |= 1 << bit;
- }
- else
- {
- sc.ScriptError (NULL);
- }
+ HandleActorFlag(sc, bag, sc.String, NULL, '+');
}
else
{
@@ -752,16 +586,16 @@ static void ParseInsideDecoration (FActorInfo *info, AActor *defaults,
unsigned int i;
int spr = GetSpriteIndex(sprite);
- for (i = 0; i < states.Size(); ++i)
+ for (i = 0; i < bag.StateArray.Size(); ++i)
{
- states[i].sprite = spr;
+ bag.StateArray[i].sprite = spr;
}
if (extra.DeathSprite[0] && extra.DeathEnd != 0)
{
int spr = GetSpriteIndex(extra.DeathSprite);
for (i = extra.DeathStart; i < extra.DeathEnd; ++i)
{
- states[i].sprite = spr;
+ bag.StateArray[i].sprite = spr;
}
}
}
diff --git a/src/thingdef/thingdef.cpp b/src/thingdef/thingdef.cpp
index 42b82c10..3a634b9b 100644
--- a/src/thingdef/thingdef.cpp
+++ b/src/thingdef/thingdef.cpp
@@ -68,82 +68,6 @@
const PClass *QuestItemClasses[31];
-
-
-//==========================================================================
-//
-// ActorConstDef
-//
-// Parses a constant definition.
-//
-//==========================================================================
-
-void ParseConstant (FScanner &sc, PSymbolTable * symt, PClass *cls)
-{
- // Read the type and make sure it's int.
- // (Maybe there will be other types later.)
- sc.MustGetToken(TK_Int);
- sc.MustGetToken(TK_Identifier);
- FName symname = sc.String;
- sc.MustGetToken('=');
- int expr = ParseExpression (sc, false, cls);
- sc.MustGetToken(';');
-
- int val = EvalExpressionI (expr, NULL, cls);
- PSymbolConst *sym = new PSymbolConst;
- sym->SymbolName = symname;
- sym->SymbolType = SYM_Const;
- sym->Value = val;
- if (symt->AddSymbol (sym) == NULL)
- {
- delete sym;
- sc.ScriptError ("'%s' is already defined in class '%s'.",
- symname.GetChars(), cls->TypeName.GetChars());
- }
-}
-
-//==========================================================================
-//
-// ActorEnumDef
-//
-// Parses an enum definition.
-//
-//==========================================================================
-
-void ParseEnum (FScanner &sc, PSymbolTable *symt, PClass *cls)
-{
- int currvalue = 0;
-
- sc.MustGetToken('{');
- while (!sc.CheckToken('}'))
- {
- sc.MustGetToken(TK_Identifier);
- FName symname = sc.String;
- if (sc.CheckToken('='))
- {
- int expr = ParseExpression(sc, false, cls);
- currvalue = EvalExpressionI(expr, NULL, cls);
- }
- PSymbolConst *sym = new PSymbolConst;
- sym->SymbolName = symname;
- sym->SymbolType = SYM_Const;
- sym->Value = currvalue;
- if (symt->AddSymbol (sym) == NULL)
- {
- delete sym;
- sc.ScriptError ("'%s' is already defined in class '%s'.",
- symname.GetChars(), cls->TypeName.GetChars());
- }
- // This allows a comma after the last value but doesn't enforce it.
- if (sc.CheckToken('}')) break;
- sc.MustGetToken(',');
- currvalue++;
- }
- sc.MustGetToken(';');
-}
-
-
-
//==========================================================================
//
// ParseParameter
@@ -245,8 +169,8 @@ int ParseParameter(FScanner &sc, PClass *cls, char type, bool constant)
// be checked here.
JumpParameters.Push(NAME_None);
}
- TArray names;
- MakeStateNameList(statestring, &names);
+
+ TArray &names = MakeStateNameList(statestring);
if (stype != NULL)
{
@@ -409,7 +333,8 @@ static void ParseActionDef (FScanner &sc, PClass *cls)
if (hasdefaults)
{
sym->defaultparameterindex = StateParameters.Size();
- for(int i = 0; i < DefaultParams.Size(); i++) StateParameters.Push(DefaultParams[i]);
+ for(unsigned int i = 0; i < DefaultParams.Size(); i++)
+ StateParameters.Push(DefaultParams[i]);
}
else
{
@@ -428,123 +353,63 @@ static void ParseActionDef (FScanner &sc, PClass *cls)
// Starts a new actor definition
//
//==========================================================================
-static FActorInfo *CreateNewActor(FScanner &sc, FActorInfo **parentc, Baggage *bag)
+static FActorInfo *CreateNewActor(FName typeName, FName parentName, FName replaceName,
+ int DoomEdNum, bool native)
{
- FName typeName;
const PClass *replacee = NULL;
- int DoomEdNum = -1;
PClass *ti = NULL;
FActorInfo *info = NULL;
- // Get actor name
- sc.MustGetString();
-
- char *colon = strchr(sc.String, ':');
- if (colon != NULL)
- {
- *colon++ = 0;
- }
-
- /*
- if (PClass::FindClass (sc.String) != NULL)
- {
- sc.ScriptError ("Actor %s is already defined.", sc.String);
- }
- */
-
- typeName = sc.String;
-
PClass *parent = RUNTIME_CLASS(AActor);
- if (parentc)
- {
- *parentc = NULL;
-
- // Do some tweaking so that a definition like 'Actor:Parent' which is read as a single token is recognized as well
- // without having resort to C-mode (which disallows periods in actor names.)
- if (colon == NULL)
- {
- sc.MustGetString ();
- if (sc.String[0]==':')
- {
- colon = sc.String + 1;
- }
- }
-
- if (colon != NULL)
- {
- if (colon[0] == 0)
- {
- sc.MustGetString ();
- colon = sc.String;
- }
- }
-
- if (colon != NULL)
- {
- parent = const_cast (PClass::FindClass (colon));
- if (parent == NULL)
- {
- sc.ScriptError ("Parent type '%s' not found", colon);
- }
- else if (!parent->IsDescendantOf(RUNTIME_CLASS(AActor)))
- {
- sc.ScriptError ("Parent type '%s' is not an actor", colon);
- }
- else if (parent->ActorInfo == NULL)
- {
- sc.ScriptError ("uninitialized parent type '%s'", colon);
- }
- else
- {
- *parentc = parent->ActorInfo;
- }
+ if (parentName != NAME_None)
+ {
+ parent = const_cast (PClass::FindClass (parentName));
+
+ if (parent == NULL)
+ {
+ I_Error ("Parent type '%s' not found in %s", parentName.GetChars(), typeName.GetChars());
+ }
+ else if (!parent->IsDescendantOf(RUNTIME_CLASS(AActor)))
+ {
+ I_Error ("Parent type '%s' is not an actor in %s", parentName.GetChars(), typeName.GetChars());
+ }
+ else if (parent->ActorInfo == NULL)
+ {
+ I_Error ("uninitialized parent type '%s' in %s", parentName.GetChars(), typeName.GetChars());
}
- else sc.UnGet();
}
// Check for "replaces"
- if (sc.CheckString ("replaces"))
+ if (replaceName != NAME_None)
{
-
// Get actor name
- sc.MustGetString ();
- replacee = PClass::FindClass (sc.String);
+ replacee = PClass::FindClass (replaceName);
if (replacee == NULL)
{
- sc.ScriptError ("Replaced type '%s' not found", sc.String);
+ I_Error ("Replaced type '%s' not found in %s", replaceName.GetChars(), typeName.GetChars());
}
else if (replacee->ActorInfo == NULL)
{
- sc.ScriptError ("Replaced type '%s' is not an actor", sc.String);
+ I_Error ("Replaced type '%s' is not an actor in %s", replaceName.GetChars(), typeName.GetChars());
}
}
- // Now, after the actor names have been parsed, it is time to switch to C-mode
- // for the rest of the actor definition.
- sc.SetCMode (true);
- if (sc.CheckNumber())
- {
- if (sc.Number>=-1 && sc.Number<32768) DoomEdNum = sc.Number;
- else sc.ScriptError ("DoomEdNum must be in the range [-1,32767]");
- }
-
- if (sc.CheckString("native"))
+ if (native)
{
ti = (PClass*)PClass::FindClass(typeName);
if (ti == NULL)
{
- sc.ScriptError("Unknown native class '%s'", typeName.GetChars());
+ I_Error("Unknown native class '%s'", typeName.GetChars());
}
else if (ti != RUNTIME_CLASS(AActor) && ti->ParentClass->NativeClass() != parent->NativeClass())
{
- sc.ScriptError("Native class '%s' does not inherit from '%s'",
- typeName.GetChars(),parent->TypeName.GetChars());
+ I_Error("Native class '%s' does not inherit from '%s'", typeName.GetChars(), parentName.GetChars());
}
else if (ti->ActorInfo != NULL)
{
- sc.ScriptMessage("Redefinition of internal class '%s'", typeName.GetChars());
+ I_Error("Redefinition of internal class '%s'", typeName.GetChars());
}
ti->InitializeActorInfo();
info = ti->ActorInfo;
@@ -555,11 +420,6 @@ static FActorInfo *CreateNewActor(FScanner &sc, FActorInfo **parentc, Baggage *b
info = ti->ActorInfo;
}
- MakeStateDefines(parent->ActorInfo->StateList);
-
- ResetBaggage (bag);
- bag->Info = info;
-
info->DoomEdNum = -1;
if (parent->ActorInfo->DamageFactors != NULL)
{
@@ -580,10 +440,98 @@ static FActorInfo *CreateNewActor(FScanner &sc, FActorInfo **parentc, Baggage *b
ti->ActorInfo->Replacee = replacee->ActorInfo;
}
- info->DoomEdNum = DoomEdNum;
+ if (DoomEdNum > 0) info->DoomEdNum = DoomEdNum;
return info;
}
+//==========================================================================
+//
+// Starts a new actor definition
+//
+//==========================================================================
+static FActorInfo *ParseActorHeader(FScanner &sc, Baggage *bag)
+{
+ FName typeName;
+ FName parentName;
+ FName replaceName;
+ bool native = false;
+ int DoomEdNum = -1;
+
+ // Get actor name
+ sc.MustGetString();
+
+ char *colon = strchr(sc.String, ':');
+ if (colon != NULL)
+ {
+ *colon++ = 0;
+ }
+
+ typeName = sc.String;
+
+ // Do some tweaking so that a definition like 'Actor:Parent' which is read as a single token is recognized as well
+ // without having resort to C-mode (which disallows periods in actor names.)
+ if (colon == NULL)
+ {
+ sc.MustGetString ();
+ if (sc.String[0]==':')
+ {
+ colon = sc.String + 1;
+ }
+ }
+
+ if (colon != NULL)
+ {
+ if (colon[0] == 0)
+ {
+ sc.MustGetString ();
+ colon = sc.String;
+ }
+ }
+
+ if (colon == NULL)
+ {
+ sc.UnGet();
+ }
+
+ parentName = colon;
+
+ // Check for "replaces"
+ if (sc.CheckString ("replaces"))
+ {
+ // Get actor name
+ sc.MustGetString ();
+ replaceName = sc.String;
+ }
+
+ // Now, after the actor names have been parsed, it is time to switch to C-mode
+ // for the rest of the actor definition.
+ sc.SetCMode (true);
+ if (sc.CheckNumber())
+ {
+ if (sc.Number>=-1 && sc.Number<32768) DoomEdNum = sc.Number;
+ else sc.ScriptError ("DoomEdNum must be in the range [-1,32767]");
+ }
+
+ if (sc.CheckString("native"))
+ {
+ native = true;
+ }
+
+ try
+ {
+ FActorInfo *info = CreateNewActor(typeName, parentName, replaceName, DoomEdNum, native);
+ ResetBaggage (bag, info->Class->ParentClass);
+ bag->Info = info;
+ bag->Lumpnum = sc.LumpNum;
+ return info;
+ }
+ catch (CRecoverableError &err)
+ {
+ sc.ScriptError("%s", err.GetMessage());
+ return NULL;
+ }
+}
+
//==========================================================================
//
// Reads an actor definition
@@ -594,64 +542,41 @@ void ParseActor(FScanner &sc)
FActorInfo * info=NULL;
Baggage bag;
- try
+ info = ParseActorHeader(sc, &bag);
+ sc.MustGetToken('{');
+ while (sc.MustGetAnyToken(), sc.TokenType != '}')
{
- FActorInfo * parent;
-
- info = CreateNewActor(sc, &parent, &bag);
- sc.MustGetToken('{');
- while (sc.MustGetAnyToken(), sc.TokenType != '}')
+ switch (sc.TokenType)
{
- switch (sc.TokenType)
- {
- case TK_Action:
- ParseActionDef (sc, info->Class);
- break;
+ case TK_Action:
+ ParseActionDef (sc, info->Class);
+ break;
- case TK_Const:
- ParseConstant (sc, &info->Class->Symbols, info->Class);
- break;
+ case TK_Const:
+ ParseConstant (sc, &info->Class->Symbols, info->Class);
+ break;
- case TK_Enum:
- ParseEnum (sc, &info->Class->Symbols, info->Class);
- break;
+ case TK_Enum:
+ ParseEnum (sc, &info->Class->Symbols, info->Class);
+ break;
- case TK_Identifier:
- // other identifier related checks here
- case TK_Projectile: // special case: both keyword and property name
- ParseActorProperty(sc, bag);
- break;
+ case TK_Identifier:
+ // other identifier related checks here
+ case TK_Projectile: // special case: both keyword and property name
+ ParseActorProperty(sc, bag);
+ break;
- case '+':
- case '-':
- ParseActorFlag(sc, bag, sc.TokenType);
- break;
-
- default:
- sc.ScriptError("Unexpected '%s' in definition of '%s'", sc.String, bag.Info->Class->TypeName.GetChars());
- break;
- }
+ case '+':
+ case '-':
+ ParseActorFlag(sc, bag, sc.TokenType);
+ break;
+ default:
+ sc.ScriptError("Unexpected '%s' in definition of '%s'", sc.String, bag.Info->Class->TypeName.GetChars());
+ break;
}
-
- FinishActor(sc, info, bag);
}
-
- catch(CRecoverableError & e)
- {
- throw e;
- }
- // I think this is better than a crash log.
-#ifndef _DEBUG
- catch (...)
- {
- if (info)
- sc.ScriptError("Unexpected error during parsing of actor %s", info->Class->TypeName.GetChars());
- else
- sc.ScriptError("Unexpected error during parsing of actor definitions");
- }
-#endif
-
+ FinishActor(sc, info, bag);
sc.SetCMode (false);
}
@@ -663,10 +588,33 @@ void ParseActor(FScanner &sc)
//
//==========================================================================
+static int ResolvePointer(const PClass **pPtr, const PClass *owner, const PClass *destclass, const char *description)
+{
+ fuglyname v;
+
+ v = *pPtr;
+ if (v != NAME_None && v.IsValidName())
+ {
+ *pPtr = PClass::FindClass(v);
+ if (!*pPtr)
+ {
+ Printf("Unknown %s '%s' in '%s'\n", description, v.GetChars(), owner->TypeName.GetChars());
+ return 1;
+ }
+ else if (!(*pPtr)->IsDescendantOf(destclass))
+ {
+ *pPtr = NULL;
+ Printf("Invalid %s '%s' in '%s'\n", description, v.GetChars(), owner->TypeName.GetChars());
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
void FinishThingdef()
{
unsigned int i;
- bool isRuntimeActor=false;
int errorcount=0;
for (i = 0;i < PClass::m_Types.Size(); i++)
@@ -676,13 +624,6 @@ void FinishThingdef()
// Skip non-actors
if (!ti->IsDescendantOf(RUNTIME_CLASS(AActor))) continue;
- // Everything coming after the first runtime actor is also a runtime actor
- // so this check is sufficient
- if (ti == PClass::m_RuntimeActors[0])
- {
- isRuntimeActor=true;
- }
-
AActor *def = GetDefaultByType(ti);
if (!def)
@@ -701,21 +642,7 @@ void FinishThingdef()
if (ti->IsDescendantOf(RUNTIME_CLASS(AInventory)))
{
AInventory * defaults=(AInventory *)def;
- fuglyname v;
-
- v = defaults->PickupFlash;
- if (v != NAME_None && v.IsValidName())
- {
- defaults->PickupFlash = PClass::FindClass(v);
- if (isRuntimeActor)
- {
- if (!defaults->PickupFlash)
- {
- Printf("Unknown pickup flash '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars());
- errorcount++;
- }
- }
- }
+ errorcount += ResolvePointer(&defaults->PickupFlash, ti, RUNTIME_CLASS(AActor), "pickup flash");
}
if (ti->IsDescendantOf(RUNTIME_CLASS(APowerupGiver)) && ti != RUNTIME_CLASS(APowerupGiver))
@@ -757,122 +684,47 @@ void FinishThingdef()
if (ti->IsDescendantOf(RUNTIME_CLASS(AWeapon)))
{
AWeapon * defaults=(AWeapon *)def;
- fuglyname v;
+ errorcount += ResolvePointer(&defaults->AmmoType1, ti, RUNTIME_CLASS(AAmmo), "ammo type");
+ errorcount += ResolvePointer(&defaults->AmmoType2, ti, RUNTIME_CLASS(AAmmo), "ammo type");
+ errorcount += ResolvePointer(&defaults->SisterWeaponType, ti, RUNTIME_CLASS(AWeapon), "sister weapon type");
- v = defaults->AmmoType1;
- if (v != NAME_None && v.IsValidName())
+ FState * ready = ti->ActorInfo->FindState(NAME_Ready);
+ FState * select = ti->ActorInfo->FindState(NAME_Select);
+ FState * deselect = ti->ActorInfo->FindState(NAME_Deselect);
+ FState * fire = ti->ActorInfo->FindState(NAME_Fire);
+
+ // Consider any weapon without any valid state abstract and don't output a warning
+ // This is for creating base classes for weapon groups that only set up some properties.
+ if (ready || select || deselect || fire)
{
- defaults->AmmoType1 = PClass::FindClass(v);
- if (isRuntimeActor)
+ // Do some consistency checks. If these states are undefined the weapon cannot work!
+ if (!ready)
{
- if (!defaults->AmmoType1)
- {
- Printf("Unknown ammo type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars());
- errorcount++;
- }
- else if (defaults->AmmoType1->ParentClass != RUNTIME_CLASS(AAmmo))
- {
- Printf("Invalid ammo type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars());
- errorcount++;
- }
+ Printf("Weapon %s doesn't define a ready state.\n", ti->TypeName.GetChars());
+ errorcount++;
+ }
+ if (!select)
+ {
+ Printf("Weapon %s doesn't define a select state.\n", ti->TypeName.GetChars());
+ errorcount++;
+ }
+ if (!deselect)
+ {
+ Printf("Weapon %s doesn't define a deselect state.\n", ti->TypeName.GetChars());
+ errorcount++;
+ }
+ if (!fire)
+ {
+ Printf("Weapon %s doesn't define a fire state.\n", ti->TypeName.GetChars());
+ errorcount++;
}
}
-
- v = defaults->AmmoType2;
- if (v != NAME_None && v.IsValidName())
- {
- defaults->AmmoType2 = PClass::FindClass(v);
- if (isRuntimeActor)
- {
- if (!defaults->AmmoType2)
- {
- Printf("Unknown ammo type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars());
- errorcount++;
- }
- else if (defaults->AmmoType2->ParentClass != RUNTIME_CLASS(AAmmo))
- {
- Printf("Invalid ammo type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars());
- errorcount++;
- }
- }
- }
-
- v = defaults->SisterWeaponType;
- if (v != NAME_None && v.IsValidName())
- {
- defaults->SisterWeaponType = PClass::FindClass(v);
- if (isRuntimeActor)
- {
- if (!defaults->SisterWeaponType)
- {
- Printf("Unknown sister weapon type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars());
- errorcount++;
- }
- else if (!defaults->SisterWeaponType->IsDescendantOf(RUNTIME_CLASS(AWeapon)))
- {
- Printf("Invalid sister weapon type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars());
- errorcount++;
- }
- }
- }
-
- if (isRuntimeActor)
- {
- FState * ready = ti->ActorInfo->FindState(NAME_Ready);
- FState * select = ti->ActorInfo->FindState(NAME_Select);
- FState * deselect = ti->ActorInfo->FindState(NAME_Deselect);
- FState * fire = ti->ActorInfo->FindState(NAME_Fire);
-
- // Consider any weapon without any valid state abstract and don't output a warning
- // This is for creating base classes for weapon groups that only set up some properties.
- if (ready || select || deselect || fire)
- {
- // Do some consistency checks. If these states are undefined the weapon cannot work!
- if (!ready)
- {
- Printf("Weapon %s doesn't define a ready state.\n", ti->TypeName.GetChars());
- errorcount++;
- }
- if (!select)
- {
- Printf("Weapon %s doesn't define a select state.\n", ti->TypeName.GetChars());
- errorcount++;
- }
- if (!deselect)
- {
- Printf("Weapon %s doesn't define a deselect state.\n", ti->TypeName.GetChars());
- errorcount++;
- }
- if (!fire)
- {
- Printf("Weapon %s doesn't define a fire state.\n", ti->TypeName.GetChars());
- errorcount++;
- }
- }
- }
-
}
// same for the weapon type of weapon pieces.
else if (ti->IsDescendantOf(RUNTIME_CLASS(AWeaponPiece)))
{
AWeaponPiece * defaults=(AWeaponPiece *)def;
- fuglyname v;
-
- v = defaults->WeaponClass;
- if (v != NAME_None && v.IsValidName())
- {
- defaults->WeaponClass = PClass::FindClass(v);
- if (!defaults->WeaponClass)
- {
- Printf("Unknown weapon type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars());
- errorcount++;
- }
- else if (!defaults->WeaponClass->IsDescendantOf(RUNTIME_CLASS(AWeapon)))
- {
- Printf("Invalid weapon type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars());
- errorcount++;
- }
- }
+ errorcount += ResolvePointer(&defaults->WeaponClass, ti, RUNTIME_CLASS(AWeapon), "weapon type");
}
}
if (errorcount > 0)
diff --git a/src/thingdef/thingdef.h b/src/thingdef/thingdef.h
index fc14386c..958f1419 100644
--- a/src/thingdef/thingdef.h
+++ b/src/thingdef/thingdef.h
@@ -5,6 +5,24 @@
class FScanner;
+
+//==========================================================================
+//
+// A flag descriptor
+//
+//==========================================================================
+
+struct FFlagDef
+{
+ int flagbit;
+ const char *name;
+ int structoffset;
+};
+
+FFlagDef *FindFlag (const PClass *type, const char *part1, const char *part2);
+void HandleDeprecatedFlags(AActor *defaults, FActorInfo *info, bool set, int index);
+
+
//==========================================================================
//
// This class is for storing a name inside a const PClass* field without
@@ -32,25 +50,72 @@ public:
//==========================================================================
//
-// Dropitem list
+// State parser
//
//==========================================================================
-struct FDropItem
+extern TArray StateParameters;
+extern TArray JumpParameters;
+
+struct FStateLabels;
+
+enum EStateDefineFlags
{
- FName Name;
- int probability;
- int amount;
- FDropItem * Next;
+ SDF_NEXT = 0,
+ SDF_STATE = 1,
+ SDF_STOP = 2,
+ SDF_WAIT = 3,
+ SDF_LABEL = 4,
+ SDF_INDEX = 5,
};
-FDropItem *GetDropItems(const PClass * cls);
+struct FStateDefine
+{
+ FName Label;
+ TArray Children;
+ FState *State;
+ BYTE DefineFlags;
+};
+
+class FStateDefinitions
+{
+ TArray StateLabels;
+
+ static FStateDefine *FindStateLabelInList(TArray &list, FName name, bool create);
+ static FStateLabels *CreateStateLabelList(TArray &statelist);
+ static void MakeStateList(const FStateLabels *list, TArray &dest);
+ static void RetargetStatePointers (intptr_t count, const char *target, TArray & statelist);
+ FStateDefine *FindStateAddress(const char *name);
+ FState *FindState(const char *name);
+
+ FState *ResolveGotoLabel (AActor *actor, const PClass *mytype, char *name);
+ static void FixStatePointers (FActorInfo *actor, TArray & list);
+ void ResolveGotoLabels (FActorInfo *actor, AActor *defaults, TArray & list);
+
+public:
+
+
+ void ClearStateLabels()
+ {
+ StateLabels.Clear();
+ }
+
+ void AddState (const char * statename, FState * state, BYTE defflags = SDF_STATE);
+ void InstallStates(FActorInfo *info, AActor *defaults);
+ int FinishStates (FActorInfo *actor, AActor *defaults, TArray &StateArray);
+
+ void MakeStateDefines(const PClass *cls);
+ void AddStateDefines(const FStateLabels *list);
+ void RetargetStates (intptr_t count, const char *target);
+
+};
//==========================================================================
//
// Extra info maintained while defining an actor.
//
//==========================================================================
+struct FDropItem;
struct Baggage
{
@@ -58,19 +123,23 @@ struct Baggage
bool DropItemSet;
bool StateSet;
int CurrentState;
+ int Lumpnum;
+ FStateDefinitions statedef;
+ TArray StateArray;
FDropItem *DropItemList;
};
-inline void ResetBaggage (Baggage *bag)
+inline void ResetBaggage (Baggage *bag, const PClass *stateclass)
{
bag->DropItemList = NULL;
bag->DropItemSet = false;
bag->CurrentState = 0;
bag->StateSet = false;
+ bag->StateArray.Clear();
+ bag->statedef.MakeStateDefines(stateclass);
}
-
//==========================================================================
//
// Action function lookup
@@ -87,25 +156,8 @@ AFuncDesc * FindFunction(const char * string);
-//==========================================================================
-//
-// State parser
-//
-//==========================================================================
-
-extern TArray StateParameters;
-extern TArray JumpParameters;
-
-void ClearStateLabels();
-void AddState (const char * statename, FState * state);
-FState * FindState(AActor * actor, const PClass * type, const char * name);
-void InstallStates(FActorInfo *info, AActor *defaults);
-void MakeStateDefines(const FStateLabels *list);
-void AddStateDefines(const FStateLabels *list);
FState *P_GetState(AActor *self, FState *CallingState, int offset);
-int FinishStates (FScanner &sc, FActorInfo *actor, AActor *defaults, Baggage &bag);
int ParseStates(FScanner &sc, FActorInfo *actor, AActor *defaults, Baggage &bag);
-FState *CheckState(FScanner &sc, PClass *type);
//==========================================================================
@@ -115,6 +167,7 @@ FState *CheckState(FScanner &sc, PClass *type);
//==========================================================================
void ParseActorProperty(FScanner &sc, Baggage &bag);
+void HandleActorFlag(FScanner &sc, Baggage &bag, const char *part1, const char *part2, int mod);
void ParseActorFlag (FScanner &sc, Baggage &bag, int mod);
void FinishActor(FScanner &sc, FActorInfo *info, Baggage &bag);
@@ -156,20 +209,91 @@ enum EDefinitionType
#if defined(_MSC_VER)
#pragma data_seg(".areg$u")
+#pragma data_seg(".greg$u")
#pragma data_seg()
#define MSVC_ASEG __declspec(allocate(".areg$u"))
#define GCC_ASEG
+#define MSVC_PSEG __declspec(allocate(".greg$u"))
+#define GCC_PSEG
#else
#define MSVC_ASEG
#define GCC_ASEG __attribute__((section(AREG_SECTION)))
+#define MSVC_PSEG
+#define GCC_PSEG __attribute__((section(GREG_SECTION)))
#endif
+union FPropParam
+{
+ int i;
+ float f;
+ const char *s;
+};
+
+typedef void (*PropHandler)(AActor *defaults, Baggage &bag, FPropParam *params);
+
+enum ECategory
+{
+ CAT_PROPERTY, // Inheritable property
+ CAT_INFO // non-inheritable info (spawn ID, Doomednum, game filter, conversation ID)
+};
+
+struct FPropertyInfo
+{
+ const char *name;
+ const char *params;
+ const PClass *cls;
+ PropHandler Handler;
+ int category;
+};
+
+FPropertyInfo *FindProperty(const char * string);
+int MatchString (const char *in, const char **strings);
+
+
+#define DEFINE_PROPERTY_BASE(name, paramlist, clas, cat) \
+ static void Handler_##name##_##paramlist##_##clas(A##clas *defaults, Baggage &bag, FPropParam *params); \
+ static FPropertyInfo Prop_##name##_##paramlist##_##clas = \
+ { #name, #paramlist, RUNTIME_CLASS(A##clas), (PropHandler)Handler_##name##_##paramlist##_##clas, cat }; \
+ MSVC_PSEG FPropertyInfo *infoptr_##name##_##paramlist##_##clas GCC_PSEG = &Prop_##name##_##paramlist##_##clas; \
+ static void Handler_##name##_##paramlist##_##clas(A##clas *defaults, Baggage &bag, FPropParam *params)
+
+#define DEFINE_PREFIXED_PROPERTY_BASE(prefix, name, paramlist, clas, cat) \
+ static void Handler_##name##_##paramlist##_##clas(A##clas *defaults, Baggage &bag, FPropParam *params); \
+ static FPropertyInfo Prop_##name##_##paramlist##_##clas = \
+{ #prefix"."#name, #paramlist, RUNTIME_CLASS(A##clas), (PropHandler)Handler_##name##_##paramlist##_##clas, cat }; \
+ MSVC_PSEG FPropertyInfo *infoptr_##name##_##paramlist##_##clas GCC_PSEG = &Prop_##name##_##paramlist##_##clas; \
+ static void Handler_##name##_##paramlist##_##clas(A##clas *defaults, Baggage &bag, FPropParam *params)
+
+
+#define DEFINE_PROPERTY(name, paramlist, clas) DEFINE_PROPERTY_BASE(name, paramlist, clas, CAT_PROPERTY)
+#define DEFINE_INFO_PROPERTY(name, paramlist, clas) DEFINE_PROPERTY_BASE(name, paramlist, clas, CAT_INFO)
+
+#define DEFINE_CLASS_PROPERTY(name, paramlist, clas) DEFINE_PREFIXED_PROPERTY_BASE(clas, name, paramlist, clas, CAT_PROPERTY)
+#define DEFINE_CLASS_PROPERTY_PREFIX(prefix, name, paramlist, clas) DEFINE_PREFIXED_PROPERTY_BASE(prefix, name, paramlist, clas, CAT_PROPERTY)
+
+#define PROP_PARM_COUNT (params[0].i)
+
+#define PROP_STRING_PARM(var, no) \
+ const char *var = params[(no)+1].s;
+
+#define PROP_INT_PARM(var, no) \
+ int var = params[(no)+1].i;
+
+#define PROP_FLOAT_PARM(var, no) \
+ float var = params[(no)+1].f;
+
+#define PROP_FIXED_PARM(var, no) \
+ fixed_t var = fixed_t(params[(no)+1].f * FRACUNIT);
+
+#define PROP_COLOR_PARM(var, no) \
+ int var = params[(no)+1].i== 0? params[(no)+2].i : V_GetColor(NULL, params[(no)+2].s);
+
struct StateCallData
{
- FState * State;
- AActor * Item;
+ FState *State;
+ AActor *Item;
bool Result;
};
diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp
index 7a9799d1..85bd5c8a 100644
--- a/src/thingdef/thingdef_codeptr.cpp
+++ b/src/thingdef/thingdef_codeptr.cpp
@@ -354,51 +354,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_BulletAttack)
}
-//==========================================================================
-//
-// Resolves a label parameter
-//
-//==========================================================================
-
-FState *P_GetState(AActor *self, FState *CallingState, int offset)
-{
- if (offset == 0 || offset == INT_MIN)
- {
- return NULL; // 0 means 'no state'
- }
- else if (offset>0)
- {
- if (CallingState == NULL) return NULL;
- return CallingState + offset;
- }
- else if (self != NULL)
- {
- offset = -offset;
-
- FName classname = JumpParameters[offset];
- const PClass *cls;
- cls = classname==NAME_None? RUNTIME_TYPE(self) : PClass::FindClass(classname);
- if (cls==NULL || cls->ActorInfo==NULL) return NULL; // shouldn't happen
-
- int numnames = (int)JumpParameters[offset+1];
- FState *jumpto = cls->ActorInfo->FindState(numnames, &JumpParameters[offset+2]);
- if (jumpto == NULL)
- {
- const char *dot="";
- Printf("Jump target '");
- if (classname != NAME_None) Printf("%s::", classname.GetChars());
- for (int i=0;iGetClass()->TypeName.GetChars());
- }
- return jumpto;
- }
- else return NULL;
-}
-
//==========================================================================
//
// Do the state jump
@@ -2236,3 +2191,49 @@ DEFINE_ACTION_FUNCTION(AActor, A_ResetReloadCounter)
AWeapon *weapon = self->player->ReadyWeapon;
weapon->ReloadCounter = 0;
}
+
+//===========================================================================
+//
+// A_ChangeFlag
+//
+//===========================================================================
+DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ChangeFlag)
+{
+ ACTION_PARAM_START(2);
+ ACTION_PARAM_STRING(flagname, 0);
+ ACTION_PARAM_BOOL(expression, 1);
+
+ const char *dot = strchr (flagname, '.');
+ FFlagDef *fd;
+ const PClass *cls = self->GetClass();
+
+ if (dot != NULL)
+ {
+ FString part1(flagname, dot-flagname);
+ fd = FindFlag (cls, part1, dot+1);
+ }
+ else
+ {
+ fd = FindFlag (cls, flagname, NULL);
+ }
+
+ if (fd != NULL)
+ {
+ if (fd->structoffset == -1)
+ {
+ HandleDeprecatedFlags(self, cls->ActorInfo, expression, fd->flagbit);
+ }
+ else
+ {
+ int * flagp = (int*) (((char*)self) + fd->structoffset);
+
+ if (expression) *flagp |= fd->flagbit;
+ else *flagp &= ~fd->flagbit;
+ }
+ }
+ else
+ {
+ Printf("Unknown flag '%s' in '%s'\n", flagname, cls->TypeName.GetChars());
+ }
+}
+
diff --git a/src/thingdef/thingdef_main.cpp b/src/thingdef/thingdef_main.cpp
index 4525ff73..85513e15 100644
--- a/src/thingdef/thingdef_main.cpp
+++ b/src/thingdef/thingdef_main.cpp
@@ -47,9 +47,6 @@
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
void ParseActor(FScanner &sc);
-void ParseClass(FScanner &sc);
-void ParseGlobalConst(FScanner &sc);
-void ParseGlobalEnum(FScanner &sc);
void FinishThingdef();
void ParseOldDecoration(FScanner &sc, EDefinitionType def);
diff --git a/src/thingdef/thingdef_parse.cpp b/src/thingdef/thingdef_parse.cpp
new file mode 100644
index 00000000..f06b8d80
--- /dev/null
+++ b/src/thingdef/thingdef_parse.cpp
@@ -0,0 +1,559 @@
+/*
+** thingdef-parse.cpp
+**
+** Actor definitions - all parser related code
+**
+**---------------------------------------------------------------------------
+** Copyright 2002-2007 Christoph Oelckers
+** Copyright 2004-2007 Randy Heit
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+**
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** 3. The name of the author may not be used to endorse or promote products
+** derived from this software without specific prior written permission.
+** 4. When not used as part of ZDoom or a ZDoom derivative, this code will be
+** covered by the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or (at
+** your option) any later version.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**---------------------------------------------------------------------------
+**
+*/
+
+#include "doomtype.h"
+#include "actor.h"
+#include "a_pickups.h"
+#include "sc_man.h"
+#include "thingdef.h"
+#include "a_morph.h"
+#include "cmdlib.h"
+#include "templates.h"
+#include "v_palette.h"
+#include "doomerrors.h"
+#include "autosegs.h"
+#include "i_system.h"
+
+
+//==========================================================================
+//
+// ActorConstDef
+//
+// Parses a constant definition.
+//
+//==========================================================================
+
+void ParseConstant (FScanner &sc, PSymbolTable * symt, PClass *cls)
+{
+ // Read the type and make sure it's int.
+ // (Maybe there will be other types later.)
+ sc.MustGetToken(TK_Int);
+ sc.MustGetToken(TK_Identifier);
+ FName symname = sc.String;
+ sc.MustGetToken('=');
+ int expr = ParseExpression (sc, false, cls);
+ sc.MustGetToken(';');
+
+ int val = EvalExpressionI (expr, NULL, cls);
+ PSymbolConst *sym = new PSymbolConst;
+ sym->SymbolName = symname;
+ sym->SymbolType = SYM_Const;
+ sym->Value = val;
+ if (symt->AddSymbol (sym) == NULL)
+ {
+ delete sym;
+ sc.ScriptError ("'%s' is already defined in class '%s'.",
+ symname.GetChars(), cls->TypeName.GetChars());
+ }
+}
+
+//==========================================================================
+//
+// ActorEnumDef
+//
+// Parses an enum definition.
+//
+//==========================================================================
+
+void ParseEnum (FScanner &sc, PSymbolTable *symt, PClass *cls)
+{
+ int currvalue = 0;
+
+ sc.MustGetToken('{');
+ while (!sc.CheckToken('}'))
+ {
+ sc.MustGetToken(TK_Identifier);
+ FName symname = sc.String;
+ if (sc.CheckToken('='))
+ {
+ int expr = ParseExpression(sc, false, cls);
+ currvalue = EvalExpressionI(expr, NULL, cls);
+ }
+ PSymbolConst *sym = new PSymbolConst;
+ sym->SymbolName = symname;
+ sym->SymbolType = SYM_Const;
+ sym->Value = currvalue;
+ if (symt->AddSymbol (sym) == NULL)
+ {
+ delete sym;
+ sc.ScriptError ("'%s' is already defined in class '%s'.",
+ symname.GetChars(), cls->TypeName.GetChars());
+ }
+ // This allows a comma after the last value but doesn't enforce it.
+ if (sc.CheckToken('}')) break;
+ sc.MustGetToken(',');
+ currvalue++;
+ }
+ sc.MustGetToken(';');
+}
+
+//==========================================================================
+//
+// Parses a flag name
+//
+//==========================================================================
+void ParseActorFlag (FScanner &sc, Baggage &bag, int mod)
+{
+ sc.MustGetString ();
+
+ FString part1 = sc.String;
+ const char *part2 = NULL;
+ if (sc.CheckString ("."))
+ {
+ sc.MustGetString ();
+ part2 = sc.String;
+ }
+ HandleActorFlag(sc, bag, part1, part2, mod);
+}
+
+//==========================================================================
+//
+// Processes a flag. Also used by olddecorations.cpp
+//
+//==========================================================================
+void HandleActorFlag(FScanner &sc, Baggage &bag, const char *part1, const char *part2, int mod)
+{
+ FFlagDef *fd;
+
+ if ( (fd = FindFlag (bag.Info->Class, part1, part2)) )
+ {
+ AActor *defaults = (AActor*)bag.Info->Class->Defaults;
+ if (fd->structoffset == -1) // this is a deprecated flag that has been changed into a real property
+ {
+ HandleDeprecatedFlags(defaults, bag.Info, mod=='+', fd->flagbit);
+ }
+ else
+ {
+ DWORD * flagvar = (DWORD*) ((char*)defaults + fd->structoffset);
+ if (mod == '+')
+ {
+ *flagvar |= fd->flagbit;
+ }
+ else
+ {
+ *flagvar &= ~fd->flagbit;
+ }
+ }
+ }
+ else
+ {
+ if (part2 == NULL)
+ {
+ sc.ScriptError("\"%s\" is an unknown flag\n", part1);
+ }
+ else
+ {
+ sc.ScriptError("\"%s.%s\" is an unknown flag\n", part1, part2);
+ }
+ }
+}
+
+//==========================================================================
+//
+// [MH] parses a morph style expression
+//
+//==========================================================================
+
+static int ParseMorphStyle (FScanner &sc)
+{
+ static const char * morphstyles[]={
+ "MRF_ADDSTAMINA", "MRF_FULLHEALTH", "MRF_UNDOBYTOMEOFPOWER", "MRF_UNDOBYCHAOSDEVICE",
+ "MRF_FAILNOTELEFRAG", "MRF_FAILNOLAUGH", "MRF_WHENINVULNERABLE", "MRF_LOSEACTUALWEAPON",
+ "MRF_NEWTIDBEHAVIOUR", "MRF_UNDOBYDEATH", "MRF_UNDOBYDEATHFORCED", "MRF_UNDOBYDEATHSAVES", NULL};
+
+ static const int morphstyle_values[]={
+ MORPH_ADDSTAMINA, MORPH_FULLHEALTH, MORPH_UNDOBYTOMEOFPOWER, MORPH_UNDOBYCHAOSDEVICE,
+ MORPH_FAILNOTELEFRAG, MORPH_FAILNOLAUGH, MORPH_WHENINVULNERABLE, MORPH_LOSEACTUALWEAPON,
+ MORPH_NEWTIDBEHAVIOUR, MORPH_UNDOBYDEATH, MORPH_UNDOBYDEATHFORCED, MORPH_UNDOBYDEATHSAVES};
+
+ // May be given flags by number...
+ if (sc.CheckNumber())
+ {
+ sc.MustGetNumber();
+ return sc.Number;
+ }
+
+ // ... else should be flags by name.
+ // NOTE: Later this should be removed and a normal expression used.
+ // The current DECORATE parser can't handle this though.
+ bool gotparen = sc.CheckString("(");
+ int style = 0;
+ do
+ {
+ sc.MustGetString();
+ style |= morphstyle_values[sc.MustMatchString(morphstyles)];
+ }
+ while (sc.CheckString("|"));
+ if (gotparen)
+ {
+ sc.MustGetStringName(")");
+ }
+
+ return style;
+}
+
+//==========================================================================
+//
+// For getting a state address from the parent
+// No attempts have been made to add new functionality here
+// This is strictly for keeping compatibility with old WADs!
+//
+//==========================================================================
+
+FState *CheckState(FScanner &sc, PClass *type)
+{
+ int v=0;
+
+ if (sc.GetString() && !sc.Crossed)
+ {
+ if (sc.Compare("0")) return NULL;
+ else if (sc.Compare("PARENT"))
+ {
+ FState * state = NULL;
+ sc.MustGetString();
+
+ FActorInfo * info = type->ParentClass->ActorInfo;
+
+ if (info != NULL)
+ {
+ state = info->FindState(FName(sc.String));
+ }
+
+ if (sc.GetString ())
+ {
+ if (sc.Compare ("+"))
+ {
+ sc.MustGetNumber ();
+ v = sc.Number;
+ }
+ else
+ {
+ sc.UnGet ();
+ }
+ }
+
+ if (state == NULL && v==0) return NULL;
+
+ if (v!=0 && state==NULL)
+ {
+ sc.ScriptError("Attempt to get invalid state from actor %s\n", type->ParentClass->TypeName.GetChars());
+ return NULL;
+ }
+ state+=v;
+ return state;
+ }
+ else sc.ScriptError("Invalid state assignment");
+ }
+ return NULL;
+}
+
+//==========================================================================
+//
+// Parses an actor property's parameters and calls the handler
+//
+//==========================================================================
+
+bool ParsePropertyParams(FScanner &sc, FPropertyInfo *prop, AActor *defaults, Baggage &bag)
+{
+ static TArray params;
+ static TArray strings;
+
+ params.Clear();
+ strings.Clear();
+ params.Reserve(1);
+ params[0].i = 0;
+ if (prop->params[0] != '0')
+ {
+ const char * p = prop->params;
+ bool nocomma;
+ bool optcomma;
+ while (*p)
+ {
+ FPropParam conv;
+ FPropParam pref;
+
+ nocomma = false;
+ conv.s = NULL;
+ pref.i = -1;
+ switch ((*p) & 223)
+ {
+ case 'X': // Expression in parentheses or number.
+
+ if (sc.CheckString ("("))
+ {
+ conv.i = 0x40000000 | ParseExpression (sc, false, bag.Info->Class);
+ params.Push(conv);
+ sc.MustGetStringName(")");
+ break;
+ }
+ // fall through
+
+ case 'I':
+ sc.MustGetNumber();
+ conv.i = sc.Number;
+ break;
+
+ case 'F':
+ sc.MustGetFloat();
+ conv.f = sc.Float;
+ break;
+
+ case 'Z': // an optional string. Does not allow any numerical value.
+ if (sc.CheckFloat())
+ {
+ nocomma = true;
+ sc.UnGet();
+ break;
+ }
+ // fall through
+
+ case 'S':
+ case 'T':
+ sc.MustGetString();
+ conv.s = strings[strings.Reserve(1)] = sc.String;
+ break;
+
+ case 'C':
+ if (sc.CheckNumber ())
+ {
+ int R, G, B;
+ R = clamp (sc.Number, 0, 255);
+ sc.CheckString (",");
+ sc.MustGetNumber ();
+ G = clamp (sc.Number, 0, 255);
+ sc.CheckString (",");
+ sc.MustGetNumber ();
+ B = clamp (sc.Number, 0, 255);
+ conv.i = MAKERGB(R, G, B);
+ pref.i = 0;
+ }
+ else
+ {
+ sc.MustGetString ();
+ conv.s = strings[strings.Reserve(1)] = sc.String;
+ pref.i = 1;
+ }
+ break;
+
+ case 'M': // special case. An expression-aware parser will not need this.
+ conv.i = ParseMorphStyle(sc);
+ break;
+
+ case 'L': // Either a number or a list of strings
+ if (sc.CheckNumber())
+ {
+ pref.i = 0;
+ conv.i = sc.Number;
+ }
+ else
+ {
+ pref.i = 1;
+ params.Push(pref);
+ params[0].i++;
+
+ do
+ {
+ sc.MustGetString ();
+ conv.s = strings[strings.Reserve(1)] = sc.String;
+ params.Push(conv);
+ params[0].i++;
+ }
+ while (sc.CheckString(","));
+ goto endofparm;
+ }
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+ if (pref.i != -1)
+ {
+ params.Push(pref);
+ params[0].i++;
+ }
+ params.Push(conv);
+ params[0].i++;
+ endofparm:
+ p++;
+ // Hack for some properties that have to allow comma less
+ // parameter lists for compatibility.
+ if ((optcomma = (*p == '_')))
+ p++;
+
+ if (nocomma)
+ {
+ continue;
+ }
+ else if (*p == 0)
+ {
+ break;
+ }
+ else if (*p >= 'a')
+ {
+ if (!sc.CheckString(","))
+ {
+ if (optcomma)
+ {
+ if (!sc.CheckFloat()) break;
+ else sc.UnGet();
+ }
+ else break;
+ }
+ }
+ else
+ {
+ if (!optcomma) sc.MustGetStringName(",");
+ else sc.CheckString(",");
+ }
+ }
+ }
+ // call the handler
+ try
+ {
+ prop->Handler(defaults, bag, ¶ms[0]);
+ }
+ catch (CRecoverableError &error)
+ {
+ sc.ScriptError("%s", error.GetMessage());
+ }
+
+ return true;
+}
+
+//==========================================================================
+//
+// Parses an actor property
+//
+//==========================================================================
+
+void ParseActorProperty(FScanner &sc, Baggage &bag)
+{
+ static const char *statenames[] = {
+ "Spawn", "See", "Melee", "Missile", "Pain", "Death", "XDeath", "Burn",
+ "Ice", "Raise", "Crash", "Crush", "Wound", "Disintegrate", "Heal", NULL };
+
+ strlwr (sc.String);
+
+ FString propname = sc.String;
+
+ if (sc.CheckString ("."))
+ {
+ sc.MustGetString ();
+ propname += '.';
+ strlwr (sc.String);
+ propname += sc.String;
+ }
+ else
+ {
+ sc.UnGet ();
+ }
+
+ FPropertyInfo *prop = FindProperty(propname);
+
+ if (prop != NULL)
+ {
+ if (bag.Info->Class->IsDescendantOf(prop->cls))
+ {
+ ParsePropertyParams(sc, prop, (AActor *)bag.Info->Class->Defaults, bag);
+ }
+ else
+ {
+ sc.ScriptError("\"%s\" requires an actor of type \"%s\"\n", propname.GetChars(), prop->cls->TypeName.GetChars());
+ }
+ }
+ else if (!propname.CompareNoCase("States"))
+ {
+ if (!bag.StateSet) ParseStates(sc, bag.Info, (AActor *)bag.Info->Class->Defaults, bag);
+ else sc.ScriptError("Multiple state declarations not allowed");
+ bag.StateSet=true;
+ }
+ else if (MatchString(propname, statenames) != -1)
+ {
+ bag.statedef.AddState(propname, CheckState (sc, bag.Info->Class));
+ }
+ else
+ {
+ sc.ScriptError("\"%s\" is an unknown actor property\n", propname.GetChars());
+ }
+}
+
+
+//==========================================================================
+//
+// Finalizes an actor definition
+//
+//==========================================================================
+
+void FinishActor(FScanner &sc, FActorInfo *info, Baggage &bag)
+{
+ AActor *defaults = (AActor*)info->Class->Defaults;
+
+ try
+ {
+ bag.statedef.FinishStates (info, defaults, bag.StateArray);
+ }
+ catch (CRecoverableError &err)
+ {
+ sc.ScriptError(err.GetMessage());
+ }
+ bag.statedef.InstallStates (info, defaults);
+ bag.StateArray.Clear ();
+ if (bag.DropItemSet)
+ {
+ if (bag.DropItemList == NULL)
+ {
+ if (info->Class->Meta.GetMetaInt (ACMETA_DropItems) != 0)
+ {
+ info->Class->Meta.SetMetaInt (ACMETA_DropItems, 0);
+ }
+ }
+ else
+ {
+ info->Class->Meta.SetMetaInt (ACMETA_DropItems,
+ StoreDropItemChain(bag.DropItemList));
+ }
+ }
+ if (info->Class->IsDescendantOf (RUNTIME_CLASS(AInventory)))
+ {
+ defaults->flags |= MF_SPECIAL;
+ }
+}
diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp
index 5c355f80..ea12c553 100644
--- a/src/thingdef/thingdef_properties.cpp
+++ b/src/thingdef/thingdef_properties.cpp
@@ -1,7 +1,7 @@
/*
** thingdef-properties.cpp
**
-** Actor definitions - properties and flags parser
+** Actor definitions - properties and flags handling
**
**---------------------------------------------------------------------------
** Copyright 2002-2007 Christoph Oelckers
@@ -41,7 +41,6 @@
#include "gi.h"
#include "actor.h"
#include "info.h"
-#include "sc_man.h"
#include "tarray.h"
#include "w_wad.h"
#include "templates.h"
@@ -68,6 +67,7 @@
#include "r_translate.h"
#include "a_morph.h"
#include "colormatcher.h"
+#include "autosegs.h"
//==========================================================================
//
@@ -81,13 +81,6 @@
#define DEFINE_DEPRECATED_FLAG(name) { DEPF_##name, #name, -1 }
#define DEFINE_DUMMY_FLAG(name) { DEPF_UNUSED, #name, -1 }
-struct flagdef
-{
- int flagbit;
- const char *name;
- int structoffset;
-};
-
enum
{
DEPF_UNUSED,
@@ -101,7 +94,7 @@ enum
DEPF_FIRERESIST,
};
-static flagdef ActorFlags[]=
+static FFlagDef ActorFlags[]=
{
DEFINE_FLAG(MF, PICKUP, APlayerPawn, flags),
DEFINE_FLAG(MF, SPECIAL, APlayerPawn, flags),
@@ -267,7 +260,7 @@ static flagdef ActorFlags[]=
DEFINE_DUMMY_FLAG(ALLOWCLIENTSPAWN),
};
-static flagdef InventoryFlags[] =
+static FFlagDef InventoryFlags[] =
{
// Inventory flags
DEFINE_FLAG(IF, QUIET, AInventory, ItemFlags),
@@ -288,7 +281,7 @@ static flagdef InventoryFlags[] =
};
-static flagdef WeaponFlags[] =
+static FFlagDef WeaponFlags[] =
{
// Weapon flags
DEFINE_FLAG(WIF, NOAUTOFIRE, AWeapon, WeaponFlags),
@@ -311,11 +304,11 @@ static flagdef WeaponFlags[] =
DEFINE_DUMMY_FLAG(NOLMS),
};
-static const struct { const PClass *Type; flagdef *Defs; int NumDefs; } FlagLists[] =
+static const struct { const PClass *Type; FFlagDef *Defs; int NumDefs; } FlagLists[] =
{
- { RUNTIME_CLASS(AActor), ActorFlags, sizeof(ActorFlags)/sizeof(flagdef) },
- { RUNTIME_CLASS(AInventory), InventoryFlags, sizeof(InventoryFlags)/sizeof(flagdef) },
- { RUNTIME_CLASS(AWeapon), WeaponFlags, sizeof(WeaponFlags)/sizeof(flagdef) }
+ { RUNTIME_CLASS(AActor), ActorFlags, sizeof(ActorFlags)/sizeof(FFlagDef) },
+ { RUNTIME_CLASS(AInventory), InventoryFlags, sizeof(InventoryFlags)/sizeof(FFlagDef) },
+ { RUNTIME_CLASS(AWeapon), WeaponFlags, sizeof(WeaponFlags)/sizeof(FFlagDef) }
};
#define NUM_FLAG_LISTS 3
@@ -326,10 +319,10 @@ static const struct { const PClass *Type; flagdef *Defs; int NumDefs; } FlagList
//==========================================================================
static int STACK_ARGS flagcmp (const void * a, const void * b)
{
- return stricmp( ((flagdef*)a)->name, ((flagdef*)b)->name);
+ return stricmp( ((FFlagDef*)a)->name, ((FFlagDef*)b)->name);
}
-static flagdef *FindFlag (flagdef *flags, int numflags, const char *flag)
+static FFlagDef *FindFlag (FFlagDef *flags, int numflags, const char *flag)
{
int min = 0, max = numflags - 1;
@@ -353,17 +346,17 @@ static flagdef *FindFlag (flagdef *flags, int numflags, const char *flag)
return NULL;
}
-static flagdef *FindFlag (const PClass *type, const char *part1, const char *part2)
+FFlagDef *FindFlag (const PClass *type, const char *part1, const char *part2)
{
static bool flagsorted = false;
- flagdef *def;
+ FFlagDef *def;
int i;
if (!flagsorted)
{
for (i = 0; i < NUM_FLAG_LISTS; ++i)
{
- qsort (FlagLists[i].Defs, FlagLists[i].NumDefs, sizeof(flagdef), flagcmp);
+ qsort (FlagLists[i].Defs, FlagLists[i].NumDefs, sizeof(FFlagDef), flagcmp);
}
flagsorted = true;
}
@@ -412,7 +405,7 @@ static flagdef *FindFlag (const PClass *type, const char *part1, const char *par
// properties is not recommended
//
//===========================================================================
-static void HandleDeprecatedFlags(AActor *defaults, FActorInfo *info, bool set, int index)
+void HandleDeprecatedFlags(AActor *defaults, FActorInfo *info, bool set, int index)
{
switch (index)
{
@@ -452,372 +445,126 @@ static void HandleDeprecatedFlags(AActor *defaults, FActorInfo *info, bool set,
}
}
-//===========================================================================
-//
-// A_ChangeFlag
-//
-// This cannot be placed in thingdef_codeptr because it needs the flag table
-//
-//===========================================================================
-DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ChangeFlag)
-{
- ACTION_PARAM_START(2);
- ACTION_PARAM_STRING(flagname, 0);
- ACTION_PARAM_BOOL(expression, 1);
-
- const char *dot = strchr (flagname, '.');
- flagdef *fd;
- const PClass *cls = self->GetClass();
-
- if (dot != NULL)
- {
- FString part1(flagname, dot-flagname);
- fd = FindFlag (cls, part1, dot+1);
- }
- else
- {
- fd = FindFlag (cls, flagname, NULL);
- }
-
- if (fd != NULL)
- {
- if (fd->structoffset == -1)
- {
- HandleDeprecatedFlags(self, cls->ActorInfo, expression, fd->flagbit);
- }
- else
- {
- int * flagp = (int*) (((char*)self) + fd->structoffset);
-
- if (expression) *flagp |= fd->flagbit;
- else *flagp &= ~fd->flagbit;
- }
- }
- else
- {
- Printf("Unknown flag '%s' in '%s'\n", flagname, cls->TypeName.GetChars());
- }
-}
-
//==========================================================================
//
+//
+//
//==========================================================================
-void ParseActorFlag (FScanner &sc, Baggage &bag, int mod)
+int MatchString (const char *in, const char **strings)
{
- flagdef *fd;
+ int i;
- sc.MustGetString ();
-
- FString part1 = sc.String;
- const char *part2 = NULL;
- if (sc.CheckString ("."))
+ for (i = 0; *strings != NULL; i++)
{
- sc.MustGetString ();
- part2 = sc.String;
- }
- if ( (fd = FindFlag (bag.Info->Class, part1.GetChars(), part2)) )
- {
- AActor *defaults = (AActor*)bag.Info->Class->Defaults;
- if (fd->structoffset == -1) // this is a deprecated flag that has been changed into a real property
+ if (!stricmp(in, *strings++))
{
- HandleDeprecatedFlags(defaults, bag.Info, mod=='+', fd->flagbit);
- }
- else
- {
- DWORD * flagvar = (DWORD*) ((char*)defaults + fd->structoffset);
- if (mod == '+')
- {
- *flagvar |= fd->flagbit;
- }
- else
- {
- *flagvar &= ~fd->flagbit;
- }
- }
- }
- else
- {
- if (part2 == NULL)
- {
- sc.ScriptError("\"%s\" is an unknown flag\n", part1.GetChars());
- }
- else
- {
- sc.ScriptError("\"%s.%s\" is an unknown flag\n", part1.GetChars(), part2);
- }
- }
-}
-
-
-
-//----------------------------------------------------------------------------
-//----------------------------------------------------------------------------
-//
-// Translation parsing
-//
-//----------------------------------------------------------------------------
-//----------------------------------------------------------------------------
-FRemapTable CurrentTranslation;
-TArray BloodTranslationColors;
-
-PalEntry BloodTranslations[256];
-
-static bool Check(char *& range, char c, bool error=true)
-{
- while (isspace(*range)) range++;
- if (*range==c)
- {
- range++;
- return true;
- }
- if (error)
- {
- //sc.ScriptError("Invalid syntax in translation specification: '%c' expected", c);
- }
- return false;
-}
-
-
-static void AddToTranslation(char * range)
-{
- int start,end;
-
- start=strtol(range, &range, 10);
- if (!Check(range, ':')) return;
- end=strtol(range, &range, 10);
- if (!Check(range, '=')) return;
- if (!Check(range, '[', false))
- {
- int pal1,pal2;
-
- pal1=strtol(range, &range, 10);
- if (!Check(range, ':')) return;
- pal2=strtol(range, &range, 10);
-
- CurrentTranslation.AddIndexRange(start, end, pal1, pal2);
- }
- else
- {
- // translation using RGB values
- int r1,g1,b1,r2,g2,b2;
-
- r1=strtol(range, &range, 10);
- if (!Check(range, ',')) return;
- g1=strtol(range, &range, 10);
- if (!Check(range, ',')) return;
- b1=strtol(range, &range, 10);
- if (!Check(range, ']')) return;
- if (!Check(range, ':')) return;
- if (!Check(range, '[')) return;
- r2=strtol(range, &range, 10);
- if (!Check(range, ',')) return;
- g2=strtol(range, &range, 10);
- if (!Check(range, ',')) return;
- b2=strtol(range, &range, 10);
- if (!Check(range, ']')) return;
-
- CurrentTranslation.AddColorRange(start, end, r1, g1, b1, r2, g2, b2);
- }
-}
-
-static int StoreTranslation(FScanner &sc)
-{
- unsigned int i;
-
- for (i = 0; i < translationtables[TRANSLATION_Decorate].Size(); i++)
- {
- if (CurrentTranslation == *translationtables[TRANSLATION_Decorate][i])
- {
- // A duplicate of this translation already exists
- return TRANSLATION(TRANSLATION_Decorate, i);
- }
- }
- if (translationtables[TRANSLATION_Decorate].Size() >= MAX_DECORATE_TRANSLATIONS)
- {
- sc.ScriptError("Too many translations in DECORATE");
- }
- FRemapTable *newtrans = new FRemapTable;
- *newtrans = CurrentTranslation;
- i = translationtables[TRANSLATION_Decorate].Push(newtrans);
- return TRANSLATION(TRANSLATION_Decorate, i);
-}
-
-static int CreateBloodTranslation(FScanner &sc, PalEntry color)
-{
- unsigned int i;
-
- for (i = 0; i < BloodTranslationColors.Size(); i++)
- {
- if (color.r == BloodTranslationColors[i].r &&
- color.g == BloodTranslationColors[i].g &&
- color.b == BloodTranslationColors[i].b)
- {
- // A duplicate of this translation already exists
return i;
}
}
- if (BloodTranslationColors.Size() >= MAX_DECORATE_TRANSLATIONS)
- {
- sc.ScriptError("Too many blood colors in DECORATE");
- }
- FRemapTable *trans = new FRemapTable;
- for (i = 0; i < 256; i++)
- {
- int bright = MAX(MAX(GPalette.BaseColors[i].r, GPalette.BaseColors[i].g), GPalette.BaseColors[i].b);
- PalEntry pe = PalEntry(color.r*bright/255, color.g*bright/255, color.b*bright/255);
- int entry = ColorMatcher.Pick(pe.r, pe.g, pe.b);
-
- trans->Palette[i] = pe;
- trans->Remap[i] = entry;
- }
- translationtables[TRANSLATION_Blood].Push(trans);
- return BloodTranslationColors.Push(color);
-}
-
-//----------------------------------------------------------------------------
-//
-// DropItem handling
-//
-//----------------------------------------------------------------------------
-
-static void FreeDropItemChain(FDropItem *chain)
-{
- while (chain != NULL)
- {
- FDropItem *next = chain->Next;
- delete chain;
- chain = next;
- }
-}
-
-class FDropItemPtrArray : public TArray
-{
-public:
- ~FDropItemPtrArray()
- {
- for (unsigned int i = 0; i < Size(); ++i)
- {
- FreeDropItemChain ((*this)[i]);
- }
- }
-};
-
-static FDropItemPtrArray DropItemList;
-
-FDropItem *GetDropItems(const PClass *cls)
-{
- unsigned int index = cls->Meta.GetMetaInt (ACMETA_DropItems) - 1;
-
- if (index >= 0 && index < DropItemList.Size())
- {
- return DropItemList[index];
- }
- return NULL;
+ return -1;
}
//==========================================================================
//
+// Info Property handlers
//
//==========================================================================
-typedef void (*ActorPropFunction) (FScanner &sc, AActor *defaults, Baggage &bag);
-
-struct ActorProps
-{
- const char *name;
- ActorPropFunction Handler;
- const PClass * type;
-};
-
-typedef ActorProps (*ActorPropHandler) (const char *str, unsigned int len);
-
-static const ActorProps *is_actorprop (const char *str);
-
-
//==========================================================================
//
-// Checks for a numeric parameter which may or may not be preceded by a comma
-//
//==========================================================================
-static bool CheckNumParm(FScanner &sc)
+DEFINE_INFO_PROPERTY(game, T, Actor)
{
- if (sc.CheckString(","))
+ PROP_STRING_PARM(str, 0);
+ if (!stricmp(str, "Doom"))
{
- sc.MustGetNumber();
- return true;
+ bag.Info->GameFilter |= GAME_Doom;
+ }
+ else if (!stricmp(str, "Heretic"))
+ {
+ bag.Info->GameFilter |= GAME_Heretic;
+ }
+ else if (!stricmp(str, "Hexen"))
+ {
+ bag.Info->GameFilter |= GAME_Hexen;
+ }
+ else if (!stricmp(str, "Raven"))
+ {
+ bag.Info->GameFilter |= GAME_Raven;
+ }
+ else if (!stricmp(str, "Strife"))
+ {
+ bag.Info->GameFilter |= GAME_Strife;
+ }
+ else if (!stricmp(str, "Chex"))
+ {
+ bag.Info->GameFilter |= GAME_Chex;
+ }
+ else if (!stricmp(str, "Any"))
+ {
+ bag.Info->GameFilter = GAME_Any;
}
else
{
- return sc.CheckNumber();
+ I_Error ("Unknown game type %s", str);
}
}
-static bool CheckFloatParm(FScanner &sc)
+//==========================================================================
+//
+//==========================================================================
+DEFINE_INFO_PROPERTY(spawnid, I, Actor)
{
- if (sc.CheckString(","))
+ PROP_INT_PARM(id, 0);
+ if (id<0 || id>255)
{
- sc.MustGetFloat();
- return true;
- }
- else
- {
- return sc.CheckFloat();
+ I_Error ("SpawnID must be in the range [0,255]");
}
+ else bag.Info->SpawnID=(BYTE)id;
}
-// [MH]
-static int ParseMorphStyle (FScanner &sc)
+//==========================================================================
+//
+//==========================================================================
+DEFINE_INFO_PROPERTY(conversationid, IiI, Actor)
{
- static const char * morphstyles[]={
- "MRF_ADDSTAMINA", "MRF_FULLHEALTH", "MRF_UNDOBYTOMEOFPOWER", "MRF_UNDOBYCHAOSDEVICE",
- "MRF_FAILNOTELEFRAG", "MRF_FAILNOLAUGH", "MRF_WHENINVULNERABLE", "MRF_LOSEACTUALWEAPON",
- "MRF_NEWTIDBEHAVIOUR", "MRF_UNDOBYDEATH", "MRF_UNDOBYDEATHFORCED", "MRF_UNDOBYDEATHSAVES", NULL};
+ PROP_INT_PARM(convid, 0);
+ PROP_INT_PARM(id1, 1);
+ PROP_INT_PARM(id2, 2);
- static const int morphstyle_values[]={
- MORPH_ADDSTAMINA, MORPH_FULLHEALTH, MORPH_UNDOBYTOMEOFPOWER, MORPH_UNDOBYCHAOSDEVICE,
- MORPH_FAILNOTELEFRAG, MORPH_FAILNOLAUGH, MORPH_WHENINVULNERABLE, MORPH_LOSEACTUALWEAPON,
- MORPH_NEWTIDBEHAVIOUR, MORPH_UNDOBYDEATH, MORPH_UNDOBYDEATHFORCED, MORPH_UNDOBYDEATHSAVES};
-
- // May be given flags by number...
- if (sc.CheckNumber())
+ // Handling for Strife teaser IDs - only of meaning for the standard items
+ // as PWADs cannot be loaded with the teasers.
+ if (PROP_PARM_COUNT > 1)
{
- sc.MustGetNumber();
- return sc.Number;
- }
+ if ((gameinfo.flags & (GI_SHAREWARE|GI_TEASER2)) == (GI_SHAREWARE))
+ convid=id1;
- // ... else should be flags by name.
- // NOTE: Later this should be removed and a normal expression used.
- // The current DECORATE parser can't handle this though.
- bool gotparen = sc.CheckString("(");
- int style = 0;
- do
- {
- sc.MustGetString();
- style |= morphstyle_values[sc.MustMatchString(morphstyles)];
- }
- while (sc.CheckString("|"));
- if (gotparen)
- {
- sc.MustGetStringName(")");
- }
+ if ((gameinfo.flags & (GI_SHAREWARE|GI_TEASER2)) == (GI_SHAREWARE|GI_TEASER2))
+ convid=id2;
- return style;
+ if (convid==-1) return;
+ }
+ if (convid<0 || convid>1000)
+ {
+ I_Error ("ConversationID must be in the range [0,1000]");
+ }
+ else StrifeTypes[convid] = bag.Info->Class;
}
//==========================================================================
//
-// Property parsers
+// Property handlers
//
//==========================================================================
//==========================================================================
//
//==========================================================================
-static void ActorSkipSuper (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(skip_super, 0, Actor)
{
if (bag.Info->Class->IsDescendantOf(RUNTIME_CLASS(AInventory)))
{
- sc.ScriptMessage("'skip_super' in definition of inventory item igmored.\n");
+ Printf("'skip_super' in definition of inventory item '%s' ignored.", bag.Info->Class->TypeName.GetChars() );
return;
}
@@ -826,264 +573,173 @@ static void ActorSkipSuper (FScanner &sc, AActor *defaults, Baggage &bag)
{
FreeDropItemChain (bag.DropItemList);
}
- ResetBaggage (&bag);
- MakeStateDefines(NULL);
+ ResetBaggage (&bag, RUNTIME_CLASS(AActor));
}
//==========================================================================
//
//==========================================================================
-static void ActorGame (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(tag, S, Actor)
{
- sc.MustGetString ();
- if (sc.Compare ("Doom"))
+ PROP_STRING_PARM(str, 0);
+ bag.Info->Class->Meta.SetMetaString(AMETA_StrifeName, str);
+}
+
+//==========================================================================
+//
+//==========================================================================
+DEFINE_PROPERTY(health, I, Actor)
+{
+ PROP_INT_PARM(id, 0);
+ defaults->health=id;
+}
+
+//==========================================================================
+//
+//==========================================================================
+DEFINE_PROPERTY(gibhealth, I, Actor)
+{
+ PROP_INT_PARM(id, 0);
+ bag.Info->Class->Meta.SetMetaInt (AMETA_GibHealth, id);
+}
+
+//==========================================================================
+//
+//==========================================================================
+DEFINE_PROPERTY(woundhealth, I, Actor)
+{
+ PROP_INT_PARM(id, 0);
+ bag.Info->Class->Meta.SetMetaInt (AMETA_WoundHealth, id);
+}
+
+//==========================================================================
+//
+//==========================================================================
+DEFINE_PROPERTY(reactiontime, I, Actor)
+{
+ PROP_INT_PARM(id, 0);
+ defaults->reactiontime=id;
+}
+
+//==========================================================================
+//
+//==========================================================================
+DEFINE_PROPERTY(painchance, ZI, Actor)
+{
+ PROP_STRING_PARM(str, 0);
+ PROP_INT_PARM(id, 1);
+ if (str == NULL)
{
- bag.Info->GameFilter |= GAME_Doom;
- }
- else if (sc.Compare ("Heretic"))
- {
- bag.Info->GameFilter |= GAME_Heretic;
- }
- else if (sc.Compare ("Hexen"))
- {
- bag.Info->GameFilter |= GAME_Hexen;
- }
- else if (sc.Compare ("Raven"))
- {
- bag.Info->GameFilter |= GAME_Raven;
- }
- else if (sc.Compare ("Strife"))
- {
- bag.Info->GameFilter |= GAME_Strife;
- }
- else if (sc.Compare ("Chex"))
- {
- bag.Info->GameFilter |= GAME_Chex;
- }
- else if (sc.Compare ("Any"))
- {
- bag.Info->GameFilter = GAME_Any;
+ defaults->PainChance=id;
}
else
- {
- sc.ScriptError ("Unknown game type %s", sc.String);
- }
-}
-
-//==========================================================================
-//
-//==========================================================================
-static void ActorSpawnID (FScanner &sc, AActor *defaults, Baggage &bag)
-{
- sc.MustGetNumber();
- if (sc.Number<0 || sc.Number>255)
- {
- sc.ScriptError ("SpawnID must be in the range [0,255]");
- }
- else bag.Info->SpawnID=(BYTE)sc.Number;
-}
-
-//==========================================================================
-//
-//==========================================================================
-static void ActorConversationID (FScanner &sc, AActor *defaults, Baggage &bag)
-{
- int convid;
-
- sc.MustGetNumber();
- convid = sc.Number;
-
- // Handling for Strife teaser IDs - only of meaning for the standard items
- // as PWADs cannot be loaded with the teasers.
- if (sc.CheckString(","))
- {
- sc.MustGetNumber();
- if ((gameinfo.flags & (GI_SHAREWARE|GI_TEASER2)) == (GI_SHAREWARE))
- convid=sc.Number;
-
- sc.MustGetStringName(",");
- sc.MustGetNumber();
- if ((gameinfo.flags & (GI_SHAREWARE|GI_TEASER2)) == (GI_SHAREWARE|GI_TEASER2))
- convid=sc.Number;
-
- if (convid==-1) return;
- }
- if (convid<0 || convid>1000)
- {
- sc.ScriptError ("ConversationID must be in the range [0,1000]");
- }
- else StrifeTypes[convid] = bag.Info->Class;
-}
-
-//==========================================================================
-//
-//==========================================================================
-static void ActorTag (FScanner &sc, AActor *defaults, Baggage &bag)
-{
- sc.MustGetString();
- bag.Info->Class->Meta.SetMetaString(AMETA_StrifeName, sc.String);
-}
-
-//==========================================================================
-//
-//==========================================================================
-static void ActorHealth (FScanner &sc, AActor *defaults, Baggage &bag)
-{
- sc.MustGetNumber();
- defaults->health=sc.Number;
-}
-
-//==========================================================================
-//
-//==========================================================================
-static void ActorGibHealth (FScanner &sc, AActor *defaults, Baggage &bag)
-{
- sc.MustGetNumber();
- bag.Info->Class->Meta.SetMetaInt (AMETA_GibHealth, sc.Number);
-}
-
-//==========================================================================
-//
-//==========================================================================
-static void ActorWoundHealth (FScanner &sc, AActor *defaults, Baggage &bag)
-{
- sc.MustGetNumber();
- bag.Info->Class->Meta.SetMetaInt (AMETA_WoundHealth, sc.Number);
-}
-
-//==========================================================================
-//
-//==========================================================================
-static void ActorReactionTime (FScanner &sc, AActor *defaults, Baggage &bag)
-{
- sc.MustGetNumber();
- defaults->reactiontime=sc.Number;
-}
-
-//==========================================================================
-//
-//==========================================================================
-static void ActorPainChance (FScanner &sc, AActor *defaults, Baggage &bag)
-{
- if (!sc.CheckNumber())
{
FName painType;
- sc.MustGetString();
- if (sc.Compare("Normal")) painType = NAME_None;
- else painType=sc.String;
- sc.MustGetToken(',');
- sc.MustGetNumber();
- bag.Info->SetPainChance(painType, sc.Number);
- return;
+ if (!stricmp(str, "Normal")) painType = NAME_None;
+ else painType=str;
+
+ if (bag.Info->PainChances == NULL) bag.Info->PainChances=new PainChanceList;
+ (*bag.Info->PainChances)[painType] = (BYTE)id;
}
- defaults->PainChance=sc.Number;
}
//==========================================================================
//
//==========================================================================
-static void ActorDamage (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(damage, X, Actor)
{
+ PROP_INT_PARM(id, 0);
+
// Damage can either be a single number, in which case it is subject
// to the original damage calculation rules. Or, it can be an expression
// and will be calculated as-is, ignoring the original rules. For
// compatibility reasons, expressions must be enclosed within
// parentheses.
- if (sc.CheckString ("("))
+ defaults->Damage = id;
+}
+
+//==========================================================================
+//
+//==========================================================================
+DEFINE_PROPERTY(speed, F, Actor)
+{
+ PROP_FIXED_PARM(id, 0);
+ defaults->Speed = id;
+}
+
+//==========================================================================
+//
+//==========================================================================
+DEFINE_PROPERTY(floatspeed, F, Actor)
+{
+ PROP_FIXED_PARM(id, 0);
+ defaults->FloatSpeed=id;
+}
+
+//==========================================================================
+//
+//==========================================================================
+DEFINE_PROPERTY(radius, F, Actor)
+{
+ PROP_FIXED_PARM(id, 0);
+ defaults->radius=id;
+}
+
+//==========================================================================
+//
+//==========================================================================
+DEFINE_PROPERTY(height, F, Actor)
+{
+ PROP_FIXED_PARM(id, 0);
+ defaults->height=id;
+}
+
+//==========================================================================
+//
+//==========================================================================
+DEFINE_PROPERTY(mass, I, Actor)
+{
+ PROP_INT_PARM(id, 0);
+ defaults->Mass=id;
+}
+
+//==========================================================================
+//
+//==========================================================================
+DEFINE_PROPERTY(xscale, F, Actor)
+{
+ PROP_FIXED_PARM(id, 0);
+ defaults->scaleX = id;
+}
+
+//==========================================================================
+//
+//==========================================================================
+DEFINE_PROPERTY(yscale, F, Actor)
+{
+ PROP_FIXED_PARM(id, 0);
+ defaults->scaleY = id;
+}
+
+//==========================================================================
+//
+//==========================================================================
+DEFINE_PROPERTY(scale, F, Actor)
+{
+ PROP_FIXED_PARM(id, 0);
+ defaults->scaleX = defaults->scaleY = id;
+}
+
+//==========================================================================
+//
+//==========================================================================
+DEFINE_PROPERTY(args, Iiiii, Actor)
+{
+ for (int i = 0; i < PROP_PARM_COUNT; i++)
{
- defaults->Damage = 0x40000000 | ParseExpression (sc, false, bag.Info->Class);
- sc.MustGetStringName(")");
- }
- else
- {
- sc.MustGetNumber ();
- defaults->Damage = sc.Number;
- }
-}
-
-//==========================================================================
-//
-//==========================================================================
-static void ActorSpeed (FScanner &sc, AActor *defaults, Baggage &bag)
-{
- sc.MustGetFloat();
- defaults->Speed=fixed_t(sc.Float*FRACUNIT);
-}
-
-//==========================================================================
-//
-//==========================================================================
-static void ActorFloatSpeed (FScanner &sc, AActor *defaults, Baggage &bag)
-{
- sc.MustGetFloat();
- defaults->FloatSpeed=fixed_t(sc.Float*FRACUNIT);
-}
-
-//==========================================================================
-//
-//==========================================================================
-static void ActorRadius (FScanner &sc, AActor *defaults, Baggage &bag)
-{
- sc.MustGetFloat();
- defaults->radius=fixed_t(sc.Float*FRACUNIT);
-}
-
-//==========================================================================
-//
-//==========================================================================
-static void ActorHeight (FScanner &sc, AActor *defaults, Baggage &bag)
-{
- sc.MustGetFloat();
- defaults->height=fixed_t(sc.Float*FRACUNIT);
-}
-
-//==========================================================================
-//
-//==========================================================================
-static void ActorMass (FScanner &sc, AActor *defaults, Baggage &bag)
-{
- sc.MustGetNumber();
- defaults->Mass=sc.Number;
-}
-
-//==========================================================================
-//
-//==========================================================================
-static void ActorXScale (FScanner &sc, AActor *defaults, Baggage &bag)
-{
- sc.MustGetFloat();
- defaults->scaleX = FLOAT2FIXED(sc.Float);
-}
-
-//==========================================================================
-//
-//==========================================================================
-static void ActorYScale (FScanner &sc, AActor *defaults, Baggage &bag)
-{
- sc.MustGetFloat();
- defaults->scaleY = FLOAT2FIXED(sc.Float);
-}
-
-//==========================================================================
-//
-//==========================================================================
-static void ActorScale (FScanner &sc, AActor *defaults, Baggage &bag)
-{
- sc.MustGetFloat();
- defaults->scaleX= defaults->scaleY = FLOAT2FIXED(sc.Float);
-}
-
-//==========================================================================
-//
-//==========================================================================
-static void ActorArgs (FScanner &sc, AActor *defaults, Baggage &bag)
-{
- for (int i = 0; i < 5; i++)
- {
- sc.MustGetNumber();
- defaults->args[i] = sc.Number;
- if (i < 4 && !sc.CheckToken(',')) break;
+ PROP_INT_PARM(id, i);
+ defaults->args[i] = id;
}
defaults->flags2|=MF2_ARGSDEFINED;
}
@@ -1091,62 +747,64 @@ static void ActorArgs (FScanner &sc, AActor *defaults, Baggage &bag)
//==========================================================================
//
//==========================================================================
-static void ActorSeeSound (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(seesound, S, Actor)
{
- sc.MustGetString();
- defaults->SeeSound = sc.String;
+ PROP_STRING_PARM(str, 0);
+ defaults->SeeSound = str;
}
//==========================================================================
//
//==========================================================================
-static void ActorAttackSound (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(attacksound, S, Actor)
{
- sc.MustGetString();
- defaults->AttackSound = sc.String;
+ PROP_STRING_PARM(str, 0);
+ defaults->AttackSound = str;
}
//==========================================================================
//
//==========================================================================
-static void ActorPainSound (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(painsound, S, Actor)
{
- sc.MustGetString();
- defaults->PainSound = sc.String;
+ PROP_STRING_PARM(str, 0);
+ defaults->PainSound = str;
}
//==========================================================================
//
//==========================================================================
-static void ActorDeathSound (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(deathsound, S, Actor)
{
- sc.MustGetString();
- defaults->DeathSound = sc.String;
+ PROP_STRING_PARM(str, 0);
+ defaults->DeathSound = str;
}
//==========================================================================
//
//==========================================================================
-static void ActorActiveSound (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(activesound, S, Actor)
{
- sc.MustGetString();
- defaults->ActiveSound = sc.String;
+ PROP_STRING_PARM(str, 0);
+ defaults->ActiveSound = str;
}
//==========================================================================
//
//==========================================================================
-static void ActorHowlSound (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(howlsound, S, Actor)
{
- sc.MustGetString();
- bag.Info->Class->Meta.SetMetaInt (AMETA_HowlSound, S_FindSound(sc.String));
+ PROP_STRING_PARM(str, 0);
+ bag.Info->Class->Meta.SetMetaInt (AMETA_HowlSound, S_FindSound(str));
}
//==========================================================================
//
//==========================================================================
-static void ActorDropItem (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(dropitem, S_i_i, Actor)
{
+ PROP_STRING_PARM(type, 0);
+
// create a linked list of dropitems
if (!bag.DropItemSet)
{
@@ -1156,17 +814,18 @@ static void ActorDropItem (FScanner &sc, AActor *defaults, Baggage &bag)
FDropItem *di = new FDropItem;
- sc.MustGetString();
- di->Name=sc.String;
+ di->Name =type;
di->probability=255;
di->amount=-1;
- if (CheckNumParm(sc))
+ if (PROP_PARM_COUNT > 1)
{
- di->probability = sc.Number;
- if (CheckNumParm(sc))
+ PROP_INT_PARM(prob, 1);
+ di->probability = prob;
+ if (PROP_PARM_COUNT > 2)
{
- di->amount = sc.Number;
+ PROP_INT_PARM(amt, 1);
+ di->amount = amt;
}
}
di->Next = bag.DropItemList;
@@ -1176,138 +835,9 @@ static void ActorDropItem (FScanner &sc, AActor *defaults, Baggage &bag)
//==========================================================================
//
//==========================================================================
-static void ActorSpawnState (FScanner &sc, AActor *defaults, Baggage &bag)
-{
- AddState("Spawn", CheckState (sc, bag.Info->Class));
-}
-
-//==========================================================================
-//
-//==========================================================================
-static void ActorSeeState (FScanner &sc, AActor *defaults, Baggage &bag)
-{
- AddState("See", CheckState (sc, bag.Info->Class));
-}
-
-//==========================================================================
-//
-//==========================================================================
-static void ActorMeleeState (FScanner &sc, AActor *defaults, Baggage &bag)
-{
- AddState("Melee", CheckState (sc, bag.Info->Class));
-}
-
-//==========================================================================
-//
-//==========================================================================
-static void ActorMissileState (FScanner &sc, AActor *defaults, Baggage &bag)
-{
- AddState("Missile", CheckState (sc, bag.Info->Class));
-}
-
-//==========================================================================
-//
-//==========================================================================
-static void ActorPainState (FScanner &sc, AActor *defaults, Baggage &bag)
-{
- AddState("Pain", CheckState (sc, bag.Info->Class));
-}
-
-//==========================================================================
-//
-//==========================================================================
-static void ActorDeathState (FScanner &sc, AActor *defaults, Baggage &bag)
-{
- AddState("Death", CheckState (sc, bag.Info->Class));
-}
-
-//==========================================================================
-//
-//==========================================================================
-static void ActorXDeathState (FScanner &sc, AActor *defaults, Baggage &bag)
-{
- AddState("XDeath", CheckState (sc, bag.Info->Class));
-}
-
-//==========================================================================
-//
-//==========================================================================
-static void ActorBurnState (FScanner &sc, AActor *defaults, Baggage &bag)
-{
- AddState("Burn", CheckState (sc, bag.Info->Class));
-}
-
-//==========================================================================
-//
-//==========================================================================
-static void ActorIceState (FScanner &sc, AActor *defaults, Baggage &bag)
-{
- AddState("Ice", CheckState (sc, bag.Info->Class));
-}
-
-//==========================================================================
-//
-//==========================================================================
-static void ActorRaiseState (FScanner &sc, AActor *defaults, Baggage &bag)
-{
- AddState("Raise", CheckState (sc, bag.Info->Class));
-}
-
-//==========================================================================
-//
-//==========================================================================
-static void ActorCrashState (FScanner &sc, AActor *defaults, Baggage &bag)
-{
- AddState("Crash", CheckState (sc, bag.Info->Class));
-}
-
-//==========================================================================
-//
-//==========================================================================
-static void ActorCrushState (FScanner &sc, AActor *defaults, Baggage &bag)
-{
- AddState("Crush", CheckState (sc, bag.Info->Class));
-}
-
-//==========================================================================
-//
-//==========================================================================
-static void ActorWoundState (FScanner &sc, AActor *defaults, Baggage &bag)
-{
- AddState("Wound", CheckState (sc, bag.Info->Class));
-}
-
-//==========================================================================
-//
-//==========================================================================
-static void ActorDisintegrateState (FScanner &sc, AActor *defaults, Baggage &bag)
-{
- AddState("Disintegrate", CheckState (sc, bag.Info->Class));
-}
-
-//==========================================================================
-//
-//==========================================================================
-static void ActorHealState (FScanner &sc, AActor *defaults, Baggage &bag)
-{
- AddState("Heal", CheckState (sc, bag.Info->Class));
-}
-
-//==========================================================================
-//
-//==========================================================================
-static void ActorStates (FScanner &sc, AActor *defaults, Baggage &bag)
-{
- if (!bag.StateSet) ParseStates(sc, bag.Info, defaults, bag);
- else sc.ScriptError("Multiple state declarations not allowed");
- bag.StateSet=true;
-}
-
-//==========================================================================
-//
-//==========================================================================
-static void ActorRenderStyle (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(renderstyle, S, Actor)
{
+ PROP_STRING_PARM(str, 0);
static const char * renderstyles[]={
"NONE","NORMAL","FUZZY","SOULTRANS","OPTFUZZY","STENCIL","TRANSLUCENT", "ADD","SHADED", NULL};
@@ -1315,48 +845,53 @@ static void ActorRenderStyle (FScanner &sc, AActor *defaults, Baggage &bag)
STYLE_None, STYLE_Normal, STYLE_Fuzzy, STYLE_SoulTrans, STYLE_OptFuzzy,
STYLE_TranslucentStencil, STYLE_Translucent, STYLE_Add, STYLE_Shaded};
- sc.MustGetString();
- defaults->RenderStyle = LegacyRenderStyles[renderstyle_values[sc.MustMatchString(renderstyles)]];
+ // make this work for old style decorations, too.
+ if (!strnicmp(str, "style_", 6)) str+=6;
+
+ int style = MatchString(str, renderstyles);
+ if (style < 0) I_Error("Unknown render style '%s'");
+ defaults->RenderStyle = LegacyRenderStyles[renderstyle_values[style]];
}
//==========================================================================
//
//==========================================================================
-static void ActorAlpha (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(defaultalpha, 0, Actor)
{
- if (sc.CheckString("DEFAULT"))
- {
- defaults->alpha = gameinfo.gametype == GAME_Heretic ? HR_SHADOW : HX_SHADOW;
- }
- else
- {
- sc.MustGetFloat();
- defaults->alpha=fixed_t(sc.Float*FRACUNIT);
- }
+ defaults->alpha = gameinfo.gametype == GAME_Heretic ? HR_SHADOW : HX_SHADOW;
}
//==========================================================================
//
//==========================================================================
-static void ActorObituary (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(alpha, F, Actor)
{
- sc.MustGetString();
- bag.Info->Class->Meta.SetMetaString (AMETA_Obituary, sc.String);
+ PROP_FIXED_PARM(id, 0);
+ defaults->alpha = id;
}
//==========================================================================
//
//==========================================================================
-static void ActorHitObituary (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(obituary, S, Actor)
{
- sc.MustGetString();
- bag.Info->Class->Meta.SetMetaString (AMETA_HitObituary, sc.String);
+ PROP_STRING_PARM(str, 0);
+ bag.Info->Class->Meta.SetMetaString (AMETA_Obituary, str);
}
//==========================================================================
//
//==========================================================================
-static void ActorDontHurtShooter (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(hitobituary, S, Actor)
+{
+ PROP_STRING_PARM(str, 0);
+ bag.Info->Class->Meta.SetMetaString (AMETA_HitObituary, str);
+}
+
+//==========================================================================
+//
+//==========================================================================
+DEFINE_PROPERTY(donthurtshooter, 0, Actor)
{
bag.Info->Class->Meta.SetMetaInt (ACMETA_DontHurtShooter, true);
}
@@ -1364,28 +899,27 @@ static void ActorDontHurtShooter (FScanner &sc, AActor *defaults, Baggage &bag)
//==========================================================================
//
//==========================================================================
-static void ActorExplosionRadius (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(explosionradius, I, Actor)
{
- sc.MustGetNumber();
- bag.Info->Class->Meta.SetMetaInt (ACMETA_ExplosionRadius, sc.Number);
+ PROP_INT_PARM(id, 0);
+ bag.Info->Class->Meta.SetMetaInt (ACMETA_ExplosionRadius, id);
}
//==========================================================================
//
//==========================================================================
-static void ActorExplosionDamage (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(explosiondamage, I, Actor)
{
- sc.MustGetNumber();
- bag.Info->Class->Meta.SetMetaInt (ACMETA_ExplosionDamage, sc.Number);
+ PROP_INT_PARM(id, 0);
+ bag.Info->Class->Meta.SetMetaInt (ACMETA_ExplosionDamage, id);
}
//==========================================================================
//
//==========================================================================
-static void ActorDeathHeight (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(deathheight, F, Actor)
{
- sc.MustGetFloat();
- fixed_t h = fixed_t(sc.Float * FRACUNIT);
+ PROP_FIXED_PARM(h, 0);
// AActor::Die() uses a height of 0 to mean "cut the height to 1/4",
// so if a height of 0 is desired, store it as -1.
bag.Info->Class->Meta.SetMetaFixed (AMETA_DeathHeight, h <= 0 ? -1 : h);
@@ -1394,10 +928,9 @@ static void ActorDeathHeight (FScanner &sc, AActor *defaults, Baggage &bag)
//==========================================================================
//
//==========================================================================
-static void ActorBurnHeight (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(burnheight, F, Actor)
{
- sc.MustGetFloat();
- fixed_t h = fixed_t(sc.Float * FRACUNIT);
+ PROP_FIXED_PARM(h, 0);
// The note above for AMETA_DeathHeight also applies here.
bag.Info->Class->Meta.SetMetaFixed (AMETA_BurnHeight, h <= 0 ? -1 : h);
}
@@ -1405,162 +938,124 @@ static void ActorBurnHeight (FScanner &sc, AActor *defaults, Baggage &bag)
//==========================================================================
//
//==========================================================================
-static void ActorMaxTargetRange (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(maxtargetrange, F, Actor)
{
- sc.MustGetFloat();
- defaults->maxtargetrange = fixed_t(sc.Float*FRACUNIT);
+ PROP_FIXED_PARM(id, 0);
+ defaults->maxtargetrange = id;
}
//==========================================================================
//
//==========================================================================
-static void ActorMeleeThreshold (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(meleethreshold, F, Actor)
{
- sc.MustGetFloat();
- defaults->meleethreshold = fixed_t(sc.Float*FRACUNIT);
+ PROP_FIXED_PARM(id, 0);
+ defaults->meleethreshold = id;
}
//==========================================================================
//
//==========================================================================
-static void ActorMeleeDamage (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(meleedamage, I, Actor)
{
- sc.MustGetNumber();
- bag.Info->Class->Meta.SetMetaInt (ACMETA_MeleeDamage, sc.Number);
+ PROP_INT_PARM(id, 0);
+ bag.Info->Class->Meta.SetMetaInt (ACMETA_MeleeDamage, id);
}
//==========================================================================
//
//==========================================================================
-static void ActorMeleeRange (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(meleerange, F, Actor)
{
- sc.MustGetFloat();
- defaults->meleerange = fixed_t(sc.Float*FRACUNIT);
+ PROP_FIXED_PARM(id, 0);
+ defaults->meleerange = id;
}
//==========================================================================
//
//==========================================================================
-static void ActorMeleeSound (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(meleesound, S, Actor)
{
- sc.MustGetString();
- bag.Info->Class->Meta.SetMetaInt (ACMETA_MeleeSound, S_FindSound(sc.String));
+ PROP_STRING_PARM(str, 0);
+ bag.Info->Class->Meta.SetMetaInt (ACMETA_MeleeSound, S_FindSound(str));
}
//==========================================================================
//
//==========================================================================
-static void ActorMissileType (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(missiletype, S, Actor)
{
- sc.MustGetString();
- bag.Info->Class->Meta.SetMetaInt (ACMETA_MissileName, FName(sc.String));
+ PROP_STRING_PARM(str, 0);
+ bag.Info->Class->Meta.SetMetaInt (ACMETA_MissileName, FName(str));
}
//==========================================================================
//
//==========================================================================
-static void ActorMissileHeight (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(missileheight, F, Actor)
{
- sc.MustGetFloat();
- bag.Info->Class->Meta.SetMetaFixed (ACMETA_MissileHeight, fixed_t(sc.Float*FRACUNIT));
+ PROP_FIXED_PARM(id, 0);
+ bag.Info->Class->Meta.SetMetaFixed (ACMETA_MissileHeight, id);
}
//==========================================================================
//
//==========================================================================
-static void ActorTranslation (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(translation, L, Actor)
{
- if (sc.CheckNumber())
+ PROP_INT_PARM(type, 0);
+
+ if (type == 0)
{
+ PROP_INT_PARM(trans, 1);
int max = (gameinfo.gametype==GAME_Strife || (bag.Info->GameFilter&GAME_Strife)) ? 6:2;
- if (sc.Number < 0 || sc.Number > max)
+ if (trans < 0 || trans > max)
{
- sc.ScriptError ("Translation must be in the range [0,%d]", max);
+ I_Error ("Translation must be in the range [0,%d]", max);
}
- defaults->Translation = TRANSLATION(TRANSLATION_Standard, sc.Number);
+ defaults->Translation = TRANSLATION(TRANSLATION_Standard, trans);
}
- else if (sc.CheckString("Ice"))
- {
- defaults->Translation = TRANSLATION(TRANSLATION_Standard, 7);
- }
- else
+ else
{
+ FRemapTable CurrentTranslation;
+
CurrentTranslation.MakeIdentity();
- do
+ for(int i = 1; i < PROP_PARM_COUNT; i++)
{
- sc.GetString();
- AddToTranslation(sc.String);
+ PROP_STRING_PARM(str, i);
+ if (i== 1 && PROP_PARM_COUNT == 2 && !stricmp(str, "Ice"))
+ {
+ defaults->Translation = TRANSLATION(TRANSLATION_Standard, 7);
+ return;
+ }
+ else
+ {
+ CurrentTranslation.AddToTranslation(str);
+ }
}
- while (sc.CheckString(","));
- defaults->Translation = StoreTranslation (sc);
+ defaults->Translation = CurrentTranslation.StoreTranslation ();
}
}
//==========================================================================
//
//==========================================================================
-static void ActorStencilColor (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(stencilcolor, C, Actor)
{
- int r,g,b;
+ PROP_COLOR_PARM(color, 0);
- if (sc.CheckNumber())
- {
- sc.MustGetNumber();
- r=clamp(sc.Number, 0, 255);
- sc.CheckString(",");
- sc.MustGetNumber();
- g=clamp(sc.Number, 0, 255);
- sc.CheckString(",");
- sc.MustGetNumber();
- b=clamp(sc.Number, 0, 255);
- }
- else
- {
- sc.MustGetString();
- int c = V_GetColor(NULL, sc.String);
- r=RPART(c);
- g=GPART(c);
- b=BPART(c);
- }
- defaults->fillcolor = MAKERGB(r,g,b) | (ColorMatcher.Pick (r, g, b) << 24);
+ defaults->fillcolor = color | (ColorMatcher.Pick (RPART(color), GPART(color), BPART(color)) << 24);
}
-
//==========================================================================
//
//==========================================================================
-static void ActorBloodColor (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(bloodcolor, C, Actor)
{
- int r,g,b;
+ PROP_COLOR_PARM(color, 0);
- if (sc.CheckNumber())
- {
- sc.MustGetNumber();
- r = clamp(sc.Number, 0, 255);
- sc.CheckString(",");
- sc.MustGetNumber();
- g = clamp(sc.Number, 0, 255);
- sc.CheckString(",");
- sc.MustGetNumber();
- b = clamp(sc.Number, 0, 255);
- }
- else
- {
- sc.MustGetString();
- int c = V_GetColor(NULL, sc.String);
- r = RPART(c);
- g = GPART(c);
- b = BPART(c);
- }
- PalEntry pe = MAKERGB(r,g,b);
- pe.a = CreateBloodTranslation(sc, pe);
- if (DWORD(pe) == 0)
- {
- // If black is the first color being created it will create a value of 0
- // which stands for 'no translation'
- // Using (1,1,1) instead of (0,0,0) won't be noticable.
- pe = MAKERGB(1,1,1);
- }
+ PalEntry pe = color;
+ pe.a = CreateBloodTranslation(pe);
bag.Info->Class->Meta.SetMetaInt (AMETA_BloodColor, pe);
}
@@ -1568,25 +1063,26 @@ static void ActorBloodColor (FScanner &sc, AActor *defaults, Baggage &bag)
//==========================================================================
//
//==========================================================================
-static void ActorBloodType (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(bloodtype, Sss, Actor)
{
- sc.MustGetString();
- FName blood = sc.String;
+ PROP_STRING_PARM(str, 0)
+ PROP_STRING_PARM(str1, 1)
+ PROP_STRING_PARM(str2, 2)
+
+ FName blood = str;
// normal blood
bag.Info->Class->Meta.SetMetaInt (AMETA_BloodType, blood);
- if (sc.CheckString(","))
+ if (PROP_PARM_COUNT > 1)
{
- sc.MustGetString();
- blood = sc.String;
+ blood = str1;
}
// blood splatter
bag.Info->Class->Meta.SetMetaInt (AMETA_BloodType2, blood);
- if (sc.CheckString(","))
+ if (PROP_PARM_COUNT > 2)
{
- sc.MustGetString();
- blood = sc.String;
+ blood = str2;
}
// axe blood
bag.Info->Class->Meta.SetMetaInt (AMETA_BloodType3, blood);
@@ -1595,157 +1091,154 @@ static void ActorBloodType (FScanner &sc, AActor *defaults, Baggage &bag)
//==========================================================================
//
//==========================================================================
-static void ActorBounceFactor (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(bouncefactor, F, Actor)
{
- sc.MustGetFloat ();
- defaults->bouncefactor = clamp(fixed_t(sc.Float * FRACUNIT), 0, FRACUNIT);
+ PROP_FIXED_PARM(id, 0);
+ defaults->bouncefactor = clamp(id, 0, FRACUNIT);
}
//==========================================================================
//
//==========================================================================
-static void ActorWallBounceFactor (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(wallbouncefactor, F, Actor)
{
- sc.MustGetFloat ();
- defaults->wallbouncefactor = clamp(fixed_t(sc.Float * FRACUNIT), 0, FRACUNIT);
+ PROP_FIXED_PARM(id, 0);
+ defaults->wallbouncefactor = clamp(id, 0, FRACUNIT);
}
//==========================================================================
//
//==========================================================================
-static void ActorBounceCount (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(bouncecount, I, Actor)
{
- sc.MustGetNumber ();
- defaults->bouncecount = sc.Number;
+ PROP_INT_PARM(id, 0);
+ defaults->bouncecount = id;
}
//==========================================================================
//
//==========================================================================
-static void ActorMinMissileChance (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(minmissilechance, I, Actor)
{
- sc.MustGetNumber ();
- defaults->MinMissileChance=sc.Number;
+ PROP_INT_PARM(id, 0);
+ defaults->MinMissileChance=id;
}
//==========================================================================
//
//==========================================================================
-static void ActorDamageType (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(damagetype, S, Actor)
{
- sc.MustGetString ();
- if (sc.Compare("Normal")) defaults->DamageType = NAME_None;
- else defaults->DamageType=sc.String;
+ PROP_STRING_PARM(str, 0);
+ if (!stricmp(str, "Normal")) defaults->DamageType = NAME_None;
+ else defaults->DamageType=str;
}
//==========================================================================
//
//==========================================================================
-static void ActorDamageFactor (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(damagefactor, SF, Actor)
{
- sc.MustGetString ();
+ PROP_STRING_PARM(str, 0);
+ PROP_FIXED_PARM(id, 0);
+
+ if (bag.Info->DamageFactors == NULL) bag.Info->DamageFactors=new DmgFactors;
FName dmgType;
- if (sc.Compare("Normal")) dmgType = NAME_None;
- else dmgType=sc.String;
+ if (!stricmp(str, "Normal")) dmgType = NAME_None;
+ else dmgType=str;
- sc.MustGetToken(',');
- sc.MustGetFloat();
- bag.Info->SetDamageFactor(dmgType, FLOAT2FIXED(sc.Float));
+ (*bag.Info->DamageFactors)[dmgType]=id;
}
//==========================================================================
//
//==========================================================================
-static void ActorDecal (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(decal, S, Actor)
{
- sc.MustGetString();
- defaults->DecalGenerator = (FDecalBase *)intptr_t(int(FName(sc.String)));
+ PROP_STRING_PARM(str, 0);
+ defaults->DecalGenerator = (FDecalBase *)intptr_t(int(FName(str)));
}
//==========================================================================
//
//==========================================================================
-static void ActorMaxStepHeight (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(maxstepheight, F, Actor)
{
- sc.MustGetNumber ();
- defaults->MaxStepHeight=sc.Number * FRACUNIT;
+ PROP_FIXED_PARM(i, 0);
+ defaults->MaxStepHeight = i;
}
//==========================================================================
//
//==========================================================================
-static void ActorMaxDropoffHeight (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(maxdropoffheight, F, Actor)
{
- sc.MustGetNumber ();
- defaults->MaxDropOffHeight=sc.Number * FRACUNIT;
+ PROP_FIXED_PARM(i, 0);
+ defaults->MaxDropOffHeight = i;
}
//==========================================================================
//
//==========================================================================
-static void ActorPoisonDamage (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(poisondamage, I, Actor)
{
- sc.MustGetNumber();
- bag.Info->Class->Meta.SetMetaInt (AMETA_PoisonDamage, sc.Number);
+ PROP_INT_PARM(i, 0);
+ bag.Info->Class->Meta.SetMetaInt (AMETA_PoisonDamage, i);
}
//==========================================================================
//
//==========================================================================
-static void ActorFastSpeed (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(fastspeed, F, Actor)
{
- sc.MustGetFloat();
- bag.Info->Class->Meta.SetMetaFixed (AMETA_FastSpeed, fixed_t(sc.Float*FRACUNIT));
+ PROP_FIXED_PARM(i, 0);
+ bag.Info->Class->Meta.SetMetaFixed (AMETA_FastSpeed, i);
}
//==========================================================================
//
//==========================================================================
-static void ActorRadiusDamageFactor (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(radiusdamagefactor, F, Actor)
{
- sc.MustGetFloat();
- bag.Info->Class->Meta.SetMetaFixed (AMETA_RDFactor, fixed_t(sc.Float*FRACUNIT));
+ PROP_FIXED_PARM(i, 0);
+ bag.Info->Class->Meta.SetMetaFixed (AMETA_RDFactor, i);
}
//==========================================================================
//
//==========================================================================
-static void ActorCameraheight (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(cameraheight, F, Actor)
{
- sc.MustGetFloat();
- bag.Info->Class->Meta.SetMetaFixed (AMETA_CameraHeight, fixed_t(sc.Float*FRACUNIT));
+ PROP_FIXED_PARM(i, 0);
+ bag.Info->Class->Meta.SetMetaFixed (AMETA_CameraHeight, i);
}
//==========================================================================
//
//==========================================================================
-static void ActorVSpeed (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(vspeed, F, Actor)
{
- sc.MustGetFloat();
- defaults->momz = fixed_t(sc.Float*FRACUNIT);
+ PROP_FIXED_PARM(i, 0);
+ defaults->momz = i;
}
//==========================================================================
//
//==========================================================================
-static void ActorGravity (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(gravity, F, Actor)
{
- sc.MustGetFloat ();
+ PROP_FIXED_PARM(i, 0);
- if (sc.Float < 0.f)
- sc.ScriptError ("Gravity must not be negative.");
-
- defaults->gravity = FLOAT2FIXED (sc.Float);
-
- if (sc.Float == 0.f)
- defaults->flags |= MF_NOGRAVITY;
+ if (i < 0) I_Error ("Gravity must not be negative.");
+ defaults->gravity = i;
+ if (i == 0) defaults->flags |= MF_NOGRAVITY;
}
//==========================================================================
//
//==========================================================================
-static void ActorClearFlags (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(clearflags, 0, Actor)
{
defaults->flags=defaults->flags3=defaults->flags4=defaults->flags5=0;
defaults->flags2&=MF2_ARGSDEFINED; // this flag must not be cleared
@@ -1754,9 +1247,9 @@ static void ActorClearFlags (FScanner &sc, AActor *defaults, Baggage &bag)
//==========================================================================
//
//==========================================================================
-static void ActorMonster (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(monster, 0, Actor)
{
- // sets the standard flag for a monster
+ // sets the standard flags for a monster
defaults->flags|=MF_SHOOTABLE|MF_COUNTKILL|MF_SOLID;
defaults->flags2|=MF2_PUSHWALL|MF2_MCROSS|MF2_PASSMOBJ;
defaults->flags3|=MF3_ISMONSTER;
@@ -1766,7 +1259,7 @@ static void ActorMonster (FScanner &sc, AActor *defaults, Baggage &bag)
//==========================================================================
//
//==========================================================================
-static void ActorProjectile (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_PROPERTY(projectile, 0, Actor)
{
// sets the standard flags for a projectile
defaults->flags|=MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE;
@@ -1783,129 +1276,127 @@ static void ActorProjectile (FScanner &sc, AActor *defaults, Baggage &bag)
//==========================================================================
//
//==========================================================================
-static void AmmoBackpackAmount (FScanner &sc, AAmmo *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(backpackamount, I, Ammo)
{
- sc.MustGetNumber();
- defaults->BackpackAmount=sc.Number;
+ PROP_INT_PARM(i, 0);
+ defaults->BackpackAmount = i;
}
//==========================================================================
//
//==========================================================================
-static void AmmoBackpackMaxAmount (FScanner &sc, AAmmo *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(backpackmaxamount, I, Ammo)
{
- sc.MustGetNumber();
- defaults->BackpackMaxAmount=sc.Number;
+ PROP_INT_PARM(i, 0);
+ defaults->BackpackMaxAmount = i;
}
//==========================================================================
//
//==========================================================================
-static void AmmoDropAmount (FScanner &sc, AAmmo *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(dropamount, I, Ammo)
{
- sc.MustGetNumber();
- bag.Info->Class->Meta.SetMetaInt (AIMETA_DropAmount, sc.Number);
+ PROP_INT_PARM(i, 0);
+ bag.Info->Class->Meta.SetMetaInt (AIMETA_DropAmount, i);
}
//==========================================================================
//
//==========================================================================
-static void ArmorMaxSaveAmount (FScanner &sc, ABasicArmorBonus *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY_PREFIX(armor, maxsaveamount, I, BasicArmorBonus)
{
- sc.MustGetNumber();
- defaults->MaxSaveAmount = sc.Number;
+ PROP_INT_PARM(i, 0);
+ defaults->MaxSaveAmount = i;
}
//==========================================================================
//
//==========================================================================
-static void ArmorMaxBonus (FScanner &sc, ABasicArmorBonus *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY_PREFIX(armor, maxbonus, I, BasicArmorBonus)
{
- sc.MustGetNumber();
- defaults->BonusCount = sc.Number;
+ PROP_INT_PARM(i, 0);
+ defaults->BonusCount = i;
}
//==========================================================================
//
//==========================================================================
-static void ArmorMaxBonusMax (FScanner &sc, ABasicArmorBonus *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY_PREFIX(armor, maxbonusmax, I, BasicArmorBonus)
{
- sc.MustGetNumber();
- defaults->BonusMax = sc.Number;
+ PROP_INT_PARM(i, 0);
+ defaults->BonusMax = i;
}
//==========================================================================
//
//==========================================================================
-static void ArmorSaveAmount (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(saveamount, I, Armor)
{
- sc.MustGetNumber();
+ PROP_INT_PARM(i, 0);
+
// Special case here because this property has to work for 2 unrelated classes
if (bag.Info->Class->IsDescendantOf(RUNTIME_CLASS(ABasicArmorPickup)))
{
- ((ABasicArmorPickup*)defaults)->SaveAmount=sc.Number;
+ ((ABasicArmorPickup*)defaults)->SaveAmount=i;
}
else if (bag.Info->Class->IsDescendantOf(RUNTIME_CLASS(ABasicArmorBonus)))
{
- ((ABasicArmorBonus*)defaults)->SaveAmount=sc.Number;
+ ((ABasicArmorBonus*)defaults)->SaveAmount=i;
}
else
{
- sc.ScriptError("\"%s\" requires an actor of type \"Armor\"\n", sc.String);
+ I_Error("\"Armor.SaveAmount\" requires an actor of type \"Armor\"");
}
}
//==========================================================================
//
//==========================================================================
-static void ArmorSavePercent (FScanner &sc, AActor *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(savepercent, F, Armor)
{
- sc.MustGetFloat();
- if (sc.Float<0.0f) sc.Float=0.0f;
- if (sc.Float>100.0f) sc.Float=100.0f;
+ PROP_FIXED_PARM(i, 0);
+
+ i = clamp(i, 0, 100*FRACUNIT)/100;
// Special case here because this property has to work for 2 unrelated classes
if (bag.Info->Class->IsDescendantOf(RUNTIME_CLASS(ABasicArmorPickup)))
{
- ((ABasicArmorPickup*)defaults)->SavePercent=fixed_t(sc.Float*FRACUNIT/100.0f);
+ ((ABasicArmorPickup*)defaults)->SavePercent = i;
}
else if (bag.Info->Class->IsDescendantOf(RUNTIME_CLASS(ABasicArmorBonus)))
{
- ((ABasicArmorBonus*)defaults)->SavePercent=fixed_t(sc.Float*FRACUNIT/100.0f);
+ ((ABasicArmorBonus*)defaults)->SavePercent = i;
}
else
{
- sc.ScriptError("\"%s\" requires an actor of type \"Armor\"\n", sc.String);
+ I_Error("\"Armor.SavePercent\" requires an actor of type \"Armor\"\n");
}
}
//==========================================================================
//
//==========================================================================
-static void InventoryAmount (FScanner &sc, AInventory *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(amount, I, Inventory)
{
- sc.MustGetNumber();
- defaults->Amount=sc.Number;
+ PROP_INT_PARM(i, 0);
+ defaults->Amount = i;
}
//==========================================================================
//
//==========================================================================
-static void InventoryIcon (FScanner &sc, AInventory *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(icon, S, Inventory)
{
- sc.MustGetString();
- defaults->Icon = TexMan.AddPatch (sc.String);
+ PROP_STRING_PARM(i, 0);
+
+ defaults->Icon = TexMan.CheckForTexture(i, FTexture::TEX_MiscPatch);
if (!defaults->Icon.isValid())
{
- defaults->Icon = TexMan.AddPatch (sc.String, ns_sprites);
- if (!defaults->Icon.isValid())
+ // Don't print warnings if the item is for another game or if this is a shareware IWAD.
+ // Strife's teaser doesn't contain all the icon graphics of the full game.
+ if ((bag.Info->GameFilter == GAME_Any || bag.Info->GameFilter & gameinfo.gametype) &&
+ !(gameinfo.flags&GI_SHAREWARE) && Wads.GetLumpFile(bag.Lumpnum) != 0)
{
- // Don't print warnings if the item is for another game or if this is a shareware IWAD.
- // Strife's teaser doesn't contain all the icon graphics of the full game.
- if ((bag.Info->GameFilter == GAME_Any || bag.Info->GameFilter & gameinfo.gametype) &&
- !(gameinfo.flags&GI_SHAREWARE) && Wads.GetLumpFile(sc.LumpNum) != 0)
- {
- Printf("Icon '%s' for '%s' not found\n", sc.String, bag.Info->Class->TypeName.GetChars());
- }
+ Printf("Icon '%s' for '%s' not found\n", i, bag.Info->Class->TypeName.GetChars());
}
}
}
@@ -1913,16 +1404,16 @@ static void InventoryIcon (FScanner &sc, AInventory *defaults, Baggage &bag)
//==========================================================================
//
//==========================================================================
-static void InventoryMaxAmount (FScanner &sc, AInventory *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(maxamount, I, Inventory)
{
- sc.MustGetNumber();
- defaults->MaxAmount=sc.Number;
+ PROP_INT_PARM(i, 0);
+ defaults->MaxAmount = i;
}
//==========================================================================
//
//==========================================================================
-static void InventoryDefMaxAmount (FScanner &sc, AInventory *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(defmaxamount, 0, Inventory)
{
defaults->MaxAmount = gameinfo.gametype == GAME_Heretic ? 16 : 25;
}
@@ -1931,170 +1422,180 @@ static void InventoryDefMaxAmount (FScanner &sc, AInventory *defaults, Baggage &
//==========================================================================
//
//==========================================================================
-static void InventoryPickupflash (FScanner &sc, AInventory *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(pickupflash, S, Inventory)
{
- sc.MustGetString();
- defaults->PickupFlash = fuglyname(sc.String);
+ PROP_STRING_PARM(str, 0);
+ defaults->PickupFlash = fuglyname(str);
}
//==========================================================================
//
//==========================================================================
-static void InventoryPickupmsg (FScanner &sc, AInventory *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(pickupmessage, S, Inventory)
{
- // allow game specific pickup messages
- const char * games[] = {"Doom", "Heretic", "Hexen", "Raven", "Strife", "Chex", NULL};
- int gamemode[]={GAME_Doom, GAME_Heretic, GAME_Hexen, GAME_Raven, GAME_Strife, GAME_Chex};
-
- sc.MustGetString();
- int game = sc.MatchString(games);
-
- if (game!=-1 && sc.CheckString(","))
- {
- sc.MustGetString();
- if (!(gameinfo.gametype&gamemode[game])) return;
- }
- bag.Info->Class->Meta.SetMetaString(AIMETA_PickupMessage, sc.String);
+ PROP_STRING_PARM(str, 0);
+ bag.Info->Class->Meta.SetMetaString(AIMETA_PickupMessage, str);
}
//==========================================================================
//
//==========================================================================
-static void InventoryPickupsound (FScanner &sc, AInventory *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(pickupsound, S, Inventory)
{
- sc.MustGetString();
- defaults->PickupSound = sc.String;
+ PROP_STRING_PARM(str, 0);
+ defaults->PickupSound = str;
}
//==========================================================================
//
//==========================================================================
-static void InventoryRespawntics (FScanner &sc, AInventory *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(respawntics, I, Inventory)
{
- sc.MustGetNumber();
- defaults->RespawnTics=sc.Number;
+ PROP_INT_PARM(i, 0);
+ defaults->RespawnTics = i;
}
//==========================================================================
//
//==========================================================================
-static void InventoryUsesound (FScanner &sc, AInventory *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(usesound, S, Inventory)
{
- sc.MustGetString();
- defaults->UseSound = sc.String;
+ PROP_STRING_PARM(str, 0);
+ defaults->UseSound = str;
}
//==========================================================================
//
//==========================================================================
-static void InventoryGiveQuest (FScanner &sc, AInventory *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(givequest, I, Inventory)
{
- sc.MustGetNumber();
- bag.Info->Class->Meta.SetMetaInt(AIMETA_GiveQuest, sc.Number);
+ PROP_INT_PARM(i, 0);
+ bag.Info->Class->Meta.SetMetaInt(AIMETA_GiveQuest, i);
}
//==========================================================================
//
//==========================================================================
-static void HealthLowMessage (FScanner &sc, AHealth *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(lowmessage, IS, Health)
{
- sc.MustGetNumber();
- bag.Info->Class->Meta.SetMetaInt(AIMETA_LowHealth, sc.Number);
- sc.MustGetStringName(",");
- sc.MustGetString();
- bag.Info->Class->Meta.SetMetaString(AIMETA_LowHealthMessage, sc.String);
+ PROP_INT_PARM(i, 0);
+ PROP_STRING_PARM(str, 1);
+ bag.Info->Class->Meta.SetMetaInt(AIMETA_LowHealth, i);
+ bag.Info->Class->Meta.SetMetaString(AIMETA_LowHealthMessage, str);
}
//==========================================================================
//
//==========================================================================
-static void PuzzleitemNumber (FScanner &sc, APuzzleItem *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(number, I, PuzzleItem)
{
- sc.MustGetNumber();
- defaults->PuzzleItemNumber=sc.Number;
+ PROP_INT_PARM(i, 0);
+ defaults->PuzzleItemNumber = i;
}
//==========================================================================
//
//==========================================================================
-static void PuzzleitemFailMsg (FScanner &sc, APuzzleItem *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(failmessage, S, PuzzleItem)
{
- sc.MustGetString();
- bag.Info->Class->Meta.SetMetaString(AIMETA_PuzzFailMessage, sc.String);
+ PROP_STRING_PARM(str, 0);
+ bag.Info->Class->Meta.SetMetaString(AIMETA_PuzzFailMessage, str);
}
//==========================================================================
//
//==========================================================================
-static void WeaponAmmoGive1 (FScanner &sc, AWeapon *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(ammogive, I, Weapon)
{
- sc.MustGetNumber();
- defaults->AmmoGive1=sc.Number;
+ PROP_INT_PARM(i, 0);
+ defaults->AmmoGive1 = i;
}
//==========================================================================
//
//==========================================================================
-static void WeaponAmmoGive2 (FScanner &sc, AWeapon *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(ammogive1, I, Weapon)
{
- sc.MustGetNumber();
- defaults->AmmoGive2=sc.Number;
-}
-
-//==========================================================================
-//
-// Passing these parameters is really tricky to allow proper inheritance
-// and forward declarations. Here only a name is
-// stored which must be resolved after everything has been declared
-//
-//==========================================================================
-
-static void WeaponAmmoType1 (FScanner &sc, AWeapon *defaults, Baggage &bag)
-{
- sc.MustGetString();
- defaults->AmmoType1 = fuglyname(sc.String);
+ PROP_INT_PARM(i, 0);
+ defaults->AmmoGive1 = i;
}
//==========================================================================
//
//==========================================================================
-static void WeaponAmmoType2 (FScanner &sc, AWeapon *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(ammogive2, I, Weapon)
{
- sc.MustGetString();
- defaults->AmmoType2 = fuglyname(sc.String);
+ PROP_INT_PARM(i, 0);
+ defaults->AmmoGive2 = 2;
}
//==========================================================================
//
//==========================================================================
-static void WeaponAmmoUse1 (FScanner &sc, AWeapon *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(ammotype, S, Weapon)
{
- sc.MustGetNumber();
- defaults->AmmoUse1=sc.Number;
+ PROP_STRING_PARM(str, 0);
+ defaults->AmmoType1 = fuglyname(str);
}
//==========================================================================
//
//==========================================================================
-static void WeaponAmmoUse2 (FScanner &sc, AWeapon *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(ammotype1, S, Weapon)
{
- sc.MustGetNumber();
- defaults->AmmoUse2=sc.Number;
+ PROP_STRING_PARM(str, 0);
+ defaults->AmmoType1 = fuglyname(str);
}
//==========================================================================
//
//==========================================================================
-static void WeaponKickback (FScanner &sc, AWeapon *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(ammotype2, S, Weapon)
{
- sc.MustGetNumber();
- defaults->Kickback=sc.Number;
+ PROP_STRING_PARM(str, 0);
+ defaults->AmmoType2 = fuglyname(str);
}
//==========================================================================
//
//==========================================================================
-static void WeaponDefKickback (FScanner &sc, AWeapon *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(ammouse, I, Weapon)
+{
+ PROP_INT_PARM(i, 0);
+ defaults->AmmoUse1 = i;
+}
+
+//==========================================================================
+//
+//==========================================================================
+DEFINE_CLASS_PROPERTY(ammouse1, I, Weapon)
+{
+ PROP_INT_PARM(i, 0);
+ defaults->AmmoUse1 = i;
+}
+
+//==========================================================================
+//
+//==========================================================================
+DEFINE_CLASS_PROPERTY(ammouse2, I, Weapon)
+{
+ PROP_INT_PARM(i, 0);
+ defaults->AmmoUse2 = i;
+}
+
+//==========================================================================
+//
+//==========================================================================
+DEFINE_CLASS_PROPERTY(kickback, I, Weapon)
+{
+ PROP_INT_PARM(i, 0);
+ defaults->Kickback = i;
+}
+
+//==========================================================================
+//
+//==========================================================================
+DEFINE_CLASS_PROPERTY(defaultkickback, 0, Weapon)
{
defaults->Kickback = gameinfo.defKickback;
}
@@ -2102,74 +1603,73 @@ static void WeaponDefKickback (FScanner &sc, AWeapon *defaults, Baggage &bag)
//==========================================================================
//
//==========================================================================
-static void WeaponReadySound (FScanner &sc, AWeapon *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(readysound, S, Weapon)
{
- sc.MustGetString();
- defaults->ReadySound = sc.String;
+ PROP_STRING_PARM(str, 0);
+ defaults->ReadySound = str;
}
//==========================================================================
//
//==========================================================================
-static void WeaponSelectionOrder (FScanner &sc, AWeapon *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(selectionorder, I, Weapon)
{
- sc.MustGetNumber();
- defaults->SelectionOrder=sc.Number;
+ PROP_INT_PARM(i, 0);
+ defaults->SelectionOrder = i;
}
//==========================================================================
//
//==========================================================================
-static void WeaponSisterWeapon (FScanner &sc, AWeapon *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(sisterweapon, S, Weapon)
{
- sc.MustGetString();
- defaults->SisterWeaponType=fuglyname(sc.String);
+ PROP_STRING_PARM(str, 0);
+ defaults->SisterWeaponType = fuglyname(str);
}
//==========================================================================
//
//==========================================================================
-static void WeaponUpSound (FScanner &sc, AWeapon *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(upsound, S, Weapon)
{
- sc.MustGetString();
- defaults->UpSound = sc.String;
+ PROP_STRING_PARM(str, 0);
+ defaults->UpSound = str;
}
//==========================================================================
//
//==========================================================================
-static void WeaponYAdjust (FScanner &sc, AWeapon *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(yadjust, F, Weapon)
{
- sc.MustGetFloat();
- defaults->YAdjust=fixed_t(sc.Float * FRACUNIT);
+ PROP_FIXED_PARM(i, 0);
+ defaults->YAdjust = i;
}
//==========================================================================
//
//==========================================================================
-static void WPieceValue (FScanner &sc, AWeaponPiece *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(number, I, WeaponPiece)
{
- sc.MustGetNumber();
- defaults->PieceValue = 1 << (sc.Number-1);
+ PROP_INT_PARM(i, 0);
+ defaults->PieceValue = 1 << (i-1);
}
//==========================================================================
//
//==========================================================================
-static void WPieceWeapon (FScanner &sc, AWeaponPiece *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(weapon, S, WeaponPiece)
{
- sc.MustGetString();
- defaults->WeaponClass = fuglyname(sc.String);
+ PROP_STRING_PARM(str, 0);
+ defaults->WeaponClass = fuglyname(str);
}
//==========================================================================
//
//==========================================================================
-static void PowerupColor (FScanner &sc, APowerupGiver *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY_PREFIX(powerup, color, C_f, Inventory)
{
- int r;
- int g;
- int b;
+ PROP_INT_PARM(i, 0);
+
int alpha;
PalEntry * pBlendColor;
@@ -2183,67 +1683,60 @@ static void PowerupColor (FScanner &sc, APowerupGiver *defaults, Baggage &bag)
}
else
{
- sc.ScriptError("\"%s\" requires an actor of type \"Powerup\"\n", sc.String);
+ I_Error("\"powerup.color\" requires an actor of type \"Powerup\"\n");
return;
}
- if (sc.CheckNumber())
- {
- r=clamp(sc.Number, 0, 255);
- sc.CheckString(",");
- sc.MustGetNumber();
- g=clamp(sc.Number, 0, 255);
- sc.CheckString(",");
- sc.MustGetNumber();
- b=clamp(sc.Number, 0, 255);
- }
- else
- {
- sc.MustGetString();
+ PROP_INT_PARM(mode, 0);
+ PROP_INT_PARM(color, 1);
- if (sc.Compare("INVERSEMAP"))
+ if (mode == 1)
+ {
+ PROP_STRING_PARM(name, 1);
+
+ if (!stricmp(name, "INVERSEMAP"))
{
- defaults->BlendColor = INVERSECOLOR;
+ *pBlendColor = INVERSECOLOR;
return;
}
- else if (sc.Compare("GOLDMAP"))
+ else if (!stricmp(name, "GOLDMAP"))
{
- defaults->BlendColor = GOLDCOLOR;
+ *pBlendColor = GOLDCOLOR;
return;
}
// [BC] Yay, more hacks.
- else if ( sc.Compare( "REDMAP" ))
+ else if (!stricmp(name, "REDMAP" ))
{
- defaults->BlendColor = REDCOLOR;
+ *pBlendColor = REDCOLOR;
return;
}
- else if ( sc.Compare( "GREENMAP" ))
+ else if (!stricmp(name, "GREENMAP" ))
{
- defaults->BlendColor = GREENCOLOR;
+ *pBlendColor = GREENCOLOR;
return;
}
- int c = V_GetColor(NULL, sc.String);
- r=RPART(c);
- g=GPART(c);
- b=BPART(c);
+ color = V_GetColor(NULL, name);
}
- sc.CheckString(",");
- sc.MustGetFloat();
- alpha=int(sc.Float*255);
+ else if (PROP_PARM_COUNT > 1)
+ {
+ PROP_FLOAT_PARM(falpha, 2);
+ alpha=int(falpha*255);
+ }
+ else alpha = 255/3;
+
alpha=clamp(alpha, 0, 255);
- if (alpha!=0) *pBlendColor = MAKEARGB(alpha, r, g, b);
+ if (alpha!=0) *pBlendColor = MAKEARGB(alpha, 0, 0, 0) | color;
else *pBlendColor = 0;
}
//==========================================================================
//
//==========================================================================
-static void PowerupDuration (FScanner &sc, APowerupGiver *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY_PREFIX(powerup, duration, I, Inventory)
{
int *pEffectTics;
-
if (bag.Info->Class->IsDescendantOf(RUNTIME_CLASS(APowerup)))
{
pEffectTics = &((APowerup*)defaults)->EffectTics;
@@ -2254,30 +1747,30 @@ static void PowerupDuration (FScanner &sc, APowerupGiver *defaults, Baggage &bag
}
else
{
- sc.ScriptError("\"%s\" requires an actor of type \"Powerup\"\n", sc.String);
+ I_Error("\"powerup.color\" requires an actor of type \"Powerup\"\n");
return;
}
- sc.MustGetNumber();
- *pEffectTics = (sc.Number >= 0) ? sc.Number : -sc.Number * TICRATE;
+ PROP_INT_PARM(i, 0);
+ *pEffectTics = (i >= 0) ? i : -i * TICRATE;
}
//==========================================================================
//
//==========================================================================
-static void PowerupMode (FScanner &sc, APowerupGiver *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY_PREFIX(powerup, mode, S, PowerupGiver)
{
- sc.MustGetString();
- defaults->mode = (FName)sc.String;
+ PROP_STRING_PARM(str, 0);
+ defaults->mode = (FName)str;
}
//==========================================================================
//
//==========================================================================
-static void PowerupType (FScanner &sc, APowerupGiver *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY_PREFIX(powerup, type, S, PowerupGiver)
{
- sc.MustGetString();
- defaults->PowerupType = fuglyname(sc.String);
+ PROP_STRING_PARM(str, 0);
+ defaults->PowerupType = fuglyname(str);
}
//==========================================================================
@@ -2289,21 +1782,20 @@ static void PowerupType (FScanner &sc, APowerupGiver *defaults, Baggage &bag)
//==========================================================================
//
//==========================================================================
-static void PlayerDisplayName (FScanner &sc, APlayerPawn *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY_PREFIX(player, displayname, S, PlayerPawn)
{
- sc.MustGetString ();
- bag.Info->Class->Meta.SetMetaString (APMETA_DisplayName, sc.String);
+ PROP_STRING_PARM(str, 0);
+ bag.Info->Class->Meta.SetMetaString (APMETA_DisplayName, str);
}
//==========================================================================
//
//==========================================================================
-static void PlayerSoundClass (FScanner &sc, APlayerPawn *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY_PREFIX(player, soundclass, S, PlayerPawn)
{
- FString tmp;
+ PROP_STRING_PARM(str, 0);
- sc.MustGetString ();
- tmp = sc.String;
+ FString tmp = str;
tmp.ReplaceChars (' ', '_');
bag.Info->Class->Meta.SetMetaString (APMETA_SoundClass, tmp);
}
@@ -2311,19 +1803,18 @@ static void PlayerSoundClass (FScanner &sc, APlayerPawn *defaults, Baggage &bag)
//==========================================================================
//
//==========================================================================
-static void PlayerFace (FScanner &sc, APlayerPawn *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY_PREFIX(player, face, S, PlayerPawn)
{
- FString tmp;
+ PROP_STRING_PARM(str, 0);
+ FString tmp = str;
- sc.MustGetString ();
- tmp = sc.String;
+ tmp.ToUpper();
if (tmp.Len() != 3)
{
Printf("Invalid face '%s' for '%s';\nSTF replacement codes must be 3 characters.\n",
- sc.String, bag.Info->Class->TypeName.GetChars ());
+ tmp.GetChars(), bag.Info->Class->TypeName.GetChars ());
}
- tmp.ToUpper();
bool valid = (
(((tmp[0] >= 'A') && (tmp[0] <= 'Z')) || ((tmp[0] >= '0') && (tmp[0] <= '9'))) &&
(((tmp[1] >= 'A') && (tmp[1] <= 'Z')) || ((tmp[1] >= '0') && (tmp[1] <= '9'))) &&
@@ -2332,7 +1823,7 @@ static void PlayerFace (FScanner &sc, APlayerPawn *defaults, Baggage &bag)
if (!valid)
{
Printf("Invalid face '%s' for '%s';\nSTF replacement codes must be alphanumeric.\n",
- sc.String, bag.Info->Class->TypeName.GetChars ());
+ tmp.GetChars(), bag.Info->Class->TypeName.GetChars ());
}
bag.Info->Class->Meta.SetMetaString (APMETA_Face, tmp);
@@ -2341,15 +1832,10 @@ static void PlayerFace (FScanner &sc, APlayerPawn *defaults, Baggage &bag)
//==========================================================================
//
//==========================================================================
-static void PlayerColorRange (FScanner &sc, APlayerPawn *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY_PREFIX(player, colorrange, I_I, PlayerPawn)
{
- int start, end;
-
- sc.MustGetNumber ();
- start = sc.Number;
- sc.CheckString(",");
- sc.MustGetNumber ();
- end = sc.Number;
+ PROP_INT_PARM(start, 0);
+ PROP_INT_PARM(end, 0);
if (start > end)
swap (start, end);
@@ -2360,113 +1846,48 @@ static void PlayerColorRange (FScanner &sc, APlayerPawn *defaults, Baggage &bag)
//==========================================================================
//
//==========================================================================
-static void PlayerAttackZOffset (FScanner &sc, APlayerPawn *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY_PREFIX(player, attackzoffset, F, PlayerPawn)
{
- sc.MustGetFloat ();
- defaults->AttackZOffset = FLOAT2FIXED (sc.Float);
+ PROP_FIXED_PARM(z, 0);
+ defaults->AttackZOffset = z;
}
//==========================================================================
//
//==========================================================================
-static void PlayerJumpZ (FScanner &sc, APlayerPawn *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY_PREFIX(player, jumpz, F, PlayerPawn)
{
- sc.MustGetFloat ();
- defaults->JumpZ = FLOAT2FIXED (sc.Float);
+ PROP_FIXED_PARM(z, 0);
+ defaults->JumpZ = z;
}
//==========================================================================
//
//==========================================================================
-static void PlayerSpawnClass (FScanner &sc, APlayerPawn *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY_PREFIX(player, spawnclass, L, PlayerPawn)
{
- sc.MustGetString ();
- if (sc.Compare ("Any"))
- defaults->SpawnMask = 0;
- else if (sc.Compare ("Fighter"))
- defaults->SpawnMask |= 1;
- else if (sc.Compare ("Cleric"))
- defaults->SpawnMask |= 2;
- else if (sc.Compare ("Mage"))
- defaults->SpawnMask |= 4;
- else if (IsNum(sc.String))
+ PROP_INT_PARM(type, 0);
+
+ if (type == 0)
{
- int val = strtol(sc.String, NULL, 0);
+ PROP_INT_PARM(val, 1);
if (val > 0) defaults->SpawnMask |= 1<<(val-1);
}
-}
-
-//==========================================================================
-//
-//==========================================================================
-static void PlayerViewHeight (FScanner &sc, APlayerPawn *defaults, Baggage &bag)
-{
- sc.MustGetFloat ();
- defaults->ViewHeight = FLOAT2FIXED (sc.Float);
-}
-
-//==========================================================================
-//
-//==========================================================================
-static void PlayerForwardMove (FScanner &sc, APlayerPawn *defaults, Baggage &bag)
-{
- sc.MustGetFloat ();
- defaults->ForwardMove1 = defaults->ForwardMove2 = FLOAT2FIXED (sc.Float);
- if (CheckFloatParm (sc))
- defaults->ForwardMove2 = FLOAT2FIXED (sc.Float);
-}
-
-//==========================================================================
-//
-//==========================================================================
-static void PlayerSideMove (FScanner &sc, APlayerPawn *defaults, Baggage &bag)
-{
- sc.MustGetFloat ();
- defaults->SideMove1 = defaults->SideMove2 = FLOAT2FIXED (sc.Float);
- if (CheckFloatParm (sc))
- defaults->SideMove2 = FLOAT2FIXED (sc.Float);
-}
-
-//==========================================================================
-//
-//==========================================================================
-static void PlayerMaxHealth (FScanner &sc, APlayerPawn *defaults, Baggage &bag)
-{
- sc.MustGetNumber ();
- defaults->MaxHealth = sc.Number;
-}
-
-//==========================================================================
-//
-//==========================================================================
-static void PlayerRunHealth (FScanner &sc, APlayerPawn *defaults, Baggage &bag)
-{
- sc.MustGetNumber ();
- defaults->RunHealth = sc.Number;
-}
-
-//==========================================================================
-//
-//==========================================================================
-static void PlayerMorphWeapon (FScanner &sc, APlayerPawn *defaults, Baggage &bag)
-{
- sc.MustGetString ();
- defaults->MorphWeapon = FName(sc.String);
-}
-
-//==========================================================================
-//
-//==========================================================================
-static void PlayerScoreIcon (FScanner &sc, APlayerPawn *defaults, Baggage &bag)
-{
- sc.MustGetString ();
- defaults->ScoreIcon = TexMan.AddPatch (sc.String);
- if (!defaults->ScoreIcon.isValid())
+ else
{
- defaults->ScoreIcon = TexMan.AddPatch (sc.String, ns_sprites);
- if (!defaults->ScoreIcon.isValid())
+ for(int i=1; iClass->TypeName.GetChars ());
+ PROP_STRING_PARM(str, i);
+
+ if (!stricmp(str, "Any"))
+ defaults->SpawnMask = 0;
+ else if (!stricmp(str, "Fighter"))
+ defaults->SpawnMask |= 1;
+ else if (!stricmp(str, "Cleric"))
+ defaults->SpawnMask |= 2;
+ else if (!stricmp(str, "Mage"))
+ defaults->SpawnMask |= 4;
+
}
}
}
@@ -2474,50 +1895,110 @@ static void PlayerScoreIcon (FScanner &sc, APlayerPawn *defaults, Baggage &bag)
//==========================================================================
//
//==========================================================================
-static void PlayerCrouchSprite (FScanner &sc, APlayerPawn *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY_PREFIX(player, viewheight, F, PlayerPawn)
{
- sc.MustGetString ();
- for (int i = 0; i < sc.StringLen; i++)
- {
- sc.String[i] = toupper (sc.String[i]);
- }
- defaults->crouchsprite = GetSpriteIndex (sc.String);
+ PROP_FIXED_PARM(z, 0);
+ defaults->ViewHeight = z;
}
//==========================================================================
//
//==========================================================================
-static void PlayerDmgScreenColor (FScanner &sc, APlayerPawn *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY_PREFIX(player, forwardmove, F_f, PlayerPawn)
{
- if (sc.CheckNumber ())
+ PROP_FIXED_PARM(m, 0);
+ defaults->ForwardMove1 = defaults->ForwardMove2 = m;
+ if (PROP_PARM_COUNT > 1)
{
- sc.MustGetNumber ();
- defaults->RedDamageFade = clamp (sc.Number, 0, 255);
- sc.CheckString (",");
- sc.MustGetNumber ();
- defaults->GreenDamageFade = clamp (sc.Number, 0, 255);
- sc.CheckString (",");
- sc.MustGetNumber ();
- defaults->BlueDamageFade = clamp (sc.Number, 0, 255);
+ PROP_FIXED_PARM(m2, 1);
+ defaults->ForwardMove2 = m2;
}
- else
+}
+
+//==========================================================================
+//
+//==========================================================================
+DEFINE_CLASS_PROPERTY_PREFIX(player, sidemove, F_f, PlayerPawn)
+{
+ PROP_FIXED_PARM(m, 0);
+ defaults->SideMove1 = defaults->SideMove2 = m;
+ if (PROP_PARM_COUNT > 1)
{
- sc.MustGetString ();
- int c = V_GetColor (NULL, sc.String);
- defaults->RedDamageFade = RPART (c);
- defaults->GreenDamageFade = GPART (c);
- defaults->BlueDamageFade = BPART (c);
+ PROP_FIXED_PARM(m2, 1);
+ defaults->SideMove2 = m2;
}
}
+//==========================================================================
+//
+//==========================================================================
+DEFINE_CLASS_PROPERTY_PREFIX(player, maxhealth, I, PlayerPawn)
+{
+ PROP_INT_PARM(z, 0);
+ defaults->MaxHealth = z;
+}
+
+//==========================================================================
+//
+//==========================================================================
+DEFINE_CLASS_PROPERTY_PREFIX(player, runhealth, I, PlayerPawn)
+{
+ PROP_INT_PARM(z, 0);
+ defaults->RunHealth = z;
+}
+
+//==========================================================================
+//
+//==========================================================================
+DEFINE_CLASS_PROPERTY_PREFIX(player, morphweapon, S, PlayerPawn)
+{
+ PROP_STRING_PARM(z, 0);
+ defaults->MorphWeapon = FName(z);
+}
+
+//==========================================================================
+//
+//==========================================================================
+DEFINE_CLASS_PROPERTY_PREFIX(player, scoreicon, S, PlayerPawn)
+{
+ PROP_STRING_PARM(z, 0);
+ defaults->ScoreIcon = TexMan.CheckForTexture(z, FTexture::TEX_MiscPatch);
+ if (!defaults->ScoreIcon.isValid())
+ {
+ Printf("Icon '%s' for '%s' not found\n", z, bag.Info->Class->TypeName.GetChars ());
+ }
+}
+
+//==========================================================================
+//
+//==========================================================================
+DEFINE_CLASS_PROPERTY_PREFIX(player, crouchsprite, S, PlayerPawn)
+{
+ PROP_STRING_PARM(z, 0);
+ defaults->crouchsprite = GetSpriteIndex (z);
+}
+
+//==========================================================================
+//
+//==========================================================================
+DEFINE_CLASS_PROPERTY_PREFIX(player, damagescreencolor, C, PlayerPawn)
+{
+ PROP_COLOR_PARM(c, 0);
+ defaults->RedDamageFade = RPART (c);
+ defaults->GreenDamageFade = GPART (c);
+ defaults->BlueDamageFade = BPART (c);
+}
+
//==========================================================================
//
// [GRB] Store start items in drop item list
//
//==========================================================================
-static void PlayerStartItem (FScanner &sc, APlayerPawn *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY_PREFIX(player, startitem, S_i, PlayerPawn)
{
- // create a linked list of dropitems
+ PROP_STRING_PARM(str, 0);
+
+ // create a linked list of startitems
if (!bag.DropItemSet)
{
bag.DropItemSet = true;
@@ -2526,13 +2007,13 @@ static void PlayerStartItem (FScanner &sc, APlayerPawn *defaults, Baggage &bag)
FDropItem * di=new FDropItem;
- sc.MustGetString();
- di->Name = sc.String;
+ di->Name = str;
di->probability = 255;
di->amount = 1;
- if (CheckNumParm(sc))
+ if (PROP_PARM_COUNT > 1)
{
- di->amount = sc.Number;
+ PROP_INT_PARM(amt, 1);
+ di->amount = amt;
}
di->Next = bag.DropItemList;
bag.DropItemList = di;
@@ -2541,136 +2022,162 @@ static void PlayerStartItem (FScanner &sc, APlayerPawn *defaults, Baggage &bag)
//==========================================================================
//
//==========================================================================
-static void PlayerInvulMode (FScanner &sc, APlayerPawn *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY_PREFIX(player, invulnerabilitymode, S, PlayerPawn)
{
- sc.MustGetString ();
- bag.Info->Class->Meta.SetMetaInt (APMETA_InvulMode, (FName)sc.String);
+ PROP_STRING_PARM(str, 0);
+ bag.Info->Class->Meta.SetMetaInt (APMETA_InvulMode, (FName)str);
}
//==========================================================================
//
//==========================================================================
-static void PlayerHealRadius (FScanner &sc, APlayerPawn *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY_PREFIX(player, healradiustype, S, PlayerPawn)
{
- sc.MustGetString ();
- bag.Info->Class->Meta.SetMetaInt (APMETA_HealingRadius, (FName)sc.String);
+ PROP_STRING_PARM(str, 0);
+ bag.Info->Class->Meta.SetMetaInt (APMETA_HealingRadius, (FName)str);
}
//==========================================================================
//
//==========================================================================
-static void PlayerHexenArmor (FScanner &sc, APlayerPawn *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY_PREFIX(player, hexenarmor, FFFFF, PlayerPawn)
{
for (int i=0;i<5;i++)
{
- sc.MustGetFloat ();
- bag.Info->Class->Meta.SetMetaFixed (APMETA_Hexenarmor0+i, FLOAT2FIXED (sc.Float));
- if (i!=4) sc.MustGetStringName(",");
+ PROP_FIXED_PARM(val, i);
+ bag.Info->Class->Meta.SetMetaFixed (APMETA_Hexenarmor0+i, val);
}
}
//==========================================================================
//
//==========================================================================
-static void EggFXPlayerClass (FScanner &sc, AMorphProjectile *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(playerclass, S, MorphProjectile)
{
- sc.MustGetString ();
- defaults->PlayerClass = FName(sc.String);
+ PROP_STRING_PARM(str, 0);
+ defaults->PlayerClass = FName(str);
}
//==========================================================================
//
//==========================================================================
-static void EggFXMonsterClass (FScanner &sc, AMorphProjectile *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(monsterclass, S, MorphProjectile)
{
- sc.MustGetString ();
- defaults->MonsterClass = FName(sc.String);
+ PROP_STRING_PARM(str, 0);
+ defaults->MonsterClass = FName(str);
}
//==========================================================================
//
//==========================================================================
-static void EggFXDuration (FScanner &sc, AMorphProjectile *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(duration, I, MorphProjectile)
{
- sc.MustGetNumber ();
- defaults->Duration = sc.Number;
+ PROP_INT_PARM(i, 0);
+ defaults->Duration = i >= 0 ? i : -i*TICRATE;
}
//==========================================================================
//
//==========================================================================
-static void EggFXMorphStyle (FScanner &sc, AMorphProjectile *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(morphstyle, M, MorphProjectile)
{
- defaults->MorphStyle = ParseMorphStyle(sc);
+ PROP_INT_PARM(i, 0);
+ defaults->MorphStyle = i;
}
//==========================================================================
//
//==========================================================================
-static void EggFXMorphFlash (FScanner &sc, AMorphProjectile *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(morphflash, S, MorphProjectile)
{
- sc.MustGetString ();
- defaults->MorphFlash = FName(sc.String);
+ PROP_STRING_PARM(str, 0);
+ defaults->MorphFlash = FName(str);
}
//==========================================================================
//
//==========================================================================
-static void EggFXUnMorphFlash (FScanner &sc, AMorphProjectile *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(unmorphflash, S, MorphProjectile)
{
- sc.MustGetString ();
- defaults->UnMorphFlash = FName(sc.String);
+ PROP_STRING_PARM(str, 0);
+ defaults->UnMorphFlash = FName(str);
}
//==========================================================================
//
//==========================================================================
-static void PowerMorphPlayerClass (FScanner &sc, APowerMorph *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(playerclass, S, PowerMorph)
{
- sc.MustGetString ();
- defaults->PlayerClass = FName(sc.String);
+ PROP_STRING_PARM(str, 0);
+ defaults->PlayerClass = FName(str);
}
//==========================================================================
//
//==========================================================================
-static void PowerMorphMorphStyle (FScanner &sc, APowerMorph *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(morphstyle, M, PowerMorph)
{
- defaults->MorphStyle = ParseMorphStyle(sc);
+ PROP_INT_PARM(i, 0);
+ defaults->MorphStyle = i;
}
//==========================================================================
//
//==========================================================================
-static void PowerMorphMorphFlash (FScanner &sc, APowerMorph *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(morphflash, S, PowerMorph)
{
- sc.MustGetString ();
- defaults->MorphFlash = FName(sc.String);
+ PROP_STRING_PARM(str, 0);
+ defaults->MorphFlash = FName(str);
}
//==========================================================================
//
//==========================================================================
-static void PowerMorphUnMorphFlash (FScanner &sc, APowerMorph *defaults, Baggage &bag)
+DEFINE_CLASS_PROPERTY(unmorphflash, S, PowerMorph)
{
- sc.MustGetString ();
- defaults->UnMorphFlash = FName(sc.String);
+ PROP_STRING_PARM(str, 0);
+ defaults->UnMorphFlash = FName(str);
}
+
//==========================================================================
//
+// Find a property by name using a binary search
+//
//==========================================================================
-static const ActorProps *APropSearch (const char *str, const ActorProps *props, int numprops)
+static int STACK_ARGS propcmp(const void * a, const void * b)
{
- int min = 0, max = numprops - 1;
+ return stricmp( (*(FPropertyInfo**)a)->name, (*(FPropertyInfo**)b)->name);
+}
+
+static TArray properties;
+
+FPropertyInfo *FindProperty(const char * string)
+{
+ static bool propsorted=false;
+
+ if (!propsorted)
+ {
+ TAutoSegIterator probe;
+
+ while (++probe != NULL)
+ {
+ properties.Push(probe);
+ }
+ properties.ShrinkToFit();
+ qsort(&properties[0], properties.Size(), sizeof(properties[0]), propcmp);
+ propsorted=true;
+ }
+
+ int min = 0, max = properties.Size()-1;
while (min <= max)
{
int mid = (min + max) / 2;
- int lexval = strcmp (str, props[mid].name);
+ int lexval = stricmp (string, properties[mid]->name);
if (lexval == 0)
{
- return &props[mid];
+ return properties[mid];
}
else if (lexval > 0)
{
@@ -2683,250 +2190,3 @@ static const ActorProps *APropSearch (const char *str, const ActorProps *props,
}
return NULL;
}
-
-//==========================================================================
-//
-// all actor properties
-//
-//==========================================================================
-#define apf ActorPropFunction
-static const ActorProps props[] =
-{
- { "activesound", ActorActiveSound, RUNTIME_CLASS(AActor) },
- { "alpha", ActorAlpha, RUNTIME_CLASS(AActor) },
- { "ammo.backpackamount", (apf)AmmoBackpackAmount, RUNTIME_CLASS(AAmmo) },
- { "ammo.backpackmaxamount", (apf)AmmoBackpackMaxAmount, RUNTIME_CLASS(AAmmo) },
- { "ammo.dropamount", (apf)AmmoDropAmount, RUNTIME_CLASS(AAmmo) },
- { "args", ActorArgs, RUNTIME_CLASS(AActor) },
- { "armor.maxbonus", (apf)ArmorMaxBonus, RUNTIME_CLASS(ABasicArmorBonus) },
- { "armor.maxbonusmax", (apf)ArmorMaxBonusMax, RUNTIME_CLASS(ABasicArmorBonus) },
- { "armor.maxsaveamount", (apf)ArmorMaxSaveAmount, RUNTIME_CLASS(ABasicArmorBonus) },
- { "armor.saveamount", (apf)ArmorSaveAmount, RUNTIME_CLASS(AActor) },
- { "armor.savepercent", (apf)ArmorSavePercent, RUNTIME_CLASS(AActor) },
- { "attacksound", ActorAttackSound, RUNTIME_CLASS(AActor) },
- { "bloodcolor", ActorBloodColor, RUNTIME_CLASS(AActor) },
- { "bloodtype", ActorBloodType, RUNTIME_CLASS(AActor) },
- { "bouncecount", ActorBounceCount, RUNTIME_CLASS(AActor) },
- { "bouncefactor", ActorBounceFactor, RUNTIME_CLASS(AActor) },
- { "burn", ActorBurnState, RUNTIME_CLASS(AActor) },
- { "burnheight", ActorBurnHeight, RUNTIME_CLASS(AActor) },
- { "cameraheight", ActorCameraheight, RUNTIME_CLASS(AActor) },
- { "clearflags", ActorClearFlags, RUNTIME_CLASS(AActor) },
- { "conversationid", ActorConversationID, RUNTIME_CLASS(AActor) },
- { "crash", ActorCrashState, RUNTIME_CLASS(AActor) },
- { "crush", ActorCrushState, RUNTIME_CLASS(AActor) },
- { "damage", ActorDamage, RUNTIME_CLASS(AActor) },
- { "damagefactor", ActorDamageFactor, RUNTIME_CLASS(AActor) },
- { "damagetype", ActorDamageType, RUNTIME_CLASS(AActor) },
- { "death", ActorDeathState, RUNTIME_CLASS(AActor) },
- { "deathheight", ActorDeathHeight, RUNTIME_CLASS(AActor) },
- { "deathsound", ActorDeathSound, RUNTIME_CLASS(AActor) },
- { "decal", ActorDecal, RUNTIME_CLASS(AActor) },
- { "disintegrate", ActorDisintegrateState, RUNTIME_CLASS(AActor) },
- { "donthurtshooter", ActorDontHurtShooter, RUNTIME_CLASS(AActor) },
- { "dropitem", ActorDropItem, RUNTIME_CLASS(AActor) },
- { "explosiondamage", ActorExplosionDamage, RUNTIME_CLASS(AActor) },
- { "explosionradius", ActorExplosionRadius, RUNTIME_CLASS(AActor) },
- { "fastspeed", ActorFastSpeed, RUNTIME_CLASS(AActor) },
- { "floatspeed", ActorFloatSpeed, RUNTIME_CLASS(AActor) },
- { "game", ActorGame, RUNTIME_CLASS(AActor) },
- { "gibhealth", ActorGibHealth, RUNTIME_CLASS(AActor) },
- { "gravity", ActorGravity, RUNTIME_CLASS(AActor) },
- { "heal", ActorHealState, RUNTIME_CLASS(AActor) },
- { "health", ActorHealth, RUNTIME_CLASS(AActor) },
- { "health.lowmessage", (apf)HealthLowMessage, RUNTIME_CLASS(AHealth) },
- { "height", ActorHeight, RUNTIME_CLASS(AActor) },
- { "hitobituary", ActorHitObituary, RUNTIME_CLASS(AActor) },
- { "howlsound", ActorHowlSound, RUNTIME_CLASS(AActor) },
- { "ice", ActorIceState, RUNTIME_CLASS(AActor) },
- { "inventory.amount", (apf)InventoryAmount, RUNTIME_CLASS(AInventory) },
- { "inventory.defmaxamount", (apf)InventoryDefMaxAmount, RUNTIME_CLASS(AInventory) },
- { "inventory.givequest", (apf)InventoryGiveQuest, RUNTIME_CLASS(AInventory) },
- { "inventory.icon", (apf)InventoryIcon, RUNTIME_CLASS(AInventory) },
- { "inventory.maxamount", (apf)InventoryMaxAmount, RUNTIME_CLASS(AInventory) },
- { "inventory.pickupflash", (apf)InventoryPickupflash, RUNTIME_CLASS(AInventory) },
- { "inventory.pickupmessage", (apf)InventoryPickupmsg, RUNTIME_CLASS(AInventory) },
- { "inventory.pickupsound", (apf)InventoryPickupsound, RUNTIME_CLASS(AInventory) },
- { "inventory.respawntics", (apf)InventoryRespawntics, RUNTIME_CLASS(AInventory) },
- { "inventory.usesound", (apf)InventoryUsesound, RUNTIME_CLASS(AInventory) },
- { "mass", ActorMass, RUNTIME_CLASS(AActor) },
- { "maxdropoffheight", ActorMaxDropoffHeight, RUNTIME_CLASS(AActor) },
- { "maxstepheight", ActorMaxStepHeight, RUNTIME_CLASS(AActor) },
- { "maxtargetrange", ActorMaxTargetRange, RUNTIME_CLASS(AActor) },
- { "melee", ActorMeleeState, RUNTIME_CLASS(AActor) },
- { "meleedamage", ActorMeleeDamage, RUNTIME_CLASS(AActor) },
- { "meleerange", ActorMeleeRange, RUNTIME_CLASS(AActor) },
- { "meleesound", ActorMeleeSound, RUNTIME_CLASS(AActor) },
- { "meleethreshold", ActorMeleeThreshold, RUNTIME_CLASS(AActor) },
- { "minmissilechance", ActorMinMissileChance, RUNTIME_CLASS(AActor) },
- { "missile", ActorMissileState, RUNTIME_CLASS(AActor) },
- { "missileheight", ActorMissileHeight, RUNTIME_CLASS(AActor) },
- { "missiletype", ActorMissileType, RUNTIME_CLASS(AActor) },
- { "monster", ActorMonster, RUNTIME_CLASS(AActor) },
- { "morphprojectile.duration", (apf)EggFXDuration, RUNTIME_CLASS(AMorphProjectile) },
- { "morphprojectile.monsterclass", (apf)EggFXMonsterClass, RUNTIME_CLASS(AMorphProjectile) },
- { "morphprojectile.morphflash", (apf)EggFXMorphFlash, RUNTIME_CLASS(AMorphProjectile) },
- { "morphprojectile.morphstyle", (apf)EggFXMorphStyle, RUNTIME_CLASS(AMorphProjectile) },
- { "morphprojectile.playerclass", (apf)EggFXPlayerClass, RUNTIME_CLASS(AMorphProjectile) },
- { "morphprojectile.unmorphflash", (apf)EggFXUnMorphFlash, RUNTIME_CLASS(AMorphProjectile) },
- { "obituary", ActorObituary, RUNTIME_CLASS(AActor) },
- { "pain", ActorPainState, RUNTIME_CLASS(AActor) },
- { "painchance", ActorPainChance, RUNTIME_CLASS(AActor) },
- { "painsound", ActorPainSound, RUNTIME_CLASS(AActor) },
- { "player.attackzoffset", (apf)PlayerAttackZOffset, RUNTIME_CLASS(APlayerPawn) },
- { "player.colorrange", (apf)PlayerColorRange, RUNTIME_CLASS(APlayerPawn) },
- { "player.crouchsprite", (apf)PlayerCrouchSprite, RUNTIME_CLASS(APlayerPawn) },
- { "player.damagescreencolor", (apf)PlayerDmgScreenColor, RUNTIME_CLASS(APlayerPawn) },
- { "player.displayname", (apf)PlayerDisplayName, RUNTIME_CLASS(APlayerPawn) },
- { "player.face", (apf)PlayerFace, RUNTIME_CLASS(APlayerPawn) },
- { "player.forwardmove", (apf)PlayerForwardMove, RUNTIME_CLASS(APlayerPawn) },
- { "player.healradiustype", (apf)PlayerHealRadius, RUNTIME_CLASS(APlayerPawn) },
- { "player.hexenarmor", (apf)PlayerHexenArmor, RUNTIME_CLASS(APlayerPawn) },
- { "player.invulnerabilitymode", (apf)PlayerInvulMode, RUNTIME_CLASS(APlayerPawn) },
- { "player.jumpz", (apf)PlayerJumpZ, RUNTIME_CLASS(APlayerPawn) },
- { "player.maxhealth", (apf)PlayerMaxHealth, RUNTIME_CLASS(APlayerPawn) },
- { "player.morphweapon", (apf)PlayerMorphWeapon, RUNTIME_CLASS(APlayerPawn) },
- { "player.runhealth", (apf)PlayerRunHealth, RUNTIME_CLASS(APlayerPawn) },
- { "player.scoreicon", (apf)PlayerScoreIcon, RUNTIME_CLASS(APlayerPawn) },
- { "player.sidemove", (apf)PlayerSideMove, RUNTIME_CLASS(APlayerPawn) },
- { "player.soundclass", (apf)PlayerSoundClass, RUNTIME_CLASS(APlayerPawn) },
- { "player.spawnclass", (apf)PlayerSpawnClass, RUNTIME_CLASS(APlayerPawn) },
- { "player.startitem", (apf)PlayerStartItem, RUNTIME_CLASS(APlayerPawn) },
- { "player.viewheight", (apf)PlayerViewHeight, RUNTIME_CLASS(APlayerPawn) },
- { "poisondamage", ActorPoisonDamage, RUNTIME_CLASS(AActor) },
- { "powermorph.morphflash", (apf)PowerMorphMorphFlash, RUNTIME_CLASS(APowerMorph) },
- { "powermorph.morphstyle", (apf)PowerMorphMorphStyle, RUNTIME_CLASS(APowerMorph) },
- { "powermorph.playerclass", (apf)PowerMorphPlayerClass, RUNTIME_CLASS(APowerMorph) },
- { "powermorph.unmorphflash", (apf)PowerMorphUnMorphFlash, RUNTIME_CLASS(APowerMorph) },
- { "powerup.color", (apf)PowerupColor, RUNTIME_CLASS(AInventory) },
- { "powerup.duration", (apf)PowerupDuration, RUNTIME_CLASS(AInventory) },
- { "powerup.mode", (apf)PowerupMode, RUNTIME_CLASS(APowerupGiver) },
- { "powerup.type", (apf)PowerupType, RUNTIME_CLASS(APowerupGiver) },
- { "projectile", ActorProjectile, RUNTIME_CLASS(AActor) },
- { "puzzleitem.failmessage", (apf)PuzzleitemFailMsg, RUNTIME_CLASS(APuzzleItem) },
- { "puzzleitem.number", (apf)PuzzleitemNumber, RUNTIME_CLASS(APuzzleItem) },
- { "radius", ActorRadius, RUNTIME_CLASS(AActor) },
- { "radiusdamagefactor", ActorRadiusDamageFactor, RUNTIME_CLASS(AActor) },
- { "raise", ActorRaiseState, RUNTIME_CLASS(AActor) },
- { "reactiontime", ActorReactionTime, RUNTIME_CLASS(AActor) },
- { "renderstyle", ActorRenderStyle, RUNTIME_CLASS(AActor) },
- { "scale", ActorScale, RUNTIME_CLASS(AActor) },
- { "see", ActorSeeState, RUNTIME_CLASS(AActor) },
- { "seesound", ActorSeeSound, RUNTIME_CLASS(AActor) },
- { "skip_super", ActorSkipSuper, RUNTIME_CLASS(AActor) },
- { "spawn", ActorSpawnState, RUNTIME_CLASS(AActor) },
- { "spawnid", ActorSpawnID, RUNTIME_CLASS(AActor) },
- { "speed", ActorSpeed, RUNTIME_CLASS(AActor) },
- { "states", ActorStates, RUNTIME_CLASS(AActor) },
- { "stencilcolor", ActorStencilColor, RUNTIME_CLASS(AActor) },
- { "tag", ActorTag, RUNTIME_CLASS(AActor) },
- { "translation", ActorTranslation, RUNTIME_CLASS(AActor) },
- { "vspeed", ActorVSpeed, RUNTIME_CLASS(AActor) },
- { "wallbouncefactor", ActorWallBounceFactor, RUNTIME_CLASS(AActor) },
- { "weapon.ammogive", (apf)WeaponAmmoGive1, RUNTIME_CLASS(AWeapon) },
- { "weapon.ammogive1", (apf)WeaponAmmoGive1, RUNTIME_CLASS(AWeapon) },
- { "weapon.ammogive2", (apf)WeaponAmmoGive2, RUNTIME_CLASS(AWeapon) },
- { "weapon.ammotype", (apf)WeaponAmmoType1, RUNTIME_CLASS(AWeapon) },
- { "weapon.ammotype1", (apf)WeaponAmmoType1, RUNTIME_CLASS(AWeapon) },
- { "weapon.ammotype2", (apf)WeaponAmmoType2, RUNTIME_CLASS(AWeapon) },
- { "weapon.ammouse", (apf)WeaponAmmoUse1, RUNTIME_CLASS(AWeapon) },
- { "weapon.ammouse1", (apf)WeaponAmmoUse1, RUNTIME_CLASS(AWeapon) },
- { "weapon.ammouse2", (apf)WeaponAmmoUse2, RUNTIME_CLASS(AWeapon) },
- { "weapon.defaultkickback", (apf)WeaponDefKickback, RUNTIME_CLASS(AWeapon) },
- { "weapon.kickback", (apf)WeaponKickback, RUNTIME_CLASS(AWeapon) },
- { "weapon.readysound", (apf)WeaponReadySound, RUNTIME_CLASS(AWeapon) },
- { "weapon.selectionorder", (apf)WeaponSelectionOrder, RUNTIME_CLASS(AWeapon) },
- { "weapon.sisterweapon", (apf)WeaponSisterWeapon, RUNTIME_CLASS(AWeapon) },
- { "weapon.upsound", (apf)WeaponUpSound, RUNTIME_CLASS(AWeapon) },
- { "weapon.yadjust", (apf)WeaponYAdjust, RUNTIME_CLASS(AWeapon) },
- { "weaponpiece.number", (apf)WPieceValue, RUNTIME_CLASS(AWeaponPiece) },
- { "weaponpiece.weapon", (apf)WPieceWeapon, RUNTIME_CLASS(AWeaponPiece) },
- { "wound", ActorWoundState, RUNTIME_CLASS(AActor) },
- { "woundhealth", ActorWoundHealth, RUNTIME_CLASS(AActor) },
- { "xdeath", ActorXDeathState, RUNTIME_CLASS(AActor) },
- { "xscale", ActorXScale, RUNTIME_CLASS(AActor) },
- { "yscale", ActorYScale, RUNTIME_CLASS(AActor) },
- // AWeapon:MinAmmo1 and 2 are never used so there is no point in adding them here!
-};
-static const ActorProps *is_actorprop (const char *str)
-{
- return APropSearch (str, props, sizeof(props)/sizeof(ActorProps));
-}
-
-
-//==========================================================================
-//
-// Parses an actor property
-//
-//==========================================================================
-
-void ParseActorProperty(FScanner &sc, Baggage &bag)
-{
- strlwr (sc.String);
-
- FString propname = sc.String;
-
- if (sc.CheckString ("."))
- {
- sc.MustGetString ();
- propname += '.';
- strlwr (sc.String);
- propname += sc.String;
- }
- else
- {
- sc.UnGet ();
- }
-
- const ActorProps *prop = is_actorprop (propname.GetChars());
-
- if (prop != NULL)
- {
- if (!bag.Info->Class->IsDescendantOf(prop->type))
- {
- sc.ScriptError("\"%s\" requires an actor of type \"%s\"\n", propname.GetChars(), prop->type->TypeName.GetChars());
- }
- else
- {
- prop->Handler (sc, (AActor *)bag.Info->Class->Defaults, bag);
- }
- }
- else
- {
- sc.ScriptError("\"%s\" is an unknown actor property\n", propname.GetChars());
- }
-}
-
-
-//==========================================================================
-//
-// Finalizes an actor definition
-//
-//==========================================================================
-
-void FinishActor(FScanner &sc, FActorInfo *info, Baggage &bag)
-{
- AActor *defaults = (AActor*)info->Class->Defaults;
-
- FinishStates (sc, info, defaults, bag);
- InstallStates (info, defaults);
- if (bag.DropItemSet)
- {
- if (bag.DropItemList == NULL)
- {
- if (info->Class->Meta.GetMetaInt (ACMETA_DropItems) != 0)
- {
- info->Class->Meta.SetMetaInt (ACMETA_DropItems, 0);
- }
- }
- else
- {
- info->Class->Meta.SetMetaInt (ACMETA_DropItems,
- DropItemList.Push (bag.DropItemList) + 1);
- }
- }
- if (info->Class->IsDescendantOf (RUNTIME_CLASS(AInventory)))
- {
- defaults->flags |= MF_SPECIAL;
- }
-}
diff --git a/src/thingdef/thingdef_states.cpp b/src/thingdef/thingdef_states.cpp
index e814afde..f315b382 100644
--- a/src/thingdef/thingdef_states.cpp
+++ b/src/thingdef/thingdef_states.cpp
@@ -57,9 +57,7 @@
#include "colormatcher.h"
TArray StateParameters;
-TArray JumpParameters;
static TArray AFTable;
-static TArray StateArray;
//==========================================================================
//
@@ -132,261 +130,12 @@ PSymbolActionFunction *FindGlobalActionFunction(const char *name)
return NULL;
}
-//==========================================================================
-//
-// Find a state address
-//
-//==========================================================================
-struct FStateDefine
-{
- FName Label;
- TArray Children;
- FState *State;
-};
-static TArray StateLabels;
-void ClearStateLabels()
-{
- StateLabels.Clear();
-}
//==========================================================================
-//
-// Search one list of state definitions for the given name
-//
-//==========================================================================
-
-static FStateDefine * FindStateLabelInList(TArray & list, FName name, bool create)
-{
- for(unsigned i = 0; i namelist(3);
- FStateDefine * statedef=NULL;
-
- MakeStateNameList(name, &namelist);
-
- TArray * statelist = &StateLabels;
- for(unsigned i=0;iChildren;
- }
- return statedef;
-}
-
-void AddState (const char * statename, FState * state)
-{
- FStateDefine * std = FindStateAddress(statename);
- std->State = state;
-}
-
-//==========================================================================
-//
-// Finds the state associated with the given name
-//
-//==========================================================================
-
-FState * FindState(AActor * actor, const PClass * type, const char * name)
-{
- static TArray namelist(3);
- FStateDefine * statedef=NULL;
-
- MakeStateNameList(name, &namelist);
-
- TArray * statelist = &StateLabels;
- for(unsigned i=0;iChildren;
- }
- return statedef? statedef->State : NULL;
-}
-
-//==========================================================================
-//
-// Finds the state associated with the given name
-//
-//==========================================================================
-
-FState * FindStateInClass(AActor * actor, const PClass * type, const char * name)
-{
- static TArray namelist(3);
-
- MakeStateNameList(name, &namelist);
- FActorInfo * info = type->ActorInfo;
- if (info) return info->FindState(namelist.Size(), &namelist[0], true);
- return NULL;
-}
-
-//==========================================================================
-//
-// Checks if a state list is empty
-// A list is empty if it doesn't contain any states and no children
-// that contain any states
-//
-//==========================================================================
-
-static bool IsStateListEmpty(TArray & statelist)
-{
- for(unsigned i=0;iLabel - (int)B->Label);
-}
-
-static FStateLabels * CreateStateLabelList(TArray & statelist)
-{
- // First delete all empty labels from the list
- for (int i=statelist.Size()-1;i>=0;i--)
- {
- if (statelist[i].Label == NAME_None || (statelist[i].State == NULL && statelist[i].Children.Size() == 0))
- {
- statelist.Delete(i);
- }
- }
-
- int count=statelist.Size();
-
- if (count == 0) return NULL;
-
- FStateLabels * list = (FStateLabels*)M_Malloc(sizeof(FStateLabels)+(count-1)*sizeof(FStateLabel));
- list->NumLabels = count;
-
- for (int i=0;iLabels[i].Label = statelist[i].Label;
- list->Labels[i].State = statelist[i].State;
- list->Labels[i].Children = CreateStateLabelList(statelist[i].Children);
- }
- qsort(list->Labels, count, sizeof(FStateLabel), labelcmp);
- return list;
-}
-
-//===========================================================================
-//
-// InstallStates
-//
-// Creates the actor's state list from the current definition
-//
-//===========================================================================
-
-void InstallStates(FActorInfo *info, AActor *defaults)
-{
- // First ensure we have a valid spawn state.
- FState * state = FindState(defaults, info->Class, "Spawn");
-
- if (state == NULL)
- {
- // A NULL spawn state will crash the engine so set it to something valid.
- AddState("Spawn", GetDefault()->SpawnState);
- }
-
- if (info->StateList != NULL)
- {
- info->StateList->Destroy();
- M_Free(info->StateList);
- }
- info->StateList = CreateStateLabelList(StateLabels);
-
- // Cache these states as member veriables.
- defaults->SpawnState = info->FindState(NAME_Spawn);
- defaults->SeeState = info->FindState(NAME_See);
- // Melee and Missile states are manipulated by the scripted marines so they
- // have to be stored locally
- defaults->MeleeState = info->FindState(NAME_Melee);
- defaults->MissileState = info->FindState(NAME_Missile);
-}
-
-
-//===========================================================================
-//
-// MakeStateDefines
-//
-// Creates a list of state definitions from an existing actor
-// Used by Dehacked to modify an actor's state list
-//
-//===========================================================================
-
-static void MakeStateList(const FStateLabels *list, TArray &dest)
-{
- dest.Clear();
- if (list != NULL) for(int i=0;iNumLabels;i++)
- {
- FStateDefine def;
-
- def.Label = list->Labels[i].Label;
- def.State = list->Labels[i].State;
- dest.Push(def);
- if (list->Labels[i].Children != NULL)
- {
- MakeStateList(list->Labels[i].Children, dest[dest.Size()-1].Children);
- }
- }
-}
-
-void MakeStateDefines(const FStateLabels *list)
-{
- MakeStateList(list, StateLabels);
-}
-
-void AddStateDefines(const FStateLabels *list)
-{
- if (list != NULL) for(int i=0;iNumLabels;i++)
- {
- if (list->Labels[i].Children == NULL)
- {
- if (!FindStateLabelInList(StateLabels, list->Labels[i].Label, false))
- {
- FStateDefine def;
-
- def.Label = list->Labels[i].Label;
- def.State = list->Labels[i].State;
- StateLabels.Push(def);
- }
- }
- }
-}
-
-//==========================================================================
-//
+//***
// PrepareStateParameters
// creates an empty parameter list for a parameterized function call
//
@@ -403,7 +152,7 @@ int PrepareStateParameters(FState * state, int numparams)
}
//==========================================================================
-//
+//***
// DoActionSpecials
// handles action specials as code pointers
//
@@ -457,40 +206,7 @@ bool DoActionSpecials(FScanner &sc, FState & state, bool multistate, int * state
}
//==========================================================================
-//
-// RetargetState(Pointer)s
-//
-// These functions are used when a goto follows one or more labels.
-// Because multiple labels are permitted to occur consecutively with no
-// intervening states, it is not enough to remember the last label defined
-// and adjust it. So these functions search for all labels that point to
-// the current position in the state array and give them a copy of the
-// target string instead.
-//
-//==========================================================================
-
-static void RetargetStatePointers (intptr_t count, const char *target, TArray & statelist)
-{
- for(unsigned i = 0;i 0)
- {
- RetargetStatePointers(count, target, statelist[i].Children);
- }
- }
-}
-
-static void RetargetStates (intptr_t count, const char *target)
-{
- RetargetStatePointers(count, target, StateLabels);
-}
-
-//==========================================================================
-//
+//***
// Reads a state label that may contain '.'s.
// processes a state block
//
@@ -515,7 +231,7 @@ static FString ParseStateString(FScanner &sc)
}
//==========================================================================
-//
+//***
// ParseStates
// parses a state block
//
@@ -551,10 +267,11 @@ do_goto:
if (laststate != NULL)
{ // Following a state definition: Modify it.
laststate->NextState = (FState*)copystring(statestring);
+ laststate->DefineFlags = SDF_LABEL;
}
else if (lastlabel >= 0)
{ // Following a label: Retarget it.
- RetargetStates (count+1, statestring);
+ bag.statedef.RetargetStates (count+1, statestring);
}
else
{
@@ -566,11 +283,11 @@ do_goto:
do_stop:
if (laststate!=NULL)
{
- laststate->NextState=(FState*)-1;
+ laststate->DefineFlags = SDF_STOP;
}
else if (lastlabel >=0)
{
- RetargetStates (count+1, NULL);
+ bag.statedef.RetargetStates (count+1, NULL);
}
else
{
@@ -585,7 +302,7 @@ do_stop:
sc.ScriptError("%s before first state", sc.String);
continue;
}
- laststate->NextState=(FState*)-2;
+ laststate->DefineFlags = SDF_WAIT;
}
else if (!statestring.CompareNoCase("LOOP"))
{
@@ -595,6 +312,7 @@ do_stop:
continue;
}
laststate->NextState=(FState*)(lastlabel+1);
+ laststate->DefineFlags = SDF_INDEX;
}
else
{
@@ -607,7 +325,7 @@ do_stop:
do
{
lastlabel = count;
- AddState(statestring, (FState *) (count+1));
+ bag.statedef.AddState(statestring, (FState *) (count+1), SDF_INDEX);
statestring = ParseStateString(sc);
if (!statestring.CompareNoCase("GOTO"))
{
@@ -788,7 +506,7 @@ do_stop:
}
sc.UnGet();
endofstate:
- StateArray.Push(state);
+ bag.StateArray.Push(state);
while (*statestrp)
{
int frame=((*statestrp++)&223)-'A';
@@ -800,10 +518,10 @@ endofstate:
}
state.Frame=(state.Frame&(SF_FULLBRIGHT))|frame;
- StateArray.Push(state);
+ bag.StateArray.Push(state);
count++;
}
- laststate=&StateArray[count];
+ laststate=&bag.StateArray[count];
count++;
}
}
@@ -815,240 +533,3 @@ endofstate:
return count;
}
-//==========================================================================
-//
-// ResolveGotoLabel
-//
-//==========================================================================
-
-static FState *ResolveGotoLabel (FScanner &sc, AActor *actor, const PClass *mytype, char *name)
-{
- const PClass *type=mytype;
- FState *state;
- char *namestart = name;
- char *label, *offset, *pt;
- int v;
-
- // Check for classname
- if ((pt = strstr (name, "::")) != NULL)
- {
- const char *classname = name;
- *pt = '\0';
- name = pt + 2;
-
- // The classname may either be "Super" to identify this class's immediate
- // superclass, or it may be the name of any class that this one derives from.
- if (stricmp (classname, "Super") == 0)
- {
- type = type->ParentClass;
- actor = GetDefaultByType (type);
- }
- else
- {
- // first check whether a state of the desired name exists
- const PClass *stype = PClass::FindClass (classname);
- if (stype == NULL)
- {
- sc.ScriptError ("%s is an unknown class.", classname);
- }
- if (!stype->IsDescendantOf (RUNTIME_CLASS(AActor)))
- {
- sc.ScriptError ("%s is not an actor class, so it has no states.", stype->TypeName.GetChars());
- }
- if (!stype->IsAncestorOf (type))
- {
- sc.ScriptError ("%s is not derived from %s so cannot access its states.",
- type->TypeName.GetChars(), stype->TypeName.GetChars());
- }
- if (type != stype)
- {
- type = stype;
- actor = GetDefaultByType (type);
- }
- }
- }
- label = name;
- // Check for offset
- offset = NULL;
- if ((pt = strchr (name, '+')) != NULL)
- {
- *pt = '\0';
- offset = pt + 1;
- }
- v = offset ? strtol (offset, NULL, 0) : 0;
-
- // Get the state's address.
- if (type==mytype) state = FindState (actor, type, label);
- else state = FindStateInClass (actor, type, label);
-
- if (state != NULL)
- {
- state += v;
- }
- else if (v != 0)
- {
- sc.ScriptError ("Attempt to get invalid state %s from actor %s.", label, type->TypeName.GetChars());
- }
- delete[] namestart; // free the allocated string buffer
- return state;
-}
-
-//==========================================================================
-//
-// FixStatePointers
-//
-// Fixes an actor's default state pointers.
-//
-//==========================================================================
-
-static void FixStatePointers (FActorInfo *actor, TArray & list)
-{
- for(unsigned i=0;i= 1 && v < 0x10000)
- {
- list[i].State = actor->OwnedStates + v - 1;
- }
- if (list[i].Children.Size() > 0) FixStatePointers(actor, list[i].Children);
- }
-}
-
-//==========================================================================
-//
-// FixStatePointersAgain
-//
-// Resolves an actor's state pointers that were specified as jumps.
-//
-//==========================================================================
-
-static void FixStatePointersAgain (FScanner &sc, FActorInfo *actor, AActor *defaults, TArray & list)
-{
- for(unsigned i=0;iClass, (char *)list[i].State);
- }
- if (list[i].Children.Size() > 0) FixStatePointersAgain(sc, actor, defaults, list[i].Children);
- }
-}
-
-
-//==========================================================================
-//
-// FinishStates
-// copies a state block and fixes all state links
-//
-//==========================================================================
-
-int FinishStates (FScanner &sc, FActorInfo *actor, AActor *defaults, Baggage &bag)
-{
- static int c=0;
- int count = StateArray.Size();
-
- if (count > 0)
- {
- FState *realstates = new FState[count];
- int i;
- int currange;
-
- memcpy(realstates, &StateArray[0], count*sizeof(FState));
- actor->OwnedStates = realstates;
- actor->NumOwnedStates = count;
-
- // adjust the state pointers
- // In the case new states are added these must be adjusted, too!
- FixStatePointers (actor, StateLabels);
-
- for(i = currange = 0; i < count; i++)
- {
- // resolve labels and jumps
- switch((ptrdiff_t)realstates[i].NextState)
- {
- case 0: // next
- realstates[i].NextState = (i < count-1 ? &realstates[i+1] : &realstates[0]);
- break;
-
- case -1: // stop
- realstates[i].NextState = NULL;
- break;
-
- case -2: // wait
- realstates[i].NextState = &realstates[i];
- break;
-
- default: // loop
- if ((size_t)realstates[i].NextState < 0x10000)
- {
- realstates[i].NextState = &realstates[(size_t)realstates[i].NextState-1];
- }
- else // goto
- {
- realstates[i].NextState = ResolveGotoLabel (sc, defaults, bag.Info->Class, (char *)realstates[i].NextState);
- }
- }
- }
- }
- StateArray.Clear ();
-
- // Fix state pointers that are gotos
- FixStatePointersAgain (sc, actor, defaults, StateLabels);
-
- return count;
-}
-
-//==========================================================================
-//
-// For getting a state address from the parent
-// No attempts have been made to add new functionality here
-// This is strictly for keeping compatibility with old WADs!
-//
-//==========================================================================
-FState *CheckState(FScanner &sc, PClass *type)
-{
- int v=0;
-
- if (sc.GetString() && !sc.Crossed)
- {
- if (sc.Compare("0")) return NULL;
- else if (sc.Compare("PARENT"))
- {
- FState * state = NULL;
- sc.MustGetString();
-
- FActorInfo * info = type->ParentClass->ActorInfo;
-
- if (info != NULL)
- {
- state = info->FindState(FName(sc.String));
- }
-
- if (sc.GetString ())
- {
- if (sc.Compare ("+"))
- {
- sc.MustGetNumber ();
- v = sc.Number;
- }
- else
- {
- sc.UnGet ();
- }
- }
-
- if (state == NULL && v==0) return NULL;
-
- if (v!=0 && state==NULL)
- {
- sc.ScriptError("Attempt to get invalid state from actor %s\n", type->ParentClass->TypeName.GetChars());
- return NULL;
- }
- state+=v;
- return state;
- }
- else sc.ScriptError("Invalid state assignment");
- }
- return NULL;
-}
-
diff --git a/src/timidity/timidity.cpp b/src/timidity/timidity.cpp
index 521097ef..3a4345df 100644
--- a/src/timidity/timidity.cpp
+++ b/src/timidity/timidity.cpp
@@ -383,7 +383,7 @@ static int read_config_file(const char *name, bool ismain)
bank->tone[i].name = w[2];
bank->tone[i].fontbank = atoi(w[3]);
bank->tone[i].fontpreset = atoi(w[4]);
- if (bank->tone[i].fontbank == 128 || (w[5][0] >= '0' && w[5][0] <= '9'))
+ if (words > 5 && (bank->tone[i].fontbank == 128 || (w[5][0] >= '0' && w[5][0] <= '9')))
{
bank->tone[i].fontnote = atoi(w[5]);
j = 6;
diff --git a/src/v_collection.cpp b/src/v_collection.cpp
index 78301287..b8ee25d8 100644
--- a/src/v_collection.cpp
+++ b/src/v_collection.cpp
@@ -62,12 +62,7 @@ void FImageCollection::Add (const char **patchNames, int numPatches, int namespc
for (int i = 0; i < numPatches; ++i)
{
- FTextureID picnum = TexMan.AddPatch (patchNames[i], namespc, true);
-
- if (!picnum.Exists() && namespc != ns_sprites)
- {
- picnum = TexMan.AddPatch (patchNames[i], ns_sprites);
- }
+ FTextureID picnum = TexMan.CheckForTexture(patchNames[i], namespc);
ImageMap[OldCount + i] = picnum;
}
}
diff --git a/src/v_font.cpp b/src/v_font.cpp
index 3e349031..2388e025 100644
--- a/src/v_font.cpp
+++ b/src/v_font.cpp
@@ -1768,7 +1768,7 @@ void V_InitCustomFonts()
return;
wrong:
- sc.ScriptError ("Invalid combination of properties in font '%s'", namebuffer);
+ sc.ScriptError ("Invalid combination of properties in font '%s'", namebuffer.GetChars());
}
//==========================================================================
diff --git a/src/v_video.h b/src/v_video.h
index b02e4ea1..788b3190 100644
--- a/src/v_video.h
+++ b/src/v_video.h
@@ -114,13 +114,6 @@ enum
HUD_HorizCenter
};
-// Screenshot buffer image data types
-enum ESSType
-{
- SS_PAL,
- SS_RGB,
- SS_BGRA
-};
class FFont;
struct FRemapTable;
diff --git a/src/wi_stuff.cpp b/src/wi_stuff.cpp
index d51dc042..cf49c684 100644
--- a/src/wi_stuff.cpp
+++ b/src/wi_stuff.cpp
@@ -763,7 +763,7 @@ void WI_drawLF ()
{
int y = WI_TITLEY;
- FTexture * tex = wbs->lname0[0]? TexMan[wbs->lname0] : NULL;
+ FTexture * tex = wbs->LName0;
// draw
if (tex)
@@ -825,7 +825,7 @@ void WI_drawEL ()
}
// draw
- FTexture * tex = wbs->lname1[0]? TexMan[wbs->lname1] : NULL;
+ FTexture * tex = wbs->LName1;
if (tex)
{
screen->DrawTexture(tex, (SCREENWIDTH - tex->GetWidth() * CleanXfac) / 2, y * CleanYfac, DTA_CleanNoMove, true, TAG_DONE);
diff --git a/src/wi_stuff.h b/src/wi_stuff.h
index 266fe166..dee36e73 100644
--- a/src/wi_stuff.h
+++ b/src/wi_stuff.h
@@ -24,6 +24,8 @@
#include "doomdef.h"
+class FTexture;
+
//
// INTERMISSION
// Structure passed e.g. to WI_Start(wb)
@@ -50,8 +52,8 @@ struct wbstartstruct_t
FString current; // [RH] Name of map just finished
FString next; // next level, [RH] actual map name
- FString lname0;
- FString lname1;
+ FTexture *LName0;
+ FTexture *LName1;
int maxkills;
int maxitems;
diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/actors/constants.txt
index 91caf723..3e7d2834 100644
--- a/wadsrc/static/actors/constants.txt
+++ b/wadsrc/static/actors/constants.txt
@@ -13,7 +13,8 @@ const int SXF_ABSOLUTEMOMENTUM=8;
const int SXF_SETMASTER=16;
const int SXF_NOCHECKPOSITION = 32;
const int SXF_TELEFRAG=64;
-const int SXF_TRANSFERAMBUSHFLAG=128;
+// 128 was uses by Skulltag
+const int SXF_TRANSFERAMBUSHFLAG=256;
// Flags for A_Chase
const int CHF_FASTCHASE = 1;
@@ -28,3 +29,17 @@ const int LOF_NOSOUNDCHECK = 2;
const int LOF_DONTCHASEGOAL = 4;
const int LOF_NOSEESOUND = 8;
const int LOF_FULLVOLSEESOUND = 16;
+
+// Morph constants
+const int MRF_ADDSTAMINA = 1;
+const int MRF_FULLHEALTH = 2;
+const int MRF_UNDOBYTOMEOFPOWER = 4;
+const int MRF_UNDOBYCHAOSDEVICE = 8;
+const int MRF_FAILNOTELEFRAG = 16;
+const int MRF_FAILNOLAUGH = 32;
+const int MRF_WHENINVULNERABLE = 64;
+const int MRF_LOSEACTUALWEAPON = 128;
+const int MRF_NEWTIDBEHAVIOUR = 256;
+const int MRF_UNDOBYDEATH = 512;
+const int MRF_UNDOBYDEATHFORCED = 1024;
+const int MRF_UNDOBYDEATHSAVES = 2048;
diff --git a/wadsrc/static/actors/shared/splashes.txt b/wadsrc/static/actors/shared/splashes.txt
index 64bb1490..56713fd1 100644
--- a/wadsrc/static/actors/shared/splashes.txt
+++ b/wadsrc/static/actors/shared/splashes.txt
@@ -65,7 +65,7 @@ ACTOR LavaSmoke
+NOGRAVITY
+DONTSPLASH
RenderStyle Translucent
- Alpha Default
+ DefaultAlpha
States
{
Spawn: