TUNIC: Fix plando connections, seed groups, and UT support (#3429)

This commit is contained in:
Scipio Wright 2024-06-03 04:44:37 -04:00 committed by GitHub
parent d9120f0bea
commit 70e9ccb13c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 27 additions and 20 deletions

View File

@ -8,7 +8,7 @@ from .er_rules import set_er_location_rules
from .regions import tunic_regions from .regions import tunic_regions
from .er_scripts import create_er_regions from .er_scripts import create_er_regions
from .er_data import portal_mapping from .er_data import portal_mapping
from .options import TunicOptions, EntranceRando, tunic_option_groups, tunic_option_presets from .options import TunicOptions, EntranceRando, tunic_option_groups, tunic_option_presets, TunicPlandoConnections
from worlds.AutoWorld import WebWorld, World from worlds.AutoWorld import WebWorld, World
from Options import PlandoConnection from Options import PlandoConnection
from decimal import Decimal, ROUND_HALF_UP from decimal import Decimal, ROUND_HALF_UP
@ -43,7 +43,7 @@ class SeedGroup(TypedDict):
logic_rules: int # logic rules value logic_rules: int # logic rules value
laurels_at_10_fairies: bool # laurels location value laurels_at_10_fairies: bool # laurels location value
fixed_shop: bool # fixed shop value fixed_shop: bool # fixed shop value
plando: List[PlandoConnection] # consolidated list of plando connections for the seed group plando: TunicPlandoConnections # consolidated of plando connections for the seed group
class TunicWorld(World): class TunicWorld(World):
@ -96,13 +96,15 @@ class TunicWorld(World):
self.options.hexagon_quest.value = passthrough["hexagon_quest"] self.options.hexagon_quest.value = passthrough["hexagon_quest"]
self.options.entrance_rando.value = passthrough["entrance_rando"] self.options.entrance_rando.value = passthrough["entrance_rando"]
self.options.shuffle_ladders.value = passthrough["shuffle_ladders"] self.options.shuffle_ladders.value = 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
@classmethod @classmethod
def stage_generate_early(cls, multiworld: MultiWorld) -> None: def stage_generate_early(cls, multiworld: MultiWorld) -> None:
tunic_worlds: Tuple[TunicWorld] = multiworld.get_game_worlds("TUNIC") tunic_worlds: Tuple[TunicWorld] = multiworld.get_game_worlds("TUNIC")
for tunic in tunic_worlds: for tunic in tunic_worlds:
# if it's one of the options, then it isn't a custom seed group # if it's one of the options, then it isn't a custom seed group
if tunic.options.entrance_rando.value in EntranceRando.options: if tunic.options.entrance_rando.value in EntranceRando.options.values():
continue continue
group = tunic.options.entrance_rando.value group = tunic.options.entrance_rando.value
# if this is the first world in the group, set the rules equal to its rules # if this is the first world in the group, set the rules equal to its rules
@ -147,7 +149,7 @@ class TunicWorld(World):
f"{tunic.multiworld.get_player_name(tunic.player)}'s plando " f"{tunic.multiworld.get_player_name(tunic.player)}'s plando "
f"connection {cxn.entrance} <-> {cxn.exit}") f"connection {cxn.entrance} <-> {cxn.exit}")
if new_cxn: if new_cxn:
cls.seed_groups[group]["plando"].append(cxn) cls.seed_groups[group]["plando"].value.append(cxn)
def create_item(self, name: str) -> TunicItem: def create_item(self, name: str) -> TunicItem:
item_data = item_table[name] item_data = item_table[name]

View File

@ -140,7 +140,7 @@ def pair_portals(world: "TunicWorld") -> Dict[Portal, Portal]:
waterfall_plando = False waterfall_plando = False
# if it's not one of the EntranceRando options, it's a custom seed # if it's not one of the EntranceRando options, it's a custom seed
if world.options.entrance_rando.value not in EntranceRando.options: if world.options.entrance_rando.value not in EntranceRando.options.values():
seed_group = world.seed_groups[world.options.entrance_rando.value] seed_group = world.seed_groups[world.options.entrance_rando.value]
logic_rules = seed_group["logic_rules"] logic_rules = seed_group["logic_rules"]
fixed_shop = seed_group["fixed_shop"] fixed_shop = seed_group["fixed_shop"]
@ -162,6 +162,11 @@ def pair_portals(world: "TunicWorld") -> Dict[Portal, Portal]:
portal_map.remove(portal) portal_map.remove(portal)
break 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()
# create separate lists for dead ends and non-dead ends # create separate lists for dead ends and non-dead ends
for portal in portal_map: for portal in portal_map:
dead_end_status = tunic_er_regions[portal.region].dead_end dead_end_status = tunic_er_regions[portal.region].dead_end
@ -193,7 +198,7 @@ def pair_portals(world: "TunicWorld") -> Dict[Portal, Portal]:
connected_regions.add(start_region) connected_regions.add(start_region)
connected_regions = update_reachable_regions(connected_regions, traversal_reqs, has_laurels, logic_rules) connected_regions = update_reachable_regions(connected_regions, traversal_reqs, has_laurels, logic_rules)
if world.options.entrance_rando.value in EntranceRando.options: if world.options.entrance_rando.value in EntranceRando.options.values():
plando_connections = world.options.plando_connections.value plando_connections = world.options.plando_connections.value
else: else:
plando_connections = world.seed_groups[world.options.entrance_rando.value]["plando"] plando_connections = world.seed_groups[world.options.entrance_rando.value]["plando"]
@ -255,7 +260,7 @@ def pair_portals(world: "TunicWorld") -> Dict[Portal, Portal]:
else: else:
# if not both, they're both dead ends # if not both, they're both dead ends
if not portal2: if not portal2:
if world.options.entrance_rando.value not in EntranceRando.options: if world.options.entrance_rando.value not in EntranceRando.options.values():
raise Exception(f"Tunic ER seed group {world.options.entrance_rando.value} paired a dead " raise Exception(f"Tunic ER seed group {world.options.entrance_rando.value} paired a dead "
"end to a dead end in their plando connections.") "end to a dead end in their plando connections.")
else: else:
@ -302,21 +307,21 @@ def pair_portals(world: "TunicWorld") -> Dict[Portal, Portal]:
traversal_reqs.setdefault(portal1.region, dict())[portal2.region] = [] traversal_reqs.setdefault(portal1.region, dict())[portal2.region] = []
traversal_reqs.setdefault(portal2.region, dict())[portal1.region] = [] traversal_reqs.setdefault(portal2.region, dict())[portal1.region] = []
if portal1.region == "Zig Skip Exit" or portal2.region == "Zig Skip Exit": if (portal1.region == "Zig Skip Exit" and (portal2_dead_end or portal2.region == "Secret Gathering Place")
if portal1_dead_end or portal2_dead_end or \ or portal2.region == "Zig Skip Exit" and (portal1_dead_end or portal1.region == "Secret Gathering Place")):
portal1.region == "Secret Gathering Place" or portal2.region == "Secret Gathering Place": if world.options.entrance_rando.value not in EntranceRando.options.values():
if world.options.entrance_rando.value not in EntranceRando.options:
raise Exception(f"Tunic ER seed group {world.options.entrance_rando.value} paired a dead " raise Exception(f"Tunic ER seed group {world.options.entrance_rando.value} paired a dead "
"end to a dead end in their plando connections.") "end to a dead end in their plando connections.")
else: else:
raise Exception(f"{player_name} paired a dead end to a dead end in their " raise Exception(f"{player_name} paired a dead end to a dead end in their "
"plando connections.") "plando connections.")
if portal1.region == "Secret Gathering Place" or portal2.region == "Secret Gathering Place": if (portal1.region == "Secret Gathering Place" and (portal2_dead_end or portal2.region == "Zig Skip Exit")
or portal2.region == "Secret Gathering Place" and (portal1_dead_end or portal1.region == "Zig Skip Exit")):
# need to make sure you didn't pair this to a dead end or zig skip # need to make sure you didn't pair this to a dead end or zig skip
if portal1_dead_end or portal2_dead_end or \ if portal1_dead_end or portal2_dead_end or \
portal1.region == "Zig Skip Exit" or portal2.region == "Zig Skip Exit": portal1.region == "Zig Skip Exit" or portal2.region == "Zig Skip Exit":
if world.options.entrance_rando.value not in EntranceRando.options: if world.options.entrance_rando.value not in EntranceRando.options.values():
raise Exception(f"Tunic ER seed group {world.options.entrance_rando.value} paired a dead " raise Exception(f"Tunic ER seed group {world.options.entrance_rando.value} paired a dead "
"end to a dead end in their plando connections.") "end to a dead end in their plando connections.")
else: else:

View File

@ -173,7 +173,7 @@ class ShuffleLadders(Toggle):
display_name = "Shuffle Ladders" display_name = "Shuffle Ladders"
class TUNICPlandoConnections(PlandoConnections): class TunicPlandoConnections(PlandoConnections):
entrances = {*(portal.name for portal in portal_mapping), "Shop", "Shop Portal"} entrances = {*(portal.name for portal in portal_mapping), "Shop", "Shop Portal"}
exits = {*(portal.name for portal in portal_mapping), "Shop", "Shop Portal"} exits = {*(portal.name for portal in portal_mapping), "Shop", "Shop Portal"}
@ -198,7 +198,7 @@ class TunicOptions(PerGameCommonOptions):
lanternless: Lanternless lanternless: Lanternless
maskless: Maskless maskless: Maskless
laurels_location: LaurelsLocation laurels_location: LaurelsLocation
plando_connections: TUNICPlandoConnections plando_connections: TunicPlandoConnections
tunic_option_groups = [ tunic_option_groups = [