47 lines
2.3 KiB
GDScript
47 lines
2.3 KiB
GDScript
extends RefCounted
|
|
## Rare visual landmarks use a random stream independent of expedition rewards.
|
|
const SPECS := [
|
|
{"kind":"fissure", "chance":0.55, "count":3, "min_size":90.0, "max_size":155.0},
|
|
{"kind":"meteor_crater", "chance":0.14, "count":1, "min_size":160.0, "max_size":220.0},
|
|
{"kind":"abandoned_hamlet", "chance":0.06, "count":1, "min_size":155.0, "max_size":185.0},
|
|
{"kind":"weathered_stones", "chance":0.12, "count":1, "min_size":70.0, "max_size":100.0},
|
|
{"kind":"dry_hollow", "chance":0.30, "count":1, "min_size":95.0, "max_size":140.0}
|
|
]
|
|
|
|
static func generate(data: Dictionary) -> void:
|
|
var rng := RandomNumberGenerator.new()
|
|
rng.seed = int(data.seed) ^ 0x4c414e44
|
|
data.landmarks = []
|
|
for spec in SPECS:
|
|
var chance := float(spec.chance)
|
|
if spec.kind == "dry_hollow" and int(data.landscape.index) < 3:
|
|
chance *= 0.4
|
|
if rng.randf() >= chance:
|
|
continue
|
|
for index in rng.randi_range(1, int(spec.count)):
|
|
var width := rng.randf_range(float(spec.min_size), float(spec.max_size))
|
|
var position := _find_site(data, rng, width*0.55)
|
|
if position == Vector2.INF:
|
|
continue
|
|
data.landmarks.append({"kind":spec.kind, "position":position, "size":width, "rotation":rng.randf_range(-PI, PI)})
|
|
# A crater rim and ruined roofs should remain visible through the vegetation.
|
|
for landmark in data.landmarks:
|
|
data.trees = data.trees.filter(func(prop): return prop.position.distance_to(landmark.position) > float(landmark.size)*0.48+float(prop.size)*0.4)
|
|
data.rocks = data.rocks.filter(func(prop): return prop.position.distance_to(landmark.position) > float(landmark.size)*0.5+float(prop.size)*0.5)
|
|
|
|
static func _find_site(data: Dictionary, rng: RandomNumberGenerator, radius: float) -> Vector2:
|
|
for attempt in 120:
|
|
var point := Vector2(rng.randf_range(-1650, 1650), rng.randf_range(-1650, 1650))
|
|
if not preload("res://scripts/planets/surface_details.gd")._clear_site(data, point, radius):
|
|
continue
|
|
# Check interior cells as well as the perimeter so small ponds stay clear.
|
|
var good := true
|
|
for y in range(-ceili(radius), ceili(radius)+1, 30):
|
|
for x in range(-ceili(radius), ceili(radius)+1, 30):
|
|
var h := preload("res://scripts/planets/surface_details.gd")._height(data, point+Vector2(x,y))
|
|
if h < 0.33 or h > 0.66:
|
|
good = false
|
|
if good:
|
|
return point
|
|
return Vector2.INF
|