extends GutTest var ArcherTower_scene = preload("res://Game/Towers/archer_tower.tscn") var tower func before_each(): tower = ArcherTower_scene.instantiate() add_child(tower) gut.p("════════════════════════════════════════") gut.p("Setting up test with fresh tower instance") gut.p("════════════════════════════════════════") func after_each(): gut.p("─────────────────────────────────────────") gut.p("Cleaning up test resources...") # Clean up all spawned bullets from the test's children var bullets_to_remove = [] var bullet_count = 0 for child in get_children(): if child.name.begins_with("Arrow") or child.name.begins_with("Magic") or child.name.begins_with("Rock"): bullets_to_remove.append(child) bullet_count += 1 gut.p("Found %d bullets to remove: %s" % [bullet_count, bullets_to_remove.map(func(b): return b.name)]) for bullet in bullets_to_remove: bullet.queue_free() if tower and not tower.is_queued_for_deletion(): tower.queue_free() gut.p("Tower cleaned up successfully") gut.p("─────────────────────────────────────────\n") func test_properties_initialize(): gut.p("\n▶ TEST: Properties Initialize") gut.p(" Checking default tower property values...") gut.p(" → shootingTime: %s (expected: 0)" % tower.shootingTime) assert_eq(tower.shootingTime, 0) gut.p(" → bulletSpeed: %s (expected: 600)" % tower.bulletSpeed) assert_eq(tower.bulletSpeed, 600) gut.p(" → hitpoint: %s (expected: 25)" % tower.hitpoint) assert_eq(tower.hitpoint, 25) gut.p(" → follower: %s (expected: true)" % tower.follower) assert_eq(tower.follower, true) gut.p(" → target: %s (expected: null)" % tower.target) assert_eq(tower.target, null) gut.p(" ✓ All default properties initialized correctly") func test_set_properties_archer_tower(): gut.p("\n▶ TEST: Set Properties - Archer Tower") tower.name = "ArcherTower" gut.p(" Tower name set to: %s" % tower.name) tower.set_properties() gut.p(" set_properties() called") var timer_wait = tower.get_node("Timer").wait_time gut.p(" → Timer wait_time: %s (expected: 0.5 ±0.01)" % timer_wait) assert_almost_eq(timer_wait, 0.5, 0.01) gut.p(" → bulletSpeed: %s (expected: 600)" % tower.bulletSpeed) assert_eq(tower.bulletSpeed, 600) gut.p(" → hitpoint: %s (expected: 25)" % tower.hitpoint) assert_eq(tower.hitpoint, 25) var radius = tower.get_node("CharacterBody2D/Area2D/CollisionShape2D").shape.radius gut.p(" → Detection radius: %s (expected: 150)" % radius) assert_eq(radius, 150) gut.p(" ✓ Archer tower properties set correctly") func test_set_properties_wizard_tower(): gut.p("\n▶ TEST: Set Properties - Wizard Tower") tower.name = "WizardTower" gut.p(" Tower name set to: %s" % tower.name) tower.set_properties() gut.p(" set_properties() called") var timer_wait = tower.get_node("Timer").wait_time gut.p(" → Timer wait_time: %s (expected: 1.0 ±0.01)" % timer_wait) assert_almost_eq(timer_wait, 1.0, 0.01) gut.p(" → bulletSpeed: %s (expected: 450)" % tower.bulletSpeed) assert_eq(tower.bulletSpeed, 450) gut.p(" → hitpoint: %s (expected: 15)" % tower.hitpoint) assert_eq(tower.hitpoint, 15) gut.p(" ✓ Wizard tower properties set correctly") func test_set_properties_mortar_tower(): gut.p("\n▶ TEST: Set Properties - Mortar Tower") tower.name = "MortarTower" gut.p(" Tower name set to: %s" % tower.name) tower.set_properties() gut.p(" set_properties() called") var timer_wait = tower.get_node("Timer").wait_time gut.p(" → Timer wait_time: %s (expected: 2.0 ±0.01)" % timer_wait) assert_almost_eq(timer_wait, 2.0, 0.01) gut.p(" → hitpoint: %s (expected: 80)" % tower.hitpoint) assert_eq(tower.hitpoint, 80) gut.p(" ✓ Mortar tower properties set correctly") func test_archer_tower_shoots_arrow(): gut.p("\n▶ TEST: Archer Tower Shoots Arrow") tower.name = "ArcherTower" gut.p(" Tower name set to: %s" % tower.name) tower._ready() gut.p(" Tower _ready() called") var dummy_target = Node2D.new() tower.target = dummy_target gut.p(" Dummy target assigned to tower.target") var bullets_before = 0 for child in tower.get_parent().get_children(): if child.name.begins_with("Arrow") or child.name.begins_with("Magic") or child.name.begins_with("Rock"): bullets_before += 1 gut.p(" Bullets in scene before shoot(): %d" % bullets_before) tower.shoot() gut.p(" shoot() called") var found_arrow = false var arrow_name = "" for child in tower.get_parent().get_children(): if child.name.begins_with("Arrow"): found_arrow = true arrow_name = child.name break if found_arrow: gut.p(" ✓ Arrow created successfully: %s" % arrow_name) else: gut.p(" ✗ No arrow found after shoot() call") assert_true(found_arrow) dummy_target.queue_free() gut.p(" ✓ Archer tower successfully shoots arrows") func test_wizard_tower_shoots_magic(): gut.p("\n▶ TEST: Wizard Tower Shoots Magic") tower.name = "WizardTower" gut.p(" Tower name set to: %s" % tower.name) tower._ready() gut.p(" Tower _ready() called") var dummy_target = Node2D.new() tower.target = dummy_target gut.p(" Dummy target assigned to tower.target") var bullets_before = 0 for child in tower.get_parent().get_children(): if child.name.begins_with("Arrow") or child.name.begins_with("Magic") or child.name.begins_with("Rock"): bullets_before += 1 gut.p(" Bullets in scene before shoot(): %d" % bullets_before) tower.shoot() gut.p(" shoot() called") var found_magic = false var magic_name = "" for child in tower.get_parent().get_children(): if child.name.begins_with("Magic"): found_magic = true magic_name = child.name break if found_magic: gut.p(" ✓ Magic projectile created successfully: %s" % magic_name) else: gut.p(" ✗ No magic projectile found after shoot() call") assert_true(found_magic) dummy_target.queue_free() gut.p(" ✓ Wizard tower successfully shoots magic") func test_mortar_tower_lifter_animates(): gut.p("\n▶ TEST: Mortar Tower Lifter Animation") tower.name = "MortarTower" gut.p(" Tower name set to: %s" % tower.name) tower._ready() gut.p(" Tower _ready() called") tower.lifter = false tower.lifteramount = 0 gut.p(" Lifter state reset: lifter=%s, lifteramount=%d" % [tower.lifter, tower.lifteramount]) var dummy_target = Node2D.new() tower.target = dummy_target gut.p(" Dummy target assigned to tower.target") gut.p(" Checking initial lifter state...") assert_false(tower.lifter) gut.p(" → Initial lifter: false ✓") tower.shoot() gut.p(" shoot() called") gut.p(" Checking lifter state after shoot()...") var lifter_state = tower.lifter var lifter_amount = tower.lifteramount gut.p(" → Lifter state after shoot(): %s (expected: true)" % lifter_state) assert_true(tower.lifter) gut.p(" → Lifter amount: %d (expected: 0)" % lifter_amount) assert_eq(tower.lifteramount, 0) dummy_target.queue_free() gut.p(" ✓ Mortar tower lifter animation triggered correctly") func test_no_shoot_without_target(): gut.p("\n▶ TEST: No Shoot Without Target") tower.name = "ArcherTower" gut.p(" Tower name set to: %s" % tower.name) tower._ready() gut.p(" Tower _ready() called") var initial_bullet_count = 0 for child in tower.get_parent().get_children(): if child.name.begins_with("Arrow") or child.name.begins_with("Magic") or child.name.begins_with("Rock"): initial_bullet_count += 1 gut.p(" Initial bullet count in scene: %d" % initial_bullet_count) tower.target = null gut.p(" Tower target set to: null") gut.p(" Calling shoot() with no target...") tower.shoot() var final_bullet_count = 0 for child in tower.get_parent().get_children(): if child.name.begins_with("Arrow") or child.name.begins_with("Magic") or child.name.begins_with("Rock"): final_bullet_count += 1 gut.p(" Final bullet count in scene: %d" % final_bullet_count) var new_bullets_created = final_bullet_count - initial_bullet_count gut.p(" New bullets created: %d (expected: 0)" % new_bullets_created) assert_eq(new_bullets_created, 0) gut.p(" ✓ Tower correctly prevented shooting without target")