diff options
author | Daniel Weipert <git@mail.dweipert.de> | 2025-04-07 11:45:05 +0200 |
---|---|---|
committer | Daniel Weipert <git@mail.dweipert.de> | 2025-04-07 11:45:05 +0200 |
commit | f3d360e022fce829370c7d916abe98083b14818c (patch) | |
tree | 4ac9f886b45a9482dcd42e991e85ab2e4bea3dbc | |
parent | bd77c88efc9327805b6f6fd83fa0492ed59d0f9a (diff) |
37 files changed, 1068 insertions, 186 deletions
diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..83bbb9d --- /dev/null +++ b/Readme.md @@ -0,0 +1,3 @@ +- https://wiki.herc.ws/wiki/Data_Folder_Structure +- https://github.com/Doddler/RagnarokRebuild/blob/7933dd2d2ef512d58b9f12fd5d9f76df44d0765e/RebuildClient/Assets/Scripts/MapEditor/Editor/RagnarokModelLoader.cs#L267 +- https://github.com/Doddler/RagnarokRebuild/blob/7933dd2d2ef512d58b9f12fd5d9f76df44d0765e/RebuildClient/Assets/Scripts/MapEditor/Editor/RagnarokWorldSceneBuilder.cs#L332 diff --git a/byte_stream.gd b/byte_stream.gd index 219e977..5477422 100644 --- a/byte_stream.gd +++ b/byte_stream.gd @@ -100,3 +100,12 @@ func get_string_from_utf8(length: int) -> String: func get_string_from_ascii(length: int) -> String: return get_buffer(length).bytes.get_string_from_ascii() + +func get_string_from_ro(length: int) -> String: + var buffer := get_buffer(length).bytes + Engine.print_error_messages = false + var string := buffer.get_string_from_multibyte_char("EUC-KR") + Engine.print_error_messages = true + if string.is_empty(): + return buffer.get_string_from_ascii() + return string diff --git a/constants.gd b/constants.gd index e495322..28c5ab9 100644 --- a/constants.gd +++ b/constants.gd @@ -27,6 +27,25 @@ enum LoginFailedReason { AlreadyOnline = 8, } +enum LoginFailedReason2 { + UnregisteredId, + IncorrectPassword, + IdExpired, + RejectedFromServer, + BlockedByGMTeam, + GameOutdated, + LoginProhibitedUntil, + ServerFull, + CompanyAccountLimitReached, +} + +enum CharacterCreationFailedReason { + CharacterNameAlreadyInUse, + NotOldEnough, + NotAllowedToUseSlot = 3, + CharacterCreationFailed = 255, +} + enum StatusType { Weight, MaximumWeight, @@ -94,11 +113,16 @@ static var PacketDB = { CharacterServerLoginSuccessCharacterListPacket.HEADER: CharacterServerLoginSuccessCharacterListPacket, CharacterListSizePacket.HEADER: CharacterListSizePacket, LoginFailedPacket.HEADER: LoginFailedPacket, + LoginFailedPacket2.HEADER: LoginFailedPacket2, BlockCharacterPacket.HEADER: BlockCharacterPacket, PinCodeStatePacket.HEADER: PinCodeStatePacket, RequestCharacterListSuccessPacket.HEADER: RequestCharacterListSuccessPacket, CharacterSelectionSuccessPacket.HEADER: CharacterSelectionSuccessPacket, CharacterSelectionFailedPacket.HEADER: CharacterSelectionFailedPacket, + CreateCharacterPacket.HEADER: CreateCharacterPacket, + CreateCharacterSuccessPacket.HEADER: CreateCharacterSuccessPacket, + CharacterCreationFailedPacket.HEADER: CharacterCreationFailedPacket, + MapServerLoginSuccessPacket.HEADER: MapServerLoginSuccessPacket, FriendListPacket.HEADER: FriendListPacket, ServerMessagePacket.HEADER: ServerMessagePacket, @@ -139,11 +163,11 @@ static var PacketDB = { class FilePaths: - const female := "¿©" - const male := "³²" + const female := "여" + const male := "남" - const player_head := "Àΰ£Á·/¸Ó¸®Åë" - const player_body := "Àΰ£Á·/¸öÅë" + const player_head := "인간족/머리통" + const player_body := "인간족/몸통" const male_head_lookup := [2, 2, 1, 7, 5, 4, 3, 6, 8, 9, 10, 12, 11] const female_head_lookup := [2, 2, 4, 7, 1, 5, 3, 6, 12, 10, 9, 11, 8] @@ -159,33 +183,33 @@ class FilePaths: static func get_job_path(job_id: int) -> String: match job_id: Job.Novice: # NOVICE - return "Ãʺ¸ÀÚ" + return "초보자" Job.Swordman: # SWORDMAN - return "°Ë»Ç" + return "검사" Job.Magician: # MAGICIAN - return "À§Àúµå" + return "마법사" Job.Archer: # ARCHER - return "±Ã¼Ö" + return "궁수" Job.Acolyte: # ACOLYTE - return "¼ºÁ÷ÀÚ" + return "성직자" 5: # MERCHANT - return "»ÓÀÎ" + return "상인" 6: # THIEF - return "µµµÏ" + return "도둑" 7: # KNIGHT - return "±â»ç" + return "기사" 8: # PRIEST - return "¼ºÅõ»ç" + return "성투사" 9: # WIZARD - return "¸¶¹Ý»Ç" + return "위저드" 10: # BLACKSMITH - return "Á¦Ã¶°ø" + return "제철공" 11: # HUNTER - return "ÇåÅÍ" + return "헌터" # ... TODO _: # NOVICE - return "Ãʺ¸ÀÚ" + return "초보자" static func get_player_head(gender: Gender, head_id: int) -> String: diff --git a/data_models/login_character_list.gd b/data_models/login_character_list.gd index 8a8d7d5..25a94c3 100644 --- a/data_models/login_character_list.gd +++ b/data_models/login_character_list.gd @@ -35,3 +35,7 @@ func get_info_for_slot(slot_idx: int): return info return null + + +func add_character_information(info: CharacterInformation) -> void: + character_information.append(info) diff --git a/entities/player.tscn b/entities/player.tscn index 805cd45..b9c35b7 100644 --- a/entities/player.tscn +++ b/entities/player.tscn @@ -1,8 +1,8 @@ [gd_scene load_steps=4 format=3 uid="uid://b2c5mpkafk8q6"] [ext_resource type="Script" uid="uid://caid7hva3kg2i" path="res://entities/player.gd" id="1_merdl"] -[ext_resource type="Texture2D" uid="uid://danymuvfjf4o1" path="res://client_data/data/sprite/Àΰ£Á·/¸Ó¸®Åë/³²/16_³²/000.png" id="2_b0kkn"] -[ext_resource type="Texture2D" uid="uid://cwqgdd00sf7pu" path="res://client_data/data/sprite/Àΰ£Á·/¸öÅë/³²/Ãʺ¸ÀÚ_³²/000.png" id="3_e4p34"] +[ext_resource type="Texture2D" uid="uid://ci2liot5s8jnb" path="res://client_data/data/sprite/인간족/머리통/남/16_남/000.png" id="2_e4p34"] +[ext_resource type="Texture2D" uid="uid://be3ax80esna7b" path="res://client_data/data/sprite/인간족/몸통/남/초보자_남/000.png" id="3_rfe5m"] [node name="Player" type="CharacterBody3D"] script = ExtResource("1_merdl") @@ -14,9 +14,9 @@ transform = Transform3D(1, 0, 0, 0, 0.258819, 0.965926, 0, -0.965926, 0.258819, unique_name_in_owner = true transform = Transform3D(25, 0, 0, 0, 6.47048, 24.1481, 0, -24.1481, 6.47048, 0, 0, 0) offset = Vector2(0, 43) -texture = ExtResource("2_b0kkn") +texture = ExtResource("2_e4p34") [node name="Body" type="Sprite3D" parent="."] unique_name_in_owner = true transform = Transform3D(25, 0, 0, 0, 6.47048, 24.1481, 0, -24.1481, 6.47048, 0, 0, 0) -texture = ExtResource("3_e4p34") +texture = ExtResource("3_rfe5m") diff --git a/extractor/extractor_interface.gd b/extractor/extractor_interface.gd index 3afedfd..4d74a20 100644 --- a/extractor/extractor_interface.gd +++ b/extractor/extractor_interface.gd @@ -2,9 +2,11 @@ extends Control func _ready() -> void: - #var grf = GRF.open("res://client_data/data.grf") - #grf.extract()#"user://client_data") - #grf.convert()#"user://client_data") + pass + + var grf = GRF.open("res://client_data/data.grf") + #grf.extract("res://client_data") + grf.convert("res://client_data") #Sprite.from_bytes(FileAccess.get_file_as_bytes("res://client_data/data/sprite/cursors.spr")) #ActionFormat.from_bytes( @@ -22,12 +24,12 @@ func _ready() -> void: #FileAccess.get_file_as_bytes("res://client_data/data/int_land02.gnd") #) #) - var rsw = RSWFormat.from_bytes( - ByteStream.from_bytes( - #FileAccess.get_file_as_bytes("res://client_data/data/int_land02.rsw") - FileAccess.get_file_as_bytes("res://client_data/data/pay_dun00.rsw") - ) - ) + #var rsw = RSWFormat.from_bytes( + #ByteStream.from_bytes( + ##FileAccess.get_file_as_bytes("res://client_data/data/int_land02.rsw") + #FileAccess.get_file_as_bytes("res://client_data/data/pay_dun00.rsw") + #) + #) #RSMFormat.from_bytes( #ByteStream.from_bytes( ##FileAccess.get_file_as_bytes("res://client_data/data/model/prontera/chair_01.rsm") @@ -37,7 +39,7 @@ func _ready() -> void: #) #) - var scene_root := rsw.convert("pay_dun00", "res://client_data") - var scene := PackedScene.new() - scene.pack(scene_root) - ResourceSaver.save(scene, "res://extractor/test/pay_dun00.tscn") + #var scene_root := rsw.convert("pay_dun00", "res://client_data") + #var scene := PackedScene.new() + #scene.pack(scene_root) + #ResourceSaver.save(scene, "res://extractor/test/pay_dun00.tscn") diff --git a/extractor/gnd_format.gd b/extractor/gnd_format.gd index faad9ae..c49bce6 100644 --- a/extractor/gnd_format.gd +++ b/extractor/gnd_format.gd @@ -91,7 +91,7 @@ static func from_bytes(bytes: ByteStream) -> GNDFormat: gnd_format.texture_paths = [] for _n in gnd_format.texture_count: gnd_format.texture_paths.append( - bytes.get_string_from_ascii(gnd_format.texture_path_length) + bytes.get_string_from_ro(gnd_format.texture_path_length) ) gnd_format.light_map_slice_count = bytes.decode_s32() @@ -162,6 +162,10 @@ func convert(data_path: String) -> GridMap: var cubes := get_cubes() + var cache := {} + # TODO: use texture_index and surface uvs as key + # TODO: for deduplication of cell items (as long as other sides aren't accounted for..) + for x in width: for y in height: var cube = cubes[x + y * width] diff --git a/extractor/grf.gd b/extractor/grf.gd index fd0e6f7..5b7046f 100644 --- a/extractor/grf.gd +++ b/extractor/grf.gd @@ -156,7 +156,7 @@ class FileEntry: var file_access: FileAccess -static func open(path: String): +static func open(path: String) -> GRF: var grf = GRF.new() grf.file_access = FileAccess.open(path, FileAccess.ModeFlags.READ) @@ -227,12 +227,17 @@ func convert(destination: String = "res://client_data"): # BMP if file_path.ends_with(".bmp"): + #continue if not FileAccess.file_exists("%s/%s" % [destination, file_path]): continue # load existing bmp files, so language specific overwrites are kept var texture: CompressedTexture2D = load("%s/%s" % [destination, file_path]) + if not texture: + # TODO: check if .godot/imported file is there (alrdy sufficient?) + continue + var texture_image := texture.get_image() texture_image.decompress() var image := BMPTexture.convert_image( @@ -241,18 +246,19 @@ func convert(destination: String = "res://client_data"): ) image.save_png("%s/%s" % [destination, file_path.replace(".bmp", ".png")]) + continue # Sprite.spr and Action.act - var player_head_path_part = "¸Ó¸®Åë" - var player_body_path_part = "¸öÅë" + var player_head_path_part = "머리통" + var player_body_path_part = "몸통" - if file_path.ends_with(".spr") and file_path.contains(player_head_path_part): + if file_path.ends_with(".spr"): #and (file_path.contains(player_head_path_part) or file_path.contains(player_body_path_part)): continue var sprite = SpriteFormat.from_bytes(file_entry.get_contents(file_access)) sprite.save_to_file(base_file_directory_path) - elif file_path.ends_with(".act") and file_path.contains(player_head_path_part): #or file_path.contains(player_body_path_part): + elif file_path.ends_with(".act") and file_path.contains("cursors"): #and (file_path.contains(player_head_path_part) or file_path.contains(player_body_path_part)): #continue if not FileAccess.file_exists("%s/000.png.import" % base_file_directory_path): continue @@ -267,6 +273,7 @@ func convert(destination: String = "res://client_data"): ResourceSaver.save(scene, "%s/actions.tscn" % base_file_directory_path) + continue # Map.rsw and .gnd and .gat if file_path.ends_with(".rsw") and (file_path.contains("pay_dun") or file_path.contains("iz_int") or file_path.contains("int_land")): @@ -279,5 +286,9 @@ func convert(destination: String = "res://client_data"): static func decode_string(bytes: PackedByteArray): - # TODO: use iconv to decode EUC-KR - return bytes.get_string_from_ascii() + Engine.print_error_messages = false + var string := bytes.get_string_from_multibyte_char("EUC-KR") + Engine.print_error_messages = true + if string.is_empty(): + return bytes.get_string_from_ascii() + return string diff --git a/extractor/rsm_format.gd b/extractor/rsm_format.gd index c01826e..7f16368 100644 --- a/extractor/rsm_format.gd +++ b/extractor/rsm_format.gd @@ -92,17 +92,17 @@ static func from_bytes(bytes: ByteStream) -> RSMFormat: rsm_format.texture_names = [] as Array[String] for _n in rsm_format.texture_count: - rsm_format.texture_names.append(bytes.get_string_from_ascii(40)) + rsm_format.texture_names.append(bytes.get_string_from_ro(40)) if version.lower_than(2, 2): - rsm_format.root_node_name = bytes.get_string_from_ascii(40) + rsm_format.root_node_name = bytes.get_string_from_ro(40) if version.higher_than(2, 1): # >= 2.2 rsm_format.root_node_count = bytes.decode_u32() rsm_format.root_node_names = [] as Array[String] for _n in rsm_format.root_node_count: - rsm_format.root_node_names.append(bytes.get_string_from_ascii(40)) + rsm_format.root_node_names.append(bytes.get_string_from_ro(40)) rsm_format.node_count = bytes.decode_u32() rsm_format.nodes = [] as Array[ModelNode] @@ -253,7 +253,7 @@ class ModelNode: var node = ModelNode.new() node.node_name = bytes.get_string_from_utf8(40) - node.parent_node_name = bytes.get_string_from_ascii(40) + node.parent_node_name = bytes.get_string_from_ro(40) if version.lower_than(2, 3): # < 2.3 node.texture_count = bytes.decode_u32() @@ -267,7 +267,7 @@ class ModelNode: node.texture_names = [] as Array[String] for _n in node.texture_name_count: - node.texture_names.append(bytes.get_string_from_ascii(40)) + node.texture_names.append(bytes.get_string_from_ro(40)) node.offset_matrix = [] as Array[Vector3] for _in in 3: @@ -362,7 +362,7 @@ class ModelNode: node.translate(translation_2) if rotation_axis != Vector3.ZERO: - node.rotation = rotation_axis * rotation_angle + node.rotation = (rotation_axis * rotation_angle) * Vector3(1,-1,1) node.scale = scale diff --git a/extractor/rsw_format.gd b/extractor/rsw_format.gd index 85d873c..7e70850 100644 --- a/extractor/rsw_format.gd +++ b/extractor/rsw_format.gd @@ -122,12 +122,14 @@ func convert(name: String, data_path: String) -> Node3D: if not FileAccess.file_exists(model_file_path): continue - var rsm := RSMFormat.from_bytes(ByteStream.from_bytes(FileAccess.get_file_as_bytes(model_file_path))) + var rsm := RSMFormat.from_bytes(ByteStream.from_bytes( + FileAccess.get_file_as_bytes(model_file_path) + )) var model_root := Node3D.new() model_root.name = resource.name model_root.position = resource.get_position() * Vector3(-1, 1, 1) - model_root.rotation_degrees = resource.get_rotation() + model_root.rotation_degrees = resource.get_rotation() * Vector3(-1,1,-1) model_root.scale = resource.get_scale() node.add_child(model_root) @@ -397,11 +399,11 @@ class Animated3DModel extends MapResource: static func from_bytes(bytes: ByteStream) -> Animated3DModel: var resource = Animated3DModel.new() - resource.name = bytes.get_string_from_ascii(40) + resource.name = bytes.get_string_from_ro(40) resource.animation_type = bytes.decode_u32() resource.animation_speed_percent = bytes.decode_float() resource.collision_flags = bytes.decode_u32() - resource.model_file = bytes.get_string_from_ascii(80) + resource.model_file = bytes.get_string_from_ro(80) resource.root_node_name = bytes.get_string_from_utf8(80) resource.position_x = bytes.decode_float() resource.position_y = bytes.decode_float() @@ -462,7 +464,7 @@ class DynamicLightSource extends MapResource: static func from_bytes(bytes: ByteStream) -> DynamicLightSource: var resource = DynamicLightSource.new() - resource.name = bytes.get_string_from_ascii(80) + resource.name = bytes.get_string_from_ro(80) resource.position_x = bytes.decode_float() resource.position_y = bytes.decode_float() resource.position_z = bytes.decode_float() @@ -528,8 +530,8 @@ class SpatialAudioSource extends MapResource: static func from_bytes(bytes: ByteStream) -> SpatialAudioSource: var resource = SpatialAudioSource.new() - resource.name = bytes.get_string_from_ascii(80) - resource.audio_file = bytes.get_string_from_ascii(80) + resource.name = bytes.get_string_from_ro(80) + resource.audio_file = bytes.get_string_from_ro(80) resource.position_x = bytes.decode_float() resource.position_y = bytes.decode_float() resource.position_z = bytes.decode_float() @@ -593,7 +595,7 @@ class ParticleEffectEmitter extends MapResource: static func from_bytes(bytes: ByteStream) -> ParticleEffectEmitter: var resource = ParticleEffectEmitter.new() - resource.name = bytes.get_string_from_ascii(80) + resource.name = bytes.get_string_from_ro(80) resource.position_x = bytes.decode_float() resource.position_y = bytes.decode_float() resource.position_z = bytes.decode_float() diff --git a/network/character_server.gd b/network/character_server.gd index 60389e4..7f0ac24 100644 --- a/network/character_server.gd +++ b/network/character_server.gd @@ -2,8 +2,8 @@ class_name CharacterServer extends Server -signal logged_in(packet: CharacterServerLoginSuccessPacket) -signal logged_in_character_list(packet: CharacterServerLoginSuccessCharacterListPacket) +#signal logged_in(packet: CharacterServerLoginSuccessPacket) +#signal logged_in_character_list(packet: CharacterServerLoginSuccessCharacterListPacket) signal requested_character_list(packet: RequestCharacterListSuccessPacket) signal selected_character(packet: CharacterSelectionSuccessPacket) @@ -24,25 +24,13 @@ func login(account_id: int, login_id1: int, login_id2: int, gender: Constants.Ge peer.get_data(4) # in-between packet - var login_response_packet = await received_packet - if login_response_packet is CharacterServerLoginSuccessPacket: - logged_in.emit(login_response_packet) - - var character_list_packet = await received_packet - if character_list_packet is CharacterServerLoginSuccessCharacterListPacket: - logged_in_character_list.emit(character_list_packet) - - var character_list_size_packet = await received_packet - var block_character_packet = await received_packet - var pin_code_state_packet = await received_packet - - return { - "login": login_response_packet, - "character_list": character_list_packet, - "character_list_size": character_list_size_packet, - "block_character": block_character_packet, - "pin_code_state": pin_code_state_packet, - } + return await wait_for_all_packets([ + CharacterServerLoginSuccessPacket, + CharacterServerLoginSuccessCharacterListPacket, + CharacterListSizePacket, + BlockCharacterPacket, + PinCodeStatePacket, + ], [CharacterSelectionFailedPacket]) func request_character_list(): @@ -65,6 +53,30 @@ func select_character(slot: int): selected_character.emit(packet) +func create_character( + name: String, + slot: int, + hair_color: int, + hair_style: int, + start_job: Constants.Job, + gender: Constants.Gender +): + var create_character_packet = CreateCharacterPacket.new() + create_character_packet.name = name + create_character_packet.slot = slot + create_character_packet.hair_color = hair_color + create_character_packet.hair_style = hair_style + create_character_packet.start_job = start_job + create_character_packet.gender = gender + + send(create_character_packet) + + return await wait_for_packets([ + CreateCharacterSuccessPacket, + CharacterCreationFailedPacket, + ]) + + func get_keep_alive_timer() -> Timer: var character_server_keep_alive_timer = Timer.new() character_server_keep_alive_timer.name = "CharacterServerKeepAliveTimer" diff --git a/network/client_info.gd b/network/client_info.gd new file mode 100644 index 0000000..45327e8 --- /dev/null +++ b/network/client_info.gd @@ -0,0 +1,19 @@ +class_name ClientInfo + + +var file: String + + +func _init(file_path: String) -> void: + file = FileAccess.get_file_as_string(file_path) + + + +func get_address() -> String: + var regex := RegEx.create_from_string("<address>(.*)<\\/address>") + return regex.search(file).get_string(1) + + +func get_port() -> int: + var regex := RegEx.create_from_string("<port>(.*)<\\/port>") + return regex.search(file).get_string(1) as int diff --git a/network/login_server.gd b/network/login_server.gd index 902c477..b2e6e1b 100644 --- a/network/login_server.gd +++ b/network/login_server.gd @@ -2,8 +2,8 @@ class_name LoginServer extends Server -signal logged_in(packet: LoginServerLoginSuccessPacket) -signal login_failed(packet: LoginFailedPacket) +#signal logged_in(packet: LoginServerLoginSuccessPacket) +#signal login_failed(packet: LoginFailedPacket) @warning_ignore("shadowed_variable_base_class") @@ -11,20 +11,18 @@ func _init(host: String, port: int = 6900) -> void: super._init(host, port) -func login(username: String, password: String): +func login(username: String, password: String) -> Packet: var login_server_login_packet = LoginServerLoginPacket.new() login_server_login_packet.username = username login_server_login_packet.password = password send(login_server_login_packet) - var packet = await received_packet - if packet is LoginServerLoginSuccessPacket: - logged_in.emit(packet) - elif packet is LoginFailedPacket: - login_failed.emit(packet) - - return packet + return await wait_for_packets([ + LoginServerLoginSuccessPacket, + LoginFailedPacket, + LoginFailedPacket2, + ]) func get_keep_alive_timer() -> Timer: @@ -32,7 +30,7 @@ func get_keep_alive_timer() -> Timer: login_server_keep_alive_timer.name = "LoginServerKeepAliveTimer" login_server_keep_alive_timer.autostart = true login_server_keep_alive_timer.one_shot = false - login_server_keep_alive_timer.wait_time = 30.0 # 60.0 + login_server_keep_alive_timer.wait_time = 20.0 # 30.0 # 60.0 login_server_keep_alive_timer.timeout.connect(func(): var login_server_keep_alive_packet := LoginServerKeepAlivePacket.new() diff --git a/network/network.gd b/network/network.gd index 63de38a..736f58b 100644 --- a/network/network.gd +++ b/network/network.gd @@ -1,11 +1,17 @@ extends Node +static var client_info: ClientInfo static var login_server: LoginServer static var character_server: CharacterServer static var map_server: MapServer +func _ready() -> void: + if FileAccess.file_exists("res://client_data/clientinfo.xml"): + client_info = ClientInfo.new("res://client_data/clientinfo.xml") + + func _process(_delta: float) -> void: if login_server: login_server.listen() diff --git a/network/server.gd b/network/server.gd index 56e9861..b8f8319 100644 --- a/network/server.gd +++ b/network/server.gd @@ -84,3 +84,42 @@ func send(packet: Packet) -> Error: func send_raw(bytes: PackedByteArray) -> Error: return peer.put_data(bytes) + + +func wait_for_packets(packet_types: Array) -> Packet: + var packet: Packet + while true: + packet = await received_packet + for type in packet_types: + if is_instance_of(packet, type): + return packet + + # code path return satisfaction + return packet + + +func wait_for_all_packets(packet_types: Array, error_packet_types: Array = []) -> Dictionary[int, Packet]: + var packets: Dictionary[int, Packet] = {} + var packet: Packet + var has_error := false + while true: + packet = await received_packet + + # check packets + for type in packet_types: + if is_instance_of(packet, type): + packets.set(type.get("HEADER"), packet) + break + + # check for errors + for type in error_packet_types: + if is_instance_of(packet, type): + packets.set(type.get("HEADER"), packet) + has_error = true + break + + # finish if all packages received or one package errors + if packets.size() == packet_types.size() or has_error: + break + + return packets diff --git a/packets/character_server/character_creation_failed_packet.gd b/packets/character_server/character_creation_failed_packet.gd new file mode 100644 index 0000000..8ce5b15 --- /dev/null +++ b/packets/character_server/character_creation_failed_packet.gd @@ -0,0 +1,19 @@ +class_name CharacterCreationFailedPacket +extends Packet + + +const HEADER := 0x006e +const BYTE_LENGTH := 3 + + +## Byte Type: u8 +## Byte Length: 1 +var reason: Constants.CharacterCreationFailedReason + + +static func from_bytes(bytes: PackedByteArray): + var packet = CharacterCreationFailedPacket.new() + + packet.reason = bytes.decode_u8(2) + + return packet diff --git a/packets/character_server/create_character_success_packet.gd b/packets/character_server/create_character_success_packet.gd new file mode 100644 index 0000000..b7f826d --- /dev/null +++ b/packets/character_server/create_character_success_packet.gd @@ -0,0 +1,22 @@ +class_name CreateCharacterSuccessPacket +extends Packet + + +const HEADER := 0x0b6f +const BYTE_LENGTH := 0 + + +## Byte Type: u16 +## Byte Length: 2 +var packet_length: int + +var character_information: CharacterInformation + + +static func from_bytes(bytes: PackedByteArray): + var packet = CreateCharacterSuccessPacket.new() + + packet.packet_length = bytes.decode_u16(2) + packet.character_information = CharacterInformation.from_bytes(bytes.slice(4)) + + return packet diff --git a/packets/client/character_server/create_character_packet.gd b/packets/client/character_server/create_character_packet.gd new file mode 100644 index 0000000..a368508 --- /dev/null +++ b/packets/client/character_server/create_character_packet.gd @@ -0,0 +1,54 @@ +class_name CreateCharacterPacket +extends Packet + + +const HEADER := 0x0a39 +const BYTE_LENGTH := 36 + + +## Byte Type: u8 +## Byte Length: 24 +var name: String + +## Byte Type: u8 +## Byte Length: 1 +var slot: int + +## Byte Type: u16 +## Byte Length: 2 +var hair_color: int + +## Byte Type: u16 +## Byte Length: 2 +var hair_style: int + +## Byte Type: u16 +## Byte Length: 2 +var start_job: int + +## Byte Type: u8 +## Byte Length: 2 +var unknown: int + +## Byte Type: u8 +## Byte Length: 1 +var gender: Constants.Gender + + +func to_bytes(): + var payload = PackedByteArray([]) + + var name_buffer = name.to_ascii_buffer() + name_buffer.resize(24) + payload.append_array(name_buffer) + + payload.resize(BYTE_LENGTH - 2) + + payload.encode_u8(24, slot) + payload.encode_u16(25, hair_color) + payload.encode_u16(27, hair_style) + payload.encode_u16(29, start_job) + payload.encode_u16(31, unknown) + payload.encode_u8(33, gender) + + return get_header() + payload diff --git a/packets/login_failed_packet.gd b/packets/login_server/login_failed_packet.gd index 93ebf23..93ebf23 100644 --- a/packets/login_failed_packet.gd +++ b/packets/login_server/login_failed_packet.gd diff --git a/packets/login_server/login_failed_packet_2.gd b/packets/login_server/login_failed_packet_2.gd new file mode 100644 index 0000000..1c4bb4a --- /dev/null +++ b/packets/login_server/login_failed_packet_2.gd @@ -0,0 +1,27 @@ +## rAthena References: +## - clif_authfail_fd +class_name LoginFailedPacket2 +extends Packet + + +const HEADER := 0x083e +const BYTE_LENGTH := 26 + + +## Byte Type: u32 +## Byte Length: 4 +@warning_ignore("enum_variable_without_default") +var reason: Constants.LoginFailedReason2 + +## Byte Type: u8 +## Byte Length: 20 +var unblock_time: String + + +static func from_bytes(bytes: PackedByteArray) -> LoginFailedPacket2: + var packet = LoginFailedPacket2.new() + + packet.reason = bytes.decode_u32(2) + packet.unblock_time = bytes.slice(6, 26).get_string_from_utf8() + + return packet diff --git a/packets/login_server/login_server_login_success_packet.gd b/packets/login_server/login_server_login_success_packet.gd index ce6a058..f1893df 100644 --- a/packets/login_server/login_server_login_success_packet.gd +++ b/packets/login_server/login_server_login_success_packet.gd @@ -32,7 +32,7 @@ var ip_address: PackedByteArray ## Byte Length: 26 var last_login: PackedByteArray -## Byte Type: u8 +## Byte Type: u8 [br] ## Byte Length: 1 var gender: Constants.Gender diff --git a/project.godot b/project.godot index 6d281f7..5951a79 100644 --- a/project.godot +++ b/project.godot @@ -12,7 +12,7 @@ config_version=5 config/name="Minerva" run/main_scene="res://ui/login.tscn" -config/features=PackedStringArray("4.4", "Forward Plus") +config/features=PackedStringArray("4.5", "Forward Plus") config/icon="uid://du8c0ll5pq5ci" [autoload] diff --git a/sound_manager.tscn b/sound_manager.tscn index fe577ba..d268c41 100644 --- a/sound_manager.tscn +++ b/sound_manager.tscn @@ -1,7 +1,7 @@ [gd_scene load_steps=3 format=3 uid="uid://cf02havkcqt1l"] -[ext_resource type="AudioStream" uid="uid://pibh8ld1pcq5" path="res://client_data/data/wav/¹öư¼Ò¸®.wav" id="1_g5net"] [ext_resource type="Script" uid="uid://r3smu0o27hwj" path="res://sound_manager.gd" id="1_mdjn0"] +[ext_resource type="AudioStream" uid="uid://dn0464j35rina" path="res://client_data/data/wav/버튼소리.wav" id="2_mdjn0"] [node name="SoundManager" type="Node"] script = ExtResource("1_mdjn0") @@ -9,4 +9,4 @@ script = ExtResource("1_mdjn0") [node name="UI" type="Node" parent="."] [node name="SoundButtonClick" type="AudioStreamPlayer" parent="UI"] -stream = ExtResource("1_g5net") +stream = ExtResource("2_mdjn0") diff --git a/ui/chat_window.tscn b/ui/chat_window.tscn index b430fb8..5804fd0 100644 --- a/ui/chat_window.tscn +++ b/ui/chat_window.tscn @@ -1,8 +1,7 @@ -[gd_scene load_steps=5 format=3 uid="uid://c8uqw08hxfqlu"] +[gd_scene load_steps=4 format=3 uid="uid://c8uqw08hxfqlu"] [ext_resource type="Script" uid="uid://cy5bwkc4gokw1" path="res://ui/chat_window.gd" id="1_vovuq"] -[ext_resource type="PackedScene" uid="uid://cjcm2mai50thr" path="res://ui/bmp_texture_button.tscn" id="2_2x3wj"] -[ext_resource type="Texture2D" uid="uid://dqq3mtjcrwqnp" path="res://client_data/data/texture/À¯ÀúÀÎÅÍÆäÀ̽º/basic_interface/sys_base_off.bmp" id="3_smgio"] +[ext_resource type="Texture2D" uid="uid://dwv8ca3u5xk3o" path="res://client_data/data/texture/유저인터페이스/basic_interface/sys_base_off.png" id="2_2x3wj"] [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ku06j"] bg_color = Color(0.133333, 0.133333, 0.133333, 0.784314) @@ -45,6 +44,7 @@ layout_mode = 2 [node name="ToPlayer" type="LineEdit" parent="VBoxContainer/HBoxContainer"] unique_name_in_owner = true layout_mode = 2 +placeholder_text = "Player" [node name="LineEdit" type="LineEdit" parent="VBoxContainer/HBoxContainer"] unique_name_in_owner = true @@ -52,9 +52,11 @@ layout_mode = 2 size_flags_horizontal = 3 placeholder_text = "Send Messages here" -[node name="Handle" parent="VBoxContainer/HBoxContainer" instance=ExtResource("2_2x3wj")] +[node name="Handle" type="TextureButton" parent="VBoxContainer/HBoxContainer"] +texture_filter = 1 layout_mode = 2 -texture_normal = ExtResource("3_smgio") +mouse_default_cursor_shape = 2 +texture_normal = ExtResource("2_2x3wj") stretch_mode = 5 [connection signal="text_submitted" from="VBoxContainer/HBoxContainer/LineEdit" to="." method="_on_line_edit_text_submitted"] diff --git a/ui/login.gd b/ui/login.gd index 70cc52e..1c5284e 100644 --- a/ui/login.gd +++ b/ui/login.gd @@ -28,11 +28,16 @@ func switch_screen(screen: Node): func _on_login_pressed() -> void: SoundManager.sound_button_click.play() - Network.login_server = LoginServer.new("127.0.0.1") + Network.login_server = LoginServer.new(Network.client_info.get_address(), Network.client_info.get_port()) Network.login_server.establish_connection() if Network.login_server.get_status() == Error.FAILED: - Client.show_message_window("Couldn't connect to server at 127.0.0.1", "Connection Error", %Login/Window, SIDE_BOTTOM) + Client.show_message_window( + "Couldn't connect to server at %s:%s" % [Network.login_server.host, Network.login_server.port], + "Connection Error", + %Login/Window, + SIDE_BOTTOM + ) return var response = await Network.login_server.login(username.text, password.text) @@ -48,6 +53,30 @@ func _on_login_pressed() -> void: Client.show_message_window(message, "Login Error", %Login/Window, SIDE_BOTTOM) return + if response is LoginFailedPacket2: + var message := "" + if response.reason == Constants.LoginFailedReason2.UnregisteredId: + message = "Unregistered ID" + elif response.reason == Constants.LoginFailedReason2.IncorrectPassword: + message = "Incorrect Password" + elif response.reason == Constants.LoginFailedReason2.IdExpired: + message = "ID expired" + elif response.reason == Constants.LoginFailedReason2.RejectedFromServer: + message = "Rejected from Server" + elif response.reason == Constants.LoginFailedReason2.BlockedByGMTeam: + message = "Blocked by GM Team" + elif response.reason == Constants.LoginFailedReason2.GameOutdated: + message = "Game Outdated" + elif response.reason == Constants.LoginFailedReason2.LoginProhibitedUntil: + message = "Login prohibited until %s" % response.unblock_time + elif response.reason == Constants.LoginFailedReason2.ServerFull: + message = "Server Full" + elif response.reason == Constants.LoginFailedReason2.CompanyAccountLimitReached: + message = "CompanyAccountLimitReached" + + Client.show_message_window(message, "Login Error", %Login/Window, SIDE_BOTTOM) + return + account_information = response character_server_information = account_information.character_server_information @@ -96,10 +125,12 @@ func _on_character_server_login_pressed(character_server_info: CharacterServerIn account_information.gender ) - if response.login is CharacterSelectionFailedPacket: + if response.has(CharacterSelectionFailedPacket.HEADER): Client.show_message_window( - "Connection rejected from server \"%s\" at %s" % [ - character_server_info.server_name, character_server_info.get_server_ip() + "Connection rejected from server \"%s\" at %s:%s" % [ + character_server_info.server_name, + character_server_info.get_server_ip(), + character_server_info.server_port ], "Connection Error", %CharacterServer/Window, SIDE_BOTTOM ) @@ -107,7 +138,7 @@ func _on_character_server_login_pressed(character_server_info: CharacterServerIn get_tree().root.add_child(Network.character_server.get_keep_alive_timer()) - var character_list: CharacterServerLoginSuccessCharacterListPacket = response.character_list + var character_list: CharacterServerLoginSuccessCharacterListPacket = response[CharacterServerLoginSuccessCharacterListPacket.HEADER] var login_character_list := LoginCharacterList.from_character_list_login_packet(character_list) %CharacterSelectionList.login_character_list = login_character_list @@ -118,11 +149,18 @@ func _on_character_server_login_pressed(character_server_info: CharacterServerIn var info = login_character_list.get_info_for_slot(slot_idx) if info: current_character_information = info + %CharacterSelectionCreate.visible = false + %CharacterLogin.visible = true else: current_character_information = null + %CharacterSelectionCreate.visible = true + %CharacterLogin.visible = false ) %CharacterSelectionList.requested_login.connect(func(slot_idx: int): - _on_character_selected_pressed(slot_idx) + if current_character_information: + _on_character_selected_pressed(slot_idx) + else: + _on_character_selection_create_pressed() ) # pre-select first character @@ -178,5 +216,56 @@ func _on_character_selection_back_button_pressed() -> void: switch_screen(%CharacterServer) +func _on_character_selection_create_pressed() -> void: + SoundManager.sound_button_click.play() + switch_screen(%CharacterCreation) + + %CharacterCreationInterface.strength = 5 + %CharacterCreationInterface.agility = 5 + %CharacterCreationInterface.vitality = 5 + %CharacterCreationInterface.intelligence = 5 + %CharacterCreationInterface.dexterity = 5 + %CharacterCreationInterface.luck = 5 + + func _on_character_login_pressed() -> void: _on_character_selected_pressed(current_character_slot_idx) + + +func _on_character_creation_cancel_pressed() -> void: + SoundManager.sound_button_click.play() + switch_screen(%CharacterSelection) + + +func _on_character_creation_create_pressed() -> void: + SoundManager.sound_button_click.play() + + var response = await Network.character_server.create_character( + %CharacterCreationInterface.character_name, + current_character_slot_idx, + 0, + %CharacterCreationInterface.head_id, + Constants.Job.Novice, + account_information.gender + ) + + if response is CharacterCreationFailedPacket: + var message := "" + if response.reason == Constants.CharacterCreationFailedReason.CharacterNameAlreadyInUse: + message = "Character Name already in use" + elif response.reason == Constants.CharacterCreationFailedReason.NotOldEnough: + message = "Not old enough" + elif response.reason == Constants.CharacterCreationFailedReason.NotAllowedToUseSlot: + message = "Not allowed to use slot" + elif response.reason == Constants.CharacterCreationFailedReason.CharacterCreationFailed: + message = "Character creation failed. Reason unknown" + + Client.show_message_window(message, "Character Creation Error") + return + + # TODO: create character + # TODO: reload selection list data + + switch_screen(%CharacterSelection) + %CharacterSelectionList.login_character_list.add_character_information(response.character_information) + print(inst_to_dict(response.character_information)) diff --git a/ui/login.tscn b/ui/login.tscn index e889508..04f24b1 100644 --- a/ui/login.tscn +++ b/ui/login.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=24 format=3 uid="uid://dser74lcd3a4g"] +[gd_scene load_steps=25 format=3 uid="uid://dser74lcd3a4g"] [ext_resource type="Script" uid="uid://dqswsdaamfhbq" path="res://ui/login.gd" id="1_1m5cv"] [ext_resource type="Texture2D" uid="uid://cxd6dnc7s17vg" path="res://client_data/skin/login_background.jpg" id="2_elmti"] @@ -6,22 +6,23 @@ [ext_resource type="Theme" uid="uid://c5sm3yvuakj3b" path="res://ui/theme.tres" id="3_7ogdv"] [ext_resource type="PackedScene" uid="uid://cjcm2mai50thr" path="res://ui/bmp_texture_button.tscn" id="3_qemc0"] [ext_resource type="PackedScene" uid="uid://c8uqw08hxfqlu" path="res://ui/chat_window.tscn" id="4_ah2a1"] -[ext_resource type="Texture2D" uid="uid://bern5mhol3l8y" path="res://client_data/data/texture/À¯ÀúÀÎÅÍÆäÀ̽º/login_interface/btn_connect.bmp" id="4_wpax4"] -[ext_resource type="Texture2D" uid="uid://c31u8nlyugk3p" path="res://client_data/data/texture/À¯ÀúÀÎÅÍÆäÀ̽º/login_interface/btn_connect_b.bmp" id="5_7ogdv"] -[ext_resource type="Texture2D" uid="uid://c5kctdb8b2msx" path="res://client_data/data/texture/À¯ÀúÀÎÅÍÆäÀ̽º/login_interface/btn_connect_a.bmp" id="6_l3yss"] -[ext_resource type="Texture2D" uid="uid://l3c7ssoc4lxq" path="res://client_data/data/texture/À¯ÀúÀÎÅÍÆäÀ̽º/login_interface/btn_connect.png" id="7_pfdi0"] -[ext_resource type="Texture2D" uid="uid://p7bxfof7gd0t" path="res://client_data/data/texture/À¯ÀúÀÎÅÍÆäÀ̽º/login_interface/btn_connect_b.png" id="8_38pxr"] -[ext_resource type="Texture2D" uid="uid://ba8j1t53lqxr0" path="res://client_data/data/texture/À¯ÀúÀÎÅÍÆäÀ̽º/login_interface/btn_connect_a.png" id="9_hqeko"] +[ext_resource type="Texture2D" uid="uid://1vrog6v0c8dd" path="res://client_data/data/texture/유저인터페이스/login_interface/btn_connect.png" id="7_8pgsx"] +[ext_resource type="Texture2D" uid="uid://txbfc4bmwl3o" path="res://client_data/data/texture/유저인터페이스/login_interface/btn_connect_b.png" id="8_dx2ir"] +[ext_resource type="Texture2D" uid="uid://xj061qbyw4mp" path="res://client_data/data/texture/유저인터페이스/login_interface/btn_connect_a.png" id="9_tftjj"] [ext_resource type="Theme" uid="uid://c6y6r8kcnbb10" path="res://ui/theme_clear.tres" id="9_toei2"] [ext_resource type="PackedScene" uid="uid://f2urhroq21t0" path="res://ui/login/character_server_button.tscn" id="10_38pxr"] -[ext_resource type="Texture2D" uid="uid://byn26biifjkng" path="res://client_data/data/texture/À¯ÀúÀÎÅÍÆäÀ̽º/btn_cancel.bmp" id="11_tihdy"] -[ext_resource type="Texture2D" uid="uid://wvnt34j5mkvy" path="res://client_data/data/texture/À¯ÀúÀÎÅÍÆäÀ̽º/btn_cancel_b.bmp" id="12_mma3j"] -[ext_resource type="Texture2D" uid="uid://pv886kwtlrq0" path="res://client_data/data/texture/À¯ÀúÀÎÅÍÆäÀ̽º/btn_cancel_a.bmp" id="13_0vsp3"] -[ext_resource type="Texture2D" uid="uid://b13jh48hyjyrt" path="res://client_data/data/texture/À¯ÀúÀÎÅÍÆäÀ̽º/btn_next.bmp" id="14_pfdi0"] -[ext_resource type="Texture2D" uid="uid://bo277gh8uyw1w" path="res://client_data/data/texture/À¯ÀúÀÎÅÍÆäÀ̽º/btn_next_b.bmp" id="15_38pxr"] -[ext_resource type="Texture2D" uid="uid://qvmuk8xa3yej" path="res://client_data/data/texture/À¯ÀúÀÎÅÍÆäÀ̽º/btn_next_a.bmp" id="16_hqeko"] +[ext_resource type="Texture2D" uid="uid://pjerdwsogw84" path="res://client_data/data/texture/유저인터페이스/btn_cancel.png" id="11_60jnu"] +[ext_resource type="Texture2D" uid="uid://ba3g38r086pyk" path="res://client_data/data/texture/유저인터페이스/btn_cancel_b.png" id="12_up3vp"] +[ext_resource type="Texture2D" uid="uid://bw3j7xm53qoqe" path="res://client_data/data/texture/유저인터페이스/btn_cancel_a.png" id="13_swwvu"] +[ext_resource type="Texture2D" uid="uid://brkbxq02xuyw8" path="res://client_data/data/texture/유저인터페이스/btn_next.png" id="14_ohrmw"] +[ext_resource type="Texture2D" uid="uid://dweiqt26hgws2" path="res://client_data/data/texture/유저인터페이스/btn_next_b.png" id="15_c1fiv"] +[ext_resource type="Texture2D" uid="uid://h6r0smppndhq" path="res://client_data/data/texture/유저인터페이스/btn_next_a.png" id="16_14c6s"] [ext_resource type="PackedScene" uid="uid://bxbprntny8duj" path="res://ui/login/login_character_selection_list.tscn" id="16_tihdy"] [ext_resource type="PackedScene" uid="uid://swtqlba1wi3o" path="res://ui/window.tscn" id="17_mma3j"] +[ext_resource type="Texture2D" uid="uid://cgsgfo5j5lm2t" path="res://client_data/data/texture/유저인터페이스/btn_make_b.png" id="19_dx2ir"] +[ext_resource type="Texture2D" uid="uid://bvbne1gpgvk08" path="res://client_data/data/texture/유저인터페이스/btn_make_a.png" id="20_tftjj"] +[ext_resource type="Texture2D" uid="uid://cnhrbacvvitjq" path="res://client_data/data/texture/유저인터페이스/btn_make.png" id="22_82qbc"] +[ext_resource type="PackedScene" uid="uid://di8inwptr42fe" path="res://ui/login/character_creation.tscn" id="24_8pgsx"] [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_pfdi0"] bg_color = Color(0.977834, 0.977834, 0.977834, 1) @@ -119,9 +120,9 @@ secret_character = "*" layout_mode = 2 size_flags_horizontal = 8 theme = ExtResource("3_7ogdv") -texture_normal = ExtResource("7_pfdi0") -texture_pressed = ExtResource("8_38pxr") -texture_hover = ExtResource("9_hqeko") +texture_normal = ExtResource("7_8pgsx") +texture_pressed = ExtResource("8_dx2ir") +texture_hover = ExtResource("9_tftjj") [node name="CharacterServer" type="CenterContainer" parent="."] unique_name_in_owner = true @@ -169,16 +170,16 @@ layout_mode = 2 [node name="CharacterServerBackButton" parent="CharacterServer/Window/VBoxContainer/ButtonBar/ButtonBarElements/HBoxContainer" instance=ExtResource("3_qemc0")] layout_mode = 2 size_flags_horizontal = 0 -texture_normal = ExtResource("11_tihdy") -texture_pressed = ExtResource("12_mma3j") -texture_hover = ExtResource("13_0vsp3") +texture_normal = ExtResource("11_60jnu") +texture_pressed = ExtResource("12_up3vp") +texture_hover = ExtResource("13_swwvu") [node name="CharacterServerNextButton" parent="CharacterServer/Window/VBoxContainer/ButtonBar/ButtonBarElements/HBoxContainer" instance=ExtResource("3_qemc0")] layout_mode = 2 size_flags_horizontal = 10 -texture_normal = ExtResource("14_pfdi0") -texture_pressed = ExtResource("15_38pxr") -texture_hover = ExtResource("16_hqeko") +texture_normal = ExtResource("14_ohrmw") +texture_pressed = ExtResource("15_c1fiv") +texture_hover = ExtResource("16_14c6s") [node name="CharacterSelection" type="CenterContainer" parent="."] unique_name_in_owner = true @@ -294,17 +295,72 @@ layout_mode = 2 [node name="CharacterSelectionBackButton" parent="CharacterSelection/Window/VBoxContainer/ButtonBar/ButtonBarElements" index="0" instance=ExtResource("3_qemc0")] layout_mode = 2 size_flags_horizontal = 0 -texture_normal = ExtResource("11_tihdy") -texture_pressed = ExtResource("12_mma3j") -texture_hover = ExtResource("13_0vsp3") +texture_normal = ExtResource("11_60jnu") +texture_pressed = ExtResource("12_up3vp") +texture_hover = ExtResource("13_swwvu") -[node name="CharacterLogin" parent="CharacterSelection/Window/VBoxContainer/ButtonBar/ButtonBarElements" index="1" instance=ExtResource("3_qemc0")] +[node name="HBoxContainer" type="HBoxContainer" parent="CharacterSelection/Window/VBoxContainer/ButtonBar/ButtonBarElements" index="1"] +layout_mode = 2 +size_flags_horizontal = 8 + +[node name="CharacterSelectionCreate" type="TextureButton" parent="CharacterSelection/Window/VBoxContainer/ButtonBar/ButtonBarElements/HBoxContainer"] +unique_name_in_owner = true +texture_filter = 1 +layout_mode = 2 +size_flags_horizontal = 8 +mouse_default_cursor_shape = 2 +texture_normal = ExtResource("22_82qbc") +texture_pressed = ExtResource("19_dx2ir") +texture_hover = ExtResource("20_tftjj") + +[node name="CharacterLogin" parent="CharacterSelection/Window/VBoxContainer/ButtonBar/ButtonBarElements/HBoxContainer" instance=ExtResource("3_qemc0")] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 8 +texture_normal = ExtResource("7_8pgsx") +texture_pressed = ExtResource("8_dx2ir") +texture_hover = ExtResource("9_tftjj") + +[node name="CharacterCreation" type="CenterContainer" parent="."] +unique_name_in_owner = true +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="Window" parent="CharacterCreation" instance=ExtResource("17_mma3j")] +layout_mode = 2 + +[node name="MarginContainer" type="MarginContainer" parent="CharacterCreation/Window/VBoxContainer/Body" index="0"] +layout_mode = 2 +theme_override_constants/margin_left = 16 +theme_override_constants/margin_top = 16 +theme_override_constants/margin_right = 16 +theme_override_constants/margin_bottom = 16 + +[node name="CharacterCreationInterface" parent="CharacterCreation/Window/VBoxContainer/Body/MarginContainer" instance=ExtResource("24_8pgsx")] unique_name_in_owner = true layout_mode = 2 + +[node name="CharacterCreationCancel" type="TextureButton" parent="CharacterCreation/Window/VBoxContainer/ButtonBar/ButtonBarElements" index="0"] +texture_filter = 1 +layout_mode = 2 +size_flags_horizontal = 0 +mouse_default_cursor_shape = 2 +texture_normal = ExtResource("11_60jnu") +texture_pressed = ExtResource("12_up3vp") +texture_hover = ExtResource("13_swwvu") + +[node name="CharacterCreationCreate" type="TextureButton" parent="CharacterCreation/Window/VBoxContainer/ButtonBar/ButtonBarElements" index="1"] +texture_filter = 1 +layout_mode = 2 size_flags_horizontal = 8 -texture_normal = ExtResource("4_wpax4") -texture_pressed = ExtResource("5_7ogdv") -texture_hover = ExtResource("6_l3yss") +mouse_default_cursor_shape = 2 +texture_normal = ExtResource("22_82qbc") +texture_pressed = ExtResource("19_dx2ir") +texture_hover = ExtResource("20_tftjj") [node name="BackgroundMusic" type="AudioStreamPlayer" parent="."] stream = ExtResource("3_2nukd") @@ -327,8 +383,12 @@ grow_vertical = 0 [connection signal="pressed" from="CharacterServer/Window/VBoxContainer/ButtonBar/ButtonBarElements/HBoxContainer/CharacterServerNextButton" to="." method="_on_character_server_next_button_pressed"] [connection signal="pressed" from="CharacterSelection/VBoxContainer/CharacterSelectionBackButton" to="." method="_on_character_selection_back_button_pressed"] [connection signal="pressed" from="CharacterSelection/Window/VBoxContainer/ButtonBar/ButtonBarElements/CharacterSelectionBackButton" to="." method="_on_character_selection_back_button_pressed"] -[connection signal="pressed" from="CharacterSelection/Window/VBoxContainer/ButtonBar/ButtonBarElements/CharacterLogin" to="." method="_on_character_login_pressed"] +[connection signal="pressed" from="CharacterSelection/Window/VBoxContainer/ButtonBar/ButtonBarElements/HBoxContainer/CharacterSelectionCreate" to="." method="_on_character_selection_create_pressed"] +[connection signal="pressed" from="CharacterSelection/Window/VBoxContainer/ButtonBar/ButtonBarElements/HBoxContainer/CharacterLogin" to="." method="_on_character_login_pressed"] +[connection signal="pressed" from="CharacterCreation/Window/VBoxContainer/ButtonBar/ButtonBarElements/CharacterCreationCancel" to="." method="_on_character_creation_cancel_pressed"] +[connection signal="pressed" from="CharacterCreation/Window/VBoxContainer/ButtonBar/ButtonBarElements/CharacterCreationCreate" to="." method="_on_character_creation_create_pressed"] [editable path="Login/Window"] [editable path="CharacterServer/Window"] [editable path="CharacterSelection/Window"] +[editable path="CharacterCreation/Window"] diff --git a/ui/login/character_creation.gd b/ui/login/character_creation.gd new file mode 100644 index 0000000..f3989d1 --- /dev/null +++ b/ui/login/character_creation.gd @@ -0,0 +1,134 @@ +extends HBoxContainer + + +var strength := 5: + set(value): + strength = value + %StatEntryStrength.value = value + %Polygon.polygon[0] = ( + Vector2(100, 100) + + ((Vector2(100, 0) - Vector2(100, 100)) / 9.0) * value + ) + +var vitality := 5: + set(value): + vitality = value + %StatEntryVitality.value = value + %Polygon.polygon[1] = ( + Vector2(100, 100) + + ((Vector2(200, 50) - Vector2(100, 100)) / 9.0) * value + ) + +var luck := 5: + set(value): + luck = value + %StatEntryLuck.value = value + %Polygon.polygon[2] = ( + Vector2(100, 100) + + ((Vector2(200, 150) - Vector2(100, 100)) / 9.0) * value + ) + +var intelligence := 5: + set(value): + intelligence = value + %StatEntryIntelligence.value = value + %Polygon.polygon[3] = ( + Vector2(100, 100) + + ((Vector2(100, 200) - Vector2(100, 100)) / 9.0) * value + ) + +var dexterity := 5: + set(value): + dexterity = value + %StatEntryDexterity.value = value + %Polygon.polygon[4] = ( + Vector2(100, 100) + + ((Vector2(0, 150) - Vector2(100, 100)) / 9.0) * value + ) + +var agility := 5: + set(value): + agility = value + %StatEntryAgility.value = value + %Polygon.polygon[5] = ( + Vector2(100, 100) + + ((Vector2(0, 50) - Vector2(100, 100)) / 9.0) * value + ) + +var head_id := 1: + set(value): + head_id = value + %Head.texture = load( + "%s/%s/000.png" % [ + "res://client_data/data/sprite", + Constants.FilePaths.get_player_head(Constants.Gender.Male, head_id), + ] + ) + +var character_name: String + + +func _on_strength_button_pressed() -> void: + if strength >= 9: + return + + strength += 1 + intelligence -= 1 + + +func _on_vitality_button_pressed() -> void: + if vitality >= 9: + return + + vitality += 1 + dexterity -= 1 + + +func _on_luck_button_pressed() -> void: + if luck >= 9: + return + + luck += 1 + agility -= 1 + + +func _on_intelligence_button_pressed() -> void: + if intelligence >= 9: + return + + intelligence += 1 + strength -= 1 + + +func _on_dexterity_button_pressed() -> void: + if dexterity >= 9: + return + + dexterity += 1 + vitality -= 1 + + +func _on_agility_button_pressed() -> void: + if agility >= 9: + return + + agility += 1 + luck -= 1 + + +func _on_appearance_left_button_pressed() -> void: + head_id = (head_id - 1) % (42 + 1) + # TODO: fix + + +func _on_appearance_right_button_pressed() -> void: + head_id = (head_id + 1) % (42 + 1) + + +func _on_appearance_up_button_pressed() -> void: + # TODO: change hair color + pass # Replace with function body. + + +func _on_name_text_changed(new_text: String) -> void: + character_name = new_text diff --git a/ui/login/character_creation.tscn b/ui/login/character_creation.tscn new file mode 100644 index 0000000..dbecf32 --- /dev/null +++ b/ui/login/character_creation.tscn @@ -0,0 +1,304 @@ +[gd_scene load_steps=21 format=3 uid="uid://di8inwptr42fe"] + +[ext_resource type="Script" uid="uid://w10xfhscfuo0" path="res://ui/login/character_creation.gd" id="1_i6vfx"] +[ext_resource type="Theme" uid="uid://c6y6r8kcnbb10" path="res://ui/theme_clear.tres" id="1_kuhsd"] +[ext_resource type="Texture2D" uid="uid://687s0xq708kn" path="res://client_data/data/texture/유저인터페이스/basic_interface/arw_left.png" id="2_6pdc2"] +[ext_resource type="Texture2D" uid="uid://0to1babdx1js" path="res://client_data/data/texture/유저인터페이스/basic_interface/arw_right.png" id="3_60s0a"] +[ext_resource type="Texture2D" uid="uid://mvgh8pjg7qar" path="res://client_data/data/texture/유저인터페이스/basic_interface/arw_up.png" id="4_ufd68"] +[ext_resource type="Texture2D" uid="uid://ci2liot5s8jnb" path="res://client_data/data/sprite/인간족/머리통/남/16_남/000.png" id="5_6pdc2"] +[ext_resource type="Texture2D" uid="uid://be3ax80esna7b" path="res://client_data/data/sprite/인간족/몸통/남/초보자_남/000.png" id="6_60s0a"] +[ext_resource type="Texture2D" uid="uid://c0kd66xiup6qq" path="res://client_data/data/texture/유저인터페이스/login_interface/arw-str0.png" id="8_6pdc2"] +[ext_resource type="Texture2D" uid="uid://c5k65ct7at0ns" path="res://client_data/data/texture/유저인터페이스/login_interface/arw-str1.png" id="9_60s0a"] +[ext_resource type="Texture2D" uid="uid://cnpgjr7mj4j14" path="res://client_data/data/texture/유저인터페이스/login_interface/arw-vit0.png" id="10_6pdc2"] +[ext_resource type="Texture2D" uid="uid://b4878jg8ex7tm" path="res://client_data/data/texture/유저인터페이스/login_interface/arw-vit1.png" id="11_60s0a"] +[ext_resource type="Texture2D" uid="uid://iviinm4jtx2j" path="res://client_data/data/texture/유저인터페이스/login_interface/arw-luk0.png" id="12_6pdc2"] +[ext_resource type="Texture2D" uid="uid://dx0w5jac6n12s" path="res://client_data/data/texture/유저인터페이스/login_interface/arw-luk1.png" id="13_60s0a"] +[ext_resource type="PackedScene" uid="uid://cff164qwvlsqd" path="res://ui/login/stat_entry.tscn" id="14_b1a0f"] +[ext_resource type="Texture2D" uid="uid://qrudl7mwwjvq" path="res://client_data/data/texture/유저인터페이스/login_interface/arw-int0.png" id="14_ufd68"] +[ext_resource type="Texture2D" uid="uid://7vxidv2eb4uk" path="res://client_data/data/texture/유저인터페이스/login_interface/arw-int1.png" id="15_uors6"] +[ext_resource type="Texture2D" uid="uid://bd20v4ovvst4r" path="res://client_data/data/texture/유저인터페이스/login_interface/arw-dex0.png" id="16_kbej0"] +[ext_resource type="Texture2D" uid="uid://cyry27r8wpd7i" path="res://client_data/data/texture/유저인터페이스/login_interface/arw-dex1.png" id="17_1iw4y"] +[ext_resource type="Texture2D" uid="uid://cd7riu7j5lyri" path="res://client_data/data/texture/유저인터페이스/login_interface/arw-agi0.png" id="18_225jb"] +[ext_resource type="Texture2D" uid="uid://dcotmlbpx0iaa" path="res://client_data/data/texture/유저인터페이스/login_interface/arw-agi1.png" id="19_b1a0f"] + +[node name="CharacterCreation" type="HBoxContainer"] +script = ExtResource("1_i6vfx") + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +layout_mode = 2 +size_flags_vertical = 8 + +[node name="Control" type="Control" parent="VBoxContainer"] +custom_minimum_size = Vector2(0, 20) +layout_mode = 2 + +[node name="AppearanceLeftButton" type="TextureButton" parent="VBoxContainer/Control"] +texture_filter = 1 +layout_mode = 1 +anchors_preset = 4 +anchor_top = 0.5 +anchor_bottom = 0.5 +offset_top = -5.5 +offset_right = 11.0 +offset_bottom = 5.5 +grow_vertical = 2 +scale = Vector2(1.5, 1.5) +mouse_default_cursor_shape = 2 +texture_normal = ExtResource("2_6pdc2") + +[node name="AppearanceRightButton" type="TextureButton" parent="VBoxContainer/Control"] +texture_filter = 1 +layout_mode = 1 +anchors_preset = 6 +anchor_left = 1.0 +anchor_top = 0.5 +anchor_right = 1.0 +anchor_bottom = 0.5 +offset_left = -11.0 +offset_top = -5.5 +offset_bottom = 5.5 +grow_horizontal = 0 +grow_vertical = 2 +scale = Vector2(1.5, 1.5) +mouse_default_cursor_shape = 2 +texture_normal = ExtResource("3_60s0a") + +[node name="AppearanceUpButton" type="TextureButton" parent="VBoxContainer/Control"] +texture_filter = 1 +layout_mode = 1 +anchors_preset = 5 +anchor_left = 0.5 +anchor_right = 0.5 +offset_left = -5.5 +offset_top = -8.0 +offset_right = 5.5 +offset_bottom = 3.0 +grow_horizontal = 2 +scale = Vector2(1.5, 1.5) +mouse_default_cursor_shape = 2 +texture_normal = ExtResource("4_ufd68") + +[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer"] +layout_mode = 2 +theme_override_constants/separation = -8 + +[node name="Head" type="TextureRect" parent="VBoxContainer/VBoxContainer"] +unique_name_in_owner = true +z_index = 1 +texture_filter = 1 +layout_mode = 2 +texture = ExtResource("5_6pdc2") +stretch_mode = 5 + +[node name="Body" type="TextureRect" parent="VBoxContainer/VBoxContainer"] +texture_filter = 1 +layout_mode = 2 +texture = ExtResource("6_60s0a") +stretch_mode = 5 + +[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer"] +layout_mode = 2 + +[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer"] +texture_filter = 1 +layout_mode = 2 +theme = ExtResource("1_kuhsd") +theme_type_variation = &"LabelLabel" +text = "Name" + +[node name="Name" type="LineEdit" parent="VBoxContainer/HBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_vertical = 4 +theme = ExtResource("1_kuhsd") + +[node name="Control" type="Control" parent="."] +custom_minimum_size = Vector2(280, 280) +layout_mode = 2 + +[node name="Container" type="Node2D" parent="Control"] +position = Vector2(40, 40) + +[node name="Polygon" type="Polygon2D" parent="Control/Container"] +unique_name_in_owner = true +color = Color(0.776471, 0.807843, 0.905882, 1) +polygon = PackedVector2Array(100, 50, 148, 76, 148, 124, 100, 150, 52, 124, 52, 76) +uv = PackedVector2Array(100, 0, 200, 50, 200, 150, 100, 200, 0, 150, 0, 75) + +[node name="LineCircle" type="Line2D" parent="Control/Container"] +points = PackedVector2Array(100, 0, 200, 50, 200, 150, 100, 200, 0, 150, 0, 50) +closed = true +width = 1.0 +default_color = Color(0.776471, 0.807843, 0.905882, 1) + +[node name="LineNS" type="Line2D" parent="Control/Container"] +points = PackedVector2Array(100, 0, 100, 200) +closed = true +width = 1.0 +default_color = Color(0.776471, 0.807843, 0.905882, 1) + +[node name="LineNESW" type="Line2D" parent="Control/Container"] +points = PackedVector2Array(200, 50, 0, 150) +closed = true +width = 1.0 +default_color = Color(0.776471, 0.807843, 0.905882, 1) + +[node name="LineNWSE" type="Line2D" parent="Control/Container"] +points = PackedVector2Array(0, 50, 200, 150) +closed = true +width = 1.0 +default_color = Color(0.776471, 0.807843, 0.905882, 1) + +[node name="StrengthButton" type="TextureButton" parent="Control"] +texture_filter = 1 +layout_mode = 1 +anchors_preset = 5 +anchor_left = 0.5 +anchor_right = 0.5 +offset_left = -19.0 +offset_top = 1.0 +offset_right = 21.0 +offset_bottom = 41.0 +grow_horizontal = 2 +mouse_default_cursor_shape = 2 +texture_normal = ExtResource("8_6pdc2") +texture_pressed = ExtResource("9_60s0a") + +[node name="VitalityButton" type="TextureButton" parent="Control"] +texture_filter = 1 +layout_mode = 1 +anchors_preset = 1 +anchor_left = 1.0 +anchor_right = 1.0 +offset_left = -42.9999 +offset_top = 67.0 +offset_right = -2.99994 +offset_bottom = 107.0 +grow_horizontal = 0 +mouse_default_cursor_shape = 2 +texture_normal = ExtResource("10_6pdc2") +texture_pressed = ExtResource("11_60s0a") + +[node name="LuckButton" type="TextureButton" parent="Control"] +texture_filter = 1 +layout_mode = 1 +anchors_preset = 3 +anchor_left = 1.0 +anchor_top = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = -44.0 +offset_top = -101.0 +offset_right = -4.0 +offset_bottom = -61.0 +grow_horizontal = 0 +grow_vertical = 0 +mouse_default_cursor_shape = 2 +texture_normal = ExtResource("12_6pdc2") +texture_pressed = ExtResource("13_60s0a") + +[node name="IntelligenceButton" type="TextureButton" parent="Control"] +texture_filter = 1 +layout_mode = 1 +anchors_preset = 7 +anchor_left = 0.5 +anchor_top = 1.0 +anchor_right = 0.5 +anchor_bottom = 1.0 +offset_left = -18.0 +offset_top = -40.0 +offset_right = 22.0 +grow_horizontal = 2 +grow_vertical = 0 +mouse_default_cursor_shape = 2 +texture_normal = ExtResource("14_ufd68") +texture_pressed = ExtResource("15_uors6") + +[node name="DexterityButton" type="TextureButton" parent="Control"] +texture_filter = 1 +layout_mode = 1 +anchors_preset = 2 +anchor_top = 1.0 +anchor_bottom = 1.0 +offset_left = 9.0 +offset_top = -104.0 +offset_right = 49.0 +offset_bottom = -64.0 +grow_vertical = 0 +mouse_default_cursor_shape = 2 +texture_normal = ExtResource("16_kbej0") +texture_pressed = ExtResource("17_1iw4y") + +[node name="AgilityButton" type="TextureButton" parent="Control"] +texture_filter = 1 +layout_mode = 1 +offset_left = 8.0 +offset_top = 67.0 +offset_right = 48.0 +offset_bottom = 107.0 +mouse_default_cursor_shape = 2 +texture_normal = ExtResource("18_225jb") +texture_pressed = ExtResource("19_b1a0f") + +[node name="VBoxContainer2" type="VBoxContainer" parent="."] +layout_mode = 2 +theme_override_constants/separation = 1 + +[node name="StatEntryStrength" parent="VBoxContainer2" instance=ExtResource("14_b1a0f")] +unique_name_in_owner = true +layout_mode = 2 +theme_override_constants/separation = 0 +label = "STR" +value = 5 +value_alignment = 1 + +[node name="StatEntryAgility" parent="VBoxContainer2" instance=ExtResource("14_b1a0f")] +unique_name_in_owner = true +layout_mode = 2 +theme_override_constants/separation = 0 +label = "AGI" +value = 5 +value_alignment = 1 + +[node name="StatEntryVitality" parent="VBoxContainer2" instance=ExtResource("14_b1a0f")] +unique_name_in_owner = true +layout_mode = 2 +theme_override_constants/separation = 0 +label = "VIT" +value = 5 +value_alignment = 1 + +[node name="StatEntryIntelligence" parent="VBoxContainer2" instance=ExtResource("14_b1a0f")] +unique_name_in_owner = true +layout_mode = 2 +theme_override_constants/separation = 0 +label = "INT" +value = 5 +value_alignment = 1 + +[node name="StatEntryDexterity" parent="VBoxContainer2" instance=ExtResource("14_b1a0f")] +unique_name_in_owner = true +layout_mode = 2 +theme_override_constants/separation = 0 +label = "DEX" +value = 5 +value_alignment = 1 + +[node name="StatEntryLuck" parent="VBoxContainer2" instance=ExtResource("14_b1a0f")] +unique_name_in_owner = true +layout_mode = 2 +theme_override_constants/separation = 0 +label = "LUK" +value = 5 +value_alignment = 1 + +[connection signal="pressed" from="VBoxContainer/Control/AppearanceLeftButton" to="." method="_on_appearance_left_button_pressed"] +[connection signal="pressed" from="VBoxContainer/Control/AppearanceRightButton" to="." method="_on_appearance_right_button_pressed"] +[connection signal="pressed" from="VBoxContainer/Control/AppearanceUpButton" to="." method="_on_appearance_up_button_pressed"] +[connection signal="text_changed" from="VBoxContainer/HBoxContainer/Name" to="." method="_on_name_text_changed"] +[connection signal="pressed" from="Control/StrengthButton" to="." method="_on_strength_button_pressed"] +[connection signal="pressed" from="Control/VitalityButton" to="." method="_on_vitality_button_pressed"] +[connection signal="pressed" from="Control/LuckButton" to="." method="_on_luck_button_pressed"] +[connection signal="pressed" from="Control/IntelligenceButton" to="." method="_on_intelligence_button_pressed"] +[connection signal="pressed" from="Control/DexterityButton" to="." method="_on_dexterity_button_pressed"] +[connection signal="pressed" from="Control/AgilityButton" to="." method="_on_agility_button_pressed"] diff --git a/ui/login/character_selection_item.tscn b/ui/login/character_selection_item.tscn index de28392..0dab44c 100644 --- a/ui/login/character_selection_item.tscn +++ b/ui/login/character_selection_item.tscn @@ -1,10 +1,10 @@ [gd_scene load_steps=7 format=3 uid="uid://rrd131rq74n5"] [ext_resource type="Script" uid="uid://bsglhorusc7ug" path="res://ui/login/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"] +[ext_resource type="Texture2D" uid="uid://ci2liot5s8jnb" path="res://client_data/data/sprite/인간족/머리통/남/16_남/000.png" id="2_u21ok"] +[ext_resource type="Texture2D" uid="uid://be3ax80esna7b" path="res://client_data/data/sprite/인간족/몸통/남/초보자_남/000.png" id="3_vhrt2"] [ext_resource type="PackedScene" uid="uid://knmmuhon34rh" path="res://ui/bmp_texture_rect.tscn" id="4_vhrt2"] -[ext_resource type="Texture2D" uid="uid://1s8lrydoctbv" path="res://client_data/data/texture/À¯ÀúÀÎÅÍÆäÀ̽º/login_interface/box_select.png" id="5_vhrt2"] +[ext_resource type="Texture2D" uid="uid://bfe86fb6ytqg3" path="res://client_data/data/texture/유저인터페이스/login_interface/box_select.png" id="5_vhrt2"] [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_u21ok"] bg_color = Color(0, 0, 0, 0.0980392) @@ -43,14 +43,14 @@ unique_name_in_owner = true z_index = 1 texture_filter = 1 layout_mode = 2 -texture = ExtResource("2_aqbfs") +texture = ExtResource("2_u21ok") stretch_mode = 3 [node name="Body" type="TextureRect" parent="MarginContainer/VBoxContainer/Sprite"] unique_name_in_owner = true texture_filter = 1 layout_mode = 2 -texture = ExtResource("3_xv3pn") +texture = ExtResource("3_vhrt2") stretch_mode = 3 [node name="SelectionBorder" parent="." instance=ExtResource("4_vhrt2")] diff --git a/ui/login/login_character_selection_list.gd b/ui/login/login_character_selection_list.gd index bd19fa1..7ff43cf 100644 --- a/ui/login/login_character_selection_list.gd +++ b/ui/login/login_character_selection_list.gd @@ -76,6 +76,11 @@ func set_login_character_list(value: LoginCharacterList) -> void: draw() +func add_character_information(info: CharacterInformation) -> void: + login_character_list.add_character_information(info) + draw() + + func draw(): if not login_character_list: return diff --git a/ui/login/login_character_selection_list.tscn b/ui/login/login_character_selection_list.tscn index 02a9dc2..373dcde 100644 --- a/ui/login/login_character_selection_list.tscn +++ b/ui/login/login_character_selection_list.tscn @@ -4,12 +4,12 @@ [ext_resource type="Script" uid="uid://dmch4gi1khn2r" path="res://ui/login/login_character_selection_list.gd" id="1_togb6"] [ext_resource type="PackedScene" uid="uid://rrd131rq74n5" path="res://ui/login/character_selection_item.tscn" id="2_k142l"] [ext_resource type="PackedScene" uid="uid://cjcm2mai50thr" path="res://ui/bmp_texture_button.tscn" id="2_s7n6r"] -[ext_resource type="Texture2D" uid="uid://cey66pn46da80" path="res://client_data/data/texture/À¯ÀúÀÎÅÍÆäÀ̽º/select_character/chr_arrow_l_out.png" id="3_wnv6e"] -[ext_resource type="Texture2D" uid="uid://bbs77ppnvcm23" path="res://client_data/data/texture/À¯ÀúÀÎÅÍÆäÀ̽º/select_character/chr_arrow_l_press.png" id="4_rdaw5"] -[ext_resource type="Texture2D" uid="uid://c4supu7w8gabw" path="res://client_data/data/texture/À¯ÀúÀÎÅÍÆäÀ̽º/select_character/chr_arrow_l_over.png" id="5_1vggc"] -[ext_resource type="Texture2D" uid="uid://dqweltumn8n7t" path="res://client_data/data/texture/À¯ÀúÀÎÅÍÆäÀ̽º/select_character/chr_arrow_r_out.png" id="7_wnv6e"] -[ext_resource type="Texture2D" uid="uid://bsdygckmj667w" path="res://client_data/data/texture/À¯ÀúÀÎÅÍÆäÀ̽º/select_character/chr_arrow_r_press.png" id="8_rdaw5"] -[ext_resource type="Texture2D" uid="uid://dqdmks4uak1go" path="res://client_data/data/texture/À¯ÀúÀÎÅÍÆäÀ̽º/select_character/chr_arrow_r_over.png" id="9_1vggc"] +[ext_resource type="Texture2D" uid="uid://c1cgkiyacvr4k" path="res://client_data/data/texture/유저인터페이스/styleshop/chr_arrow_l_out.png" id="3_wnv6e"] +[ext_resource type="Texture2D" uid="uid://dar08umwslovr" path="res://client_data/data/texture/유저인터페이스/styleshop/chr_arrow_l_press.png" id="4_wnv6e"] +[ext_resource type="Texture2D" uid="uid://b38efa2wsrsiw" path="res://client_data/data/texture/유저인터페이스/styleshop/chr_arrow_l_over.png" id="5_wnv6e"] +[ext_resource type="Texture2D" uid="uid://cjmj1etf1wth7" path="res://client_data/data/texture/유저인터페이스/styleshop/chr_arrow_r_out.png" id="7_1vggc"] +[ext_resource type="Texture2D" uid="uid://deorq2yjwe4ie" path="res://client_data/data/texture/유저인터페이스/styleshop/chr_arrow_r_press.png" id="8_1oc8k"] +[ext_resource type="Texture2D" uid="uid://ccfm5ls854xpf" path="res://client_data/data/texture/유저인터페이스/styleshop/chr_arrow_r_over.png" id="9_muwiy"] [node name="LoginCharacterSelectionList" type="VBoxContainer"] theme_override_constants/separation = 32 @@ -31,8 +31,8 @@ unique_name_in_owner = true texture_filter = 0 layout_mode = 2 texture_normal = ExtResource("3_wnv6e") -texture_pressed = ExtResource("4_rdaw5") -texture_hover = ExtResource("5_1vggc") +texture_pressed = ExtResource("4_wnv6e") +texture_hover = ExtResource("5_wnv6e") stretch_mode = 5 [node name="CharacterList" type="HBoxContainer" parent="MarginContainer/HBoxContainer"] @@ -50,9 +50,9 @@ layout_mode = 2 unique_name_in_owner = true texture_filter = 0 layout_mode = 2 -texture_normal = ExtResource("7_wnv6e") -texture_pressed = ExtResource("8_rdaw5") -texture_hover = ExtResource("9_1vggc") +texture_normal = ExtResource("7_1vggc") +texture_pressed = ExtResource("8_1oc8k") +texture_hover = ExtResource("9_muwiy") stretch_mode = 5 [node name="CharacterSelectionStatus" parent="." instance=ExtResource("1_5anyi")] diff --git a/ui/login/stat_entry.gd b/ui/login/stat_entry.gd new file mode 100644 index 0000000..6d79ac0 --- /dev/null +++ b/ui/login/stat_entry.gd @@ -0,0 +1,18 @@ +@tool +extends HBoxContainer + + +@export var label: String: + set(value): + label = value + $Label.text = value + +@export var value: int: + set(v): + value = v + $Value.text = str(v) + +@export var value_alignment: HorizontalAlignment: + set(value): + value_alignment = value + $Value.horizontal_alignment = value diff --git a/ui/login/stat_entry.tscn b/ui/login/stat_entry.tscn new file mode 100644 index 0000000..91e9abe --- /dev/null +++ b/ui/login/stat_entry.tscn @@ -0,0 +1,24 @@ +[gd_scene load_steps=3 format=3 uid="uid://cff164qwvlsqd"] + +[ext_resource type="Theme" uid="uid://c6y6r8kcnbb10" path="res://ui/theme_clear.tres" id="1_3i1yo"] +[ext_resource type="Script" uid="uid://bjdgrc1kwcbtj" path="res://ui/login/stat_entry.gd" id="1_vt1a4"] + +[node name="StatEntry" type="HBoxContainer"] +offset_right = 169.0 +offset_bottom = 20.0 +script = ExtResource("1_vt1a4") + +[node name="Label" type="Label" parent="."] +custom_minimum_size = Vector2(45, 0) +layout_mode = 2 +theme = ExtResource("1_3i1yo") +theme_type_variation = &"CharacterSelectionStatusLabel" +text = "Label" + +[node name="Value" type="Label" parent="."] +custom_minimum_size = Vector2(120, 0) +layout_mode = 2 +size_flags_horizontal = 3 +theme = ExtResource("1_3i1yo") +theme_type_variation = &"CharacterSelectionStatusLabel2" +text = "value" diff --git a/ui/message_window.tscn b/ui/message_window.tscn index 5c195bf..b46fbe3 100644 --- a/ui/message_window.tscn +++ b/ui/message_window.tscn @@ -4,9 +4,9 @@ [ext_resource type="PackedScene" uid="uid://cjcm2mai50thr" path="res://ui/bmp_texture_button.tscn" id="2_3gmlp"] [ext_resource type="Theme" uid="uid://c6y6r8kcnbb10" path="res://ui/theme_clear.tres" id="2_prcjf"] [ext_resource type="Script" uid="uid://o36qsov00kwb" path="res://ui/message_window.gd" id="2_rr7kw"] -[ext_resource type="Texture2D" uid="uid://b1yjeotua8xj5" path="res://client_data/data/texture/À¯ÀúÀÎÅÍÆäÀ̽º/btn_close.bmp" id="3_prcjf"] -[ext_resource type="Texture2D" uid="uid://d4mycn8dag5yl" path="res://client_data/data/texture/À¯ÀúÀÎÅÍÆäÀ̽º/inventory/btn_close_press.bmp" id="4_rr7kw"] -[ext_resource type="Texture2D" uid="uid://ds70r0x5vvy6t" path="res://client_data/data/texture/À¯ÀúÀÎÅÍÆäÀ̽º/basic_interface/btn_close_a.bmp" id="5_ql6vf"] +[ext_resource type="Texture2D" uid="uid://b0o61r0oau4k7" path="res://client_data/data/texture/유저인터페이스/btn_close.png" id="5_m5dfh"] +[ext_resource type="Texture2D" uid="uid://6sx7uu2xjc4" path="res://client_data/data/texture/유저인터페이스/btn_close_b.png" id="6_m5dfh"] +[ext_resource type="Texture2D" uid="uid://bdxjoywe2tdif" path="res://client_data/data/texture/유저인터페이스/btn_close_a.png" id="7_a7gey"] [node name="MessageWindow" instance=ExtResource("1_m7647")] offset_right = 63.0 @@ -40,8 +40,8 @@ text = "Message" unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 8 -texture_normal = ExtResource("3_prcjf") -texture_pressed = ExtResource("4_rr7kw") -texture_hover = ExtResource("5_ql6vf") +texture_normal = ExtResource("5_m5dfh") +texture_pressed = ExtResource("6_m5dfh") +texture_hover = ExtResource("7_a7gey") [connection signal="pressed" from="VBoxContainer/ButtonBar/ButtonBarElements/CloseButtonBottom" to="." method="_on_close_button_bottom_pressed"] diff --git a/ui/theme.tres b/ui/theme.tres index 69ad428..a2a513d 100644 --- a/ui/theme.tres +++ b/ui/theme.tres @@ -1,29 +1,20 @@ -[gd_resource type="Theme" load_steps=9 format=3 uid="uid://c5sm3yvuakj3b"] - -[ext_resource type="Texture2D" uid="uid://34bqfgx41tf0" path="res://client_data/data/texture/À¯ÀúÀÎÅÍÆäÀ̽º/login_interface/bt_otp_over.png" id="1_iqtc0"] -[ext_resource type="Texture2D" uid="uid://cehi7txcq4p2q" path="res://client_data/data/texture/À¯ÀúÀÎÅÍÆäÀ̽º/login_interface/name-edit.bmp" id="1_rqugq"] -[ext_resource type="Texture2D" uid="uid://b63yrv7hceon4" path="res://client_data/data/texture/À¯ÀúÀÎÅÍÆäÀ̽º/login_interface/bt_otp_normal.png" id="2_7any1"] -[ext_resource type="Texture2D" uid="uid://yew2ev1s10pk" path="res://client_data/data/texture/À¯ÀúÀÎÅÍÆäÀ̽º/login_interface/bt_otp_press.png" id="3_3fgq6"] +[gd_resource type="Theme" load_steps=5 format=3 uid="uid://c5sm3yvuakj3b"] [sub_resource type="StyleBoxTexture" id="StyleBoxTexture_y5ki2"] -texture = ExtResource("1_iqtc0") [sub_resource type="StyleBoxTexture" id="StyleBoxTexture_rtqkv"] content_margin_left = 4.0 content_margin_top = 2.0 content_margin_right = 4.0 content_margin_bottom = 2.0 -texture = ExtResource("2_7any1") [sub_resource type="StyleBoxTexture" id="StyleBoxTexture_47c11"] -texture = ExtResource("3_3fgq6") [sub_resource type="StyleBoxTexture" id="StyleBoxTexture_jf26r"] content_margin_left = 4.0 content_margin_top = 4.0 content_margin_right = 4.0 content_margin_bottom = 4.0 -texture = ExtResource("1_rqugq") [resource] Button/colors/font_color = Color(0.133333, 0.133333, 0.133333, 1) diff --git a/ui/theme_clear.tres b/ui/theme_clear.tres index f5028a8..7fa57f0 100644 --- a/ui/theme_clear.tres +++ b/ui/theme_clear.tres @@ -52,7 +52,7 @@ content_margin_left = 3.0 content_margin_top = 0.0 content_margin_right = 3.0 content_margin_bottom = 0.0 -bg_color = Color(0.94902, 0.94902, 0.94902, 1) +bg_color = Color(0.980392, 0.980392, 0.980392, 1) border_width_left = 1 border_width_top = 1 border_width_right = 1 diff --git a/ui/window.tscn b/ui/window.tscn index d27d7c5..f0c3d95 100644 --- a/ui/window.tscn +++ b/ui/window.tscn @@ -2,17 +2,17 @@ [ext_resource type="PackedScene" uid="uid://knmmuhon34rh" path="res://ui/bmp_texture_rect.tscn" id="1_4qpm3"] [ext_resource type="Script" uid="uid://qdg2tjk8xmjt" path="res://ui/window.gd" id="1_hfgic"] -[ext_resource type="Texture2D" uid="uid://22px3uxdg48t" path="res://client_data/data/texture/À¯ÀúÀÎÅÍÆäÀ̽º/basic_interface/titlebar_left.png" id="3_74c65"] -[ext_resource type="Texture2D" uid="uid://dc2f7tx5xsico" path="res://client_data/data/texture/À¯ÀúÀÎÅÍÆäÀ̽º/basic_interface/titlebar_mid.bmp" id="3_mngfx"] -[ext_resource type="Texture2D" uid="uid://dkqx0rjvi6aba" path="res://client_data/data/texture/À¯ÀúÀÎÅÍÆäÀ̽º/basic_interface/titlebar_right.png" id="5_qkejn"] -[ext_resource type="Texture2D" uid="uid://clqwl83uoxeue" path="res://client_data/data/texture/À¯ÀúÀÎÅÍÆäÀ̽º/basic_interface/btnbar_mid1.bmp" id="6_mnaxm"] -[ext_resource type="Texture2D" uid="uid://dmuuq7siyfv4r" path="res://client_data/data/texture/À¯ÀúÀÎÅÍÆäÀ̽º/basic_interface/sys_base_off.png" id="6_uftm1"] +[ext_resource type="Texture2D" uid="uid://b40mcjrv0d0gi" path="res://client_data/data/texture/유저인터페이스/basic_interface/titlebar_left.png" id="3_74c65"] +[ext_resource type="Texture2D" uid="uid://b3d3jmq8eso2v" path="res://client_data/data/texture/유저인터페이스/basic_interface/titlebar_mid.png" id="4_qkejn"] +[ext_resource type="Texture2D" uid="uid://d22mmihwnjj0c" path="res://client_data/data/texture/유저인터페이스/basic_interface/titlebar_right.png" id="5_uftm1"] +[ext_resource type="Texture2D" uid="uid://dwv8ca3u5xk3o" path="res://client_data/data/texture/유저인터페이스/basic_interface/sys_base_off.png" id="6_74c65"] [ext_resource type="PackedScene" uid="uid://cjcm2mai50thr" path="res://ui/bmp_texture_button.tscn" id="7_m42e5"] -[ext_resource type="Texture2D" uid="uid://dtaegqi7vx4ia" path="res://client_data/data/texture/À¯ÀúÀÎÅÍÆäÀ̽º/basic_interface/big_sys_close_off.png" id="8_vjbfl"] -[ext_resource type="Texture2D" uid="uid://jwguf7fj0iyx" path="res://client_data/data/texture/À¯ÀúÀÎÅÍÆäÀ̽º/basic_interface/big_sys_close_on.png" id="9_kh8ey"] -[ext_resource type="Texture2D" uid="uid://dif01o7ri7qop" path="res://client_data/data/texture/À¯ÀúÀÎÅÍÆäÀ̽º/basic_interface/btnbar_left1.png" id="10_ug6hj"] -[ext_resource type="Texture2D" uid="uid://bp60ikxqixf6q" path="res://client_data/data/texture/À¯ÀúÀÎÅÍÆäÀ̽º/basic_interface/btnbar_right1.png" id="12_xgidv"] -[ext_resource type="Texture2D" uid="uid://ch1t3k18kvhtk" path="res://client_data/data/texture/À¯ÀúÀÎÅÍÆäÀ̽º/basic_interface/btn_comparison_resize.png" id="13_sy0l2"] +[ext_resource type="Texture2D" uid="uid://dt2t71nhoaelo" path="res://client_data/data/texture/유저인터페이스/basic_interface/big_sys_close_off.png" id="8_74c65"] +[ext_resource type="Texture2D" uid="uid://dguxqcl61xj50" path="res://client_data/data/texture/유저인터페이스/basic_interface/big_sys_close_on.png" id="9_qkejn"] +[ext_resource type="Texture2D" uid="uid://k78jsflcoc84" path="res://client_data/data/texture/유저인터페이스/basic_interface/btnbar_left1.png" id="10_74c65"] +[ext_resource type="Texture2D" uid="uid://bn66ekthd5657" path="res://client_data/data/texture/유저인터페이스/basic_interface/btnbar_mid1.png" id="11_qkejn"] +[ext_resource type="Texture2D" uid="uid://bwi568g2qyf3o" path="res://client_data/data/texture/유저인터페이스/basic_interface/btnbar_right1.png" id="12_uftm1"] +[ext_resource type="Texture2D" uid="uid://cygyjjv5s6dx0" path="res://client_data/data/texture/유저인터페이스/basic_interface/btn_comparison_resize.png" id="13_74c65"] [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_fufdc"] bg_color = Color(1, 1, 1, 1) @@ -45,11 +45,11 @@ texture = ExtResource("3_74c65") [node name="Middle" parent="VBoxContainer/TitleBar/TitleBarBackground" instance=ExtResource("1_4qpm3")] layout_mode = 2 size_flags_horizontal = 3 -texture = ExtResource("3_mngfx") +texture = ExtResource("4_qkejn") [node name="Right" parent="VBoxContainer/TitleBar/TitleBarBackground" instance=ExtResource("1_4qpm3")] layout_mode = 2 -texture = ExtResource("5_qkejn") +texture = ExtResource("5_uftm1") [node name="TitleBarElements" type="MarginContainer" parent="VBoxContainer/TitleBar"] unique_name_in_owner = true @@ -67,15 +67,15 @@ theme_override_constants/margin_right = 2 [node name="BMPTextureRect" parent="VBoxContainer/TitleBar/TitleBarButtons" instance=ExtResource("1_4qpm3")] layout_mode = 2 size_flags_horizontal = 0 -texture = ExtResource("6_uftm1") +texture = ExtResource("6_74c65") stretch_mode = 3 [node name="CloseButton" parent="VBoxContainer/TitleBar/TitleBarButtons" instance=ExtResource("7_m42e5")] unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 8 -texture_normal = ExtResource("8_vjbfl") -texture_hover = ExtResource("9_kh8ey") +texture_normal = ExtResource("8_74c65") +texture_hover = ExtResource("9_qkejn") stretch_mode = 5 [node name="Body" type="PanelContainer" parent="VBoxContainer"] @@ -94,16 +94,16 @@ theme_override_constants/separation = 0 [node name="BMPTextureRect" parent="VBoxContainer/ButtonBar/ButtonBarBackground" instance=ExtResource("1_4qpm3")] layout_mode = 2 -texture = ExtResource("10_ug6hj") +texture = ExtResource("10_74c65") [node name="BMPTextureRect2" parent="VBoxContainer/ButtonBar/ButtonBarBackground" instance=ExtResource("1_4qpm3")] layout_mode = 2 size_flags_horizontal = 3 -texture = ExtResource("6_mnaxm") +texture = ExtResource("11_qkejn") [node name="BMPTextureRect3" parent="VBoxContainer/ButtonBar/ButtonBarBackground" instance=ExtResource("1_4qpm3")] layout_mode = 2 -texture = ExtResource("12_xgidv") +texture = ExtResource("12_uftm1") [node name="ButtonBarElements" type="MarginContainer" parent="VBoxContainer/ButtonBar"] unique_name_in_owner = true @@ -120,7 +120,7 @@ layout_mode = 2 size_flags_horizontal = 8 size_flags_vertical = 8 mouse_default_cursor_shape = 2 -texture = ExtResource("13_sy0l2") +texture = ExtResource("13_74c65") stretch_mode = 5 [connection signal="gui_input" from="VBoxContainer/TitleBar" to="." method="_on_title_bar_gui_input"] |