diff --git a/autogen/lua_definitions/constants.lua b/autogen/lua_definitions/constants.lua index f2d30851a..d981a171e 100644 --- a/autogen/lua_definitions/constants.lua +++ b/autogen/lua_definitions/constants.lua @@ -3276,7 +3276,7 @@ PVP_ATTACK_KNOCKBACK_TIMER_DEFAULT = 10 PVP_ATTACK_KNOCKBACK_TIMER_OVERRIDE = -5 --- @type integer -PVP_ATTACK_OVERRIDE_VANILLA_INVINCIBILITY = 0x0000FFFF +PVP_ATTACK_KNOCKBACK_ACTION_ARG = 0x10000 --- @type integer INT_STATUS_ATTACK_MASK = 0x000000FF diff --git a/docs/lua/constants.md b/docs/lua/constants.md index 7632878e6..664556031 100644 --- a/docs/lua/constants.md +++ b/docs/lua/constants.md @@ -1459,7 +1459,7 @@ - ATTACK_FROM_BELOW - PVP_ATTACK_KNOCKBACK_TIMER_DEFAULT - PVP_ATTACK_KNOCKBACK_TIMER_OVERRIDE -- PVP_ATTACK_OVERRIDE_VANILLA_INVINCIBILITY +- PVP_ATTACK_KNOCKBACK_ACTION_ARG - INT_STATUS_ATTACK_MASK - INT_STATUS_HOOT_GRABBED_BY_MARIO - INT_STATUS_MARIO_UNK1 diff --git a/src/game/interaction.c b/src/game/interaction.c index d81651099..4304a23ae 100644 --- a/src/game/interaction.c +++ b/src/game/interaction.c @@ -643,7 +643,9 @@ static u32 unused_determine_knockback_action(struct MarioState *m) { return bonkAction; } -u32 determine_knockback_action(struct MarioState *m, UNUSED s32 arg) { +u32 determine_knockback_action(struct MarioState *m, RET bool *isPlayerAttack) { + *isPlayerAttack = false; + if (!m) { return 0; } if (m->interactObj == NULL) { return sForwardKnockbackActions[0][0]; @@ -739,6 +741,7 @@ u32 determine_knockback_action(struct MarioState *m, UNUSED s32 arg) { m->knockbackTimer = hasBeenPunched ? PVP_ATTACK_KNOCKBACK_TIMER_OVERRIDE : PVP_ATTACK_KNOCKBACK_TIMER_DEFAULT; #undef IF_REVAMPED_PVP m->faceAngle[1] = m->interactObj->oFaceAngleYaw + (sign == 1.0f ? 0 : 0x8000); + *isPlayerAttack = true; } return bonkAction; @@ -870,7 +873,10 @@ u32 take_damage_and_knock_back(struct MarioState *m, struct Object *o) { } update_mario_sound_and_camera(m); - return drop_and_set_mario_action(m, determine_knockback_action(m, o->oDamageOrCoinValue), damage); + + bool isPlayerAttack = false; + u32 knockbackAction = determine_knockback_action(m, &isPlayerAttack); + return drop_and_set_mario_action(m, knockbackAction, damage | (isPlayerAttack ? PVP_ATTACK_KNOCKBACK_ACTION_ARG : 0)); } return FALSE; @@ -1724,8 +1730,9 @@ u32 interact_snufit_bullet(struct MarioState *m, UNUSED u32 interactType, struct play_character_sound(m, CHAR_SOUND_ATTACKED); update_mario_sound_and_camera(m); - return drop_and_set_mario_action(m, determine_knockback_action(m, o->oDamageOrCoinValue), - o->oDamageOrCoinValue); + bool isPlayerAttack = false; + u32 knockbackAction = determine_knockback_action(m, &isPlayerAttack); + return drop_and_set_mario_action(m, knockbackAction, o->oDamageOrCoinValue | (isPlayerAttack ? PVP_ATTACK_KNOCKBACK_ACTION_ARG : 0)); } } diff --git a/src/game/interaction.h b/src/game/interaction.h index 7dfe20a74..d06e9a795 100644 --- a/src/game/interaction.h +++ b/src/game/interaction.h @@ -101,7 +101,7 @@ enum InteractionFlag { #define PVP_ATTACK_KNOCKBACK_TIMER_DEFAULT 10 #define PVP_ATTACK_KNOCKBACK_TIMER_OVERRIDE -5 -#define PVP_ATTACK_OVERRIDE_VANILLA_INVINCIBILITY 0x0000FFFF +#define PVP_ATTACK_KNOCKBACK_ACTION_ARG 0x10000 #define INT_STATUS_ATTACK_MASK 0x000000FF diff --git a/src/game/mario.c b/src/game/mario.c index 2c1e6c56b..897bbc3fe 100644 --- a/src/game/mario.c +++ b/src/game/mario.c @@ -1043,6 +1043,29 @@ static u32 set_mario_action_airborne(struct MarioState *m, u32 action, u32 actio case ACT_JUMP_KICK: m->vel[1] = 20.0f; break; + + // Set forward vel to a predefined value for non-player knockbacks + case ACT_BACKWARD_AIR_KB: + case ACT_HARD_BACKWARD_AIR_KB: + if (!(actionArg & PVP_ATTACK_KNOCKBACK_ACTION_ARG)) { + mario_set_forward_vel(m, -16.0f); + } + break; + + case ACT_FORWARD_AIR_KB: + case ACT_HARD_FORWARD_AIR_KB: + if (!(actionArg & PVP_ATTACK_KNOCKBACK_ACTION_ARG)) { + mario_set_forward_vel(m, 16.0f); + } + break; + + case ACT_THROWN_BACKWARD: + case ACT_THROWN_FORWARD: + case ACT_SOFT_BONK: + if (!(actionArg & PVP_ATTACK_KNOCKBACK_ACTION_ARG)) { + mario_set_forward_vel(m, m->forwardVel); // needed to update velocities + } + break; } m->peakHeight = m->pos[1]; @@ -2221,6 +2244,7 @@ void init_single_mario(struct MarioState* m) { m->heldObj = NULL; m->heldByObj = NULL; + m->interactObj = NULL; m->riddenObj = NULL; m->usedObj = NULL; m->bubbleObj = NULL; diff --git a/src/game/mario_actions_airborne.c b/src/game/mario_actions_airborne.c index 5bf71f395..00b338447 100644 --- a/src/game/mario_actions_airborne.c +++ b/src/game/mario_actions_airborne.c @@ -57,7 +57,7 @@ depending on whether Mario's forward velocity is high enough to be considered a |descriptionEnd| */ void play_knockback_sound(struct MarioState *m) { if (!m) { return; } - if (m->actionArg == 0 && (m->forwardVel <= -28.0f || m->forwardVel >= 28.0f)) { + if ((m->actionArg & ~PVP_ATTACK_KNOCKBACK_ACTION_ARG) == 0 && (m->forwardVel <= -28.0f || m->forwardVel >= 28.0f)) { play_character_sound_if_no_flag(m, CHAR_SOUND_DOH, MARIO_MARIO_SOUND_PLAYED); } else { play_character_sound_if_no_flag(m, CHAR_SOUND_UH, MARIO_MARIO_SOUND_PLAYED); @@ -1236,13 +1236,8 @@ u32 common_air_knockback_step(struct MarioState *m, u32 landAction, u32 hardFall if (!m) { return 0; } u32 stepResult; - if (m->knockbackTimer == 0) { - if (m->interactObj == NULL || !(m->interactObj->oInteractType & INTERACT_PLAYER)) { - mario_set_forward_vel(m, speed); - } - } else if (m->knockbackTimer < 0) { - // do nothing - } else { + // Refresh knockbackTimer + if (m->knockbackTimer > 0) { m->knockbackTimer = PVP_ATTACK_KNOCKBACK_TIMER_DEFAULT; } @@ -1356,7 +1351,7 @@ s32 act_hard_forward_air_kb(struct MarioState *m) { s32 act_thrown_backward(struct MarioState *m) { if (!m) { return 0; } u32 landAction; - if (m->actionArg != 0) { + if ((m->actionArg & ~PVP_ATTACK_KNOCKBACK_ACTION_ARG) != 0) { landAction = ACT_HARD_BACKWARD_GROUND_KB; } else { landAction = ACT_BACKWARD_GROUND_KB; @@ -1375,7 +1370,7 @@ s32 act_thrown_forward(struct MarioState *m) { s16 pitch; u32 landAction; - if (m->actionArg != 0) { + if ((m->actionArg & ~PVP_ATTACK_KNOCKBACK_ACTION_ARG) != 0) { landAction = ACT_HARD_FORWARD_GROUND_KB; } else { landAction = ACT_FORWARD_GROUND_KB; diff --git a/src/game/mario_actions_moving.c b/src/game/mario_actions_moving.c index 6a21d45d5..c502e5f31 100644 --- a/src/game/mario_actions_moving.c +++ b/src/game/mario_actions_moving.c @@ -1775,12 +1775,13 @@ Handles knockback on the ground (getting hit while on the ground) with shared lo s32 common_ground_knockback_action(struct MarioState *m, s32 animation, s32 arg2, s32 arg3, s32 arg4) { if (!m) { return 0; } s32 animFrame; + s32 damage = arg4 & ~PVP_ATTACK_KNOCKBACK_ACTION_ARG; if (arg3) { play_mario_heavy_landing_sound_once(m, SOUND_ACTION_TERRAIN_BODY_HIT_GROUND); } - if (arg4 > 0) { + if (damage > 0) { play_character_sound_if_no_flag(m, CHAR_SOUND_ATTACKED, MARIO_MARIO_SOUND_PLAYED); } else { #ifdef VERSION_JP @@ -1790,18 +1791,18 @@ s32 common_ground_knockback_action(struct MarioState *m, s32 animation, s32 arg2 #endif } - if (m->knockbackTimer == 0) { - if (m->interactObj == NULL || !(m->interactObj->oInteractType & INTERACT_PLAYER)) { - if (m->forwardVel > 32.0f) { - m->forwardVel = 32.0f; - } - if (m->forwardVel < -32.0f) { - m->forwardVel = -32.0f; - } + // Cap speed if it's not a PVP attack + if (!(arg4 & PVP_ATTACK_KNOCKBACK_ACTION_ARG)) { + if (m->forwardVel > 32.0f) { + m->forwardVel = 32.0f; } - } else if (m->knockbackTimer < 0) { - // do nothing - } else { + if (m->forwardVel < -32.0f) { + m->forwardVel = -32.0f; + } + } + + // Refresh knockbackTimer + if (m->knockbackTimer > 0) { m->knockbackTimer = PVP_ATTACK_KNOCKBACK_TIMER_DEFAULT; } @@ -1824,7 +1825,7 @@ s32 common_ground_knockback_action(struct MarioState *m, s32 animation, s32 arg2 if (m->health < 0x100) { set_mario_action(m, ACT_STANDING_DEATH, 0); } else { - if (arg4 > 0) { + if (damage > 0) { m->invincTimer = 30; } set_mario_action(m, ACT_IDLE, 0); diff --git a/src/pc/lua/smlua_constants_autogen.c b/src/pc/lua/smlua_constants_autogen.c index a55aae378..129a8f876 100644 --- a/src/pc/lua/smlua_constants_autogen.c +++ b/src/pc/lua/smlua_constants_autogen.c @@ -1653,7 +1653,7 @@ char gSmluaConstants[] = "" "ATTACK_FROM_BELOW=6\n" "PVP_ATTACK_KNOCKBACK_TIMER_DEFAULT=10\n" "PVP_ATTACK_KNOCKBACK_TIMER_OVERRIDE=-5\n" -"PVP_ATTACK_OVERRIDE_VANILLA_INVINCIBILITY=0x0000FFFF\n" +"PVP_ATTACK_KNOCKBACK_ACTION_ARG=0x10000\n" "INT_STATUS_ATTACK_MASK=0x000000FF\n" "INT_STATUS_HOOT_GRABBED_BY_MARIO=(1 << 0)\n" "INT_STATUS_MARIO_UNK1=(1 << 1)\n"