about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorStar Rauchenberger <fefferburbia@gmail.com>2025-11-04 14:56:04 -0500
committerStar Rauchenberger <fefferburbia@gmail.com>2025-11-04 14:56:04 -0500
commit452289b3b6247bb512b9353e0f2c6a9b7090be55 (patch)
tree499bb3c365cb91cb161b8b0e9bf51c6d5c0d72f8
parent24a59794f408c6aa878a8477a920a1d7b7d9c4c5 (diff)
downloadlingo2-archipelago-452289b3b6247bb512b9353e0f2c6a9b7090be55.tar.gz
lingo2-archipelago-452289b3b6247bb512b9353e0f2c6a9b7090be55.tar.bz2
lingo2-archipelago-452289b3b6247bb512b9353e0f2c6a9b7090be55.zip
Split map-specific initialization into separate files
-rw-r--r--apworld/client/apworld_runtime.gd5
-rw-r--r--apworld/client/manager.gd14
-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_unyielding.gd5
-rw-r--r--apworld/client/player.gd636
-rw-r--r--apworld/client/source_runtime.gd4
17 files changed, 658 insertions, 632 deletions
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/manager.gd b/apworld/client/manager.gd index 830ebb8..8c981f9 100644 --- a/apworld/client/manager.gd +++ b/apworld/client/manager.gd
@@ -30,6 +30,7 @@ var _held_letters = {}
30var _letters_setup = false 30var _letters_setup = false
31var _already_connected = false 31var _already_connected = false
32var _ignored_locations = [] 32var _ignored_locations = []
33var _map_scripts = {}
33 34
34const kSHUFFLE_LETTERS_VANILLA = 0 35const kSHUFFLE_LETTERS_VANILLA = 0
35const kSHUFFLE_LETTERS_UNLOCKED = 1 36const kSHUFFLE_LETTERS_UNLOCKED = 1
@@ -701,3 +702,16 @@ func toggle_ignored_location(loc_id):
701 client.removeIgnoredLocation(loc_id) 702 client.removeIgnoredLocation(loc_id)
702 else: 703 else:
703 client.addIgnoredLocation(loc_id) 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_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 65bf54e..5fac9fd 100644 --- a/apworld/client/player.gd +++ b/apworld/client/player.gd
@@ -19,612 +19,10 @@ func _ready():
19 19
20 ap.start_batching_locations() 20 ap.start_batching_locations()
21 21
22 if global.map == "control_center": 22 # Run map-specific initialization.
23 get_node("/root/scene/Components/Doors/entry_18").queue_free() 23 var map_script = ap.get_map_script(global.map)
24 24 if map_script != null:
25 _set_up_mastery_listener("advanced") 25 map_script.on_map_load(get_tree().get_root())
26 _set_up_mastery_listener("charismatic")
27 _set_up_mastery_listener("crystalline")
28 _set_up_mastery_listener("fuzzy")
29 _set_up_mastery_listener("icarus")
30 _set_up_mastery_listener("stellar")
31
32 if ap.endings_requirement != 12 or ap.masteries_requirement != 0:
33 # Set up listeners for the potential White Ending requirements.
34 var merging_prefab = preload("res://objects/nodes/listeners/mergingListener.tscn")
35
36 var old_door = get_node("/root/scene/Components/Doors/entry_19")
37 var new_door = old_door.duplicate()
38 new_door.name = "entry_19_new"
39 new_door.senders.clear()
40 new_door.senderGroup.clear()
41 new_door.excludeSenders.clear()
42
43 if ap.endings_requirement == 12:
44 new_door.senderGroup.append(NodePath("/root/scene/Meshes/Trophies/Listeners"))
45 elif ap.endings_requirement > 0:
46 if ap.masteries_requirement == 0:
47 new_door.senderGroup.append(NodePath("/root/scene/Meshes/Trophies/Listeners"))
48 new_door.complete_at = ap.endings_requirement
49 else:
50 var endings_merge = merging_prefab.instantiate()
51 endings_merge.name = "EndingsMerge"
52 endings_merge.senderGroup.append(
53 NodePath("/root/scene/Meshes/Trophies/Listeners")
54 )
55 endings_merge.complete_at = ap.endings_requirement
56 get_node("/root/scene/Components").add_child.call_deferred(endings_merge)
57 new_door.senders.append(NodePath("/root/scene/Components/EndingsMerge"))
58
59 var max_masteries = 13 + ap.enable_gift_maps.size()
60 if ap.enable_icarus:
61 max_masteries += 1
62
63 if ap.masteries_requirement == max_masteries:
64 new_door.senderGroup.append(
65 NodePath("/root/scene/Meshes/Trophies/MasteryListeners")
66 )
67 new_door.excludeSenders.append(
68 NodePath(
69 "/root/scene/Meshes/Trophies/MasteryListeners/unlockReaderListenerWhite"
70 )
71 )
72 elif ap.masteries_requirement > 0:
73 if ap.endings_requirement == 0:
74 new_door.senderGroup.append(
75 NodePath("/root/scene/Meshes/Trophies/MasteryListeners")
76 )
77 new_door.excludeSenders.append(
78 NodePath(
79 "/root/scene/Meshes/Trophies/MasteryListeners/unlockReaderListenerWhite"
80 )
81 )
82 new_door.complete_at = ap.masteries_requirement
83 else:
84 var masteries_merge = merging_prefab.instantiate()
85 masteries_merge.name = "MasteriesMerge"
86 masteries_merge.senderGroup.append(
87 NodePath("/root/scene/Meshes/Trophies/MasteryListeners")
88 )
89 masteries_merge.excludeSenders.append(
90 NodePath(
91 "/root/scene/Meshes/Trophies/MasteryListeners/unlockReaderListenerWhite"
92 )
93 )
94 masteries_merge.complete_at = ap.masteries_requirement
95 get_node("/root/scene/Components").add_child.call_deferred(masteries_merge)
96 new_door.senders.append(NodePath("/root/scene/Components/MasteriesMerge"))
97
98 old_door.queue_free()
99 get_node("/root/scene/Components/Doors").add_child.call_deferred(new_door)
100
101 if global.map == "daedalus":
102 # Teleport the direction panels when the stairs are there.
103 var tpl_prefab = preload("res://objects/nodes/listeners/teleportListener.tscn")
104
105 var dir1 = get_node("/root/scene/Panels/Castle Entrance/castle_direction_1")
106 var dir1_tpl = tpl_prefab.instantiate()
107 dir1_tpl.target_path = dir1
108 dir1_tpl.teleport_point = Vector3(59.5, 8, -6.5)
109 dir1_tpl.teleport_rotate = Vector3(-45, 0, 0)
110 dir1_tpl.senders.append(NodePath("/root/scene/Panels/Castle Entrance/castle_south"))
111 dir1_tpl.senders.append(NodePath("/root/scene/Panels/Castle Entrance/castle_north"))
112 dir1_tpl.senders.append(NodePath("/root/scene/Panels/Castle Entrance/castle_west"))
113 dir1.add_child.call_deferred(dir1_tpl)
114
115 var dir2 = get_node("/root/scene/Panels/Castle Entrance/castle_direction_2")
116 var dir2_tpl = tpl_prefab.instantiate()
117 dir2_tpl.target_path = dir2
118 dir2_tpl.teleport_point = Vector3(59.5, 8, 6.5)
119 dir2_tpl.teleport_rotate = Vector3(-45, -180, 0)
120 dir2_tpl.senders.append(NodePath("/root/scene/Panels/Castle Entrance/castle_south"))
121 dir2_tpl.senders.append(NodePath("/root/scene/Panels/Castle Entrance/castle_north"))
122 dir2_tpl.senders.append(NodePath("/root/scene/Panels/Castle Entrance/castle_west"))
123 dir2.add_child.call_deferred(dir2_tpl)
124
125 var dir3 = get_node("/root/scene/Panels/Castle Entrance/castle_direction_3")
126 var dir3_tpl = tpl_prefab.instantiate()
127 dir3_tpl.target_path = dir3
128 dir3_tpl.teleport_point = Vector3(54, 8, 0)
129 dir3_tpl.teleport_rotate = Vector3(-45, 90, 0)
130 dir3_tpl.senders.append(NodePath("/root/scene/Panels/Castle Entrance/castle_south"))
131 dir3_tpl.senders.append(NodePath("/root/scene/Panels/Castle Entrance/castle_north"))
132 dir3_tpl.senders.append(NodePath("/root/scene/Panels/Castle Entrance/castle_west"))
133 dir3.add_child.call_deferred(dir3_tpl)
134
135 # Block off roof access in Daedalus.
136 if not ap.daedalus_roof_access:
137 _set_up_invis_wall(75.5, 11, -24.5, 1, 10, 49)
138 _set_up_invis_wall(51.5, 11, -17, 16, 10, 1)
139 _set_up_invis_wall(46, 10, -9.5, 1, 10, 10)
140 _set_up_invis_wall(67.5, 11, 17, 16, 10, 1)
141 _set_up_invis_wall(50.5, 11, 14, 10, 10, 1)
142 _set_up_invis_wall(39, 10, 18.5, 1, 10, 22)
143 _set_up_invis_wall(20, 15, 18.5, 1, 10, 16)
144 _set_up_invis_wall(11.5, 15, 3, 32, 10, 1)
145 _set_up_invis_wall(11.5, 16, -20, 14, 20, 1)
146 _set_up_invis_wall(14, 16, -26.5, 1, 20, 4)
147 _set_up_invis_wall(28.5, 20.5, -26.5, 1, 15, 25)
148 _set_up_invis_wall(40.5, 20.5, -11, 30, 15, 1)
149 _set_up_invis_wall(50.5, 15, 5.5, 7, 10, 1)
150 _set_up_invis_wall(83.5, 33.5, 5.5, 1, 7, 11)
151 _set_up_invis_wall(83.5, 33.5, -5.5, 1, 7, 11)
152
153 var warp_exit_prefab = preload("res://objects/nodes/exit.tscn")
154 var warp_exit = warp_exit_prefab.instantiate()
155 warp_exit.name = "roof_access_blocker_warp_exit"
156 warp_exit.position = Vector3(58, 10, 0)
157 warp_exit.rotation_degrees.y = 90
158 get_parent().add_child.call_deferred(warp_exit)
159
160 var warp_enter_prefab = preload("res://objects/nodes/teleportAuto.tscn")
161 var warp_enter = warp_enter_prefab.instantiate()
162 warp_enter.target = warp_exit
163 warp_enter.position = Vector3(76.5, 30, 1)
164 warp_enter.scale = Vector3(4, 1.5, 1)
165 warp_enter.rotation_degrees.y = 90
166 get_parent().add_child.call_deferred(warp_enter)
167
168 if global.map == "the_entry":
169 # Remove door behind X1.
170 var door_node = get_tree().get_root().get_node("/root/scene/Components/Doors/exit_1")
171 door_node.handleTriggered()
172
173 # Display win condition.
174 var sign_prefab = preload("res://objects/nodes/sign.tscn")
175 var sign1 = sign_prefab.instantiate()
176 sign1.position = Vector3(-7, 5, -15.01)
177 sign1.text = "victory"
178 get_parent().add_child.call_deferred(sign1)
179
180 var sign2 = sign_prefab.instantiate()
181 sign2.position = Vector3(-7, 4, -15.01)
182 sign2.text = "%s ending" % ap.kEndingNameByVictoryValue.get(ap.victory_condition, "?")
183
184 var sign2_color = ap.kEndingNameByVictoryValue.get(ap.victory_condition, "coral").to_lower()
185 if sign2_color == "white":
186 sign2_color = "silver"
187
188 sign2.material = load("res://assets/materials/%s.material" % sign2_color)
189 get_parent().add_child.call_deferred(sign2)
190
191 # Add the gift map entry panel if needed.
192 if not ap.enable_gift_maps.is_empty():
193 var panel_prefab = preload("res://objects/nodes/panel.tscn")
194 var tpl_prefab = preload("res://objects/nodes/listeners/teleportListener.tscn")
195 var wpl_prefab = preload("res://objects/nodes/listeners/worldportListener.tscn")
196
197 var giftmap_parent = Node.new()
198 giftmap_parent.name = "GiftMapEntrance"
199 get_node("/root/scene/Components").add_child.call_deferred(giftmap_parent)
200
201 var symbolless_player = ""
202 for i in range(ap.client.ap_user.length()):
203 if "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".contains(
204 ap.client.ap_user[i]
205 ):
206 symbolless_player = symbolless_player + ap.client.ap_user[i].to_lower()
207
208 var giftmap_panel = panel_prefab.instantiate()
209 giftmap_panel.name = "Panel"
210 giftmap_panel.position = Vector3(33.5, -190, 5.5)
211 giftmap_panel.rotation_degrees = Vector3(-45, 0, 0)
212 giftmap_panel.clue = "player"
213 giftmap_panel.answer = symbolless_player
214
215 if ap.enable_gift_maps.has("The Advanced"):
216 var icely_panel = panel_prefab.instantiate()
217 icely_panel.name = "IcelyPanel"
218 icely_panel.answer = "icely"
219 icely_panel.position = Vector3(33.5, -200, 5.5)
220 giftmap_panel.proxies.append(NodePath("../IcelyPanel"))
221 giftmap_parent.add_child.call_deferred(icely_panel)
222
223 var icely_wpl = wpl_prefab.instantiate()
224 icely_wpl.name = "IcelyWpl"
225 icely_wpl.exit = "the_advanced"
226 icely_wpl.senders.append(NodePath("../IcelyPanel"))
227 giftmap_parent.add_child.call_deferred(icely_wpl)
228
229 if ap.enable_gift_maps.has("The Charismatic"):
230 var souvey_panel = panel_prefab.instantiate()
231 souvey_panel.name = "SouveyPanel"
232 souvey_panel.answer = "souvey"
233 souvey_panel.position = Vector3(33.5, -210, 5.5)
234 giftmap_panel.proxies.append(NodePath("../SouveyPanel"))
235 giftmap_parent.add_child.call_deferred(souvey_panel)
236
237 var souvey_wpl = wpl_prefab.instantiate()
238 souvey_wpl.name = "SouveyWpl"
239 souvey_wpl.exit = "the_charismatic"
240 souvey_wpl.senders.append(NodePath("../SouveyPanel"))
241 giftmap_parent.add_child.call_deferred(souvey_wpl)
242
243 if ap.enable_gift_maps.has("The Crystalline"):
244 var q_panel = panel_prefab.instantiate()
245 q_panel.name = "QPanel"
246 q_panel.answer = "q"
247 q_panel.position = Vector3(33.5, -220, 5.5)
248 giftmap_panel.proxies.append(NodePath("../QPanel"))
249 giftmap_parent.add_child.call_deferred(q_panel)
250
251 var q_wpl = wpl_prefab.instantiate()
252 q_wpl.name = "QWpl"
253 q_wpl.exit = "the_crystalline"
254 q_wpl.senders.append(NodePath("../QPanel"))
255 giftmap_parent.add_child.call_deferred(q_wpl)
256
257 if ap.enable_gift_maps.has("The Fuzzy"):
258 var gongus_panel = panel_prefab.instantiate()
259 gongus_panel.name = "GongusPanel"
260 gongus_panel.answer = "gongus"
261 gongus_panel.position = Vector3(33.5, -260, 5.5)
262 giftmap_panel.proxies.append(NodePath("../GongusPanel"))
263 giftmap_parent.add_child.call_deferred(gongus_panel)
264
265 var kiwi_panel = panel_prefab.instantiate()
266 kiwi_panel.name = "KiwiPanel"
267 kiwi_panel.answer = "kiwi"
268 kiwi_panel.position = Vector3(33.5, -270, 5.5)
269 giftmap_panel.proxies.append(NodePath("../KiwiPanel"))
270 giftmap_parent.add_child.call_deferred(kiwi_panel)
271
272 var fuzzy_wpl = wpl_prefab.instantiate()
273 fuzzy_wpl.name = "FuzzyWpl"
274 fuzzy_wpl.exit = "the_fuzzy"
275 fuzzy_wpl.senders.append(NodePath("../GongusPanel"))
276 fuzzy_wpl.senders.append(NodePath("../KiwiPanel"))
277 fuzzy_wpl.complete_at = 1
278 giftmap_parent.add_child.call_deferred(fuzzy_wpl)
279
280 if ap.enable_gift_maps.has("The Stellar"):
281 var hatkirby_panel = panel_prefab.instantiate()
282 hatkirby_panel.name = "HatkirbyPanel"
283 hatkirby_panel.answer = "hatkirby"
284 hatkirby_panel.position = Vector3(33.5, -230, 5.5)
285 giftmap_panel.proxies.append(NodePath("../HatkirbyPanel"))
286 giftmap_parent.add_child.call_deferred(hatkirby_panel)
287
288 var kirby_panel = panel_prefab.instantiate()
289 kirby_panel.name = "KirbyPanel"
290 kirby_panel.answer = "kirby"
291 kirby_panel.position = Vector3(33.5, -240, 5.5)
292 giftmap_panel.proxies.append(NodePath("../KirbyPanel"))
293 giftmap_parent.add_child.call_deferred(kirby_panel)
294
295 var star_panel = panel_prefab.instantiate()
296 star_panel.name = "StarPanel"
297 star_panel.answer = "star"
298 star_panel.position = Vector3(33.5, -250, 5.5)
299 giftmap_panel.proxies.append(NodePath("../StarPanel"))
300 giftmap_parent.add_child.call_deferred(star_panel)
301
302 var stellar_wpl = wpl_prefab.instantiate()
303 stellar_wpl.name = "StellarWpl"
304 stellar_wpl.exit = "the_stellar"
305 stellar_wpl.senders.append(NodePath("../HatkirbyPanel"))
306 stellar_wpl.senders.append(NodePath("../KirbyPanel"))
307 stellar_wpl.senders.append(NodePath("../StarPanel"))
308 stellar_wpl.complete_at = 1
309 giftmap_parent.add_child.call_deferred(stellar_wpl)
310
311 giftmap_parent.add_child.call_deferred(giftmap_panel)
312
313 var giftmap_tpl = tpl_prefab.instantiate()
314 giftmap_tpl.name = "PanelTeleporter"
315 giftmap_tpl.teleport_point = Vector3(33.5, 1, 5.5)
316 giftmap_tpl.teleport_rotate = Vector3(-45, 0, 0)
317 giftmap_tpl.target_path = giftmap_panel
318 giftmap_tpl.senders.append(
319 NodePath("/root/scene/Components/Listeners/unlockReaderListenerDoubles")
320 )
321 giftmap_parent.add_child.call_deferred(giftmap_tpl)
322
323 # Add the strict purple ending validation.
324 if global.map == "the_sun_temple" and ap.strict_purple_ending:
325 var panel_prefab = preload("res://objects/nodes/panel.tscn")
326 var tpl_prefab = preload("res://objects/nodes/listeners/teleportListener.tscn")
327 var reverse_prefab = preload("res://objects/nodes/listeners/reversingListener.tscn")
328
329 var previous_panel = null
330 var next_y = -100
331 var words = ["quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog"]
332 for word in words:
333 var panel = panel_prefab.instantiate()
334 panel.position = Vector3(0, next_y, 0)
335 next_y -= 10
336 panel.clue = word
337 panel.symbol = ""
338 panel.answer = word
339 panel.name = "EndCheck_%s" % word
340
341 var tpl = tpl_prefab.instantiate()
342 tpl.teleport_point = Vector3(0, 1, 0)
343 tpl.teleport_rotate = Vector3(-45, 180, 0)
344 tpl.target_path = panel
345 tpl.name = "Teleport"
346
347 if previous_panel == null:
348 tpl.senders.append(NodePath("/root/scene/Panels/End/panel_24"))
349 else:
350 tpl.senders.append(NodePath("../../%s" % previous_panel.name))
351
352 var reversing = reverse_prefab.instantiate()
353 reversing.senders.append(NodePath(".."))
354 reversing.name = "Reversing"
355 tpl.senders.append(NodePath("../Reversing"))
356
357 panel.add_child.call_deferred(tpl)
358 panel.add_child.call_deferred(reversing)
359 get_parent().get_node("Panels").add_child.call_deferred(panel)
360
361 previous_panel = panel
362
363 # Duplicate the doors that usually wait on EQUINOX. We can't set the senders
364 # here for some reason so we actually set them in the door ready function.
365 var endplat = get_node("/root/scene/Components/Doors/EndPlatform")
366 var endplat2 = endplat.duplicate()
367 endplat2.name = "spe_EndPlatform"
368 endplat.get_parent().add_child.call_deferred(endplat2)
369 endplat.queue_free()
370
371 var entry2 = get_node("/root/scene/Components/Doors/entry_2")
372 var entry22 = entry2.duplicate()
373 entry22.name = "spe_entry_2"
374 entry2.get_parent().add_child.call_deferred(entry22)
375 entry2.queue_free()
376
377 # Add the strict cyan ending validation.
378 if global.map == "the_parthenon" and ap.strict_cyan_ending:
379 var panel_prefab = preload("res://objects/nodes/panel.tscn")
380 var tpl_prefab = preload("res://objects/nodes/listeners/teleportListener.tscn")
381 var reverse_prefab = preload("res://objects/nodes/listeners/reversingListener.tscn")
382
383 var previous_panel = null
384 var next_y = -100
385 var words = ["quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog"]
386 for word in words:
387 var panel = panel_prefab.instantiate()
388 panel.position = Vector3(0, next_y, 0)
389 next_y -= 10
390 panel.clue = word
391 panel.symbol = "."
392 panel.answer = "%s%s" % [word, word]
393 panel.name = "EndCheck_%s" % word
394
395 var tpl = tpl_prefab.instantiate()
396 tpl.teleport_point = Vector3(0, 1, -11)
397 tpl.teleport_rotate = Vector3(-45, 0, 0)
398 tpl.target_path = panel
399 tpl.name = "Teleport"
400
401 if previous_panel == null:
402 tpl.senderGroup.append(NodePath("/root/scene/Panels/Rulers"))
403 else:
404 tpl.senders.append(NodePath("../../%s" % previous_panel.name))
405
406 var reversing = reverse_prefab.instantiate()
407 reversing.senders.append(NodePath(".."))
408 reversing.name = "Reversing"
409 tpl.senders.append(NodePath("../Reversing"))
410
411 panel.add_child.call_deferred(tpl)
412 panel.add_child.call_deferred(reversing)
413 get_parent().get_node("Panels").add_child.call_deferred(panel)
414
415 previous_panel = panel
416
417 # Duplicate the door that usually waits on the rulers. We can't set the
418 # senders here for some reason so we actually set them in the door ready
419 # function.
420 var entry1 = get_node("/root/scene/Components/Doors/entry_1")
421 var entry12 = entry1.duplicate()
422 entry12.name = "spe_entry_1"
423 entry1.get_parent().add_child.call_deferred(entry12)
424 entry1.queue_free()
425
426 # Move the Plaza RTE trigger outside of the turtle.
427 if global.map == "the_plaza":
428 var rte_trigger = get_node("/root/scene/Components/Warps/triggerArea")
429 rte_trigger.position.z = 0
430
431 # Add the mastery to Icarus.
432 if global.map == "icarus" and ap.enable_icarus:
433 var collectable_prefab = preload("res://objects/nodes/collectable.tscn")
434 var saver_prefab = preload("res://objects/nodes/saver.tscn")
435 var tpl_prefab = preload("res://objects/nodes/listeners/teleportListener.tscn")
436 var usl_prefab = preload("res://objects/nodes/listeners/unlockSetterListener.tscn")
437
438 var mastery = collectable_prefab.instantiate()
439 mastery.name = "collectable"
440 mastery.position = Vector3(0, -2000, 0)
441 mastery.unlock_type = "smiley"
442 mastery.material_override = load("res://assets/materials/gold.material")
443 get_node("/root/scene/Components/Collectables").add_child.call_deferred(mastery)
444
445 var tpl = tpl_prefab.instantiate()
446 tpl.teleport_point = Vector3(56.25, 0, -5.5)
447 tpl.teleport_rotate = Vector3(0, 0, 0)
448 tpl.target_path = mastery
449 tpl.name = "Teleport"
450 tpl.senderGroup.append(NodePath("/root/scene/Panels"))
451 tpl.nested = true
452 mastery.add_child.call_deferred(tpl)
453
454 var usl = usl_prefab.instantiate()
455 usl.name = "unlockSetterListenerMastery"
456 usl.key = "icarus_mastery"
457 usl.value = "unlocked"
458 usl.senders.append(NodePath("/root/scene/Components/Collectables/collectable"))
459 get_node("/root/scene/Components").add_child.call_deferred(usl)
460
461 var saver = saver_prefab.instantiate()
462 saver.name = "saver_collectables"
463 saver.type = "collectables"
464 saver.senderGroup.append(NodePath("/root/scene/Components/Collectables"))
465 get_node("/root/scene").add_child.call_deferred(saver)
466
467 # Add the mastery to The Advanced.
468 if global.map == "the_advanced":
469 var collectable_prefab = preload("res://objects/nodes/collectable.tscn")
470 var saver_prefab = preload("res://objects/nodes/saver.tscn")
471 var tpl_prefab = preload("res://objects/nodes/listeners/teleportListener.tscn")
472 var usl_prefab = preload("res://objects/nodes/listeners/unlockSetterListener.tscn")
473
474 var mastery = collectable_prefab.instantiate()
475 mastery.name = "collectable"
476 mastery.position = Vector3(0, -200, -5)
477 mastery.unlock_type = "smiley"
478 mastery.material_override = load("res://assets/materials/gold.material")
479 get_node("/root/scene/Components/Collectables").add_child.call_deferred(mastery)
480
481 var tpl = tpl_prefab.instantiate()
482 tpl.teleport_point = Vector3(0, 2, -5)
483 tpl.teleport_rotate = Vector3(0, 0, 0)
484 tpl.target_path = mastery
485 tpl.name = "Teleport"
486 tpl.senders.append(NodePath("/root/scene/Panels/Room_1/panel_29"))
487 tpl.senders.append(NodePath("/root/scene/Panels/Room_1/panel_30"))
488 tpl.senders.append(NodePath("/root/scene/Panels/Room_1/panel_31"))
489 mastery.add_child.call_deferred(tpl)
490
491 var usl = usl_prefab.instantiate()
492 usl.name = "unlockSetterListenerMastery"
493 usl.key = "advanced_mastery"
494 usl.value = "unlocked"
495 usl.senders.append(NodePath("/root/scene/Components/Collectables/collectable"))
496 get_node("/root/scene/Components").add_child.call_deferred(usl)
497
498 var saver = saver_prefab.instantiate()
499 saver.name = "saver_collectables"
500 saver.type = "collectables"
501 saver.senderGroup.append(NodePath("/root/scene/Components/Collectables"))
502 get_node("/root/scene").add_child.call_deferred(saver)
503
504 # Add the mastery to The Charismatic.
505 if global.map == "the_charismatic":
506 var collectable_prefab = preload("res://objects/nodes/collectable.tscn")
507 var saver_prefab = preload("res://objects/nodes/saver.tscn")
508 var usl_prefab = preload("res://objects/nodes/listeners/unlockSetterListener.tscn")
509
510 var mastery = collectable_prefab.instantiate()
511 mastery.name = "collectable"
512 mastery.position = Vector3(-17, 2, -29)
513 mastery.rotation_degrees = Vector3(0, 45, 0)
514 mastery.unlock_type = "smiley"
515 mastery.material_override = load("res://assets/materials/gold.material")
516 get_node("/root/scene/Components/Collectables").add_child.call_deferred(mastery)
517
518 var usl = usl_prefab.instantiate()
519 usl.name = "unlockSetterListenerMastery"
520 usl.key = "charismatic_mastery"
521 usl.value = "unlocked"
522 usl.senders.append(NodePath("/root/scene/Components/Collectables/collectable"))
523 get_node("/root/scene/Components").add_child.call_deferred(usl)
524
525 var saver = saver_prefab.instantiate()
526 saver.name = "saver_collectables"
527 saver.type = "collectables"
528 saver.senderGroup.append(NodePath("/root/scene/Components/Collectables"))
529 get_node("/root/scene").add_child.call_deferred(saver)
530
531 # Add the mastery to The Crystalline.
532 if global.map == "the_crystalline":
533 var collectable_prefab = preload("res://objects/nodes/collectable.tscn")
534 var saver_prefab = preload("res://objects/nodes/saver.tscn")
535 var tpl_prefab = preload("res://objects/nodes/listeners/teleportListener.tscn")
536 var usl_prefab = preload("res://objects/nodes/listeners/unlockSetterListener.tscn")
537
538 var mastery = collectable_prefab.instantiate()
539 mastery.name = "collectable"
540 mastery.position = Vector3(0, 13, 37)
541 mastery.unlock_type = "smiley"
542 mastery.material_override = load("res://assets/materials/gold.material")
543 get_node("/root/scene/Components/Collectables").add_child.call_deferred(mastery)
544
545 var tpl = tpl_prefab.instantiate()
546 tpl.teleport_point = Vector3(0, 11.5, -20)
547 tpl.teleport_rotate = Vector3(0, 0, 180)
548 tpl.target_path = mastery
549 tpl.name = "Teleport"
550 tpl.senders.append(NodePath("/root/scene/Panels/Room_1/panel_3"))
551 mastery.add_child.call_deferred(tpl)
552
553 var usl = usl_prefab.instantiate()
554 usl.name = "unlockSetterListenerMastery"
555 usl.key = "crystalline_mastery"
556 usl.value = "unlocked"
557 usl.senders.append(NodePath("/root/scene/Components/Collectables/collectable"))
558 get_node("/root/scene/Components").add_child.call_deferred(usl)
559
560 var saver = saver_prefab.instantiate()
561 saver.name = "saver_collectables"
562 saver.type = "collectables"
563 saver.senderGroup.append(NodePath("/root/scene/Components/Collectables"))
564 get_node("/root/scene").add_child.call_deferred(saver)
565
566 # Add the mastery to The Fuzzy.
567 if global.map == "the_fuzzy":
568 var collectable_prefab = preload("res://objects/nodes/collectable.tscn")
569 var saver_prefab = preload("res://objects/nodes/saver.tscn")
570 var usl_prefab = preload("res://objects/nodes/listeners/unlockSetterListener.tscn")
571
572 var mastery = collectable_prefab.instantiate()
573 mastery.name = "collectable"
574 mastery.position = Vector3(0, 2, -20)
575 mastery.unlock_type = "smiley"
576 mastery.material_override = load("res://assets/materials/gold.material")
577 get_node("/root/scene/Components/Collectables").add_child.call_deferred(mastery)
578
579 var usl = usl_prefab.instantiate()
580 usl.name = "unlockSetterListenerMastery"
581 usl.key = "fuzzy_mastery"
582 usl.value = "unlocked"
583 usl.senders.append(NodePath("/root/scene/Components/Collectables/collectable"))
584 get_node("/root/scene/Components").add_child.call_deferred(usl)
585
586 var saver = saver_prefab.instantiate()
587 saver.name = "saver_collectables"
588 saver.type = "collectables"
589 saver.senderGroup.append(NodePath("/root/scene/Components/Collectables"))
590 get_node("/root/scene").add_child.call_deferred(saver)
591
592 # Add the mastery to The Stellar.
593 if global.map == "the_stellar":
594 var collectable_prefab = preload("res://objects/nodes/collectable.tscn")
595 var saver_prefab = preload("res://objects/nodes/saver.tscn")
596 var usl_prefab = preload("res://objects/nodes/listeners/unlockSetterListener.tscn")
597
598 var collectables = Node.new()
599 collectables.name = "Collectables"
600
601 var mastery = collectable_prefab.instantiate()
602 mastery.name = "collectable"
603 mastery.position = Vector3(2, 2, -31)
604 mastery.rotation_degrees = Vector3(0, 90, 0)
605 mastery.unlock_type = "smiley"
606 mastery.material_override = load("res://assets/materials/gold.material")
607 collectables.add_child.call_deferred(mastery)
608 get_node("/root/scene/Components").add_child.call_deferred(collectables)
609
610 var usl = usl_prefab.instantiate()
611 usl.name = "unlockSetterListenerMastery"
612 usl.key = "stellar_mastery"
613 usl.value = "unlocked"
614 usl.senders.append(NodePath("/root/scene/Components/Collectables/collectable"))
615 get_node("/root/scene/Components").add_child.call_deferred(usl)
616
617 var saver = saver_prefab.instantiate()
618 saver.name = "saver_collectables"
619 saver.type = "collectables"
620 saver.senderGroup.append(NodePath("/root/scene/Components/Collectables"))
621 get_node("/root/scene").add_child.call_deferred(saver)
622
623 # Shrink the painting trigger in The Unyielding.
624 if global.map == "the_unyielding":
625 var trigger_area = get_node("/root/scene/Components/PaintingUnlocker/triggerArea")
626 trigger_area.position = Vector3(0, 0, -6)
627 trigger_area.scale = Vector3(6, 1, 6)
628 26
629 ap.update_job_well_done_sign() 27 ap.update_job_well_done_sign()
630 28
@@ -779,31 +177,5 @@ func _ready():
779 ap.stop_batching_locations() 177 ap.stop_batching_locations()
780 178
781 179
782func _set_up_invis_wall(x, y, z, sx, sy, sz):
783 var prefab = preload("res://objects/nodes/block.tscn")
784 var newwall = prefab.instantiate()
785 newwall.position.x = x
786 newwall.position.y = y
787 newwall.position.z = z
788 newwall.scale.x = sz
789 newwall.scale.y = sy
790 newwall.scale.z = sx
791 newwall.set_surface_override_material(0, preload("res://assets/materials/blackMatte.material"))
792 newwall.visibility_range_end = 3
793 newwall.visibility_range_end_margin = 1
794 newwall.visibility_range_fade_mode = RenderingServer.VISIBILITY_RANGE_FADE_SELF
795 newwall.skeleton = ".."
796 get_parent().add_child.call_deferred(newwall)
797
798
799func _set_up_mastery_listener(name):
800 var prefab = preload("res://objects/nodes/listeners/unlockReaderListener.tscn")
801 var url = prefab.instantiate()
802 url.name = "unlockReaderListenerMastery_%s" % name
803 url.key = "%s_mastery" % name
804 url.value = "unlocked"
805 get_node("/root/scene/Meshes/Trophies/MasteryListeners").add_child.call_deferred(url)
806
807
808func _process(_dt): 180func _process(_dt):
809 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