1
0
Fork 0
mirror of https://github.com/jugeeya/UltimateTrainingModpack.git synced 2025-03-16 11:26:11 +00:00

Add Ledge/Aerial Delay Options (#147)

* Fix Multi Followups

* Add Aerial Delay Toggle

* Add Ledge Delay Toggle

* Add More Delay Options

* Add More Delay Options

* Add Dash Toggle

* Version +
This commit is contained in:
sidschingis 2020-08-24 22:57:22 +02:00 committed by GitHub
parent 22e2852df7
commit 7d153da81c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 185 additions and 63 deletions

View file

@ -38,7 +38,7 @@ include $(DEVKITPRO)/libnx/switch_rules
# NACP building is skipped as well.
#---------------------------------------------------------------------------------
APP_TITLE := Training Modpack
APP_VERSION := 2.5
APP_VERSION := 2.5.1Beta
TARGET := ovlTrainingModpack
BUILD := build

View file

@ -97,6 +97,9 @@ CPUs will also perform a defensive
option after getting up.
)"""";
const std::string ledge_delay_help = R""""(
Frames to delay ledge option.)"""";
// Tech Option
// clang-format off
@ -161,7 +164,7 @@ of hitstun or out of specific states.
x(type,NeutralB,"Neutral B") x(type,SideB,"Side B") x(type,UpB,"Up B") x(type,DownB,"Down B") \
x(type,FSmash,"Forward Smash") x(type,USmash,"Up Smash") x(type,DSmash,"Down Smash") \
x(type,Jab,"Jab") x(type,FTilt,"Ftilt") x(type,UTilt,"Utilt") x(type,Dtilt,"Dtilt") \
x(type,Grab,"Grab") //x(type,DashAttack,"Dash Attack")
x(type,Grab,"Grab") x(type,Dash,"Dash") //x(type,DashAttack,"Dash Attack")
// clang-format on
DEFINE_ENUM_CLASS(ActionFlag);
@ -258,7 +261,9 @@ out of specific states.)"""";
x(type,D1,"1") x(type,D2,"2") x(type,D3,"3") x(type,D4,"4") x(type,D5,"5") \
x(type,D6,"6") x(type,D7,"7") x(type,D8,"8") x(type,D9,"9") x(type,D10,"10") \
x(type,D11,"11") x(type,D12,"12") x(type,D13,"13") x(type,D14,"14") x(type,D15,"15") \
x(type,D16,"16") x(type,D17,"17") x(type,D18,"18") x(type,D19,"19") x(type,D20,"20")
x(type,D16,"16") x(type,D17,"17") x(type,D18,"18") x(type,D19,"19") x(type,D20,"20") \
x(type,D21,"21") x(type,D22,"22") x(type,D23,"23") x(type,D24,"24") x(type,D25,"25") \
x(type,D26,"26") x(type,D27,"27") x(type,D28,"28") x(type,D29,"29") x(type,D30,"30") \
// clang-format on
DEFINE_ENUM_CLASS(DelayFlag);
@ -282,6 +287,9 @@ CPUs will only begin
aerials at the apex of
their jump.)"""";
const std::string aerial_delay_help = R""""(
Frames to delay CPU Aerial.)"""";
const std::string full_hop_help = R""""(
CPUs will full hop
rather than short hop

View file

@ -16,6 +16,7 @@ static struct TrainingModpackMenu
ActionFlags MASH_STATE = ActionFlags::None;
ActionFlags FOLLOW_UP = ActionFlags::None;
LedgeFlags LEDGE_STATE = LedgeFlags::All;
DelayFlags LEDGE_DELAY = DelayFlags::All;
TechFlags TECH_STATE = TechFlags::All;
int SHIELD_STATE = NONE;
DefensiveFlags DEFENSIVE_STATE = DefensiveFlags::All;
@ -25,6 +26,7 @@ static struct TrainingModpackMenu
BoolFlags FAST_FALL = BoolFlags::None;
DelayFlags FAST_FALL_DELAY = DelayFlags::None;
BoolFlags FALLING_AERIALS = BoolFlags::None;
DelayFlags AERIAL_DELAY = DelayFlags::None;
BoolFlags FULL_HOP = BoolFlags::None;
} menu;
@ -275,7 +277,8 @@ public:
namespace
{
template<typename T> tsl::elm::ListItem* createBitFlagOption(T* option, const std::string& name, const std::string& help, GuiMain* guiMain)
template<typename T>
tsl::elm::ListItem* createBitFlagOption(T* option, const std::string& name, const std::string& help, GuiMain* guiMain)
{
using FlagType = typename T::Type;
@ -283,29 +286,31 @@ template<typename T> tsl::elm::ListItem* createBitFlagOption(T* option, const st
item->setClickListener([name, help, option, guiMain](u64 keys) -> bool {
if(keys & KEY_A)
{
tsl::changeTo<GuiLambda>([option, name, help]() -> tsl::elm::Element* {
auto toggleList = new OverflowList();
std::vector<tsl::elm::ToggleListItem*> items;
for(auto& [flag, str] : detail::EnumArray<FlagType>::values)
{
items.emplace_back(new BitFlagToggleListItem<FlagType>(str, flag, option, name, help));
}
tsl::changeTo<GuiLambda>(
[option, name, help]() -> tsl::elm::Element* {
auto toggleList = new OverflowList();
std::vector<tsl::elm::ToggleListItem*> items;
for(auto& [flag, str] : detail::EnumArray<FlagType>::values)
{
items.emplace_back(new BitFlagToggleListItem<FlagType>(str, flag, option, name, help));
}
auto allOff = new SetToggleListItem({}, items, "None", name, help);
auto allOn = new SetToggleListItem(items, {}, "All", name, help);
auto allOff = new SetToggleListItem({}, items, "None", name, help);
auto allOn = new SetToggleListItem(items, {}, "All", name, help);
toggleList->addItem(allOn);
toggleList->addItem(allOff);
toggleList->addItem(allOn);
toggleList->addItem(allOff);
for(auto it : items)
{
toggleList->addItem(it);
}
for(auto it : items)
{
toggleList->addItem(it);
}
auto frame = new OverlayFrameWithHelp(name, "Press \uE0E3 for help with these options.");
frame->setContent(toggleList);
return frame;
}, guiMain);
auto frame = new OverlayFrameWithHelp(name, "Press \uE0E3 for help with these options.");
frame->setContent(toggleList);
return frame;
},
guiMain);
return true;
}
if(keys & KEY_Y)
@ -376,7 +381,8 @@ tsl::elm::Element* GuiMain::createUI()
list->addItem(createBitFlagOption(&menu.MASH_STATE, "Mash Toggles", mash_help, this));
list->addItem(createBitFlagOption(&menu.FOLLOW_UP, "Followup Toggles", follow_up_help, this));
list->addItem(new BitFlagToggleListItem<OnOffFlags::Type>("Mash In Neutral", OnOffFlag::On, &menu.MASH_IN_NEUTRAL, "Mash In Neutral", mash_neutral_help));
list->addItem(new BitFlagToggleListItem<OnOffFlags::Type>(
"Mash In Neutral", OnOffFlag::On, &menu.MASH_IN_NEUTRAL, "Mash In Neutral", mash_neutral_help));
list->addItem(new tsl::elm::CategoryHeader("Left Stick", true));
@ -392,12 +398,12 @@ tsl::elm::Element* GuiMain::createUI()
valueListItems.push_back(shieldItem);
ClickableListItem* frameAdvantageItem = new ClickableListItem("Frame Advantage",
frame_advantage_items,
nullptr,
"frameAdvantage",
0,
"Frame Advantage",
frame_advantage_help);
frame_advantage_items,
nullptr,
"frameAdvantage",
0,
"Frame Advantage",
frame_advantage_help);
frameAdvantageItem->setClickListener([](std::vector<std::string> values,
int* curValue,
std::string extdata,
@ -414,6 +420,7 @@ tsl::elm::Element* GuiMain::createUI()
list->addItem(new tsl::elm::CategoryHeader("Chase", true));
list->addItem(createBitFlagOption(&menu.LEDGE_STATE, "Ledge Options", ledge_help, this));
list->addItem(createBitFlagOption(&menu.LEDGE_DELAY, "Ledge Delay", ledge_delay_help, this));
list->addItem(createBitFlagOption(&menu.TECH_STATE, "Tech Options", tech_help, this));
list->addItem(createBitFlagOption(&menu.DEFENSIVE_STATE, "Defensive Options", defensive_help, this));
@ -422,14 +429,16 @@ tsl::elm::Element* GuiMain::createUI()
list->addItem(createBitFlagOption(&menu.FAST_FALL, "Fast Fall", fast_fall_help, this));
list->addItem(createBitFlagOption(&menu.FAST_FALL_DELAY, "Fast Fall Delay", fast_fall_delay_help, this));
list->addItem(createBitFlagOption(&menu.FALLING_AERIALS, "Falling Aerials", falling_aerials_help, this));
list->addItem(createBitFlagOption(&menu.AERIAL_DELAY, "Aerial Delay", aerial_delay_help, this));
list->addItem(createBitFlagOption(&menu.FULL_HOP, "Full Hop", full_hop_help, this));
list->addItem(new tsl::elm::CategoryHeader("Miscellaneous", true));
list->addItem(new BitFlagToggleListItem<OnOffFlags::Type>("Hitbox Visualization", OnOffFlag::On, &menu.HITBOX_VIS, "Hitbox Visualization", hitbox_help));
list->addItem(new BitFlagToggleListItem<OnOffFlags::Type>(
"Hitbox Visualization", OnOffFlag::On, &menu.HITBOX_VIS, "Hitbox Visualization", hitbox_help));
ClickableListItem* saveStateItem = new ClickableListItem(
"Save States", empty_items, nullptr, "saveStates", 0, "Save States", save_states_help);
ClickableListItem* saveStateItem =
new ClickableListItem("Save States", empty_items, nullptr, "saveStates", 0, "Save States", save_states_help);
saveStateItem->setClickListener([](std::vector<std::string> values,
int* curValue,
std::string extdata,
@ -439,20 +448,15 @@ tsl::elm::Element* GuiMain::createUI()
saveStateItem->setHelpListener([](std::string title, std::string help) { tsl::changeTo<GuiHelp>(title, help); });
list->addItem(saveStateItem);
ClickableListItem* resetMenuItem = new ClickableListItem("Reset Menu",
empty_items,
nullptr,
"resetMenu",
0,
"Reset Menu",
reset_menu_help);
ClickableListItem* resetMenuItem =
new ClickableListItem("Reset Menu", empty_items, nullptr, "resetMenu", 0, "Reset Menu", reset_menu_help);
resetMenuItem->setClickListener([](std::vector<std::string> values,
int* curValue,
std::string extdata,
int index,
std::string title,
std::string help) {
menu = defaultMenu;
int* curValue,
std::string extdata,
int index,
std::string title,
std::string help) {
menu = defaultMenu;
/* Open Sd card filesystem. */
FsFileSystem fsSdmc;
@ -463,8 +467,7 @@ tsl::elm::Element* GuiMain::createUI()
tsl::goBack();
});
resetMenuItem->setHelpListener(
[](std::string title, std::string help) { tsl::changeTo<GuiHelp>(title, help); });
resetMenuItem->setHelpListener([](std::string title, std::string help) { tsl::changeTo<GuiHelp>(title, help); });
list->addItem(resetMenuItem);
rootFrame->setContent(list);

View file

@ -211,6 +211,7 @@ bitflags! {
const GRAB = 0x400000;
// TODO: Make work
// const DASH_ATTACK = 0x400000;
const DASH = 0x800000;
}
}
@ -251,7 +252,17 @@ bitflags! {
const D17 = 0x20000;
const D18 = 0x40000;
const D19 = 0x80000;
const D20 = 0x100000;
const D20 = 0x100000;
const D21 = 0x200000;
const D22 = 0x400000;
const D23 = 0x800000;
const D24 = 0x1000000;
const D25 = 0x2000000;
const D26 = 0x4000000;
const D27 = 0x8000000;
const D28 = 0x10000000;
const D29 = 0x20000000;
const D30 = 0x40000000;
}
}
@ -289,6 +300,7 @@ pub struct TrainingModpackMenu {
pub mash_state: Action,
pub follow_up: Action,
pub ledge_state: LedgeOption,
pub ledge_delay: Delay,
pub tech_state: TechFlags,
pub shield_state: Shield,
pub defensive_state: Defensive,
@ -298,6 +310,7 @@ pub struct TrainingModpackMenu {
pub fast_fall: BoolFlag,
pub fast_fall_delay: Delay,
pub falling_aerials: BoolFlag,
pub aerial_delay: Delay,
pub full_hop: BoolFlag,
}

View file

@ -13,6 +13,7 @@ pub static mut MENU_STRUCT: consts::TrainingModpackMenu = consts::TrainingModpac
mash_state: Action::empty(),
follow_up: Action::empty(),
ledge_state: LedgeOption::all(),
ledge_delay: Delay::empty(),
tech_state: TechFlags::all(),
shield_state: Shield::None,
defensive_state: Defensive::all(),
@ -22,6 +23,7 @@ pub static mut MENU_STRUCT: consts::TrainingModpackMenu = consts::TrainingModpac
fast_fall: BoolFlag::empty(),
fast_fall_delay: Delay::empty(),
falling_aerials: BoolFlag::empty(),
aerial_delay: Delay::empty(),
full_hop: BoolFlag::empty(),
};

View file

@ -1,14 +1,43 @@
use crate::common::consts::*;
use crate::common::*;
use crate::training::frame_counter;
use crate::training::mash;
use smash::app::{self, lua_bind::*};
use smash::lib::lua_const::*;
const NOT_SET :u32 = 9001;
static mut LEDGE_DELAY: u32 = NOT_SET;
static mut LEDGE_DELAY_COUNTER: usize = 0;
pub fn init() {
unsafe {
LEDGE_DELAY_COUNTER = frame_counter::register_counter();
}
}
pub fn reset_ledge_delay(){
unsafe{
LEDGE_DELAY = NOT_SET;
}
}
fn roll_ledge_delay(){
unsafe{
if LEDGE_DELAY != NOT_SET {
return;
}
LEDGE_DELAY = MENU.ledge_delay.get_random().to_index();
}
}
pub unsafe fn force_option(module_accessor: &mut app::BattleObjectModuleAccessor) {
if StatusModule::status_kind(module_accessor) as i32 != *FIGHTER_STATUS_KIND_CLIFF_WAIT {
return;
}
roll_ledge_delay();
if !WorkModule::is_enable_transition_term(
module_accessor,
*FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_CLIFF_CLIMB,
@ -16,19 +45,14 @@ pub unsafe fn force_option(module_accessor: &mut app::BattleObjectModuleAccessor
return;
}
let random_frame = get_random_int(MotionModule::end_frame(module_accessor) as i32) as f32;
let frame = MotionModule::frame(module_accessor) as f32;
if !(frame == random_frame || frame > 30.0) {
if frame_counter::should_delay(LEDGE_DELAY, LEDGE_DELAY_COUNTER) {
return;
}
let mut status = 0;
let ledge_case: LedgeOption = MENU.ledge_state.get_random();
reset_ledge_delay();
if let Some(new_status) = ledge_case.into_status() {
status = new_status;
}
let ledge_case: LedgeOption = MENU.ledge_state.get_random();
let status = ledge_case.into_status().unwrap_or(0);
match ledge_case {
LedgeOption::JUMP => {
@ -42,8 +66,13 @@ pub unsafe fn force_option(module_accessor: &mut app::BattleObjectModuleAccessor
pub unsafe fn get_command_flag_cat(
module_accessor: &mut app::BattleObjectModuleAccessor,
_category: i32,
category: i32,
) {
// Only do once per frame
if category != FIGHTER_PAD_COMMAND_CATEGORY1 {
return;
}
if !is_training_mode() {
return;
}
@ -57,4 +86,4 @@ pub unsafe fn get_command_flag_cat(
}
force_option(module_accessor);
}
}

View file

@ -2,6 +2,7 @@ use crate::common::consts::*;
use crate::common::*;
use crate::training::character_specific;
use crate::training::fast_fall;
use crate::training::frame_counter;
use crate::training::full_hop;
use crate::training::sdi;
use crate::training::shield;
@ -13,6 +14,9 @@ static mut QUEUE: Vec<Action> = vec![];
static mut FALLING_AERIAL: bool = false;
static mut AERIAL_DELAY_COUNTER: usize = 0;
static mut AERIAL_DELAY: u32 = 0;
pub fn buffer_action(action: Action) {
unsafe {
if QUEUE.len() > 0 {
@ -24,6 +28,8 @@ pub fn buffer_action(action: Action) {
return;
}
roll_aerial_delay(action);
unsafe {
QUEUE.insert(0, action);
buffer_follow_up();
@ -34,13 +40,15 @@ pub fn buffer_follow_up() {
let action;
unsafe {
action = MENU.follow_up;
action = MENU.follow_up.get_random();
}
if action == Action::empty() {
return;
}
roll_aerial_delay(action);
unsafe {
QUEUE.insert(0, action);
}
@ -62,10 +70,15 @@ fn reset() {
}
shield::suspend_shield(get_current_buffer());
unsafe {
frame_counter::full_reset(AERIAL_DELAY_COUNTER);
AERIAL_DELAY = 0;
}
}
pub fn full_reset(){
unsafe{
pub fn full_reset() {
unsafe {
while QUEUE.len() > 0 {
reset();
}
@ -246,6 +259,18 @@ unsafe fn perform_action(module_accessor: &mut app::BattleObjectModuleAccessor)
*FIGHTER_PAD_CMD_CAT1_FLAG_AIR_ESCAPE,
);
}
Action::DASH => {
let dash_transition = *FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_DASH;
let dash_status = *FIGHTER_STATUS_KIND_DASH;
try_change_status(module_accessor, dash_status, dash_transition);
return get_flag(
module_accessor,
*FIGHTER_STATUS_KIND_DASH,
0,
);
}
_ => return get_attack_flag(module_accessor, action),
}
}
@ -395,6 +420,10 @@ unsafe fn get_aerial_flag(
return flag;
}
if should_delay_aerial(module_accessor) {
return flag;
}
/*
* We always trigger attack and change it later into the correct aerial
* @see get_attack_air_kind()
@ -413,6 +442,42 @@ unsafe fn get_aerial_flag(
return flag;
}
pub fn init() {
unsafe {
AERIAL_DELAY_COUNTER = frame_counter::register_counter();
}
}
fn roll_aerial_delay(action: Action) {
if !shield::is_aerial(action) {
return;
}
unsafe {
AERIAL_DELAY = MENU.aerial_delay.get_random().to_index();
}
}
fn should_delay_aerial(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
unsafe {
if AERIAL_DELAY == 0 {
return false;
}
if StatusModule::status_kind(module_accessor) == *FIGHTER_STATUS_KIND_ATTACK_AIR {
return false;
}
if !WorkModule::is_enable_transition_term(
module_accessor,
*FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_ATTACK_AIR,
) {
return true;
}
return frame_counter::should_delay(AERIAL_DELAY, AERIAL_DELAY_COUNTER);
}
}
/**
* Returns the flag and resets, once the action is performed
*/

View file

@ -268,6 +268,8 @@ pub fn training_mods() {
combo::init();
shield::init();
fast_fall::init();
mash::init();
ledge::init();
// // Input recorder
// SaltySD_function_replace_sym(