diff --git a/src/d_main.cpp b/src/d_main.cpp index 2dbf1273c3..dad2b86d95 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -2439,6 +2439,7 @@ void D_DoomMain (void) if (!batchrun) Printf ("ParseTeamInfo: Load team definitions.\n"); TeamLibrary.ParseTeamInfo (); + R_ParseTrnslate(); PClassActor::StaticInit (); // [GRB] Initialize player class list diff --git a/src/r_data/r_translate.cpp b/src/r_data/r_translate.cpp index c55f69016f..bf93650020 100644 --- a/src/r_data/r_translate.cpp +++ b/src/r_data/r_translate.cpp @@ -609,26 +609,26 @@ void FRemapTable::AddToTranslation(const char *range) // //---------------------------------------------------------------------------- -int FRemapTable::StoreTranslation() +int FRemapTable::StoreTranslation(int slot) { unsigned int i; - for (i = 0; i < translationtables[TRANSLATION_Decorate].Size(); i++) + for (i = 0; i < translationtables[slot].Size(); i++) { - if (*this == *translationtables[TRANSLATION_Decorate][i]) + if (*this == *translationtables[slot][i]) { // A duplicate of this translation already exists - return TRANSLATION(TRANSLATION_Decorate, i); + return TRANSLATION(slot, i); } } - if (translationtables[TRANSLATION_Decorate].Size() >= MAX_DECORATE_TRANSLATIONS) + if (translationtables[slot].Size() >= MAX_DECORATE_TRANSLATIONS) { I_Error("Too many DECORATE translations"); } FRemapTable *newtrans = new FRemapTable; *newtrans = *this; - i = translationtables[TRANSLATION_Decorate].Push(newtrans); - return TRANSLATION(TRANSLATION_Decorate, i); + i = translationtables[slot].Push(newtrans); + return TRANSLATION(slot, i); } @@ -1188,3 +1188,90 @@ void R_GetPlayerTranslation (int color, const FPlayerColorSet *colorset, FPlayer R_CreatePlayerTranslation (h, s, v, colorset, skin, table, NULL, NULL); } + +//---------------------------------------------------------------------------- +// +// +// +//---------------------------------------------------------------------------- +static TMap customTranslationMap; + +int R_FindCustomTranslation(const char *name) +{ + if (name == nullptr) + { + return -1; + } + // Ice is a special case which will remain in its original slot. + if (!stricmp(name, "Ice")) + { + return TRANSLATION(TRANSLATION_Standard, 7); + } + int *t = customTranslationMap.CheckKey(FName(name, true)); + return (t != nullptr)? *t : -1; +} + +//---------------------------------------------------------------------------- +// +// +// +//---------------------------------------------------------------------------- + +void R_ParseTrnslate() +{ + customTranslationMap.Clear(); + translationtables[TRANSLATION_Custom].Clear(); + + int lump; + int lastlump = 0; + while (-1 != (lump = Wads.FindLump("TRNSLATE", &lastlump))) + { + FScanner sc(lump); + while (sc.GetToken()) + { + sc.TokenMustBe(TK_Identifier); + + FName newtrans = sc.String; + FRemapTable *base = nullptr; + if (sc.CheckToken(':')) + { + sc.MustGetAnyToken(); + if (sc.TokenType == TK_IntConst) + { + int max = 6; + if (sc.Number < 0 || sc.Number > max) + { + sc.ScriptError("Translation must be in the range [0,%d]", max); + } + base = translationtables[TRANSLATION_Standard][sc.Number]; + } + else if (sc.TokenType == TK_Identifier) + { + int tnum = R_FindCustomTranslation(sc.String); + if (tnum == -1) + { + sc.ScriptError("Base translation '%s' not found in '%s'", sc.String, newtrans.GetChars()); + } + base = translationtables[GetTranslationType(tnum)][GetTranslationIndex(tnum)]; + } + else + { + // error out. + sc.TokenMustBe(TK_Identifier); + } + } + sc.MustGetToken('='); + FRemapTable NewTranslation; + if (base != nullptr) NewTranslation = *base; + else NewTranslation.MakeIdentity(); + do + { + sc.MustGetToken(TK_StringConst); + NewTranslation.AddToTranslation(sc.String); + } while (sc.CheckToken(',')); + + int trans = NewTranslation.StoreTranslation(TRANSLATION_Custom); + customTranslationMap[newtrans] = trans; + } + } +} diff --git a/src/r_data/r_translate.h b/src/r_data/r_translate.h index a549f07599..4ca2f203fc 100644 --- a/src/r_data/r_translate.h +++ b/src/r_data/r_translate.h @@ -19,6 +19,7 @@ enum TRANSLATION_Decorate, TRANSLATION_Blood, TRANSLATION_RainPillar, + TRANSLATION_Custom, NUM_TRANSLATION_TABLES }; @@ -42,7 +43,7 @@ struct FRemapTable 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 AddToTranslation(const char * range); - int StoreTranslation(); + int StoreTranslation(int slot); BYTE *Remap; // For the software renderer PalEntry *Palette; // The ideal palette this maps to @@ -109,6 +110,9 @@ extern TArray BloodTranslationColors; int CreateBloodTranslation(PalEntry color); +int R_FindCustomTranslation(const char *name); +void R_ParseTrnslate(); + #endif // __R_TRANSLATE_H diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index 927e3e5372..d60cda823b 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -1100,9 +1100,10 @@ DEFINE_PROPERTY(translation, L, Actor) for(int i = 1; i < PROP_PARM_COUNT; i++) { PROP_STRING_PARM(str, i); - if (i== 1 && PROP_PARM_COUNT == 2 && !stricmp(str, "Ice")) + int tnum; + if (i== 1 && PROP_PARM_COUNT == 2 && (tnum = R_FindCustomTranslation(str)) != -1) { - defaults->Translation = TRANSLATION(TRANSLATION_Standard, 7); + defaults->Translation = tnum; return; } else @@ -1110,7 +1111,7 @@ DEFINE_PROPERTY(translation, L, Actor) CurrentTranslation.AddToTranslation(str); } } - defaults->Translation = CurrentTranslation.StoreTranslation (); + defaults->Translation = CurrentTranslation.StoreTranslation (TRANSLATION_Decorate); } }