#include "configs/npcs.hpp" #include "project_parser.h" #include "helpers.hpp" #include #include #include 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(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(getAttributeValueInt(npcElement, "level")); npc.health = static_cast(getAttributeValueInt(npcElement, "health")); npc.mana = static_cast(getAttributeValueInt(npcElement, "mana")); npc.experience = static_cast(getAttributeValueInt(npcElement, "experience")); npc.lootTableId = static_cast(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(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(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& 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