diff --git a/src/ship/map.rs b/src/ship/map.rs index 7119976..4b60645 100644 --- a/src/ship/map.rs +++ b/src/ship/map.rs @@ -7,6 +7,7 @@ use std::fs::File; use byteorder::{LittleEndian, ReadBytesExt}; use rand::Rng; +use thiserror::Error; use crate::ship::monster::MonsterType; use crate::ship::room::Episode; @@ -65,18 +66,22 @@ impl RawMapEnemy { } -#[derive(Debug)] +#[derive(Error, Debug)] +#[error("")] enum MapEnemyError { UnknownEnemyId(u32), + MapAreaError(#[from] MapAreaError), } #[derive(Debug, Copy, Clone)] pub struct MapEnemy { pub monster: MonsterType, + pub map_area: MapArea, hp: u32, - // other stats from bp.n - dead: bool, + // TODO: other stats from battleparam + pub dropped_item: bool, + pub gave_exp: bool, } impl MapEnemy { @@ -169,16 +174,20 @@ impl MapEnemy { Ok(MapEnemy { monster: monster, + map_area: MapArea::from_value(&episode, enemy.map_area as u32)?, hp: 0, - dead: false, + dropped_item: false, + gave_exp: false, }) } - fn new(monster: MonsterType) -> MapEnemy { + fn new(monster: MonsterType, map_area: MapArea) -> MapEnemy { MapEnemy { monster: monster, + map_area: map_area, hp: 0, - dead: false, + dropped_item: false, + gave_exp: false, } } } @@ -340,7 +349,7 @@ enum MapVariantMode { Offline, } -#[derive(Debug)] +#[derive(Debug, Copy, Clone)] pub enum MapArea { Pioneer2Ep1, Forest1, @@ -359,12 +368,14 @@ pub enum MapArea { DarkFalz, } +#[derive(Error, Debug)] +#[error("")] pub enum MapAreaError { UnknownMapArea(u32), } impl MapArea { - pub fn from_value(episode: Episode, area: u32) -> Result { + pub fn from_value(episode: &Episode, area: u32) -> Result { match (episode, area) { (Episode::One, 0) => Ok(MapArea::Pioneer2Ep1), (Episode::One, 1) => Ok(MapArea::Forest1), @@ -404,6 +415,26 @@ impl MapArea { _ => 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, + } + } } @@ -516,76 +547,76 @@ fn enemy_data_from_map_data(path: PathBuf, episode: &Episode) -> Vec { for _ in 0..30 { - monsters.push(Some(MapEnemy::new(MonsterType::Mothmant))); + monsters.push(Some(MapEnemy::new(MonsterType::Mothmant, monster.map_area))); } }, MonsterType::PofuillySlime => { for _ in 0..4 { - monsters.push(Some(MapEnemy::new(MonsterType::PofuillySlime))); + monsters.push(Some(MapEnemy::new(MonsterType::PofuillySlime, monster.map_area))); } }, MonsterType::PanArms => { - monsters.push(Some(MapEnemy::new(MonsterType::Hidoom))); - monsters.push(Some(MapEnemy::new(MonsterType::Migium))); + monsters.push(Some(MapEnemy::new(MonsterType::Hidoom, monster.map_area))); + monsters.push(Some(MapEnemy::new(MonsterType::Migium, monster.map_area))); }, MonsterType::SinowBeat => { for _ in 0..4 { - monsters.push(Some(MapEnemy::new(MonsterType::SinowBeat))); + monsters.push(Some(MapEnemy::new(MonsterType::SinowBeat, monster.map_area))); } }, MonsterType::SinowGold => { for _ in 0..4 { - monsters.push(Some(MapEnemy::new(MonsterType::SinowGold))); + monsters.push(Some(MapEnemy::new(MonsterType::SinowGold, monster.map_area))); } }, MonsterType::Canane => { for _ in 0..8 { - monsters.push(Some(MapEnemy::new(MonsterType::RingCanadine))); + monsters.push(Some(MapEnemy::new(MonsterType::RingCanadine, monster.map_area))); } }, MonsterType::ChaosSorcerer => { - monsters.push(Some(MapEnemy::new(MonsterType::BeeR))); - monsters.push(Some(MapEnemy::new(MonsterType::BeeL))); + monsters.push(Some(MapEnemy::new(MonsterType::BeeR, monster.map_area))); + monsters.push(Some(MapEnemy::new(MonsterType::BeeL, monster.map_area))); }, MonsterType::Bulclaw => { for _ in 0..4 { - monsters.push(Some(MapEnemy::new(MonsterType::Claw))); + monsters.push(Some(MapEnemy::new(MonsterType::Claw, monster.map_area))); } }, MonsterType::DeRolLe => { for _ in 0..10 { - monsters.push(Some(MapEnemy::new(MonsterType::DeRolLeBody))); + monsters.push(Some(MapEnemy::new(MonsterType::DeRolLeBody, monster.map_area))); } for _ in 0..9 { - monsters.push(Some(MapEnemy::new(MonsterType::DeRolLeMine))); + monsters.push(Some(MapEnemy::new(MonsterType::DeRolLeMine, monster.map_area))); } }, MonsterType::VolOptPartA => { for _ in 0..6 { - monsters.push(Some(MapEnemy::new(MonsterType::VolOptPillar))); + monsters.push(Some(MapEnemy::new(MonsterType::VolOptPillar, monster.map_area))); } for _ in 0..24 { - monsters.push(Some(MapEnemy::new(MonsterType::VolOptMonitor))); + monsters.push(Some(MapEnemy::new(MonsterType::VolOptMonitor, monster.map_area))); } for _ in 0..2 { - monsters.push(Some(MapEnemy::new(MonsterType::VolOptUnused))); + monsters.push(Some(MapEnemy::new(MonsterType::VolOptUnused, monster.map_area))); } - monsters.push(Some(MapEnemy::new(MonsterType::VolOptAmp))); - monsters.push(Some(MapEnemy::new(MonsterType::VolOptCore))); - monsters.push(Some(MapEnemy::new(MonsterType::VolOptUnused))); + monsters.push(Some(MapEnemy::new(MonsterType::VolOptAmp, monster.map_area))); + monsters.push(Some(MapEnemy::new(MonsterType::VolOptCore, monster.map_area))); + monsters.push(Some(MapEnemy::new(MonsterType::VolOptUnused, monster.map_area))); }, // TOOD: this cares about difficulty (theres an ult-specific darvant?) MonsterType::DarkFalz => { for _ in 0..509 { - monsters.push(Some(MapEnemy::new(MonsterType::Darvant))); + monsters.push(Some(MapEnemy::new(MonsterType::Darvant, monster.map_area))); } - monsters.push(Some(MapEnemy::new(MonsterType::DarkFalz3))); - monsters.push(Some(MapEnemy::new(MonsterType::DarkFalz2))); - monsters.push(Some(MapEnemy::new(MonsterType::DarkFalz1))); + monsters.push(Some(MapEnemy::new(MonsterType::DarkFalz3, monster.map_area))); + monsters.push(Some(MapEnemy::new(MonsterType::DarkFalz2, monster.map_area))); + monsters.push(Some(MapEnemy::new(MonsterType::DarkFalz1, monster.map_area))); }, _ => { for _ in 0..enemy.children { - monsters.push(Some(MapEnemy::new(monster.monster))); + monsters.push(Some(MapEnemy::new(monster.monster, monster.map_area))); } } } @@ -596,6 +627,12 @@ fn enemy_data_from_map_data(path: PathBuf, episode: &Episode) -> Vec MapEnemy { - self.enemy_data[id].unwrap() + pub fn enemy_by_id(&self, id: usize) -> Result { + self.enemy_data[id].ok_or(MapsError::InvalidMonsterId(id)) } pub fn map_headers(&self) -> [u32; 0x20] {