GUT tests for towers and enemy
This commit is contained in:
51
README.md
51
README.md
@ -1,51 +0,0 @@
|
|||||||
# Tokebi Metrics Godot Plugin
|
|
||||||
|
|
||||||
An analytics plugin for Godot games to connect with Tokebi Metrics backend.
|
|
||||||
|
|
||||||
## Features
|
|
||||||
- Event tracking
|
|
||||||
- Funnel analysis
|
|
||||||
- User segmentation
|
|
||||||
|
|
||||||
## Requirements
|
|
||||||
- Godot version 4.0 or higher
|
|
||||||
- Tokebi Metrics account [https://tokebimetrics.com]
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
# Tokebi Godot Plugin — Quick Setup Steps
|
|
||||||
|
|
||||||
1. **Download Installer**
|
|
||||||
Get the installer script from:
|
|
||||||
https://tokebimetrics.com/documentation-guide/godot-plugin-guide or use this repo
|
|
||||||
|
|
||||||
2. **Add Installer to Project**
|
|
||||||
Copy the file `install_tokebi.gd` into the root folder of your Godot project (where your `project.godot` lives).
|
|
||||||
|
|
||||||
3. **Run Installer**
|
|
||||||
Open `install_tokebi.gd` in Godot’s script editor and run it. This will set up the plugin files and configuration automatically.
|
|
||||||
|
|
||||||
4. **Enable Plugin**
|
|
||||||
In Godot editor, go to **Project Settings → Plugins**.
|
|
||||||
Find **Tokebi Analytics SDK** and enable it.
|
|
||||||
|
|
||||||
5. **Configure API Key**
|
|
||||||
In the new **Tokebi Setup** dock, enter your API key (from your Tokebi dashboard).
|
|
||||||
|
|
||||||
6. **Set AutoLoad**
|
|
||||||
Go to **Project Settings → AutoLoad**, add the generated `tokebi.gd` script as an autoload singleton named `Tokebi`.
|
|
||||||
|
|
||||||
7. **Start Tracking Events**
|
|
||||||
In your game scripts, track analytics events with:
|
|
||||||
|
|
||||||
```gdscript
|
|
||||||
Tokebi.track("event_name", {"key": "value"})
|
|
||||||
|
|
||||||
|
|
||||||
## License
|
|
||||||
MIT License. See LICENSE file.
|
|
||||||
|
|
||||||
## Documentation
|
|
||||||
More detailed docs at — [https://tokebimetrics.com/documentation-guide/godot-plugin-guide]
|
|
||||||
|
|
||||||
## Contact
|
|
||||||
Created by Marco Diaz — [https://tokebimetrics.com]
|
|
||||||
@ -9,13 +9,16 @@ func before_each():
|
|||||||
_mock_parent = PathFollow2D.new()
|
_mock_parent = PathFollow2D.new()
|
||||||
_mock_parent.name = "PathFollow2D_Mock"
|
_mock_parent.name = "PathFollow2D_Mock"
|
||||||
add_child(_mock_parent)
|
add_child(_mock_parent)
|
||||||
|
gut.p(" → PathFollow2D mock created")
|
||||||
|
|
||||||
# Instantiate scene
|
# Instantiate scene
|
||||||
_enemy_instance = EnemyScene.instantiate()
|
_enemy_instance = EnemyScene.instantiate()
|
||||||
_mock_parent.add_child(_enemy_instance)
|
_mock_parent.add_child(_enemy_instance)
|
||||||
|
gut.p(" → Enemy instance instantiated from: %s" % EnemyScene.resource_path)
|
||||||
|
|
||||||
# Initialize child nodes
|
# Initialize child nodes
|
||||||
await get_tree().process_frame # Required for complete _ready() execution
|
await get_tree().process_frame # Required for complete _ready() execution
|
||||||
|
gut.p(" → Process frame awaited for initialization")
|
||||||
|
|
||||||
func after_each():
|
func after_each():
|
||||||
_enemy_instance.queue_free()
|
_enemy_instance.queue_free()
|
||||||
@ -23,60 +26,82 @@ func after_each():
|
|||||||
|
|
||||||
# Check for children
|
# Check for children
|
||||||
func test_scene_initialization():
|
func test_scene_initialization():
|
||||||
|
gut.p("\n▶ TEST: Scene Initialization")
|
||||||
var character_body = _enemy_instance.get_node("CharacterBody2D")
|
var character_body = _enemy_instance.get_node("CharacterBody2D")
|
||||||
var health_bar = _enemy_instance.get_node("ProgressBar")
|
var health_bar = _enemy_instance.get_node("ProgressBar")
|
||||||
|
gut.p(" → CharacterBody2D: %s" % ("✓ Found" if character_body else "✗ Missing"))
|
||||||
assert_not_null(character_body, "Missing CharacterBody2D")
|
assert_not_null(character_body, "Missing CharacterBody2D")
|
||||||
|
gut.p(" → ProgressBar: %s" % ("✓ Found" if health_bar else "✗ Missing"))
|
||||||
assert_not_null(health_bar, "Missing ProgressBar")
|
assert_not_null(health_bar, "Missing ProgressBar")
|
||||||
|
|
||||||
# Check damage mechanics
|
# Check damage mechanics
|
||||||
func test_shield_damage_reduction():
|
func test_shield_damage_reduction():
|
||||||
|
gut.p("\n▶ TEST: Shield Damage Reduction")
|
||||||
_enemy_instance.current_shield = 50
|
_enemy_instance.current_shield = 50
|
||||||
_enemy_instance.current_health = 100
|
_enemy_instance.current_health = 100
|
||||||
|
gut.p(" → Initial: Shield=%d, Health=%d" % [_enemy_instance.current_shield, _enemy_instance.current_health])
|
||||||
_enemy_instance.enemy_hurt(30)
|
_enemy_instance.enemy_hurt(30)
|
||||||
|
gut.p(" → After 30 damage: Shield=%d (expected 20), Health=%d (expected 100)" % [_enemy_instance.current_shield, _enemy_instance.current_health])
|
||||||
assert_eq(_enemy_instance.current_shield, 20, "Incorrect shield value")
|
assert_eq(_enemy_instance.current_shield, 20, "Incorrect shield value")
|
||||||
assert_eq(_enemy_instance.current_health, 100, "Health should remain unchanged with this damage amount")
|
assert_eq(_enemy_instance.current_health, 100, "Health should remain unchanged with this damage amount")
|
||||||
|
|
||||||
func test_shield_break_and_health_damage():
|
func test_shield_break_and_health_damage():
|
||||||
|
gut.p("\n▶ TEST: Shield Break and Health Damage")
|
||||||
_enemy_instance.current_shield = 20
|
_enemy_instance.current_shield = 20
|
||||||
_enemy_instance.current_health = 100
|
_enemy_instance.current_health = 100
|
||||||
|
gut.p(" → Initial: Shield=%d, Health=%d" % [_enemy_instance.current_shield, _enemy_instance.current_health])
|
||||||
_enemy_instance.enemy_hurt(30)
|
_enemy_instance.enemy_hurt(30)
|
||||||
|
gut.p(" → After 30 damage: Shield=%d (expected 0), Health=%d (expected 90)" % [_enemy_instance.current_shield, _enemy_instance.current_health])
|
||||||
assert_eq(_enemy_instance.current_shield, 0, "Shield should be depleted")
|
assert_eq(_enemy_instance.current_shield, 0, "Shield should be depleted")
|
||||||
assert_eq(_enemy_instance.current_health, 90, "Incorrect health value")
|
assert_eq(_enemy_instance.current_health, 90, "Incorrect health value")
|
||||||
|
|
||||||
func test_health_damage_without_shield():
|
func test_health_damage_without_shield():
|
||||||
|
gut.p("\n▶ TEST: Health Damage Without Shield")
|
||||||
_enemy_instance.current_shield = 0
|
_enemy_instance.current_shield = 0
|
||||||
_enemy_instance.current_health = 80
|
_enemy_instance.current_health = 80
|
||||||
|
gut.p(" → Initial: Shield=%d, Health=%d" % [_enemy_instance.current_shield, _enemy_instance.current_health])
|
||||||
_enemy_instance.enemy_hurt(25)
|
_enemy_instance.enemy_hurt(25)
|
||||||
|
gut.p(" → After 25 damage: Shield=%d (expected 0), Health=%d (expected 55)" % [_enemy_instance.current_shield, _enemy_instance.current_health])
|
||||||
assert_eq(_enemy_instance.current_shield, 0, "Shield should remain zero")
|
assert_eq(_enemy_instance.current_shield, 0, "Shield should remain zero")
|
||||||
assert_eq(_enemy_instance.current_health, 55, "Incorrect health amount")
|
assert_eq(_enemy_instance.current_health, 55, "Incorrect health amount")
|
||||||
|
|
||||||
#Check for animation change
|
#Check for animation change
|
||||||
func test_hurt_animation_plays_on_damage():
|
func test_hurt_animation_plays_on_damage():
|
||||||
|
gut.p("\n▶ TEST: Hurt Animation on Damage")
|
||||||
_enemy_instance.enemy_hurt(10)
|
_enemy_instance.enemy_hurt(10)
|
||||||
var anim_sprite = _enemy_instance.get_node("CharacterBody2D/AnimatedSprite2D")
|
var anim_sprite = _enemy_instance.get_node("CharacterBody2D/AnimatedSprite2D")
|
||||||
|
gut.p(" → Animation: %s (expected 'hurt')" % anim_sprite.animation)
|
||||||
assert_eq(anim_sprite.animation, "hurt", "Hurt animation must be playing")
|
assert_eq(anim_sprite.animation, "hurt", "Hurt animation must be playing")
|
||||||
|
|
||||||
#Check animation speed change
|
#Check animation speed change
|
||||||
func test_animation_speed_scales_with_speed():
|
func test_animation_speed_scales_with_speed():
|
||||||
# Sebesség beállítások ellenőrzése
|
gut.p("\n▶ TEST: Animation Speed Scaling")
|
||||||
_enemy_instance.set_character_data()
|
_enemy_instance.set_character_data()
|
||||||
var anim_sprite = _enemy_instance.get_node("CharacterBody2D/AnimatedSprite2D")
|
var anim_sprite = _enemy_instance.get_node("CharacterBody2D/AnimatedSprite2D")
|
||||||
var expected_speed = snapped(_enemy_instance.speed / 100.0 , 0.1)
|
var expected_speed = snapped(_enemy_instance.speed / 100.0 , 0.1)
|
||||||
assert_eq(snapped(anim_sprite.speed_scale, 0.1), expected_speed, "Animation speed should match movement speed")
|
var actual_speed = snapped(anim_sprite.speed_scale, 0.1)
|
||||||
|
gut.p(" → Character speed: %d" % _enemy_instance.speed)
|
||||||
|
gut.p(" → Animation speed: %s (expected %s)" % [actual_speed, expected_speed])
|
||||||
|
assert_eq(actual_speed, expected_speed, "Animation speed should match movement speed")
|
||||||
|
|
||||||
#check for cholorchange on healthbar
|
#check for colorchange on healthbar
|
||||||
func test_health_bar_color_changes_with_shield():
|
func test_health_bar_color_changes_with_shield():
|
||||||
|
gut.p("\n▶ TEST: Health Bar Color with Shield")
|
||||||
_enemy_instance.current_shield = 50
|
_enemy_instance.current_shield = 50
|
||||||
_enemy_instance.adjust_health_bar()
|
_enemy_instance.adjust_health_bar()
|
||||||
var fill_style = _enemy_instance.get_node("ProgressBar").get_theme_stylebox("fill")
|
var fill_style = _enemy_instance.get_node("ProgressBar").get_theme_stylebox("fill")
|
||||||
|
gut.p(" → Shield: %d, Color: %s (expected blue)" % [_enemy_instance.current_shield, fill_style.bg_color])
|
||||||
assert_eq(fill_style.bg_color, Color(0,0,1), "Must be blue in case of shield")
|
assert_eq(fill_style.bg_color, Color(0,0,1), "Must be blue in case of shield")
|
||||||
|
|
||||||
#Check character flip
|
#Check character flip
|
||||||
func test_character_flips_based_on_movement_direction():
|
func test_character_flips_based_on_movement_direction():
|
||||||
|
gut.p("\n▶ TEST: Character Flip Direction")
|
||||||
var initial_scale = _mock_parent.scale.x
|
var initial_scale = _mock_parent.scale.x
|
||||||
_mock_parent.position.x += 10
|
_mock_parent.position.x += 10
|
||||||
_enemy_instance.move_character(0.1)
|
_enemy_instance.move_character(0.1)
|
||||||
|
gut.p(" → Moving right: scale=%s (expected > 0)" % _mock_parent.scale.x)
|
||||||
assert_gt(_mock_parent.scale.x, 0, "Positive scaling when moving to the right")
|
assert_gt(_mock_parent.scale.x, 0, "Positive scaling when moving to the right")
|
||||||
_mock_parent.position.x -= 20
|
_mock_parent.position.x -= 20
|
||||||
_enemy_instance.move_character(0.1)
|
_enemy_instance.move_character(0.1)
|
||||||
|
gut.p(" → Moving left: scale=%s (expected < 0)" % _mock_parent.scale.x)
|
||||||
assert_lt(_mock_parent.scale.x, 0, "Negative scaling when moving left")
|
assert_lt(_mock_parent.scale.x, 0, "Negative scaling when moving left")
|
||||||
|
|||||||
259
test/test_tower.gd
Normal file
259
test/test_tower.gd
Normal file
@ -0,0 +1,259 @@
|
|||||||
|
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")
|
||||||
1
test/test_tower.gd.uid
Normal file
1
test/test_tower.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://g32irt61oxi5
|
||||||
Reference in New Issue
Block a user