about summary refs log tree commit diff stats
path: root/apworld
diff options
context:
space:
mode:
Diffstat (limited to 'apworld')
-rw-r--r--apworld/__init__.py7
-rw-r--r--apworld/client/client.gd8
-rw-r--r--apworld/client/gamedata.gd20
-rw-r--r--apworld/client/manager.gd32
-rw-r--r--apworld/client/player.gd3
-rw-r--r--apworld/client/settings_screen.gd10
-rw-r--r--apworld/client/worldportListener.gd2
-rw-r--r--apworld/context.py3
-rw-r--r--apworld/regions.py6
9 files changed, 67 insertions, 24 deletions
diff --git a/apworld/__init__.py b/apworld/__init__.py index 1d12050..57e3d9b 100644 --- a/apworld/__init__.py +++ b/apworld/__init__.py
@@ -4,6 +4,7 @@ Archipelago init file for Lingo 2
4from typing import ClassVar 4from typing import ClassVar
5 5
6from BaseClasses import ItemClassification, Item, Tutorial 6from BaseClasses import ItemClassification, Item, Tutorial
7from Options import OptionError
7from settings import Group, UserFilePath 8from settings import Group, UserFilePath
8from worlds.AutoWorld import WebWorld, World 9from worlds.AutoWorld import WebWorld, World
9from .items import Lingo2Item, ANTI_COLLECTABLE_TRAPS 10from .items import Lingo2Item, ANTI_COLLECTABLE_TRAPS
@@ -33,6 +34,7 @@ class Lingo2Settings(Group):
33 is_exe = True 34 is_exe = True
34 35
35 exe_file: ExecutableFile = ExecutableFile() 36 exe_file: ExecutableFile = ExecutableFile()
37 start_game: bool = True
36 38
37 39
38class Lingo2World(World): 40class Lingo2World(World):
@@ -108,6 +110,11 @@ class Lingo2World(World):
108 for i in range(0, item_difference): 110 for i in range(0, item_difference):
109 pool.append(self.create_item(self.get_filler_item_name())) 111 pool.append(self.create_item(self.get_filler_item_name()))
110 112
113 if not any(ItemClassification.progression in item.classification for item in pool):
114 raise OptionError(f"Lingo 2 player {self.player} has no progression items. Please enable at least one "
115 f"option that would add progression gating to your world, such as Shuffle Doors or "
116 f"Shuffle Letters.")
117
111 self.multiworld.itempool += pool 118 self.multiworld.itempool += pool
112 119
113 def create_item(self, name: str) -> Item: 120 def create_item(self, name: str) -> Item:
diff --git a/apworld/client/client.gd b/apworld/client/client.gd index e25ad4b..9a4b402 100644 --- a/apworld/client/client.gd +++ b/apworld/client/client.gd
@@ -108,7 +108,7 @@ func _on_web_socket_server_message_received(_peer_id: int, packet: String) -> vo
108 108
109 _checked_locations = [] 109 _checked_locations = []
110 for location in message["checked_locations"]: 110 for location in message["checked_locations"]:
111 _checked_locations.append(int(message["checked_locations"])) 111 _checked_locations.append(int(location))
112 112
113 client_connected.emit(_slot_data) 113 client_connected.emit(_slot_data)
114 114
@@ -158,11 +158,7 @@ func _on_web_socket_server_message_received(_peer_id: int, packet: String) -> vo
158 elif cmd == "LocationInfo": 158 elif cmd == "LocationInfo":
159 for loc in message["locations"]: 159 for loc in message["locations"]:
160 location_scout_received.emit( 160 location_scout_received.emit(
161 int(loc["id"]), 161 int(loc["id"]), loc["item"], loc["player"], int(loc["flags"]), int(loc["self"])
162 loc["item"],
163 loc["player"],
164 int(loc["flags"]),
165 int(loc["for_self"])
166 ) 162 )
167 163
168 elif cmd == "AccessibleLocations": 164 elif cmd == "AccessibleLocations":
diff --git a/apworld/client/gamedata.gd b/apworld/client/gamedata.gd index 334d42a..9305003 100644 --- a/apworld/client/gamedata.gd +++ b/apworld/client/gamedata.gd
@@ -72,7 +72,13 @@ func load(data_bytes):
72 72
73 if door.has_ap_id(): 73 if door.has_ap_id():
74 door_id_by_ap_id[door.get_ap_id()] = door.get_id() 74 door_id_by_ap_id[door.get_ap_id()] = door.get_id()
75 location_name_by_id[door.get_ap_id()] = _get_door_location_name(door) 75
76 if (
77 door.get_type() == SCRIPT_proto.DoorType.STANDARD
78 or door.get_type() == SCRIPT_proto.DoorType.LOCATION_ONLY
79 or door.get_type() == SCRIPT_proto.DoorType.GRAVESTONE
80 ):
81 location_name_by_id[door.get_ap_id()] = _get_door_location_name(door)
76 82
77 for painting in objects.get_paintings(): 83 for painting in objects.get_paintings():
78 var room = objects.get_rooms()[painting.get_room_id()] 84 var room = objects.get_rooms()[painting.get_room_id()]
@@ -166,8 +172,7 @@ func get_door_ap_id(door_id):
166 172
167func get_door_map_name(door_id): 173func get_door_map_name(door_id):
168 var door = objects.get_doors()[door_id] 174 var door = objects.get_doors()[door_id]
169 var room = objects.get_rooms()[door.get_room_id()] 175 var map = objects.get_maps()[door.get_map_id()]
170 var map = objects.get_maps()[room.get_map_id()]
171 return map.get_name() 176 return map.get_name()
172 177
173 178
@@ -227,8 +232,11 @@ func _get_generated_door_location_name(door):
227 var panel = objects.get_panels()[panel_id.get_panel()] 232 var panel = objects.get_panels()[panel_id.get_panel()]
228 var panel_room = objects.get_rooms()[panel.get_room_id()] 233 var panel_room = objects.get_rooms()[panel.get_room_id()]
229 # It's okay if panel_display_name is not present because then it's coalesced with other unnamed areas. 234 # It's okay if panel_display_name is not present because then it's coalesced with other unnamed areas.
230 if not map_areas.has(panel_room.get_panel_display_name()): 235 var panel_display_name = ""
231 map_areas.append(panel_room.get_panel_display_name()) 236 if panel_room.has_panel_display_name():
237 panel_display_name = panel_room.get_panel_display_name()
238 if not map_areas.has(panel_display_name):
239 map_areas.append(panel_display_name)
232 240
233 if map_areas.size() > 1: 241 if map_areas.size() > 1:
234 return null 242 return null
@@ -264,7 +272,7 @@ func _get_generated_door_location_name(door):
264 272
265 273
266func _get_letter_location_name(letter): 274func _get_letter_location_name(letter):
267 var letter_level = 2 if letter.get_level2() else 1 275 var letter_level = 2 if (letter.has_level2() and letter.get_level2()) else 1
268 var letter_name = "%s%d" % [letter.get_key().to_upper(), letter_level] 276 var letter_name = "%s%d" % [letter.get_key().to_upper(), letter_level]
269 return "%s - %s" % [_get_room_object_map_name(letter), letter_name] 277 return "%s - %s" % [_get_room_object_map_name(letter), letter_name]
270 278
diff --git a/apworld/client/manager.gd b/apworld/client/manager.gd index 0d5a5aa..4f5018f 100644 --- a/apworld/client/manager.gd +++ b/apworld/client/manager.gd
@@ -237,6 +237,9 @@ func _process_item(item, amount):
237 if player != null: 237 if player != null:
238 player.evaluate_solvability.emit() 238 player.evaluate_solvability.emit()
239 239
240 if item_id == gamedata.objects.get_special_ids()["A Job Well Done"]:
241 update_job_well_done_sign()
242
240 # Show a message about the item if it's new. 243 # Show a message about the item if it's new.
241 if int(item["index"]) > _last_new_item: 244 if int(item["index"]) > _last_new_item:
242 _last_new_item = int(item["index"]) 245 _last_new_item = int(item["index"])
@@ -503,6 +506,9 @@ func start_batching_locations():
503 506
504 507
505func send_location(loc_id): 508func send_location(loc_id):
509 if client._checked_locations.has(loc_id):
510 return
511
506 if _batch_locations: 512 if _batch_locations:
507 _held_locations.append(loc_id) 513 _held_locations.append(loc_id)
508 else: 514 else:
@@ -601,3 +607,29 @@ func _process_key_item(key, level):
601 level += 1 607 level += 1
602 608
603 keyboard.collect_remote_letter(key, level) 609 keyboard.collect_remote_letter(key, level)
610
611
612func update_job_well_done_sign():
613 if global.map != "daedalus":
614 return
615
616 var gamedata = global.get_node("Gamedata")
617 var job_item = gamedata.objects.get_special_ids()["A Job Well Done"]
618 var jobs_done = client.getItemAmount(job_item)
619
620 var sign2 = get_tree().get_root().get_node_or_null("scene/Meshes/Miscellaneous/sign2")
621 var sign3 = get_tree().get_root().get_node_or_null("scene/Meshes/Miscellaneous/sign3")
622
623 if sign2 != null and sign3 != null:
624 if jobs_done == 0:
625 sign2.text = "what are you doing"
626 sign3.text = "?"
627 elif jobs_done == 1:
628 sign2.text = "a job well done"
629 sign3.text = "is its own reward"
630 else:
631 sign2.text = "%d jobs well done" % jobs_done
632 sign3.text = "are their own reward"
633
634 sign2.get_node("MeshInstance3D").mesh.text = sign2.text
635 sign3.get_node("MeshInstance3D").mesh.text = sign3.text
diff --git a/apworld/client/player.gd b/apworld/client/player.gd index 5417a48..b73f61e 100644 --- a/apworld/client/player.gd +++ b/apworld/client/player.gd
@@ -31,6 +31,7 @@ func _ready():
31 if ( 31 if (
32 door.get_type() == gamedata.SCRIPT_proto.DoorType.ITEM_ONLY 32 door.get_type() == gamedata.SCRIPT_proto.DoorType.ITEM_ONLY
33 or door.get_type() == gamedata.SCRIPT_proto.DoorType.GALLERY_PAINTING 33 or door.get_type() == gamedata.SCRIPT_proto.DoorType.GALLERY_PAINTING
34 or door.get_type() == gamedata.SCRIPT_proto.DoorType.CONTROL_CENTER_COLOR
34 ): 35 ):
35 continue 36 continue
36 37
@@ -312,6 +313,8 @@ func _ready():
312 entry1.get_parent().add_child.call_deferred(entry12) 313 entry1.get_parent().add_child.call_deferred(entry12)
313 entry1.queue_free() 314 entry1.queue_free()
314 315
316 ap.update_job_well_done_sign()
317
315 var minimap = ap.SCRIPT_minimap.new() 318 var minimap = ap.SCRIPT_minimap.new()
316 minimap.name = "Minimap" 319 minimap.name = "Minimap"
317 minimap.visible = ap.show_minimap 320 minimap.visible = ap.show_minimap
diff --git a/apworld/client/settings_screen.gd b/apworld/client/settings_screen.gd index b430b17..89e8b68 100644 --- a/apworld/client/settings_screen.gd +++ b/apworld/client/settings_screen.gd
@@ -100,7 +100,7 @@ func _ready():
100 server_box.offset_top = 295.0 100 server_box.offset_top = 295.0
101 server_box.offset_right = 1144.0 101 server_box.offset_right = 1144.0
102 server_box.offset_bottom = 445.0 102 server_box.offset_bottom = 445.0
103 server_box.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER 103 server_box.alignment = HORIZONTAL_ALIGNMENT_CENTER
104 server_box.caret_blink = true 104 server_box.caret_blink = true
105 panel.add_child(server_box) 105 panel.add_child(server_box)
106 106
@@ -110,7 +110,7 @@ func _ready():
110 player_box.offset_top = 477.0 110 player_box.offset_top = 477.0
111 player_box.offset_right = 1144.0 111 player_box.offset_right = 1144.0
112 player_box.offset_bottom = 627.0 112 player_box.offset_bottom = 627.0
113 player_box.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER 113 player_box.alignment = HORIZONTAL_ALIGNMENT_CENTER
114 player_box.caret_blink = true 114 player_box.caret_blink = true
115 panel.add_child(player_box) 115 panel.add_child(player_box)
116 116
@@ -120,20 +120,16 @@ func _ready():
120 password_box.offset_top = 659.0 120 password_box.offset_top = 659.0
121 password_box.offset_right = 1144.0 121 password_box.offset_right = 1144.0
122 password_box.offset_bottom = 809.0 122 password_box.offset_bottom = 809.0
123 password_box.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER 123 password_box.alignment = HORIZONTAL_ALIGNMENT_CENTER
124 password_box.caret_blink = true 124 password_box.caret_blink = true
125 panel.add_child(password_box) 125 panel.add_child(password_box)
126 126
127 var accept_dialog = AcceptDialog.new() 127 var accept_dialog = AcceptDialog.new()
128 accept_dialog.name = "AcceptDialog" 128 accept_dialog.name = "AcceptDialog"
129 accept_dialog.offset_right = 83.0
130 accept_dialog.offset_bottom = 58.0
131 panel.add_child(accept_dialog) 129 panel.add_child(accept_dialog)
132 130
133 var version_mismatch = ConfirmationDialog.new() 131 var version_mismatch = ConfirmationDialog.new()
134 version_mismatch.name = "VersionMismatch" 132 version_mismatch.name = "VersionMismatch"
135 version_mismatch.offset_right = 83.0
136 version_mismatch.offset_bottom = 58.0
137 panel.add_child(version_mismatch) 133 panel.add_child(version_mismatch)
138 134
139 var connection_history = MenuButton.new() 135 var connection_history = MenuButton.new()
diff --git a/apworld/client/worldportListener.gd b/apworld/client/worldportListener.gd index 5c2faff..4cff8e9 100644 --- a/apworld/client/worldportListener.gd +++ b/apworld/client/worldportListener.gd
@@ -2,7 +2,7 @@ extends "res://scripts/nodes/listeners/worldportListener.gd"
2 2
3 3
4func handleTriggered(): 4func handleTriggered():
5 if exit == "menus/credits": 5 if exit.begins_with("menus/credits"):
6 return 6 return
7 7
8 super.handleTriggered() 8 super.handleTriggered()
diff --git a/apworld/context.py b/apworld/context.py index 7b5f0bc..a0ee34d 100644 --- a/apworld/context.py +++ b/apworld/context.py
@@ -615,7 +615,8 @@ async def run_game():
615 615
616def client_main(*launch_args: str) -> None: 616def client_main(*launch_args: str) -> None:
617 async def main(args): 617 async def main(args):
618 async_start(run_game()) 618 if settings.get_settings().lingo2_options.start_game:
619 async_start(run_game())
619 620
620 client_ctx = Lingo2ClientContext(args.connect, args.password) 621 client_ctx = Lingo2ClientContext(args.connect, args.password)
621 game_ctx = Lingo2GameContext() 622 game_ctx = Lingo2GameContext()
diff --git a/apworld/regions.py b/apworld/regions.py index 3735858..1215f5a 100644 --- a/apworld/regions.py +++ b/apworld/regions.py
@@ -97,7 +97,7 @@ def create_regions(world: "Lingo2World"):
97 97
98 if connection.HasField("port"): 98 if connection.HasField("port"):
99 port = world.static_logic.objects.ports[connection.port] 99 port = world.static_logic.objects.ports[connection.port]
100 connection_name = f"{connection_name} (via port {port.name})" 100 connection_name = f"{connection_name} (via {port.display_name})"
101 101
102 if world.options.shuffle_worldports and not port.no_shuffle: 102 if world.options.shuffle_worldports and not port.no_shuffle:
103 continue 103 continue
@@ -157,7 +157,7 @@ def shuffle_entrances(world: "Lingo2World"):
157 port_region_name = world.static_logic.get_room_region_name(port.room_id) 157 port_region_name = world.static_logic.get_room_region_name(port.room_id)
158 port_region = world.multiworld.get_region(port_region_name, world.player) 158 port_region = world.multiworld.get_region(port_region_name, world.player)
159 159
160 connection_name = f"{port_region_name} - {port.name}" 160 connection_name = f"{port_region_name} - {port.display_name}"
161 port_id_by_name[connection_name] = port.id 161 port_id_by_name[connection_name] = port.id
162 162
163 entrance = port_region.create_er_target(connection_name) 163 entrance = port_region.create_er_target(connection_name)
@@ -195,7 +195,7 @@ def connect_ports_from_ut(port_pairings: dict[int, int], world: "Lingo2World"):
195 from_region = world.multiworld.get_region(from_region_name, world.player) 195 from_region = world.multiworld.get_region(from_region_name, world.player)
196 to_region = world.multiworld.get_region(to_region_name, world.player) 196 to_region = world.multiworld.get_region(to_region_name, world.player)
197 197
198 connection = Entrance(world.player, f"{from_region_name} - {from_port.name}", from_region) 198 connection = Entrance(world.player, f"{from_region_name} - {from_port.display_name}", from_region)
199 199
200 reqs = AccessRequirements() 200 reqs = AccessRequirements()
201 if from_port.HasField("required_door"): 201 if from_port.HasField("required_door"):