From 6ff762ba5748eb03f07801669a366935b98fb846 Mon Sep 17 00:00:00 2001 From: Gent S Date: Wed, 25 Nov 2020 10:41:10 -0500 Subject: [PATCH] Save gruntwork group mobs hierarchically --- src/ChatManager.cpp | 12 +++++-- src/TableData.cpp | 77 ++++++++++++++++++++++++++++++++++++++------- src/TableData.hpp | 1 + 3 files changed, 76 insertions(+), 14 deletions(-) diff --git a/src/ChatManager.cpp b/src/ChatManager.cpp index 24ce155..faaefc3 100644 --- a/src/ChatManager.cpp +++ b/src/ChatManager.cpp @@ -651,8 +651,6 @@ void summonGroupCommand(std::string full, std::vector& args, CNSock ChatManager::sendServerMessage(sock, "/summonGroup(W): placed mob with type: " + std::to_string(type) + ", id: " + std::to_string(npc->appearanceData.iNPC_ID)); - if (wCommand) - TableData::RunningMobs[npc->appearanceData.iNPC_ID] = npc; // only record the one in the template if (i == 0 && team == 2) { type = type2; @@ -660,6 +658,16 @@ void summonGroupCommand(std::string full, std::vector& args, CNSock leadNpc->groupLeader = leadNpc->appearanceData.iNPC_ID; } } + + if (!wCommand) + return; // not writing; don't add to running mobs + + if (leadNpc == nullptr) { + std::cout << "/summonGroupW: can't find group leader! Won't be saved!\n"; + return; + } + + TableData::RunningGroups[leadNpc->appearanceData.iNPC_ID] = leadNpc; // only record the leader } void flushCommand(std::string full, std::vector& args, CNSocket* sock) { diff --git a/src/TableData.cpp b/src/TableData.cpp index 41684e4..ccce668 100644 --- a/src/TableData.cpp +++ b/src/TableData.cpp @@ -16,6 +16,7 @@ std::map> TableData::RunningSkywayRoutes; std::map TableData::RunningNPCRotations; std::map TableData::RunningNPCMapNumbers; std::map TableData::RunningMobs; +std::map TableData::RunningGroups; std::map TableData::RunningEggs; class TableException : public std::exception { @@ -781,19 +782,12 @@ void TableData::flush() { continue; int x, y, z, hp; - int offsetX = 0; - int offsetY = 0; if (npc->npcClass == NPC_MOB) { Mob *m = (Mob*)npc; x = m->spawnX; y = m->spawnY; z = m->spawnZ; hp = m->maxHealth; - // handling groups - if (m->groupLeader != 0 && m->groupLeader != m->appearanceData.iNPC_ID) { - offsetX = m->offsetX; - offsetY = m->offsetY; - } } else { x = npc->appearanceData.iX; y = npc->appearanceData.iY; @@ -811,14 +805,73 @@ void TableData::flush() { // this is a bit imperfect, since this is a live angle, not a spawn angle so it'll change often, but eh mob["iAngle"] = npc->appearanceData.iAngle; - // there is an assumption that group mobs will never have an offset of (0,0) - if (offsetX != 0 || offsetY != 0) { - mob["iOffsetX"] = offsetX; - mob["iOffsetY"] = offsetY; + // it's called mobs, but really it's everything + gruntwork["mobs"].push_back(mob); + } + + for (auto& pair : RunningGroups) { + nlohmann::json mob; + BaseNPC* npc = pair.second; + + if (NPCManager::NPCs.find(pair.first) == NPCManager::NPCs.end()) + continue; + + int x, y, z, hp; + std::vector followers; + if (npc->npcClass == NPC_MOB) { + Mob* m = (Mob*)npc; + x = m->spawnX; + y = m->spawnY; + z = m->spawnZ; + hp = m->maxHealth; + if (m->groupLeader != m->appearanceData.iNPC_ID) { // make sure this is a leader + std::cout << "[WARN] Non-leader mob found in running groups; ignoring\n"; + continue; + } + + // add follower data to vector; go until OOB or until follower ID is 0 + for (int i = 0; i < 4 && m->groupMember[i] > 0; i++) { + if (MobManager::Mobs.find(m->groupMember[i]) == MobManager::Mobs.end()) { + std::cout << "[WARN] Follower with ID " << m->groupMember[i] << " not found; skipping\n"; + continue; + } + followers.push_back(MobManager::Mobs[m->groupMember[i]]); + } + } + else { + x = npc->appearanceData.iX; + y = npc->appearanceData.iY; + z = npc->appearanceData.iZ; + hp = npc->appearanceData.iHP; + } + + // NOTE: this format deviates slightly from the one in mobs.json + mob["iNPCType"] = (int)npc->appearanceData.iNPCType; + mob["iHP"] = hp; + mob["iX"] = x; + mob["iY"] = y; + mob["iZ"] = z; + mob["iMapNum"] = MAPNUM(npc->instanceID); + // this is a bit imperfect, since this is a live angle, not a spawn angle so it'll change often, but eh + mob["iAngle"] = npc->appearanceData.iAngle; + + // followers + while (followers.size() > 0) { + Mob* follower = followers.back(); + followers.pop_back(); // remove from vector + + // populate JSON entry + nlohmann::json fol; + fol["iNPCType"] = follower->appearanceData.iNPCType; + fol["iHP"] = follower->maxHealth; + fol["iOffsetX"] = follower->offsetX; + fol["iOffsetY"] = follower->offsetY; + + mob["aFollowers"].push_back(fol); // add to follower array } // it's called mobs, but really it's everything - gruntwork["mobs"].push_back(mob); + gruntwork["groups"].push_back(mob); } for (auto& pair : RunningEggs) { diff --git a/src/TableData.hpp b/src/TableData.hpp index 7b9cd9b..04f3019 100644 --- a/src/TableData.hpp +++ b/src/TableData.hpp @@ -9,6 +9,7 @@ namespace TableData { extern std::map RunningNPCRotations; extern std::map RunningNPCMapNumbers; extern std::map RunningMobs; + extern std::map RunningGroups; extern std::map RunningEggs; void init();