From 9e94ef72a9d945363f867e0055f8eec33bbe0d5a Mon Sep 17 00:00:00 2001 From: GradualSyrup <68757075+GradualSyrup@users.noreply.github.com> Date: Wed, 30 Aug 2023 21:00:29 -0500 Subject: [PATCH] Pikmin Save States and Skyline Smash update (#613) * Add reusable print_fighter_info() * rustfmt * Clippy * starting charge * Working Pikmin Save States, motion not working, order can be messed up by loading during an aerial, if you save too quickly you lose pikmin in the state * often failing boid read * notes * Prevent Pikmin from being cleaned up by the regular cleanup process * migration progress * skyline-smash branch, more pikmin work * Using buff to spawn pikmin, character specific file for cleanliness * failed reordering attempt * more failed ordering * almost kind of works but out of order * failed all, need to try individual hold and status change * hard reorder crash * battleobject not boma * comment clarification * messing around with printing * printing, about to try to find where autonomy is being set * solution found, going to hook backshield to find where autonomy is being set to true * found where to hook, will start hooking * switched to charge, issues with inline hook * need to only have autonomy ignored on save state load * distance and status controls (doesn't work perfectly) * Christmas Miracle * Working w/ Cleanup * training mode check, improved owner check * debug feature print methods * Pikmin debug assertions * clippy print fix * appease clippy --- Cargo.toml | 2 +- src/common/mod.rs | 86 ++++++++- src/common/release.rs | 2 +- src/training/character_specific/mod.rs | 1 + src/training/character_specific/pikmin.rs | 214 ++++++++++++++++++++++ src/training/charge.rs | 76 +++++++- src/training/mod.rs | 28 ++- src/training/save_states.rs | 13 +- training_mod_consts/src/options.rs | 1 - 9 files changed, 405 insertions(+), 18 deletions(-) create mode 100644 src/training/character_specific/pikmin.rs diff --git a/Cargo.toml b/Cargo.toml index a78dc6d..acf4b4d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ crate-type = ["cdylib"] [dependencies] skyline = { git = "https://github.com/ultimate-research/skyline-rs.git" } -skyline_smash = { git = "https://github.com/ultimate-research/skyline-smash.git", branch = "no-cache" } +skyline_smash = { git = "https://github.com/GradualSyrup/skyline-smash.git", branch = "training-modpack-updates" } skyline-web = { git = "https://github.com/skyline-rs/skyline-web.git" } bitflags = "1.2.1" parking_lot = { version = "0.12.0", features = ["nightly"] } diff --git a/src/common/mod.rs b/src/common/mod.rs index d8be0d4..cb2b7f8 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -1,4 +1,4 @@ -use smash::app::{self, lua_bind::*}; +use smash::app::{self, lua_bind::*, utility}; use smash::hash40; use smash::lib::lua_const::*; use smash::lua2cpp::L2CFighterCommon; @@ -34,7 +34,7 @@ pub fn is_training_mode() -> bool { } pub fn get_category(module_accessor: &app::BattleObjectModuleAccessor) -> i32 { - (module_accessor.info >> 28) as u8 as i32 + (module_accessor.battle_object_id >> 28) as u8 as i32 } pub fn is_emulator() -> bool { @@ -266,6 +266,88 @@ pub unsafe fn get_fighter_distance() -> f32 { ) } +// Example Call: + +// print_fighter_info( +// module_accessor, +// "DebugTest", +// true, +// false, +// true, +// true, +// vec![ +// ("FIGHTER_INSTANCE_WORK_ID_INT_CLIFF_COUNT", FIGHTER_INSTANCE_WORK_ID_INT_CLIFF_COUNT), +// ], +// Vec::new(), +// vec![ +// ("FIGHTER_STATUS_CLIFF_FLAG_TO_FALL", FIGHTER_STATUS_CLIFF_FLAG_TO_FALL), +// ], +// ); +#[allow(dead_code)] // We won't be using this function in builds, but we don't want to be warned about it +#[allow(clippy::too_many_arguments)] // This function has so many arguments so it's easy to quickly fill them in when debugging with the analyzer +pub fn print_fighter_info( + module_accessor: &mut app::BattleObjectModuleAccessor, + title: &str, + player_only: bool, + cpu_only: bool, + print_fighter_kind: bool, + print_status: bool, + work_int_pairs: Vec<(&str, i32)>, + work_float_pairs: Vec<(&str, i32)>, + work_flag_pairs: Vec<(&str, i32)>, +) { + unsafe { + // Don't print for fighters we don't want to + let is_cpu = is_operation_cpu(module_accessor); + if (player_only && is_cpu) || (cpu_only && !is_cpu) { + return; + } + // Print Title + print!("{}: ", title); + // Print Fighter Kind: + if print_fighter_kind { + print!("FIGHTER_KIND: {}, ", utility::get_kind(module_accessor)); + } + // Print Status: + if print_status { + print!( + "FIGHTER_STATUS: {}, ", + StatusModule::status_kind(module_accessor) + ); + } + + // Print Work Ints: + for work_int_pair in work_int_pairs { + print!( + "{}: {}, ", + work_int_pair.0, + WorkModule::get_int(module_accessor, work_int_pair.1) + ); + } + + // Print Work Floats: + for work_float_pair in work_float_pairs { + print!( + "{}: {}, ", + work_float_pair.0, + WorkModule::get_float(module_accessor, work_float_pair.1) + ); + } + + // Print Work Flags: + for work_flag_pair in work_flag_pairs { + print!( + "{}: {}, ", + work_flag_pair.0, + WorkModule::is_flag(module_accessor, work_flag_pair.1) + ); + } + + // End Line + println!("|"); + } +} + // From https://github.com/chrispo-git/ult-s/blob/cc1c3060ed83f6d33f39964e84f9c32c07a17bae/src/controls/util.rs#L106 pub unsafe fn get_fighter_common_from_accessor( module_accessor: &mut app::BattleObjectModuleAccessor, diff --git a/src/common/release.rs b/src/common/release.rs index 91dbb84..2231129 100644 --- a/src/common/release.rs +++ b/src/common/release.rs @@ -1,6 +1,6 @@ #![allow(clippy::unnecessary_unwrap)] +use crate::common::dialog; use crate::consts::*; -use crate::dialog; use crate::logging::*; use crate::MENU; use anyhow::{anyhow, Result}; diff --git a/src/training/character_specific/mod.rs b/src/training/character_specific/mod.rs index 8054e4b..0546682 100644 --- a/src/training/character_specific/mod.rs +++ b/src/training/character_specific/mod.rs @@ -2,6 +2,7 @@ use smash::app::{self}; mod bowser; pub mod items; +pub mod pikmin; pub mod steve; /** diff --git a/src/training/character_specific/pikmin.rs b/src/training/character_specific/pikmin.rs new file mode 100644 index 0000000..edced29 --- /dev/null +++ b/src/training/character_specific/pikmin.rs @@ -0,0 +1,214 @@ +use smash::app::{self, lua_bind::*, smashball::is_training_mode}; +use smash::lib::lua_const::*; + +#[repr(C)] +struct TroopsManager { + _x0: u64, + max_pikmin_count: usize, // always 3 + current_pikmin_count: usize, + pikmin_objects: *mut *mut app::BattleObject, + pikmin: [*mut app::BattleObject; 3], + padding_0: u64, + padding_1: u64, + padding_2: u64, + padding_3: u64, + padding_4: u64, + padding_5: u64, + padding_6: u64, + padding_7: u64, + padding_8: u64, + held_pikmin_count: usize, + maybe_more_pikmin_objects: *mut *mut app::BattleObject, + held_pikmin: [*mut app::BattleObject; 3], // @ 0x90 +} + +#[repr(C)] +pub struct WeaponWorkModule { + vtable: u64, + owner: *mut app::BattleObjectModuleAccessor, +} + +// Prevent Order Loss +static ACTIVATE_AUTONOMY_OFFSET: usize = 0x034b5cf0; +#[skyline::hook(offset = ACTIVATE_AUTONOMY_OFFSET)] +pub unsafe fn autonomy_handle(weapon: *mut app::Weapon, work_module: *mut WeaponWorkModule) { + if !is_training_mode() { + return original!()(weapon, work_module); + } + let pikmin_boma = (*work_module).owner; + // If the Pikmin is in a status where we want this behavior, execute the original process + let pikmin_status = StatusModule::status_kind(pikmin_boma); + let is_pikmin_thrown = (*WEAPON_PIKMIN_PIKMIN_STATUS_KIND_ATTACK_AIR + ..=*WEAPON_PIKMIN_PIKMIN_STATUS_KIND_ATTACK_HI4_LANDING) + .contains(&pikmin_status); + if is_pikmin_thrown { + original!()(weapon, work_module) + } +} + +pub fn init() { + skyline::install_hooks!(autonomy_handle,); +} + +fn get_pikmin_prev(variation: i32) -> i32 { + if variation > 0 { + return variation - 1; + } + 4 +} + +pub unsafe fn follow(module_accessor: &mut app::BattleObjectModuleAccessor) { + let troops_manager = WorkModule::get_int64(module_accessor, 0x100000C0) as *mut TroopsManager; + let following_count = (*troops_manager).current_pikmin_count; + let held_count = (*troops_manager).held_pikmin_count; + + let mut pikmin_boid_following_vec = Vec::new(); + let mut pikmin_boid_held_vec = Vec::new(); + + // First, we get the order of held pikmin, since they'll be in front if we save state during a move or grab + for held_index in 0..held_count { + let held_boid = (*((*troops_manager).held_pikmin[held_index])).battle_object_id; + pikmin_boid_held_vec.push(held_boid); + } + // Next, we get the order of the following pikmin + for following_index in 0..following_count { + let following_boid = (*((*troops_manager).pikmin[following_index])).battle_object_id; + pikmin_boid_following_vec.push(following_boid); + } + + for pikmin_boid in pikmin_boid_following_vec { + let pikmin_boma = app::sv_battle_object::module_accessor(pikmin_boid); + StatusModule::change_status_request( + pikmin_boma, + *WEAPON_PIKMIN_PIKMIN_STATUS_KIND_AIR_FOLLOW, + false, + ); + } +} + +pub unsafe fn spawn_pikmin(module_accessor: &mut app::BattleObjectModuleAccessor, variation: i32) { + WorkModule::set_int( + module_accessor, + get_pikmin_prev(variation), + *FIGHTER_PIKMIN_INSTANCE_WORK_INT_PRE_PIKMIN_VARIATION, + ); + WorkModule::set_int( + module_accessor, + get_pikmin_prev(get_pikmin_prev(variation)), + *FIGHTER_PIKMIN_INSTANCE_WORK_INT_BEFORE_PRE_PIKMIN_VARIATION, + ); + ArticleModule::generate_article( + module_accessor as *mut app::BattleObjectModuleAccessor, + 0, + false, + -1, + ); +} + +pub unsafe fn get_current_pikmin( + module_accessor: &mut app::BattleObjectModuleAccessor, +) -> [Option; 3] { + let troops_manager = WorkModule::get_int64(module_accessor, 0x100000C0) as *mut TroopsManager; + + let following_count = (*troops_manager).current_pikmin_count; + let held_count = (*troops_manager).held_pikmin_count; + + let mut pikmin_boid_vec = Vec::new(); + //let mut pikmin_boma_vec: [*mut app::BattleObjectModuleAccessor; 3] = [0 as *mut app::BattleObjectModuleAccessor; 3]; + let mut ordered_pikmin_variation: [Option; 3] = [None; 3]; + + // First, we get the order of held pikmin, since they'll be in front if we save state during a move or grab + for held_index in 0..held_count { + let held_work_var = match held_index { + 0 => *FIGHTER_PIKMIN_INSTANCE_WORK_INT_PIKMIN_HOLD_PIKMIN_OBJECT_ID_0, + 1 => *FIGHTER_PIKMIN_INSTANCE_WORK_INT_PIKMIN_HOLD_PIKMIN_OBJECT_ID_1, + 2 => *FIGHTER_PIKMIN_INSTANCE_WORK_INT_PIKMIN_HOLD_PIKMIN_OBJECT_ID_2, + _ => { + panic!("Pikmin Held Out of Bounds!"); + } + }; + let held_boid = WorkModule::get_int(module_accessor, held_work_var) as u32; + println!(", boid: {}", held_boid); + pikmin_boid_vec.push(held_boid); + } + // Next, we get the order of the following pikmin + for following_index in 0..following_count { + let following_boid = (*((*troops_manager).pikmin[following_index])).battle_object_id; + pikmin_boid_vec.push(following_boid); + } + // Now, we have all pikmin boids, and want to get their bomas (if they exist) so we can check their color + for (idx, pikmin_boid) in pikmin_boid_vec.iter().enumerate() { + if *pikmin_boid != *BATTLE_OBJECT_ID_INVALID as u32 + && app::sv_battle_object::is_active(*pikmin_boid) + { + let pikmin_boma = app::sv_battle_object::module_accessor(*pikmin_boid); + let pikmin_variation = WorkModule::get_int( + pikmin_boma, + *WEAPON_PIKMIN_PIKMIN_INSTANCE_WORK_ID_INT_VARIATION, + ); + ordered_pikmin_variation[idx] = Some(pikmin_variation); + } + } + + ordered_pikmin_variation +} + +#[cfg(debug_assertions)] +#[allow(dead_code)] +pub unsafe fn pretty_print(module_accessor: &mut app::BattleObjectModuleAccessor) { + let troops_manager = WorkModule::get_int64(module_accessor, 0x100000C0) as *mut TroopsManager; + + let following_count = (*troops_manager).current_pikmin_count; + let held_count = (*troops_manager).held_pikmin_count; + + let mut pikmin_following_boid_vec = Vec::new(); + let mut pikmin_held_boid_vec = Vec::new(); + + // First, we get the order of held pikmin, since they'll be in front if we save state during a move or grab + for held_index in 0..held_count { + let held_boid = (*((*troops_manager).held_pikmin[held_index])).battle_object_id; + pikmin_held_boid_vec.push(held_boid); + print(held_boid, true); + } + // Next, we get the order of the following pikmin + for following_index in 0..following_count { + let following_boid = (*((*troops_manager).pikmin[following_index])).battle_object_id; + pikmin_following_boid_vec.push(following_boid); + print(following_boid, false); + } + println!("----------------------------------------") +} + +#[cfg(debug_assertions)] +#[allow(dead_code)] +unsafe fn print(boid: u32, held: bool) { + if boid != *BATTLE_OBJECT_ID_INVALID as u32 && app::sv_battle_object::is_active(boid) { + let pikmin_boma = app::sv_battle_object::module_accessor(boid); + let pikmin_variation = WorkModule::get_int( + pikmin_boma, + *WEAPON_PIKMIN_PIKMIN_INSTANCE_WORK_ID_INT_VARIATION, + ); + let pikmin_status = StatusModule::status_kind(pikmin_boma); + let pikmin_autonomy: bool = WorkModule::is_flag( + pikmin_boma, + *WEAPON_PIKMIN_PIKMIN_INSTANCE_WORK_ID_FLAG_AUTONOMY, + ); + // solution: + //WorkModule::off_flag(pikmin_boma, *WEAPON_PIKMIN_PIKMIN_INSTANCE_WORK_ID_FLAG_AUTONOMY); + let owner_cond = WorkModule::get_int( + pikmin_boma, + *WEAPON_PIKMIN_PIKMIN_INSTANCE_WORK_ID_INT_OWNER_CONDITION_CURRENT, + ); + let owner_cond_follow = WorkModule::get_int( + pikmin_boma, + *WEAPON_PIKMIN_PIKMIN_INSTANCE_WORK_ID_INT_OWNER_CONDITION_FOLLOW, + ); + let owner_opt_flag_follow = WorkModule::get_int( + pikmin_boma, + *WEAPON_PIKMIN_PIKMIN_INSTANCE_WORK_ID_INT_OWNER_OPTION_FLAG_FOLLOW, + ); + println!("Color: {}, Status: {}, Held {}, Autonomy: {}, owner_cond: {}, owner_cond_follow: {}, owner_opt_flag_follow: {}", + pikmin_variation, pikmin_status, held, pikmin_autonomy, owner_cond, owner_cond_follow, owner_opt_flag_follow + ); + } +} diff --git a/src/training/charge.rs b/src/training/charge.rs index a3202fb..abef0f3 100644 --- a/src/training/charge.rs +++ b/src/training/charge.rs @@ -1,3 +1,4 @@ +use crate::training::character_specific::pikmin; use serde::{Deserialize, Serialize}; use smash::app::{self, lua_bind::*, ArticleOperationTarget, FighterFacial, FighterUtil}; use smash::lib::lua_const::*; @@ -7,6 +8,7 @@ use smash::phx::{Hash40, Vector3f}; pub struct ChargeState { pub int_x: Option, pub int_y: Option, + pub int_z: Option, pub float_x: Option, pub float_y: Option, pub float_z: Option, @@ -39,6 +41,18 @@ impl ChargeState { self } + fn set_pikmin( + mut self, + pikmin_1: Option, + pikmin_2: Option, + pikmin_3: Option, + ) -> Self { + self.int_x = pikmin_1; + self.int_y = pikmin_2; + self.int_z = pikmin_3; + self + } + fn has_charge(mut self, has_charge: bool) -> Self { self.has_charge = Some(has_charge); self @@ -115,7 +129,10 @@ pub unsafe fn get_charge( } // Wario Waft else if fighter_kind == FIGHTER_KIND_WARIO { - let my_charge = WorkModule::get_int(module_accessor, 0x100000BF); // FIGHTER_WARIO_INSTANCE_WORK_ID_INT_GASS_COUNT + let my_charge = WorkModule::get_int( + module_accessor, + *FIGHTER_WARIO_INSTANCE_WORK_ID_INT_GASS_COUNT, + ); charge_state.int_x(my_charge) } // Squirtle Water Gun @@ -126,6 +143,11 @@ pub unsafe fn get_charge( ); charge_state.int_x(my_charge) } + // Olimar Pikmin + else if fighter_kind == FIGHTER_KIND_PIKMIN { + let pikmin_array = pikmin::get_current_pikmin(module_accessor); + return charge_state.set_pikmin(pikmin_array[0], pikmin_array[1], pikmin_array[2]); + } // Lucario Aura Sphere else if fighter_kind == FIGHTER_KIND_LUCARIO { let my_charge = WorkModule::get_int( @@ -174,7 +196,10 @@ pub unsafe fn get_charge( } // Pac-Man Bonus Fruit else if fighter_kind == FIGHTER_KIND_PACMAN { - let my_charge = WorkModule::get_int(module_accessor, 0x100000C1); // FIGHTER_PACMAN_INSTANCE_WORK_ID_INT_SPECIAL_N_CHARGE_RANK + let my_charge = WorkModule::get_int( + module_accessor, + *FIGHTER_PACMAN_INSTANCE_WORK_ID_INT_SPECIAL_N_CHARGE_RANK, + ); let fruit_have = WorkModule::is_flag( module_accessor, *FIGHTER_PACMAN_INSTANCE_WORK_ID_FLAG_SPECIAL_N_PULL_THROW, @@ -501,7 +526,11 @@ pub unsafe fn handle_charge( // Wario Waft - 0 to 6000 else if fighter_kind == FIGHTER_KIND_WARIO { charge.int_x.map(|waft_count| { - WorkModule::set_int(module_accessor, waft_count, 0x100000BF); // FIGHTER_WARIO_INSTANCE_WORK_ID_INT_GASS_COUNT + WorkModule::set_int( + module_accessor, + waft_count, + *FIGHTER_WARIO_INSTANCE_WORK_ID_INT_GASS_COUNT, + ); }); } // Squirtle Water Gun - 0 to 45 @@ -517,6 +546,36 @@ pub unsafe fn handle_charge( } }); } + // Olimar Pikmin - 0 to 4 + else if fighter_kind == FIGHTER_KIND_PIKMIN { + ArticleModule::remove_exist( + module_accessor, + *FIGHTER_PIKMIN_GENERATE_ARTICLE_PIKMIN, + app::ArticleOperationTarget(*ARTICLE_OPE_TARGET_ALL), + ); + if ArticleModule::get_active_num(module_accessor, *FIGHTER_PIKMIN_GENERATE_ARTICLE_PIKMIN) + == 0 + { + charge.int_x.map(|pikmin_1| { + pikmin::spawn_pikmin(module_accessor, pikmin_1); + }); + } + if ArticleModule::get_active_num(module_accessor, *FIGHTER_PIKMIN_GENERATE_ARTICLE_PIKMIN) + == 1 + { + charge.int_y.map(|pikmin_2| { + pikmin::spawn_pikmin(module_accessor, pikmin_2); + }); + } + if ArticleModule::get_active_num(module_accessor, *FIGHTER_PIKMIN_GENERATE_ARTICLE_PIKMIN) + == 2 + { + charge.int_z.map(|pikmin_3| { + pikmin::spawn_pikmin(module_accessor, pikmin_3); + }); + } + pikmin::follow(module_accessor); + } // Lucario Aura Sphere - 0 to 90, Boolean else if fighter_kind == FIGHTER_KIND_LUCARIO { charge.int_x.map(|charge_frame| { @@ -641,7 +700,11 @@ pub unsafe fn handle_charge( else if fighter_kind == FIGHTER_KIND_PACMAN { let mut has_key = false; charge.int_x.map(|charge_rank| { - WorkModule::set_int(module_accessor, charge_rank, 0x100000C1); // FIGHTER_PACMAN_INSTANCE_WORK_ID_INT_SPECIAL_N_CHARGE_RANK + WorkModule::set_int( + module_accessor, + charge_rank, + *FIGHTER_PACMAN_INSTANCE_WORK_ID_INT_SPECIAL_N_CHARGE_RANK, + ); if charge_rank == 12 { EffectModule::req_common(module_accessor, Hash40::new("charge_max"), 0.0); @@ -799,7 +862,10 @@ pub unsafe fn handle_charge( // Hero (Ka)frizz(le) - 0 to 81 else if fighter_kind == FIGHTER_KIND_BRAVE { EffectModule::remove_common(module_accessor, Hash40::new("charge_max")); - WorkModule::off_flag(module_accessor, 0x200000E8); // FIGHTER_BRAVE_INSTANCE_WORK_ID_FLAG_SPECIAL_N_MAX_EFFECT + WorkModule::off_flag( + module_accessor, + *FIGHTER_BRAVE_INSTANCE_WORK_ID_FLAG_SPECIAL_N_MAX_EFFECT, + ); charge.int_x.map(|frizz_charge| { WorkModule::set_int( module_accessor, diff --git a/src/training/mod.rs b/src/training/mod.rs index 4a1d15e..7ffb43b 100644 --- a/src/training/mod.rs +++ b/src/training/mod.rs @@ -7,7 +7,7 @@ use crate::common::{ use crate::hitbox_visualizer; use crate::input::*; use crate::logging::*; -use crate::training::character_specific::items; +use crate::training::character_specific::{items, pikmin}; use skyline::hooks::{getRegionAddress, InlineCtx, Region}; use skyline::nn::ro::LookupSymbol; use smash::app::{self, enSEType, lua_bind::*, utility}; @@ -680,6 +680,17 @@ pub unsafe fn handle_reused_ui( original!()(fighter_data, param_2) } +static ARTICLE_GET_INT_OFFSET: usize = 0x3d5920; + +#[skyline::hook(offset = ARTICLE_GET_INT_OFFSET)] +pub unsafe fn handle_article_get_int( + article_module: *mut app::BattleObjectModuleAccessor, // *mut ArticleModule + generate_article: i32, + address: i32, +) -> i32 { + original!()(article_module, generate_article, address) +} + // Instruction run on the completion of the CPU Control function static OPCF_OFFSET: usize = 0x06b7fdc; @@ -735,6 +746,15 @@ unsafe fn handle_final_input_mapping( input_record::handle_final_input_mapping(player_idx, out); } +static BOMA_OFFSET: usize = 0x15cf1b0; + +#[skyline::hook(offset = BOMA_OFFSET)] +pub unsafe fn handle_get_module_accessor( + battle_object_id: u32, +) -> *mut app::BattleObjectModuleAccessor { + original!()(battle_object_id) +} + pub fn training_mods() { info!("Applying training mods."); @@ -813,10 +833,14 @@ pub fn training_mods() { // Notifications handle_once_per_cpu_frame, // Input - handle_final_input_mapping + handle_final_input_mapping, + // Charge + handle_article_get_int, + handle_get_module_accessor, ); items::init(); input_record::init(); ui::init(); + pikmin::init(); } diff --git a/src/training/save_states.rs b/src/training/save_states.rs index afab02d..64e4693 100644 --- a/src/training/save_states.rs +++ b/src/training/save_states.rs @@ -34,7 +34,7 @@ use crate::training::reset; use crate::training::ui::notifications; use crate::{is_ptrainer, ITEM_MANAGER_ADDR}; -// Don't remove Mii hats, or Luma, or crafting table +// Don't remove Mii hats, Pikmin, Luma, or crafting table const ARTICLE_ALLOWLIST: [(LuaConst, LuaConst); 8] = [ ( FIGHTER_KIND_MIIFIGHTER, @@ -98,6 +98,7 @@ macro_rules! default_save_state { charge: ChargeState { int_x: None, int_y: None, + int_z: None, float_x: None, float_y: None, float_z: None, @@ -308,12 +309,11 @@ unsafe fn on_ptrainer_death(module_accessor: &mut app::BattleObjectModuleAccesso ptrainer_module_accessor, *WEAPON_PTRAINER_PTRAINER_GENERATE_ARTICLE_MBALL, ) { - let ptrainer_masterball: u64 = ArticleModule::get_article( + let ptrainer_masterball: *mut app::Article = ArticleModule::get_article( ptrainer_module_accessor, *WEAPON_PTRAINER_PTRAINER_GENERATE_ARTICLE_MBALL, ); - let ptrainer_masterball_id = - Article::get_battle_object_id(ptrainer_masterball as *mut app::Article); + let ptrainer_masterball_id = Article::get_battle_object_id(ptrainer_masterball); let ptrainer_masterball_module_accessor = &mut *app::sv_battle_object::module_accessor(ptrainer_masterball_id as u32); MotionModule::set_rate(ptrainer_masterball_module_accessor, 1000.0); @@ -339,8 +339,9 @@ unsafe fn on_death(fighter_kind: i32, module_accessor: &mut app::BattleObjectMod }) .for_each(|article_idx| { if ArticleModule::is_exist(module_accessor, article_idx) { - let article: u64 = ArticleModule::get_article(module_accessor, article_idx); - let article_object_id = Article::get_battle_object_id(article as *mut app::Article); + let article: *mut app::Article = + ArticleModule::get_article(module_accessor, article_idx); + let article_object_id = Article::get_battle_object_id(article); ArticleModule::remove_exist_object_id(module_accessor, article_object_id as u32); } }); diff --git a/training_mod_consts/src/options.rs b/training_mod_consts/src/options.rs index 3ed4ccd..cc82ab8 100644 --- a/training_mod_consts/src/options.rs +++ b/training_mod_consts/src/options.rs @@ -496,7 +496,6 @@ bitflags! { const U_TILT = 0x0010_0000; const D_TILT = 0x0020_0000; const GRAB = 0x0040_0000; - // TODO: Make work const DASH = 0x0080_0000; const DASH_ATTACK = 0x0100_0000; const PLAYBACK_1 = 0x0200_0000;