diff options
| -rw-r--r-- | Archipelago/client.gd | 54 | ||||
| -rw-r--r-- | Archipelago/effects.gd | 66 | ||||
| -rw-r--r-- | Archipelago/load.gd | 1 | ||||
| -rw-r--r-- | Archipelago/multiplayer.gd | 55 | ||||
| -rw-r--r-- | Archipelago/textclient.gd | 16 | ||||
| -rw-r--r-- | CHANGELOG.md | 19 | ||||
| -rw-r--r-- | README.md | 5 | 
7 files changed, 199 insertions, 17 deletions
| diff --git a/Archipelago/client.gd b/Archipelago/client.gd index 5f8be4e..8cddb83 100644 --- a/Archipelago/client.gd +++ b/Archipelago/client.gd | |||
| @@ -19,7 +19,7 @@ var enable_multiplayer = false | |||
| 19 | var track_player = false | 19 | var track_player = false | 
| 20 | var connection_history = [] | 20 | var connection_history = [] | 
| 21 | 21 | ||
| 22 | const my_version = "panels-beta6" | 22 | const my_version = "4.2.1" | 
| 23 | const ap_version = {"major": 0, "minor": 5, "build": 0, "class": "Version"} | 23 | const ap_version = {"major": 0, "minor": 5, "build": 0, "class": "Version"} | 
| 24 | const color_items = [ | 24 | const color_items = [ | 
| 25 | "White", "Black", "Red", "Blue", "Green", "Brown", "Gray", "Orange", "Purple", "Yellow" | 25 | "White", "Black", "Red", "Blue", "Green", "Brown", "Gray", "Orange", "Purple", "Yellow" | 
| @@ -114,6 +114,7 @@ var _pilgrimage_allows_roof_access = false | |||
| 114 | var _pilgrimage_allows_paintings = false | 114 | var _pilgrimage_allows_paintings = false | 
| 115 | var _sunwarp_shuffle = false | 115 | var _sunwarp_shuffle = false | 
| 116 | var _sunwarp_mapping = [] | 116 | var _sunwarp_mapping = [] | 
| 117 | var _speed_boost_mode = false | ||
| 117 | var _slot_seed = 0 | 118 | var _slot_seed = 0 | 
| 118 | 119 | ||
| 119 | var _map_loaded = false | 120 | var _map_loaded = false | 
| @@ -127,8 +128,11 @@ var _puzzle_skips = 0 | |||
| 127 | var _cached_slowness = 0 | 128 | var _cached_slowness = 0 | 
| 128 | var _cached_iceland = 0 | 129 | var _cached_iceland = 0 | 
| 129 | var _cached_atbash = 0 | 130 | var _cached_atbash = 0 | 
| 131 | var _cached_speed_boosts = 0 | ||
| 130 | var _geronimo_skip = false | 132 | var _geronimo_skip = false | 
| 131 | var _checked_paintings = [] | 133 | var _checked_paintings = [] | 
| 134 | var _hints_key = "" | ||
| 135 | var _hinted_locations = [] | ||
| 132 | 136 | ||
| 133 | signal could_not_connect | 137 | signal could_not_connect | 
| 134 | signal connect_status | 138 | signal connect_status | 
| @@ -346,6 +350,10 @@ func _on_data(): | |||
| 346 | _sunwarp_shuffle = false | 350 | _sunwarp_shuffle = false | 
| 347 | if _slot_data.has("sunwarp_permutation"): | 351 | if _slot_data.has("sunwarp_permutation"): | 
| 348 | _sunwarp_mapping = _slot_data["sunwarp_permutation"] | 352 | _sunwarp_mapping = _slot_data["sunwarp_permutation"] | 
| 353 | if _slot_data.has("speed_boost_mode"): | ||
| 354 | _speed_boost_mode = _slot_data["speed_boost_mode"] | ||
| 355 | else: | ||
| 356 | _speed_boost_mode = false | ||
| 349 | 357 | ||
| 350 | if ( | 358 | if ( | 
| 351 | _location_classification_bit != kCLASSIFICATION_LOCAL_INSANITY | 359 | _location_classification_bit != kCLASSIFICATION_LOCAL_INSANITY | 
| @@ -364,6 +372,7 @@ func _on_data(): | |||
| 364 | _cached_slowness = 0 | 372 | _cached_slowness = 0 | 
| 365 | _cached_iceland = 0 | 373 | _cached_iceland = 0 | 
| 366 | _cached_atbash = 0 | 374 | _cached_atbash = 0 | 
| 375 | _cached_speed_boosts = 0 | ||
| 367 | _geronimo_skip = false | 376 | _geronimo_skip = false | 
| 368 | 377 | ||
| 369 | _localdata_file = "user://archipelago_data/%s_%d" % [_seed, _slot] | 378 | _localdata_file = "user://archipelago_data/%s_%d" % [_seed, _slot] | 
| @@ -395,6 +404,9 @@ func _on_data(): | |||
| 395 | if localdata.size() > 5: | 404 | if localdata.size() > 5: | 
| 396 | _geronimo_skip = localdata[5] | 405 | _geronimo_skip = localdata[5] | 
| 397 | 406 | ||
| 407 | if localdata.size() > 6: | ||
| 408 | _cached_speed_boosts = localdata[6] | ||
| 409 | |||
| 398 | requestSync() | 410 | requestSync() | 
| 399 | 411 | ||
| 400 | sendMessage( | 412 | sendMessage( | 
| @@ -409,6 +421,11 @@ func _on_data(): | |||
| 409 | ] | 421 | ] | 
| 410 | ) | 422 | ) | 
| 411 | 423 | ||
| 424 | _hints_key = "_read_hints_%d_%d" % [_team, _slot] | ||
| 425 | sendMessage( | ||
| 426 | [{"cmd": "SetNotify", "keys": [_hints_key]}, {"cmd": "Get", "keys": [_hints_key]}] | ||
| 427 | ) | ||
| 428 | |||
| 412 | emit_signal("client_connected") | 429 | emit_signal("client_connected") | 
| 413 | 430 | ||
| 414 | elif cmd == "ConnectionRefused": | 431 | elif cmd == "ConnectionRefused": | 
| @@ -506,9 +523,12 @@ func _on_data(): | |||
| 506 | ) | 523 | ) | 
| 507 | else: | 524 | else: | 
| 508 | if message["receiving"] != _slot: | 525 | if message["receiving"] != _slot: | 
| 509 | messages.showMessage( | 526 | var sentMsg = ( | 
| 510 | "Sent [color=%s]%s[/color] to %s" % [item_color, item_name, player_name] | 527 | "Sent [color=%s]%s[/color] to %s" % [item_color, item_name, player_name] | 
| 511 | ) | 528 | ) | 
| 529 | if _hinted_locations.has(message["item"]["location"]): | ||
| 530 | sentMsg += " ([color=#fafad2]Hinted![/color])" | ||
| 531 | messages.showMessage(sentMsg) | ||
| 512 | 532 | ||
| 513 | elif cmd == "Bounced": | 533 | elif cmd == "Bounced": | 
| 514 | if ( | 534 | if ( | 
| @@ -529,8 +549,15 @@ func _on_data(): | |||
| 529 | get_tree().get_root().get_node("Spatial/player/pause_menu")._reload() | 549 | get_tree().get_root().get_node("Spatial/player/pause_menu")._reload() | 
| 530 | 550 | ||
| 531 | elif cmd == "SetReply": | 551 | elif cmd == "SetReply": | 
| 532 | if message.has("key") and message["key"] == ("Lingo_%d_Paintings" % _slot): | 552 | if message.has("key"): | 
| 533 | _checked_paintings = message["value"] | 553 | if message["key"] == ("Lingo_%d_Paintings" % _slot): | 
| 554 | _checked_paintings = message["value"] | ||
| 555 | elif message["key"] == _hints_key: | ||
| 556 | parseHints(message["value"]) | ||
| 557 | |||
| 558 | elif cmd == "Retrieved": | ||
| 559 | if message.has("keys") and message["keys"].has(_hints_key): | ||
| 560 | parseHints(message["keys"][_hints_key]) | ||
| 534 | 561 | ||
| 535 | 562 | ||
| 536 | func _process(_delta): | 563 | func _process(_delta): | 
| @@ -584,7 +611,8 @@ func saveLocaldata(): | |||
| 584 | effects_node.slowness_remaining, | 611 | effects_node.slowness_remaining, | 
| 585 | effects_node.iceland_remaining, | 612 | effects_node.iceland_remaining, | 
| 586 | effects_node.atbash_remaining, | 613 | effects_node.atbash_remaining, | 
| 587 | _geronimo_skip | 614 | _geronimo_skip, | 
| 615 | effects_node.speed_boosts_remaining, | ||
| 588 | ] | 616 | ] | 
| 589 | file.store_var(data, true) | 617 | file.store_var(data, true) | 
| 590 | file.close() | 618 | file.close() | 
| @@ -831,12 +859,14 @@ func processItem(item, index, from, flags): | |||
| 831 | ) | 859 | ) | 
| 832 | 860 | ||
| 833 | var effects_node = get_tree().get_root().get_node("Spatial/AP_Effects") | 861 | var effects_node = get_tree().get_root().get_node("Spatial/AP_Effects") | 
| 834 | if item_name == "Slowness Trap": | 862 | if item_name == "Slowness Trap" and !_speed_boost_mode: | 
| 835 | effects_node.trigger_slowness_trap() | 863 | effects_node.trigger_slowness_trap() | 
| 836 | if item_name == "Iceland Trap": | 864 | if item_name == "Iceland Trap": | 
| 837 | effects_node.trigger_iceland_trap() | 865 | effects_node.trigger_iceland_trap() | 
| 838 | if item_name == "Atbash Trap": | 866 | if item_name == "Atbash Trap": | 
| 839 | effects_node.trigger_atbash_trap() | 867 | effects_node.trigger_atbash_trap() | 
| 868 | if item_name == "Speed Boost" and _speed_boost_mode: | ||
| 869 | effects_node.trigger_speed_boost() | ||
| 840 | if item_name == "Puzzle Skip": | 870 | if item_name == "Puzzle Skip": | 
| 841 | _puzzle_skips += 1 | 871 | _puzzle_skips += 1 | 
| 842 | 872 | ||
| @@ -887,6 +917,14 @@ func checkPainting(painting_id): | |||
| 887 | setValue("Paintings", [painting_id], "add") | 917 | setValue("Paintings", [painting_id], "add") | 
| 888 | 918 | ||
| 889 | 919 | ||
| 920 | func parseHints(hints): | ||
| 921 | _hinted_locations.clear() | ||
| 922 | |||
| 923 | for hint in hints: | ||
| 924 | if hint["finding_player"] == int(_slot): | ||
| 925 | _hinted_locations.append(hint["location"]) | ||
| 926 | |||
| 927 | |||
| 890 | func colorForItemType(flags): | 928 | func colorForItemType(flags): | 
| 891 | var int_flags = int(flags) | 929 | var int_flags = int(flags) | 
| 892 | if int_flags & 1: # progression | 930 | if int_flags & 1: # progression | 
| @@ -936,6 +974,10 @@ func parse_printjson(message): | |||
| 936 | textclient_node.parse_printjson("".join(parts)) | 974 | textclient_node.parse_printjson("".join(parts)) | 
| 937 | 975 | ||
| 938 | 976 | ||
| 977 | func get_player_name(): | ||
| 978 | return _player_name_by_slot[_slot] | ||
| 979 | |||
| 980 | |||
| 939 | func compareVersion(lhs, rhs): | 981 | func compareVersion(lhs, rhs): | 
| 940 | if lhs["major"] == rhs["major"]: | 982 | if lhs["major"] == rhs["major"]: | 
| 941 | if lhs["minor"] == rhs["minor"]: | 983 | if lhs["minor"] == rhs["minor"]: | 
| diff --git a/Archipelago/effects.gd b/Archipelago/effects.gd index 1e2e311..341a783 100644 --- a/Archipelago/effects.gd +++ b/Archipelago/effects.gd | |||
| @@ -5,6 +5,7 @@ var effect_running = false | |||
| 5 | var slowness_remaining = 0 | 5 | var slowness_remaining = 0 | 
| 6 | var iceland_remaining = 0 | 6 | var iceland_remaining = 0 | 
| 7 | var atbash_remaining = 0 | 7 | var atbash_remaining = 0 | 
| 8 | var speed_boosts_remaining = 0 | ||
| 8 | var queued_iceland = 0 | 9 | var queued_iceland = 0 | 
| 9 | var skip_available = false | 10 | var skip_available = false | 
| 10 | var puzzle_focused = false | 11 | var puzzle_focused = false | 
| @@ -48,6 +49,12 @@ func _ready(): | |||
| 48 | add_child(slowness_timer) | 49 | add_child(slowness_timer) | 
| 49 | slowness_timer.connect("timeout", self, "_tick_slowness") | 50 | slowness_timer.connect("timeout", self, "_tick_slowness") | 
| 50 | 51 | ||
| 52 | var speed_boost_timer = Timer.new() | ||
| 53 | speed_boost_timer.name = "SpeedBoostTimer" | ||
| 54 | speed_boost_timer.wait_time = 1.0 | ||
| 55 | add_child(speed_boost_timer) | ||
| 56 | speed_boost_timer.connect("timeout", self, "_tick_speed_boost") | ||
| 57 | |||
| 51 | var iceland_timer = Timer.new() | 58 | var iceland_timer = Timer.new() | 
| 52 | iceland_timer.name = "IcelandTimer" | 59 | iceland_timer.name = "IcelandTimer" | 
| 53 | iceland_timer.wait_time = 1.0 | 60 | iceland_timer.wait_time = 1.0 | 
| @@ -63,6 +70,12 @@ func activate(): | |||
| 63 | 70 | ||
| 64 | queued_iceland = 0 | 71 | queued_iceland = 0 | 
| 65 | 72 | ||
| 73 | var apclient = global.get_node("Archipelago") | ||
| 74 | if apclient._speed_boost_mode: | ||
| 75 | var player = get_tree().get_root().get_node("Spatial/player") | ||
| 76 | player.walk_speed = orig_walk / 2.0 | ||
| 77 | player.run_speed = orig_run / 2.0 | ||
| 78 | |||
| 66 | 79 | ||
| 67 | func trigger_slowness_trap(length = 30): | 80 | func trigger_slowness_trap(length = 30): | 
| 68 | if slowness_remaining == 0: | 81 | if slowness_remaining == 0: | 
| @@ -79,6 +92,21 @@ func trigger_slowness_trap(length = 30): | |||
| 79 | apclient.saveLocaldata() | 92 | apclient.saveLocaldata() | 
| 80 | 93 | ||
| 81 | 94 | ||
| 95 | func trigger_speed_boost(length = 20): | ||
| 96 | if speed_boosts_remaining == 0: | ||
| 97 | var player = get_tree().get_root().get_node("Spatial/player") | ||
| 98 | player.walk_speed = orig_walk | ||
| 99 | player.run_speed = orig_run | ||
| 100 | |||
| 101 | $SpeedBoostTimer.start() | ||
| 102 | |||
| 103 | speed_boosts_remaining += length | ||
| 104 | text_dirty = true | ||
| 105 | |||
| 106 | var apclient = global.get_node("Archipelago") | ||
| 107 | apclient.saveLocaldata() | ||
| 108 | |||
| 109 | |||
| 82 | func trigger_iceland_trap(length = 60): | 110 | func trigger_iceland_trap(length = 60): | 
| 83 | if not activated: | 111 | if not activated: | 
| 84 | queued_iceland += length | 112 | queued_iceland += length | 
| @@ -99,7 +127,7 @@ func trigger_iceland_trap(length = 60): | |||
| 99 | 127 | ||
| 100 | 128 | ||
| 101 | func trigger_atbash_trap(): | 129 | func trigger_atbash_trap(): | 
| 102 | var newly_atbash = (atbash_remaining == 0) | 130 | var newly_atbash = atbash_remaining == 0 | 
| 103 | atbash_remaining += 1 | 131 | atbash_remaining += 1 | 
| 104 | 132 | ||
| 105 | if newly_atbash: | 133 | if newly_atbash: | 
| @@ -121,7 +149,7 @@ func deactivate_atbash_trap(): | |||
| 121 | apclient.evaluateSolvability() | 149 | apclient.evaluateSolvability() | 
| 122 | 150 | ||
| 123 | text_dirty = true | 151 | text_dirty = true | 
| 124 | 152 | ||
| 125 | var apclient = global.get_node("Archipelago") | 153 | var apclient = global.get_node("Archipelago") | 
| 126 | apclient.saveLocaldata() | 154 | apclient.saveLocaldata() | 
| 127 | 155 | ||
| @@ -192,23 +220,37 @@ func _tick_slowness(): | |||
| 192 | player.run_speed = orig_run | 220 | player.run_speed = orig_run | 
| 193 | 221 | ||
| 194 | $SlownessTimer.stop() | 222 | $SlownessTimer.stop() | 
| 195 | 223 | ||
| 196 | if slowness_remaining % 5 == 0: | 224 | if slowness_remaining % 5 == 0: | 
| 197 | var apclient = global.get_node("Archipelago") | 225 | var apclient = global.get_node("Archipelago") | 
| 198 | apclient.saveLocaldata() | 226 | apclient.saveLocaldata() | 
| 199 | 227 | ||
| 200 | 228 | ||
| 229 | func _tick_speed_boost(): | ||
| 230 | speed_boosts_remaining -= 1 | ||
| 231 | text_dirty = true | ||
| 232 | |||
| 233 | if speed_boosts_remaining == 0: | ||
| 234 | var player = get_tree().get_root().get_node("Spatial/player") | ||
| 235 | player.walk_speed = orig_walk / 2.0 | ||
| 236 | player.run_speed = orig_run / 2.0 | ||
| 237 | |||
| 238 | $SpeedBoostTimer.stop() | ||
| 239 | |||
| 240 | if speed_boosts_remaining % 5 == 0: | ||
| 241 | var apclient = global.get_node("Archipelago") | ||
| 242 | apclient.saveLocaldata() | ||
| 243 | |||
| 244 | |||
| 201 | func _tick_iceland(): | 245 | func _tick_iceland(): | 
| 202 | iceland_remaining -= 1 | 246 | iceland_remaining -= 1 | 
| 203 | text_dirty = true | 247 | text_dirty = true | 
| 204 | 248 | ||
| 205 | if iceland_remaining == 0: | 249 | if iceland_remaining == 0: | 
| 206 | get_tree().get_root().get_node("Spatial/player/pivot/camera").set_environment( | 250 | get_tree().get_root().get_node("Spatial/player/pivot/camera").set_environment(orig_env) | 
| 207 | orig_env | ||
| 208 | ) | ||
| 209 | 251 | ||
| 210 | $IcelandTimer.stop() | 252 | $IcelandTimer.stop() | 
| 211 | 253 | ||
| 212 | if iceland_remaining % 5 == 0: | 254 | if iceland_remaining % 5 == 0: | 
| 213 | var apclient = global.get_node("Archipelago") | 255 | var apclient = global.get_node("Archipelago") | 
| 214 | apclient.saveLocaldata() | 256 | apclient.saveLocaldata() | 
| @@ -220,9 +262,11 @@ func _process(_delta): | |||
| 220 | if wallcast.is_colliding(): | 262 | if wallcast.is_colliding(): | 
| 221 | var player = get_tree().get_root().get_node("Spatial/player") | 263 | var player = get_tree().get_root().get_node("Spatial/player") | 
| 222 | var puzzlecast = player.get_node("pivot/camera/RayCast_sight") | 264 | var puzzlecast = player.get_node("pivot/camera/RayCast_sight") | 
| 223 | var distance = puzzlecast.get_collision_point().distance_to(wallcast.get_collision_point()) | 265 | var distance = puzzlecast.get_collision_point().distance_to( | 
| 266 | wallcast.get_collision_point() | ||
| 267 | ) | ||
| 224 | should_nbw = (distance < 0.05) | 268 | should_nbw = (distance < 0.05) | 
| 225 | 269 | ||
| 226 | if should_nbw != not_behind_wall: | 270 | if should_nbw != not_behind_wall: | 
| 227 | not_behind_wall = should_nbw | 271 | not_behind_wall = should_nbw | 
| 228 | text_dirty = true | 272 | text_dirty = true | 
| @@ -239,6 +283,10 @@ func _process(_delta): | |||
| 239 | if not text.empty(): | 283 | if not text.empty(): | 
| 240 | text += "\n" | 284 | text += "\n" | 
| 241 | text += "Slowness: %d seconds" % slowness_remaining | 285 | text += "Slowness: %d seconds" % slowness_remaining | 
| 286 | if speed_boosts_remaining > 0: | ||
| 287 | if not text.empty(): | ||
| 288 | text += "\n" | ||
| 289 | text += "Speed Boost: %d seconds" % speed_boosts_remaining | ||
| 242 | if iceland_remaining > 0: | 290 | if iceland_remaining > 0: | 
| 243 | if not text.empty(): | 291 | if not text.empty(): | 
| 244 | text += "\n" | 292 | text += "\n" | 
| diff --git a/Archipelago/load.gd b/Archipelago/load.gd index ce7bba5..4811b47 100644 --- a/Archipelago/load.gd +++ b/Archipelago/load.gd | |||
| @@ -674,6 +674,7 @@ func _load(): | |||
| 674 | # Create the multiplayer node, if needed. | 674 | # Create the multiplayer node, if needed. | 
| 675 | if apclient.enable_multiplayer: | 675 | if apclient.enable_multiplayer: | 
| 676 | var multiplayer_node = apclient.SCRIPT_multiplayer.new() | 676 | var multiplayer_node = apclient.SCRIPT_multiplayer.new() | 
| 677 | multiplayer_node.name = "Multiplayer" | ||
| 677 | multiplayer_node.ghost_mode = true | 678 | multiplayer_node.ghost_mode = true | 
| 678 | add_child(multiplayer_node) | 679 | add_child(multiplayer_node) | 
| 679 | 680 | ||
| diff --git a/Archipelago/multiplayer.gd b/Archipelago/multiplayer.gd index 0bc2241..c2d9875 100644 --- a/Archipelago/multiplayer.gd +++ b/Archipelago/multiplayer.gd | |||
| @@ -1,5 +1,8 @@ | |||
| 1 | extends "res://scripts/multiplayer.gd" | 1 | extends "res://scripts/multiplayer.gd" | 
| 2 | 2 | ||
| 3 | var queued_messages = [] | ||
| 4 | var queued_messages_mutex = Mutex.new() | ||
| 5 | |||
| 3 | 6 | ||
| 4 | func _request_lobby_list(): | 7 | func _request_lobby_list(): | 
| 5 | var apclient = global.get_node("Archipelago") | 8 | var apclient = global.get_node("Archipelago") | 
| @@ -41,3 +44,55 @@ func _update_lobby_members(): | |||
| 41 | if member_id != player_steam_id and member_id in active_lobby_members: | 44 | if member_id != player_steam_id and member_id in active_lobby_members: | 
| 42 | var slot_name = Steam.getLobbyMemberData(active_lobby_id, member_id, "slot_name") | 45 | var slot_name = Steam.getLobbyMemberData(active_lobby_id, member_id, "slot_name") | 
| 43 | active_lobby_members[member_id].steam_name = slot_name | 46 | active_lobby_members[member_id].steam_name = slot_name | 
| 47 | |||
| 48 | |||
| 49 | func say(text): | ||
| 50 | queued_messages_mutex.lock() | ||
| 51 | queued_messages.append(text) | ||
| 52 | queued_messages_mutex.unlock() | ||
| 53 | |||
| 54 | |||
| 55 | func _physics_process(_delta): | ||
| 56 | if queued_messages_mutex.try_lock() == OK: | ||
| 57 | if queued_messages.empty(): | ||
| 58 | queued_messages_mutex.unlock() | ||
| 59 | else: | ||
| 60 | var messages = queued_messages.duplicate() | ||
| 61 | queued_messages = [] | ||
| 62 | queued_messages_mutex.unlock() | ||
| 63 | |||
| 64 | var player = get_tree().get_root().get_node("Spatial/player") | ||
| 65 | var space_state = get_tree().get_root().get_world().direct_space_state | ||
| 66 | var nearby_members = [] | ||
| 67 | for member_id in active_lobby_members.keys(): | ||
| 68 | var other_member = active_lobby_members[member_id] | ||
| 69 | var ray = space_state.intersect_ray( | ||
| 70 | player.global_translation, other_member.global_translation, [player], 0b0101 | ||
| 71 | ) | ||
| 72 | if !("collider" in ray) or ray["collider"] == other_member: | ||
| 73 | # Visible! | ||
| 74 | nearby_members.append(member_id) | ||
| 75 | |||
| 76 | var apclient = global.get_node("Archipelago") | ||
| 77 | var player_name = apclient.get_player_name() | ||
| 78 | for member_id in nearby_members: | ||
| 79 | for msg in messages: | ||
| 80 | _send_p2p_packet( | ||
| 81 | {"solves": [{"say": msg, "from": player_name}]}, | ||
| 82 | member_id, | ||
| 83 | Steam.P2P_SEND_RELIABLE, | ||
| 84 | true | ||
| 85 | ) | ||
| 86 | |||
| 87 | |||
| 88 | # I'm completely hijacking this callback, since we're in ghost mode and it won't be called normally. | ||
| 89 | func _receive_solve(data): | ||
| 90 | if "say" in data: | ||
| 91 | get_tree().get_root().get_node("Spatial/AP_TextClient").parse_printjson( | ||
| 92 | "[LOCAL] [color=#fafad2]%s[/color]: %s" % [data["from"], data["say"]] | ||
| 93 | ) | ||
| 94 | messages.showMessage("[color=#fafad2]%s[/color]: %s" % [data["from"], data["say"]]) | ||
| 95 | |||
| 96 | |||
| 97 | func _send_hi(_discard): | ||
| 98 | pass | ||
| diff --git a/Archipelago/textclient.gd b/Archipelago/textclient.gd index 7bddf38..3abd9e0 100644 --- a/Archipelago/textclient.gd +++ b/Archipelago/textclient.gd | |||
| @@ -25,6 +25,7 @@ func _ready(): | |||
| 25 | label.margin_top = 80 | 25 | label.margin_top = 80 | 
| 26 | label.margin_bottom = 720 | 26 | label.margin_bottom = 720 | 
| 27 | label.scroll_following = true | 27 | label.scroll_following = true | 
| 28 | label.selection_enabled = true | ||
| 28 | panel.add_child(label) | 29 | panel.add_child(label) | 
| 29 | 30 | ||
| 30 | var dynamic_font = DynamicFont.new() | 31 | var dynamic_font = DynamicFont.new() | 
| @@ -51,7 +52,7 @@ func _ready(): | |||
| 51 | 52 | ||
| 52 | func _input(event): | 53 | func _input(event): | 
| 53 | if event is InputEventKey and event.pressed: | 54 | if event is InputEventKey and event.pressed: | 
| 54 | if event.scancode == KEY_TAB: | 55 | if event.scancode == KEY_TAB and !Input.is_key_pressed(KEY_SHIFT): | 
| 55 | if !get_tree().paused: | 56 | if !get_tree().paused: | 
| 56 | is_open = true | 57 | is_open = true | 
| 57 | get_tree().paused = true | 58 | get_tree().paused = true | 
| @@ -84,5 +85,16 @@ func parse_printjson(text): | |||
| 84 | 85 | ||
| 85 | func text_entered(text): | 86 | func text_entered(text): | 
| 86 | var apclient = global.get_node("Archipelago") | 87 | var apclient = global.get_node("Archipelago") | 
| 87 | apclient.say(text.trim_suffix("\n")) | 88 | var cmd = text.trim_suffix("\n") | 
| 89 | if cmd.begins_with("/say "): | ||
| 90 | if apclient.enable_multiplayer: | ||
| 91 | var msg = cmd.trim_prefix("/say ") | ||
| 92 | parse_printjson( | ||
| 93 | "[LOCAL] [color=#ee00ee]%s[/color]: %s" % [apclient.get_player_name(), msg] | ||
| 94 | ) | ||
| 95 | get_tree().get_root().get_node("Spatial/Multiplayer").say(msg) | ||
| 96 | else: | ||
| 97 | parse_printjson("Multiplayer must be enabled to use /say") | ||
| 98 | else: | ||
| 99 | apclient.say(cmd) | ||
| 88 | entry.text = "" | 100 | entry.text = "" | 
| diff --git a/CHANGELOG.md b/CHANGELOG.md index d00999c..6bea522 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md | |||
| @@ -1,5 +1,24 @@ | |||
| 1 | # lingo-archipelago Releases | 1 | # lingo-archipelago Releases | 
| 2 | 2 | ||
| 3 | ## v4.2.1 - 2024-09-21 | ||
| 4 | |||
| 5 | - The text client will no longer open if SHIFT is being held, to prevent | ||
| 6 | conflicts with the Steam Overlay. | ||
| 7 | |||
| 8 | Download: | ||
| 9 | [lingo-archipelago-v4.2.1.zip](https://files.fourisland.com/releases/lingo-archipelago/lingo-archipelago-v4.2.1.zip)<br/> | ||
| 10 | Source: [v4.2.1](https://code.fourisland.com/lingo-archipelago/tag/?h=v4.2.1) | ||
| 11 | |||
| 12 | ## v4.2.0 - 2024-09-20 | ||
| 13 | |||
| 14 | - Added a proximity chat feature. You can use the command "/say" followed by a | ||
| 15 | message in the text client, and it will broadcast the message only to other | ||
| 16 | nearby Lingo players. | ||
| 17 | |||
| 18 | Download: | ||
| 19 | [lingo-archipelago-v4.2.0.zip](https://files.fourisland.com/releases/lingo-archipelago/lingo-archipelago-v4.2.0.zip)<br/> | ||
| 20 | Source: [v4.2.0](https://code.fourisland.com/lingo-archipelago/tag/?h=v4.2.0) | ||
| 21 | |||
| 3 | ## v4.1.0 - 2024-09-02 | 22 | ## v4.1.0 - 2024-09-02 | 
| 4 | 23 | ||
| 5 | - Added an in-game text client, which can be used to talk to other players and | 24 | - Added an in-game text client, which can be used to talk to other players and | 
| diff --git a/README.md b/README.md index a8491d6..dcdc9cd 100644 --- a/README.md +++ b/README.md | |||
| @@ -95,6 +95,11 @@ pick and choose which ones you would like to use. | |||
| 95 | There is also a built-in text client you can use to talk to other players and | 95 | There is also a built-in text client you can use to talk to other players and | 
| 96 | issue commands. You can open and close it by pressing tab. | 96 | issue commands. You can open and close it by pressing tab. | 
| 97 | 97 | ||
| 98 | The command "/say" can be used in the built-in text client to send messages that | ||
| 99 | are only visible to players that you can currently see. Note that this is not | ||
| 100 | symmetric: it is possible that you may see someone who cannot see you back, if, | ||
| 101 | for instance, there is a door in between you and it is only open on your slot. | ||
| 102 | |||
| 98 | ## Frequently Asked Questions | 103 | ## Frequently Asked Questions | 
| 99 | 104 | ||
| 100 | ### What are location checks in this game? | 105 | ### What are location checks in this game? | 
