mirror of
https://github.com/jugeeya/UltimateTrainingModpack.git
synced 2025-03-18 20:36:11 +00:00
Buff Health Fixes (#571)
* Hooked AddDamage, pointer manipulation trouble * Working Wii Fit Fix * Inline Hook Setup for Sephiroth Wing (crashes) * Revert Broken Wing Chanes * Further revert * Fix Sephiroth Buff Percentage glitches
This commit is contained in:
parent
60f8ffc410
commit
fe8ae6f39f
5 changed files with 61 additions and 69 deletions
|
@ -2,6 +2,7 @@
|
||||||
#![feature(const_mut_refs)]
|
#![feature(const_mut_refs)]
|
||||||
#![feature(exclusive_range_pattern)]
|
#![feature(exclusive_range_pattern)]
|
||||||
#![feature(c_variadic)]
|
#![feature(c_variadic)]
|
||||||
|
#![feature(pointer_byte_offsets)]
|
||||||
#![allow(
|
#![allow(
|
||||||
clippy::borrow_interior_mutable_const,
|
clippy::borrow_interior_mutable_const,
|
||||||
clippy::declare_interior_mutable_const,
|
clippy::declare_interior_mutable_const,
|
||||||
|
|
|
@ -62,9 +62,10 @@ pub unsafe fn handle_buffs(
|
||||||
module_accessor: &mut app::BattleObjectModuleAccessor,
|
module_accessor: &mut app::BattleObjectModuleAccessor,
|
||||||
fighter_kind: i32,
|
fighter_kind: i32,
|
||||||
status: i32,
|
status: i32,
|
||||||
percent: f32,
|
|
||||||
) -> bool {
|
) -> 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
|
SoundModule::stop_all_sound(module_accessor); // silences buff sfx other than KO Punch
|
||||||
ControlModule::stop_rumble(module_accessor, false);
|
ControlModule::stop_rumble(module_accessor, false);
|
||||||
MotionAnimcmdModule::set_sleep(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) {
|
} else if fighter_kind == *FIGHTER_KIND_JACK && menu_vec.contains(&BuffOption::ARSENE) {
|
||||||
return buff_joker(module_accessor);
|
return buff_joker(module_accessor);
|
||||||
} else if fighter_kind == *FIGHTER_KIND_WIIFIT && menu_vec.contains(&BuffOption::BREATHING) {
|
} 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) {
|
} else if fighter_kind == *FIGHTER_KIND_CLOUD && menu_vec.contains(&BuffOption::LIMIT) {
|
||||||
return buff_cloud(module_accessor);
|
return buff_cloud(module_accessor);
|
||||||
} else if fighter_kind == *FIGHTER_KIND_LITTLEMAC && menu_vec.contains(&BuffOption::KO) {
|
} else if fighter_kind == *FIGHTER_KIND_LITTLEMAC && menu_vec.contains(&BuffOption::KO) {
|
||||||
return buff_mac(module_accessor);
|
return buff_mac(module_accessor);
|
||||||
} else if fighter_kind == *FIGHTER_KIND_EDGE && menu_vec.contains(&BuffOption::WING) {
|
} 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 {
|
} else if fighter_kind == *FIGHTER_KIND_SHULK {
|
||||||
return buff_shulk(module_accessor, status);
|
return buff_shulk(module_accessor, status);
|
||||||
}
|
}
|
||||||
|
@ -193,27 +194,36 @@ unsafe fn buff_mac(module_accessor: &mut app::BattleObjectModuleAccessor) -> boo
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn buff_sepiroth(
|
unsafe fn buff_sepiroth(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
|
||||||
module_accessor: &mut app::BattleObjectModuleAccessor,
|
if !is_buffing(module_accessor) {
|
||||||
percent: f32,
|
// To ensure Sephiroth gains Wing, we set flags for Sephiroth being in a Stamina Mode Sudden Death match.
|
||||||
) -> bool {
|
// The function that checks whether to start giving Sephiroth Wing every frame also checks for this exact
|
||||||
start_buff(module_accessor);
|
// scenario. We do this because inline hooking it with the current version of skyline crashes the game,
|
||||||
if WorkModule::get_int(
|
// likely due to the hook clobbering some of the floating point registers that we need for later.
|
||||||
module_accessor,
|
WorkModule::on_flag(
|
||||||
*FIGHTER_EDGE_INSTANCE_WORK_ID_INT_ONE_WINGED_WING_STATE,
|
|
||||||
) == 1
|
|
||||||
{
|
|
||||||
// Once we're in wing, heal to correct damage
|
|
||||||
DamageModule::heal(
|
|
||||||
module_accessor,
|
module_accessor,
|
||||||
-1.0 * DamageModule::damage(module_accessor, 0),
|
*FIGHTER_EDGE_INSTANCE_WORK_ID_FLAG_IS_RULE_HP,
|
||||||
0,
|
);
|
||||||
|
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;
|
return true;
|
||||||
} else {
|
|
||||||
// if we're not in wing, add damage
|
|
||||||
DamageModule::add_damage(module_accessor, 1000.0, 0);
|
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
@ -259,29 +269,13 @@ unsafe fn buff_shulk(module_accessor: &mut app::BattleObjectModuleAccessor, stat
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn buff_wiifit(
|
unsafe fn buff_wiifit(module_accessor: &mut app::BattleObjectModuleAccessor, status: i32) -> bool {
|
||||||
module_accessor: &mut app::BattleObjectModuleAccessor,
|
if !is_buffing(module_accessor) {
|
||||||
status: i32,
|
start_buff(module_accessor);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
let prev_status_kind = StatusModule::prev_status_kind(module_accessor, 0);
|
let prev_status_kind = StatusModule::prev_status_kind(module_accessor, 0);
|
||||||
if prev_status_kind == FIGHTER_WIIFIT_STATUS_KIND_SPECIAL_LW_SUCCESS {
|
if prev_status_kind == FIGHTER_WIIFIT_STATUS_KIND_SPECIAL_LW_SUCCESS {
|
||||||
start_buff(module_accessor);
|
return true;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
if status != FIGHTER_WIIFIT_STATUS_KIND_SPECIAL_LW_SUCCESS {
|
if status != FIGHTER_WIIFIT_STATUS_KIND_SPECIAL_LW_SUCCESS {
|
||||||
StatusModule::change_status_force(
|
StatusModule::change_status_force(
|
||||||
|
|
|
@ -622,10 +622,6 @@ unsafe fn get_flag(
|
||||||
) -> i32 {
|
) -> i32 {
|
||||||
// let current_status = StatusModule::prev_status_kind(module_accessor,0);
|
// let current_status = StatusModule::prev_status_kind(module_accessor,0);
|
||||||
let current_status = StatusModule::status_kind(module_accessor);
|
let current_status = StatusModule::status_kind(module_accessor);
|
||||||
println!(
|
|
||||||
"Current Status: {}, Expected Status: {}",
|
|
||||||
current_status, expected_status
|
|
||||||
);
|
|
||||||
if current_status == expected_status {
|
if current_status == expected_status {
|
||||||
// Reset Buffer
|
// Reset Buffer
|
||||||
reset();
|
reset();
|
||||||
|
|
|
@ -120,26 +120,6 @@ fn once_per_frame_per_fighter(
|
||||||
return;
|
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 {
|
unsafe {
|
||||||
if menu::menu_condition(module_accessor) {
|
if menu::menu_condition(module_accessor) {
|
||||||
menu::spawn_menu();
|
menu::spawn_menu();
|
||||||
|
@ -406,6 +386,26 @@ pub unsafe fn handle_check_doyle_summon_dispatch(
|
||||||
ori
|
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
|
// Set Stale Moves to On
|
||||||
static STALE_OFFSET: usize = 0x013e88a4;
|
static STALE_OFFSET: usize = 0x013e88a4;
|
||||||
|
|
||||||
|
@ -691,6 +691,9 @@ pub fn training_mods() {
|
||||||
handle_check_doyle_summon_dispatch,
|
handle_check_doyle_summon_dispatch,
|
||||||
handle_reused_ui,
|
handle_reused_ui,
|
||||||
handle_req_screen,
|
handle_req_screen,
|
||||||
|
handle_add_damage,
|
||||||
|
// Buff SFX
|
||||||
|
handle_fighter_play_se,
|
||||||
// Stale Moves
|
// Stale Moves
|
||||||
stale_handle,
|
stale_handle,
|
||||||
stale_menu_handle,
|
stale_menu_handle,
|
||||||
|
@ -702,8 +705,6 @@ pub fn training_mods() {
|
||||||
handle_star_ko,
|
handle_star_ko,
|
||||||
// Clatter
|
// Clatter
|
||||||
clatter::hook_start_clatter,
|
clatter::hook_start_clatter,
|
||||||
// Buff SFX
|
|
||||||
handle_fighter_play_se,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
combo::init();
|
combo::init();
|
||||||
|
|
|
@ -621,7 +621,7 @@ pub unsafe fn save_states(module_accessor: &mut app::BattleObjectModuleAccessor)
|
||||||
|
|
||||||
if save_state.state == ApplyBuff {
|
if save_state.state == ApplyBuff {
|
||||||
// needs its own save_state.state since this may take multiple frames, want it to loop
|
// 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
|
// returns true when done buffing fighter
|
||||||
buff::restart_buff(module_accessor);
|
buff::restart_buff(module_accessor);
|
||||||
// set is_buffing back to false when done
|
// set is_buffing back to false when done
|
||||||
|
|
Loading…
Add table
Reference in a new issue