mirror of
https://github.com/jugeeya/UltimateTrainingModpack.git
synced 2025-04-27 07:59:18 +00:00
Initial
This commit is contained in:
parent
2b241dcb19
commit
ddd5f16b87
11 changed files with 248 additions and 313 deletions
3
ryujinx_build.ps1
vendored
3
ryujinx_build.ps1
vendored
|
@ -1,5 +1,8 @@
|
||||||
$IP=(Test-Connection -ComputerName (hostname) -Count 1 | Select -ExpandProperty IPV4Address).IPAddressToString
|
$IP=(Test-Connection -ComputerName (hostname) -Count 1 | Select -ExpandProperty IPV4Address).IPAddressToString
|
||||||
cargo skyline build --release --features layout_arc_from_file
|
cargo skyline build --release --features layout_arc_from_file
|
||||||
|
if (($lastexitcode -ne 0)) {
|
||||||
|
exit $lastexitcode
|
||||||
|
}
|
||||||
|
|
||||||
# Set up symlinks
|
# Set up symlinks
|
||||||
$RYUJINX_LAYOUT_ARC_PATH="C:\Users\Josh\AppData\Roaming\Ryujinx\sdcard\ultimate\TrainingModpack\layout.arc"
|
$RYUJINX_LAYOUT_ARC_PATH="C:\Users\Josh\AppData\Roaming\Ryujinx\sdcard\ultimate\TrainingModpack\layout.arc"
|
||||||
|
|
|
@ -46,6 +46,113 @@ pub fn button_mapping(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn name_to_font_glyph(button: ButtonConfig, style: ControllerStyle) -> Option<u16> {
|
||||||
|
let is_gcc = style == ControllerStyle::GCController;
|
||||||
|
Some(match button {
|
||||||
|
ButtonConfig::A => 0xE0E0,
|
||||||
|
ButtonConfig::B => 0xE0E1,
|
||||||
|
ButtonConfig::X => {
|
||||||
|
if is_gcc {
|
||||||
|
0xE206
|
||||||
|
} else {
|
||||||
|
0xE0E2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ButtonConfig::Y => {
|
||||||
|
if is_gcc {
|
||||||
|
0xE207
|
||||||
|
} else {
|
||||||
|
0xE0E3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ButtonConfig::L => {
|
||||||
|
if is_gcc {
|
||||||
|
return None;
|
||||||
|
} else {
|
||||||
|
0xE0E4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ButtonConfig::R => {
|
||||||
|
if is_gcc {
|
||||||
|
0xE205
|
||||||
|
} else {
|
||||||
|
0xE0E5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ButtonConfig::ZL => {
|
||||||
|
if is_gcc {
|
||||||
|
0xE204
|
||||||
|
} else {
|
||||||
|
0xE0E6
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ButtonConfig::ZR => {
|
||||||
|
if is_gcc {
|
||||||
|
0xE208
|
||||||
|
} else {
|
||||||
|
0xE0E7
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ButtonConfig::DPAD_UP => {
|
||||||
|
if is_gcc {
|
||||||
|
0xE209
|
||||||
|
} else {
|
||||||
|
0xE0EB
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ButtonConfig::DPAD_DOWN => {
|
||||||
|
if is_gcc {
|
||||||
|
0xE20A
|
||||||
|
} else {
|
||||||
|
0xE0EC
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ButtonConfig::DPAD_LEFT => {
|
||||||
|
if is_gcc {
|
||||||
|
0xE20B
|
||||||
|
} else {
|
||||||
|
0xE0ED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ButtonConfig::DPAD_RIGHT => {
|
||||||
|
if is_gcc {
|
||||||
|
0xE20C
|
||||||
|
} else {
|
||||||
|
0xE0EE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ButtonConfig::PLUS => {
|
||||||
|
if is_gcc {
|
||||||
|
0xE20D
|
||||||
|
} else {
|
||||||
|
0xE0EF
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ButtonConfig::MINUS => {
|
||||||
|
if is_gcc {
|
||||||
|
return None;
|
||||||
|
} else {
|
||||||
|
0xE0F0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ButtonConfig::LSTICK => {
|
||||||
|
if is_gcc {
|
||||||
|
return None;
|
||||||
|
} else {
|
||||||
|
0xE104
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ButtonConfig::RSTICK => {
|
||||||
|
if is_gcc {
|
||||||
|
return None;
|
||||||
|
} else {
|
||||||
|
0xE105
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => return None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, EnumIter, PartialEq, Eq, Hash, Copy, Clone)]
|
#[derive(Debug, EnumIter, PartialEq, Eq, Hash, Copy, Clone)]
|
||||||
pub enum ButtonCombo {
|
pub enum ButtonCombo {
|
||||||
OpenMenu,
|
OpenMenu,
|
||||||
|
|
|
@ -41,14 +41,25 @@ pub fn is_emulator() -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_module_accessor(fighter_id: FighterId) -> *mut app::BattleObjectModuleAccessor {
|
pub fn get_module_accessor(fighter_id: FighterId) -> *mut app::BattleObjectModuleAccessor {
|
||||||
|
try_get_module_accessor(fighter_id).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn try_get_module_accessor(
|
||||||
|
fighter_id: FighterId,
|
||||||
|
) -> Option<*mut app::BattleObjectModuleAccessor> {
|
||||||
let entry_id_int = fighter_id as i32;
|
let entry_id_int = fighter_id as i32;
|
||||||
let entry_id = app::FighterEntryID(entry_id_int);
|
let entry_id = app::FighterEntryID(entry_id_int);
|
||||||
unsafe {
|
unsafe {
|
||||||
let mgr = *(FIGHTER_MANAGER_ADDR as *mut *mut app::FighterManager);
|
let mgr = *(FIGHTER_MANAGER_ADDR as *mut *mut app::FighterManager);
|
||||||
let fighter_entry =
|
let fighter_entry =
|
||||||
FighterManager::get_fighter_entry(mgr, entry_id) as *mut app::FighterEntry;
|
FighterManager::get_fighter_entry(mgr, entry_id) as *mut app::FighterEntry;
|
||||||
|
if fighter_entry.is_null() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
let current_fighter_id = FighterEntry::current_fighter_id(fighter_entry);
|
let current_fighter_id = FighterEntry::current_fighter_id(fighter_entry);
|
||||||
app::sv_battle_object::module_accessor(current_fighter_id as u32)
|
Some(app::sv_battle_object::module_accessor(
|
||||||
|
current_fighter_id as u32,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Binary file not shown.
23
src/training/input_log.rs
Normal file
23
src/training/input_log.rs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
|
use crate::common::input::*;
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
use parking_lot::Mutex;
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
pub static ref P1_INPUT_MAPPINGS: Mutex<VecDeque<MappedInputs>> = Mutex::new(VecDeque::new());
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: how many
|
||||||
|
const NUM_INPUTS: usize = 120;
|
||||||
|
|
||||||
|
pub fn handle_final_input_mapping(player_idx: i32, out: *mut MappedInputs) {
|
||||||
|
unsafe {
|
||||||
|
if player_idx == 0 {
|
||||||
|
let mut mappings = P1_INPUT_MAPPINGS.lock();
|
||||||
|
|
||||||
|
mappings.push_front(*out);
|
||||||
|
mappings.truncate(NUM_INPUTS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,9 @@
|
||||||
use crate::common::button_config;
|
use crate::common::button_config;
|
||||||
use crate::common::consts::{FighterId, HitstunPlayback, OnOff, RecordTrigger};
|
use crate::common::consts::{FighterId, HitstunPlayback, OnOff, RecordTrigger};
|
||||||
use crate::common::input::*;
|
use crate::common::input::*;
|
||||||
use crate::common::{get_module_accessor, is_in_hitstun, is_in_shieldstun, MENU};
|
use crate::common::{
|
||||||
|
get_module_accessor, is_in_hitstun, is_in_shieldstun, try_get_module_accessor, MENU,
|
||||||
|
};
|
||||||
use crate::training::mash;
|
use crate::training::mash;
|
||||||
use crate::training::ui::notifications::{clear_notifications, color_notification};
|
use crate::training::ui::notifications::{clear_notifications, color_notification};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
|
@ -434,7 +436,14 @@ unsafe fn set_cpu_controls(p_data: *mut *mut u8) {
|
||||||
should_mash_playback();
|
should_mash_playback();
|
||||||
}
|
}
|
||||||
|
|
||||||
let cpu_module_accessor = get_module_accessor(FighterId::CPU);
|
let cpu_module_accessor = try_get_module_accessor(FighterId::CPU);
|
||||||
|
|
||||||
|
// Sometimes we can try to grab their module accessor before they are valid?
|
||||||
|
if cpu_module_accessor.is_none() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let cpu_module_accessor = cpu_module_accessor.unwrap();
|
||||||
|
|
||||||
if INPUT_RECORD == Pause {
|
if INPUT_RECORD == Pause {
|
||||||
match LOCKOUT_FRAME.cmp(&0) {
|
match LOCKOUT_FRAME.cmp(&0) {
|
||||||
Ordering::Greater => LOCKOUT_FRAME -= 1,
|
Ordering::Greater => LOCKOUT_FRAME -= 1,
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
#[macro_use]
|
|
||||||
pub mod structures;
|
|
|
@ -1,307 +0,0 @@
|
||||||
#![allow(dead_code)] // TODO: Yeah don't do this
|
|
||||||
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;
|
|
||||||
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
|
|
||||||
// can I actually derive these?
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct ControlModuleInternal {
|
|
||||||
pub vtable: *mut u8,
|
|
||||||
pub controller_index: i32,
|
|
||||||
pub buttons: Buttons,
|
|
||||||
pub stick_x: f32,
|
|
||||||
pub stick_y: f32,
|
|
||||||
pub padding: [f32; 2],
|
|
||||||
pub unk: [u32; 8],
|
|
||||||
pub clamped_lstick_x: f32,
|
|
||||||
pub clamped_lstick_y: f32,
|
|
||||||
pub padding2: [f32; 2],
|
|
||||||
pub clamped_rstick_x: f32,
|
|
||||||
pub clamped_rstick_y: f32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ControlModuleInternal {
|
|
||||||
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();
|
|
||||||
self.clamped_lstick_x = 0.0;
|
|
||||||
self.clamped_lstick_y = 0.0;
|
|
||||||
self.clamped_rstick_x = 0.0;
|
|
||||||
self.clamped_rstick_y = 0.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct ControlModuleStored {
|
|
||||||
// Custom type for saving only necessary controls/not saving vtable
|
|
||||||
pub buttons: Buttons,
|
|
||||||
pub stick_x: f32,
|
|
||||||
pub stick_y: f32,
|
|
||||||
pub padding: [f32; 2],
|
|
||||||
pub unk: [u32; 8],
|
|
||||||
pub clamped_lstick_x: f32,
|
|
||||||
pub clamped_lstick_y: f32,
|
|
||||||
pub padding2: [f32; 2],
|
|
||||||
pub clamped_rstick_x: f32,
|
|
||||||
pub clamped_rstick_y: f32,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Re-ordered bitfield the game uses for buttons - TODO: Is this a problem? What's the original order?
|
|
||||||
pub type ButtonBitfield = i32; // may need to actually implement? Not for now though
|
|
||||||
|
|
||||||
/// Controller style declaring what kind of controller is being used
|
|
||||||
#[derive(PartialEq, Eq, Debug, Copy, Clone)]
|
|
||||||
#[repr(u32)]
|
|
||||||
pub enum ControllerStyle {
|
|
||||||
Handheld = 0x1,
|
|
||||||
DualJoycon = 0x2,
|
|
||||||
LeftJoycon = 0x3,
|
|
||||||
RightJoycon = 0x4,
|
|
||||||
ProController = 0x5,
|
|
||||||
DebugPad = 0x6, // probably
|
|
||||||
GCController = 0x7,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct AutorepeatInfo {
|
|
||||||
field: [u8; 0x18],
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can map any of these over any button - what does this mean?
|
|
||||||
#[repr(u8)]
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
|
||||||
pub enum InputKind {
|
|
||||||
Attack = 0x0,
|
|
||||||
Special = 0x1,
|
|
||||||
Jump = 0x2,
|
|
||||||
Guard = 0x3,
|
|
||||||
Grab = 0x4,
|
|
||||||
SmashAttack = 0x5,
|
|
||||||
AppealHi = 0xA,
|
|
||||||
AppealS = 0xB,
|
|
||||||
AppealLw = 0xC,
|
|
||||||
Unset = 0xD,
|
|
||||||
}
|
|
||||||
|
|
||||||
// 0x50 Byte struct containing the information for controller mappings
|
|
||||||
#[derive(Debug)]
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct ControllerMapping {
|
|
||||||
pub gc_l: InputKind,
|
|
||||||
pub gc_r: InputKind,
|
|
||||||
pub gc_z: InputKind,
|
|
||||||
pub gc_dup: InputKind,
|
|
||||||
pub gc_dlr: InputKind,
|
|
||||||
pub gc_ddown: InputKind,
|
|
||||||
pub gc_a: InputKind,
|
|
||||||
pub gc_b: InputKind,
|
|
||||||
pub gc_cstick: InputKind,
|
|
||||||
pub gc_y: InputKind,
|
|
||||||
pub gc_x: InputKind,
|
|
||||||
pub gc_rumble: bool,
|
|
||||||
pub gc_absmash: bool,
|
|
||||||
pub gc_tapjump: bool,
|
|
||||||
pub gc_sensitivity: u8,
|
|
||||||
// 0xF
|
|
||||||
pub pro_l: InputKind,
|
|
||||||
pub pro_r: InputKind,
|
|
||||||
pub pro_zl: InputKind,
|
|
||||||
pub pro_zr: InputKind,
|
|
||||||
pub pro_dup: InputKind,
|
|
||||||
pub pro_dlr: InputKind,
|
|
||||||
pub pro_ddown: InputKind,
|
|
||||||
pub pro_a: InputKind,
|
|
||||||
pub pro_b: InputKind,
|
|
||||||
pub pro_cstick: InputKind,
|
|
||||||
pub pro_x: InputKind,
|
|
||||||
pub pro_y: InputKind,
|
|
||||||
pub pro_rumble: bool,
|
|
||||||
pub pro_absmash: bool,
|
|
||||||
pub pro_tapjump: bool,
|
|
||||||
pub pro_sensitivity: u8,
|
|
||||||
// 0x1F
|
|
||||||
pub joy_shoulder: InputKind,
|
|
||||||
pub joy_zshoulder: InputKind,
|
|
||||||
pub joy_sl: InputKind,
|
|
||||||
pub joy_sr: InputKind,
|
|
||||||
pub joy_up: InputKind,
|
|
||||||
pub joy_right: InputKind,
|
|
||||||
pub joy_left: InputKind,
|
|
||||||
pub joy_down: InputKind,
|
|
||||||
pub joy_rumble: bool,
|
|
||||||
pub joy_absmash: bool,
|
|
||||||
pub joy_tapjump: bool,
|
|
||||||
pub joy_sensitivity: u8,
|
|
||||||
// 0x2B
|
|
||||||
pub _2b: u8,
|
|
||||||
pub _2c: u8,
|
|
||||||
pub _2d: u8,
|
|
||||||
pub _2e: u8,
|
|
||||||
pub _2f: u8,
|
|
||||||
pub _30: u8,
|
|
||||||
pub _31: u8,
|
|
||||||
pub _32: u8,
|
|
||||||
pub is_absmash: bool,
|
|
||||||
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 {
|
|
||||||
const ATTACK = 0x1;
|
|
||||||
const SPECIAL = 0x2;
|
|
||||||
const JUMP = 0x4;
|
|
||||||
const GUARD = 0x8;
|
|
||||||
const CATCH = 0x10;
|
|
||||||
const SMASH = 0x20;
|
|
||||||
const JUMP_MINI = 0x40;
|
|
||||||
const CSTICK_ON = 0x80;
|
|
||||||
const STOCK_SHARE = 0x100;
|
|
||||||
const ATTACK_RAW = 0x200;
|
|
||||||
const APPEAL_HI = 0x400;
|
|
||||||
const SPECIAL_RAW = 0x800;
|
|
||||||
const APPEAL_LW = 0x1000;
|
|
||||||
const APPEAL_SL = 0x2000;
|
|
||||||
const APPEAL_SR = 0x4000;
|
|
||||||
const FLICK_JUMP = 0x8000;
|
|
||||||
const GUARD_HOLD = 0x10000;
|
|
||||||
const SPECIAL_RAW2 = 0x20000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Controller class used internally by the game
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct Controller {
|
|
||||||
pub vtable: *const u64,
|
|
||||||
pub current_buttons: ButtonBitfield,
|
|
||||||
pub previous_buttons: ButtonBitfield,
|
|
||||||
pub left_stick_x: f32,
|
|
||||||
pub left_stick_y: f32,
|
|
||||||
pub left_trigger: f32,
|
|
||||||
pub _left_padding: u32,
|
|
||||||
pub right_stick_x: f32,
|
|
||||||
pub right_stick_y: f32,
|
|
||||||
pub right_trigger: f32,
|
|
||||||
pub _right_padding: u32,
|
|
||||||
pub gyro: [f32; 4],
|
|
||||||
pub button_timespan: AutorepeatInfo,
|
|
||||||
pub lstick_timespan: AutorepeatInfo,
|
|
||||||
pub rstick_timespan: AutorepeatInfo,
|
|
||||||
pub just_down: ButtonBitfield,
|
|
||||||
pub just_release: ButtonBitfield,
|
|
||||||
pub autorepeat_keys: u32,
|
|
||||||
pub autorepeat_threshold: u32,
|
|
||||||
pub autorepeat_initial_press_threshold: u32,
|
|
||||||
pub style: ControllerStyle,
|
|
||||||
pub controller_id: u32,
|
|
||||||
pub primary_controller_color1: u32,
|
|
||||||
pub primary_controller_color2: u32,
|
|
||||||
pub secondary_controller_color1: u32,
|
|
||||||
pub secondary_controller_color2: u32,
|
|
||||||
pub led_pattern: u8,
|
|
||||||
pub button_autorepeat_initial_press: bool,
|
|
||||||
pub lstick_autorepeat_initial_press: bool,
|
|
||||||
pub rstick_autorepeat_initial_press: bool,
|
|
||||||
pub is_valid_controller: bool,
|
|
||||||
pub _x_b9: [u8; 2],
|
|
||||||
pub is_connected: bool,
|
|
||||||
pub is_left_connected: bool,
|
|
||||||
pub is_right_connected: bool,
|
|
||||||
pub is_wired: bool,
|
|
||||||
pub is_left_wired: bool,
|
|
||||||
pub is_right_wired: bool,
|
|
||||||
pub _x_c1: [u8; 3],
|
|
||||||
pub npad_number: u32,
|
|
||||||
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,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Define struct used for final controller inputs
|
|
||||||
#[derive(Copy, Clone)]
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct MappedInputs {
|
|
||||||
pub buttons: Buttons,
|
|
||||||
pub lstick_x: i8,
|
|
||||||
pub lstick_y: i8,
|
|
||||||
pub rstick_x: i8,
|
|
||||||
pub rstick_y: i8,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MappedInputs {
|
|
||||||
// pub needed?
|
|
||||||
pub fn default() -> MappedInputs {
|
|
||||||
MappedInputs {
|
|
||||||
buttons: Buttons::empty(),
|
|
||||||
lstick_x: 0,
|
|
||||||
lstick_y: 0,
|
|
||||||
rstick_x: 0,
|
|
||||||
rstick_y: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Final Structure containing all input recording slots, menu options, and save states.
|
|
||||||
// 5 Input Recording Slots should be fine for now for most mix up scenarios
|
|
||||||
// When loading a "scenario", we want to load all menu options (with maybe overrides in the config?), load savestate(s), and load input recording slots.
|
|
||||||
// If we have submenus for input recording slots, we need to get that info as well, and we want to apply saved damage from save states to the menu.
|
|
||||||
// Damage range seems to be saved in menu for range of damage, so that's taken care of with menu.
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct Scenario {
|
|
||||||
pub record_slots: Vec<Vec<MappedInputs>>,
|
|
||||||
pub starting_statuses: Vec<i32>,
|
|
||||||
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 title: String,
|
|
||||||
pub description: 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.
|
|
||||||
// pub screenshot: image????
|
|
||||||
// datetime?
|
|
||||||
// author?
|
|
||||||
// mirroring?
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Scenario {
|
|
||||||
pub fn default() -> Scenario {
|
|
||||||
Scenario {
|
|
||||||
record_slots: vec![vec![MappedInputs::default(); 600]; 5],
|
|
||||||
starting_statuses: vec![0],
|
|
||||||
menu: crate::common::consts::DEFAULTS_MENU,
|
|
||||||
save_states: vec![default_save_state!(); 5],
|
|
||||||
player_char: 0,
|
|
||||||
cpu_char: 0,
|
|
||||||
stage: -1, // index of stage, but -1 = random/any stage
|
|
||||||
title: "Scenario Title".to_string(),
|
|
||||||
description: "Description...".to_string(),
|
|
||||||
mod_version: CURRENT_VERSION.to_string(),
|
|
||||||
smash_version: smash_version(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -34,6 +34,7 @@ mod character_specific;
|
||||||
mod fast_fall;
|
mod fast_fall;
|
||||||
mod full_hop;
|
mod full_hop;
|
||||||
pub mod input_delay;
|
pub mod input_delay;
|
||||||
|
mod input_log;
|
||||||
mod input_record;
|
mod input_record;
|
||||||
mod mash;
|
mod mash;
|
||||||
mod reset;
|
mod reset;
|
||||||
|
@ -712,15 +713,34 @@ unsafe fn handle_final_input_mapping(
|
||||||
controller_struct: &mut SomeControllerStruct,
|
controller_struct: &mut SomeControllerStruct,
|
||||||
arg: bool,
|
arg: bool,
|
||||||
) {
|
) {
|
||||||
// go through the original mapping function first
|
// Order of hooks here REALLY matters. Tread lightly
|
||||||
|
|
||||||
|
// Go through the original mapping function first
|
||||||
original!()(mappings, player_idx, out, controller_struct, arg);
|
original!()(mappings, player_idx, out, controller_struct, arg);
|
||||||
if !is_training_mode() {
|
if !is_training_mode() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Grab button input requests from player
|
||||||
|
// Non-mutable pull
|
||||||
button_config::handle_final_input_mapping(player_idx, controller_struct);
|
button_config::handle_final_input_mapping(player_idx, controller_struct);
|
||||||
|
|
||||||
|
// Grab menu inputs from player
|
||||||
|
// Non-mutable pull
|
||||||
menu::handle_final_input_mapping(player_idx, controller_struct, out);
|
menu::handle_final_input_mapping(player_idx, controller_struct, out);
|
||||||
|
|
||||||
|
// Check if we should apply hot reload configs
|
||||||
|
// Non-mutable pull
|
||||||
dev_config::handle_final_input_mapping(player_idx, controller_struct);
|
dev_config::handle_final_input_mapping(player_idx, controller_struct);
|
||||||
|
|
||||||
|
// Potentially apply input delay
|
||||||
|
// MUTATES controller state
|
||||||
input_delay::handle_final_input_mapping(player_idx, out);
|
input_delay::handle_final_input_mapping(player_idx, out);
|
||||||
|
|
||||||
|
input_log::handle_final_input_mapping(player_idx, out);
|
||||||
|
|
||||||
|
// Potentially apply input recording, thus with delay
|
||||||
|
// MUTATES controller state
|
||||||
input_record::handle_final_input_mapping(player_idx, out);
|
input_record::handle_final_input_mapping(player_idx, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
69
src/training/ui/input_log.rs
Normal file
69
src/training/ui/input_log.rs
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
use skyline::nn::ui2d::*;
|
||||||
|
use smash::ui2d::{SmashPane, SmashTextBox};
|
||||||
|
use training_mod_consts::ButtonConfig;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
common::{
|
||||||
|
button_config::name_to_font_glyph,
|
||||||
|
input::Buttons,
|
||||||
|
menu::{P1_CONTROLLER_STYLE, QUICK_MENU_ACTIVE},
|
||||||
|
},
|
||||||
|
training::input_log::P1_INPUT_MAPPINGS,
|
||||||
|
};
|
||||||
|
|
||||||
|
macro_rules! log_parent_fmt {
|
||||||
|
($x:ident) => {
|
||||||
|
format!("TrModInputLog{}", $x).as_str()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn draw(root_pane: &Pane) {
|
||||||
|
let log_number = 0;
|
||||||
|
let log_pane = root_pane
|
||||||
|
.find_pane_by_name_recursive(log_parent_fmt!(log_number))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// TODO: And menu option for input log is on
|
||||||
|
log_pane.set_visible(!QUICK_MENU_ACTIVE);
|
||||||
|
|
||||||
|
let logs_ptr = P1_INPUT_MAPPINGS.data_ptr();
|
||||||
|
if logs_ptr.is_null() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let logs = &*logs_ptr;
|
||||||
|
let first_log = logs.front();
|
||||||
|
if first_log.is_none() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let first_log = first_log.unwrap();
|
||||||
|
|
||||||
|
let p1_style_ptr = P1_CONTROLLER_STYLE.data_ptr();
|
||||||
|
if p1_style_ptr.is_null() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let input_pane = log_pane
|
||||||
|
.find_pane_by_name_recursive("InputTxt")
|
||||||
|
.unwrap()
|
||||||
|
.as_textbox();
|
||||||
|
|
||||||
|
input_pane.set_text_string("NONE");
|
||||||
|
|
||||||
|
if first_log.buttons.contains(Buttons::ATTACK) {
|
||||||
|
let potential_font_glyph = name_to_font_glyph(ButtonConfig::A, *p1_style_ptr);
|
||||||
|
if let Some(font_glyph) = potential_font_glyph {
|
||||||
|
input_pane.set_text_string("");
|
||||||
|
|
||||||
|
let it = input_pane.text_buf as *mut u16;
|
||||||
|
input_pane.text_len = 1;
|
||||||
|
*it = font_glyph;
|
||||||
|
*(it.add(1)) = 0x0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log_pane
|
||||||
|
.find_pane_by_name_recursive("FrameTxt")
|
||||||
|
.unwrap()
|
||||||
|
.as_textbox()
|
||||||
|
.set_text_string(format!("{}", logs.len()).as_str());
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ use crate::consts::LAYOUT_ARC_PATH;
|
||||||
|
|
||||||
mod damage;
|
mod damage;
|
||||||
mod display;
|
mod display;
|
||||||
|
mod input_log;
|
||||||
mod menu;
|
mod menu;
|
||||||
pub mod notifications;
|
pub mod notifications;
|
||||||
|
|
||||||
|
@ -38,6 +39,7 @@ pub unsafe fn handle_draw(layout: *mut Layout, draw_info: u64, cmd_buffer: u64)
|
||||||
damage::draw(root_pane, &layout_name);
|
damage::draw(root_pane, &layout_name);
|
||||||
|
|
||||||
if layout_name == "info_training" {
|
if layout_name == "info_training" {
|
||||||
|
input_log::draw(root_pane);
|
||||||
display::draw(root_pane);
|
display::draw(root_pane);
|
||||||
menu::draw(root_pane);
|
menu::draw(root_pane);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue