extends SceneTree var failures: Array[String] = [] func _init() -> void: _run.call_deferred() func _run() -> void: var exporter: Script = load("res://tools/export_action_patterns.gd") _expect(exporter != null, "Action pattern export tool should load") if exporter != null: var patterns: Dictionary = exporter.call("export_patterns") var expected := { "A": &"ground_attack_left_1", "AA": &"ground_attack_left_2", "AAA": &"ground_attack_left_3", "ASP": &"dash_slash_left", "AASP": &"combo_finisher_left", "AAASP": &"ground_smash_left", "D": &"ground_attack_right_1", "DD": &"ground_attack_right_2", "DDD": &"ground_attack_right_3", "DSP": &"dash_slash_right", "DDSP": &"combo_finisher_right", "DDDSP": &"ground_smash_right", "W": &"launcher_up", "S": &"block_start", } _expect_int(patterns.size(), expected.size(), "Exported pattern count") for key: String in expected: _expect(patterns.get(key) == expected[key], "Pattern %s should map to %s" % [key, expected[key]]) for forbidden_key: String in ["AD", "DA", "ASPSP"]: _expect(not patterns.has(forbidden_key), "Forbidden pattern %s should not be exported" % forbidden_key) _expect(not patterns.has("SS"), "SS should not be exported as a separate skill; runtime should reuse trailing S block fallback") var text := str(exporter.call("to_text")) _expect(text.contains("A -> ground_attack_left_1"), "Pattern export text should include A") _expect(text.contains("W -> launcher_up"), "Pattern export text should include W") _expect(text.contains("S -> block_start"), "Pattern export text should include S") _finish() func _expect(condition: bool, label: String) -> void: if not condition: failures.append(label) func _expect_int(actual: int, expected: int, label: String) -> void: if actual != expected: failures.append("%s: expected %d, got %d" % [label, expected, actual]) func _finish() -> void: if failures.is_empty(): print("PASS action pattern export") quit(0) else: for failure: String in failures: push_error(failure) quit(1)