about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--Archipelago/client.gd182
-rw-r--r--Archipelago/load.gd113
-rw-r--r--Archipelago/mypainting.gd5
-rw-r--r--Archipelago/painting.gd10
-rw-r--r--Archipelago/painting_eye.gd16
-rw-r--r--Archipelago/painting_scenery.gd10
-rw-r--r--Archipelago/panel.gd2
-rw-r--r--Archipelago/pilgrimage_terminator.gd11
-rw-r--r--Archipelago/settings_screen.gd35
-rw-r--r--Archipelago/teleport.gd27
-rw-r--r--CHANGELOG.md51
-rw-r--r--README.md62
-rw-r--r--archipelago.tscn25
-rw-r--r--util/generate_gamedata.rb69
14 files changed, 502 insertions, 116 deletions
diff --git a/Archipelago/client.gd b/Archipelago/client.gd index a3b503a..bc952b9 100644 --- a/Archipelago/client.gd +++ b/Archipelago/client.gd
@@ -7,6 +7,7 @@ var SCRIPT_multiplayer
7var SCRIPT_mypainting 7var SCRIPT_mypainting
8var SCRIPT_notifier 8var SCRIPT_notifier
9var SCRIPT_panel 9var SCRIPT_panel
10var SCRIPT_pilgrimage_terminator
10var SCRIPT_uuid 11var SCRIPT_uuid
11 12
12var ap_server = "" 13var ap_server = ""
@@ -15,60 +16,30 @@ var ap_pass = ""
15var confusify_world = false 16var confusify_world = false
16var enable_multiplayer = false 17var enable_multiplayer = false
17var track_player = false 18var track_player = false
19var connection_history = []
18 20
19const my_version = "2.1.0" 21const my_version = "3.0.1"
20const ap_version = {"major": 0, "minor": 4, "build": 5, "class": "Version"} 22const ap_version = {"major": 0, "minor": 4, "build": 6, "class": "Version"}
21const color_items = [ 23const color_items = [
22 "White", "Black", "Red", "Blue", "Green", "Brown", "Gray", "Orange", "Purple", "Yellow" 24 "White", "Black", "Red", "Blue", "Green", "Brown", "Gray", "Orange", "Purple", "Yellow"
23] 25]
24const progressive_items = { 26const progressive_items = {
25 "Progressive Orange Tower": 27 "Progressive Orange Tower":
26 [ 28 ["Second Floor", "Third Floor", "Fourth Floor", "Fifth Floor", "Sixth Floor", "Seventh Floor"],
27 {"item": "Orange Tower - Second Floor", "display": "Second Floor"},
28 {"item": "Orange Tower - Third Floor", "display": "Third Floor"},
29 {"item": "Orange Tower - Fourth Floor", "display": "Fourth Floor"},
30 {"item": "Orange Tower - Fifth Floor", "display": "Fifth Floor"},
31 {"item": "Orange Tower - Sixth Floor", "display": "Sixth Floor"},
32 {"item": "Orange Tower - Seventh Floor", "display": "Seventh Floor"},
33 ],
34 "Progressive Art Gallery": 29 "Progressive Art Gallery":
35 [ 30 ["Second Floor", "Third Floor", "Fourth Floor", "Fifth Floor", "Exit"],
36 {"item": "Art Gallery - Second Floor", "display": "Second Floor"}, 31 "Progressive Hallway Room": ["First Door", "Second Door", "Third Door", "Fourth Door"],
37 {"item": "Art Gallery - Third Floor", "display": "Third Floor"}, 32 "Progressive Fearless": ["Second Floor", "Third Floor"],
38 {"item": "Art Gallery - Fourth Floor", "display": "Fourth Floor"},
39 {"item": "Art Gallery - Fifth Floor", "display": "Fifth Floor"},
40 {"item": "Art Gallery - Exit", "display": "Exit"},
41 ],
42 "Progressive Hallway Room":
43 [
44 {"item": "Outside The Agreeable - Hallway Door", "display": "First Door"},
45 {"item": "Hallway Room (2) - Exit", "display": "Second Door"},
46 {"item": "Hallway Room (3) - Exit", "display": "Third Door"},
47 {"item": "Hallway Room (4) - Exit", "display": "Fourth Door"},
48 ],
49 "Progressive Fearless":
50 [
51 {"item": "The Fearless (First Floor) - Second Floor", "display": "Second Floor"},
52 {"item": "The Fearless (Second Floor) - Third Floor", "display": "Third Floor"},
53 ],
54 "Progressive Colorful": 33 "Progressive Colorful":
55 [ 34 ["White", "Black", "Red", "Yellow", "Blue", "Purple", "Orange", "Green", "Brown", "Gray"],
56 {"item": "The Colorful - White Door", "display": "White"}, 35 "Progressive Pilgrimage":
57 {"item": "The Colorful - Black Door", "display": "Black"}, 36 ["1 Sunwarp", "2 Sunwarp", "3 Sunwarp", "4 Sunwarp", "5 Sunwarp", "6 Sunwarp"]
58 {"item": "The Colorful - Red Door", "display": "Red"},
59 {"item": "The Colorful - Yellow Door", "display": "Yellow"},
60 {"item": "The Colorful - Blue Door", "display": "Blue"},
61 {"item": "The Colorful - Purple Door", "display": "Purple"},
62 {"item": "The Colorful - Orange Door", "display": "Orange"},
63 {"item": "The Colorful - Green Door", "display": "Green"},
64 {"item": "The Colorful - Brown Door", "display": "Brown"},
65 {"item": "The Colorful - Gray Door", "display": "Gray"},
66 ]
67} 37}
68 38
69const kTHE_END = 0 39const kTHE_END = 0
70const kTHE_MASTER = 1 40const kTHE_MASTER = 1
71const kLEVEL_2 = 2 41const kLEVEL_2 = 2
42const kPILGRIMAGE = 3
72 43
73const kNO_PANEL_SHUFFLE = 0 44const kNO_PANEL_SHUFFLE = 0
74const kREARRANGE_PANELS = 1 45const kREARRANGE_PANELS = 1
@@ -81,6 +52,12 @@ const kCLASSIFICATION_REMOTE_NORMAL = 0
81const kCLASSIFICATION_REMOTE_REDUCED = 1 52const kCLASSIFICATION_REMOTE_REDUCED = 1
82const kCLASSIFICATION_REMOTE_INSANITY = 2 53const kCLASSIFICATION_REMOTE_INSANITY = 2
83 54
55const kSUNWARP_ACCESS_NORMAL = 0
56const kSUNWARP_ACCESS_DISABLED = 1
57const kSUNWARP_ACCESS_UNLOCK = 2
58const kSUNWARP_ACCESS_INDIVIDUAL = 3
59const kSUNWARP_ACCESS_PROGRESSIVE = 4
60
84var _client = WebSocketClient.new() 61var _client = WebSocketClient.new()
85var _should_process = false 62var _should_process = false
86var _initiated_disconnect = false 63var _initiated_disconnect = false
@@ -94,6 +71,7 @@ var _item_name_to_id = {} # LINGO only
94var _location_name_to_id = {} # LINGO only 71var _location_name_to_id = {} # LINGO only
95 72
96var _remote_version = {"major": 0, "minor": 0, "build": 0} 73var _remote_version = {"major": 0, "minor": 0, "build": 0}
74var _gen_version = {"major": 0, "minor": 0, "build": 0}
97 75
98# TODO: caching per MW/slot, reset between connections 76# TODO: caching per MW/slot, reset between connections
99var _authenticated = false 77var _authenticated = false
@@ -102,6 +80,7 @@ var _team = 0
102var _slot = 0 80var _slot = 0
103var _players = [] 81var _players = []
104var _player_name_by_slot = {} 82var _player_name_by_slot = {}
83var _game_by_player = {}
105var _checked_locations = [] 84var _checked_locations = []
106var _slot_data = {} 85var _slot_data = {}
107var _paintings_mapping = {} 86var _paintings_mapping = {}
@@ -112,10 +91,17 @@ var _door_shuffle = false
112var _color_shuffle = false 91var _color_shuffle = false
113var _panel_shuffle = 0 # none, rearrange 92var _panel_shuffle = 0 # none, rearrange
114var _painting_shuffle = false 93var _painting_shuffle = false
94var _sunwarp_access = 0 # normal, disabled, unlock, progressive
115var _mastery_achievements = 21 95var _mastery_achievements = 21
116var _level_2_requirement = 223 96var _level_2_requirement = 223
117var _location_classification_bit = 0 97var _location_classification_bit = 0
118var _early_color_hallways = false 98var _early_color_hallways = false
99var _pilgrimage_compatibility = false # set to true for pre-0.4.6
100var _pilgrimage_enabled = false
101var _pilgrimage_allows_roof_access = false
102var _pilgrimage_allows_paintings = false
103var _sunwarp_shuffle = false
104var _sunwarp_mapping = []
119var _slot_seed = 0 105var _slot_seed = 0
120 106
121var _map_loaded = false 107var _map_loaded = false
@@ -147,6 +133,10 @@ func _init():
147 var data = file.get_var(true) 133 var data = file.get_var(true)
148 file.close() 134 file.close()
149 135
136 if typeof(data) != TYPE_ARRAY:
137 global._print("AP settings file is corrupted")
138 data = []
139
150 if data.size() > 0: 140 if data.size() > 0:
151 ap_server = data[0] 141 ap_server = data[0]
152 if data.size() > 1: 142 if data.size() > 1:
@@ -161,6 +151,8 @@ func _init():
161 enable_multiplayer = data[5] 151 enable_multiplayer = data[5]
162 if data.size() > 6: 152 if data.size() > 6:
163 track_player = data[6] 153 track_player = data[6]
154 if data.size() > 7:
155 connection_history = data[7]
164 156
165 processDatapackages() 157 processDatapackages()
166 158
@@ -230,6 +222,7 @@ func _on_data():
230 if cmd == "RoomInfo": 222 if cmd == "RoomInfo":
231 _seed = message["seed_name"] 223 _seed = message["seed_name"]
232 _remote_version = message["version"] 224 _remote_version = message["version"]
225 _gen_version = message["generator_version"]
233 226
234 var needed_games = [] 227 var needed_games = []
235 for game in message["datapackage_checksums"].keys(): 228 for game in message["datapackage_checksums"].keys():
@@ -268,6 +261,7 @@ func _on_data():
268 261
269 for player in _players: 262 for player in _players:
270 _player_name_by_slot[player["slot"]] = player["alias"] 263 _player_name_by_slot[player["slot"]] = player["alias"]
264 _game_by_player[player["slot"]] = message["slot_info"][str(player["slot"])]["game"]
271 265
272 _death_link = _slot_data.has("death_link") and _slot_data["death_link"] 266 _death_link = _slot_data.has("death_link") and _slot_data["death_link"]
273 if _death_link: 267 if _death_link:
@@ -283,6 +277,10 @@ func _on_data():
283 _painting_shuffle = _slot_data["shuffle_paintings"] 277 _painting_shuffle = _slot_data["shuffle_paintings"]
284 if _slot_data.has("shuffle_panels"): 278 if _slot_data.has("shuffle_panels"):
285 _panel_shuffle = _slot_data["shuffle_panels"] 279 _panel_shuffle = _slot_data["shuffle_panels"]
280 if _slot_data.has("sunwarp_access"):
281 _sunwarp_access = _slot_data["sunwarp_access"]
282 else:
283 _sunwarp_access = kSUNWARP_ACCESS_NORMAL
286 if _slot_data.has("seed"): 284 if _slot_data.has("seed"):
287 _slot_seed = _slot_data["seed"] 285 _slot_seed = _slot_data["seed"]
288 if _slot_data.has("painting_entrance_to_exit"): 286 if _slot_data.has("painting_entrance_to_exit"):
@@ -300,6 +298,25 @@ func _on_data():
300 _location_classification_bit = kCLASSIFICATION_LOCAL_INSANITY 298 _location_classification_bit = kCLASSIFICATION_LOCAL_INSANITY
301 if _slot_data.has("early_color_hallways"): 299 if _slot_data.has("early_color_hallways"):
302 _early_color_hallways = _slot_data["early_color_hallways"] 300 _early_color_hallways = _slot_data["early_color_hallways"]
301 if _slot_data.has("enable_pilgrimage"):
302 _pilgrimage_enabled = _slot_data["enable_pilgrimage"]
303 else:
304 _pilgrimage_compatibility = true
305 _pilgrimage_enabled = true
306 if _slot_data.has("pilgrimage_allows_roof_access"):
307 _pilgrimage_allows_roof_access = _slot_data["pilgrimage_allows_roof_access"]
308 else:
309 _pilgrimage_allows_roof_access = true
310 if _slot_data.has("pilgrimage_allows_paintings"):
311 _pilgrimage_allows_paintings = _slot_data["pilgrimage_allows_paintings"]
312 else:
313 _pilgrimage_allows_paintings = true
314 if _slot_data.has("shuffle_sunwarps"):
315 _sunwarp_shuffle = _slot_data["shuffle_sunwarps"]
316 else:
317 _sunwarp_shuffle = false
318 if _slot_data.has("sunwarp_permutation"):
319 _sunwarp_mapping = _slot_data["sunwarp_permutation"]
303 320
304 if track_player: 321 if track_player:
305 setValue("PlayerPos", {"x": 0, "z": 0}) 322 setValue("PlayerPos", {"x": 0, "z": 0})
@@ -315,6 +332,10 @@ func _on_data():
315 var localdata = ap_file.get_var(true) 332 var localdata = ap_file.get_var(true)
316 ap_file.close() 333 ap_file.close()
317 334
335 if typeof(localdata) != TYPE_ARRAY:
336 global._print("AP localdata file is corrupted")
337 localdata = []
338
318 if localdata.size() > 0: 339 if localdata.size() > 0:
319 _last_new_item = localdata[0] 340 _last_new_item = localdata[0]
320 else: 341 else:
@@ -412,12 +433,14 @@ func _on_data():
412 continue 433 continue
413 434
414 var item_name = "Unknown" 435 var item_name = "Unknown"
415 if _item_id_to_name.has(message["item"]["item"]): 436 var item_player_game = _game_by_player[message["receiving"]]
416 item_name = _item_id_to_name[message["item"]["item"]] 437 if _item_id_to_name[item_player_game].has(message["item"]["item"]):
438 item_name = _item_id_to_name[item_player_game][message["item"]["item"]]
417 439
418 var location_name = "Unknown" 440 var location_name = "Unknown"
419 if _location_id_to_name.has(message["item"]["location"]): 441 var location_player_game = _game_by_player[message["item"]["player"]]
420 location_name = _location_id_to_name[message["item"]["location"]] 442 if _location_id_to_name[location_player_game].has(message["item"]["location"]):
443 location_name = _location_id_to_name[location_player_game][message["item"]["location"]]
421 444
422 var player_name = "Unknown" 445 var player_name = "Unknown"
423 if _player_name_by_slot.has(message["receiving"]): 446 if _player_name_by_slot.has(message["receiving"]):
@@ -485,7 +508,8 @@ func saveSettings():
485 _datapackages, 508 _datapackages,
486 confusify_world, 509 confusify_world,
487 enable_multiplayer, 510 enable_multiplayer,
488 track_player 511 track_player,
512 connection_history
489 ] 513 ]
490 file.store_var(data, true) 514 file.store_var(data, true)
491 file.close() 515 file.close()
@@ -566,12 +590,16 @@ func requestDatapackages(games):
566func processDatapackages(): 590func processDatapackages():
567 _item_id_to_name = {} 591 _item_id_to_name = {}
568 _location_id_to_name = {} 592 _location_id_to_name = {}
569 for package in _datapackages.values(): 593 for game in _datapackages.keys():
594 var package = _datapackages[game]
595
596 _item_id_to_name[game] = {}
570 for name in package["item_name_to_id"].keys(): 597 for name in package["item_name_to_id"].keys():
571 _item_id_to_name[package["item_name_to_id"][name]] = name 598 _item_id_to_name[game][package["item_name_to_id"][name]] = name
572 599
600 _location_id_to_name[game] = {}
573 for name in package["location_name_to_id"].keys(): 601 for name in package["location_name_to_id"].keys():
574 _location_id_to_name[package["location_name_to_id"][name]] = name 602 _location_id_to_name[game][package["location_name_to_id"][name]] = name
575 603
576 if _datapackages.has("Lingo"): 604 if _datapackages.has("Lingo"):
577 _item_name_to_id = _datapackages["Lingo"]["item_name_to_id"] 605 _item_name_to_id = _datapackages["Lingo"]["item_name_to_id"]
@@ -660,8 +688,8 @@ func processItem(item, index, from, flags):
660 688
661 var gamedata = $Gamedata 689 var gamedata = $Gamedata
662 var item_name = "Unknown" 690 var item_name = "Unknown"
663 if _item_id_to_name.has(item): 691 if _item_id_to_name["Lingo"].has(item):
664 item_name = _item_id_to_name[item] 692 item_name = _item_id_to_name["Lingo"][item]
665 693
666 if gamedata.door_ids_by_item_id.has(int(item)): 694 if gamedata.door_ids_by_item_id.has(int(item)):
667 var doorsNode = get_tree().get_root().get_node("Spatial/Doors") 695 var doorsNode = get_tree().get_root().get_node("Spatial/Doors")
@@ -682,19 +710,25 @@ func processItem(item, index, from, flags):
682 if painting_node != null: 710 if painting_node != null:
683 painting_node.get_node("Script").movePainting() 711 painting_node.get_node("Script").movePainting()
684 712
713 if gamedata.warp_ids_by_item_id.has(int(item)):
714 var warpsNode = get_tree().get_root().get_node("Spatial/Warps")
715 for warp_id in gamedata.warp_ids_by_item_id[int(item)]:
716 warpsNode.get_node(warp_id).unlock_warp()
717
685 # Handle progressive items. 718 # Handle progressive items.
686 if item_name in progressive_items.keys(): 719 if int(item) in gamedata.items_by_progressive_id.keys():
687 if not item_name in _progressive_progress: 720 if not int(item) in _progressive_progress:
688 _progressive_progress[item_name] = 0 721 _progressive_progress[int(item)] = 0
689 722
690 if _progressive_progress[item_name] < progressive_items[item_name].size(): 723 if _progressive_progress[int(item)] < gamedata.items_by_progressive_id[int(item)].size():
691 var subitem_name = progressive_items[item_name][_progressive_progress[item_name]]["item"] 724 var subitems = gamedata.items_by_progressive_id[int(item)]
692 global._print(subitem_name) 725 var subitem_id = subitems[_progressive_progress[int(item)]]
693 processItem(_item_name_to_id[subitem_name], null, null, null) 726 global._print("Subitem: %d" % subitem_id)
694 _progressive_progress[item_name] += 1 727 processItem(subitem_id, null, null, null)
695 728 _progressive_progress[int(item)] += 1
696 if _color_shuffle and color_items.has(_item_id_to_name[item]): 729
697 var lcol = _item_id_to_name[item].to_lower() 730 if _color_shuffle and color_items.has(_item_id_to_name["Lingo"][item]):
731 var lcol = _item_id_to_name["Lingo"][item].to_lower()
698 if not _has_colors.has(lcol): 732 if not _has_colors.has(lcol):
699 _has_colors.append(lcol) 733 _has_colors.append(lcol)
700 emit_signal("evaluate_solvability") 734 emit_signal("evaluate_solvability")
@@ -705,8 +739,8 @@ func processItem(item, index, from, flags):
705 saveLocaldata() 739 saveLocaldata()
706 740
707 if item_name in progressive_items: 741 if item_name in progressive_items:
708 var subitem = progressive_items[item_name][_progressive_progress[item_name] - 1] 742 var subitem = progressive_items[item_name][_progressive_progress[int(item)] - 1]
709 item_name += " (%s)" % subitem["display"] 743 item_name += " (%s)" % subitem
710 744
711 var player_name = "Unknown" 745 var player_name = "Unknown"
712 if _player_name_by_slot.has(from): 746 if _player_name_by_slot.has(from):
@@ -742,6 +776,10 @@ func paintingIsVanilla(painting):
742 return !$Gamedata.mentioned_paintings.has(painting) 776 return !$Gamedata.mentioned_paintings.has(painting)
743 777
744 778
779func warpIsVanilla(warp):
780 return !$Gamedata.mentioned_warps.has(warp)
781
782
745func evaluateSolvability(): 783func evaluateSolvability():
746 emit_signal("evaluate_solvability") 784 emit_signal("evaluate_solvability")
747 785
@@ -775,3 +813,17 @@ func colorForItemType(flags):
775 return "#d63a22" 813 return "#d63a22"
776 else: # filler 814 else: # filler
777 return "#14de9e" 815 return "#14de9e"
816
817
818func compareVersion(lhs, rhs):
819 if lhs["major"] == rhs["major"]:
820 if lhs["minor"] == rhs["minor"]:
821 return lhs["build"] < rhs["build"]
822 else:
823 return lhs["minor"] < rhs["minor"]
824 else:
825 return lhs["major"] < rhs["major"]
826
827
828func wasGeneratedBeforeVersion(major, minor, build):
829 return compareVersion(_gen_version, {"major": major, "minor": minor, "build": build})
diff --git a/Archipelago/load.gd b/Archipelago/load.gd index 1b77c9e..931dfde 100644 --- a/Archipelago/load.gd +++ b/Archipelago/load.gd
@@ -96,18 +96,19 @@ func _load():
96 96
97 wanderer_achieve.translation = Vector3(-51, -33, 35) # way under the map 97 wanderer_achieve.translation = Vector3(-51, -33, 35) # way under the map
98 98
99 # Turn THE COLORFUL into a cdp.
100 var real_colorful = panels_parent.get_node("Countdown Panels/Panel_colorful_colorful")
101 var cdp_auto_scene = load("res://nodes/panel_countdown_auto.tscn") 99 var cdp_auto_scene = load("res://nodes/panel_countdown_auto.tscn")
102 var colorful_cdp = cdp_auto_scene.instance() 100 if !apclient.wasGeneratedBeforeVersion(0, 4, 5):
103 colorful_cdp.name = "CountdownPanel_colorful" 101 # Turn THE COLORFUL into a cdp.
104 colorful_cdp.replace_with = "../../Panels/Countdown Panels/Panel_colorful_colorful" 102 var real_colorful = panels_parent.get_node("Countdown Panels/Panel_colorful_colorful")
105 colorful_cdp.panels = "../../Panels/Doorways Room" 103 var colorful_cdp = cdp_auto_scene.instance()
106 colorful_cdp.translation = real_colorful.translation 104 colorful_cdp.name = "CountdownPanel_colorful"
107 colorful_cdp.rotation = real_colorful.rotation 105 colorful_cdp.replace_with = "../../Panels/Countdown Panels/Panel_colorful_colorful"
108 get_node("CountdownPanels").add_child(colorful_cdp) 106 colorful_cdp.panels = "../../Panels/Doorways Room"
109 real_colorful.translation = Vector3(-51, -35, 35) # way under the map 107 colorful_cdp.translation = real_colorful.translation
110 get_node("Doors/Doorway Room Doors/Door_gray2").queue_free() 108 colorful_cdp.rotation = real_colorful.rotation
109 get_node("CountdownPanels").add_child(colorful_cdp)
110 real_colorful.translation = Vector3(-51, -35, 35) # way under the map
111 get_node("Doors/Doorway Room Doors/Door_gray2").queue_free()
111 112
112 # Set up The Master to be variable. 113 # Set up The Master to be variable.
113 var old_master_cdp = get_node("CountdownPanels/CountdownPanel_countdown_16") 114 var old_master_cdp = get_node("CountdownPanels/CountdownPanel_countdown_16")
@@ -262,6 +263,9 @@ func _load():
262 hidden_parent.get_node("hidden_door_58").translation.x = 48 263 hidden_parent.get_node("hidden_door_58").translation.x = 48
263 hidden_parent.get_node("hidden_door_58")._setReference("whiteBlock") 264 hidden_parent.get_node("hidden_door_58")._setReference("whiteBlock")
264 265
266 # Remove Fearless entrance indicator.
267 get_node("Decorations/Signs/Miscellaneous/Sign14").queue_free()
268
265 if apclient._panel_shuffle != apclient.kNO_PANEL_SHUFFLE: 269 if apclient._panel_shuffle != apclient.kNO_PANEL_SHUFFLE:
266 # Make The Wondrous's FIRE solely midred. 270 # Make The Wondrous's FIRE solely midred.
267 clear_gridmap_tile(-76.5, 1.5, -73.5) 271 clear_gridmap_tile(-76.5, 1.5, -73.5)
@@ -353,6 +357,8 @@ func _load():
353 victory_condition = "the master" 357 victory_condition = "the master"
354 elif apclient._victory_condition == apclient.kLEVEL_2: 358 elif apclient._victory_condition == apclient.kLEVEL_2:
355 victory_condition = "level 2" 359 victory_condition = "level 2"
360 elif apclient._victory_condition == apclient.kPILGRIMAGE:
361 victory_condition = "pilgrimage"
356 362
357 set_static_panel("Entry Room/Panel_this_this", victory_condition) 363 set_static_panel("Entry Room/Panel_this_this", victory_condition)
358 set_static_panel("Entry Room/Panel_hidden_hidden", "hewwo") 364 set_static_panel("Entry Room/Panel_hidden_hidden", "hewwo")
@@ -572,11 +578,84 @@ func _load():
572 level_2.get_node("Viewport/GUI/Panel/TextEdit").connect( 578 level_2.get_node("Viewport/GUI/Panel/TextEdit").connect(
573 "answer_correct", apclient, "completedGoal" 579 "answer_correct", apclient, "completedGoal"
574 ) 580 )
581 elif apclient._victory_condition == apclient.kPILGRIMAGE:
582 var pilgrim_panel = self.get_node("Panels/Lingo Room/Panel_pilgrim")
583 pilgrim_panel.get_node("Viewport/GUI/Panel/TextEdit").connect(
584 "answer_correct", apclient, "completedGoal"
585 )
575 else: 586 else:
576 var the_end = self.get_node("Decorations/EndPanel/Panel_end_end") 587 var the_end = self.get_node("Decorations/EndPanel/Panel_end_end")
577 the_end.get_node("Viewport/GUI/Panel/TextEdit").connect( 588 the_end.get_node("Viewport/GUI/Panel/TextEdit").connect(
578 "answer_correct", apclient, "completedGoal" 589 "answer_correct", apclient, "completedGoal"
579 ) 590 )
591
592 # If pilgrimage does not allow roof access, add a node on the Crossroads
593 # Roof Access stairs that disables it.
594 if !apclient._pilgrimage_allows_roof_access:
595 var terminator = apclient.SCRIPT_pilgrimage_terminator.new()
596 terminator.name = "RoofAccessPilgrimageTerminator"
597 terminator.translation.x = -36
598 terminator.translation.y = 3
599 terminator.translation.z = -35
600
601 var terminator_shape = CollisionShape.new()
602 terminator_shape.shape = BoxShape.new()
603 terminator_shape.shape.extents.x = 0.1
604
605 terminator.add_child(terminator_shape)
606 get_node("Decorations").add_child(terminator)
607
608 if apclient._sunwarp_shuffle:
609 # Sunwarps 1 and 6 are rotated differently from the rest, so we have to fix that.
610 get_node("Decorations/Teleporter Windows/localmap").rotation_degrees.y = 0
611 get_node("Decorations/Teleporter Windows/localmap2").rotation_degrees.y = 0
612 get_node("Decorations/Teleporter Windows/localmap11").rotation_degrees.y = 0
613 get_node("Decorations/Teleporter Windows/localmap12").rotation_degrees.y = 0
614 get_node("Decorations/Teleporter Windows/localmap13").rotation_degrees.y = -90
615
616 get_node("Warps/Teleporter Warps/Sunwarp_enter_1").translation.x = 19.5
617 get_node("Warps/Teleporter Warps/Sunwarp_exit_1").translation.x = -15.5
618 get_node("Warps/Teleporter Warps/Sunwarp_enter_6").translation.x = 4.5
619 get_node("Warps/Teleporter Warps/Sunwarp_exit_6").translation.x = -37.5
620 get_node("Warps/Teleporter Warps/Sunwarp_exit_7").translation.z = 23.5
621
622 # Change the sunwarps in accordance with the mapping.
623 var sw_orig_translations = []
624 var sw_text_translations = []
625 var sw_text_rotations = []
626 for i in range(1,7):
627 sw_orig_translations.append(get_node("Warps/Teleporter Warps/Sunwarp_enter_%d" % i).translation)
628 sw_text_translations.append(get_node("Decorations/Signs/Sunwarp Numbers/enter_%d" % i).translation)
629 sw_text_rotations.append(get_node("Decorations/Signs/Sunwarp Numbers/enter_%d" % i).rotation_degrees)
630 for i in range(1,7):
631 sw_orig_translations.append(get_node("Warps/Teleporter Warps/Sunwarp_exit_%d" % i).translation)
632 sw_text_translations.append(get_node("Decorations/Signs/Sunwarp Numbers/exit_%d" % i).translation)
633 sw_text_rotations.append(get_node("Decorations/Signs/Sunwarp Numbers/exit_%d" % i).rotation_degrees)
634
635 var sw_enter_indicators = [4, 5, 6, 12, 7, 10]
636 for i in range(1,7):
637 get_node("Warps/Teleporter Warps/Sunwarp_enter_%d" % i).translation = sw_orig_translations[apclient._sunwarp_mapping[i-1]]
638 get_node("Warps/Teleporter Warps/Sunwarp_exit_%d" % i).translation = sw_orig_translations[apclient._sunwarp_mapping[i+5]]
639
640 get_node("Decorations/Signs/Sunwarp Numbers/enter_%d" % i).translation = sw_text_translations[apclient._sunwarp_mapping[i-1]]
641 get_node("Decorations/Signs/Sunwarp Numbers/enter_%d" % i).rotation_degrees = sw_text_rotations[apclient._sunwarp_mapping[i-1]]
642
643 get_node("Decorations/Signs/Sunwarp Numbers/exit_%d" % i).translation = sw_text_translations[apclient._sunwarp_mapping[i+5]]
644 get_node("Decorations/Signs/Sunwarp Numbers/exit_%d" % i).rotation_degrees = sw_text_rotations[apclient._sunwarp_mapping[i+5]]
645
646 var enter_rot = _dir_to_int(gamedata.sunwarps[apclient._sunwarp_mapping[i-1]]["orientation"]) * 90
647 var exit_rot = _dir_to_int(gamedata.sunwarps[apclient._sunwarp_mapping[i+5]]["orientation"]) * 90
648 var final_rot = enter_rot - exit_rot
649 if final_rot < 0:
650 final_rot += 360
651 get_node("Warps/Teleporter Warps/Sunwarp_enter_%d" % i).rotate = str(final_rot)
652
653 var sw_enter_indicator_pos = gamedata.sunwarps[apclient._sunwarp_mapping[i-1]]["entrance_indicator_pos"]
654 var sw_enter_indicator = get_node("Decorations/Signs/Welcome Back Signs/Sign%d" % sw_enter_indicators[i-1])
655 sw_enter_indicator.translation.x = sw_enter_indicator_pos[0]
656 sw_enter_indicator.translation.y = sw_enter_indicator_pos[1]
657 sw_enter_indicator.translation.z = sw_enter_indicator_pos[2]
658 sw_enter_indicator.rotation_degrees.y = (enter_rot * -1) + 180
580 659
581 # Create the effects node. 660 # Create the effects node.
582 var effects_script = apclient.SCRIPT_effects 661 var effects_script = apclient.SCRIPT_effects
@@ -707,3 +786,15 @@ func set_small_gridmap_tile(x, y, z, tile):
707 786
708func archipelago_disconnected(reason): 787func archipelago_disconnected(reason):
709 messages.showMessage(reason) 788 messages.showMessage(reason)
789
790
791func _dir_to_int(dir):
792 if dir == "north":
793 return 0
794 elif dir == "west":
795 return 1
796 elif dir == "south":
797 return 2
798 elif dir == "east":
799 return 3
800 return 4
diff --git a/Archipelago/mypainting.gd b/Archipelago/mypainting.gd index 5e9c703..999b122 100644 --- a/Archipelago/mypainting.gd +++ b/Archipelago/mypainting.gd
@@ -86,6 +86,11 @@ func _looked_at(body, painting):
86 body.rotate_y(3 * PI / 2) 86 body.rotate_y(3 * PI / 2)
87 body.velocity = body.velocity.rotated(Vector3(0, 1, 0), 3 * PI / 2) 87 body.velocity = body.velocity.rotated(Vector3(0, 1, 0), 3 * PI / 2)
88 88
89 var apclient = global.get_node("Archipelago")
90 if !apclient._pilgrimage_allows_paintings:
91 global.sunwarp = 1
92 body.get_node("pivot/camera/sunwarp_background").visible = false
93
89 94
90func _dir_to_int(dir): 95func _dir_to_int(dir):
91 if dir == "north": 96 if dir == "north":
diff --git a/Archipelago/painting.gd b/Archipelago/painting.gd new file mode 100644 index 0000000..adc8337 --- /dev/null +++ b/Archipelago/painting.gd
@@ -0,0 +1,10 @@
1extends "res://scripts/painting.gd"
2
3func _looked_at(var body, var painting):
4 ._looked_at(body, painting)
5
6 if body.is_in_group("player") && (painting.get_name() == self.get_name()):
7 var apclient = global.get_node("Archipelago")
8 if !apclient._pilgrimage_allows_paintings:
9 global.sunwarp = 1
10 body.get_node("pivot/camera/sunwarp_background").visible = false
diff --git a/Archipelago/painting_eye.gd b/Archipelago/painting_eye.gd index 53d42b5..b2e6973 100644 --- a/Archipelago/painting_eye.gd +++ b/Archipelago/painting_eye.gd
@@ -3,9 +3,23 @@ extends "res://scripts/painting_eye.gd"
3 3
4func _answer_correct(): 4func _answer_correct():
5 var apclient = global.get_node("Archipelago") 5 var apclient = global.get_node("Archipelago")
6 if not apclient._door_shuffle or apclient.paintingIsVanilla(self.name): 6 if !apclient._pilgrimage_compatibility and get_name() == "pilgrim_painting2":
7 # When pilgrimage is enabled, the HOT CRUST panel should actually move the sun painting.
8 if apclient._pilgrimage_enabled:
9 movePainting()
10 elif not apclient._door_shuffle or apclient.paintingIsVanilla(self.name):
7 ._answer_correct() 11 ._answer_correct()
8 12
9 13
10func movePainting(): 14func movePainting():
11 ._answer_correct() 15 ._answer_correct()
16
17
18func _looked_at(var body, var painting):
19 ._looked_at(body, painting)
20
21 if body.is_in_group("player") && (painting.get_name() == self.get_name()):
22 var apclient = global.get_node("Archipelago")
23 if !apclient._pilgrimage_allows_paintings:
24 global.sunwarp = 1
25 body.get_node("pivot/camera/sunwarp_background").visible = false
diff --git a/Archipelago/painting_scenery.gd b/Archipelago/painting_scenery.gd index f49d602..1186e2f 100644 --- a/Archipelago/painting_scenery.gd +++ b/Archipelago/painting_scenery.gd
@@ -9,3 +9,13 @@ func _answer_correct():
9 9
10func movePainting(): 10func movePainting():
11 ._answer_correct() 11 ._answer_correct()
12
13
14func _looked_at(var body, var painting):
15 ._looked_at(body, painting)
16
17 if body.is_in_group("player") && (painting.get_name() == self.get_name()):
18 var apclient = global.get_node("Archipelago")
19 if !apclient._pilgrimage_allows_paintings:
20 global.sunwarp = 1
21 body.get_node("pivot/camera/sunwarp_background").visible = false
diff --git a/Archipelago/panel.gd b/Archipelago/panel.gd index aec18e8..fc5963a 100644 --- a/Archipelago/panel.gd +++ b/Archipelago/panel.gd
@@ -22,7 +22,7 @@ func _ready():
22 else: 22 else:
23 atbash_text += old_char 23 atbash_text += old_char
24 24
25 self.get_parent().get_node("Viewport/GUI/Panel/TextEdit").connect( 25 var _ignore = self.get_parent().get_node("Viewport/GUI/Panel/TextEdit").connect(
26 "answer_correct", self, "answer_correct" 26 "answer_correct", self, "answer_correct"
27 ) 27 )
28 28
diff --git a/Archipelago/pilgrimage_terminator.gd b/Archipelago/pilgrimage_terminator.gd new file mode 100644 index 0000000..29db2ee --- /dev/null +++ b/Archipelago/pilgrimage_terminator.gd
@@ -0,0 +1,11 @@
1extends Area
2
3
4func _ready():
5 var _connected = self.connect("body_entered", self, "_body_entered")
6
7
8func _body_entered(body):
9 if body.is_in_group("player"):
10 global.sunwarp = 1
11 body.get_node("pivot/camera/sunwarp_background").visible = false
diff --git a/Archipelago/settings_screen.gd b/Archipelago/settings_screen.gd index de64214..79fdcc3 100644 --- a/Archipelago/settings_screen.gd +++ b/Archipelago/settings_screen.gd
@@ -30,6 +30,8 @@ func _ready():
30 apclient_instance.SCRIPT_mypainting = load("user://maps/Archipelago/mypainting.gd") 30 apclient_instance.SCRIPT_mypainting = load("user://maps/Archipelago/mypainting.gd")
31 apclient_instance.SCRIPT_notifier = load("user://maps/Archipelago/notifier.gd") 31 apclient_instance.SCRIPT_notifier = load("user://maps/Archipelago/notifier.gd")
32 apclient_instance.SCRIPT_panel = load("user://maps/Archipelago/panel.gd") 32 apclient_instance.SCRIPT_panel = load("user://maps/Archipelago/panel.gd")
33 var pilg_term = load("user://maps/Archipelago/pilgrimage_terminator.gd")
34 apclient_instance.SCRIPT_pilgrimage_terminator = pilg_term
33 apclient_instance.SCRIPT_uuid = load("user://maps/Archipelago/vendor/uuid.gd") 35 apclient_instance.SCRIPT_uuid = load("user://maps/Archipelago/vendor/uuid.gd")
34 36
35 var apdata = ResourceLoader.load("user://maps/Archipelago/gamedata.gd") 37 var apdata = ResourceLoader.load("user://maps/Archipelago/gamedata.gd")
@@ -45,6 +47,7 @@ func _ready():
45 # Let's also inject any scripts we need to inject now. 47 # Let's also inject any scripts we need to inject now.
46 installScriptExtension(apclient_instance.SCRIPT_doorControl) 48 installScriptExtension(apclient_instance.SCRIPT_doorControl)
47 installScriptExtension(ResourceLoader.load("user://maps/Archipelago/load.gd")) 49 installScriptExtension(ResourceLoader.load("user://maps/Archipelago/load.gd"))
50 installScriptExtension(ResourceLoader.load("user://maps/Archipelago/painting.gd"))
48 installScriptExtension(ResourceLoader.load("user://maps/Archipelago/painting_eye.gd")) 51 installScriptExtension(ResourceLoader.load("user://maps/Archipelago/painting_eye.gd"))
49 installScriptExtension(ResourceLoader.load("user://maps/Archipelago/painting_scenery.gd")) 52 installScriptExtension(ResourceLoader.load("user://maps/Archipelago/painting_scenery.gd"))
50 installScriptExtension(ResourceLoader.load("user://maps/Archipelago/panelLevelSwitch.gd")) 53 installScriptExtension(ResourceLoader.load("user://maps/Archipelago/panelLevelSwitch.gd"))
@@ -52,6 +55,7 @@ func _ready():
52 installScriptExtension(ResourceLoader.load("user://maps/Archipelago/panelInput.gd")) 55 installScriptExtension(ResourceLoader.load("user://maps/Archipelago/panelInput.gd"))
53 installScriptExtension(ResourceLoader.load("user://maps/Archipelago/pause_menu.gd")) 56 installScriptExtension(ResourceLoader.load("user://maps/Archipelago/pause_menu.gd"))
54 installScriptExtension(ResourceLoader.load("user://maps/Archipelago/player.gd")) 57 installScriptExtension(ResourceLoader.load("user://maps/Archipelago/player.gd"))
58 installScriptExtension(ResourceLoader.load("user://maps/Archipelago/teleport.gd"))
55 installScriptExtension(ResourceLoader.load("user://maps/Archipelago/worldTransporter.gd")) 59 installScriptExtension(ResourceLoader.load("user://maps/Archipelago/worldTransporter.gd"))
56 60
57 var apclient = global.get_node("Archipelago") 61 var apclient = global.get_node("Archipelago")
@@ -67,6 +71,19 @@ func _ready():
67 self.get_node("Panel/multiplayer_box").pressed = apclient.enable_multiplayer 71 self.get_node("Panel/multiplayer_box").pressed = apclient.enable_multiplayer
68 self.get_node("Panel/position_box").pressed = apclient.track_player 72 self.get_node("Panel/position_box").pressed = apclient.track_player
69 73
74 var history_box = get_node("Panel/connection_history")
75 if apclient.connection_history.empty():
76 history_box.disabled = true
77 else:
78 history_box.disabled = false
79
80 var i = 0
81 for details in apclient.connection_history:
82 history_box.get_popup().add_item("%s (%s)" % [details[1], details[0]], i)
83 i += 1
84
85 history_box.get_popup().connect("id_pressed", self, "historySelected")
86
70 # Show client version. 87 # Show client version.
71 self.get_node("Panel/title").text = "ARCHIPELAGO (%s)" % apclient.my_version 88 self.get_node("Panel/title").text = "ARCHIPELAGO (%s)" % apclient.my_version
72 89
@@ -109,6 +126,15 @@ func connectionStatus(message):
109func connectionSuccessful(): 126func connectionSuccessful():
110 var apclient = global.get_node("Archipelago") 127 var apclient = global.get_node("Archipelago")
111 128
129 # Save connection details
130 var connection_details = [apclient.ap_server, apclient.ap_user, apclient.ap_pass]
131 if apclient.connection_history.has(connection_details):
132 apclient.connection_history.erase(connection_details)
133 apclient.connection_history.push_front(connection_details)
134 if apclient.connection_history.size() > 10:
135 apclient.connection_history.resize(10)
136 apclient.saveSettings()
137
112 # Switch to LL1 138 # Switch to LL1
113 Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) 139 Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
114 global.save_file = apclient.getSaveFileName() 140 global.save_file = apclient.getSaveFileName()
@@ -130,3 +156,12 @@ func connectionUnsuccessful(error_message):
130 popup.popup_exclusive = true 156 popup.popup_exclusive = true
131 popup.get_ok().visible = true 157 popup.get_ok().visible = true
132 popup.popup_centered() 158 popup.popup_centered()
159
160
161func historySelected(index):
162 var apclient = global.get_node("Archipelago")
163 var details = apclient.connection_history[index]
164
165 self.get_node("Panel/server_box").text = details[0]
166 self.get_node("Panel/player_box").text = details[1]
167 self.get_node("Panel/password_box").text = details[2]
diff --git a/Archipelago/teleport.gd b/Archipelago/teleport.gd new file mode 100644 index 0000000..532f081 --- /dev/null +++ b/Archipelago/teleport.gd
@@ -0,0 +1,27 @@
1extends "res://scripts/teleport.gd"
2
3var _unlocked = true
4
5
6func _ready():
7 var apclient = global.get_node("Archipelago")
8 if self.get_parent().name == "Teleporter Warps":
9 if apclient._sunwarp_access != apclient.kSUNWARP_ACCESS_NORMAL:
10 _unlocked = false
11 elif apclient._door_shuffle and !apclient.warpIsVanilla(self.get_parent().name + "/" + self.name):
12 _unlocked = false
13
14
15func _body_entered(body):
16 if _unlocked:
17 ._body_entered(body)
18
19 if body.is_in_group("player"):
20 var apclient = global.get_node("Archipelago")
21 if !apclient._pilgrimage_enabled:
22 global.sunwarp = 1
23 body.get_node("pivot/camera/sunwarp_background").visible = false
24
25
26func unlock_warp():
27 _unlocked = true
diff --git a/CHANGELOG.md b/CHANGELOG.md index a5ef1f2..de47cb0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md
@@ -1,5 +1,56 @@
1# lingo-archipelago Releases 1# lingo-archipelago Releases
2 2
3## v3.0.1 - 2024-04-22
4
5- Fixed issue where Progressive Hallway Room did not work properly on worlds
6 generated on Archipelago 0.4.5 or earlier.
7
8Download:
9[lingo-archipelago-v3.0.1.zip](https://files.fourisland.com/releases/lingo-archipelago/lingo-archipelago-v3.0.1.zip)<br/>
10Source: [v3.0.1](https://code.fourisland.com/lingo-archipelago/tag/?h=v3.0.1)
11
12## v3.0.0 - 2024-04-22
13
14- [Archipelago 0.4.6](https://github.com/ArchipelagoMW/Archipelago/releases/tag/0.4.6)
15 has been released! This includes a major update for Lingo: The Pilgrim Update!
16 - The pilgrimage can now be disabled entirely.
17 - When enabled, the pilgrimage uses real logic to determine whether it is
18 possible, rather than a specific route.
19 - You can now specify whether paintings and/or roof access are allowed for the
20 pilgrimage.
21 - You can lock access to sunwarps behind item keys, like door shuffle.
22 - Sunwarps can be shuffled, similar to painting shuffle.
23 - Pilgrimage has been added as a win condition.
24- This update should retain backwards compatibility with Archipelago 0.4.5
25 worlds. World generated in Archipelago 0.4.4 will likely continue to have
26 minor problems, and it is best to downpatch to v1.2.1 if you need to play an
27 older world.
28
29Download:
30[lingo-archipelago-v3.0.0.zip](https://files.fourisland.com/releases/lingo-archipelago/lingo-archipelago-v3.0.0.zip)<br/>
31Source: [v3.0.0](https://code.fourisland.com/lingo-archipelago/tag/?h=v3.0.0)
32
33## v2.2.0 - 2024-04-17
34
35- The last ten connections are now saved in a list so that you can easily switch
36 between concurrent multiworlds.
37- THE COLORFUL is no longer turned into a countdown panel if the multiworld was
38 generated before Archipelago 0.4.5. This should improve backwards
39 compatibility, but a v1.x.x version is still the most accurate way to play an
40 older multiworld.
41
42Download:
43[lingo-archipelago-v2.2.0.zip](https://files.fourisland.com/releases/lingo-archipelago/lingo-archipelago-v2.2.0.zip)<br/>
44Source: [v2.2.0](https://code.fourisland.com/lingo-archipelago/tag/?h=v2.2.0)
45
46## v2.1.1 - 2024-04-11
47
48- Added some debug logging.
49
50Download:
51[lingo-archipelago-v2.1.1.zip](https://files.fourisland.com/releases/lingo-archipelago/lingo-archipelago-v2.1.1.zip)<br/>
52Source: [v2.1.1](https://code.fourisland.com/lingo-archipelago/tag/?h=v2.1.1)
53
3## v2.1.0 - 2024-04-03 54## v2.1.0 - 2024-04-03
4 55
5- Added a checkbox that enables tracking the player's current position. This can 56- Added a checkbox that enables tracking the player's current position. This can
diff --git a/README.md b/README.md index 68580e8..a242f95 100644 --- a/README.md +++ b/README.md
@@ -87,6 +87,10 @@ pick and choose which ones you would like to use.
87- **Painting shuffle**: This randomizes the appearance of the paintings in the 87- **Painting shuffle**: This randomizes the appearance of the paintings in the
88 game, as well as which of them are warps, and the locations that they warp you 88 game, as well as which of them are warps, and the locations that they warp you
89 to. It is the equivalent of an entrance randomizer in another game. 89 to. It is the equivalent of an entrance randomizer in another game.
90- **Sunwarp shuffle**: This randomizes the six pairs of sunwarps. The pairing of
91 the warps can change, whether a warp is an entrance or an exit can change, and
92 the numbering can change. You can also specify whether access to the sunwarps
93 should be locked behind receiving certain items.
90 94
91## Frequently Asked Questions 95## Frequently Asked Questions
92 96
@@ -155,33 +159,31 @@ to WELCOME BACK.
155 159
156### What about the pilgrimage? 160### What about the pilgrimage?
157 161
158The intended method of reaching the Pilgrim Room in the base game is known as 162You can enable or disable the pilgrimage in the world options. It defaults to
159"doing a pilgrimage". It involves entering each sunwarp in order without using 163disabled. When disabled, it is impossible to perform a pilgrimage (although the
160any non-painting warps in between. This is difficult to map out properly in AP 164sunwarps will still work, as long as you haven't disabled them too). The Sun
161logic, so we only consider one specific path through the map to be the canonical 165Painting will be added to the item pool, even if you do not have door shuffle
162pilgrimage route. Accessing the Pilgrim Room by pilgrimage is only in logic if 166on, so that you can still access the Pilgrim Antechamber.
163this specific route is available to you: 167
164 168When the pilgrimage is enabled, you are required to perform a pilgrimage in
165- From the Starting Room, proceed through the Second Room and into the Hub Room. 169order to access the Pilgrim Antechamber (although the Pilgrim Room itself may
166 Enter the first sunwarp. 170still be accessible through The Seeker if you have door shuffle on). The Sun
167- From the Crossroads, use the front tower entrance (the one nearest The 171Painting will not be added to the pool, and will behave as it does in vanilla
168 Discerning; not the one next to Sword/Words). Go through the Hot Crusts Door 172(in that it only moves when you solve HOT CRUST inside the Pilgrim Antechamber).
169 and enter the second sunwarp. 173It is non-trivial to determine whether you are able to perform a pilgrimage at
170- Enter the third sunwarp immediately after. 174any given state, but logic will expect you to be able to figure this out. There
171- Proceed past The Initiated and through the shortcut door back to the Hub Room. 175are options that let you determine whether or not paintings and/or the roof
172 Go through the shortcut door to the tower's first floor and enter the fourth 176access stairs in Crossroads will disable a pilgrimage. When sunwarps are
173 sunwarp. 177shuffled, your pilgrimage must take the new numbering of the warps into
174- Use the shortcut to the Directional Gallery (the one outside The Undeterred; 178consideration. The tracker is able to tell you whether or not the Pilgrim
175 not the one further down the hallway where the Number Hunt is), pass through 179Antechamber is accessible (as long as there is an otherwise accessible check
176 the Salt Pepper Door, and return to the Hub Room. Use the nearby entrance to 180inside it), but it can't tell you what your pilgrimage path should be. If you
177 the Crossroads and proceed to the fifth sunwarp. 181are lost, you can check your world's spoiler log for direction on the pilgrimage
178- Use the door that takes you to The Steady, and then the one that takes you to 182path to take.
179 The Bearer, and then the one that takes you to The Initiated. Return to the 183
180 Hub Room once more, and enter The Tenacious via the shortcut that opens upon 184In previous versions of the randomizer, there was a "canonical pilgrimage" that
181 solving the palindromes. Use the top-right door to access the area Outside the 185involved following a specific path in order to reach the Pilgrim Antechamber.
182 Agreeable, and enter the final sunwarp. 186This is no longer relevant, because all possible pilgrimage paths are now in
183 187logic, but you can still see the old route
184This route can be seen 188[starting at 2:47 in this video](https://youtu.be/8GfuDRRswdA?t=167) for
185[starting at 2:47 in this video](https://youtu.be/8GfuDRRswdA?t=167). Note that 189reference.
186this will almost never be required if door shuffle is enabled, as one of the
187other entrances to the room will usually be available sooner.
diff --git a/archipelago.tscn b/archipelago.tscn index f0b8ab9..f063af9 100644 --- a/archipelago.tscn +++ b/archipelago.tscn
@@ -86,9 +86,9 @@ align = 2
86 86
87[node name="credit5" parent="Panel" instance=ExtResource( 1 )] 87[node name="credit5" parent="Panel" instance=ExtResource( 1 )]
88margin_left = 1239.0 88margin_left = 1239.0
89margin_top = 271.0 89margin_top = 422.0
90margin_right = 1829.0 90margin_right = 1829.0
91margin_bottom = 335.0 91margin_bottom = 486.0
92custom_fonts/font = ExtResource( 2 ) 92custom_fonts/font = ExtResource( 2 )
93custom_styles/normal = SubResource( 1 ) 93custom_styles/normal = SubResource( 1 )
94text = "OPTIONS" 94text = "OPTIONS"
@@ -155,9 +155,9 @@ margin_bottom = 58.0
155 155
156[node name="confusing_box" type="CheckBox" parent="Panel"] 156[node name="confusing_box" type="CheckBox" parent="Panel"]
157margin_left = 1227.0 157margin_left = 1227.0
158margin_top = 351.0 158margin_top = 502.0
159margin_right = 1832.0 159margin_right = 1832.0
160margin_bottom = 439.0 160margin_bottom = 590.0
161custom_fonts/font = ExtResource( 6 ) 161custom_fonts/font = ExtResource( 6 )
162custom_icons/checked = ExtResource( 8 ) 162custom_icons/checked = ExtResource( 8 )
163custom_icons/unchecked = ExtResource( 7 ) 163custom_icons/unchecked = ExtResource( 7 )
@@ -165,9 +165,9 @@ text = "Make world more confusing"
165 165
166[node name="multiplayer_box" type="CheckBox" parent="Panel"] 166[node name="multiplayer_box" type="CheckBox" parent="Panel"]
167margin_left = 1227.0 167margin_left = 1227.0
168margin_top = 461.0 168margin_top = 612.0
169margin_right = 1832.0 169margin_right = 1832.0
170margin_bottom = 549.0 170margin_bottom = 700.0
171custom_fonts/font = ExtResource( 6 ) 171custom_fonts/font = ExtResource( 6 )
172custom_icons/checked = ExtResource( 8 ) 172custom_icons/checked = ExtResource( 8 )
173custom_icons/unchecked = ExtResource( 7 ) 173custom_icons/unchecked = ExtResource( 7 )
@@ -175,13 +175,22 @@ text = "Show other players"
175 175
176[node name="position_box" type="CheckBox" parent="Panel"] 176[node name="position_box" type="CheckBox" parent="Panel"]
177margin_left = 1227.0 177margin_left = 1227.0
178margin_top = 571.0 178margin_top = 722.0
179margin_right = 1832.0 179margin_right = 1832.0
180margin_bottom = 654.0 180margin_bottom = 810.0
181custom_fonts/font = ExtResource( 6 ) 181custom_fonts/font = ExtResource( 6 )
182custom_icons/checked = ExtResource( 8 ) 182custom_icons/checked = ExtResource( 8 )
183custom_icons/unchecked = ExtResource( 7 ) 183custom_icons/unchecked = ExtResource( 7 )
184text = "Send position to tracker" 184text = "Send position to tracker"
185 185
186[node name="connection_history" type="MenuButton" parent="Panel"]
187margin_left = 1239.0
188margin_top = 276.0
189margin_right = 1829.0
190margin_bottom = 372.0
191custom_fonts/font = ExtResource( 6 )
192text = "connection history"
193flat = false
194
186[connection signal="pressed" from="Panel/connect_button" to="Panel/connect_button" method="_connect_pressed"] 195[connection signal="pressed" from="Panel/connect_button" to="Panel/connect_button" method="_connect_pressed"]
187[connection signal="pressed" from="Panel/quit_button" to="Panel/quit_button" method="_back_pressed"] 196[connection signal="pressed" from="Panel/quit_button" to="Panel/quit_button" method="_back_pressed"]
diff --git a/util/generate_gamedata.rb b/util/generate_gamedata.rb index f63e062..1f18b7e 100644 --- a/util/generate_gamedata.rb +++ b/util/generate_gamedata.rb
@@ -11,15 +11,20 @@ CLASSIFICATION_INSANITY = 4
11 11
12panel_to_id = {} 12panel_to_id = {}
13door_groups = {} 13door_groups = {}
14warp_groups = {}
14 15
15panel_output = [] 16panel_output = []
16door_ids_by_item_id = {} 17door_ids_by_item_id = {}
17painting_ids_by_item_id = {} 18painting_ids_by_item_id = {}
19warp_ids_by_item_id = {}
18panel_ids_by_location_id = {} 20panel_ids_by_location_id = {}
19classification_by_location_id = {} 21classification_by_location_id = {}
22sunwarps = Array.new(12) {Hash.new}
20mentioned_doors = Set[] 23mentioned_doors = Set[]
21mentioned_paintings = Set[] 24mentioned_paintings = Set[]
25mentioned_warps = Set[]
22painting_output = {} 26painting_output = {}
27items_by_progressive_id = {}
23 28
24ids_config = YAML.load_file(idspath) 29ids_config = YAML.load_file(idspath)
25 30
@@ -88,6 +93,30 @@ config.each do |room_name, room_data|
88 painting_output[painting["id"]] = painting 93 painting_output[painting["id"]] = painting
89 end 94 end
90 end 95 end
96
97 if room_data.include? "sunwarps"
98 room_data["sunwarps"].each do |sunwarp|
99 index = sunwarp["dots"] - 1
100 if sunwarp["direction"] == "exit" then
101 index += 6
102 end
103 sunwarps[index] = sunwarp
104 end
105 end
106
107 if room_data.include? "progression"
108 room_data["progression"].each do |progressive_item_name, progression|
109 progressive_id = ids_config["progression"][progressive_item_name]
110 items_by_progressive_id[progressive_id] = []
111
112 progression.each do |item|
113 item_room_name = (item.kind_of? Hash) ? item["room"] : room_name
114 item_item_name = (item.kind_of? Hash) ? item["door"] : item
115
116 items_by_progressive_id[progressive_id] << ids_config["doors"][item_room_name][item_item_name]["item"]
117 end
118 end
119 end
91end 120end
92 121
93config.each do |room_name, room_data| 122config.each do |room_name, room_data|
@@ -152,6 +181,23 @@ config.each do |room_name, room_data|
152 painting_ids_by_item_id[item_id] = internal_painting_ids 181 painting_ids_by_item_id[item_id] = internal_painting_ids
153 mentioned_paintings.merge(internal_painting_ids) 182 mentioned_paintings.merge(internal_painting_ids)
154 end 183 end
184
185 if door.include? "warp_id"
186 internal_warp_ids = []
187 if door["warp_id"].kind_of? String
188 internal_warp_ids = [door["warp_id"]]
189 else
190 internal_warp_ids = door["warp_id"]
191 end
192
193 if door.include? "door_group"
194 warp_groups[door["door_group"]] ||= Set[]
195 warp_groups[door["door_group"]].merge(internal_warp_ids)
196 end
197
198 warp_ids_by_item_id[item_id] = internal_warp_ids
199 mentioned_warps.merge(internal_warp_ids)
200 end
155 end 201 end
156 end 202 end
157 end 203 end
@@ -162,6 +208,11 @@ door_groups.each do |group_name, door_ids|
162 door_ids_by_item_id[item_id] = door_ids.to_a 208 door_ids_by_item_id[item_id] = door_ids.to_a
163end 209end
164 210
211warp_groups.each do |group_name, warp_ids|
212 item_id = ids_config["door_groups"][group_name]
213 warp_ids_by_item_id[item_id] = warp_ids.to_a
214end
215
165File.open(outputpath, "w") do |f| 216File.open(outputpath, "w") do |f|
166 f.write "extends Node\n\nvar panels = [" 217 f.write "extends Node\n\nvar panels = ["
167 f.write(panel_output.map do |panel| 218 f.write(panel_output.map do |panel|
@@ -181,6 +232,12 @@ File.open(outputpath, "w") do |f|
181 "\"#{painting_id}\"" 232 "\"#{painting_id}\""
182 end.join(",") + "]" 233 end.join(",") + "]"
183 end.join(",")) 234 end.join(","))
235 f.write "}\nvar warp_ids_by_item_id = {"
236 f.write(warp_ids_by_item_id.map do |item_id, warp_ids|
237 "#{item_id}:[" + warp_ids.map do |warp_id|
238 "\"#{warp_id}\""
239 end.join(",") + "]"
240 end.join(","))
184 f.write "}\nvar panel_ids_by_location_id = {" 241 f.write "}\nvar panel_ids_by_location_id = {"
185 f.write(panel_ids_by_location_id.map do |location_id, panel_ids| 242 f.write(panel_ids_by_location_id.map do |location_id, panel_ids|
186 "#{location_id}:[" + panel_ids.map do |panel_id| 243 "#{location_id}:[" + panel_ids.map do |panel_id|
@@ -195,6 +252,10 @@ File.open(outputpath, "w") do |f|
195 f.write(mentioned_paintings.map do |painting_id| 252 f.write(mentioned_paintings.map do |painting_id|
196 "\"#{painting_id}\"" 253 "\"#{painting_id}\""
197 end.join(",")) 254 end.join(","))
255 f.write "]\nvar mentioned_warps = ["
256 f.write(mentioned_warps.map do |warp_id|
257 "\"#{warp_id}\""
258 end.join(","))
198 f.write "]\nvar paintings = {" 259 f.write "]\nvar paintings = {"
199 f.write(painting_output.map do |painting_id, painting| 260 f.write(painting_output.map do |painting_id, painting|
200 "\"#{painting_id}\":{\"orientation\":\"#{painting["orientation"]}\",\"move\":#{painting.include? "move" and painting["move"]}}" 261 "\"#{painting_id}\":{\"orientation\":\"#{painting["orientation"]}\",\"move\":#{painting.include? "move" and painting["move"]}}"
@@ -203,5 +264,13 @@ File.open(outputpath, "w") do |f|
203 f.write(classification_by_location_id.map do |location_id, classification| 264 f.write(classification_by_location_id.map do |location_id, classification|
204 "#{location_id}:#{classification}" 265 "#{location_id}:#{classification}"
205 end.join(",")) 266 end.join(","))
267 f.write "}\nvar sunwarps = ["
268 f.write(sunwarps.map do |sunwarp|
269 "{\"orientation\":\"#{sunwarp["orientation"]}\",\"entrance_indicator_pos\":#{sunwarp["entrance_indicator_pos"].to_s}}"
270 end.join(","))
271 f.write "]\nvar items_by_progressive_id = {"
272 f.write(items_by_progressive_id.map do |item_id, progression_ids|
273 "#{item_id}:[" + progression_ids.map(&:to_s).join(",") + "]"
274 end.join(","))
206 f.write "}" 275 f.write "}"
207end 276end