mirror of
https://github.com/jugeeya/UltimateTrainingModpack.git
synced 2024-11-20 00:46:34 +00:00
Buffing (#297)
* continued testing * Scuffed Acceleratle Implementation * Cleanup and Groundwork, Only Accel * Wii Fit complete, Joker, Hero and Cloud WIP. * Preparing for multiple spells * Implemented Multi Buffing * Cloud Hook, Hero Improvements * Nearly complete, still messing around with KO Punch * Works for both fighters now * Add buff icon * Wii Fit sound cut, Sepiroth darken fixed * Cleanup * Fix Hero Screen Shake * Clean up buff a bit more * slight clean up * Update README.md Add Buff Options info/file
This commit is contained in:
parent
35a80f83c5
commit
b598aaeee2
9 changed files with 431 additions and 2 deletions
|
@ -115,6 +115,7 @@ When multiple options are selected, one of the selected options will be chosen a
|
|||
| Throw Options | Throw to be performed when a grab is landed | None, Forward Throw, Back Throw, Up Throw, Down Throw |
|
||||
| Throw Delay | How many frames to delay the throw option | 0 to 150 frames (2.5 seconds) in increments of 5 frames |
|
||||
| Pummel Delay | How many frames after a grab to wait before starting to pummel | 0 to 150 frames (2.5 seconds) in increments of 5 frames |
|
||||
| Buff Options | Buffs to be applied to respective character when loading save states | Acceleratle, Oomph, Psyche Up, Bounce, Arsene, Deep Breathing, Limit Break, KO Punch, One-Winged Angel |
|
||||
| Input Delay | Frames to delay player inputs by | 0 to 10 frames (0.167 seconds) |
|
||||
| Save Damage | Should save states retain player/CPU damage | Yes, No |
|
||||
| Hitbox Visualization | Should hitboxes be displayed, hiding other visual effects | Yes, No |
|
||||
|
@ -144,6 +145,7 @@ SD Card Root
|
|||
│ ├── aerial_delay.svg
|
||||
│ ├── air_dodge_dir.svg
|
||||
│ ├── attack_angle.svg
|
||||
│ ├── buff_state.svg
|
||||
│ ├── check.svg
|
||||
│ ├── defensive_state.svg
|
||||
│ ├── di_state.svg
|
||||
|
@ -231,4 +233,4 @@ To build the entire modpack including supporting files, use the steps in [`full_
|
|||
|
||||
## Prerequisites
|
||||
- Stable Rust environment with [cargo-skyline](https://github.com/jam1garner/cargo-skyline)
|
||||
- [DEVKITPRO](https://devkitpro.org/wiki/Getting_Started) `switch-dev` installation
|
||||
- [DEVKITPRO](https://devkitpro.org/wiki/Getting_Started) `switch-dev` installation
|
||||
|
|
|
@ -502,6 +502,56 @@ impl ThrowOption {
|
|||
|
||||
extra_bitflag_impls! {ThrowOption}
|
||||
|
||||
// Buff Option
|
||||
bitflags! {
|
||||
pub struct BuffOption : u32
|
||||
{
|
||||
const ACCELERATLE = 0x1;
|
||||
const OOMPH = 0x2;
|
||||
const PSYCHE = 0x4;
|
||||
const BOUNCE = 0x8;
|
||||
const ARSENE = 0x10;
|
||||
const BREATHING = 0x20;
|
||||
const LIMIT = 0x40;
|
||||
const KO = 0x80;
|
||||
const WING = 0x100;
|
||||
}
|
||||
}
|
||||
|
||||
impl BuffOption {
|
||||
pub fn into_int(self) -> Option<i32> {
|
||||
Some(match self {
|
||||
BuffOption::ACCELERATLE => *FIGHTER_BRAVE_SPECIAL_LW_COMMAND11_SPEED_UP,
|
||||
BuffOption::OOMPH => *FIGHTER_BRAVE_SPECIAL_LW_COMMAND12_ATTACK_UP,
|
||||
BuffOption::PSYCHE => *FIGHTER_BRAVE_SPECIAL_LW_COMMAND21_CHARGE,
|
||||
BuffOption::BOUNCE => *FIGHTER_BRAVE_SPECIAL_LW_COMMAND13_REFLECT,
|
||||
BuffOption::BREATHING => 1,
|
||||
BuffOption::ARSENE => 1,
|
||||
BuffOption::LIMIT => 1,
|
||||
BuffOption::KO => 1,
|
||||
BuffOption::WING => 1,
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
|
||||
fn as_str(self) -> Option<&'static str> {
|
||||
Some(match self {
|
||||
BuffOption::ACCELERATLE => "Acceleratle",
|
||||
BuffOption::OOMPH => "Oomph",
|
||||
BuffOption::BOUNCE => "Bounce",
|
||||
BuffOption::PSYCHE => "Psyche Up",
|
||||
BuffOption::BREATHING => "Deep Breathing",
|
||||
BuffOption::ARSENE => "Arsene",
|
||||
BuffOption::LIMIT => "Limit Break",
|
||||
BuffOption::KO => "KO Punch",
|
||||
BuffOption::WING => "One-Winged Angel",
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
extra_bitflag_impls! {BuffOption}
|
||||
|
||||
impl Delay {
|
||||
pub fn as_str(self) -> Option<&'static str> {
|
||||
Some(match self {
|
||||
|
@ -836,6 +886,7 @@ url_params! {
|
|||
pub throw_state: ThrowOption,
|
||||
pub throw_delay: MedDelay,
|
||||
pub pummel_delay: MedDelay,
|
||||
pub buff_state: BuffOption,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -886,6 +937,7 @@ impl TrainingModpackMenu {
|
|||
throw_state = ThrowOption::from_bits(val),
|
||||
throw_delay = MedDelay::from_bits(val),
|
||||
pummel_delay = MedDelay::from_bits(val),
|
||||
buff_state = BuffOption::from_bits(val),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -503,6 +503,13 @@ pub unsafe fn write_menu() {
|
|||
MedDelay,
|
||||
"Pummel Delay: How many frames after a grab to wait before starting to pummel"
|
||||
);
|
||||
add_bitflag_submenu!(
|
||||
overall_menu,
|
||||
"Buff Options",
|
||||
buff_state,
|
||||
BuffOption,
|
||||
"Buff Options: Buff(s) to be applied to respective character when loading save states"
|
||||
);
|
||||
|
||||
// Slider menus
|
||||
overall_menu.add_sub_menu(
|
||||
|
|
|
@ -42,6 +42,7 @@ pub static BASE_MENU: consts::TrainingModpackMenu = consts::TrainingModpackMenu
|
|||
throw_state: ThrowOption::NONE,
|
||||
throw_delay: MedDelay::empty(),
|
||||
pummel_delay: MedDelay::empty(),
|
||||
buff_state: BuffOption::empty(),
|
||||
};
|
||||
|
||||
pub static mut DEFAULT_MENU: TrainingModpackMenu = BASE_MENU;
|
||||
|
|
82
src/templates/buff_state.svg
Normal file
82
src/templates/buff_state.svg
Normal file
|
@ -0,0 +1,82 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="80.0px"
|
||||
height="80.0px"
|
||||
viewBox="0 0 80.0 80.0"
|
||||
version="1.1"
|
||||
id="SVGRoot"
|
||||
sodipodi:docname="buff_state.svg"
|
||||
inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<defs
|
||||
id="defs5503" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#000000"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="8"
|
||||
inkscape:cx="52.625"
|
||||
inkscape:cy="33.6875"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
inkscape:document-rotation="0"
|
||||
showgrid="true"
|
||||
inkscape:window-width="1431"
|
||||
inkscape:window-height="1041"
|
||||
inkscape:window-x="256"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:pagecheckerboard="1">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid6073"
|
||||
spacingx="0.1"
|
||||
spacingy="0.1" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata5506">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<g
|
||||
id="g243"
|
||||
style="fill:#ffffea;fill-opacity:1"
|
||||
transform="matrix(0.54490954,0,0,-0.44245854,-24.388508,217.32339)">
|
||||
<g
|
||||
id="g245"
|
||||
style="fill:#ffffea;fill-opacity:1">
|
||||
<g
|
||||
id="g251"
|
||||
style="fill:#ffffea;fill-opacity:1">
|
||||
<g
|
||||
id="g253"
|
||||
style="fill:#ffffea;fill-opacity:1">
|
||||
<path
|
||||
d="m 58.348,376.03 c 3.332,-50.936 45.698,-55.695 45.698,-55.695 v 0 c -36.178,20.944 -24.437,58.551 -1.666,79.495 v 0 c 13.625,12.533 9.71,21.5 9.313,22.314 v 0 c 7.57,-14.95 1.868,-19.957 -2.411,-37.546 v 0 c -4.284,-17.614 6.188,-36.178 17.613,-33.44 v 0 c 11.424,2.737 5.95,17.969 5.95,17.969 v 0 c 26.419,-26.896 0.952,-44.746 0.952,-44.746 v 0 c 0,0 39.034,10.948 42.604,47.365 v 0 c 3.571,36.415 -25.705,51.411 -25.705,51.411 v 0 c 9.758,-8.093 9.283,-23.327 -1.904,-24.279 v 0 c -11.187,-0.951 -18.089,3.333 -10.71,35.464 v 0 c 7.378,32.132 -34.036,50.457 -34.036,50.457 v 0 C 124.039,438.387 55.015,426.963 58.348,376.03 m 53.314,46.174 c 0,0 0,0 0,0 v 0 c 0,0 0,0 0,0"
|
||||
style="fill:#ffffea;stroke:none;fill-opacity:1"
|
||||
id="path267" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.9 KiB |
220
src/training/buff.rs
Normal file
220
src/training/buff.rs
Normal file
|
@ -0,0 +1,220 @@
|
|||
use crate::common::consts::*;
|
||||
use crate::common::*;
|
||||
use smash::app::{self, lua_bind::*};
|
||||
use smash::lib::lua_const::*;
|
||||
use crate::training::handle_add_limit;
|
||||
use crate::training::frame_counter;
|
||||
use crate::is_operation_cpu;
|
||||
|
||||
static mut BUFF_DELAY_COUNTER: usize = 0;
|
||||
|
||||
static mut BUFF_REMAINING_PLAYER: i32 = 0;
|
||||
static mut BUFF_REMAINING_CPU: i32 = 0;
|
||||
|
||||
static mut IS_BUFFING_PLAYER: bool = false;
|
||||
static mut IS_BUFFING_CPU: bool = false;
|
||||
|
||||
pub fn init() {
|
||||
unsafe {
|
||||
BUFF_DELAY_COUNTER = frame_counter::register_counter();
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn restart_buff(module_accessor: &mut app::BattleObjectModuleAccessor) {
|
||||
if is_operation_cpu(module_accessor) {
|
||||
IS_BUFFING_CPU = false;
|
||||
return;
|
||||
}
|
||||
IS_BUFFING_PLAYER = false;
|
||||
}
|
||||
|
||||
pub unsafe fn start_buff(module_accessor: &mut app::BattleObjectModuleAccessor) {
|
||||
if is_operation_cpu(module_accessor) {
|
||||
IS_BUFFING_CPU = true;
|
||||
return;
|
||||
}
|
||||
IS_BUFFING_PLAYER = true;
|
||||
}
|
||||
|
||||
pub unsafe fn is_buffing(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
|
||||
if is_operation_cpu(module_accessor) {
|
||||
return IS_BUFFING_CPU;
|
||||
}
|
||||
return IS_BUFFING_PLAYER;
|
||||
}
|
||||
|
||||
pub unsafe fn set_buff_rem(module_accessor: &mut app::BattleObjectModuleAccessor, new_value: i32) {
|
||||
if is_operation_cpu(module_accessor) {
|
||||
BUFF_REMAINING_CPU = new_value;
|
||||
return;
|
||||
}
|
||||
BUFF_REMAINING_PLAYER = new_value;
|
||||
}
|
||||
|
||||
pub unsafe fn get_buff_rem(module_accessor: &mut app::BattleObjectModuleAccessor) -> i32 {
|
||||
if is_operation_cpu(module_accessor) {
|
||||
return BUFF_REMAINING_CPU;
|
||||
}
|
||||
return BUFF_REMAINING_PLAYER;
|
||||
}
|
||||
|
||||
fn get_spell_vec() -> Vec<BuffOption> {
|
||||
unsafe {
|
||||
let menu_buff = MENU.buff_state.to_vec();
|
||||
let menu_iter = menu_buff.iter();
|
||||
let mut spell_buff: Vec<BuffOption> = Vec::new();
|
||||
for buff in menu_iter {
|
||||
if buff.into_int().unwrap_or(1) != 1 {
|
||||
// all non-spells into_int as 1
|
||||
spell_buff.push(*buff);
|
||||
}
|
||||
}
|
||||
return spell_buff;
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn handle_buffs(module_accessor: &mut app::BattleObjectModuleAccessor, fighter_kind: i32, status: i32, percent: f32) -> bool {
|
||||
SoundModule::stop_all_sound(module_accessor); // silences buff sfx other than KO Punch
|
||||
ControlModule::stop_rumble(module_accessor, false);
|
||||
MotionAnimcmdModule::set_sleep(module_accessor, false);
|
||||
|
||||
let menu_vec = MENU.buff_state.to_vec();
|
||||
|
||||
if fighter_kind == *FIGHTER_KIND_BRAVE {
|
||||
return buff_hero(module_accessor,status);
|
||||
} else if fighter_kind == *FIGHTER_KIND_JACK && menu_vec.contains(&BuffOption::ARSENE) {
|
||||
return buff_joker(module_accessor);
|
||||
} else if fighter_kind == *FIGHTER_KIND_WIIFIT && menu_vec.contains(&BuffOption::BREATHING) {
|
||||
return buff_wiifit(module_accessor,status);
|
||||
} else if fighter_kind == *FIGHTER_KIND_CLOUD && menu_vec.contains(&BuffOption::LIMIT) {
|
||||
return buff_cloud(module_accessor);
|
||||
} else if fighter_kind == *FIGHTER_KIND_LITTLEMAC && menu_vec.contains(&BuffOption::KO) {
|
||||
return buff_mac(module_accessor);
|
||||
} else if fighter_kind == *FIGHTER_KIND_EDGE && menu_vec.contains(&BuffOption::WING) {
|
||||
return buff_sepiroth(module_accessor, percent);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
unsafe fn buff_hero(module_accessor: &mut app::BattleObjectModuleAccessor, status: i32) -> bool {
|
||||
let buff_vec = get_spell_vec();
|
||||
if !is_buffing(module_accessor) {
|
||||
// Initial set up for spells
|
||||
start_buff(module_accessor);
|
||||
set_buff_rem(module_accessor,buff_vec.len() as i32);
|
||||
// Since it's the first step of buffing, we need to set up how many buffs there are
|
||||
}
|
||||
if get_buff_rem(module_accessor) <= 0 {
|
||||
// If there are no buffs selected/left, we're done
|
||||
return true;
|
||||
}
|
||||
buff_hero_single(module_accessor, status, buff_vec);
|
||||
return false;
|
||||
}
|
||||
|
||||
unsafe fn buff_hero_single(module_accessor: &mut app::BattleObjectModuleAccessor, status: i32, buff_vec: Vec<BuffOption>) {
|
||||
let prev_status_kind = StatusModule::prev_status_kind(module_accessor, 0);
|
||||
if prev_status_kind == FIGHTER_BRAVE_STATUS_KIND_SPECIAL_LW_START {
|
||||
// If we just applied a buff successfully, subtract from buffs remaining
|
||||
let new_rem_value = get_buff_rem(module_accessor) - 1;
|
||||
set_buff_rem(module_accessor, new_rem_value);
|
||||
}
|
||||
let spell_index = get_buff_rem(module_accessor) - 1;
|
||||
// Used to get spell from our vector
|
||||
let spell_option = buff_vec.get(spell_index as usize);
|
||||
if spell_option.is_none() {
|
||||
// There are no spells selected, or something went wrong with making the vector
|
||||
return;
|
||||
}
|
||||
let real_spell_value = spell_option.unwrap().into_int().unwrap();
|
||||
if status != FIGHTER_BRAVE_STATUS_KIND_SPECIAL_LW_START {
|
||||
WorkModule::set_int(module_accessor, real_spell_value, *FIGHTER_BRAVE_INSTANCE_WORK_ID_INT_SPECIAL_LW_DECIDE_COMMAND);
|
||||
StatusModule::change_status_force(
|
||||
module_accessor,
|
||||
*FIGHTER_BRAVE_STATUS_KIND_SPECIAL_LW_START,
|
||||
true,
|
||||
// True to prevent Shielding over the spells
|
||||
);
|
||||
}
|
||||
if status == FIGHTER_BRAVE_STATUS_KIND_SPECIAL_LW_START {
|
||||
MotionModule::set_rate(module_accessor, 50.0);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn buff_cloud(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
|
||||
if !is_buffing(module_accessor) {
|
||||
// Only need to add to the limit gauge once
|
||||
start_buff(module_accessor);
|
||||
handle_add_limit(100.0,module_accessor,0);
|
||||
}
|
||||
if frame_counter::should_delay(2 as u32, BUFF_DELAY_COUNTER) {
|
||||
// Need to wait 2 frames to make sure we stop the limit SFX, since it's a bit delayed
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
unsafe fn buff_joker(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
|
||||
if !is_buffing(module_accessor) { // Only need to add to the rebel gauge once
|
||||
start_buff(module_accessor);
|
||||
let entry_id = app::FighterEntryID(FighterId::CPU as i32);
|
||||
// Strangely, this doesn't actually matter and works for both fighters
|
||||
app::FighterSpecializer_Jack::add_rebel_gauge(module_accessor, entry_id, 120.0);
|
||||
}
|
||||
if frame_counter::should_delay(2 as u32, BUFF_DELAY_COUNTER) {
|
||||
// Need to wait 2 frames to make sure we stop the voice call, since it's a bit delayed
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
unsafe fn buff_mac(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
|
||||
WorkModule::set_float(module_accessor, 100.0, *FIGHTER_LITTLEMAC_INSTANCE_WORK_ID_FLOAT_KO_GAGE);
|
||||
// Trying to stop KO Punch from playing seems to make it play multiple times in rapid succession
|
||||
// Look at 0x7100c44b60 for the func that handles this
|
||||
// Need to figure out how to update the KO meter if this is fixed
|
||||
return true;
|
||||
}
|
||||
|
||||
unsafe fn buff_sepiroth(module_accessor: &mut app::BattleObjectModuleAccessor, percent: f32) -> bool {
|
||||
start_buff(module_accessor);
|
||||
if WorkModule::get_int(module_accessor, *FIGHTER_EDGE_INSTANCE_WORK_ID_INT_ONE_WINGED_WING_STATE) == 1 {
|
||||
// Once we're in wing, heal to correct damage
|
||||
DamageModule::heal(
|
||||
module_accessor,
|
||||
-1.0 * DamageModule::damage(module_accessor, 0),
|
||||
0,
|
||||
);
|
||||
DamageModule::add_damage(module_accessor, percent, 0);
|
||||
return true;
|
||||
} else { // if we're not in wing, add damage
|
||||
DamageModule::add_damage(module_accessor, 1000.0, 0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
unsafe fn buff_wiifit(module_accessor: &mut app::BattleObjectModuleAccessor, status: i32) -> bool {
|
||||
if is_buffing(module_accessor) {
|
||||
if frame_counter::should_delay(2 as u32, BUFF_DELAY_COUNTER) {
|
||||
// Need to wait 2 frames to make sure we stop breathing SFX
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
let prev_status_kind = StatusModule::prev_status_kind(module_accessor, 0);
|
||||
if prev_status_kind == FIGHTER_WIIFIT_STATUS_KIND_SPECIAL_LW_SUCCESS {
|
||||
start_buff(module_accessor);
|
||||
return false;
|
||||
}
|
||||
if status != FIGHTER_WIIFIT_STATUS_KIND_SPECIAL_LW_SUCCESS {
|
||||
StatusModule::change_status_force(
|
||||
module_accessor,
|
||||
*FIGHTER_WIIFIT_STATUS_KIND_SPECIAL_LW_SUCCESS,
|
||||
false,
|
||||
);
|
||||
} else {
|
||||
MotionModule::set_rate(module_accessor, 40.0);
|
||||
}
|
||||
return false;
|
||||
}
|
0
src/training/buff/training.rs
Normal file
0
src/training/buff/training.rs
Normal file
|
@ -5,6 +5,7 @@ use skyline::nn::ro::LookupSymbol;
|
|||
use smash::app::{self, lua_bind::*};
|
||||
use smash::lib::lua_const::*;
|
||||
use smash::params::*;
|
||||
use smash::phx::Hash40;
|
||||
|
||||
pub mod combo;
|
||||
pub mod directional_influence;
|
||||
|
@ -14,6 +15,7 @@ pub mod sdi;
|
|||
pub mod shield;
|
||||
pub mod tech;
|
||||
pub mod throw;
|
||||
pub mod buff;
|
||||
|
||||
mod air_dodge_direction;
|
||||
mod attack_angle;
|
||||
|
@ -305,6 +307,39 @@ fn params_main(params_info: &ParamsInfo<'_>) {
|
|||
}
|
||||
}
|
||||
|
||||
static CLOUD_ADD_LIMIT_OFFSET: usize = 0x008dc140; // this function is used to add limit to Cloud's limit gauge. Hooking it here so we can call it in buff.rs
|
||||
#[skyline::hook(offset = CLOUD_ADD_LIMIT_OFFSET)]
|
||||
pub unsafe fn handle_add_limit(add_limit: f32, module_accessor: &mut app::BattleObjectModuleAccessor, is_special_lw: u64) {
|
||||
original!()(add_limit,module_accessor,is_special_lw)
|
||||
}
|
||||
|
||||
#[skyline::hook(replace = EffectModule::req_screen)] // hooked to prevent the screen from darkening when loading a save state with One-Winged Angel
|
||||
pub unsafe fn handle_req_screen(module_accessor: &mut app::BattleObjectModuleAccessor, my_hash: Hash40, bool_1:bool, bool_2:bool, bool_3:bool) -> u64 {
|
||||
if !is_training_mode() {
|
||||
return original!()(module_accessor,my_hash,bool_1,bool_2,bool_3);
|
||||
}
|
||||
let new_hash = my_hash.hash;
|
||||
if new_hash == 72422354958 && buff::is_buffing(module_accessor) { // Wing bg hash
|
||||
let replace_hash = Hash40::new("bg");
|
||||
return original!()(module_accessor,replace_hash,bool_1,bool_2,bool_3);
|
||||
}
|
||||
original!()(module_accessor,my_hash,bool_1,bool_2,bool_3)
|
||||
}
|
||||
|
||||
#[skyline::hook(replace = app::FighterSpecializer_Jack::check_doyle_summon_dispatch)] // returns status of summon dispatch if triggered, -1 as u64 otherwise
|
||||
pub unsafe fn handle_check_doyle_summon_dispatch(module_accessor: &mut app::BattleObjectModuleAccessor, bool_1: bool, bool_2: bool) -> u64 {
|
||||
let ori = original!()(module_accessor,bool_1,bool_2);
|
||||
if !is_training_mode() {
|
||||
return ori;
|
||||
}
|
||||
if ori == *FIGHTER_JACK_STATUS_KIND_SUMMON as u64 {
|
||||
if buff::is_buffing(module_accessor) {
|
||||
return 4294967295;
|
||||
}
|
||||
}
|
||||
return ori;
|
||||
}
|
||||
|
||||
#[allow(improper_ctypes)]
|
||||
extern "C" {
|
||||
fn add_nn_hid_hook(callback: fn(*mut NpadHandheldState, *const u32));
|
||||
|
@ -366,6 +401,11 @@ pub fn training_mods() {
|
|||
handle_is_enable_transition_term,
|
||||
// SDI
|
||||
crate::training::sdi::check_hit_stop_delay_command,
|
||||
// Buffs
|
||||
//get_param_float_hook,
|
||||
handle_add_limit,
|
||||
handle_check_doyle_summon_dispatch,
|
||||
handle_req_screen,
|
||||
);
|
||||
|
||||
combo::init();
|
||||
|
@ -375,4 +415,5 @@ pub fn training_mods() {
|
|||
ledge::init();
|
||||
throw::init();
|
||||
menu::init();
|
||||
buff::init();
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ use crate::common::consts::SaveStateMirroring;
|
|||
use crate::common::MENU;
|
||||
use crate::common::{get_random_int, is_dead};
|
||||
use crate::training::reset;
|
||||
use crate::training::buff;
|
||||
use smash::app::{self, lua_bind::*};
|
||||
use smash::hash40;
|
||||
use smash::lib::lua_const::*;
|
||||
|
@ -16,6 +17,7 @@ enum SaveState {
|
|||
KillPlayer,
|
||||
PosMove,
|
||||
NanaPosMove,
|
||||
ApplyBuff,
|
||||
}
|
||||
|
||||
struct SavedState {
|
||||
|
@ -147,6 +149,15 @@ pub unsafe fn save_states(module_accessor: &mut app::BattleObjectModuleAccessor)
|
|||
.contains(&fighter_kind);
|
||||
let fighter_is_popo = fighter_kind == *FIGHTER_KIND_POPO; // For making sure Popo doesn't steal Nana's PosMove
|
||||
let fighter_is_nana = fighter_kind == *FIGHTER_KIND_NANA; // Don't want Nana to reopen savestates etc.
|
||||
let fighter_is_buffable = [
|
||||
*FIGHTER_KIND_BRAVE,
|
||||
*FIGHTER_KIND_CLOUD,
|
||||
*FIGHTER_KIND_JACK,
|
||||
*FIGHTER_KIND_LITTLEMAC,
|
||||
*FIGHTER_KIND_EDGE,
|
||||
*FIGHTER_KIND_WIIFIT,
|
||||
]
|
||||
.contains(&fighter_kind);
|
||||
|
||||
// Grab + Dpad up: reset state
|
||||
if ControlModule::check_button_on(module_accessor, *CONTROL_PAD_BUTTON_CATCH)
|
||||
|
@ -253,9 +264,12 @@ pub unsafe fn save_states(module_accessor: &mut app::BattleObjectModuleAccessor)
|
|||
save_state.state = NoAction;
|
||||
}
|
||||
|
||||
// if we're done moving, reset percent
|
||||
// if we're done moving, reset percent and apply buffs
|
||||
if save_state.state == NoAction {
|
||||
set_damage(module_accessor, save_state.percent);
|
||||
if fighter_is_buffable {
|
||||
save_state.state = ApplyBuff;
|
||||
}
|
||||
}
|
||||
|
||||
// if the fighter is Popo, change the state to one where only Nana can move
|
||||
|
@ -269,6 +283,16 @@ pub unsafe fn save_states(module_accessor: &mut app::BattleObjectModuleAccessor)
|
|||
|
||||
return;
|
||||
}
|
||||
|
||||
if save_state.state == ApplyBuff {
|
||||
// needs its own save_state.state since this may take multiple frames, want it to loop
|
||||
if buff::handle_buffs(module_accessor, fighter_kind, status, save_state.percent) {
|
||||
// returns true when done buffing fighter
|
||||
buff::restart_buff(module_accessor);
|
||||
// set is_buffing back to false when done
|
||||
save_state.state = NoAction;
|
||||
}
|
||||
}
|
||||
|
||||
// Grab + Dpad down: Save state
|
||||
if ControlModule::check_button_on(module_accessor, *CONTROL_PAD_BUTTON_CATCH)
|
||||
|
|
Loading…
Reference in a new issue