extends SceneTree ## Exact damage regression + visible game identity. La classifica e' attiva di default ## nelle build di gioco; qui, girando come --script, resta spenta. const Player = preload("res://scripts/player.gd") const Grenade = preload("res://scripts/grenade.gd") const Boss = preload("res://scripts/alien_grunt.gd") const Target = preload("res://tools/grenade_test_target.gd") var checks := 0 var failures := 0 func _initialize() -> void: call_deferred("run_test") func check(ok: bool, label: String) -> void: checks += 1 if not ok: failures += 1 print("PASS: " if ok else "FAIL: ", label) func run_test() -> void: check(Player.BULLET_DAMAGE == 17.5, "fucile: 35 -> 17,5 senza arrotondamento") check(Grenade.MAX_DAMAGE == 320 and Grenade.BLAST_RADIUS == 5, "granata: 160 -> 320, raggio invariato a 5m") check(Boss.stats_for_wave(10).ranged == 8 and Boss.stats_for_wave(20).ranged == 10, "proiettili alieni invariati a tutti i gradi") check(ProjectSettings.get_setting("application/config/name") == "Work-Death Balance", "titolo nativo del progetto aggiornato") var icon: Texture2D = load(ProjectSettings.get_setting("application/config/icon")) check(icon != null and icon.get_size() == Vector2(512, 512), "icona del progetto caricata, 512x512") var preset := ConfigFile.new() preset.load("res://export_presets.cfg") check(preset.get_value("preset.0.options", "html/export_icon", false), "favicon Web abilitata tramite esportazione icona ufficiale") var world = load("res://scenes/main.tscn").instantiate() root.add_child(world) # first real renamed startup also exercises profile migration world.player.set_physics_process(false) world.player.hp = 100000 world.player.position = Vector3(0, 0.1, 2) Input.mouse_mode = Input.MOUSE_MODE_VISIBLE var title_found := false for label in world.start_screen.find_children("*", "Label", true, false): if label.text == "Work-Death Balance": title_found = true check(title_found, "menu mostra Work-Death Balance") check(world.leaderboard.disabled and world.leaderboard.base_url == "", "suite di test: nessun invio alla classifica pubblica") var zombie = load("res://scripts/zombie.gd").new() zombie.player = world.player zombie.position = Vector3(0, 0.05, -3) world.add_child(zombie) zombie.entering = false zombie.set_physics_process(false) world.player.camera.look_at(zombie.position + Vector3.UP) await physics_frame await physics_frame world.player.shoot() check(is_equal_approx(zombie.hp, 82.5), "colpo reale al corpo: esattamente 17,5 danni") world.player.camera.look_at(zombie.position + Vector3.UP * 1.7) world.player.shoot() check(is_equal_approx(zombie.hp, 38.75), "headshot zombie: 43,75 danni, moltiplicatore 2,5 invariato") zombie.queue_free() await process_frame var near := Target.new() near.position = Vector3(0, 0, -1) world.add_child(near) var half := Target.new() half.position = Vector3(0, 0, -2.5) world.add_child(half) var far := Target.new() far.position = Vector3(0, 0, -6) world.add_child(far) var grenade := Grenade.new() grenade.position = Vector3(0, 0.9, 0) grenade.thrower = world.player world.add_child(grenade) grenade.freeze = true var hp_before: float = world.player.hp var player_distance: float = grenade.position.distance_to(world.player.position + Vector3.UP * 0.9) var expected_self_damage := 320.0 * (1.0 - player_distance / 5.0) grenade._request_detonation(grenade.position) await process_frame await process_frame check(is_equal_approx(near.damage_taken, 256.0), "esplosione a 1m: 256 danni, decadimento lineare invariato") check(is_equal_approx(half.damage_taken, 160.0), "esplosione a 2,5m: 160 danni, il doppio di prima") check(far.damage_taken == 0, "nessun danno oltre il raggio originale") check(is_equal_approx(hp_before - world.player.hp, expected_self_damage), "danno dell'esplosione al tiratore raddoppiato con lo stesso decadimento") world.queue_free() await process_frame print(checks - failures, " controlli superati, ", failures, " falliti") quit(1 if failures else 0)