diff --git a/src/bin/kawari-world.rs b/src/bin/kawari-world.rs index e237ba9..e6b3acd 100644 --- a/src/bin/kawari-world.rs +++ b/src/bin/kawari-world.rs @@ -1,11 +1,14 @@ use std::time::{SystemTime, UNIX_EPOCH}; -use kawari::ipc::{ActorControlType, IPCOpCode, IPCSegment, IPCStructData}; +use kawari::ipc::{IPCOpCode, IPCSegment, IPCStructData}; use kawari::oodle::FFXIVOodle; use kawari::packet::{ CompressionType, PacketSegment, SegmentType, State, parse_packet, send_keep_alive, send_packet, }; -use kawari::world::{PlayerSpawnData, Position}; +use kawari::world::{ + ActorControlSelf, ActorControlType, InitZone, PlayerSetup, PlayerSpawn, PlayerStats, + UpdateClassInfo, +}; use kawari::{CONTENT_ID, WORLD_ID, ZONE_ID}; use tokio::io::AsyncReadExt; use tokio::net::TcpListener; @@ -194,15 +197,18 @@ async fn main() { op_code: IPCOpCode::ActorControlSelf, server_id: 0, timestamp: timestamp_secs(), - data: IPCStructData::ActorControlSelf { - category: ActorControlType::SetCharaGearParamUI, - param1: 1, - param2: 1, - param3: 0, - param4: 0, - param5: 0, - param6: 0, - }, + data: IPCStructData::ActorControlSelf( + ActorControlSelf { + category: + ActorControlType::SetCharaGearParamUI, + param1: 1, + param2: 1, + param3: 0, + param4: 0, + param5: 0, + param6: 0, + }, + ), }; let response_packet = PacketSegment { @@ -227,39 +233,12 @@ async fn main() { op_code: IPCOpCode::PlayerStats, server_id: 0, timestamp: timestamp_secs(), - data: IPCStructData::PlayerStats { + data: IPCStructData::PlayerStats(PlayerStats { strength: 1, - dexterity: 0, - vitality: 0, - intelligence: 0, - mind: 0, - piety: 0, hp: 100, mp: 100, - tp: 0, - gp: 0, - cp: 0, - delay: 0, - tenacity: 0, - attack_power: 0, - defense: 0, - direct_hit_rate: 0, - evasion: 0, - magic_defense: 0, - critical_hit: 0, - attack_magic_potency: 0, - healing_magic_potency: 0, - elemental_bonus: 0, - determination: 0, - skill_speed: 0, - spell_speed: 0, - haste: 0, - craftmanship: 0, - control: 0, - gathering: 0, - perception: 0, - unk1: [0; 26], - }, + ..Default::default() + }), }; let response_packet = PacketSegment { @@ -284,127 +263,13 @@ async fn main() { op_code: IPCOpCode::PlayerSetup, server_id: 0, timestamp: timestamp_secs(), - data: IPCStructData::PlayerSetup { + data: IPCStructData::PlayerSetup(PlayerSetup { content_id: CONTENT_ID, - crest: 0, - unknown10: 0, - char_id: 0, - rested_exp: 0, - companion_current_exp: 0, - unknown1c: 0, - fish_caught: 0, - use_bait_catalog_id: 0, - unknown28: 0, - unknown_pvp2c: 0, - unknown2e: 0, - pvp_frontline_overall_campaigns: 0, - unknown_timestamp34: 0, - unknown_timestamp38: 0, - unknown3c: 0, - unknown40: 0, - unknown44: 0, - companion_time_passed: 0.0, - unknown4c: 0, - unknown50: 0, - unknown_pvp52: [0; 4], - pvp_series_exp: 0, - player_commendations: 0, - unknown64: [0; 8], - pvp_rival_wings_total_matches: 0, - pvp_rival_wings_total_victories: 0, - pvp_rival_wings_weekly_matches: 0, - pvp_rival_wings_weekly_victories: 0, - max_level: 0, - expansion: 0, - unknown76: 0, - unknown77: 0, - unknown78: 0, - race: 0, - tribe: 0, - gender: 0, - current_job: 0, - current_class: 0, - deity: 0, - nameday_month: 0, - nameday_day: 0, - city_state: 0, - homepoint: 0, - unknown8d: [0; 3], - companion_rank: 0, - companion_stars: 0, - companion_sp: 0, - companion_unk93: 0, - companion_color: 0, - companion_fav_feed: 0, - fav_aetheryte_count: 0, - unknown97: [0; 5], - sightseeing21_to_80_unlock: 0, - sightseeing_heavensward_unlock: 0, - unknown9e: [0; 26], exp: [10000; 32], - pvp_total_exp: 0, - unknown_pvp124: 0, - pvp_exp: 0, - pvp_frontline_overall_ranks: [0; 3], - unknown138: 0, levels: [100; 32], - unknown194: [0; 218], - companion_name: [0; 21], - companion_def_rank: 0, - companion_att_rank: 0, - companion_heal_rank: 0, - mount_guide_mask: [0; 33], - ornament_mask: [0; 4], - unknown281: [0; 23], name: "KAWARI".to_string(), - unknown293: [0; 16], - unknown2a3: 0, - unlock_bitmask: [0; 64], - aetheryte: [0; 26], - favorite_aetheryte_ids: [0; 4], - free_aetheryte_id: 0, - ps_plus_free_aetheryte_id: 0, - discovery: [0; 480], - howto: [0; 36], - unknown554: [0; 4], - minions: [0; 60], - chocobo_taxi_mask: [0; 12], - watched_cutscenes: [0; 159], - companion_barding_mask: [0; 12], - companion_equipped_head: 0, - companion_equipped_body: 0, - companion_equipped_legs: 0, - unknown_mask: [0; 287], - pose: [0; 7], - unknown6df: [0; 3], - challenge_log_complete: [0; 13], - secret_recipe_book_mask: [0; 12], - unknown_mask6f7: [0; 29], - relic_completion: [0; 12], - sightseeing_mask: [0; 37], - hunting_mark_mask: [0; 102], - triple_triad_cards: [0; 45], - unknown895: 0, - unknown7d7: [0; 15], - unknown7d8: 0, - unknown7e6: [0; 49], - regional_folklore_mask: [0; 6], - orchestrion_mask: [0; 87], - hall_of_novice_completion: [0; 3], - anima_completion: [0; 11], - unknown85e: [0; 41], - unlocked_raids: [0; 28], - unlocked_dungeons: [0; 18], - unlocked_guildhests: [0; 10], - unlocked_trials: [0; 12], - unlocked_pvp: [0; 5], - cleared_raids: [0; 28], - cleared_dungeons: [0; 18], - cleared_guildhests: [0; 10], - cleared_trials: [0; 12], - cleared_pvp: [0; 5], - unknown948: [0; 15], - }, + ..Default::default() + }), }; let response_packet = PacketSegment { @@ -429,14 +294,15 @@ async fn main() { op_code: IPCOpCode::UpdateClassInfo, server_id: 69, // lol timestamp: timestamp_secs(), - data: IPCStructData::UpdateClassInfo { - class_id: 35, - unknown: 1, - is_specialist: 0, - synced_level: 90, - class_level: 90, - role_actions: [0; 10], - }, + data: IPCStructData::UpdateClassInfo( + UpdateClassInfo { + class_id: 35, + unknown: 1, + synced_level: 90, + class_level: 90, + ..Default::default() + }, + ), }; let response_packet = PacketSegment { @@ -461,29 +327,11 @@ async fn main() { op_code: IPCOpCode::InitZone, server_id: 0, timestamp: timestamp_secs(), - data: IPCStructData::InitZone { + data: IPCStructData::InitZone(InitZone { server_id: WORLD_ID, zone_id: ZONE_ID, - zone_index: 0, - content_finder_condition_id: 0, - layer_set_id: 0, - layout_id: 0, - weather_id: 1, - unk_bitmask1: 0x10, - unk_bitmask2: 0, - unk1: 0, - unk2: 0, - festival_id: 0, - additional_festival_id: 0, - unk3: 0, - unk4: 0, - unk5: 0, - unk6: [0; 4], - unk7: [0; 3], - position: Position::default(), - unk8: [0; 4], - unk9: 0, - }, + ..Default::default() + }), }; let response_packet = PacketSegment { @@ -514,7 +362,7 @@ async fn main() { server_id: 0, timestamp: timestamp_secs(), data: IPCStructData::PlayerSpawn( - PlayerSpawnData::default(), + PlayerSpawn::default(), ), }; diff --git a/src/ipc.rs b/src/ipc.rs index e7841ce..7855acb 100644 --- a/src/ipc.rs +++ b/src/ipc.rs @@ -2,7 +2,10 @@ use binrw::binrw; use crate::{ common::{read_string, write_string}, - world::{PlayerSpawnData, Position}, + world::{ + ActorControlSelf, InitZone, PlayerSetup, PlayerSpawn, PlayerStats, Position, + UpdateClassInfo, + }, }; // NOTE: See https://github.com/karashiiro/FFXIVOpcodes/blob/master/FFXIVOpcodes/Ipcs.cs for opcodes @@ -150,13 +153,6 @@ pub enum LobbyCharacterAction { Request = 0x15, } -#[binrw] -#[derive(Debug, Eq, PartialEq, Clone)] -#[brw(repr = u16)] -pub enum ActorControlType { - SetCharaGearParamUI = 0x260, -} - #[binrw] #[br(import(magic: &IPCOpCode))] #[derive(Debug, Clone)] @@ -350,212 +346,17 @@ pub enum IPCStructData { unk2: u32, }, #[br(pre_assert(false))] - InitZone { - server_id: u16, - zone_id: u16, - zone_index: u16, - content_finder_condition_id: u16, - layer_set_id: u32, - layout_id: u32, - weather_id: u32, - unk_bitmask1: u8, - unk_bitmask2: u8, - unk1: u8, - unk2: u32, - festival_id: u16, - additional_festival_id: u16, - unk3: u32, - unk4: u32, - unk5: u32, - unk6: [u32; 4], - unk7: [u32; 3], - position: Position, - unk8: [u32; 4], - unk9: u32, - }, + InitZone(InitZone), #[br(pre_assert(false))] - ActorControlSelf { - #[brw(pad_after = 2)] - category: ActorControlType, - param1: u32, - param2: u32, - param3: u32, - param4: u32, - param5: u32, - #[brw(pad_after = 4)] - param6: u32, - }, + ActorControlSelf(ActorControlSelf), #[br(pre_assert(false))] - PlayerStats { - strength: u32, - dexterity: u32, - vitality: u32, - intelligence: u32, - mind: u32, - piety: u32, - hp: u32, - mp: u32, - tp: u32, - gp: u32, - cp: u32, - delay: u32, - tenacity: u32, - attack_power: u32, - defense: u32, - direct_hit_rate: u32, - evasion: u32, - magic_defense: u32, - critical_hit: u32, - attack_magic_potency: u32, - healing_magic_potency: u32, - elemental_bonus: u32, - determination: u32, - skill_speed: u32, - spell_speed: u32, - haste: u32, - craftmanship: u32, - control: u32, - gathering: u32, - perception: u32, - unk1: [u32; 26], - }, + PlayerStats(PlayerStats), #[br(pre_assert(false))] - PlayerSetup { - content_id: u64, - crest: u64, - unknown10: u64, - char_id: u32, - rested_exp: u32, - companion_current_exp: u32, - unknown1c: u32, - fish_caught: u32, - use_bait_catalog_id: u32, - unknown28: u32, - unknown_pvp2c: u16, - unknown2e: u16, - pvp_frontline_overall_campaigns: u32, - unknown_timestamp34: u32, - unknown_timestamp38: u32, - unknown3c: u32, - unknown40: u32, - unknown44: u32, - companion_time_passed: f32, - unknown4c: u32, - unknown50: u16, - unknown_pvp52: [u16; 4], - pvp_series_exp: u16, - player_commendations: u16, - unknown64: [u16; 8], - pvp_rival_wings_total_matches: u16, - pvp_rival_wings_total_victories: u16, - pvp_rival_wings_weekly_matches: u16, - pvp_rival_wings_weekly_victories: u16, - max_level: u8, - expansion: u8, - unknown76: u8, - unknown77: u8, - unknown78: u8, - race: u8, - tribe: u8, - gender: u8, - current_job: u8, - current_class: u8, - deity: u8, - nameday_month: u8, - nameday_day: u8, - city_state: u8, - homepoint: u8, - unknown8d: [u8; 3], - companion_rank: u8, - companion_stars: u8, - companion_sp: u8, - companion_unk93: u8, - companion_color: u8, - companion_fav_feed: u8, - fav_aetheryte_count: u8, - unknown97: [u8; 5], - sightseeing21_to_80_unlock: u8, - sightseeing_heavensward_unlock: u8, - unknown9e: [u8; 26], - exp: [u32; 32], - pvp_total_exp: u32, - unknown_pvp124: u32, - pvp_exp: u32, - pvp_frontline_overall_ranks: [u32; 3], - unknown138: u32, - levels: [u16; 32], - unknown194: [u8; 218], - companion_name: [u8; 21], - companion_def_rank: u8, - companion_att_rank: u8, - companion_heal_rank: u8, - mount_guide_mask: [u8; 33], - ornament_mask: [u8; 4], - unknown281: [u8; 23], - #[br(count = 32)] - #[bw(pad_size_to = 32)] - #[br(map = read_string)] - #[bw(map = write_string)] - name: String, - unknown293: [u8; 16], - unknown2a3: u8, - unlock_bitmask: [u8; 64], - aetheryte: [u8; 26], - favorite_aetheryte_ids: [u16; 4], - free_aetheryte_id: u16, - ps_plus_free_aetheryte_id: u16, - discovery: [u8; 480], - howto: [u8; 36], - unknown554: [u8; 4], - minions: [u8; 60], - chocobo_taxi_mask: [u8; 12], - watched_cutscenes: [u8; 159], - companion_barding_mask: [u8; 12], - companion_equipped_head: u8, - companion_equipped_body: u8, - companion_equipped_legs: u8, - unknown_mask: [u8; 287], - pose: [u8; 7], - unknown6df: [u8; 3], - challenge_log_complete: [u8; 13], - secret_recipe_book_mask: [u8; 12], - unknown_mask6f7: [u8; 29], - relic_completion: [u8; 12], - sightseeing_mask: [u8; 37], - hunting_mark_mask: [u8; 102], - triple_triad_cards: [u8; 45], - unknown895: u8, - unknown7d7: [u8; 15], - unknown7d8: u8, - unknown7e6: [u8; 49], - regional_folklore_mask: [u8; 6], - orchestrion_mask: [u8; 87], - hall_of_novice_completion: [u8; 3], - anima_completion: [u8; 11], - unknown85e: [u8; 41], - unlocked_raids: [u8; 28], - unlocked_dungeons: [u8; 18], - unlocked_guildhests: [u8; 10], - unlocked_trials: [u8; 12], - unlocked_pvp: [u8; 5], - cleared_raids: [u8; 28], - cleared_dungeons: [u8; 18], - cleared_guildhests: [u8; 10], - cleared_trials: [u8; 12], - cleared_pvp: [u8; 5], - unknown948: [u8; 15], - }, + PlayerSetup(PlayerSetup), #[br(pre_assert(false))] - UpdateClassInfo { - class_id: u16, - unknown: u8, - is_specialist: u8, - synced_level: u16, - class_level: u16, - role_actions: [u32; 10], - }, + UpdateClassInfo(UpdateClassInfo), #[br(pre_assert(false))] - PlayerSpawn(PlayerSpawnData), + PlayerSpawn(PlayerSpawn), } #[binrw] @@ -651,15 +452,7 @@ mod tests { entitled_expansion: 0, characters: Vec::new(), }, - IPCStructData::ActorControlSelf { - category: ActorControlType::SetCharaGearParamUI, - param1: 0, - param2: 0, - param3: 0, - param4: 0, - param5: 0, - param6: 0, - }, + IPCStructData::ActorControlSelf(ActorControlSelf::default()), IPCStructData::InitializeChat { unk: [0; 8] }, ]; diff --git a/src/world/actor_control_self.rs b/src/world/actor_control_self.rs new file mode 100644 index 0000000..5ecc8d7 --- /dev/null +++ b/src/world/actor_control_self.rs @@ -0,0 +1,23 @@ +use binrw::binrw; + +#[binrw] +#[derive(Debug, Eq, PartialEq, Clone, Default)] +#[brw(repr = u16)] +pub enum ActorControlType { + #[default] + SetCharaGearParamUI = 0x260, +} + +#[binrw] +#[derive(Debug, Clone, Default)] +pub struct ActorControlSelf { + #[brw(pad_after = 2)] + pub category: ActorControlType, + pub param1: u32, + pub param2: u32, + pub param3: u32, + pub param4: u32, + pub param5: u32, + #[brw(pad_after = 4)] + pub param6: u32, +} diff --git a/src/world/init_zone.rs b/src/world/init_zone.rs new file mode 100644 index 0000000..ab42c73 --- /dev/null +++ b/src/world/init_zone.rs @@ -0,0 +1,29 @@ +use binrw::binrw; + +use super::Position; + +#[binrw] +#[derive(Debug, Clone, Default)] +pub struct InitZone { + pub server_id: u16, + pub zone_id: u16, + pub zone_index: u16, + pub content_finder_condition_id: u16, + pub layer_set_id: u32, + pub layout_id: u32, + pub weather_id: u32, + pub unk_bitmask1: u8, + pub unk_bitmask2: u8, + pub unk1: u8, + pub unk2: u32, + pub festival_id: u16, + pub additional_festival_id: u16, + pub unk3: u32, + pub unk4: u32, + pub unk5: u32, + pub unk6: [u32; 4], + pub unk7: [u32; 3], + pub position: Position, + pub unk8: [u32; 4], + pub unk9: u32, +} diff --git a/src/world/mod.rs b/src/world/mod.rs index c8e2ff9..7535a14 100644 --- a/src/world/mod.rs +++ b/src/world/mod.rs @@ -1,8 +1,24 @@ mod player_spawn; -pub use player_spawn::PlayerSpawnData; +pub use player_spawn::PlayerSpawn; mod position; pub use position::Position; mod status_effect; pub use status_effect::StatusEffect; + +mod update_class_info; +pub use update_class_info::UpdateClassInfo; + +mod player_setup; +pub use player_setup::PlayerSetup; + +mod player_stats; +pub use player_stats::PlayerStats; + +mod actor_control_self; +pub use actor_control_self::ActorControlSelf; +pub use actor_control_self::ActorControlType; + +mod init_zone; +pub use init_zone::InitZone; diff --git a/src/world/player_setup.rs b/src/world/player_setup.rs new file mode 100644 index 0000000..4af57e2 --- /dev/null +++ b/src/world/player_setup.rs @@ -0,0 +1,159 @@ +use binrw::binrw; + +use crate::common::{read_string, write_string}; + +#[binrw] +#[derive(Debug, Clone, Default)] +pub struct PlayerSetup { + pub content_id: u64, + pub crest: u64, + pub unknown10: u64, + pub char_id: u32, + pub rested_exp: u32, + pub companion_current_exp: u32, + pub unknown1c: u32, + pub fish_caught: u32, + pub use_bait_catalog_id: u32, + pub unknown28: u32, + pub unknown_pvp2c: u16, + pub unknown2e: u16, + pub pvp_frontline_overall_campaigns: u32, + pub unknown_timestamp34: u32, + pub unknown_timestamp38: u32, + pub unknown3c: u32, + pub unknown40: u32, + pub unknown44: u32, + pub companion_time_passed: f32, + pub unknown4c: u32, + pub unknown50: u16, + pub unknown_pvp52: [u16; 4], + pub pvp_series_exp: u16, + pub player_commendations: u16, + pub unknown64: [u16; 8], + pub pvp_rival_wings_total_matches: u16, + pub pvp_rival_wings_total_victories: u16, + pub pvp_rival_wings_weekly_matches: u16, + pub pvp_rival_wings_weekly_victories: u16, + pub max_level: u8, + pub expansion: u8, + pub unknown76: u8, + pub unknown77: u8, + pub unknown78: u8, + pub race: u8, + pub tribe: u8, + pub gender: u8, + pub current_job: u8, + pub current_class: u8, + pub deity: u8, + pub nameday_month: u8, + pub nameday_day: u8, + pub city_state: u8, + pub homepoint: u8, + pub unknown8d: [u8; 3], + pub companion_rank: u8, + pub companion_stars: u8, + pub companion_sp: u8, + pub companion_unk93: u8, + pub companion_color: u8, + pub companion_fav_feed: u8, + pub fav_aetheryte_count: u8, + pub unknown97: [u8; 5], + pub sightseeing21_to_80_unlock: u8, + pub sightseeing_heavensward_unlock: u8, + pub unknown9e: [u8; 26], + pub exp: [u32; 32], + pub pvp_total_exp: u32, + pub unknown_pvp124: u32, + pub pvp_exp: u32, + pub pvp_frontline_overall_ranks: [u32; 3], + pub unknown138: u32, + pub levels: [u16; 32], + #[br(count = 218)] + #[bw(pad_size_to = 218)] + pub unknown194: Vec, + pub companion_name: [u8; 21], + pub companion_def_rank: u8, + pub companion_att_rank: u8, + pub companion_heal_rank: u8, + #[br(count = 33)] + #[bw(pad_size_to = 33)] + pub mount_guide_mask: Vec, + pub ornament_mask: [u8; 4], + pub unknown281: [u8; 23], + #[br(count = 32)] + #[bw(pad_size_to = 32)] + #[br(map = read_string)] + #[bw(map = write_string)] + pub name: String, + pub unknown293: [u8; 16], + pub unknown2a3: u8, + #[br(count = 64)] + #[bw(pad_size_to = 64)] + pub unlock_bitmask: Vec, + pub aetheryte: [u8; 26], + pub favorite_aetheryte_ids: [u16; 4], + pub free_aetheryte_id: u16, + pub ps_plus_free_aetheryte_id: u16, + #[br(count = 480)] + #[bw(pad_size_to = 480)] + pub discovery: Vec, + #[br(count = 36)] + #[bw(pad_size_to = 36)] + pub howto: Vec, + pub unknown554: [u8; 4], + #[br(count = 60)] + #[bw(pad_size_to = 60)] + pub minions: Vec, + pub chocobo_taxi_mask: [u8; 12], + #[br(count = 159)] + #[bw(pad_size_to = 159)] + pub watched_cutscenes: Vec, + pub companion_barding_mask: [u8; 12], + pub companion_equipped_head: u8, + pub companion_equipped_body: u8, + pub companion_equipped_legs: u8, + #[br(count = 287)] + #[bw(pad_size_to = 287)] + pub unknown_mask: Vec, + pub pose: [u8; 7], + pub unknown6df: [u8; 3], + pub challenge_log_complete: [u8; 13], + pub secret_recipe_book_mask: [u8; 12], + pub unknown_mask6f7: [u8; 29], + pub relic_completion: [u8; 12], + #[br(count = 37)] + #[bw(pad_size_to = 37)] + pub sightseeing_mask: Vec, + #[br(count = 102)] + #[bw(pad_size_to = 102)] + pub hunting_mark_mask: Vec, + #[br(count = 45)] + #[bw(pad_size_to = 45)] + pub triple_triad_cards: Vec, + pub unknown895: u8, + pub unknown7d7: [u8; 15], + pub unknown7d8: u8, + #[br(count = 49)] + #[bw(pad_size_to = 49)] + pub unknown7e6: Vec, + pub regional_folklore_mask: [u8; 6], + #[br(count = 87)] + #[bw(pad_size_to = 87)] + pub orchestrion_mask: Vec, + pub hall_of_novice_completion: [u8; 3], + pub anima_completion: [u8; 11], + #[br(count = 41)] + #[bw(pad_size_to = 41)] + pub unknown85e: Vec, + pub unlocked_raids: [u8; 28], + pub unlocked_dungeons: [u8; 18], + pub unlocked_guildhests: [u8; 10], + pub unlocked_trials: [u8; 12], + pub unlocked_pvp: [u8; 5], + pub cleared_raids: [u8; 28], + pub cleared_dungeons: [u8; 18], + pub cleared_guildhests: [u8; 10], + pub cleared_trials: [u8; 12], + pub cleared_pvp: [u8; 5], + pub unknown948: [u8; 15], +} diff --git a/src/world/player_spawn.rs b/src/world/player_spawn.rs index f0a18ea..2226dba 100644 --- a/src/world/player_spawn.rs +++ b/src/world/player_spawn.rs @@ -4,8 +4,8 @@ use super::position::Position; use super::status_effect::StatusEffect; #[binrw] -#[derive(Debug, Clone, Default)] -pub struct PlayerSpawnData { +#[derive(Debug, Clone, Copy, Default)] +pub struct PlayerSpawn { pub title: u16, pub u1b: u16, pub current_world_id: u16, diff --git a/src/world/player_stats.rs b/src/world/player_stats.rs new file mode 100644 index 0000000..a336124 --- /dev/null +++ b/src/world/player_stats.rs @@ -0,0 +1,37 @@ +use binrw::binrw; + +#[binrw] +#[derive(Debug, Clone, Copy, Default)] +pub struct PlayerStats { + pub strength: u32, + pub dexterity: u32, + pub vitality: u32, + pub intelligence: u32, + pub mind: u32, + pub piety: u32, + pub hp: u32, + pub mp: u32, + pub tp: u32, + pub gp: u32, + pub cp: u32, + pub delay: u32, + pub tenacity: u32, + pub attack_power: u32, + pub defense: u32, + pub direct_hit_rate: u32, + pub evasion: u32, + pub magic_defense: u32, + pub critical_hit: u32, + pub attack_magic_potency: u32, + pub healing_magic_potency: u32, + pub elemental_bonus: u32, + pub determination: u32, + pub skill_speed: u32, + pub spell_speed: u32, + pub haste: u32, + pub craftmanship: u32, + pub control: u32, + pub gathering: u32, + pub perception: u32, + pub unk1: [u32; 26], +} diff --git a/src/world/position.rs b/src/world/position.rs index 1b07895..07a9bc0 100644 --- a/src/world/position.rs +++ b/src/world/position.rs @@ -1,7 +1,7 @@ use binrw::binrw; #[binrw] -#[derive(Debug, Clone, Default)] +#[derive(Debug, Clone, Copy, Default)] pub struct Position { pub x: f32, pub y: f32, diff --git a/src/world/update_class_info.rs b/src/world/update_class_info.rs new file mode 100644 index 0000000..93bcd1d --- /dev/null +++ b/src/world/update_class_info.rs @@ -0,0 +1,12 @@ +use binrw::binrw; + +#[binrw] +#[derive(Debug, Clone, Copy, Default)] +pub struct UpdateClassInfo { + pub class_id: u16, + pub unknown: u8, + pub is_specialist: u8, + pub synced_level: u16, + pub class_level: u16, + pub role_actions: [u32; 10], +}