|
|
@ -85,6 +85,7 @@ pub struct MapEnemy { |
|
|
|
|
|
|
|
impl MapEnemy {
|
|
|
|
fn from_raw(enemy: RawMapEnemy, episode: &Episode, map_area: &MapArea /*, battleparam */) -> Result<MapEnemy, MapEnemyError> {
|
|
|
|
// TODO: rare enemies ep1-4, tower lilys, ult variants?
|
|
|
|
let monster = match map_area {
|
|
|
|
MapArea::Forest1 | MapArea::Forest2 | MapArea::Dragon |
|
|
|
|
MapArea::Caves1 | MapArea::Caves2 | MapArea::Caves3 | MapArea::DeRolLe |
|
|
|
@ -92,7 +93,9 @@ impl MapEnemy { |
|
|
|
MapArea::Ruins1 | MapArea::Ruins2 | MapArea::Ruins3 | MapArea::DarkFalz => {
|
|
|
|
match (enemy, episode) {
|
|
|
|
(RawMapEnemy {id: 64, ..}, _) => MonsterType::Hildebear,
|
|
|
|
// (RawMapEnemy {id: 64, ..}, _) => MonsterType::Hildeblue,
|
|
|
|
(RawMapEnemy {id: 65, ..}, _) => MonsterType::RagRappy,
|
|
|
|
// (RawMapEnemy {id: 65, ..}, _) => MonsterType::AlRappy,
|
|
|
|
(RawMapEnemy {id: 66, ..}, _) => MonsterType::Monest,
|
|
|
|
(RawMapEnemy {id: 67, field2: 0, ..}, _) => MonsterType::SavageWolf,
|
|
|
|
(RawMapEnemy {id: 67, ..}, _) => MonsterType::BarbarousWolf,
|
|
|
@ -101,11 +104,13 @@ impl MapEnemy { |
|
|
|
(RawMapEnemy {id: 68, skin: 2, ..}, _) => MonsterType::Gigobooma,
|
|
|
|
(RawMapEnemy {id: 96, ..}, _) => MonsterType::GrassAssassin,
|
|
|
|
(RawMapEnemy {id: 97, ..}, _) => MonsterType::PoisonLily,
|
|
|
|
// (RawMapEnemy {id: 97, ..}, _) => MonsterType::NarLily,
|
|
|
|
(RawMapEnemy {id: 98, ..}, _) => MonsterType::NanoDragon,
|
|
|
|
(RawMapEnemy {id: 99, skin: 0, ..}, _) => MonsterType::EvilShark,
|
|
|
|
(RawMapEnemy {id: 99, skin: 1, ..}, _) => MonsterType::PalShark,
|
|
|
|
(RawMapEnemy {id: 99, skin: 2, ..}, _) => MonsterType::GuilShark,
|
|
|
|
(RawMapEnemy {id: 100, ..}, _) => MonsterType::PofuillySlime,
|
|
|
|
// (RawMapEnemy {id: 100, ..}, _) => MonsterType::PouillySlime,
|
|
|
|
(RawMapEnemy {id: 101, ..}, _) => MonsterType::PanArms,
|
|
|
|
(RawMapEnemy {id: 128, skin: 0, ..}, _) => MonsterType::Dubchic,
|
|
|
|
(RawMapEnemy {id: 128, skin: 1, ..}, _) => MonsterType::Gillchic,
|
|
|
@ -133,18 +138,23 @@ impl MapEnemy { |
|
|
|
_ => return Err(MapEnemyError::UnknownEnemyId(enemy.id))
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
MapArea::VrTempleAlpha | MapArea::VrTempleBeta | MapArea::BarbaRay |
|
|
|
|
MapArea::VrSpaceshipAlpha | MapArea::VrSpaceshipBeta | MapArea::GolDragon |
|
|
|
|
MapArea::JungleAreaNorth | MapArea::JungleAreaEast | MapArea::Mountain | MapArea::Seaside | MapArea::Cca | MapArea::GalGryphon |
|
|
|
|
MapArea::SeabedUpper | MapArea::SeabedLower | MapArea::OlgaFlow => {
|
|
|
|
match (enemy, episode) {
|
|
|
|
(RawMapEnemy {id: 64, ..}, _) => MonsterType::Hildebear,
|
|
|
|
// (RawMapEnemy {id: 64, ..}, _) => MonsterType::Hildeblue,
|
|
|
|
(RawMapEnemy {id: 65, ..}, _) => MonsterType::RagRappy,
|
|
|
|
// (RawMapEnemy {id: 65, ..}, _) => MonsterType::EventRappy,
|
|
|
|
(RawMapEnemy {id: 66, ..}, _) => MonsterType::Monest,
|
|
|
|
(RawMapEnemy {id: 67, field2: 0, ..}, _) => MonsterType::SavageWolf,
|
|
|
|
(RawMapEnemy {id: 67, ..}, _) => MonsterType::BarbarousWolf,
|
|
|
|
(RawMapEnemy {id: 96, ..}, _) => MonsterType::GrassAssassin,
|
|
|
|
(RawMapEnemy {id: 97, ..}, _) => MonsterType::PoisonLily,
|
|
|
|
// (RawMapEnemy {id: 97, ..}, _) => MonsterType::NarLily,
|
|
|
|
// (RawMapEnemy {id: 97, ..}, _) => MonsterType::DelLily,
|
|
|
|
(RawMapEnemy {id: 101, ..}, _) => MonsterType::PanArms,
|
|
|
|
(RawMapEnemy {id: 128, skin: 0, ..}, _) => MonsterType::Dubchic,
|
|
|
|
(RawMapEnemy {id: 128, skin: 1, ..}, _) => MonsterType::Gillchic,
|
|
|
@ -185,33 +195,41 @@ impl MapEnemy { |
|
|
|
_ => return Err(MapEnemyError::UnknownEnemyId(enemy.id))
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
MapArea::CraterEast | MapArea::CraterWest | MapArea::CraterSouth | MapArea::CraterNorth | MapArea::CraterInterior => {
|
|
|
|
match (enemy, episode) {
|
|
|
|
(RawMapEnemy {id: 65, ..}, Episode::Four) => MonsterType::SandRappyCrater,
|
|
|
|
// (RawMapEnemy {id: 65, ..}, Episode::Four) => MonsterType::DelRappyCrater,
|
|
|
|
(RawMapEnemy {id: 272, ..}, _) => MonsterType::Astark,
|
|
|
|
(RawMapEnemy {id: 273, field2: 0, ..}, _) => MonsterType::SatelliteLizardCrater,
|
|
|
|
(RawMapEnemy {id: 273, ..}, _) => MonsterType::YowieCrater,
|
|
|
|
(RawMapEnemy {id: 276, ..}, _) => MonsterType::ZuCrater,
|
|
|
|
// (RawMapEnemy {id: 276, ..}, _) => MonsterType::PazuzuCrater,
|
|
|
|
(RawMapEnemy {id: 277, skin: 0, ..}, _) => MonsterType::Boota,
|
|
|
|
(RawMapEnemy {id: 277, skin: 1, ..}, _) => MonsterType::ZeBoota,
|
|
|
|
(RawMapEnemy {id: 277, skin: 2, ..}, _) => MonsterType::BaBoota,
|
|
|
|
(RawMapEnemy {id: 278, ..}, _) => MonsterType::Dorphon,
|
|
|
|
// (RawMapEnemy {id: 278, ..}, _) => MonsterType::DorphonEclair,
|
|
|
|
_ => return Err(MapEnemyError::UnknownEnemyId(enemy.id))
|
|
|
|
}
|
|
|
|
},
|
|
|
|
MapArea::SubDesert1 | MapArea::SubDesert2 | MapArea::SubDesert3 | MapArea::SaintMillion => {
|
|
|
|
match (enemy, episode) {
|
|
|
|
(RawMapEnemy {id: 65, ..}, Episode::Four) => MonsterType::SandRappyDesert,
|
|
|
|
// (RawMapEnemy {id: 65, ..}, Episode::Four) => MonsterType::DelRappyDesert,
|
|
|
|
(RawMapEnemy {id: 273, field2: 0, ..}, _) => MonsterType::SatelliteLizardDesert,
|
|
|
|
(RawMapEnemy {id: 273, ..}, _) => MonsterType::YowieDesert,
|
|
|
|
(RawMapEnemy {id: 274, ..}, _) => MonsterType::MerissaA,
|
|
|
|
// (RawMapEnemy {id: 274, ..}, _) => MonsterType::MerissaAA,
|
|
|
|
(RawMapEnemy {id: 275, ..}, _) => MonsterType::Girtablulu,
|
|
|
|
(RawMapEnemy {id: 276, ..}, _) => MonsterType::ZuDesert,
|
|
|
|
// (RawMapEnemy {id: 276, ..}, _) => MonsterType::PazuzuDesert,
|
|
|
|
(RawMapEnemy {id: 279, skin: 0, ..}, _) => MonsterType::Goran,
|
|
|
|
(RawMapEnemy {id: 279, skin: 1, ..}, _) => MonsterType::PyroGoran,
|
|
|
|
(RawMapEnemy {id: 279, skin: 2, ..}, _) => MonsterType::GoranDetonator,
|
|
|
|
(RawMapEnemy {id: 281, skin: 0, ..}, _) => MonsterType::SaintMillion,
|
|
|
|
(RawMapEnemy {id: 281, skin: 1, ..}, _) => MonsterType::Shambertin,
|
|
|
|
// (RawMapEnemy {id: 281, skin: 1, ..}, _) => MonsterType::Kondrieu,
|
|
|
|
_ => return Err(MapEnemyError::UnknownEnemyId(enemy.id))
|
|
|
|
}
|
|
|
|
},
|
|
|
@ -264,7 +282,7 @@ struct RawMapObject { |
|
|
|
|
|
|
|
impl RawMapObject {
|
|
|
|
fn from_byte_stream<R: Read>(cursor: &mut R) -> Result<RawMapObject, std::io::Error> {
|
|
|
|
let r = RawMapObject {
|
|
|
|
Ok(RawMapObject {
|
|
|
|
otype: cursor.read_u16::<LittleEndian>()?,
|
|
|
|
unknown1: cursor.read_u16::<LittleEndian>()?,
|
|
|
|
unknown2: cursor.read_u32::<LittleEndian>()?,
|
|
|
@ -285,9 +303,7 @@ impl RawMapObject { |
|
|
|
field5: cursor.read_u32::<LittleEndian>()?,
|
|
|
|
field6: cursor.read_u32::<LittleEndian>()?,
|
|
|
|
field7: cursor.read_u32::<LittleEndian>()?,
|
|
|
|
};
|
|
|
|
println!("from_byte_stream object: {:?}", r);
|
|
|
|
Ok(r)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
@ -671,17 +687,16 @@ impl MapVariant { |
|
|
|
MapArea::GolDragon => 0,
|
|
|
|
|
|
|
|
MapArea::Pioneer2Ep4 => 0,
|
|
|
|
MapArea::CraterEast => 2, // 0: good map. 1: good. 2: good
|
|
|
|
MapArea::CraterWest => 2, // 0: bad map. 1: bad. 2: bad
|
|
|
|
MapArea::CraterSouth => 2, // 0: bad map. 1: bad. 2:
|
|
|
|
MapArea::CraterNorth => 2, // 0: bad map. 1: bad . 2:
|
|
|
|
MapArea::CraterInterior => 2,
|
|
|
|
// MapArea::CraterWest | MapArea::CraterSouth | MapArea::CraterNorth | MapArea::CraterInterior => rand::thread_rng().gen_range(0, 2),
|
|
|
|
MapArea::CraterEast => 2, // 0 good, 1 good, 2 good
|
|
|
|
MapArea::CraterWest => 2, // 0 bad, 1 bad, 2 bad
|
|
|
|
MapArea::CraterSouth => 2, // 0 bad, 1 bad, 2 bad
|
|
|
|
MapArea::CraterNorth => 2, // 0 bad, 1 bad, 2 bad
|
|
|
|
MapArea::CraterInterior => 2, // 0 good, 1 good, 2 good
|
|
|
|
MapArea::SubDesert1 | MapArea::SubDesert3 => 0,
|
|
|
|
MapArea::SubDesert2 => rand::thread_rng().gen_range(0, 2),
|
|
|
|
MapArea::SaintMillion => 0,
|
|
|
|
};
|
|
|
|
println!("map: {:?}, mode: {:?}, major: {:?}, minor: {:?}", map, mode, major, minor);
|
|
|
|
|
|
|
|
MapVariant {
|
|
|
|
map: map,
|
|
|
|
mode: mode,
|
|
|
@ -721,13 +736,8 @@ impl MapVariant { |
|
|
|
|
|
|
|
let minor = match map {
|
|
|
|
MapArea::Pioneer2Ep1 => 0,
|
|
|
|
MapArea::Forest1 => rand::thread_rng().gen_range(0, 3) * 2,
|
|
|
|
MapArea::Forest2 => 0, // TODO: check if the other offline map files are corrupted?
|
|
|
|
// MapArea::Forest2 => {match rand::thread_rng().gen_range(0, 3) {
|
|
|
|
// 0 => 0, // valid
|
|
|
|
// 1 => 3, // invalid
|
|
|
|
// 2 => 4, // invalid
|
|
|
|
// _ => unreachable!()}},
|
|
|
|
MapArea::Forest1 => rand::thread_rng().gen_range(0, 3),
|
|
|
|
MapArea::Forest2 => rand::thread_rng().gen_range(0, 3),
|
|
|
|
MapArea::Caves1 | MapArea::Caves2 | MapArea::Caves3 => 0,
|
|
|
|
MapArea::Mines1 | MapArea::Mines2 => rand::thread_rng().gen_range(0, 2), // no offline-specific maps
|
|
|
|
MapArea::Ruins1 | MapArea::Ruins2 | MapArea::Ruins3 => rand::thread_rng().gen_range(0, 2),// no offline-specific maps
|
|
|
@ -747,13 +757,18 @@ impl MapVariant { |
|
|
|
MapArea::GolDragon => 0,
|
|
|
|
|
|
|
|
MapArea::Pioneer2Ep4 => 0,
|
|
|
|
MapArea::CraterEast | MapArea::CraterWest | MapArea::CraterSouth | MapArea::CraterNorth | MapArea::CraterInterior => rand::thread_rng().gen_range(0, 2),
|
|
|
|
// MapArea::CraterEast | MapArea::CraterWest | MapArea::CraterSouth | MapArea::CraterNorth | MapArea::CraterInterior => rand::thread_rng().gen_range(0, 2),
|
|
|
|
MapArea::CraterEast => 0,
|
|
|
|
MapArea::CraterWest => 0,
|
|
|
|
MapArea::CraterSouth => 0,
|
|
|
|
MapArea::CraterNorth => 0,
|
|
|
|
MapArea::CraterInterior => 0,
|
|
|
|
MapArea::SubDesert1 | MapArea::SubDesert3 => 0,
|
|
|
|
MapArea::SubDesert2 => rand::thread_rng().gen_range(0, 2),
|
|
|
|
MapArea::SaintMillion => 0,
|
|
|
|
|
|
|
|
};
|
|
|
|
println!("map: {:?}, mode: {:?}, major: {:?}, minor: {:?}", map, mode, major, minor);
|
|
|
|
|
|
|
|
MapVariant {
|
|
|
|
map: map,
|
|
|
|
mode: mode,
|
|
|
@ -814,7 +829,13 @@ impl MapVariant { |
|
|
|
match self.map {
|
|
|
|
MapArea::Pioneer2Ep1 => "data/maps/map_city00_00e_s.dat".into(),
|
|
|
|
MapArea::Forest1 => format!("data/maps/map_forest01_0{}_offe.dat", self.minor*2),
|
|
|
|
MapArea::Forest2 => format!("data/maps/map_forest02_0{}_offe.dat", self.minor),
|
|
|
|
MapArea::Forest2 => {
|
|
|
|
match self.minor {
|
|
|
|
0 => format!("data/maps/map_forest02_00_offe.dat"),
|
|
|
|
1 => format!("data/maps/map_forest02_03_offe.dat"),
|
|
|
|
2 => format!("data/maps/map_forest02_04_offe.dat"),
|
|
|
|
_ => unreachable!()
|
|
|
|
}},
|
|
|
|
MapArea::Caves1 => format!("data/maps/map_cave01_0{}_0{}_offe.dat", self.major, self.minor),
|
|
|
|
MapArea::Caves2 => format!("data/maps/map_cave02_0{}_0{}_offe.dat", self.major, self.minor),
|
|
|
|
MapArea::Caves3 => format!("data/maps/map_cave03_0{}_0{}_offe.dat", self.major, self.minor),
|
|
|
@ -845,7 +866,7 @@ impl MapVariant { |
|
|
|
MapArea::BarbaRay => "data/maps/map_boss07e.dat".into(),
|
|
|
|
MapArea::GolDragon => "data/maps/map_boss08e.dat".into(),
|
|
|
|
|
|
|
|
MapArea::Pioneer2Ep4 => "data/maps/map_city02_00_00e.dat".into(),
|
|
|
|
MapArea::Pioneer2Ep4 => "data/maps/map_city02_00_00e_s.dat".into(),
|
|
|
|
MapArea::CraterEast => format!("data/maps/map_wilds01_0{}_0{}e.dat", self.major, self.minor),
|
|
|
|
MapArea::CraterWest => format!("data/maps/map_wilds01_0{}_0{}e.dat", self.major, self.minor),
|
|
|
|
MapArea::CraterSouth => format!("data/maps/map_wilds01_0{}_0{}e.dat", self.major, self.minor),
|
|
|
@ -909,8 +930,14 @@ impl MapVariant { |
|
|
|
} else {
|
|
|
|
match self.map {
|
|
|
|
MapArea::Pioneer2Ep1 => "data/maps/map_city00_00o_s.dat".into(),
|
|
|
|
MapArea::Forest1 => format!("data/maps/map_forest01_0{}o.dat", self.minor),
|
|
|
|
MapArea::Forest2 => format!("data/maps/map_forest02_0{}o.dat", self.minor),
|
|
|
|
MapArea::Forest1 => format!("data/maps/map_forest01_0{}o.dat", self.minor*2),
|
|
|
|
MapArea::Forest2 => {
|
|
|
|
match self.minor {
|
|
|
|
0 => format!("data/maps/map_forest02_00o.dat"),
|
|
|
|
1 => format!("data/maps/map_forest02_03o.dat"),
|
|
|
|
2 => format!("data/maps/map_forest02_04o.dat"),
|
|
|
|
_ => unreachable!()
|
|
|
|
}},
|
|
|
|
MapArea::Caves1 => format!("data/maps/map_cave01_0{}_0{}o.dat", self.major, self.minor),
|
|
|
|
MapArea::Caves2 => format!("data/maps/map_cave02_0{}_0{}o.dat", self.major, self.minor),
|
|
|
|
MapArea::Caves3 => format!("data/maps/map_cave03_0{}_0{}o.dat", self.major, self.minor),
|
|
|
@ -941,7 +968,7 @@ impl MapVariant { |
|
|
|
MapArea::BarbaRay => "data/maps/map_boss07_offo.dat".into(),
|
|
|
|
MapArea::GolDragon => "data/maps/map_boss08_offo.dat".into(),
|
|
|
|
|
|
|
|
MapArea::Pioneer2Ep4 => "data/maps/map_city02_00_00o.dat".into(),
|
|
|
|
MapArea::Pioneer2Ep4 => "data/maps/map_city02_00_00o_s.dat".into(),
|
|
|
|
MapArea::CraterEast => format!("data/maps/map_wilds01_0{}_0{}o.dat", self.major, self.minor),
|
|
|
|
MapArea::CraterWest => format!("data/maps/map_wilds01_0{}_0{}o.dat", self.major, self.minor),
|
|
|
|
MapArea::CraterSouth => format!("data/maps/map_wilds01_0{}_0{}o.dat", self.major, self.minor),
|
|
|
@ -972,7 +999,6 @@ pub fn objects_from_stream(cursor: &mut impl Read, episode: &Episode, map_area: |
|
|
|
}
|
|
|
|
|
|
|
|
fn objects_from_map_data(path: PathBuf, episode: &Episode, map_area: &MapArea) -> Vec<Option<MapObject>> {
|
|
|
|
println!("objects_from_map_data() path: {:?}, episode: {:?}, map_area: {:?}", path, episode, map_area);
|
|
|
|
let mut cursor = File::open(path.clone()).unwrap();
|
|
|
|
objects_from_stream(&mut cursor, episode, map_area)
|
|
|
|
}
|
|
|
@ -1110,7 +1136,6 @@ pub fn enemy_data_from_stream(cursor: &mut impl Read, map_area: &MapArea, episod |
|
|
|
|
|
|
|
fn enemy_data_from_map_data(map_variant: &MapVariant, episode: &Episode) -> Vec<Option<MapEnemy>> {
|
|
|
|
let path = map_variant.dat_file();
|
|
|
|
println!("loaded map: {:?}", path);
|
|
|
|
let mut cursor = File::open(path).unwrap();
|
|
|
|
enemy_data_from_stream(&mut cursor, &map_variant.map, episode)
|
|
|
|
}
|
|
|
@ -1225,7 +1250,6 @@ impl Maps { |
|
|
|
|
|
|
|
let maps = Maps {
|
|
|
|
enemy_data: map_variants.iter().fold(Vec::new(), |mut enemy_data, map_variant| {
|
|
|
|
// enemy_data.append(&mut enemy_data_from_map_data(&map_variant, &episode));
|
|
|
|
enemy_data.append(&mut enemy_data_from_map_data(&map_variant, &room_mode.episode()));
|
|
|
|
enemy_data
|
|
|
|
}),
|
|
|
@ -1234,8 +1258,6 @@ impl Maps { |
|
|
|
}).flatten().collect(),
|
|
|
|
map_variants: map_variants,
|
|
|
|
};
|
|
|
|
println!("loading maps: {:?}", maps.map_variants);
|
|
|
|
println!("loading objects: {:?}", maps.object_data);
|
|
|
|
maps
|
|
|
|
}
|
|
|
|
|
|
|
@ -1244,7 +1266,6 @@ impl Maps { |
|
|
|
}
|
|
|
|
|
|
|
|
pub fn object_by_id(&self, id: usize) -> Result<MapObject, MapsError> {
|
|
|
|
println!("{:?}", self.object_data[id]);
|
|
|
|
self.object_data[id].ok_or(MapsError::InvalidObjectId(id))
|
|
|
|
}
|
|
|
|
|
|
|
|