extends RefCounted const EARTHLIKE_FAMILIES := ["Terrestrial", "Lush", "Tropical"] const MATERIALS := ["silicon", "copper", "nickel", "tungsten", "mercury"] const MATERIAL_NAMES := {"silicon":"Krzem","copper":"Miedź","nickel":"Nikiel","tungsten":"Wolfram","mercury":"Rtęć"} const THREAT_KEYS := ["oxygen","temperature","biology"] const POI_SAFE_CHANCES := [0.90,0.70,0.40] const POI_DANGER_CHANCES := [0.15,0.05,0.0] static func is_earthlike(texture: Texture2D) -> bool: if texture == null: return false for family in EARTHLIKE_FAMILIES: if texture.resource_path.contains("/Solid/%s/" % family): return true return false static func earthlike_textures() -> Array[Texture2D]: var found: Array[Texture2D] = [] for texture in preload("res://scripts/levels/celestial_texture_catalog.gd").PLANET_TEXTURES: if is_earthlike(texture): found.append(texture) return found static func level(profile: Dictionary) -> int: return clampi(int(profile.get("system_level",1)),1,1000) static func generate(system_seed: int, index: int, name: String, system_level: int = 1) -> Dictionary: var rng := RandomNumberGenerator.new() rng.seed = system_seed ^ (index*0x504c414e) ^ 0x42494f4d var progression := 1.0-exp(-float(maxi(1,system_level)-1)/45.0) var difficulty := clampf(progression*rng.randf_range(0.85,1.15),0,1) var oxygen := roundi(95.0-difficulty*rng.randf_range(55,95)) var extreme_temperature := rng.randf_range(65,100) if rng.randf() < 0.5 else rng.randf_range(-50,-20) var temperature := roundi(lerpf(20.0,extreme_temperature,difficulty)) var flora := roundi(difficulty*rng.randf_range(15,50)) return {"id":"%d:planet:%d" % [system_seed,index],"name":name,"system_level":maxi(1,system_level),"oxygen":oxygen,"temperature":temperature,"flora":flora,"easy":difficulty < 0.18,"difficulty":difficulty,"landing_damage":roundi(5+10*difficulty),"seed":rng.randi(),"index":index} static func raw_threats(profile: Dictionary) -> Dictionary: var oxygen := clampf((80.0-float(profile.get("oxygen",95)))/80.0,0,1)*100 var temperature := float(profile.get("temperature",20)) var thermal := 0.0 if temperature < -10: thermal = clampf((-10-temperature)/40,0,1)*100 elif temperature > 40: thermal = clampf((temperature-40)/60,0,1)*100 return {"oxygen":oxygen,"temperature":thermal,"biology":clampf(float(profile.get("flora",0))/50.0,0,1)*100} static func equipment_report(profile: Dictionary, captain: Resource, weights: Array = [1.0,1.0,1.0]) -> Dictionary: var gear := preload("res://scripts/planets/captain_equipment.gd") var raw := raw_threats(profile) var deficit := 0.0 var surplus := 0.0 var weight_total := 0.0 var effective := {} var requirements := {} for index in 3: var key: String = THREAT_KEYS[index] var required := maxf(1.0,level(profile)*(0.85+0.45*float(raw[key])/100.0)) var ratio := float(gear.level(captain,gear.KINDS[index]))/required var shortfall := clampf(1.0-ratio,0,1) effective[key] = shortfall*100 requirements[key] = required deficit += shortfall*float(weights[index]) surplus += clampf(ratio-1.0,0,1)*float(weights[index]) weight_total += float(weights[index]) return {"deficit":deficit/weight_total,"surplus":surplus/weight_total,"raw":raw,"effective":effective,"requirements":requirements} static func threat_report(profile: Dictionary, captain: Resource) -> Dictionary: var report := equipment_report(profile,captain) var raw_total := 0.0 var total := 0.0 for key in THREAT_KEYS: raw_total += float(report.raw[key]) total += float(report.effective[key]) return {"raw":report.raw,"effective":report.effective,"raw_total":raw_total,"total":total} static func global_threat(profile: Dictionary, captain: Resource) -> float: return float(threat_report(profile,captain).total) static func poi_loot_report(profile: Dictionary, captain: Resource, weights: Array = [1.0,1.0,1.0]) -> Dictionary: var gear := equipment_report(profile,captain,weights) var recovery := 1.0-0.5*float(gear.deficit) var gear_multiplier := 1.0+0.1*float(gear.surplus) return {"multiplier":recovery*gear_multiplier,"recovery":recovery,"gear_multiplier":gear_multiplier,"threat":float(gear.deficit)*300,"deficit":gear.deficit,"surplus":gear.surplus} static func success_chance(profile: Dictionary, captain: Resource, stage: int) -> float: var index := clampi(stage,0,2) return lerpf(POI_SAFE_CHANCES[index],POI_DANGER_CHANCES[index],clampf(global_threat(profile,captain)/150,0,1)) static func average_success_chance(profile: Dictionary, captain: Resource) -> float: var total := 0.0 for stage in 3: total += success_chance(profile,captain,stage) return total/3 static func biome_name(profile: Dictionary) -> String: if bool(profile.get("easy",false)): return "Łagodna biosfera" if int(profile.get("temperature",20)) < -10: return "Zimna biosfera" if int(profile.get("temperature",20)) > 40: return "Gorąca biosfera" return "Dzika biosfera" static func scan_description(profile: Dictionary, captain: Resource) -> String: return "%s · Poziom %d\nLądowanie: −%d HP\nLądownik: %d / 100 HP\nPOI: podleć i naciśnij E, aby zaplanować eksplorację." % [profile.name,level(profile),profile.landing_damage,ceili(captain.expedition.lander_hp)]