Inventory updates, API updates, lots of file renaming

This commit is contained in:
2026-03-17 04:05:04 -04:00
parent b060784bb7
commit fb6f902f28
63 changed files with 820 additions and 553 deletions

View File

@@ -41,6 +41,8 @@ namespace game::resource::xml
query_anm2(root, "Anm2", archive, textureRootPath, anm2);
query_string_attribute(root, "Name", &name);
query_vec3(root, "ColorR", "ColorG", "ColorB", color);
root->QueryFloatAttribute("Weight", &weight);
root->QueryFloatAttribute("Capacity", &capacity);
@@ -159,6 +161,15 @@ namespace game::resource::xml
if (auto element = root->FirstChildElement("InteractAreas"))
{
auto interact_type_id_get = [&](const std::string& typeName)
{
for (int i = 0; i < (int)interactTypeNames.size(); i++)
if (interactTypeNames[i] == typeName) return i;
interactTypeNames.emplace_back(typeName);
return (int)interactTypeNames.size() - 1;
};
for (auto child = element->FirstChildElement("InteractArea"); child;
child = child->NextSiblingElement("InteractArea"))
{
@@ -173,6 +184,7 @@ namespace game::resource::xml
query_string_attribute(child, "AnimationCursorActive", &interactArea.animationCursorActive);
query_sound_entry_collection(child, "Sound", archive, soundRootPath, interactArea.sound, "Path");
dialogue.query_pool_id(child, "DialoguePoolID", interactArea.pool.id);
query_bool_attribute(child, "IsHold", &interactArea.isHold);
child->QueryFloatAttribute("DigestionBonusRub", &interactArea.digestionBonusRub);
child->QueryFloatAttribute("DigestionBonusClick", &interactArea.digestionBonusClick);
child->QueryFloatAttribute("Time", &interactArea.time);
@@ -181,9 +193,7 @@ namespace game::resource::xml
std::string typeString{};
query_string_attribute(child, "Type", &typeString);
for (int i = 0; i < (int)std::size(INTERACT_TYPE_STRINGS); i++)
if (typeString == INTERACT_TYPE_STRINGS[i]) interactArea.type = (InteractType)i;
if (!typeString.empty()) interactArea.typeID = interact_type_id_get(typeString);
interactAreas.emplace_back(std::move(interactArea));
}
@@ -210,10 +220,10 @@ namespace game::resource::xml
else
logger.warning(std::format("No character cursor.xml file found: {}", path.string()));
if (auto playSchemaPath = physfs::Path(archive + "/" + "play.xml"); playSchemaPath.is_valid())
playSchema = Play(playSchemaPath, dialogue);
if (auto skillCheckSchemaPath = physfs::Path(archive + "/" + "skill_check.xml"); skillCheckSchemaPath.is_valid())
skillCheckSchema = SkillCheck(skillCheckSchemaPath, dialogue);
else
logger.warning(std::format("No character play.xml file found: {}", path.string()));
logger.warning(std::format("No character skill_check.xml file found: {}", path.string()));
logger.info(std::format("Initialized character: {}", name));

View File

@@ -3,7 +3,6 @@
#include <filesystem>
#include <vector>
#include "../../util/interact_type.hpp"
#include "../audio.hpp"
#include "animation_entry.hpp"
#include "anm2.hpp"
@@ -12,7 +11,7 @@
#include "dialogue.hpp"
#include "item.hpp"
#include "menu.hpp"
#include "play.hpp"
#include "skill_check.hpp"
#include "save.hpp"
namespace game::resource::xml
@@ -51,7 +50,8 @@ namespace game::resource::xml
int nullID{-1};
int layerID{-1};
InteractType type{(InteractType)-1};
int typeID{-1};
bool isHold{};
Dialogue::PoolReference pool{-1};
float digestionBonusRub{};
@@ -97,7 +97,7 @@ namespace game::resource::xml
Item itemSchema{};
Menu menuSchema{};
Cursor cursorSchema{};
Play playSchema{};
SkillCheck skillCheckSchema{};
Save save{};
@@ -107,9 +107,12 @@ namespace game::resource::xml
Sounds sounds{};
glm::vec3 color{0.120f, 0.515f, 0.115f};
std::vector<Stage> stages{};
std::vector<ExpandArea> expandAreas{};
std::vector<EatArea> eatAreas{};
std::vector<std::string> interactTypeNames{};
std::vector<InteractArea> interactAreas{};
AlternateSpritesheet alternateSpritesheet{};

View File

@@ -42,6 +42,7 @@ namespace game::resource::xml
query_string_attribute(root, "Name", &name);
query_string_attribute(root, "Description", &description);
query_string_attribute(root, "Author", &author);
query_vec3(root, "ColorR", "ColorG", "ColorB", color);
root->QueryFloatAttribute("Weight", &weight);
if (auto element = root->FirstChildElement("Stages"))

View File

@@ -1,6 +1,7 @@
#pragma once
#include <filesystem>
#include <glm/glm.hpp>
#include <string>
#include <vector>
@@ -22,6 +23,7 @@ namespace game::resource::xml
Texture portrait{};
Texture render{};
Save save{};
glm::vec3 color{0.120f, 0.515f, 0.115f};
int stages{1};

View File

@@ -142,7 +142,7 @@ namespace game::resource::xml
query_int_optional_attribute(child, "UpgradeCount", item.upgradeCount);
}
query_bool_attribute(child, "IsPlayReward", &item.isPlayReward);
query_bool_attribute(child, "IsSkillCheckReward", &item.isSkillCheckReward);
query_bool_attribute(child, "IsToggleSpritesheet", &item.isToggleSpritesheet);
std::string categoryString{};
@@ -173,7 +173,7 @@ namespace game::resource::xml
{
auto& item = items[i];
pools[item.rarityID].emplace_back(i);
if (item.isPlayReward) rewardItemPool.emplace_back(i);
if (item.isSkillCheckReward) skillCheckRewardItemPool.emplace_back(i);
}
for (int i = 0; i < (int)rarities.size(); i++)

View File

@@ -50,7 +50,7 @@ namespace game::resource::xml
std::optional<float> digestionBonus{};
std::optional<float> gravity{};
std::optional<int> chewCount{};
bool isPlayReward{};
bool isSkillCheckReward{};
bool isToggleSpritesheet{};
};
@@ -85,7 +85,7 @@ namespace game::resource::xml
std::vector<int> rarityIDsSortedByChance{};
std::unordered_map<int, Pool> pools{};
Pool rewardItemPool{};
Pool skillCheckRewardItemPool{};
Animations animations{};
Sounds sounds{};

View File

@@ -22,15 +22,13 @@ namespace game::resource::xml
XMLDocument document;
auto pathString = path.string();
// Fail silently if there's no save.
auto result = document.LoadFile(pathString.c_str());
if (result == XML_ERROR_FILE_NOT_FOUND || result == XML_ERROR_FILE_COULD_NOT_BE_OPENED) return;
if (result != XML_SUCCESS)
{
logger.error(
std::format("Could not initialize character save file: {} ({})", pathString, document.ErrorStr()));
logger.error(std::format("Could not initialize character save file: {} ({})", pathString, document.ErrorStr()));
return;
}
@@ -54,7 +52,9 @@ namespace game::resource::xml
element->QueryIntAttribute("TotalFoodItemsEaten", &totalFoodItemsEaten);
}
if (auto element = root->FirstChildElement("Play"))
auto element = root->FirstChildElement("SkillCheck");
if (!element) element = root->FirstChildElement("Play");
if (element)
{
element->QueryIntAttribute("TotalPlays", &totalPlays);
element->QueryIntAttribute("HighScore", &highScore);
@@ -130,13 +130,13 @@ namespace game::resource::xml
characterElement->SetAttribute("TotalCaloriesConsumed", totalCaloriesConsumed);
characterElement->SetAttribute("TotalFoodItemsEaten", totalFoodItemsEaten);
auto playElement = element->InsertNewChildElement("Play");
auto skillCheckElement = element->InsertNewChildElement("SkillCheck");
playElement->SetAttribute("TotalPlays", totalPlays);
playElement->SetAttribute("HighScore", highScore);
playElement->SetAttribute("BestCombo", bestCombo);
skillCheckElement->SetAttribute("TotalPlays", totalPlays);
skillCheckElement->SetAttribute("HighScore", highScore);
skillCheckElement->SetAttribute("BestCombo", bestCombo);
auto gradesElement = playElement->InsertNewChildElement("Grades");
auto gradesElement = skillCheckElement->InsertNewChildElement("Grades");
for (auto& [i, count] : gradeCounts)
{

View File

@@ -23,8 +23,7 @@ namespace game::resource::xml
if (document.LoadFile(pathString.c_str()) != XML_SUCCESS)
{
logger.error(
std::format("Could not initialize character save file: {} ({})", pathString, document.ErrorStr()));
logger.error(std::format("Could not initialize character save file: {} ({})", pathString, document.ErrorStr()));
return;
}
@@ -34,13 +33,10 @@ namespace game::resource::xml
query_string_attribute(root, "MeasurementSystem", &measurementSystemString);
measurementSystem = measurementSystemString == "Imperial" ? measurement::IMPERIAL : measurement::METRIC;
root->QueryIntAttribute("Volume", &volume);
root->QueryFloatAttribute("ColorR", &color.r);
root->QueryFloatAttribute("ColorG", &color.g);
root->QueryFloatAttribute("ColorB", &color.b);
root->QueryFloatAttribute("WindowX", &windowPosition.x);
root->QueryFloatAttribute("WindowY", &windowPosition.y);
root->QueryIntAttribute("WindowW", &windowSize.x);
root->QueryIntAttribute("WindowH", &windowSize.y);
query_vec3(root, "ColorR", "ColorG", "ColorB", color);
query_vec2(root, "WindowX", "WindowY", windowPosition);
query_ivec2(root, "WindowW", "WindowH", windowSize);
query_bool_attribute(root, "IsUseCharacterColor", &isUseCharacterColor);
}
logger.info(std::format("Initialized settings: {}", pathString));
@@ -59,13 +55,10 @@ namespace game::resource::xml
element->SetAttribute("MeasurementSystem", measurementSystem == measurement::IMPERIAL ? "Imperial" : "Metric");
element->SetAttribute("Volume", volume);
element->SetAttribute("ColorR", color.r);
element->SetAttribute("ColorG", color.g);
element->SetAttribute("ColorB", color.b);
element->SetAttribute("WindowX", windowPosition.x);
element->SetAttribute("WindowY", windowPosition.y);
element->SetAttribute("WindowW", windowSize.x);
element->SetAttribute("WindowH", windowSize.y);
set_vec3_attribute(element, "ColorR", "ColorG", "ColorB", color);
set_vec2_attribute(element, "WindowX", "WindowY", windowPosition);
set_ivec2_attribute(element, "WindowW", "WindowH", windowSize);
set_bool_attribute(element, "IsUseCharacterColor", isUseCharacterColor);
document.InsertFirstChild(element);

View File

@@ -21,6 +21,7 @@ namespace game::resource::xml
util::measurement::System measurementSystem{util::measurement::METRIC};
int volume{50};
bool isUseCharacterColor{true};
glm::vec3 color{0.120f, 0.515f, 0.115f};
glm::ivec2 windowSize{1600, 900};

View File

@@ -1,4 +1,4 @@
#include "play.hpp"
#include "skill_check.hpp"
#include "../../log.hpp"
#include "util.hpp"
@@ -10,7 +10,7 @@ using namespace game::util;
namespace game::resource::xml
{
Play::Play(const physfs::Path& path, Dialogue& dialogue)
SkillCheck::SkillCheck(const physfs::Path& path, Dialogue& dialogue)
{
XMLDocument document;
@@ -62,8 +62,8 @@ namespace game::resource::xml
}
isValid = true;
logger.info(std::format("Initialized play schema: {}", path.c_str()));
logger.info(std::format("Initialized skill check schema: {}", path.c_str()));
}
bool Play::is_valid() const { return isValid; };
bool SkillCheck::is_valid() const { return isValid; };
}

View File

@@ -8,7 +8,7 @@
namespace game::resource::xml
{
class Play
class SkillCheck
{
public:
struct Grade
@@ -48,8 +48,8 @@ namespace game::resource::xml
bool isValid{};
Play() = default;
Play(const util::physfs::Path&, Dialogue&);
SkillCheck() = default;
SkillCheck(const util::physfs::Path&, Dialogue&);
bool is_valid() const;
};

View File

@@ -12,6 +12,8 @@ using namespace game::util;
namespace game::resource::xml
{
XMLError query_result_merge(XMLError result, XMLError next) { return result == XML_SUCCESS ? next : result; }
XMLError query_string_attribute(XMLElement* element, const char* attribute, std::string* value)
{
const char* temp = nullptr;
@@ -45,6 +47,60 @@ namespace game::resource::xml
return result;
}
XMLError query_ivec2(XMLElement* element, const char* attributeX, const char* attributeY, glm::ivec2& value)
{
auto result = element->QueryIntAttribute(attributeX, &value.x);
result = query_result_merge(result, element->QueryIntAttribute(attributeY, &value.y));
return result;
}
XMLError query_vec2(XMLElement* element, const char* attributeX, const char* attributeY, glm::vec2& value)
{
auto result = element->QueryFloatAttribute(attributeX, &value.x);
result = query_result_merge(result, element->QueryFloatAttribute(attributeY, &value.y));
return result;
}
XMLError query_vec3(XMLElement* element, const char* attributeX, const char* attributeY, const char* attributeZ,
glm::vec3& value)
{
auto result = element->QueryFloatAttribute(attributeX, &value.x);
result = query_result_merge(result, element->QueryFloatAttribute(attributeY, &value.y));
result = query_result_merge(result, element->QueryFloatAttribute(attributeZ, &value.z));
return result;
}
XMLError set_bool_attribute(XMLElement* element, const char* attribute, bool value)
{
element->SetAttribute(attribute, value ? "true" : "false");
return XML_SUCCESS;
}
XMLError set_ivec2_attribute(XMLElement* element, const char* attributeX, const char* attributeY,
const glm::ivec2& value)
{
element->SetAttribute(attributeX, value.x);
element->SetAttribute(attributeY, value.y);
return XML_SUCCESS;
}
XMLError set_vec2_attribute(XMLElement* element, const char* attributeX, const char* attributeY,
const glm::vec2& value)
{
element->SetAttribute(attributeX, value.x);
element->SetAttribute(attributeY, value.y);
return XML_SUCCESS;
}
XMLError set_vec3_attribute(XMLElement* element, const char* attributeX, const char* attributeY,
const char* attributeZ, const glm::vec3& value)
{
element->SetAttribute(attributeX, value.x);
element->SetAttribute(attributeY, value.y);
element->SetAttribute(attributeZ, value.z);
return XML_SUCCESS;
}
XMLError query_float_optional_attribute(XMLElement* element, const char* attribute, std::optional<float>& value)
{
value.emplace();
@@ -84,102 +140,139 @@ namespace game::resource::xml
return result;
}
void query_event_id(XMLElement* element, const char* name, const Anm2& anm2, int& eventID)
XMLError query_event_id(XMLElement* element, const char* name, const Anm2& anm2, int& eventID)
{
std::string string{};
query_string_attribute(element, name, &string);
auto result = query_string_attribute(element, name, &string);
if (result != XML_SUCCESS) return result;
if (anm2.eventMap.contains(string))
{
eventID = anm2.eventMap.at(string);
return XML_SUCCESS;
}
else
{
logger.error(std::format("Could not query anm2 event ID: {} ({})", string, anm2.path));
eventID = -1;
return XML_ERROR_PARSING_ATTRIBUTE;
}
}
void query_layer_id(XMLElement* element, const char* name, const Anm2& anm2, int& layerID)
XMLError query_layer_id(XMLElement* element, const char* name, const Anm2& anm2, int& layerID)
{
std::string string{};
query_string_attribute(element, name, &string);
auto result = query_string_attribute(element, name, &string);
if (result != XML_SUCCESS) return result;
if (anm2.layerMap.contains(string))
{
layerID = anm2.layerMap.at(string);
return XML_SUCCESS;
}
else
{
logger.error(std::format("Could not query anm2 layer ID: {} ({})", string, anm2.path));
layerID = -1;
return XML_ERROR_PARSING_ATTRIBUTE;
}
}
void query_null_id(XMLElement* element, const char* name, const Anm2& anm2, int& nullID)
XMLError query_null_id(XMLElement* element, const char* name, const Anm2& anm2, int& nullID)
{
std::string string{};
query_string_attribute(element, name, &string);
auto result = query_string_attribute(element, name, &string);
if (result != XML_SUCCESS) return result;
if (anm2.nullMap.contains(string))
{
nullID = anm2.nullMap.at(string);
return XML_SUCCESS;
}
else
{
logger.error(std::format("Could not query anm2 null ID: {} ({})", string, anm2.path));
nullID = -1;
return XML_ERROR_PARSING_ATTRIBUTE;
}
}
void query_anm2(XMLElement* element, const char* name, const std::string& archive, const std::string& rootPath,
Anm2& anm2, Anm2::Flags flags)
XMLError query_anm2(XMLElement* element, const char* name, const std::string& archive, const std::string& rootPath,
Anm2& anm2, Anm2::Flags flags)
{
std::string string{};
query_string_attribute(element, name, &string);
auto result = query_string_attribute(element, name, &string);
if (result != XML_SUCCESS) return result;
anm2 = Anm2(physfs::Path(archive + "/" + rootPath + "/" + string), flags);
return XML_SUCCESS;
}
void query_texture(XMLElement* element, const char* name, const std::string& archive, const std::string& rootPath,
Texture& texture)
XMLError query_texture(XMLElement* element, const char* name, const std::string& archive, const std::string& rootPath,
Texture& texture)
{
std::string string{};
query_string_attribute(element, name, &string);
auto result = query_string_attribute(element, name, &string);
if (result != XML_SUCCESS) return result;
texture = Texture(physfs::Path(archive + "/" + rootPath + "/" + string));
return XML_SUCCESS;
}
void query_sound(XMLElement* element, const char* name, const std::string& archive, const std::string& rootPath,
Audio& sound)
XMLError query_sound(XMLElement* element, const char* name, const std::string& archive, const std::string& rootPath,
Audio& sound)
{
std::string string{};
query_string_attribute(element, name, &string);
auto result = query_string_attribute(element, name, &string);
if (result != XML_SUCCESS) return result;
sound = Audio(physfs::Path(archive + "/" + rootPath + "/" + string));
return XML_SUCCESS;
}
void query_font(XMLElement* element, const char* name, const std::string& archive, const std::string& rootPath,
Font& font)
XMLError query_font(XMLElement* element, const char* name, const std::string& archive, const std::string& rootPath,
Font& font)
{
std::string string{};
query_string_attribute(element, name, &string);
auto result = query_string_attribute(element, name, &string);
if (result != XML_SUCCESS) return result;
font = Font(physfs::Path(archive + "/" + rootPath + "/" + string));
return XML_SUCCESS;
}
void query_animation_entry(XMLElement* element, AnimationEntry& animationEntry)
XMLError query_animation_entry(XMLElement* element, AnimationEntry& animationEntry)
{
query_string_attribute(element, "Animation", &animationEntry.animation);
element->QueryFloatAttribute("Weight", &animationEntry.weight);
auto result = query_string_attribute(element, "Animation", &animationEntry.animation);
result = query_result_merge(result, element->QueryFloatAttribute("Weight", &animationEntry.weight));
return result;
}
void query_animation_entry_collection(XMLElement* element, const char* name,
AnimationEntryCollection& animationEntryCollection)
XMLError query_animation_entry_collection(XMLElement* element, const char* name,
AnimationEntryCollection& animationEntryCollection)
{
auto result = XML_SUCCESS;
for (auto child = element->FirstChildElement(name); child; child = child->NextSiblingElement(name))
query_animation_entry(child, animationEntryCollection.emplace_back());
result = query_result_merge(result, query_animation_entry(child, animationEntryCollection.emplace_back()));
return result;
}
void query_sound_entry(XMLElement* element, const std::string& archive, const std::string& rootPath,
SoundEntry& soundEntry, const std::string& attributeName)
XMLError query_sound_entry(XMLElement* element, const std::string& archive, const std::string& rootPath,
SoundEntry& soundEntry, const std::string& attributeName)
{
query_sound(element, attributeName.c_str(), archive, rootPath, soundEntry.sound);
element->QueryFloatAttribute("Weight", &soundEntry.weight);
auto result = query_sound(element, attributeName.c_str(), archive, rootPath, soundEntry.sound);
result = query_result_merge(result, element->QueryFloatAttribute("Weight", &soundEntry.weight));
return result;
}
void query_sound_entry_collection(XMLElement* element, const char* name, const std::string& archive,
const std::string& rootPath, SoundEntryCollection& soundEntryCollection,
const std::string& attributeName)
XMLError query_sound_entry_collection(XMLElement* element, const char* name, const std::string& archive,
const std::string& rootPath, SoundEntryCollection& soundEntryCollection,
const std::string& attributeName)
{
auto result = XML_SUCCESS;
for (auto child = element->FirstChildElement(name); child; child = child->NextSiblingElement(name))
query_sound_entry(child, archive, rootPath, soundEntryCollection.emplace_back(), attributeName);
result = query_result_merge(
result, query_sound_entry(child, archive, rootPath, soundEntryCollection.emplace_back(), attributeName));
return result;
}
}

View File

@@ -4,6 +4,7 @@
#include <optional>
#include <string>
#include <glm/glm.hpp>
#include <tinyxml2.h>
#include "animation_entry.hpp"
@@ -19,33 +20,43 @@ namespace game::resource::xml
tinyxml2::XMLError query_bool_attribute(tinyxml2::XMLElement*, const char*, bool*);
tinyxml2::XMLError query_path_attribute(tinyxml2::XMLElement*, const char*, std::filesystem::path*);
tinyxml2::XMLError query_color_attribute(tinyxml2::XMLElement*, const char*, float*);
tinyxml2::XMLError query_ivec2(tinyxml2::XMLElement*, const char*, const char*, glm::ivec2&);
tinyxml2::XMLError query_vec2(tinyxml2::XMLElement*, const char*, const char*, glm::vec2&);
tinyxml2::XMLError query_vec3(tinyxml2::XMLElement*, const char*, const char*, const char*, glm::vec3&);
tinyxml2::XMLError set_bool_attribute(tinyxml2::XMLElement*, const char*, bool);
tinyxml2::XMLError set_ivec2_attribute(tinyxml2::XMLElement*, const char*, const char*, const glm::ivec2&);
tinyxml2::XMLError set_vec2_attribute(tinyxml2::XMLElement*, const char*, const char*, const glm::vec2&);
tinyxml2::XMLError set_vec3_attribute(tinyxml2::XMLElement*, const char*, const char*, const char*,
const glm::vec3&);
tinyxml2::XMLError query_float_optional_attribute(tinyxml2::XMLElement* element, const char* attribute,
std::optional<float>& value);
tinyxml2::XMLError query_int_optional_attribute(tinyxml2::XMLElement* element, const char* attribute,
std::optional<int>& value);
void query_event_id(tinyxml2::XMLElement* element, const char* name, const Anm2& anm2, int& eventID);
void query_layer_id(tinyxml2::XMLElement* element, const char* name, const Anm2& anm2, int& layerID);
void query_null_id(tinyxml2::XMLElement* element, const char* name, const Anm2& anm2, int& nullID);
tinyxml2::XMLError query_event_id(tinyxml2::XMLElement* element, const char* name, const Anm2& anm2, int& eventID);
tinyxml2::XMLError query_layer_id(tinyxml2::XMLElement* element, const char* name, const Anm2& anm2, int& layerID);
tinyxml2::XMLError query_null_id(tinyxml2::XMLElement* element, const char* name, const Anm2& anm2, int& nullID);
void query_anm2(tinyxml2::XMLElement* element, const char* name, const std::string& archive,
const std::string& rootPath, Anm2& anm2, Anm2::Flags flags = {});
void query_texture(tinyxml2::XMLElement* element, const char* name, const std::string& archive,
const std::string& rootPath, Texture& texture);
void query_sound(tinyxml2::XMLElement* element, const char* name, const std::string& archive,
const std::string& rootPath, Audio& sound);
void query_font(tinyxml2::XMLElement* element, const char* name, const std::string& archive,
const std::string& rootPath, Font& font);
tinyxml2::XMLError query_anm2(tinyxml2::XMLElement* element, const char* name, const std::string& archive,
const std::string& rootPath, Anm2& anm2, Anm2::Flags flags = {});
tinyxml2::XMLError query_texture(tinyxml2::XMLElement* element, const char* name, const std::string& archive,
const std::string& rootPath, Texture& texture);
tinyxml2::XMLError query_sound(tinyxml2::XMLElement* element, const char* name, const std::string& archive,
const std::string& rootPath, Audio& sound);
tinyxml2::XMLError query_font(tinyxml2::XMLElement* element, const char* name, const std::string& archive,
const std::string& rootPath, Font& font);
void query_animation_entry(tinyxml2::XMLElement* element, AnimationEntry& animationEntry);
void query_animation_entry_collection(tinyxml2::XMLElement* element, const char* name,
AnimationEntryCollection& animationEntryCollection);
tinyxml2::XMLError query_animation_entry(tinyxml2::XMLElement* element, AnimationEntry& animationEntry);
tinyxml2::XMLError query_animation_entry_collection(tinyxml2::XMLElement* element, const char* name,
AnimationEntryCollection& animationEntryCollection);
void query_sound_entry(tinyxml2::XMLElement* element, const std::string& archive, const std::string& rootPath,
SoundEntry& soundEntry, const std::string& attributeName = "Sound");
void query_sound_entry_collection(tinyxml2::XMLElement* element, const char* name, const std::string& archive,
const std::string& rootPath, SoundEntryCollection& soundEntryCollection,
const std::string& attributeName = "Sound");
tinyxml2::XMLError query_sound_entry(tinyxml2::XMLElement* element, const std::string& archive,
const std::string& rootPath, SoundEntry& soundEntry,
const std::string& attributeName = "Sound");
tinyxml2::XMLError query_sound_entry_collection(tinyxml2::XMLElement* element, const char* name,
const std::string& archive, const std::string& rootPath,
SoundEntryCollection& soundEntryCollection,
const std::string& attributeName = "Sound");
tinyxml2::XMLError document_load(const util::physfs::Path&, tinyxml2::XMLDocument&);
}