scopedvr-map-editor/tests/test_loadout.gd
2026-10-31 01:00:32 +01:00

141 lines
6.2 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

extends SceneTree
## Editor-Test (headless): Map-Loadout (V18) — Katalog, Validierung, Panel mit
## Undo/Redo und Speichern/Laden. Ausführen:
## godot --headless --path . --script res://tests/test_loadout.gd
var failures := 0
var checks := 0
var main: Control
func _initialize() -> void:
_run_all.call_deferred()
func _check(cond: bool, label: String) -> void:
checks += 1
if cond:
print(" ok: %s" % label)
else:
failures += 1
print(" FAIL: %s" % label)
func _run_all() -> void:
_test_katalog()
await _test_panel()
if failures == 0:
print("ALL OK: %d checks" % checks)
quit(0)
else:
print("FAILED: %d/%d checks" % [failures, checks])
quit(1)
func _test_katalog() -> void:
print("Testgruppe: Katalog + Validierung")
_check(LoadoutKatalog.waffen_ids().size() >= 50, "Katalog hat Waffen")
_check(LoadoutKatalog.hat_waffe("m40") and LoadoutKatalog.hat_waffe("pistol1"), "m40 + pistol1 bekannt")
_check(LoadoutKatalog.validate(null).is_empty(), "fehlend gültig")
_check(LoadoutKatalog.validate({"mode": "player"}).is_empty(), "player gültig")
_check(not LoadoutKatalog.validate({"mode": "fixed"}).is_empty(), "fixed ohne Primär ungültig")
_check(not LoadoutKatalog.validate({"mode": "fixed", "primary": "nix"}).is_empty(), "unbekannte Waffe ungültig")
_check(not LoadoutKatalog.validate({"mode": "x"}).is_empty(), "unbekannter Modus ungültig")
_check(LoadoutKatalog.validate({"mode": "fixed", "primary": "sr1", "secondary": ""}).is_empty(), "fixed ohne Sekundär gültig")
_check(not LoadoutKatalog.validate({"mode": "fixed", "primary": "sr1",
"attachments": {"ar1": ""}}).is_empty(), "Aufsatz für Fremdwaffe ungültig")
_check(not LoadoutKatalog.validate({"mode": "fixed", "primary": "sr1",
"attachments": {"sr1": "sight=nix"}}).is_empty(), "unbekanntes Teil ungültig")
var sel := LoadoutKatalog.auswahl("sr1", "")
sel["muzzle"] = "muzzle_suppressor_01"
var wire := LoadoutKatalog.encode("sr1", sel)
_check(wire == "muzzle=muzzle_suppressor_01", "encode nur Abweichungen: " + wire)
_check(LoadoutKatalog.pruefe_aufsaetze("sr1", wire) == "", "encodierter Text gültig")
# Rotpunktvisier statt Zielfernrohr: wählbar, gültig, deutscher Name
var rot := LoadoutKatalog.auswahl("sr1", "")
rot["sight"] = "sight_collimator"
var rot_wire := LoadoutKatalog.encode("sr1", rot)
_check(rot_wire == "sight=sight_collimator", "Rotpunkt-Draht: " + rot_wire)
_check(LoadoutKatalog.validate({"mode": "fixed", "primary": "sr1", "secondary": "",
"attachments": {"sr1": rot_wire}}).is_empty(), "Rotpunkt im festen Loadout gültig")
_check(LoadoutKatalog.auswahl("sr1", rot_wire)["sight"] == "sight_collimator", "Rotpunkt Rundlauf")
_check(LoadoutKatalog.teil_name("sight_collimator") == "Rotpunktvisier", "Rotpunkt-Name deutsch")
_check(LoadoutKatalog.teil_name("") == "— nichts —", "leerer Slot benannt")
func _test_panel() -> void:
print("Testgruppe: Panel")
var scene: PackedScene = load("res://scenes/main.tscn")
main = scene.instantiate()
root.add_child(main)
await process_frame
await process_frame
main.doc = SvmapDocument.create_new("LoadoutTest", 512.0, "mittag")
main.history.doc = main.doc
main.call("_refresh_all")
var panel: Node = main.map_mod.sections_host().get_node_or_null("loadout")
_check(panel != null, "Loadout-Panel hängt im Map-Tab")
if panel == null:
return
_check(not panel.is_fixed() and not main.doc.has("loadout"), "Start: Spieler-Loadout, kein Block")
_check(not panel.fixed_box.visible, "Waffen-Auswahl verborgen")
panel.set_fixed(true)
_check(panel.is_fixed() and main.doc["loadout"]["primary"] == "m40", "fest: M40 als Start")
_check(panel.fixed_box.visible, "Waffen-Auswahl sichtbar")
panel.set_weapons("sr1", "")
_check(main.doc["loadout"]["primary"] == "sr1" and main.doc["loadout"]["secondary"] == "", "Waffen gesetzt, Sekundär leer")
panel.set_part("sr1", "muzzle", "muzzle_suppressor_01")
_check(main.doc["loadout"]["attachments"].get("sr1", "") == "muzzle=muzzle_suppressor_01", "Aufsatz gespeichert")
panel.set_part("ar1", "muzzle", "muzzle_suppressor_01")
_check(not main.doc["loadout"]["attachments"].has("ar1"), "Aufsatz für Nicht-Loadout-Waffe ignoriert")
_check(SvmapIO.validate_map(_signed(main.doc)).is_empty(), "Map mit Loadout besteht V1–V18")
# Rotpunktvisier: in der Auswahl deutsch benannt, wird gespeichert, besteht die Prüfung
var visier := panel.attach_box.find_child("Teil_sr1_sight", true, false) as OptionButton
var eintraege: Array[String] = []
if visier != null:
for i in visier.item_count:
eintraege.append(visier.get_item_text(i))
_check(eintraege.has("Rotpunktvisier"), "Rotpunktvisier in der Visier-Auswahl")
panel.set_part("sr1", "sight", "sight_collimator")
_check(main.doc["loadout"]["attachments"]["sr1"] == "muzzle=muzzle_suppressor_01;sight=sight_collimator", "Rotpunkt gespeichert")
_check(SvmapIO.validate_map(_signed(main.doc)).is_empty(), "Map mit Rotpunkt besteht V1–V18")
main.history.undo()
main.call("_refresh_all")
panel.set_weapons("ar1", "")
_check(not main.doc["loadout"]["attachments"].has("sr1"), "Waffenwechsel verwirft Aufsätze der alten Waffe")
# Undo/Redo
main.history.undo()
main.call("_refresh_all")
_check(main.doc["loadout"]["primary"] == "sr1" and main.doc["loadout"]["attachments"].has("sr1"), "Undo: Waffenwechsel zurück")
main.history.undo()
main.history.undo()
main.history.undo()
main.call("_refresh_all")
_check(not main.doc.has("loadout") and not panel.fixed_box.visible, "Undo bis Start: Block weg, UI nachgezogen")
main.history.redo()
main.call("_refresh_all")
_check(main.doc.has("loadout") and panel.is_fixed(), "Redo: fest wieder da")
# Zurück auf Spieler-Loadout entfernt den Block
panel.set_fixed(false)
_check(not main.doc.has("loadout"), "Spieler-Loadout entfernt den Block")
# Speichern/Laden
panel.set_fixed(true)
panel.set_weapons("sr2", "pistol2")
var path := "user://loadout_test.svmap"
var doc2: Dictionary = main.doc.duplicate(true)
SvmapIO.sign_map(doc2)
var res := SvmapIO.save_to_file(path, doc2)
_check(res["ok"], "Speichern ok: " + str(res["errors"]))
var back := SvmapIO.load_from_file(path)
_check(back["ok"] and back["data"]["loadout"]["primary"] == "sr2", "Laden: Loadout bleibt erhalten")
func _signed(d: Dictionary) -> Dictionary:
var c := d.duplicate(true)
SvmapIO.sign_map(c)
return c