mirror of
https://github.com/jugeeya/UltimateTrainingModpack.git
synced 2024-11-28 04:44:06 +00:00
Save States with items (#350)
* initial * Complete refactor, add save state autoload * forgot to commit consts folder * Format Rust code using rustfmt * Refactor, attempt CPU as well * Update items.rs * Format Rust code using rustfmt * Fix web menu * Format Rust code using rustfmt * Fix crashes due to cpu kind not set * Format Rust code using rustfmt * Prevent Nana from Spawning with Items (#353) Simple check before giving items * somehow this code caused blackscreens on ryujinx? * remerge * Link and Diddy fixes, Players spawning with CPU item fixes (#355) * Format Rust code using rustfmt * Delete mash buffer queue entirely when spawning items to fix diddy as cpu; nits * fix merge * nit * Format Rust code using rustfmt Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: GradualSyrup <68757075+GradualSyrup@users.noreply.github.com>
This commit is contained in:
parent
41ecb8aa38
commit
ac78fb4a4d
9 changed files with 669 additions and 9 deletions
|
@ -1,7 +1,7 @@
|
|||
set -eu
|
||||
|
||||
# Obviously adjust these based on your paths
|
||||
RYUJINX_APPLICATION_PATH="/mnt/c/Users/Jdsam/Downloads/ryujinx-Release-1.0.0+ba3ae74-win_x64/Ryujinx.exe"
|
||||
RYUJINX_APPLICATION_PATH="/mnt/c/Users/Jdsam/Downloads/ryujinx-1.1.119-win_x64/publish/Ryujinx.exe"
|
||||
SMASH_APPLICATION_PATH="C:\Users\Jdsam\Downloads\Super Smash Bros. Ultimate (World) (En,Ja,Fr,De,Es,It,Nl,Zh-Hant,Zh-Hans,Ko,Ru)\Super Smash Bros. Ultimate (World) (En,Ja,Fr,De,Es,It,Nl,Zh-Hant,Zh-Hans,Ko,Ru).xci"
|
||||
RYUJINX_SMASH_SKYLINE_PLUGINS_PATH="/mnt/c/Users/Jdsam/AppData/Roaming/Ryujinx/mods/contents/01006a800016e000/romfs/skyline/plugins"
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ pub use crate::common::consts::MENU;
|
|||
pub static mut DEFAULTS_MENU: TrainingModpackMenu = crate::common::consts::DEFAULTS_MENU;
|
||||
pub static mut BASE_MENU: TrainingModpackMenu = unsafe { DEFAULTS_MENU };
|
||||
pub static mut FIGHTER_MANAGER_ADDR: usize = 0;
|
||||
pub static mut ITEM_MANAGER_ADDR: usize = 0;
|
||||
pub static mut STAGE_MANAGER_ADDR: usize = 0;
|
||||
|
||||
#[cfg(not(feature = "outside_training_mode"))]
|
||||
|
|
|
@ -166,7 +166,6 @@ pub fn main() {
|
|||
received_input = true;
|
||||
});
|
||||
let b_press = &mut button_presses.b;
|
||||
let b_prev_press = b_press.prev_frame_is_pressed;
|
||||
b_press.read_press().then(|| {
|
||||
received_input = true;
|
||||
if !app.outer_list {
|
||||
|
|
553
src/training/character_specific/items.rs
Normal file
553
src/training/character_specific/items.rs
Normal file
|
@ -0,0 +1,553 @@
|
|||
use crate::common::consts::*;
|
||||
use crate::common::*;
|
||||
use crate::training::mash;
|
||||
use smash::app;
|
||||
use smash::app::lua_bind::*;
|
||||
use smash::app::ItemKind;
|
||||
use smash::app::{ArticleOperationTarget, BattleObjectModuleAccessor, Item};
|
||||
use smash::cpp::l2c_value::LuaConst;
|
||||
use smash::lib::lua_const::*;
|
||||
|
||||
pub struct CharItem {
|
||||
pub fighter_kind: LuaConst,
|
||||
pub item_kind: Option<LuaConst>,
|
||||
pub article_kind: Option<LuaConst>,
|
||||
pub variation: Option<LuaConst>,
|
||||
}
|
||||
|
||||
pub const ALL_CHAR_ITEMS: [CharItem; 45] = [
|
||||
CharItem {
|
||||
fighter_kind: FIGHTER_KIND_DIDDY,
|
||||
item_kind: None,
|
||||
article_kind: Some(FIGHTER_DIDDY_GENERATE_ARTICLE_ITEM_BANANA),
|
||||
variation: None,
|
||||
},
|
||||
CharItem {
|
||||
// Robin Tome
|
||||
fighter_kind: FIGHTER_KIND_REFLET,
|
||||
item_kind: Some(ITEM_KIND_BOOK),
|
||||
article_kind: None,
|
||||
variation: None, // TODO: Look at the lua const ITEM_BOOK_STATUS_KIND_BEFORE_BORN
|
||||
},
|
||||
CharItem {
|
||||
// Banjo-Kazooie Grenade Egg
|
||||
fighter_kind: FIGHTER_KIND_BUDDY,
|
||||
item_kind: Some(ITEM_KIND_BUDDYBOMB),
|
||||
article_kind: None,
|
||||
variation: None,
|
||||
},
|
||||
CharItem {
|
||||
// Turnip
|
||||
fighter_kind: FIGHTER_KIND_DAISY,
|
||||
item_kind: None,
|
||||
article_kind: Some(FIGHTER_DAISY_GENERATE_ARTICLE_DAIKON),
|
||||
variation: Some(ITEM_VARIATION_DAISYDAIKON_1), // Smile
|
||||
},
|
||||
CharItem {
|
||||
// Turnip
|
||||
fighter_kind: FIGHTER_KIND_DAISY,
|
||||
item_kind: None,
|
||||
article_kind: Some(FIGHTER_DAISY_GENERATE_ARTICLE_DAIKON),
|
||||
variation: Some(ITEM_VARIATION_DAISYDAIKON_6), // Winky
|
||||
},
|
||||
CharItem {
|
||||
// Turnip
|
||||
fighter_kind: FIGHTER_KIND_DAISY,
|
||||
item_kind: None,
|
||||
article_kind: Some(FIGHTER_DAISY_GENERATE_ARTICLE_DAIKON),
|
||||
variation: Some(ITEM_VARIATION_DAISYDAIKON_7), // Dot-Eyes
|
||||
},
|
||||
CharItem {
|
||||
// Turnip
|
||||
fighter_kind: FIGHTER_KIND_DAISY,
|
||||
item_kind: None,
|
||||
article_kind: Some(FIGHTER_DAISY_GENERATE_ARTICLE_DAIKON),
|
||||
variation: Some(ITEM_VARIATION_DAISYDAIKON_8), // Stitch-face
|
||||
},
|
||||
CharItem {
|
||||
// Mr Saturn
|
||||
fighter_kind: FIGHTER_KIND_DAISY,
|
||||
item_kind: Some(ITEM_KIND_DOSEISAN),
|
||||
article_kind: None,
|
||||
variation: None,
|
||||
},
|
||||
CharItem {
|
||||
// Bob-omb
|
||||
fighter_kind: FIGHTER_KIND_DAISY,
|
||||
item_kind: Some(ITEM_KIND_BOMBHEI),
|
||||
article_kind: None,
|
||||
variation: Some(ITEM_VARIATION_BOMBHEI_NORMAL),
|
||||
},
|
||||
CharItem {
|
||||
fighter_kind: FIGHTER_KIND_DIDDY,
|
||||
item_kind: Some(ITEM_KIND_DIDDYPEANUTS),
|
||||
article_kind: None,
|
||||
variation: None,
|
||||
},
|
||||
CharItem {
|
||||
// Sheik Sideb Bomb
|
||||
fighter_kind: FIGHTER_KIND_SHEIK,
|
||||
item_kind: Some(ITEM_KIND_EXPLOSIONBOMB),
|
||||
article_kind: None,
|
||||
variation: None,
|
||||
},
|
||||
CharItem {
|
||||
fighter_kind: FIGHTER_KIND_KROOL,
|
||||
item_kind: Some(ITEM_KIND_KROOLCROWN),
|
||||
article_kind: None,
|
||||
variation: None,
|
||||
},
|
||||
CharItem {
|
||||
fighter_kind: FIGHTER_KIND_LINK,
|
||||
item_kind: Some(ITEM_KIND_LINKARROW),
|
||||
article_kind: None,
|
||||
variation: None,
|
||||
},
|
||||
CharItem {
|
||||
fighter_kind: FIGHTER_KIND_LINK,
|
||||
item_kind: Some(ITEM_KIND_LINKBOMB),
|
||||
article_kind: None,
|
||||
variation: None,
|
||||
},
|
||||
CharItem {
|
||||
fighter_kind: FIGHTER_KIND_KOOPAJR,
|
||||
item_kind: Some(ITEM_KIND_MECHAKOOPA),
|
||||
article_kind: None,
|
||||
variation: None,
|
||||
},
|
||||
CharItem {
|
||||
fighter_kind: FIGHTER_KIND_ROCKMAN,
|
||||
item_kind: Some(ITEM_KIND_METALBLADE),
|
||||
article_kind: None,
|
||||
variation: None,
|
||||
},
|
||||
CharItem {
|
||||
fighter_kind: FIGHTER_KIND_PACMAN,
|
||||
item_kind: Some(ITEM_KIND_PACMANCHERRY),
|
||||
article_kind: None,
|
||||
variation: None,
|
||||
},
|
||||
CharItem {
|
||||
fighter_kind: FIGHTER_KIND_PACMAN,
|
||||
item_kind: Some(ITEM_KIND_PACMANSTRAWBERRY),
|
||||
article_kind: None,
|
||||
variation: None,
|
||||
},
|
||||
CharItem {
|
||||
fighter_kind: FIGHTER_KIND_PACMAN,
|
||||
item_kind: Some(ITEM_KIND_PACMANORANGE),
|
||||
article_kind: None,
|
||||
variation: None,
|
||||
},
|
||||
CharItem {
|
||||
fighter_kind: FIGHTER_KIND_PACMAN,
|
||||
item_kind: Some(ITEM_KIND_PACMANAPPLE),
|
||||
article_kind: None,
|
||||
variation: None,
|
||||
},
|
||||
CharItem {
|
||||
fighter_kind: FIGHTER_KIND_PACMAN,
|
||||
item_kind: Some(ITEM_KIND_PACMANMELON),
|
||||
article_kind: None,
|
||||
variation: None,
|
||||
},
|
||||
CharItem {
|
||||
fighter_kind: FIGHTER_KIND_PACMAN,
|
||||
item_kind: Some(ITEM_KIND_PACMANBOSS),
|
||||
article_kind: None,
|
||||
variation: None,
|
||||
},
|
||||
CharItem {
|
||||
fighter_kind: FIGHTER_KIND_PACMAN,
|
||||
item_kind: Some(ITEM_KIND_PACMANBELL),
|
||||
article_kind: None,
|
||||
variation: None,
|
||||
},
|
||||
CharItem {
|
||||
fighter_kind: FIGHTER_KIND_PACMAN,
|
||||
item_kind: Some(ITEM_KIND_PACMANKEY),
|
||||
article_kind: None,
|
||||
variation: None,
|
||||
},
|
||||
CharItem {
|
||||
// Turnip
|
||||
fighter_kind: FIGHTER_KIND_PEACH,
|
||||
item_kind: None,
|
||||
article_kind: Some(FIGHTER_PEACH_GENERATE_ARTICLE_DAIKON),
|
||||
variation: Some(ITEM_VARIATION_PEACHDAIKON_1), // Smile
|
||||
},
|
||||
CharItem {
|
||||
// Turnip
|
||||
fighter_kind: FIGHTER_KIND_PEACH,
|
||||
item_kind: None,
|
||||
article_kind: Some(FIGHTER_PEACH_GENERATE_ARTICLE_DAIKON),
|
||||
variation: Some(ITEM_VARIATION_PEACHDAIKON_6), // Winky
|
||||
},
|
||||
CharItem {
|
||||
// Turnip
|
||||
fighter_kind: FIGHTER_KIND_PEACH,
|
||||
item_kind: None,
|
||||
article_kind: Some(FIGHTER_PEACH_GENERATE_ARTICLE_DAIKON),
|
||||
variation: Some(ITEM_VARIATION_PEACHDAIKON_7), // Dot-Eyes
|
||||
},
|
||||
CharItem {
|
||||
// Turnip
|
||||
fighter_kind: FIGHTER_KIND_PEACH,
|
||||
item_kind: None,
|
||||
article_kind: Some(FIGHTER_PEACH_GENERATE_ARTICLE_DAIKON),
|
||||
variation: Some(ITEM_VARIATION_PEACHDAIKON_8), // Stitch-face
|
||||
},
|
||||
CharItem {
|
||||
// Mr Saturn
|
||||
fighter_kind: FIGHTER_KIND_PEACH,
|
||||
item_kind: Some(ITEM_KIND_DOSEISAN),
|
||||
article_kind: None,
|
||||
variation: None,
|
||||
},
|
||||
CharItem {
|
||||
// Bob-omb
|
||||
fighter_kind: FIGHTER_KIND_PEACH,
|
||||
item_kind: Some(ITEM_KIND_BOMBHEI),
|
||||
article_kind: None,
|
||||
variation: Some(ITEM_VARIATION_BOMBHEI_NORMAL),
|
||||
},
|
||||
CharItem {
|
||||
fighter_kind: FIGHTER_KIND_RICHTER,
|
||||
item_kind: Some(ITEM_KIND_RICHTERHOLYWATER),
|
||||
article_kind: None,
|
||||
variation: None,
|
||||
},
|
||||
CharItem {
|
||||
fighter_kind: FIGHTER_KIND_ROBOT,
|
||||
item_kind: Some(ITEM_KIND_ROBOTGYRO),
|
||||
article_kind: None,
|
||||
variation: Some(ITEM_VARIATION_ROBOTGYRO_1P),
|
||||
},
|
||||
CharItem {
|
||||
fighter_kind: FIGHTER_KIND_ROBOT,
|
||||
item_kind: Some(ITEM_KIND_ROBOTGYRO),
|
||||
article_kind: None,
|
||||
variation: Some(ITEM_VARIATION_ROBOTGYRO_2P),
|
||||
},
|
||||
CharItem {
|
||||
fighter_kind: FIGHTER_KIND_ROBOT,
|
||||
item_kind: Some(ITEM_KIND_ROBOTGYRO),
|
||||
article_kind: None,
|
||||
variation: Some(ITEM_VARIATION_ROBOTGYRO_3P),
|
||||
},
|
||||
CharItem {
|
||||
fighter_kind: FIGHTER_KIND_ROBOT,
|
||||
item_kind: Some(ITEM_KIND_ROBOTGYRO),
|
||||
article_kind: None,
|
||||
variation: Some(ITEM_VARIATION_ROBOTGYRO_4P),
|
||||
},
|
||||
CharItem {
|
||||
fighter_kind: FIGHTER_KIND_ROBOT,
|
||||
item_kind: Some(ITEM_KIND_ROBOTGYRO),
|
||||
article_kind: None,
|
||||
variation: Some(ITEM_VARIATION_ROBOTGYRO_5P),
|
||||
},
|
||||
CharItem {
|
||||
fighter_kind: FIGHTER_KIND_ROBOT,
|
||||
item_kind: Some(ITEM_KIND_ROBOTGYRO),
|
||||
article_kind: None,
|
||||
variation: Some(ITEM_VARIATION_ROBOTGYRO_6P),
|
||||
},
|
||||
CharItem {
|
||||
fighter_kind: FIGHTER_KIND_ROBOT,
|
||||
item_kind: Some(ITEM_KIND_ROBOTGYRO),
|
||||
article_kind: None,
|
||||
variation: Some(ITEM_VARIATION_ROBOTGYRO_7P),
|
||||
},
|
||||
CharItem {
|
||||
fighter_kind: FIGHTER_KIND_ROBOT,
|
||||
item_kind: Some(ITEM_KIND_ROBOTGYRO),
|
||||
article_kind: None,
|
||||
variation: Some(ITEM_VARIATION_ROBOTGYRO_8P),
|
||||
},
|
||||
CharItem {
|
||||
fighter_kind: FIGHTER_KIND_SIMON,
|
||||
item_kind: Some(ITEM_KIND_SIMONHOLYWATER),
|
||||
article_kind: None,
|
||||
variation: None,
|
||||
},
|
||||
CharItem {
|
||||
fighter_kind: FIGHTER_KIND_SNAKE,
|
||||
item_kind: Some(ITEM_KIND_SNAKEGRENADE),
|
||||
article_kind: None,
|
||||
variation: None,
|
||||
},
|
||||
// CharItem {
|
||||
// // Cardboard Box from Taunt
|
||||
// fighter_kind: FIGHTER_KIND_SNAKE,
|
||||
// item_kind: Some(ITEM_KIND_SNAKECBOX),
|
||||
// article_kind: None,
|
||||
// variation: None,
|
||||
// },
|
||||
CharItem {
|
||||
// Robin Levin Sword
|
||||
fighter_kind: FIGHTER_KIND_REFLET,
|
||||
item_kind: Some(ITEM_KIND_THUNDERSWORD),
|
||||
article_kind: None,
|
||||
variation: None,
|
||||
},
|
||||
CharItem {
|
||||
fighter_kind: FIGHTER_KIND_TOONLINK,
|
||||
item_kind: Some(ITEM_KIND_TOONLINKBOMB),
|
||||
article_kind: None,
|
||||
variation: None,
|
||||
},
|
||||
// CharItem {
|
||||
// fighter_kind: FIGHTER_KIND_WARIO,
|
||||
// item_kind: Some(ITEM_KIND_WARIOBIKE),
|
||||
// // Pretty sure these other ones are just the bike parts
|
||||
// // ITEM_KIND_WARIOBIKEA,
|
||||
// // ITEM_KIND_WARIOBIKEB,
|
||||
// // ITEM_KIND_WARIOBIKEC,
|
||||
// // ITEM_KIND_WARIOBIKED,
|
||||
// // ITEM_KIND_WARIOBIKEE,
|
||||
// article_kind: None,
|
||||
// variation: None,
|
||||
// },
|
||||
CharItem {
|
||||
// Villager Wood Chip
|
||||
fighter_kind: FIGHTER_KIND_MURABITO,
|
||||
item_kind: Some(ITEM_KIND_WOOD),
|
||||
article_kind: None,
|
||||
variation: None,
|
||||
},
|
||||
CharItem {
|
||||
fighter_kind: FIGHTER_KIND_YOUNGLINK,
|
||||
item_kind: Some(ITEM_KIND_YOUNGLINKBOMB),
|
||||
article_kind: None,
|
||||
variation: None,
|
||||
},
|
||||
];
|
||||
|
||||
pub static mut TURNIP_CHOSEN: Option<u32> = None;
|
||||
pub static mut TARGET_PLAYER: Option<*mut BattleObjectModuleAccessor> = None;
|
||||
|
||||
unsafe fn apply_single_item(player_fighter_kind: i32, item: &CharItem) {
|
||||
let player_module_accessor = get_module_accessor(FighterId::Player);
|
||||
let cpu_module_accessor = get_module_accessor(FighterId::CPU);
|
||||
// Now we make sure the module_accessor we use to generate the item/article is the correct character
|
||||
let generator_module_accessor = if item.fighter_kind == player_fighter_kind {
|
||||
player_module_accessor
|
||||
} else {
|
||||
cpu_module_accessor
|
||||
};
|
||||
let variation = item.variation.as_ref().map(|v| **v).unwrap_or(0);
|
||||
item.item_kind.as_ref().map(|item_kind| {
|
||||
let item_kind = **item_kind;
|
||||
// For Link, use special article generation to link the bomb for detonation
|
||||
if item_kind == *ITEM_KIND_LINKBOMB {
|
||||
ArticleModule::generate_article_have_item(
|
||||
generator_module_accessor,
|
||||
*FIGHTER_LINK_GENERATE_ARTICLE_LINKBOMB,
|
||||
*FIGHTER_HAVE_ITEM_WORK_MAIN,
|
||||
smash::phx::Hash40::new("invalid"),
|
||||
);
|
||||
if player_fighter_kind != *FIGHTER_KIND_LINK {
|
||||
ItemModule::drop_item(cpu_module_accessor, 0.0, 0.0, 0);
|
||||
//ItemModule::eject_have_item(cpu_module_accessor, 0, false, false);
|
||||
let item_mgr = *(ITEM_MANAGER_ADDR as *mut *mut app::ItemManager);
|
||||
let item_ptr = ItemManager::get_active_item(item_mgr, 0);
|
||||
ItemModule::have_item_instance(
|
||||
player_module_accessor,
|
||||
item_ptr as *mut smash::app::Item,
|
||||
0,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
ItemModule::have_item(
|
||||
player_module_accessor,
|
||||
ItemKind(item_kind),
|
||||
variation,
|
||||
0,
|
||||
false,
|
||||
false,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
item.article_kind.as_ref().map(|article_kind| {
|
||||
TURNIP_CHOSEN = if [*ITEM_VARIATION_PEACHDAIKON_8, *ITEM_VARIATION_DAISYDAIKON_8]
|
||||
.contains(&variation)
|
||||
{
|
||||
Some(8)
|
||||
} else if [*ITEM_VARIATION_PEACHDAIKON_7, *ITEM_VARIATION_DAISYDAIKON_7]
|
||||
.contains(&variation)
|
||||
{
|
||||
Some(7)
|
||||
} else if [*ITEM_VARIATION_PEACHDAIKON_6, *ITEM_VARIATION_DAISYDAIKON_6]
|
||||
.contains(&variation)
|
||||
{
|
||||
Some(6)
|
||||
} else if [*ITEM_VARIATION_PEACHDAIKON_1, *ITEM_VARIATION_DAISYDAIKON_1]
|
||||
.contains(&variation)
|
||||
{
|
||||
Some(1)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let article_kind = **article_kind;
|
||||
if article_kind == FIGHTER_DIDDY_GENERATE_ARTICLE_ITEM_BANANA {
|
||||
ArticleModule::generate_article_have_item(
|
||||
generator_module_accessor,
|
||||
*FIGHTER_DIDDY_GENERATE_ARTICLE_ITEM_BANANA,
|
||||
*FIGHTER_HAVE_ITEM_WORK_MAIN,
|
||||
smash::phx::Hash40::new("invalid"),
|
||||
);
|
||||
WorkModule::on_flag(
|
||||
generator_module_accessor,
|
||||
*FIGHTER_DIDDY_STATUS_SPECIAL_LW_FLAG_ITEM_THROW,
|
||||
);
|
||||
ArticleModule::shoot(
|
||||
generator_module_accessor,
|
||||
*FIGHTER_DIDDY_GENERATE_ARTICLE_ITEM_BANANA,
|
||||
ArticleOperationTarget(*ARTICLE_OPE_TARGET_ALL),
|
||||
false,
|
||||
);
|
||||
// Grab item from the middle of the stage where it gets shot
|
||||
let item_mgr = *(ITEM_MANAGER_ADDR as *mut *mut app::ItemManager);
|
||||
let item = ItemManager::get_active_item(item_mgr, 0);
|
||||
ItemModule::have_item_instance(
|
||||
player_module_accessor,
|
||||
item as *mut Item,
|
||||
0,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
);
|
||||
} else {
|
||||
TARGET_PLAYER = Some(player_module_accessor); // set so we generate CPU article on the player (in dittos, items always belong to player, even if cpu item is chosen)
|
||||
ArticleModule::generate_article(
|
||||
generator_module_accessor, // we want CPU's article
|
||||
article_kind,
|
||||
false,
|
||||
0,
|
||||
);
|
||||
TARGET_PLAYER = None;
|
||||
}
|
||||
TURNIP_CHOSEN = None;
|
||||
});
|
||||
}
|
||||
|
||||
pub unsafe fn apply_item(character_item: CharacterItem) {
|
||||
let player_module_accessor = get_module_accessor(FighterId::Player);
|
||||
let cpu_module_accessor = get_module_accessor(FighterId::CPU);
|
||||
let player_fighter_kind = app::utility::get_kind(&mut *player_module_accessor);
|
||||
let cpu_fighter_kind = app::utility::get_kind(&mut *cpu_module_accessor);
|
||||
let character_item_num = character_item.as_idx();
|
||||
let (item_fighter_kind, variation_idx) =
|
||||
if character_item_num <= CharacterItem::PlayerVariation8.as_idx() {
|
||||
(
|
||||
player_fighter_kind,
|
||||
(character_item_num - CharacterItem::PlayerVariation1.as_idx()) as usize,
|
||||
)
|
||||
} else {
|
||||
(
|
||||
cpu_fighter_kind,
|
||||
(character_item_num - CharacterItem::CpuVariation1.as_idx()) as usize,
|
||||
)
|
||||
};
|
||||
ALL_CHAR_ITEMS
|
||||
.iter()
|
||||
.filter(|item| item_fighter_kind == item.fighter_kind)
|
||||
.nth(variation_idx)
|
||||
.map(|item| apply_single_item(player_fighter_kind, item));
|
||||
mash::clear_queue();
|
||||
}
|
||||
|
||||
macro_rules! daikon_replace {
|
||||
($caps_char: ident, $char:ident, $num:literal) => {
|
||||
paste::paste! {
|
||||
extern "C" {
|
||||
#[link_name = "\u{1}_ZN3app11" $char "daikon31" $caps_char "_" $caps_char "DAIKON_DAIKON_" $num "_PROBEv"]
|
||||
pub fn [<$char daikon_ $num _prob>]() -> f32;
|
||||
}
|
||||
|
||||
#[skyline::hook(replace = [<$char daikon_ $num _prob>])]
|
||||
pub unsafe fn [<handle_ $char daikon_ $num _prob>]() -> f32 {
|
||||
let orig = original!()();
|
||||
if is_training_mode() {
|
||||
if TURNIP_CHOSEN == Some($num) {
|
||||
return 58.0;
|
||||
} else if TURNIP_CHOSEN != None {
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
orig
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
daikon_replace!(PEACH, peach, 8);
|
||||
daikon_replace!(PEACH, peach, 7);
|
||||
daikon_replace!(PEACH, peach, 6);
|
||||
daikon_replace!(PEACH, peach, 5);
|
||||
daikon_replace!(PEACH, peach, 4);
|
||||
daikon_replace!(PEACH, peach, 3);
|
||||
daikon_replace!(PEACH, peach, 2);
|
||||
daikon_replace!(PEACH, peach, 1);
|
||||
daikon_replace!(DAISY, daisy, 8);
|
||||
daikon_replace!(DAISY, daisy, 7);
|
||||
daikon_replace!(DAISY, daisy, 6);
|
||||
daikon_replace!(DAISY, daisy, 5);
|
||||
daikon_replace!(DAISY, daisy, 4);
|
||||
daikon_replace!(DAISY, daisy, 3);
|
||||
daikon_replace!(DAISY, daisy, 2);
|
||||
daikon_replace!(DAISY, daisy, 1);
|
||||
|
||||
// GenerateArticleForTarget for Peach/Diddy(/Link?) item creation
|
||||
static GAFT_OFFSET: usize = 0x03d40a0;
|
||||
#[skyline::hook(offset = GAFT_OFFSET)]
|
||||
pub unsafe fn handle_generate_article_for_target(
|
||||
article_module_accessor: *mut app::BattleObjectModuleAccessor,
|
||||
int_1: i32,
|
||||
module_accessor: *mut app::BattleObjectModuleAccessor, // this is always 0x0 normally
|
||||
bool_1: bool,
|
||||
int_2: i32,
|
||||
) -> u64 {
|
||||
// unknown return value, gets cast to an (Article *)
|
||||
let target_module_accessor = TARGET_PLAYER.unwrap_or(module_accessor);
|
||||
let ori = original!()(
|
||||
article_module_accessor,
|
||||
int_1,
|
||||
target_module_accessor,
|
||||
bool_1,
|
||||
int_2,
|
||||
);
|
||||
return ori;
|
||||
}
|
||||
|
||||
pub fn init() {
|
||||
skyline::install_hooks!(
|
||||
handle_peachdaikon_8_prob,
|
||||
handle_peachdaikon_7_prob,
|
||||
handle_peachdaikon_6_prob,
|
||||
handle_peachdaikon_5_prob,
|
||||
handle_peachdaikon_4_prob,
|
||||
handle_peachdaikon_3_prob,
|
||||
handle_peachdaikon_2_prob,
|
||||
handle_peachdaikon_1_prob,
|
||||
handle_daisydaikon_8_prob,
|
||||
handle_daisydaikon_7_prob,
|
||||
handle_daisydaikon_6_prob,
|
||||
handle_daisydaikon_5_prob,
|
||||
handle_daisydaikon_4_prob,
|
||||
handle_daisydaikon_3_prob,
|
||||
handle_daisydaikon_2_prob,
|
||||
handle_daisydaikon_1_prob,
|
||||
// Items
|
||||
handle_generate_article_for_target,
|
||||
);
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
use smash::app::{self};
|
||||
|
||||
mod bowser;
|
||||
pub mod items;
|
||||
pub mod steve;
|
||||
|
||||
/**
|
||||
|
|
|
@ -87,6 +87,10 @@ pub fn full_reset() {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn clear_queue() {
|
||||
unsafe { QUEUE.clear() }
|
||||
}
|
||||
|
||||
pub fn set_aerial(attack: Action) {
|
||||
unsafe {
|
||||
CURRENT_AERIAL = attack;
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
use crate::common::{is_training_mode, menu, FIGHTER_MANAGER_ADDR, STAGE_MANAGER_ADDR};
|
||||
use crate::common::{
|
||||
is_training_mode, menu, FIGHTER_MANAGER_ADDR, ITEM_MANAGER_ADDR, STAGE_MANAGER_ADDR,
|
||||
};
|
||||
use crate::hitbox_visualizer;
|
||||
use crate::training::character_specific::items;
|
||||
use skyline::hooks::{getRegionAddress, InlineCtx, Region};
|
||||
use skyline::nn::hid::*;
|
||||
use skyline::nn::ro::LookupSymbol;
|
||||
|
@ -485,6 +488,13 @@ pub fn training_mods() {
|
|||
.as_ptr(),
|
||||
);
|
||||
|
||||
LookupSymbol(
|
||||
&mut ITEM_MANAGER_ADDR,
|
||||
"_ZN3lib9SingletonIN3app11ItemManagerEE9instance_E\0"
|
||||
.as_bytes()
|
||||
.as_ptr(),
|
||||
);
|
||||
|
||||
smash::params::add_hook(params_main).unwrap();
|
||||
}
|
||||
|
||||
|
@ -536,4 +546,5 @@ pub fn training_mods() {
|
|||
throw::init();
|
||||
menu::init();
|
||||
buff::init();
|
||||
items::init();
|
||||
}
|
||||
|
|
|
@ -5,14 +5,15 @@ use crate::common::consts::SaveStateMirroring;
|
|||
use crate::common::is_dead;
|
||||
use crate::common::MENU;
|
||||
use crate::training::buff;
|
||||
use crate::training::character_specific::steve;
|
||||
use crate::training::charge::{self, ChargeState};
|
||||
use crate::training::items::apply_item;
|
||||
use crate::training::reset;
|
||||
use smash::app::{self, lua_bind::*};
|
||||
use smash::app::{self, lua_bind::*, Item};
|
||||
use smash::hash40;
|
||||
use smash::lib::lua_const::*;
|
||||
use smash::phx::{Hash40, Vector3f};
|
||||
|
||||
use crate::training::character_specific::steve;
|
||||
use training_mod_consts::CharacterItem;
|
||||
|
||||
#[derive(PartialEq)]
|
||||
enum SaveState {
|
||||
|
@ -75,6 +76,7 @@ macro_rules! default_save_state {
|
|||
};
|
||||
}
|
||||
|
||||
use crate::ITEM_MANAGER_ADDR;
|
||||
use SaveState::*;
|
||||
|
||||
static mut SAVE_STATE_PLAYER: SavedState = default_save_state!();
|
||||
|
@ -229,6 +231,16 @@ pub unsafe fn save_states(module_accessor: &mut app::BattleObjectModuleAccessor)
|
|||
};
|
||||
PostureModule::set_pos(module_accessor, &pos);
|
||||
|
||||
let item_mgr = *(ITEM_MANAGER_ADDR as *mut *mut app::ItemManager);
|
||||
(0..ItemManager::get_num_of_active_item_all(item_mgr)).for_each(|item_idx| {
|
||||
let item = ItemManager::get_active_item(item_mgr, item_idx);
|
||||
if item != 0 {
|
||||
let item = item as *mut Item;
|
||||
let item_battle_object_id =
|
||||
smash::app::lua_bind::Item::get_battle_object_id(item) as u32;
|
||||
ItemManager::remove_item_from_id(item_mgr, item_battle_object_id);
|
||||
}
|
||||
});
|
||||
MotionAnimcmdModule::set_sleep(module_accessor, true);
|
||||
SoundModule::pause_se_all(module_accessor, true);
|
||||
ControlModule::stop_rumble(module_accessor, true);
|
||||
|
@ -319,6 +331,11 @@ pub unsafe fn save_states(module_accessor: &mut app::BattleObjectModuleAccessor)
|
|||
// If we're done moving, reset percent, handle charges, and apply buffs
|
||||
if save_state.state == NoAction {
|
||||
set_damage(module_accessor, save_state.percent);
|
||||
// Set to held item
|
||||
if !is_cpu && !fighter_is_nana && MENU.character_item != CharacterItem::None {
|
||||
apply_item(MENU.character_item);
|
||||
}
|
||||
|
||||
// Set the charge of special moves if the fighter matches the kind in the save state
|
||||
if save_state.fighter_kind == fighter_kind {
|
||||
charge::handle_charge(module_accessor, fighter_kind, save_state.charge);
|
||||
|
|
|
@ -918,6 +918,71 @@ impl ToUrlParam for i32 {
|
|||
}
|
||||
}
|
||||
|
||||
/// Item Selections
|
||||
#[repr(i32)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, FromPrimitive, EnumIter, Serialize, Deserialize)]
|
||||
pub enum CharacterItem {
|
||||
None = 0,
|
||||
PlayerVariation1 = 0x1,
|
||||
PlayerVariation2 = 0x2,
|
||||
PlayerVariation3 = 0x4,
|
||||
PlayerVariation4 = 0x8,
|
||||
PlayerVariation5 = 0x10,
|
||||
PlayerVariation6 = 0x20,
|
||||
PlayerVariation7 = 0x40,
|
||||
PlayerVariation8 = 0x80,
|
||||
CpuVariation1 = 0x100,
|
||||
CpuVariation2 = 0x200,
|
||||
CpuVariation3 = 0x400,
|
||||
CpuVariation4 = 0x800,
|
||||
CpuVariation5 = 0x1000,
|
||||
CpuVariation6 = 0x2000,
|
||||
CpuVariation7 = 0x4000,
|
||||
CpuVariation8 = 0x8000,
|
||||
}
|
||||
|
||||
impl CharacterItem {
|
||||
pub fn as_idx(self) -> u32 {
|
||||
log_2(self as i32 as u32)
|
||||
}
|
||||
|
||||
pub fn as_str(self) -> Option<&'static str> {
|
||||
Some(match self {
|
||||
CharacterItem::PlayerVariation1 => "Player 1st Var.",
|
||||
CharacterItem::PlayerVariation2 => "Player 2nd Var.",
|
||||
CharacterItem::PlayerVariation3 => "Player 3rd Var.",
|
||||
CharacterItem::PlayerVariation4 => "Player 4th Var.",
|
||||
CharacterItem::PlayerVariation5 => "Player 5th Var.",
|
||||
CharacterItem::PlayerVariation6 => "Player 6th Var.",
|
||||
CharacterItem::PlayerVariation7 => "Player 7th Var.",
|
||||
CharacterItem::PlayerVariation8 => "Player 8th Var.",
|
||||
CharacterItem::CpuVariation1 => "CPU 1st Var.",
|
||||
CharacterItem::CpuVariation2 => "CPU 2nd Var.",
|
||||
CharacterItem::CpuVariation3 => "CPU 3rd Var.",
|
||||
CharacterItem::CpuVariation4 => "CPU 4th Var.",
|
||||
CharacterItem::CpuVariation5 => "CPU 5th Var.",
|
||||
CharacterItem::CpuVariation6 => "CPU 6th Var.",
|
||||
CharacterItem::CpuVariation7 => "CPU 7th Var.",
|
||||
CharacterItem::CpuVariation8 => "CPU 8th Var.",
|
||||
_ => "None",
|
||||
})
|
||||
}
|
||||
|
||||
pub fn to_url_param(&self) -> String {
|
||||
(*self as i32).to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl ToggleTrait for CharacterItem {
|
||||
fn to_toggle_strs() -> Vec<&'static str> {
|
||||
CharacterItem::iter().map(|i| i.as_str().unwrap_or("")).collect()
|
||||
}
|
||||
|
||||
fn to_toggle_vals() -> Vec<usize> {
|
||||
CharacterItem::iter().map(|i| i as usize).collect()
|
||||
}
|
||||
}
|
||||
|
||||
// Macro to build the url parameter string
|
||||
macro_rules! url_params {
|
||||
(
|
||||
|
@ -992,6 +1057,7 @@ url_params! {
|
|||
pub throw_delay: MedDelay,
|
||||
pub pummel_delay: MedDelay,
|
||||
pub buff_state: BuffOption,
|
||||
pub character_item: CharacterItem,
|
||||
pub quick_menu: OnOff,
|
||||
}
|
||||
}
|
||||
|
@ -1055,6 +1121,7 @@ impl TrainingModpackMenu {
|
|||
throw_delay = MedDelay::from_bits(val),
|
||||
pummel_delay = MedDelay::from_bits(val),
|
||||
buff_state = BuffOption::from_bits(val),
|
||||
character_item = num::FromPrimitive::from_u32(val),
|
||||
quick_menu = OnOff::from_val(val),
|
||||
);
|
||||
}
|
||||
|
@ -1120,6 +1187,7 @@ pub static DEFAULTS_MENU: TrainingModpackMenu = TrainingModpackMenu {
|
|||
throw_delay: MedDelay::empty(),
|
||||
pummel_delay: MedDelay::empty(),
|
||||
buff_state: BuffOption::empty(),
|
||||
character_item: CharacterItem::None,
|
||||
quick_menu: OnOff::Off,
|
||||
};
|
||||
|
||||
|
@ -1420,9 +1488,9 @@ pub unsafe fn get_menu() -> UiMenu<'static> {
|
|||
false, // TODO: Should this be true?
|
||||
);
|
||||
defensive_tab.add_submenu_with_toggles::<Defensive>(
|
||||
"Defensive Toggles",
|
||||
"Escape Toggles",
|
||||
"defensive_state",
|
||||
"Defensive Options: Actions to take after a ledge option, tech option, or mistech option",
|
||||
"Escape Options: Actions to take after a ledge option, tech option, or mistech option",
|
||||
false,
|
||||
);
|
||||
defensive_tab.add_submenu_with_toggles::<BuffOption>(
|
||||
|
@ -1431,6 +1499,12 @@ pub unsafe fn get_menu() -> UiMenu<'static> {
|
|||
"Buff Options: Buff(s) to be applied to respective character when loading save states",
|
||||
false,
|
||||
);
|
||||
defensive_tab.add_submenu_with_toggles::<CharacterItem>(
|
||||
"Character Item",
|
||||
"character_item",
|
||||
"Character Item: CPU/Player item to hold when loading a save state",
|
||||
true
|
||||
);
|
||||
overall_menu.tabs.push(defensive_tab);
|
||||
|
||||
let mut misc_tab = Tab {
|
||||
|
@ -1457,7 +1531,7 @@ pub unsafe fn get_menu() -> UiMenu<'static> {
|
|||
true,
|
||||
);
|
||||
misc_tab.add_submenu_with_toggles::<OnOff>(
|
||||
"Autoload Save States",
|
||||
"Save States Autoload",
|
||||
"save_state_autoload",
|
||||
"Save States Autoload: Load save state when any fighter dies",
|
||||
true,
|
||||
|
|
Loading…
Reference in a new issue