From 62279060722b5e3271589bebee3e24ff6732e86f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 21 Sep 2008 18:02:38 +0000 Subject: [PATCH] - 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. SVN r1240 (trunk) --- docs/rh-log.txt | 28 + src/actor.h | 22 + src/autosegs.h | 6 +- src/d_dehacked.cpp | 24 +- src/d_main.cpp | 13 +- src/dobjtype.cpp | 2 +- src/g_doom/a_bossbrain.cpp | 2 +- src/g_level.cpp | 12 +- src/g_shared/a_action.cpp | 2 +- src/g_shared/a_keys.cpp | 1 + src/g_shared/a_randomspawner.cpp | 2 +- src/g_shared/a_weapons.cpp | 2 +- src/gi.cpp | 15 + src/gi.h | 1 + src/info.cpp | 13 +- src/m_cheat.cpp | 56 +- src/m_misc.cpp | 18 +- src/p_mobj.cpp | 42 + src/p_teleport.cpp | 34 +- src/p_udmf.cpp | 1 + src/p_user.cpp | 2 +- src/r_translate.cpp | 279 +++ src/r_translate.h | 6 + src/sc_man.cpp | 2 +- src/sc_man.h | 2 +- src/thingdef/olddecorations.cpp | 168 +- src/thingdef/thingdef.cpp | 77 +- src/thingdef/thingdef.h | 113 +- src/thingdef/thingdef_codeptr.cpp | 46 + src/thingdef/thingdef_main.cpp | 3 - src/thingdef/thingdef_parse.cpp | 550 ++++++ src/thingdef/thingdef_properties.cpp | 2235 ++++++++-------------- src/thingdef/thingdef_states.cpp | 54 - src/wi_stuff.cpp | 4 +- src/wi_stuff.h | 6 +- wadsrc/static/actors/constants.txt | 14 + wadsrc/static/actors/shared/splashes.txt | 2 +- zdoom.vcproj | 753 ++++---- 38 files changed, 2303 insertions(+), 2309 deletions(-) create mode 100644 src/thingdef/thingdef_parse.cpp diff --git a/docs/rh-log.txt b/docs/rh-log.txt index c0b44d1c8..357bdc467 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,31 @@ +September 21, 2008 (Changes by Graf Zahl) +- 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. diff --git a/src/actor.h b/src/actor.h index acf1b857f..adf6f635d 100644 --- a/src/actor.h +++ b/src/actor.h @@ -427,6 +427,27 @@ enum AMETA_BloodType3, // AxeBlood replacement type }; +struct FDropItem +{ + FName Name; + int probability; + int amount; + FDropItem * Next; +}; + +class FDropItemPtrArray : public TArray +{ +public: + ~FDropItemPtrArray(); +}; + +extern FDropItemPtrArray DropItemList; + +void FreeDropItemChain(FDropItem *chain); +int StoreDropItemChain(FDropItem *chain); + + + // Map Object definition. class AActor : public DThinker { @@ -448,6 +469,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); diff --git a/src/autosegs.h b/src/autosegs.h index 0f5fd0c01..c4b9c8963 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 3d23baf04..d3e20387b 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -1697,18 +1697,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 +2199,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)) { diff --git a/src/d_main.cpp b/src/d_main.cpp index 68a4556e6..ce8aef512 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -2481,12 +2481,6 @@ void D_DoomMain (void) StartScreen->AppendStatusLine(temp); } - Printf ("Texman.Init: Init texture manager.\n"); - TexMan.Init(); - - // Now that all textues have been loaded the crosshair can be initialized. - crosshair.Callback (); - // [RH] Parse through all loaded mapinfo lumps Printf ("G_ParseMapInfo: Load map definitions.\n"); G_ParseMapInfo (); @@ -2495,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 73c66da96..2bd670b08 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/g_doom/a_bossbrain.cpp b/src/g_doom/a_bossbrain.cpp index 6cf9146cb..2c7e3e862 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 78cef7fc3..bfd6f13d5 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -830,6 +830,7 @@ 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.CheckForTexture(levelinfo->pname, FTexture::TEX_MiscPatch).Exists()) @@ -837,6 +838,7 @@ static void G_DoParseMapInfo (int lump) levelinfo->pname[0] = 0; } } + */ break; } @@ -1704,7 +1706,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 (); } @@ -1973,7 +1975,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 && @@ -1981,20 +1983,20 @@ 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)]; } } diff --git a/src/g_shared/a_action.cpp b/src/g_shared/a_action.cpp index d38a1b063..399a3d146 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 33988becc..e9298e8fa 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 0c520fc6c..e54f31756 100644 --- a/src/g_shared/a_randomspawner.cpp +++ b/src/g_shared/a_randomspawner.cpp @@ -30,7 +30,7 @@ class ARandomSpawner : public AActor 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 5fb39bbac..33f27930e 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) { diff --git a/src/gi.cpp b/src/gi.cpp index 088c1a693..d26733e22 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 26514d2c6..9ef71f8a8 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 61eb767f3..043a16b38 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -174,16 +174,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); diff --git a/src/m_cheat.cpp b/src/m_cheat.cpp index 5754da927..1a2762167 100644 --- a/src/m_cheat.cpp +++ b/src/m_cheat.cpp @@ -44,6 +44,7 @@ #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 @@ -630,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); @@ -874,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 381656e03..a7ef11e30 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/p_mobj.cpp b/src/p_mobj.cpp index ccd2b8560..90bdffd11 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -4887,3 +4887,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_teleport.cpp b/src/p_teleport.cpp index c1b3bb357..b60fe0bd7 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 7cfc8ddc0..da34393b6 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 36c002a73..245e3bff9 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -982,7 +982,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_translate.cpp b/src/r_translate.cpp index f6ec46c27..4a0481283 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 84e481b03..098edb699 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/sc_man.cpp b/src/sc_man.cpp index cf0622a74..6a228cf85 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 81061b9c9..fba8275fb 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/thingdef/olddecorations.cpp b/src/thingdef/olddecorations.cpp index 8e25f7641..fab128550 100644 --- a/src/thingdef/olddecorations.cpp +++ b/src/thingdef/olddecorations.cpp @@ -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 -------------------------------------------------------------------- //========================================================================== @@ -243,65 +152,8 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def) info->GameFilter = 0x80; MakeStateDefines(parent->ActorInfo->StateList); - // 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)); @@ -724,23 +576,9 @@ 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); - } + Baggage bag; + bag.Info = info; + HandleActorFlag(sc, bag, sc.String, NULL, '+'); } else { diff --git a/src/thingdef/thingdef.cpp b/src/thingdef/thingdef.cpp index c9abe1daf..e8922501b 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 @@ -560,6 +484,7 @@ static FActorInfo *CreateNewActor(FScanner &sc, FActorInfo **parentc, Baggage *b ResetBaggage (bag); bag->Info = info; + bag->Lumpnum = sc.LumpNum; info->DoomEdNum = -1; if (parent->ActorInfo->DamageFactors != NULL) diff --git a/src/thingdef/thingdef.h b/src/thingdef/thingdef.h index fc14386cf..dcfc41301 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 @@ -30,27 +48,12 @@ public: }; -//========================================================================== -// -// Dropitem list -// -//========================================================================== - -struct FDropItem -{ - FName Name; - int probability; - int amount; - FDropItem * Next; -}; - -FDropItem *GetDropItems(const PClass * cls); - //========================================================================== // // Extra info maintained while defining an actor. // //========================================================================== +struct FDropItem; struct Baggage { @@ -58,6 +61,7 @@ struct Baggage bool DropItemSet; bool StateSet; int CurrentState; + int Lumpnum; FDropItem *DropItemList; }; @@ -70,7 +74,6 @@ inline void ResetBaggage (Baggage *bag) bag->StateSet = false; } - //========================================================================== // // Action function lookup @@ -115,6 +118,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 +160,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 7a9799d12..4e52acbfe 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -2236,3 +2236,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 4525ff735..85513e156 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 000000000..67a18e5bb --- /dev/null +++ b/src/thingdef/thingdef_parse.cpp @@ -0,0 +1,550 @@ +/* +** 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" + + +//========================================================================== +// +// 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) + { + 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; + + 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, + 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 52b9fe686..5b4f0c868 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; } @@ -833,257 +580,167 @@ static void ActorSkipSuper (FScanner &sc, AActor *defaults, Baggage &bag) //========================================================================== // //========================================================================== -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 +748,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 +815,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 +836,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 +846,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 +900,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 +929,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 +939,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 +1064,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 +1092,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 +1248,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 +1260,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,125 +1277,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.CheckForTexture(sc.String, FTexture::TEX_MiscPatch); + PROP_STRING_PARM(i, 0); + + defaults->Icon = TexMan.CheckForTexture(i, FTexture::TEX_MiscPatch); 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(sc.LumpNum) != 0) + !(gameinfo.flags&GI_SHAREWARE) && Wads.GetLumpFile(bag.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()); } } } @@ -1909,16 +1405,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; } @@ -1927,170 +1423,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; } @@ -2098,74 +1604,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; @@ -2179,67 +1684,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; @@ -2250,30 +1748,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); } //========================================================================== @@ -2285,21 +1783,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); } @@ -2307,19 +1804,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'))) && @@ -2328,7 +1824,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); @@ -2337,15 +1833,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); @@ -2356,150 +1847,147 @@ 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); } + else + { + for(int i=1; iSpawnMask = 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; + + } + } } //========================================================================== // //========================================================================== -static void PlayerViewHeight (FScanner &sc, APlayerPawn *defaults, Baggage &bag) +DEFINE_CLASS_PROPERTY_PREFIX(player, viewheight, F, PlayerPawn) { - sc.MustGetFloat (); - defaults->ViewHeight = FLOAT2FIXED (sc.Float); + PROP_FIXED_PARM(z, 0); + defaults->ViewHeight = z; } //========================================================================== // //========================================================================== -static void PlayerForwardMove (FScanner &sc, APlayerPawn *defaults, Baggage &bag) +DEFINE_CLASS_PROPERTY_PREFIX(player, forwardmove, F_f, PlayerPawn) { - sc.MustGetFloat (); - defaults->ForwardMove1 = defaults->ForwardMove2 = FLOAT2FIXED (sc.Float); - if (CheckFloatParm (sc)) - defaults->ForwardMove2 = FLOAT2FIXED (sc.Float); + PROP_FIXED_PARM(m, 0); + defaults->ForwardMove1 = defaults->ForwardMove2 = m; + if (PROP_PARM_COUNT > 1) + { + PROP_FIXED_PARM(m2, 1); + defaults->ForwardMove2 = m2; + } } //========================================================================== // //========================================================================== -static void PlayerSideMove (FScanner &sc, APlayerPawn *defaults, Baggage &bag) +DEFINE_CLASS_PROPERTY_PREFIX(player, sidemove, F_f, PlayerPawn) { - sc.MustGetFloat (); - defaults->SideMove1 = defaults->SideMove2 = FLOAT2FIXED (sc.Float); - if (CheckFloatParm (sc)) - defaults->SideMove2 = FLOAT2FIXED (sc.Float); + PROP_FIXED_PARM(m, 0); + defaults->SideMove1 = defaults->SideMove2 = m; + if (PROP_PARM_COUNT > 1) + { + PROP_FIXED_PARM(m2, 1); + defaults->SideMove2 = m2; + } } //========================================================================== // //========================================================================== -static void PlayerMaxHealth (FScanner &sc, APlayerPawn *defaults, Baggage &bag) +DEFINE_CLASS_PROPERTY_PREFIX(player, maxhealth, I, PlayerPawn) { - sc.MustGetNumber (); - defaults->MaxHealth = sc.Number; + PROP_INT_PARM(z, 0); + defaults->MaxHealth = z; } //========================================================================== // //========================================================================== -static void PlayerRunHealth (FScanner &sc, APlayerPawn *defaults, Baggage &bag) +DEFINE_CLASS_PROPERTY_PREFIX(player, runhealth, I, PlayerPawn) { - sc.MustGetNumber (); - defaults->RunHealth = sc.Number; + PROP_INT_PARM(z, 0); + defaults->RunHealth = z; } //========================================================================== // //========================================================================== -static void PlayerMorphWeapon (FScanner &sc, APlayerPawn *defaults, Baggage &bag) +DEFINE_CLASS_PROPERTY_PREFIX(player, morphweapon, S, PlayerPawn) { - sc.MustGetString (); - defaults->MorphWeapon = FName(sc.String); + PROP_STRING_PARM(z, 0); + defaults->MorphWeapon = FName(z); } //========================================================================== // //========================================================================== -static void PlayerScoreIcon (FScanner &sc, APlayerPawn *defaults, Baggage &bag) +DEFINE_CLASS_PROPERTY_PREFIX(player, scoreicon, S, PlayerPawn) { - sc.MustGetString (); - defaults->ScoreIcon = TexMan.CheckForTexture(sc.String, FTexture::TEX_MiscPatch); + 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", sc.String, bag.Info->Class->TypeName.GetChars ()); + Printf("Icon '%s' for '%s' not found\n", z, bag.Info->Class->TypeName.GetChars ()); } } //========================================================================== // //========================================================================== -static void PlayerCrouchSprite (FScanner &sc, APlayerPawn *defaults, Baggage &bag) +DEFINE_CLASS_PROPERTY_PREFIX(player, crouchsprite, S, PlayerPawn) { - sc.MustGetString (); - for (int i = 0; i < sc.StringLen; i++) - { - sc.String[i] = toupper (sc.String[i]); - } - defaults->crouchsprite = GetSpriteIndex (sc.String); + PROP_STRING_PARM(z, 0); + defaults->crouchsprite = GetSpriteIndex (z); } //========================================================================== // //========================================================================== -static void PlayerDmgScreenColor (FScanner &sc, APlayerPawn *defaults, Baggage &bag) +DEFINE_CLASS_PROPERTY_PREFIX(player, damagescreencolor, C, PlayerPawn) { - if (sc.CheckNumber ()) - { - 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); - } - else - { - sc.MustGetString (); - int c = V_GetColor (NULL, sc.String); - defaults->RedDamageFade = RPART (c); - defaults->GreenDamageFade = GPART (c); - defaults->BlueDamageFade = BPART (c); - } + PROP_COLOR_PARM(c, 0); + defaults->RedDamageFade = RPART (c); + defaults->GreenDamageFade = GPART (c); + defaults->BlueDamageFade = BPART (c); } //========================================================================== @@ -2507,9 +1995,11 @@ static void PlayerDmgScreenColor (FScanner &sc, APlayerPawn *defaults, Baggage & // [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; @@ -2518,13 +2008,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, 0); + di->amount = amt; } di->Next = bag.DropItemList; bag.DropItemList = di; @@ -2533,136 +2023,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) { @@ -2675,250 +2191,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 e814afde9..b3a2d2bf4 100644 --- a/src/thingdef/thingdef_states.cpp +++ b/src/thingdef/thingdef_states.cpp @@ -998,57 +998,3 @@ int FinishStates (FScanner &sc, FActorInfo *actor, AActor *defaults, Baggage &ba 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/wi_stuff.cpp b/src/wi_stuff.cpp index d51dc0429..cf49c684f 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 266fe166c..dee36e736 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 91caf723c..bbf0b4448 100644 --- a/wadsrc/static/actors/constants.txt +++ b/wadsrc/static/actors/constants.txt @@ -28,3 +28,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 64bb14909..56713fd17 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: diff --git a/zdoom.vcproj b/zdoom.vcproj index b64b0f1d5..c79012dc7 100644 --- a/zdoom.vcproj +++ b/zdoom.vcproj @@ -1,7 +1,7 @@ + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - + + @@ -1551,6 +1554,16 @@ Outputs="$(IntDir)\$(InputName).obj" /> + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + @@ -1793,14 +1804,6 @@ Outputs="$(IntDir)/$(InputName).obj" /> - - - @@ -1966,14 +1969,6 @@ Outputs="$(IntDir)\$(InputName).obj" /> - - - @@ -1984,6 +1979,14 @@ Outputs="$(IntDir)\$(InputName).obj" /> + + + - - - + + + - - - @@ -5292,6 +5287,14 @@ AdditionalIncludeDirectories="src\win32;$(NoInherit)" /> + + + @@ -5570,7 +5573,7 @@ />