mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2025-02-21 11:01:36 +00:00
- Fixed: deadthings.txt contained a superfluous ';' which created parsing errors
with my changed code. - Cleaned up DECORATE parser a little - moved the old style parsing code into its own file and rearranged a few things. - Made ProcessStates non-static so that it doesn't need to be passed as an argument to all functions in the DECORATE parser. - Moved DECORATE parser files into their own subdirectory. - Optimization: SC_GetToken no longer sets sc_name for identifiers. In most cases this creates needless overhead by adding a potentially unneeded name to the name table and looking up the name. In almost all cases where a name is needed it's as easy to assign sc_String to the name variable. - Added enum definitions to DECORATE. SVN r537 (trunk)
This commit is contained in:
parent
91241eb96e
commit
50f75b6e8a
28 changed files with 3341 additions and 3191 deletions
|
@ -1,3 +1,17 @@
|
||||||
|
May 28, 2007 (Changes by Graf Zahl)
|
||||||
|
- Fixed: deadthings.txt contained a superfluous ';' which created parsing errors
|
||||||
|
with my changed code.
|
||||||
|
- Cleaned up DECORATE parser a little - moved the old style parsing code into its
|
||||||
|
own file and rearranged a few things.
|
||||||
|
- Made ProcessStates non-static so that it doesn't need to be passed as an argument
|
||||||
|
to all functions in the DECORATE parser.
|
||||||
|
- Moved DECORATE parser files into their own subdirectory.
|
||||||
|
- Optimization: SC_GetToken no longer sets sc_name for identifiers. In most cases
|
||||||
|
this creates needless overhead by adding a potentially unneeded name to the name
|
||||||
|
table and looking up the name. In almost all cases where a name is needed it's as
|
||||||
|
easy to assign sc_String to the name variable.
|
||||||
|
- Added enum definitions to DECORATE.
|
||||||
|
|
||||||
May 27, 2007 (Changes by Graf Zahl)
|
May 27, 2007 (Changes by Graf Zahl)
|
||||||
- Fixed: Hirestex replacements for sprites didn't work properly due to some
|
- Fixed: Hirestex replacements for sprites didn't work properly due to some
|
||||||
incorrect calculations in R_ProjectSprite.
|
incorrect calculations in R_ProjectSprite.
|
||||||
|
|
|
@ -63,7 +63,7 @@
|
||||||
#include "r_draw.h"
|
#include "r_draw.h"
|
||||||
#include "v_palette.h"
|
#include "v_palette.h"
|
||||||
#include "a_sharedglobal.h"
|
#include "a_sharedglobal.h"
|
||||||
#include "thingdef.h"
|
#include "thingdef/thingdef.h"
|
||||||
#include "vectors.h"
|
#include "vectors.h"
|
||||||
#include "dobject.h"
|
#include "dobject.h"
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
#include "p_effect.h"
|
#include "p_effect.h"
|
||||||
#include "gi.h"
|
#include "gi.h"
|
||||||
#include "templates.h"
|
#include "templates.h"
|
||||||
#include "thingdef.h"
|
#include "thingdef/thingdef.h"
|
||||||
|
|
||||||
static FRandom pr_punch ("Punch");
|
static FRandom pr_punch ("Punch");
|
||||||
static FRandom pr_saw ("Saw");
|
static FRandom pr_saw ("Saw");
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#include "p_enemy.h"
|
#include "p_enemy.h"
|
||||||
#include "gstrings.h"
|
#include "gstrings.h"
|
||||||
#include "a_action.h"
|
#include "a_action.h"
|
||||||
#include "thingdef.h"
|
#include "thingdef/thingdef.h"
|
||||||
|
|
||||||
//
|
//
|
||||||
// Mancubus attack,
|
// Mancubus attack,
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include "p_local.h"
|
#include "p_local.h"
|
||||||
#include "a_doomglobal.h"
|
#include "a_doomglobal.h"
|
||||||
#include "a_action.h"
|
#include "a_action.h"
|
||||||
#include "thingdef.h"
|
#include "thingdef/thingdef.h"
|
||||||
|
|
||||||
void A_PainAttack (AActor *);
|
void A_PainAttack (AActor *);
|
||||||
void A_PainDie (AActor *);
|
void A_PainDie (AActor *);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#include "actor.h"
|
#include "actor.h"
|
||||||
#include "thingdef.h"
|
#include "thingdef/thingdef.h"
|
||||||
#include "p_conversation.h"
|
#include "p_conversation.h"
|
||||||
#include "p_lnspec.h"
|
#include "p_lnspec.h"
|
||||||
#include "a_action.h"
|
#include "a_action.h"
|
||||||
|
|
|
@ -52,7 +52,7 @@
|
||||||
#include "templates.h"
|
#include "templates.h"
|
||||||
#include "cmdlib.h"
|
#include "cmdlib.h"
|
||||||
|
|
||||||
extern void LoadDecorations (void (*process)(FState *, int));
|
extern void LoadDecorations ();
|
||||||
|
|
||||||
// Each state is owned by an actor. Actors can own any number of
|
// Each state is owned by an actor. Actors can own any number of
|
||||||
// states, but a single state cannot be owned by more than one
|
// states, but a single state cannot be owned by more than one
|
||||||
|
@ -215,7 +215,7 @@ int GetSpriteIndex(const char * spritename)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
static void ProcessStates (FState *states, int numstates)
|
void ProcessStates (FState *states, int numstates)
|
||||||
{
|
{
|
||||||
int sprite = -1;
|
int sprite = -1;
|
||||||
|
|
||||||
|
@ -278,7 +278,7 @@ void FActorInfo::StaticInit ()
|
||||||
}
|
}
|
||||||
|
|
||||||
Printf ("LoadDecorations: Load external actors.\n");
|
Printf ("LoadDecorations: Load external actors.\n");
|
||||||
LoadDecorations (ProcessStates);
|
LoadDecorations ();
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
|
@ -453,6 +453,7 @@ extern FDoomEdMap DoomEdMap;
|
||||||
|
|
||||||
int GetSpriteIndex(const char * spritename);
|
int GetSpriteIndex(const char * spritename);
|
||||||
void MakeStateNameList(const char * fname, TArray<FName> * out);
|
void MakeStateNameList(const char * fname, TArray<FName> * out);
|
||||||
|
void ProcessStates (FState *states, int numstates);
|
||||||
|
|
||||||
#include "infomacros.h"
|
#include "infomacros.h"
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
#include "r_data.h"
|
#include "r_data.h"
|
||||||
#include "w_wad.h"
|
#include "w_wad.h"
|
||||||
#include "a_strifeglobal.h"
|
#include "a_strifeglobal.h"
|
||||||
#include "thingdef.h"
|
#include "thingdef/thingdef.h"
|
||||||
|
|
||||||
void FActorInfo::BuildDefaults ()
|
void FActorInfo::BuildDefaults ()
|
||||||
{
|
{
|
||||||
|
|
|
@ -43,7 +43,7 @@
|
||||||
#include "a_sharedglobal.h"
|
#include "a_sharedglobal.h"
|
||||||
#include "a_doomglobal.h"
|
#include "a_doomglobal.h"
|
||||||
#include "a_action.h"
|
#include "a_action.h"
|
||||||
#include "thingdef.h"
|
#include "thingdef/thingdef.h"
|
||||||
|
|
||||||
#include "gi.h"
|
#include "gi.h"
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@
|
||||||
#include "a_action.h"
|
#include "a_action.h"
|
||||||
#include "a_keys.h"
|
#include "a_keys.h"
|
||||||
#include "p_conversation.h"
|
#include "p_conversation.h"
|
||||||
#include "thingdef.h"
|
#include "thingdef/thingdef.h"
|
||||||
#include "g_game.h"
|
#include "g_game.h"
|
||||||
|
|
||||||
// MACROS ------------------------------------------------------------------
|
// MACROS ------------------------------------------------------------------
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
#include "p_effect.h"
|
#include "p_effect.h"
|
||||||
#include "a_doomglobal.h"
|
#include "a_doomglobal.h"
|
||||||
#include "templates.h"
|
#include "templates.h"
|
||||||
#include "thingdef.h"
|
#include "thingdef/thingdef.h"
|
||||||
|
|
||||||
// MACROS ------------------------------------------------------------------
|
// MACROS ------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@
|
||||||
#include "doomdef.h"
|
#include "doomdef.h"
|
||||||
#include "c_dispatch.h"
|
#include "c_dispatch.h"
|
||||||
#include "tarray.h"
|
#include "tarray.h"
|
||||||
#include "thingdef.h"
|
#include "thingdef/thingdef.h"
|
||||||
|
|
||||||
static FRandom pr_skullpop ("SkullPop");
|
static FRandom pr_skullpop ("SkullPop");
|
||||||
|
|
||||||
|
|
|
@ -1193,7 +1193,7 @@ void R_ProjectSprite (AActor *thing, int fakeside)
|
||||||
if (thing == NULL ||
|
if (thing == NULL ||
|
||||||
(thing->renderflags & RF_INVISIBLE) ||
|
(thing->renderflags & RF_INVISIBLE) ||
|
||||||
thing->RenderStyle == STYLE_None ||
|
thing->RenderStyle == STYLE_None ||
|
||||||
(thing->RenderStyle >= STYLE_Translucent && thing->alpha <= 0))
|
(thing->RenderStyle >= STYLE_Translucent && thing->alpha <= 0))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -390,7 +390,7 @@ bool SC_GetToken ()
|
||||||
{
|
{
|
||||||
if (SC_ScanString (true))
|
if (SC_ScanString (true))
|
||||||
{
|
{
|
||||||
if (sc_TokenType == TK_Identifier || sc_TokenType == TK_NameConst)
|
if (sc_TokenType == TK_NameConst)
|
||||||
{
|
{
|
||||||
sc_Name = FName(sc_String);
|
sc_Name = FName(sc_String);
|
||||||
}
|
}
|
||||||
|
@ -854,6 +854,10 @@ FString SC_TokenName (int token, const char *string)
|
||||||
"'stop'",
|
"'stop'",
|
||||||
"'eval'",
|
"'eval'",
|
||||||
"'evalnot'",
|
"'evalnot'",
|
||||||
|
"'pickup'",
|
||||||
|
"'breakable'",
|
||||||
|
"'projectile'",
|
||||||
|
"'#include'",
|
||||||
};
|
};
|
||||||
|
|
||||||
FString work;
|
FString work;
|
||||||
|
|
|
@ -145,6 +145,10 @@ enum
|
||||||
TK_Stop,
|
TK_Stop,
|
||||||
TK_Eval,
|
TK_Eval,
|
||||||
TK_EvalNot,
|
TK_EvalNot,
|
||||||
|
TK_Pickup,
|
||||||
|
TK_Breakable,
|
||||||
|
TK_Projectile,
|
||||||
|
TK_Include,
|
||||||
|
|
||||||
TK_LastToken
|
TK_LastToken
|
||||||
};
|
};
|
||||||
|
|
5530
src/sc_man_scanner.h
5530
src/sc_man_scanner.h
File diff suppressed because it is too large
Load diff
|
@ -143,6 +143,12 @@ std2:
|
||||||
'evalnot' { RET(TK_EvalNot); }
|
'evalnot' { RET(TK_EvalNot); }
|
||||||
'action' { RET(TK_Action); }
|
'action' { RET(TK_Action); }
|
||||||
|
|
||||||
|
/* other DECORATE top level keywords */
|
||||||
|
'#include' { RET(TK_Include); }
|
||||||
|
'pickup' { RET(TK_Pickup); }
|
||||||
|
'breakable' { RET(TK_Breakable); }
|
||||||
|
'projectile' { RET(TK_Projectile); }
|
||||||
|
|
||||||
L (L|D)* { RET(TK_Identifier); }
|
L (L|D)* { RET(TK_Identifier); }
|
||||||
|
|
||||||
("0" [xX] H+ IS?) | ("0" D+ IS?) | (D+ IS?)
|
("0" [xX] H+ IS?) | ("0" D+ IS?) | (D+ IS?)
|
||||||
|
|
|
@ -38,7 +38,6 @@
|
||||||
#include "info.h"
|
#include "info.h"
|
||||||
#include "sc_man.h"
|
#include "sc_man.h"
|
||||||
#include "tarray.h"
|
#include "tarray.h"
|
||||||
#include "w_wad.h"
|
|
||||||
#include "templates.h"
|
#include "templates.h"
|
||||||
#include "r_defs.h"
|
#include "r_defs.h"
|
||||||
#include "r_draw.h"
|
#include "r_draw.h"
|
||||||
|
@ -53,18 +52,8 @@
|
||||||
#include "thingdef.h"
|
#include "thingdef.h"
|
||||||
#include "vectors.h"
|
#include "vectors.h"
|
||||||
|
|
||||||
// MACROS ------------------------------------------------------------------
|
|
||||||
|
|
||||||
// TYPES -------------------------------------------------------------------
|
// TYPES -------------------------------------------------------------------
|
||||||
|
|
||||||
enum EDefinitionType
|
|
||||||
{
|
|
||||||
DEF_Decoration,
|
|
||||||
DEF_BreakableDecoration,
|
|
||||||
DEF_Pickup,
|
|
||||||
DEF_Projectile,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FExtraInfo
|
struct FExtraInfo
|
||||||
{
|
{
|
||||||
char DeathSprite[5];
|
char DeathSprite[5];
|
||||||
|
@ -111,14 +100,6 @@ IMPLEMENT_STATELESS_ACTOR (AFakeInventory, Any, -1, 0)
|
||||||
PROP_Flags (MF_SPECIAL)
|
PROP_Flags (MF_SPECIAL)
|
||||||
END_DEFAULTS
|
END_DEFAULTS
|
||||||
|
|
||||||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
|
||||||
|
|
||||||
void ProcessActor(void (*process)(FState *, int));
|
|
||||||
void ParseClass();
|
|
||||||
void ParseGlobalConst();
|
|
||||||
void FinishThingdef();
|
|
||||||
void InitDecorateTranslations();
|
|
||||||
|
|
||||||
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
||||||
|
|
||||||
void A_ScreamAndUnblock (AActor *);
|
void A_ScreamAndUnblock (AActor *);
|
||||||
|
@ -127,17 +108,10 @@ void A_ActiveSound (AActor *);
|
||||||
|
|
||||||
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
||||||
|
|
||||||
static void ParseDecorate (void (*process)(FState *, int));
|
|
||||||
static void ParseInsideDecoration (FActorInfo *info, AActor *defaults,
|
static void ParseInsideDecoration (FActorInfo *info, AActor *defaults,
|
||||||
TArray<FState> &states, FExtraInfo &extra, EDefinitionType def);
|
TArray<FState> &states, FExtraInfo &extra, EDefinitionType def);
|
||||||
static void ParseSpriteFrames (FActorInfo *info, TArray<FState> &states);
|
static void ParseSpriteFrames (FActorInfo *info, TArray<FState> &states);
|
||||||
|
|
||||||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
|
||||||
|
|
||||||
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
|
||||||
|
|
||||||
TArray<FActorInfo *> Decorations;
|
|
||||||
|
|
||||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||||
|
|
||||||
static const char *RenderStyles[] =
|
static const char *RenderStyles[] =
|
||||||
|
@ -248,332 +222,255 @@ static const char *FlagNames3[] =
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// LoadDecorations
|
// ParseOldDecoration
|
||||||
//
|
//
|
||||||
// Called from FActor::StaticInit()
|
// Reads an old style decoration object
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void LoadDecorations (void (*process)(FState *, int))
|
void ParseOldDecoration(EDefinitionType def)
|
||||||
{
|
|
||||||
int lastlump, lump;
|
|
||||||
|
|
||||||
InitDecorateTranslations();
|
|
||||||
lastlump = 0;
|
|
||||||
while ((lump = Wads.FindLump ("DECORATE", &lastlump)) != -1)
|
|
||||||
{
|
|
||||||
SC_OpenLumpNum (lump, Wads.GetLumpFullName(lump));
|
|
||||||
ParseDecorate (process);
|
|
||||||
SC_Close ();
|
|
||||||
}
|
|
||||||
FinishThingdef();
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// ParseDecorate
|
|
||||||
//
|
|
||||||
// Parses a single DECORATE lump
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
static void ParseDecorate (void (*process)(FState *, int))
|
|
||||||
{
|
{
|
||||||
TArray<FState> states;
|
TArray<FState> states;
|
||||||
FExtraInfo extra;
|
FExtraInfo extra;
|
||||||
PClass *type;
|
PClass *type;
|
||||||
PClass *parent;
|
PClass *parent;
|
||||||
EDefinitionType def;
|
|
||||||
FActorInfo *info;
|
FActorInfo *info;
|
||||||
FName typeName;
|
FName typeName;
|
||||||
int recursion=0;
|
|
||||||
|
|
||||||
// Get actor class name.
|
if (def == DEF_Pickup) parent = RUNTIME_CLASS(AFakeInventory);
|
||||||
while (true)
|
else parent = RUNTIME_CLASS(AActor);
|
||||||
|
|
||||||
|
SC_MustGetString();
|
||||||
|
typeName = FName(sc_String);
|
||||||
|
type = parent->CreateDerivedClass (typeName, parent->Size);
|
||||||
|
info = type->ActorInfo;
|
||||||
|
info->GameFilter = 0x80;
|
||||||
|
MakeStateDefines(parent->ActorInfo->StateList);
|
||||||
|
|
||||||
|
SC_MustGetString ();
|
||||||
|
while (!SC_Compare ("{"))
|
||||||
{
|
{
|
||||||
if (!SC_GetString ())
|
if (SC_Compare ("Doom"))
|
||||||
{
|
{
|
||||||
if (recursion==0) return;
|
info->GameFilter |= GAME_Doom;
|
||||||
SC_Close();
|
|
||||||
SC_RestoreScriptState();
|
|
||||||
recursion--;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
if (SC_Compare ("#include"))
|
else if (SC_Compare ("Heretic"))
|
||||||
{
|
{
|
||||||
int lump;
|
info->GameFilter |= GAME_Heretic;
|
||||||
|
|
||||||
SC_MustGetString();
|
|
||||||
// This is not using SC_Open because it can print a more useful error message when done here
|
|
||||||
lump = Wads.CheckNumForFullName(sc_String);
|
|
||||||
if (lump==-1) lump = Wads.CheckNumForName(sc_String);
|
|
||||||
if (lump==-1) SC_ScriptError("Lump '%s' not found", sc_String);
|
|
||||||
SC_SaveScriptState();
|
|
||||||
SC_OpenLumpNum(lump, sc_String);
|
|
||||||
recursion++;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
if (SC_Compare ("Actor"))
|
else if (SC_Compare ("Hexen"))
|
||||||
{
|
{
|
||||||
ProcessActor (process);
|
info->GameFilter |= GAME_Hexen;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
if (SC_Compare ("Pickup"))
|
else if (SC_Compare ("Raven"))
|
||||||
{
|
{
|
||||||
parent = RUNTIME_CLASS(AFakeInventory);
|
info->GameFilter |= GAME_Raven;
|
||||||
def = DEF_Pickup;
|
|
||||||
SC_MustGetString ();
|
|
||||||
}
|
}
|
||||||
else if (SC_Compare ("Breakable"))
|
else if (SC_Compare ("Strife"))
|
||||||
{
|
{
|
||||||
parent = RUNTIME_CLASS(AActor);
|
info->GameFilter |= GAME_Strife;
|
||||||
def = DEF_BreakableDecoration;
|
|
||||||
SC_MustGetString ();
|
|
||||||
}
|
}
|
||||||
else if (SC_Compare ("Projectile"))
|
else if (SC_Compare ("Any"))
|
||||||
{
|
|
||||||
parent = RUNTIME_CLASS(AActor);
|
|
||||||
def = DEF_Projectile;
|
|
||||||
SC_MustGetString ();
|
|
||||||
}
|
|
||||||
else if (SC_Compare ("class"))
|
|
||||||
{
|
|
||||||
ParseClass();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if (SC_Compare ("Const"))
|
|
||||||
{
|
|
||||||
ParseGlobalConst();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
parent = RUNTIME_CLASS(AActor);
|
|
||||||
def = DEF_Decoration;
|
|
||||||
}
|
|
||||||
|
|
||||||
typeName = FName(sc_String);
|
|
||||||
type = parent->CreateDerivedClass (typeName, parent->Size);
|
|
||||||
info = type->ActorInfo;
|
|
||||||
info->GameFilter = 0x80;
|
|
||||||
Decorations.Push (info);
|
|
||||||
MakeStateDefines(parent->ActorInfo->StateList);
|
|
||||||
|
|
||||||
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
|
|
||||||
{
|
|
||||||
SC_ScriptError ("Unknown game type %s", sc_String);
|
|
||||||
}
|
|
||||||
SC_MustGetString ();
|
|
||||||
}
|
|
||||||
if (info->GameFilter == 0x80)
|
|
||||||
{
|
{
|
||||||
info->GameFilter = GAME_Any;
|
info->GameFilter = GAME_Any;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
info->GameFilter &= ~0x80;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
states.Clear ();
|
states.Clear ();
|
||||||
memset (&extra, 0, sizeof(extra));
|
memset (&extra, 0, sizeof(extra));
|
||||||
ParseInsideDecoration (info, (AActor *)(type->Defaults), states, extra, def);
|
ParseInsideDecoration (info, (AActor *)(type->Defaults), states, extra, def);
|
||||||
|
|
||||||
info->NumOwnedStates = states.Size();
|
info->NumOwnedStates = states.Size();
|
||||||
if (info->NumOwnedStates == 0)
|
if (info->NumOwnedStates == 0)
|
||||||
{
|
{
|
||||||
SC_ScriptError ("%s does not define any animation frames", typeName.GetChars() );
|
SC_ScriptError ("%s does not define any animation frames", typeName.GetChars() );
|
||||||
}
|
}
|
||||||
else if (extra.SpawnEnd == 0)
|
else if (extra.SpawnEnd == 0)
|
||||||
{
|
{
|
||||||
SC_ScriptError ("%s does not have a Frames definition", typeName.GetChars() );
|
SC_ScriptError ("%s does not have a Frames definition", typeName.GetChars() );
|
||||||
}
|
}
|
||||||
else if (def == DEF_BreakableDecoration && extra.DeathEnd == 0)
|
else if (def == DEF_BreakableDecoration && extra.DeathEnd == 0)
|
||||||
{
|
{
|
||||||
SC_ScriptError ("%s does not have a DeathFrames definition", typeName.GetChars() );
|
SC_ScriptError ("%s does not have a DeathFrames definition", typeName.GetChars() );
|
||||||
}
|
}
|
||||||
else if (extra.IceDeathEnd != 0 && extra.bGenericIceDeath)
|
else if (extra.IceDeathEnd != 0 && extra.bGenericIceDeath)
|
||||||
{
|
{
|
||||||
SC_ScriptError ("You cannot use IceDeathFrames and GenericIceDeath together");
|
SC_ScriptError ("You cannot use IceDeathFrames and GenericIceDeath together");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (extra.IceDeathEnd != 0)
|
if (extra.IceDeathEnd != 0)
|
||||||
{
|
{
|
||||||
// Make a copy of the final frozen frame for A_FreezeDeathChunks
|
// Make a copy of the final frozen frame for A_FreezeDeathChunks
|
||||||
FState icecopy = states[extra.IceDeathEnd-1];
|
FState icecopy = states[extra.IceDeathEnd-1];
|
||||||
states.Push (icecopy);
|
states.Push (icecopy);
|
||||||
info->NumOwnedStates += 1;
|
info->NumOwnedStates += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
info->OwnedStates = new FState[info->NumOwnedStates];
|
info->OwnedStates = new FState[info->NumOwnedStates];
|
||||||
memcpy (info->OwnedStates, &states[0], info->NumOwnedStates * sizeof(info->OwnedStates[0]));
|
memcpy (info->OwnedStates, &states[0], info->NumOwnedStates * sizeof(info->OwnedStates[0]));
|
||||||
if (info->NumOwnedStates == 1)
|
if (info->NumOwnedStates == 1)
|
||||||
{
|
{
|
||||||
info->OwnedStates->Tics = 0;
|
info->OwnedStates->Tics = 0;
|
||||||
info->OwnedStates->Misc1 = 0;
|
info->OwnedStates->Misc1 = 0;
|
||||||
info->OwnedStates->Frame &= ~SF_BIGTIC;
|
info->OwnedStates->Frame &= ~SF_BIGTIC;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
// Spawn states loop endlessly
|
// Spawn states loop endlessly
|
||||||
for (i = extra.SpawnStart; i < extra.SpawnEnd-1; ++i)
|
for (i = extra.SpawnStart; i < extra.SpawnEnd-1; ++i)
|
||||||
|
{
|
||||||
|
info->OwnedStates[i].NextState = &info->OwnedStates[i+1];
|
||||||
|
}
|
||||||
|
info->OwnedStates[i].NextState = &info->OwnedStates[extra.SpawnStart];
|
||||||
|
|
||||||
|
// Death states are one-shot and freeze on the final state
|
||||||
|
if (extra.DeathEnd != 0)
|
||||||
|
{
|
||||||
|
for (i = extra.DeathStart; i < extra.DeathEnd-1; ++i)
|
||||||
{
|
{
|
||||||
info->OwnedStates[i].NextState = &info->OwnedStates[i+1];
|
info->OwnedStates[i].NextState = &info->OwnedStates[i+1];
|
||||||
}
|
}
|
||||||
info->OwnedStates[i].NextState = &info->OwnedStates[extra.SpawnStart];
|
if (extra.bDiesAway || def == DEF_Projectile)
|
||||||
|
|
||||||
// Death states are one-shot and freeze on the final state
|
|
||||||
if (extra.DeathEnd != 0)
|
|
||||||
{
|
{
|
||||||
for (i = extra.DeathStart; i < extra.DeathEnd-1; ++i)
|
info->OwnedStates[i].NextState = NULL;
|
||||||
{
|
}
|
||||||
info->OwnedStates[i].NextState = &info->OwnedStates[i+1];
|
else
|
||||||
}
|
{
|
||||||
if (extra.bDiesAway || def == DEF_Projectile)
|
info->OwnedStates[i].Tics = 0;
|
||||||
{
|
info->OwnedStates[i].Misc1 = 0;
|
||||||
info->OwnedStates[i].NextState = NULL;
|
info->OwnedStates[i].Frame &= ~SF_BIGTIC;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
info->OwnedStates[i].Tics = 0;
|
|
||||||
info->OwnedStates[i].Misc1 = 0;
|
|
||||||
info->OwnedStates[i].Frame &= ~SF_BIGTIC;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (def == DEF_Projectile)
|
|
||||||
{
|
|
||||||
if (extra.bExplosive)
|
|
||||||
{
|
|
||||||
info->OwnedStates[extra.DeathStart].Action = A_ExplodeParms;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// The first frame plays the death sound and
|
|
||||||
// the second frame makes it nonsolid.
|
|
||||||
info->OwnedStates[extra.DeathStart].Action= A_Scream;
|
|
||||||
if (extra.bSolidOnDeath)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
else if (extra.DeathStart + 1 < extra.DeathEnd)
|
|
||||||
{
|
|
||||||
info->OwnedStates[extra.DeathStart+1].Action = A_NoBlocking;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
info->OwnedStates[extra.DeathStart].Action = A_ScreamAndUnblock;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (extra.DeathHeight == 0) extra.DeathHeight = ((AActor*)(type->Defaults))->height;
|
|
||||||
info->Class->Meta.SetMetaFixed (AMETA_DeathHeight, extra.DeathHeight);
|
|
||||||
}
|
|
||||||
AddState("Death", &info->OwnedStates[extra.DeathStart]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Burn states are the same as death states, except they can optionally terminate
|
if (def == DEF_Projectile)
|
||||||
if (extra.FireDeathEnd != 0)
|
|
||||||
{
|
{
|
||||||
for (i = extra.FireDeathStart; i < extra.FireDeathEnd-1; ++i)
|
if (extra.bExplosive)
|
||||||
{
|
{
|
||||||
info->OwnedStates[i].NextState = &info->OwnedStates[i+1];
|
info->OwnedStates[extra.DeathStart].Action = A_ExplodeParms;
|
||||||
}
|
}
|
||||||
if (extra.bBurnAway)
|
}
|
||||||
{
|
else
|
||||||
info->OwnedStates[i].NextState = NULL;
|
{
|
||||||
}
|
// The first frame plays the death sound and
|
||||||
else
|
|
||||||
{
|
|
||||||
info->OwnedStates[i].Tics = 0;
|
|
||||||
info->OwnedStates[i].Misc1 = 0;
|
|
||||||
info->OwnedStates[i].Frame &= ~SF_BIGTIC;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The first frame plays the burn sound and
|
|
||||||
// the second frame makes it nonsolid.
|
// the second frame makes it nonsolid.
|
||||||
info->OwnedStates[extra.FireDeathStart].Action = A_ActiveSound;
|
info->OwnedStates[extra.DeathStart].Action= A_Scream;
|
||||||
if (extra.bSolidOnBurn)
|
if (extra.bSolidOnDeath)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
else if (extra.FireDeathStart + 1 < extra.FireDeathEnd)
|
else if (extra.DeathStart + 1 < extra.DeathEnd)
|
||||||
{
|
{
|
||||||
info->OwnedStates[extra.FireDeathStart+1].Action = A_NoBlocking;
|
info->OwnedStates[extra.DeathStart+1].Action = A_NoBlocking;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
info->OwnedStates[extra.FireDeathStart].Action = A_ActiveAndUnblock;
|
info->OwnedStates[extra.DeathStart].Action = A_ScreamAndUnblock;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (extra.BurnHeight == 0) extra.BurnHeight = ((AActor*)(type->Defaults))->height;
|
if (extra.DeathHeight == 0) extra.DeathHeight = ((AActor*)(type->Defaults))->height;
|
||||||
type->Meta.SetMetaFixed (AMETA_BurnHeight, extra.BurnHeight);
|
info->Class->Meta.SetMetaFixed (AMETA_DeathHeight, extra.DeathHeight);
|
||||||
|
|
||||||
AddState("Burn", &info->OwnedStates[extra.FireDeathStart]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ice states are similar to burn and death, except their final frame enters
|
|
||||||
// a loop that eventually causes them to bust to pieces.
|
|
||||||
if (extra.IceDeathEnd != 0)
|
|
||||||
{
|
|
||||||
for (i = extra.IceDeathStart; i < extra.IceDeathEnd-1; ++i)
|
|
||||||
{
|
|
||||||
info->OwnedStates[i].NextState = &info->OwnedStates[i+1];
|
|
||||||
}
|
|
||||||
info->OwnedStates[i].NextState = &info->OwnedStates[info->NumOwnedStates-1];
|
|
||||||
info->OwnedStates[i].Tics = 6;
|
|
||||||
info->OwnedStates[i].Misc1 = 0;
|
|
||||||
info->OwnedStates[i].Action = A_FreezeDeath;
|
|
||||||
|
|
||||||
i = info->NumOwnedStates - 1;
|
|
||||||
info->OwnedStates[i].NextState = &info->OwnedStates[i];
|
|
||||||
info->OwnedStates[i].Tics = 2;
|
|
||||||
info->OwnedStates[i].Misc1 = 0;
|
|
||||||
info->OwnedStates[i].Action = A_FreezeDeathChunks;
|
|
||||||
AddState("Ice", &info->OwnedStates[extra.IceDeathStart]);
|
|
||||||
}
|
|
||||||
else if (extra.bGenericIceDeath)
|
|
||||||
{
|
|
||||||
AddState("Ice", &AActor::States[AActor::S_GENERICFREEZEDEATH]);
|
|
||||||
}
|
}
|
||||||
|
AddState("Death", &info->OwnedStates[extra.DeathStart]);
|
||||||
}
|
}
|
||||||
if (def == DEF_BreakableDecoration)
|
|
||||||
|
// Burn states are the same as death states, except they can optionally terminate
|
||||||
|
if (extra.FireDeathEnd != 0)
|
||||||
{
|
{
|
||||||
((AActor *)(type->Defaults))->flags |= MF_SHOOTABLE;
|
for (i = extra.FireDeathStart; i < extra.FireDeathEnd-1; ++i)
|
||||||
|
{
|
||||||
|
info->OwnedStates[i].NextState = &info->OwnedStates[i+1];
|
||||||
|
}
|
||||||
|
if (extra.bBurnAway)
|
||||||
|
{
|
||||||
|
info->OwnedStates[i].NextState = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
info->OwnedStates[i].Tics = 0;
|
||||||
|
info->OwnedStates[i].Misc1 = 0;
|
||||||
|
info->OwnedStates[i].Frame &= ~SF_BIGTIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The first frame plays the burn sound and
|
||||||
|
// the second frame makes it nonsolid.
|
||||||
|
info->OwnedStates[extra.FireDeathStart].Action = A_ActiveSound;
|
||||||
|
if (extra.bSolidOnBurn)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
else if (extra.FireDeathStart + 1 < extra.FireDeathEnd)
|
||||||
|
{
|
||||||
|
info->OwnedStates[extra.FireDeathStart+1].Action = A_NoBlocking;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
info->OwnedStates[extra.FireDeathStart].Action = A_ActiveAndUnblock;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extra.BurnHeight == 0) extra.BurnHeight = ((AActor*)(type->Defaults))->height;
|
||||||
|
type->Meta.SetMetaFixed (AMETA_BurnHeight, extra.BurnHeight);
|
||||||
|
|
||||||
|
AddState("Burn", &info->OwnedStates[extra.FireDeathStart]);
|
||||||
}
|
}
|
||||||
if (def == DEF_Projectile)
|
|
||||||
|
// Ice states are similar to burn and death, except their final frame enters
|
||||||
|
// a loop that eventually causes them to bust to pieces.
|
||||||
|
if (extra.IceDeathEnd != 0)
|
||||||
{
|
{
|
||||||
((AActor *)(type->Defaults))->flags |= MF_DROPOFF|MF_MISSILE;
|
for (i = extra.IceDeathStart; i < extra.IceDeathEnd-1; ++i)
|
||||||
|
{
|
||||||
|
info->OwnedStates[i].NextState = &info->OwnedStates[i+1];
|
||||||
|
}
|
||||||
|
info->OwnedStates[i].NextState = &info->OwnedStates[info->NumOwnedStates-1];
|
||||||
|
info->OwnedStates[i].Tics = 6;
|
||||||
|
info->OwnedStates[i].Misc1 = 0;
|
||||||
|
info->OwnedStates[i].Action = A_FreezeDeath;
|
||||||
|
|
||||||
|
i = info->NumOwnedStates - 1;
|
||||||
|
info->OwnedStates[i].NextState = &info->OwnedStates[i];
|
||||||
|
info->OwnedStates[i].Tics = 2;
|
||||||
|
info->OwnedStates[i].Misc1 = 0;
|
||||||
|
info->OwnedStates[i].Action = A_FreezeDeathChunks;
|
||||||
|
AddState("Ice", &info->OwnedStates[extra.IceDeathStart]);
|
||||||
|
}
|
||||||
|
else if (extra.bGenericIceDeath)
|
||||||
|
{
|
||||||
|
AddState("Ice", &AActor::States[AActor::S_GENERICFREEZEDEATH]);
|
||||||
}
|
}
|
||||||
AddState("Spawn", &info->OwnedStates[extra.SpawnStart]);
|
|
||||||
InstallStates(info, ((AActor *)(type->Defaults)));
|
|
||||||
process (info->OwnedStates, info->NumOwnedStates);
|
|
||||||
}
|
}
|
||||||
|
if (def == DEF_BreakableDecoration)
|
||||||
|
{
|
||||||
|
((AActor *)(type->Defaults))->flags |= MF_SHOOTABLE;
|
||||||
|
}
|
||||||
|
if (def == DEF_Projectile)
|
||||||
|
{
|
||||||
|
((AActor *)(type->Defaults))->flags |= MF_DROPOFF|MF_MISSILE;
|
||||||
|
}
|
||||||
|
AddState("Spawn", &info->OwnedStates[extra.SpawnStart]);
|
||||||
|
InstallStates (info, ((AActor *)(type->Defaults)));
|
||||||
|
ProcessStates (info->OwnedStates, info->NumOwnedStates);
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
|
@ -73,8 +73,6 @@
|
||||||
const PClass *QuestItemClasses[31];
|
const PClass *QuestItemClasses[31];
|
||||||
|
|
||||||
|
|
||||||
extern TArray<FActorInfo *> Decorations;
|
|
||||||
|
|
||||||
// allow decal specifications in DECORATE. Decals are loaded after DECORATE so the names must be stored here.
|
// allow decal specifications in DECORATE. Decals are loaded after DECORATE so the names must be stored here.
|
||||||
TArray<char*> DecalNames;
|
TArray<char*> DecalNames;
|
||||||
// all state parameters
|
// all state parameters
|
||||||
|
@ -1169,7 +1167,6 @@ static FActorInfo * CreateNewActor(FActorInfo ** parentc, Baggage *bag)
|
||||||
PClass * ti = parent->CreateDerivedClass (typeName, parent->Size);
|
PClass * ti = parent->CreateDerivedClass (typeName, parent->Size);
|
||||||
FActorInfo * info = ti->ActorInfo;
|
FActorInfo * info = ti->ActorInfo;
|
||||||
|
|
||||||
Decorations.Push (info);
|
|
||||||
MakeStateDefines(parent->ActorInfo->StateList);
|
MakeStateDefines(parent->ActorInfo->StateList);
|
||||||
|
|
||||||
ResetBaggage (bag);
|
ResetBaggage (bag);
|
||||||
|
@ -2150,7 +2147,7 @@ void ParseActorProperties (Baggage &bag)
|
||||||
// Reads an actor definition
|
// Reads an actor definition
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
void ProcessActor(void (*process)(FState *, int))
|
void ProcessActor()
|
||||||
{
|
{
|
||||||
FActorInfo * info=NULL;
|
FActorInfo * info=NULL;
|
||||||
AActor * defaults;
|
AActor * defaults;
|
||||||
|
@ -2169,8 +2166,8 @@ void ProcessActor(void (*process)(FState *, int))
|
||||||
|
|
||||||
ParseActorProperties (bag);
|
ParseActorProperties (bag);
|
||||||
FinishStates (info, defaults, bag);
|
FinishStates (info, defaults, bag);
|
||||||
InstallStates(info, defaults);
|
InstallStates (info, defaults);
|
||||||
process(info->OwnedStates, info->NumOwnedStates);
|
ProcessStates (info->OwnedStates, info->NumOwnedStates);
|
||||||
if (bag.DropItemSet)
|
if (bag.DropItemSet)
|
||||||
{
|
{
|
||||||
if (bag.DropItemList == NULL)
|
if (bag.DropItemList == NULL)
|
||||||
|
@ -2252,7 +2249,7 @@ static void ActorConstDef (AActor *defaults, Baggage &bag)
|
||||||
// (Maybe there will be other types later.)
|
// (Maybe there will be other types later.)
|
||||||
SC_MustGetToken(TK_Int);
|
SC_MustGetToken(TK_Int);
|
||||||
SC_MustGetToken(TK_Identifier);
|
SC_MustGetToken(TK_Identifier);
|
||||||
FName symname = sc_Name;
|
FName symname = sc_String;
|
||||||
SC_MustGetToken('=');
|
SC_MustGetToken('=');
|
||||||
int expr = ParseExpression (false, bag.Info->Class);
|
int expr = ParseExpression (false, bag.Info->Class);
|
||||||
SC_MustGetToken(';');
|
SC_MustGetToken(';');
|
||||||
|
@ -2270,6 +2267,46 @@ static void ActorConstDef (AActor *defaults, Baggage &bag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// ActorEnumDef
|
||||||
|
//
|
||||||
|
// Parses an enum definition.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
static void ActorEnumDef (AActor *defaults, Baggage &bag)
|
||||||
|
{
|
||||||
|
int currvalue = 0;
|
||||||
|
|
||||||
|
SC_MustGetToken('{');
|
||||||
|
while (!SC_CheckToken('}'))
|
||||||
|
{
|
||||||
|
SC_MustGetToken(TK_Identifier);
|
||||||
|
FName symname = sc_String;
|
||||||
|
if (SC_CheckToken('='))
|
||||||
|
{
|
||||||
|
int expr = ParseExpression(false, bag.Info->Class);
|
||||||
|
currvalue = EvalExpressionI (expr, NULL, bag.Info->Class);
|
||||||
|
}
|
||||||
|
PSymbolConst *sym = new PSymbolConst;
|
||||||
|
sym->SymbolName = symname;
|
||||||
|
sym->SymbolType = SYM_Const;
|
||||||
|
sym->Value = currvalue;
|
||||||
|
if (bag.Info->Class->Symbols.AddSymbol (sym) == NULL)
|
||||||
|
{
|
||||||
|
delete sym;
|
||||||
|
SC_ScriptError ("'%s' is already defined in class '%s'.",
|
||||||
|
symname.GetChars(), bag.Info->Class->TypeName.GetChars());
|
||||||
|
}
|
||||||
|
// This allows a comma after the last value but doesn't enforce it.
|
||||||
|
if (SC_CheckToken('}')) break;
|
||||||
|
SC_MustGetToken(',');
|
||||||
|
currvalue++;
|
||||||
|
}
|
||||||
|
SC_MustGetToken(';');
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// ParseGlobalConst
|
// ParseGlobalConst
|
||||||
|
@ -2287,6 +2324,14 @@ void ParseGlobalConst()
|
||||||
ActorConstDef(GetDefault<AActor>(), bag);
|
ActorConstDef(GetDefault<AActor>(), bag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ParseGlobalEnum()
|
||||||
|
{
|
||||||
|
Baggage bag;
|
||||||
|
|
||||||
|
bag.Info = RUNTIME_CLASS(AActor)->ActorInfo;
|
||||||
|
ActorEnumDef(GetDefault<AActor>(), bag);
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// ActorActionDef
|
// ActorActionDef
|
||||||
|
@ -2309,7 +2354,7 @@ static void ActorActionDef (AActor *defaults, Baggage &bag)
|
||||||
|
|
||||||
SC_MustGetToken(TK_Native);
|
SC_MustGetToken(TK_Native);
|
||||||
SC_MustGetToken(TK_Identifier);
|
SC_MustGetToken(TK_Identifier);
|
||||||
funcname = sc_Name;
|
funcname = sc_String;
|
||||||
afd = FindFunction(sc_String);
|
afd = FindFunction(sc_String);
|
||||||
if (afd == NULL)
|
if (afd == NULL)
|
||||||
{
|
{
|
||||||
|
@ -4177,6 +4222,7 @@ static const ActorProps props[] =
|
||||||
{ "disintegrate", ActorDisintegrateState, RUNTIME_CLASS(AActor) },
|
{ "disintegrate", ActorDisintegrateState, RUNTIME_CLASS(AActor) },
|
||||||
{ "donthurtshooter", ActorDontHurtShooter, RUNTIME_CLASS(AActor) },
|
{ "donthurtshooter", ActorDontHurtShooter, RUNTIME_CLASS(AActor) },
|
||||||
{ "dropitem", ActorDropItem, RUNTIME_CLASS(AActor) },
|
{ "dropitem", ActorDropItem, RUNTIME_CLASS(AActor) },
|
||||||
|
{ "enum", ActorEnumDef, RUNTIME_CLASS(AActor) },
|
||||||
{ "explosiondamage", ActorExplosionDamage, RUNTIME_CLASS(AActor) },
|
{ "explosiondamage", ActorExplosionDamage, RUNTIME_CLASS(AActor) },
|
||||||
{ "explosionradius", ActorExplosionRadius, RUNTIME_CLASS(AActor) },
|
{ "explosionradius", ActorExplosionRadius, RUNTIME_CLASS(AActor) },
|
||||||
{ "fastspeed", ActorFastSpeed, RUNTIME_CLASS(AActor) },
|
{ "fastspeed", ActorFastSpeed, RUNTIME_CLASS(AActor) },
|
||||||
|
@ -4449,10 +4495,10 @@ void ParseClass()
|
||||||
FName supername;
|
FName supername;
|
||||||
|
|
||||||
SC_MustGetToken(TK_Identifier); // class name
|
SC_MustGetToken(TK_Identifier); // class name
|
||||||
classname = sc_Name;
|
classname = sc_String;
|
||||||
SC_MustGetToken(TK_Extends); // because I'm not supporting Object
|
SC_MustGetToken(TK_Extends); // because I'm not supporting Object
|
||||||
SC_MustGetToken(TK_Identifier); // superclass name
|
SC_MustGetToken(TK_Identifier); // superclass name
|
||||||
supername = sc_Name;
|
supername = sc_String;
|
||||||
SC_MustGetToken(TK_Native); // use actor definitions for your own stuff
|
SC_MustGetToken(TK_Native); // use actor definitions for your own stuff
|
||||||
SC_MustGetToken('{');
|
SC_MustGetToken('{');
|
||||||
|
|
||||||
|
@ -4478,190 +4524,15 @@ void ParseClass()
|
||||||
{
|
{
|
||||||
ActorConstDef (0, bag);
|
ActorConstDef (0, bag);
|
||||||
}
|
}
|
||||||
|
else if (sc_TokenType == TK_Enum)
|
||||||
|
{
|
||||||
|
ActorEnumDef (0, bag);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FString tokname = SC_TokenName(sc_TokenType, sc_String);
|
FString tokname = SC_TokenName(sc_TokenType, sc_String);
|
||||||
SC_ScriptError ("Expected 'action' or 'const' but got %s", tokname.GetChars());
|
SC_ScriptError ("Expected 'action', 'const' or 'enum' but got %s", tokname.GetChars());
|
||||||
}
|
}
|
||||||
SC_MustGetAnyToken();
|
SC_MustGetAnyToken();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool ParseFunctionCall(Baggage &bag, FState & state)
|
|
||||||
{
|
|
||||||
// Make the action name lowercase to satisfy the gperf hashers
|
|
||||||
strlwr (sc_String);
|
|
||||||
FString funcname = sc_String;
|
|
||||||
|
|
||||||
int minreq=0;
|
|
||||||
memset(&state, 0, sizeof(state));
|
|
||||||
if (DoSpecialFunctions(state, false, &minreq, bag))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
PSymbol *sym = bag.Info->Class->Symbols.FindSymbol (FName(sc_String, true), true);
|
|
||||||
if (sym != NULL && sym->SymbolType == SYM_ActionFunction)
|
|
||||||
{
|
|
||||||
PSymbolActionFunction *afd = static_cast<PSymbolActionFunction *>(sym);
|
|
||||||
state.Action = afd->Function;
|
|
||||||
if (!afd->Arguments.IsEmpty())
|
|
||||||
{
|
|
||||||
const char *params = afd->Arguments.GetChars();
|
|
||||||
int numparams = (int)afd->Arguments.Len();
|
|
||||||
|
|
||||||
int v;
|
|
||||||
|
|
||||||
if (!islower(*params))
|
|
||||||
{
|
|
||||||
SC_MustGetToken('(');
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!SC_CheckToken('('))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int paramindex = PrepareStateParameters(&state, numparams);
|
|
||||||
int paramstart = paramindex;
|
|
||||||
bool varargs = params[numparams - 1] == '+';
|
|
||||||
|
|
||||||
if (varargs)
|
|
||||||
{
|
|
||||||
StateParameters[paramindex++] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (*params)
|
|
||||||
{
|
|
||||||
switch(*params)
|
|
||||||
{
|
|
||||||
case 'I':
|
|
||||||
case 'i': // Integer
|
|
||||||
SC_MustGetNumber();
|
|
||||||
v=sc_Number;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'F':
|
|
||||||
case 'f': // Fixed point
|
|
||||||
SC_MustGetFloat();
|
|
||||||
v=fixed_t(sc_Float*FRACUNIT);
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
case 'S':
|
|
||||||
case 's': // Sound name
|
|
||||||
SC_MustGetString();
|
|
||||||
v=S_FindSound(sc_String);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'M':
|
|
||||||
case 'm': // Actor name
|
|
||||||
case 'T':
|
|
||||||
case 't': // String
|
|
||||||
SC_MustGetString();
|
|
||||||
v = (int)(sc_String[0] ? FName(sc_String) : NAME_None);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'L':
|
|
||||||
case 'l': // Jump label
|
|
||||||
|
|
||||||
SC_ScriptError("You cannot use state jump calls in action functions (%s tries to call %s)\n",
|
|
||||||
funcname.GetChars(), afd->SymbolName.GetChars());
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'C':
|
|
||||||
case 'c': // Color
|
|
||||||
SC_MustGetString ();
|
|
||||||
if (SC_Compare("none"))
|
|
||||||
{
|
|
||||||
v = -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int c = V_GetColor (NULL, sc_String);
|
|
||||||
// 0 needs to be the default so we have to mark the color.
|
|
||||||
v = MAKEARGB(1, RPART(c), GPART(c), BPART(c));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'X':
|
|
||||||
case 'x':
|
|
||||||
v = ParseExpression (false, bag.Info->Class);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'Y':
|
|
||||||
case 'y':
|
|
||||||
v = ParseExpression (true, bag.Info->Class);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
assert(false);
|
|
||||||
v = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
StateParameters[paramindex++] = v;
|
|
||||||
params++;
|
|
||||||
if (varargs)
|
|
||||||
{
|
|
||||||
StateParameters[paramstart]++;
|
|
||||||
}
|
|
||||||
if (*params)
|
|
||||||
{
|
|
||||||
if (*params == '+')
|
|
||||||
{
|
|
||||||
if (SC_CheckString(")"))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
params--;
|
|
||||||
v = 0;
|
|
||||||
StateParameters.Push(v);
|
|
||||||
}
|
|
||||||
else if ((islower(*params) || *params=='!') && SC_CheckString(")"))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
SC_MustGetStringName (",");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SC_MustGetStringName(")");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SC_MustGetString();
|
|
||||||
if (SC_Compare("("))
|
|
||||||
{
|
|
||||||
SC_ScriptError("You cannot pass parameters to '%s'\n",funcname.GetChars());
|
|
||||||
}
|
|
||||||
SC_UnGet();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ParseActionFunction()
|
|
||||||
{
|
|
||||||
FState state;
|
|
||||||
Baggage bag;
|
|
||||||
bag.Info=RUNTIME_CLASS(AActor)->ActorInfo;
|
|
||||||
|
|
||||||
// for now only void functions with no parameters
|
|
||||||
SC_MustGetToken(TK_Void);
|
|
||||||
SC_MustGetString();
|
|
||||||
FName funcname = sc_String;
|
|
||||||
SC_MustGetToken('(');
|
|
||||||
SC_MustGetToken(')');
|
|
||||||
SC_MustGetToken('{');
|
|
||||||
// All this can do for the moment is parse a list of simple function calls, nothing more
|
|
||||||
while (SC_MustGetString(), sc_TokenType != '}');
|
|
||||||
{
|
|
||||||
ParseFunctionCall(bag, state);
|
|
||||||
SC_MustGetToken(';');
|
|
||||||
// Todo: Take the state's content and make a list of it.
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -71,5 +71,15 @@ enum
|
||||||
int FindLineSpecialEx (const char *string, int *minargs, int *maxargs);
|
int FindLineSpecialEx (const char *string, int *minargs, int *maxargs);
|
||||||
|
|
||||||
|
|
||||||
|
// Types of old style decorations
|
||||||
|
enum EDefinitionType
|
||||||
|
{
|
||||||
|
DEF_Decoration,
|
||||||
|
DEF_BreakableDecoration,
|
||||||
|
DEF_Pickup,
|
||||||
|
DEF_Projectile,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -696,7 +696,7 @@ static ExpData *ParseExpressionA (const PClass *cls)
|
||||||
}
|
}
|
||||||
SC_MustGetToken('.');
|
SC_MustGetToken('.');
|
||||||
SC_MustGetToken(TK_Identifier);
|
SC_MustGetToken(TK_Identifier);
|
||||||
PSymbol *sym = cls->Symbols.FindSymbol (sc_Name, true);
|
PSymbol *sym = cls->Symbols.FindSymbol (sc_String, true);
|
||||||
if (sym != NULL && sym->SymbolType == SYM_Const)
|
if (sym != NULL && sym->SymbolType == SYM_Const)
|
||||||
{
|
{
|
||||||
ExpData *data = new ExpData;
|
ExpData *data = new ExpData;
|
||||||
|
@ -713,7 +713,7 @@ static ExpData *ParseExpressionA (const PClass *cls)
|
||||||
}
|
}
|
||||||
else if (SC_CheckToken(TK_Identifier))
|
else if (SC_CheckToken(TK_Identifier))
|
||||||
{
|
{
|
||||||
switch (sc_Name)
|
switch (FName(sc_String))
|
||||||
{
|
{
|
||||||
case NAME_Random:
|
case NAME_Random:
|
||||||
{
|
{
|
||||||
|
@ -842,7 +842,7 @@ static ExpData *ParseExpressionA (const PClass *cls)
|
||||||
// Check if this is a constant
|
// Check if this is a constant
|
||||||
if (cls != NULL)
|
if (cls != NULL)
|
||||||
{
|
{
|
||||||
PSymbol *sym = cls->Symbols.FindSymbol (sc_Name, true);
|
PSymbol *sym = cls->Symbols.FindSymbol (sc_String, true);
|
||||||
if (sym != NULL && sym->SymbolType == SYM_Const)
|
if (sym != NULL && sym->SymbolType == SYM_Const)
|
||||||
{
|
{
|
||||||
ExpData *data = new ExpData;
|
ExpData *data = new ExpData;
|
||||||
|
@ -855,9 +855,10 @@ static ExpData *ParseExpressionA (const PClass *cls)
|
||||||
|
|
||||||
// Check if it's a variable we understand
|
// Check if it's a variable we understand
|
||||||
int varid = -1;
|
int varid = -1;
|
||||||
|
FName vname = sc_String;
|
||||||
for (size_t i = 0; i < countof(ExpVars); i++)
|
for (size_t i = 0; i < countof(ExpVars); i++)
|
||||||
{
|
{
|
||||||
if (sc_Name == ExpVars[i].name)
|
if (vname == ExpVars[i].name)
|
||||||
{
|
{
|
||||||
varid = (int)i;
|
varid = (int)i;
|
||||||
break;
|
break;
|
170
src/thingdef/thingdef_main.cpp
Normal file
170
src/thingdef/thingdef_main.cpp
Normal file
|
@ -0,0 +1,170 @@
|
||||||
|
/*
|
||||||
|
** decorations.cpp
|
||||||
|
** Loads custom actors out of DECORATE lumps.
|
||||||
|
**
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
** Copyright 2002-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.
|
||||||
|
**
|
||||||
|
** 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.
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
// HEADER FILES ------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "actor.h"
|
||||||
|
#include "info.h"
|
||||||
|
#include "sc_man.h"
|
||||||
|
#include "tarray.h"
|
||||||
|
#include "w_wad.h"
|
||||||
|
#include "templates.h"
|
||||||
|
#include "s_sound.h"
|
||||||
|
#include "cmdlib.h"
|
||||||
|
#include "thingdef.h"
|
||||||
|
#include "vectors.h"
|
||||||
|
|
||||||
|
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||||
|
|
||||||
|
void ProcessActor();
|
||||||
|
void ParseClass();
|
||||||
|
void ParseGlobalConst();
|
||||||
|
void ParseGlobalEnum();
|
||||||
|
void FinishThingdef();
|
||||||
|
void InitDecorateTranslations();
|
||||||
|
void ParseOldDecoration(EDefinitionType def);
|
||||||
|
|
||||||
|
// STATIC FUNCTION PROTOTYPES --------------------------------------------
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// ParseDecorate
|
||||||
|
//
|
||||||
|
// Parses a single DECORATE lump
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
static void ParseDecorate ()
|
||||||
|
{
|
||||||
|
int recursion=0;
|
||||||
|
int lump;
|
||||||
|
|
||||||
|
// Get actor class name.
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
SC_SavePos();
|
||||||
|
if (!SC_GetToken ())
|
||||||
|
{
|
||||||
|
if (recursion==0) return;
|
||||||
|
SC_Close();
|
||||||
|
SC_RestoreScriptState();
|
||||||
|
recursion--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
switch (sc_TokenType)
|
||||||
|
{
|
||||||
|
case TK_Include:
|
||||||
|
SC_MustGetString();
|
||||||
|
// This is not using SC_Open because it can print a more useful error message when done here
|
||||||
|
lump = Wads.CheckNumForFullName(sc_String);
|
||||||
|
if (lump==-1) lump = Wads.CheckNumForName(sc_String);
|
||||||
|
if (lump==-1) SC_ScriptError("Lump '%s' not found", sc_String);
|
||||||
|
SC_SaveScriptState();
|
||||||
|
SC_OpenLumpNum(lump, sc_String);
|
||||||
|
recursion++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TK_Class:
|
||||||
|
ParseClass();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TK_Const:
|
||||||
|
ParseGlobalConst();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TK_Enum:
|
||||||
|
ParseGlobalEnum();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TK_Pickup:
|
||||||
|
ParseOldDecoration(DEF_Pickup);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TK_Breakable:
|
||||||
|
ParseOldDecoration(DEF_BreakableDecoration);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TK_Projectile:
|
||||||
|
ParseOldDecoration(DEF_Projectile);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ';':
|
||||||
|
// ';' is the start of a comment in the non-cmode parser which
|
||||||
|
// is used to parse parts of the DECORATE lump. If we don't add
|
||||||
|
// a check here the user will only get weird non-informative
|
||||||
|
// error messages if a semicolon is found.
|
||||||
|
SC_ScriptError("Unexpected ';'");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TK_Identifier:
|
||||||
|
// 'ACTOR' cannot be a keyword because it is also needed as a class identifier
|
||||||
|
// so let's do a special case for this.
|
||||||
|
if (SC_Compare("ACTOR"))
|
||||||
|
{
|
||||||
|
ProcessActor ();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Yuck! Too bad that there's no better way to check this properly
|
||||||
|
SC_RestorePos();
|
||||||
|
ParseOldDecoration(DEF_Decoration);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// LoadDecorations
|
||||||
|
//
|
||||||
|
// Called from FActor::StaticInit()
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void LoadDecorations ()
|
||||||
|
{
|
||||||
|
int lastlump, lump;
|
||||||
|
|
||||||
|
InitDecorateTranslations();
|
||||||
|
lastlump = 0;
|
||||||
|
while ((lump = Wads.FindLump ("DECORATE", &lastlump)) != -1)
|
||||||
|
{
|
||||||
|
SC_OpenLumpNum (lump, Wads.GetLumpFullName(lump));
|
||||||
|
ParseDecorate ();
|
||||||
|
SC_Close ();
|
||||||
|
}
|
||||||
|
FinishThingdef();
|
||||||
|
}
|
||||||
|
|
|
@ -63,7 +63,7 @@
|
||||||
#include "vectors.h"
|
#include "vectors.h"
|
||||||
#include "a_sharedglobal.h"
|
#include "a_sharedglobal.h"
|
||||||
#include "a_doomglobal.h"
|
#include "a_doomglobal.h"
|
||||||
#include "thingdef.h"
|
#include "thingdef/thingdef.h"
|
||||||
#include "v_video.h"
|
#include "v_video.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@ actor DeadShotgunGuy : ShotgunGuy 19
|
||||||
Spawn:
|
Spawn:
|
||||||
Goto Super::Death+4
|
Goto Super::Death+4
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
// Dead imp ----------------------------------------------------------------
|
// Dead imp ----------------------------------------------------------------
|
||||||
|
|
||||||
|
|
16
zdoom.vcproj
16
zdoom.vcproj
|
@ -4283,15 +4283,15 @@
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\src\decorations.cpp"
|
RelativePath=".\src\thingdef\olddecorations.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\src\thingdef.cpp"
|
RelativePath=".\src\thingdef\thingdef.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\src\thingdef.h"
|
RelativePath=".\src\thingdef\thingdef.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
|
@ -4299,7 +4299,15 @@
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\src\thingdef_exp.cpp"
|
RelativePath=".\src\thingdef\thingdef_exp.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\thingdef\thingdef_main.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\thingdef\thingdef_specials.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
|
Loading…
Reference in a new issue