Randoloot/scripts/planets/surface_scenery.gd
2026-10-18 08:43:54 +02:00

60 lines
2.7 KiB
GDScript

extends RefCounted
const BUILDING_SCALE := 0.65
const KINDS := ["ruined_house","warehouse","radar","airstrip","fuel_depot","solar_farm","scrapyard"]
const WIDTHS := {"ruined_house":135.0,"warehouse":180.0,"radar":130.0,"airstrip":290.0,"fuel_depot":150.0,"solar_farm":180.0,"scrapyard":160.0,"engineer_camp":130.0}
static func generate(data: Dictionary, rng: RandomNumberGenerator) -> void:
data.structures = []
data.events = []
for index in rng.randi_range(2,5):
var kind: String = KINDS[rng.randi_range(0,KINDS.size()-1)]
var width: float = WIDTHS[kind]*BUILDING_SCALE*rng.randf_range(0.85,1.15)
var position := find_site(data,rng,width*0.55)
if position == Vector2.INF:
continue
data.structures.append({"kind":kind,"position":position,"size":width,"rotation":rng.randf_range(-PI,PI)})
var event_rng := RandomNumberGenerator.new()
event_rng.seed = int(data.seed) ^ 0x45564e54
if event_rng.randf() < 0.5:
var position := find_site(data,event_rng,60)
if position != Vector2.INF:
var kinds: Array = preload("res://scripts/planets/surface_events.gd").KINDS
data.events.append({"kind":kinds[event_rng.randi_range(0,kinds.size()-1)],"position":position,"seed":event_rng.randi(),"complete":false,"discovered":false})
var clearings: Array = data.structures.duplicate()
for clearing in clearings:
data.trees = data.trees.filter(func(prop): return prop.position.distance_to(clearing.position) > float(clearing.size)*0.6+float(prop.size)*0.3)
data.rocks = data.rocks.filter(func(prop): return prop.position.distance_to(clearing.position) > float(clearing.size)*0.6+float(prop.size)*0.3)
static func find_site(data: Dictionary, rng: RandomNumberGenerator, radius: float) -> Vector2:
for attempt in 300:
var point := Vector2(rng.randf_range(-1600,1600),rng.randf_range(-1600,1600))
if point.length() < radius+250:
continue
var good := true
var minimum := 1.0
var maximum := 0.0
for offset in [Vector2.ZERO,Vector2.LEFT,Vector2.RIGHT,Vector2.UP,Vector2.DOWN,Vector2(-0.7,-0.7),Vector2(0.7,0.7),Vector2(-0.7,0.7),Vector2(0.7,-0.7)]:
var at: Vector2 = point+offset*radius
var x := clampi(int((at.x+1920)/40),0,95)
var y := clampi(int((at.y+1920)/40),0,95)
var h: float = data.heights[y*96+x]
minimum = minf(minimum,h)
maximum = maxf(maximum,h)
if minimum < 0.32 or maximum > 0.76 or maximum-minimum > 0.16:
continue
for mountain in data.mountains:
if point.distance_to(mountain.position) < radius+float(mountain.size)*0.7:
good = false
break
for poi in data.pois:
if point.distance_to(poi.position) < radius+150:
good = false
break
for structure in data.structures:
if point.distance_to(structure.position) < radius+float(structure.size)*0.65+60:
good = false
break
if good:
return point
return Vector2.INF