1
0
Fork 0
mirror of https://github.com/jugeeya/UltimateTrainingModpack.git synced 2025-03-14 02:16:10 +00:00

Calculate Frame Advantage (#85)

* initial attempt

* frame adv correct calculation

* add to menu

* add menu support

* changed menu return button combo
This commit is contained in:
jugeeya 2020-06-15 23:13:03 -07:00 committed by GitHub
parent 2b2a2eb440
commit 79a84fba3a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 130 additions and 7 deletions

@ -1 +1 @@
Subproject commit 5ff4c5f02b77d21a49927bae629fc97f1bd0d318
Subproject commit deb973c588f8c9f285ae11ded7437c8967f23591

View file

@ -268,5 +268,5 @@ pub struct TrainingModpackMenu {
pub shield_state: Shield,
pub defensive_state: Defensive,
pub oos_offset: i32,
pub mash_in_neutral: MashInNeutral,
pub mash_in_neutral: MashInNeutral
}

View file

@ -16,10 +16,12 @@ pub static mut MENU_STRUCT: consts::TrainingModpackMenu = consts::TrainingModpac
shield_state: Shield::None,
defensive_state: Defensive::Random,
oos_offset: 0,
mash_in_neutral: MashInNeutral::Off,
mash_in_neutral: MashInNeutral::Off
};
pub static MENU: &'static mut consts::TrainingModpackMenu = unsafe { &mut MENU_STRUCT };
pub static mut FRAME_ADVANTAGE: i32 = 0;
pub static mut MENU: &'static mut consts::TrainingModpackMenu = unsafe { &mut MENU_STRUCT };
pub static mut FIGHTER_MANAGER_ADDR: usize = 0;

View file

@ -38,7 +38,7 @@ pub fn main() {
nro::add_hook(nro_main).unwrap();
unsafe {
let buffer = format!("{:x}", MENU as *const _ as u64);
let mut buffer = format!("{:x}", MENU as *const _ as u64);
println!(
"[Training Modpack] Writing training_modpack.log with {}...",
buffer
@ -49,7 +49,7 @@ pub fn main() {
remove(c_str!("sd:/TrainingModpack/training_modpack.conf"));
}
let f = fopen(
let mut f = fopen(
c_str!("sd:/TrainingModpack/training_modpack.log"),
c_str!("w"),
);
@ -58,5 +58,21 @@ pub fn main() {
fwrite(c_str!(buffer) as *const c_void, 1, buffer.len(), f);
fclose(f);
}
buffer = format!("{:x}", &FRAME_ADVANTAGE as *const _ as u64);
println!(
"[Training Modpack] Writing training_modpack_frame_adv.log with {}...",
buffer
);
f = fopen(
c_str!("sd:/TrainingModpack/training_modpack_frame_adv.log"),
c_str!("w"),
);
if !f.is_null() {
fwrite(c_str!(buffer) as *const c_void, 1, buffer.len(), f);
fclose(f);
}
}
}

View file

@ -2,6 +2,8 @@ use crate::common::FIGHTER_MANAGER_ADDR;
use crate::hitbox_visualizer;
use skyline::nn::ro::LookupSymbol;
use smash::app::{self, lua_bind::*};
use smash::lib::{lua_const::*};
use crate::common::*;
pub mod directional_influence;
pub mod shield;
@ -33,6 +35,49 @@ pub unsafe fn handle_get_attack_air_kind(
mash::get_attack_air_kind(module_accessor).unwrap_or_else(|| original!()(module_accessor))
}
static mut FRAME_COUNTER : u64 = 0;
static mut PLAYER_ACTIONABLE : bool = false;
static mut CPU_ACTIONABLE : bool = false;
static mut PLAYER_ACTIVE_FRAME : u64 = 0;
static mut CPU_ACTIVE_FRAME : u64 = 0;
static mut FRAME_ADVANTAGE_CHECK : bool = false;
pub unsafe fn was_in_hitstun(module_accessor: *mut app::BattleObjectModuleAccessor) -> bool {
let prev_status = StatusModule::prev_status_kind(module_accessor, 0);
(*FIGHTER_STATUS_KIND_DAMAGE..=*FIGHTER_STATUS_KIND_DAMAGE_FALL).contains(&prev_status)
}
pub unsafe fn was_in_shieldstun(module_accessor: *mut app::BattleObjectModuleAccessor) -> bool {
let prev_status = StatusModule::prev_status_kind(module_accessor, 0);
prev_status == FIGHTER_STATUS_KIND_GUARD_DAMAGE
}
pub unsafe fn get_module_accessor(entry_id_int: i32) -> *mut app::BattleObjectModuleAccessor {
let entry_id = app::FighterEntryID(entry_id_int);
let mgr = *(FIGHTER_MANAGER_ADDR as *mut *mut app::FighterManager);
let fighter_entry =
FighterManager::get_fighter_entry(mgr, entry_id) as *mut app::FighterEntry;
let current_fighter_id = FighterEntry::current_fighter_id(fighter_entry);
app::sv_battle_object::module_accessor(current_fighter_id as u32)
}
pub unsafe fn is_actionable(module_accessor: *mut app::BattleObjectModuleAccessor) -> bool {
WorkModule::is_enable_transition_term(
module_accessor,
*FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_ESCAPE_AIR) ||
WorkModule::is_enable_transition_term(
module_accessor,
*FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_ATTACK_AIR) ||
WorkModule::is_enable_transition_term(
module_accessor,
*FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_GUARD_ON) ||
WorkModule::is_enable_transition_term(
module_accessor,
*FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_ESCAPE) ||
CancelModule::is_enable_cancel(module_accessor)
}
#[skyline::hook(replace = ControlModule::get_command_flag_cat)]
pub unsafe fn handle_get_command_flag_cat(
module_accessor: &mut app::BattleObjectModuleAccessor,
@ -42,6 +87,63 @@ pub unsafe fn handle_get_command_flag_cat(
let mut flag = original!()(module_accessor, category);
if is_training_mode() {
if category == 0 {
let entry_id_int =
WorkModule::get_int(module_accessor, *FIGHTER_INSTANCE_WORK_ID_INT_ENTRY_ID) as i32;
// do only once.
if entry_id_int == 0 {
let player_module_accessor = get_module_accessor(0);
let cpu_module_accessor = get_module_accessor(1);
// Use to factor in that we should only update frame advantage if
// there's been a hit that connects
// if AttackModule::is_infliction(
// player_module_accessor,
// *COLLISION_KIND_MASK_HIT | *COLLISION_KIND_MASK_SHIELD) {
// }
// the frame the fighter *becomes* actionable
if !CPU_ACTIONABLE && is_actionable(cpu_module_accessor) {
CPU_ACTIVE_FRAME = FRAME_COUNTER;
}
if !PLAYER_ACTIONABLE && is_actionable(player_module_accessor) {
PLAYER_ACTIVE_FRAME = FRAME_COUNTER;
}
CPU_ACTIONABLE = is_actionable(cpu_module_accessor);
PLAYER_ACTIONABLE = is_actionable(player_module_accessor);
// if neither are active
if !CPU_ACTIONABLE && !PLAYER_ACTIONABLE {
FRAME_ADVANTAGE_CHECK = true;
}
// if both are now active
if PLAYER_ACTIONABLE && CPU_ACTIONABLE {
if FRAME_ADVANTAGE_CHECK {
if was_in_hitstun(cpu_module_accessor) || was_in_shieldstun(cpu_module_accessor) {
let frame_advantage : i64;
if PLAYER_ACTIVE_FRAME > CPU_ACTIVE_FRAME {
frame_advantage = (PLAYER_ACTIVE_FRAME - CPU_ACTIVE_FRAME) as i64 * -1;
} else {
frame_advantage = (CPU_ACTIVE_FRAME - PLAYER_ACTIVE_FRAME) as i64;
}
FRAME_ADVANTAGE = frame_advantage as i32;
}
FRAME_ADVANTAGE_CHECK = false;
}
}
FRAME_COUNTER += 1;
}
}
}
// bool replace;
// int ret = InputRecorder::get_command_flag_cat(module_accessor, category, flag, replace);
// if (replace) return ret;

View file

@ -69,6 +69,9 @@ pub unsafe fn save_states(module_accessor: &mut app::BattleObjectModuleAccessor)
// move to camera bounds
if *save_state == CameraMove {
let mgr = *(FIGHTER_MANAGER_ADDR as *mut *mut app::FighterManager);
FighterManager::reset_fighter(mgr, false);
*save_state = PosMove;
let left_right = (PostureModule::pos_x(module_accessor) > 0.0) as i32 as f32

View file

@ -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: i32 = MENU.oos_offset;
static mut MULTI_HIT_OFFSET: i32 = unsafe { MENU.oos_offset };
// Used to only decrease once per shieldstun change
static mut WAS_IN_SHIELDSTUN: bool = false;