implement Factorio options max_science_pack and tech_cost
also give warnings about deprecated LttP options also fix FactorioClient.py getting stuck if send an unknown item id also fix !missing having an extra newline after each entry also default to no webui
This commit is contained in:
parent
d225eb9ca8
commit
91bcd59940
|
@ -137,11 +137,12 @@ async def factorio_server_watcher(ctx: FactorioContext):
|
|||
if ctx.rcon_client:
|
||||
while ctx.send_index < len(ctx.items_received):
|
||||
item_id = ctx.items_received[ctx.send_index].item
|
||||
item_name = lookup_id_to_name[item_id]
|
||||
factorio_server_logger.info(f"Sending {item_name} to Nauvis.")
|
||||
response = ctx.rcon_client.send_command(f'/ap-get-technology {item_name}')
|
||||
if response:
|
||||
factorio_server_logger.info(response)
|
||||
if item_id not in lookup_id_to_name:
|
||||
logging.error(f"Unknown item ID: {item_id}")
|
||||
else:
|
||||
item_name = lookup_id_to_name[item_id]
|
||||
factorio_server_logger.info(f"Sending {item_name} to Nauvis.")
|
||||
ctx.rcon_client.send_command(f'/ap-get-technology {item_name}')
|
||||
ctx.send_index += 1
|
||||
|
||||
await asyncio.sleep(1)
|
||||
|
|
|
@ -982,8 +982,8 @@ async def main():
|
|||
parser.add_argument('--loglevel', default='info', choices=['debug', 'info', 'warning', 'error', 'critical'])
|
||||
parser.add_argument('--founditems', default=False, action='store_true',
|
||||
help='Show items found by other players for themselves.')
|
||||
parser.add_argument('--disable_web_ui', default=False, action='store_true',
|
||||
help="Turn off emitting a webserver for the webbrowser based user interface.")
|
||||
parser.add_argument('--web_ui', default=False, action='store_true',
|
||||
help="Emit a webserver for the webbrowser based user interface.")
|
||||
args = parser.parse_args()
|
||||
logging.basicConfig(format='%(message)s', level=getattr(logging, args.loglevel.upper(), logging.INFO))
|
||||
if args.diff_file:
|
||||
|
@ -1002,7 +1002,7 @@ async def main():
|
|||
asyncio.create_task(run_game(adjustedromfile if adjusted else romfile))
|
||||
|
||||
port = None
|
||||
if not args.disable_web_ui:
|
||||
if args.web_ui:
|
||||
# Find an available port on the host system to use for hosting the websocket server
|
||||
while True:
|
||||
port = randrange(49152, 65535)
|
||||
|
@ -1015,7 +1015,7 @@ async def main():
|
|||
|
||||
ctx = Context(args.snes, args.connect, args.password, args.founditems, port)
|
||||
input_task = asyncio.create_task(console_loop(ctx), name="Input")
|
||||
if not args.disable_web_ui:
|
||||
if args.web_ui:
|
||||
ui_socket = websockets.serve(functools.partial(websocket_server, ctx=ctx),
|
||||
'localhost', port, ping_timeout=None, ping_interval=None)
|
||||
await ui_socket
|
||||
|
|
2
Main.py
2
Main.py
|
@ -135,6 +135,8 @@ def main(args, seed=None):
|
|||
import Options
|
||||
for hk_option in Options.hollow_knight_options:
|
||||
setattr(world, hk_option, getattr(args, hk_option, {}))
|
||||
for factorio_option in Options.factorio_options:
|
||||
setattr(world, factorio_option, getattr(args, factorio_option, {}))
|
||||
world.glitch_triforce = args.glitch_triforce # This is enabled/disabled globally, no per player option.
|
||||
|
||||
world.rom_seeds = {player: random.Random(world.random.randint(0, 999999999)) for player in range(1, world.players + 1)}
|
||||
|
|
|
@ -794,7 +794,7 @@ class ClientMessageProcessor(CommonCommandProcessor):
|
|||
locations = get_missing_checks(self.ctx, self.client)
|
||||
|
||||
if locations:
|
||||
texts = [f'Missing: {get_item_name_from_id(location)}\n' for location in locations]
|
||||
texts = [f'Missing: {get_item_name_from_id(location)}' for location in locations]
|
||||
texts.append(f"Found {len(locations)} missing location checks")
|
||||
self.ctx.notify_client_multiple(self.client, texts)
|
||||
else:
|
||||
|
|
87
Mystery.py
87
Mystery.py
|
@ -198,11 +198,15 @@ def main(args=None, callback=ERmain):
|
|||
pre_rolled["original_seed_name"] = seedname
|
||||
pre_rolled["pre_rolled"] = vars(settings).copy()
|
||||
if "plando_items" in pre_rolled["pre_rolled"]:
|
||||
pre_rolled["pre_rolled"]["plando_items"] = [item.to_dict() for item in pre_rolled["pre_rolled"]["plando_items"]]
|
||||
pre_rolled["pre_rolled"]["plando_items"] = [item.to_dict() for item in
|
||||
pre_rolled["pre_rolled"]["plando_items"]]
|
||||
if "plando_connections" in pre_rolled["pre_rolled"]:
|
||||
pre_rolled["pre_rolled"]["plando_connections"] = [connection.to_dict() for connection in pre_rolled["pre_rolled"]["plando_connections"]]
|
||||
pre_rolled["pre_rolled"]["plando_connections"] = [connection.to_dict() for connection in
|
||||
pre_rolled["pre_rolled"][
|
||||
"plando_connections"]]
|
||||
|
||||
with open(os.path.join(args.outputpath if args.outputpath else ".", f"{os.path.split(path)[-1].split('.')[0]}_pre_rolled.yaml"), "wt") as f:
|
||||
with open(os.path.join(args.outputpath if args.outputpath else ".",
|
||||
f"{os.path.split(path)[-1].split('.')[0]}_pre_rolled.yaml"), "wt") as f:
|
||||
yaml.dump(pre_rolled, f)
|
||||
for k, v in vars(settings).items():
|
||||
if v is not None:
|
||||
|
@ -294,7 +298,8 @@ def handle_name(name: str, player: int, name_counter: Counter):
|
|||
name_counter[name] += 1
|
||||
new_name = "%".join([x.replace("%number%", "{number}").replace("%player%", "{player}") for x in name.split("%%")])
|
||||
new_name = string.Formatter().vformat(new_name, (), SafeDict(number=name_counter[name],
|
||||
NUMBER=(name_counter[name] if name_counter[name] > 1 else ''),
|
||||
NUMBER=(name_counter[name] if name_counter[
|
||||
name] > 1 else ''),
|
||||
player=player,
|
||||
PLAYER=(player if player > 1 else '')))
|
||||
return new_name.strip().replace(' ', '_')[:16]
|
||||
|
@ -315,17 +320,42 @@ available_boss_locations: typing.Set[str] = {f"{loc.lower()}{f' {level}' if leve
|
|||
boss_shuffle_options = {None: 'none',
|
||||
'none': 'none',
|
||||
'basic': 'basic',
|
||||
'normal': 'normal',
|
||||
'full': 'full',
|
||||
'chaos': 'chaos',
|
||||
'singularity': 'singularity'
|
||||
}
|
||||
|
||||
goals = {
|
||||
'ganon': 'ganon',
|
||||
'crystals': 'crystals',
|
||||
'bosses': 'bosses',
|
||||
'pedestal': 'pedestal',
|
||||
'ganon_pedestal': 'ganonpedestal',
|
||||
'triforce_hunt': 'triforcehunt',
|
||||
'local_triforce_hunt': 'localtriforcehunt',
|
||||
'ganon_triforce_hunt': 'ganontriforcehunt',
|
||||
'local_ganon_triforce_hunt': 'localganontriforcehunt',
|
||||
'ice_rod_hunt': 'icerodhunt',
|
||||
}
|
||||
|
||||
# remove sometime before 1.0.0, warn before
|
||||
legacy_boss_shuffle_options = {
|
||||
# legacy, will go away:
|
||||
'simple': 'basic',
|
||||
'random': 'full',
|
||||
}
|
||||
|
||||
legacy_goals = {
|
||||
'dungeons': 'bosses',
|
||||
'fast_ganon': 'crystals',
|
||||
}
|
||||
|
||||
def roll_percentage(percentage: typing.Union[int, float]) -> bool:
|
||||
"""Roll a percentage chance.
|
||||
percentage is expected to be in range [0, 100]"""
|
||||
return random.random() < (float(percentage) / 100)
|
||||
|
||||
|
||||
def update_weights(weights: dict, new_weights: dict, type: str, name: str) -> dict:
|
||||
logging.debug(f'Applying {new_weights}')
|
||||
new_options = set(new_weights) - set(weights)
|
||||
|
@ -337,6 +367,7 @@ def update_weights(weights: dict, new_weights: dict, type: str, name: str) -> di
|
|||
f'This is probably in error.')
|
||||
return weights
|
||||
|
||||
|
||||
def roll_linked_options(weights: dict) -> dict:
|
||||
weights = weights.copy() # make sure we don't write back to other weights sets in same_settings
|
||||
for option_set in weights["linked_options"]:
|
||||
|
@ -349,7 +380,8 @@ def roll_linked_options(weights: dict) -> dict:
|
|||
weights = update_weights(weights, option_set["options"], "Linked", option_set["name"])
|
||||
if "rom_options" in option_set:
|
||||
rom_weights = weights.get("rom", dict())
|
||||
rom_weights = update_weights(rom_weights, option_set["rom_options"], "Linked Rom", option_set["name"])
|
||||
rom_weights = update_weights(rom_weights, option_set["rom_options"], "Linked Rom",
|
||||
option_set["name"])
|
||||
weights["rom"] = rom_weights
|
||||
else:
|
||||
logging.debug(f"linked option {option_set['name']} skipped.")
|
||||
|
@ -358,6 +390,7 @@ def roll_linked_options(weights: dict) -> dict:
|
|||
f"Please fix your linked option.") from e
|
||||
return weights
|
||||
|
||||
|
||||
def roll_triggers(weights: dict) -> dict:
|
||||
weights = weights.copy() # make sure we don't write back to other weights sets in same_settings
|
||||
weights["_Generator_Version"] = "Archipelago" # Some means for triggers to know if the seed is on main or doors.
|
||||
|
@ -375,7 +408,8 @@ def roll_triggers(weights: dict) -> dict:
|
|||
weights = update_weights(weights, option_set["options"], "Triggered", option_set["option_name"])
|
||||
if "rom_options" in option_set:
|
||||
rom_weights = weights.get("rom", dict())
|
||||
rom_weights = update_weights(rom_weights, option_set["rom_options"], "Triggered Rom", option_set["option_name"])
|
||||
rom_weights = update_weights(rom_weights, option_set["rom_options"], "Triggered Rom",
|
||||
option_set["option_name"])
|
||||
weights["rom"] = rom_weights
|
||||
weights[key] = result
|
||||
except Exception as e:
|
||||
|
@ -385,6 +419,11 @@ def roll_triggers(weights: dict) -> dict:
|
|||
|
||||
|
||||
def get_plando_bosses(boss_shuffle: str, plando_options: typing.Set[str]) -> str:
|
||||
if boss_shuffle in legacy_boss_shuffle_options:
|
||||
new_boss_shuffle = legacy_boss_shuffle_options[boss_shuffle]
|
||||
logging.warning(f"Boss shuffle {boss_shuffle} is deprecated, "
|
||||
f"please use {new_boss_shuffle} instead")
|
||||
return new_boss_shuffle
|
||||
if boss_shuffle in boss_shuffle_options:
|
||||
return boss_shuffle_options[boss_shuffle]
|
||||
elif "bosses" in plando_options:
|
||||
|
@ -392,6 +431,10 @@ def get_plando_bosses(boss_shuffle: str, plando_options: typing.Set[str]) -> str
|
|||
remainder_shuffle = "none" # vanilla
|
||||
bosses = []
|
||||
for boss in options:
|
||||
if boss in legacy_boss_shuffle_options:
|
||||
remainder_shuffle = legacy_boss_shuffle_options[boss_shuffle]
|
||||
logging.warning(f"Boss shuffle {boss} is deprecated, "
|
||||
f"please use {remainder_shuffle} instead")
|
||||
if boss in boss_shuffle_options:
|
||||
remainder_shuffle = boss_shuffle_options[boss]
|
||||
elif "-" in boss:
|
||||
|
@ -419,7 +462,7 @@ def get_plando_bosses(boss_shuffle: str, plando_options: typing.Set[str]) -> str
|
|||
raise Exception(f"Boss Shuffle {boss_shuffle} is unknown and boss plando is turned off.")
|
||||
|
||||
|
||||
def roll_settings(weights: dict, plando_options: typing.Set[str] = frozenset(("bosses", ))):
|
||||
def roll_settings(weights: dict, plando_options: typing.Set[str] = frozenset(("bosses",))):
|
||||
if "pre_rolled" in weights:
|
||||
pre_rolled = weights["pre_rolled"]
|
||||
|
||||
|
@ -435,7 +478,8 @@ def roll_settings(weights: dict, plando_options: typing.Set[str] = frozenset(("b
|
|||
if "plando_connections" in pre_rolled:
|
||||
pre_rolled["plando_connections"] = [PlandoConnection(connection["entrance"],
|
||||
connection["exit"],
|
||||
connection["direction"]) for connection in pre_rolled["plando_connections"]]
|
||||
connection["direction"]) for connection in
|
||||
pre_rolled["plando_connections"]]
|
||||
if "connections" not in plando_options and pre_rolled["plando_connections"]:
|
||||
raise Exception("Connection Plando is turned off. Reusing this pre-rolled setting not permitted.")
|
||||
|
||||
|
@ -486,11 +530,16 @@ def roll_settings(weights: dict, plando_options: typing.Set[str] = frozenset(("b
|
|||
for option_name, option in Options.hollow_knight_options.items():
|
||||
setattr(ret, option_name, option.from_any(get_choice(option_name, weights, True)))
|
||||
elif ret.game == "Factorio":
|
||||
pass
|
||||
for option_name, option in Options.factorio_options.items():
|
||||
if option_name in weights:
|
||||
setattr(ret, option_name, option.from_any(get_choice(option_name, weights)))
|
||||
else:
|
||||
setattr(ret, option_name, option.default)
|
||||
else:
|
||||
raise Exception(f"Unsupported game {ret.game}")
|
||||
return ret
|
||||
|
||||
|
||||
def roll_alttp_settings(ret: argparse.Namespace, weights, plando_options):
|
||||
glitches_required = get_choice('glitches_required', weights)
|
||||
if glitches_required not in [None, 'none', 'no_logic', 'overworld_glitches', 'minor_glitches']:
|
||||
|
@ -533,17 +582,11 @@ def roll_alttp_settings(ret: argparse.Namespace, weights, plando_options):
|
|||
ret.shuffle = entrance_shuffle if entrance_shuffle != 'none' else 'vanilla'
|
||||
|
||||
goal = get_choice('goals', weights, 'ganon')
|
||||
ret.goal = {'ganon': 'ganon',
|
||||
'crystals': 'crystals',
|
||||
'bosses': 'bosses',
|
||||
'pedestal': 'pedestal',
|
||||
'ganon_pedestal': 'ganonpedestal',
|
||||
'triforce_hunt': 'triforcehunt',
|
||||
'local_triforce_hunt': 'localtriforcehunt',
|
||||
'ganon_triforce_hunt': 'ganontriforcehunt',
|
||||
'local_ganon_triforce_hunt': 'localganontriforcehunt',
|
||||
'ice_rod_hunt': 'icerodhunt'
|
||||
}[goal]
|
||||
|
||||
if goal in legacy_goals:
|
||||
logging.warning(f"Goal {goal} is depcrecated, please use {legacy_goals[goal]} instead.")
|
||||
goal = legacy_goals[goal]
|
||||
ret.goal = goals[goal]
|
||||
|
||||
# TODO consider moving open_pyramid to an automatic variable in the core roller, set to True when
|
||||
# fast ganon + ganon at hole
|
||||
|
@ -602,6 +645,7 @@ def roll_alttp_settings(ret: argparse.Namespace, weights, plando_options):
|
|||
|
||||
ret.enemy_shuffle = bool(get_choice('enemy_shuffle', weights, False))
|
||||
|
||||
|
||||
ret.killable_thieves = get_choice('killable_thieves', weights, False)
|
||||
ret.tile_shuffle = get_choice('tile_shuffle', weights, False)
|
||||
ret.bush_shuffle = get_choice('bush_shuffle', weights, False)
|
||||
|
@ -772,5 +816,6 @@ def roll_alttp_settings(ret: argparse.Namespace, weights, plando_options):
|
|||
ret.quickswap = True
|
||||
ret.sprite = "Link"
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
39
Options.py
39
Options.py
|
@ -23,6 +23,7 @@ class AssembleOptions(type):
|
|||
class Option(metaclass=AssembleOptions):
|
||||
value: int
|
||||
name_lookup: typing.Dict[int, str]
|
||||
default = 0
|
||||
|
||||
def __repr__(self):
|
||||
return f"{self.__class__.__name__}({self.get_option_name()})"
|
||||
|
@ -47,6 +48,7 @@ class Option(metaclass=AssembleOptions):
|
|||
class Toggle(Option):
|
||||
option_false = 0
|
||||
option_true = 1
|
||||
default = 0
|
||||
|
||||
def __init__(self, value: int):
|
||||
self.value = value
|
||||
|
@ -86,6 +88,7 @@ class Toggle(Option):
|
|||
def get_option_name(self):
|
||||
return bool(self.value)
|
||||
|
||||
|
||||
class Choice(Option):
|
||||
def __init__(self, value: int):
|
||||
self.value: int = value
|
||||
|
@ -233,6 +236,42 @@ hollow_knight_skip_options: typing.Dict[str, type(Option)] = {
|
|||
|
||||
hollow_knight_options: typing.Dict[str, Option] = {**hollow_knight_randomize_options, **hollow_knight_skip_options}
|
||||
|
||||
|
||||
class MaxSciencePack(Choice):
|
||||
option_automation_science_pack = 0
|
||||
option_logistic_science_pack = 1
|
||||
option_military_science_pack = 2
|
||||
option_chemical_science_pack = 3
|
||||
option_production_science_pack = 4
|
||||
option_utility_science_pack = 5
|
||||
option_space_science_pack = 6
|
||||
default = 6
|
||||
|
||||
def get_allowed_packs(self):
|
||||
return {option.replace("_", "-") for option, value in self.options.items()
|
||||
if value <= self.value}
|
||||
|
||||
|
||||
class TechCost(Choice):
|
||||
option_very_easy = 0
|
||||
option_easy = 1
|
||||
option_kind = 2
|
||||
option_normal = 3
|
||||
option_hard = 4
|
||||
option_very_hard = 5
|
||||
option_insane = 6
|
||||
default = 3
|
||||
|
||||
|
||||
class TechTreeLayout(Choice):
|
||||
option_single = 0
|
||||
default = 0
|
||||
|
||||
|
||||
factorio_options: typing.Dict[str, type(Option)] = {"max_science_pack": MaxSciencePack,
|
||||
"tech_tree_layout": TechTreeLayout,
|
||||
"tech_cost": TechCost}
|
||||
|
||||
if __name__ == "__main__":
|
||||
import argparse
|
||||
|
||||
|
|
|
@ -2,11 +2,28 @@
|
|||
local technologies = data.raw["technology"]
|
||||
local original_tech
|
||||
local new_tree_copy
|
||||
allowed_ingredients = {}
|
||||
{%- for ingredient in allowed_science_packs %}
|
||||
allowed_ingredients["{{ingredient}}"]= 1
|
||||
{% endfor %}
|
||||
local template_tech = table.deepcopy(technologies["automation"])
|
||||
{#- ensure the copy unlocks nothing #}
|
||||
template_tech.unlocks = {}
|
||||
template_tech.upgrade = false
|
||||
template_tech.effects = {}
|
||||
template_tech.prerequisites = {}
|
||||
|
||||
function filter_ingredients(ingredients)
|
||||
local new_ingredient_list = {}
|
||||
for _, ingredient_table in pairs(ingredients) do
|
||||
if allowed_ingredients[ingredient_table[1]] then -- name of ingredient_table
|
||||
table.insert(new_ingredient_list, ingredient_table)
|
||||
end
|
||||
end
|
||||
|
||||
return new_ingredient_list
|
||||
end
|
||||
|
||||
{# each randomized tech gets set to be invisible, with new nodes added that trigger those #}
|
||||
{%- for original_tech_name, item_name, receiving_player in locations %}
|
||||
original_tech = technologies["{{original_tech_name}}"]
|
||||
|
@ -17,6 +34,12 @@ new_tree_copy.name = "ap-{{ tech_table[original_tech_name] }}-"{# use AP ID #}
|
|||
original_tech.enabled = false
|
||||
{#- copy original tech costs #}
|
||||
new_tree_copy.unit = table.deepcopy(original_tech.unit)
|
||||
new_tree_copy.unit.ingredients = filter_ingredients(new_tree_copy.unit.ingredients)
|
||||
{% if tech_cost != 1 %}
|
||||
if new_tree_copy.unit.count then
|
||||
new_tree_copy.unit.count = math.max(1, math.floor(new_tree_copy.unit.count * {{ tech_cost }}))
|
||||
end
|
||||
{% endif %}
|
||||
{% if item_name in tech_table %}
|
||||
{#- copy Factorio Technology Icon #}
|
||||
new_tree_copy.icon = table.deepcopy(technologies["{{ item_name }}"].icon)
|
||||
|
|
|
@ -35,6 +35,25 @@ accessibility:
|
|||
progression_balancing:
|
||||
on: 50 # A system to reduce BK, as in times during which you can't do anything by moving your items into an earlier access sphere to make it likely you have stuff to do
|
||||
off: 0 # Turn this off if you don't mind a longer multiworld, or can glitch/sequence break around missing items.
|
||||
# Factorio options:
|
||||
tech_tree_layout:
|
||||
single: 1
|
||||
max_science_pack:
|
||||
automation_science_pack: 0
|
||||
logistic_science_pack: 0
|
||||
military_science_pack: 0
|
||||
chemical_science_pack: 0
|
||||
production_science_pack: 0
|
||||
utility_science_pack: 0
|
||||
space_science_pack: 1
|
||||
tech_cost:
|
||||
very_easy : 0
|
||||
easy : 0
|
||||
kind : 0
|
||||
normal : 1
|
||||
hard : 0
|
||||
very_hard : 0
|
||||
insane : 0
|
||||
# A Link to the Past options:
|
||||
### Logic Section ###
|
||||
# Warning: overworld_glitches is not available and minor_glitches is only partially implemented on the door-rando version
|
||||
|
|
|
@ -241,7 +241,7 @@ def place_bosses(world, player: int):
|
|||
if shuffle_mode == "none":
|
||||
return # vanilla bosses come pre-placed
|
||||
|
||||
if shuffle_mode in ["basic", "normal"]:
|
||||
if shuffle_mode in ["basic", "full"]:
|
||||
if world.boss_shuffle[player] == "basic": # vanilla bosses shuffled
|
||||
bosses = placeable_bosses + ['Armos Knights', 'Lanmolas', 'Moldorm']
|
||||
else: # all bosses present, the three duplicates chosen at random
|
||||
|
|
|
@ -1651,7 +1651,7 @@ def write_custom_shops(rom, world, player):
|
|||
if item is None:
|
||||
break
|
||||
if not item['item'] in item_table: # item not native to ALTTP
|
||||
item_code = 0x21
|
||||
item_code = 0x09 # Hammer
|
||||
else:
|
||||
item_code = ItemFactory(item['item'], player).code
|
||||
if item['item'] == 'Single Arrow' and item['player'] == 0 and world.retro[player]:
|
||||
|
|
|
@ -35,11 +35,19 @@ def generate_mod(world: MultiWorld, player: int):
|
|||
player_names = {x: world.player_names[x][0] for x in world.player_ids}
|
||||
locations = []
|
||||
for location in world.get_filled_locations(player):
|
||||
if not location.name.startswith("recipe-"): # introduce this a new location property?
|
||||
if not location.name.startswith("recipe-"): # introduce this as a new location property?
|
||||
locations.append((location.name, location.item.name, location.item.player))
|
||||
mod_name = f"archipelago-client-{world.seed}-{player}"
|
||||
tech_cost = {0: 0.1,
|
||||
1: 0.25,
|
||||
2: 0.5,
|
||||
3: 1,
|
||||
4: 2,
|
||||
5: 5,
|
||||
6: 10}[world.tech_cost[player].value]
|
||||
template_data = {"locations": locations, "player_names" : player_names, "tech_table": tech_table,
|
||||
"mod_name": mod_name}
|
||||
"mod_name": mod_name, "allowed_science_packs": world.max_science_pack[player].get_allowed_packs(),
|
||||
"tech_cost": tech_cost}
|
||||
|
||||
mod_code = template.render(**template_data)
|
||||
|
||||
|
|
|
@ -29,10 +29,8 @@ for technology in sorted(raw):
|
|||
requirements[technology] = set(data["requires"])
|
||||
current_ingredients = set(data["ingredients"])-starting_ingredient_recipes
|
||||
if current_ingredients:
|
||||
|
||||
all_ingredients |= current_ingredients
|
||||
current_ingredients = {"recipe-"+ingredient for ingredient in current_ingredients}
|
||||
ingredients[technology] = current_ingredients
|
||||
ingredients[technology] = {"recipe-"+ingredient for ingredient in current_ingredients}
|
||||
|
||||
recipe_sources = {}
|
||||
|
||||
|
@ -41,6 +39,6 @@ for technology, data in raw.items():
|
|||
for recipe in recipe_source:
|
||||
recipe_sources["recipe-"+recipe] = technology
|
||||
|
||||
all_ingredients = {"recipe-"+ingredient for ingredient in all_ingredients}
|
||||
all_ingredients_recipe = {"recipe-"+ingredient for ingredient in all_ingredients}
|
||||
del(raw)
|
||||
lookup_id_to_name: Dict[int, str] = {item_id: item_name for item_name, item_id in tech_table.items()}
|
|
@ -2,7 +2,7 @@ import logging
|
|||
|
||||
from BaseClasses import Region, Entrance, Location, MultiWorld, Item
|
||||
|
||||
from .Technologies import tech_table, requirements, ingredients, all_ingredients, recipe_sources
|
||||
from .Technologies import tech_table, requirements, ingredients, all_ingredients, recipe_sources, all_ingredients_recipe
|
||||
|
||||
static_nodes = {"automation", "logistics"}
|
||||
|
||||
|
@ -30,7 +30,7 @@ def factorio_create_regions(world: MultiWorld, player: int):
|
|||
tech = Location(player, tech_name, tech_id, nauvis)
|
||||
nauvis.locations.append(tech)
|
||||
tech.game = "Factorio"
|
||||
for ingredient in all_ingredients: # register science packs as events
|
||||
for ingredient in all_ingredients_recipe: # register science packs as events
|
||||
ingredient_location = Location(player, ingredient, 0, nauvis)
|
||||
ingredient_location.item = Item(ingredient, True, 0, player)
|
||||
ingredient_location.event = ingredient_location.locked = True
|
||||
|
@ -56,4 +56,4 @@ def set_rules(world: MultiWorld, player: int):
|
|||
|
||||
|
||||
world.completion_condition[player] = lambda state: all(state.has(ingredient, player)
|
||||
for ingredient in all_ingredients)
|
||||
for ingredient in all_ingredients_recipe)
|
||||
|
|
Loading…
Reference in New Issue