From e67c69ed63d5f2b6bea94dfa58f7f01d6934b02e Mon Sep 17 00:00:00 2001 From: sidschingis Date: Thu, 11 Jun 2020 23:57:35 +0200 Subject: [PATCH] Code Refactoring (#83) * Update TrainingModpackOverlay * Apply Auto Formatter * Auto Format * Extract Modding Behaviour Moved to separate function * Guard Clause * Guard Clause * Use Match Clause * Fix Comment * Extract Shared Condition * Extract Modding Function * Guard Clause * Guard Clause * Guard Clause * Guard Clause * Guard Clause * Extract Shared Code * Fix Variable Reference Properly borrow the variables * Fix Missed Tech Buffering * Move Training Mode Check To Start * Guard Clause * Guard Clause * Extract Modding Behaviour * Extract Function For randomizing the di angle * Guard Clause * Guard Clause * Simplify Loop Separate condition from behaviour * Extract Modding Behaviour * Extract Modding Behaviour * Formatting * Fix Typos * Fix Typos * Fix Mash Toggle ! was binding stronger than == * Move Negation Inwards * Reduce Nesting * Extract Shared Condition * Extract Method Moved random command list definition to separate function --- src/hitbox_visualizer/mod.rs | 208 +++++++++------- src/training/directional_influence.rs | 89 ++++--- src/training/ledge.rs | 119 +++++---- src/training/mash.rs | 277 +++++++++++---------- src/training/save_states.rs | 285 +++++++++++---------- src/training/shield.rs | 344 +++++++++++++------------- src/training/tech.rs | 281 ++++++++++++--------- 7 files changed, 882 insertions(+), 721 deletions(-) diff --git a/src/hitbox_visualizer/mod.rs b/src/hitbox_visualizer/mod.rs index b508f3c..3a5d52d 100644 --- a/src/hitbox_visualizer/mod.rs +++ b/src/hitbox_visualizer/mod.rs @@ -158,78 +158,82 @@ pub unsafe fn get_command_flag_cat( module_accessor: &mut app::BattleObjectModuleAccessor, category: i32, ) { - if is_training_mode() { - // Pause Effect AnimCMD if hitbox visualization is active - MotionAnimcmdModule::set_sleep_effect( - module_accessor, - MENU.hitbox_vis - && !((*FIGHTER_STATUS_KIND_CATCH..=*FIGHTER_STATUS_KIND_TREAD_FALL) - .contains(&StatusModule::status_kind(module_accessor))), - ); + if !is_training_mode() { + return; } // apply only once per frame - if category == 0 && is_training_mode() && MENU.hitbox_vis { - let status_kind = StatusModule::status_kind(module_accessor) as i32; - if !(*FIGHTER_STATUS_KIND_CATCH..=*FIGHTER_STATUS_KIND_CATCH_TURN).contains(&status_kind) - && !is_shielding(module_accessor) - { - EffectModule::set_visible_kind(module_accessor, Hash40::new("sys_shield"), false); - EffectModule::kill_kind(module_accessor, Hash40::new("sys_shield"), false, true); - for i in 0..8 { - if AttackModule::is_attack(module_accessor, i, false) { - let attack_data = *AttackModule::attack_data(module_accessor, i, false); - let is_capsule = - attack_data.x2 != 0.0 || attack_data.y2 != 0.0 || attack_data.z2 != 0.0; - let mut x2 = None; - let mut y2 = None; - let mut z2 = None; - if is_capsule { - x2 = Some(attack_data.x2); - y2 = Some(attack_data.y2); - z2 = Some(attack_data.z2); - } - generate_hitbox_effects( - module_accessor, - attack_data.node, // joint - attack_data.size, - attack_data.x, - attack_data.y, - attack_data.z, - x2, - y2, - z2, - ID_COLORS[(i % 8) as usize], - ); - } - } + if category != 0 { + return; + } + + // Resume Effect AnimCMD incase we don't display hitboxes + MotionAnimcmdModule::set_sleep_effect(module_accessor, false); + + if !MENU.hitbox_vis { + return; + } + + let status_kind = StatusModule::status_kind(module_accessor) as i32; + if (*FIGHTER_STATUS_KIND_CATCH..=*FIGHTER_STATUS_KIND_CATCH_TURN).contains(&status_kind) { + return; + } + + if is_shielding(module_accessor) { + return; + } + + // Pause Effect AnimCMD if hitbox visualization is active + MotionAnimcmdModule::set_sleep_effect(module_accessor, true); + + EffectModule::set_visible_kind(module_accessor, Hash40::new("sys_shield"), false); + EffectModule::kill_kind(module_accessor, Hash40::new("sys_shield"), false, true); + for i in 0..8 { + if !AttackModule::is_attack(module_accessor, i, false) { + continue; } + + let attack_data = *AttackModule::attack_data(module_accessor, i, false); + let is_capsule = attack_data.x2 != 0.0 || attack_data.y2 != 0.0 || attack_data.z2 != 0.0; + let mut x2 = None; + let mut y2 = None; + let mut z2 = None; + if is_capsule { + x2 = Some(attack_data.x2); + y2 = Some(attack_data.y2); + z2 = Some(attack_data.z2); + } + generate_hitbox_effects( + module_accessor, + attack_data.node, // joint + attack_data.size, + attack_data.x, + attack_data.y, + attack_data.z, + x2, + y2, + z2, + ID_COLORS[(i % 8) as usize], + ); } } // Necessary to ensure we visualize on the first frame of the hitbox #[skyline::hook(replace = sv_animcmd::ATTACK)] unsafe fn handle_attack(lua_state: u64) { + mod_handle_attack(lua_state); + original!()(lua_state); +} + +unsafe fn mod_handle_attack(lua_state: u64) { + if !is_training_mode() { + return; + } + let mut l2c_agent = L2CAgent::new(lua_state); - // get all necessary grabbox params - let id = l2c_agent.pop_lua_stack(1); // int - let joint = l2c_agent.pop_lua_stack(3); // hash40 - let _damage = l2c_agent.pop_lua_stack(4); // float - let _angle = l2c_agent.pop_lua_stack(5); // int - let _kbg = l2c_agent.pop_lua_stack(6); // int - let _fkb = l2c_agent.pop_lua_stack(7); // int - let _bkb = l2c_agent.pop_lua_stack(8); // int - let size = l2c_agent.pop_lua_stack(9); // float - let x = l2c_agent.pop_lua_stack(10); // float - let y = l2c_agent.pop_lua_stack(11); // float - let z = l2c_agent.pop_lua_stack(12); // float - let x2 = l2c_agent.pop_lua_stack(13); // float or void - let y2 = l2c_agent.pop_lua_stack(14); // float or void - let z2 = l2c_agent.pop_lua_stack(15); // float or void - // hacky way of forcing no shield damage on all hitboxes - if is_training_mode() && MENU.shield_state == Shield::Infinite { + if MENU.shield_state == Shield::Infinite { let hitbox_params: Vec = (0..36).map(|i| l2c_agent.pop_lua_stack(i + 1)).collect(); l2c_agent.clear_lua_stack(); @@ -243,9 +247,24 @@ unsafe fn handle_attack(lua_state: u64) { } } - original!()(lua_state); + // Hitbox Visualization + if MENU.hitbox_vis { + // get all necessary grabbox params + let id = l2c_agent.pop_lua_stack(1); // int + let joint = l2c_agent.pop_lua_stack(3); // hash40 + let _damage = l2c_agent.pop_lua_stack(4); // float + let _angle = l2c_agent.pop_lua_stack(5); // int + let _kbg = l2c_agent.pop_lua_stack(6); // int + let _fkb = l2c_agent.pop_lua_stack(7); // int + let _bkb = l2c_agent.pop_lua_stack(8); // int + let size = l2c_agent.pop_lua_stack(9); // float + let x = l2c_agent.pop_lua_stack(10); // float + let y = l2c_agent.pop_lua_stack(11); // float + let z = l2c_agent.pop_lua_stack(12); // float + let x2 = l2c_agent.pop_lua_stack(13); // float or void + let y2 = l2c_agent.pop_lua_stack(14); // float or void + let z2 = l2c_agent.pop_lua_stack(15); // float or void - if MENU.hitbox_vis && is_training_mode() { generate_hitbox_effects( sv_system::battle_object_module_accessor(lua_state), joint.get_int(), @@ -263,9 +282,21 @@ unsafe fn handle_attack(lua_state: u64) { #[skyline::hook(replace = sv_animcmd::CATCH)] unsafe fn handle_catch(lua_state: u64) { - let mut l2c_agent = L2CAgent::new(lua_state); + mod_handle_catch(lua_state); + original!()(lua_state); +} + +unsafe fn mod_handle_catch(lua_state: u64) { + if !is_training_mode() { + return; + } + + if !MENU.hitbox_vis { + return; + } // get all necessary grabbox params + let mut l2c_agent = L2CAgent::new(lua_state); let id = l2c_agent.pop_lua_stack(1); // int let joint = l2c_agent.pop_lua_stack(2); // hash40 let size = l2c_agent.pop_lua_stack(3); // float @@ -276,22 +307,18 @@ unsafe fn handle_catch(lua_state: u64) { let y2 = l2c_agent.pop_lua_stack(8); // float or void let z2 = l2c_agent.pop_lua_stack(9); // float or void - original!()(lua_state); - - if MENU.hitbox_vis && is_training_mode() { - generate_hitbox_effects( - sv_system::battle_object_module_accessor(lua_state), - joint.get_int(), - size.get_num(), - x.get_num(), - y.get_num(), - z.get_num(), - x2.try_get_num(), - y2.try_get_num(), - z2.try_get_num(), - ID_COLORS[(id.get_int() + 3 % 8) as usize], - ); - } + generate_hitbox_effects( + sv_system::battle_object_module_accessor(lua_state), + joint.get_int(), + size.get_num(), + x.get_num(), + y.get_num(), + z.get_num(), + x2.try_get_num(), + y2.try_get_num(), + z2.try_get_num(), + ID_COLORS[(id.get_int() + 3 % 8) as usize], + ); } pub unsafe fn is_shielding(module_accessor: *mut app::BattleObjectModuleAccessor) -> bool { @@ -304,15 +331,26 @@ 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) { - EffectModule::set_visible_kind(module_accessor, Hash40::new("sys_shield"), false); - EffectModule::kill_kind(module_accessor, Hash40::new("sys_shield"), false, true); - } + mod_handle_handle_set_rebound(module_accessor, rebound); + original!()(module_accessor, rebound); +} + +unsafe fn mod_handle_handle_set_rebound(module_accessor: *mut app::BattleObjectModuleAccessor, rebound: bool) { + if !is_training_mode() { + return; } - original!()(module_accessor, rebound); + if rebound != false { + return; + } + + // only if we're not shielding + if is_shielding(module_accessor) { + return; + } + + EffectModule::set_visible_kind(module_accessor, Hash40::new("sys_shield"), false); + EffectModule::kill_kind(module_accessor, Hash40::new("sys_shield"), false, true); } pub fn hitbox_visualization() { diff --git a/src/training/directional_influence.rs b/src/training/directional_influence.rs index 6afc07d..f901577 100644 --- a/src/training/directional_influence.rs +++ b/src/training/directional_influence.rs @@ -15,40 +15,59 @@ pub unsafe fn handle_correct_damage_vector_common( fighter: &mut L2CFighterCommon, arg1: L2CValue, ) -> L2CValue { - let module_accessor = sv_system::battle_object_module_accessor(fighter.lua_state_agent); - if is_training_mode() && is_operation_cpu(module_accessor) { - if MENU.di_state != DirectionalInfluence::None { - DI_ANGLE = (MENU.di_state as i32 - 1) as f64 * PI / 4.0; - - // Either left, right, or none - if MENU.di_state == DirectionalInfluence::RandomInAway { - let rand = app::sv_math::rand(hash40("fighter"), 3); - // Either 0 (right) or PI (left) - if [0, 1].contains(&rand) { - DI_ANGLE = rand as f64 * PI; - } else { - DI_ANGLE = NO_DI; - } - } - // If facing left, reverse angle - if DI_ANGLE != NO_DI && PostureModule::lr(module_accessor) != -1.0 { - DI_ANGLE -= PI; - } - - if DI_ANGLE != NO_DI { - WorkModule::set_float( - module_accessor, - DI_ANGLE.cos() as f32, - *FIGHTER_STATUS_DAMAGE_WORK_FLOAT_VECOR_CORRECT_STICK_X, - ); - WorkModule::set_float( - module_accessor, - DI_ANGLE.sin() as f32, - *FIGHTER_STATUS_DAMAGE_WORK_FLOAT_VECOR_CORRECT_STICK_Y, - ); - } - } - } - + mod_handle_di(fighter, arg1); original!()(fighter, arg1) } + +unsafe fn mod_handle_di(fighter: &mut L2CFighterCommon, _arg1: L2CValue) { + if !is_training_mode() { + return; + } + + if MENU.di_state == DirectionalInfluence::None { + return; + } + + let module_accessor = sv_system::battle_object_module_accessor(fighter.lua_state_agent); + if !is_operation_cpu(module_accessor) { + return; + } + + // Either left, right, or none + if MENU.di_state == DirectionalInfluence::RandomInAway { + DI_ANGLE = get_random_di(); + } else { + DI_ANGLE = (MENU.di_state as i32 - 1) as f64 * PI / 4.0; + } + + // If facing left, reverse angle + if DI_ANGLE != NO_DI && PostureModule::lr(module_accessor) != -1.0 { + DI_ANGLE -= PI; + } + + // Nothig to do on no DI + if DI_ANGLE == NO_DI { + return; + } + + WorkModule::set_float( + module_accessor, + DI_ANGLE.cos() as f32, + *FIGHTER_STATUS_DAMAGE_WORK_FLOAT_VECOR_CORRECT_STICK_X, + ); + WorkModule::set_float( + module_accessor, + DI_ANGLE.sin() as f32, + *FIGHTER_STATUS_DAMAGE_WORK_FLOAT_VECOR_CORRECT_STICK_Y, + ); +} + +unsafe fn get_random_di() -> f64 { + let rand = app::sv_math::rand(hash40("fighter"), 3); + if [0, 1].contains(&rand) { + // Either 0 (right) or PI (left) + rand as f64 * PI + } else { + NO_DI + } +} diff --git a/src/training/ledge.rs b/src/training/ledge.rs index ba70a26..9be614f 100644 --- a/src/training/ledge.rs +++ b/src/training/ledge.rs @@ -5,35 +5,41 @@ use smash::hash40; use smash::lib::lua_const::*; 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: LedgeOption; - - if MENU.ledge_state == LedgeOption::Random { - ledge_case = (app::sv_math::rand(hash40("fighter"), 4) + 2).into(); - } else { - ledge_case = MENU.ledge_state; - } - - if let Some(new_status) = ledge_case.into_status() { - status = new_status; - } - - StatusModule::change_status_request_from_script(module_accessor, status, true); - } - } + if StatusModule::status_kind(module_accessor) as i32 != *FIGHTER_STATUS_KIND_CLIFF_WAIT { + return; } + + if !WorkModule::is_enable_transition_term( + module_accessor, + *FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_CLIFF_CLIMB, + ) { + return; + } + + 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) { + return; + } + + let mut status = 0; + let ledge_case: LedgeOption; + + if MENU.ledge_state == LedgeOption::Random { + ledge_case = (app::sv_math::rand(hash40("fighter"), 4) + 2).into(); + } else { + ledge_case = MENU.ledge_state; + } + + if let Some(new_status) = ledge_case.into_status() { + status = new_status; + } + + StatusModule::change_status_request_from_script(module_accessor, status, true); } pub unsafe fn should_perform_defensive_option( @@ -62,28 +68,40 @@ pub unsafe fn defensive_option( let status = StatusModule::status_kind(module_accessor) as i32; let prev_status = StatusModule::prev_status_kind(module_accessor, 0) as i32; - if should_perform_defensive_option(module_accessor, prev_status, status) { - perform_defensive_option(module_accessor, flag); + if !should_perform_defensive_option(module_accessor, prev_status, status) { + return; } + + 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); - } - } + if !is_training_mode() { + return None; } - None + if !is_operation_cpu(module_accessor) { + return None; + } + + if ![*CONTROL_PAD_BUTTON_GUARD_HOLD, *CONTROL_PAD_BUTTON_GUARD].contains(&button) { + return None; + } + + if MENU.defensive_state != Defensive::Shield { + return None; + } + + let prev_status = StatusModule::prev_status_kind(module_accessor, 0) as i32; + let status = StatusModule::status_kind(module_accessor) as i32; + if !should_perform_defensive_option(module_accessor, prev_status, status) { + return None; + } + + Some(true) } pub unsafe fn get_command_flag_cat( @@ -91,11 +109,18 @@ pub unsafe fn get_command_flag_cat( category: i32, flag: &mut i32, ) { - if MENU.ledge_state != LedgeOption::None - && is_training_mode() - && is_operation_cpu(module_accessor) - { - force_option(module_accessor); - defensive_option(module_accessor, category, flag); + if !is_training_mode() { + return; } + + if !is_operation_cpu(module_accessor) { + return; + } + + if MENU.ledge_state == LedgeOption::None { + return; + } + + force_option(module_accessor); + defensive_option(module_accessor, category, flag); } diff --git a/src/training/mash.rs b/src/training/mash.rs index d79b8a3..56ce92b 100644 --- a/src/training/mash.rs +++ b/src/training/mash.rs @@ -8,16 +8,24 @@ use smash::lib::lua_const::*; 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 { - MENU.mash_attack_state.into_attack_air_kind() - } else if MENU.mash_state == Mash::Random { - Some(app::sv_math::rand(hash40("fighter"), 5) + 1) - } else { - None + if !is_training_mode() { + return None; + } + + if !is_operation_cpu(module_accessor) { + return None; + } + + match MENU.mash_state { + Mash::Attack => { + return MENU.mash_attack_state.into_attack_air_kind(); + } + Mash::Random => { + return Some(app::sv_math::rand(hash40("fighter"), 5) + 1); + } + _ => { + return None; } - } else { - None } } @@ -26,140 +34,153 @@ pub unsafe fn get_command_flag_cat( category: i32, flag: &mut i32, ) { - // Check for OOS delay - if is_training_mode() && is_operation_cpu(module_accessor) - && is_in_shieldstun(module_accessor) && !shield::allow_oos(){ + if category != FIGHTER_PAD_COMMAND_CATEGORY1 { return; } - 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) - || is_in_footstool(module_accessor) - || StatusModule::status_kind(module_accessor) == FIGHTER_STATUS_KIND_CLIFF_ROBBED - { - 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 - { + if !is_training_mode() { + return; + } + + if !is_operation_cpu(module_accessor) { + return; + } + + // Check for OOS delay + if is_in_shieldstun(module_accessor) && !shield::allow_oos() { + return; + } + + if !(is_in_hitstun(module_accessor) + || is_in_landing(module_accessor) + || is_in_shieldstun(module_accessor) + || is_in_footstool(module_accessor) + || StatusModule::status_kind(module_accessor) == FIGHTER_STATUS_KIND_CLIFF_ROBBED) + { + return; + } + + match MENU.mash_state { + Mash::Airdodge => { + *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_AIR_ESCAPE; + } + Mash::Jump => { + if !is_in_landing(module_accessor) { + *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_JUMP_BUTTON; + } + } + Mash::Spotdodge => { + *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE; + } + Mash::RollForward => { + *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE_F; + } + Mash::RollBack => { + *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE_B; + } + Mash::Attack => { + use Attack::*; + + match MENU.mash_attack_state { + Nair | Fair | Bair | UpAir | 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::Spotdodge => { - if category == FIGHTER_PAD_COMMAND_CATEGORY1 { - *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE; - } - } - Mash::RollForward => { - if category == FIGHTER_PAD_COMMAND_CATEGORY1 { - *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE_F; - } - } - Mash::RollBack => { - if category == FIGHTER_PAD_COMMAND_CATEGORY1 { - *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE_B; - } - } - Mash::Attack => { - if category == FIGHTER_PAD_COMMAND_CATEGORY1 { - use Attack::*; - - match MENU.mash_attack_state { - Nair | Fair | Bair | UpAir | 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; - } - } - NeutralB => *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_N, - SideB => *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_S, - UpB => *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_HI, - DownB => *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_LW, - UpSmash => *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_HI4, - 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]; - } - } - } - _ => (), + NeutralB => *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_N, + SideB => *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_S, + UpB => *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_HI, + DownB => *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_LW, + UpSmash => *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_HI4, + Grab => *flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_CATCH, } } + Mash::Random => { + let random_commands = get_random_command_list(module_accessor); + + if random_commands.len() == 0 { + return; + } + + let random_cmd_index = + app::sv_math::rand(hash40("fighter"), random_commands.len() as i32) as usize; + + *flag |= random_commands[random_cmd_index]; + } + _ => (), } } +unsafe fn get_random_command_list( + module_accessor: &mut app::BattleObjectModuleAccessor, +) -> Vec { + let situation_kind = StatusModule::situation_kind(module_accessor) as i32; + + if situation_kind == SITUATION_KIND_AIR { + return 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, + ]; + } + + if situation_kind == SITUATION_KIND_GROUND { + return 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, + ]; + } + + return vec![]; +} + 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) - || is_in_footstool(module_accessor)) - { - return Some(true); - } - } + if !is_training_mode() { + return None; + } + + if !is_operation_cpu(module_accessor) { + return None; + } + + if ![*CONTROL_PAD_BUTTON_GUARD_HOLD, *CONTROL_PAD_BUTTON_GUARD].contains(&button) { + return None; + } + + if MENU.mash_state == Mash::Airdodge + && !(is_in_hitstun(module_accessor) + || is_in_landing(module_accessor) + || is_in_footstool(module_accessor)) + { + return Some(true); } None diff --git a/src/training/save_states.rs b/src/training/save_states.rs index 62bdedc..21d5356 100644 --- a/src/training/save_states.rs +++ b/src/training/save_states.rs @@ -29,166 +29,163 @@ static mut SAVE_STATE_LR_CPU: f32 = 1.0; static mut SAVE_STATE_SITUATION_KIND_CPU: i32 = 0 as i32; pub unsafe fn save_states(module_accessor: &mut app::BattleObjectModuleAccessor) { + if !is_training_mode() { + return; + } + let status = StatusModule::status_kind(module_accessor) as i32; - if is_training_mode() { - let save_state_x: *mut f32; - let save_state_y: *mut f32; - let save_state_percent: *mut f32; - let save_state_lr: *mut f32; - let save_state_situation_kind: *mut i32; - let save_state: *mut SaveState; - if is_operation_cpu(module_accessor) { - save_state_x = &mut SAVE_STATE_X_CPU; - save_state_y = &mut SAVE_STATE_Y_CPU; - save_state_percent = &mut SAVE_STATE_PERCENT_CPU; - save_state_lr = &mut SAVE_STATE_LR_CPU; - save_state_situation_kind = &mut SAVE_STATE_SITUATION_KIND_CPU; - save_state = &mut SAVE_STATE_CPU_STATE; - } else { - save_state_x = &mut SAVE_STATE_X_PLAYER; - save_state_y = &mut SAVE_STATE_Y_PLAYER; - save_state_percent = &mut SAVE_STATE_PERCENT_PLAYER; - save_state_lr = &mut SAVE_STATE_LR_PLAYER; - save_state_situation_kind = &mut SAVE_STATE_SITUATION_KIND_PLAYER; - save_state = &mut SAVE_STATE_PLAYER_STATE; + let save_state_x: *mut f32; + let save_state_y: *mut f32; + let save_state_percent: *mut f32; + let save_state_lr: *mut f32; + let save_state_situation_kind: *mut i32; + let save_state: *mut SaveState; + if is_operation_cpu(module_accessor) { + save_state_x = &mut SAVE_STATE_X_CPU; + save_state_y = &mut SAVE_STATE_Y_CPU; + save_state_percent = &mut SAVE_STATE_PERCENT_CPU; + save_state_lr = &mut SAVE_STATE_LR_CPU; + save_state_situation_kind = &mut SAVE_STATE_SITUATION_KIND_CPU; + save_state = &mut SAVE_STATE_CPU_STATE; + } else { + save_state_x = &mut SAVE_STATE_X_PLAYER; + save_state_y = &mut SAVE_STATE_Y_PLAYER; + save_state_percent = &mut SAVE_STATE_PERCENT_PLAYER; + save_state_lr = &mut SAVE_STATE_LR_PLAYER; + save_state_situation_kind = &mut SAVE_STATE_SITUATION_KIND_PLAYER; + save_state = &mut SAVE_STATE_PLAYER_STATE; + } + + // Grab + Dpad up: reset state + if ControlModule::check_button_on(module_accessor, *CONTROL_PAD_BUTTON_CATCH) + && ControlModule::check_button_trigger(module_accessor, *CONTROL_PAD_BUTTON_APPEAL_HI) + { + if *save_state == NoAction { + SAVE_STATE_PLAYER_STATE = CameraMove; + SAVE_STATE_CPU_STATE = CameraMove; } + return; + } - // Grab + Dpad up: reset state - if ControlModule::check_button_on(module_accessor, *CONTROL_PAD_BUTTON_CATCH) - && ControlModule::check_button_trigger(module_accessor, *CONTROL_PAD_BUTTON_APPEAL_HI) - { - if *save_state == NoAction { - SAVE_STATE_PLAYER_STATE = CameraMove; - SAVE_STATE_CPU_STATE = CameraMove; - } - return; - } + // move to camera bounds + if *save_state == CameraMove { + *save_state = PosMove; - // move to camera bounds - if *save_state == CameraMove { - *save_state = PosMove; + let left_right = (PostureModule::pos_x(module_accessor) > 0.0) as i32 as f32 + - (PostureModule::pos_x(module_accessor) < 0.0) as i32 as f32; + let y_pos = 20.0; - let left_right = (PostureModule::pos_x(module_accessor) > 0.0) as i32 as f32 - - (PostureModule::pos_x(module_accessor) < 0.0) as i32 as f32; - let y_pos = 20.0; + let pos = Vector3f { + x: left_right * 50.0, + y: y_pos, + z: 0.0, + }; + PostureModule::set_pos(module_accessor, &pos); - let pos = Vector3f { - x: left_right * 50.0, - y: y_pos, - z: 0.0, - }; - PostureModule::set_pos(module_accessor, &pos); - - // force aerial, because from aerial state we can move anywhere - if StatusModule::situation_kind(module_accessor) == SITUATION_KIND_GROUND { - StatusModule::change_status_request( - module_accessor, - *FIGHTER_STATUS_KIND_JUMP_SQUAT, - false, - ); - } - return; - } - - // move to correct pos - if *save_state == PosMove { - if StatusModule::situation_kind(module_accessor) == SITUATION_KIND_GROUND { - return; - } - - KineticModule::clear_speed_all(module_accessor); - - let pos = Vector3f { - x: *save_state_x, - y: *save_state_y, - z: 0.0, - }; - PostureModule::set_pos(module_accessor, &pos); - PostureModule::set_lr(module_accessor, *save_state_lr); - DamageModule::heal( + // force aerial, because from aerial state we can move anywhere + if StatusModule::situation_kind(module_accessor) == SITUATION_KIND_GROUND { + StatusModule::change_status_request( module_accessor, - -1.0 * DamageModule::damage(module_accessor, 0), - 0, - ); - DamageModule::add_damage(module_accessor, *save_state_percent, 0); - - StatusModule::set_situation_kind( - module_accessor, - app::SituationKind { - situation_kind: *save_state_situation_kind, - }, + *FIGHTER_STATUS_KIND_JUMP_SQUAT, false, ); + } + return; + } - if *save_state_situation_kind == SITUATION_KIND_GROUND - && status != FIGHTER_STATUS_KIND_WAIT - { - StatusModule::change_status_request( - module_accessor, - *FIGHTER_STATUS_KIND_CLIFF_WAIT, - false, - ); - } else if *save_state_situation_kind == SITUATION_KIND_AIR - && status != FIGHTER_STATUS_KIND_FALL - { - StatusModule::change_status_request( - module_accessor, - *FIGHTER_STATUS_KIND_FALL, - false, - ); - } else if *save_state_situation_kind == SITUATION_KIND_CLIFF - && status != FIGHTER_STATUS_KIND_CLIFF_CATCH_MOVE - && status != FIGHTER_STATUS_KIND_CLIFF_CATCH - { - StatusModule::change_status_request( - module_accessor, - *FIGHTER_STATUS_KIND_CLIFF_CATCH_MOVE, - false, - ); - } - *save_state = NoAction; + // move to correct pos + if *save_state == PosMove { + if StatusModule::situation_kind(module_accessor) == SITUATION_KIND_GROUND { return; } - // Grab + Dpad down: Save state - if ControlModule::check_button_on(module_accessor, *CONTROL_PAD_BUTTON_CATCH) - && ControlModule::check_button_trigger(module_accessor, *CONTROL_PAD_BUTTON_APPEAL_LW) + KineticModule::clear_speed_all(module_accessor); + + let pos = Vector3f { + x: *save_state_x, + y: *save_state_y, + z: 0.0, + }; + PostureModule::set_pos(module_accessor, &pos); + PostureModule::set_lr(module_accessor, *save_state_lr); + DamageModule::heal( + module_accessor, + -1.0 * DamageModule::damage(module_accessor, 0), + 0, + ); + DamageModule::add_damage(module_accessor, *save_state_percent, 0); + + StatusModule::set_situation_kind( + module_accessor, + app::SituationKind { + situation_kind: *save_state_situation_kind, + }, + false, + ); + + if *save_state_situation_kind == SITUATION_KIND_GROUND && status != FIGHTER_STATUS_KIND_WAIT { - SAVE_STATE_PLAYER_STATE = Save; - SAVE_STATE_CPU_STATE = Save; - } - - if *save_state == Save { - *save_state = NoAction; - - *save_state_x = PostureModule::pos_x(module_accessor); - *save_state_y = PostureModule::pos_y(module_accessor); - *save_state_lr = PostureModule::lr(module_accessor); - *save_state_percent = DamageModule::damage(module_accessor, 0); - *save_state_situation_kind = StatusModule::situation_kind(module_accessor); - - let zeros = Vector3f { - x: 0.0, - y: 0.0, - z: 0.0, - }; - - EffectModule::req_on_joint( + StatusModule::change_status_request( module_accessor, - Hash40::new("sys_deku_flash"), - Hash40::new("top"), - &zeros, - &zeros, - 0.25, - &zeros, - &zeros, - true, - *EFFECT_SUB_ATTRIBUTE_NO_JOINT_SCALE as u32 - | *EFFECT_SUB_ATTRIBUTE_FOLLOW as u32 - | *EFFECT_SUB_ATTRIBUTE_CONCLUDE_STATUS as u32, - 0, - 0, + *FIGHTER_STATUS_KIND_CLIFF_WAIT, + false, + ); + } else if *save_state_situation_kind == SITUATION_KIND_AIR + && status != FIGHTER_STATUS_KIND_FALL + { + StatusModule::change_status_request(module_accessor, *FIGHTER_STATUS_KIND_FALL, false); + } else if *save_state_situation_kind == SITUATION_KIND_CLIFF + && status != FIGHTER_STATUS_KIND_CLIFF_CATCH_MOVE + && status != FIGHTER_STATUS_KIND_CLIFF_CATCH + { + StatusModule::change_status_request( + module_accessor, + *FIGHTER_STATUS_KIND_CLIFF_CATCH_MOVE, + false, ); } + *save_state = NoAction; + return; + } + + // Grab + Dpad down: Save state + if ControlModule::check_button_on(module_accessor, *CONTROL_PAD_BUTTON_CATCH) + && ControlModule::check_button_trigger(module_accessor, *CONTROL_PAD_BUTTON_APPEAL_LW) + { + SAVE_STATE_PLAYER_STATE = Save; + SAVE_STATE_CPU_STATE = Save; + } + + if *save_state == Save { + *save_state = NoAction; + + *save_state_x = PostureModule::pos_x(module_accessor); + *save_state_y = PostureModule::pos_y(module_accessor); + *save_state_lr = PostureModule::lr(module_accessor); + *save_state_percent = DamageModule::damage(module_accessor, 0); + *save_state_situation_kind = StatusModule::situation_kind(module_accessor); + + let zeros = Vector3f { + x: 0.0, + y: 0.0, + z: 0.0, + }; + + EffectModule::req_on_joint( + module_accessor, + Hash40::new("sys_deku_flash"), + Hash40::new("top"), + &zeros, + &zeros, + 0.25, + &zeros, + &zeros, + true, + *EFFECT_SUB_ATTRIBUTE_NO_JOINT_SCALE as u32 + | *EFFECT_SUB_ATTRIBUTE_FOLLOW as u32 + | *EFFECT_SUB_ATTRIBUTE_CONCLUDE_STATUS as u32, + 0, + 0, + ); } } diff --git a/src/training/shield.rs b/src/training/shield.rs index 9fde5fb..87afbb7 100644 --- a/src/training/shield.rs +++ b/src/training/shield.rs @@ -9,7 +9,7 @@ use smash::lib::L2CValue; use smash::lua2cpp::L2CFighterCommon; // How many hits to hold shield until picking an Out Of Shield option -static mut MULTI_HIT_OFFSET : u8 = MENU.oos_offset; +static mut MULTI_HIT_OFFSET: u8 = MENU.oos_offset; // Used to only decrease once per shieldstun change static mut WAS_IN_SHIELDSTUN: bool = false; @@ -24,7 +24,7 @@ unsafe fn should_pause_shield_decay() -> bool { !SHIELD_DECAY } -unsafe fn reset_oos_offset(){ +unsafe fn reset_oos_offset() { /* * Need to offset by 1, since we decrease as soon as shield gets hit * but only check later if we can OOS @@ -32,8 +32,7 @@ unsafe fn reset_oos_offset(){ MULTI_HIT_OFFSET = MENU.oos_offset + 1; } -unsafe fn handle_oos_offset(module_accessor: &mut app::BattleObjectModuleAccessor) -{ +unsafe fn handle_oos_offset(module_accessor: &mut app::BattleObjectModuleAccessor) { // Check if we are currently in shield stun if !is_in_shieldstun(module_accessor) { // Make sure we don't forget and wait until we get hit on shield @@ -55,7 +54,7 @@ unsafe fn handle_oos_offset(module_accessor: &mut app::BattleObjectModuleAccesso WAS_IN_SHIELDSTUN = true; } -pub unsafe fn allow_oos()->bool { +pub unsafe fn allow_oos() -> bool { // Delay OOS until offset hits 0 MULTI_HIT_OFFSET == 0 } @@ -70,8 +69,7 @@ pub unsafe fn get_command_flag_cat(module_accessor: &mut app::BattleObjectModule } // Reset oos offset when standing - if is_idle(module_accessor) - || is_in_hitstun(module_accessor){ + if is_idle(module_accessor) || is_in_hitstun(module_accessor) { reset_oos_offset(); } @@ -87,29 +85,32 @@ pub unsafe fn get_param_float( param_type: u64, param_hash: u64, ) -> Option { + if !is_training_mode() { + return None; + } + if !is_operation_cpu(module_accessor) { return None; } - if is_training_mode() { + if MENU.shield_state != Shield::None { + handle_oos_offset(module_accessor); + } - if MENU.shield_state != Shield::None { - handle_oos_offset(module_accessor); + // Shield Decay//Recovery + if MENU.shield_state == Shield::Infinite || should_pause_shield_decay() { + if param_type != hash40("common") { + return None; } - - if MENU.shield_state == Shield::Infinite || should_pause_shield_decay() { - 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); - } - } + 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); } } @@ -118,31 +119,33 @@ pub unsafe fn get_param_float( 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 attack then we will always hold shield - if MENU.mash_state != Mash::Attack { - return true; + if ![Shield::Hold, Shield::Infinite].contains(&MENU.shield_state) { + return false; + } + + // If we are not mashing attack then we will always hold shield + if MENU.mash_state != Mash::Attack { + return true; + } + + // Hold shield while OOS is not allowed + if !allow_oos() { + 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 [Attack::NeutralB, Attack::SideB, Attack::DownB].contains(&MENU.mash_attack_state) { + return false; } - // Hold shield while OOS is not allowed - if !allow_oos() { + if MENU.mash_attack_state == Attack::Grab { 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 [Attack::NeutralB, Attack::SideB, Attack::DownB].contains(&MENU.mash_attack_state) { - return false; - } - - if MENU.mash_attack_state == Attack::Grab { - return true; - } - } } false @@ -150,154 +153,153 @@ pub unsafe fn should_hold_shield(module_accessor: &mut app::BattleObjectModuleAc #[skyline::hook(replace = smash::lua2cpp::L2CFighterCommon_sub_guard_cont)] pub unsafe fn handle_sub_guard_cont(fighter: &mut L2CFighterCommon) -> L2CValue { + mod_handle_sub_guard_cont(fighter); + original!()(fighter) +} + +unsafe fn mod_handle_sub_guard_cont(fighter: &mut L2CFighterCommon) { let module_accessor = sv_system::battle_object_module_accessor(fighter.lua_state_agent); + if !is_training_mode() + || !is_operation_cpu(module_accessor) + || StatusModule::prev_status_kind(module_accessor, 0) != FIGHTER_STATUS_KIND_GUARD_DAMAGE + { + return; + } // Enable shield decay - if is_training_mode() - && is_operation_cpu(module_accessor) - && StatusModule::prev_status_kind(module_accessor, 0) == FIGHTER_STATUS_KIND_GUARD_DAMAGE - { - set_shield_decay(true); - } + set_shield_decay(true); // Check for OOS delay - if is_training_mode() - && is_operation_cpu(module_accessor) - && StatusModule::prev_status_kind(module_accessor, 0) == FIGHTER_STATUS_KIND_GUARD_DAMAGE - && !allow_oos() { - return original!()(fighter); + if !allow_oos() { + return; } - if is_training_mode() && is_operation_cpu(module_accessor) { - if MENU.mash_state == Mash::Attack && MENU.mash_attack_state == Attack::Grab { - if StatusModule::prev_status_kind(module_accessor, 0) - == FIGHTER_STATUS_KIND_GUARD_DAMAGE - { - if WorkModule::get_int( - module_accessor, - *FIGHTER_INSTANCE_WORK_ID_INT_INVALID_CATCH_FRAME, - ) == 0 - { - if WorkModule::is_enable_transition_term( - module_accessor, - *FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_CATCH, - ) { - fighter.fighter_base.change_status( - L2CValue::new_int(*FIGHTER_STATUS_KIND_CATCH as u64), - L2CValue::new_bool(true), - ); - } - } - } - } - if MENU.mash_state == Mash::Spotdodge { - if StatusModule::prev_status_kind(module_accessor, 0) - == FIGHTER_STATUS_KIND_GUARD_DAMAGE - { - if WorkModule::is_enable_transition_term( - module_accessor, - *FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_ESCAPE, - ) { - fighter.fighter_base.change_status( - L2CValue::new_int(*FIGHTER_STATUS_KIND_ESCAPE as u64), - L2CValue::new_bool(true), - ); - } - } - } - if MENU.mash_state == Mash::RollForward { - if StatusModule::prev_status_kind(module_accessor, 0) - == FIGHTER_STATUS_KIND_GUARD_DAMAGE - { - if WorkModule::is_enable_transition_term( - module_accessor, - *FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_ESCAPE, - ) { - fighter.fighter_base.change_status( - L2CValue::new_int(*FIGHTER_STATUS_KIND_ESCAPE_F as u64), - L2CValue::new_bool(true), - ); - } - } - } - if MENU.mash_state == Mash::RollBack { - if StatusModule::prev_status_kind(module_accessor, 0) - == FIGHTER_STATUS_KIND_GUARD_DAMAGE - { - if WorkModule::is_enable_transition_term( - module_accessor, - *FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_ESCAPE, - ) { - fighter.fighter_base.change_status( - L2CValue::new_int(*FIGHTER_STATUS_KIND_ESCAPE_B as u64), - L2CValue::new_bool(true), - ); - } - } - } - if MENU.mash_state == Mash::Attack { - if MENU.mash_attack_state == Attack::UpB { - if StatusModule::prev_status_kind(module_accessor, 0) - == FIGHTER_STATUS_KIND_GUARD_DAMAGE - { - if WorkModule::is_enable_transition_term( - module_accessor, - *FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_JUMP_SQUAT_BUTTON, - ) { - fighter.fighter_base.change_status( - L2CValue::new_int(*FIGHTER_STATUS_KIND_SPECIAL_HI as u64), - L2CValue::new_bool(false), - ); - } - } - } - if MENU.mash_attack_state == Attack::UpSmash { - if StatusModule::prev_status_kind(module_accessor, 0) - == FIGHTER_STATUS_KIND_GUARD_DAMAGE - { - if WorkModule::is_enable_transition_term( - module_accessor, - *FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_JUMP_SQUAT_BUTTON, - ) { - fighter.fighter_base.change_status( - L2CValue::new_int(*FIGHTER_STATUS_KIND_ATTACK_HI4_START as u64), - L2CValue::new_bool(false), - ); - } - } - } - } + if MENU.mash_state == Mash::Attack { + handle_attack_option(fighter, module_accessor); + return; } - original!()(fighter) + if WorkModule::is_enable_transition_term( + module_accessor, + *FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_ESCAPE, + ) { + handle_escape_option(fighter); + } +} + +unsafe fn handle_escape_option(fighter: &mut L2CFighterCommon) { + match MENU.mash_state { + Mash::Spotdodge => { + fighter.fighter_base.change_status( + L2CValue::new_int(*FIGHTER_STATUS_KIND_ESCAPE as u64), + L2CValue::new_bool(true), + ); + } + Mash::RollForward => { + fighter.fighter_base.change_status( + L2CValue::new_int(*FIGHTER_STATUS_KIND_ESCAPE_F as u64), + L2CValue::new_bool(true), + ); + } + Mash::RollBack => { + fighter.fighter_base.change_status( + L2CValue::new_int(*FIGHTER_STATUS_KIND_ESCAPE_B as u64), + L2CValue::new_bool(true), + ); + } + _ => (), + } +} + +unsafe fn handle_attack_option( + fighter: &mut L2CFighterCommon, + module_accessor: &mut app::BattleObjectModuleAccessor, +) { + match MENU.mash_attack_state { + Attack::Grab => { + if !WorkModule::is_enable_transition_term( + module_accessor, + *FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_CATCH, + ) || !WorkModule::get_int( + module_accessor, + *FIGHTER_INSTANCE_WORK_ID_INT_INVALID_CATCH_FRAME, + ) == 0 + { + return; + } + + fighter.fighter_base.change_status( + L2CValue::new_int(*FIGHTER_STATUS_KIND_CATCH as u64), + L2CValue::new_bool(true), + ); + } + Attack::UpB => { + if !WorkModule::is_enable_transition_term( + module_accessor, + *FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_JUMP_SQUAT_BUTTON, + ) { + return; + } + fighter.fighter_base.change_status( + L2CValue::new_int(*FIGHTER_STATUS_KIND_SPECIAL_HI as u64), + L2CValue::new_bool(false), + ); + } + Attack::UpSmash => { + if !WorkModule::is_enable_transition_term( + module_accessor, + *FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_JUMP_SQUAT_BUTTON, + ) { + return; + } + fighter.fighter_base.change_status( + L2CValue::new_int(*FIGHTER_STATUS_KIND_ATTACK_HI4_START as u64), + L2CValue::new_bool(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); - } - } + if should_return_none_in_check_button(module_accessor, button) { + return None; } - - None + Some(true) } 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); - } - } + if should_return_none_in_check_button(module_accessor, button) { + return None; + } + Some(false) +} + +unsafe fn should_return_none_in_check_button( + module_accessor: &mut app::BattleObjectModuleAccessor, + button: i32, +) -> bool { + if !is_training_mode() { + return true; } - None + if !is_operation_cpu(module_accessor) { + return true; + } + + if ![*CONTROL_PAD_BUTTON_GUARD_HOLD, *CONTROL_PAD_BUTTON_GUARD].contains(&button) { + return true; + } + + if !should_hold_shield(module_accessor) { + return true; + } + + false } diff --git a/src/training/tech.rs b/src/training/tech.rs index 45d4f08..9a4afa2 100644 --- a/src/training/tech.rs +++ b/src/training/tech.rs @@ -15,61 +15,89 @@ pub unsafe fn handle_change_status( ) -> L2CValue { let mut status_kind = status_kind; let mut unk = unk; - let module_accessor = sv_system::battle_object_module_accessor(fighter.lua_state_agent); - if is_training_mode() && is_operation_cpu(module_accessor) { - let status_kind_int = status_kind - .try_get_int() - .unwrap_or(*FIGHTER_STATUS_KIND_WAIT as u64) as i32; - if status_kind_int == FIGHTER_STATUS_KIND_DOWN - || status_kind_int == FIGHTER_STATUS_KIND_DAMAGE_FLY_REFLECT_D - { - match MENU.tech_state { - TechOption::Random => { - 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 { - status_kind = - L2CValue::new_int(random_statuses[random_status_index] as u64); - unk = L2CValue::new_bool(true); - } - } - TechOption::InPlace => { - status_kind = L2CValue::new_int(*FIGHTER_STATUS_KIND_PASSIVE as u64); - unk = L2CValue::new_bool(true); - } - TechOption::Roll => { - status_kind = L2CValue::new_int(*FIGHTER_STATUS_KIND_PASSIVE_FB as u64); - unk = L2CValue::new_bool(true); - } - _ => (), - } - } else if status_kind_int == FIGHTER_STATUS_KIND_STOP_WALL - || status_kind_int == FIGHTER_STATUS_KIND_DAMAGE_FLY_REFLECT_LR - { - if MENU.tech_state != TechOption::None && MENU.tech_state != TechOption::Miss { - status_kind = L2CValue::new_int(*FIGHTER_STATUS_KIND_PASSIVE_WALL as u64); - unk = L2CValue::new_bool(true); - } - } else if status_kind_int == FIGHTER_STATUS_KIND_STOP_CEIL - || status_kind_int == FIGHTER_STATUS_KIND_DAMAGE_FLY_REFLECT_U - { - if MENU.tech_state != TechOption::None && MENU.tech_state != TechOption::Miss { - status_kind = L2CValue::new_int(*FIGHTER_STATUS_KIND_PASSIVE_CEIL as u64); - unk = L2CValue::new_bool(true); - } - } - } + mod_handle_change_status(fighter, &mut status_kind, &mut unk); original!()(fighter, status_kind, unk) } +unsafe fn mod_handle_change_status( + fighter: &mut L2CFighterBase, + status_kind: &mut L2CValue, + unk: &mut L2CValue, +) { + if !is_training_mode() { + return; + } + + let module_accessor = sv_system::battle_object_module_accessor(fighter.lua_state_agent); + if !is_operation_cpu(module_accessor) { + return; + } + + if MENU.tech_state == TechOption::None { + return; + } + + if MENU.tech_state == TechOption::Miss { + return; + } + + let status_kind_int = status_kind + .try_get_int() + .unwrap_or(*FIGHTER_STATUS_KIND_WAIT as u64) as i32; + + // Ground Tech + if status_kind_int == FIGHTER_STATUS_KIND_DOWN + || status_kind_int == FIGHTER_STATUS_KIND_DAMAGE_FLY_REFLECT_D + { + match MENU.tech_state { + TechOption::Random => { + 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 { + *status_kind = L2CValue::new_int(random_statuses[random_status_index] as u64); + *unk = L2CValue::new_bool(true); + } + } + TechOption::InPlace => { + *status_kind = L2CValue::new_int(*FIGHTER_STATUS_KIND_PASSIVE as u64); + *unk = L2CValue::new_bool(true); + } + TechOption::Roll => { + *status_kind = L2CValue::new_int(*FIGHTER_STATUS_KIND_PASSIVE_FB as u64); + *unk = L2CValue::new_bool(true); + } + _ => (), + } + + return; + } + + // Wall Tech + if status_kind_int == FIGHTER_STATUS_KIND_STOP_WALL + || status_kind_int == FIGHTER_STATUS_KIND_DAMAGE_FLY_REFLECT_LR + { + *status_kind = L2CValue::new_int(*FIGHTER_STATUS_KIND_PASSIVE_WALL as u64); + *unk = L2CValue::new_bool(true); + return; + } + + // Ceiling Tech + if status_kind_int == FIGHTER_STATUS_KIND_STOP_CEIL + || status_kind_int == FIGHTER_STATUS_KIND_DAMAGE_FLY_REFLECT_U + { + *status_kind = L2CValue::new_int(*FIGHTER_STATUS_KIND_PASSIVE_CEIL as u64); + *unk = L2CValue::new_bool(true); + return; + } +} + pub unsafe fn should_perform_defensive_option( module_accessor: &mut app::BattleObjectModuleAccessor, prev_status: i32, @@ -101,34 +129,46 @@ pub unsafe fn get_command_flag_cat( _category: i32, flag: &mut i32, ) { - if MENU.tech_state != TechOption::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, - ]; + if !is_training_mode() { + return; + } - 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], - false, - ); - } else if should_perform_defensive_option(module_accessor, prev_status, status) { - perform_defensive_option(module_accessor, flag); - } + if !is_operation_cpu(module_accessor) { + return; + } + + if MENU.tech_state == TechOption::None { + return; + } + + 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], + false, + ); + return; + } + + let prev_status = StatusModule::prev_status_kind(module_accessor, 0) as i32; + + if should_perform_defensive_option(module_accessor, prev_status, status) { + perform_defensive_option(module_accessor, flag); } } @@ -136,47 +176,66 @@ 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); - } - } + if !is_training_mode() { + return None; } - None + if !is_operation_cpu(module_accessor) { + return None; + } + + if ![*CONTROL_PAD_BUTTON_GUARD_HOLD, *CONTROL_PAD_BUTTON_GUARD].contains(&button) { + return None; + } + + if !(MENU.defensive_state == Defensive::Shield) { + return None; + } + + let prev_status = StatusModule::prev_status_kind(module_accessor, 0) as i32; + let status = StatusModule::status_kind(module_accessor) as i32; + if !should_perform_defensive_option(module_accessor, prev_status, status) { + return None; + } + + return Some(true); } pub unsafe fn change_motion( module_accessor: &mut app::BattleObjectModuleAccessor, motion_kind: u64, ) -> Option { - if MENU.tech_state != TechOption::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")); - } + if !is_training_mode() { + return None; + } + + if !is_operation_cpu(module_accessor) { + return None; + } + + if MENU.tech_state == TechOption::None { + return None; + } + + let random_roll = app::sv_math::rand(hash40("fighter"), 2); + + if [hash40("passive_stand_f"), hash40("passive_stand_b")].contains(&motion_kind) { + if random_roll != 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 random_roll != 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 random_roll != 0 { + return Some(hash40("down_forward_d")); + } else { + return Some(hash40("down_back_d")); } }