mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-01-31 05:40:44 +00:00
- Added native variables to expression evaluator and replaced the previous
handling of actor variables in expressions with it. - Added support for floating point constants to DECORATE expression evaluator. SVN r1271 (trunk)
This commit is contained in:
parent
633154d46f
commit
b9afb78523
28 changed files with 3868 additions and 2919 deletions
|
@ -1,3 +1,8 @@
|
|||
October 19, 2008 (Changes by Graf Zahl)
|
||||
- Added native variables to expression evaluator and replaced the previous
|
||||
handling of actor variables in expressions with it.
|
||||
- Added support for floating point constants to DECORATE expression evaluator.
|
||||
|
||||
October 18, 2008
|
||||
- Rewrote the SeePastShootableLines check in P_SightCheckLine() to be
|
||||
more readable.
|
||||
|
|
|
@ -624,6 +624,7 @@ add_executable( zdoom WIN32
|
|||
thingdef/olddecorations.cpp
|
||||
thingdef/thingdef.cpp
|
||||
thingdef/thingdef_codeptr.cpp
|
||||
thingdef/thingdef_data.cpp
|
||||
thingdef/thingdef_exp.cpp
|
||||
thingdef/thingdef_expression.cpp
|
||||
thingdef/thingdef_main.cpp
|
||||
|
|
10
src/actor.h
10
src/actor.h
|
@ -633,7 +633,7 @@ public:
|
|||
FRenderStyle RenderStyle; // Style to draw this actor with
|
||||
DWORD renderflags; // Different rendering flags
|
||||
FTextureID picnum; // Draw this instead of sprite if valid
|
||||
SWORD TIDtoHate; // TID of things to hate (0 if none)
|
||||
int TIDtoHate; // TID of things to hate (0 if none)
|
||||
DWORD effects; // [RH] see p_effect.h
|
||||
fixed_t alpha;
|
||||
DWORD fillcolor; // Color to draw when STYLE_Shaded
|
||||
|
@ -678,18 +678,18 @@ public:
|
|||
TObjPtr<AActor> LastLookActor; // Actor last looked for (if TIDtoHate != 0)
|
||||
fixed_t SpawnPoint[3]; // For nightmare respawn
|
||||
WORD SpawnAngle;
|
||||
BYTE SoundChans; // Bitfield indicating which sound channels are playing.
|
||||
int skillrespawncount;
|
||||
TObjPtr<AActor> tracer; // Thing being chased/attacked for tracers
|
||||
TObjPtr<AActor> master; // Thing which spawned this one (prevents mutual attacks)
|
||||
fixed_t floorclip; // value to use for floor clipping
|
||||
SWORD tid; // thing identifier
|
||||
BYTE SoundChans; // Bitfield indicating which sound channels are playing.
|
||||
BYTE special; // special
|
||||
int tid; // thing identifier
|
||||
int special; // special
|
||||
int args[5]; // special arguments
|
||||
|
||||
AActor *inext, **iprev;// Links to other mobjs in same bucket
|
||||
TObjPtr<AActor> goal; // Monster's goal if not chasing anything
|
||||
BYTE waterlevel; // 0=none, 1=feet, 2=waist, 3=eyes
|
||||
int waterlevel; // 0=none, 1=feet, 2=waist, 3=eyes
|
||||
BYTE boomwaterlevel; // splash information for non-swimmable water sectors
|
||||
BYTE MinMissileChance;// [RH] If a random # is > than this, then missile attack.
|
||||
SBYTE LastLookPlayerNumber;// Player number last looked for (if TIDtoHate == 0)
|
||||
|
|
|
@ -40,10 +40,12 @@
|
|||
#define AREG_SECTION "__DATA,areg"
|
||||
#define CREG_SECTION "__DATA,creg"
|
||||
#define GREG_SECTION "__DATA,greg"
|
||||
#define GREG_SECTION "__DATA,mreg"
|
||||
#else
|
||||
#define AREG_SECTION "areg"
|
||||
#define CREG_SECTION "creg"
|
||||
#define GREG_SECTION "greg"
|
||||
#define MREG_SECTION "mreg"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -62,6 +64,10 @@ extern REGINFO CRegTail;
|
|||
extern REGINFO GRegHead;
|
||||
extern REGINFO GRegTail;
|
||||
|
||||
// List of variables
|
||||
extern REGINFO MRegHead;
|
||||
extern REGINFO MRegTail;
|
||||
|
||||
template<class T, REGINFO *_head, REGINFO *_tail>
|
||||
class TAutoSegIteratorNoArrow
|
||||
{
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
|
||||
#if defined(_MSC_VER)
|
||||
|
||||
#pragma comment(linker, "/merge:.areg=.data /merge:.creg=.data /merge:.greg=.data /merge:.wreg=.data")
|
||||
#pragma comment(linker, "/merge:.areg=.data /merge:.creg=.data /merge:.greg=.data /merge:.mreg=.data")
|
||||
|
||||
#pragma data_seg(".areg$a")
|
||||
void *ARegHead = 0;
|
||||
|
@ -57,6 +57,9 @@ void *CRegHead = 0;
|
|||
#pragma data_seg(".greg$a")
|
||||
void *GRegHead = 0;
|
||||
|
||||
#pragma data_seg(".mreg$a")
|
||||
void *MRegHead = 0;
|
||||
|
||||
#pragma data_seg()
|
||||
|
||||
// We want visual styles support under XP
|
||||
|
@ -83,6 +86,7 @@ void *GRegHead = 0;
|
|||
void *ARegHead __attribute__((section(AREG_SECTION))) = 0;
|
||||
void *CRegHead __attribute__((section(CREG_SECTION))) = 0;
|
||||
void *GRegHead __attribute__((section(GREG_SECTION))) = 0;
|
||||
void *MRegHead __attribute__((section(MREG_SECTION))) = 0;
|
||||
|
||||
#elif
|
||||
|
||||
|
|
|
@ -46,6 +46,9 @@ void *CRegTail = 0;
|
|||
#pragma data_seg(".greg$z")
|
||||
void *GRegTail = 0;
|
||||
|
||||
#pragma data_seg(".mreg$z")
|
||||
void *MRegTail = 0;
|
||||
|
||||
#pragma data_seg()
|
||||
|
||||
|
||||
|
@ -55,6 +58,7 @@ void *GRegTail = 0;
|
|||
void *ARegTail __attribute__((section(AREG_SECTION))) = 0;
|
||||
void *CRegTail __attribute__((section(CREG_SECTION))) = 0;
|
||||
void *GRegTail __attribute__((section(GREG_SECTION))) = 0;
|
||||
void *MRegTail __attribute__((section(GREG_SECTION))) = 0;
|
||||
|
||||
#elif
|
||||
|
||||
|
|
|
@ -5,11 +5,14 @@
|
|||
#error You must #include "dobject.h" to get dobjtype.h
|
||||
#endif
|
||||
|
||||
#include "thingdef/thingdef_type.h"
|
||||
|
||||
// Symbol information -------------------------------------------------------
|
||||
|
||||
enum ESymbolType
|
||||
{
|
||||
SYM_Const,
|
||||
SYM_Variable,
|
||||
SYM_ActionFunction
|
||||
};
|
||||
|
||||
|
@ -19,13 +22,34 @@ struct PSymbol
|
|||
|
||||
ESymbolType SymbolType;
|
||||
FName SymbolName;
|
||||
|
||||
protected:
|
||||
PSymbol(FName name, ESymbolType type) { SymbolType = type; SymbolName = name; }
|
||||
};
|
||||
|
||||
// A constant value ---------------------------------------------------------
|
||||
|
||||
struct PSymbolConst : public PSymbol
|
||||
{
|
||||
int Value;
|
||||
int ValueType;
|
||||
union
|
||||
{
|
||||
int Value;
|
||||
double Float;
|
||||
};
|
||||
|
||||
PSymbolConst(FName name) : PSymbol(name, SYM_Const) {}
|
||||
};
|
||||
|
||||
// A variable ---------------------------------------------------------
|
||||
|
||||
struct PSymbolVariable : public PSymbol
|
||||
{
|
||||
FExpressionType ValueType;
|
||||
int size;
|
||||
intptr_t offset;
|
||||
|
||||
PSymbolVariable(FName name) : PSymbol(name, SYM_Variable) {}
|
||||
};
|
||||
|
||||
// An action function -------------------------------------------------------
|
||||
|
@ -55,6 +79,8 @@ struct PSymbolActionFunction : public PSymbol
|
|||
FString Arguments;
|
||||
actionf_p Function;
|
||||
int defaultparameterindex;
|
||||
|
||||
PSymbolActionFunction(FName name) : PSymbol(name, SYM_ActionFunction) {}
|
||||
};
|
||||
|
||||
// A symbol table -----------------------------------------------------------
|
||||
|
|
|
@ -768,8 +768,6 @@ int FStateDefinitions::FinishStates (FActorInfo *actor, AActor *defaults, TArray
|
|||
static int c=0;
|
||||
int count = StateArray.Size();
|
||||
|
||||
DPrintf("Finishing states for %s\n", actor->Class->TypeName.GetChars());
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
FState *realstates = new FState[count];
|
||||
|
|
|
@ -914,6 +914,8 @@ FString FScanner::TokenName (int token, const char *string)
|
|||
"'breakable'",
|
||||
"'projectile'",
|
||||
"'#include'",
|
||||
"'fixed_t'",
|
||||
"'angle_t'",
|
||||
};
|
||||
|
||||
FString work;
|
||||
|
|
|
@ -209,6 +209,8 @@ enum
|
|||
TK_Breakable,
|
||||
TK_Projectile,
|
||||
TK_Include,
|
||||
TK_Fixed_t,
|
||||
TK_Angle_t,
|
||||
|
||||
TK_LastToken
|
||||
};
|
||||
|
|
3585
src/sc_man_scanner.h
3585
src/sc_man_scanner.h
File diff suppressed because it is too large
Load diff
|
@ -145,6 +145,8 @@ std2:
|
|||
'pickup' { RET(TK_Pickup); }
|
||||
'breakable' { RET(TK_Breakable); }
|
||||
'projectile' { RET(TK_Projectile); }
|
||||
'fixed_t' { RET(TK_Fixed_t); }
|
||||
'angle_t' { RET(TK_Angle_t); }
|
||||
|
||||
L (L|D)* { RET(TK_Identifier); }
|
||||
|
||||
|
|
|
@ -99,8 +99,6 @@ IMPLEMENT_CLASS (AFakeInventory)
|
|||
|
||||
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
||||
|
||||
PSymbolActionFunction *FindGlobalActionFunction(const char *name);
|
||||
|
||||
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
||||
|
||||
static void ParseInsideDecoration (Baggage &bag, AActor *defaults,
|
||||
|
|
|
@ -325,9 +325,7 @@ static void ParseActionDef (FScanner &sc, PClass *cls)
|
|||
}
|
||||
}
|
||||
sc.MustGetToken(';');
|
||||
PSymbolActionFunction *sym = new PSymbolActionFunction;
|
||||
sym->SymbolName = funcname;
|
||||
sym->SymbolType = SYM_ActionFunction;
|
||||
PSymbolActionFunction *sym = new PSymbolActionFunction(funcname);
|
||||
sym->Arguments = args;
|
||||
sym->Function = afd->Function;
|
||||
if (hasdefaults)
|
||||
|
@ -563,6 +561,10 @@ void ParseActor(FScanner &sc)
|
|||
ParseEnum (sc, &info->Class->Symbols, info->Class);
|
||||
break;
|
||||
|
||||
case TK_Native:
|
||||
ParseVariable (sc, &info->Class->Symbols, info->Class);
|
||||
break;
|
||||
|
||||
case TK_Identifier:
|
||||
// other identifier related checks here
|
||||
case TK_Projectile: // special case: both keyword and property name
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
#define __THINGDEF_H
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "info.h"
|
||||
|
||||
|
||||
class FScanner;
|
||||
|
||||
|
@ -162,6 +164,7 @@ AFuncDesc * FindFunction(const char * string);
|
|||
FState *P_GetState(AActor *self, FState *CallingState, int offset);
|
||||
int ParseStates(FScanner &sc, FActorInfo *actor, AActor *defaults, Baggage &bag);
|
||||
|
||||
PSymbolActionFunction *FindGlobalActionFunction(const char *name);
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
@ -175,6 +178,7 @@ void ParseActorFlag (FScanner &sc, Baggage &bag, int mod);
|
|||
void FinishActor(FScanner &sc, FActorInfo *info, Baggage &bag);
|
||||
|
||||
void ParseConstant (FScanner &sc, PSymbolTable *symt, PClass *cls);
|
||||
void ParseVariable (FScanner &sc, PSymbolTable *symt, PClass *cls);
|
||||
void ParseEnum (FScanner &sc, PSymbolTable *symt, PClass *cls);
|
||||
int ParseParameter(FScanner &sc, PClass *cls, char type, bool constant);
|
||||
|
||||
|
@ -182,10 +186,22 @@ int ParseParameter(FScanner &sc, PClass *cls, char type, bool constant);
|
|||
int ParseExpression (FScanner &sc, bool _not, PClass *cls);
|
||||
|
||||
bool IsExpressionConst(int id);
|
||||
int EvalExpressionI (int id, AActor *self, const PClass *cls=NULL);
|
||||
double EvalExpressionF (int id, AActor *self, const PClass *cls=NULL);
|
||||
fixed_t EvalExpressionFix (int id, AActor *self, const PClass *cls=NULL);
|
||||
int EvalExpressionI (int id, AActor *self);
|
||||
double EvalExpressionF (int id, AActor *self);
|
||||
fixed_t EvalExpressionFix (int id, AActor *self);
|
||||
|
||||
enum
|
||||
{
|
||||
DEPF_UNUSED,
|
||||
DEPF_FIREDAMAGE,
|
||||
DEPF_ICEDAMAGE,
|
||||
DEPF_LOWGRAVITY,
|
||||
DEPF_LONGMELEERANGE,
|
||||
DEPF_SHORTMISSILERANGE,
|
||||
DEPF_PICKUPFLASH,
|
||||
DEPF_QUARTERGRAVITY,
|
||||
DEPF_FIRERESIST,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -213,17 +229,22 @@ enum EDefinitionType
|
|||
#if defined(_MSC_VER)
|
||||
#pragma data_seg(".areg$u")
|
||||
#pragma data_seg(".greg$u")
|
||||
#pragma data_seg(".mreg$u")
|
||||
#pragma data_seg()
|
||||
|
||||
#define MSVC_ASEG __declspec(allocate(".areg$u"))
|
||||
#define GCC_ASEG
|
||||
#define MSVC_PSEG __declspec(allocate(".greg$u"))
|
||||
#define GCC_PSEG
|
||||
#define MSVC_MSEG __declspec(allocate(".mreg$u"))
|
||||
#define GCC_MSEG
|
||||
#else
|
||||
#define MSVC_ASEG
|
||||
#define GCC_ASEG __attribute__((section(AREG_SECTION)))
|
||||
#define MSVC_PSEG
|
||||
#define GCC_PSEG __attribute__((section(GREG_SECTION)))
|
||||
#define MSVC_MSEG
|
||||
#define GCC_MSEG __attribute__((section(MREG_SECTION)))
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -251,7 +272,16 @@ struct FPropertyInfo
|
|||
int category;
|
||||
};
|
||||
|
||||
struct FVariableInfo
|
||||
{
|
||||
const char *name;
|
||||
intptr_t address;
|
||||
const PClass *owner;
|
||||
};
|
||||
|
||||
|
||||
FPropertyInfo *FindProperty(const char * string);
|
||||
FVariableInfo *FindVariable(const char * string, const PClass *cls);
|
||||
int MatchString (const char *in, const char **strings);
|
||||
|
||||
|
||||
|
@ -293,6 +323,18 @@ int MatchString (const char *in, const char **strings);
|
|||
#define PROP_COLOR_PARM(var, no) \
|
||||
int var = params[(no)+1].i== 0? params[(no)+2].i : V_GetColor(NULL, params[(no)+2].s);
|
||||
|
||||
|
||||
#define DEFINE_GLOBAL_VARIABLE(name) \
|
||||
static FVariableInfo GlobalDef__##name = { #name, intptr_t(&name), NULL }; \
|
||||
MSVC_MSEG FVariableInfo *infoptr_GlobalDef__##name = &GlobalDef__##name;
|
||||
|
||||
#define DEFINE_MEMBER_VARIABLE(name, cls) \
|
||||
static FVariableInfo GlobalDef__##name = { #name, myoffsetof(cls, name), RUNTIME_CLASS(cls) }; \
|
||||
MSVC_MSEG FVariableInfo *infoptr_GlobalDef__##name = &GlobalDef__##name;
|
||||
|
||||
|
||||
|
||||
|
||||
struct StateCallData
|
||||
{
|
||||
FState *State;
|
||||
|
@ -308,13 +350,13 @@ struct StateCallData
|
|||
// access a function that requires parameters.
|
||||
#define DEFINE_ACTION_FUNCTION(cls, name) \
|
||||
void AF_##name (AActor *self, FState *, int, StateCallData *); \
|
||||
AFuncDesc info_##cls##_##name = { #name, AF_##name }; \
|
||||
static AFuncDesc info_##cls##_##name = { #name, AF_##name }; \
|
||||
MSVC_ASEG AFuncDesc *infoptr_##cls##_##name GCC_ASEG = &info_##cls##_##name; \
|
||||
void AF_##name (AActor *self, FState *, int, StateCallData *statecall)
|
||||
|
||||
#define DEFINE_ACTION_FUNCTION_PARAMS(cls, name) \
|
||||
void AFP_##name (AActor *self, FState *CallingState, int ParameterIndex, StateCallData *statecall); \
|
||||
AFuncDesc info_##cls##_##name = { #name, AFP_##name }; \
|
||||
static AFuncDesc info_##cls##_##name = { #name, AFP_##name }; \
|
||||
MSVC_ASEG AFuncDesc *infoptr_##cls##_##name GCC_ASEG = &info_##cls##_##name; \
|
||||
void AFP_##name (AActor *self, FState *CallingState, int ParameterIndex, StateCallData *statecall)
|
||||
|
||||
|
|
549
src/thingdef/thingdef_data.cpp
Normal file
549
src/thingdef/thingdef_data.cpp
Normal file
|
@ -0,0 +1,549 @@
|
|||
/*
|
||||
** thingdef_data.cpp
|
||||
**
|
||||
** DECORATE data tables
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2002-2008 Christoph Oelckers
|
||||
** Copyright 2004-2008 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 "thingdef.h"
|
||||
#include "actor.h"
|
||||
#include "d_player.h"
|
||||
#include "p_effect.h"
|
||||
#include "autosegs.h"
|
||||
|
||||
static TArray<FPropertyInfo*> properties;
|
||||
static TArray<AFuncDesc> AFTable;
|
||||
static TArray<FVariableInfo*> variables;
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// List of all flags
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
// [RH] Keep GCC quiet by not using offsetof on Actor types.
|
||||
#define DEFINE_FLAG(prefix, name, type, variable) { prefix##_##name, #name, (int)(size_t)&((type*)1)->variable - 1 }
|
||||
#define DEFINE_FLAG2(symbol, name, type, variable) { symbol, #name, (int)(size_t)&((type*)1)->variable - 1 }
|
||||
#define DEFINE_DEPRECATED_FLAG(name) { DEPF_##name, #name, -1 }
|
||||
#define DEFINE_DUMMY_FLAG(name) { DEPF_UNUSED, #name, -1 }
|
||||
|
||||
static FFlagDef ActorFlags[]=
|
||||
{
|
||||
DEFINE_FLAG(MF, PICKUP, APlayerPawn, flags),
|
||||
DEFINE_FLAG(MF, SPECIAL, APlayerPawn, flags),
|
||||
DEFINE_FLAG(MF, SOLID, AActor, flags),
|
||||
DEFINE_FLAG(MF, SHOOTABLE, AActor, flags),
|
||||
DEFINE_FLAG(MF, NOSECTOR, AActor, flags),
|
||||
DEFINE_FLAG(MF, NOBLOCKMAP, AActor, flags),
|
||||
DEFINE_FLAG(MF, AMBUSH, AActor, flags),
|
||||
DEFINE_FLAG(MF, JUSTHIT, AActor, flags),
|
||||
DEFINE_FLAG(MF, JUSTATTACKED, AActor, flags),
|
||||
DEFINE_FLAG(MF, SPAWNCEILING, AActor, flags),
|
||||
DEFINE_FLAG(MF, NOGRAVITY, AActor, flags),
|
||||
DEFINE_FLAG(MF, DROPOFF, AActor, flags),
|
||||
DEFINE_FLAG(MF, NOCLIP, AActor, flags),
|
||||
DEFINE_FLAG(MF, FLOAT, AActor, flags),
|
||||
DEFINE_FLAG(MF, TELEPORT, AActor, flags),
|
||||
DEFINE_FLAG(MF, MISSILE, AActor, flags),
|
||||
DEFINE_FLAG(MF, DROPPED, AActor, flags),
|
||||
DEFINE_FLAG(MF, SHADOW, AActor, flags),
|
||||
DEFINE_FLAG(MF, NOBLOOD, AActor, flags),
|
||||
DEFINE_FLAG(MF, CORPSE, AActor, flags),
|
||||
DEFINE_FLAG(MF, INFLOAT, AActor, flags),
|
||||
DEFINE_FLAG(MF, COUNTKILL, AActor, flags),
|
||||
DEFINE_FLAG(MF, COUNTITEM, AActor, flags),
|
||||
DEFINE_FLAG(MF, SKULLFLY, AActor, flags),
|
||||
DEFINE_FLAG(MF, NOTDMATCH, AActor, flags),
|
||||
DEFINE_FLAG(MF, SPAWNSOUNDSOURCE, AActor, flags),
|
||||
DEFINE_FLAG(MF, FRIENDLY, AActor, flags),
|
||||
DEFINE_FLAG(MF, NOLIFTDROP, AActor, flags),
|
||||
DEFINE_FLAG(MF, STEALTH, AActor, flags),
|
||||
DEFINE_FLAG(MF, ICECORPSE, AActor, flags),
|
||||
DEFINE_FLAG(MF2, DONTREFLECT, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, WINDTHRUST, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, HERETICBOUNCE , AActor, flags2),
|
||||
DEFINE_FLAG(MF2, BLASTED, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, FLOORCLIP, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, SPAWNFLOAT, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, NOTELEPORT, AActor, flags2),
|
||||
DEFINE_FLAG2(MF2_RIP, RIPPER, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, PUSHABLE, AActor, flags2),
|
||||
DEFINE_FLAG2(MF2_SLIDE, SLIDESONWALLS, AActor, flags2),
|
||||
DEFINE_FLAG2(MF2_PASSMOBJ, CANPASS, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, CANNOTPUSH, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, THRUGHOST, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, BOSS, AActor, flags2),
|
||||
DEFINE_FLAG2(MF2_NODMGTHRUST, NODAMAGETHRUST, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, DONTTRANSLATE, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, TELESTOMP, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, FLOATBOB, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, HEXENBOUNCE, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, DOOMBOUNCE, AActor, flags2),
|
||||
DEFINE_FLAG2(MF2_IMPACT, ACTIVATEIMPACT, AActor, flags2),
|
||||
DEFINE_FLAG2(MF2_PUSHWALL, CANPUSHWALLS, AActor, flags2),
|
||||
DEFINE_FLAG2(MF2_MCROSS, ACTIVATEMCROSS, AActor, flags2),
|
||||
DEFINE_FLAG2(MF2_PCROSS, ACTIVATEPCROSS, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, CANTLEAVEFLOORPIC, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, NONSHOOTABLE, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, INVULNERABLE, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, DORMANT, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, SEEKERMISSILE, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, REFLECTIVE, AActor, flags2),
|
||||
DEFINE_FLAG(MF3, FLOORHUGGER, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, CEILINGHUGGER, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, NORADIUSDMG, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, GHOST, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, SPECIALFLOORCLIP, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, ALWAYSPUFF, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, DONTSPLASH, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, DONTOVERLAP, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, DONTMORPH, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, DONTSQUASH, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, EXPLOCOUNT, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, FULLVOLACTIVE, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, ISMONSTER, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, SKYEXPLODE, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, STAYMORPHED, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, DONTBLAST, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, CANBLAST, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, NOTARGET, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, DONTGIB, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, NOBLOCKMONST, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, FULLVOLDEATH, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, CANBOUNCEWATER, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, NOWALLBOUNCESND, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, FOILINVUL, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, NOTELEOTHER, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, BLOODLESSIMPACT, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, NOEXPLODEFLOOR, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, PUFFONACTORS, AActor, flags3),
|
||||
DEFINE_FLAG(MF4, QUICKTORETALIATE, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, NOICEDEATH, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, RANDOMIZE, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, FIXMAPTHINGPOS , AActor, flags4),
|
||||
DEFINE_FLAG(MF4, ACTLIKEBRIDGE, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, STRIFEDAMAGE, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, CANUSEWALLS, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, MISSILEMORE, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, MISSILEEVENMORE, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, FORCERADIUSDMG, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, DONTFALL, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, SEESDAGGERS, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, INCOMBAT, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, LOOKALLAROUND, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, STANDSTILL, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, SPECTRAL, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, NOSPLASHALERT, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, SYNCHRONIZED, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, NOTARGETSWITCH, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, DONTHURTSPECIES, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, SHIELDREFLECT, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, DEFLECT, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, ALLOWPARTICLES, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, EXTREMEDEATH, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, NOEXTREMEDEATH, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, FRIGHTENED, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, NOBOUNCESOUND, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, NOSKIN, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, BOSSDEATH, AActor, flags4),
|
||||
|
||||
DEFINE_FLAG(MF5, FASTER, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, FASTMELEE, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, NODROPOFF, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, BOUNCEONACTORS, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, EXPLODEONWATER, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, NODAMAGE, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, BLOODSPLATTER, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, OLDRADIUSDMG, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, DEHEXPLOSION, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, PIERCEARMOR, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, NOBLOODDECALS, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, USESPECIAL, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, NOPAIN, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, ALWAYSFAST, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, NEVERFAST, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, ALWAYSRESPAWN, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, NEVERRESPAWN, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, DONTRIP, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, NOINFIGHTING, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, NOINTERACTION, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, NOTIMEFREEZE, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, PUFFGETSOWNER, AActor, flags5), // [BB] added PUFFGETSOWNER
|
||||
DEFINE_FLAG(MF5, SPECIALFIREDAMAGE, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, SUMMONEDMONSTER, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, NOVERTICALMELEERANGE, AActor, flags5),
|
||||
|
||||
// Effect flags
|
||||
DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects),
|
||||
DEFINE_FLAG2(FX_ROCKET, ROCKETTRAIL, AActor, effects),
|
||||
DEFINE_FLAG2(FX_GRENADE, GRENADETRAIL, AActor, effects),
|
||||
DEFINE_FLAG(RF, INVISIBLE, AActor, renderflags),
|
||||
DEFINE_FLAG(RF, FORCEYBILLBOARD, AActor, renderflags),
|
||||
DEFINE_FLAG(RF, FORCEXYBILLBOARD, AActor, renderflags),
|
||||
|
||||
// Deprecated flags. Handling must be performed in HandleDeprecatedFlags
|
||||
DEFINE_DEPRECATED_FLAG(FIREDAMAGE),
|
||||
DEFINE_DEPRECATED_FLAG(ICEDAMAGE),
|
||||
DEFINE_DEPRECATED_FLAG(LOWGRAVITY),
|
||||
DEFINE_DEPRECATED_FLAG(SHORTMISSILERANGE),
|
||||
DEFINE_DEPRECATED_FLAG(LONGMELEERANGE),
|
||||
DEFINE_DEPRECATED_FLAG(QUARTERGRAVITY),
|
||||
DEFINE_DEPRECATED_FLAG(FIRERESIST),
|
||||
DEFINE_DUMMY_FLAG(NONETID),
|
||||
DEFINE_DUMMY_FLAG(ALLOWCLIENTSPAWN),
|
||||
};
|
||||
|
||||
static FFlagDef InventoryFlags[] =
|
||||
{
|
||||
// Inventory flags
|
||||
DEFINE_FLAG(IF, QUIET, AInventory, ItemFlags),
|
||||
DEFINE_FLAG(IF, AUTOACTIVATE, AInventory, ItemFlags),
|
||||
DEFINE_FLAG(IF, UNDROPPABLE, AInventory, ItemFlags),
|
||||
DEFINE_FLAG(IF, INVBAR, AInventory, ItemFlags),
|
||||
DEFINE_FLAG(IF, HUBPOWER, AInventory, ItemFlags),
|
||||
DEFINE_FLAG(IF, INTERHUBSTRIP, AInventory, ItemFlags),
|
||||
DEFINE_FLAG(IF, ALWAYSPICKUP, AInventory, ItemFlags),
|
||||
DEFINE_FLAG(IF, FANCYPICKUPSOUND, AInventory, ItemFlags),
|
||||
DEFINE_FLAG(IF, BIGPOWERUP, AInventory, ItemFlags),
|
||||
DEFINE_FLAG(IF, KEEPDEPLETED, AInventory, ItemFlags),
|
||||
DEFINE_FLAG(IF, IGNORESKILL, AInventory, ItemFlags),
|
||||
DEFINE_FLAG(IF, ADDITIVETIME, AInventory, ItemFlags),
|
||||
DEFINE_FLAG(IF, NOATTENPICKUPSOUND, AInventory, ItemFlags),
|
||||
|
||||
DEFINE_DEPRECATED_FLAG(PICKUPFLASH),
|
||||
|
||||
};
|
||||
|
||||
static FFlagDef WeaponFlags[] =
|
||||
{
|
||||
// Weapon flags
|
||||
DEFINE_FLAG(WIF, NOAUTOFIRE, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, READYSNDHALF, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, DONTBOB, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, AXEBLOOD, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, NOALERT, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, AMMO_OPTIONAL, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, ALT_AMMO_OPTIONAL, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, PRIMARY_USES_BOTH, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, WIMPY_WEAPON, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, POWERED_UP, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, STAFF2_KICKBACK, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF_BOT, EXPLOSIVE, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG2(WIF_BOT_MELEE, MELEEWEAPON, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF_BOT, BFG, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, CHEATNOTWEAPON, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, NO_AUTO_SWITCH, AWeapon, WeaponFlags),
|
||||
|
||||
DEFINE_DUMMY_FLAG(NOLMS),
|
||||
};
|
||||
|
||||
static const struct { const PClass *Type; FFlagDef *Defs; int NumDefs; } FlagLists[] =
|
||||
{
|
||||
{ RUNTIME_CLASS(AActor), ActorFlags, sizeof(ActorFlags)/sizeof(FFlagDef) },
|
||||
{ RUNTIME_CLASS(AInventory), InventoryFlags, sizeof(InventoryFlags)/sizeof(FFlagDef) },
|
||||
{ RUNTIME_CLASS(AWeapon), WeaponFlags, sizeof(WeaponFlags)/sizeof(FFlagDef) }
|
||||
};
|
||||
#define NUM_FLAG_LISTS 3
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Find a flag by name using a binary search
|
||||
//
|
||||
//==========================================================================
|
||||
static FFlagDef *FindFlag (FFlagDef *flags, int numflags, const char *flag)
|
||||
{
|
||||
int min = 0, max = numflags - 1;
|
||||
|
||||
while (min <= max)
|
||||
{
|
||||
int mid = (min + max) / 2;
|
||||
int lexval = stricmp (flag, flags[mid].name);
|
||||
if (lexval == 0)
|
||||
{
|
||||
return &flags[mid];
|
||||
}
|
||||
else if (lexval > 0)
|
||||
{
|
||||
min = mid + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
max = mid - 1;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Finds a flag that may have a qualified name
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FFlagDef *FindFlag (const PClass *type, const char *part1, const char *part2)
|
||||
{
|
||||
FFlagDef *def;
|
||||
int i;
|
||||
|
||||
if (part2 == NULL)
|
||||
{ // Search all lists
|
||||
for (i = 0; i < NUM_FLAG_LISTS; ++i)
|
||||
{
|
||||
if (type->IsDescendantOf (FlagLists[i].Type))
|
||||
{
|
||||
def = FindFlag (FlagLists[i].Defs, FlagLists[i].NumDefs, part1);
|
||||
if (def != NULL)
|
||||
{
|
||||
return def;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // Search just the named list
|
||||
for (i = 0; i < NUM_FLAG_LISTS; ++i)
|
||||
{
|
||||
if (stricmp (FlagLists[i].Type->TypeName.GetChars(), part1) == 0)
|
||||
{
|
||||
if (type->IsDescendantOf (FlagLists[i].Type))
|
||||
{
|
||||
return FindFlag (FlagLists[i].Defs, FlagLists[i].NumDefs, part2);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Find a property by name using a binary search
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FPropertyInfo *FindProperty(const char * string)
|
||||
{
|
||||
int min = 0, max = properties.Size()-1;
|
||||
|
||||
while (min <= max)
|
||||
{
|
||||
int mid = (min + max) / 2;
|
||||
int lexval = stricmp (string, properties[mid]->name);
|
||||
if (lexval == 0)
|
||||
{
|
||||
return properties[mid];
|
||||
}
|
||||
else if (lexval > 0)
|
||||
{
|
||||
min = mid + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
max = mid - 1;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Find a function by name using a binary search
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
AFuncDesc * FindFunction(const char * string)
|
||||
{
|
||||
int min = 0, max = AFTable.Size()-1;
|
||||
|
||||
while (min <= max)
|
||||
{
|
||||
int mid = (min + max) / 2;
|
||||
int lexval = stricmp (string, AFTable[mid].Name);
|
||||
if (lexval == 0)
|
||||
{
|
||||
return &AFTable[mid];
|
||||
}
|
||||
else if (lexval > 0)
|
||||
{
|
||||
min = mid + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
max = mid - 1;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Find a varIABLE by name using a binary search
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FVariableInfo *FindVariable(const char * string, const PClass *cls)
|
||||
{
|
||||
int min = 0, max = variables.Size()-1;
|
||||
|
||||
while (min <= max)
|
||||
{
|
||||
int mid = (min + max) / 2;
|
||||
int lexval;
|
||||
|
||||
if (cls < variables[mid]->owner) lexval = -1;
|
||||
else if (cls > variables[mid]->owner) lexval = 1;
|
||||
else lexval = stricmp (string, variables[mid]->name);
|
||||
|
||||
if (lexval == 0)
|
||||
{
|
||||
return variables[mid];
|
||||
}
|
||||
else if (lexval > 0)
|
||||
{
|
||||
min = mid + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
max = mid - 1;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Find an action function in AActor's table
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
PSymbolActionFunction *FindGlobalActionFunction(const char *name)
|
||||
{
|
||||
PSymbol *sym = RUNTIME_CLASS(AActor)->Symbols.FindSymbol(name, false);
|
||||
if (sym != NULL && sym->SymbolType == SYM_ActionFunction)
|
||||
return static_cast<PSymbolActionFunction*>(sym);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Sorting helpers
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static int STACK_ARGS flagcmp (const void * a, const void * b)
|
||||
{
|
||||
return stricmp( ((FFlagDef*)a)->name, ((FFlagDef*)b)->name);
|
||||
}
|
||||
|
||||
static int STACK_ARGS propcmp(const void * a, const void * b)
|
||||
{
|
||||
return stricmp( (*(FPropertyInfo**)a)->name, (*(FPropertyInfo**)b)->name);
|
||||
}
|
||||
|
||||
static int STACK_ARGS funccmp(const void * a, const void * b)
|
||||
{
|
||||
return stricmp( ((AFuncDesc*)a)->Name, ((AFuncDesc*)b)->Name);
|
||||
}
|
||||
|
||||
static int STACK_ARGS varcmp(const void * a, const void * b)
|
||||
{
|
||||
FVariableInfo *A = *(FVariableInfo**)a;
|
||||
FVariableInfo *B = *(FVariableInfo**)b;
|
||||
if (A->owner < B->owner) return -1;
|
||||
if (A->owner > B->owner) return 1;
|
||||
return stricmp(A->name, B->name);
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Initialization
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void InitThingdef()
|
||||
{
|
||||
// Sort the flag lists
|
||||
for (int i = 0; i < NUM_FLAG_LISTS; ++i)
|
||||
{
|
||||
qsort (FlagLists[i].Defs, FlagLists[i].NumDefs, sizeof(FFlagDef), flagcmp);
|
||||
}
|
||||
|
||||
// Create a sorted list of properties
|
||||
{
|
||||
TAutoSegIterator<FPropertyInfo *, &GRegHead, &GRegTail> probe;
|
||||
|
||||
while (++probe != NULL)
|
||||
{
|
||||
properties.Push(probe);
|
||||
}
|
||||
properties.ShrinkToFit();
|
||||
qsort(&properties[0], properties.Size(), sizeof(properties[0]), propcmp);
|
||||
}
|
||||
|
||||
// Create a sorted list of native action functions
|
||||
{
|
||||
TAutoSegIterator<AFuncDesc *, &ARegHead, &ARegTail> probe;
|
||||
|
||||
while (++probe != NULL)
|
||||
{
|
||||
AFTable.Push(*probe);
|
||||
}
|
||||
AFTable.ShrinkToFit();
|
||||
qsort(&AFTable[0], AFTable.Size(), sizeof(AFTable[0]), funccmp);
|
||||
}
|
||||
|
||||
// Create a sorted list of native variables
|
||||
{
|
||||
TAutoSegIterator<FVariableInfo *, &MRegHead, &MRegTail> probe;
|
||||
|
||||
while (++probe != NULL)
|
||||
{
|
||||
variables.Push(probe);
|
||||
}
|
||||
variables.ShrinkToFit();
|
||||
qsort(&variables[0], variables.Size(), sizeof(variables[0]), varcmp);
|
||||
}
|
||||
}
|
|
@ -52,180 +52,6 @@
|
|||
|
||||
FRandom pr_exrandom ("EX_Random");
|
||||
|
||||
extern PSymbolTable GlobalSymbols;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
typedef ExpVal (*ExpVarGet) (AActor *, int);
|
||||
|
||||
ExpVal GetAlpha (AActor *actor, int id)
|
||||
{
|
||||
ExpVal val;
|
||||
val.Type = VAL_Float;
|
||||
val.Float = FIXED2FLOAT (actor->alpha);
|
||||
return val;
|
||||
}
|
||||
|
||||
ExpVal GetAngle (AActor *actor, int id)
|
||||
{
|
||||
ExpVal val;
|
||||
val.Type = VAL_Float;
|
||||
val.Float = (double)actor->angle / ANGLE_1;
|
||||
return val;
|
||||
}
|
||||
|
||||
ExpVal GetArgs (AActor *actor, int id)
|
||||
{
|
||||
ExpVal val;
|
||||
val.Type = VAL_Int;
|
||||
val.Int = actor->args[id];
|
||||
return val;
|
||||
}
|
||||
|
||||
ExpVal GetCeilingZ (AActor *actor, int id)
|
||||
{
|
||||
ExpVal val;
|
||||
val.Type = VAL_Float;
|
||||
val.Float = FIXED2FLOAT (actor->ceilingz);
|
||||
return val;
|
||||
}
|
||||
|
||||
ExpVal GetFloorZ (AActor *actor, int id)
|
||||
{
|
||||
ExpVal val;
|
||||
val.Type = VAL_Float;
|
||||
val.Float = FIXED2FLOAT (actor->floorz);
|
||||
return val;
|
||||
}
|
||||
|
||||
ExpVal GetHealth (AActor *actor, int id)
|
||||
{
|
||||
ExpVal val;
|
||||
val.Type = VAL_Int;
|
||||
val.Int = actor->health;
|
||||
return val;
|
||||
}
|
||||
|
||||
ExpVal GetPitch (AActor *actor, int id)
|
||||
{
|
||||
ExpVal val;
|
||||
val.Type = VAL_Float;
|
||||
val.Float = (double)actor->pitch / ANGLE_1;
|
||||
return val;
|
||||
}
|
||||
|
||||
ExpVal GetSpecial (AActor *actor, int id)
|
||||
{
|
||||
ExpVal val;
|
||||
val.Type = VAL_Int;
|
||||
val.Int = actor->special;
|
||||
return val;
|
||||
}
|
||||
|
||||
ExpVal GetTID (AActor *actor, int id)
|
||||
{
|
||||
ExpVal val;
|
||||
val.Type = VAL_Int;
|
||||
val.Int = actor->tid;
|
||||
return val;
|
||||
}
|
||||
|
||||
ExpVal GetTIDToHate (AActor *actor, int id)
|
||||
{
|
||||
ExpVal val;
|
||||
val.Type = VAL_Int;
|
||||
val.Int = actor->TIDtoHate;
|
||||
return val;
|
||||
}
|
||||
|
||||
ExpVal GetWaterLevel (AActor *actor, int id)
|
||||
{
|
||||
ExpVal val;
|
||||
val.Type = VAL_Int;
|
||||
val.Int = actor->waterlevel;
|
||||
return val;
|
||||
}
|
||||
|
||||
ExpVal GetX (AActor *actor, int id)
|
||||
{
|
||||
ExpVal val;
|
||||
val.Type = VAL_Float;
|
||||
val.Float = FIXED2FLOAT (actor->x);
|
||||
return val;
|
||||
}
|
||||
|
||||
ExpVal GetY (AActor *actor, int id)
|
||||
{
|
||||
ExpVal val;
|
||||
val.Type = VAL_Float;
|
||||
val.Float = FIXED2FLOAT (actor->y);
|
||||
return val;
|
||||
}
|
||||
|
||||
ExpVal GetZ (AActor *actor, int id)
|
||||
{
|
||||
ExpVal val;
|
||||
val.Type = VAL_Float;
|
||||
val.Float = FIXED2FLOAT (actor->z);
|
||||
return val;
|
||||
}
|
||||
|
||||
ExpVal GetMomX (AActor *actor, int id)
|
||||
{
|
||||
ExpVal val;
|
||||
val.Type = VAL_Float;
|
||||
val.Float = FIXED2FLOAT (actor->momx);
|
||||
return val;
|
||||
}
|
||||
|
||||
ExpVal GetMomY (AActor *actor, int id)
|
||||
{
|
||||
ExpVal val;
|
||||
val.Type = VAL_Float;
|
||||
val.Float = FIXED2FLOAT (actor->momy);
|
||||
return val;
|
||||
}
|
||||
|
||||
ExpVal GetMomZ (AActor *actor, int id)
|
||||
{
|
||||
ExpVal val;
|
||||
val.Type = VAL_Float;
|
||||
val.Float = FIXED2FLOAT (actor->momz);
|
||||
return val;
|
||||
}
|
||||
|
||||
static struct FExpVar
|
||||
{
|
||||
ENamedName name; // identifier
|
||||
int array; // array size (0 if not an array)
|
||||
ExpVarGet get;
|
||||
int ValueType;
|
||||
} ExpVars[] = {
|
||||
{ NAME_Alpha, 0, GetAlpha, VAL_Float },
|
||||
{ NAME_Angle, 0, GetAngle, VAL_Float },
|
||||
{ NAME_Args, 5, GetArgs, VAL_Int },
|
||||
{ NAME_CeilingZ, 0, GetCeilingZ, VAL_Float },
|
||||
{ NAME_FloorZ, 0, GetFloorZ, VAL_Float },
|
||||
{ NAME_Health, 0, GetHealth, VAL_Int },
|
||||
{ NAME_Pitch, 0, GetPitch, VAL_Float },
|
||||
{ NAME_Special, 0, GetSpecial, VAL_Int },
|
||||
{ NAME_TID, 0, GetTID, VAL_Int },
|
||||
{ NAME_TIDtoHate, 0, GetTIDToHate, VAL_Int },
|
||||
{ NAME_WaterLevel, 0, GetWaterLevel, VAL_Int },
|
||||
{ NAME_X, 0, GetX, VAL_Float },
|
||||
{ NAME_Y, 0, GetY, VAL_Float },
|
||||
{ NAME_Z, 0, GetZ, VAL_Float },
|
||||
{ NAME_MomX, 0, GetMomX, VAL_Float },
|
||||
{ NAME_MomY, 0, GetMomY, VAL_Float },
|
||||
{ NAME_MomZ, 0, GetMomZ, VAL_Float },
|
||||
};
|
||||
|
||||
|
||||
TDeletingArray<FxExpression *> StateExpressions;
|
||||
|
||||
//
|
||||
// ParseExpression
|
||||
// [GRB] Parses an expression and stores it into Expression array
|
||||
|
@ -244,6 +70,7 @@ static FxExpression *ParseExpressionD (FScanner &sc, const PClass *cls);
|
|||
static FxExpression *ParseExpressionC (FScanner &sc, const PClass *cls);
|
||||
static FxExpression *ParseExpressionB (FScanner &sc, const PClass *cls);
|
||||
static FxExpression *ParseExpressionA (FScanner &sc, const PClass *cls);
|
||||
static FxExpression *ParseExpression0 (FScanner &sc, const PClass *cls);
|
||||
|
||||
FxExpression *ParseExpression (FScanner &sc, PClass *cls)
|
||||
{
|
||||
|
@ -251,23 +78,15 @@ FxExpression *ParseExpression (FScanner &sc, PClass *cls)
|
|||
|
||||
FCompileContext ctx;
|
||||
ctx.cls = cls;
|
||||
ctx.lax = true;
|
||||
data = data->Resolve(ctx);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
int ParseExpression (FScanner &sc, bool _not, PClass *cls)
|
||||
{
|
||||
if (StateExpressions.Size()==0)
|
||||
{
|
||||
// StateExpressions[0] always is const 0;
|
||||
FxExpression *data = new FxConstant(0, FScriptPosition());
|
||||
StateExpressions.Push (data);
|
||||
}
|
||||
|
||||
FxExpression *data = ParseExpression (sc, cls);
|
||||
return StateExpressions.Push (data);
|
||||
return AddExpression(ParseExpression (sc, cls));
|
||||
}
|
||||
|
||||
static FxExpression *ParseExpressionM (FScanner &sc, const PClass *cls)
|
||||
|
@ -440,8 +259,64 @@ static FxExpression *ParseExpressionB (FScanner &sc, const PClass *cls)
|
|||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ParseExpressionB
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static FxExpression *ParseExpressionA (FScanner &sc, const PClass *cls)
|
||||
{
|
||||
FxExpression *base_expr = ParseExpression0 (sc, cls);
|
||||
|
||||
while(1)
|
||||
{
|
||||
FScriptPosition pos(sc);
|
||||
|
||||
#if 0
|
||||
if (sc.CheckToken('.'))
|
||||
{
|
||||
if (sc.CheckToken(TK_Default))
|
||||
{
|
||||
sc.MustGetToken('.');
|
||||
base_expr = new FxClassDefaults(base_expr, pos);
|
||||
}
|
||||
sc.MustGetToken(TK_Identifier);
|
||||
|
||||
FName FieldName = sc.String;
|
||||
pos = sc;
|
||||
/* later!
|
||||
if (SC_CheckToken('('))
|
||||
{
|
||||
if (base_expr->IsDefaultObject())
|
||||
{
|
||||
SC_ScriptError("Cannot call methods for default.");
|
||||
}
|
||||
base_expr = ParseFunctionCall(base_expr, FieldName, false, false, pos);
|
||||
}
|
||||
else
|
||||
*/
|
||||
{
|
||||
base_expr = new FxDotIdentifier(base_expr, FieldName, pos);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (sc.CheckToken('['))
|
||||
{
|
||||
FxExpression *index = ParseExpressionM(sc, cls);
|
||||
sc.MustGetToken(']');
|
||||
base_expr = new FxArrayElement(base_expr, index);
|
||||
}
|
||||
else break;
|
||||
}
|
||||
|
||||
return base_expr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static FxExpression *ParseExpression0 (FScanner &sc, const PClass *cls)
|
||||
{
|
||||
FScriptPosition scpos(sc);
|
||||
if (sc.CheckToken('('))
|
||||
|
@ -466,34 +341,6 @@ static FxExpression *ParseExpressionA (FScanner &sc, const PClass *cls)
|
|||
{
|
||||
return new FxConstant(sc.Float, scpos);
|
||||
}
|
||||
/*
|
||||
else if (sc.CheckToken(TK_Class))
|
||||
{
|
||||
// Accept class'SomeClassName'.SomeConstant
|
||||
sc.MustGetToken(TK_NameConst);
|
||||
cls = PClass::FindClass (sc.Name);
|
||||
if (cls == NULL)
|
||||
{
|
||||
sc.ScriptError ("Unknown class '%s'", sc.String);
|
||||
}
|
||||
sc.MustGetToken('.');
|
||||
sc.MustGetToken(TK_Identifier);
|
||||
PSymbol *sym = cls->Symbols.FindSymbol (sc.String, true);
|
||||
if (sym != NULL && sym->SymbolType == SYM_Const)
|
||||
{
|
||||
FxExpression *data = new FxExpression;
|
||||
data->Type = EX_Const;
|
||||
data->Value.Type = VAL_Int;
|
||||
data->Value.Int = static_cast<PSymbolConst *>(sym)->Value;
|
||||
return data;
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.ScriptError ("'%s' is not a constant value in class '%s'", sc.String, cls->TypeName.GetChars());
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
*/
|
||||
else if (sc.CheckToken(TK_Identifier))
|
||||
{
|
||||
FName identifier = FName(sc.String);
|
||||
|
@ -560,201 +407,89 @@ static FxExpression *ParseExpressionA (FScanner &sc, const PClass *cls)
|
|||
return new FxAbs(x);
|
||||
}
|
||||
|
||||
case NAME_Sin:
|
||||
{
|
||||
sc.MustGetToken('(');
|
||||
|
||||
FxExpression *data = new FxExpression;
|
||||
data->Type = EX_Sin;
|
||||
data->ValueType = VAL_Float;
|
||||
|
||||
data->Children[0] = ParseExpressionM (sc, cls);
|
||||
|
||||
sc.MustGetToken(')');
|
||||
return data;
|
||||
}
|
||||
break;
|
||||
|
||||
case NAME_Cos:
|
||||
{
|
||||
sc.MustGetToken('(');
|
||||
|
||||
FxExpression *data = new FxExpression;
|
||||
data->Type = EX_Cos;
|
||||
data->ValueType = VAL_Float;
|
||||
|
||||
data->Children[0] = ParseExpressionM (sc, cls);
|
||||
|
||||
sc.MustGetToken(')');
|
||||
return data;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
int specnum, min_args, max_args;
|
||||
|
||||
// Check if this is an action special
|
||||
specnum = P_FindLineSpecial (sc.String, &min_args, &max_args);
|
||||
if (specnum != 0 && min_args >= 0)
|
||||
if (sc.CheckToken('('))
|
||||
{
|
||||
int i;
|
||||
|
||||
sc.MustGetToken('(');
|
||||
|
||||
FxExpression *data = new FxExpression, **left;
|
||||
data->Type = EX_ActionSpecial;
|
||||
data->Value.Int = specnum;
|
||||
data->ValueType = VAL_Int;
|
||||
|
||||
data->Children[0] = ParseExpressionM (sc, cls);
|
||||
left = &data->Children[1];
|
||||
|
||||
for (i = 1; i < 5 && sc.CheckToken(','); ++i)
|
||||
if (identifier == NAME_Sin)
|
||||
{
|
||||
FxExpression *right = new FxExpression;
|
||||
right->Type = EX_Right;
|
||||
right->Children[0] = ParseExpressionM (sc, cls);
|
||||
*left = right;
|
||||
left = &right->Children[1];
|
||||
FxExpression *data = new FxExpression;
|
||||
data->Type = EX_Sin;
|
||||
data->ValueType = VAL_Float;
|
||||
|
||||
data->Children[0] = ParseExpressionM (sc, cls);
|
||||
|
||||
sc.MustGetToken(')');
|
||||
return data;
|
||||
}
|
||||
*left = NULL;
|
||||
sc.MustGetToken(')');
|
||||
if (i < min_args)
|
||||
sc.ScriptError ("Not enough arguments to action special");
|
||||
if (i > max_args)
|
||||
sc.ScriptError ("Too many arguments to action special");
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
// Check if this is a constant
|
||||
if (cls != NULL)
|
||||
{
|
||||
PSymbol *sym = cls->Symbols.FindSymbol (identifier, true);
|
||||
if (sym == NULL) sym = GlobalSymbols.FindSymbol (identifier, true);
|
||||
if (sym != NULL && sym->SymbolType == SYM_Const)
|
||||
else if (identifier == NAME_Cos)
|
||||
{
|
||||
return new FxConstant(static_cast<PSymbolConst *>(sym)->Value, sc);
|
||||
}
|
||||
}
|
||||
FxExpression *data = new FxExpression;
|
||||
data->Type = EX_Cos;
|
||||
data->ValueType = VAL_Float;
|
||||
|
||||
// Check if it's a variable we understand
|
||||
int varid = -1;
|
||||
FName vname = sc.String;
|
||||
for (size_t i = 0; i < countof(ExpVars); i++)
|
||||
{
|
||||
if (vname == ExpVars[i].name)
|
||||
data->Children[0] = ParseExpressionM (sc, cls);
|
||||
|
||||
sc.MustGetToken(')');
|
||||
return data;
|
||||
}
|
||||
else
|
||||
{
|
||||
varid = (int)i;
|
||||
break;
|
||||
int specnum, min_args, max_args;
|
||||
|
||||
// Check if this is an action special
|
||||
specnum = P_FindLineSpecial (sc.String, &min_args, &max_args);
|
||||
if (specnum != 0 && min_args >= 0)
|
||||
{
|
||||
int i;
|
||||
|
||||
FxExpression *data = new FxExpression, **left;
|
||||
data->Type = EX_ActionSpecial;
|
||||
data->Value.Int = specnum;
|
||||
data->ValueType = VAL_Int;
|
||||
|
||||
data->Children[0] = ParseExpressionM (sc, cls);
|
||||
left = &data->Children[1];
|
||||
|
||||
for (i = 1; i < 5 && sc.CheckToken(','); ++i)
|
||||
{
|
||||
FxExpression *right = new FxExpression;
|
||||
right->Type = EX_Right;
|
||||
right->Children[0] = ParseExpressionM (sc, cls);
|
||||
*left = right;
|
||||
left = &right->Children[1];
|
||||
}
|
||||
*left = NULL;
|
||||
sc.MustGetToken(')');
|
||||
if (i < min_args)
|
||||
sc.ScriptError ("Not enough arguments to action special");
|
||||
if (i > max_args)
|
||||
sc.ScriptError ("Too many arguments to action special");
|
||||
|
||||
return data;
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.ScriptError("Unknown function '%s'", identifier.GetChars());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (varid == -1)
|
||||
sc.ScriptError ("Unknown value '%s'", sc.String);
|
||||
|
||||
FxExpression *data = new FxExpression;
|
||||
data->Type = EX_Var;
|
||||
data->Value.Type = VAL_Int;
|
||||
data->Value.Int = varid;
|
||||
data->ValueType = ExpVars[varid].ValueType;
|
||||
|
||||
if (ExpVars[varid].array)
|
||||
else
|
||||
{
|
||||
sc.MustGetToken('[');
|
||||
data->Children[0] = ParseExpressionM (sc, cls);
|
||||
sc.MustGetToken(']');
|
||||
return new FxIdentifier(identifier, sc);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FString tokname = sc.TokenName(sc.TokenType, sc.String);
|
||||
sc.ScriptError ("Unexpected token %s", tokname.GetChars());
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// EvalExpression
|
||||
// [GRB] Evaluates previously stored expression
|
||||
//
|
||||
|
||||
bool IsExpressionConst(int id)
|
||||
{
|
||||
if (StateExpressions.Size() <= (unsigned int)id) return false;
|
||||
|
||||
return StateExpressions[id]->isConstant();
|
||||
}
|
||||
|
||||
int EvalExpressionI (int id, AActor *self, const PClass *cls)
|
||||
{
|
||||
if (StateExpressions.Size() <= (unsigned int)id) return 0;
|
||||
|
||||
if (cls == NULL && self != NULL)
|
||||
{
|
||||
cls = self->GetClass();
|
||||
}
|
||||
|
||||
ExpVal val = StateExpressions[id]->EvalExpression (self, cls);
|
||||
|
||||
switch (val.Type)
|
||||
{
|
||||
default:
|
||||
case VAL_Int:
|
||||
return val.Int;
|
||||
case VAL_Float:
|
||||
return (int)val.Float;
|
||||
}
|
||||
}
|
||||
|
||||
double EvalExpressionF (int id, AActor *self, const PClass *cls)
|
||||
{
|
||||
if (StateExpressions.Size() <= (unsigned int)id) return 0.f;
|
||||
|
||||
if (cls == NULL && self != NULL)
|
||||
{
|
||||
cls = self->GetClass();
|
||||
}
|
||||
|
||||
ExpVal val = StateExpressions[id]->EvalExpression (self, cls);
|
||||
|
||||
switch (val.Type)
|
||||
{
|
||||
default:
|
||||
case VAL_Int:
|
||||
return (double)val.Int;
|
||||
case VAL_Float:
|
||||
return val.Float;
|
||||
}
|
||||
}
|
||||
|
||||
fixed_t EvalExpressionFix (int id, AActor *self, const PClass *cls)
|
||||
{
|
||||
if (StateExpressions.Size() <= (unsigned int)id) return 0;
|
||||
|
||||
if (cls == NULL && self != NULL)
|
||||
{
|
||||
cls = self->GetClass();
|
||||
}
|
||||
|
||||
ExpVal val = StateExpressions[id]->EvalExpression (self, cls);
|
||||
|
||||
switch (val.Type)
|
||||
{
|
||||
default:
|
||||
case VAL_Int:
|
||||
return val.Int << FRACBITS;
|
||||
case VAL_Float:
|
||||
return fixed_t(val.Float*FRACUNIT);
|
||||
}
|
||||
}
|
||||
|
||||
ExpVal FxExpression::EvalExpression (AActor *self, const PClass *cls)
|
||||
ExpVal FxExpression::EvalExpression (AActor *self)
|
||||
{
|
||||
ExpVal val;
|
||||
|
||||
|
@ -766,26 +501,9 @@ ExpVal FxExpression::EvalExpression (AActor *self, const PClass *cls)
|
|||
assert (Type != EX_NOP);
|
||||
val = Value;
|
||||
break;
|
||||
case EX_Var:
|
||||
if (!self)
|
||||
{
|
||||
I_FatalError ("Missing actor data");
|
||||
}
|
||||
else
|
||||
{
|
||||
int id = 0;
|
||||
if (ExpVars[Value.Int].array)
|
||||
{
|
||||
ExpVal idval = Children[0]->EvalExpression (self, cls);
|
||||
id = ((idval.Type == VAL_Int) ? idval.Int : (int)idval.Float) % ExpVars[Value.Int].array;
|
||||
}
|
||||
|
||||
val = ExpVars[Value.Int].get (self, id);
|
||||
}
|
||||
break;
|
||||
case EX_Sin:
|
||||
{
|
||||
ExpVal a = Children[0]->EvalExpression (self, cls);
|
||||
ExpVal a = Children[0]->EvalExpression (self);
|
||||
angle_t angle = (a.Type == VAL_Int) ? (a.Int * ANGLE_1) : angle_t(a.Float * ANGLE_1);
|
||||
|
||||
val.Type = VAL_Float;
|
||||
|
@ -795,7 +513,7 @@ ExpVal FxExpression::EvalExpression (AActor *self, const PClass *cls)
|
|||
|
||||
case EX_Cos:
|
||||
{
|
||||
ExpVal a = Children[0]->EvalExpression (self, cls);
|
||||
ExpVal a = Children[0]->EvalExpression (self);
|
||||
angle_t angle = (a.Type == VAL_Int) ? (a.Int * ANGLE_1) : angle_t(a.Float * ANGLE_1);
|
||||
|
||||
val.Type = VAL_Float;
|
||||
|
@ -811,7 +529,7 @@ ExpVal FxExpression::EvalExpression (AActor *self, const PClass *cls)
|
|||
|
||||
while (parm != NULL && i < 5)
|
||||
{
|
||||
ExpVal val = parm->Children[0]->EvalExpression (self, cls);
|
||||
ExpVal val = parm->Children[0]->EvalExpression (self);
|
||||
if (val.Type == VAL_Int)
|
||||
{
|
||||
parms[i] = val.Int;
|
||||
|
@ -852,54 +570,3 @@ FxExpression *FxExpression::Resolve(FCompileContext &ctx)
|
|||
return this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
some stuff for later
|
||||
static FxExpression *ParseExpressionA (FScanner &sc, const PClass *cls)
|
||||
{
|
||||
else if (sc.CheckToken(TK_Identifier))
|
||||
{
|
||||
FName IdName = FName(sc.String);
|
||||
switch (IdName)
|
||||
{
|
||||
default:
|
||||
{
|
||||
FScriptPosition scriptpos(sc);
|
||||
if (sc.CheckToken('('))
|
||||
{
|
||||
// function call
|
||||
TArray<FxExpression *> arguments;
|
||||
|
||||
do
|
||||
{
|
||||
FxExpression *data = ParseExpressionM(sc, cls);
|
||||
arguments.Push(data);
|
||||
}
|
||||
while (sc.CheckToken(','));
|
||||
return new FxFunctionCall(arguments, scriptpos);
|
||||
}
|
||||
else
|
||||
{
|
||||
FxExpression *data = new FxIdentifier(IdName, scriptpos);
|
||||
if (sc.CheckToken('['))
|
||||
{
|
||||
FxExpression *index = ParseExpressionM(sc, cls);
|
||||
sc.MustGetToken(']');
|
||||
data = new FxArrayElement(data, index);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FString tokname = sc.TokenName(sc.TokenType, sc.String);
|
||||
sc.ScriptError ("Unexpected token %s", tokname.GetChars());
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
|
@ -48,24 +48,7 @@
|
|||
#define ABORT(p) if (!(p)) { delete this; return NULL; }
|
||||
#define SAFE_RESOLVE(p,c) RESOLVE(p,c); ABORT(p)
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
/*
|
||||
class FxType
|
||||
{
|
||||
EBaseType type;
|
||||
public:
|
||||
FxType(EBaseType t) { type = t; }
|
||||
FxType(const FxType & t) { type = t.type; }
|
||||
FxType &operator =(const FxType &t) { type = t.type; return *this; }
|
||||
|
||||
EBaseType GetBaseType() const { return type; }
|
||||
};
|
||||
*/
|
||||
extern PSymbolTable GlobalSymbols;
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
@ -119,7 +102,7 @@ struct FScriptPosition
|
|||
return *this;
|
||||
}
|
||||
|
||||
void Message(int severity, const char *message,...);
|
||||
void Message(int severity, const char *message,...) const;
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
|
@ -131,6 +114,17 @@ struct FScriptPosition
|
|||
struct FCompileContext
|
||||
{
|
||||
const PClass *cls;
|
||||
bool lax;
|
||||
|
||||
|
||||
PSymbol *FindInClass(FName identifier)
|
||||
{
|
||||
return cls? cls->Symbols.FindSymbol(identifier, true) : NULL;
|
||||
}
|
||||
PSymbol *FindGlobal(FName identifier)
|
||||
{
|
||||
return GlobalSymbols.FindSymbol(identifier, true);
|
||||
}
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
|
@ -157,23 +151,6 @@ enum ExpOp
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
enum ExpValType
|
||||
{
|
||||
VAL_Int,
|
||||
VAL_Float,
|
||||
VAL_Unknown,
|
||||
|
||||
// only used for accessing class member fields to ensure proper conversion
|
||||
VAL_Fixed,
|
||||
VAL_Angle,
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
struct ExpVal
|
||||
{
|
||||
ExpValType Type;
|
||||
|
@ -181,6 +158,7 @@ struct ExpVal
|
|||
{
|
||||
int Int;
|
||||
double Float;
|
||||
void *pointer;
|
||||
};
|
||||
|
||||
int GetInt()
|
||||
|
@ -198,6 +176,11 @@ struct ExpVal
|
|||
return Type == VAL_Int? !!Int : Type == VAL_Float? Float!=0. : false;
|
||||
}
|
||||
|
||||
template<class T> T *GetPointer()
|
||||
{
|
||||
return Type == VAL_Object || Type == VAL_Pointer? (T*)pointer : NULL;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -246,15 +229,16 @@ public:
|
|||
return Resolve(ctx);
|
||||
}
|
||||
|
||||
virtual ExpVal EvalExpression (AActor *self, const PClass *cls);
|
||||
virtual ExpVal EvalExpression (AActor *self);
|
||||
virtual bool isConstant() const;
|
||||
virtual void RequestAddress();
|
||||
|
||||
int Type;
|
||||
ExpVal Value;
|
||||
FxExpression *Children[2];
|
||||
|
||||
FScriptPosition ScriptPosition;
|
||||
int ValueType;
|
||||
FExpressionType ValueType;
|
||||
protected:
|
||||
bool isresolved;
|
||||
};
|
||||
|
@ -309,23 +293,6 @@ public:
|
|||
bool IsDefaultObject() const;
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FxArrayElement
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
class FxArrayElement : public FxExpression
|
||||
{
|
||||
public:
|
||||
FxExpression *Array;
|
||||
FxExpression *index;
|
||||
|
||||
FxArrayElement(FxExpression*, FxExpression*, const FScriptPosition&);
|
||||
~FxArrayElement();
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FxConstant
|
||||
|
@ -355,11 +322,13 @@ public:
|
|||
ValueType = cv.Type;
|
||||
}
|
||||
|
||||
static FxExpression *MakeConstant(PSymbol *sym, const FScriptPosition &pos);
|
||||
|
||||
bool isConstant() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
ExpVal EvalExpression (AActor *self, const PClass *cls);
|
||||
ExpVal EvalExpression (AActor *self);
|
||||
};
|
||||
|
||||
|
||||
|
@ -379,7 +348,7 @@ public:
|
|||
~FxIntCast();
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
|
||||
ExpVal EvalExpression (AActor *self, const PClass *cls);
|
||||
ExpVal EvalExpression (AActor *self);
|
||||
};
|
||||
|
||||
|
||||
|
@ -413,7 +382,7 @@ public:
|
|||
FxMinusSign(FxExpression*);
|
||||
~FxMinusSign();
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
ExpVal EvalExpression (AActor *self, const PClass *cls);
|
||||
ExpVal EvalExpression (AActor *self);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
|
@ -430,7 +399,7 @@ public:
|
|||
FxUnaryNotBitwise(FxExpression*);
|
||||
~FxUnaryNotBitwise();
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
ExpVal EvalExpression (AActor *self, const PClass *cls);
|
||||
ExpVal EvalExpression (AActor *self);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
|
@ -447,7 +416,7 @@ public:
|
|||
FxUnaryNotBoolean(FxExpression*);
|
||||
~FxUnaryNotBoolean();
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
ExpVal EvalExpression (AActor *self, const PClass *cls);
|
||||
ExpVal EvalExpression (AActor *self);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
|
@ -480,7 +449,7 @@ public:
|
|||
|
||||
FxAddSub(int, FxExpression*, FxExpression*);
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
ExpVal EvalExpression (AActor *self, const PClass *cls);
|
||||
ExpVal EvalExpression (AActor *self);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
|
@ -495,7 +464,7 @@ public:
|
|||
|
||||
FxMulDiv(int, FxExpression*, FxExpression*);
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
ExpVal EvalExpression (AActor *self, const PClass *cls);
|
||||
ExpVal EvalExpression (AActor *self);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
|
@ -510,7 +479,7 @@ public:
|
|||
|
||||
FxCompareRel(int, FxExpression*, FxExpression*);
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
ExpVal EvalExpression (AActor *self, const PClass *cls);
|
||||
ExpVal EvalExpression (AActor *self);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
|
@ -525,7 +494,7 @@ public:
|
|||
|
||||
FxCompareEq(int, FxExpression*, FxExpression*);
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
ExpVal EvalExpression (AActor *self, const PClass *cls);
|
||||
ExpVal EvalExpression (AActor *self);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
|
@ -540,7 +509,7 @@ public:
|
|||
|
||||
FxBinaryInt(int, FxExpression*, FxExpression*);
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
ExpVal EvalExpression (AActor *self, const PClass *cls);
|
||||
ExpVal EvalExpression (AActor *self);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
|
@ -560,7 +529,7 @@ public:
|
|||
~FxBinaryLogical();
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
|
||||
ExpVal EvalExpression (AActor *self, const PClass *cls);
|
||||
ExpVal EvalExpression (AActor *self);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
|
@ -580,7 +549,7 @@ public:
|
|||
~FxConditional();
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
|
||||
ExpVal EvalExpression (AActor *self, const PClass *cls);
|
||||
ExpVal EvalExpression (AActor *self);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
|
@ -599,7 +568,7 @@ public:
|
|||
~FxAbs();
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
|
||||
ExpVal EvalExpression (AActor *self, const PClass *cls);
|
||||
ExpVal EvalExpression (AActor *self);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
|
@ -619,7 +588,7 @@ public:
|
|||
~FxRandom();
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
|
||||
ExpVal EvalExpression (AActor *self, const PClass *cls);
|
||||
ExpVal EvalExpression (AActor *self);
|
||||
};
|
||||
|
||||
|
||||
|
@ -641,11 +610,87 @@ public:
|
|||
~FxRandom2();
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
|
||||
ExpVal EvalExpression (AActor *self, const PClass *cls);
|
||||
ExpVal EvalExpression (AActor *self);
|
||||
};
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FxGlobalVariable
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
class FxGlobalVariable : public FxExpression
|
||||
{
|
||||
public:
|
||||
PSymbolVariable *var;
|
||||
bool AddressRequested;
|
||||
|
||||
FxGlobalVariable(PSymbolVariable*, const FScriptPosition&);
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
void RequestAddress();
|
||||
ExpVal EvalExpression (AActor *self);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FxClassMember
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
class FxClassMember : public FxExpression
|
||||
{
|
||||
public:
|
||||
FxExpression *classx;
|
||||
PSymbolVariable *membervar;
|
||||
bool AddressRequested;
|
||||
|
||||
FxClassMember(FxExpression*, PSymbolVariable*, const FScriptPosition&);
|
||||
~FxClassMember();
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
void RequestAddress();
|
||||
ExpVal EvalExpression (AActor *self);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FxSelf
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
class FxSelf : public FxExpression
|
||||
{
|
||||
public:
|
||||
FxSelf(const FScriptPosition&);
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
ExpVal EvalExpression (AActor *self);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FxArrayElement
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
class FxArrayElement : public FxExpression
|
||||
{
|
||||
public:
|
||||
FxExpression *Array;
|
||||
FxExpression *index;
|
||||
//bool AddressRequested;
|
||||
|
||||
FxArrayElement(FxExpression*, FxExpression*);
|
||||
~FxArrayElement();
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
//void RequestAddress();
|
||||
ExpVal EvalExpression (AActor *self);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
FxExpression *ParseExpression (FScanner &sc, PClass *cls);
|
||||
int AddExpression (FxExpression *data);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -46,6 +46,7 @@
|
|||
|
||||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||
|
||||
void InitThingdef();
|
||||
void ParseActor(FScanner &sc);
|
||||
void FinishThingdef();
|
||||
void ParseOldDecoration(FScanner &sc, EDefinitionType def);
|
||||
|
@ -102,6 +103,10 @@ static void ParseDecorate (FScanner &sc)
|
|||
ParseOldDecoration (sc, DEF_Projectile);
|
||||
break;
|
||||
|
||||
case TK_Native:
|
||||
ParseVariable(sc, &GlobalSymbols, NULL);
|
||||
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
|
||||
|
@ -142,6 +147,7 @@ void LoadDecorations ()
|
|||
{
|
||||
int lastlump, lump;
|
||||
|
||||
InitThingdef();
|
||||
lastlump = 0;
|
||||
while ((lump = Wads.FindLump ("DECORATE", &lastlump)) != -1)
|
||||
{
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
#include "autosegs.h"
|
||||
#include "i_system.h"
|
||||
#include "thingdef_exp.h"
|
||||
#include "w_wad.h"
|
||||
|
||||
|
||||
//==========================================================================
|
||||
|
@ -63,26 +64,39 @@
|
|||
|
||||
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('=');
|
||||
FxExpression *expr = ParseExpression (sc, cls);
|
||||
sc.MustGetToken(';');
|
||||
|
||||
int val = expr->EvalExpression(NULL, cls).GetInt();
|
||||
delete expr;
|
||||
PSymbolConst *sym = new PSymbolConst;
|
||||
sym->SymbolName = symname;
|
||||
sym->SymbolType = SYM_Const;
|
||||
sym->Value = val;
|
||||
if (symt->AddSymbol (sym) == NULL)
|
||||
// Read the type and make sure it's int or float.
|
||||
if (sc.CheckToken(TK_Int) || sc.CheckToken(TK_Float))
|
||||
{
|
||||
delete sym;
|
||||
sc.ScriptError ("'%s' is already defined in '%s'.",
|
||||
symname.GetChars(), cls? cls->TypeName.GetChars() : "Global");
|
||||
int type = sc.TokenType;
|
||||
sc.MustGetToken(TK_Identifier);
|
||||
FName symname = sc.String;
|
||||
sc.MustGetToken('=');
|
||||
FxExpression *expr = ParseExpression (sc, cls);
|
||||
sc.MustGetToken(';');
|
||||
|
||||
ExpVal val = expr->EvalExpression(NULL);
|
||||
delete expr;
|
||||
PSymbolConst *sym = new PSymbolConst(symname);
|
||||
if (type == TK_Int)
|
||||
{
|
||||
sym->ValueType = VAL_Int;
|
||||
sym->Value = val.GetInt();
|
||||
}
|
||||
else
|
||||
{
|
||||
sym->ValueType = VAL_Float;
|
||||
sym->Value = val.GetFloat();
|
||||
}
|
||||
if (symt->AddSymbol (sym) == NULL)
|
||||
{
|
||||
delete sym;
|
||||
sc.ScriptError ("'%s' is already defined in '%s'.",
|
||||
symname.GetChars(), cls? cls->TypeName.GetChars() : "Global");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.ScriptError("Numeric type required for constant");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,18 +120,17 @@ void ParseEnum (FScanner &sc, PSymbolTable *symt, PClass *cls)
|
|||
if (sc.CheckToken('='))
|
||||
{
|
||||
FxExpression *expr = ParseExpression (sc, cls);
|
||||
currvalue = expr->EvalExpression(NULL, cls).GetInt();
|
||||
currvalue = expr->EvalExpression(NULL).GetInt();
|
||||
delete expr;
|
||||
}
|
||||
PSymbolConst *sym = new PSymbolConst;
|
||||
sym->SymbolName = symname;
|
||||
sym->SymbolType = SYM_Const;
|
||||
PSymbolConst *sym = new PSymbolConst(symname);
|
||||
sym->ValueType = VAL_Int;
|
||||
sym->Value = currvalue;
|
||||
if (symt->AddSymbol (sym) == NULL)
|
||||
{
|
||||
delete sym;
|
||||
sc.ScriptError ("'%s' is already defined in '%s'.",
|
||||
symname.GetChars(), cls? cls->TypeName.GetChars() : "Global");
|
||||
sc.ScriptError ("'%s' is already defined in '%s'.",
|
||||
symname.GetChars(), cls? cls->TypeName.GetChars() : "Global");
|
||||
}
|
||||
// This allows a comma after the last value but doesn't enforce it.
|
||||
if (sc.CheckToken('}')) break;
|
||||
|
@ -127,6 +140,88 @@ void ParseEnum (FScanner &sc, PSymbolTable *symt, PClass *cls)
|
|||
sc.MustGetToken(';');
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ActorConstDef
|
||||
//
|
||||
// Parses a constant definition.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void ParseVariable (FScanner &sc, PSymbolTable * symt, PClass *cls)
|
||||
{
|
||||
FExpressionType valuetype;
|
||||
|
||||
if (sc.LumpNum == -1 || Wads.GetLumpFile(sc.LumpNum) > 0)
|
||||
{
|
||||
sc.ScriptError ("variables can only be imported by internal class and actor definitions!");
|
||||
}
|
||||
|
||||
// Read the type and make sure it's int or float.
|
||||
sc.MustGetAnyToken();
|
||||
switch (sc.TokenType)
|
||||
{
|
||||
case TK_Int:
|
||||
valuetype = VAL_Int;
|
||||
break;
|
||||
|
||||
case TK_Float:
|
||||
valuetype = VAL_Float;
|
||||
break;
|
||||
|
||||
case TK_Angle_t:
|
||||
valuetype = VAL_Angle;
|
||||
break;
|
||||
|
||||
case TK_Fixed_t:
|
||||
valuetype = VAL_Fixed;
|
||||
break;
|
||||
|
||||
case TK_Bool:
|
||||
valuetype = VAL_Bool;
|
||||
break;
|
||||
|
||||
case TK_Identifier:
|
||||
valuetype = VAL_Object;
|
||||
// Todo: Object type
|
||||
sc.ScriptError("Object type variables not implemented yet!");
|
||||
break;
|
||||
|
||||
default:
|
||||
sc.ScriptError("Invalid variable type %s", sc.String);
|
||||
return;
|
||||
}
|
||||
|
||||
sc.MustGetToken(TK_Identifier);
|
||||
FName symname = sc.String;
|
||||
if (sc.CheckToken('['))
|
||||
{
|
||||
FxExpression *expr = ParseExpression (sc, cls);
|
||||
int maxelems = expr->EvalExpression(NULL).GetInt();
|
||||
delete expr;
|
||||
sc.MustGetToken(']');
|
||||
valuetype.MakeArray(maxelems);
|
||||
}
|
||||
sc.MustGetToken(';');
|
||||
|
||||
FVariableInfo *vi = FindVariable(symname, cls);
|
||||
if (vi == NULL)
|
||||
{
|
||||
sc.ScriptError("Unknown native variable '%s'", symname.GetChars());
|
||||
}
|
||||
|
||||
PSymbolVariable *sym = new PSymbolVariable(symname);
|
||||
sym->offset = vi->address; // todo
|
||||
sym->ValueType = valuetype;
|
||||
|
||||
if (symt->AddSymbol (sym) == NULL)
|
||||
{
|
||||
delete sym;
|
||||
sc.ScriptError ("'%s' is already defined in '%s'.",
|
||||
symname.GetChars(), cls? cls->TypeName.GetChars() : "Global");
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Parses a flag name
|
||||
|
|
|
@ -69,332 +69,6 @@
|
|||
#include "colormatcher.h"
|
||||
#include "autosegs.h"
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// List of all flags
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
// [RH] Keep GCC quiet by not using offsetof on Actor types.
|
||||
#define DEFINE_FLAG(prefix, name, type, variable) { prefix##_##name, #name, (int)(size_t)&((type*)1)->variable - 1 }
|
||||
#define DEFINE_FLAG2(symbol, name, type, variable) { symbol, #name, (int)(size_t)&((type*)1)->variable - 1 }
|
||||
#define DEFINE_DEPRECATED_FLAG(name) { DEPF_##name, #name, -1 }
|
||||
#define DEFINE_DUMMY_FLAG(name) { DEPF_UNUSED, #name, -1 }
|
||||
|
||||
enum
|
||||
{
|
||||
DEPF_UNUSED,
|
||||
DEPF_FIREDAMAGE,
|
||||
DEPF_ICEDAMAGE,
|
||||
DEPF_LOWGRAVITY,
|
||||
DEPF_LONGMELEERANGE,
|
||||
DEPF_SHORTMISSILERANGE,
|
||||
DEPF_PICKUPFLASH,
|
||||
DEPF_QUARTERGRAVITY,
|
||||
DEPF_FIRERESIST,
|
||||
};
|
||||
|
||||
static FFlagDef ActorFlags[]=
|
||||
{
|
||||
DEFINE_FLAG(MF, PICKUP, APlayerPawn, flags),
|
||||
DEFINE_FLAG(MF, SPECIAL, APlayerPawn, flags),
|
||||
DEFINE_FLAG(MF, SOLID, AActor, flags),
|
||||
DEFINE_FLAG(MF, SHOOTABLE, AActor, flags),
|
||||
DEFINE_FLAG(MF, NOSECTOR, AActor, flags),
|
||||
DEFINE_FLAG(MF, NOBLOCKMAP, AActor, flags),
|
||||
DEFINE_FLAG(MF, AMBUSH, AActor, flags),
|
||||
DEFINE_FLAG(MF, JUSTHIT, AActor, flags),
|
||||
DEFINE_FLAG(MF, JUSTATTACKED, AActor, flags),
|
||||
DEFINE_FLAG(MF, SPAWNCEILING, AActor, flags),
|
||||
DEFINE_FLAG(MF, NOGRAVITY, AActor, flags),
|
||||
DEFINE_FLAG(MF, DROPOFF, AActor, flags),
|
||||
DEFINE_FLAG(MF, NOCLIP, AActor, flags),
|
||||
DEFINE_FLAG(MF, FLOAT, AActor, flags),
|
||||
DEFINE_FLAG(MF, TELEPORT, AActor, flags),
|
||||
DEFINE_FLAG(MF, MISSILE, AActor, flags),
|
||||
DEFINE_FLAG(MF, DROPPED, AActor, flags),
|
||||
DEFINE_FLAG(MF, SHADOW, AActor, flags),
|
||||
DEFINE_FLAG(MF, NOBLOOD, AActor, flags),
|
||||
DEFINE_FLAG(MF, CORPSE, AActor, flags),
|
||||
DEFINE_FLAG(MF, INFLOAT, AActor, flags),
|
||||
DEFINE_FLAG(MF, COUNTKILL, AActor, flags),
|
||||
DEFINE_FLAG(MF, COUNTITEM, AActor, flags),
|
||||
DEFINE_FLAG(MF, SKULLFLY, AActor, flags),
|
||||
DEFINE_FLAG(MF, NOTDMATCH, AActor, flags),
|
||||
DEFINE_FLAG(MF, SPAWNSOUNDSOURCE, AActor, flags),
|
||||
DEFINE_FLAG(MF, FRIENDLY, AActor, flags),
|
||||
DEFINE_FLAG(MF, NOLIFTDROP, AActor, flags),
|
||||
DEFINE_FLAG(MF, STEALTH, AActor, flags),
|
||||
DEFINE_FLAG(MF, ICECORPSE, AActor, flags),
|
||||
DEFINE_FLAG(MF2, DONTREFLECT, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, WINDTHRUST, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, HERETICBOUNCE , AActor, flags2),
|
||||
DEFINE_FLAG(MF2, BLASTED, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, FLOORCLIP, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, SPAWNFLOAT, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, NOTELEPORT, AActor, flags2),
|
||||
DEFINE_FLAG2(MF2_RIP, RIPPER, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, PUSHABLE, AActor, flags2),
|
||||
DEFINE_FLAG2(MF2_SLIDE, SLIDESONWALLS, AActor, flags2),
|
||||
DEFINE_FLAG2(MF2_PASSMOBJ, CANPASS, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, CANNOTPUSH, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, THRUGHOST, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, BOSS, AActor, flags2),
|
||||
DEFINE_FLAG2(MF2_NODMGTHRUST, NODAMAGETHRUST, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, DONTTRANSLATE, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, TELESTOMP, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, FLOATBOB, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, HEXENBOUNCE, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, DOOMBOUNCE, AActor, flags2),
|
||||
DEFINE_FLAG2(MF2_IMPACT, ACTIVATEIMPACT, AActor, flags2),
|
||||
DEFINE_FLAG2(MF2_PUSHWALL, CANPUSHWALLS, AActor, flags2),
|
||||
DEFINE_FLAG2(MF2_MCROSS, ACTIVATEMCROSS, AActor, flags2),
|
||||
DEFINE_FLAG2(MF2_PCROSS, ACTIVATEPCROSS, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, CANTLEAVEFLOORPIC, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, NONSHOOTABLE, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, INVULNERABLE, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, DORMANT, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, SEEKERMISSILE, AActor, flags2),
|
||||
DEFINE_FLAG(MF2, REFLECTIVE, AActor, flags2),
|
||||
DEFINE_FLAG(MF3, FLOORHUGGER, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, CEILINGHUGGER, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, NORADIUSDMG, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, GHOST, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, SPECIALFLOORCLIP, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, ALWAYSPUFF, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, DONTSPLASH, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, DONTOVERLAP, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, DONTMORPH, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, DONTSQUASH, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, EXPLOCOUNT, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, FULLVOLACTIVE, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, ISMONSTER, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, SKYEXPLODE, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, STAYMORPHED, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, DONTBLAST, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, CANBLAST, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, NOTARGET, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, DONTGIB, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, NOBLOCKMONST, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, FULLVOLDEATH, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, CANBOUNCEWATER, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, NOWALLBOUNCESND, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, FOILINVUL, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, NOTELEOTHER, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, BLOODLESSIMPACT, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, NOEXPLODEFLOOR, AActor, flags3),
|
||||
DEFINE_FLAG(MF3, PUFFONACTORS, AActor, flags3),
|
||||
DEFINE_FLAG(MF4, QUICKTORETALIATE, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, NOICEDEATH, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, RANDOMIZE, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, FIXMAPTHINGPOS , AActor, flags4),
|
||||
DEFINE_FLAG(MF4, ACTLIKEBRIDGE, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, STRIFEDAMAGE, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, CANUSEWALLS, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, MISSILEMORE, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, MISSILEEVENMORE, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, FORCERADIUSDMG, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, DONTFALL, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, SEESDAGGERS, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, INCOMBAT, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, LOOKALLAROUND, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, STANDSTILL, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, SPECTRAL, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, NOSPLASHALERT, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, SYNCHRONIZED, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, NOTARGETSWITCH, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, DONTHURTSPECIES, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, SHIELDREFLECT, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, DEFLECT, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, ALLOWPARTICLES, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, EXTREMEDEATH, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, NOEXTREMEDEATH, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, FRIGHTENED, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, NOBOUNCESOUND, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, NOSKIN, AActor, flags4),
|
||||
DEFINE_FLAG(MF4, BOSSDEATH, AActor, flags4),
|
||||
|
||||
DEFINE_FLAG(MF5, FASTER, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, FASTMELEE, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, NODROPOFF, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, BOUNCEONACTORS, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, EXPLODEONWATER, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, NODAMAGE, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, BLOODSPLATTER, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, OLDRADIUSDMG, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, DEHEXPLOSION, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, PIERCEARMOR, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, NOBLOODDECALS, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, USESPECIAL, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, NOPAIN, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, ALWAYSFAST, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, NEVERFAST, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, ALWAYSRESPAWN, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, NEVERRESPAWN, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, DONTRIP, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, NOINFIGHTING, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, NOINTERACTION, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, NOTIMEFREEZE, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, PUFFGETSOWNER, AActor, flags5), // [BB] added PUFFGETSOWNER
|
||||
DEFINE_FLAG(MF5, SPECIALFIREDAMAGE, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, SUMMONEDMONSTER, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, NOVERTICALMELEERANGE, AActor, flags5),
|
||||
|
||||
// Effect flags
|
||||
DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects),
|
||||
DEFINE_FLAG2(FX_ROCKET, ROCKETTRAIL, AActor, effects),
|
||||
DEFINE_FLAG2(FX_GRENADE, GRENADETRAIL, AActor, effects),
|
||||
DEFINE_FLAG(RF, INVISIBLE, AActor, renderflags),
|
||||
DEFINE_FLAG(RF, FORCEYBILLBOARD, AActor, renderflags),
|
||||
DEFINE_FLAG(RF, FORCEXYBILLBOARD, AActor, renderflags),
|
||||
|
||||
// Deprecated flags. Handling must be performed in HandleDeprecatedFlags
|
||||
DEFINE_DEPRECATED_FLAG(FIREDAMAGE),
|
||||
DEFINE_DEPRECATED_FLAG(ICEDAMAGE),
|
||||
DEFINE_DEPRECATED_FLAG(LOWGRAVITY),
|
||||
DEFINE_DEPRECATED_FLAG(SHORTMISSILERANGE),
|
||||
DEFINE_DEPRECATED_FLAG(LONGMELEERANGE),
|
||||
DEFINE_DEPRECATED_FLAG(QUARTERGRAVITY),
|
||||
DEFINE_DEPRECATED_FLAG(FIRERESIST),
|
||||
DEFINE_DUMMY_FLAG(NONETID),
|
||||
DEFINE_DUMMY_FLAG(ALLOWCLIENTSPAWN),
|
||||
};
|
||||
|
||||
static FFlagDef InventoryFlags[] =
|
||||
{
|
||||
// Inventory flags
|
||||
DEFINE_FLAG(IF, QUIET, AInventory, ItemFlags),
|
||||
DEFINE_FLAG(IF, AUTOACTIVATE, AInventory, ItemFlags),
|
||||
DEFINE_FLAG(IF, UNDROPPABLE, AInventory, ItemFlags),
|
||||
DEFINE_FLAG(IF, INVBAR, AInventory, ItemFlags),
|
||||
DEFINE_FLAG(IF, HUBPOWER, AInventory, ItemFlags),
|
||||
DEFINE_FLAG(IF, INTERHUBSTRIP, AInventory, ItemFlags),
|
||||
DEFINE_FLAG(IF, ALWAYSPICKUP, AInventory, ItemFlags),
|
||||
DEFINE_FLAG(IF, FANCYPICKUPSOUND, AInventory, ItemFlags),
|
||||
DEFINE_FLAG(IF, BIGPOWERUP, AInventory, ItemFlags),
|
||||
DEFINE_FLAG(IF, KEEPDEPLETED, AInventory, ItemFlags),
|
||||
DEFINE_FLAG(IF, IGNORESKILL, AInventory, ItemFlags),
|
||||
DEFINE_FLAG(IF, ADDITIVETIME, AInventory, ItemFlags),
|
||||
DEFINE_FLAG(IF, NOATTENPICKUPSOUND, AInventory, ItemFlags),
|
||||
|
||||
DEFINE_DEPRECATED_FLAG(PICKUPFLASH),
|
||||
|
||||
};
|
||||
|
||||
static FFlagDef WeaponFlags[] =
|
||||
{
|
||||
// Weapon flags
|
||||
DEFINE_FLAG(WIF, NOAUTOFIRE, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, READYSNDHALF, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, DONTBOB, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, AXEBLOOD, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, NOALERT, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, AMMO_OPTIONAL, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, ALT_AMMO_OPTIONAL, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, PRIMARY_USES_BOTH, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, WIMPY_WEAPON, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, POWERED_UP, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, STAFF2_KICKBACK, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF_BOT, EXPLOSIVE, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG2(WIF_BOT_MELEE, MELEEWEAPON, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF_BOT, BFG, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, CHEATNOTWEAPON, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, NO_AUTO_SWITCH, AWeapon, WeaponFlags),
|
||||
|
||||
DEFINE_DUMMY_FLAG(NOLMS),
|
||||
};
|
||||
|
||||
static const struct { const PClass *Type; FFlagDef *Defs; int NumDefs; } FlagLists[] =
|
||||
{
|
||||
{ RUNTIME_CLASS(AActor), ActorFlags, sizeof(ActorFlags)/sizeof(FFlagDef) },
|
||||
{ RUNTIME_CLASS(AInventory), InventoryFlags, sizeof(InventoryFlags)/sizeof(FFlagDef) },
|
||||
{ RUNTIME_CLASS(AWeapon), WeaponFlags, sizeof(WeaponFlags)/sizeof(FFlagDef) }
|
||||
};
|
||||
#define NUM_FLAG_LISTS 3
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Find a flag by name using a binary search
|
||||
//
|
||||
//==========================================================================
|
||||
static int STACK_ARGS flagcmp (const void * a, const void * b)
|
||||
{
|
||||
return stricmp( ((FFlagDef*)a)->name, ((FFlagDef*)b)->name);
|
||||
}
|
||||
|
||||
static FFlagDef *FindFlag (FFlagDef *flags, int numflags, const char *flag)
|
||||
{
|
||||
int min = 0, max = numflags - 1;
|
||||
|
||||
while (min <= max)
|
||||
{
|
||||
int mid = (min + max) / 2;
|
||||
int lexval = stricmp (flag, flags[mid].name);
|
||||
if (lexval == 0)
|
||||
{
|
||||
return &flags[mid];
|
||||
}
|
||||
else if (lexval > 0)
|
||||
{
|
||||
min = mid + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
max = mid - 1;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FFlagDef *FindFlag (const PClass *type, const char *part1, const char *part2)
|
||||
{
|
||||
static bool flagsorted = false;
|
||||
FFlagDef *def;
|
||||
int i;
|
||||
|
||||
if (!flagsorted)
|
||||
{
|
||||
for (i = 0; i < NUM_FLAG_LISTS; ++i)
|
||||
{
|
||||
qsort (FlagLists[i].Defs, FlagLists[i].NumDefs, sizeof(FFlagDef), flagcmp);
|
||||
}
|
||||
flagsorted = true;
|
||||
}
|
||||
if (part2 == NULL)
|
||||
{ // Search all lists
|
||||
for (i = 0; i < NUM_FLAG_LISTS; ++i)
|
||||
{
|
||||
if (type->IsDescendantOf (FlagLists[i].Type))
|
||||
{
|
||||
def = FindFlag (FlagLists[i].Defs, FlagLists[i].NumDefs, part1);
|
||||
if (def != NULL)
|
||||
{
|
||||
return def;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // Search just the named list
|
||||
for (i = 0; i < NUM_FLAG_LISTS; ++i)
|
||||
{
|
||||
if (stricmp (FlagLists[i].Type->TypeName.GetChars(), part1) == 0)
|
||||
{
|
||||
if (type->IsDescendantOf (FlagLists[i].Type))
|
||||
{
|
||||
return FindFlag (FlagLists[i].Defs, FlagLists[i].NumDefs, part2);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// HandleDeprecatedFlags
|
||||
|
@ -2149,53 +1823,3 @@ DEFINE_CLASS_PROPERTY(unmorphflash, S, PowerMorph)
|
|||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Find a property by name using a binary search
|
||||
//
|
||||
//==========================================================================
|
||||
static int STACK_ARGS propcmp(const void * a, const void * b)
|
||||
{
|
||||
return stricmp( (*(FPropertyInfo**)a)->name, (*(FPropertyInfo**)b)->name);
|
||||
}
|
||||
|
||||
static TArray<FPropertyInfo*> properties;
|
||||
|
||||
FPropertyInfo *FindProperty(const char * string)
|
||||
{
|
||||
static bool propsorted=false;
|
||||
|
||||
if (!propsorted)
|
||||
{
|
||||
TAutoSegIterator<FPropertyInfo *, &GRegHead, &GRegTail> probe;
|
||||
|
||||
while (++probe != NULL)
|
||||
{
|
||||
properties.Push(probe);
|
||||
}
|
||||
properties.ShrinkToFit();
|
||||
qsort(&properties[0], properties.Size(), sizeof(properties[0]), propcmp);
|
||||
propsorted=true;
|
||||
}
|
||||
|
||||
int min = 0, max = properties.Size()-1;
|
||||
|
||||
while (min <= max)
|
||||
{
|
||||
int mid = (min + max) / 2;
|
||||
int lexval = stricmp (string, properties[mid]->name);
|
||||
if (lexval == 0)
|
||||
{
|
||||
return properties[mid];
|
||||
}
|
||||
else if (lexval > 0)
|
||||
{
|
||||
min = mid + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
max = mid - 1;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -57,80 +57,6 @@
|
|||
#include "colormatcher.h"
|
||||
|
||||
TArray<int> StateParameters;
|
||||
static TArray<AFuncDesc> AFTable;
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Action functions
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Find a function by name using a binary search
|
||||
//
|
||||
//==========================================================================
|
||||
static int STACK_ARGS funccmp(const void * a, const void * b)
|
||||
{
|
||||
return stricmp( ((AFuncDesc*)a)->Name, ((AFuncDesc*)b)->Name);
|
||||
}
|
||||
|
||||
AFuncDesc * FindFunction(const char * string)
|
||||
{
|
||||
static bool funcsorted=false;
|
||||
|
||||
if (!funcsorted)
|
||||
{
|
||||
TAutoSegIterator<AFuncDesc *, &ARegHead, &ARegTail> probe;
|
||||
|
||||
while (++probe != NULL)
|
||||
{
|
||||
AFTable.Push(*probe);
|
||||
}
|
||||
AFTable.ShrinkToFit();
|
||||
qsort(&AFTable[0], AFTable.Size(), sizeof(AFTable[0]), funccmp);
|
||||
funcsorted=true;
|
||||
}
|
||||
|
||||
int min = 0, max = AFTable.Size()-1;
|
||||
|
||||
while (min <= max)
|
||||
{
|
||||
int mid = (min + max) / 2;
|
||||
int lexval = stricmp (string, AFTable[mid].Name);
|
||||
if (lexval == 0)
|
||||
{
|
||||
return &AFTable[mid];
|
||||
}
|
||||
else if (lexval > 0)
|
||||
{
|
||||
min = mid + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
max = mid - 1;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Find an action function in AActor's table
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
PSymbolActionFunction *FindGlobalActionFunction(const char *name)
|
||||
{
|
||||
PSymbol *sym = RUNTIME_CLASS(AActor)->Symbols.FindSymbol(name, false);
|
||||
if (sym != NULL && sym->SymbolType == SYM_ActionFunction)
|
||||
return static_cast<PSymbolActionFunction*>(sym);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
91
src/thingdef/thingdef_type.h
Normal file
91
src/thingdef/thingdef_type.h
Normal file
|
@ -0,0 +1,91 @@
|
|||
#ifndef THINGDEF_TYPE_H
|
||||
#define THINGDEF_TYPE_H
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
enum ExpValType
|
||||
{
|
||||
VAL_Int,
|
||||
VAL_Float,
|
||||
VAL_Unknown,
|
||||
VAL_Array,
|
||||
VAL_Object,
|
||||
VAL_Class,
|
||||
VAL_Pointer,
|
||||
|
||||
// only used for accessing external variables to ensure proper conversion
|
||||
VAL_Fixed,
|
||||
VAL_Angle,
|
||||
VAL_Bool,
|
||||
};
|
||||
|
||||
struct FExpressionType
|
||||
{
|
||||
BYTE Type;
|
||||
BYTE BaseType;
|
||||
WORD size; // for arrays;
|
||||
const PClass *ClassType;
|
||||
|
||||
FExpressionType &operator=(int typeval)
|
||||
{
|
||||
Type = typeval;
|
||||
BaseType = 0;
|
||||
size = 0;
|
||||
ClassType = NULL;
|
||||
return *this;
|
||||
}
|
||||
|
||||
FExpressionType &operator=(const PClass *cls)
|
||||
{
|
||||
Type = VAL_Class;
|
||||
BaseType = 0;
|
||||
size = 0;
|
||||
ClassType = cls;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(int typeval) const
|
||||
{
|
||||
return Type == typeval;
|
||||
}
|
||||
|
||||
bool operator!=(int typeval) const
|
||||
{
|
||||
return Type != typeval;
|
||||
}
|
||||
|
||||
bool isNumeric() const
|
||||
{
|
||||
return Type == VAL_Float || Type == VAL_Int;
|
||||
}
|
||||
|
||||
bool isPointer() const
|
||||
{
|
||||
return Type == VAL_Object || Type == VAL_Class;
|
||||
}
|
||||
|
||||
FExpressionType GetBaseType() const
|
||||
{
|
||||
FExpressionType ret = *this;
|
||||
ret.Type = BaseType;
|
||||
ret.BaseType = 0;
|
||||
ret.size = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
// currently only used for args[].
|
||||
// Needs to be done differently for a generic implementation!
|
||||
void MakeArray(int siz)
|
||||
{
|
||||
BaseType = Type;
|
||||
Type = VAL_Array;
|
||||
size = siz;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -75,7 +75,7 @@
|
|||
// SAVESIG should match SAVEVER.
|
||||
|
||||
// MINSAVEVER is the minimum level snapshot version that can be loaded.
|
||||
#define MINSAVEVER 1253
|
||||
#define MINSAVEVER 1271
|
||||
|
||||
#if SVN_REVISION_NUMBER < MINSAVEVER
|
||||
// Never write a savegame with a version lower than what we need
|
||||
|
|
|
@ -18,6 +18,28 @@ ACTOR Actor native //: Thinker
|
|||
FloatSpeed 4
|
||||
Gravity 1
|
||||
|
||||
// Variables for the expression evaluator
|
||||
// NOTE: fixed_t and angle_t are only used here to ensure proper conversion
|
||||
// Internally they are handled as floats.
|
||||
// Variables must be native.
|
||||
native fixed_t alpha;
|
||||
native angle_t angle;
|
||||
native int args[5];
|
||||
native fixed_t ceilingz;
|
||||
native fixed_t floorz;
|
||||
native int health;
|
||||
native angle_t pitch;
|
||||
native int special;
|
||||
native int tid;
|
||||
native int TIDtoHate;
|
||||
native int waterlevel;
|
||||
native fixed_t x;
|
||||
native fixed_t y;
|
||||
native fixed_t z;
|
||||
native fixed_t momx;
|
||||
native fixed_t momy;
|
||||
native fixed_t momz;
|
||||
|
||||
action native A_MonsterRail();
|
||||
action native A_BFGSpray(class<Actor> spraytype = "BFGExtra", int numrays = 40, int damagecount = 15);
|
||||
action native A_Pain();
|
||||
|
|
|
@ -43,3 +43,6 @@ const int MRF_NEWTIDBEHAVIOUR = 256;
|
|||
const int MRF_UNDOBYDEATH = 512;
|
||||
const int MRF_UNDOBYDEATHFORCED = 1024;
|
||||
const int MRF_UNDOBYDEATHSAVES = 2048;
|
||||
|
||||
// This is only here to provide one global variable for testing.
|
||||
native int testglobalvar;
|
||||
|
|
|
@ -1059,6 +1059,10 @@
|
|||
RelativePath=".\src\thingdef\thingdef_codeptr.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\thingdef\thingdef_data.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\thingdef\thingdef_exp.cpp"
|
||||
>
|
||||
|
@ -1087,6 +1091,10 @@
|
|||
RelativePath=".\src\thingdef\thingdef_states.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\thingdef\thingdef_type.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
|
|
Loading…
Reference in a new issue