Files

118 lines
4.1 KiB
Python
Raw Permalink Normal View History

#!/usr/bin/env python3
"""Regenerate the Relic portion of InventoryItemConfig from game tables.
Pass a directory containing RelicConfig.json, ItemConfigRelic.json,
RelicMainAffixConfig.json, and RelicSubAffixConfig.json from the revision
recorded in InventoryItemConfig.json. Existing item and Light Cone entries
are preserved; only visible BASIC Relic types from ItemConfigRelic are included.
"""
from __future__ import annotations
import argparse
import json
from pathlib import Path
from typing import Any
TABLES = (
"RelicConfig.json",
"ItemConfigRelic.json",
"RelicMainAffixConfig.json",
"RelicSubAffixConfig.json",
)
def read_rows(path: Path) -> list[dict[str, Any]]:
with path.open("r", encoding="utf-8") as source:
rows = json.load(source)
if not isinstance(rows, list):
raise ValueError(f"{path.name} must contain a JSON array")
return rows
def build_relic_catalog(source_dir: Path) -> list[dict[str, Any]]:
relic_rows = read_rows(source_dir / "RelicConfig.json")
item_rows = read_rows(source_dir / "ItemConfigRelic.json")
main_rows = read_rows(source_dir / "RelicMainAffixConfig.json")
sub_rows = read_rows(source_dir / "RelicSubAffixConfig.json")
visible_item_ids = {
int(row["ID"])
for row in item_rows
if row.get("ItemMainType") == "Relic" and row.get("isVisible") is True
}
main_by_group: dict[int, list[dict[str, Any]]] = {}
for row in main_rows:
main_by_group.setdefault(int(row["GroupID"]), []).append(row)
sub_by_group: dict[int, list[dict[str, Any]]] = {}
for row in sub_rows:
sub_by_group.setdefault(int(row["GroupID"]), []).append(row)
for rows in (*main_by_group.values(), *sub_by_group.values()):
rows.sort(key=lambda row: int(row["AffixID"]))
catalog: list[dict[str, Any]] = []
seen: set[int] = set()
for relic in sorted(relic_rows, key=lambda row: int(row["ID"])):
relic_id = int(relic["ID"])
if relic.get("Mode") != "BASIC" or relic_id not in visible_item_ids:
continue
if relic_id in seen:
raise ValueError(f"duplicate Relic ID {relic_id}")
main_options = main_by_group.get(int(relic["MainAffixGroup"]), [])
if not main_options:
raise ValueError(f"Relic {relic_id} has no MainAffixGroup rows")
main = main_options[0]
sub_options = [
row
for row in sub_by_group.get(int(relic["SubAffixGroup"]), [])
if row.get("Property") != main.get("Property")
]
if len(sub_options) < 4:
raise ValueError(f"Relic {relic_id} has fewer than four valid sub-affixes")
catalog.append(
{
"relic_id": relic_id,
"relic_set_id": int(relic["SetID"]),
"main_affix_id": int(main["AffixID"]),
"sub_affixes": [
{
"sub_affix_id": int(row["AffixID"]),
"count": 1,
"step": 0,
}
for row in sub_options[:4]
],
}
)
seen.add(relic_id)
if not catalog:
raise ValueError("no visible BASIC Relics were found in the supplied tables")
return catalog
def main() -> None:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--source-dir", type=Path, required=True)
parser.add_argument("--inventory-config", type=Path, required=True)
args = parser.parse_args()
missing = [name for name in TABLES if not (args.source_dir / name).is_file()]
if missing:
raise SystemExit("Missing source tables: " + ", ".join(missing))
with args.inventory_config.open("r", encoding="utf-8") as source:
resource = json.load(source)
resource["relics"] = build_relic_catalog(args.source_dir)
with args.inventory_config.open("w", encoding="utf-8", newline="\n") as output:
json.dump(resource, output, ensure_ascii=False, indent=2)
output.write("\n")
print(f"Wrote {len(resource['relics'])} Client-configured Relic templates")
if __name__ == "__main__":
main()