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.

381 lines
20 KiB

4 years ago
2 years ago
2 years ago
2 years ago
  1. // TOOD: `pub(super) for most of these?`
  2. use std::io::{Read};
  3. use std::collections::HashMap;
  4. use std::fs::File;
  5. use std::path::PathBuf;
  6. use byteorder::{LittleEndian, ReadBytesExt};
  7. use thiserror::Error;
  8. use rand::{Rng, SeedableRng};
  9. use serde::{Serialize, Deserialize};
  10. use crate::Holiday;
  11. use crate::area::{MapArea, MapAreaError};
  12. use crate::room::Episode;
  13. use crate::monster::MonsterType;
  14. #[derive(Debug, Copy, Clone)]
  15. pub struct RawMapEnemy {
  16. id: u32,
  17. _unknown1: u16,
  18. pub children: u16,
  19. _map_area: u16,
  20. _unknown4: u16,
  21. _section: u16,
  22. _wave_idd: u16,
  23. _wave_id: u32,
  24. _x: f32,
  25. _y: f32,
  26. _z: f32,
  27. _xrot: u32,
  28. _yrot: u32,
  29. _zrot: u32,
  30. _field1: u32,
  31. field2: u32,
  32. _field3: u32,
  33. _field4: u32,
  34. _field5: u32,
  35. skin: u32,
  36. _field6: u32
  37. }
  38. impl RawMapEnemy {
  39. pub fn from_byte_stream<R: Read>(cursor: &mut R) -> Result<RawMapEnemy, std::io::Error> {
  40. Ok(RawMapEnemy {
  41. id: cursor.read_u32::<LittleEndian>()?, // TODO: is this really u32? shiny monsters are referred to by u16 in the client
  42. _unknown1: cursor.read_u16::<LittleEndian>()?,
  43. children: cursor.read_u16::<LittleEndian>()?,
  44. _map_area: cursor.read_u16::<LittleEndian>()?,
  45. _unknown4: cursor.read_u16::<LittleEndian>()?,
  46. _section: cursor.read_u16::<LittleEndian>()?,
  47. _wave_idd: cursor.read_u16::<LittleEndian>()?,
  48. _wave_id: cursor.read_u32::<LittleEndian>()?,
  49. _x: cursor.read_f32::<LittleEndian>()?,
  50. _y: cursor.read_f32::<LittleEndian>()?,
  51. _z: cursor.read_f32::<LittleEndian>()?,
  52. _xrot: cursor.read_u32::<LittleEndian>()?,
  53. _yrot: cursor.read_u32::<LittleEndian>()?,
  54. _zrot: cursor.read_u32::<LittleEndian>()?,
  55. _field1: cursor.read_u32::<LittleEndian>()?,
  56. field2: cursor.read_u32::<LittleEndian>()?,
  57. _field3: cursor.read_u32::<LittleEndian>()?,
  58. _field4: cursor.read_u32::<LittleEndian>()?,
  59. _field5: cursor.read_u32::<LittleEndian>()?,
  60. skin: cursor.read_u32::<LittleEndian>()?,
  61. _field6: cursor.read_u32::<LittleEndian>()?,
  62. })
  63. }
  64. }
  65. pub fn load_rare_monster_file<T: serde::de::DeserializeOwned>(episode: Episode) -> T {
  66. // TODO: where does the rare monster toml file actually live
  67. let mut path = PathBuf::from("data/battle_param/");
  68. path.push(episode.to_string().to_lowercase() + "_rare_monster.toml");
  69. let mut f = File::open(path).unwrap();
  70. let mut s = String::new();
  71. f.read_to_string(&mut s).unwrap();
  72. toml::from_str::<T>(s.as_str()).unwrap()
  73. }
  74. #[derive(Error, Debug)]
  75. #[error("")]
  76. pub enum MapEnemyError {
  77. UnknownEnemyId(u32),
  78. MapAreaError(#[from] MapAreaError),
  79. }
  80. // making this `pub type` doesn't allow `impl`s to be defined?
  81. #[derive(Clone, Debug, Serialize, Deserialize)]
  82. pub struct RareMonsterAppearTable {
  83. pub appear_rate: HashMap<MonsterType, f32>,
  84. }
  85. impl RareMonsterAppearTable {
  86. pub fn new(episode: Episode) -> RareMonsterAppearTable {
  87. let cfg: HashMap<String, f32> = load_rare_monster_file(episode);
  88. let appear_rates: HashMap<MonsterType, f32> = cfg
  89. .into_iter()
  90. .filter_map(|(monster, rate)| {
  91. let monster: MonsterType = monster.parse().ok()?;
  92. Some((monster, rate))
  93. })
  94. .collect();
  95. RareMonsterAppearTable {
  96. appear_rate: appear_rates,
  97. }
  98. }
  99. fn roll_is_rare(&self, monster: &MonsterType) -> bool {
  100. rand_chacha::ChaChaRng::from_entropy().gen::<f32>() < *self.appear_rate.get(monster).unwrap_or(&0.0f32)
  101. }
  102. pub fn apply(&self, enemy: MapEnemy, event: Holiday) -> MapEnemy {
  103. if enemy.can_be_rare() && self.roll_is_rare(&enemy.monster) {
  104. enemy.into_rare(event)
  105. }
  106. else {
  107. enemy
  108. }
  109. }
  110. }
  111. #[derive(Debug, Copy, Clone)]
  112. pub struct MapEnemy {
  113. pub monster: MonsterType,
  114. pub map_area: MapArea,
  115. _hp: u32,
  116. // TODO: other stats from battleparam
  117. pub player_hit: [bool; 4],
  118. pub dropped_item: bool,
  119. pub gave_exp: bool,
  120. pub shiny: bool,
  121. }
  122. impl MapEnemy {
  123. pub fn from_raw(enemy: RawMapEnemy, episode: &Episode, map_area: &MapArea /*, battleparam */) -> Result<MapEnemy, MapEnemyError> {
  124. // TODO: rare enemies ep1-4, tower lilys, event rappies, ult variants?
  125. // TODO: check what "skin" actually does. some unexpected enemies have many (panarms, slimes, lilys)
  126. let monster = match map_area {
  127. MapArea::Forest1 | MapArea::Forest2 | MapArea::Dragon |
  128. MapArea::Caves1 | MapArea::Caves2 | MapArea::Caves3 | MapArea::DeRolLe |
  129. MapArea::Mines1 | MapArea::Mines2 | MapArea::VolOpt |
  130. MapArea::Ruins1 | MapArea::Ruins2 | MapArea::Ruins3 | MapArea::DarkFalz => {
  131. match (enemy, episode) {
  132. (RawMapEnemy {id: 64, skin: 0, ..}, _) => MonsterType::Hildebear,
  133. (RawMapEnemy {id: 64, skin: 1, ..}, _) => MonsterType::Hildeblue,
  134. (RawMapEnemy {id: 65, skin: 0, ..}, _) => MonsterType::RagRappy,
  135. (RawMapEnemy {id: 65, skin: 1, ..}, _) => MonsterType::AlRappy,
  136. (RawMapEnemy {id: 66, ..}, _) => MonsterType::Monest,
  137. (RawMapEnemy {id: 67, field2: 0, ..}, _) => MonsterType::SavageWolf,
  138. (RawMapEnemy {id: 67, ..}, _) => MonsterType::BarbarousWolf,
  139. (RawMapEnemy {id: 68, skin: 0, ..}, _) => MonsterType::Booma,
  140. (RawMapEnemy {id: 68, skin: 1, ..}, _) => MonsterType::Gobooma,
  141. (RawMapEnemy {id: 68, skin: 2, ..}, _) => MonsterType::Gigobooma,
  142. (RawMapEnemy {id: 96, ..}, _) => MonsterType::GrassAssassin,
  143. (RawMapEnemy {id: 97, ..}, _) => MonsterType::PoisonLily,
  144. // (RawMapEnemy {id: 97, skin: 0, ..}, _) => MonsterType::PoisonLily,
  145. // (RawMapEnemy {id: 97, skin: 1, ..}, _) => MonsterType::NarLily,
  146. (RawMapEnemy {id: 98, ..}, _) => MonsterType::NanoDragon,
  147. (RawMapEnemy {id: 99, skin: 0, ..}, _) => MonsterType::EvilShark,
  148. (RawMapEnemy {id: 99, skin: 1, ..}, _) => MonsterType::PalShark,
  149. (RawMapEnemy {id: 99, skin: 2, ..}, _) => MonsterType::GuilShark,
  150. (RawMapEnemy {id: 100, ..}, _) => MonsterType::PofuillySlime,
  151. // (RawMapEnemy {id: 100, skin: 0, ..}, _) => MonsterType::PofuillySlime,
  152. // (RawMapEnemy {id: 100, skin: 1, ..}, _) => MonsterType::PouillySlime,
  153. // (RawMapEnemy {id: 100, skin: 2, ..}, _) => MonsterType::PofuillySlime,
  154. (RawMapEnemy {id: 101, ..}, _) => MonsterType::PanArms,
  155. (RawMapEnemy {id: 128, skin: 0, ..}, _) => MonsterType::Dubchic,
  156. (RawMapEnemy {id: 128, skin: 1, ..}, _) => MonsterType::Gillchic,
  157. (RawMapEnemy {id: 129, ..}, _) => MonsterType::Garanz,
  158. (RawMapEnemy {id: 130, field2: 0, ..}, _) => MonsterType::SinowBeat,
  159. (RawMapEnemy {id: 130, ..}, _) => MonsterType::SinowGold,
  160. (RawMapEnemy {id: 131, ..}, _) => MonsterType::Canadine,
  161. (RawMapEnemy {id: 132, ..}, _) => MonsterType::Canane,
  162. (RawMapEnemy {id: 133, ..}, _) => MonsterType::Dubwitch,
  163. (RawMapEnemy {id: 160, ..}, _) => MonsterType::Delsaber,
  164. (RawMapEnemy {id: 161, ..}, _) => MonsterType::ChaosSorcerer,
  165. (RawMapEnemy {id: 162, ..}, _) => MonsterType::DarkGunner,
  166. (RawMapEnemy {id: 163, ..}, _) => MonsterType::DeathGunner,
  167. (RawMapEnemy {id: 164, ..}, _) => MonsterType::ChaosBringer,
  168. (RawMapEnemy {id: 165, ..}, _) => MonsterType::DarkBelra,
  169. (RawMapEnemy {id: 166, skin: 0, ..}, _) => MonsterType::Dimenian,
  170. (RawMapEnemy {id: 166, skin: 1, ..}, _) => MonsterType::LaDimenian,
  171. (RawMapEnemy {id: 166, skin: 2, ..}, _) => MonsterType::SoDimenian,
  172. (RawMapEnemy {id: 167, ..}, _) => MonsterType::Bulclaw,
  173. (RawMapEnemy {id: 168, ..}, _) => MonsterType::Claw,
  174. (RawMapEnemy {id: 192, ..}, Episode::One) => MonsterType::Dragon,
  175. (RawMapEnemy {id: 193, ..}, _) => MonsterType::DeRolLe,
  176. (RawMapEnemy {id: 194, ..}, _) => MonsterType::VolOptPartA,
  177. (RawMapEnemy {id: 197, ..}, _) => MonsterType::VolOpt,
  178. (RawMapEnemy {id: 200, ..}, _) => MonsterType::DarkFalz,
  179. _ => return Err(MapEnemyError::UnknownEnemyId(enemy.id))
  180. }
  181. },
  182. MapArea::VrTempleAlpha | MapArea::VrTempleBeta | MapArea::BarbaRay |
  183. MapArea::VrSpaceshipAlpha | MapArea::VrSpaceshipBeta | MapArea::GolDragon |
  184. MapArea::JungleAreaNorth | MapArea::JungleAreaEast | MapArea::Mountain | MapArea::Seaside | MapArea::SeasideNight | MapArea::Cca | MapArea::GalGryphon |
  185. MapArea::SeabedUpper | MapArea::SeabedLower | MapArea::OlgaFlow => {
  186. match (enemy, episode) {
  187. (RawMapEnemy {id: 64, skin: 0, ..}, _) => MonsterType::Hildebear,
  188. (RawMapEnemy {id: 64, skin: 1, ..}, _) => MonsterType::Hildeblue,
  189. (RawMapEnemy {id: 65, skin: 0, ..}, _) => MonsterType::RagRappy,
  190. (RawMapEnemy {id: 65, skin: 1, ..}, _) => MonsterType::EventRappy,
  191. (RawMapEnemy {id: 66, ..}, _) => MonsterType::Monest,
  192. (RawMapEnemy {id: 67, field2: 0, ..}, _) => MonsterType::SavageWolf,
  193. (RawMapEnemy {id: 67, ..}, _) => MonsterType::BarbarousWolf,
  194. (RawMapEnemy {id: 96, ..}, _) => MonsterType::GrassAssassin,
  195. (RawMapEnemy {id: 97, skin: 0, ..}, _) => MonsterType::PoisonLily,
  196. (RawMapEnemy {id: 97, skin: 1, ..}, _) => MonsterType::NarLily,
  197. (RawMapEnemy {id: 101, ..}, _) => MonsterType::PanArms,
  198. (RawMapEnemy {id: 128, skin: 0, ..}, _) => MonsterType::Dubchic,
  199. (RawMapEnemy {id: 128, skin: 1, ..}, _) => MonsterType::Gillchic,
  200. (RawMapEnemy {id: 129, ..}, _) => MonsterType::Garanz,
  201. (RawMapEnemy {id: 133, ..}, _) => MonsterType::Dubwitch,
  202. (RawMapEnemy {id: 160, ..}, _) => MonsterType::Delsaber,
  203. (RawMapEnemy {id: 161, ..}, _) => MonsterType::ChaosSorcerer,
  204. (RawMapEnemy {id: 165, ..}, _) => MonsterType::DarkBelra,
  205. (RawMapEnemy {id: 166, skin: 0, ..}, _) => MonsterType::Dimenian,
  206. (RawMapEnemy {id: 166, skin: 1, ..}, _) => MonsterType::LaDimenian,
  207. (RawMapEnemy {id: 166, skin: 2, ..}, _) => MonsterType::SoDimenian,
  208. (RawMapEnemy {id: 192, ..}, Episode::Two) => MonsterType::GalGryphon,
  209. (RawMapEnemy {id: 202, ..}, _) => MonsterType::OlgaFlow,
  210. (RawMapEnemy {id: 203, ..}, _) => MonsterType::BarbaRay,
  211. (RawMapEnemy {id: 204, ..}, _) => MonsterType::GolDragon,
  212. (RawMapEnemy {id: 212, skin: 0, ..}, _) => MonsterType::SinowBerill,
  213. (RawMapEnemy {id: 212, skin: 1, ..}, _) => MonsterType::SinowSpigell,
  214. (RawMapEnemy {id: 213, skin: 0, ..}, _) => MonsterType::Merillia,
  215. (RawMapEnemy {id: 213, skin: 1, ..}, _) => MonsterType::Meriltas,
  216. (RawMapEnemy {id: 214, skin: 0, ..}, _) => MonsterType::Mericarol,
  217. (RawMapEnemy {id: 214, skin: 1, ..}, _) => MonsterType::Merikle,
  218. (RawMapEnemy {id: 214, skin: 2, ..}, _) => MonsterType::Mericus,
  219. (RawMapEnemy {id: 215, skin: 0, ..}, _) => MonsterType::UlGibbon,
  220. (RawMapEnemy {id: 215, skin: 1, ..}, _) => MonsterType::ZolGibbon,
  221. (RawMapEnemy {id: 216, ..}, _) => MonsterType::Gibbles,
  222. (RawMapEnemy {id: 217, ..}, _) => MonsterType::Gee,
  223. (RawMapEnemy {id: 218, ..}, _) => MonsterType::GiGue,
  224. (RawMapEnemy {id: 219, ..}, _) => MonsterType::Deldepth,
  225. (RawMapEnemy {id: 220, ..}, _) => MonsterType::Delbiter,
  226. (RawMapEnemy {id: 221, skin: 0, ..}, _) => MonsterType::Dolmolm,
  227. (RawMapEnemy {id: 221, skin: 1, ..}, _) => MonsterType::Dolmdarl,
  228. (RawMapEnemy {id: 222, ..}, _) => MonsterType::Morfos,
  229. (RawMapEnemy {id: 223, ..}, _) => MonsterType::Recobox,
  230. (RawMapEnemy {id: 224, skin: 0, ..}, _) => MonsterType::SinowZoa,
  231. (RawMapEnemy {id: 224, skin: 1, ..}, _) => MonsterType::SinowZele,
  232. (RawMapEnemy {id: 224, ..}, _) => MonsterType::Epsilon,
  233. (RawMapEnemy {id: 225, ..}, _) => MonsterType::IllGill,
  234. _ => return Err(MapEnemyError::UnknownEnemyId(enemy.id))
  235. }
  236. },
  237. MapArea::Tower => {
  238. match (enemy, episode) {
  239. (RawMapEnemy {id: 97, ..}, _) => MonsterType::DelLily,
  240. (RawMapEnemy {id: 214, skin: 0, ..}, _) => MonsterType::Mericarol,
  241. (RawMapEnemy {id: 214, skin: 1, ..}, _) => MonsterType::Merikle,
  242. (RawMapEnemy {id: 214, skin: 2, ..}, _) => MonsterType::Mericus,
  243. (RawMapEnemy {id: 216, ..}, _) => MonsterType::Gibbles,
  244. (RawMapEnemy {id: 218, ..}, _) => MonsterType::GiGue,
  245. (RawMapEnemy {id: 220, ..}, _) => MonsterType::Delbiter,
  246. (RawMapEnemy {id: 223, ..}, _) => MonsterType::Recobox,
  247. (RawMapEnemy {id: 224, ..}, _) => MonsterType::Epsilon,
  248. (RawMapEnemy {id: 225, ..}, _) => MonsterType::IllGill,
  249. _ => return Err(MapEnemyError::UnknownEnemyId(enemy.id))
  250. }
  251. },
  252. MapArea::CraterEast | MapArea::CraterWest | MapArea::CraterSouth | MapArea::CraterNorth | MapArea::CraterInterior => {
  253. match (enemy, episode) {
  254. (RawMapEnemy {id: 65, skin: 0, ..}, Episode::Four) => MonsterType::SandRappyCrater,
  255. (RawMapEnemy {id: 65, skin: 1, ..}, Episode::Four) => MonsterType::DelRappyCrater,
  256. (RawMapEnemy {id: 272, ..}, _) => MonsterType::Astark,
  257. (RawMapEnemy {id: 273, field2: 0, ..}, _) => MonsterType::SatelliteLizardCrater,
  258. (RawMapEnemy {id: 273, ..}, _) => MonsterType::YowieCrater,
  259. (RawMapEnemy {id: 276, skin: 0, ..}, _) => MonsterType::ZuCrater,
  260. (RawMapEnemy {id: 276, skin: 1, ..}, _) => MonsterType::PazuzuCrater,
  261. (RawMapEnemy {id: 277, skin: 0, ..}, _) => MonsterType::Boota,
  262. (RawMapEnemy {id: 277, skin: 1, ..}, _) => MonsterType::ZeBoota,
  263. (RawMapEnemy {id: 277, skin: 2, ..}, _) => MonsterType::BaBoota,
  264. (RawMapEnemy {id: 278, skin: 0, ..}, _) => MonsterType::Dorphon,
  265. (RawMapEnemy {id: 278, skin: 1, ..}, _) => MonsterType::DorphonEclair,
  266. _ => return Err(MapEnemyError::UnknownEnemyId(enemy.id))
  267. }
  268. },
  269. MapArea::SubDesert1 | MapArea::SubDesert2 | MapArea::SubDesert3 | MapArea::SaintMillion => {
  270. match (enemy, episode) {
  271. (RawMapEnemy {id: 65, skin: 0, ..}, Episode::Four) => MonsterType::SandRappyDesert,
  272. (RawMapEnemy {id: 65, skin: 1, ..}, Episode::Four) => MonsterType::DelRappyDesert,
  273. (RawMapEnemy {id: 273, field2: 0, ..}, _) => MonsterType::SatelliteLizardDesert,
  274. (RawMapEnemy {id: 273, ..}, _) => MonsterType::YowieDesert,
  275. (RawMapEnemy {id: 274, skin: 0, ..}, _) => MonsterType::MerissaA,
  276. (RawMapEnemy {id: 274, skin: 1, ..}, _) => MonsterType::MerissaAA,
  277. (RawMapEnemy {id: 275, ..}, _) => MonsterType::Girtablulu,
  278. (RawMapEnemy {id: 276, skin: 0, ..}, _) => MonsterType::ZuDesert,
  279. (RawMapEnemy {id: 276, skin: 1, ..}, _) => MonsterType::PazuzuDesert,
  280. (RawMapEnemy {id: 279, skin: 0, ..}, _) => MonsterType::Goran,
  281. (RawMapEnemy {id: 279, skin: 1, ..}, _) => MonsterType::PyroGoran,
  282. (RawMapEnemy {id: 279, skin: 2, ..}, _) => MonsterType::GoranDetonator,
  283. (RawMapEnemy {id: 281, skin: 0, ..}, _) => MonsterType::SaintMillion,
  284. (RawMapEnemy {id: 281, skin: 1, ..}, _) => MonsterType::Shambertin, // TODO: don't guess the skin
  285. (RawMapEnemy {id: 281, skin: 2, ..}, _) => MonsterType::Kondrieu, // TODO: don't guess the skin
  286. _ => return Err(MapEnemyError::UnknownEnemyId(enemy.id))
  287. }
  288. },
  289. _ => return Err(MapEnemyError::UnknownEnemyId(enemy.id))
  290. };
  291. Ok(MapEnemy {
  292. monster,
  293. map_area: *map_area,
  294. _hp: 0,
  295. dropped_item: false,
  296. gave_exp: false,
  297. player_hit: [false; 4],
  298. shiny: false,
  299. })
  300. }
  301. pub fn new(monster: MonsterType, map_area: MapArea) -> MapEnemy {
  302. MapEnemy {
  303. monster,
  304. map_area,
  305. _hp: 0,
  306. dropped_item: false,
  307. gave_exp: false,
  308. player_hit: [false; 4],
  309. shiny: false,
  310. }
  311. }
  312. #[must_use]
  313. pub fn set_shiny(self) -> MapEnemy {
  314. MapEnemy {
  315. shiny: true,
  316. ..self
  317. }
  318. }
  319. pub fn can_be_rare(&self) -> bool {
  320. matches!(self.monster,
  321. MonsterType::RagRappy | MonsterType::Hildebear |
  322. MonsterType::PoisonLily | MonsterType::PofuillySlime |
  323. MonsterType::SandRappyCrater | MonsterType::ZuCrater | MonsterType::Dorphon |
  324. MonsterType::SandRappyDesert | MonsterType::ZuDesert | MonsterType::MerissaA |
  325. MonsterType::SaintMillion | MonsterType::Shambertin
  326. )
  327. }
  328. /*
  329. TODO: distinguish between a `random` rare monster and a `set/guaranteed` rare monster? (does any acceptable quest even have this?)
  330. guaranteed rare monsters don't count towards the limit
  331. */
  332. #[must_use]
  333. pub fn into_rare(self, event: Holiday) -> MapEnemy {
  334. match (self.monster, self.map_area.to_episode(), event) {
  335. (MonsterType::RagRappy, Episode::One, _) => {MapEnemy {monster: MonsterType::AlRappy, shiny:true, ..self}},
  336. (MonsterType::RagRappy, Episode::Two, Holiday::Easter) => {MapEnemy {monster: MonsterType::EasterRappy, shiny:true, ..self}},
  337. (MonsterType::RagRappy, Episode::Two, Holiday::Halloween) => {MapEnemy {monster: MonsterType::HalloRappy, shiny:true, ..self}},
  338. (MonsterType::RagRappy, Episode::Two, Holiday::Christmas) => {MapEnemy {monster: MonsterType::StRappy, shiny:true, ..self}},
  339. (MonsterType::RagRappy, Episode::Two, _) => {MapEnemy {monster: MonsterType::LoveRappy, shiny:true, ..self}},
  340. (MonsterType::Hildebear, _, _) => {MapEnemy {monster: MonsterType::Hildeblue, shiny:true, ..self}},
  341. (MonsterType::PoisonLily, _, _) => {MapEnemy {monster: MonsterType::NarLily, shiny:true, ..self}},
  342. (MonsterType::PofuillySlime, _, _) => {MapEnemy {monster: MonsterType::PouillySlime, shiny:true, ..self}},
  343. (MonsterType::SandRappyCrater, _, _) => {MapEnemy {monster: MonsterType::DelRappyCrater, shiny:true, ..self}},
  344. (MonsterType::ZuCrater, _, _) => {MapEnemy {monster: MonsterType::PazuzuCrater, shiny:true, ..self}},
  345. (MonsterType::Dorphon, _, _) => {MapEnemy {monster: MonsterType::DorphonEclair, shiny:true, ..self}},
  346. (MonsterType::SandRappyDesert, _, _) => {MapEnemy {monster: MonsterType::DelRappyDesert, shiny:true, ..self}},
  347. (MonsterType::ZuDesert, _, _) => {MapEnemy {monster: MonsterType::PazuzuDesert, shiny:true, ..self}},
  348. (MonsterType::MerissaA, _, _) => {MapEnemy {monster: MonsterType::MerissaAA, shiny:true, ..self}},
  349. (MonsterType::SaintMillion, _, _) => {MapEnemy {monster: MonsterType::Kondrieu, shiny:true, ..self}},
  350. (MonsterType::Shambertin, _, _) => {MapEnemy {monster: MonsterType::Kondrieu, shiny:true, ..self}},
  351. _ => {self},
  352. }
  353. }
  354. }