mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-05-07 09:33:51 +00:00
feat(editor): add --list-{creatures,objects,quests} for indexed enumeration
Verbose enumeration of every entry, complementing the existing
--info-* (summary counts) and unblocking --remove-* (which takes a
0-based index).
wowee_editor --list-creatures custom_zones/Z/creatures.json
creatures.json: custom_zones/Z/creatures.json (2 total)
idx name lvl display pos (x, y, z)
0 Wolf 7 11430 (100.0, 200.0, 50.0)
1 Black Bear 12 11445 (110.0, 210.0, 55.0)
The 'idx' column is exactly what --remove-creature/object/quest
takes, closing the workflow loop:
wowee_editor --list-creatures $Z/creatures.json |
grep -i 'wolf' | awk '{print $1}' |
xargs -I{} wowee_editor --remove-creature $Z {}
Each command has matching --json mode that emits per-entry records
with index, key fields, and position. Verified on a synthesized
zone with 2 creatures + 2 objects + 2 quests; tables align, indices
match, JSON is well-formed and round-trips through jq cleanly.
This commit is contained in:
parent
aa499b7462
commit
78a2624159
1 changed files with 136 additions and 0 deletions
|
|
@ -455,6 +455,12 @@ static void printUsage(const char* argv0) {
|
|||
std::printf(" Print objects.json summary (counts, types, scale range) and exit\n");
|
||||
std::printf(" --info-quests <p> [--json]\n");
|
||||
std::printf(" Print quests.json summary (counts, rewards, chain errors) and exit\n");
|
||||
std::printf(" --list-creatures <p> [--json]\n");
|
||||
std::printf(" List every creature with index, name, position, level (for --remove-creature)\n");
|
||||
std::printf(" --list-objects <p> [--json]\n");
|
||||
std::printf(" List every object with index, type, path, position\n");
|
||||
std::printf(" --list-quests <p> [--json]\n");
|
||||
std::printf(" List every quest with index, title, giver, XP\n");
|
||||
std::printf(" --info-wcp <wcp-path> [--json]\n");
|
||||
std::printf(" Print WCP archive metadata (name, files) and exit\n");
|
||||
std::printf(" --list-wcp <wcp-path> Print every file inside a WCP archive (sorted by path) and exit\n");
|
||||
|
|
@ -479,6 +485,7 @@ int main(int argc, char* argv[]) {
|
|||
"--info-creatures", "--info-objects", "--info-quests",
|
||||
"--info-extract", "--list-missing-sidecars",
|
||||
"--info-zone", "--info-wcp", "--list-wcp",
|
||||
"--list-creatures", "--list-objects", "--list-quests",
|
||||
"--unpack-wcp", "--pack-wcp",
|
||||
"--validate", "--validate-wom", "--validate-wob", "--validate-woc",
|
||||
"--validate-whm", "--validate-all", "--zone-summary",
|
||||
|
|
@ -1056,6 +1063,135 @@ int main(int argc, char* argv[]) {
|
|||
stationary, wander, patrol);
|
||||
std::printf(" unique displayIds: %zu\n", displayIdHist.size());
|
||||
return 0;
|
||||
} else if (std::strcmp(argv[i], "--list-creatures") == 0 && i + 1 < argc) {
|
||||
// Verbose enumeration of every spawn — needed because
|
||||
// --remove-creature takes a 0-based index but --info-creatures
|
||||
// only shows aggregate counts.
|
||||
std::string path = argv[++i];
|
||||
bool jsonOut = (i + 1 < argc &&
|
||||
std::strcmp(argv[i + 1], "--json") == 0);
|
||||
if (jsonOut) i++;
|
||||
wowee::editor::NpcSpawner spawner;
|
||||
if (!spawner.loadFromFile(path)) {
|
||||
std::fprintf(stderr, "Failed to load creatures.json: %s\n", path.c_str());
|
||||
return 1;
|
||||
}
|
||||
const auto& spawns = spawner.getSpawns();
|
||||
if (jsonOut) {
|
||||
nlohmann::json j;
|
||||
j["file"] = path;
|
||||
j["total"] = spawns.size();
|
||||
nlohmann::json arr = nlohmann::json::array();
|
||||
for (size_t k = 0; k < spawns.size(); ++k) {
|
||||
const auto& s = spawns[k];
|
||||
arr.push_back({
|
||||
{"index", k},
|
||||
{"name", s.name},
|
||||
{"displayId", s.displayId},
|
||||
{"level", s.level},
|
||||
{"position", {s.position.x, s.position.y, s.position.z}},
|
||||
{"hostile", s.hostile},
|
||||
});
|
||||
}
|
||||
j["spawns"] = arr;
|
||||
std::printf("%s\n", j.dump(2).c_str());
|
||||
return 0;
|
||||
}
|
||||
std::printf("creatures.json: %s (%zu total)\n", path.c_str(), spawns.size());
|
||||
std::printf(" idx name lvl display pos (x, y, z)\n");
|
||||
for (size_t k = 0; k < spawns.size(); ++k) {
|
||||
const auto& s = spawns[k];
|
||||
std::printf(" %3zu %-30s %3u %7u (%.1f, %.1f, %.1f)%s\n",
|
||||
k, s.name.substr(0, 30).c_str(), s.level, s.displayId,
|
||||
s.position.x, s.position.y, s.position.z,
|
||||
s.hostile ? " [hostile]" : "");
|
||||
}
|
||||
return 0;
|
||||
} else if (std::strcmp(argv[i], "--list-objects") == 0 && i + 1 < argc) {
|
||||
std::string path = argv[++i];
|
||||
bool jsonOut = (i + 1 < argc &&
|
||||
std::strcmp(argv[i + 1], "--json") == 0);
|
||||
if (jsonOut) i++;
|
||||
wowee::editor::ObjectPlacer placer;
|
||||
if (!placer.loadFromFile(path)) {
|
||||
std::fprintf(stderr, "Failed to load objects.json: %s\n", path.c_str());
|
||||
return 1;
|
||||
}
|
||||
const auto& objs = placer.getObjects();
|
||||
auto typeStr = [](wowee::editor::PlaceableType t) {
|
||||
return t == wowee::editor::PlaceableType::M2 ? "m2" : "wmo";
|
||||
};
|
||||
if (jsonOut) {
|
||||
nlohmann::json j;
|
||||
j["file"] = path;
|
||||
j["total"] = objs.size();
|
||||
nlohmann::json arr = nlohmann::json::array();
|
||||
for (size_t k = 0; k < objs.size(); ++k) {
|
||||
const auto& o = objs[k];
|
||||
arr.push_back({
|
||||
{"index", k},
|
||||
{"type", typeStr(o.type)},
|
||||
{"path", o.path},
|
||||
{"position", {o.position.x, o.position.y, o.position.z}},
|
||||
{"scale", o.scale},
|
||||
});
|
||||
}
|
||||
j["objects"] = arr;
|
||||
std::printf("%s\n", j.dump(2).c_str());
|
||||
return 0;
|
||||
}
|
||||
std::printf("objects.json: %s (%zu total)\n", path.c_str(), objs.size());
|
||||
std::printf(" idx type scale path pos (x, y, z)\n");
|
||||
for (size_t k = 0; k < objs.size(); ++k) {
|
||||
const auto& o = objs[k];
|
||||
std::printf(" %3zu %-4s %5.2f %-38s (%.1f, %.1f, %.1f)\n",
|
||||
k, typeStr(o.type), o.scale,
|
||||
o.path.substr(0, 38).c_str(),
|
||||
o.position.x, o.position.y, o.position.z);
|
||||
}
|
||||
return 0;
|
||||
} else if (std::strcmp(argv[i], "--list-quests") == 0 && i + 1 < argc) {
|
||||
std::string path = argv[++i];
|
||||
bool jsonOut = (i + 1 < argc &&
|
||||
std::strcmp(argv[i + 1], "--json") == 0);
|
||||
if (jsonOut) i++;
|
||||
wowee::editor::QuestEditor qe;
|
||||
if (!qe.loadFromFile(path)) {
|
||||
std::fprintf(stderr, "Failed to load quests.json: %s\n", path.c_str());
|
||||
return 1;
|
||||
}
|
||||
const auto& quests = qe.getQuests();
|
||||
if (jsonOut) {
|
||||
nlohmann::json j;
|
||||
j["file"] = path;
|
||||
j["total"] = quests.size();
|
||||
nlohmann::json arr = nlohmann::json::array();
|
||||
for (size_t k = 0; k < quests.size(); ++k) {
|
||||
const auto& q = quests[k];
|
||||
arr.push_back({
|
||||
{"index", k},
|
||||
{"title", q.title},
|
||||
{"giver", q.questGiverNpcId},
|
||||
{"turnIn", q.turnInNpcId},
|
||||
{"requiredLevel", q.requiredLevel},
|
||||
{"xp", q.reward.xp},
|
||||
{"nextQuestId", q.nextQuestId},
|
||||
});
|
||||
}
|
||||
j["quests"] = arr;
|
||||
std::printf("%s\n", j.dump(2).c_str());
|
||||
return 0;
|
||||
}
|
||||
std::printf("quests.json: %s (%zu total)\n", path.c_str(), quests.size());
|
||||
std::printf(" idx lvl giver turnIn xp title\n");
|
||||
for (size_t k = 0; k < quests.size(); ++k) {
|
||||
const auto& q = quests[k];
|
||||
std::printf(" %3zu %3u %7u %7u %5u %s%s\n",
|
||||
k, q.requiredLevel, q.questGiverNpcId, q.turnInNpcId,
|
||||
q.reward.xp, q.title.c_str(),
|
||||
q.nextQuestId ? " [chained]" : "");
|
||||
}
|
||||
return 0;
|
||||
} else if (std::strcmp(argv[i], "--diff-wcp") == 0 && i + 2 < argc) {
|
||||
// Print which files differ between two WCP archives. Useful
|
||||
// when verifying that an authoring tweak only changed what
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue