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

  1. // TOOD: `pub(super) for most of these?`
  2. use std::io::Read;
  3. use byteorder::{LittleEndian, ReadBytesExt};
  4. use crate::room::Episode;
  5. use crate::area::MapArea;
  6. #[derive(Debug, Copy, Clone)]
  7. pub struct RawMapObject {
  8. otype: u16,
  9. _unknown1: u16,
  10. _unknown2: u32,
  11. _id: u16,
  12. _group: u16,
  13. _section: u16,
  14. _unknown3: u16,
  15. _x: f32,
  16. _y: f32,
  17. _z: f32,
  18. _xrot: u32,
  19. _yrot: u32,
  20. _zrot: u32,
  21. field1: f32,
  22. field2: f32,
  23. field3: f32,
  24. field4: u32,
  25. _field5: u32,
  26. _field6: u32,
  27. _field7: u32,
  28. }
  29. impl RawMapObject {
  30. pub fn from_byte_stream<R: Read>(cursor: &mut R) -> Result<RawMapObject, std::io::Error> {
  31. Ok(RawMapObject {
  32. otype: cursor.read_u16::<LittleEndian>()?,
  33. _unknown1: cursor.read_u16::<LittleEndian>()?,
  34. _unknown2: cursor.read_u32::<LittleEndian>()?,
  35. _id: cursor.read_u16::<LittleEndian>()?,
  36. _group: cursor.read_u16::<LittleEndian>()?,
  37. _section: cursor.read_u16::<LittleEndian>()?,
  38. _unknown3: cursor.read_u16::<LittleEndian>()?,
  39. _x: cursor.read_f32::<LittleEndian>()?,
  40. _y: cursor.read_f32::<LittleEndian>()?,
  41. _z: cursor.read_f32::<LittleEndian>()?,
  42. _xrot: cursor.read_u32::<LittleEndian>()?,
  43. _yrot: cursor.read_u32::<LittleEndian>()?,
  44. _zrot: cursor.read_u32::<LittleEndian>()?,
  45. field1: cursor.read_f32::<LittleEndian>()?,
  46. field2: cursor.read_f32::<LittleEndian>()?,
  47. field3: cursor.read_f32::<LittleEndian>()?,
  48. field4: cursor.read_u32::<LittleEndian>()?,
  49. _field5: cursor.read_u32::<LittleEndian>()?,
  50. _field6: cursor.read_u32::<LittleEndian>()?,
  51. _field7: cursor.read_u32::<LittleEndian>()?,
  52. })
  53. }
  54. }
  55. #[derive(Debug, Copy, Clone)]
  56. pub enum FixedBoxDropType {
  57. Weapon,
  58. Armor,
  59. Tool,
  60. Meseta,
  61. Random,
  62. Specific(u32), // TODO: ItemDropType
  63. }
  64. impl FixedBoxDropType {
  65. fn from_object(field1: f32, field2: f32, field3: f32, field4: u32) -> FixedBoxDropType {
  66. match (field1.round() as i32, field2.round() as i32, field3.round() as i32, field4) {
  67. (0, 1, 1, 0) => {
  68. FixedBoxDropType::Random
  69. },
  70. (0, 1, _, 0x4000000) => {
  71. FixedBoxDropType::Meseta
  72. },
  73. (0, 1, 1, _) => {
  74. FixedBoxDropType::Specific(field4)
  75. },
  76. (-1, 1, 1, _) => { // ???????
  77. FixedBoxDropType::Specific(field4)
  78. },
  79. (0, 1, 0, 0) => {
  80. FixedBoxDropType::Weapon
  81. },
  82. (0, 1, 0, 0x1000000) => {
  83. FixedBoxDropType::Armor
  84. },
  85. (0, 1, 0, 0x3000000) => {
  86. FixedBoxDropType::Tool
  87. },
  88. (1, _, _, _) => {
  89. FixedBoxDropType::Random
  90. },
  91. _ => {
  92. println!("this box state should not occur? {} {} {} {}", field1.round() as i32, field2.round() as i32, field3.round() as i32, field4);
  93. FixedBoxDropType::Random
  94. }
  95. }
  96. }
  97. }
  98. #[derive(Debug, Copy, Clone)]
  99. pub enum MapObjectType {
  100. Box,
  101. FixedBox(FixedBoxDropType),
  102. EnemyBox,
  103. EnemyFixedBox(FixedBoxDropType),
  104. RuinsBox,
  105. RuinsFixedBox(FixedBoxDropType),
  106. RuinsEnemyBox,
  107. RuinsEnemyFixedBox(FixedBoxDropType),
  108. CcaBox,
  109. CcaFixedBox(FixedBoxDropType),
  110. EmptyBox,
  111. EmptyFixedBox(FixedBoxDropType),
  112. RuinsEmptyBox,
  113. RuinsEmptyFixedBox,
  114. }
  115. #[derive(Debug, Copy, Clone)]
  116. pub struct MapObject {
  117. pub object: MapObjectType,
  118. pub map: MapArea,
  119. pub dropped_item: bool,
  120. //id: u32,
  121. }
  122. #[derive(Debug, Copy, Clone)]
  123. pub enum MapObjectError {
  124. UnknownObjectType(u16, RawMapObject),
  125. }
  126. impl MapObject {
  127. pub fn from_raw(raw: RawMapObject, episode: Episode, map_area: &MapArea) -> Result<MapObject, MapObjectError> {
  128. let object = match (raw, episode) {
  129. (RawMapObject {otype: 136, ..}, _) => MapObjectType::Box,
  130. (RawMapObject {otype: 145, ..}, _) => MapObjectType::EnemyBox,
  131. (RawMapObject {otype: 146, ..}, _) => MapObjectType::FixedBox(FixedBoxDropType::from_object(raw.field1, raw.field2, raw.field3, raw.field4)),
  132. (RawMapObject {otype: 147, ..}, _) => MapObjectType::EnemyFixedBox(FixedBoxDropType::from_object(raw.field1, raw.field2, raw.field3, raw.field4)),
  133. (RawMapObject {otype: 149, ..}, _) => MapObjectType::EmptyFixedBox(FixedBoxDropType::from_object(raw.field1, raw.field2, raw.field3, raw.field4)),
  134. (RawMapObject {otype: 353, ..}, _) => MapObjectType::RuinsFixedBox(FixedBoxDropType::from_object(raw.field1, raw.field2, raw.field3, raw.field4)),
  135. (RawMapObject {otype: 354, ..}, _) => MapObjectType::RuinsBox,
  136. (RawMapObject {otype: 355, ..}, _) => MapObjectType::RuinsEnemyFixedBox(FixedBoxDropType::from_object(raw.field1, raw.field2, raw.field3, raw.field4)),
  137. (RawMapObject {otype: 356, ..}, _) => MapObjectType::RuinsEnemyBox,
  138. (RawMapObject {otype: 357, ..}, _) => MapObjectType::RuinsEmptyBox,
  139. (RawMapObject {otype: 512, ..}, _) => MapObjectType::CcaBox,
  140. (RawMapObject {otype: 515, ..}, _) => MapObjectType::CcaFixedBox(FixedBoxDropType::from_object(raw.field1, raw.field2, raw.field3, raw.field4)),
  141. _ => return Err(MapObjectError::UnknownObjectType(raw.otype, raw))
  142. };
  143. Ok(MapObject {
  144. object,
  145. map: *map_area,
  146. dropped_item: false,
  147. })
  148. }
  149. }