mirror of
https://github.com/jugeeya/UltimateTrainingModpack.git
synced 2025-03-14 02:16:10 +00:00
Initial Save State Slots (#474)
This commit is contained in:
parent
e10092b766
commit
bf78f06f7d
7 changed files with 124 additions and 68 deletions
|
@ -1 +1 @@
|
|||
stable
|
||||
nightly
|
|
@ -33,6 +33,14 @@ static mut BUTTON_COMBO_CONFIG: BtnComboConfig = BtnComboConfig {
|
|||
hold: vec![],
|
||||
press: vec![],
|
||||
},
|
||||
previous_save_state_slot: BtnList {
|
||||
hold: vec![],
|
||||
press: vec![],
|
||||
},
|
||||
next_save_state_slot: BtnList {
|
||||
hold: vec![],
|
||||
press: vec![],
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -40,6 +48,8 @@ pub enum ButtonCombo {
|
|||
OpenMenu,
|
||||
SaveState,
|
||||
LoadState,
|
||||
PrevSaveStateSlot,
|
||||
NextSaveStateSlot
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Default)]
|
||||
|
@ -53,6 +63,8 @@ struct BtnComboConfig {
|
|||
open_menu: BtnList,
|
||||
save_state: BtnList,
|
||||
load_state: BtnList,
|
||||
previous_save_state_slot: BtnList,
|
||||
next_save_state_slot: BtnList
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
|
@ -64,7 +76,8 @@ pub fn validate_config(data: &str) -> bool {
|
|||
let conf: TopLevelBtnComboConfig =
|
||||
toml::from_str(data).expect("Custom button config has invalid schema");
|
||||
let conf = conf.button_config;
|
||||
let configs = [conf.open_menu, conf.save_state, conf.load_state];
|
||||
let configs = [conf.open_menu, conf.save_state, conf.load_state,
|
||||
conf.previous_save_state_slot, conf.next_save_state_slot];
|
||||
let bad_keys = configs
|
||||
.iter()
|
||||
.flat_map(|btn_list| {
|
||||
|
@ -108,6 +121,14 @@ pub fn save_all_btn_config_from_defaults() {
|
|||
hold: vec!["GRAB".to_string()],
|
||||
press: vec!["UPTAUNT".to_string()],
|
||||
},
|
||||
previous_save_state_slot: BtnList {
|
||||
hold: vec!["GRAB".to_string()],
|
||||
press: vec!["LEFTTAUNT".to_string()],
|
||||
},
|
||||
next_save_state_slot: BtnList {
|
||||
hold: vec!["GRAB".to_string()],
|
||||
press: vec!["RIGHTTAUNT".to_string()],
|
||||
},
|
||||
},
|
||||
};
|
||||
unsafe {
|
||||
|
@ -144,6 +165,14 @@ pub fn combo_passes(
|
|||
&BUTTON_COMBO_CONFIG.load_state.hold,
|
||||
&BUTTON_COMBO_CONFIG.load_state.press,
|
||||
),
|
||||
ButtonCombo::PrevSaveStateSlot => (
|
||||
&BUTTON_COMBO_CONFIG.previous_save_state_slot.hold,
|
||||
&BUTTON_COMBO_CONFIG.previous_save_state_slot.press,
|
||||
),
|
||||
ButtonCombo::NextSaveStateSlot => (
|
||||
&BUTTON_COMBO_CONFIG.next_save_state_slot.hold,
|
||||
&BUTTON_COMBO_CONFIG.next_save_state_slot.press,
|
||||
),
|
||||
};
|
||||
hold.iter()
|
||||
.map(|hold| *BUTTON_MAPPING.get(&*hold.to_uppercase()).unwrap())
|
||||
|
@ -187,4 +216,12 @@ press=["DOWNTAUNT",]
|
|||
[button_config.load_state]
|
||||
hold=["GRAB",]
|
||||
press=["UPTAUNT",]
|
||||
|
||||
[button_config.previous_save_state_slot]
|
||||
hold=["GRAB",]
|
||||
press=["LEFTTAUNT",]
|
||||
|
||||
[button_config.next_save_state_slot]
|
||||
hold=["GRAB",]
|
||||
press=["RIGHTTAUNT",]
|
||||
"#;
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
clippy::missing_safety_doc,
|
||||
clippy::wrong_self_convention,
|
||||
clippy::option_map_unit_fn,
|
||||
clippy::float_cmp,
|
||||
clippy::fn_null_check,
|
||||
// Look into why for this one
|
||||
clippy::transmute_num_to_bytes
|
||||
|
@ -80,10 +79,10 @@ pub fn main() {
|
|||
info!("Initialized.");
|
||||
unsafe {
|
||||
EVENT_QUEUE.push(Event::smash_open());
|
||||
notification("Training Modpack", "Welcome!", 60);
|
||||
notification("Open Menu", "Special + Uptaunt", 120);
|
||||
notification("Save State", "Grab + Downtaunt", 120);
|
||||
notification("Load State", "Grab + Uptaunt", 120);
|
||||
notification("Training Modpack".to_string(), "Welcome!".to_string(), 60);
|
||||
notification("Open Menu".to_string(), "Special + Uptaunt".to_string(), 120);
|
||||
notification("Save State".to_string(), "Grab + Downtaunt".to_string(), 120);
|
||||
notification("Load State".to_string(), "Grab + Uptaunt".to_string(), 120);
|
||||
}
|
||||
|
||||
hitbox_visualizer::hitbox_visualization();
|
||||
|
|
|
@ -5,7 +5,6 @@ use crate::common::*;
|
|||
use crate::training::*;
|
||||
|
||||
pub static mut FRAME_ADVANTAGE: i32 = 0;
|
||||
static mut FRAME_ADVANTAGE_STR: String = String::new();
|
||||
static mut PLAYER_ACTIONABLE: bool = false;
|
||||
static mut CPU_ACTIONABLE: bool = false;
|
||||
static mut PLAYER_ACTIVE_FRAME: u32 = 0;
|
||||
|
@ -50,13 +49,11 @@ unsafe fn is_actionable(module_accessor: *mut app::BattleObjectModuleAccessor) -
|
|||
fn update_frame_advantage(new_frame_adv: i32) {
|
||||
unsafe {
|
||||
FRAME_ADVANTAGE = new_frame_adv;
|
||||
FRAME_ADVANTAGE_STR = String::new();
|
||||
FRAME_ADVANTAGE_STR.push_str(&format!("{FRAME_ADVANTAGE}"));
|
||||
if MENU.frame_advantage == OnOff::On {
|
||||
ui::notifications::clear_notifications("Frame Advantage");
|
||||
ui::notifications::color_notification(
|
||||
"Frame Advantage",
|
||||
&FRAME_ADVANTAGE_STR,
|
||||
"Frame Advantage".to_string(),
|
||||
format!("{FRAME_ADVANTAGE}"),
|
||||
60,
|
||||
match FRAME_ADVANTAGE {
|
||||
x if x < 0 => ResColor { r: 200, g: 8, b: 8, a: 255 },
|
||||
|
|
|
@ -12,19 +12,22 @@ use crate::training::character_specific::steve;
|
|||
use crate::training::charge::{self, ChargeState};
|
||||
use crate::training::items::apply_item;
|
||||
use crate::training::reset;
|
||||
use crate::{is_ptrainer, ITEM_MANAGER_ADDR};
|
||||
use SaveState::*;
|
||||
use smash::app::{self, lua_bind::*, Item};
|
||||
use smash::hash40;
|
||||
use smash::lib::lua_const::*;
|
||||
use smash::phx::{Hash40, Vector3f};
|
||||
use std::collections::HashMap;
|
||||
use training_mod_consts::{CharacterItem, SaveDamage};
|
||||
use crate::training::ui::notifications;
|
||||
|
||||
extern "C" {
|
||||
#[link_name = "\u{1}_ZN3app14sv_information8stage_idEv"]
|
||||
pub fn stage_id() -> i32;
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
#[derive(PartialEq, Copy, Clone)]
|
||||
enum SaveState {
|
||||
Save,
|
||||
NoAction,
|
||||
|
@ -34,6 +37,7 @@ enum SaveState {
|
|||
ApplyBuff,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct SavedState {
|
||||
x: f32,
|
||||
y: f32,
|
||||
|
@ -85,21 +89,32 @@ macro_rules! default_save_state {
|
|||
};
|
||||
}
|
||||
|
||||
use crate::{is_ptrainer, ITEM_MANAGER_ADDR};
|
||||
use SaveState::*;
|
||||
// static mut SAVE_STATE_PLAYER: SavedState = default_save_state!();
|
||||
// static mut SAVE_STATE_CPU: SavedState = default_save_state!();
|
||||
|
||||
const NUM_SAVE_STATE_SLOTS : usize = 5;
|
||||
static mut SAVE_STATE_PLAYER : [SavedState; NUM_SAVE_STATE_SLOTS] = [default_save_state!(); NUM_SAVE_STATE_SLOTS];
|
||||
static mut SAVE_STATE_CPU : [SavedState; NUM_SAVE_STATE_SLOTS] = [default_save_state!(); NUM_SAVE_STATE_SLOTS];
|
||||
static mut SAVE_STATE_SLOT : usize = 0;
|
||||
|
||||
unsafe fn save_state_player() -> &'static mut SavedState {
|
||||
&mut SAVE_STATE_PLAYER[SAVE_STATE_SLOT]
|
||||
}
|
||||
|
||||
unsafe fn save_state_cpu() -> &'static mut SavedState {
|
||||
&mut SAVE_STATE_CPU[SAVE_STATE_SLOT]
|
||||
}
|
||||
|
||||
static mut SAVE_STATE_PLAYER: SavedState = default_save_state!();
|
||||
static mut SAVE_STATE_CPU: SavedState = default_save_state!();
|
||||
static mut MIRROR_STATE: f32 = 1.0;
|
||||
// MIRROR_STATE == 1 -> Do not mirror
|
||||
// MIRROR_STATE == -1 -> Do Mirror
|
||||
static mut MIRROR_STATE: f32 = 1.0;
|
||||
|
||||
pub unsafe fn is_killing() -> bool {
|
||||
SAVE_STATE_PLAYER.state == KillPlayer || SAVE_STATE_CPU.state == KillPlayer
|
||||
save_state_player().state == KillPlayer || save_state_cpu().state == KillPlayer
|
||||
}
|
||||
|
||||
pub unsafe fn is_loading() -> bool {
|
||||
SAVE_STATE_PLAYER.state != NoAction || SAVE_STATE_CPU.state != NoAction
|
||||
save_state_player().state != NoAction || save_state_cpu().state != NoAction
|
||||
}
|
||||
|
||||
pub unsafe fn should_mirror() -> f32 {
|
||||
|
@ -221,9 +236,9 @@ pub unsafe fn save_states(module_accessor: &mut app::BattleObjectModuleAccessor)
|
|||
let is_cpu = WorkModule::get_int(module_accessor, *FIGHTER_INSTANCE_WORK_ID_INT_ENTRY_ID)
|
||||
== FighterId::CPU as i32;
|
||||
let save_state = if is_cpu {
|
||||
&mut SAVE_STATE_CPU
|
||||
save_state_cpu()
|
||||
} else {
|
||||
&mut SAVE_STATE_PLAYER
|
||||
save_state_player()
|
||||
};
|
||||
|
||||
let fighter_kind = app::utility::get_kind(module_accessor);
|
||||
|
@ -240,6 +255,28 @@ pub unsafe fn save_states(module_accessor: &mut app::BattleObjectModuleAccessor)
|
|||
]
|
||||
.contains(&fighter_kind);
|
||||
|
||||
if !is_operation_cpu(module_accessor) &&
|
||||
button_config::combo_passes(module_accessor, button_config::ButtonCombo::PrevSaveStateSlot) {
|
||||
SAVE_STATE_SLOT = if SAVE_STATE_SLOT == 0 {
|
||||
NUM_SAVE_STATE_SLOTS - 1
|
||||
} else {
|
||||
SAVE_STATE_SLOT - 1
|
||||
};
|
||||
notifications::clear_notifications("Save State");
|
||||
notifications::notification("Save State".to_string(), format!("Switched to Slot {SAVE_STATE_SLOT}"), 120);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if !is_operation_cpu(module_accessor) &&
|
||||
button_config::combo_passes(module_accessor, button_config::ButtonCombo::NextSaveStateSlot) {
|
||||
SAVE_STATE_SLOT = (SAVE_STATE_SLOT + 1) % NUM_SAVE_STATE_SLOTS;
|
||||
notifications::clear_notifications("Save State");
|
||||
notifications::notification("Save State".to_string(), format!("Switched to Slot {SAVE_STATE_SLOT}"), 120);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Grab + Dpad up: reset state
|
||||
let autoload_reset = MENU.save_state_autoload == OnOff::On
|
||||
&& save_state.state == NoAction
|
||||
|
@ -251,8 +288,8 @@ pub unsafe fn save_states(module_accessor: &mut app::BattleObjectModuleAccessor)
|
|||
}
|
||||
if (autoload_reset || triggered_reset) && !fighter_is_nana {
|
||||
if save_state.state == NoAction {
|
||||
SAVE_STATE_PLAYER.state = KillPlayer;
|
||||
SAVE_STATE_CPU.state = KillPlayer;
|
||||
save_state_player().state = KillPlayer;
|
||||
save_state_cpu().state = KillPlayer;
|
||||
}
|
||||
MIRROR_STATE = should_mirror();
|
||||
return;
|
||||
|
@ -497,8 +534,8 @@ pub unsafe fn save_states(module_accessor: &mut app::BattleObjectModuleAccessor)
|
|||
if button_config::combo_passes(module_accessor, button_config::ButtonCombo::SaveState) {
|
||||
// Don't begin saving state if Nana's delayed input is captured
|
||||
MIRROR_STATE = 1.0;
|
||||
SAVE_STATE_PLAYER.state = Save;
|
||||
SAVE_STATE_CPU.state = Save;
|
||||
save_state_player().state = Save;
|
||||
save_state_cpu().state = Save;
|
||||
}
|
||||
|
||||
if save_state.state == Save && !fighter_is_nana {
|
||||
|
|
|
@ -24,32 +24,30 @@ pub unsafe fn draw(root_pane: &mut Pane) {
|
|||
let notification_idx = 0;
|
||||
|
||||
let queue = &mut ui::notifications::QUEUE;
|
||||
let notification = queue.first_mut();
|
||||
let notification = queue.first();
|
||||
|
||||
if let Some(parent) = root_pane.find_pane_by_name_recursive(display_parent_fmt!(notification_idx)) {
|
||||
parent.set_visible(notification.is_some());
|
||||
if notification.is_none() {
|
||||
return;
|
||||
}
|
||||
root_pane.find_pane_by_name_recursive(display_parent_fmt!(notification_idx))
|
||||
.unwrap().set_visible(notification.is_some());
|
||||
if notification.is_none() {
|
||||
return;
|
||||
}
|
||||
|
||||
let notification = notification.unwrap();
|
||||
let header_txt = notification.header();
|
||||
let message = notification.message();
|
||||
let color = notification.color();
|
||||
let color = notification.color;
|
||||
|
||||
root_pane.find_pane_by_name_recursive(display_header_fmt!(notification_idx))
|
||||
.unwrap()
|
||||
.as_textbox().set_text_string(¬ification.header);
|
||||
|
||||
let text = root_pane.find_pane_by_name_recursive(display_txt_fmt!(notification_idx))
|
||||
.unwrap().as_textbox();
|
||||
text.set_text_string(¬ification.message);
|
||||
text.set_default_material_colors();
|
||||
text.set_color(color.r, color.g, color.b, color.a);
|
||||
|
||||
let notification = queue.first_mut().unwrap();
|
||||
let has_completed = notification.tick();
|
||||
if has_completed {
|
||||
queue.remove(0);
|
||||
}
|
||||
|
||||
if let Some(header) = root_pane.find_pane_by_name_recursive(display_header_fmt!(notification_idx)) {
|
||||
header.as_textbox().set_text_string(header_txt);
|
||||
}
|
||||
|
||||
if let Some(text) = root_pane.find_pane_by_name_recursive(display_txt_fmt!(notification_idx)) {
|
||||
let text = text.as_textbox();
|
||||
text.set_text_string(message);
|
||||
text.set_default_material_colors();
|
||||
text.set_color(color.r, color.g, color.b, color.a);
|
||||
}
|
||||
}
|
|
@ -1,17 +1,17 @@
|
|||
use skyline::nn::ui2d::ResColor;
|
||||
|
||||
pub static mut QUEUE: Vec<Notification<'static>> = vec![];
|
||||
pub static mut QUEUE: Vec<Notification> = vec![];
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Notification<'a> {
|
||||
header: &'a str,
|
||||
message: &'a str,
|
||||
#[derive(Clone)]
|
||||
pub struct Notification {
|
||||
pub header: String,
|
||||
pub message: String,
|
||||
length: u32,
|
||||
color: ResColor
|
||||
pub color: ResColor
|
||||
}
|
||||
|
||||
impl<'a> Notification<'a> {
|
||||
pub fn new(header: &'a str, message: &'a str, length: u32, color: ResColor) -> Notification<'a> {
|
||||
impl Notification {
|
||||
pub fn new(header: String, message: String, length: u32, color: ResColor) -> Notification {
|
||||
Notification {
|
||||
header,
|
||||
message,
|
||||
|
@ -28,21 +28,9 @@ impl<'a> Notification<'a> {
|
|||
self.length -= 1;
|
||||
false
|
||||
}
|
||||
|
||||
pub fn header(self) -> &'a str {
|
||||
self.header
|
||||
}
|
||||
|
||||
pub fn message(self) -> &'a str {
|
||||
self.message
|
||||
}
|
||||
|
||||
pub fn color(self) -> ResColor {
|
||||
self.color
|
||||
}
|
||||
}
|
||||
|
||||
pub fn notification(header: &'static str, message: &'static str, len: u32) {
|
||||
pub fn notification(header: String, message: String, len: u32) {
|
||||
unsafe {
|
||||
let queue = &mut QUEUE;
|
||||
queue.push(Notification::new(header, message, len, ResColor {
|
||||
|
@ -54,7 +42,7 @@ pub fn notification(header: &'static str, message: &'static str, len: u32) {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn color_notification(header: &'static str, message: &'static str, len: u32, color: ResColor) {
|
||||
pub fn color_notification(header: String, message: String, len: u32, color: ResColor) {
|
||||
unsafe {
|
||||
let queue = &mut QUEUE;
|
||||
queue.push(Notification::new(header, message, len, color));
|
||||
|
|
Loading…
Add table
Reference in a new issue