mirror of
https://github.com/jugeeya/UltimateTrainingModpack.git
synced 2024-11-20 00:46:34 +00:00
Feature: Clatter Strength (#337)
* Initial clatter work * Add clatter to menus * Change joint to hip * Update SDI and Clatter to use the same enum * Avoid early clatter/sdi input
This commit is contained in:
parent
92a3d5711d
commit
2cd382e0bc
6 changed files with 250 additions and 157 deletions
|
@ -1,138 +1,142 @@
|
|||
pub mod consts;
|
||||
pub mod events;
|
||||
pub mod menu;
|
||||
pub mod raygun_printer;
|
||||
pub mod release;
|
||||
|
||||
use crate::common::consts::*;
|
||||
use smash::app::{self, lua_bind::*};
|
||||
use smash::lib::lua_const::*;
|
||||
|
||||
pub use crate::common::consts::MENU;
|
||||
pub static mut DEFAULTS_MENU: TrainingModpackMenu = crate::common::consts::DEFAULTS_MENU;
|
||||
pub static mut BASE_MENU: TrainingModpackMenu = unsafe { DEFAULTS_MENU };
|
||||
pub static mut FIGHTER_MANAGER_ADDR: usize = 0;
|
||||
pub static mut STAGE_MANAGER_ADDR: usize = 0;
|
||||
|
||||
#[cfg(not(feature = "outside_training_mode"))]
|
||||
extern "C" {
|
||||
#[link_name = "\u{1}_ZN3app9smashball16is_training_modeEv"]
|
||||
pub fn is_training_mode() -> bool;
|
||||
}
|
||||
|
||||
#[cfg(feature = "outside_training_mode")]
|
||||
pub fn is_training_mode() -> bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
pub fn get_category(module_accessor: &mut app::BattleObjectModuleAccessor) -> i32 {
|
||||
(module_accessor.info >> 28) as u8 as i32
|
||||
}
|
||||
|
||||
pub fn is_emulator() -> bool {
|
||||
unsafe { skyline::hooks::getRegionAddress(skyline::hooks::Region::Text) as u64 == 0x8004000 }
|
||||
}
|
||||
|
||||
pub fn get_module_accessor(fighter_id: FighterId) -> *mut app::BattleObjectModuleAccessor {
|
||||
let entry_id_int = fighter_id as i32;
|
||||
let entry_id = app::FighterEntryID(entry_id_int);
|
||||
unsafe {
|
||||
let mgr = *(FIGHTER_MANAGER_ADDR as *mut *mut app::FighterManager);
|
||||
let fighter_entry =
|
||||
FighterManager::get_fighter_entry(mgr, entry_id) as *mut app::FighterEntry;
|
||||
let current_fighter_id = FighterEntry::current_fighter_id(fighter_entry);
|
||||
app::sv_battle_object::module_accessor(current_fighter_id as u32)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_fighter(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
|
||||
get_category(module_accessor) == BATTLE_OBJECT_CATEGORY_FIGHTER
|
||||
}
|
||||
|
||||
pub fn is_operation_cpu(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
|
||||
unsafe {
|
||||
if !is_fighter(module_accessor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let entry_id_int =
|
||||
WorkModule::get_int(module_accessor, *FIGHTER_INSTANCE_WORK_ID_INT_ENTRY_ID) as i32;
|
||||
|
||||
if entry_id_int == 0 {
|
||||
return false;
|
||||
}
|
||||
|
||||
let entry_id = app::FighterEntryID(entry_id_int);
|
||||
let mgr = *(FIGHTER_MANAGER_ADDR as *mut *mut app::FighterManager);
|
||||
let fighter_information =
|
||||
FighterManager::get_fighter_information(mgr, entry_id) as *mut app::FighterInformation;
|
||||
|
||||
FighterInformation::is_operation_cpu(fighter_information)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_grounded(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
|
||||
let situation_kind = unsafe { StatusModule::situation_kind(module_accessor) as i32 };
|
||||
|
||||
situation_kind == SITUATION_KIND_GROUND
|
||||
}
|
||||
|
||||
pub fn is_airborne(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
|
||||
let situation_kind = unsafe { StatusModule::situation_kind(module_accessor) as i32 };
|
||||
|
||||
situation_kind == SITUATION_KIND_AIR
|
||||
}
|
||||
|
||||
pub fn is_idle(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
|
||||
let status_kind = unsafe { StatusModule::status_kind(module_accessor) };
|
||||
|
||||
status_kind == FIGHTER_STATUS_KIND_WAIT
|
||||
}
|
||||
|
||||
pub fn is_in_hitstun(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
|
||||
let status_kind = unsafe { StatusModule::status_kind(module_accessor) };
|
||||
|
||||
(*FIGHTER_STATUS_KIND_DAMAGE..*FIGHTER_STATUS_KIND_DAMAGE_FALL).contains(&status_kind)
|
||||
}
|
||||
pub fn is_in_footstool(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
|
||||
let status_kind = unsafe { StatusModule::status_kind(module_accessor) };
|
||||
|
||||
(*FIGHTER_STATUS_KIND_TREAD_DAMAGE..=*FIGHTER_STATUS_KIND_TREAD_FALL).contains(&status_kind)
|
||||
}
|
||||
|
||||
pub fn is_shielding(module_accessor: *mut app::BattleObjectModuleAccessor) -> bool {
|
||||
let status_kind = unsafe { StatusModule::status_kind(module_accessor) as i32 };
|
||||
|
||||
(*FIGHTER_STATUS_KIND_GUARD_ON..=*FIGHTER_STATUS_KIND_GUARD_DAMAGE).contains(&status_kind)
|
||||
}
|
||||
|
||||
pub fn is_in_shieldstun(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
|
||||
let status_kind = unsafe { StatusModule::status_kind(module_accessor) };
|
||||
let prev_status = unsafe { StatusModule::prev_status_kind(module_accessor, 0) };
|
||||
|
||||
// If we are taking shield damage or we are droping shield from taking shield damage we are in hitstun
|
||||
status_kind == FIGHTER_STATUS_KIND_GUARD_DAMAGE
|
||||
|| (prev_status == FIGHTER_STATUS_KIND_GUARD_DAMAGE
|
||||
&& status_kind == FIGHTER_STATUS_KIND_GUARD_OFF)
|
||||
}
|
||||
|
||||
pub unsafe fn is_dead(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
|
||||
let fighter_kind = app::utility::get_kind(module_accessor);
|
||||
let fighter_is_ptrainer = [
|
||||
*FIGHTER_KIND_PZENIGAME,
|
||||
*FIGHTER_KIND_PFUSHIGISOU,
|
||||
*FIGHTER_KIND_PLIZARDON,
|
||||
]
|
||||
.contains(&fighter_kind);
|
||||
let status_kind = StatusModule::status_kind(module_accessor) as i32;
|
||||
let prev_status_kind = StatusModule::prev_status_kind(module_accessor, 0);
|
||||
// Pokemon trainer enters FIGHTER_STATUS_KIND_WAIT for one frame during their respawn animation
|
||||
// And the previous status is FIGHTER_STATUS_NONE
|
||||
if fighter_is_ptrainer {
|
||||
[*FIGHTER_STATUS_KIND_DEAD, *FIGHTER_STATUS_KIND_STANDBY].contains(&status_kind)
|
||||
|| (status_kind == FIGHTER_STATUS_KIND_WAIT
|
||||
&& prev_status_kind == FIGHTER_STATUS_KIND_NONE)
|
||||
} else {
|
||||
[*FIGHTER_STATUS_KIND_DEAD, *FIGHTER_STATUS_KIND_STANDBY].contains(&status_kind)
|
||||
}
|
||||
}
|
||||
pub mod consts;
|
||||
pub mod events;
|
||||
pub mod menu;
|
||||
pub mod raygun_printer;
|
||||
pub mod release;
|
||||
|
||||
use crate::common::consts::*;
|
||||
use smash::app::{self, lua_bind::*};
|
||||
use smash::lib::lua_const::*;
|
||||
|
||||
pub use crate::common::consts::MENU;
|
||||
pub static mut DEFAULTS_MENU: TrainingModpackMenu = crate::common::consts::DEFAULTS_MENU;
|
||||
pub static mut BASE_MENU: TrainingModpackMenu = unsafe { DEFAULTS_MENU };
|
||||
pub static mut FIGHTER_MANAGER_ADDR: usize = 0;
|
||||
pub static mut STAGE_MANAGER_ADDR: usize = 0;
|
||||
|
||||
#[cfg(not(feature = "outside_training_mode"))]
|
||||
extern "C" {
|
||||
#[link_name = "\u{1}_ZN3app9smashball16is_training_modeEv"]
|
||||
pub fn is_training_mode() -> bool;
|
||||
}
|
||||
|
||||
#[cfg(feature = "outside_training_mode")]
|
||||
pub fn is_training_mode() -> bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
pub fn get_category(module_accessor: &mut app::BattleObjectModuleAccessor) -> i32 {
|
||||
(module_accessor.info >> 28) as u8 as i32
|
||||
}
|
||||
|
||||
pub fn is_emulator() -> bool {
|
||||
unsafe { skyline::hooks::getRegionAddress(skyline::hooks::Region::Text) as u64 == 0x8004000 }
|
||||
}
|
||||
|
||||
pub fn get_module_accessor(fighter_id: FighterId) -> *mut app::BattleObjectModuleAccessor {
|
||||
let entry_id_int = fighter_id as i32;
|
||||
let entry_id = app::FighterEntryID(entry_id_int);
|
||||
unsafe {
|
||||
let mgr = *(FIGHTER_MANAGER_ADDR as *mut *mut app::FighterManager);
|
||||
let fighter_entry =
|
||||
FighterManager::get_fighter_entry(mgr, entry_id) as *mut app::FighterEntry;
|
||||
let current_fighter_id = FighterEntry::current_fighter_id(fighter_entry);
|
||||
app::sv_battle_object::module_accessor(current_fighter_id as u32)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_fighter(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
|
||||
get_category(module_accessor) == BATTLE_OBJECT_CATEGORY_FIGHTER
|
||||
}
|
||||
|
||||
pub fn is_operation_cpu(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
|
||||
unsafe {
|
||||
if !is_fighter(module_accessor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let entry_id_int =
|
||||
WorkModule::get_int(module_accessor, *FIGHTER_INSTANCE_WORK_ID_INT_ENTRY_ID) as i32;
|
||||
|
||||
if entry_id_int == 0 {
|
||||
return false;
|
||||
}
|
||||
|
||||
let entry_id = app::FighterEntryID(entry_id_int);
|
||||
let mgr = *(FIGHTER_MANAGER_ADDR as *mut *mut app::FighterManager);
|
||||
let fighter_information =
|
||||
FighterManager::get_fighter_information(mgr, entry_id) as *mut app::FighterInformation;
|
||||
|
||||
FighterInformation::is_operation_cpu(fighter_information)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_grounded(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
|
||||
let situation_kind = unsafe { StatusModule::situation_kind(module_accessor) as i32 };
|
||||
|
||||
situation_kind == SITUATION_KIND_GROUND
|
||||
}
|
||||
|
||||
pub fn is_airborne(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
|
||||
let situation_kind = unsafe { StatusModule::situation_kind(module_accessor) as i32 };
|
||||
|
||||
situation_kind == SITUATION_KIND_AIR
|
||||
}
|
||||
|
||||
pub fn is_idle(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
|
||||
let status_kind = unsafe { StatusModule::status_kind(module_accessor) };
|
||||
|
||||
status_kind == FIGHTER_STATUS_KIND_WAIT
|
||||
}
|
||||
|
||||
pub fn is_in_hitstun(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
|
||||
let status_kind = unsafe { StatusModule::status_kind(module_accessor) };
|
||||
|
||||
(*FIGHTER_STATUS_KIND_DAMAGE..*FIGHTER_STATUS_KIND_DAMAGE_FALL).contains(&status_kind)
|
||||
}
|
||||
pub fn is_in_footstool(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
|
||||
let status_kind = unsafe { StatusModule::status_kind(module_accessor) };
|
||||
|
||||
(*FIGHTER_STATUS_KIND_TREAD_DAMAGE..=*FIGHTER_STATUS_KIND_TREAD_FALL).contains(&status_kind)
|
||||
}
|
||||
|
||||
pub fn is_shielding(module_accessor: *mut app::BattleObjectModuleAccessor) -> bool {
|
||||
let status_kind = unsafe { StatusModule::status_kind(module_accessor) as i32 };
|
||||
|
||||
(*FIGHTER_STATUS_KIND_GUARD_ON..=*FIGHTER_STATUS_KIND_GUARD_DAMAGE).contains(&status_kind)
|
||||
}
|
||||
|
||||
pub fn is_in_shieldstun(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
|
||||
let status_kind = unsafe { StatusModule::status_kind(module_accessor) };
|
||||
let prev_status = unsafe { StatusModule::prev_status_kind(module_accessor, 0) };
|
||||
|
||||
// If we are taking shield damage or we are droping shield from taking shield damage we are in hitstun
|
||||
status_kind == FIGHTER_STATUS_KIND_GUARD_DAMAGE
|
||||
|| (prev_status == FIGHTER_STATUS_KIND_GUARD_DAMAGE
|
||||
&& status_kind == FIGHTER_STATUS_KIND_GUARD_OFF)
|
||||
}
|
||||
|
||||
pub unsafe fn is_dead(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
|
||||
let fighter_kind = app::utility::get_kind(module_accessor);
|
||||
let fighter_is_ptrainer = [
|
||||
*FIGHTER_KIND_PZENIGAME,
|
||||
*FIGHTER_KIND_PFUSHIGISOU,
|
||||
*FIGHTER_KIND_PLIZARDON,
|
||||
]
|
||||
.contains(&fighter_kind);
|
||||
let status_kind = StatusModule::status_kind(module_accessor) as i32;
|
||||
let prev_status_kind = StatusModule::prev_status_kind(module_accessor, 0);
|
||||
// Pokemon trainer enters FIGHTER_STATUS_KIND_WAIT for one frame during their respawn animation
|
||||
// And the previous status is FIGHTER_STATUS_NONE
|
||||
if fighter_is_ptrainer {
|
||||
[*FIGHTER_STATUS_KIND_DEAD, *FIGHTER_STATUS_KIND_STANDBY].contains(&status_kind)
|
||||
|| (status_kind == FIGHTER_STATUS_KIND_WAIT
|
||||
&& prev_status_kind == FIGHTER_STATUS_KIND_NONE)
|
||||
} else {
|
||||
[*FIGHTER_STATUS_KIND_DEAD, *FIGHTER_STATUS_KIND_STANDBY].contains(&status_kind)
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn is_in_clatter(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
|
||||
ControlModule::get_clatter_time(module_accessor, 0) > 0.0
|
||||
}
|
||||
|
|
25
src/static/img/clatter_strength.svg
Normal file
25
src/static/img/clatter_strength.svg
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="80"
|
||||
height="80"
|
||||
viewBox="0 0 21.166666 21.166667"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<g
|
||||
id="layer2"
|
||||
style="display:inline">
|
||||
<path
|
||||
style="fill:#ffffff;stroke:none;stroke-width:0.0497127;fill-opacity:1"
|
||||
d="M 13.064037,0.15777454 C 8.1424266,0.80397653 3.2845429,3.5550995 1.5652428,8.4884178 -0.15917764,13.436426 2.3169541,19.190626 7.5459235,20.622254 8.7329642,20.947276 10.006356,21.008224 11.224666,20.852722 17.566967,20.0432 20.634193,13.067458 19.846047,7.3450248 19.413696,4.206053 17.925744,0.44725481 14.306856,0.18197818 13.892599,0.15161215 13.479984,0.10316141 13.064037,0.15777454 m 5.915816,6.88897386 c -0.824287,0.084412 -1.367697,1.0032528 -1.66145,1.6902331 -0.575375,1.3453265 -0.676441,2.8591785 -0.320746,4.2752955 0.152618,0.607689 0.386119,1.283832 0.888516,1.690233 -0.170267,0.95528 -1.129524,1.975436 -1.789659,2.634776 -2.336747,2.333913 -5.743263,3.326677 -8.8985796,2.202672 C 2.6731458,17.928122 1.0093348,12.893563 2.45869,8.5878433 2.9049613,7.262104 3.7953064,5.583255 4.9608613,4.7599623 c 0,1.6125322 1.2650897,2.6094715 2.7839132,2.8540084 C 9.8316157,7.9499792 12.349118,7.2792051 13.68475,5.5553662 14.496013,4.5083512 14.838633,2.7528502 13.80774,1.7296327 13.428282,1.353019 12.920069,1.1740531 12.417772,1.0315068 12.922058,0.81791598 13.723775,0.89852022 14.257143,0.96779492 17.150126,1.3435586 18.762956,4.3213617 18.979853,7.0467484 M 8.6893164,10.448492 c -0.6508391,0.09321 -1.2731928,0.277596 -1.8393712,0.621359 -2.0621489,1.251966 -2.6350683,4.142314 -1.0290437,6.018871 1.0799496,1.261858 2.7350854,1.804871 4.3597975,1.569531 0.528645,-0.07661 1.030843,-0.232059 1.491382,-0.505877 3.699025,-2.199391 1.102429,-8.288854 -2.9827646,-7.703884 z"
|
||||
id="path5397" />
|
||||
</g>
|
||||
<g
|
||||
id="layer3"
|
||||
style="display:inline" />
|
||||
</svg>
|
After Width: | Height: | Size: 2 KiB |
49
src/training/clatter.rs
Normal file
49
src/training/clatter.rs
Normal file
|
@ -0,0 +1,49 @@
|
|||
use crate::common::{is_in_clatter, is_operation_cpu, is_training_mode, MENU};
|
||||
use smash::app::lua_bind::{ControlModule, EffectModule};
|
||||
use smash::app::BattleObjectModuleAccessor;
|
||||
use smash::lib::lua_const::*;
|
||||
use smash::phx::{Hash40, Vector3f};
|
||||
|
||||
static mut COUNTER: u32 = 0;
|
||||
|
||||
unsafe fn do_clatter_input(module_accessor: &mut BattleObjectModuleAccessor) {
|
||||
ControlModule::add_clatter_time(module_accessor, -8.0, 0);
|
||||
let zeros = Vector3f {
|
||||
x: 0.0,
|
||||
y: 0.0,
|
||||
z: 0.0,
|
||||
};
|
||||
|
||||
EffectModule::req_on_joint(
|
||||
module_accessor,
|
||||
Hash40::new("sys_clatter"),
|
||||
Hash40::new("hip"),
|
||||
&zeros,
|
||||
&zeros,
|
||||
1.0,
|
||||
&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,
|
||||
);
|
||||
}
|
||||
|
||||
pub unsafe fn handle_clatter(module_accessor: &mut BattleObjectModuleAccessor) {
|
||||
if !is_training_mode() || !is_operation_cpu(module_accessor) {
|
||||
return;
|
||||
}
|
||||
|
||||
if !is_in_clatter(module_accessor) {
|
||||
return;
|
||||
}
|
||||
let repeat = MENU.clatter_strength.into_u32();
|
||||
|
||||
COUNTER = (COUNTER + 1) % repeat;
|
||||
if COUNTER == repeat - 1 {
|
||||
do_clatter_input(module_accessor);
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@ use smash::phx::{Hash40, Vector3f};
|
|||
|
||||
pub mod buff;
|
||||
pub mod charge;
|
||||
pub mod clatter;
|
||||
pub mod combo;
|
||||
pub mod directional_influence;
|
||||
pub mod frame_counter;
|
||||
|
@ -114,6 +115,7 @@ fn once_per_frame_per_fighter(
|
|||
hitbox_visualizer::get_command_flag_cat(module_accessor);
|
||||
save_states::save_states(module_accessor);
|
||||
tech::get_command_flag_cat(module_accessor);
|
||||
clatter::handle_clatter(module_accessor);
|
||||
}
|
||||
|
||||
fast_fall::get_command_flag_cat(module_accessor);
|
||||
|
|
|
@ -36,9 +36,10 @@ pub unsafe fn check_hit_stop_delay_command(
|
|||
if !is_training_mode() || !is_operation_cpu(module_accessor) {
|
||||
return original!()(module_accessor, sdi_direction);
|
||||
}
|
||||
let repeat = MENU.sdi_strength.into_u32();
|
||||
|
||||
COUNTER = (COUNTER + 1) % MENU.sdi_strength.into_u32();
|
||||
if COUNTER == 1 {
|
||||
COUNTER = (COUNTER + 1) % repeat;
|
||||
if COUNTER == repeat - 1 {
|
||||
if let Some(angle) = get_sdi_direction() {
|
||||
// If there is a non-neutral direction picked,
|
||||
// modify the SDI angle Vector2f as a side-effect
|
||||
|
|
|
@ -866,26 +866,29 @@ impl BoolFlag {
|
|||
|
||||
#[repr(u32)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, EnumIter, Serialize, Deserialize)]
|
||||
pub enum SdiStrength {
|
||||
Normal = 0,
|
||||
Medium = 1,
|
||||
High = 2,
|
||||
pub enum InputFrequency {
|
||||
None = 0,
|
||||
Normal = 1,
|
||||
Medium = 2,
|
||||
High = 4,
|
||||
}
|
||||
|
||||
impl SdiStrength {
|
||||
impl InputFrequency {
|
||||
pub fn into_u32(self) -> u32 {
|
||||
match self {
|
||||
SdiStrength::Normal => 8,
|
||||
SdiStrength::Medium => 6,
|
||||
SdiStrength::High => 4,
|
||||
InputFrequency::None => u32::MAX,
|
||||
InputFrequency::Normal => 8,
|
||||
InputFrequency::Medium => 6,
|
||||
InputFrequency::High => 4,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_str(self) -> Option<&'static str> {
|
||||
Some(match self {
|
||||
SdiStrength::Normal => "Normal",
|
||||
SdiStrength::Medium => "Medium",
|
||||
SdiStrength::High => "High",
|
||||
InputFrequency::None => "None",
|
||||
InputFrequency::Normal => "Normal",
|
||||
InputFrequency::Medium => "Medium",
|
||||
InputFrequency::High => "High",
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -894,13 +897,13 @@ impl SdiStrength {
|
|||
}
|
||||
}
|
||||
|
||||
impl ToggleTrait for SdiStrength {
|
||||
impl ToggleTrait for InputFrequency {
|
||||
fn to_toggle_strs() -> Vec<&'static str> {
|
||||
SdiStrength::iter().map(|i| i.as_str().unwrap_or("")).collect()
|
||||
InputFrequency::iter().map(|i| i.as_str().unwrap_or("")).collect()
|
||||
}
|
||||
|
||||
fn to_toggle_vals() -> Vec<usize> {
|
||||
SdiStrength::iter().map(|i| i as usize).collect()
|
||||
InputFrequency::iter().map(|i| i as usize).collect()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -958,7 +961,8 @@ url_params! {
|
|||
pub stage_hazards: OnOff,
|
||||
pub di_state: Direction,
|
||||
pub sdi_state: Direction,
|
||||
pub sdi_strength: SdiStrength,
|
||||
pub sdi_strength: InputFrequency,
|
||||
pub clatter_strength: InputFrequency,
|
||||
pub air_dodge_dir: Direction,
|
||||
pub mash_state: Action,
|
||||
pub follow_up: Action,
|
||||
|
@ -1018,6 +1022,7 @@ impl TrainingModpackMenu {
|
|||
aerial_delay = Delay::from_bits(val),
|
||||
air_dodge_dir = Direction::from_bits(val),
|
||||
attack_angle = AttackAngle::from_bits(val),
|
||||
clatter_strength = num::FromPrimitive::from_u32(val),
|
||||
defensive_state = Defensive::from_bits(val),
|
||||
di_state = Direction::from_bits(val),
|
||||
falling_aerials = BoolFlag::from_bits(val),
|
||||
|
@ -1082,7 +1087,8 @@ pub static DEFAULTS_MENU: TrainingModpackMenu = TrainingModpackMenu {
|
|||
stage_hazards: OnOff::Off,
|
||||
di_state: Direction::empty(),
|
||||
sdi_state: Direction::empty(),
|
||||
sdi_strength: SdiStrength::Normal,
|
||||
sdi_strength: InputFrequency::None,
|
||||
clatter_strength: InputFrequency::None,
|
||||
air_dodge_dir: Direction::empty(),
|
||||
mash_state: Action::empty(),
|
||||
follow_up: Action::empty(),
|
||||
|
@ -1362,12 +1368,18 @@ pub unsafe fn get_menu() -> UiMenu<'static> {
|
|||
"SDI Direction: Direction to angle the smash directional influence during hitlag",
|
||||
false,
|
||||
);
|
||||
defensive_tab.add_submenu_with_toggles::<SdiStrength>(
|
||||
defensive_tab.add_submenu_with_toggles::<InputFrequency>(
|
||||
"SDI Strength",
|
||||
"sdi_strength",
|
||||
"SDI Strength: Relative strength of the smash directional influence inputs",
|
||||
true,
|
||||
);
|
||||
defensive_tab.add_submenu_with_toggles::<InputFrequency>(
|
||||
"Clatter Strength",
|
||||
"clatter_strength",
|
||||
"Clatter Strength: Relative strength of the mashing out of grabs, buries, etc.",
|
||||
true,
|
||||
);
|
||||
defensive_tab.add_submenu_with_toggles::<LedgeOption>(
|
||||
"Ledge Options",
|
||||
"ledge_state",
|
||||
|
|
Loading…
Reference in a new issue