diff --git a/docs/rh-log.txt b/docs/rh-log.txt index c0b44d1c87..357bdc467f 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 acf1b857f3..adf6f635dc 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 0f5fd0c013..c4b9c89633 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 3d23baf048..d3e20387bb 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 68a4556e68..ce8aef5129 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 73c66da968..2bd670b08c 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 6cf9146cbe..2c7e3e862c 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 78cef7fc35..bfd6f13d51 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 d38a1b0635..399a3d1464 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 33988becc4..e9298e8fa0 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 0c520fc6c2..e54f31756a 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 5fb39bbac8..33f27930e9 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 088c1a6932..d26733e227 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 26514d2c66..9ef71f8a86 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 61eb767f32..043a16b38c 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 5754da9270..1a2762167b 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 381656e030..a7ef11e30a 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 ccd2b85601..90bdffd111 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 c1b3bb3574..b60fe0bd79 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 7cfc8ddc0e..da34393b63 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 36c002a730..245e3bff93 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 f6ec46c27e..4a0481283c 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 84e481b03b..098edb6992 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 cf0622a749..6a228cf85d 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 81061b9c9c..fba8275fb7 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 8e25f7641d..fab1285502 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 c9abe1daf6..e8922501b8 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 fc14386cf9..dcfc413016 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 7a9799d124..4e52acbfe8 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 4525ff7353..85513e1564 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 0000000000..67a18e5bba --- /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 52b9fe686c..5b4f0c868c 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 e814afde9f..b3a2d2bf47 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 d51dc0429d..cf49c684f1 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 266fe166cb..dee36e7364 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 91caf723c7..bbf0b44489 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 64bb14909b..56713fd172 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 b64b0f1d54..c79012dc75 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 @@ />