mirror of
https://github.com/jugeeya/UltimateTrainingModpack.git
synced 2024-11-20 00:46:34 +00:00
Blujay's visualizer
Use blujay's visualizer plugin for hitbox/hurtbox visualization (#236) * working * Update rust.yml Fix GH Action for getting visualizer.nro Fix to visualization, allow hitbox/hurtbox toggle
This commit is contained in:
parent
ed135e88c3
commit
f8dba57044
10 changed files with 89 additions and 360 deletions
8
.github/workflows/rust.yml
vendored
8
.github/workflows/rust.yml
vendored
|
@ -86,11 +86,17 @@ jobs:
|
|||
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/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 libnro_hook.nro ${{env.SMASH_PLUGIN_DIR}}/libnro_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}}/{}
|
||||
zip -r training_modpack_beta.zip atmosphere
|
||||
zip -r training_modpack_beta.zip atmosphere colors.json
|
||||
- name: Update Release
|
||||
uses: meeDamian/github-release@2.0
|
||||
with:
|
||||
|
|
|
@ -79,6 +79,25 @@ pub fn random_option<T>(arg: &[T]) -> &T {
|
|||
&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
|
||||
/*
|
||||
0, 0.785398, 1.570796, 2.356194, -3.14159, -2.356194, -1.570796, -0.785398
|
||||
|
@ -711,7 +730,7 @@ macro_rules! url_params {
|
|||
url_params! {
|
||||
#[derive(Clone, Copy, )]
|
||||
pub struct TrainingModpackMenu {
|
||||
pub hitbox_vis: OnOff,
|
||||
pub visualization: VisualizationFlags,
|
||||
pub stage_hazards: OnOff,
|
||||
pub di_state: Direction,
|
||||
pub sdi_state: Direction,
|
||||
|
@ -765,7 +784,7 @@ impl TrainingModpackMenu {
|
|||
(fast_fall = BoolFlag::from_bits(val))
|
||||
(follow_up = Action::from_bits(val))
|
||||
(full_hop = BoolFlag::from_bits(val))
|
||||
(hitbox_vis = OnOff::from_val(val))
|
||||
(visualization = VisualizationFlags::from_bits(val))
|
||||
(input_delay = Some(val as i32))
|
||||
(ledge_delay = LongDelay::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, "Hitbox Visualization", hitbox_vis, "Hitbox Visualization: Should hitboxes be displayed, hiding other visual effects");
|
||||
add_bitflag_submenu!(overall_menu, "Visualization", visualization, VisualizationFlags, "Visualization: Should hitboxes and/or hurtboxes be displayed.");
|
||||
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, "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::*;
|
||||
|
||||
pub static DEFAULT_MENU: consts::TrainingModpackMenu = consts::TrainingModpackMenu {
|
||||
hitbox_vis: OnOff::On,
|
||||
visualization: VisualizationFlags::all(),
|
||||
stage_hazards: OnOff::Off,
|
||||
di_state: Direction::empty(),
|
||||
sdi_state: Direction::empty(),
|
||||
|
|
|
@ -1,344 +0,0 @@
|
|||
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,7 +6,6 @@
|
|||
|
||||
pub mod common;
|
||||
mod hazard_manager;
|
||||
mod hitbox_visualizer;
|
||||
mod training;
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -59,7 +58,6 @@ pub fn main() {
|
|||
}
|
||||
|
||||
log!("Initialized.");
|
||||
hitbox_visualizer::hitbox_visualization();
|
||||
hazard_manager::hazard_manager();
|
||||
training::training_mods();
|
||||
nro::add_hook(nro_main).unwrap();
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
viewBox="0 0 80.0 80.0"
|
||||
version="1.1"
|
||||
id="SVGRoot"
|
||||
sodipodi:docname="hitbox_vis.svg"
|
||||
sodipodi:docname="visualization.svg"
|
||||
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)">
|
||||
<defs
|
||||
id="defs2223" />
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
|
@ -1,8 +1,7 @@
|
|||
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::hid::*;
|
||||
use smash::app::{self, lua_bind::*};
|
||||
use smash::app::{self, lua_bind::*, sv_animcmd};
|
||||
use smash::lib::lua_const::*;
|
||||
use smash::params::*;
|
||||
|
||||
|
@ -12,6 +11,7 @@ pub mod sdi;
|
|||
pub mod shield;
|
||||
pub mod tech;
|
||||
pub mod ledge;
|
||||
pub mod visualizer;
|
||||
|
||||
mod air_dodge_direction;
|
||||
mod attack_angle;
|
||||
|
@ -78,6 +78,8 @@ pub unsafe fn handle_get_command_flag_cat(
|
|||
shield::param_installer();
|
||||
}
|
||||
|
||||
visualizer::get_command_flag_cat(module_accessor);
|
||||
|
||||
if !is_training_mode() {
|
||||
return flag;
|
||||
}
|
||||
|
@ -104,7 +106,6 @@ fn once_per_frame_per_fighter(
|
|||
|
||||
input_record::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);
|
||||
tech::get_command_flag_cat(module_accessor);
|
||||
}
|
||||
|
@ -279,6 +280,15 @@ pub unsafe fn handle_set_dead_rumble(lua_state: u64) -> u64 {
|
|||
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 _;
|
||||
|
||||
fn params_main(params_info: &ParamsInfo<'_>) {
|
||||
|
@ -349,6 +359,8 @@ pub fn training_mods() {
|
|||
handle_is_enable_transition_term,
|
||||
// SDI
|
||||
crate::training::sdi::check_hit_stop_delay_command,
|
||||
// Infinite shield damage
|
||||
handle_attack
|
||||
);
|
||||
|
||||
combo::init();
|
||||
|
|
|
@ -2,12 +2,9 @@ use crate::common::consts::*;
|
|||
use crate::common::*;
|
||||
use crate::training::frame_counter;
|
||||
use crate::training::mash;
|
||||
use smash::app;
|
||||
use smash::app::lua_bind::*;
|
||||
use smash::app::sv_system;
|
||||
use smash::app::{self, lua_bind::*, sv_system};
|
||||
use smash::hash40;
|
||||
use smash::lib::lua_const::*;
|
||||
use smash::lib::L2CValue;
|
||||
use smash::lib::{L2CAgent, L2CValue, lua_const::*};
|
||||
use smash::lua2cpp::L2CFighterCommon;
|
||||
|
||||
// How many hits to hold shield until picking an Out Of Shield option
|
||||
|
@ -387,3 +384,22 @@ fn was_in_shieldstun(module_accessor: &mut app::BattleObjectModuleAccessor) -> b
|
|||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
22
src/training/visualizer.rs
Normal file
22
src/training/visualizer.rs
Normal file
|
@ -0,0 +1,22 @@
|
|||
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