extends Node const AI = preload("res://scripts/ai/simple_ai.gd") var main: Node3D var checks: int = 0 var failures: Array[String] = [] var expedition: bool = "--expedition" in OS.get_cmdline_user_args() func check(value: bool, message: String) -> void: checks += 1 if not value: failures.append(message) printerr("RUNTIME_FAIL: ", message) func key(code: Key) -> void: var event := InputEventKey.new() event.keycode = code event.pressed = true get_viewport().push_input(event,true) event = event.duplicate() event.pressed = false get_viewport().push_input(event,true) func _ready() -> void: call_deferred("run") func run() -> void: GameState.reset_match() GameState.factions = ["glutpakt", "glutpakt"] GameState.timed_build = true GameState.select_mode(GameState.MODE_SHORT) main = load("res://scenes/main.tscn").instantiate() add_child(main) WaveManager.set_physics_process(false) await get_tree().process_frame main.hud._overlay_action.pressed.emit() main.hud._starter_button.pressed.emit() await get_tree().process_frame var cursor := Vector2(530,360) var press := InputEventMouseButton.new() press.position = cursor press.button_index = MOUSE_BUTTON_MIDDLE press.pressed = true get_viewport().push_input(press,true) var motion := InputEventMouseMotion.new() motion.position = cursor + Vector2(90,40) motion.relative = Vector2(90,40) motion.button_mask = MOUSE_BUTTON_MASK_MIDDLE var initial_focus: Vector3 = main._focus get_viewport().push_input(motion,true) press = press.duplicate() press.pressed = false get_viewport().push_input(press,true) check(main._manual_camera and main._focus != initial_focus, "Middle drag pans and disables auto-follow") key(KEY_R) check(not main._manual_camera and main._focus.is_equal_approx(initial_focus), "Reset resumes following") main.hud._ready_button.grab_focus() key(KEY_F1) key(KEY_SPACE) check(GameState.phase == GameState.Phase.BUILD and main.hud.settings_panel.visible, "Ready button cannot activate behind options") key(KEY_ESCAPE) check(main.hud._ready_button.has_focus(), "Closing options restores keyboard focus") # Exercise volume, mute and lane filtering without altering saved preferences. var old_mute: bool = Preferences.muted var old_volume: float = Preferences.volume Preferences.muted = false Preferences.volume = .65 Preferences.apply() Soundscape.enabled = true Soundscape.viewed_team = 0 await get_tree().create_timer(.15).timeout check(Soundscape.play("ability"), "An audible effect starts") check(not Soundscape.play("ability"), "Immediate duplicate effect is rate-limited") check(not Soundscape.play("stone",1,true), "Hidden lane is silent") Preferences.muted = true Preferences.apply() check(not Soundscape.play("error"), "Mute prevents effects") Preferences.muted = false Preferences.apply() # Advance seven regular waves, then render a timed 2x boss fight. GameState.ai_level = GameState.AI_LEARNING if expedition: GameState.reset_match() if "--wurzelbund" in OS.get_cmdline_user_args(): GameState.factions = ["wurzelbund", "wurzelbund"] GameState.select_mode(GameState.MODE_EXPEDITION) GameState.ai_level = GameState.AI_STANDARD WaveManager.start_match() var ai := AI.new() Soundscape.enabled = false var last_wave: int = DataCatalog.wave_count() main.battle.render_enabled = false for number: int in range(1,last_wave+1): ai.plan(0,number,WaveManager.rival_snapshot(),GameState.last_reports[0],GameState.AI_STANDARD) if number == last_wave: main.battle.render_enabled = true WaveManager.ready_for_battle() if number == last_wave: break for step: int in range(5401): if GameState.phase != GameState.Phase.COMBAT: break WaveManager.advance(1.0/60.0) WaveManager.ready_for_battle() GameState.speed = 2 Soundscape.enabled = true WaveManager.set_physics_process(true) await get_tree().create_timer(2.0).timeout var frames: Array[float] = [] var calls: Array[int] = [] var start: int = Time.get_ticks_usec() var previous: int = start var sound_start: int = Soundscape.played var units_start: int = main.battle.units.size() while Time.get_ticks_usec() - start < 12000000: await get_tree().process_frame var now: int = Time.get_ticks_usec() frames.append((now - previous)/1000.0) calls.append(int(Performance.get_monitor(Performance.RENDER_TOTAL_DRAW_CALLS_IN_FRAME))) previous = now frames.sort() calls.sort() var mean: float = 0 for value: float in frames: mean += value mean /= frames.size() var sounds: int = Soundscape.played - sound_start check(sounds > 0 and sounds <= 190, "2x audio stays bounded and produces effects") var result: Dictionary = {"engine": Engine.get_version_info().string, "device": RenderingServer.get_video_adapter_name(), "viewport": str(get_viewport().get_visible_rect().size), "wave": last_wave, "speed": 2, "sample_seconds": 12, "units_at_start": units_start, "frames":frames.size(),"mean_frame_ms":mean,"p95_frame_ms":frames[floori(frames.size()*.95)], "mean_fps":1000.0/mean,"max_draw_calls":calls.back(),"audio_events":sounds,"checks":checks,"failures":failures} var phase: String = "phase10" if "--phase10" in OS.get_cmdline_user_args() else "phase9" if "--wurzelbund" in OS.get_cmdline_user_args() else "phase8" if expedition else ("phase7" if "--phase7" in OS.get_cmdline_user_args() else "phase6") result["renderer"] = RenderingServer.get_current_rendering_method() var file := FileAccess.open("res://docs/" + phase + "-runtime.json", FileAccess.WRITE) file.store_string(JSON.stringify(result,"\t")); file.close() print("PHASE6_RUNTIME: ",JSON.stringify(result)) Preferences.volume = old_volume Preferences.muted = old_mute Preferences.apply() await Soundscape.quit_game(0 if failures.is_empty() else 1)