diff --git a/src/lobby/client_select_data.rs b/src/lobby/client_select_data.rs index 7c5ec1f..5e4cb03 100644 --- a/src/lobby/client_select_data.rs +++ b/src/lobby/client_select_data.rs @@ -2,6 +2,18 @@ use serde_json::json; use crate::common::CustomizeData; +// TODO: this isn't really an enum in the game, nor is it a flag either. it's weird! +#[derive(Clone, Copy)] +#[repr(i32)] +pub enum RemakeMode { + /// No remake options are available. + None, + /// "You are granted one opportunity to edit your character's race, tribe, gender, appearance, and name." + EditAppearanceName = 1, + /// "If you wish, you can edit your character's race, sex, and appearance." + EditAppearance = 4, +} + /// See https://github.com/aers/FFXIVClientStructs/blob/main/FFXIVClientStructs/FFXIV/Application/Network/WorkDefinitions/ClientSelectData.cs pub struct ClientSelectData { pub game_name_unk: String, @@ -16,16 +28,18 @@ pub struct ClientSelectData { pub unk8: i32, pub unk9: i32, pub zone_id: i32, - pub unk11: i32, + /// Index into the ContentFinderCondition Excel sheet (presumably). But if != 0, then it does special things to the Lobby screen. + /// The most notable is if your character can be remade, it says "Your character is currently bound by duty..." + pub content_finder_condition: i32, pub customize: CustomizeData, pub model_main_weapon: i32, pub model_sub_weapon: i32, pub unk14: [i32; 10], // probably model ids pub unk15: i32, pub unk16: i32, - /// If set to 1, the user is granted one opportunity to edit their character and are prompted to re-choose their class. - pub legacy_character: i32, - pub unk18: i32, + pub remake_mode: RemakeMode, // TODO: upstream a comment about this to FFXIVClientStructs + /// If above 0, then a message warns the user that they have X minutes left to remake their character. + pub remake_minutes_remaining: i32, pub unk19: i32, pub unk20: i32, pub world_name: String, @@ -48,15 +62,15 @@ impl ClientSelectData { self.unk8.to_string(), self.unk9.to_string(), self.zone_id.to_string(), - self.unk11.to_string(), + self.content_finder_condition.to_string(), self.customize.to_json(), self.model_main_weapon.to_string(), self.model_sub_weapon.to_string(), self.unk14.map(|x| x.to_string()), self.unk15.to_string(), self.unk16.to_string(), - self.legacy_character.to_string(), - self.unk18.to_string(), + (self.remake_mode as i32).to_string(), + self.remake_minutes_remaining.to_string(), self.unk19.to_string(), self.unk20.to_string(), self.world_name, diff --git a/src/lobby/mod.rs b/src/lobby/mod.rs index 36bd454..e2afb98 100644 --- a/src/lobby/mod.rs +++ b/src/lobby/mod.rs @@ -2,7 +2,7 @@ mod chara_make; pub use chara_make::CharaMake; mod client_select_data; -pub use client_select_data::ClientSelectData; +pub use client_select_data::{ClientSelectData, RemakeMode}; mod connection; pub use connection::{LobbyConnection, send_custom_world_packet}; diff --git a/src/world/database.rs b/src/world/database.rs index d61353d..7e0352b 100644 --- a/src/world/database.rs +++ b/src/world/database.rs @@ -5,8 +5,7 @@ use rusqlite::Connection; use crate::{ common::Position, lobby::{ - CharaMake, ClientSelectData, - ipc::{CharacterDetails, CharacterFlag}, + ipc::{CharacterDetails, CharacterFlag}, CharaMake, ClientSelectData, RemakeMode }, }; @@ -173,23 +172,23 @@ impl WorldDatabase { birth_month: chara_make.birth_month, birth_day: chara_make.birth_day, guardian: chara_make.guardian, - unk8: 255, - unk9: 255, + unk8: 0, + unk9: 0, zone_id: zone_id as i32, - unk11: 255, + content_finder_condition: 0, customize: chara_make.customize, model_main_weapon: 0, model_sub_weapon: 0, unk14: [0; 10], - unk15: 255, - unk16: 2, - legacy_character: 2, - unk18: 255, - unk19: 255, - unk20: 255, + unk15: 0, + unk16: 0, + remake_mode: RemakeMode::None, + remake_minutes_remaining: 0, + unk19: 0, + unk20: 0, world_name: String::new(), - unk22: 255, - unk23: 255, + unk22: 0, + unk23: 0, }; characters.push(CharacterDetails {