85 lines
4.1 KiB
GDScript
85 lines
4.1 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
|
|
var position := find_event_site(data,event_rng)
|
|
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})
|
|
data.trees = data.trees.filter(func(prop): return prop.position.distance_to(position) > 90+float(prop.size)*0.3)
|
|
data.mountains = data.mountains.filter(func(prop): return bool(prop.get("cave_anchor",false)) or prop.position.distance_to(position) > 90+float(prop.size)*0.7)
|
|
data.rocks = data.rocks.filter(func(prop): return prop.position.distance_to(position) > 80)
|
|
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
|
|
|
|
static func find_event_site(data: Dictionary, rng: RandomNumberGenerator) -> Vector2:
|
|
var preferred := find_site(data,rng,60)
|
|
if preferred != Vector2.INF: return preferred
|
|
# Lander movement supports every terrain. Guarantee one encounter even on
|
|
# maps without flat ground, away from the landing pad and other locations.
|
|
var chosen := Vector2(1200,1200)
|
|
var best_clearance := -INF
|
|
for y in range(-1600,1601,160):
|
|
for x in range(-1600,1601,160):
|
|
var point := Vector2(x,y)
|
|
if point.length() < 400: continue
|
|
var clearance := point.length()-310
|
|
for poi in data.pois:
|
|
clearance = minf(clearance,point.distance_to(poi.position)-210)
|
|
for mountain in data.mountains:
|
|
if mountain.get("cave_anchor",false):
|
|
clearance = minf(clearance,point.distance_to(mountain.position)-float(mountain.size)*0.7-90)
|
|
for structure in data.structures:
|
|
clearance = minf(clearance,point.distance_to(structure.position)-float(structure.size)*0.65-120)
|
|
if clearance > best_clearance:
|
|
best_clearance = clearance
|
|
chosen = point
|
|
return chosen
|