Randoloot/scripts/levels/exploration_generator.gd
2026-10-11 21:19:40 +02:00

55 lines
2.1 KiB
GDScript

extends RefCounted
const POI := preload("res://scripts/levels/exploration_poi.gd")
static func spawn(game: Node2D, data: Dictionary, player: CharacterBody2D) -> void:
var rng := RandomNumberGenerator.new()
rng.seed = GameState.system_seed ^ 0x504f49
var occupied: Array[Vector2] = []
var wreck_count := rng.randi_range(2, 4)
for index in wreck_count + rng.randi_range(6, 10):
var kind := "wreck" if index < wreck_count else "asteroid"
var candidate := Vector2.ZERO
var found := false
for attempt in 200:
candidate = Vector2(rng.randf_range(-2300, 2300), rng.randf_range(-1500, 1500))
if candidate.length() < 650 or candidate.distance_to(player.position) < 450:
continue
var clear := true
for planet in data["planets"]:
if candidate.distance_to(planet["position"]) < float(planet["radius"]) + 220:
clear = false
for point in occupied:
if candidate.distance_to(point) < 180:
clear = false
if clear:
found = true
break
if found:
occupied.append(candidate)
_add(game, player, kind, candidate, index, rng.randi())
# Rare per system, at most one ruin on an uninhabited planet.
if rng.randf() < 0.08:
var candidates: Array[int] = []
for index in data["planets"].size():
if not data["planets"][index]["protected"]:
candidates.append(index)
if not candidates.is_empty():
var index := candidates[rng.randi_range(0, candidates.size() - 1)]
var planet := game.get_node("CelestialBodies/Planet%d" % (index + 1))
_add(game, player, "ruin", planet.position, 100, rng.randi(), float(planet.get("radius")) + 100.0)
static func _add(game: Node2D, player: CharacterBody2D, kind: String, position: Vector2, index: int, reward_seed: int, approach_radius: float = 115.0) -> void:
var id := "%d:%d" % [GameState.system_seed, index]
if GameState.explored_pois.has(id):
return
var poi := StaticBody2D.new()
poi.set_script(POI)
poi.set("kind", kind)
poi.set("poi_id", id)
poi.set("reward_seed", reward_seed)
poi.set("player", player)
poi.set("approach_radius", approach_radius)
poi.position = position
game.add_child(poi)