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.

353 lines
12 KiB

  1. // TOOD: `pub(super) for most of these?`
  2. use serde::{Serialize, Deserialize};
  3. use std::collections::HashMap;
  4. use thiserror::Error;
  5. use crate::ship::room::Episode;
  6. #[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
  7. pub enum MapArea {
  8. Pioneer2Ep1,
  9. Forest1,
  10. Forest2,
  11. Caves1,
  12. Caves2,
  13. Caves3,
  14. Mines1,
  15. Mines2,
  16. Ruins1,
  17. Ruins2,
  18. Ruins3,
  19. Dragon,
  20. DeRolLe,
  21. VolOpt,
  22. DarkFalz,
  23. Pioneer2Ep2,
  24. VrTempleAlpha,
  25. VrTempleBeta,
  26. VrSpaceshipAlpha,
  27. VrSpaceshipBeta,
  28. Cca,
  29. JungleAreaNorth,
  30. JungleAreaEast,
  31. Mountain,
  32. Seaside,
  33. SeabedUpper,
  34. SeabedLower,
  35. GalGryphon,
  36. OlgaFlow,
  37. BarbaRay,
  38. GolDragon,
  39. SeasideNight,
  40. Tower,
  41. Pioneer2Ep4,
  42. CraterEast,
  43. CraterWest,
  44. CraterSouth,
  45. CraterNorth,
  46. CraterInterior,
  47. SubDesert1,
  48. SubDesert2,
  49. SubDesert3,
  50. SaintMillion,
  51. // TestMapEp4,
  52. }
  53. #[derive(Error, Debug)]
  54. #[error("")]
  55. pub enum MapAreaError {
  56. UnknownMapArea(u16),
  57. }
  58. impl MapArea {
  59. pub fn from_bb_map_designate(map_number: u8) -> Option<MapArea> {
  60. match map_number {
  61. 0 => Some(MapArea::Pioneer2Ep1),
  62. 1 => Some(MapArea::Forest1),
  63. 2 => Some(MapArea::Forest2),
  64. 3 => Some(MapArea::Caves1),
  65. 4 => Some(MapArea::Caves2),
  66. 5 => Some(MapArea::Caves3),
  67. 6 => Some(MapArea::Mines1),
  68. 7 => Some(MapArea::Mines2),
  69. 8 => Some(MapArea::Ruins1),
  70. 9 => Some(MapArea::Ruins2),
  71. 10 => Some(MapArea::Ruins3),
  72. 11 => Some(MapArea::Dragon),
  73. 12 => Some(MapArea::DeRolLe),
  74. 13 => Some(MapArea::VolOpt),
  75. 14 => Some(MapArea::DarkFalz),
  76. 18 => Some(MapArea::Pioneer2Ep2),
  77. 19 => Some(MapArea::VrTempleAlpha),
  78. 20 => Some(MapArea::VrTempleBeta),
  79. 21 => Some(MapArea::VrSpaceshipAlpha),
  80. 22 => Some(MapArea::VrSpaceshipBeta),
  81. 23 => Some(MapArea::Cca),
  82. 24 => Some(MapArea::JungleAreaNorth),
  83. 25 => Some(MapArea::JungleAreaEast),
  84. 26 => Some(MapArea::Mountain),
  85. 27 => Some(MapArea::Seaside),
  86. 28 => Some(MapArea::SeabedUpper),
  87. 29 => Some(MapArea::SeabedLower),
  88. 30 => Some(MapArea::GalGryphon),
  89. 31 => Some(MapArea::OlgaFlow),
  90. 32 => Some(MapArea::BarbaRay),
  91. 33 => Some(MapArea::GolDragon),
  92. 34 => Some(MapArea::SeasideNight),
  93. 35 => Some(MapArea::Tower),
  94. 45 => Some(MapArea::Pioneer2Ep4),
  95. 36 => Some(MapArea::CraterEast),
  96. 37 => Some(MapArea::CraterWest),
  97. 38 => Some(MapArea::CraterSouth),
  98. 39 => Some(MapArea::CraterNorth),
  99. 40 => Some(MapArea::CraterInterior),
  100. 41 => Some(MapArea::SubDesert1),
  101. 42 => Some(MapArea::SubDesert2),
  102. 43 => Some(MapArea::SubDesert3),
  103. 44 => Some(MapArea::SaintMillion),
  104. _=> None
  105. }
  106. }
  107. pub fn drop_area_value(&self) -> Option<u32> {
  108. match self {
  109. MapArea::Forest1 => Some(0),
  110. MapArea::Forest2 => Some(1),
  111. MapArea::Caves1 => Some(2),
  112. MapArea::Caves2 => Some(3),
  113. MapArea::Caves3 => Some(4),
  114. MapArea::Mines1 => Some(5),
  115. MapArea::Mines2 => Some(6),
  116. MapArea::Ruins1 => Some(7),
  117. MapArea::Ruins2 => Some(8),
  118. MapArea::Ruins3 => Some(9),
  119. MapArea::Dragon => Some(2),
  120. MapArea::DeRolLe => Some(5),
  121. MapArea::VolOpt => Some(7),
  122. MapArea::DarkFalz => Some(9),
  123. MapArea::VrTempleAlpha => Some(0),
  124. MapArea::VrTempleBeta => Some(1),
  125. MapArea::VrSpaceshipAlpha => Some(2),
  126. MapArea::VrSpaceshipBeta => Some(3),
  127. MapArea::Cca => Some(4),
  128. MapArea::JungleAreaNorth => Some(5),
  129. MapArea::JungleAreaEast => Some(5),
  130. MapArea::Mountain => Some(6),
  131. MapArea::Seaside => Some(7),
  132. MapArea::SeabedUpper => Some(8),
  133. MapArea::SeabedLower => Some(9),
  134. MapArea::GalGryphon => Some(8),
  135. MapArea::OlgaFlow => Some(9),
  136. MapArea::BarbaRay => Some(2),
  137. MapArea::GolDragon => Some(5),
  138. MapArea::SeasideNight => Some(7), // TODO: this could also be 9? needs research
  139. MapArea::Tower => Some(9),
  140. MapArea::CraterEast => Some(2),
  141. MapArea::CraterWest => Some(3),
  142. MapArea::CraterSouth => Some(4),
  143. MapArea::CraterNorth => Some(5),
  144. MapArea::CraterInterior => Some(6),
  145. MapArea::SubDesert1 => Some(7),
  146. MapArea::SubDesert2 => Some(8),
  147. MapArea::SubDesert3 => Some(9),
  148. MapArea::SaintMillion => Some(9),
  149. // MapArea::TestMapEp4 => Some(0),
  150. _ => None
  151. }
  152. }
  153. pub fn area_value(&self) -> u8 {
  154. match self {
  155. MapArea::Pioneer2Ep1 => 0,
  156. MapArea::Forest1 => 1,
  157. MapArea::Forest2 => 2,
  158. MapArea::Caves1 => 3,
  159. MapArea::Caves2 => 4,
  160. MapArea::Caves3 => 5,
  161. MapArea::Mines1 => 6,
  162. MapArea::Mines2 => 7,
  163. MapArea::Ruins1 => 8,
  164. MapArea::Ruins2 => 9,
  165. MapArea::Ruins3 => 10,
  166. MapArea::Dragon => 11,
  167. MapArea::DeRolLe => 12,
  168. MapArea::VolOpt => 13,
  169. MapArea::DarkFalz => 14,
  170. MapArea::Pioneer2Ep2 => 0,
  171. MapArea::VrTempleAlpha => 1,
  172. MapArea::VrTempleBeta => 2,
  173. MapArea::VrSpaceshipAlpha => 3,
  174. MapArea::VrSpaceshipBeta => 4,
  175. MapArea::Cca => 5,
  176. MapArea::JungleAreaNorth => 6,
  177. MapArea::JungleAreaEast => 7,
  178. MapArea::Mountain => 8,
  179. MapArea::Seaside => 9,
  180. MapArea::SeabedUpper => 10,
  181. MapArea::SeabedLower => 11,
  182. MapArea::GalGryphon => 12,
  183. MapArea::OlgaFlow => 13,
  184. MapArea::BarbaRay => 14,
  185. MapArea::GolDragon => 15,
  186. MapArea::SeasideNight => 16,
  187. MapArea::Tower => 17,
  188. MapArea::Pioneer2Ep4 => 0,
  189. MapArea::CraterEast => 1,
  190. MapArea::CraterWest => 2,
  191. MapArea::CraterSouth => 3,
  192. MapArea::CraterNorth => 4,
  193. MapArea::CraterInterior => 5,
  194. MapArea::SubDesert1 => 6,
  195. MapArea::SubDesert2 => 7,
  196. MapArea::SubDesert3 => 8,
  197. MapArea::SaintMillion => 9,
  198. // MapArea::TestMapEp4 => 10,
  199. }
  200. }
  201. pub fn to_episode(self) -> Episode {
  202. match self {
  203. MapArea::Pioneer2Ep1 => Episode::One,
  204. MapArea::Forest1 => Episode::One,
  205. MapArea::Forest2 => Episode::One,
  206. MapArea::Caves1 => Episode::One,
  207. MapArea::Caves2 => Episode::One,
  208. MapArea::Caves3 => Episode::One,
  209. MapArea::Mines1 => Episode::One,
  210. MapArea::Mines2 => Episode::One,
  211. MapArea::Ruins1 => Episode::One,
  212. MapArea::Ruins2 => Episode::One,
  213. MapArea::Ruins3 => Episode::One,
  214. MapArea::Dragon => Episode::One,
  215. MapArea::DeRolLe => Episode::One,
  216. MapArea::VolOpt => Episode::One,
  217. MapArea::DarkFalz => Episode::One,
  218. MapArea::Pioneer2Ep2 => Episode::Two,
  219. MapArea::VrTempleAlpha => Episode::Two,
  220. MapArea::VrTempleBeta => Episode::Two,
  221. MapArea::VrSpaceshipAlpha => Episode::Two,
  222. MapArea::VrSpaceshipBeta => Episode::Two,
  223. MapArea::Cca => Episode::Two,
  224. MapArea::JungleAreaNorth => Episode::Two,
  225. MapArea::JungleAreaEast => Episode::Two,
  226. MapArea::Mountain => Episode::Two,
  227. MapArea::Seaside => Episode::Two,
  228. MapArea::SeabedUpper => Episode::Two,
  229. MapArea::SeabedLower => Episode::Two,
  230. MapArea::GalGryphon => Episode::Two,
  231. MapArea::OlgaFlow => Episode::Two,
  232. MapArea::BarbaRay => Episode::Two,
  233. MapArea::GolDragon => Episode::Two,
  234. MapArea::SeasideNight => Episode::Two,
  235. MapArea::Tower => Episode::Two,
  236. MapArea::Pioneer2Ep4 => Episode::Four,
  237. MapArea::CraterEast => Episode::Four,
  238. MapArea::CraterWest => Episode::Four,
  239. MapArea::CraterSouth => Episode::Four,
  240. MapArea::CraterNorth => Episode::Four,
  241. MapArea::CraterInterior => Episode::Four,
  242. MapArea::SubDesert1 => Episode::Four,
  243. MapArea::SubDesert2 => Episode::Four,
  244. MapArea::SubDesert3 => Episode::Four,
  245. MapArea::SaintMillion => Episode::Four,
  246. }
  247. }
  248. }
  249. #[derive(Debug, Clone)]
  250. pub struct MapAreaLookup(HashMap<u16, MapArea>);
  251. impl MapAreaLookup {
  252. pub fn get_area_map(&self, map_area: u16) -> Result<&MapArea, MapAreaError> {
  253. self.0.get(&map_area).ok_or(MapAreaError::UnknownMapArea(map_area))
  254. }
  255. fn default_ep1_maps() -> MapAreaLookup {
  256. let mut ep1 = HashMap::new();
  257. ep1.insert(0, MapArea::Pioneer2Ep1);
  258. ep1.insert(1, MapArea::Forest1);
  259. ep1.insert(2, MapArea::Forest2);
  260. ep1.insert(3, MapArea::Caves1);
  261. ep1.insert(4, MapArea::Caves2);
  262. ep1.insert(5, MapArea::Caves3);
  263. ep1.insert(6, MapArea::Mines1);
  264. ep1.insert(7, MapArea::Mines2);
  265. ep1.insert(8, MapArea::Ruins1);
  266. ep1.insert(9, MapArea::Ruins2);
  267. ep1.insert(10, MapArea::Ruins3);
  268. ep1.insert(11, MapArea::Dragon);
  269. ep1.insert(12, MapArea::DeRolLe);
  270. ep1.insert(13, MapArea::VolOpt);
  271. ep1.insert(14, MapArea::DarkFalz);
  272. MapAreaLookup(ep1)
  273. }
  274. fn default_ep2_maps() -> MapAreaLookup {
  275. let mut ep2 = HashMap::new();
  276. ep2.insert(0, MapArea::Pioneer2Ep2);
  277. ep2.insert(1, MapArea::VrTempleAlpha);
  278. ep2.insert(2, MapArea::VrTempleBeta);
  279. ep2.insert(3, MapArea::VrSpaceshipAlpha);
  280. ep2.insert(4, MapArea::VrSpaceshipBeta);
  281. ep2.insert(5, MapArea::Cca);
  282. ep2.insert(6, MapArea::JungleAreaNorth);
  283. ep2.insert(7, MapArea::JungleAreaEast);
  284. ep2.insert(8, MapArea::Mountain);
  285. ep2.insert(9, MapArea::Seaside);
  286. ep2.insert(10, MapArea::SeabedUpper);
  287. ep2.insert(11, MapArea::SeabedLower);
  288. ep2.insert(12, MapArea::GalGryphon);
  289. ep2.insert(13, MapArea::OlgaFlow);
  290. ep2.insert(14, MapArea::BarbaRay);
  291. ep2.insert(15, MapArea::GolDragon);
  292. ep2.insert(16, MapArea::SeasideNight);
  293. ep2.insert(17, MapArea::Tower);
  294. MapAreaLookup(ep2)
  295. }
  296. fn default_ep4_maps() -> MapAreaLookup {
  297. let mut ep4 = HashMap::new();
  298. ep4.insert(0, MapArea::Pioneer2Ep4);
  299. ep4.insert(1, MapArea::CraterEast);
  300. ep4.insert(2, MapArea::CraterWest);
  301. ep4.insert(3, MapArea::CraterSouth);
  302. ep4.insert(4, MapArea::CraterNorth);
  303. ep4.insert(5, MapArea::CraterInterior);
  304. ep4.insert(6, MapArea::SubDesert1);
  305. ep4.insert(7, MapArea::SubDesert2);
  306. ep4.insert(8, MapArea::SubDesert3);
  307. ep4.insert(9, MapArea::SaintMillion);
  308. MapAreaLookup(ep4)
  309. }
  310. pub fn new(episode: &Episode) -> MapAreaLookup {
  311. match episode {
  312. Episode::One => MapAreaLookup::default_ep1_maps(),
  313. Episode::Two => MapAreaLookup::default_ep2_maps(),
  314. Episode::Four => MapAreaLookup::default_ep4_maps(),
  315. }
  316. }
  317. }
  318. #[derive(Default)]
  319. pub struct MapAreaLookupBuilder {
  320. map_areas: HashMap<u16, MapArea>,
  321. }
  322. impl MapAreaLookupBuilder {
  323. #[must_use]
  324. pub fn add(mut self, value: u16, map_area: MapArea) -> MapAreaLookupBuilder {
  325. self.map_areas.insert(value, map_area);
  326. self
  327. }
  328. pub fn build(self) -> MapAreaLookup {
  329. MapAreaLookup(self.map_areas)
  330. }
  331. }