# GDScript class_name Projectile extends Node3D signal hit(collider: Object) @export var initial_speed: float = 50.0 @export var damage: float = 3.0 @export var lifetime_after_hit: float = 3.0 @export var uses_x_forward: bool = true # Mesh zeigt mit +X nach vorne var speed: float = 0.0 var direction: Vector3 = Vector3.ZERO @onready var ray_cast: RayCast3D = $RayCast3D func _physics_process(delta: float) -> void: if speed > 0.0: var move_dir := direction if direction != Vector3.ZERO else -global_transform.basis.z global_translate(move_dir * speed * delta) if ray_cast and ray_cast.is_colliding(): var collider: Object = ray_cast.get_collider() _on_hit(collider) func shoot(new_direction: Vector3 = Vector3.ZERO) -> void: direction = new_direction.normalized() if new_direction != Vector3.ZERO else -global_transform.basis.z speed = initial_speed # Beim Abfeuern aus der Waffen-Hierarchie lösen, damit Maus-/Kamerabewegung den Pfeil nicht beeinflusst _detach_to_world() # Visuelle Ausrichtung konsistent zur Flugrichtung setzen _align_visual_to_direction() if ray_cast: ray_cast.enabled = true func _align_visual_to_direction() -> void: look_at(global_transform.origin + direction, Vector3.UP) # Godot richtet -Z nach vorne aus; wenn das Mesh +X als "vorne" hat, um -90° um Y korrigieren if uses_x_forward: rotate_z(deg_to_rad(90.0)) func _detach_to_world() -> void: var target_parent: Node = get_tree().current_scene if get_tree().current_scene != null else get_tree().root if target_parent == null: return var gt := global_transform var p := get_parent() if p and p != target_parent: p.remove_child(self) target_parent.add_child(self) global_transform = gt func _on_hit(collider: Object) -> void: if speed == 0.0: return speed = 0.0 if ray_cast: ray_cast.enabled = false emit_signal("hit", collider) _apply_damage_if_supported(collider) if lifetime_after_hit > 0.0: var timer := get_tree().create_timer(lifetime_after_hit) timer.timeout.connect(queue_free) else: queue_free() func _apply_damage_if_supported(collider: Object) -> void: if collider and collider.has_method("take_damage"): collider.call("take_damage", damage)