extends SceneTree ## 难度小怪血量倍率:简单保持基准 650,普通 ×3 = 1950,困难 ×5 = 3250。 ## 注意 --script 测试模式下 autoload 同样会加载,GameSettings 始终存在, ## 因此这里显式钉住难度(直接写字段、不落盘),逐档验证。 var failures: Array[String] = [] func _init() -> void: _run.call_deferred() func _run() -> void: await process_frame _ensure_named_node("EventBus", "res://autoload/event_bus.gd") _ensure_named_node("TimePhaseManager", "res://autoload/time_phase_manager.gd") var settings := _ensure_named_node("GameSettings", "res://autoload/game_settings.gd") _expect_float(float(settings.call("minion_health_multiplier", &"easy")), 1.0, "easy multiplier") _expect_float(float(settings.call("minion_health_multiplier", &"normal")), 3.0, "normal multiplier") _expect_float(float(settings.call("minion_health_multiplier", &"hard")), 5.0, "hard multiplier") settings.set("difficulty", &"easy") _expect_int(await _spawn_minion_max_health(), 650, "easy minion HP keeps the 650 baseline") settings.set("difficulty", &"normal") _expect_int(await _spawn_minion_max_health(), 1950, "normal minion HP is 3x the baseline") settings.set("difficulty", &"hard") _expect_int(await _spawn_minion_max_health(), 3250, "hard minion HP is 5x the baseline") # Boss 不吃小怪倍率:难度仍为 hard 时 Boss 血量保持自身导出值。 settings.set("difficulty", &"hard") var boss_scene: PackedScene = load("res://scenes/enemies/boss.tscn") if boss_scene != null: var boss := boss_scene.instantiate() root.add_child(boss) await process_frame var boss_health := boss.get_node_or_null("HealthComponent") if boss_health != null: _expect_int(int(boss_health.get("maximum")), int(boss.get("max_health")), "boss HP must not scale with the minion multiplier") boss.queue_free() await process_frame settings.set("difficulty", &"normal") _finish() func _spawn_minion_max_health() -> int: var scene: PackedScene = load("res://scenes/enemies/minion.tscn") if scene == null: failures.append("minion scene failed to load") return -1 var minion: Node2D = scene.instantiate() root.add_child(minion) await process_frame var health := minion.get_node_or_null("HealthComponent") if health == null: failures.append("minion has no HealthComponent") minion.queue_free() await process_frame return -1 var maximum := int(health.get("maximum")) var current := int(health.get("current")) if current != maximum: failures.append("minion should spawn at full HP: %d / %d" % [current, maximum]) minion.queue_free() await process_frame return maximum func _ensure_named_node(node_name: String, script_path: String) -> Node: var existing := root.get_node_or_null(node_name) if existing != null: return existing var node: Node = load(script_path).new() node.name = node_name root.add_child(node) return node func _expect_int(actual: int, expected: int, label: String) -> void: if actual != expected: failures.append("%s: expected %d, got %d" % [label, expected, actual]) func _expect_float(actual: float, expected: float, label: String) -> void: if not is_equal_approx(actual, expected): failures.append("%s: expected %f, got %f" % [label, expected, actual]) func _finish() -> void: if failures.is_empty(): print("PASS difficulty minion health") quit(0) else: for failure: String in failures: push_error(failure) quit(1)