class_name Ball extends RigidBody3D # Physics ball. Floor gravity is untouched (gravity_scale in ball.tscn); this # only adds the wall/ceiling "surface pull" (see ArenaBoundary.get_surface_pull) # so the ball can cling near a wall for dribbling or hang against the ceiling # for ceiling shots, plus a safety speed clamp (the ball previously had none). @export_group("Surface Pull") @export var wall_pull_strength = 4.0 # Weaker than the ship's — assist, not adherence @export var wall_pull_range = 2.0 @export var ceiling_pull_strength = 5.5 # Stays below the ball's effective gravity (0.8 * 9.8) @export var ceiling_pull_range = 2.0 # Kept close to ship_observations.gd's BALL_SPEED_SCALE (30.0) so this feature # doesn't push ball velocity further out of the range trained policies expect. const MAX_SPEED := 32.0 var _boundary: ArenaBoundary func _ready() -> void: _boundary = get_tree().get_first_node_in_group("arena_boundary") func _integrate_forces(state: PhysicsDirectBodyState3D) -> void: if _boundary: var pull := _boundary.get_surface_pull( global_position, wall_pull_strength, wall_pull_range, ceiling_pull_strength, ceiling_pull_range ) state.apply_central_force(pull * mass) if state.linear_velocity.length() > MAX_SPEED: state.linear_velocity = state.linear_velocity.normalized() * MAX_SPEED