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

213 lines
9.2 KiB
GDScript

extends Node
const CATALOG := preload("res://scripts/captain/captain_skills.gd")
const PROGRESS := preload("res://scripts/captain/captain_progress.gd")
const POI := preload("res://scripts/levels/exploration_poi.gd")
func _ready() -> void:
_test_offers()
GameState.start_new_run()
var game := preload("res://scenes/game/game.tscn").instantiate()
add_child(game)
game.set_physics_process(false)
var ship: CharacterBody2D = game.get_node("PlayerShip")
ship.set_physics_process(false)
ship.get_node("WeaponController").set_physics_process(false)
for enemy in get_tree().get_nodes_in_group("enemies"):
enemy.set_physics_process(false)
var captain := GameState.captain
var inventory: ShipInventory = ship.get_node("ShipInventory")
for rank in range(1, 4):
captain.skills["business_shark"] = rank
assert(inventory.get_ammunition_buy_cost() == [54, 42, 24][rank - 1])
assert(inventory.get_missile_buy_cost() == [27, 21, 12][rank - 1])
assert(inventory.get_irradiated_ammunition_buy_cost() == [45, 35, 20][rank - 1])
captain.skills["efficient_magazine"] = rank
captain._ammo_credit.clear()
inventory.ammunition = 100
inventory.irradiated_ammunition = 100
for shot in 100:
assert(inventory.consume_ammunition())
assert(inventory.consume_irradiated_ammunition())
assert(inventory.ammunition == [10, 20, 50][rank - 1])
assert(inventory.irradiated_ammunition == [10, 20, 50][rank - 1])
inventory.missile_ammunition = 2
assert(inventory.consume_missile())
assert(inventory.missile_ammunition == 1)
captain.skills["reactor_overload"] = rank
captain.skills["tactical_maneuver"] = rank
captain.skills["power_redirect"] = rank
assert(captain.equip_skill(0, "reactor_overload"))
assert(captain.equip_skill(1, "tactical_maneuver"))
assert(captain.equip_skill(2, "power_redirect"))
captain.skill_cooldowns.clear()
captain.skill_durations.clear()
var base_regeneration: float = ship.get_energy_regeneration()
assert(captain.activate_skill("reactor_overload", ship))
assert(is_equal_approx(ship.get_energy_regeneration(), base_regeneration * [1.2, 1.5, 2.0][rank - 1]))
ship.energy = 0.0
ship._physics_process(0.1)
assert(is_equal_approx(ship.energy, base_regeneration * [1.2, 1.5, 2.0][rank - 1] * 0.1))
assert(not captain.activate_skill("reactor_overload", ship))
assert(captain.activate_skill("tactical_maneuver", ship))
assert(is_equal_approx(ship.get_evasion_chance(), [0.3, 0.6, 1.0][rank - 1]))
if rank == 3:
var before_hit: float = ship.shields
ship.take_damage(100.0)
assert(ship.shields == before_hit)
ship.shields = ship.max_shields * 0.24
assert(not captain.activate_skill("power_redirect", ship))
assert(not captain.skill_cooldowns.has("power_redirect"))
ship.shields = ship.max_shields * 0.25
assert(captain.activate_skill("power_redirect", ship))
assert(ship.shields == 0.0)
assert(is_equal_approx(captain.energy_regeneration_multiplier(), 1.0 + [0.2, 0.5, 1.0][rank - 1] + [0.5, 0.9, 1.5][rank - 1]))
ship.shield_on_damage_percent = 100.0
ship.restore_shields_from_damage(100.0)
assert(ship.shields == 0.0)
var shield_ability := preload("res://scripts/abilities/shield_charge_ability.gd").new()
shield_ability.activate(ship)
assert(ship.shields == 0.0)
var previous_regeneration: float = ship.shield_regeneration
ship.shield_regeneration = 10.0
ship._physics_process(0.1)
assert(ship.shields == 0.0)
captain.tick_skills(4.9)
assert(not captain.is_skill_active("power_redirect"))
assert(ship.get_evasion_chance() == 0.0)
assert(is_equal_approx(captain.energy_regeneration_multiplier(), 1.0))
assert(is_equal_approx(captain.skill_cooldowns["reactor_overload"], 24.9))
ship._physics_process(0.1)
assert(ship.shields > 0.0)
ship.shield_regeneration = previous_regeneration
ship.restore_shields_from_damage(10.0)
assert(ship.shields > 0.0)
captain.tick_skills(25.0)
assert(captain.skill_cooldowns["reactor_overload"] == 0.0)
assert(captain.equipped_skills.size() == 5)
assert(not captain.equip_skill(5, "reactor_overload"))
assert(not captain.equip_skill(-1, "reactor_overload"))
assert(not captain.equip_skill(3, "miner"))
assert(not captain.equip_skill(3, "unknown"))
captain.skill_cooldowns["reactor_overload"] = 12.0
assert(captain.equip_skill(4, "reactor_overload"))
assert(captain.equipped_skills[0] == "" and captain.equipped_skills[4] == "reactor_overload")
assert(captain.skill_cooldowns["reactor_overload"] == 12.0)
assert(captain.equip_skill(4, ""))
captain.skill_cooldowns.clear()
assert(not captain.activate_skill("reactor_overload", ship))
assert(captain.equip_skill(4, "reactor_overload"))
captain.emit_changed()
await get_tree().process_frame
await get_tree().process_frame
var hotkey_ui := game.get_node("HUD/CaptainSkills")
var event := InputEventKey.new()
event.physical_keycode = KEY_F5
event.pressed = true
hotkey_ui._unhandled_key_input(event)
assert(captain.is_skill_active("reactor_overload"))
assert(captain.skill_cooldowns["reactor_overload"] == 30.0)
assert(hotkey_ui.get("_bar").get_child_count() == 5)
captain.credits = 1000
assert(inventory.buy_ammunition())
assert(captain.credits == 976)
_test_mining(game, ship)
inventory.ammunition = 0
inventory.irradiated_ammunition = 0
assert(not inventory.consume_ammunition() and not inventory.consume_irradiated_ammunition())
# Level-ups wait for the captain button, then advance queued choices while paused.
captain.skills.clear()
captain.normalize_equipped_skills()
captain.skill_cooldowns.clear()
captain.skill_durations.clear()
captain.add_rewards(250, 0)
await get_tree().process_frame
await get_tree().process_frame
var ui := game.get_node("HUD/CaptainSkills")
assert(not get_tree().paused and captain.learning_points == 2)
assert(not ui.get("_screen").visible)
var level_button := game.get_node("HUD/HUDRoot/CaptainPanel/Contents/LevelUpButton") as Button
assert(level_button.visible and level_button.text == "Nowy poziom")
var offers := captain.skill_offers.duplicate()
level_button.pressed.emit()
assert(get_tree().paused and ui.get("_screen").visible)
assert(offers == captain.skill_offers and offers.size() == 3)
ui._close()
assert(get_tree().paused)
var selected: String = offers[0]
ui._choose(selected)
assert(captain.get_skill_rank(selected) == 1 and get_tree().paused and captain.learning_points == 1)
await get_tree().process_frame
assert(ui.get("_screen").visible and captain.skill_offers.size() == 3)
ui._choose(captain.skill_offers[0])
assert(not get_tree().paused and captain.learning_points == 0)
await get_tree().process_frame
assert(not level_button.visible and not ui.get("_screen").visible)
ui.open_management()
assert(get_tree().paused)
captain.skill_cooldowns["reactor_overload"] = 17.0
ship.set_physics_process(true)
await get_tree().create_timer(0.1, true).timeout
assert(captain.skill_cooldowns["reactor_overload"] == 17.0)
ship.set_physics_process(false)
ui._close()
var profile := GameState.captain
GameState.system_level = 2
game.queue_free()
await get_tree().process_frame
var next_system := preload("res://scenes/game/game.tscn").instantiate()
add_child(next_system)
next_system.get_node("PlayerShip").set_physics_process(false)
assert(GameState.captain == profile and profile.get_spent_learning_points() == 2)
assert(profile.skill_cooldowns.is_empty() and profile.skill_durations.is_empty())
GameState.start_new_run()
assert(GameState.captain.skills.is_empty() and GameState.captain.skill_cooldowns.is_empty())
print("CAPTAIN_SKILLS_TEST: PASS (eight skills, three ranks, five equipped slots, F5 input, slot swaps preserve cooldown, new boards reset cooldown, offers, pause, economy, ammo, mining, buffs, shield lock, new run)")
get_tree().quit()
func _test_offers() -> void:
var profile := PROGRESS.new()
profile.add_rewards(250, 0)
assert(profile.level == 3 and profile.learning_points == 2)
assert(profile.skill_offers.size() == 3)
assert(not profile.train_skill("unknown"))
var choices := profile.skill_offers.duplicate()
profile.prepare_skill_offers()
assert(choices == profile.skill_offers)
assert(profile.train_skill(choices[0]))
assert(profile.get_skill_rank(choices[0]) == 1)
for skill in CATALOG.IDS:
profile.skills[skill] = 3
profile.skills["miner"] = 2
profile.skill_offers.clear()
profile.prepare_skill_offers()
assert(profile.skill_offers == ["miner"])
assert(profile.train_skill("miner"))
profile.add_rewards(1000, 0)
assert(profile.skill_offers.is_empty() and profile.learning_points == 0)
assert(not profile.can_reset_skills())
profile.normalize_skill_ranks()
assert(profile.get_skill_rank("miner") == 3)
func _test_mining(game: Node, ship: CharacterBody2D) -> void:
var results: Array[int] = []
for rank in range(4):
GameState.captain.skills["miner"] = rank
GameState.captain.minerals = {"iron": 0, "aluminium": 0, "titanium": 0, "uranium": 0}
var asteroid := StaticBody2D.new()
asteroid.set_script(POI)
asteroid.set("kind", "asteroid")
asteroid.set("player", ship)
asteroid.set("reward_seed", 123)
asteroid.set("poi_id", "captain_skill_test_%d" % rank)
game.add_child(asteroid)
assert(asteroid.claim())
var total := 0
for amount in GameState.captain.minerals.values():
total += int(amount)
results.append(total)
assert(results[1] == results[0] + 3 and results[2] == results[0] + 6 and results[3] == results[0] + 10)