mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-10 14:51:51 +00:00
- decoupled the string table from game implementation details.
Using callbacks now to query needed game state.
This commit is contained in:
parent
c3a381ed92
commit
b3c7b81893
6 changed files with 94 additions and 40 deletions
|
@ -2539,6 +2539,7 @@ static const char *DoomButtons[] =
|
||||||
"moveup" };
|
"moveup" };
|
||||||
|
|
||||||
CVAR(Bool, lookspring, true, CVAR_ARCHIVE); // Generate centerview when -mlook encountered?
|
CVAR(Bool, lookspring, true, CVAR_ARCHIVE); // Generate centerview when -mlook encountered?
|
||||||
|
EXTERN_CVAR(String, language)
|
||||||
|
|
||||||
void Mlook_ReleaseHandler()
|
void Mlook_ReleaseHandler()
|
||||||
{
|
{
|
||||||
|
@ -2548,6 +2549,17 @@ void Mlook_ReleaseHandler()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int StrTable_GetGender()
|
||||||
|
{
|
||||||
|
return players[consoleplayer].userinfo.GetGender();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StrTable_ValidFilter(const char* str)
|
||||||
|
{
|
||||||
|
if (gameinfo.gametype == GAME_Strife && (gameinfo.flags & GI_SHAREWARE) && !stricmp(str, "strifeteaser")) return true;
|
||||||
|
return stricmp(str, GameNames[gameinfo.gametype]) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// D_DoomMain
|
// D_DoomMain
|
||||||
|
@ -2570,7 +2582,12 @@ static int D_DoomMain_Internal (void)
|
||||||
buttonMap.GetButton(Button_Mlook)->bReleaseLock = true;
|
buttonMap.GetButton(Button_Mlook)->bReleaseLock = true;
|
||||||
buttonMap.GetButton(Button_Klook)->bReleaseLock = true;
|
buttonMap.GetButton(Button_Klook)->bReleaseLock = true;
|
||||||
|
|
||||||
// button != &Button_Mlook && button != &Button_Klook)
|
static StringtableCallbacks stblcb =
|
||||||
|
{
|
||||||
|
StrTable_ValidFilter,
|
||||||
|
StrTable_GetGender
|
||||||
|
};
|
||||||
|
GStrings.SetCallbacks(&stblcb);
|
||||||
|
|
||||||
std::set_new_handler(NewFailure);
|
std::set_new_handler(NewFailure);
|
||||||
const char *batchout = Args->CheckValue("-errorlog");
|
const char *batchout = Args->CheckValue("-errorlog");
|
||||||
|
@ -2778,7 +2795,7 @@ static int D_DoomMain_Internal (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
// [RH] Initialize localizable strings.
|
// [RH] Initialize localizable strings.
|
||||||
GStrings.LoadStrings ();
|
GStrings.LoadStrings (language);
|
||||||
|
|
||||||
V_InitFontColors ();
|
V_InitFontColors ();
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,6 @@
|
||||||
int SaveVersion;
|
int SaveVersion;
|
||||||
|
|
||||||
// Localizable strings
|
// Localizable strings
|
||||||
FStringTable GStrings;
|
|
||||||
|
|
||||||
// Game speed
|
// Game speed
|
||||||
EGameSpeed GameSpeed = SPEED_Normal;
|
EGameSpeed GameSpeed = SPEED_Normal;
|
||||||
|
|
|
@ -201,7 +201,7 @@ CUSTOM_CVAR(Bool, ui_generic, false, CVAR_NOINITCALL) // This is for allowing to
|
||||||
|
|
||||||
CUSTOM_CVAR(String, language, "auto", CVAR_ARCHIVE | CVAR_NOINITCALL | CVAR_GLOBALCONFIG)
|
CUSTOM_CVAR(String, language, "auto", CVAR_ARCHIVE | CVAR_NOINITCALL | CVAR_GLOBALCONFIG)
|
||||||
{
|
{
|
||||||
GStrings.UpdateLanguage();
|
GStrings.UpdateLanguage(self);
|
||||||
for (auto Level : AllLevels())
|
for (auto Level : AllLevels())
|
||||||
{
|
{
|
||||||
// does this even make sense on secondary levels...?
|
// does this even make sense on secondary levels...?
|
||||||
|
|
|
@ -3079,7 +3079,7 @@ void FinishDehPatch ()
|
||||||
StateMap.Reset();
|
StateMap.Reset();
|
||||||
TouchedActors.Reset();
|
TouchedActors.Reset();
|
||||||
EnglishStrings.Clear();
|
EnglishStrings.Clear();
|
||||||
GStrings.SetDehackedStrings(std::move(DehStrings));
|
GStrings.SetOverrideStrings(std::move(DehStrings));
|
||||||
|
|
||||||
// Now it gets nasty: We have to fiddle around with the weapons' ammo use info to make Doom's original
|
// Now it gets nasty: We have to fiddle around with the weapons' ammo use info to make Doom's original
|
||||||
// ammo consumption work as intended.
|
// ammo consumption work as intended.
|
||||||
|
|
|
@ -37,14 +37,11 @@
|
||||||
#include "stringtable.h"
|
#include "stringtable.h"
|
||||||
#include "cmdlib.h"
|
#include "cmdlib.h"
|
||||||
#include "filesystem.h"
|
#include "filesystem.h"
|
||||||
#include "i_system.h"
|
|
||||||
#include "sc_man.h"
|
#include "sc_man.h"
|
||||||
#include "c_dispatch.h"
|
#include "c_dispatch.h"
|
||||||
#include "v_text.h"
|
#include "v_text.h"
|
||||||
#include "gi.h"
|
#include "c_cvars.h"
|
||||||
#include "d_player.h"
|
#include "printf.h"
|
||||||
|
|
||||||
EXTERN_CVAR(String, language)
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
@ -52,7 +49,7 @@ EXTERN_CVAR(String, language)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void FStringTable::LoadStrings ()
|
void FStringTable::LoadStrings (const char *language)
|
||||||
{
|
{
|
||||||
int lastlump, lump;
|
int lastlump, lump;
|
||||||
|
|
||||||
|
@ -70,7 +67,7 @@ void FStringTable::LoadStrings ()
|
||||||
if (!ParseLanguageCSV(lump, lumpdata))
|
if (!ParseLanguageCSV(lump, lumpdata))
|
||||||
LoadLanguage (lump, lumpdata);
|
LoadLanguage (lump, lumpdata);
|
||||||
}
|
}
|
||||||
UpdateLanguage();
|
UpdateLanguage(language);
|
||||||
allMacros.Clear();
|
allMacros.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,7 +169,7 @@ bool FStringTable::readMacros(int lumpnum)
|
||||||
auto language = data[i][1];
|
auto language = data[i][1];
|
||||||
if (macroname.IsEmpty() || language.IsEmpty()) continue;
|
if (macroname.IsEmpty() || language.IsEmpty()) continue;
|
||||||
FStringf combined_name("%s/%s", language.GetChars(), macroname.GetChars());
|
FStringf combined_name("%s/%s", language.GetChars(), macroname.GetChars());
|
||||||
FName name = combined_name;
|
FName name = combined_name.GetChars();
|
||||||
|
|
||||||
StringMacro macro;
|
StringMacro macro;
|
||||||
|
|
||||||
|
@ -240,12 +237,26 @@ bool FStringTable::ParseLanguageCSV(int lumpnum, const TArray<uint8_t> &buffer)
|
||||||
if (filtercol > -1)
|
if (filtercol > -1)
|
||||||
{
|
{
|
||||||
auto filterstr = row[filtercol];
|
auto filterstr = row[filtercol];
|
||||||
|
if (filterstr.IsNotEmpty())
|
||||||
|
{
|
||||||
|
bool ok = false;
|
||||||
|
if (callbacks && callbacks->ValidFilter)
|
||||||
|
{
|
||||||
auto filter = filterstr.Split(" ", FString::TOK_SKIPEMPTY);
|
auto filter = filterstr.Split(" ", FString::TOK_SKIPEMPTY);
|
||||||
if (filter.Size() > 0 && filter.FindEx([](const auto &str) { return str.CompareNoCase(GameNames[gameinfo.gametype]) == 0; }) == filter.Size())
|
for (auto& entry : filter)
|
||||||
continue;
|
{
|
||||||
|
if (callbacks->ValidFilter(entry))
|
||||||
|
{
|
||||||
|
ok = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!ok) continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FName strName = row[labelcol];
|
FName strName = row[labelcol].GetChars();
|
||||||
if (hasDefaultEntry)
|
if (hasDefaultEntry)
|
||||||
{
|
{
|
||||||
DeleteForLabel(lumpnum, strName);
|
DeleteForLabel(lumpnum, strName);
|
||||||
|
@ -348,14 +359,7 @@ void FStringTable::LoadLanguage (int lumpnum, const TArray<uint8_t> &buffer)
|
||||||
sc.MustGetStringName("ifgame");
|
sc.MustGetStringName("ifgame");
|
||||||
sc.MustGetStringName("(");
|
sc.MustGetStringName("(");
|
||||||
sc.MustGetString();
|
sc.MustGetString();
|
||||||
if (sc.Compare("strifeteaser"))
|
skip |= (!callbacks || !callbacks->ValidFilter || !callbacks->ValidFilter(sc.String));
|
||||||
{
|
|
||||||
skip |= (gameinfo.gametype != GAME_Strife) || !(gameinfo.flags & GI_SHAREWARE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
skip |= !sc.Compare(GameTypeName());
|
|
||||||
}
|
|
||||||
sc.MustGetStringName(")");
|
sc.MustGetStringName(")");
|
||||||
sc.MustGetString();
|
sc.MustGetString();
|
||||||
|
|
||||||
|
@ -445,11 +449,11 @@ void FStringTable::InsertString(int lumpnum, int langid, FName label, const FStr
|
||||||
FString macroname(te.strings[0].GetChars() + index + 2, endindex - index - 2);
|
FString macroname(te.strings[0].GetChars() + index + 2, endindex - index - 2);
|
||||||
FStringf lookupstr("%s/%s", strlangid, macroname.GetChars());
|
FStringf lookupstr("%s/%s", strlangid, macroname.GetChars());
|
||||||
FStringf replacee("@[%s]", macroname.GetChars());
|
FStringf replacee("@[%s]", macroname.GetChars());
|
||||||
FName lookupname(lookupstr, true);
|
FName lookupname(lookupstr.GetChars(), true);
|
||||||
auto replace = allMacros.CheckKey(lookupname);
|
auto replace = allMacros.CheckKey(lookupname);
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
const char *replacement = replace && replace->Replacements[i] ? replace->Replacements[i] : "";
|
const char *replacement = replace && replace->Replacements[i] ? replace->Replacements[i].GetChars() : "";
|
||||||
te.strings[i].Substitute(replacee, replacement);
|
te.strings[i].Substitute(replacee, replacement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -462,8 +466,10 @@ void FStringTable::InsertString(int lumpnum, int langid, FName label, const FStr
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void FStringTable::UpdateLanguage()
|
void FStringTable::UpdateLanguage(const char *language)
|
||||||
{
|
{
|
||||||
|
if (language) activeLanguage = language;
|
||||||
|
else language = activeLanguage.GetChars();
|
||||||
size_t langlen = strlen(language);
|
size_t langlen = strlen(language);
|
||||||
|
|
||||||
int LanguageID = (langlen < 2 || langlen > 3) ?
|
int LanguageID = (langlen < 2 || langlen > 3) ?
|
||||||
|
@ -479,7 +485,7 @@ void FStringTable::UpdateLanguage()
|
||||||
currentLanguageSet.Push(std::make_pair(lang_id, list));
|
currentLanguageSet.Push(std::make_pair(lang_id, list));
|
||||||
};
|
};
|
||||||
|
|
||||||
checkone(dehacked_table);
|
checkone(override_table);
|
||||||
checkone(global_table);
|
checkone(global_table);
|
||||||
checkone(LanguageID);
|
checkone(LanguageID);
|
||||||
checkone(LanguageID & MAKE_ID(0xff, 0xff, 0, 0));
|
checkone(LanguageID & MAKE_ID(0xff, 0xff, 0, 0));
|
||||||
|
@ -534,7 +540,7 @@ bool FStringTable::exists(const char *name)
|
||||||
FName nm(name, true);
|
FName nm(name, true);
|
||||||
if (nm != NAME_None)
|
if (nm != NAME_None)
|
||||||
{
|
{
|
||||||
uint32_t defaultStrings[] = { default_table, global_table, dehacked_table };
|
uint32_t defaultStrings[] = { default_table, global_table, override_table };
|
||||||
|
|
||||||
for (auto mapid : defaultStrings)
|
for (auto mapid : defaultStrings)
|
||||||
{
|
{
|
||||||
|
@ -561,7 +567,7 @@ const char *FStringTable::GetString(const char *name, uint32_t *langtable, int g
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (gender == -1) gender = players[consoleplayer].userinfo.GetGender();
|
if (gender == -1 && callbacks && callbacks->GetPlayerGender) gender = callbacks->GetPlayerGender();
|
||||||
if (gender < 0 || gender > 3) gender = 0;
|
if (gender < 0 || gender > 3) gender = 0;
|
||||||
FName nm(name, true);
|
FName nm(name, true);
|
||||||
if (nm != NAME_None)
|
if (nm != NAME_None)
|
||||||
|
@ -591,7 +597,7 @@ const char *FStringTable::GetLanguageString(const char *name, uint32_t langtable
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (gender == -1) gender = players[consoleplayer].userinfo.GetGender();
|
if (gender == -1 && callbacks && callbacks->GetPlayerGender) gender = callbacks->GetPlayerGender();
|
||||||
if (gender < 0 || gender > 3) gender = 0;
|
if (gender < 0 || gender > 3) gender = 0;
|
||||||
FName nm(name, true);
|
FName nm(name, true);
|
||||||
if (nm != NAME_None)
|
if (nm != NAME_None)
|
||||||
|
@ -657,3 +663,5 @@ const char *StringMap::MatchString (const char *string) const
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FStringTable GStrings;
|
||||||
|
|
|
@ -44,8 +44,18 @@
|
||||||
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "doomdef.h"
|
#include "basics.h"
|
||||||
#include "doomtype.h"
|
#include "zstring.h"
|
||||||
|
#include "tarray.h"
|
||||||
|
#include "name.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct StringtableCallbacks
|
||||||
|
{
|
||||||
|
// These two functions would create a dependency on the game code so they are installed as callbacks.
|
||||||
|
bool (*ValidFilter)(const char* str);
|
||||||
|
int (*GetPlayerGender)();
|
||||||
|
};
|
||||||
|
|
||||||
struct TableElement
|
struct TableElement
|
||||||
{
|
{
|
||||||
|
@ -74,19 +84,19 @@ public:
|
||||||
{
|
{
|
||||||
default_table = MAKE_ID('*', '*', 0, 0),
|
default_table = MAKE_ID('*', '*', 0, 0),
|
||||||
global_table = MAKE_ID('*', 0, 0, 0),
|
global_table = MAKE_ID('*', 0, 0, 0),
|
||||||
dehacked_table = MAKE_ID('*', '*', '*', 0)
|
override_table = MAKE_ID('*', '*', '*', 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
using LangMap = TMap<uint32_t, StringMap>;
|
using LangMap = TMap<uint32_t, StringMap>;
|
||||||
using StringMacroMap = TMap<FName, StringMacro>;
|
using StringMacroMap = TMap<FName, StringMacro>;
|
||||||
|
|
||||||
void LoadStrings ();
|
void LoadStrings(const char *language);
|
||||||
void UpdateLanguage();
|
void UpdateLanguage(const char* language);
|
||||||
StringMap GetDefaultStrings() { return allStrings[default_table]; } // Dehacked needs these for comparison
|
StringMap GetDefaultStrings() { return allStrings[default_table]; } // Dehacked needs these for comparison
|
||||||
void SetDehackedStrings(StringMap && map)
|
void SetOverrideStrings(StringMap && map)
|
||||||
{
|
{
|
||||||
allStrings.Insert(dehacked_table, map);
|
allStrings.Insert(override_table, map);
|
||||||
UpdateLanguage();
|
UpdateLanguage(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *GetLanguageString(const char *name, uint32_t langtable, int gender = -1) const;
|
const char *GetLanguageString(const char *name, uint32_t langtable, int gender = -1) const;
|
||||||
|
@ -98,12 +108,15 @@ public:
|
||||||
return GetString(name, nullptr);
|
return GetString(name, nullptr);
|
||||||
}
|
}
|
||||||
bool exists(const char *name);
|
bool exists(const char *name);
|
||||||
|
void SetCallbacks(StringtableCallbacks* cb) { callbacks = cb; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
FString activeLanguage;
|
||||||
StringMacroMap allMacros;
|
StringMacroMap allMacros;
|
||||||
LangMap allStrings;
|
LangMap allStrings;
|
||||||
TArray<std::pair<uint32_t, StringMap*>> currentLanguageSet;
|
TArray<std::pair<uint32_t, StringMap*>> currentLanguageSet;
|
||||||
|
StringtableCallbacks* callbacks = nullptr;
|
||||||
|
|
||||||
void LoadLanguage (int lumpnum, const TArray<uint8_t> &buffer);
|
void LoadLanguage (int lumpnum, const TArray<uint8_t> &buffer);
|
||||||
TArray<TArray<FString>> parseCSV(const TArray<uint8_t> &buffer);
|
TArray<TArray<FString>> parseCSV(const TArray<uint8_t> &buffer);
|
||||||
|
@ -116,6 +129,23 @@ private:
|
||||||
void DeleteForLabel(int lumpnum, FName label);
|
void DeleteForLabel(int lumpnum, FName label);
|
||||||
|
|
||||||
static size_t ProcessEscapes (char *str);
|
static size_t ProcessEscapes (char *str);
|
||||||
|
public:
|
||||||
|
static FString MakeMacro(const char *str)
|
||||||
|
{
|
||||||
|
if (*str == '$') return str;
|
||||||
|
return FString("$") + str;
|
||||||
|
}
|
||||||
|
|
||||||
|
static FString MakeMacro(const char *str, size_t len)
|
||||||
|
{
|
||||||
|
if (*str == '$') return FString(str, len);
|
||||||
|
return "$" + FString(str, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* localize(const char* str)
|
||||||
|
{
|
||||||
|
return *str == '$' ? operator()(str + 1) : str;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //__STRINGTABLE_H__
|
#endif //__STRINGTABLE_H__
|
||||||
|
|
Loading…
Reference in a new issue