#!/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()