mirror of
https://github.com/jugeeya/UltimateTrainingModpack.git
synced 2024-11-24 10:54:16 +00:00
parent
bf08bcb19a
commit
c82cd073f4
10 changed files with 360 additions and 89 deletions
8
.github/workflows/rust.yml
vendored
8
.github/workflows/rust.yml
vendored
|
@ -86,17 +86,11 @@ jobs:
|
||||||
wget https://github.com/ultimate-research/params-hook-plugin/releases/download/v0.1.1/libparam_hook.nro
|
wget https://github.com/ultimate-research/params-hook-plugin/releases/download/v0.1.1/libparam_hook.nro
|
||||||
wget https://github.com/ultimate-research/nro-hook-plugin/releases/download/v0.1.1/libnro_hook.nro
|
wget https://github.com/ultimate-research/nro-hook-plugin/releases/download/v0.1.1/libnro_hook.nro
|
||||||
wget https://github.com/jugeeya/nn-hid-hook/releases/download/beta/libnn_hid_hook.nro
|
wget https://github.com/jugeeya/nn-hid-hook/releases/download/beta/libnn_hid_hook.nro
|
||||||
wget https://github.com/blu-dev/smash-visualizer/releases/download/0.1.0/Smash-Visualizer-0.1.0.zip
|
|
||||||
cp libparam_hook.nro ${{env.SMASH_PLUGIN_DIR}}/libparam_hook.nro
|
cp libparam_hook.nro ${{env.SMASH_PLUGIN_DIR}}/libparam_hook.nro
|
||||||
cp libnro_hook.nro ${{env.SMASH_PLUGIN_DIR}}/libnro_hook.nro
|
cp libnro_hook.nro ${{env.SMASH_PLUGIN_DIR}}/libnro_hook.nro
|
||||||
cp libnn_hid_hook.nro ${{env.SMASH_PLUGIN_DIR}}/libnn_hid_hook.nro
|
cp libnn_hid_hook.nro ${{env.SMASH_PLUGIN_DIR}}/libnn_hid_hook.nro
|
||||||
unzip -o Smash-Visualizer-0.1.0.zip
|
|
||||||
ls
|
|
||||||
#cp Smash-Visualizer/${{env.SMASH_PLUGIN_DIR}}/visualizer.nro ${{env.SMASH_PLUGIN_DIR}}/visualizer.nro
|
|
||||||
#cp Smash-Visualizer/colors.json colors.json
|
|
||||||
|
|
||||||
ls -1 svg/*.svg | xargs -n 1 basename | xargs -L1 -I{} cp svg/{} ${{env.SMASH_WEB_DIR}}/{}
|
ls -1 svg/*.svg | xargs -n 1 basename | xargs -L1 -I{} cp svg/{} ${{env.SMASH_WEB_DIR}}/{}
|
||||||
zip -r training_modpack_beta.zip atmosphere colors.json
|
zip -r training_modpack_beta.zip atmosphere
|
||||||
- name: Update Release
|
- name: Update Release
|
||||||
uses: meeDamian/github-release@2.0
|
uses: meeDamian/github-release@2.0
|
||||||
with:
|
with:
|
||||||
|
|
|
@ -79,25 +79,6 @@ pub fn random_option<T>(arg: &[T]) -> &T {
|
||||||
&arg[get_random_int(arg.len() as i32) as usize]
|
&arg[get_random_int(arg.len() as i32) as usize]
|
||||||
}
|
}
|
||||||
|
|
||||||
bitflags! {
|
|
||||||
pub struct VisualizationFlags : u32 {
|
|
||||||
const HITBOX_VIS = 0x1;
|
|
||||||
const HURTBOX_VIS = 0x2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl VisualizationFlags {
|
|
||||||
fn into_string(self) -> String {
|
|
||||||
match self {
|
|
||||||
VisualizationFlags::HITBOX_VIS => "Hitbox Visualization",
|
|
||||||
VisualizationFlags::HURTBOX_VIS => "Hurtbox Visualization",
|
|
||||||
_ => "",
|
|
||||||
}.to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extra_bitflag_impls! {VisualizationFlags}
|
|
||||||
|
|
||||||
// DI
|
// DI
|
||||||
/*
|
/*
|
||||||
0, 0.785398, 1.570796, 2.356194, -3.14159, -2.356194, -1.570796, -0.785398
|
0, 0.785398, 1.570796, 2.356194, -3.14159, -2.356194, -1.570796, -0.785398
|
||||||
|
@ -730,7 +711,7 @@ macro_rules! url_params {
|
||||||
url_params! {
|
url_params! {
|
||||||
#[derive(Clone, Copy, )]
|
#[derive(Clone, Copy, )]
|
||||||
pub struct TrainingModpackMenu {
|
pub struct TrainingModpackMenu {
|
||||||
pub visualization: VisualizationFlags,
|
pub hitbox_vis: OnOff,
|
||||||
pub stage_hazards: OnOff,
|
pub stage_hazards: OnOff,
|
||||||
pub di_state: Direction,
|
pub di_state: Direction,
|
||||||
pub sdi_state: Direction,
|
pub sdi_state: Direction,
|
||||||
|
@ -784,7 +765,7 @@ impl TrainingModpackMenu {
|
||||||
(fast_fall = BoolFlag::from_bits(val))
|
(fast_fall = BoolFlag::from_bits(val))
|
||||||
(follow_up = Action::from_bits(val))
|
(follow_up = Action::from_bits(val))
|
||||||
(full_hop = BoolFlag::from_bits(val))
|
(full_hop = BoolFlag::from_bits(val))
|
||||||
(visualization = VisualizationFlags::from_bits(val))
|
(hitbox_vis = OnOff::from_val(val))
|
||||||
(input_delay = Some(val as i32))
|
(input_delay = Some(val as i32))
|
||||||
(ledge_delay = LongDelay::from_bits(val))
|
(ledge_delay = LongDelay::from_bits(val))
|
||||||
(ledge_state = LedgeOption::from_bits(val))
|
(ledge_state = LedgeOption::from_bits(val))
|
||||||
|
|
|
@ -299,7 +299,7 @@ pub unsafe fn write_menu() {
|
||||||
);
|
);
|
||||||
|
|
||||||
add_onoff_submenu!(overall_menu, "Save Damage", save_damage, "Save Damage: Should save states retain player/CPU damage");
|
add_onoff_submenu!(overall_menu, "Save Damage", save_damage, "Save Damage: Should save states retain player/CPU damage");
|
||||||
add_bitflag_submenu!(overall_menu, "Visualization", visualization, VisualizationFlags, "Visualization: Should hitboxes and/or hurtboxes be displayed.");
|
add_onoff_submenu!(overall_menu, "Hitbox Visualization", hitbox_vis, "Hitbox Visualization: Should hitboxes be displayed, hiding other visual effects");
|
||||||
add_onoff_submenu!(overall_menu, "Stage Hazards", stage_hazards, "Stage Hazards: Should stage hazards be present");
|
add_onoff_submenu!(overall_menu, "Stage Hazards", stage_hazards, "Stage Hazards: Should stage hazards be present");
|
||||||
add_onoff_submenu!(overall_menu, "Frame Advantage", frame_advantage, "Frame Advantage: Display the time difference between when the player is actionable and the CPU is actionable");
|
add_onoff_submenu!(overall_menu, "Frame Advantage", frame_advantage, "Frame Advantage: Display the time difference between when the player is actionable and the CPU is actionable");
|
||||||
add_onoff_submenu!(overall_menu, "Mash In Neutral", mash_in_neutral, "Mash In Neutral: Should Mash options be performed repeatedly or only when the CPU is hit");
|
add_onoff_submenu!(overall_menu, "Mash In Neutral", mash_in_neutral, "Mash In Neutral: Should Mash options be performed repeatedly or only when the CPU is hit");
|
||||||
|
|
|
@ -9,7 +9,7 @@ use smash::hash40;
|
||||||
use smash::lib::lua_const::*;
|
use smash::lib::lua_const::*;
|
||||||
|
|
||||||
pub static DEFAULT_MENU: consts::TrainingModpackMenu = consts::TrainingModpackMenu {
|
pub static DEFAULT_MENU: consts::TrainingModpackMenu = consts::TrainingModpackMenu {
|
||||||
visualization: VisualizationFlags::all(),
|
hitbox_vis: OnOff::On,
|
||||||
stage_hazards: OnOff::Off,
|
stage_hazards: OnOff::Off,
|
||||||
di_state: Direction::empty(),
|
di_state: Direction::empty(),
|
||||||
sdi_state: Direction::empty(),
|
sdi_state: Direction::empty(),
|
||||||
|
|
344
src/hitbox_visualizer/mod.rs
Normal file
344
src/hitbox_visualizer/mod.rs
Normal file
|
@ -0,0 +1,344 @@
|
||||||
|
use crate::common::{consts::*, *};
|
||||||
|
use smash::app::{self, lua_bind::*, sv_animcmd, sv_system};
|
||||||
|
use smash::lib::{lua_const::*, L2CAgent, L2CValue};
|
||||||
|
use smash::phx::{Hash40, Vector3f};
|
||||||
|
|
||||||
|
pub const ID_COLORS: &[Vector3f] = &[
|
||||||
|
// used to tint the hitbox effects -- make sure that at least one component
|
||||||
|
// is equal to 1.0
|
||||||
|
Vector3f {
|
||||||
|
x: 1.0,
|
||||||
|
y: 0.0,
|
||||||
|
z: 0.0,
|
||||||
|
}, // #ff0000 (red)
|
||||||
|
Vector3f {
|
||||||
|
x: 1.0,
|
||||||
|
y: 0.4,
|
||||||
|
z: 0.0,
|
||||||
|
}, // #ff9900 (orange)
|
||||||
|
Vector3f {
|
||||||
|
x: 0.8,
|
||||||
|
y: 1.0,
|
||||||
|
z: 0.0,
|
||||||
|
}, // #ccff00 (yellow)
|
||||||
|
Vector3f {
|
||||||
|
x: 0.2,
|
||||||
|
y: 1.0,
|
||||||
|
z: 0.2,
|
||||||
|
}, // #00ff33 (green)
|
||||||
|
Vector3f {
|
||||||
|
x: 0.0,
|
||||||
|
y: 0.8,
|
||||||
|
z: 1.0,
|
||||||
|
}, // #00ccff (sky blue)
|
||||||
|
Vector3f {
|
||||||
|
x: 0.4,
|
||||||
|
y: 0.4,
|
||||||
|
z: 1.0,
|
||||||
|
}, // #6666ff (blue)
|
||||||
|
Vector3f {
|
||||||
|
x: 0.8,
|
||||||
|
y: 0.0,
|
||||||
|
z: 1.0,
|
||||||
|
}, // #cc00ff (purple)
|
||||||
|
Vector3f {
|
||||||
|
x: 1.0,
|
||||||
|
y: 0.2,
|
||||||
|
z: 0.8,
|
||||||
|
}, // #ff33cc (pink)
|
||||||
|
];
|
||||||
|
const MAX_EFFECTS_PER_HITBOX: i32 = 16; // max # of circles drawn for an extended hitbox
|
||||||
|
|
||||||
|
pub unsafe fn generate_hitbox_effects(
|
||||||
|
module_accessor: &mut app::BattleObjectModuleAccessor,
|
||||||
|
bone: u64,
|
||||||
|
size: f32,
|
||||||
|
center: Vector3f,
|
||||||
|
capsule_center: Option<Vector3f>,
|
||||||
|
color: Vector3f,
|
||||||
|
) {
|
||||||
|
let size_mult = 19.0 / 200.0;
|
||||||
|
|
||||||
|
let (x,y,z) = (center.x, center.y, center.z);
|
||||||
|
|
||||||
|
let x_dist: f32;
|
||||||
|
let y_dist: f32;
|
||||||
|
let z_dist: f32;
|
||||||
|
let mut n_effects: i32;
|
||||||
|
if let Some(capsule_center) = capsule_center {
|
||||||
|
let (x2,y2,z2) = (capsule_center.x, capsule_center.y, capsule_center.z);
|
||||||
|
x_dist = x2 - x;
|
||||||
|
y_dist = y2 - y;
|
||||||
|
z_dist = z2 - z;
|
||||||
|
let dist_sq: f32 = x_dist * x_dist + y_dist * y_dist + z_dist * z_dist;
|
||||||
|
let dist = dist_sq.sqrt();
|
||||||
|
n_effects = ((dist / (size * 1.75)) + 1.0).ceil() as i32; // just enough effects to form a continuous line
|
||||||
|
if n_effects < 2 {
|
||||||
|
n_effects = 2;
|
||||||
|
} else if n_effects > MAX_EFFECTS_PER_HITBOX {
|
||||||
|
n_effects = MAX_EFFECTS_PER_HITBOX;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
x_dist = 0.0;
|
||||||
|
y_dist = 0.0;
|
||||||
|
z_dist = 0.0;
|
||||||
|
n_effects = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in 0..n_effects {
|
||||||
|
let t = if n_effects > 1 {
|
||||||
|
(i as f32) / ((n_effects - 1) as f32)
|
||||||
|
} else {
|
||||||
|
0.0
|
||||||
|
};
|
||||||
|
let x_curr = x + x_dist * t;
|
||||||
|
let y_curr = y + y_dist * t;
|
||||||
|
let z_curr = z + z_dist * t;
|
||||||
|
|
||||||
|
let pos = Vector3f {
|
||||||
|
x: x_curr,
|
||||||
|
y: y_curr,
|
||||||
|
z: z_curr,
|
||||||
|
};
|
||||||
|
let zeros = Vector3f {
|
||||||
|
x: 0.0,
|
||||||
|
y: 0.0,
|
||||||
|
z: 0.0,
|
||||||
|
};
|
||||||
|
|
||||||
|
if false {
|
||||||
|
// is_fighter(module_accessor) {
|
||||||
|
EffectModule::req_on_joint(
|
||||||
|
module_accessor,
|
||||||
|
Hash40::new("sys_shield"),
|
||||||
|
Hash40::new_raw(bone),
|
||||||
|
&pos,
|
||||||
|
&zeros,
|
||||||
|
size * size_mult,
|
||||||
|
&zeros,
|
||||||
|
&zeros,
|
||||||
|
true,
|
||||||
|
*EFFECT_SUB_ATTRIBUTE_NO_JOINT_SCALE as u32
|
||||||
|
| *EFFECT_SUB_ATTRIBUTE_FOLLOW as u32
|
||||||
|
| *EFFECT_SUB_ATTRIBUTE_CONCLUDE_STATUS as u32,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
EffectModule::req_follow(
|
||||||
|
module_accessor,
|
||||||
|
Hash40::new("sys_shield"),
|
||||||
|
Hash40::new_raw(bone),
|
||||||
|
&pos,
|
||||||
|
&zeros,
|
||||||
|
size * size_mult,
|
||||||
|
true,
|
||||||
|
*EFFECT_SUB_ATTRIBUTE_NO_JOINT_SCALE as u32
|
||||||
|
| *EFFECT_SUB_ATTRIBUTE_FOLLOW as u32
|
||||||
|
| *EFFECT_SUB_ATTRIBUTE_CONCLUDE_STATUS as u32,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set to hitbox ID color
|
||||||
|
EffectModule::set_rgb_partial_last(module_accessor, color.x, color.y, color.z);
|
||||||
|
|
||||||
|
// speed up animation by rate to remove pulsing effect
|
||||||
|
EffectModule::set_rate_last(module_accessor, 8.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn get_command_flag_cat(module_accessor: &mut app::BattleObjectModuleAccessor) {
|
||||||
|
// Resume Effect AnimCMD incase we don't display hitboxes
|
||||||
|
MotionAnimcmdModule::set_sleep_effect(module_accessor, false);
|
||||||
|
|
||||||
|
if MENU.hitbox_vis == OnOff::Off {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let status_kind = StatusModule::status_kind(module_accessor) as i32;
|
||||||
|
if (*FIGHTER_STATUS_KIND_CATCH..=*FIGHTER_STATUS_KIND_CATCH_TURN).contains(&status_kind) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if is_shielding(module_accessor) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pause Effect AnimCMD if hitbox visualization is active
|
||||||
|
// Keep effects on for missed tech effect
|
||||||
|
MotionAnimcmdModule::set_sleep_effect(module_accessor, status_kind != FIGHTER_STATUS_KIND_DOWN);
|
||||||
|
|
||||||
|
EffectModule::set_visible_kind(module_accessor, Hash40::new("sys_shield"), false);
|
||||||
|
EffectModule::kill_kind(module_accessor, Hash40::new("sys_shield"), false, true);
|
||||||
|
for i in 0..8 {
|
||||||
|
if !AttackModule::is_attack(module_accessor, i, false) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let attack_data = *AttackModule::attack_data(module_accessor, i, false);
|
||||||
|
let center = Vector3f{x: attack_data.x, y: attack_data.y, z: attack_data.z};
|
||||||
|
let is_capsule = attack_data.x2 != 0.0 || attack_data.y2 != 0.0 || attack_data.z2 != 0.0;
|
||||||
|
let capsule_center = if is_capsule {
|
||||||
|
Some(Vector3f{x: attack_data.x2, y: attack_data.y2, z: attack_data.z2})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
generate_hitbox_effects(
|
||||||
|
module_accessor,
|
||||||
|
attack_data.node, // joint
|
||||||
|
attack_data.size,
|
||||||
|
center,
|
||||||
|
capsule_center,
|
||||||
|
ID_COLORS[(i % 8) as usize],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Necessary to ensure we visualize on the first frame of the hitbox
|
||||||
|
#[skyline::hook(replace = sv_animcmd::ATTACK)]
|
||||||
|
unsafe fn handle_attack(lua_state: u64) {
|
||||||
|
if is_training_mode() {
|
||||||
|
mod_handle_attack(lua_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
original!()(lua_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn mod_handle_attack(lua_state: u64) {
|
||||||
|
let mut l2c_agent = L2CAgent::new(lua_state);
|
||||||
|
|
||||||
|
// necessary if param object fails
|
||||||
|
// hacky way of forcing no shield damage on all hitboxes
|
||||||
|
if MENU.shield_state == Shield::Infinite {
|
||||||
|
let mut hitbox_params: Vec<L2CValue> =
|
||||||
|
(0..36).map(|i| l2c_agent.pop_lua_stack(i + 1)).collect();
|
||||||
|
l2c_agent.clear_lua_stack();
|
||||||
|
for (i, mut x) in hitbox_params.iter_mut().enumerate().take(36) {
|
||||||
|
if i == 20 {
|
||||||
|
l2c_agent.push_lua_stack(&mut L2CValue::new_num(-999.0));
|
||||||
|
} else {
|
||||||
|
l2c_agent.push_lua_stack(&mut x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hitbox Visualization
|
||||||
|
if MENU.hitbox_vis == OnOff::On {
|
||||||
|
// get all necessary grabbox params
|
||||||
|
let id = l2c_agent.pop_lua_stack(1); // int
|
||||||
|
let joint = l2c_agent.pop_lua_stack(3); // hash40
|
||||||
|
let _damage = l2c_agent.pop_lua_stack(4); // float
|
||||||
|
let _angle = l2c_agent.pop_lua_stack(5); // int
|
||||||
|
let _kbg = l2c_agent.pop_lua_stack(6); // int
|
||||||
|
let _fkb = l2c_agent.pop_lua_stack(7); // int
|
||||||
|
let _bkb = l2c_agent.pop_lua_stack(8); // int
|
||||||
|
let size = l2c_agent.pop_lua_stack(9); // float
|
||||||
|
let x = l2c_agent.pop_lua_stack(10); // float
|
||||||
|
let y = l2c_agent.pop_lua_stack(11); // float
|
||||||
|
let z = l2c_agent.pop_lua_stack(12); // float
|
||||||
|
let x2 = l2c_agent.pop_lua_stack(13); // float or void
|
||||||
|
let y2 = l2c_agent.pop_lua_stack(14); // float or void
|
||||||
|
let z2 = l2c_agent.pop_lua_stack(15); // float or void
|
||||||
|
|
||||||
|
let center = Vector3f{x: x.get_num(), y: y.get_num(), z: z.get_num()};
|
||||||
|
let capsule_center =
|
||||||
|
if let (Some(x2), Some(y2), Some(z2)) = (x2.try_get_num(), y2.try_get_num(), z2.try_get_num()) {
|
||||||
|
Some(Vector3f{x: x2, y: y2, z: z2})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
generate_hitbox_effects(
|
||||||
|
sv_system::battle_object_module_accessor(lua_state),
|
||||||
|
joint.get_int(),
|
||||||
|
size.get_num(),
|
||||||
|
center,
|
||||||
|
capsule_center,
|
||||||
|
ID_COLORS[(id.get_int() % 8) as usize],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[skyline::hook(replace = sv_animcmd::CATCH)]
|
||||||
|
unsafe fn handle_catch(lua_state: u64) {
|
||||||
|
if is_training_mode() {
|
||||||
|
mod_handle_catch(lua_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
original!()(lua_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn mod_handle_catch(lua_state: u64) {
|
||||||
|
if MENU.hitbox_vis == OnOff::Off {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get all necessary grabbox params
|
||||||
|
let mut l2c_agent = L2CAgent::new(lua_state);
|
||||||
|
let id = l2c_agent.pop_lua_stack(1); // int
|
||||||
|
let joint = l2c_agent.pop_lua_stack(2); // hash40
|
||||||
|
let size = l2c_agent.pop_lua_stack(3); // float
|
||||||
|
let x = l2c_agent.pop_lua_stack(4); // float
|
||||||
|
let y = l2c_agent.pop_lua_stack(5); // float
|
||||||
|
let z = l2c_agent.pop_lua_stack(6); // float
|
||||||
|
let x2 = l2c_agent.pop_lua_stack(7); // float or void
|
||||||
|
let y2 = l2c_agent.pop_lua_stack(8); // float or void
|
||||||
|
let z2 = l2c_agent.pop_lua_stack(9); // float or void
|
||||||
|
|
||||||
|
let center = Vector3f{x: x.get_num(), y: y.get_num(), z: z.get_num()};
|
||||||
|
let capsule_center =
|
||||||
|
if let (Some(x2), Some(y2), Some(z2)) = (x2.try_get_num(), y2.try_get_num(), z2.try_get_num()) {
|
||||||
|
Some(Vector3f{x: x2, y: y2, z: z2})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
generate_hitbox_effects(
|
||||||
|
sv_system::battle_object_module_accessor(lua_state),
|
||||||
|
joint.get_int(),
|
||||||
|
size.get_num(),
|
||||||
|
center,
|
||||||
|
capsule_center,
|
||||||
|
ID_COLORS[(id.get_int() + 3 % 8) as usize],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[skyline::hook(replace = GrabModule::set_rebound)]
|
||||||
|
pub unsafe fn handle_set_rebound(
|
||||||
|
module_accessor: *mut app::BattleObjectModuleAccessor,
|
||||||
|
rebound: bool,
|
||||||
|
) {
|
||||||
|
if is_training_mode() {
|
||||||
|
mod_handle_handle_set_rebound(module_accessor, rebound);
|
||||||
|
}
|
||||||
|
|
||||||
|
original!()(module_accessor, rebound);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn mod_handle_handle_set_rebound(
|
||||||
|
module_accessor: *mut app::BattleObjectModuleAccessor,
|
||||||
|
rebound: bool,
|
||||||
|
) {
|
||||||
|
if rebound {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// only if we're not shielding
|
||||||
|
if is_shielding(module_accessor) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
EffectModule::set_visible_kind(module_accessor, Hash40::new("sys_shield"), false);
|
||||||
|
EffectModule::kill_kind(module_accessor, Hash40::new("sys_shield"), false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hitbox_visualization() {
|
||||||
|
println!("[Training Modpack] Applying hitbox visualization mods.");
|
||||||
|
skyline::install_hooks!(handle_attack, handle_catch, handle_set_rebound);
|
||||||
|
}
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
pub mod common;
|
pub mod common;
|
||||||
mod hazard_manager;
|
mod hazard_manager;
|
||||||
|
mod hitbox_visualizer;
|
||||||
mod training;
|
mod training;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -58,6 +59,7 @@ pub fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
log!("Initialized.");
|
log!("Initialized.");
|
||||||
|
hitbox_visualizer::hitbox_visualization();
|
||||||
hazard_manager::hazard_manager();
|
hazard_manager::hazard_manager();
|
||||||
training::training_mods();
|
training::training_mods();
|
||||||
nro::add_hook(nro_main).unwrap();
|
nro::add_hook(nro_main).unwrap();
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
viewBox="0 0 80.0 80.0"
|
viewBox="0 0 80.0 80.0"
|
||||||
version="1.1"
|
version="1.1"
|
||||||
id="SVGRoot"
|
id="SVGRoot"
|
||||||
sodipodi:docname="visualization.svg"
|
sodipodi:docname="hitbox_vis.svg"
|
||||||
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)">
|
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)">
|
||||||
<defs
|
<defs
|
||||||
id="defs2223" />
|
id="defs2223" />
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
|
@ -1,7 +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, STAGE_MANAGER_ADDR};
|
||||||
|
use crate::hitbox_visualizer;
|
||||||
use skyline::nn::ro::LookupSymbol;
|
use skyline::nn::ro::LookupSymbol;
|
||||||
use skyline::nn::hid::*;
|
use skyline::nn::hid::*;
|
||||||
use smash::app::{self, lua_bind::*, sv_animcmd};
|
use smash::app::{self, lua_bind::*};
|
||||||
use smash::lib::lua_const::*;
|
use smash::lib::lua_const::*;
|
||||||
use smash::params::*;
|
use smash::params::*;
|
||||||
|
|
||||||
|
@ -11,7 +12,6 @@ pub mod sdi;
|
||||||
pub mod shield;
|
pub mod shield;
|
||||||
pub mod tech;
|
pub mod tech;
|
||||||
pub mod ledge;
|
pub mod ledge;
|
||||||
pub mod visualizer;
|
|
||||||
|
|
||||||
mod air_dodge_direction;
|
mod air_dodge_direction;
|
||||||
mod attack_angle;
|
mod attack_angle;
|
||||||
|
@ -78,8 +78,6 @@ pub unsafe fn handle_get_command_flag_cat(
|
||||||
shield::param_installer();
|
shield::param_installer();
|
||||||
}
|
}
|
||||||
|
|
||||||
visualizer::get_command_flag_cat(module_accessor);
|
|
||||||
|
|
||||||
if !is_training_mode() {
|
if !is_training_mode() {
|
||||||
return flag;
|
return flag;
|
||||||
}
|
}
|
||||||
|
@ -106,6 +104,7 @@ fn once_per_frame_per_fighter(
|
||||||
|
|
||||||
input_record::get_command_flag_cat(module_accessor);
|
input_record::get_command_flag_cat(module_accessor);
|
||||||
combo::get_command_flag_cat(module_accessor);
|
combo::get_command_flag_cat(module_accessor);
|
||||||
|
hitbox_visualizer::get_command_flag_cat(module_accessor);
|
||||||
save_states::save_states(module_accessor);
|
save_states::save_states(module_accessor);
|
||||||
tech::get_command_flag_cat(module_accessor);
|
tech::get_command_flag_cat(module_accessor);
|
||||||
}
|
}
|
||||||
|
@ -280,15 +279,6 @@ pub unsafe fn handle_set_dead_rumble(lua_state: u64) -> u64 {
|
||||||
original!()(lua_state)
|
original!()(lua_state)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[skyline::hook(replace = sv_animcmd::ATTACK)]
|
|
||||||
unsafe fn handle_attack(lua_state: u64) {
|
|
||||||
if is_training_mode() {
|
|
||||||
shield::mod_handle_attack(lua_state);
|
|
||||||
}
|
|
||||||
|
|
||||||
original!()(lua_state);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub static mut COMMON_PARAMS: *mut CommonParams = 0 as *mut _;
|
pub static mut COMMON_PARAMS: *mut CommonParams = 0 as *mut _;
|
||||||
|
|
||||||
fn params_main(params_info: &ParamsInfo<'_>) {
|
fn params_main(params_info: &ParamsInfo<'_>) {
|
||||||
|
@ -359,8 +349,6 @@ pub fn training_mods() {
|
||||||
handle_is_enable_transition_term,
|
handle_is_enable_transition_term,
|
||||||
// SDI
|
// SDI
|
||||||
crate::training::sdi::check_hit_stop_delay_command,
|
crate::training::sdi::check_hit_stop_delay_command,
|
||||||
// Infinite shield damage
|
|
||||||
handle_attack
|
|
||||||
);
|
);
|
||||||
|
|
||||||
combo::init();
|
combo::init();
|
||||||
|
|
|
@ -2,9 +2,12 @@ use crate::common::consts::*;
|
||||||
use crate::common::*;
|
use crate::common::*;
|
||||||
use crate::training::frame_counter;
|
use crate::training::frame_counter;
|
||||||
use crate::training::mash;
|
use crate::training::mash;
|
||||||
use smash::app::{self, lua_bind::*, sv_system};
|
use smash::app;
|
||||||
|
use smash::app::lua_bind::*;
|
||||||
|
use smash::app::sv_system;
|
||||||
use smash::hash40;
|
use smash::hash40;
|
||||||
use smash::lib::{L2CAgent, L2CValue, lua_const::*};
|
use smash::lib::lua_const::*;
|
||||||
|
use smash::lib::L2CValue;
|
||||||
use smash::lua2cpp::L2CFighterCommon;
|
use smash::lua2cpp::L2CFighterCommon;
|
||||||
|
|
||||||
// How many hits to hold shield until picking an Out Of Shield option
|
// How many hits to hold shield until picking an Out Of Shield option
|
||||||
|
@ -384,22 +387,3 @@ fn was_in_shieldstun(module_accessor: &mut app::BattleObjectModuleAccessor) -> b
|
||||||
StatusModule::prev_status_kind(module_accessor, 0) == FIGHTER_STATUS_KIND_GUARD_DAMAGE
|
StatusModule::prev_status_kind(module_accessor, 0) == FIGHTER_STATUS_KIND_GUARD_DAMAGE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn mod_handle_attack(lua_state: u64) {
|
|
||||||
let mut l2c_agent = L2CAgent::new(lua_state);
|
|
||||||
|
|
||||||
// necessary if param object fails
|
|
||||||
// hacky way of forcing no shield damage on all hitboxes
|
|
||||||
if MENU.shield_state == Shield::Infinite {
|
|
||||||
let mut hitbox_params: Vec<L2CValue> =
|
|
||||||
(0..36).map(|i| l2c_agent.pop_lua_stack(i + 1)).collect();
|
|
||||||
l2c_agent.clear_lua_stack();
|
|
||||||
for (i, mut x) in hitbox_params.iter_mut().enumerate().take(36) {
|
|
||||||
if i == 20 {
|
|
||||||
l2c_agent.push_lua_stack(&mut L2CValue::new_num(-999.0));
|
|
||||||
} else {
|
|
||||||
l2c_agent.push_lua_stack(&mut x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
use crate::common::{consts::*, *};
|
|
||||||
use smash::app;
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
fn enable_hitbox_vis(enable: bool);
|
|
||||||
fn enable_hurtbox_vis(enable: bool);
|
|
||||||
fn enable_special_vis(enable: bool);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn get_command_flag_cat(_module_accessor: &mut app::BattleObjectModuleAccessor) {
|
|
||||||
if (enable_hitbox_vis as *const ()).is_null() {
|
|
||||||
panic!("The visualizer plugin is not found. Please check your Skyline plugins directory for visualizer.nro.");
|
|
||||||
}
|
|
||||||
|
|
||||||
let vis_options = MENU.visualization.to_vec();
|
|
||||||
let hitbox_vis = is_training_mode() && vis_options.contains(&VisualizationFlags::HITBOX_VIS);
|
|
||||||
let hurtbox_vis = is_training_mode() && vis_options.contains(&VisualizationFlags::HURTBOX_VIS);
|
|
||||||
|
|
||||||
enable_hitbox_vis(hitbox_vis);
|
|
||||||
enable_hurtbox_vis(hurtbox_vis);
|
|
||||||
enable_special_vis(hitbox_vis);
|
|
||||||
}
|
|
Loading…
Reference in a new issue