1
0
Fork 0
mirror of https://github.com/jugeeya/UltimateTrainingModpack.git synced 2024-11-20 08:54:15 +00:00

Code Refactoring (#83)

* Update TrainingModpackOverlay

* Apply Auto Formatter

* Auto Format

* Extract Modding Behaviour

Moved to separate function

* Guard Clause

* Guard Clause

* Use Match Clause

* Fix Comment

* Extract Shared Condition

* Extract Modding Function

* Guard Clause

* Guard Clause

* Guard Clause

* Guard Clause

* Guard Clause

* Extract Shared Code

* Fix Variable Reference

Properly borrow the variables

* Fix Missed Tech Buffering

* Move Training Mode Check To Start

* Guard Clause

* Guard Clause

* Extract Modding Behaviour

* Extract Function

For randomizing the di angle

* Guard Clause

* Guard Clause

* Simplify Loop

Separate condition from behaviour

* Extract Modding Behaviour

* Extract Modding Behaviour

* Formatting

* Fix Typos

* Fix Typos

* Fix Mash Toggle

! was binding stronger than ==

* Move Negation Inwards

* Reduce Nesting

* Extract Shared Condition

* Extract Method

Moved random command list definition to separate function
This commit is contained in:
sidschingis 2020-06-11 23:57:35 +02:00 committed by GitHub
parent e5ff95ce61
commit e67c69ed63
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 882 additions and 721 deletions

View file

@ -158,78 +158,82 @@ pub unsafe fn get_command_flag_cat(
module_accessor: &mut app::BattleObjectModuleAccessor,
category: i32,
) {
if is_training_mode() {
// Pause Effect AnimCMD if hitbox visualization is active
MotionAnimcmdModule::set_sleep_effect(
module_accessor,
MENU.hitbox_vis
&& !((*FIGHTER_STATUS_KIND_CATCH..=*FIGHTER_STATUS_KIND_TREAD_FALL)
.contains(&StatusModule::status_kind(module_accessor))),
);
if !is_training_mode() {
return;
}
// apply only once per frame
if category == 0 && is_training_mode() && MENU.hitbox_vis {
let status_kind = StatusModule::status_kind(module_accessor) as i32;
if !(*FIGHTER_STATUS_KIND_CATCH..=*FIGHTER_STATUS_KIND_CATCH_TURN).contains(&status_kind)
&& !is_shielding(module_accessor)
{
EffectModule::set_visible_kind(module_accessor, Hash40::new("sys_shield"), false);
EffectModule::kill_kind(module_accessor, Hash40::new("sys_shield"), false, true);
for i in 0..8 {
if AttackModule::is_attack(module_accessor, i, false) {
let attack_data = *AttackModule::attack_data(module_accessor, i, false);
let is_capsule =
attack_data.x2 != 0.0 || attack_data.y2 != 0.0 || attack_data.z2 != 0.0;
let mut x2 = None;
let mut y2 = None;
let mut z2 = None;
if is_capsule {
x2 = Some(attack_data.x2);
y2 = Some(attack_data.y2);
z2 = Some(attack_data.z2);
}
generate_hitbox_effects(
module_accessor,
attack_data.node, // joint
attack_data.size,
attack_data.x,
attack_data.y,
attack_data.z,
x2,
y2,
z2,
ID_COLORS[(i % 8) as usize],
);
}
}
if category != 0 {
return;
}
// Resume Effect AnimCMD incase we don't display hitboxes
MotionAnimcmdModule::set_sleep_effect(module_accessor, false);
if !MENU.hitbox_vis {
return;
}
let status_kind = StatusModule::status_kind(module_accessor) as i32;
if (*FIGHTER_STATUS_KIND_CATCH..=*FIGHTER_STATUS_KIND_CATCH_TURN).contains(&status_kind) {
return;
}
if is_shielding(module_accessor) {
return;
}
// Pause Effect AnimCMD if hitbox visualization is active
MotionAnimcmdModule::set_sleep_effect(module_accessor, true);
EffectModule::set_visible_kind(module_accessor, Hash40::new("sys_shield"), false);
EffectModule::kill_kind(module_accessor, Hash40::new("sys_shield"), false, true);
for i in 0..8 {
if !AttackModule::is_attack(module_accessor, i, false) {
continue;
}
let attack_data = *AttackModule::attack_data(module_accessor, i, false);
let is_capsule = attack_data.x2 != 0.0 || attack_data.y2 != 0.0 || attack_data.z2 != 0.0;
let mut x2 = None;
let mut y2 = None;
let mut z2 = None;
if is_capsule {
x2 = Some(attack_data.x2);
y2 = Some(attack_data.y2);
z2 = Some(attack_data.z2);
}
generate_hitbox_effects(
module_accessor,
attack_data.node, // joint
attack_data.size,
attack_data.x,
attack_data.y,
attack_data.z,
x2,
y2,
z2,
ID_COLORS[(i % 8) as usize],
);
}
}
// Necessary to ensure we visualize on the first frame of the hitbox
#[skyline::hook(replace = sv_animcmd::ATTACK)]
unsafe fn handle_attack(lua_state: u64) {
mod_handle_attack(lua_state);
original!()(lua_state);
}
unsafe fn mod_handle_attack(lua_state: u64) {
if !is_training_mode() {
return;
}
let mut l2c_agent = L2CAgent::new(lua_state);
// get all necessary grabbox params
let id = l2c_agent.pop_lua_stack(1); // int
let joint = l2c_agent.pop_lua_stack(3); // hash40
let _damage = l2c_agent.pop_lua_stack(4); // float
let _angle = l2c_agent.pop_lua_stack(5); // int
let _kbg = l2c_agent.pop_lua_stack(6); // int
let _fkb = l2c_agent.pop_lua_stack(7); // int
let _bkb = l2c_agent.pop_lua_stack(8); // int
let size = l2c_agent.pop_lua_stack(9); // float
let x = l2c_agent.pop_lua_stack(10); // float
let y = l2c_agent.pop_lua_stack(11); // float
let z = l2c_agent.pop_lua_stack(12); // float
let x2 = l2c_agent.pop_lua_stack(13); // float or void
let y2 = l2c_agent.pop_lua_stack(14); // float or void
let z2 = l2c_agent.pop_lua_stack(15); // float or void
// hacky way of forcing no shield damage on all hitboxes
if is_training_mode() && MENU.shield_state == Shield::Infinite {
if MENU.shield_state == Shield::Infinite {
let hitbox_params: Vec<L2CValue> =
(0..36).map(|i| l2c_agent.pop_lua_stack(i + 1)).collect();
l2c_agent.clear_lua_stack();
@ -243,9 +247,24 @@ unsafe fn handle_attack(lua_state: u64) {
}
}
original!()(lua_state);
// Hitbox Visualization
if MENU.hitbox_vis {
// get all necessary grabbox params
let id = l2c_agent.pop_lua_stack(1); // int
let joint = l2c_agent.pop_lua_stack(3); // hash40
let _damage = l2c_agent.pop_lua_stack(4); // float
let _angle = l2c_agent.pop_lua_stack(5); // int
let _kbg = l2c_agent.pop_lua_stack(6); // int
let _fkb = l2c_agent.pop_lua_stack(7); // int
let _bkb = l2c_agent.pop_lua_stack(8); // int
let size = l2c_agent.pop_lua_stack(9); // float
let x = l2c_agent.pop_lua_stack(10); // float
let y = l2c_agent.pop_lua_stack(11); // float
let z = l2c_agent.pop_lua_stack(12); // float
let x2 = l2c_agent.pop_lua_stack(13); // float or void
let y2 = l2c_agent.pop_lua_stack(14); // float or void
let z2 = l2c_agent.pop_lua_stack(15); // float or void
if MENU.hitbox_vis && is_training_mode() {
generate_hitbox_effects(
sv_system::battle_object_module_accessor(lua_state),
joint.get_int(),
@ -263,9 +282,21 @@ unsafe fn handle_attack(lua_state: u64) {
#[skyline::hook(replace = sv_animcmd::CATCH)]
unsafe fn handle_catch(lua_state: u64) {
let mut l2c_agent = L2CAgent::new(lua_state);
mod_handle_catch(lua_state);
original!()(lua_state);
}
unsafe fn mod_handle_catch(lua_state: u64) {
if !is_training_mode() {
return;
}
if !MENU.hitbox_vis {
return;
}
// get all necessary grabbox params
let mut l2c_agent = L2CAgent::new(lua_state);
let id = l2c_agent.pop_lua_stack(1); // int
let joint = l2c_agent.pop_lua_stack(2); // hash40
let size = l2c_agent.pop_lua_stack(3); // float
@ -276,22 +307,18 @@ unsafe fn handle_catch(lua_state: u64) {
let y2 = l2c_agent.pop_lua_stack(8); // float or void
let z2 = l2c_agent.pop_lua_stack(9); // float or void
original!()(lua_state);
if MENU.hitbox_vis && is_training_mode() {
generate_hitbox_effects(
sv_system::battle_object_module_accessor(lua_state),
joint.get_int(),
size.get_num(),
x.get_num(),
y.get_num(),
z.get_num(),
x2.try_get_num(),
y2.try_get_num(),
z2.try_get_num(),
ID_COLORS[(id.get_int() + 3 % 8) as usize],
);
}
generate_hitbox_effects(
sv_system::battle_object_module_accessor(lua_state),
joint.get_int(),
size.get_num(),
x.get_num(),
y.get_num(),
z.get_num(),
x2.try_get_num(),
y2.try_get_num(),
z2.try_get_num(),
ID_COLORS[(id.get_int() + 3 % 8) as usize],
);
}
pub unsafe fn is_shielding(module_accessor: *mut app::BattleObjectModuleAccessor) -> bool {
@ -304,15 +331,26 @@ pub unsafe fn handle_set_rebound(
module_accessor: *mut app::BattleObjectModuleAccessor,
rebound: bool,
) {
if is_training_mode() && rebound == false {
// only if we're not shielding
if !is_shielding(module_accessor) {
EffectModule::set_visible_kind(module_accessor, Hash40::new("sys_shield"), false);
EffectModule::kill_kind(module_accessor, Hash40::new("sys_shield"), false, true);
}
mod_handle_handle_set_rebound(module_accessor, rebound);
original!()(module_accessor, rebound);
}
unsafe fn mod_handle_handle_set_rebound(module_accessor: *mut app::BattleObjectModuleAccessor, rebound: bool) {
if !is_training_mode() {
return;
}
original!()(module_accessor, rebound);
if rebound != false {
return;
}
// only if we're not shielding
if is_shielding(module_accessor) {
return;
}
EffectModule::set_visible_kind(module_accessor, Hash40::new("sys_shield"), false);
EffectModule::kill_kind(module_accessor, Hash40::new("sys_shield"), false, true);
}
pub fn hitbox_visualization() {

View file

@ -15,40 +15,59 @@ pub unsafe fn handle_correct_damage_vector_common(
fighter: &mut L2CFighterCommon,
arg1: L2CValue,
) -> L2CValue {
let module_accessor = sv_system::battle_object_module_accessor(fighter.lua_state_agent);
if is_training_mode() && is_operation_cpu(module_accessor) {
if MENU.di_state != DirectionalInfluence::None {
DI_ANGLE = (MENU.di_state as i32 - 1) as f64 * PI / 4.0;
// Either left, right, or none
if MENU.di_state == DirectionalInfluence::RandomInAway {
let rand = app::sv_math::rand(hash40("fighter"), 3);
// Either 0 (right) or PI (left)
if [0, 1].contains(&rand) {
DI_ANGLE = rand as f64 * PI;
} else {
DI_ANGLE = NO_DI;
}
}
// If facing left, reverse angle
if DI_ANGLE != NO_DI && PostureModule::lr(module_accessor) != -1.0 {
DI_ANGLE -= PI;
}
if DI_ANGLE != NO_DI {
WorkModule::set_float(
module_accessor,
DI_ANGLE.cos() as f32,
*FIGHTER_STATUS_DAMAGE_WORK_FLOAT_VECOR_CORRECT_STICK_X,
);
WorkModule::set_float(
module_accessor,
DI_ANGLE.sin() as f32,
*FIGHTER_STATUS_DAMAGE_WORK_FLOAT_VECOR_CORRECT_STICK_Y,
);
}
}
}
mod_handle_di(fighter, arg1);
original!()(fighter, arg1)
}
unsafe fn mod_handle_di(fighter: &mut L2CFighterCommon, _arg1: L2CValue) {
if !is_training_mode() {
return;
}
if MENU.di_state == DirectionalInfluence::None {
return;
}
let module_accessor = sv_system::battle_object_module_accessor(fighter.lua_state_agent);
if !is_operation_cpu(module_accessor) {
return;
}
// Either left, right, or none
if MENU.di_state == DirectionalInfluence::RandomInAway {
DI_ANGLE = get_random_di();
} else {
DI_ANGLE = (MENU.di_state as i32 - 1) as f64 * PI / 4.0;
}
// If facing left, reverse angle
if DI_ANGLE != NO_DI && PostureModule::lr(module_accessor) != -1.0 {
DI_ANGLE -= PI;
}
// Nothig to do on no DI
if DI_ANGLE == NO_DI {
return;
}
WorkModule::set_float(
module_accessor,
DI_ANGLE.cos() as f32,
*FIGHTER_STATUS_DAMAGE_WORK_FLOAT_VECOR_CORRECT_STICK_X,
);
WorkModule::set_float(
module_accessor,
DI_ANGLE.sin() as f32,
*FIGHTER_STATUS_DAMAGE_WORK_FLOAT_VECOR_CORRECT_STICK_Y,
);
}
unsafe fn get_random_di() -> f64 {
let rand = app::sv_math::rand(hash40("fighter"), 3);
if [0, 1].contains(&rand) {
// Either 0 (right) or PI (left)
rand as f64 * PI
} else {
NO_DI
}
}

View file

@ -5,35 +5,41 @@ use smash::hash40;
use smash::lib::lua_const::*;
pub unsafe fn force_option(module_accessor: &mut app::BattleObjectModuleAccessor) {
if StatusModule::status_kind(module_accessor) as i32 == *FIGHTER_STATUS_KIND_CLIFF_WAIT {
if WorkModule::is_enable_transition_term(
module_accessor,
*FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_CLIFF_CLIMB,
) {
let random_frame = app::sv_math::rand(
hash40("fighter"),
MotionModule::end_frame(module_accessor) as i32,
) as f32;
let frame = MotionModule::frame(module_accessor) as f32;
if frame == random_frame || frame > 30.0 {
let mut status = 0;
let ledge_case: LedgeOption;
if MENU.ledge_state == LedgeOption::Random {
ledge_case = (app::sv_math::rand(hash40("fighter"), 4) + 2).into();
} else {
ledge_case = MENU.ledge_state;
}
if let Some(new_status) = ledge_case.into_status() {
status = new_status;
}
StatusModule::change_status_request_from_script(module_accessor, status, true);
}
}
if StatusModule::status_kind(module_accessor) as i32 != *FIGHTER_STATUS_KIND_CLIFF_WAIT {
return;
}
if !WorkModule::is_enable_transition_term(
module_accessor,
*FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_CLIFF_CLIMB,
) {
return;
}
let random_frame = app::sv_math::rand(
hash40("fighter"),
MotionModule::end_frame(module_accessor) as i32,
) as f32;
let frame = MotionModule::frame(module_accessor) as f32;
if !(frame == random_frame || frame > 30.0) {
return;
}
let mut status = 0;
let ledge_case: LedgeOption;
if MENU.ledge_state == LedgeOption::Random {
ledge_case = (app::sv_math::rand(hash40("fighter"), 4) + 2).into();
} else {
ledge_case = MENU.ledge_state;
}
if let Some(new_status) = ledge_case.into_status() {
status = new_status;
}
StatusModule::change_status_request_from_script(module_accessor, status, true);
}
pub unsafe fn should_perform_defensive_option(
@ -62,28 +68,40 @@ pub unsafe fn defensive_option(
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) {
perform_defensive_option(module_accessor, flag);
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 [*CONTROL_PAD_BUTTON_GUARD_HOLD, *CONTROL_PAD_BUTTON_GUARD].contains(&button) {
if is_training_mode() && is_operation_cpu(module_accessor) {
let prev_status = StatusModule::prev_status_kind(module_accessor, 0) as i32;
let status = StatusModule::status_kind(module_accessor) as i32;
if MENU.defensive_state == Defensive::Shield
&& should_perform_defensive_option(module_accessor, prev_status, status)
{
return Some(true);
}
}
if !is_training_mode() {
return None;
}
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(
@ -91,11 +109,18 @@ pub unsafe fn get_command_flag_cat(
category: i32,
flag: &mut i32,
) {
if MENU.ledge_state != LedgeOption::None
&& is_training_mode()
&& is_operation_cpu(module_accessor)
{
force_option(module_accessor);
defensive_option(module_accessor, category, flag);
if !is_training_mode() {
return;
}
if !is_operation_cpu(module_accessor) {
return;
}
if MENU.ledge_state == LedgeOption::None {
return;
}
force_option(module_accessor);
defensive_option(module_accessor, category, flag);
}

View file

@ -8,16 +8,24 @@ use smash::lib::lua_const::*;
pub unsafe fn get_attack_air_kind(
module_accessor: &mut app::BattleObjectModuleAccessor,
) -> Option<i32> {
if is_training_mode() && is_operation_cpu(module_accessor) {
if MENU.mash_state == Mash::Attack {
MENU.mash_attack_state.into_attack_air_kind()
} else if MENU.mash_state == Mash::Random {
Some(app::sv_math::rand(hash40("fighter"), 5) + 1)
} else {
None
if !is_training_mode() {
return None;
}
if !is_operation_cpu(module_accessor) {
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;
}
} else {
None
}
}
@ -26,140 +34,153 @@ pub unsafe fn get_command_flag_cat(
category: i32,
flag: &mut i32,
) {
// Check for OOS delay
if is_training_mode() && is_operation_cpu(module_accessor)
&& is_in_shieldstun(module_accessor) && !shield::allow_oos(){
if category != FIGHTER_PAD_COMMAND_CATEGORY1 {
return;
}
if is_training_mode() && is_operation_cpu(module_accessor) {
if is_in_hitstun(module_accessor)
|| is_in_landing(module_accessor)
|| is_in_shieldstun(module_accessor)
|| is_in_footstool(module_accessor)
|| StatusModule::status_kind(module_accessor) == FIGHTER_STATUS_KIND_CLIFF_ROBBED
{
match MENU.mash_state {
Mash::Airdodge => {
if category == FIGHTER_PAD_COMMAND_CATEGORY1 {
*flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_AIR_ESCAPE;
}
}
Mash::Jump => {
if !is_in_landing(module_accessor) && category == FIGHTER_PAD_COMMAND_CATEGORY1
{
if !is_training_mode() {
return;
}
if !is_operation_cpu(module_accessor) {
return;
}
// Check for OOS delay
if is_in_shieldstun(module_accessor) && !shield::allow_oos() {
return;
}
if !(is_in_hitstun(module_accessor)
|| is_in_landing(module_accessor)
|| is_in_shieldstun(module_accessor)
|| is_in_footstool(module_accessor)
|| StatusModule::status_kind(module_accessor) == FIGHTER_STATUS_KIND_CLIFF_ROBBED)
{
return;
}
match MENU.mash_state {
Mash::Airdodge => {
*flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_AIR_ESCAPE;
}
Mash::Jump => {
if !is_in_landing(module_accessor) {
*flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_JUMP_BUTTON;
}
}
Mash::Spotdodge => {
*flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE;
}
Mash::RollForward => {
*flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE_F;
}
Mash::RollBack => {
*flag |= *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 performing the attack OOS we also need to jump
if is_in_shieldstun(module_accessor) {
*flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_JUMP_BUTTON;
}
}
Mash::Spotdodge => {
if category == FIGHTER_PAD_COMMAND_CATEGORY1 {
*flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE;
}
}
Mash::RollForward => {
if category == FIGHTER_PAD_COMMAND_CATEGORY1 {
*flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE_F;
}
}
Mash::RollBack => {
if category == FIGHTER_PAD_COMMAND_CATEGORY1 {
*flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_ESCAPE_B;
}
}
Mash::Attack => {
if category == FIGHTER_PAD_COMMAND_CATEGORY1 {
use Attack::*;
match MENU.mash_attack_state {
Nair | Fair | Bair | UpAir | Dair => {
*flag |= *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_N;
// If we are performing the attack OOS we also need to jump
if is_in_shieldstun(module_accessor) {
*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,
}
}
}
Mash::Random => {
if category == FIGHTER_PAD_COMMAND_CATEGORY1 {
let situation_kind = StatusModule::situation_kind(module_accessor) as i32;
if situation_kind == SITUATION_KIND_AIR {
let random_commands = 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,
];
let random_cmd_index =
app::sv_math::rand(hash40("fighter"), random_commands.len() as i32)
as usize;
*flag |= random_commands[random_cmd_index];
} else if situation_kind == SITUATION_KIND_GROUND {
let random_commands = 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,
];
let random_cmd_index =
app::sv_math::rand(hash40("fighter"), random_commands.len() as i32)
as usize;
*flag |= random_commands[random_cmd_index];
}
}
}
_ => (),
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,
}
}
Mash::Random => {
let random_commands = get_random_command_list(module_accessor);
if random_commands.len() == 0 {
return;
}
let random_cmd_index =
app::sv_math::rand(hash40("fighter"), random_commands.len() as i32) as usize;
*flag |= random_commands[random_cmd_index];
}
_ => (),
}
}
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 [*CONTROL_PAD_BUTTON_GUARD_HOLD, *CONTROL_PAD_BUTTON_GUARD].contains(&button) {
if is_training_mode() && is_operation_cpu(module_accessor) {
if MENU.mash_state == Mash::Airdodge
&& (is_in_hitstun(module_accessor)
|| is_in_landing(module_accessor)
|| is_in_footstool(module_accessor))
{
return Some(true);
}
}
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

View file

@ -29,166 +29,163 @@ static mut SAVE_STATE_LR_CPU: f32 = 1.0;
static mut SAVE_STATE_SITUATION_KIND_CPU: i32 = 0 as i32;
pub unsafe fn save_states(module_accessor: &mut app::BattleObjectModuleAccessor) {
if !is_training_mode() {
return;
}
let status = StatusModule::status_kind(module_accessor) as i32;
if is_training_mode() {
let save_state_x: *mut f32;
let save_state_y: *mut f32;
let save_state_percent: *mut f32;
let save_state_lr: *mut f32;
let save_state_situation_kind: *mut i32;
let save_state: *mut SaveState;
if is_operation_cpu(module_accessor) {
save_state_x = &mut SAVE_STATE_X_CPU;
save_state_y = &mut SAVE_STATE_Y_CPU;
save_state_percent = &mut SAVE_STATE_PERCENT_CPU;
save_state_lr = &mut SAVE_STATE_LR_CPU;
save_state_situation_kind = &mut SAVE_STATE_SITUATION_KIND_CPU;
save_state = &mut SAVE_STATE_CPU_STATE;
} else {
save_state_x = &mut SAVE_STATE_X_PLAYER;
save_state_y = &mut SAVE_STATE_Y_PLAYER;
save_state_percent = &mut SAVE_STATE_PERCENT_PLAYER;
save_state_lr = &mut SAVE_STATE_LR_PLAYER;
save_state_situation_kind = &mut SAVE_STATE_SITUATION_KIND_PLAYER;
save_state = &mut SAVE_STATE_PLAYER_STATE;
let save_state_x: *mut f32;
let save_state_y: *mut f32;
let save_state_percent: *mut f32;
let save_state_lr: *mut f32;
let save_state_situation_kind: *mut i32;
let save_state: *mut SaveState;
if is_operation_cpu(module_accessor) {
save_state_x = &mut SAVE_STATE_X_CPU;
save_state_y = &mut SAVE_STATE_Y_CPU;
save_state_percent = &mut SAVE_STATE_PERCENT_CPU;
save_state_lr = &mut SAVE_STATE_LR_CPU;
save_state_situation_kind = &mut SAVE_STATE_SITUATION_KIND_CPU;
save_state = &mut SAVE_STATE_CPU_STATE;
} else {
save_state_x = &mut SAVE_STATE_X_PLAYER;
save_state_y = &mut SAVE_STATE_Y_PLAYER;
save_state_percent = &mut SAVE_STATE_PERCENT_PLAYER;
save_state_lr = &mut SAVE_STATE_LR_PLAYER;
save_state_situation_kind = &mut SAVE_STATE_SITUATION_KIND_PLAYER;
save_state = &mut SAVE_STATE_PLAYER_STATE;
}
// Grab + Dpad up: reset state
if ControlModule::check_button_on(module_accessor, *CONTROL_PAD_BUTTON_CATCH)
&& ControlModule::check_button_trigger(module_accessor, *CONTROL_PAD_BUTTON_APPEAL_HI)
{
if *save_state == NoAction {
SAVE_STATE_PLAYER_STATE = CameraMove;
SAVE_STATE_CPU_STATE = CameraMove;
}
return;
}
// Grab + Dpad up: reset state
if ControlModule::check_button_on(module_accessor, *CONTROL_PAD_BUTTON_CATCH)
&& ControlModule::check_button_trigger(module_accessor, *CONTROL_PAD_BUTTON_APPEAL_HI)
{
if *save_state == NoAction {
SAVE_STATE_PLAYER_STATE = CameraMove;
SAVE_STATE_CPU_STATE = CameraMove;
}
return;
}
// move to camera bounds
if *save_state == CameraMove {
*save_state = PosMove;
// move to camera bounds
if *save_state == CameraMove {
*save_state = PosMove;
let left_right = (PostureModule::pos_x(module_accessor) > 0.0) as i32 as f32
- (PostureModule::pos_x(module_accessor) < 0.0) as i32 as f32;
let y_pos = 20.0;
let left_right = (PostureModule::pos_x(module_accessor) > 0.0) as i32 as f32
- (PostureModule::pos_x(module_accessor) < 0.0) as i32 as f32;
let y_pos = 20.0;
let pos = Vector3f {
x: left_right * 50.0,
y: y_pos,
z: 0.0,
};
PostureModule::set_pos(module_accessor, &pos);
let pos = Vector3f {
x: left_right * 50.0,
y: y_pos,
z: 0.0,
};
PostureModule::set_pos(module_accessor, &pos);
// force aerial, because from aerial state we can move anywhere
if StatusModule::situation_kind(module_accessor) == SITUATION_KIND_GROUND {
StatusModule::change_status_request(
module_accessor,
*FIGHTER_STATUS_KIND_JUMP_SQUAT,
false,
);
}
return;
}
// move to correct pos
if *save_state == PosMove {
if StatusModule::situation_kind(module_accessor) == SITUATION_KIND_GROUND {
return;
}
KineticModule::clear_speed_all(module_accessor);
let pos = Vector3f {
x: *save_state_x,
y: *save_state_y,
z: 0.0,
};
PostureModule::set_pos(module_accessor, &pos);
PostureModule::set_lr(module_accessor, *save_state_lr);
DamageModule::heal(
// force aerial, because from aerial state we can move anywhere
if StatusModule::situation_kind(module_accessor) == SITUATION_KIND_GROUND {
StatusModule::change_status_request(
module_accessor,
-1.0 * DamageModule::damage(module_accessor, 0),
0,
);
DamageModule::add_damage(module_accessor, *save_state_percent, 0);
StatusModule::set_situation_kind(
module_accessor,
app::SituationKind {
situation_kind: *save_state_situation_kind,
},
*FIGHTER_STATUS_KIND_JUMP_SQUAT,
false,
);
}
return;
}
if *save_state_situation_kind == SITUATION_KIND_GROUND
&& status != FIGHTER_STATUS_KIND_WAIT
{
StatusModule::change_status_request(
module_accessor,
*FIGHTER_STATUS_KIND_CLIFF_WAIT,
false,
);
} else if *save_state_situation_kind == SITUATION_KIND_AIR
&& status != FIGHTER_STATUS_KIND_FALL
{
StatusModule::change_status_request(
module_accessor,
*FIGHTER_STATUS_KIND_FALL,
false,
);
} else if *save_state_situation_kind == SITUATION_KIND_CLIFF
&& status != FIGHTER_STATUS_KIND_CLIFF_CATCH_MOVE
&& status != FIGHTER_STATUS_KIND_CLIFF_CATCH
{
StatusModule::change_status_request(
module_accessor,
*FIGHTER_STATUS_KIND_CLIFF_CATCH_MOVE,
false,
);
}
*save_state = NoAction;
// move to correct pos
if *save_state == PosMove {
if StatusModule::situation_kind(module_accessor) == SITUATION_KIND_GROUND {
return;
}
// Grab + Dpad down: Save state
if ControlModule::check_button_on(module_accessor, *CONTROL_PAD_BUTTON_CATCH)
&& ControlModule::check_button_trigger(module_accessor, *CONTROL_PAD_BUTTON_APPEAL_LW)
KineticModule::clear_speed_all(module_accessor);
let pos = Vector3f {
x: *save_state_x,
y: *save_state_y,
z: 0.0,
};
PostureModule::set_pos(module_accessor, &pos);
PostureModule::set_lr(module_accessor, *save_state_lr);
DamageModule::heal(
module_accessor,
-1.0 * DamageModule::damage(module_accessor, 0),
0,
);
DamageModule::add_damage(module_accessor, *save_state_percent, 0);
StatusModule::set_situation_kind(
module_accessor,
app::SituationKind {
situation_kind: *save_state_situation_kind,
},
false,
);
if *save_state_situation_kind == SITUATION_KIND_GROUND && status != FIGHTER_STATUS_KIND_WAIT
{
SAVE_STATE_PLAYER_STATE = Save;
SAVE_STATE_CPU_STATE = Save;
}
if *save_state == Save {
*save_state = NoAction;
*save_state_x = PostureModule::pos_x(module_accessor);
*save_state_y = PostureModule::pos_y(module_accessor);
*save_state_lr = PostureModule::lr(module_accessor);
*save_state_percent = DamageModule::damage(module_accessor, 0);
*save_state_situation_kind = StatusModule::situation_kind(module_accessor);
let zeros = Vector3f {
x: 0.0,
y: 0.0,
z: 0.0,
};
EffectModule::req_on_joint(
StatusModule::change_status_request(
module_accessor,
Hash40::new("sys_deku_flash"),
Hash40::new("top"),
&zeros,
&zeros,
0.25,
&zeros,
&zeros,
true,
*EFFECT_SUB_ATTRIBUTE_NO_JOINT_SCALE as u32
| *EFFECT_SUB_ATTRIBUTE_FOLLOW as u32
| *EFFECT_SUB_ATTRIBUTE_CONCLUDE_STATUS as u32,
0,
0,
*FIGHTER_STATUS_KIND_CLIFF_WAIT,
false,
);
} else if *save_state_situation_kind == SITUATION_KIND_AIR
&& status != FIGHTER_STATUS_KIND_FALL
{
StatusModule::change_status_request(module_accessor, *FIGHTER_STATUS_KIND_FALL, false);
} else if *save_state_situation_kind == SITUATION_KIND_CLIFF
&& status != FIGHTER_STATUS_KIND_CLIFF_CATCH_MOVE
&& status != FIGHTER_STATUS_KIND_CLIFF_CATCH
{
StatusModule::change_status_request(
module_accessor,
*FIGHTER_STATUS_KIND_CLIFF_CATCH_MOVE,
false,
);
}
*save_state = NoAction;
return;
}
// Grab + Dpad down: Save state
if ControlModule::check_button_on(module_accessor, *CONTROL_PAD_BUTTON_CATCH)
&& ControlModule::check_button_trigger(module_accessor, *CONTROL_PAD_BUTTON_APPEAL_LW)
{
SAVE_STATE_PLAYER_STATE = Save;
SAVE_STATE_CPU_STATE = Save;
}
if *save_state == Save {
*save_state = NoAction;
*save_state_x = PostureModule::pos_x(module_accessor);
*save_state_y = PostureModule::pos_y(module_accessor);
*save_state_lr = PostureModule::lr(module_accessor);
*save_state_percent = DamageModule::damage(module_accessor, 0);
*save_state_situation_kind = StatusModule::situation_kind(module_accessor);
let zeros = Vector3f {
x: 0.0,
y: 0.0,
z: 0.0,
};
EffectModule::req_on_joint(
module_accessor,
Hash40::new("sys_deku_flash"),
Hash40::new("top"),
&zeros,
&zeros,
0.25,
&zeros,
&zeros,
true,
*EFFECT_SUB_ATTRIBUTE_NO_JOINT_SCALE as u32
| *EFFECT_SUB_ATTRIBUTE_FOLLOW as u32
| *EFFECT_SUB_ATTRIBUTE_CONCLUDE_STATUS as u32,
0,
0,
);
}
}

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 : u8 = MENU.oos_offset;
static mut MULTI_HIT_OFFSET: u8 = MENU.oos_offset;
// Used to only decrease once per shieldstun change
static mut WAS_IN_SHIELDSTUN: bool = false;
@ -24,7 +24,7 @@ unsafe fn should_pause_shield_decay() -> bool {
!SHIELD_DECAY
}
unsafe fn reset_oos_offset(){
unsafe fn reset_oos_offset() {
/*
* Need to offset by 1, since we decrease as soon as shield gets hit
* but only check later if we can OOS
@ -32,8 +32,7 @@ unsafe fn reset_oos_offset(){
MULTI_HIT_OFFSET = MENU.oos_offset + 1;
}
unsafe fn handle_oos_offset(module_accessor: &mut app::BattleObjectModuleAccessor)
{
unsafe fn handle_oos_offset(module_accessor: &mut app::BattleObjectModuleAccessor) {
// Check if we are currently in shield stun
if !is_in_shieldstun(module_accessor) {
// Make sure we don't forget and wait until we get hit on shield
@ -55,7 +54,7 @@ unsafe fn handle_oos_offset(module_accessor: &mut app::BattleObjectModuleAccesso
WAS_IN_SHIELDSTUN = true;
}
pub unsafe fn allow_oos()->bool {
pub unsafe fn allow_oos() -> bool {
// Delay OOS until offset hits 0
MULTI_HIT_OFFSET == 0
}
@ -70,8 +69,7 @@ pub unsafe fn get_command_flag_cat(module_accessor: &mut app::BattleObjectModule
}
// Reset oos offset when standing
if is_idle(module_accessor)
|| is_in_hitstun(module_accessor){
if is_idle(module_accessor) || is_in_hitstun(module_accessor) {
reset_oos_offset();
}
@ -87,29 +85,32 @@ pub unsafe fn get_param_float(
param_type: u64,
param_hash: u64,
) -> Option<f32> {
if !is_training_mode() {
return None;
}
if !is_operation_cpu(module_accessor) {
return None;
}
if is_training_mode() {
if MENU.shield_state != Shield::None {
handle_oos_offset(module_accessor);
}
if MENU.shield_state != Shield::None {
handle_oos_offset(module_accessor);
// Shield Decay//Recovery
if MENU.shield_state == Shield::Infinite || should_pause_shield_decay() {
if param_type != hash40("common") {
return None;
}
if MENU.shield_state == Shield::Infinite || should_pause_shield_decay() {
if param_type == hash40("common") {
if param_hash == hash40("shield_dec1") {
return Some(0.0);
}
if param_hash == hash40("shield_recovery1") {
return Some(999.0);
}
// doesn't work, somehow. This parameter isn't checked?
if param_hash == hash40("shield_damage_mul") {
return Some(0.0);
}
}
if param_hash == hash40("shield_dec1") {
return Some(0.0);
}
if param_hash == hash40("shield_recovery1") {
return Some(999.0);
}
// doesn't work, somehow. This parameter isn't checked?
if param_hash == hash40("shield_damage_mul") {
return Some(0.0);
}
}
@ -118,31 +119,33 @@ pub unsafe fn get_param_float(
pub unsafe fn should_hold_shield(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
// We should hold shield if the state requires it
if [Shield::Hold, Shield::Infinite].contains(&MENU.shield_state) {
// If we are not mashing attack then we will always hold shield
if MENU.mash_state != Mash::Attack {
return true;
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) {
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;
}
// Hold shield while OOS is not allowed
if !allow_oos() {
if MENU.mash_attack_state == Attack::Grab {
return true;
}
if !is_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;
}
}
}
false
@ -150,154 +153,153 @@ pub unsafe fn should_hold_shield(module_accessor: &mut app::BattleObjectModuleAc
#[skyline::hook(replace = smash::lua2cpp::L2CFighterCommon_sub_guard_cont)]
pub unsafe fn handle_sub_guard_cont(fighter: &mut L2CFighterCommon) -> L2CValue {
mod_handle_sub_guard_cont(fighter);
original!()(fighter)
}
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
{
return;
}
// Enable shield decay
if is_training_mode()
&& is_operation_cpu(module_accessor)
&& StatusModule::prev_status_kind(module_accessor, 0) == FIGHTER_STATUS_KIND_GUARD_DAMAGE
{
set_shield_decay(true);
}
set_shield_decay(true);
// Check for OOS delay
if is_training_mode()
&& is_operation_cpu(module_accessor)
&& StatusModule::prev_status_kind(module_accessor, 0) == FIGHTER_STATUS_KIND_GUARD_DAMAGE
&& !allow_oos() {
return original!()(fighter);
if !allow_oos() {
return;
}
if is_training_mode() && is_operation_cpu(module_accessor) {
if MENU.mash_state == Mash::Attack && MENU.mash_attack_state == Attack::Grab {
if StatusModule::prev_status_kind(module_accessor, 0)
== FIGHTER_STATUS_KIND_GUARD_DAMAGE
{
if WorkModule::get_int(
module_accessor,
*FIGHTER_INSTANCE_WORK_ID_INT_INVALID_CATCH_FRAME,
) == 0
{
if WorkModule::is_enable_transition_term(
module_accessor,
*FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_CATCH,
) {
fighter.fighter_base.change_status(
L2CValue::new_int(*FIGHTER_STATUS_KIND_CATCH as u64),
L2CValue::new_bool(true),
);
}
}
}
}
if MENU.mash_state == Mash::Spotdodge {
if StatusModule::prev_status_kind(module_accessor, 0)
== FIGHTER_STATUS_KIND_GUARD_DAMAGE
{
if WorkModule::is_enable_transition_term(
module_accessor,
*FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_ESCAPE,
) {
fighter.fighter_base.change_status(
L2CValue::new_int(*FIGHTER_STATUS_KIND_ESCAPE as u64),
L2CValue::new_bool(true),
);
}
}
}
if MENU.mash_state == Mash::RollForward {
if StatusModule::prev_status_kind(module_accessor, 0)
== FIGHTER_STATUS_KIND_GUARD_DAMAGE
{
if WorkModule::is_enable_transition_term(
module_accessor,
*FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_ESCAPE,
) {
fighter.fighter_base.change_status(
L2CValue::new_int(*FIGHTER_STATUS_KIND_ESCAPE_F as u64),
L2CValue::new_bool(true),
);
}
}
}
if MENU.mash_state == Mash::RollBack {
if StatusModule::prev_status_kind(module_accessor, 0)
== FIGHTER_STATUS_KIND_GUARD_DAMAGE
{
if WorkModule::is_enable_transition_term(
module_accessor,
*FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_ESCAPE,
) {
fighter.fighter_base.change_status(
L2CValue::new_int(*FIGHTER_STATUS_KIND_ESCAPE_B as u64),
L2CValue::new_bool(true),
);
}
}
}
if MENU.mash_state == Mash::Attack {
if MENU.mash_attack_state == Attack::UpB {
if StatusModule::prev_status_kind(module_accessor, 0)
== FIGHTER_STATUS_KIND_GUARD_DAMAGE
{
if WorkModule::is_enable_transition_term(
module_accessor,
*FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_JUMP_SQUAT_BUTTON,
) {
fighter.fighter_base.change_status(
L2CValue::new_int(*FIGHTER_STATUS_KIND_SPECIAL_HI as u64),
L2CValue::new_bool(false),
);
}
}
}
if MENU.mash_attack_state == Attack::UpSmash {
if StatusModule::prev_status_kind(module_accessor, 0)
== FIGHTER_STATUS_KIND_GUARD_DAMAGE
{
if WorkModule::is_enable_transition_term(
module_accessor,
*FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_JUMP_SQUAT_BUTTON,
) {
fighter.fighter_base.change_status(
L2CValue::new_int(*FIGHTER_STATUS_KIND_ATTACK_HI4_START as u64),
L2CValue::new_bool(false),
);
}
}
}
}
if MENU.mash_state == Mash::Attack {
handle_attack_option(fighter, module_accessor);
return;
}
original!()(fighter)
if WorkModule::is_enable_transition_term(
module_accessor,
*FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_ESCAPE,
) {
handle_escape_option(fighter);
}
}
unsafe fn handle_escape_option(fighter: &mut L2CFighterCommon) {
match MENU.mash_state {
Mash::Spotdodge => {
fighter.fighter_base.change_status(
L2CValue::new_int(*FIGHTER_STATUS_KIND_ESCAPE as u64),
L2CValue::new_bool(true),
);
}
Mash::RollForward => {
fighter.fighter_base.change_status(
L2CValue::new_int(*FIGHTER_STATUS_KIND_ESCAPE_F as u64),
L2CValue::new_bool(true),
);
}
Mash::RollBack => {
fighter.fighter_base.change_status(
L2CValue::new_int(*FIGHTER_STATUS_KIND_ESCAPE_B as u64),
L2CValue::new_bool(true),
);
}
_ => (),
}
}
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;
}
fighter.fighter_base.change_status(
L2CValue::new_int(*FIGHTER_STATUS_KIND_CATCH as u64),
L2CValue::new_bool(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(
L2CValue::new_int(*FIGHTER_STATUS_KIND_SPECIAL_HI as u64),
L2CValue::new_bool(false),
);
}
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(
L2CValue::new_int(*FIGHTER_STATUS_KIND_ATTACK_HI4_START as u64),
L2CValue::new_bool(false),
);
}
_ => (),
}
}
pub unsafe fn check_button_on(
module_accessor: &mut app::BattleObjectModuleAccessor,
button: i32,
) -> Option<bool> {
if [*CONTROL_PAD_BUTTON_GUARD_HOLD, *CONTROL_PAD_BUTTON_GUARD].contains(&button) {
if is_training_mode() && is_operation_cpu(module_accessor) {
if should_hold_shield(module_accessor) {
return Some(true);
}
}
if should_return_none_in_check_button(module_accessor, button) {
return None;
}
None
Some(true)
}
pub unsafe fn check_button_off(
module_accessor: &mut app::BattleObjectModuleAccessor,
button: i32,
) -> Option<bool> {
if [*CONTROL_PAD_BUTTON_GUARD_HOLD, *CONTROL_PAD_BUTTON_GUARD].contains(&button) {
if is_training_mode() && is_operation_cpu(module_accessor) {
if should_hold_shield(module_accessor) {
return Some(false);
}
}
if should_return_none_in_check_button(module_accessor, button) {
return None;
}
Some(false)
}
unsafe fn should_return_none_in_check_button(
module_accessor: &mut app::BattleObjectModuleAccessor,
button: i32,
) -> bool {
if !is_training_mode() {
return true;
}
None
if !is_operation_cpu(module_accessor) {
return true;
}
if ![*CONTROL_PAD_BUTTON_GUARD_HOLD, *CONTROL_PAD_BUTTON_GUARD].contains(&button) {
return true;
}
if !should_hold_shield(module_accessor) {
return true;
}
false
}

View file

@ -15,61 +15,89 @@ pub unsafe fn handle_change_status(
) -> L2CValue {
let mut status_kind = status_kind;
let mut unk = unk;
let module_accessor = sv_system::battle_object_module_accessor(fighter.lua_state_agent);
if is_training_mode() && is_operation_cpu(module_accessor) {
let status_kind_int = status_kind
.try_get_int()
.unwrap_or(*FIGHTER_STATUS_KIND_WAIT as u64) as i32;
if status_kind_int == FIGHTER_STATUS_KIND_DOWN
|| status_kind_int == FIGHTER_STATUS_KIND_DAMAGE_FLY_REFLECT_D
{
match MENU.tech_state {
TechOption::Random => {
let random_statuses = vec![
*FIGHTER_STATUS_KIND_DOWN,
*FIGHTER_STATUS_KIND_PASSIVE,
*FIGHTER_STATUS_KIND_PASSIVE_FB,
];
let random_status_index =
app::sv_math::rand(hash40("fighter"), random_statuses.len() as i32)
as usize;
if random_statuses[random_status_index] != FIGHTER_STATUS_KIND_DOWN {
status_kind =
L2CValue::new_int(random_statuses[random_status_index] as u64);
unk = L2CValue::new_bool(true);
}
}
TechOption::InPlace => {
status_kind = L2CValue::new_int(*FIGHTER_STATUS_KIND_PASSIVE as u64);
unk = L2CValue::new_bool(true);
}
TechOption::Roll => {
status_kind = L2CValue::new_int(*FIGHTER_STATUS_KIND_PASSIVE_FB as u64);
unk = L2CValue::new_bool(true);
}
_ => (),
}
} else if status_kind_int == FIGHTER_STATUS_KIND_STOP_WALL
|| status_kind_int == FIGHTER_STATUS_KIND_DAMAGE_FLY_REFLECT_LR
{
if MENU.tech_state != TechOption::None && MENU.tech_state != TechOption::Miss {
status_kind = L2CValue::new_int(*FIGHTER_STATUS_KIND_PASSIVE_WALL as u64);
unk = L2CValue::new_bool(true);
}
} else if status_kind_int == FIGHTER_STATUS_KIND_STOP_CEIL
|| status_kind_int == FIGHTER_STATUS_KIND_DAMAGE_FLY_REFLECT_U
{
if MENU.tech_state != TechOption::None && MENU.tech_state != TechOption::Miss {
status_kind = L2CValue::new_int(*FIGHTER_STATUS_KIND_PASSIVE_CEIL as u64);
unk = L2CValue::new_bool(true);
}
}
}
mod_handle_change_status(fighter, &mut status_kind, &mut unk);
original!()(fighter, status_kind, unk)
}
unsafe fn mod_handle_change_status(
fighter: &mut L2CFighterBase,
status_kind: &mut L2CValue,
unk: &mut L2CValue,
) {
if !is_training_mode() {
return;
}
let module_accessor = sv_system::battle_object_module_accessor(fighter.lua_state_agent);
if !is_operation_cpu(module_accessor) {
return;
}
if MENU.tech_state == TechOption::None {
return;
}
if MENU.tech_state == TechOption::Miss {
return;
}
let status_kind_int = status_kind
.try_get_int()
.unwrap_or(*FIGHTER_STATUS_KIND_WAIT as u64) as i32;
// Ground Tech
if status_kind_int == FIGHTER_STATUS_KIND_DOWN
|| status_kind_int == FIGHTER_STATUS_KIND_DAMAGE_FLY_REFLECT_D
{
match MENU.tech_state {
TechOption::Random => {
let random_statuses = vec![
*FIGHTER_STATUS_KIND_DOWN,
*FIGHTER_STATUS_KIND_PASSIVE,
*FIGHTER_STATUS_KIND_PASSIVE_FB,
];
let random_status_index =
app::sv_math::rand(hash40("fighter"), random_statuses.len() as i32) as usize;
if random_statuses[random_status_index] != FIGHTER_STATUS_KIND_DOWN {
*status_kind = L2CValue::new_int(random_statuses[random_status_index] as u64);
*unk = L2CValue::new_bool(true);
}
}
TechOption::InPlace => {
*status_kind = L2CValue::new_int(*FIGHTER_STATUS_KIND_PASSIVE as u64);
*unk = L2CValue::new_bool(true);
}
TechOption::Roll => {
*status_kind = L2CValue::new_int(*FIGHTER_STATUS_KIND_PASSIVE_FB as u64);
*unk = L2CValue::new_bool(true);
}
_ => (),
}
return;
}
// Wall Tech
if status_kind_int == FIGHTER_STATUS_KIND_STOP_WALL
|| status_kind_int == FIGHTER_STATUS_KIND_DAMAGE_FLY_REFLECT_LR
{
*status_kind = L2CValue::new_int(*FIGHTER_STATUS_KIND_PASSIVE_WALL as u64);
*unk = L2CValue::new_bool(true);
return;
}
// Ceiling Tech
if status_kind_int == FIGHTER_STATUS_KIND_STOP_CEIL
|| status_kind_int == FIGHTER_STATUS_KIND_DAMAGE_FLY_REFLECT_U
{
*status_kind = L2CValue::new_int(*FIGHTER_STATUS_KIND_PASSIVE_CEIL as u64);
*unk = L2CValue::new_bool(true);
return;
}
}
pub unsafe fn should_perform_defensive_option(
module_accessor: &mut app::BattleObjectModuleAccessor,
prev_status: i32,
@ -101,34 +129,46 @@ pub unsafe fn get_command_flag_cat(
_category: i32,
flag: &mut i32,
) {
if MENU.tech_state != TechOption::None
&& is_training_mode()
&& is_operation_cpu(module_accessor)
{
let prev_status = StatusModule::prev_status_kind(module_accessor, 0) as i32;
let status = StatusModule::status_kind(module_accessor) as i32;
if [
*FIGHTER_STATUS_KIND_DOWN_WAIT,
*FIGHTER_STATUS_KIND_DOWN_WAIT_CONTINUE,
]
.contains(&status)
{
let random_statuses = vec![
*FIGHTER_STATUS_KIND_DOWN_STAND,
*FIGHTER_STATUS_KIND_DOWN_STAND_FB,
*FIGHTER_STATUS_KIND_DOWN_STAND_ATTACK,
];
if !is_training_mode() {
return;
}
let random_status_index =
app::sv_math::rand(hash40("fighter"), random_statuses.len() as i32) as usize;
StatusModule::change_status_request_from_script(
module_accessor,
random_statuses[random_status_index],
false,
);
} else if should_perform_defensive_option(module_accessor, prev_status, status) {
perform_defensive_option(module_accessor, flag);
}
if !is_operation_cpu(module_accessor) {
return;
}
if MENU.tech_state == TechOption::None {
return;
}
let status = StatusModule::status_kind(module_accessor) as i32;
if [
*FIGHTER_STATUS_KIND_DOWN_WAIT,
*FIGHTER_STATUS_KIND_DOWN_WAIT_CONTINUE,
]
.contains(&status)
{
let random_statuses = vec![
*FIGHTER_STATUS_KIND_DOWN_STAND,
*FIGHTER_STATUS_KIND_DOWN_STAND_FB,
*FIGHTER_STATUS_KIND_DOWN_STAND_ATTACK,
];
let random_status_index =
app::sv_math::rand(hash40("fighter"), random_statuses.len() as i32) as usize;
StatusModule::change_status_request_from_script(
module_accessor,
random_statuses[random_status_index],
false,
);
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);
}
}
@ -136,47 +176,66 @@ pub unsafe fn check_button_on(
module_accessor: &mut app::BattleObjectModuleAccessor,
button: i32,
) -> Option<bool> {
if [*CONTROL_PAD_BUTTON_GUARD_HOLD, *CONTROL_PAD_BUTTON_GUARD].contains(&button) {
if is_training_mode() && is_operation_cpu(module_accessor) {
let prev_status = StatusModule::prev_status_kind(module_accessor, 0) as i32;
let status = StatusModule::status_kind(module_accessor) as i32;
if MENU.defensive_state == Defensive::Shield
&& should_perform_defensive_option(module_accessor, prev_status, status)
{
return Some(true);
}
}
if !is_training_mode() {
return None;
}
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,
motion_kind: u64,
) -> Option<u64> {
if MENU.tech_state != TechOption::None
&& is_training_mode()
&& is_operation_cpu(module_accessor)
{
if [hash40("passive_stand_f"), hash40("passive_stand_b")].contains(&motion_kind) {
if app::sv_math::rand(hash40("fighter"), 2) != 0 {
return Some(hash40("passive_stand_f"));
} else {
return Some(hash40("passive_stand_b"));
}
} else if [hash40("down_forward_u"), hash40("down_back_u")].contains(&motion_kind) {
if app::sv_math::rand(hash40("fighter"), 2) != 0 {
return Some(hash40("down_forward_u"));
} else {
return Some(hash40("down_back_u"));
}
} else if [hash40("down_forward_d"), hash40("down_back_d")].contains(&motion_kind) {
if app::sv_math::rand(hash40("fighter"), 2) != 0 {
return Some(hash40("down_forward_d"));
} else {
return Some(hash40("down_back_d"));
}
if !is_training_mode() {
return None;
}
if !is_operation_cpu(module_accessor) {
return None;
}
if MENU.tech_state == TechOption::None {
return None;
}
let random_roll = app::sv_math::rand(hash40("fighter"), 2);
if [hash40("passive_stand_f"), hash40("passive_stand_b")].contains(&motion_kind) {
if random_roll != 0 {
return Some(hash40("passive_stand_f"));
} else {
return Some(hash40("passive_stand_b"));
}
} else if [hash40("down_forward_u"), hash40("down_back_u")].contains(&motion_kind) {
if random_roll != 0 {
return Some(hash40("down_forward_u"));
} else {
return Some(hash40("down_back_u"));
}
} else if [hash40("down_forward_d"), hash40("down_back_d")].contains(&motion_kind) {
if random_roll != 0 {
return Some(hash40("down_forward_d"));
} else {
return Some(hash40("down_back_d"));
}
}