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.

428 lines
20 KiB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
  1. use log::warn;
  2. use std::io::Cursor;
  3. use std::convert::Into;
  4. use std::path::PathBuf;
  5. use std::io::{Read};
  6. use std::fs::File;
  7. use byteorder::{LittleEndian, ReadBytesExt};
  8. use rand::Rng;
  9. use crate::ship::monster::MonsterType;
  10. use crate::ship::room::Episode;
  11. #[derive(Debug, Copy, Clone)]
  12. struct RawMapEnemy {
  13. id: u32,
  14. _unknown1: u16,
  15. children: u16,
  16. _unknown3: u16,
  17. _unknown4: u16,
  18. section: u16,
  19. wave_idd: u16,
  20. wave_id: u32,
  21. x: f32,
  22. y: f32,
  23. z: f32,
  24. xrot: u32,
  25. yrot: u32,
  26. zrot: u32,
  27. _field1: u32,
  28. field2: u32,
  29. _field3: u32,
  30. _field4: u32,
  31. _field5: u32,
  32. skin: u32,
  33. _field6: u32
  34. }
  35. impl RawMapEnemy {
  36. fn from_byte_stream<R: Read>(cursor: &mut R) -> Result<RawMapEnemy, std::io::Error> {
  37. Ok(RawMapEnemy {
  38. id: cursor.read_u32::<LittleEndian>()?,
  39. _unknown1: cursor.read_u16::<LittleEndian>()?,
  40. children: cursor.read_u16::<LittleEndian>()?,
  41. _unknown3: cursor.read_u16::<LittleEndian>()?,
  42. _unknown4: cursor.read_u16::<LittleEndian>()?,
  43. section: cursor.read_u16::<LittleEndian>()?,
  44. wave_idd: cursor.read_u16::<LittleEndian>()?,
  45. wave_id: cursor.read_u32::<LittleEndian>()?,
  46. x: cursor.read_f32::<LittleEndian>()?,
  47. y: cursor.read_f32::<LittleEndian>()?,
  48. z: cursor.read_f32::<LittleEndian>()?,
  49. xrot: cursor.read_u32::<LittleEndian>()?,
  50. yrot: cursor.read_u32::<LittleEndian>()?,
  51. zrot: cursor.read_u32::<LittleEndian>()?,
  52. _field1: cursor.read_u32::<LittleEndian>()?,
  53. field2: cursor.read_u32::<LittleEndian>()?,
  54. _field3: cursor.read_u32::<LittleEndian>()?,
  55. _field4: cursor.read_u32::<LittleEndian>()?,
  56. _field5: cursor.read_u32::<LittleEndian>()?,
  57. skin: cursor.read_u32::<LittleEndian>()?,
  58. _field6: cursor.read_u32::<LittleEndian>()?,
  59. })
  60. }
  61. }
  62. #[derive(Debug)]
  63. enum MapEnemyError {
  64. UnknownEnemyId(u32),
  65. }
  66. #[derive(Debug, Copy, Clone)]
  67. pub struct MapEnemy {
  68. pub monster: MonsterType,
  69. hp: u32,
  70. // other stats from bp.n
  71. dead: bool,
  72. }
  73. impl MapEnemy {
  74. fn from_raw(enemy: RawMapEnemy, episode: &Episode /*, battleparam */) -> Result<MapEnemy, MapEnemyError> {
  75. let monster = match (enemy, episode) {
  76. (RawMapEnemy {id: 64, ..}, _) => MonsterType::Hildebear,
  77. (RawMapEnemy {id: 65, ..}, Episode::Four) => MonsterType::SandRappy,
  78. (RawMapEnemy {id: 65, ..}, _) => MonsterType::RagRappy,
  79. (RawMapEnemy {id: 66, ..}, _) => MonsterType::Monest,
  80. (RawMapEnemy {id: 67, field2: 0, ..}, _) => MonsterType::SavageWolf,
  81. (RawMapEnemy {id: 67, ..}, _) => MonsterType::BarbarousWolf,
  82. (RawMapEnemy {id: 68, skin: 0, ..}, _) => MonsterType::Booma,
  83. (RawMapEnemy {id: 68, skin: 1, ..}, _) => MonsterType::Gobooma,
  84. (RawMapEnemy {id: 68, skin: 2, ..}, _) => MonsterType::Gigobooma,
  85. (RawMapEnemy {id: 96, ..}, _) => MonsterType::GrassAssassin,
  86. (RawMapEnemy {id: 97, ..}, Episode::Two) => MonsterType::DelLily,
  87. (RawMapEnemy {id: 97, ..}, _) => MonsterType::PoisonLily,
  88. (RawMapEnemy {id: 98, ..}, _) => MonsterType::NanoDragon,
  89. (RawMapEnemy {id: 99, skin: 0, ..}, _) => MonsterType::EvilShark,
  90. (RawMapEnemy {id: 99, skin: 1, ..}, _) => MonsterType::PalShark,
  91. (RawMapEnemy {id: 99, skin: 2, ..}, _) => MonsterType::GuilShark,
  92. (RawMapEnemy {id: 100, ..}, _) => MonsterType::PofuillySlime,
  93. (RawMapEnemy {id: 101, ..}, _) => MonsterType::PanArms,
  94. (RawMapEnemy {id: 128, skin: 0, ..}, _) => MonsterType::Dubchic,
  95. (RawMapEnemy {id: 128, skin: 1, ..}, _) => MonsterType::Gillchic,
  96. (RawMapEnemy {id: 129, ..}, _) => MonsterType::Garanz,
  97. (RawMapEnemy {id: 130, field2: 0, ..}, _) => MonsterType::SinowBeat,
  98. (RawMapEnemy {id: 130, ..}, _) => MonsterType::SinowGold,
  99. (RawMapEnemy {id: 131, ..}, _) => MonsterType::Canadine,
  100. (RawMapEnemy {id: 132, ..}, _) => MonsterType::Canane,
  101. (RawMapEnemy {id: 133, ..}, _) => MonsterType::DubchicSwitch,
  102. (RawMapEnemy {id: 160, ..}, _) => MonsterType::Delsaber,
  103. (RawMapEnemy {id: 161, ..}, _) => MonsterType::ChaosSorcerer,
  104. (RawMapEnemy {id: 162, ..}, _) => MonsterType::DarkGunner,
  105. (RawMapEnemy {id: 164, ..}, _) => MonsterType::ChaosBringer,
  106. (RawMapEnemy {id: 165, ..}, _) => MonsterType::DarkBelra,
  107. (RawMapEnemy {id: 166, skin: 0, ..}, _) => MonsterType::Dimenian,
  108. (RawMapEnemy {id: 166, skin: 1, ..}, _) => MonsterType::LaDimenian,
  109. (RawMapEnemy {id: 166, skin: 2, ..}, _) => MonsterType::SoDimenian,
  110. (RawMapEnemy {id: 167, ..}, _) => MonsterType::Bulclaw,
  111. (RawMapEnemy {id: 168, ..}, _) => MonsterType::Claw,
  112. (RawMapEnemy {id: 192, ..}, Episode::One) => MonsterType::Dragon,
  113. (RawMapEnemy {id: 192, ..}, Episode::Two) => MonsterType::GalGryphon,
  114. (RawMapEnemy {id: 193, ..}, _) => MonsterType::DeRolLe,
  115. (RawMapEnemy {id: 194, ..}, _) => MonsterType::VolOptPartA,
  116. (RawMapEnemy {id: 197, ..}, _) => MonsterType::VolOpt,
  117. (RawMapEnemy {id: 200, ..}, _) => MonsterType::DarkFalz,
  118. (RawMapEnemy {id: 202, ..}, _) => MonsterType::Olga,
  119. (RawMapEnemy {id: 203, ..}, _) => MonsterType::BarbaRay,
  120. (RawMapEnemy {id: 204, ..}, _) => MonsterType::GolDragon,
  121. (RawMapEnemy {id: 212, skin: 0, ..}, _) => MonsterType::SinowBeril,
  122. (RawMapEnemy {id: 212, skin: 1, ..}, _) => MonsterType::SinowSpigell,
  123. (RawMapEnemy {id: 213, skin: 0, ..}, _) => MonsterType::Merillias,
  124. (RawMapEnemy {id: 213, skin: 1, ..}, _) => MonsterType::Meriltas,
  125. (RawMapEnemy {id: 214, skin: 0, ..}, _) => MonsterType::Mericarol,
  126. (RawMapEnemy {id: 214, skin: 1, ..}, _) => MonsterType::Merikle,
  127. (RawMapEnemy {id: 214, skin: 2, ..}, _) => MonsterType::Mericus,
  128. (RawMapEnemy {id: 215, skin: 0, ..}, _) => MonsterType::UlGibbon,
  129. (RawMapEnemy {id: 215, skin: 1, ..}, _) => MonsterType::ZolGibbon,
  130. (RawMapEnemy {id: 216, ..}, _) => MonsterType::Gibbles,
  131. (RawMapEnemy {id: 217, ..}, _) => MonsterType::Gee,
  132. (RawMapEnemy {id: 218, ..}, _) => MonsterType::GiGue,
  133. (RawMapEnemy {id: 219, ..}, _) => MonsterType::Deldepth,
  134. (RawMapEnemy {id: 220, ..}, _) => MonsterType::Delbiter,
  135. (RawMapEnemy {id: 221, skin: 0, ..}, _) => MonsterType::Dolmdarl,
  136. (RawMapEnemy {id: 221, skin: 1, ..}, _) => MonsterType::Dolmolm,
  137. (RawMapEnemy {id: 222, ..}, _) => MonsterType::Morfos,
  138. (RawMapEnemy {id: 223, ..}, _) => MonsterType::ReconBox,
  139. (RawMapEnemy {id: 224, ..}, _) => MonsterType::Epsilon,
  140. (RawMapEnemy {id: 224, skin: 0, ..}, _) => MonsterType::SinowZoa,
  141. (RawMapEnemy {id: 224, skin: 1, ..}, _) => MonsterType::SinowZele,
  142. (RawMapEnemy {id: 225, ..}, _) => MonsterType::IllGill,
  143. (RawMapEnemy {id: 272, ..}, _) => MonsterType::Astark,
  144. (RawMapEnemy {id: 273, field2: 0, ..}, _) => MonsterType::SatelliteLizard,
  145. (RawMapEnemy {id: 273, ..}, _) => MonsterType::Yowie,
  146. (RawMapEnemy {id: 274, ..}, _) => MonsterType::MerissaA,
  147. (RawMapEnemy {id: 275, ..}, _) => MonsterType::Girtablulu,
  148. (RawMapEnemy {id: 276, ..}, _) => MonsterType::Zu,
  149. (RawMapEnemy {id: 277, skin: 0, ..}, _) => MonsterType::Boota,
  150. (RawMapEnemy {id: 277, skin: 1, ..}, _) => MonsterType::ZeBoota,
  151. (RawMapEnemy {id: 277, skin: 2, ..}, _) => MonsterType::BaBoota,
  152. (RawMapEnemy {id: 278, ..}, _) => MonsterType::Dorphon,
  153. (RawMapEnemy {id: 279, skin: 0, ..}, _) => MonsterType::Goran,
  154. (RawMapEnemy {id: 279, skin: 1, ..}, _) => MonsterType::PyroGoran,
  155. (RawMapEnemy {id: 279, skin: 2, ..}, _) => MonsterType::GoranDetonator,
  156. (RawMapEnemy {id: 281, skin: 0, ..}, _) => MonsterType::SaintMillion,
  157. (RawMapEnemy {id: 281, skin: 1, ..}, _) => MonsterType::Shambertin,
  158. _ => return Err(MapEnemyError::UnknownEnemyId(enemy.id))
  159. };
  160. Ok(MapEnemy {
  161. monster: monster,
  162. hp: 0,
  163. dead: false,
  164. })
  165. }
  166. fn new(monster: MonsterType) -> MapEnemy {
  167. MapEnemy {
  168. monster: monster,
  169. hp: 0,
  170. dead: false,
  171. }
  172. }
  173. }
  174. #[derive(Debug)]
  175. enum MapVariantMode {
  176. Online,
  177. Offline,
  178. }
  179. #[derive(Debug)]
  180. enum MapVariantType {
  181. Pioneer2Ep1,
  182. Forest1,
  183. Forest2,
  184. Caves1,
  185. Caves2,
  186. Caves3,
  187. Mines1,
  188. Mines2,
  189. Ruins1,
  190. Ruins2,
  191. Ruins3,
  192. Dragon,
  193. DeRolLe,
  194. VolOpt,
  195. DarkFalz,
  196. }
  197. #[derive(Debug)]
  198. struct MapVariant {
  199. map: MapVariantType,
  200. mode: MapVariantMode,
  201. major: u8,
  202. minor: u8,
  203. }
  204. impl MapVariant {
  205. fn new(map: MapVariantType, mode: MapVariantMode) -> MapVariant {
  206. let major = match map {
  207. MapVariantType::Pioneer2Ep1 => 0,
  208. MapVariantType::Forest1 | MapVariantType::Forest2 => 0,
  209. MapVariantType::Caves1 | MapVariantType::Caves2 | MapVariantType::Caves3 => rand::thread_rng().gen_range(0, 3),
  210. MapVariantType::Mines1 | MapVariantType::Mines2 => rand::thread_rng().gen_range(0, 3),
  211. MapVariantType::Ruins1 | MapVariantType::Ruins2 | MapVariantType::Ruins3 => rand::thread_rng().gen_range(0, 3),
  212. MapVariantType::Dragon | MapVariantType::DeRolLe | MapVariantType::VolOpt | MapVariantType::DarkFalz => 0,
  213. };
  214. let minor = match map {
  215. MapVariantType::Pioneer2Ep1 => 0,
  216. MapVariantType::Forest1 => rand::thread_rng().gen_range(0, 6),
  217. MapVariantType::Forest2 => rand::thread_rng().gen_range(0, 5),
  218. MapVariantType::Caves1 | MapVariantType::Caves2 | MapVariantType::Caves3 => rand::thread_rng().gen_range(0, 2),
  219. MapVariantType::Mines1 | MapVariantType::Mines2 => rand::thread_rng().gen_range(0, 2),
  220. MapVariantType::Ruins1 | MapVariantType::Ruins2 | MapVariantType::Ruins3 => rand::thread_rng().gen_range(0, 2),
  221. MapVariantType::Dragon | MapVariantType::DeRolLe | MapVariantType::VolOpt | MapVariantType::DarkFalz => 0,
  222. };
  223. MapVariant {
  224. map: map,
  225. mode: mode,
  226. major: major,
  227. minor: minor,
  228. }
  229. }
  230. fn dat_file(&self) -> String {
  231. match self.map {
  232. MapVariantType::Pioneer2Ep1 => "data/maps/map_city00_00e.dat".into(),
  233. MapVariantType::Forest1 => format!("data/maps/map_forest01_0{}e.dat", self.minor),
  234. MapVariantType::Forest2 => format!("data/maps/map_forest02_0{}e.dat", self.minor),
  235. MapVariantType::Caves1 => format!("data/maps/map_cave01_0{}_0{}e.dat", self.major, self.minor),
  236. MapVariantType::Caves2 => format!("data/maps/map_cave02_0{}_0{}e.dat", self.major, self.minor),
  237. MapVariantType::Caves3 => format!("data/maps/map_cave03_0{}_0{}e.dat", self.major, self.minor),
  238. MapVariantType::Mines1 => format!("data/maps/map_machine01_0{}_0{}e.dat", self.major, self.minor),
  239. MapVariantType::Mines2 => format!("data/maps/map_machine02_0{}_0{}e.dat", self.major, self.minor),
  240. MapVariantType::Ruins1 => format!("data/maps/map_ancient01_0{}_0{}e.dat", self.major, self.minor),
  241. MapVariantType::Ruins2 => format!("data/maps/map_ancient02_0{}_0{}e.dat", self.major, self.minor),
  242. MapVariantType::Ruins3 => format!("data/maps/map_ancient03_0{}_0{}e.dat", self.major, self.minor),
  243. MapVariantType::Dragon => "data/maps/map_boss01e.dat".into(),
  244. MapVariantType::DeRolLe => "data/maps/map_boss02e.dat".into(),
  245. MapVariantType::VolOpt => "data/maps/map_boss03e.dat".into(),
  246. MapVariantType::DarkFalz => "data/maps/map_boss04e.dat".into(),
  247. }
  248. }
  249. fn pkt_header(&self) -> [u8; 2] {
  250. [self.major, self.minor]
  251. }
  252. }
  253. fn enemy_data_from_map_data(path: PathBuf, episode: &Episode) -> Vec<Option<MapEnemy>> {
  254. let mut cursor = File::open(path).unwrap();
  255. let mut enemy_data = Vec::new();
  256. while let Ok(enemy) = RawMapEnemy::from_byte_stream(&mut cursor) {
  257. let new_enemy = MapEnemy::from_raw(enemy, episode);
  258. enemy_data.append(&mut new_enemy
  259. .map_or(vec![None], |monster| {
  260. let mut monsters = Vec::new();
  261. monsters.push(Some(monster));
  262. match monster.monster {
  263. MonsterType::Monest => {
  264. for _ in 0..30 {
  265. monsters.push(Some(MapEnemy::new(MonsterType::Mothmant)));
  266. }
  267. },
  268. MonsterType::PofuillySlime => {
  269. for _ in 0..4 {
  270. monsters.push(Some(MapEnemy::new(MonsterType::PofuillySlime)));
  271. }
  272. },
  273. MonsterType::PanArms => {
  274. monsters.push(Some(MapEnemy::new(MonsterType::Hidoom)));
  275. monsters.push(Some(MapEnemy::new(MonsterType::Migium)));
  276. },
  277. MonsterType::SinowBeat => {
  278. for _ in 0..4 {
  279. monsters.push(Some(MapEnemy::new(MonsterType::SinowBeat)));
  280. }
  281. },
  282. MonsterType::SinowGold => {
  283. for _ in 0..4 {
  284. monsters.push(Some(MapEnemy::new(MonsterType::SinowGold)));
  285. }
  286. },
  287. MonsterType::Canane => {
  288. for _ in 0..8 {
  289. monsters.push(Some(MapEnemy::new(MonsterType::RingCanadine)));
  290. }
  291. },
  292. MonsterType::ChaosSorcerer => {
  293. monsters.push(Some(MapEnemy::new(MonsterType::BeeR)));
  294. monsters.push(Some(MapEnemy::new(MonsterType::BeeL)));
  295. },
  296. MonsterType::Bulclaw => {
  297. for _ in 0..4 {
  298. monsters.push(Some(MapEnemy::new(MonsterType::Claw)));
  299. }
  300. },
  301. MonsterType::DeRolLe => {
  302. for _ in 0..10 {
  303. monsters.push(Some(MapEnemy::new(MonsterType::DeRolLeBody)));
  304. }
  305. for _ in 0..9 {
  306. monsters.push(Some(MapEnemy::new(MonsterType::DeRolLeMine)));
  307. }
  308. },
  309. MonsterType::VolOptPartA => {
  310. for _ in 0..6 {
  311. monsters.push(Some(MapEnemy::new(MonsterType::VolOptPillar)));
  312. }
  313. for _ in 0..24 {
  314. monsters.push(Some(MapEnemy::new(MonsterType::VolOptMonitor)));
  315. }
  316. for _ in 0..2 {
  317. monsters.push(Some(MapEnemy::new(MonsterType::VolOptUnused)));
  318. }
  319. monsters.push(Some(MapEnemy::new(MonsterType::VolOptAmp)));
  320. monsters.push(Some(MapEnemy::new(MonsterType::VolOptCore)));
  321. monsters.push(Some(MapEnemy::new(MonsterType::VolOptUnused)));
  322. },
  323. // TOOD: this cares about difficulty (theres an ult-specific darvant?)
  324. MonsterType::DarkFalz => {
  325. for _ in 0..509 {
  326. monsters.push(Some(MapEnemy::new(MonsterType::Darvant)));
  327. }
  328. monsters.push(Some(MapEnemy::new(MonsterType::DarkFalz3)));
  329. monsters.push(Some(MapEnemy::new(MonsterType::DarkFalz2)));
  330. monsters.push(Some(MapEnemy::new(MonsterType::DarkFalz1)));
  331. },
  332. _ => {
  333. warn!("children: {}", enemy.children);
  334. for _ in 0..enemy.children {
  335. monsters.push(Some(MapEnemy::new(monster.monster)));
  336. }
  337. }
  338. }
  339. monsters
  340. }));
  341. }
  342. enemy_data
  343. }
  344. #[derive(Debug)]
  345. pub struct Maps {
  346. map_variants: [MapVariant; 15],
  347. enemy_data: Vec<Option<MapEnemy>>
  348. }
  349. impl Maps {
  350. pub fn new(episode: Episode) -> Maps {
  351. warn!("new maps ep: {:?}", episode);
  352. let map_variants = match episode {
  353. Episode::One => {
  354. [MapVariant::new(MapVariantType::Pioneer2Ep1, MapVariantMode::Online),
  355. MapVariant::new(MapVariantType::Forest1, MapVariantMode::Online),
  356. MapVariant::new(MapVariantType::Forest2, MapVariantMode::Online),
  357. MapVariant::new(MapVariantType::Caves1, MapVariantMode::Online),
  358. MapVariant::new(MapVariantType::Caves2, MapVariantMode::Online),
  359. MapVariant::new(MapVariantType::Caves3, MapVariantMode::Online),
  360. MapVariant::new(MapVariantType::Mines1, MapVariantMode::Online),
  361. MapVariant::new(MapVariantType::Mines2, MapVariantMode::Online),
  362. MapVariant::new(MapVariantType::Ruins1, MapVariantMode::Online),
  363. MapVariant::new(MapVariantType::Ruins2, MapVariantMode::Online),
  364. MapVariant::new(MapVariantType::Ruins3, MapVariantMode::Online),
  365. MapVariant::new(MapVariantType::Dragon, MapVariantMode::Online),
  366. MapVariant::new(MapVariantType::DeRolLe, MapVariantMode::Online),
  367. MapVariant::new(MapVariantType::VolOpt, MapVariantMode::Online),
  368. MapVariant::new(MapVariantType::DarkFalz, MapVariantMode::Online),
  369. ]
  370. },
  371. _ => panic!()
  372. };
  373. let mut maps = Maps {
  374. enemy_data: map_variants.iter().fold(Vec::new(), |mut enemy_data, map_variant| {
  375. enemy_data.append(&mut enemy_data_from_map_data(map_variant.dat_file().into(), &episode));
  376. enemy_data
  377. }),
  378. map_variants: map_variants,
  379. };
  380. maps
  381. }
  382. pub fn enemy_by_id(&self, id: usize) -> MapEnemy {
  383. self.enemy_data[id].unwrap()
  384. }
  385. pub fn map_headers(&self) -> [u32; 0x20] {
  386. self.map_variants.iter()
  387. .enumerate()
  388. .fold([0; 0x20], |mut header, (i, map_variant)| {
  389. let [major, minor] = map_variant.pkt_header();
  390. header[i*2] = major as u32;
  391. header[i*2 + 1] = minor as u32;
  392. header
  393. })
  394. }
  395. }