summary refs log tree commit diff stats
path: root/apworld
diff options
context:
space:
mode:
authorStar Rauchenberger <fefferburbia@gmail.com>2025-08-30 12:00:03 -0400
committerStar Rauchenberger <fefferburbia@gmail.com>2025-08-30 12:00:03 -0400
commitd2bc5b2811171685e8bdc895122987b53defcf0a (patch)
treedabf111e8d4ba8caceee46189075968e223e3ee8 /apworld
parent3b77044a6a53d38a6960eb2a5855283a00b24d75 (diff)
downloadlingo2-archipelago-d2bc5b2811171685e8bdc895122987b53defcf0a.tar.gz
lingo2-archipelago-d2bc5b2811171685e8bdc895122987b53defcf0a.tar.bz2
lingo2-archipelago-d2bc5b2811171685e8bdc895122987b53defcf0a.zip
Changed how door location names are formatted
STANDARD type doors with at most four panels in the same map area and no
other trigger objects will have their location names generated from the
names of the panels used to open the door, similar to Lingo 1. Other
door types will use the door's name. In either case, the name can be
overridden using the new location_name field.

Rooms can also set a panel_display_name field, which will be used in
location names for doors, and is used to group panels into areas.

Panels themselves can set display names, which differentiates their
locations from other panels in the same area.

Many maps were updated for this, but note that the_symbolic and
the_unyielding have validator failures because of duplicate panel names.
This won't matter until panelsanity is implemented.
Diffstat (limited to 'apworld')
-rw-r--r--apworld/player_logic.py2
-rw-r--r--apworld/static_logic.py75
2 files changed, 72 insertions, 5 deletions
diff --git a/apworld/player_logic.py b/apworld/player_logic.py index 3854c99..ae22818 100644 --- a/apworld/player_logic.py +++ b/apworld/player_logic.py
@@ -105,7 +105,7 @@ class Lingo2PlayerLogic:
105 # before we calculate any access requirements. 105 # before we calculate any access requirements.
106 for door in world.static_logic.objects.doors: 106 for door in world.static_logic.objects.doors:
107 if door.type in [data_pb2.DoorType.STANDARD, data_pb2.DoorType.ITEM_ONLY] and self.world.options.shuffle_doors: 107 if door.type in [data_pb2.DoorType.STANDARD, data_pb2.DoorType.ITEM_ONLY] and self.world.options.shuffle_doors:
108 door_item_name = self.world.static_logic.get_door_item_name(door.id) 108 door_item_name = self.world.static_logic.get_door_item_name(door)
109 self.item_by_door[door.id] = door_item_name 109 self.item_by_door[door.id] = door_item_name
110 self.real_items.append(door_item_name) 110 self.real_items.append(door_item_name)
111 111
diff --git a/apworld/static_logic.py b/apworld/static_logic.py index 965ce3e..ff1f17d 100644 --- a/apworld/static_logic.py +++ b/apworld/static_logic.py
@@ -18,11 +18,11 @@ class Lingo2StaticLogic:
18 18
19 for door in self.objects.doors: 19 for door in self.objects.doors:
20 if door.type in [data_pb2.DoorType.STANDARD, data_pb2.DoorType.LOCATION_ONLY, data_pb2.DoorType.GRAVESTONE]: 20 if door.type in [data_pb2.DoorType.STANDARD, data_pb2.DoorType.LOCATION_ONLY, data_pb2.DoorType.GRAVESTONE]:
21 location_name = f"{self.get_map_object_map_name(door)} - {door.name}" 21 location_name = self.get_door_location_name(door)
22 self.location_id_to_name[door.ap_id] = location_name 22 self.location_id_to_name[door.ap_id] = location_name
23 23
24 if door.type not in [data_pb2.DoorType.EVENT, data_pb2.DoorType.LOCATION_ONLY, data_pb2.DoorType.GRAVESTONE]: 24 if door.type not in [data_pb2.DoorType.EVENT, data_pb2.DoorType.LOCATION_ONLY, data_pb2.DoorType.GRAVESTONE]:
25 item_name = self.get_door_item_name(door.id) 25 item_name = self.get_door_item_name(door)
26 self.item_id_to_name[door.ap_id] = item_name 26 self.item_id_to_name[door.ap_id] = item_name
27 27
28 for letter in self.objects.letters: 28 for letter in self.objects.letters:
@@ -46,10 +46,77 @@ class Lingo2StaticLogic:
46 self.item_name_to_id = {name: ap_id for ap_id, name in self.item_id_to_name.items()} 46 self.item_name_to_id = {name: ap_id for ap_id, name in self.item_id_to_name.items()}
47 self.location_name_to_id = {name: ap_id for ap_id, name in self.location_id_to_name.items()} 47 self.location_name_to_id = {name: ap_id for ap_id, name in self.location_id_to_name.items()}
48 48
49 def get_door_item_name(self, door_id: int) -> str: 49 def get_door_item_name(self, door: data_pb2.Door) -> str:
50 door = self.objects.doors[door_id]
51 return f"{self.get_map_object_map_name(door)} - {door.name}" 50 return f"{self.get_map_object_map_name(door)} - {door.name}"
52 51
52 def get_door_item_name_by_id(self, door_id: int) -> str:
53 door = self.objects.doors[door_id]
54 return self.get_door_item_name(door_id)
55
56 def get_door_location_name(self, door: data_pb2.Door) -> str:
57 game_map = self.objects.maps[door.map_id]
58 room = self.objects.rooms[door.room_id]
59
60 if room.HasField("panel_display_name"):
61 map_part = f"{game_map.display_name} ({room.panel_display_name})"
62 else:
63 map_part = game_map.display_name
64
65 if door.HasField("location_name"):
66 return f"{map_part} - {door.location_name}"
67
68 generated_location_name = self.get_generated_door_location_name(door)
69 if generated_location_name is not None:
70 return generated_location_name
71
72 return f"{map_part} - {door.name}"
73
74 def get_generated_door_location_name(self, door: data_pb2.Door) -> str | None:
75 if door.type != data_pb2.DoorType.STANDARD:
76 return None
77
78 if len(door.keyholders) > 0 or len(door.endings) > 0:
79 return None
80
81 if len(door.panels) > 4:
82 return None
83
84 map_areas = set()
85 for panel_id in door.panels:
86 panel = self.objects.panels[panel_id.panel]
87 panel_room = self.objects.rooms[panel.room_id]
88 # It's okay if panel_display_name is not present because then it's coalesced with other unnamed areas.
89 map_areas.add(panel_room.panel_display_name)
90
91 if len(map_areas) > 1:
92 return None
93
94 game_map = self.objects.maps[door.map_id]
95 map_area = map_areas.pop()
96 if map_area == "":
97 map_part = game_map.display_name
98 else:
99 map_part = f"{game_map.display_name} ({map_area})"
100
101 def get_panel_display_name(panel: data_pb2.ProxyIdentifier) -> str:
102 panel_data = self.objects.panels[panel.panel]
103 panel_name = panel_data.display_name if panel_data.HasField("display_name") else panel_data.name
104
105 if panel.HasField("answer"):
106 return f"{panel_name}/{panel.answer.upper()}"
107 else:
108 return panel_name
109
110 panel_names = [get_panel_display_name(panel_id)
111 for panel_id in door.panels]
112 panel_names.sort()
113
114 return f"{map_part} - {", ".join(panel_names)}"
115
116 def get_door_location_name_by_id(self, door_id: int) -> str:
117 door = self.objects.doors[door_id]
118 return self.get_door_location_name(door)
119
53 def get_room_region_name(self, room_id: int) -> str: 120 def get_room_region_name(self, room_id: int) -> str:
54 room = self.objects.rooms[room_id] 121 room = self.objects.rooms[room_id]
55 return f"{self.get_map_object_map_name(room)} - {room.name}" 122 return f"{self.get_map_object_map_name(room)} - {room.name}"