mirror of
https://github.com/jugeeya/UltimateTrainingModpack.git
synced 2024-11-28 04:44:06 +00:00
Pokemon Trainer: Save State Fix (#387)
* Initial; stay same pokemon, but still go through ball throw animation * Remove PTrainer ball throw animation * Merge with master * Needed import * Format Rust code using rustfmt Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This commit is contained in:
parent
d25583cda2
commit
7bbae26f35
3 changed files with 68 additions and 29 deletions
|
@ -9,7 +9,7 @@ crate-type = ["cdylib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
skyline = { git = "https://github.com/ultimate-research/skyline-rs.git" }
|
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/ultimate-research/skyline-smash.git", branch = "no-cache" }
|
||||||
skyline-web = { git = "https://github.com/skyline-rs/skyline-web.git" }
|
skyline-web = { git = "https://github.com/skyline-rs/skyline-web.git" }
|
||||||
bitflags = "1.2.1"
|
bitflags = "1.2.1"
|
||||||
parking_lot = { version = "0.12.0", features = ["nightly"] }
|
parking_lot = { version = "0.12.0", features = ["nightly"] }
|
||||||
|
|
|
@ -118,19 +118,21 @@ pub fn is_in_shieldstun(module_accessor: &mut app::BattleObjectModuleAccessor) -
|
||||||
&& status_kind == FIGHTER_STATUS_KIND_GUARD_OFF)
|
&& status_kind == FIGHTER_STATUS_KIND_GUARD_OFF)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn is_dead(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
|
pub unsafe fn is_ptrainer(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
|
||||||
let fighter_kind = app::utility::get_kind(module_accessor);
|
[
|
||||||
let fighter_is_ptrainer = [
|
|
||||||
*FIGHTER_KIND_PZENIGAME,
|
*FIGHTER_KIND_PZENIGAME,
|
||||||
*FIGHTER_KIND_PFUSHIGISOU,
|
*FIGHTER_KIND_PFUSHIGISOU,
|
||||||
*FIGHTER_KIND_PLIZARDON,
|
*FIGHTER_KIND_PLIZARDON,
|
||||||
]
|
]
|
||||||
.contains(&fighter_kind);
|
.contains(&app::utility::get_kind(module_accessor))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn is_dead(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
|
||||||
let status_kind = StatusModule::status_kind(module_accessor) as i32;
|
let status_kind = StatusModule::status_kind(module_accessor) as i32;
|
||||||
let prev_status_kind = StatusModule::prev_status_kind(module_accessor, 0);
|
let prev_status_kind = StatusModule::prev_status_kind(module_accessor, 0);
|
||||||
// Pokemon trainer enters FIGHTER_STATUS_KIND_WAIT for one frame during their respawn animation
|
// Pokemon trainer enters FIGHTER_STATUS_KIND_WAIT for one frame during their respawn animation
|
||||||
// And the previous status is FIGHTER_STATUS_NONE
|
// And the previous status is FIGHTER_STATUS_NONE
|
||||||
if fighter_is_ptrainer {
|
if is_ptrainer(module_accessor) {
|
||||||
[*FIGHTER_STATUS_KIND_DEAD, *FIGHTER_STATUS_KIND_STANDBY].contains(&status_kind)
|
[*FIGHTER_STATUS_KIND_DEAD, *FIGHTER_STATUS_KIND_STANDBY].contains(&status_kind)
|
||||||
|| (status_kind == FIGHTER_STATUS_KIND_WAIT
|
|| (status_kind == FIGHTER_STATUS_KIND_WAIT
|
||||||
&& prev_status_kind == FIGHTER_STATUS_KIND_NONE)
|
&& prev_status_kind == FIGHTER_STATUS_KIND_NONE)
|
||||||
|
|
|
@ -76,7 +76,7 @@ macro_rules! default_save_state {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
use crate::ITEM_MANAGER_ADDR;
|
use crate::{get_module_accessor, is_ptrainer, ITEM_MANAGER_ADDR};
|
||||||
use SaveState::*;
|
use SaveState::*;
|
||||||
|
|
||||||
static mut SAVE_STATE_PLAYER: SavedState = default_save_state!();
|
static mut SAVE_STATE_PLAYER: SavedState = default_save_state!();
|
||||||
|
@ -124,6 +124,9 @@ pub unsafe fn get_param_int(
|
||||||
if param_hash == hash40("rebirth_move_frame") {
|
if param_hash == hash40("rebirth_move_frame") {
|
||||||
return Some(0);
|
return Some(0);
|
||||||
}
|
}
|
||||||
|
if param_hash == hash40("rebirth_move_frame_trainer") {
|
||||||
|
return Some(0);
|
||||||
|
}
|
||||||
if param_hash == hash40("rebirth_wait_frame") {
|
if param_hash == hash40("rebirth_wait_frame") {
|
||||||
return Some(0);
|
return Some(0);
|
||||||
}
|
}
|
||||||
|
@ -134,6 +137,11 @@ pub unsafe fn get_param_int(
|
||||||
return Some(0);
|
return Some(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if param_type == hash40("param_mball") {
|
||||||
|
if param_hash == hash40("change_fly_frame") {
|
||||||
|
return Some(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -159,6 +167,40 @@ fn set_damage(module_accessor: &mut app::BattleObjectModuleAccessor, damage: f32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe fn get_ptrainer_module_accessor(
|
||||||
|
module_accessor: &mut app::BattleObjectModuleAccessor,
|
||||||
|
) -> &mut app::BattleObjectModuleAccessor {
|
||||||
|
let ptrainer_object_id =
|
||||||
|
LinkModule::get_parent_object_id(module_accessor, *FIGHTER_POKEMON_LINK_NO_PTRAINER);
|
||||||
|
&mut *app::sv_battle_object::module_accessor(ptrainer_object_id as u32)
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn on_ptrainer_death(module_accessor: &mut app::BattleObjectModuleAccessor) {
|
||||||
|
if !is_ptrainer(module_accessor) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
WorkModule::off_flag(
|
||||||
|
get_ptrainer_module_accessor(module_accessor),
|
||||||
|
*WEAPON_PTRAINER_PTRAINER_INSTANCE_WORK_ID_FLAG_ENABLE_CHANGE_POKEMON,
|
||||||
|
);
|
||||||
|
let ptrainer_module_accessor = get_ptrainer_module_accessor(module_accessor);
|
||||||
|
MotionModule::set_rate(ptrainer_module_accessor, 1000.0);
|
||||||
|
if ArticleModule::is_exist(
|
||||||
|
ptrainer_module_accessor,
|
||||||
|
*WEAPON_PTRAINER_PTRAINER_GENERATE_ARTICLE_MBALL,
|
||||||
|
) {
|
||||||
|
let ptrainer_masterball: u64 = 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_module_accessor =
|
||||||
|
&mut *app::sv_battle_object::module_accessor(ptrainer_masterball_id as u32);
|
||||||
|
MotionModule::set_rate(ptrainer_masterball_module_accessor, 1000.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub unsafe fn save_states(module_accessor: &mut app::BattleObjectModuleAccessor) {
|
pub unsafe fn save_states(module_accessor: &mut app::BattleObjectModuleAccessor) {
|
||||||
if MENU.save_state_enable == OnOff::Off {
|
if MENU.save_state_enable == OnOff::Off {
|
||||||
return;
|
return;
|
||||||
|
@ -174,14 +216,9 @@ pub unsafe fn save_states(module_accessor: &mut app::BattleObjectModuleAccessor)
|
||||||
};
|
};
|
||||||
|
|
||||||
let fighter_kind = app::utility::get_kind(module_accessor);
|
let fighter_kind = app::utility::get_kind(module_accessor);
|
||||||
let fighter_is_ptrainer = [
|
let fighter_is_ptrainer = is_ptrainer(module_accessor);
|
||||||
*FIGHTER_KIND_PZENIGAME,
|
|
||||||
*FIGHTER_KIND_PFUSHIGISOU,
|
|
||||||
*FIGHTER_KIND_PLIZARDON,
|
|
||||||
]
|
|
||||||
.contains(&fighter_kind);
|
|
||||||
let fighter_is_popo = fighter_kind == *FIGHTER_KIND_POPO; // For making sure Popo doesn't steal Nana's PosMove
|
let fighter_is_popo = fighter_kind == *FIGHTER_KIND_POPO; // For making sure Popo doesn't steal Nana's PosMove
|
||||||
let fighter_is_nana = fighter_kind == *FIGHTER_KIND_NANA; // Don't want Nana to reopen savestates etc.
|
let fighter_is_nana = fighter_kind == *FIGHTER_KIND_NANA; // Don't want Nana to reopen save states etc.
|
||||||
let fighter_is_buffable = [
|
let fighter_is_buffable = [
|
||||||
*FIGHTER_KIND_BRAVE,
|
*FIGHTER_KIND_BRAVE,
|
||||||
*FIGHTER_KIND_CLOUD,
|
*FIGHTER_KIND_CLOUD,
|
||||||
|
@ -193,14 +230,13 @@ pub unsafe fn save_states(module_accessor: &mut app::BattleObjectModuleAccessor)
|
||||||
.contains(&fighter_kind);
|
.contains(&fighter_kind);
|
||||||
|
|
||||||
// Grab + Dpad up: reset state
|
// Grab + Dpad up: reset state
|
||||||
if (MENU.save_state_autoload == OnOff::On
|
let autoload_reset = MENU.save_state_autoload == OnOff::On
|
||||||
&& !fighter_is_ptrainer
|
|
||||||
&& save_state.state == NoAction
|
&& save_state.state == NoAction
|
||||||
&& is_dead(module_accessor))
|
&& is_dead(module_accessor);
|
||||||
|| (ControlModule::check_button_on(module_accessor, *CONTROL_PAD_BUTTON_CATCH)
|
let triggered_reset =
|
||||||
&& ControlModule::check_button_trigger(module_accessor, *CONTROL_PAD_BUTTON_APPEAL_HI))
|
ControlModule::check_button_on(module_accessor, *CONTROL_PAD_BUTTON_CATCH)
|
||||||
&& !fighter_is_nana
|
&& ControlModule::check_button_trigger(module_accessor, *CONTROL_PAD_BUTTON_APPEAL_HI);
|
||||||
{
|
if (autoload_reset || triggered_reset) && !fighter_is_nana {
|
||||||
if save_state.state == NoAction {
|
if save_state.state == NoAction {
|
||||||
SAVE_STATE_PLAYER.state = KillPlayer;
|
SAVE_STATE_PLAYER.state = KillPlayer;
|
||||||
SAVE_STATE_CPU.state = KillPlayer;
|
SAVE_STATE_CPU.state = KillPlayer;
|
||||||
|
@ -211,15 +247,10 @@ pub unsafe fn save_states(module_accessor: &mut app::BattleObjectModuleAccessor)
|
||||||
|
|
||||||
// move to camera bounds
|
// move to camera bounds
|
||||||
if save_state.state == KillPlayer {
|
if save_state.state == KillPlayer {
|
||||||
|
on_ptrainer_death(module_accessor);
|
||||||
SoundModule::stop_all_sound(module_accessor);
|
SoundModule::stop_all_sound(module_accessor);
|
||||||
if status == FIGHTER_STATUS_KIND_REBIRTH {
|
if status == FIGHTER_STATUS_KIND_REBIRTH {
|
||||||
if !(fighter_is_ptrainer
|
save_state.state = PosMove;
|
||||||
&& save_state.fighter_kind > 0
|
|
||||||
&& fighter_kind != save_state.fighter_kind)
|
|
||||||
{
|
|
||||||
// For ptrainer, don't move on unless we're cycled back to the right pokemon
|
|
||||||
save_state.state = PosMove;
|
|
||||||
}
|
|
||||||
} else if !is_dead(module_accessor) && !fighter_is_nana {
|
} else if !is_dead(module_accessor) && !fighter_is_nana {
|
||||||
// Don't kill Nana again, since she already gets killed by the game from Popo's death
|
// Don't kill Nana again, since she already gets killed by the game from Popo's death
|
||||||
// Try moving off-screen so we don't see effects.
|
// Try moving off-screen so we don't see effects.
|
||||||
|
@ -236,7 +267,7 @@ pub unsafe fn save_states(module_accessor: &mut app::BattleObjectModuleAccessor)
|
||||||
if item != 0 {
|
if item != 0 {
|
||||||
let item = item as *mut Item;
|
let item = item as *mut Item;
|
||||||
let item_battle_object_id =
|
let item_battle_object_id =
|
||||||
smash::app::lua_bind::Item::get_battle_object_id(item) as u32;
|
app::lua_bind::Item::get_battle_object_id(item) as u32;
|
||||||
ItemManager::remove_item_from_id(item_mgr, item_battle_object_id);
|
ItemManager::remove_item_from_id(item_mgr, item_battle_object_id);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -358,6 +389,12 @@ pub unsafe fn save_states(module_accessor: &mut app::BattleObjectModuleAccessor)
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if fighter_is_ptrainer {
|
||||||
|
WorkModule::on_flag(
|
||||||
|
get_ptrainer_module_accessor(module_accessor),
|
||||||
|
*WEAPON_PTRAINER_PTRAINER_INSTANCE_WORK_ID_FLAG_ENABLE_CHANGE_POKEMON,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the fighter is Popo, change the state to one where only Nana can move
|
// if the fighter is Popo, change the state to one where only Nana can move
|
||||||
|
|
Loading…
Reference in a new issue