112 lines
5.0 KiB
GDScript
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()
|