Randoloot/scripts/planets/mining_network.gd
2026-10-19 22:58:37 +02:00

93 lines
4.1 KiB
GDScript

extends RefCounted
## The network belongs to expedition progress, so it survives visits and system travel.
const BUILD_COST := 200
const DEPOSIT_CHANCE := 0.60
const CREW_CHANCE := 0.40
const CABINS := ["cabin_1", "cabin_2", "cabin_3", "cabin_4", "cabin_5"]
const FIRST_NAMES := ["Ada", "Mira", "Jan", "Leon", "Iga", "Oskar", "Nina", "Tomasz", "Sara", "Emil"]
const LAST_NAMES := ["Nowak", "Voss", "Kowalski", "Orion", "Lis", "Ward", "Keller", "Wilk", "Stern", "Vale"]
static func planet_roll(profile: Dictionary, salt: int) -> RandomNumberGenerator:
var rng := RandomNumberGenerator.new()
rng.seed = int(profile.get("seed", 0)) ^ str(profile.get("id", "planet")).hash() ^ salt
return rng
static func has_deep_deposit(profile: Dictionary) -> bool:
return planet_roll(profile, 0x44454550).randf() < DEPOSIT_CHANCE
static func has_recruit(profile: Dictionary) -> bool:
return planet_roll(profile, 0x43524557).randf() < CREW_CHANCE
static func recruit(profile: Dictionary) -> Dictionary:
var rng := planet_roll(profile, 0x50455253)
var rating := clampi(1 + roundi(clampf(float(profile.get("difficulty", 0)), 0, 1) * 80) + rng.randi_range(0, 19), 1, 100)
return {"id":str(profile.id)+":crew", "name":FIRST_NAMES[rng.randi_range(0,9)]+" "+LAST_NAMES[rng.randi_range(0,9)], "management":rating, "planet_id":str(profile.id), "planet_name":str(profile.name), "cabin":""}
static func free_cabin(progress: Resource) -> String:
for cabin in CABINS:
if progress.freighter_rooms.get(cabin, "") != "crew_cabin": continue
if cabin_crew(progress, cabin).is_empty(): return cabin
return ""
static func cabin_crew(progress: Resource, cabin: String) -> Dictionary:
for member in progress.crew.values():
if str(member.cabin) == cabin: return member
return {}
static func hire(progress: Resource, profile: Dictionary) -> bool:
var candidate := recruit(profile)
var cabin := free_cabin(progress)
if not has_recruit(profile) or progress.recruited_planets.has(str(profile.id)) or cabin.is_empty(): return false
candidate.cabin = cabin
progress.crew[candidate.id] = candidate
progress.recruited_planets[str(profile.id)] = true
progress.emit_changed()
return true
static func dismiss(progress: Resource, member_id: String) -> bool:
if not progress.crew.has(member_id): return false
for station in progress.mining_stations.values():
if str(station.get("crew_id", "")) == member_id: station.crew_id = ""
progress.crew.erase(member_id)
progress.emit_changed()
return true
static func build(progress: Resource, captain: Resource, profile: Dictionary, system: int) -> bool:
var id := str(profile.id)
if not has_deep_deposit(profile) or progress.mining_stations.has(id) or captain.parts < BUILD_COST: return false
captain.parts -= BUILD_COST
progress.mining_stations[id] = {"id":id, "planet_name":str(profile.name), "system":system, "crew_id":"", "produced":0.0}
captain.emit_changed()
progress.emit_changed()
return true
static func assign(progress: Resource, station_id: String, member_id: String) -> bool:
if not progress.mining_stations.has(station_id): return false
if not member_id.is_empty() and not progress.crew.has(member_id): return false
if not member_id.is_empty():
for station in progress.mining_stations.values():
if str(station.get("crew_id", "")) == member_id: station.crew_id = ""
progress.mining_stations[station_id].crew_id = member_id
progress.emit_changed()
return true
static func station_rate(progress: Resource, station: Dictionary) -> float:
var id := str(station.get("crew_id", ""))
if not progress.crew.has(id): return 0.0
return 1.0 + clampi(int(progress.crew[id].management), 1, 100)
static func total_rate(progress: Resource) -> float:
var total := 0.0
for station in progress.mining_stations.values(): total += station_rate(progress, station)
return total
static func advance(progress: Resource, seconds: float) -> float:
if seconds <= 0: return 0
var gained := 0.0
for station in progress.mining_stations.values():
var amount := station_rate(progress, station) * seconds / 60.0
station.produced = float(station.get("produced", 0)) + amount
gained += amount
progress.deuter += gained
return gained