99 lines
3.4 KiB
GDScript
99 lines
3.4 KiB
GDScript
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)
|