class_name Projectile extends RigidBody3D var damage := 0.0 # set by launch(), read by whatever we hit var _time_left := 10.0 func _ready() -> void: add_to_group("shift_with_origin") body_entered.connect(_on_body_entered) ## Call after add_child(). Configures this projectile from a def and sends it flying. func launch(def: AmmoDef, muzzle: Transform3D, speed_scale := 1.0) -> void: damage = def.damage gravity_scale = def.gravity_scale _time_left = def.lifetime global_transform = muzzle linear_velocity = -muzzle.basis.z * def.muzzle_speed * speed_scale reset_physics_interpolation() func _physics_process(delta: float) -> void: if Vector3.UP.cross(linear_velocity).length_squared() > 0.01: look_at(global_position + linear_velocity) _time_left -= delta if _time_left <= 0.0: queue_free() func _on_body_entered(body: Node) -> void: if body.has_method("take_damage"): body.take_damage(damage) queue_free()