Randoloot/tests/ships/alien_shield_technologies_test.gd
2026-10-27 22:20:01 +01:00

177 lines
7.4 KiB
GDScript

extends Node2D
const DATA := preload("res://scripts/planets/alien_research.gd")
const ENEMY := preload("res://scenes/game/enemy_ship.tscn")
var player: CharacterBody2D
var progress: Resource
class StraightAlien extends "res://scripts/game/enemy_ship.gd":
func _laser_aim_direction(direction: Vector2) -> Vector2:
return direction
func enemy_at(point: Vector2) -> CharacterBody2D:
var enemy := ENEMY.instantiate() as CharacterBody2D
enemy.set_script(StraightAlien)
add_child(enemy)
enemy.set_physics_process(false)
enemy.position = point
enemy.max_hull = 10000.0
enemy.hull = 10000.0
enemy.max_shields = 1000.0
enemy.shields = 1000.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,"shields"))
for side in ["a","b"]:
var id: String = "shields_"+side
for level in 4:
assert(DATA.cost(id)==20+level*5 and complete(progress,id))
assert(not complete(progress,id))
id+="_next"
assert(DATA.ACTIVE_IDS.size()==28)
player = preload("res://scenes/game/player_ship.tscn").instantiate()
add_child(player)
player.set_physics_process(false)
var weapon := player.get_node("WeaponController")
weapon.set_physics_process(false)
var enemy := enemy_at(Vector2(1000,0))
var nearby := enemy_at(Vector2(1100,0))
var chain := enemy_at(Vector2(1200,0))
progress.alien_skills = {"shields":true,"shields_a":true}
enemy.take_research_weapon_hit(100,false,DamageTypes.Type.ENERGY,0,-1)
assert(is_equal_approx(enemy.shields,885.0),"Shield bonuses add to 15 percent")
progress.alien_skills = {"shields_a_next":true}
enemy.shields = 500
enemy.take_research_weapon_hit(10,false,DamageTypes.Type.ENERGY,0,-1)
assert(enemy._shield_regen_lock==5.0)
enemy.regenerate_defenses(1.0)
assert(enemy.shields==490.0)
enemy.tick_shield_technologies(3.0)
enemy.take_research_weapon_hit(10,false,DamageTypes.Type.ENERGY,0,-1)
assert(enemy._shield_regen_lock==5.0)
enemy.tick_shield_technologies(5.1)
enemy.regenerate_defenses(1.0)
assert(enemy.shields==490.0)
progress.alien_skills = {"shields_a_next_next":true}
enemy.shields = 50
nearby.shields = 50
enemy.take_research_weapon_hit(100,false,DamageTypes.Type.ENERGY,0,-1)
assert(nearby.shields==0 and nearby.hull==9650,"Overload deals 400 percent, including spill")
assert(chain.shields==1000,"Overload cannot trigger a chain")
assert(enemy._shield_overload_cooldown==10)
enemy.shields = 1
enemy.take_research_weapon_hit(100,false,DamageTypes.Type.ENERGY,0,-1)
assert(nearby.hull==9650,"Regrown shield cannot spam overload")
enemy.tick_shield_technologies(10.1)
enemy.shields = 1
enemy.take_research_weapon_hit(100,false,DamageTypes.Type.ENERGY,0,-1)
assert(nearby.hull==9250)
progress.alien_skills = {"shields_b":true}
player.shields = 20
player.apply_equipment_bonuses({})
assert(is_equal_approx(player.max_shields,player.base_max_shields*1.1) and player.shields==20)
player.max_shields = 100
player.max_hull = 1000
player.hull = 1000
player.absorption = Vector3.ZERO
progress.alien_skills = {"shields_b_next":true}
player.shields = 40
player.take_damage(20)
assert(player._shield_reserve_remaining==2 and player._shield_reserve_cooldown==15)
player.energy = 5
assert(weapon._consume_energy(10) and player.energy==0,"Reduced cost is applied once")
player.tick_hull_technologies(2.1)
player.energy = 5
assert(not weapon._consume_energy(10),"Normal cost after reserve expires")
player.shields = 40
player.take_damage(20)
assert(player._shield_reserve_remaining==0,"Reserve cooldown prevents retrigger")
progress.alien_skills = {"shields_b_next_next":true}
player.shields = 100
player.take_damage(100)
assert(player.shields==90 and player._salvo_cooldown==60)
player.take_damage(20)
assert(player.shields==70,"Only first hit is reduced")
player.is_docked = true
player.tick_hull_technologies(60)
assert(player._salvo_cooldown==60,"Docking does not refresh cooldown")
player.is_docked = false
player.tick_hull_technologies(60)
player.shields = 5
player.take_damage(100)
assert(player.shields==0 and player.hull==995,"First-hit reduction also covers spill")
progress.alien_skills = {"shields_b_next_next_next":true}
player.hull = 1000
player.shields = 10
player.take_damage(20)
assert(player.shields==25 and player.hull==990 and player._emergency_shield_cooldown==30)
player.take_damage(20)
assert(player.shields==15,"Emergency shield halves following hits")
progress.alien_skills["shields_b_next_next"] = true
player._salvo_cooldown = 0
player.take_damage(100)
assert(player.shields==5,"Stronger protection applies without multiplying reductions")
player.tick_hull_technologies(2.1)
player.take_damage(10)
assert(player.shields==0 and player.hull==985,"Emergency shield cannot retrigger during cooldown")
progress.alien_skills = {"shields_a_next_next_next":true}
player.shields = 100
enemy.shields = 100
player.take_enemy_weapon_hit(50,false,DamageTypes.Type.ENERGY,enemy)
assert(player.shields==50 and enemy.shields==90,"Reflection uses absorbed damage and actual shooter")
player.shields = 5
player.take_enemy_weapon_hit(50,false,DamageTypes.Type.ENERGY,enemy)
assert(enemy.shields==89,"Hull damage is not reflected")
player.take_enemy_weapon_hit(10,false,DamageTypes.Type.ENERGY,enemy)
assert(enemy.shields==89,"No reflection without shields")
player.shields = 100
enemy.virus_controlled = true
player.take_enemy_weapon_hit(10,false,DamageTypes.Type.ENERGY,enemy)
assert(enemy.shields==89,"Friendly controlled aliens do not receive reflection")
enemy.virus_controlled = false
player.shields = 100
var projectile := preload("res://scenes/game/weapon_projectile.tscn").instantiate()
projectile.enemy_shot = true
projectile.source_ship = enemy
projectile.damage = 20
add_child(projectile)
projectile.set_physics_process(false)
projectile._apply_damage_once(player)
assert(player.shields==80 and is_equal_approx(enemy.shields,85),"Enemy projectile retains its shooter for reflection")
projectile.queue_free()
var shooter := enemy_at(Vector2(0,-180))
shooter.weapon_kind = ItemDefinition.WeaponKind.LASER
shooter.weapon_damage = 20
shooter.weapon_range = 500
shooter._combat_target = player
player.shields = 100
await get_tree().physics_frame
await get_tree().physics_frame
var laser_damage: float = shooter.get_shot_damage()
shooter._fire_plasma(Vector2.DOWN)
assert(is_equal_approx(player.shields,100-laser_damage),"Actual laser hits the player")
assert(is_equal_approx(shooter.shields,1000-laser_damage*0.2),"Actual laser reflection returns to the shooter")
var orphan := preload("res://scenes/game/weapon_projectile.tscn").instantiate()
orphan.enemy_shot = true
orphan.source_ship = enemy
orphan.configure(Vector2(3000,3000),Vector2.RIGHT,ItemDefinition.WeaponKind.PLASMA,600,10,1000)
add_child(orphan)
orphan.set_physics_process(false)
enemy.free()
player.shields = 100
orphan._physics_process(0.01)
orphan._hit_target(player)
assert(player.shields==90,"Projectile still hits safely after shooter is freed; no reflection to invalid source")
print("ALIEN_SHIELD_TECHNOLOGIES_TEST: PASS (8 skills, costs, 400% overload without chains, regen lock, energy reserve, 10% first hit/60s, emergency shield, reflection)")