You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

370 lines
8.8 KiB

4 years ago
4 years ago
4 years ago
3 years ago
4 years ago
4 years ago
4 years ago
  1. use std::convert::{From, Into};
  2. use std::collections::HashMap;
  3. use serde::{Serialize, Deserialize};
  4. use libpso::packet::ship::{UpdateConfig, WriteInfoboard};
  5. use libpso::character::character::{DEFAULT_PALETTE_CONFIG, DEFAULT_TECH_MENU};
  6. use crate::entity::item::tech::Technique;
  7. use crate::entity::account::UserAccountId;
  8. #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, enum_utils::FromStr, derive_more::Display, Serialize, Deserialize)]
  9. pub enum CharacterClass {
  10. HUmar,
  11. HUnewearl,
  12. HUcast,
  13. HUcaseal,
  14. RAmar,
  15. RAmarl,
  16. RAcast,
  17. RAcaseal,
  18. FOmar,
  19. FOmarl,
  20. FOnewm,
  21. FOnewearl,
  22. }
  23. // TODO: TryFrom
  24. impl From<u8> for CharacterClass {
  25. fn from(f: u8) -> CharacterClass {
  26. match f {
  27. 0 => CharacterClass::HUmar,
  28. 1 => CharacterClass::HUnewearl,
  29. 2 => CharacterClass::HUcast,
  30. 3 => CharacterClass::RAmar,
  31. 4 => CharacterClass::RAcast,
  32. 5 => CharacterClass::RAcaseal,
  33. 6 => CharacterClass::FOmarl,
  34. 7 => CharacterClass::FOnewm,
  35. 8 => CharacterClass::FOnewearl,
  36. 9 => CharacterClass::HUcaseal,
  37. 10 => CharacterClass::FOmar,
  38. 11 => CharacterClass::RAmarl,
  39. _ => panic!("unknown class")
  40. }
  41. }
  42. }
  43. impl Into<u8> for CharacterClass {
  44. fn into(self) -> u8 {
  45. match self {
  46. CharacterClass::HUmar => 0,
  47. CharacterClass::HUnewearl => 1,
  48. CharacterClass::HUcast => 2,
  49. CharacterClass::RAmar => 3,
  50. CharacterClass::RAcast => 4,
  51. CharacterClass::RAcaseal => 5,
  52. CharacterClass::FOmarl => 6,
  53. CharacterClass::FOnewm => 7,
  54. CharacterClass::FOnewearl => 8,
  55. CharacterClass::HUcaseal => 9,
  56. CharacterClass::FOmar => 10,
  57. CharacterClass::RAmarl => 11,
  58. }
  59. }
  60. }
  61. impl CharacterClass {
  62. pub fn is_human(&self) -> bool {
  63. match self {
  64. CharacterClass::HUmar |
  65. CharacterClass::RAmar | CharacterClass::RAmarl |
  66. CharacterClass::FOmar | CharacterClass::FOmarl => true,
  67. _ => false,
  68. }
  69. }
  70. pub fn is_newman(&self) -> bool {
  71. match self {
  72. CharacterClass::HUnewearl |
  73. CharacterClass::FOnewm | CharacterClass::FOnewearl => true,
  74. _ => false,
  75. }
  76. }
  77. pub fn is_android(&self) -> bool {
  78. match self {
  79. CharacterClass::HUcast | CharacterClass::HUcaseal |
  80. CharacterClass::RAcast | CharacterClass::RAcaseal => true,
  81. _ => false,
  82. }
  83. }
  84. }
  85. #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, enum_utils::FromStr, derive_more::Display, Serialize, Deserialize)]
  86. pub enum SectionID {
  87. Viridia,
  88. Greenill,
  89. Skyly,
  90. Bluefull,
  91. Purplenum,
  92. Pinkal,
  93. Redria,
  94. Oran,
  95. Yellowboze,
  96. Whitill,
  97. }
  98. impl From<u8> for SectionID {
  99. fn from(id: u8) -> SectionID {
  100. match id {
  101. 0 => SectionID::Viridia,
  102. 1 => SectionID::Greenill,
  103. 2 => SectionID::Skyly,
  104. 3 => SectionID::Bluefull,
  105. 4 => SectionID::Purplenum,
  106. 5 => SectionID::Pinkal,
  107. 6 => SectionID::Redria,
  108. 7 => SectionID::Oran,
  109. 8 => SectionID::Yellowboze,
  110. 9 => SectionID::Whitill,
  111. _ => panic!(),
  112. }
  113. }
  114. }
  115. impl Into<u8> for SectionID {
  116. fn into(self) -> u8 {
  117. match self {
  118. SectionID::Viridia => 0,
  119. SectionID::Greenill => 1,
  120. SectionID::Skyly => 2,
  121. SectionID::Bluefull => 3,
  122. SectionID::Purplenum => 4,
  123. SectionID::Pinkal => 5,
  124. SectionID::Redria => 6,
  125. SectionID::Oran => 7,
  126. SectionID::Yellowboze => 8,
  127. SectionID::Whitill => 9,
  128. }
  129. }
  130. }
  131. #[derive(Clone, Debug, Default)]
  132. pub struct CharacterAppearance {
  133. pub costume: u16,
  134. pub skin: u16,
  135. pub face: u16,
  136. pub head: u16,
  137. pub hair: u16,
  138. pub hair_r: u16,
  139. pub hair_g: u16,
  140. pub hair_b: u16,
  141. pub prop_x: f32,
  142. pub prop_y: f32,
  143. }
  144. #[derive(Clone, Debug)]
  145. pub struct TechLevel(pub u8);
  146. #[derive(Clone, Debug)]
  147. pub struct CharacterTechniques {
  148. pub techs: HashMap<Technique, TechLevel>
  149. }
  150. impl CharacterTechniques {
  151. fn new() -> CharacterTechniques {
  152. CharacterTechniques {
  153. techs: HashMap::new(),
  154. }
  155. }
  156. pub fn set_tech(&mut self, tech: Technique, level: TechLevel) {
  157. self.techs.insert(tech, TechLevel(level.0 - 1));
  158. }
  159. // from_bytes
  160. pub fn as_bytes(&self) -> [u8; 20] {
  161. self.techs.iter()
  162. .fold([0xFF; 20], |mut techlist, (tech, level)| {
  163. let index = tech.as_value();
  164. techlist[index as usize] = level.0;
  165. techlist
  166. })
  167. }
  168. }
  169. #[derive(Clone)]
  170. pub struct CharacterConfig {
  171. pub raw_data: [u8; 0xE8],
  172. }
  173. impl CharacterConfig {
  174. fn new() -> CharacterConfig {
  175. CharacterConfig {
  176. raw_data: DEFAULT_PALETTE_CONFIG,
  177. }
  178. }
  179. pub fn update(&mut self, new_config: &UpdateConfig) {
  180. self.raw_data = new_config.config;
  181. }
  182. pub fn as_bytes(&self) -> [u8; 0xE8] {
  183. self.raw_data
  184. }
  185. }
  186. #[derive(Clone)]
  187. pub struct CharacterInfoboard {
  188. pub board: [u16; 172],
  189. }
  190. impl CharacterInfoboard {
  191. fn new() -> CharacterInfoboard {
  192. CharacterInfoboard {
  193. board: [0; 172]
  194. }
  195. }
  196. pub fn as_bytes(&self) -> [u16; 172] {
  197. self.board
  198. }
  199. pub fn update_infoboard(&mut self, new_board: &WriteInfoboard) {
  200. self.board = libpso::utf8_to_utf16_array!(new_board.message, 172);
  201. }
  202. }
  203. #[derive(Clone, Default)]
  204. pub struct CharacterGuildCard {
  205. pub description: String,
  206. }
  207. #[derive(Clone)]
  208. pub struct CharacterTechMenu {
  209. pub tech_menu: [u8; 40],
  210. }
  211. impl CharacterTechMenu {
  212. fn new() -> CharacterTechMenu {
  213. CharacterTechMenu {
  214. tech_menu: DEFAULT_TECH_MENU,
  215. }
  216. }
  217. pub fn as_bytes(&self) -> [u8; 40] {
  218. self.tech_menu
  219. }
  220. }
  221. #[derive(Clone, Default)]
  222. pub struct CharacterMaterials {
  223. pub power: u32,
  224. pub mind: u32,
  225. pub def: u32,
  226. pub evade: u32,
  227. pub luck: u32,
  228. pub hp: u32,
  229. pub tp: u32,
  230. }
  231. #[derive(Debug)]
  232. pub enum PlayerTraps {
  233. FireTrap,
  234. FreezeTrap,
  235. SlowTrap,
  236. ConfuseTrap,
  237. }
  238. impl PlayerTraps {
  239. fn from(id: u16) -> PlayerTraps {
  240. match id {
  241. 0 => PlayerTraps::FireTrap,
  242. 1 => PlayerTraps::FreezeTrap,
  243. 2 => PlayerTraps::SlowTrap,
  244. 3 => PlayerTraps::ConfuseTrap,
  245. _ => panic!(),
  246. }
  247. }
  248. fn into(self) -> u16 {
  249. match self {
  250. PlayerTraps::FireTrap => 0,
  251. PlayerTraps::FreezeTrap => 1,
  252. PlayerTraps::SlowTrap => 2,
  253. PlayerTraps::ConfuseTrap => 3,
  254. }
  255. }
  256. }
  257. #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
  258. pub struct CharacterEntityId(pub u32);
  259. #[derive(Clone)]
  260. pub struct NewCharacterEntity {
  261. pub user_id: UserAccountId,
  262. pub slot: u32,
  263. pub name: String,
  264. pub exp: u32,
  265. pub char_class: CharacterClass,
  266. pub section_id: SectionID,
  267. pub appearance: CharacterAppearance,
  268. pub techs: CharacterTechniques,
  269. pub config: CharacterConfig,
  270. pub info_board: CharacterInfoboard,
  271. pub guildcard: CharacterGuildCard,
  272. pub materials: CharacterMaterials,
  273. pub tech_menu: CharacterTechMenu,
  274. pub meseta: u32,
  275. pub bank_meseta: u32,
  276. pub option_flags: u32,
  277. }
  278. impl NewCharacterEntity {
  279. pub fn new(user: UserAccountId) -> NewCharacterEntity {
  280. NewCharacterEntity {
  281. user_id: user,
  282. slot: 0,
  283. name: "".into(),
  284. exp: 0,
  285. char_class: CharacterClass::HUmar,
  286. section_id: SectionID::Viridia,
  287. appearance: CharacterAppearance::default(),
  288. techs: CharacterTechniques::new(),
  289. config: CharacterConfig::new(),
  290. info_board: CharacterInfoboard::new(),
  291. guildcard: CharacterGuildCard::default(),
  292. materials: CharacterMaterials::default(),
  293. tech_menu: CharacterTechMenu::new(),
  294. meseta: 0,
  295. bank_meseta: 0,
  296. option_flags: 0,
  297. }
  298. }
  299. }
  300. #[derive(Clone)]
  301. pub struct CharacterEntity {
  302. pub id: CharacterEntityId,
  303. pub user_id: UserAccountId,
  304. pub slot: u32,
  305. pub name: String,
  306. pub exp: u32,
  307. pub char_class: CharacterClass,
  308. pub section_id: SectionID,
  309. pub appearance: CharacterAppearance,
  310. pub techs: CharacterTechniques,
  311. pub config: CharacterConfig,
  312. pub info_board: CharacterInfoboard,
  313. pub guildcard: CharacterGuildCard,
  314. pub materials: CharacterMaterials,
  315. pub tech_menu: CharacterTechMenu,
  316. pub meseta: u32,
  317. // TODO: this should not be tied to the character
  318. pub bank_meseta: u32,
  319. pub option_flags: u32,
  320. }