TUNIC: Fix plando connections, seed groups, and UT support (#3429)
This commit is contained in:
parent
d9120f0bea
commit
70e9ccb13c
|
@ -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]
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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 = [
|
||||||
|
|
Loading…
Reference in New Issue