131 lines
6.1 KiB
GDScript
131 lines
6.1 KiB
GDScript
extends RefCounted
|
|
## The network belongs to expedition progress, so it survives visits and system travel.
|
|
const PARTS_PER_RICHNESS := 10
|
|
const CREDITS_PER_MANAGEMENT := 1000
|
|
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
|
|
|
|
# Strict level bands prevent early systems from rolling endgame deposits.
|
|
static func richness_bounds(system: int) -> Vector2i:
|
|
var levels := [1, 20, 40, 60, 80, 100, 120]
|
|
var lows := [1, 8, 20, 35, 50, 65, 80]
|
|
var highs := [10, 25, 40, 55, 70, 85, 100]
|
|
var level := clampi(system, 1, 120)
|
|
for index in range(1, levels.size()):
|
|
if level <= int(levels[index]):
|
|
var weight := float(level - int(levels[index-1])) / float(int(levels[index]) - int(levels[index-1]))
|
|
return Vector2i(roundi(lerpf(lows[index-1], lows[index], weight)), roundi(lerpf(highs[index-1], highs[index], weight)))
|
|
return Vector2i(80, 100)
|
|
|
|
static func deposit_richness(profile: Dictionary, system: int) -> int:
|
|
var bounds := richness_bounds(system)
|
|
return planet_roll(profile, 0x52494348).randi_range(bounds.x, bounds.y)
|
|
|
|
static func build_cost(profile: Dictionary, system: int) -> int:
|
|
return deposit_richness(profile, system) * PARTS_PER_RICHNESS
|
|
|
|
static func recruitment_cost(candidate: Dictionary) -> int:
|
|
return clampi(int(candidate.get("management", 1)), 1, 100) * CREDITS_PER_MANAGEMENT
|
|
|
|
static func station_richness(station: Dictionary) -> int:
|
|
if not station.has("richness"):
|
|
# Upgrade existing stations using their original planet identity and system.
|
|
var identity := str(station.id).split(":")
|
|
var profile := {"id":str(station.id), "seed":int(station.get("planet_seed", 0))}
|
|
if identity.size() == 3 and identity[1] == "planet":
|
|
profile = preload("res://scripts/planets/planet_profiles.gd").generate(int(identity[0]), int(identity[2]), str(station.planet_name),int(station.get("system",1)))
|
|
station.richness = deposit_richness(profile, int(station.get("system", 1)))
|
|
return clampi(int(station.richness), 1, 100)
|
|
|
|
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 level := clampi(int(profile.get("system_level",1)),1,100)
|
|
var rating := rng.randi_range(maxi(1,level-5),mini(100,level+5))
|
|
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, captain: Resource, profile: Dictionary) -> bool:
|
|
var candidate := recruit(profile)
|
|
var cabin := free_cabin(progress)
|
|
var cost := recruitment_cost(candidate)
|
|
if not has_recruit(profile) or progress.recruited_planets.has(str(profile.id)) or cabin.is_empty() or captain.credits < cost: return false
|
|
captain.credits -= cost
|
|
candidate.cabin = cabin
|
|
progress.crew[candidate.id] = candidate
|
|
progress.recruited_planets[str(profile.id)] = true
|
|
captain.emit_changed()
|
|
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)
|
|
var cost := build_cost(profile, system)
|
|
if not has_deep_deposit(profile) or progress.mining_stations.has(id) or captain.parts < cost: return false
|
|
captain.parts -= cost
|
|
progress.mining_stations[id] = {"id":id, "planet_name":str(profile.name), "system":system, "planet_seed":int(profile.get("seed", 0)), "richness":deposit_richness(profile, 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 station_richness(station) * (1.0 + clampi(int(progress.crew[id].management), 1, 100) / 100.0)
|
|
|
|
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
|