extends Node3D class_name HitscanTracer var speed: float = 300.0 # Extremely fast var target_position: Vector3 var distance_traveled: float = 0.0 var max_distance: float = 0.0 ## Spawn a cel-styled tracer bolt: unshaded hot core with an ink outline, ## flying from origin to target. Shared by every hitscan weapon and the ## remote-fire replay so all bullets look on-theme. static func spawn_bolt(scene: Node, origin: Vector3, target: Vector3, color: Color = Color(1.0, 0.72, 0.15)) -> void: if scene == null or origin.distance_squared_to(target) <= 0.1: return var tracer := HitscanTracer.new() var core := MeshInstance3D.new() var core_mesh := CapsuleMesh.new() core_mesh.radius = 0.025 core_mesh.height = 1.1 var m := StandardMaterial3D.new() m.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED m.albedo_color = color.lightened(0.35) m.emission_enabled = true m.emission = color m.emission_energy_multiplier = 2.2 core_mesh.material = m core.mesh = core_mesh core.rotation.x = deg_to_rad(90) # orient capsule along Z core.position = Vector3(0, 0, -0.55) # tail sits at the origin core.material_overlay = LevelMaterials.outline(0.004) tracer.add_child(core) tracer.position = origin tracer.target_position = target scene.add_child(tracer) var up := Vector3.UP if absf((target - origin).normalized().dot(up)) > 0.99: up = Vector3.RIGHT tracer.look_at(target, up) func _ready() -> void: max_distance = global_position.distance_to(target_position) if max_distance < 0.1: queue_free() func _physics_process(delta: float) -> void: var move_dist = speed * delta distance_traveled += move_dist if distance_traveled >= max_distance: # Reached target queue_free() else: global_position += -global_transform.basis.z * move_dist