diff --git a/autogen/lua_definitions/constants.lua b/autogen/lua_definitions/constants.lua index 4825bbe6..a3143cc5 100644 --- a/autogen/lua_definitions/constants.lua +++ b/autogen/lua_definitions/constants.lua @@ -9333,7 +9333,10 @@ HOOK_ON_PLAY_SOUND = 41 HOOK_ON_SEQ_LOAD = 42 --- @type LuaHookedEventType -HOOK_MAX = 43 +HOOK_ON_ATTACK_OBJECT = 43 + +--- @type LuaHookedEventType +HOOK_MAX = 44 --- @class HudDisplayFlags diff --git a/docs/lua/constants.md b/docs/lua/constants.md index 6f6a27bf..f180873e 100644 --- a/docs/lua/constants.md +++ b/docs/lua/constants.md @@ -3335,7 +3335,8 @@ | HOOK_ON_OBJECT_LOAD | 40 | | HOOK_ON_PLAY_SOUND | 41 | | HOOK_ON_SEQ_LOAD | 42 | -| HOOK_MAX | 43 | +| HOOK_ON_ATTACK_OBJECT | 43 | +| HOOK_MAX | 44 | [:arrow_up_small:](#) diff --git a/docs/lua/guides/hooks.md b/docs/lua/guides/hooks.md index 486eece3..fbec8363 100644 --- a/docs/lua/guides/hooks.md +++ b/docs/lua/guides/hooks.md @@ -129,6 +129,8 @@ The lua functions sent to `hook_event()` will be automatically called by SM64 wh | HOOK_OVERRIDE_PHYS_STEP_DEFACTO_SPEED | Called when slope defacto speed for walking is being calculated, overrides the floor normal in the equation | [MarioState](../structs.md#MarioState) mario | | HOOK_ON_OBJECT_LOAD | Called when an object is spawned in | [Object](../structs.md#Object) obj | | HOOK_ON_PLAY_SOUND | Called when a sound is going to play, return a `SOUND_*` constant or `NO_SOUND` to override the sound | `integer` soundBits, `Vec3f` pos | +| HOOK_ON_SEQ_LOAD | Called when a sequence is going to play, return a `SEQ_*` constant to override the sequence. `SEQ_SOUND_PLAYER` (0) is silence. | `integer` player, `integer` seqID | +| HOOK_ON_ATTACK_OBJECT | Called when a player attacks an object. May be double-fired in some cases, you'll need to write special code for this | [MarioState](structs.md#MarioState) attacker, [Object](structs.md#Object) victim, `integer` interactionId | ### Parameters diff --git a/src/game/interaction.c b/src/game/interaction.c index c4c877ff..31ba3be4 100644 --- a/src/game/interaction.c +++ b/src/game/interaction.c @@ -234,7 +234,7 @@ u32 determine_interaction(struct MarioState *m, struct Object *o) { /** * Sets the interaction types for INT_STATUS_INTERACTED, INT_STATUS_WAS_ATTACKED */ -u32 attack_object(struct Object *o, s32 interaction) { +u32 attack_object(struct MarioState* m, struct Object *o, s32 interaction) { if (!o) { return 0; } u32 attackType = 0; @@ -264,6 +264,8 @@ u32 attack_object(struct Object *o, s32 interaction) { } o->oInteractStatus = attackType + (INT_STATUS_INTERACTED | INT_STATUS_WAS_ATTACKED); + + smlua_call_event_hooks_interact_params_no_ret(HOOK_ON_ATTACK_OBJECT, m, o, interaction); return attackType; } @@ -1681,7 +1683,7 @@ u32 interact_bully(struct MarioState *m, UNUSED u32 interactType, struct Object o->oMoveAngleYaw = m->faceAngle[1]; o->oForwardVel = 3392.0f / o->hitboxRadius; - attack_object(o, interaction); + attack_object(m, o, interaction); bounce_back_from_attack(m, interaction); return TRUE; } @@ -1767,7 +1769,7 @@ u32 interact_hit_from_below(struct MarioState *m, UNUSED u32 interactType, struc if (interaction & INT_ANY_ATTACK) { queue_rumble_data_mario(m, 5, 80); - attack_object(o, interaction); + attack_object(m, o, interaction); bounce_back_from_attack(m, interaction); if (interaction & INT_HIT_FROM_BELOW) { @@ -1808,7 +1810,7 @@ u32 interact_bounce_top(struct MarioState *m, UNUSED u32 interactType, struct Ob if (interaction & INT_ATTACK_NOT_FROM_BELOW) { queue_rumble_data_mario(m, 5, 80); - attack_object(o, interaction); + attack_object(m, o, interaction); bounce_back_from_attack(m, interaction); if (interaction & INT_HIT_FROM_ABOVE) { @@ -1870,7 +1872,7 @@ u32 interact_breakable(struct MarioState *m, UNUSED u32 interactType, struct Obj u32 interaction = determine_interaction(m, o); if (interaction & INT_ATTACK_NOT_WEAK_FROM_ABOVE) { - attack_object(o, interaction); + attack_object(m, o, interaction); bounce_back_from_attack(m, interaction); m->interactObj = o; @@ -1913,7 +1915,7 @@ u32 interact_koopa_shell(struct MarioState *m, UNUSED u32 interactType, struct O m->usedObj = o; m->riddenObj = o; - attack_object(o, interaction); + attack_object(m, o, interaction); update_mario_sound_and_camera(m); if (m->playerIndex == 0) { play_shell_music(); } mario_drop_held_object(m); @@ -2099,7 +2101,7 @@ u32 interact_grabbable(struct MarioState *m, u32 interactType, struct Object *o) if (o->oInteractionSubtype & INT_SUBTYPE_KICKABLE) { u32 interaction = determine_interaction(m, o); if (interaction & (INT_KICK | INT_TRIP)) { - attack_object(o, interaction); + attack_object(m, o, interaction); bounce_back_from_attack(m, interaction); return FALSE; } diff --git a/src/pc/lua/smlua_constants_autogen.c b/src/pc/lua/smlua_constants_autogen.c index 3eed2069..f6722c90 100644 --- a/src/pc/lua/smlua_constants_autogen.c +++ b/src/pc/lua/smlua_constants_autogen.c @@ -3310,7 +3310,8 @@ char gSmluaConstants[] = "" "HOOK_ON_OBJECT_LOAD = 40\n" "HOOK_ON_PLAY_SOUND = 41\n" "HOOK_ON_SEQ_LOAD = 42\n" -"HOOK_MAX = 43\n" +"HOOK_ON_ATTACK_OBJECT = 43\n" +"HOOK_MAX = 44\n" "ACTION_HOOK_EVERY_FRAME = 0\n" "ACTION_HOOK_GRAVITY = 1\n" "ACTION_HOOK_MAX = 2\n" diff --git a/src/pc/lua/smlua_hooks.c b/src/pc/lua/smlua_hooks.c index da7338ad..9c3f7df9 100644 --- a/src/pc/lua/smlua_hooks.c +++ b/src/pc/lua/smlua_hooks.c @@ -458,6 +458,34 @@ void smlua_call_event_hooks_interact_params_ret_bool(enum LuaHookedEventType hoo } } +void smlua_call_event_hooks_interact_params_no_ret(enum LuaHookedEventType hookType, struct MarioState* m, struct Object* obj, u32 interactType) { + lua_State* L = gLuaState; + if (L == NULL) { return; } + struct LuaHookedEvent* hook = &sHookedEvents[hookType]; + for (int i = 0; i < hook->count; i++) { + // push the callback onto the stack + lua_rawgeti(L, LUA_REGISTRYINDEX, hook->reference[i]); + + // push mario state + lua_getglobal(L, "gMarioStates"); + lua_pushinteger(L, m->playerIndex); + lua_gettable(L, -2); + lua_remove(L, -2); + + // push object + smlua_push_object(L, LOT_OBJECT, obj); + + // push interact type + lua_pushinteger(L, interactType); + + // call the callback + if (0 != smlua_call_hook(L, 3, 0, 0, hook->mod[i])) { + LOG_LUA("Failed to call the callback: %u", hookType); + continue; + } + } +} + void smlua_call_event_hooks_object_param(enum LuaHookedEventType hookType, struct Object* obj) { lua_State* L = gLuaState; if (L == NULL) { return; } diff --git a/src/pc/lua/smlua_hooks.h b/src/pc/lua/smlua_hooks.h index 47e6ac96..3d55399e 100644 --- a/src/pc/lua/smlua_hooks.h +++ b/src/pc/lua/smlua_hooks.h @@ -54,6 +54,7 @@ enum LuaHookedEventType { HOOK_ON_OBJECT_LOAD, HOOK_ON_PLAY_SOUND, HOOK_ON_SEQ_LOAD, + HOOK_ON_ATTACK_OBJECT, HOOK_MAX, }; @@ -101,6 +102,7 @@ static const char* LuaHookedEventTypeName[] = { "HOOK_ON_OBJECT_LOAD", "HOOK_ON_PLAY_SOUND", "HOOK_ON_SEQ_LOAD", + "HOOK_ON_ATTACK_OBJECT", "HOOK_MAX" }; @@ -131,6 +133,7 @@ void smlua_call_event_hooks_mario_params(enum LuaHookedEventType hookType, struc void smlua_call_event_hooks_mario_params_ret_bool(enum LuaHookedEventType hookType, struct MarioState* m1, struct MarioState* m2, u32 interaction, bool* returnValue); void smlua_call_event_hooks_interact_params(enum LuaHookedEventType hookType, struct MarioState* m, struct Object* obj, u32 interactType, bool interactValue); void smlua_call_event_hooks_interact_params_ret_bool(enum LuaHookedEventType hookType, struct MarioState* m, struct Object* obj, u32 interactType, bool* returnValue); +void smlua_call_event_hooks_interact_params_no_ret(enum LuaHookedEventType hookType, struct MarioState* m, struct Object* obj, u32 interactType); void smlua_call_event_hooks_object_param(enum LuaHookedEventType hookType, struct Object* obj); void smlua_call_event_hooks_object_model_param(enum LuaHookedEventType hookType, struct Object* obj, s32 modelID); bool smlua_call_event_hooks_ret_int(enum LuaHookedEventType hookType, s32* returnValue);