Randoloot/tests/items/weapon_damage_test.gd
2026-10-16 20:24:12 +02:00

161 lines
6.7 KiB
GDScript

extends Node2D
const GENERATOR := preload("res://scripts/items/item_generator.gd")
const PLAYER_SCENE := preload("res://scenes/game/player_ship.tscn")
const PROJECTILE_SCRIPT := preload("res://scripts/game/weapon_projectile.gd")
class LaserProbe:
extends "res://scripts/game/weapon_controller.gd"
var hits: Array[float] = []
func _aim_direction_from(_origin: Vector2) -> Vector2:
return Vector2.RIGHT
func _apply_damage(_target: Variant, damage: float, _critical: bool = false) -> void:
hits.append(damage)
func _ready() -> void:
var saw_laser_1_2 := false
var saw_laser_3_6 := false
for definition in GENERATOR.DEFINITIONS:
if definition.category != ItemDefinition.Category.WEAPON:
continue
var starter := ItemInstance.new()
starter.definition = definition
assert(is_equal_approx(starter.get_energy_cost(), definition.energy_cost))
var stronger := ItemInstance.new()
stronger.definition = definition
var initial_range := starter.get_damage_range()
stronger.damage_min = initial_range.x * 4.0
stronger.damage_max = initial_range.y * 4.0
assert(is_equal_approx(stronger.get_energy_cost(), definition.energy_cost * 2.0))
var cost_before_addon := stronger.get_energy_cost()
var addon := ItemStatModifier.new()
addon.stat_key = "damage_percent"
addon.value = 10.0
stronger.additional_modifiers.append(addon)
if definition.weapon_kind in [ItemDefinition.WeaponKind.MACHINE_GUN, ItemDefinition.WeaponKind.MISSILE, ItemDefinition.WeaponKind.GAMMA]:
assert(stronger.get_energy_cost() == 0.0)
else:
assert(stronger.get_energy_cost() > cost_before_addon)
for level in [1, 50, 1000]:
for sample in 100:
var item := GENERATOR.generate_for_definition(definition, level)
var bounds := item.get_damage_range()
assert(bounds.x >= 1 and bounds.y > bounds.x)
var scale_factor: float = 1.0 + 0.05 * (level - 1)
assert(bounds.x >= roundf(definition.damage_lower_roll_min * scale_factor))
assert(bounds.x <= roundf(definition.damage_lower_roll_max * scale_factor))
assert(bounds.y <= roundf((definition.damage_lower_roll_max + definition.damage_spread_roll_max) * scale_factor))
for shot in 20:
var damage := item.roll_damage()
assert(damage >= bounds.x and damage <= bounds.y)
assert(item.get_damage_range() == bounds)
assert(item.get_tooltip_text().contains(item.get_damage_range_text()))
if definition.item_id == "beam_laser" and level == 1:
saw_laser_1_2 = saw_laser_1_2 or bounds == Vector2(1, 2)
saw_laser_3_6 = saw_laser_3_6 or bounds == Vector2(3, 6)
assert(saw_laser_1_2 and saw_laser_3_6)
var laser := ItemInstance.new()
laser.definition = preload("res://resources/items/beam_laser.tres")
laser.damage_min = 1
laser.damage_max = 5
var results: Dictionary = {}
for shot in 300:
results[laser.roll_damage()] = true
assert(results.size() == 5 and results.has(1.0) and results.has(5.0))
var legacy := ItemInstance.new()
legacy.definition = laser.definition
legacy.primary_value_override = 7.5
assert(legacy.roll_damage() == 7.5)
var player := PLAYER_SCENE.instantiate() as CharacterBody2D
add_child(player)
player.set_physics_process(false)
player.get_node("WeaponController").set_physics_process(false)
player.set("damage_multiplier", 1.25)
var probe := LaserProbe.new()
player.add_child(probe)
probe.set_physics_process(false)
var inventory := player.get_node("ShipInventory") as ShipInventory
assert(inventory.ammunition == ShipInventory.STARTING_AMMUNITION)
var machine_gun := ItemInstance.new()
machine_gun.definition = preload("res://resources/items/machine_gun.tres")
player.set("energy", 0.0)
inventory.ammunition = 1
assert(probe._consume_shot_resource(machine_gun))
assert(inventory.ammunition == 0 and player.get("energy") == 0.0)
assert(not probe._consume_shot_resource(machine_gun))
GameState.captain.parts = 49.0
assert(not inventory.craft_ammunition())
assert(inventory.ammunition == 0 and GameState.captain.parts == 49.0)
GameState.captain.minerals["titanium"] = 1
GameState.captain.minerals["sulfur"] = 1
assert(inventory.craft_ammunition())
assert(inventory.ammunition == 10 and GameState.captain.parts == 49.0)
GameState.system_level = 3
var buy_cost := ShipInventory.AMMUNITION_BUY_BASE_COST * 3
assert(inventory.get_ammunition_buy_cost() == buy_cost)
GameState.captain.credits = buy_cost - 1
assert(not inventory.buy_ammunition())
assert(inventory.ammunition == 10 and GameState.captain.credits == buy_cost - 1)
GameState.captain.credits = buy_cost * 2
assert(inventory.buy_ammunition())
assert(inventory.ammunition == 110 and GameState.captain.credits == buy_cost)
assert(inventory.buy_ammunition())
assert(inventory.ammunition == 210 and GameState.captain.credits == 0)
assert(not inventory.buy_ammunition())
GameState.system_level = 1
inventory.preserve_for_restart()
var restored_player := PLAYER_SCENE.instantiate() as CharacterBody2D
add_child(restored_player)
assert(restored_player.get_node("ShipInventory").get("ammunition") == 210)
restored_player.queue_free()
var target := StaticBody2D.new()
target.position = Vector2(200, -28)
target.collision_layer = 4
var collision := CollisionShape2D.new()
var shape := CircleShape2D.new()
shape.radius = 20
collision.shape = shape
target.add_child(collision)
add_child(target)
await get_tree().physics_frame
await get_tree().physics_frame
for shot in 100:
player.set("energy", 100.0)
probe.set("_shot_timers", [0.0, 0.0])
probe._fire_laser(0, laser)
assert(probe.hits.size() == 100)
var laser_hits: Dictionary = {}
for hit in probe.hits:
assert(hit >= 1.25 and hit <= 6.25)
laser_hits[hit] = true
assert(laser_hits.size() == 5)
player.set("energy", 0.0)
probe.set("_shot_timers", [0.0, 0.0])
probe._fire_laser(0, laser)
assert(probe.hits.size() == 100)
player.set("energy", 100.0)
probe.set("_shot_timers", [10.0, 0.0])
probe._fire_laser(0, laser)
assert(probe.hits.size() == 100)
for definition in GENERATOR.DEFINITIONS:
if definition.category != ItemDefinition.Category.WEAPON or definition.weapon_kind == ItemDefinition.WeaponKind.LASER:
continue
var item := GENERATOR.generate_for_definition(definition, 1)
var bounds := item.get_damage_range()
var projectile_results: Dictionary = {}
for shot in 100:
var previous_child_count := get_child_count()
probe._fire_projectile(item)
var projectile := get_child(previous_child_count)
assert(projectile.get_script() == PROJECTILE_SCRIPT)
var damage := float(projectile.get("damage"))
assert(damage >= bounds.x * 1.25 and damage <= bounds.y * 1.25)
projectile_results[damage] = true
remove_child(projectile)
projectile.free()
assert(projectile_results.size() > 1)
print("WEAPON_DAMAGE_TEST: PASS (1200 weapon rolls, 24000 damage rolls, 100 laser pulses and 300 projectiles; bonuses and energy/cooldown gates)")