extends RefCounted ## Shared planet reward rules. Ammo and consumables never use material scaling. const ITEMS := preload("res://scripts/items/item_generator.gd") const MATERIAL_KEYS := ["parts","iron","titanium","aluminium","uranium","sulfur","silicon","copper","nickel","tungsten","mercury"] static func difficulty(profile: Dictionary) -> float: return clampf(float(profile.get("difficulty",0.0)),0.0,1.0) static func material_multiplier(profile: Dictionary) -> float: return 1.0+2.0*difficulty(profile) static func module_bonus_range(profile: Dictionary) -> Vector2i: var d := difficulty(profile) return Vector2i(roundi(2.0*d),roundi(2.0+8.0*d)) static func roll_module_bonus(rng: RandomNumberGenerator, profile: Dictionary) -> int: var bounds := module_bonus_range(profile) var count := bounds.y-bounds.x+1 var total := 0.0 for index in count: total += pow(0.65,index) var roll := rng.randf()*total for index in count: roll -= pow(0.65,index) if roll < 0.0: return bounds.x+index return bounds.y static func generate_module(rng: RandomNumberGenerator, profile: Dictionary, level: int, definition: ItemDefinition = null, tier := 0, exact_bonus := -1) -> ItemInstance: if definition == null: var definitions: Array = ITEMS.DEFINITIONS.filter(func(d): return d.category in [ItemDefinition.Category.SHIELD,ItemDefinition.Category.ARMOR,ItemDefinition.Category.ENGINE,ItemDefinition.Category.REACTOR,ItemDefinition.Category.COMPUTER]) definition = definitions[rng.randi_range(0,definitions.size()-1)] var bonus := exact_bonus if exact_bonus >= 0 else roll_module_bonus(rng,profile) # Events use biome bonuses; ancient structures explicitly set +1/+2/+3. return ITEMS.generate_for_definition(definition,clampi(level+bonus,1,1000),tier) static func scale_materials(reward: Dictionary, profile: Dictionary) -> Dictionary: var scaled := reward.duplicate() for key in scaled: if key in MATERIAL_KEYS: scaled[key] = maxi(1,roundi(int(scaled[key])*material_multiplier(profile))) if int(scaled[key]) > 0 else 0 return scaled static func missile_price_ratio(profile: Dictionary) -> float: return lerpf(0.70,0.50,difficulty(profile)) static func missile_barter_cost(profile: Dictionary) -> int: return maxi(1,roundi(6.0*lerpf(1.0,0.65,difficulty(profile))))