From 0fc8fdf999366977a4dfae92ea690ad4ff43f81a Mon Sep 17 00:00:00 2001
From: sidschingis <SijingYou92@gmail.com>
Date: Sun, 5 Jul 2020 22:13:54 +0200
Subject: [PATCH] Followups (#108)

* Fix Late Mash

Fixed being a frame late
Flag is now immediately returned until the action is performed

Also restore Airdodge =>  Shield when grounded behavior

* Update TrainingModpackOverlay

* Add Follow Ups WIP

Attack followups will currently overwrite the aerial toggle

* Simplify Shield

Extra attack handling is no longer needed

* Apply Action Enum

Replacing Mash

* Fix Random OOS

* Implement Queued Mashes

* Update Shield Suspension

Removed need for frame counter.
Update shield suspension when the mash buffer is updated.

Fixes follow ups oos

* Cleanup

* Cleanup

* Update Aerial Flags

* Fix Aerial Flag

* Fix Copy Paste Error

* Use Mash Toggles For Ledge Jump

Moved menu logic to buffer_menu_mash
---
 TrainingModpackOverlay |   2 +-
 src/common/consts.rs   |  95 +++++++++++++++---
 src/common/mod.rs      |   1 +
 src/training/ledge.rs  |   7 +-
 src/training/mash.rs   | 221 +++++++++++++++++++++++++----------------
 src/training/shield.rs | 157 +++++++++++------------------
 6 files changed, 283 insertions(+), 200 deletions(-)

diff --git a/TrainingModpackOverlay b/TrainingModpackOverlay
index 4393224..1bede8c 160000
--- a/TrainingModpackOverlay
+++ b/TrainingModpackOverlay
@@ -1 +1 @@
-Subproject commit 4393224a14cf6cca1cd1ff7f4e8517ca58071505
+Subproject commit 1bede8c899d015e8cad641926680c2da385fd5dd
diff --git a/src/common/consts.rs b/src/common/consts.rs
index 7182fb8..6569593 100644
--- a/src/common/consts.rs
+++ b/src/common/consts.rs
@@ -112,21 +112,6 @@ impl From<i32> for Attack {
     }
 }
 
-impl Attack {
-    pub fn into_attack_air_kind(&self) -> Option<i32> {
-        use Attack::*;
-
-        Some(match self {
-            Nair => *FIGHTER_COMMAND_ATTACK_AIR_KIND_N,
-            Fair => *FIGHTER_COMMAND_ATTACK_AIR_KIND_F,
-            Bair => *FIGHTER_COMMAND_ATTACK_AIR_KIND_B,
-            Dair => *FIGHTER_COMMAND_ATTACK_AIR_KIND_LW,
-            UpAir => *FIGHTER_COMMAND_ATTACK_AIR_KIND_HI,
-            _ => return None,
-        })
-    }
-}
-
 // Ledge Option
 #[repr(i32)]
 #[derive(Debug, Copy, Clone, PartialEq)]
@@ -268,12 +253,92 @@ pub enum OnOff {
     On = 1,
 }
 
+#[repr(i32)]
+#[derive(Debug, Clone, Copy, PartialEq)]
+pub enum Action {
+    Nothing = 0,
+    Airdodge = 1,
+    Jump = 2,
+    Spotdodge = 3,
+    RollForward = 4,
+    RollBack = 5,
+    Nair = 6,
+    Fair = 7,
+    Bair = 8,
+    UpAir = 9,
+    Dair = 10,
+    NeutralB = 11,
+    SideB = 12,
+    UpB = 13,
+    DownB = 14,
+    UpSmash = 15,
+    FSmash = 16,
+    DSmash = 17,
+    Grab = 18,
+    Jab = 19,
+    Ftilt = 20,
+    Utilt = 21,
+    Dtilt = 22,
+    Shield = 99,
+}
+
+impl Action {
+    pub fn into_attack_air_kind(&self) -> Option<i32> {
+        use Action::*;
+
+        Some(match self {
+            Nair => *FIGHTER_COMMAND_ATTACK_AIR_KIND_N,
+            Fair => *FIGHTER_COMMAND_ATTACK_AIR_KIND_F,
+            Bair => *FIGHTER_COMMAND_ATTACK_AIR_KIND_B,
+            Dair => *FIGHTER_COMMAND_ATTACK_AIR_KIND_LW,
+            UpAir => *FIGHTER_COMMAND_ATTACK_AIR_KIND_HI,
+            _ => return None,
+        })
+    }
+}
+
+// To satisfy the unused warning
+impl From<i32> for Action {
+    fn from(x: i32) -> Self {
+        use Action::*;
+
+        match x {
+            0 => Nothing,
+            1 => Airdodge,
+            2 => Jump,
+            3 => Spotdodge,
+            4 => RollForward,
+            5 => RollBack,
+            6 => Nair,
+            7 => Fair,
+            8 => Bair,
+            9 => UpAir,
+            10 => Dair,
+            11 => NeutralB,
+            12 => SideB,
+            13 => UpB,
+            14 => DownB,
+            15 => UpSmash,
+            16 => FSmash,
+            17 => DSmash,
+            18 => Grab,
+            19 => Jab,
+            20 => Ftilt,
+            21 => Utilt,
+            22 => Dtilt,
+            99 => Action::Shield,
+            _ => Nothing,
+        }
+    }
+}
+
 #[repr(C)]
 pub struct TrainingModpackMenu {
     pub hitbox_vis: HitboxVisualization,
     pub di_state: Direction,
     pub left_stick: Direction, // Currently only used for air dodge direction
     pub mash_attack_state: Attack,
+    pub follow_up: Action,
     pub ledge_state: LedgeOption,
     pub tech_state: TechOption,
     pub mash_state: Mash,
diff --git a/src/common/mod.rs b/src/common/mod.rs
index ed345c7..60b5aa7 100644
--- a/src/common/mod.rs
+++ b/src/common/mod.rs
@@ -9,6 +9,7 @@ pub static mut MENU_STRUCT: consts::TrainingModpackMenu = consts::TrainingModpac
     di_state: Direction::None,
     left_stick: Direction::None,
     mash_attack_state: Attack::Nair,
+    follow_up: Action::Nothing,
     ledge_state: LedgeOption::Random,
     tech_state: TechOption::Random,
     mash_state: Mash::None,
diff --git a/src/training/ledge.rs b/src/training/ledge.rs
index 360f659..0879afe 100644
--- a/src/training/ledge.rs
+++ b/src/training/ledge.rs
@@ -40,7 +40,12 @@ pub unsafe fn force_option(module_accessor: &mut app::BattleObjectModuleAccessor
         status = new_status;
     }
 
-    mash::perform_defensive_option();
+    match ledge_case {
+        LedgeOption::Jump => {
+            mash::buffer_menu_mash(module_accessor);
+        }
+        _ => mash::perform_defensive_option(),
+    }
 
     StatusModule::change_status_request_from_script(module_accessor, status, true);
 }
diff --git a/src/training/mash.rs b/src/training/mash.rs
index 2bd876d..dc7547c 100644
--- a/src/training/mash.rs
+++ b/src/training/mash.rs
@@ -6,43 +6,60 @@ 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;
+static mut CURRENT_AERIAL: Action = Action::Nair;
+static mut QUEUE: Vec<Action> = vec![];
 
-pub fn buffer_action(action: Mash) {
+pub fn buffer_action(action: Action) {
     unsafe {
-        if BUFFERED_ACTION != Mash::None {
+        if QUEUE.len() > 0 {
             return;
         }
     }
 
     unsafe {
-        BUFFERED_ACTION = action;
+        QUEUE.insert(0, action);
+        buffer_follow_up();
     }
 }
 
-pub fn get_current_buffer() -> Mash {
-    unsafe { BUFFERED_ACTION }
-}
+pub fn buffer_follow_up() {
+    let action;
 
-pub fn set_attack(attack: Attack) {
     unsafe {
-        if BUFFERED_ATTACK == attack {
-            return;
-        }
+        action = MENU.follow_up;
     }
+
+    if action == Action::Nothing {
+        return;
+    }
+
     unsafe {
-        BUFFERED_ATTACK = attack;
+        QUEUE.insert(0, action);
     }
 }
 
-pub fn get_current_attack() -> Attack {
-    unsafe { BUFFERED_ATTACK }
+pub fn get_current_buffer() -> Action {
+    unsafe {
+        let current = QUEUE.last().unwrap_or(&Action::Nothing);
+        *current
+    }
 }
 
 pub fn reset() {
     unsafe {
-        BUFFERED_ACTION = Mash::None;
+        QUEUE.pop();
+    }
+
+    shield::suspend_shield(get_current_buffer());
+}
+
+pub fn set_aerial(attack: Action) {
+    if !shield::is_aerial(attack) {
+        return;
+    }
+
+    unsafe {
+        CURRENT_AERIAL = attack;
     }
 }
 
@@ -57,7 +74,7 @@ pub unsafe fn get_attack_air_kind(
         return None;
     }
 
-    BUFFERED_ATTACK.into_attack_air_kind()
+    CURRENT_AERIAL.into_attack_air_kind()
 }
 
 pub unsafe fn get_command_flag_cat(
@@ -83,7 +100,7 @@ pub unsafe fn get_command_flag_cat(
 }
 
 unsafe fn check_buffer(module_accessor: &mut app::BattleObjectModuleAccessor) {
-    if BUFFERED_ACTION != Mash::None {
+    if QUEUE.len() > 0 {
         return;
     }
 
@@ -91,11 +108,41 @@ unsafe fn check_buffer(module_accessor: &mut app::BattleObjectModuleAccessor) {
         return;
     }
 
-    let mut action = MENU.mash_state;
+    buffer_menu_mash(module_accessor);
+}
 
-    if action == Mash::Random {
-        let mut random_cmds = vec![Mash::Jump, Mash::Attack];
+// Temp Translation
+pub fn buffer_menu_mash(module_accessor: &mut app::BattleObjectModuleAccessor) -> Action {
+    unsafe {
+        let action;
+        if MENU.mash_state == Mash::Random {
+            action = get_random_action(module_accessor);
+        } else {
+            action = mash_to_action(MENU.mash_state);
+        }
+        buffer_action(action);
 
+        action
+    }
+}
+
+pub fn mash_to_action(mash: Mash) -> Action {
+    use Action::*;
+    match mash {
+        Mash::Airdodge => Airdodge,
+        Mash::Jump => Jump,
+        Mash::Spotdodge => Spotdodge,
+        Mash::RollForward => RollForward,
+        Mash::RollBack => RollBack,
+        Mash::Shield => Shield,
+        Mash::Attack => unsafe { attack_to_action(MENU.mash_attack_state) },
+        _ => Nothing,
+    }
+}
+
+fn get_random_action(module_accessor: &mut app::BattleObjectModuleAccessor) -> Action {
+    let mut random_cmds = vec![Mash::Jump, Mash::Attack];
+    unsafe {
         if is_airborne(module_accessor) {
             random_cmds.push(Mash::Airdodge);
         }
@@ -109,20 +156,45 @@ unsafe fn check_buffer(module_accessor: &mut app::BattleObjectModuleAccessor) {
         let random_cmd_index =
             app::sv_math::rand(hash40("fighter"), random_cmds.len() as i32) as usize;
 
-        action = random_cmds[random_cmd_index];
+        mash_to_action(random_cmds[random_cmd_index])
     }
+}
 
-    buffer_action(action);
-    set_attack(MENU.mash_attack_state);
+fn attack_to_action(attack: Attack) -> Action {
+    use Action::*;
+    match attack {
+        Attack::Nair => Nair,
+        Attack::Fair => Fair,
+        Attack::Bair => Bair,
+        Attack::UpAir => UpAir,
+        Attack::Dair => Dair,
+        Attack::NeutralB => NeutralB,
+        Attack::SideB => SideB,
+        Attack::UpB => UpB,
+        Attack::DownB => DownB,
+        Attack::UpSmash => UpSmash,
+        Attack::FSmash => FSmash,
+        Attack::DSmash => DSmash,
+        Attack::Grab => Grab,
+        Attack::Jab => Jab,
+        Attack::Ftilt => Ftilt,
+        Attack::Utilt => Utilt,
+        Attack::Dtilt => Dtilt,
+        Attack::Nothing => Nothing,
+    }
 }
 
 unsafe fn perform_action(module_accessor: &mut app::BattleObjectModuleAccessor) -> i32 {
-    match BUFFERED_ACTION {
-        Mash::Airdodge => {
+    use Action::*;
+
+    let action = get_current_buffer();
+
+    match action {
+        Airdodge => {
             // Shield if grounded instead
             if is_grounded(module_accessor) {
                 reset();
-                buffer_action(Mash::Shield);
+                buffer_action(Shield);
                 return 0;
             }
 
@@ -132,50 +204,42 @@ unsafe fn perform_action(module_accessor: &mut app::BattleObjectModuleAccessor)
                 *FIGHTER_PAD_CMD_CAT1_FLAG_AIR_ESCAPE,
             );
         }
-        Mash::Jump => {
+        Jump => {
             return update_jump_flag(module_accessor);
         }
-        Mash::Spotdodge => {
+        Spotdodge => {
             return get_flag(
                 module_accessor,
                 *FIGHTER_STATUS_KIND_ESCAPE,
                 *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE,
             );
         }
-        Mash::RollForward => {
+        RollForward => {
             return get_flag(
                 module_accessor,
                 *FIGHTER_STATUS_KIND_ESCAPE_F,
                 *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE_F,
             );
         }
-        Mash::RollBack => {
+        RollBack => {
             return get_flag(
                 module_accessor,
                 *FIGHTER_STATUS_KIND_ESCAPE_B,
                 *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE_B,
             );
         }
-        Mash::Attack => {
-            return get_attack_flag(module_accessor);
-        }
-        Mash::Shield => {
+        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_KIND_GUARD_ON,
-            //     *FIGHTER_PAD_CMD_CAT1_FLAG_AIR_ESCAPE,
-            // );
             return get_flag(
                 module_accessor,
                 *FIGHTER_STATUS_KIND_GUARD_ON,
                 *FIGHTER_PAD_CMD_CAT1_FLAG_AIR_ESCAPE,
             );
         }
-        _ => return 0,
+        _ => return get_attack_flag(module_accessor, action),
     }
 }
 
@@ -197,15 +261,18 @@ unsafe fn update_jump_flag(module_accessor: &mut app::BattleObjectModuleAccessor
     );
 }
 
-unsafe fn get_attack_flag(module_accessor: &mut app::BattleObjectModuleAccessor) -> i32 {
-    use Attack::*;
+unsafe fn get_attack_flag(
+    module_accessor: &mut app::BattleObjectModuleAccessor,
+    action: Action,
+) -> i32 {
+    use Action::*;
 
     let action_flag: i32;
     let status: i32;
 
-    match BUFFERED_ATTACK {
+    match action {
         Nair | Fair | Bair | UpAir | Dair => {
-            return get_aerial_flag(module_accessor, BUFFERED_ATTACK);
+            return get_aerial_flag(module_accessor, action);
         }
         NeutralB => {
             action_flag = *FIGHTER_PAD_CMD_CAT1_FLAG_SPECIAL_N;
@@ -268,22 +335,16 @@ unsafe fn get_attack_flag(module_accessor: &mut app::BattleObjectModuleAccessor)
 
 unsafe fn get_aerial_flag(
     module_accessor: &mut app::BattleObjectModuleAccessor,
-    attack: Attack,
+    action: Action,
 ) -> i32 {
     let mut flag: i32 = 0;
 
     // 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;
-        }
+        flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_JUMP_BUTTON;
 
         // Delay attack until we are airborne to get a full hop
         if MENU.full_hop == OnOff::On {
-            buffer_action(Mash::Attack);
             return flag;
         }
     }
@@ -291,38 +352,27 @@ unsafe fn get_aerial_flag(
     let status = *FIGHTER_STATUS_KIND_ATTACK_AIR;
 
     if MENU.falling_aerials == OnOff::On && !fast_fall::is_falling(module_accessor) {
-        // Keep Buffering until we are falling
-        buffer_action(Mash::Attack);
         return flag;
     }
 
     let action_flag: i32;
+    use Action::*;
 
-    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;
+    /*
+     * We always trigger attack and change it later into the correct aerial
+     * @see get_attack_air_kind()
+     */
+    match action {
+        Nair | Fair | Bair | UpAir | Dair => {
+            action_flag = *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_N;
         }
         _ => {
             action_flag = 0;
         }
     }
 
+    set_aerial(action);
+
     flag |= get_flag(module_accessor, status, action_flag);
 
     flag
@@ -347,7 +397,7 @@ unsafe fn get_flag(
 pub unsafe fn perform_defensive_option() {
     reset();
 
-    let mut shield_suspension_frames = 60;
+    let action;
 
     match MENU.defensive_state {
         Defensive::Random => {
@@ -361,28 +411,27 @@ pub unsafe fn perform_defensive_option() {
             let random_cmd_index =
                 app::sv_math::rand(hash40("fighter"), random_cmds.len() as i32) as usize;
 
-            buffer_action(random_cmds[random_cmd_index]);
-            set_attack(Attack::Jab);
+            action = mash_to_action(random_cmds[random_cmd_index]);
         }
         Defensive::Roll => {
             if app::sv_math::rand(hash40("fighter"), 2) == 0 {
-                buffer_action(Mash::RollForward);
+                action = Action::RollForward;
             } else {
-                buffer_action(Mash::RollBack);
+                action = Action::RollBack;
             }
         }
-        Defensive::Spotdodge => buffer_action(Mash::Spotdodge),
+        Defensive::Spotdodge => action = Action::Spotdodge,
         Defensive::Jab => {
-            buffer_action(Mash::Attack);
-            set_attack(Attack::Jab);
+            action = Action::Jab;
         }
         Defensive::Shield => {
-            shield_suspension_frames = 0;
-            buffer_action(Mash::Shield);
+            action = Action::Shield;
         }
-        _ => (shield_suspension_frames = 0),
+        _ => return,
     }
 
+    buffer_action(action);
+
     // Suspend shield hold to allow for other defensive options
-    shield::suspend_shield(shield_suspension_frames);
+    shield::suspend_shield(action);
 }
diff --git a/src/training/shield.rs b/src/training/shield.rs
index 27c25c9..2bdee2e 100644
--- a/src/training/shield.rs
+++ b/src/training/shield.rs
@@ -15,15 +15,13 @@ static mut MULTI_HIT_OFFSET: u32 = 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;
 static mut REACTION_INDEX: usize = 0;
 
 // For how many frames should the shield hold be overwritten
-static mut SHIELD_SUSPEND_FRAMES: u32 = 0;
+static mut SUSPEND_SHIELD: bool = false;
 
 pub fn init() {
     unsafe {
-        FRAME_COUNTER_INDEX = frame_counter::register_counter();
         REACTION_INDEX = frame_counter::register_counter();
     }
 }
@@ -132,37 +130,23 @@ pub unsafe fn get_param_float(
     None
 }
 
-pub unsafe fn should_hold_shield(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
+pub fn should_hold_shield() -> bool {
     // Mash shield
-    if mash::get_current_buffer() == Mash::Shield {
+    if mash::get_current_buffer() == Action::Shield {
         return true;
     }
 
+    let shield_state;
+    unsafe {
+        shield_state = &MENU.shield_state;
+    }
+
     // We should hold shield if the state requires it
-    if ![Shield::Hold, Shield::Infinite].contains(&MENU.shield_state) {
+    if ![Shield::Hold, Shield::Infinite].contains(shield_state) {
         return false;
     }
 
-    // Hold shield while OOS is not allowed
-    if !allow_oos() {
-        return true;
-    }
-
-    if !was_in_shieldstun(module_accessor) {
-        return true;
-    }
-
-    match mash::get_current_buffer() {
-        Mash::Attack => {} // Handle attack below
-        // If we are not mashing attack then we will always hold shield
-        _ => return true,
-    }
-
-    // We will hold shield if we are in shieldstun and our attack can be performed OOS
-    match mash::get_current_attack() {
-        Attack::Grab => return true, // Grab has 4 extra shield frames
-        _ => return false,
-    }
+    true
 }
 
 #[skyline::hook(replace = smash::lua2cpp::L2CFighterCommon_sub_guard_cont)]
@@ -194,47 +178,22 @@ unsafe fn mod_handle_sub_guard_cont(fighter: &mut L2CFighterCommon) {
         return;
     }
 
-    if frame_counter::should_delay(MENU.reaction_time, REACTION_INDEX){
+    if frame_counter::should_delay(MENU.reaction_time, REACTION_INDEX) {
         return;
     }
 
+    let action = mash::buffer_menu_mash(module_accessor);
+
     if handle_escape_option(fighter, module_accessor) {
         return;
     }
 
-    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::Attack => match MENU.mash_attack_state {
-            Attack::UpSmash => {}
-            Attack::Grab => {}
-            _ => {
-                // Force shield drop
-                suspend_shield(15);
-            }
-        },
-
-        _ => {}
-    }
-}
-
-// Needed for shield drop options
-pub fn suspend_shield(frames: u32) {
-    if frames <= 0 {
-        return;
-    }
-
-    unsafe {
-        SHIELD_SUSPEND_FRAMES = frames;
-        frame_counter::reset_frame_count(FRAME_COUNTER_INDEX);
-        frame_counter::start_counting(FRAME_COUNTER_INDEX);
-    }
+    // Set shield suspension
+    suspend_shield(action);
 }
 
 /**
@@ -279,20 +238,20 @@ unsafe fn handle_escape_option(
         return false;
     }
 
-    match MENU.mash_state {
-        Mash::Spotdodge => {
+    match mash::get_current_buffer() {
+        Action::Spotdodge => {
             fighter
                 .fighter_base
                 .change_status(FIGHTER_STATUS_KIND_ESCAPE.as_lua_int(), LUA_TRUE);
             return true;
         }
-        Mash::RollForward => {
+        Action::RollForward => {
             fighter
                 .fighter_base
                 .change_status(FIGHTER_STATUS_KIND_ESCAPE_F.as_lua_int(), LUA_TRUE);
             return true;
         }
-        Mash::RollBack => {
+        Action::RollBack => {
             fighter
                 .fighter_base
                 .change_status(FIGHTER_STATUS_KIND_ESCAPE_B.as_lua_int(), LUA_TRUE);
@@ -306,55 +265,59 @@ unsafe fn handle_escape_option(
  * 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;
-            }
+    let action = mash::get_current_buffer();
 
-            if attack == Attack::UpB {
-                return true;
-            }
-        }
-        _ => {}
+    if action == Action::Jump {
+        return true;
+    }
+
+    if is_aerial(action) {
+        return true;
+    }
+
+    if action == Action::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,
+pub fn is_aerial(action: Action) -> bool {
+    match action {
+        Action::Nair => return true,
+        Action::Fair => return true,
+        Action::Bair => return true,
+        Action::UpAir => return true,
+        Action::Dair => return true,
         _ => return false,
     }
 }
 
+// Needed for shield drop options
+pub fn suspend_shield(action: Action) {
+    unsafe {
+        SUSPEND_SHIELD = need_suspend_shield(action);
+    }
+}
+
+fn need_suspend_shield(action: Action) -> bool {
+    match action {
+        Action::UpSmash => false,
+        Action::Grab => false,
+        Action::Shield => false,
+        Action::Nothing => false,
+        _ => {
+            // Force shield drop
+            true
+        }
+    }
+}
+
 /**
  * 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
+fn shield_is_suspended() -> bool {
+    unsafe { SUSPEND_SHIELD }
 }
 
 /**
@@ -376,7 +339,7 @@ unsafe fn should_return_none_in_check_button(
         return true;
     }
 
-    if !should_hold_shield(module_accessor) {
+    if !should_hold_shield() {
         return true;
     }