125 lines
4.5 KiB
C++
125 lines
4.5 KiB
C++
#include "configs/npcs.hpp"
|
|
#include "project_parser.h"
|
|
#include "helpers.hpp"
|
|
#include <iostream>
|
|
#include <sstream>
|
|
#include <algorithm>
|
|
|
|
namespace cursebreaker {
|
|
|
|
// Static helper functions
|
|
static std::string getAttributeValue(tinyxml2::XMLElement* element, const char* attribute, const std::string& defaultValue = "");
|
|
static int getAttributeValueInt(tinyxml2::XMLElement* element, const char* attribute, int defaultValue = 0);
|
|
static bool getAttributeValueBool(tinyxml2::XMLElement* element, const char* attribute, bool defaultValue = false);
|
|
static void parseNPC(tinyxml2::XMLElement* npcElement);
|
|
static void parseStats(tinyxml2::XMLElement* npcElement, NPC& npc);
|
|
static void parseLoot(tinyxml2::XMLElement* npcElement, NPC& npc);
|
|
|
|
bool loadNPCsFromXML(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;
|
|
}
|
|
|
|
g_parsedProject.m_npcs.clear();
|
|
|
|
// Parse all NPCs
|
|
for (tinyxml2::XMLElement* npcElement = root->FirstChildElement("npc");
|
|
npcElement != nullptr;
|
|
npcElement = npcElement->NextSiblingElement("npc")) {
|
|
parseNPC(npcElement);
|
|
}
|
|
|
|
std::cout << "Loaded " << g_parsedProject.m_npcs.size() << " NPCs from XML" << std::endl;
|
|
return true;
|
|
}
|
|
|
|
void 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);
|
|
|
|
g_parsedProject.m_npcs[npc.id] = std::move(npc);
|
|
}
|
|
|
|
void 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 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* getNPCById(uint16_t id) {
|
|
auto it = g_parsedProject.m_npcs.find(id);
|
|
return (it != g_parsedProject.m_npcs.end()) ? &it->second : nullptr;
|
|
}
|
|
|
|
const std::unordered_map<uint16_t, NPC>& getAllNPCs() {
|
|
return g_parsedProject.m_npcs;
|
|
}
|
|
|
|
std::string getAttributeValue(tinyxml2::XMLElement* element, const char* attribute, const std::string& defaultValue) {
|
|
const char* value = element->Attribute(attribute);
|
|
return value ? std::string(value) : defaultValue;
|
|
}
|
|
|
|
int getAttributeValueInt(tinyxml2::XMLElement* element, const char* attribute, int defaultValue) {
|
|
int value = defaultValue;
|
|
element->QueryIntAttribute(attribute, &value);
|
|
return value;
|
|
}
|
|
|
|
bool getAttributeValueBool(tinyxml2::XMLElement* element, const char* attribute, bool defaultValue) {
|
|
bool value = defaultValue;
|
|
element->QueryBoolAttribute(attribute, &value);
|
|
return value;
|
|
}
|
|
|
|
} // namespace cursebreaker
|