extends Node const PROGRESS := preload("res://scripts/captain/captain_progress.gd") const COMBAT := preload("res://scripts/game/combat_rolls.gd") const GAME_SCENE := preload("res://scenes/game/game.tscn") const GENERATOR := preload("res://scripts/items/item_generator.gd") const PROJECTILE := preload("res://scenes/game/weapon_projectile.tscn") class DamageReceiver: extends Node2D var hits: Array[Dictionary] = [] func take_weapon_hit(amount: float, critical: bool) -> void: hits.append({"damage": amount, "critical": critical}) func _ready() -> void: var profile := PROGRESS.new() assert(not profile.train_skill("gunner")) profile.add_rewards(99, 60) assert(profile.level == 1 and profile.experience == 99) profile.add_rewards(1, 15) assert(profile.level == 2 and profile.experience == 0 and profile.learning_points == 1 and profile.credits == 75) assert(profile.train_skill("gunner") and profile.get_skill_rank("gunner") == 1) assert(not profile.train_skill("piloting") and not profile.train_skill("unknown")) profile.add_rewards(450, 0) assert(profile.level == 4 and profile.experience == 100 and profile.learning_points == 2) profile.skills["piloting"] = 100 assert(not profile.train_skill("piloting")) assert(profile.reward_enemy(10, 2, 1.25, 1.5) == Vector2i(272, 261)) var hit := COMBAT.weapon_hit(10, 1.1, 0, 2, 0) assert(not hit["critical"] and is_equal_approx(hit["damage"], 11)) hit = COMBAT.weapon_hit(10, 1.1, 1, 2.4, 1) assert(hit["critical"] and is_equal_approx(hit["damage"], 26.4)) assert(not COMBAT.weapon_hit(10, 1, 0.01, 2, 0.01)["critical"]) assert(COMBAT.incoming_hit(100, 1, 0, 1)["evaded"]) assert(is_equal_approx(COMBAT.incoming_hit(100, 0.01, 0.5, 0.01)["damage"], 50)) assert(COMBAT.incoming_hit(100, 0, 1, 0)["damage"] == 0) assert(COMBAT.incoming_hit(-100, 0, 0, 0)["damage"] == 0) GameState.start_new_run() var game := GAME_SCENE.instantiate() as Node2D get_tree().root.call_deferred("add_child", game) await get_tree().process_frame await get_tree().process_frame get_tree().current_scene = game _freeze(game) profile = GameState.captain var enemies := get_tree().get_nodes_in_group("enemies") for enemy in enemies: enemy.call("take_weapon_hit", 1000000.0, true) enemy.call("take_damage", 1000000.0) assert(profile.level == 2 and profile.experience == 130 and profile.learning_points == 1) assert(profile.credits == 180) var panel := game.get_node("HUD/HUDRoot/CaptainPanel") panel.get_node("Contents/Skills/gunner/Train_gunner").emit_signal("pressed") assert(profile.get_skill_rank("gunner") == 1 and profile.learning_points == 0) panel.get_node("Contents/Skills/piloting/Train_piloting").emit_signal("pressed") assert(profile.get_skill_rank("piloting") == 0) assert(panel.get_node("Contents/Header/Level").get("text") == "POZ. 2") var player := game.get_node("PlayerShip") as CharacterBody2D profile.skills["piloting"] = 100 var before := Vector2(float(player.get("hull")), float(player.get("shields"))) player.call("take_damage", 1000.0) assert(before == Vector2(float(player.get("hull")), float(player.get("shields")))) profile.skills["piloting"] = 0 profile.skills["mechanic"] = 50 player.set("shields", 100.0) # Fixed fixture, independent of selected chassis capacity. player.call("take_damage", 100.0) assert(float(player.get("shields")) == 50 and float(player.get("hull")) == 100) player.set("shields", 0.0) player.call("take_damage", 40.0) assert(float(player.get("hull")) == 80) profile.skills["mechanic"] = 100 player.call("take_damage", 1000000.0) assert(float(player.get("hull")) == 80) profile.skills["mechanic"] = 0 profile.skills["sharp_eye"] = 1 var inventory := player.get_node("ShipInventory") as ShipInventory var weapon := GENERATOR.generate_for_definition(preload("res://resources/items/plasma_cannon.tres"), 1) weapon.additional_modifiers.clear() weapon.damage_min = 10 weapon.damage_max = 10 for data in [["critical_chance_percent", 25.0], ["critical_damage_percent", 20.0], ["damage_percent", 10.0], ["experience_percent", 25.0], ["credits_percent", 50.0]]: var modifier := ItemStatModifier.new() modifier.stat_key = data[0] modifier.value = data[1] weapon.additional_modifiers.append(modifier) var free_slot := inventory.cargo.find(null) assert(inventory.add_item(weapon) and inventory.move_item("cargo", free_slot, "weapon", 0)) assert(is_equal_approx(float(player.call("get_critical_chance")), 0.26)) assert(is_equal_approx(float(player.call("get_critical_multiplier")), 2.4)) assert(is_equal_approx(float(player.call("get_weapon_damage_multiplier")), 1.111)) profile.skills["sharp_eye"] = 100 hit = player.call("roll_weapon_hit", weapon) assert(hit["critical"] and is_equal_approx(hit["damage"], 26.664)) var receiver := DamageReceiver.new() game.add_child(receiver) var projectile := PROJECTILE.instantiate() projectile.call("configure", Vector2.ZERO, Vector2.RIGHT, ItemDefinition.WeaponKind.MISSILE, 400.0, 26.664, 1000.0, null, true) game.add_child(projectile) projectile.set_physics_process(false) projectile.call("_apply_damage_once", receiver) projectile.call("_apply_damage_once", receiver) assert(receiver.hits.size() == 1 and receiver.hits[0]["critical"]) assert(is_equal_approx(receiver.hits[0]["damage"], 26.664)) player.call("take_damage", 1000000.0) await get_tree().create_timer(1.3).timeout game = get_tree().current_scene as Node2D _freeze(game) assert(GameState.captain == profile and profile.level == 2 and profile.credits == 180) player = game.get_node("PlayerShip") as CharacterBody2D assert(player.get_node("ShipInventory").call("get_item", "weapon", 0) == weapon) for enemy in get_tree().get_nodes_in_group("enemies"): enemy.call("take_damage", 1000000.0) assert(profile.level == 4 and profile.experience == 68 and profile.credits == 452) var planet: Node2D = game.get("protected_planet") player.position = planet.position game.call("_physics_process", 0.0) assert(bool(game.call("open_wormhole"))) var portal: Node2D = game.get("wormhole") player.position = portal.position assert(bool(game.call("advance_to_next_level"))) await get_tree().process_frame await get_tree().process_frame await get_tree().process_frame game = get_tree().current_scene as Node2D _freeze(game) assert(GameState.captain == profile and GameState.system_level == 2) assert(profile.get_skill_rank("gunner") == 1 and profile.get_skill_rank("sharp_eye") == 100) var enemy := get_tree().get_nodes_in_group("enemies")[0] as CharacterBody2D enemy.call("take_damage", 1000000.0) assert(profile.level == 5 and profile.experience == 15 and profile.credits == 641) print("CAPTAIN_SYSTEM_TEST: PASS (XP, multiple levels, learning UI, rewards once, dodge, reduction, critical addons, projectile metadata, death and next system)") func _freeze(game: Node2D) -> void: game.set_physics_process(false) game.get_node("PlayerShip").set_physics_process(false) game.get_node("PlayerShip/WeaponController").set_physics_process(false) for enemy in get_tree().get_nodes_in_group("enemies"): if game.is_ancestor_of(enemy): enemy.set_physics_process(false)