Scale coastal crab spawning by habitat

This commit is contained in:
Alexander Sellite 2026-08-31 16:04:34 -04:00
parent d8bf59bca0
commit 0158b0215f
9 changed files with 261 additions and 59 deletions

View file

@ -43,6 +43,7 @@ var _entity_revisions: Dictionary = {}
var _surface_triangles: Dictionary = {}
var _surface_areas: Dictionary = {}
var _surface_total_areas: Dictionary = {}
var _surface_height_ranges: Dictionary = {}
var _spawn_anchor_positions: Dictionary = {}
var _respawns: Array[Dictionary] = []
var _next_respawn_by_type: Dictionary[StringName, float] = {}
@ -322,10 +323,14 @@ func _cache_spawn_surface(entry: GatherableDataType) -> void:
if not entry.diggable_area_id.is_empty():
triangles = _world.get_diggable_area_triangles(entry.diggable_area_id)
else:
var height_range := _resolved_surface_height_range(entry)
triangles = _world.get_spawn_surface_triangles(
entry.surface_materials,
entry.minimum_surface_y,
height_range.x,
0.6,
height_range.y,
)
_surface_height_ranges[entry.type_id] = height_range
var areas := PackedFloat32Array()
var total_area: float = 0.0
for triangle: PackedVector3Array in triangles:
@ -519,9 +524,18 @@ func _sample_surface_position(
if triangles.is_empty() or total_area <= 0.0:
return Vector3(INF, INF, INF)
var validates_diggable_surface := not entry.diggable_area_id.is_empty()
var height_range: Vector2 = _surface_height_ranges.get(
entry.type_id,
Vector2(entry.minimum_surface_y, entry.maximum_surface_y),
)
var validates_height_range := _surface_height_ranges.has(entry.type_id)
var attempts: int = (
48
if validates_diggable_surface or is_finite(maximum_distance)
if (
validates_diggable_surface
or validates_height_range
or is_finite(maximum_distance)
)
else 1
)
var fallback: Vector3 = Vector3(INF, INF, INF)
@ -551,9 +565,20 @@ func _sample_surface_position(
point,
)
)
if within_requested_distance and valid_diggable_surface:
var valid_height := (
not validates_height_range
or (
point.y > height_range.x
and point.y < height_range.y
)
)
if (
within_requested_distance
and valid_diggable_surface
and valid_height
):
return point
if validates_diggable_surface:
if validates_diggable_surface or validates_height_range:
return Vector3(INF, INF, INF)
if origin.is_finite() and is_finite(maximum_distance):
return origin
@ -1405,8 +1430,12 @@ func _reconcile_seasonal_population() -> void:
func _target_population(entry: GatherableDataType) -> int:
if entry == null or entry.spawn_anchor_set_id.is_empty():
return entry.population if entry != null else 0
if entry == null:
return 0
if entry.spawn_anchor_set_id.is_empty():
return entry.target_population_for_surface_area(
float(_surface_total_areas.get(entry.type_id, 0.0))
)
var anchors: PackedVector3Array = _spawn_anchor_positions.get(
entry.type_id,
PackedVector3Array(),
@ -1414,6 +1443,25 @@ func _target_population(entry: GatherableDataType) -> int:
return entry.target_population_for_anchor_count(anchors.size())
func _resolved_surface_height_range(entry: GatherableDataType) -> Vector2:
var minimum_y := entry.minimum_surface_y
var maximum_y := entry.maximum_surface_y
var saltwater_height := _world.get_saltwater_surface_height()
if is_finite(saltwater_height):
match entry.surface_water_relation:
GatherableDataType.SurfaceWaterRelation.ABOVE_SALT_WATER:
minimum_y = maxf(
minimum_y,
saltwater_height + entry.waterline_margin,
)
GatherableDataType.SurfaceWaterRelation.BELOW_SALT_WATER:
maximum_y = minf(
maximum_y,
saltwater_height - entry.waterline_margin,
)
return Vector2(minimum_y, maximum_y)
func _population_for_type(type_id: StringName) -> int:
var count: int = 0
for state: Dictionary in _entities.values():
@ -1445,6 +1493,7 @@ func _clear_world() -> void:
_surface_triangles.clear()
_surface_areas.clear()
_surface_total_areas.clear()
_surface_height_ranges.clear()
_spawn_anchor_positions.clear()
_respawns.clear()
_next_respawn_by_type.clear()