diff --git a/dynamic/src/consts.rs b/dynamic/src/consts.rs index 0fdda0d76a..84db6849cf 100644 --- a/dynamic/src/consts.rs +++ b/dynamic/src/consts.rs @@ -1610,8 +1610,11 @@ pub mod vars { pub mod pitb { pub mod instance { + // ints + pub const SPECIAL_LW_SITUATION_START: i32 = 0x0100; + // flags - pub const SPECIAL_LW_DISABLE_LC: i32 = 0x0100; + pub const SPECIAL_LW_ENABLE_CANCEL: i32 = 0x0100; pub const SPECIAL_LW_DISABLE_STALL: i32 = 0x0101; } } diff --git a/fighters/brave/src/menu.rs b/fighters/brave/src/menu.rs index be926aa32d..4819bc65e8 100644 --- a/fighters/brave/src/menu.rs +++ b/fighters/brave/src/menu.rs @@ -12,8 +12,12 @@ extern "C" { } unsafe fn set_command_for_slot(fighter: &mut BattleObject, slot: usize, id: i32) { - let mana = if !VarModule::is_flag(fighter, vars::brave::instance::SPECIAL_MENU) { get_special_lw_command_sp_cost(fighter.module_accessor, id, false) } else { 0.0 }; - let mana_req = if !VarModule::is_flag(fighter, vars::brave::instance::SPECIAL_MENU) { fighter.get_float(0x53) >= mana } else { true }; + let mana = FighterSpecializer_Brave::get_special_lw_command_sp_cost( + fighter.module_accessor, + FighterBraveSpecialLwCommand{ _address: id as u8 }, + false + ); + let mana_req = fighter.get_float(0x53) >= mana; FighterManager::instance().unwrap().send_event(BraveSetMenuCommand::new( fighter.get_int(*FIGHTER_INSTANCE_WORK_ID_INT_ENTRY_ID) as u32, // ENTRY_ID @@ -104,7 +108,7 @@ pub unsafe fn roll_spells(fighter: &mut BattleObject, vals: &mut Vec) { continue; } } - + vals.push(val); if vals.len() >= 4 { break; @@ -166,7 +170,7 @@ pub unsafe extern "C" fn hero_rng_hook_impl(fighter: &mut BattleObject) { break; } } - + set_command_for_slot(fighter, 0, rand);/*0x14);*/ set_command_for_slot(fighter, 1, rand);/*0xB);*/ set_command_for_slot(fighter, 2, rand);/*0xA);*/ @@ -175,7 +179,7 @@ pub unsafe extern "C" fn hero_rng_hook_impl(fighter: &mut BattleObject) { else { let mut vals = vec![]; roll_spells(fighter, &mut vals); - + set_command_for_slot(fighter, 0, vals[0]); set_command_for_slot(fighter, 1, vals[1]); set_command_for_slot(fighter, 2, vals[2]); @@ -202,4 +206,4 @@ pub unsafe extern "C" fn hero_rng_hook_impl(fighter: &mut BattleObject) { fighter.get_int(*FIGHTER_INSTANCE_WORK_ID_INT_ENTRY_ID) as u32, (index as u32) + 1 )); -} \ No newline at end of file +} diff --git a/fighters/brave/src/status/special_lw.rs b/fighters/brave/src/status/special_lw.rs index 804a013d73..f58fcb5588 100644 --- a/fighters/brave/src/status/special_lw.rs +++ b/fighters/brave/src/status/special_lw.rs @@ -286,7 +286,7 @@ unsafe extern "C" fn special_lw_select_main_loop(fighter: &mut L2CFighterCommon) fighter.change_status(FIGHTER_BRAVE_STATUS_KIND_SPECIAL_LW_CANCEL.into(), false.into()); } } - + return 1.into(); } if fighter.is_cat_flag(Cat1::JumpButton) @@ -347,10 +347,10 @@ unsafe extern "C" fn special_lw_select_main_loop(fighter: &mut L2CFighterCommon) return 0.into(); } -unsafe extern "C" fn brave_special_check_sp_set_flag(fighter: &mut L2CFighterCommon, sp_cost: i32, success: i32) -> bool { +unsafe extern "C" fn brave_special_check_sp_set_flag(fighter: &mut L2CFighterCommon, sp_cost: f32, success: i32) -> bool { let sp = fighter.get_float(*FIGHTER_BRAVE_INSTANCE_WORK_ID_FLOAT_SP); let max_sp = fighter.get_float(*FIGHTER_BRAVE_INSTANCE_WORK_ID_FLOAT_MAX_SP); - if sp_cost as f32 <= sp { + if sp_cost <= sp { fighter.on_flag(success); return true; } @@ -372,7 +372,7 @@ unsafe extern "C" fn special_lw_exit(fighter: &mut L2CFighterCommon) -> L2CValue if interrupt == *FIGHTER_BRAVE_STATUS_KIND_SPECIAL_LW_SELECT { return 0.into(); } - + let handle = VarModule::get_int(fighter.battle_object, vars::brave::instance::MENU_ICON_EFFECT_HANDLE); if interrupt == *FIGHTER_BRAVE_STATUS_KIND_SPECIAL_LW_START || interrupt == *FIGHTER_BRAVE_STATUS_KIND_SPECIAL_LW_STEEL_START { @@ -382,7 +382,7 @@ unsafe extern "C" fn special_lw_exit(fighter: &mut L2CFighterCommon) -> L2CValue EffectModule::kill(fighter.module_accessor, handle as u32, true, true); } VarModule::set_int(fighter.battle_object, vars::brave::instance::MENU_ICON_EFFECT_HANDLE, -1); - + return 0.into(); } @@ -514,4 +514,4 @@ pub fn install(agent: &mut Agent) { agent.status(Main, *FIGHTER_BRAVE_STATUS_KIND_SPECIAL_LW_STEEL_START, special_lw_steel_start_main); agent.status(Pre, *FIGHTER_BRAVE_STATUS_KIND_SPECIAL_LW_FAILURE, special_lw_failure_pre); -} \ No newline at end of file +} diff --git a/fighters/common/src/function_hooks/fighterspecializer/brave.rs b/fighters/common/src/function_hooks/fighterspecializer/brave.rs index 898d14fbdf..e73c102b26 100644 --- a/fighters/common/src/function_hooks/fighterspecializer/brave.rs +++ b/fighters/common/src/function_hooks/fighterspecializer/brave.rs @@ -15,4 +15,4 @@ pub fn install() { skyline::install_hooks!( get_special_lw_command_sp_cost ); -} \ No newline at end of file +} diff --git a/fighters/pitb/src/acmd/ground.rs b/fighters/pitb/src/acmd/ground.rs index cc78202dcb..4b4365e3d9 100644 --- a/fighters/pitb/src/acmd/ground.rs +++ b/fighters/pitb/src/acmd/ground.rs @@ -8,9 +8,9 @@ unsafe extern "C" fn game_attack11(agent: &mut L2CAgentBase) { frame(lua_state, 5.0); FT_MOTION_RATE_RANGE(agent, 5.0, 5.5, 1.0); if is_excute(agent) { - hitbox!(agent, { extends: PITB_SWORD_HITBOX_S, id: 0, bone: "armr", dmg: 3.0, angle: 80, kbg: 40, bkb: 10, size: 3.0, x: 2.0, y: 0.0, z: 0.0, facing: LrCheck::F, situation: CollisionSituation::GA_d, }); - hitbox!(agent, { extends: PITB_SWORD_HITBOX_S, id: 1, bone: "bowr", dmg: 3.0, angle: 80, kbg: 40, bkb: 10, size: 3.0, x: 0.0, y: 2.0, z: 0.0, facing: LrCheck::F, situation: CollisionSituation::GA_d, }); - hitbox!(agent, { extends: PITB_SWORD_HITBOX_S, id: 2, bone: "bowr", dmg: 3.0, angle: 80, kbg: 40, bkb: 10, size: 3.0, x: 0.0, y: 7.0, z: 0.0, facing: LrCheck::F, situation: CollisionSituation::GA_d, }); + hitbox!(agent, { extends: PITB_SWORD_HITBOX_S, id: 0, bone: "armr", dmg: 3.0, angle: 74, kbg: 60, bkb: 20, size: 3.0, x: 2.0, y: 0.0, z: 0.0, facing: LrCheck::F, situation: CollisionSituation::GA_d, }); + hitbox!(agent, { extends: PITB_SWORD_HITBOX_S, id: 1, bone: "bowr", dmg: 3.0, angle: 74, kbg: 60, bkb: 20, size: 3.0, x: 0.0, y: 2.0, z: 0.0, facing: LrCheck::F, situation: CollisionSituation::GA_d, }); + hitbox!(agent, { extends: PITB_SWORD_HITBOX_S, id: 2, bone: "bowr", dmg: 3.0, angle: 74, kbg: 60, bkb: 20, size: 3.0, x: 0.0, y: 7.0, z: 0.0, facing: LrCheck::F, situation: CollisionSituation::GA_d, }); // Jab lock hitboxes hitbox!(agent, { extends: PITB_SWORD_HITBOX_S, id: 3, bone: "armr", dmg: 3.0, angle: 361, kbg: 15, bkb: 30, size: 3.0, x: 2.0, y: 0.0, z: 0.0, facing: LrCheck::F, situation: CollisionSituation::G, }); hitbox!(agent, { extends: PITB_SWORD_HITBOX_S, id: 4, bone: "bowr", dmg: 3.0, angle: 361, kbg: 15, bkb: 30, size: 3.0, x: 0.0, y: 2.0, z: 0.0, facing: LrCheck::F, situation: CollisionSituation::G, }); @@ -49,12 +49,16 @@ unsafe extern "C" fn effect_attack11(agent: &mut L2CAgentBase) { unsafe extern "C" fn game_attack12(agent: &mut L2CAgentBase) { let lua_state = agent.lua_state_agent; let boma = agent.boma(); + frame(lua_state, 1.0); + FT_MOTION_RATE_RANGE(agent, 1.0, 4.0, 1.0); + frame(lua_state, 4.0); + FT_MOTION_RATE(agent, 1.0); frame(lua_state, 5.0); FT_MOTION_RATE_RANGE(agent, 5.0, 5.5, 1.0); if is_excute(agent) { - hitbox!(agent, { extends: PITB_SWORD_HITBOX_S, id: 0, bone: "arml", dmg: 3.0, angle: 60, kbg: 40, fkb: 70, bkb: 0, size: 3.0, x: 2.0, y: 0.0, z: 0.0, facing: LrCheck::F, situation: CollisionSituation::GA_d, }); - hitbox!(agent, { extends: PITB_SWORD_HITBOX_S, id: 1, bone: "bowl", dmg: 3.0, angle: 90, kbg: 40, fkb: 70, bkb: 0, size: 3.2, x: 0.0, y: -2.0, z: 0.0, facing: LrCheck::F, situation: CollisionSituation::GA_d, }); - hitbox!(agent, { extends: PITB_SWORD_HITBOX_S, id: 2, bone: "bowl", dmg: 3.0, angle: 145, kbg: 40, fkb: 85, bkb: 0, size: 3.2, x: 0.0, y: -7.0, z: 0.0, facing: LrCheck::F, situation: CollisionSituation::GA_d, }); + hitbox!(agent, { extends: PITB_SWORD_HITBOX_S, id: 0, bone: "arml", dmg: 3.0, angle: 80, kbg: 60, bkb: 20, size: 3.0, x: 2.0, y: 0.0, z: 0.0, facing: LrCheck::F, situation: CollisionSituation::GA_d, }); + hitbox!(agent, { extends: PITB_SWORD_HITBOX_S, id: 1, bone: "bowl", dmg: 3.0, angle: 80, kbg: 60, bkb: 20, size: 3.2, x: 0.0, y: -2.0, z: 0.0, facing: LrCheck::F, situation: CollisionSituation::GA_d, }); + hitbox!(agent, { extends: PITB_SWORD_HITBOX_S, id: 2, bone: "bowl", dmg: 3.0, angle: 80, kbg: 60, bkb: 20, size: 3.2, x: 0.0, y: -7.0, z: 0.0, facing: LrCheck::F, situation: CollisionSituation::GA_d, }); // Jab lock hitboxes hitbox!(agent, { extends: PITB_SWORD_HITBOX_S, id: 3, bone: "arml", dmg: 3.0, angle: 361, kbg: 15, bkb: 30, size: 3.0, x: 2.0, y: 0.0, z: 0.0, facing: LrCheck::F, situation: CollisionSituation::G, }); hitbox!(agent, { extends: PITB_SWORD_HITBOX_S, id: 4, bone: "bowl", dmg: 3.0, angle: 361, kbg: 15, bkb: 30, size: 3.2, x: 0.0, y: -2.0, z: 0.0, facing: LrCheck::F, situation: CollisionSituation::G, }); diff --git a/fighters/pitb/src/acmd/specials.rs b/fighters/pitb/src/acmd/specials.rs index 53f33ce655..a73017a325 100644 --- a/fighters/pitb/src/acmd/specials.rs +++ b/fighters/pitb/src/acmd/specials.rs @@ -144,21 +144,22 @@ unsafe extern "C" fn game_speciallwstart(agent: &mut L2CAgentBase) { let lua_state = agent.lua_state_agent; let boma = agent.boma(); frame(lua_state, 1.0); - FT_MOTION_RATE_RANGE(agent, 1.0, 6.0, 3.0); - frame(lua_state, 6.0); - FT_MOTION_RATE_RANGE(agent, 6.0, 6.9, 1.0); if is_excute(agent) { shield!(agent, *MA_MSC_CMD_SHIELD_ON, *COLLISION_KIND_REFLECTOR, 0, *FIGHTER_PIT_REFLECTOR_GROUP_SPECIAL_LW); shield!(agent, *MA_MSC_CMD_SHIELD_ON, *COLLISION_KIND_REFLECTOR, 1, *FIGHTER_PIT_REFLECTOR_GROUP_SPECIAL_LW); } + FT_MOTION_RATE_RANGE(agent, 1.0, 6.9, 1.0); frame(lua_state, 6.9); FT_MOTION_RATE_RANGE(agent, 6.9, 7.0, 3.0); if is_excute(agent) { - hitbox!(agent, { extends: BASE_HITBOX, id: 0, bone: "top", dmg: 5.0, angle: 24, kbg: 100, fkb: 40, bkb: 0, set_weight: true, size: 7.5, x: 0.0, y: 7.0, z: -1.5, x2: 0.0, y2: 7.0, z2: 1.5, hitlag: 1.0, sdi: 1.15, clank: SetOff::Off, effect: "collision_attr_magic", sound_level: SoundLevel::M, hit_sound: CollisionSound::Magic, region: AttackRegion::None, }); + hitbox!(agent, { extends: BASE_HITBOX, id: 0, bone: "top", dmg: 5.0, angle: 361, kbg: 100, fkb: 80, bkb: 0, set_weight: true, size: 7.5, x: 0.0, y: 7.0, z: -1.5, x2: 0.0, y2: 7.0, z2: 1.5, hitlag: 1.0, sdi: 1.15, clank: SetOff::Off, effect: "collision_attr_magic", sound_level: SoundLevel::M, hit_sound: CollisionSound::Magic, region: AttackRegion::None, }); } frame(lua_state, 6.933); if is_excute(agent) { AttackModule::clear_all(boma); + // enables slideoff + VarModule::on_flag(agent.battle_object, vars::pitb::instance::SPECIAL_LW_ENABLE_CANCEL); + agent.ground_correct_by_situation(*GROUND_CORRECT_KIND_GROUND, *GROUND_CORRECT_KIND_AIR); } frame(lua_state, 7.0); FT_MOTION_RATE(agent, 1.0); @@ -198,6 +199,8 @@ unsafe extern "C" fn game_speciallwhold(agent: &mut L2CAgentBase) { shield!(agent, *MA_MSC_CMD_SHIELD_ON, *COLLISION_KIND_REFLECTOR, 0, *FIGHTER_PIT_REFLECTOR_GROUP_SPECIAL_LW); shield!(agent, *MA_MSC_CMD_SHIELD_ON, *COLLISION_KIND_REFLECTOR, 1, *FIGHTER_PIT_REFLECTOR_GROUP_SPECIAL_LW); VarModule::on_flag(agent.battle_object, vars::common::status::DISABLE_ECB_SHIFT); + // enables slideoff + agent.ground_correct_by_situation(*GROUND_CORRECT_KIND_GROUND, *GROUND_CORRECT_KIND_AIR); } } diff --git a/fighters/pitb/src/opff.rs b/fighters/pitb/src/opff.rs index aca52fdad7..b82bb4cebd 100644 --- a/fighters/pitb/src/opff.rs +++ b/fighters/pitb/src/opff.rs @@ -10,48 +10,37 @@ unsafe fn bow_lc(boma: &mut BattleObjectModuleAccessor) { } } -unsafe fn guardian_orbitar(fighter: &mut L2CFighterCommon) { - // happens on init - if fighter.is_status_one_of(&[ - *FIGHTER_STATUS_KIND_SPECIAL_LW, - ]) - && StatusModule::is_changing(fighter.module_accessor) { - if !VarModule::is_flag(fighter.battle_object, vars::pitb::instance::SPECIAL_LW_DISABLE_STALL) { - sv_kinetic_energy!( - set_speed, - fighter, - FIGHTER_KINETIC_ENERGY_ID_GRAVITY, - 0.0 - ); - sv_kinetic_energy!( - set_accel, - fighter, - FIGHTER_KINETIC_ENERGY_ID_GRAVITY, - 0.0 - ); - } - VarModule::off_flag(fighter.battle_object, vars::pitb::instance::SPECIAL_LW_DISABLE_LC); - VarModule::on_flag(fighter.battle_object, vars::pitb::instance::SPECIAL_LW_DISABLE_STALL); - } - +unsafe fn dspecial_cancel(fighter: &mut L2CFighterCommon) { // happens on main for all statuses if fighter.is_status_one_of(&[ *FIGHTER_STATUS_KIND_SPECIAL_LW, *FIGHTER_PIT_STATUS_KIND_SPECIAL_LW_HOLD, *FIGHTER_PIT_STATUS_KIND_SPECIAL_LW_END, ]) { + let situation_kind = fighter.global_table[SITUATION_KIND].get_i32(); + // disable land cancel on parry if AttackModule::is_infliction_status(fighter.module_accessor, *COLLISION_KIND_MASK_PARRY) { - VarModule::on_flag(fighter.battle_object, vars::pitb::instance::SPECIAL_LW_DISABLE_LC); + // prevents slideoffs + VarModule::off_flag(fighter.battle_object, vars::pitb::instance::SPECIAL_LW_ENABLE_CANCEL); + fighter.ground_correct_by_situation(*GROUND_CORRECT_KIND_GROUND_CLIFF_STOP_ATTACK, *GROUND_CORRECT_KIND_AIR); + + // ends the attack early if !fighter.is_status(*FIGHTER_PIT_STATUS_KIND_SPECIAL_LW_END) && !fighter.is_in_hitlag() { fighter.change_status(FIGHTER_PIT_STATUS_KIND_SPECIAL_LW_END.into(), false.into()); } } - // land cancel - if !VarModule::is_flag(fighter.battle_object, vars::pitb::instance::SPECIAL_LW_DISABLE_LC) { - fighter.check_land_cancel(None); + // cancel the attack when situation changes + if situation_kind != VarModule::get_int(fighter.battle_object, vars::pitb::instance::SPECIAL_LW_SITUATION_START) + && VarModule::is_flag(fighter.battle_object, vars::pitb::instance::SPECIAL_LW_ENABLE_CANCEL) { + if situation_kind == *SITUATION_KIND_GROUND { + // we don't use check_land_cancel because the transition is defered until the hitbox comes out + fighter.change_status(FIGHTER_STATUS_KIND_LANDING.into(), false.into()); + } else { + fighter.change_status(FIGHTER_STATUS_KIND_FALL.into(), false.into()); + } } } } @@ -75,7 +64,7 @@ extern "Rust" { pub unsafe fn moveset(fighter: &mut L2CFighterCommon, boma: &mut BattleObjectModuleAccessor, id: usize, cat: [i32 ; 4], status_kind: i32, situation_kind: i32, motion_kind: u64, stick_x: f32, stick_y: f32, facing: f32, frame: f32) { bow_lc(boma); - guardian_orbitar(fighter); + dspecial_cancel(fighter); electroshock_land_cancel_on_hit(fighter); pits_common(fighter, boma, status_kind); } diff --git a/fighters/pitb/src/status/mod.rs b/fighters/pitb/src/status/mod.rs index 7c677edc4c..2085a8b7aa 100644 --- a/fighters/pitb/src/status/mod.rs +++ b/fighters/pitb/src/status/mod.rs @@ -3,6 +3,7 @@ use globals::*; // status script import mod special_hi; +mod special_lw; mod special_n; unsafe extern "C" fn change_status_callback(fighter: &mut L2CFighterCommon) -> L2CValue { @@ -21,5 +22,6 @@ unsafe extern "C" fn on_start(fighter: &mut L2CFighterCommon) { pub fn install(agent: &mut Agent) { agent.on_start(on_start); special_hi::install(agent); + special_lw::install(agent); special_n::install(agent); } \ No newline at end of file diff --git a/fighters/pitb/src/status/special_lw.rs b/fighters/pitb/src/status/special_lw.rs new file mode 100644 index 0000000000..1a83ba2ccb --- /dev/null +++ b/fighters/pitb/src/status/special_lw.rs @@ -0,0 +1,33 @@ +use super::*; + +// FIGHTER_STATUS_KIND_SPECIAL_LW + +unsafe extern "C" fn special_lw_main(fighter: &mut L2CFighterCommon) -> L2CValue { + + let ret = smashline::original_status(Main, fighter, *FIGHTER_STATUS_KIND_SPECIAL_LW)(fighter); + + let situation_kind = fighter.global_table[SITUATION_KIND].get_i32(); + VarModule::set_int(fighter.battle_object, vars::pitb::instance::SPECIAL_LW_SITUATION_START, situation_kind); + VarModule::off_flag(fighter.battle_object, vars::pitb::instance::SPECIAL_LW_ENABLE_CANCEL); + if !VarModule::is_flag(fighter.battle_object, vars::pitb::instance::SPECIAL_LW_DISABLE_STALL) { + sv_kinetic_energy!( + set_speed, + fighter, + FIGHTER_KINETIC_ENERGY_ID_GRAVITY, + 0.0 + ); + sv_kinetic_energy!( + set_accel, + fighter, + FIGHTER_KINETIC_ENERGY_ID_GRAVITY, + 0.0 + ); + } + VarModule::on_flag(fighter.battle_object, vars::pitb::instance::SPECIAL_LW_DISABLE_STALL); + + ret +} + +pub fn install(agent: &mut Agent) { + agent.status(Main, *FIGHTER_STATUS_KIND_SPECIAL_LW, special_lw_main); +} \ No newline at end of file diff --git a/fighters/robot/src/status/item_shoot_air.rs b/fighters/robot/src/status/item_shoot_air.rs new file mode 100644 index 0000000000..4af4578537 --- /dev/null +++ b/fighters/robot/src/status/item_shoot_air.rs @@ -0,0 +1,9 @@ +use super::*; + +unsafe extern "C" fn item_shoot_air_pre(fighter: &mut L2CFighterCommon) -> L2CValue { + fighter.status_pre_ItemShootAir_New() +} // remove vanilla rob up b -> attack mechanics + +pub fn install(agent: &mut Agent) { + agent.status(Pre, *FIGHTER_STATUS_KIND_ITEM_SHOOT_AIR, item_shoot_air_pre); +} diff --git a/fighters/robot/src/status/item_throw.rs b/fighters/robot/src/status/item_throw.rs new file mode 100644 index 0000000000..c7f106ffb6 --- /dev/null +++ b/fighters/robot/src/status/item_throw.rs @@ -0,0 +1,9 @@ +use super::*; + +unsafe extern "C" fn item_throw_pre(fighter: &mut L2CFighterCommon) -> L2CValue { + fighter.status_pre_ItemThrow() +} // remove vanilla rob up b -> attack mechanics + +pub fn install(agent: &mut Agent) { + agent.status(Pre, *FIGHTER_STATUS_KIND_ITEM_THROW, item_throw_pre); +} diff --git a/fighters/robot/src/status/mod.rs b/fighters/robot/src/status/mod.rs index 1fe7456a35..4028f0b347 100644 --- a/fighters/robot/src/status/mod.rs +++ b/fighters/robot/src/status/mod.rs @@ -3,11 +3,19 @@ use globals::*; // status script import mod attack_air; + mod special_s; mod special_hi; +mod item_throw; +mod item_shoot_air; + pub fn install(agent: &mut Agent) { attack_air::install(agent); + special_s::install(agent); special_hi::install(agent); + + item_throw::install(agent); + item_shoot_air::install(agent); }