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_5 := false var saw_laser_4_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) 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_5 = saw_laser_1_5 or bounds == Vector2(1, 5) saw_laser_4_6 = saw_laser_4_6 or bounds == Vector2(4, 6) assert(saw_laser_1_5 and saw_laser_4_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 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)")