extends RefCounted const NAMES := {"deposit":"Złoże surowców","ruins":"Starożytna struktura","warehouse":"Opuszczony magazyn","village":"Opuszczona wioska","cave":"Jaskinia","deep_deposit":"Głębokie złoże deuteru","crew":"Obóz specjalisty","hermit":"Pustelnik / Kartograf","time_engineer":"Inżynier chronalny"} const KINDS := ["deposit","ruins","warehouse","village","cave"] const WEIGHTS := {"deposit":[0.1,0.7,0.2],"ruins":[0.2,0.5,0.3],"warehouse":[0.1,0.25,0.65],"village":[0.15,0.2,0.65],"cave":[0.7,0.2,0.1]} const PROFILES := preload("res://scripts/planets/planet_profiles.gd") const REWARDS := preload("res://scripts/planets/planet_rewards.gd") static func report(kind: String, profile: Dictionary, captain: Resource) -> Dictionary: return PROFILES.poi_loot_report(profile,captain,WEIGHTS.get(kind,[1.0,1.0,1.0])) static func richness(profile: Dictionary) -> float: return REWARDS.material_multiplier(profile)*(1.0+0.02*(PROFILES.level(profile)-1)) static func reward(kind: String, rng: RandomNumberGenerator, profile: Dictionary, captain: Resource, risky: bool = false) -> Dictionary: var result := {} var multiplier: float = report(kind,profile,captain).multiplier*(0.35 if risky else 1.0) var supplies := 1.0+0.5*REWARDS.difficulty(profile)+0.005*(PROFILES.level(profile)-1) match kind: "deposit": var key: String = PROFILES.MATERIALS[rng.randi_range(0,PROFILES.MATERIALS.size()-1)] result[key] = rng.randi_range(18,28)*richness(profile) "warehouse": result.ammunition = rng.randi_range(130,210)*supplies result.missile = rng.randi_range(2,4)*supplies if rng.randf() < 0.25: result.irradiated_ammunition = rng.randi_range(20,35)*supplies var keys := ["iron","titanium","aluminium","uranium","sulfur"] result[keys[rng.randi_range(0,4)]] = rng.randi_range(8,16)*richness(profile) "village": result.credits = rng.randi_range(140,220)*richness(profile) var xp: int = captain.encounter_xp(6.0*pow(PROFILES.level(profile),0.75),PROFILES.level(profile)) if xp > 0: result.experience = xp "cave": result.samples = rng.randi_range(3,5)*sqrt(richness(profile)) for key in result: result[key] = maxi(1,roundi(float(result[key])*multiplier)) return result static func module_count(profile: Dictionary, captain: Resource, risky: bool = false) -> int: if risky: return 1 return clampi(roundi((1.0+REWARDS.difficulty(profile))*float(report("ruins",profile,captain).multiplier)),1,3) static func module_bonus(rng: RandomNumberGenerator, profile: Dictionary, captain: Resource, risky: bool = false) -> int: var equipment := roundi((float(report("ruins",profile,captain).gear_multiplier)-1.0)*10) return REWARDS.roll_module_bonus(rng,profile)+equipment+(2 if risky else 0) static func has_bonus(poi: Dictionary, profile: Dictionary) -> bool: if str(poi.get("kind","")) not in KINDS: return false if poi.has("bonus_available"): return bool(poi.bonus_available) var rng := rng_for(int(profile.get("seed",1)),poi,24) return rng.randf() < 0.25 static func rng_for(visit_seed: int, poi: Dictionary, salt: int = 0) -> RandomNumberGenerator: var rng := RandomNumberGenerator.new() rng.seed = visit_seed ^ (int(poi.get("id",0))*7919) ^ str(poi.get("kind","")).hash() ^ ((salt+1)*104729) return rng static func damage_range(kind: String, profile: Dictionary, captain: Resource, risky: bool = false) -> Vector2i: var equipment := report(kind,profile,captain) var base := 13.0+5.0*REWARDS.difficulty(profile)+20.0*float(equipment.deficit)-3.0*float(equipment.surplus) if risky else 3.0+3.0*REWARDS.difficulty(profile)+16.0*float(equipment.deficit)-1.5*float(equipment.surplus) var spread := 5 if risky else 1 return Vector2i(maxi(1,floori(base)-spread),maxi(1,ceili(base)+spread)) static func preview(profile: Dictionary, captain: Resource, poi: Dictionary, visit_seed: int, risky: bool = false) -> Dictionary: var kind := str(poi.get("kind","")) if kind not in KINDS: return {} var bounds := REWARDS.module_bonus_range(profile) var equipment := roundi((float(report("ruins",profile,captain).gear_multiplier)-1.0)*10)+(2 if risky else 0) return {"materials":reward(kind,rng_for(visit_seed,poi,10 if risky else 0),profile,captain,risky),"modules":module_count(profile,captain,risky) if kind == "ruins" else 0,"module_levels":Vector2i(clampi(PROFILES.level(profile)+bounds.x+equipment,1,1000),clampi(PROFILES.level(profile)+bounds.y+equipment,1,1000)),"damage":damage_range(kind,profile,captain,risky),"bonus":risky}