diff --git a/playerSettings.yaml b/playerSettings.yaml index 2ae233e55d17..7e16c057ef69 100644 --- a/playerSettings.yaml +++ b/playerSettings.yaml @@ -154,15 +154,32 @@ Factorio: cliff_settings: name: cliff cliff_elevation_0: 10 # base elevation, can't be changed in GUI - cliff_elevation_interval: 40 # = 40/frequency - richness: 1 # 0=off, >0 = continuity + cliff_elevation_interval: 40 # 40/frequency + richness: 1 # 0: off, >0: continuity + property_expression_names: + "control-setting:moisture:bias": 0 # grass bias -0.5 to +0.5 + "control-setting:moisture:frequency:multiplier": 1 # 1/scale in GUI + "control-setting:aux:bias": 0 # -sand/+red desert bias -0.5 to +0.5 + "control-setting:aux:frequency:multiplier": 1 # 1/scale in GUI pollution: enabled: true diffusion_ratio: 0.02 - ageing: 1 + ageing: 1 # GUI dissipation factor enemy_attack_pollution_consumption_modifier: 1 min_pollution_to_damage_trees: 60 pollution_restored_per_tree_damage: 10 + enemy_evolution: + enabled: true + time_factor: 40.0e-7 # GUI value * 0.0000001 + destroy_factor: 200.0e-5 # GUI value * 0.00001 + pollution_factor: 9.0e-7 # GUI value * 0.0000001 + enemy_expansion: + enabled: true + max_expansion_distance: 7 + settler_group_min_size: 5 + settler_group_max_size: 20 + min_expansion_cooldown: 14400 # 1 to 60 min in ticks + max_expansion_cooldown: 216000 # 5 to 180 min in ticks Minecraft: advancement_goal: 50 # Number of advancements required (out of 92 total) to spawn the Ender Dragon and complete the game. combat_difficulty: # Modifies the level of items logically required for exploring dangerous areas and fighting bosses. diff --git a/worlds/factorio/Options.py b/worlds/factorio/Options.py index cb2563d6fb36..3214727a729d 100644 --- a/worlds/factorio/Options.py +++ b/worlds/factorio/Options.py @@ -109,25 +109,57 @@ class FactorioStartItems(OptionDict): class FactorioWorldGen(OptionDict): # FIXME: do we want default be a rando-optimized default or in-game DS? value: typing.Dict[str, typing.Dict[str, typing.Any]] - default = {"terrain_segmentation": 0.5, - "water": 1.5, - "autoplace_controls": {"coal": {"frequency": 1, "size": 3, "richness": 6}, - "copper-ore": {"frequency": 1, "size": 3, "richness": 6}, - "crude-oil": {"frequency": 1, "size": 3, "richness": 6}, - "enemy-base": {"frequency": 1, "size": 1, "richness": 1}, - "iron-ore": {"frequency": 1, "size": 3, "richness": 6}, - "stone": {"frequency": 1, "size": 3, "richness": 6}, - "trees": {"frequency": 1, "size": 1, "richness": 1}, - "uranium-ore": {"frequency": 1, "size": 3, "richness": 6}}, - "seed": None, - "starting_area": 1, - "peaceful_mode": False, - "cliff_settings": {"name": "cliff", "cliff_elevation_0": 10, "cliff_elevation_interval": 40, - "richness": 1}, - "pollution": {"enabled": True, "diffusion_ratio": 0.02, "ageing": 1, - "enemy_attack_pollution_consumption_modifier": 1, - "min_pollution_to_damage_trees": 60, - "pollution_restored_per_tree_damage": 10}} + default = { + "terrain_segmentation": 0.5, + "water": 1.5, + "autoplace_controls": { + "coal": {"frequency": 1, "size": 3, "richness": 6}, + "copper-ore": {"frequency": 1, "size": 3, "richness": 6}, + "crude-oil": {"frequency": 1, "size": 3, "richness": 6}, + "enemy-base": {"frequency": 1, "size": 1, "richness": 1}, + "iron-ore": {"frequency": 1, "size": 3, "richness": 6}, + "stone": {"frequency": 1, "size": 3, "richness": 6}, + "trees": {"frequency": 1, "size": 1, "richness": 1}, + "uranium-ore": {"frequency": 1, "size": 3, "richness": 6} + }, + "seed": None, + "starting_area": 1, + "peaceful_mode": False, + "cliff_settings": { + "name": "cliff", + "cliff_elevation_0": 10, + "cliff_elevation_interval": 40, + "richness": 1 + }, + "property_expression_names": { + "control-setting:moisture:bias": 0, + "control-setting:moisture:frequency:multiplier": 1, + "control-setting:aux:bias": 0, + "control-setting:aux:frequency:multiplier": 1 + }, + "pollution": { + "enabled": True, + "diffusion_ratio": 0.02, + "ageing": 1, + "enemy_attack_pollution_consumption_modifier": 1, + "min_pollution_to_damage_trees": 60, + "pollution_restored_per_tree_damage": 10 + }, + "enemy_evolution": { + "enabled": True, + "time_factor": 40.0e-7, + "destroy_factor": 200.0e-5, + "pollution_factor": 9.0e-7 + }, + "enemy_expansion": { + "enabled": True, + "max_expansion_distance": 7, + "settler_group_min_size": 5, + "settler_group_max_size": 20, + "min_expansion_cooldown": 14400, + "max_expansion_cooldown": 216000 + } + } schema = Schema({ "basic": { Optional("terrain_segmentation"): FloatRange(0.166, 6), @@ -136,14 +168,23 @@ class FactorioWorldGen(OptionDict): str: { "frequency": FloatRange(0, 6), "size": FloatRange(0, 6), - "richness": FloatRange(0.166, 6)}}, + "richness": FloatRange(0.166, 6) + } + }, Optional("seed"): Or(None, And(int, lambda n: n >= 0)), Optional("starting_area"): FloatRange(0.166, 6), Optional("peaceful_mode"): LuaBool, Optional("cliff_settings"): { "name": str, "cliff_elevation_0": FloatRange(0, 99), "cliff_elevation_interval": FloatRange(0.066, 241), # 40/frequency - "richness": FloatRange(0, 6)}, + "richness": FloatRange(0, 6) + }, + Optional("property_expression_names"): Schema({ + "control-setting:moisture:bias": FloatRange(-0.5, 0.5), + "control-setting:moisture:frequency:multiplier": FloatRange(0.166, 6), + "control-setting:aux:bias": FloatRange(-0.5, 0.5), + "control-setting:aux:frequency:multiplier": FloatRange(0.166, 6) + }, ignore_extra_keys=True) }, "advanced": { Optional("pollution"): { @@ -152,17 +193,43 @@ class FactorioWorldGen(OptionDict): Optional("ageing"): FloatRange(0.1, 4), Optional("enemy_attack_pollution_consumption_modifier"): FloatRange(0.1, 4), Optional("min_pollution_to_damage_trees"): FloatRange(0, 9999), - Optional("pollution_restored_per_tree_damage"): FloatRange(0, 9999)} + Optional("pollution_restored_per_tree_damage"): FloatRange(0, 9999) + }, + Optional("enemy_evolution"): { + Optional("enabled"): LuaBool, + Optional("time_factor"): FloatRange(0, 1000e-7), + Optional("destroy_factor"): FloatRange(0, 1000e-5), + Optional("pollution_factor"): FloatRange(0, 1000e-7), + }, + Optional("enemy_expansion"): { + Optional("enabled"): LuaBool, + Optional("max_expansion_distance"): FloatRange(2, 20), + Optional("settler_group_min_size"): FloatRange(1, 20), + Optional("settler_group_max_size"): FloatRange(1, 50), + Optional("min_expansion_cooldown"): FloatRange(3600, 216000), + Optional("max_expansion_cooldown"): FloatRange(18000, 648000) + } } }) def __init__(self, value: typing.Dict[str, typing.Any]): - advanced = {"pollution"} + advanced = {"pollution", "enemy_evolution", "enemy_expansion"} self.value = { "basic": {key: value[key] for key in value.keys() - advanced}, "advanced": {key: value[key] for key in value.keys() & advanced} } + # verify min_values <= max_values + def optional_min_lte_max(container, min_key, max_key): + min_val = container.get(min_key, None) + max_val = container.get(max_key, None) + if min_val is not None and max_val is not None and min_val > max_val: + raise ValueError(f"{min_key} can't be bigger than {max_key}") + + enemy_expansion = self.value["advanced"].get("enemy_expansion", {}) + optional_min_lte_max(enemy_expansion, "settler_group_min_size", "settler_group_max_size") + optional_min_lte_max(enemy_expansion, "min_expansion_cooldown", "max_expansion_cooldown") + @classmethod def from_any(cls, data: typing.Dict[str, typing.Any]) -> FactorioWorldGen: if type(data) == dict: