mirror of
https://github.com/ArchipelagoMW/Archipelago.git
synced 2026-03-29 19:03:25 -07:00
Add decoupled option, mess with plando connection stuff
This commit is contained in:
@@ -54,6 +54,7 @@ class SeedGroup(TypedDict):
|
||||
ladder_storage: int # ls value
|
||||
laurels_at_10_fairies: bool # laurels location value
|
||||
entrance_layout: int # entrance layout value
|
||||
decoupled: bool
|
||||
plando: TunicPlandoConnections # consolidated plando connections for the seed group
|
||||
|
||||
|
||||
@@ -113,6 +114,7 @@ class TunicWorld(World):
|
||||
self.options.entrance_rando.value = passthrough["entrance_rando"]
|
||||
self.options.shuffle_ladders.value = passthrough["shuffle_ladders"]
|
||||
self.options.entrance_layout.value = EntranceLayout.option_standard
|
||||
self.options.decoupled = passthrough["decoupled"]
|
||||
self.options.laurels_location.value = LaurelsLocation.option_anywhere
|
||||
self.options.combat_logic.value = passthrough["combat_logic"]
|
||||
|
||||
@@ -132,7 +134,8 @@ class TunicWorld(World):
|
||||
ladder_storage=tunic.options.ladder_storage.value,
|
||||
laurels_at_10_fairies=tunic.options.laurels_location == LaurelsLocation.option_10_fairies,
|
||||
entrance_layout=tunic.options.entrance_layout.value,
|
||||
plando=multiworld.plando_connections[tunic.player])
|
||||
decoupled=bool(tunic.options.decoupled),
|
||||
plando=tunic.options.plando_connections)
|
||||
continue
|
||||
|
||||
# off is more restrictive
|
||||
@@ -154,33 +157,41 @@ class TunicWorld(World):
|
||||
elif cls.seed_groups[group]["entrance_layout"] != tunic.options.entrance_layout.value:
|
||||
raise OptionError(f"TUNIC: Conflict between seed group {group}'s Entrance Layout options. "
|
||||
f"Seed group cannot have both Fixed Shop and Direction Pairs enabled.")
|
||||
|
||||
# todo: make it break if you don't have matching portal directions with direction pairs on
|
||||
if multiworld.plando_connections[tunic.player]:
|
||||
# decoupled loses to coupled, I could instead make this fail but eh
|
||||
if not tunic.options.decoupled:
|
||||
cls.seed_groups[group]["decoupled"] = False
|
||||
if tunic.options.plando_connections:
|
||||
# loop through the connections in the player's yaml
|
||||
for cxn in multiworld.plando_connections[tunic.player]:
|
||||
for cxn in tunic.options.plando_connections:
|
||||
new_cxn = True
|
||||
# if they used the entrance direction, just swap it around
|
||||
if cxn.direction == "entrance" and cls.seed_groups[group]["decoupled"]:
|
||||
player_cxn = PlandoConnection(entrance=cxn.exit, exit=cxn.entrance, direction="exit", percentage=cxn.percentage)
|
||||
else:
|
||||
player_cxn = cxn
|
||||
for group_cxn in cls.seed_groups[group]["plando"]:
|
||||
# if neither entrance nor exit match anything in the group, add to group
|
||||
if ((cxn.entrance == group_cxn.entrance and cxn.exit == group_cxn.exit)
|
||||
or (cxn.exit == group_cxn.entrance and cxn.entrance == group_cxn.exit)):
|
||||
if ((player_cxn.entrance == group_cxn.entrance and player_cxn.exit == group_cxn.exit)
|
||||
# if decoupled is off, the entrance and exit can be swapped
|
||||
or (player_cxn.exit == group_cxn.entrance and player_cxn.entrance == group_cxn.exit
|
||||
and not cls.seed_groups[group]["decoupled"])):
|
||||
new_cxn = False
|
||||
break
|
||||
|
||||
|
||||
# check if this pair is the same as a pair in the group already
|
||||
is_mismatched = (
|
||||
cxn.entrance == group_cxn.entrance and cxn.exit != group_cxn.exit
|
||||
or cxn.entrance == group_cxn.exit and cxn.exit != group_cxn.entrance
|
||||
or cxn.exit == group_cxn.entrance and cxn.entrance != group_cxn.exit
|
||||
or cxn.exit == group_cxn.exit and cxn.entrance != group_cxn.entrance
|
||||
player_cxn.entrance == group_cxn.entrance and player_cxn.exit != group_cxn.exit
|
||||
or player_cxn.entrance == group_cxn.exit and player_cxn.exit != group_cxn.entrance
|
||||
or player_cxn.exit == group_cxn.entrance and player_cxn.entrance != group_cxn.exit
|
||||
or player_cxn.exit == group_cxn.exit and player_cxn.entrance != group_cxn.entrance
|
||||
)
|
||||
if is_mismatched:
|
||||
raise OptionError(f"TUNIC: Conflict between seed group {group}'s plando "
|
||||
f"connection {group_cxn.entrance} <-> {group_cxn.exit} and "
|
||||
f"{tunic.multiworld.get_player_name(tunic.player)}'s plando "
|
||||
f"connection {cxn.entrance} <-> {cxn.exit}")
|
||||
f"connection {player_cxn.entrance} <-> {player_cxn.exit}")
|
||||
if new_cxn:
|
||||
cls.seed_groups[group]["plando"].value.append(cxn)
|
||||
cls.seed_groups[group]["plando"].value.append(player_cxn)
|
||||
|
||||
def create_item(self, name: str, classification: ItemClassification = None) -> TunicItem:
|
||||
item_data = item_table[name]
|
||||
@@ -400,6 +411,7 @@ class TunicWorld(World):
|
||||
"lanternless": self.options.lanternless.value,
|
||||
"maskless": self.options.maskless.value,
|
||||
"entrance_rando": int(bool(self.options.entrance_rando.value)),
|
||||
"decoupled": self.options.decoupled.value,
|
||||
"shuffle_ladders": self.options.shuffle_ladders.value,
|
||||
"combat_logic": self.options.combat_logic.value,
|
||||
"Hexagon Quest Prayer": self.ability_unlocks["Pages 24-25 (Prayer)"],
|
||||
|
||||
@@ -557,3 +557,53 @@ def update_reachable_regions(connected_regions: Set[str], traversal_reqs: Dict[s
|
||||
connected_regions = update_reachable_regions(connected_regions, traversal_reqs, has_laurels, logic)
|
||||
|
||||
return connected_regions
|
||||
|
||||
|
||||
# which directions are opposites
|
||||
direction_pairs: Dict[int, int] = {
|
||||
Direction.north: Direction.south,
|
||||
Direction.south: Direction.north,
|
||||
Direction.east: Direction.west,
|
||||
Direction.west: Direction.east,
|
||||
Direction.ladder_up: Direction.ladder_down,
|
||||
Direction.ladder_down: Direction.ladder_up,
|
||||
Direction.floor: Direction.floor,
|
||||
}
|
||||
|
||||
|
||||
# verify that two portals are in compatible directions
|
||||
def verify_direction_pair(portal1: Portal, portal2: Portal) -> bool:
|
||||
if portal1.direction == direction_pairs[portal2.direction]:
|
||||
return True
|
||||
elif portal1.name.startswith("Shop"):
|
||||
if portal2.direction in [Direction.north, Direction.east]:
|
||||
return True
|
||||
elif portal2.name.startswith("Shop"):
|
||||
if portal1.direction in [Direction.north, Direction.east]:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
# verify that two plando'd portals are in compatible directions
|
||||
def verify_plando_directions(connection: PlandoConnection) -> bool:
|
||||
entrance_portal = None
|
||||
exit_portal = None
|
||||
for portal in portal_mapping:
|
||||
if connection.entrance == portal.name:
|
||||
entrance_portal = portal
|
||||
if connection.exit == portal.name:
|
||||
exit_portal = portal
|
||||
if entrance_portal and exit_portal:
|
||||
if entrance_portal.direction == direction_pairs[exit_portal.direction]:
|
||||
return True
|
||||
# this is two shop portals, they can never pair directions
|
||||
elif not entrance_portal and not exit_portal:
|
||||
return False
|
||||
# if one of them is none, it's a shop, which has two possible directions
|
||||
elif not entrance_portal:
|
||||
if exit_portal.direction in [Direction.north, Direction.east]:
|
||||
return True
|
||||
elif not exit_portal:
|
||||
if entrance_portal.direction in [Direction.north, Direction.east]:
|
||||
return True
|
||||
|
||||
@@ -146,6 +146,15 @@ class EntranceLayout(Choice):
|
||||
default = 0
|
||||
|
||||
|
||||
class Decoupled(Toggle):
|
||||
"""
|
||||
Decouple the entrances, so that when you go from one entrance to another, the return trip won't necessarily bring you back to the same place.
|
||||
Note: For seed groups, if any player in a seed group does not have Decoupled enabled, no one in the seed group will have Decoupled entrances.
|
||||
"""
|
||||
internal_name = "decoupled"
|
||||
display_name = "Decoupled Entrances"
|
||||
|
||||
|
||||
class LaurelsLocation(Choice):
|
||||
"""
|
||||
Force the Hero's Laurels to be placed at a location in your world.
|
||||
@@ -176,7 +185,9 @@ class TunicPlandoConnections(PlandoConnections):
|
||||
Generic connection plando. Format is:
|
||||
- entrance: "Entrance Name"
|
||||
exit: "Exit Name"
|
||||
direction: "Direction"
|
||||
percentage: 100
|
||||
Direction must be one of 'entrance', 'exit', or 'both', and defaults to 'both' if omitted.
|
||||
Percentage is an integer from 0 to 100 which determines whether that connection will be made. Defaults to 100 if omitted.
|
||||
If the Entrance Layout option is set to Standard or Fixed Shop, you can plando multiple shops.
|
||||
Note that you will wrong warp if you have multiple shops in the same scene.
|
||||
@@ -272,6 +283,7 @@ class TunicOptions(PerGameCommonOptions):
|
||||
shuffle_ladders: ShuffleLadders
|
||||
entrance_rando: EntranceRando
|
||||
entrance_layout: EntranceLayout
|
||||
decoupled: Decoupled
|
||||
plando_connections: TunicPlandoConnections
|
||||
fool_traps: FoolTraps
|
||||
hexagon_quest: HexagonQuest
|
||||
@@ -298,8 +310,14 @@ tunic_option_groups = [
|
||||
LaurelsZips,
|
||||
IceGrappling,
|
||||
LadderStorage,
|
||||
LadderStorageWithoutItems
|
||||
])
|
||||
LadderStorageWithoutItems,
|
||||
]),
|
||||
OptionGroup("Entrance Randomizer", [
|
||||
EntranceRando,
|
||||
EntranceLayout,
|
||||
Decoupled,
|
||||
PlandoConnections,
|
||||
]),
|
||||
]
|
||||
|
||||
tunic_option_presets: Dict[str, Dict[str, Any]] = {
|
||||
|
||||
Reference in New Issue
Block a user