Skip to content

Commit

Permalink
Show useful difficulty names in the Difficulty editor
Browse files Browse the repository at this point in the history
The default difficulty names are contained within the 'difficultyMenu' entity
def stored inside the mod data itself; however these names are intended to be
translated using the mod-specific translation system, which is not read or
processed by DarkRadiant. Therefore the names actually shown in the GUI were
meaningless string table entries like '#str_03000', rather than the
user-friendly names like 'Easy'.

Rather than try to support the entire mod translation system, which would be a
massive task, a simple string table lookup is performed based on the contents
of additional <string> nodes which have been added to the darkmod.game file.
  • Loading branch information
Matthew Mott committed Mar 2, 2020
1 parent 28358ed commit 2b2c39d
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 14 deletions.
6 changes: 5 additions & 1 deletion install/games/darkmod.game
Expand Up @@ -325,6 +325,10 @@
<defaultSettingsEclass value="atdm:difficulty_settings_default" />
<mapSettingsEclass value="atdm:difficulty_settings" />
<appTypeIgnore value="_IGNORE" />
<difficultyMenuEclass value="difficultyMenu" />
<difficultyMenuEclass value="difficultyMenu">
<string id="#str_03000">Easy</string>
<string id="#str_03004">Medium</string>
<string id="#str_03011">Difficult</string>
</difficultyMenuEclass>
</difficulty>
</game>
12 changes: 10 additions & 2 deletions libs/gamelib.h
Expand Up @@ -11,6 +11,15 @@ namespace game
namespace current
{

/**
* \brief
* Get the node(s) identified by the given path in the current game tree.
*/
inline xml::NodeList getNodes(const std::string& localPath)
{
return GlobalGameManager().currentGame()->getLocalXPath(localPath);
}

/**
* \brief
* Get the value of the current game's tree in the registry and convert it
Expand All @@ -23,8 +32,7 @@ namespace current
template<typename T>
inline T getValue(const std::string& localXPath, T defaultVal = T())
{
xml::NodeList list = GlobalGameManager().currentGame()->getLocalXPath(localXPath);

xml::NodeList list = getNodes(localXPath);
return list.empty() ? defaultVal : string::convert<T>(list[0].getAttributeValue("value"));
}

Expand Down
44 changes: 33 additions & 11 deletions plugins/dm.difficulty/DifficultySettingsManager.cpp
Expand Up @@ -68,19 +68,31 @@ void DifficultySettingsManager::loadMapSettings() {
}
}

void DifficultySettingsManager::loadDifficultyNames() {
void DifficultySettingsManager::loadDifficultyNames()
{
// Locate the worldspawn entity
Entity* worldspawn = Scene_FindEntityByClass("worldspawn");

// Try to locate the difficulty menu entity, where the default names are defined
IEntityClassPtr eclass = GlobalEntityClassManager().findClass(
IEntityClassPtr menuEclass = GlobalEntityClassManager().findClass(
game::current::getValue<std::string>(GKEY_DIFFICULTY_ENTITYDEF_MENU)
);

// 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)
{
transStrings[xmlNode.getAttributeValue("id")] = xmlNode.getContent();
}

// greebo: Setup the default difficulty levels using the found entityDef
int numLevels = game::current::getValue<int>(GKEY_DIFFICULTY_LEVELS);
for (int i = 0; i < numLevels; i++) {
std::string nameKey = "diff" + string::to_string(i) + "default";
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) {
Expand All @@ -92,18 +104,28 @@ void DifficultySettingsManager::loadDifficultyNames() {
}
}

// If the above failed, try to load the default setting
if (eclass != NULL) {
EntityClassAttribute attr = eclass->getAttribute(nameKey);

if (!attr.getValue().empty()) {
_difficultyNames.push_back(attr.getValue());
// 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(string::to_string(i));
_difficultyNames.push_back(std::to_string(i));
}
}

Expand Down

0 comments on commit 2b2c39d

Please sign in to comment.