mirror of
https://github.com/ZDoom/qzdoom-gpl.git
synced 2024-11-29 23:23:07 +00:00
This commit is contained in:
commit
7ef8ed5867
54 changed files with 864 additions and 349 deletions
|
@ -644,8 +644,12 @@ bool FConfigFile::ReadConfig (void *file)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Do not process tail of long line
|
// Do not process tail of long line
|
||||||
const bool longline = 255 == strlen(readbuf) && '\n' != readbuf[254];
|
const bool longline = (READBUFFERSIZE - 1) == strlen(readbuf) && '\n' != readbuf[READBUFFERSIZE - 2];
|
||||||
if (!longline)
|
if (longline)
|
||||||
|
{
|
||||||
|
endpt = start + READBUFFERSIZE - 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// Remove white space at end of line
|
// Remove white space at end of line
|
||||||
endpt = start + strlen (start) - 1;
|
endpt = start + strlen (start) - 1;
|
||||||
|
|
|
@ -1316,6 +1316,7 @@ PPointer::PPointer(PType *pointsat, bool isconst)
|
||||||
: PBasicType(sizeof(void *), alignof(void *)), PointedType(pointsat), IsConst(isconst)
|
: PBasicType(sizeof(void *), alignof(void *)), PointedType(pointsat), IsConst(isconst)
|
||||||
{
|
{
|
||||||
mDescriptiveName.Format("Pointer<%s%s>", pointsat->DescriptiveName(), isconst? "readonly " : "");
|
mDescriptiveName.Format("Pointer<%s%s>", pointsat->DescriptiveName(), isconst? "readonly " : "");
|
||||||
|
mVersion = pointsat->mVersion;
|
||||||
SetOps();
|
SetOps();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1518,6 +1519,7 @@ PClassPointer::PClassPointer(PClass *restrict)
|
||||||
// This means we can use the cheapoer non-barriered opcodes here.
|
// This means we can use the cheapoer non-barriered opcodes here.
|
||||||
loadOp = OP_LOS;
|
loadOp = OP_LOS;
|
||||||
storeOp = OP_SP;
|
storeOp = OP_SP;
|
||||||
|
mVersion = restrict->mVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -2522,6 +2524,14 @@ PField::PField(FName name, PType *type, DWORD flags, size_t offset, int bitvalue
|
||||||
else BitValue = -1;
|
else BitValue = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VersionInfo PField::GetVersion()
|
||||||
|
{
|
||||||
|
VersionInfo Highest = { 0,0,0 };
|
||||||
|
if (!(Flags & VARF_Deprecated)) Highest = mVersion;
|
||||||
|
if (Type->mVersion > Highest) Highest = Type->mVersion;
|
||||||
|
return Highest;
|
||||||
|
}
|
||||||
|
|
||||||
/* PProperty *****************************************************************/
|
/* PProperty *****************************************************************/
|
||||||
|
|
||||||
IMPLEMENT_CLASS(PProperty, false, false)
|
IMPLEMENT_CLASS(PProperty, false, false)
|
||||||
|
@ -3146,6 +3156,9 @@ void PClass::Derive(PClass *newclass, FName name)
|
||||||
newclass->Symbols.SetParentTable(&this->Symbols);
|
newclass->Symbols.SetParentTable(&this->Symbols);
|
||||||
newclass->TypeName = name;
|
newclass->TypeName = name;
|
||||||
newclass->mDescriptiveName.Format("Class<%s>", name.GetChars());
|
newclass->mDescriptiveName.Format("Class<%s>", name.GetChars());
|
||||||
|
newclass->mVersion = mVersion;
|
||||||
|
newclass->MetaSize = MetaSize;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -3292,7 +3305,6 @@ PClass *PClass::CreateDerivedClass(FName name, unsigned int size)
|
||||||
type->bRuntimeClass = true;
|
type->bRuntimeClass = true;
|
||||||
Derive(type, name);
|
Derive(type, name);
|
||||||
type->Size = size;
|
type->Size = size;
|
||||||
type->MetaSize = MetaSize;
|
|
||||||
if (size != TentativeClass)
|
if (size != TentativeClass)
|
||||||
{
|
{
|
||||||
type->InitializeDefaults();
|
type->InitializeDefaults();
|
||||||
|
|
|
@ -91,6 +91,7 @@ public:
|
||||||
PSymbolTable Symbols;
|
PSymbolTable Symbols;
|
||||||
bool MemberOnly = false; // type may only be used as a struct/class member but not as a local variable or function argument.
|
bool MemberOnly = false; // type may only be used as a struct/class member but not as a local variable or function argument.
|
||||||
FString mDescriptiveName;
|
FString mDescriptiveName;
|
||||||
|
VersionInfo mVersion = { 0,0,0 };
|
||||||
BYTE loadOp, storeOp, moveOp, RegType, RegCount;
|
BYTE loadOp, storeOp, moveOp, RegType, RegCount;
|
||||||
|
|
||||||
PType(unsigned int size = 1, unsigned int align = 1);
|
PType(unsigned int size = 1, unsigned int align = 1);
|
||||||
|
|
|
@ -193,6 +193,38 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct VersionInfo
|
||||||
|
{
|
||||||
|
uint16_t major;
|
||||||
|
uint16_t minor;
|
||||||
|
uint32_t revision;
|
||||||
|
|
||||||
|
bool operator <=(const VersionInfo &o) const
|
||||||
|
{
|
||||||
|
return o.major > this->major || (o.major == this->major && o.minor > this->minor) || (o.major == this->major && o.minor == this->minor && o.revision >= this->revision);
|
||||||
|
}
|
||||||
|
bool operator >=(const VersionInfo &o) const
|
||||||
|
{
|
||||||
|
return o.major < this->major || (o.major == this->major && o.minor < this->minor) || (o.major == this->major && o.minor == this->minor && o.revision <= this->revision);
|
||||||
|
}
|
||||||
|
bool operator > (const VersionInfo &o) const
|
||||||
|
{
|
||||||
|
return o.major < this->major || (o.major == this->major && o.minor < this->minor) || (o.major == this->major && o.minor == this->minor && o.revision < this->revision);
|
||||||
|
}
|
||||||
|
bool operator < (const VersionInfo &o) const
|
||||||
|
{
|
||||||
|
return o.major > this->major || (o.major == this->major && o.minor > this->minor) || (o.major == this->major && o.minor == this->minor && o.revision > this->revision);
|
||||||
|
}
|
||||||
|
void operator=(const char *string);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Cannot be a constructor because Lemon would puke on it.
|
||||||
|
inline VersionInfo MakeVersion(unsigned int ma, unsigned int mi, unsigned int re = 0)
|
||||||
|
{
|
||||||
|
return{ (uint16_t)ma, (uint16_t)mi, (uint32_t)re };
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Screenshot buffer image data types
|
// Screenshot buffer image data types
|
||||||
enum ESSType
|
enum ESSType
|
||||||
|
|
|
@ -1463,6 +1463,8 @@ void G_InitLevelLocals ()
|
||||||
level.NextMap = info->NextMap;
|
level.NextMap = info->NextMap;
|
||||||
level.NextSecretMap = info->NextSecretMap;
|
level.NextSecretMap = info->NextSecretMap;
|
||||||
level.F1Pic = info->F1Pic;
|
level.F1Pic = info->F1Pic;
|
||||||
|
level.hazardcolor = info->hazardcolor;
|
||||||
|
level.hazardflash = info->hazardflash;
|
||||||
|
|
||||||
compatflags.Callback();
|
compatflags.Callback();
|
||||||
compatflags2.Callback();
|
compatflags2.Callback();
|
||||||
|
|
|
@ -315,6 +315,8 @@ struct level_info_t
|
||||||
FName Intermission;
|
FName Intermission;
|
||||||
FName deathsequence;
|
FName deathsequence;
|
||||||
FName slideshow;
|
FName slideshow;
|
||||||
|
DWORD hazardcolor;
|
||||||
|
DWORD hazardflash;
|
||||||
|
|
||||||
// Redirection: If any player is carrying the specified item, then
|
// Redirection: If any player is carrying the specified item, then
|
||||||
// you go to the RedirectMap instead of this one.
|
// you go to the RedirectMap instead of this one.
|
||||||
|
|
|
@ -43,6 +43,9 @@ struct FLevelLocals
|
||||||
DWORD fadeto; // The color the palette fades to (usually black)
|
DWORD fadeto; // The color the palette fades to (usually black)
|
||||||
DWORD outsidefog; // The fog for sectors with sky ceilings
|
DWORD outsidefog; // The fog for sectors with sky ceilings
|
||||||
|
|
||||||
|
DWORD hazardcolor; // what color strife hazard blends the screen color as
|
||||||
|
DWORD hazardflash; // what color strife hazard flashes the screen color as
|
||||||
|
|
||||||
FString Music;
|
FString Music;
|
||||||
int musicorder;
|
int musicorder;
|
||||||
int cdtrack;
|
int cdtrack;
|
||||||
|
|
|
@ -273,6 +273,8 @@ void level_info_t::Reset()
|
||||||
SndSeq = "";
|
SndSeq = "";
|
||||||
BorderTexture = "";
|
BorderTexture = "";
|
||||||
teamdamage = 0.f;
|
teamdamage = 0.f;
|
||||||
|
hazardcolor = 0xff004200;
|
||||||
|
hazardflash = 0xff00ff00;
|
||||||
specialactions.Clear();
|
specialactions.Clear();
|
||||||
DefaultEnvironment = 0;
|
DefaultEnvironment = 0;
|
||||||
PrecacheSounds.Clear();
|
PrecacheSounds.Clear();
|
||||||
|
@ -1200,6 +1202,20 @@ DEFINE_MAP_OPTION(defaultenvironment, false)
|
||||||
info->DefaultEnvironment = id;
|
info->DefaultEnvironment = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_MAP_OPTION(hazardcolor, true)
|
||||||
|
{
|
||||||
|
parse.ParseAssign();
|
||||||
|
parse.sc.MustGetString();
|
||||||
|
info->hazardcolor = V_GetColor(NULL, parse.sc);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_MAP_OPTION(hazardflash, true)
|
||||||
|
{
|
||||||
|
parse.ParseAssign();
|
||||||
|
parse.sc.MustGetString();
|
||||||
|
info->hazardflash = V_GetColor(NULL, parse.sc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
|
|
@ -143,17 +143,26 @@ bool OpenGLFrameBuffer::WipeStartScreen(int type)
|
||||||
glFinish();
|
glFinish();
|
||||||
wipestartscreen->Bind(0, false, false);
|
wipestartscreen->Bind(0, false, false);
|
||||||
|
|
||||||
|
const auto copyPixels = [&viewport]()
|
||||||
|
{
|
||||||
|
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, viewport.left, viewport.top, viewport.width, viewport.height);
|
||||||
|
};
|
||||||
|
|
||||||
if (FGLRenderBuffers::IsEnabled())
|
if (FGLRenderBuffers::IsEnabled())
|
||||||
{
|
{
|
||||||
GLRenderer->mBuffers->BindCurrentFB();
|
GLRenderer->mBuffers->BindCurrentFB();
|
||||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, viewport.left, viewport.top, viewport.width, viewport.height);
|
copyPixels();
|
||||||
|
}
|
||||||
|
else if (gl.legacyMode)
|
||||||
|
{
|
||||||
|
copyPixels();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GLint readbuffer = 0;
|
GLint readbuffer = 0;
|
||||||
glGetIntegerv(GL_READ_BUFFER, &readbuffer);
|
glGetIntegerv(GL_READ_BUFFER, &readbuffer);
|
||||||
glReadBuffer(GL_FRONT);
|
glReadBuffer(GL_FRONT);
|
||||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, viewport.left, viewport.top, viewport.width, viewport.height);
|
copyPixels();
|
||||||
glReadBuffer(readbuffer);
|
glReadBuffer(readbuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9088,6 +9088,35 @@ scriptwait:
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PCD_TRANSLATIONRANGE4:
|
||||||
|
{ // Colourise translation
|
||||||
|
int start = STACK(5);
|
||||||
|
int end = STACK(4);
|
||||||
|
int r = STACK(3);
|
||||||
|
int g = STACK(2);
|
||||||
|
int b = STACK(1);
|
||||||
|
sp -= 5;
|
||||||
|
|
||||||
|
if (translation != NULL)
|
||||||
|
translation->AddColourisation(start, end, r, g, b);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PCD_TRANSLATIONRANGE5:
|
||||||
|
{ // Tint translation
|
||||||
|
int start = STACK(6);
|
||||||
|
int end = STACK(5);
|
||||||
|
int a = STACK(4);
|
||||||
|
int r = STACK(3);
|
||||||
|
int g = STACK(2);
|
||||||
|
int b = STACK(1);
|
||||||
|
sp -= 6;
|
||||||
|
|
||||||
|
if (translation != NULL)
|
||||||
|
translation->AddTint(start, end, r, g, b, a);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case PCD_ENDTRANSLATION:
|
case PCD_ENDTRANSLATION:
|
||||||
if (translation != NULL)
|
if (translation != NULL)
|
||||||
{
|
{
|
||||||
|
|
|
@ -779,6 +779,8 @@ public:
|
||||||
/*380*/ PCD_STRCPYTOSCRIPTCHRANGE,
|
/*380*/ PCD_STRCPYTOSCRIPTCHRANGE,
|
||||||
PCD_LSPEC5EX,
|
PCD_LSPEC5EX,
|
||||||
PCD_LSPEC5EXRESULT,
|
PCD_LSPEC5EXRESULT,
|
||||||
|
PCD_TRANSLATIONRANGE4,
|
||||||
|
PCD_TRANSLATIONRANGE5,
|
||||||
|
|
||||||
/*381*/ PCODE_COMMAND_COUNT
|
/*381*/ PCODE_COMMAND_COUNT
|
||||||
};
|
};
|
||||||
|
|
|
@ -487,6 +487,56 @@ void FRemapTable::AddDesaturation(int start, int end, double r1, double g1, doub
|
||||||
//
|
//
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void FRemapTable::AddColourisation(int start, int end, int r, int g, int b)
|
||||||
|
{
|
||||||
|
for (int i = start; i < end; ++i)
|
||||||
|
{
|
||||||
|
float br = GPalette.BaseColors[i].r;
|
||||||
|
float bg = GPalette.BaseColors[i].g;
|
||||||
|
float bb = GPalette.BaseColors[i].b;
|
||||||
|
float grey = (br * 0.299 + bg * 0.587 + bb * 0.114) / 255.0f;
|
||||||
|
if (grey > 1.0) grey = 1.0;
|
||||||
|
br = r * grey;
|
||||||
|
bg = g * grey;
|
||||||
|
bb = b * grey;
|
||||||
|
|
||||||
|
int j = GPalette.Remap[i];
|
||||||
|
Palette[j] = PalEntry(j == 0 ? 0 : 255, int(br), int(bg), int(bb));
|
||||||
|
Remap[j] = ColorMatcher.Pick(Palette[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void FRemapTable::AddTint(int start, int end, int r, int g, int b, int amount)
|
||||||
|
{
|
||||||
|
for (int i = start; i < end; ++i)
|
||||||
|
{
|
||||||
|
float br = GPalette.BaseColors[i].r;
|
||||||
|
float bg = GPalette.BaseColors[i].g;
|
||||||
|
float bb = GPalette.BaseColors[i].b;
|
||||||
|
float a = amount * 0.01f;
|
||||||
|
float ia = 1.0f - a;
|
||||||
|
br = br * ia + r * a;
|
||||||
|
bg = bg * ia + g * a;
|
||||||
|
bb = bb * ia + b * a;
|
||||||
|
|
||||||
|
int j = GPalette.Remap[i];
|
||||||
|
Palette[j] = PalEntry(j == 0 ? 0 : 255, int(br), int(bg), int(bb));
|
||||||
|
Remap[j] = ColorMatcher.Pick(Palette[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
void FRemapTable::AddToTranslation(const char *range)
|
void FRemapTable::AddToTranslation(const char *range)
|
||||||
{
|
{
|
||||||
int start,end;
|
int start,end;
|
||||||
|
@ -511,19 +561,9 @@ void FRemapTable::AddToTranslation(const char *range)
|
||||||
}
|
}
|
||||||
|
|
||||||
sc.MustGetAnyToken();
|
sc.MustGetAnyToken();
|
||||||
|
Printf(0, "token type: %d", sc.TokenType);
|
||||||
|
|
||||||
if (sc.TokenType != '[' && sc.TokenType != '%')
|
if (sc.TokenType == '[')
|
||||||
{
|
|
||||||
int pal1,pal2;
|
|
||||||
|
|
||||||
sc.TokenMustBe(TK_IntConst);
|
|
||||||
pal1 = sc.Number;
|
|
||||||
sc.MustGetToken(':');
|
|
||||||
sc.MustGetToken(TK_IntConst);
|
|
||||||
pal2 = sc.Number;
|
|
||||||
AddIndexRange(start, end, pal1, pal2);
|
|
||||||
}
|
|
||||||
else if (sc.TokenType == '[')
|
|
||||||
{
|
{
|
||||||
// translation using RGB values
|
// translation using RGB values
|
||||||
int r1,g1,b1,r2,g2,b2;
|
int r1,g1,b1,r2,g2,b2;
|
||||||
|
@ -596,6 +636,54 @@ void FRemapTable::AddToTranslation(const char *range)
|
||||||
|
|
||||||
AddDesaturation(start, end, r1, g1, b1, r2, g2, b2);
|
AddDesaturation(start, end, r1, g1, b1, r2, g2, b2);
|
||||||
}
|
}
|
||||||
|
else if (sc.TokenType == '#')
|
||||||
|
{
|
||||||
|
// Colourise translation
|
||||||
|
int r, g, b;
|
||||||
|
sc.MustGetToken('[');
|
||||||
|
sc.MustGetToken(TK_IntConst);
|
||||||
|
r = sc.Number;
|
||||||
|
sc.MustGetToken(',');
|
||||||
|
sc.MustGetToken(TK_IntConst);
|
||||||
|
g = sc.Number;
|
||||||
|
sc.MustGetToken(',');
|
||||||
|
sc.MustGetToken(TK_IntConst);
|
||||||
|
b = sc.Number;
|
||||||
|
sc.MustGetToken(']');
|
||||||
|
|
||||||
|
AddColourisation(start, end, r, g, b);
|
||||||
|
}
|
||||||
|
else if (sc.TokenType == '@')
|
||||||
|
{
|
||||||
|
// Tint translation
|
||||||
|
int a, r, g, b;
|
||||||
|
|
||||||
|
sc.MustGetToken(TK_IntConst);
|
||||||
|
a = sc.Number;
|
||||||
|
sc.MustGetToken('[');
|
||||||
|
sc.MustGetToken(TK_IntConst);
|
||||||
|
r = sc.Number;
|
||||||
|
sc.MustGetToken(',');
|
||||||
|
sc.MustGetToken(TK_IntConst);
|
||||||
|
g = sc.Number;
|
||||||
|
sc.MustGetToken(',');
|
||||||
|
sc.MustGetToken(TK_IntConst);
|
||||||
|
b = sc.Number;
|
||||||
|
sc.MustGetToken(']');
|
||||||
|
|
||||||
|
AddTint(start, end, r, g, b, a);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int pal1, pal2;
|
||||||
|
|
||||||
|
sc.TokenMustBe(TK_IntConst);
|
||||||
|
pal1 = sc.Number;
|
||||||
|
sc.MustGetToken(':');
|
||||||
|
sc.MustGetToken(TK_IntConst);
|
||||||
|
pal2 = sc.Number;
|
||||||
|
AddIndexRange(start, end, pal1, pal2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (CRecoverableError &err)
|
catch (CRecoverableError &err)
|
||||||
{
|
{
|
||||||
|
|
|
@ -42,6 +42,8 @@ struct FRemapTable
|
||||||
void AddIndexRange(int start, int end, int pal1, int pal2);
|
void AddIndexRange(int start, int end, int pal1, int pal2);
|
||||||
void AddColorRange(int start, int end, int r1,int g1, int b1, int r2, int g2, int b2);
|
void AddColorRange(int start, int end, int r1,int g1, int b1, int r2, int g2, int b2);
|
||||||
void AddDesaturation(int start, int end, double r1, double g1, double b1, double r2, double g2, double b2);
|
void AddDesaturation(int start, int end, double r1, double g1, double b1, double r2, double g2, double b2);
|
||||||
|
void AddColourisation(int start, int end, int r, int g, int b);
|
||||||
|
void AddTint(int start, int end, int r, int g, int b, int amount);
|
||||||
void AddToTranslation(const char * range);
|
void AddToTranslation(const char * range);
|
||||||
int StoreTranslation(int slot);
|
int StoreTranslation(int slot);
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,31 @@
|
||||||
|
|
||||||
// CODE --------------------------------------------------------------------
|
// CODE --------------------------------------------------------------------
|
||||||
|
|
||||||
|
void VersionInfo::operator=(const char *string)
|
||||||
|
{
|
||||||
|
char *endp;
|
||||||
|
major = (int16_t)clamp<unsigned long long>(strtoull(string, &endp, 10), 0, USHRT_MAX);
|
||||||
|
if (*endp == '.')
|
||||||
|
{
|
||||||
|
minor = (int16_t)clamp<unsigned long long>(strtoull(endp + 1, &endp, 10), 0, USHRT_MAX);
|
||||||
|
if (*endp == '.')
|
||||||
|
{
|
||||||
|
revision = (int16_t)clamp<unsigned long long>(strtoull(endp + 1, &endp, 10), 0, USHRT_MAX);
|
||||||
|
if (*endp != 0) major = USHRT_MAX;
|
||||||
|
}
|
||||||
|
else if (*endp == 0)
|
||||||
|
{
|
||||||
|
revision = 0;
|
||||||
|
}
|
||||||
|
else major = USHRT_MAX;
|
||||||
|
}
|
||||||
|
else if (*endp == 0)
|
||||||
|
{
|
||||||
|
minor = revision = 0;
|
||||||
|
}
|
||||||
|
else major = USHRT_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// FScanner Constructor
|
// FScanner Constructor
|
||||||
|
|
|
@ -24,6 +24,10 @@ public:
|
||||||
void OpenString(const char *name, FString buffer);
|
void OpenString(const char *name, FString buffer);
|
||||||
void OpenLumpNum(int lump);
|
void OpenLumpNum(int lump);
|
||||||
void Close();
|
void Close();
|
||||||
|
void SetParseVersion(VersionInfo ver)
|
||||||
|
{
|
||||||
|
ParseVersion = ver;
|
||||||
|
}
|
||||||
|
|
||||||
void SetCMode(bool cmode);
|
void SetCMode(bool cmode);
|
||||||
void SetEscape(bool esc);
|
void SetEscape(bool esc);
|
||||||
|
@ -102,6 +106,7 @@ protected:
|
||||||
BYTE StateMode;
|
BYTE StateMode;
|
||||||
bool StateOptions;
|
bool StateOptions;
|
||||||
bool Escape;
|
bool Escape;
|
||||||
|
VersionInfo ParseVersion = { 0, 0, 0 }; // no ZScript extensions by default
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
|
|
@ -143,50 +143,38 @@ std2:
|
||||||
'false' { RET(TK_False); }
|
'false' { RET(TK_False); }
|
||||||
'none' { RET(TK_None); }
|
'none' { RET(TK_None); }
|
||||||
'auto' { RET(TK_Auto); }
|
'auto' { RET(TK_Auto); }
|
||||||
'exec' { RET(TK_Exec); }
|
|
||||||
'property' { RET(TK_Property); }
|
'property' { RET(TK_Property); }
|
||||||
'native' { RET(TK_Native); }
|
'native' { RET(TK_Native); }
|
||||||
'var' { RET(TK_Var); }
|
'var' { RET(TK_Var); }
|
||||||
'out' { RET(TK_Out); }
|
'out' { RET(ParseVersion >= MakeVersion(1, 0, 0)? TK_Out : TK_Identifier); }
|
||||||
'ref' { RET(TK_Ref); }
|
|
||||||
'event' { RET(TK_Event); }
|
|
||||||
'static' { RET(TK_Static); }
|
'static' { RET(TK_Static); }
|
||||||
'transient' { RET(TK_Transient); }
|
'transient' { RET(ParseVersion >= MakeVersion(1, 0, 0)? TK_Transient : TK_Identifier); }
|
||||||
'final' { RET(TK_Final); }
|
'final' { RET(ParseVersion >= MakeVersion(1, 0, 0)? TK_Final : TK_Identifier); }
|
||||||
'throws' { RET(TK_Throws); }
|
'extend' { RET(ParseVersion >= MakeVersion(1, 0, 0)? TK_Extend : TK_Identifier); }
|
||||||
'extend' { RET(TK_Extend); }
|
'protected' { RET(ParseVersion >= MakeVersion(1, 0, 0)? TK_Protected : TK_Identifier); }
|
||||||
'public' { RET(TK_Public); }
|
'private' { RET(ParseVersion >= MakeVersion(1, 0, 0)? TK_Private : TK_Identifier); }
|
||||||
'protected' { RET(TK_Protected); }
|
|
||||||
'private' { RET(TK_Private); }
|
|
||||||
'dot' { RET(TK_Dot); }
|
'dot' { RET(TK_Dot); }
|
||||||
'cross' { RET(TK_Cross); }
|
'cross' { RET(TK_Cross); }
|
||||||
'localized' { RET(TK_Localized); }
|
'virtual' { RET(ParseVersion >= MakeVersion(1, 0, 0)? TK_Virtual : TK_Identifier); }
|
||||||
'latent' { RET(TK_Latent); }
|
'override' { RET(ParseVersion >= MakeVersion(1, 0, 0)? TK_Override : TK_Identifier); }
|
||||||
'singular' { RET(TK_Singular); }
|
'vararg' { RET(ParseVersion >= MakeVersion(1, 0, 0)? TK_VarArg : TK_Identifier); }
|
||||||
'config' { RET(TK_Config); }
|
'ui' { RET(ParseVersion >= MakeVersion(2, 4, 0)? TK_UI : TK_Identifier); }
|
||||||
'coerce' { RET(TK_Coerce); }
|
'play' { RET(ParseVersion >= MakeVersion(2, 4, 0)? TK_Play : TK_Identifier); }
|
||||||
'optional' { RET(TK_Optional); }
|
'clearscope' { RET(ParseVersion >= MakeVersion(2, 4, 0)? TK_ClearScope : TK_Identifier); }
|
||||||
'export' { RET(TK_Export); }
|
'virtualscope' { RET(ParseVersion >= MakeVersion(2, 4, 0)? TK_VirtualScope : TK_Identifier); }
|
||||||
'virtual' { RET(TK_Virtual); }
|
'super' { RET(ParseVersion >= MakeVersion(1, 0, 0)? TK_Super : TK_Identifier); }
|
||||||
'override' { RET(TK_Override); }
|
|
||||||
'vararg' { RET(TK_VarArg); }
|
|
||||||
'ui' { RET(TK_UI); }
|
|
||||||
'play' { RET(TK_Play); }
|
|
||||||
'clearscope' { RET(TK_ClearScope); }
|
|
||||||
'virtualscope' { RET(TK_VirtualScope); }
|
|
||||||
'super' { RET(TK_Super); }
|
|
||||||
'global' { RET(TK_Global); }
|
|
||||||
'stop' { RET(TK_Stop); }
|
'stop' { RET(TK_Stop); }
|
||||||
'null' { RET(TK_Null); }
|
'null' { RET(TK_Null); }
|
||||||
|
|
||||||
'is' { RET(TK_Is); }
|
'is' { RET(ParseVersion >= MakeVersion(1, 0, 0)? TK_Is : TK_Identifier); }
|
||||||
'replaces' { RET(TK_Replaces); }
|
'replaces' { RET(ParseVersion >= MakeVersion(1, 0, 0)? TK_Replaces : TK_Identifier); }
|
||||||
'states' { RET(TK_States); }
|
'states' { RET(TK_States); }
|
||||||
'meta' { RET(TK_Meta); }
|
'meta' { RET(ParseVersion >= MakeVersion(1, 0, 0)? TK_Meta : TK_Identifier); }
|
||||||
'deprecated' { RET(TK_Deprecated); }
|
'deprecated' { RET(ParseVersion >= MakeVersion(1, 0, 0)? TK_Deprecated : TK_Identifier); }
|
||||||
'action' { RET(TK_Action); }
|
'version' { RET(ParseVersion >= MakeVersion(2, 4, 0)? TK_Version : TK_Identifier); }
|
||||||
'readonly' { RET(TK_ReadOnly); }
|
'action' { RET(ParseVersion >= MakeVersion(1, 0, 0)? TK_Action : TK_Identifier); }
|
||||||
'let' { RET(TK_Let); }
|
'readonly' { RET(ParseVersion >= MakeVersion(1, 0, 0)? TK_ReadOnly : TK_Identifier); }
|
||||||
|
'let' { RET(ParseVersion >= MakeVersion(1, 0, 0)? TK_Let : TK_Identifier); }
|
||||||
|
|
||||||
/* Actor state options */
|
/* Actor state options */
|
||||||
'bright' { RET(StateOptions ? TK_Bright : TK_Identifier); }
|
'bright' { RET(StateOptions ? TK_Bright : TK_Identifier); }
|
||||||
|
@ -267,6 +255,8 @@ std2:
|
||||||
"^" { RET('^'); }
|
"^" { RET('^'); }
|
||||||
"|" { RET('|'); }
|
"|" { RET('|'); }
|
||||||
"?" { RET('?'); }
|
"?" { RET('?'); }
|
||||||
|
"#" { RET('#'); }
|
||||||
|
"@" { RET('@'); }
|
||||||
|
|
||||||
[ \t\v\f\r]+ { goto std1; }
|
[ \t\v\f\r]+ { goto std1; }
|
||||||
"\n" { goto newline; }
|
"\n" { goto newline; }
|
||||||
|
|
|
@ -108,8 +108,6 @@ xx(TK_Singular, "'singular'")
|
||||||
xx(TK_Config, "'config'")
|
xx(TK_Config, "'config'")
|
||||||
xx(TK_Coerce, "'coerce'")
|
xx(TK_Coerce, "'coerce'")
|
||||||
xx(TK_Iterator, "'iterator'")
|
xx(TK_Iterator, "'iterator'")
|
||||||
xx(TK_Optional, "'optional'")
|
|
||||||
xx(TK_Export, "'expert'")
|
|
||||||
xx(TK_Virtual, "'virtual'")
|
xx(TK_Virtual, "'virtual'")
|
||||||
xx(TK_VarArg, "'vararg'")
|
xx(TK_VarArg, "'vararg'")
|
||||||
xx(TK_UI, "'ui'")
|
xx(TK_UI, "'ui'")
|
||||||
|
@ -138,6 +136,7 @@ xx(TK_Fail, "'fail'")
|
||||||
xx(TK_Wait, "'wait'")
|
xx(TK_Wait, "'wait'")
|
||||||
xx(TK_Meta, "'meta'")
|
xx(TK_Meta, "'meta'")
|
||||||
xx(TK_Deprecated, "'deprecated'")
|
xx(TK_Deprecated, "'deprecated'")
|
||||||
|
xx(TK_Version, "'version'")
|
||||||
xx(TK_ReadOnly, "'readonly'")
|
xx(TK_ReadOnly, "'readonly'")
|
||||||
|
|
||||||
xx(TK_CanRaise, "'canraise'")
|
xx(TK_CanRaise, "'canraise'")
|
||||||
|
|
|
@ -90,45 +90,24 @@ static const FLOP FxFlops[] =
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// [ZZ] Magic methods to be used in vmexec.h for runtime checking of scope
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
// this can be imported in vmexec.h
|
|
||||||
void FScopeBarrier_ValidateNew(PClass* cls, PFunction* callingfunc)
|
|
||||||
{
|
|
||||||
int outerside = callingfunc->Variants.Size() ? FScopeBarrier::SideFromFlags(callingfunc->Variants[0].Flags) : FScopeBarrier::Side_Virtual;
|
|
||||||
if (outerside == FScopeBarrier::Side_Virtual)
|
|
||||||
outerside = FScopeBarrier::SideFromObjectFlags(callingfunc->OwningClass->ObjectFlags);
|
|
||||||
int innerside = FScopeBarrier::SideFromObjectFlags(cls->ObjectFlags);
|
|
||||||
if ((outerside != innerside) && (innerside != FScopeBarrier::Side_PlainData)) // "cannot construct ui class ... from data context"
|
|
||||||
ThrowAbortException(X_OTHER, "Cannot construct %s class %s from %s context", FScopeBarrier::StringFromSide(innerside), cls->TypeName.GetChars(), FScopeBarrier::StringFromSide(outerside));
|
|
||||||
}
|
|
||||||
// this can be imported in vmexec.h
|
|
||||||
void FScopeBarrier_ValidateCall(PFunction* calledfunc, PFunction* callingfunc, PClass* selftype)
|
|
||||||
{
|
|
||||||
// [ZZ] anonymous blocks have 0 variants, so give them Side_Virtual.
|
|
||||||
int outerside = callingfunc->Variants.Size() ? FScopeBarrier::SideFromFlags(callingfunc->Variants[0].Flags) : FScopeBarrier::Side_Virtual;
|
|
||||||
if (outerside == FScopeBarrier::Side_Virtual)
|
|
||||||
outerside = FScopeBarrier::SideFromObjectFlags(callingfunc->OwningClass->ObjectFlags);
|
|
||||||
int innerside = FScopeBarrier::SideFromFlags(calledfunc->Variants[0].Flags);
|
|
||||||
if (innerside == FScopeBarrier::Side_Virtual)
|
|
||||||
innerside = FScopeBarrier::SideFromObjectFlags(selftype->ObjectFlags);
|
|
||||||
if ((outerside != innerside) && (innerside != FScopeBarrier::Side_PlainData))
|
|
||||||
ThrowAbortException(X_OTHER, "Cannot call %s function %s from %s context", FScopeBarrier::StringFromSide(innerside), calledfunc->SymbolName.GetChars(), FScopeBarrier::StringFromSide(outerside));
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// FCompileContext
|
// FCompileContext
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
FCompileContext::FCompileContext(PNamespace *cg, PFunction *fnc, PPrototype *ret, bool fromdecorate, int stateindex, int statecount, int lump)
|
FCompileContext::FCompileContext(PNamespace *cg, PFunction *fnc, PPrototype *ret, bool fromdecorate, int stateindex, int statecount, int lump, const VersionInfo &ver)
|
||||||
: ReturnProto(ret), Function(fnc), Class(nullptr), FromDecorate(fromdecorate), StateIndex(stateindex), StateCount(statecount), Lump(lump), CurGlobals(cg)
|
: ReturnProto(ret), Function(fnc), Class(nullptr), FromDecorate(fromdecorate), StateIndex(stateindex), StateCount(statecount), Lump(lump), CurGlobals(cg), Version(ver)
|
||||||
{
|
{
|
||||||
|
if (Version >= MakeVersion(2, 3))
|
||||||
|
{
|
||||||
|
VersionString.Format("ZScript version %d.%d.%d", Version.major, Version.minor, Version.revision);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
VersionString = "DECORATE";
|
||||||
|
}
|
||||||
|
|
||||||
if (fnc != nullptr) Class = fnc->OwningClass;
|
if (fnc != nullptr) Class = fnc->OwningClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -409,7 +388,7 @@ bool FxExpression::isConstant() const
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
VMFunction *FxExpression::GetDirectFunction()
|
VMFunction *FxExpression::GetDirectFunction(const VersionInfo &ver)
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -5986,6 +5965,15 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx)
|
||||||
}
|
}
|
||||||
else if (sym->IsKindOf(RUNTIME_CLASS(PField)))
|
else if (sym->IsKindOf(RUNTIME_CLASS(PField)))
|
||||||
{
|
{
|
||||||
|
PField *vsym = static_cast<PField*>(sym);
|
||||||
|
|
||||||
|
if (vsym->GetVersion() > ctx.Version)
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "%s not accessible to %s", sym->SymbolName.GetChars(), ctx.VersionString.GetChars());
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
// internally defined global variable
|
// internally defined global variable
|
||||||
ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as global variable\n", Identifier.GetChars());
|
ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as global variable\n", Identifier.GetChars());
|
||||||
newex = new FxGlobalVariable(static_cast<PField *>(sym), ScriptPosition);
|
newex = new FxGlobalVariable(static_cast<PField *>(sym), ScriptPosition);
|
||||||
|
@ -6045,7 +6033,8 @@ FxExpression *FxIdentifier::ResolveMember(FCompileContext &ctx, PStruct *classct
|
||||||
if (!objtype->IsKindOf(RUNTIME_CLASS(PClassActor)))
|
if (!objtype->IsKindOf(RUNTIME_CLASS(PClassActor)))
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "'Default' requires an actor type.");
|
ScriptPosition.Message(MSG_ERROR, "'Default' requires an actor type.");
|
||||||
delete this;
|
delete object;
|
||||||
|
object = nullptr;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6067,21 +6056,66 @@ FxExpression *FxIdentifier::ResolveMember(FCompileContext &ctx, PStruct *classct
|
||||||
else if (sym->IsKindOf(RUNTIME_CLASS(PField)))
|
else if (sym->IsKindOf(RUNTIME_CLASS(PField)))
|
||||||
{
|
{
|
||||||
PField *vsym = static_cast<PField*>(sym);
|
PField *vsym = static_cast<PField*>(sym);
|
||||||
|
if (vsym->GetVersion() > ctx.Version)
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "%s not accessible to %s", sym->SymbolName.GetChars(), ctx.VersionString.GetChars());
|
||||||
|
delete object;
|
||||||
|
object = nullptr;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if ((vsym->Flags & VARF_Deprecated) && sym->mVersion >= ctx.Version)
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_WARNING, "Accessing deprecated member variable %s - deprecated since %d.%d.%d", sym->SymbolName.GetChars(), vsym->mVersion.major, vsym->mVersion.minor, vsym->mVersion.revision);
|
||||||
|
ScriptPosition.Message(MSG_WARNING, "Accessing deprecated member variable %s", vsym->SymbolName.GetChars());
|
||||||
|
}
|
||||||
|
|
||||||
// We have 4 cases to consider here:
|
// We have 4 cases to consider here:
|
||||||
// 1. The symbol is a static/meta member (not implemented yet) which is always accessible.
|
// 1. The symbol is a static/meta member which is always accessible.
|
||||||
// 2. This is a static function
|
// 2. This is a static function
|
||||||
// 3. This is an action function with a restricted self pointer
|
// 3. This is an action function with a restricted self pointer
|
||||||
// 4. This is a normal member or unrestricted action function.
|
// 4. This is a normal member or unrestricted action function.
|
||||||
if (vsym->Flags & VARF_Deprecated && !ctx.FromDecorate)
|
|
||||||
{
|
|
||||||
ScriptPosition.Message(MSG_WARNING, "Accessing deprecated member variable %s", vsym->SymbolName.GetChars());
|
|
||||||
}
|
|
||||||
if ((vsym->Flags & VARF_Private) && symtbl != &classctx->Symbols)
|
if ((vsym->Flags & VARF_Private) && symtbl != &classctx->Symbols)
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "Private member %s not accessible", vsym->SymbolName.GetChars());
|
ScriptPosition.Message(MSG_ERROR, "Private member %s not accessible", vsym->SymbolName.GetChars());
|
||||||
|
delete object;
|
||||||
|
object = nullptr;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
PClass* cls_ctx = dyn_cast<PClass>(classctx);
|
||||||
|
PClass* cls_target = dyn_cast<PClass>(objtype);
|
||||||
|
// [ZZ] neither PSymbol, PField or PSymbolTable have the necessary information. so we need to do the more complex check here.
|
||||||
|
if (vsym->Flags & VARF_Protected)
|
||||||
|
{
|
||||||
|
// early break.
|
||||||
|
if (!cls_ctx || !cls_target)
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Protected member %s not accessible", vsym->SymbolName.GetChars());
|
||||||
|
delete object;
|
||||||
|
object = nullptr;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// find the class that declared this field.
|
||||||
|
PClass* p = cls_target;
|
||||||
|
while (p)
|
||||||
|
{
|
||||||
|
if (&p->Symbols == symtbl)
|
||||||
|
{
|
||||||
|
cls_target = p;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = p->ParentClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cls_ctx->IsDescendantOf(cls_target))
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Protected member %s not accessible", vsym->SymbolName.GetChars());
|
||||||
|
delete object;
|
||||||
|
object = nullptr;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto x = isclass ? new FxClassMember(object, vsym, ScriptPosition) : new FxStructMember(object, vsym, ScriptPosition);
|
auto x = isclass ? new FxClassMember(object, vsym, ScriptPosition) : new FxStructMember(object, vsym, ScriptPosition);
|
||||||
object = nullptr;
|
object = nullptr;
|
||||||
|
@ -6810,12 +6844,6 @@ bool FxStructMember::RequestAddress(FCompileContext &ctx, bool *writable)
|
||||||
// [ZZ] original check.
|
// [ZZ] original check.
|
||||||
bool bWritable = (AddressWritable && !ctx.CheckWritable(membervar->Flags) &&
|
bool bWritable = (AddressWritable && !ctx.CheckWritable(membervar->Flags) &&
|
||||||
(!classx->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) || !static_cast<PPointer*>(classx->ValueType)->IsConst));
|
(!classx->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) || !static_cast<PPointer*>(classx->ValueType)->IsConst));
|
||||||
// [ZZ] self in a const function is not writable.
|
|
||||||
if (bWritable) // don't do complex checks on early fail
|
|
||||||
{
|
|
||||||
if ((classx->ExprType == EFX_Self) && (ctx.Function && (ctx.Function->Variants[0].Flags & VARF_ReadOnly)))
|
|
||||||
bWritable = false;
|
|
||||||
}
|
|
||||||
// [ZZ] implement write barrier between different scopes
|
// [ZZ] implement write barrier between different scopes
|
||||||
if (bWritable)
|
if (bWritable)
|
||||||
{
|
{
|
||||||
|
@ -8468,19 +8496,44 @@ PPrototype *FxVMFunctionCall::ReturnProto()
|
||||||
return Function->Variants[0].Proto;
|
return Function->Variants[0].Proto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool FxVMFunctionCall::CheckAccessibility(const VersionInfo &ver)
|
||||||
|
{
|
||||||
|
if (Function->mVersion > ver && !(Function->Variants[0].Flags & VARF_Deprecated))
|
||||||
|
{
|
||||||
|
FString VersionString;
|
||||||
|
if (ver >= MakeVersion(2, 3))
|
||||||
|
{
|
||||||
|
VersionString.Format("ZScript version %d.%d.%d", ver.major, ver.minor, ver.revision);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
VersionString = "DECORATE";
|
||||||
|
}
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "%s not accessible to %s", Function->SymbolName.GetChars(), VersionString.GetChars());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ((Function->Variants[0].Flags & VARF_Deprecated) && Function->mVersion >= ver)
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_WARNING, "Accessing deprecated function %s - deprecated since %d.%d.%d", Function->SymbolName.GetChars(), Function->mVersion.major, Function->mVersion.minor, Function->mVersion.revision);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
VMFunction *FxVMFunctionCall::GetDirectFunction()
|
VMFunction *FxVMFunctionCall::GetDirectFunction(const VersionInfo &ver)
|
||||||
{
|
{
|
||||||
// If this return statement calls a non-virtual function with no arguments,
|
// If this return statement calls a non-virtual function with no arguments,
|
||||||
// then it can be a "direct" function. That is, the DECORATE
|
// then it can be a "direct" function. That is, the DECORATE
|
||||||
// definition can call that function directly without wrapping
|
// definition can call that function directly without wrapping
|
||||||
// it inside VM code.
|
// it inside VM code.
|
||||||
if (ArgList.Size() == 0 && !(Function->Variants[0].Flags & VARF_Virtual))
|
|
||||||
|
if (ArgList.Size() == 0 && !(Function->Variants[0].Flags & VARF_Virtual) && CheckAccessibility(ver))
|
||||||
{
|
{
|
||||||
unsigned imp = Function->GetImplicitArgs();
|
unsigned imp = Function->GetImplicitArgs();
|
||||||
if (Function->Variants[0].ArgFlags.Size() > imp && !(Function->Variants[0].ArgFlags[imp] & VARF_Optional)) return nullptr;
|
if (Function->Variants[0].ArgFlags.Size() > imp && !(Function->Variants[0].ArgFlags[imp] & VARF_Optional)) return nullptr;
|
||||||
|
@ -8509,6 +8562,11 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx)
|
||||||
|
|
||||||
int implicit = Function->GetImplicitArgs();
|
int implicit = Function->GetImplicitArgs();
|
||||||
|
|
||||||
|
if (!CheckAccessibility(ctx.Version))
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// This should never happen.
|
// This should never happen.
|
||||||
if (Self == nullptr && (Function->Variants[0].Flags & VARF_Method))
|
if (Self == nullptr && (Function->Variants[0].Flags & VARF_Method))
|
||||||
{
|
{
|
||||||
|
@ -8718,7 +8776,7 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build)
|
||||||
}
|
}
|
||||||
|
|
||||||
VMFunction *vmfunc = Function->Variants[0].Implementation;
|
VMFunction *vmfunc = Function->Variants[0].Implementation;
|
||||||
bool staticcall = (vmfunc->Final || vmfunc->VirtualIndex == ~0u || NoVirtual);
|
bool staticcall = ((vmfunc->VarFlags & VARF_Final) || vmfunc->VirtualIndex == ~0u || NoVirtual);
|
||||||
|
|
||||||
count = 0;
|
count = 0;
|
||||||
// Emit code to pass implied parameters
|
// Emit code to pass implied parameters
|
||||||
|
@ -9345,11 +9403,11 @@ ExpEmit FxSequence::Emit(VMFunctionBuilder *build)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
VMFunction *FxSequence::GetDirectFunction()
|
VMFunction *FxSequence::GetDirectFunction(const VersionInfo &ver)
|
||||||
{
|
{
|
||||||
if (Expressions.Size() == 1)
|
if (Expressions.Size() == 1)
|
||||||
{
|
{
|
||||||
return Expressions[0]->GetDirectFunction();
|
return Expressions[0]->GetDirectFunction(ver);
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -10331,11 +10389,11 @@ ExpEmit FxReturnStatement::Emit(VMFunctionBuilder *build)
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
VMFunction *FxReturnStatement::GetDirectFunction()
|
VMFunction *FxReturnStatement::GetDirectFunction(const VersionInfo &ver)
|
||||||
{
|
{
|
||||||
if (Args.Size() == 1)
|
if (Args.Size() == 1)
|
||||||
{
|
{
|
||||||
return Args[0]->GetDirectFunction();
|
return Args[0]->GetDirectFunction(ver);
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,8 +86,10 @@ struct FCompileContext
|
||||||
bool Unsafe = false;
|
bool Unsafe = false;
|
||||||
TDeletingArray<FxLocalVariableDeclaration *> FunctionArgs;
|
TDeletingArray<FxLocalVariableDeclaration *> FunctionArgs;
|
||||||
PNamespace *CurGlobals;
|
PNamespace *CurGlobals;
|
||||||
|
VersionInfo Version;
|
||||||
|
FString VersionString;
|
||||||
|
|
||||||
FCompileContext(PNamespace *spc, PFunction *func, PPrototype *ret, bool fromdecorate, int stateindex, int statecount, int lump);
|
FCompileContext(PNamespace *spc, PFunction *func, PPrototype *ret, bool fromdecorate, int stateindex, int statecount, int lump, const VersionInfo &ver);
|
||||||
FCompileContext(PNamespace *spc, PStruct *cls, bool fromdecorate); // only to be used to resolve constants!
|
FCompileContext(PNamespace *spc, PStruct *cls, bool fromdecorate); // only to be used to resolve constants!
|
||||||
|
|
||||||
PSymbol *FindInClass(FName identifier, PSymbolTable *&symt);
|
PSymbol *FindInClass(FName identifier, PSymbolTable *&symt);
|
||||||
|
@ -322,7 +324,7 @@ public:
|
||||||
virtual bool isConstant() const;
|
virtual bool isConstant() const;
|
||||||
virtual bool RequestAddress(FCompileContext &ctx, bool *writable);
|
virtual bool RequestAddress(FCompileContext &ctx, bool *writable);
|
||||||
virtual PPrototype *ReturnProto();
|
virtual PPrototype *ReturnProto();
|
||||||
virtual VMFunction *GetDirectFunction();
|
virtual VMFunction *GetDirectFunction(const VersionInfo &ver);
|
||||||
virtual bool CheckReturn() { return false; }
|
virtual bool CheckReturn() { return false; }
|
||||||
virtual int GetBitValue() { return -1; }
|
virtual int GetBitValue() { return -1; }
|
||||||
bool IsNumeric() const { return ValueType->isNumeric(); }
|
bool IsNumeric() const { return ValueType->isNumeric(); }
|
||||||
|
@ -1712,12 +1714,14 @@ class FxVMFunctionCall : public FxExpression
|
||||||
TArray<ExpEmit> ReturnRegs;
|
TArray<ExpEmit> ReturnRegs;
|
||||||
PFunction *CallingFunction;
|
PFunction *CallingFunction;
|
||||||
|
|
||||||
|
bool CheckAccessibility(const VersionInfo &ver);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FxVMFunctionCall(FxExpression *self, PFunction *func, FArgumentList &args, const FScriptPosition &pos, bool novirtual);
|
FxVMFunctionCall(FxExpression *self, PFunction *func, FArgumentList &args, const FScriptPosition &pos, bool novirtual);
|
||||||
~FxVMFunctionCall();
|
~FxVMFunctionCall();
|
||||||
FxExpression *Resolve(FCompileContext&);
|
FxExpression *Resolve(FCompileContext&);
|
||||||
PPrototype *ReturnProto();
|
PPrototype *ReturnProto();
|
||||||
VMFunction *GetDirectFunction();
|
VMFunction *GetDirectFunction(const VersionInfo &ver);
|
||||||
ExpEmit Emit(VMFunctionBuilder *build);
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
bool CheckEmitCast(VMFunctionBuilder *build, bool returnit, ExpEmit ®);
|
bool CheckEmitCast(VMFunctionBuilder *build, bool returnit, ExpEmit ®);
|
||||||
TArray<PType*> &GetReturnTypes() const
|
TArray<PType*> &GetReturnTypes() const
|
||||||
|
@ -1742,7 +1746,7 @@ public:
|
||||||
FxExpression *Resolve(FCompileContext&);
|
FxExpression *Resolve(FCompileContext&);
|
||||||
ExpEmit Emit(VMFunctionBuilder *build);
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
void Add(FxExpression *expr) { if (expr != NULL) Expressions.Push(expr); expr->NeedResult = false; }
|
void Add(FxExpression *expr) { if (expr != NULL) Expressions.Push(expr); expr->NeedResult = false; }
|
||||||
VMFunction *GetDirectFunction();
|
VMFunction *GetDirectFunction(const VersionInfo &ver);
|
||||||
bool CheckReturn();
|
bool CheckReturn();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1949,7 +1953,7 @@ public:
|
||||||
~FxReturnStatement();
|
~FxReturnStatement();
|
||||||
FxExpression *Resolve(FCompileContext&);
|
FxExpression *Resolve(FCompileContext&);
|
||||||
ExpEmit Emit(VMFunctionBuilder *build);
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
VMFunction *GetDirectFunction();
|
VMFunction *GetDirectFunction(const VersionInfo &ver);
|
||||||
bool CheckReturn() { return true; }
|
bool CheckReturn() { return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#include "scopebarrier.h"
|
|
||||||
#include "dobject.h"
|
#include "dobject.h"
|
||||||
|
#include "scopebarrier.h"
|
||||||
|
|
||||||
|
|
||||||
// Note: the same object can't be both UI and Play. This is checked explicitly in the field construction and will cause esoteric errors here if found.
|
// Note: the same object can't be both UI and Play. This is checked explicitly in the field construction and will cause esoteric errors here if found.
|
||||||
|
@ -44,6 +44,19 @@ int FScopeBarrier::FlagsFromSide(int side)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int FScopeBarrier::ObjectFlagsFromSide(int side)
|
||||||
|
{
|
||||||
|
switch (side)
|
||||||
|
{
|
||||||
|
case Side_Play:
|
||||||
|
return OF_Play;
|
||||||
|
case Side_UI:
|
||||||
|
return OF_UI;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// used for errors
|
// used for errors
|
||||||
const char* FScopeBarrier::StringFromSide(int side)
|
const char* FScopeBarrier::StringFromSide(int side)
|
||||||
{
|
{
|
||||||
|
@ -72,6 +85,14 @@ int FScopeBarrier::ChangeSideInFlags(int flags, int side)
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this modifies OF_ flags and sets the side properly.
|
||||||
|
int FScopeBarrier::ChangeSideInObjectFlags(int flags, int side)
|
||||||
|
{
|
||||||
|
flags &= ~(OF_UI | OF_Play);
|
||||||
|
flags |= ObjectFlagsFromSide(side);
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
FScopeBarrier::FScopeBarrier()
|
FScopeBarrier::FScopeBarrier()
|
||||||
{
|
{
|
||||||
sidefrom = -1;
|
sidefrom = -1;
|
||||||
|
@ -150,3 +171,27 @@ void FScopeBarrier::AddFlags(int flags1, int flags2, const char* name)
|
||||||
if (name) callerror.Format("Can't call %s function %s from %s context", StringFromSide(sideto), name, StringFromSide(sidefrom));
|
if (name) callerror.Format("Can't call %s function %s from %s context", StringFromSide(sideto), name, StringFromSide(sidefrom));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// these are for vmexec.h
|
||||||
|
void FScopeBarrier::ValidateNew(PClass* cls, PFunction* callingfunc)
|
||||||
|
{
|
||||||
|
int outerside = callingfunc->Variants.Size() ? FScopeBarrier::SideFromFlags(callingfunc->Variants[0].Flags) : FScopeBarrier::Side_Virtual;
|
||||||
|
if (outerside == FScopeBarrier::Side_Virtual)
|
||||||
|
outerside = FScopeBarrier::SideFromObjectFlags(callingfunc->OwningClass->ObjectFlags);
|
||||||
|
int innerside = FScopeBarrier::SideFromObjectFlags(cls->ObjectFlags);
|
||||||
|
if ((outerside != innerside) && (innerside != FScopeBarrier::Side_PlainData)) // "cannot construct ui class ... from data context"
|
||||||
|
ThrowAbortException(X_OTHER, "Cannot construct %s class %s from %s context", FScopeBarrier::StringFromSide(innerside), cls->TypeName.GetChars(), FScopeBarrier::StringFromSide(outerside));
|
||||||
|
}
|
||||||
|
// this can be imported in vmexec.h
|
||||||
|
void FScopeBarrier::ValidateCall(PFunction* calledfunc, PFunction* callingfunc, PClass* selftype)
|
||||||
|
{
|
||||||
|
// [ZZ] anonymous blocks have 0 variants, so give them Side_Virtual.
|
||||||
|
int outerside = callingfunc->Variants.Size() ? FScopeBarrier::SideFromFlags(callingfunc->Variants[0].Flags) : FScopeBarrier::Side_Virtual;
|
||||||
|
if (outerside == FScopeBarrier::Side_Virtual)
|
||||||
|
outerside = FScopeBarrier::SideFromObjectFlags(callingfunc->OwningClass->ObjectFlags);
|
||||||
|
int innerside = FScopeBarrier::SideFromFlags(calledfunc->Variants[0].Flags);
|
||||||
|
if (innerside == FScopeBarrier::Side_Virtual)
|
||||||
|
innerside = FScopeBarrier::SideFromObjectFlags(selftype->ObjectFlags);
|
||||||
|
if ((outerside != innerside) && (innerside != FScopeBarrier::Side_PlainData))
|
||||||
|
ThrowAbortException(X_OTHER, "Cannot call %s function %s from %s context", FScopeBarrier::StringFromSide(innerside), calledfunc->SymbolName.GetChars(), FScopeBarrier::StringFromSide(outerside));
|
||||||
|
}
|
|
@ -35,12 +35,15 @@ struct FScopeBarrier
|
||||||
|
|
||||||
//
|
//
|
||||||
static int FlagsFromSide(int side);
|
static int FlagsFromSide(int side);
|
||||||
|
static int ObjectFlagsFromSide(int side);
|
||||||
|
|
||||||
// used for errors
|
// used for errors
|
||||||
static const char* StringFromSide(int side);
|
static const char* StringFromSide(int side);
|
||||||
|
|
||||||
// this modifies VARF_ flags and sets the side properly.
|
// this modifies VARF_ flags and sets the side properly.
|
||||||
static int ChangeSideInFlags(int flags, int side);
|
static int ChangeSideInFlags(int flags, int side);
|
||||||
|
// this modifies OF_ flags and sets the side properly.
|
||||||
|
static int ChangeSideInObjectFlags(int flags, int side);
|
||||||
FScopeBarrier();
|
FScopeBarrier();
|
||||||
FScopeBarrier(int flags1, int flags2, const char* name);
|
FScopeBarrier(int flags1, int flags2, const char* name);
|
||||||
|
|
||||||
|
@ -48,5 +51,9 @@ struct FScopeBarrier
|
||||||
// This is used for comparing a.b.c.d access - if non-allowed field is seen anywhere in the chain, anything after it is non-allowed.
|
// This is used for comparing a.b.c.d access - if non-allowed field is seen anywhere in the chain, anything after it is non-allowed.
|
||||||
// This struct is used so that the logic is in a single place.
|
// This struct is used so that the logic is in a single place.
|
||||||
void AddFlags(int flags1, int flags2, const char* name);
|
void AddFlags(int flags1, int flags2, const char* name);
|
||||||
|
|
||||||
|
// this is called from vmexec.h
|
||||||
|
static void ValidateNew(PClass* cls, PFunction* callingfunc);
|
||||||
|
static void ValidateCall(PFunction* calledfunc, PFunction* callingfunc, PClass* selftype);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -802,9 +802,9 @@ void VMFunctionBuilder::BackpatchListToHere(TArray<size_t> &locs)
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
FFunctionBuildList FunctionBuildList;
|
FFunctionBuildList FunctionBuildList;
|
||||||
|
|
||||||
VMFunction *FFunctionBuildList::AddFunction(PNamespace *gnspc, PFunction *functype, FxExpression *code, const FString &name, bool fromdecorate, int stateindex, int statecount, int lumpnum)
|
VMFunction *FFunctionBuildList::AddFunction(PNamespace *gnspc, const VersionInfo &ver, PFunction *functype, FxExpression *code, const FString &name, bool fromdecorate, int stateindex, int statecount, int lumpnum)
|
||||||
{
|
{
|
||||||
auto func = code->GetDirectFunction();
|
auto func = code->GetDirectFunction(ver);
|
||||||
if (func != nullptr)
|
if (func != nullptr)
|
||||||
{
|
{
|
||||||
delete code;
|
delete code;
|
||||||
|
@ -828,6 +828,7 @@ VMFunction *FFunctionBuildList::AddFunction(PNamespace *gnspc, PFunction *functy
|
||||||
it.StateIndex = stateindex;
|
it.StateIndex = stateindex;
|
||||||
it.StateCount = statecount;
|
it.StateCount = statecount;
|
||||||
it.Lump = lumpnum;
|
it.Lump = lumpnum;
|
||||||
|
it.Version = ver;
|
||||||
assert(it.Func->Variants.Size() == 1);
|
assert(it.Func->Variants.Size() == 1);
|
||||||
it.Func->Variants[0].Implementation = it.Function;
|
it.Func->Variants[0].Implementation = it.Function;
|
||||||
|
|
||||||
|
@ -856,7 +857,7 @@ void FFunctionBuildList::Build()
|
||||||
assert(item.Code != NULL);
|
assert(item.Code != NULL);
|
||||||
|
|
||||||
// We don't know the return type in advance for anonymous functions.
|
// We don't know the return type in advance for anonymous functions.
|
||||||
FCompileContext ctx(item.CurGlobals, item.Func, item.Func->SymbolName == NAME_None ? nullptr : item.Func->Variants[0].Proto, item.FromDecorate, item.StateIndex, item.StateCount, item.Lump);
|
FCompileContext ctx(item.CurGlobals, item.Func, item.Func->SymbolName == NAME_None ? nullptr : item.Func->Variants[0].Proto, item.FromDecorate, item.StateIndex, item.StateCount, item.Lump, item.Version);
|
||||||
|
|
||||||
// Allocate registers for the function's arguments and create local variable nodes before starting to resolve it.
|
// Allocate registers for the function's arguments and create local variable nodes before starting to resolve it.
|
||||||
VMFunctionBuilder buildit(item.Func->GetImplicitArgs());
|
VMFunctionBuilder buildit(item.Func->GetImplicitArgs());
|
||||||
|
|
|
@ -146,13 +146,14 @@ class FFunctionBuildList
|
||||||
int StateIndex;
|
int StateIndex;
|
||||||
int StateCount;
|
int StateCount;
|
||||||
int Lump;
|
int Lump;
|
||||||
|
VersionInfo Version;
|
||||||
bool FromDecorate;
|
bool FromDecorate;
|
||||||
};
|
};
|
||||||
|
|
||||||
TArray<Item> mItems;
|
TArray<Item> mItems;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VMFunction *AddFunction(PNamespace *curglobals, PFunction *func, FxExpression *code, const FString &name, bool fromdecorate, int currentstate, int statecnt, int lumpnum);
|
VMFunction *AddFunction(PNamespace *curglobals, const VersionInfo &ver, PFunction *func, FxExpression *code, const FString &name, bool fromdecorate, int currentstate, int statecnt, int lumpnum);
|
||||||
void Build();
|
void Build();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -119,6 +119,7 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def, PNamespace *ns)
|
||||||
bag.Namespace = ns;
|
bag.Namespace = ns;
|
||||||
bag.Info = type;
|
bag.Info = type;
|
||||||
bag.fromDecorate = true;
|
bag.fromDecorate = true;
|
||||||
|
bag.Version = { 2, 0, 0 };
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
bag.ClassName = type->TypeName;
|
bag.ClassName = type->TypeName;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -69,6 +69,10 @@ EXTERN_CVAR(Bool, strictdecorate);
|
||||||
|
|
||||||
PClassActor *DecoDerivedClass(const FScriptPosition &sc, PClassActor *parent, FName typeName)
|
PClassActor *DecoDerivedClass(const FScriptPosition &sc, PClassActor *parent, FName typeName)
|
||||||
{
|
{
|
||||||
|
if (parent->mVersion > MakeVersion(2, 0))
|
||||||
|
{
|
||||||
|
sc.Message(MSG_ERROR, "Parent class %s of %s not accessible to DECORATE", parent->GetClass()->TypeName.GetChars(), typeName.GetChars());
|
||||||
|
}
|
||||||
PClassActor *type = static_cast<PClassActor *>(parent->CreateDerivedClass(typeName, parent->Size));
|
PClassActor *type = static_cast<PClassActor *>(parent->CreateDerivedClass(typeName, parent->Size));
|
||||||
if (type == nullptr)
|
if (type == nullptr)
|
||||||
{
|
{
|
||||||
|
@ -1125,6 +1129,7 @@ static void ParseActor(FScanner &sc, PNamespace *ns)
|
||||||
Baggage bag;
|
Baggage bag;
|
||||||
|
|
||||||
bag.Namespace = ns;
|
bag.Namespace = ns;
|
||||||
|
bag.Version = { 2, 0, 0 };
|
||||||
bag.fromDecorate = true;
|
bag.fromDecorate = true;
|
||||||
info = ParseActorHeader(sc, &bag);
|
info = ParseActorHeader(sc, &bag);
|
||||||
sc.MustGetToken('{');
|
sc.MustGetToken('{');
|
||||||
|
|
|
@ -340,7 +340,7 @@ endofstate:
|
||||||
if (ScriptCode != nullptr)
|
if (ScriptCode != nullptr)
|
||||||
{
|
{
|
||||||
auto funcsym = CreateAnonymousFunction(actor, nullptr, state.UseFlags);
|
auto funcsym = CreateAnonymousFunction(actor, nullptr, state.UseFlags);
|
||||||
state.ActionFunc = FunctionBuildList.AddFunction(bag.Namespace, funcsym, ScriptCode, FStringf("%s.StateFunction.%d", actor->TypeName.GetChars(), bag.statedef.GetStateCount()), true, bag.statedef.GetStateCount(), int(statestring.Len()), sc.LumpNum);
|
state.ActionFunc = FunctionBuildList.AddFunction(bag.Namespace, bag.Version, funcsym, ScriptCode, FStringf("%s.StateFunction.%d", actor->TypeName.GetChars(), bag.statedef.GetStateCount()), true, bag.statedef.GetStateCount(), int(statestring.Len()), sc.LumpNum);
|
||||||
}
|
}
|
||||||
int count = bag.statedef.AddStates(&state, statestring, scp);
|
int count = bag.statedef.AddStates(&state, statestring, scp);
|
||||||
if (count < 0)
|
if (count < 0)
|
||||||
|
|
|
@ -26,6 +26,7 @@ class PSymbol : public DObject
|
||||||
DECLARE_ABSTRACT_CLASS(PSymbol, DObject);
|
DECLARE_ABSTRACT_CLASS(PSymbol, DObject);
|
||||||
public:
|
public:
|
||||||
FName SymbolName;
|
FName SymbolName;
|
||||||
|
VersionInfo mVersion = { 0,0,0 };
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
PSymbol(FName name) { SymbolName = name; }
|
PSymbol(FName name) { SymbolName = name; }
|
||||||
|
@ -76,6 +77,7 @@ class PField : public PSymbol
|
||||||
HAS_OBJECT_POINTERS
|
HAS_OBJECT_POINTERS
|
||||||
public:
|
public:
|
||||||
PField(FName name, PType *type, uint32_t flags = 0, size_t offset = 0, int bitvalue = 0);
|
PField(FName name, PType *type, uint32_t flags = 0, size_t offset = 0, int bitvalue = 0);
|
||||||
|
VersionInfo GetVersion();
|
||||||
|
|
||||||
size_t Offset;
|
size_t Offset;
|
||||||
PType *Type;
|
PType *Type;
|
||||||
|
|
|
@ -195,6 +195,8 @@ PFunction *FindClassMemberFunction(PStruct *selfcls, PStruct *funccls, FName nam
|
||||||
|
|
||||||
if (symbol != nullptr)
|
if (symbol != nullptr)
|
||||||
{
|
{
|
||||||
|
PClass* cls_ctx = dyn_cast<PClass>(funccls);
|
||||||
|
PClass* cls_target = funcsym?dyn_cast<PClass>(funcsym->OwningClass):nullptr;
|
||||||
if (funcsym == nullptr)
|
if (funcsym == nullptr)
|
||||||
{
|
{
|
||||||
sc.Message(MSG_ERROR, "%s is not a member function of %s", name.GetChars(), selfcls->TypeName.GetChars());
|
sc.Message(MSG_ERROR, "%s is not a member function of %s", name.GetChars(), selfcls->TypeName.GetChars());
|
||||||
|
@ -204,6 +206,11 @@ PFunction *FindClassMemberFunction(PStruct *selfcls, PStruct *funccls, FName nam
|
||||||
// private access is only allowed if the symbol table belongs to the class in which the current function is being defined.
|
// private access is only allowed if the symbol table belongs to the class in which the current function is being defined.
|
||||||
sc.Message(MSG_ERROR, "%s is declared private and not accessible", symbol->SymbolName.GetChars());
|
sc.Message(MSG_ERROR, "%s is declared private and not accessible", symbol->SymbolName.GetChars());
|
||||||
}
|
}
|
||||||
|
else if ((funcsym->Variants[0].Flags & VARF_Protected) && (!cls_ctx || !cls_target || !cls_ctx->IsDescendantOf((PClass*)cls_target)))
|
||||||
|
{
|
||||||
|
sc.Message(MSG_ERROR, "%s is declared protected and not accessible", symbol->SymbolName.GetChars());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
else if (funcsym->Variants[0].Flags & VARF_Deprecated)
|
else if (funcsym->Variants[0].Flags & VARF_Deprecated)
|
||||||
{
|
{
|
||||||
sc.Message(MSG_WARNING, "Call to deprecated function %s", symbol->SymbolName.GetChars());
|
sc.Message(MSG_WARNING, "Call to deprecated function %s", symbol->SymbolName.GetChars());
|
||||||
|
@ -221,7 +228,7 @@ PFunction *FindClassMemberFunction(PStruct *selfcls, PStruct *funccls, FName nam
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void CreateDamageFunction(PNamespace *OutNamespace, PClassActor *info, AActor *defaults, FxExpression *id, bool fromDecorate, int lumpnum)
|
void CreateDamageFunction(PNamespace *OutNamespace, const VersionInfo &ver, PClassActor *info, AActor *defaults, FxExpression *id, bool fromDecorate, int lumpnum)
|
||||||
{
|
{
|
||||||
if (id == nullptr)
|
if (id == nullptr)
|
||||||
{
|
{
|
||||||
|
@ -231,7 +238,7 @@ void CreateDamageFunction(PNamespace *OutNamespace, PClassActor *info, AActor *d
|
||||||
{
|
{
|
||||||
auto dmg = new FxReturnStatement(new FxIntCast(id, true), id->ScriptPosition);
|
auto dmg = new FxReturnStatement(new FxIntCast(id, true), id->ScriptPosition);
|
||||||
auto funcsym = CreateAnonymousFunction(info, TypeSInt32, 0);
|
auto funcsym = CreateAnonymousFunction(info, TypeSInt32, 0);
|
||||||
defaults->DamageFunc = FunctionBuildList.AddFunction(OutNamespace, funcsym, dmg, FStringf("%s.DamageFunction", info->TypeName.GetChars()), fromDecorate, -1, 0, lumpnum);
|
defaults->DamageFunc = FunctionBuildList.AddFunction(OutNamespace, ver, funcsym, dmg, FStringf("%s.DamageFunction", info->TypeName.GetChars()), fromDecorate, -1, 0, lumpnum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -124,6 +124,7 @@ struct Baggage
|
||||||
bool fromDecorate;
|
bool fromDecorate;
|
||||||
int CurrentState;
|
int CurrentState;
|
||||||
int Lumpnum;
|
int Lumpnum;
|
||||||
|
VersionInfo Version;
|
||||||
FStateDefinitions statedef;
|
FStateDefinitions statedef;
|
||||||
|
|
||||||
FDropItem *DropItemList;
|
FDropItem *DropItemList;
|
||||||
|
@ -161,7 +162,7 @@ FName CheckCastKludges(FName in);
|
||||||
void SetImplicitArgs(TArray<PType *> *args, TArray<DWORD> *argflags, TArray<FName> *argnames, PStruct *cls, DWORD funcflags, int useflags);
|
void SetImplicitArgs(TArray<PType *> *args, TArray<DWORD> *argflags, TArray<FName> *argnames, PStruct *cls, DWORD funcflags, int useflags);
|
||||||
PFunction *CreateAnonymousFunction(PClass *containingclass, PType *returntype, int flags);
|
PFunction *CreateAnonymousFunction(PClass *containingclass, PType *returntype, int flags);
|
||||||
PFunction *FindClassMemberFunction(PStruct *cls, PStruct *funccls, FName name, FScriptPosition &sc, bool *error);
|
PFunction *FindClassMemberFunction(PStruct *cls, PStruct *funccls, FName name, FScriptPosition &sc, bool *error);
|
||||||
void CreateDamageFunction(PNamespace *ns, PClassActor *info, AActor *defaults, FxExpression *id, bool fromDecorate, int lumpnum);
|
void CreateDamageFunction(PNamespace *ns, const VersionInfo &ver, PClassActor *info, AActor *defaults, FxExpression *id, bool fromDecorate, int lumpnum);
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
|
|
@ -679,7 +679,7 @@ DEFINE_PROPERTY(damage, X, Actor)
|
||||||
|
|
||||||
defaults->DamageVal = dmgval;
|
defaults->DamageVal = dmgval;
|
||||||
// Only DECORATE can get here with a valid expression.
|
// Only DECORATE can get here with a valid expression.
|
||||||
CreateDamageFunction(bag.Namespace, bag.Info, defaults, id, true, bag.Lumpnum);
|
CreateDamageFunction(bag.Namespace, bag.Version, bag.Info, defaults, id, true, bag.Lumpnum);
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
|
@ -7,11 +7,8 @@
|
||||||
#include "cmdlib.h"
|
#include "cmdlib.h"
|
||||||
#include "doomerrors.h"
|
#include "doomerrors.h"
|
||||||
#include "memarena.h"
|
#include "memarena.h"
|
||||||
|
#include "scripting/backend/scopebarrier.h"
|
||||||
|
|
||||||
// [ZZ] there are serious circular references between this and the rest of ZScript code, so it needs to be done like this
|
|
||||||
// these are used in vmexec.h
|
|
||||||
void FScopeBarrier_ValidateNew(PClass* cls, PFunction* callingfunc);
|
|
||||||
void FScopeBarrier_ValidateCall(PFunction* calledfunc, PFunction* callingfunc, PClass* selftype);
|
|
||||||
class DObject;
|
class DObject;
|
||||||
|
|
||||||
extern FMemArena ClassDataAllocator;
|
extern FMemArena ClassDataAllocator;
|
||||||
|
@ -705,11 +702,8 @@ do_double: if (inexact)
|
||||||
class VMFunction
|
class VMFunction
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool Native;
|
bool Unsafe = false;
|
||||||
bool Final = false; // cannot be overridden
|
int VarFlags = 0; // [ZZ] this replaces 5+ bool fields
|
||||||
bool Unsafe = false; // Contains references to class fields that are unsafe for psp and item state calls.
|
|
||||||
bool FuncConst = false; // [ZZ] readonly function
|
|
||||||
int BarrierSide = 0; // [ZZ] FScopeBarrier::Side
|
|
||||||
BYTE ImplicitArgs = 0; // either 0 for static, 1 for method or 3 for action
|
BYTE ImplicitArgs = 0; // either 0 for static, 1 for method or 3 for action
|
||||||
unsigned VirtualIndex = ~0u;
|
unsigned VirtualIndex = ~0u;
|
||||||
FName Name;
|
FName Name;
|
||||||
|
@ -718,7 +712,7 @@ public:
|
||||||
|
|
||||||
class PPrototype *Proto;
|
class PPrototype *Proto;
|
||||||
|
|
||||||
VMFunction(FName name = NAME_None) : Native(false), ImplicitArgs(0), Name(name), Proto(NULL)
|
VMFunction(FName name = NAME_None) : ImplicitArgs(0), Name(name), Proto(NULL)
|
||||||
{
|
{
|
||||||
AllFunctions.Push(this);
|
AllFunctions.Push(this);
|
||||||
}
|
}
|
||||||
|
@ -942,9 +936,10 @@ class VMNativeFunction : public VMFunction
|
||||||
public:
|
public:
|
||||||
typedef int (*NativeCallType)(VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret);
|
typedef int (*NativeCallType)(VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret);
|
||||||
|
|
||||||
VMNativeFunction() : NativeCall(NULL) { Native = true; }
|
// 8 is VARF_Native. I can't write VARF_Native because of circular references between this and dobject/dobjtype.
|
||||||
VMNativeFunction(NativeCallType call) : NativeCall(call) { Native = true; }
|
VMNativeFunction() : NativeCall(NULL) { VarFlags = 8; }
|
||||||
VMNativeFunction(NativeCallType call, FName name) : VMFunction(name), NativeCall(call) { Native = true; }
|
VMNativeFunction(NativeCallType call) : NativeCall(call) { VarFlags = 8; }
|
||||||
|
VMNativeFunction(NativeCallType call, FName name) : VMFunction(name), NativeCall(call) { VarFlags = 8; }
|
||||||
|
|
||||||
// Return value is the number of results.
|
// Return value is the number of results.
|
||||||
NativeCallType NativeCall;
|
NativeCallType NativeCall;
|
||||||
|
|
|
@ -201,7 +201,7 @@ void VMFillParams(VMValue *params, VMFrame *callee, int numparam)
|
||||||
VMScriptFunction *calleefunc = static_cast<VMScriptFunction *>(callee->Func);
|
VMScriptFunction *calleefunc = static_cast<VMScriptFunction *>(callee->Func);
|
||||||
const VMRegisters calleereg(callee);
|
const VMRegisters calleereg(callee);
|
||||||
|
|
||||||
assert(calleefunc != NULL && !calleefunc->Native);
|
assert(calleefunc != NULL && !(calleefunc->VarFlags & VARF_Native));
|
||||||
assert(numparam == calleefunc->NumArgs || ((int)calleefunc->DefaultArgs.Size() == calleefunc->NumArgs));
|
assert(numparam == calleefunc->NumArgs || ((int)calleefunc->DefaultArgs.Size() == calleefunc->NumArgs));
|
||||||
assert(REGT_INT == 0 && REGT_FLOAT == 1 && REGT_STRING == 2 && REGT_POINTER == 3);
|
assert(REGT_INT == 0 && REGT_FLOAT == 1 && REGT_STRING == 2 && REGT_POINTER == 3);
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret)
|
||||||
const FVoidObj *konsta;
|
const FVoidObj *konsta;
|
||||||
const VM_ATAG *konstatag;
|
const VM_ATAG *konstatag;
|
||||||
|
|
||||||
if (f->Func != NULL && !f->Func->Native)
|
if (f->Func != NULL && !(f->Func->VarFlags & VARF_Native))
|
||||||
{
|
{
|
||||||
sfunc = static_cast<VMScriptFunction *>(f->Func);
|
sfunc = static_cast<VMScriptFunction *>(f->Func);
|
||||||
konstd = sfunc->KonstD;
|
konstd = sfunc->KonstD;
|
||||||
|
@ -673,13 +673,13 @@ begin:
|
||||||
PFunction* callingfunc = (PFunction*)(reg.param + f->NumParam - b)[1].a;
|
PFunction* callingfunc = (PFunction*)(reg.param + f->NumParam - b)[1].a;
|
||||||
DObject* dobj = (DObject*)(reg.param + f->NumParam - b)[2].a; // this is the self pointer. it should be in, since Side_Virtual functions are always non-static methods.
|
DObject* dobj = (DObject*)(reg.param + f->NumParam - b)[2].a; // this is the self pointer. it should be in, since Side_Virtual functions are always non-static methods.
|
||||||
PClass* selftype = dobj->GetClass();
|
PClass* selftype = dobj->GetClass();
|
||||||
FScopeBarrier_ValidateCall(calledfunc, callingfunc, selftype);
|
FScopeBarrier::ValidateCall(calledfunc, callingfunc, selftype);
|
||||||
b -= 2;
|
b -= 2;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
FillReturns(reg, f, returns, pc+1, C);
|
FillReturns(reg, f, returns, pc+1, C);
|
||||||
if (call->Native)
|
if (call->VarFlags & VARF_Native)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -736,7 +736,7 @@ begin:
|
||||||
{
|
{
|
||||||
VMFunction *call = (VMFunction *)ptr;
|
VMFunction *call = (VMFunction *)ptr;
|
||||||
|
|
||||||
if (call->Native)
|
if (call->VarFlags & VARF_Native)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -821,7 +821,7 @@ begin:
|
||||||
if (cls->ObjectFlags & OF_Abstract) ThrowAbortException(X_OTHER, "Cannot instantiate abstract class %s", cls->TypeName.GetChars());
|
if (cls->ObjectFlags & OF_Abstract) ThrowAbortException(X_OTHER, "Cannot instantiate abstract class %s", cls->TypeName.GetChars());
|
||||||
// [ZZ] validate readonly and between scope construction
|
// [ZZ] validate readonly and between scope construction
|
||||||
if (callingfunc)
|
if (callingfunc)
|
||||||
FScopeBarrier_ValidateNew(cls, callingfunc);
|
FScopeBarrier::ValidateNew(cls, callingfunc);
|
||||||
reg.a[a] = cls->CreateNew();
|
reg.a[a] = cls->CreateNew();
|
||||||
reg.atag[a] = ATAG_OBJECT;
|
reg.atag[a] = ATAG_OBJECT;
|
||||||
NEXTOP;
|
NEXTOP;
|
||||||
|
@ -1966,7 +1966,7 @@ static void SetReturn(const VMRegisters ®, VMFrame *frame, VMReturn *ret, VM_
|
||||||
const void *src;
|
const void *src;
|
||||||
VMScriptFunction *func = static_cast<VMScriptFunction *>(frame->Func);
|
VMScriptFunction *func = static_cast<VMScriptFunction *>(frame->Func);
|
||||||
|
|
||||||
assert(func != NULL && !func->Native);
|
assert(func != NULL && !(func->VarFlags & VARF_Native));
|
||||||
assert((regtype & ~REGT_KONST) == ret->RegType);
|
assert((regtype & ~REGT_KONST) == ret->RegType);
|
||||||
|
|
||||||
switch (regtype & REGT_TYPE)
|
switch (regtype & REGT_TYPE)
|
||||||
|
|
|
@ -48,7 +48,6 @@ TArray<VMFunction *> VMFunction::AllFunctions;
|
||||||
|
|
||||||
VMScriptFunction::VMScriptFunction(FName name)
|
VMScriptFunction::VMScriptFunction(FName name)
|
||||||
{
|
{
|
||||||
Native = false;
|
|
||||||
Name = name;
|
Name = name;
|
||||||
LineInfo = nullptr;
|
LineInfo = nullptr;
|
||||||
Code = NULL;
|
Code = NULL;
|
||||||
|
@ -438,7 +437,7 @@ int VMFrameStack::Call(VMFunction *func, VMValue *params, int numparams, VMRetur
|
||||||
bool allocated = false;
|
bool allocated = false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (func->Native)
|
if (func->VarFlags & VARF_Native)
|
||||||
{
|
{
|
||||||
return static_cast<VMNativeFunction *>(func)->NativeCall(params, func->DefaultArgs, numparams, results, numresults);
|
return static_cast<VMNativeFunction *>(func)->NativeCall(params, func->DefaultArgs, numparams, results, numresults);
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@ static void SetNodeLine(ZCC_TreeNode *name, int line)
|
||||||
struct ClassFlagsBlock {
|
struct ClassFlagsBlock {
|
||||||
VM_UWORD Flags;
|
VM_UWORD Flags;
|
||||||
ZCC_Identifier *Replaces;
|
ZCC_Identifier *Replaces;
|
||||||
|
VersionInfo Version;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct StateOpts {
|
struct StateOpts {
|
||||||
|
@ -188,6 +189,7 @@ class_head(X) ::= EXTEND CLASS(T) IDENTIFIER(A).
|
||||||
head->ParentName = nullptr;
|
head->ParentName = nullptr;
|
||||||
head->Flags = ZCC_Extension;
|
head->Flags = ZCC_Extension;
|
||||||
head->Replaces = nullptr;
|
head->Replaces = nullptr;
|
||||||
|
head->Version = {0, 0};
|
||||||
head->Type = nullptr;
|
head->Type = nullptr;
|
||||||
head->Symbol = nullptr;
|
head->Symbol = nullptr;
|
||||||
X = head;
|
X = head;
|
||||||
|
@ -200,6 +202,7 @@ class_head(X) ::= CLASS(T) IDENTIFIER(A) class_ancestry(B) class_flags(C).
|
||||||
head->ParentName = B;
|
head->ParentName = B;
|
||||||
head->Flags = C.Flags;
|
head->Flags = C.Flags;
|
||||||
head->Replaces = C.Replaces;
|
head->Replaces = C.Replaces;
|
||||||
|
head->Version = C.Version;
|
||||||
head->Type = nullptr;
|
head->Type = nullptr;
|
||||||
head->Symbol = nullptr;
|
head->Symbol = nullptr;
|
||||||
X = head;
|
X = head;
|
||||||
|
@ -210,12 +213,13 @@ class_ancestry(X) ::= . { X = NULL; }
|
||||||
class_ancestry(X) ::= COLON dottable_id(A). { X = A; /*X-overwrites-A*/ }
|
class_ancestry(X) ::= COLON dottable_id(A). { X = A; /*X-overwrites-A*/ }
|
||||||
|
|
||||||
%type class_flags{ClassFlagsBlock}
|
%type class_flags{ClassFlagsBlock}
|
||||||
class_flags(X) ::= . { X.Flags = 0; X.Replaces = NULL; }
|
class_flags(X) ::= . { X.Flags = 0; X.Replaces = NULL; X.Version = {0,0}; }
|
||||||
class_flags(X) ::= class_flags(A) ABSTRACT. { X.Flags = A.Flags | ZCC_Abstract; X.Replaces = A.Replaces; }
|
class_flags(X) ::= class_flags(A) ABSTRACT. { X.Flags = A.Flags | ZCC_Abstract; X.Replaces = A.Replaces; }
|
||||||
class_flags(X) ::= class_flags(A) NATIVE. { X.Flags = A.Flags | ZCC_Native; X.Replaces = A.Replaces; }
|
class_flags(X) ::= class_flags(A) NATIVE. { X.Flags = A.Flags | ZCC_Native; X.Replaces = A.Replaces; }
|
||||||
class_flags(X) ::= class_flags(A) UI. { X.Flags = A.Flags | ZCC_UIFlag; X.Replaces = A.Replaces; }
|
class_flags(X) ::= class_flags(A) UI. { X.Flags = A.Flags | ZCC_UIFlag; X.Replaces = A.Replaces; }
|
||||||
class_flags(X) ::= class_flags(A) PLAY. { X.Flags = A.Flags | ZCC_Play; X.Replaces = A.Replaces; }
|
class_flags(X) ::= class_flags(A) PLAY. { X.Flags = A.Flags | ZCC_Play; X.Replaces = A.Replaces; }
|
||||||
class_flags(X) ::= class_flags(A) REPLACES dottable_id(B). { X.Flags = A.Flags; X.Replaces = B; }
|
class_flags(X) ::= class_flags(A) REPLACES dottable_id(B). { X.Flags = A.Flags; X.Replaces = B; }
|
||||||
|
class_flags(X) ::= class_flags(A) VERSION LPAREN STRCONST(C) RPAREN. { X.Flags = A.Flags | ZCC_Version; X.Replaces = A.Replaces; X.Version = C.String->GetChars(); }
|
||||||
|
|
||||||
/*----- Dottable Identifier -----*/
|
/*----- Dottable Identifier -----*/
|
||||||
// This can be either a single identifier or two identifiers connected by a .
|
// This can be either a single identifier or two identifiers connected by a .
|
||||||
|
@ -322,15 +326,18 @@ struct_def(X) ::= STRUCT(T) IDENTIFIER(A) struct_flags(S) LBRACE opt_struct_body
|
||||||
def->Body = B;
|
def->Body = B;
|
||||||
def->Type = nullptr;
|
def->Type = nullptr;
|
||||||
def->Symbol = nullptr;
|
def->Symbol = nullptr;
|
||||||
|
def->Version = S.Version;
|
||||||
def->Flags = S.Flags;
|
def->Flags = S.Flags;
|
||||||
X = def;
|
X = def;
|
||||||
}
|
}
|
||||||
|
|
||||||
%type struct_flags{ClassFlagsBlock}
|
%type struct_flags{ClassFlagsBlock}
|
||||||
struct_flags(X) ::= . { X.Flags = 0; }
|
struct_flags(X) ::= . { X.Flags = 0; X.Version = {0, 0}; }
|
||||||
struct_flags(X) ::= struct_flags(A) UI. { X.Flags = A.Flags | ZCC_UIFlag; }
|
struct_flags(X) ::= struct_flags(A) UI. { X.Flags = A.Flags | ZCC_UIFlag; }
|
||||||
struct_flags(X) ::= struct_flags(A) PLAY. { X.Flags = A.Flags | ZCC_Play; }
|
struct_flags(X) ::= struct_flags(A) PLAY. { X.Flags = A.Flags | ZCC_Play; }
|
||||||
|
struct_flags(X) ::= struct_flags(A) CLEARSCOPE. { X.Flags = A.Flags | ZCC_ClearScope; }
|
||||||
struct_flags(X) ::= struct_flags(A) NATIVE. { X.Flags = A.Flags | ZCC_Native; }
|
struct_flags(X) ::= struct_flags(A) NATIVE. { X.Flags = A.Flags | ZCC_Native; }
|
||||||
|
struct_flags(X) ::= struct_flags(A) VERSION LPAREN STRCONST(C) RPAREN. { X.Flags = A.Flags | ZCC_Version; X.Version = C.String->GetChars(); }
|
||||||
|
|
||||||
opt_struct_body(X) ::= . { X = NULL; }
|
opt_struct_body(X) ::= . { X = NULL; }
|
||||||
opt_struct_body(X) ::= struct_body(X).
|
opt_struct_body(X) ::= struct_body(X).
|
||||||
|
@ -866,6 +873,9 @@ declarator(X) ::= decl_flags(A) type_list_or_void(B) variables_or_function(C).
|
||||||
decl->Name = C.FuncName;
|
decl->Name = C.FuncName;
|
||||||
decl->UseFlags = A == nullptr? nullptr : A->Id;
|
decl->UseFlags = A == nullptr? nullptr : A->Id;
|
||||||
decl->Flags = (A == nullptr? 0 : A->Flags) | C.FuncFlags;
|
decl->Flags = (A == nullptr? 0 : A->Flags) | C.FuncFlags;
|
||||||
|
if (A == nullptr) decl->Version = {0,0,0};
|
||||||
|
else decl->Version = A->Version;
|
||||||
|
|
||||||
decl->Body = C.FuncBody;
|
decl->Body = C.FuncBody;
|
||||||
X = decl;
|
X = decl;
|
||||||
}
|
}
|
||||||
|
@ -874,7 +884,16 @@ declarator(X) ::= decl_flags(A) type_list_or_void(B) variables_or_function(C).
|
||||||
NEW_AST_NODE(VarDeclarator, decl, A == nullptr? B->SourceLoc : A->SourceLoc);
|
NEW_AST_NODE(VarDeclarator, decl, A == nullptr? B->SourceLoc : A->SourceLoc);
|
||||||
decl->Type = B;
|
decl->Type = B;
|
||||||
decl->Names = C.VarNames;
|
decl->Names = C.VarNames;
|
||||||
decl->Flags = (A == nullptr? 0 : A->Flags);
|
if (A == nullptr)
|
||||||
|
{
|
||||||
|
decl->Flags = 0;
|
||||||
|
decl->Version = {0,0,0};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
decl->Flags = A->Flags;
|
||||||
|
decl->Version = A->Version;
|
||||||
|
}
|
||||||
X = decl;
|
X = decl;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -965,6 +984,7 @@ decl_flags(X) ::= decl_flags(F) decl_flag(A).
|
||||||
X = nil_f;
|
X = nil_f;
|
||||||
X->Id = nullptr;
|
X->Id = nullptr;
|
||||||
X->Flags = A.Int;
|
X->Flags = A.Int;
|
||||||
|
X->Version = { 0, 0 };
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -981,6 +1001,8 @@ decl_flags(X) ::= decl_flags(F) ACTION(B) states_opts(A).
|
||||||
NEW_AST_NODE(DeclFlags,nil_f,B.SourceLoc);
|
NEW_AST_NODE(DeclFlags,nil_f,B.SourceLoc);
|
||||||
X = nil_f;
|
X = nil_f;
|
||||||
X->Flags = ZCC_Action;
|
X->Flags = ZCC_Action;
|
||||||
|
X->Id = nullptr;
|
||||||
|
X->Version = { 0, 0 };
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -990,6 +1012,42 @@ decl_flags(X) ::= decl_flags(F) ACTION(B) states_opts(A).
|
||||||
X->Id = A;
|
X->Id = A;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
decl_flags(X) ::= decl_flags(F) DEPRECATED(B) LPAREN STRCONST(A) RPAREN.
|
||||||
|
{
|
||||||
|
if (F == nullptr)
|
||||||
|
{
|
||||||
|
NEW_AST_NODE(DeclFlags,nil_f,B.SourceLoc);
|
||||||
|
X = nil_f;
|
||||||
|
X->Flags = ZCC_Deprecated;
|
||||||
|
X->Id = nullptr;
|
||||||
|
X->Version = { 0, 0 };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
X = F;
|
||||||
|
X->Flags |= ZCC_Deprecated;
|
||||||
|
}
|
||||||
|
X->Version = A.String->GetChars();
|
||||||
|
}
|
||||||
|
|
||||||
|
decl_flags(X) ::= decl_flags(F) VERSION(B) LPAREN STRCONST(A) RPAREN.
|
||||||
|
{
|
||||||
|
if (F == nullptr)
|
||||||
|
{
|
||||||
|
NEW_AST_NODE(DeclFlags,nil_f,B.SourceLoc);
|
||||||
|
X = nil_f;
|
||||||
|
X->Flags = ZCC_Version;
|
||||||
|
X->Id = nullptr;
|
||||||
|
X->Version = { 0, 0 };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
X = F;
|
||||||
|
X->Flags |= ZCC_Version;
|
||||||
|
}
|
||||||
|
X->Version = A.String->GetChars();
|
||||||
|
}
|
||||||
|
|
||||||
decl_flag(X) ::= NATIVE(T). { X.Int = ZCC_Native; X.SourceLoc = T.SourceLoc; }
|
decl_flag(X) ::= NATIVE(T). { X.Int = ZCC_Native; X.SourceLoc = T.SourceLoc; }
|
||||||
decl_flag(X) ::= STATIC(T). { X.Int = ZCC_Static; X.SourceLoc = T.SourceLoc; }
|
decl_flag(X) ::= STATIC(T). { X.Int = ZCC_Static; X.SourceLoc = T.SourceLoc; }
|
||||||
decl_flag(X) ::= PRIVATE(T). { X.Int = ZCC_Private; X.SourceLoc = T.SourceLoc; }
|
decl_flag(X) ::= PRIVATE(T). { X.Int = ZCC_Private; X.SourceLoc = T.SourceLoc; }
|
||||||
|
@ -999,7 +1057,6 @@ decl_flag(X) ::= FINAL(T). { X.Int = ZCC_Final; X.SourceLoc = T.SourceLoc; }
|
||||||
decl_flag(X) ::= META(T). { X.Int = ZCC_Meta; X.SourceLoc = T.SourceLoc; }
|
decl_flag(X) ::= META(T). { X.Int = ZCC_Meta; X.SourceLoc = T.SourceLoc; }
|
||||||
decl_flag(X) ::= TRANSIENT(T). { X.Int = ZCC_Transient; X.SourceLoc = T.SourceLoc; }
|
decl_flag(X) ::= TRANSIENT(T). { X.Int = ZCC_Transient; X.SourceLoc = T.SourceLoc; }
|
||||||
decl_flag(X) ::= READONLY(T). { X.Int = ZCC_ReadOnly; X.SourceLoc = T.SourceLoc; }
|
decl_flag(X) ::= READONLY(T). { X.Int = ZCC_ReadOnly; X.SourceLoc = T.SourceLoc; }
|
||||||
decl_flag(X) ::= DEPRECATED(T). { X.Int = ZCC_Deprecated; X.SourceLoc = T.SourceLoc; }
|
|
||||||
decl_flag(X) ::= VIRTUAL(T). { X.Int = ZCC_Virtual; X.SourceLoc = T.SourceLoc; }
|
decl_flag(X) ::= VIRTUAL(T). { X.Int = ZCC_Virtual; X.SourceLoc = T.SourceLoc; }
|
||||||
decl_flag(X) ::= OVERRIDE(T). { X.Int = ZCC_Override; X.SourceLoc = T.SourceLoc; }
|
decl_flag(X) ::= OVERRIDE(T). { X.Int = ZCC_Override; X.SourceLoc = T.SourceLoc; }
|
||||||
decl_flag(X) ::= VARARG(T). { X.Int = ZCC_VarArg; X.SourceLoc = T.SourceLoc; }
|
decl_flag(X) ::= VARARG(T). { X.Int = ZCC_VarArg; X.SourceLoc = T.SourceLoc; }
|
||||||
|
|
|
@ -275,8 +275,8 @@ void ZCCCompiler::ProcessStruct(ZCC_Struct *cnode, PSymbolTreeNode *treenode, ZC
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
ZCCCompiler::ZCCCompiler(ZCC_AST &ast, DObject *_outer, PSymbolTable &_symbols, PNamespace *_outnamespc, int lumpnum)
|
ZCCCompiler::ZCCCompiler(ZCC_AST &ast, DObject *_outer, PSymbolTable &_symbols, PNamespace *_outnamespc, int lumpnum, const VersionInfo &ver)
|
||||||
: Outer(_outer), GlobalTreeNodes(&_symbols), OutNamespace(_outnamespc), AST(ast), Lump(lumpnum)
|
: Outer(_outer), GlobalTreeNodes(&_symbols), OutNamespace(_outnamespc), AST(ast), Lump(lumpnum), mVersion(ver)
|
||||||
{
|
{
|
||||||
FScriptPosition::ResetErrorCounter();
|
FScriptPosition::ResetErrorCounter();
|
||||||
// Group top-level nodes by type
|
// Group top-level nodes by type
|
||||||
|
@ -495,16 +495,32 @@ void ZCCCompiler::CreateStructTypes()
|
||||||
{
|
{
|
||||||
s->strct->Type = NewStruct(s->NodeName(), outer);
|
s->strct->Type = NewStruct(s->NodeName(), outer);
|
||||||
}
|
}
|
||||||
|
if (s->strct->Flags & ZCC_Version)
|
||||||
if ((s->strct->Flags & (ZCC_UIFlag | ZCC_Play)) == (ZCC_UIFlag | ZCC_Play))
|
|
||||||
{
|
{
|
||||||
Error(s->strct, "Struct %s has incompatible flags", s->NodeName().GetChars());
|
s->strct->Type->mVersion = s->strct->Version;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->strct->Flags & ZCC_UIFlag)
|
if (mVersion >= MakeVersion(2, 4, 0))
|
||||||
s->Type()->ObjectFlags |= OF_UI;
|
{
|
||||||
if (s->strct->Flags & ZCC_Play)
|
if ((s->strct->Flags & (ZCC_UIFlag | ZCC_Play)) == (ZCC_UIFlag | ZCC_Play))
|
||||||
s->Type()->ObjectFlags |= OF_Play;
|
{
|
||||||
|
Error(s->strct, "Struct %s has incompatible flags", s->NodeName().GetChars());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (outer != OutNamespace) s->Type()->ObjectFlags = FScopeBarrier::ChangeSideInObjectFlags(s->Type()->ObjectFlags, FScopeBarrier::SideFromObjectFlags(outer->ObjectFlags));
|
||||||
|
else if (s->strct->Flags & ZCC_ClearScope) Warn(s->strct, "Useless 'ClearScope' on struct %s not inside a class", s->NodeName().GetChars());
|
||||||
|
if (s->strct->Flags & ZCC_UIFlag)
|
||||||
|
s->Type()->ObjectFlags = FScopeBarrier::ChangeSideInObjectFlags(s->Type()->ObjectFlags, FScopeBarrier::Side_UI);
|
||||||
|
if (s->strct->Flags & ZCC_Play)
|
||||||
|
s->Type()->ObjectFlags = FScopeBarrier::ChangeSideInObjectFlags(s->Type()->ObjectFlags, FScopeBarrier::Side_Play);
|
||||||
|
if (s->strct->Flags & ZCC_ClearScope)
|
||||||
|
s->Type()->ObjectFlags = FScopeBarrier::ChangeSideInObjectFlags(s->Type()->ObjectFlags, FScopeBarrier::Side_PlainData); // don't inherit the scope from the outer class
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// old versions force 'play'.
|
||||||
|
s->Type()->ObjectFlags = FScopeBarrier::ChangeSideInObjectFlags(s->Type()->ObjectFlags, FScopeBarrier::Side_Play);
|
||||||
|
}
|
||||||
s->strct->Symbol = new PSymbolType(s->NodeName(), s->Type());
|
s->strct->Symbol = new PSymbolType(s->NodeName(), s->Type());
|
||||||
syms->AddSymbol(s->strct->Symbol);
|
syms->AddSymbol(s->strct->Symbol);
|
||||||
|
|
||||||
|
@ -593,6 +609,10 @@ void ZCCCompiler::CreateClassTypes()
|
||||||
// We will never get here if the name is a duplicate, so we can just do the assignment.
|
// We will never get here if the name is a duplicate, so we can just do the assignment.
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
if (parent->mVersion > mVersion)
|
||||||
|
{
|
||||||
|
Error(c->cls, "Parent class %s of %s not accessible to ZScript version %d.%d.%d", parent->TypeName.GetChars(), c->NodeName().GetChars(), mVersion.major, mVersion.minor, mVersion.revision);
|
||||||
|
}
|
||||||
c->cls->Type = parent->CreateDerivedClass(c->NodeName(), TentativeClass);
|
c->cls->Type = parent->CreateDerivedClass(c->NodeName(), TentativeClass);
|
||||||
if (c->Type() == nullptr)
|
if (c->Type() == nullptr)
|
||||||
{
|
{
|
||||||
|
@ -610,28 +630,40 @@ void ZCCCompiler::CreateClassTypes()
|
||||||
if (c->Type() == nullptr) c->cls->Type = parent->FindClassTentative(c->NodeName());
|
if (c->Type() == nullptr) c->cls->Type = parent->FindClassTentative(c->NodeName());
|
||||||
if (c->cls->Flags & ZCC_Abstract)
|
if (c->cls->Flags & ZCC_Abstract)
|
||||||
c->Type()->ObjectFlags |= OF_Abstract;
|
c->Type()->ObjectFlags |= OF_Abstract;
|
||||||
//
|
|
||||||
static int incompatible[] = { ZCC_UIFlag, ZCC_Play, ZCC_ClearScope };
|
if (c->cls->Flags & ZCC_Version)
|
||||||
int incompatiblecnt = 0;
|
|
||||||
for (size_t k = 0; k < countof(incompatible); k++)
|
|
||||||
if (incompatible[k] & c->cls->Flags) incompatiblecnt++;
|
|
||||||
|
|
||||||
if (incompatiblecnt > 1)
|
|
||||||
{
|
{
|
||||||
Error(c->cls, "Class %s has incompatible flags", c->NodeName().GetChars());
|
c->Type()->mVersion = c->cls->Version;
|
||||||
}
|
}
|
||||||
|
//
|
||||||
if (c->cls->Flags & ZCC_UIFlag)
|
if (mVersion >= MakeVersion(2, 4, 0))
|
||||||
c->Type()->ObjectFlags = (c->Type()->ObjectFlags&~OF_Play) | OF_UI;
|
|
||||||
if (c->cls->Flags & ZCC_Play)
|
|
||||||
c->Type()->ObjectFlags = (c->Type()->ObjectFlags&~OF_UI) | OF_Play;
|
|
||||||
if (parent->ObjectFlags & (OF_UI | OF_Play)) // parent is either ui or play
|
|
||||||
{
|
{
|
||||||
if (c->cls->Flags & (ZCC_UIFlag | ZCC_Play))
|
static int incompatible[] = { ZCC_UIFlag, ZCC_Play, ZCC_ClearScope };
|
||||||
|
int incompatiblecnt = 0;
|
||||||
|
for (size_t k = 0; k < countof(incompatible); k++)
|
||||||
|
if (incompatible[k] & c->cls->Flags) incompatiblecnt++;
|
||||||
|
|
||||||
|
if (incompatiblecnt > 1)
|
||||||
{
|
{
|
||||||
Error(c->cls, "Can't change class scope in class %s", c->NodeName().GetChars());
|
Error(c->cls, "Class %s has incompatible flags", c->NodeName().GetChars());
|
||||||
}
|
}
|
||||||
c->Type()->ObjectFlags = (c->Type()->ObjectFlags & ~(OF_UI | OF_Play)) | (parent->ObjectFlags & (OF_UI | OF_Play));
|
|
||||||
|
if (c->cls->Flags & ZCC_UIFlag)
|
||||||
|
c->Type()->ObjectFlags = (c->Type()->ObjectFlags&~OF_Play) | OF_UI;
|
||||||
|
if (c->cls->Flags & ZCC_Play)
|
||||||
|
c->Type()->ObjectFlags = (c->Type()->ObjectFlags&~OF_UI) | OF_Play;
|
||||||
|
if (parent->ObjectFlags & (OF_UI | OF_Play)) // parent is either ui or play
|
||||||
|
{
|
||||||
|
if (c->cls->Flags & (ZCC_UIFlag | ZCC_Play))
|
||||||
|
{
|
||||||
|
Error(c->cls, "Can't change class scope in class %s", c->NodeName().GetChars());
|
||||||
|
}
|
||||||
|
c->Type()->ObjectFlags = (c->Type()->ObjectFlags & ~(OF_UI | OF_Play)) | (parent->ObjectFlags & (OF_UI | OF_Play));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
c->Type()->ObjectFlags = (c->Type()->ObjectFlags&~OF_UI) | OF_Play;
|
||||||
}
|
}
|
||||||
|
|
||||||
c->Type()->bExported = true; // this class is accessible to script side type casts. (The reason for this flag is that types like PInt need to be skipped.)
|
c->Type()->bExported = true; // this class is accessible to script side type casts. (The reason for this flag is that types like PInt need to be skipped.)
|
||||||
|
@ -1098,16 +1130,23 @@ bool ZCCCompiler::CompileFields(PStruct *type, TArray<ZCC_VarDeclarator *> &Fiel
|
||||||
if (field->Flags & ZCC_Deprecated) varflags |= VARF_Deprecated;
|
if (field->Flags & ZCC_Deprecated) varflags |= VARF_Deprecated;
|
||||||
if (field->Flags & ZCC_ReadOnly) varflags |= VARF_ReadOnly;
|
if (field->Flags & ZCC_ReadOnly) varflags |= VARF_ReadOnly;
|
||||||
if (field->Flags & ZCC_Transient) varflags |= VARF_Transient;
|
if (field->Flags & ZCC_Transient) varflags |= VARF_Transient;
|
||||||
if (type->ObjectFlags & OF_UI)
|
if (mVersion >= MakeVersion(2, 4, 0))
|
||||||
varflags |= VARF_UI;
|
{
|
||||||
if (type->ObjectFlags & OF_Play)
|
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)
|
||||||
|
varflags = FScopeBarrier::ChangeSideInFlags(varflags, FScopeBarrier::Side_Play);
|
||||||
|
if (field->Flags & ZCC_ClearScope)
|
||||||
|
varflags = FScopeBarrier::ChangeSideInFlags(varflags, FScopeBarrier::Side_PlainData);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
varflags |= VARF_Play;
|
varflags |= VARF_Play;
|
||||||
if (field->Flags & ZCC_UIFlag)
|
}
|
||||||
varflags = FScopeBarrier::ChangeSideInFlags(varflags, FScopeBarrier::Side_UI);
|
|
||||||
if (field->Flags & ZCC_Play)
|
|
||||||
varflags = FScopeBarrier::ChangeSideInFlags(varflags, FScopeBarrier::Side_Play);
|
|
||||||
if (field->Flags & ZCC_ClearScope)
|
|
||||||
varflags = FScopeBarrier::ChangeSideInFlags(varflags, FScopeBarrier::Side_PlainData);
|
|
||||||
|
|
||||||
if (field->Flags & ZCC_Native)
|
if (field->Flags & ZCC_Native)
|
||||||
{
|
{
|
||||||
|
@ -1174,7 +1213,8 @@ bool ZCCCompiler::CompileFields(PStruct *type, TArray<ZCC_VarDeclarator *> &Fiel
|
||||||
{
|
{
|
||||||
// for bit fields the type must point to the source variable.
|
// 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;
|
if (fd->BitValue != 0) thisfieldtype = fd->FieldSize == 1 ? TypeUInt8 : fd->FieldSize == 2 ? TypeUInt16 : TypeUInt32;
|
||||||
type->AddNativeField(name->Name, thisfieldtype, fd->FieldOffset, varflags, fd->BitValue);
|
auto f = type->AddNativeField(name->Name, thisfieldtype, fd->FieldOffset, varflags, fd->BitValue);
|
||||||
|
if (field->Flags & (ZCC_Version | ZCC_Deprecated)) f->mVersion = field->Version;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1184,7 +1224,8 @@ bool ZCCCompiler::CompileFields(PStruct *type, TArray<ZCC_VarDeclarator *> &Fiel
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
type->AddField(name->Name, thisfieldtype, varflags);
|
auto f = type->AddField(name->Name, thisfieldtype, varflags);
|
||||||
|
if (field->Flags & (ZCC_Version | ZCC_Deprecated)) f->mVersion = field->Version;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
name = static_cast<ZCC_VarName*>(name->SiblingNext);
|
name = static_cast<ZCC_VarName*>(name->SiblingNext);
|
||||||
|
@ -1467,6 +1508,11 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n
|
||||||
Error(field, "%s does not represent a class type", FName(ctype->Restriction->Id).GetChars());
|
Error(field, "%s does not represent a class type", FName(ctype->Restriction->Id).GetChars());
|
||||||
return TypeError;
|
return TypeError;
|
||||||
}
|
}
|
||||||
|
if (typesym->Type->mVersion > mVersion)
|
||||||
|
{
|
||||||
|
Error(field, "Class %s not accessible to ZScript version %d.%d.%d", FName(ctype->Restriction->Id).GetChars(), mVersion.major, mVersion.minor, mVersion.revision);
|
||||||
|
return TypeError;
|
||||||
|
}
|
||||||
retval = NewClassPointer(static_cast<PClass *>(typesym->Type));
|
retval = NewClassPointer(static_cast<PClass *>(typesym->Type));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1500,6 +1546,12 @@ PType *ZCCCompiler::ResolveUserType(ZCC_BasicType *type, PSymbolTable *symt)
|
||||||
if (sym != nullptr && sym->IsKindOf(RUNTIME_CLASS(PSymbolType)))
|
if (sym != nullptr && sym->IsKindOf(RUNTIME_CLASS(PSymbolType)))
|
||||||
{
|
{
|
||||||
auto ptype = static_cast<PSymbolType *>(sym)->Type;
|
auto ptype = static_cast<PSymbolType *>(sym)->Type;
|
||||||
|
if (ptype->mVersion > mVersion)
|
||||||
|
{
|
||||||
|
Error(type, "Type %s not accessible to ZScript version %d.%d.%d", FName(type->UserType->Id).GetChars(), mVersion.major, mVersion.minor, mVersion.revision);
|
||||||
|
return TypeError;
|
||||||
|
}
|
||||||
|
|
||||||
if (ptype->IsKindOf(RUNTIME_CLASS(PEnum)))
|
if (ptype->IsKindOf(RUNTIME_CLASS(PEnum)))
|
||||||
{
|
{
|
||||||
return TypeSInt32; // hack this to an integer until we can resolve the enum mess.
|
return TypeSInt32; // hack this to an integer until we can resolve the enum mess.
|
||||||
|
@ -1846,7 +1898,7 @@ void ZCCCompiler::ProcessDefaultProperty(PClassActor *cls, ZCC_PropertyStmt *pro
|
||||||
if (namenode->Id == NAME_DamageFunction)
|
if (namenode->Id == NAME_DamageFunction)
|
||||||
{
|
{
|
||||||
auto x = ConvertNode(prop->Values);
|
auto x = ConvertNode(prop->Values);
|
||||||
CreateDamageFunction(OutNamespace, cls, (AActor *)bag.Info->Defaults, x, false, Lump);
|
CreateDamageFunction(OutNamespace, mVersion, cls, (AActor *)bag.Info->Defaults, x, false, Lump);
|
||||||
((AActor *)bag.Info->Defaults)->DamageVal = -1;
|
((AActor *)bag.Info->Defaults)->DamageVal = -1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2001,6 +2053,7 @@ void ZCCCompiler::InitDefaults()
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
bag.ClassName = c->Type()->TypeName;
|
bag.ClassName = c->Type()->TypeName;
|
||||||
#endif
|
#endif
|
||||||
|
bag.Version = mVersion;
|
||||||
bag.Namespace = OutNamespace;
|
bag.Namespace = OutNamespace;
|
||||||
bag.Info = ti;
|
bag.Info = ti;
|
||||||
bag.DropItemSet = false;
|
bag.DropItemSet = false;
|
||||||
|
@ -2124,31 +2177,27 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
|
||||||
if (f->Flags & ZCC_Override) varflags |= VARF_Override;
|
if (f->Flags & ZCC_Override) varflags |= VARF_Override;
|
||||||
if (f->Flags & ZCC_VarArg) varflags |= VARF_VarArg;
|
if (f->Flags & ZCC_VarArg) varflags |= VARF_VarArg;
|
||||||
if (f->Flags & ZCC_FuncConst) varflags |= VARF_ReadOnly; // FuncConst method is internally marked as VARF_ReadOnly
|
if (f->Flags & ZCC_FuncConst) varflags |= VARF_ReadOnly; // FuncConst method is internally marked as VARF_ReadOnly
|
||||||
if (c->Type()->ObjectFlags & OF_UI)
|
if (mVersion >= MakeVersion(2, 4, 0))
|
||||||
varflags |= VARF_UI;
|
|
||||||
if (c->Type()->ObjectFlags & OF_Play)
|
|
||||||
varflags |= VARF_Play;
|
|
||||||
if (f->Flags & ZCC_FuncConst)
|
|
||||||
varflags = FScopeBarrier::ChangeSideInFlags(varflags, FScopeBarrier::Side_PlainData); // const implies clearscope. this is checked a bit later to also not have ZCC_Play/ZCC_UIFlag.
|
|
||||||
if (f->Flags & ZCC_UIFlag)
|
|
||||||
varflags = FScopeBarrier::ChangeSideInFlags(varflags, FScopeBarrier::Side_UI);
|
|
||||||
if (f->Flags & ZCC_Play)
|
|
||||||
varflags = FScopeBarrier::ChangeSideInFlags(varflags, FScopeBarrier::Side_Play);
|
|
||||||
if (f->Flags & ZCC_ClearScope)
|
|
||||||
varflags = FScopeBarrier::ChangeSideInFlags(varflags, FScopeBarrier::Side_Clear);
|
|
||||||
if (f->Flags & ZCC_VirtualScope)
|
|
||||||
varflags = FScopeBarrier::ChangeSideInFlags(varflags, FScopeBarrier::Side_Virtual);
|
|
||||||
|
|
||||||
// [ZZ] supporting const self for actors is quite a cumbersome task because there's no concept of a const pointer (?)
|
|
||||||
// either way, it doesn't make sense, because you can call any method on a readonly class instance.
|
|
||||||
|
|
||||||
// The above is nonsense. This needs to work and needs to be implemented properly.
|
|
||||||
/*
|
|
||||||
if ((f->Flags & ZCC_FuncConst) && (c->Type()->IsKindOf(RUNTIME_CLASS(PClass))))
|
|
||||||
{
|
{
|
||||||
Error(f, "'Const' on a method can only be used in structs");
|
if (c->Type()->ObjectFlags & OF_UI)
|
||||||
|
varflags |= VARF_UI;
|
||||||
|
if (c->Type()->ObjectFlags & OF_Play)
|
||||||
|
varflags |= VARF_Play;
|
||||||
|
//if (f->Flags & ZCC_FuncConst)
|
||||||
|
// varflags = FScopeBarrier::ChangeSideInFlags(varflags, FScopeBarrier::Side_PlainData); // const implies clearscope. this is checked a bit later to also not have ZCC_Play/ZCC_UIFlag.
|
||||||
|
if (f->Flags & ZCC_UIFlag)
|
||||||
|
varflags = FScopeBarrier::ChangeSideInFlags(varflags, FScopeBarrier::Side_UI);
|
||||||
|
if (f->Flags & ZCC_Play)
|
||||||
|
varflags = FScopeBarrier::ChangeSideInFlags(varflags, FScopeBarrier::Side_Play);
|
||||||
|
if (f->Flags & ZCC_ClearScope)
|
||||||
|
varflags = FScopeBarrier::ChangeSideInFlags(varflags, FScopeBarrier::Side_Clear);
|
||||||
|
if (f->Flags & ZCC_VirtualScope)
|
||||||
|
varflags = FScopeBarrier::ChangeSideInFlags(varflags, FScopeBarrier::Side_Virtual);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
varflags |= VARF_Play;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
if ((f->Flags & ZCC_VarArg) && !(f->Flags & ZCC_Native))
|
if ((f->Flags & ZCC_VarArg) && !(f->Flags & ZCC_Native))
|
||||||
{
|
{
|
||||||
|
@ -2216,13 +2265,6 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
|
||||||
Error(f, "'VirtualScope' on a static method is not supported");
|
Error(f, "'VirtualScope' on a static method is not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
// you can't have a const function belonging to either ui or play.
|
|
||||||
// const is intended for plain data to signify that you can call a method on readonly variable.
|
|
||||||
if ((f->Flags & ZCC_FuncConst) && (f->Flags & (ZCC_UIFlag | ZCC_Play | ZCC_VirtualScope)))
|
|
||||||
{
|
|
||||||
Error(f, "Invalid combination of qualifiers %s on function %s", FlagsToString(f->Flags&(ZCC_FuncConst | ZCC_UIFlag | ZCC_Play | ZCC_VirtualScope)).GetChars(), FName(f->Name).GetChars());
|
|
||||||
}
|
|
||||||
|
|
||||||
static int excludescope[] = { ZCC_UIFlag, ZCC_Play, ZCC_ClearScope, ZCC_VirtualScope };
|
static int excludescope[] = { ZCC_UIFlag, ZCC_Play, ZCC_ClearScope, ZCC_VirtualScope };
|
||||||
excludeflags = 0;
|
excludeflags = 0;
|
||||||
fc = 0;
|
fc = 0;
|
||||||
|
@ -2393,6 +2435,14 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
|
||||||
if (imp != nullptr) vindex = imp->VirtualIndex;
|
if (imp != nullptr) vindex = imp->VirtualIndex;
|
||||||
else Error(f, "Virtual base function %s not found in %s", FName(f->Name).GetChars(), cls->ParentClass->TypeName.GetChars());
|
else Error(f, "Virtual base function %s not found in %s", FName(f->Name).GetChars(), cls->ParentClass->TypeName.GetChars());
|
||||||
}
|
}
|
||||||
|
if (f->Flags & (ZCC_Version | ZCC_Deprecated))
|
||||||
|
{
|
||||||
|
sym->mVersion = f->Version;
|
||||||
|
if (varflags & VARF_Override)
|
||||||
|
{
|
||||||
|
Error(f, "Overridden function %s may not alter version restriction in %s", FName(f->Name).GetChars(), cls->ParentClass->TypeName.GetChars());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!(f->Flags & ZCC_Native))
|
if (!(f->Flags & ZCC_Native))
|
||||||
{
|
{
|
||||||
|
@ -2406,7 +2456,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
|
||||||
auto code = ConvertAST(c->Type(), f->Body);
|
auto code = ConvertAST(c->Type(), f->Body);
|
||||||
if (code != nullptr)
|
if (code != nullptr)
|
||||||
{
|
{
|
||||||
FunctionBuildList.AddFunction(OutNamespace, sym, code, FStringf("%s.%s", c->Type()->TypeName.GetChars(), FName(f->Name).GetChars()), false, -1, 0, Lump);
|
FunctionBuildList.AddFunction(OutNamespace, mVersion, sym, code, FStringf("%s.%s", c->Type()->TypeName.GetChars(), FName(f->Name).GetChars()), false, -1, 0, Lump);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2418,7 +2468,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
|
||||||
if (sym->Variants[0].Implementation != nullptr)
|
if (sym->Variants[0].Implementation != nullptr)
|
||||||
{
|
{
|
||||||
// [ZZ] unspecified virtual function inherits old scope. virtual function scope can't be changed.
|
// [ZZ] unspecified virtual function inherits old scope. virtual function scope can't be changed.
|
||||||
sym->Variants[0].Implementation->BarrierSide = FScopeBarrier::SideFromFlags(varflags);
|
sym->Variants[0].Implementation->VarFlags = sym->Variants[0].Flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
PClass *clstype = static_cast<PClass *>(c->Type());
|
PClass *clstype = static_cast<PClass *>(c->Type());
|
||||||
|
@ -2429,11 +2479,6 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
|
||||||
Error(f, "Virtual function %s.%s not present", c->Type()->TypeName.GetChars(), FName(f->Name).GetChars());
|
Error(f, "Virtual function %s.%s not present", c->Type()->TypeName.GetChars(), FName(f->Name).GetChars());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (varflags & VARF_Final)
|
|
||||||
sym->Variants[0].Implementation->Final = true;
|
|
||||||
if (varflags & VARF_ReadOnly)
|
|
||||||
sym->Variants[0].Implementation->FuncConst = true;
|
|
||||||
|
|
||||||
if (forclass)
|
if (forclass)
|
||||||
{
|
{
|
||||||
|
@ -2448,7 +2493,12 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto oldfunc = clstype->Virtuals[vindex];
|
auto oldfunc = clstype->Virtuals[vindex];
|
||||||
if (oldfunc->Final)
|
auto parentfunc = dyn_cast<PFunction>(clstype->ParentClass->Symbols.FindSymbol(sym->SymbolName, true));
|
||||||
|
if (parentfunc && parentfunc->mVersion > mVersion)
|
||||||
|
{
|
||||||
|
Error(f, "Attempt to override function %s which is incompatible with version %d.%d.%d", FName(f->Name).GetChars(), mVersion.major, mVersion.minor, mVersion.revision);
|
||||||
|
}
|
||||||
|
if (oldfunc->VarFlags & VARF_Final)
|
||||||
{
|
{
|
||||||
Error(f, "Attempt to override final function %s", FName(f->Name).GetChars());
|
Error(f, "Attempt to override final function %s", FName(f->Name).GetChars());
|
||||||
}
|
}
|
||||||
|
@ -2458,19 +2508,26 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
|
||||||
Error(f, "Attempt to change scope for virtual function %s", FName(f->Name).GetChars());
|
Error(f, "Attempt to change scope for virtual function %s", FName(f->Name).GetChars());
|
||||||
}
|
}
|
||||||
// you can't change const qualifier for a virtual method
|
// you can't change const qualifier for a virtual method
|
||||||
if (oldfunc->FuncConst != sym->Variants[0].Implementation->FuncConst)
|
if ((sym->Variants[0].Implementation->VarFlags & VARF_ReadOnly) && !(oldfunc->VarFlags & VARF_ReadOnly))
|
||||||
{
|
{
|
||||||
Error(f, "Attempt to change const qualifier for virtual function %s", FName(f->Name).GetChars());
|
Error(f, "Attempt to add const qualifier to virtual function %s", FName(f->Name).GetChars());
|
||||||
|
}
|
||||||
|
// you can't change protected qualifier for a virtual method (i.e. putting private), because this cannot be reliably checked without runtime stuff
|
||||||
|
if (f->Flags & (ZCC_Private | ZCC_Protected))
|
||||||
|
{
|
||||||
|
Error(f, "Attempt to change private/protected qualifiers for virtual function %s", FName(f->Name).GetChars());
|
||||||
}
|
}
|
||||||
// inherit scope of original function if override not specified
|
// inherit scope of original function if override not specified
|
||||||
sym->Variants[0].Implementation->BarrierSide = oldfunc->BarrierSide;
|
sym->Variants[0].Flags = FScopeBarrier::ChangeSideInFlags(sym->Variants[0].Flags, FScopeBarrier::SideFromFlags(oldfunc->VarFlags));
|
||||||
sym->Variants[0].Flags = FScopeBarrier::ChangeSideInFlags(sym->Variants[0].Flags, oldfunc->BarrierSide);
|
|
||||||
// inherit const from original function
|
// inherit const from original function
|
||||||
if ((sym->Variants[0].Implementation->FuncConst = oldfunc->FuncConst))
|
if (oldfunc->VarFlags & VARF_ReadOnly)
|
||||||
sym->Variants[0].Flags |= VARF_ReadOnly;
|
sym->Variants[0].Flags |= VARF_ReadOnly;
|
||||||
|
if (oldfunc->VarFlags & VARF_Protected)
|
||||||
|
sym->Variants[0].Flags |= VARF_Protected;
|
||||||
|
|
||||||
clstype->Virtuals[vindex] = sym->Variants[0].Implementation;
|
clstype->Virtuals[vindex] = sym->Variants[0].Implementation;
|
||||||
sym->Variants[0].Implementation->VirtualIndex = vindex;
|
sym->Variants[0].Implementation->VirtualIndex = vindex;
|
||||||
|
sym->Variants[0].Implementation->VarFlags = sym->Variants[0].Flags;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -2740,7 +2797,7 @@ void ZCCCompiler::CompileStates()
|
||||||
if (code != nullptr)
|
if (code != nullptr)
|
||||||
{
|
{
|
||||||
auto funcsym = CreateAnonymousFunction(c->Type(), nullptr, state.UseFlags);
|
auto funcsym = CreateAnonymousFunction(c->Type(), nullptr, state.UseFlags);
|
||||||
state.ActionFunc = FunctionBuildList.AddFunction(OutNamespace, funcsym, code, FStringf("%s.StateFunction.%d", c->Type()->TypeName.GetChars(), statedef.GetStateCount()), false, statedef.GetStateCount(), (int)sl->Frames->Len(), Lump);
|
state.ActionFunc = FunctionBuildList.AddFunction(OutNamespace, mVersion, funcsym, code, FStringf("%s.StateFunction.%d", c->Type()->TypeName.GetChars(), statedef.GetStateCount()), false, statedef.GetStateCount(), (int)sl->Frames->Len(), Lump);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,7 @@ struct ZCC_ConstantWork
|
||||||
class ZCCCompiler
|
class ZCCCompiler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ZCCCompiler(ZCC_AST &tree, DObject *outer, PSymbolTable &symbols, PNamespace *outnamespace, int lumpnum);
|
ZCCCompiler(ZCC_AST &tree, DObject *outer, PSymbolTable &symbols, PNamespace *outnamespace, int lumpnum, const VersionInfo & ver);
|
||||||
~ZCCCompiler();
|
~ZCCCompiler();
|
||||||
int Compile();
|
int Compile();
|
||||||
|
|
||||||
|
@ -127,6 +127,7 @@ private:
|
||||||
TArray<ZCC_StructWork *> Structs;
|
TArray<ZCC_StructWork *> Structs;
|
||||||
TArray<ZCC_ClassWork *> Classes;
|
TArray<ZCC_ClassWork *> Classes;
|
||||||
TArray<ZCC_PropertyWork *> Properties;
|
TArray<ZCC_PropertyWork *> Properties;
|
||||||
|
VersionInfo mVersion;
|
||||||
|
|
||||||
PSymbolTreeNode *AddTreeNode(FName name, ZCC_TreeNode *node, PSymbolTable *treenodes, bool searchparents = false);
|
PSymbolTreeNode *AddTreeNode(FName name, ZCC_TreeNode *node, PSymbolTable *treenodes, bool searchparents = false);
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
#include "i_system.h"
|
#include "i_system.h"
|
||||||
#include "m_argv.h"
|
#include "m_argv.h"
|
||||||
#include "v_text.h"
|
#include "v_text.h"
|
||||||
|
#include "version.h"
|
||||||
#include "zcc_parser.h"
|
#include "zcc_parser.h"
|
||||||
#include "zcc_compile.h"
|
#include "zcc_compile.h"
|
||||||
|
|
||||||
|
@ -145,6 +146,7 @@ static void InitTokenMap()
|
||||||
TOKENDEF (TK_Final, ZCC_FINAL);
|
TOKENDEF (TK_Final, ZCC_FINAL);
|
||||||
TOKENDEF (TK_Meta, ZCC_META);
|
TOKENDEF (TK_Meta, ZCC_META);
|
||||||
TOKENDEF (TK_Deprecated, ZCC_DEPRECATED);
|
TOKENDEF (TK_Deprecated, ZCC_DEPRECATED);
|
||||||
|
TOKENDEF (TK_Version, ZCC_VERSION);
|
||||||
TOKENDEF (TK_ReadOnly, ZCC_READONLY);
|
TOKENDEF (TK_ReadOnly, ZCC_READONLY);
|
||||||
TOKENDEF ('{', ZCC_LBRACE);
|
TOKENDEF ('{', ZCC_LBRACE);
|
||||||
TOKENDEF ('}', ZCC_RBRACE);
|
TOKENDEF ('}', ZCC_RBRACE);
|
||||||
|
@ -179,7 +181,6 @@ static void InitTokenMap()
|
||||||
TOKENDEF (']', ZCC_RBRACKET);
|
TOKENDEF (']', ZCC_RBRACKET);
|
||||||
TOKENDEF (TK_In, ZCC_IN);
|
TOKENDEF (TK_In, ZCC_IN);
|
||||||
TOKENDEF (TK_Out, ZCC_OUT);
|
TOKENDEF (TK_Out, ZCC_OUT);
|
||||||
TOKENDEF (TK_Optional, ZCC_OPTIONAL);
|
|
||||||
TOKENDEF (TK_Super, ZCC_SUPER);
|
TOKENDEF (TK_Super, ZCC_SUPER);
|
||||||
TOKENDEF (TK_Null, ZCC_NULLPTR);
|
TOKENDEF (TK_Null, ZCC_NULLPTR);
|
||||||
TOKENDEF ('~', ZCC_TILDE);
|
TOKENDEF ('~', ZCC_TILDE);
|
||||||
|
@ -232,29 +233,36 @@ static void InitTokenMap()
|
||||||
|
|
||||||
//**--------------------------------------------------------------------------
|
//**--------------------------------------------------------------------------
|
||||||
|
|
||||||
static void ParseSingleFile(const char *filename, int lump, void *parser, ZCCParseState &state)
|
static void ParseSingleFile(FScanner *pSC, const char *filename, int lump, void *parser, ZCCParseState &state)
|
||||||
{
|
{
|
||||||
int tokentype;
|
int tokentype;
|
||||||
//bool failed;
|
//bool failed;
|
||||||
ZCCToken value;
|
ZCCToken value;
|
||||||
FScanner sc;
|
FScanner lsc;
|
||||||
|
|
||||||
if (filename != nullptr)
|
if (pSC == nullptr)
|
||||||
{
|
{
|
||||||
lump = Wads.CheckNumForFullName(filename, true);
|
if (filename != nullptr)
|
||||||
if (lump >= 0)
|
|
||||||
{
|
{
|
||||||
sc.OpenLumpNum(lump);
|
lump = Wads.CheckNumForFullName(filename, true);
|
||||||
|
if (lump >= 0)
|
||||||
|
{
|
||||||
|
lsc.OpenLumpNum(lump);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Printf("Could not find script lump '%s'\n", filename);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else lsc.OpenLumpNum(lump);
|
||||||
{
|
|
||||||
Printf("Could not find script lump '%s'\n", filename);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else sc.OpenLumpNum(lump);
|
|
||||||
|
|
||||||
|
pSC = &lsc;
|
||||||
|
}
|
||||||
|
FScanner &sc = *pSC;
|
||||||
|
sc.SetParseVersion(state.ParseVersion);
|
||||||
state.sc = ≻
|
state.sc = ≻
|
||||||
|
|
||||||
while (sc.GetToken())
|
while (sc.GetToken())
|
||||||
{
|
{
|
||||||
value.SourceLoc = sc.GetMessageLine();
|
value.SourceLoc = sc.GetMessageLine();
|
||||||
|
@ -343,9 +351,47 @@ static void DoParse(int lumpnum)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
sc.OpenLumpNum(lumpnum);
|
sc.OpenLumpNum(lumpnum);
|
||||||
|
sc.SetParseVersion({ 2, 4 }); // To get 'version' we need parse version 2.4 for the initial test
|
||||||
auto saved = sc.SavePos();
|
auto saved = sc.SavePos();
|
||||||
|
|
||||||
ParseSingleFile(nullptr, lumpnum, parser, state);
|
if (sc.GetToken())
|
||||||
|
{
|
||||||
|
if (sc.TokenType == TK_Version)
|
||||||
|
{
|
||||||
|
char *endp;
|
||||||
|
sc.MustGetString();
|
||||||
|
state.ParseVersion.major = (int16_t)clamp<unsigned long long>(strtoull(sc.String, &endp, 10), 0, USHRT_MAX);
|
||||||
|
if (*endp != '.')
|
||||||
|
{
|
||||||
|
sc.ScriptError("Bad version directive");
|
||||||
|
}
|
||||||
|
state.ParseVersion.minor = (int16_t)clamp<unsigned long long>(strtoll(endp + 1, &endp, 10), 0, USHRT_MAX);
|
||||||
|
if (*endp == '.')
|
||||||
|
{
|
||||||
|
state.ParseVersion.revision = (int16_t)clamp<unsigned long long>(strtoll(endp + 1, &endp, 10), 0, USHRT_MAX);
|
||||||
|
}
|
||||||
|
else state.ParseVersion.revision = 0;
|
||||||
|
if (*endp != 0)
|
||||||
|
{
|
||||||
|
sc.ScriptError("Bad version directive");
|
||||||
|
}
|
||||||
|
if (state.ParseVersion.major == USHRT_MAX || state.ParseVersion.minor == USHRT_MAX || state.ParseVersion.revision == USHRT_MAX)
|
||||||
|
{
|
||||||
|
sc.ScriptError("Bad version directive");
|
||||||
|
}
|
||||||
|
if (state.ParseVersion > MakeVersion(VER_MAJOR, VER_MINOR, VER_REVISION))
|
||||||
|
{
|
||||||
|
sc.ScriptError("Version mismatch. %d.%d.%d expected but only %d.%d.%d supported", state.ParseVersion.major, state.ParseVersion.minor, state.ParseVersion.revision, VER_MAJOR, VER_MINOR, VER_REVISION);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state.ParseVersion = MakeVersion(2, 3); // 2.3 is the first version of ZScript.
|
||||||
|
sc.RestorePos(saved);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ParseSingleFile(&sc, nullptr, lumpnum, parser, state);
|
||||||
for (unsigned i = 0; i < Includes.Size(); i++)
|
for (unsigned i = 0; i < Includes.Size(); i++)
|
||||||
{
|
{
|
||||||
lumpnum = Wads.CheckNumForFullName(Includes[i], true);
|
lumpnum = Wads.CheckNumForFullName(Includes[i], true);
|
||||||
|
@ -362,7 +408,7 @@ static void DoParse(int lumpnum)
|
||||||
Wads.GetWadFullName(Wads.GetLumpFile(baselump)), Includes[i].GetChars());
|
Wads.GetWadFullName(Wads.GetLumpFile(baselump)), Includes[i].GetChars());
|
||||||
}
|
}
|
||||||
|
|
||||||
ParseSingleFile(nullptr, lumpnum, parser, state);
|
ParseSingleFile(nullptr, nullptr, lumpnum, parser, state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Includes.Clear();
|
Includes.Clear();
|
||||||
|
@ -405,7 +451,7 @@ static void DoParse(int lumpnum)
|
||||||
|
|
||||||
PSymbolTable symtable;
|
PSymbolTable symtable;
|
||||||
auto newns = Wads.GetLumpFile(lumpnum) == 0 ? Namespaces.GlobalNamespace : Namespaces.NewNamespace(Wads.GetLumpFile(lumpnum));
|
auto newns = Wads.GetLumpFile(lumpnum) == 0 ? Namespaces.GlobalNamespace : Namespaces.NewNamespace(Wads.GetLumpFile(lumpnum));
|
||||||
ZCCCompiler cc(state, NULL, symtable, newns, lumpnum);
|
ZCCCompiler cc(state, NULL, symtable, newns, lumpnum, state.ParseVersion);
|
||||||
cc.Compile();
|
cc.Compile();
|
||||||
|
|
||||||
if (FScriptPosition::ErrorCounter > 0)
|
if (FScriptPosition::ErrorCounter > 0)
|
||||||
|
@ -436,16 +482,6 @@ void ParseScripts()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
CCMD(parse)
|
|
||||||
{
|
|
||||||
if (argv.argc() == 2)
|
|
||||||
{
|
|
||||||
DoParse(argv[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
static FString ZCCTokenName(int terminal)
|
static FString ZCCTokenName(int terminal)
|
||||||
{
|
{
|
||||||
if (terminal == ZCC_EOF)
|
if (terminal == ZCC_EOF)
|
||||||
|
|
|
@ -41,6 +41,7 @@ enum
|
||||||
ZCC_Play = 1 << 18,
|
ZCC_Play = 1 << 18,
|
||||||
ZCC_ClearScope = 1 << 19,
|
ZCC_ClearScope = 1 << 19,
|
||||||
ZCC_VirtualScope = 1 << 20,
|
ZCC_VirtualScope = 1 << 20,
|
||||||
|
ZCC_Version = 1 << 21,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function parameter modifiers
|
// Function parameter modifiers
|
||||||
|
@ -194,6 +195,7 @@ struct ZCC_Struct : ZCC_NamedNode
|
||||||
VM_UWORD Flags;
|
VM_UWORD Flags;
|
||||||
ZCC_TreeNode *Body;
|
ZCC_TreeNode *Body;
|
||||||
PStruct *Type;
|
PStruct *Type;
|
||||||
|
VersionInfo Version;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ZCC_Property : ZCC_NamedNode
|
struct ZCC_Property : ZCC_NamedNode
|
||||||
|
@ -483,6 +485,7 @@ struct ZCC_FuncParamDecl : ZCC_TreeNode
|
||||||
struct ZCC_DeclFlags : ZCC_TreeNode
|
struct ZCC_DeclFlags : ZCC_TreeNode
|
||||||
{
|
{
|
||||||
ZCC_Identifier *Id;
|
ZCC_Identifier *Id;
|
||||||
|
VersionInfo Version;
|
||||||
int Flags;
|
int Flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -497,6 +500,7 @@ struct ZCC_Declarator : ZCC_TreeNode
|
||||||
{
|
{
|
||||||
ZCC_Type *Type;
|
ZCC_Type *Type;
|
||||||
int Flags;
|
int Flags;
|
||||||
|
VersionInfo Version;
|
||||||
};
|
};
|
||||||
|
|
||||||
// A variable in a class or struct.
|
// A variable in a class or struct.
|
||||||
|
@ -542,6 +546,7 @@ struct ZCC_AST
|
||||||
FSharedStringArena Strings;
|
FSharedStringArena Strings;
|
||||||
FMemArena SyntaxArena;
|
FMemArena SyntaxArena;
|
||||||
struct ZCC_TreeNode *TopNode;
|
struct ZCC_TreeNode *TopNode;
|
||||||
|
VersionInfo ParseVersion;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ZCCParseState : public ZCC_AST
|
struct ZCCParseState : public ZCC_AST
|
||||||
|
|
|
@ -51,6 +51,7 @@
|
||||||
#include "colormatcher.h"
|
#include "colormatcher.h"
|
||||||
#include "v_palette.h"
|
#include "v_palette.h"
|
||||||
#include "d_player.h"
|
#include "d_player.h"
|
||||||
|
#include "g_levellocals.h"
|
||||||
|
|
||||||
CVAR( Float, blood_fade_scalar, 1.0f, CVAR_ARCHIVE ) // [SP] Pulled from Skulltag - changed default from 0.5 to 1.0
|
CVAR( Float, blood_fade_scalar, 1.0f, CVAR_ARCHIVE ) // [SP] Pulled from Skulltag - changed default from 0.5 to 1.0
|
||||||
CVAR( Float, pickup_fade_scalar, 1.0f, CVAR_ARCHIVE ) // [SP] Uses same logic as blood_fade_scalar except for pickups
|
CVAR( Float, pickup_fade_scalar, 1.0f, CVAR_ARCHIVE ) // [SP] Uses same logic as blood_fade_scalar except for pickups
|
||||||
|
@ -168,13 +169,19 @@ void V_AddPlayerBlend (player_t *CPlayer, float blend[4], float maxinvalpha, int
|
||||||
{
|
{
|
||||||
if (CPlayer->hazardcount > 16*TICRATE || (CPlayer->hazardcount & 8))
|
if (CPlayer->hazardcount > 16*TICRATE || (CPlayer->hazardcount & 8))
|
||||||
{
|
{
|
||||||
V_AddBlend (0.f, 1.f, 0.f, 0.125f, blend);
|
float r = ((level.hazardflash & 0xff0000) >> 16) / 255.f;
|
||||||
|
float g = ((level.hazardflash & 0xff00) >> 8) / 255.f;
|
||||||
|
float b = ((level.hazardflash & 0xff)) / 255.f;
|
||||||
|
V_AddBlend (r, g, b, 0.125f, blend);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cnt= MIN(CPlayer->hazardcount/8, 64);
|
cnt= MIN(CPlayer->hazardcount/8, 64);
|
||||||
V_AddBlend (0.f, 0.2571f, 0.f, cnt/93.2571428571f, blend);
|
float r = ((level.hazardcolor & 0xff0000) >> 16) / 255.f;
|
||||||
|
float g = ((level.hazardcolor & 0xff00) >> 8) / 255.f;
|
||||||
|
float b = ((level.hazardcolor & 0xff)) / 255.f;
|
||||||
|
V_AddBlend (r, g, b, cnt/93.2571428571f, blend);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,10 @@ const char *GetVersionString();
|
||||||
#define RC_FILEVERSION 1,3,9999,0
|
#define RC_FILEVERSION 1,3,9999,0
|
||||||
#define RC_PRODUCTVERSION 1,3,9999,0
|
#define RC_PRODUCTVERSION 1,3,9999,0
|
||||||
#define RC_PRODUCTVERSION2 VERSIONSTR
|
#define RC_PRODUCTVERSION2 VERSIONSTR
|
||||||
|
// These are for content versioning. The current state is '2.4'.
|
||||||
|
#define VER_MAJOR 2
|
||||||
|
#define VER_MINOR 4
|
||||||
|
#define VER_REVISION 0
|
||||||
|
|
||||||
// Version identifier for network games.
|
// Version identifier for network games.
|
||||||
// Bump it every time you do a release unless you're certain you
|
// Bump it every time you do a release unless you're certain you
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
version "2.4"
|
||||||
#include "zscript/base.txt"
|
#include "zscript/base.txt"
|
||||||
#include "zscript/sounddata.txt"
|
#include "zscript/sounddata.txt"
|
||||||
#include "zscript/mapdata.txt"
|
#include "zscript/mapdata.txt"
|
||||||
|
|
|
@ -237,17 +237,17 @@ class Actor : Thinker native
|
||||||
//int ConversationRoot; // THe root of the current dialogue
|
//int ConversationRoot; // THe root of the current dialogue
|
||||||
|
|
||||||
// deprecated things.
|
// deprecated things.
|
||||||
native readonly deprecated double X;
|
native readonly deprecated("2.3") double X;
|
||||||
native readonly deprecated double Y;
|
native readonly deprecated("2.3") double Y;
|
||||||
native readonly deprecated double Z;
|
native readonly deprecated("2.3") double Z;
|
||||||
native readonly deprecated double VelX;
|
native readonly deprecated("2.3") double VelX;
|
||||||
native readonly deprecated double VelY;
|
native readonly deprecated("2.3") double VelY;
|
||||||
native readonly deprecated double VelZ;
|
native readonly deprecated("2.3") double VelZ;
|
||||||
native readonly deprecated double MomX;
|
native readonly deprecated("2.3") double MomX;
|
||||||
native readonly deprecated double MomY;
|
native readonly deprecated("2.3") double MomY;
|
||||||
native readonly deprecated double MomZ;
|
native readonly deprecated("2.3") double MomZ;
|
||||||
native deprecated double ScaleX;
|
native deprecated("2.3") double ScaleX;
|
||||||
native deprecated double ScaleY;
|
native deprecated("2.3") double ScaleY;
|
||||||
|
|
||||||
//FStrifeDialogueNode *Conversation; // [RH] The dialogue to show when this actor is used.;
|
//FStrifeDialogueNode *Conversation; // [RH] The dialogue to show when this actor is used.;
|
||||||
|
|
||||||
|
@ -717,7 +717,7 @@ class Actor : Thinker native
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
deprecated void A_FaceConsolePlayer(double MaxTurnAngle = 0) {}
|
deprecated("2.3") void A_FaceConsolePlayer(double MaxTurnAngle = 0) {}
|
||||||
|
|
||||||
void A_SetSpecial(int spec, int arg0 = 0, int arg1 = 0, int arg2 = 0, int arg3 = 0, int arg4 = 0)
|
void A_SetSpecial(int spec, int arg0 = 0, int arg1 = 0, int arg2 = 0, int arg3 = 0, int arg4 = 0)
|
||||||
{
|
{
|
||||||
|
@ -868,18 +868,18 @@ class Actor : Thinker native
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
deprecated void A_MeleeAttack()
|
deprecated("2.3") void A_MeleeAttack()
|
||||||
{
|
{
|
||||||
DoAttack(true, false, MeleeDamage, MeleeSound, NULL, 0);
|
DoAttack(true, false, MeleeDamage, MeleeSound, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
deprecated void A_MissileAttack()
|
deprecated("2.3") void A_MissileAttack()
|
||||||
{
|
{
|
||||||
Class<Actor> MissileType = MissileName;
|
Class<Actor> MissileType = MissileName;
|
||||||
DoAttack(false, true, 0, 0, MissileType, MissileHeight);
|
DoAttack(false, true, 0, 0, MissileType, MissileHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
deprecated void A_ComboAttack()
|
deprecated("2.3") void A_ComboAttack()
|
||||||
{
|
{
|
||||||
Class<Actor> MissileType = MissileName;
|
Class<Actor> MissileType = MissileName;
|
||||||
DoAttack(true, true, MeleeDamage, MeleeSound, MissileType, MissileHeight);
|
DoAttack(true, true, MeleeDamage, MeleeSound, MissileType, MissileHeight);
|
||||||
|
@ -919,13 +919,13 @@ class Actor : Thinker native
|
||||||
native void A_Wander(int flags = 0);
|
native void A_Wander(int flags = 0);
|
||||||
native void A_Look2();
|
native void A_Look2();
|
||||||
|
|
||||||
deprecated native void A_BulletAttack();
|
deprecated("2.3") native void A_BulletAttack();
|
||||||
native void A_WolfAttack(int flags = 0, sound whattoplay = "weapons/pistol", double snipe = 1.0, int maxdamage = 64, int blocksize = 128, int pointblank = 2, int longrange = 4, double runspeed = 160.0, class<Actor> pufftype = "BulletPuff");
|
native void A_WolfAttack(int flags = 0, sound whattoplay = "weapons/pistol", double snipe = 1.0, int maxdamage = 64, int blocksize = 128, int pointblank = 2, int longrange = 4, double runspeed = 160.0, class<Actor> pufftype = "BulletPuff");
|
||||||
native void A_PlaySound(sound whattoplay = "weapons/pistol", int slot = CHAN_BODY, double volume = 1.0, bool looping = false, double attenuation = ATTN_NORM, bool local = false);
|
native void A_PlaySound(sound whattoplay = "weapons/pistol", int slot = CHAN_BODY, double volume = 1.0, bool looping = false, double attenuation = ATTN_NORM, bool local = false);
|
||||||
deprecated void A_PlayWeaponSound(sound whattoplay) { A_PlaySound(whattoplay, CHAN_WEAPON); }
|
deprecated("2.3") void A_PlayWeaponSound(sound whattoplay) { A_PlaySound(whattoplay, CHAN_WEAPON); }
|
||||||
native void A_StopSound(int slot = CHAN_VOICE); // Bad default but that's what is originally was...
|
native void A_StopSound(int slot = CHAN_VOICE); // Bad default but that's what is originally was...
|
||||||
deprecated native void A_PlaySoundEx(sound whattoplay, name slot, bool looping = false, int attenuation = 0);
|
deprecated("2.3") native void A_PlaySoundEx(sound whattoplay, name slot, bool looping = false, int attenuation = 0);
|
||||||
deprecated native void A_StopSoundEx(name slot);
|
deprecated("2.3") native void A_StopSoundEx(name slot);
|
||||||
native void A_SeekerMissile(int threshold, int turnmax, int flags = 0, int chance = 50, int distance = 10);
|
native void A_SeekerMissile(int threshold, int turnmax, int flags = 0, int chance = 50, int distance = 10);
|
||||||
native action state A_Jump(int chance, statelabel label, ...);
|
native action state A_Jump(int chance, statelabel label, ...);
|
||||||
native Actor A_SpawnProjectile(class<Actor> missiletype, double spawnheight = 32, double spawnofs_xy = 0, double angle = 0, int flags = 0, double pitch = 0, int ptr = AAPTR_TARGET);
|
native Actor A_SpawnProjectile(class<Actor> missiletype, double spawnheight = 32, double spawnofs_xy = 0, double angle = 0, int flags = 0, double pitch = 0, int ptr = AAPTR_TARGET);
|
||||||
|
@ -951,7 +951,7 @@ class Actor : Thinker native
|
||||||
native void A_ExtChase(bool usemelee, bool usemissile, bool playactive = true, bool nightmarefast = false);
|
native void A_ExtChase(bool usemelee, bool usemissile, bool playactive = true, bool nightmarefast = false);
|
||||||
native void A_DropInventory(class<Inventory> itemtype, int amount = -1);
|
native void A_DropInventory(class<Inventory> itemtype, int amount = -1);
|
||||||
native void A_SetBlend(color color1, double alpha, int tics, color color2 = 0);
|
native void A_SetBlend(color color1, double alpha, int tics, color color2 = 0);
|
||||||
deprecated native void A_ChangeFlag(string flagname, bool value);
|
deprecated("2.3") native void A_ChangeFlag(string flagname, bool value);
|
||||||
native void A_ChangeCountFlags(int kill = FLAG_NO_CHANGE, int item = FLAG_NO_CHANGE, int secret = FLAG_NO_CHANGE);
|
native void A_ChangeCountFlags(int kill = FLAG_NO_CHANGE, int item = FLAG_NO_CHANGE, int secret = FLAG_NO_CHANGE);
|
||||||
native void A_RaiseMaster(int flags = 0);
|
native void A_RaiseMaster(int flags = 0);
|
||||||
native void A_RaiseChildren(int flags = 0);
|
native void A_RaiseChildren(int flags = 0);
|
||||||
|
@ -990,10 +990,10 @@ class Actor : Thinker native
|
||||||
native void A_SetRoll(double roll, int flags = 0, int ptr = AAPTR_DEFAULT);
|
native void A_SetRoll(double roll, int flags = 0, int ptr = AAPTR_DEFAULT);
|
||||||
native void A_ScaleVelocity(double scale, int ptr = AAPTR_DEFAULT);
|
native void A_ScaleVelocity(double scale, int ptr = AAPTR_DEFAULT);
|
||||||
native void A_ChangeVelocity(double x = 0, double y = 0, double z = 0, int flags = 0, int ptr = AAPTR_DEFAULT);
|
native void A_ChangeVelocity(double x = 0, double y = 0, double z = 0, int flags = 0, int ptr = AAPTR_DEFAULT);
|
||||||
deprecated native void A_SetUserVar(name varname, int value);
|
deprecated("2.3") native void A_SetUserVar(name varname, int value);
|
||||||
deprecated native void A_SetUserArray(name varname, int index, int value);
|
deprecated("2.3") native void A_SetUserArray(name varname, int index, int value);
|
||||||
deprecated native void A_SetUserVarFloat(name varname, double value);
|
deprecated("2.3") native void A_SetUserVarFloat(name varname, double value);
|
||||||
deprecated native void A_SetUserArrayFloat(name varname, int index, double value);
|
deprecated("2.3") native void A_SetUserArrayFloat(name varname, int index, double value);
|
||||||
native void A_Quake(int intensity, int duration, int damrad, int tremrad, sound sfx = "world/quake");
|
native void A_Quake(int intensity, int duration, int damrad, int tremrad, sound sfx = "world/quake");
|
||||||
native void A_QuakeEx(int intensityX, int intensityY, int intensityZ, int duration, int damrad, int tremrad, sound sfx = "world/quake", int flags = 0, double mulWaveX = 1, double mulWaveY = 1, double mulWaveZ = 1, int falloff = 0, int highpoint = 0, double rollIntensity = 0, double rollWave = 0);
|
native void A_QuakeEx(int intensityX, int intensityY, int intensityZ, int duration, int damrad, int tremrad, sound sfx = "world/quake", int flags = 0, double mulWaveX = 1, double mulWaveY = 1, double mulWaveZ = 1, int falloff = 0, int highpoint = 0, double rollIntensity = 0, double rollWave = 0);
|
||||||
action native void A_SetTics(int tics);
|
action native void A_SetTics(int tics);
|
||||||
|
@ -1093,7 +1093,7 @@ class Actor : Thinker native
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal functions
|
// Internal functions
|
||||||
deprecated private native int __decorate_internal_int__(int i);
|
deprecated("2.3") private native int __decorate_internal_int__(int i);
|
||||||
deprecated private native bool __decorate_internal_bool__(bool b);
|
deprecated("2.3") private native bool __decorate_internal_bool__(bool b);
|
||||||
deprecated private native double __decorate_internal_float__(double f);
|
deprecated("2.3") private native double __decorate_internal_float__(double f);
|
||||||
}
|
}
|
||||||
|
|
|
@ -170,7 +170,7 @@ extend class Actor
|
||||||
|
|
||||||
private native bool CheckFlag(string flagname, int check_pointer = AAPTR_DEFAULT);
|
private native bool CheckFlag(string flagname, int check_pointer = AAPTR_DEFAULT);
|
||||||
|
|
||||||
deprecated action state A_CheckFlag(string flagname, statelabel label, int check_pointer = AAPTR_DEFAULT)
|
deprecated("2.3") action state A_CheckFlag(string flagname, statelabel label, int check_pointer = AAPTR_DEFAULT)
|
||||||
{
|
{
|
||||||
return CheckFlag(flagname, check_pointer)? ResolveState(label) : null;
|
return CheckFlag(flagname, check_pointer)? ResolveState(label) : null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
struct InputEventData native
|
struct InputEventData native version("2.4")
|
||||||
{
|
{
|
||||||
native uint8 type;
|
native uint8 type;
|
||||||
native uint8 subtype;
|
native uint8 subtype;
|
||||||
|
@ -244,7 +244,7 @@ struct Font native
|
||||||
native BrokenLines BreakLines(String text, int maxlen);
|
native BrokenLines BreakLines(String text, int maxlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Translation
|
struct Translation version("2.4")
|
||||||
{
|
{
|
||||||
Color colors[256];
|
Color colors[256];
|
||||||
|
|
||||||
|
@ -290,7 +290,7 @@ struct CVar native
|
||||||
native int ResetToDefault();
|
native int ResetToDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct GIFont
|
struct GIFont version("2.4")
|
||||||
{
|
{
|
||||||
Name fontname;
|
Name fontname;
|
||||||
Name color;
|
Name color;
|
||||||
|
@ -337,7 +337,7 @@ class Object native
|
||||||
virtual virtualscope void OnDestroy() {}
|
virtual virtualscope void OnDestroy() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
class BrokenLines : Object native
|
class BrokenLines : Object native version("2.4")
|
||||||
{
|
{
|
||||||
native int Count();
|
native int Count();
|
||||||
native int StringWidth(int line);
|
native int StringWidth(int line);
|
||||||
|
@ -458,23 +458,23 @@ struct LevelLocals native
|
||||||
native int found_items;
|
native int found_items;
|
||||||
native int total_monsters;
|
native int total_monsters;
|
||||||
native int killed_monsters;
|
native int killed_monsters;
|
||||||
native double gravity;
|
native play double gravity;
|
||||||
native double aircontrol;
|
native play double aircontrol;
|
||||||
native double airfriction;
|
native play double airfriction;
|
||||||
native int airsupply;
|
native play int airsupply;
|
||||||
native double teamdamage;
|
native readonly double teamdamage;
|
||||||
native bool monsterstelefrag;
|
native readonly bool monsterstelefrag;
|
||||||
native bool actownspecial;
|
native readonly bool actownspecial;
|
||||||
native bool sndseqtotalctrl;
|
native readonly bool sndseqtotalctrl;
|
||||||
native bool allmap;
|
native bool allmap;
|
||||||
native bool missilesactivateimpact;
|
native readonly bool missilesactivateimpact;
|
||||||
native bool monsterfallingdamage;
|
native readonly bool monsterfallingdamage;
|
||||||
native bool checkswitchrange;
|
native readonly bool checkswitchrange;
|
||||||
native bool polygrind;
|
native readonly bool polygrind;
|
||||||
native bool nomonsters;
|
native readonly bool nomonsters;
|
||||||
native bool frozen;
|
native bool frozen;
|
||||||
native bool infinite_flight;
|
native readonly bool infinite_flight;
|
||||||
native bool no_dlg_freeze;
|
native readonly bool no_dlg_freeze;
|
||||||
// level_info_t *info cannot be done yet.
|
// level_info_t *info cannot be done yet.
|
||||||
|
|
||||||
native String GetUDMFString(int type, int index, Name key);
|
native String GetUDMFString(int type, int index, Name key);
|
||||||
|
@ -618,7 +618,7 @@ class Floor : Thinker native
|
||||||
floorRaiseInstant,
|
floorRaiseInstant,
|
||||||
floorMoveToValue,
|
floorMoveToValue,
|
||||||
floorRaiseToLowestCeiling,
|
floorRaiseToLowestCeiling,
|
||||||
floorRaiseuint8xture,
|
floorRaiseByTexture,
|
||||||
|
|
||||||
floorLowerAndChange,
|
floorLowerAndChange,
|
||||||
floorRaiseAndChange,
|
floorRaiseAndChange,
|
||||||
|
@ -626,7 +626,7 @@ class Floor : Thinker native
|
||||||
floorRaiseToLowest,
|
floorRaiseToLowest,
|
||||||
floorRaiseToCeiling,
|
floorRaiseToCeiling,
|
||||||
floorLowerToLowestCeiling,
|
floorLowerToLowestCeiling,
|
||||||
floorLoweruint8xture,
|
floorLowerByTexture,
|
||||||
floorLowerToCeiling,
|
floorLowerToCeiling,
|
||||||
|
|
||||||
donutRaise,
|
donutRaise,
|
||||||
|
@ -669,8 +669,8 @@ class Ceiling : Thinker native
|
||||||
ceilLowerToNearest,
|
ceilLowerToNearest,
|
||||||
ceilRaiseToHighestFloor,
|
ceilRaiseToHighestFloor,
|
||||||
ceilRaiseToFloor,
|
ceilRaiseToFloor,
|
||||||
ceilRaiseuint8xture,
|
ceilRaiseByTexture,
|
||||||
ceilLoweruint8xture,
|
ceilLowerByTexture,
|
||||||
|
|
||||||
genCeilingChg0,
|
genCeilingChg0,
|
||||||
genCeilingChgT,
|
genCeilingChgT,
|
||||||
|
|
|
@ -2,12 +2,12 @@
|
||||||
|
|
||||||
extend class Object
|
extend class Object
|
||||||
{
|
{
|
||||||
deprecated static int GameType() // deprecated for 2.4.x
|
deprecated("2.4") static int GameType()
|
||||||
{
|
{
|
||||||
return gameinfo.gametype;
|
return gameinfo.gametype;
|
||||||
}
|
}
|
||||||
|
|
||||||
deprecated static void C_MidPrint(string fontname, string textlabel, bool bold = false) // deprecated for 2.4.x
|
deprecated("2.4") static void C_MidPrint(string fontname, string textlabel, bool bold = false)
|
||||||
{
|
{
|
||||||
let f = Font.GetFont(fontname);
|
let f = Font.GetFont(fontname);
|
||||||
if (f == null) return;
|
if (f == null) return;
|
||||||
|
@ -18,7 +18,7 @@ extend class Object
|
||||||
|
|
||||||
extend class Actor
|
extend class Actor
|
||||||
{
|
{
|
||||||
deprecated void A_CustomMissile(class<Actor> missiletype, double spawnheight = 32, double spawnofs_xy = 0, double angle = 0, int flags = 0, double pitch = 0, int ptr = AAPTR_TARGET)
|
deprecated("2.3") void A_CustomMissile(class<Actor> missiletype, double spawnheight = 32, double spawnofs_xy = 0, double angle = 0, int flags = 0, double pitch = 0, int ptr = AAPTR_TARGET)
|
||||||
{
|
{
|
||||||
A_SpawnProjectile(missiletype, spawnheight, spawnofs_xy, angle, flags|CMF_BADPITCH, pitch, ptr);
|
A_SpawnProjectile(missiletype, spawnheight, spawnofs_xy, angle, flags|CMF_BADPITCH, pitch, ptr);
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ extend class Actor
|
||||||
|
|
||||||
extend class StateProvider
|
extend class StateProvider
|
||||||
{
|
{
|
||||||
deprecated action void A_FireCustomMissile(class<Actor> missiletype, double angle = 0, bool useammo = true, double spawnofs_xy = 0, double spawnheight = 0, int flags = 0, double pitch = 0)
|
deprecated("2.3") action void A_FireCustomMissile(class<Actor> missiletype, double angle = 0, bool useammo = true, double spawnofs_xy = 0, double spawnheight = 0, int flags = 0, double pitch = 0)
|
||||||
{
|
{
|
||||||
A_FireProjectile(missiletype, angle, useammo, spawnofs_xy, spawnheight, flags, -pitch);
|
A_FireProjectile(missiletype, angle, useammo, spawnofs_xy, spawnheight, flags, -pitch);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
class BaseEvent native { } // just a base class. it doesn't inherit from Object on the scripting side so you can't call Destroy() on it and break everything.
|
class BaseEvent native version("2.4") { } // just a base class. it doesn't inherit from Object on the scripting side so you can't call Destroy() on it and break everything.
|
||||||
|
|
||||||
class RenderEvent : BaseEvent native ui
|
class RenderEvent : BaseEvent native ui version("2.4")
|
||||||
{
|
{
|
||||||
native readonly Vector3 ViewPos;
|
native readonly Vector3 ViewPos;
|
||||||
native readonly double ViewAngle;
|
native readonly double ViewAngle;
|
||||||
|
@ -10,7 +10,7 @@ class RenderEvent : BaseEvent native ui
|
||||||
native readonly Actor Camera;
|
native readonly Actor Camera;
|
||||||
}
|
}
|
||||||
|
|
||||||
class WorldEvent : BaseEvent native play
|
class WorldEvent : BaseEvent native play version("2.4")
|
||||||
{
|
{
|
||||||
// for loaded/unloaded
|
// for loaded/unloaded
|
||||||
native readonly bool IsSaveGame;
|
native readonly bool IsSaveGame;
|
||||||
|
@ -28,7 +28,7 @@ class WorldEvent : BaseEvent native play
|
||||||
native readonly double DamageAngle;
|
native readonly double DamageAngle;
|
||||||
}
|
}
|
||||||
|
|
||||||
class PlayerEvent : BaseEvent native play
|
class PlayerEvent : BaseEvent native play version("2.4")
|
||||||
{
|
{
|
||||||
// this is the player number that caused the event.
|
// this is the player number that caused the event.
|
||||||
// note: you can get player struct from this by using players[e.PlayerNumber]
|
// note: you can get player struct from this by using players[e.PlayerNumber]
|
||||||
|
@ -37,7 +37,7 @@ class PlayerEvent : BaseEvent native play
|
||||||
native readonly bool IsReturn;
|
native readonly bool IsReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
class UiEvent : BaseEvent native ui
|
class UiEvent : BaseEvent native ui version("2.4")
|
||||||
{
|
{
|
||||||
// d_gui.h
|
// d_gui.h
|
||||||
enum EGUIEvent
|
enum EGUIEvent
|
||||||
|
@ -121,7 +121,7 @@ class UiEvent : BaseEvent native ui
|
||||||
native readonly bool IsAlt;
|
native readonly bool IsAlt;
|
||||||
}
|
}
|
||||||
|
|
||||||
class InputEvent : BaseEvent native play
|
class InputEvent : BaseEvent native play version("2.4")
|
||||||
{
|
{
|
||||||
enum EGenericEvent
|
enum EGenericEvent
|
||||||
{
|
{
|
||||||
|
@ -270,7 +270,7 @@ class InputEvent : BaseEvent native play
|
||||||
native readonly int MouseY;
|
native readonly int MouseY;
|
||||||
}
|
}
|
||||||
|
|
||||||
class ConsoleEvent : BaseEvent native
|
class ConsoleEvent : BaseEvent native version("2.4")
|
||||||
{
|
{
|
||||||
// for net events, this will be the activator.
|
// for net events, this will be the activator.
|
||||||
// for UI events, this is always -1, and you need to check if level is loaded and use players[consoleplayer].
|
// for UI events, this is always -1, and you need to check if level is loaded and use players[consoleplayer].
|
||||||
|
@ -279,16 +279,16 @@ class ConsoleEvent : BaseEvent native
|
||||||
native readonly int Args[3];
|
native readonly int Args[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
class StaticEventHandler : Object native play
|
class StaticEventHandler : Object native play version("2.4")
|
||||||
{
|
{
|
||||||
// static event handlers CAN register other static event handlers.
|
// static event handlers CAN register other static event handlers.
|
||||||
// unlike EventHandler.Create that will not create them.
|
// unlike EventHandler.Create that will not create them.
|
||||||
protected static native StaticEventHandler Create(class<StaticEventHandler> type);
|
clearscope static native StaticEventHandler Create(class<StaticEventHandler> type);
|
||||||
protected static native StaticEventHandler CreateOnce(class<StaticEventHandler> type);
|
clearscope static native StaticEventHandler CreateOnce(class<StaticEventHandler> type);
|
||||||
protected static native StaticEventHandler Find(Class<StaticEventHandler> type); // just for convenience. who knows.
|
clearscope static native StaticEventHandler Find(Class<StaticEventHandler> type); // just for convenience. who knows.
|
||||||
|
|
||||||
protected static native bool Register(StaticEventHandler handler);
|
clearscope static native bool Register(StaticEventHandler handler);
|
||||||
protected static native bool Unregister(StaticEventHandler handler);
|
clearscope static native bool Unregister(StaticEventHandler handler);
|
||||||
|
|
||||||
// these are called when the handler gets registered or unregistered
|
// these are called when the handler gets registered or unregistered
|
||||||
// you can set Order/IsUiProcessor here.
|
// you can set Order/IsUiProcessor here.
|
||||||
|
@ -335,14 +335,14 @@ class StaticEventHandler : Object native play
|
||||||
native bool RequireMouse;
|
native bool RequireMouse;
|
||||||
}
|
}
|
||||||
|
|
||||||
class EventHandler : StaticEventHandler native
|
class EventHandler : StaticEventHandler native version("2.4")
|
||||||
{
|
{
|
||||||
static native StaticEventHandler Create(class<StaticEventHandler> type);
|
clearscope static native StaticEventHandler Create(class<StaticEventHandler> type);
|
||||||
static native StaticEventHandler CreateOnce(class<StaticEventHandler> type);
|
clearscope static native StaticEventHandler CreateOnce(class<StaticEventHandler> type);
|
||||||
static native StaticEventHandler Find(class<StaticEventHandler> type);
|
clearscope static native StaticEventHandler Find(class<StaticEventHandler> type);
|
||||||
|
|
||||||
static native bool Register(StaticEventHandler handler);
|
clearscope static native bool Register(StaticEventHandler handler);
|
||||||
static native bool Unregister(StaticEventHandler handler);
|
clearscope static native bool Unregister(StaticEventHandler handler);
|
||||||
|
|
||||||
clearscope static native void SendNetworkEvent(String name, int arg1 = 0, int arg2 = 0, int arg3 = 0);
|
clearscope static native void SendNetworkEvent(String name, int arg1 = 0, int arg2 = 0, int arg3 = 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -751,7 +751,7 @@ class Inventory : Actor native
|
||||||
virtual bool Use (bool pickup) { return false; }
|
virtual bool Use (bool pickup) { return false; }
|
||||||
virtual double GetSpeedFactor() { return 1; }
|
virtual double GetSpeedFactor() { return 1; }
|
||||||
virtual bool GetNoTeleportFreeze() { return false; }
|
virtual bool GetNoTeleportFreeze() { return false; }
|
||||||
virtual ui void AlterWeaponSprite(VisStyle vis, in out int changed) {}
|
virtual version("2.4") ui void AlterWeaponSprite(VisStyle vis, in out int changed) {}
|
||||||
virtual void OwnerDied() {}
|
virtual void OwnerDied() {}
|
||||||
virtual Color GetBlend () { return 0; }
|
virtual Color GetBlend () { return 0; }
|
||||||
|
|
||||||
|
@ -818,7 +818,7 @@ class Inventory : Actor native
|
||||||
//
|
//
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
virtual ui bool DrawPowerup(int x, int y) { return false; }
|
virtual ui version("2.4") bool DrawPowerup(int x, int y) { return false; }
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
|
|
|
@ -31,10 +31,10 @@ class CustomInventory : StateProvider
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
// This is only here, because these functions were originally exported on Inventory, despite only working for weapons, so this is here to satisfy some potential old mods having called it through CustomInventory.
|
// This is only here, because these functions were originally exported on Inventory, despite only working for weapons, so this is here to satisfy some potential old mods having called it through CustomInventory.
|
||||||
deprecated action void A_GunFlash(statelabel flash = null, int flags = 0) {}
|
deprecated("2.3") action void A_GunFlash(statelabel flash = null, int flags = 0) {}
|
||||||
deprecated action void A_Lower() {}
|
deprecated("2.3") action void A_Lower() {}
|
||||||
deprecated action void A_Raise() {}
|
deprecated("2.3") action void A_Raise() {}
|
||||||
deprecated action void A_CheckReload() {}
|
deprecated("2.3") action void A_CheckReload() {}
|
||||||
native bool CallStateChain (Actor actor, State state);
|
native bool CallStateChain (Actor actor, State state);
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
**
|
**
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct StrifeDialogueNode native
|
struct StrifeDialogueNode native version("2.4")
|
||||||
{
|
{
|
||||||
native Class<Actor> DropType;
|
native Class<Actor> DropType;
|
||||||
native int ThisNodeNum;
|
native int ThisNodeNum;
|
||||||
|
@ -49,7 +49,7 @@ struct StrifeDialogueNode native
|
||||||
}
|
}
|
||||||
|
|
||||||
// FStrifeDialogueReply holds responses the player can give to the NPC
|
// FStrifeDialogueReply holds responses the player can give to the NPC
|
||||||
struct StrifeDialogueReply native
|
struct StrifeDialogueReply native version("2.4")
|
||||||
{
|
{
|
||||||
native StrifeDialogueReply Next;
|
native StrifeDialogueReply Next;
|
||||||
native Class<Actor> GiveType;
|
native Class<Actor> GiveType;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
struct KeyBindings native
|
struct KeyBindings native version("2.4")
|
||||||
{
|
{
|
||||||
native static String NameKeys(int k1, int k2);
|
native static String NameKeys(int k1, int k2);
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ struct KeyBindings native
|
||||||
native void UnbindACommand (String str);
|
native void UnbindACommand (String str);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct OptionValues native
|
struct OptionValues native version("2.4")
|
||||||
{
|
{
|
||||||
native static int GetCount(Name group);
|
native static int GetCount(Name group);
|
||||||
native static String GetText(Name group, int index);
|
native static String GetText(Name group, int index);
|
||||||
|
@ -16,7 +16,7 @@ struct OptionValues native
|
||||||
native static String GetTextValue(Name group, int index);
|
native static String GetTextValue(Name group, int index);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct JoystickConfig native
|
struct JoystickConfig native version("2.4")
|
||||||
{
|
{
|
||||||
enum EJoyAxis
|
enum EJoyAxis
|
||||||
{
|
{
|
||||||
|
@ -48,7 +48,7 @@ struct JoystickConfig native
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class Menu : Object native ui
|
class Menu : Object native ui version("2.4")
|
||||||
{
|
{
|
||||||
enum EMenuKey
|
enum EMenuKey
|
||||||
{
|
{
|
||||||
|
@ -287,7 +287,7 @@ class Menu : Object native ui
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class MenuDescriptor : Object native ui
|
class MenuDescriptor : Object native ui version("2.4")
|
||||||
{
|
{
|
||||||
native Name mMenuName;
|
native Name mMenuName;
|
||||||
native String mNetgameMessage;
|
native String mNetgameMessage;
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
//
|
//
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
class MenuItemBase : Object native ui
|
class MenuItemBase : Object native ui version("2.4")
|
||||||
{
|
{
|
||||||
protected native double mXpos, mYpos;
|
protected native double mXpos, mYpos;
|
||||||
protected native Name mAction;
|
protected native Name mAction;
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
**
|
**
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct FOptionMenuSettings
|
struct FOptionMenuSettings version("2.4")
|
||||||
{
|
{
|
||||||
int mTitleColor;
|
int mTitleColor;
|
||||||
int mFontColor;
|
int mFontColor;
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
// INTERMISSION
|
// INTERMISSION
|
||||||
// Structure passed e.g. to WI_Start(wb)
|
// Structure passed e.g. to WI_Start(wb)
|
||||||
//
|
//
|
||||||
struct WBPlayerStruct native
|
struct WBPlayerStruct native version("2.4")
|
||||||
{
|
{
|
||||||
// Player stats, kills, collected items etc.
|
// Player stats, kills, collected items etc.
|
||||||
native int skills;
|
native int skills;
|
||||||
|
@ -14,7 +14,7 @@ struct WBPlayerStruct native
|
||||||
native int fragcount; // [RH] Cumulative frags for this player
|
native int fragcount; // [RH] Cumulative frags for this player
|
||||||
}
|
}
|
||||||
|
|
||||||
struct WBStartStruct native
|
struct WBStartStruct native version("2.4")
|
||||||
{
|
{
|
||||||
native int finished_ep;
|
native int finished_ep;
|
||||||
native int next_ep;
|
native int next_ep;
|
||||||
|
|
Loading…
Reference in a new issue