use std::convert::{From, Into, TryFrom, TryInto}; use std::collections::HashMap; use libpso::packet::ship::{UpdateConfig, WriteInfoboard}; use crate::entity::item::tech::Technique; use crate::entity::account::UserAccountId; #[derive(Copy, Clone, Hash, PartialEq, Eq)] pub enum CharacterClass { HUmar, HUnewearl, HUcast, HUcaseal, RAmar, RAmarl, RAcast, RAcaseal, FOmar, FOmarl, FOnewm, FOnewearl, } // TODO: TryFrom impl From for CharacterClass { fn from(f: u8) -> CharacterClass { match f { 0 => CharacterClass::HUmar, 1 => CharacterClass::HUnewearl, 2 => CharacterClass::HUcast, 3 => CharacterClass::RAmar, 4 => CharacterClass::RAcast, 5 => CharacterClass::RAcaseal, 6 => CharacterClass::FOmarl, 7 => CharacterClass::FOnewm, 8 => CharacterClass::FOnewearl, 9 => CharacterClass::HUcaseal, 10 => CharacterClass::FOmar, 11 => CharacterClass::RAmarl, _ => panic!("unknown class") } } } impl Into for CharacterClass { fn into(self) -> u8 { match self { CharacterClass::HUmar => 0, CharacterClass::HUnewearl => 1, CharacterClass::HUcast => 2, CharacterClass::RAmar => 3, CharacterClass::RAcast => 4, CharacterClass::RAcaseal => 5, CharacterClass::FOmarl => 6, CharacterClass::FOnewm => 7, CharacterClass::FOnewearl => 8, CharacterClass::HUcaseal => 9, CharacterClass::FOmar => 10, CharacterClass::RAmarl => 11, } } } #[derive(Copy, Clone, Hash, PartialEq, Eq, derive_more::Display)] pub enum SectionID { Viridia, Greenill, Skyly, Bluefull, Purplenum, Pinkal, Redria, Oran, Yellowboze, Whitill, } impl From for SectionID { fn from(id: u8) -> SectionID { match id { 0 => SectionID::Viridia, 1 => SectionID::Greenill, 2 => SectionID::Skyly, 3 => SectionID::Bluefull, 4 => SectionID::Purplenum, 5 => SectionID::Pinkal, 6 => SectionID::Redria, 7 => SectionID::Oran, 8 => SectionID::Yellowboze, 9 => SectionID::Whitill, _ => panic!(), } } } impl Into for SectionID { fn into(self) -> u8 { match self { SectionID::Viridia => 0, SectionID::Greenill => 1, SectionID::Skyly => 2, SectionID::Bluefull => 3, SectionID::Purplenum => 4, SectionID::Pinkal => 5, SectionID::Redria => 6, SectionID::Oran => 7, SectionID::Yellowboze => 8, SectionID::Whitill => 9, } } } #[derive(Clone, Debug, Default)] pub struct CharacterAppearance { 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, } #[derive(Clone, Debug)] pub struct TechLevel(pub u8); #[derive(Clone, Debug)] pub struct CharacterTechniques { techs: HashMap } impl CharacterTechniques { fn new() -> CharacterTechniques { CharacterTechniques { techs: HashMap::new(), } } pub fn set_tech(&mut self, tech: Technique, level: TechLevel) { self.techs.insert(tech, level); } // from_bytes pub fn as_bytes(&self) -> [u8; 20] { self.techs.iter() .fold([0xFF; 20], |mut techlist, (tech, level)| { let index = match tech { Technique::Foie => 0, Technique::Gifoie => 1, Technique::Rafoie => 2, Technique::Barta => 3, Technique::Gibarta => 4, Technique::Rabarta => 5, Technique::Zonde => 6, Technique::Gizonde => 7, Technique::Razonde => 8, Technique::Grants => 9, Technique::Deband => 10, Technique::Jellen => 11, Technique::Zalure => 12, Technique::Shifta => 13, Technique::Ryuker => 14, Technique::Resta => 15, Technique::Anti => 16, Technique::Reverser => 17, Technique::Megid => 18, }; techlist[index] = level.0 - 1; techlist }) } } #[derive(Clone)] pub struct CharacterConfig { raw_data: [u8; 0xE8], } impl CharacterConfig { fn new() -> CharacterConfig { CharacterConfig { raw_data: [0; 0xE8], } } pub fn update(&mut self, new_config: &UpdateConfig) { self.raw_data = new_config.config; } pub fn as_bytes(&self) -> [u8; 0xE8] { self.raw_data } } #[derive(Clone)] pub struct CharacterInfoboard { board: [u16; 172], } impl CharacterInfoboard { fn new() -> CharacterInfoboard { CharacterInfoboard { board: [0; 172] } } pub fn as_bytes(&self) -> [u16; 172] { self.board } pub fn update_infoboard(&mut self, new_board: &WriteInfoboard) { self.board = libpso::utf8_to_utf16_array!(new_board.message, 172); } } #[derive(Clone, Default)] pub struct CharacterGuildCard { pub description: String, } #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct CharacterEntityId(pub u32); #[derive(Clone)] pub struct CharacterEntity { pub id: Option, pub user_id: UserAccountId, pub slot: u32, pub name: String, pub exp: u32, pub char_class: CharacterClass, pub section_id: SectionID, pub appearance: CharacterAppearance, pub techs: CharacterTechniques, pub config: CharacterConfig, pub info_board: CharacterInfoboard, pub guildcard: CharacterGuildCard, } impl CharacterEntity { pub fn new(user: UserAccountId) -> CharacterEntity { CharacterEntity { id: None, user_id: user, slot: 0, name: "".into(), exp: 0, char_class: CharacterClass::HUmar, section_id: SectionID::Viridia, appearance: CharacterAppearance::default(), techs: CharacterTechniques::new(), config: CharacterConfig::new(), info_board: CharacterInfoboard::new(), guildcard: CharacterGuildCard::default(), } } }