From f0c9b1765e8473b801f3fd8605aa3068a5c39a9c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 9 Nov 2023 17:22:46 +0100 Subject: [PATCH] gave translations a dedicated scripted type. This is needed for implementing reliable serialization of custom translations. As long as they are merely ints they cannot be restored on loading a savegame because the serialization code does not know that these variables are special. --- src/common/engine/namedef.h | 2 + src/common/engine/palettecontainer.h | 40 +++++ src/common/engine/sc_man_scanner.re | 2 +- src/common/engine/serializer.cpp | 15 ++ src/common/engine/serializer.h | 2 + src/common/scripting/backend/codegen.cpp | 155 +++++++++++++++++- src/common/scripting/backend/codegen.h | 14 ++ src/common/scripting/core/types.cpp | 45 +++++ src/common/scripting/core/types.h | 10 ++ src/common/scripting/frontend/zcc_compile.cpp | 6 + src/common/scripting/interface/vmnatives.cpp | 35 ++++ src/r_data/r_translate.cpp | 7 - wadsrc/static/zscript/actors/actor.zs | 4 +- wadsrc/static/zscript/actors/player/player.zs | 2 +- wadsrc/static/zscript/doombase.zs | 11 +- wadsrc/static/zscript/engine/base.zs | 9 +- wadsrc/static/zscript/engine/screenjob.zs | 10 +- .../static/zscript/ui/menu/playerdisplay.zs | 4 +- .../static/zscript/ui/statusbar/statusbar.zs | 2 +- 19 files changed, 341 insertions(+), 34 deletions(-) diff --git a/src/common/engine/namedef.h b/src/common/engine/namedef.h index 70080a965..e76186f21 100644 --- a/src/common/engine/namedef.h +++ b/src/common/engine/namedef.h @@ -182,6 +182,7 @@ xx(Voidptr) xx(StateLabel) xx(SpriteID) xx(TextureID) +xx(TranslationID) xx(Overlay) xx(IsValid) xx(IsNull) @@ -272,6 +273,7 @@ xx(BuiltinFRandom) xx(BuiltinNameToClass) xx(BuiltinClassCast) xx(BuiltinFunctionPtrCast) +xx(BuiltinFindTranslation) xx(ScreenJobRunner) xx(Action) diff --git a/src/common/engine/palettecontainer.h b/src/common/engine/palettecontainer.h index a761ae33c..96413fe1f 100644 --- a/src/common/engine/palettecontainer.h +++ b/src/common/engine/palettecontainer.h @@ -42,6 +42,46 @@ struct FRemapTable private: }; + +struct FTranslationID +{ +public: + FTranslationID() = default; + +private: + constexpr FTranslationID(int id) : ID(id) + { + } +public: + static constexpr FTranslationID fromInt(int i) + { + return FTranslationID(i); + } + FTranslationID(const FTranslationID& other) = default; + FTranslationID& operator=(const FTranslationID& other) = default; + bool operator !=(FTranslationID other) const + { + return ID != other.ID; + } + bool operator ==(FTranslationID other) const + { + return ID == other.ID; + } + bool operator ==(int other) const = delete; + bool operator !=(int other) const = delete; + constexpr int index() const + { + return ID; + } + constexpr bool isvalid() const + { + return ID > 0; + } +private: + + int ID; +}; + // A class that initializes unusued pointers to NULL. This is used so that when // the TAutoGrowArray below is expanded, the new elements will be NULLed. class FRemapTablePtr diff --git a/src/common/engine/sc_man_scanner.re b/src/common/engine/sc_man_scanner.re index 8bca2ccc6..5af7e62f9 100644 --- a/src/common/engine/sc_man_scanner.re +++ b/src/common/engine/sc_man_scanner.re @@ -167,7 +167,7 @@ std2: 'vector2' { RET(TK_Vector2); } 'vector3' { RET(TK_Vector3); } 'map' { RET(TK_Map); } - 'mapiterator' { RET(TK_MapIterator); } + 'mapiterator' { RET(ParseVersion >= MakeVersion(4, 10, 0)? TK_MapIterator : TK_Identifier); } 'array' { RET(TK_Array); } 'function' { RET(ParseVersion >= MakeVersion(4, 12, 0)? TK_FunctionType : TK_Identifier); } 'in' { RET(TK_In); } diff --git a/src/common/engine/serializer.cpp b/src/common/engine/serializer.cpp index 34fd6956b..71a0031b6 100644 --- a/src/common/engine/serializer.cpp +++ b/src/common/engine/serializer.cpp @@ -1196,6 +1196,21 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FTextureID &value, FTe return arc; } +//========================================================================== +// +// +// +//========================================================================== + +FSerializer& Serialize(FSerializer& arc, const char* key, FTranslationID& value, FTranslationID* defval) +{ + int v = value.index(); + int* defv = (int*)defval; + Serialize(arc, key, v, defv); + value = FTranslationID::fromInt(v); + return arc; +} + //========================================================================== // // This never uses defval and instead uses 'null' as default diff --git a/src/common/engine/serializer.h b/src/common/engine/serializer.h index 9328f2f22..ec1d10949 100644 --- a/src/common/engine/serializer.h +++ b/src/common/engine/serializer.h @@ -20,6 +20,7 @@ class FSoundID; union FRenderStyle; class DObject; class FTextureID; +struct FTranslationID; inline bool nullcmp(const void *buffer, size_t length) { @@ -240,6 +241,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FSoundID &sid, FSoundI FSerializer &Serialize(FSerializer &arc, const char *key, FString &sid, FString *def); FSerializer &Serialize(FSerializer &arc, const char *key, NumericValue &sid, NumericValue *def); FSerializer &Serialize(FSerializer &arc, const char *key, struct ModelOverride &sid, struct ModelOverride *def); +FSerializer& Serialize(FSerializer& arc, const char* key, FTranslationID& value, FTranslationID* defval); void SerializeFunctionPointer(FSerializer &arc, const char *key, FunctionPointerValue *&p); diff --git a/src/common/scripting/backend/codegen.cpp b/src/common/scripting/backend/codegen.cpp index 3ff45c335..7f3a410ca 100644 --- a/src/common/scripting/backend/codegen.cpp +++ b/src/common/scripting/backend/codegen.cpp @@ -43,11 +43,13 @@ #include "texturemanager.h" #include "m_random.h" #include "v_font.h" +#include "palettecontainer.h" extern FRandom pr_exrandom; FMemArena FxAlloc(65536); CompileEnvironment compileEnvironment; +int R_FindCustomTranslation(FName name); struct FLOP { @@ -161,6 +163,12 @@ void FCompileContext::CheckReturn(PPrototype *proto, FScriptPosition &pos) PType* expected = ReturnProto->ReturnTypes[i]; PType* actual = proto->ReturnTypes[i]; if (swapped) std::swap(expected, actual); + // this must pass for older ZScripts. + if (Version < MakeVersion(4, 12, 0)) + { + if (expected == TypeTranslationID) expected = TypeSInt32; + if (actual == TypeTranslationID) actual = TypeSInt32; + } if (expected != actual && !AreCompatiblePointerTypes(expected, actual)) { // Incompatible @@ -993,6 +1001,19 @@ FxExpression *FxIntCast::Resolve(FCompileContext &ctx) if (basex->ValueType->GetRegType() == REGT_INT) { + if (basex->ValueType == TypeTranslationID) + { + // translation IDs must be entirely incompatible with ints, not even allowing an explicit conversion, + // but since the type was only introduced in version 4.12, older ZScript versions must allow this conversion. + if (ctx.Version < MakeVersion(4, 12, 0)) + { + FxExpression* x = basex; + x->ValueType = ValueType; + basex = nullptr; + delete this; + return x; + } + } if (basex->ValueType->isNumeric() || Explicit) // names can be converted to int, but only with an explicit type cast. { FxExpression *x = basex; @@ -1006,7 +1027,7 @@ FxExpression *FxIntCast::Resolve(FCompileContext &ctx) // Ugh. This should abort, but too many mods fell into this logic hole somewhere, so this serious error needs to be reduced to a warning. :( // At least in ZScript, MSG_OPTERROR always means to report an error, not a warning so the problem only exists in DECORATE. if (!basex->isConstant()) - ScriptPosition.Message(MSG_OPTERROR, "Numeric type expected, got a name"); + ScriptPosition.Message(MSG_OPTERROR, "Numeric type expected, got a %s", basex->ValueType->DescriptiveName()); else ScriptPosition.Message(MSG_OPTERROR, "Numeric type expected, got \"%s\"", static_cast(basex)->GetValue().GetName().GetChars()); FxExpression * x = new FxConstant(0, ScriptPosition); delete this; @@ -1127,7 +1148,8 @@ FxExpression *FxFloatCast::Resolve(FCompileContext &ctx) { // Ugh. This should abort, but too many mods fell into this logic hole somewhere, so this seroious error needs to be reduced to a warning. :( // At least in ZScript, MSG_OPTERROR always means to report an error, not a warning so the problem only exists in DECORATE. - if (!basex->isConstant()) ScriptPosition.Message(MSG_OPTERROR, "Numeric type expected, got a name"); + if (!basex->isConstant()) + ScriptPosition.Message(MSG_OPTERROR, "Numeric type expected, got a %s", basex->ValueType->DescriptiveName()); else ScriptPosition.Message(MSG_OPTERROR, "Numeric type expected, got \"%s\"", static_cast(basex)->GetValue().GetName().GetChars()); FxExpression *x = new FxConstant(0.0, ScriptPosition); delete this; @@ -1534,6 +1556,107 @@ ExpEmit FxSoundCast::Emit(VMFunctionBuilder *build) return to; } +//========================================================================== +// +// +// +//========================================================================== + +FxTranslationCast::FxTranslationCast(FxExpression* x) + : FxExpression(EFX_TranslationCast, x->ScriptPosition) +{ + basex = x; + ValueType = TypeTranslationID; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxTranslationCast::~FxTranslationCast() +{ + SAFE_DELETE(basex); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression* FxTranslationCast::Resolve(FCompileContext& ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(basex, ctx); + + if (basex->ValueType->isInt()) + { + // 0 is a valid constant for translations, meaning 'no translation at all'. note that this conversion ONLY allows a constant! + if (basex->isConstant() && static_cast(basex)->GetValue().GetInt() == 0) + { + FxExpression* x = basex; + x->ValueType = TypeTranslationID; + basex = nullptr; + delete this; + return x; + } + if (ctx.Version < MakeVersion(4, 12, 0)) + { + // only allow this conversion as a fallback + FxExpression* x = basex; + x->ValueType = TypeTranslationID; + basex = nullptr; + delete this; + return x; + } + } + else if (basex->ValueType == TypeString || basex->ValueType == TypeName) + { + if (basex->isConstant()) + { + ExpVal constval = static_cast(basex)->GetValue(); + FxExpression* x = new FxConstant(R_FindCustomTranslation(constval.GetName()), ScriptPosition); + x->ValueType = TypeTranslationID; + delete this; + return x; + } + else if (basex->ValueType == TypeString) + { + basex = new FxNameCast(basex, true); + basex = basex->Resolve(ctx); + } + return this; + } + ScriptPosition.Message(MSG_ERROR, "Cannot convert to translation ID"); + delete this; + return nullptr; +} + +//========================================================================== +// +// +// +//========================================================================== + +ExpEmit FxTranslationCast::Emit(VMFunctionBuilder* build) +{ + ExpEmit to(build, REGT_POINTER); + + VMFunction* callfunc; + auto sym = FindBuiltinFunction(NAME_BuiltinFindTranslation); + + assert(sym); + callfunc = sym->Variants[0].Implementation; + + FunctionCallEmitter emitters(callfunc); + emitters.AddParameter(build, basex); + emitters.AddReturn(REGT_INT); + return emitters.EmitCall(build); +} + + //========================================================================== // // @@ -1766,6 +1889,14 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx) delete this; return x; } + else if (ValueType == TypeTranslationID) + { + FxExpression* x = new FxTranslationCast(basex); + x = x->Resolve(ctx); + basex = nullptr; + delete this; + return x; + } else if (ValueType == TypeColor) { FxExpression *x = new FxColorCast(basex); @@ -4639,6 +4770,7 @@ ExpEmit FxConcat::Emit(VMFunctionBuilder *build) else if (left->ValueType == TypeColor) cast = CAST_Co2S; else if (left->ValueType == TypeSpriteID) cast = CAST_SID2S; else if (left->ValueType == TypeTextureID) cast = CAST_TID2S; + else if (left->ValueType == TypeTranslationID) cast = CAST_U2S; else if (op1.RegType == REGT_POINTER) cast = CAST_P2S; else if (op1.RegType == REGT_INT) cast = CAST_I2S; else assert(false && "Bad type for string concatenation"); @@ -4672,6 +4804,7 @@ ExpEmit FxConcat::Emit(VMFunctionBuilder *build) else if (right->ValueType == TypeColor) cast = CAST_Co2S; else if (right->ValueType == TypeSpriteID) cast = CAST_SID2S; else if (right->ValueType == TypeTextureID) cast = CAST_TID2S; + else if (right->ValueType == TypeTranslationID) cast = CAST_U2S; else if (op2.RegType == REGT_POINTER) cast = CAST_P2S; else if (op2.RegType == REGT_INT) cast = CAST_I2S; else assert(false && "Bad type for string concatenation"); @@ -5143,11 +5276,24 @@ FxExpression *FxConditional::Resolve(FCompileContext& ctx) ValueType = truex->ValueType; else if (falsex->IsPointer() && truex->ValueType == TypeNullPtr) ValueType = falsex->ValueType; + // translation IDs need a bit of glue for compatibility and the 0 literal. + else if (truex->IsInteger() && falsex->ValueType == TypeTranslationID) + { + truex = new FxTranslationCast(truex); + truex = truex->Resolve(ctx); + ValueType = ctx.Version < MakeVersion(4, 12, 0)? TypeSInt32 : TypeTranslationID; + } + else if (falsex->IsInteger() && truex->ValueType == TypeTranslationID) + { + falsex = new FxTranslationCast(falsex); + falsex = falsex->Resolve(ctx); + ValueType = ctx.Version < MakeVersion(4, 12, 0) ? TypeSInt32 : TypeTranslationID; + } + else ValueType = TypeVoid; - //else if (truex->ValueType != falsex->ValueType) - if (ValueType->GetRegType() == REGT_NIL) + if (truex == nullptr || falsex == nullptr || ValueType->GetRegType() == REGT_NIL) { ScriptPosition.Message(MSG_ERROR, "Incompatible types for ?: operator"); delete this; @@ -8279,6 +8425,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) MethodName == NAME_Name ? TypeName : MethodName == NAME_SpriteID ? TypeSpriteID : MethodName == NAME_TextureID ? TypeTextureID : + MethodName == NAME_TranslationID ? TypeTranslationID : MethodName == NAME_State ? TypeState : MethodName == NAME_Color ? TypeColor : (PType*)TypeSound; diff --git a/src/common/scripting/backend/codegen.h b/src/common/scripting/backend/codegen.h index 6aff3b75d..e1ad37856 100644 --- a/src/common/scripting/backend/codegen.h +++ b/src/common/scripting/backend/codegen.h @@ -232,6 +232,7 @@ enum EFxType EFX_StringCast, EFX_ColorCast, EFX_SoundCast, + EFX_TranslationCast, EFX_TypeCast, EFX_PlusSign, EFX_MinusSign, @@ -715,6 +716,19 @@ public: ExpEmit Emit(VMFunctionBuilder *build); }; +class FxTranslationCast : public FxExpression +{ + FxExpression* basex; + +public: + + FxTranslationCast(FxExpression* x); + ~FxTranslationCast(); + FxExpression* Resolve(FCompileContext&); + + ExpEmit Emit(VMFunctionBuilder* build); +}; + class FxFontCast : public FxExpression { FxExpression *basex; diff --git a/src/common/scripting/core/types.cpp b/src/common/scripting/core/types.cpp index efe4dfec5..b9949a5ea 100644 --- a/src/common/scripting/core/types.cpp +++ b/src/common/scripting/core/types.cpp @@ -41,6 +41,7 @@ #include "printf.h" #include "textureid.h" #include "maps.h" +#include "palettecontainer.h" FTypeTable TypeTable; @@ -58,6 +59,7 @@ PName *TypeName; PSound *TypeSound; PColor *TypeColor; PTextureID *TypeTextureID; +PTranslationID* TypeTranslationID; PSpriteID *TypeSpriteID; PStatePointer *TypeState; PPointer *TypeFont; @@ -322,6 +324,7 @@ void PType::StaticInit() TypeTable.AddType(TypeNullPtr = new PPointer, NAME_Pointer); TypeTable.AddType(TypeSpriteID = new PSpriteID, NAME_SpriteID); TypeTable.AddType(TypeTextureID = new PTextureID, NAME_TextureID); + TypeTable.AddType(TypeTranslationID = new PTranslationID, NAME_TranslationID); TypeVoidPtr = NewPointer(TypeVoid, false); TypeRawFunction = new PPointer; @@ -1321,6 +1324,48 @@ bool PTextureID::ReadValue(FSerializer &ar, const char *key, void *addr) const return true; } +/* PTranslationID ******************************************************************/ + +//========================================================================== +// +// PTranslationID Default Constructor +// +//========================================================================== + +PTranslationID::PTranslationID() + : PInt(sizeof(FTranslationID), true, false) +{ + mDescriptiveName = "TranslationID"; + Flags |= TYPE_IntNotInt; + static_assert(sizeof(FTranslationID) == alignof(FTranslationID), "TranslationID not properly aligned"); +} + +//========================================================================== +// +// PTranslationID :: WriteValue +// +//========================================================================== + +void PTranslationID::WriteValue(FSerializer& ar, const char* key, const void* addr) const +{ + FTranslationID val = *(FTranslationID*)addr; + ar(key, val); +} + +//========================================================================== +// +// PTranslationID :: ReadValue +// +//========================================================================== + +bool PTranslationID::ReadValue(FSerializer& ar, const char* key, void* addr) const +{ + FTranslationID val; + ar(key, val); + *(FTranslationID*)addr = val; + return true; +} + /* PSound *****************************************************************/ //========================================================================== diff --git a/src/common/scripting/core/types.h b/src/common/scripting/core/types.h index e24bcd38b..e892a8b12 100644 --- a/src/common/scripting/core/types.h +++ b/src/common/scripting/core/types.h @@ -383,6 +383,15 @@ public: bool ReadValue(FSerializer &ar, const char *key, void *addr) const override; }; +class PTranslationID : public PInt +{ +public: + PTranslationID(); + + void WriteValue(FSerializer& ar, const char* key, const void* addr) const override; + bool ReadValue(FSerializer& ar, const char* key, void* addr) const override; +}; + class PColor : public PInt { public: @@ -712,6 +721,7 @@ extern PName *TypeName; extern PSound *TypeSound; extern PColor *TypeColor; extern PTextureID *TypeTextureID; +extern PTranslationID* TypeTranslationID; extern PSpriteID *TypeSpriteID; extern PStruct* TypeVector2; extern PStruct* TypeVector3; diff --git a/src/common/scripting/frontend/zcc_compile.cpp b/src/common/scripting/frontend/zcc_compile.cpp index c29a580a3..d7a1a54b7 100644 --- a/src/common/scripting/frontend/zcc_compile.cpp +++ b/src/common/scripting/frontend/zcc_compile.cpp @@ -1886,6 +1886,12 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n retval = TypeTextureID; break; + case NAME_TranslationID: + retval = TypeTranslationID; + break; + + + default: retval = ResolveUserType(btype, btype->UserType, outertype ? &outertype->Symbols : nullptr, false); break; diff --git a/src/common/scripting/interface/vmnatives.cpp b/src/common/scripting/interface/vmnatives.cpp index 5ab3051d4..6242d556b 100644 --- a/src/common/scripting/interface/vmnatives.cpp +++ b/src/common/scripting/interface/vmnatives.cpp @@ -1372,3 +1372,38 @@ DEFINE_ACTION_FUNCTION_NATIVE(DObject, FindFunction, FindFunctionPointer) ACTION_RETURN_POINTER(FindFunctionPointer(cls, fn.GetIndex())); } +int R_FindCustomTranslation(FName name); + +static int ZFindTranslation(int intname) +{ + return R_FindCustomTranslation(ENamedName(intname)); +} + +static int MakeTransID(int g, int s) +{ + return TRANSLATION(g, s); +} + +DEFINE_ACTION_FUNCTION_NATIVE(_Translation, GetID, ZFindTranslation) +{ + PARAM_PROLOGUE; + PARAM_INT(t); + ACTION_RETURN_INT(ZFindTranslation(t)); +} + +// same as above for the compiler which needs a class to look this up. +DEFINE_ACTION_FUNCTION_NATIVE(DObject, BuiltinFindTranslation, ZFindTranslation) +{ + PARAM_PROLOGUE; + PARAM_INT(t); + ACTION_RETURN_INT(ZFindTranslation(t)); +} + +DEFINE_ACTION_FUNCTION_NATIVE(_Translation, MakeID, MakeTransID) +{ + PARAM_PROLOGUE; + PARAM_INT(g); + PARAM_INT(t); + ACTION_RETURN_INT(MakeTransID(g, t)); +} + diff --git a/src/r_data/r_translate.cpp b/src/r_data/r_translate.cpp index c2b34f005..ca2b34fbe 100644 --- a/src/r_data/r_translate.cpp +++ b/src/r_data/r_translate.cpp @@ -666,13 +666,6 @@ int R_FindCustomTranslation(FName name) return (t != nullptr)? *t : -1; } -DEFINE_ACTION_FUNCTION(_Translation, GetID) -{ - PARAM_PROLOGUE; - PARAM_NAME(t); - ACTION_RETURN_INT(R_FindCustomTranslation(t)); -} - //---------------------------------------------------------------------------- // // diff --git a/wadsrc/static/zscript/actors/actor.zs b/wadsrc/static/zscript/actors/actor.zs index 52085804c..04a5ecdd4 100644 --- a/wadsrc/static/zscript/actors/actor.zs +++ b/wadsrc/static/zscript/actors/actor.zs @@ -218,7 +218,7 @@ class Actor : Thinker native native Inventory Inv; native uint8 smokecounter; native uint8 FriendPlayer; - native uint Translation; + native TranslationID Translation; native sound AttackSound; native sound DeathSound; native sound SeeSound; @@ -253,7 +253,7 @@ class Actor : Thinker native native double StealthAlpha; native int WoundHealth; // Health needed to enter wound state native readonly color BloodColor; - native readonly int BloodTranslation; + native readonly TranslationID BloodTranslation; native int RenderHidden; native int RenderRequired; native int FriendlySeeBlocks; diff --git a/wadsrc/static/zscript/actors/player/player.zs b/wadsrc/static/zscript/actors/player/player.zs index aca1c4bca..807835ebb 100644 --- a/wadsrc/static/zscript/actors/player/player.zs +++ b/wadsrc/static/zscript/actors/player/player.zs @@ -2667,7 +2667,7 @@ class PSprite : Object native play native Bool firstTic; native bool InterpolateTic; native int Tics; - native uint Translation; + native TranslationID Translation; native bool bAddWeapon; native bool bAddBob; native bool bPowDouble; diff --git a/wadsrc/static/zscript/doombase.zs b/wadsrc/static/zscript/doombase.zs index f6c8dcb00..8bdc59b54 100644 --- a/wadsrc/static/zscript/doombase.zs +++ b/wadsrc/static/zscript/doombase.zs @@ -51,25 +51,21 @@ extend struct Console extend struct Translation { - Color colors[256]; - - native int AddTranslation(); native static bool SetPlayerTranslation(int group, int num, int plrnum, PlayerClass pclass); - native static int GetID(Name transname); } // This is needed because Actor contains a field named 'translation' which shadows the above. struct Translate version("4.5") { - static int MakeID(int group, int num) + static TranslationID MakeID(int group, int num) { - return (group << 16) + num; + return Translation.MakeID(group, num); } static bool SetPlayerTranslation(int group, int num, int plrnum, PlayerClass pclass) { return Translation.SetPlayerTranslation(group, num, plrnum, pclass); } - static int GetID(Name transname) + static TranslationID GetID(Name transname) { return Translation.GetID(transname); } @@ -115,6 +111,7 @@ extend struct GameInfoStruct extend class Object { private native static Object BuiltinNewDoom(Class cls, int outerclass, int compatibility); + private native static TranslationID BuiltinFindTranslation(Name nm); private native static int BuiltinCallLineSpecial(int special, Actor activator, int arg1, int arg2, int arg3, int arg4, int arg5); // These really should be global functions... native static String G_SkillName(); diff --git a/wadsrc/static/zscript/engine/base.zs b/wadsrc/static/zscript/engine/base.zs index 2644dc197..ada5fbaaf 100644 --- a/wadsrc/static/zscript/engine/base.zs +++ b/wadsrc/static/zscript/engine/base.zs @@ -919,10 +919,11 @@ struct StringStruct native struct Translation version("2.4") { - static int MakeID(int group, int num) - { - return (group << 16) + num; - } + Color colors[256]; + + native TranslationID AddTranslation(); + native static TranslationID MakeID(int group, int num); + native static TranslationID GetID(Name transname); } // Convenient way to attach functions to Quat diff --git a/wadsrc/static/zscript/engine/screenjob.zs b/wadsrc/static/zscript/engine/screenjob.zs index a339def91..dc50f5535 100644 --- a/wadsrc/static/zscript/engine/screenjob.zs +++ b/wadsrc/static/zscript/engine/screenjob.zs @@ -141,12 +141,12 @@ class BlackScreen : ScreenJob class ImageScreen : SkippableScreenJob { int tilenum; - int trans; + TranslationID trans; int waittime; // in ms. bool cleared; TextureID texid; - ScreenJob Init(TextureID tile, int fade = fadein | fadeout, int wait = 3000, int translation = 0) + ScreenJob Init(TextureID tile, int fade = fadein | fadeout, int wait = 3000, TranslationID translation = 0) { Super.Init(fade); waittime = wait; @@ -156,7 +156,7 @@ class ImageScreen : SkippableScreenJob return self; } - ScreenJob InitNamed(String tex, int fade = fadein | fadeout, int wait = 3000, int translation = 0) + ScreenJob InitNamed(String tex, int fade = fadein | fadeout, int wait = 3000, TranslationID translation = 0) { Super.Init(fade); waittime = wait; @@ -166,12 +166,12 @@ class ImageScreen : SkippableScreenJob return self; } - static ScreenJob Create(TextureID tile, int fade = fadein | fadeout, int wait = 3000, int translation = 0) + static ScreenJob Create(TextureID tile, int fade = fadein | fadeout, int wait = 3000, TranslationID translation = 0) { return new("ImageScreen").Init(tile, fade, wait, translation); } - static ScreenJob CreateNamed(String tex, int fade = fadein | fadeout, int wait = 3000, int translation = 0) + static ScreenJob CreateNamed(String tex, int fade = fadein | fadeout, int wait = 3000, TranslationID translation = 0) { return new("ImageScreen").InitNamed(tex, fade, wait, translation); } diff --git a/wadsrc/static/zscript/ui/menu/playerdisplay.zs b/wadsrc/static/zscript/ui/menu/playerdisplay.zs index d77853187..acb2f3b05 100644 --- a/wadsrc/static/zscript/ui/menu/playerdisplay.zs +++ b/wadsrc/static/zscript/ui/menu/playerdisplay.zs @@ -294,7 +294,7 @@ class ListMenuItemPlayerDisplay : ListMenuItem if (sprite.IsValid()) { - int trans = mTranslate? Translation.MakeID(TRANSLATION_Players, MAXPLAYERS) : 0; + let trans = mTranslate? Translation.MakeID(TRANSLATION_Players, MAXPLAYERS) : 0; let tscale = TexMan.GetScaledSize(sprite); Scale.X *= sx * tscale.X; Scale.Y *= sy * tscale.Y; @@ -357,7 +357,7 @@ class PlayerMenuPlayerDisplay : ListMenuItemPlayerDisplay if (sprite.IsValid()) { - int trans = mTranslate? Translation.MakeID(TRANSLATION_Players, MAXPLAYERS) : 0; + let trans = mTranslate? Translation.MakeID(TRANSLATION_Players, MAXPLAYERS) : 0; let tscale = TexMan.GetScaledSize(sprite); Scale.X *= CleanXfac_1 * tscale.X * 2; Scale.Y *= CleanYfac_1 * tscale.Y * 2; diff --git a/wadsrc/static/zscript/ui/statusbar/statusbar.zs b/wadsrc/static/zscript/ui/statusbar/statusbar.zs index 26d4bf1ad..58f2ecc3a 100644 --- a/wadsrc/static/zscript/ui/statusbar/statusbar.zs +++ b/wadsrc/static/zscript/ui/statusbar/statusbar.zs @@ -755,7 +755,7 @@ class BaseStatusBar : StatusBarCore native // //============================================================================ - int GetTranslation() const + TranslationID GetTranslation() const { if(gameinfo.gametype & GAME_Raven) return Translation.MakeID(TRANSLATION_PlayersExtra, CPlayer.mo.PlayerNumber());