about summary refs log tree commit diff stats
path: root/apworld/client
diff options
context:
space:
mode:
Diffstat (limited to 'apworld/client')
-rw-r--r--apworld/client/allowNumbers.gd10
-rw-r--r--apworld/client/apworld_runtime.gd5
-rw-r--r--apworld/client/client.gd26
-rw-r--r--apworld/client/gamedata.gd10
-rw-r--r--apworld/client/keyHolderResetterListener.gd2
-rw-r--r--apworld/client/keyboard.gd3
-rw-r--r--apworld/client/main.gd11
-rw-r--r--apworld/client/manager.gd49
-rw-r--r--apworld/client/maps/control_center.gd85
-rw-r--r--apworld/client/maps/daedalus.gd85
-rw-r--r--apworld/client/maps/icarus.gd38
-rw-r--r--apworld/client/maps/the_advanced.gd36
-rw-r--r--apworld/client/maps/the_charismatic.gd26
-rw-r--r--apworld/client/maps/the_crystalline.gd34
-rw-r--r--apworld/client/maps/the_entry.gd156
-rw-r--r--apworld/client/maps/the_fuzzy.gd25
-rw-r--r--apworld/client/maps/the_parthenon.gd51
-rw-r--r--apworld/client/maps/the_plaza.gd4
-rw-r--r--apworld/client/maps/the_stellar.gd30
-rw-r--r--apworld/client/maps/the_sun_temple.gd56
-rw-r--r--apworld/client/maps/the_unkempt.gd4
-rw-r--r--apworld/client/maps/the_unyielding.gd5
-rw-r--r--apworld/client/player.gd428
-rw-r--r--apworld/client/source_runtime.gd4
-rw-r--r--apworld/client/textclient.gd102
-rw-r--r--apworld/client/unlockReaderListener.gd46
26 files changed, 892 insertions, 439 deletions
diff --git a/apworld/client/allowNumbers.gd b/apworld/client/allowNumbers.gd new file mode 100644 index 0000000..d958b50 --- /dev/null +++ b/apworld/client/allowNumbers.gd
@@ -0,0 +1,10 @@
1extends "res://scripts/nodes/allowNumbers.gd"
2
3
4func _readier():
5 var ap = global.get_node("Archipelago")
6 var gamedata = global.get_node("Gamedata")
7
8 var item_id = gamedata.objects.get_special_ids()["Numbers"]
9 if ap.client.getItemAmount(item_id) >= 1:
10 global.allow_numbers = true
diff --git a/apworld/client/apworld_runtime.gd b/apworld/client/apworld_runtime.gd index faf8e0c..03568bf 100644 --- a/apworld/client/apworld_runtime.gd +++ b/apworld/client/apworld_runtime.gd
@@ -15,6 +15,11 @@ func _get_true_path(path):
15 return "lingo2/client/%s" % path 15 return "lingo2/client/%s" % path
16 16
17 17
18func path_exists(path):
19 var true_path = _get_true_path(path)
20 return apworld_reader.file_exists(true_path)
21
22
18func load_script(path): 23func load_script(path):
19 var true_path = _get_true_path(path) 24 var true_path = _get_true_path(path)
20 25
diff --git a/apworld/client/client.gd b/apworld/client/client.gd index ce5ac7e..c149482 100644 --- a/apworld/client/client.gd +++ b/apworld/client/client.gd
@@ -26,6 +26,7 @@ var _accessible_locations = []
26var _accessible_worldports = [] 26var _accessible_worldports = []
27var _goal_accessible = false 27var _goal_accessible = false
28var _latched_doors = [] 28var _latched_doors = []
29var _hinted_locations = []
29 30
30signal could_not_connect 31signal could_not_connect
31signal connect_status 32signal connect_status
@@ -38,8 +39,10 @@ signal hint_received(message)
38signal door_latched(id) 39signal door_latched(id)
39signal accessible_locations_updated 40signal accessible_locations_updated
40signal checked_locations_updated 41signal checked_locations_updated
42signal ignored_locations_updated(locations)
41signal checked_worldports_updated 43signal checked_worldports_updated
42signal keyboard_update_received 44signal keyboard_update_received
45signal hinted_locations_updated
43 46
44 47
45func _init(): 48func _init():
@@ -199,6 +202,21 @@ func _on_web_socket_server_message_received(_peer_id: int, packet: String) -> vo
199 202
200 door_latched.emit(iid) 203 door_latched.emit(iid)
201 204
205 elif cmd == "SetIgnoredLocations":
206 var locs = []
207 for id in message["locations"]:
208 locs.append(int(id))
209
210 ignored_locations_updated.emit(locs)
211
212 elif cmd == "UpdateHintedLocations":
213 for id in message["locations"]:
214 var iid = int(id)
215 if !_hinted_locations.has(iid):
216 _hinted_locations.append(iid)
217
218 hinted_locations_updated.emit()
219
202 220
203func connectToServer(server, un, pw): 221func connectToServer(server, un, pw):
204 sendMessage([{"cmd": "Connect", "server": server, "player": un, "password": pw}]) 222 sendMessage([{"cmd": "Connect", "server": server, "player": un, "password": pw}])
@@ -280,6 +298,14 @@ func getLogicalPath(object_type, object_id):
280 sendMessage([msg]) 298 sendMessage([msg])
281 299
282 300
301func addIgnoredLocation(loc_id):
302 sendMessage([{"cmd": "IgnoreLocation", "id": loc_id}])
303
304
305func removeIgnoredLocation(loc_id):
306 sendMessage([{"cmd": "UnignoreLocation", "id": loc_id}])
307
308
283func sendQuit(): 309func sendQuit():
284 sendMessage([{"cmd": "Quit"}]) 310 sendMessage([{"cmd": "Quit"}])
285 311
diff --git a/apworld/client/gamedata.gd b/apworld/client/gamedata.gd index 9305003..d7e3136 100644 --- a/apworld/client/gamedata.gd +++ b/apworld/client/gamedata.gd
@@ -15,6 +15,7 @@ var symbol_item_ids = []
15var anti_trap_ids = {} 15var anti_trap_ids = {}
16var location_name_by_id = {} 16var location_name_by_id = {}
17var ending_display_name_by_name = {} 17var ending_display_name_by_name = {}
18var port_id_by_ap_id = {}
18 19
19var kSYMBOL_ITEMS 20var kSYMBOL_ITEMS
20 21
@@ -99,6 +100,9 @@ func load(data_bytes):
99 var map_data = port_id_by_map_node_path[map.get_name()] 100 var map_data = port_id_by_map_node_path[map.get_name()]
100 map_data[port.get_path()] = port.get_id() 101 map_data[port.get_path()] = port.get_id()
101 102
103 if port.has_ap_id():
104 port_id_by_ap_id[port.get_ap_id()] = port.get_id()
105
102 for progressive in objects.get_progressives(): 106 for progressive in objects.get_progressives():
103 progressive_id_by_ap_id[progressive.get_ap_id()] = progressive.get_id() 107 progressive_id_by_ap_id[progressive.get_ap_id()] = progressive.get_id()
104 108
@@ -221,7 +225,11 @@ func _get_generated_door_location_name(door):
221 if door.get_type() != SCRIPT_proto.DoorType.STANDARD: 225 if door.get_type() != SCRIPT_proto.DoorType.STANDARD:
222 return null 226 return null
223 227
224 if door.get_keyholders().size() > 0 or door.get_endings().size() > 0 or door.has_complete_at(): 228 if (
229 door.get_keyholders().size() > 0
230 or (door.has_white_ending() and door.get_white_ending())
231 or door.has_complete_at()
232 ):
225 return null 233 return null
226 234
227 if door.get_panels().size() > 4: 235 if door.get_panels().size() > 4:
diff --git a/apworld/client/keyHolderResetterListener.gd b/apworld/client/keyHolderResetterListener.gd index d5300f3..9ab45f9 100644 --- a/apworld/client/keyHolderResetterListener.gd +++ b/apworld/client/keyHolderResetterListener.gd
@@ -6,3 +6,5 @@ func reset():
6 var was_removed = ap.keyboard.reset_keyholders() 6 var was_removed = ap.keyboard.reset_keyholders()
7 if was_removed: 7 if was_removed:
8 sfxPlayer.sfx_play("pickup") 8 sfxPlayer.sfx_play("pickup")
9
10 ap.client.requestSync()
diff --git a/apworld/client/keyboard.gd b/apworld/client/keyboard.gd index a59c4d0..9026c06 100644 --- a/apworld/client/keyboard.gd +++ b/apworld/client/keyboard.gd
@@ -191,9 +191,6 @@ func load_keyholders(map):
191 191
192 192
193func reset_keyholders(): 193func reset_keyholders():
194 if letters_in_keyholders.is_empty() and letters_blocked.is_empty():
195 return false
196
197 var cleared_anything = not letters_in_keyholders.is_empty() or not letters_blocked.is_empty() 194 var cleared_anything = not letters_in_keyholders.is_empty() or not letters_blocked.is_empty()
198 195
199 if keyholder_state.has(global.map): 196 if keyholder_state.has(global.map):
diff --git a/apworld/client/main.gd b/apworld/client/main.gd index 1d0df1f..c90d6e7 100644 --- a/apworld/client/main.gd +++ b/apworld/client/main.gd
@@ -36,6 +36,7 @@ func _ready():
36 global.add_child(ap_instance) 36 global.add_child(ap_instance)
37 37
38 # Let's also inject any scripts we need to inject now. 38 # Let's also inject any scripts we need to inject now.
39 installScriptExtension(runtime.load_script("allowNumbers.gd"))
39 installScriptExtension(runtime.load_script("animationListener.gd")) 40 installScriptExtension(runtime.load_script("animationListener.gd"))
40 installScriptExtension(runtime.load_script("collectable.gd")) 41 installScriptExtension(runtime.load_script("collectable.gd"))
41 installScriptExtension(runtime.load_script("door.gd")) 42 installScriptExtension(runtime.load_script("door.gd"))
@@ -50,6 +51,7 @@ func _ready():
50 installScriptExtension(runtime.load_script("saver.gd")) 51 installScriptExtension(runtime.load_script("saver.gd"))
51 installScriptExtension(runtime.load_script("teleport.gd")) 52 installScriptExtension(runtime.load_script("teleport.gd"))
52 installScriptExtension(runtime.load_script("teleportListener.gd")) 53 installScriptExtension(runtime.load_script("teleportListener.gd"))
54 installScriptExtension(runtime.load_script("unlockReaderListener.gd"))
53 installScriptExtension(runtime.load_script("visibilityListener.gd")) 55 installScriptExtension(runtime.load_script("visibilityListener.gd"))
54 installScriptExtension(runtime.load_script("worldport.gd")) 56 installScriptExtension(runtime.load_script("worldport.gd"))
55 installScriptExtension(runtime.load_script("worldportListener.gd")) 57 installScriptExtension(runtime.load_script("worldportListener.gd"))
@@ -83,6 +85,13 @@ func _ready():
83 compass_overlay_instance.SCRIPT_compass = runtime.load_script("compass.gd") 85 compass_overlay_instance.SCRIPT_compass = runtime.load_script("compass.gd")
84 global.add_child(compass_overlay_instance) 86 global.add_child(compass_overlay_instance)
85 87
88 unlocks.data["advanced_mastery"] = ""
89 unlocks.data["charismatic_mastery"] = ""
90 unlocks.data["crystalline_mastery"] = ""
91 unlocks.data["fuzzy_mastery"] = ""
92 unlocks.data["icarus_mastery"] = ""
93 unlocks.data["stellar_mastery"] = ""
94
86 var ap = global.get_node("Archipelago") 95 var ap = global.get_node("Archipelago")
87 var gamedata = global.get_node("Gamedata") 96 var gamedata = global.get_node("Gamedata")
88 ap.ap_connected.connect(connectionSuccessful) 97 ap.ap_connected.connect(connectionSuccessful)
@@ -237,6 +246,7 @@ func startGame():
237 settings.worldport_fades = "never" 246 settings.worldport_fades = "never"
238 247
239 clearResourceCache("res://objects/meshes/gridDoor.tscn") 248 clearResourceCache("res://objects/meshes/gridDoor.tscn")
249 clearResourceCache("res://objects/nodes/allowNumbers.tscn")
240 clearResourceCache("res://objects/nodes/collectable.tscn") 250 clearResourceCache("res://objects/nodes/collectable.tscn")
241 clearResourceCache("res://objects/nodes/door.tscn") 251 clearResourceCache("res://objects/nodes/door.tscn")
242 clearResourceCache("res://objects/nodes/keyHolder.tscn") 252 clearResourceCache("res://objects/nodes/keyHolder.tscn")
@@ -244,6 +254,7 @@ func startGame():
244 clearResourceCache("res://objects/nodes/listeners/keyHolderChecker.tscn") 254 clearResourceCache("res://objects/nodes/listeners/keyHolderChecker.tscn")
245 clearResourceCache("res://objects/nodes/listeners/keyHolderResetterListener.tscn") 255 clearResourceCache("res://objects/nodes/listeners/keyHolderResetterListener.tscn")
246 clearResourceCache("res://objects/nodes/listeners/teleportListener.tscn") 256 clearResourceCache("res://objects/nodes/listeners/teleportListener.tscn")
257 clearResourceCache("res://objects/nodes/listeners/unlockReaderListener.tscn")
247 clearResourceCache("res://objects/nodes/listeners/visibilityListener.tscn") 258 clearResourceCache("res://objects/nodes/listeners/visibilityListener.tscn")
248 clearResourceCache("res://objects/nodes/listeners/worldportListener.tscn") 259 clearResourceCache("res://objects/nodes/listeners/worldportListener.tscn")
249 clearResourceCache("res://objects/nodes/panel.tscn") 260 clearResourceCache("res://objects/nodes/panel.tscn")
diff --git a/apworld/client/manager.gd b/apworld/client/manager.gd index 41ab648..8c981f9 100644 --- a/apworld/client/manager.gd +++ b/apworld/client/manager.gd
@@ -29,6 +29,8 @@ var _inverse_item_locks = {}
29var _held_letters = {} 29var _held_letters = {}
30var _letters_setup = false 30var _letters_setup = false
31var _already_connected = false 31var _already_connected = false
32var _ignored_locations = []
33var _map_scripts = {}
32 34
33const kSHUFFLE_LETTERS_VANILLA = 0 35const kSHUFFLE_LETTERS_VANILLA = 0
34const kSHUFFLE_LETTERS_UNLOCKED = 1 36const kSHUFFLE_LETTERS_UNLOCKED = 1
@@ -65,7 +67,9 @@ var cyan_door_behavior = kCYAN_DOOR_BEHAVIOR_H2
65var daedalus_roof_access = false 67var daedalus_roof_access = false
66var enable_gift_maps = [] 68var enable_gift_maps = []
67var enable_icarus = false 69var enable_icarus = false
70var endings_requirement = 0
68var keyholder_sanity = false 71var keyholder_sanity = false
72var masteries_requirement = 0
69var port_pairings = {} 73var port_pairings = {}
70var shuffle_control_center_colors = false 74var shuffle_control_center_colors = false
71var shuffle_doors = false 75var shuffle_doors = false
@@ -142,6 +146,8 @@ func _ready():
142 client.hint_received.connect(_process_hint_received) 146 client.hint_received.connect(_process_hint_received)
143 client.accessible_locations_updated.connect(_on_accessible_locations_updated) 147 client.accessible_locations_updated.connect(_on_accessible_locations_updated)
144 client.checked_locations_updated.connect(_on_checked_locations_updated) 148 client.checked_locations_updated.connect(_on_checked_locations_updated)
149 client.ignored_locations_updated.connect(_on_ignored_locations_updated)
150 client.hinted_locations_updated.connect(_on_hinted_locations_updated)
145 client.checked_worldports_updated.connect(_on_checked_worldports_updated) 151 client.checked_worldports_updated.connect(_on_checked_worldports_updated)
146 client.door_latched.connect(_on_door_latched) 152 client.door_latched.connect(_on_door_latched)
147 153
@@ -259,6 +265,9 @@ func _process_item(item, amount):
259 if item_id == gamedata.objects.get_special_ids()["A Job Well Done"]: 265 if item_id == gamedata.objects.get_special_ids()["A Job Well Done"]:
260 update_job_well_done_sign() 266 update_job_well_done_sign()
261 267
268 if item_id == gamedata.objects.get_special_ids()["Numbers"] and global.map == "the_fuzzy":
269 global.allow_numbers = true
270
262 # Show a message about the item if it's new. 271 # Show a message about the item if it's new.
263 if int(item["index"]) > _last_new_item: 272 if int(item["index"]) > _last_new_item:
264 _last_new_item = int(item["index"]) 273 _last_new_item = int(item["index"])
@@ -379,6 +388,20 @@ func _on_checked_worldports_updated():
379 textclient_node.update_worldports() 388 textclient_node.update_worldports()
380 389
381 390
391func _on_ignored_locations_updated(locations):
392 _ignored_locations = locations
393
394 var textclient_node = global.get_node("Textclient")
395 if textclient_node != null:
396 textclient_node.update_locations()
397
398
399func _on_hinted_locations_updated():
400 var textclient_node = global.get_node("Textclient")
401 if textclient_node != null:
402 textclient_node.update_locations()
403
404
382func _on_door_latched(door_id): 405func _on_door_latched(door_id):
383 var gamedata = global.get_node("Gamedata") 406 var gamedata = global.get_node("Gamedata")
384 if gamedata.get_door_map_name(door_id) != global.map: 407 if gamedata.get_door_map_name(door_id) != global.map:
@@ -443,7 +466,9 @@ func _client_connected(slot_data):
443 daedalus_roof_access = bool(slot_data.get("daedalus_roof_access", false)) 466 daedalus_roof_access = bool(slot_data.get("daedalus_roof_access", false))
444 enable_gift_maps = slot_data.get("enable_gift_maps", []) 467 enable_gift_maps = slot_data.get("enable_gift_maps", [])
445 enable_icarus = bool(slot_data.get("enable_icarus", false)) 468 enable_icarus = bool(slot_data.get("enable_icarus", false))
469 endings_requirement = int(slot_data.get("endings_requirement", 0))
446 keyholder_sanity = bool(slot_data.get("keyholder_sanity", false)) 470 keyholder_sanity = bool(slot_data.get("keyholder_sanity", false))
471 masteries_requirement = int(slot_data.get("masteries_requirement", 0))
447 shuffle_control_center_colors = bool(slot_data.get("shuffle_control_center_colors", false)) 472 shuffle_control_center_colors = bool(slot_data.get("shuffle_control_center_colors", false))
448 shuffle_doors = bool(slot_data.get("shuffle_doors", false)) 473 shuffle_doors = bool(slot_data.get("shuffle_doors", false))
449 shuffle_gallery_paintings = bool(slot_data.get("shuffle_gallery_paintings", false)) 474 shuffle_gallery_paintings = bool(slot_data.get("shuffle_gallery_paintings", false))
@@ -465,7 +490,9 @@ func _client_connected(slot_data):
465 var raw_pp = slot_data.get("port_pairings") 490 var raw_pp = slot_data.get("port_pairings")
466 491
467 for p1 in raw_pp.keys(): 492 for p1 in raw_pp.keys():
468 port_pairings[int(p1)] = int(raw_pp[p1]) 493 port_pairings[gamedata.port_id_by_ap_id[int(p1)]] = gamedata.port_id_by_ap_id[int(
494 raw_pp[p1]
495 )]
469 496
470 # Set up item locks. 497 # Set up item locks.
471 _item_locks = {} 498 _item_locks = {}
@@ -668,3 +695,23 @@ func update_job_well_done_sign():
668 695
669 sign2.get_node("MeshInstance3D").mesh.text = sign2.text 696 sign2.get_node("MeshInstance3D").mesh.text = sign2.text
670 sign3.get_node("MeshInstance3D").mesh.text = sign3.text 697 sign3.get_node("MeshInstance3D").mesh.text = sign3.text
698
699
700func toggle_ignored_location(loc_id):
701 if loc_id in _ignored_locations:
702 client.removeIgnoredLocation(loc_id)
703 else:
704 client.addIgnoredLocation(loc_id)
705
706
707func get_map_script(map_name):
708 if !_map_scripts.has(map_name):
709 var runtime = global.get_node("Runtime")
710 var script_path = "maps/%s.gd" % map_name
711 if runtime.path_exists(script_path):
712 var script = runtime.load_script(script_path)
713 _map_scripts[map_name] = script.new()
714 else:
715 _map_scripts[map_name] = null
716
717 return _map_scripts[map_name]
diff --git a/apworld/client/maps/control_center.gd b/apworld/client/maps/control_center.gd new file mode 100644 index 0000000..de9ae4b --- /dev/null +++ b/apworld/client/maps/control_center.gd
@@ -0,0 +1,85 @@
1func on_map_load(root):
2 var ap = global.get_node("Archipelago")
3
4 # Remove the door blocking the trophy case.
5 root.get_node("/root/scene/Components/Doors/entry_18").queue_free()
6
7 # Set up mastery listeners for extra maps.
8 _set_up_mastery_listener(root, "advanced")
9 _set_up_mastery_listener(root, "charismatic")
10 _set_up_mastery_listener(root, "crystalline")
11 _set_up_mastery_listener(root, "fuzzy")
12 _set_up_mastery_listener(root, "icarus")
13 _set_up_mastery_listener(root, "stellar")
14
15 if ap.endings_requirement != 12 or ap.masteries_requirement != 0:
16 # Set up listeners for the potential White Ending requirements.
17 var merging_prefab = preload("res://objects/nodes/listeners/mergingListener.tscn")
18
19 var old_door = root.get_node("/root/scene/Components/Doors/entry_19")
20 var new_door = old_door.duplicate()
21 new_door.name = "entry_19_new"
22 new_door.senders.clear()
23 new_door.senderGroup.clear()
24 new_door.excludeSenders.clear()
25
26 if ap.endings_requirement == 12:
27 new_door.senderGroup.append(NodePath("/root/scene/Meshes/Trophies/Listeners"))
28 elif ap.endings_requirement > 0:
29 if ap.masteries_requirement == 0:
30 new_door.senderGroup.append(NodePath("/root/scene/Meshes/Trophies/Listeners"))
31 new_door.complete_at = ap.endings_requirement
32 else:
33 var endings_merge = merging_prefab.instantiate()
34 endings_merge.name = "EndingsMerge"
35 endings_merge.senderGroup.append(NodePath("/root/scene/Meshes/Trophies/Listeners"))
36 endings_merge.complete_at = ap.endings_requirement
37 root.get_node("/root/scene/Components").add_child.call_deferred(endings_merge)
38 new_door.senders.append(NodePath("/root/scene/Components/EndingsMerge"))
39
40 var max_masteries = 13 + ap.enable_gift_maps.size()
41 if ap.enable_icarus:
42 max_masteries += 1
43
44 if ap.masteries_requirement == max_masteries:
45 new_door.senderGroup.append(NodePath("/root/scene/Meshes/Trophies/MasteryListeners"))
46 new_door.excludeSenders.append(
47 NodePath("/root/scene/Meshes/Trophies/MasteryListeners/unlockReaderListenerWhite")
48 )
49 elif ap.masteries_requirement > 0:
50 if ap.endings_requirement == 0:
51 new_door.senderGroup.append(
52 NodePath("/root/scene/Meshes/Trophies/MasteryListeners")
53 )
54 new_door.excludeSenders.append(
55 NodePath(
56 "/root/scene/Meshes/Trophies/MasteryListeners/unlockReaderListenerWhite"
57 )
58 )
59 new_door.complete_at = ap.masteries_requirement
60 else:
61 var masteries_merge = merging_prefab.instantiate()
62 masteries_merge.name = "MasteriesMerge"
63 masteries_merge.senderGroup.append(
64 NodePath("/root/scene/Meshes/Trophies/MasteryListeners")
65 )
66 masteries_merge.excludeSenders.append(
67 NodePath(
68 "/root/scene/Meshes/Trophies/MasteryListeners/unlockReaderListenerWhite"
69 )
70 )
71 masteries_merge.complete_at = ap.masteries_requirement
72 root.get_node("/root/scene/Components").add_child.call_deferred(masteries_merge)
73 new_door.senders.append(NodePath("/root/scene/Components/MasteriesMerge"))
74
75 old_door.queue_free()
76 root.get_node("/root/scene/Components/Doors").add_child.call_deferred(new_door)
77
78
79func _set_up_mastery_listener(root, name):
80 var prefab = preload("res://objects/nodes/listeners/unlockReaderListener.tscn")
81 var url = prefab.instantiate()
82 url.name = "unlockReaderListenerMastery_%s" % name
83 url.key = "%s_mastery" % name
84 url.value = "unlocked"
85 root.get_node("/root/scene/Meshes/Trophies/MasteryListeners").add_child.call_deferred(url)
diff --git a/apworld/client/maps/daedalus.gd b/apworld/client/maps/daedalus.gd new file mode 100644 index 0000000..5fcf7a5 --- /dev/null +++ b/apworld/client/maps/daedalus.gd
@@ -0,0 +1,85 @@
1func on_map_load(root):
2 var ap = global.get_node("Archipelago")
3
4 # Teleport the direction panels when the stairs are there.
5 var tpl_prefab = preload("res://objects/nodes/listeners/teleportListener.tscn")
6
7 var dir1 = root.get_node("/root/scene/Panels/Castle Entrance/castle_direction_1")
8 var dir1_tpl = tpl_prefab.instantiate()
9 dir1_tpl.target_path = dir1
10 dir1_tpl.teleport_point = Vector3(59.5, 8, -6.5)
11 dir1_tpl.teleport_rotate = Vector3(-45, 0, 0)
12 dir1_tpl.senders.append(NodePath("/root/scene/Panels/Castle Entrance/castle_south"))
13 dir1_tpl.senders.append(NodePath("/root/scene/Panels/Castle Entrance/castle_north"))
14 dir1_tpl.senders.append(NodePath("/root/scene/Panels/Castle Entrance/castle_west"))
15 dir1.add_child.call_deferred(dir1_tpl)
16
17 var dir2 = root.get_node("/root/scene/Panels/Castle Entrance/castle_direction_2")
18 var dir2_tpl = tpl_prefab.instantiate()
19 dir2_tpl.target_path = dir2
20 dir2_tpl.teleport_point = Vector3(59.5, 8, 6.5)
21 dir2_tpl.teleport_rotate = Vector3(-45, -180, 0)
22 dir2_tpl.senders.append(NodePath("/root/scene/Panels/Castle Entrance/castle_south"))
23 dir2_tpl.senders.append(NodePath("/root/scene/Panels/Castle Entrance/castle_north"))
24 dir2_tpl.senders.append(NodePath("/root/scene/Panels/Castle Entrance/castle_west"))
25 dir2.add_child.call_deferred(dir2_tpl)
26
27 var dir3 = root.get_node("/root/scene/Panels/Castle Entrance/castle_direction_3")
28 var dir3_tpl = tpl_prefab.instantiate()
29 dir3_tpl.target_path = dir3
30 dir3_tpl.teleport_point = Vector3(54, 8, 0)
31 dir3_tpl.teleport_rotate = Vector3(-45, 90, 0)
32 dir3_tpl.senders.append(NodePath("/root/scene/Panels/Castle Entrance/castle_south"))
33 dir3_tpl.senders.append(NodePath("/root/scene/Panels/Castle Entrance/castle_north"))
34 dir3_tpl.senders.append(NodePath("/root/scene/Panels/Castle Entrance/castle_west"))
35 dir3.add_child.call_deferred(dir3_tpl)
36
37 # Block off roof access in Daedalus.
38 if not ap.daedalus_roof_access:
39 _set_up_invis_wall(root, 75.5, 11, -24.5, 1, 10, 49)
40 _set_up_invis_wall(root, 51.5, 11, -17, 16, 10, 1)
41 _set_up_invis_wall(root, 46, 10, -9.5, 1, 10, 10)
42 _set_up_invis_wall(root, 67.5, 11, 17, 16, 10, 1)
43 _set_up_invis_wall(root, 50.5, 11, 14, 10, 10, 1)
44 _set_up_invis_wall(root, 39, 10, 18.5, 1, 10, 22)
45 _set_up_invis_wall(root, 20, 15, 18.5, 1, 10, 16)
46 _set_up_invis_wall(root, 11.5, 15, 3, 32, 10, 1)
47 _set_up_invis_wall(root, 11.5, 16, -20, 14, 20, 1)
48 _set_up_invis_wall(root, 14, 16, -26.5, 1, 20, 4)
49 _set_up_invis_wall(root, 28.5, 20.5, -26.5, 1, 15, 25)
50 _set_up_invis_wall(root, 40.5, 20.5, -11, 30, 15, 1)
51 _set_up_invis_wall(root, 50.5, 15, 5.5, 7, 10, 1)
52 _set_up_invis_wall(root, 83.5, 33.5, 5.5, 1, 7, 11)
53 _set_up_invis_wall(root, 83.5, 33.5, -5.5, 1, 7, 11)
54
55 var warp_exit_prefab = preload("res://objects/nodes/exit.tscn")
56 var warp_exit = warp_exit_prefab.instantiate()
57 warp_exit.name = "roof_access_blocker_warp_exit"
58 warp_exit.position = Vector3(58, 10, 0)
59 warp_exit.rotation_degrees.y = 90
60 root.get_node("/root/scene").add_child.call_deferred(warp_exit)
61
62 var warp_enter_prefab = preload("res://objects/nodes/teleportAuto.tscn")
63 var warp_enter = warp_enter_prefab.instantiate()
64 warp_enter.target = warp_exit
65 warp_enter.position = Vector3(76.5, 30, 1)
66 warp_enter.scale = Vector3(4, 1.5, 1)
67 warp_enter.rotation_degrees.y = 90
68 root.get_node("/root/scene").add_child.call_deferred(warp_enter)
69
70
71func _set_up_invis_wall(root, x, y, z, sx, sy, sz):
72 var prefab = preload("res://objects/nodes/block.tscn")
73 var newwall = prefab.instantiate()
74 newwall.position.x = x
75 newwall.position.y = y
76 newwall.position.z = z
77 newwall.scale.x = sz
78 newwall.scale.y = sy
79 newwall.scale.z = sx
80 newwall.set_surface_override_material(0, preload("res://assets/materials/blackMatte.material"))
81 newwall.visibility_range_end = 3
82 newwall.visibility_range_end_margin = 1
83 newwall.visibility_range_fade_mode = RenderingServer.VISIBILITY_RANGE_FADE_SELF
84 newwall.skeleton = ".."
85 root.get_node("/root/scene").add_child.call_deferred(newwall)
diff --git a/apworld/client/maps/icarus.gd b/apworld/client/maps/icarus.gd new file mode 100644 index 0000000..ad00741 --- /dev/null +++ b/apworld/client/maps/icarus.gd
@@ -0,0 +1,38 @@
1func on_map_load(root):
2 var ap = global.get_node("Archipelago")
3
4 # Add the mastery to Icarus.
5 if ap.enable_icarus:
6 var collectable_prefab = preload("res://objects/nodes/collectable.tscn")
7 var saver_prefab = preload("res://objects/nodes/saver.tscn")
8 var tpl_prefab = preload("res://objects/nodes/listeners/teleportListener.tscn")
9 var usl_prefab = preload("res://objects/nodes/listeners/unlockSetterListener.tscn")
10
11 var mastery = collectable_prefab.instantiate()
12 mastery.name = "collectable"
13 mastery.position = Vector3(0, -2000, 0)
14 mastery.unlock_type = "smiley"
15 mastery.material_override = load("res://assets/materials/gold.material")
16 root.get_node("/root/scene/Components/Collectables").add_child.call_deferred(mastery)
17
18 var tpl = tpl_prefab.instantiate()
19 tpl.teleport_point = Vector3(56.25, 0, -5.5)
20 tpl.teleport_rotate = Vector3(0, 0, 0)
21 tpl.target_path = mastery
22 tpl.name = "Teleport"
23 tpl.senderGroup.append(NodePath("/root/scene/Panels"))
24 tpl.nested = true
25 mastery.add_child.call_deferred(tpl)
26
27 var usl = usl_prefab.instantiate()
28 usl.name = "unlockSetterListenerMastery"
29 usl.key = "icarus_mastery"
30 usl.value = "unlocked"
31 usl.senders.append(NodePath("/root/scene/Components/Collectables/collectable"))
32 root.get_node("/root/scene/Components").add_child.call_deferred(usl)
33
34 var saver = saver_prefab.instantiate()
35 saver.name = "saver_collectables"
36 saver.type = "collectables"
37 saver.senderGroup.append(NodePath("/root/scene/Components/Collectables"))
38 root.get_node("/root/scene").add_child.call_deferred(saver)
diff --git a/apworld/client/maps/the_advanced.gd b/apworld/client/maps/the_advanced.gd new file mode 100644 index 0000000..b41549c --- /dev/null +++ b/apworld/client/maps/the_advanced.gd
@@ -0,0 +1,36 @@
1func on_map_load(root):
2 # Add the mastery to The Advanced.
3 var collectable_prefab = preload("res://objects/nodes/collectable.tscn")
4 var saver_prefab = preload("res://objects/nodes/saver.tscn")
5 var tpl_prefab = preload("res://objects/nodes/listeners/teleportListener.tscn")
6 var usl_prefab = preload("res://objects/nodes/listeners/unlockSetterListener.tscn")
7
8 var mastery = collectable_prefab.instantiate()
9 mastery.name = "collectable"
10 mastery.position = Vector3(0, -200, -5)
11 mastery.unlock_type = "smiley"
12 mastery.material_override = load("res://assets/materials/gold.material")
13 root.get_node("/root/scene/Components/Collectables").add_child.call_deferred(mastery)
14
15 var tpl = tpl_prefab.instantiate()
16 tpl.teleport_point = Vector3(0, 2, -5)
17 tpl.teleport_rotate = Vector3(0, 0, 0)
18 tpl.target_path = mastery
19 tpl.name = "Teleport"
20 tpl.senders.append(NodePath("/root/scene/Panels/Room_1/panel_29"))
21 tpl.senders.append(NodePath("/root/scene/Panels/Room_1/panel_30"))
22 tpl.senders.append(NodePath("/root/scene/Panels/Room_1/panel_31"))
23 mastery.add_child.call_deferred(tpl)
24
25 var usl = usl_prefab.instantiate()
26 usl.name = "unlockSetterListenerMastery"
27 usl.key = "advanced_mastery"
28 usl.value = "unlocked"
29 usl.senders.append(NodePath("/root/scene/Components/Collectables/collectable"))
30 root.get_node("/root/scene/Components").add_child.call_deferred(usl)
31
32 var saver = saver_prefab.instantiate()
33 saver.name = "saver_collectables"
34 saver.type = "collectables"
35 saver.senderGroup.append(NodePath("/root/scene/Components/Collectables"))
36 root.get_node("/root/scene").add_child.call_deferred(saver)
diff --git a/apworld/client/maps/the_charismatic.gd b/apworld/client/maps/the_charismatic.gd new file mode 100644 index 0000000..734001d --- /dev/null +++ b/apworld/client/maps/the_charismatic.gd
@@ -0,0 +1,26 @@
1func on_map_load(root):
2 # Add the mastery to The Charismatic.
3 var collectable_prefab = preload("res://objects/nodes/collectable.tscn")
4 var saver_prefab = preload("res://objects/nodes/saver.tscn")
5 var usl_prefab = preload("res://objects/nodes/listeners/unlockSetterListener.tscn")
6
7 var mastery = collectable_prefab.instantiate()
8 mastery.name = "collectable"
9 mastery.position = Vector3(-17, 2, -29)
10 mastery.rotation_degrees = Vector3(0, 45, 0)
11 mastery.unlock_type = "smiley"
12 mastery.material_override = load("res://assets/materials/gold.material")
13 root.get_node("/root/scene/Components/Collectables").add_child.call_deferred(mastery)
14
15 var usl = usl_prefab.instantiate()
16 usl.name = "unlockSetterListenerMastery"
17 usl.key = "charismatic_mastery"
18 usl.value = "unlocked"
19 usl.senders.append(NodePath("/root/scene/Components/Collectables/collectable"))
20 root.get_node("/root/scene/Components").add_child.call_deferred(usl)
21
22 var saver = saver_prefab.instantiate()
23 saver.name = "saver_collectables"
24 saver.type = "collectables"
25 saver.senderGroup.append(NodePath("/root/scene/Components/Collectables"))
26 root.get_node("/root/scene").add_child.call_deferred(saver)
diff --git a/apworld/client/maps/the_crystalline.gd b/apworld/client/maps/the_crystalline.gd new file mode 100644 index 0000000..7d43e78 --- /dev/null +++ b/apworld/client/maps/the_crystalline.gd
@@ -0,0 +1,34 @@
1func on_map_load(root):
2 # Add the mastery to The Crystalline.
3 var collectable_prefab = preload("res://objects/nodes/collectable.tscn")
4 var saver_prefab = preload("res://objects/nodes/saver.tscn")
5 var tpl_prefab = preload("res://objects/nodes/listeners/teleportListener.tscn")
6 var usl_prefab = preload("res://objects/nodes/listeners/unlockSetterListener.tscn")
7
8 var mastery = collectable_prefab.instantiate()
9 mastery.name = "collectable"
10 mastery.position = Vector3(0, 13, 37)
11 mastery.unlock_type = "smiley"
12 mastery.material_override = load("res://assets/materials/gold.material")
13 root.get_node("/root/scene/Components/Collectables").add_child.call_deferred(mastery)
14
15 var tpl = tpl_prefab.instantiate()
16 tpl.teleport_point = Vector3(0, 11.5, -20)
17 tpl.teleport_rotate = Vector3(0, 0, 180)
18 tpl.target_path = mastery
19 tpl.name = "Teleport"
20 tpl.senders.append(NodePath("/root/scene/Panels/Room_1/panel_3"))
21 mastery.add_child.call_deferred(tpl)
22
23 var usl = usl_prefab.instantiate()
24 usl.name = "unlockSetterListenerMastery"
25 usl.key = "crystalline_mastery"
26 usl.value = "unlocked"
27 usl.senders.append(NodePath("/root/scene/Components/Collectables/collectable"))
28 root.get_node("/root/scene/Components").add_child.call_deferred(usl)
29
30 var saver = saver_prefab.instantiate()
31 saver.name = "saver_collectables"
32 saver.type = "collectables"
33 saver.senderGroup.append(NodePath("/root/scene/Components/Collectables"))
34 root.get_node("/root/scene").add_child.call_deferred(saver)
diff --git a/apworld/client/maps/the_entry.gd b/apworld/client/maps/the_entry.gd new file mode 100644 index 0000000..3608bb3 --- /dev/null +++ b/apworld/client/maps/the_entry.gd
@@ -0,0 +1,156 @@
1func on_map_load(root):
2 var ap = global.get_node("Archipelago")
3
4 # Remove door behind X1.
5 var door_node = root.get_node("/root/scene/Components/Doors/exit_1")
6 door_node.handleTriggered()
7
8 # Display win condition.
9 var sign_prefab = preload("res://objects/nodes/sign.tscn")
10 var sign1 = sign_prefab.instantiate()
11 sign1.position = Vector3(-7, 5, -15.01)
12 sign1.text = "victory"
13 root.get_node("/root/scene").add_child.call_deferred(sign1)
14
15 var sign2 = sign_prefab.instantiate()
16 sign2.position = Vector3(-7, 4, -15.01)
17 sign2.text = "%s ending" % ap.kEndingNameByVictoryValue.get(ap.victory_condition, "?")
18
19 var sign2_color = ap.kEndingNameByVictoryValue.get(ap.victory_condition, "coral").to_lower()
20 if sign2_color == "white":
21 sign2_color = "silver"
22
23 sign2.material = load("res://assets/materials/%s.material" % sign2_color)
24 root.get_node("/root/scene").add_child.call_deferred(sign2)
25
26 # Add the gift map entry panel if needed.
27 if not ap.enable_gift_maps.is_empty():
28 var panel_prefab = preload("res://objects/nodes/panel.tscn")
29 var tpl_prefab = preload("res://objects/nodes/listeners/teleportListener.tscn")
30 var wpl_prefab = preload("res://objects/nodes/listeners/worldportListener.tscn")
31
32 var giftmap_parent = Node.new()
33 giftmap_parent.name = "GiftMapEntrance"
34 root.get_node("/root/scene/Components").add_child.call_deferred(giftmap_parent)
35
36 var symbolless_player = ""
37 for i in range(ap.client.ap_user.length()):
38 if "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".contains(
39 ap.client.ap_user[i]
40 ):
41 symbolless_player = symbolless_player + ap.client.ap_user[i].to_lower()
42
43 var giftmap_panel = panel_prefab.instantiate()
44 giftmap_panel.name = "Panel"
45 giftmap_panel.position = Vector3(33.5, -190, 5.5)
46 giftmap_panel.rotation_degrees = Vector3(-45, 0, 0)
47 giftmap_panel.clue = "player"
48 giftmap_panel.answer = symbolless_player
49
50 if ap.enable_gift_maps.has("The Advanced"):
51 var icely_panel = panel_prefab.instantiate()
52 icely_panel.name = "IcelyPanel"
53 icely_panel.answer = "icely"
54 icely_panel.position = Vector3(33.5, -200, 5.5)
55 giftmap_panel.proxies.append(NodePath("../IcelyPanel"))
56 giftmap_parent.add_child.call_deferred(icely_panel)
57
58 var icely_wpl = wpl_prefab.instantiate()
59 icely_wpl.name = "IcelyWpl"
60 icely_wpl.exit = "the_advanced"
61 icely_wpl.senders.append(NodePath("../IcelyPanel"))
62 giftmap_parent.add_child.call_deferred(icely_wpl)
63
64 if ap.enable_gift_maps.has("The Charismatic"):
65 var souvey_panel = panel_prefab.instantiate()
66 souvey_panel.name = "SouveyPanel"
67 souvey_panel.answer = "souvey"
68 souvey_panel.position = Vector3(33.5, -210, 5.5)
69 giftmap_panel.proxies.append(NodePath("../SouveyPanel"))
70 giftmap_parent.add_child.call_deferred(souvey_panel)
71
72 var souvey_wpl = wpl_prefab.instantiate()
73 souvey_wpl.name = "SouveyWpl"
74 souvey_wpl.exit = "the_charismatic"
75 souvey_wpl.senders.append(NodePath("../SouveyPanel"))
76 giftmap_parent.add_child.call_deferred(souvey_wpl)
77
78 if ap.enable_gift_maps.has("The Crystalline"):
79 var q_panel = panel_prefab.instantiate()
80 q_panel.name = "QPanel"
81 q_panel.answer = "q"
82 q_panel.position = Vector3(33.5, -220, 5.5)
83 giftmap_panel.proxies.append(NodePath("../QPanel"))
84 giftmap_parent.add_child.call_deferred(q_panel)
85
86 var q_wpl = wpl_prefab.instantiate()
87 q_wpl.name = "QWpl"
88 q_wpl.exit = "the_crystalline"
89 q_wpl.senders.append(NodePath("../QPanel"))
90 giftmap_parent.add_child.call_deferred(q_wpl)
91
92 if ap.enable_gift_maps.has("The Fuzzy"):
93 var gongus_panel = panel_prefab.instantiate()
94 gongus_panel.name = "GongusPanel"
95 gongus_panel.answer = "gongus"
96 gongus_panel.position = Vector3(33.5, -260, 5.5)
97 giftmap_panel.proxies.append(NodePath("../GongusPanel"))
98 giftmap_parent.add_child.call_deferred(gongus_panel)
99
100 var kiwi_panel = panel_prefab.instantiate()
101 kiwi_panel.name = "KiwiPanel"
102 kiwi_panel.answer = "kiwi"
103 kiwi_panel.position = Vector3(33.5, -270, 5.5)
104 giftmap_panel.proxies.append(NodePath("../KiwiPanel"))
105 giftmap_parent.add_child.call_deferred(kiwi_panel)
106
107 var fuzzy_wpl = wpl_prefab.instantiate()
108 fuzzy_wpl.name = "FuzzyWpl"
109 fuzzy_wpl.exit = "the_fuzzy"
110 fuzzy_wpl.senders.append(NodePath("../GongusPanel"))
111 fuzzy_wpl.senders.append(NodePath("../KiwiPanel"))
112 fuzzy_wpl.complete_at = 1
113 giftmap_parent.add_child.call_deferred(fuzzy_wpl)
114
115 if ap.enable_gift_maps.has("The Stellar"):
116 var hatkirby_panel = panel_prefab.instantiate()
117 hatkirby_panel.name = "HatkirbyPanel"
118 hatkirby_panel.answer = "hatkirby"
119 hatkirby_panel.position = Vector3(33.5, -230, 5.5)
120 giftmap_panel.proxies.append(NodePath("../HatkirbyPanel"))
121 giftmap_parent.add_child.call_deferred(hatkirby_panel)
122
123 var kirby_panel = panel_prefab.instantiate()
124 kirby_panel.name = "KirbyPanel"
125 kirby_panel.answer = "kirby"
126 kirby_panel.position = Vector3(33.5, -240, 5.5)
127 giftmap_panel.proxies.append(NodePath("../KirbyPanel"))
128 giftmap_parent.add_child.call_deferred(kirby_panel)
129
130 var star_panel = panel_prefab.instantiate()
131 star_panel.name = "StarPanel"
132 star_panel.answer = "star"
133 star_panel.position = Vector3(33.5, -250, 5.5)
134 giftmap_panel.proxies.append(NodePath("../StarPanel"))
135 giftmap_parent.add_child.call_deferred(star_panel)
136
137 var stellar_wpl = wpl_prefab.instantiate()
138 stellar_wpl.name = "StellarWpl"
139 stellar_wpl.exit = "the_stellar"
140 stellar_wpl.senders.append(NodePath("../HatkirbyPanel"))
141 stellar_wpl.senders.append(NodePath("../KirbyPanel"))
142 stellar_wpl.senders.append(NodePath("../StarPanel"))
143 stellar_wpl.complete_at = 1
144 giftmap_parent.add_child.call_deferred(stellar_wpl)
145
146 giftmap_parent.add_child.call_deferred(giftmap_panel)
147
148 var giftmap_tpl = tpl_prefab.instantiate()
149 giftmap_tpl.name = "PanelTeleporter"
150 giftmap_tpl.teleport_point = Vector3(33.5, 1, 5.5)
151 giftmap_tpl.teleport_rotate = Vector3(-45, 0, 0)
152 giftmap_tpl.target_path = giftmap_panel
153 giftmap_tpl.senders.append(
154 NodePath("/root/scene/Components/Listeners/unlockReaderListenerDoubles")
155 )
156 giftmap_parent.add_child.call_deferred(giftmap_tpl)
diff --git a/apworld/client/maps/the_fuzzy.gd b/apworld/client/maps/the_fuzzy.gd new file mode 100644 index 0000000..269dcee --- /dev/null +++ b/apworld/client/maps/the_fuzzy.gd
@@ -0,0 +1,25 @@
1func on_map_load(root):
2 # Add the mastery to The Fuzzy.
3 var collectable_prefab = preload("res://objects/nodes/collectable.tscn")
4 var saver_prefab = preload("res://objects/nodes/saver.tscn")
5 var usl_prefab = preload("res://objects/nodes/listeners/unlockSetterListener.tscn")
6
7 var mastery = collectable_prefab.instantiate()
8 mastery.name = "collectable"
9 mastery.position = Vector3(0, 2, -20)
10 mastery.unlock_type = "smiley"
11 mastery.material_override = load("res://assets/materials/gold.material")
12 root.get_node("/root/scene/Components/Collectables").add_child.call_deferred(mastery)
13
14 var usl = usl_prefab.instantiate()
15 usl.name = "unlockSetterListenerMastery"
16 usl.key = "fuzzy_mastery"
17 usl.value = "unlocked"
18 usl.senders.append(NodePath("/root/scene/Components/Collectables/collectable"))
19 root.get_node("/root/scene/Components").add_child.call_deferred(usl)
20
21 var saver = saver_prefab.instantiate()
22 saver.name = "saver_collectables"
23 saver.type = "collectables"
24 saver.senderGroup.append(NodePath("/root/scene/Components/Collectables"))
25 root.get_node("/root/scene").add_child.call_deferred(saver)
diff --git a/apworld/client/maps/the_parthenon.gd b/apworld/client/maps/the_parthenon.gd new file mode 100644 index 0000000..96510da --- /dev/null +++ b/apworld/client/maps/the_parthenon.gd
@@ -0,0 +1,51 @@
1func on_map_load(root):
2 var ap = global.get_node("Archipelago")
3
4 # Add the strict cyan ending validation.
5 if ap.strict_cyan_ending:
6 var panel_prefab = preload("res://objects/nodes/panel.tscn")
7 var tpl_prefab = preload("res://objects/nodes/listeners/teleportListener.tscn")
8 var reverse_prefab = preload("res://objects/nodes/listeners/reversingListener.tscn")
9
10 var previous_panel = null
11 var next_y = -100
12 var words = ["quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog"]
13 for word in words:
14 var panel = panel_prefab.instantiate()
15 panel.position = Vector3(0, next_y, 0)
16 next_y -= 10
17 panel.clue = word
18 panel.symbol = "."
19 panel.answer = "%s%s" % [word, word]
20 panel.name = "EndCheck_%s" % word
21
22 var tpl = tpl_prefab.instantiate()
23 tpl.teleport_point = Vector3(0, 1, -11)
24 tpl.teleport_rotate = Vector3(-45, 0, 0)
25 tpl.target_path = panel
26 tpl.name = "Teleport"
27
28 if previous_panel == null:
29 tpl.senderGroup.append(NodePath("/root/scene/Panels/Rulers"))
30 else:
31 tpl.senders.append(NodePath("../../%s" % previous_panel.name))
32
33 var reversing = reverse_prefab.instantiate()
34 reversing.senders.append(NodePath(".."))
35 reversing.name = "Reversing"
36 tpl.senders.append(NodePath("../Reversing"))
37
38 panel.add_child.call_deferred(tpl)
39 panel.add_child.call_deferred(reversing)
40 root.get_node("/root/scene/Panels").add_child.call_deferred(panel)
41
42 previous_panel = panel
43
44 # Duplicate the door that usually waits on the rulers. We can't set the
45 # senders here for some reason so we actually set them in the door ready
46 # function.
47 var entry1 = root.get_node("/root/scene/Components/Doors/entry_1")
48 var entry12 = entry1.duplicate()
49 entry12.name = "spe_entry_1"
50 entry1.get_parent().add_child.call_deferred(entry12)
51 entry1.queue_free()
diff --git a/apworld/client/maps/the_plaza.gd b/apworld/client/maps/the_plaza.gd new file mode 100644 index 0000000..13e002d --- /dev/null +++ b/apworld/client/maps/the_plaza.gd
@@ -0,0 +1,4 @@
1func on_map_load(root):
2 # Move the Plaza RTE trigger outside of the turtle.
3 var rte_trigger = root.get_node("/root/scene/Components/Warps/triggerArea")
4 rte_trigger.position.z = 0
diff --git a/apworld/client/maps/the_stellar.gd b/apworld/client/maps/the_stellar.gd new file mode 100644 index 0000000..d633535 --- /dev/null +++ b/apworld/client/maps/the_stellar.gd
@@ -0,0 +1,30 @@
1func on_map_load(root):
2 # Add the mastery to The Stellar.
3 var collectable_prefab = preload("res://objects/nodes/collectable.tscn")
4 var saver_prefab = preload("res://objects/nodes/saver.tscn")
5 var usl_prefab = preload("res://objects/nodes/listeners/unlockSetterListener.tscn")
6
7 var collectables = Node.new()
8 collectables.name = "Collectables"
9
10 var mastery = collectable_prefab.instantiate()
11 mastery.name = "collectable"
12 mastery.position = Vector3(2, 2, -31)
13 mastery.rotation_degrees = Vector3(0, 90, 0)
14 mastery.unlock_type = "smiley"
15 mastery.material_override = load("res://assets/materials/gold.material")
16 collectables.add_child.call_deferred(mastery)
17 root.get_node("/root/scene/Components").add_child.call_deferred(collectables)
18
19 var usl = usl_prefab.instantiate()
20 usl.name = "unlockSetterListenerMastery"
21 usl.key = "stellar_mastery"
22 usl.value = "unlocked"
23 usl.senders.append(NodePath("/root/scene/Components/Collectables/collectable"))
24 root.get_node("/root/scene/Components").add_child.call_deferred(usl)
25
26 var saver = saver_prefab.instantiate()
27 saver.name = "saver_collectables"
28 saver.type = "collectables"
29 saver.senderGroup.append(NodePath("/root/scene/Components/Collectables"))
30 root.get_node("/root/scene").add_child.call_deferred(saver)
diff --git a/apworld/client/maps/the_sun_temple.gd b/apworld/client/maps/the_sun_temple.gd new file mode 100644 index 0000000..9804bf8 --- /dev/null +++ b/apworld/client/maps/the_sun_temple.gd
@@ -0,0 +1,56 @@
1func on_map_load(root):
2 var ap = global.get_node("Archipelago")
3
4 # Add the strict purple ending validation.
5 if ap.strict_purple_ending:
6 var panel_prefab = preload("res://objects/nodes/panel.tscn")
7 var tpl_prefab = preload("res://objects/nodes/listeners/teleportListener.tscn")
8 var reverse_prefab = preload("res://objects/nodes/listeners/reversingListener.tscn")
9
10 var previous_panel = null
11 var next_y = -100
12 var words = ["quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog"]
13 for word in words:
14 var panel = panel_prefab.instantiate()
15 panel.position = Vector3(0, next_y, 0)
16 next_y -= 10
17 panel.clue = word
18 panel.symbol = ""
19 panel.answer = word
20 panel.name = "EndCheck_%s" % word
21
22 var tpl = tpl_prefab.instantiate()
23 tpl.teleport_point = Vector3(0, 1, 0)
24 tpl.teleport_rotate = Vector3(-45, 180, 0)
25 tpl.target_path = panel
26 tpl.name = "Teleport"
27
28 if previous_panel == null:
29 tpl.senders.append(NodePath("/root/scene/Panels/End/panel_24"))
30 else:
31 tpl.senders.append(NodePath("../../%s" % previous_panel.name))
32
33 var reversing = reverse_prefab.instantiate()
34 reversing.senders.append(NodePath(".."))
35 reversing.name = "Reversing"
36 tpl.senders.append(NodePath("../Reversing"))
37
38 panel.add_child.call_deferred(tpl)
39 panel.add_child.call_deferred(reversing)
40 root.get_node("/root/scene/Panels").add_child.call_deferred(panel)
41
42 previous_panel = panel
43
44 # Duplicate the doors that usually wait on EQUINOX. We can't set the senders
45 # here for some reason so we actually set them in the door ready function.
46 var endplat = root.get_node("/root/scene/Components/Doors/EndPlatform")
47 var endplat2 = endplat.duplicate()
48 endplat2.name = "spe_EndPlatform"
49 endplat.get_parent().add_child.call_deferred(endplat2)
50 endplat.queue_free()
51
52 var entry2 = root.get_node("/root/scene/Components/Doors/entry_2")
53 var entry22 = entry2.duplicate()
54 entry22.name = "spe_entry_2"
55 entry2.get_parent().add_child.call_deferred(entry22)
56 entry2.queue_free()
diff --git a/apworld/client/maps/the_unkempt.gd b/apworld/client/maps/the_unkempt.gd new file mode 100644 index 0000000..c907650 --- /dev/null +++ b/apworld/client/maps/the_unkempt.gd
@@ -0,0 +1,4 @@
1func on_map_load(root):
2 # Prevent the COLOR panel from disappearing.
3 var color_tpl = root.get_node("/root/scene/Panels/Assorted/panel_1/teleportListener")
4 color_tpl.target_path = color_tpl
diff --git a/apworld/client/maps/the_unyielding.gd b/apworld/client/maps/the_unyielding.gd new file mode 100644 index 0000000..a2f8eee --- /dev/null +++ b/apworld/client/maps/the_unyielding.gd
@@ -0,0 +1,5 @@
1func on_map_load(root):
2 # Shrink the painting trigger in The Unyielding.
3 var trigger_area = root.get_node("/root/scene/Components/PaintingUnlocker/triggerArea")
4 trigger_area.position = Vector3(0, 0, -6)
5 trigger_area.scale = Vector3(6, 1, 6)
diff --git a/apworld/client/player.gd b/apworld/client/player.gd index 789d1b7..5fac9fd 100644 --- a/apworld/client/player.gd +++ b/apworld/client/player.gd
@@ -19,404 +19,10 @@ func _ready():
19 19
20 ap.start_batching_locations() 20 ap.start_batching_locations()
21 21
22 # Block off roof access in Daedalus. 22 # Run map-specific initialization.
23 if global.map == "daedalus" and not ap.daedalus_roof_access: 23 var map_script = ap.get_map_script(global.map)
24 _set_up_invis_wall(75.5, 11, -24.5, 1, 10, 49) 24 if map_script != null:
25 _set_up_invis_wall(51.5, 11, -17, 16, 10, 1) 25 map_script.on_map_load(get_tree().get_root())
26 _set_up_invis_wall(46, 10, -9.5, 1, 10, 10)
27 _set_up_invis_wall(67.5, 11, 17, 16, 10, 1)
28 _set_up_invis_wall(50.5, 11, 14, 10, 10, 1)
29 _set_up_invis_wall(39, 10, 18.5, 1, 10, 22)
30 _set_up_invis_wall(20, 15, 18.5, 1, 10, 16)
31 _set_up_invis_wall(11.5, 15, 3, 32, 10, 1)
32 _set_up_invis_wall(11.5, 16, -20, 14, 20, 1)
33 _set_up_invis_wall(14, 16, -26.5, 1, 20, 4)
34 _set_up_invis_wall(28.5, 20.5, -26.5, 1, 15, 25)
35 _set_up_invis_wall(40.5, 20.5, -11, 30, 15, 1)
36 _set_up_invis_wall(50.5, 15, 5.5, 7, 10, 1)
37 _set_up_invis_wall(83.5, 33.5, 5.5, 1, 7, 11)
38 _set_up_invis_wall(83.5, 33.5, -5.5, 1, 7, 11)
39
40 var warp_exit_prefab = preload("res://objects/nodes/exit.tscn")
41 var warp_exit = warp_exit_prefab.instantiate()
42 warp_exit.name = "roof_access_blocker_warp_exit"
43 warp_exit.position = Vector3(58, 10, 0)
44 warp_exit.rotation_degrees.y = 90
45 get_parent().add_child.call_deferred(warp_exit)
46
47 var warp_enter_prefab = preload("res://objects/nodes/teleportAuto.tscn")
48 var warp_enter = warp_enter_prefab.instantiate()
49 warp_enter.target = warp_exit
50 warp_enter.position = Vector3(76.5, 30, 1)
51 warp_enter.scale = Vector3(4, 1.5, 1)
52 warp_enter.rotation_degrees.y = 90
53 get_parent().add_child.call_deferred(warp_enter)
54
55 if global.map == "the_entry":
56 # Remove door behind X1.
57 var door_node = get_tree().get_root().get_node("/root/scene/Components/Doors/exit_1")
58 door_node.handleTriggered()
59
60 # Display win condition.
61 var sign_prefab = preload("res://objects/nodes/sign.tscn")
62 var sign1 = sign_prefab.instantiate()
63 sign1.position = Vector3(-7, 5, -15.01)
64 sign1.text = "victory"
65 get_parent().add_child.call_deferred(sign1)
66
67 var sign2 = sign_prefab.instantiate()
68 sign2.position = Vector3(-7, 4, -15.01)
69 sign2.text = "%s ending" % ap.kEndingNameByVictoryValue.get(ap.victory_condition, "?")
70
71 var sign2_color = ap.kEndingNameByVictoryValue.get(ap.victory_condition, "coral").to_lower()
72 if sign2_color == "white":
73 sign2_color = "silver"
74
75 sign2.material = load("res://assets/materials/%s.material" % sign2_color)
76 get_parent().add_child.call_deferred(sign2)
77
78 # Add the gift map entry panel if needed.
79 if not ap.enable_gift_maps.is_empty():
80 var panel_prefab = preload("res://objects/nodes/panel.tscn")
81 var tpl_prefab = preload("res://objects/nodes/listeners/teleportListener.tscn")
82 var wpl_prefab = preload("res://objects/nodes/listeners/worldportListener.tscn")
83
84 var giftmap_parent = Node.new()
85 giftmap_parent.name = "GiftMapEntrance"
86 get_node("/root/scene/Components").add_child.call_deferred(giftmap_parent)
87
88 var symbolless_player = ""
89 for i in range(ap.client.ap_user.length()):
90 if "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".contains(
91 ap.client.ap_user[i]
92 ):
93 symbolless_player = symbolless_player + ap.client.ap_user[i].to_lower()
94
95 var giftmap_panel = panel_prefab.instantiate()
96 giftmap_panel.name = "Panel"
97 giftmap_panel.position = Vector3(33.5, -190, 5.5)
98 giftmap_panel.rotation_degrees = Vector3(-45, 0, 0)
99 giftmap_panel.clue = "player"
100 giftmap_panel.answer = symbolless_player
101
102 if ap.enable_gift_maps.has("The Advanced"):
103 var icely_panel = panel_prefab.instantiate()
104 icely_panel.name = "IcelyPanel"
105 icely_panel.answer = "icely"
106 icely_panel.position = Vector3(33.5, -200, 5.5)
107 giftmap_panel.proxies.append(NodePath("../IcelyPanel"))
108 giftmap_parent.add_child.call_deferred(icely_panel)
109
110 var icely_wpl = wpl_prefab.instantiate()
111 icely_wpl.name = "IcelyWpl"
112 icely_wpl.exit = "the_advanced"
113 icely_wpl.senders.append(NodePath("../IcelyPanel"))
114 giftmap_parent.add_child.call_deferred(icely_wpl)
115
116 if ap.enable_gift_maps.has("The Charismatic"):
117 var souvey_panel = panel_prefab.instantiate()
118 souvey_panel.name = "SouveyPanel"
119 souvey_panel.answer = "souvey"
120 souvey_panel.position = Vector3(33.5, -210, 5.5)
121 giftmap_panel.proxies.append(NodePath("../SouveyPanel"))
122 giftmap_parent.add_child.call_deferred(souvey_panel)
123
124 var souvey_wpl = wpl_prefab.instantiate()
125 souvey_wpl.name = "SouveyWpl"
126 souvey_wpl.exit = "the_charismatic"
127 souvey_wpl.senders.append(NodePath("../SouveyPanel"))
128 giftmap_parent.add_child.call_deferred(souvey_wpl)
129
130 if ap.enable_gift_maps.has("The Crystalline"):
131 var q_panel = panel_prefab.instantiate()
132 q_panel.name = "QPanel"
133 q_panel.answer = "q"
134 q_panel.position = Vector3(33.5, -220, 5.5)
135 giftmap_panel.proxies.append(NodePath("../QPanel"))
136 giftmap_parent.add_child.call_deferred(q_panel)
137
138 var q_wpl = wpl_prefab.instantiate()
139 q_wpl.name = "QWpl"
140 q_wpl.exit = "the_crystalline"
141 q_wpl.senders.append(NodePath("../QPanel"))
142 giftmap_parent.add_child.call_deferred(q_wpl)
143
144 if ap.enable_gift_maps.has("The Stellar"):
145 var hatkirby_panel = panel_prefab.instantiate()
146 hatkirby_panel.name = "HatkirbyPanel"
147 hatkirby_panel.answer = "hatkirby"
148 hatkirby_panel.position = Vector3(33.5, -230, 5.5)
149 giftmap_panel.proxies.append(NodePath("../HatkirbyPanel"))
150 giftmap_parent.add_child.call_deferred(hatkirby_panel)
151
152 var kirby_panel = panel_prefab.instantiate()
153 kirby_panel.name = "KirbyPanel"
154 kirby_panel.answer = "kirby"
155 kirby_panel.position = Vector3(33.5, -240, 5.5)
156 giftmap_panel.proxies.append(NodePath("../KirbyPanel"))
157 giftmap_parent.add_child.call_deferred(kirby_panel)
158
159 var star_panel = panel_prefab.instantiate()
160 star_panel.name = "StarPanel"
161 star_panel.answer = "star"
162 star_panel.position = Vector3(33.5, -250, 5.5)
163 giftmap_panel.proxies.append(NodePath("../StarPanel"))
164 giftmap_parent.add_child.call_deferred(star_panel)
165
166 var stellar_wpl = wpl_prefab.instantiate()
167 stellar_wpl.name = "StellarWpl"
168 stellar_wpl.exit = "the_stellar"
169 stellar_wpl.senders.append(NodePath("../HatkirbyPanel"))
170 stellar_wpl.senders.append(NodePath("../KirbyPanel"))
171 stellar_wpl.senders.append(NodePath("../StarPanel"))
172 stellar_wpl.complete_at = 1
173 giftmap_parent.add_child.call_deferred(stellar_wpl)
174
175 giftmap_parent.add_child.call_deferred(giftmap_panel)
176
177 var giftmap_tpl = tpl_prefab.instantiate()
178 giftmap_tpl.name = "PanelTeleporter"
179 giftmap_tpl.teleport_point = Vector3(33.5, 1, 5.5)
180 giftmap_tpl.teleport_rotate = Vector3(-45, 0, 0)
181 giftmap_tpl.target_path = giftmap_panel
182 giftmap_tpl.senders.append(
183 NodePath("/root/scene/Components/Listeners/unlockReaderListenerDoubles")
184 )
185 giftmap_parent.add_child.call_deferred(giftmap_tpl)
186
187 # Add the strict purple ending validation.
188 if global.map == "the_sun_temple" and ap.strict_purple_ending:
189 var panel_prefab = preload("res://objects/nodes/panel.tscn")
190 var tpl_prefab = preload("res://objects/nodes/listeners/teleportListener.tscn")
191 var reverse_prefab = preload("res://objects/nodes/listeners/reversingListener.tscn")
192
193 var previous_panel = null
194 var next_y = -100
195 var words = ["quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog"]
196 for word in words:
197 var panel = panel_prefab.instantiate()
198 panel.position = Vector3(0, next_y, 0)
199 next_y -= 10
200 panel.clue = word
201 panel.symbol = ""
202 panel.answer = word
203 panel.name = "EndCheck_%s" % word
204
205 var tpl = tpl_prefab.instantiate()
206 tpl.teleport_point = Vector3(0, 1, 0)
207 tpl.teleport_rotate = Vector3(-45, 180, 0)
208 tpl.target_path = panel
209 tpl.name = "Teleport"
210
211 if previous_panel == null:
212 tpl.senders.append(NodePath("/root/scene/Panels/End/panel_24"))
213 else:
214 tpl.senders.append(NodePath("../../%s" % previous_panel.name))
215
216 var reversing = reverse_prefab.instantiate()
217 reversing.senders.append(NodePath(".."))
218 reversing.name = "Reversing"
219 tpl.senders.append(NodePath("../Reversing"))
220
221 panel.add_child.call_deferred(tpl)
222 panel.add_child.call_deferred(reversing)
223 get_parent().get_node("Panels").add_child.call_deferred(panel)
224
225 previous_panel = panel
226
227 # Duplicate the doors that usually wait on EQUINOX. We can't set the senders
228 # here for some reason so we actually set them in the door ready function.
229 var endplat = get_node("/root/scene/Components/Doors/EndPlatform")
230 var endplat2 = endplat.duplicate()
231 endplat2.name = "spe_EndPlatform"
232 endplat.get_parent().add_child.call_deferred(endplat2)
233 endplat.queue_free()
234
235 var entry2 = get_node("/root/scene/Components/Doors/entry_2")
236 var entry22 = entry2.duplicate()
237 entry22.name = "spe_entry_2"
238 entry2.get_parent().add_child.call_deferred(entry22)
239 entry2.queue_free()
240
241 # Add the strict cyan ending validation.
242 if global.map == "the_parthenon" and ap.strict_cyan_ending:
243 var panel_prefab = preload("res://objects/nodes/panel.tscn")
244 var tpl_prefab = preload("res://objects/nodes/listeners/teleportListener.tscn")
245 var reverse_prefab = preload("res://objects/nodes/listeners/reversingListener.tscn")
246
247 var previous_panel = null
248 var next_y = -100
249 var words = ["quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog"]
250 for word in words:
251 var panel = panel_prefab.instantiate()
252 panel.position = Vector3(0, next_y, 0)
253 next_y -= 10
254 panel.clue = word
255 panel.symbol = "."
256 panel.answer = "%s%s" % [word, word]
257 panel.name = "EndCheck_%s" % word
258
259 var tpl = tpl_prefab.instantiate()
260 tpl.teleport_point = Vector3(0, 1, -11)
261 tpl.teleport_rotate = Vector3(-45, 0, 0)
262 tpl.target_path = panel
263 tpl.name = "Teleport"
264
265 if previous_panel == null:
266 tpl.senderGroup.append(NodePath("/root/scene/Panels/Rulers"))
267 else:
268 tpl.senders.append(NodePath("../../%s" % previous_panel.name))
269
270 var reversing = reverse_prefab.instantiate()
271 reversing.senders.append(NodePath(".."))
272 reversing.name = "Reversing"
273 tpl.senders.append(NodePath("../Reversing"))
274
275 panel.add_child.call_deferred(tpl)
276 panel.add_child.call_deferred(reversing)
277 get_parent().get_node("Panels").add_child.call_deferred(panel)
278
279 previous_panel = panel
280
281 # Duplicate the door that usually waits on the rulers. We can't set the
282 # senders here for some reason so we actually set them in the door ready
283 # function.
284 var entry1 = get_node("/root/scene/Components/Doors/entry_1")
285 var entry12 = entry1.duplicate()
286 entry12.name = "spe_entry_1"
287 entry1.get_parent().add_child.call_deferred(entry12)
288 entry1.queue_free()
289
290 # Move the Plaza RTE trigger outside of the turtle.
291 if global.map == "the_plaza":
292 var rte_trigger = get_node("/root/scene/Components/Warps/triggerArea")
293 rte_trigger.position.z = 0
294
295 # Add the mastery to Icarus.
296 if global.map == "icarus" and ap.enable_icarus:
297 var collectable_prefab = preload("res://objects/nodes/collectable.tscn")
298 var saver_prefab = preload("res://objects/nodes/saver.tscn")
299 var tpl_prefab = preload("res://objects/nodes/listeners/teleportListener.tscn")
300
301 var mastery = collectable_prefab.instantiate()
302 mastery.name = "collectable"
303 mastery.position = Vector3(0, -2000, 0)
304 mastery.unlock_type = "smiley"
305 mastery.material_override = load("res://assets/materials/gold.material")
306 get_node("/root/scene/Components/Collectables").add_child.call_deferred(mastery)
307
308 var tpl = tpl_prefab.instantiate()
309 tpl.teleport_point = Vector3(56.25, 0, -5.5)
310 tpl.teleport_rotate = Vector3(0, 0, 0)
311 tpl.target_path = mastery
312 tpl.name = "Teleport"
313 tpl.senderGroup.append(NodePath("/root/scene/Panels"))
314 tpl.nested = true
315 mastery.add_child.call_deferred(tpl)
316
317 var saver = saver_prefab.instantiate()
318 saver.name = "saver_collectables"
319 saver.type = "collectables"
320 saver.senderGroup.append(NodePath("/root/scene/Components/Collectables"))
321 get_node("/root/scene").add_child.call_deferred(saver)
322
323 # Add the mastery to The Advanced.
324 if global.map == "the_advanced":
325 var collectable_prefab = preload("res://objects/nodes/collectable.tscn")
326 var saver_prefab = preload("res://objects/nodes/saver.tscn")
327 var tpl_prefab = preload("res://objects/nodes/listeners/teleportListener.tscn")
328
329 var mastery = collectable_prefab.instantiate()
330 mastery.name = "collectable"
331 mastery.position = Vector3(0, -200, -5)
332 mastery.unlock_type = "smiley"
333 mastery.material_override = load("res://assets/materials/gold.material")
334 get_node("/root/scene/Components/Collectables").add_child.call_deferred(mastery)
335
336 var tpl = tpl_prefab.instantiate()
337 tpl.teleport_point = Vector3(0, 2, -5)
338 tpl.teleport_rotate = Vector3(0, 0, 0)
339 tpl.target_path = mastery
340 tpl.name = "Teleport"
341 tpl.senders.append(NodePath("/root/scene/Panels/Room_1/panel_29"))
342 tpl.senders.append(NodePath("/root/scene/Panels/Room_1/panel_30"))
343 tpl.senders.append(NodePath("/root/scene/Panels/Room_1/panel_31"))
344 mastery.add_child.call_deferred(tpl)
345
346 var saver = saver_prefab.instantiate()
347 saver.name = "saver_collectables"
348 saver.type = "collectables"
349 saver.senderGroup.append(NodePath("/root/scene/Components/Collectables"))
350 get_node("/root/scene").add_child.call_deferred(saver)
351
352 # Add the mastery to The Charismatic.
353 if global.map == "the_charismatic":
354 var collectable_prefab = preload("res://objects/nodes/collectable.tscn")
355 var saver_prefab = preload("res://objects/nodes/saver.tscn")
356
357 var mastery = collectable_prefab.instantiate()
358 mastery.name = "collectable"
359 mastery.position = Vector3(-17, 2, -29)
360 mastery.rotation_degrees = Vector3(0, 45, 0)
361 mastery.unlock_type = "smiley"
362 mastery.material_override = load("res://assets/materials/gold.material")
363 get_node("/root/scene/Components/Collectables").add_child.call_deferred(mastery)
364
365 var saver = saver_prefab.instantiate()
366 saver.name = "saver_collectables"
367 saver.type = "collectables"
368 saver.senderGroup.append(NodePath("/root/scene/Components/Collectables"))
369 get_node("/root/scene").add_child.call_deferred(saver)
370
371 # Add the mastery to The Crystalline.
372 if global.map == "the_crystalline":
373 var collectable_prefab = preload("res://objects/nodes/collectable.tscn")
374 var saver_prefab = preload("res://objects/nodes/saver.tscn")
375 var tpl_prefab = preload("res://objects/nodes/listeners/teleportListener.tscn")
376
377 var mastery = collectable_prefab.instantiate()
378 mastery.name = "collectable"
379 mastery.position = Vector3(0, 13, 37)
380 mastery.unlock_type = "smiley"
381 mastery.material_override = load("res://assets/materials/gold.material")
382 get_node("/root/scene/Components/Collectables").add_child.call_deferred(mastery)
383
384 var tpl = tpl_prefab.instantiate()
385 tpl.teleport_point = Vector3(0, 11.5, -20)
386 tpl.teleport_rotate = Vector3(0, 0, 180)
387 tpl.target_path = mastery
388 tpl.name = "Teleport"
389 tpl.senders.append(NodePath("/root/scene/Panels/Room_1/panel_3"))
390 mastery.add_child.call_deferred(tpl)
391
392 var saver = saver_prefab.instantiate()
393 saver.name = "saver_collectables"
394 saver.type = "collectables"
395 saver.senderGroup.append(NodePath("/root/scene/Components/Collectables"))
396 get_node("/root/scene").add_child.call_deferred(saver)
397
398 # Add the mastery to The Stellar.
399 if global.map == "the_stellar":
400 var collectable_prefab = preload("res://objects/nodes/collectable.tscn")
401 var saver_prefab = preload("res://objects/nodes/saver.tscn")
402
403 var collectables = Node.new()
404 collectables.name = "Collectables"
405
406 var mastery = collectable_prefab.instantiate()
407 mastery.name = "collectable"
408 mastery.position = Vector3(2, 2, -31)
409 mastery.rotation_degrees = Vector3(0, 90, 0)
410 mastery.unlock_type = "smiley"
411 mastery.material_override = load("res://assets/materials/gold.material")
412 collectables.add_child.call_deferred(mastery)
413 get_node("/root/scene/Components").add_child.call_deferred(collectables)
414
415 var saver = saver_prefab.instantiate()
416 saver.name = "saver_collectables"
417 saver.type = "collectables"
418 saver.senderGroup.append(NodePath("/root/scene/Components/Collectables"))
419 get_node("/root/scene").add_child.call_deferred(saver)
420 26
421 ap.update_job_well_done_sign() 27 ap.update_job_well_done_sign()
422 28
@@ -430,9 +36,12 @@ func _ready():
430 continue 36 continue
431 37
432 if ( 38 if (
433 door.get_type() == gamedata.SCRIPT_proto.DoorType.ITEM_ONLY 39 not (door.has_legacy_location() and door.get_legacy_location())
434 or door.get_type() == gamedata.SCRIPT_proto.DoorType.GALLERY_PAINTING 40 and (
435 or door.get_type() == gamedata.SCRIPT_proto.DoorType.CONTROL_CENTER_COLOR 41 door.get_type() == gamedata.SCRIPT_proto.DoorType.ITEM_ONLY
42 or door.get_type() == gamedata.SCRIPT_proto.DoorType.GALLERY_PAINTING
43 or door.get_type() == gamedata.SCRIPT_proto.DoorType.CONTROL_CENTER_COLOR
44 )
436 ): 45 ):
437 continue 46 continue
438 47
@@ -568,22 +177,5 @@ func _ready():
568 ap.stop_batching_locations() 177 ap.stop_batching_locations()
569 178
570 179
571func _set_up_invis_wall(x, y, z, sx, sy, sz):
572 var prefab = preload("res://objects/nodes/block.tscn")
573 var newwall = prefab.instantiate()
574 newwall.position.x = x
575 newwall.position.y = y
576 newwall.position.z = z
577 newwall.scale.x = sz
578 newwall.scale.y = sy
579 newwall.scale.z = sx
580 newwall.set_surface_override_material(0, preload("res://assets/materials/blackMatte.material"))
581 newwall.visibility_range_end = 3
582 newwall.visibility_range_end_margin = 1
583 newwall.visibility_range_fade_mode = RenderingServer.VISIBILITY_RANGE_FADE_SELF
584 newwall.skeleton = ".."
585 get_parent().add_child.call_deferred(newwall)
586
587
588func _process(_dt): 180func _process(_dt):
589 compass.update_rotation(global_rotation.y) 181 compass.update_rotation(global_rotation.y)
diff --git a/apworld/client/source_runtime.gd b/apworld/client/source_runtime.gd index 35428ea..146587a 100644 --- a/apworld/client/source_runtime.gd +++ b/apworld/client/source_runtime.gd
@@ -7,6 +7,10 @@ func _init(path):
7 source_path = path 7 source_path = path
8 8
9 9
10func path_exists(path):
11 return FileAccess.file_exists("%s/%s" % [source_path, path])
12
13
10func load_script(path): 14func load_script(path):
11 return ResourceLoader.load("%s/%s" % [source_path, path]) 15 return ResourceLoader.load("%s/%s" % [source_path, path])
12 16
diff --git a/apworld/client/textclient.gd b/apworld/client/textclient.gd index f785a03..ce28a3a 100644 --- a/apworld/client/textclient.gd +++ b/apworld/client/textclient.gd
@@ -16,6 +16,8 @@ var tracker_loc_tree_item_by_id = {}
16var tracker_port_tree_item_by_id = {} 16var tracker_port_tree_item_by_id = {}
17var tracker_goal_tree_item = null 17var tracker_goal_tree_item = null
18var tracker_object_by_index = {} 18var tracker_object_by_index = {}
19var tracker_object_by_ignored_index = {}
20var tracker_ignored_group = null
19 21
20var worldports_tab 22var worldports_tab
21var worldports_tree 23var worldports_tree
@@ -99,7 +101,7 @@ func _ready():
99 tabs.add_child(tracker_margins) 101 tabs.add_child(tracker_margins)
100 102
101 tracker_tree = Tree.new() 103 tracker_tree = Tree.new()
102 tracker_tree.columns = 3 104 tracker_tree.columns = 4
103 tracker_tree.hide_root = true 105 tracker_tree.hide_root = true
104 tracker_tree.add_theme_font_size_override("font_size", 24) 106 tracker_tree.add_theme_font_size_override("font_size", 24)
105 tracker_tree.add_theme_color_override("font_color", Color(0.8, 0.8, 0.8, 1)) 107 tracker_tree.add_theme_color_override("font_color", Color(0.8, 0.8, 0.8, 1))
@@ -108,7 +110,9 @@ func _ready():
108 tracker_tree.set_column_expand(0, false) 110 tracker_tree.set_column_expand(0, false)
109 tracker_tree.set_column_expand(1, true) 111 tracker_tree.set_column_expand(1, true)
110 tracker_tree.set_column_expand(2, false) 112 tracker_tree.set_column_expand(2, false)
113 tracker_tree.set_column_expand(3, false)
111 tracker_tree.set_column_custom_minimum_width(2, 200) 114 tracker_tree.set_column_custom_minimum_width(2, 200)
115 tracker_tree.set_column_custom_minimum_width(3, 200)
112 tracker_margins.add_child(tracker_tree) 116 tracker_margins.add_child(tracker_tree)
113 117
114 worldports_tab = MarginContainer.new() 118 worldports_tab = MarginContainer.new()
@@ -208,6 +212,8 @@ func update_locations(reset_locations = true):
208 "name": location_name, 212 "name": location_name,
209 "type": kLocation, 213 "type": kLocation,
210 "id": location_id, 214 "id": location_id,
215 "ignored": ap._ignored_locations.has(location_id),
216 "hint": ap.client._hinted_locations.has(location_id),
211 } 217 }
212 ) 218 )
213 ) 219 )
@@ -222,11 +228,13 @@ func update_locations(reset_locations = true):
222 "name": port_name, 228 "name": port_name,
223 "type": kWorldport, 229 "type": kWorldport,
224 "id": port_id, 230 "id": port_id,
231 "ignored": false,
232 "hint": false,
225 } 233 }
226 ) 234 )
227 ) 235 )
228 236
229 locations.sort_custom(func(a, b): return a["name"] < b["name"]) 237 locations.sort_custom(_cmp_tracker_objects)
230 238
231 if ap.client._goal_accessible: 239 if ap.client._goal_accessible:
232 var location_name = gamedata.ending_display_name_by_name[ap.kEndingNameByVictoryValue[ 240 var location_name = gamedata.ending_display_name_by_name[ap.kEndingNameByVictoryValue[
@@ -238,14 +246,18 @@ func update_locations(reset_locations = true):
238 { 246 {
239 "name": location_name, 247 "name": location_name,
240 "type": kGoal, 248 "type": kGoal,
249 "ignored": false,
250 "hint": false,
241 } 251 }
242 ) 252 )
243 ) 253 )
244 254
245 var count = 0 255 var count = 0
246 for location in locations: 256 for location in locations:
247 if count < 18: 257 if count < 18 and not location["ignored"]:
248 locations_overlay.push_paragraph(HORIZONTAL_ALIGNMENT_RIGHT) 258 locations_overlay.push_paragraph(HORIZONTAL_ALIGNMENT_RIGHT)
259 if location["hint"]:
260 locations_overlay.push_color(Color("#fafad2"))
249 locations_overlay.append_text(location["name"]) 261 locations_overlay.append_text(location["name"])
250 locations_overlay.append_text(" ") 262 locations_overlay.append_text(" ")
251 if location["type"] == kLocation: 263 if location["type"] == kLocation:
@@ -254,6 +266,8 @@ func update_locations(reset_locations = true):
254 locations_overlay.add_image(worldport_texture) 266 locations_overlay.add_image(worldport_texture)
255 elif location["type"] == kGoal: 267 elif location["type"] == kGoal:
256 locations_overlay.add_image(goal_texture) 268 locations_overlay.add_image(goal_texture)
269 if location["hint"]:
270 locations_overlay.pop()
257 locations_overlay.pop() 271 locations_overlay.pop()
258 count += 1 272 count += 1
259 273
@@ -266,17 +280,43 @@ func update_locations(reset_locations = true):
266 var root_ti = tracker_tree.create_item(null) 280 var root_ti = tracker_tree.create_item(null)
267 281
268 for location in locations: 282 for location in locations:
269 var loc_row = root_ti.create_child() 283 var loc_row
284
285 if location["ignored"]:
286 if tracker_ignored_group == null:
287 tracker_ignored_group = root_ti.create_child()
288 tracker_ignored_group.set_text(1, "Ignored Locations")
289 tracker_ignored_group.set_selectable(0, false)
290 tracker_ignored_group.set_selectable(1, false)
291 tracker_ignored_group.set_selectable(2, false)
292 tracker_ignored_group.set_selectable(3, false)
293
294 loc_row = tracker_ignored_group.create_child()
295 else:
296 loc_row = root_ti.create_child()
297
270 loc_row.set_cell_mode(0, TreeItem.CELL_MODE_ICON) 298 loc_row.set_cell_mode(0, TreeItem.CELL_MODE_ICON)
271 loc_row.set_selectable(0, false) 299 loc_row.set_selectable(0, false)
272 loc_row.set_text(1, location["name"]) 300 loc_row.set_text(1, location["name"])
273 loc_row.set_selectable(1, false) 301 loc_row.set_selectable(1, false)
302 if location["hint"]:
303 loc_row.set_custom_color(1, Color("#fafad2"))
274 loc_row.set_cell_mode(2, TreeItem.CELL_MODE_CUSTOM) 304 loc_row.set_cell_mode(2, TreeItem.CELL_MODE_CUSTOM)
275 loc_row.set_text(2, "Show Path") 305 loc_row.set_text(2, "Show Path")
276 loc_row.set_custom_as_button(2, true) 306 loc_row.set_custom_as_button(2, true)
277 loc_row.set_editable(2, true) 307 loc_row.set_editable(2, true)
278 loc_row.set_selectable(2, false) 308 loc_row.set_selectable(2, false)
279 loc_row.set_text_alignment(2, HORIZONTAL_ALIGNMENT_CENTER) 309 loc_row.set_text_alignment(2, HORIZONTAL_ALIGNMENT_CENTER)
310 loc_row.set_selectable(3, false)
311 if location["type"] == kLocation:
312 loc_row.set_cell_mode(3, TreeItem.CELL_MODE_CUSTOM)
313 if location["ignored"]:
314 loc_row.set_text(3, "Unignore")
315 else:
316 loc_row.set_text(3, "Ignore")
317 loc_row.set_custom_as_button(3, true)
318 loc_row.set_editable(3, true)
319 loc_row.set_text_alignment(3, HORIZONTAL_ALIGNMENT_CENTER)
280 320
281 if location["type"] == kLocation: 321 if location["type"] == kLocation:
282 loc_row.set_icon(0, location_texture) 322 loc_row.set_icon(0, location_texture)
@@ -288,7 +328,10 @@ func update_locations(reset_locations = true):
288 loc_row.set_icon(0, goal_texture) 328 loc_row.set_icon(0, goal_texture)
289 tracker_goal_tree_item = loc_row 329 tracker_goal_tree_item = loc_row
290 330
291 tracker_object_by_index[loc_row.get_index()] = location 331 if location["ignored"]:
332 tracker_object_by_ignored_index[loc_row.get_index()] = location
333 else:
334 tracker_object_by_index[loc_row.get_index()] = location
292 else: 335 else:
293 for loc_row in tracker_tree.get_root().get_children(): 336 for loc_row in tracker_tree.get_root().get_children():
294 loc_row.visible = false 337 loc_row.visible = false
@@ -310,6 +353,18 @@ func update_locations(reset_locations = true):
310 if tracker_goal_tree_item != null and ap.client._goal_accessible: 353 if tracker_goal_tree_item != null and ap.client._goal_accessible:
311 tracker_goal_tree_item.visible = true 354 tracker_goal_tree_item.visible = true
312 355
356 if tracker_ignored_group != null:
357 tracker_ignored_group.visible = true
358
359
360func _cmp_tracker_objects(a, b) -> bool:
361 if a["ignored"] != b["ignored"]:
362 return !a["ignored"]
363 elif a["hint"] != b["hint"]:
364 return a["hint"]
365 else:
366 return a["name"] < b["name"]
367
313 368
314func update_locations_visibility(): 369func update_locations_visibility():
315 var ap = global.get_node("Archipelago") 370 var ap = global.get_node("Archipelago")
@@ -317,20 +372,33 @@ func update_locations_visibility():
317 372
318 373
319func _on_tracker_button_clicked(): 374func _on_tracker_button_clicked():
375 var ap = global.get_node("Archipelago")
376
320 var edited_item = tracker_tree.get_edited() 377 var edited_item = tracker_tree.get_edited()
321 var edited_index = edited_item.get_index() 378 var edited_index = edited_item.get_index()
322 379
323 if tracker_object_by_index.has(edited_index): 380 if edited_item.get_parent() == tracker_tree.get_root():
324 var tracker_object = tracker_object_by_index[edited_index] 381 if tracker_object_by_index.has(edited_index):
325 var ap = global.get_node("Archipelago") 382 var tracker_object = tracker_object_by_index[edited_index]
326 var type_str = "" 383 if tracker_tree.get_edited_column() == 2:
327 if tracker_object["type"] == kLocation: 384 var type_str = ""
328 type_str = "location" 385 if tracker_object["type"] == kLocation:
329 elif tracker_object["type"] == kWorldport: 386 type_str = "location"
330 type_str = "worldport" 387 elif tracker_object["type"] == kWorldport:
331 elif tracker_object["type"] == kGoal: 388 type_str = "worldport"
332 type_str = "goal" 389 elif tracker_object["type"] == kGoal:
333 ap.client.getLogicalPath(type_str, tracker_object.get("id", null)) 390 type_str = "goal"
391 ap.client.getLogicalPath(type_str, tracker_object.get("id", null))
392 elif tracker_tree.get_edited_column() == 3:
393 ap.toggle_ignored_location(tracker_object["id"])
394 elif edited_item.get_parent() == tracker_ignored_group:
395 # This is the ignored locations group.
396 if (
397 tracker_object_by_ignored_index.has(edited_index)
398 and tracker_tree.get_edited_column() == 3
399 ):
400 var tracker_object = tracker_object_by_ignored_index[edited_index]
401 ap.toggle_ignored_location(tracker_object["id"])
334 402
335 403
336func display_logical_path(object_type, object_id, paths): 404func display_logical_path(object_type, object_id, paths):
@@ -435,4 +503,6 @@ func reset_tracker_tab():
435 tracker_port_tree_item_by_id.clear() 503 tracker_port_tree_item_by_id.clear()
436 tracker_goal_tree_item = null 504 tracker_goal_tree_item = null
437 tracker_object_by_index.clear() 505 tracker_object_by_index.clear()
506 tracker_object_by_ignored_index.clear()
507 tracker_ignored_group = null
438 tracker_tree.clear() 508 tracker_tree.clear()
diff --git a/apworld/client/unlockReaderListener.gd b/apworld/client/unlockReaderListener.gd new file mode 100644 index 0000000..a5754b9 --- /dev/null +++ b/apworld/client/unlockReaderListener.gd
@@ -0,0 +1,46 @@
1extends "res://scripts/nodes/listeners/unlockReaderListener.gd"
2
3var item_id = null
4var item_amount
5
6
7func _ready():
8 var node_path = String(
9 get_tree().get_root().get_node("scene").get_path_to(self).get_concatenated_names()
10 )
11
12 var gamedata = global.get_node("Gamedata")
13 var door_id = gamedata.get_door_for_map_node_path(global.map, node_path)
14 if door_id != null:
15 var ap = global.get_node("Archipelago")
16 var item_lock = ap.get_item_id_for_door(door_id)
17
18 if item_lock != null:
19 item_id = item_lock[0]
20 item_amount = item_lock[1]
21
22 self.senders = []
23 self.senderGroup = []
24 self.nested = false
25 self.complete_at = 0
26 self.max_length = 0
27 self.excludeSenders = []
28
29 super._ready()
30
31
32func _readier():
33 if item_id != null:
34 var ap = global.get_node("Archipelago")
35
36 if ap.client.getItemAmount(item_id) >= item_amount:
37 handleTriggered()
38 else:
39 super._readier()
40
41
42func handleTriggered():
43 if item_id != null:
44 emit_signal("trigger")
45 else:
46 super.handleTriggered()