straywild/world/regions/world_region.gd
Voyager 4575830857 Improve nearby water recovery and camera prompts
Recover players on generated worlds to the nearest safe grass or sand surface. Use the active gameplay camera when positioning shop and storage prompts.
2026-08-29 17:43:11 -04:00

172 lines
4.5 KiB
GDScript

@tool
class_name WorldRegion
extends Node3D
@export var region_id: StringName
@export var fishable_water_root: NodePath = ^"FishingWater"
@export var water_recovery_root: NodePath = ^"WaterRecovery"
@export var safe_respawns_root: NodePath = ^"SafeRespawns"
@export var diggable_area_root: NodePath = ^"DiggableAreas"
@export var gatherable_anchor_root: NodePath = ^"GatherableAnchors"
func get_player_spawn_transform() -> Transform3D:
return global_transform
func get_fishing_shop() -> FishingShopInteraction:
return null
func get_player_storage() -> PlayerStorageInteraction:
return null
func get_saltwater_shoreline_mesh() -> MeshInstance3D:
return null
func set_light_performance_profile(_enabled: bool) -> void:
pass
func get_playable_half_extents() -> Vector2:
return Vector2(50.0, 50.0)
func get_spawn_surface_triangles(
_material_names: Array[StringName],
_minimum_global_y: float,
_minimum_up_dot: float = 0.6,
) -> Array[PackedVector3Array]:
return []
func get_fishable_water_regions() -> Array[FishableWaterRegion]:
var regions: Array[FishableWaterRegion] = []
var root: Node = get_node_or_null(fishable_water_root)
if root == null:
return regions
_collect_fishable_water_regions(root, regions)
return regions
func get_water_recovery_triggers() -> Array[PlayerWaterTrigger]:
var triggers: Array[PlayerWaterTrigger] = []
var root: Node = get_node_or_null(water_recovery_root)
if root == null:
return triggers
_collect_water_recovery_triggers(root, triggers)
return triggers
func get_safe_respawn_points() -> Array[SafeRespawnPoint]:
var points: Array[SafeRespawnPoint] = []
var root: Node = get_node_or_null(safe_respawns_root)
if root == null:
return points
for child: Node in root.get_children():
var point: SafeRespawnPoint = child as SafeRespawnPoint
if point != null:
points.append(point)
return points
func get_water_recovery_position(
entry_position: Vector3,
fallback_position: Vector3,
) -> Vector3:
if not entry_position.is_finite():
return fallback_position
var target_position := fallback_position
var nearest_distance := INF
for point: SafeRespawnPoint in get_safe_respawn_points():
if point == null or not is_instance_valid(point) or not point.enabled:
continue
var distance := point.get_horizontal_distance_squared(entry_position)
if distance < nearest_distance:
nearest_distance = distance
target_position = point.global_position
return target_position
func get_diggable_areas() -> Array[DiggableArea3D]:
var areas: Array[DiggableArea3D] = []
var root: Node = get_node_or_null(diggable_area_root)
if root == null:
return areas
_collect_diggable_areas(root, areas)
return areas
func get_diggable_area(area_id: StringName) -> DiggableArea3D:
if area_id.is_empty():
return null
for area: DiggableArea3D in get_diggable_areas():
if area.area_id == area_id:
return area
return null
func get_gatherable_anchor_sets() -> Array[GatherableAnchorSet3D]:
var anchor_sets: Array[GatherableAnchorSet3D] = []
var root: Node = get_node_or_null(gatherable_anchor_root)
if root == null:
return anchor_sets
_collect_gatherable_anchor_sets(root, anchor_sets)
return anchor_sets
func get_gatherable_anchor_set(
anchor_set_id: StringName,
) -> GatherableAnchorSet3D:
if anchor_set_id.is_empty():
return null
for anchor_set: GatherableAnchorSet3D in get_gatherable_anchor_sets():
if anchor_set.anchor_set_id == anchor_set_id:
return anchor_set
return null
func _collect_fishable_water_regions(
root: Node,
regions: Array[FishableWaterRegion],
) -> void:
for child: Node in root.get_children():
var water := child as FishableWaterRegion
if water != null:
regions.append(water)
_collect_fishable_water_regions(child, regions)
func _collect_water_recovery_triggers(
root: Node,
triggers: Array[PlayerWaterTrigger],
) -> void:
for child: Node in root.get_children():
var trigger := child as PlayerWaterTrigger
if trigger != null:
triggers.append(trigger)
_collect_water_recovery_triggers(child, triggers)
func _collect_diggable_areas(
root: Node,
areas: Array[DiggableArea3D],
) -> void:
for child: Node in root.get_children():
var area := child as DiggableArea3D
if area != null:
areas.append(area)
_collect_diggable_areas(child, areas)
func _collect_gatherable_anchor_sets(
root: Node,
anchor_sets: Array[GatherableAnchorSet3D],
) -> void:
for child: Node in root.get_children():
var anchor_set := child as GatherableAnchorSet3D
if anchor_set != null:
anchor_sets.append(anchor_set)
_collect_gatherable_anchor_sets(child, anchor_sets)