Randoloot/tests/abilities/electrician_drones_tactics_test.gd
2026-10-16 23:36:49 +02:00

112 lines
5.0 KiB
GDScript

extends Node2D
const PLAYER := preload("res://scenes/game/player_ship.tscn")
const ENEMY := preload("res://scenes/game/enemy_ship.tscn")
const DRONES := preload("res://resources/items/combat_drones.tres")
func _ready() -> void:
GameState.start_new_run()
var ship := PLAYER.instantiate() as CharacterBody2D
add_child(ship)
ship.set_physics_process(false)
var weapons := ship.get_node("WeaponController")
weapons.set_physics_process(false)
var systems := ship.get_node("ExtensionSystems")
systems.set_physics_process(false)
var inventory := ship.get_node("ShipInventory") as ShipInventory
# Every rank replaces the baseline, respects the energy cap, and uses one bank.
for rank in range(4):
GameState.captain.skills["electrician"] = rank
inventory.energy_banks = 2
ship.set("energy", 0.0)
assert(inventory.use_energy_bank())
assert(is_equal_approx(float(ship.get("energy")), float(ship.get("max_energy")) * [0.10, 0.15, 0.20, 0.25][rank]))
ship.set("energy", float(ship.get("max_energy")) - 1.0)
assert(inventory.use_energy_bank())
assert(ship.get("energy") == ship.get("max_energy"))
assert(inventory.energy_banks == 0)
assert(preload("res://scripts/captain/captain_skills.gd").icon("electrician") != null)
assert(not GameState.captain.equip_skill(0, "electrician"))
# Tactics move toward, away from, or around their target, then flee below 50%.
var enemy := ENEMY.instantiate() as CharacterBody2D
enemy.position = Vector2(250, 0)
add_child(enemy)
enemy.set_physics_process(false)
enemy.set("_player", ship)
enemy.set("tactic", 0)
assert(enemy.call("combat_movement", Vector2(200, 0)).x > 0.0)
enemy.set("tactic", 1)
assert(enemy.call("combat_movement", Vector2(100, 0)).x < 0.0)
assert(enemy.call("combat_movement", Vector2(700, 0)).x > 0.0)
assert(absf(enemy.call("combat_movement", Vector2(420, 0)).y) > 0.0)
enemy.set("hull", float(enemy.get("max_hull")) * 0.5)
assert(not enemy.call("is_retreating"))
enemy.set("hull", float(enemy.get("max_hull")) * 0.49)
for tactic in [0, 1]:
enemy.set("tactic", tactic)
assert(enemy.call("is_retreating"))
assert(enemy.call("combat_movement", Vector2(500, 0)).x < 0.0)
enemy.set("hull", 10000.0)
# Module is lootable, charges exactly 50 ammo even with the ammunition passive.
assert(DRONES in preload("res://scripts/items/item_generator.gd").DEFINITIONS)
var module := ItemInstance.new()
module.definition = DRONES
inventory.extension_slots[0] = module
GameState.captain.skills["efficient_magazine"] = 3
inventory.ammunition = 49
assert(not ship.call("activate_ability", 0))
assert(inventory.ammunition == 49)
inventory.ammunition = 100
var dps := inventory.get_total_dps()
assert(dps > 0.0)
assert(ship.call("activate_ability", 0))
assert(inventory.ammunition == 50)
assert(not ship.call("activate_ability", 0))
var drones := get_tree().get_nodes_in_group("player_combat_drones")
assert(drones.size() == 3)
var total_dps := 0.0
for drone in drones:
drone.set_physics_process(false)
total_dps += float(drone.get("damage_per_shot")) / float(drone.FIRE_INTERVAL)
assert(is_equal_approx(total_dps, dps * 0.5))
assert(is_equal_approx(inventory.get_total_dps(), dps))
await get_tree().physics_frame
await get_tree().process_frame
var before := float(enemy.get("hull")) + float(enemy.get("shields"))
drones[0].position = Vector2(100, 0)
drones[0].call("_fire", enemy)
for bullet in get_children():
if bullet is Area2D and bullet.get_script() == preload("res://scripts/game/weapon_projectile.gd"):
bullet.call("_physics_process", 0.2)
assert(float(enemy.get("hull")) + float(enemy.get("shields")) < before, "Drone bullets must damage enemies")
assert(inventory.ammunition == 50, "No extra ammunition charged per shot")
systems.call("_physics_process", 10.0)
for drone in drones:
assert(drone.is_queued_for_deletion())
await get_tree().process_frame
assert(get_tree().get_nodes_in_group("player_combat_drones").is_empty())
systems.call("reset_combat_state")
assert(ship.call("activate_ability", 0))
var deployed := get_tree().get_nodes_in_group("player_combat_drones")
for drone in deployed:
drone.set_physics_process(false)
get_tree().paused = true
assert(not ship.call("activate_ability", 0))
await get_tree().create_timer(0.05, true).timeout
assert(float(systems.get("drones_remaining")) == 10.0)
get_tree().paused = false
ship.set("is_docked", true)
systems.call("_physics_process", 0.1)
await get_tree().process_frame
assert(get_tree().get_nodes_in_group("player_combat_drones").is_empty())
ship.set("is_docked", false)
systems.call("reset_combat_state")
inventory.ammunition = 50
assert(ship.call("activate_ability", 0))
systems.call("reset_combat_state")
await get_tree().process_frame
assert(get_tree().get_nodes_in_group("player_combat_drones").is_empty())
assert(float(systems.get("drones_remaining")) == 0.0)
print("ELECTRICIAN_DRONES_TACTICS_TEST: PASS (four bank strengths/caps, passive icon, tactics and retreat, loot module, exact ammo cost, 3 drones, shared 50% DPS, actual bullet damage, lifetime and reset)")
get_tree().quit()