use libpso::character::character; use stats::leveltable::CharacterStats; use entity::character::CharacterEntity; //use crate::ship::items::{CharacterInventory, CharacterBank}; use crate::ship::items::bank::BankState; use crate::ship::items::inventory::InventoryState; use entity::item::Meseta; #[derive(Default)] pub struct CharacterBytesBuilder<'a> { character: Option<&'a CharacterEntity>, stats: Option<&'a CharacterStats>, level: Option, meseta: Option, } impl<'a> CharacterBytesBuilder<'a> { #[must_use] pub fn character(self, character: &'a CharacterEntity) -> CharacterBytesBuilder<'a> { CharacterBytesBuilder { character: Some(character), ..self } } #[must_use] pub fn stats(self, stats: &'a CharacterStats) -> CharacterBytesBuilder<'a> { CharacterBytesBuilder { stats: Some(stats), ..self } } #[must_use] pub fn level(self, level: u32) -> CharacterBytesBuilder<'a> { CharacterBytesBuilder { level: Some(level), ..self } } #[must_use] pub fn meseta(self, meseta: Meseta) -> CharacterBytesBuilder<'a> { CharacterBytesBuilder { meseta: Some(meseta), ..self } } pub fn build(self) -> character::Character { let character = self.character.unwrap(); let stats = self.stats.unwrap(); let level = self.level.unwrap(); let meseta = self.meseta.unwrap(); character::Character { name: libpso::utf8_to_utf16_array!(character.name, 16), hp: stats.hp, atp: stats.atp + character.materials.power as u16 * 2, mst: stats.mst + character.materials.mind as u16 * 2, evp: stats.evp + character.materials.evade as u16 * 2, dfp: stats.dfp + character.materials.def as u16 * 2, ata: stats.ata, lck: stats.lck + character.materials.luck as u16 * 2, level, section_id: character.section_id.into(), ch_class: character.char_class.into(), costume: character.appearance.costume, skin: character.appearance.skin, face: character.appearance.face, head: character.appearance.head, hair: character.appearance.hair, hair_r: character.appearance.hair_r, hair_g: character.appearance.hair_g, hair_b: character.appearance.hair_b, prop_x: character.appearance.prop_x, prop_y: character.appearance.prop_y, config: character.config.as_bytes(), techniques: character.techs.as_bytes(), meseta: meseta.0, exp: character.exp, ..character::Character::default() } } } #[derive(Default)] pub struct FullCharacterBytesBuilder<'a> { character: Option<&'a CharacterEntity>, stats: Option<&'a CharacterStats>, level: Option, meseta: Option, inventory: Option<&'a InventoryState>, bank: Option<&'a BankState>, keyboard_config: Option<&'a [u8; 0x16C]>, gamepad_config: Option<&'a [u8; 0x38]>, symbol_chat: Option<&'a [u8; 1248]>, tech_menu: Option<&'a [u8; 40]>, option_flags: Option, } impl<'a> FullCharacterBytesBuilder<'a> { #[must_use] pub fn character(self, character: &'a CharacterEntity) -> FullCharacterBytesBuilder<'a> { FullCharacterBytesBuilder { character: Some(character), ..self } } #[must_use] pub fn stats(self, stats: &'a CharacterStats) -> FullCharacterBytesBuilder<'a> { FullCharacterBytesBuilder { stats: Some(stats), ..self } } #[must_use] pub fn level(self, level: u32) -> FullCharacterBytesBuilder<'a> { FullCharacterBytesBuilder { level: Some(level), ..self } } #[must_use] pub fn meseta(self, meseta: Meseta) -> FullCharacterBytesBuilder<'a> { FullCharacterBytesBuilder { meseta: Some(meseta), ..self } } #[must_use] pub fn inventory(self, inventory: &'a InventoryState) -> FullCharacterBytesBuilder<'a> { FullCharacterBytesBuilder { inventory: Some(inventory), ..self } } #[must_use] pub fn bank(self, bank: &'a BankState) -> FullCharacterBytesBuilder<'a> { FullCharacterBytesBuilder { bank: Some(bank), ..self } } #[must_use] pub fn keyboard_config(self, keyboard_config: &'a [u8; 0x16C]) -> FullCharacterBytesBuilder<'a> { FullCharacterBytesBuilder { keyboard_config: Some(keyboard_config), ..self } } #[must_use] pub fn gamepad_config(self, gamepad_config: &'a [u8; 0x38]) -> FullCharacterBytesBuilder<'a> { FullCharacterBytesBuilder { gamepad_config: Some(gamepad_config), ..self } } #[must_use] pub fn symbol_chat(self, symbol_chat: &'a [u8; 1248]) -> FullCharacterBytesBuilder<'a> { FullCharacterBytesBuilder { symbol_chat: Some(symbol_chat), ..self } } #[must_use] pub fn tech_menu(self, tech_menu: &'a [u8; 40]) -> FullCharacterBytesBuilder<'a> { FullCharacterBytesBuilder { tech_menu: Some(tech_menu), ..self } } #[must_use] pub fn option_flags(self, option_flags: u32) -> FullCharacterBytesBuilder<'a> { FullCharacterBytesBuilder { option_flags: Some(option_flags), ..self } } pub fn build(self) -> character::FullCharacter { let character = self.character.unwrap(); let stats = self.stats.unwrap(); let level = self.level.unwrap(); let meseta = self.meseta.unwrap(); let inventory = self.inventory.unwrap(); let bank = self.bank.unwrap(); let keyboard_config = self.keyboard_config.unwrap(); let gamepad_config = self.gamepad_config.unwrap(); let symbol_chat = self.symbol_chat.unwrap(); let tech_menu = self.tech_menu.unwrap(); let option_flags = self.option_flags.unwrap(); let mut inventory_items = inventory.as_client_inventory_items(); inventory_items[7].material_count = character.materials.power as u8; inventory_items[8].material_count = character.materials.mind as u8; inventory_items[9].material_count = character.materials.evade as u8; inventory_items[10].material_count = character.materials.def as u8; inventory_items[11].material_count = character.materials.luck as u8; character::FullCharacter { character: CharacterBytesBuilder::default() .character(character) .stats(stats) .level(level - 1) .meseta(meseta) .build(), inventory: character::Inventory { item_count: inventory.count() as u8, items: inventory_items, hp_mats_used: character.materials.hp as u8 * 2, tp_mats_used: character.materials.tp as u8 * 2, ..character::Inventory::default() }, key_team_config: character::KeyTeamConfig { keyboard_config: *keyboard_config, gamepad_config: *gamepad_config, ..character::KeyTeamConfig::default() }, info_board: character.info_board.as_bytes(), symbol_chats: *symbol_chat, tech_menu: *tech_menu, bank: bank.as_client_bank_items(), option_flags, ..character::FullCharacter::default() } } }