1
0
Fork 0
mirror of https://github.com/jugeeya/UltimateTrainingModpack.git synced 2025-03-16 11:26:11 +00:00

Finishing up with button config

This commit is contained in:
jugeeya 2023-08-08 00:20:55 -07:00 committed by GitHub
parent 98edfc6160
commit 0ab6e64cfa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 121 additions and 97 deletions

View file

@ -1,32 +1,60 @@
use std::collections::HashMap;
use std::fs;
use crate::common::menu::P1_CONTROLLER_STATE;
use crate::consts::TRAINING_MODPACK_TOML_PATH;
use crate::input::{ControllerStyle::*, *};
use lazy_static::lazy_static;
use log::info;
use serde::Deserialize;
use smash::app::lua_bind::ControlModule;
use strum::IntoEnumIterator;
use strum_macros::EnumIter;
use toml;
lazy_static! {
// Using the LuaConst names wasn't working for some reason...
static ref BUTTON_MAPPING: HashMap<&'static str, i32> = HashMap::from([
("ATTACK", 0), // *CONTROL_PAD_BUTTON_ATTACK
("SPECIAL", 1), // *CONTROL_PAD_BUTTON_SPECIAL
("SHIELD", 3), // *CONTROL_PAD_BUTTON_GUARD
("GRAB", 9), // *CONTROL_PAD_BUTTON_CATCH
("JUMP", 2), // *CONTROL_PAD_BUTTON_JUMP
("UPTAUNT", 5), // *CONTROL_PAD_BUTTON_APPEAL_HI
("DOWNTAUNT", 6), // *CONTROL_PAD_BUTTON_APPEAL_LW
("LEFTTAUNT", 7), // *CONTROL_PAD_BUTTON_APPEAL_S_L
("RIGHTTAUNT", 8), // *CONTROL_PAD_BUTTON_APPEAL_S_R
("SHARESTOCK", 0xD), // *CONTROL_PAD_BUTTON_STOCK_SHARE
("JUMPMINI", 0xA), // *CONTROL_PAD_BUTTON_JUMP_MINI
]);
const BUTTON_MAPPINGS: [&str; 12] = [
"A",
"B",
"X",
"Y",
"L",
"R",
"ZL",
"ZR",
"DPAD_UP",
"DPAD_DOWN",
"DPAD_LEFT",
"DPAD_RIGHT",
];
fn button_mapping(name: &str, style: ControllerStyle, b: ButtonBitfield) -> bool {
match name {
"A" => b.a(),
"B" => b.b(),
"X" => b.x(),
"Y" => b.y(),
"L" => match style {
GCController => false,
_ => b.l(),
},
"R" => match style {
GCController => b.zr(),
_ => b.r(),
},
"ZL" => match style {
GCController => b.l() || b.real_digital_l(),
_ => b.zl(),
},
"ZR" => match style {
GCController => b.r() || b.real_digital_r(),
_ => b.zr(),
},
"DPAD_UP" => b.dpad_up(),
"DPAD_DOWN" => b.dpad_down(),
"DPAD_LEFT" => b.dpad_left(),
"DPAD_RIGHT" => b.dpad_right(),
_ => panic!("Invalid button name: {}", name),
}
}
static mut BUTTON_COMBO_CONFIG: BtnComboConfig = BtnComboConfig {
open_menu: BtnList {
hold: vec![],
@ -107,24 +135,24 @@ fn save_all_btn_config_from_defaults() {
let conf = TopLevelBtnComboConfig {
button_config: BtnComboConfig {
open_menu: BtnList {
hold: vec!["SPECIAL".to_string()],
press: vec!["UPTAUNT".to_string()],
hold: vec!["B".to_string()],
press: vec!["DPAD_UP".to_string()],
},
save_state: BtnList {
hold: vec!["SHIELD".to_string()],
press: vec!["DOWNTAUNT".to_string()],
hold: vec!["ZL".to_string()],
press: vec!["DPAD_DOWN".to_string()],
},
load_state: BtnList {
hold: vec!["SHIELD".to_string()],
press: vec!["UPTAUNT".to_string()],
hold: vec!["ZL".to_string()],
press: vec!["DPAD_UP".to_string()],
},
input_record: BtnList {
hold: vec!["ATTACK".to_string()],
press: vec!["LEFTTAUNT".to_string()],
hold: vec!["ZR".to_string()],
press: vec!["DPAD_LEFT".to_string()],
},
input_playback: BtnList {
hold: vec!["ATTACK".to_string()],
press: vec!["RIGHTTAUNT".to_string()],
hold: vec!["ZR".to_string()],
press: vec!["DPAD_RIGHT".to_string()],
},
},
};
@ -146,7 +174,13 @@ fn save_all_btn_config_from_toml(data: &str) {
fn validate_config(conf: TopLevelBtnComboConfig) -> bool {
let conf = conf.button_config;
let configs = [conf.open_menu, conf.save_state, conf.load_state];
let configs = [
conf.open_menu,
conf.save_state,
conf.load_state,
conf.input_record,
conf.input_playback,
];
let bad_keys = configs
.iter()
.flat_map(|btn_list| {
@ -154,7 +188,7 @@ fn validate_config(conf: TopLevelBtnComboConfig) -> bool {
.hold
.iter()
.chain(btn_list.press.iter())
.filter(|x| !BUTTON_MAPPING.contains_key(x.to_uppercase().as_str()))
.filter(|x| !BUTTON_MAPPINGS.contains(&x.to_uppercase().as_str()))
})
.collect::<Vec<&String>>();
@ -165,9 +199,7 @@ fn validate_config(conf: TopLevelBtnComboConfig) -> bool {
&format!(
"The following keys are invalid in\n{}:\n\
{:?}\n\nPossible Keys: {:#?}\0",
TRAINING_MODPACK_TOML_PATH,
&bad_keys,
BUTTON_MAPPING.keys()
TRAINING_MODPACK_TOML_PATH, &bad_keys, BUTTON_MAPPINGS
),
);
false
@ -201,73 +233,72 @@ unsafe fn get_combo_keys(combo: ButtonCombo) -> (&'static Vec<String>, &'static
}
}
fn combo_passes(
module_accessor: *mut smash::app::BattleObjectModuleAccessor,
combo: ButtonCombo,
) -> bool {
fn combo_passes(combo: ButtonCombo) -> bool {
unsafe {
let (hold, press) = get_combo_keys(combo);
let this_combo_passes = hold
.iter()
.map(|hold| *BUTTON_MAPPING.get(&*hold.to_uppercase()).unwrap())
.all(|hold| ControlModule::check_button_on(module_accessor, hold))
&& press
.iter()
.map(|press| *BUTTON_MAPPING.get(&*press.to_uppercase()).unwrap())
.all(|press| ControlModule::check_button_trigger(module_accessor, press));
let p1_controller_state = *P1_CONTROLLER_STATE.data_ptr();
let this_combo_passes = hold.iter().all(|hold| {
button_mapping(
&*hold.to_uppercase(),
p1_controller_state.style,
p1_controller_state.current_buttons,
)
}) && press.iter().all(|hold| {
button_mapping(
&*hold.to_uppercase(),
p1_controller_state.style,
p1_controller_state.just_down,
)
});
this_combo_passes
}
}
pub fn combo_passes_exclusive(
module_accessor: *mut smash::app::BattleObjectModuleAccessor,
combo: ButtonCombo,
) -> bool {
pub fn combo_passes_exclusive(combo: ButtonCombo) -> bool {
let other_combo_passes = ButtonCombo::iter()
.filter(|other_combo| *other_combo != combo)
.any(|other_combo| combo_passes(module_accessor, other_combo));
combo_passes(module_accessor, combo) && !other_combo_passes
.any(|other_combo| combo_passes(other_combo));
combo_passes(combo) && !other_combo_passes
}
const DEFAULT_BTN_CONFIG: &str = r#"[button_config]
# Available Options:
#
# ATTACK
# SPECIAL
# SHIELD
# GRAB
# JUMP
# UPTAUNT
# DOWNTAUNT
# LEFTTAUNT
# RIGHTTAUNT
# SHARESTOCK
# JUMPMINI
# DPAD_UP
# DPAD_RIGHT
# DPAD_DOWN
# DPAD_LEFT
# A
# B
# X
# Y
# L
# R
# ZL
# ZR
#
# It is recommended to only put one button in the "press" section for each button
# combination, but you can add several buttons to "hold" like this:
# hold=["ATTACK", "SPECIAL",]
# hold=["A", "B",]
#
# SHARESTOCK is typically A+B
# JUMPMINI is the combination of two jump buttons
[button_config.open_menu]
hold=["SPECIAL",]
press=["UPTAUNT",]
hold=["B",]
press=["DPAD_UP",]
[button_config.save_state]
hold=["SHIELD",]
press=["DOWNTAUNT",]
hold=["ZL",]
press=["DPAD_DOWN",]
[button_config.load_state]
hold=["SHIELD",]
press=["UPTAUNT",]
hold=["ZL",]
press=["DPAD_UP",]
[button_config.input_record]
hold=["ATTACK",]
press=["LEFTTAUNT",]
hold=["ZR",]
press=["DPAD_LEFT",]
[button_config.input_playback]
hold=["ATTACK",]
press=["RIGHTTAUNT",]
hold=["ZR",]
press=["DPAD_RIGHT",]
"#;

View file

@ -19,8 +19,8 @@ pub static mut FRAME_COUNTER: u32 = 0;
const MENU_CLOSE_WAIT_FRAMES: u32 = 60;
pub static mut QUICK_MENU_ACTIVE: bool = false;
pub unsafe fn menu_condition(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
button_config::combo_passes_exclusive(module_accessor, button_config::ButtonCombo::OpenMenu)
pub unsafe fn menu_condition() -> bool {
button_config::combo_passes_exclusive(button_config::ButtonCombo::OpenMenu)
}
pub fn load_from_file() {
@ -94,10 +94,12 @@ pub fn handle_final_input_mapping(
out: *mut MappedInputs,
) {
unsafe {
if QUICK_MENU_ACTIVE && player_idx == 0 {
if player_idx == 0 {
*P1_CONTROLLER_STATE.lock() = *controller_struct.controller;
// If we're here, remove all other presses
*out = MappedInputs::default();
if QUICK_MENU_ACTIVE {
// If we're here, remove all other presses
*out = MappedInputs::default();
}
}
}
}
@ -154,13 +156,13 @@ pub unsafe fn quick_menu_loop() {
app.reset_all_submenus();
received_input = true;
});
button_presses.l().then(|| {
(button_presses.l() || button_presses.real_digital_l()).then(|| {
if is_gcc {
app.previous_tab();
}
received_input = true;
});
button_presses.r().then(|| {
(button_presses.r() || button_presses.real_digital_r()).then(|| {
if is_gcc {
app.next_tab();
} else {

View file

@ -180,16 +180,10 @@ pub unsafe fn get_command_flag_cat(module_accessor: &mut BattleObjectModuleAcces
CURRENT_RECORD_SLOT = MENU.recording_slot.into_idx();
if entry_id_int == 0 && !fighter_is_nana {
if button_config::combo_passes_exclusive(
module_accessor,
button_config::ButtonCombo::InputPlayback,
) {
if button_config::combo_passes_exclusive(button_config::ButtonCombo::InputPlayback) {
playback(MENU.playback_button_combination.get_random().into_idx());
} else if MENU.record_trigger == OnOff::On
&& button_config::combo_passes_exclusive(
module_accessor,
button_config::ButtonCombo::InputRecord,
)
&& button_config::combo_passes_exclusive(button_config::ButtonCombo::InputRecord)
{
lockout_record();
}

View file

@ -120,7 +120,7 @@ fn once_per_frame_per_fighter(
}
unsafe {
if menu::menu_condition(module_accessor) {
if menu::menu_condition() {
menu::spawn_menu();
}

View file

@ -408,10 +408,8 @@ pub unsafe fn save_states(module_accessor: &mut app::BattleObjectModuleAccessor)
&& is_dead(module_accessor);
let mut triggered_reset: bool = false;
if !is_operation_cpu(module_accessor) && !fighter_is_nana {
triggered_reset = button_config::combo_passes_exclusive(
module_accessor,
button_config::ButtonCombo::LoadState,
);
triggered_reset =
button_config::combo_passes_exclusive(button_config::ButtonCombo::LoadState);
}
if (autoload_reset || triggered_reset) && !fighter_is_nana {
if save_state.state == NoAction {
@ -626,8 +624,7 @@ pub unsafe fn save_states(module_accessor: &mut app::BattleObjectModuleAccessor)
}
// Save state
if button_config::combo_passes_exclusive(module_accessor, button_config::ButtonCombo::SaveState)
{
if button_config::combo_passes_exclusive(button_config::ButtonCombo::SaveState) {
// Don't begin saving state if Nana's delayed input is captured
MIRROR_STATE = 1.0;
save_state_player(MENU.save_state_slot.as_idx() as usize).state = Save;