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