153 lines
7.8 KiB
GDScript
153 lines
7.8 KiB
GDScript
extends Node
|
|
var is_runner := false
|
|
var failures: Array[String] = []
|
|
const GENERATOR := preload("res://scripts/levels/distant_sector_generator.gd")
|
|
const ORBS := preload("res://scripts/items/special_orbs.gd")
|
|
const LOOT := preload("res://scripts/game/distant_loot.gd")
|
|
func _ready() -> void:
|
|
if not is_runner:
|
|
var runner = get_script().new()
|
|
runner.is_runner = true
|
|
get_tree().root.add_child.call_deferred(runner)
|
|
else:
|
|
_run.call_deferred()
|
|
func check(value: bool, message: String) -> void:
|
|
if not value: failures.append(message); push_error("DISTANT_TEST: "+message)
|
|
func frames(count: int = 4) -> void:
|
|
for index in count: await get_tree().process_frame
|
|
func freeze_game(game: Node) -> void:
|
|
game.get_node("PlayerShip").set_physics_process(false)
|
|
for enemy in get_tree().get_nodes_in_group("enemies"): enemy.set_physics_process(false)
|
|
func _run() -> void:
|
|
for level in [1,60,120,125,500]:
|
|
var ordinary := preload("res://scripts/levels/level_balance.gd").enemy_tiers(level)
|
|
var tiers := GENERATOR.enemy_tiers(level)
|
|
check(tiers.count(2)==1,"One boss")
|
|
check(tiers.count(0)==ordinary.count(0)*2,"Double normals")
|
|
check(tiers.count(1)==ordinary.count(1)*2,"Double elites")
|
|
check(preload("res://scripts/levels/level_balance.gd").enemy_stat_scale(125)>preload("res://scripts/levels/level_balance.gd").enemy_stat_scale(120),"Stats beyond 120")
|
|
check(LOOT.roll(125,false,2,0.149,0.0).size()==1,"Map 15 percent")
|
|
check(LOOT.roll(125,false,2,0.15,0.0).is_empty(),"Map boundary and no regular orb")
|
|
for seed_value in 100:
|
|
for chance in [0.0,0.15,1.0]:
|
|
var boss_drops := LOOT.roll(125,true,seed_value,chance,1.0)
|
|
check(boss_drops.size()==2 and boss_drops[0].has("map") and boss_drops[1].has("orb"),"Exactly one guaranteed boss map and orb")
|
|
var next_map: Dictionary = LOOT.roll(125,false,2,0.0,1.0)[0].map
|
|
check(int(next_map.level)>125 and int(next_map.level)<=130,"Map chain")
|
|
GameState.start_new_run()
|
|
GameState.system_level = 7
|
|
GameState.system_seed = 777
|
|
GameState.remember_system()
|
|
GameState.captain.expedition.distant_maps["integration"] = {"id":"integration","level":125,"seed":123456,"name":"Sektor testowy","source_planet":"Test","source_level":120}
|
|
GameState.captain.expedition.deuter = 124999
|
|
check(not GameState.depart_distant("integration"),"No flight without fuel")
|
|
check(GameState.system_level==7 and GameState.captain.expedition.deuter==124999,"Failed departure preserved state")
|
|
GameState.captain.expedition.deuter = 125000
|
|
get_tree().change_scene_to_file("res://scenes/game/game.tscn")
|
|
await frames()
|
|
var game := get_tree().current_scene
|
|
freeze_game(game)
|
|
var player := game.get_node("PlayerShip")
|
|
var inventory := player.get_node("ShipInventory")
|
|
player.is_docked = true
|
|
var weapon: ItemInstance = inventory.weapon_slots[0]
|
|
var engine := ItemInstance.new()
|
|
engine.definition = preload("res://resources/items/engine_extension.tres")
|
|
inventory.module_slots[2] = engine
|
|
var progress: Resource = GameState.captain.expedition
|
|
progress.orbs = {"piercing":2,"booster":1}
|
|
check(not ORBS.apply(progress,inventory,engine,"piercing"),"Piercing category restriction")
|
|
check(not ORBS.apply(progress,inventory,weapon,"booster"),"Booster category restriction")
|
|
check(ORBS.apply(progress,inventory,weapon,"piercing"),"Apply piercing")
|
|
check(not ORBS.apply(progress,inventory,weapon,"piercing") and progress.orbs.piercing==1,"No stacking or extra cost")
|
|
check(ORBS.apply(progress,inventory,engine,"booster"),"Apply booster")
|
|
check(player.has_free_mini_boost(),"Equipped engine")
|
|
Input.action_press("ship_mini_boost")
|
|
player.energy = 0
|
|
player._update_mini_boost(1.0)
|
|
check(player._mini_boost_active and player.energy==0,"Free TAB with empty generator")
|
|
Input.action_release("ship_mini_boost")
|
|
inventory.module_slots[2] = null
|
|
check(not player.has_free_mini_boost(),"Unequipped engine no effect")
|
|
inventory.module_slots[2] = engine
|
|
check(game.travel_to_distant("integration"),"Flight requested")
|
|
await frames(8)
|
|
game = get_tree().current_scene
|
|
freeze_game(game)
|
|
check(GameState.captain.expedition.deuter==0,"Exactly one fuel payment")
|
|
check(GameState.system_level==125 and GameState.highest_system==7,"Isolated progression")
|
|
check(game.get_node_or_null("CelestialBodies")==null,"No celestial bodies")
|
|
check(game.get_node_or_null("PlanetExpeditions")==null,"No planet expeditions")
|
|
check(game.get_node("AncientStructures").get_child_count()==14,"Decorative structures")
|
|
check(game.get_remaining_enemies()==46 and not game._boss_spawned,"Doubled encounter before boss")
|
|
player = game.get_node("PlayerShip")
|
|
inventory = player.get_node("ShipInventory")
|
|
player.is_docked = true
|
|
check("piercing" in inventory.weapon_slots[0].special_orbs,"Orb persisted across travel")
|
|
check(player.has_free_mini_boost(),"Engine orb persisted")
|
|
var enemy: Node = get_tree().get_first_node_in_group("enemies")
|
|
enemy.absorption = Vector3.ZERO
|
|
enemy.shields = 100
|
|
enemy.hull = 1000
|
|
enemy.take_piercing_weapon_hit(100,false,0,0.5)
|
|
check(is_equal_approx(enemy.shields,50) and is_equal_approx(enemy.hull,950),"50 percent shield bypass")
|
|
enemy.shields = 100
|
|
enemy.hull = 1000
|
|
enemy.take_weapon_hit(100,false,0)
|
|
check(is_equal_approx(enemy.shields,0) and is_equal_approx(enemy.hull,1000),"Other weapons unchanged")
|
|
enemy.shields = 10
|
|
enemy.hull = 1000
|
|
enemy.take_piercing_weapon_hit(100,false,0,0.5)
|
|
check(is_equal_approx(enemy.shields,0) and is_equal_approx(enemy.hull,910),"Shield overflow")
|
|
enemy.shields = 100
|
|
enemy.hull = 1000
|
|
player.get_node("WeaponController")._apply_damage(enemy,100,false,0.5)
|
|
check(is_equal_approx(enemy.hull,950),"Laser piercing")
|
|
enemy.shields = 100
|
|
enemy.hull = 1000
|
|
var projectile := preload("res://scenes/game/weapon_projectile.tscn").instantiate()
|
|
projectile.damage = 100
|
|
projectile.shield_piercing = 0.5
|
|
projectile.weapon_kind = ItemDefinition.WeaponKind.PLASMA
|
|
projectile._apply_damage_once(enemy)
|
|
check(is_equal_approx(enemy.hull,950),"Projectile piercing")
|
|
projectile.free()
|
|
var payload := Node2D.new()
|
|
payload.set_script(preload("res://scripts/items/expedition_pickup.gd"))
|
|
payload.payload = {"orb":"booster"}
|
|
payload.position = player.position
|
|
game.add_child(payload)
|
|
var count: int = progress.orbs.booster
|
|
payload._physics_process(0)
|
|
check(progress.orbs.booster==count+1,"Collect orb")
|
|
await frames()
|
|
for victim in get_tree().get_nodes_in_group("enemies"): victim.queue_free()
|
|
await frames()
|
|
game.get_node("DistantSector")._physics_process(0.3)
|
|
await frames()
|
|
check(game._boss_spawned and game.get_remaining_enemies()==1,"Exactly one boss after wave")
|
|
var boss: Node = get_tree().get_first_node_in_group("enemies")
|
|
boss.shields = 0
|
|
boss.take_damage(1000000000.0,false,0,true)
|
|
await frames()
|
|
var maps := 0
|
|
var orbs := 0
|
|
for pickup in get_tree().get_nodes_in_group("loot"):
|
|
if pickup.get_script() == preload("res://scripts/items/expedition_pickup.gd"):
|
|
if pickup.payload.has("map"): maps += 1
|
|
if pickup.payload.has("orb"): orbs += 1
|
|
check(maps==1 and orbs==1,"Actual boss death drops exactly one map and orb")
|
|
check(get_tree().get_nodes_in_group("time_crystal_pickups").size()==1,"Boss also drops time crystals")
|
|
game.get_node("DistantSector")._physics_process(0.3)
|
|
check(game.system_cleared,"Sector cleared")
|
|
player.landing_combat_lock = 0
|
|
game.get_node("DistantSector")._return_home()
|
|
await frames(8)
|
|
game = get_tree().current_scene
|
|
freeze_game(game)
|
|
check(GameState.active_distant_map.is_empty() and GameState.system_level==7 and GameState.system_seed==777,"Return home")
|
|
check(GameState.captain.expedition.deuter==0,"Return free")
|
|
check(game.has_node("PlanetExpeditions") and game.has_node("CelestialBodies"),"Normal scene restored")
|
|
check(is_instance_valid(game.get_node("PlanetExpeditions").screen) and game.get_node("PlayerShip").is_docked,"Return docks at freighter")
|
|
print("DISTANT_INTEGRATION_RESULT: "+JSON.stringify({"failures":failures,"passed":failures.is_empty()}))
|