/
DifficultySettingsManager.cpp
187 lines (155 loc) · 6.16 KB
/
DifficultySettingsManager.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
#include "DifficultySettingsManager.h"
#include "ieclass.h"
#include "itextstream.h"
#include "entitylib.h"
#include "gamelib.h"
#include "string/string.h"
#include "registry/registry.h"
#include "DifficultyEntity.h"
#include "DifficultyEntityFinder.h"
namespace difficulty {
DifficultySettingsPtr DifficultySettingsManager::getSettings(int level) {
for (std::size_t i = 0; i < _settings.size(); i++) {
if (_settings[i]->getLevel() == level) {
return _settings[i];
}
}
return DifficultySettingsPtr();
}
void DifficultySettingsManager::loadSettings() {
loadDefaultSettings();
loadMapSettings();
loadDifficultyNames();
}
void DifficultySettingsManager::loadDefaultSettings() {
// Try to lookup the given entityDef
IEntityClassPtr eclass = GlobalEntityClassManager().findClass(
game::current::getValue<std::string>(GKEY_DIFFICULTY_ENTITYDEF_DEFAULT)
);
if (eclass == NULL) {
rError() << "Could not find default difficulty settings entityDef.\n";
return;
}
// 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++) {
// Allocate a new settings object
DifficultySettingsPtr settings(new DifficultySettings(i));
// Parse the settings from the given default settings entityDef
settings->parseFromEntityDef(eclass);
// Store the settings object in the local list
_settings.push_back(settings);
}
}
void DifficultySettingsManager::loadMapSettings() {
// Construct a helper walker
DifficultyEntityFinder finder;
GlobalSceneGraph().root()->traverse(finder);
const DifficultyEntityFinder::EntityList& found = finder.getEntities();
// Pop all entities into each difficulty setting
for (DifficultyEntityFinder::EntityList::const_iterator ent = found.begin();
ent != found.end(); ent++)
{
for (std::size_t i = 0; i < _settings.size(); i++) {
_settings[i]->parseFromMapEntity(*ent);
}
}
}
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 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" + std::to_string(i) + "default";
// First, try to find a map-specific name
if (worldspawn != NULL) {
std::string name = worldspawn->getKeyValue(nameKey);
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));
}
}
void DifficultySettingsManager::saveSettings()
{
// Locates all difficulty entities
DifficultyEntityFinder finder;
GlobalSceneGraph().root()->traverse(finder);
// Copy the list from the finder to a local list
DifficultyEntityFinder::EntityList entities = finder.getEntities();
if (entities.empty())
{
// Create a new difficulty entity
std::string eclassName = game::current::getValue<std::string>(GKEY_DIFFICULTY_ENTITYDEF_MAP);
IEntityClassPtr diffEclass = GlobalEntityClassManager().findClass(eclassName);
if (diffEclass == NULL) {
rError() << "[Diff]: Cannot create difficulty entity!\n";
return;
}
// Create and insert a new entity node into the scenegraph root
IEntityNodePtr entNode = GlobalEntityCreator().createEntity(diffEclass);
GlobalSceneGraph().root()->addChildNode(entNode);
// Add the entity to the list
entities.push_back(&entNode->getEntity());
}
// Clear all difficulty-spawnargs from existing entities
for (DifficultyEntityFinder::EntityList::const_iterator i = entities.begin();
i != entities.end(); i++)
{
// Construct a difficulty entity using the raw Entity* pointer
DifficultyEntity diffEnt(*i);
// Clear the difficulty-related spawnargs from the entity
diffEnt.clear();
}
// Take the first entity
DifficultyEntity diffEnt(*entities.begin());
// Cycle through all settings objects and issue save call
for (std::size_t i = 0; i < _settings.size(); i++) {
_settings[i]->saveToEntity(diffEnt);
}
}
std::string DifficultySettingsManager::getDifficultyName(int level) {
if (level < 0 || level >= static_cast<int>(_difficultyNames.size())) {
return "";
}
return _difficultyNames[level];
}
} // namespace difficulty