1
0
Fork 0
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:
jugeeya 2023-08-02 13:53:24 -07:00 committed by GitHub
parent 1486ad8d05
commit 9ef506aac7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 204 additions and 134 deletions

View file

@ -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
})
}
}

View file

@ -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::*;

View file

@ -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,);
}

View file

@ -1,2 +1,2 @@
#[macro_use]
pub mod structures;
pub mod structures;

View file

@ -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(),
}
}
}
}

View file

@ -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;
}

View file

@ -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();

View file

@ -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;

View file

@ -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;

View file

@ -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 {

View file

@ -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()
}
}
}