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/gamedata.gd8
-rw-r--r--apworld/client/manager.gd31
-rw-r--r--apworld/client/maps/control_center.gd55
-rw-r--r--apworld/client/player.gd40
-rw-r--r--apworld/client/rteMenu.gd55
5 files changed, 188 insertions, 1 deletions
diff --git a/apworld/client/gamedata.gd b/apworld/client/gamedata.gd index d7e3136..373f981 100644 --- a/apworld/client/gamedata.gd +++ b/apworld/client/gamedata.gd
@@ -16,6 +16,7 @@ var 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 = {} 18var port_id_by_ap_id = {}
19var map_id_by_rte_ap_id = {}
19 20
20var kSYMBOL_ITEMS 21var kSYMBOL_ITEMS
21 22
@@ -57,6 +58,9 @@ func load(data_bytes):
57 for map in objects.get_maps(): 58 for map in objects.get_maps():
58 map_id_by_name[map.get_name()] = map.get_id() 59 map_id_by_name[map.get_name()] = map.get_id()
59 60
61 if map.has_rte_ap_id():
62 map_id_by_rte_ap_id[map.get_rte_ap_id()] = map.get_id()
63
60 for door in objects.get_doors(): 64 for door in objects.get_doors():
61 var map = objects.get_maps()[door.get_map_id()] 65 var map = objects.get_maps()[door.get_map_id()]
62 66
@@ -300,3 +304,7 @@ func _get_keyholder_location_name(keyholder):
300 "%s - %s Keyholder" 304 "%s - %s Keyholder"
301 % [_get_room_object_location_prefix(keyholder), keyholder.get_key().to_upper()] 305 % [_get_room_object_location_prefix(keyholder), keyholder.get_key().to_upper()]
302 ) 306 )
307
308
309func vec3d_to_vector3(input) -> Vector3:
310 return Vector3(input.get_x(), input.get_y(), input.get_z())
diff --git a/apworld/client/manager.gd b/apworld/client/manager.gd index 1e0b549..f10a0b7 100644 --- a/apworld/client/manager.gd +++ b/apworld/client/manager.gd
@@ -46,6 +46,10 @@ const kCYAN_DOOR_BEHAVIOR_H2 = 0
46const kCYAN_DOOR_BEHAVIOR_DOUBLE_LETTER = 1 46const kCYAN_DOOR_BEHAVIOR_DOUBLE_LETTER = 1
47const kCYAN_DOOR_BEHAVIOR_ITEM = 2 47const kCYAN_DOOR_BEHAVIOR_ITEM = 2
48 48
49const kFAST_TRAVEL_ACCESS_VANILLA = 0
50const kFAST_TRAVEL_ACCESS_UNLOCKED = 1
51const kFAST_TRAVEL_ACCESS_ITEMS = 2
52
49const kEndingNameByVictoryValue = { 53const kEndingNameByVictoryValue = {
50 0: "GRAY", 54 0: "GRAY",
51 1: "PURPLE", 55 1: "PURPLE",
@@ -63,21 +67,26 @@ const kEndingNameByVictoryValue = {
63} 67}
64 68
65var apworld_version = [0, 0, 0] 69var apworld_version = [0, 0, 0]
70var custom_mint_ending = ""
66var cyan_door_behavior = kCYAN_DOOR_BEHAVIOR_H2 71var cyan_door_behavior = kCYAN_DOOR_BEHAVIOR_H2
67var daedalus_only = false 72var daedalus_only = false
68var daedalus_roof_access = false 73var daedalus_roof_access = false
69var enable_gift_maps = [] 74var enable_gift_maps = []
70var enable_icarus = false 75var enable_icarus = false
71var endings_requirement = 0 76var endings_requirement = 0
77var fast_travel_access = 0
72var keyholder_sanity = false 78var keyholder_sanity = false
73var masteries_requirement = 0 79var masteries_requirement = 0
80var music_mapping = {}
74var port_pairings = {} 81var port_pairings = {}
82var rte_mapping = []
75var shuffle_control_center_colors = false 83var shuffle_control_center_colors = false
76var shuffle_doors = false 84var shuffle_doors = false
77var shuffle_gallery_paintings = false 85var shuffle_gallery_paintings = false
78var shuffle_letters = kSHUFFLE_LETTERS_VANILLA 86var shuffle_letters = kSHUFFLE_LETTERS_VANILLA
79var shuffle_symbols = false 87var shuffle_symbols = false
80var shuffle_worldports = false 88var shuffle_worldports = false
89var slot_rng = null
81var strict_cyan_ending = false 90var strict_cyan_ending = false
82var strict_purple_ending = false 91var strict_purple_ending = false
83var victory_condition = -1 92var victory_condition = -1
@@ -269,6 +278,13 @@ func _process_item(item, amount):
269 if item_id == gamedata.objects.get_special_ids()["Numbers"] and global.map == "the_fuzzy": 278 if item_id == gamedata.objects.get_special_ids()["Numbers"] and global.map == "the_fuzzy":
270 global.allow_numbers = true 279 global.allow_numbers = true
271 280
281 if gamedata.map_id_by_rte_ap_id.has(item_id):
282 var rteInner = get_tree().get_root().get_node_or_null(
283 "scene/player/pause_menu/menu/return/rteInner"
284 )
285 if rteInner != null:
286 rteInner.refreshButtons()
287
272 # Show a message about the item if it's new. 288 # Show a message about the item if it's new.
273 if int(item["index"]) > _last_new_item: 289 if int(item["index"]) > _last_new_item:
274 _last_new_item = int(item["index"]) 290 _last_new_item = int(item["index"])
@@ -463,12 +479,14 @@ func _client_connected(slot_data):
463 _last_new_item = localdata[0] 479 _last_new_item = localdata[0]
464 480
465 # Read slot data. 481 # Read slot data.
482 custom_mint_ending = slot_data.get("custom_mint_ending", "")
466 cyan_door_behavior = int(slot_data.get("cyan_door_behavior", 0)) 483 cyan_door_behavior = int(slot_data.get("cyan_door_behavior", 0))
467 daedalus_only = bool(slot_data.get("daedalus_only", false)) 484 daedalus_only = bool(slot_data.get("daedalus_only", false))
468 daedalus_roof_access = bool(slot_data.get("daedalus_roof_access", false)) 485 daedalus_roof_access = bool(slot_data.get("daedalus_roof_access", false))
469 enable_gift_maps = slot_data.get("enable_gift_maps", []) 486 enable_gift_maps = slot_data.get("enable_gift_maps", [])
470 enable_icarus = bool(slot_data.get("enable_icarus", false)) 487 enable_icarus = bool(slot_data.get("enable_icarus", false))
471 endings_requirement = int(slot_data.get("endings_requirement", 0)) 488 endings_requirement = int(slot_data.get("endings_requirement", 0))
489 fast_travel_access = int(slot_data.get("fast_travel_access", 0))
472 keyholder_sanity = bool(slot_data.get("keyholder_sanity", false)) 490 keyholder_sanity = bool(slot_data.get("keyholder_sanity", false))
473 masteries_requirement = int(slot_data.get("masteries_requirement", 0)) 491 masteries_requirement = int(slot_data.get("masteries_requirement", 0))
474 shuffle_control_center_colors = bool(slot_data.get("shuffle_control_center_colors", false)) 492 shuffle_control_center_colors = bool(slot_data.get("shuffle_control_center_colors", false))
@@ -496,6 +514,19 @@ func _client_connected(slot_data):
496 raw_pp[p1] 514 raw_pp[p1]
497 )] 515 )]
498 516
517 rte_mapping.clear()
518 if slot_data.has("rte"):
519 rte_mapping = slot_data.get("rte")
520
521 slot_rng = RandomNumberGenerator.new()
522 slot_rng.seed = int(slot_data.get("seed", 0))
523
524 music_mapping.clear()
525 if bool(slot_data.get("shuffle_music", false)):
526 for map_name in global.reserved_scenes:
527 var track_index = slot_rng.randi_range(0, musicPlayer.all_tracks.size() - 1)
528 music_mapping[map_name] = musicPlayer.all_tracks.keys()[track_index]
529
499 # Set up item locks. 530 # Set up item locks.
500 _item_locks = {} 531 _item_locks = {}
501 532
diff --git a/apworld/client/maps/control_center.gd b/apworld/client/maps/control_center.gd index fadfed9..8e919ab 100644 --- a/apworld/client/maps/control_center.gd +++ b/apworld/client/maps/control_center.gd
@@ -74,6 +74,61 @@ func on_map_load(root):
74 old_door.queue_free() 74 old_door.queue_free()
75 root.get_node("/root/scene/Components/Doors").add_child.call_deferred(new_door) 75 root.get_node("/root/scene/Components/Doors").add_child.call_deferred(new_door)
76 76
77 # Display White Ending requirements.
78 var ending_count = 0
79 var mastery_count = 0
80 for key in unlocks.data:
81 if unlocks.data[key] == "unlocked":
82 if key.ends_with("_ending") and key != "free_ending":
83 ending_count += 1
84 elif key.ends_with("_mastery"):
85 mastery_count += 1
86
87 var sign_prefab = preload("res://objects/nodes/sign.tscn")
88 var sign1 = sign_prefab.instantiate()
89 sign1.position = Vector3(87.5, 5, -42.01)
90 sign1.text = "Endings: %d/%d" % [ending_count, ap.endings_requirement]
91 root.get_node("/root/scene").add_child.call_deferred(sign1)
92
93 var sign2 = sign_prefab.instantiate()
94 sign2.position = Vector3(87.5, 5, -15.99)
95 sign2.rotation_degrees.y = 180
96 sign2.text = "Masteries: %d/%d" % [mastery_count, ap.masteries_requirement]
97 root.get_node("/root/scene").add_child.call_deferred(sign2)
98
99 # Handle custom Mint Ending.
100 if ap.custom_mint_ending != "":
101 var panel_prefab = preload("res://objects/nodes/panel.tscn")
102 var tpl_prefab = preload("res://objects/nodes/listeners/teleportListener.tscn")
103
104 var mint_ending = root.get_node("/root/scene/Components/Endings/mint_ending")
105
106 var mint_panel = panel_prefab.instantiate()
107 mint_panel.name = "mint_panel"
108 mint_panel.clue = ap.custom_mint_ending
109 mint_panel.symbol = ""
110 mint_panel.answer = ap.custom_mint_ending
111 mint_panel.position = Vector3(-63, 3, -29)
112 mint_panel.rotation_degrees = Vector3(-45, 90, 0)
113 root.get_node("/root/scene").add_child.call_deferred(mint_panel)
114
115 var mint_tpl = tpl_prefab.instantiate()
116 mint_tpl.name = "mint_tpl"
117 mint_tpl.teleport_point = mint_ending.position
118 mint_tpl.teleport_rotate = mint_ending.rotation_degrees
119 mint_tpl.target_path = mint_ending
120 mint_tpl.senders.append(NodePath("/root/scene/mint_panel"))
121 root.get_node("/root/scene").add_child.call_deferred(mint_tpl)
122
123 var mint_tpl2 = tpl_prefab.instantiate()
124 mint_tpl2.name = "mint_tpl2"
125 mint_tpl2.teleport_point = Vector3(0, -1000, 0)
126 mint_tpl2.target_path = mint_panel
127 mint_tpl2.senders.append(NodePath("/root/scene/mint_panel"))
128 root.get_node("/root/scene").add_child.call_deferred(mint_tpl2)
129
130 mint_ending.position.y = -1000
131
77 132
78func _set_up_mastery_listener(root, name): 133func _set_up_mastery_listener(root, name):
79 var prefab = preload("res://objects/nodes/listeners/unlockReaderListener.tscn") 134 var prefab = preload("res://objects/nodes/listeners/unlockReaderListener.tscn")
diff --git a/apworld/client/player.gd b/apworld/client/player.gd index 5fac9fd..dabc15d 100644 --- a/apworld/client/player.gd +++ b/apworld/client/player.gd
@@ -13,6 +13,8 @@ func _ready():
13 13
14 var ap = global.get_node("Archipelago") 14 var ap = global.get_node("Archipelago")
15 var gamedata = global.get_node("Gamedata") 15 var gamedata = global.get_node("Gamedata")
16 var map_id = gamedata.map_id_by_name.get(global.map)
17 var map_data = gamedata.objects.get_maps()[map_id]
16 18
17 compass = global.get_node("Compass") 19 compass = global.get_node("Compass")
18 compass.visible = ap.show_compass 20 compass.visible = ap.show_compass
@@ -26,8 +28,33 @@ func _ready():
26 28
27 ap.update_job_well_done_sign() 29 ap.update_job_well_done_sign()
28 30
31 # Set up the RTE trigger, if there is one.
32 if map_data.has_rte_trigger_pos():
33 var oneShotListener_prefab = preload("res://objects/nodes/listeners/oneShotListener.tscn")
34 var triggerArea_prefab = preload("res://objects/nodes/triggerArea.tscn")
35 var unlockSetterListener_prefab = preload(
36 "res://objects/nodes/listeners/unlockSetterListener.tscn"
37 )
38
39 var triggerArea = triggerArea_prefab.instantiate()
40 triggerArea.name = "rte_triggerArea"
41 triggerArea.position = gamedata.vec3d_to_vector3(map_data.get_rte_trigger_pos())
42 triggerArea.scale = gamedata.vec3d_to_vector3(map_data.get_rte_trigger_scale())
43 get_parent().add_child.call_deferred(triggerArea)
44
45 var osl = oneShotListener_prefab.instantiate()
46 osl.name = "rte_osl"
47 osl.senders.append(NodePath("/root/scene/rte_triggerArea"))
48 get_parent().add_child.call_deferred(osl)
49
50 var usl = unlockSetterListener_prefab.instantiate()
51 usl.name = "rte_usl"
52 usl.key = "rte_%s" % global.map
53 usl.value = "unlocked"
54 usl.senders.append(NodePath("/root/scene/rte_osl"))
55 get_parent().add_child.call_deferred(usl)
56
29 # Set up door locations. 57 # Set up door locations.
30 var map_id = gamedata.map_id_by_name.get(global.map)
31 for door in gamedata.objects.get_doors(): 58 for door in gamedata.objects.get_doors():
32 if door.get_map_id() != map_id: 59 if door.get_map_id() != map_id:
33 continue 60 continue
@@ -169,6 +196,17 @@ func _ready():
169 minimap.visible = ap.show_minimap 196 minimap.visible = ap.show_minimap
170 get_parent().add_child.call_deferred(minimap) 197 get_parent().add_child.call_deferred(minimap)
171 198
199 if ap.music_mapping.has(global.map):
200 var song_setter = get_node_or_null("/root/scene/songSetter")
201 if song_setter:
202 song_setter.song_name = ap.music_mapping[global.map]
203 else:
204 var song_setter_prefab = preload("res://objects/nodes/songSetter.tscn")
205 song_setter = song_setter_prefab.instantiate()
206 song_setter.name = "songSetter"
207 song_setter.song_name = ap.music_mapping[global.map]
208 get_parent().add_child.call_deferred(song_setter)
209
172 super._ready() 210 super._ready()
173 211
174 await get_tree().process_frame 212 await get_tree().process_frame
diff --git a/apworld/client/rteMenu.gd b/apworld/client/rteMenu.gd index 5882d77..519f09f 100644 --- a/apworld/client/rteMenu.gd +++ b/apworld/client/rteMenu.gd
@@ -1,5 +1,7 @@
1extends "res://scripts/ui/rteMenu.gd" 1extends "res://scripts/ui/rteMenu.gd"
2 2
3var buttons = []
4
3 5
4func _readier(): 6func _readier():
5 var ap = global.get_node("Archipelago") 7 var ap = global.get_node("Archipelago")
@@ -8,5 +10,58 @@ func _readier():
8 get_node("rte_daedalus").show() 10 get_node("rte_daedalus").show()
9 11
10 switcher.preload_map("res://objects/scenes/daedalus.tscn") 12 switcher.preload_map("res://objects/scenes/daedalus.tscn")
13 elif !ap.rte_mapping.is_empty():
14 buttons = [$rte_the_plaza, $rte_the_gallery, $rte_daedalus, $rte_control_center]
15 for i in range(4):
16 buttons[i].name = "button_%d" % i
17 for i in range(4):
18 _setupButton(buttons[i], ap.rte_mapping[i])
19
20 refreshButtons()
11 else: 21 else:
12 super()._readier() 22 super()._readier()
23
24
25func _setupButton(button, map_name):
26 switcher.preload_map("res://objects/scenes/%s.tscn" % map_name)
27
28 button.hide()
29 button.text = map_name.replace("_", " ")
30 button.name = "rte_%s" % map_name
31 button.autowrap_mode = TextServer.AUTOWRAP_WORD
32
33 var ap = global.get_node("Archipelago")
34 if (
35 ap.fast_travel_access == ap.kFAST_TRAVEL_ACCESS_VANILLA
36 and !unlocks.data.has("rte_%s" % map_name)
37 ):
38 unlocks.data["rte_%s" % map_name] = ""
39
40
41func refreshButtons():
42 var ap = global.get_node("Archipelago")
43 if ap.rte_mapping.is_empty():
44 return
45
46 for i in range(4):
47 if _shouldShowButton(ap.rte_mapping[i]):
48 buttons[i].show()
49 else:
50 buttons[i].hide()
51
52
53func _shouldShowButton(map_name):
54 var ap = global.get_node("Archipelago")
55
56 if ap.fast_travel_access == ap.kFAST_TRAVEL_ACCESS_VANILLA:
57 return unlocks.data["rte_%s" % map_name] == "unlocked"
58 elif ap.fast_travel_access == ap.kFAST_TRAVEL_ACCESS_UNLOCKED:
59 return true
60 elif ap.fast_travel_access == ap.kFAST_TRAVEL_ACCESS_ITEMS:
61 var gamedata = global.get_node("Gamedata")
62 var map_id = gamedata.map_id_by_name[map_name]
63 var rte_ap_id = gamedata.objects.get_maps()[map_id].get_rte_ap_id()
64
65 return ap.client.hasItem(rte_ap_id)
66
67 return false