saumwacht-godot/tools/luneraria/g2_probe.gd
Martin Stickelbroeck 9f62e30377 G2: Ancients, Türme, Bossgrotte und Superboss; macOS- und Windows-ARM64-Pakete
Mondherz-Ancients (Saumkern-Kristall als Herz, Sichelklingen, Ringe, Krone,
Teamwappen, Energieadern) mit den Stufen stabil/instabil/kritisch, kurzem
Zusammenbruch und bleibender Ruine; der Sieg wartet nie auf die Grafik.
Turmfamilie aus einem Blender-Generator: Grenzwacht (Tower 1), Bastion
(Tower 2), Kernwacht (Basisturm in der Formensprache des Ancients), mit
Schadensstufen, Einsturz, Ruine und sichtbarem Angriff (Zielring, Aufladen,
Bolzen, Einschlag) - der Schaden bleibt vollständig in der Simulation.
Bossgrotte Mondschlund mit Tor, Treppe in die Tiefe, Altar, Säulen, Felsen
und fünf Zuständen; der Generator hält Abstand zur Top-Lane, die Höhle
braucht eine kleine Geländesenke (nur Darstellung). Superboss Schlundkrone
mit 24 Knochen und 11 Clips (inkl. Brüllen und Sieg), Adern in Teamfarbe,
dasselbe Modell für Grotte und Lane. Gemeinsame LN-Materialfamilie (Stein,
Metall, Kristall, Rune, Stoff, Mondwasser, Kreaturenhaut), Occlusion-Fade
ohne dithernde Schatten. Keine Regeländerung.

Geprüft: verify_g2 245/245, verify_g1 443/443, Regeln 91/91 und 73/73,
Stress 17/17, Balance 40 Partien identisch mit G1, verify_m1 38/38,
verify_m2 14/14, Netz 43/43 und Loopback 12/12, Legacy 209 und 463.
21 Ansichten vorher/nachher (1920x1080), Videos Turmkampf und Bossbegegnung,
Leistung G1/G2 auf demselben Mac (+0,5 ms in vollen Kampfansichten).
Pakete 0.17.0-g2 für macOS (Universal, ad-hoc signiert), Windows x64/ARM64
und Linux; macOS nativ und unter Rosetta, beide Windows-Pakete in Windows 11
ARM (Parallels, OpenGL-Fallback) mit --lune-smoke bestanden.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 14:12:49 +02:00

79 lines
3.1 KiB
GDScript

extends Node
## Quick look-dev captures from the real game camera (G2 iteration aid, not an acceptance
## tool). Every shot is "name@x,z,zoom[,yaw_steps]" in world metres; shots are separated by ";".
## Run: godot --path . --resolution 1920x1080 res://tools/luneraria/g2_probe.tscn -- --out=/tmp/probe/ \
## --shots="grotto@-13.5,-13.5,20;gate@-18,-18,16,2" [--hud=0] [--round=10] [--wait=1.5]
## [--boss-claim=0|1] [--hp=id:fraction,...] [--combat=seconds]
const Game = preload("res://scripts/luneraria/lune_game.gd")
var out: String = "/tmp/probe/"
var shots: Array = []
var hud: bool = true
var round_number: int = -1
var wait_seconds: float = 1.2
var claim: int = -1
var hp: Dictionary = {}
var combat_seconds: float = -1.0
var game: Node3D
func _ready() -> void:
for arg: String in OS.get_cmdline_user_args():
var value: String = arg.get_slice("=", 1)
if arg.begins_with("--out="):
out = value if value.ends_with("/") else value + "/"
elif arg.begins_with("--shots="):
for spec: String in value.split(";", false):
var name: String = spec.get_slice("@", 0)
var numbers: PackedFloat64Array = []
for part: String in spec.get_slice("@", 1).split(","):
numbers.append(float(part))
shots.append([name, numbers])
elif arg.begins_with("--hud="):
hud = value != "0"
elif arg.begins_with("--round="):
round_number = int(value)
elif arg.begins_with("--wait="):
wait_seconds = float(value)
elif arg.begins_with("--boss-claim="):
claim = int(value)
elif arg.begins_with("--combat="):
combat_seconds = float(value)
elif arg.begins_with("--hp="):
for pair: String in value.split(",", false):
hp[pair.get_slice(":", 0)] = float(pair.get_slice(":", 1))
call_deferred("run")
func run() -> void:
Soundscape.enabled = false
game = Game.new()
add_child(game)
game.start({"seed": 4, "human_slot": 1, "bunds": ["wurzelbund", "wurzelbund", "glutpakt", "glutpakt", "wurzelbund", "glutpakt"]})
await get_tree().process_frame
var state: LuneMatch = game.match_state
if round_number > 0:
state.round_number = round_number
if claim >= 0:
state.boss.claim = {"team": claim, "won_round": state.round_number - 1, "deploy_round": state.round_number, "chooser_slot": claim * 3, "lane": "top"}
state.boss.next_available_round = state.round_number + 3
for id: String in hp:
state.building_hp[id] = float(state.map.building_def(id).max_hp) * float(hp[id])
if combat_seconds >= 0.0:
game._on_ready()
await get_tree().process_frame
while state.phase == LuneMatch.Phase.COMBAT and state.combat.elapsed < combat_seconds:
for i: int in range(20):
state.step_combat()
await get_tree().process_frame
game.paused = true
game.hud.visible = hud
for shot: Array in shots:
var numbers: PackedFloat64Array = shot[1]
if numbers.size() > 3:
game.camera._goal_yaw = numbers[3] * PI * .25
game.camera.look_at_point(Vector3(numbers[0], 0, numbers[1]), numbers[2], true)
await get_tree().create_timer(wait_seconds).timeout
await RenderingServer.frame_post_draw
DirAccess.make_dir_recursive_absolute(out)
get_viewport().get_texture().get_image().save_png(out + str(shot[0]) + ".png")
print("PROBE ", shot[0])
get_tree().quit()