extends SceneTree const BattleStateScript := preload("res://scripts/core/battle_state.gd") func _init() -> void: var failures: Array[String] = [] var state = BattleStateScript.new() if not state.load_battle("res://data/scenarios/009_xiapi_siege.json"): push_error("Could not load Xiapi smoke scenario.") quit(1) return _check_single_withdraw(state, failures) _check_multi_withdraw(state, failures) if failures.is_empty(): print("event withdraw smoke ok") quit(0) return for failure in failures: push_error(failure) quit(1) func _check_single_withdraw(state, failures: Array[String]) -> void: var logs := [] var feedback := [] state.log_added.connect(func(message: String) -> void: logs.append(message) ) state.combat_feedback_requested.connect(func(unit_id: String, text: String, kind: String) -> void: feedback.append({"unit_id": unit_id, "text": text, "kind": kind}) ) _spawn_smoke_unit(state, "withdraw_smoke_enemy", "Smoke Raider", Vector2i(4, 4)) logs.clear() feedback.clear() var before_living: int = state.get_living_units("enemy").size() state._execute_event_action({"type": "withdraw_unit", "unit_id": "withdraw_smoke_enemy"}) var unit: Dictionary = state.get_unit("withdraw_smoke_enemy") if unit.is_empty(): failures.append("single withdraw smoke unit disappeared from state") return if bool(unit.get("deployed", true)): failures.append("single withdraw unit should no longer be deployed") if not bool(unit.get("alive", false)): failures.append("single withdraw unit should stay alive for non-defeat retreat semantics") if not state.get_unit_at(Vector2i(4, 4)).is_empty(): failures.append("single withdraw unit should no longer occupy its map cell") if state.get_living_units("enemy").size() != before_living - 1: failures.append("single withdraw should remove one living enemy from battle counts") _check_log_contains(failures, logs, "Smoke Raider withdraws from the battlefield.") _check_feedback_contains(failures, feedback, "withdraw_smoke_enemy", "WITHDRAW", "fade") func _check_multi_withdraw(state, failures: Array[String]) -> void: _spawn_smoke_unit(state, "withdraw_smoke_north", "North Raider", Vector2i(5, 4)) _spawn_smoke_unit(state, "withdraw_smoke_south", "South Raider", Vector2i(6, 4)) state._execute_event_action({ "type": "withdraw_units", "unit_ids": ["withdraw_smoke_north", "withdraw_smoke_south"] }) for unit_id in ["withdraw_smoke_north", "withdraw_smoke_south"]: var unit: Dictionary = state.get_unit(unit_id) if unit.is_empty(): failures.append("multi withdraw unit missing from state: %s" % unit_id) continue if bool(unit.get("deployed", true)): failures.append("multi withdraw unit should no longer be deployed: %s" % unit_id) if not bool(unit.get("alive", false)): failures.append("multi withdraw unit should stay alive: %s" % unit_id) func _spawn_smoke_unit(state, unit_id: String, unit_name: String, cell: Vector2i) -> void: state._execute_event_action({ "type": "spawn_deployment", "deployment": { "unit_id": unit_id, "name": unit_name, "class_id": "cavalry", "team": "enemy", "level": 8, "pos": [cell.x, cell.y], "base": {"hp": 40, "atk": 15, "def": 8, "agi": 11} } }) func _check_log_contains(failures: Array[String], logs: Array, expected: String) -> void: for log_entry in logs: if str(log_entry) == expected: return failures.append("expected log `%s` in `%s`" % [expected, logs]) func _check_feedback_contains( failures: Array[String], feedback: Array, expected_unit_id: String, expected_text: String, expected_kind: String ) -> void: for entry in feedback: if ( str(entry.get("unit_id", "")) == expected_unit_id and str(entry.get("text", "")) == expected_text and str(entry.get("kind", "")) == expected_kind ): return failures.append("expected feedback `%s/%s/%s` in `%s`" % [ expected_unit_id, expected_text, expected_kind, feedback ])