Skip to content

Commit a2d13ae

Browse files
authored
Merge pull request #2213 from HDR-Development/smash-64-mode
Add Smash 64 mode
2 parents 6dea02d + 37c70fc commit a2d13ae

File tree

11 files changed

+206
-7
lines changed

11 files changed

+206
-7
lines changed

dynamic/src/game_modes.rs

+3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ pub enum CustomMode {
88
TurboMode = 1,
99
HitfallMode = 2,
1010
AirdashMode = 3,
11+
Smash64Mode = 4,
1112
}
1213

1314
impl fmt::Display for CustomMode {
@@ -17,6 +18,7 @@ impl fmt::Display for CustomMode {
1718
CustomMode::TurboMode => write!(f, "Turbo"),
1819
CustomMode::HitfallMode => write!(f, "Hitfall"),
1920
CustomMode::AirdashMode => write!(f, "Airdash"),
21+
CustomMode::Smash64Mode => write!(f, "Smash64"),
2022
}
2123
}
2224
}
@@ -31,6 +33,7 @@ impl FromStr for CustomMode {
3133
"turbo" => Ok(CustomMode::TurboMode),
3234
"hitfall" => Ok(CustomMode::HitfallMode),
3335
"airdash" => Ok(CustomMode::AirdashMode),
36+
"smash64" => Ok(CustomMode::Smash64Mode),
3437
_ => Err(()),
3538
}
3639
}

fighters/common/src/function_hooks/attack.rs

+32-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use super::*;
22
use utils::ext::*;
33
use std::arch::asm;
4+
use utils::game_modes::CustomMode;
45

56

67
#[skyline::hook(offset = 0x3dc160)]
@@ -49,6 +50,36 @@ unsafe fn attack_module_set_attack(module: u64, id: i32, group: i32, data: &mut
4950
call_original!(module, id, group, data)
5051
}
5152

53+
#[skyline::hook(offset = 0x403c1c, inline)]
54+
unsafe fn get_damage_frame_mul(ctx: &mut skyline::hooks::InlineCtx) {
55+
match utils::game_modes::get_custom_mode() {
56+
Some(modes) => {
57+
if modes.contains(&CustomMode::Smash64Mode) {
58+
let damage_frame_mul_n64: f32 = 0.533;
59+
asm!("fmov s0, w8", in("w8") damage_frame_mul_n64)
60+
}
61+
},
62+
_ => {}
63+
}
64+
}
65+
66+
#[skyline::hook(offset = 0x406bd4, inline)]
67+
unsafe fn get_hitstop_frame_add(ctx: &mut skyline::hooks::InlineCtx) {
68+
match utils::game_modes::get_custom_mode() {
69+
Some(modes) => {
70+
if modes.contains(&CustomMode::Smash64Mode) {
71+
let hitstop_frame_add_n64: f32 = 5.0;
72+
asm!("fmov s0, w8", in("w8") hitstop_frame_add_n64)
73+
}
74+
},
75+
_ => {}
76+
}
77+
}
78+
5279
pub fn install() {
53-
skyline::install_hooks!(attack_module_set_attack);
80+
skyline::install_hooks!(
81+
attack_module_set_attack,
82+
get_damage_frame_mul,
83+
get_hitstop_frame_add
84+
);
5485
}

fighters/common/src/function_hooks/change_status.rs

+20-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use super::*;
22
use globals::*;
3+
use utils::game_modes::CustomMode;
4+
35

46
#[skyline::hook(replace=StatusModule::change_status_request)]
57
unsafe fn change_status_request_hook(boma: &mut BattleObjectModuleAccessor, status_kind: i32, arg3: bool) -> u64 {
@@ -52,10 +54,27 @@ unsafe fn change_status_request_from_script_hook(boma: &mut BattleObjectModuleAc
5254
let mut clear_buffer = arg3;
5355

5456
if boma.is_fighter() {
57+
match utils::game_modes::get_custom_mode() {
58+
Some(modes) => {
59+
if modes.contains(&CustomMode::Smash64Mode) {
60+
if [*FIGHTER_STATUS_KIND_ESCAPE_AIR, *FIGHTER_STATUS_KIND_PASSIVE_CEIL, *FIGHTER_STATUS_KIND_PASSIVE_WALL, *FIGHTER_STATUS_KIND_PASSIVE_WALL_JUMP].contains(&next_status) {
61+
return 0;
62+
}
63+
}
64+
},
65+
_ => {}
66+
}
5567
// Allow buffered wavedashes when Shield is pressed at any time within Jump input's buffer window
5668
if next_status == *FIGHTER_STATUS_KIND_JUMP_SQUAT {
5769
if boma.is_cat_flag(Cat1::AirEscape) && !boma.is_cat_flag(Cat1::AttackN) {
58-
VarModule::on_flag(boma.object(), vars::common::instance::ENABLE_AIR_ESCAPE_JUMPSQUAT);
70+
match utils::game_modes::get_custom_mode() {
71+
Some(modes) => {
72+
if !modes.contains(&CustomMode::Smash64Mode) {
73+
VarModule::on_flag(boma.object(), vars::common::instance::ENABLE_AIR_ESCAPE_JUMPSQUAT);
74+
}
75+
},
76+
_ => { VarModule::on_flag(boma.object(), vars::common::instance::ENABLE_AIR_ESCAPE_JUMPSQUAT); }
77+
}
5978
}
6079
}
6180
// Clears buffer when sliding off an edge in a damaged state, to prevent accidental buffered aerials/airdodges (common on missed techs)

fighters/common/src/function_hooks/get_param.rs

+73
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use globals::*;
33
use std::arch::asm;
44
// Addresses, offsets, and inline hooking
55
use skyline::hooks::{getRegionAddress, Region, InlineCtx};
6+
use utils::game_modes::CustomMode;
67

78
pub fn install() {
89
skyline::install_hooks!(
@@ -47,6 +48,19 @@ pub unsafe fn get_param_int_hook(x0: u64, x1: u64, x2 :u64) -> i32 {
4748

4849
if boma_reference.is_fighter() {
4950

51+
52+
53+
match utils::game_modes::get_custom_mode() {
54+
Some(modes) => {
55+
if modes.contains(&CustomMode::Smash64Mode) {
56+
if x1 == hash40("landing_heavy_frame") {
57+
return 4;
58+
}
59+
}
60+
},
61+
_ => {}
62+
}
63+
5064
if x2 == hash40("just_shield_precede_extension") {
5165
return 1000;
5266
}
@@ -117,6 +131,65 @@ pub unsafe fn get_param_float_hook(x0 /*boma*/: u64, x1 /*param_type*/: u64, x2
117131

118132
if boma_reference.is_fighter() {
119133

134+
match utils::game_modes::get_custom_mode() {
135+
Some(modes) => {
136+
if modes.contains(&CustomMode::Smash64Mode) {
137+
if x2 == hash40("shield_setoff_add") {
138+
return 4.0;
139+
}
140+
141+
if x2 == hash40("shield_setoff_mul") {
142+
return 1.62;
143+
}
144+
145+
if x1 == hash40("air_speed_y_stable") {
146+
return original!()(x0, x1, x2) * 0.8;
147+
}
148+
149+
if x1 == hash40("air_accel_y") {
150+
return original!()(x0, x1, x2) * 0.8;
151+
}
152+
153+
if x1 == hash40("damage_fly_top_air_accel_y") {
154+
return original!()(x0, x1, x2) * 0.8;
155+
}
156+
157+
if x1 == hash40("damage_fly_top_speed_y_stable") {
158+
return original!()(x0, x1, x2) * 0.8;
159+
}
160+
161+
if x1 == hash40("dive_speed_y") {
162+
return original!()(x0, x1, x2) * 0.8;
163+
}
164+
165+
if x1 == hash40("landing_frame") {
166+
return 4.0;
167+
}
168+
169+
if x1 == hash40("landing_attack_air_frame_n") {
170+
return 4.0;
171+
}
172+
173+
if x1 == hash40("landing_attack_air_frame_f") {
174+
return 4.0;
175+
}
176+
177+
if x1 == hash40("landing_attack_air_frame_b") {
178+
return 4.0;
179+
}
180+
181+
if x1 == hash40("landing_attack_air_frame_hi") {
182+
return 4.0;
183+
}
184+
185+
if x1 == hash40("landing_attack_air_frame_lw") {
186+
return 4.0;
187+
}
188+
}
189+
},
190+
_ => {}
191+
}
192+
120193
/*if x1 == hash40("air_speed_x_stable") {
121194
if StatusModule::status_kind(boma) == *FIGHTER_STATUS_KIND_JUMP_SQUAT {
122195
if StatusModule::prev_status_kind(boma, 0) == *FIGHTER_STATUS_KIND_RUN {

fighters/common/src/general_statuses/damage.rs

+9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// status imports
22
use super::*;
33
use globals::*;
4+
use utils::game_modes::CustomMode;
45

56
pub fn install() {
67
skyline::nro::add_hook(nro_hook);
@@ -147,6 +148,14 @@ pub unsafe fn FighterStatusUniqProcessDamage_leave_stop_hook(fighter: &mut L2CFi
147148
}
148149

149150
unsafe extern "C" fn check_asdi(fighter: &mut L2CFighterCommon) {
151+
match utils::game_modes::get_custom_mode() {
152+
Some(modes) => {
153+
if modes.contains(&CustomMode::Smash64Mode) {
154+
return;
155+
}
156+
},
157+
_ => {}
158+
}
150159
if fighter.global_table[STATUS_KIND] != FIGHTER_STATUS_KIND_DAMAGE_FLY_REFLECT_LR // prevents ASDI on wall bounces
151160
&& fighter.global_table[STATUS_KIND] != FIGHTER_STATUS_KIND_DAMAGE_FLY_REFLECT_U // prevents ASDI on ceiling bounces
152161
&& fighter.global_table[STATUS_KIND] != FIGHTER_STATUS_KIND_DAMAGE_FLY_REFLECT_D // prevents ASDI on ground bounces

fighters/common/src/general_statuses/jumpsquat.rs

+17-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// status imports
22
use super::*;
33
use globals::*;
4+
use utils::game_modes::CustomMode;
45
// This file contains code for wavedashing out of jumpsquat, fullhop buffered aerials/attack canceling
56

67
pub fn install() {
@@ -90,7 +91,14 @@ unsafe fn status_JumpSquat(fighter: &mut L2CFighterCommon) -> L2CValue {
9091
let lr_update = fighter.sub_status_JumpSquat_check_stick_lr_update();
9192
fighter.status_JumpSquat_common(lr_update);
9293
if fighter.is_cat_flag(CatHdr::Wavedash) {
93-
VarModule::on_flag(fighter.battle_object, vars::common::instance::ENABLE_AIR_ESCAPE_JUMPSQUAT);
94+
match utils::game_modes::get_custom_mode() {
95+
Some(modes) => {
96+
if !modes.contains(&CustomMode::Smash64Mode) {
97+
VarModule::on_flag(fighter.battle_object, vars::common::instance::ENABLE_AIR_ESCAPE_JUMPSQUAT);
98+
}
99+
},
100+
_ => { VarModule::on_flag(fighter.battle_object, vars::common::instance::ENABLE_AIR_ESCAPE_JUMPSQUAT); }
101+
}
94102
}
95103
fighter.sub_shift_status_main(L2CValue::Ptr(status_JumpSquat_Main as *const () as _))
96104
}
@@ -298,7 +306,14 @@ unsafe fn uniq_process_JumpSquat_exec_status_param(fighter: &mut L2CFighterCommo
298306
&& cat1 & *FIGHTER_PAD_CMD_CAT1_FLAG_ATTACK_N == 0 {
299307
if !(fighter.kind() == *FIGHTER_KIND_PICKEL
300308
&& fighter.is_prev_status_one_of(&[*FIGHTER_PICKEL_STATUS_KIND_SPECIAL_N1_JUMP_SQUAT, *FIGHTER_PICKEL_STATUS_KIND_SPECIAL_N3_JUMP_SQUAT])) {
301-
VarModule::on_flag(fighter.battle_object, vars::common::instance::ENABLE_AIR_ESCAPE_JUMPSQUAT);
309+
match utils::game_modes::get_custom_mode() {
310+
Some(modes) => {
311+
if !modes.contains(&CustomMode::Smash64Mode) {
312+
VarModule::on_flag(fighter.battle_object, vars::common::instance::ENABLE_AIR_ESCAPE_JUMPSQUAT);
313+
}
314+
},
315+
_ => { VarModule::on_flag(fighter.battle_object, vars::common::instance::ENABLE_AIR_ESCAPE_JUMPSQUAT); }
316+
}
302317
}
303318
}
304319
let end_frame = WorkModule::get_param_int(fighter.module_accessor, hash40("jump_squat_frame"), 0);

fighters/common/src/general_statuses/mod.rs

+23
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// status imports
22
use super::*;
33
use globals::*;
4+
use utils::game_modes::CustomMode;
45

56
macro_rules! interrupt {
67
() => { return L2CValue::I32(1); };
@@ -124,6 +125,7 @@ fn nro_hook(info: &skyline::nro::NroInfo) {
124125
sub_cliff_uniq_process_exec_fix_pos,
125126
end_pass_ground,
126127
virtual_ftStatusUniqProcessDamage_exec_common,
128+
FighterStatusDamage__correctDamageVector,
127129
FighterStatusDamage__correctDamageVectorEffect,
128130
sub_fighter_pre_end_status,
129131
sub_is_dive,
@@ -568,8 +570,29 @@ pub unsafe fn virtual_ftStatusUniqProcessDamage_exec_common(fighter: &mut L2CFig
568570
}
569571
}
570572

573+
#[skyline::hook(replace = smash::lua2cpp::L2CFighterCommon_FighterStatusDamage__correctDamageVector)]
574+
pub unsafe fn FighterStatusDamage__correctDamageVector(fighter: &mut L2CFighterCommon) -> L2CValue {
575+
match utils::game_modes::get_custom_mode() {
576+
Some(modes) => {
577+
if modes.contains(&CustomMode::Smash64Mode) {
578+
return 0.into();
579+
}
580+
},
581+
_ => {}
582+
}
583+
call_original!(fighter)
584+
}
585+
571586
#[skyline::hook(replace = smash::lua2cpp::L2CFighterCommon_FighterStatusDamage__correctDamageVectorEffect)]
572587
pub unsafe fn FighterStatusDamage__correctDamageVectorEffect(fighter: &mut L2CFighterCommon) -> L2CValue {
588+
match utils::game_modes::get_custom_mode() {
589+
Some(modes) => {
590+
if modes.contains(&CustomMode::Smash64Mode) {
591+
return 0.into();
592+
}
593+
},
594+
_ => {}
595+
}
573596
if fighter.global_table[STATUS_KIND_INTERRUPT] != FIGHTER_STATUS_KIND_DAMAGE_AIR {
574597
return call_original!(fighter);
575598
}

romfs/source/ui/docs/gamemodes.html

+23
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,17 @@
8080
</div>
8181
</div>
8282
</a>
83+
<a id="btn-smash64" tabindex="0" class="flex-button abstract-button" onfocus="focusMenu(this)" onkeydown="toggle_mode('Smash 64', this)" nx-se-disabled="">
84+
<div class="abstract-icon-back-decoration"></div>
85+
<div class="abstract-button-border">
86+
<div class="abstract-button-inner">
87+
<div class="abstract-icon-wrapper">
88+
<img class="abstract-icon" ref="../../img/icon/juji.svg" />
89+
</div>
90+
<div class="abstract-button-text f-u-bold"><span id="smash64-text-field" data-msgid="textbox_id-4-1">Smash 64 Mode (OFF)</span></div>
91+
</div>
92+
</div>
93+
</a>
8394
<a id="btn-play" tabindex="0" class="flex-button abstract-button" onfocus="focusMenu(this)" onkeydown="exit_with_id()" nx-se-disabled="">
8495
<div class="abstract-icon-back-decoration"></div>
8596
<div class="abstract-button-border">
@@ -142,6 +153,18 @@
142153
</div>
143154
</div>
144155
</div>
156+
<div id="about-smash64" class="l-main-content is-hidden">
157+
<div class="l-screen-shot-wrapper">
158+
<div class="screen-shot-wrapper">
159+
<img class="screen-shot video" ref="../../../hdr/smash64.webp" />
160+
</div>
161+
</div>
162+
<div class="l-description">
163+
<div class="f-b-bold">
164+
<p class="sentence"><span data-msgid="textbox_id-5">Clash in classic fashion!<br />Removes DI, airdodges, walltechs, and landing lag. Also raises hitstun and shieldstun and alters character physics.</span></p>
165+
</div>
166+
</div>
167+
</div>
145168
<div id="about-play" class="l-main-content is-hidden">
146169
<div class="l-screen-shot-wrapper">
147170
<div class="screen-shot-wrapper">

romfs/source/ui/docs/gamemodes.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@ enabled_modes.set('tag', false);
33
enabled_modes.set('turbo', false);
44
enabled_modes.set('hitfall', false);
55
enabled_modes.set('airdash', false);
6+
enabled_modes.set('smash64', false);
67

78
function toggle_mode(mode_name, self) {
89
if (event && event.keyCode !== 13) return
910
//alert("toggling: " + mode_name);
10-
var is_now_enabled = !enabled_modes.get(mode_name.toLowerCase());
11-
enabled_modes.set(mode_name.toLowerCase(), is_now_enabled);
11+
var is_now_enabled = !enabled_modes.get(mode_name.replace(/\s+/g, '').toLowerCase());
12+
enabled_modes.set(mode_name.replace(/\s+/g, '').toLowerCase(), is_now_enabled);
1213
var button_text = mode_name + " Mode (" + (is_now_enabled ? "ON" : "OFF") + ")";
13-
var element = document.getElementById(mode_name.toLowerCase() + "-text-field");
14+
var element = document.getElementById(mode_name.replace(/\s+/g, '').toLowerCase() + "-text-field");
1415
element.innerHTML = button_text;
1516
self.blur();
1617
self.focus();

romfs/source/ui/docs/smash64.webp

8.57 MB
Binary file not shown.

utils/src/game_modes.rs

+2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ lazy_static! {
1616
static ref TURBO_WEBP: Vec<u8> = std::fs::read("mods:/ui/docs/turbo.webp").unwrap();
1717
static ref HITFALL_WEBP: Vec<u8> = std::fs::read("mods:/ui/docs/hitfall.webp").unwrap();
1818
static ref AIRDASH_WEBP: Vec<u8> = std::fs::read("mods:/ui/docs/airdash.webp").unwrap();
19+
static ref SMASH64_WEBP: Vec<u8> = std::fs::read("mods:/ui/docs/smash64.webp").unwrap();
1920
}
2021

2122
static mut CURRENT_CUSTOM_MODES: Option<HashSet<CustomMode>> = None;
@@ -90,6 +91,7 @@ pub unsafe fn open_modes_session() {
9091
.file("hdr/turbo.webp", TURBO_WEBP.as_slice())
9192
.file("hdr/hitfall.webp", HITFALL_WEBP.as_slice())
9293
.file("hdr/airdash.webp", AIRDASH_WEBP.as_slice())
94+
.file("hdr/smash64.webp", SMASH64_WEBP.as_slice())
9395
.start_page("help/html/USen/gamemodes.html")
9496
.open()
9597
.unwrap();

0 commit comments

Comments
 (0)