// TOOD: `pub(super) for most of these?` use std::io::Read; use byteorder::{LittleEndian, ReadBytesExt}; use crate::room::Episode; use crate::area::MapArea; #[derive(Debug, Copy, Clone)] pub struct RawMapObject { otype: u16, _unknown1: u16, _unknown2: u32, _id: u16, _group: u16, _section: u16, _unknown3: u16, _x: f32, _y: f32, _z: f32, _xrot: u32, _yrot: u32, _zrot: u32, field1: f32, field2: f32, field3: f32, field4: u32, _field5: u32, _field6: u32, _field7: u32, } impl RawMapObject { pub fn from_byte_stream(cursor: &mut R) -> Result { Ok(RawMapObject { otype: cursor.read_u16::()?, _unknown1: cursor.read_u16::()?, _unknown2: cursor.read_u32::()?, _id: cursor.read_u16::()?, _group: cursor.read_u16::()?, _section: cursor.read_u16::()?, _unknown3: cursor.read_u16::()?, _x: cursor.read_f32::()?, _y: cursor.read_f32::()?, _z: cursor.read_f32::()?, _xrot: cursor.read_u32::()?, _yrot: cursor.read_u32::()?, _zrot: cursor.read_u32::()?, field1: cursor.read_f32::()?, field2: cursor.read_f32::()?, field3: cursor.read_f32::()?, field4: cursor.read_u32::()?, _field5: cursor.read_u32::()?, _field6: cursor.read_u32::()?, _field7: cursor.read_u32::()?, }) } } #[derive(Debug, Copy, Clone)] pub enum FixedBoxDropType { Weapon, Armor, Tool, Meseta, Random, Specific(u32), // TODO: ItemDropType } impl FixedBoxDropType { fn from_object(field1: f32, field2: f32, field3: f32, field4: u32) -> FixedBoxDropType { match (field1.round() as i32, field2.round() as i32, field3.round() as i32, field4) { (0, 1, 1, 0) => { FixedBoxDropType::Random }, (0, 1, _, 0x4000000) => { FixedBoxDropType::Meseta }, (0, 1, 1, _) => { FixedBoxDropType::Specific(field4) }, (-1, 1, 1, _) => { // ??????? FixedBoxDropType::Specific(field4) }, (0, 1, 0, 0) => { FixedBoxDropType::Weapon }, (0, 1, 0, 0x1000000) => { FixedBoxDropType::Armor }, (0, 1, 0, 0x3000000) => { FixedBoxDropType::Tool }, (1, _, _, _) => { FixedBoxDropType::Random }, _ => { println!("this box state should not occur? {} {} {} {}", field1.round() as i32, field2.round() as i32, field3.round() as i32, field4); FixedBoxDropType::Random } } } } #[derive(Debug, Copy, Clone)] pub enum MapObjectType { Box, FixedBox(FixedBoxDropType), EnemyBox, EnemyFixedBox(FixedBoxDropType), RuinsBox, RuinsFixedBox(FixedBoxDropType), RuinsEnemyBox, RuinsEnemyFixedBox(FixedBoxDropType), CcaBox, CcaFixedBox(FixedBoxDropType), EmptyBox, EmptyFixedBox(FixedBoxDropType), RuinsEmptyBox, RuinsEmptyFixedBox, } #[derive(Debug, Copy, Clone)] pub struct MapObject { pub object: MapObjectType, pub map: MapArea, pub dropped_item: bool, //id: u32, } #[derive(Debug, Copy, Clone)] pub enum MapObjectError { UnknownObjectType(u16, RawMapObject), } impl MapObject { pub fn from_raw(raw: RawMapObject, episode: Episode, map_area: &MapArea) -> Result { let object = match (raw, episode) { (RawMapObject {otype: 136, ..}, _) => MapObjectType::Box, (RawMapObject {otype: 145, ..}, _) => MapObjectType::EnemyBox, (RawMapObject {otype: 146, ..}, _) => MapObjectType::FixedBox(FixedBoxDropType::from_object(raw.field1, raw.field2, raw.field3, raw.field4)), (RawMapObject {otype: 147, ..}, _) => MapObjectType::EnemyFixedBox(FixedBoxDropType::from_object(raw.field1, raw.field2, raw.field3, raw.field4)), (RawMapObject {otype: 149, ..}, _) => MapObjectType::EmptyFixedBox(FixedBoxDropType::from_object(raw.field1, raw.field2, raw.field3, raw.field4)), (RawMapObject {otype: 353, ..}, _) => MapObjectType::RuinsFixedBox(FixedBoxDropType::from_object(raw.field1, raw.field2, raw.field3, raw.field4)), (RawMapObject {otype: 354, ..}, _) => MapObjectType::RuinsBox, (RawMapObject {otype: 355, ..}, _) => MapObjectType::RuinsEnemyFixedBox(FixedBoxDropType::from_object(raw.field1, raw.field2, raw.field3, raw.field4)), (RawMapObject {otype: 356, ..}, _) => MapObjectType::RuinsEnemyBox, (RawMapObject {otype: 357, ..}, _) => MapObjectType::RuinsEmptyBox, (RawMapObject {otype: 512, ..}, _) => MapObjectType::CcaBox, (RawMapObject {otype: 515, ..}, _) => MapObjectType::CcaFixedBox(FixedBoxDropType::from_object(raw.field1, raw.field2, raw.field3, raw.field4)), _ => return Err(MapObjectError::UnknownObjectType(raw.otype, raw)) }; Ok(MapObject { object, map: *map_area, dropped_item: false, }) } }