- added a dummy struct named '_' to define global variables. This can only be used internally.

This method was chosen because it avoids adding variable declarations to the global namespace which would have required a lot more work while polluting the grammar.
This way the global variables can be handled by a small bit of special coding in the struct generator.
This commit is contained in:
Christoph Oelckers 2017-03-13 14:42:14 +01:00
parent feb680a4eb
commit cd392e50e9
15 changed files with 135 additions and 153 deletions

View File

@ -158,6 +158,9 @@ FKeyBindings Bindings;
FKeyBindings DoubleBindings;
FKeyBindings AutomapBindings;
DEFINE_GLOBAL(Bindings)
DEFINE_GLOBAL(AutomapBindings)
static unsigned int DClickTime[NUM_KEYS];
static uint8_t DClicked[(NUM_KEYS+7)/8];

View File

@ -212,6 +212,7 @@ DehInfo deh =
40, // BFG cells per shot
};
DEFINE_GLOBAL(deh)
DEFINE_FIELD_X(DehInfo, DehInfo, MaxSoulsphere)
DEFINE_FIELD_X(DehInfo, DehInfo, ExplosionStyle)
DEFINE_FIELD_X(DehInfo, DehInfo, ExplosionAlpha)

View File

@ -2982,3 +2982,18 @@ bool G_CheckDemoStatus (void)
return false;
}
DEFINE_GLOBAL(players)
DEFINE_GLOBAL(playeringame)
DEFINE_GLOBAL(PlayerClasses)
DEFINE_GLOBAL_NAMED(Skins, PlayerSkins)
DEFINE_GLOBAL(consoleplayer)
DEFINE_GLOBAL_NAMED(PClassActor::AllActorClasses, AllActorClasses)
DEFINE_GLOBAL(validcount)
DEFINE_GLOBAL(multiplayer)
DEFINE_GLOBAL(gameaction)
DEFINE_GLOBAL(gamestate)
DEFINE_GLOBAL(skyflatnum)
DEFINE_GLOBAL_NAMED(bglobal.freeze, globalfreeze)
DEFINE_GLOBAL(gametic)
DEFINE_GLOBAL(demoplayback)

View File

@ -1901,7 +1901,7 @@ void FLevelLocals::AddScroller (int secnum)
//
//
//==========================================================================
DEFINE_GLOBAL(level);
DEFINE_FIELD(FLevelLocals, sectors)
DEFINE_FIELD(FLevelLocals, lines)
DEFINE_FIELD(FLevelLocals, sides)

View File

@ -45,6 +45,7 @@
gameinfo_t gameinfo;
DEFINE_GLOBAL(gameinfo)
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, backpacktype)
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, Armor2Percent)
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, ArmorIcon1)

View File

@ -1057,7 +1057,9 @@ CCMD(undocolorpic)
}
DEFINE_GLOBAL(menuactive)
DEFINE_GLOBAL(BackbuttonTime)
DEFINE_GLOBAL(BackbuttonAlpha)
DEFINE_FIELD(DMenu, mParentMenu)
DEFINE_FIELD(DMenu, mMouseCapture);

View File

@ -67,6 +67,8 @@ PClass *DefaultOptionMenuClass;
void I_BuildALDeviceList(FOptionValues *opt);
DEFINE_GLOBAL_NAMED(OptionSettings, OptionMenuSettings)
DEFINE_ACTION_FUNCTION(FOptionValues, GetCount)
{
PARAM_PROLOGUE;

View File

@ -1,6 +1,7 @@
// 'None' must always be the first name.
xx(None)
xx(Null)
xx(_)
xx(Super)
xx(Object)

View File

@ -664,11 +664,12 @@ AFuncDesc *FindFunction(PStruct *cls, const char * string)
FieldDesc *FindField(PStruct *cls, const char * string)
{
int min = 0, max = FieldTable.Size() - 1;
const char * cname = cls ? cls->TypeName.GetChars() : "";
while (min <= max)
{
int mid = (min + max) / 2;
int lexval = stricmp(cls->TypeName.GetChars(), FieldTable[mid].ClassName + 1);
int lexval = stricmp(cname, FieldTable[mid].ClassName + 1);
if (lexval == 0) lexval = stricmp(string, FieldTable[mid].FieldName);
if (lexval == 0)
{
@ -740,9 +741,7 @@ static int fieldcmp(const void * a, const void * b)
void InitThingdef()
{
// Create all global variables here because this cannot be done on the script side and really isn't worth adding support for.
// Also create all special fields here that cannot be declared by script syntax plus the pointer serializers. Doing all these with class overrides would be a bit messy.
// Some native types need size and serialization information added before the scripts get compiled.
auto secplanestruct = NewNativeStruct("Secplane", nullptr);
secplanestruct->Size = sizeof(secplane_t);
secplanestruct->Align = alignof(secplane_t);
@ -853,140 +852,11 @@ void InitThingdef()
}
);
// expose the global validcount variable.
PField *vcf = new PField("validcount", TypeSInt32, VARF_Native | VARF_Static, (intptr_t)&validcount);
Namespaces.GlobalNamespace->Symbols.AddSymbol(vcf);
// expose the global Multiplayer variable.
PField *multif = new PField("multiplayer", TypeBool, VARF_Native | VARF_ReadOnly | VARF_Static, (intptr_t)&multiplayer);
Namespaces.GlobalNamespace->Symbols.AddSymbol(multif);
// set up a variable for the global level data structure
PStruct *lstruct = NewNativeStruct("LevelLocals", nullptr);
PField *levelf = new PField("level", lstruct, VARF_Native | VARF_Static, (intptr_t)&level);
Namespaces.GlobalNamespace->Symbols.AddSymbol(levelf);
auto aact = NewPointer(NewStaticArray(NewClassPointer(RUNTIME_CLASS(AActor))), true);
PField *aacf = new PField("AllActorClasses", aact, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&PClassActor::AllActorClasses);
Namespaces.GlobalNamespace->Symbols.AddSymbol(aacf);
auto plrcls = NewPointer(NewStaticArray(playerclassstruct), false);
PField *plrclsf = new PField("PlayerClasses", plrcls, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&PlayerClasses);
Namespaces.GlobalNamespace->Symbols.AddSymbol(plrclsf);
auto plrskn = NewPointer(NewStaticArray(playerskinstruct), false);
PField *plrsknf = new PField("PlayerSkins", plrskn, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&Skins);
Namespaces.GlobalNamespace->Symbols.AddSymbol(plrsknf);
auto teamst = NewPointer(NewStaticArray(teamstruct), false);
PField *teamf = new PField("Teams", teamst, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&Teams);
Namespaces.GlobalNamespace->Symbols.AddSymbol(teamf);
auto bindcls = NewNativeStruct("KeyBindings", nullptr);
PField *binding = new PField("Bindings", bindcls, VARF_Native | VARF_Static, (intptr_t)&Bindings);
Namespaces.GlobalNamespace->Symbols.AddSymbol(binding);
binding = new PField("AutomapBindings", bindcls, VARF_Native | VARF_Static, (intptr_t)&AutomapBindings);
Namespaces.GlobalNamespace->Symbols.AddSymbol(binding);
// set up a variable for the DEH data
PStruct *dstruct = NewNativeStruct("DehInfo", nullptr);
PField *dehf = new PField("deh", dstruct, VARF_Native | VARF_Static, (intptr_t)&deh);
Namespaces.GlobalNamespace->Symbols.AddSymbol(dehf);
// set up a variable for the global gameinfo data
PStruct *gistruct = NewNativeStruct("GameInfoStruct", nullptr);
PField *gi = new PField("gameinfo", gistruct, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&gameinfo);
Namespaces.GlobalNamespace->Symbols.AddSymbol(gi);
// set up a variable for the global players array.
PArray *parray = NewArray(pstruct, MAXPLAYERS);
PField *fieldptr = new PField("players", parray, VARF_Native | VARF_Static, (intptr_t)&players);
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
parray = NewArray(TypeBool, MAXPLAYERS);
fieldptr = new PField("playeringame", parray, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&playeringame);
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
fieldptr = new PField("gameaction", TypeUInt32, VARF_Native | VARF_Static, (intptr_t)&gameaction);
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
fieldptr = new PField("gamestate", TypeSInt32, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&gamestate);
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
fieldptr = new PField("skyflatnum", TypeTextureID, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&skyflatnum);
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
fieldptr = new PField("globalfreeze", TypeUInt8, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&bglobal.freeze);
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
fieldptr = new PField("consoleplayer", TypeSInt32, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&consoleplayer);
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
auto fontptr = NewPointer(NewNativeStruct("Font", nullptr));
fieldptr = new PField("smallfont", fontptr, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&SmallFont);
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
fieldptr = new PField("smallfont2", fontptr, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&SmallFont2);
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
fieldptr = new PField("bigfont", fontptr, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&BigFont);
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
fieldptr = new PField("confont", fontptr, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&ConFont);
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
fieldptr = new PField("intermissionfont", fontptr, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&IntermissionFont);
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
fieldptr = new PField("CleanXFac", TypeSInt32, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&CleanXfac);
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
fieldptr = new PField("CleanYFac", TypeSInt32, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&CleanYfac);
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
fieldptr = new PField("CleanWidth", TypeSInt32, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&CleanWidth);
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
fieldptr = new PField("CleanHeight", TypeSInt32, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&CleanHeight);
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
fieldptr = new PField("CleanXFac_1", TypeSInt32, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&CleanXfac_1);
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
fieldptr = new PField("CleanYFac_1", TypeSInt32, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&CleanYfac_1);
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
fieldptr = new PField("CleanWidth_1", TypeSInt32, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&CleanWidth_1);
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
fieldptr = new PField("CleanHeight_1", TypeSInt32, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&CleanHeight_1);
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
fieldptr = new PField("menuactive", TypeSInt32, VARF_Native | VARF_Static, (intptr_t)&menuactive);
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
fieldptr = new PField("OptionMenuSettings", NewStruct("FOptionMenuSettings", nullptr), VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&OptionSettings);
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
fieldptr = new PField("gametic", TypeSInt32, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&gametic);
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
fieldptr = new PField("demoplayback", TypeBool, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&demoplayback);
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
fieldptr = new PField("BackbuttonTime", TypeSInt32, VARF_Native | VARF_Static, (intptr_t)&BackbuttonTime);
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
fieldptr = new PField("BackbuttonAlpha", TypeFloat32, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&BackbuttonAlpha);
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
// Argh. It sucks when bad hacks need to be supported. WP_NOCHANGE is just a bogus pointer but it used everywhere as a special flag.
// It cannot be defined as constant because constants can either be numbers or strings but nothing else, so the only 'solution'
// is to create a static variable from it and reference that in the script. Yuck!!!
wpnochg = WP_NOCHANGE;
fieldptr = new PField("WP_NOCHANGE", NewPointer(RUNTIME_CLASS(AWeapon), false), VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&wpnochg);
PField *fieldptr = new PField("WP_NOCHANGE", NewPointer(RUNTIME_CLASS(AWeapon), false), VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&wpnochg);
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
// synthesize a symbol for each flag from the flag name tables to avoid redundant declaration of them.

View File

@ -1170,7 +1170,12 @@ struct AFuncDesc
MSVC_FSEG FieldDesc const *const VMField_##cls##_##scriptname##_HookPtr GCC_FSEG = &VMField_##cls##_##scriptname;
#define DEFINE_GLOBAL(name) \
static const FieldDesc VMGlobal_##name = { nullptr, #name, (intptr_t)&name, (unsigned)sizeof(name), 0 }; \
static const FieldDesc VMGlobal_##name = { "", #name, (intptr_t)&name, (unsigned)sizeof(name), 0 }; \
extern FieldDesc const *const VMGlobal_##name##_HookPtr; \
MSVC_FSEG FieldDesc const *const VMGlobal_##name##_HookPtr GCC_FSEG = &VMGlobal_##name;
#define DEFINE_GLOBAL_NAMED(iname, name) \
static const FieldDesc VMGlobal_##name = { "", #name, (intptr_t)&iname, (unsigned)sizeof(iname), 0 }; \
extern FieldDesc const *const VMGlobal_##name##_HookPtr; \
MSVC_FSEG FieldDesc const *const VMGlobal_##name##_HookPtr GCC_FSEG = &VMGlobal_##name;

View File

@ -487,7 +487,13 @@ void ZCCCompiler::CreateStructTypes()
syms = &OutNamespace->Symbols;
}
if (s->strct->Flags & ZCC_Native)
if (s->NodeName() == NAME__ && Wads.GetLumpFile(Lump) == 0)
{
// This is just a container for syntactic purposes.
s->strct->Type = nullptr;
continue;
}
else if (s->strct->Flags & ZCC_Native)
{
s->strct->Type = NewNativeStruct(s->NodeName(), outer);
}
@ -776,7 +782,8 @@ void ZCCCompiler::CompileAllConstants()
}
for (auto s : Structs)
{
CopyConstants(constantwork, s->Constants, s->Type(), &s->Type()->Symbols);
if (s->Type() != nullptr)
CopyConstants(constantwork, s->Constants, s->Type(), &s->Type()->Symbols);
}
// Before starting to resolve the list, let's create symbols for all already resolved ones first (i.e. all literal constants), to reduce work.
@ -1048,7 +1055,7 @@ void ZCCCompiler::CompileAllFields()
donesomething = false;
for (unsigned i = 0; i < Structs.Size(); i++)
{
if (CompileFields(Structs[i]->Type(), Structs[i]->Fields, Structs[i]->Outer, &Structs[i]->TreeNodes, true))
if (CompileFields(Structs[i]->Type(), Structs[i]->Fields, Structs[i]->Outer, Structs[i]->Type() == 0? GlobalTreeNodes : &Structs[i]->TreeNodes, true))
{
// Remove from the list if all fields got compiled.
Structs.Delete(i--);
@ -1132,10 +1139,13 @@ bool ZCCCompiler::CompileFields(PStruct *type, TArray<ZCC_VarDeclarator *> &Fiel
if (field->Flags & ZCC_Transient) varflags |= VARF_Transient;
if (mVersion >= MakeVersion(2, 4, 0))
{
if (type->ObjectFlags & OF_UI)
varflags |= VARF_UI;
if (type->ObjectFlags & OF_Play)
varflags |= VARF_Play;
if (type != nullptr)
{
if (type->ObjectFlags & OF_UI)
varflags |= VARF_UI;
if (type->ObjectFlags & OF_Play)
varflags |= VARF_Play;
}
if (field->Flags & ZCC_UIFlag)
varflags = FScopeBarrier::ChangeSideInFlags(varflags, FScopeBarrier::Side_UI);
if (field->Flags & ZCC_Play)
@ -1202,21 +1212,33 @@ bool ZCCCompiler::CompileFields(PStruct *type, TArray<ZCC_VarDeclarator *> &Fiel
fd = FindField(type, FName(name->Name).GetChars());
if (fd == nullptr)
{
Error(field, "The member variable '%s.%s' has not been exported from the executable.", type->TypeName.GetChars(), FName(name->Name).GetChars());
Error(field, "The member variable '%s.%s' has not been exported from the executable.", type == nullptr? "" : type->TypeName.GetChars(), FName(name->Name).GetChars());
}
// For native structs a size check cannot be done because they normally have no size. But for a native reference they are still fine.
else if (thisfieldtype->Size != ~0u && thisfieldtype->Size != fd->FieldSize && fd->BitValue == 0 && !thisfieldtype->IsA(RUNTIME_CLASS(PNativeStruct)))
{
Error(field, "The member variable '%s.%s' has mismatching sizes in internal and external declaration. (Internal = %d, External = %d)", type->TypeName.GetChars(), FName(name->Name).GetChars(), fd->FieldSize, thisfieldtype->Size);
Error(field, "The member variable '%s.%s' has mismatching sizes in internal and external declaration. (Internal = %d, External = %d)", type == nullptr ? "" : type->TypeName.GetChars(), FName(name->Name).GetChars(), fd->FieldSize, thisfieldtype->Size);
}
// Q: Should we check alignment, too? A mismatch may be an indicator for bad assumptions.
else
else if (type != nullptr)
{
// for bit fields the type must point to the source variable.
if (fd->BitValue != 0) thisfieldtype = fd->FieldSize == 1 ? TypeUInt8 : fd->FieldSize == 2 ? TypeUInt16 : TypeUInt32;
auto f = type->AddNativeField(name->Name, thisfieldtype, fd->FieldOffset, varflags, fd->BitValue);
if (field->Flags & (ZCC_Version | ZCC_Deprecated)) f->mVersion = field->Version;
}
else
{
// This is a global variable.
if (fd->BitValue != 0) thisfieldtype = fd->FieldSize == 1 ? TypeUInt8 : fd->FieldSize == 2 ? TypeUInt16 : TypeUInt32;
PField *field = new PField(name->Name, thisfieldtype, varflags | VARF_Native | VARF_Static, fd->FieldOffset, fd->BitValue);
if (OutNamespace->Symbols.AddSymbol(field) == nullptr)
{ // name is already in use
field->Destroy();
return nullptr;
}
}
}
}
else if (hasnativechildren)
@ -1432,7 +1454,7 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n
{
Error(field, "%s: @ not allowed for user scripts", name.GetChars());
}
retval = ResolveUserType(btype, &outertype->Symbols, true);
retval = ResolveUserType(btype, outertype? &outertype->Symbols : nullptr, true);
break;
case ZCC_UserType:
@ -1456,7 +1478,7 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n
break;
default:
retval = ResolveUserType(btype, &outertype->Symbols, false);
retval = ResolveUserType(btype, outertype ? &outertype->Symbols : nullptr, false);
break;
}
break;
@ -1515,7 +1537,7 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n
// This doesn't check the class list directly but the current symbol table to ensure that
// this does not reference a type that got shadowed by a more local definition.
// We first look in the current class and its parents, and then in the current namespace and its parents.
auto sym = outertype->Symbols.FindSymbol(ctype->Restriction->Id, true);
auto sym = outertype ? outertype->Symbols.FindSymbol(ctype->Restriction->Id, true) : nullptr;
if (sym == nullptr) sym = OutNamespace->Symbols.FindSymbol(ctype->Restriction->Id, true);
if (sym == nullptr)
{
@ -1562,8 +1584,10 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n
PType *ZCCCompiler::ResolveUserType(ZCC_BasicType *type, PSymbolTable *symt, bool nativetype)
{
// Check the symbol table for the identifier.
PSymbol *sym = symt->FindSymbol(type->UserType->Id, true);
PSymbol *sym = nullptr;
// We first look in the current class and its parents, and then in the current namespace and its parents.
if (symt != nullptr) sym = symt->FindSymbol(type->UserType->Id, true);
if (sym == nullptr) sym = OutNamespace->Symbols.FindSymbol(type->UserType->Id, true);
if (sym != nullptr && sym->IsKindOf(RUNTIME_CLASS(PSymbolType)))
{

View File

@ -335,4 +335,5 @@ CCMD (teamlist)
}
DEFINE_FIELD_NAMED(FTeam, m_Name, mName)
DEFINE_GLOBAL(Teams)
DEFINE_FIELD_NAMED(FTeam, m_Name, mName)

View File

@ -1783,3 +1783,17 @@ CCMD(vid_listadapters)
if (Video != NULL)
Video->DumpAdapters();
}
DEFINE_GLOBAL(SmallFont)
DEFINE_GLOBAL(SmallFont2)
DEFINE_GLOBAL(BigFont)
DEFINE_GLOBAL(ConFont)
DEFINE_GLOBAL(IntermissionFont)
DEFINE_GLOBAL(CleanXfac)
DEFINE_GLOBAL(CleanYfac)
DEFINE_GLOBAL(CleanWidth)
DEFINE_GLOBAL(CleanHeight)
DEFINE_GLOBAL(CleanXfac_1)
DEFINE_GLOBAL(CleanYfac_1)
DEFINE_GLOBAL(CleanWidth_1)
DEFINE_GLOBAL(CleanHeight_1)

View File

@ -1,3 +1,46 @@
struct _ native
{
native readonly Array<class<Actor> > AllActorClasses;
native readonly Array<@PlayerClass> PlayerClasses;
native readonly Array<@PlayerSkin> PlayerSkins;
native readonly Array<@Team> Teams;
native int validcount;
native readonly bool multiplayer;
native play @LevelLocals level;
native @KeyBindings Bindings;
native @KeyBindings AutomapBindings;
native play @DehInfo deh;
native readonly @GameInfoStruct gameinfo;
native play @PlayerInfo players[MAXPLAYERS];
native readonly bool playeringame[MAXPLAYERS];
native play uint gameaction;
native readonly int gamestate;
native readonly TextureID skyflatnum;
native readonly uint8 globalfreeze;
native readonly int consoleplayer;
native readonly Font smallfont;
native readonly Font smallfont2;
native readonly Font bigfont;
native readonly Font confont;
native readonly Font intermissionfont;
native readonly int CleanXFac;
native readonly int CleanYFac;
native readonly int CleanWidth;
native readonly int CleanHeight;
native readonly int CleanXFac_1;
native readonly int CleanYFac_1;
native readonly int CleanWidth_1;
native readonly int CleanHeight_1;
native ui int menuactive;
native readonly @FOptionMenuSettings OptionMenuSettings;
native readonly int gametic;
native readonly bool demoplayback;
native ui int BackbuttonTime;
native ui float BackbuttonAlpha;
}
struct TexMan
{
enum EUseTypes

View File

@ -32,7 +32,7 @@
**
*/
struct FOptionMenuSettings version("2.4")
struct FOptionMenuSettings native version("2.4")
{
int mTitleColor;
int mFontColor;