From 6da6aa41b75eb1941c0d5caff02a910864242c10 Mon Sep 17 00:00:00 2001 From: jugeeya Date: Thu, 24 Mar 2022 23:48:50 -0700 Subject: [PATCH] Clippy Linter Fixes (#323) * initial * small fix * Update rust.yml * Update lib.rs * Format Rust code using rustfmt Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .github/workflows/rust.yml | 12 +- src/common/menu.rs | 546 +++++++++++---------- src/common/mod.rs | 277 ++++++----- src/lib.rs | 69 ++- src/training/buff.rs | 26 +- src/training/character_specific/mod.rs | 2 +- src/training/character_specific/steve.rs | 168 +++++-- src/training/charge.rs | 594 +++++++++++++++++------ src/training/ledge.rs | 6 +- src/training/mod.rs | 6 +- src/training/save_states.rs | 14 +- src/training/throw.rs | 2 +- training_mod_tui/src/lib.rs | 1 + 13 files changed, 1079 insertions(+), 644 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index bd7c8d4..3462110 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -116,20 +116,20 @@ jobs: Install the same way you would install a full release. - ## Installing on Ryujinx \n + ## Installing on Ryujinx - Instructions to get the beta working on Ryujinx.\n + Instructions to get the beta working on Ryujinx. - 1. Download a Skyline-tolerant build of Ryujinx, which can be found here: https://github.com/Ryujinx/Ryujinx/pull/2966#issuecomment-1003648371 \n + 1. Download a Skyline-tolerant build of Ryujinx, which can be found here: https://github.com/Ryujinx/Ryujinx/pull/2966#issuecomment-1003648371 - 2. Download the beta. https://github.com/jugeeya/UltimateTrainingModpack/releases/tag/beta \n + 2. Download the beta. https://github.com/jugeeya/UltimateTrainingModpack/releases/tag/beta - 3. The atmosphere folder from the beta zip is everything that should be in Ryujinx's mod folder. This means `%AppData%/Ryujinx/mods/contents/01006a800016e000` should have what `atmosphere/contents/01006a800016e000` has. \n + 3. The atmosphere folder from the beta zip is everything that should be in Ryujinx's mod folder. This means `%AppData%/Ryujinx/mods/contents/01006a800016e000` should have what `atmosphere/contents/01006a800016e000` has. - 4. You should be good to go after this. When in training mode, use Special+Uptaunt to bring up the menu. \n + 4. You should be good to go after this. When in training mode, use Special+Uptaunt to bring up the menu. files: > training_modpack_beta.zip - name: Upload zip as artifact diff --git a/src/common/menu.rs b/src/common/menu.rs index a738071..ee8f787 100644 --- a/src/common/menu.rs +++ b/src/common/menu.rs @@ -1,256 +1,290 @@ -use crate::common::*; -use crate::events::{Event, EVENT_QUEUE}; -use crate::training::frame_counter; -use crate::common::consts::get_menu_from_url; -use ramhorns::Template; -use skyline::info::get_program_id; -use skyline_web::{Background, BootDisplay, Webpage}; -use smash::lib::lua_const::*; -use std::fs; -use std::path::Path; -use crate::mkdir; - -static mut FRAME_COUNTER_INDEX: usize = 0; -const MENU_LOCKOUT_FRAMES: u32 = 15; -pub static mut QUICK_MENU_ACTIVE: bool = false; - -pub fn init() { - unsafe { - FRAME_COUNTER_INDEX = frame_counter::register_counter(); - write_menu(); - } -} - -pub unsafe fn menu_condition(module_accessor: &mut smash::app::BattleObjectModuleAccessor) -> bool { - // Only check for button combination if the counter is 0 (not locked out) - match frame_counter::get_frame_count(FRAME_COUNTER_INDEX) { - 0 => { - ControlModule::check_button_on(module_accessor, *CONTROL_PAD_BUTTON_SPECIAL) - && ControlModule::check_button_on_trriger( - module_accessor, - *CONTROL_PAD_BUTTON_APPEAL_HI, - ) - } - 1..MENU_LOCKOUT_FRAMES => false, - _ => { - // Waited longer than the lockout time, reset the counter so the menu can be opened again - frame_counter::full_reset(FRAME_COUNTER_INDEX); - false - } - } -} - -pub unsafe fn write_menu() { - let tpl = Template::new(include_str!("../templates/menu.html")).unwrap(); - - let overall_menu = get_menu(); - - let data = tpl.render(&overall_menu); - - // Now that we have the html, write it to file - // From skyline-web - let program_id = get_program_id(); - let htdocs_dir = "training_modpack"; - let menu_dir_path = Path::new("sd:/atmosphere/contents") - .join(&format!("{:016X}", program_id)) - .join(&format!("manual_html/html-document/{}.htdocs/", htdocs_dir)); - - let menu_html_path = menu_dir_path - .join("training_menu.html"); - - mkdir(menu_dir_path.to_str().unwrap().as_bytes().as_ptr(), 777); - let write_resp = fs::write(menu_html_path, data); - if write_resp.is_err() { - println!("Error!: {}", write_resp.err().unwrap()); - } -} - -const MENU_CONF_PATH: &str = "sd:/TrainingModpack/training_modpack_menu.conf"; - -pub fn set_menu_from_url(orig_last_url: &str) { - let last_url = &orig_last_url.replace("&save_defaults=1", ""); - unsafe { - MENU = get_menu_from_url(MENU, last_url); - - if MENU.quick_menu == OnOff::Off { - if is_emulator() { - skyline::error::show_error( - 0x69, - "Cannot use web menu on emulator.\n\0", - "Only the quick menu is runnable via emulator currently.\n\0", - ); - MENU.quick_menu = OnOff::On; - } - } - } - - if last_url.len() != orig_last_url.len() { - // Save as default - unsafe { - DEFAULT_MENU = MENU; - write_menu(); - } - let menu_defaults_conf_path = "sd:/TrainingModpack/training_modpack_menu_defaults.conf"; - std::fs::write(menu_defaults_conf_path, last_url) - .expect("Failed to write default menu conf file"); - } - - std::fs::write(MENU_CONF_PATH, last_url).expect("Failed to write menu conf file"); - unsafe { - EVENT_QUEUE.push(Event::menu_open(last_url.to_string())); - } -} - -pub fn spawn_menu() { - unsafe { - frame_counter::reset_frame_count(FRAME_COUNTER_INDEX); - frame_counter::start_counting(FRAME_COUNTER_INDEX); - } - - let mut quick_menu = false; - unsafe { - if MENU.quick_menu == OnOff::On { - quick_menu = true; - } - } - - if !quick_menu { - let fname = "training_menu.html"; - let params = unsafe { MENU.to_url_params() }; - let page_response = Webpage::new() - .background(Background::BlurredScreenshot) - .htdocs_dir("training_modpack") - .boot_display(BootDisplay::BlurredScreenshot) - .boot_icon(true) - .start_page(&format!("{}{}", fname, params)) - .open() - .unwrap(); - - let orig_last_url = page_response.get_last_url().unwrap(); - - set_menu_from_url(orig_last_url); - } else { - unsafe { - QUICK_MENU_ACTIVE = true; - } - } -} - -use skyline::nn::hid::NpadGcState; - -pub struct ButtonPresses { - pub a: ButtonPress, - pub b: ButtonPress, - pub zr: ButtonPress, - pub zl: ButtonPress, - pub left: ButtonPress, - pub right: ButtonPress, - pub up: ButtonPress, - pub down: ButtonPress -} - -pub struct ButtonPress { - pub is_pressed: bool, - pub lockout_frames: usize -} - -impl ButtonPress { - pub fn default() -> ButtonPress { - ButtonPress{ - is_pressed: false, - lockout_frames: 0 - } - } - - pub fn read_press(&mut self) -> bool { - if self.is_pressed { - self.is_pressed = false; - if self.lockout_frames == 0 { - self.lockout_frames = 15; - return true; - } - } - - if self.lockout_frames > 0 { - self.lockout_frames -= 1; - } - - false - } -} - -impl ButtonPresses { - pub fn default() -> ButtonPresses { - ButtonPresses{ - a: ButtonPress::default(), - b: ButtonPress::default(), - zr: ButtonPress::default(), - zl: ButtonPress::default(), - left: ButtonPress::default(), - right: ButtonPress::default(), - up: ButtonPress::default(), - down: ButtonPress::default() - } - } -} - -pub static mut BUTTON_PRESSES : ButtonPresses = ButtonPresses{ - a: ButtonPress{is_pressed: false, lockout_frames: 0}, - b: ButtonPress{is_pressed: false, lockout_frames: 0}, - zr: ButtonPress{is_pressed: false, lockout_frames: 0}, - zl: ButtonPress{is_pressed: false, lockout_frames: 0}, - left: ButtonPress{is_pressed: false, lockout_frames: 0}, - right: ButtonPress{is_pressed: false, lockout_frames: 0}, - up: ButtonPress{is_pressed: false, lockout_frames: 0}, - down: ButtonPress{is_pressed: false, lockout_frames: 0}, -}; - -pub fn handle_get_npad_state(state: *mut NpadGcState, _controller_id: *const u32) { - unsafe { - if menu::QUICK_MENU_ACTIVE { - // TODO: This should make more sense, look into. - // BUTTON_PRESSES.a.is_pressed = (*state).Buttons & (1 << 0) > 0; - // BUTTON_PRESSES.b.is_pressed = (*state).Buttons & (1 << 1) > 0; - // BUTTON_PRESSES.zl.is_pressed = (*state).Buttons & (1 << 8) > 0; - // BUTTON_PRESSES.zr.is_pressed = (*state).Buttons & (1 << 9) > 0; - // BUTTON_PRESSES.left.is_pressed = (*state).Buttons & ((1 << 12) | (1 << 16)) > 0; - // BUTTON_PRESSES.right.is_pressed = (*state).Buttons & ((1 << 14) | (1 << 18)) > 0; - // BUTTON_PRESSES.down.is_pressed = (*state).Buttons & ((1 << 15) | (1 << 19)) > 0; - // BUTTON_PRESSES.up.is_pressed = (*state).Buttons & ((1 << 13) | (1 << 17)) > 0; - - if frame_counter::get_frame_count(FRAME_COUNTER_INDEX) != 0 { - return; - } - - if (*state).Buttons & (1 << 0) > 0 { - BUTTON_PRESSES.a.is_pressed = true; - } - if (*state).Buttons & (1 << 1) > 0 { - BUTTON_PRESSES.b.is_pressed = true; - } - if (*state).Buttons & (1 << 8) > 0 { - BUTTON_PRESSES.zl.is_pressed = true; - } - if (*state).Buttons & (1 << 9) > 0 { - BUTTON_PRESSES.zr.is_pressed = true; - } - if (*state).Buttons & ((1 << 12) | (1 << 16)) > 0 { - BUTTON_PRESSES.left.is_pressed = true; - } - if (*state).Buttons & ((1 << 14) | (1 << 18)) > 0 { - BUTTON_PRESSES.right.is_pressed = true; - } - if (*state).Buttons & ((1 << 15) | (1 << 19)) > 0 { - BUTTON_PRESSES.down.is_pressed = true; - } - if (*state).Buttons & ((1 << 13) | (1 << 17)) > 0 { - BUTTON_PRESSES.up.is_pressed = true; - } - - // If we're here, remove all other Npad presses... - // Should we exclude the home button? - (*state) = NpadGcState::default(); - } - } -} - +use crate::common::consts::get_menu_from_url; +use crate::common::*; +use crate::events::{Event, EVENT_QUEUE}; +use crate::mkdir; +use crate::training::frame_counter; +use ramhorns::Template; +use skyline::info::get_program_id; +use skyline_web::{Background, BootDisplay, Webpage}; +use smash::lib::lua_const::*; +use std::fs; +use std::path::Path; + +static mut FRAME_COUNTER_INDEX: usize = 0; +const MENU_LOCKOUT_FRAMES: u32 = 15; +pub static mut QUICK_MENU_ACTIVE: bool = false; + +pub fn init() { + unsafe { + FRAME_COUNTER_INDEX = frame_counter::register_counter(); + write_menu(); + } +} + +pub unsafe fn menu_condition(module_accessor: &mut smash::app::BattleObjectModuleAccessor) -> bool { + // Only check for button combination if the counter is 0 (not locked out) + match frame_counter::get_frame_count(FRAME_COUNTER_INDEX) { + 0 => { + ControlModule::check_button_on(module_accessor, *CONTROL_PAD_BUTTON_SPECIAL) + && ControlModule::check_button_on_trriger( + module_accessor, + *CONTROL_PAD_BUTTON_APPEAL_HI, + ) + } + 1..MENU_LOCKOUT_FRAMES => false, + _ => { + // Waited longer than the lockout time, reset the counter so the menu can be opened again + frame_counter::full_reset(FRAME_COUNTER_INDEX); + false + } + } +} + +pub unsafe fn write_menu() { + let tpl = Template::new(include_str!("../templates/menu.html")).unwrap(); + + let overall_menu = get_menu(); + + let data = tpl.render(&overall_menu); + + // Now that we have the html, write it to file + // From skyline-web + let program_id = get_program_id(); + let htdocs_dir = "training_modpack"; + let menu_dir_path = Path::new("sd:/atmosphere/contents") + .join(&format!("{:016X}", program_id)) + .join(&format!("manual_html/html-document/{}.htdocs/", htdocs_dir)); + + let menu_html_path = menu_dir_path.join("training_menu.html"); + + mkdir(menu_dir_path.to_str().unwrap().as_bytes().as_ptr(), 777); + let write_resp = fs::write(menu_html_path, data); + if write_resp.is_err() { + println!("Error!: {}", write_resp.err().unwrap()); + } +} + +const MENU_CONF_PATH: &str = "sd:/TrainingModpack/training_modpack_menu.conf"; + +pub fn set_menu_from_url(orig_last_url: &str) { + let last_url = &orig_last_url.replace("&save_defaults=1", ""); + unsafe { + MENU = get_menu_from_url(MENU, last_url); + + if MENU.quick_menu == OnOff::Off { + if is_emulator() { + skyline::error::show_error( + 0x69, + "Cannot use web menu on emulator.\n\0", + "Only the quick menu is runnable via emulator currently.\n\0", + ); + MENU.quick_menu = OnOff::On; + } + } + } + + if last_url.len() != orig_last_url.len() { + // Save as default + unsafe { + DEFAULT_MENU = MENU; + write_menu(); + } + let menu_defaults_conf_path = "sd:/TrainingModpack/training_modpack_menu_defaults.conf"; + std::fs::write(menu_defaults_conf_path, last_url) + .expect("Failed to write default menu conf file"); + } + + std::fs::write(MENU_CONF_PATH, last_url).expect("Failed to write menu conf file"); + unsafe { + EVENT_QUEUE.push(Event::menu_open(last_url.to_string())); + } +} + +pub fn spawn_menu() { + unsafe { + frame_counter::reset_frame_count(FRAME_COUNTER_INDEX); + frame_counter::start_counting(FRAME_COUNTER_INDEX); + } + + let mut quick_menu = false; + unsafe { + if MENU.quick_menu == OnOff::On { + quick_menu = true; + } + } + + if !quick_menu { + let fname = "training_menu.html"; + let params = unsafe { MENU.to_url_params() }; + let page_response = Webpage::new() + .background(Background::BlurredScreenshot) + .htdocs_dir("training_modpack") + .boot_display(BootDisplay::BlurredScreenshot) + .boot_icon(true) + .start_page(&format!("{}{}", fname, params)) + .open() + .unwrap(); + + let orig_last_url = page_response.get_last_url().unwrap(); + + set_menu_from_url(orig_last_url); + } else { + unsafe { + QUICK_MENU_ACTIVE = true; + } + } +} + +use skyline::nn::hid::NpadGcState; + +pub struct ButtonPresses { + pub a: ButtonPress, + pub b: ButtonPress, + pub zr: ButtonPress, + pub zl: ButtonPress, + pub left: ButtonPress, + pub right: ButtonPress, + pub up: ButtonPress, + pub down: ButtonPress, +} + +pub struct ButtonPress { + pub prev_frame_is_pressed: bool, + pub is_pressed: bool, + pub lockout_frames: usize, +} + +impl ButtonPress { + pub fn default() -> ButtonPress { + ButtonPress { + prev_frame_is_pressed: false, + is_pressed: false, + lockout_frames: 0, + } + } + + pub fn read_press(&mut self) -> bool { + if self.is_pressed { + self.is_pressed = false; + if !self.prev_frame_is_pressed && self.lockout_frames == 0 { + self.lockout_frames = 10; + self.prev_frame_is_pressed = true; + return true; + } + } + + if self.lockout_frames > 0 { + self.lockout_frames -= 1; + } + + self.prev_frame_is_pressed = self.is_pressed; + false + } +} + +impl ButtonPresses { + pub fn default() -> ButtonPresses { + ButtonPresses { + a: ButtonPress::default(), + b: ButtonPress::default(), + zr: ButtonPress::default(), + zl: ButtonPress::default(), + left: ButtonPress::default(), + right: ButtonPress::default(), + up: ButtonPress::default(), + down: ButtonPress::default(), + } + } +} + +pub static mut BUTTON_PRESSES: ButtonPresses = ButtonPresses { + a: ButtonPress { + prev_frame_is_pressed: false, + is_pressed: false, + lockout_frames: 0, + }, + b: ButtonPress { + prev_frame_is_pressed: false, + is_pressed: false, + lockout_frames: 0, + }, + zr: ButtonPress { + prev_frame_is_pressed: false, + is_pressed: false, + lockout_frames: 0, + }, + zl: ButtonPress { + prev_frame_is_pressed: false, + is_pressed: false, + lockout_frames: 0, + }, + left: ButtonPress { + prev_frame_is_pressed: false, + is_pressed: false, + lockout_frames: 0, + }, + right: ButtonPress { + prev_frame_is_pressed: false, + is_pressed: false, + lockout_frames: 0, + }, + up: ButtonPress { + prev_frame_is_pressed: false, + is_pressed: false, + lockout_frames: 0, + }, + down: ButtonPress { + prev_frame_is_pressed: false, + is_pressed: false, + lockout_frames: 0, + }, +}; + +pub fn handle_get_npad_state(state: *mut NpadGcState, _controller_id: *const u32) { + unsafe { + if menu::QUICK_MENU_ACTIVE { + // TODO: This should make more sense, look into. + // BUTTON_PRESSES.a.is_pressed = (*state).Buttons & (1 << 0) > 0; + // BUTTON_PRESSES.b.is_pressed = (*state).Buttons & (1 << 1) > 0; + // BUTTON_PRESSES.zl.is_pressed = (*state).Buttons & (1 << 8) > 0; + // BUTTON_PRESSES.zr.is_pressed = (*state).Buttons & (1 << 9) > 0; + // BUTTON_PRESSES.left.is_pressed = (*state).Buttons & ((1 << 12) | (1 << 16)) > 0; + // BUTTON_PRESSES.right.is_pressed = (*state).Buttons & ((1 << 14) | (1 << 18)) > 0; + // BUTTON_PRESSES.down.is_pressed = (*state).Buttons & ((1 << 15) | (1 << 19)) > 0; + // BUTTON_PRESSES.up.is_pressed = (*state).Buttons & ((1 << 13) | (1 << 17)) > 0; + + if frame_counter::get_frame_count(FRAME_COUNTER_INDEX) != 0 { + return; + } + + if (*state).Buttons & (1 << 0) > 0 { + BUTTON_PRESSES.a.is_pressed = true; + } + if (*state).Buttons & (1 << 1) > 0 { + BUTTON_PRESSES.b.is_pressed = true; + } + if (*state).Buttons & (1 << 8) > 0 { + BUTTON_PRESSES.zl.is_pressed = true; + } + if (*state).Buttons & (1 << 9) > 0 { + BUTTON_PRESSES.zr.is_pressed = true; + } + if (*state).Buttons & ((1 << 12) | (1 << 16)) > 0 { + BUTTON_PRESSES.left.is_pressed = true; + } + if (*state).Buttons & ((1 << 14) | (1 << 18)) > 0 { + BUTTON_PRESSES.right.is_pressed = true; + } + if (*state).Buttons & ((1 << 15) | (1 << 19)) > 0 { + BUTTON_PRESSES.down.is_pressed = true; + } + if (*state).Buttons & ((1 << 13) | (1 << 17)) > 0 { + BUTTON_PRESSES.up.is_pressed = true; + } + + // If we're here, remove all other Npad presses... + // Should we exclude the home button? + (*state) = NpadGcState::default(); + } + } +} diff --git a/src/common/mod.rs b/src/common/mod.rs index 4067eaf..1673bc5 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -1,139 +1,138 @@ -pub mod consts; -pub mod events; -pub mod menu; -pub mod raygun_printer; -pub mod release; - -use crate::common::consts::*; -use smash::app::{self, lua_bind::*}; -use smash::lib::lua_const::*; - -pub use crate::common::consts::MENU; -pub static mut DEFAULT_MENU: TrainingModpackMenu = crate::common::consts::DEFAULT_MENU; -pub static mut BASE_MENU: TrainingModpackMenu = unsafe { DEFAULT_MENU }; -pub static mut FIGHTER_MANAGER_ADDR: usize = 0; -pub static mut STAGE_MANAGER_ADDR: usize = 0; - -#[cfg(not(feature = "outside_training_mode"))] -extern "C" { - #[link_name = "\u{1}_ZN3app9smashball16is_training_modeEv"] - pub fn is_training_mode() -> bool; -} - -#[cfg(feature = "outside_training_mode")] -pub fn is_training_mode() -> bool { - return true; -} - -pub fn get_category(module_accessor: &mut app::BattleObjectModuleAccessor) -> i32 { - (module_accessor.info >> 28) as u8 as i32 -} - -pub fn is_emulator() -> bool { - unsafe { skyline::hooks::getRegionAddress(skyline::hooks::Region::Text) as u64 == 0x8004000 } -} - - -pub fn get_module_accessor(fighter_id: FighterId) -> *mut app::BattleObjectModuleAccessor { - let entry_id_int = fighter_id as i32; - let entry_id = app::FighterEntryID(entry_id_int); - unsafe { - let mgr = *(FIGHTER_MANAGER_ADDR as *mut *mut app::FighterManager); - let fighter_entry = - FighterManager::get_fighter_entry(mgr, entry_id) as *mut app::FighterEntry; - let current_fighter_id = FighterEntry::current_fighter_id(fighter_entry); - app::sv_battle_object::module_accessor(current_fighter_id as u32) - } -} - -pub fn is_fighter(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool { - get_category(module_accessor) == BATTLE_OBJECT_CATEGORY_FIGHTER -} - -pub fn is_operation_cpu(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool { - unsafe { - if !is_fighter(module_accessor) { - return false; - } - - let entry_id_int = - WorkModule::get_int(module_accessor, *FIGHTER_INSTANCE_WORK_ID_INT_ENTRY_ID) as i32; - - if entry_id_int == 0 { - return false; - } - - let entry_id = app::FighterEntryID(entry_id_int); - let mgr = *(FIGHTER_MANAGER_ADDR as *mut *mut app::FighterManager); - let fighter_information = - FighterManager::get_fighter_information(mgr, entry_id) as *mut app::FighterInformation; - - FighterInformation::is_operation_cpu(fighter_information) - } -} - -pub fn is_grounded(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool { - let situation_kind = unsafe { StatusModule::situation_kind(module_accessor) as i32 }; - - situation_kind == SITUATION_KIND_GROUND -} - -pub fn is_airborne(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool { - let situation_kind = unsafe { StatusModule::situation_kind(module_accessor) as i32 }; - - situation_kind == SITUATION_KIND_AIR -} - -pub fn is_idle(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool { - let status_kind = unsafe { StatusModule::status_kind(module_accessor) }; - - status_kind == FIGHTER_STATUS_KIND_WAIT -} - -pub fn is_in_hitstun(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool { - let status_kind = unsafe { StatusModule::status_kind(module_accessor) }; - - (*FIGHTER_STATUS_KIND_DAMAGE..*FIGHTER_STATUS_KIND_DAMAGE_FALL).contains(&status_kind) -} -pub fn is_in_footstool(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool { - let status_kind = unsafe { StatusModule::status_kind(module_accessor) }; - - (*FIGHTER_STATUS_KIND_TREAD_DAMAGE..=*FIGHTER_STATUS_KIND_TREAD_FALL).contains(&status_kind) -} - -pub fn is_shielding(module_accessor: *mut app::BattleObjectModuleAccessor) -> bool { - let status_kind = unsafe { StatusModule::status_kind(module_accessor) as i32 }; - - (*FIGHTER_STATUS_KIND_GUARD_ON..=*FIGHTER_STATUS_KIND_GUARD_DAMAGE).contains(&status_kind) -} - -pub fn is_in_shieldstun(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool { - let status_kind = unsafe { StatusModule::status_kind(module_accessor) }; - let prev_status = unsafe { StatusModule::prev_status_kind(module_accessor, 0) }; - - // If we are taking shield damage or we are droping shield from taking shield damage we are in hitstun - status_kind == FIGHTER_STATUS_KIND_GUARD_DAMAGE - || (prev_status == FIGHTER_STATUS_KIND_GUARD_DAMAGE - && status_kind == FIGHTER_STATUS_KIND_GUARD_OFF) -} - -pub unsafe fn is_dead(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool { - let fighter_kind = app::utility::get_kind(module_accessor); - let fighter_is_ptrainer = [ - *FIGHTER_KIND_PZENIGAME, - *FIGHTER_KIND_PFUSHIGISOU, - *FIGHTER_KIND_PLIZARDON, - ] - .contains(&fighter_kind); - let status_kind = StatusModule::status_kind(module_accessor) as i32; - let prev_status_kind = StatusModule::prev_status_kind(module_accessor, 0); - // Pokemon trainer enters FIGHTER_STATUS_KIND_WAIT for one frame during their respawn animation - // And the previous status is FIGHTER_STATUS_NONE - if fighter_is_ptrainer { - [*FIGHTER_STATUS_KIND_DEAD, *FIGHTER_STATUS_KIND_STANDBY].contains(&status_kind) - || (status_kind == FIGHTER_STATUS_KIND_WAIT - && prev_status_kind == FIGHTER_STATUS_KIND_NONE) - } else { - [*FIGHTER_STATUS_KIND_DEAD, *FIGHTER_STATUS_KIND_STANDBY].contains(&status_kind) - } -} +pub mod consts; +pub mod events; +pub mod menu; +pub mod raygun_printer; +pub mod release; + +use crate::common::consts::*; +use smash::app::{self, lua_bind::*}; +use smash::lib::lua_const::*; + +pub use crate::common::consts::MENU; +pub static mut DEFAULT_MENU: TrainingModpackMenu = crate::common::consts::DEFAULT_MENU; +pub static mut BASE_MENU: TrainingModpackMenu = unsafe { DEFAULT_MENU }; +pub static mut FIGHTER_MANAGER_ADDR: usize = 0; +pub static mut STAGE_MANAGER_ADDR: usize = 0; + +#[cfg(not(feature = "outside_training_mode"))] +extern "C" { + #[link_name = "\u{1}_ZN3app9smashball16is_training_modeEv"] + pub fn is_training_mode() -> bool; +} + +#[cfg(feature = "outside_training_mode")] +pub fn is_training_mode() -> bool { + return true; +} + +pub fn get_category(module_accessor: &mut app::BattleObjectModuleAccessor) -> i32 { + (module_accessor.info >> 28) as u8 as i32 +} + +pub fn is_emulator() -> bool { + unsafe { skyline::hooks::getRegionAddress(skyline::hooks::Region::Text) as u64 == 0x8004000 } +} + +pub fn get_module_accessor(fighter_id: FighterId) -> *mut app::BattleObjectModuleAccessor { + let entry_id_int = fighter_id as i32; + let entry_id = app::FighterEntryID(entry_id_int); + unsafe { + let mgr = *(FIGHTER_MANAGER_ADDR as *mut *mut app::FighterManager); + let fighter_entry = + FighterManager::get_fighter_entry(mgr, entry_id) as *mut app::FighterEntry; + let current_fighter_id = FighterEntry::current_fighter_id(fighter_entry); + app::sv_battle_object::module_accessor(current_fighter_id as u32) + } +} + +pub fn is_fighter(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool { + get_category(module_accessor) == BATTLE_OBJECT_CATEGORY_FIGHTER +} + +pub fn is_operation_cpu(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool { + unsafe { + if !is_fighter(module_accessor) { + return false; + } + + let entry_id_int = + WorkModule::get_int(module_accessor, *FIGHTER_INSTANCE_WORK_ID_INT_ENTRY_ID) as i32; + + if entry_id_int == 0 { + return false; + } + + let entry_id = app::FighterEntryID(entry_id_int); + let mgr = *(FIGHTER_MANAGER_ADDR as *mut *mut app::FighterManager); + let fighter_information = + FighterManager::get_fighter_information(mgr, entry_id) as *mut app::FighterInformation; + + FighterInformation::is_operation_cpu(fighter_information) + } +} + +pub fn is_grounded(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool { + let situation_kind = unsafe { StatusModule::situation_kind(module_accessor) as i32 }; + + situation_kind == SITUATION_KIND_GROUND +} + +pub fn is_airborne(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool { + let situation_kind = unsafe { StatusModule::situation_kind(module_accessor) as i32 }; + + situation_kind == SITUATION_KIND_AIR +} + +pub fn is_idle(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool { + let status_kind = unsafe { StatusModule::status_kind(module_accessor) }; + + status_kind == FIGHTER_STATUS_KIND_WAIT +} + +pub fn is_in_hitstun(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool { + let status_kind = unsafe { StatusModule::status_kind(module_accessor) }; + + (*FIGHTER_STATUS_KIND_DAMAGE..*FIGHTER_STATUS_KIND_DAMAGE_FALL).contains(&status_kind) +} +pub fn is_in_footstool(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool { + let status_kind = unsafe { StatusModule::status_kind(module_accessor) }; + + (*FIGHTER_STATUS_KIND_TREAD_DAMAGE..=*FIGHTER_STATUS_KIND_TREAD_FALL).contains(&status_kind) +} + +pub fn is_shielding(module_accessor: *mut app::BattleObjectModuleAccessor) -> bool { + let status_kind = unsafe { StatusModule::status_kind(module_accessor) as i32 }; + + (*FIGHTER_STATUS_KIND_GUARD_ON..=*FIGHTER_STATUS_KIND_GUARD_DAMAGE).contains(&status_kind) +} + +pub fn is_in_shieldstun(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool { + let status_kind = unsafe { StatusModule::status_kind(module_accessor) }; + let prev_status = unsafe { StatusModule::prev_status_kind(module_accessor, 0) }; + + // If we are taking shield damage or we are droping shield from taking shield damage we are in hitstun + status_kind == FIGHTER_STATUS_KIND_GUARD_DAMAGE + || (prev_status == FIGHTER_STATUS_KIND_GUARD_DAMAGE + && status_kind == FIGHTER_STATUS_KIND_GUARD_OFF) +} + +pub unsafe fn is_dead(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool { + let fighter_kind = app::utility::get_kind(module_accessor); + let fighter_is_ptrainer = [ + *FIGHTER_KIND_PZENIGAME, + *FIGHTER_KIND_PFUSHIGISOU, + *FIGHTER_KIND_PLIZARDON, + ] + .contains(&fighter_kind); + let status_kind = StatusModule::status_kind(module_accessor) as i32; + let prev_status_kind = StatusModule::prev_status_kind(module_accessor, 0); + // Pokemon trainer enters FIGHTER_STATUS_KIND_WAIT for one frame during their respawn animation + // And the previous status is FIGHTER_STATUS_NONE + if fighter_is_ptrainer { + [*FIGHTER_STATUS_KIND_DEAD, *FIGHTER_STATUS_KIND_STANDBY].contains(&status_kind) + || (status_kind == FIGHTER_STATUS_KIND_WAIT + && prev_status_kind == FIGHTER_STATUS_KIND_NONE) + } else { + [*FIGHTER_STATUS_KIND_DEAD, *FIGHTER_STATUS_KIND_STANDBY].contains(&status_kind) + } +} diff --git a/src/lib.rs b/src/lib.rs index 19bd259..d110a66 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,7 +7,9 @@ clippy::borrow_interior_mutable_const, clippy::not_unsafe_ptr_arg_deref, clippy::missing_safety_doc, - clippy::wrong_self_convention + clippy::wrong_self_convention, + clippy::option_map_unit_fn, + clippy::float_cmp )] pub mod common; @@ -18,9 +20,9 @@ mod training; #[cfg(test)] mod test; +use crate::common::consts::get_menu_from_url; use crate::common::*; use crate::events::{Event, EVENT_QUEUE}; -use crate::common::consts::get_menu_from_url; use skyline::libc::{c_char, mkdir}; use skyline::nro::{self, NroInfo}; @@ -69,8 +71,7 @@ pub fn render_text_to_screen(s: &str) { pub fn main() { macro_rules! log { ($($arg:tt)*) => { - print!("{}", "[Training Modpack] ".green()); - println!($($arg)*); + print!("{}{}", "[Training Modpack] ".green(), format!($($arg)*)); }; } @@ -84,7 +85,6 @@ pub fn main() { training::training_mods(); nro::add_hook(nro_main).unwrap(); - unsafe { mkdir(c_str!("sd:/TrainingModpack/"), 777); } @@ -141,7 +141,9 @@ pub fn main() { } if is_emulator() { - unsafe { MENU.quick_menu = OnOff::On; } + unsafe { + MENU.quick_menu = OnOff::On; + } } std::thread::spawn(|| loop { @@ -179,34 +181,60 @@ pub fn main() { let button_presses = &mut common::menu::BUTTON_PRESSES; let mut received_input = true; loop { - button_presses.a.read_press().then(|| { app.on_a(); received_input = true; }); + button_presses.a.read_press().then(|| { + app.on_a(); + received_input = true; + }); let b_press = &mut button_presses.b; + let b_prev_press = b_press.prev_frame_is_pressed; b_press.read_press().then(|| { received_input = true; if !app.outer_list { app.on_b() - } else { + } else if !b_prev_press { // Leave menu. menu::QUICK_MENU_ACTIVE = false; crate::menu::set_menu_from_url(url.as_str()); } }); - button_presses.zl.read_press().then(|| { app.on_l(); received_input = true; }); - button_presses.zr.read_press().then(|| { app.on_r(); received_input = true; }); - button_presses.left.read_press().then(|| { app.on_left(); received_input = true; }); - button_presses.right.read_press().then(|| { app.on_right(); received_input = true; }); - button_presses.up.read_press().then(|| { app.on_up(); received_input = true; }); - button_presses.down.read_press().then(|| { app.on_down(); received_input = true; }); + button_presses.zl.read_press().then(|| { + app.on_l(); + received_input = true; + }); + button_presses.zr.read_press().then(|| { + app.on_r(); + received_input = true; + }); + button_presses.left.read_press().then(|| { + app.on_left(); + received_input = true; + }); + button_presses.right.read_press().then(|| { + app.on_right(); + received_input = true; + }); + button_presses.up.read_press().then(|| { + app.on_up(); + received_input = true; + }); + button_presses.down.read_press().then(|| { + app.on_down(); + received_input = true; + }); std::thread::sleep(std::time::Duration::from_millis(16)); has_slept_millis += 16; - if has_slept_millis < 16 * render_frames { continue; } + if has_slept_millis < 16 * render_frames { + continue; + } has_slept_millis = 16; if !menu::QUICK_MENU_ACTIVE { set_should_display_text_to_screen(false); continue; } - if !received_input { continue; } + if !received_input { + continue; + } let mut view = String::new(); let frame_res = terminal @@ -228,9 +256,12 @@ pub fn main() { Color::Yellow => write!(&mut view, "{}", &cell.symbol.yellow()), Color::LightYellow => write!(&mut view, "{}", &cell.symbol.bright_yellow()), Color::Magenta => write!(&mut view, "{}", &cell.symbol.magenta()), - Color::LightMagenta => write!(&mut view, "{}", &cell.symbol.bright_magenta()), - _ => write!(&mut view, "{}", &cell.symbol), - }.unwrap(); + Color::LightMagenta => { + write!(&mut view, "{}", &cell.symbol.bright_magenta()) + } + _ => write!(&mut view, "{}", &cell.symbol), + } + .unwrap(); if i % frame_res.area.width as usize == frame_res.area.width as usize - 1 { writeln!(&mut view).unwrap(); } diff --git a/src/training/buff.rs b/src/training/buff.rs index f94d578..f1e71e1 100644 --- a/src/training/buff.rs +++ b/src/training/buff.rs @@ -39,7 +39,7 @@ pub unsafe fn is_buffing(module_accessor: &mut app::BattleObjectModuleAccessor) if is_operation_cpu(module_accessor) { return IS_BUFFING_CPU; } - return IS_BUFFING_PLAYER; + IS_BUFFING_PLAYER } pub unsafe fn set_buff_rem(module_accessor: &mut app::BattleObjectModuleAccessor, new_value: i32) { @@ -54,7 +54,7 @@ pub unsafe fn get_buff_rem(module_accessor: &mut app::BattleObjectModuleAccessor if is_operation_cpu(module_accessor) { return BUFF_REMAINING_CPU; } - return BUFF_REMAINING_PLAYER; + BUFF_REMAINING_PLAYER } fn get_spell_vec() -> Vec { @@ -68,7 +68,7 @@ fn get_spell_vec() -> Vec { spell_buff.push(*buff); } } - return spell_buff; + spell_buff } } @@ -99,7 +99,7 @@ pub unsafe fn handle_buffs( return buff_sepiroth(module_accessor, percent); } - return true; + true } unsafe fn buff_hero(module_accessor: &mut app::BattleObjectModuleAccessor, status: i32) -> bool { @@ -115,7 +115,7 @@ unsafe fn buff_hero(module_accessor: &mut app::BattleObjectModuleAccessor, statu return true; } buff_hero_single(module_accessor, status, buff_vec); - return false; + false } unsafe fn buff_hero_single( @@ -161,11 +161,11 @@ unsafe fn buff_cloud(module_accessor: &mut app::BattleObjectModuleAccessor) -> b start_buff(module_accessor); handle_add_limit(100.0, module_accessor, 0); } - if frame_counter::should_delay(2 as u32, BUFF_DELAY_COUNTER) { + if frame_counter::should_delay(2_u32, BUFF_DELAY_COUNTER) { // Need to wait 2 frames to make sure we stop the limit SFX, since it's a bit delayed return false; } - return true; + true } unsafe fn buff_joker(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool { @@ -176,11 +176,11 @@ unsafe fn buff_joker(module_accessor: &mut app::BattleObjectModuleAccessor) -> b // Strangely, this doesn't actually matter and works for both fighters app::FighterSpecializer_Jack::add_rebel_gauge(module_accessor, entry_id, 120.0); } - if frame_counter::should_delay(2 as u32, BUFF_DELAY_COUNTER) { + if frame_counter::should_delay(2_u32, BUFF_DELAY_COUNTER) { // Need to wait 2 frames to make sure we stop the voice call, since it's a bit delayed return false; } - return true; + true } unsafe fn buff_mac(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool { @@ -192,7 +192,7 @@ unsafe fn buff_mac(module_accessor: &mut app::BattleObjectModuleAccessor) -> boo // Trying to stop KO Punch from playing seems to make it play multiple times in rapid succession // Look at 0x7100c44b60 for the func that handles this // Need to figure out how to update the KO meter if this is fixed - return true; + true } unsafe fn buff_sepiroth( @@ -217,12 +217,12 @@ unsafe fn buff_sepiroth( // if we're not in wing, add damage DamageModule::add_damage(module_accessor, 1000.0, 0); } - return false; + false } unsafe fn buff_wiifit(module_accessor: &mut app::BattleObjectModuleAccessor, status: i32) -> bool { if is_buffing(module_accessor) { - if frame_counter::should_delay(2 as u32, BUFF_DELAY_COUNTER) { + if frame_counter::should_delay(2_u32, BUFF_DELAY_COUNTER) { // Need to wait 2 frames to make sure we stop breathing SFX return false; } @@ -242,5 +242,5 @@ unsafe fn buff_wiifit(module_accessor: &mut app::BattleObjectModuleAccessor, sta } else { MotionModule::set_rate(module_accessor, 40.0); } - return false; + false } diff --git a/src/training/character_specific/mod.rs b/src/training/character_specific/mod.rs index 298b66e..1b85fdb 100644 --- a/src/training/character_specific/mod.rs +++ b/src/training/character_specific/mod.rs @@ -16,4 +16,4 @@ pub fn check_status( } false -} \ No newline at end of file +} diff --git a/src/training/character_specific/steve.rs b/src/training/character_specific/steve.rs index 2dd8f0a..62c912c 100644 --- a/src/training/character_specific/steve.rs +++ b/src/training/character_specific/steve.rs @@ -29,10 +29,12 @@ fn is_steve(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool { fighter_id == *FIGHTER_KIND_PICKEL } -pub fn save_steve_state(module_accessor: &mut app::BattleObjectModuleAccessor) -> Option { +pub fn save_steve_state( + module_accessor: &mut app::BattleObjectModuleAccessor, +) -> Option { // Returns None if not Steve, a SteveState if it is if !is_steve(module_accessor) { - return None; + None } else { unsafe { Some(save(module_accessor)) // should return the SteveState @@ -40,36 +42,69 @@ pub fn save_steve_state(module_accessor: &mut app::BattleObjectModuleAccessor) - } } -pub fn load_steve_state(module_accessor: &mut app::BattleObjectModuleAccessor, steve_state: SteveState) -> bool { +pub fn load_steve_state( + module_accessor: &mut app::BattleObjectModuleAccessor, + steve_state: SteveState, +) -> bool { // Returns false if not Steve, true if it is and we've set the variables if !is_steve(module_accessor) { - return false; + false } else { - unsafe { - load(module_accessor, steve_state) - } - return true; + unsafe { load(module_accessor, steve_state) } + true } } unsafe fn save(module_accessor: &mut app::BattleObjectModuleAccessor) -> SteveState { - let mat_g1 = WorkModule::get_int(module_accessor, *FIGHTER_PICKEL_INSTANCE_WORK_ID_INT_MATERIAL_NUM_GRADE_1); - let mat_wood = WorkModule::get_int(module_accessor, *FIGHTER_PICKEL_INSTANCE_WORK_ID_INT_MATERIAL_NUM_WOOD); - let mat_stone = WorkModule::get_int(module_accessor, *FIGHTER_PICKEL_INSTANCE_WORK_ID_INT_MATERIAL_NUM_STONE); - let mat_iron = WorkModule::get_int(module_accessor, *FIGHTER_PICKEL_INSTANCE_WORK_ID_INT_MATERIAL_NUM_IRON); - let mat_gold = WorkModule::get_int(module_accessor, *FIGHTER_PICKEL_INSTANCE_WORK_ID_INT_MATERIAL_NUM_GOLD); - let mat_redstone = WorkModule::get_int(module_accessor, *FIGHTER_PICKEL_INSTANCE_WORK_ID_INT_MATERIAL_NUM_RED_STONE); - let mat_diamond = WorkModule::get_int(module_accessor, *FIGHTER_PICKEL_INSTANCE_WORK_ID_INT_MATERIAL_NUM_DIAMOND); - let extend_buffer_address = WorkModule::get_int64(module_accessor, *FIGHTER_PICKEL_INSTANCE_WORK_ID_INT_EXTEND_BUFFER); - let sword_mat = *((extend_buffer_address + (0xC * 0)) as *const char); - let sword_durability = *(((extend_buffer_address + ((0xC * 0) + 4))) as *const f32); - let axe_mat = *((extend_buffer_address + (0xC * 1)) as *const char); - let axe_durability = *(((extend_buffer_address + ((0xC * 1) + 4))) as *const f32); - let pick_mat = *((extend_buffer_address + (0xC * 2)) as *const char); - let pick_durability = *(((extend_buffer_address + ((0xC * 2) + 4))) as *const f32); - let shovel_mat = *((extend_buffer_address + (0xC * 3)) as *const char); - let shovel_durability = *(((extend_buffer_address + ((0xC * 3) + 4))) as *const f32); - + let mat_g1 = WorkModule::get_int( + module_accessor, + *FIGHTER_PICKEL_INSTANCE_WORK_ID_INT_MATERIAL_NUM_GRADE_1, + ); + let mat_wood = WorkModule::get_int( + module_accessor, + *FIGHTER_PICKEL_INSTANCE_WORK_ID_INT_MATERIAL_NUM_WOOD, + ); + let mat_stone = WorkModule::get_int( + module_accessor, + *FIGHTER_PICKEL_INSTANCE_WORK_ID_INT_MATERIAL_NUM_STONE, + ); + let mat_iron = WorkModule::get_int( + module_accessor, + *FIGHTER_PICKEL_INSTANCE_WORK_ID_INT_MATERIAL_NUM_IRON, + ); + let mat_gold = WorkModule::get_int( + module_accessor, + *FIGHTER_PICKEL_INSTANCE_WORK_ID_INT_MATERIAL_NUM_GOLD, + ); + let mat_redstone = WorkModule::get_int( + module_accessor, + *FIGHTER_PICKEL_INSTANCE_WORK_ID_INT_MATERIAL_NUM_RED_STONE, + ); + let mat_diamond = WorkModule::get_int( + module_accessor, + *FIGHTER_PICKEL_INSTANCE_WORK_ID_INT_MATERIAL_NUM_DIAMOND, + ); + let extend_buffer_address = WorkModule::get_int64( + module_accessor, + *FIGHTER_PICKEL_INSTANCE_WORK_ID_INT_EXTEND_BUFFER, + ); + let mut extend_buffer_offset = 0; + let sword_mat = *((extend_buffer_address + (0xC * extend_buffer_offset)) as *const char); + let sword_durability = + *((extend_buffer_address + ((0xC * extend_buffer_offset) + 4)) as *const f32); + extend_buffer_offset += 1; + let axe_mat = *((extend_buffer_address + (0xC * extend_buffer_offset)) as *const char); + let axe_durability = + *((extend_buffer_address + ((0xC * extend_buffer_offset) + 4)) as *const f32); + extend_buffer_offset += 1; + let pick_mat = *((extend_buffer_address + (0xC * extend_buffer_offset)) as *const char); + let pick_durability = + *((extend_buffer_address + ((0xC * extend_buffer_offset) + 4)) as *const f32); + extend_buffer_offset += 1; + let shovel_mat = *((extend_buffer_address + (0xC * extend_buffer_offset)) as *const char); + let shovel_durability = + *((extend_buffer_address + ((0xC * extend_buffer_offset) + 4)) as *const f32); + SteveState { mat_g1, mat_wood, @@ -90,35 +125,78 @@ unsafe fn save(module_accessor: &mut app::BattleObjectModuleAccessor) -> SteveSt } unsafe fn load(module_accessor: &mut app::BattleObjectModuleAccessor, steve_state: SteveState) { - WorkModule::set_int(module_accessor, steve_state.mat_g1, *FIGHTER_PICKEL_INSTANCE_WORK_ID_INT_MATERIAL_NUM_GRADE_1); - WorkModule::set_int(module_accessor, steve_state.mat_wood, *FIGHTER_PICKEL_INSTANCE_WORK_ID_INT_MATERIAL_NUM_WOOD); - WorkModule::set_int(module_accessor, steve_state.mat_stone, *FIGHTER_PICKEL_INSTANCE_WORK_ID_INT_MATERIAL_NUM_STONE); - WorkModule::set_int(module_accessor, steve_state.mat_iron, *FIGHTER_PICKEL_INSTANCE_WORK_ID_INT_MATERIAL_NUM_IRON); - WorkModule::set_int(module_accessor, steve_state.mat_gold, *FIGHTER_PICKEL_INSTANCE_WORK_ID_INT_MATERIAL_NUM_GOLD); - WorkModule::set_int(module_accessor, steve_state.mat_redstone, *FIGHTER_PICKEL_INSTANCE_WORK_ID_INT_MATERIAL_NUM_RED_STONE); - WorkModule::set_int(module_accessor, steve_state.mat_diamond, *FIGHTER_PICKEL_INSTANCE_WORK_ID_INT_MATERIAL_NUM_DIAMOND); - - let extend_buffer_address = WorkModule::get_int64(module_accessor, *FIGHTER_PICKEL_INSTANCE_WORK_ID_INT_EXTEND_BUFFER); + WorkModule::set_int( + module_accessor, + steve_state.mat_g1, + *FIGHTER_PICKEL_INSTANCE_WORK_ID_INT_MATERIAL_NUM_GRADE_1, + ); + WorkModule::set_int( + module_accessor, + steve_state.mat_wood, + *FIGHTER_PICKEL_INSTANCE_WORK_ID_INT_MATERIAL_NUM_WOOD, + ); + WorkModule::set_int( + module_accessor, + steve_state.mat_stone, + *FIGHTER_PICKEL_INSTANCE_WORK_ID_INT_MATERIAL_NUM_STONE, + ); + WorkModule::set_int( + module_accessor, + steve_state.mat_iron, + *FIGHTER_PICKEL_INSTANCE_WORK_ID_INT_MATERIAL_NUM_IRON, + ); + WorkModule::set_int( + module_accessor, + steve_state.mat_gold, + *FIGHTER_PICKEL_INSTANCE_WORK_ID_INT_MATERIAL_NUM_GOLD, + ); + WorkModule::set_int( + module_accessor, + steve_state.mat_redstone, + *FIGHTER_PICKEL_INSTANCE_WORK_ID_INT_MATERIAL_NUM_RED_STONE, + ); + WorkModule::set_int( + module_accessor, + steve_state.mat_diamond, + *FIGHTER_PICKEL_INSTANCE_WORK_ID_INT_MATERIAL_NUM_DIAMOND, + ); + + let extend_buffer_address = WorkModule::get_int64( + module_accessor, + *FIGHTER_PICKEL_INSTANCE_WORK_ID_INT_EXTEND_BUFFER, + ); // We have to grab the address every time instead of saving it, because loading // a state from a separate training mode instance would cause a crash - *((extend_buffer_address + (0xC * 0)) as *mut char) = steve_state.sword_mat; - *((extend_buffer_address + (0xC * 1)) as *mut char) = steve_state.axe_mat; - *((extend_buffer_address + (0xC * 2)) as *mut char) = steve_state.pick_mat; - *((extend_buffer_address + (0xC * 3)) as *mut char) = steve_state.shovel_mat; + let mut extend_buffer_offset = 0; + *((extend_buffer_address + (0xC * extend_buffer_offset)) as *mut char) = steve_state.sword_mat; + extend_buffer_offset += 1; + *((extend_buffer_address + (0xC * extend_buffer_offset)) as *mut char) = steve_state.axe_mat; + extend_buffer_offset += 1; + *((extend_buffer_address + (0xC * extend_buffer_offset)) as *mut char) = steve_state.pick_mat; + extend_buffer_offset += 1; + *((extend_buffer_address + (0xC * extend_buffer_offset)) as *mut char) = steve_state.shovel_mat; // Update durability - *((extend_buffer_address + (0xC * 0) + 4) as *mut f32) = steve_state.sword_durability; - *((extend_buffer_address + (0xC * 1) + 4) as *mut f32) = steve_state.axe_durability; - *((extend_buffer_address + (0xC * 2) + 4) as *mut f32) = steve_state.pick_durability; - *((extend_buffer_address + (0xC * 3) + 4) as *mut f32) = steve_state.shovel_durability; + extend_buffer_offset = 0; + *((extend_buffer_address + (0xC * extend_buffer_offset) + 4) as *mut f32) = + steve_state.sword_durability; + extend_buffer_offset += 1; + *((extend_buffer_address + (0xC * extend_buffer_offset) + 4) as *mut f32) = + steve_state.axe_durability; + extend_buffer_offset += 1; + *((extend_buffer_address + (0xC * extend_buffer_offset) + 4) as *mut f32) = + steve_state.pick_durability; + extend_buffer_offset += 1; + *((extend_buffer_address + (0xC * extend_buffer_offset) + 4) as *mut f32) = + steve_state.shovel_durability; // Update UI meter at the bottom by subtracting the materials by 0 after setting them - + let mut curr_material = 0; while curr_material < 7 { - app::FighterSpecializer_Pickel::sub_material_num(module_accessor,curr_material,0); + app::FighterSpecializer_Pickel::sub_material_num(module_accessor, curr_material, 0); curr_material += 1; } -} \ No newline at end of file +} diff --git a/src/training/charge.rs b/src/training/charge.rs index 6ed639b..126efe5 100644 --- a/src/training/charge.rs +++ b/src/training/charge.rs @@ -1,4 +1,4 @@ -use smash::app::{self, lua_bind::*, ArticleOperationTarget, FighterUtil, FighterFacial}; +use smash::app::{self, lua_bind::*, ArticleOperationTarget, FighterFacial, FighterUtil}; use smash::lib::lua_const::*; use smash::phx::{Hash40, Vector3f}; @@ -9,7 +9,7 @@ pub struct ChargeState { pub float_x: Option, pub float_y: Option, pub float_z: Option, - pub has_charge: Option + pub has_charge: Option, } impl ChargeState { @@ -42,7 +42,6 @@ impl ChargeState { self.has_charge = Some(has_charge); self } - } impl Default for ChargeState { @@ -53,151 +52,234 @@ impl Default for ChargeState { float_x: None, float_y: None, float_z: None, - has_charge: None + has_charge: None, } } } -pub unsafe fn get_charge(module_accessor: &mut app::BattleObjectModuleAccessor, fighter_kind: i32) -> ChargeState { +pub unsafe fn get_charge( + module_accessor: &mut app::BattleObjectModuleAccessor, + fighter_kind: i32, +) -> ChargeState { let charge_state = ChargeState::default(); // Mario FLUDD if fighter_kind == FIGHTER_KIND_MARIO { - let my_charge = WorkModule::get_int(module_accessor, *FIGHTER_MARIO_INSTANCE_WORK_ID_INT_SPECIAL_LW_CHARGE); + let my_charge = WorkModule::get_int( + module_accessor, + *FIGHTER_MARIO_INSTANCE_WORK_ID_INT_SPECIAL_LW_CHARGE, + ); charge_state.int_x(my_charge) } - // Donkey Kong Giant Punch else if fighter_kind == FIGHTER_KIND_DONKEY { - let my_charge = WorkModule::get_int(module_accessor, *FIGHTER_DONKEY_INSTANCE_WORK_ID_INT_SPECIAL_N_COUNT); + let my_charge = WorkModule::get_int( + module_accessor, + *FIGHTER_DONKEY_INSTANCE_WORK_ID_INT_SPECIAL_N_COUNT, + ); charge_state.int_x(my_charge) } - // Samus/Dark Samus Charge Shot else if fighter_kind == FIGHTER_KIND_SAMUS || fighter_kind == FIGHTER_KIND_SAMUSD { - let my_charge = WorkModule::get_int(module_accessor, *FIGHTER_SAMUS_INSTANCE_WORK_ID_INT_SPECIAL_N_COUNT); + let my_charge = WorkModule::get_int( + module_accessor, + *FIGHTER_SAMUS_INSTANCE_WORK_ID_INT_SPECIAL_N_COUNT, + ); charge_state.int_x(my_charge) } - // Sheik Needles else if fighter_kind == FIGHTER_KIND_SHEIK { - let my_charge = WorkModule::get_int(module_accessor, *FIGHTER_SHEIK_INSTANCE_WORK_ID_INT_NEEDLE_COUNT); + let my_charge = WorkModule::get_int( + module_accessor, + *FIGHTER_SHEIK_INSTANCE_WORK_ID_INT_NEEDLE_COUNT, + ); charge_state.int_x(my_charge) } - // Mewtwo Shadowball else if fighter_kind == FIGHTER_KIND_MEWTWO { - let my_charge = WorkModule::get_int(module_accessor, *FIGHTER_MEWTWO_INSTANCE_WORK_ID_INT_SHADOWBALL_CHARGE_FRAME); - let prev_frame = WorkModule::get_int(module_accessor, *FIGHTER_MEWTWO_INSTANCE_WORK_ID_INT_PREV_SHADOWBALL_CHARGE_FRAME); - let ball_had = WorkModule::is_flag(module_accessor, *FIGHTER_MEWTWO_INSTANCE_WORK_ID_FLAG_SHADOWBALL_HAD); - charge_state.int_x(my_charge).int_y(prev_frame).has_charge(ball_had) + let my_charge = WorkModule::get_int( + module_accessor, + *FIGHTER_MEWTWO_INSTANCE_WORK_ID_INT_SHADOWBALL_CHARGE_FRAME, + ); + let prev_frame = WorkModule::get_int( + module_accessor, + *FIGHTER_MEWTWO_INSTANCE_WORK_ID_INT_PREV_SHADOWBALL_CHARGE_FRAME, + ); + let ball_had = WorkModule::is_flag( + module_accessor, + *FIGHTER_MEWTWO_INSTANCE_WORK_ID_FLAG_SHADOWBALL_HAD, + ); + charge_state + .int_x(my_charge) + .int_y(prev_frame) + .has_charge(ball_had) } - // Game and Watch Bucket else if fighter_kind == FIGHTER_KIND_GAMEWATCH { - let my_charge = WorkModule::get_float(module_accessor, *FIGHTER_GAMEWATCH_INSTANCE_WORK_ID_FLOAT_SPECIAL_LW_GAUGE); - let my_attack = WorkModule::get_float(module_accessor, *FIGHTER_GAMEWATCH_INSTANCE_WORK_ID_FLOAT_SPECIAL_LW_ATTACK); + let my_charge = WorkModule::get_float( + module_accessor, + *FIGHTER_GAMEWATCH_INSTANCE_WORK_ID_FLOAT_SPECIAL_LW_GAUGE, + ); + let my_attack = WorkModule::get_float( + module_accessor, + *FIGHTER_GAMEWATCH_INSTANCE_WORK_ID_FLOAT_SPECIAL_LW_ATTACK, + ); charge_state.float_x(my_charge).float_y(my_attack) } - // Wario Waft else if fighter_kind == FIGHTER_KIND_WARIO { let my_charge = WorkModule::get_int(module_accessor, 0x100000BF); // FIGHTER_WARIO_INSTANCE_WORK_ID_INT_GASS_COUNT charge_state.int_x(my_charge) } - // Squirtle Water Gun else if fighter_kind == FIGHTER_KIND_PZENIGAME { - let my_charge = WorkModule::get_int(module_accessor, *FIGHTER_PZENIGAME_INSTANCE_WORK_ID_INT_SPECIAL_N_CHARGE); + let my_charge = WorkModule::get_int( + module_accessor, + *FIGHTER_PZENIGAME_INSTANCE_WORK_ID_INT_SPECIAL_N_CHARGE, + ); charge_state.int_x(my_charge) } - // Lucario Aura Sphere else if fighter_kind == FIGHTER_KIND_LUCARIO { - let my_charge = WorkModule::get_int(module_accessor, *FIGHTER_LUCARIO_INSTANCE_WORK_ID_INT_AURABALL_CHARGE_FRAME); - let prev_frame = WorkModule::get_int(module_accessor, *FIGHTER_LUCARIO_INSTANCE_WORK_ID_INT_PREV_AURABALL_CHARGE_FRAME); - let ball_had = WorkModule::is_flag(module_accessor, *FIGHTER_LUCARIO_INSTANCE_WORK_ID_FLAG_AURABALL_HAD); - charge_state.int_x(my_charge).int_y(prev_frame).has_charge(ball_had) + let my_charge = WorkModule::get_int( + module_accessor, + *FIGHTER_LUCARIO_INSTANCE_WORK_ID_INT_AURABALL_CHARGE_FRAME, + ); + let prev_frame = WorkModule::get_int( + module_accessor, + *FIGHTER_LUCARIO_INSTANCE_WORK_ID_INT_PREV_AURABALL_CHARGE_FRAME, + ); + let ball_had = WorkModule::is_flag( + module_accessor, + *FIGHTER_LUCARIO_INSTANCE_WORK_ID_FLAG_AURABALL_HAD, + ); + charge_state + .int_x(my_charge) + .int_y(prev_frame) + .has_charge(ball_had) } - // ROB Gyro/Laser/Fuel else if fighter_kind == FIGHTER_KIND_ROBOT { - let laser_charge = WorkModule::get_float(module_accessor, *FIGHTER_ROBOT_INSTANCE_WORK_ID_FLOAT_BEAM_ENERGY_VALUE); - let gyro_charge = WorkModule::get_float(module_accessor, *FIGHTER_ROBOT_INSTANCE_WORK_ID_FLOAT_GYRO_CHARGE_VALUE); - let fuel_charge = WorkModule::get_float(module_accessor, *FIGHTER_ROBOT_INSTANCE_WORK_ID_FLOAT_BURNER_ENERGY_VALUE); - charge_state.float_x(laser_charge).float_y(gyro_charge).float_z(fuel_charge) + let laser_charge = WorkModule::get_float( + module_accessor, + *FIGHTER_ROBOT_INSTANCE_WORK_ID_FLOAT_BEAM_ENERGY_VALUE, + ); + let gyro_charge = WorkModule::get_float( + module_accessor, + *FIGHTER_ROBOT_INSTANCE_WORK_ID_FLOAT_GYRO_CHARGE_VALUE, + ); + let fuel_charge = WorkModule::get_float( + module_accessor, + *FIGHTER_ROBOT_INSTANCE_WORK_ID_FLOAT_BURNER_ENERGY_VALUE, + ); + charge_state + .float_x(laser_charge) + .float_y(gyro_charge) + .float_z(fuel_charge) } - // Wii Fit Sun Salutation else if fighter_kind == FIGHTER_KIND_WIIFIT { - let my_charge = WorkModule::get_float(module_accessor, *FIGHTER_WIIFIT_INSTANCE_WORK_ID_FLOAT_SPECIAL_N_CHARGE_LEVEL_RATIO); + let my_charge = WorkModule::get_float( + module_accessor, + *FIGHTER_WIIFIT_INSTANCE_WORK_ID_FLOAT_SPECIAL_N_CHARGE_LEVEL_RATIO, + ); charge_state.float_x(my_charge) } - // Pac-Man Bonus Fruit else if fighter_kind == FIGHTER_KIND_PACMAN { let my_charge = WorkModule::get_int(module_accessor, 0x100000C1); // FIGHTER_PACMAN_INSTANCE_WORK_ID_INT_SPECIAL_N_CHARGE_RANK - let max_have = WorkModule::is_flag(module_accessor, *FIGHTER_PACMAN_INSTANCE_WORK_ID_FLAG_SPECIAL_N_MAX_HAVE_ITEM); + let max_have = WorkModule::is_flag( + module_accessor, + *FIGHTER_PACMAN_INSTANCE_WORK_ID_FLAG_SPECIAL_N_MAX_HAVE_ITEM, + ); charge_state.int_x(my_charge).has_charge(max_have) } - // Robin Thunder Tome Spells else if fighter_kind == FIGHTER_KIND_REFLET { - let my_charge = WorkModule::get_int(module_accessor, *FIGHTER_REFLET_INSTANCE_WORK_ID_INT_SPECIAL_N_THUNDER_KIND); + let my_charge = WorkModule::get_int( + module_accessor, + *FIGHTER_REFLET_INSTANCE_WORK_ID_INT_SPECIAL_N_THUNDER_KIND, + ); charge_state.int_x(my_charge) } - // Plant Poison Breath else if fighter_kind == FIGHTER_KIND_PACKUN { - let my_charge = WorkModule::get_int(module_accessor, *FIGHTER_PACKUN_INSTANCE_WORK_ID_INT_SPECIAL_S_COUNT); + let my_charge = WorkModule::get_int( + module_accessor, + *FIGHTER_PACKUN_INSTANCE_WORK_ID_INT_SPECIAL_S_COUNT, + ); charge_state.int_x(my_charge) } - // Hero (Ka)frizz(le) else if fighter_kind == FIGHTER_KIND_BRAVE { - let my_charge = WorkModule::get_int(module_accessor, *FIGHTER_BRAVE_INSTANCE_WORK_ID_INT_SPECIAL_N_HOLD_FRAME); + let my_charge = WorkModule::get_int( + module_accessor, + *FIGHTER_BRAVE_INSTANCE_WORK_ID_INT_SPECIAL_N_HOLD_FRAME, + ); charge_state.int_x(my_charge) } - // Banjo Wonderwing else if fighter_kind == FIGHTER_KIND_BUDDY { - let my_charge = WorkModule::get_int(module_accessor, *FIGHTER_BUDDY_INSTANCE_WORK_ID_INT_SPECIAL_S_REMAIN); + let my_charge = WorkModule::get_int( + module_accessor, + *FIGHTER_BUDDY_INSTANCE_WORK_ID_INT_SPECIAL_S_REMAIN, + ); charge_state.int_x(my_charge) } - // Mii Gunner Charge Blast else if fighter_kind == FIGHTER_KIND_MIIGUNNER { - let my_charge = WorkModule::get_int(module_accessor, *FIGHTER_MIIGUNNER_INSTANCE_WORK_ID_INT_GUNNER_CHARGE_COUNT); + let my_charge = WorkModule::get_int( + module_accessor, + *FIGHTER_MIIGUNNER_INSTANCE_WORK_ID_INT_GUNNER_CHARGE_COUNT, + ); charge_state.int_x(my_charge) } else { charge_state } } -pub unsafe fn handle_charge(module_accessor: &mut app::BattleObjectModuleAccessor, fighter_kind: i32, charge: ChargeState) { +pub unsafe fn handle_charge( + module_accessor: &mut app::BattleObjectModuleAccessor, + fighter_kind: i32, + charge: ChargeState, +) { // Mario Fludd - 0 to 80 if fighter_kind == FIGHTER_KIND_MARIO { charge.int_x.map(|fludd_charge| { - WorkModule::set_int(module_accessor, fludd_charge, *FIGHTER_MARIO_INSTANCE_WORK_ID_INT_SPECIAL_LW_CHARGE); + WorkModule::set_int( + module_accessor, + fludd_charge, + *FIGHTER_MARIO_INSTANCE_WORK_ID_INT_SPECIAL_LW_CHARGE, + ); if fludd_charge == 80 { EffectModule::req_common(module_accessor, Hash40::new("charge_max"), 0.0); } }); } - // DK Punch - 0 to 110 else if fighter_kind == FIGHTER_KIND_DONKEY { charge.int_x.map(|punch_charge| { - WorkModule::set_int(module_accessor, punch_charge, *FIGHTER_DONKEY_INSTANCE_WORK_ID_INT_SPECIAL_N_COUNT); + WorkModule::set_int( + module_accessor, + punch_charge, + *FIGHTER_DONKEY_INSTANCE_WORK_ID_INT_SPECIAL_N_COUNT, + ); if punch_charge == 110 { - FighterUtil::set_face_motion_by_priority(module_accessor,FighterFacial(*FIGHTER_FACIAL_SPECIAL), Hash40::new("special_n_max_face")); + FighterUtil::set_face_motion_by_priority( + module_accessor, + FighterFacial(*FIGHTER_FACIAL_SPECIAL), + Hash40::new("special_n_max_face"), + ); } }); } - // Samus/Dark Samus Charge Shot - 0 to 112 else if fighter_kind == FIGHTER_KIND_SAMUS || fighter_kind == FIGHTER_KIND_SAMUSD { charge.int_x.map(|shot_charge| { - WorkModule::set_int(module_accessor, shot_charge, *FIGHTER_SAMUS_INSTANCE_WORK_ID_INT_SPECIAL_N_COUNT); + WorkModule::set_int( + module_accessor, + shot_charge, + *FIGHTER_SAMUS_INSTANCE_WORK_ID_INT_SPECIAL_N_COUNT, + ); if shot_charge == 112 { EffectModule::req_common(module_accessor, Hash40::new("charge_max"), 0.0); let samus_cshot_hash; @@ -218,65 +300,127 @@ pub unsafe fn handle_charge(module_accessor: &mut app::BattleObjectModuleAccesso z: 176.373, }; let efh = EffectModule::req_follow( - module_accessor, samus_cshot_hash, - joint_hash, &pos, &rot, 1.0, false, - 0, 0, 0, 0, 0, - false, false + module_accessor, + samus_cshot_hash, + joint_hash, + &pos, + &rot, + 1.0, + false, + 0, + 0, + 0, + 0, + 0, + false, + false, + ); + WorkModule::set_int( + module_accessor, + efh as i32, + *FIGHTER_SAMUS_INSTANCE_WORK_ID_INT_EFH_CHARGE_MAX, ); - WorkModule::set_int(module_accessor, efh as i32, *FIGHTER_SAMUS_INSTANCE_WORK_ID_INT_EFH_CHARGE_MAX); } }); } - // Sheik Needles - 0 to 6 else if fighter_kind == FIGHTER_KIND_SHEIK { charge.int_x.map(|needle_charge| { - WorkModule::set_int(module_accessor, needle_charge, *FIGHTER_SHEIK_INSTANCE_WORK_ID_INT_NEEDLE_COUNT); - ArticleModule::generate_article_enable(module_accessor,*FIGHTER_SHEIK_GENERATE_ARTICLE_NEEDLEHAVE, false, -1); + WorkModule::set_int( + module_accessor, + needle_charge, + *FIGHTER_SHEIK_INSTANCE_WORK_ID_INT_NEEDLE_COUNT, + ); + ArticleModule::generate_article_enable( + module_accessor, + *FIGHTER_SHEIK_GENERATE_ARTICLE_NEEDLEHAVE, + false, + -1, + ); let hash_main = Hash40::new("set_main"); match needle_charge { 6 => { EffectModule::req_common(module_accessor, Hash40::new("charge_max"), 0.0); - ArticleModule::set_visibility(module_accessor,*FIGHTER_SHEIK_GENERATE_ARTICLE_NEEDLEHAVE, - hash_main, Hash40::new("group_main_default"),ArticleOperationTarget(0)); + ArticleModule::set_visibility( + module_accessor, + *FIGHTER_SHEIK_GENERATE_ARTICLE_NEEDLEHAVE, + hash_main, + Hash40::new("group_main_default"), + ArticleOperationTarget(0), + ); } 5 => { - ArticleModule::set_visibility(module_accessor,*FIGHTER_SHEIK_GENERATE_ARTICLE_NEEDLEHAVE, - hash_main, Hash40::new("group_main_5"),ArticleOperationTarget(0)); + ArticleModule::set_visibility( + module_accessor, + *FIGHTER_SHEIK_GENERATE_ARTICLE_NEEDLEHAVE, + hash_main, + Hash40::new("group_main_5"), + ArticleOperationTarget(0), + ); } 4 => { - ArticleModule::set_visibility(module_accessor,*FIGHTER_SHEIK_GENERATE_ARTICLE_NEEDLEHAVE, - hash_main, Hash40::new("group_main_4"),ArticleOperationTarget(0)); + ArticleModule::set_visibility( + module_accessor, + *FIGHTER_SHEIK_GENERATE_ARTICLE_NEEDLEHAVE, + hash_main, + Hash40::new("group_main_4"), + ArticleOperationTarget(0), + ); } 3 => { - ArticleModule::set_visibility(module_accessor,*FIGHTER_SHEIK_GENERATE_ARTICLE_NEEDLEHAVE, - hash_main, Hash40::new("group_main_3"),ArticleOperationTarget(0)); + ArticleModule::set_visibility( + module_accessor, + *FIGHTER_SHEIK_GENERATE_ARTICLE_NEEDLEHAVE, + hash_main, + Hash40::new("group_main_3"), + ArticleOperationTarget(0), + ); } 2 => { - ArticleModule::set_visibility(module_accessor,*FIGHTER_SHEIK_GENERATE_ARTICLE_NEEDLEHAVE, - hash_main, Hash40::new("group_main_2"),ArticleOperationTarget(0)); + ArticleModule::set_visibility( + module_accessor, + *FIGHTER_SHEIK_GENERATE_ARTICLE_NEEDLEHAVE, + hash_main, + Hash40::new("group_main_2"), + ArticleOperationTarget(0), + ); } 1 => { - ArticleModule::set_visibility(module_accessor,*FIGHTER_SHEIK_GENERATE_ARTICLE_NEEDLEHAVE, - hash_main, Hash40::new("group_main_1"),ArticleOperationTarget(0)); + ArticleModule::set_visibility( + module_accessor, + *FIGHTER_SHEIK_GENERATE_ARTICLE_NEEDLEHAVE, + hash_main, + Hash40::new("group_main_1"), + ArticleOperationTarget(0), + ); } _ => { - ArticleModule::set_visibility(module_accessor,*FIGHTER_SHEIK_GENERATE_ARTICLE_NEEDLEHAVE, - hash_main, Hash40::new("group_main_0"),ArticleOperationTarget(0)); + ArticleModule::set_visibility( + module_accessor, + *FIGHTER_SHEIK_GENERATE_ARTICLE_NEEDLEHAVE, + hash_main, + Hash40::new("group_main_0"), + ArticleOperationTarget(0), + ); } - } - }); } - // Mewtwo Shadowball - 0 to 120, Boolean else if fighter_kind == FIGHTER_KIND_MEWTWO { charge.int_x.map(|charge_frame| { - WorkModule::set_int(module_accessor, charge_frame, *FIGHTER_MEWTWO_INSTANCE_WORK_ID_INT_SHADOWBALL_CHARGE_FRAME); + WorkModule::set_int( + module_accessor, + charge_frame, + *FIGHTER_MEWTWO_INSTANCE_WORK_ID_INT_SHADOWBALL_CHARGE_FRAME, + ); }); charge.int_y.map(|prev_frame| { - WorkModule::set_int(module_accessor, prev_frame, *FIGHTER_MEWTWO_INSTANCE_WORK_ID_INT_PREV_SHADOWBALL_CHARGE_FRAME); + WorkModule::set_int( + module_accessor, + prev_frame, + *FIGHTER_MEWTWO_INSTANCE_WORK_ID_INT_PREV_SHADOWBALL_CHARGE_FRAME, + ); if prev_frame == 120 { EffectModule::req_common(module_accessor, Hash40::new("charge_max"), 0.0); let effect_hash = Hash40::new("mewtwo_shadowball_max_hand"); @@ -293,30 +437,65 @@ pub unsafe fn handle_charge(module_accessor: &mut app::BattleObjectModuleAccesso z: 0.0, }; let efh_1 = EffectModule::req_follow( - module_accessor, effect_hash, - joint_hash_1, &pos, &rot, 1.0, false, - 0, 0, -1, 0, 0, - false, false + module_accessor, + effect_hash, + joint_hash_1, + &pos, + &rot, + 1.0, + false, + 0, + 0, + -1, + 0, + 0, + false, + false, ); let efh_2 = EffectModule::req_follow( - module_accessor, effect_hash, - joint_hash_2, &pos, &rot, 1.0, false, - 0, 0, -1, 0, 0, - false, false + module_accessor, + effect_hash, + joint_hash_2, + &pos, + &rot, + 1.0, + false, + 0, + 0, + -1, + 0, + 0, + false, + false, + ); + WorkModule::set_int( + module_accessor, + efh_1 as i32, + *FIGHTER_MEWTWO_INSTANCE_WORK_ID_INT_EF_ID_SHADOWBALL_MAX_L, + ); + WorkModule::set_int( + module_accessor, + efh_2 as i32, + *FIGHTER_MEWTWO_INSTANCE_WORK_ID_INT_EF_ID_SHADOWBALL_MAX_R, ); - WorkModule::set_int(module_accessor, efh_1 as i32, *FIGHTER_MEWTWO_INSTANCE_WORK_ID_INT_EF_ID_SHADOWBALL_MAX_L); - WorkModule::set_int(module_accessor, efh_2 as i32, *FIGHTER_MEWTWO_INSTANCE_WORK_ID_INT_EF_ID_SHADOWBALL_MAX_R); } }); charge.has_charge.map(|has_shadowball| { - WorkModule::set_flag(module_accessor, has_shadowball, *FIGHTER_MEWTWO_INSTANCE_WORK_ID_FLAG_SHADOWBALL_HAD); + WorkModule::set_flag( + module_accessor, + has_shadowball, + *FIGHTER_MEWTWO_INSTANCE_WORK_ID_FLAG_SHADOWBALL_HAD, + ); }); } - // GnW Bucket - 0 to 3, Attack not tested else if fighter_kind == FIGHTER_KIND_GAMEWATCH { charge.float_x.map(|bucket_level| { - WorkModule::set_float(module_accessor, bucket_level, *FIGHTER_GAMEWATCH_INSTANCE_WORK_ID_FLOAT_SPECIAL_LW_GAUGE); + WorkModule::set_float( + module_accessor, + bucket_level, + *FIGHTER_GAMEWATCH_INSTANCE_WORK_ID_FLOAT_SPECIAL_LW_GAUGE, + ); if bucket_level == 3.0 { EffectModule::req_common(module_accessor, Hash40::new("charge_max"), 0.0); } else { @@ -325,34 +504,47 @@ pub unsafe fn handle_charge(module_accessor: &mut app::BattleObjectModuleAccesso } }); charge.float_y.map(|bucket_attack| { - WorkModule::set_float(module_accessor, bucket_attack, *FIGHTER_GAMEWATCH_INSTANCE_WORK_ID_FLOAT_SPECIAL_LW_ATTACK); + WorkModule::set_float( + module_accessor, + bucket_attack, + *FIGHTER_GAMEWATCH_INSTANCE_WORK_ID_FLOAT_SPECIAL_LW_ATTACK, + ); }); } - // Wario Waft - 0 to 6000 else if fighter_kind == FIGHTER_KIND_WARIO { charge.int_x.map(|waft_count| { WorkModule::set_int(module_accessor, waft_count, 0x100000BF); // FIGHTER_WARIO_INSTANCE_WORK_ID_INT_GASS_COUNT }); } - // Squirtle Water Gun - 0 to 45 else if fighter_kind == FIGHTER_KIND_PZENIGAME { charge.int_x.map(|water_charge| { - WorkModule::set_int(module_accessor, water_charge, *FIGHTER_PZENIGAME_INSTANCE_WORK_ID_INT_SPECIAL_N_CHARGE); + WorkModule::set_int( + module_accessor, + water_charge, + *FIGHTER_PZENIGAME_INSTANCE_WORK_ID_INT_SPECIAL_N_CHARGE, + ); if water_charge == 45 { EffectModule::req_common(module_accessor, Hash40::new("charge_max"), 0.0); } }); } - // Lucario Aura Sphere - 0 to 90, Boolean else if fighter_kind == FIGHTER_KIND_LUCARIO { charge.int_x.map(|charge_frame| { - WorkModule::set_int(module_accessor, charge_frame, *FIGHTER_LUCARIO_INSTANCE_WORK_ID_INT_AURABALL_CHARGE_FRAME); + WorkModule::set_int( + module_accessor, + charge_frame, + *FIGHTER_LUCARIO_INSTANCE_WORK_ID_INT_AURABALL_CHARGE_FRAME, + ); }); charge.int_y.map(|prev_frame| { - WorkModule::set_int(module_accessor, prev_frame, *FIGHTER_LUCARIO_INSTANCE_WORK_ID_INT_PREV_AURABALL_CHARGE_FRAME); + WorkModule::set_int( + module_accessor, + prev_frame, + *FIGHTER_LUCARIO_INSTANCE_WORK_ID_INT_PREV_AURABALL_CHARGE_FRAME, + ); if prev_frame == 90 { EffectModule::req_common(module_accessor, Hash40::new("charge_max"), 0.0); let effect_hash_1 = Hash40::new("lucario_hadoudan_max_l"); @@ -370,70 +562,122 @@ pub unsafe fn handle_charge(module_accessor: &mut app::BattleObjectModuleAccesso z: 0.0, }; let efh_1 = EffectModule::req_follow( - module_accessor, effect_hash_1, - joint_hash_1, &pos, &rot, 1.0, false, - 0, 0, -1, 0, 0, - false, false + module_accessor, + effect_hash_1, + joint_hash_1, + &pos, + &rot, + 1.0, + false, + 0, + 0, + -1, + 0, + 0, + false, + false, ); let efh_2 = EffectModule::req_follow( - module_accessor, effect_hash_2, - joint_hash_2, &pos, &rot, 1.0, false, - 0, 0, -1, 0, 0, - false, false + module_accessor, + effect_hash_2, + joint_hash_2, + &pos, + &rot, + 1.0, + false, + 0, + 0, + -1, + 0, + 0, + false, + false, + ); + WorkModule::set_int( + module_accessor, + efh_1 as i32, + *FIGHTER_LUCARIO_INSTANCE_WORK_ID_INT_EF_ID_AURABALL_MAX_L, + ); + WorkModule::set_int( + module_accessor, + efh_2 as i32, + *FIGHTER_LUCARIO_INSTANCE_WORK_ID_INT_EF_ID_AURABALL_MAX_R, ); - WorkModule::set_int(module_accessor, efh_1 as i32, *FIGHTER_LUCARIO_INSTANCE_WORK_ID_INT_EF_ID_AURABALL_MAX_L); - WorkModule::set_int(module_accessor, efh_2 as i32, *FIGHTER_LUCARIO_INSTANCE_WORK_ID_INT_EF_ID_AURABALL_MAX_R); } }); charge.has_charge.map(|has_aurasphere| { - WorkModule::set_flag(module_accessor, has_aurasphere, *FIGHTER_LUCARIO_INSTANCE_WORK_ID_FLAG_AURABALL_HAD); + WorkModule::set_flag( + module_accessor, + has_aurasphere, + *FIGHTER_LUCARIO_INSTANCE_WORK_ID_FLAG_AURABALL_HAD, + ); }); } - // ROB Gyro/Laser/Fuel - Gyro from 0 to 90, rest unchecked else if fighter_kind == FIGHTER_KIND_ROBOT { charge.float_x.map(|beam_energy| { - WorkModule::set_float(module_accessor, beam_energy, *FIGHTER_ROBOT_INSTANCE_WORK_ID_FLOAT_BEAM_ENERGY_VALUE); + WorkModule::set_float( + module_accessor, + beam_energy, + *FIGHTER_ROBOT_INSTANCE_WORK_ID_FLOAT_BEAM_ENERGY_VALUE, + ); }); charge.float_y.map(|gyro_charge| { - WorkModule::set_float(module_accessor, gyro_charge, *FIGHTER_ROBOT_INSTANCE_WORK_ID_FLOAT_GYRO_CHARGE_VALUE); + WorkModule::set_float( + module_accessor, + gyro_charge, + *FIGHTER_ROBOT_INSTANCE_WORK_ID_FLOAT_GYRO_CHARGE_VALUE, + ); if gyro_charge == 90.0 { EffectModule::req_common(module_accessor, Hash40::new("charge_max"), 0.0); } }); charge.float_z.map(|burner_energy| { - WorkModule::set_float(module_accessor, burner_energy, *FIGHTER_ROBOT_INSTANCE_WORK_ID_FLOAT_BURNER_ENERGY_VALUE); + WorkModule::set_float( + module_accessor, + burner_energy, + *FIGHTER_ROBOT_INSTANCE_WORK_ID_FLOAT_BURNER_ENERGY_VALUE, + ); }); } - // Wii Fit Sun Salutation - 0 to 1 else if fighter_kind == FIGHTER_KIND_WIIFIT { charge.float_x.map(|sun_ratio| { - WorkModule::set_float(module_accessor, sun_ratio, *FIGHTER_WIIFIT_INSTANCE_WORK_ID_FLOAT_SPECIAL_N_CHARGE_LEVEL_RATIO) + WorkModule::set_float( + module_accessor, + sun_ratio, + *FIGHTER_WIIFIT_INSTANCE_WORK_ID_FLOAT_SPECIAL_N_CHARGE_LEVEL_RATIO, + ) }); } - // Pac-Man Bonus Fruit - 0 to 12 else if fighter_kind == FIGHTER_KIND_PACMAN { charge.int_x.map(|charge_rank| { WorkModule::set_int(module_accessor, charge_rank, 0x100000C1); // FIGHTER_PACMAN_INSTANCE_WORK_ID_INT_SPECIAL_N_CHARGE_RANK - + if charge_rank == 12 { EffectModule::req_common(module_accessor, Hash40::new("charge_max"), 0.0); } }); charge.has_charge.map(|has_fruit| { - WorkModule::set_flag(module_accessor, has_fruit, *FIGHTER_PACMAN_INSTANCE_WORK_ID_FLAG_SPECIAL_N_MAX_HAVE_ITEM); + WorkModule::set_flag( + module_accessor, + has_fruit, + *FIGHTER_PACMAN_INSTANCE_WORK_ID_FLAG_SPECIAL_N_MAX_HAVE_ITEM, + ); }); } - // Robin Thunder Tome Spells - 0 to 3 else if fighter_kind == FIGHTER_KIND_REFLET { charge.int_x.map(|thunder_kind| { - WorkModule::set_int(module_accessor, thunder_kind, *FIGHTER_REFLET_INSTANCE_WORK_ID_INT_SPECIAL_N_THUNDER_KIND); - if thunder_kind == 3 { + WorkModule::set_int( + module_accessor, + thunder_kind, + *FIGHTER_REFLET_INSTANCE_WORK_ID_INT_SPECIAL_N_THUNDER_KIND, + ); + if thunder_kind == 3 { EffectModule::req_common(module_accessor, Hash40::new("charge_max"), 0.0); - let reflet_hash = Hash40::new("reflet_thunder_max"); + let reflet_hash = Hash40::new("reflet_thunder_max"); let joint_hash = Hash40::new("handl"); let pos = Vector3f { x: 1.0, @@ -446,19 +690,32 @@ pub unsafe fn handle_charge(module_accessor: &mut app::BattleObjectModuleAccesso z: 0.0, }; EffectModule::req_follow( - module_accessor, reflet_hash, - joint_hash, &pos, &rot, 1.0, false, - 0, 0, -1, 0, 0, - false, false + module_accessor, + reflet_hash, + joint_hash, + &pos, + &rot, + 1.0, + false, + 0, + 0, + -1, + 0, + 0, + false, + false, ); } }); } - // Mii Gunner Charge Blast - 0 to 120 else if fighter_kind == FIGHTER_KIND_MIIGUNNER { charge.int_x.map(|blast_charge| { - WorkModule::set_int(module_accessor, blast_charge, *FIGHTER_MIIGUNNER_INSTANCE_WORK_ID_INT_GUNNER_CHARGE_COUNT); + WorkModule::set_int( + module_accessor, + blast_charge, + *FIGHTER_MIIGUNNER_INSTANCE_WORK_ID_INT_GUNNER_CHARGE_COUNT, + ); if blast_charge == 120 { EffectModule::req_common(module_accessor, Hash40::new("charge_max"), 0.0); let gunner_hash = Hash40::new("miigunner_cshot_max"); @@ -474,23 +731,40 @@ pub unsafe fn handle_charge(module_accessor: &mut app::BattleObjectModuleAccesso z: 0.0, }; let efh = EffectModule::req_follow( - module_accessor, gunner_hash, - joint_hash, &pos, &rot, 1.0, false, - 0, 0, 0, 0, 0, - false, false + module_accessor, + gunner_hash, + joint_hash, + &pos, + &rot, + 1.0, + false, + 0, + 0, + 0, + 0, + 0, + false, + false, + ); + WorkModule::set_int( + module_accessor, + efh as i32, + *FIGHTER_MIIGUNNER_INSTANCE_WORK_ID_INT_EFH_CHARGE_MAX, ); - WorkModule::set_int(module_accessor, efh as i32, *FIGHTER_MIIGUNNER_INSTANCE_WORK_ID_INT_EFH_CHARGE_MAX); } }); } - // Plant Poison - 0 to 75 else if fighter_kind == FIGHTER_KIND_PACKUN { charge.int_x.map(|poison_count| { - WorkModule::set_int(module_accessor, poison_count, *FIGHTER_PACKUN_INSTANCE_WORK_ID_INT_SPECIAL_S_COUNT); - if poison_count == 75 { + WorkModule::set_int( + module_accessor, + poison_count, + *FIGHTER_PACKUN_INSTANCE_WORK_ID_INT_SPECIAL_S_COUNT, + ); + if poison_count == 75 { EffectModule::req_common(module_accessor, Hash40::new("charge_max"), 0.0); - let plant_hash = Hash40::new("packun_poison_max_smoke"); + let plant_hash = Hash40::new("packun_poison_max_smoke"); let joint_hash = Hash40::new("hip"); let pos = Vector3f { x: 0.0, @@ -503,31 +777,49 @@ pub unsafe fn handle_charge(module_accessor: &mut app::BattleObjectModuleAccesso z: 0.0, }; let efh = EffectModule::req_follow( - module_accessor, plant_hash, - joint_hash, &pos, &rot, 1.0, false, - 32768, 0, -1, 0, 0, - false, false + module_accessor, + plant_hash, + joint_hash, + &pos, + &rot, + 1.0, + false, + 32768, + 0, + -1, + 0, + 0, + false, + false, + ); + WorkModule::set_int( + module_accessor, + efh as i32, + *FIGHTER_PACKUN_INSTANCE_WORK_ID_INT_SPECIAL_S_CHARGE_MAX_EFFECT_HANDLE, ); - WorkModule::set_int(module_accessor, efh as i32, *FIGHTER_PACKUN_INSTANCE_WORK_ID_INT_SPECIAL_S_CHARGE_MAX_EFFECT_HANDLE); } }); } - // Hero (Ka)frizz(le) - 0 to 81 else if fighter_kind == FIGHTER_KIND_BRAVE { EffectModule::remove_common(module_accessor, Hash40::new("charge_max")); WorkModule::off_flag(module_accessor, 0x200000E8); // FIGHTER_BRAVE_INSTANCE_WORK_ID_FLAG_SPECIAL_N_MAX_EFFECT charge.int_x.map(|frizz_charge| { - WorkModule::set_int(module_accessor, frizz_charge, *FIGHTER_BRAVE_INSTANCE_WORK_ID_INT_SPECIAL_N_HOLD_FRAME); + WorkModule::set_int( + module_accessor, + frizz_charge, + *FIGHTER_BRAVE_INSTANCE_WORK_ID_INT_SPECIAL_N_HOLD_FRAME, + ); }); } - // Banjo Wonderwing - 0 to 5 else if fighter_kind == FIGHTER_KIND_BUDDY { charge.int_x.map(|wing_remain| { - WorkModule::set_int(module_accessor, wing_remain, *FIGHTER_BUDDY_INSTANCE_WORK_ID_INT_SPECIAL_S_REMAIN); + WorkModule::set_int( + module_accessor, + wing_remain, + *FIGHTER_BUDDY_INSTANCE_WORK_ID_INT_SPECIAL_S_REMAIN, + ); }); } - - return; } diff --git a/src/training/ledge.rs b/src/training/ledge.rs index c433274..96c452e 100644 --- a/src/training/ledge.rs +++ b/src/training/ledge.rs @@ -64,13 +64,14 @@ pub unsafe fn force_option(module_accessor: &mut app::BattleObjectModuleAccessor reset_ledge_delay(); return; } - + // Need to roll ledge delay so we know if getup needs to be buffered roll_ledge_delay(); roll_ledge_case(); // This flag is false when needing to buffer, and true when getting up - let flag_cliff = WorkModule::is_flag(module_accessor,*FIGHTER_INSTANCE_WORK_ID_FLAG_CATCH_CLIFF); + let flag_cliff = + WorkModule::is_flag(module_accessor, *FIGHTER_INSTANCE_WORK_ID_FLAG_CATCH_CLIFF); let current_frame = MotionModule::frame(module_accessor) as i32; let should_buffer = (LEDGE_DELAY == 0) && (current_frame == 19) && (!flag_cliff); @@ -105,7 +106,6 @@ pub unsafe fn force_option(module_accessor: &mut app::BattleObjectModuleAccessor } _ => mash::perform_defensive_option(), } - } pub unsafe fn is_enable_transition_term( diff --git a/src/training/mod.rs b/src/training/mod.rs index 9158cb8..ef47520 100644 --- a/src/training/mod.rs +++ b/src/training/mod.rs @@ -9,6 +9,7 @@ use smash::params::*; use smash::phx::{Hash40, Vector3f}; pub mod buff; +pub mod charge; pub mod combo; pub mod directional_influence; pub mod frame_counter; @@ -17,7 +18,6 @@ pub mod sdi; pub mod shield; pub mod tech; pub mod throw; -pub mod charge; mod air_dodge_direction; mod attack_angle; @@ -354,7 +354,7 @@ pub unsafe fn handle_check_doyle_summon_dispatch( return 4294967295; } } - return ori; + ori } // Set Stale Moves to On @@ -373,7 +373,7 @@ static STALE_MENU_OFFSET: usize = 0x013e88a0; #[skyline::hook(offset=STALE_MENU_OFFSET, inline)] unsafe fn stale_menu_handle(ctx: &mut InlineCtx) { // Set the text pointer to where "mel_training_on" is located - let on_text_ptr = ((getRegionAddress(Region::Text) as u64) + (0x42b215e as u64)) as u64; + let on_text_ptr = ((getRegionAddress(Region::Text) as u64) + (0x42b215e)) as u64; let x1 = ctx.registers[1].x.as_mut(); *x1 = on_text_ptr; } diff --git a/src/training/save_states.rs b/src/training/save_states.rs index e654bc5..adf05b5 100644 --- a/src/training/save_states.rs +++ b/src/training/save_states.rs @@ -5,8 +5,8 @@ use crate::common::consts::SaveStateMirroring; use crate::common::is_dead; use crate::common::MENU; use crate::training::buff; -use crate::training::reset; use crate::training::charge::{self, ChargeState}; +use crate::training::reset; use smash::app::{self, lua_bind::*}; use smash::hash40; use smash::lib::lua_const::*; @@ -87,7 +87,7 @@ pub unsafe fn is_killing() -> bool { if SAVE_STATE_PLAYER.state == KillPlayer || SAVE_STATE_CPU.state == KillPlayer { return true; } - return false; + false } pub unsafe fn should_mirror() -> f32 { @@ -234,14 +234,14 @@ pub unsafe fn save_states(module_accessor: &mut app::BattleObjectModuleAccessor) CameraModule::zoom_out(module_accessor, 0); // Remove blue effect (but does not remove darkened screen) EffectModule::kill_kind( - module_accessor, + module_accessor, Hash40::new("sys_bg_criticalhit"), - false, - false + false, + false, ); // Removes the darkened screen from special zooms // If there's a crit that doesn't get removed, it's likely bg_criticalhit2. - EffectModule::remove_screen(module_accessor,Hash40::new("bg_criticalhit"),0); + EffectModule::remove_screen(module_accessor, Hash40::new("bg_criticalhit"), 0); // Remove all quakes to prevent screen shake lingering through load. for quake_kind in *CAMERA_QUAKE_KIND_NONE..=*CAMERA_QUAKE_KIND_MAX { CameraModule::stop_quake(module_accessor, quake_kind); @@ -325,7 +325,7 @@ pub unsafe fn save_states(module_accessor: &mut app::BattleObjectModuleAccessor) } // Perform fighter specific loading actions save_state.steve_state.map(|load_steve| { - steve::load_steve_state(module_accessor,load_steve); + steve::load_steve_state(module_accessor, load_steve); }); // Play Training Reset SFX, since silence is eerie // Only play for the CPU so we don't have 2 overlapping diff --git a/src/training/throw.rs b/src/training/throw.rs index 6b57d84..606c694 100644 --- a/src/training/throw.rs +++ b/src/training/throw.rs @@ -150,5 +150,5 @@ pub unsafe fn get_command_flag_throw_direction( return cmd; } - return 0; + 0 } diff --git a/training_mod_tui/src/lib.rs b/training_mod_tui/src/lib.rs index 76c4dcf..2ac8da3 100644 --- a/training_mod_tui/src/lib.rs +++ b/training_mod_tui/src/lib.rs @@ -387,6 +387,7 @@ pub fn ui(f: &mut Frame, app: &mut App) -> String { f.render_stateful_widget(list, list_chunks[list_section], &mut state); } + // TODO: Add Save Defaults let help_paragraph = Paragraph::new( item_help.unwrap_or("").replace("\"", "") + "\nA: Enter sub-menu | B: Exit menu | ZL/ZR: Next tab"