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