1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
//! Structs and functions to interact with the data of dungeons, dungeon groups and fixed rooms
//! in a general context.
use crate::api::overlay::OverlayLoadLease;
use crate::ffi;
use core::mem::MaybeUninit;
/// A dungeon ID with associated methods to get metadata.
///
/// Use the associated constants or the [`Self::new`] method to get instances of this.
pub type DungeonGroupId = ffi::dungeon_group_id;
impl Copy for DungeonGroupId {}
/// This impl provides general metadata about dungeons in the game.
impl DungeonGroupId {
/// Returns the ID struct for the dungeon group with the given ID.
///
/// # Safety
/// The caller must make sure the ID is valid (refers to an existing dungeon group),
/// otherwise this is UB.
pub const unsafe fn new(id: u32) -> Self {
Self(id)
}
/// Returns the ID of this dungeon group.
pub const fn id(&self) -> u32 {
self.0
}
}
impl From<DungeonGroupId> for u32 {
fn from(v: DungeonGroupId) -> Self {
v.0
}
}
/// A dungeon group ID with associated methods to get metadata.
///
/// Use the associated constants or the [`Self::new`] method to get instances of this.
pub type DungeonId = ffi::dungeon_id;
impl Copy for DungeonId {}
/// This impl provides general metadata about dungeons in the game.
impl DungeonId {
/// Returns the ID struct for the dungeon with the given ID.
///
/// # Safety
/// The caller must make sure the ID is valid (refers to an existing dungeon),
/// otherwise this is UB.
pub const unsafe fn new(id: u32) -> Self {
Self(id)
}
/// Returns the ID of this dungeon.
pub const fn id(&self) -> u32 {
self.0
}
/// Returns the number of floors of the given dungeon.
///
/// The result is hardcoded for certain dungeons, such as dojo mazes.
pub fn number_floors(&self) -> i32 {
unsafe { ffi::GetNbFloors(*self) }
}
/// Returns the dungeon group associated to the given dungeon.
///
/// For IDs greater or equal to [`DungeonId::DUNGEON_NORMAL_FLY_MAZE`],
/// returns [`DungeonGroupId::DGROUP_MAROWAK_DOJO`].
pub fn group(&self) -> DungeonGroupId {
unsafe { ffi::GetDungeonGroup(*self) }
}
/// Given a dungeon ID, returns the total amount of floors summed by all the previous dungeons
/// in its group.
///
/// The value is normally pulled from
/// [`ffi::dungeon_data_list_entry::n_preceding_floors_group`], except for dungeons with an
/// ID >= [`DungeonId::DUNGEON_NORMAL_FLY_MAZE`], for which this function always returns 0.
pub fn number_preceding_floors(&self) -> i32 {
unsafe { ffi::GetNbPrecedingFloors(*self) }
}
/// Returns the total amount of floors among all the dungeons in the dungeon group of the
/// specified dungeon.
pub fn number_floors_in_group(&self) -> i32 {
unsafe { ffi::GetNbFloorsDungeonGroup(*self) }
}
/// Given this dungeon ID and a floor number, returns a struct with the corresponding dungeon
/// group and floor number in that group.
///
/// The function normally uses the data in mappa_s.bin to calculate the result, but there's
/// some dungeons (such as dojo mazes) that have hardcoded return values.
pub fn conv_floor_to_group_floor(&self, dungeon_floor_number: u8) -> (DungeonGroupId, u8) {
let mut out: MaybeUninit<ffi::dungeon_group_and_group_floor> = MaybeUninit::zeroed();
let mut inp = ffi::dungeon_floor_pair {
dungeon_id: ffi::dungeon_id_8 {
_bitfield_align_1: [],
_bitfield_1: ffi::dungeon_id_8::new_bitfield_1(*self),
},
floor_id: dungeon_floor_number,
};
unsafe {
ffi::DungeonFloorToGroupFloor(out.as_mut_ptr(), &mut inp);
let out = out.assume_init();
(out.group_id.val(), out.group_floor)
}
}
/// Returns whether this dungeon is considered as going upward or not
pub fn goes_up(&self) -> bool {
unsafe { ffi::DungeonGoesUp(*self) > 0 }
}
/// Returns the maximum rescue attempts allowed in this dungeon,
/// or -1 if rescues are disabled.
pub fn get_max_rescue_attempts(&self) -> i8 {
unsafe { ffi::GetMaxRescueAttempts(*self) }
}
/// Returns true if the flag that allows changing leaders is set in the restrictions of this
/// dungeon.
pub fn get_leader_change_flag(&self) -> bool {
unsafe { ffi::GetLeaderChangeFlag(*self) > 0 }
}
/// Returns whether this dungeon has a joined at location between
/// [`DungeonId::DUNGEON_JOINED_AT_BIDOOF`] and [`DungeonId::DUNGEON_DUMMY_0xE3`].
pub fn is_special_joined_at_location(&self) -> bool {
unsafe {
ffi::JoinedAtRangeCheck(ffi::dungeon_id_8 {
_bitfield_align_1: [],
_bitfield_1: ffi::dungeon_id_8::new_bitfield_1(*self),
}) > 0
}
}
/// Returns whether a certain joined_at field value is equal to [`DungeonId::DUNGEON_BEACH`] or
/// is between [`DungeonId::DUNGEON_DUMMY_0xEC`] and [`DungeonId::DUNGEON_DUMMY_0xF0`].
pub fn is_special_joined_at_location2(&self) -> bool {
unsafe {
ffi::JoinedAtRangeCheck2(ffi::dungeon_id_8 {
_bitfield_align_1: [],
_bitfield_1: ffi::dungeon_id_8::new_bitfield_1(*self),
}) > 0
}
}
/// Checks if enemy Treasure Box drops are enabled in the dungeon.
pub fn are_treasure_box_drops_enabled(&self) -> bool {
unsafe { ffi::TreasureBoxDropsEnabled(*self) > 0 }
}
}
impl From<DungeonId> for u32 {
fn from(v: DungeonId) -> Self {
v.0
}
}
/// A fixed room ID with associated methods to get metadata.
///
/// Use the associated constants or the [`Self::new`] method to get instances of this.
pub type FixedRoomId = ffi::fixed_room_id;
impl Copy for FixedRoomId {}
/// This impl provides general metadata about fixed rooms in the game.
impl FixedRoomId {
/// Returns the ID struct for the fixed room with the given ID.
///
/// # Safety
/// The caller must make sure the ID is valid (refers to an existing fixed room),
/// otherwise this is UB.
pub const unsafe fn new(id: u32) -> Self {
Self(id)
}
/// Returns the ID of this fixed room.
pub const fn id(&self) -> u32 {
self.0
}
/// Checks if this ID corresponds to a fixed, full-floor layout.
pub fn is_full_floor_fixed_room(&self, _ov29: &OverlayLoadLease<29>) -> bool {
// SAFETY:We hold a valid mutable reference to the global dungeon struct.
unsafe { ffi::IsNotFullFloorFixedRoom(*self) == 0 }
}
}
impl From<FixedRoomId> for u32 {
fn from(v: FixedRoomId) -> Self {
v.0
}
}