mirror of
https://github.com/jugeeya/UltimateTrainingModpack.git
synced 2024-11-24 10:54:16 +00:00
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
This commit is contained in:
parent
a19245e126
commit
0fc8fdf999
6 changed files with 283 additions and 200 deletions
|
@ -1 +1 @@
|
|||
Subproject commit 4393224a14cf6cca1cd1ff7f4e8517ca58071505
|
||||
Subproject commit 1bede8c899d015e8cad641926680c2da385fd5dd
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue