diff options
Diffstat (limited to 'client/Archipelago/manager.gd')
-rw-r--r-- | client/Archipelago/manager.gd | 213 |
1 files changed, 187 insertions, 26 deletions
diff --git a/client/Archipelago/manager.gd b/client/Archipelago/manager.gd index 609e645..cd0654f 100644 --- a/client/Archipelago/manager.gd +++ b/client/Archipelago/manager.gd | |||
@@ -3,6 +3,7 @@ extends Node | |||
3 | const my_version = "0.1.0" | 3 | const my_version = "0.1.0" |
4 | 4 | ||
5 | var SCRIPT_client | 5 | var SCRIPT_client |
6 | var SCRIPT_keyboard | ||
6 | var SCRIPT_locationListener | 7 | var SCRIPT_locationListener |
7 | var SCRIPT_uuid | 8 | var SCRIPT_uuid |
8 | var SCRIPT_victoryListener | 9 | var SCRIPT_victoryListener |
@@ -13,16 +14,39 @@ var ap_pass = "" | |||
13 | var connection_history = [] | 14 | var connection_history = [] |
14 | 15 | ||
15 | var client | 16 | var client |
17 | var keyboard | ||
16 | 18 | ||
17 | var _localdata_file = "" | 19 | var _localdata_file = "" |
18 | var _last_new_item = -1 | 20 | var _last_new_item = -1 |
19 | var _batch_locations = false | 21 | var _batch_locations = false |
20 | var _held_locations = [] | 22 | var _held_locations = [] |
23 | var _held_location_scouts = [] | ||
24 | var _location_scouts = {} | ||
21 | var _item_locks = {} | 25 | var _item_locks = {} |
26 | var _inverse_item_locks = {} | ||
27 | var _held_letters = {} | ||
28 | var _letters_setup = false | ||
22 | 29 | ||
30 | const kSHUFFLE_LETTERS_VANILLA = 0 | ||
31 | const kSHUFFLE_LETTERS_UNLOCKED = 1 | ||
32 | const kSHUFFLE_LETTERS_PROGRESSIVE = 2 | ||
33 | const kSHUFFLE_LETTERS_VANILLA_CYAN = 3 | ||
34 | const kSHUFFLE_LETTERS_ITEM_CYAN = 4 | ||
35 | |||
36 | const kLETTER_BEHAVIOR_VANILLA = 0 | ||
37 | const kLETTER_BEHAVIOR_ITEM = 1 | ||
38 | const kLETTER_BEHAVIOR_UNLOCKED = 2 | ||
39 | |||
40 | const kCYAN_DOOR_BEHAVIOR_H2 = 0 | ||
41 | const kCYAN_DOOR_BEHAVIOR_DOUBLE_LETTER = 1 | ||
42 | const kCYAN_DOOR_BEHAVIOR_ITEM = 2 | ||
43 | |||
44 | var cyan_door_behavior = kCYAN_DOOR_BEHAVIOR_H2 | ||
23 | var daedalus_roof_access = false | 45 | var daedalus_roof_access = false |
24 | var keyholder_sanity = false | 46 | var keyholder_sanity = false |
47 | var shuffle_control_center_colors = false | ||
25 | var shuffle_doors = false | 48 | var shuffle_doors = false |
49 | var shuffle_letters = kSHUFFLE_LETTERS_VANILLA | ||
26 | var victory_condition = -1 | 50 | var victory_condition = -1 |
27 | 51 | ||
28 | signal could_not_connect | 52 | signal could_not_connect |
@@ -60,12 +84,16 @@ func _ready(): | |||
60 | 84 | ||
61 | client.connect("item_received", _process_item) | 85 | client.connect("item_received", _process_item) |
62 | client.connect("message_received", _process_message) | 86 | client.connect("message_received", _process_message) |
87 | client.connect("location_scout_received", _process_location_scout) | ||
63 | client.connect("could_not_connect", _client_could_not_connect) | 88 | client.connect("could_not_connect", _client_could_not_connect) |
64 | client.connect("connect_status", _client_connect_status) | 89 | client.connect("connect_status", _client_connect_status) |
65 | client.connect("client_connected", _client_connected) | 90 | client.connect("client_connected", _client_connected) |
66 | 91 | ||
67 | add_child(client) | 92 | add_child(client) |
68 | 93 | ||
94 | keyboard = SCRIPT_keyboard.new() | ||
95 | add_child(keyboard) | ||
96 | |||
69 | 97 | ||
70 | func saveSettings(): | 98 | func saveSettings(): |
71 | # Save the AP settings to disk. | 99 | # Save the AP settings to disk. |
@@ -100,6 +128,12 @@ func saveLocaldata(): | |||
100 | 128 | ||
101 | func connectToServer(): | 129 | func connectToServer(): |
102 | _last_new_item = -1 | 130 | _last_new_item = -1 |
131 | _batch_locations = false | ||
132 | _held_locations = [] | ||
133 | _held_location_scouts = [] | ||
134 | _location_scouts = {} | ||
135 | _letters_setup = false | ||
136 | _held_letters = {} | ||
103 | 137 | ||
104 | client.connectToServer(ap_server, ap_user, ap_pass) | 138 | client.connectToServer(ap_server, ap_user, ap_pass) |
105 | 139 | ||
@@ -122,29 +156,32 @@ func _process_item(item, index, from, flags, amount): | |||
122 | item_name = client._item_id_to_name["Lingo 2"][item] | 156 | item_name = client._item_id_to_name["Lingo 2"][item] |
123 | 157 | ||
124 | var gamedata = global.get_node("Gamedata") | 158 | var gamedata = global.get_node("Gamedata") |
125 | var door_id = gamedata.door_id_by_ap_id.get(item, null) | ||
126 | var prog_id = null | ||
127 | 159 | ||
128 | if door_id == null: | 160 | var prog_id = null |
129 | prog_id = gamedata.progressive_id_by_ap_id.get(item, null) | 161 | if _inverse_item_locks.has(item): |
130 | if prog_id != null: | 162 | for lock in _inverse_item_locks.get(item): |
131 | var progressive = gamedata.objects.get_progressives()[prog_id] | 163 | if lock[1] != amount: |
132 | if progressive.get_doors().size() >= amount: | 164 | continue |
133 | door_id = progressive.get_doors()[amount - 1] | 165 | |
134 | 166 | if gamedata.progressive_id_by_ap_id.has(item): | |
135 | if door_id != null and gamedata.get_door_map_name(door_id) == global.map: | 167 | prog_id = lock[0] |
136 | var receivers = gamedata.get_door_receivers(door_id) | 168 | |
137 | var scene = get_tree().get_root().get_node_or_null("scene") | 169 | if gamedata.get_door_map_name(lock[0]) != global.map: |
138 | if scene != null: | 170 | continue |
139 | for receiver in receivers: | 171 | |
140 | var rnode = scene.get_node_or_null(receiver) | 172 | var receivers = gamedata.get_door_receivers(lock[0]) |
141 | if rnode != null: | 173 | var scene = get_tree().get_root().get_node_or_null("scene") |
142 | rnode.handleTriggered() | 174 | if scene != null: |
143 | #for painting_id in gamedata.objects.get_doors()[door_id].get_move_paintings(): | 175 | for receiver in receivers: |
144 | # var painting = gamedata.objects.get_paintings()[painting_id] | 176 | var rnode = scene.get_node_or_null(receiver) |
145 | # var pnode = scene.get_node_or_null(painting.get_path() + "/teleportListener") | 177 | if rnode != null: |
146 | # if pnode != null: | 178 | rnode.handleTriggered() |
147 | # pnode.handleTriggered() | 179 | |
180 | var letter_id = gamedata.letter_id_by_ap_id.get(item, null) | ||
181 | if letter_id != null: | ||
182 | var letter = gamedata.objects.get_letters()[letter_id] | ||
183 | if not letter.has_level2() or not letter.get_level2(): | ||
184 | _process_key_item(letter.get_key(), amount) | ||
148 | 185 | ||
149 | # Show a message about the item if it's new. | 186 | # Show a message about the item if it's new. |
150 | if index != null and index > _last_new_item: | 187 | if index != null and index > _last_new_item: |
@@ -158,8 +195,8 @@ func _process_item(item, index, from, flags, amount): | |||
158 | var item_color = colorForItemType(flags) | 195 | var item_color = colorForItemType(flags) |
159 | 196 | ||
160 | var full_item_name = item_name | 197 | var full_item_name = item_name |
161 | if prog_id != null and door_id != null: | 198 | if prog_id != null: |
162 | var door = gamedata.objects.get_doors()[door_id] | 199 | var door = gamedata.objects.get_doors()[prog_id] |
163 | full_item_name = "%s (%s)" % [item_name, door.get_name()] | 200 | full_item_name = "%s (%s)" % [item_name, door.get_name()] |
164 | 201 | ||
165 | var message | 202 | var message |
@@ -261,6 +298,29 @@ func parse_printjson_for_textclient(message): | |||
261 | textclient_node.parse_printjson("".join(parts)) | 298 | textclient_node.parse_printjson("".join(parts)) |
262 | 299 | ||
263 | 300 | ||
301 | func _process_location_scout(item_id, location_id, player, flags): | ||
302 | _location_scouts[location_id] = {"item": item_id, "player": player, "flags": flags} | ||
303 | |||
304 | var gamedata = global.get_node("Gamedata") | ||
305 | var map_id = gamedata.map_id_by_name.get(global.map) | ||
306 | |||
307 | var item_name = "Unknown" | ||
308 | var item_player_game = client._game_by_player[float(player)] | ||
309 | if client._item_id_to_name[item_player_game].has(item_id): | ||
310 | item_name = client._item_id_to_name[item_player_game][item_id] | ||
311 | |||
312 | var letter_id = gamedata.letter_id_by_ap_id.get(location_id, null) | ||
313 | if letter_id != null: | ||
314 | var letter = gamedata.objects.get_letters()[letter_id] | ||
315 | var room = gamedata.objects.get_rooms()[letter.get_room_id()] | ||
316 | if room.get_map_id() == map_id: | ||
317 | var collectable = get_tree().get_root().get_node("scene").get_node_or_null( | ||
318 | letter.get_path() | ||
319 | ) | ||
320 | if collectable != null: | ||
321 | collectable.setScoutedText(item_name) | ||
322 | |||
323 | |||
264 | func _client_could_not_connect(): | 324 | func _client_could_not_connect(): |
265 | emit_signal("could_not_connect") | 325 | emit_signal("could_not_connect") |
266 | 326 | ||
@@ -290,9 +350,12 @@ func _client_connected(slot_data): | |||
290 | _last_new_item = localdata[0] | 350 | _last_new_item = localdata[0] |
291 | 351 | ||
292 | # Read slot data. | 352 | # Read slot data. |
353 | cyan_door_behavior = int(slot_data.get("cyan_door_behavior", 0)) | ||
293 | daedalus_roof_access = bool(slot_data.get("daedalus_roof_access", false)) | 354 | daedalus_roof_access = bool(slot_data.get("daedalus_roof_access", false)) |
294 | keyholder_sanity = bool(slot_data.get("keyholder_sanity", false)) | 355 | keyholder_sanity = bool(slot_data.get("keyholder_sanity", false)) |
356 | shuffle_control_center_colors = bool(slot_data.get("shuffle_control_center_colors", false)) | ||
295 | shuffle_doors = bool(slot_data.get("shuffle_doors", false)) | 357 | shuffle_doors = bool(slot_data.get("shuffle_doors", false)) |
358 | shuffle_letters = int(slot_data.get("shuffle_letters", 0)) | ||
296 | victory_condition = int(slot_data.get("victory_condition", 0)) | 359 | victory_condition = int(slot_data.get("victory_condition", 0)) |
297 | 360 | ||
298 | # Set up item locks. | 361 | # Set up item locks. |
@@ -311,6 +374,42 @@ func _client_connected(slot_data): | |||
311 | var door = gamedata.objects.get_doors()[progressive.get_doors()[i]] | 374 | var door = gamedata.objects.get_doors()[progressive.get_doors()[i]] |
312 | _item_locks[door.get_id()] = [progressive.get_ap_id(), i + 1] | 375 | _item_locks[door.get_id()] = [progressive.get_ap_id(), i + 1] |
313 | 376 | ||
377 | for door_group in gamedata.objects.get_door_groups(): | ||
378 | if ( | ||
379 | door_group.get_type() == gamedata.SCRIPT_proto.DoorGroupType.CONNECTOR | ||
380 | or door_group.get_type() == gamedata.SCRIPT_proto.DoorGroupType.SHUFFLE_GROUP | ||
381 | ): | ||
382 | for door in door_group.get_doors(): | ||
383 | _item_locks[door] = [door_group.get_ap_id(), 1] | ||
384 | |||
385 | if shuffle_control_center_colors: | ||
386 | for door in gamedata.objects.get_doors(): | ||
387 | if door.get_type() == gamedata.SCRIPT_proto.DoorType.CONTROL_CENTER_COLOR: | ||
388 | _item_locks[door.get_id()] = [door.get_ap_id(), 1] | ||
389 | |||
390 | for door_group in gamedata.objects.get_door_groups(): | ||
391 | if door_group.get_type() == gamedata.SCRIPT_proto.DoorGroupType.COLOR_CONNECTOR: | ||
392 | for door in door_group.get_doors(): | ||
393 | _item_locks[door] = [door_group.get_ap_id(), 1] | ||
394 | |||
395 | if cyan_door_behavior == kCYAN_DOOR_BEHAVIOR_ITEM: | ||
396 | for door_group in gamedata.objects.get_door_groups(): | ||
397 | if door_group.get_type() == gamedata.SCRIPT_proto.DoorGroupType.CYAN_DOORS: | ||
398 | for door in door_group.get_doors(): | ||
399 | if not _item_locks.has(door): | ||
400 | _item_locks[door] = [door_group.get_ap_id(), 1] | ||
401 | |||
402 | # Create a reverse item locks map for processing items. | ||
403 | _inverse_item_locks = {} | ||
404 | |||
405 | for door_id in _item_locks.keys(): | ||
406 | var lock = _item_locks.get(door_id) | ||
407 | |||
408 | if not _inverse_item_locks.has(lock[0]): | ||
409 | _inverse_item_locks[lock[0]] = [] | ||
410 | |||
411 | _inverse_item_locks[lock[0]].append([door_id, lock[1]]) | ||
412 | |||
314 | emit_signal("ap_connected") | 413 | emit_signal("ap_connected") |
315 | 414 | ||
316 | 415 | ||
@@ -325,10 +424,28 @@ func send_location(loc_id): | |||
325 | client.sendLocation(loc_id) | 424 | client.sendLocation(loc_id) |
326 | 425 | ||
327 | 426 | ||
427 | func scout_location(loc_id): | ||
428 | if _location_scouts.has(loc_id): | ||
429 | return _location_scouts.get(loc_id) | ||
430 | |||
431 | if _batch_locations: | ||
432 | _held_location_scouts.append(loc_id) | ||
433 | else: | ||
434 | client.scoutLocation(loc_id) | ||
435 | |||
436 | return null | ||
437 | |||
438 | |||
328 | func stop_batching_locations(): | 439 | func stop_batching_locations(): |
329 | _batch_locations = false | 440 | _batch_locations = false |
330 | client.sendLocations(_held_locations) | 441 | |
331 | _held_locations.clear() | 442 | if not _held_locations.is_empty(): |
443 | client.sendLocations(_held_locations) | ||
444 | _held_locations.clear() | ||
445 | |||
446 | if not _held_location_scouts.is_empty(): | ||
447 | client.scoutLocations(_held_location_scouts) | ||
448 | _held_location_scouts.clear() | ||
332 | 449 | ||
333 | 450 | ||
334 | func colorForItemType(flags): | 451 | func colorForItemType(flags): |
@@ -344,3 +461,47 @@ func colorForItemType(flags): | |||
344 | return "#d63a22" | 461 | return "#d63a22" |
345 | else: # filler | 462 | else: # filler |
346 | return "#14de9e" | 463 | return "#14de9e" |
464 | |||
465 | |||
466 | func get_letter_behavior(key, level2): | ||
467 | if shuffle_letters == kSHUFFLE_LETTERS_UNLOCKED: | ||
468 | return kLETTER_BEHAVIOR_UNLOCKED | ||
469 | |||
470 | if [kSHUFFLE_LETTERS_VANILLA_CYAN, kSHUFFLE_LETTERS_ITEM_CYAN].has(shuffle_letters): | ||
471 | if level2: | ||
472 | if shuffle_letters == kSHUFFLE_LETTERS_VANILLA_CYAN: | ||
473 | return kLETTER_BEHAVIOR_VANILLA | ||
474 | else: | ||
475 | return kLETTER_BEHAVIOR_ITEM | ||
476 | else: | ||
477 | return kLETTER_BEHAVIOR_UNLOCKED | ||
478 | |||
479 | if not level2 and ["h", "i", "n", "t"].has(key): | ||
480 | # This differs from the equivalent function in the apworld. Logically it is | ||
481 | # the same as UNLOCKED since they are in the starting room, but VANILLA | ||
482 | # means the player still has to actually pick up the letters. | ||
483 | return kLETTER_BEHAVIOR_VANILLA | ||
484 | |||
485 | if shuffle_letters == kSHUFFLE_LETTERS_PROGRESSIVE: | ||
486 | return kLETTER_BEHAVIOR_ITEM | ||
487 | |||
488 | return kLETTER_BEHAVIOR_VANILLA | ||
489 | |||
490 | |||
491 | func setup_keys(): | ||
492 | keyboard.load_seed() | ||
493 | |||
494 | _letters_setup = true | ||
495 | |||
496 | for k in _held_letters.keys(): | ||
497 | _process_key_item(k, _held_letters[k]) | ||
498 | |||
499 | _held_letters.clear() | ||
500 | |||
501 | |||
502 | func _process_key_item(key, level): | ||
503 | if not _letters_setup: | ||
504 | _held_letters[key] = max(_held_letters.get(key, 0), level) | ||
505 | return | ||
506 | |||
507 | keyboard.collect_remote_letter(key, level) | ||