std::string FormatTag(std::string const& src, json::Value& data) { if (src.empty()) return src; if (src[0] == '$' && src.back() == '$') return src; size_t slash = src.find('/'); if (slash == std::string::npos) return src; auto list = Strings::list(src.substr(0, slash)); if (!list) { Logger::log("StringList not found: %s", src.substr(0, slash).c_str()); return src; } size_t at = src.find('@', slash); std::string text = src.substr(slash + 1, at == std::string::npos ? at : at - slash - 1); if (!list.has(text)) { Logger::log("String not found: %s", src.substr(0, at).c_str()); return src; } text = list[text]; if (at != std::string::npos) { size_t quest = src.find('?', at); if (quest == std::string::npos) quest = src.length(); FormatFlags flags = FormatTags; PowerTag* context = nullptr; AttributeMap values = GameAffixes::defaultMap(); if (quest > at + 1) { flags = FormatHTML; context = PowerTags::get(src.substr(at + 1, quest - at - 1)); if (!context) { Logger::log("PowerTag not found: %s", src.substr(at + 1, quest - at - 1).c_str()); } } else { values["value"] = AttributeValue("%"); values["value1"] = AttributeValue("%"); values["value2"] = AttributeValue("%"); values["value3"] = AttributeValue("%"); } std::map<std::string, std::string> replace; if (quest < src.length()) { std::vector<std::string> parts = split(src.substr(quest + 1), '&'); for (auto& p : parts) { size_t eq = p.find('='); if (eq == std::string::npos) continue; std::string key = p.substr(0, eq); std::string value = p.substr(eq + 1); if (!testString(key, isalnum)) { size_t pos = text.find(key); if (pos == std::string::npos) continue; std::string rval = fmtstring("@%d", replace.size() + 1); replace.emplace(rval, value); text.replace(pos, key.length(), rval); continue; } if (testString(value, isdigit)) { values.emplace(key, atof(value.c_str())); continue; } size_t ss = value.find('/'); if (ss == std::string::npos) { values[key] = AttributeValue(value); } else { std::string listname = value.substr(0, ss); if (!testString(listname, isalpha)) { values[key] = AttributeValue(value); continue; } auto sublist = Strings::list(listname); if (!sublist) { Logger::log("StringList not found: %s", listname.c_str()); continue; } std::string subtext = value.substr(ss + 1); if (!sublist.has(subtext)) { Logger::log("String not found: %s", value.c_str()); continue; } values[key] = AttributeValue(sublist[subtext]); } } } text = FormatDescription(text, flags, values, context); for (auto& kv : replace) { size_t pos = text.find(kv.first); if (pos == std::string::npos) continue; text.replace(pos, kv.first.length(), kv.second); } } return text; }