2019-09-05 14:36:08 -07:00
|
|
|
// TODO: ch_class to CharacterClass enum
|
|
|
|
// TODO: section_id to SectionId enum
|
2019-11-08 22:51:59 -08:00
|
|
|
// TODO: techniques to enum
|
|
|
|
use psopacket::PSOPacketData;
|
|
|
|
use crate::{PSOPacketData, PacketParseError};
|
|
|
|
//use crate::PSOPacketData;
|
2019-09-05 14:36:08 -07:00
|
|
|
|
2020-04-19 23:15:26 -03:00
|
|
|
const DEFAULT_PALETTE_CONFIG: [u8; 0xE8] = [
|
|
|
|
0, 0, 0, 0,
|
|
|
|
1, 0, 0, 0,
|
|
|
|
2, 0, 1, 0,
|
|
|
|
2, 1, 1, 0,
|
|
|
|
4, 0, 1, 0,
|
|
|
|
0, 0, 1, 0,
|
|
|
|
0, 0, 1, 0,
|
|
|
|
0, 0, 1, 0,
|
|
|
|
0, 0, 1, 0,
|
|
|
|
0, 0, 1, 0,
|
|
|
|
0, 0, 1, 0,
|
|
|
|
0, 0, 1, 0,
|
|
|
|
0, 0, 1, 0,
|
|
|
|
0, 0, 1, 0,
|
|
|
|
0, 0, 1, 0,
|
|
|
|
1, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0
|
|
|
|
];
|
2019-12-03 21:40:31 -08:00
|
|
|
|
2020-04-20 00:31:27 -03:00
|
|
|
const DEFAULT_TECH_MENU: [u8; 40] = [
|
|
|
|
0x00, 0x00,
|
|
|
|
0x06, 0x00,
|
|
|
|
0x03, 0x00,
|
|
|
|
0x01, 0x00,
|
|
|
|
0x07, 0x00,
|
|
|
|
0x04, 0x00,
|
|
|
|
0x02, 0x00,
|
|
|
|
0x08, 0x00,
|
|
|
|
0x05, 0x00,
|
|
|
|
0x09, 0x00,
|
|
|
|
0x12, 0x00,
|
|
|
|
0x0f, 0x00,
|
|
|
|
0x10, 0x00,
|
|
|
|
0x11, 0x00,
|
|
|
|
0x0d, 0x00,
|
|
|
|
0x0a, 0x00,
|
|
|
|
0x0b, 0x00,
|
|
|
|
0x0c, 0x00,
|
|
|
|
0x0e, 0x00,
|
|
|
|
0x00, 0x00,
|
|
|
|
];
|
|
|
|
|
2019-12-03 21:40:31 -08:00
|
|
|
#[repr(u32)]
|
|
|
|
#[derive(Copy, Clone, Hash, PartialEq, Eq)]
|
|
|
|
pub enum Class {
|
|
|
|
HUmar,
|
|
|
|
HUnewearl,
|
|
|
|
HUcast,
|
|
|
|
HUcaseal,
|
|
|
|
RAmar,
|
|
|
|
RAmarl,
|
|
|
|
RAcast,
|
|
|
|
RAcaseal,
|
|
|
|
FOmar,
|
|
|
|
FOmarl,
|
|
|
|
FOnewm,
|
|
|
|
FOnewearl,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl std::convert::From<u8> for Class {
|
|
|
|
fn from(f: u8) -> Class {
|
|
|
|
match f {
|
|
|
|
0 => Class::HUmar,
|
|
|
|
1 => Class::HUnewearl,
|
|
|
|
2 => Class::HUcast,
|
|
|
|
3 => Class::RAmar,
|
|
|
|
4 => Class::RAcast,
|
|
|
|
5 => Class::RAcaseal,
|
|
|
|
6 => Class::FOmarl,
|
|
|
|
7 => Class::FOnewm,
|
2020-01-17 10:34:00 -04:00
|
|
|
8 => Class::FOnewearl,
|
2019-12-03 21:40:31 -08:00
|
|
|
9 => Class::HUcaseal,
|
|
|
|
10 => Class::RAmarl,
|
|
|
|
11 => Class::FOmar,
|
|
|
|
_ => panic!("unknown class")
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub enum SectionID {
|
|
|
|
Viridia,
|
|
|
|
Greenill,
|
|
|
|
Skyly,
|
|
|
|
Bluefull,
|
|
|
|
Purplenum,
|
|
|
|
Pinkal,
|
|
|
|
Redria,
|
|
|
|
Oran,
|
|
|
|
Yellowboze,
|
|
|
|
Whitill,
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-11-09 15:14:05 -08:00
|
|
|
#[derive(PSOPacketData, Copy, Clone)]
|
2019-09-08 23:43:07 -07:00
|
|
|
#[repr(C)]
|
2019-09-05 14:36:08 -07:00
|
|
|
pub struct Character {
|
|
|
|
pub atp: u16,
|
|
|
|
pub mst: u16,
|
|
|
|
pub evp: u16,
|
|
|
|
pub hp: u16,
|
|
|
|
pub dfp: u16,
|
|
|
|
pub ata: u16,
|
|
|
|
pub lck: u16,
|
|
|
|
pub _unknown1: u16,
|
|
|
|
pub _unknown2: [u32; 2],
|
|
|
|
pub level: u32,
|
|
|
|
pub exp: u32,
|
|
|
|
pub meseta: u32,
|
|
|
|
pub guildcard: [u8; 16],
|
|
|
|
pub _unknown3: [u32; 2],
|
|
|
|
pub name_color: u32,
|
|
|
|
pub model: u8,
|
|
|
|
pub _unused: [u8; 11],
|
|
|
|
pub play_time: u32,
|
|
|
|
pub name_color_checksum: u32,
|
|
|
|
pub section_id: u8,
|
|
|
|
pub ch_class: u8,
|
|
|
|
pub v2flags: u8,
|
|
|
|
pub version: u8,
|
2019-11-09 15:13:35 -08:00
|
|
|
pub v1flags: u32,
|
2019-09-05 14:36:08 -07:00
|
|
|
pub costume: u16,
|
|
|
|
pub skin: u16,
|
|
|
|
pub face: u16,
|
|
|
|
pub head: u16,
|
|
|
|
pub hair: u16,
|
|
|
|
pub hair_r: u16,
|
|
|
|
pub hair_g: u16,
|
|
|
|
pub hair_b: u16,
|
|
|
|
pub prop_x: f32,
|
|
|
|
pub prop_y: f32,
|
|
|
|
pub name: [u16; 16],
|
2019-11-09 15:14:05 -08:00
|
|
|
pub config: [u8; 0xE8],
|
2019-09-05 14:36:08 -07:00
|
|
|
pub techniques: [u8; 0x14],
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Character {
|
|
|
|
pub fn as_select_screen(self) -> SelectScreenCharacter {
|
|
|
|
SelectScreenCharacter {
|
|
|
|
exp: self.exp,
|
|
|
|
level: self.level,
|
|
|
|
guildcard: self.guildcard,
|
|
|
|
_unknown: self._unknown3,
|
|
|
|
name_color: self.name_color,
|
|
|
|
model: self.model,
|
|
|
|
_unused: [0; 15],
|
|
|
|
name_color_checksum: self.name_color_checksum,
|
|
|
|
section_id: self.section_id,
|
|
|
|
ch_class: self.ch_class,
|
|
|
|
v2flags: self.v2flags,
|
|
|
|
version: self.version,
|
|
|
|
v1flags: self.v1flags,
|
|
|
|
costume: self.costume,
|
|
|
|
skin: self.skin,
|
|
|
|
face: self.face,
|
|
|
|
head: self.head,
|
|
|
|
hair: self.hair,
|
|
|
|
hair_r: self.hair_r,
|
|
|
|
hair_g: self.hair_g,
|
|
|
|
hair_b: self.hair_b,
|
|
|
|
prop_x: self.prop_x,
|
|
|
|
prop_y: self.prop_y,
|
|
|
|
name: self.name,
|
|
|
|
play_time: self.play_time,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-16 23:10:18 -08:00
|
|
|
impl std::default::Default for Character {
|
|
|
|
fn default() -> Character {
|
2020-04-19 23:15:26 -03:00
|
|
|
let mut c = Character::from_bytes(&mut std::io::Cursor::new([0; 0x190].to_vec())).unwrap();
|
|
|
|
c.config = DEFAULT_PALETTE_CONFIG;
|
|
|
|
c
|
2019-11-16 23:10:18 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-25 12:51:42 -08:00
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Default)]
|
2019-09-08 23:43:07 -07:00
|
|
|
#[repr(C)]
|
2019-09-05 14:36:08 -07:00
|
|
|
pub struct SelectScreenCharacter {
|
|
|
|
pub exp: u32,
|
|
|
|
pub level: u32,
|
|
|
|
pub guildcard: [u8; 16],
|
|
|
|
pub _unknown: [u32; 2],
|
|
|
|
pub name_color: u32,
|
|
|
|
pub model: u8,
|
|
|
|
pub _unused: [u8; 15],
|
|
|
|
pub name_color_checksum: u32,
|
|
|
|
pub section_id: u8,
|
|
|
|
pub ch_class: u8,
|
|
|
|
pub v2flags: u8,
|
|
|
|
pub version: u8,
|
2019-11-09 15:13:35 -08:00
|
|
|
pub v1flags: u32,
|
2019-09-05 14:36:08 -07:00
|
|
|
pub costume: u16,
|
|
|
|
pub skin: u16,
|
|
|
|
pub face: u16,
|
|
|
|
pub head: u16,
|
|
|
|
pub hair: u16,
|
|
|
|
pub hair_r: u16,
|
|
|
|
pub hair_g: u16,
|
|
|
|
pub hair_b: u16,
|
|
|
|
pub prop_x: f32,
|
|
|
|
pub prop_y: f32,
|
|
|
|
pub name: [u16; 16],
|
|
|
|
pub play_time: u32,
|
|
|
|
}
|
2019-09-08 23:43:07 -07:00
|
|
|
|
|
|
|
impl SelectScreenCharacter {
|
|
|
|
pub const SIZE: usize = 0x7C;
|
|
|
|
|
|
|
|
pub fn from_le_bytes(bytes: [u8; 0x7C]) -> Result<SelectScreenCharacter, crate::PacketParseError> {
|
|
|
|
unsafe {
|
|
|
|
Ok(std::mem::transmute(bytes))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn to_le_bytes(&self) -> [u8; 0x7C] {
|
|
|
|
unsafe {
|
|
|
|
std::mem::transmute(*self)
|
|
|
|
}
|
|
|
|
}
|
2019-09-23 22:23:17 -07:00
|
|
|
|
|
|
|
pub fn as_character(&self) -> Character {
|
|
|
|
Character {
|
|
|
|
exp: self.exp,
|
|
|
|
level: self.level,
|
|
|
|
guildcard: self.guildcard,
|
|
|
|
_unknown3: self._unknown,
|
|
|
|
name_color: self.name_color,
|
|
|
|
model: self.model,
|
|
|
|
name_color_checksum: self.name_color_checksum,
|
|
|
|
section_id: self.section_id,
|
|
|
|
ch_class: self.ch_class,
|
|
|
|
v2flags: self.v2flags,
|
|
|
|
version: self.version,
|
|
|
|
v1flags: self.v1flags,
|
|
|
|
costume: self.costume,
|
|
|
|
skin: self.skin,
|
|
|
|
face: self.face,
|
|
|
|
head: self.head,
|
|
|
|
hair: self.hair,
|
|
|
|
hair_r: self.hair_r,
|
|
|
|
hair_g: self.hair_g,
|
|
|
|
hair_b: self.hair_b,
|
|
|
|
prop_x: self.prop_x,
|
|
|
|
prop_y: self.prop_y,
|
|
|
|
name: self.name,
|
|
|
|
play_time: self.play_time,
|
|
|
|
|
2019-11-09 15:14:05 -08:00
|
|
|
_unknown1: 0,
|
|
|
|
_unknown2: [0; 2],
|
|
|
|
_unused: [0; 11],
|
|
|
|
atp: 0,
|
|
|
|
mst: 0,
|
|
|
|
evp: 0,
|
|
|
|
hp: 0,
|
|
|
|
dfp: 0,
|
|
|
|
ata: 0,
|
|
|
|
lck: 0,
|
|
|
|
config: [0; 0xE8],
|
|
|
|
meseta: 0,
|
|
|
|
techniques: [0; 0x14],
|
2019-09-23 22:23:17 -07:00
|
|
|
}
|
|
|
|
}
|
2019-09-08 23:43:07 -07:00
|
|
|
}
|
2019-11-04 23:36:51 -04:00
|
|
|
|
2019-11-08 22:51:59 -08:00
|
|
|
#[derive(PSOPacketData, Default, Copy, Clone)]
|
2019-11-04 23:36:51 -04:00
|
|
|
pub struct InventoryItem {
|
|
|
|
pub equipped: u16,
|
2020-03-21 19:42:31 -07:00
|
|
|
pub tech: u8,
|
|
|
|
pub material_count: u8, // in items 8 - 13 material usage values are stored here
|
2019-11-04 23:36:51 -04:00
|
|
|
pub flags: u32,
|
|
|
|
pub data1: [u8; 12],
|
|
|
|
pub item_id: u32,
|
|
|
|
pub data2: [u8; 4],
|
|
|
|
}
|
|
|
|
|
2019-11-08 22:51:59 -08:00
|
|
|
#[derive(PSOPacketData, Default, Copy, Clone)]
|
2019-11-04 23:36:51 -04:00
|
|
|
pub struct BankItem {
|
|
|
|
pub data1: [u8; 12],
|
|
|
|
pub item_id: u32,
|
|
|
|
pub data2: [u8; 4],
|
|
|
|
pub amount: u16,
|
|
|
|
pub flags: u16,
|
|
|
|
}
|
|
|
|
|
2019-12-11 16:01:35 -08:00
|
|
|
#[derive(PSOPacketData, Default, Copy, Clone)]
|
2019-11-04 23:36:51 -04:00
|
|
|
pub struct Inventory {
|
|
|
|
pub item_count: u8,
|
|
|
|
pub hp_mats_used: u8,
|
|
|
|
pub tp_mats_used: u8,
|
|
|
|
pub language: u8,
|
|
|
|
pub items: [InventoryItem; 30],
|
|
|
|
}
|
|
|
|
|
2019-11-08 22:51:59 -08:00
|
|
|
#[derive(PSOPacketData, Copy, Clone)]
|
2019-11-04 23:36:51 -04:00
|
|
|
pub struct Bank {
|
|
|
|
pub item_count: u32,
|
|
|
|
pub meseta: u32,
|
|
|
|
pub items: [BankItem; 200],
|
|
|
|
}
|
|
|
|
|
2019-11-08 22:51:59 -08:00
|
|
|
#[derive(PSOPacketData, Copy, Clone)]
|
2019-11-04 23:36:51 -04:00
|
|
|
pub struct KeyTeamConfig {
|
|
|
|
pub _unknown: [u8; 0x114],
|
|
|
|
pub key_config: [u8; 0x16C],
|
|
|
|
pub joystick_config: [u8; 0x38],
|
|
|
|
pub guildcard: u32,
|
|
|
|
pub team_id: u32,
|
|
|
|
pub team_info: [u32; 2],
|
|
|
|
pub team_priv: u16,
|
|
|
|
pub _reserved: u16,
|
|
|
|
pub team_name: [u16; 16],
|
|
|
|
pub team_flag: [u8; 2048],
|
|
|
|
pub team_rewards: [u32; 2],
|
|
|
|
}
|
|
|
|
|
2019-12-11 16:01:35 -08:00
|
|
|
impl std::default::Default for KeyTeamConfig {
|
|
|
|
fn default() -> KeyTeamConfig {
|
|
|
|
KeyTeamConfig::from_bytes(&mut std::io::Cursor::new([0; 0xAF4].to_vec())).unwrap()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-08 22:51:59 -08:00
|
|
|
#[derive(PSOPacketData, Copy, Clone)]
|
2019-11-04 23:36:51 -04:00
|
|
|
pub struct Player {
|
|
|
|
pub inventory: Inventory,
|
|
|
|
pub character: Character,
|
|
|
|
pub c_rank: [u8; 0x174],
|
|
|
|
pub info_board: [u16; 172],
|
|
|
|
pub blacklist: [u32; 30],
|
|
|
|
pub autoreply: [u16; 172],
|
|
|
|
}
|
|
|
|
|
2019-11-08 22:51:59 -08:00
|
|
|
#[derive(PSOPacketData, Copy, Clone)]
|
|
|
|
pub struct FullCharacter {
|
2019-11-04 23:36:51 -04:00
|
|
|
pub inventory: Inventory,
|
|
|
|
pub character: Character,
|
|
|
|
pub _unknown1: [u8; 16],
|
|
|
|
pub option_flags: u32,
|
|
|
|
pub quest_data1: [u8; 520],
|
|
|
|
pub bank: Bank,
|
|
|
|
pub guildcard: u32,
|
|
|
|
pub name: [u16; 24],
|
|
|
|
pub team_name: [u16; 16],
|
|
|
|
pub guildcard_desc: [u16; 88],
|
|
|
|
pub _reserved1: u8,
|
|
|
|
pub _reserved2: u8,
|
|
|
|
pub section_id: u8,
|
|
|
|
pub char_class: u8,
|
|
|
|
pub _unknown2: u32,
|
2020-04-19 23:15:26 -03:00
|
|
|
pub symbol_chats: [u8; 0x4E0],
|
2019-11-04 23:36:51 -04:00
|
|
|
pub shortcuts: [u8; 2624],
|
|
|
|
pub autoreply: [u16; 172],
|
|
|
|
pub info_board: [u16; 172],
|
|
|
|
pub challenge_data: [u8; 320],
|
|
|
|
pub tech_menu: [u8; 40],
|
|
|
|
pub _unknown4: [u8; 44],
|
|
|
|
pub quest_data2: [u8; 88],
|
|
|
|
pub key_team_config: KeyTeamConfig,
|
|
|
|
}
|
|
|
|
|
2019-11-16 23:10:18 -08:00
|
|
|
impl std::default::Default for FullCharacter {
|
|
|
|
fn default() -> FullCharacter {
|
2020-04-20 00:31:27 -03:00
|
|
|
let mut fc = FullCharacter::from_bytes(&mut std::io::Cursor::new([0; 0x3998].to_vec())).unwrap();
|
|
|
|
fc.tech_menu = DEFAULT_TECH_MENU;
|
|
|
|
fc
|
2019-11-16 23:10:18 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-08 22:51:59 -08:00
|
|
|
#[derive(PSOPacketData, Copy, Clone)]
|
2019-11-04 23:36:51 -04:00
|
|
|
pub struct DBChar {
|
|
|
|
pub inventory: Inventory,
|
|
|
|
pub character: Character,
|
|
|
|
pub quest_data1: [u8; 520],
|
|
|
|
pub bank: Bank,
|
|
|
|
pub guildcard_desc: [u16; 88],
|
|
|
|
pub autoreply: [u16; 172],
|
|
|
|
pub info_board: [u16; 172],
|
|
|
|
pub challenge_data: [u8; 320],
|
|
|
|
pub tech_menu: [u8; 40],
|
|
|
|
pub quest_data2: [u8; 88],
|
|
|
|
}
|
|
|
|
|
2019-11-08 22:51:59 -08:00
|
|
|
#[derive(PSOPacketData, Copy, Clone)]
|
2019-11-04 23:36:51 -04:00
|
|
|
pub struct DBOpts {
|
|
|
|
pub blocked: [u32; 30],
|
|
|
|
pub key_config: [u8; 0x16C],
|
|
|
|
pub joystick_config: [u8; 0x38],
|
|
|
|
pub option_flags: u32,
|
|
|
|
pub shortcuts: [u8; 0xA40],
|
|
|
|
pub symbol_chats: [u8; 0x4E0],
|
2019-11-05 00:33:43 -04:00
|
|
|
pub team_name: [u16; 16],
|
2019-11-08 22:51:59 -08:00
|
|
|
}
|