diff --git a/worlds/factorio/Mod.py b/worlds/factorio/Mod.py index 484ed626..ef9893cb 100644 --- a/worlds/factorio/Mod.py +++ b/worlds/factorio/Mod.py @@ -107,6 +107,9 @@ def generate_mod(world, output_directory: str): if getattr(multiworld, "silo")[player].value == Options.Silo.option_randomize_recipe: template_data["free_sample_blacklist"]["rocket-silo"] = 1 + + if getattr(multiworld, "satellite")[player].value == Options.Satellite.option_randomize_recipe: + template_data["free_sample_blacklist"]["satellite"] = 1 control_code = control_template.render(**template_data) data_template_code = data_template.render(**template_data) diff --git a/worlds/factorio/Options.py b/worlds/factorio/Options.py index 0c9e3cd8..a3ef1162 100644 --- a/worlds/factorio/Options.py +++ b/worlds/factorio/Options.py @@ -55,6 +55,14 @@ class Silo(Choice): default = 0 +class Satellite(Choice): + """Ingredients to craft satellite.""" + displayname = "Satellite" + option_vanilla = 0 + option_randomize_recipe = 1 + default = 0 + + class FreeSamples(Choice): """Get free items with your technologies.""" displayname = "Free Samples" @@ -289,6 +297,7 @@ factorio_options: typing.Dict[str, type(Option)] = { "tech_tree_layout": TechTreeLayout, "tech_cost": TechCost, "silo": Silo, + "satellite": Satellite, "free_samples": FreeSamples, "tech_tree_information": TechTreeInformation, "starting_items": FactorioStartItems, diff --git a/worlds/factorio/Technologies.py b/worlds/factorio/Technologies.py index 9e7f88fd..89f50b84 100644 --- a/worlds/factorio/Technologies.py +++ b/worlds/factorio/Technologies.py @@ -300,13 +300,17 @@ for category_name, machine_name in machine_per_category.items(): required_technologies: Dict[str, FrozenSet[Technology]] = Utils.KeyedDefaultDict(lambda ingredient_name: frozenset( recursively_get_unlocking_technologies(ingredient_name, unlock_func=unlock))) -def get_rocket_requirements(silo_recipe: Recipe, part_recipe: Recipe) -> Set[str]: +def get_rocket_requirements(silo_recipe: Recipe, part_recipe: Recipe, satellite_recipe: Recipe) -> Set[str]: techs = set() if silo_recipe: for ingredient in silo_recipe.ingredients: techs |= recursively_get_unlocking_technologies(ingredient) for ingredient in part_recipe.ingredients: techs |= recursively_get_unlocking_technologies(ingredient) + if satellite_recipe: + techs |= satellite_recipe.unlocking_technologies + for ingredient in satellite_recipe.ingredients: + techs |= recursively_get_unlocking_technologies(ingredient) return {tech.name for tech in techs} diff --git a/worlds/factorio/__init__.py b/worlds/factorio/__init__.py index fb40f722..0c957180 100644 --- a/worlds/factorio/__init__.py +++ b/worlds/factorio/__init__.py @@ -10,7 +10,7 @@ from .Technologies import base_tech_table, recipe_sources, base_technology_table get_science_pack_pools, Recipe, recipes, technology_table, tech_table, factorio_base_id, useless_technologies from .Shapes import get_shapes from .Mod import generate_mod -from .Options import factorio_options, Silo, TechTreeInformation +from .Options import factorio_options, MaxSciencePack, Silo, Satellite, TechTreeInformation import logging @@ -142,11 +142,13 @@ class Factorio(World): locations=locations: all(state.can_reach(loc) for loc in locations)) silo_recipe = None if self.world.silo[self.player].value == Silo.option_spawn \ - else self.custom_recipes["rocket-silo"] \ - if "rocket-silo" in self.custom_recipes \ + else self.custom_recipes["rocket-silo"] if "rocket-silo" in self.custom_recipes \ else next(iter(all_product_sources.get("rocket-silo"))) part_recipe = self.custom_recipes["rocket-part"] - victory_tech_names = get_rocket_requirements(silo_recipe, part_recipe) + satellite_recipe = None if self.world.max_science_pack[self.player].value != MaxSciencePack.option_space_science_pack \ + else self.custom_recipes["satellite"] if "satellite" in self.custom_recipes \ + else next(iter(all_product_sources.get("satellite"))) + victory_tech_names = get_rocket_requirements(silo_recipe, part_recipe, satellite_recipe) world.get_location("Rocket Launch", player).access_rule = lambda state: all(state.has(technology, player) for technology in victory_tech_names) @@ -283,18 +285,31 @@ class Factorio(World): new_recipe = Recipe(pack, original.category, new_ingredients, original.products, original.energy) self.custom_recipes[pack] = new_recipe - if self.world.silo[self.player].value == Silo.option_randomize_recipe: + if self.world.silo[self.player].value == Silo.option_randomize_recipe \ + or self.world.satellite[self.player].value == Satellite.option_randomize_recipe: valid_pool = [] for pack in sorted(self.world.max_science_pack[self.player].get_allowed_packs()): valid_pool += sorted(science_pack_pools[pack]) - new_recipe = self.make_balanced_recipe(recipes["rocket-silo"], valid_pool, - factor=(self.world.max_science_pack[self.player].value + 1) / 7) - self.custom_recipes["rocket-silo"] = new_recipe - needed_recipes = self.world.max_science_pack[self.player].get_allowed_packs() | {"rocket-silo", "rocket-part"} + if self.world.silo[self.player].value == Silo.option_randomize_recipe: + new_recipe = self.make_balanced_recipe(recipes["rocket-silo"], valid_pool, + factor=(self.world.max_science_pack[self.player].value + 1) / 7) + self.custom_recipes["rocket-silo"] = new_recipe + + if self.world.satellite[self.player].value == Satellite.option_randomize_recipe: + new_recipe = self.make_balanced_recipe(recipes["satellite"], valid_pool, + factor=(self.world.max_science_pack[self.player].value + 1) / 7) + self.custom_recipes["satellite"] = new_recipe + + needed_recipes = self.world.max_science_pack[self.player].get_allowed_packs() | {"rocket-part"} + if self.world.silo[self.player] != Silo.option_spawn: + needed_recipes |= {"rocket-silo"} + if self.world.max_science_pack[self.player].value == MaxSciencePack.option_space_science_pack: + needed_recipes |= {"satellite"} for recipe in needed_recipes: recipe = self.custom_recipes.get(recipe, recipes[recipe]) + self.advancement_technologies |= {tech.name for tech in recipe.unlocking_technologies} self.advancement_technologies |= {tech.name for tech in recipe.recursive_unlocking_technologies} # handle marking progressive techs as advancement diff --git a/worlds/factorio/data/mod_template/control.lua b/worlds/factorio/data/mod_template/control.lua index 8c049e14..cf9fc1da 100644 --- a/worlds/factorio/data/mod_template/control.lua +++ b/worlds/factorio/data/mod_template/control.lua @@ -8,6 +8,7 @@ SLOT_NAME = "{{ slot_name }}" SEED_NAME = "{{ seed_name }}" FREE_SAMPLE_BLACKLIST = {{ dict_to_lua(free_sample_blacklist) }} TRAP_EVO_FACTOR = {{ evolution_trap_increase }} / 100 +MAX_SCIENCE_PACK = {{ max_science_pack }} DEATH_LINK = {{ death_link | int }} CURRENTLY_DEATH_LOCK = 0 @@ -107,8 +108,19 @@ end script.on_event(defines.events.on_player_removed, on_player_removed) function on_rocket_launched(event) - global.forcedata[event.rocket.force.name]['victory'] = 1 - dumpInfo(event.rocket.force) + if event.rocket and event.rocket.valid and global.forcedata[event.rocket.force.name]['victory'] == 0 then + if event.rocket.get_item_count("satellite") > 0 or MAX_SCIENCE_PACK < 6 then + global.forcedata[event.rocket.force.name]['victory'] = 1 + dumpInfo(event.rocket.force) + game.set_game_state + { + game_finished = true, + player_won = true, + can_continue = true, + victorious_force = event.rocket.force + } + end + end end script.on_event(defines.events.on_rocket_launched, on_rocket_launched) @@ -198,6 +210,10 @@ script.on_init(function() e.player_index = index on_player_created(e) end + + if remote.interfaces["silo_script"] then + remote.call("silo_script", "set_no_victory", true) + end end) -- hook into researches done