- 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:
Christoph Oelckers 2008-10-19 21:43:36 +00:00
parent 633154d46f
commit b9afb78523
28 changed files with 3868 additions and 2919 deletions

View File

@ -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.

View File

@ -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

View File

@ -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)

View File

@ -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
{

View File

@ -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

View File

@ -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

View File

@ -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 -----------------------------------------------------------

View File

@ -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];

View File

@ -914,6 +914,8 @@ FString FScanner::TokenName (int token, const char *string)
"'breakable'",
"'projectile'",
"'#include'",
"'fixed_t'",
"'angle_t'",
};
FString work;

View File

@ -209,6 +209,8 @@ enum
TK_Breakable,
TK_Projectile,
TK_Include,
TK_Fixed_t,
TK_Angle_t,
TK_LastToken
};

File diff suppressed because it is too large Load Diff

View File

@ -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); }

View File

@ -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,

View File

@ -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

View File

@ -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)

View 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);
}
}

View File

@ -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;
}
}
*/

View File

@ -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()
@ -197,6 +175,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
@ -354,12 +321,14 @@ public:
value = cv;
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

View File

@ -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)
{

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View 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

View File

@ -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

View File

@ -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();

View File

@ -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;

View File

@ -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