extends Node ## Comparison captures for the graphics phases G1–G6, always from the real game camera ## and the real HUD at the running window size (use 1920x1080). ## Run: godot --path . --resolution 1920x1080 res://tools/luneraria/g_views.tscn -- --out=res://docs/luneraria/screenshots/g1/nachher ## Views: 01 map, 02–04 lanes in combat, 05/06 bases, 07 grotto, 08 many units, 09 HUD, ## 10 hero selected, 11 close zoom, 12 camera in motion. Match and fixture are fixed ## (seed 4, Wurzelbund on Mid) so every phase is photographed the same way. Fixture gold ## only exists in this capture run; the rules are the ones of the running build. const Game = preload("res://scripts/luneraria/lune_game.gd") var out: String = "res://docs/luneraria/screenshots/g1/nachher/" var main: Node var shots: Array[String] = [] func _ready() -> void: for arg: String in OS.get_cmdline_user_args(): if arg.begins_with("--out="): out = arg.substr(6) if not out.ends_with("/"): out += "/" call_deferred("run") func shot(label: String, frames: int = 14) -> void: for i: int in frames: await get_tree().process_frame await RenderingServer.frame_post_draw DirAccess.make_dir_recursive_absolute(ProjectSettings.globalize_path(out)) get_viewport().get_texture().get_image().save_png(out + label + ".png") shots.append(label) print("G_VIEW ", label) ## Camera helpers that only use public map data, so they frame old and new layouts alike. func grotto_point(game: Node3D) -> Vector2: var map: LuneMap = game.match_state.map return map.grotto_center() if map.has_method("grotto_center") else LuneMap.GROTTO func look(game: Node3D, at: Vector2, zoom: float) -> void: game.camera.look_at_point(Vector3(at.x, 0, at.y), zoom, true) ## Runs the combat clock quickly (more fixed steps per frame, rules unchanged) and holds it. func advance_combat(game: Node3D, seconds: float) -> void: var state: LuneMatch = game.match_state game.paused = false while state.phase == LuneMatch.Phase.COMBAT and state.combat.elapsed < seconds: for i: int in range(20): if state.phase != LuneMatch.Phase.COMBAT or state.combat.elapsed >= seconds: break state.step_combat() await get_tree().process_frame game.paused = true ## Documentation only (not a game view): orthographic top-down plan without the HUD. func plan_view(game: Node3D) -> void: var plan := Camera3D.new() plan.projection = Camera3D.PROJECTION_ORTHOGONAL plan.size = 86.0 plan.far = 400.0 game.add_child(plan) plan.position = Vector3(0, 150, 0) plan.rotation = Vector3(-PI * .5, 0, 0) plan.current = true game.hud.visible = false await shot("00-kartenplan-draufsicht", 10) game.hud.visible = true game.camera.current = true plan.queue_free() func run() -> void: Soundscape.enabled = false main = load("res://scenes/luneraria.tscn").instantiate() add_child(main) var menu: MainMenu = main.menu while not (menu.stage.is_ready("glutpakt") and menu.stage.is_ready("wurzelbund")): await get_tree().process_frame menu.bund = "wurzelbund" menu.lane = "mid" main.start_match({"seed": 4}) await get_tree().create_timer(.8).timeout var game: Node3D = main.game var state: LuneMatch = game.match_state var slot: int = game.human_slot # Fixture: enough gold for a hero with one item next to the starting army. state.players[slot].draft.gold = 900 game._on_command({"type": "hero_buy", "hero_id": "held_ringborke"}) game._on_command({"type": "item_buy", "item_id": "basaltschild"}) game.hud._starter.pressed.emit() game.hud.show_page(0) game.focus_lane("mid", true) await shot("09-hud-planung", 24) game.hud.show_page(1) await shot("10-held-ausgewaehlt") game.hud.show_page(0) game.camera.overview(true) await shot("01-karte", 20) await plan_view(game) look(game, state.map.core_position(0), 26.0) await shot("05-eigene-basis") look(game, state.map.core_position(1), 26.0) await shot("06-gegnerbasis") look(game, grotto_point(game), 22.0) await shot("07-bossgrotte") game._on_ready() await get_tree().process_frame await advance_combat(game, 16.0) var names := {"top": "02-top-lane", "mid": "03-mid-lane", "bot": "04-bottom-lane"} for lane: String in LuneMap.LANES: game.focus_lane(lane, true) await shot(names[lane]) # Camera in motion: a real, non-instant pan from Mid towards the own base. game.focus_lane("mid", true) await get_tree().process_frame var base: Vector2 = state.map.core_position(0) game.camera.look_at_point(Vector3(base.x, 0, base.y), 30.0, false) await shot("12-kamera-bewegt", 5) # Many units: all six armies at the supply cap in a round-13 wave (capture fixture). main.queue_free() await get_tree().process_frame var crowd: Node3D = Game.new() add_child(crowd) crowd.start({"seed": 5, "human_slot": 1}) var crowd_state: LuneMatch = crowd.match_state crowd_state.round_number = 13 for other: int in range(6): crowd_state.players[other].draft.gold = 100000 crowd_state.players[other].draft.roster.clear() LuneBot.plan(crowd_state, other, "ausgewogen") crowd._on_ready() await get_tree().process_frame await advance_combat(crowd, 13.0) crowd.focus_lane("mid", true) await shot("08-kampf-viele-einheiten", 20) var fight: Vector2 = crowd_state.map.lane_point(0, "mid", crowd_state.map.lanes["mid"].length * .5) look(crowd, fight, 13.0) await shot("11-zoom-nah") print("G_VIEWS_DONE ", shots.size()) get_tree().quit()