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.

1177 lines
51 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. use std::collections::HashMap;
  2. use serde::{Serialize, Deserialize};
  3. use crate::entity::item::tool::ToolType;
  4. use crate::entity::character::{CharacterClass, SectionID};
  5. use crate::entity::item::ItemEntityId;
  6. use std::io::Read;
  7. use std::cmp::Ordering::{Less, Greater, Equal};
  8. #[derive(Debug, Deserialize)]
  9. struct MagStats {
  10. feed_table: usize,
  11. photon_blast: Option<PhotonBlast>
  12. }
  13. #[derive(Debug, Deserialize)]
  14. struct MagFeedTable {
  15. def: i16,
  16. pow: i16,
  17. dex: i16,
  18. mnd: i16,
  19. iq: i8,
  20. syn: i8,
  21. }
  22. lazy_static::lazy_static! {
  23. static ref MAG_STATS: HashMap<MagType, MagStats> = {
  24. let mut f = std::fs::File::open("data/item_stats/mag_stats.toml").unwrap();
  25. let mut s = String::new();
  26. f.read_to_string(&mut s).unwrap();
  27. let mag_stats: HashMap<String, MagStats> = toml::from_str(&s).unwrap();
  28. mag_stats.into_iter()
  29. .map(|(name, stats)| {
  30. (name.parse().unwrap(), stats)
  31. })
  32. .collect::<HashMap<MagType, MagStats>>()
  33. };
  34. static ref MAG_FEEDING_TABLES: Vec<HashMap<ToolType, MagFeedTable>> = {
  35. let mut f = std::fs::File::open("data/item_stats/mag_feed_table.toml").unwrap();
  36. let mut s = String::new();
  37. f.read_to_string(&mut s).unwrap();
  38. let mut feed: HashMap<String, Vec<HashMap<String, MagFeedTable>>> = toml::from_str(&s).unwrap();
  39. let feed = feed.remove("feedtable".into()).unwrap();
  40. feed.into_iter()
  41. .map(|table| {
  42. table.into_iter()
  43. .map(|(tool, stats)| {
  44. (tool.parse().unwrap(), stats)
  45. })
  46. .collect()
  47. })
  48. .collect::<Vec<HashMap<ToolType, MagFeedTable>>>()
  49. };
  50. }
  51. #[derive(Debug, Copy, Clone)]
  52. pub enum ItemParseError {
  53. InvalidMagType,
  54. InvalidMagBytes,
  55. }
  56. #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display, strum_macros::EnumIter)]
  57. pub enum MagType {
  58. Mag,
  59. Varuna,
  60. Mitra,
  61. Surya,
  62. Vayu,
  63. Varaha,
  64. Kama,
  65. Ushasu,
  66. Apsaras,
  67. Kumara,
  68. Kaitabha,
  69. Tapas,
  70. Bhirava,
  71. Kalki,
  72. Rudra,
  73. Marutah,
  74. Yaksa,
  75. Sita,
  76. Garuda,
  77. Nandin,
  78. Ashvinau,
  79. Ribhava,
  80. Soma,
  81. Ila,
  82. Durga,
  83. Vritra,
  84. Namuci,
  85. Sumba,
  86. Naga,
  87. Pitri,
  88. Kabanda,
  89. Ravana,
  90. Marica,
  91. Soniti,
  92. Preta,
  93. Andhaka,
  94. Bana,
  95. Naraka,
  96. Madhu,
  97. Churel,
  98. Robochao,
  99. OpaOpa,
  100. Pian,
  101. Chao,
  102. ChuChu,
  103. KapuKapu,
  104. AngelsWing,
  105. DevilsWing,
  106. Elenor,
  107. MarkIII,
  108. MasterSystem,
  109. Genesis,
  110. SegaSaturn,
  111. Dreamcast,
  112. Hamburger,
  113. PanzersTail,
  114. DevilsTail,
  115. Deva,
  116. Rati,
  117. Savitri,
  118. Rukmin,
  119. Pushan,
  120. Diwari,
  121. Sato,
  122. Bhima,
  123. Nidra,
  124. GeungSi,
  125. Tellusis,
  126. StrikerUnit,
  127. Pioneer,
  128. Puyo,
  129. Moro,
  130. Rappy,
  131. Yahoo,
  132. GaelGiel,
  133. Agastya,
  134. }
  135. impl MagType {
  136. pub fn value(&self) -> [u8; 3] {
  137. match self {
  138. MagType::Mag => [0x02, 0x00, 0x00],
  139. MagType::Varuna => [0x02, 0x01, 0x00],
  140. MagType::Mitra => [0x02, 0x02, 0x00],
  141. MagType::Surya => [0x02, 0x03, 0x00],
  142. MagType::Vayu => [0x02, 0x04, 0x00],
  143. MagType::Varaha => [0x02, 0x05, 0x00],
  144. MagType::Kama => [0x02, 0x06, 0x00],
  145. MagType::Ushasu => [0x02, 0x07, 0x00],
  146. MagType::Apsaras => [0x02, 0x08, 0x00],
  147. MagType::Kumara => [0x02, 0x09, 0x00],
  148. MagType::Kaitabha => [0x02, 0x0A, 0x00],
  149. MagType::Tapas => [0x02, 0x0B, 0x00],
  150. MagType::Bhirava => [0x02, 0x0C, 0x00],
  151. MagType::Kalki => [0x02, 0x0D, 0x00],
  152. MagType::Rudra => [0x02, 0x0E, 0x00],
  153. MagType::Marutah => [0x02, 0x0F, 0x00],
  154. MagType::Yaksa => [0x02, 0x10, 0x00],
  155. MagType::Sita => [0x02, 0x11, 0x00],
  156. MagType::Garuda => [0x02, 0x12, 0x00],
  157. MagType::Nandin => [0x02, 0x13, 0x00],
  158. MagType::Ashvinau => [0x02, 0x14, 0x00],
  159. MagType::Ribhava => [0x02, 0x15, 0x00],
  160. MagType::Soma => [0x02, 0x16, 0x00],
  161. MagType::Ila => [0x02, 0x17, 0x00],
  162. MagType::Durga => [0x02, 0x18, 0x00],
  163. MagType::Vritra => [0x02, 0x19, 0x00],
  164. MagType::Namuci => [0x02, 0x1A, 0x00],
  165. MagType::Sumba => [0x02, 0x1B, 0x00],
  166. MagType::Naga => [0x02, 0x1C, 0x00],
  167. MagType::Pitri => [0x02, 0x1D, 0x00],
  168. MagType::Kabanda => [0x02, 0x1E, 0x00],
  169. MagType::Ravana => [0x02, 0x1F, 0x00],
  170. MagType::Marica => [0x02, 0x20, 0x00],
  171. MagType::Soniti => [0x02, 0x21, 0x00],
  172. MagType::Preta => [0x02, 0x22, 0x00],
  173. MagType::Andhaka => [0x02, 0x23, 0x00],
  174. MagType::Bana => [0x02, 0x24, 0x00],
  175. MagType::Naraka => [0x02, 0x25, 0x00],
  176. MagType::Madhu => [0x02, 0x26, 0x00],
  177. MagType::Churel => [0x02, 0x27, 0x00],
  178. MagType::Robochao => [0x02, 0x28, 0x00],
  179. MagType::OpaOpa => [0x02, 0x29, 0x00],
  180. MagType::Pian => [0x02, 0x2A, 0x00],
  181. MagType::Chao => [0x02, 0x2B, 0x00],
  182. MagType::ChuChu => [0x02, 0x2C, 0x00],
  183. MagType::KapuKapu => [0x02, 0x2D, 0x00],
  184. MagType::AngelsWing => [0x02, 0x2E, 0x00],
  185. MagType::DevilsWing => [0x02, 0x2F, 0x00],
  186. MagType::Elenor => [0x02, 0x30, 0x00],
  187. MagType::MarkIII => [0x02, 0x31, 0x00],
  188. MagType::MasterSystem => [0x02, 0x32, 0x00],
  189. MagType::Genesis => [0x02, 0x33, 0x00],
  190. MagType::SegaSaturn => [0x02, 0x34, 0x00],
  191. MagType::Dreamcast => [0x02, 0x35, 0x00],
  192. MagType::Hamburger => [0x02, 0x36, 0x00],
  193. MagType::PanzersTail => [0x02, 0x37, 0x00],
  194. MagType::DevilsTail => [0x02, 0x38, 0x00],
  195. MagType::Deva => [0x02, 0x39, 0x00],
  196. MagType::Rati => [0x02, 0x3A, 0x00],
  197. MagType::Savitri => [0x02, 0x3B, 0x00],
  198. MagType::Rukmin => [0x02, 0x3C, 0x00],
  199. MagType::Pushan => [0x02, 0x3D, 0x00],
  200. MagType::Diwari => [0x02, 0x3E, 0x00],
  201. MagType::Sato => [0x02, 0x3F, 0x00],
  202. MagType::Bhima => [0x02, 0x40, 0x00],
  203. MagType::Nidra => [0x02, 0x41, 0x00],
  204. MagType::GeungSi => [0x02, 0x42, 0x00],
  205. MagType::Tellusis => [0x02, 0x44, 0x00],
  206. MagType::StrikerUnit => [0x02, 0x45, 0x00],
  207. MagType::Pioneer => [0x02, 0x46, 0x00],
  208. MagType::Puyo => [0x02, 0x47, 0x00],
  209. MagType::Moro => [0x02, 0x48, 0x00],
  210. MagType::Rappy => [0x02, 0x49, 0x00],
  211. MagType::Yahoo => [0x02, 0x4A, 0x00],
  212. MagType::GaelGiel => [0x02, 0x4B, 0x00],
  213. MagType::Agastya => [0x02, 0x4C, 0x00],
  214. }
  215. }
  216. pub fn parse_type(data: [u8; 3]) -> Result<MagType, ItemParseError> {
  217. match data {
  218. [0x02, 0x00, 0x00] => Ok(MagType::Mag),
  219. [0x02, 0x01, 0x00] => Ok(MagType::Varuna),
  220. [0x02, 0x02, 0x00] => Ok(MagType::Mitra),
  221. [0x02, 0x03, 0x00] => Ok(MagType::Surya),
  222. [0x02, 0x04, 0x00] => Ok(MagType::Vayu),
  223. [0x02, 0x05, 0x00] => Ok(MagType::Varaha),
  224. [0x02, 0x06, 0x00] => Ok(MagType::Kama),
  225. [0x02, 0x07, 0x00] => Ok(MagType::Ushasu),
  226. [0x02, 0x08, 0x00] => Ok(MagType::Apsaras),
  227. [0x02, 0x09, 0x00] => Ok(MagType::Kumara),
  228. [0x02, 0x0A, 0x00] => Ok(MagType::Kaitabha),
  229. [0x02, 0x0B, 0x00] => Ok(MagType::Tapas),
  230. [0x02, 0x0C, 0x00] => Ok(MagType::Bhirava),
  231. [0x02, 0x0D, 0x00] => Ok(MagType::Kalki),
  232. [0x02, 0x0E, 0x00] => Ok(MagType::Rudra),
  233. [0x02, 0x0F, 0x00] => Ok(MagType::Marutah),
  234. [0x02, 0x10, 0x00] => Ok(MagType::Yaksa),
  235. [0x02, 0x11, 0x00] => Ok(MagType::Sita),
  236. [0x02, 0x12, 0x00] => Ok(MagType::Garuda),
  237. [0x02, 0x13, 0x00] => Ok(MagType::Nandin),
  238. [0x02, 0x14, 0x00] => Ok(MagType::Ashvinau),
  239. [0x02, 0x15, 0x00] => Ok(MagType::Ribhava),
  240. [0x02, 0x16, 0x00] => Ok(MagType::Soma),
  241. [0x02, 0x17, 0x00] => Ok(MagType::Ila),
  242. [0x02, 0x18, 0x00] => Ok(MagType::Durga),
  243. [0x02, 0x19, 0x00] => Ok(MagType::Vritra),
  244. [0x02, 0x1A, 0x00] => Ok(MagType::Namuci),
  245. [0x02, 0x1B, 0x00] => Ok(MagType::Sumba),
  246. [0x02, 0x1C, 0x00] => Ok(MagType::Naga),
  247. [0x02, 0x1D, 0x00] => Ok(MagType::Pitri),
  248. [0x02, 0x1E, 0x00] => Ok(MagType::Kabanda),
  249. [0x02, 0x1F, 0x00] => Ok(MagType::Ravana),
  250. [0x02, 0x20, 0x00] => Ok(MagType::Marica),
  251. [0x02, 0x21, 0x00] => Ok(MagType::Soniti),
  252. [0x02, 0x22, 0x00] => Ok(MagType::Preta),
  253. [0x02, 0x23, 0x00] => Ok(MagType::Andhaka),
  254. [0x02, 0x24, 0x00] => Ok(MagType::Bana),
  255. [0x02, 0x25, 0x00] => Ok(MagType::Naraka),
  256. [0x02, 0x26, 0x00] => Ok(MagType::Madhu),
  257. [0x02, 0x27, 0x00] => Ok(MagType::Churel),
  258. [0x02, 0x28, 0x00] => Ok(MagType::Robochao),
  259. [0x02, 0x29, 0x00] => Ok(MagType::OpaOpa),
  260. [0x02, 0x2A, 0x00] => Ok(MagType::Pian),
  261. [0x02, 0x2B, 0x00] => Ok(MagType::Chao),
  262. [0x02, 0x2C, 0x00] => Ok(MagType::ChuChu),
  263. [0x02, 0x2D, 0x00] => Ok(MagType::KapuKapu),
  264. [0x02, 0x2E, 0x00] => Ok(MagType::AngelsWing),
  265. [0x02, 0x2F, 0x00] => Ok(MagType::DevilsWing),
  266. [0x02, 0x30, 0x00] => Ok(MagType::Elenor),
  267. [0x02, 0x31, 0x00] => Ok(MagType::MarkIII),
  268. [0x02, 0x32, 0x00] => Ok(MagType::MasterSystem),
  269. [0x02, 0x33, 0x00] => Ok(MagType::Genesis),
  270. [0x02, 0x34, 0x00] => Ok(MagType::SegaSaturn),
  271. [0x02, 0x35, 0x00] => Ok(MagType::Dreamcast),
  272. [0x02, 0x36, 0x00] => Ok(MagType::Hamburger),
  273. [0x02, 0x37, 0x00] => Ok(MagType::PanzersTail),
  274. [0x02, 0x38, 0x00] => Ok(MagType::DevilsTail),
  275. [0x02, 0x39, 0x00] => Ok(MagType::Deva),
  276. [0x02, 0x3A, 0x00] => Ok(MagType::Rati),
  277. [0x02, 0x3B, 0x00] => Ok(MagType::Savitri),
  278. [0x02, 0x3C, 0x00] => Ok(MagType::Rukmin),
  279. [0x02, 0x3D, 0x00] => Ok(MagType::Pushan),
  280. [0x02, 0x3E, 0x00] => Ok(MagType::Diwari),
  281. [0x02, 0x3F, 0x00] => Ok(MagType::Sato),
  282. [0x02, 0x40, 0x00] => Ok(MagType::Bhima),
  283. [0x02, 0x41, 0x00] => Ok(MagType::Nidra),
  284. [0x02, 0x42, 0x00] => Ok(MagType::GeungSi),
  285. [0x02, 0x44, 0x00] => Ok(MagType::Tellusis),
  286. [0x02, 0x45, 0x00] => Ok(MagType::StrikerUnit),
  287. [0x02, 0x46, 0x00] => Ok(MagType::Pioneer),
  288. [0x02, 0x47, 0x00] => Ok(MagType::Puyo),
  289. [0x02, 0x48, 0x00] => Ok(MagType::Moro),
  290. [0x02, 0x49, 0x00] => Ok(MagType::Rappy),
  291. [0x02, 0x4A, 0x00] => Ok(MagType::Yahoo),
  292. [0x02, 0x4B, 0x00] => Ok(MagType::GaelGiel),
  293. [0x02, 0x4C, 0x00] => Ok(MagType::Agastya),
  294. _ => Err(ItemParseError::InvalidMagType),
  295. }
  296. }
  297. pub fn can_evolve(&self) -> bool {
  298. match self {
  299. MagType::Mag => true,
  300. MagType::Varuna => true,
  301. MagType::Mitra => true,
  302. MagType::Surya => true,
  303. MagType::Vayu => true,
  304. MagType::Varaha => true,
  305. MagType::Kama => true,
  306. MagType::Ushasu => true,
  307. MagType::Apsaras => true,
  308. MagType::Kumara => true,
  309. MagType::Kaitabha => true,
  310. MagType::Tapas => true,
  311. MagType::Bhirava => true,
  312. MagType::Kalki => true,
  313. MagType::Rudra => true,
  314. MagType::Marutah => true,
  315. MagType::Yaksa => true,
  316. MagType::Sita => true,
  317. MagType::Garuda => true,
  318. MagType::Nandin => true,
  319. MagType::Ashvinau => true,
  320. MagType::Ribhava => true,
  321. MagType::Soma => true,
  322. MagType::Ila => true,
  323. MagType::Durga => true,
  324. MagType::Vritra => true,
  325. MagType::Namuci => true,
  326. MagType::Sumba => true,
  327. MagType::Naga => true,
  328. MagType::Pitri => true,
  329. MagType::Kabanda => true,
  330. MagType::Ravana => true,
  331. MagType::Marica => true,
  332. MagType::Soniti => true,
  333. MagType::Preta => true,
  334. MagType::Andhaka => true,
  335. MagType::Bana => true,
  336. MagType::Naraka => true,
  337. MagType::Madhu => true,
  338. MagType::Churel => false,
  339. MagType::Robochao => false,
  340. MagType::OpaOpa => false,
  341. MagType::Pian => false,
  342. MagType::Chao => false,
  343. MagType::ChuChu => false,
  344. MagType::KapuKapu => false,
  345. MagType::AngelsWing => false,
  346. MagType::DevilsWing => false,
  347. MagType::Elenor => false,
  348. MagType::MarkIII => false,
  349. MagType::MasterSystem => false,
  350. MagType::Genesis => false,
  351. MagType::SegaSaturn => false,
  352. MagType::Dreamcast => false,
  353. MagType::Hamburger => false,
  354. MagType::PanzersTail => false,
  355. MagType::DevilsTail => false,
  356. MagType::Deva => false,
  357. MagType::Rati => false,
  358. MagType::Savitri => false,
  359. MagType::Rukmin => false,
  360. MagType::Pushan => false,
  361. MagType::Diwari => false,
  362. MagType::Sato => false,
  363. MagType::Bhima => false,
  364. MagType::Nidra => false,
  365. MagType::GeungSi => false,
  366. MagType::Tellusis => false,
  367. MagType::StrikerUnit => false,
  368. MagType::Pioneer => false,
  369. MagType::Puyo => false,
  370. MagType::Moro => false,
  371. MagType::Rappy => false,
  372. MagType::Yahoo => false,
  373. MagType::GaelGiel => false,
  374. MagType::Agastya => false,
  375. }
  376. }
  377. }
  378. pub enum MagCell {
  379. CellOfMag502,
  380. CellOfMag213,
  381. PartsOfRobochao,
  382. HeartOfOpaOpa,
  383. HeartOfPian,
  384. HeartOfChao,
  385. HeartOfAngel,
  386. HeartOfDevil,
  387. KitOfHamburger,
  388. PanthersSpirit,
  389. KitOfMark3,
  390. KitOfMasterSystem,
  391. KitOfGenesis,
  392. KitOfSegaSaturn,
  393. KitOfDreamcast,
  394. Tablet,
  395. DragonScale,
  396. HeavenStrikerCoat,
  397. PioneerParts,
  398. AmitiesMemo,
  399. HeartOfMorolian,
  400. RappysBeak,
  401. YahoosEngine,
  402. DPhotonCore,
  403. LibertaKit,
  404. }
  405. impl std::convert::TryFrom<ToolType> for MagCell {
  406. type Error = ();
  407. fn try_from(tool: ToolType) -> Result<MagCell, ()> {
  408. match tool {
  409. ToolType::CellOfMag502 => Ok(MagCell::CellOfMag502),
  410. ToolType::CellOfMag213 => Ok(MagCell::CellOfMag213),
  411. ToolType::PartsOfRobochao => Ok(MagCell::PartsOfRobochao),
  412. ToolType::HeartOfOpaOpa => Ok(MagCell::HeartOfOpaOpa),
  413. ToolType::HeartOfPian => Ok(MagCell::HeartOfPian),
  414. ToolType::HeartOfChao => Ok(MagCell::HeartOfChao),
  415. ToolType::HeartOfAngel => Ok(MagCell::HeartOfAngel),
  416. ToolType::HeartOfDevil => Ok(MagCell::HeartOfDevil),
  417. ToolType::KitOfHamburger => Ok(MagCell::KitOfHamburger),
  418. ToolType::PanthersSpirit => Ok(MagCell::PanthersSpirit),
  419. ToolType::KitOfMark3 => Ok(MagCell::KitOfMark3),
  420. ToolType::KitOfMasterSystem => Ok(MagCell::KitOfMasterSystem),
  421. ToolType::KitOfGenesis => Ok(MagCell::KitOfGenesis),
  422. ToolType::KitOfSegaSaturn => Ok(MagCell::KitOfSegaSaturn),
  423. ToolType::KitOfDreamcast => Ok(MagCell::KitOfDreamcast),
  424. ToolType::Tablet => Ok(MagCell::Tablet),
  425. ToolType::DragonScale => Ok(MagCell::DragonScale),
  426. ToolType::HeavenStrikerCoat => Ok(MagCell::HeavenStrikerCoat),
  427. ToolType::PioneerParts => Ok(MagCell::PioneerParts),
  428. ToolType::AmitiesMemo => Ok(MagCell::AmitiesMemo),
  429. ToolType::HeartOfMorolian => Ok(MagCell::HeartOfMorolian),
  430. ToolType::RappysBeak => Ok(MagCell::RappysBeak),
  431. ToolType::YahoosEngine => Ok(MagCell::YahoosEngine),
  432. ToolType::DPhotonCore => Ok(MagCell::DPhotonCore),
  433. ToolType::LibertaKit => Ok(MagCell::LibertaKit),
  434. _ => Err(()),
  435. }
  436. }
  437. }
  438. enum MagAttribute {
  439. //Def,
  440. Pow,
  441. Dex,
  442. Mind,
  443. }
  444. // one day I hope to be cool enough to figure how to enforce that each magattribute in sequence must be unique
  445. // (to not need the _ in the match)
  446. enum MagAttributeOrdering {
  447. Sequence(MagAttribute, MagAttribute, MagAttribute),
  448. Primary(MagAttribute),
  449. MultiPrimary
  450. }
  451. impl MagAttributeOrdering {
  452. fn new(pow: u16, dex: u16, mnd: u16) -> MagAttributeOrdering {
  453. let primary = if pow > dex && pow > mnd {
  454. MagAttribute::Pow
  455. }
  456. else if dex > pow && dex > mnd{
  457. MagAttribute::Dex
  458. }
  459. else if mnd > pow && mnd > dex {
  460. MagAttribute::Mind
  461. }
  462. else {
  463. return MagAttributeOrdering::MultiPrimary
  464. };
  465. match primary {
  466. MagAttribute::Pow => {
  467. match dex.cmp(&mnd) {
  468. Greater => MagAttributeOrdering::Sequence(primary, MagAttribute::Dex, MagAttribute::Mind),
  469. Equal => MagAttributeOrdering::Primary(primary),
  470. Less => MagAttributeOrdering::Sequence(primary, MagAttribute::Mind, MagAttribute::Dex),
  471. }
  472. },
  473. MagAttribute::Dex => {
  474. match pow.cmp(&mnd) {
  475. Greater => MagAttributeOrdering::Sequence(primary, MagAttribute::Pow, MagAttribute::Mind),
  476. Equal => MagAttributeOrdering::Primary(primary),
  477. Less => MagAttributeOrdering::Sequence(primary, MagAttribute::Mind, MagAttribute::Pow),
  478. }
  479. },
  480. MagAttribute::Mind => {
  481. match pow.cmp(&dex) {
  482. Greater => MagAttributeOrdering::Sequence(primary, MagAttribute::Pow, MagAttribute::Dex),
  483. Equal => MagAttributeOrdering::Primary(primary),
  484. Less => MagAttributeOrdering::Sequence(primary, MagAttribute::Dex, MagAttribute::Pow),
  485. }
  486. },
  487. }
  488. }
  489. }
  490. #[derive(Debug, Clone, PartialEq)]
  491. pub enum MagModifier {
  492. FeedMag{
  493. food: ItemEntityId,
  494. },
  495. BankMag, // when putting a mag in the bank it truncates the values which has applications when raising degenerate mags
  496. MagCell(ItemEntityId),
  497. OwnerChange(CharacterClass, SectionID)
  498. }
  499. #[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize, enum_utils::FromStr)]
  500. pub enum PhotonBlast {
  501. Farlla,
  502. Estlla,
  503. Leilla,
  504. Pilla,
  505. Golla,
  506. MyllaYoulla,
  507. }
  508. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
  509. pub struct Mag {
  510. pub mag: MagType,
  511. def: u16,
  512. pow: u16,
  513. dex: u16,
  514. mnd: u16,
  515. pub synchro: u8,
  516. iq: u8,
  517. photon_blast: [Option<PhotonBlast>; 3],
  518. pub color: u8,
  519. //modifiers: Vec<MagModifier>,
  520. pub class: CharacterClass,
  521. pub id: SectionID,
  522. }
  523. impl Mag {
  524. pub fn baby_mag(skin: u16) -> Mag {
  525. Mag {
  526. mag: MagType::Mag,
  527. def: 500,
  528. pow: 0,
  529. dex: 0,
  530. mnd: 0,
  531. synchro: 20,
  532. iq: 0,
  533. photon_blast: [None; 3],
  534. color: (skin % 18) as u8,
  535. //modifiers: Vec::new(),
  536. class: CharacterClass::HUmar,
  537. id: SectionID::Viridia,
  538. }
  539. }
  540. pub fn as_bytes(&self) -> [u8; 16] {
  541. let mut result = [0; 16];
  542. result[0..3].copy_from_slice(&self.mag.value());
  543. result[3] = self.photon_blast_value();
  544. result[4..6].copy_from_slice(&self.def.to_le_bytes());
  545. result[6..8].copy_from_slice(&self.pow.to_le_bytes());
  546. result[8..10].copy_from_slice(&self.dex.to_le_bytes());
  547. result[10..12].copy_from_slice(&self.mnd.to_le_bytes());
  548. result[12] = self.synchro;
  549. result[13] = self.iq;
  550. result[14] = self.photon_blast_count();
  551. result[15] = self.color;
  552. result
  553. }
  554. fn photon_blast_value(&self) -> u8 {
  555. let mut photon_blast_list = vec![PhotonBlast::Farlla,
  556. PhotonBlast::Estlla,
  557. PhotonBlast::Golla,
  558. PhotonBlast::Pilla,
  559. PhotonBlast::Leilla,
  560. PhotonBlast::MyllaYoulla];
  561. let mut photon_blast: u8 = 0;
  562. if let Some(ref pb_mid) = self.photon_blast[0] {
  563. match *pb_mid {
  564. PhotonBlast::Farlla => {},
  565. PhotonBlast::Estlla => photon_blast |= 1,
  566. PhotonBlast::Golla => photon_blast |= 2,
  567. PhotonBlast::Pilla => photon_blast |= 3,
  568. PhotonBlast::Leilla => photon_blast |= 4,
  569. PhotonBlast::MyllaYoulla => photon_blast |= 5,
  570. }
  571. photon_blast_list.retain(|k| k != pb_mid);
  572. }
  573. if let Some(ref pb_right) = self.photon_blast[1] {
  574. match *pb_right {
  575. PhotonBlast::Farlla => {}
  576. PhotonBlast::Estlla => photon_blast |= 1 << 3,
  577. PhotonBlast::Golla => photon_blast |= 2 << 3,
  578. PhotonBlast::Pilla => photon_blast |= 3 << 3,
  579. PhotonBlast::Leilla => photon_blast |= 4 << 3,
  580. PhotonBlast::MyllaYoulla => photon_blast |= 5 << 3,
  581. }
  582. photon_blast_list.retain(|k| k != pb_right);
  583. }
  584. if let Some(ref pb_left) = self.photon_blast[2] {
  585. if let Some(pos) = photon_blast_list.iter().position(|k| k == pb_left) {
  586. photon_blast |= (pos as u8) << 6;
  587. };
  588. }
  589. photon_blast
  590. }
  591. fn photon_blast_count(&self) -> u8 {
  592. let mut count = 0;
  593. for i in 0..3 {
  594. if let Some(_) = self.photon_blast[i] {
  595. count |= 1 << i
  596. };
  597. }
  598. count
  599. }
  600. pub fn from_bytes(data: [u8; 16]) -> Result<Mag, ItemParseError> {
  601. let m = MagType::parse_type([data[0], data[1], data[2]]);
  602. if m.is_ok() {
  603. let mut def = u16::from_le_bytes([data[4], data[5]]);
  604. let mut pow = u16::from_le_bytes([data[6], data[7]]);
  605. let mut dex = u16::from_le_bytes([data[8], data[9]]);
  606. let mut mind = u16::from_le_bytes([data[10], data[11]]);
  607. if (def/100 + dex/100 + pow/100 + mind/100) > 200 {
  608. def = 0;
  609. pow = 0;
  610. dex = 0;
  611. mind = 0;
  612. }
  613. let sync = data[12] % 121; // TODO: handle invalid values.
  614. let iq = data[13] % 201; // TODO: handle invalid values.
  615. Ok(Mag{
  616. mag: m.unwrap(),
  617. def: def,
  618. pow: pow,
  619. dex: dex,
  620. mnd: mind,
  621. synchro: sync,
  622. iq: iq,
  623. photon_blast: [None, None, None], // TODO: actually get PBs from bytes
  624. color: data[15] % 18,
  625. //modifiers: Vec::new(),
  626. class: CharacterClass::HUmar,
  627. id: SectionID::Viridia,
  628. })
  629. }
  630. else {
  631. Err(ItemParseError::InvalidMagBytes) // TODO: error handling if wrong bytes are given
  632. }
  633. }
  634. pub fn def(&self) -> u16 {
  635. self.def/100
  636. }
  637. pub fn pow(&self) -> u16 {
  638. self.pow/100
  639. }
  640. pub fn dex(&self) -> u16 {
  641. self.dex/100
  642. }
  643. pub fn mind(&self) -> u16 {
  644. self.mnd/100
  645. }
  646. pub fn level(&self) -> u16 {
  647. self.def() + self.pow() + self.dex() + self.mind()
  648. }
  649. fn change_mag_type(&mut self, previous_level: u16) {
  650. if !self.mag.can_evolve() {
  651. return
  652. }
  653. if self.level() >= 10 && previous_level < 10 {
  654. match self.class {
  655. CharacterClass::HUmar | CharacterClass::HUnewearl | CharacterClass::HUcast | CharacterClass::HUcaseal => {
  656. self.mag = MagType::Varuna
  657. },
  658. CharacterClass::RAmar | CharacterClass::RAmarl | CharacterClass::RAcast | CharacterClass::RAcaseal => {
  659. self.mag = MagType::Kalki
  660. },
  661. CharacterClass::FOmar | CharacterClass::FOmarl | CharacterClass::FOnewm | CharacterClass::FOnewearl => {
  662. self.mag = MagType::Vritra
  663. },
  664. }
  665. }
  666. if self.level() >= 35 && previous_level < 35 {
  667. match self.mag {
  668. MagType::Varuna => {
  669. if self.pow > self.dex && self.pow > self.mnd {
  670. self.mag = MagType::Rudra
  671. }
  672. else if self.dex > self.pow && self.dex > self.mnd {
  673. self.mag = MagType::Marutah
  674. }
  675. else if self.mnd > self.pow && self.mnd > self.dex {
  676. self.mag = MagType::Vayu
  677. }
  678. else {
  679. self.mag = MagType::Rudra
  680. }
  681. },
  682. MagType::Kalki => {
  683. if self.pow > self.dex && self.pow > self.mnd {
  684. self.mag = MagType::Surya
  685. }
  686. else if self.dex > self.pow && self.dex > self.mnd {
  687. self.mag = MagType::Mitra
  688. }
  689. else if self.mnd > self.pow && self.mnd > self.dex {
  690. self.mag = MagType::Tapas
  691. }
  692. else {
  693. self.mag = MagType::Mitra
  694. }
  695. },
  696. MagType::Vritra => {
  697. if self.pow > self.dex && self.pow > self.mnd {
  698. self.mag = MagType::Sumba
  699. }
  700. else if self.dex > self.pow && self.dex > self.mnd {
  701. self.mag = MagType::Ashvinau
  702. }
  703. else if self.mnd > self.pow && self.mnd > self.dex {
  704. self.mag = MagType::Namuci
  705. }
  706. else {
  707. self.mag = MagType::Namuci
  708. }
  709. },
  710. _ => unreachable!(),
  711. }
  712. }
  713. if self.level() >= 50 && self.level() % 5 == 0 {
  714. let mag_attr_ordering = MagAttributeOrdering::new(self.pow, self.dex, self.mnd);
  715. self.mag = match self.id {
  716. SectionID::Viridia | SectionID::Skyly | SectionID::Purplenum | SectionID::Redria | SectionID::Yellowboze => {
  717. match self.class {
  718. CharacterClass::HUmar | CharacterClass::HUnewearl | CharacterClass::HUcast | CharacterClass::HUcaseal => {
  719. match mag_attr_ordering {
  720. MagAttributeOrdering::Primary(MagAttribute::Pow) => MagType::Varaha,
  721. MagAttributeOrdering::Primary(MagAttribute::Dex) => MagType::Nandin,
  722. MagAttributeOrdering::Primary(MagAttribute::Mind) => MagType::Kabanda,
  723. MagAttributeOrdering::Sequence(MagAttribute::Pow, MagAttribute::Dex, MagAttribute::Mind) => MagType::Varaha,
  724. MagAttributeOrdering::Sequence(MagAttribute::Pow, MagAttribute::Mind, MagAttribute::Dex) => MagType::Bhirava,
  725. MagAttributeOrdering::Sequence(MagAttribute::Dex, MagAttribute::Pow, MagAttribute::Mind) => MagType::Ila,
  726. MagAttributeOrdering::Sequence(MagAttribute::Dex, MagAttribute::Mind, MagAttribute::Pow) => MagType::Nandin,
  727. MagAttributeOrdering::Sequence(MagAttribute::Mind, MagAttribute::Pow, MagAttribute::Dex) => MagType::Kabanda,
  728. MagAttributeOrdering::Sequence(MagAttribute::Mind, MagAttribute::Dex, MagAttribute::Pow) => MagType::Ushasu,
  729. MagAttributeOrdering::MultiPrimary => {
  730. if self.dex >= self.mnd {
  731. MagType::Varaha
  732. }
  733. else {
  734. MagType::Bhirava
  735. }
  736. },
  737. _ => unreachable!()
  738. }
  739. },
  740. CharacterClass::RAmar | CharacterClass::RAmarl | CharacterClass::RAcast | CharacterClass::RAcaseal => {
  741. match mag_attr_ordering {
  742. MagAttributeOrdering::Primary(MagAttribute::Pow) => MagType::Kama,
  743. MagAttributeOrdering::Primary(MagAttribute::Dex) => MagType::Kama,
  744. MagAttributeOrdering::Primary(MagAttribute::Mind) => MagType::Varaha,
  745. MagAttributeOrdering::Sequence(MagAttribute::Pow, MagAttribute::Dex, MagAttribute::Mind) => MagType::Kama,
  746. MagAttributeOrdering::Sequence(MagAttribute::Pow, MagAttribute::Mind, MagAttribute::Dex) => MagType::Bhirava,
  747. MagAttributeOrdering::Sequence(MagAttribute::Dex, MagAttribute::Pow, MagAttribute::Mind) => MagType::Bhirava,
  748. MagAttributeOrdering::Sequence(MagAttribute::Dex, MagAttribute::Mind, MagAttribute::Pow) => MagType::Kama,
  749. MagAttributeOrdering::Sequence(MagAttribute::Mind, MagAttribute::Pow, MagAttribute::Dex) => MagType::Varaha,
  750. MagAttributeOrdering::Sequence(MagAttribute::Mind, MagAttribute::Dex, MagAttribute::Pow) => MagType::Apsaras,
  751. MagAttributeOrdering::MultiPrimary => {
  752. if self.mnd >= self.pow {
  753. MagType::Kama
  754. }
  755. else {
  756. MagType::Bhirava
  757. }
  758. }
  759. _ => unreachable!()
  760. }
  761. },
  762. CharacterClass::FOmar | CharacterClass::FOmarl | CharacterClass::FOnewm | CharacterClass::FOnewearl => {
  763. match (mag_attr_ordering, self.def() >= 45) {
  764. (MagAttributeOrdering::Primary(MagAttribute::Pow), true) => MagType::Andhaka,
  765. (MagAttributeOrdering::Primary(MagAttribute::Dex), true) => MagType::Bana,
  766. (MagAttributeOrdering::Primary(MagAttribute::Mind), true) => MagType::Bana,
  767. (MagAttributeOrdering::Sequence(MagAttribute::Pow, MagAttribute::Dex, MagAttribute::Mind), true) => MagType::Andhaka,
  768. (MagAttributeOrdering::Sequence(MagAttribute::Pow, MagAttribute::Mind, MagAttribute::Dex), true) => MagType::Andhaka,
  769. (MagAttributeOrdering::Sequence(MagAttribute::Dex, MagAttribute::Pow, MagAttribute::Mind), true) => MagType::Bana,
  770. (MagAttributeOrdering::Sequence(MagAttribute::Dex, MagAttribute::Mind, MagAttribute::Pow), true) => MagType::Bana,
  771. (MagAttributeOrdering::Sequence(MagAttribute::Mind, MagAttribute::Pow, MagAttribute::Dex), true) => MagType::Bana,
  772. (MagAttributeOrdering::Sequence(MagAttribute::Mind, MagAttribute::Dex, MagAttribute::Pow), true) => MagType::Bana,
  773. (MagAttributeOrdering::MultiPrimary, true) => MagType::Bana,
  774. (MagAttributeOrdering::Primary(MagAttribute::Pow), false) => MagType::Naraka,
  775. (MagAttributeOrdering::Primary(MagAttribute::Dex), false) => MagType::Sita,
  776. (MagAttributeOrdering::Primary(MagAttribute::Mind), false) => MagType::Naga,
  777. (MagAttributeOrdering::Sequence(MagAttribute::Pow, MagAttribute::Dex, MagAttribute::Mind), false) => MagType::Naraka,
  778. (MagAttributeOrdering::Sequence(MagAttribute::Pow, MagAttribute::Mind, MagAttribute::Dex), false) => MagType::Ravana,
  779. (MagAttributeOrdering::Sequence(MagAttribute::Dex, MagAttribute::Pow, MagAttribute::Mind), false) => MagType::Ribhava,
  780. (MagAttributeOrdering::Sequence(MagAttribute::Dex, MagAttribute::Mind, MagAttribute::Pow), false) => MagType::Sita,
  781. (MagAttributeOrdering::Sequence(MagAttribute::Mind, MagAttribute::Pow, MagAttribute::Dex), false) => MagType::Naga,
  782. (MagAttributeOrdering::Sequence(MagAttribute::Mind, MagAttribute::Dex, MagAttribute::Pow), false) => MagType::Kabanda,
  783. (MagAttributeOrdering::MultiPrimary, false) => {
  784. if self.pow >= self.dex {
  785. MagType::Naga
  786. }
  787. else {
  788. MagType::Kabanda
  789. }
  790. }
  791. _ => unreachable!()
  792. }
  793. },
  794. }
  795. },
  796. SectionID::Greenill | SectionID::Bluefull | SectionID::Pinkal | SectionID::Oran | SectionID::Whitill => {
  797. match self.class {
  798. CharacterClass::HUmar | CharacterClass::HUnewearl | CharacterClass::HUcast | CharacterClass::HUcaseal => {
  799. match mag_attr_ordering {
  800. MagAttributeOrdering::Primary(MagAttribute::Pow) => MagType::Kama,
  801. MagAttributeOrdering::Primary(MagAttribute::Dex) => MagType::Yaksa,
  802. MagAttributeOrdering::Primary(MagAttribute::Mind) => MagType::Bana,
  803. MagAttributeOrdering::Sequence(MagAttribute::Pow, MagAttribute::Dex, MagAttribute::Mind) => MagType::Kama,
  804. MagAttributeOrdering::Sequence(MagAttribute::Pow, MagAttribute::Mind, MagAttribute::Dex) => MagType::Apsaras,
  805. MagAttributeOrdering::Sequence(MagAttribute::Dex, MagAttribute::Pow, MagAttribute::Mind) => MagType::Garuda,
  806. MagAttributeOrdering::Sequence(MagAttribute::Dex, MagAttribute::Mind, MagAttribute::Pow) => MagType::Yaksa,
  807. MagAttributeOrdering::Sequence(MagAttribute::Mind, MagAttribute::Pow, MagAttribute::Dex) => MagType::Bana,
  808. MagAttributeOrdering::Sequence(MagAttribute::Mind, MagAttribute::Dex, MagAttribute::Pow) => MagType::Soma,
  809. MagAttributeOrdering::MultiPrimary => {
  810. if self.dex >= self.mnd {
  811. MagType::Kama
  812. }
  813. else {
  814. MagType::Apsaras
  815. }
  816. }
  817. _ => unreachable!()
  818. }
  819. },
  820. CharacterClass::RAmar | CharacterClass::RAmarl | CharacterClass::RAcast | CharacterClass::RAcaseal => {
  821. match mag_attr_ordering {
  822. MagAttributeOrdering::Primary(MagAttribute::Pow) => MagType::Madhu,
  823. MagAttributeOrdering::Primary(MagAttribute::Dex) => MagType::Varaha,
  824. MagAttributeOrdering::Primary(MagAttribute::Mind) => MagType::Kabanda,
  825. MagAttributeOrdering::Sequence(MagAttribute::Pow, MagAttribute::Dex, MagAttribute::Mind) => MagType::Madhu,
  826. MagAttributeOrdering::Sequence(MagAttribute::Pow, MagAttribute::Mind, MagAttribute::Dex) => MagType::Kaitabha,
  827. MagAttributeOrdering::Sequence(MagAttribute::Dex, MagAttribute::Pow, MagAttribute::Mind) => MagType::Kaitabha,
  828. MagAttributeOrdering::Sequence(MagAttribute::Dex, MagAttribute::Mind, MagAttribute::Pow) => MagType::Varaha,
  829. MagAttributeOrdering::Sequence(MagAttribute::Mind, MagAttribute::Pow, MagAttribute::Dex) => MagType::Kabanda,
  830. MagAttributeOrdering::Sequence(MagAttribute::Mind, MagAttribute::Dex, MagAttribute::Pow) => MagType::Durga,
  831. MagAttributeOrdering::MultiPrimary => {
  832. if self.pow > self.mnd {
  833. MagType::Kaitabha
  834. }
  835. else {
  836. MagType::Varaha
  837. }
  838. }
  839. _ => unreachable!()
  840. }
  841. },
  842. CharacterClass::FOmar | CharacterClass::FOmarl | CharacterClass::FOnewm | CharacterClass::FOnewearl => {
  843. match (mag_attr_ordering, self.def() >= 45) {
  844. (MagAttributeOrdering::Primary(MagAttribute::Pow), true) => MagType::Andhaka,
  845. (MagAttributeOrdering::Primary(MagAttribute::Dex), true) => MagType::Bana,
  846. (MagAttributeOrdering::Primary(MagAttribute::Mind), true) => MagType::Bana,
  847. (MagAttributeOrdering::Sequence(MagAttribute::Pow, MagAttribute::Dex, MagAttribute::Mind), true) => MagType::Andhaka,
  848. (MagAttributeOrdering::Sequence(MagAttribute::Pow, MagAttribute::Mind, MagAttribute::Dex), true) => MagType::Andhaka,
  849. (MagAttributeOrdering::Sequence(MagAttribute::Dex, MagAttribute::Pow, MagAttribute::Mind), true) => MagType::Bana,
  850. (MagAttributeOrdering::Sequence(MagAttribute::Dex, MagAttribute::Mind, MagAttribute::Pow), true) => MagType::Bana,
  851. (MagAttributeOrdering::Sequence(MagAttribute::Mind, MagAttribute::Pow, MagAttribute::Dex), true) => MagType::Bana,
  852. (MagAttributeOrdering::Sequence(MagAttribute::Mind, MagAttribute::Dex, MagAttribute::Pow), true) => MagType::Bana,
  853. (MagAttributeOrdering::MultiPrimary, true) => MagType::Bana,
  854. (MagAttributeOrdering::Primary(MagAttribute::Pow), false) => MagType::Marica,
  855. (MagAttributeOrdering::Primary(MagAttribute::Dex), false) => MagType::Bhirava,
  856. (MagAttributeOrdering::Primary(MagAttribute::Mind), false) => MagType::Kumara,
  857. (MagAttributeOrdering::Sequence(MagAttribute::Pow, MagAttribute::Dex, MagAttribute::Mind), false) => MagType::Marica,
  858. (MagAttributeOrdering::Sequence(MagAttribute::Pow, MagAttribute::Mind, MagAttribute::Dex), false) => MagType::Naga,
  859. (MagAttributeOrdering::Sequence(MagAttribute::Dex, MagAttribute::Pow, MagAttribute::Mind), false) => MagType::Garuda,
  860. (MagAttributeOrdering::Sequence(MagAttribute::Dex, MagAttribute::Mind, MagAttribute::Pow), false) => MagType::Bhirava,
  861. (MagAttributeOrdering::Sequence(MagAttribute::Mind, MagAttribute::Pow, MagAttribute::Dex), false) => MagType::Kumara,
  862. (MagAttributeOrdering::Sequence(MagAttribute::Mind, MagAttribute::Dex, MagAttribute::Pow), false) => MagType::Ila,
  863. (MagAttributeOrdering::MultiPrimary, false) => {
  864. if self.pow >= self.dex {
  865. MagType::Kumara
  866. }
  867. else {
  868. MagType::Ila
  869. }
  870. }
  871. _ => unreachable!()
  872. }
  873. },
  874. }
  875. }
  876. };
  877. }
  878. if self.level() >= 100 && self.level() % 5 == 0 {
  879. match self.id {
  880. SectionID::Skyly | SectionID::Pinkal | SectionID::Yellowboze => {
  881. if self.def() + self.pow() == self.dex() + self.mind() {
  882. self.mag = match self.class {
  883. CharacterClass::HUmar | CharacterClass::HUcast => {
  884. MagType::Rati
  885. },
  886. CharacterClass::HUnewearl | CharacterClass::HUcaseal => {
  887. MagType::Savitri
  888. },
  889. CharacterClass::RAmar | CharacterClass::RAcast => {
  890. MagType::Pushan
  891. },
  892. CharacterClass::RAmarl | CharacterClass::RAcaseal => {
  893. MagType::Diwari
  894. },
  895. CharacterClass::FOmar | CharacterClass::FOnewm => {
  896. MagType::Nidra
  897. },
  898. CharacterClass::FOmarl | CharacterClass::FOnewearl => {
  899. MagType::Bhima
  900. },
  901. }
  902. }
  903. },
  904. SectionID::Viridia | SectionID::Bluefull | SectionID::Redria | SectionID::Whitill => {
  905. if self.def() + self.dex() == self.pow() + self.mind() {
  906. self.mag = match self.class {
  907. CharacterClass::HUmar | CharacterClass::HUcast => {
  908. MagType::Deva
  909. },
  910. CharacterClass::HUnewearl | CharacterClass::HUcaseal => {
  911. MagType::Savitri
  912. },
  913. CharacterClass::RAmar | CharacterClass::RAcast => {
  914. MagType::Pushan
  915. },
  916. CharacterClass::RAmarl | CharacterClass::RAcaseal => {
  917. MagType::Rukmin
  918. },
  919. CharacterClass::FOmar | CharacterClass::FOnewm => {
  920. MagType::Nidra
  921. },
  922. CharacterClass::FOmarl | CharacterClass::FOnewearl => {
  923. MagType::Sato // best mag
  924. },
  925. }
  926. }
  927. },
  928. SectionID::Greenill | SectionID::Purplenum | SectionID::Oran => {
  929. if self.def() + self.mind() == self.pow() + self.dex() {
  930. self.mag = match self.class {
  931. CharacterClass::HUmar | CharacterClass::HUcast => {
  932. MagType::Rati
  933. },
  934. CharacterClass::HUnewearl | CharacterClass::HUcaseal => {
  935. MagType::Savitri
  936. },
  937. CharacterClass::RAmar | CharacterClass::RAcast => {
  938. MagType::Pushan
  939. },
  940. CharacterClass::RAmarl | CharacterClass::RAcaseal => {
  941. MagType::Rukmin
  942. },
  943. CharacterClass::FOmar | CharacterClass::FOnewm => {
  944. MagType::Nidra
  945. },
  946. CharacterClass::FOmarl | CharacterClass::FOnewearl => {
  947. MagType::Bhima
  948. },
  949. }
  950. }
  951. }
  952. }
  953. }
  954. }
  955. pub fn assign_photon_blast(&mut self) {
  956. MAG_STATS.get(&self.mag).map(|stats| {
  957. stats.photon_blast.map(|photon_blast| {
  958. if !self.photon_blast.contains(&Some(photon_blast)) {
  959. self.photon_blast.iter_mut().find(|k| k.is_none()).map(|pb_slot| {
  960. *pb_slot = Some(photon_blast)
  961. });
  962. }
  963. })
  964. });
  965. }
  966. pub fn feed(&mut self, tool: ToolType) {
  967. let previous_level = self.level();
  968. MAG_STATS.get(&self.mag).map(|stats| {
  969. MAG_FEEDING_TABLES.get(stats.feed_table).map(|feeding_table| {
  970. feeding_table.get(&tool).map(|feed_stats| {
  971. self.def = std::cmp::max(std::cmp::max((self.def as i16) + feed_stats.def, 0) as u16, self.def()*100);
  972. self.pow = std::cmp::max(std::cmp::max((self.pow as i16) + feed_stats.pow, 0) as u16, self.pow()*100);
  973. self.dex = std::cmp::max(std::cmp::max((self.dex as i16) + feed_stats.dex, 0) as u16, self.dex()*100);
  974. self.mnd = std::cmp::max(std::cmp::max((self.mnd as i16) + feed_stats.mnd, 0) as u16, self.mind()*100);
  975. self.iq = std::cmp::min(((self.iq as i16) + feed_stats.iq as i16) as u8, 200);
  976. self.synchro = std::cmp::min(((self.synchro as i8) + feed_stats.syn) as u8, 120);
  977. })
  978. })
  979. });
  980. //if previous_level != self.level() {
  981. self.change_mag_type(previous_level);
  982. self.assign_photon_blast();
  983. //}
  984. }
  985. pub fn change_owner(&mut self, class: CharacterClass, id: SectionID) {
  986. self.class = class;
  987. self.id = id;
  988. }
  989. pub fn bank(&mut self) {
  990. self.def = self.def & 0xFFFE;
  991. self.pow = self.pow & 0xFFFE;
  992. self.dex = self.dex & 0xFFFE;
  993. self.mnd = self.mnd & 0xFFFE;
  994. }
  995. // TODO: this needs more checks on validity
  996. pub fn apply_mag_cell(&mut self, mag_cell: MagCell) {
  997. self.mag = match mag_cell {
  998. MagCell::CellOfMag502 => {
  999. match self.id {
  1000. SectionID::Viridia | SectionID::Skyly | SectionID::Purplenum | SectionID::Redria | SectionID::Yellowboze => {
  1001. MagType::Soniti
  1002. },
  1003. SectionID::Greenill | SectionID::Bluefull | SectionID::Pinkal | SectionID::Oran | SectionID::Whitill => {
  1004. MagType::Pitri
  1005. }
  1006. }
  1007. }
  1008. MagCell::CellOfMag213 => {
  1009. match self.id {
  1010. SectionID::Viridia | SectionID::Skyly | SectionID::Purplenum | SectionID::Redria | SectionID::Yellowboze => {
  1011. MagType::Churel
  1012. },
  1013. SectionID::Greenill | SectionID::Bluefull | SectionID::Pinkal | SectionID::Oran | SectionID::Whitill => {
  1014. MagType::Preta
  1015. }
  1016. }
  1017. },
  1018. MagCell::PartsOfRobochao => MagType::Robochao,
  1019. MagCell::HeartOfOpaOpa => MagType::OpaOpa,
  1020. MagCell::HeartOfPian => MagType::Pian,
  1021. MagCell::HeartOfChao => MagType::Chao,
  1022. MagCell::HeartOfAngel => MagType::AngelsWing,
  1023. MagCell::HeartOfDevil => if self.mag == MagType::DevilsWing {
  1024. MagType::DevilsTail
  1025. }
  1026. else {
  1027. MagType::DevilsWing
  1028. },
  1029. MagCell::KitOfHamburger => MagType::Hamburger,
  1030. MagCell::PanthersSpirit => MagType::PanzersTail,
  1031. MagCell::KitOfMark3 => MagType::MarkIII,
  1032. MagCell::KitOfMasterSystem => MagType::MasterSystem,
  1033. MagCell::KitOfGenesis => MagType::Genesis,
  1034. MagCell::KitOfSegaSaturn => MagType::SegaSaturn,
  1035. MagCell::KitOfDreamcast => MagType::Dreamcast,
  1036. MagCell::Tablet => MagType::GeungSi,
  1037. MagCell::DragonScale => MagType::Tellusis,
  1038. MagCell::HeavenStrikerCoat => MagType::StrikerUnit,
  1039. MagCell::PioneerParts => MagType::Pioneer,
  1040. MagCell::AmitiesMemo => MagType::Puyo,
  1041. MagCell::HeartOfMorolian => MagType::Moro,
  1042. MagCell::RappysBeak => MagType::Rappy,
  1043. MagCell::YahoosEngine => MagType::Yahoo,
  1044. MagCell::DPhotonCore => MagType::GaelGiel,
  1045. MagCell::LibertaKit => MagType::Agastya,
  1046. }
  1047. }
  1048. }
  1049. #[cfg(test)]
  1050. mod test {
  1051. use super::*;
  1052. use std::io::Read;
  1053. #[test]
  1054. fn test_load_mag_stats() {
  1055. let mut f = std::fs::File::open("data/item_stats/mag_stats.toml").unwrap();
  1056. let mut s = String::new();
  1057. f.read_to_string(&mut s).unwrap();
  1058. let mags: HashMap<String, MagStats> = toml::from_str(&s).unwrap();
  1059. let _mags = mags.into_iter()
  1060. .map(|(name, stats)| {
  1061. (name.parse().unwrap(), stats)
  1062. })
  1063. .collect::<HashMap<MagType, MagStats>>();
  1064. }
  1065. #[test]
  1066. fn test_load_mag_feed_table() {
  1067. let mut f = std::fs::File::open("data/item_stats/mag_feed_table.toml").unwrap();
  1068. let mut s = String::new();
  1069. f.read_to_string(&mut s).unwrap();
  1070. let mut feed: HashMap<String, Vec<HashMap<String, MagFeedTable>>> = toml::from_str(&s).unwrap();
  1071. let feed = feed.remove("feedtable".into()).unwrap();
  1072. let _feed = feed.into_iter()
  1073. .map(|table| {
  1074. table.into_iter()
  1075. .map(|(tool, stats)| {
  1076. (tool.parse().unwrap(), stats)
  1077. })
  1078. .collect()
  1079. })
  1080. .collect::<Vec<HashMap<ToolType, MagFeedTable>>>();
  1081. }
  1082. #[test]
  1083. fn test_raise_a_sato() {
  1084. let mut mag = Mag::baby_mag(0);
  1085. mag.change_owner(CharacterClass::RAcaseal, SectionID::Whitill);
  1086. for _ in 0..137 {
  1087. mag.feed(ToolType::Antidote);
  1088. }
  1089. for _ in 0..75 {
  1090. mag.feed(ToolType::Antiparalysis);
  1091. }
  1092. mag.change_owner(CharacterClass::FOmarl, SectionID::Whitill);
  1093. for _ in 0..51 {
  1094. mag.feed(ToolType::Antiparalysis);
  1095. }
  1096. for _ in 0..284 {
  1097. mag.feed(ToolType::Dimate);
  1098. }
  1099. assert!(mag == Mag {
  1100. mag: MagType::Sato,
  1101. def: 507,
  1102. pow: 5019,
  1103. dex: 4505,
  1104. mnd: 0,
  1105. synchro: 120,
  1106. iq: 200,
  1107. photon_blast: [Some(PhotonBlast::Estlla), Some(PhotonBlast::Pilla), Some(PhotonBlast::MyllaYoulla)],
  1108. color: 0,
  1109. class: CharacterClass::FOmarl,
  1110. id: SectionID::Whitill,
  1111. });
  1112. }
  1113. #[test]
  1114. fn test_mag_does_not_level_down() {
  1115. }
  1116. }