use std::convert::{From, Into, TryFrom, TryInto}; use std::collections::HashMap; use libpso::character::character; use libpso::packet::ship::{UpdateConfig, WriteInfoboard}; #[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::RAmarl, 11 => CharacterClass::FOmar, _ => 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::RAmarl => 10, CharacterClass::FOmar => 11, } } } #[derive(Copy, Clone, Hash, PartialEq, Eq)] 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, PartialEq, Eq, Hash)] pub enum Technique { Foie, Gifoie, Rafoie, Zonde, Gizonde, Razonde, Barta, Gibarta, Rabarta, Grants, Megid, Shifta, Deband, Jellen, Zalure, Resta, Anti, Reverser, Ryuker, } #[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(&mut 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)] pub struct Character { pub id: u32, pub user_id: u32, 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, } impl std::default::Default for Character { fn default() -> Character { Character { id: 0, user_id: 0, 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(), } } }