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.

319 lines
10 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. }
  202. #[derive(Debug, Clone)]
  203. pub struct MapAreaLookup(HashMap<u16, MapArea>);
  204. impl MapAreaLookup {
  205. pub fn get_area_map(&self, map_area: u16) -> Result<&MapArea, MapAreaError> {
  206. self.0.get(&map_area).ok_or(MapAreaError::UnknownMapArea(map_area))
  207. }
  208. fn default_ep1_maps() -> MapAreaLookup {
  209. let mut ep1 = HashMap::new();
  210. ep1.insert(0, MapArea::Pioneer2Ep1);
  211. ep1.insert(1, MapArea::Forest1);
  212. ep1.insert(2, MapArea::Forest2);
  213. ep1.insert(3, MapArea::Caves1);
  214. ep1.insert(4, MapArea::Caves2);
  215. ep1.insert(5, MapArea::Caves3);
  216. ep1.insert(6, MapArea::Mines1);
  217. ep1.insert(7, MapArea::Mines2);
  218. ep1.insert(8, MapArea::Ruins1);
  219. ep1.insert(9, MapArea::Ruins2);
  220. ep1.insert(10, MapArea::Ruins3);
  221. ep1.insert(11, MapArea::Dragon);
  222. ep1.insert(12, MapArea::DeRolLe);
  223. ep1.insert(13, MapArea::VolOpt);
  224. ep1.insert(14, MapArea::DarkFalz);
  225. MapAreaLookup(ep1)
  226. }
  227. fn default_ep2_maps() -> MapAreaLookup {
  228. let mut ep2 = HashMap::new();
  229. ep2.insert(0, MapArea::Pioneer2Ep2);
  230. ep2.insert(1, MapArea::VrTempleAlpha);
  231. ep2.insert(2, MapArea::VrTempleBeta);
  232. ep2.insert(3, MapArea::VrSpaceshipAlpha);
  233. ep2.insert(4, MapArea::VrSpaceshipBeta);
  234. ep2.insert(5, MapArea::Cca);
  235. ep2.insert(6, MapArea::JungleAreaNorth);
  236. ep2.insert(7, MapArea::JungleAreaEast);
  237. ep2.insert(8, MapArea::Mountain);
  238. ep2.insert(9, MapArea::Seaside);
  239. ep2.insert(10, MapArea::SeabedUpper);
  240. ep2.insert(11, MapArea::SeabedLower);
  241. ep2.insert(12, MapArea::GalGryphon);
  242. ep2.insert(13, MapArea::OlgaFlow);
  243. ep2.insert(14, MapArea::BarbaRay);
  244. ep2.insert(15, MapArea::GolDragon);
  245. ep2.insert(16, MapArea::SeasideNight);
  246. ep2.insert(17, MapArea::Tower);
  247. MapAreaLookup(ep2)
  248. }
  249. fn default_ep4_maps() -> MapAreaLookup {
  250. let mut ep4 = HashMap::new();
  251. ep4.insert(0, MapArea::Pioneer2Ep4);
  252. ep4.insert(1, MapArea::CraterEast);
  253. ep4.insert(2, MapArea::CraterWest);
  254. ep4.insert(3, MapArea::CraterSouth);
  255. ep4.insert(4, MapArea::CraterNorth);
  256. ep4.insert(5, MapArea::CraterInterior);
  257. ep4.insert(6, MapArea::SubDesert1);
  258. ep4.insert(7, MapArea::SubDesert2);
  259. ep4.insert(8, MapArea::SubDesert3);
  260. ep4.insert(9, MapArea::SaintMillion);
  261. MapAreaLookup(ep4)
  262. }
  263. pub fn new(episode: &Episode) -> MapAreaLookup {
  264. match episode {
  265. Episode::One => MapAreaLookup::default_ep1_maps(),
  266. Episode::Two => MapAreaLookup::default_ep2_maps(),
  267. Episode::Four => MapAreaLookup::default_ep4_maps(),
  268. }
  269. }
  270. pub fn from_changed_floor(&self, floor: u8) -> Option<MapArea> {
  271. match floor {
  272. 20 => Some(MapArea::Forest1),
  273. 30 => Some(MapArea::Caves1),
  274. 40 => Some(MapArea::Mines1),
  275. 48 => Some(MapArea::Ruins1),
  276. _ => None,
  277. }
  278. }
  279. }
  280. pub struct MapAreaLookupBuilder {
  281. map_areas: HashMap<u16, MapArea>,
  282. }
  283. impl MapAreaLookupBuilder {
  284. pub fn new() -> MapAreaLookupBuilder {
  285. MapAreaLookupBuilder {
  286. map_areas: HashMap::new()
  287. }
  288. }
  289. pub fn add(mut self, value: u16, map_area: MapArea) -> MapAreaLookupBuilder {
  290. self.map_areas.insert(value, map_area);
  291. self
  292. }
  293. pub fn build(self) -> MapAreaLookup {
  294. MapAreaLookup(self.map_areas)
  295. }
  296. }