Skip to content

Commit

Permalink
Refactor difficulty name translation into new class
Browse files Browse the repository at this point in the history
New class ModDifficultyNames handles looking up mod-specific difficult name
defaults and their translations in the .game file.
  • Loading branch information
Matthew Mott committed Mar 31, 2020
1 parent 41cf59f commit 84cbe47
Showing 1 changed file with 78 additions and 40 deletions.
118 changes: 78 additions & 40 deletions plugins/dm.difficulty/DifficultySettingsManager.cpp
Expand Up @@ -52,7 +52,8 @@ void DifficultySettingsManager::loadDefaultSettings() {
}
}

void DifficultySettingsManager::loadMapSettings() {
void DifficultySettingsManager::loadMapSettings()
{
// Construct a helper walker
DifficultyEntityFinder finder;
GlobalSceneGraph().root()->traverse(finder);
Expand All @@ -69,64 +70,101 @@ void DifficultySettingsManager::loadMapSettings() {
}
}

void DifficultySettingsManager::loadDifficultyNames()
namespace
{
// Locate the worldspawn entity
Entity* worldspawn = map::current::getWorldspawn();

// Try to locate the difficulty menu entity, where the default names are defined
IEntityClassPtr menuEclass = GlobalEntityClassManager().findClass(
game::current::getValue<std::string>(GKEY_DIFFICULTY_ENTITYDEF_MENU)
);
// Class to manage mod-specific difficulty names (which are probably string
// table entries like "#str_000300") and their English translations (we
// maintain these translations separately in the .game file since we don't have
// any support for parsing the mod-specific translation data).
class ModDifficultyNames
{
// Lookup table of strings and their translations
std::map<std::string, std::string> _transStrings;

// Obtain translations for the string table entries from the .game file
xml::NodeList transNodes = game::current::getNodes(
GKEY_DIFFICULTY_ENTITYDEF_MENU + "/string"
);
std::map<std::string, std::string> transStrings;
for (auto xmlNode: transNodes)
// Mod-specific entity giving default difficulty names
IEntityClassPtr _menuEclass;

public:

// Construct and initialise
ModDifficultyNames()
: _menuEclass(
GlobalEntityClassManager().findClass(
game::current::getValue<std::string>(GKEY_DIFFICULTY_ENTITYDEF_MENU)
)
)
{
transStrings[xmlNode.getAttributeValue("id")] = xmlNode.getContent();
// Load translations from xml nodes in the .game file
xml::NodeList transNodes = game::current::getNodes(
GKEY_DIFFICULTY_ENTITYDEF_MENU + "/string"
);
for (auto xmlNode: transNodes)
{
_transStrings[xmlNode.getAttributeValue("id")] = xmlNode.getContent();
}
}

// greebo: Setup the default difficulty levels using the found entityDef
// Return the translated name for a key, such as "diff0Default"
std::string getNameForKey(const std::string& nameKey) const
{
if (_menuEclass)
{
EntityClassAttribute attr = _menuEclass->getAttribute(nameKey);
std::string rawName = attr.getValue();
if (!rawName.empty())
{
// Look for a translation, otherwise use the raw name
auto found = _transStrings.find(rawName);
if (found != _transStrings.end())
return found->second;
else
return rawName;
}
}

return "";
}
};

}

void DifficultySettingsManager::loadDifficultyNames()
{
// Locate the worldspawn entity
Entity* worldspawn = map::current::getWorldspawn();

// Load mod-specific difficulty names if possible
ModDifficultyNames diffNames;

// Look up a name for each difficulty level, starting with a map-specific
// name set on the worldspawn, then falling back to mod default names and
// then autogenerated names.
int numLevels = game::current::getValue<int>(GKEY_DIFFICULTY_LEVELS);
for (int i = 0; i < numLevels; i++)
{
std::string nameKey = "diff" + std::to_string(i) + "default";

// First, try to find a map-specific name
if (worldspawn != NULL) {
if (worldspawn)
{
std::string name = worldspawn->getKeyValue(nameKey);
if (!name.empty()) {
if (!name.empty())
{
// Found a setting on worldspawn, take it
_difficultyNames.push_back(name);
continue; // done for this level
}
}

// If the above failed, try to load the default setting, which we will
// need to translate from a string table entry into English.
if (menuEclass)
{
EntityClassAttribute attr = menuEclass->getAttribute(nameKey);
std::string rawName = attr.getValue();
if (!rawName.empty())
{
// Look for a translation, otherwise use the raw name
auto found = transStrings.find(rawName);
if (found != transStrings.end())
_difficultyNames.push_back(found->second);
else
_difficultyNames.push_back(rawName);

// Finished for this difficulty level
continue;
}
}

// Fall back to a non-empty default
_difficultyNames.push_back(std::to_string(i));
// If there is no map-specific name, use a mod default
std::string defaultName = diffNames.getNameForKey(nameKey);
if (!defaultName.empty())
// Use the (hopefully translated) mod-specific default name
_difficultyNames.push_back(defaultName);
else
// Fall back to a non-empty default
_difficultyNames.push_back(std::to_string(i));
}
}

Expand Down

0 comments on commit 84cbe47

Please sign in to comment.