diff options
Diffstat (limited to 'apworld')
| -rw-r--r-- | apworld/__init__.py | 11 | ||||
| -rw-r--r-- | apworld/client/gamedata.gd | 4 | ||||
| -rw-r--r-- | apworld/client/manager.gd | 4 | ||||
| -rw-r--r-- | apworld/client/player.gd | 113 | ||||
| -rw-r--r-- | apworld/context.py | 31 | ||||
| -rw-r--r-- | apworld/player_logic.py | 3 | ||||
| -rw-r--r-- | apworld/static_logic.py | 9 | ||||
| -rw-r--r-- | apworld/tracker.py | 5 |
8 files changed, 131 insertions, 49 deletions
| diff --git a/apworld/__init__.py b/apworld/__init__.py index f5774c6..3d2f075 100644 --- a/apworld/__init__.py +++ b/apworld/__init__.py | |||
| @@ -77,7 +77,10 @@ class Lingo2World(World): | |||
| 77 | if self.options.shuffle_worldports: | 77 | if self.options.shuffle_worldports: |
| 78 | if hasattr(self.multiworld, "re_gen_passthrough") and "Lingo 2" in self.multiworld.re_gen_passthrough: | 78 | if hasattr(self.multiworld, "re_gen_passthrough") and "Lingo 2" in self.multiworld.re_gen_passthrough: |
| 79 | slot_value = self.multiworld.re_gen_passthrough["Lingo 2"]["port_pairings"] | 79 | slot_value = self.multiworld.re_gen_passthrough["Lingo 2"]["port_pairings"] |
| 80 | self.port_pairings = {int(fp): int(tp) for fp, tp in slot_value.items()} | 80 | self.port_pairings = { |
| 81 | self.static_logic.port_id_by_ap_id[int(fp)]: self.static_logic.port_id_by_ap_id[int(tp)] | ||
| 82 | for fp, tp in slot_value.items() | ||
| 83 | } | ||
| 81 | 84 | ||
| 82 | connect_ports_from_ut(self.port_pairings, self) | 85 | connect_ports_from_ut(self.port_pairings, self) |
| 83 | else: | 86 | else: |
| @@ -152,7 +155,11 @@ class Lingo2World(World): | |||
| 152 | } | 155 | } |
| 153 | 156 | ||
| 154 | if self.options.shuffle_worldports: | 157 | if self.options.shuffle_worldports: |
| 155 | slot_data["port_pairings"] = self.port_pairings | 158 | def get_port_ap_id(port_id): |
| 159 | return self.static_logic.objects.ports[port_id].ap_id | ||
| 160 | |||
| 161 | slot_data["port_pairings"] = {get_port_ap_id(from_id): get_port_ap_id(to_id) | ||
| 162 | for from_id, to_id in self.port_pairings.items()} | ||
| 156 | 163 | ||
| 157 | return slot_data | 164 | return slot_data |
| 158 | 165 | ||
| diff --git a/apworld/client/gamedata.gd b/apworld/client/gamedata.gd index 3a35125..d7e3136 100644 --- a/apworld/client/gamedata.gd +++ b/apworld/client/gamedata.gd | |||
| @@ -15,6 +15,7 @@ var symbol_item_ids = [] | |||
| 15 | var anti_trap_ids = {} | 15 | var anti_trap_ids = {} |
| 16 | var location_name_by_id = {} | 16 | var location_name_by_id = {} |
| 17 | var ending_display_name_by_name = {} | 17 | var ending_display_name_by_name = {} |
| 18 | var port_id_by_ap_id = {} | ||
| 18 | 19 | ||
| 19 | var kSYMBOL_ITEMS | 20 | var kSYMBOL_ITEMS |
| 20 | 21 | ||
| @@ -99,6 +100,9 @@ func load(data_bytes): | |||
| 99 | var map_data = port_id_by_map_node_path[map.get_name()] | 100 | var map_data = port_id_by_map_node_path[map.get_name()] |
| 100 | map_data[port.get_path()] = port.get_id() | 101 | map_data[port.get_path()] = port.get_id() |
| 101 | 102 | ||
| 103 | if port.has_ap_id(): | ||
| 104 | port_id_by_ap_id[port.get_ap_id()] = port.get_id() | ||
| 105 | |||
| 102 | for progressive in objects.get_progressives(): | 106 | for progressive in objects.get_progressives(): |
| 103 | progressive_id_by_ap_id[progressive.get_ap_id()] = progressive.get_id() | 107 | progressive_id_by_ap_id[progressive.get_ap_id()] = progressive.get_id() |
| 104 | 108 | ||
| diff --git a/apworld/client/manager.gd b/apworld/client/manager.gd index aa07559..727d17a 100644 --- a/apworld/client/manager.gd +++ b/apworld/client/manager.gd | |||
| @@ -472,7 +472,9 @@ func _client_connected(slot_data): | |||
| 472 | var raw_pp = slot_data.get("port_pairings") | 472 | var raw_pp = slot_data.get("port_pairings") |
| 473 | 473 | ||
| 474 | for p1 in raw_pp.keys(): | 474 | for p1 in raw_pp.keys(): |
| 475 | port_pairings[int(p1)] = int(raw_pp[p1]) | 475 | port_pairings[gamedata.port_id_by_ap_id[int(p1)]] = gamedata.port_id_by_ap_id[int( |
| 476 | raw_pp[p1] | ||
| 477 | )] | ||
| 476 | 478 | ||
| 477 | # Set up item locks. | 479 | # Set up item locks. |
| 478 | _item_locks = {} | 480 | _item_locks = {} |
| diff --git a/apworld/client/player.gd b/apworld/client/player.gd index 712a59b..65bf54e 100644 --- a/apworld/client/player.gd +++ b/apworld/client/player.gd | |||
| @@ -98,38 +98,72 @@ func _ready(): | |||
| 98 | old_door.queue_free() | 98 | old_door.queue_free() |
| 99 | get_node("/root/scene/Components/Doors").add_child.call_deferred(new_door) | 99 | get_node("/root/scene/Components/Doors").add_child.call_deferred(new_door) |
| 100 | 100 | ||
| 101 | # Block off roof access in Daedalus. | 101 | if global.map == "daedalus": |
| 102 | if global.map == "daedalus" and not ap.daedalus_roof_access: | 102 | # Teleport the direction panels when the stairs are there. |
| 103 | _set_up_invis_wall(75.5, 11, -24.5, 1, 10, 49) | 103 | var tpl_prefab = preload("res://objects/nodes/listeners/teleportListener.tscn") |
| 104 | _set_up_invis_wall(51.5, 11, -17, 16, 10, 1) | 104 | |
| 105 | _set_up_invis_wall(46, 10, -9.5, 1, 10, 10) | 105 | var dir1 = get_node("/root/scene/Panels/Castle Entrance/castle_direction_1") |
| 106 | _set_up_invis_wall(67.5, 11, 17, 16, 10, 1) | 106 | var dir1_tpl = tpl_prefab.instantiate() |
| 107 | _set_up_invis_wall(50.5, 11, 14, 10, 10, 1) | 107 | dir1_tpl.target_path = dir1 |
| 108 | _set_up_invis_wall(39, 10, 18.5, 1, 10, 22) | 108 | dir1_tpl.teleport_point = Vector3(59.5, 8, -6.5) |
| 109 | _set_up_invis_wall(20, 15, 18.5, 1, 10, 16) | 109 | dir1_tpl.teleport_rotate = Vector3(-45, 0, 0) |
| 110 | _set_up_invis_wall(11.5, 15, 3, 32, 10, 1) | 110 | dir1_tpl.senders.append(NodePath("/root/scene/Panels/Castle Entrance/castle_south")) |
| 111 | _set_up_invis_wall(11.5, 16, -20, 14, 20, 1) | 111 | dir1_tpl.senders.append(NodePath("/root/scene/Panels/Castle Entrance/castle_north")) |
| 112 | _set_up_invis_wall(14, 16, -26.5, 1, 20, 4) | 112 | dir1_tpl.senders.append(NodePath("/root/scene/Panels/Castle Entrance/castle_west")) |
| 113 | _set_up_invis_wall(28.5, 20.5, -26.5, 1, 15, 25) | 113 | dir1.add_child.call_deferred(dir1_tpl) |
| 114 | _set_up_invis_wall(40.5, 20.5, -11, 30, 15, 1) | 114 | |
| 115 | _set_up_invis_wall(50.5, 15, 5.5, 7, 10, 1) | 115 | var dir2 = get_node("/root/scene/Panels/Castle Entrance/castle_direction_2") |
| 116 | _set_up_invis_wall(83.5, 33.5, 5.5, 1, 7, 11) | 116 | var dir2_tpl = tpl_prefab.instantiate() |
| 117 | _set_up_invis_wall(83.5, 33.5, -5.5, 1, 7, 11) | 117 | dir2_tpl.target_path = dir2 |
| 118 | 118 | dir2_tpl.teleport_point = Vector3(59.5, 8, 6.5) | |
| 119 | var warp_exit_prefab = preload("res://objects/nodes/exit.tscn") | 119 | dir2_tpl.teleport_rotate = Vector3(-45, -180, 0) |
| 120 | var warp_exit = warp_exit_prefab.instantiate() | 120 | dir2_tpl.senders.append(NodePath("/root/scene/Panels/Castle Entrance/castle_south")) |
| 121 | warp_exit.name = "roof_access_blocker_warp_exit" | 121 | dir2_tpl.senders.append(NodePath("/root/scene/Panels/Castle Entrance/castle_north")) |
| 122 | warp_exit.position = Vector3(58, 10, 0) | 122 | dir2_tpl.senders.append(NodePath("/root/scene/Panels/Castle Entrance/castle_west")) |
| 123 | warp_exit.rotation_degrees.y = 90 | 123 | dir2.add_child.call_deferred(dir2_tpl) |
| 124 | get_parent().add_child.call_deferred(warp_exit) | 124 | |
| 125 | 125 | var dir3 = get_node("/root/scene/Panels/Castle Entrance/castle_direction_3") | |
| 126 | var warp_enter_prefab = preload("res://objects/nodes/teleportAuto.tscn") | 126 | var dir3_tpl = tpl_prefab.instantiate() |
| 127 | var warp_enter = warp_enter_prefab.instantiate() | 127 | dir3_tpl.target_path = dir3 |
| 128 | warp_enter.target = warp_exit | 128 | dir3_tpl.teleport_point = Vector3(54, 8, 0) |
| 129 | warp_enter.position = Vector3(76.5, 30, 1) | 129 | dir3_tpl.teleport_rotate = Vector3(-45, 90, 0) |
| 130 | warp_enter.scale = Vector3(4, 1.5, 1) | 130 | dir3_tpl.senders.append(NodePath("/root/scene/Panels/Castle Entrance/castle_south")) |
| 131 | warp_enter.rotation_degrees.y = 90 | 131 | dir3_tpl.senders.append(NodePath("/root/scene/Panels/Castle Entrance/castle_north")) |
| 132 | get_parent().add_child.call_deferred(warp_enter) | 132 | dir3_tpl.senders.append(NodePath("/root/scene/Panels/Castle Entrance/castle_west")) |
| 133 | dir3.add_child.call_deferred(dir3_tpl) | ||
| 134 | |||
| 135 | # Block off roof access in Daedalus. | ||
| 136 | if not ap.daedalus_roof_access: | ||
| 137 | _set_up_invis_wall(75.5, 11, -24.5, 1, 10, 49) | ||
| 138 | _set_up_invis_wall(51.5, 11, -17, 16, 10, 1) | ||
| 139 | _set_up_invis_wall(46, 10, -9.5, 1, 10, 10) | ||
| 140 | _set_up_invis_wall(67.5, 11, 17, 16, 10, 1) | ||
| 141 | _set_up_invis_wall(50.5, 11, 14, 10, 10, 1) | ||
| 142 | _set_up_invis_wall(39, 10, 18.5, 1, 10, 22) | ||
| 143 | _set_up_invis_wall(20, 15, 18.5, 1, 10, 16) | ||
| 144 | _set_up_invis_wall(11.5, 15, 3, 32, 10, 1) | ||
| 145 | _set_up_invis_wall(11.5, 16, -20, 14, 20, 1) | ||
| 146 | _set_up_invis_wall(14, 16, -26.5, 1, 20, 4) | ||
| 147 | _set_up_invis_wall(28.5, 20.5, -26.5, 1, 15, 25) | ||
| 148 | _set_up_invis_wall(40.5, 20.5, -11, 30, 15, 1) | ||
| 149 | _set_up_invis_wall(50.5, 15, 5.5, 7, 10, 1) | ||
| 150 | _set_up_invis_wall(83.5, 33.5, 5.5, 1, 7, 11) | ||
| 151 | _set_up_invis_wall(83.5, 33.5, -5.5, 1, 7, 11) | ||
| 152 | |||
| 153 | var warp_exit_prefab = preload("res://objects/nodes/exit.tscn") | ||
| 154 | var warp_exit = warp_exit_prefab.instantiate() | ||
| 155 | warp_exit.name = "roof_access_blocker_warp_exit" | ||
| 156 | warp_exit.position = Vector3(58, 10, 0) | ||
| 157 | warp_exit.rotation_degrees.y = 90 | ||
| 158 | get_parent().add_child.call_deferred(warp_exit) | ||
| 159 | |||
| 160 | var warp_enter_prefab = preload("res://objects/nodes/teleportAuto.tscn") | ||
| 161 | var warp_enter = warp_enter_prefab.instantiate() | ||
| 162 | warp_enter.target = warp_exit | ||
| 163 | warp_enter.position = Vector3(76.5, 30, 1) | ||
| 164 | warp_enter.scale = Vector3(4, 1.5, 1) | ||
| 165 | warp_enter.rotation_degrees.y = 90 | ||
| 166 | get_parent().add_child.call_deferred(warp_enter) | ||
| 133 | 167 | ||
| 134 | if global.map == "the_entry": | 168 | if global.map == "the_entry": |
| 135 | # Remove door behind X1. | 169 | # Remove door behind X1. |
| @@ -586,6 +620,12 @@ func _ready(): | |||
| 586 | saver.senderGroup.append(NodePath("/root/scene/Components/Collectables")) | 620 | saver.senderGroup.append(NodePath("/root/scene/Components/Collectables")) |
| 587 | get_node("/root/scene").add_child.call_deferred(saver) | 621 | get_node("/root/scene").add_child.call_deferred(saver) |
| 588 | 622 | ||
| 623 | # Shrink the painting trigger in The Unyielding. | ||
| 624 | if global.map == "the_unyielding": | ||
| 625 | var trigger_area = get_node("/root/scene/Components/PaintingUnlocker/triggerArea") | ||
| 626 | trigger_area.position = Vector3(0, 0, -6) | ||
| 627 | trigger_area.scale = Vector3(6, 1, 6) | ||
| 628 | |||
| 589 | ap.update_job_well_done_sign() | 629 | ap.update_job_well_done_sign() |
| 590 | 630 | ||
| 591 | # Set up door locations. | 631 | # Set up door locations. |
| @@ -598,9 +638,12 @@ func _ready(): | |||
| 598 | continue | 638 | continue |
| 599 | 639 | ||
| 600 | if ( | 640 | if ( |
| 601 | door.get_type() == gamedata.SCRIPT_proto.DoorType.ITEM_ONLY | 641 | not (door.has_legacy_location() and door.get_legacy_location()) |
| 602 | or door.get_type() == gamedata.SCRIPT_proto.DoorType.GALLERY_PAINTING | 642 | and ( |
| 603 | or door.get_type() == gamedata.SCRIPT_proto.DoorType.CONTROL_CENTER_COLOR | 643 | door.get_type() == gamedata.SCRIPT_proto.DoorType.ITEM_ONLY |
| 644 | or door.get_type() == gamedata.SCRIPT_proto.DoorType.GALLERY_PAINTING | ||
| 645 | or door.get_type() == gamedata.SCRIPT_proto.DoorType.CONTROL_CENTER_COLOR | ||
| 646 | ) | ||
| 604 | ): | 647 | ): |
| 605 | continue | 648 | continue |
| 606 | 649 | ||
| diff --git a/apworld/context.py b/apworld/context.py index e2d80cd..52b04ae 100644 --- a/apworld/context.py +++ b/apworld/context.py | |||
| @@ -30,6 +30,16 @@ KEY_STORAGE_MAPPING = { | |||
| 30 | REVERSE_KEY_STORAGE_MAPPING = {t: k for k, t in KEY_STORAGE_MAPPING.items()} | 30 | REVERSE_KEY_STORAGE_MAPPING = {t: k for k, t in KEY_STORAGE_MAPPING.items()} |
| 31 | 31 | ||
| 32 | 32 | ||
| 33 | # There is a distinction between an object's ID and its AP ID. The latter is stable between releases, whereas the former | ||
| 34 | # can change and is also namespaced based on the object type. We should only store AP IDs in multiworld state (such as | ||
| 35 | # slot data and data storage) to increase compatability between releases. The data we currently store is: | ||
| 36 | # - Port pairings for worldport shuffle (slot data) | ||
| 37 | # - Checked worldports for worldport shuffle (data storage) | ||
| 38 | # - Latched doors (data storage) | ||
| 39 | # The client generally deals in the actual object IDs rather than the stable IDs, although it does have to convert the | ||
| 40 | # port pairing IDs when reading them from slot data. The context (this file here) does the work of converting back and | ||
| 41 | # forth between the values. AP IDs are converted to IDs after reading them from data storage, and IDs are converted to | ||
| 42 | # AP IDs before sending them to data storage. | ||
| 33 | class Lingo2Manager: | 43 | class Lingo2Manager: |
| 34 | game_ctx: "Lingo2GameContext" | 44 | game_ctx: "Lingo2GameContext" |
| 35 | client_ctx: "Lingo2ClientContext" | 45 | client_ctx: "Lingo2ClientContext" |
| @@ -74,6 +84,7 @@ class Lingo2Manager: | |||
| 74 | 84 | ||
| 75 | return ret | 85 | return ret |
| 76 | 86 | ||
| 87 | # Input should be real IDs, not AP IDs | ||
| 77 | def update_worldports(self, new_worldports: set[int]) -> set[int]: | 88 | def update_worldports(self, new_worldports: set[int]) -> set[int]: |
| 78 | ret = new_worldports.difference(self.worldports) | 89 | ret = new_worldports.difference(self.worldports) |
| 79 | self.worldports.update(new_worldports) | 90 | self.worldports.update(new_worldports) |
| @@ -227,6 +238,7 @@ class Lingo2GameContext: | |||
| 227 | 238 | ||
| 228 | async_start(self.send_msgs([msg]), name="update keyboard") | 239 | async_start(self.send_msgs([msg]), name="update keyboard") |
| 229 | 240 | ||
| 241 | # Input should be real IDs, not AP IDs | ||
| 230 | def send_update_worldports(self, worldports): | 242 | def send_update_worldports(self, worldports): |
| 231 | if self.server is None: | 243 | if self.server is None: |
| 232 | return | 244 | return |
| @@ -441,13 +453,15 @@ class Lingo2ClientContext(CommonContext): | |||
| 441 | elif args["key"] == self.get_datastorage_key("keyboard2"): | 453 | elif args["key"] == self.get_datastorage_key("keyboard2"): |
| 442 | self.handle_keyboard_update(2, args) | 454 | self.handle_keyboard_update(2, args) |
| 443 | elif args["key"] == self.get_datastorage_key("worldports"): | 455 | elif args["key"] == self.get_datastorage_key("worldports"): |
| 444 | updates = self.manager.update_worldports(set(args["value"])) | 456 | port_ids = set(Lingo2World.static_logic.port_id_by_ap_id[ap_id] for ap_id in args["value"]) |
| 457 | updates = self.manager.update_worldports(port_ids) | ||
| 445 | if len(updates) > 0: | 458 | if len(updates) > 0: |
| 446 | self.manager.game_ctx.send_update_worldports(updates) | 459 | self.manager.game_ctx.send_update_worldports(updates) |
| 447 | elif args["key"] == self.victory_data_storage_key: | 460 | elif args["key"] == self.victory_data_storage_key: |
| 448 | self.handle_status_update(args["value"]) | 461 | self.handle_status_update(args["value"]) |
| 449 | elif args["key"] == self.get_datastorage_key("latches"): | 462 | elif args["key"] == self.get_datastorage_key("latches"): |
| 450 | updates = self.manager.update_latches(set(args["value"])) | 463 | door_ids = set(Lingo2World.static_logic.door_id_by_ap_id[ap_id] for ap_id in args["value"]) |
| 464 | updates = self.manager.update_latches(door_ids) | ||
| 451 | if len(updates) > 0: | 465 | if len(updates) > 0: |
| 452 | self.manager.game_ctx.send_update_latches(updates) | 466 | self.manager.game_ctx.send_update_latches(updates) |
| 453 | 467 | ||
| @@ -515,14 +529,16 @@ class Lingo2ClientContext(CommonContext): | |||
| 515 | if len(updates) > 0: | 529 | if len(updates) > 0: |
| 516 | self.manager.game_ctx.send_update_keyboard(updates) | 530 | self.manager.game_ctx.send_update_keyboard(updates) |
| 517 | 531 | ||
| 532 | # Input should be real IDs, not AP IDs | ||
| 518 | async def update_worldports(self, updates: set[int]): | 533 | async def update_worldports(self, updates: set[int]): |
| 534 | port_ap_ids = [Lingo2World.static_logic.objects.ports[port_id].ap_id for port_id in updates] | ||
| 519 | await self.send_msgs([{ | 535 | await self.send_msgs([{ |
| 520 | "cmd": "Set", | 536 | "cmd": "Set", |
| 521 | "key": self.get_datastorage_key("worldports"), | 537 | "key": self.get_datastorage_key("worldports"), |
| 522 | "want_reply": True, | 538 | "want_reply": True, |
| 523 | "operations": [{ | 539 | "operations": [{ |
| 524 | "operation": "update", | 540 | "operation": "update", |
| 525 | "value": updates | 541 | "value": port_ap_ids |
| 526 | }] | 542 | }] |
| 527 | }]) | 543 | }]) |
| 528 | 544 | ||
| @@ -532,13 +548,14 @@ class Lingo2ClientContext(CommonContext): | |||
| 532 | self.manager.game_ctx.send_accessible_locations() | 548 | self.manager.game_ctx.send_accessible_locations() |
| 533 | 549 | ||
| 534 | async def update_latches(self, updates: set[int]): | 550 | async def update_latches(self, updates: set[int]): |
| 551 | door_ap_ids = [Lingo2World.static_logic.objects.doors[door_id].ap_id for door_id in updates] | ||
| 535 | await self.send_msgs([{ | 552 | await self.send_msgs([{ |
| 536 | "cmd": "Set", | 553 | "cmd": "Set", |
| 537 | "key": self.get_datastorage_key("latches"), | 554 | "key": self.get_datastorage_key("latches"), |
| 538 | "want_reply": True, | 555 | "want_reply": True, |
| 539 | "operations": [{ | 556 | "operations": [{ |
| 540 | "operation": "update", | 557 | "operation": "update", |
| 541 | "value": updates | 558 | "value": door_ap_ids |
| 542 | }] | 559 | }] |
| 543 | }]) | 560 | }]) |
| 544 | 561 | ||
| @@ -590,12 +607,14 @@ async def process_game_cmd(manager: Lingo2Manager, args: dict): | |||
| 590 | async_start(manager.client_ctx.update_keyboard(updates), name="client update keyboard") | 607 | async_start(manager.client_ctx.update_keyboard(updates), name="client update keyboard") |
| 591 | elif cmd == "CheckWorldport": | 608 | elif cmd == "CheckWorldport": |
| 592 | port_id = args["port_id"] | 609 | port_id = args["port_id"] |
| 610 | port_ap_id = Lingo2World.static_logic.objects.ports[port_id].ap_id | ||
| 593 | worldports = {port_id} | 611 | worldports = {port_id} |
| 594 | 612 | ||
| 595 | # Also check the reverse port if it's a two-way connection. | 613 | # Also check the reverse port if it's a two-way connection. |
| 596 | port_pairings = manager.client_ctx.slot_data["port_pairings"] | 614 | port_pairings = manager.client_ctx.slot_data["port_pairings"] |
| 597 | if str(port_id) in port_pairings and port_pairings.get(str(port_pairings[str(port_id)]), None) == port_id: | 615 | if str(port_ap_id) in port_pairings and\ |
| 598 | worldports.add(port_pairings[str(port_id)]) | 616 | port_pairings.get(str(port_pairings[str(port_ap_id)]), None) == port_ap_id: |
| 617 | worldports.add(Lingo2World.static_logic.port_id_by_ap_id[port_pairings[str(port_ap_id)]]) | ||
| 599 | 618 | ||
| 600 | updates = manager.update_worldports(worldports) | 619 | updates = manager.update_worldports(worldports) |
| 601 | if len(updates) > 0: | 620 | if len(updates) > 0: |
| diff --git a/apworld/player_logic.py b/apworld/player_logic.py index 1d68e4a..3ee8f38 100644 --- a/apworld/player_logic.py +++ b/apworld/player_logic.py | |||
| @@ -299,8 +299,7 @@ class Lingo2PlayerLogic: | |||
| 299 | if door.map_id not in self.shuffled_maps: | 299 | if door.map_id not in self.shuffled_maps: |
| 300 | continue | 300 | continue |
| 301 | 301 | ||
| 302 | if door.type in [data_pb2.DoorType.EVENT, data_pb2.DoorType.LOCATION_ONLY, data_pb2.DoorType.GRAVESTONE, | 302 | if door.type in [data_pb2.DoorType.EVENT, data_pb2.DoorType.LOCATION_ONLY, data_pb2.DoorType.GRAVESTONE]: |
| 303 | data_pb2.DoorType.LEGACY_LOCATION]: | ||
| 304 | continue | 303 | continue |
| 305 | 304 | ||
| 306 | if door.id in self.item_by_door: | 305 | if door.id in self.item_by_door: |
| diff --git a/apworld/static_logic.py b/apworld/static_logic.py index 702f30b..8a84111 100644 --- a/apworld/static_logic.py +++ b/apworld/static_logic.py | |||
| @@ -15,6 +15,9 @@ class Lingo2StaticLogic: | |||
| 15 | 15 | ||
| 16 | letter_weights: dict[str, int] | 16 | letter_weights: dict[str, int] |
| 17 | 17 | ||
| 18 | door_id_by_ap_id: dict[int, int] | ||
| 19 | port_id_by_ap_id: dict[int, int] | ||
| 20 | |||
| 18 | def __init__(self): | 21 | def __init__(self): |
| 19 | self.item_id_to_name = {} | 22 | self.item_id_to_name = {} |
| 20 | self.location_id_to_name = {} | 23 | self.location_id_to_name = {} |
| @@ -31,8 +34,7 @@ class Lingo2StaticLogic: | |||
| 31 | location_name = self.get_door_location_name(door) | 34 | location_name = self.get_door_location_name(door) |
| 32 | self.location_id_to_name[door.ap_id] = location_name | 35 | self.location_id_to_name[door.ap_id] = location_name |
| 33 | 36 | ||
| 34 | if door.type not in [data_pb2.DoorType.EVENT, data_pb2.DoorType.LOCATION_ONLY, data_pb2.DoorType.GRAVESTONE, | 37 | if door.type not in [data_pb2.DoorType.EVENT, data_pb2.DoorType.LOCATION_ONLY, data_pb2.DoorType.GRAVESTONE]: |
| 35 | data_pb2.DoorType.LEGACY_LOCATION]: | ||
| 36 | item_name = self.get_door_item_name(door) | 38 | item_name = self.get_door_item_name(door) |
| 37 | self.item_id_to_name[door.ap_id] = item_name | 39 | self.item_id_to_name[door.ap_id] = item_name |
| 38 | 40 | ||
| @@ -84,6 +86,9 @@ class Lingo2StaticLogic: | |||
| 84 | for letter in panel.answer.upper(): | 86 | for letter in panel.answer.upper(): |
| 85 | self.letter_weights[letter] = self.letter_weights.get(letter, 0) + 1 | 87 | self.letter_weights[letter] = self.letter_weights.get(letter, 0) + 1 |
| 86 | 88 | ||
| 89 | self.door_id_by_ap_id = {door.ap_id: door.id for door in self.objects.doors if door.HasField("ap_id")} | ||
| 90 | self.port_id_by_ap_id = {port.ap_id: port.id for port in self.objects.ports if port.HasField("ap_id")} | ||
| 91 | |||
| 87 | def get_door_item_name(self, door: data_pb2.Door) -> str: | 92 | def get_door_item_name(self, door: data_pb2.Door) -> str: |
| 88 | return f"{self.get_map_object_map_name(door)} - {door.name}" | 93 | return f"{self.get_map_object_map_name(door)} - {door.name}" |
| 89 | 94 | ||
| diff --git a/apworld/tracker.py b/apworld/tracker.py index c65317c..d473af4 100644 --- a/apworld/tracker.py +++ b/apworld/tracker.py | |||
| @@ -47,7 +47,10 @@ class Tracker: | |||
| 47 | self.world.create_regions() | 47 | self.world.create_regions() |
| 48 | 48 | ||
| 49 | if self.world.options.shuffle_worldports: | 49 | if self.world.options.shuffle_worldports: |
| 50 | port_pairings = {int(fp): int(tp) for fp, tp in slot_data["port_pairings"].items()} | 50 | port_pairings = { |
| 51 | self.world.static_logic.port_id_by_ap_id[int(fp)]: self.world.static_logic.port_id_by_ap_id[int(tp)] | ||
| 52 | for fp, tp in slot_data["port_pairings"].items() | ||
| 53 | } | ||
| 51 | connect_ports_from_ut(port_pairings, self.world) | 54 | connect_ports_from_ut(port_pairings, self.world) |
| 52 | 55 | ||
| 53 | self.refresh_state() | 56 | self.refresh_state() |
