a (not so) mini update
This commit is contained in:
@@ -43,28 +43,31 @@ namespace game::resource::xml
|
||||
|
||||
query_vec3(root, "ColorR", "ColorG", "ColorB", color);
|
||||
|
||||
root->QueryFloatAttribute("Weight", &weight);
|
||||
root->QueryDoubleAttribute("Weight", &weight);
|
||||
root->QueryDoubleAttribute("WeightMax", &weightMax);
|
||||
|
||||
root->QueryFloatAttribute("Capacity", &capacity);
|
||||
root->QueryFloatAttribute("CapacityMin", &capacityMin);
|
||||
root->QueryFloatAttribute("CapacityMax", &capacityMax);
|
||||
root->QueryFloatAttribute("CapacityMaxMultiplier", &capacityMaxMultiplier);
|
||||
root->QueryFloatAttribute("CapacityIfOverStuffedOnDigestBonus", &capacityIfOverStuffedOnDigestBonus);
|
||||
root->QueryDoubleAttribute("Capacity", &capacity);
|
||||
root->QueryDoubleAttribute("CapacityMin", &capacityMin);
|
||||
root->QueryDoubleAttribute("CapacityMax", &capacityMax);
|
||||
root->QueryDoubleAttribute("CapacityMaxMultiplier", &capacityMaxMultiplier);
|
||||
root->QueryDoubleAttribute("CapacityIfOverStuffedOnDigestBonus", &capacityIfOverStuffedOnDigestBonus);
|
||||
|
||||
root->QueryFloatAttribute("CaloriesToKilogram", &caloriesToKilogram);
|
||||
root->QueryDoubleAttribute("CaloriesToKilogram", &caloriesToKilogram);
|
||||
|
||||
root->QueryFloatAttribute("DigestionRate", &digestionRate);
|
||||
root->QueryFloatAttribute("DigestionRateMin", &digestionRateMin);
|
||||
root->QueryFloatAttribute("DigestionRateMax", &digestionRateMax);
|
||||
root->QueryDoubleAttribute("DigestionRate", &digestionRate);
|
||||
root->QueryDoubleAttribute("DigestionRateMin", &digestionRateMin);
|
||||
root->QueryDoubleAttribute("DigestionRateMax", &digestionRateMax);
|
||||
root->QueryIntAttribute("DigestionTimerMax", &digestionTimerMax);
|
||||
|
||||
root->QueryFloatAttribute("EatSpeed", &eatSpeed);
|
||||
root->QueryFloatAttribute("EatSpeedMin", &eatSpeedMin);
|
||||
root->QueryFloatAttribute("EatSpeedMax", &eatSpeedMax);
|
||||
root->QueryDoubleAttribute("EatSpeed", &eatSpeed);
|
||||
root->QueryDoubleAttribute("EatSpeedMin", &eatSpeedMin);
|
||||
root->QueryDoubleAttribute("EatSpeedMax", &eatSpeedMax);
|
||||
|
||||
root->QueryFloatAttribute("BlinkChance", &blinkChance);
|
||||
root->QueryFloatAttribute("GurgleChance", &gurgleChance);
|
||||
root->QueryFloatAttribute("GurgleCapacityMultiplier", &gurgleCapacityMultiplier);
|
||||
root->QueryDoubleAttribute("BlinkChance", &blinkChance);
|
||||
root->QueryDoubleAttribute("GurgleChance", &gurgleChance);
|
||||
root->QueryDoubleAttribute("GurgleCapacityMultiplier", &gurgleCapacityMultiplier);
|
||||
|
||||
root->QueryIntAttribute("TextBlipPeriodBase", &textBlipPeriodBase);
|
||||
|
||||
auto dialoguePath = physfs::Path(archive + "/" + "dialogue.xml");
|
||||
|
||||
@@ -100,6 +103,7 @@ namespace game::resource::xml
|
||||
|
||||
if (auto element = root->FirstChildElement("Sounds"))
|
||||
{
|
||||
query_sound_entry_collection(element, "Blip", archive, soundRootPath, sounds.blip);
|
||||
query_sound_entry_collection(element, "Digest", archive, soundRootPath, sounds.digest);
|
||||
query_sound_entry_collection(element, "Gurgle", archive, soundRootPath, sounds.gurgle);
|
||||
}
|
||||
@@ -127,6 +131,7 @@ namespace game::resource::xml
|
||||
child->QueryFloatAttribute("Threshold", &stage.threshold);
|
||||
child->QueryIntAttribute("AreaID", &stage.areaID);
|
||||
dialogue.query_pool_id(child, "DialoguePoolID", stage.pool.id);
|
||||
query_string_attribute(child, "AnimationAppendID", &stage.animationAppendID);
|
||||
stages.emplace_back(std::move(stage));
|
||||
}
|
||||
}
|
||||
@@ -178,12 +183,11 @@ namespace game::resource::xml
|
||||
if (child->FindAttribute("Layer")) query_layer_id(child, "Layer", anm2, interactArea.layerID);
|
||||
|
||||
query_null_id(child, "Null", anm2, interactArea.nullID);
|
||||
query_string_attribute(child, "Animation", &interactArea.animation);
|
||||
query_string_attribute(child, "AnimationFull", &interactArea.animationFull);
|
||||
query_string_attribute(child, "AnimationCursorHover", &interactArea.animationCursorHover);
|
||||
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);
|
||||
dialogue.query_pool_id(child, "DialoguePoolIDFull", interactArea.poolFull.id);
|
||||
query_bool_attribute(child, "IsHold", &interactArea.isHold);
|
||||
child->QueryFloatAttribute("DigestionBonusRub", &interactArea.digestionBonusRub);
|
||||
child->QueryFloatAttribute("DigestionBonusClick", &interactArea.digestionBonusClick);
|
||||
@@ -225,6 +229,9 @@ namespace game::resource::xml
|
||||
else
|
||||
logger.warning(std::format("No character skill_check.xml file found: {}", path.string()));
|
||||
|
||||
if (auto stringsPath = physfs::Path(archive + "/" + "strings.xml"); stringsPath.is_valid())
|
||||
strings = Strings(stringsPath);
|
||||
|
||||
logger.info(std::format("Initialized character: {}", name));
|
||||
|
||||
this->path = path;
|
||||
|
||||
@@ -11,8 +11,9 @@
|
||||
#include "dialogue.hpp"
|
||||
#include "item.hpp"
|
||||
#include "menu.hpp"
|
||||
#include "skill_check.hpp"
|
||||
#include "save.hpp"
|
||||
#include "skill_check.hpp"
|
||||
#include "strings.hpp"
|
||||
|
||||
namespace game::resource::xml
|
||||
{
|
||||
@@ -24,6 +25,7 @@ namespace game::resource::xml
|
||||
float threshold{};
|
||||
int areaID{};
|
||||
Dialogue::PoolReference pool{-1};
|
||||
std::string animationAppendID{};
|
||||
};
|
||||
|
||||
struct EatArea
|
||||
@@ -42,8 +44,6 @@ namespace game::resource::xml
|
||||
|
||||
struct InteractArea
|
||||
{
|
||||
std::string animation{};
|
||||
std::string animationFull{};
|
||||
std::string animationCursorActive{};
|
||||
std::string animationCursorHover{};
|
||||
SoundEntryCollection sound{};
|
||||
@@ -53,6 +53,7 @@ namespace game::resource::xml
|
||||
int typeID{-1};
|
||||
bool isHold{};
|
||||
Dialogue::PoolReference pool{-1};
|
||||
Dialogue::PoolReference poolFull{-1};
|
||||
|
||||
float digestionBonusRub{};
|
||||
float digestionBonusClick{};
|
||||
@@ -73,6 +74,7 @@ namespace game::resource::xml
|
||||
|
||||
struct Sounds
|
||||
{
|
||||
SoundEntryCollection blip{};
|
||||
SoundEntryCollection gurgle{};
|
||||
SoundEntryCollection digest{};
|
||||
};
|
||||
@@ -98,6 +100,7 @@ namespace game::resource::xml
|
||||
Menu menuSchema{};
|
||||
Cursor cursorSchema{};
|
||||
SkillCheck skillCheckSchema{};
|
||||
Strings strings{};
|
||||
|
||||
Save save{};
|
||||
|
||||
@@ -119,23 +122,25 @@ namespace game::resource::xml
|
||||
|
||||
std::string name{};
|
||||
std::filesystem::path path{};
|
||||
float weight{50};
|
||||
float capacity{2000.0f};
|
||||
float capacityMin{2000.0f};
|
||||
float capacityMax{99999.0f};
|
||||
float capacityMaxMultiplier{1.5f};
|
||||
float capacityIfOverStuffedOnDigestBonus{0.25f};
|
||||
float caloriesToKilogram{1000.0f};
|
||||
float digestionRate{0.05f};
|
||||
float digestionRateMin{0.0f};
|
||||
float digestionRateMax{0.25f};
|
||||
double weight{50};
|
||||
double weightMax{1000};
|
||||
double capacity{2000.0};
|
||||
double capacityMin{2000.0};
|
||||
double capacityMax{99999.0};
|
||||
double capacityMaxMultiplier{1.5};
|
||||
double capacityIfOverStuffedOnDigestBonus{0.25};
|
||||
double caloriesToKilogram{1000.0};
|
||||
double digestionRate{0.05};
|
||||
double digestionRateMin{0.0};
|
||||
double digestionRateMax{0.25};
|
||||
int digestionTimerMax{60};
|
||||
float eatSpeed{1.0f};
|
||||
float eatSpeedMin{1.0f};
|
||||
float eatSpeedMax{3.0f};
|
||||
float blinkChance{1.0f};
|
||||
float gurgleChance{1.0f};
|
||||
float gurgleCapacityMultiplier{1.0f};
|
||||
int textBlipPeriodBase{3};
|
||||
double eatSpeed{1.0};
|
||||
double eatSpeedMin{1.0};
|
||||
double eatSpeedMax{3.0};
|
||||
double blinkChance{1.0};
|
||||
double gurgleChance{1.0};
|
||||
double gurgleCapacityMultiplier{1.0};
|
||||
Dialogue::PoolReference pool{-1};
|
||||
|
||||
Character() = default;
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace game::resource::xml
|
||||
|
||||
query_string_attribute(root, "Name", &name);
|
||||
query_string_attribute(root, "Description", &description);
|
||||
query_string_attribute(root, "Author", &author);
|
||||
query_string_attribute(root, "Credits", &credits);
|
||||
query_vec3(root, "ColorR", "ColorG", "ColorB", color);
|
||||
root->QueryFloatAttribute("Weight", &weight);
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace game::resource::xml
|
||||
int stages{1};
|
||||
|
||||
std::string name{};
|
||||
std::string author{};
|
||||
std::string credits{};
|
||||
std::string description{};
|
||||
std::filesystem::path path{};
|
||||
float weight{50};
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "../../log.hpp"
|
||||
#include "../../util/math.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <format>
|
||||
|
||||
using namespace tinyxml2;
|
||||
@@ -98,6 +99,8 @@ namespace game::resource::xml
|
||||
|
||||
id++;
|
||||
}
|
||||
|
||||
entrySelectionOrder.assign(entries.size(), -1);
|
||||
}
|
||||
|
||||
if (auto element = root->FirstChildElement("Pools"))
|
||||
@@ -158,15 +161,32 @@ namespace game::resource::xml
|
||||
}
|
||||
}
|
||||
|
||||
int Dialogue::Pool::get() const
|
||||
int Dialogue::entry_pick(Pool& pool)
|
||||
{
|
||||
if (this->empty()) return -1;
|
||||
auto index = rand() % this->size();
|
||||
return this->at(index);
|
||||
if (pool.empty()) return -1;
|
||||
|
||||
std::vector<int> unselected{};
|
||||
for (auto id : pool)
|
||||
if (id >= 0 && id < (int)entrySelectionOrder.size() && entrySelectionOrder[id] < 0) unselected.emplace_back(id);
|
||||
|
||||
std::vector<int> candidates = unselected.empty() ? std::vector<int>(pool.begin(), pool.end()) : unselected;
|
||||
if (candidates.empty()) return -1;
|
||||
|
||||
auto oldestOrder = entrySelectionOrder[candidates.front()];
|
||||
for (auto id : candidates)
|
||||
oldestOrder = std::min(oldestOrder, entrySelectionOrder[id]);
|
||||
|
||||
std::vector<int> oldestCandidates{};
|
||||
for (auto id : candidates)
|
||||
if (entrySelectionOrder[id] == oldestOrder) oldestCandidates.emplace_back(id);
|
||||
|
||||
auto pickedID = oldestCandidates.at(rand() % oldestCandidates.size());
|
||||
entrySelectionOrder[pickedID] = selectionCounter++;
|
||||
return pickedID;
|
||||
}
|
||||
Dialogue::Entry* Dialogue::get(int id) { return &entries.at(id); }
|
||||
Dialogue::Entry* Dialogue::get(Dialogue::EntryReference& entry) { return &entries.at(entry.id); }
|
||||
Dialogue::Entry* Dialogue::get(const std::string& string) { return &entries.at(entryIDMap.at(string)); }
|
||||
Dialogue::Entry* Dialogue::get(Dialogue::PoolReference& pool) { return &entries.at(pools.at(pool.id).get()); }
|
||||
Dialogue::Entry* Dialogue::get(Dialogue::Pool& pool) { return &entries.at(pool.get()); }
|
||||
Dialogue::Entry* Dialogue::get(Dialogue::PoolReference& pool) { return &entries.at(entry_pick(pools.at(pool.id))); }
|
||||
Dialogue::Entry* Dialogue::get(Dialogue::Pool& pool) { return &entries.at(entry_pick(pool)); }
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <string>
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "../../util/physfs.hpp"
|
||||
|
||||
@@ -45,11 +46,7 @@ namespace game::resource::xml
|
||||
inline bool is_valid() const { return id != -1; };
|
||||
};
|
||||
|
||||
class Pool : public std::vector<int>
|
||||
{
|
||||
public:
|
||||
int get() const;
|
||||
};
|
||||
class Pool : public std::vector<int> {};
|
||||
|
||||
std::map<std::string, int> entryIDMap;
|
||||
std::map<int, std::string> entryIDMapReverse;
|
||||
@@ -57,6 +54,8 @@ namespace game::resource::xml
|
||||
|
||||
std::vector<Pool> pools{};
|
||||
std::map<std::string, int> poolMap{};
|
||||
std::vector<long long> entrySelectionOrder{};
|
||||
long long selectionCounter{};
|
||||
|
||||
EntryReference start{-1};
|
||||
EntryReference end{-1};
|
||||
@@ -83,8 +82,9 @@ namespace game::resource::xml
|
||||
Entry* get(Dialogue::EntryReference&);
|
||||
Entry* get(Dialogue::Pool&);
|
||||
Entry* get(Dialogue::PoolReference&);
|
||||
int entry_pick(Pool&);
|
||||
void query_entry_id(tinyxml2::XMLElement* element, const char* name, int& id);
|
||||
void query_pool_id(tinyxml2::XMLElement* element, const char* name, int& id);
|
||||
inline bool is_valid() const { return isValid; };
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,7 +110,8 @@ namespace game::resource::xml
|
||||
std::string itemTextureRootPath{};
|
||||
query_string_attribute(element, "TextureRootPath", &itemTextureRootPath);
|
||||
|
||||
element->QueryIntAttribute("ChewCount", &chewCount);
|
||||
element->QueryIntAttribute("Durability", &durability);
|
||||
if (element->FindAttribute("ChewCount")) element->QueryIntAttribute("ChewCount", &durability);
|
||||
element->QueryIntAttribute("QuantityMax", &quantityMax);
|
||||
|
||||
for (auto child = element->FirstChildElement("Item"); child; child = child->NextSiblingElement("Item"))
|
||||
@@ -121,11 +122,14 @@ namespace game::resource::xml
|
||||
query_string_attribute(child, "Description", &item.description);
|
||||
|
||||
query_float_optional_attribute(child, "Calories", item.calories);
|
||||
query_float_optional_attribute(child, "CapacityBonus", item.capacityBonus);
|
||||
query_optional_vec3(child, "ColorR", "ColorG", "ColorB", item.color);
|
||||
query_float_optional_attribute(child, "DigestionBonus", item.digestionBonus);
|
||||
query_float_optional_attribute(child, "EatSpeedBonus", item.eatSpeedBonus);
|
||||
query_float_optional_attribute(child, "Gravity", item.gravity);
|
||||
|
||||
query_int_optional_attribute(child, "ChewCount", item.chewCount);
|
||||
query_int_optional_attribute(child, "Durability", item.durability);
|
||||
if (!item.durability.has_value()) query_int_optional_attribute(child, "ChewCount", item.durability);
|
||||
|
||||
if (child->FindAttribute("UpgradeID"))
|
||||
{
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "../audio.hpp"
|
||||
#include "anm2.hpp"
|
||||
#include "sound_entry.hpp"
|
||||
@@ -46,10 +48,12 @@ namespace game::resource::xml
|
||||
std::optional<int> upgradeID{};
|
||||
std::optional<int> flavorID;
|
||||
std::optional<float> calories{};
|
||||
std::optional<float> capacityBonus{};
|
||||
std::optional<glm::vec3> color{};
|
||||
std::optional<float> eatSpeedBonus{};
|
||||
std::optional<float> digestionBonus{};
|
||||
std::optional<float> gravity{};
|
||||
std::optional<int> chewCount{};
|
||||
std::optional<int> durability{};
|
||||
bool isSkillCheckReward{};
|
||||
bool isToggleSpritesheet{};
|
||||
};
|
||||
@@ -90,7 +94,7 @@ namespace game::resource::xml
|
||||
Animations animations{};
|
||||
Sounds sounds{};
|
||||
Anm2 baseAnm2{};
|
||||
int chewCount{2};
|
||||
int durability{2};
|
||||
int quantityMax{99};
|
||||
|
||||
bool isValid{};
|
||||
|
||||
@@ -91,7 +91,8 @@ namespace game::resource::xml
|
||||
{
|
||||
Item item{};
|
||||
child->QueryIntAttribute("ID", &item.id);
|
||||
child->QueryIntAttribute("ChewCount", &item.chewCount);
|
||||
child->QueryIntAttribute("Durability", &item.durability);
|
||||
if (child->FindAttribute("ChewCount")) child->QueryIntAttribute("ChewCount", &item.durability);
|
||||
child->QueryFloatAttribute("PositionX", &item.position.x);
|
||||
child->QueryFloatAttribute("PositionY", &item.position.y);
|
||||
child->QueryFloatAttribute("VelocityX", &item.velocity.x);
|
||||
@@ -162,7 +163,7 @@ namespace game::resource::xml
|
||||
auto itemElement = itemsElement->InsertNewChildElement("Item");
|
||||
|
||||
itemElement->SetAttribute("ID", item.id);
|
||||
itemElement->SetAttribute("ChewCount", item.chewCount);
|
||||
itemElement->SetAttribute("Durability", item.durability);
|
||||
itemElement->SetAttribute("PositionX", item.position.x);
|
||||
itemElement->SetAttribute("PositionY", item.position.y);
|
||||
itemElement->SetAttribute("VelocityX", item.velocity.x);
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace game::resource::xml
|
||||
struct Item
|
||||
{
|
||||
int id{};
|
||||
int chewCount{};
|
||||
int durability{};
|
||||
glm::vec2 position{};
|
||||
glm::vec2 velocity{};
|
||||
float rotation{};
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace game::resource::xml
|
||||
int volume{50};
|
||||
bool isUseCharacterColor{true};
|
||||
|
||||
glm::vec3 color{0.120f, 0.515f, 0.115f};
|
||||
glm::vec3 color{0.120f, 0.120f, 0.120f};
|
||||
glm::ivec2 windowSize{1600, 900};
|
||||
glm::vec2 windowPosition{};
|
||||
|
||||
|
||||
48
src/resource/xml/strings.cpp
Normal file
48
src/resource/xml/strings.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
#include "strings.hpp"
|
||||
|
||||
#include "../../log.hpp"
|
||||
#include "util.hpp"
|
||||
|
||||
#include <format>
|
||||
|
||||
using namespace tinyxml2;
|
||||
|
||||
namespace game::resource::xml
|
||||
{
|
||||
namespace
|
||||
{
|
||||
std::string definition_element_name_get(const Strings::Definition& definition)
|
||||
{
|
||||
std::string name = definition.attribute;
|
||||
if (name.rfind("Text", 0) == 0) name.replace(0, 4, "String");
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
Strings::Strings()
|
||||
{
|
||||
for (int i = 0; i < Count; i++)
|
||||
values[i] = definitions[i].fallback;
|
||||
}
|
||||
|
||||
Strings::Strings(const util::physfs::Path& path)
|
||||
{
|
||||
for (int i = 0; i < Count; i++)
|
||||
values[i] = definitions[i].fallback;
|
||||
|
||||
XMLDocument document;
|
||||
if (document_load(path, document) != XML_SUCCESS) return;
|
||||
|
||||
auto root = document.RootElement();
|
||||
if (!root) return;
|
||||
|
||||
for (int i = 0; i < Count; i++)
|
||||
if (auto element = root->FirstChildElement(definition_element_name_get(definitions[i]).c_str()))
|
||||
query_string_attribute(element, "Text", &values[i]);
|
||||
|
||||
isValid = true;
|
||||
logger.info(std::format("Initialized strings: {}", path.c_str()));
|
||||
}
|
||||
|
||||
const std::string& Strings::get(Type type) const { return values[type]; }
|
||||
}
|
||||
159
src/resource/xml/strings.hpp
Normal file
159
src/resource/xml/strings.hpp
Normal file
@@ -0,0 +1,159 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../util/physfs.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <string>
|
||||
|
||||
namespace game::resource::xml
|
||||
{
|
||||
#define GAME_XML_STRING_LIST(X) \
|
||||
X(MenuTabInteract, "TextMenuTabInteract", "Interact") \
|
||||
X(MenuTabArcade, "TextMenuTabArcade", "Arcade") \
|
||||
X(MenuTabInventory, "TextMenuTabInventory", "Inventory") \
|
||||
X(MenuTabSettings, "TextMenuTabSettings", "Settings") \
|
||||
X(MenuTabCheats, "TextMenuTabCheats", "Cheats") \
|
||||
X(MenuTabDebug, "TextMenuTabDebug", "Debug") \
|
||||
X(MenuOpenTooltip, "TextMenuOpenTooltip", "Open Main Menu") \
|
||||
X(MenuCloseTooltip, "TextMenuCloseTooltip", "Close Main Menu") \
|
||||
X(InteractChatButton, "TextInteractChatButton", "Let's chat!") \
|
||||
X(InteractHelpButton, "TextInteractHelpButton", "Help") \
|
||||
X(InteractFeelingButton, "TextInteractFeelingButton", "How are you feeling?") \
|
||||
X(InteractWeightFormat, "TextInteractWeightFormat", "Weight: %0.2f %s (Stage: %i)") \
|
||||
X(InteractCapacityFormat, "TextInteractCapacityFormat", "Capacity: %0.0f kcal (Max: %0.0f kcal)") \
|
||||
X(InteractDigestionRateFormat, "TextInteractDigestionRateFormat", "Digestion Rate: %0.2f%%/sec") \
|
||||
X(InteractEatingSpeedFormat, "TextInteractEatingSpeedFormat", "Eating Speed: %0.2fx") \
|
||||
X(InteractTotalCaloriesFormat, "TextInteractTotalCaloriesFormat", "Total Calories Consumed: %0.0f kcal") \
|
||||
X(InteractTotalFoodItemsFormat, "TextInteractTotalFoodItemsFormat", "Total Food Items Eaten: %i") \
|
||||
X(SettingsMeasurementSystem, "TextSettingsMeasurementSystem", "Measurement System") \
|
||||
X(SettingsMetric, "TextSettingsMetric", "Metric") \
|
||||
X(SettingsMetricTooltip, "TextSettingsMetricTooltip", "Use kilograms (kg).") \
|
||||
X(SettingsImperial, "TextSettingsImperial", "Imperial") \
|
||||
X(SettingsImperialTooltip, "TextSettingsImperialTooltip", "Use pounds (lbs).") \
|
||||
X(SettingsSound, "TextSettingsSound", "Sound") \
|
||||
X(SettingsVolume, "TextSettingsVolume", "Volume") \
|
||||
X(SettingsVolumeTooltip, "TextSettingsVolumeTooltip", "Adjust master volume.") \
|
||||
X(SettingsAppearance, "TextSettingsAppearance", "Appearance") \
|
||||
X(SettingsUseCharacterColor, "TextSettingsUseCharacterColor", "Use Character Color") \
|
||||
X(SettingsUseCharacterColorTooltip, "TextSettingsUseCharacterColorTooltip", \
|
||||
"When playing, the UI will use the character's preset UI color.") \
|
||||
X(SettingsColor, "TextSettingsColor", "Color") \
|
||||
X(SettingsColorTooltip, "TextSettingsColorTooltip", "Change the UI color.") \
|
||||
X(SettingsResetButton, "TextSettingsResetButton", "Reset to Default") \
|
||||
X(SettingsSaveButton, "TextSettingsSaveButton", "Save") \
|
||||
X(SettingsSaveTooltip, "TextSettingsSaveTooltip", "Save the game.\n(Note: the game autosaves frequently.)") \
|
||||
X(SettingsReturnToCharactersButton, "TextSettingsReturnToCharactersButton", "Return to Characters") \
|
||||
X(SettingsReturnToCharactersTooltip, "TextSettingsReturnToCharactersTooltip", \
|
||||
"Go back to the character selection screen.\nProgress will be saved.") \
|
||||
X(ToastCheatsUnlocked, "TextToastCheatsUnlocked", "Cheats unlocked!") \
|
||||
X(ToastSaving, "TextToastSaving", "Saving...") \
|
||||
X(ToolsHomeButton, "TextToolsHomeButton", "Home") \
|
||||
X(ToolsHomeTooltip, "TextToolsHomeTooltip", "Reset camera view.\n(Shortcut: Home)") \
|
||||
X(ToolsOpenTooltip, "TextToolsOpenTooltip", "Open Tools") \
|
||||
X(ToolsCloseTooltip, "TextToolsCloseTooltip", "Close Tools") \
|
||||
X(DebugCursorScreenFormat, "TextDebugCursorScreenFormat", "Cursor Pos (Screen): %0.0f, %0.0f") \
|
||||
X(DebugCursorWorldFormat, "TextDebugCursorWorldFormat", "Cursor Pos (World): %0.0f, %0.0f") \
|
||||
X(DebugAnimations, "TextDebugAnimations", "Animations") \
|
||||
X(DebugNowPlayingFormat, "TextDebugNowPlayingFormat", "Now Playing: %s") \
|
||||
X(DebugDialogue, "TextDebugDialogue", "Dialogue") \
|
||||
X(DebugShowNulls, "TextDebugShowNulls", "Show Nulls (Hitboxes)") \
|
||||
X(DebugShowWorldBounds, "TextDebugShowWorldBounds", "Show World Bounds") \
|
||||
X(DebugItem, "TextDebugItem", "Item") \
|
||||
X(DebugHeld, "TextDebugHeld", "Held") \
|
||||
X(DebugItemTypeFormat, "TextDebugItemTypeFormat", "Type: %i") \
|
||||
X(DebugItemPositionFormat, "TextDebugItemPositionFormat", "Position: %0.0f, %0.0f") \
|
||||
X(DebugItemVelocityFormat, "TextDebugItemVelocityFormat", "Velocity: %0.0f, %0.0f") \
|
||||
X(DebugItemDurabilityFormat, "TextDebugItemDurabilityFormat", "Durability: %i") \
|
||||
X(InventoryEmptyHint, "TextInventoryEmptyHint", "Check the \"Arcade\" tab to earn rewards!") \
|
||||
X(InventoryFlavorFormat, "TextInventoryFlavorFormat", "Flavor: %s") \
|
||||
X(InventoryCaloriesFormat, "TextInventoryCaloriesFormat", "%0.0f kcal") \
|
||||
X(InventoryDurabilityFormat, "TextInventoryDurabilityFormat", "Durability: %i") \
|
||||
X(InventoryCapacityBonusFormat, "TextInventoryCapacityBonusFormat", "Capacity Bonus: +%0.0f kcal") \
|
||||
X(InventoryDigestionRateBonusFormat, "TextInventoryDigestionRateBonusFormat", "Digestion Rate Bonus: +%0.2f%% / sec") \
|
||||
X(InventoryDigestionRatePenaltyFormat, "TextInventoryDigestionRatePenaltyFormat", "Digestion Rate Penalty: %0.2f%% / sec") \
|
||||
X(InventoryEatSpeedBonusFormat, "TextInventoryEatSpeedBonusFormat", "Eat Speed Bonus: +%0.2f%% / sec") \
|
||||
X(InventoryEatSpeedPenaltyFormat, "TextInventoryEatSpeedPenaltyFormat", "Eat Speed Penalty: %0.2f%% / sec") \
|
||||
X(InventoryUpgradePreviewFormat, "TextInventoryUpgradePreviewFormat", "Upgrade: %ix -> %s") \
|
||||
X(InventoryUnknown, "TextInventoryUnknown", "???") \
|
||||
X(InventorySpawnButton, "TextInventorySpawnButton", "Spawn") \
|
||||
X(InventoryUpgradeButton, "TextInventoryUpgradeButton", "Upgrade") \
|
||||
X(InventoryUpgradeAllButton, "TextInventoryUpgradeAllButton", "Upgrade All") \
|
||||
X(InventoryUpgradeNoPath, "TextInventoryUpgradeNoPath", "This item cannot be upgraded.") \
|
||||
X(InventoryUpgradeNeedsTemplate, "TextInventoryUpgradeNeedsTemplate", "Needs {}x to upgrade into {}!") \
|
||||
X(InventoryUpgradeOneTemplate, "TextInventoryUpgradeOneTemplate", "Use {}x to upgrade into 1x {}.") \
|
||||
X(InventoryUpgradeAllTemplate, "TextInventoryUpgradeAllTemplate", "Use {}x to upgrade into {}x {}.") \
|
||||
X(ArcadeSkillCheckName, "TextArcadeSkillCheckName", "Skill Check") \
|
||||
X(ArcadeSkillCheckDescription, "TextArcadeSkillCheckDescription", \
|
||||
"Test your timing to build score, chain combos, and earn rewards based on your performance.") \
|
||||
X(ArcadePlayButton, "TextArcadePlayButton", "Play") \
|
||||
X(ArcadeStatsButton, "TextArcadeStatsButton", "Stats") \
|
||||
X(ArcadeBackButton, "TextArcadeBackButton", "Back") \
|
||||
X(ArcadeBestFormat, "TextArcadeBestFormat", "Best: %i pts (%ix)") \
|
||||
X(ArcadeTotalSkillChecksFormat, "TextArcadeTotalSkillChecksFormat", "Total Skill Checks: %i") \
|
||||
X(ArcadeAccuracyFormat, "TextArcadeAccuracyFormat", "Accuracy: %0.2f%%") \
|
||||
X(InfoProgressMax, "TextInfoProgressMax", "MAX") \
|
||||
X(InfoProgressToNextStage, "TextInfoProgressToNextStage", "To Next Stage") \
|
||||
X(InfoStageProgressFormat, "TextInfoStageProgressFormat", "Stage: %i/%i (%0.1f%%)") \
|
||||
X(InfoMaxedOut, "TextInfoMaxedOut", "Maxed out!") \
|
||||
X(InfoStageStartFormat, "TextInfoStageStartFormat", "Start: %0.2f %s") \
|
||||
X(InfoStageCurrentFormat, "TextInfoStageCurrentFormat", "Current: %0.2f %s") \
|
||||
X(InfoStageNextFormat, "TextInfoStageNextFormat", "Next: %0.2f %s") \
|
||||
X(InfoDigestion, "TextInfoDigestion", "Digestion") \
|
||||
X(InfoDigesting, "TextInfoDigesting", "Digesting...") \
|
||||
X(InfoDigestionInProgress, "TextInfoDigestionInProgress", "Digestion in progress...") \
|
||||
X(InfoGiveFoodToStartDigesting, "TextInfoGiveFoodToStartDigesting", "Give food to start digesting!") \
|
||||
X(InfoDigestionRateFormat, "TextInfoDigestionRateFormat", "Rate: %0.2f%% / sec") \
|
||||
X(InfoEatingSpeedFormat, "TextInfoEatingSpeedFormat", "Eating Speed: %0.2fx") \
|
||||
X(SkillCheckScoreFormat, "TextSkillCheckScoreFormat", "Score: %i pts (%ix)") \
|
||||
X(SkillCheckBestFormat, "TextSkillCheckBestFormat", "Best: %i pts (%ix)") \
|
||||
X(SkillCheckInstructions, "TextSkillCheckInstructions", "Match the line to the colored areas with Space/click! Better performance, better rewards!") \
|
||||
X(SkillCheckScoreLoss, "TextSkillCheckScoreLoss", "-1") \
|
||||
X(SkillCheckRewardToast, "TextSkillCheckRewardToast", "Fantastic score! Congratulations!") \
|
||||
X(SkillCheckHighScoreToast, "TextSkillCheckHighScoreToast", "High Score!") \
|
||||
X(SkillCheckGradeSuccessTemplate, "TextSkillCheckGradeSuccessTemplate", "{} (+{})") \
|
||||
X(SkillCheckMenuButton, "TextSkillCheckMenuButton", "Menu") \
|
||||
X(CheatsCalories, "TextCheatsCalories", "Calories") \
|
||||
X(CheatsCapacity, "TextCheatsCapacity", "Capacity") \
|
||||
X(CheatsWeight, "TextCheatsWeight", "Weight") \
|
||||
X(CheatsWeightFormat, "TextCheatsWeightFormat", "%0.2f kg") \
|
||||
X(CheatsStage, "TextCheatsStage", "Stage") \
|
||||
X(CheatsDigestionRate, "TextCheatsDigestionRate", "Digestion Rate") \
|
||||
X(CheatsDigestionRateFormat, "TextCheatsDigestionRateFormat", "%0.2f% / tick") \
|
||||
X(CheatsEatSpeed, "TextCheatsEatSpeed", "Eat Speed") \
|
||||
X(CheatsEatSpeedFormat, "TextCheatsEatSpeedFormat", "%0.2fx") \
|
||||
X(CheatsDigestButton, "TextCheatsDigestButton", "Digest") \
|
||||
X(CheatsInventory, "TextCheatsInventory", "Inventory")
|
||||
|
||||
class Strings
|
||||
{
|
||||
public:
|
||||
enum Type
|
||||
{
|
||||
#define X(type, attr, fallback) type,
|
||||
GAME_XML_STRING_LIST(X)
|
||||
#undef X
|
||||
Count
|
||||
};
|
||||
|
||||
struct Definition
|
||||
{
|
||||
const char* attribute;
|
||||
const char* fallback;
|
||||
};
|
||||
|
||||
inline static constexpr std::array<Definition, Count> definitions{{
|
||||
#define X(type, attr, fallback) {attr, fallback},
|
||||
GAME_XML_STRING_LIST(X)
|
||||
#undef X
|
||||
}};
|
||||
|
||||
std::array<std::string, Count> values{};
|
||||
|
||||
bool isValid{};
|
||||
|
||||
Strings();
|
||||
Strings(const util::physfs::Path&);
|
||||
|
||||
const std::string& get(Type) const;
|
||||
};
|
||||
}
|
||||
@@ -117,6 +117,29 @@ namespace game::resource::xml
|
||||
return result;
|
||||
}
|
||||
|
||||
XMLError query_optional_vec3(XMLElement* element, const char* attributeX, const char* attributeY,
|
||||
const char* attributeZ, std::optional<glm::vec3>& value)
|
||||
{
|
||||
auto hasX = element->FindAttribute(attributeX);
|
||||
auto hasY = element->FindAttribute(attributeY);
|
||||
auto hasZ = element->FindAttribute(attributeZ);
|
||||
|
||||
if (!hasX && !hasY && !hasZ)
|
||||
{
|
||||
value.reset();
|
||||
return XML_NO_ATTRIBUTE;
|
||||
}
|
||||
|
||||
value = glm::vec3();
|
||||
auto result = XML_SUCCESS;
|
||||
|
||||
if (hasX) result = query_result_merge(result, element->QueryFloatAttribute(attributeX, &value->x));
|
||||
if (hasY) result = query_result_merge(result, element->QueryFloatAttribute(attributeY, &value->y));
|
||||
if (hasZ) result = query_result_merge(result, element->QueryFloatAttribute(attributeZ, &value->z));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
XMLError document_load(const physfs::Path& path, XMLDocument& document)
|
||||
{
|
||||
if (!path.is_valid())
|
||||
|
||||
@@ -32,6 +32,8 @@ namespace game::resource::xml
|
||||
std::optional<float>& value);
|
||||
tinyxml2::XMLError query_int_optional_attribute(tinyxml2::XMLElement* element, const char* attribute,
|
||||
std::optional<int>& value);
|
||||
tinyxml2::XMLError query_optional_vec3(tinyxml2::XMLElement* element, const char* attributeX, const char* attributeY,
|
||||
const char* attributeZ, std::optional<glm::vec3>& value);
|
||||
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user