Added HOOK_ON_DEATH

This commit is contained in:
MysterD 2022-04-21 18:34:12 -07:00
parent c292793470
commit ef7dc41560
19 changed files with 209 additions and 43 deletions

View file

@ -4404,7 +4404,7 @@ PLAYER_INTERACTIONS_SOLID = 1
PLAYER_INTERACTIONS_PVP = 2
--- @type integer
MAX_RX_SEQ_IDS = 16
MAX_RX_SEQ_IDS = 64
--- @type integer
NETWORK_PLAYER_TIMEOUT = 10
@ -7849,7 +7849,10 @@ HOOK_ON_SET_CAMERA_MODE = 18
HOOK_ON_OBJECT_RENDER = 19
--- @type LuaHookedEventType
HOOK_MAX = 20
HOOK_ON_DEATH = 20
--- @type LuaHookedEventType
HOOK_MAX = 21
--- @class ModelExtendedId

View file

@ -3930,6 +3930,12 @@ function hurt_and_set_mario_action(m, action, actionArg, hurtCounter)
-- ...
end
--- @param m MarioState
--- @return nil
function init_single_mario(m)
-- ...
end
--- @param m MarioState
--- @return integer
function is_anim_at_end(m)

View file

@ -2754,7 +2754,8 @@
| HOOK_GET_STAR_COLLECTION_DIALOG | 17 |
| HOOK_ON_SET_CAMERA_MODE | 18 |
| HOOK_ON_OBJECT_RENDER | 19 |
| HOOK_MAX | 20 |
| HOOK_ON_DEATH | 20 |
| HOOK_MAX | 21 |
[:arrow_up_small:](#)

View file

@ -765,6 +765,7 @@
- [find_mario_anim_flags_and_translation](#find_mario_anim_flags_and_translation)
- [force_idle_state](#force_idle_state)
- [hurt_and_set_mario_action](#hurt_and_set_mario_action)
- [init_single_mario](#init_single_mario)
- [is_anim_at_end](#is_anim_at_end)
- [is_anim_past_end](#is_anim_past_end)
- [is_anim_past_frame](#is_anim_past_frame)
@ -14941,6 +14942,26 @@ The `reliable` field will ensure that the packet arrives, but should be used spa
<br />
## [init_single_mario](#init_single_mario)
### Lua Example
`init_single_mario(m)`
### Parameters
| Field | Type |
| ----- | ---- |
| m | [MarioState](structs.md#MarioState) |
### Returns
- None
### C Prototype
`void init_single_mario(struct MarioState* m);`
[:arrow_up_small:](#)
<br />
## [is_anim_at_end](#is_anim_at_end)
### Lua Example

View file

@ -106,6 +106,7 @@ The lua functions sent to `hook_event()` will be automatically called by SM64 wh
| HOOK_GET_STAR_COLLECTION_DIALOG | Called when the local player collects a star, return a [DialogId](constants.md#enum-DialogId) to show a message | None |
| HOOK_ON_SET_CAMERA_MODE | Called when the camera mode gets set, return `false` to prevent the camera mode from being set | [Camera](structs.md#Camera), `integer` mode, `integer` frames |
| HOOK_ON_OBJECT_RENDER | Called right before an object is rendered. **Note:** You must set the `hookRender` field of the object to a non-zero value | [Object](structs.md#Object) |
| HOOK_ON_DEATH | Called when the local player dies, return `false` to prevent normal death sequence | [MarioState](structs.md#MarioState) |
### Parameters

View file

@ -858,16 +858,24 @@ static void level_cmd_place_object_ext(void) {
u16 modIndex = gLevelScriptModIndex;
const char* behStr = dynos_level_get_token(CMD_GET(u32, 20));
if (gLevelScriptModIndex == -1) {
LOG_ERROR("Could not find level script mod index");
sCurrentCmd = CMD_NEXT;
return;
}
gSmLuaConvertSuccess = true;
gSmLuaSuppressErrors = true;
enum BehaviorId behId = smlua_get_mod_variable(modIndex, behStr);
gSmLuaSuppressErrors = false;
if (!gSmLuaConvertSuccess) {
gSmLuaConvertSuccess = true;
behId = smlua_get_any_mod_variable(behStr);
}
if ((gLevelScriptModIndex == -1) || !gSmLuaConvertSuccess) {
LOG_ERROR("Failed to place custom object: %u :: %s", behId, behStr);
if (!gSmLuaConvertSuccess) {
LOG_LUA("Failed to place custom object, could not find behavior '%s'", behStr);
sCurrentCmd = CMD_NEXT;
return;
}
@ -907,22 +915,37 @@ static void level_cmd_place_object_ext2(void) {
const char* modelStr = dynos_level_get_token(CMD_GET(u32, 20));
const char* behStr = dynos_level_get_token(CMD_GET(u32, 24));
if (gLevelScriptModIndex == -1) {
LOG_ERROR("Could not find level script mod index");
sCurrentCmd = CMD_NEXT;
return;
}
gSmLuaConvertSuccess = true;
gSmLuaSuppressErrors = true;
enum ModelExtendedId modelId = smlua_get_mod_variable(modIndex, modelStr);
gSmLuaSuppressErrors = false;
if (!gSmLuaConvertSuccess) {
gSmLuaConvertSuccess = true;
modelId = smlua_get_any_mod_variable(modelStr);
}
if (!gSmLuaConvertSuccess) {
LOG_LUA("Failed to place custom object, could not find model '%s'", modelStr);
sCurrentCmd = CMD_NEXT;
return;
}
gSmLuaConvertSuccess = true;
gSmLuaSuppressErrors = true;
enum BehaviorId behId = smlua_get_mod_variable(modIndex, behStr);
gSmLuaSuppressErrors = false;
if (!gSmLuaConvertSuccess) {
gSmLuaConvertSuccess = true;
behId = smlua_get_any_mod_variable(behStr);
}
if ((gLevelScriptModIndex == -1) || !gSmLuaConvertSuccess) {
LOG_ERROR("Failed to place custom object: %u, %u", modelId, behId);
if (!gSmLuaConvertSuccess) {
LOG_LUA("Failed to place custom object, could not find behavior '%s'", behStr);
sCurrentCmd = CMD_NEXT;
return;
}

View file

@ -2209,6 +2209,10 @@ void check_death_barrier(struct MarioState *m) {
if (m->playerIndex != 0) { return; }
if (m->pos[1] < m->floorHeight + 2048.0f) {
bool allowDeath = true;
smlua_call_event_hooks_mario_param_ret_bool(HOOK_ON_DEATH, m, &allowDeath);
if (!allowDeath) { return; }
if (mario_can_bubble(m)) {
switch (gCurrCourseNum) {
case COURSE_COTMC: // (20) Cavern of the Metal Cap

View file

@ -2107,7 +2107,7 @@ s32 force_idle_state(struct MarioState* m) {
* INITIALIZATION *
**************************************************/
static void init_single_mario(struct MarioState* m) {
void init_single_mario(struct MarioState* m) {
u16 playerIndex = m->playerIndex;
struct SpawnInfo* spawnInfo = &gPlayerSpawnInfos[playerIndex];

View file

@ -54,6 +54,7 @@ s32 transition_submerged_to_walking(struct MarioState *m);
s32 set_water_plunge_action(struct MarioState *m);
s32 execute_mario_action(UNUSED struct Object *o);
s32 force_idle_state(struct MarioState* m);
void init_single_mario(struct MarioState* m);
void init_mario(void);
void init_mario_from_save_file(void);

View file

@ -1576,11 +1576,20 @@ s32 act_lava_boost(struct MarioState *m) {
if (m != &gMarioStates[0]) {
// never kill remote marios
m->health = 0x100;
} else if (mario_can_bubble(m)) {
m->health = 0xFF;
mario_set_bubbled(m);
} else {
level_trigger_warp(m, WARP_OP_DEATH);
bool allowDeath = true;
smlua_call_event_hooks_mario_param_ret_bool(HOOK_ON_DEATH, m, &allowDeath);
if (!allowDeath) {
reset_rumble_timers(m);
return FALSE;
}
if (mario_can_bubble(m)) {
m->health = 0xFF;
mario_set_bubbled(m);
} else {
level_trigger_warp(m, WARP_OP_DEATH);
}
}
}

View file

@ -35,6 +35,7 @@
#include "pc/configfile.h"
#include "pc/network/network.h"
#include "pc/lua/smlua.h"
#include "pc/lua/smlua_hooks.h"
// TODO: put this elsewhere
enum SaveOption { SAVE_OPT_SAVE_AND_CONTINUE = 1, /*SAVE_OPT_SAVE_AND_QUIT, SAVE_OPT_SAVE_EXIT_GAME,*/ SAVE_OPT_CONTINUE_DONT_SAVE };
@ -777,10 +778,16 @@ s32 common_death_handler(struct MarioState *m, s32 animation, s32 frameToDeathWa
if (animFrame == frameToDeathWarp) {
if (m->playerIndex != 0) {
// do nothing
} else if (mario_can_bubble(m)) {
mario_set_bubbled(m);
} else {
level_trigger_warp(m, WARP_OP_DEATH);
bool allowDeath = true;
smlua_call_event_hooks_mario_param_ret_bool(HOOK_ON_DEATH, m, &allowDeath);
if (!allowDeath) { return animFrame; }
if (mario_can_bubble(m)) {
mario_set_bubbled(m);
} else {
level_trigger_warp(m, WARP_OP_DEATH);
}
}
}
m->marioBodyState->eyeState = MARIO_EYES_DEAD;
@ -842,12 +849,18 @@ s32 act_quicksand_death(struct MarioState *m) {
if ((m->quicksandDepth += 5.0f) >= 180.0f) {
if (m->playerIndex != 0) {
// do nothing
} else if (mario_can_bubble(m)) {
mario_set_bubbled(m);
} else {
level_trigger_warp(m, WARP_OP_DEATH);
m->actionState = 2;
bool allowDeath = true;
smlua_call_event_hooks_mario_param_ret_bool(HOOK_ON_DEATH, m, &allowDeath);
if (!allowDeath) { return FALSE; }
if (mario_can_bubble(m)) {
mario_set_bubbled(m);
} else {
level_trigger_warp(m, WARP_OP_DEATH);
}
}
m->actionState = 2;
}
}
stationary_ground_step(m);
@ -862,11 +875,17 @@ s32 act_eaten_by_bubba(struct MarioState *m) {
if (m->actionTimer++ == 60) {
if (m->playerIndex != 0) {
// do nothing
} else if (mario_can_bubble(m)) {
m->health = 0xFF;
mario_set_bubbled(m);
} else {
level_trigger_warp(m, WARP_OP_DEATH);
bool allowDeath = true;
smlua_call_event_hooks_mario_param_ret_bool(HOOK_ON_DEATH, m, &allowDeath);
if (!allowDeath) { return FALSE; }
if (mario_can_bubble(m)) {
m->health = 0xFF;
mario_set_bubbled(m);
} else {
level_trigger_warp(m, WARP_OP_DEATH);
}
}
}
@ -1743,15 +1762,21 @@ s32 act_squished(struct MarioState *m) {
if (m->playerIndex != 0) {
// never kill remote marios
m->health = 0x100;
} else if (mario_can_bubble(m)) {
mario_set_bubbled(m);
} else {
// 0 units of health
m->health = 0x00FF;
m->hurtCounter = 0;
level_trigger_warp(m, WARP_OP_DEATH);
// woosh, he's gone!
set_mario_action(m, ACT_DISAPPEARED, 0);
bool allowDeath = true;
smlua_call_event_hooks_mario_param_ret_bool(HOOK_ON_DEATH, m, &allowDeath);
if (!allowDeath) { return FALSE; }
if (mario_can_bubble(m)) {
mario_set_bubbled(m);
} else {
// 0 units of health
m->health = 0x00FF;
m->hurtCounter = 0;
level_trigger_warp(m, WARP_OP_DEATH);
// woosh, he's gone!
set_mario_action(m, ACT_DISAPPEARED, 0);
}
}
}
stop_and_set_height_to_floor(m);

View file

@ -20,6 +20,7 @@
#include "pc/configfile.h"
#include "pc/network/network.h"
#include "pc/lua/smlua.h"
#include "pc/lua/smlua_hooks.h"
#define MIN_SWIM_STRENGTH 160
#define MIN_SWIM_SPEED 16.0f
@ -944,10 +945,16 @@ static s32 act_drowning(struct MarioState *m) {
if (m->marioObj->header.gfx.animInfo.animFrame == 30) {
if (m->playerIndex != 0) {
// do nothing
} else if (mario_can_bubble(m)) {
mario_set_bubbled(m);
} else {
level_trigger_warp(m, WARP_OP_DEATH);
bool allowDeath = true;
smlua_call_event_hooks_mario_param_ret_bool(HOOK_ON_DEATH, m, &allowDeath);
if (!allowDeath) { return FALSE; }
if (mario_can_bubble(m)) {
mario_set_bubbled(m);
} else {
level_trigger_warp(m, WARP_OP_DEATH);
}
}
}
break;
@ -972,10 +979,16 @@ static s32 act_water_death(struct MarioState *m) {
if (set_mario_animation(m, MARIO_ANIM_WATER_DYING) == 35) {
if (m->playerIndex != 0) {
// do nothing
} else if (mario_can_bubble(m)) {
mario_set_bubbled(m);
} else {
level_trigger_warp(m, WARP_OP_DEATH);
bool allowDeath = true;
smlua_call_event_hooks_mario_param_ret_bool(HOOK_ON_DEATH, m, &allowDeath);
if (!allowDeath) { return FALSE; }
if (mario_can_bubble(m)) {
mario_set_bubbled(m);
} else {
level_trigger_warp(m, WARP_OP_DEATH);
}
}
}
@ -1090,10 +1103,16 @@ static s32 act_caught_in_whirlpool(struct MarioState *m) {
if (distance < 16.1f && m->actionTimer++ == 16) {
if (m->playerIndex != 0) {
// do nothing
} else if (mario_can_bubble(m)) {
mario_set_bubbled(m);
} else {
level_trigger_warp(m, WARP_OP_DEATH);
bool allowDeath = true;
smlua_call_event_hooks_mario_param_ret_bool(HOOK_ON_DEATH, m, &allowDeath);
if (!allowDeath) { reset_rumble_timers(m); return FALSE; }
if (mario_can_bubble(m)) {
mario_set_bubbled(m);
} else {
level_trigger_warp(m, WARP_OP_DEATH);
}
}
}
}

View file

@ -8,6 +8,7 @@
lua_State* gLuaState = NULL;
u8 gLuaInitializingScript = 0;
u8 gSmLuaSuppressErrors = 0;
struct Mod* gLuaLoadingMod = NULL;
struct Mod* gLuaActiveMod = NULL;
struct Mod* gLuaLastHookMod = NULL;

View file

@ -19,7 +19,7 @@
#include "pc/debuglog.h"
#define LOG_LUA(...) ( _debuglog_print_log("LUA ", __FILE__), printf(__VA_ARGS__), printf("\n"), smlua_mod_error() )
#define LOG_LUA(...) { if (!gSmLuaSuppressErrors) { _debuglog_print_log("LUA ", __FILE__), printf(__VA_ARGS__), printf("\n"), smlua_mod_error(); } }
#ifdef DEVELOPMENT
#define LUA_STACK_CHECK_BEGIN() int __LUA_STACK_TOP = lua_gettop(gLuaState)
@ -31,6 +31,7 @@
extern lua_State* gLuaState;
extern u8 gLuaInitializingScript;
extern u8 gSmLuaSuppressErrors;
extern struct Mod* gLuaLoadingMod;
extern struct Mod* gLuaActiveMod;
extern struct Mod* gLuaLastHookMod;

View file

@ -1656,7 +1656,7 @@ char gSmluaConstants[] = ""
"UNKNOWN_GLOBAL_INDEX = (-1)\n"
"UNKNOWN_NETWORK_INDEX = (-1)\n"
"NETWORK_PLAYER_TIMEOUT = 10\n"
"MAX_RX_SEQ_IDS = 16\n"
"MAX_RX_SEQ_IDS = 64\n"
"NPT_UNKNOWN = 0\n"
"NPT_LOCAL = 1\n"
"NPT_SERVER = 2\n"
@ -2797,7 +2797,8 @@ char gSmluaConstants[] = ""
"HOOK_GET_STAR_COLLECTION_DIALOG = 17\n"
"HOOK_ON_SET_CAMERA_MODE = 18\n"
"HOOK_ON_OBJECT_RENDER = 19\n"
"HOOK_MAX = 20\n"
"HOOK_ON_DEATH = 20\n"
"HOOK_MAX = 21\n"
"E_MODEL_NONE = 0\n"
"E_MODEL_MARIO = 1\n"
"E_MODEL_SMOKE = 2\n"

View file

@ -8026,6 +8026,17 @@ int smlua_func_hurt_and_set_mario_action(lua_State* L) {
return 1;
}
int smlua_func_init_single_mario(lua_State* L) {
if(!smlua_functions_valid_param_count(L, 1)) { return 0; }
struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIOSTATE);
if (!gSmLuaConvertSuccess) { return 0; }
init_single_mario(m);
return 1;
}
int smlua_func_is_anim_at_end(lua_State* L) {
if(!smlua_functions_valid_param_count(L, 1)) { return 0; }
@ -16549,6 +16560,7 @@ void smlua_bind_functions_autogen(void) {
smlua_bind_function(L, "find_mario_anim_flags_and_translation", smlua_func_find_mario_anim_flags_and_translation);
smlua_bind_function(L, "force_idle_state", smlua_func_force_idle_state);
smlua_bind_function(L, "hurt_and_set_mario_action", smlua_func_hurt_and_set_mario_action);
smlua_bind_function(L, "init_single_mario", smlua_func_init_single_mario);
smlua_bind_function(L, "is_anim_at_end", smlua_func_is_anim_at_end);
smlua_bind_function(L, "is_anim_past_end", smlua_func_is_anim_past_end);
smlua_bind_function(L, "is_anim_past_frame", smlua_func_is_anim_past_frame);

View file

@ -223,6 +223,37 @@ void smlua_call_event_hooks_mario_param(enum LuaHookedEventType hookType, struct
}
}
void smlua_call_event_hooks_mario_param_ret_bool(enum LuaHookedEventType hookType, struct MarioState* m, bool* returnValue) {
lua_State* L = gLuaState;
if (L == NULL) { return; }
struct LuaHookedEvent* hook = &sHookedEvents[hookType];
for (int i = 0; i < hook->count; i++) {
s32 prevTop = lua_gettop(L);
// 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);
// call the callback
if (0 != smlua_call_hook(L, 1, 1, 0, hook->mod[i])) {
LOG_LUA("Failed to call the callback: %u, %s", hookType, lua_tostring(L, -1));
smlua_logline();
continue;
}
// output the return value
if (lua_type(L, -1) == LUA_TBOOLEAN) {
*returnValue = smlua_to_boolean(L, -1);
}
lua_settop(L, prevTop);
}
}
void smlua_call_event_hooks_mario_params(enum LuaHookedEventType hookType, struct MarioState* m1, struct MarioState* m2) {
lua_State* L = gLuaState;
if (L == NULL) { return; }

View file

@ -28,6 +28,7 @@ enum LuaHookedEventType {
HOOK_GET_STAR_COLLECTION_DIALOG,
HOOK_ON_SET_CAMERA_MODE,
HOOK_ON_OBJECT_RENDER,
HOOK_ON_DEATH,
HOOK_MAX,
};
@ -52,6 +53,7 @@ static char* LuaHookedEventTypeName[] = {
"HOOK_GET_STAR_COLLECTION_DIALOG",
"HOOK_ON_SET_CAMERA_MODE",
"HOOK_ON_OBJECT_RENDER",
"HOOK_ON_DEATH",
"HOOK_MAX"
};
@ -61,6 +63,7 @@ void smlua_call_event_hooks(enum LuaHookedEventType hookType);
void smlua_call_event_hooks_bool_param(enum LuaHookedEventType hookType, bool value);
void smlua_call_event_hooks_bool_param_ret_bool(enum LuaHookedEventType hookType, bool value, bool* returnValue);
void smlua_call_event_hooks_mario_param(enum LuaHookedEventType hookType, struct MarioState* m);
void smlua_call_event_hooks_mario_param_ret_bool(enum LuaHookedEventType hookType, struct MarioState* m, bool* returnValue);
void smlua_call_event_hooks_mario_params(enum LuaHookedEventType hookType, struct MarioState* m1, struct MarioState* m2);
void smlua_call_event_hooks_mario_params_ret_bool(enum LuaHookedEventType hookType, struct MarioState* m1, struct MarioState* m2, bool* returnValue);
void smlua_call_event_hooks_interact_params(enum LuaHookedEventType hookType, struct MarioState* m, struct Object* obj, u32 interactType, bool interactValue);

View file

@ -397,6 +397,7 @@ s64 smlua_get_mod_variable(u16 modIndex, const char* variable) {
s64 smlua_get_any_mod_variable(const char* variable) {
lua_State* L = gLuaState;
u8 prevSuppress = gSmLuaSuppressErrors;
s64 value = 0;
for (s32 i = 0; i < gActiveMods.entryCount; i++) {
@ -406,15 +407,18 @@ s64 smlua_get_any_mod_variable(const char* variable) {
int prevTop = lua_gettop(L);
lua_getglobal(L, "_G"); // get global table
lua_getfield(L, LUA_REGISTRYINDEX, mod->relativePath); // get the file's "global" table
gSmLuaSuppressErrors = true;
value = smlua_get_integer_field(-1, (char*)variable);
lua_settop(L, prevTop);
if (gSmLuaConvertSuccess) {
gSmLuaSuppressErrors = prevSuppress;
return value;
}
}
// return variable
gSmLuaSuppressErrors = prevSuppress;
return value;
}