diff --git a/src/common/consts.rs b/src/common/consts.rs index 1ce689e..5f4d14f 100644 --- a/src/common/consts.rs +++ b/src/common/consts.rs @@ -26,10 +26,10 @@ macro_rules! extra_bitflag_impls { pub fn to_index(&self) -> u32 { if self.bits == 0 { - return 0; + 0 + } else { + self.bits.trailing_zeros() } - - return self.bits.trailing_zeros(); } pub fn get_random(&self) -> $e { @@ -47,9 +47,9 @@ macro_rules! extra_bitflag_impls { } } - pub fn to_toggle_strs() -> Vec { + pub fn to_toggle_strs() -> Vec<&'static str> { let all_options = <$e>::all().to_vec(); - all_options.iter().map(|i| i.into_string()).collect() + all_options.iter().map(|i| i.as_str().unwrap_or("")).collect() } pub fn to_toggle_vals() -> Vec { @@ -57,19 +57,11 @@ macro_rules! extra_bitflag_impls { all_options.iter().map(|i| i.bits() as usize).collect() } pub fn to_url_param(&self) -> String { - let mut vec = self.to_vec(); - let mut s = String::new(); - let mut first = true; - while !vec.is_empty() { - let field = vec.pop().unwrap().bits(); - if !first { - s.push_str(","); - } else { - first = false; - } - s.push_str(&field.to_string()); - } - s + self.to_vec() + .into_iter() + .map(|field| field.bits().to_string()) + .collect::>() + .join(",") } } } @@ -108,10 +100,10 @@ impl Direction { let index = self.into_index(); if index == 0 { - return None; + None + } else { + Some((index as i32 - 1) as f64 * PI / 4.0) } - - Some((index as i32 - 1) as f64 * PI / 4.0) } fn into_index(self) -> i32 { match self { @@ -130,8 +122,8 @@ impl Direction { } } - fn into_string(self) -> String { - match self { + fn as_str(self) -> Option<&'static str> { + Some(match self { Direction::OUT => "Away", Direction::UP_OUT => "Up and Away", Direction::UP => "Up", @@ -143,9 +135,8 @@ impl Direction { Direction::NEUTRAL => "Neutral", Direction::LEFT => "Left", Direction::RIGHT => "Right", - _ => "", - } - .to_string() + _ => return None, + }) } } @@ -175,16 +166,15 @@ impl LedgeOption { }) } - fn into_string(self) -> String { - match self { + fn as_str(self) -> Option<&'static str> { + Some(match self { LedgeOption::NEUTRAL => "Neutral Getup", LedgeOption::ROLL => "Roll", LedgeOption::JUMP => "Jump", LedgeOption::ATTACK => "Getup Attack", LedgeOption::WAIT => "Wait", - _ => "", - } - .to_string() + _ => return None, + }) } } @@ -201,15 +191,14 @@ bitflags! { } impl TechFlags { - fn into_string(self) -> String { - match self { + fn as_str(self) -> Option<&'static str> { + Some(match self { TechFlags::NO_TECH => "No Tech", TechFlags::ROLL_F => "Roll Forwards", TechFlags::ROLL_B => "Roll Backwards", TechFlags::IN_PLACE => "Tech In Place", - _ => "", - } - .to_string() + _ => return None, + }) } } @@ -226,15 +215,14 @@ bitflags! { } impl MissTechFlags { - fn into_string(self) -> String { - match self { + fn as_str(self) -> Option<&'static str> { + Some(match self { MissTechFlags::GETUP => "Neutral Getup", MissTechFlags::ATTACK => "Getup Attack", MissTechFlags::ROLL_F => "Roll Forwards", MissTechFlags::ROLL_B => "Roll Backwards", - _ => "", - } - .to_string() + _ => return None, + }) } } @@ -251,24 +239,17 @@ pub enum Shield { } impl Shield { - pub fn into_string(self) -> String { - match self { + pub fn as_str(self) -> Option<&'static str> { + Some(match self { Shield::None => "None", Shield::Infinite => "Infinite", Shield::Hold => "Hold", Shield::Constant => "Constant", - } - .to_string() + }) } pub fn to_url_param(&self) -> String { - match self { - Shield::None => "0", - Shield::Infinite => "1", - Shield::Hold => "2", - Shield::Constant => "3", - } - .to_string() + (*self as i32).to_string() } } @@ -282,22 +263,16 @@ pub enum SaveStateMirroring { } impl SaveStateMirroring { - pub fn into_string(self) -> String { - match self { + pub fn as_str(self) -> Option<&'static str> { + Some(match self { SaveStateMirroring::None => "None", SaveStateMirroring::Alternate => "Alternate", SaveStateMirroring::Random => "Random", - } - .to_string() + }) } fn to_url_param(&self) -> String { - match self { - SaveStateMirroring::None => "0", - SaveStateMirroring::Alternate => "1", - SaveStateMirroring::Random => "2", - } - .to_string() + (*self as i32).to_string() } } @@ -313,16 +288,15 @@ bitflags! { } impl Defensive { - fn into_string(self) -> String { - match self { + fn as_str(self) -> Option<&'static str> { + Some(match self { Defensive::SPOT_DODGE => "Spotdodge", Defensive::ROLL_F => "Roll Forwards", Defensive::ROLL_B => "Roll Backwards", Defensive::JAB => "Jab", Defensive::SHIELD => "Shield", - _ => "", - } - .to_string() + _ => return None, + }) } } @@ -344,20 +318,15 @@ impl OnOff { } } - pub fn into_string(self) -> String { - match self { + pub fn as_str(self) -> Option<&'static str> { + Some(match self { OnOff::Off => "Off", OnOff::On => "On", - } - .to_string() + }) } pub fn to_url_param(&self) -> String { - match self { - OnOff::Off => "0", - OnOff::On => "1", - } - .to_string() + (*self as i32).to_string() } } @@ -404,8 +373,8 @@ impl Action { }) } - pub fn into_string(self) -> String { - match self { + pub fn as_str(self) -> Option<&'static str> { + Some(match self { Action::AIR_DODGE => "Airdodge", Action::JUMP => "Jump", Action::SHIELD => "Shield", @@ -431,9 +400,8 @@ impl Action { Action::GRAB => "Grab", Action::DASH => "Dash", Action::DASH_ATTACK => "Dash Attack", - _ => "", - } - .to_string() + _ => return None, + }) } } @@ -448,14 +416,13 @@ bitflags! { } impl AttackAngle { - pub fn into_string(self) -> String { - match self { + pub fn as_str(self) -> Option<&'static str> { + Some(match self { AttackAngle::NEUTRAL => "Neutral", AttackAngle::UP => "Up", AttackAngle::DOWN => "Down", - _ => "", - } - .to_string() + _ => return None, + }) } } @@ -498,8 +465,8 @@ bitflags! { } impl Delay { - pub fn into_string(self) -> String { - match self { + pub fn as_str(self) -> Option<&'static str> { + Some(match self { Delay::D0 => "0", Delay::D1 => "1", Delay::D2 => "2", @@ -531,9 +498,8 @@ impl Delay { Delay::D28 => "28", Delay::D29 => "29", Delay::D30 => "30", - _ => "", - } - .to_string() + _ => return None, + }) } pub fn into_delay(&self) -> u32 { @@ -580,8 +546,8 @@ bitflags! { } impl LongDelay { - pub fn into_string(self) -> String { - match self { + pub fn as_str(self) -> Option<&'static str> { + Some(match self { LongDelay::D0 => "0", LongDelay::D10 => "10", LongDelay::D20 => "20", @@ -613,9 +579,8 @@ impl LongDelay { LongDelay::D280 => "280", LongDelay::D290 => "290", LongDelay::D300 => "300", - _ => "", - } - .to_string() + _ => return None, + }) } pub fn into_longdelay(&self) -> u32 { @@ -639,12 +604,11 @@ impl BoolFlag { matches!(self, BoolFlag::TRUE) } - pub fn into_string(self) -> String { - match self { + pub fn as_str(self) -> Option<&'static str> { + Some(match self { BoolFlag::TRUE => "True", _ => "False", - } - .to_string() + }) } } @@ -665,22 +629,16 @@ impl SdiStrength { } } - pub fn into_string(self) -> String { - match self { + pub fn as_str(self) -> Option<&'static str> { + Some(match self { SdiStrength::Normal => "Normal", SdiStrength::Medium => "Medium", SdiStrength::High => "High", - } - .to_string() + }) } pub fn to_url_param(&self) -> String { - match self { - SdiStrength::Normal => "0", - SdiStrength::Medium => "1", - SdiStrength::High => "2", - } - .to_string() + (*self as u32).to_string() } } diff --git a/src/common/events.rs b/src/common/events.rs index 762a4ad..623c36e 100644 --- a/src/common/events.rs +++ b/src/common/events.rs @@ -5,6 +5,8 @@ use skyline::nn::{account, crypto, oe, time}; use std::convert::TryInto; use std::time::{SystemTime, UNIX_EPOCH}; +use crate::common::release::CURRENT_VERSION; + pub static mut EVENT_QUEUE: Vec = vec![]; static mut SESSION_ID: OnceCell = OnceCell::new(); static mut DEVICE_ID: OnceCell = OnceCell::new(); @@ -29,18 +31,17 @@ extern "C" { #[derive(Debug)] pub struct Uuid { - Size: u32, - StringSize: u32, + size: u32, + string_size: u32, data: [u8; 16], } impl Uuid { pub fn to_str(&self) -> String { self.data - .into_iter() + .iter() .map(|i| format!("{:02x}", i)) - .collect::>() - .join("") + .collect::() } } @@ -51,15 +52,14 @@ struct Sha256Hash { impl Event { pub fn new() -> Event { let mut device_uuid = Uuid { - Size: 16, - StringSize: 300, + size: 16, + string_size: 300, data: [0u8; 16], }; unsafe { GetPseudoDeviceId(&mut device_uuid as *mut Uuid); } - let mut time = skyline::nn::time::PosixTime { time: 0 }; unsafe { time::Initialize(); let event_time = SystemTime::now() @@ -67,10 +67,6 @@ impl Event { .expect("Time went backwards") .as_millis(); - let mut smash_version = oe::DisplayVersion { - name: [0 as skyline::libc::c_char; 16], - }; - oe::GetDisplayVersion(&mut smash_version); if SESSION_ID.get().is_none() { account::Initialize(); let mut user_uid = account::Uid::new(); @@ -88,7 +84,7 @@ impl Event { .set( user_uid .id - .into_iter() + .iter() .map(|i| format!("{:02x}", i)) .collect::>() .join(""), @@ -106,7 +102,7 @@ impl Event { .set( device_uuid .data - .into_iter() + .iter() .map(|i| format!("{:02x}", i)) .collect::>() .join(""), @@ -134,7 +130,7 @@ impl Event { .set( session_id_hash .hash - .into_iter() + .iter() .map(|i| format!("{:02x}", i)) .collect::>() .join(""), @@ -142,32 +138,42 @@ impl Event { .unwrap(); } - let mut event = Event::default(); - event.user_id = USER_ID.get().unwrap().to_string(); - event.device_id = DEVICE_ID.get().unwrap().to_string(); - event.event_time = event_time; - event.session_id = SESSION_ID.get().unwrap().to_string(); - event.mod_version = crate::common::release::CURRENT_VERSION.to_string(); - event.smash_version = - std::ffi::CStr::from_ptr(smash_version.name.as_ptr() as *const i8) - .to_owned() - .to_str() - .unwrap() - .to_string(); - event + Event { + user_id: USER_ID.get().unwrap().to_string(), + device_id: DEVICE_ID.get().unwrap().to_string(), + event_time, + session_id: SESSION_ID.get().unwrap().to_string(), + mod_version: CURRENT_VERSION.to_string(), + smash_version: smash_version(), + ..Default::default() + } } } pub fn smash_open() -> Event { - let mut event = Event::new(); - event.event_name = "SMASH_OPEN".to_string(); - event + Event { + event_name: "SMASH_OPEN".to_string(), + ..Event::new() + } } pub fn menu_open(menu_settings: String) -> Event { - let mut event = Event::new(); - event.event_name = "MENU_OPEN".to_string(); - event.menu_settings = menu_settings; - event + Event { + event_name: "MENU_OPEN".to_string(), + menu_settings, + ..Event::new() + } + } +} + +fn smash_version() -> String { + let mut smash_version = oe::DisplayVersion { name: [0; 16] }; + + unsafe { + oe::GetDisplayVersion(&mut smash_version); + + std::ffi::CStr::from_ptr(smash_version.name.as_ptr() as *const i8) + .to_string_lossy() + .into_owned() } } diff --git a/src/common/menu.rs b/src/common/menu.rs index 0c0f0f2..61c4ee6 100644 --- a/src/common/menu.rs +++ b/src/common/menu.rs @@ -6,6 +6,7 @@ use skyline::info::get_program_id; use skyline_web::{Background, BootDisplay, Webpage}; use smash::lib::lua_const::*; use std::fs; +use std::ops::BitOr; use std::path::Path; use strum::IntoEnumIterator; @@ -219,7 +220,7 @@ macro_rules! add_bitflag_submenu { $title, stringify!($id), MENU.$id.bits() as usize, - [<$id _strs>].iter().map(|i| i.as_str()).collect(), + [<$id _strs>], [<$id _vals>], DEFAULT_MENU.$id.bits() as usize, stringify!($help_text), @@ -233,14 +234,14 @@ macro_rules! add_single_option_submenu { paste::paste!{ let mut [<$id _toggles>] = Vec::new(); for val in [<$e>]::iter() { - [<$id _toggles>].push((val.into_string(), val as usize)); + [<$id _toggles>].push((val.as_str().unwrap_or(""), val as usize)); } $menu.add_sub_menu( $title, stringify!($id), MENU.$id as usize, - [<$id _toggles>].iter().map(|(x, y)| (x.as_str(), *y)).collect::>(), + [<$id _toggles>], [].to_vec(), DEFAULT_MENU.$id as usize, stringify!($help_text), @@ -283,15 +284,12 @@ pub fn set_menu_from_url(s: &str) { let toggle_vals = toggle_value_split[1]; - let mut bits = 0; - for toggle_val in toggle_vals.split(',') { - if toggle_val.is_empty() { - continue; - } - - let val = toggle_val.parse::().unwrap(); - bits |= val; - } + let bitwise_or = >::bitor; + let bits = toggle_vals + .split(',') + .filter(|val| !val.is_empty()) + .map(|val| val.parse().unwrap()) + .fold(0, bitwise_or); unsafe { MENU.set(toggle, bits); @@ -556,11 +554,16 @@ pub unsafe fn write_menu() { fs::write(path, data).unwrap(); } -pub unsafe fn spawn_menu() { - frame_counter::reset_frame_count(FRAME_COUNTER_INDEX); - frame_counter::start_counting(FRAME_COUNTER_INDEX); +const MENU_CONF_PATH: &str = "sd:/TrainingModpack/training_modpack_menu.conf"; + +pub fn spawn_menu() { + unsafe { + frame_counter::reset_frame_count(FRAME_COUNTER_INDEX); + frame_counter::start_counting(FRAME_COUNTER_INDEX); + } + let fname = "training_menu.html"; - let params = MENU.to_url_params(); + let params = unsafe { MENU.to_url_params() }; let page_response = Webpage::new() .background(Background::BlurredScreenshot) .htdocs_dir("contents") @@ -574,8 +577,7 @@ pub unsafe fn spawn_menu() { set_menu_from_url(last_url); - let menu_conf_path = "sd:/TrainingModpack/training_modpack_menu.conf"; - std::fs::write(menu_conf_path, last_url).expect("Failed to write menu conf file"); + std::fs::write(MENU_CONF_PATH, last_url).expect("Failed to write menu conf file"); unsafe { EVENT_QUEUE.push(Event::menu_open(last_url.to_string())); } diff --git a/src/common/mod.rs b/src/common/mod.rs index c750946..d3f1626 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -5,7 +5,6 @@ pub mod raygun_printer; pub mod release; use crate::common::consts::*; -use crate::common::events::*; use smash::app::{self, lua_bind::*}; use smash::hash40; use smash::lib::lua_const::*; @@ -95,59 +94,43 @@ pub fn is_operation_cpu(module_accessor: &mut app::BattleObjectModuleAccessor) - } pub fn is_grounded(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool { - let situation_kind; - unsafe { - situation_kind = StatusModule::situation_kind(module_accessor) as i32; - } + let situation_kind = unsafe { StatusModule::situation_kind(module_accessor) as i32 }; + situation_kind == SITUATION_KIND_GROUND } pub fn is_airborne(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool { - let situation_kind; - unsafe { - situation_kind = StatusModule::situation_kind(module_accessor) as i32; - } + let situation_kind = unsafe { StatusModule::situation_kind(module_accessor) as i32 }; + situation_kind == SITUATION_KIND_AIR } pub fn is_idle(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool { - let status_kind; - unsafe { - status_kind = StatusModule::status_kind(module_accessor); - } + let status_kind = unsafe { StatusModule::status_kind(module_accessor) }; + status_kind == FIGHTER_STATUS_KIND_WAIT } pub fn is_in_hitstun(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool { - let status_kind; - unsafe { - status_kind = StatusModule::status_kind(module_accessor); - } + let status_kind = unsafe { StatusModule::status_kind(module_accessor) }; + (*FIGHTER_STATUS_KIND_DAMAGE..*FIGHTER_STATUS_KIND_DAMAGE_FALL).contains(&status_kind) } pub fn is_in_footstool(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool { - let status_kind; - unsafe { - status_kind = StatusModule::status_kind(module_accessor); - } + let status_kind = unsafe { StatusModule::status_kind(module_accessor) }; + (*FIGHTER_STATUS_KIND_TREAD_DAMAGE..=*FIGHTER_STATUS_KIND_TREAD_FALL).contains(&status_kind) } pub fn is_shielding(module_accessor: *mut app::BattleObjectModuleAccessor) -> bool { - unsafe { - let status_kind = StatusModule::status_kind(module_accessor) as i32; - (*FIGHTER_STATUS_KIND_GUARD_ON..=*FIGHTER_STATUS_KIND_GUARD_DAMAGE).contains(&status_kind) - } + let status_kind = unsafe { StatusModule::status_kind(module_accessor) as i32 }; + + (*FIGHTER_STATUS_KIND_GUARD_ON..=*FIGHTER_STATUS_KIND_GUARD_DAMAGE).contains(&status_kind) } pub fn is_in_shieldstun(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool { - let status_kind; - let prev_status; - - unsafe { - status_kind = StatusModule::status_kind(module_accessor); - prev_status = StatusModule::prev_status_kind(module_accessor, 0); - } + let status_kind = unsafe { StatusModule::status_kind(module_accessor) }; + let prev_status = unsafe { StatusModule::prev_status_kind(module_accessor, 0) }; // If we are taking shield damage or we are droping shield from taking shield damage we are in hitstun status_kind == FIGHTER_STATUS_KIND_GUARD_DAMAGE diff --git a/src/common/raygun_printer.rs b/src/common/raygun_printer.rs index 5f7eb8f..20b6e45 100644 --- a/src/common/raygun_printer.rs +++ b/src/common/raygun_printer.rs @@ -1,9 +1,11 @@ +use std::ops::Neg; + use smash::app; use smash::phx::{Hash40, Vector3f}; -pub static RAYGUN_LENGTH: f32 = 8.0; -pub static RAYGUN_HEIGHT: f32 = 6.0; -pub static RAYGUN_HORIZ_OFFSET: f32 = 2.0; +pub const RAYGUN_LENGTH: f32 = 8.0; +pub const RAYGUN_HEIGHT: f32 = 6.0; +pub const RAYGUN_HORIZ_OFFSET: f32 = 2.0; /* segment data list : {Z, Y, X, ZRot, Size} @@ -152,6 +154,9 @@ fn print_char( horiz_offset: f32, facing_left: i32, ) { + let is_facing_left = facing_left == -1; + let x_direction = facing_left as f32; + let alph_index = alphabet_index(to_print); if !(0..40).contains(&alph_index) { return; @@ -164,30 +169,22 @@ fn print_char( let mut index = segment_char as i32 - 'a' as i32; let segment: [f32; 5]; - if facing_left == -1 { + if is_facing_left { index = SEGMENT_REV[index as usize] as i32 - 'a' as i32; } segment = SEGMENT_DICT[index as usize]; - let size_mult: f32 = 0.5; + const SIZE_MULT: f32 = 0.5; - let mut z = segment[0]; - let mut y = segment[1] + line_offset; - let mut x = segment[2] + horiz_offset; - let mut zrot = segment[3]; + let x = ((segment[2] + horiz_offset) * SIZE_MULT) + (x_direction * 5.0); + let y = ((segment[1] + line_offset) * SIZE_MULT) + 5.0; + let z = segment[0] * SIZE_MULT; - if facing_left == -1 { - zrot *= -1.0; - } + let zrot = segment[3]; + let zrot = if is_facing_left { zrot.neg() } else { zrot }; - let mut size = segment[4]; + let size = segment[4] * SIZE_MULT; - x *= size_mult; - x += facing_left as f32 * 5.0; - y *= size_mult; - y += 5.0; - z *= size_mult; - size *= size_mult; show_segment(module_accessor, z, y, x, zrot, size); } } @@ -207,10 +204,8 @@ pub fn print_string(module_accessor: &mut app::BattleObjectModuleAccessor, to_wr let mut horiz_offset = 0.0; let mut char_num = 0; - let facing_left: i32; - unsafe { - facing_left = app::lua_bind::PostureModule::lr(module_accessor) as i32; - } + let facing_left = unsafe { app::lua_bind::PostureModule::lr(module_accessor) as i32 }; + let facing_direction = facing_left as f32; if to_write.len() <= 8 && !to_write.contains('\n') { line_num = 1; @@ -234,9 +229,9 @@ pub fn print_string(module_accessor: &mut app::BattleObjectModuleAccessor, to_wr char_num += 1; // short characters if curr_char == 'D' || curr_char == '1' { - horiz_offset += facing_left as f32 * (RAYGUN_LENGTH / 2.0 + 3.0); + horiz_offset += facing_direction * (RAYGUN_LENGTH / 2.0 + 3.0); } else { - horiz_offset += facing_left as f32 * (RAYGUN_LENGTH + 3.0); + horiz_offset += facing_direction * (RAYGUN_LENGTH + 3.0); } if char_num > 8 { diff --git a/src/common/release.rs b/src/common/release.rs index 03d1d1f..47a9e01 100644 --- a/src/common/release.rs +++ b/src/common/release.rs @@ -1,6 +1,6 @@ use skyline_web::DialogOk; use std::fs; -use std::io::Write; + pub const CURRENT_VERSION: &str = env!("CARGO_PKG_VERSION"); const VERSION_FILE_PATH: &str = "sd:/TrainingModpack/version.txt"; @@ -9,14 +9,15 @@ fn is_current_version(fpath: &str) -> bool { if fs::metadata(fpath).is_err() { let _ = fs::File::create(fpath).expect("Could not create version file!"); } - let content = fs::read_to_string(fpath).unwrap_or_else(|_| "".to_string()); - content == CURRENT_VERSION + + fs::read_to_string(fpath) + .map(|content| content == CURRENT_VERSION) + .unwrap_or(false) } fn record_current_version(fpath: &str) { // Write the current version to the version file - let mut f = fs::File::create(fpath).unwrap(); - write!(f, "{}", CURRENT_VERSION.to_owned()).expect("Could not record current version!"); + fs::write(fpath, CURRENT_VERSION).expect("Could not record current version!") } pub fn version_check() {