diff --git a/src/lib.rs b/src/lib.rs index fef05f0..7b7a50e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,6 +2,7 @@ #![feature(const_mut_refs)] #![feature(exclusive_range_pattern)] #![feature(c_variadic)] +#![feature(pointer_byte_offsets)] #![allow( clippy::borrow_interior_mutable_const, clippy::declare_interior_mutable_const, diff --git a/src/training/buff.rs b/src/training/buff.rs index 71aebe0..57c55f0 100644 --- a/src/training/buff.rs +++ b/src/training/buff.rs @@ -62,9 +62,10 @@ pub unsafe fn handle_buffs( module_accessor: &mut app::BattleObjectModuleAccessor, fighter_kind: i32, status: i32, - percent: f32, ) -> bool { - // Future Enhancement - Remove startup effects on buffs (Flash of Limit, Wii Fit's flash, Shulk's occasional Jump Art smoke, etc.) + // Future Enhancements: + // - Remove startup effects on buffs (Flash of Limit, Wii Fit's flash, Shulk's occasional Jump Art smoke, etc.) + // - Ensure IS_BUFFING_CPU && IS_BUFFING_PLAYER are set to false on leaving training mode SoundModule::stop_all_sound(module_accessor); // silences buff sfx other than KO Punch ControlModule::stop_rumble(module_accessor, false); MotionAnimcmdModule::set_sleep(module_accessor, false); @@ -78,13 +79,13 @@ pub unsafe fn handle_buffs( } else if fighter_kind == *FIGHTER_KIND_JACK && menu_vec.contains(&BuffOption::ARSENE) { return buff_joker(module_accessor); } else if fighter_kind == *FIGHTER_KIND_WIIFIT && menu_vec.contains(&BuffOption::BREATHING) { - return buff_wiifit(module_accessor, status, percent); + return buff_wiifit(module_accessor, status); } else if fighter_kind == *FIGHTER_KIND_CLOUD && menu_vec.contains(&BuffOption::LIMIT) { return buff_cloud(module_accessor); } else if fighter_kind == *FIGHTER_KIND_LITTLEMAC && menu_vec.contains(&BuffOption::KO) { return buff_mac(module_accessor); } else if fighter_kind == *FIGHTER_KIND_EDGE && menu_vec.contains(&BuffOption::WING) { - return buff_sepiroth(module_accessor, percent); + return buff_sepiroth(module_accessor); } else if fighter_kind == *FIGHTER_KIND_SHULK { return buff_shulk(module_accessor, status); } @@ -193,27 +194,36 @@ unsafe fn buff_mac(module_accessor: &mut app::BattleObjectModuleAccessor) -> boo true } -unsafe fn buff_sepiroth( - module_accessor: &mut app::BattleObjectModuleAccessor, - percent: f32, -) -> bool { - start_buff(module_accessor); - if WorkModule::get_int( - module_accessor, - *FIGHTER_EDGE_INSTANCE_WORK_ID_INT_ONE_WINGED_WING_STATE, - ) == 1 - { - // Once we're in wing, heal to correct damage - DamageModule::heal( +unsafe fn buff_sepiroth(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool { + if !is_buffing(module_accessor) { + // To ensure Sephiroth gains Wing, we set flags for Sephiroth being in a Stamina Mode Sudden Death match. + // The function that checks whether to start giving Sephiroth Wing every frame also checks for this exact + // scenario. We do this because inline hooking it with the current version of skyline crashes the game, + // likely due to the hook clobbering some of the floating point registers that we need for later. + WorkModule::on_flag( module_accessor, - -1.0 * DamageModule::damage(module_accessor, 0), - 0, + *FIGHTER_EDGE_INSTANCE_WORK_ID_FLAG_IS_RULE_HP, + ); + WorkModule::on_flag( + module_accessor, + *FIGHTER_EDGE_INSTANCE_WORK_ID_FLAG_SUDDEN_DEATH, + ); + } + start_buff(module_accessor); + if WorkModule::is_flag( + module_accessor, + *FIGHTER_EDGE_INSTANCE_WORK_ID_FLAG_ONE_WINGED_ACTIVATED, + ) { + // Wing is activated, so we turn off these flags so future deaths don't spawn Sephiroth in with Wing + WorkModule::off_flag( + module_accessor, + *FIGHTER_EDGE_INSTANCE_WORK_ID_FLAG_IS_RULE_HP, + ); + WorkModule::off_flag( + module_accessor, + *FIGHTER_EDGE_INSTANCE_WORK_ID_FLAG_SUDDEN_DEATH, ); - DamageModule::add_damage(module_accessor, percent, 0); return true; - } else { - // if we're not in wing, add damage - DamageModule::add_damage(module_accessor, 1000.0, 0); } false } @@ -259,29 +269,13 @@ unsafe fn buff_shulk(module_accessor: &mut app::BattleObjectModuleAccessor, stat false } -unsafe fn buff_wiifit( - module_accessor: &mut app::BattleObjectModuleAccessor, - status: i32, - percent: f32, -) -> bool { - if is_buffing(module_accessor) { - if frame_counter::should_delay(2_u32, BUFF_DELAY_COUNTER) { - // Need to wait 2 frames to make sure we stop breathing SFX - return false; - } - // Deep Breathing can heal, so we need to reset the damage - DamageModule::heal( - module_accessor, - -1.0 * DamageModule::damage(module_accessor, 0), - 0, - ); - DamageModule::add_damage(module_accessor, percent, 0); - return true; +unsafe fn buff_wiifit(module_accessor: &mut app::BattleObjectModuleAccessor, status: i32) -> bool { + if !is_buffing(module_accessor) { + start_buff(module_accessor); } let prev_status_kind = StatusModule::prev_status_kind(module_accessor, 0); if prev_status_kind == FIGHTER_WIIFIT_STATUS_KIND_SPECIAL_LW_SUCCESS { - start_buff(module_accessor); - return false; + return true; } if status != FIGHTER_WIIFIT_STATUS_KIND_SPECIAL_LW_SUCCESS { StatusModule::change_status_force( diff --git a/src/training/mash.rs b/src/training/mash.rs index fb04123..69062bf 100644 --- a/src/training/mash.rs +++ b/src/training/mash.rs @@ -622,10 +622,6 @@ unsafe fn get_flag( ) -> i32 { // let current_status = StatusModule::prev_status_kind(module_accessor,0); let current_status = StatusModule::status_kind(module_accessor); - println!( - "Current Status: {}, Expected Status: {}", - current_status, expected_status - ); if current_status == expected_status { // Reset Buffer reset(); diff --git a/src/training/mod.rs b/src/training/mod.rs index 6e3ead9..d9d702e 100644 --- a/src/training/mod.rs +++ b/src/training/mod.rs @@ -120,26 +120,6 @@ fn once_per_frame_per_fighter( return; } - /*unsafe { - let fighter_kind = app::utility::get_kind(module_accessor); - if fighter_kind == *FIGHTER_KIND_LITTLEMAC { - let status = StatusModule::status_kind(module_accessor); - let gage_max_keep = WorkModule::get_int(module_accessor, *FIGHTER_LITTLEMAC_INSTANCE_WORK_ID_INT_KO_GAGE_MAX_KEEP_FRAME); - let select_timer = WorkModule::get_int(module_accessor, *FIGHTER_LITTLEMAC_INSTANCE_WORK_ID_INT_SPECIAL_N2_HIT_FRAME); - - let max_effect_flag = WorkModule::is_flag(module_accessor, *FIGHTER_LITTLEMAC_INSTANCE_WORK_ID_FLAG_REQUEST_KO_GAUGE_MAX_EFFECT); - let mesh_flag = WorkModule::is_flag(module_accessor, *FIGHTER_LITTLEMAC_INSTANCE_WORK_ID_FLAG_DAMAGE_MESH); - - let gage_max_keep = WorkModule::get_float(module_accessor, *FIGHTER_LITTLEMAC_INSTANCE_WORK_ID_INT_KO_GAGE_MAX_KEEP_FRAME); - let select_timer = WorkModule::get_float(module_accessor, *FIGHTER_LITTLEMAC_INSTANCE_WORK_ID_INT_SPECIAL_N2_HIT_FRAME); - - // may need to check out his status flags and not just work insts - println!("Status: {:x}, Counter: {}, Select_Timer: {}, Decide_Interval_Frame: {}, SNType: {}, SNTypeSelect: {}, Sel_F: {}, Active_F: {}, SelButton: {}, Circ Menu: {}", - status, counter, select_timer, decide_interval_frame, special_n_type, special_n_type_select, select_flag, active_flag, select_button_push_flag, circle_menu_flag - ); - } - }*/ - unsafe { if menu::menu_condition(module_accessor) { menu::spawn_menu(); @@ -406,6 +386,26 @@ pub unsafe fn handle_check_doyle_summon_dispatch( ori } +#[skyline::hook(offset = 0x03ff9a0)] +pub unsafe fn handle_add_damage( + damage_module: *mut u64, // DamageModule + mut damage_to_add: f32, + param_2: i32, +) -> u64 { + if !is_training_mode() { + return original!()(damage_module, damage_to_add, param_2); + } + let module_accessor = + &mut **(damage_module.byte_add(0x8) as *mut *mut app::BattleObjectModuleAccessor); + // Prevent Wii Fit Deep Breathing from Healing on Save State Load + if utility::get_kind(module_accessor) == *FIGHTER_KIND_WIIFIT + && buff::is_buffing(module_accessor) + { + damage_to_add = 0.0; + } + original!()(damage_module, damage_to_add, param_2) +} + // Set Stale Moves to On static STALE_OFFSET: usize = 0x013e88a4; @@ -691,6 +691,9 @@ pub fn training_mods() { handle_check_doyle_summon_dispatch, handle_reused_ui, handle_req_screen, + handle_add_damage, + // Buff SFX + handle_fighter_play_se, // Stale Moves stale_handle, stale_menu_handle, @@ -702,8 +705,6 @@ pub fn training_mods() { handle_star_ko, // Clatter clatter::hook_start_clatter, - // Buff SFX - handle_fighter_play_se, ); combo::init(); diff --git a/src/training/save_states.rs b/src/training/save_states.rs index 488c558..1f92fdf 100644 --- a/src/training/save_states.rs +++ b/src/training/save_states.rs @@ -621,7 +621,7 @@ pub unsafe fn save_states(module_accessor: &mut app::BattleObjectModuleAccessor) if save_state.state == ApplyBuff { // needs its own save_state.state since this may take multiple frames, want it to loop - if buff::handle_buffs(module_accessor, fighter_kind, status, save_state.percent) { + if buff::handle_buffs(module_accessor, fighter_kind, status) { // returns true when done buffing fighter buff::restart_buff(module_accessor); // set is_buffing back to false when done