mirror of
https://github.com/jugeeya/UltimateTrainingModpack.git
synced 2025-02-17 22:50:32 +00:00
Refactor Mash Module (#101)
* Add Frame Counter Module * Allow Multiple Frame Counters * Apply Frame Counter * Add Enum For Fighter Id * Simplify Calculation * Restore Original Indentation * Add Transition Checks Check if the transition is possible before setting the flag * Add Normal Attacks * Update Mash Recactored attack options Extracted sub functions * Remove deprecated function * Update Mash Module Handle all attack options through the mash module. * Fix Some OOS Options Jump/Aerial/UpB * Update Mash Module Return the flag in get_command_flag so we don't need to borrow a mut Removed transition check for usmash for now * Fix Multi Buffer Fixed buffering more than once per shield interaction * Fix drop shield options Options that require shield drop now work * Use Minimal Checks Commented out unnecessary checks * Fix USmash OOS * Fix Roll/Dodge OOS * Fix Aerials Fixed starting 1 frame late * Fix USmash OOS again * Remove PrintLns * Update TrainingModpackOverlay * Remove unused Methods * Default To FastFall Off * Update Defensive Options Remove Shield Button Checks outside shield module. * Update Defensive Options Now handled through mash buffer * Formatting * Cleanup * Reimplement Random Mash * Add ToDos
This commit is contained in:
parent
63a3358a0f
commit
c6cf52af33
9 changed files with 506 additions and 414 deletions
|
@ -1 +1 @@
|
|||
Subproject commit 88e4eb92387319ad3ceb398364ecb3ab52425e86
|
||||
Subproject commit eff9297a01f3df86d5bc2a0e80d00c537f44e247
|
|
@ -76,6 +76,10 @@ pub enum Attack {
|
|||
DownB = 8,
|
||||
UpSmash = 9,
|
||||
Grab = 10,
|
||||
Jab = 11,
|
||||
Ftilt = 12, // @TODO implement
|
||||
Utilt = 13, // @TODO implement
|
||||
Dtilt = 14, // @TODO implement
|
||||
}
|
||||
|
||||
impl From<i32> for Attack {
|
||||
|
@ -192,6 +196,7 @@ pub enum Mash {
|
|||
RollForward = 5,
|
||||
RollBack = 6,
|
||||
Random = 7,
|
||||
Shield = 99,
|
||||
}
|
||||
|
||||
impl From<i32> for Mash {
|
||||
|
|
|
@ -2,7 +2,6 @@ pub mod consts;
|
|||
|
||||
use crate::common::consts::*;
|
||||
use smash::app::{self, lua_bind::*};
|
||||
use smash::hash40;
|
||||
use smash::lib::lua_const::*;
|
||||
|
||||
pub static mut MENU_STRUCT: consts::TrainingModpackMenu = consts::TrainingModpackMenu {
|
||||
|
@ -17,7 +16,7 @@ pub static mut MENU_STRUCT: consts::TrainingModpackMenu = consts::TrainingModpac
|
|||
defensive_state: Defensive::Random,
|
||||
oos_offset: 0,
|
||||
mash_in_neutral: MashInNeutral::Off,
|
||||
fast_fall: FastFall::On,
|
||||
fast_fall: FastFall::Off,
|
||||
};
|
||||
|
||||
pub static mut MENU: &'static mut consts::TrainingModpackMenu = unsafe { &mut MENU_STRUCT };
|
||||
|
@ -55,12 +54,12 @@ pub unsafe fn is_operation_cpu(module_accessor: &mut app::BattleObjectModuleAcce
|
|||
FighterInformation::is_operation_cpu(fighter_information)
|
||||
}
|
||||
|
||||
pub unsafe fn is_grounded(module_accessor: &mut app::BattleObjectModuleAccessor) ->bool{
|
||||
pub unsafe fn is_grounded(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
|
||||
let situation_kind = StatusModule::situation_kind(module_accessor) as i32;
|
||||
situation_kind == SITUATION_KIND_GROUND
|
||||
}
|
||||
|
||||
pub unsafe fn is_airborne(module_accessor: &mut app::BattleObjectModuleAccessor) ->bool{
|
||||
pub unsafe fn is_airborne(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
|
||||
let situation_kind = StatusModule::situation_kind(module_accessor) as i32;
|
||||
situation_kind == SITUATION_KIND_AIR
|
||||
}
|
||||
|
@ -84,43 +83,3 @@ pub unsafe fn is_in_shieldstun(module_accessor: &mut app::BattleObjectModuleAcce
|
|||
&& status_kind == FIGHTER_STATUS_KIND_GUARD_OFF)
|
||||
}
|
||||
|
||||
pub unsafe fn is_in_landing(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
|
||||
let status_kind = StatusModule::status_kind(module_accessor);
|
||||
(*FIGHTER_STATUS_KIND_LANDING..=*FIGHTER_STATUS_KIND_LANDING_DAMAGE_LIGHT)
|
||||
.contains(&status_kind)
|
||||
}
|
||||
|
||||
pub unsafe fn is_in_footstool(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
|
||||
let status_kind = StatusModule::status_kind(module_accessor);
|
||||
(*FIGHTER_STATUS_KIND_TREAD_DAMAGE..=*FIGHTER_STATUS_KIND_TREAD_FALL).contains(&status_kind)
|
||||
}
|
||||
|
||||
pub unsafe fn perform_defensive_option(
|
||||
_module_accessor: &mut app::BattleObjectModuleAccessor,
|
||||
flag: &mut i32,
|
||||
) {
|
||||
match MENU.defensive_state {
|
||||
Defensive::Random => {
|
||||
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,
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use crate::common::consts::*;
|
||||
use crate::common::*;
|
||||
use crate::training::mash;
|
||||
use smash::app::{self, lua_bind::*};
|
||||
use smash::hash40;
|
||||
use smash::lib::lua_const::*;
|
||||
|
@ -39,75 +40,14 @@ pub unsafe fn force_option(module_accessor: &mut app::BattleObjectModuleAccessor
|
|||
status = new_status;
|
||||
}
|
||||
|
||||
mash::perform_defensive_option();
|
||||
|
||||
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 !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<bool> {
|
||||
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.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(
|
||||
module_accessor: &mut app::BattleObjectModuleAccessor,
|
||||
category: i32,
|
||||
flag: &mut i32,
|
||||
_category: i32,
|
||||
) {
|
||||
if !is_training_mode() {
|
||||
return;
|
||||
|
@ -122,5 +62,4 @@ pub unsafe fn get_command_flag_cat(
|
|||
}
|
||||
|
||||
force_option(module_accessor);
|
||||
defensive_option(module_accessor, category, flag);
|
||||
}
|
||||
|
|
|
@ -5,6 +5,46 @@ use smash::app::{self, lua_bind::*};
|
|||
use smash::hash40;
|
||||
use smash::lib::lua_const::*;
|
||||
|
||||
static mut BUFFERED_ACTION: Mash = Mash::None;
|
||||
static mut BUFFERED_ATTACK: Attack = Attack::Nair;
|
||||
|
||||
pub fn buffer_action(action: Mash) {
|
||||
unsafe {
|
||||
if BUFFERED_ACTION != Mash::None {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
unsafe {
|
||||
BUFFERED_ACTION = action;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_current_buffer() -> Mash {
|
||||
unsafe { BUFFERED_ACTION }
|
||||
}
|
||||
|
||||
pub fn set_attack(attack: Attack) {
|
||||
unsafe {
|
||||
if BUFFERED_ATTACK == attack {
|
||||
return;
|
||||
}
|
||||
}
|
||||
unsafe {
|
||||
BUFFERED_ATTACK = attack;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_current_attack() -> Attack {
|
||||
unsafe { BUFFERED_ATTACK }
|
||||
}
|
||||
|
||||
pub fn reset() {
|
||||
unsafe {
|
||||
BUFFERED_ACTION = Mash::None;
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn get_attack_air_kind(
|
||||
module_accessor: &mut app::BattleObjectModuleAccessor,
|
||||
) -> Option<i32> {
|
||||
|
@ -16,177 +56,296 @@ pub unsafe fn get_attack_air_kind(
|
|||
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;
|
||||
}
|
||||
}
|
||||
BUFFERED_ATTACK.into_attack_air_kind()
|
||||
}
|
||||
|
||||
pub unsafe fn get_command_flag_cat(
|
||||
module_accessor: &mut app::BattleObjectModuleAccessor,
|
||||
category: i32,
|
||||
flag: &mut i32,
|
||||
) {
|
||||
) -> i32 {
|
||||
// Only do once per frame
|
||||
if category != FIGHTER_PAD_COMMAND_CATEGORY1 {
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if !is_training_mode() {
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if !is_operation_cpu(module_accessor) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
check_buffer(module_accessor);
|
||||
|
||||
perform_action(module_accessor)
|
||||
}
|
||||
|
||||
unsafe fn check_buffer(module_accessor: &mut app::BattleObjectModuleAccessor) {
|
||||
if BUFFERED_ACTION != Mash::None {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for OOS delay
|
||||
if is_in_shieldstun(module_accessor) && !shield::allow_oos() {
|
||||
if !is_in_hitstun(module_accessor) && MENU.mash_in_neutral != MashInNeutral::On {
|
||||
return;
|
||||
}
|
||||
|
||||
if !(is_in_hitstun(module_accessor)
|
||||
|| is_in_landing(module_accessor)
|
||||
|| is_in_shieldstun(module_accessor)
|
||||
|| is_in_footstool(module_accessor)
|
||||
|| MENU.mash_in_neutral == MashInNeutral::On
|
||||
|| StatusModule::status_kind(module_accessor) == FIGHTER_STATUS_KIND_CLIFF_ROBBED)
|
||||
{
|
||||
return;
|
||||
let mut action = MENU.mash_state;
|
||||
|
||||
if action == Mash::Random {
|
||||
let mut random_cmds = vec![
|
||||
Mash::Jump,
|
||||
Mash::Attack,
|
||||
];
|
||||
|
||||
if is_airborne(module_accessor){
|
||||
random_cmds.push(Mash::Airdodge);
|
||||
}
|
||||
|
||||
if is_grounded(module_accessor){
|
||||
random_cmds.push(Mash::RollBack);
|
||||
random_cmds.push(Mash::RollForward);
|
||||
random_cmds.push(Mash::Spotdodge);
|
||||
}
|
||||
|
||||
let random_cmd_index =
|
||||
app::sv_math::rand(hash40("fighter"), random_cmds.len() as i32) as usize;
|
||||
|
||||
action = random_cmds[random_cmd_index];
|
||||
}
|
||||
|
||||
match MENU.mash_state {
|
||||
buffer_action(action);
|
||||
set_attack(MENU.mash_attack_state);
|
||||
}
|
||||
|
||||
unsafe fn perform_action(module_accessor: &mut app::BattleObjectModuleAccessor) -> i32 {
|
||||
match BUFFERED_ACTION {
|
||||
Mash::Airdodge => {
|
||||
*flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_AIR_ESCAPE;
|
||||
return get_flag(
|
||||
module_accessor,
|
||||
*FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_ESCAPE_AIR,
|
||||
*FIGHTER_PAD_CMD_CAT1_FLAG_AIR_ESCAPE,
|
||||
);
|
||||
}
|
||||
Mash::Jump => {
|
||||
if !is_in_landing(module_accessor) {
|
||||
*flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_JUMP_BUTTON;
|
||||
}
|
||||
return update_jump_flag(module_accessor);
|
||||
}
|
||||
Mash::Spotdodge => {
|
||||
*flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE;
|
||||
return get_flag(
|
||||
module_accessor,
|
||||
*FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_ESCAPE,
|
||||
*FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE,
|
||||
);
|
||||
}
|
||||
Mash::RollForward => {
|
||||
*flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE_F;
|
||||
return get_flag(
|
||||
module_accessor,
|
||||
*FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_ESCAPE_F,
|
||||
*FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE_F,
|
||||
);
|
||||
}
|
||||
Mash::RollBack => {
|
||||
*flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE_B;
|
||||
return get_flag(
|
||||
module_accessor,
|
||||
*FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_ESCAPE_B,
|
||||
*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 shielding we also need to jump
|
||||
if is_in_shieldstun(module_accessor)
|
||||
|| (is_grounded(module_accessor)
|
||||
&& MENU.mash_in_neutral == MashInNeutral::On)
|
||||
{
|
||||
*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,
|
||||
}
|
||||
return get_attack_flag(module_accessor);
|
||||
}
|
||||
Mash::Random => {
|
||||
let random_commands = get_random_command_list(module_accessor);
|
||||
Mash::Shield => {
|
||||
/*
|
||||
Doesn't actually cause the shield, but will clear the buffer once shield is possible.
|
||||
Shield hold is performed trough shield::should_hold_shield
|
||||
*/
|
||||
return get_flag(
|
||||
module_accessor,
|
||||
*FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_GUARD_ON,
|
||||
*FIGHTER_PAD_CMD_CAT1_FLAG_AIR_ESCAPE,
|
||||
);
|
||||
}
|
||||
_ => return 0,
|
||||
}
|
||||
}
|
||||
|
||||
if random_commands.len() == 0 {
|
||||
return;
|
||||
}
|
||||
unsafe fn update_jump_flag(module_accessor: &mut app::BattleObjectModuleAccessor) -> i32 {
|
||||
let check_flag: i32;
|
||||
|
||||
if is_grounded(module_accessor) {
|
||||
check_flag = *FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_JUMP_SQUAT_BUTTON;
|
||||
} else if is_airborne(module_accessor) {
|
||||
check_flag = *FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_JUMP_AERIAL_BUTTON;
|
||||
} else {
|
||||
check_flag = *FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_CLIFF_JUMP_BUTTON;
|
||||
}
|
||||
|
||||
return get_flag(
|
||||
module_accessor,
|
||||
check_flag,
|
||||
*FIGHTER_PAD_CMD_CAT1_FLAG_JUMP_BUTTON,
|
||||
);
|
||||
}
|
||||
|
||||
unsafe fn get_attack_flag(module_accessor: &mut app::BattleObjectModuleAccessor) -> i32 {
|
||||
use Attack::*;
|
||||
|
||||
let action_flag: i32;
|
||||
let transition_flag: i32;
|
||||
|
||||
match BUFFERED_ATTACK {
|
||||
Nair | Fair | Bair | UpAir | Dair => {
|
||||
return get_aerial_flag(module_accessor, BUFFERED_ATTACK);
|
||||
}
|
||||
NeutralB => {
|
||||
action_flag = *FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_N;
|
||||
transition_flag = *FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_SPECIAL_N;
|
||||
}
|
||||
SideB => {
|
||||
action_flag = *FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_S;
|
||||
transition_flag = *FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_SPECIAL_S;
|
||||
}
|
||||
UpB => {
|
||||
action_flag = *FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_HI;
|
||||
transition_flag = *FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_SPECIAL_HI;
|
||||
}
|
||||
DownB => {
|
||||
action_flag = *FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_LW;
|
||||
transition_flag = *FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_SPECIAL_LW;
|
||||
}
|
||||
UpSmash => {
|
||||
action_flag = *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_HI4;
|
||||
// ATTACK_HI4 transition returns false while in shield
|
||||
// transition_flag = *FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_ATTACK_HI4;
|
||||
transition_flag = *FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_JUMP_SQUAT_BUTTON;
|
||||
}
|
||||
Grab => {
|
||||
action_flag = *FIGHTER_PAD_CMD_CAT1_FLAG_CATCH;
|
||||
transition_flag = *FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_CATCH;
|
||||
}
|
||||
Jab => {
|
||||
action_flag = *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_N;
|
||||
transition_flag = *FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_ATTACK;
|
||||
}
|
||||
_ => return 0,
|
||||
}
|
||||
|
||||
return get_flag(module_accessor, transition_flag, action_flag);
|
||||
}
|
||||
|
||||
unsafe fn get_aerial_flag(
|
||||
module_accessor: &mut app::BattleObjectModuleAccessor,
|
||||
attack: Attack,
|
||||
) -> i32 {
|
||||
let mut flag: i32 = 0;
|
||||
|
||||
let transition_flag: i32;
|
||||
// If we are grounded we also need to jump
|
||||
if is_grounded(module_accessor) {
|
||||
flag += update_jump_flag(module_accessor);
|
||||
|
||||
if flag == 0 {
|
||||
// Can't jump, return
|
||||
return 0;
|
||||
}
|
||||
|
||||
transition_flag = 0;
|
||||
} else {
|
||||
transition_flag = *FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_ATTACK_AIR;
|
||||
}
|
||||
|
||||
let action_flag: i32;
|
||||
|
||||
match attack {
|
||||
Attack::Nair => {
|
||||
action_flag = *FIGHTER_COMMAND_ATTACK_AIR_KIND_N;
|
||||
}
|
||||
Attack::Fair => {
|
||||
// For some reason the game doesn't trigger the fair correctly
|
||||
// action_flag = *FIGHTER_COMMAND_ATTACK_AIR_KIND_F;
|
||||
action_flag = *FIGHTER_COMMAND_ATTACK_AIR_KIND_N;
|
||||
}
|
||||
Attack::Bair => {
|
||||
action_flag = *FIGHTER_COMMAND_ATTACK_AIR_KIND_B;
|
||||
}
|
||||
Attack::UpAir => {
|
||||
// For some reason the game doesn't trigger the uair correctly
|
||||
// action_flag = *FIGHTER_COMMAND_ATTACK_AIR_KIND_HI;
|
||||
action_flag = *FIGHTER_COMMAND_ATTACK_AIR_KIND_N;
|
||||
}
|
||||
Attack::Dair => {
|
||||
action_flag = *FIGHTER_COMMAND_ATTACK_AIR_KIND_LW;
|
||||
}
|
||||
_ => {
|
||||
action_flag = 0;
|
||||
}
|
||||
}
|
||||
|
||||
flag |= get_flag(module_accessor, transition_flag, action_flag);
|
||||
|
||||
flag
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the flag if the transition is valid
|
||||
*
|
||||
*/
|
||||
unsafe fn get_flag(
|
||||
module_accessor: &mut app::BattleObjectModuleAccessor,
|
||||
transition_flag: i32,
|
||||
action_flag: i32,
|
||||
) -> i32 {
|
||||
if transition_flag > 0
|
||||
&& !WorkModule::is_enable_transition_term(module_accessor, transition_flag)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Reset Buffer
|
||||
reset();
|
||||
|
||||
return action_flag;
|
||||
}
|
||||
|
||||
pub unsafe fn perform_defensive_option() {
|
||||
reset();
|
||||
|
||||
let mut shield_suspension_frames = 60;
|
||||
|
||||
match MENU.defensive_state {
|
||||
Defensive::Random => {
|
||||
let random_cmds = vec![
|
||||
Mash::Spotdodge,
|
||||
Mash::RollBack,
|
||||
Mash::RollForward,
|
||||
Mash::Attack,
|
||||
];
|
||||
|
||||
let random_cmd_index =
|
||||
app::sv_math::rand(hash40("fighter"), random_commands.len() as i32) as usize;
|
||||
app::sv_math::rand(hash40("fighter"), random_cmds.len() as i32) as usize;
|
||||
|
||||
*flag |= random_commands[random_cmd_index];
|
||||
buffer_action(random_cmds[random_cmd_index]);
|
||||
set_attack(Attack::Jab);
|
||||
}
|
||||
_ => (),
|
||||
Defensive::Roll => {
|
||||
if app::sv_math::rand(hash40("fighter"), 2) == 0 {
|
||||
buffer_action(Mash::RollForward);
|
||||
} else {
|
||||
buffer_action(Mash::RollBack);
|
||||
}
|
||||
}
|
||||
Defensive::Spotdodge => buffer_action(Mash::Spotdodge),
|
||||
Defensive::Jab => {
|
||||
buffer_action(Mash::Attack);
|
||||
set_attack(Attack::Jab);
|
||||
}
|
||||
Defensive::Shield => {
|
||||
shield_suspension_frames = 0;
|
||||
buffer_action(Mash::Shield);
|
||||
}
|
||||
_ => (shield_suspension_frames = 0),
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn get_random_command_list(
|
||||
module_accessor: &mut app::BattleObjectModuleAccessor,
|
||||
) -> Vec<i32> {
|
||||
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<bool> {
|
||||
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
|
||||
|
||||
// Suspend shield hold to allow for other defensive options
|
||||
shield::suspend_shield(shield_suspension_frames);
|
||||
}
|
||||
|
|
|
@ -64,9 +64,9 @@ pub unsafe fn handle_get_command_flag_cat(
|
|||
// if (replace) return ret;
|
||||
|
||||
shield::get_command_flag_cat(module_accessor);
|
||||
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);
|
||||
flag |= mash::get_command_flag_cat(module_accessor, category);
|
||||
ledge::get_command_flag_cat(module_accessor, category);
|
||||
tech::get_command_flag_cat(module_accessor, category);
|
||||
hitbox_visualizer::get_command_flag_cat(module_accessor, category);
|
||||
fast_fall::get_command_flag_cat(module_accessor, category);
|
||||
|
||||
|
@ -151,14 +151,8 @@ 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))
|
||||
})
|
||||
})
|
||||
})
|
||||
shield::check_button_on(module_accessor, button).unwrap_or_else(
|
||||
|| original!()(module_accessor, button))
|
||||
}
|
||||
|
||||
#[skyline::hook(replace = ControlModule::check_button_off)]
|
||||
|
@ -225,6 +219,7 @@ pub fn training_mods() {
|
|||
);
|
||||
|
||||
combo::init();
|
||||
shield::init();
|
||||
|
||||
// // Input recorder
|
||||
// SaltySD_function_replace_sym(
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use crate::common::*;
|
||||
use crate::training::mash;
|
||||
use smash::app::{self, lua_bind::*};
|
||||
use smash::lib::lua_const::*;
|
||||
use smash::phx::{Hash40, Vector3f};
|
||||
|
@ -99,6 +100,7 @@ pub unsafe fn save_states(module_accessor: &mut app::BattleObjectModuleAccessor,
|
|||
SAVE_STATE_PLAYER_STATE = CameraMove;
|
||||
SAVE_STATE_CPU_STATE = CameraMove;
|
||||
}
|
||||
mash::reset();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
use crate::common::consts::*;
|
||||
use crate::common::*;
|
||||
use crate::hitbox_visualizer;
|
||||
use crate::training::frame_counter;
|
||||
use crate::training::mash;
|
||||
use smash::app;
|
||||
use smash::app::lua_bind::*;
|
||||
use smash::app::sv_system;
|
||||
|
@ -13,6 +16,17 @@ 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;
|
||||
|
||||
static mut FRAME_COUNTER_INDEX: usize = 0;
|
||||
|
||||
// For how many frames should the shield hold be overwritten
|
||||
static mut SHIELD_SUSPEND_FRAMES: u32 = 0;
|
||||
|
||||
pub fn init() {
|
||||
unsafe {
|
||||
FRAME_COUNTER_INDEX = frame_counter::register_counter();
|
||||
}
|
||||
}
|
||||
|
||||
// Toggle for shield decay
|
||||
static mut SHIELD_DECAY: bool = false;
|
||||
|
||||
|
@ -118,37 +132,44 @@ pub unsafe fn get_param_float(
|
|||
}
|
||||
|
||||
pub unsafe fn should_hold_shield(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
|
||||
// Mash shield
|
||||
if mash::get_current_buffer() == Mash::Shield {
|
||||
return true;
|
||||
}
|
||||
|
||||
// We should hold shield if the state requires it
|
||||
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) {
|
||||
if !was_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;
|
||||
}
|
||||
match mash::get_current_buffer() {
|
||||
Mash::Attack => {} // Handle attack below
|
||||
// Mash::RollForward => {return true}
|
||||
// Mash::RollBack => {return true}
|
||||
// If we are not mashing attack then we will always hold shield
|
||||
_ => return true,
|
||||
}
|
||||
|
||||
false
|
||||
// We will hold shield if we are in shieldstun and our attack can be performed OOS
|
||||
match mash::get_current_attack() {
|
||||
// Attack::UpSmash => return true,
|
||||
Attack::Grab => return true,
|
||||
// Attack::UpB => return true,
|
||||
// Attack::Nair => return true,
|
||||
// Attack::Fair => return true,
|
||||
// Attack::UpAir => return true,
|
||||
// Attack::Bair => return true,
|
||||
_ => return false,
|
||||
}
|
||||
}
|
||||
|
||||
#[skyline::hook(replace = smash::lua2cpp::L2CFighterCommon_sub_guard_cont)]
|
||||
|
@ -159,10 +180,11 @@ pub unsafe fn handle_sub_guard_cont(fighter: &mut L2CFighterCommon) -> L2CValue
|
|||
|
||||
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
|
||||
{
|
||||
if !is_training_mode() || !is_operation_cpu(module_accessor) {
|
||||
return;
|
||||
}
|
||||
|
||||
if !was_in_shieldstun(module_accessor) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -174,93 +196,52 @@ unsafe fn mod_handle_sub_guard_cont(fighter: &mut L2CFighterCommon) {
|
|||
return;
|
||||
}
|
||||
|
||||
if MENU.mash_state == Mash::Attack {
|
||||
handle_attack_option(fighter, module_accessor);
|
||||
if !hitbox_visualizer::is_shielding(module_accessor) {
|
||||
return;
|
||||
}
|
||||
|
||||
if WorkModule::is_enable_transition_term(
|
||||
module_accessor,
|
||||
*FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_ESCAPE,
|
||||
) {
|
||||
handle_escape_option(fighter);
|
||||
if handle_escape_option(fighter, module_accessor) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn handle_escape_option(fighter: &mut L2CFighterCommon) {
|
||||
mash::buffer_action(MENU.mash_state);
|
||||
mash::set_attack(MENU.mash_attack_state);
|
||||
|
||||
if needs_oos_handling_drop_shield() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set shield suspension frames
|
||||
match MENU.mash_state {
|
||||
Mash::Spotdodge => {
|
||||
fighter.fighter_base.change_status(
|
||||
FIGHTER_STATUS_KIND_ESCAPE.as_lua_int(),
|
||||
LUA_TRUE,
|
||||
);
|
||||
}
|
||||
Mash::RollForward => {
|
||||
fighter.fighter_base.change_status(
|
||||
FIGHTER_STATUS_KIND_ESCAPE_F.as_lua_int(),
|
||||
LUA_TRUE,
|
||||
);
|
||||
}
|
||||
Mash::RollBack => {
|
||||
fighter.fighter_base.change_status(
|
||||
FIGHTER_STATUS_KIND_ESCAPE_B.as_lua_int(),
|
||||
LUA_TRUE,
|
||||
);
|
||||
}
|
||||
_ => (),
|
||||
Mash::Attack => match MENU.mash_attack_state {
|
||||
Attack::UpSmash => {}
|
||||
Attack::Grab => {}
|
||||
_ => {
|
||||
// Force shield drop
|
||||
suspend_shield(15);
|
||||
}
|
||||
},
|
||||
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
// Needed for shield drop options
|
||||
pub fn suspend_shield(frames: u32) {
|
||||
if frames <= 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
fighter.fighter_base.change_status(
|
||||
FIGHTER_STATUS_KIND_CATCH.as_lua_int(),
|
||||
LUA_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(
|
||||
FIGHTER_STATUS_KIND_SPECIAL_HI.as_lua_int(),
|
||||
LUA_TRUE,
|
||||
);
|
||||
}
|
||||
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(
|
||||
FIGHTER_STATUS_KIND_ATTACK_HI4_START.as_lua_int(),
|
||||
LUA_TRUE,
|
||||
);
|
||||
}
|
||||
_ => (),
|
||||
unsafe {
|
||||
SHIELD_SUSPEND_FRAMES = frames;
|
||||
frame_counter::reset_frame_count(FRAME_COUNTER_INDEX);
|
||||
frame_counter::start_counting(FRAME_COUNTER_INDEX);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is needed to have the CPU put up shield
|
||||
*/
|
||||
pub unsafe fn check_button_on(
|
||||
module_accessor: &mut app::BattleObjectModuleAccessor,
|
||||
button: i32,
|
||||
|
@ -271,16 +252,116 @@ pub unsafe fn check_button_on(
|
|||
Some(true)
|
||||
}
|
||||
|
||||
/**
|
||||
* This is needed to prevent dropping shield immediately
|
||||
*/
|
||||
pub unsafe fn check_button_off(
|
||||
module_accessor: &mut app::BattleObjectModuleAccessor,
|
||||
button: i32,
|
||||
) -> Option<bool> {
|
||||
if should_return_none_in_check_button(module_accessor, button) {
|
||||
if should_return_none_in_check_button(module_accessor, button)
|
||||
|| needs_oos_handling_drop_shield()
|
||||
{
|
||||
return None;
|
||||
}
|
||||
Some(false)
|
||||
}
|
||||
|
||||
/**
|
||||
* Roll/Dodge doesn't work oos the normal way
|
||||
*/
|
||||
unsafe fn handle_escape_option(
|
||||
fighter: &mut L2CFighterCommon,
|
||||
module_accessor: &mut app::BattleObjectModuleAccessor,
|
||||
) -> bool {
|
||||
if !WorkModule::is_enable_transition_term(
|
||||
module_accessor,
|
||||
*FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_ESCAPE,
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
match MENU.mash_state {
|
||||
Mash::Spotdodge => {
|
||||
fighter
|
||||
.fighter_base
|
||||
.change_status(FIGHTER_STATUS_KIND_ESCAPE.as_lua_int(), LUA_TRUE);
|
||||
return true;
|
||||
}
|
||||
Mash::RollForward => {
|
||||
fighter
|
||||
.fighter_base
|
||||
.change_status(FIGHTER_STATUS_KIND_ESCAPE_F.as_lua_int(), LUA_TRUE);
|
||||
return true;
|
||||
}
|
||||
Mash::RollBack => {
|
||||
fighter
|
||||
.fighter_base
|
||||
.change_status(FIGHTER_STATUS_KIND_ESCAPE_B.as_lua_int(), LUA_TRUE);
|
||||
return true;
|
||||
}
|
||||
_ => return false,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Needed to allow these attacks to work OOS
|
||||
*/
|
||||
fn needs_oos_handling_drop_shield() -> bool {
|
||||
match mash::get_current_buffer() {
|
||||
Mash::Jump => return true,
|
||||
Mash::Attack => {
|
||||
let attack = mash::get_current_attack();
|
||||
if is_aerial(attack) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if attack == Attack::UpB {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
_ => {},
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
fn is_aerial(attack: Attack) -> bool {
|
||||
match attack {
|
||||
Attack::Nair => return true,
|
||||
Attack::Fair => return true,
|
||||
Attack::Bair => return true,
|
||||
Attack::UpAir => return true,
|
||||
Attack::Dair => return true,
|
||||
_ => return false,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Needed for these options to work OOS
|
||||
*/
|
||||
unsafe fn shield_is_suspended() -> bool {
|
||||
// Normal behavior when not mashing
|
||||
if SHIELD_SUSPEND_FRAMES == 0 {
|
||||
return false;
|
||||
}
|
||||
|
||||
let resume_normal_behavior =
|
||||
frame_counter::get_frame_count(FRAME_COUNTER_INDEX) > SHIELD_SUSPEND_FRAMES;
|
||||
|
||||
if resume_normal_behavior {
|
||||
SHIELD_SUSPEND_FRAMES = 0;
|
||||
frame_counter::stop_counting(FRAME_COUNTER_INDEX);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
/**
|
||||
* AKA should the cpu hold the shield button
|
||||
*/
|
||||
unsafe fn should_return_none_in_check_button(
|
||||
module_accessor: &mut app::BattleObjectModuleAccessor,
|
||||
button: i32,
|
||||
|
@ -301,5 +382,15 @@ unsafe fn should_return_none_in_check_button(
|
|||
return true;
|
||||
}
|
||||
|
||||
if shield_is_suspended() {
|
||||
return true;
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
fn was_in_shieldstun(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
|
||||
unsafe {
|
||||
StatusModule::prev_status_kind(module_accessor, 0) == FIGHTER_STATUS_KIND_GUARD_DAMAGE
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use crate::common::consts::*;
|
||||
use crate::common::*;
|
||||
use crate::training::mash;
|
||||
use smash::app::sv_system;
|
||||
use smash::app::{self, lua_bind::*};
|
||||
use smash::hash40;
|
||||
|
@ -76,6 +77,8 @@ unsafe fn mod_handle_change_status(
|
|||
_ => (),
|
||||
}
|
||||
|
||||
mash::perform_defensive_option();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -98,36 +101,9 @@ unsafe fn mod_handle_change_status(
|
|||
}
|
||||
}
|
||||
|
||||
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,
|
||||
) || MotionModule::is_end(module_accessor)
|
||||
|| CancelModule::is_enable_cancel(module_accessor))
|
||||
}
|
||||
|
||||
pub unsafe fn get_command_flag_cat(
|
||||
module_accessor: &mut app::BattleObjectModuleAccessor,
|
||||
_category: i32,
|
||||
flag: &mut i32,
|
||||
) {
|
||||
if !is_training_mode() {
|
||||
return;
|
||||
|
@ -150,9 +126,9 @@ pub unsafe fn get_command_flag_cat(
|
|||
.contains(&status)
|
||||
{
|
||||
let random_statuses = vec![
|
||||
*FIGHTER_STATUS_KIND_DOWN_STAND,
|
||||
*FIGHTER_STATUS_KIND_DOWN_STAND_FB,
|
||||
*FIGHTER_STATUS_KIND_DOWN_STAND_ATTACK,
|
||||
*FIGHTER_STATUS_KIND_DOWN_STAND, // Normal Getup
|
||||
*FIGHTER_STATUS_KIND_DOWN_STAND_FB, // Getup Roll
|
||||
*FIGHTER_STATUS_KIND_DOWN_STAND_ATTACK, // Getup Attack
|
||||
];
|
||||
|
||||
let random_status_index =
|
||||
|
@ -164,42 +140,8 @@ pub unsafe fn get_command_flag_cat(
|
|||
);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn check_button_on(
|
||||
module_accessor: &mut app::BattleObjectModuleAccessor,
|
||||
button: i32,
|
||||
) -> Option<bool> {
|
||||
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.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,
|
||||
|
|
Loading…
Reference in a new issue