191 lines
8.2 KiB
GDScript
191 lines
8.2 KiB
GDScript
extends Node2D
|
|
const DATA := preload("res://scripts/planets/alien_research.gd")
|
|
const ENEMY := preload("res://scenes/game/enemy_ship.tscn")
|
|
const PROJECTILE := preload("res://scenes/game/weapon_projectile.tscn")
|
|
var player: CharacterBody2D
|
|
var progress: Resource
|
|
|
|
class StraightLaser extends "res://scripts/game/weapon_controller.gd":
|
|
func _aim_direction_from(_origin: Vector2) -> Vector2:
|
|
return Vector2.RIGHT
|
|
|
|
func enemy_at(point: Vector2, hp := 1000.0, tier := 0) -> CharacterBody2D:
|
|
var enemy := ENEMY.instantiate() as CharacterBody2D
|
|
add_child(enemy)
|
|
enemy.set_physics_process(false)
|
|
enemy.position = point
|
|
enemy.loot_tier = tier
|
|
enemy.max_hull = hp
|
|
enemy.hull = hp
|
|
enemy.shields = 0.0
|
|
enemy.absorption = Vector3.ZERO
|
|
enemy._player = player
|
|
return enemy
|
|
|
|
func complete(value: Resource, id: String) -> bool:
|
|
var started := DATA.purchase(value,id)
|
|
if started: DATA.advance(value,600)
|
|
return started
|
|
|
|
func _ready() -> void:
|
|
GameState.start_new_run()
|
|
GameState.captain.level = 80
|
|
progress = GameState.captain.expedition
|
|
progress.analysis_samples = 1000
|
|
assert(complete(progress,"general") and complete(progress,"hull"))
|
|
for side in ["a","b"]:
|
|
var id: String = "hull_"+side
|
|
for level in 4:
|
|
assert(DATA.cost(id)==20+level*5 and complete(progress,id))
|
|
assert(not complete(progress,id))
|
|
id+="_next"
|
|
assert(not complete(progress,"shields_a"),"Shield category prerequisite is required")
|
|
progress.alien_skills = {"hull_a":true}
|
|
player = preload("res://scenes/game/player_ship.tscn").instantiate()
|
|
add_child(player)
|
|
player.set_physics_process(false)
|
|
player.get_node("WeaponController").set_physics_process(false)
|
|
var enemy := enemy_at(Vector2(5000,0))
|
|
enemy.take_research_weapon_hit(100,false,DamageTypes.Type.ENERGY,0,-1)
|
|
assert(is_equal_approx(enemy.hull,895.0))
|
|
progress.alien_skills = {"hull_a_next":true}
|
|
enemy.hull = 1000.0
|
|
enemy.absorption = Vector3(0,60,0)
|
|
enemy.take_research_weapon_hit(100,false,DamageTypes.Type.ENERGY,0,-1)
|
|
assert(enemy.hull==960.0 and enemy._hull_breach_remaining==5.0)
|
|
enemy.take_research_weapon_hit(100,false,DamageTypes.Type.ENERGY,0,-1)
|
|
assert(enemy.hull==890.0 and enemy._hull_breach_remaining==5.0,"Breach halves absorption without stacking")
|
|
enemy._physics_process(5.1)
|
|
assert(enemy._hull_breach_remaining==0.0)
|
|
enemy.set_physics_process(false)
|
|
progress.alien_skills = {"hull_a_next_next_next":true}
|
|
var normal := enemy_at(Vector2(6000,0))
|
|
normal.configure(player,preload("res://scripts/items/alien_ship_catalog.gd").TEXTURES[0])
|
|
normal.hull = 90.0
|
|
normal.take_research_weapon_hit(10,false,DamageTypes.Type.ENERGY,0,-1)
|
|
assert(normal.hull==0.0 and normal._execution_finish)
|
|
var collapse_found := false
|
|
for child in get_children():
|
|
if child.get_script()==preload("res://scripts/game/hull_collapse_effect.gd"):
|
|
assert(child._pieces.size()==9)
|
|
child._process(0.1)
|
|
collapse_found = true
|
|
assert(collapse_found,"Execution uses actual ship texture fragments")
|
|
var boss := enemy_at(Vector2(7000,0),1000,2)
|
|
boss.hull = 40.0
|
|
boss.take_research_weapon_hit(10,false,DamageTypes.Type.ENERGY,0,-1)
|
|
assert(boss.hull==30.0)
|
|
boss.take_research_weapon_hit(10,false,DamageTypes.Type.ENERGY,0,-1)
|
|
assert(boss.hull==0.0)
|
|
var shielded := enemy_at(Vector2(8000,0))
|
|
shielded.hull = 50.0
|
|
shielded.shields = 100.0
|
|
shielded.take_research_weapon_hit(10,false,DamageTypes.Type.ENERGY,0,-1)
|
|
assert(shielded.hull==50.0,"A hit absorbed by shields cannot execute")
|
|
progress.alien_skills = {"hull_a_next_next":true}
|
|
var first := enemy_at(Vector2(100,100))
|
|
var second := enemy_at(Vector2(300,100))
|
|
var third := enemy_at(Vector2(500,100))
|
|
var shot := PROJECTILE.instantiate()
|
|
shot.configure(first.position,Vector2.RIGHT,ItemDefinition.WeaponKind.PLASMA,600,100,800)
|
|
add_child(shot)
|
|
shot.set_physics_process(false)
|
|
shot._hit_target(first)
|
|
await get_tree().process_frame
|
|
var continuation: Node
|
|
for child in get_children():
|
|
if child.get_script()==preload("res://scripts/game/weapon_projectile.gd") and child._overpenetration_used: continuation=child
|
|
assert(continuation!=null and continuation.damage==50.0)
|
|
continuation.set_physics_process(false)
|
|
continuation._physics_process(0.2)
|
|
assert(continuation.global_position.x>150.0,"Continuation exits the pierced ship instead of getting stuck")
|
|
continuation._physics_process(0.2)
|
|
assert(first.hull==900.0 and second.hull==950.0 and third.hull==1000.0)
|
|
assert(continuation.is_queued_for_deletion(),"A penetrating shot cannot create a third hit")
|
|
first.hull = 1000.0
|
|
second.hull = 1000.0
|
|
var missile := PROJECTILE.instantiate()
|
|
missile.configure(first.position,Vector2.RIGHT,ItemDefinition.WeaponKind.MISSILE,600,100,800)
|
|
add_child(missile)
|
|
missile.set_physics_process(false)
|
|
missile._hit_target(first)
|
|
await get_tree().process_frame
|
|
var missile_continuation: Node
|
|
for child in get_children():
|
|
if child.get_script()==preload("res://scripts/game/weapon_projectile.gd") and child._overpenetration_used and child.weapon_kind==ItemDefinition.WeaponKind.MISSILE: missile_continuation=child
|
|
assert(missile_continuation!=null)
|
|
missile_continuation.set_physics_process(false)
|
|
missile_continuation._physics_process(0.2)
|
|
missile_continuation._physics_process(0.2)
|
|
assert(first.hull==900.0 and second.hull==950.0 and third.hull==1000.0,"Missile continuation deals half damage to one additional target")
|
|
first.position = Vector2(160,-28)
|
|
second.position = Vector2(300,-28)
|
|
third.position = Vector2(450,-28)
|
|
first.hull = 1000.0
|
|
second.hull = 1000.0
|
|
var laser := StraightLaser.new()
|
|
player.add_child(laser)
|
|
laser.set_physics_process(false)
|
|
var laser_item := ItemInstance.new()
|
|
laser_item.definition = preload("res://resources/items/beam_laser.tres")
|
|
laser_item.damage_min = 100.0
|
|
laser_item.damage_max = 100.0
|
|
player.energy = 1000.0
|
|
await get_tree().physics_frame
|
|
await get_tree().physics_frame
|
|
laser._fire_laser(0,laser_item)
|
|
assert(first.hull==900.0 and second.hull==950.0 and third.hull==1000.0,"Laser penetrates precisely one additional target")
|
|
assert(laser._laser_lines[0].get_point_count()==3)
|
|
laser.queue_free()
|
|
progress.alien_skills = {"hull_b":true}
|
|
var inventory: ShipInventory = player.get_node("ShipInventory")
|
|
player.hull = 50.0
|
|
inventory._recalculate_ship_stats()
|
|
assert(is_equal_approx(player.max_hull,player.base_max_hull*1.1) and player.hull==50.0)
|
|
progress.alien_skills = {"hull_b_next":true}
|
|
player.max_hull = 100.0
|
|
player.hull = 100.0
|
|
player.shields = 5.0
|
|
player.absorption = Vector3.ZERO
|
|
player.take_damage(25.0)
|
|
assert(player.hull==94.0 and player._reactive_armor_cooldown==15.0)
|
|
player.take_damage(10.0)
|
|
assert(player.hull==84.0)
|
|
player.tick_hull_technologies(15.0)
|
|
player.take_damage(10.0)
|
|
assert(player.hull==81.0)
|
|
progress.alien_skills = {"hull_b_next_next":true}
|
|
player.hull = 40.0
|
|
player.shields = 0.0
|
|
player.take_damage(20.0)
|
|
assert(player.hull==20.0 and player._bulkhead_cooldown==45.0)
|
|
player.tick_hull_technologies(2.0)
|
|
assert(player.hull==26.0)
|
|
player.take_damage(1.0)
|
|
player.tick_hull_technologies(3.0)
|
|
assert(player.hull==34.0,"Hits do not interrupt five-second repair")
|
|
player.take_damage(10.0)
|
|
assert(player._bulkhead_repair_remaining==0.0,"Repair cannot retrigger during cooldown")
|
|
progress.alien_skills = {"hull_b_next_next_next":true}
|
|
player.hull = 10.0
|
|
player.take_damage(1000.0)
|
|
assert(player.hull==1.0 and not player._is_destroyed and GameState.hull_bastion_used)
|
|
player.take_damage(1000.0)
|
|
assert(player.hull==1.0)
|
|
player.is_docked = true
|
|
player.tick_hull_technologies(10.0)
|
|
assert(GameState.hull_bastion_used and player._bastion_invulnerability==2.0,"Docking does not renew Last Bastion")
|
|
player.is_docked = false
|
|
player.tick_hull_technologies(2.1)
|
|
player.take_damage(1000.0)
|
|
assert(player._is_destroyed,"Last Bastion works only once")
|
|
GameState.system_level = 7
|
|
GameState.system_seed = 777
|
|
progress.distant_maps["hull_test"] = {"id":"hull_test","level":125,"seed":123}
|
|
progress.deuter = 125000
|
|
assert(GameState.depart_distant("hull_test") and not GameState.hull_bastion_used)
|
|
GameState.hull_bastion_used = true
|
|
GameState.restore_distant_home()
|
|
assert(GameState.hull_bastion_used and GameState.system_level==7,"Return preserves the home's used rescue")
|
|
print("ALIEN_HULL_TECHNOLOGIES_TEST: PASS (8 technologies, costs, breach, execution thresholds, penetration, reactive armor, uninterrupted repair, persistent one-use rescue)")
|