101 lines
4.1 KiB
GDScript
101 lines
4.1 KiB
GDScript
extends Node2D
|
||
|
||
const PLAYER := preload("res://scenes/game/player_ship.tscn")
|
||
const ENEMY := preload("res://scenes/game/enemy_ship.tscn")
|
||
|
||
class AimedGun:
|
||
extends "res://scripts/game/weapon_controller.gd"
|
||
func _aim_direction_from(_origin: Vector2) -> Vector2:
|
||
return Vector2.RIGHT
|
||
|
||
func _ready() -> void:
|
||
get_tree().create_timer(20.0).timeout.connect(func() -> void:
|
||
push_error("MACHINE_GUN_SHIELD_RECOVERY_TEST: timed out")
|
||
Input.action_release("ship_fire_primary")
|
||
get_tree().quit(1)
|
||
)
|
||
seed(12345)
|
||
GameState.start_new_run()
|
||
var ship := PLAYER.instantiate() as CharacterBody2D
|
||
ship.name = "PlayerShip"
|
||
add_child(ship)
|
||
ship.set_physics_process(false)
|
||
ship.get_node("WeaponController").set_physics_process(false)
|
||
ship.set("shields", 0.0)
|
||
ship.set("energy", 0.0)
|
||
var inventory := ship.get_node("ShipInventory") as ShipInventory
|
||
var gun := ItemInstance.new()
|
||
gun.definition = preload("res://resources/items/machine_gun.tres")
|
||
assert(inventory.add_item(gun))
|
||
assert(inventory.move_item("cargo", 0, "weapon", 0))
|
||
var module := ItemInstance.new()
|
||
module.definition = preload("res://resources/items/engine_extension.tres")
|
||
var addon := ItemStatModifier.new()
|
||
addon.affix = preload("res://resources/items/affixes/shield_on_damage.tres")
|
||
addon.stat_key = addon.affix.stat_key
|
||
addon.value = addon.affix.roll_value(1)
|
||
module.additional_modifiers.append(addon)
|
||
assert(inventory.add_item(module))
|
||
assert(inventory.move_item("cargo", inventory.cargo.find(module), "module", 2))
|
||
assert(ship.get("shield_on_damage_percent") == 1.0)
|
||
var indicator := Node2D.new()
|
||
indicator.set_script(preload("res://scripts/game/ship_energy_indicator.gd"))
|
||
indicator.set("player", ship)
|
||
ship.add_child(indicator)
|
||
var enemy := ENEMY.instantiate() as CharacterBody2D
|
||
enemy.position = Vector2(240, -28)
|
||
add_child(enemy)
|
||
enemy.set_physics_process(false)
|
||
enemy.set("_player", ship)
|
||
enemy.set("max_hull", 10000.0)
|
||
enemy.set("hull", 10000.0)
|
||
enemy.set("shields", 0.0)
|
||
var controller := AimedGun.new()
|
||
ship.add_child(controller)
|
||
await get_tree().physics_frame
|
||
await get_tree().physics_frame
|
||
# Fire a real projectile with the smallest level-1 damage: 2 DMG.
|
||
gun.damage_min = 2.0
|
||
gun.damage_max = 2.0
|
||
Input.action_press("ship_fire_primary")
|
||
for frame in 60:
|
||
await get_tree().physics_frame
|
||
if inventory.ammunition < 50:
|
||
break
|
||
Input.action_release("ship_fire_primary")
|
||
assert(inventory.ammunition == 49)
|
||
for frame in 60:
|
||
await get_tree().physics_frame
|
||
if enemy.get("hull") < 10000.0:
|
||
break
|
||
assert(is_equal_approx(enemy.get("hull"), 9998.0))
|
||
assert(is_equal_approx(ship.get("shields"), 0.02))
|
||
print("MACHINE_GUN_RECOVERY: single physical hit: 2 DMG -> +%.4f shields" % ship.get("shields"))
|
||
# Restore the normal starter roll (3–4 DMG), then empty the remaining magazine.
|
||
gun.damage_min = -1.0
|
||
gun.damage_max = -1.0
|
||
Input.action_press("ship_fire_primary")
|
||
for frame in 600:
|
||
await get_tree().physics_frame
|
||
if inventory.ammunition == 0:
|
||
break
|
||
Input.action_release("ship_fire_primary")
|
||
assert(inventory.ammunition == 0)
|
||
for frame in 45:
|
||
await get_tree().physics_frame
|
||
var actual_damage := 10000.0 - float(enemy.get("hull"))
|
||
var recovered := float(ship.get("shields"))
|
||
assert(is_equal_approx(recovered, actual_damage * 0.01))
|
||
assert(recovered > 1.0 and ship.get("energy") == 0.0)
|
||
indicator.call("_process", 1.0)
|
||
assert(is_equal_approx(indicator.get("_display_shield_ratio"), recovered / float(ship.get("max_shields"))))
|
||
print("MACHINE_GUN_RECOVERY: 50 physical hits, %.0f total DMG -> +%.4f shields; white bar: %.4f%% (%.3f px)" % [actual_damage, recovered, recovered / float(ship.get("max_shields")) * 100.0, recovered / float(ship.get("max_shields")) * 88.0])
|
||
# Empty ammo cannot keep firing or generate any further shields.
|
||
Input.action_press("ship_fire_primary")
|
||
for frame in 30:
|
||
await get_tree().physics_frame
|
||
Input.action_release("ship_fire_primary")
|
||
assert(is_equal_approx(ship.get("shields"), recovered))
|
||
print("MACHINE_GUN_SHIELD_RECOVERY_TEST: PASS (real firing input, projectile flight, collisions, 2-DMG fractions, accumulated recovery, ammo consumption, zero energy, shield bar, empty ammo)")
|
||
get_tree().quit()
|