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_panacea_cleanses_debuffs(failures) _check_no_effect_panacea_is_not_consumed(failures) _check_panacea_menu_text(failures) if failures.is_empty(): print("item debuff cleanse smoke ok") quit(0) return for failure in failures: push_error(failure) quit(1) func _check_panacea_cleanses_debuffs(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 cao_cao: Dictionary = state.get_unit("cao_cao") if cao_cao.is_empty(): failures.append("missing Cao Cao") return cao_cao["status_effects"] = _mixed_status_effects() state.battle_inventory["panacea"] = 1 var preview: Dictionary = state.get_item_preview("cao_cao", "panacea", cao_cao["pos"]) var cure_names: Array = preview.get("cure_statuses", []) for expected in ["Poison", "Seal", "ATK down", "MOVE down"]: if not cure_names.has(expected): failures.append("Panacea preview should include %s in %s" % [expected, str(cure_names)]) var logs: Array[String] = [] var feedback: Array[String] = [] 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("%s|%s|%s" % [unit_id, text, kind]) ) if not state.select_unit("cao_cao"): failures.append("could not select Cao Cao") return if not state.try_use_selected_item_on_cell("panacea", cao_cao["pos"]): failures.append("Panacea should apply to Cao Cao with poison, seal, and debuffs") return if int(state.get_inventory_snapshot().get("panacea", 0)) != 0: failures.append("Panacea should be consumed after cleansing") var summary := state.get_status_effect_summary("cao_cao") if not summary.contains("DEF +4"): failures.append("Panacea should keep positive buffs: %s" % summary) for removed_text in ["ATK -3", "MOVE -1", "Poison", "Seal"]: if summary.contains(removed_text): failures.append("Panacea should remove %s from summary: %s" % [removed_text, summary]) _check_log_contains(failures, logs, "Cao Cao is cured of Poison.") _check_log_contains(failures, logs, "Cao Cao is cured of Seal.") _check_log_contains(failures, logs, "Cao Cao is cleansed of ATK down, MOVE down.") if not feedback.has("cao_cao|CLEANSE|support"): failures.append("Panacea cleanse feedback missing: %s" % str(feedback)) func _check_no_effect_panacea_is_not_consumed(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 for no-effect check") return var cao_cao: Dictionary = state.get_unit("cao_cao") cao_cao["status_effects"] = [{ "source_skill": "guard_order", "name": "Guard Order", "type": "stat_bonus", "stat": "def", "amount": 4, "remaining_phases": 2 }] state.battle_inventory["panacea"] = 1 if not state.select_unit("cao_cao"): failures.append("could not select Cao Cao for no-effect check") return if state.try_use_selected_item_on_cell("panacea", cao_cao["pos"]): failures.append("Panacea should not apply when only positive buffs are active") if int(state.get_inventory_snapshot().get("panacea", 0)) != 1: failures.append("No-effect Panacea should not be consumed") func _check_panacea_menu_text(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 for menu text") scene.free() return var text := scene._format_item_effect_text(scene.state.get_item_def("panacea")) if not text.contains("Cleanse debuffs"): failures.append("Panacea menu text should mention debuff cleanse: %s" % text) scene.free() func _mixed_status_effects() -> Array: return [ { "source_skill": "disrupt_order", "name": "Disrupt Order", "type": "stat_bonus", "stat": "atk", "amount": -3, "remaining_phases": 2 }, { "source_skill": "hamper_order", "name": "Hamper Order", "type": "stat_bonus", "stat": "move", "amount": -1, "remaining_phases": 2 }, { "source_skill": "guard_order", "name": "Guard Order", "type": "stat_bonus", "stat": "def", "amount": 4, "remaining_phases": 2 }, { "source_skill": "poison_mist", "name": "Poison Mist", "type": "damage_over_time", "status": "poison", "amount": 4, "remaining_phases": 2 }, { "source_skill": "seal_tactic", "name": "Seal Tactic", "type": "action_lock", "status": "seal", "action": "skill", "remaining_phases": 2 } ] 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, str(logs)])