mirror of
https://github.com/ArchipelagoMW/Archipelago.git
synced 2026-03-07 23:25:51 -08:00
Compare commits
10 Commits
0.6.5
...
NewSoupVi-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ad8223998e | ||
|
|
b6e2c8129f | ||
|
|
fd4e47efab | ||
|
|
b42fb77451 | ||
|
|
5a8e166289 | ||
|
|
5fa719143c | ||
|
|
a906f139c3 | ||
|
|
56363ea7e7 | ||
|
|
01e1e1fe11 | ||
|
|
4477dc7a66 |
@@ -632,7 +632,7 @@ class OptionsCreator(ThemedApp):
|
||||
self.create_options_panel(world_btn)
|
||||
|
||||
for world, cls in sorted(AutoWorldRegister.world_types.items(), key=lambda x: x[0]):
|
||||
if world == "Archipelago":
|
||||
if cls.hidden:
|
||||
continue
|
||||
world_text = MDButtonText(text=world, size_hint_y=None, width=dp(150),
|
||||
pos_hint={"x": 0.03, "center_y": 0.5})
|
||||
|
||||
2
Utils.py
2
Utils.py
@@ -48,7 +48,7 @@ class Version(typing.NamedTuple):
|
||||
return ".".join(str(item) for item in self)
|
||||
|
||||
|
||||
__version__ = "0.6.5"
|
||||
__version__ = "0.6.6"
|
||||
version_tuple = tuplize_version(__version__)
|
||||
|
||||
is_linux = sys.platform.startswith("linux")
|
||||
|
||||
@@ -23,6 +23,17 @@ app.jinja_env.filters['any'] = any
|
||||
app.jinja_env.filters['all'] = all
|
||||
app.jinja_env.filters['get_file_safe_name'] = get_file_safe_name
|
||||
|
||||
# overwrites of flask default config
|
||||
app.config["DEBUG"] = False
|
||||
app.config["PORT"] = 80
|
||||
app.config["UPLOAD_FOLDER"] = UPLOAD_FOLDER
|
||||
app.config["MAX_CONTENT_LENGTH"] = 64 * 1024 * 1024 # 64 megabyte limit
|
||||
# if you want to deploy, make sure you have a non-guessable secret key
|
||||
app.config["SECRET_KEY"] = bytes(socket.gethostname(), encoding="utf-8")
|
||||
app.config["SESSION_PERMANENT"] = True
|
||||
app.config["MAX_FORM_MEMORY_SIZE"] = 2 * 1024 * 1024 # 2 MB, needed for large option pages such as SC2
|
||||
|
||||
# custom config
|
||||
app.config["SELFHOST"] = True # application process is in charge of running the websites
|
||||
app.config["GENERATORS"] = 8 # maximum concurrent world gens
|
||||
app.config["HOSTERS"] = 8 # maximum concurrent room hosters
|
||||
@@ -30,19 +41,12 @@ app.config["SELFLAUNCH"] = True # application process is in charge of launching
|
||||
app.config["SELFLAUNCHCERT"] = None # can point to a SSL Certificate to encrypt Room websocket connections
|
||||
app.config["SELFLAUNCHKEY"] = None # can point to a SSL Certificate Key to encrypt Room websocket connections
|
||||
app.config["SELFGEN"] = True # application process is in charge of scheduling Generations.
|
||||
app.config["DEBUG"] = False
|
||||
app.config["PORT"] = 80
|
||||
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
|
||||
app.config['MAX_CONTENT_LENGTH'] = 64 * 1024 * 1024 # 64 megabyte limit
|
||||
# if you want to deploy, make sure you have a non-guessable secret key
|
||||
app.config["SECRET_KEY"] = bytes(socket.gethostname(), encoding="utf-8")
|
||||
# at what amount of worlds should scheduling be used, instead of rolling in the web-thread
|
||||
app.config["JOB_THRESHOLD"] = 1
|
||||
# after what time in seconds should generation be aborted, freeing the queue slot. Can be set to None to disable.
|
||||
app.config["JOB_TIME"] = 600
|
||||
# memory limit for generator processes in bytes
|
||||
app.config["GENERATOR_MEMORY_LIMIT"] = 4294967296
|
||||
app.config['SESSION_PERMANENT'] = True
|
||||
|
||||
# waitress uses one thread for I/O, these are for processing of views that then get sent
|
||||
# archipelago.gg uses gunicorn + nginx; ignoring this option
|
||||
|
||||
@@ -177,7 +177,8 @@
|
||||
/worlds/sa2b/ @PoryGone @RaspberrySpace
|
||||
|
||||
# Starcraft 2
|
||||
/worlds/sc2/ @Ziktofel
|
||||
# Note: @Ziktofel acts as a mentor
|
||||
/worlds/sc2/ @MatthewMarinets @Snarkie @SirChuckOfTheChuckles
|
||||
|
||||
# Super Metroid
|
||||
/worlds/sm/ @lordlou
|
||||
|
||||
@@ -31,3 +31,21 @@ components.append(
|
||||
supports_uri=True,
|
||||
)
|
||||
)
|
||||
|
||||
# There are two optional parameters that are worth drawing attention to here: "game_name" and "supports_uri".
|
||||
# As you might know, on a room page on WebHost, clicking a slot name opens your locally installed Launcher
|
||||
# and asks you if you want to open a Text Client.
|
||||
# If you have "game_name" set on your Component, your user also gets the option to open that instead.
|
||||
# Furthermore, if you have "supports_uri" set to True, your Component will be passed a uri as an arg.
|
||||
# This uri contains the room url + port, the slot name, and the password.
|
||||
# You can process this uri arg to automatically connect the user to their slot without having to type anything.
|
||||
|
||||
# As you can see above, the APQuest client has both of these parameters set.
|
||||
# This means a user can click on the slot name of an APQuest slot on WebHost,
|
||||
# then click "APQuest Client" instead of "Text Client" in the Launcher popup, and after a few seconds,
|
||||
# they will be connected and playing the game without having to touch their keyboard once.
|
||||
|
||||
# Since a Component is just Python code, this doesn't just work with CommonClient-derived clients.
|
||||
# You could forward this uri arg to your standalone C++/Java/.NET/whatever client as well,
|
||||
# meaning just about every client can support this "Click on slot name -> Everything happens automatically" action.
|
||||
# The author would like to see more clients be aware of this feature and try to support it.
|
||||
|
||||
@@ -158,11 +158,11 @@ class Game:
|
||||
if not self.gameboard.ready:
|
||||
return
|
||||
|
||||
if self.active_math_problem is not None:
|
||||
if input_key in DIGIT_INPUTS_TO_DIGITS:
|
||||
self.math_problem_input(DIGIT_INPUTS_TO_DIGITS[input_key])
|
||||
if input_key == Input.BACKSPACE:
|
||||
self.math_problem_delete()
|
||||
if input_key in DIGIT_INPUTS_TO_DIGITS:
|
||||
self.math_problem_input(DIGIT_INPUTS_TO_DIGITS[input_key])
|
||||
return
|
||||
if input_key == Input.BACKSPACE:
|
||||
self.math_problem_delete()
|
||||
return
|
||||
|
||||
if input_key == Input.LEFT:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from typing import Dict, List
|
||||
|
||||
from .Technologies import factorio_base_id
|
||||
from .Technologies import factorio_base_id, recipes
|
||||
from .Options import MaxSciencePack
|
||||
|
||||
|
||||
@@ -21,5 +21,18 @@ for pool in location_pools.values():
|
||||
location_table.update({name: ap_id for ap_id, name in enumerate(pool, start=end_id)})
|
||||
end_id += len(pool)
|
||||
|
||||
craftsanity_locations = []
|
||||
valid_items = []
|
||||
item_category = {}
|
||||
for recipe_name, recipe in recipes.items():
|
||||
if not recipe_name.endswith(("-barrel", "-science-pack")):
|
||||
for result in recipe.products:
|
||||
if result not in valid_items:
|
||||
valid_items.append(result)
|
||||
for i, item in enumerate(valid_items, start=end_id):
|
||||
location_table[f"Craft {item}"] = i
|
||||
craftsanity_locations.append(f"Craft {item}")
|
||||
end_id += 1
|
||||
|
||||
assert end_id - len(location_table) == factorio_base_id
|
||||
del pool
|
||||
|
||||
@@ -112,7 +112,7 @@ def generate_mod(world: "Factorio", output_directory: str):
|
||||
settings_template = template_env.get_template("settings.lua")
|
||||
# get data for templates
|
||||
locations = [(location, location.item)
|
||||
for location in world.science_locations]
|
||||
for location in world.science_locations + world.craftsanity_locations]
|
||||
mod_name = f"AP-{multiworld.seed_name}-P{player}-{multiworld.get_file_safe_player_name(player)}"
|
||||
versioned_mod_name = mod_name + "_" + Utils.__version__
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import typing
|
||||
from schema import Schema, Optional, And, Or, SchemaError
|
||||
|
||||
from Options import Choice, OptionDict, OptionSet, DefaultOnToggle, Range, DeathLink, Toggle, \
|
||||
StartInventoryPool, PerGameCommonOptions, OptionGroup
|
||||
StartInventoryPool, PerGameCommonOptions, OptionGroup, NamedRange
|
||||
|
||||
|
||||
# schema helpers
|
||||
@@ -60,6 +60,20 @@ class Goal(Choice):
|
||||
default = 0
|
||||
|
||||
|
||||
class CraftSanity(NamedRange):
|
||||
"""Choose a number of researches to require crafting a specific item rather than with science packs.
|
||||
May be capped based on the total number of locations.
|
||||
There will always be at least 2 Science Pack research locations for automation and logistics, and 1 for rocket-silo
|
||||
if the Rocket Silo option is not set to Spawn."""
|
||||
display_name = "CraftSanity"
|
||||
default = 0
|
||||
range_start = 0
|
||||
range_end = 183
|
||||
special_range_names = {
|
||||
"disabled": 0
|
||||
}
|
||||
|
||||
|
||||
class TechCost(Range):
|
||||
range_start = 1
|
||||
range_end = 10000
|
||||
@@ -475,6 +489,7 @@ class EnergyLink(Toggle):
|
||||
class FactorioOptions(PerGameCommonOptions):
|
||||
max_science_pack: MaxSciencePack
|
||||
goal: Goal
|
||||
craftsanity: CraftSanity
|
||||
tech_tree_layout: TechTreeLayout
|
||||
min_tech_cost: MinTechCost
|
||||
max_tech_cost: MaxTechCost
|
||||
|
||||
@@ -334,14 +334,15 @@ required_technologies: Dict[str, FrozenSet[Technology]] = Utils.KeyedDefaultDict
|
||||
recursively_get_unlocking_technologies(ingredient_name, unlock_func=unlock)))
|
||||
|
||||
|
||||
def get_rocket_requirements(silo_recipe: Optional[Recipe], part_recipe: Recipe,
|
||||
def get_rocket_requirements(silo_recipe: Optional[Recipe], part_recipe: Optional[Recipe],
|
||||
satellite_recipe: Optional[Recipe], cargo_landing_pad_recipe: Optional[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 part_recipe:
|
||||
for ingredient in part_recipe.ingredients:
|
||||
techs |= recursively_get_unlocking_technologies(ingredient)
|
||||
if cargo_landing_pad_recipe:
|
||||
for ingredient in cargo_landing_pad_recipe.ingredients:
|
||||
techs |= recursively_get_unlocking_technologies(ingredient)
|
||||
|
||||
@@ -9,7 +9,7 @@ from BaseClasses import Region, Location, Item, Tutorial, ItemClassification
|
||||
from worlds.AutoWorld import World, WebWorld
|
||||
from worlds.LauncherComponents import Component, components, Type, launch as launch_component
|
||||
from worlds.generic import Rules
|
||||
from .Locations import location_pools, location_table
|
||||
from .Locations import location_pools, location_table, craftsanity_locations
|
||||
from .Mod import generate_mod
|
||||
from .Options import (FactorioOptions, MaxSciencePack, Silo, Satellite, TechTreeInformation, Goal,
|
||||
TechCostDistribution, option_groups)
|
||||
@@ -88,6 +88,7 @@ class Factorio(World):
|
||||
skip_silo: bool = False
|
||||
origin_region_name = "Nauvis"
|
||||
science_locations: typing.List[FactorioScienceLocation]
|
||||
craftsanity_locations: typing.List[FactorioCraftsanityLocation]
|
||||
removed_technologies: typing.Set[str]
|
||||
settings: typing.ClassVar[FactorioSettings]
|
||||
trap_names: tuple[str] = ("Evolution", "Attack", "Teleport", "Grenade", "Cluster Grenade", "Artillery",
|
||||
@@ -100,6 +101,7 @@ class Factorio(World):
|
||||
self.advancement_technologies = set()
|
||||
self.custom_recipes = {}
|
||||
self.science_locations = []
|
||||
self.craftsanity_locations = []
|
||||
self.tech_tree_layout_prerequisites = {}
|
||||
|
||||
generate_output = generate_mod
|
||||
@@ -127,17 +129,42 @@ class Factorio(World):
|
||||
|
||||
location_pool = []
|
||||
|
||||
craftsanity_pool = [craft for craft in craftsanity_locations
|
||||
if self.options.silo != Silo.option_spawn
|
||||
or craft not in ["Craft rocket-silo", "Craft cargo-landing-pad"]]
|
||||
# Ensure at least 2 science pack locations for automation and logistics, and 1 more for rocket-silo
|
||||
# if it is not pre-spawned
|
||||
craftsanity_count = min(self.options.craftsanity.value, len(craftsanity_pool),
|
||||
location_count - (2 if self.options.silo == Silo.option_spawn else 3))
|
||||
|
||||
location_count -= craftsanity_count
|
||||
|
||||
for pack in sorted(self.options.max_science_pack.get_allowed_packs()):
|
||||
location_pool.extend(location_pools[pack])
|
||||
try:
|
||||
location_names = random.sample(location_pool, location_count)
|
||||
# Ensure there are two "AP-1-" locations for automation and logistics, and one max science pack location
|
||||
# for rocket-silo if it is not pre-spawned
|
||||
max_science_pack_number = len(self.options.max_science_pack.get_allowed_packs())
|
||||
science_location_names = None
|
||||
while (not science_location_names or
|
||||
len([location for location in science_location_names if location.startswith("AP-1-")]) < 2
|
||||
or (self.options.silo != Silo.option_spawn and len([location for location in science_location_names
|
||||
if location.startswith(f"AP-{max_science_pack_number}")]) < 1)):
|
||||
science_location_names = random.sample(location_pool, location_count)
|
||||
craftsanity_location_names = random.sample(craftsanity_pool, craftsanity_count)
|
||||
|
||||
except ValueError as e:
|
||||
# should be "ValueError: Sample larger than population or is negative"
|
||||
raise Exception("Too many traps for too few locations. Either decrease the trap count, "
|
||||
f"or increase the location count (higher max science pack). (Player {self.player})") from e
|
||||
|
||||
self.science_locations = [FactorioScienceLocation(player, loc_name, self.location_name_to_id[loc_name], nauvis)
|
||||
for loc_name in location_names]
|
||||
for loc_name in science_location_names]
|
||||
|
||||
self.craftsanity_locations = [FactorioCraftsanityLocation(player, loc_name, self.location_name_to_id[loc_name], nauvis)
|
||||
for loc_name in craftsanity_location_names]
|
||||
|
||||
|
||||
distribution: TechCostDistribution = self.options.tech_cost_distribution
|
||||
min_cost = self.options.min_tech_cost.value
|
||||
max_cost = self.options.max_tech_cost.value
|
||||
@@ -159,6 +186,7 @@ class Factorio(World):
|
||||
location.count = rand_values[i]
|
||||
del rand_values
|
||||
nauvis.locations.extend(self.science_locations)
|
||||
nauvis.locations.extend(self.craftsanity_locations)
|
||||
location = FactorioLocation(player, "Rocket Launch", None, nauvis)
|
||||
nauvis.locations.append(location)
|
||||
event = FactorioItem("Victory", ItemClassification.progression, None, player)
|
||||
@@ -188,7 +216,7 @@ class Factorio(World):
|
||||
loc: FactorioScienceLocation
|
||||
if self.options.tech_tree_information == TechTreeInformation.option_full:
|
||||
# mark all locations as pre-hinted
|
||||
for loc in self.science_locations:
|
||||
for loc in self.science_locations + self.craftsanity_locations:
|
||||
loc.revealed = True
|
||||
if self.skip_silo:
|
||||
self.removed_technologies |= {"rocket-silo"}
|
||||
@@ -236,6 +264,23 @@ class Factorio(World):
|
||||
location.access_rule = lambda state, ingredient=ingredient: \
|
||||
all(state.has(technology.name, player) for technology in required_technologies[ingredient])
|
||||
|
||||
for location in self.craftsanity_locations:
|
||||
if location.crafted_item == "crude-oil":
|
||||
recipe = recipes["pumpjack"]
|
||||
elif location.crafted_item in recipes:
|
||||
recipe = recipes[location.crafted_item]
|
||||
else:
|
||||
for recipe_name, recipe in recipes.items():
|
||||
if recipe_name.endswith("-barrel"):
|
||||
continue
|
||||
if location.crafted_item in recipe.products:
|
||||
break
|
||||
else:
|
||||
raise Exception(
|
||||
f"No recipe found for {location.crafted_item} for Craftsanity for player {self.player}")
|
||||
location.access_rule = lambda state, recipe=recipe: \
|
||||
state.has_all({technology.name for technology in recipe.recursive_unlocking_technologies}, player)
|
||||
|
||||
for location in self.science_locations:
|
||||
Rules.set_rule(location, lambda state, ingredients=frozenset(location.ingredients):
|
||||
all(state.has(f"Automated {ingredient}", player) for ingredient in ingredients))
|
||||
@@ -250,10 +295,11 @@ class Factorio(World):
|
||||
silo_recipe = self.get_recipe("rocket-silo")
|
||||
cargo_pad_recipe = self.get_recipe("cargo-landing-pad")
|
||||
part_recipe = self.custom_recipes["rocket-part"]
|
||||
satellite_recipe = None
|
||||
if self.options.goal == Goal.option_satellite:
|
||||
satellite_recipe = self.get_recipe("satellite")
|
||||
victory_tech_names = get_rocket_requirements(silo_recipe, part_recipe, satellite_recipe, cargo_pad_recipe)
|
||||
satellite_recipe = self.get_recipe("satellite")
|
||||
victory_tech_names = get_rocket_requirements(
|
||||
silo_recipe, part_recipe,
|
||||
satellite_recipe if self.options.goal == Goal.option_satellite else None,
|
||||
cargo_pad_recipe)
|
||||
if self.options.silo == Silo.option_spawn:
|
||||
victory_tech_names -= {"rocket-silo"}
|
||||
else:
|
||||
@@ -263,6 +309,46 @@ class Factorio(World):
|
||||
victory_tech_names)
|
||||
self.multiworld.completion_condition[player] = lambda state: state.has('Victory', player)
|
||||
|
||||
if "Craft rocket-silo" in self.multiworld.regions.location_cache[self.player]:
|
||||
victory_tech_names_r = get_rocket_requirements(silo_recipe, None, None, None)
|
||||
if self.options.silo == Silo.option_spawn:
|
||||
victory_tech_names_r -= {"rocket-silo"}
|
||||
else:
|
||||
victory_tech_names_r |= {"rocket-silo"}
|
||||
self.get_location("Craft rocket-silo").access_rule = lambda state: all(state.has(technology, player)
|
||||
for technology in
|
||||
victory_tech_names_r)
|
||||
|
||||
if "Craft rocket-part" in self.multiworld.regions.location_cache[self.player]:
|
||||
victory_tech_names_p = get_rocket_requirements(silo_recipe, part_recipe, None, None)
|
||||
if self.options.silo == Silo.option_spawn:
|
||||
victory_tech_names_p -= {"rocket-silo"}
|
||||
else:
|
||||
victory_tech_names_p |= {"rocket-silo"}
|
||||
self.get_location("Craft rocket-part").access_rule = lambda state: all(state.has(technology, player)
|
||||
for technology in
|
||||
victory_tech_names_p)
|
||||
|
||||
if "Craft satellite" in self.multiworld.regions.location_cache[self.player]:
|
||||
victory_tech_names_s = get_rocket_requirements(None, None, satellite_recipe, None)
|
||||
if self.options.silo == Silo.option_spawn:
|
||||
victory_tech_names_s -= {"rocket-silo"}
|
||||
else:
|
||||
victory_tech_names_s |= {"rocket-silo"}
|
||||
self.get_location("Craft satellite").access_rule = lambda state: all(state.has(technology, player)
|
||||
for technology in
|
||||
victory_tech_names_s)
|
||||
|
||||
if "Craft cargo-landing-pad" in self.multiworld.regions.location_cache[self.player]:
|
||||
victory_tech_names_c = get_rocket_requirements(None, None, None, cargo_pad_recipe)
|
||||
if self.options.silo == Silo.option_spawn:
|
||||
victory_tech_names_c -= {"rocket-silo"}
|
||||
else:
|
||||
victory_tech_names_c |= {"rocket-silo"}
|
||||
self.get_location("Craft cargo-landing-pad").access_rule = lambda state: all(state.has(technology, player)
|
||||
for technology in
|
||||
victory_tech_names_c)
|
||||
|
||||
def get_recipe(self, name: str) -> Recipe:
|
||||
return self.custom_recipes[name] if name in self.custom_recipes \
|
||||
else next(iter(all_product_sources.get(name)))
|
||||
@@ -486,9 +572,17 @@ class Factorio(World):
|
||||
needed_recipes = self.options.max_science_pack.get_allowed_packs() | {"rocket-part"}
|
||||
if self.options.silo != Silo.option_spawn:
|
||||
needed_recipes |= {"rocket-silo", "cargo-landing-pad"}
|
||||
if self.options.goal.value == Goal.option_satellite:
|
||||
if (self.options.goal.value == Goal.option_satellite
|
||||
or "Craft satellite" in self.multiworld.regions.location_cache[self.player]):
|
||||
needed_recipes |= {"satellite"}
|
||||
|
||||
needed_items = {location.crafted_item for location in self.craftsanity_locations}
|
||||
for recipe_name, recipe in recipes.items():
|
||||
for product in recipe.products:
|
||||
if product in needed_items:
|
||||
self.advancement_technologies |= {tech.name for tech in recipe.recursive_unlocking_technologies}
|
||||
break
|
||||
|
||||
for recipe in needed_recipes:
|
||||
recipe = self.custom_recipes.get(recipe, recipes[recipe])
|
||||
self.advancement_technologies |= {tech.name for tech in recipe.recursive_unlocking_technologies}
|
||||
@@ -520,9 +614,23 @@ class FactorioLocation(Location):
|
||||
game: str = Factorio.game
|
||||
|
||||
|
||||
class FactorioCraftsanityLocation(FactorioLocation):
|
||||
ingredients = {}
|
||||
count = 0
|
||||
revealed = False
|
||||
|
||||
def __init__(self, player: int, name: str, address: int, parent: Region):
|
||||
super(FactorioCraftsanityLocation, self).__init__(player, name, address, parent)
|
||||
|
||||
@property
|
||||
def crafted_item(self):
|
||||
return " ".join(self.name.split(" ")[1:])
|
||||
|
||||
|
||||
class FactorioScienceLocation(FactorioLocation):
|
||||
complexity: int
|
||||
revealed: bool = False
|
||||
crafted_item = None
|
||||
|
||||
# Factorio technology properties:
|
||||
ingredients: typing.Dict[str, int]
|
||||
|
||||
@@ -63,22 +63,6 @@ template_tech.upgrade = false
|
||||
template_tech.effects = {}
|
||||
template_tech.prerequisites = {}
|
||||
|
||||
{%- if max_science_pack < 6 %}
|
||||
technologies["space-science-pack"].effects = {}
|
||||
{%- if max_science_pack == 0 %}
|
||||
table.insert (technologies["automation"].effects, {type = "unlock-recipe", recipe = "satellite"})
|
||||
{%- elif max_science_pack == 1 %}
|
||||
table.insert (technologies["logistic-science-pack"].effects, {type = "unlock-recipe", recipe = "satellite"})
|
||||
{%- elif max_science_pack == 2 %}
|
||||
table.insert (technologies["military-science-pack"].effects, {type = "unlock-recipe", recipe = "satellite"})
|
||||
{%- elif max_science_pack == 3 %}
|
||||
table.insert (technologies["chemical-science-pack"].effects, {type = "unlock-recipe", recipe = "satellite"})
|
||||
{%- elif max_science_pack == 4 %}
|
||||
table.insert (technologies["production-science-pack"].effects, {type = "unlock-recipe", recipe = "satellite"})
|
||||
{%- elif max_science_pack == 5 %}
|
||||
table.insert (technologies["utility-science-pack"].effects, {type = "unlock-recipe", recipe = "satellite"})
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{%- if silo == 2 %}
|
||||
data.raw["recipe"]["rocket-silo"].enabled = true
|
||||
{% endif %}
|
||||
@@ -169,9 +153,16 @@ technologies["{{ original_tech_name }}"].hidden_in_factoriopedia = true
|
||||
{#- the tech researched by the local player #}
|
||||
new_tree_copy = table.deepcopy(template_tech)
|
||||
new_tree_copy.name = "ap-{{ location.address }}-"{# use AP ID #}
|
||||
{% if location.crafted_item is not none %}
|
||||
new_tree_copy.research_trigger = {
|
||||
type = "{{ 'craft-fluid' if location.crafted_item in liquids else 'craft-item' }}",
|
||||
{{ 'fluid' if location.crafted_item in liquids else 'item' }} = {{ variable_to_lua(location.crafted_item) }}
|
||||
}
|
||||
new_tree_copy.unit = nil
|
||||
{% else %}
|
||||
new_tree_copy.unit.count = {{ location.count }}
|
||||
new_tree_copy.unit.ingredients = {{ variable_to_lua(location.factorio_ingredients) }}
|
||||
|
||||
{% endif %}
|
||||
{%- if location.revealed and item.name in base_tech_table -%}
|
||||
{#- copy Factorio Technology Icon #}
|
||||
copy_factorio_icon(new_tree_copy, "{{ item.name }}")
|
||||
|
||||
5
worlds/tloz/archipelago.json
Normal file
5
worlds/tloz/archipelago.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"game": "The Legend of Zelda",
|
||||
"world_version": "1.0.0",
|
||||
"authors": ["Rosalie"]
|
||||
}
|
||||
Reference in New Issue
Block a user