summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Weipert <git@mail.dweipert.de>2024-12-20 11:42:22 +0100
committerDaniel Weipert <git@mail.dweipert.de>2024-12-20 11:42:22 +0100
commitf4e07d090cded56ebab54363f1b47f1ea45c8682 (patch)
tree616698bb4306184469b92d68d3f74dfb61d02c72
parent75793bd23d275d10d6a0bd8024a7e412b64557ce (diff)
next commitHEADmain
-rw-r--r--.gitignore7
-rw-r--r--client.gd9
-rw-r--r--client_data/.gitkeep (renamed from data/.gitkeep)0
-rw-r--r--constants.gd26
-rw-r--r--extractor/grf.gd12
-rw-r--r--packets/login_failed_packet.gd22
-rw-r--r--packets/map_server/moving_entity_appeared_packet.gd1
-rw-r--r--ui/character_selection_item.gd14
-rw-r--r--ui/character_selection_item.tscn36
-rw-r--r--ui/chat_message_format.gd5
-rw-r--r--ui/chat_window.gd5
-rw-r--r--ui/cursor.tscn2
-rw-r--r--ui/login.gd35
-rw-r--r--ui/login.tscn114
14 files changed, 239 insertions, 49 deletions
diff --git a/.gitignore b/.gitignore
index 669284d..9296307 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,9 +1,10 @@
# Godot 4+ specific ignores
.godot/
+*.gd.uid
/android/
-/data/*.grf
-/data/extracted/
-/data/BGM/
+/client_data/*.grf
+/client_data/data/
+/client_data/BGM/
/extractor/test/
diff --git a/client.gd b/client.gd
index 5348117..0d9766b 100644
--- a/client.gd
+++ b/client.gd
@@ -11,17 +11,18 @@ var character: Dictionary = {
func _ready() -> void:
- #var grf = GRF.open("res://data/data.grf")
+ #var grf = GRF.open("res://client_data/data.grf")
+ #grf.extract()
#grf.convert()#"user://data")
- #Sprite.from_bytes(FileAccess.get_file_as_bytes("res://data/extracted/data/sprite/cursors.spr"))
+ #Sprite.from_bytes(FileAccess.get_file_as_bytes("res://client_data/data/sprite/cursors.spr"))
#ActionFormat.from_bytes(
#ByteStream.from_bytes(
- #FileAccess.get_file_as_bytes("res://data/extracted/data/sprite/cursors.act")
+ #FileAccess.get_file_as_bytes("res://client_data/data/sprite/cursors.act")
#)
#)
GATFormat.from_bytes(
ByteStream.from_bytes(
- FileAccess.get_file_as_bytes("res://data/extracted/data/int_land02.gat")
+ FileAccess.get_file_as_bytes("res://client_data/data/int_land02.gat")
)
)
diff --git a/data/.gitkeep b/client_data/.gitkeep
index c059196..c059196 100644
--- a/data/.gitkeep
+++ b/client_data/.gitkeep
diff --git a/constants.gd b/constants.gd
index 41f048f..5bb518a 100644
--- a/constants.gd
+++ b/constants.gd
@@ -21,6 +21,12 @@ enum PinCodeState {
Wrong = 8,
}
+enum LoginFailedReason {
+ ServerClosed = 1,
+ AlreadyLoggedIn = 2,
+ AlreadyOnline = 8,
+}
+
enum StatusType {
Weight,
MaximumWeight,
@@ -52,6 +58,15 @@ enum EmotionType {
# ... TODO
}
+enum Job {
+ Novice = 0,
+ Swordman = 1,
+ Magician = 2,
+ Archer = 3,
+ Acolyte = 4,
+}
+
+
static var PacketDB = {
#LoginServerLoginPacket.HEADER: LoginServerLoginPacket,
LoginServerLoginSuccessPacket.HEADER: LoginServerLoginSuccessPacket,
@@ -59,6 +74,7 @@ static var PacketDB = {
CharacterServerLoginSuccessPacket.HEADER: CharacterServerLoginSuccessPacket,
CharacterServerLoginSuccessCharacterListPacket.HEADER: CharacterServerLoginSuccessCharacterListPacket,
CharacterListSizePacket.HEADER: CharacterListSizePacket,
+ LoginFailedPacket.HEADER: LoginFailedPacket,
BlockCharacterPacket.HEADER: BlockCharacterPacket,
PinCodeStatePacket.HEADER: PinCodeStatePacket,
#RequestCharacterListPacket.HEADER: RequestCharacterListPacket,
@@ -127,15 +143,15 @@ class FilePaths:
static func get_job_path(job_id: int) -> String:
match job_id:
- 0: # NOVICE
+ Job.Novice: # NOVICE
return "Ãʺ¸ÀÚ"
- 1: # SWORDMAN
+ Job.Swordman: # SWORDMAN
return "°Ë»Ç"
- 2: # MAGICIAN
+ Job.Magician: # MAGICIAN
return "À§Àúµå"
- 3: # ARCHER
+ Job.Archer: # ARCHER
return "±Ã¼Ö"
- 4: # ACOLYTE
+ Job.Acolyte: # ACOLYTE
return "¼ºÁ÷ÀÚ"
5: # MERCHANT
return "»ÓÀÎ"
diff --git a/extractor/grf.gd b/extractor/grf.gd
index 9917a74..08f72ee 100644
--- a/extractor/grf.gd
+++ b/extractor/grf.gd
@@ -190,23 +190,25 @@ static func open(path: String):
return grf
-func extract(destination: String = "res://data"):
+func extract(destination: String = "user://client_data"):
+ DirAccess.make_dir_recursive_absolute(destination)
+
for file_entry in file_entries:
var file_path: String = file_entry.get_file_path()
var base_directory = DirAccess.open(destination)
- base_directory.make_dir_recursive("extracted/" + file_path.get_base_dir())
+ base_directory.make_dir_recursive(file_path.get_base_dir())
- var file = FileAccess.open("%s/extracted/%s" % [destination, file_path], FileAccess.WRITE_READ)
+ var file = FileAccess.open("%s/%s" % [destination, file_path], FileAccess.WRITE_READ)
file.store_buffer(file_entry.get_contents(file_access))
-func convert(destination: String = "res://data"):
+func convert(destination: String = "res://client_data"):
for file_entry in file_entries:
var file_path: String = file_entry.get_file_path()
var base_directory = DirAccess.open(destination)
- var base_directory_path = "extracted/%s" % file_path.get_base_dir()
+ var base_directory_path = "%s" % file_path.get_base_dir()
base_directory.make_dir_recursive(base_directory_path)
base_directory.change_dir(base_directory_path)
diff --git a/packets/login_failed_packet.gd b/packets/login_failed_packet.gd
new file mode 100644
index 0000000..93ebf23
--- /dev/null
+++ b/packets/login_failed_packet.gd
@@ -0,0 +1,22 @@
+## rAthena References:
+## - clif_authfail_fd
+class_name LoginFailedPacket
+extends Packet
+
+
+const HEADER := 0x0081
+const BYTE_LENGTH := 3
+
+
+## Byte Type: u8
+## Byte Length: 1
+@warning_ignore("enum_variable_without_default")
+var reason: Constants.LoginFailedReason
+
+
+static func from_bytes(bytes: PackedByteArray) -> LoginFailedPacket:
+ var packet = LoginFailedPacket.new()
+
+ packet.reason = bytes.decode_u8(2)
+
+ return packet
diff --git a/packets/map_server/moving_entity_appeared_packet.gd b/packets/map_server/moving_entity_appeared_packet.gd
index 43b19ae..50afaf5 100644
--- a/packets/map_server/moving_entity_appeared_packet.gd
+++ b/packets/map_server/moving_entity_appeared_packet.gd
@@ -1,5 +1,6 @@
## rAthena References:
## - ZC_NOTIFY_MOVEENTRY11
+## - clif_set_unit_walking
class_name MovingEntityAppearedPacket
extends Packet
diff --git a/ui/character_selection_item.gd b/ui/character_selection_item.gd
index 67ebea7..59dbdf8 100644
--- a/ui/character_selection_item.gd
+++ b/ui/character_selection_item.gd
@@ -1,20 +1,22 @@
+class_name CharacterSelectionItem
extends Control
-signal pressed
+signal activated
+signal selected
func initialize_with_info(info: CharacterInformation):
%Head.texture = load(
"%s/%s/000.png" % [
- "res://data/extracted/data/sprite",
+ "res://client_data/data/sprite",
Constants.FilePaths.get_player_head(info.gender, info.head),
]
)
%Body.texture = load(
"%s/%s/000.png" % [
- "res://data/extracted/data/sprite",
+ "res://client_data/data/sprite",
Constants.FilePaths.get_player_body(info.gender, info.job),
]
)
@@ -24,4 +26,8 @@ func initialize_with_info(info: CharacterInformation):
func _on_gui_input(event: InputEvent) -> void:
if event.is_pressed():
- pressed.emit()
+ activated.emit()
+
+
+func _on_login_button_pressed() -> void:
+ selected.emit()
diff --git a/ui/character_selection_item.tscn b/ui/character_selection_item.tscn
index 33fed42..f6e3055 100644
--- a/ui/character_selection_item.tscn
+++ b/ui/character_selection_item.tscn
@@ -1,20 +1,31 @@
[gd_scene load_steps=4 format=3 uid="uid://rrd131rq74n5"]
-[ext_resource type="Script" uid="uid://7gt65vxl14n2" path="res://ui/character_selection_item.gd" id="1_25yur"]
-[ext_resource type="Texture2D" uid="uid://danymuvfjf4o1" path="res://data/extracted/data/sprite/Àΰ£Á·/¸Ó¸®Åë/³²/16_³²/000.png" id="2_aqbfs"]
-[ext_resource type="Texture2D" uid="uid://cwqgdd00sf7pu" path="res://data/extracted/data/sprite/Àΰ£Á·/¸öÅë/³²/Ãʺ¸ÀÚ_³²/000.png" id="3_xv3pn"]
+[ext_resource type="Script" uid="uid://bsglhorusc7ug" path="res://ui/character_selection_item.gd" id="1_25yur"]
+[ext_resource type="Texture2D" uid="uid://danymuvfjf4o1" path="res://client_data/data/sprite/Àΰ£Á·/¸Ó¸®Åë/³²/16_³²/000.png" id="2_aqbfs"]
+[ext_resource type="Texture2D" uid="uid://cwqgdd00sf7pu" path="res://client_data/data/sprite/Àΰ£Á·/¸öÅë/³²/Ãʺ¸ÀÚ_³²/000.png" id="3_xv3pn"]
-[node name="CharacterSelectionItem" type="VBoxContainer"]
-offset_bottom = 4.0
+[node name="CharacterSelectionItem" type="PanelContainer"]
+offset_right = 150.0
+offset_bottom = 163.0
mouse_default_cursor_shape = 2
script = ExtResource("1_25yur")
-[node name="Sprite" type="VBoxContainer" parent="."]
+[node name="MarginContainer" type="MarginContainer" parent="."]
+layout_mode = 2
+theme_override_constants/margin_left = 4
+theme_override_constants/margin_top = 4
+theme_override_constants/margin_right = 4
+theme_override_constants/margin_bottom = 4
+
+[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer"]
+layout_mode = 2
+
+[node name="Sprite" type="VBoxContainer" parent="MarginContainer/VBoxContainer"]
layout_mode = 2
size_flags_vertical = 3
theme_override_constants/separation = -8
-[node name="Head" type="TextureRect" parent="Sprite"]
+[node name="Head" type="TextureRect" parent="MarginContainer/VBoxContainer/Sprite"]
unique_name_in_owner = true
z_index = 1
texture_filter = 1
@@ -22,16 +33,23 @@ layout_mode = 2
texture = ExtResource("2_aqbfs")
stretch_mode = 3
-[node name="Body" type="TextureRect" parent="Sprite"]
+[node name="Body" type="TextureRect" parent="MarginContainer/VBoxContainer/Sprite"]
unique_name_in_owner = true
texture_filter = 1
layout_mode = 2
texture = ExtResource("3_xv3pn")
stretch_mode = 3
-[node name="Name" type="Label" parent="."]
+[node name="Name" type="Label" parent="MarginContainer/VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
text = "Name"
+horizontal_alignment = 1
+
+[node name="LoginButton" type="Button" parent="MarginContainer/VBoxContainer"]
+layout_mode = 2
+mouse_default_cursor_shape = 2
+text = "Login"
[connection signal="gui_input" from="." to="." method="_on_gui_input"]
+[connection signal="pressed" from="MarginContainer/VBoxContainer/LoginButton" to="." method="_on_login_button_pressed"]
diff --git a/ui/chat_message_format.gd b/ui/chat_message_format.gd
new file mode 100644
index 0000000..b53ffe3
--- /dev/null
+++ b/ui/chat_message_format.gd
@@ -0,0 +1,5 @@
+class_name ChatMessageFormat
+extends Resource
+
+var color: Color
+var size: int
diff --git a/ui/chat_window.gd b/ui/chat_window.gd
index 640a257..d43791f 100644
--- a/ui/chat_window.gd
+++ b/ui/chat_window.gd
@@ -56,8 +56,3 @@ func _on_broadcast_formatted_message_packet_received(packet: BroadcastFormattedM
format.size = packet.font_size
add_message(packet.message, format)
-
-
-class ChatMessageFormat extends Resource:
- var color: Color
- var size: int
diff --git a/ui/cursor.tscn b/ui/cursor.tscn
index eb06186..19c31f2 100644
--- a/ui/cursor.tscn
+++ b/ui/cursor.tscn
@@ -1,7 +1,7 @@
[gd_scene load_steps=3 format=3 uid="uid://n0y3fpb8j820"]
[ext_resource type="Script" uid="uid://b50tmfud8m4bx" path="res://ui/cursor.gd" id="1_gyqds"]
-[ext_resource type="PackedScene" uid="uid://biyt4m7dnch83" path="res://data/extracted/data/sprite/cursors/actions.tscn" id="2_6gt4s"]
+[ext_resource type="PackedScene" uid="uid://biyt4m7dnch83" path="res://client_data/data/sprite/cursors/actions.tscn" id="2_6gt4s"]
[node name="Cursor" type="Node2D"]
script = ExtResource("1_gyqds")
diff --git a/ui/login.gd b/ui/login.gd
index 540355f..73b294c 100644
--- a/ui/login.gd
+++ b/ui/login.gd
@@ -9,7 +9,7 @@ var current_character_information: CharacterInformation
func _ready() -> void:
switch_screen(%Login)
- $BackgroundMusic.play()
+ #$BackgroundMusic.play()
%ChatWindow.visible = false
@@ -43,6 +43,11 @@ func _on_login_pressed() -> void:
select_character_server.pressed.connect(_on_character_server_login_pressed.bind(info))
%CharacterServerList.add_child(select_character_server)
+ # TODO: if setting is true to skip character server selection when only one server is available
+ #if character_server_information.size() == 1:
+ #(%CharacterServerList.get_child(0) as Button).pressed.emit()
+ #else:
+ #switch_screen(%CharacterServer)
switch_screen(%CharacterServer)
@@ -63,22 +68,36 @@ func _on_character_server_login_pressed(character_server_info: CharacterServerIn
var response = await Network.character_server.received_packet
if response is CharacterSelectionFailedPacket:
print("character server login failed")
- %ChatWindow.add_message("character server login failed")
+ %ChatWindow.add_message("character server login failed", ChatMessageFormat.new())
return
get_tree().root.add_child(Network.character_server.get_keep_alive_timer())
var character_list: CharacterServerLoginSuccessCharacterListPacket = await Network.character_server.logged_in_character_list
+ for node in %CharacterList.get_children():
+ node.queue_free()
+
for slot_idx in character_list.character_information.size():
var info: CharacterInformation = character_list.character_information[slot_idx]
var character = preload("res://ui/character_selection_item.tscn").instantiate()
character.initialize_with_info(info)
- character.pressed.connect(func():
+ character.activated.connect(func():
+ $CharacterSelection/VBoxContainer/HBoxContainer/CharacterInfo/Label.text = info.name
+ $CharacterSelection/VBoxContainer/HBoxContainer/CharacterInfo/HBoxContainer/Label2.text = str(info.level)
+ $CharacterSelection/VBoxContainer/HBoxContainer/CharacterInfo/HBoxContainer2/Label2.text = str(info.job_level)
+ $CharacterSelection/VBoxContainer/HBoxContainer/CharacterInfo/HBoxContainer4/Label2.text = Constants.Job.find_key(info.job)
+ $CharacterSelection/VBoxContainer/HBoxContainer/CharacterInfo/HBoxContainer3/Label2.text = str(info.strength)
+ )
+ character.selected.connect(func():
current_character_information = info
_on_character_selected_pressed(slot_idx)
)
%CharacterList.add_child(character)
+
+ # pre-select first character
+ if slot_idx == 0:
+ character.activated.emit()
switch_screen(%CharacterSelection)
@@ -118,3 +137,13 @@ func _on_character_selected_pressed(slot_idx: int):
Network.map_server.send(map_loaded_packet)
# TODO: check which map server packets to send next
+
+
+func _on_character_server_back_button_pressed() -> void:
+ $ButtonClickSound.play()
+ switch_screen(%Login)
+
+
+func _on_character_selection_back_button_pressed() -> void:
+ $ButtonClickSound.play()
+ switch_screen(%CharacterServer)
diff --git a/ui/login.tscn b/ui/login.tscn
index cc02910..c38df26 100644
--- a/ui/login.tscn
+++ b/ui/login.tscn
@@ -1,8 +1,8 @@
[gd_scene load_steps=6 format=4 uid="uid://dser74lcd3a4g"]
-[ext_resource type="Script" uid="uid://br01f7npuosll" path="res://ui/login.gd" id="1_1m5cv"]
+[ext_resource type="Script" uid="uid://dqswsdaamfhbq" path="res://ui/login.gd" id="1_1m5cv"]
[ext_resource type="Texture2D" uid="uid://cxd6dnc7s17vg" path="res://ui/backround.jpg" id="2_elmti"]
-[ext_resource type="AudioStream" uid="uid://br8ujl4uxv14a" path="res://data/BGM/01.mp3" id="3_2nukd"]
+[ext_resource type="AudioStream" uid="uid://br8ujl4uxv14a" path="res://client_data/BGM/01.mp3" id="3_2nukd"]
[ext_resource type="PackedScene" uid="uid://c8uqw08hxfqlu" path="res://ui/chat_window.tscn" id="4_ah2a1"]
[sub_resource type="AudioStreamWAV" id="AudioStreamWAV_f4kp2"]
@@ -40,30 +40,41 @@ anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
-[node name="VBoxContainer" type="VBoxContainer" parent="Login"]
+[node name="PanelContainer" type="PanelContainer" parent="Login"]
layout_mode = 2
-[node name="Username" type="LineEdit" parent="Login/VBoxContainer"]
+[node name="MarginContainer" type="MarginContainer" parent="Login/PanelContainer"]
+layout_mode = 2
+theme_override_constants/margin_left = 8
+theme_override_constants/margin_top = 8
+theme_override_constants/margin_right = 8
+theme_override_constants/margin_bottom = 8
+
+[node name="VBoxContainer" type="VBoxContainer" parent="Login/PanelContainer/MarginContainer"]
+layout_mode = 2
+
+[node name="Username" type="LineEdit" parent="Login/PanelContainer/MarginContainer/VBoxContainer"]
unique_name_in_owner = true
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
text = "dweipert"
placeholder_text = "Username"
-[node name="Password" type="LineEdit" parent="Login/VBoxContainer"]
+[node name="Password" type="LineEdit" parent="Login/PanelContainer/MarginContainer/VBoxContainer"]
unique_name_in_owner = true
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
text = "ragnarok"
placeholder_text = "Password"
-[node name="Login" type="Button" parent="Login/VBoxContainer"]
+[node name="Login" type="Button" parent="Login/PanelContainer/MarginContainer/VBoxContainer"]
layout_mode = 2
mouse_default_cursor_shape = 2
text = "Login"
[node name="CharacterServer" type="CenterContainer" parent="."]
unique_name_in_owner = true
+visible = false
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
@@ -71,9 +82,30 @@ anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
-[node name="CharacterServerList" type="VBoxContainer" parent="CharacterServer"]
+[node name="PanelContainer" type="PanelContainer" parent="CharacterServer"]
+custom_minimum_size = Vector2(100, 150)
+layout_mode = 2
+
+[node name="MarginContainer" type="MarginContainer" parent="CharacterServer/PanelContainer"]
+layout_mode = 2
+theme_override_constants/margin_left = 8
+theme_override_constants/margin_top = 8
+theme_override_constants/margin_right = 8
+theme_override_constants/margin_bottom = 8
+
+[node name="VBoxContainer" type="VBoxContainer" parent="CharacterServer/PanelContainer/MarginContainer"]
+layout_mode = 2
+
+[node name="CharacterServerList" type="VBoxContainer" parent="CharacterServer/PanelContainer/MarginContainer/VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
+size_flags_vertical = 3
+
+[node name="CharacterServerBackButton" type="Button" parent="CharacterServer/PanelContainer/MarginContainer/VBoxContainer"]
+layout_mode = 2
+size_flags_horizontal = 8
+mouse_default_cursor_shape = 2
+text = "Cancel"
[node name="CharacterSelection" type="CenterContainer" parent="."]
unique_name_in_owner = true
@@ -85,11 +117,72 @@ anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
-[node name="CharacterList" type="GridContainer" parent="CharacterSelection"]
+[node name="VBoxContainer" type="VBoxContainer" parent="CharacterSelection"]
+layout_mode = 2
+
+[node name="HBoxContainer" type="HBoxContainer" parent="CharacterSelection/VBoxContainer"]
+layout_mode = 2
+
+[node name="CharacterList" type="GridContainer" parent="CharacterSelection/VBoxContainer/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
columns = 5
+[node name="CharacterInfo" type="VBoxContainer" parent="CharacterSelection/VBoxContainer/HBoxContainer"]
+custom_minimum_size = Vector2(75, 0)
+layout_mode = 2
+
+[node name="Label" type="Label" parent="CharacterSelection/VBoxContainer/HBoxContainer/CharacterInfo"]
+layout_mode = 2
+text = "Info"
+horizontal_alignment = 1
+
+[node name="HBoxContainer" type="HBoxContainer" parent="CharacterSelection/VBoxContainer/HBoxContainer/CharacterInfo"]
+layout_mode = 2
+
+[node name="Label" type="Label" parent="CharacterSelection/VBoxContainer/HBoxContainer/CharacterInfo/HBoxContainer"]
+layout_mode = 2
+text = "Base Level:"
+
+[node name="Label2" type="Label" parent="CharacterSelection/VBoxContainer/HBoxContainer/CharacterInfo/HBoxContainer"]
+layout_mode = 2
+
+[node name="HBoxContainer2" type="HBoxContainer" parent="CharacterSelection/VBoxContainer/HBoxContainer/CharacterInfo"]
+layout_mode = 2
+
+[node name="Label" type="Label" parent="CharacterSelection/VBoxContainer/HBoxContainer/CharacterInfo/HBoxContainer2"]
+layout_mode = 2
+text = "Job Level:"
+
+[node name="Label2" type="Label" parent="CharacterSelection/VBoxContainer/HBoxContainer/CharacterInfo/HBoxContainer2"]
+layout_mode = 2
+
+[node name="HBoxContainer4" type="HBoxContainer" parent="CharacterSelection/VBoxContainer/HBoxContainer/CharacterInfo"]
+layout_mode = 2
+
+[node name="Label" type="Label" parent="CharacterSelection/VBoxContainer/HBoxContainer/CharacterInfo/HBoxContainer4"]
+layout_mode = 2
+text = "Job:"
+
+[node name="Label2" type="Label" parent="CharacterSelection/VBoxContainer/HBoxContainer/CharacterInfo/HBoxContainer4"]
+layout_mode = 2
+
+[node name="HBoxContainer3" type="HBoxContainer" parent="CharacterSelection/VBoxContainer/HBoxContainer/CharacterInfo"]
+layout_mode = 2
+
+[node name="Label" type="Label" parent="CharacterSelection/VBoxContainer/HBoxContainer/CharacterInfo/HBoxContainer3"]
+layout_mode = 2
+text = "Str:"
+
+[node name="Label2" type="Label" parent="CharacterSelection/VBoxContainer/HBoxContainer/CharacterInfo/HBoxContainer3"]
+layout_mode = 2
+
+[node name="CharacterSelectionBackButton" type="Button" parent="CharacterSelection/VBoxContainer"]
+layout_mode = 2
+size_flags_horizontal = 8
+mouse_default_cursor_shape = 2
+text = "Cancel"
+
[node name="ButtonClickSound" type="AudioStreamPlayer" parent="."]
stream = SubResource("AudioStreamWAV_f4kp2")
@@ -98,7 +191,6 @@ stream = ExtResource("3_2nukd")
[node name="ChatWindow" parent="." instance=ExtResource("4_ah2a1")]
unique_name_in_owner = true
-visible = false
layout_mode = 1
anchors_preset = -1
anchor_top = 0.829
@@ -109,4 +201,6 @@ offset_right = -31.0
offset_bottom = 0.0
grow_vertical = 0
-[connection signal="pressed" from="Login/VBoxContainer/Login" to="." method="_on_login_pressed"]
+[connection signal="pressed" from="Login/PanelContainer/MarginContainer/VBoxContainer/Login" to="." method="_on_login_pressed"]
+[connection signal="pressed" from="CharacterServer/PanelContainer/MarginContainer/VBoxContainer/CharacterServerBackButton" to="." method="_on_character_server_back_button_pressed"]
+[connection signal="pressed" from="CharacterSelection/VBoxContainer/CharacterSelectionBackButton" to="." method="_on_character_selection_back_button_pressed"]