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.
This commit is contained in:
Christoph Oelckers 2023-11-09 18:48:59 +01:00
parent 91eaa5411a
commit 990cf3eafc
27 changed files with 541 additions and 57 deletions

View file

@ -182,6 +182,7 @@ xx(Voidptr)
xx(StateLabel) xx(StateLabel)
xx(SpriteID) xx(SpriteID)
xx(TextureID) xx(TextureID)
xx(TranslationID)
xx(Overlay) xx(Overlay)
xx(IsValid) xx(IsValid)
xx(IsNull) xx(IsNull)
@ -272,6 +273,7 @@ xx(BuiltinFRandom)
xx(BuiltinNameToClass) xx(BuiltinNameToClass)
xx(BuiltinClassCast) xx(BuiltinClassCast)
xx(BuiltinFunctionPtrCast) xx(BuiltinFunctionPtrCast)
xx(BuiltinFindTranslation)
xx(ScreenJobRunner) xx(ScreenJobRunner)
xx(Action) xx(Action)

View file

@ -820,4 +820,9 @@ bool FRemapTable::AddColors(int start, int count, const uint8_t*colors, int tran
} }
// placeholder
int R_FindCustomTranslation(FName name)
{
return -1;
}

View file

@ -42,6 +42,46 @@ struct FRemapTable
private: 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 // 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. // the TAutoGrowArray below is expanded, the new elements will be NULLed.
class FRemapTablePtr class FRemapTablePtr

View file

@ -167,7 +167,7 @@ std2:
'vector2' { RET(TK_Vector2); } 'vector2' { RET(TK_Vector2); }
'vector3' { RET(TK_Vector3); } 'vector3' { RET(TK_Vector3); }
'map' { RET(TK_Map); } 'map' { RET(TK_Map); }
'mapiterator' { RET(TK_MapIterator); } 'mapiterator' { RET(ParseVersion >= MakeVersion(4, 10, 0)? TK_MapIterator : TK_Identifier); }
'array' { RET(TK_Array); } 'array' { RET(TK_Array); }
'function' { RET(ParseVersion >= MakeVersion(4, 12, 0)? TK_FunctionType : TK_Identifier); } 'function' { RET(ParseVersion >= MakeVersion(4, 12, 0)? TK_FunctionType : TK_Identifier); }
'in' { RET(TK_In); } 'in' { RET(TK_In); }

View file

@ -1196,6 +1196,21 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FTextureID &value, FTe
return arc; 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 // This never uses defval and instead uses 'null' as default

View file

@ -20,6 +20,7 @@ class FSoundID;
union FRenderStyle; union FRenderStyle;
class DObject; class DObject;
class FTextureID; class FTextureID;
struct FTranslationID;
inline bool nullcmp(const void *buffer, size_t length) 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, FString &sid, FString *def);
FSerializer &Serialize(FSerializer &arc, const char *key, NumericValue &sid, NumericValue *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, 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); void SerializeFunctionPointer(FSerializer &arc, const char *key, FunctionPointerValue *&p);

View file

@ -43,11 +43,13 @@
#include "texturemanager.h" #include "texturemanager.h"
#include "m_random.h" #include "m_random.h"
#include "v_font.h" #include "v_font.h"
#include "palettecontainer.h"
extern FRandom pr_exrandom; extern FRandom pr_exrandom;
FMemArena FxAlloc(65536); FMemArena FxAlloc(65536);
CompileEnvironment compileEnvironment; CompileEnvironment compileEnvironment;
int R_FindCustomTranslation(FName name);
struct FLOP struct FLOP
{ {
@ -161,6 +163,12 @@ void FCompileContext::CheckReturn(PPrototype *proto, FScriptPosition &pos)
PType* expected = ReturnProto->ReturnTypes[i]; PType* expected = ReturnProto->ReturnTypes[i];
PType* actual = proto->ReturnTypes[i]; PType* actual = proto->ReturnTypes[i];
if (swapped) std::swap(expected, actual); 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)) if (expected != actual && !AreCompatiblePointerTypes(expected, actual))
{ // Incompatible { // Incompatible
@ -993,6 +1001,19 @@ FxExpression *FxIntCast::Resolve(FCompileContext &ctx)
if (basex->ValueType->GetRegType() == REGT_INT) 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. if (basex->ValueType->isNumeric() || Explicit) // names can be converted to int, but only with an explicit type cast.
{ {
FxExpression *x = basex; 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. :( // 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. // 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()) 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<FxConstant*>(basex)->GetValue().GetName().GetChars()); else ScriptPosition.Message(MSG_OPTERROR, "Numeric type expected, got \"%s\"", static_cast<FxConstant*>(basex)->GetValue().GetName().GetChars());
FxExpression * x = new FxConstant(0, ScriptPosition); FxExpression * x = new FxConstant(0, ScriptPosition);
delete this; 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. :( // 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. // 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<FxConstant*>(basex)->GetValue().GetName().GetChars()); else ScriptPosition.Message(MSG_OPTERROR, "Numeric type expected, got \"%s\"", static_cast<FxConstant*>(basex)->GetValue().GetName().GetChars());
FxExpression *x = new FxConstant(0.0, ScriptPosition); FxExpression *x = new FxConstant(0.0, ScriptPosition);
delete this; delete this;
@ -1534,6 +1556,107 @@ ExpEmit FxSoundCast::Emit(VMFunctionBuilder *build)
return to; 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<FxConstant*>(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<FxConstant*>(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; delete this;
return x; 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) else if (ValueType == TypeColor)
{ {
FxExpression *x = new FxColorCast(basex); 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 == TypeColor) cast = CAST_Co2S;
else if (left->ValueType == TypeSpriteID) cast = CAST_SID2S; else if (left->ValueType == TypeSpriteID) cast = CAST_SID2S;
else if (left->ValueType == TypeTextureID) cast = CAST_TID2S; 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_POINTER) cast = CAST_P2S;
else if (op1.RegType == REGT_INT) cast = CAST_I2S; else if (op1.RegType == REGT_INT) cast = CAST_I2S;
else assert(false && "Bad type for string concatenation"); 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 == TypeColor) cast = CAST_Co2S;
else if (right->ValueType == TypeSpriteID) cast = CAST_SID2S; else if (right->ValueType == TypeSpriteID) cast = CAST_SID2S;
else if (right->ValueType == TypeTextureID) cast = CAST_TID2S; 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_POINTER) cast = CAST_P2S;
else if (op2.RegType == REGT_INT) cast = CAST_I2S; else if (op2.RegType == REGT_INT) cast = CAST_I2S;
else assert(false && "Bad type for string concatenation"); else assert(false && "Bad type for string concatenation");
@ -5143,11 +5276,24 @@ FxExpression *FxConditional::Resolve(FCompileContext& ctx)
ValueType = truex->ValueType; ValueType = truex->ValueType;
else if (falsex->IsPointer() && truex->ValueType == TypeNullPtr) else if (falsex->IsPointer() && truex->ValueType == TypeNullPtr)
ValueType = falsex->ValueType; 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 else
ValueType = TypeVoid; 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"); ScriptPosition.Message(MSG_ERROR, "Incompatible types for ?: operator");
delete this; delete this;
@ -8279,6 +8425,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx)
MethodName == NAME_Name ? TypeName : MethodName == NAME_Name ? TypeName :
MethodName == NAME_SpriteID ? TypeSpriteID : MethodName == NAME_SpriteID ? TypeSpriteID :
MethodName == NAME_TextureID ? TypeTextureID : MethodName == NAME_TextureID ? TypeTextureID :
MethodName == NAME_TranslationID ? TypeTranslationID :
MethodName == NAME_State ? TypeState : MethodName == NAME_State ? TypeState :
MethodName == NAME_Color ? TypeColor : (PType*)TypeSound; MethodName == NAME_Color ? TypeColor : (PType*)TypeSound;

View file

@ -232,6 +232,7 @@ enum EFxType
EFX_StringCast, EFX_StringCast,
EFX_ColorCast, EFX_ColorCast,
EFX_SoundCast, EFX_SoundCast,
EFX_TranslationCast,
EFX_TypeCast, EFX_TypeCast,
EFX_PlusSign, EFX_PlusSign,
EFX_MinusSign, EFX_MinusSign,
@ -715,6 +716,19 @@ public:
ExpEmit Emit(VMFunctionBuilder *build); 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 class FxFontCast : public FxExpression
{ {
FxExpression *basex; FxExpression *basex;

View file

@ -41,6 +41,7 @@
#include "printf.h" #include "printf.h"
#include "textureid.h" #include "textureid.h"
#include "maps.h" #include "maps.h"
#include "palettecontainer.h"
FTypeTable TypeTable; FTypeTable TypeTable;
@ -58,6 +59,7 @@ PName *TypeName;
PSound *TypeSound; PSound *TypeSound;
PColor *TypeColor; PColor *TypeColor;
PTextureID *TypeTextureID; PTextureID *TypeTextureID;
PTranslationID* TypeTranslationID;
PSpriteID *TypeSpriteID; PSpriteID *TypeSpriteID;
PStatePointer *TypeState; PStatePointer *TypeState;
PPointer *TypeFont; PPointer *TypeFont;
@ -322,6 +324,7 @@ void PType::StaticInit()
TypeTable.AddType(TypeNullPtr = new PPointer, NAME_Pointer); TypeTable.AddType(TypeNullPtr = new PPointer, NAME_Pointer);
TypeTable.AddType(TypeSpriteID = new PSpriteID, NAME_SpriteID); TypeTable.AddType(TypeSpriteID = new PSpriteID, NAME_SpriteID);
TypeTable.AddType(TypeTextureID = new PTextureID, NAME_TextureID); TypeTable.AddType(TypeTextureID = new PTextureID, NAME_TextureID);
TypeTable.AddType(TypeTranslationID = new PTranslationID, NAME_TranslationID);
TypeVoidPtr = NewPointer(TypeVoid, false); TypeVoidPtr = NewPointer(TypeVoid, false);
TypeRawFunction = new PPointer; TypeRawFunction = new PPointer;
@ -1321,6 +1324,48 @@ bool PTextureID::ReadValue(FSerializer &ar, const char *key, void *addr) const
return true; 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 *****************************************************************/ /* PSound *****************************************************************/
//========================================================================== //==========================================================================

View file

@ -383,6 +383,15 @@ public:
bool ReadValue(FSerializer &ar, const char *key, void *addr) const override; 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 class PColor : public PInt
{ {
public: public:
@ -712,6 +721,7 @@ extern PName *TypeName;
extern PSound *TypeSound; extern PSound *TypeSound;
extern PColor *TypeColor; extern PColor *TypeColor;
extern PTextureID *TypeTextureID; extern PTextureID *TypeTextureID;
extern PTranslationID* TypeTranslationID;
extern PSpriteID *TypeSpriteID; extern PSpriteID *TypeSpriteID;
extern PStruct* TypeVector2; extern PStruct* TypeVector2;
extern PStruct* TypeVector3; extern PStruct* TypeVector3;

View file

@ -1886,6 +1886,12 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n
retval = TypeTextureID; retval = TypeTextureID;
break; break;
case NAME_TranslationID:
retval = TypeTranslationID;
break;
default: default:
retval = ResolveUserType(btype, btype->UserType, outertype ? &outertype->Symbols : nullptr, false); retval = ResolveUserType(btype, btype->UserType, outertype ? &outertype->Symbols : nullptr, false);
break; break;

View file

@ -1372,3 +1372,38 @@ DEFINE_ACTION_FUNCTION_NATIVE(DObject, FindFunction, FindFunctionPointer)
ACTION_RETURN_POINTER(FindFunctionPointer(cls, fn.GetIndex())); 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));
}

View file

@ -49,8 +49,8 @@ const char *GetVersionString();
#define RC_PRODUCTVERSION2 VERSIONSTR #define RC_PRODUCTVERSION2 VERSIONSTR
// These are for content versioning. // These are for content versioning.
#define VER_MAJOR 4 #define VER_MAJOR 4
#define VER_MINOR 11 #define VER_MINOR 12
#define VER_REVISION 100 #define VER_REVISION 0
#define ENG_MAJOR 1 #define ENG_MAJOR 1
#define ENG_MINOR 7 #define ENG_MINOR 7

View file

@ -1,10 +1,14 @@
version "4.11.100" version "4.12"
// Generic engine code
#include "zscript/engine/base.zs" #include "zscript/engine/base.zs"
#include "zscript/engine/dynarrays.zs" #include "zscript/engine/dynarrays.zs"
#include "zscript/engine/inputevents.zs" #include "zscript/engine/maps.zs"
#include "zscript/engine/dictionary.zs" #include "zscript/engine/dictionary.zs"
#include "zscript/engine/screenjob.zs" #include "zscript/engine/inputevents.zs"
#include "zscript/engine/service.zs"
#include "zscript/engine/ppshader.zs" #include "zscript/engine/ppshader.zs"
#include "zscript/engine/screenjob.zs"
#include "zscript/engine/ui/menu/colorpickermenu.zs" #include "zscript/engine/ui/menu/colorpickermenu.zs"
#include "zscript/engine/ui/menu/joystickmenu.zs" #include "zscript/engine/ui/menu/joystickmenu.zs"

View file

@ -53,7 +53,7 @@ struct HudStats
int ammoselect; int ammoselect;
Array<String> keyicons; Array<String> keyicons;
Array<int> keytranslations; Array<TranslationID> keytranslations;
Array<String> inventoryicons; Array<String> inventoryicons;
Array<int> inventoryamounts; // negative values can be used for special states (-1: "ON", -2: "OFF", -3: "AUTO") Array<int> inventoryamounts; // negative values can be used for special states (-1: "ON", -2: "OFF", -3: "AUTO")
@ -128,7 +128,7 @@ class AltHud ui
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void DrawImageToBox(TextureID tex, int x, int y, int w, int h, double trans = 0.75, bool animate = false, int translation = 0) void DrawImageToBox(TextureID tex, int x, int y, int w, int h, double trans = 0.75, bool animate = false, TranslationID translation = 0)
{ {
double scale1, scale2; double scale1, scale2;
@ -328,7 +328,7 @@ class AltHud ui
if (icon.isValid()) if (icon.isValid())
{ {
int trans = 0; TranslationID trans = 0;
if (currentStats.keytranslations.Size()) trans = currentStats.keytranslations[keyindex]; if (currentStats.keytranslations.Size()) trans = currentStats.keytranslations[keyindex];
DrawImageToBox(icon, x, y, 8, 10, 0.75, false, trans); DrawImageToBox(icon, x, y, 8, 10, 0.75, false, trans);
return true; return true;

View file

@ -184,6 +184,7 @@ struct Vector3
struct _ native // These are the global variables, the struct is only here to avoid extending the parser for this. struct _ native // These are the global variables, the struct is only here to avoid extending the parser for this.
{ {
native readonly Array<class> AllClasses; native readonly Array<class> AllClasses;
native internal readonly Map<Name , Service> AllServices;
native readonly bool multiplayer; native readonly bool multiplayer;
native @KeyBindings Bindings; native @KeyBindings Bindings;
native @KeyBindings AutomapBindings; native @KeyBindings AutomapBindings;
@ -752,6 +753,7 @@ class Object native
private native static void BuiltinRandomSeed(voidptr rng, int seed); private native static void BuiltinRandomSeed(voidptr rng, int seed);
private native static Class<Object> BuiltinNameToClass(Name nm, Class<Object> filter); private native static Class<Object> BuiltinNameToClass(Name nm, Class<Object> filter);
private native static Object BuiltinClassCast(Object inptr, Class<Object> test); private native static Object BuiltinClassCast(Object inptr, Class<Object> test);
private native static Function<void> BuiltinFunctionPtrCast(Function<void> inptr, voidptr newtype);
native static uint MSTime(); native static uint MSTime();
native static double MSTimeF(); native static double MSTimeF();
@ -922,10 +924,11 @@ struct StringStruct native
struct Translation version("2.4") struct Translation version("2.4")
{ {
static int MakeID(int group, int num) Color colors[256];
{
return (group << 16) + num; //native TranslationID AddTranslation(); // this still needs work.
} native static TranslationID MakeID(int group, int num);
native static TranslationID GetID(Name transname);
} }
// Convenient way to attach functions to Quat // Convenient way to attach functions to Quat

View file

@ -141,12 +141,12 @@ class BlackScreen : ScreenJob
class ImageScreen : SkippableScreenJob class ImageScreen : SkippableScreenJob
{ {
int tilenum; int tilenum;
int trans; TranslationID trans;
int waittime; // in ms. int waittime; // in ms.
bool cleared; bool cleared;
TextureID texid; 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); Super.Init(fade);
waittime = wait; waittime = wait;
@ -156,7 +156,7 @@ class ImageScreen : SkippableScreenJob
return self; 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); Super.Init(fade);
waittime = wait; waittime = wait;
@ -166,12 +166,12 @@ class ImageScreen : SkippableScreenJob
return self; 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); 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); return new("ImageScreen").InitNamed(tex, fade, wait, translation);
} }
@ -622,13 +622,13 @@ class TextOverlay
{ {
int nHeight; int nHeight;
double nCrawlY; double nCrawlY;
int palette; TranslationID palette;
int crange; int crange;
bool drawclean; bool drawclean;
BrokenLines screentext; BrokenLines screentext;
Font myfont; Font myfont;
void Init(String text, int cr = Font.CR_NATIVEPAL, int pal = 0, bool clean = false) void Init(String text, int cr = Font.CR_NATIVEPAL, TranslationID pal = 0, bool clean = false)
{ {
myfont = SmallFont; // todo myfont = SmallFont; // todo
screentext = myfont.BreakLines(StringTable.Localize(text), 320); screentext = myfont.BreakLines(StringTable.Localize(text), 320);

View file

@ -0,0 +1,155 @@
/**
* This is Service interface.
*/
class Service abstract
{
deprecated("4.6.1", "Use GetString() instead") virtual play String Get(String request)
{
return "";
}
deprecated("4.6.1", "Use GetStringUI() instead") virtual ui String UiGet(String request)
{
return "";
}
// Play variants
virtual play String GetString(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null, Name nameArg = '')
{
return "";
}
virtual play int GetInt(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null, Name nameArg = '')
{
return 0;
}
virtual play double GetDouble(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null, Name nameArg = '')
{
return 0.0;
}
virtual play Object GetObject(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null, Name nameArg = '')
{
return null;
}
virtual play Name GetName(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null, Name nameArg = '')
{
return '';
}
// UI variants
virtual ui String GetStringUI(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null, Name nameArg = '')
{
return "";
}
virtual ui int GetIntUI(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null, Name nameArg = '')
{
return 0;
}
virtual ui double GetDoubleUI(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null, Name nameArg = '')
{
return 0.0;
}
virtual ui Object GetObjectUI(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null, Name nameArg = '')
{
return null;
}
virtual ui Name GetNameUI(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null, Name nameArg = '')
{
return '';
}
// data/clearscope variants
virtual clearscope String GetStringData(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null, Name nameArg = '')
{
return "";
}
virtual clearscope int GetIntData(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null, Name nameArg = '')
{
return 0;
}
virtual clearscope double GetDoubleData(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null, Name nameArg = '')
{
return 0.0;
}
virtual clearscope Object GetObjectData(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null, Name nameArg = '')
{
return null;
}
virtual clearscope Name GetNameData(String request, string stringArg = "", int intArg = 0, double doubleArg = 0, Object objectArg = null, Name nameArg = '')
{
return '';
}
static Service Find(class<Service> serviceName){
return AllServices.GetIfExists(serviceName.GetClassName());
}
}
/**
* Use this class to find and iterate over services.
*
* Example usage:
*
* @code
* ServiceIterator i = ServiceIterator.Find("MyService");
*
* Service s;
* while (s = i.Next())
* {
* String request = ...
* String answer = s.Get(request);
* ...
* }
* @endcode
*
* If no services are found, the all calls to Next() will return NULL.
*/
class ServiceIterator
{
/**
* Creates a Service iterator for a service name. It will iterate over all existing Services
* with names that match @a serviceName or have it as a part of their names.
*
* Matching is case-independent.
*
* @param serviceName class name of service to find.
*/
static ServiceIterator Find(String serviceName)
{
let result = new("ServiceIterator");
result.mServiceName = serviceName.MakeLower();
result.it.Init(AllServices);
return result;
}
/**
* Gets the service and advances the iterator.
*
* @returns service instance, or NULL if no more services found.
*/
Service Next()
{
while(it.Next())
{
String cName = it.GetKey();
if(cName.MakeLower().IndexOf(mServiceName) != -1)
return it.GetValue();
}
return null;
}
private MapIterator<Name, Service> it;
private String mServiceName;
}

View file

@ -36,7 +36,7 @@
struct KeyBindings native version("2.4") struct KeyBindings native version("2.4")
{ {
native static String NameKeys(int k1, int k2); native static String NameKeys(int k1, int k2);
native static String NameAllKeys(array<int> list); native static String NameAllKeys(array<int> list, bool colors = true);
native int, int GetKeysForCommand(String cmd); native int, int GetKeysForCommand(String cmd);
native void GetAllKeysForCommand(out array<int> list, String cmd); native void GetAllKeysForCommand(out array<int> list, String cmd);
@ -349,16 +349,16 @@ class Menu : Object native ui version("2.4")
return OptionFont().GetHeight(); return OptionFont().GetHeight();
} }
static int OptionWidth(String s) static int OptionWidth(String s, bool localize = true)
{ {
return OptionFont().StringWidth(s); return OptionFont().StringWidth(s, localize);
} }
static void DrawOptionText(int x, int y, int color, String text, bool grayed = false) static void DrawOptionText(int x, int y, int color, String text, bool grayed = false, bool localize = true)
{ {
String label = Stringtable.Localize(text); String label = localize ? Stringtable.Localize(text) : text;
int overlay = grayed? Color(96,48,0,0) : 0; int overlay = grayed? Color(96,48,0,0) : 0;
screen.DrawText (OptionFont(), color, x, y, text, DTA_CleanNoMove_1, true, DTA_ColorOverlay, overlay); screen.DrawText (OptionFont(), color, x, y, text, DTA_CleanNoMove_1, true, DTA_ColorOverlay, overlay, DTA_Localize, localize);
} }

View file

@ -61,9 +61,9 @@ class OptionMenuItem : MenuItemBase
return x; return x;
} }
protected void drawValue(int indent, int y, int color, String text, bool grayed = false) protected void drawValue(int indent, int y, int color, String text, bool grayed = false, bool localize = true)
{ {
Menu.DrawOptionText(indent + CursorSpace(), y, color, text, grayed); Menu.DrawOptionText(indent + CursorSpace(), y, color, text, grayed, localize);
} }
@ -999,7 +999,7 @@ class OptionMenuFieldBase : OptionMenuItem
{ {
bool grayed = mGrayCheck != null && !mGrayCheck.GetInt(); bool grayed = mGrayCheck != null && !mGrayCheck.GetInt();
drawLabel(indent, y, selected ? OptionMenuSettings.mFontColorSelection : OptionMenuSettings.mFontColor, grayed); drawLabel(indent, y, selected ? OptionMenuSettings.mFontColorSelection : OptionMenuSettings.mFontColor, grayed);
drawValue(indent, y, OptionMenuSettings.mFontColorValue, Represent(), grayed); drawValue(indent, y, OptionMenuSettings.mFontColorValue, Represent(), grayed, false);
return indent; return indent;
} }
@ -1068,7 +1068,7 @@ class OptionMenuItemTextField : OptionMenuFieldBase
{ {
// reposition the text so that the cursor is visible when in entering mode. // reposition the text so that the cursor is visible when in entering mode.
String text = Represent(); String text = Represent();
int tlen = Menu.OptionWidth(text) * CleanXfac_1; int tlen = Menu.OptionWidth(text, false) * CleanXfac_1;
int newindent = screen.GetWidth() - tlen - CursorSpace(); int newindent = screen.GetWidth() - tlen - CursorSpace();
if (newindent < indent) indent = newindent; if (newindent < indent) indent = newindent;
} }

View file

@ -108,13 +108,13 @@ class StatusBarCore native ui
native static String FormatNumber(int number, int minsize = 0, int maxsize = 0, int format = 0, String prefix = ""); native static String FormatNumber(int number, int minsize = 0, int maxsize = 0, int format = 0, String prefix = "");
native double, double, double, double StatusbarToRealCoords(double x, double y=0, double w=0, double h=0); native double, double, double, double StatusbarToRealCoords(double x, double y=0, double w=0, double h=0);
native void DrawTexture(TextureID texture, Vector2 pos, int flags = 0, double Alpha = 1., Vector2 box = (-1, -1), Vector2 scale = (1, 1), ERenderStyle style = STYLE_Translucent, Color col = 0xffffffff, int translation = 0, double clipwidth = -1); native void DrawTexture(TextureID texture, Vector2 pos, int flags = 0, double Alpha = 1., Vector2 box = (-1, -1), Vector2 scale = (1, 1), ERenderStyle style = STYLE_Translucent, Color col = 0xffffffff, TranslationID translation = 0, double clipwidth = -1);
native void DrawImage(String texture, Vector2 pos, int flags = 0, double Alpha = 1., Vector2 box = (-1, -1), Vector2 scale = (1, 1), ERenderStyle style = STYLE_Translucent, Color col = 0xffffffff, int translation = 0, double clipwidth = -1); native void DrawImage(String texture, Vector2 pos, int flags = 0, double Alpha = 1., Vector2 box = (-1, -1), Vector2 scale = (1, 1), ERenderStyle style = STYLE_Translucent, Color col = 0xffffffff, TranslationID translation = 0, double clipwidth = -1);
native void DrawTextureRotated(TextureID texid, Vector2 pos, int flags, double angle, double alpha = 1, Vector2 scale = (1, 1), ERenderStyle style = STYLE_Translucent, Color col = 0xffffffff, int translation = 0); native void DrawTextureRotated(TextureID texid, Vector2 pos, int flags, double angle, double alpha = 1, Vector2 scale = (1, 1), ERenderStyle style = STYLE_Translucent, Color col = 0xffffffff, TranslationID translation = 0);
native void DrawImageRotated(String texid, Vector2 pos, int flags, double angle, double alpha = 1, Vector2 scale = (1, 1), ERenderStyle style = STYLE_Translucent, Color col = 0xffffffff, int translation = 0); native void DrawImageRotated(String texid, Vector2 pos, int flags, double angle, double alpha = 1, Vector2 scale = (1, 1), ERenderStyle style = STYLE_Translucent, Color col = 0xffffffff, TranslationID translation = 0);
native void DrawString(HUDFont font, String string, Vector2 pos, int flags = 0, int translation = Font.CR_UNTRANSLATED, double Alpha = 1., int wrapwidth = -1, int linespacing = 4, Vector2 scale = (1, 1), int pt = 0, ERenderStyle style = STYLE_Translucent); native void DrawString(HUDFont font, String string, Vector2 pos, int flags = 0, int translation = Font.CR_UNTRANSLATED, double Alpha = 1., int wrapwidth = -1, int linespacing = 4, Vector2 scale = (1, 1), TranslationID pt = 0, ERenderStyle style = STYLE_Translucent);
native double, double, double, double TransformRect(double x, double y, double w, double h, int flags = 0); native double, double, double, double TransformRect(double x, double y, double w, double h, int flags = 0);
native void Fill(Color col, double x, double y, double w, double h, int flags = 0); native void Fill(Color col, double x, double y, double w, double h, int flags = 0);
native void SetClipRect(double x, double y, double w, double h, int flags = 0); native void SetClipRect(double x, double y, double w, double h, int flags = 0);

View file

@ -62,7 +62,7 @@ class ListMenuItemBloodTextItem : ListMenuItemTextItem
let gamefont = Raze.PickBigFont(); let gamefont = Raze.PickBigFont();
int xpos = mXpos - gamefont.StringWidth(mText) / 2; int xpos = mXpos - gamefont.StringWidth(mText) / 2;
int cr = generic_ui? Font.CR_GRAY : Font.CR_NATIVEPAL; int cr = generic_ui? Font.CR_GRAY : Font.CR_NATIVEPAL;
int trans = generic_ui? 0 : Translation.MakeID(Translation_Remap, pal); TranslationID trans = generic_ui? 0 : Translation.MakeID(Translation_Remap, pal);
if (selected) shade = 32 - ((MSTime() * 120 / 1000) & 63); if (selected) shade = 32 - ((MSTime() * 120 / 1000) & 63);

View file

@ -232,7 +232,7 @@ class BloodStatusBar : RazeStatusBar
DrawTexture(Blood.PowerUpIcon(power), (x, y + powerYoffs[order]), DI_SCREEN_LEFT_CENTER | DI_ITEM_RELCENTER, scale:(powerScale[order], powerScale[order])); DrawTexture(Blood.PowerUpIcon(power), (x, y + powerYoffs[order]), DI_SCREEN_LEFT_CENTER | DI_ITEM_RELCENTER, scale:(powerScale[order], powerScale[order]));
} }
DrawStatNumber("%d", remainingSeconds, "SBarNumberInv", x + 15, y, 0, remainingSeconds > warningTime ? 0 : Translation.MakeID(Translation_Remap, 2), 0.5, DI_SCREEN_LEFT_CENTER); DrawStatNumber("%d", remainingSeconds, "SBarNumberInv", x + 15, y, 0, remainingSeconds > warningTime ? 0 : 2, 0.5, DI_SCREEN_LEFT_CENTER);
y += 20; y += 20;
} }
} }
@ -452,8 +452,8 @@ class BloodStatusBar : RazeStatusBar
} }
bool meHaveBlueFlag = pPlayer.hasFlag & 1; bool meHaveBlueFlag = pPlayer.hasFlag & 1;
int trans10 = Translation.MakeID(Translation_Remap, 10); let trans10 = Translation.MakeID(Translation_Remap, 10);
int trans2 = Translation.MakeID(Translation_Remap, 2); let trans2 = Translation.MakeID(Translation_Remap, 2);
DrawImage(meHaveBlueFlag ? "FlagHave" : "FlagHaveNot", (0, 75 - 100), DI_SCREEN_RIGHT_CENTER|DI_ITEM_RELCENTER, scale:(0.35, 0.35), translation:trans10); DrawImage(meHaveBlueFlag ? "FlagHave" : "FlagHaveNot", (0, 75 - 100), DI_SCREEN_RIGHT_CENTER|DI_ITEM_RELCENTER, scale:(0.35, 0.35), translation:trans10);
if (gBlueFlagDropped) if (gBlueFlagDropped)
DrawImage("FlagDropped", (305 - 320, 83 - 100), DI_SCREEN_RIGHT_CENTER|DI_ITEM_RELCENTER, translation:trans10); DrawImage("FlagDropped", (305 - 320, 83 - 100), DI_SCREEN_RIGHT_CENTER|DI_ITEM_RELCENTER, translation:trans10);
@ -507,7 +507,7 @@ class BloodStatusBar : RazeStatusBar
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
int DrawStatusBar(BloodPlayer pPlayer, int nPalette) int DrawStatusBar(BloodPlayer pPlayer, TranslationID nPalette)
{ {
int th = texHeight("Statusbar"); int th = texHeight("Statusbar");
BeginStatusBar(false, 320, 200, th); BeginStatusBar(false, 320, 200, th);
@ -583,7 +583,7 @@ class BloodStatusBar : RazeStatusBar
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
int DrawHUD1(BloodPlayer pPlayer, int nPalette) int DrawHUD1(BloodPlayer pPlayer, TranslationID nPalette)
{ {
BeginHUD(1, false, 320, 200); BeginHUD(1, false, 320, 200);
DrawImage("FullHUD", (34, 187 - 200), DI_ITEM_RELCENTER, style:STYLE_Normal, col:0xffc0c0c0, translation:nPalette); DrawImage("FullHUD", (34, 187 - 200), DI_ITEM_RELCENTER, style:STYLE_Normal, col:0xffc0c0c0, translation:nPalette);
@ -726,19 +726,20 @@ class BloodStatusBar : RazeStatusBar
override void UpdateStatusBar(SummaryInfo summary) override void UpdateStatusBar(SummaryInfo summary)
{ {
int nPalette = 0; TranslationID nPalette = 0;
let pPlayer = Blood.GetViewPlayer(); let pPlayer = Blood.GetViewPlayer();
int y = 0; int y = 0;
int nGameType = Blood.getGameType(); int nGameType = Blood.getGameType();
if (nGameType == 3) if (nGameType == 3)
{ {
int pal;
if (pPlayer.teamId & 1) if (pPlayer.teamId & 1)
nPalette = 7; pal = 7;
else else
nPalette = 10; pal = 10;
nPalette = Translation.MakeID(Translation_Remap, nPalette); nPalette = Translation.MakeID(Translation_Remap, pal);
} }
if (hud_size == Hud_Full) if (hud_size == Hud_Full)

View file

@ -168,7 +168,7 @@ class ListMenuItemDukeTextItem : ListMenuItemTextItem
override void Draw(bool selected, ListMenuDescriptor desc) override void Draw(bool selected, ListMenuDescriptor desc)
{ {
let font = Raze.PickBigFont(); let font = Raze.PickBigFont();
int trans = mColorSelected? Translation.MakeID(Translation_Remap, 1) : 0; TranslationID trans = mColorSelected? Translation.MakeID(Translation_Remap, 1) : 0;
Color pe; Color pe;
double scale = (gameinfo.gametype & GAMEFLAG_RRALL) ? 0.4 : 1.; double scale = (gameinfo.gametype & GAMEFLAG_RRALL) ? 0.4 : 1.;
let xpos = 160 - font.StringWidth(mText) * scale * 0.5; let xpos = 160 - font.StringWidth(mText) * scale * 0.5;

View file

@ -55,7 +55,7 @@ class DRealmsScreen : SkippableScreenJob
override void Draw(double smoothratio) override void Draw(double smoothratio)
{ {
let tex = TexMan.CheckForTexture("DREALMS"); let tex = TexMan.CheckForTexture("DREALMS");
int translation = TexMan.UseGamePalette(tex)? Translation.MakeID(Translation_BasePalette, Duke.DREALMSPAL) : 0; TranslationID translation = TexMan.UseGamePalette(tex)? Translation.MakeID(Translation_BasePalette, Duke.DREALMSPAL) : 0;
screen.DrawTexture(tex, true, 0, 0, DTA_FullscreenEx, FSMode_ScaleToFit43, DTA_TranslationIndex, translation, DTA_LegacyRenderStyle, STYLE_Normal); screen.DrawTexture(tex, true, 0, 0, DTA_FullscreenEx, FSMode_ScaleToFit43, DTA_TranslationIndex, translation, DTA_LegacyRenderStyle, STYLE_Normal);
} }
@ -116,11 +116,11 @@ class DukeTitleScreen : SkippableScreenJob
override void Draw(double smoothratio) override void Draw(double smoothratio)
{ {
int clock = (ticks + smoothratio) * 120 / GameTicRate; int clock = (ticks + smoothratio) * 120 / GameTicRate;
int etrans = Translation.MakeID(Translation_BasePalette, Duke.TITLEPAL); TranslationID etrans = Translation.MakeID(Translation_BasePalette, Duke.TITLEPAL);
// Only translate if the image depends on the global palette. // Only translate if the image depends on the global palette.
let tex = TexMan.CheckForTexture("BETASCREEN"); let tex = TexMan.CheckForTexture("BETASCREEN");
int trans = TexMan.UseGamePalette(tex)? etrans : 0; TranslationID trans = TexMan.UseGamePalette(tex)? etrans : 0;
screen.DrawTexture(tex, true, 0, 0, DTA_FullscreenEx, FSMode_ScaleToFit43, DTA_TranslationIndex, trans, DTA_LegacyRenderStyle, STYLE_Normal); screen.DrawTexture(tex, true, 0, 0, DTA_FullscreenEx, FSMode_ScaleToFit43, DTA_TranslationIndex, trans, DTA_LegacyRenderStyle, STYLE_Normal);
double scale = clamp(clock - 120, 0, 60) / 64.; double scale = clamp(clock - 120, 0, 60) / 64.;
@ -251,10 +251,10 @@ class Episode1End1 : SkippableScreenJob
override void Draw(double sr) override void Draw(double sr)
{ {
int etrans = Translation.MakeID(Translation_BasePalette, Duke.ENDINGPAL); TranslationID etrans = Translation.MakeID(Translation_BasePalette, Duke.ENDINGPAL);
let tex = TexMan.CheckForTexture("VICTORY1"); let tex = TexMan.CheckForTexture("VICTORY1");
int trans = TexMan.UseGamePalette(tex)? etrans : 0; TranslationID trans = TexMan.UseGamePalette(tex)? etrans : 0;
screen.DrawTexture(tex, false, 0, 50, DTA_FullscreenScale, FSMode_Fit320x200, DTA_TranslationIndex, trans, DTA_LegacyRenderStyle, STYLE_Normal, DTA_TopLeft, true); screen.DrawTexture(tex, false, 0, 50, DTA_FullscreenScale, FSMode_Fit320x200, DTA_TranslationIndex, trans, DTA_LegacyRenderStyle, STYLE_Normal, DTA_TopLeft, true);
if (bossani.isValid()) if (bossani.isValid())

View file

@ -462,7 +462,7 @@ class Cinema : SkippableScreenJob
TextureID cinematile; TextureID cinematile;
int currentCinemaPalette; int currentCinemaPalette;
int cdtrack; int cdtrack;
int palette; TranslationID palette;
bool done; bool done;
ScreenJob Init(String bgTexture, String text, int pal, int cdtrk) ScreenJob Init(String bgTexture, String text, int pal, int cdtrk)

View file

@ -55,7 +55,7 @@ class SWDRealmsScreen : SkippableScreenJob
override void Draw(double sm) override void Draw(double sm)
{ {
let tex = TexMan.CheckForTexture("THREED_REALMS_PIC", TexMan.Type_Any); let tex = TexMan.CheckForTexture("THREED_REALMS_PIC", TexMan.Type_Any);
int translation = TexMan.UseGamePalette(tex) ? Translation.MakeID(Translation_BasePalette, DREALMSPAL) : 0; TranslationID translation = TexMan.UseGamePalette(tex) ? Translation.MakeID(Translation_BasePalette, DREALMSPAL) : 0;
Screen.DrawTexture(tex, false, 0, 0, DTA_FullscreenEx, FSMode_ScaleToFit43, DTA_TranslationIndex, translation, DTA_LegacyRenderStyle, STYLE_Normal); Screen.DrawTexture(tex, false, 0, 0, DTA_FullscreenEx, FSMode_ScaleToFit43, DTA_TranslationIndex, translation, DTA_LegacyRenderStyle, STYLE_Normal);
} }
} }