load map object files
This commit is contained in:
		
							parent
							
								
									2f2e9e5c5c
								
							
						
					
					
						commit
						979636a4c4
					
				
							
								
								
									
										193
									
								
								src/ship/map.rs
									
									
									
									
									
								
							
							
						
						
									
										193
									
								
								src/ship/map.rs
									
									
									
									
									
								
							@ -183,6 +183,156 @@ impl MapEnemy {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Copy, Clone)]
 | 
			
		||||
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 {
 | 
			
		||||
    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,
 | 
			
		||||
    //id: u32,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Copy, Clone)]
 | 
			
		||||
enum MapObjectError {
 | 
			
		||||
    UnknownObjectType(u16, RawMapObject),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
impl MapObject {
 | 
			
		||||
    fn from_raw(raw: RawMapObject, episode: Episode) -> 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,
 | 
			
		||||
            _ => return Err(MapObjectError::UnknownObjectType(raw.otype, raw))
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        Ok(MapObject {
 | 
			
		||||
            object: object,
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
enum MapVariantMode {
 | 
			
		||||
@ -269,7 +419,7 @@ impl MapVariant {
 | 
			
		||||
            minor: minor,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // TODO: rename to npc_file
 | 
			
		||||
    fn dat_file(&self) -> String {
 | 
			
		||||
        match self.map {
 | 
			
		||||
            MapVariantType::Pioneer2Ep1 => "data/maps/map_city00_00e.dat".into(),
 | 
			
		||||
@ -290,12 +440,45 @@ impl MapVariant {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn obj_file(&self) -> String {
 | 
			
		||||
        match self.map {
 | 
			
		||||
            MapVariantType::Pioneer2Ep1 => "data/maps/map_city00_00e.dat".into(),
 | 
			
		||||
            MapVariantType::Forest1 => format!("data/maps/map_forest01_0{}o.dat", self.minor),
 | 
			
		||||
            MapVariantType::Forest2 => format!("data/maps/map_forest02_0{}o.dat", self.minor),
 | 
			
		||||
            MapVariantType::Caves1 => format!("data/maps/map_cave01_0{}_0{}o.dat", self.major, self.minor),
 | 
			
		||||
            MapVariantType::Caves2 => format!("data/maps/map_cave02_0{}_0{}o.dat", self.major, self.minor),
 | 
			
		||||
            MapVariantType::Caves3 => format!("data/maps/map_cave03_0{}_0{}o.dat", self.major, self.minor),
 | 
			
		||||
            MapVariantType::Mines1 => format!("data/maps/map_machine01_0{}_0{}o.dat", self.major, self.minor),
 | 
			
		||||
            MapVariantType::Mines2 => format!("data/maps/map_machine02_0{}_0{}o.dat", self.major, self.minor),
 | 
			
		||||
            MapVariantType::Ruins1 => format!("data/maps/map_ancient01_0{}_0{}o.dat", self.major, self.minor),
 | 
			
		||||
            MapVariantType::Ruins2 => format!("data/maps/map_ancient02_0{}_0{}o.dat", self.major, self.minor),
 | 
			
		||||
            MapVariantType::Ruins3 => format!("data/maps/map_ancient03_0{}_0{}o.dat", self.major, self.minor),
 | 
			
		||||
            MapVariantType::Dragon => "data/maps/map_boss01o.dat".into(),
 | 
			
		||||
            MapVariantType::DeRolLe => "data/maps/map_boss02o.dat".into(),
 | 
			
		||||
            MapVariantType::VolOpt => "data/maps/map_boss03o.dat".into(),
 | 
			
		||||
            MapVariantType::DarkFalz => "data/maps/map_boss04o.dat".into(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn pkt_header(&self) -> [u8; 2] {
 | 
			
		||||
        [self.major, self.minor]
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
fn objects_from_map_data(path: PathBuf, episode: &Episode) -> Vec<Option<MapObject>> {
 | 
			
		||||
    let mut cursor = File::open(path.clone()).unwrap();
 | 
			
		||||
    let mut object_data = Vec::new();
 | 
			
		||||
 | 
			
		||||
    while let Ok(raw_object) = RawMapObject::from_byte_stream(&mut cursor) {
 | 
			
		||||
        let object = MapObject::from_raw(raw_object.clone(), *episode);
 | 
			
		||||
        object_data.push(object.ok());
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    object_data
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
fn enemy_data_from_map_data(path: PathBuf, episode: &Episode) -> Vec<Option<MapEnemy>> {
 | 
			
		||||
    let mut cursor = File::open(path).unwrap();
 | 
			
		||||
    let mut enemy_data = Vec::new();
 | 
			
		||||
@ -377,7 +560,6 @@ fn enemy_data_from_map_data(path: PathBuf, episode: &Episode) -> Vec<Option<MapE
 | 
			
		||||
                                           monsters.push(Some(MapEnemy::new(MonsterType::DarkFalz1)));
 | 
			
		||||
                                       },
 | 
			
		||||
                                       _ => {
 | 
			
		||||
                                           warn!("children: {}", enemy.children);
 | 
			
		||||
                                           for _ in 0..enemy.children {
 | 
			
		||||
                                               monsters.push(Some(MapEnemy::new(monster.monster)));
 | 
			
		||||
                                           }
 | 
			
		||||
@ -393,12 +575,12 @@ fn enemy_data_from_map_data(path: PathBuf, episode: &Episode) -> Vec<Option<MapE
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
pub struct Maps {
 | 
			
		||||
    map_variants: [MapVariant; 15],
 | 
			
		||||
    enemy_data: Vec<Option<MapEnemy>>
 | 
			
		||||
    enemy_data: Vec<Option<MapEnemy>>,
 | 
			
		||||
    object_data: Vec<Option<MapObject>>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Maps {
 | 
			
		||||
    pub fn new(episode: Episode) -> Maps {
 | 
			
		||||
        warn!("new maps ep: {:?}", episode);
 | 
			
		||||
        let map_variants = match episode {
 | 
			
		||||
            Episode::One => {
 | 
			
		||||
                [MapVariant::new(MapVariantType::Pioneer2Ep1, MapVariantMode::Online),
 | 
			
		||||
@ -426,6 +608,9 @@ impl Maps {
 | 
			
		||||
                enemy_data.append(&mut enemy_data_from_map_data(map_variant.dat_file().into(), &episode));
 | 
			
		||||
                enemy_data
 | 
			
		||||
            }),
 | 
			
		||||
            object_data: map_variants.iter().map(|map_variant| {
 | 
			
		||||
                objects_from_map_data(map_variant.obj_file().into(), &episode)
 | 
			
		||||
            }).flatten().collect(),
 | 
			
		||||
            map_variants: map_variants,
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user