- started scriptifying the level intermission screen. This compiles but is not active yet.
- allow treatment as one-character string constants as character constants. This became necessary because name constants already use single quotes and are much harder to repurpose due to a higher degree of ambiguity. - fixed: protected methods in structs were not usable.
This commit is contained in:
parent
ce3c397ec7
commit
1e9ef2b1df
7 changed files with 530 additions and 14 deletions
|
|
@ -58,6 +58,7 @@
|
|||
|
||||
extern FRandom pr_exrandom;
|
||||
FMemArena FxAlloc(65536);
|
||||
int utf8_decode(const char *src, int *size);
|
||||
|
||||
struct FLOP
|
||||
{
|
||||
|
|
@ -304,6 +305,36 @@ static bool AreCompatiblePointerTypes(PType *dest, PType *source, bool forcompar
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static FxExpression *StringConstToChar(FxExpression *basex)
|
||||
{
|
||||
if (!basex->isConstant()) return false;
|
||||
// Allow single character string literals be convertible to integers.
|
||||
// This serves as workaround for not being able to use single quoted literals because those are taken for names.
|
||||
ExpVal constval = static_cast<FxConstant *>(basex)->GetValue();
|
||||
FString str = constval.GetString();
|
||||
if (str.Len() == 1)
|
||||
{
|
||||
return new FxConstant(str[0], basex->ScriptPosition);
|
||||
}
|
||||
else if (str.Len() > 1)
|
||||
{
|
||||
// If the string is UTF-8, allow a single character UTF-8 sequence.
|
||||
int size;
|
||||
int c = utf8_decode(str.GetChars(), &size);
|
||||
if (c >= 0 && size == str.Len())
|
||||
{
|
||||
return new FxConstant(str[0], basex->ScriptPosition);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
|
|
@ -908,6 +939,7 @@ FxExpression *FxIntCast::Resolve(FCompileContext &ctx)
|
|||
{
|
||||
CHECKRESOLVED();
|
||||
SAFE_RESOLVE(basex, ctx);
|
||||
int c;
|
||||
|
||||
if (basex->ValueType->GetRegType() == REGT_INT)
|
||||
{
|
||||
|
|
@ -952,6 +984,17 @@ FxExpression *FxIntCast::Resolve(FCompileContext &ctx)
|
|||
|
||||
return this;
|
||||
}
|
||||
else if (basex->ValueType == TypeString && basex->isConstant())
|
||||
{
|
||||
FxExpression *x = StringConstToChar(basex);
|
||||
if (x)
|
||||
{
|
||||
x->ValueType = ValueType;
|
||||
basex = nullptr;
|
||||
delete this;
|
||||
return x;
|
||||
}
|
||||
}
|
||||
ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
|
||||
delete this;
|
||||
return nullptr;
|
||||
|
|
@ -3302,6 +3345,18 @@ FxExpression *FxCompareRel::Resolve(FCompileContext& ctx)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
FxExpression *x;
|
||||
if (left->IsNumeric() && right->ValueType == TypeString && (x = StringConstToChar(right)))
|
||||
{
|
||||
delete right;
|
||||
right = x;
|
||||
}
|
||||
else if (right->IsNumeric() && left->ValueType == TypeString && (x = StringConstToChar(left)))
|
||||
{
|
||||
delete left;
|
||||
left = x;
|
||||
}
|
||||
|
||||
if (left->ValueType == TypeString || right->ValueType == TypeString)
|
||||
{
|
||||
if (left->ValueType != TypeString)
|
||||
|
|
@ -3528,6 +3583,17 @@ FxExpression *FxCompareEq::Resolve(FCompileContext& ctx)
|
|||
|
||||
if (left->ValueType != right->ValueType) // identical types are always comparable, if they can be placed in a register, so we can save most checks if this is the case.
|
||||
{
|
||||
FxExpression *x;
|
||||
if (left->IsNumeric() && right->ValueType == TypeString && (x = StringConstToChar(right)))
|
||||
{
|
||||
delete right;
|
||||
right = x;
|
||||
}
|
||||
else if (right->IsNumeric() && left->ValueType == TypeString && (x = StringConstToChar(left)))
|
||||
{
|
||||
delete left;
|
||||
left = x;
|
||||
}
|
||||
// Special cases: Compare strings and names with names, sounds, colors, state labels and class types.
|
||||
// These are all types a string can be implicitly cast into, so for convenience, so they should when doing a comparison.
|
||||
if ((left->ValueType == TypeString || left->ValueType == TypeName) &&
|
||||
|
|
|
|||
|
|
@ -206,10 +206,9 @@ 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.
|
||||
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)))
|
||||
else if ((funcsym->Variants[0].Flags & VARF_Protected) && symtable != &funccls->Symbols && (!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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1199,7 +1199,7 @@ DEFINE_ACTION_FUNCTION(_TexMan, GetSize)
|
|||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_INT(texid);
|
||||
auto tex = TexMan[FSetTextureID(texid)];
|
||||
auto tex = TexMan.ByIndex(texid);
|
||||
int x, y;
|
||||
if (tex != nullptr)
|
||||
{
|
||||
|
|
@ -1212,11 +1212,17 @@ DEFINE_ACTION_FUNCTION(_TexMan, GetSize)
|
|||
return MIN(numret, 2);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_TexMan, GetScaledSize)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_INT(texid);
|
||||
auto tex = TexMan[FSetTextureID(texid)];
|
||||
auto tex = TexMan.ByIndex(texid);
|
||||
if (tex != nullptr)
|
||||
{
|
||||
ACTION_RETURN_VEC2(DVector2(tex->GetScaledWidthDouble(), tex->GetScaledHeightDouble()));
|
||||
|
|
@ -1224,6 +1230,24 @@ DEFINE_ACTION_FUNCTION(_TexMan, GetScaledSize)
|
|||
ACTION_RETURN_VEC2(DVector2(-1, -1));
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_TexMan, CheckRealHeight)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_INT(texid);
|
||||
auto tex = TexMan.ByIndex(texid);
|
||||
if (tex != nullptr)
|
||||
{
|
||||
ACTION_RETURN_INT(tex->CheckRealHeight());
|
||||
}
|
||||
ACTION_RETURN_INT(-1);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FTextureID::operator+
|
||||
|
|
|
|||
|
|
@ -648,22 +648,22 @@ private:
|
|||
struct FPatchInfo
|
||||
{
|
||||
FFont *mFont;
|
||||
FTexture *mPatch;
|
||||
FTextureID mPatch;
|
||||
EColorRange mColor;
|
||||
|
||||
void Init(FGIFont &gifont)
|
||||
{
|
||||
if (gifont.color == NAME_Null)
|
||||
{
|
||||
mPatch = TexMan[gifont.fontname]; // "entering"
|
||||
mColor = mPatch == NULL ? CR_UNTRANSLATED : CR_UNDEFINED;
|
||||
mPatch = TexMan.CheckForTexture(gifont.fontname, FTexture::TEX_MiscPatch);
|
||||
mColor = mPatch.isValid() ? CR_UNTRANSLATED : CR_UNDEFINED;
|
||||
mFont = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
mFont = V_GetFont(gifont.fontname);
|
||||
mColor = V_FindFontColor(gifont.color);
|
||||
mPatch = NULL;
|
||||
mPatch.SetNull();
|
||||
}
|
||||
if (mFont == NULL)
|
||||
{
|
||||
|
|
@ -748,7 +748,7 @@ public:
|
|||
FPatchInfo finished;
|
||||
FPatchInfo entering;
|
||||
|
||||
FTextureID Sp_secret; // "secret"
|
||||
FTextureID P_secret; // "secret"
|
||||
FTextureID Kills; // "Kills", "Scrt", "Items", "Frags"
|
||||
FTextureID Secret;
|
||||
FTextureID Items;
|
||||
|
|
@ -851,10 +851,11 @@ public:
|
|||
const char *string = GStrings(stringname);
|
||||
int midx = screen->GetWidth() / 2;
|
||||
|
||||
if (pinfo->mPatch != NULL)
|
||||
if (pinfo->mPatch.isValid())
|
||||
{
|
||||
screen->DrawTexture(pinfo->mPatch, midx - pinfo->mPatch->GetScaledWidth()*CleanXfac/2, y, DTA_CleanNoMove, true, TAG_DONE);
|
||||
return y + (pinfo->mPatch->GetScaledHeight() * CleanYfac);
|
||||
FTexture *tex = TexMan[pinfo->mPatch];
|
||||
screen->DrawTexture(tex, midx - tex->GetScaledWidth()*CleanXfac/2, y, DTA_CleanNoMove, true, TAG_DONE);
|
||||
return y + (tex->GetScaledHeight() * CleanYfac);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1883,7 +1884,7 @@ public:
|
|||
screen->DrawTexture (TexMan[Items], SP_STATSX, SP_STATSY+lh, DTA_Clean, true, TAG_DONE);
|
||||
WI_drawPercent (IntermissionFont, 320 - SP_STATSX, SP_STATSY+lh, cnt_items[0], wbs->maxitems);
|
||||
|
||||
screen->DrawTexture (TexMan[Sp_secret], SP_STATSX, SP_STATSY+2*lh, DTA_Clean, true, TAG_DONE);
|
||||
screen->DrawTexture (TexMan[P_secret], SP_STATSX, SP_STATSY+2*lh, DTA_Clean, true, TAG_DONE);
|
||||
WI_drawPercent (IntermissionFont, 320 - SP_STATSX, SP_STATSY+2*lh, cnt_secret[0], wbs->maxsecret);
|
||||
|
||||
screen->DrawTexture (TexMan[Timepic], SP_TIMEX, SP_TIMEY, DTA_Clean, true, TAG_DONE);
|
||||
|
|
@ -2024,7 +2025,7 @@ public:
|
|||
{
|
||||
Kills = TexMan.CheckForTexture("WIOSTK", FTexture::TEX_MiscPatch); // "kills"
|
||||
Secret = TexMan.CheckForTexture("WIOSTS", FTexture::TEX_MiscPatch); // "scrt"
|
||||
Sp_secret = TexMan.CheckForTexture("WISCRT2", FTexture::TEX_MiscPatch); // "secret"
|
||||
P_secret = TexMan.CheckForTexture("WISCRT2", FTexture::TEX_MiscPatch); // "secret"
|
||||
Items = TexMan.CheckForTexture("WIOSTI", FTexture::TEX_MiscPatch); // "items"
|
||||
Timepic = TexMan.CheckForTexture("WITIME", FTexture::TEX_MiscPatch); // "time"
|
||||
Sucks = TexMan.CheckForTexture("WISUCKS", FTexture::TEX_MiscPatch); // "sucks"
|
||||
|
|
@ -2147,3 +2148,41 @@ DEFINE_FIELD_X(WBStartStruct, wbstartstruct_t, sucktime);
|
|||
DEFINE_FIELD_X(WBStartStruct, wbstartstruct_t, totaltime);
|
||||
DEFINE_FIELD_X(WBStartStruct, wbstartstruct_t, pnum);
|
||||
DEFINE_FIELD_X(WBStartStruct, wbstartstruct_t, plyr);
|
||||
|
||||
DEFINE_FIELD(FIntermissionScreen, acceleratestage);
|
||||
DEFINE_FIELD(FIntermissionScreen, playerready);
|
||||
DEFINE_FIELD(FIntermissionScreen, me);
|
||||
DEFINE_FIELD(FIntermissionScreen, bcnt);
|
||||
DEFINE_FIELD(FIntermissionScreen, state);
|
||||
DEFINE_FIELD(FIntermissionScreen, wbs);
|
||||
DEFINE_FIELD(FIntermissionScreen, Plrs);
|
||||
DEFINE_FIELD(FIntermissionScreen, cnt);
|
||||
DEFINE_FIELD(FIntermissionScreen, cnt_kills);
|
||||
DEFINE_FIELD(FIntermissionScreen, cnt_items);
|
||||
DEFINE_FIELD(FIntermissionScreen, cnt_secret);
|
||||
DEFINE_FIELD(FIntermissionScreen, cnt_frags);
|
||||
DEFINE_FIELD(FIntermissionScreen, cnt_deaths);
|
||||
DEFINE_FIELD(FIntermissionScreen, cnt_time);
|
||||
DEFINE_FIELD(FIntermissionScreen, cnt_total_time);
|
||||
DEFINE_FIELD(FIntermissionScreen, cnt_par);
|
||||
DEFINE_FIELD(FIntermissionScreen, cnt_pause);
|
||||
DEFINE_FIELD(FIntermissionScreen, total_frags);
|
||||
DEFINE_FIELD(FIntermissionScreen, total_deaths);
|
||||
DEFINE_FIELD(FIntermissionScreen, noautostartmap);
|
||||
DEFINE_FIELD(FIntermissionScreen, dofrags);
|
||||
DEFINE_FIELD(FIntermissionScreen, ng_state);
|
||||
DEFINE_FIELD(FIntermissionScreen, shadowalpha);
|
||||
DEFINE_FIELD(FIntermissionScreen, mapname);
|
||||
DEFINE_FIELD(FIntermissionScreen, finished);
|
||||
DEFINE_FIELD(FIntermissionScreen, entering);
|
||||
DEFINE_FIELD(FIntermissionScreen, P_secret);
|
||||
DEFINE_FIELD(FIntermissionScreen, Kills);
|
||||
DEFINE_FIELD(FIntermissionScreen, Secret);
|
||||
DEFINE_FIELD(FIntermissionScreen, Items);
|
||||
DEFINE_FIELD(FIntermissionScreen, Timepic);
|
||||
DEFINE_FIELD(FIntermissionScreen, Par);
|
||||
DEFINE_FIELD(FIntermissionScreen, Sucks);
|
||||
DEFINE_FIELD(FIntermissionScreen, lnametexts);
|
||||
DEFINE_FIELD(FIntermissionScreen, snl_pointeron);
|
||||
DEFINE_FIELD(FIntermissionScreen, player_deaths);
|
||||
DEFINE_FIELD(FIntermissionScreen, sp_state);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue