diff --git a/autogen/lua_definitions/constants.lua b/autogen/lua_definitions/constants.lua index 934edf9e..5a708ed9 100644 --- a/autogen/lua_definitions/constants.lua +++ b/autogen/lua_definitions/constants.lua @@ -2484,7 +2484,7 @@ SHAKE_SHOCK = 10 SHAKE_SMALL_DAMAGE = 3 --- @type integer -PALETTE_MAX = 30 +PALETTE_MAX = 32 --- @class CharacterSound diff --git a/autogen/lua_definitions/functions.lua b/autogen/lua_definitions/functions.lua index 44b33687..b478326b 100644 --- a/autogen/lua_definitions/functions.lua +++ b/autogen/lua_definitions/functions.lua @@ -3830,6 +3830,13 @@ function mario_throw_held_object(m) -- ... end +--- @param attacker MarioState +--- @param victim MarioState +--- @return integer +function passes_pvp_interaction_checks(attacker, victim) + -- ... +end + --- @param courseNum integer --- @param levelNum integer --- @param areaIndex integer diff --git a/autogen/lua_definitions/structs.lua b/autogen/lua_definitions/structs.lua index 0e06bdaa..dd5e185f 100644 --- a/autogen/lua_definitions/structs.lua +++ b/autogen/lua_definitions/structs.lua @@ -849,6 +849,7 @@ --- @field public oBubbaUnkFC integer --- @field public oBulletBillInitialMoveYaw integer --- @field public oBullyKBTimerAndMinionKOCounter integer +--- @field public oBullyLastNetworkPlayerIndex integer --- @field public oBullyMarioCollisionAngle integer --- @field public oBullyPrevX number --- @field public oBullyPrevY number diff --git a/docs/lua/functions.md b/docs/lua/functions.md index 4df2b360..dadf234d 100644 --- a/docs/lua/functions.md +++ b/docs/lua/functions.md @@ -743,6 +743,7 @@ - [mario_stop_riding_and_holding](#mario_stop_riding_and_holding) - [mario_stop_riding_object](#mario_stop_riding_object) - [mario_throw_held_object](#mario_throw_held_object) + - [passes_pvp_interaction_checks](#passes_pvp_interaction_checks)
@@ -14630,6 +14631,27 @@ The `reliable` field will ensure that the packet arrives, but should be used spa
+## [passes_pvp_interaction_checks](#passes_pvp_interaction_checks) + +### Lua Example +`local integerValue = passes_pvp_interaction_checks(attacker, victim)` + +### Parameters +| Field | Type | +| ----- | ---- | +| attacker | [MarioState](structs.md#MarioState) | +| victim | [MarioState](structs.md#MarioState) | + +### Returns +- `integer` + +### C Prototype +`u8 passes_pvp_interaction_checks(struct MarioState* attacker, struct MarioState* victim);` + +[:arrow_up_small:](#) + +
+ --- # functions from level_info.h diff --git a/docs/lua/structs.md b/docs/lua/structs.md index 91ac4aed..eec212df 100644 --- a/docs/lua/structs.md +++ b/docs/lua/structs.md @@ -1260,6 +1260,7 @@ | oBullyPrevZ | `number` | | | oBullyKBTimerAndMinionKOCounter | `integer` | | | oBullyMarioCollisionAngle | `integer` | | +| oBullyLastNetworkPlayerIndex | `integer` | | | oButterflyYPhase | `integer` | | | oTripletButterflyScale | `number` | | | oTripletButterflySpeed | `number` | | diff --git a/src/game/interaction.c b/src/game/interaction.c index f224dc1d..1304d0aa 100644 --- a/src/game/interaction.c +++ b/src/game/interaction.c @@ -1325,6 +1325,21 @@ u8 player_is_sliding(struct MarioState* m) { return FALSE; } +u8 passes_pvp_interaction_checks(struct MarioState* attacker, struct MarioState* victim) { + // attacked + u8 isInCutscene = ((attacker->action & ACT_GROUP_MASK) == ACT_GROUP_CUTSCENE) || ((victim->action & ACT_GROUP_MASK) == ACT_GROUP_CUTSCENE); + isInCutscene = isInCutscene || (attacker->action == ACT_IN_CANNON) || (victim->action == ACT_IN_CANNON); + u8 isAttackerInvulnerable = (attacker->action & ACT_FLAG_INVULNERABLE) || attacker->invincTimer != 0 || attacker->hurtCounter != 0; + u8 isInvulnerable = (victim->action & ACT_FLAG_INVULNERABLE) || victim->invincTimer != 0 || victim->hurtCounter != 0 || isInCutscene; + u8 isIgnoredAttack = (attacker->action == ACT_JUMP || attacker->action == ACT_DOUBLE_JUMP || attacker->action == ACT_LONG_JUMP || attacker->action == ACT_SIDE_FLIP); + + if (victim->knockbackTimer > 0) { + return false; + } + + return (!isInvulnerable && !isIgnoredAttack && !isAttackerInvulnerable); +} + u32 interact_player(struct MarioState* m, UNUSED u32 interactType, struct Object* o) { if (!is_player_active(m)) { return FALSE; } if (gServerSettings.playerInteractions == PLAYER_INTERACTIONS_NONE) { return FALSE; } @@ -1362,14 +1377,7 @@ u32 interact_player(struct MarioState* m, UNUSED u32 interactType, struct Object u32 interaction = determine_interaction(m, o); - // attacked - u8 isInCutscene = ((m->action & ACT_GROUP_MASK) == ACT_GROUP_CUTSCENE) || ((m2->action & ACT_GROUP_MASK) == ACT_GROUP_CUTSCENE); - isInCutscene = isInCutscene || (m->action == ACT_IN_CANNON) || (m2->action == ACT_IN_CANNON); - u8 isAttackerInvulnerable = (m->action & ACT_FLAG_INVULNERABLE) || m->invincTimer != 0 || m->hurtCounter != 0; - u8 isInvulnerable = (m2->action & ACT_FLAG_INVULNERABLE) || m2->invincTimer != 0 || m2->hurtCounter != 0 || isInCutscene; - u8 isIgnoredAttack = (m->action == ACT_JUMP || m->action == ACT_DOUBLE_JUMP || m->action == ACT_LONG_JUMP || m->action == ACT_SIDE_FLIP); - - if ((interaction & INT_ANY_ATTACK) && !(interaction & INT_HIT_FROM_ABOVE) && !isInvulnerable && !isIgnoredAttack && !isAttackerInvulnerable) { + if ((interaction & INT_ANY_ATTACK) && !(interaction & INT_HIT_FROM_ABOVE) && passes_pvp_interaction_checks(m, m2)) { bool allow = true; smlua_call_event_hooks_mario_params_ret_bool(HOOK_ALLOW_PVP_ATTACK, m, m2, &allow); if (!allow) { @@ -1377,10 +1385,6 @@ u32 interact_player(struct MarioState* m, UNUSED u32 interactType, struct Object return false; } - if (m2->knockbackTimer > 0) { - return false; - } - // determine if slide attack should be ignored if ((interaction & INT_ATTACK_SLIDE) || player_is_sliding(m2)) { // determine the difference in velocities diff --git a/src/game/interaction.h b/src/game/interaction.h index 3069adea..58d53556 100644 --- a/src/game/interaction.h +++ b/src/game/interaction.h @@ -115,5 +115,6 @@ u32 mario_check_object_grab(struct MarioState *m); u32 get_door_save_file_flag(struct Object *door); void mario_process_interactions(struct MarioState *m); void mario_handle_special_floors(struct MarioState *m); +u8 passes_pvp_interaction_checks(struct MarioState* attacker, struct MarioState* victim); #endif // INTERACTION_H diff --git a/src/pc/lua/smlua_cobject_autogen.c b/src/pc/lua/smlua_cobject_autogen.c index 8db814e6..987a27f2 100644 --- a/src/pc/lua/smlua_cobject_autogen.c +++ b/src/pc/lua/smlua_cobject_autogen.c @@ -831,7 +831,7 @@ static struct LuaObjectField sNetworkPlayerFields[LUA_NETWORK_PLAYER_FIELD_COUNT { "type", LVT_U8, offsetof(struct NetworkPlayer, type), true, LOT_NONE }, }; -#define LUA_OBJECT_FIELD_COUNT 753 +#define LUA_OBJECT_FIELD_COUNT 754 static struct LuaObjectField sObjectFields[LUA_OBJECT_FIELD_COUNT] = { { "activeFlags", LVT_S16, offsetof(struct Object, activeFlags), false, LOT_NONE }, { "areaTimer", LVT_U32, offsetof(struct Object, areaTimer), false, LOT_NONE }, @@ -971,6 +971,7 @@ static struct LuaObjectField sObjectFields[LUA_OBJECT_FIELD_COUNT] = { { "oBubbaUnkFC", LVT_S32, offsetof(struct Object, oBubbaUnkFC), false, LOT_NONE }, { "oBulletBillInitialMoveYaw", LVT_S32, offsetof(struct Object, oBulletBillInitialMoveYaw), false, LOT_NONE }, { "oBullyKBTimerAndMinionKOCounter", LVT_S32, offsetof(struct Object, oBullyKBTimerAndMinionKOCounter), false, LOT_NONE }, + { "oBullyLastNetworkPlayerIndex", LVT_S16, offsetof(struct Object, oBullyLastNetworkPlayerIndex), false, LOT_NONE }, { "oBullyMarioCollisionAngle", LVT_S32, offsetof(struct Object, oBullyMarioCollisionAngle), false, LOT_NONE }, { "oBullyPrevX", LVT_F32, offsetof(struct Object, oBullyPrevX), false, LOT_NONE }, { "oBullyPrevY", LVT_F32, offsetof(struct Object, oBullyPrevY), false, LOT_NONE }, diff --git a/src/pc/lua/smlua_functions_autogen.c b/src/pc/lua/smlua_functions_autogen.c index aae414dd..c060f316 100644 --- a/src/pc/lua/smlua_functions_autogen.c +++ b/src/pc/lua/smlua_functions_autogen.c @@ -7822,6 +7822,19 @@ int smlua_func_mario_throw_held_object(lua_State* L) { return 1; } +int smlua_func_passes_pvp_interaction_checks(lua_State* L) { + if(!smlua_functions_valid_param_count(L, 2)) { return 0; } + + struct MarioState* attacker = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIOSTATE); + if (!gSmLuaConvertSuccess) { return 0; } + struct MarioState* victim = (struct MarioState*)smlua_to_cobject(L, 2, LOT_MARIOSTATE); + if (!gSmLuaConvertSuccess) { return 0; } + + lua_pushinteger(L, passes_pvp_interaction_checks(attacker, victim)); + + return 1; +} + ////////////////// // level_info.h // ////////////////// @@ -16490,6 +16503,7 @@ void smlua_bind_functions_autogen(void) { smlua_bind_function(L, "mario_stop_riding_and_holding", smlua_func_mario_stop_riding_and_holding); smlua_bind_function(L, "mario_stop_riding_object", smlua_func_mario_stop_riding_object); smlua_bind_function(L, "mario_throw_held_object", smlua_func_mario_throw_held_object); + smlua_bind_function(L, "passes_pvp_interaction_checks", smlua_func_passes_pvp_interaction_checks); // level_info.h smlua_bind_function(L, "get_level_name", smlua_func_get_level_name);