extends SceneTree const BattleStateScript := preload("res://scripts/core/battle_state.gd") const BattleSceneScript := preload("res://scripts/scenes/battle_scene.gd") func _init() -> void: var failures: Array[String] = [] _check_battle_visual_data(failures) _check_scene_texture_loading(failures) _check_attack_motion_signal(failures) if failures.is_empty(): print("visual assets smoke ok") quit(0) return for failure in failures: push_error(failure) quit(1) func _check_battle_visual_data(failures: Array[String]) -> void: var state = BattleStateScript.new() if not state.load_battle("res://data/scenarios/001_yellow_turbans.json"): failures.append("could not load opening battle") return var briefing := state.get_briefing() if (briefing.get("camp_dialogue", []) as Array).is_empty(): failures.append("001 briefing should expose camp dialogue") var merchant := state.get_shop_merchant() if merchant.is_empty() or (merchant.get("lines", []) as Array).is_empty(): failures.append("001 shop should expose merchant lines") _check_image_path(failures, state.get_map_background_path(), "001 map background") for unit_id in ["cao_cao", "xiahou_dun", "yellow_turban_1", "yellow_turban_2", "yellow_turban_3"]: var unit := state.get_unit(unit_id) if unit.is_empty(): failures.append("missing expected unit: %s" % unit_id) continue _check_image_path(failures, str(unit.get("sprite", "")), "unit %s sprite" % unit_id) for item_id in ["bronze_sword", "training_spear", "short_bow", "hand_axe", "iron_armor", "panacea"]: var item := state.get_item_def(item_id) if item.is_empty(): failures.append("missing expected item: %s" % item_id) continue _check_image_path(failures, str(item.get("icon", "")), "item %s icon" % item_id) func _check_scene_texture_loading(failures: Array[String]) -> void: var scene = BattleSceneScript.new() if not scene.state.load_battle("res://data/scenarios/001_yellow_turbans.json"): failures.append("could not load battle scene state") scene.free() return if scene._current_battle_background_texture() == null: failures.append("battle scene should load a battlefield background texture") var archer: Dictionary = scene.state.get_unit("yellow_turban_3") if scene._load_art_texture(str(archer.get("sprite", ""))) == null: failures.append("battle scene should load archer sprite texture") var panacea: Dictionary = scene.state.get_item_def("panacea") if scene._load_art_texture(str(panacea.get("icon", ""))) == null: failures.append("battle scene should load panacea icon texture") scene.free() func _check_attack_motion_signal(failures: Array[String]) -> void: var state = BattleStateScript.new() if not state.load_battle("res://data/scenarios/001_yellow_turbans.json"): failures.append("could not load battle for attack motion") return var attacker := state.get_unit("cao_cao") var target := state.get_unit("yellow_turban_1") if attacker.is_empty() or target.is_empty(): failures.append("missing attacker or target for attack motion") return attacker["pos"] = Vector2i(6, 2) target["pos"] = Vector2i(7, 2) var motions: Array[String] = [] state.unit_action_motion_requested.connect(func(unit_id: String, from_cell: Vector2i, to_cell: Vector2i, action_kind: String) -> void: motions.append("%s|%s|%d,%d|%d,%d" % [unit_id, action_kind, from_cell.x, from_cell.y, to_cell.x, to_cell.y]) ) if not state.select_unit("cao_cao"): failures.append("could not select Cao Cao for attack motion") return if not state.try_attack_selected("yellow_turban_1"): failures.append("Cao Cao should be able to attack adjacent target") return if not motions.has("cao_cao|attack|6,2|7,2"): failures.append("attack motion signal missing expected Cao Cao attack: %s" % str(motions)) func _check_image_path(failures: Array[String], path: String, context: String) -> void: if path.is_empty(): failures.append("%s has an empty image path" % context) return if not path.begins_with("res://"): failures.append("%s must use a res:// path: %s" % [context, path]) return if not FileAccess.file_exists(path): failures.append("%s references missing image: %s" % [context, path]) return var image := Image.new() var err := image.load(path) if err != OK: failures.append("%s references unreadable image: %s" % [context, path]) return if image.get_width() < 512 or image.get_height() < 512: failures.append("%s image should be at least 512x512: %s (%dx%d)" % [context, path, image.get_width(), image.get_height()])