Add debug CSV tables showing before/after values for each override
- Writes output/<mod>/debug_ammo.csv and debug_armor.csv - Columns: classname, source_mod, field, old_value, new_value - Helps verify rebalance changes make sense
This commit is contained in:
@@ -449,6 +449,7 @@ class AmmoOverride:
|
|||||||
classname: str
|
classname: str
|
||||||
source_mod: str
|
source_mod: str
|
||||||
changes: dict = field(default_factory=dict)
|
changes: dict = field(default_factory=dict)
|
||||||
|
originals: dict = field(default_factory=dict)
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
@@ -457,6 +458,7 @@ class ArmorOverride:
|
|||||||
source_mod: str
|
source_mod: str
|
||||||
item_type: str
|
item_type: str
|
||||||
changes: dict = field(default_factory=dict)
|
changes: dict = field(default_factory=dict)
|
||||||
|
originals: dict = field(default_factory=dict)
|
||||||
|
|
||||||
|
|
||||||
def find_ammo_overrides(
|
def find_ammo_overrides(
|
||||||
@@ -472,11 +474,13 @@ def find_ammo_overrides(
|
|||||||
|
|
||||||
base = baseline[key]
|
base = baseline[key]
|
||||||
changes = {}
|
changes = {}
|
||||||
|
originals = {}
|
||||||
for field_name in AMMO_FIELDS:
|
for field_name in AMMO_FIELDS:
|
||||||
mod_val = getattr(e, field_name)
|
mod_val = getattr(e, field_name)
|
||||||
base_val = getattr(base, field_name)
|
base_val = getattr(base, field_name)
|
||||||
if mod_val != base_val and mod_val != 0:
|
if mod_val != base_val and mod_val != 0:
|
||||||
changes[field_name] = base_val
|
changes[field_name] = base_val
|
||||||
|
originals[field_name] = mod_val
|
||||||
|
|
||||||
# Check ACE array fields (compare as strings)
|
# Check ACE array fields (compare as strings)
|
||||||
for array_field in ["ace_bc", "ace_mv", "ace_bl", "ace_vb"]:
|
for array_field in ["ace_bc", "ace_mv", "ace_bl", "ace_vb"]:
|
||||||
@@ -484,12 +488,14 @@ def find_ammo_overrides(
|
|||||||
base_val = getattr(base, array_field)
|
base_val = getattr(base, array_field)
|
||||||
if mod_val != base_val and mod_val not in ("[]", ""):
|
if mod_val != base_val and mod_val not in ("[]", ""):
|
||||||
changes[array_field] = base_val
|
changes[array_field] = base_val
|
||||||
|
originals[array_field] = mod_val
|
||||||
|
|
||||||
if changes:
|
if changes:
|
||||||
overrides.append(AmmoOverride(
|
overrides.append(AmmoOverride(
|
||||||
classname=e.classname,
|
classname=e.classname,
|
||||||
source_mod=e.source_mod,
|
source_mod=e.source_mod,
|
||||||
changes=changes,
|
changes=changes,
|
||||||
|
originals=originals,
|
||||||
))
|
))
|
||||||
|
|
||||||
return overrides
|
return overrides
|
||||||
@@ -508,6 +514,7 @@ def find_armor_overrides(
|
|||||||
|
|
||||||
base = baseline[key]
|
base = baseline[key]
|
||||||
changes = {}
|
changes = {}
|
||||||
|
originals = {}
|
||||||
for field_name in ARMOR_FIELDS:
|
for field_name in ARMOR_FIELDS:
|
||||||
mod_val = getattr(e, field_name)
|
mod_val = getattr(e, field_name)
|
||||||
base_val = getattr(base, field_name)
|
base_val = getattr(base, field_name)
|
||||||
@@ -516,6 +523,7 @@ def find_armor_overrides(
|
|||||||
continue
|
continue
|
||||||
if mod_val != base_val:
|
if mod_val != base_val:
|
||||||
changes[field_name] = base_val
|
changes[field_name] = base_val
|
||||||
|
originals[field_name] = mod_val
|
||||||
|
|
||||||
if changes:
|
if changes:
|
||||||
overrides.append(AmmoOverride(
|
overrides.append(AmmoOverride(
|
||||||
@@ -523,11 +531,13 @@ def find_armor_overrides(
|
|||||||
source_mod=e.source_mod,
|
source_mod=e.source_mod,
|
||||||
item_type=e.item_type,
|
item_type=e.item_type,
|
||||||
changes=changes,
|
changes=changes,
|
||||||
|
originals=originals,
|
||||||
) if hasattr(AmmoOverride, 'item_type') else ArmorOverride(
|
) if hasattr(AmmoOverride, 'item_type') else ArmorOverride(
|
||||||
classname=e.classname,
|
classname=e.classname,
|
||||||
source_mod=e.source_mod,
|
source_mod=e.source_mod,
|
||||||
item_type=e.item_type,
|
item_type=e.item_type,
|
||||||
changes=changes,
|
changes=changes,
|
||||||
|
originals=originals,
|
||||||
))
|
))
|
||||||
|
|
||||||
return overrides
|
return overrides
|
||||||
@@ -684,6 +694,42 @@ def write_unmatched(
|
|||||||
f"{len(unmatched_armor)} unmatched armor to {out_path}")
|
f"{len(unmatched_armor)} unmatched armor to {out_path}")
|
||||||
|
|
||||||
|
|
||||||
|
def write_debug_csvs(
|
||||||
|
mod: str,
|
||||||
|
ammo_overrides: list[AmmoOverride],
|
||||||
|
armor_overrides: list[ArmorOverride],
|
||||||
|
):
|
||||||
|
"""Write per-mod debug CSVs showing old -> new values for each override."""
|
||||||
|
mod_dir = OUTPUT_DIR / mod
|
||||||
|
|
||||||
|
if ammo_overrides:
|
||||||
|
path = mod_dir / "debug_ammo.csv"
|
||||||
|
with open(path, "w", encoding="utf-8", newline="") as f:
|
||||||
|
writer = csv.writer(f, delimiter=";")
|
||||||
|
writer.writerow(["classname", "source_mod", "field",
|
||||||
|
"old_value", "new_value"])
|
||||||
|
for o in sorted(ammo_overrides, key=lambda x: x.classname):
|
||||||
|
for field_name in sorted(o.changes.keys()):
|
||||||
|
old_val = o.originals.get(field_name, "")
|
||||||
|
new_val = o.changes[field_name]
|
||||||
|
writer.writerow([o.classname, o.source_mod,
|
||||||
|
field_name, old_val, new_val])
|
||||||
|
|
||||||
|
if armor_overrides:
|
||||||
|
path = mod_dir / "debug_armor.csv"
|
||||||
|
with open(path, "w", encoding="utf-8", newline="") as f:
|
||||||
|
writer = csv.writer(f, delimiter=";")
|
||||||
|
writer.writerow(["classname", "source_mod", "item_type",
|
||||||
|
"field", "old_value", "new_value"])
|
||||||
|
for o in sorted(armor_overrides, key=lambda x: x.classname):
|
||||||
|
for field_name in sorted(o.changes.keys()):
|
||||||
|
old_val = o.originals.get(field_name, "")
|
||||||
|
new_val = o.changes[field_name]
|
||||||
|
writer.writerow([o.classname, o.source_mod,
|
||||||
|
o.item_type, field_name,
|
||||||
|
old_val, new_val])
|
||||||
|
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Main
|
# Main
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
@@ -790,6 +836,7 @@ def main():
|
|||||||
config_path = mod_dir / "config.cpp"
|
config_path = mod_dir / "config.cpp"
|
||||||
with open(config_path, "w", encoding="utf-8") as f:
|
with open(config_path, "w", encoding="utf-8") as f:
|
||||||
f.write(config_cpp)
|
f.write(config_cpp)
|
||||||
|
write_debug_csvs(mod, mod_ammo, mod_armor)
|
||||||
mods_with_overrides.add(mod)
|
mods_with_overrides.add(mod)
|
||||||
print(f" {mod}/config.cpp ({len(mod_ammo)} ammo, {len(mod_armor)} armor)")
|
print(f" {mod}/config.cpp ({len(mod_ammo)} ammo, {len(mod_armor)} armor)")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user