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.
166 lines
5.5 KiB
166 lines
5.5 KiB
// 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<R: Read>(cursor: &mut R) -> Result<RawMapObject, std::io::Error> {
|
|
Ok(RawMapObject {
|
|
otype: cursor.read_u16::<LittleEndian>()?,
|
|
_unknown1: cursor.read_u16::<LittleEndian>()?,
|
|
_unknown2: cursor.read_u32::<LittleEndian>()?,
|
|
_id: cursor.read_u16::<LittleEndian>()?,
|
|
_group: cursor.read_u16::<LittleEndian>()?,
|
|
_section: cursor.read_u16::<LittleEndian>()?,
|
|
_unknown3: cursor.read_u16::<LittleEndian>()?,
|
|
_x: cursor.read_f32::<LittleEndian>()?,
|
|
_y: cursor.read_f32::<LittleEndian>()?,
|
|
_z: cursor.read_f32::<LittleEndian>()?,
|
|
_xrot: cursor.read_u32::<LittleEndian>()?,
|
|
_yrot: cursor.read_u32::<LittleEndian>()?,
|
|
_zrot: cursor.read_u32::<LittleEndian>()?,
|
|
field1: cursor.read_f32::<LittleEndian>()?,
|
|
field2: cursor.read_f32::<LittleEndian>()?,
|
|
field3: cursor.read_f32::<LittleEndian>()?,
|
|
field4: cursor.read_u32::<LittleEndian>()?,
|
|
_field5: cursor.read_u32::<LittleEndian>()?,
|
|
_field6: cursor.read_u32::<LittleEndian>()?,
|
|
_field7: cursor.read_u32::<LittleEndian>()?,
|
|
})
|
|
}
|
|
}
|
|
|
|
|
|
#[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<MapObject, MapObjectError> {
|
|
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,
|
|
})
|
|
}
|
|
}
|
|
|