Files
2025-09-19 18:51:25 +02:00

235 lines
7.9 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Patchuje:
1) wg-voidship-hulls.db -> base.power = 0 (dla wszystkich kadłubów)
2) wg-voidship-items.db -> reaktory: use.power=0, mods.power wg subtype;
aux-plasma: use.power=0;
dopisuje 4 reaktory jeśli brak.
Uruchom w katalogu z plikami .db
"""
import json, shutil
from pathlib import Path
HULLS_FN = Path("wg-voidship-hulls.db")
ITEMS_FN = Path("wg-voidship-items.db")
REACTOR_POWER_BY_SUBTYPE = {
"escort": 40,
"frigate": 45,
"light-cruiser": 55,
"cruiser": 60,
}
# 4 reaktory „wzorcowe” do dopisania, jeśli brak:
REACTOR_TEMPLATES = [
{
"_id": "ITEMREACTCRU0001",
"name": "Plasma Reactor (Cruiser) — Mars-Pattern",
"type": "gear",
"img": "icons/svg/energy.svg",
"flags": {
"wg-voidships-builder": {
"voidOnly": True,
"component": {"kind": "reactor", "subtype": "cruiser", "tags": ["reactor", "plasma"]}
}
},
"system": {
"description": "Standardowy reaktor plazmowy klasy krążownik (Mars-Pattern). Generuje moc dla wszystkich systemów okrętu.",
"voidship": {
"slot": "Internal",
"use": {"space": 20, "power": 0},
"mods": {"armour": 0, "integrity": 0, "manoeuvre": 0, "detection": 0, "speed": 0, "space": 0, "power": 60}
}
},
"effects": []
},
{
"_id": "ITEMREACTLCR0001",
"name": "Plasma Reactor (Light Cruiser) — Mars-Pattern",
"type": "gear",
"img": "icons/svg/energy.svg",
"flags": {
"wg-voidships-builder": {
"voidOnly": True,
"component": {"kind": "reactor", "subtype": "light-cruiser", "tags": ["reactor", "plasma"]}
}
},
"system": {
"description": "Reaktor plazmowy dla lekkich krążowników (Mars-Pattern).",
"voidship": {
"slot": "Internal",
"use": {"space": 18, "power": 0},
"mods": {"armour": 0, "integrity": 0, "manoeuvre": 0, "detection": 0, "speed": 0, "space": 0, "power": 55}
}
},
"effects": []
},
{
"_id": "ITEMREACTFRI0001",
"name": "Plasma Reactor (Frigate) — Jovian-Pattern",
"type": "gear",
"img": "icons/svg/energy.svg",
"flags": {
"wg-voidships-builder": {
"voidOnly": True,
"component": {"kind": "reactor", "subtype": "frigate", "tags": ["reactor", "plasma"]}
}
},
"system": {
"description": "Reaktor plazmowy okrętów klasy fregata (Jovian-Pattern).",
"voidship": {
"slot": "Internal",
"use": {"space": 15, "power": 0},
"mods": {"armour": 0, "integrity": 0, "manoeuvre": 0, "detection": 0, "speed": 0, "space": 0, "power": 45}
}
},
"effects": []
},
{
"_id": "ITEMREACTESC0001",
"name": "Plasma Reactor (Escort) — Jovian-Pattern",
"type": "gear",
"img": "icons/svg/energy.svg",
"flags": {
"wg-voidships-builder": {
"voidOnly": True,
"component": {"kind": "reactor", "subtype": "escort", "tags": ["reactor", "plasma"]}
}
},
"system": {
"description": "Lżejszy reaktor plazmowy dla eskort.",
"voidship": {
"slot": "Internal",
"use": {"space": 12, "power": 0},
"mods": {"armour": 0, "integrity": 0, "manoeuvre": 0, "detection": 0, "speed": 0, "space": 0, "power": 40}
}
},
"effects": []
},
]
def read_ndjson(path: Path):
if not path.exists():
print(f"[WARN] Brak pliku: {path.name}")
return []
rows = []
with path.open("r", encoding="utf-8") as f:
for i, line in enumerate(f, 1):
line = line.strip()
if not line:
continue
try:
rows.append(json.loads(line))
except Exception as e:
print(f"[WARN] {path.name}:{i}: nie mogę zdekodować JSON: {e}")
return rows
def write_ndjson(path: Path, rows):
tmp = path.with_suffix(path.suffix + ".patched")
with tmp.open("w", encoding="utf-8") as f:
for obj in rows:
f.write(json.dumps(obj, ensure_ascii=False, separators=(",", ":")) + "\n")
tmp.replace(path)
def ensure_backup(path: Path):
bak = path.with_suffix(path.suffix + ".bak")
if path.exists() and not bak.exists():
shutil.copy2(path, bak)
print(f"[OK] Backup -> {bak.name}")
def patch_hulls():
if not HULLS_FN.exists():
print(f"[INFO] Pomijam hulls (brak {HULLS_FN.name})")
return
ensure_backup(HULLS_FN)
rows = read_ndjson(HULLS_FN)
patched = 0
for o in rows:
flags = o.setdefault("flags", {}).setdefault("wg-voidships-builder", {})
base = flags.setdefault("base", {})
if base.get("power", None) != 0:
base["power"] = 0
patched += 1
write_ndjson(HULLS_FN, rows)
print(f"[OK] Hulls: ustawiono base.power=0 w {patched} rekordach ({len(rows)} linii)")
def has_tag(flags_obj, tag: str) -> bool:
try:
tags = flags_obj["wg-voidships-builder"]["component"]["tags"]
return isinstance(tags, list) and tag in tags
except Exception:
return False
def patch_items():
if not ITEMS_FN.exists():
print(f"[INFO] Pomijam items (brak {ITEMS_FN.name})")
return
ensure_backup(ITEMS_FN)
rows = read_ndjson(ITEMS_FN)
existing_ids = set()
patched_reactors = 0
patched_aux = 0
for o in rows:
existing_ids.add(o.get("_id", ""))
flags = o.get("flags", {})
comp = flags.get("wg-voidships-builder", {}).get("component", {})
kind = comp.get("kind")
subtype = comp.get("subtype")
# Upewnij się, że ścieżka system.voidship.use/mods istnieje
sys = o.setdefault("system", {})
vsh = sys.setdefault("voidship", {})
use = vsh.setdefault("use", {})
mods = vsh.setdefault("mods", {})
# Auxiliary plasma (po tagu)
if has_tag(flags, "aux-plasma"):
if use.get("power") != 0:
use["power"] = 0
patched_aux += 1
# Reaktory
if kind == "reactor":
if use.get("power") != 0:
use["power"] = 0
if subtype in REACTOR_POWER_BY_SUBTYPE:
pow_val = REACTOR_POWER_BY_SUBTYPE[subtype]
if mods.get("power") != pow_val:
mods["power"] = pow_val
patched_reactors += 1
# zadbaj o wypełnienie brakujących kluczy modów
for k in ["armour","integrity","manoeuvre","detection","speed","space"]:
mods.setdefault(k, 0)
# i sensowne sloty/space
vsh.setdefault("slot", "Internal")
use.setdefault("space", use.get("space", 0))
# Zapisz zmodyfikowane wiersze
write_ndjson(ITEMS_FN, rows)
print(f"[OK] Items: zaktualizowano reaktory: {patched_reactors}, aux-plasma: {patched_aux}")
# Dopisz brakujące 4 reaktory
to_append = [r for r in REACTOR_TEMPLATES if r["_id"] not in existing_ids]
if to_append:
with ITEMS_FN.open("a", encoding="utf-8") as f:
for obj in to_append:
f.write(json.dumps(obj, ensure_ascii=False, separators=(",", ":")) + "\n")
print(f"[OK] Items: dopisano brakujące reaktory: {[o['_id'] for o in to_append]}")
else:
print(f"[OK] Items: wszystkie reaktory już są — nic do dopisania.")
def main():
print("== WG Voidships Patch ==")
patch_hulls()
patch_items()
print("Gotowe. Zrestartuj/reloadnij Foundry i reimportuj kompendia, jeśli potrzeba.")
if __name__ == "__main__":
main()