extends Node2D const SKILLS := preload("res://scripts/captain/captain_skills.gd") const LAB := preload("res://scripts/planets/laboratory.gd") const RECIPES := preload("res://scripts/items/crafting_recipes.gd") const NEW_SKILLS := ["scientist", "gunsmith", "bounty_hunter", "missile_specialist", "emergency_procedure"] func _ready() -> void: GameState.start_new_run() var captain := GameState.captain var ship := RepairShip.new() # A real inventory without starting the flight simulation. var inventory := ShipInventory.new() inventory.weapon_slots.resize(3) inventory.module_slots.resize(5) var missile := ItemInstance.new() missile.definition = preload("res://resources/items/missile_launcher.tres") var baseline_money := captain.reward_enemy(1,0,1.0,1.0,false).y assert(SKILLS.IDS.size() == 16) for id in NEW_SKILLS: assert(SKILLS.icon(id) != null) for rank in range(1,4): assert(not SKILLS.description(id,rank).is_empty()) captain.learning_points = 1 captain.skill_offers.assign([id]) assert(captain.train_skill(id)) assert(captain.get_skill_rank(id) == 1) captain.skills[id] = 0 for rank in range(1,4): for id in NEW_SKILLS: captain.skills[id] = rank var progress: Resource = captain.expedition progress.freighter_rooms.expansion_1 = "laboratory" progress.laboratory_project = "" progress.laboratory_offers.assign(["machine_gun"]) progress.laboratory_unlocks.clear() for key in LAB.COSTS.machine_gun: captain.minerals[key] = 100 assert(LAB.start(captain,"machine_gun")) assert(is_equal_approx(progress.laboratory_remaining,[54.0,48.0,42.0][rank-1])) assert(progress.laboratory_duration == progress.laboratory_remaining) LAB.advance(progress,progress.laboratory_remaining-1.0) assert(not progress.laboratory_unlocks.has("machine_gun")) LAB.advance(progress,1.0) assert(progress.laboratory_unlocks.has("machine_gun")) for id in ["ammunition","irradiated_ammunition"]: for key in RECIPES.DATA[id].cost: captain.minerals[key] = 100 var before := inventory.get_crafted_stock(id) var iron_before: int = captain.minerals.iron assert(inventory.craft(id)) assert(inventory.get_crafted_stock(id)-before == RECIPES.output_amount(id,captain)) assert(captain.minerals.iron == iron_before-int(RECIPES.DATA[id].cost.get("iron",0))) assert(RECIPES.output_amount("ammunition",captain) == [11,12,13][rank-1]) assert(RECIPES.output_amount("irradiated_ammunition",captain) == [55,60,65][rank-1]) assert(RECIPES.output_amount("missile",captain) == 1) assert(RECIPES.output_amount("parts",captain) == 1) var credits_before := captain.credits var reward := captain.reward_enemy(1,0,1.0,1.0,false) assert(reward.y == roundi(baseline_money*(1.0+SKILLS.value("bounty_hunter",rank)))) assert(captain.credits == credits_before,"Enemy credits are collected from pickups") assert(is_equal_approx(inventory.get_missile_cooldown(missile),[4.5,4.25,4.0][rank-1])) assert(captain.equip_skill(0,"emergency_procedure")) captain.reset_combat_state() ship.max_hull = 200.0 ship.hull = 100.0 captain.parts = 0.5 assert(not captain.activate_skill("emergency_procedure",ship)) assert(not captain.skill_cooldowns.has("emergency_procedure")) captain.parts = 2.0 ship.is_docked = true assert(not captain.activate_skill("emergency_procedure",ship)) ship.is_docked = false # Feedback requires a parent; use a minimal stub for this logic test. var stub := RepairShip.new() assert(captain.activate_skill("emergency_procedure",stub)) assert(is_equal_approx(stub.hull,100.0+[10.0,20.0,30.0][rank-1])) assert(captain.parts == 1.0 and captain.skill_cooldowns.emergency_procedure == 60.0) assert(not captain.activate_skill("emergency_procedure",stub)) captain.tick_skills(60.0) stub.hull = 199.0 assert(captain.activate_skill("emergency_procedure",stub)) assert(stub.hull == 200.0 and captain.parts == 0.0) captain.reset_combat_state() captain.parts = 1.0 assert(not captain.activate_skill("emergency_procedure",stub)) assert(captain.parts == 1.0 and not captain.skill_cooldowns.has("emergency_procedure")) stub.free() ship.free() inventory.free() print("NEW_CAPTAIN_SKILLS_TEST: PASS (16 skills, icons, training, all ranks, research duration, ammo output/cost, bounty, missile cooldown, repair conditions/cost/cooldown/cap)") get_tree().quit() class RepairShip extends CharacterBody2D: var hull := 100.0 var max_hull := 200.0 var _is_destroyed := false var is_docked := false