mirror of
https://github.com/jugeeya/UltimateTrainingModpack.git
synced 2024-11-24 02:44:17 +00:00
[Build] Fix formatting (#557)
* [Build] Fix formatting * Another set of fixes
This commit is contained in:
parent
1486ad8d05
commit
9ef506aac7
11 changed files with 204 additions and 134 deletions
|
@ -41,12 +41,10 @@ pub struct Uuid {
|
|||
impl Uuid {
|
||||
pub fn to_str(&self) -> String {
|
||||
use std::fmt::Write;
|
||||
self.data
|
||||
.iter()
|
||||
.fold(String::new(), |mut output, b| {
|
||||
let _ = write!(output, "{b:02x}");
|
||||
output
|
||||
})
|
||||
self.data.iter().fold(String::new(), |mut output, b| {
|
||||
let _ = write!(output, "{b:02x}");
|
||||
output
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::training::input_record;
|
||||
use smash::app::{self, lua_bind::*};
|
||||
use smash::lib::lua_const::*;
|
||||
use crate::training::input_record;
|
||||
|
||||
use crate::common::*;
|
||||
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
use smash::app::{BattleObjectModuleAccessor, lua_bind::*, utility};
|
||||
use smash::lib::lua_const::*;
|
||||
use crate::common::consts::{FighterId, HitstunPlayback, RecordTrigger};
|
||||
use crate::common::{get_module_accessor, is_in_hitstun, is_in_shieldstun, MENU};
|
||||
use crate::training::input_recording::structures::*;
|
||||
use crate::training::mash;
|
||||
use lazy_static::lazy_static;
|
||||
use parking_lot::Mutex;
|
||||
use smash::app::{lua_bind::*, utility, BattleObjectModuleAccessor};
|
||||
use smash::lib::lua_const::*;
|
||||
use std::cmp::Ordering;
|
||||
use crate::training::input_recording::structures::*;
|
||||
use crate::common::consts::{RecordTrigger, HitstunPlayback, FighterId};
|
||||
use crate::common::{MENU, get_module_accessor, is_in_hitstun, is_in_shieldstun};
|
||||
use crate::training::mash;
|
||||
|
||||
#[derive(PartialEq)]
|
||||
#[derive(Debug)]
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub enum InputRecordState {
|
||||
None,
|
||||
Pause,
|
||||
|
@ -17,8 +16,7 @@ pub enum InputRecordState {
|
|||
Playback,
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
#[derive(Debug)]
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub enum PossessionState {
|
||||
Player,
|
||||
Cpu,
|
||||
|
@ -26,20 +24,19 @@ pub enum PossessionState {
|
|||
Standby,
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(PartialEq, Copy, Clone)]
|
||||
pub enum StartingStatus {
|
||||
Aerial, // FIGHTER_STATUS_KIND_ATTACK_AIR TODO: This shouldn't happen without starting input recording in the air - when would we want this?
|
||||
// Probably should lock input recordings to either the ground or the air
|
||||
Airdodge, // FIGHTER_STATUS_KIND_ESCAPE_AIR, FIGHTER_STATUS_KIND_ESCAPE_AIR_SLIDE
|
||||
// Other statuses cannot be used to hitstun cancel via damage_fly_attack_frame/damage_fly_escape_frame
|
||||
// Some statuses can leave shield earlier though, so we should check for this
|
||||
SpecialHi, // Up B: FIGHTER_STATUS_KIND_SPECIAL_HI,
|
||||
Jump, // FIGHTER_STATUS_KIND_JUMP_SQUAT
|
||||
SpecialHi, // Up B: FIGHTER_STATUS_KIND_SPECIAL_HI,
|
||||
Jump, // FIGHTER_STATUS_KIND_JUMP_SQUAT
|
||||
DoubleJump, //FIGHTER_STATUS_KIND_JUMP_AERIAL
|
||||
Spotdodge, // FIGHTER_STATUS_KIND_ESCAPE
|
||||
Roll, // FIGHTER_STATUS_KIND_ESCAPE_F, FIGHTER_STATUS_KIND_ESCAPE_B
|
||||
Grab, // FIGHTER_STATUS_KIND_CATCH
|
||||
Spotdodge, // FIGHTER_STATUS_KIND_ESCAPE
|
||||
Roll, // FIGHTER_STATUS_KIND_ESCAPE_F, FIGHTER_STATUS_KIND_ESCAPE_B
|
||||
Grab, // FIGHTER_STATUS_KIND_CATCH
|
||||
Other,
|
||||
}
|
||||
|
||||
|
@ -65,11 +62,9 @@ pub static mut CURRENT_PLAYBACK_SLOT: usize = 0; // Which slot is being used for
|
|||
|
||||
lazy_static! {
|
||||
static ref P1_FINAL_MAPPING: Mutex<[[MappedInputs; FINAL_RECORD_MAX]; TOTAL_SLOT_COUNT]> =
|
||||
Mutex::new([[{
|
||||
MappedInputs::default()
|
||||
}; FINAL_RECORD_MAX]; TOTAL_SLOT_COUNT]);
|
||||
Mutex::new([[{ MappedInputs::default() }; FINAL_RECORD_MAX]; TOTAL_SLOT_COUNT]);
|
||||
static ref P1_STARTING_STATUSES: Mutex<[StartingStatus; TOTAL_SLOT_COUNT]> =
|
||||
Mutex::new([{StartingStatus::Other}; TOTAL_SLOT_COUNT]);
|
||||
Mutex::new([{ StartingStatus::Other }; TOTAL_SLOT_COUNT]);
|
||||
}
|
||||
|
||||
unsafe fn can_transition(module_accessor: *mut BattleObjectModuleAccessor) -> bool {
|
||||
|
@ -93,7 +88,7 @@ unsafe fn should_mash_playback() {
|
|||
let mut should_playback = false;
|
||||
let cpu_module_accessor = get_module_accessor(FighterId::CPU);
|
||||
// depending on our current status, we want to wait for different timings to begin playback
|
||||
|
||||
|
||||
// TODO: This isn't the best way to write this I'm sure, want to rewrite
|
||||
|
||||
if is_in_hitstun(&mut *cpu_module_accessor) {
|
||||
|
@ -102,11 +97,14 @@ unsafe fn should_mash_playback() {
|
|||
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 && !StopModule::is_stop(cpu_module_accessor) {
|
||||
if 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 MENU.hitstun_playback == HitstunPlayback::Hitstun && can_transition(cpu_module_accessor)
|
||||
{
|
||||
should_playback = true;
|
||||
}
|
||||
} else if is_in_shieldstun(&mut *cpu_module_accessor) {
|
||||
|
@ -118,7 +116,6 @@ unsafe fn should_mash_playback() {
|
|||
should_playback = true;
|
||||
}
|
||||
|
||||
|
||||
// how do we deal with buffering motion inputs out of shield? You can't complete them in one frame, but they can definitely be buffered during shield drop
|
||||
// probably need a separate standby setting for grounded, aerial, shield, where shield starts once you let go of shield, and aerial keeps you in the air?
|
||||
|
||||
|
@ -132,7 +129,9 @@ unsafe fn should_mash_playback() {
|
|||
fn into_starting_status(status: i32) -> StartingStatus {
|
||||
if status == *FIGHTER_STATUS_KIND_ATTACK_AIR {
|
||||
return StartingStatus::Aerial;
|
||||
} else if (*FIGHTER_STATUS_KIND_ESCAPE_AIR..*FIGHTER_STATUS_KIND_ESCAPE_AIR_SLIDE).contains(&status) {
|
||||
} else if (*FIGHTER_STATUS_KIND_ESCAPE_AIR..*FIGHTER_STATUS_KIND_ESCAPE_AIR_SLIDE)
|
||||
.contains(&status)
|
||||
{
|
||||
return StartingStatus::Airdodge;
|
||||
} else if status == *FIGHTER_STATUS_KIND_SPECIAL_HI {
|
||||
return StartingStatus::SpecialHi;
|
||||
|
@ -146,7 +145,7 @@ fn into_starting_status(status: i32) -> StartingStatus {
|
|||
return StartingStatus::Roll;
|
||||
} else if status == *FIGHTER_STATUS_KIND_CATCH {
|
||||
return StartingStatus::Grab;
|
||||
}
|
||||
}
|
||||
StartingStatus::Other
|
||||
}
|
||||
|
||||
|
@ -169,7 +168,7 @@ pub unsafe fn get_command_flag_cat(module_accessor: &mut BattleObjectModuleAcces
|
|||
// an erroneous definition
|
||||
#[allow(clippy::unnecessary_cast)]
|
||||
let entry_id_int =
|
||||
WorkModule::get_int(module_accessor, *FIGHTER_INSTANCE_WORK_ID_INT_ENTRY_ID) as i32;
|
||||
WorkModule::get_int(module_accessor, *FIGHTER_INSTANCE_WORK_ID_INT_ENTRY_ID) as i32;
|
||||
let fighter_kind = utility::get_kind(module_accessor);
|
||||
let fighter_is_nana = fighter_kind == *FIGHTER_KIND_NANA;
|
||||
|
||||
|
@ -178,7 +177,8 @@ pub unsafe fn get_command_flag_cat(module_accessor: &mut BattleObjectModuleAcces
|
|||
if entry_id_int == 0 && !fighter_is_nana {
|
||||
// Attack + Dpad Right: Playback
|
||||
if ControlModule::check_button_on(module_accessor, *CONTROL_PAD_BUTTON_ATTACK)
|
||||
&& ControlModule::check_button_trigger(module_accessor, *CONTROL_PAD_BUTTON_APPEAL_S_R) {
|
||||
&& ControlModule::check_button_trigger(module_accessor, *CONTROL_PAD_BUTTON_APPEAL_S_R)
|
||||
{
|
||||
//crate::common::raygun_printer::print_string(&mut *module_accessor, "PLAYBACK");
|
||||
playback();
|
||||
println!("Playback Command Received!"); //debug
|
||||
|
@ -188,14 +188,15 @@ pub unsafe fn get_command_flag_cat(module_accessor: &mut BattleObjectModuleAcces
|
|||
&& ControlModule::check_button_trigger(module_accessor, *CONTROL_PAD_BUTTON_APPEAL_S_L)
|
||||
&& MENU.record_trigger == RecordTrigger::Command
|
||||
{
|
||||
//crate::common::raygun_printer::print_string(&mut *module_accessor, "RECORDING");
|
||||
lockout_record();
|
||||
println!("Record Command Received!"); //debug
|
||||
//crate::common::raygun_printer::print_string(&mut *module_accessor, "RECORDING");
|
||||
lockout_record();
|
||||
println!("Record Command Received!"); //debug
|
||||
}
|
||||
|
||||
|
||||
// may need to move this to another func
|
||||
if (INPUT_RECORD == Record || INPUT_RECORD == Playback) && INPUT_RECORD_FRAME >= FINAL_RECORD_FRAME - 1 {
|
||||
if (INPUT_RECORD == Record || INPUT_RECORD == Playback)
|
||||
&& INPUT_RECORD_FRAME >= FINAL_RECORD_FRAME - 1
|
||||
{
|
||||
INPUT_RECORD = None;
|
||||
POSSESSION = Player;
|
||||
INPUT_RECORD_FRAME = 0;
|
||||
|
@ -208,11 +209,29 @@ pub unsafe fn get_command_flag_cat(module_accessor: &mut BattleObjectModuleAcces
|
|||
// Handle Possession Coloring
|
||||
//let model_color_type = *MODEL_COLOR_TYPE_COLOR_BLEND;
|
||||
if entry_id_int == 1 && POSSESSION == Lockout {
|
||||
set_color_rgb_2(module_accessor,0.0,0.0,1.0,*MODEL_COLOR_TYPE_COLOR_BLEND);
|
||||
set_color_rgb_2(
|
||||
module_accessor,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0,
|
||||
*MODEL_COLOR_TYPE_COLOR_BLEND,
|
||||
);
|
||||
} else if entry_id_int == 1 && POSSESSION == Standby {
|
||||
set_color_rgb_2(module_accessor,1.0,0.0,1.0,*MODEL_COLOR_TYPE_COLOR_BLEND);
|
||||
set_color_rgb_2(
|
||||
module_accessor,
|
||||
1.0,
|
||||
0.0,
|
||||
1.0,
|
||||
*MODEL_COLOR_TYPE_COLOR_BLEND,
|
||||
);
|
||||
} else if entry_id_int == 1 && POSSESSION == Cpu {
|
||||
set_color_rgb_2(module_accessor,1.0,0.0,0.0,*MODEL_COLOR_TYPE_COLOR_BLEND);
|
||||
set_color_rgb_2(
|
||||
module_accessor,
|
||||
1.0,
|
||||
0.0,
|
||||
0.0,
|
||||
*MODEL_COLOR_TYPE_COLOR_BLEND,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -220,9 +239,11 @@ pub unsafe fn lockout_record() {
|
|||
INPUT_RECORD = Pause;
|
||||
INPUT_RECORD_FRAME = 0;
|
||||
POSSESSION = Lockout;
|
||||
P1_FINAL_MAPPING.lock()[CURRENT_RECORD_SLOT].iter_mut().for_each(|mapped_input| {
|
||||
*mapped_input = MappedInputs::default();
|
||||
});
|
||||
P1_FINAL_MAPPING.lock()[CURRENT_RECORD_SLOT]
|
||||
.iter_mut()
|
||||
.for_each(|mapped_input| {
|
||||
*mapped_input = MappedInputs::default();
|
||||
});
|
||||
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;
|
||||
// Store the direction the CPU is facing when we initially record, so we can turn their inputs around if needed
|
||||
|
@ -235,9 +256,11 @@ pub unsafe fn _record() {
|
|||
INPUT_RECORD = Record;
|
||||
POSSESSION = Cpu;
|
||||
// Reset mappings to nothing, and then start recording. Likely want to reset in case we cut off recording early.
|
||||
P1_FINAL_MAPPING.lock()[CURRENT_RECORD_SLOT].iter_mut().for_each(|mapped_input| {
|
||||
*mapped_input = MappedInputs::default();
|
||||
});
|
||||
P1_FINAL_MAPPING.lock()[CURRENT_RECORD_SLOT]
|
||||
.iter_mut()
|
||||
.for_each(|mapped_input| {
|
||||
*mapped_input = MappedInputs::default();
|
||||
});
|
||||
INPUT_RECORD_FRAME = 0;
|
||||
LOCKOUT_FRAME = 0;
|
||||
BUFFER_FRAME = 0;
|
||||
|
@ -266,8 +289,8 @@ pub unsafe fn playback_ledge() {
|
|||
POSSESSION = Player;
|
||||
INPUT_RECORD_FRAME = 0;
|
||||
BUFFER_FRAME = 5; // So we can make sure the option is buffered and won't get ledge trumped if delay is 0
|
||||
// drop down from ledge can't be buffered on the same frame as jump/attack/roll/ngu so we have to do this
|
||||
// Need to buffer 1 less frame for non-lassos
|
||||
// drop down from ledge can't be buffered on the same frame as jump/attack/roll/ngu so we have to do this
|
||||
// Need to buffer 1 less frame for non-lassos
|
||||
let cpu_module_accessor = get_module_accessor(FighterId::CPU);
|
||||
let status_kind = StatusModule::status_kind(cpu_module_accessor) as i32;
|
||||
if status_kind == *FIGHTER_STATUS_KIND_CLIFF_CATCH {
|
||||
|
@ -285,18 +308,24 @@ pub unsafe fn is_end_standby() -> bool {
|
|||
// Returns whether we should be done with standby this frame (if any significant controller input has been made)
|
||||
let first_frame_input = P1_FINAL_MAPPING.lock()[CURRENT_RECORD_SLOT][0];
|
||||
|
||||
let clamped_lstick_x = ((first_frame_input.lstick_x as f32) * STICK_CLAMP_MULTIPLIER).clamp(-1.0, 1.0);
|
||||
let clamped_lstick_y = ((first_frame_input.lstick_y as f32) * STICK_CLAMP_MULTIPLIER).clamp(-1.0, 1.0);
|
||||
let clamped_rstick_x = ((first_frame_input.rstick_x as f32) * STICK_CLAMP_MULTIPLIER).clamp(-1.0, 1.0);
|
||||
let clamped_rstick_y = ((first_frame_input.rstick_y as f32) * STICK_CLAMP_MULTIPLIER).clamp(-1.0, 1.0);
|
||||
let clamped_lstick_x =
|
||||
((first_frame_input.lstick_x as f32) * STICK_CLAMP_MULTIPLIER).clamp(-1.0, 1.0);
|
||||
let clamped_lstick_y =
|
||||
((first_frame_input.lstick_y as f32) * STICK_CLAMP_MULTIPLIER).clamp(-1.0, 1.0);
|
||||
let clamped_rstick_x =
|
||||
((first_frame_input.rstick_x as f32) * STICK_CLAMP_MULTIPLIER).clamp(-1.0, 1.0);
|
||||
let clamped_rstick_y =
|
||||
((first_frame_input.rstick_y as f32) * STICK_CLAMP_MULTIPLIER).clamp(-1.0, 1.0);
|
||||
|
||||
let buttons_pressed = !first_frame_input.buttons.is_empty();
|
||||
let lstick_movement = clamped_lstick_x.abs() >= STICK_NEUTRAL || clamped_lstick_y.abs() >= STICK_NEUTRAL;
|
||||
let rstick_movement = clamped_rstick_x.abs() >= STICK_NEUTRAL || clamped_rstick_y.abs() >= STICK_NEUTRAL;
|
||||
let lstick_movement =
|
||||
clamped_lstick_x.abs() >= STICK_NEUTRAL || clamped_lstick_y.abs() >= STICK_NEUTRAL;
|
||||
let rstick_movement =
|
||||
clamped_rstick_x.abs() >= STICK_NEUTRAL || clamped_rstick_y.abs() >= STICK_NEUTRAL;
|
||||
lstick_movement || rstick_movement || buttons_pressed
|
||||
}
|
||||
|
||||
static FIM_OFFSET: usize = 0x17504a0;
|
||||
static FIM_OFFSET: usize = 0x17504a0;
|
||||
// TODO: Should we define all of our offsets in one file? Should at least be a good start for changing to be based on ASM instructions
|
||||
#[skyline::hook(offset = FIM_OFFSET)]
|
||||
unsafe fn handle_final_input_mapping(
|
||||
|
@ -304,11 +333,12 @@ unsafe fn handle_final_input_mapping(
|
|||
player_idx: i32, // Is this the player index, or plugged in controller index? Need to check, assuming player for now - is this 0 indexed or 1?
|
||||
out: *mut MappedInputs,
|
||||
controller_struct: &mut SomeControllerStruct,
|
||||
arg: bool
|
||||
arg: bool,
|
||||
) {
|
||||
// go through the original mapping function first
|
||||
original!()(mappings, player_idx, out, controller_struct, arg);
|
||||
if player_idx == 0 { // if player 1
|
||||
if player_idx == 0 {
|
||||
// if player 1
|
||||
if INPUT_RECORD == Record {
|
||||
// check for standby before starting action:
|
||||
if POSSESSION == Standby && is_end_standby() {
|
||||
|
@ -321,22 +351,24 @@ unsafe fn handle_final_input_mapping(
|
|||
// We're on the second frame of recording, grabbing the status should give us the status that resulted from the first frame of input
|
||||
// We'll want to save this status so that we use the correct TRANSITION TERM for hitstun cancelling out of damage fly
|
||||
let cpu_module_accessor = get_module_accessor(FighterId::CPU);
|
||||
P1_STARTING_STATUSES.lock()[CURRENT_PLAYBACK_SLOT] = into_starting_status(StatusModule::status_kind(cpu_module_accessor));
|
||||
STARTING_STATUS = StatusModule::status_kind(cpu_module_accessor); // TODO: Handle this based on slot later instead
|
||||
P1_STARTING_STATUSES.lock()[CURRENT_PLAYBACK_SLOT] =
|
||||
into_starting_status(StatusModule::status_kind(cpu_module_accessor));
|
||||
STARTING_STATUS = StatusModule::status_kind(cpu_module_accessor);
|
||||
// TODO: Handle this based on slot later instead
|
||||
}
|
||||
|
||||
P1_FINAL_MAPPING.lock()[CURRENT_RECORD_SLOT][INPUT_RECORD_FRAME] = *out;
|
||||
*out = MappedInputs::default(); // don't control player while recording
|
||||
println!("Stored Player Input! Frame: {}",INPUT_RECORD_FRAME);
|
||||
println!("Stored Player Input! Frame: {}", INPUT_RECORD_FRAME);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[skyline::hook(offset = 0x2da180)] // After cpu controls are assigned from ai calls
|
||||
unsafe fn set_cpu_controls(p_data: *mut *mut u8) {
|
||||
call_original!(p_data);
|
||||
let controller_data = *p_data.add(1) as *mut ControlModuleInternal;
|
||||
let controller_no = (*controller_data).controller_index;
|
||||
let controller_no = (*controller_data).controller_index;
|
||||
|
||||
// Check if we need to begin playback this frame due to a mash toggle
|
||||
// TODO: Setup STARTING_STATUS based on current playback slot here
|
||||
|
@ -352,38 +384,49 @@ unsafe fn set_cpu_controls(p_data: *mut *mut u8) {
|
|||
Ordering::Equal => {
|
||||
INPUT_RECORD = Record;
|
||||
POSSESSION = Standby;
|
||||
},
|
||||
Ordering::Less => println!("LOCKOUT_FRAME OUT OF BOUNDS")
|
||||
}
|
||||
Ordering::Less => println!("LOCKOUT_FRAME OUT OF BOUNDS"),
|
||||
}
|
||||
}
|
||||
|
||||
if INPUT_RECORD == Record || INPUT_RECORD == Playback {
|
||||
let x_input_multiplier = RECORDED_LR * CURRENT_LR; // if we aren't facing the way we were when we initially recorded, we reverse horizontal inputs
|
||||
println!("Overriding Cpu Player: {}, Frame: {}, BUFFER_FRAME: {}, STARTING_STATUS: {}, INPUT_RECORD: {:#?}, POSSESSION: {:#?}", controller_no, INPUT_RECORD_FRAME, BUFFER_FRAME, STARTING_STATUS, INPUT_RECORD, POSSESSION);
|
||||
|
||||
|
||||
let mut saved_mapped_inputs = P1_FINAL_MAPPING.lock()[if INPUT_RECORD == Record {
|
||||
CURRENT_RECORD_SLOT
|
||||
} else {
|
||||
CURRENT_PLAYBACK_SLOT
|
||||
}][INPUT_RECORD_FRAME];
|
||||
|
||||
|
||||
if BUFFER_FRAME <= 3 && BUFFER_FRAME > 0 {
|
||||
// Our option is already buffered, now we need to 0 out inputs to make sure our future controls act like flicks/presses instead of holding the button
|
||||
saved_mapped_inputs = MappedInputs::default();
|
||||
}
|
||||
|
||||
(*controller_data).buttons = saved_mapped_inputs.buttons;
|
||||
(*controller_data).stick_x = x_input_multiplier * ((saved_mapped_inputs.lstick_x as f32) / (i8::MAX as f32));
|
||||
(*controller_data).stick_x =
|
||||
x_input_multiplier * ((saved_mapped_inputs.lstick_x as f32) / (i8::MAX as f32));
|
||||
(*controller_data).stick_y = (saved_mapped_inputs.lstick_y as f32) / (i8::MAX as f32);
|
||||
// Clamp stick inputs for separate part of structure
|
||||
let mut clamped_lstick_x = x_input_multiplier * ((saved_mapped_inputs.lstick_x as f32) * STICK_CLAMP_MULTIPLIER).clamp(-1.0, 1.0);
|
||||
let mut clamped_lstick_y = ((saved_mapped_inputs.lstick_y as f32) * STICK_CLAMP_MULTIPLIER).clamp(-1.0, 1.0);
|
||||
clamped_lstick_x = if clamped_lstick_x.abs() >= STICK_NEUTRAL { clamped_lstick_x } else { 0.0 };
|
||||
clamped_lstick_y = if clamped_lstick_y.abs() >= STICK_NEUTRAL { clamped_lstick_y } else { 0.0 };
|
||||
let mut clamped_lstick_x = x_input_multiplier
|
||||
* ((saved_mapped_inputs.lstick_x as f32) * STICK_CLAMP_MULTIPLIER).clamp(-1.0, 1.0);
|
||||
let mut clamped_lstick_y =
|
||||
((saved_mapped_inputs.lstick_y as f32) * STICK_CLAMP_MULTIPLIER).clamp(-1.0, 1.0);
|
||||
clamped_lstick_x = if clamped_lstick_x.abs() >= STICK_NEUTRAL {
|
||||
clamped_lstick_x
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
clamped_lstick_y = if clamped_lstick_y.abs() >= STICK_NEUTRAL {
|
||||
clamped_lstick_y
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
(*controller_data).clamped_lstick_x = clamped_lstick_x;
|
||||
(*controller_data).clamped_lstick_y = clamped_lstick_y;
|
||||
//println!("CPU Buttons: {:#018b}", (*controller_data).buttons);
|
||||
|
||||
|
||||
// Keep counting frames, unless we're in standby waiting for an input, or are buffering an option
|
||||
// When buffering an option, we keep inputting the first frame of input during the buffer window
|
||||
if BUFFER_FRAME > 0 {
|
||||
|
@ -391,7 +434,7 @@ unsafe fn set_cpu_controls(p_data: *mut *mut u8) {
|
|||
} else if INPUT_RECORD_FRAME < FINAL_RECORD_FRAME - 1 && POSSESSION != Standby {
|
||||
INPUT_RECORD_FRAME += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn is_playback() -> bool {
|
||||
|
@ -406,7 +449,8 @@ pub unsafe fn is_standby() -> bool {
|
|||
POSSESSION == Standby || POSSESSION == Lockout
|
||||
}
|
||||
|
||||
extern "C" { // TODO: we should be using this from skyline
|
||||
extern "C" {
|
||||
// TODO: we should be using this from skyline
|
||||
#[link_name = "\u{1}_ZN3app8lua_bind31ModelModule__set_color_rgb_implEPNS_26BattleObjectModuleAccessorEfffNS_16MODEL_COLOR_TYPEE"]
|
||||
pub fn set_color_rgb_2(
|
||||
arg1: *mut BattleObjectModuleAccessor,
|
||||
|
@ -418,8 +462,5 @@ extern "C" { // TODO: we should be using this from skyline
|
|||
}
|
||||
|
||||
pub fn init() {
|
||||
skyline::install_hooks!(
|
||||
set_cpu_controls,
|
||||
handle_final_input_mapping,
|
||||
);
|
||||
skyline::install_hooks!(set_cpu_controls, handle_final_input_mapping,);
|
||||
}
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
#[macro_use]
|
||||
pub mod structures;
|
||||
pub mod structures;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#![allow(dead_code)] // TODO: Yeah don't do this
|
||||
use bitflags::bitflags;
|
||||
use crate::common::release::CURRENT_VERSION;
|
||||
use crate::common::events::smash_version;
|
||||
use crate::common::release::CURRENT_VERSION;
|
||||
use crate::training::save_states::SavedState;
|
||||
use bitflags::bitflags;
|
||||
use training_mod_consts::TrainingModpackMenu;
|
||||
|
||||
use crate::default_save_state;
|
||||
|
@ -10,7 +10,6 @@ use crate::training::character_specific::steve;
|
|||
use crate::training::charge::ChargeState;
|
||||
use crate::training::save_states::SaveState::NoAction;
|
||||
|
||||
|
||||
// Need to define necesary structures here. Probably should move to consts or something. Realistically, should be in skyline smash prob tho.
|
||||
|
||||
// Final final controls used for controlmodule
|
||||
|
@ -33,7 +32,8 @@ pub struct ControlModuleInternal {
|
|||
}
|
||||
|
||||
impl ControlModuleInternal {
|
||||
pub fn _clear(&mut self) { // Try to nullify controls so we can't control player 1 during recording
|
||||
pub fn _clear(&mut self) {
|
||||
// Try to nullify controls so we can't control player 1 during recording
|
||||
self.stick_x = 0.0;
|
||||
self.stick_y = 0.0;
|
||||
self.buttons = Buttons::empty();
|
||||
|
@ -46,7 +46,8 @@ impl ControlModuleInternal {
|
|||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[repr(C)]
|
||||
pub struct ControlModuleStored { // Custom type for saving only necessary controls/not saving vtable
|
||||
pub struct ControlModuleStored {
|
||||
// Custom type for saving only necessary controls/not saving vtable
|
||||
pub buttons: Buttons,
|
||||
pub stick_x: f32,
|
||||
pub stick_y: f32,
|
||||
|
@ -72,12 +73,12 @@ pub enum ControllerStyle {
|
|||
RightJoycon = 0x4,
|
||||
ProController = 0x5,
|
||||
DebugPad = 0x6, // probably
|
||||
GCController = 0x7
|
||||
GCController = 0x7,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct AutorepeatInfo {
|
||||
field: [u8; 0x18]
|
||||
field: [u8; 0x18],
|
||||
}
|
||||
|
||||
// Can map any of these over any button - what does this mean?
|
||||
|
@ -155,10 +156,9 @@ pub struct ControllerMapping {
|
|||
pub _31: u8,
|
||||
pub _32: u8,
|
||||
pub is_absmash: bool,
|
||||
pub _34: [u8; 0x1C]
|
||||
pub _34: [u8; 0x1C],
|
||||
}
|
||||
|
||||
|
||||
//type Buttons = u32; // may need to actually implement (like label and such)? Not for now though
|
||||
bitflags! {
|
||||
pub struct Buttons: u32 {
|
||||
|
@ -226,14 +226,14 @@ pub struct Controller {
|
|||
pub is_right_wired: bool,
|
||||
pub _x_c1: [u8; 3],
|
||||
pub npad_number: u32,
|
||||
pub _x_c8: [u8; 8]
|
||||
pub _x_c8: [u8; 8],
|
||||
}
|
||||
|
||||
// SomeControllerStruct used in hooked function - need to ask blujay what this is again
|
||||
#[repr(C)]
|
||||
pub struct SomeControllerStruct {
|
||||
padding: [u8; 0x10],
|
||||
controller: &'static mut Controller
|
||||
controller: &'static mut Controller,
|
||||
}
|
||||
|
||||
// Define struct used for final controller inputs
|
||||
|
@ -244,17 +244,18 @@ pub struct MappedInputs {
|
|||
pub lstick_x: i8,
|
||||
pub lstick_y: i8,
|
||||
pub rstick_x: i8,
|
||||
pub rstick_y: i8
|
||||
pub rstick_y: i8,
|
||||
}
|
||||
|
||||
impl MappedInputs { // pub needed?
|
||||
impl MappedInputs {
|
||||
// pub needed?
|
||||
pub fn default() -> MappedInputs {
|
||||
MappedInputs {
|
||||
buttons: Buttons::empty(),
|
||||
lstick_x: 0,
|
||||
lstick_y: 0,
|
||||
rstick_x: 0,
|
||||
rstick_y: 0
|
||||
rstick_y: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -273,11 +274,11 @@ pub struct Scenario {
|
|||
pub menu: TrainingModpackMenu,
|
||||
pub save_states: Vec<SavedState>,
|
||||
pub player_char: i32, // fighter_kind
|
||||
pub cpu_char: i32, // fighter_kind
|
||||
pub stage: i32, // index of stage, but -1 = random
|
||||
pub cpu_char: i32, // fighter_kind
|
||||
pub stage: i32, // index of stage, but -1 = random
|
||||
pub title: String,
|
||||
pub description: String,
|
||||
pub mod_version: String,
|
||||
pub mod_version: String,
|
||||
pub smash_version: String,
|
||||
// depending on version, we need to modify newly added menu options, so that regardless of their defaults they reflect the previous version to minimize breakage of old scenarios
|
||||
// we may also add more scenario parts to the struct in the future etc.
|
||||
|
@ -285,7 +286,6 @@ pub struct Scenario {
|
|||
// datetime?
|
||||
// author?
|
||||
// mirroring?
|
||||
|
||||
}
|
||||
|
||||
impl Scenario {
|
||||
|
@ -304,4 +304,4 @@ impl Scenario {
|
|||
smash_version: smash_version(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ use smash::lib::lua_const::*;
|
|||
|
||||
use crate::common::consts::*;
|
||||
use crate::common::*;
|
||||
use crate::training::{frame_counter, mash, input_record};
|
||||
use crate::training::{frame_counter, input_record, mash};
|
||||
|
||||
const NOT_SET: u32 = 9001;
|
||||
static mut LEDGE_DELAY: u32 = NOT_SET;
|
||||
|
@ -60,9 +60,11 @@ fn roll_ledge_case() {
|
|||
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 regular_action = if MENU.mash_triggers.contains(MashTrigger::LEDGE) {
|
||||
Some(MENU.mash_state.get_random())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
match LEDGE_CASE {
|
||||
LedgeOption::NEUTRAL => {
|
||||
|
@ -91,7 +93,6 @@ fn get_ledge_option() -> Option<Action> {
|
|||
}
|
||||
override_action.or(regular_action)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub unsafe fn force_option(module_accessor: &mut app::BattleObjectModuleAccessor) {
|
||||
|
@ -118,9 +119,13 @@ pub unsafe fn force_option(module_accessor: &mut app::BattleObjectModuleAccessor
|
|||
let should_buffer;
|
||||
let prev_status_kind = StatusModule::prev_status_kind(module_accessor, 0);
|
||||
|
||||
if status_kind == *FIGHTER_STATUS_KIND_CLIFF_WAIT && prev_status_kind == *FIGHTER_STATUS_KIND_CLIFF_CATCH { // For regular ledge grabs, we were just in catch and want to buffer on this frame
|
||||
if status_kind == *FIGHTER_STATUS_KIND_CLIFF_WAIT
|
||||
&& prev_status_kind == *FIGHTER_STATUS_KIND_CLIFF_CATCH
|
||||
{
|
||||
// For regular ledge grabs, we were just in catch and want to buffer on this frame
|
||||
should_buffer = (LEDGE_DELAY == 0) && (current_frame == 19) && (!flag_cliff);
|
||||
} else if status_kind == *FIGHTER_STATUS_KIND_CLIFF_WAIT { // otherwise we're in "wait" from grabbing with lasso, so we want to buffer on frame
|
||||
} else if status_kind == *FIGHTER_STATUS_KIND_CLIFF_WAIT {
|
||||
// otherwise we're in "wait" from grabbing with lasso, so we want to buffer on frame
|
||||
should_buffer = (LEDGE_DELAY == 0) && (current_frame == 18) && (flag_cliff);
|
||||
} else {
|
||||
should_buffer = false;
|
||||
|
@ -132,7 +137,11 @@ pub unsafe fn force_option(module_accessor: &mut app::BattleObjectModuleAccessor
|
|||
) {
|
||||
// Not able to take any action yet
|
||||
// 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 == LedgeOption::PLAYBACK && MENU.record_trigger != RecordTrigger::Ledge && MENU.ledge_delay != LongDelay::empty() {
|
||||
if should_buffer_playback
|
||||
&& LEDGE_CASE == LedgeOption::PLAYBACK
|
||||
&& MENU.record_trigger != RecordTrigger::Ledge
|
||||
&& MENU.ledge_delay != LongDelay::empty()
|
||||
{
|
||||
input_record::playback_ledge();
|
||||
return;
|
||||
}
|
||||
|
@ -183,7 +192,8 @@ pub unsafe fn is_enable_transition_term(
|
|||
}
|
||||
|
||||
// Disallow the default cliff-climb if we are waiting or we wait as part of a recording
|
||||
if (LEDGE_CASE == LedgeOption::WAIT || frame_counter::get_frame_count(LEDGE_DELAY_COUNTER) < LEDGE_DELAY)
|
||||
if (LEDGE_CASE == LedgeOption::WAIT
|
||||
|| frame_counter::get_frame_count(LEDGE_DELAY_COUNTER) < LEDGE_DELAY)
|
||||
&& term == *FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_CLIFF_CLIMB
|
||||
{
|
||||
return Some(false);
|
||||
|
@ -195,18 +205,25 @@ pub fn get_command_flag_cat(module_accessor: &mut app::BattleObjectModuleAccesso
|
|||
if !is_operation_cpu(module_accessor) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Set up check for beginning of ledge grab
|
||||
unsafe {
|
||||
let current_frame = MotionModule::frame(module_accessor) as i32;
|
||||
// Frame 18 is right before actionability for cliff catch
|
||||
#[allow(clippy::unnecessary_cast)]
|
||||
let just_grabbed_ledge = (StatusModule::status_kind(module_accessor) as i32 == *FIGHTER_STATUS_KIND_CLIFF_CATCH) && current_frame == 18;
|
||||
let just_grabbed_ledge = (StatusModule::status_kind(module_accessor) as i32
|
||||
== *FIGHTER_STATUS_KIND_CLIFF_CATCH)
|
||||
&& current_frame == 18;
|
||||
// Needs to be a frame earlier for lasso grabs
|
||||
#[allow(clippy::unnecessary_cast)]
|
||||
let just_lassoed_ledge = (StatusModule::status_kind(module_accessor) as i32 == *FIGHTER_STATUS_KIND_CLIFF_WAIT) && current_frame == 17;
|
||||
let just_lassoed_ledge = (StatusModule::status_kind(module_accessor) as i32
|
||||
== *FIGHTER_STATUS_KIND_CLIFF_WAIT)
|
||||
&& current_frame == 17;
|
||||
// Begin recording on ledge if this is the recording trigger
|
||||
if (just_grabbed_ledge || just_lassoed_ledge) && MENU.record_trigger == RecordTrigger::Ledge && !input_record::is_standby() {
|
||||
if (just_grabbed_ledge || just_lassoed_ledge)
|
||||
&& MENU.record_trigger == RecordTrigger::Ledge
|
||||
&& !input_record::is_standby()
|
||||
{
|
||||
input_record::lockout_record();
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -24,13 +24,16 @@ static mut AERIAL_DELAY_COUNTER: usize = 0;
|
|||
static mut AERIAL_DELAY: u32 = 0;
|
||||
|
||||
// Track if we're about to do another command flag cat run in the same frame for a dash or dash attack
|
||||
static mut IS_TRANSITIONING_DASH: bool = false;
|
||||
static mut IS_TRANSITIONING_DASH: bool = false;
|
||||
|
||||
unsafe fn is_beginning_dash_attack(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
|
||||
let current_status = StatusModule::status_kind(module_accessor);
|
||||
let is_dashing = current_status == *FIGHTER_STATUS_KIND_DASH;
|
||||
let is_dash_attacking = current_status == *FIGHTER_STATUS_KIND_ATTACK_DASH;
|
||||
let can_cancel_dash_attack = WorkModule::is_enable_transition_term(module_accessor, *FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_CATCH_DASH);
|
||||
let can_cancel_dash_attack = WorkModule::is_enable_transition_term(
|
||||
module_accessor,
|
||||
*FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_CATCH_DASH,
|
||||
);
|
||||
// We have to check the frame since the transition term is wrong early in the dash attack
|
||||
let motion_frame = MotionModule::frame(module_accessor);
|
||||
is_dashing || (is_dash_attacking && (can_cancel_dash_attack || motion_frame <= 2.0))
|
||||
|
@ -64,12 +67,18 @@ pub fn buffer_action(action: Action) {
|
|||
if action == Action::empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// We want to allow for triggering a mash to end playback for neutral playbacks, but not for SDI/disadv playbacks
|
||||
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 && input_record::is_playback() && !input_record::is_recording() && !input_record::is_standby() && !is_playback_queued() && action != Action::PLAYBACK {
|
||||
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
|
||||
&& input_record::is_playback()
|
||||
&& !input_record::is_recording()
|
||||
&& !input_record::is_standby()
|
||||
&& !is_playback_queued()
|
||||
&& action != Action::PLAYBACK
|
||||
{
|
||||
println!("Stopping mash playback for menu option!");
|
||||
input_record::stop_playback();
|
||||
}
|
||||
|
@ -487,7 +496,7 @@ unsafe fn get_attack_flag(
|
|||
try_change_status(module_accessor, *FIGHTER_STATUS_KIND_DASH, dash_transition);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
command_flag = 0;
|
||||
status = *FIGHTER_STATUS_KIND_ATTACK_DASH;
|
||||
|
||||
|
@ -496,7 +505,8 @@ unsafe fn get_attack_flag(
|
|||
let is_motion_dash = curr_motion_kind == smash::hash40("dash");
|
||||
let motion_frame = MotionModule::frame(module_accessor);
|
||||
|
||||
if current_status == *FIGHTER_STATUS_KIND_DASH && motion_frame == 0.0 && is_motion_dash {
|
||||
if current_status == *FIGHTER_STATUS_KIND_DASH && motion_frame == 0.0 && is_motion_dash
|
||||
{
|
||||
if !IS_TRANSITIONING_DASH {
|
||||
// The first time these conditions are met, we aren't ready to begin dash attacking, so get ready to transition next frame
|
||||
IS_TRANSITIONING_DASH = true;
|
||||
|
@ -605,7 +615,10 @@ unsafe fn get_flag(
|
|||
) -> i32 {
|
||||
// let current_status = StatusModule::prev_status_kind(module_accessor,0);
|
||||
let current_status = StatusModule::status_kind(module_accessor);
|
||||
println!("Current Status: {}, Expected Status: {}", current_status, expected_status);
|
||||
println!(
|
||||
"Current Status: {}, Expected Status: {}",
|
||||
current_status, expected_status
|
||||
);
|
||||
if current_status == expected_status {
|
||||
// Reset Buffer
|
||||
reset();
|
||||
|
|
|
@ -30,11 +30,11 @@ pub mod ui;
|
|||
mod air_dodge_direction;
|
||||
mod attack_angle;
|
||||
mod character_specific;
|
||||
mod input_recording;
|
||||
mod fast_fall;
|
||||
mod full_hop;
|
||||
pub mod input_delay;
|
||||
mod input_record;
|
||||
mod input_recording;
|
||||
mod mash;
|
||||
mod reset;
|
||||
pub mod save_states;
|
||||
|
|
|
@ -17,17 +17,17 @@ use crate::common::consts::get_random_float;
|
|||
use crate::common::consts::get_random_int;
|
||||
use crate::common::consts::FighterId;
|
||||
use crate::common::consts::OnOff;
|
||||
use crate::common::consts::SaveStateMirroring;
|
||||
use crate::common::consts::RecordTrigger;
|
||||
use crate::common::consts::SaveStateMirroring;
|
||||
//TODO: Cleanup above
|
||||
use crate::common::consts::SAVE_STATES_TOML_PATH;
|
||||
use crate::common::is_dead;
|
||||
use crate::common::MENU;
|
||||
use crate::is_operation_cpu;
|
||||
use crate::training::input_record;
|
||||
use crate::training::buff;
|
||||
use crate::training::character_specific::steve;
|
||||
use crate::training::charge::{self, ChargeState};
|
||||
use crate::training::input_record;
|
||||
use crate::training::items::apply_item;
|
||||
use crate::training::reset;
|
||||
use crate::training::ui::notifications;
|
||||
|
|
|
@ -8,7 +8,7 @@ use smash::lua2cpp::L2CFighterCommon;
|
|||
|
||||
use crate::common::consts::*;
|
||||
use crate::common::*;
|
||||
use crate::training::{mash, frame_counter, save_states, input_record};
|
||||
use crate::training::{frame_counter, input_record, mash, save_states};
|
||||
|
||||
// How many hits to hold shield until picking an Out Of Shield option
|
||||
static mut MULTI_HIT_OFFSET: u32 = 0;
|
||||
|
@ -105,7 +105,8 @@ pub unsafe fn get_param_float(
|
|||
param_type: u64,
|
||||
param_hash: u64,
|
||||
) -> Option<f32> {
|
||||
if !is_operation_cpu(module_accessor) || input_record::is_playback() { // shield normally during playback
|
||||
if !is_operation_cpu(module_accessor) || input_record::is_playback() {
|
||||
// shield normally during playback
|
||||
return None;
|
||||
}
|
||||
|
||||
|
@ -368,7 +369,7 @@ fn needs_oos_handling_drop_shield() -> bool {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if action == Action::SHIELD {
|
||||
let shield_state;
|
||||
unsafe {
|
||||
|
|
|
@ -1153,7 +1153,6 @@ impl ToggleTrait for SaveStateSlot {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// Input Recording Slot
|
||||
#[repr(u32)]
|
||||
#[derive(
|
||||
|
@ -1280,7 +1279,8 @@ impl ToggleTrait for RecordTrigger {
|
|||
#[derive(
|
||||
Debug, Clone, Copy, PartialEq, FromPrimitive, EnumIter, Serialize_repr, Deserialize_repr,
|
||||
)]
|
||||
pub enum HitstunPlayback { // Should these start at 0? All of my new menu structs need some review, I'm just doing whatever atm
|
||||
pub enum HitstunPlayback {
|
||||
// Should these start at 0? All of my new menu structs need some review, I'm just doing whatever atm
|
||||
Hitstun = 0x1,
|
||||
Hitstop = 0x2,
|
||||
Instant = 0x4,
|
||||
|
@ -1306,4 +1306,4 @@ impl ToggleTrait for HitstunPlayback {
|
|||
fn to_toggle_vals() -> Vec<u32> {
|
||||
HitstunPlayback::iter().map(|i| i as u32).collect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue