mirror of
https://github.com/jugeeya/UltimateTrainingModpack.git
synced 2025-03-11 00:46:11 +00:00
Fixes to hold + consistency
This commit is contained in:
parent
a76808c838
commit
96c10caa6b
4 changed files with 111 additions and 64 deletions
|
@ -1,7 +1,10 @@
|
||||||
use crate::common::menu::P1_CONTROLLER_STATE;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::common::*;
|
use crate::common::*;
|
||||||
use crate::input::{ControllerStyle::*, *};
|
use crate::input::{ControllerStyle::*, *};
|
||||||
|
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
use parking_lot::Mutex;
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
use strum_macros::EnumIter;
|
use strum_macros::EnumIter;
|
||||||
|
|
||||||
|
@ -43,7 +46,7 @@ pub fn button_mapping(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, EnumIter, PartialEq)]
|
#[derive(Debug, EnumIter, PartialEq, Eq, Hash, Copy, Clone)]
|
||||||
pub enum ButtonCombo {
|
pub enum ButtonCombo {
|
||||||
OpenMenu,
|
OpenMenu,
|
||||||
SaveState,
|
SaveState,
|
||||||
|
@ -62,27 +65,32 @@ unsafe fn get_combo_keys(combo: ButtonCombo) -> ButtonConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn combo_passes(combo: ButtonCombo) -> bool {
|
lazy_static! {
|
||||||
|
static ref BUTTON_COMBO_REQUESTS: Mutex<HashMap<ButtonCombo, bool>> =
|
||||||
|
Mutex::new(HashMap::from([
|
||||||
|
(ButtonCombo::OpenMenu, false),
|
||||||
|
(ButtonCombo::SaveState, false),
|
||||||
|
(ButtonCombo::LoadState, false),
|
||||||
|
(ButtonCombo::InputRecord, false),
|
||||||
|
(ButtonCombo::InputPlayback, false),
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn combo_passes(p1_controller: Controller, combo: ButtonCombo) -> bool {
|
||||||
unsafe {
|
unsafe {
|
||||||
let combo_keys = get_combo_keys(combo).to_vec();
|
let combo_keys = get_combo_keys(combo).to_vec();
|
||||||
let p1_controller_state = *P1_CONTROLLER_STATE.data_ptr();
|
|
||||||
|
|
||||||
let mut this_combo_passes = false;
|
let mut this_combo_passes = false;
|
||||||
|
|
||||||
for hold_button in &combo_keys[..] {
|
for hold_button in &combo_keys[..] {
|
||||||
if button_mapping(
|
if button_mapping(
|
||||||
*hold_button,
|
*hold_button,
|
||||||
p1_controller_state.style,
|
p1_controller.style,
|
||||||
p1_controller_state.current_buttons,
|
p1_controller.current_buttons,
|
||||||
) && combo_keys
|
) && combo_keys
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|press_button| **press_button != *hold_button)
|
.filter(|press_button| **press_button != *hold_button)
|
||||||
.all(|press_button| {
|
.all(|press_button| {
|
||||||
button_mapping(
|
button_mapping(*press_button, p1_controller.style, p1_controller.just_down)
|
||||||
*press_button,
|
|
||||||
p1_controller_state.style,
|
|
||||||
p1_controller_state.just_down,
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
this_combo_passes = true;
|
this_combo_passes = true;
|
||||||
|
@ -93,9 +101,39 @@ fn combo_passes(combo: ButtonCombo) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn combo_passes_exclusive(combo: ButtonCombo) -> bool {
|
pub fn _combo_passes_exclusive(p1_controller: Controller, combo: ButtonCombo) -> bool {
|
||||||
let other_combo_passes = ButtonCombo::iter()
|
let other_combo_passes = ButtonCombo::iter()
|
||||||
.filter(|other_combo| *other_combo != combo)
|
.filter(|other_combo| *other_combo != combo)
|
||||||
.any(combo_passes);
|
.any(|other_combo| combo_passes(p1_controller, other_combo));
|
||||||
combo_passes(combo) && !other_combo_passes
|
combo_passes(p1_controller, combo) && !other_combo_passes
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn combo_passes_exclusive(combo: ButtonCombo) -> bool {
|
||||||
|
unsafe {
|
||||||
|
let button_combo_requests = &mut *BUTTON_COMBO_REQUESTS.data_ptr();
|
||||||
|
let passes = button_combo_requests.get_mut(&combo);
|
||||||
|
let mut did_pass = false;
|
||||||
|
if let Some(passes) = passes {
|
||||||
|
if *passes {
|
||||||
|
did_pass = true;
|
||||||
|
}
|
||||||
|
*passes = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
did_pass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn handle_final_input_mapping(player_idx: i32, controller_struct: &SomeControllerStruct) {
|
||||||
|
if player_idx == 0 {
|
||||||
|
let p1_controller = *controller_struct.controller;
|
||||||
|
let button_combo_requests = &mut *BUTTON_COMBO_REQUESTS.lock();
|
||||||
|
button_combo_requests
|
||||||
|
.iter_mut()
|
||||||
|
.for_each(|(combo, is_request)| {
|
||||||
|
if !*is_request {
|
||||||
|
*is_request = _combo_passes_exclusive(p1_controller, *combo);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,18 +78,6 @@ pub fn spawn_menu() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy_static! {
|
|
||||||
pub static ref QUICK_MENU_APP: Mutex<training_mod_tui::App<'static>> = Mutex::new(
|
|
||||||
training_mod_tui::App::new(unsafe { ui_menu(MENU) }, unsafe {
|
|
||||||
(
|
|
||||||
ui_menu(DEFAULTS_MENU),
|
|
||||||
serde_json::to_string(&DEFAULTS_MENU).unwrap(),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
);
|
|
||||||
pub static ref P1_CONTROLLER_STATE: Mutex<Controller> = Mutex::new(Controller::default());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Hash, Copy, Clone)]
|
#[derive(Eq, PartialEq, Hash, Copy, Clone)]
|
||||||
enum DirectionButton {
|
enum DirectionButton {
|
||||||
DpadLeft,
|
DpadLeft,
|
||||||
|
@ -106,6 +94,36 @@ enum DirectionButton {
|
||||||
RUp,
|
RUp,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
pub static ref QUICK_MENU_APP: Mutex<training_mod_tui::App<'static>> = Mutex::new(
|
||||||
|
training_mod_tui::App::new(unsafe { ui_menu(MENU) }, unsafe {
|
||||||
|
(
|
||||||
|
ui_menu(DEFAULTS_MENU),
|
||||||
|
serde_json::to_string(&DEFAULTS_MENU).unwrap(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
);
|
||||||
|
pub static ref P1_CONTROLLER_STYLE: Mutex<ControllerStyle> =
|
||||||
|
Mutex::new(ControllerStyle::default());
|
||||||
|
static ref DIRECTION_HOLD_FRAMES: Mutex<HashMap<DirectionButton, u32>> = {
|
||||||
|
use DirectionButton::*;
|
||||||
|
Mutex::new(HashMap::from([
|
||||||
|
(DpadLeft, 0),
|
||||||
|
(LLeft, 0),
|
||||||
|
(RLeft, 0),
|
||||||
|
(DpadDown, 0),
|
||||||
|
(LDown, 0),
|
||||||
|
(RDown, 0),
|
||||||
|
(DpadRight, 0),
|
||||||
|
(LRight, 0),
|
||||||
|
(RRight, 0),
|
||||||
|
(DpadUp, 0),
|
||||||
|
(LUp, 0),
|
||||||
|
(RUp, 0),
|
||||||
|
]))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub fn handle_final_input_mapping(
|
pub fn handle_final_input_mapping(
|
||||||
player_idx: i32,
|
player_idx: i32,
|
||||||
controller_struct: &SomeControllerStruct,
|
controller_struct: &SomeControllerStruct,
|
||||||
|
@ -113,7 +131,8 @@ pub fn handle_final_input_mapping(
|
||||||
) {
|
) {
|
||||||
unsafe {
|
unsafe {
|
||||||
if player_idx == 0 {
|
if player_idx == 0 {
|
||||||
*P1_CONTROLLER_STATE.lock() = *controller_struct.controller;
|
let p1_controller = *controller_struct.controller;
|
||||||
|
*P1_CONTROLLER_STYLE.lock() = p1_controller.style;
|
||||||
if QUICK_MENU_ACTIVE {
|
if QUICK_MENU_ACTIVE {
|
||||||
// If we're here, remove all other presses
|
// If we're here, remove all other presses
|
||||||
*out = MappedInputs::empty();
|
*out = MappedInputs::empty();
|
||||||
|
@ -122,12 +141,7 @@ pub fn handle_final_input_mapping(
|
||||||
|
|
||||||
const DIRECTION_HOLD_REPEAT_FRAMES: u32 = 20;
|
const DIRECTION_HOLD_REPEAT_FRAMES: u32 = 20;
|
||||||
use DirectionButton::*;
|
use DirectionButton::*;
|
||||||
let directions = [
|
let direction_hold_frames = &mut *DIRECTION_HOLD_FRAMES.lock();
|
||||||
DpadLeft, LLeft, RLeft, DpadDown, LDown, RDown, DpadRight, LRight, RRight,
|
|
||||||
DpadUp, LUp, RUp,
|
|
||||||
];
|
|
||||||
let mut direction_hold_frames: HashMap<DirectionButton, u32> =
|
|
||||||
directions.iter().map(|config| (*config, 0)).collect();
|
|
||||||
|
|
||||||
// Check for all controllers unplugged
|
// Check for all controllers unplugged
|
||||||
let mut potential_controller_ids = (0..8).collect::<Vec<u32>>();
|
let mut potential_controller_ids = (0..8).collect::<Vec<u32>>();
|
||||||
|
@ -140,41 +154,30 @@ pub fn handle_final_input_mapping(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let p1_controller_state = *P1_CONTROLLER_STATE.data_ptr();
|
let style = p1_controller.style;
|
||||||
let style = p1_controller_state.style;
|
let button_presses = p1_controller.just_down;
|
||||||
let button_presses = p1_controller_state.just_down;
|
|
||||||
|
|
||||||
let button_current_held = p1_controller_state.current_buttons;
|
let button_current_held = p1_controller.current_buttons;
|
||||||
let button_released = p1_controller_state.just_release;
|
|
||||||
direction_hold_frames
|
direction_hold_frames
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.for_each(|(direction, frames)| {
|
.for_each(|(direction, frames)| {
|
||||||
let (still_held, released) = match direction {
|
let still_held = match direction {
|
||||||
DpadLeft => {
|
DpadLeft => button_current_held.dpad_left(),
|
||||||
(button_current_held.dpad_left(), button_released.dpad_left())
|
LLeft => button_current_held.l_left(),
|
||||||
}
|
RLeft => button_current_held.r_left(),
|
||||||
LLeft => (button_current_held.l_left(), button_released.l_left()),
|
DpadDown => button_current_held.dpad_down(),
|
||||||
RLeft => (button_current_held.r_left(), button_released.r_left()),
|
LDown => button_current_held.l_down(),
|
||||||
DpadDown => {
|
RDown => button_current_held.r_down(),
|
||||||
(button_current_held.dpad_down(), button_released.dpad_down())
|
DpadRight => button_current_held.dpad_right(),
|
||||||
}
|
LRight => button_current_held.l_right(),
|
||||||
LDown => (button_current_held.l_down(), button_released.l_down()),
|
RRight => button_current_held.r_right(),
|
||||||
RDown => (button_current_held.r_down(), button_released.r_down()),
|
DpadUp => button_current_held.dpad_up(),
|
||||||
DpadRight => (
|
LUp => button_current_held.l_up(),
|
||||||
button_current_held.dpad_right(),
|
RUp => button_current_held.r_up(),
|
||||||
button_released.dpad_right(),
|
|
||||||
),
|
|
||||||
LRight => (button_current_held.l_right(), button_released.l_right()),
|
|
||||||
RRight => (button_current_held.r_right(), button_released.r_right()),
|
|
||||||
DpadUp => (button_current_held.dpad_up(), button_released.dpad_up()),
|
|
||||||
LUp => (button_current_held.l_up(), button_released.l_up()),
|
|
||||||
RUp => (button_current_held.r_up(), button_released.r_up()),
|
|
||||||
};
|
};
|
||||||
if still_held {
|
if still_held {
|
||||||
*frames += 1;
|
*frames += 1;
|
||||||
}
|
} else {
|
||||||
|
|
||||||
if released {
|
|
||||||
*frames = 0;
|
*frames = 0;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -227,6 +230,7 @@ pub fn handle_final_input_mapping(
|
||||||
|| button_presses.r_left()
|
|| button_presses.r_left()
|
||||||
|| [DpadLeft, LLeft, RLeft].iter().any(hold_condition))
|
|| [DpadLeft, LLeft, RLeft].iter().any(hold_condition))
|
||||||
.then(|| {
|
.then(|| {
|
||||||
|
received_input = true;
|
||||||
app.on_left();
|
app.on_left();
|
||||||
});
|
});
|
||||||
(button_presses.dpad_right()
|
(button_presses.dpad_right()
|
||||||
|
@ -234,6 +238,7 @@ pub fn handle_final_input_mapping(
|
||||||
|| button_presses.r_right()
|
|| button_presses.r_right()
|
||||||
|| [DpadRight, LRight, RRight].iter().any(hold_condition))
|
|| [DpadRight, LRight, RRight].iter().any(hold_condition))
|
||||||
.then(|| {
|
.then(|| {
|
||||||
|
received_input = true;
|
||||||
app.on_right();
|
app.on_right();
|
||||||
});
|
});
|
||||||
(button_presses.dpad_up()
|
(button_presses.dpad_up()
|
||||||
|
@ -241,6 +246,7 @@ pub fn handle_final_input_mapping(
|
||||||
|| button_presses.r_up()
|
|| button_presses.r_up()
|
||||||
|| [DpadUp, LUp, RUp].iter().any(hold_condition))
|
|| [DpadUp, LUp, RUp].iter().any(hold_condition))
|
||||||
.then(|| {
|
.then(|| {
|
||||||
|
received_input = true;
|
||||||
app.on_up();
|
app.on_up();
|
||||||
});
|
});
|
||||||
(button_presses.dpad_down()
|
(button_presses.dpad_down()
|
||||||
|
@ -248,10 +254,12 @@ pub fn handle_final_input_mapping(
|
||||||
|| button_presses.r_down()
|
|| button_presses.r_down()
|
||||||
|| [DpadDown, LDown, RDown].iter().any(hold_condition))
|
|| [DpadDown, LDown, RDown].iter().any(hold_condition))
|
||||||
.then(|| {
|
.then(|| {
|
||||||
|
received_input = true;
|
||||||
app.on_down();
|
app.on_down();
|
||||||
});
|
});
|
||||||
|
|
||||||
if received_input {
|
if received_input {
|
||||||
|
direction_hold_frames.iter_mut().for_each(|(_, f)| *f = 0);
|
||||||
set_menu_from_json(&app.get_menu_selections());
|
set_menu_from_json(&app.get_menu_selections());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::common::button_config;
|
||||||
use crate::common::{
|
use crate::common::{
|
||||||
consts::BuffOption, consts::FighterId, consts::MENU, dev_config, get_module_accessor,
|
consts::BuffOption, consts::FighterId, consts::MENU, dev_config, get_module_accessor,
|
||||||
is_training_mode, menu, FIGHTER_MANAGER_ADDR, ITEM_MANAGER_ADDR, STAGE_MANAGER_ADDR,
|
is_training_mode, menu, FIGHTER_MANAGER_ADDR, ITEM_MANAGER_ADDR, STAGE_MANAGER_ADDR,
|
||||||
|
@ -628,6 +629,7 @@ unsafe fn handle_final_input_mapping(
|
||||||
if !is_training_mode() {
|
if !is_training_mode() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
button_config::handle_final_input_mapping(player_idx, controller_struct);
|
||||||
menu::handle_final_input_mapping(player_idx, controller_struct, out);
|
menu::handle_final_input_mapping(player_idx, controller_struct, out);
|
||||||
dev_config::handle_final_input_mapping(player_idx, controller_struct);
|
dev_config::handle_final_input_mapping(player_idx, controller_struct);
|
||||||
input_delay::handle_final_input_mapping(player_idx, out);
|
input_delay::handle_final_input_mapping(player_idx, out);
|
||||||
|
|
|
@ -405,8 +405,7 @@ pub unsafe fn draw(root_pane: &Pane) {
|
||||||
};
|
};
|
||||||
let tab_titles = [prev_tab, tab_selected, next_tab].map(|idx| app_tabs[idx]);
|
let tab_titles = [prev_tab, tab_selected, next_tab].map(|idx| app_tabs[idx]);
|
||||||
|
|
||||||
let is_gcc =
|
let is_gcc = (*common::menu::P1_CONTROLLER_STYLE.data_ptr()) == ControllerStyle::GCController;
|
||||||
(*common::menu::P1_CONTROLLER_STATE.data_ptr()).style == ControllerStyle::GCController;
|
|
||||||
let button_mapping = if is_gcc {
|
let button_mapping = if is_gcc {
|
||||||
GCC_BUTTON_MAPPING.clone()
|
GCC_BUTTON_MAPPING.clone()
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Add table
Reference in a new issue