1
0
Fork 0
mirror of https://github.com/jugeeya/UltimateTrainingModpack.git synced 2025-03-30 02:02:43 +00:00

Update MENU

This commit is contained in:
asimon-1 2024-11-12 22:49:44 -05:00
parent 8c78561cc7
commit 76b38f575e
32 changed files with 369 additions and 372 deletions

View file

@ -3,11 +3,11 @@ use std::collections::HashMap;
use crate::common::menu::{MENU_CLOSE_FRAME_COUNTER, QUICK_MENU_ACTIVE};
use crate::common::ButtonConfig;
use crate::input::{ControllerStyle::*, *};
use training_mod_sync::*;
use crate::training::frame_counter;
use crate::training::ui::menu::VANILLA_MENU_ACTIVE;
use training_mod_consts::{OnOff, MENU};
use training_mod_sync::*;
use strum_macros::EnumIter;
@ -176,10 +176,10 @@ unsafe fn get_combo_keys(combo: ButtonCombo) -> ButtonConfig {
match combo {
// For OpenMenu, have a default in addition to accepting start press
ButtonCombo::OpenMenu => DEFAULT_OPEN_MENU_CONFIG,
ButtonCombo::SaveState => MENU.save_state_save,
ButtonCombo::LoadState => MENU.save_state_load,
ButtonCombo::InputRecord => MENU.input_record,
ButtonCombo::InputPlayback => MENU.input_playback,
ButtonCombo::SaveState => get(&MENU).save_state_save,
ButtonCombo::LoadState => get(&MENU).save_state_load,
ButtonCombo::InputRecord => get(&MENU).input_record,
ButtonCombo::InputPlayback => get(&MENU).input_playback,
}
}
@ -245,7 +245,7 @@ pub fn handle_final_input_mapping(player_idx: i32, controller_struct: &mut SomeC
let mut start_menu_request = false;
let menu_close_wait_frame = frame_counter::get_frame_count(*MENU_CLOSE_FRAME_COUNTER);
if unsafe { MENU.menu_open_start_press == OnOff::ON } {
if get(&MENU).menu_open_start_press == OnOff::ON {
let mut start_hold_frames = read_rwlock(&START_HOLD_FRAMES);
if p1_controller.current_buttons.plus() {
start_hold_frames += 1;

View file

@ -37,7 +37,7 @@ pub fn load_from_file() {
if let Ok(menu_conf_json) = serde_json::from_reader::<BufReader<_>, MenuJsonStruct>(reader)
{
unsafe {
MENU = menu_conf_json.menu;
assign_rwlock(&MENU, menu_conf_json.menu);
DEFAULTS_MENU = menu_conf_json.defaults_menu;
info!("Previous menu found. Loading...");
}
@ -68,7 +68,7 @@ pub unsafe fn set_menu_from_json(message: &str) {
info!("Received menu message: {message}");
if let Ok(message_json) = response {
// Includes both MENU and DEFAULTS_MENU
MENU = message_json.menu;
assign_rwlock(&MENU, message_json.menu);
DEFAULTS_MENU = message_json.defaults_menu;
fs::write(
MENU_OPTIONS_PATH,

View file

@ -5,7 +5,8 @@ use zip::ZipArchive;
use crate::common::dialog;
use crate::consts::*;
use crate::logging::*;
use training_mod_sync::LazyLock;
use training_mod_sync::*;
pub static CURRENT_VERSION: LazyLock<String> = LazyLock::new(|| {
info!("Initialized lazy static value: CURRENT_VERSION");
@ -74,7 +75,7 @@ impl Release {
}
fn get_update_policy() -> UpdatePolicy {
unsafe { MENU.update_policy }
get(&MENU).update_policy
}
fn get_release(beta: bool) -> Result<Release> {

View file

@ -6,7 +6,8 @@ use smash::app::smashball::is_training_mode;
use crate::common::consts::*;
use crate::logging::*;
use training_mod_sync::LazyLock;
use training_mod_sync::*;
use HazardState::*;
use HookState::*;
@ -93,7 +94,7 @@ fn hazard_intercept(_ctx: &skyline::hooks::InlineCtx) {
fn mod_handle_hazards() {
unsafe {
let address = *HAZARD_FLAG_ADDRESS as *mut u8;
*address = (MENU.stage_hazards == OnOff::ON) as u8;
*address = (get(&MENU).stage_hazards == OnOff::ON) as u8;
}
}

View file

@ -5,6 +5,8 @@ use smash::phx::{Hash40, Vector3f};
use crate::common::{consts::*, *};
use crate::logging::*;
use training_mod_sync::*;
pub const ID_COLORS: &[Vector3f] = &[
// used to tint the hitbox effects -- make sure that at least one component
// is equal to 1.0
@ -135,7 +137,7 @@ pub unsafe fn get_command_flag_cat(module_accessor: &mut app::BattleObjectModule
// Resume Effect AnimCMD incase we don't display hitboxes
MotionAnimcmdModule::set_sleep_effect(module_accessor, false);
if MENU.hitbox_vis == OnOff::OFF {
if get(&MENU).hitbox_vis == OnOff::OFF {
return;
}
@ -205,7 +207,7 @@ unsafe fn mod_handle_attack(lua_state: u64) {
// necessary if param object fails
// hacky way of forcing no shield damage on all hitboxes
if MENU.shield_state == Shield::INFINITE {
if get(&MENU).shield_state == Shield::INFINITE {
let mut hitbox_params: Vec<L2CValue> =
(0..36).map(|i| l2c_agent.pop_lua_stack(i + 1)).collect();
l2c_agent.clear_lua_stack();
@ -219,7 +221,7 @@ unsafe fn mod_handle_attack(lua_state: u64) {
}
// Hitbox Visualization
if MENU.hitbox_vis == OnOff::ON {
if get(&MENU).hitbox_vis == OnOff::ON {
// get all necessary grabbox params
let id = l2c_agent.pop_lua_stack(1); // int
let joint = l2c_agent.pop_lua_stack(3); // hash40
@ -274,7 +276,7 @@ unsafe fn handle_catch(lua_state: u64) {
}
unsafe fn mod_handle_catch(lua_state: u64) {
if MENU.hitbox_vis == OnOff::OFF {
if get(&MENU).hitbox_vis == OnOff::OFF {
return;
}

View file

@ -126,38 +126,36 @@ pub fn main() {
info!("Skipping version check because we are using an emulator");
}
unsafe {
notification("Training Modpack".to_string(), "Welcome!".to_string(), 60);
notification(
"Open Menu".to_string(),
if MENU.menu_open_start_press == OnOff::ON {
"Hold Start".to_string()
} else {
DEFAULT_OPEN_MENU_CONFIG.to_string()
},
120,
);
notification(
"Save State".to_string(),
MENU.save_state_save.to_string(),
120,
);
notification(
"Load State".to_string(),
MENU.save_state_load.to_string(),
120,
);
notification(
"Input Record".to_string(),
MENU.input_record.to_string(),
120,
);
notification(
"Input Playback".to_string(),
MENU.input_playback.to_string(),
120,
);
}
notification("Training Modpack".to_string(), "Welcome!".to_string(), 60);
notification(
"Open Menu".to_string(),
if get(&MENU).menu_open_start_press == OnOff::ON {
"Hold Start".to_string()
} else {
DEFAULT_OPEN_MENU_CONFIG.to_string()
},
120,
);
notification(
"Save State".to_string(),
get(&MENU).save_state_save.to_string(),
120,
);
notification(
"Load State".to_string(),
get(&MENU).save_state_load.to_string(),
120,
);
notification(
"Input Record".to_string(),
get(&MENU).input_record.to_string(),
120,
);
notification(
"Input Playback".to_string(),
get(&MENU).input_playback.to_string(),
120,
);
std::thread::spawn(events_loop);
}

View file

@ -5,8 +5,8 @@ use smash::lib::lua_const::*;
use crate::common::consts::*;
use crate::common::*;
use training_mod_sync::*;
use crate::training::directional_influence::should_reverse_angle;
use training_mod_sync::*;
static AIRDODGE_STICK_DIRECTION: RwLock<Direction> = RwLock::new(Direction::empty());
@ -32,7 +32,10 @@ unsafe fn get_angle(module_accessor: &mut app::BattleObjectModuleAccessor) -> Op
return None;
}
assign_rwlock(&AIRDODGE_STICK_DIRECTION, MENU.air_dodge_dir.get_random());
assign_rwlock(
&AIRDODGE_STICK_DIRECTION,
get(&MENU).air_dodge_dir.get_random(),
);
let direction = read_rwlock(&AIRDODGE_STICK_DIRECTION);
direction.into_angle().map(|angle| {
if !should_reverse_angle(direction) {

View file

@ -7,9 +7,10 @@ use training_mod_sync::*;
static ATTACK_ANGLE_DIRECTION: RwLock<AttackAngle> = RwLock::new(AttackAngle::NEUTRAL);
pub fn roll_direction() {
unsafe {
assign_rwlock(&ATTACK_ANGLE_DIRECTION, MENU.attack_angle.get_random());
}
assign_rwlock(
&ATTACK_ANGLE_DIRECTION,
get(&MENU).attack_angle.get_random(),
);
}
pub unsafe fn mod_get_stick_dir(

View file

@ -5,10 +5,11 @@ use smash::phx::{Hash40, Vector3f};
use crate::common::consts::*;
use crate::is_operation_cpu;
use training_mod_sync::*;
use crate::training::frame_counter;
use crate::training::handle_add_limit;
use training_mod_sync::*;
static BUFF_REMAINING_PLAYER: RwLock<usize> = RwLock::new(0);
static BUFF_REMAINING_CPU: RwLock<usize> = RwLock::new(0);
@ -77,7 +78,7 @@ pub unsafe fn handle_buffs(
CameraModule::stop_quake(module_accessor, *CAMERA_QUAKE_KIND_M); // stops Psyche-Up quake
CameraModule::stop_quake(module_accessor, *CAMERA_QUAKE_KIND_S); // stops Monado Art quake
let menu_vec = MENU.buff_state;
let menu_vec = get(&MENU).buff_state;
if fighter_kind == *FIGHTER_KIND_BRAVE {
return buff_hero(module_accessor, status);
@ -102,7 +103,7 @@ pub unsafe fn handle_buffs(
}
unsafe fn buff_hero(module_accessor: &mut app::BattleObjectModuleAccessor, status: i32) -> bool {
let buff_vec: Vec<BuffOption> = MENU.buff_state.hero_buffs().to_vec();
let buff_vec: Vec<BuffOption> = get(&MENU).buff_state.hero_buffs().to_vec();
if !is_buffing(module_accessor) {
// Initial set up for spells
start_buff(module_accessor);
@ -239,7 +240,7 @@ unsafe fn buff_sepiroth(module_accessor: &mut app::BattleObjectModuleAccessor) -
unsafe fn buff_wario(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
if !is_buffing(module_accessor) {
let waft_level: BuffOption = MENU.buff_state.wario_buffs().get_random();
let waft_level: BuffOption = get(&MENU).buff_state.wario_buffs().get_random();
let waft_count_secs = match waft_level {
BuffOption::WAFT_MINI => WorkModule::get_param_float(
module_accessor,
@ -275,7 +276,7 @@ unsafe fn buff_wario(module_accessor: &mut app::BattleObjectModuleAccessor) -> b
}
unsafe fn buff_shulk(module_accessor: &mut app::BattleObjectModuleAccessor, status: i32) -> bool {
let current_art = MENU.buff_state.shulk_buffs().get_random();
let current_art = get(&MENU).buff_state.shulk_buffs().get_random();
if current_art == BuffOption::empty() {
// No Monado Arts selected in the buff menu, so we don't need to buff
return true;

View file

@ -47,7 +47,7 @@ pub unsafe fn handle_clatter(module_accessor: &mut BattleObjectModuleAccessor) {
// Don't do clatter inputs if we're not in clatter
return;
}
let repeat = MENU.clatter_strength.into_u32();
let repeat = get(&MENU).clatter_strength.into_u32();
let mut counter_guard = lock_write_rwlock(&COUNTER);
*counter_guard = ((*counter_guard) + 1) % repeat;

View file

@ -3,10 +3,11 @@ use training_mod_consts::OnOff;
use crate::common::*;
use crate::consts::Action;
use training_mod_sync::*;
use crate::training::ui::notifications;
use crate::training::*;
use training_mod_sync::*;
static PLAYER_WAS_ACTIONABLE: RwLock<bool> = RwLock::new(false);
static CPU_WAS_ACTIONABLE: RwLock<bool> = RwLock::new(false);
@ -49,37 +50,35 @@ unsafe fn is_actionable(module_accessor: *mut BattleObjectModuleAccessor) -> boo
}
fn update_frame_advantage(frame_advantage: i32) {
unsafe {
if MENU.frame_advantage == OnOff::ON {
// Prioritize Frame Advantage over Input Recording Playback
notifications::clear_notifications_except("Input Recording");
notifications::clear_notifications_except("Frame Advantage");
notifications::color_notification(
"Frame Advantage".to_string(),
format!("{frame_advantage}"),
60,
match frame_advantage {
x if x < 0 => ResColor {
r: 200,
g: 8,
b: 8,
a: 255,
},
0 => ResColor {
r: 0,
g: 0,
b: 0,
a: 255,
},
_ => ResColor {
r: 31,
g: 198,
b: 0,
a: 255,
},
if get(&MENU).frame_advantage == OnOff::ON {
// Prioritize Frame Advantage over Input Recording Playback
notifications::clear_notifications_except("Input Recording");
notifications::clear_notifications_except("Frame Advantage");
notifications::color_notification(
"Frame Advantage".to_string(),
format!("{frame_advantage}"),
60,
match frame_advantage {
x if x < 0 => ResColor {
r: 200,
g: 8,
b: 8,
a: 255,
},
);
}
0 => ResColor {
r: 0,
g: 0,
b: 0,
a: 255,
},
_ => ResColor {
r: 31,
g: 198,
b: 0,
a: 255,
},
},
);
}
}
@ -101,7 +100,7 @@ pub unsafe fn once_per_frame(module_accessor: &mut BattleObjectModuleAccessor) {
|| frame_counter::is_counting(*CPU_FRAME_COUNTER_INDEX);
if !is_counting {
if MENU.mash_state == Action::empty()
if get(&MENU).mash_state == Action::empty()
&& !player_is_actionable
&& !cpu_is_actionable
&& (!was_in_shieldstun(cpu_module_accessor) && is_in_shieldstun(cpu_module_accessor)

View file

@ -4,13 +4,15 @@ use smash::lib::lua_const::*;
use crate::common::consts::OnOff;
use crate::common::*;
use training_mod_sync::*;
pub unsafe fn mod_get_stick_y(module_accessor: &mut BattleObjectModuleAccessor) -> Option<f32> {
if !is_operation_cpu(module_accessor) {
return None;
}
let fighter_status_kind = StatusModule::status_kind(module_accessor);
if MENU.crouch == OnOff::ON
if get(&MENU).crouch == OnOff::ON
&& [
*FIGHTER_STATUS_KIND_WAIT,
*FIGHTER_STATUS_KIND_SQUAT,

View file

@ -12,15 +12,12 @@ use training_mod_sync::*;
static DI_CASE: RwLock<Direction> = RwLock::new(Direction::empty());
pub fn roll_di_case() {
unsafe {
let mut di_case_guard = lock_write_rwlock(&DI_CASE);
if *di_case_guard != Direction::empty() {
// DI direction already selected, don't pick a new one
return;
}
*di_case_guard = MENU.di_state.get_random();
let mut di_case_guard = lock_write_rwlock(&DI_CASE);
if *di_case_guard != Direction::empty() {
// DI direction already selected, don't pick a new one
return;
}
*di_case_guard = get(&MENU).di_state.get_random();
}
pub fn reset_di_case(module_accessor: &mut app::BattleObjectModuleAccessor) {
@ -47,7 +44,7 @@ pub unsafe fn handle_correct_damage_vector_common(
}
unsafe fn mod_handle_di(fighter: &L2CFighterCommon, _arg1: L2CValue) {
if MENU.di_state == Direction::empty() {
if get(&MENU).di_state == Direction::empty() {
return;
}

View file

@ -3,9 +3,10 @@ use smash::lib::lua_const::*;
use smash::phx::{Hash40, Vector3f};
use crate::common::*;
use training_mod_sync::*;
use crate::training::{frame_counter, input_record};
use training_mod_sync::*;
static DELAY: RwLock<u32> = RwLock::new(0);
static FAST_FALL: RwLock<bool> = RwLock::new(false);
static FRAME_COUNTER_INDEX: LazyLock<usize> =
@ -16,9 +17,7 @@ fn should_fast_fall() -> bool {
}
pub fn roll_fast_fall() {
unsafe {
assign_rwlock(&FAST_FALL, MENU.fast_fall.get_random().into_bool());
}
assign_rwlock(&FAST_FALL, get(&MENU).fast_fall.get_random().into_bool());
}
pub fn get_command_flag_cat(module_accessor: &mut app::BattleObjectModuleAccessor) {
@ -38,7 +37,7 @@ pub fn get_command_flag_cat(module_accessor: &mut app::BattleObjectModuleAccesso
unsafe {
if !is_falling(module_accessor) {
// Roll FF delay
assign_rwlock(&DELAY, MENU.fast_fall_delay.get_random().into_delay());
assign_rwlock(&DELAY, get(&MENU).fast_fall_delay.get_random().into_delay());
frame_counter::full_reset(*FRAME_COUNTER_INDEX);
return;
}

View file

@ -13,9 +13,7 @@ pub fn should_full_hop() -> bool {
}
pub fn roll_full_hop() {
unsafe {
assign_rwlock(&FULL_HOP, MENU.full_hop.get_random().into_bool());
}
assign_rwlock(&FULL_HOP, get(&MENU).full_hop.get_random().into_bool());
}
pub unsafe fn check_button_on(

View file

@ -4,6 +4,8 @@ use crate::common::input::*;
use lazy_static::lazy_static;
use parking_lot::Mutex;
use training_mod_sync::*;
use crate::common::MENU;
lazy_static! {
@ -17,14 +19,14 @@ pub fn handle_final_input_mapping(player_idx: i32, out: *mut MappedInputs) {
let mut delayed_mappings = P1_DELAYED_INPUT_MAPPINGS.lock();
let actual_mapping = *out;
if delayed_mappings.len() < MENU.input_delay.into_delay() as usize {
if delayed_mappings.len() < get(&MENU).input_delay.into_delay() as usize {
*out = MappedInputs::empty();
} else if let Some(delayed_mapping) = delayed_mappings.back() {
*out = *delayed_mapping;
}
delayed_mappings.push_front(actual_mapping);
delayed_mappings.truncate(MENU.input_delay.into_delay() as usize);
delayed_mappings.truncate(get(&MENU).input_delay.into_delay() as usize);
}
}
}

View file

@ -3,11 +3,11 @@ use std::collections::VecDeque;
use crate::common::input::*;
use crate::menu::QUICK_MENU_ACTIVE;
use training_mod_sync::*;
use crate::try_get_module_accessor;
use skyline::nn::ui2d::ResColor;
use smash::app::{lua_bind::*, utility};
use training_mod_consts::{FighterId, InputDisplay, MENU};
use training_mod_sync::*;
use super::{frame_counter, input_record::STICK_CLAMP_MULTIPLIER};
@ -136,50 +136,51 @@ fn bin_stick_values(x: i8, y: i8) -> (DirectionStrength, f32) {
impl InputLog {
pub fn is_different(&self, other: &InputLog) -> bool {
unsafe {
match MENU.input_display {
InputDisplay::SMASH => self.is_smash_different(other),
InputDisplay::RAW => self.is_raw_different(other),
InputDisplay::STATUS => self.is_status_different(other),
InputDisplay::NONE => false,
_ => panic!("Invalid value in is_different: {}", MENU.input_display),
}
match get(&MENU).input_display {
InputDisplay::SMASH => self.is_smash_different(other),
InputDisplay::RAW => self.is_raw_different(other),
InputDisplay::STATUS => self.is_status_different(other),
InputDisplay::NONE => false,
_ => panic!(
"Invalid value in is_different: {}",
get(&MENU).input_display
),
}
}
pub fn binned_lstick(&self) -> (DirectionStrength, f32) {
unsafe {
match MENU.input_display {
InputDisplay::SMASH => self.smash_binned_lstick(),
InputDisplay::RAW => self.raw_binned_lstick(),
InputDisplay::STATUS => (DirectionStrength::None, 0.0),
InputDisplay::NONE => panic!("Invalid input display to log"),
_ => panic!("Invalid value in binned_lstick: {}", MENU.input_display),
}
match get(&MENU).input_display {
InputDisplay::SMASH => self.smash_binned_lstick(),
InputDisplay::RAW => self.raw_binned_lstick(),
InputDisplay::STATUS => (DirectionStrength::None, 0.0),
InputDisplay::NONE => panic!("Invalid input display to log"),
_ => panic!(
"Invalid value in binned_lstick: {}",
get(&MENU).input_display
),
}
}
pub fn binned_rstick(&self) -> (DirectionStrength, f32) {
unsafe {
match MENU.input_display {
InputDisplay::SMASH => self.smash_binned_rstick(),
InputDisplay::RAW => self.raw_binned_rstick(),
InputDisplay::STATUS => (DirectionStrength::None, 0.0),
InputDisplay::NONE => panic!("Invalid input display to log"),
_ => panic!("Invalid value in binned_rstick: {}", MENU.input_display),
}
match get(&MENU).input_display {
InputDisplay::SMASH => self.smash_binned_rstick(),
InputDisplay::RAW => self.raw_binned_rstick(),
InputDisplay::STATUS => (DirectionStrength::None, 0.0),
InputDisplay::NONE => panic!("Invalid input display to log"),
_ => panic!(
"Invalid value in binned_rstick: {}",
get(&MENU).input_display
),
}
}
pub fn button_icons(&self) -> VecDeque<(&str, ResColor)> {
unsafe {
match MENU.input_display {
InputDisplay::SMASH => self.smash_button_icons(),
InputDisplay::RAW => self.raw_button_icons(),
InputDisplay::STATUS => VecDeque::new(),
InputDisplay::NONE => panic!("Invalid input display to log"),
_ => unreachable!(),
}
match get(&MENU).input_display {
InputDisplay::SMASH => self.smash_button_icons(),
InputDisplay::RAW => self.raw_button_icons(),
InputDisplay::STATUS => VecDeque::new(),
InputDisplay::NONE => panic!("Invalid input display to log"),
_ => unreachable!(),
}
}
@ -260,14 +261,12 @@ impl InputLog {
self.smash_inputs.buttons != other.smash_inputs.buttons
|| self.smash_binned_lstick() != other.smash_binned_lstick()
|| self.smash_binned_rstick() != other.smash_binned_rstick()
|| (unsafe { MENU.input_display_status.as_bool() } && self.status != other.status)
|| (get(&MENU).input_display_status.as_bool() && self.status != other.status)
}
fn is_status_different(&self, other: &InputLog) -> bool {
unsafe {
let input_display_status = MENU.input_display_status.as_bool();
input_display_status && (self.status != other.status)
}
let input_display_status = get(&MENU).input_display_status.as_bool();
input_display_status && (self.status != other.status)
}
fn smash_binned_lstick(&self) -> (DirectionStrength, f32) {
@ -282,7 +281,7 @@ impl InputLog {
self.raw_inputs.current_buttons != other.raw_inputs.current_buttons
|| self.raw_binned_lstick() != other.raw_binned_lstick()
|| self.raw_binned_rstick() != other.raw_binned_rstick()
|| (unsafe { MENU.input_display_status.as_bool() } && self.status != other.status)
|| (get(&MENU).input_display_status.as_bool() && self.status != other.status)
}
fn raw_binned_lstick(&self) -> (DirectionStrength, f32) {
@ -316,7 +315,7 @@ pub fn handle_final_input_mapping(
out: *mut MappedInputs,
) {
unsafe {
if MENU.input_display == InputDisplay::NONE {
if get(&MENU).input_display == InputDisplay::NONE {
return;
}

View file

@ -20,6 +20,8 @@ use crate::training::mash;
use crate::training::ui::notifications::{clear_notifications_except, color_notification};
use crate::{error, warn};
use training_mod_sync::*;
#[derive(PartialEq, Debug)]
pub enum InputRecordState {
None,
@ -104,17 +106,18 @@ unsafe fn should_mash_playback() {
if is_in_hitstun(&mut *cpu_module_accessor) {
// if we're in hitstun and want to enter the frame we start hitstop for SDI, start if we're in any damage status instantly
if MENU.hitstun_playback == HitstunPlayback::INSTANT {
if get(&MENU).hitstun_playback == HitstunPlayback::INSTANT {
should_playback = true;
}
// if we want to wait until we exit hitstop and begin flying away for shield art etc, start if we're not in hitstop
if MENU.hitstun_playback == HitstunPlayback::HITSTOP
if get(&MENU).hitstun_playback == HitstunPlayback::HITSTOP
&& !StopModule::is_stop(cpu_module_accessor)
{
should_playback = true;
}
// if we're in hitstun and want to wait till FAF to act, then we want to match our starting status to the correct transition term to see if we can hitstun cancel
if MENU.hitstun_playback == HitstunPlayback::HITSTUN && can_transition(cpu_module_accessor)
if get(&MENU).hitstun_playback == HitstunPlayback::HITSTUN
&& can_transition(cpu_module_accessor)
{
should_playback = true;
}
@ -193,12 +196,12 @@ unsafe fn handle_recording_for_fighter(module_accessor: &mut BattleObjectModuleA
let fighter_kind = utility::get_kind(module_accessor);
let fighter_is_nana = fighter_kind == *FIGHTER_KIND_NANA;
CURRENT_RECORD_SLOT = MENU.recording_slot.into_idx().unwrap_or(0);
CURRENT_RECORD_SLOT = get(&MENU).recording_slot.into_idx().unwrap_or(0);
if entry_id_int == 0 && !fighter_is_nana {
if button_config::combo_passes(button_config::ButtonCombo::InputPlayback) {
playback(MENU.playback_button_slots.get_random().into_idx());
} else if MENU.record_trigger.contains(&RecordTrigger::COMMAND)
playback(get(&MENU).playback_button_slots.get_random().into_idx());
} else if get(&MENU).record_trigger.contains(&RecordTrigger::COMMAND)
&& button_config::combo_passes(button_config::ButtonCombo::InputRecord)
{
lockout_record();
@ -217,7 +220,9 @@ unsafe fn handle_recording_for_fighter(module_accessor: &mut BattleObjectModuleA
// If we need to crop the recording for neutral input
// INPUT_RECORD_FRAME must be > 0 to prevent bounding errors
if INPUT_RECORD == Record && MENU.recording_crop == OnOff::ON && INPUT_RECORD_FRAME > 0
if INPUT_RECORD == Record
&& get(&MENU).recording_crop == OnOff::ON
&& INPUT_RECORD_FRAME > 0
{
while INPUT_RECORD_FRAME > 0 && is_input_neutral(INPUT_RECORD_FRAME - 1) {
// Discard frames at the end of the recording until the last frame with input
@ -229,7 +234,7 @@ unsafe fn handle_recording_for_fighter(module_accessor: &mut BattleObjectModuleA
INPUT_RECORD_FRAME = 0;
if MENU.playback_loop == OnOff::ON && INPUT_RECORD == Playback {
if get(&MENU).playback_loop == OnOff::ON && INPUT_RECORD == Playback {
playback(Some(CURRENT_PLAYBACK_SLOT));
} else {
INPUT_RECORD = None;
@ -327,7 +332,7 @@ pub unsafe fn lockout_record() {
.for_each(|mapped_input| {
*mapped_input = MappedInputs::empty();
});
CURRENT_FRAME_LENGTH = MENU.recording_duration.into_frames();
CURRENT_FRAME_LENGTH = get(&MENU).recording_duration.into_frames();
P1_FRAME_LENGTH_MAPPING.lock()[CURRENT_RECORD_SLOT] = CURRENT_FRAME_LENGTH;
LOCKOUT_FRAME = 30; // This needs to be this high or issues occur dropping shield - but does this cause problems when trying to record ledge?
BUFFER_FRAME = 0;

View file

@ -3,9 +3,10 @@ use smash::lib::lua_const::*;
use crate::common::consts::*;
use crate::common::*;
use training_mod_sync::*;
use crate::training::{frame_counter, input_record, mash};
use training_mod_sync::*;
const NOT_SET: u32 = 9001;
static LEDGE_DELAY: RwLock<u32> = RwLock::new(NOT_SET);
static LEDGE_CASE: RwLock<LedgeOption> = RwLock::new(LedgeOption::empty());
@ -35,10 +36,7 @@ fn roll_ledge_delay() {
// Don't roll another ledge delay if one is already selected
return;
}
unsafe {
*ledge_delay_guard = MENU.ledge_delay.get_random().into_longdelay();
}
*ledge_delay_guard = get(&MENU).ledge_delay.get_random().into_longdelay();
}
fn roll_ledge_case() {
@ -48,48 +46,43 @@ fn roll_ledge_case() {
if *ledge_case_guard != LedgeOption::empty() {
return;
}
unsafe {
*ledge_case_guard = MENU.ledge_state.get_random();
}
*ledge_case_guard = get(&MENU).ledge_state.get_random();
}
fn get_ledge_option() -> Option<Action> {
unsafe {
let mut override_action: Option<Action> = None;
let regular_action = if MENU.mash_triggers.contains(&MashTrigger::LEDGE) {
Some(MENU.mash_state.get_random())
} else {
None
};
let mut override_action: Option<Action> = None;
let regular_action = if get(&MENU).mash_triggers.contains(&MashTrigger::LEDGE) {
Some(get(&MENU).mash_state.get_random())
} else {
None
};
match read_rwlock(&LEDGE_CASE) {
LedgeOption::NEUTRAL => {
if MENU.ledge_neutral_override != Action::empty() {
override_action = Some(MENU.ledge_neutral_override.get_random());
}
}
LedgeOption::ROLL => {
if MENU.ledge_roll_override != Action::empty() {
override_action = Some(MENU.ledge_roll_override.get_random());
}
}
LedgeOption::JUMP => {
if MENU.ledge_jump_override != Action::empty() {
override_action = Some(MENU.ledge_jump_override.get_random());
}
}
LedgeOption::ATTACK => {
if MENU.ledge_attack_override != Action::empty() {
override_action = Some(MENU.ledge_attack_override.get_random());
}
}
_ => {
override_action = None;
match read_rwlock(&LEDGE_CASE) {
LedgeOption::NEUTRAL => {
if get(&MENU).ledge_neutral_override != Action::empty() {
override_action = Some(get(&MENU).ledge_neutral_override.get_random());
}
}
override_action.or(regular_action)
LedgeOption::ROLL => {
if get(&MENU).ledge_roll_override != Action::empty() {
override_action = Some(get(&MENU).ledge_roll_override.get_random());
}
}
LedgeOption::JUMP => {
if get(&MENU).ledge_jump_override != Action::empty() {
override_action = Some(get(&MENU).ledge_jump_override.get_random());
}
}
LedgeOption::ATTACK => {
if get(&MENU).ledge_attack_override != Action::empty() {
override_action = Some(get(&MENU).ledge_attack_override.get_random());
}
}
_ => {
override_action = None;
}
}
override_action.or(regular_action)
}
pub unsafe fn force_option(module_accessor: &mut app::BattleObjectModuleAccessor) {
@ -137,7 +130,7 @@ pub unsafe fn force_option(module_accessor: &mut app::BattleObjectModuleAccessor
// We buffer playback on frame 18 because we don't change status this frame from inputting on next frame; do we need to do one earlier for lasso?
if should_buffer_playback
&& ledge_case.is_playback()
&& MENU.ledge_delay != LongDelay::empty()
&& get(&MENU).ledge_delay != LongDelay::empty()
{
input_record::playback_ledge(ledge_case.playback_slot());
return;
@ -180,7 +173,7 @@ pub unsafe fn is_enable_transition_term(
// Only handle ledge scenarios from menu
if StatusModule::status_kind(_module_accessor) != *FIGHTER_STATUS_KIND_CLIFF_WAIT
|| MENU.ledge_state == LedgeOption::empty()
|| get(&MENU).ledge_state == LedgeOption::empty()
{
return None;
}
@ -210,7 +203,7 @@ pub fn get_command_flag_cat(module_accessor: &mut app::BattleObjectModuleAccesso
return;
}
if MENU.ledge_state == LedgeOption::empty() {
if get(&MENU).ledge_state == LedgeOption::empty() {
return;
}

View file

@ -11,6 +11,8 @@ use crate::training::input_record;
use crate::training::shield;
use crate::training::{attack_angle, save_states};
use training_mod_sync::*;
use once_cell::sync::Lazy;
const DISTANCE_CLOSE_THRESHOLD: f32 = 16.0;
@ -80,7 +82,7 @@ pub fn buffer_action(action: Action) {
unsafe {
// exit playback if we want to perform mash actions out of it
// TODO: Figure out some way to deal with trying to playback into another playback
if MENU.playback_mash == OnOff::ON
if get(&MENU).playback_mash == OnOff::ON
&& input_record::is_playback()
&& !input_record::is_recording()
&& !input_record::is_standby()
@ -108,9 +110,7 @@ pub fn buffer_action(action: Action) {
pub fn buffer_follow_up() {
let action;
unsafe {
action = MENU.follow_up.get_random();
}
action = get(&MENU).follow_up.get_random();
if action == Action::empty() {
return;
@ -216,91 +216,100 @@ unsafe fn get_buffered_action(
return None;
}
let fighter_distance = get_fighter_distance();
let menu = get(&MENU);
if is_in_tech(module_accessor) {
let action = MENU.tech_action_override.get_random();
let action = menu.tech_action_override.get_random();
if action != Action::empty() {
Some(action)
} else if MENU.mash_triggers.contains(&MashTrigger::TECH) {
Some(MENU.mash_state.get_random())
} else if menu.mash_triggers.contains(&MashTrigger::TECH) {
Some(menu.mash_state.get_random())
} else {
None
}
} else if is_in_clatter(module_accessor) {
let action = MENU.clatter_override.get_random();
let action = menu.clatter_override.get_random();
if action != Action::empty() {
Some(action)
} else if MENU.mash_triggers.contains(&MashTrigger::CLATTER) {
Some(MENU.mash_state.get_random())
} else if menu.mash_triggers.contains(&MashTrigger::CLATTER) {
Some(menu.mash_state.get_random())
} else {
None
}
} else if is_in_tumble(module_accessor) {
// Note that the tumble check needs to come before hitstun,
// otherwise the hitstun check will always return first
let action = MENU.tumble_override.get_random();
let action = menu.tumble_override.get_random();
if action != Action::empty() {
Some(action)
} else if MENU.mash_triggers.contains(&MashTrigger::TUMBLE) {
Some(MENU.mash_state.get_random())
} else if menu.mash_triggers.contains(&MashTrigger::TUMBLE) {
Some(menu.mash_state.get_random())
} else {
None
}
} else if is_in_hitstun(module_accessor) {
let action = MENU.hitstun_override.get_random();
let action = menu.hitstun_override.get_random();
if action != Action::empty() {
Some(action)
} else if MENU.mash_triggers.contains(&MashTrigger::HIT) {
Some(MENU.mash_state.get_random())
} else if menu.mash_triggers.contains(&MashTrigger::HIT) {
Some(menu.mash_state.get_random())
} else {
None
}
} else if is_in_parry(module_accessor) {
let action = MENU.parry_override.get_random();
let action = menu.parry_override.get_random();
if action != Action::empty() {
Some(action)
} else if MENU.mash_triggers.contains(&MashTrigger::PARRY) {
Some(MENU.mash_state.get_random())
} else if menu.mash_triggers.contains(&MashTrigger::PARRY) {
Some(menu.mash_state.get_random())
} else {
None
}
} else if is_in_footstool(module_accessor) {
let action = MENU.footstool_override.get_random();
let action = menu.footstool_override.get_random();
if action != Action::empty() {
Some(action)
} else if MENU.mash_triggers.contains(&MashTrigger::FOOTSTOOL) {
Some(MENU.mash_state.get_random())
} else if menu.mash_triggers.contains(&MashTrigger::FOOTSTOOL) {
Some(menu.mash_state.get_random())
} else {
None
}
} else if is_in_ledgetrump(module_accessor) {
let action = MENU.trump_override.get_random();
let action = menu.trump_override.get_random();
if action != Action::empty() {
Some(action)
} else if MENU.mash_triggers.contains(&MashTrigger::TRUMP) {
Some(MENU.mash_state.get_random())
} else if menu.mash_triggers.contains(&MashTrigger::TRUMP) {
Some(menu.mash_state.get_random())
} else {
None
}
} else if is_in_landing(module_accessor) {
let action = MENU.landing_override.get_random();
let action = menu.landing_override.get_random();
if action != Action::empty() {
Some(action)
} else if MENU.mash_triggers.contains(&MashTrigger::LANDING) {
Some(MENU.mash_state.get_random())
} else if menu.mash_triggers.contains(&MashTrigger::LANDING) {
Some(menu.mash_state.get_random())
} else {
None
}
} else if (MENU.mash_triggers.contains(&MashTrigger::GROUNDED) && is_grounded(module_accessor))
|| (MENU.mash_triggers.contains(&MashTrigger::AIRBORNE) && is_airborne(module_accessor))
|| (MENU.mash_triggers.contains(&MashTrigger::DISTANCE_CLOSE)
} else if (menu.mash_triggers.contains(&MashTrigger::GROUNDED)
&& is_grounded(module_accessor))
|| (menu.mash_triggers.contains(&MashTrigger::AIRBORNE)
&& is_airborne(module_accessor))
|| (menu
.mash_triggers
.contains(&MashTrigger::DISTANCE_CLOSE)
&& fighter_distance < DISTANCE_CLOSE_THRESHOLD)
|| (MENU.mash_triggers.contains(&MashTrigger::DISTANCE_MID)
|| (menu
.mash_triggers
.contains(&MashTrigger::DISTANCE_MID)
&& fighter_distance < DISTANCE_MID_THRESHOLD)
|| (MENU.mash_triggers.contains(&MashTrigger::DISTANCE_FAR)
|| (menu
.mash_triggers
.contains(&MashTrigger::DISTANCE_FAR)
&& fighter_distance < DISTANCE_FAR_THRESHOLD)
|| MENU.mash_triggers.contains(&MashTrigger::ALWAYS)
|| menu.mash_triggers.contains(&MashTrigger::ALWAYS)
{
Some(MENU.mash_state.get_random())
Some(menu.mash_state.get_random())
} else {
// SHIELD handled in shield.rs
// LEDGE handled in ledge.rs
@ -313,7 +322,7 @@ fn buffer_menu_mash(action: Action) {
buffer_action(action);
full_hop::roll_full_hop();
fast_fall::roll_fast_fall();
FALLING_AERIAL = MENU.falling_aerials.get_random().into_bool();
FALLING_AERIAL = get(&MENU).falling_aerials.get_random().into_bool();
}
}
@ -577,7 +586,7 @@ fn roll_aerial_delay(action: Action) {
return;
}
unsafe {
AERIAL_DELAY = MENU.aerial_delay.get_random().into_delay();
AERIAL_DELAY = get(&MENU).aerial_delay.get_random().into_delay();
}
}

View file

@ -10,7 +10,6 @@ use crate::common::{
use crate::hitbox_visualizer;
use crate::input::*;
use crate::logging::*;
use training_mod_sync::*;
use crate::training::character_specific::{items, kirby, pikmin, ptrainer};
use skyline::hooks::{getRegionAddress, InlineCtx, Region};
use skyline::nn::ro::LookupSymbol;
@ -20,6 +19,7 @@ use smash::app::{
use smash::lib::lua_const::*;
use smash::params::*;
use smash::phx::{Hash40, Vector3f};
use training_mod_sync::*;
pub mod buff;
pub mod charge;
@ -134,7 +134,7 @@ fn once_per_frame_per_fighter(module_accessor: &mut BattleObjectModuleAccessor,
// Handle dodge staling here b/c input recording or mash can cause dodging
WorkModule::set_flag(
module_accessor,
!(MENU.stale_dodges.as_bool()),
!(get(&MENU).stale_dodges.as_bool()),
*FIGHTER_INSTANCE_WORK_ID_FLAG_DISABLE_ESCAPE_PENALTY,
);
input_record::handle_recording();
@ -428,7 +428,7 @@ pub unsafe fn handle_add_damage(
#[skyline::hook(offset = *OFFSET_TRAINING_RESET_CHECK, inline)]
unsafe fn lra_handle(ctx: &mut InlineCtx) {
let x8 = ctx.registers[8].x.as_mut();
if !(MENU.lra_reset.as_bool()) {
if !(get(&MENU).lra_reset.as_bool()) {
*x8 = 0;
}
}
@ -766,7 +766,7 @@ pub unsafe fn handle_reused_ui(
// If Little Mac is in the game and we're buffing him, set the meter to 100
if (player_fighter_kind == *FIGHTER_KIND_LITTLEMAC
|| cpu_fighter_kind == *FIGHTER_KIND_LITTLEMAC)
&& MENU.buff_state.contains(&BuffOption::KO)
&& get(&MENU).buff_state.contains(&BuffOption::KO)
{
param_2 = 100;
}

View file

@ -27,7 +27,6 @@ use crate::common::get_module_accessor;
use crate::common::is_dead;
use crate::common::MENU;
use crate::is_operation_cpu;
use training_mod_sync::*;
use crate::training::buff;
use crate::training::character_specific::{ptrainer, steve};
use crate::training::charge::{self, ChargeState};
@ -36,6 +35,7 @@ use crate::training::items::apply_item;
use crate::training::reset;
use crate::training::ui::notifications;
use crate::{is_ptrainer, ITEM_MANAGER_ADDR};
use training_mod_sync::*;
// Don't remove Mii hats, Pikmin, Luma, or crafting table
const ARTICLE_ALLOWLIST: [(LuaConst, LuaConst); 9] = [
@ -233,11 +233,11 @@ static mut MIRROR_STATE: f32 = 1.0;
static mut RANDOM_SLOT: usize = 0;
unsafe fn get_slot() -> usize {
let random_slot = MENU.randomize_slots.get_random();
let random_slot = get(&MENU).randomize_slots.get_random();
if random_slot != SaveStateSlot::empty() {
RANDOM_SLOT
} else {
MENU.save_state_slot.into_idx().unwrap_or(0)
get(&MENU).save_state_slot.into_idx().unwrap_or(0)
}
}
@ -256,13 +256,13 @@ pub unsafe fn is_loading() -> bool {
}
pub unsafe fn should_mirror() -> f32 {
match MENU.save_state_mirroring {
match get(&MENU).save_state_mirroring {
SaveStateMirroring::NONE => 1.0,
SaveStateMirroring::ALTERNATE => -1.0 * MIRROR_STATE,
SaveStateMirroring::RANDOM => ([-1.0, 1.0])[get_random_int(2) as usize],
_ => panic!(
"Invalid value in should_mirror: {}",
MENU.save_state_mirroring
get(&MENU).save_state_mirroring
),
}
}
@ -417,7 +417,7 @@ pub unsafe fn on_death(fighter_kind: i32, module_accessor: &mut app::BattleObjec
}
pub unsafe fn save_states(module_accessor: &mut app::BattleObjectModuleAccessor) {
if MENU.save_state_enable == OnOff::OFF {
if get(&MENU).save_state_enable == OnOff::OFF {
return;
}
@ -449,7 +449,7 @@ pub unsafe fn save_states(module_accessor: &mut app::BattleObjectModuleAccessor)
.contains(&fighter_kind);
// Reset state
let autoload_reset = MENU.save_state_autoload == OnOff::ON
let autoload_reset = get(&MENU).save_state_autoload == OnOff::ON
&& save_state.state == NoAction
&& is_dead(module_accessor);
let mut triggered_reset: bool = false;
@ -458,7 +458,7 @@ pub unsafe fn save_states(module_accessor: &mut app::BattleObjectModuleAccessor)
}
if (autoload_reset || triggered_reset) && !fighter_is_nana {
if save_state.state == NoAction {
let random_slot = MENU.randomize_slots.get_random();
let random_slot = get(&MENU).randomize_slots.get_random();
let slot = if random_slot != SaveStateSlot::empty() {
RANDOM_SLOT = random_slot.into_idx().unwrap_or(0);
RANDOM_SLOT
@ -573,48 +573,48 @@ pub unsafe fn save_states(module_accessor: &mut app::BattleObjectModuleAccessor)
if save_state.state == NoAction {
// Set damage of the save state
if !is_cpu {
match MENU.save_damage_player {
match get(&MENU).save_damage_player {
SaveDamage::SAVED => {
set_damage(module_accessor, save_state.percent);
}
SaveDamage::RANDOM => {
// Gen random value
let pct: f32 = get_random_float(
MENU.save_damage_limits_player.0 as f32,
MENU.save_damage_limits_player.1 as f32,
get(&MENU).save_damage_limits_player.0 as f32,
get(&MENU).save_damage_limits_player.1 as f32,
);
set_damage(module_accessor, pct);
}
SaveDamage::DEFAULT => {}
_ => panic!(
"Invalid value in save_states()::save_damage_player: {}",
MENU.save_damage_player
get(&MENU).save_damage_player
),
}
} else {
match MENU.save_damage_cpu {
match get(&MENU).save_damage_cpu {
SaveDamage::SAVED => {
set_damage(module_accessor, save_state.percent);
}
SaveDamage::RANDOM => {
// Gen random value
let pct: f32 = get_random_float(
MENU.save_damage_limits_cpu.0 as f32,
MENU.save_damage_limits_cpu.1 as f32,
get(&MENU).save_damage_limits_cpu.0 as f32,
get(&MENU).save_damage_limits_cpu.1 as f32,
);
set_damage(module_accessor, pct);
}
SaveDamage::DEFAULT => {}
_ => panic!(
"Invalid value in save_states()::save_damage_cpu: {}",
MENU.save_damage_cpu
get(&MENU).save_damage_cpu
),
}
}
// Set to held item
if !is_cpu && !fighter_is_nana && MENU.character_item != CharacterItem::NONE {
apply_item(MENU.character_item);
if !is_cpu && !fighter_is_nana && get(&MENU).character_item != CharacterItem::NONE {
apply_item(get(&MENU).character_item);
}
// Set the charge of special moves if the fighter matches the kind in the save state
@ -662,17 +662,20 @@ pub unsafe fn save_states(module_accessor: &mut app::BattleObjectModuleAccessor)
}
// if we're recording on state load, record
if MENU.record_trigger.contains(&RecordTrigger::SAVESTATE) {
if get(&MENU)
.record_trigger
.contains(&RecordTrigger::SAVESTATE)
{
input_record::lockout_record();
return;
}
// otherwise, begin input recording playback if selected
// for ledge, don't do this - if you want playback on a ledge, you have to set it as a ledge option,
// otherwise there too many edge cases here
else if MENU.save_state_playback.get_random() != PlaybackSlot::empty()
else if get(&MENU).save_state_playback.get_random() != PlaybackSlot::empty()
&& save_state.situation_kind != SITUATION_KIND_CLIFF
{
input_record::playback(MENU.save_state_playback.get_random().into_idx());
input_record::playback(get(&MENU).save_state_playback.get_random().into_idx());
}
return;
@ -707,12 +710,12 @@ pub unsafe fn save_states(module_accessor: &mut app::BattleObjectModuleAccessor)
if button_config::combo_passes(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.into_idx().unwrap_or(0)).state = Save;
save_state_cpu(MENU.save_state_slot.into_idx().unwrap_or(0)).state = Save;
save_state_player(get(&MENU).save_state_slot.into_idx().unwrap_or(0)).state = Save;
save_state_cpu(get(&MENU).save_state_slot.into_idx().unwrap_or(0)).state = Save;
notifications::clear_notifications_except("Save State");
notifications::notification(
"Save State".to_string(),
format!("Saved Slot {}", MENU.save_state_slot),
format!("Saved Slot {}", get(&MENU).save_state_slot),
120,
);
}

View file

@ -5,8 +5,8 @@ use smash::Vector2f;
use crate::common::consts::*;
use crate::common::*;
use training_mod_sync::*;
use crate::training::directional_influence;
use training_mod_sync::*;
static COUNTER: RwLock<u32> = RwLock::new(0);
static DIRECTION: RwLock<Direction> = RwLock::new(Direction::NEUTRAL);
@ -14,9 +14,7 @@ static DIRECTION: RwLock<Direction> = RwLock::new(Direction::NEUTRAL);
// TODO! Bug - we only roll a new direction when loading a save state or on LRA reset
pub fn roll_direction() {
assign_rwlock(&COUNTER, 0);
unsafe {
assign_rwlock(&DIRECTION, MENU.sdi_state.get_random());
}
assign_rwlock(&DIRECTION, get(&MENU).sdi_state.get_random());
}
unsafe fn get_sdi_direction() -> Option<f64> {
@ -40,7 +38,7 @@ 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();
let repeat = get(&MENU).sdi_strength.into_u32();
let mut counter_guard = lock_write_rwlock(&COUNTER);
*counter_guard = (*counter_guard + 1) % repeat;
if *counter_guard == repeat - 1 {

View file

@ -8,9 +8,10 @@ use smash::lua2cpp::L2CFighterCommon;
use crate::common::consts::*;
use crate::common::*;
use training_mod_sync::*;
use crate::training::{frame_counter, input_record, mash, save_states};
use training_mod_sync::*;
// TODO!() We only reset this on save state load or LRA reset
// How many hits to hold shield until picking an Out Of Shield option
static MULTI_HIT_OFFSET: RwLock<u32> = RwLock::new(0);
@ -43,16 +44,14 @@ fn should_pause_shield_decay() -> bool {
}
fn reset_oos_offset() {
unsafe {
/*
* Need to offset by 1, since we decrease as soon as shield gets hit
* but only check later if we can OOS
*/
assign_rwlock(
&MULTI_HIT_OFFSET,
MENU.oos_offset.get_random().into_delay() + 1,
);
}
/*
* Need to offset by 1, since we decrease as soon as shield gets hit
* but only check later if we can OOS
*/
assign_rwlock(
&MULTI_HIT_OFFSET,
get(&MENU).oos_offset.get_random().into_delay() + 1,
);
}
fn handle_oos_offset(module_accessor: &mut app::BattleObjectModuleAccessor) {
@ -70,9 +69,10 @@ fn handle_oos_offset(module_accessor: &mut app::BattleObjectModuleAccessor) {
}
// Roll shield delay
unsafe {
assign_rwlock(&SHIELD_DELAY, MENU.reaction_time.get_random().into_delay());
}
assign_rwlock(
&SHIELD_DELAY,
get(&MENU).reaction_time.get_random().into_delay(),
);
// Decrease offset once if needed
let mut multi_hit_offset_guard = lock_write_rwlock(&MULTI_HIT_OFFSET);
@ -116,7 +116,7 @@ pub unsafe fn get_param_float(
return None;
}
if MENU.shield_state != Shield::NONE {
if get(&MENU).shield_state != Shield::NONE {
handle_oos_offset(module_accessor);
}
@ -125,10 +125,7 @@ pub unsafe fn get_param_float(
// Shield Decay//Recovery
fn handle_shield_decay(param_type: u64, param_hash: u64) -> Option<f32> {
let menu_state;
unsafe {
menu_state = MENU.shield_state;
}
let menu_state = get(&MENU).shield_state;
if menu_state != Shield::INFINITE
&& menu_state != Shield::CONSTANT
@ -166,7 +163,7 @@ pub unsafe fn param_installer() {
*cached_shield_damage_mul_guard = Some(common_params.shield_damage_mul);
}
if is_training_mode() && (MENU.shield_state == Shield::INFINITE) {
if is_training_mode() && (get(&MENU).shield_state == Shield::INFINITE) {
// if you are in training mode and have infinite shield enabled,
// set the game's shield_damage_mul to 0.0
common_params.shield_damage_mul = 0.0;
@ -190,10 +187,7 @@ pub fn should_hold_shield(module_accessor: &mut app::BattleObjectModuleAccessor)
return true;
}
let shield_state;
unsafe {
shield_state = &MENU.shield_state;
}
let shield_state = &get(&MENU).shield_state;
// We should hold shield if the state requires it
if unsafe { save_states::is_loading() }
@ -228,7 +222,7 @@ unsafe fn mod_handle_sub_guard_cont(fighter: &mut L2CFighterCommon) {
}
// Enable shield decay
if MENU.shield_state == Shield::HOLD {
if get(&MENU).shield_state == Shield::HOLD {
set_shield_decay(true);
}
@ -250,11 +244,11 @@ unsafe fn mod_handle_sub_guard_cont(fighter: &mut L2CFighterCommon) {
return;
}
if MENU.mash_triggers.contains(&MashTrigger::SHIELDSTUN) {
if MENU.shieldstun_override == Action::empty() {
mash::external_buffer_menu_mash(MENU.mash_state.get_random())
if get(&MENU).mash_triggers.contains(&MashTrigger::SHIELDSTUN) {
if get(&MENU).shieldstun_override == Action::empty() {
mash::external_buffer_menu_mash(get(&MENU).mash_state.get_random())
} else {
mash::external_buffer_menu_mash(MENU.shieldstun_override.get_random())
mash::external_buffer_menu_mash(get(&MENU).shieldstun_override.get_random())
}
}
@ -360,10 +354,7 @@ fn needs_oos_handling_drop_shield() -> bool {
}
// Make sure we only flicker shield when Airdodge and Shield mash options are selected
if action == Action::AIR_DODGE {
let shield_state;
unsafe {
shield_state = &MENU.shield_state;
}
let shield_state = &get(&MENU).shield_state;
// If we're supposed to be holding shield, let airdodge make us drop shield
if [Shield::HOLD, Shield::INFINITE, Shield::CONSTANT].contains(shield_state) {
suspend_shield(Action::AIR_DODGE);
@ -373,10 +364,7 @@ fn needs_oos_handling_drop_shield() -> bool {
// Make sure we only flicker shield when Airdodge and Shield mash options are selected
if action == Action::AIR_DODGE {
let shield_state;
unsafe {
shield_state = &MENU.shield_state;
}
let shield_state = &get(&MENU).shield_state;
// If we're supposed to be holding shield, let airdodge make us drop shield
if [Shield::HOLD, Shield::INFINITE, Shield::CONSTANT].contains(shield_state) {
suspend_shield(Action::AIR_DODGE);
@ -385,10 +373,7 @@ fn needs_oos_handling_drop_shield() -> bool {
}
if action == Action::SHIELD {
let shield_state;
unsafe {
shield_state = &MENU.shield_state;
}
let shield_state = &get(&MENU).shield_state;
// Don't drop shield on shield hit if we're supposed to be holding shield
if [Shield::HOLD, Shield::INFINITE, Shield::CONSTANT].contains(shield_state) {
return false;

View file

@ -7,24 +7,18 @@ use training_mod_sync::*;
static SHIELD_STICK_DIRECTION: RwLock<Direction> = RwLock::new(Direction::OUT);
pub fn roll_direction() {
unsafe {
assign_rwlock(&SHIELD_STICK_DIRECTION, MENU.shield_tilt.get_random());
}
assign_rwlock(&SHIELD_STICK_DIRECTION, get(&MENU).shield_tilt.get_random());
}
pub unsafe fn mod_get_stick_x(
module_accessor: &mut app::BattleObjectModuleAccessor,
) -> Option<f32> {
pub fn mod_get_stick_x(module_accessor: &mut app::BattleObjectModuleAccessor) -> Option<f32> {
get_angle(module_accessor).map(|a| a.cos() as f32)
}
pub unsafe fn mod_get_stick_y(
module_accessor: &mut app::BattleObjectModuleAccessor,
) -> Option<f32> {
pub fn mod_get_stick_y(module_accessor: &mut app::BattleObjectModuleAccessor) -> Option<f32> {
get_angle(module_accessor).map(|a| a.sin() as f32)
}
unsafe fn get_angle(module_accessor: &mut app::BattleObjectModuleAccessor) -> Option<f64> {
fn get_angle(module_accessor: &mut app::BattleObjectModuleAccessor) -> Option<f64> {
if !is_operation_cpu(module_accessor) {
return None;
}

View file

@ -13,8 +13,8 @@ use crate::common::offsets::{
OFFSET_CHANGE_ACTIVE_CAMERA, OFFSET_SET_TRAINING_FIXED_CAMERA_VALUES,
};
use crate::common::*;
use training_mod_sync::*;
use crate::training::{frame_counter, mash, save_states};
use training_mod_sync::*;
static TECH_ROLL_DIRECTION: RwLock<Direction> = RwLock::new(Direction::empty());
static MISS_TECH_ROLL_DIRECTION: RwLock<Direction> = RwLock::new(Direction::empty());
@ -63,7 +63,7 @@ unsafe fn mod_handle_change_status(
.try_get_int()
.unwrap_or(*FIGHTER_STATUS_KIND_WAIT as u64) as i32;
let state: TechFlags = MENU.tech_state.get_random();
let state: TechFlags = get(&MENU).tech_state.get_random();
if handle_grnd_tech(module_accessor, status_kind, unk, status_kind_int, state) {
return;
@ -125,11 +125,11 @@ unsafe fn handle_grnd_tech(
}
_ => false,
};
if do_tech && MENU.mash_triggers.contains(&MashTrigger::TECH) {
if MENU.tech_action_override == Action::empty() {
mash::external_buffer_menu_mash(MENU.mash_state.get_random())
if do_tech && get(&MENU).mash_triggers.contains(&MashTrigger::TECH) {
if get(&MENU).tech_action_override == Action::empty() {
mash::external_buffer_menu_mash(get(&MENU).mash_state.get_random())
} else {
mash::external_buffer_menu_mash(MENU.tech_action_override.get_random())
mash::external_buffer_menu_mash(get(&MENU).tech_action_override.get_random())
}
}
@ -172,11 +172,11 @@ unsafe fn handle_wall_tech(
}
_ => false,
};
if do_tech && MENU.mash_triggers.contains(&MashTrigger::TECH) {
if MENU.tech_action_override == Action::empty() {
mash::external_buffer_menu_mash(MENU.mash_state.get_random())
if do_tech && get(&MENU).mash_triggers.contains(&MashTrigger::TECH) {
if get(&MENU).tech_action_override == Action::empty() {
mash::external_buffer_menu_mash(get(&MENU).mash_state.get_random())
} else {
mash::external_buffer_menu_mash(MENU.tech_action_override.get_random())
mash::external_buffer_menu_mash(get(&MENU).tech_action_override.get_random())
}
}
true
@ -207,18 +207,18 @@ unsafe fn handle_ceil_tech(
*status_kind = FIGHTER_STATUS_KIND_PASSIVE_CEIL.as_lua_int();
*unk = LUA_TRUE;
if MENU.mash_triggers.contains(&MashTrigger::TECH) {
if MENU.tech_action_override == Action::empty() {
mash::external_buffer_menu_mash(MENU.mash_state.get_random())
if get(&MENU).mash_triggers.contains(&MashTrigger::TECH) {
if get(&MENU).tech_action_override == Action::empty() {
mash::external_buffer_menu_mash(get(&MENU).mash_state.get_random())
} else {
mash::external_buffer_menu_mash(MENU.tech_action_override.get_random())
mash::external_buffer_menu_mash(get(&MENU).tech_action_override.get_random())
}
}
true
}
pub unsafe fn get_command_flag_cat(module_accessor: &mut BattleObjectModuleAccessor) {
if !is_operation_cpu(module_accessor) || MENU.tech_state == TechFlags::empty() {
if !is_operation_cpu(module_accessor) || get(&MENU).tech_state == TechFlags::empty() {
return;
}
@ -231,7 +231,7 @@ pub unsafe fn get_command_flag_cat(module_accessor: &mut BattleObjectModuleAcces
.contains(&status)
{
// Mistech
requested_status = match MENU.miss_tech_state.get_random() {
requested_status = match get(&MENU).miss_tech_state.get_random() {
MissTechFlags::GETUP => *FIGHTER_STATUS_KIND_DOWN_STAND,
MissTechFlags::ATTACK => *FIGHTER_STATUS_KIND_DOWN_STAND_ATTACK,
MissTechFlags::ROLL_F => {
@ -250,7 +250,7 @@ pub unsafe fn get_command_flag_cat(module_accessor: &mut BattleObjectModuleAcces
if frame_counter::should_delay(lockout_time, *FRAME_COUNTER) {
return;
};
requested_status = match MENU.miss_tech_state.get_random() {
requested_status = match get(&MENU).miss_tech_state.get_random() {
MissTechFlags::GETUP => *FIGHTER_STATUS_KIND_DOWN_STAND,
MissTechFlags::ATTACK => *FIGHTER_STATUS_KIND_DOWN_STAND_ATTACK,
MissTechFlags::ROLL_F => {
@ -265,7 +265,7 @@ pub unsafe fn get_command_flag_cat(module_accessor: &mut BattleObjectModuleAcces
};
} else if status == *FIGHTER_STATUS_KIND_SLIP_WAIT {
// Handle slips (like Diddy banana)
requested_status = match MENU.miss_tech_state.get_random() {
requested_status = match get(&MENU).miss_tech_state.get_random() {
MissTechFlags::GETUP => *FIGHTER_STATUS_KIND_SLIP_STAND,
MissTechFlags::ATTACK => *FIGHTER_STATUS_KIND_SLIP_STAND_ATTACK,
MissTechFlags::ROLL_F => *FIGHTER_STATUS_KIND_SLIP_STAND_F,
@ -279,11 +279,11 @@ pub unsafe fn get_command_flag_cat(module_accessor: &mut BattleObjectModuleAcces
if requested_status != 0 {
StatusModule::change_status_force(module_accessor, requested_status, true);
if MENU.mash_triggers.contains(&MashTrigger::MISTECH) {
if MENU.tech_action_override == Action::empty() {
mash::external_buffer_menu_mash(MENU.mash_state.get_random())
if get(&MENU).mash_triggers.contains(&MashTrigger::MISTECH) {
if get(&MENU).tech_action_override == Action::empty() {
mash::external_buffer_menu_mash(get(&MENU).mash_state.get_random())
} else {
mash::external_buffer_menu_mash(MENU.tech_action_override.get_random())
mash::external_buffer_menu_mash(get(&MENU).tech_action_override.get_random())
}
}
}
@ -297,7 +297,7 @@ pub unsafe fn change_motion(
return None;
}
if MENU.tech_state == TechFlags::empty() {
if get(&MENU).tech_state == TechFlags::empty() {
return None;
}
@ -349,7 +349,7 @@ unsafe fn get_snake_laydown_lockout_time(module_accessor: &mut BattleObjectModul
}
pub unsafe fn hide_tech() {
if !is_training_mode() || MENU.tech_hide == OnOff::OFF {
if !is_training_mode() || get(&MENU).tech_hide == OnOff::OFF {
return;
}
let module_accessor = get_module_accessor(FighterId::CPU);
@ -407,7 +407,7 @@ pub unsafe fn handle_fighter_req_quake_pos(
return original!()(module_accessor, quake_kind);
}
let status = StatusModule::status_kind(module_accessor);
if status == FIGHTER_STATUS_KIND_DOWN && MENU.tech_hide == OnOff::ON {
if status == FIGHTER_STATUS_KIND_DOWN && get(&MENU).tech_hide == OnOff::ON {
// We're hiding techs, prevent mistech quake from giving away missed tech
return original!()(module_accessor, *CAMERA_QUAKE_KIND_NONE);
}
@ -450,7 +450,7 @@ pub struct CameraManager {
unsafe fn set_fixed_camera_values() {
let camera_manager = get_camera_manager();
if MENU.tech_hide == OnOff::OFF {
if get(&MENU).tech_hide == OnOff::OFF {
// Use Stage's Default Values for fixed Camera
camera_manager.fixed_camera_center = read_rwlock(&DEFAULT_FIXED_CAM_CENTER);
} else {

View file

@ -3,10 +3,9 @@ use smash::lib::lua_const::*;
use crate::common::consts::*;
use crate::common::*;
use training_mod_sync::*;
use crate::training::frame_counter;
use crate::training::mash;
use training_mod_sync::*;
const NOT_SET: u32 = 9001;
static THROW_DELAY: RwLock<u32> = RwLock::new(NOT_SET);
@ -44,27 +43,27 @@ pub fn reset_throw_case() {
fn roll_throw_delay() {
if read_rwlock(&THROW_DELAY) == NOT_SET {
// Only roll another throw delay if one is not already selected
unsafe {
assign_rwlock(&THROW_DELAY, MENU.throw_delay.get_random().into_meddelay());
}
assign_rwlock(
&THROW_DELAY,
get(&MENU).throw_delay.get_random().into_meddelay(),
);
}
}
fn roll_pummel_delay() {
if read_rwlock(&PUMMEL_DELAY) == NOT_SET {
// Don't roll another pummel delay if one is already selected
unsafe {
assign_rwlock(&PUMMEL_DELAY, MENU.pummel_delay.get_random().into_meddelay());
}
assign_rwlock(
&PUMMEL_DELAY,
get(&MENU).pummel_delay.get_random().into_meddelay(),
);
}
}
fn roll_throw_case() {
if read_rwlock(&THROW_CASE) == ThrowOption::empty() {
// Only re-roll if there is not already a throw option selected
unsafe {
assign_rwlock(&THROW_CASE, MENU.throw_state.get_random());
}
assign_rwlock(&THROW_CASE, get(&MENU).throw_state.get_random());
}
}
@ -113,7 +112,7 @@ pub unsafe fn get_command_flag_throw_direction(
}
// If no pummel delay is selected (default), then don't pummel
if MENU.pummel_delay == MedDelay::empty() {
if get(&MENU).pummel_delay == MedDelay::empty() {
return 0;
}
@ -132,7 +131,7 @@ pub unsafe fn get_command_flag_throw_direction(
*FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_THROW_HI,
) {
let cmd = read_rwlock(&THROW_CASE).into_cmd().unwrap_or(0);
mash::external_buffer_menu_mash(MENU.mash_state.get_random());
mash::external_buffer_menu_mash(get(&MENU).mash_state.get_random());
return cmd;
}

View file

@ -6,12 +6,12 @@ use training_mod_consts::{InputDisplay, MENU};
use crate::common::consts::status_display_name;
use crate::menu::QUICK_MENU_ACTIVE;
use training_mod_sync::*;
use crate::training::input_log::{
DirectionStrength, InputLog, DRAW_LOG_BASE_IDX, NUM_LOGS, P1_INPUT_LOGS, WHITE, YELLOW,
};
use crate::training::ui::fade_out;
use crate::training::ui::menu::VANILLA_MENU_ACTIVE;
use training_mod_sync::*;
macro_rules! log_parent_fmt {
($x:ident) => {
@ -176,7 +176,7 @@ unsafe fn draw_log(root_pane: &Pane, log_idx: usize, log: &InputLog) {
.as_textbox()
.set_text_string(frame_text.as_str());
let status_text = if MENU.input_display_status.as_bool() {
let status_text = if get(&MENU).input_display_status.as_bool() {
status_display_name(log.fighter_kind, log.status)
} else {
"".to_string()
@ -195,9 +195,9 @@ pub unsafe fn draw(root_pane: &Pane) {
logs_pane.set_visible(
!read_rwlock(&QUICK_MENU_ACTIVE)
&& !read_rwlock(&VANILLA_MENU_ACTIVE)
&& MENU.input_display != InputDisplay::NONE,
&& get(&MENU).input_display != InputDisplay::NONE,
);
if MENU.input_display == InputDisplay::NONE {
if get(&MENU).input_display == InputDisplay::NONE {
return;
}

View file

@ -10,8 +10,8 @@ use crate::common::offsets::{OFFSET_DRAW, OFFSET_LAYOUT_ARC_MALLOC};
use crate::common::{is_ready_go, is_training_mode};
#[cfg(feature = "layout_arc_from_file")]
use crate::consts::LAYOUT_ARC_PATH;
use training_mod_sync::*;
use crate::training::frame_counter;
use training_mod_sync::*;
mod damage;
mod display;
@ -72,7 +72,7 @@ pub unsafe fn handle_draw(layout: *mut Layout, draw_info: u64, cmd_buffer: u64)
{
// InfluencedAlpha means "Should my children panes' alpha be influenced by mine, as the parent?"
root_pane.flags |= 1 << PaneFlag::InfluencedAlpha as u8;
root_pane.set_visible(MENU.hud == OnOff::ON && !read_rwlock(&QUICK_MENU_ACTIVE));
root_pane.set_visible(get(&MENU).hud == OnOff::ON && !read_rwlock(&QUICK_MENU_ACTIVE));
}
damage::draw(root_pane, &layout_name);

View file

@ -17,7 +17,8 @@ skyline_smash = { git = "https://github.com/ultimate-research/skyline-smash.git"
toml = "0.5.9"
anyhow = "1.0.72"
rand = { git = "https://github.com/skyline-rs/rand" }
training_mod_tui = { path = "../training_mod_tui"}
training_mod_sync = { path = "../training_mod_sync" }
training_mod_tui = { path = "../training_mod_tui" }
[features]
default = ["smash"]

View file

@ -12,6 +12,8 @@ pub mod config;
pub use config::*;
use paste::paste;
use training_mod_sync::*;
pub use training_mod_tui::*;
pub const TOGGLE_MAX: u8 = 5;
@ -204,7 +206,7 @@ pub static DEFAULTS_MENU: TrainingModpackMenu = TrainingModpackMenu {
lra_reset: OnOff::ON,
};
pub static mut MENU: TrainingModpackMenu = DEFAULTS_MENU;
pub static MENU: RwLock<TrainingModpackMenu> = RwLock::new(DEFAULTS_MENU);
impl_toggletrait! {
OnOff,

View file

@ -33,4 +33,9 @@ pub fn lock_write_rwlock<T>(rwlock: &RwLock<T>) -> RwLockWriteGuard<T> {
/// Don't forget to drop the guard as soon as you're finished with it
pub fn lock_read_rwlock<T>(rwlock: &RwLock<T>) -> RwLockReadGuard<T> {
rwlock.read().unwrap()
}
}
/// Shorthand for read_rwlock
pub fn get<T: Copy>(rwlock: &RwLock<T>) -> T {
read_rwlock(rwlock)
}