Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TUNIC: Modify UT support to make a better pattern #3860

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
40 changes: 23 additions & 17 deletions worlds/tunic/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ class TunicWorld(World):
er_portal_hints: Dict[int, str]
seed_groups: Dict[str, SeedGroup] = {}

using_ut: bool # so we can check if we're using UT only once
passthrough: Dict[str, Any]

def generate_early(self) -> None:
if self.options.plando_connections:
for index, cxn in enumerate(self.options.plando_connections):
Expand All @@ -94,19 +97,24 @@ def generate_early(self) -> None:
# Universal tracker stuff, shouldn't do anything in standard gen
if hasattr(self.multiworld, "re_gen_passthrough"):
ScipioWright marked this conversation as resolved.
Show resolved Hide resolved
if "TUNIC" in self.multiworld.re_gen_passthrough:
passthrough = self.multiworld.re_gen_passthrough["TUNIC"]
self.options.start_with_sword.value = passthrough["start_with_sword"]
self.options.keys_behind_bosses.value = passthrough["keys_behind_bosses"]
self.options.sword_progression.value = passthrough["sword_progression"]
self.options.ability_shuffling.value = passthrough["ability_shuffling"]
self.options.logic_rules.value = passthrough["logic_rules"]
self.options.lanternless.value = passthrough["lanternless"]
self.options.maskless.value = passthrough["maskless"]
self.options.hexagon_quest.value = passthrough["hexagon_quest"]
self.options.entrance_rando.value = passthrough["entrance_rando"]
self.options.shuffle_ladders.value = passthrough["shuffle_ladders"]
self.using_ut = True
self.passthrough = self.multiworld.re_gen_passthrough["TUNIC"]
self.options.start_with_sword.value = self.passthrough["start_with_sword"]
self.options.keys_behind_bosses.value = self.passthrough["keys_behind_bosses"]
self.options.sword_progression.value = self.passthrough["sword_progression"]
self.options.ability_shuffling.value = self.passthrough["ability_shuffling"]
self.options.logic_rules.value = self.passthrough["logic_rules"]
ScipioWright marked this conversation as resolved.
Show resolved Hide resolved
self.options.lanternless.value = self.passthrough["lanternless"]
self.options.maskless.value = self.passthrough["maskless"]
self.options.hexagon_quest.value = self.passthrough["hexagon_quest"]
self.options.entrance_rando.value = self.passthrough["entrance_rando"]
self.options.shuffle_ladders.value = self.passthrough["shuffle_ladders"]
self.options.fixed_shop.value = self.options.fixed_shop.option_false
self.options.laurels_location.value = self.options.laurels_location.option_anywhere
else:
self.using_ut = False
else:
self.using_ut = False

@classmethod
def stage_generate_early(cls, multiworld: MultiWorld) -> None:
Expand Down Expand Up @@ -275,12 +283,10 @@ def create_regions(self) -> None:
self.ability_unlocks = randomize_ability_unlocks(self.random, self.options)

# stuff for universal tracker support, can be ignored for standard gen
if hasattr(self.multiworld, "re_gen_passthrough"):
if "TUNIC" in self.multiworld.re_gen_passthrough:
passthrough = self.multiworld.re_gen_passthrough["TUNIC"]
self.ability_unlocks["Pages 24-25 (Prayer)"] = passthrough["Hexagon Quest Prayer"]
self.ability_unlocks["Pages 42-43 (Holy Cross)"] = passthrough["Hexagon Quest Holy Cross"]
self.ability_unlocks["Pages 52-53 (Icebolt)"] = passthrough["Hexagon Quest Icebolt"]
if self.using_ut:
self.ability_unlocks["Pages 24-25 (Prayer)"] = self.passthrough["Hexagon Quest Prayer"]
self.ability_unlocks["Pages 42-43 (Holy Cross)"] = self.passthrough["Hexagon Quest Holy Cross"]
self.ability_unlocks["Pages 52-53 (Icebolt)"] = self.passthrough["Hexagon Quest Icebolt"]

# ladder rando uses ER with vanilla connections, so that we're not managing more rules files
if self.options.entrance_rando or self.options.shuffle_ladders:
Expand Down
57 changes: 27 additions & 30 deletions worlds/tunic/er_scripts.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ def pair_portals(world: "TunicWorld") -> Dict[Portal, Portal]:
laurels_location = "10_fairies" if seed_group["laurels_at_10_fairies"] is True else False

# marking that you don't immediately have laurels
if laurels_location == "10_fairies" and not hasattr(world.multiworld, "re_gen_passthrough"):
if laurels_location == "10_fairies" and not world.using_ut:
has_laurels = False

shop_scenes: Set[str] = set()
Expand All @@ -163,9 +163,8 @@ def pair_portals(world: "TunicWorld") -> Dict[Portal, Portal]:
break

# If using Universal Tracker, restore portal_map. Could be cleaner, but it does not matter for UT even a little bit
if hasattr(world.multiworld, "re_gen_passthrough"):
if "TUNIC" in world.multiworld.re_gen_passthrough:
portal_map = portal_mapping.copy()
if world.using_ut:
portal_map = portal_mapping.copy()

# create separate lists for dead ends and non-dead ends
for portal in portal_map:
Expand Down Expand Up @@ -204,25 +203,24 @@ def pair_portals(world: "TunicWorld") -> Dict[Portal, Portal]:
plando_connections = world.seed_groups[world.options.entrance_rando.value]["plando"]

# universal tracker support stuff, don't need to care about region dependency
if hasattr(world.multiworld, "re_gen_passthrough"):
if "TUNIC" in world.multiworld.re_gen_passthrough:
plando_connections.clear()
# universal tracker stuff, won't do anything in normal gen
for portal1, portal2 in world.multiworld.re_gen_passthrough["TUNIC"]["Entrance Rando"].items():
portal_name1 = ""
portal_name2 = ""

for portal in portal_mapping:
if portal.scene_destination() == portal1:
portal_name1 = portal.name
# connected_regions.update(add_dependent_regions(portal.region, logic_rules))
if portal.scene_destination() == portal2:
portal_name2 = portal.name
# connected_regions.update(add_dependent_regions(portal.region, logic_rules))
# shops have special handling
if not portal_name2 and portal2 == "Shop, Previous Region_":
portal_name2 = "Shop Portal"
plando_connections.append(PlandoConnection(portal_name1, portal_name2, "both"))
if world.using_ut:
plando_connections.clear()
# universal tracker stuff, won't do anything in normal gen
for portal1, portal2 in world.passthrough["Entrance Rando"].items():
portal_name1 = ""
portal_name2 = ""

for portal in portal_mapping:
if portal.scene_destination() == portal1:
portal_name1 = portal.name
# connected_regions.update(add_dependent_regions(portal.region, logic_rules))
if portal.scene_destination() == portal2:
portal_name2 = portal.name
# connected_regions.update(add_dependent_regions(portal.region, logic_rules))
# shops have special handling
if not portal_name2 and portal2 == "Shop, Previous Region_":
portal_name2 = "Shop Portal"
plando_connections.append(PlandoConnection(portal_name1, portal_name2, "both"))

non_dead_end_regions = set()
for region_name, region_info in tunic_er_regions.items():
Expand Down Expand Up @@ -333,7 +331,7 @@ def pair_portals(world: "TunicWorld") -> Dict[Portal, Portal]:
# if we have plando connections, our connected regions may change somewhat
connected_regions = update_reachable_regions(connected_regions, traversal_reqs, has_laurels, logic_rules)

if fixed_shop and not hasattr(world.multiworld, "re_gen_passthrough"):
if fixed_shop and not world.using_ut:
portal1 = None
for portal in two_plus:
if portal.scene_destination() == "Overworld Redux, Windmill_":
Expand Down Expand Up @@ -361,7 +359,7 @@ def pair_portals(world: "TunicWorld") -> Dict[Portal, Portal]:
fail_count = 0
while len(connected_regions) < len(non_dead_end_regions):
# if this is universal tracker, just break immediately and move on
if hasattr(world.multiworld, "re_gen_passthrough"):
if world.using_ut:
break
# if the connected regions length stays unchanged for too long, it's stuck in a loop
# should, hopefully, only ever occur if someone plandos connections poorly
Expand Down Expand Up @@ -413,9 +411,8 @@ def pair_portals(world: "TunicWorld") -> Dict[Portal, Portal]:
random_object.shuffle(two_plus)

# for universal tracker, we want to skip shop gen
if hasattr(world.multiworld, "re_gen_passthrough"):
if "TUNIC" in world.multiworld.re_gen_passthrough:
shop_count = 0
if world.using_ut:
shop_count = 0

for i in range(shop_count):
portal1 = None
Expand All @@ -434,15 +431,15 @@ def pair_portals(world: "TunicWorld") -> Dict[Portal, Portal]:
# connect dead ends to random non-dead ends
# none of the key events are in dead ends, so we don't need to do gate_before_switch
while len(dead_ends) > 0:
if hasattr(world.multiworld, "re_gen_passthrough"):
if world.using_ut:
break
portal1 = two_plus.pop()
portal2 = dead_ends.pop()
portal_pairs[portal1] = portal2
# then randomly connect the remaining portals to each other
# every region is accessible, so gate_before_switch is not necessary
while len(two_plus) > 1:
if hasattr(world.multiworld, "re_gen_passthrough"):
if world.using_ut:
break
portal1 = two_plus.pop()
portal2 = two_plus.pop()
Expand Down
Loading