HarvestableInfo.xml, Achievements.xml, Loot.xml, NPCInfo.xml and Shops.xml.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,3 +4,4 @@ CBAssets
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
build
|
||||||
67
include/configs/achievements.hpp
Normal file
67
include/configs/achievements.hpp
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include <tinyxml2.h>
|
||||||
|
|
||||||
|
#include "constants.h"
|
||||||
|
|
||||||
|
namespace cursebreaker {
|
||||||
|
|
||||||
|
struct AchievementRequirement
|
||||||
|
{
|
||||||
|
ActionType action{};
|
||||||
|
uint16_t targetId{}; // e.g., item id, npc id, etc.
|
||||||
|
uint16_t count{};
|
||||||
|
std::string description;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Achievement
|
||||||
|
{
|
||||||
|
uint16_t id{};
|
||||||
|
uint16_t points{};
|
||||||
|
uint16_t category{};
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
std::string description;
|
||||||
|
std::string icon;
|
||||||
|
|
||||||
|
std::vector<AchievementRequirement> requirements;
|
||||||
|
|
||||||
|
Achievement() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Achievements configuration manager
|
||||||
|
class AchievementsConfig {
|
||||||
|
public:
|
||||||
|
static AchievementsConfig& getInstance() {
|
||||||
|
static AchievementsConfig instance;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool loadFromXML(const std::string& filepath);
|
||||||
|
const Achievement* getAchievementById(int id) const;
|
||||||
|
const std::unordered_map<int, Achievement>& getAllAchievements() const { return m_achievements; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
AchievementsConfig() = default;
|
||||||
|
~AchievementsConfig() = default;
|
||||||
|
AchievementsConfig(const AchievementsConfig&) = delete;
|
||||||
|
AchievementsConfig& operator=(const AchievementsConfig&) = delete;
|
||||||
|
|
||||||
|
std::unordered_map<int, Achievement> m_achievements;
|
||||||
|
|
||||||
|
// Helper methods for parsing
|
||||||
|
void parseAchievement(tinyxml2::XMLElement* achievementElement);
|
||||||
|
void parseRequirements(tinyxml2::XMLElement* achievementElement, Achievement& achievement);
|
||||||
|
std::string getAttributeValue(tinyxml2::XMLElement* element, const char* attribute, const std::string& defaultValue = "");
|
||||||
|
int getAttributeValueInt(tinyxml2::XMLElement* element, const char* attribute, int defaultValue = 0);
|
||||||
|
bool getAttributeValueBool(tinyxml2::XMLElement* element, const char* attribute, bool defaultValue = false);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper functions for enum conversions
|
||||||
|
ActionType stringToActionType(const std::string& str);
|
||||||
|
|
||||||
|
} // namespace cursebreaker
|
||||||
65
include/configs/harvestables.hpp
Normal file
65
include/configs/harvestables.hpp
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include <tinyxml2.h>
|
||||||
|
|
||||||
|
#include "constants.h"
|
||||||
|
#include "items.hpp" // for stringToSkillType
|
||||||
|
|
||||||
|
namespace cursebreaker {
|
||||||
|
|
||||||
|
struct HarvestableLootEntry
|
||||||
|
{
|
||||||
|
uint16_t itemId{};
|
||||||
|
uint16_t amount{};
|
||||||
|
uint16_t chance{}; // percentage chance
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Harvestable
|
||||||
|
{
|
||||||
|
uint16_t id{};
|
||||||
|
uint16_t level{};
|
||||||
|
uint16_t respawnTime{}; // in seconds or minutes, TBD
|
||||||
|
|
||||||
|
SkillType skill{};
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
std::string description;
|
||||||
|
|
||||||
|
std::vector<HarvestableLootEntry> loot;
|
||||||
|
|
||||||
|
Harvestable() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Harvestables configuration manager
|
||||||
|
class HarvestablesConfig {
|
||||||
|
public:
|
||||||
|
static HarvestablesConfig& getInstance() {
|
||||||
|
static HarvestablesConfig instance;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool loadFromXML(const std::string& filepath);
|
||||||
|
const Harvestable* getHarvestableById(int id) const;
|
||||||
|
const std::unordered_map<int, Harvestable>& getAllHarvestables() const { return m_harvestables; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
HarvestablesConfig() = default;
|
||||||
|
~HarvestablesConfig() = default;
|
||||||
|
HarvestablesConfig(const HarvestablesConfig&) = delete;
|
||||||
|
HarvestablesConfig& operator=(const HarvestablesConfig&) = delete;
|
||||||
|
|
||||||
|
std::unordered_map<int, Harvestable> m_harvestables;
|
||||||
|
|
||||||
|
// Helper methods for parsing
|
||||||
|
void parseHarvestable(tinyxml2::XMLElement* harvestableElement);
|
||||||
|
void parseLoot(tinyxml2::XMLElement* harvestableElement, Harvestable& harvestable);
|
||||||
|
std::string getAttributeValue(tinyxml2::XMLElement* element, const char* attribute, const std::string& defaultValue = "");
|
||||||
|
int getAttributeValueInt(tinyxml2::XMLElement* element, const char* attribute, int defaultValue = 0);
|
||||||
|
bool getAttributeValueBool(tinyxml2::XMLElement* element, const char* attribute, bool defaultValue = false);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace cursebreaker
|
||||||
61
include/configs/loot.hpp
Normal file
61
include/configs/loot.hpp
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include <tinyxml2.h>
|
||||||
|
|
||||||
|
#include "constants.h"
|
||||||
|
|
||||||
|
namespace cursebreaker {
|
||||||
|
|
||||||
|
struct LootEntry
|
||||||
|
{
|
||||||
|
uint16_t itemId{};
|
||||||
|
uint16_t minAmount{};
|
||||||
|
uint16_t maxAmount{};
|
||||||
|
uint16_t chance{}; // percentage chance
|
||||||
|
uint16_t level{}; // minimum level required
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LootTable
|
||||||
|
{
|
||||||
|
uint16_t id{};
|
||||||
|
std::string name;
|
||||||
|
std::string description;
|
||||||
|
|
||||||
|
std::vector<LootEntry> entries;
|
||||||
|
|
||||||
|
LootTable() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Loot configuration manager
|
||||||
|
class LootConfig {
|
||||||
|
public:
|
||||||
|
static LootConfig& getInstance() {
|
||||||
|
static LootConfig instance;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool loadFromXML(const std::string& filepath);
|
||||||
|
const LootTable* getLootTableById(int id) const;
|
||||||
|
const std::unordered_map<int, LootTable>& getAllLootTables() const { return m_lootTables; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
LootConfig() = default;
|
||||||
|
~LootConfig() = default;
|
||||||
|
LootConfig(const LootConfig&) = delete;
|
||||||
|
LootConfig& operator=(const LootConfig&) = delete;
|
||||||
|
|
||||||
|
std::unordered_map<int, LootTable> m_lootTables;
|
||||||
|
|
||||||
|
// Helper methods for parsing
|
||||||
|
void parseLootTable(tinyxml2::XMLElement* lootTableElement);
|
||||||
|
void parseEntries(tinyxml2::XMLElement* lootTableElement, LootTable& lootTable);
|
||||||
|
std::string getAttributeValue(tinyxml2::XMLElement* element, const char* attribute, const std::string& defaultValue = "");
|
||||||
|
int getAttributeValueInt(tinyxml2::XMLElement* element, const char* attribute, int defaultValue = 0);
|
||||||
|
bool getAttributeValueBool(tinyxml2::XMLElement* element, const char* attribute, bool defaultValue = false);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace cursebreaker
|
||||||
68
include/configs/npcs.hpp
Normal file
68
include/configs/npcs.hpp
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include <tinyxml2.h>
|
||||||
|
|
||||||
|
#include "constants.h"
|
||||||
|
#include "items.hpp" // for stringToStatType
|
||||||
|
|
||||||
|
namespace cursebreaker {
|
||||||
|
|
||||||
|
struct NPCStat
|
||||||
|
{
|
||||||
|
StatType type{};
|
||||||
|
uint16_t value{};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct NPC
|
||||||
|
{
|
||||||
|
uint16_t id{};
|
||||||
|
uint16_t level{};
|
||||||
|
uint16_t health{};
|
||||||
|
uint16_t mana{};
|
||||||
|
uint16_t experience{};
|
||||||
|
uint16_t lootTableId{};
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
std::string description;
|
||||||
|
std::string faction;
|
||||||
|
|
||||||
|
std::vector<NPCStat> stats;
|
||||||
|
std::vector<uint16_t> lootItems; // alternative simple loot
|
||||||
|
|
||||||
|
NPC() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
// NPCs configuration manager
|
||||||
|
class NPCsConfig {
|
||||||
|
public:
|
||||||
|
static NPCsConfig& getInstance() {
|
||||||
|
static NPCsConfig instance;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool loadFromXML(const std::string& filepath);
|
||||||
|
const NPC* getNPCById(int id) const;
|
||||||
|
const std::unordered_map<int, NPC>& getAllNPCs() const { return m_npcs; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
NPCsConfig() = default;
|
||||||
|
~NPCsConfig() = default;
|
||||||
|
NPCsConfig(const NPCsConfig&) = delete;
|
||||||
|
NPCsConfig& operator=(const NPCsConfig&) = delete;
|
||||||
|
|
||||||
|
std::unordered_map<int, NPC> m_npcs;
|
||||||
|
|
||||||
|
// Helper methods for parsing
|
||||||
|
void parseNPC(tinyxml2::XMLElement* npcElement);
|
||||||
|
void parseStats(tinyxml2::XMLElement* npcElement, NPC& npc);
|
||||||
|
void parseLoot(tinyxml2::XMLElement* npcElement, NPC& npc);
|
||||||
|
std::string getAttributeValue(tinyxml2::XMLElement* element, const char* attribute, const std::string& defaultValue = "");
|
||||||
|
int getAttributeValueInt(tinyxml2::XMLElement* element, const char* attribute, int defaultValue = 0);
|
||||||
|
bool getAttributeValueBool(tinyxml2::XMLElement* element, const char* attribute, bool defaultValue = false);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace cursebreaker
|
||||||
61
include/configs/shops.hpp
Normal file
61
include/configs/shops.hpp
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include <tinyxml2.h>
|
||||||
|
|
||||||
|
#include "constants.h"
|
||||||
|
|
||||||
|
namespace cursebreaker {
|
||||||
|
|
||||||
|
struct ShopItem
|
||||||
|
{
|
||||||
|
uint16_t itemId{};
|
||||||
|
uint16_t price{};
|
||||||
|
uint16_t stock{}; // -1 for unlimited
|
||||||
|
uint16_t levelRequired{};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Shop
|
||||||
|
{
|
||||||
|
uint16_t id{};
|
||||||
|
std::string name;
|
||||||
|
std::string description;
|
||||||
|
std::string location;
|
||||||
|
|
||||||
|
std::vector<ShopItem> inventory;
|
||||||
|
|
||||||
|
Shop() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Shops configuration manager
|
||||||
|
class ShopsConfig {
|
||||||
|
public:
|
||||||
|
static ShopsConfig& getInstance() {
|
||||||
|
static ShopsConfig instance;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool loadFromXML(const std::string& filepath);
|
||||||
|
const Shop* getShopById(int id) const;
|
||||||
|
const std::unordered_map<int, Shop>& getAllShops() const { return m_shops; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
ShopsConfig() = default;
|
||||||
|
~ShopsConfig() = default;
|
||||||
|
ShopsConfig(const ShopsConfig&) = delete;
|
||||||
|
ShopsConfig& operator=(const ShopsConfig&) = delete;
|
||||||
|
|
||||||
|
std::unordered_map<int, Shop> m_shops;
|
||||||
|
|
||||||
|
// Helper methods for parsing
|
||||||
|
void parseShop(tinyxml2::XMLElement* shopElement);
|
||||||
|
void parseInventory(tinyxml2::XMLElement* shopElement, Shop& shop);
|
||||||
|
std::string getAttributeValue(tinyxml2::XMLElement* element, const char* attribute, const std::string& defaultValue = "");
|
||||||
|
int getAttributeValueInt(tinyxml2::XMLElement* element, const char* attribute, int defaultValue = 0);
|
||||||
|
bool getAttributeValueBool(tinyxml2::XMLElement* element, const char* attribute, bool defaultValue = false);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace cursebreaker
|
||||||
122
src/configs/achievements.cpp
Normal file
122
src/configs/achievements.cpp
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
#include "configs/achievements.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
namespace cursebreaker {
|
||||||
|
|
||||||
|
ActionType stringToActionType(const std::string& str) {
|
||||||
|
static const std::unordered_map<std::string, ActionType> actionMap = {
|
||||||
|
{"NpcDeath", ActionType::NpcDeath},
|
||||||
|
{"PlayerDeath", ActionType::PlayerDeath},
|
||||||
|
{"PlayerRespawn", ActionType::PlayerRespawn},
|
||||||
|
{"NpcInteract", ActionType::NpcInteract},
|
||||||
|
{"QuestUpdate", ActionType::QuestUpdate},
|
||||||
|
{"QuestTimerEnd", ActionType::QuestTimerEnd},
|
||||||
|
{"UseItemOnItem", ActionType::UseItemOnItem},
|
||||||
|
{"UseItemOnNpc", ActionType::UseItemOnNpc},
|
||||||
|
{"ConsumeItem", ActionType::ConsumeItem},
|
||||||
|
{"NpcCombatInteract", ActionType::NpcCombatInteract},
|
||||||
|
{"NpcKilledByPlayer", ActionType::NpcKilledByPlayer},
|
||||||
|
{"EnterMap", ActionType::EnterMap},
|
||||||
|
{"VarUpdated", ActionType::VarUpdated},
|
||||||
|
{"GrantAchievement", ActionType::GrantAchievement},
|
||||||
|
{"PlayerKilledByNpc", ActionType::PlayerKilledByNpc},
|
||||||
|
{"UseItem", ActionType::UseItem},
|
||||||
|
{"CraftItem", ActionType::CraftItem},
|
||||||
|
{"HarvestItem", ActionType::HarvestItem},
|
||||||
|
{"BuyItem", ActionType::BuyItem},
|
||||||
|
{"NpcTagKilledByPlayer", ActionType::NpcTagKilledByPlayer},
|
||||||
|
{"UseAbility", ActionType::UseAbility},
|
||||||
|
{"LootItem", ActionType::LootItem},
|
||||||
|
{"UseItemCategoryOnItem", ActionType::UseItemCategoryOnItem}
|
||||||
|
};
|
||||||
|
|
||||||
|
auto it = actionMap.find(str);
|
||||||
|
return (it != actionMap.end()) ? it->second : ActionType::none;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AchievementsConfig::loadFromXML(const std::string& filepath) {
|
||||||
|
tinyxml2::XMLDocument doc;
|
||||||
|
tinyxml2::XMLError result = doc.LoadFile(filepath.c_str());
|
||||||
|
|
||||||
|
if (result != tinyxml2::XML_SUCCESS) {
|
||||||
|
std::cerr << "Failed to load achievements XML file: " << filepath << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
tinyxml2::XMLElement* root = doc.FirstChildElement("achievements");
|
||||||
|
if (!root) {
|
||||||
|
std::cerr << "Invalid XML structure: missing 'achievements' root element" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_achievements.clear();
|
||||||
|
|
||||||
|
// Parse all achievements
|
||||||
|
for (tinyxml2::XMLElement* achievementElement = root->FirstChildElement("achievement");
|
||||||
|
achievementElement != nullptr;
|
||||||
|
achievementElement = achievementElement->NextSiblingElement("achievement")) {
|
||||||
|
parseAchievement(achievementElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Loaded " << m_achievements.size() << " achievements from XML" << std::endl;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AchievementsConfig::parseAchievement(tinyxml2::XMLElement* achievementElement) {
|
||||||
|
Achievement achievement;
|
||||||
|
|
||||||
|
// Parse basic attributes
|
||||||
|
achievement.id = static_cast<uint16_t>(getAttributeValueInt(achievementElement, "id"));
|
||||||
|
achievement.name = getAttributeValue(achievementElement, "name");
|
||||||
|
achievement.description = getAttributeValue(achievementElement, "description");
|
||||||
|
achievement.icon = getAttributeValue(achievementElement, "icon");
|
||||||
|
|
||||||
|
// Parse numeric attributes
|
||||||
|
achievement.points = static_cast<uint16_t>(getAttributeValueInt(achievementElement, "points"));
|
||||||
|
achievement.category = static_cast<uint16_t>(getAttributeValueInt(achievementElement, "category"));
|
||||||
|
|
||||||
|
// Parse child elements
|
||||||
|
parseRequirements(achievementElement, achievement);
|
||||||
|
|
||||||
|
m_achievements[achievement.id] = std::move(achievement);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AchievementsConfig::parseRequirements(tinyxml2::XMLElement* achievementElement, Achievement& achievement) {
|
||||||
|
for (tinyxml2::XMLElement* reqElement = achievementElement->FirstChildElement("requirement");
|
||||||
|
reqElement != nullptr;
|
||||||
|
reqElement = reqElement->NextSiblingElement("requirement")) {
|
||||||
|
|
||||||
|
AchievementRequirement req;
|
||||||
|
req.action = stringToActionType(getAttributeValue(reqElement, "action"));
|
||||||
|
req.targetId = static_cast<uint16_t>(getAttributeValueInt(reqElement, "targetid"));
|
||||||
|
req.count = static_cast<uint16_t>(getAttributeValueInt(reqElement, "count"));
|
||||||
|
req.description = getAttributeValue(reqElement, "description");
|
||||||
|
|
||||||
|
achievement.requirements.push_back(req);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Achievement* AchievementsConfig::getAchievementById(int id) const {
|
||||||
|
auto it = m_achievements.find(id);
|
||||||
|
return (it != m_achievements.end()) ? &it->second : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string AchievementsConfig::getAttributeValue(tinyxml2::XMLElement* element, const char* attribute, const std::string& defaultValue) {
|
||||||
|
const char* value = element->Attribute(attribute);
|
||||||
|
return value ? std::string(value) : defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int AchievementsConfig::getAttributeValueInt(tinyxml2::XMLElement* element, const char* attribute, int defaultValue) {
|
||||||
|
int value = defaultValue;
|
||||||
|
element->QueryIntAttribute(attribute, &value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AchievementsConfig::getAttributeValueBool(tinyxml2::XMLElement* element, const char* attribute, bool defaultValue) {
|
||||||
|
bool value = defaultValue;
|
||||||
|
element->QueryBoolAttribute(attribute, &value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cursebreaker
|
||||||
91
src/configs/harvestables.cpp
Normal file
91
src/configs/harvestables.cpp
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
#include "configs/harvestables.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace cursebreaker {
|
||||||
|
|
||||||
|
bool HarvestablesConfig::loadFromXML(const std::string& filepath) {
|
||||||
|
tinyxml2::XMLDocument doc;
|
||||||
|
tinyxml2::XMLError result = doc.LoadFile(filepath.c_str());
|
||||||
|
|
||||||
|
if (result != tinyxml2::XML_SUCCESS) {
|
||||||
|
std::cerr << "Failed to load harvestables XML file: " << filepath << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
tinyxml2::XMLElement* root = doc.FirstChildElement("harvestables");
|
||||||
|
if (!root) {
|
||||||
|
std::cerr << "Invalid XML structure: missing 'harvestables' root element" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_harvestables.clear();
|
||||||
|
|
||||||
|
// Parse all harvestables
|
||||||
|
for (tinyxml2::XMLElement* harvestableElement = root->FirstChildElement("harvestable");
|
||||||
|
harvestableElement != nullptr;
|
||||||
|
harvestableElement = harvestableElement->NextSiblingElement("harvestable")) {
|
||||||
|
parseHarvestable(harvestableElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Loaded " << m_harvestables.size() << " harvestables from XML" << std::endl;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HarvestablesConfig::parseHarvestable(tinyxml2::XMLElement* harvestableElement) {
|
||||||
|
Harvestable harvestable;
|
||||||
|
|
||||||
|
// Parse basic attributes
|
||||||
|
harvestable.id = static_cast<uint16_t>(getAttributeValueInt(harvestableElement, "id"));
|
||||||
|
harvestable.name = getAttributeValue(harvestableElement, "name");
|
||||||
|
harvestable.description = getAttributeValue(harvestableElement, "description");
|
||||||
|
harvestable.skill = stringToSkillType(getAttributeValue(harvestableElement, "skill"));
|
||||||
|
|
||||||
|
// Parse numeric attributes
|
||||||
|
harvestable.level = static_cast<uint16_t>(getAttributeValueInt(harvestableElement, "level"));
|
||||||
|
harvestable.respawnTime = static_cast<uint16_t>(getAttributeValueInt(harvestableElement, "respawntime"));
|
||||||
|
|
||||||
|
// Parse child elements
|
||||||
|
parseLoot(harvestableElement, harvestable);
|
||||||
|
|
||||||
|
m_harvestables[harvestable.id] = std::move(harvestable);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HarvestablesConfig::parseLoot(tinyxml2::XMLElement* harvestableElement, Harvestable& harvestable) {
|
||||||
|
for (tinyxml2::XMLElement* lootElement = harvestableElement->FirstChildElement("loot");
|
||||||
|
lootElement != nullptr;
|
||||||
|
lootElement = lootElement->NextSiblingElement("loot")) {
|
||||||
|
|
||||||
|
HarvestableLootEntry lootEntry;
|
||||||
|
lootEntry.itemId = static_cast<uint16_t>(getAttributeValueInt(lootElement, "itemid"));
|
||||||
|
lootEntry.amount = static_cast<uint16_t>(getAttributeValueInt(lootElement, "amount"));
|
||||||
|
lootEntry.chance = static_cast<uint16_t>(getAttributeValueInt(lootElement, "chance"));
|
||||||
|
|
||||||
|
harvestable.loot.push_back(lootEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Harvestable* HarvestablesConfig::getHarvestableById(int id) const {
|
||||||
|
auto it = m_harvestables.find(id);
|
||||||
|
return (it != m_harvestables.end()) ? &it->second : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string HarvestablesConfig::getAttributeValue(tinyxml2::XMLElement* element, const char* attribute, const std::string& defaultValue) {
|
||||||
|
const char* value = element->Attribute(attribute);
|
||||||
|
return value ? std::string(value) : defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int HarvestablesConfig::getAttributeValueInt(tinyxml2::XMLElement* element, const char* attribute, int defaultValue) {
|
||||||
|
int value = defaultValue;
|
||||||
|
element->QueryIntAttribute(attribute, &value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HarvestablesConfig::getAttributeValueBool(tinyxml2::XMLElement* element, const char* attribute, bool defaultValue) {
|
||||||
|
bool value = defaultValue;
|
||||||
|
element->QueryBoolAttribute(attribute, &value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cursebreaker
|
||||||
86
src/configs/loot.cpp
Normal file
86
src/configs/loot.cpp
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
#include "configs/loot.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace cursebreaker {
|
||||||
|
|
||||||
|
bool LootConfig::loadFromXML(const std::string& filepath) {
|
||||||
|
tinyxml2::XMLDocument doc;
|
||||||
|
tinyxml2::XMLError result = doc.LoadFile(filepath.c_str());
|
||||||
|
|
||||||
|
if (result != tinyxml2::XML_SUCCESS) {
|
||||||
|
std::cerr << "Failed to load loot XML file: " << filepath << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
tinyxml2::XMLElement* root = doc.FirstChildElement("lootTables");
|
||||||
|
if (!root) {
|
||||||
|
std::cerr << "Invalid XML structure: missing 'lootTables' root element" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_lootTables.clear();
|
||||||
|
|
||||||
|
// Parse all loot tables
|
||||||
|
for (tinyxml2::XMLElement* lootTableElement = root->FirstChildElement("lootTable");
|
||||||
|
lootTableElement != nullptr;
|
||||||
|
lootTableElement = lootTableElement->NextSiblingElement("lootTable")) {
|
||||||
|
parseLootTable(lootTableElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Loaded " << m_lootTables.size() << " loot tables from XML" << std::endl;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LootConfig::parseLootTable(tinyxml2::XMLElement* lootTableElement) {
|
||||||
|
LootTable lootTable;
|
||||||
|
|
||||||
|
// Parse basic attributes
|
||||||
|
lootTable.id = static_cast<uint16_t>(getAttributeValueInt(lootTableElement, "id"));
|
||||||
|
lootTable.name = getAttributeValue(lootTableElement, "name");
|
||||||
|
lootTable.description = getAttributeValue(lootTableElement, "description");
|
||||||
|
|
||||||
|
// Parse child elements
|
||||||
|
parseEntries(lootTableElement, lootTable);
|
||||||
|
|
||||||
|
m_lootTables[lootTable.id] = std::move(lootTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LootConfig::parseEntries(tinyxml2::XMLElement* lootTableElement, LootTable& lootTable) {
|
||||||
|
for (tinyxml2::XMLElement* entryElement = lootTableElement->FirstChildElement("entry");
|
||||||
|
entryElement != nullptr;
|
||||||
|
entryElement = entryElement->NextSiblingElement("entry")) {
|
||||||
|
|
||||||
|
LootEntry entry;
|
||||||
|
entry.itemId = static_cast<uint16_t>(getAttributeValueInt(entryElement, "itemid"));
|
||||||
|
entry.minAmount = static_cast<uint16_t>(getAttributeValueInt(entryElement, "minamount"));
|
||||||
|
entry.maxAmount = static_cast<uint16_t>(getAttributeValueInt(entryElement, "maxamount"));
|
||||||
|
entry.chance = static_cast<uint16_t>(getAttributeValueInt(entryElement, "chance"));
|
||||||
|
entry.level = static_cast<uint16_t>(getAttributeValueInt(entryElement, "level"));
|
||||||
|
|
||||||
|
lootTable.entries.push_back(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const LootTable* LootConfig::getLootTableById(int id) const {
|
||||||
|
auto it = m_lootTables.find(id);
|
||||||
|
return (it != m_lootTables.end()) ? &it->second : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string LootConfig::getAttributeValue(tinyxml2::XMLElement* element, const char* attribute, const std::string& defaultValue) {
|
||||||
|
const char* value = element->Attribute(attribute);
|
||||||
|
return value ? std::string(value) : defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int LootConfig::getAttributeValueInt(tinyxml2::XMLElement* element, const char* attribute, int defaultValue) {
|
||||||
|
int value = defaultValue;
|
||||||
|
element->QueryIntAttribute(attribute, &value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LootConfig::getAttributeValueBool(tinyxml2::XMLElement* element, const char* attribute, bool defaultValue) {
|
||||||
|
bool value = defaultValue;
|
||||||
|
element->QueryBoolAttribute(attribute, &value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cursebreaker
|
||||||
111
src/configs/npcs.cpp
Normal file
111
src/configs/npcs.cpp
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
#include "configs/npcs.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace cursebreaker {
|
||||||
|
|
||||||
|
bool NPCsConfig::loadFromXML(const std::string& filepath) {
|
||||||
|
tinyxml2::XMLDocument doc;
|
||||||
|
tinyxml2::XMLError result = doc.LoadFile(filepath.c_str());
|
||||||
|
|
||||||
|
if (result != tinyxml2::XML_SUCCESS) {
|
||||||
|
std::cerr << "Failed to load NPCs XML file: " << filepath << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
tinyxml2::XMLElement* root = doc.FirstChildElement("npcs");
|
||||||
|
if (!root) {
|
||||||
|
std::cerr << "Invalid XML structure: missing 'npcs' root element" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_npcs.clear();
|
||||||
|
|
||||||
|
// Parse all NPCs
|
||||||
|
for (tinyxml2::XMLElement* npcElement = root->FirstChildElement("npc");
|
||||||
|
npcElement != nullptr;
|
||||||
|
npcElement = npcElement->NextSiblingElement("npc")) {
|
||||||
|
parseNPC(npcElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Loaded " << m_npcs.size() << " NPCs from XML" << std::endl;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NPCsConfig::parseNPC(tinyxml2::XMLElement* npcElement) {
|
||||||
|
NPC npc;
|
||||||
|
|
||||||
|
// Parse basic attributes
|
||||||
|
npc.id = static_cast<uint16_t>(getAttributeValueInt(npcElement, "id"));
|
||||||
|
npc.name = getAttributeValue(npcElement, "name");
|
||||||
|
npc.description = getAttributeValue(npcElement, "description");
|
||||||
|
npc.faction = getAttributeValue(npcElement, "faction");
|
||||||
|
|
||||||
|
// Parse numeric attributes
|
||||||
|
npc.level = static_cast<uint16_t>(getAttributeValueInt(npcElement, "level"));
|
||||||
|
npc.health = static_cast<uint16_t>(getAttributeValueInt(npcElement, "health"));
|
||||||
|
npc.mana = static_cast<uint16_t>(getAttributeValueInt(npcElement, "mana"));
|
||||||
|
npc.experience = static_cast<uint16_t>(getAttributeValueInt(npcElement, "experience"));
|
||||||
|
npc.lootTableId = static_cast<uint16_t>(getAttributeValueInt(npcElement, "loottableid"));
|
||||||
|
|
||||||
|
// Parse child elements
|
||||||
|
parseStats(npcElement, npc);
|
||||||
|
parseLoot(npcElement, npc);
|
||||||
|
|
||||||
|
m_npcs[npc.id] = std::move(npc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NPCsConfig::parseStats(tinyxml2::XMLElement* npcElement, NPC& npc) {
|
||||||
|
for (tinyxml2::XMLElement* statElement = npcElement->FirstChildElement("stat");
|
||||||
|
statElement != nullptr;
|
||||||
|
statElement = statElement->NextSiblingElement("stat")) {
|
||||||
|
|
||||||
|
NPCStat stat;
|
||||||
|
std::string statTypeStr = getAttributeValue(statElement, "type");
|
||||||
|
stat.type = stringToStatType(statTypeStr);
|
||||||
|
stat.value = static_cast<uint16_t>(getAttributeValueInt(statElement, "value"));
|
||||||
|
|
||||||
|
npc.stats.push_back(stat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NPCsConfig::parseLoot(tinyxml2::XMLElement* npcElement, NPC& npc) {
|
||||||
|
std::string lootItemsStr = getAttributeValue(npcElement, "lootitems");
|
||||||
|
if (!lootItemsStr.empty()) {
|
||||||
|
std::stringstream ss(lootItemsStr);
|
||||||
|
std::string itemStr;
|
||||||
|
while (std::getline(ss, itemStr, ',')) {
|
||||||
|
try {
|
||||||
|
uint16_t itemId = static_cast<uint16_t>(std::stoi(itemStr));
|
||||||
|
npc.lootItems.push_back(itemId);
|
||||||
|
} catch (const std::exception&) {
|
||||||
|
// Skip invalid items
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const NPC* NPCsConfig::getNPCById(int id) const {
|
||||||
|
auto it = m_npcs.find(id);
|
||||||
|
return (it != m_npcs.end()) ? &it->second : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string NPCsConfig::getAttributeValue(tinyxml2::XMLElement* element, const char* attribute, const std::string& defaultValue) {
|
||||||
|
const char* value = element->Attribute(attribute);
|
||||||
|
return value ? std::string(value) : defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int NPCsConfig::getAttributeValueInt(tinyxml2::XMLElement* element, const char* attribute, int defaultValue) {
|
||||||
|
int value = defaultValue;
|
||||||
|
element->QueryIntAttribute(attribute, &value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NPCsConfig::getAttributeValueBool(tinyxml2::XMLElement* element, const char* attribute, bool defaultValue) {
|
||||||
|
bool value = defaultValue;
|
||||||
|
element->QueryBoolAttribute(attribute, &value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cursebreaker
|
||||||
86
src/configs/shops.cpp
Normal file
86
src/configs/shops.cpp
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
#include "configs/shops.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace cursebreaker {
|
||||||
|
|
||||||
|
bool ShopsConfig::loadFromXML(const std::string& filepath) {
|
||||||
|
tinyxml2::XMLDocument doc;
|
||||||
|
tinyxml2::XMLError result = doc.LoadFile(filepath.c_str());
|
||||||
|
|
||||||
|
if (result != tinyxml2::XML_SUCCESS) {
|
||||||
|
std::cerr << "Failed to load shops XML file: " << filepath << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
tinyxml2::XMLElement* root = doc.FirstChildElement("shops");
|
||||||
|
if (!root) {
|
||||||
|
std::cerr << "Invalid XML structure: missing 'shops' root element" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_shops.clear();
|
||||||
|
|
||||||
|
// Parse all shops
|
||||||
|
for (tinyxml2::XMLElement* shopElement = root->FirstChildElement("shop");
|
||||||
|
shopElement != nullptr;
|
||||||
|
shopElement = shopElement->NextSiblingElement("shop")) {
|
||||||
|
parseShop(shopElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Loaded " << m_shops.size() << " shops from XML" << std::endl;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShopsConfig::parseShop(tinyxml2::XMLElement* shopElement) {
|
||||||
|
Shop shop;
|
||||||
|
|
||||||
|
// Parse basic attributes
|
||||||
|
shop.id = static_cast<uint16_t>(getAttributeValueInt(shopElement, "id"));
|
||||||
|
shop.name = getAttributeValue(shopElement, "name");
|
||||||
|
shop.description = getAttributeValue(shopElement, "description");
|
||||||
|
shop.location = getAttributeValue(shopElement, "location");
|
||||||
|
|
||||||
|
// Parse child elements
|
||||||
|
parseInventory(shopElement, shop);
|
||||||
|
|
||||||
|
m_shops[shop.id] = std::move(shop);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShopsConfig::parseInventory(tinyxml2::XMLElement* shopElement, Shop& shop) {
|
||||||
|
for (tinyxml2::XMLElement* itemElement = shopElement->FirstChildElement("item");
|
||||||
|
itemElement != nullptr;
|
||||||
|
itemElement = itemElement->NextSiblingElement("item")) {
|
||||||
|
|
||||||
|
ShopItem item;
|
||||||
|
item.itemId = static_cast<uint16_t>(getAttributeValueInt(itemElement, "itemid"));
|
||||||
|
item.price = static_cast<uint16_t>(getAttributeValueInt(itemElement, "price"));
|
||||||
|
item.stock = static_cast<uint16_t>(getAttributeValueInt(itemElement, "stock"));
|
||||||
|
item.levelRequired = static_cast<uint16_t>(getAttributeValueInt(itemElement, "levelrequired"));
|
||||||
|
|
||||||
|
shop.inventory.push_back(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Shop* ShopsConfig::getShopById(int id) const {
|
||||||
|
auto it = m_shops.find(id);
|
||||||
|
return (it != m_shops.end()) ? &it->second : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ShopsConfig::getAttributeValue(tinyxml2::XMLElement* element, const char* attribute, const std::string& defaultValue) {
|
||||||
|
const char* value = element->Attribute(attribute);
|
||||||
|
return value ? std::string(value) : defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ShopsConfig::getAttributeValueInt(tinyxml2::XMLElement* element, const char* attribute, int defaultValue) {
|
||||||
|
int value = defaultValue;
|
||||||
|
element->QueryIntAttribute(attribute, &value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ShopsConfig::getAttributeValueBool(tinyxml2::XMLElement* element, const char* attribute, bool defaultValue) {
|
||||||
|
bool value = defaultValue;
|
||||||
|
element->QueryBoolAttribute(attribute, &value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cursebreaker
|
||||||
Reference in New Issue
Block a user