grunk/levels/ghost_ship/ambient_drone.gd

88 lines
2.1 KiB
GDScript

extends AudioStreamPlayer
const MUTE_VOLUME := -80.0
@export var volume_increment := 0.618
@export var base_volume := -18.0
@export var boosted_volume := -2.0
@export_category("Beast Proximity Boost")
@export var proximity_cutoff := 20.0
@export var proximity_scale := 17.0
var target_volume := MUTE_VOLUME
var suppressed := false
var boosted := false
func _ready() -> void:
World.instance.manager.alert_raised.connect(_on_alert_raised)
func get_target_volume() -> float:
if suppressed:
return MUTE_VOLUME
if boosted:
return boosted_volume
return target_volume + beast_proximity_boost(closest_beast_distance())
## Calculate the volume gain from proximity to a beast
func beast_proximity_boost(distance: float) -> float:
return max(0.0, proximity_scale * (proximity_cutoff - distance) / proximity_cutoff)
## Get the distance from the player to the closest beast
func closest_beast_distance() -> float:
if not is_instance_valid(Player.instance):
return INF
var min_dist_sq := INF
var nodes := get_tree().get_nodes_in_group("GrunkBeast")
for node: Node in nodes:
var n3d := node as Node3D
if is_instance_valid(n3d):
var dist_sq := n3d.global_position.distance_squared_to(Player.instance.global_position)
if dist_sq < min_dist_sq:
min_dist_sq = dist_sq
return sqrt(min_dist_sq)
## Temporarily suppress ambience
func suppress(time: float = 5.0) -> void:
suppressed = true
get_tree().create_timer(time).timeout.connect(_unsuppress)
## Temporarily boost ambience
func boost(time: float = 5.0) -> void:
boosted = true
get_tree().create_timer(time).timeout.connect(_unboost)
func _unsuppress() -> void:
suppressed = false
func _unboost() -> void:
boosted = false
func _process(delta: float) -> void:
volume_db = lerpf(volume_db, get_target_volume(), volume_increment * delta)
func _on_player_enters_ship(_body: Node3D) -> void:
target_volume = MUTE_VOLUME
func _on_player_exits_ship(_body: Node3D) -> void:
target_volume = base_volume
func _on_alert_raised(new_level: int) -> void:
if new_level == World.instance.manager.MAX_ALERT:
suppress(30)
else:
boost(10.0)