about summary refs log tree commit diff stats
path: root/client
diff options
context:
space:
mode:
Diffstat (limited to 'client')
-rw-r--r--client/Archipelago/gamedata.gd47
-rw-r--r--client/Archipelago/manager.gd10
-rw-r--r--client/Archipelago/panel.gd101
-rw-r--r--client/Archipelago/player.gd7
-rw-r--r--client/Archipelago/settings_screen.gd4
-rw-r--r--client/README.md4
6 files changed, 169 insertions, 4 deletions
diff --git a/client/Archipelago/gamedata.gd b/client/Archipelago/gamedata.gd index f7a5d90..d8d16ed 100644 --- a/client/Archipelago/gamedata.gd +++ b/client/Archipelago/gamedata.gd
@@ -5,15 +5,41 @@ var SCRIPT_proto
5var objects 5var objects
6var door_id_by_map_node_path = {} 6var door_id_by_map_node_path = {}
7var painting_id_by_map_node_path = {} 7var painting_id_by_map_node_path = {}
8var panel_id_by_map_node_path = {}
8var door_id_by_ap_id = {} 9var door_id_by_ap_id = {}
9var map_id_by_name = {} 10var map_id_by_name = {}
10var progressive_id_by_ap_id = {} 11var progressive_id_by_ap_id = {}
11var letter_id_by_ap_id = {} 12var letter_id_by_ap_id = {}
13var symbol_item_ids = []
14
15var kSYMBOL_ITEMS
12 16
13 17
14func _init(proto_script): 18func _init(proto_script):
15 SCRIPT_proto = proto_script 19 SCRIPT_proto = proto_script
16 20
21 kSYMBOL_ITEMS = {
22 SCRIPT_proto.PuzzleSymbol.SUN: "Sun Symbol",
23 SCRIPT_proto.PuzzleSymbol.SPARKLES: "Sparkles Symbol",
24 SCRIPT_proto.PuzzleSymbol.ZERO: "Zero Symbol",
25 SCRIPT_proto.PuzzleSymbol.EXAMPLE: "Example Symbol",
26 SCRIPT_proto.PuzzleSymbol.BOXES: "Boxes Symbol",
27 SCRIPT_proto.PuzzleSymbol.PLANET: "Planet Symbol",
28 SCRIPT_proto.PuzzleSymbol.PYRAMID: "Pyramid Symbol",
29 SCRIPT_proto.PuzzleSymbol.CROSS: "Cross Symbol",
30 SCRIPT_proto.PuzzleSymbol.SWEET: "Sweet Symbol",
31 SCRIPT_proto.PuzzleSymbol.GENDER: "Gender Symbol",
32 SCRIPT_proto.PuzzleSymbol.AGE: "Age Symbol",
33 SCRIPT_proto.PuzzleSymbol.SOUND: "Sound Symbol",
34 SCRIPT_proto.PuzzleSymbol.ANAGRAM: "Anagram Symbol",
35 SCRIPT_proto.PuzzleSymbol.JOB: "Job Symbol",
36 SCRIPT_proto.PuzzleSymbol.STARS: "Stars Symbol",
37 SCRIPT_proto.PuzzleSymbol.NULL: "Null Symbol",
38 SCRIPT_proto.PuzzleSymbol.EVAL: "Eval Symbol",
39 SCRIPT_proto.PuzzleSymbol.LINGO: "Lingo Symbol",
40 SCRIPT_proto.PuzzleSymbol.QUESTION: "Question Symbol",
41 }
42
17 43
18func load(data_bytes): 44func load(data_bytes):
19 objects = SCRIPT_proto.AllObjects.new() 45 objects = SCRIPT_proto.AllObjects.new()
@@ -58,6 +84,19 @@ func load(data_bytes):
58 for letter in objects.get_letters(): 84 for letter in objects.get_letters():
59 letter_id_by_ap_id[letter.get_ap_id()] = letter.get_id() 85 letter_id_by_ap_id[letter.get_ap_id()] = letter.get_id()
60 86
87 for panel in objects.get_panels():
88 var room = objects.get_rooms()[panel.get_room_id()]
89 var map = objects.get_maps()[room.get_map_id()]
90
91 if not map.get_name() in panel_id_by_map_node_path:
92 panel_id_by_map_node_path[map.get_name()] = {}
93
94 var map_data = panel_id_by_map_node_path[map.get_name()]
95 map_data[panel.get_path()] = panel.get_id()
96
97 for symbol_name in kSYMBOL_ITEMS.values():
98 symbol_item_ids.append(objects.get_special_ids()[symbol_name])
99
61 100
62func get_door_for_map_node_path(map_name, node_path): 101func get_door_for_map_node_path(map_name, node_path):
63 if not door_id_by_map_node_path.has(map_name): 102 if not door_id_by_map_node_path.has(map_name):
@@ -67,6 +106,14 @@ func get_door_for_map_node_path(map_name, node_path):
67 return map_data.get(node_path, null) 106 return map_data.get(node_path, null)
68 107
69 108
109func get_panel_for_map_node_path(map_name, node_path):
110 if not panel_id_by_map_node_path.has(map_name):
111 return null
112
113 var map_data = panel_id_by_map_node_path[map_name]
114 return map_data.get(node_path, null)
115
116
70func get_door_ap_id(door_id): 117func get_door_ap_id(door_id):
71 var door = objects.get_doors()[door_id] 118 var door = objects.get_doors()[door_id]
72 if door.has_ap_id(): 119 if door.has_ap_id():
diff --git a/client/Archipelago/manager.gd b/client/Archipelago/manager.gd index cd0654f..383be1f 100644 --- a/client/Archipelago/manager.gd +++ b/client/Archipelago/manager.gd
@@ -1,6 +1,7 @@
1extends Node 1extends Node
2 2
3const my_version = "0.1.0" 3const MAJOR_VERSION = 1
4const MINOR_VERSION = 0
4 5
5var SCRIPT_client 6var SCRIPT_client
6var SCRIPT_keyboard 7var SCRIPT_keyboard
@@ -47,6 +48,7 @@ var keyholder_sanity = false
47var shuffle_control_center_colors = false 48var shuffle_control_center_colors = false
48var shuffle_doors = false 49var shuffle_doors = false
49var shuffle_letters = kSHUFFLE_LETTERS_VANILLA 50var shuffle_letters = kSHUFFLE_LETTERS_VANILLA
51var shuffle_symbols = false
50var victory_condition = -1 52var victory_condition = -1
51 53
52signal could_not_connect 54signal could_not_connect
@@ -183,6 +185,11 @@ func _process_item(item, index, from, flags, amount):
183 if not letter.has_level2() or not letter.get_level2(): 185 if not letter.has_level2() or not letter.get_level2():
184 _process_key_item(letter.get_key(), amount) 186 _process_key_item(letter.get_key(), amount)
185 187
188 if gamedata.symbol_item_ids.has(item):
189 var player = get_tree().get_root().get_node_or_null("scene/player")
190 if player != null:
191 player.emit_signal("evaluate_solvability")
192
186 # Show a message about the item if it's new. 193 # Show a message about the item if it's new.
187 if index != null and index > _last_new_item: 194 if index != null and index > _last_new_item:
188 _last_new_item = index 195 _last_new_item = index
@@ -356,6 +363,7 @@ func _client_connected(slot_data):
356 shuffle_control_center_colors = bool(slot_data.get("shuffle_control_center_colors", false)) 363 shuffle_control_center_colors = bool(slot_data.get("shuffle_control_center_colors", false))
357 shuffle_doors = bool(slot_data.get("shuffle_doors", false)) 364 shuffle_doors = bool(slot_data.get("shuffle_doors", false))
358 shuffle_letters = int(slot_data.get("shuffle_letters", 0)) 365 shuffle_letters = int(slot_data.get("shuffle_letters", 0))
366 shuffle_symbols = bool(slot_data.get("shuffle_symbols", false))
359 victory_condition = int(slot_data.get("victory_condition", 0)) 367 victory_condition = int(slot_data.get("victory_condition", 0))
360 368
361 # Set up item locks. 369 # Set up item locks.
diff --git a/client/Archipelago/panel.gd b/client/Archipelago/panel.gd new file mode 100644 index 0000000..fdaaf0e --- /dev/null +++ b/client/Archipelago/panel.gd
@@ -0,0 +1,101 @@
1extends "res://scripts/nodes/panel.gd"
2
3var panel_logic = null
4var symbol_solvable = true
5
6var black = load("res://assets/materials/black.material")
7
8
9func _ready():
10 super._ready()
11
12 var node_path = String(
13 get_tree().get_root().get_node("scene").get_path_to(self).get_concatenated_names()
14 )
15
16 var gamedata = global.get_node("Gamedata")
17 var panel_id = gamedata.get_panel_for_map_node_path(global.map, node_path)
18 if panel_id != null:
19 var ap = global.get_node("Archipelago")
20 if ap.shuffle_symbols:
21 if global.map == "the_entry" and node_path == "Panels/Entry/front_1":
22 clue = "i"
23 symbol = ""
24
25 setField("clue", clue)
26 setField("symbol", symbol)
27
28 panel_logic = gamedata.objects.get_panels()[panel_id]
29 checkSymbolSolvable()
30
31 if not symbol_solvable:
32 get_tree().get_root().get_node("scene/player").connect(
33 "evaluate_solvability", evaluateSolvability
34 )
35
36
37func checkSymbolSolvable():
38 var old_solvable = symbol_solvable
39 symbol_solvable = true
40
41 if panel_logic == null:
42 # There's no logic for this panel.
43 return
44
45 var ap = global.get_node("Archipelago")
46 if not ap.shuffle_symbols:
47 # Symbols aren't item-locked.
48 return
49
50 var gamedata = global.get_node("Gamedata")
51 for symbol in panel_logic.get_symbols():
52 var item_name = gamedata.kSYMBOL_ITEMS.get(symbol)
53 var item_id = gamedata.objects.get_special_ids()[item_name]
54 if ap.client.getItemAmount(item_id) < 1:
55 symbol_solvable = false
56 break
57
58 if symbol_solvable != old_solvable:
59 if symbol_solvable:
60 setField("clue", clue)
61 setField("symbol", symbol)
62 setField("answer", answer)
63 else:
64 quad_mesh.surface_set_material(0, black)
65 get_node("Hinge/clue").text = "missing"
66 get_node("Hinge/answer").text = "symbols"
67
68
69func checkSolvable(key):
70 checkSymbolSolvable()
71 if not symbol_solvable:
72 return false
73
74 return super.checkSolvable(key)
75
76
77func evaluateSolvability():
78 checkSolvable("")
79
80
81func passedInput(key, skip_focus_check = false):
82 if not symbol_solvable:
83 return
84
85 super.passedInput(key, skip_focus_check)
86
87
88func focus():
89 if not symbol_solvable:
90 has_focus = false
91 return
92
93 super.focus()
94
95
96func unfocus():
97 if not symbol_solvable:
98 has_focus = false
99 return
100
101 super.unfocus()
diff --git a/client/Archipelago/player.gd b/client/Archipelago/player.gd index dd6aa2b..4b995bc 100644 --- a/client/Archipelago/player.gd +++ b/client/Archipelago/player.gd
@@ -16,6 +16,8 @@ const kEndingNameByVictoryValue = {
16 12: "WHITE", 16 12: "WHITE",
17} 17}
18 18
19signal evaluate_solvability
20
19 21
20func _ready(): 22func _ready():
21 var khl_script = load("res://scripts/nodes/keyHolderListener.gd") 23 var khl_script = load("res://scripts/nodes/keyHolderListener.gd")
@@ -188,6 +190,11 @@ func _ready():
188 warp_enter.rotation_degrees.y = 90 190 warp_enter.rotation_degrees.y = 90
189 get_parent().add_child.call_deferred(warp_enter) 191 get_parent().add_child.call_deferred(warp_enter)
190 192
193 # Remove door behind X1.
194 if global.map == "the_entry":
195 var door_node = get_tree().get_root().get_node("/root/scene/Components/Doors/exit_1")
196 door_node.handleTriggered()
197
191 super._ready() 198 super._ready()
192 199
193 await get_tree().process_frame 200 await get_tree().process_frame
diff --git a/client/Archipelago/settings_screen.gd b/client/Archipelago/settings_screen.gd index aaaf72a..a3bc25e 100644 --- a/client/Archipelago/settings_screen.gd +++ b/client/Archipelago/settings_screen.gd
@@ -40,6 +40,7 @@ func _ready():
40 ResourceLoader.load("user://maps/Archipelago/keyHolderResetterListener.gd") 40 ResourceLoader.load("user://maps/Archipelago/keyHolderResetterListener.gd")
41 ) 41 )
42 installScriptExtension(ResourceLoader.load("user://maps/Archipelago/painting.gd")) 42 installScriptExtension(ResourceLoader.load("user://maps/Archipelago/painting.gd"))
43 installScriptExtension(ResourceLoader.load("user://maps/Archipelago/panel.gd"))
43 installScriptExtension(ResourceLoader.load("user://maps/Archipelago/pauseMenu.gd")) 44 installScriptExtension(ResourceLoader.load("user://maps/Archipelago/pauseMenu.gd"))
44 installScriptExtension(ResourceLoader.load("user://maps/Archipelago/player.gd")) 45 installScriptExtension(ResourceLoader.load("user://maps/Archipelago/player.gd"))
45 installScriptExtension(ResourceLoader.load("user://maps/Archipelago/saver.gd")) 46 installScriptExtension(ResourceLoader.load("user://maps/Archipelago/saver.gd"))
@@ -89,7 +90,7 @@ func _ready():
89 history_box.get_popup().connect("id_pressed", historySelected) 90 history_box.get_popup().connect("id_pressed", historySelected)
90 91
91 # Show client version. 92 # Show client version.
92 $Panel/title.text = "ARCHIPELAGO (%s)" % ap.my_version 93 $Panel/title.text = "ARCHIPELAGO (%d.%d)" % [ap.MAJOR_VERSION, ap.MINOR_VERSION]
93 94
94 # Increase font size in text boxes. 95 # Increase font size in text boxes.
95 $Panel/server_box.add_theme_font_size_override("font_size", 36) 96 $Panel/server_box.add_theme_font_size_override("font_size", 36)
@@ -159,6 +160,7 @@ func connectionSuccessful():
159 clearResourceCache("res://objects/nodes/listeners/keyHolderResetterListener.tscn") 160 clearResourceCache("res://objects/nodes/listeners/keyHolderResetterListener.tscn")
160 clearResourceCache("res://objects/nodes/listeners/teleportListener.tscn") 161 clearResourceCache("res://objects/nodes/listeners/teleportListener.tscn")
161 clearResourceCache("res://objects/nodes/listeners/worldportListener.tscn") 162 clearResourceCache("res://objects/nodes/listeners/worldportListener.tscn")
163 clearResourceCache("res://objects/nodes/panel.tscn")
162 clearResourceCache("res://objects/nodes/player.tscn") 164 clearResourceCache("res://objects/nodes/player.tscn")
163 clearResourceCache("res://objects/nodes/saver.tscn") 165 clearResourceCache("res://objects/nodes/saver.tscn")
164 clearResourceCache("res://objects/scenes/menus/pause_menu.tscn") 166 clearResourceCache("res://objects/scenes/menus/pause_menu.tscn")
diff --git a/client/README.md b/client/README.md index 07c5459..1e94bdb 100644 --- a/client/README.md +++ b/client/README.md
@@ -6,7 +6,7 @@ to an Archipelago Multiworld and randomize your game.
6## Installation 6## Installation
7 7
81. Download the Lingo 2 Archipelago Randomizer from 81. Download the Lingo 2 Archipelago Randomizer from
9 [the releases page](https://code.fourisland.com/lingo-archipelago2/about/client/CHANGELOG.md). 9 [the releases page](https://code.fourisland.com/lingo2-archipelago/about/client/CHANGELOG.md).
102. Open up Lingo 2, go to settings, and click View Game Data. This should open 102. Open up Lingo 2, go to settings, and click View Game Data. This should open
11 up a folder in Windows Explorer. 11 up a folder in Windows Explorer.
123. Unzip the randomizer into the "maps" folder. Ensure that archipelago.tscn and 123. Unzip the randomizer into the "maps" folder. Ensure that archipelago.tscn and
@@ -44,7 +44,7 @@ need to be generated before the client can be run.
44 44
45The first file is `data.binpb`, the datafile containing the randomizer logic. 45The first file is `data.binpb`, the datafile containing the randomizer logic.
46You can read about how to generate it on 46You can read about how to generate it on
47[its own README page](https://code.fourisland.com/lingo-archipelago2/about/data/README.md). 47[its own README page](https://code.fourisland.com/lingo2-archipelago/about/data/README.md).
48Once you have it, put it in a subfolder of `client` called `generated`. 48Once you have it, put it in a subfolder of `client` called `generated`.
49 49
50The second generated file is `proto.gd`. This file allows Lingo 2 to read the 50The second generated file is `proto.gd`. This file allows Lingo 2 to read the