1
0
mirror of https://github.com/jugeeya/UltimateTrainingModpack.git synced 2026-01-16 15:30:24 +00:00
Files
UltimateTrainingModpack/training_mod_consts/src/lib.rs
jugeeya e981a0bfd0 Move files to sd:/ultimate/TrainingModpack (#480)
* Initial

* Move filepaths

* Small fix

* Notification on save state save
2023-02-13 19:58:22 -08:00

590 lines
18 KiB
Rust

#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate bitflags_serde_shim;
#[macro_use]
extern crate num_derive;
use serde::{Deserialize, Serialize};
pub mod options;
pub use options::*;
pub mod files;
pub use files::*;
#[repr(C)]
#[derive(Clone, Copy, Serialize, Deserialize, Debug)]
pub struct TrainingModpackMenu {
pub aerial_delay: Delay,
pub air_dodge_dir: Direction,
pub attack_angle: AttackAngle,
pub buff_state: BuffOption,
pub character_item: CharacterItem,
pub clatter_strength: ClatterFrequency,
pub crouch: OnOff,
pub di_state: Direction,
pub falling_aerials: BoolFlag,
pub fast_fall_delay: Delay,
pub fast_fall: BoolFlag,
pub follow_up: Action,
pub frame_advantage: OnOff,
pub full_hop: BoolFlag,
pub hitbox_vis: OnOff,
pub hud: OnOff,
pub input_delay: Delay,
pub ledge_delay: LongDelay,
pub ledge_state: LedgeOption,
pub mash_state: Action,
pub mash_triggers: MashTrigger,
pub miss_tech_state: MissTechFlags,
pub oos_offset: Delay,
pub pummel_delay: MedDelay,
pub reaction_time: Delay,
pub save_damage_cpu: SaveDamage,
pub save_damage_limits_cpu: DamagePercent,
pub save_damage_player: SaveDamage,
pub save_damage_limits_player: DamagePercent,
pub save_state_autoload: OnOff,
pub save_state_enable: OnOff,
pub save_state_mirroring: SaveStateMirroring,
pub sdi_state: Direction,
pub sdi_strength: SdiFrequency,
pub shield_state: Shield,
pub shield_tilt: Direction,
pub stage_hazards: OnOff,
pub tech_state: TechFlags,
pub throw_delay: MedDelay,
pub throw_state: ThrowOption,
}
#[repr(C)]
#[derive(Debug, Serialize, Deserialize)]
pub struct MenuJsonStruct {
pub menu: TrainingModpackMenu,
pub defaults_menu: TrainingModpackMenu,
// pub last_focused_submenu: &str
}
// Fighter Ids
#[repr(i32)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FighterId {
Player = 0,
CPU = 1,
}
#[derive(Clone)]
pub enum SubMenuType {
TOGGLE,
SLIDER,
}
impl SubMenuType {
pub fn from_str(s: &str) -> SubMenuType {
match s {
"toggle" => SubMenuType::TOGGLE,
"slider" => SubMenuType::SLIDER,
_ => panic!("Unexpected SubMenuType!"),
}
}
}
pub static DEFAULTS_MENU: TrainingModpackMenu = TrainingModpackMenu {
aerial_delay: Delay::empty(),
air_dodge_dir: Direction::empty(),
attack_angle: AttackAngle::empty(),
buff_state: BuffOption::empty(),
character_item: CharacterItem::None,
clatter_strength: ClatterFrequency::None,
crouch: OnOff::Off,
di_state: Direction::empty(),
falling_aerials: BoolFlag::FALSE,
fast_fall_delay: Delay::empty(),
fast_fall: BoolFlag::FALSE,
follow_up: Action::empty(),
frame_advantage: OnOff::Off,
full_hop: BoolFlag::TRUE,
hitbox_vis: OnOff::On,
hud: OnOff::On,
input_delay: Delay::D0,
ledge_delay: LongDelay::empty(),
ledge_state: LedgeOption::default(),
mash_state: Action::empty(),
mash_triggers: MashTrigger::default(),
miss_tech_state: MissTechFlags::all(),
oos_offset: Delay::empty(),
pummel_delay: MedDelay::empty(),
reaction_time: Delay::empty(),
save_damage_cpu: SaveDamage::DEFAULT,
save_damage_limits_cpu: DamagePercent::default(),
save_damage_player: SaveDamage::DEFAULT,
save_damage_limits_player: DamagePercent::default(),
save_state_autoload: OnOff::Off,
save_state_enable: OnOff::On,
save_state_mirroring: SaveStateMirroring::None,
sdi_state: Direction::empty(),
sdi_strength: SdiFrequency::None,
shield_state: Shield::None,
shield_tilt: Direction::empty(),
stage_hazards: OnOff::Off,
tech_state: TechFlags::all(),
throw_delay: MedDelay::empty(),
throw_state: ThrowOption::NONE,
};
pub static mut MENU: TrainingModpackMenu = DEFAULTS_MENU;
#[derive(Clone, Serialize)]
pub struct Slider {
pub selected_min: u32,
pub selected_max: u32,
pub abs_min: u32,
pub abs_max: u32,
}
#[derive(Clone, Serialize)]
pub struct Toggle<'a> {
pub toggle_value: u32,
pub toggle_title: &'a str,
pub checked: bool,
}
#[derive(Clone, Serialize)]
pub struct SubMenu<'a> {
pub submenu_title: &'a str,
pub submenu_id: &'a str,
pub help_text: &'a str,
pub is_single_option: bool,
pub toggles: Vec<Toggle<'a>>,
pub slider: Option<Slider>,
pub _type: &'a str,
}
impl<'a> SubMenu<'a> {
pub fn add_toggle(&mut self, toggle_value: u32, toggle_title: &'a str, checked: bool) {
self.toggles.push(Toggle {
toggle_value,
toggle_title,
checked,
});
}
pub fn new_with_toggles<T: ToggleTrait>(
submenu_title: &'a str,
submenu_id: &'a str,
help_text: &'a str,
is_single_option: bool,
initial_value: &u32,
) -> SubMenu<'a> {
let mut instance = SubMenu {
submenu_title: submenu_title,
submenu_id: submenu_id,
help_text: help_text,
is_single_option: is_single_option,
toggles: Vec::new(),
slider: None,
_type: "toggle",
};
let values = T::to_toggle_vals();
let titles = T::to_toggle_strs();
for i in 0..values.len() {
let checked: bool =
(values[i] & initial_value) > 0 || (!values[i] == 0 && initial_value == &0);
instance.add_toggle(values[i], titles[i], checked);
}
// Select the first option if there's nothing selected atm but it's a single option submenu
if is_single_option && instance.toggles.iter().all(|t| !t.checked) {
instance.toggles[0].checked = true;
}
instance
}
pub fn new_with_slider<S: SliderTrait>(
submenu_title: &'a str,
submenu_id: &'a str,
help_text: &'a str,
initial_lower_value: &u32,
initial_upper_value: &u32,
) -> SubMenu<'a> {
let min_max = S::get_limits();
SubMenu {
submenu_title: submenu_title,
submenu_id: submenu_id,
help_text: help_text,
is_single_option: false,
toggles: Vec::new(),
slider: Some(Slider {
selected_min: *initial_lower_value,
selected_max: *initial_upper_value,
abs_min: min_max.0,
abs_max: min_max.1,
}),
_type: "slider",
}
}
}
#[derive(Serialize, Clone)]
pub struct Tab<'a> {
pub tab_id: &'a str,
pub tab_title: &'a str,
pub tab_submenus: Vec<SubMenu<'a>>,
}
impl<'a> Tab<'a> {
pub fn add_submenu_with_toggles<T: ToggleTrait>(
&mut self,
submenu_title: &'a str,
submenu_id: &'a str,
help_text: &'a str,
is_single_option: bool,
initial_value: &u32,
) {
self.tab_submenus.push(SubMenu::new_with_toggles::<T>(
submenu_title,
submenu_id,
help_text,
is_single_option,
initial_value,
));
}
pub fn add_submenu_with_slider<S: SliderTrait>(
&mut self,
submenu_title: &'a str,
submenu_id: &'a str,
help_text: &'a str,
initial_lower_value: &u32,
initial_upper_value: &u32,
) {
self.tab_submenus.push(SubMenu::new_with_slider::<S>(
submenu_title,
submenu_id,
help_text,
initial_lower_value,
initial_upper_value,
))
}
}
#[derive(Serialize, Clone)]
pub struct UiMenu<'a> {
pub tabs: Vec<Tab<'a>>,
}
pub unsafe fn ui_menu(menu: TrainingModpackMenu) -> UiMenu<'static> {
let mut overall_menu = UiMenu { tabs: Vec::new() };
let mut mash_tab = Tab {
tab_id: "mash",
tab_title: "Mash Settings",
tab_submenus: Vec::new(),
};
mash_tab.add_submenu_with_toggles::<Action>(
"Mash Toggles",
"mash_state",
"Mash Toggles: Actions to be performed as soon as possible",
false,
&(menu.mash_state.bits()),
);
mash_tab.add_submenu_with_toggles::<Action>(
"Followup Toggles",
"follow_up",
"Followup Toggles: Actions to be performed after the Mash option",
false,
&(menu.follow_up.bits()),
);
mash_tab.add_submenu_with_toggles::<MashTrigger>(
"Mash Triggers",
"mash_triggers",
"Mash triggers: When the Mash Option will be performed",
false,
&(menu.mash_triggers.bits()),
);
mash_tab.add_submenu_with_toggles::<AttackAngle>(
"Attack Angle",
"attack_angle",
"Attack Angle: For attacks that can be angled, such as some forward tilts",
false,
&(menu.attack_angle.bits()),
);
mash_tab.add_submenu_with_toggles::<ThrowOption>(
"Throw Options",
"throw_state",
"Throw Options: Throw to be performed when a grab is landed",
false,
&(menu.throw_state.bits()),
);
mash_tab.add_submenu_with_toggles::<MedDelay>(
"Throw Delay",
"throw_delay",
"Throw Delay: How many frames to delay the throw option",
false,
&(menu.throw_delay.bits()),
);
mash_tab.add_submenu_with_toggles::<MedDelay>(
"Pummel Delay",
"pummel_delay",
"Pummel Delay: How many frames after a grab to wait before starting to pummel",
false,
&(menu.pummel_delay.bits()),
);
mash_tab.add_submenu_with_toggles::<BoolFlag>(
"Falling Aerials",
"falling_aerials",
"Falling Aerials: Should aerials be performed when rising or when falling",
false,
&(menu.falling_aerials.bits()),
);
mash_tab.add_submenu_with_toggles::<BoolFlag>(
"Full Hop",
"full_hop",
"Full Hop: Should the CPU perform a full hop or a short hop",
false,
&(menu.full_hop.bits()),
);
mash_tab.add_submenu_with_toggles::<Delay>(
"Aerial Delay",
"aerial_delay",
"Aerial Delay: How long to delay a Mash aerial attack",
false,
&(menu.aerial_delay.bits()),
);
mash_tab.add_submenu_with_toggles::<BoolFlag>(
"Fast Fall",
"fast_fall",
"Fast Fall: Should the CPU fastfall during a jump",
false,
&(menu.fast_fall.bits()),
);
mash_tab.add_submenu_with_toggles::<Delay>(
"Fast Fall Delay",
"fast_fall_delay",
"Fast Fall Delay: How many frames the CPU should delay their fastfall",
false,
&(menu.fast_fall_delay.bits()),
);
mash_tab.add_submenu_with_toggles::<Delay>(
"OoS Offset",
"oos_offset",
"OoS Offset: How many times the CPU shield can be hit before performing a Mash option",
false,
&(menu.oos_offset.bits()),
);
mash_tab.add_submenu_with_toggles::<Delay>(
"Reaction Time",
"reaction_time",
"Reaction Time: How many frames to delay before performing a mash option",
false,
&(menu.reaction_time.bits()),
);
overall_menu.tabs.push(mash_tab);
let mut defensive_tab = Tab {
tab_id: "defensive",
tab_title: "Defensive Settings",
tab_submenus: Vec::new(),
};
defensive_tab.add_submenu_with_toggles::<Direction>(
"Airdodge Direction",
"air_dodge_dir",
"Airdodge Direction: Direction to angle airdodges",
false,
&(menu.air_dodge_dir.bits()),
);
defensive_tab.add_submenu_with_toggles::<Direction>(
"DI Direction",
"di_state",
"DI Direction: Direction to angle the directional influence during hitlag",
false,
&(menu.di_state.bits()),
);
defensive_tab.add_submenu_with_toggles::<Direction>(
"SDI Direction",
"sdi_state",
"SDI Direction: Direction to angle the smash directional influence during hitlag",
false,
&(menu.sdi_state.bits()),
);
defensive_tab.add_submenu_with_toggles::<SdiFrequency>(
"SDI Strength",
"sdi_strength",
"SDI Strength: Relative strength of the smash directional influence inputs",
true,
&(menu.sdi_strength as u32),
);
defensive_tab.add_submenu_with_toggles::<ClatterFrequency>(
"Clatter Strength",
"clatter_strength",
"Clatter Strength: Relative strength of the mashing out of grabs, buries, etc.",
true,
&(menu.clatter_strength as u32),
);
defensive_tab.add_submenu_with_toggles::<LedgeOption>(
"Ledge Options",
"ledge_state",
"Ledge Options: Actions to be taken when on the ledge",
false,
&(menu.ledge_state.bits()),
);
defensive_tab.add_submenu_with_toggles::<LongDelay>(
"Ledge Delay",
"ledge_delay",
"Ledge Delay: How many frames to delay the ledge option",
false,
&(menu.ledge_delay.bits()),
);
defensive_tab.add_submenu_with_toggles::<TechFlags>(
"Tech Options",
"tech_state",
"Tech Options: Actions to take when slammed into a hard surface",
false,
&(menu.tech_state.bits()),
);
defensive_tab.add_submenu_with_toggles::<MissTechFlags>(
"Mistech Options",
"miss_tech_state",
"Mistech Options: Actions to take after missing a tech",
false,
&(menu.miss_tech_state.bits()),
);
defensive_tab.add_submenu_with_toggles::<Shield>(
"Shield Toggles",
"shield_state",
"Shield Toggles: CPU Shield Behavior",
true,
&(menu.shield_state as u32),
);
defensive_tab.add_submenu_with_toggles::<Direction>(
"Shield Tilt",
"shield_tilt",
"Shield Tilt: Direction to tilt the shield",
false, // TODO: Should this be true?
&(menu.shield_tilt.bits()),
);
defensive_tab.add_submenu_with_toggles::<OnOff>(
"Crouch",
"crouch",
"Crouch: Should the CPU crouch when on the ground",
true,
&(menu.crouch as u32),
);
overall_menu.tabs.push(defensive_tab);
let mut save_state_tab = Tab {
tab_id: "save_state",
tab_title: "Save States",
tab_submenus: Vec::new(),
};
save_state_tab.add_submenu_with_toggles::<SaveStateMirroring>(
"Mirroring",
"save_state_mirroring",
"Mirroring: Flips save states in the left-right direction across the stage center",
true,
&(menu.save_state_mirroring as u32),
);
save_state_tab.add_submenu_with_toggles::<OnOff>(
"Auto Save States",
"save_state_autoload",
"Auto Save States: Load save state when any fighter dies",
true,
&(menu.save_state_autoload as u32),
);
save_state_tab.add_submenu_with_toggles::<SaveDamage>(
"Save Dmg (CPU)",
"save_damage_cpu",
"Save Damage: Should save states retain CPU damage",
true,
&(menu.save_damage_cpu.bits()),
);
save_state_tab.add_submenu_with_slider::<DamagePercent>(
"Dmg Range (CPU)",
"save_damage_limits_cpu",
"Limits on random damage to apply to the CPU when loading a save state",
&(menu.save_damage_limits_cpu.0 as u32),
&(menu.save_damage_limits_cpu.1 as u32),
);
save_state_tab.add_submenu_with_toggles::<SaveDamage>(
"Save Dmg (Player)",
"save_damage_player",
"Save Damage: Should save states retain player damage",
true,
&(menu.save_damage_player.bits() as u32),
);
save_state_tab.add_submenu_with_slider::<DamagePercent>(
"Dmg Range (Player)",
"save_damage_limits_player",
"Limits on random damage to apply to the player when loading a save state",
&(menu.save_damage_limits_player.0 as u32),
&(menu.save_damage_limits_player.1 as u32),
);
save_state_tab.add_submenu_with_toggles::<OnOff>(
"Enable Save States",
"save_state_enable",
"Save States: Enable save states! Save a state with Grab+Down Taunt, load it with Grab+Up Taunt.",
true,
&(menu.save_state_enable as u32),
);
save_state_tab.add_submenu_with_toggles::<CharacterItem>(
"Character Item",
"character_item",
"Character Item: CPU/Player item to hold when loading a save state",
true,
&(menu.character_item as u32),
);
save_state_tab.add_submenu_with_toggles::<BuffOption>(
"Buff Options",
"buff_state",
"Buff Options: Buff(s) to be applied to respective character when loading save states",
false,
&(menu.buff_state.bits()),
);
overall_menu.tabs.push(save_state_tab);
let mut misc_tab = Tab {
tab_id: "misc",
tab_title: "Misc Settings",
tab_submenus: Vec::new(),
};
misc_tab.add_submenu_with_toggles::<OnOff>(
"Frame Advantage",
"frame_advantage",
"Frame Advantage: Display the time difference between when the player is actionable and the CPU is actionable",
true,
&(menu.frame_advantage as u32),
);
misc_tab.add_submenu_with_toggles::<OnOff>(
"Hitbox Visualization",
"hitbox_vis",
"Hitbox Visualization: Should hitboxes be displayed, hiding other visual effects",
true,
&(menu.hitbox_vis as u32),
);
misc_tab.add_submenu_with_toggles::<Delay>(
"Input Delay",
"input_delay",
"Input Delay: Frames to delay player inputs by",
true,
&(menu.input_delay.bits()),
);
misc_tab.add_submenu_with_toggles::<OnOff>(
"Stage Hazards",
"stage_hazards",
"Stage Hazards: Should stage hazards be present",
true,
&(menu.stage_hazards as u32),
);
misc_tab.add_submenu_with_toggles::<OnOff>(
"HUD",
"hud",
"HUD: Turn UI on or off",
true,
&(menu.hud as u32),
);
overall_menu.tabs.push(misc_tab);
overall_menu
}