diff --git a/src/common/mod.rs b/src/common/mod.rs index b599600..d7394d7 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -18,35 +18,47 @@ pub static menu : consts::TrainingModpackMenu = consts::TrainingModpackMenu{ DEFENSIVE_STATE : RANDOM_DEFENSIVE, }; -static mut fighter_manager: FighterManager = FighterManager{ _address: 0 }; +pub static mut fighter_manager_addr : usize = 0; extern "C" { #[link_name = "\u{1}_ZN3app9smashball16is_training_modeEv"] pub fn is_training_mode() -> bool; } -pub fn get_category(module_accessor: &mut app::BattleObjectModuleAccessor) -> i32 { +pub fn get_category( + module_accessor: &mut app::BattleObjectModuleAccessor) -> i32 +{ return (module_accessor.info >> 28) as u8 as i32; } -pub unsafe fn is_operation_cpu(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool { +pub unsafe fn is_operation_cpu( + module_accessor: &mut app::BattleObjectModuleAccessor) -> bool +{ if get_category(module_accessor) as i32 != BATTLE_OBJECT_CATEGORY_FIGHTER { return false } - let entry_id = app::FighterEntryID(WorkModule::get_int(module_accessor, *FIGHTER_INSTANCE_WORK_ID_INT_ENTRY_ID) as i32); - let fighter_information = lua_bind::FighterManager::get_fighter_information(&mut fighter_manager, entry_id) as *mut FighterInformation; + let entry_id_int = WorkModule::get_int(module_accessor, *FIGHTER_INSTANCE_WORK_ID_INT_ENTRY_ID) as i32; + let entry_id = app::FighterEntryID(entry_id_int); + // let mut mgr = FighterManager{_address : fighter_manager_addr as u64}; + // let fighter_information = lua_bind::FighterManager::get_fighter_information(&mut mgr, entry_id) as *mut FighterInformation; + // println!("FighterInformation: {:#?}", fighter_information); - lua_bind::FighterInformation::is_operation_cpu(fighter_information) + // lua_bind::FighterInformation::is_operation_cpu(fighter_information) + entry_id_int > 0 } -pub unsafe fn is_in_hitstun(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool { +pub unsafe fn is_in_hitstun( + module_accessor: &mut app::BattleObjectModuleAccessor) -> bool +{ let status_kind = StatusModule::status_kind(module_accessor) as i32; (FIGHTER_STATUS_KIND_DAMAGE..=FIGHTER_STATUS_KIND_DAMAGE_FALL) .contains(&status_kind) } -pub unsafe fn is_in_shieldstun(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool { +pub unsafe fn is_in_shieldstun( + module_accessor: &mut app::BattleObjectModuleAccessor) -> bool +{ let status_kind = StatusModule::status_kind(module_accessor) as i32; let prev_status = StatusModule::prev_status_kind(module_accessor, 0) as i32; // If we are taking shield damage or we are droping shield from taking shield damage we are in hitstun @@ -59,33 +71,41 @@ pub unsafe fn is_in_shieldstun(module_accessor: &mut app::BattleObjectModuleAcce } -pub unsafe fn is_in_landing(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool { +pub unsafe fn is_in_landing( + module_accessor: &mut app::BattleObjectModuleAccessor) -> bool +{ let status_kind = StatusModule::status_kind(module_accessor) as i32; (FIGHTER_STATUS_KIND_LANDING..=FIGHTER_STATUS_KIND_LANDING_DAMAGE_LIGHT) .contains(&status_kind) } -pub unsafe fn perform_defensive_option(module_accessor: &mut app::BattleObjectModuleAccessor, flag: &mut i32) { - if menu.DEFENSIVE_STATE == RANDOM_DEFENSIVE { - let random_cmds = vec![ - *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE, - *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE_F, - *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE_B, - *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_N - ]; - - let random_cmd_index = app::sv_math::rand(hash40("fighter"), random_cmds.len() as i32) as usize; - *flag |= random_cmds[random_cmd_index]; - } else if menu.DEFENSIVE_STATE == DEFENSIVE_ROLL { - if app::sv_math::rand(hash40("fighter"), 2) == 0 { - *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE_F; - } else { - *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE_B; - } - } else if menu.DEFENSIVE_STATE == DEFENSIVE_SPOTDODGE { - *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE; - } else if menu.DEFENSIVE_STATE == DEFENSIVE_JAB { - *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_N; +pub unsafe fn perform_defensive_option( + module_accessor: &mut app::BattleObjectModuleAccessor, + flag: &mut i32) +{ + match menu.DEFENSIVE_STATE { + RANDOM_DEFENSIVE => { + let random_cmds = vec![ + *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE, + *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE_F, + *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE_B, + *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_N + ]; + + let random_cmd_index = app::sv_math::rand( + hash40("fighter"), random_cmds.len() as i32) as usize; + *flag |= random_cmds[random_cmd_index]; + }, + DEFENSIVE_ROLL => { + if app::sv_math::rand(hash40("fighter"), 2) == 0 { + *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE_F; + } else { + *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE_B; + } + }, + DEFENSIVE_SPOTDODGE => *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE, + DEFENSIVE_JAB => *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_N, + _ => () } } \ No newline at end of file diff --git a/src/hitbox_visualizer/mod.rs b/src/hitbox_visualizer/mod.rs index bc0fcbc..bbbdc7f 100644 --- a/src/hitbox_visualizer/mod.rs +++ b/src/hitbox_visualizer/mod.rs @@ -1,13 +1,12 @@ use smash::hash40; -use smash::app::BattleObjectModuleAccessor; -use smash::app::sv_animcmd::{self}; -use smash::app::lua_bind::*; -use smash::lib::{self, L2CAgent, L2CValue}; -use smash::phx::{Hash40, Vector3f}; -use smash::lib::lua_const::{*}; -use smash::app::sv_system::{self}; use smash::app::{self}; -use skyline::logging::hex_dump_ptr; +use smash::app::sv_animcmd::{self}; +use smash::app::sv_system::{self}; +use smash::app::lua_bind::*; +use smash::lib::lua_const::*; +use smash::lib::{L2CAgent, L2CValue, L2CValueType}; +use smash::phx::{Hash40, Vector3f}; +use skyline::{logging::HexDump}; use crate::common::*; /** @@ -108,7 +107,7 @@ pub unsafe fn generate_hitbox_effects(l2c_agent: &mut L2CAgent, bone: L2CValue, let y_dist : f32; let z_dist : f32; let mut n_effects : i32; - if let lib::L2CValueType::Void = x2.val_type{ // && let lib::L2CValueType::Void = y2.val_type && let lib::L2CValueType::Void = z2.val_type { // extended hitbox + if let L2CValueType::Void = x2.val_type { // && let lib::L2CValueType::Void = y2.val_type && let lib::L2CValueType::Void = z2.val_type { // extended hitbox x_dist = 0.0; y_dist = 0.0; z_dist = 0.0; n_effects = 1; } @@ -177,7 +176,7 @@ unsafe fn handle_attack(lua_state: u64) { if menu.HITBOX_VIS && is_training_mode() { // generate hitbox effect(s) let color_scale: f32; - if false { // color intensity scales with damage + if true { // color intensity scales with damage color_scale = unlerp_bounded(1.0, 18.0, damage.get_num()); } else { // color intensity scales with total KB // calculate the expected KB a character with 95 weight will receive @@ -232,14 +231,14 @@ unsafe fn handle_catch(lua_state: u64) { } } -pub unsafe fn is_shielding(module_accessor: *mut BattleObjectModuleAccessor) -> bool { +pub unsafe fn is_shielding(module_accessor: *mut app::BattleObjectModuleAccessor) -> bool { let status_kind = StatusModule::status_kind(module_accessor) as i32; (FIGHTER_STATUS_KIND_GUARD_ON..=FIGHTER_STATUS_KIND_GUARD_OFF).contains(&status_kind) } #[allow(unused_unsafe)] #[skyline::hook(replace = AttackModule::clear_all)] -pub unsafe fn handle_clear_all(module_accessor: *mut BattleObjectModuleAccessor) { +pub unsafe fn handle_clear_all(module_accessor: *mut app::BattleObjectModuleAccessor) { if is_training_mode() { // only if we're not shielding if !is_shielding(module_accessor) { @@ -252,7 +251,7 @@ pub unsafe fn handle_clear_all(module_accessor: *mut BattleObjectModuleAccessor) #[allow(unused_unsafe)] #[skyline::hook(replace = GrabModule::set_rebound)] -pub unsafe fn handle_set_rebound(module_accessor: *mut BattleObjectModuleAccessor, rebound: bool) { +pub unsafe fn handle_set_rebound(module_accessor: *mut app::BattleObjectModuleAccessor, rebound: bool) { if is_training_mode() && rebound == false { // only if we're not shielding if !is_shielding(module_accessor) { diff --git a/src/lib.rs b/src/lib.rs index dcca399..000da36 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -21,37 +21,87 @@ use skyline::libc::{size_t, c_int, c_void, strlen}; use smash::Result; use skyline::nn; use skyline::patching::patch_data_from_text; -use skyline::{from_c_str, c_str}; +use skyline::{from_c_str, c_str, hooks::A64HookFunction}; use std::fs; +use skyline::nro::{self, NroInfo}; + +extern "C" { + #[link_name = "\u{1}_ZN7lua2cpp16L2CFighterCommon28status_AttackAir_Main_commonEv"] + pub fn status_AttackAirMain_common( + arg1: *mut L2CAgent + ) -> u64; + + #[link_name = "\u{1}_ZN7lua2cpp27L2CFighterAnimcmdGameCommon21game_BatSwing4Common1Ev"] + pub fn game_BatSwing4Common1( + arg1: *mut L2CAgent + ) -> u64; + + #[link_name = "\u{1}_ZN7lua2cpp27L2CFighterAnimcmdGameCommon21game_BatSwing4Common2Ev"] + pub fn game_BatSwing4Common2( + arg1: *mut L2CAgent + ) -> u64; +} #[allow(unused_unsafe)] -#[skyline::hook(replace = nn::ro::LoadModule)] -pub unsafe fn handle_load_module( - p_out_module: *mut skyline::nn::ro::Module, - p_image: *const c_void, - buffer: *mut c_void, - buffer_size: size_t, - flag: c_int) -> Result { +#[skyline::hook(replace = status_AttackAirMain_common)] +pub unsafe fn handle_AttackAirMain(fighter: *mut L2CAgent) { + CancelModule::enable_cancel(sv_system::battle_object_module_accessor((*fighter).lua_state_agent)); + original!()(fighter); +} - let ret = original!()(p_out_module, p_image, buffer, buffer_size, flag); +#[allow(unused_unsafe)] +#[skyline::hook(replace = game_BatSwing4Common1)] +pub unsafe fn handle_game_BatSwing4Common1(fighter: *mut L2CAgent) { + println!("[handle_game_BatSwing4Common1]"); + original!()(fighter); +} - let name = from_c_str(&(*p_out_module).Name as *const u8); - println!("[handleLoadModule] NRO name: {}\n", name); - let text_start = (*(*p_out_module).ModuleObject).module_base; - println!("Module base: {}\n", text_start); - if name.starts_with("common") { - println!("Is common!"); - // raw const_value_table is at : 0x635b70 - let fighter_status_kind_fall : u64 = 0x8ee6c39e9be4f0b5; - let res = match patch_data_from_text(text_start as *const u8, 0x6362b8, &fighter_status_kind_fall) { - Ok(v) => format!("Patched!"), - Err(e) => format!("Error patching with e: {}", e) - }; - - println!("{}", res); +#[allow(unused_unsafe)] +#[skyline::hook(replace = game_BatSwing4Common2)] +pub unsafe fn handle_game_BatSwing4Common2(fighter: *mut L2CAgent) { + println!("[handle_game_BatSwing4Common2]"); + sv_animcmd::frame((*fighter).lua_state_agent, 0x30 as f32); + if sv_animcmd::is_excute((*fighter).lua_state_agent) { + hitbox_visualizer::wrap(sv_animcmd::EFFECT_FOLLOW_NO_SCALE, + &mut (*fighter), + &mut [ + L2CValue::new_int(hash40("sys_shield")), L2CValue::new_int(hash40("top")), + L2CValue::new_num(0.0), L2CValue::new_num(0.0), L2CValue::new_num(0.0), L2CValue::new_num(0.0), L2CValue::new_num(0.0), L2CValue::new_num(0.0), + L2CValue::new_num(1.0), L2CValue::new_bool(false)].to_vec()); } + original!()(fighter); +} - ret +fn nro_main(nro: &NroInfo) { + match nro.name { + "common" => + { + println!("Loaded common NRO!"); + unsafe { + let text_start = (*(*nro.module).ModuleObject).module_base; + println!("Common Text Start: {:x}", text_start); + // raw const_value_table is at : 0x635b70 + let fighter_status_kind_fall : u64 = 0x8ee6c39e9be4f0b5; + // let res = match patch_data_from_text(text_start as *const u8, 0x6362b8, &fighter_status_kind_fall) { + // Ok(v) => format!("Patched!"), + // Err(e) => format!("Error patching with e: {}", e) + // }; + let fighter_kind_popo : u64 = 0x04aa7a0e945950d5; + let res = match patch_data_from_text(text_start as *const u8, 0x638d78, &fighter_kind_popo) { + Ok(v) => format!("Patched!"), + Err(e) => format!("Error patching with e: {}", e) + }; + println!("Result: {}", res); + + // skyline::install_hook!(handle_AttackAirMain); + // skyline::install_hook!(handle_game_BatSwing4Common1); + // skyline::install_hook!(handle_game_BatSwing4Common2); + println!("Hooked!"); + } + }, + "item" => println!("Loaded item NRO!"), + _ => () + } } #[skyline::main(name = "test")] @@ -59,10 +109,11 @@ pub fn main() { println!("Training modpack initialized."); hitbox_visualizer::hitbox_visualization(); training::training_mods(); + nro::add_hook(nro_main).unwrap(); - println!("OpenMode_Write: {} {}", nn::fs::OpenMode_OpenMode_Write, nn::fs::OpenMode_OpenMode_Write as i32); - let buffer = format!("{:x}", &common::menu as *const _ as u64); - println!("Writing training_modpack.log with {}...\n", buffer); + // println!("OpenMode_Write: {} {}", nn::fs::OpenMode_OpenMode_Write, nn::fs::OpenMode_OpenMode_Write as i32); + // let buffer = format!("{:x}", &common::menu as *const _ as u64); + // println!("Writing training_modpack.log with {}...\n", buffer); - // skyline::install_hook!(handle_load_module); + // fs::File::create("sd:/test.log").unwrap(); } diff --git a/src/training/DirectionalInfluence.rs b/src/training/DirectionalInfluence.rs new file mode 100644 index 0000000..e0d213d --- /dev/null +++ b/src/training/DirectionalInfluence.rs @@ -0,0 +1,40 @@ +use smash::hash40; +use smash::app::{self}; +use smash::app::lua_bind::*; +use smash::lib::lua_const::*; +use crate::common::*; +use crate::common::consts::*; +use core::f64::consts::PI; + + +pub unsafe fn get_float(module_accessor: &mut app::BattleObjectModuleAccessor, var: i32) -> Option { + if var == FIGHTER_STATUS_DAMAGE_WORK_FLOAT_VECOR_CORRECT_STICK_X || + var == FIGHTER_STATUS_DAMAGE_WORK_FLOAT_VECOR_CORRECT_STICK_Y { + if is_training_mode() && + is_operation_cpu(module_accessor) && + is_in_hitstun(module_accessor) { + if menu.DI_STATE != NONE { + let mut angle = (menu.DI_STATE - 1) as f64 * PI / 4.0; + + // Either 0 (right) or PI (left) + if menu.DI_STATE == DI_RANDOM_IN_AWAY { + angle = app::sv_math::rand(hash40("fighter"), 2) as f64 * PI; + } + // If facing left, reverse angle + if PostureModule::lr(module_accessor) != -1.0 { + angle -= PI; + } + + if var == FIGHTER_STATUS_DAMAGE_WORK_FLOAT_VECOR_CORRECT_STICK_X { + return Some(angle.cos() as f32) + } + + if var == FIGHTER_STATUS_DAMAGE_WORK_FLOAT_VECOR_CORRECT_STICK_Y { + return Some(angle.sin() as f32) + } + } + } + } + + None +} \ No newline at end of file diff --git a/src/training/Ledge.rs b/src/training/Ledge.rs new file mode 100644 index 0000000..fc53e7d --- /dev/null +++ b/src/training/Ledge.rs @@ -0,0 +1,108 @@ +use smash::{hash40, phx::Hash40}; +use smash::app::{self}; +use smash::app::lua_bind::*; +use smash::lib::lua_const::*; +use crate::common::*; +use crate::common::consts::*; + +pub unsafe fn force_option( + module_accessor: &mut app::BattleObjectModuleAccessor) +{ + if StatusModule::status_kind(module_accessor) as i32 == *FIGHTER_STATUS_KIND_CLIFF_WAIT { + if WorkModule::is_enable_transition_term(module_accessor, *FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_CLIFF_CLIMB) { + + let random_frame = app::sv_math::rand( + hash40("fighter"), + MotionModule::end_frame(module_accessor) as i32) as f32; + + let frame = MotionModule::frame(module_accessor) as f32; + + if frame == random_frame || frame > 30.0 { + let mut status = 0; + let ledge_case : i32; + + if menu.LEDGE_STATE == RANDOM_LEDGE { + ledge_case = app::sv_math::rand(hash40("fighter"), 4) + 2; + } else { + ledge_case = menu.LEDGE_STATE; + } + + match ledge_case { + NEUTRAL_LEDGE => status = *FIGHTER_STATUS_KIND_CLIFF_CLIMB, + ROLL_LEDGE => status = *FIGHTER_STATUS_KIND_CLIFF_ESCAPE, + JUMP_LEDGE => status = *FIGHTER_STATUS_KIND_CLIFF_JUMP1, + ATTACK_LEDGE => status = *FIGHTER_STATUS_KIND_CLIFF_ATTACK, + _ => () + } + + StatusModule::change_status_request_from_script(module_accessor, status, true); + } + } + } +} + +pub unsafe fn should_perform_defensive_option( + module_accessor: &mut app::BattleObjectModuleAccessor, + prev_status: i32, + status: i32) -> bool +{ + ([*FIGHTER_STATUS_KIND_CLIFF_CLIMB, + *FIGHTER_STATUS_KIND_CLIFF_ATTACK, + *FIGHTER_STATUS_KIND_CLIFF_ESCAPE] + .iter() + .any(|i| i == &status || i == &prev_status) + ) + && + ( + WorkModule::is_enable_transition_term(module_accessor, *FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_ESCAPE) || + CancelModule::is_enable_cancel(module_accessor) + ) +} + +pub unsafe fn defensive_option( + module_accessor: &mut app::BattleObjectModuleAccessor, + category: i32, + flag: &mut i32) +{ + let status = StatusModule::status_kind(module_accessor) as i32; + let prev_status = StatusModule::prev_status_kind(module_accessor, 0) as i32; + if [*FIGHTER_STATUS_KIND_CLIFF_JUMP3, + *FIGHTER_STATUS_KIND_CLIFF_JUMP2, + *FIGHTER_STATUS_KIND_CLIFF_JUMP1].contains(&status) { + *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_AIR_ESCAPE; + } + + if should_perform_defensive_option(module_accessor, prev_status, status) { + perform_defensive_option(module_accessor, flag); + } +} + +pub unsafe fn check_button_on( + module_accessor: &mut app::BattleObjectModuleAccessor, + button: i32) -> Option +{ + if [*CONTROL_PAD_BUTTON_GUARD_HOLD, *CONTROL_PAD_BUTTON_GUARD].contains(&button) { + if is_training_mode() && is_operation_cpu(module_accessor) { + let prev_status = StatusModule::prev_status_kind(module_accessor, 0) as i32; + let status = StatusModule::status_kind(module_accessor) as i32; + if menu.DEFENSIVE_STATE == DEFENSIVE_SHIELD && + should_perform_defensive_option( + module_accessor, prev_status, status) { + return Some(true) + } + } + } + + None +} + +pub unsafe fn get_command_flag_cat( + module_accessor: &mut app::BattleObjectModuleAccessor, + category: i32, + flag: &mut i32) +{ + if menu.LEDGE_STATE != NONE && is_training_mode() && is_operation_cpu(module_accessor) { + force_option(module_accessor); + defensive_option(module_accessor, category, flag); + } +} \ No newline at end of file diff --git a/src/training/Mash.rs b/src/training/Mash.rs new file mode 100644 index 0000000..fe86cf5 --- /dev/null +++ b/src/training/Mash.rs @@ -0,0 +1,158 @@ +use smash::{hash40, phx::Hash40}; +use smash::app::{self}; +use smash::app::lua_bind::*; +use smash::lib::lua_const::*; +use crate::common::*; +use crate::common::consts::*; + +pub unsafe fn get_attack_air_kind( + module_accessor: &mut app::BattleObjectModuleAccessor) -> Option +{ + if is_training_mode() && is_operation_cpu(module_accessor) { + if menu.MASH_STATE == MASH_ATTACK { + match menu.ATTACK_STATE { + MASH_NAIR => return Some(*FIGHTER_COMMAND_ATTACK_AIR_KIND_N), + MASH_FAIR => return Some(*FIGHTER_COMMAND_ATTACK_AIR_KIND_F), + MASH_BAIR => return Some(*FIGHTER_COMMAND_ATTACK_AIR_KIND_B), + MASH_UPAIR => return Some(*FIGHTER_COMMAND_ATTACK_AIR_KIND_HI), + MASH_DAIR => return Some(*FIGHTER_COMMAND_ATTACK_AIR_KIND_LW), + _ => () + } + } + + if menu.MASH_STATE == MASH_RANDOM { + return Some(app::sv_math::rand(hash40("fighter"), 5) + 1); + } + } + + None +} + +pub unsafe fn get_command_flag_cat( + module_accessor: &mut app::BattleObjectModuleAccessor, + category: i32, + flag: &mut i32) +{ + if is_training_mode() && is_operation_cpu(module_accessor) { + if is_in_hitstun(module_accessor) || is_in_landing(module_accessor) || is_in_shieldstun(module_accessor) { + match menu.MASH_STATE { + MASH_AIRDODGE => { + if category == FIGHTER_PAD_COMMAND_CATEGORY1 { + *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_AIR_ESCAPE; + } + }, + MASH_JUMP => { + if !is_in_landing(module_accessor) && category == FIGHTER_PAD_COMMAND_CATEGORY1 { + *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_JUMP_BUTTON; + } + }, + MASH_SPOTDODGE => { + if category == FIGHTER_PAD_COMMAND_CATEGORY1 { + *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE; + } + }, + MASH_ATTACK => { + if category == FIGHTER_PAD_COMMAND_CATEGORY1 { + match menu.ATTACK_STATE { + MASH_NAIR | + MASH_FAIR | + MASH_BAIR | + MASH_UPAIR | + MASH_DAIR => { + *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_N; + // If we are performing the attack OOS we also need to jump + if is_in_shieldstun(module_accessor) { + *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_JUMP_BUTTON; + } + }, + MASH_NEUTRAL_B => *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_N, + MASH_SIDE_B => *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_S, + MASH_UP_B => *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_HI, + MASH_DOWN_B => *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_LW, + MASH_UP_SMASH => *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_HI4, + MASH_GRAB => *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_CATCH, + _ => () + } + } else if category == 1 { + if menu.ATTACK_STATE == MASH_GRAB { *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_CATCH; } + } + }, + MASH_RANDOM => { + if category == FIGHTER_PAD_COMMAND_CATEGORY1 { + let situation_kind = StatusModule::situation_kind(module_accessor) as i32; + + if situation_kind == SITUATION_KIND_AIR { + let random_commands = vec![ + *FIGHTER_PAD_CMD_CAT1_FLAG_AIR_ESCAPE, + *FIGHTER_PAD_CMD_CAT1_FLAG_JUMP_BUTTON, + // one for each aerial + *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_N, + *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_N, + *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_N, + *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_N, + *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_N, + *FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_N, + *FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_S, + *FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_HI, + *FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_LW, + ]; + + let random_cmd_index = app::sv_math::rand( + hash40("fighter"), random_commands.len() as i32) as usize; + + *flag |= random_commands[random_cmd_index]; + } else if situation_kind == SITUATION_KIND_GROUND { + let random_commands = vec![ + *FIGHTER_PAD_CMD_CAT1_FLAG_JUMP_BUTTON, + *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_N, + *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_S3, + *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_HI3, + *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_LW3, + *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_S4, + *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_HI4, + *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_LW4, + *FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_HI, + *FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_S, + *FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_HI, + *FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_LW, + *FIGHTER_PAD_CMD_CAT1_FLAG_CATCH, + *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE, + *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE_F, + *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE_B, + ]; + + let random_cmd_index = app::sv_math::rand( + hash40("fighter"), random_commands.len() as i32) as usize; + + *flag |= random_commands[random_cmd_index]; + } + } + }, + _ => () + } + } + } +} + +pub unsafe fn check_button_on( + module_accessor: &mut app::BattleObjectModuleAccessor, + button: i32) -> Option +{ + if [*CONTROL_PAD_BUTTON_GUARD_HOLD, *CONTROL_PAD_BUTTON_GUARD].contains(&button) { + if is_training_mode() && is_operation_cpu(module_accessor) { + if menu.MASH_STATE == MASH_AIRDODGE && (is_in_hitstun(module_accessor) || is_in_landing(module_accessor)) { + return Some(true) + } + } + } + + if [*CONTROL_PAD_BUTTON_ATTACK, *CONTROL_PAD_BUTTON_CATCH].contains(&button) { + if is_training_mode() && is_operation_cpu(module_accessor) { + if menu.MASH_STATE == MASH_ATTACK && menu.ATTACK_STATE == MASH_GRAB && is_in_shieldstun(module_accessor) { + return Some(true) + } + } + } + + None +} \ No newline at end of file diff --git a/src/training/Shield.rs b/src/training/Shield.rs new file mode 100644 index 0000000..ec6c50a --- /dev/null +++ b/src/training/Shield.rs @@ -0,0 +1,75 @@ + +use smash::hash40; +use smash::app::{self}; +use smash::app::lua_bind::*; +use smash::lib::lua_const::*; +use crate::common::*; +use crate::common::consts::*; + +pub unsafe fn get_param_float(module_accessor: &mut app::BattleObjectModuleAccessor, param_type: u64, param_hash: u64) -> Option { + if is_training_mode() { + if menu.SHIELD_STATE == SHIELD_INFINITE { + if param_type == hash40("common") { + if param_hash == hash40("shield_dec1") { + return Some(0.0) + } + if param_hash == hash40("shield_recovery1") { + return Some(999.0) + } + // doesn't work, somehow. This parameter isn't checked? + if param_hash == hash40("shield_damage_mul") { + return Some(0.0) + } + } + } + } + + None +} + +pub unsafe fn should_hold_shield(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool { + // We should hold shield if the state requires it + if [SHIELD_HOLD, SHIELD_INFINITE].contains(&menu.SHIELD_STATE) { + // If we are not mashing then we will always hold shield + if menu.MASH_STATE == NONE { + return true + } + + if !is_in_shieldstun(module_accessor) { + return true + } + + // We will only drop shield if we are in shieldstun and our attack can be performed OOS + if menu.MASH_STATE == MASH_ATTACK { + if [MASH_NEUTRAL_B, MASH_SIDE_B, MASH_DOWN_B].contains(&menu.ATTACK_STATE) { + return true + } + } + } + + false +} + +pub unsafe fn check_button_on(module_accessor: &mut app::BattleObjectModuleAccessor, button: i32) -> Option { + if [*CONTROL_PAD_BUTTON_GUARD_HOLD, *CONTROL_PAD_BUTTON_GUARD].contains(&button) { + if is_training_mode() && is_operation_cpu(module_accessor) { + if should_hold_shield(module_accessor) { + return Some(true) + } + } + } + + None +} + +pub unsafe fn check_button_off(module_accessor: &mut app::BattleObjectModuleAccessor, button: i32) -> Option { + if [*CONTROL_PAD_BUTTON_GUARD_HOLD, *CONTROL_PAD_BUTTON_GUARD].contains(&button) { + if is_training_mode() && is_operation_cpu(module_accessor) { + if should_hold_shield(module_accessor) { + return Some(false) + } + } + } + + None +} \ No newline at end of file diff --git a/src/training/Tech.rs b/src/training/Tech.rs new file mode 100644 index 0000000..bc3309f --- /dev/null +++ b/src/training/Tech.rs @@ -0,0 +1,144 @@ +use smash::{hash40, phx::Hash40}; +use smash::app::{self}; +use smash::app::lua_bind::*; +use smash::lib::lua_const::*; +use crate::common::*; +use crate::common::consts::*; + +pub unsafe fn init_settings( + module_accessor: &mut app::BattleObjectModuleAccessor, + status_kind: i32) -> Option<()> +{ + if is_training_mode() && is_operation_cpu(module_accessor) { + if status_kind == FIGHTER_STATUS_KIND_DOWN { + match menu.TECH_STATE { + RANDOM_TECH => { + let random_statuses = vec![ + *FIGHTER_STATUS_KIND_DOWN, + *FIGHTER_STATUS_KIND_PASSIVE, + *FIGHTER_STATUS_KIND_PASSIVE_FB + ]; + + let random_status_index = app::sv_math::rand(hash40("fighter"), random_statuses.len() as i32) as usize; + if random_statuses[random_status_index] != FIGHTER_STATUS_KIND_DOWN { + StatusModule::change_status_request_from_script( + module_accessor, + random_statuses[random_status_index], + true); + return Some(()) + } + }, + TECH_IN_PLACE => { + StatusModule::change_status_request_from_script( + module_accessor, + *FIGHTER_STATUS_KIND_PASSIVE, + true); + return Some(()) + }, + TECH_ROLL => { + StatusModule::change_status_request_from_script( + module_accessor, + *FIGHTER_STATUS_KIND_PASSIVE_FB, + true); + return Some(()) + }, + _ => () + } + } + } + + None +} + +pub unsafe fn should_perform_defensive_option( + module_accessor: &mut app::BattleObjectModuleAccessor, + prev_status: i32, + status: i32) -> bool +{ + ( + [*FIGHTER_STATUS_KIND_PASSIVE, + *FIGHTER_STATUS_KIND_PASSIVE_FB, + *FIGHTER_STATUS_KIND_DOWN_STAND, + *FIGHTER_STATUS_KIND_DOWN_STAND_FB, + *FIGHTER_STATUS_KIND_DOWN_STAND_ATTACK].contains(&prev_status) || + + [*FIGHTER_STATUS_KIND_DOWN_STAND, + *FIGHTER_STATUS_KIND_DOWN_STAND_FB, + *FIGHTER_STATUS_KIND_DOWN_STAND_ATTACK].contains(&status) + ) + && + ( + WorkModule::is_enable_transition_term(module_accessor, *FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_GUARD_ON) || + CancelModule::is_enable_cancel(module_accessor) + ) +} + +pub unsafe fn get_command_flag_cat( + module_accessor: &mut app::BattleObjectModuleAccessor, + category: i32, + flag: &mut i32) +{ + if menu.TECH_STATE != NONE && is_training_mode() && is_operation_cpu(module_accessor) { + let prev_status = StatusModule::prev_status_kind(module_accessor, 0) as i32; + let status = StatusModule::status_kind(module_accessor) as i32; + if [*FIGHTER_STATUS_KIND_DOWN_WAIT, *FIGHTER_STATUS_KIND_DOWN_WAIT_CONTINUE].contains(&status) { + let random_statuses = vec![ + *FIGHTER_STATUS_KIND_DOWN_STAND, + *FIGHTER_STATUS_KIND_DOWN_STAND_FB, + *FIGHTER_STATUS_KIND_DOWN_STAND_ATTACK + ]; + + let random_status_index = app::sv_math::rand(hash40("fighter"), random_statuses.len() as i32) as usize; + StatusModule::change_status_request_from_script(module_accessor, random_statuses[random_status_index], true); + } else if should_perform_defensive_option(module_accessor, prev_status, status) { + perform_defensive_option(module_accessor, flag); + } + } +} + +pub unsafe fn check_button_on( + module_accessor: &mut app::BattleObjectModuleAccessor, + button: i32) -> Option +{ + if [*CONTROL_PAD_BUTTON_GUARD_HOLD, *CONTROL_PAD_BUTTON_GUARD].contains(&button) { + if is_training_mode() && is_operation_cpu(module_accessor) { + let prev_status = StatusModule::prev_status_kind(module_accessor, 0) as i32; + let status = StatusModule::status_kind(module_accessor) as i32; + if menu.DEFENSIVE_STATE == DEFENSIVE_SHIELD && + should_perform_defensive_option(module_accessor, prev_status, status) { + return Some(true) + } + } + } + + None +} + +pub unsafe fn change_motion( + module_accessor: &mut app::BattleObjectModuleAccessor, + motion_kind: u64) -> Option +{ + if menu.TECH_STATE != NONE && is_training_mode() && is_operation_cpu(module_accessor) { + if [hash40("passive_stand_f"), hash40("passive_stand_b")].contains(&motion_kind) { + if app::sv_math::rand(hash40("fighter"), 2) != 0 { + return Some(hash40("passive_stand_f")) + } else { + return Some(hash40("passive_stand_b")) + } + } else if [hash40("down_forward_u") | hash40("down_back_u")].contains(&motion_kind) { + if app::sv_math::rand(hash40("fighter"), 2) != 0 { + return Some(hash40("down_forward_u")) + } else { + return Some(hash40("down_back_u")) + } + } else if [hash40("down_forward_d") | hash40("down_back_d")].contains(&motion_kind) { + if app::sv_math::rand(hash40("fighter"), 2) != 0 { + return Some(hash40("down_forward_d")) + } else { + return Some(hash40("down_back_d")) + } + } + } + + None +} \ No newline at end of file diff --git a/src/training/mod.rs b/src/training/mod.rs index a362ae8..9314e66 100644 --- a/src/training/mod.rs +++ b/src/training/mod.rs @@ -1,78 +1,74 @@ -use smash::hash40; -use smash::app::BattleObjectModuleAccessor; -use smash::app::sv_animcmd::{self}; -use smash::app::lua_bind::*; -use smash::lib::{self, L2CAgent, L2CValue}; +use smash::app::{self, sv_system, sv_animcmd, lua_bind::*, FighterManager}; +use smash::lib::{self, L2CAgent, L2CValue, lua_const::*}; use smash::phx::{Hash40, Vector3f}; -use smash::lib::lua_const::{*}; -use smash::app::sv_system::{self}; -use smash::app::{self}; -use skyline::logging::hex_dump_ptr; +use smash::hash40; +use skyline::{c_str, nn::ro::LookupSymbol, logging::hex_dump_ptr}; +use crate::common::fighter_manager_addr; use crate::common::*; +use crate::common::consts::*; + +mod DirectionalInfluence; +mod Shield; +mod Tech; +mod Mash; +mod Ledge; #[allow(unused_unsafe)] #[skyline::hook(replace = WorkModule::get_float)] -pub unsafe fn handle_get_float(module_accessor: *mut BattleObjectModuleAccessor, var: i32) -> f32 { - let mut replace = false; - //float ret = DirectionalInfluence::get_float(module_accessor, var, replace); - //if (replace) return ret; - - original!()(module_accessor, var) +pub unsafe fn handle_get_float(module_accessor: &mut app::BattleObjectModuleAccessor, var: i32) -> f32 { + DirectionalInfluence::get_float(module_accessor, var).unwrap_or_else( || { + original!()(module_accessor, var) + }) } -// float get_param_float_replace(u64 module_accessor, u64 param_type, u64 param_hash) { -// bool replace; -// float ret = Shield::get_param_float(module_accessor, param_type, param_hash, replace); -// if (replace) return ret; +#[allow(unused_unsafe)] +#[skyline::hook(replace = WorkModule::get_param_float)] +pub unsafe fn handle_get_param_float(module_accessor: &mut app::BattleObjectModuleAccessor, param_type: u64, param_hash: u64) -> f32 { + Shield::get_param_float(module_accessor, param_type, param_hash).unwrap_or_else( || { + original!()(module_accessor, param_type, param_hash) + }) +} -// u64 work_module = load_module(module_accessor, 0x50); -// float (*get_param_float)(u64, u64, u64) = (float (*)(u64, u64, u64)) load_module_impl(work_module, 0x240); -// return get_param_float(work_module, param_type, param_hash); -// } -// } // namespace WorkModule +#[allow(unused_unsafe)] +#[skyline::hook(replace = ControlModule::get_attack_air_kind)] +pub unsafe fn handle_get_attack_air_kind(module_accessor: &mut app::BattleObjectModuleAccessor) -> i32 { + // bool replace; + // int kind = InputRecorder::get_attack_air_kind(module_accessor, replace); + // if (replace) return kind; -// namespace ControlModule { -// int get_attack_air_kind_replace(u64 module_accessor) { -// bool replace; -// int kind = InputRecorder::get_attack_air_kind(module_accessor, replace); -// if (replace) return kind; + Mash::get_attack_air_kind(module_accessor).unwrap_or_else( || { + original!()(module_accessor) + }) +} -// kind = Mash::get_attack_air_kind(module_accessor, replace); -// if (replace) return kind; +#[allow(unused_unsafe)] +#[skyline::hook(replace = ControlModule::get_command_flag_cat)] +pub unsafe fn handle_get_command_flag_cat( + module_accessor: &mut app::BattleObjectModuleAccessor, + category: i32) -> i32 +{ + //save_states(module_accessor); -// u64 control_module = load_module(module_accessor, 0x48); -// int (*get_attack_air_kind)(u64) = (int (*)(u64)) load_module_impl(control_module, 0x3B0); -// return get_attack_air_kind(control_module); -// } + // Pause Effect AnimCMD if hitbox visualization is active + let status_kind = StatusModule::status_kind(module_accessor) as i32; + MotionAnimcmdModule::set_sleep_effect(module_accessor, + is_training_mode() && + menu.HITBOX_VIS && + !((*FIGHTER_STATUS_KIND_CATCH..=*FIGHTER_STATUS_KIND_TREAD_FALL).contains(&status_kind) || + (*FIGHTER_STATUS_KIND_WAIT..=*FIGHTER_STATUS_KIND_REBOUND_JUMP).contains(&status_kind))); -// int get_command_flag_cat_replace(u64 module_accessor, int category) { -// int (*prev_replace)(u64, int) = (int (*)(u64, int)) prev_get_command_flag_cat; -// if (prev_replace) -// prev_replace(module_accessor, category); -// //save_states(module_accessor); + let mut flag = original!()(module_accessor, category); -// // Pause Effect AnimCMD if hitbox visualization is active -// int status_kind = StatusModule::status_kind(module_accessor); -// MotionAnimcmdModule::set_sleep_effect(module_accessor, -// is_training_mode() && -// menu.HITBOX_VIS && -// !((status_kind >= FIGHTER_STATUS_KIND_CATCH && status_kind <= FIGHTER_STATUS_KIND_TREAD_FALL) || -// (status_kind >= FIGHTER_STATUS_KIND_WAIT && status_kind <= FIGHTER_STATUS_KIND_REBOUND_JUMP))); + // bool replace; + // int ret = InputRecorder::get_command_flag_cat(module_accessor, category, flag, replace); + // if (replace) return ret; -// u64 control_module = load_module(module_accessor, 0x48); -// int (*get_command_flag_cat)(u64, int) = (int (*)(u64, int)) load_module_impl(control_module, 0x350); -// int flag = get_command_flag_cat(control_module, category); + Mash::get_command_flag_cat(module_accessor, category, &mut flag); + Ledge::get_command_flag_cat(module_accessor, category, &mut flag); + Tech::get_command_flag_cat(module_accessor, category, &mut flag); -// // bool replace; -// // int ret = InputRecorder::get_command_flag_cat(module_accessor, category, flag, replace); -// // if (replace) return ret; - -// Mash::get_command_flag_cat(module_accessor, category, flag); -// Ledge::get_command_flag_cat(module_accessor, category, flag); -// Tech::get_command_flag_cat(module_accessor, category, flag); - -// return flag; -// } + flag +} // int get_pad_flag(u64 module_accessor) { // u64 control_module = load_module(module_accessor, 0x48); @@ -110,96 +106,93 @@ pub unsafe fn handle_get_float(module_accessor: *mut BattleObjectModuleAccessor, // return stick_y; // } -// bool check_button_on_replace(u64 module_accessor, int button) { -// bool replace; -// bool ret = Shield::check_button_on(module_accessor, button, replace); -// if (replace) return ret; -// ret = Mash::check_button_on(module_accessor, button, replace); -// if (replace) return ret; -// ret = Tech::check_button_on(module_accessor, button, replace); -// if (replace) return ret; -// ret = Ledge::check_button_on(module_accessor, button, replace); -// if (replace) return ret; +#[allow(unused_unsafe)] +#[skyline::hook(replace = ControlModule::check_button_on)] +pub unsafe fn handle_check_button_on( + module_accessor: &mut app::BattleObjectModuleAccessor, + button: i32) -> bool +{ + Shield::check_button_on(module_accessor, button).unwrap_or_else( || { + Mash::check_button_on(module_accessor, button).unwrap_or_else( || { + Tech::check_button_on(module_accessor, button).unwrap_or_else( || { + Ledge::check_button_on(module_accessor, button).unwrap_or_else( || { + original!()(module_accessor, button) + }) + }) + }) + }) +} -// u64 control_module = load_module(module_accessor, 0x48); -// bool (*check_button_on)(u64, int) = (bool (*)(u64, int)) load_module_impl(control_module, 0x260); -// return check_button_on(control_module, button); -// } +#[allow(unused_unsafe)] +#[skyline::hook(replace = ControlModule::check_button_off)] +pub unsafe fn handle_check_button_off( + module_accessor: &mut app::BattleObjectModuleAccessor, + button: i32) -> bool +{ + Shield::check_button_off(module_accessor, button).unwrap_or_else( || { + original!()(module_accessor, button) + }) +} -// bool check_button_off_replace(u64 module_accessor, int button) { -// bool replace; -// bool ret = Shield::check_button_off(module_accessor, button, replace); -// if (replace) return ret; +#[allow(unused_unsafe)] +#[skyline::hook(replace = StatusModule::init_settings)] +pub unsafe fn handle_init_settings( + module_accessor: &mut app::BattleObjectModuleAccessor, + situationKind: i32, + unk1: i32, + unk2: u32, + groundCliffCheckKind: i32, + unk3: bool, + unk4: i32, + unk5: i32, + unk6: i32, + unk7: i32) +{ + let status_kind = StatusModule::status_kind(module_accessor) as i32; + Tech::init_settings(module_accessor, status_kind).unwrap_or_else( || { + original!()(module_accessor, situationKind, unk1, unk2, groundCliffCheckKind, unk3, unk4, unk5, unk6, unk7) + }) +} -// u64 control_module = load_module(module_accessor, 0x48); -// bool (*check_button_off)(u64, int) = (bool (*)(u64, int)) load_module_impl(control_module, 0x268); -// return check_button_off(control_module, button); -// } -// } // namespace ControlModule - -// namespace StatusModule { -// void init_settings_replace(u64 module_accessor, int situationKind, int unk1, uint unk2, int groundCliffCheckKind, bool unk3, int unk4, int unk5, int unk6, int unk7) { -// bool replace; -// Tech::init_settings(module_accessor, StatusModule::status_kind(module_accessor), replace); -// if (replace) return; - -// u64 status_module = load_module(module_accessor, 0x40); -// void (*init_settings)(u64,int,int,uint,int,bool,int,int,int,int) = -// (void (*)(u64,int,int,uint,int,bool,int,int,int,int)) load_module_impl(status_module, 0x1C8); - -// init_settings(status_module, situationKind, unk1, unk2, groundCliffCheckKind, unk3, unk4, unk5, unk6, unk7); -// } -// } // namespace StatusModule - -// namespace MotionModule { -// u64 change_motion_replace(u64 module_accessor, u64 motion_kind, float unk1, float unk2, bool unk3, float unk4, bool unk5, bool unk6) { -// bool replace; -// u64 motion_kind_ret = Tech::change_motion(module_accessor, motion_kind, replace); -// if (replace) motion_kind = motion_kind_ret; - -// u64 motion_module = load_module(module_accessor, 0x88); -// u64 change_motion_offset = 0; -// if (major < 4) change_motion_offset = 0xD8; -// else change_motion_offset = 0xE0; - -// u64 (*change_motion)(u64,u64,float,float,bool,float,bool,bool) = -// (u64 (*)(u64,u64,float,float,bool,float,bool,bool)) load_module_impl(motion_module, change_motion_offset); - -// return change_motion(motion_module, motion_kind, unk1, unk2, unk3, unk4, unk5, unk6); -// } -// } // namespace MotionModule -// } // namespace app::lua_bind +#[allow(unused_unsafe)] +#[skyline::hook(replace = MotionModule::change_motion)] +pub unsafe fn handle_change_motion( + module_accessor: &mut app::BattleObjectModuleAccessor, + motion_kind: u64, + unk1: f32, + unk2: f32, + unk3: bool, + unk4: f32, + unk5: bool, + unk6: bool) -> u64 +{ + Tech::change_motion(module_accessor, motion_kind).unwrap_or_else( || { + original!()(module_accessor, motion_kind, unk1, unk2, unk3, unk4, unk5, unk6) + }) +} pub fn training_mods() { - println!("Applying hitbox visualization mods."); - // fighter_manager_addr = SaltySDCore_FindSymbol( - // "_ZN3lib9SingletonIN3app14FighterManagerEE9instance_E"); + println!("Applying training mods."); + unsafe { + LookupSymbol(&mut fighter_manager_addr, c_str("_ZN3lib9SingletonIN3app14FighterManagerEE9instance_E")); + println!("Lookup symbol output: {:#?}", fighter_manager_addr); + } - // // Mash airdodge/jump - // SaltySD_function_replace_sym_check_prev( - // "_ZN3app8lua_bind40ControlModule__get_command_flag_cat_implEPNS_26BattleObjectModuleAccessorEi", - // (u64)&ControlModule::get_command_flag_cat_replace, - // prev_get_command_flag_cat); + // Mash airdodge/jump + skyline::install_hook!(handle_get_command_flag_cat); // Set DI skyline::install_hook!(handle_get_float); // Hold/Infinite shield - // SaltySD_function_replace_sym( - // "_ZN3app8lua_bind35ControlModule__check_button_on_implEPNS_26BattleObjectModuleAccessorEi", - // (u64)&ControlModule::check_button_on_replace); - // SaltySD_function_replace_sym( - // "_ZN3app8lua_bind36ControlModule__check_button_off_implEPNS_26BattleObjectModuleAccessorEi", - // (u64)&ControlModule::check_button_off_replace); - // SaltySD_function_replace_sym( - // "_ZN3app8lua_bind32WorkModule__get_param_float_implEPNS_26BattleObjectModuleAccessorEmm", - // (u64)&WorkModule::get_param_float_replace); + skyline::install_hook!(handle_check_button_on); + skyline::install_hook!(handle_check_button_off); - // // Mash attack - // SaltySD_function_replace_sym( - // "_ZN3app8lua_bind39ControlModule__get_attack_air_kind_implEPNS_26BattleObjectModuleAccessorE", - // (u64)&ControlModule::get_attack_air_kind_replace); + skyline::install_hook!(handle_get_param_float); + + // Mash attack + skyline::install_hook!(handle_get_attack_air_kind); // // Input recorder // SaltySD_function_replace_sym( @@ -209,11 +202,7 @@ pub fn training_mods() { // "_ZN3app8lua_bind31ControlModule__get_stick_y_implEPNS_26BattleObjectModuleAccessorE", // (u64)&ControlModule::get_stick_y_replace); - // // Tech options - // SaltySD_function_replace_sym( - // "_ZN3app8lua_bind32StatusModule__init_settings_implEPNS_26BattleObjectModuleAccessorENS_13SituationKindEijNS_20GroundCliffCheckKindEbiiii", - // (u64)&StatusModule::init_settings_replace); - // SaltySD_function_replace_sym( - // "_ZN3app8lua_bind32MotionModule__change_motion_implEPNS_26BattleObjectModuleAccessorEN3phx6Hash40Effbfbb", - // (u64)&MotionModule::change_motion_replace); + // Tech options + skyline::install_hook!(handle_init_settings); + skyline::install_hook!(handle_change_motion); }