extends ExplosiveProjectile class_name BouncingProjectile var fuse_time: float = -1.0 # -1 means no fuse started yet var bounce_fuse_delay: float = 3.0 # How long to wait after bouncing var impact_detonate_time: float = 2.0 var bounciness: float = 0.4 var flight_time: float = 0.0 func _physics_process(delta: float) -> void: flight_time += delta if fuse_time > 0.0: fuse_time -= delta if fuse_time <= 0.0: _explode(global_position) destroy() return # Apply gravity drop if any velocity.y -= drop_gravity * delta var movement = velocity * delta var space_state = get_world_3d().direct_space_state var query = PhysicsRayQueryParameters3D.create(_previous_position, global_position + movement) if owner_player: query.exclude = [owner_player.get_rid()] var result = space_state.intersect_ray(query) if result: if flight_time > impact_detonate_time: # Explode on impact if flying long enough _on_hit(result) else: # Bounce global_position = result.position + result.normal * 0.05 _previous_position = global_position # Reflect velocity velocity = velocity.bounce(result.normal) * bounciness # Start the fuse if it hasn't started if fuse_time < 0.0: fuse_time = bounce_fuse_delay # If it hits an entity directly, still bounce, it's a heavy mortar shell! else: global_position += movement distance_traveled += movement.length() _previous_position = global_position