use std::borrow::Cow;
use shared::*;
use crate::{dltx::DLString, fd4::FD4Time, rva};
#[repr(C)]
pub struct MenuMan {
_vftable: usize,
_unk08: [u8; 0x8],
_unk10: u8,
_unk11: u8,
_unk12: u8,
_unk13: u8,
pub draw_layout_on_cursor: bool,
pub draw_layout_only_last: bool,
pub draw_layout_display_position: bool,
pub draw_layout_only_register: bool,
pub show_action_button: bool,
pub hide_fe: bool,
pub hide_all_menus: bool,
pub flags: [i32; 1000],
_unkfc0: u64,
pub move_map_step_number: i32,
pub move_map_step_update_time: f32,
_unkfd0: [u8; 0x4],
pub talk_message_id: i32,
pub enable_talk_icon: bool,
_unkfd9: [u8; 0x3],
_unkfdc: u8,
pub talk_shop_message_id: i32,
_unkfe4: u32,
_unkfe8: u32,
_unkfec: u32,
_unkff0: u8,
_unkff4: u32,
_unkff8: u32,
_unkffc: u8,
_unk1000: u32,
pub map_action_data_invisible_time: f32,
_unk1008: [u8; 0x8],
pub action_spots: [MaybeEmpty<MenuActionSpot>; 6],
_unk11f0: u64,
_unk11f8: u32,
_unk1200: u64,
_unk1208: u64,
_unk1210: u64,
_unk1218: u64,
_unk1220: u32,
_unk1224: u16,
_unk1228: u32,
_unk122c: [u8; 0x4],
_unk1230: u32,
_unk1234: u32,
_unk1238: u32,
_unk123c: u32,
_unk1240: u64,
_unk1248: u64,
_unk1250: u32,
_unk1254: u16,
_unk1256: [u8; 0x2],
_unk1258: u32,
_unk125c: [u8; 0x4],
pub drop_equip_type: i32,
pub drop_equip_id: i32,
pub drop_durability: i32,
pub drop_quantity: i32,
_unk1270: u64,
_unk1278: u64,
_unk1280: u8,
_unk1284: u32,
_unk1288: u32,
_unk128c: u32,
_unk1290: u32,
_unk1294: u8,
_unk1295: [u8; 0x3],
_unk1298: UnknownStruct<0x1f0>,
_unk1488: u16,
_unk148a: u16,
_unk148c: u16,
_unk148e: u16,
_unk1490: u16,
_unk1492: u16,
_unk1494: u16,
_unk1496: u16,
_unk1498: UnknownStruct<0x1f0>,
pub floating_pc_gauges: [FloatingPcGauge; 0x7],
pub target_site_position: F32Vector3,
_unk1eac: u32,
_unk1eb0: u32,
_unk1eb4: u32,
pub target_site_visible: bool,
pub target_site_force_visible: bool,
_unk1eba: [u8; 0x6],
_unk1ec0: u32,
_unk1ec4: u32,
_unk1ec8: u32,
_unk1ecc: u32,
_unk1ed0: u32,
_unk1ed4: u32,
pub vfx_data_position: F32Vector2,
pub vfx_data_visible: bool,
_unk1ee1: [u8; 0xf],
_unk1ef0: UnknownStruct<0xb0>,
_unk1efa0: u64,
_unk1efa8: u16,
_unk1efaa: u8,
_unk1efb0: u64,
pub ugc_restricted: bool,
pub menu_info_data: MenuInfoData,
_unk2110: u8,
_unk2111: [u8; 0x7],
_unk2118: UnknownStruct<0x10>,
pub last_talk_id: i32,
_unk212c: u32,
_unk2130: u16,
_unk2132: u8,
_unk2133: [u8; 0x9],
_unk213c: u8,
_unk213d: [u8; 0x3],
_unk2140: [UnknownStruct<0x34>; 10],
pub shop_lineup_start_id: i32,
pub shop_lineup_end_id: i32,
pub enable_shop_test: bool,
pub enemy_gauges: [MaybeEmpty<EnemyGauge>; 16],
_unk2614: u32,
_unk2618: u32,
_unk261c: u32,
_unk2620: u32,
_unk2624: u32,
_unk2628: [u8; 8],
_unk2630: UnknownStruct<0x4c0>,
_unk2af0: u32,
_unk2af4: [u8; 0x54],
_unk2b48: u32,
_unk2b4c: u32,
_unk2b50: u32,
_unk2b54: u32,
_unk2b58: u32,
_unk2b5c: u32,
_unk2b60: u32,
_unk2b64: [u8; 0x4],
_unk2b68: [UnknownStruct<0x10>; 2],
_menu_user_texture_data: [u32; 0x20],
pub miniboss_gauge_name_id: i32,
_unk2c0c: u32,
pub miniboss_gauge_my_damage: i32,
pub miniboss_gauge_net_damage: i32,
_unk2c18: u8,
_unk2c1c: u32,
_unk2c20: u64,
_unk2c28: u64,
_unk2c30: u64,
_unk2c38: u64,
_unk2c40: u64,
_unk2c48: u64,
_unk2c50: u64,
_unk2c58: u64,
_unk2c60: u64,
_unk2c68: u64,
_unk2c70: u64,
_unk2c78: u64,
_unk2c80: u64,
_unk2c88: u64,
_unk2c90: u64,
_unk2c98: u64,
_unk2d00: u64,
_unk2d08: u64,
pub miniboss_gauge_name_id_2: i32,
_unk2cb4: [u8; 0x15c],
pub boss_gauge_name_id: i32,
_unk2e14: u32,
pub boss_gauge_my_damage: i32,
pub boss_gauge_net_damage: i32,
_unk2e20: u8,
_unk2e24: u32,
_unk2e28: u64,
_unk2e30: u64,
_unk2e38: u64,
_unk2e40: u64,
_unk2e48: u64,
_unk2e50: u64,
_unk2e58: u64,
_unk2e60: u64,
_unk2e68: u64,
_unk2e70: u64,
_unk2e78: u64,
_unk2e80: u64,
_unk2e88: u64,
_unk2e90: u64,
_unk2e98: u32,
_unk2e9c: u32,
_unk2ea0: u32,
_unk2ea4: u32,
_unk2ea8: u32,
_unk2eac: u32,
_unk2eb0: u32,
_unk2eb4: u32,
pub boss_gauge_name_id_2: i32,
_unk2ebc: [u8; 0x14c],
_unk3008: u32,
_unk3010: u32,
pub select_equip_info_type: i32,
pub select_equip_info_id: i32,
pub select_equip_info_durability: i32,
_unk3020: u32,
pub condition_message_ids: [i32; 6],
_unk303c: [u32; 6],
pub current_condition_message_id: i32,
pub next_condition_message_id: i32,
_unk305c: u8,
_unk3060: i32,
_unk3064: u8,
_unk3068: i32,
_unk306c: i32,
_unk3070: u32,
_unk3074: u8,
pub start_tab_animation_play_speed: f32,
_unk307c: u8,
_unk3080: UnknownPtr,
_unk3088: u64,
_unk3090: i32,
_unk3094: u32,
_unk3098: i32,
_unk309c: u8,
_unk30a0: u64,
_unk30a8: u64,
_unk30b0: [u8; 0x88],
_unk3138: u64,
_unk3140: u64,
pub last_selected_top_menu_item: i32,
_unk314c: u32,
_unk3150: u64,
_unk3158: u32,
pub last_selected_equipment: i32,
_unk3160: u64,
pub last_selected_inventory_tab: i32,
pub last_selected_tab_scroll_position: i32,
pub last_selected_inventory_item: i32,
pub last_selected_inventory_item_scroll_position: i32,
_unk3178: u32,
pub last_selected_message_tab: i32,
_unk3180: u32,
pub last_selected_message_item: i32,
pub last_selected_message_item_scroll_position: i32,
pub last_selected_message_edit_mode: i32,
pub last_selected_option_tab: i32,
_unk3194: u32,
pub last_selected_option_item: i32,
_unk319c: u32,
_unk31a0: u64,
_unk31a8: u64,
_unk31b0: u64,
_unk31b8: u32,
_unk31bc: u8,
pub current_player_pad_index: i32,
pub desired_player_pad_index: i32,
_unk31c8: u8,
_unk31d0: u64,
_unk31d8: u32,
_unk31dc: [u8; 0x4],
_player_menu_ctrl: UnknownStruct<0x58>,
_unk3238: UnknownPtr,
_unk3240: FD4Time,
_unk3250: UnknownPtr,
_unk3258: [u8; 0x10],
_unk3268: UnknownPtr,
_unk3270: UnknownPtr,
_unk3278: UnknownStruct<0x88>,
_unk3300: u8,
_unk3308: u64,
}
impl MenuMan {
pub fn is_menu_mode(&self) -> bool {
self.flags[9] > 0
}
pub fn set_menu_mode(&mut self, enabled: bool) {
self.flags[0] = if enabled { 2 } else { 0 };
}
pub fn caption_flag(&self) -> i32 {
self.flags[0x37]
}
pub fn selected_inventory_id(&self) -> i32 {
self.flags[0x67]
}
pub fn drop_ret_inventory_id(&self) -> i32 {
self.flags[0x68]
}
pub fn selected_inventory_slot(&self) -> i32 {
self.flags[0x69]
}
pub fn inventory_page_state(&self) -> i32 {
self.flags[0x6a]
}
pub fn selected_sort_inventory_id(&self) -> i32 {
self.flags[0x6b]
}
pub fn disable_popup_menu(&self) -> i32 {
self.flags[0xb2]
}
pub fn set_disable_popup_menu(&mut self, value: i32) {
self.flags[0xb2] = value
}
pub fn menu_tab_type(&self) -> i32 {
self.flags[0x7d]
}
pub fn action_spots(&self) -> impl Iterator<Item = &MenuActionSpot> {
self.action_spots.iter().non_empty()
}
pub fn action_spots_mut(&mut self) -> impl Iterator<Item = &mut MenuActionSpot> {
self.action_spots.iter_mut().non_empty()
}
pub fn enemy_gauges(&self) -> impl Iterator<Item = &EnemyGauge> {
self.enemy_gauges.iter().non_empty()
}
pub fn enemy_gauge_mut(&mut self) -> impl Iterator<Item = &mut EnemyGauge> {
self.enemy_gauges.iter_mut().non_empty()
}
}
impl FromStatic for MenuMan {
fn name() -> Cow<'static, str> {
"MenuMan".into()
}
fn instance_ptr() -> fromsoftware_shared::InstanceResult<*mut Self> {
unsafe { shared::load_static_indirect(rva::get().sprj_menu_man_ptr) }
}
}
#[repr(C)]
pub struct MenuActionSpot {
pub unique_id: u32,
_unk04: [u8; 0xb],
_unk10: u64,
_unk18: u64,
pub distance: f32,
pub max_distance: f32,
_unk28: u64,
pub score: i32,
pub position: F32Vector2,
pub text_id: i32,
pub time_since_vanish: f32,
_unk44: u16,
_unk46: [u8; 0xa],
}
unsafe impl IsEmpty for MenuActionSpot {
fn is_empty(value: &MaybeEmpty<Self>) -> bool {
*unsafe { value.as_non_null().cast::<u32>().as_ref() } == 0
}
}
#[repr(C)]
pub struct FloatingPcGauge {
pub position: F32Vector3,
pub is_visible: bool,
pub is_shielded: bool,
pub display_permanently: bool,
_unkf: u8,
_unk10: u32,
_unk14: [u8; 0x4],
_string1: DLString,
_string2: DLString,
_unk78: u64,
pub damage_value: i32,
pub damage_value_display_timer: f32,
_unk88: u32,
_unk8c: u32,
_unk90: u8,
_unk91: [u8; 0x2],
pub force_visible: bool,
_unk94: u8,
_unk95: [u8; 0x3],
_unk98: u8,
_unka0: u64,
_unka8: u64,
_unkb0: u32,
_unkb8: u64,
_unkc0: u64,
_unkc8: u64,
_unkd0: u32,
_unkd4: u8,
_unkd8: u32,
_unke0: u64,
_unke8: u64,
_unkf0: u32,
_unkf8: u64,
_unk100: u64,
_unk108: u64,
_unk110: u32,
_unk114: u8,
_unk118: u32,
_unk11c: [u8; 0x4],
_unk120: u8,
}
#[repr(C)]
pub struct MenuInfoData {
pub current_stack_index: i32,
pub entries: [MenuInfoDataEntry; 5],
_unk148: u32,
}
#[repr(C)]
pub struct MenuInfoDataEntry {
_unk0: u32,
_unk4: u32,
_unk8: u32,
_unkc: u32,
_unk10: u32,
_unk14: u32,
pub system_message_id: i32,
_use_list_data: UnknownPtr,
_use_buffer_data: UnknownPtr,
pub is_in_use: bool,
pub use_tos_menu: bool,
pub use_any_pad_menu: bool,
pub button_type: i32,
pub user_id: i32,
_unk3c: u32,
}
#[repr(C, packed(4))]
pub struct EnemyGauge {
pub handle: u32,
pub draw_position: F32Vector2,
_unkc: [u8; 0x4],
pub is_lock: bool,
_unk11: u8,
pub is_visible: bool,
_unk13: u8,
pub damage_value: i32,
_unk18: u32,
_unk1c: u32,
pub time_since_vanish: f32,
pub time_since_appear: f32,
pub time_since_hit: f32,
}
unsafe impl IsEmpty for EnemyGauge {
fn is_empty(value: &MaybeEmpty<Self>) -> bool {
*unsafe { value.as_non_null().cast::<i32>().as_ref() } == -1
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn proper_sizes() {
assert_eq!(0x50, size_of::<MenuActionSpot>());
assert_eq!(0x128, size_of::<FloatingPcGauge>());
assert_eq!(0x40, size_of::<MenuInfoDataEntry>());
assert_eq!(0x150, size_of::<MenuInfoData>());
assert_eq!(0x3310, size_of::<MenuMan>());
}
}