mirror of
https://github.com/ZDoom/qzdoom.git
synced 2025-01-17 23:01:04 +00:00
- Fixed: SNDINFO must be loaded before the textures. However, this required
some changes to the MAPINFO parser which tried to access the texture manager to check if the level name patches exist. That check had to be moved to where the intermission screen is set up. - Fixed: 'bloodcolor' ignored the first parameter value when given a list of integers. Please note that this creates an incompatibility between old and new versions so if you want to create something that works with both 2.2.0 and current versions better use the string format version for the color parameter! - Rewrote the DECORATE property parser so that the parser is completely separated from the property handlers. This should allow reuse of all the handler code for a new format if Doomscript requires one. - Fixed: PClass::InitializeActorInfo copied too many bytes if a subclass's defaults were larger than the parent's. - Moved A_ChangeFlag to thingdef_codeptr.cpp. - Moved translation related code from thingdef_properties.cpp to r_translate.cpp and rewrote the translation parser to use FScanner instead of strtol. - replaced DECORATE's 'alpha default' by 'defaultalpha' for consistency. Since this was never used outside zdoom.pk3 it's not critical. - Removed support for game specific pickup messages because the only thing this was ever used for - Raven's invulnerability item - has already been split up into a Heretic and Hexen version. SVN r1240 (trunk)
This commit is contained in:
parent
2b16b99f4d
commit
6227906072
38 changed files with 2303 additions and 2309 deletions
|
@ -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.
|
||||
|
|
22
src/actor.h
22
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<FDropItem *>
|
||||
{
|
||||
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);
|
||||
|
|
|
@ -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 T, REGINFO *_head, REGINFO *_tail>
|
||||
class TAutoSegIteratorNoArrow
|
||||
{
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -587,7 +587,7 @@ IMPLEMENT_CLASS(AWeaponGiver)
|
|||
|
||||
bool AWeaponGiver::TryPickup(AActor *&toucher)
|
||||
{
|
||||
FDropItem *di = GetDropItems(GetClass());
|
||||
FDropItem *di = GetDropItems();
|
||||
|
||||
if (di != NULL)
|
||||
{
|
||||
|
|
15
src/gi.cpp
15
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",
|
||||
};
|
||||
|
|
1
src/gi.h
1
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;
|
||||
|
|
13
src/info.cpp
13
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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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<PalEntry> 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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<PalEntry> BloodTranslationColors;
|
||||
|
||||
int CreateBloodTranslation(PalEntry color);
|
||||
|
||||
|
||||
|
||||
#endif // __R_TRANSLATE_H
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
550
src/thingdef/thingdef_parse.cpp
Normal file
550
src/thingdef/thingdef_parse.cpp
Normal file
|
@ -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<FPropParam> params;
|
||||
static TArray<FString> 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;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 <LevelName>
|
||||
if (tex)
|
||||
|
@ -825,7 +825,7 @@ void WI_drawEL ()
|
|||
}
|
||||
|
||||
// draw <LevelName>
|
||||
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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -65,7 +65,7 @@ ACTOR LavaSmoke
|
|||
+NOGRAVITY
|
||||
+DONTSPLASH
|
||||
RenderStyle Translucent
|
||||
Alpha Default
|
||||
DefaultAlpha
|
||||
States
|
||||
{
|
||||
Spawn:
|
||||
|
|
753
zdoom.vcproj
753
zdoom.vcproj
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue