// TOOD: `pub(super) for most of these?` use std::io::{Read}; use byteorder::{LittleEndian, ReadBytesExt}; use crate::ship::room::Episode; // TODO: don't use * use crate::ship::map::*; #[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, }) } }