class_name GameBall extends RigidBody3D ## Base class for all gfolf balls signal entered_water const TERRAIN_DAMPING_EPSILON := 1e-6 const IRON_DAMPING := 9999.0 ## Angular damping while in air @export var air_damping := 0.0 ## Angular damping while in collision with rough terrain @export var rough_damping := 8.0 ## Angular damping for iron balls @export var iron_damping := 9999.0 ## Causes the ball to act more like a brick @export var iron_ball := false: set(value): if value: physics_material_override = iron_physics else: physics_material_override = normal_physics iron_ball = value var _zones: Array[BallZone] = [] @onready var normal_physics: PhysicsMaterial = preload( "res://src/equipment/balls/physics_ball/normal_physics.tres" ) @onready var iron_physics: PhysicsMaterial = preload( "res://src/equipment/balls/physics_ball/iron_physics.tres" ) ## Called by a water area when this ball enters it func enter_water() -> void: entered_water.emit() func _total_terrain_angular_damping() -> float: return _zones.reduce( func(a: float, b: BallZone) -> float: return a + b.terrain_angular_damping, 0.0 ) func _integrate_forces(state: PhysicsDirectBodyState3D) -> void: var damping := air_damping if iron_ball: damping = iron_damping elif state.get_contact_count(): damping = _total_terrain_angular_damping() if damping <= TERRAIN_DAMPING_EPSILON: damping = rough_damping angular_damp = damping func enter_zone(zone: BallZone) -> void: _zones.push_back(zone) if zone.water_hazard: entered_water.emit() func exit_zone(zone: BallZone) -> void: _zones.erase(zone)