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

// TOOD: `pub(super) for most of these?`
use serde::{Serialize, Deserialize};
use std::collections::HashMap;
use thiserror::Error;
use crate::ship::room::Episode;
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
pub enum MapArea {
Pioneer2Ep1,
Forest1,
Forest2,
Caves1,
Caves2,
Caves3,
Mines1,
Mines2,
Ruins1,
Ruins2,
Ruins3,
Dragon,
DeRolLe,
VolOpt,
DarkFalz,
Pioneer2Ep2,
VrTempleAlpha,
VrTempleBeta,
VrSpaceshipAlpha,
VrSpaceshipBeta,
Cca,
JungleAreaNorth,
JungleAreaEast,
Mountain,
Seaside,
SeabedUpper,
SeabedLower,
GalGryphon,
OlgaFlow,
BarbaRay,
GolDragon,
SeasideNight,
Tower,
Pioneer2Ep4,
CraterEast,
CraterWest,
CraterSouth,
CraterNorth,
CraterInterior,
SubDesert1,
SubDesert2,
SubDesert3,
SaintMillion,
// TestMapEp4,
}
#[derive(Error, Debug)]
#[error("")]
pub enum MapAreaError {
UnknownMapArea(u16),
}
impl MapArea {
pub fn from_bb_map_designate(map_number: u8) -> Option<MapArea> {
match map_number {
0 => Some(MapArea::Pioneer2Ep1),
1 => Some(MapArea::Forest1),
2 => Some(MapArea::Forest2),
3 => Some(MapArea::Caves1),
4 => Some(MapArea::Caves2),
5 => Some(MapArea::Caves3),
6 => Some(MapArea::Mines1),
7 => Some(MapArea::Mines2),
8 => Some(MapArea::Ruins1),
9 => Some(MapArea::Ruins2),
10 => Some(MapArea::Ruins3),
11 => Some(MapArea::Dragon),
12 => Some(MapArea::DeRolLe),
13 => Some(MapArea::VolOpt),
14 => Some(MapArea::DarkFalz),
18 => Some(MapArea::Pioneer2Ep2),
19 => Some(MapArea::VrTempleAlpha),
20 => Some(MapArea::VrTempleBeta),
21 => Some(MapArea::VrSpaceshipAlpha),
22 => Some(MapArea::VrSpaceshipBeta),
23 => Some(MapArea::Cca),
24 => Some(MapArea::JungleAreaNorth),
25 => Some(MapArea::JungleAreaEast),
26 => Some(MapArea::Mountain),
27 => Some(MapArea::Seaside),
28 => Some(MapArea::SeabedUpper),
29 => Some(MapArea::SeabedLower),
30 => Some(MapArea::GalGryphon),
31 => Some(MapArea::OlgaFlow),
32 => Some(MapArea::BarbaRay),
33 => Some(MapArea::GolDragon),
34 => Some(MapArea::SeasideNight),
35 => Some(MapArea::Tower),
45 => Some(MapArea::Pioneer2Ep4),
36 => Some(MapArea::CraterEast),
37 => Some(MapArea::CraterWest),
38 => Some(MapArea::CraterSouth),
39 => Some(MapArea::CraterNorth),
40 => Some(MapArea::CraterInterior),
41 => Some(MapArea::SubDesert1),
42 => Some(MapArea::SubDesert2),
43 => Some(MapArea::SubDesert3),
44 => Some(MapArea::SaintMillion),
_=> None
}
}
pub fn drop_area_value(&self) -> Option<u32> {
match self {
MapArea::Forest1 => Some(0),
MapArea::Forest2 => Some(1),
MapArea::Caves1 => Some(2),
MapArea::Caves2 => Some(3),
MapArea::Caves3 => Some(4),
MapArea::Mines1 => Some(5),
MapArea::Mines2 => Some(6),
MapArea::Ruins1 => Some(7),
MapArea::Ruins2 => Some(8),
MapArea::Ruins3 => Some(9),
MapArea::Dragon => Some(2),
MapArea::DeRolLe => Some(5),
MapArea::VolOpt => Some(7),
MapArea::DarkFalz => Some(9),
MapArea::VrTempleAlpha => Some(0),
MapArea::VrTempleBeta => Some(1),
MapArea::VrSpaceshipAlpha => Some(2),
MapArea::VrSpaceshipBeta => Some(3),
MapArea::Cca => Some(4),
MapArea::JungleAreaNorth => Some(5),
MapArea::JungleAreaEast => Some(5),
MapArea::Mountain => Some(6),
MapArea::Seaside => Some(7),
MapArea::SeabedUpper => Some(8),
MapArea::SeabedLower => Some(9),
MapArea::GalGryphon => Some(8),
MapArea::OlgaFlow => Some(9),
MapArea::BarbaRay => Some(2),
MapArea::GolDragon => Some(5),
MapArea::SeasideNight => Some(7), // TODO: this could also be 9? needs research
MapArea::Tower => Some(9),
MapArea::CraterEast => Some(2),
MapArea::CraterWest => Some(3),
MapArea::CraterSouth => Some(4),
MapArea::CraterNorth => Some(5),
MapArea::CraterInterior => Some(6),
MapArea::SubDesert1 => Some(7),
MapArea::SubDesert2 => Some(8),
MapArea::SubDesert3 => Some(9),
MapArea::SaintMillion => Some(9),
// MapArea::TestMapEp4 => Some(0),
_ => None
}
}
pub fn area_value(&self) -> u8 {
match self {
MapArea::Pioneer2Ep1 => 0,
MapArea::Forest1 => 1,
MapArea::Forest2 => 2,
MapArea::Caves1 => 3,
MapArea::Caves2 => 4,
MapArea::Caves3 => 5,
MapArea::Mines1 => 6,
MapArea::Mines2 => 7,
MapArea::Ruins1 => 8,
MapArea::Ruins2 => 9,
MapArea::Ruins3 => 10,
MapArea::Dragon => 11,
MapArea::DeRolLe => 12,
MapArea::VolOpt => 13,
MapArea::DarkFalz => 14,
MapArea::Pioneer2Ep2 => 0,
MapArea::VrTempleAlpha => 1,
MapArea::VrTempleBeta => 2,
MapArea::VrSpaceshipAlpha => 3,
MapArea::VrSpaceshipBeta => 4,
MapArea::Cca => 5,
MapArea::JungleAreaNorth => 6,
MapArea::JungleAreaEast => 7,
MapArea::Mountain => 8,
MapArea::Seaside => 9,
MapArea::SeabedUpper => 10,
MapArea::SeabedLower => 11,
MapArea::GalGryphon => 12,
MapArea::OlgaFlow => 13,
MapArea::BarbaRay => 14,
MapArea::GolDragon => 15,
MapArea::SeasideNight => 16,
MapArea::Tower => 17,
MapArea::Pioneer2Ep4 => 0,
MapArea::CraterEast => 1,
MapArea::CraterWest => 2,
MapArea::CraterSouth => 3,
MapArea::CraterNorth => 4,
MapArea::CraterInterior => 5,
MapArea::SubDesert1 => 6,
MapArea::SubDesert2 => 7,
MapArea::SubDesert3 => 8,
MapArea::SaintMillion => 9,
// MapArea::TestMapEp4 => 10,
}
}
pub fn to_episode(self) -> Episode {
match self {
MapArea::Pioneer2Ep1 => Episode::One,
MapArea::Forest1 => Episode::One,
MapArea::Forest2 => Episode::One,
MapArea::Caves1 => Episode::One,
MapArea::Caves2 => Episode::One,
MapArea::Caves3 => Episode::One,
MapArea::Mines1 => Episode::One,
MapArea::Mines2 => Episode::One,
MapArea::Ruins1 => Episode::One,
MapArea::Ruins2 => Episode::One,
MapArea::Ruins3 => Episode::One,
MapArea::Dragon => Episode::One,
MapArea::DeRolLe => Episode::One,
MapArea::VolOpt => Episode::One,
MapArea::DarkFalz => Episode::One,
MapArea::Pioneer2Ep2 => Episode::Two,
MapArea::VrTempleAlpha => Episode::Two,
MapArea::VrTempleBeta => Episode::Two,
MapArea::VrSpaceshipAlpha => Episode::Two,
MapArea::VrSpaceshipBeta => Episode::Two,
MapArea::Cca => Episode::Two,
MapArea::JungleAreaNorth => Episode::Two,
MapArea::JungleAreaEast => Episode::Two,
MapArea::Mountain => Episode::Two,
MapArea::Seaside => Episode::Two,
MapArea::SeabedUpper => Episode::Two,
MapArea::SeabedLower => Episode::Two,
MapArea::GalGryphon => Episode::Two,
MapArea::OlgaFlow => Episode::Two,
MapArea::BarbaRay => Episode::Two,
MapArea::GolDragon => Episode::Two,
MapArea::SeasideNight => Episode::Two,
MapArea::Tower => Episode::Two,
MapArea::Pioneer2Ep4 => Episode::Four,
MapArea::CraterEast => Episode::Four,
MapArea::CraterWest => Episode::Four,
MapArea::CraterSouth => Episode::Four,
MapArea::CraterNorth => Episode::Four,
MapArea::CraterInterior => Episode::Four,
MapArea::SubDesert1 => Episode::Four,
MapArea::SubDesert2 => Episode::Four,
MapArea::SubDesert3 => Episode::Four,
MapArea::SaintMillion => Episode::Four,
}
}
}
#[derive(Debug, Clone)]
pub struct MapAreaLookup(HashMap<u16, MapArea>);
impl MapAreaLookup {
pub fn get_area_map(&self, map_area: u16) -> Result<&MapArea, MapAreaError> {
self.0.get(&map_area).ok_or(MapAreaError::UnknownMapArea(map_area))
}
fn default_ep1_maps() -> MapAreaLookup {
let mut ep1 = HashMap::new();
ep1.insert(0, MapArea::Pioneer2Ep1);
ep1.insert(1, MapArea::Forest1);
ep1.insert(2, MapArea::Forest2);
ep1.insert(3, MapArea::Caves1);
ep1.insert(4, MapArea::Caves2);
ep1.insert(5, MapArea::Caves3);
ep1.insert(6, MapArea::Mines1);
ep1.insert(7, MapArea::Mines2);
ep1.insert(8, MapArea::Ruins1);
ep1.insert(9, MapArea::Ruins2);
ep1.insert(10, MapArea::Ruins3);
ep1.insert(11, MapArea::Dragon);
ep1.insert(12, MapArea::DeRolLe);
ep1.insert(13, MapArea::VolOpt);
ep1.insert(14, MapArea::DarkFalz);
MapAreaLookup(ep1)
}
fn default_ep2_maps() -> MapAreaLookup {
let mut ep2 = HashMap::new();
ep2.insert(0, MapArea::Pioneer2Ep2);
ep2.insert(1, MapArea::VrTempleAlpha);
ep2.insert(2, MapArea::VrTempleBeta);
ep2.insert(3, MapArea::VrSpaceshipAlpha);
ep2.insert(4, MapArea::VrSpaceshipBeta);
ep2.insert(5, MapArea::Cca);
ep2.insert(6, MapArea::JungleAreaNorth);
ep2.insert(7, MapArea::JungleAreaEast);
ep2.insert(8, MapArea::Mountain);
ep2.insert(9, MapArea::Seaside);
ep2.insert(10, MapArea::SeabedUpper);
ep2.insert(11, MapArea::SeabedLower);
ep2.insert(12, MapArea::GalGryphon);
ep2.insert(13, MapArea::OlgaFlow);
ep2.insert(14, MapArea::BarbaRay);
ep2.insert(15, MapArea::GolDragon);
ep2.insert(16, MapArea::SeasideNight);
ep2.insert(17, MapArea::Tower);
MapAreaLookup(ep2)
}
fn default_ep4_maps() -> MapAreaLookup {
let mut ep4 = HashMap::new();
ep4.insert(0, MapArea::Pioneer2Ep4);
ep4.insert(1, MapArea::CraterEast);
ep4.insert(2, MapArea::CraterWest);
ep4.insert(3, MapArea::CraterSouth);
ep4.insert(4, MapArea::CraterNorth);
ep4.insert(5, MapArea::CraterInterior);
ep4.insert(6, MapArea::SubDesert1);
ep4.insert(7, MapArea::SubDesert2);
ep4.insert(8, MapArea::SubDesert3);
ep4.insert(9, MapArea::SaintMillion);
MapAreaLookup(ep4)
}
pub fn new(episode: &Episode) -> MapAreaLookup {
match episode {
Episode::One => MapAreaLookup::default_ep1_maps(),
Episode::Two => MapAreaLookup::default_ep2_maps(),
Episode::Four => MapAreaLookup::default_ep4_maps(),
}
}
}
#[derive(Default)]
pub struct MapAreaLookupBuilder {
map_areas: HashMap<u16, MapArea>,
}
impl MapAreaLookupBuilder {
#[must_use]
pub fn add(mut self, value: u16, map_area: MapArea) -> MapAreaLookupBuilder {
self.map_areas.insert(value, map_area);
self
}
pub fn build(self) -> MapAreaLookup {
MapAreaLookup(self.map_areas)
}
}