36#define DEFAULT_ATTRIBUTESDB_FILE "attributes.xml"
37#define DEFAULT_POINTS 30
38#define DEFAULT_MIN_PTS 1
39#define DEFAULT_MAX_PTS 9
57 static std::map<unsigned int, Attribute> attributes;
60 static std::map<std::string, std::string> tags;
63 static std::vector<std::string> attributeLabels;
72 return creationPoints;
77 return attributeMinimum;
82 return attributeMaximum;
87 return attributeLabels;
93 static void fillLabels()
96 attributeLabels.clear();
97 for (
const auto &[
_, attribute] : attributes)
99 if (attribute.modifiable &&
100 (attribute.scope ==
"character" || attribute.scope ==
"being"))
101 attributeLabels.push_back(attribute.name +
":");
108 static int getPlayerInfoIdFromAttrType(std::string attrType)
111 if (attrType ==
"level")
113 else if (attrType ==
"hp")
115 else if (attrType ==
"max-hp")
117 else if (attrType ==
"mp")
119 else if (attrType ==
"max-mp")
121 else if (attrType ==
"exp")
123 else if (attrType ==
"exp-needed")
125 else if (attrType ==
"money")
127 else if (attrType ==
"total-weight")
128 return ::TOTAL_WEIGHT;
129 else if (attrType ==
"max-weight")
131 else if (attrType ==
"skill-points")
132 return ::SKILL_POINTS;
133 else if (attrType ==
"char-points")
134 return ::CHAR_POINTS;
135 else if (attrType ==
"corr-points")
136 return ::CORR_POINTS;
137 else if (attrType ==
"none")
145 auto it = attributes.find(attrId);
146 if (it != attributes.end())
148 return it->second.playerInfoId;
154 static void loadBuiltins()
159 a.name =
_(
"Strength");
161 a.scope =
"character";
164 attributes[a.id] = a;
165 tags.insert(std::make_pair(
"str",
_(
"Strength %+.1f")));
171 a.name =
_(
"Agility");
173 a.scope =
"character";
176 attributes[a.id] = a;
177 tags.insert(std::make_pair(
"agi",
_(
"Agility %+.1f")));
183 a.name =
_(
"Dexterity");
185 a.scope =
"character";
188 attributes[a.id] = a;
189 tags.insert(std::make_pair(
"dex",
_(
"Dexterity %+.1f")));
195 a.name =
_(
"Vitality");
197 a.scope =
"character";
200 attributes[a.id] = a;
201 tags.insert(std::make_pair(
"vit",
_(
"Vitality %+.1f")));
207 a.name =
_(
"Intelligence");
209 a.scope =
"character";
212 attributes[a.id] = a;
213 tags.insert(std::make_pair(
"int",
_(
"Intelligence %+.1f")));
219 a.name =
_(
"Willpower");
221 a.scope =
"character";
224 attributes[a.id] = a;
225 tags.insert(std::make_pair(
"wil",
_(
"Willpower %+.1f")));
231 if (!attributes.empty())
243 Log::info(
"Attributes: Invalid or missing stat ID in "
248 if (attributes.find(
id) != attributes.end())
250 Log::info(
"Attributes: Redefinition of stat ID %d",
id);
257 Log::info(
"Attributes: Invalid or missing stat name in "
272 unsigned int count = 0;
273 for (
auto effectNode : node.
children())
275 if (effectNode.name() !=
"modifier")
278 std::string tag = effectNode.getProperty(
"tag",
"");
283 Log::info(
"Attribute modifier in attribute %u:%s: "
284 "Empty name definition "
285 "on empty tag definition, skipping.",
290 tag = name.substr(0, name.size() > 3 ? 3 : name.size());
294 std::string effect = effectNode.getProperty(
"effect",
"");
299 Log::info(
"Attribute modifier in attribute %u:%s: "
300 "Empty name definition "
301 "on empty effect definition, skipping.",
307 effect = name +
" %+f";
309 tags.insert(std::make_pair(tag, effect));
311 Log::info(
"Found %d tags for attribute %d.", count,
id);
324 Log::info(
"Loaded points: start: %i, min: %i, max: %i.",
325 creationPoints, attributeMinimum, attributeMaximum);
333 Log::info(
"Found %d tags for %d attributes.",
int(tags.size()),
334 int(attributes.size()));
336 if (attributes.size() == 0)
344 auto modifiableAttributeCount = (float) attributeLabels.size();
345 float averageValue = ((float) creationPoints) / modifiableAttributeCount;
346 if (averageValue > attributeMaximum || averageValue < attributeMinimum
347 || creationPoints < 1)
349 Log::info(
"Attributes: Character's point values make "
350 "the character's creation impossible. "
351 "Switch back to defaults.");
365 std::list<ItemStat> dbStats;
367 for (
const auto &[tag, format] : tags)
368 dbStats.emplace_back(tag, format);
375 for (
const auto &[
_, attribute] : attributes)
377 if (attribute.playerInfoId == -1 &&
378 (attribute.scope ==
"character" || attribute.scope ==
"being"))
382 attribute.modifiable,
383 attribute.description);
#define DEFAULT_ATTRIBUTESDB_FILE
void addAttribute(int id, const std::string &name, bool modifiable, const std::string &description)
int getProperty(const char *name, int def) const
Children children() const
bool getBoolProperty(const char *name, bool def) const
StatusWindow * statusWindow
void setStatsList(std::list< ItemStat > stats)
void readPointsNode(XML::Node node, const std::string &filename)
Read points node.
unsigned int getAttributeMaximum()
Give the maximum attribute point possible at character's creation.
void informStatusWindow()
std::vector< std::string > & getLabels()
Returns the list of base attribute labels.
void checkStatus()
Check if all the data loaded by readPointsNode and readAttributeNode is ok.
unsigned int getCreationPoints()
Give the attribute points given to a character at its creation.
int getPlayerInfoIdFromAttrId(int attrId)
Give back the corresponding playerinfo Id from the attribute id defined in the xml file.
void readAttributeNode(XML::Node node, const std::string &filename)
Read attribute node.
unsigned int getAttributeMinimum()
Give the minimum attribute point possible at character's creation.
void info(const char *log_text,...) LOG_PRINTF_ATTR
Attribute
Standard attributes for players.
std::string & toLower(std::string &str)
Converts the given string to lower case.
std::string toString(const T &arg)
Converts the given value to a string using std::stringstream.
int playerInfoId
The playerInfo core Id the attribute is linked with or -1 if not.
bool modifiable
Whether the attribute value can be modified by the player.