Prevent even more possible crashes from the mod api

This commit is contained in:
MysterD 2023-05-11 01:46:27 -07:00
parent f785050ccb
commit 039be71266
12 changed files with 5735 additions and 6 deletions

View file

@ -64,6 +64,11 @@ function rnd_number()
return t[math.random(#t)] return t[math.random(#t)]
end end
function rnd_boolean()
t = { nil, false, true }
return t[math.random(#t)]
end
function rnd_Vec3s() function rnd_Vec3s()
t = { nil, { x = rnd_integer(), y = rnd_integer(), z = rnd_integer() } } t = { nil, { x = rnd_integer(), y = rnd_integer(), z = rnd_integer() } }
return t[math.random(#t)] return t[math.random(#t)]
@ -124,18 +129,30 @@ function rnd_PlayerGeometry()
return t[math.random(#t)] return t[math.random(#t)]
end end
function rnd_Surface()
t = { nil, gMarioStates[0].ceil, gMarioStates[0].floor }
return t[math.random(#t)]
end
-------- --------
function fuzz_functions() function fuzz_functions()
-- $[FUNCS] -- $[FUNCS]
end end
id_bhvFuncs = hook_behavior(nil, OBJ_LIST_DEFAULT, true, fuzz_functions, nil, 'id_bhvFuncs')
-------- --------
function fuzz_structs() function fuzz_structs()
end end
function update()
fuzz_functions()
end
hook_chat_command('fuzz-funcs', 'funcs', fuzz_functions) hook_chat_command('fuzz-funcs', 'funcs', fuzz_functions)
hook_chat_command('fuzz-structs', 'structs', fuzz_structs) hook_chat_command('fuzz-structs', 'structs', fuzz_structs)
fuzz_functions() hook_event(HOOK_UPDATE, update)
print('!')
spawn_non_sync_object(id_bhvFuncs, E_MODEL_SPINY_BALL, 0, 0, 0, nil)

5582
grind.log Normal file

File diff suppressed because it is too large Load diff

View file

@ -1762,6 +1762,7 @@ static void update_game_sound(void) {
* Called from threads: thread4_sound, thread5_game_loop * Called from threads: thread4_sound, thread5_game_loop
*/ */
static void seq_player_play_sequence(u8 player, u8 seqId, u16 arg2) { static void seq_player_play_sequence(u8 player, u8 seqId, u16 arg2) {
if (player >= SEQUENCE_PLAYERS) { return; }
u8 targetVolume; u8 targetVolume;
u8 i; u8 i;
@ -1840,6 +1841,8 @@ void fade_volume_scale(u8 player, u8 targetScale, u16 fadeDuration) {
*/ */
static void fade_channel_volume_scale(u8 player, u8 channelIndex, u8 targetScale, u16 fadeDuration) { static void fade_channel_volume_scale(u8 player, u8 channelIndex, u8 targetScale, u16 fadeDuration) {
struct ChannelVolumeScaleFade *temp; struct ChannelVolumeScaleFade *temp;
if (player >= SEQUENCE_PLAYERS) { return; }
if (channelIndex >= CHANNELS_MAX) { return; }
if (gSequencePlayers[player].channels[channelIndex] != &gSequenceChannelNone) { if (gSequencePlayers[player].channels[channelIndex] != &gSequenceChannelNone) {
temp = &sVolumeScaleFades[player][channelIndex]; temp = &sVolumeScaleFades[player][channelIndex];
@ -1856,6 +1859,7 @@ static void fade_channel_volume_scale(u8 player, u8 channelIndex, u8 targetScale
* Called from threads: thread4_sound, thread5_game_loop (EU only) * Called from threads: thread4_sound, thread5_game_loop (EU only)
*/ */
static void fade_seqplayer_channels(u8 player) { static void fade_seqplayer_channels(u8 player) {
if (player >= SEQUENCE_PLAYERS) { return; }
// Loop over channels // Loop over channels
for (u8 i = 0; i < CHANNELS_MAX; i++) { for (u8 i = 0; i < CHANNELS_MAX; i++) {
if (gSequencePlayers[player].channels[i] != &gSequenceChannelNone if (gSequencePlayers[player].channels[i] != &gSequenceChannelNone
@ -2260,6 +2264,9 @@ void stop_sound(u32 soundBits, f32 *pos) {
sSoundBanks[bank][soundIndex].soundBits = NO_SOUND; sSoundBanks[bank][soundIndex].soundBits = NO_SOUND;
soundIndex = 0xff; // break soundIndex = 0xff; // break
} else { } else {
if (soundIndex == sSoundBanks[bank][soundIndex].next) {
break;
}
soundIndex = sSoundBanks[bank][soundIndex].next; soundIndex = sSoundBanks[bank][soundIndex].next;
} }
} }

View file

@ -10,7 +10,7 @@
#define PRELOAD_BANKS 2 #define PRELOAD_BANKS 2
#define PRELOAD_SEQUENCE 1 #define PRELOAD_SEQUENCE 1
#define IS_SEQUENCE_CHANNEL_VALID(ptr) ((uintptr_t)(ptr) != (uintptr_t)&gSequenceChannelNone) #define IS_SEQUENCE_CHANNEL_VALID(ptr) ((uintptr_t)(ptr) != (uintptr_t)&gSequenceChannelNone && ptr != NULL)
extern struct Note *gNotes; extern struct Note *gNotes;

View file

@ -34,6 +34,7 @@ u8 get_instrument(struct SequenceChannel *seqChannel, u8 instId, struct Instrume
struct AdsrSettings *adsr); struct AdsrSettings *adsr);
void sequence_channel_init(struct SequenceChannel *seqChannel) { void sequence_channel_init(struct SequenceChannel *seqChannel) {
if (!seqChannel) { return; }
s32 i; s32 i;
seqChannel->enabled = FALSE; seqChannel->enabled = FALSE;
@ -101,6 +102,7 @@ void sequence_channel_init(struct SequenceChannel *seqChannel) {
} }
s32 seq_channel_set_layer(struct SequenceChannel *seqChannel, s32 layerIndex) { s32 seq_channel_set_layer(struct SequenceChannel *seqChannel, s32 layerIndex) {
if (layerIndex >= LAYERS_MAX) { return 0; }
struct SequenceChannelLayer *layer; struct SequenceChannelLayer *layer;
if (seqChannel->layers[layerIndex] == NULL) { if (seqChannel->layers[layerIndex] == NULL) {
@ -167,6 +169,7 @@ void seq_channel_layer_disable(struct SequenceChannelLayer *layer) {
} }
void seq_channel_layer_free(struct SequenceChannel *seqChannel, s32 layerIndex) { void seq_channel_layer_free(struct SequenceChannel *seqChannel, s32 layerIndex) {
if (layerIndex >= LAYERS_MAX) { return; }
struct SequenceChannelLayer *layer = seqChannel->layers[layerIndex]; struct SequenceChannelLayer *layer = seqChannel->layers[layerIndex];
if (layer != NULL) { if (layer != NULL) {
@ -189,6 +192,7 @@ void seq_channel_layer_free(struct SequenceChannel *seqChannel, s32 layerIndex)
} }
void sequence_channel_disable(struct SequenceChannel *seqChannel) { void sequence_channel_disable(struct SequenceChannel *seqChannel) {
if (!seqChannel) { return; }
for (s32 i = 0; i < LAYERS_MAX; i++) { for (s32 i = 0; i < LAYERS_MAX; i++) {
seq_channel_layer_free(seqChannel, i); seq_channel_layer_free(seqChannel, i);
} }
@ -214,6 +218,7 @@ struct SequenceChannel *allocate_sequence_channel(void) {
} }
void sequence_player_init_channels(struct SequencePlayer *seqPlayer, u16 channelBits) { void sequence_player_init_channels(struct SequencePlayer *seqPlayer, u16 channelBits) {
if (!seqPlayer) { return; }
for (u32 i = 0; i < CHANNELS_MAX; i++) { for (u32 i = 0; i < CHANNELS_MAX; i++) {
if (channelBits & 1) { if (channelBits & 1) {
struct SequenceChannel *seqChannel = seqPlayer->channels[i]; struct SequenceChannel *seqChannel = seqPlayer->channels[i];
@ -244,6 +249,7 @@ void sequence_player_init_channels(struct SequencePlayer *seqPlayer, u16 channel
} }
void sequence_player_disable_channels(struct SequencePlayer *seqPlayer, u16 channelBits) { void sequence_player_disable_channels(struct SequencePlayer *seqPlayer, u16 channelBits) {
if (!seqPlayer) { return; }
eu_stubbed_printf_0("SUBTRACK DIM\n"); eu_stubbed_printf_0("SUBTRACK DIM\n");
for (u32 i = 0; i < CHANNELS_MAX; i++) { for (u32 i = 0; i < CHANNELS_MAX; i++) {
if (channelBits & 1) { if (channelBits & 1) {
@ -272,6 +278,7 @@ void sequence_player_disable_channels(struct SequencePlayer *seqPlayer, u16 chan
} }
void sequence_player_init_channels_extended(struct SequencePlayer* seqPlayer, u64 channelBits) { void sequence_player_init_channels_extended(struct SequencePlayer* seqPlayer, u64 channelBits) {
if (!seqPlayer) { return; }
LOG_DEBUG("Enabling channels (extended) with corresponding bits %llX", channelBits); LOG_DEBUG("Enabling channels (extended) with corresponding bits %llX", channelBits);
for (u32 i = 0; i < CHANNELS_MAX; i++) { for (u32 i = 0; i < CHANNELS_MAX; i++) {
@ -309,6 +316,7 @@ void sequence_player_init_channels_extended(struct SequencePlayer* seqPlayer, u6
} }
void sequence_player_disable_channels_extended(struct SequencePlayer* seqPlayer, u64 channelBits) { void sequence_player_disable_channels_extended(struct SequencePlayer* seqPlayer, u64 channelBits) {
if (!seqPlayer) { return; }
LOG_DEBUG("Disabling channels (extended) with corresponding bits %llX", channelBits); LOG_DEBUG("Disabling channels (extended) with corresponding bits %llX", channelBits);
for (u32 i = 0; i < CHANNELS_MAX; i++) { for (u32 i = 0; i < CHANNELS_MAX; i++) {
@ -331,6 +339,7 @@ void sequence_player_disable_channels_extended(struct SequencePlayer* seqPlayer,
} }
void sequence_player_disable_all_channels(struct SequencePlayer *seqPlayer) { void sequence_player_disable_all_channels(struct SequencePlayer *seqPlayer) {
if (!seqPlayer) { return; }
eu_stubbed_printf_0("SUBTRACK DIM\n"); eu_stubbed_printf_0("SUBTRACK DIM\n");
for (u32 i = 0; i < CHANNELS_MAX; i++) { for (u32 i = 0; i < CHANNELS_MAX; i++) {
struct SequenceChannel *seqChannel = seqPlayer->channels[i]; struct SequenceChannel *seqChannel = seqPlayer->channels[i];
@ -352,6 +361,8 @@ void sequence_player_disable_all_channels(struct SequencePlayer *seqPlayer) {
} }
void sequence_channel_enable(struct SequencePlayer *seqPlayer, u8 channelIndex, void *script) { void sequence_channel_enable(struct SequencePlayer *seqPlayer, u8 channelIndex, void *script) {
if (!seqPlayer) { return; }
if (channelIndex >= CHANNELS_MAX) { return; }
struct SequenceChannel *seqChannel = seqPlayer->channels[channelIndex]; struct SequenceChannel *seqChannel = seqPlayer->channels[channelIndex];
s32 i; s32 i;
if (IS_SEQUENCE_CHANNEL_VALID(seqChannel) == FALSE) { if (IS_SEQUENCE_CHANNEL_VALID(seqChannel) == FALSE) {
@ -386,6 +397,7 @@ void sequence_channel_enable(struct SequencePlayer *seqPlayer, u8 channelIndex,
} }
void sequence_player_disable(struct SequencePlayer *seqPlayer) { void sequence_player_disable(struct SequencePlayer *seqPlayer) {
if (!seqPlayer) { return; }
LOG_DEBUG("Disabling sequence player %p", seqPlayer); LOG_DEBUG("Disabling sequence player %p", seqPlayer);
sequence_player_disable_all_channels(seqPlayer); sequence_player_disable_all_channels(seqPlayer);
@ -435,6 +447,7 @@ void sequence_player_disable(struct SequencePlayer *seqPlayer) {
* Add an item to the end of a list, if it's not already in any list. * Add an item to the end of a list, if it's not already in any list.
*/ */
void audio_list_push_back(struct AudioListItem *list, struct AudioListItem *item) { void audio_list_push_back(struct AudioListItem *list, struct AudioListItem *item) {
if (!list || !item) { return; }
if (item->prev != NULL) { if (item->prev != NULL) {
eu_stubbed_printf_0("Error:Same List Add\n"); eu_stubbed_printf_0("Error:Same List Add\n");
} else { } else {
@ -451,6 +464,7 @@ void audio_list_push_back(struct AudioListItem *list, struct AudioListItem *item
* Remove the last item from a list, and return it (or NULL if empty). * Remove the last item from a list, and return it (or NULL if empty).
*/ */
void *audio_list_pop_back(struct AudioListItem *list) { void *audio_list_pop_back(struct AudioListItem *list) {
if (!list) { return NULL; }
struct AudioListItem *item = list->prev; struct AudioListItem *item = list->prev;
if (item == list) { if (item == list) {
return NULL; return NULL;
@ -2902,6 +2916,7 @@ void process_sequences(UNUSED s32 iterationsRemaining) {
} }
void init_sequence_player(u32 player) { void init_sequence_player(u32 player) {
if (player >= SEQUENCE_PLAYERS) { return; }
struct SequencePlayer *seqPlayer = &gSequencePlayers[player]; struct SequencePlayer *seqPlayer = &gSequencePlayers[player];
#if defined(VERSION_EU) || defined(VERSION_SH) #if defined(VERSION_EU) || defined(VERSION_SH)
sequence_player_disable(seqPlayer); sequence_player_disable(seqPlayer);

View file

@ -1269,6 +1269,7 @@ static BhvCommandProc BehaviorCmdTable[BEHAVIOR_CMD_TABLE_MAX] = {
// Execute the behavior script of the current object, process the object flags, and other miscellaneous code for updating objects. // Execute the behavior script of the current object, process the object flags, and other miscellaneous code for updating objects.
void cur_obj_update(void) { void cur_obj_update(void) {
if (!gCurrentObject) { return; }
// Don't update if dormant // Don't update if dormant
if (gCurrentObject->activeFlags & ACTIVE_FLAG_DORMANT) { if (gCurrentObject->activeFlags & ACTIVE_FLAG_DORMANT) {
gCurrentObject->header.gfx.node.flags &= ~GRAPH_RENDER_ACTIVE; gCurrentObject->header.gfx.node.flags &= ~GRAPH_RENDER_ACTIVE;

View file

@ -131,7 +131,7 @@ void bhv_spawned_star_loop(void) {
} }
spawn_object(o, MODEL_NONE, bhvSparkleSpawn); spawn_object(o, MODEL_NONE, bhvSparkleSpawn);
} else if (o->oAction == 2) { } else if (o->oAction == 2) {
if (gCamera->cutscene == 0 && gRecentCutscene == 0) { if (gCamera && gCamera->cutscene == 0 && gRecentCutscene == 0) {
gMarioStates[0].freeze = 0; gMarioStates[0].freeze = 0;
clear_time_stop_flags(TIME_STOP_ENABLED | TIME_STOP_MARIO_AND_DOORS); clear_time_stop_flags(TIME_STOP_ENABLED | TIME_STOP_MARIO_AND_DOORS);
o->activeFlags &= ~ACTIVE_FLAG_INITIATED_TIME_STOP; o->activeFlags &= ~ACTIVE_FLAG_INITIATED_TIME_STOP;

View file

@ -2871,6 +2871,7 @@ void transition_to_camera_mode(struct Camera *c, s16 newMode, s16 numFrames) {
* @param frames number of frames the transition should last, only used when entering C_UP * @param frames number of frames the transition should last, only used when entering C_UP
*/ */
void set_camera_mode(struct Camera *c, s16 mode, s16 frames) { void set_camera_mode(struct Camera *c, s16 mode, s16 frames) {
if (!c) { return; }
struct LinearTransitionPoint *start = &sModeInfo.transitionStart; struct LinearTransitionPoint *start = &sModeInfo.transitionStart;
struct LinearTransitionPoint *end = &sModeInfo.transitionEnd; struct LinearTransitionPoint *end = &sModeInfo.transitionEnd;
@ -5183,6 +5184,7 @@ void clear_cutscene_vars(UNUSED struct Camera *c) {
* Start the cutscene, `cutscene`, if it is not already playing. * Start the cutscene, `cutscene`, if it is not already playing.
*/ */
void start_cutscene(struct Camera *c, u8 cutscene) { void start_cutscene(struct Camera *c, u8 cutscene) {
if (!c) { return; }
if (c->cutscene != cutscene) { if (c->cutscene != cutscene) {
c->cutscene = cutscene; c->cutscene = cutscene;
clear_cutscene_vars(c); clear_cutscene_vars(c);
@ -11448,6 +11450,7 @@ struct CutsceneSplinePoint sCcmOutsideCreditsSplineFocus[] = {
* the duration they want the flag to be active. * the duration they want the flag to be active.
*/ */
void play_cutscene(struct Camera *c) { void play_cutscene(struct Camera *c) {
if (!c) { return; }
UNUSED u32 pad[3]; UNUSED u32 pad[3];
UNUSED s16 unusedYawFocToMario; UNUSED s16 unusedYawFocToMario;
s16 cutsceneDuration = 0; s16 cutsceneDuration = 0;
@ -11828,6 +11831,7 @@ static UNUSED void unused_rotate_obj_randomly(struct Object *o, f32 pitchRange,
* Rotate the object towards the point `point`. * Rotate the object towards the point `point`.
*/ */
void obj_rotate_towards_point(struct Object *o, Vec3f point, s16 pitchOff, s16 yawOff, s16 pitchDiv, s16 yawDiv) { void obj_rotate_towards_point(struct Object *o, Vec3f point, s16 pitchOff, s16 yawOff, s16 pitchDiv, s16 yawDiv) {
if (!o) { return; }
f32 dist; f32 dist;
s16 pitch, yaw; s16 pitch, yaw;
Vec3f oPos; Vec3f oPos;

View file

@ -127,6 +127,7 @@ extern u8 gLastCollectedStarOrKey;
* Returns the type of cap Mario is wearing. * Returns the type of cap Mario is wearing.
*/ */
u32 get_mario_cap_flag(struct Object *capObject) { u32 get_mario_cap_flag(struct Object *capObject) {
if (!capObject) { return 0; }
const BehaviorScript *script = virtual_to_segmented(0x13, capObject->behavior); const BehaviorScript *script = virtual_to_segmented(0x13, capObject->behavior);
if (script == bhvNormalCap) { if (script == bhvNormalCap) {
@ -147,6 +148,7 @@ u32 get_mario_cap_flag(struct Object *capObject) {
* in the angular range given towards Mario. * in the angular range given towards Mario.
*/ */
u32 object_facing_mario(struct MarioState *m, struct Object *o, s16 angleRange) { u32 object_facing_mario(struct MarioState *m, struct Object *o, s16 angleRange) {
if (!m || !o) { return FALSE; }
f32 dx = m->pos[0] - o->oPosX; f32 dx = m->pos[0] - o->oPosX;
f32 dz = m->pos[2] - o->oPosZ; f32 dz = m->pos[2] - o->oPosZ;
@ -161,6 +163,7 @@ u32 object_facing_mario(struct MarioState *m, struct Object *o, s16 angleRange)
} }
s16 mario_obj_angle_to_object(struct MarioState *m, struct Object *o) { s16 mario_obj_angle_to_object(struct MarioState *m, struct Object *o) {
if (!m || !o) { return 0; }
f32 dx = o->oPosX - m->pos[0]; f32 dx = o->oPosX - m->pos[0];
f32 dz = o->oPosZ - m->pos[2]; f32 dz = o->oPosZ - m->pos[2];
@ -172,6 +175,8 @@ s16 mario_obj_angle_to_object(struct MarioState *m, struct Object *o) {
* action, speed, and position. * action, speed, and position.
*/ */
static u32 determine_interaction_internal(struct MarioState *m, struct Object *o, u8 isPVP) { static u32 determine_interaction_internal(struct MarioState *m, struct Object *o, u8 isPVP) {
if (!m || !o) { return 0; }
u32 interaction = 0; u32 interaction = 0;
u32 action = m->action; u32 action = m->action;
@ -268,6 +273,7 @@ u32 determine_interaction_pvp(struct MarioState *m, struct Object *o) {
* Sets the interaction types for INT_STATUS_INTERACTED, INT_STATUS_WAS_ATTACKED * Sets the interaction types for INT_STATUS_INTERACTED, INT_STATUS_WAS_ATTACKED
*/ */
u32 attack_object(struct Object *o, s32 interaction) { u32 attack_object(struct Object *o, s32 interaction) {
if (!o) { return 0; }
u32 attackType = 0; u32 attackType = 0;
switch (interaction) { switch (interaction) {
@ -300,6 +306,7 @@ u32 attack_object(struct Object *o, s32 interaction) {
} }
void mario_stop_riding_object(struct MarioState *m) { void mario_stop_riding_object(struct MarioState *m) {
if (!m) { return; }
if (m->riddenObj != NULL && m->playerIndex == 0) { if (m->riddenObj != NULL && m->playerIndex == 0) {
m->riddenObj->oInteractStatus = INT_STATUS_STOP_RIDING; m->riddenObj->oInteractStatus = INT_STATUS_STOP_RIDING;
if (m->riddenObj->oSyncID != 0) { if (m->riddenObj->oSyncID != 0) {
@ -311,6 +318,7 @@ void mario_stop_riding_object(struct MarioState *m) {
} }
void mario_grab_used_object(struct MarioState *m) { void mario_grab_used_object(struct MarioState *m) {
if (!m) { return; }
if (m->usedObj == NULL || m->usedObj->oHeldState == HELD_HELD) { return; } if (m->usedObj == NULL || m->usedObj->oHeldState == HELD_HELD) { return; }
if (m->heldObj == NULL && m->usedObj != NULL) { if (m->heldObj == NULL && m->usedObj != NULL) {
// prevent grabbing a non-grabbable object // prevent grabbing a non-grabbable object
@ -467,6 +475,7 @@ u32 able_to_grab_object(struct MarioState *m, UNUSED struct Object *o) {
} }
struct Object *mario_get_collided_object(struct MarioState *m, u32 interactType) { struct Object *mario_get_collided_object(struct MarioState *m, u32 interactType) {
if (!m) { return NULL; }
s32 i; s32 i;
struct Object *object; struct Object *object;
@ -482,6 +491,7 @@ struct Object *mario_get_collided_object(struct MarioState *m, u32 interactType)
} }
u32 mario_check_object_grab(struct MarioState *m) { u32 mario_check_object_grab(struct MarioState *m) {
if (!m) { return 0; }
u32 result = FALSE; u32 result = FALSE;
const BehaviorScript *script; const BehaviorScript *script;
@ -517,6 +527,7 @@ u32 mario_check_object_grab(struct MarioState *m) {
} }
u32 bully_knock_back_mario(struct MarioState *mario) { u32 bully_knock_back_mario(struct MarioState *mario) {
if (!mario) { return 0; }
struct BullyCollisionData marioData; struct BullyCollisionData marioData;
struct BullyCollisionData bullyData; struct BullyCollisionData bullyData;
s16 newMarioYaw; s16 newMarioYaw;
@ -582,6 +593,7 @@ u32 bully_knock_back_mario(struct MarioState *mario) {
} }
void bounce_off_object(struct MarioState *m, struct Object *o, f32 velY) { void bounce_off_object(struct MarioState *m, struct Object *o, f32 velY) {
if (!m || !o) { return; }
m->pos[1] = o->oPosY + o->hitboxHeight; m->pos[1] = o->oPosY + o->hitboxHeight;
m->vel[1] = velY; m->vel[1] = velY;
@ -591,11 +603,13 @@ void bounce_off_object(struct MarioState *m, struct Object *o, f32 velY) {
} }
void hit_object_from_below(struct MarioState *m, UNUSED struct Object *o) { void hit_object_from_below(struct MarioState *m, UNUSED struct Object *o) {
if (!m) { return; }
m->vel[1] = 0.0f; m->vel[1] = 0.0f;
if (m->playerIndex == 0) { set_camera_shake_from_hit(SHAKE_HIT_FROM_BELOW); } if (m->playerIndex == 0) { set_camera_shake_from_hit(SHAKE_HIT_FROM_BELOW); }
} }
static u32 unused_determine_knockback_action(struct MarioState *m) { static u32 unused_determine_knockback_action(struct MarioState *m) {
if (!m) { return 0; }
u32 bonkAction; u32 bonkAction;
s16 angleToObject = mario_obj_angle_to_object(m, m->interactObj); s16 angleToObject = mario_obj_angle_to_object(m, m->interactObj);
s16 facingDYaw = angleToObject - m->faceAngle[1]; s16 facingDYaw = angleToObject - m->faceAngle[1];
@ -626,6 +640,7 @@ static u32 unused_determine_knockback_action(struct MarioState *m) {
} }
u32 determine_knockback_action(struct MarioState *m, UNUSED s32 arg) { u32 determine_knockback_action(struct MarioState *m, UNUSED s32 arg) {
if (!m) { return 0; }
if (m->interactObj == NULL) { if (m->interactObj == NULL) {
return sForwardKnockbackActions[0][0]; return sForwardKnockbackActions[0][0];
} }
@ -720,6 +735,7 @@ u32 determine_knockback_action(struct MarioState *m, UNUSED s32 arg) {
} }
void push_mario_out_of_object(struct MarioState *m, struct Object *o, f32 padding) { void push_mario_out_of_object(struct MarioState *m, struct Object *o, f32 padding) {
if (!m || !o) { return; }
f32 minDistance = o->hitboxRadius + m->marioObj->hitboxRadius + padding; f32 minDistance = o->hitboxRadius + m->marioObj->hitboxRadius + padding;
f32 offsetX = m->pos[0] - o->oPosX; f32 offsetX = m->pos[0] - o->oPosX;
@ -758,6 +774,7 @@ void push_mario_out_of_object(struct MarioState *m, struct Object *o, f32 paddin
} }
void bounce_back_from_attack(struct MarioState *m, u32 interaction) { void bounce_back_from_attack(struct MarioState *m, u32 interaction) {
if (!m) { return; }
if (interaction & (INT_PUNCH | INT_KICK | INT_TRIP)) { if (interaction & (INT_PUNCH | INT_KICK | INT_TRIP)) {
if (m->action == ACT_PUNCHING) { if (m->action == ACT_PUNCHING) {
m->action = ACT_MOVE_PUNCHING; m->action = ACT_MOVE_PUNCHING;
@ -779,6 +796,7 @@ void bounce_back_from_attack(struct MarioState *m, u32 interaction) {
} }
u32 should_push_or_pull_door(struct MarioState *m, struct Object *o) { u32 should_push_or_pull_door(struct MarioState *m, struct Object *o) {
if (!m || !o) { return 0; }
f32 dx = o->oPosX - m->pos[0]; f32 dx = o->oPosX - m->pos[0];
f32 dz = o->oPosZ - m->pos[2]; f32 dz = o->oPosZ - m->pos[2];
@ -788,7 +806,7 @@ u32 should_push_or_pull_door(struct MarioState *m, struct Object *o) {
} }
u32 take_damage_from_interact_object(struct MarioState *m) { u32 take_damage_from_interact_object(struct MarioState *m) {
if (m->interactObj == NULL) { return 0; } if (!m || m->interactObj == NULL) { return 0; }
s32 shake; s32 shake;
s32 damage = m->interactObj->oDamageOrCoinValue; s32 damage = m->interactObj->oDamageOrCoinValue;
@ -823,6 +841,7 @@ u32 take_damage_from_interact_object(struct MarioState *m) {
} }
u32 take_damage_and_knock_back(struct MarioState *m, struct Object *o) { u32 take_damage_and_knock_back(struct MarioState *m, struct Object *o) {
if (!m || !o) { return FALSE; }
u32 damage; u32 damage;
if (!gInteractionInvulnerable && !(m->flags & MARIO_VANISH_CAP) if (!gInteractionInvulnerable && !(m->flags & MARIO_VANISH_CAP)
@ -849,6 +868,7 @@ u32 take_damage_and_knock_back(struct MarioState *m, struct Object *o) {
} }
void reset_mario_pitch(struct MarioState *m) { void reset_mario_pitch(struct MarioState *m) {
if (!m) { return; }
if (m->action == ACT_WATER_JUMP || m->action == ACT_SHOT_FROM_CANNON || m->action == ACT_FLYING) { if (m->action == ACT_WATER_JUMP || m->action == ACT_SHOT_FROM_CANNON || m->action == ACT_FLYING) {
if (m->playerIndex == 0) { if (m->playerIndex == 0) {
set_camera_mode(m->area->camera, m->area->camera->defMode, 1); set_camera_mode(m->area->camera, m->area->camera->defMode, 1);
@ -858,6 +878,7 @@ void reset_mario_pitch(struct MarioState *m) {
} }
u32 interact_coin(struct MarioState *m, UNUSED u32 interactType, struct Object *o) { u32 interact_coin(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
if (!m || !o) { return FALSE; }
if (m != &gMarioStates[0] || (gDjuiInMainMenu && gCurrLevelNum == LEVEL_TTM)) { if (m != &gMarioStates[0] || (gDjuiInMainMenu && gCurrLevelNum == LEVEL_TTM)) {
// only collect locally // only collect locally
return FALSE; return FALSE;
@ -883,12 +904,14 @@ u32 interact_coin(struct MarioState *m, UNUSED u32 interactType, struct Object *
} }
u32 interact_water_ring(struct MarioState *m, UNUSED u32 interactType, struct Object *o) { u32 interact_water_ring(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
if (!m || !o) { return FALSE; }
m->healCounter += 4 * o->oDamageOrCoinValue; m->healCounter += 4 * o->oDamageOrCoinValue;
o->oInteractStatus = INT_STATUS_INTERACTED; o->oInteractStatus = INT_STATUS_INTERACTED;
return FALSE; return FALSE;
} }
u32 interact_star_or_key(struct MarioState *m, UNUSED u32 interactType, struct Object *o) { u32 interact_star_or_key(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
if (!m || !o) { return FALSE; }
// only allow for local player // only allow for local player
if (m != &gMarioStates[0]) { return FALSE; } if (m != &gMarioStates[0]) { return FALSE; }
@ -992,6 +1015,7 @@ u32 interact_star_or_key(struct MarioState *m, UNUSED u32 interactType, struct O
} }
u32 interact_bbh_entrance(struct MarioState *m, UNUSED u32 interactType, struct Object *o) { u32 interact_bbh_entrance(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
if (!m || !o) { return FALSE; }
if (m->playerIndex != 0) { return FALSE; } if (m->playerIndex != 0) { return FALSE; }
if (m->action != ACT_BBH_ENTER_SPIN && m->action != ACT_BBH_ENTER_JUMP) { if (m->action != ACT_BBH_ENTER_SPIN && m->action != ACT_BBH_ENTER_JUMP) {
mario_stop_riding_and_holding(m); mario_stop_riding_and_holding(m);
@ -1011,6 +1035,7 @@ u32 interact_bbh_entrance(struct MarioState *m, UNUSED u32 interactType, struct
} }
u32 interact_warp(struct MarioState *m, UNUSED u32 interactType, struct Object *o) { u32 interact_warp(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
if (!m || !o) { return FALSE; }
u32 action; u32 action;
if (m != &gMarioStates[0]) { if (m != &gMarioStates[0]) {
@ -1057,6 +1082,7 @@ u32 interact_warp(struct MarioState *m, UNUSED u32 interactType, struct Object *
} }
u32 display_door_dialog(struct MarioState *m, u32 actionArg) { u32 display_door_dialog(struct MarioState *m, u32 actionArg) {
if (!m) { return FALSE; }
if (m != &gMarioStates[0]) { return FALSE; } if (m != &gMarioStates[0]) { return FALSE; }
// ugly hack: save the last place we opened a dialog to prevent dialog spam // ugly hack: save the last place we opened a dialog to prevent dialog spam
static f32 lastDialogPosition[3] = { 0 }; static f32 lastDialogPosition[3] = { 0 };
@ -1071,6 +1097,7 @@ u32 display_door_dialog(struct MarioState *m, u32 actionArg) {
} }
u8 prevent_interact_door(struct MarioState* m, struct Object* o) { u8 prevent_interact_door(struct MarioState* m, struct Object* o) {
if (!m) { return FALSE; }
// prevent multiple star/key unlocks on the same door // prevent multiple star/key unlocks on the same door
for (s32 i = 0; i < MAX_PLAYERS; i++) { for (s32 i = 0; i < MAX_PLAYERS; i++) {
struct MarioState* m2 = &gMarioStates[i]; struct MarioState* m2 = &gMarioStates[i];
@ -1087,6 +1114,7 @@ u8 prevent_interact_door(struct MarioState* m, struct Object* o) {
} }
u32 interact_warp_door(struct MarioState *m, UNUSED u32 interactType, struct Object *o) { u32 interact_warp_door(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
if (!m || !o) { return FALSE; }
u32 doorAction = 0; u32 doorAction = 0;
u32 saveFlags = save_file_get_flags(); u32 saveFlags = save_file_get_flags();
s16 warpDoorId = o->oBehParams >> 24; s16 warpDoorId = o->oBehParams >> 24;
@ -1179,6 +1207,7 @@ u32 get_door_save_file_flag(struct Object *door) {
} }
u32 interact_door(struct MarioState *m, UNUSED u32 interactType, struct Object *o) { u32 interact_door(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
if (!m || !o) { return FALSE; }
if (m->playerIndex != 0 && o == NULL) { return FALSE; } if (m->playerIndex != 0 && o == NULL) { return FALSE; }
s16 requiredNumStars = o->oBehParams >> 24; s16 requiredNumStars = o->oBehParams >> 24;
s16 numStars = save_file_get_total_star_count(gCurrSaveFileNum - 1, COURSE_MIN - 1, COURSE_MAX - 1); s16 numStars = save_file_get_total_star_count(gCurrSaveFileNum - 1, COURSE_MIN - 1, COURSE_MAX - 1);
@ -1259,6 +1288,7 @@ u32 interact_door(struct MarioState *m, UNUSED u32 interactType, struct Object *
} }
u32 interact_cannon_base(struct MarioState *m, UNUSED u32 interactType, struct Object *o) { u32 interact_cannon_base(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
if (!m || !o) { return FALSE; }
if (o->oAction != 0) { return FALSE; } if (o->oAction != 0) { return FALSE; }
if (m->playerIndex != 0) { return FALSE; } if (m->playerIndex != 0) { return FALSE; }
@ -1275,6 +1305,7 @@ u32 interact_cannon_base(struct MarioState *m, UNUSED u32 interactType, struct O
} }
static u8 resolve_player_collision(struct MarioState* m, struct MarioState* m2) { static u8 resolve_player_collision(struct MarioState* m, struct MarioState* m2) {
if (!m || !m2) { return FALSE; }
// move player outside of other player // move player outside of other player
f32 extentY = m->marioObj->hitboxHeight; f32 extentY = m->marioObj->hitboxHeight;
f32 radius = m->marioObj->hitboxRadius * 2.0f; f32 radius = m->marioObj->hitboxRadius * 2.0f;
@ -1341,6 +1372,7 @@ u8 determine_player_damage_value(u32 interaction) {
} }
u8 player_is_sliding(struct MarioState* m) { u8 player_is_sliding(struct MarioState* m) {
if (!m) { return FALSE; }
if (m->action & (ACT_FLAG_BUTT_OR_STOMACH_SLIDE | ACT_FLAG_DIVING)) { if (m->action & (ACT_FLAG_BUTT_OR_STOMACH_SLIDE | ACT_FLAG_DIVING)) {
return TRUE; return TRUE;
} }
@ -1378,6 +1410,7 @@ u8 passes_pvp_interaction_checks(struct MarioState* attacker, struct MarioState*
} }
u32 interact_player(struct MarioState* m, UNUSED u32 interactType, struct Object* o) { u32 interact_player(struct MarioState* m, UNUSED u32 interactType, struct Object* o) {
if (!m || !o) { return FALSE; }
if (!is_player_active(m)) { return FALSE; } if (!is_player_active(m)) { return FALSE; }
if (gServerSettings.playerInteractions == PLAYER_INTERACTIONS_NONE) { return FALSE; } if (gServerSettings.playerInteractions == PLAYER_INTERACTIONS_NONE) { return FALSE; }
if (m->action == ACT_JUMBO_STAR_CUTSCENE) { return FALSE; } if (m->action == ACT_JUMBO_STAR_CUTSCENE) { return FALSE; }
@ -1416,6 +1449,7 @@ u32 interact_player(struct MarioState* m, UNUSED u32 interactType, struct Object
} }
u32 interact_player_pvp(struct MarioState* attacker, struct MarioState* victim) { u32 interact_player_pvp(struct MarioState* attacker, struct MarioState* victim) {
if (!attacker || !victim) { return false; }
if (!is_player_active(attacker)) { return FALSE; } if (!is_player_active(attacker)) { return FALSE; }
if (!is_player_active(victim)) { return FALSE; } if (!is_player_active(victim)) { return FALSE; }
if (gServerSettings.playerInteractions == PLAYER_INTERACTIONS_NONE) { return FALSE; } if (gServerSettings.playerInteractions == PLAYER_INTERACTIONS_NONE) { return FALSE; }
@ -1512,6 +1546,7 @@ u32 interact_player_pvp(struct MarioState* attacker, struct MarioState* victim)
} }
u32 interact_igloo_barrier(struct MarioState *m, UNUSED u32 interactType, struct Object *o) { u32 interact_igloo_barrier(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
if (!m || !o) { return FALSE; }
//! Sets used object without changing action (LOTS of interesting glitches, //! Sets used object without changing action (LOTS of interesting glitches,
// but unfortunately the igloo barrier is the only object with this interaction // but unfortunately the igloo barrier is the only object with this interaction
// type) // type)
@ -1522,6 +1557,7 @@ u32 interact_igloo_barrier(struct MarioState *m, UNUSED u32 interactType, struct
} }
u32 interact_tornado(struct MarioState *m, UNUSED u32 interactType, struct Object *o) { u32 interact_tornado(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
if (!m || !o) { return FALSE; }
struct Object *marioObj = m->marioObj; struct Object *marioObj = m->marioObj;
if (m->action != ACT_TORNADO_TWIRLING && m->action != ACT_SQUISHED) { if (m->action != ACT_TORNADO_TWIRLING && m->action != ACT_SQUISHED) {
@ -1546,6 +1582,7 @@ u32 interact_tornado(struct MarioState *m, UNUSED u32 interactType, struct Objec
} }
u32 interact_whirlpool(struct MarioState *m, UNUSED u32 interactType, struct Object *o) { u32 interact_whirlpool(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
if (!m || !o) { return FALSE; }
struct Object *marioObj = m->marioObj; struct Object *marioObj = m->marioObj;
if (m->action != ACT_CAUGHT_IN_WHIRLPOOL) { if (m->action != ACT_CAUGHT_IN_WHIRLPOOL) {
@ -1568,6 +1605,7 @@ u32 interact_whirlpool(struct MarioState *m, UNUSED u32 interactType, struct Obj
} }
u32 interact_strong_wind(struct MarioState *m, UNUSED u32 interactType, struct Object *o) { u32 interact_strong_wind(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
if (!m || !o) { return FALSE; }
UNUSED struct Object *marioObj = m->marioObj; UNUSED struct Object *marioObj = m->marioObj;
if (m->action != ACT_GETTING_BLOWN) { if (m->action != ACT_GETTING_BLOWN) {
@ -1590,6 +1628,7 @@ u32 interact_strong_wind(struct MarioState *m, UNUSED u32 interactType, struct O
} }
u32 interact_flame(struct MarioState *m, UNUSED u32 interactType, struct Object *o) { u32 interact_flame(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
if (!m || !o) { return FALSE; }
u32 burningAction = ACT_BURNING_JUMP; u32 burningAction = ACT_BURNING_JUMP;
if (!gInteractionInvulnerable && !(m->flags & MARIO_METAL_CAP) && !(m->flags & MARIO_VANISH_CAP) if (!gInteractionInvulnerable && !(m->flags & MARIO_METAL_CAP) && !(m->flags & MARIO_VANISH_CAP)
@ -1619,6 +1658,7 @@ u32 interact_flame(struct MarioState *m, UNUSED u32 interactType, struct Object
} }
u32 interact_snufit_bullet(struct MarioState *m, UNUSED u32 interactType, struct Object *o) { u32 interact_snufit_bullet(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
if (!m || !o) { return FALSE; }
if (!gInteractionInvulnerable && !(m->flags & MARIO_VANISH_CAP)) { if (!gInteractionInvulnerable && !(m->flags & MARIO_VANISH_CAP)) {
if (m->flags & MARIO_METAL_CAP) { if (m->flags & MARIO_METAL_CAP) {
o->oInteractStatus = INT_STATUS_INTERACTED | INT_STATUS_WAS_ATTACKED; o->oInteractStatus = INT_STATUS_INTERACTED | INT_STATUS_WAS_ATTACKED;
@ -1644,6 +1684,7 @@ u32 interact_snufit_bullet(struct MarioState *m, UNUSED u32 interactType, struct
} }
u32 interact_clam_or_bubba(struct MarioState *m, UNUSED u32 interactType, struct Object *o) { u32 interact_clam_or_bubba(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
if (!m || !o) { return FALSE; }
if (o->oInteractionSubtype & INT_SUBTYPE_EATS_MARIO) { if (o->oInteractionSubtype & INT_SUBTYPE_EATS_MARIO) {
o->oInteractStatus = INT_STATUS_INTERACTED; o->oInteractStatus = INT_STATUS_INTERACTED;
m->interactObj = o; m->interactObj = o;
@ -1660,6 +1701,7 @@ u32 interact_clam_or_bubba(struct MarioState *m, UNUSED u32 interactType, struct
} }
u32 interact_bully(struct MarioState *m, UNUSED u32 interactType, struct Object *o) { u32 interact_bully(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
if (!m || !o) { return FALSE; }
UNUSED u32 unused; UNUSED u32 unused;
u32 interaction; u32 interaction;
@ -1704,6 +1746,7 @@ u32 interact_bully(struct MarioState *m, UNUSED u32 interactType, struct Object
} }
u32 interact_shock(struct MarioState *m, UNUSED u32 interactType, struct Object *o) { u32 interact_shock(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
if (!m || !o) { return FALSE; }
if (!gInteractionInvulnerable && !(m->flags & MARIO_VANISH_CAP) if (!gInteractionInvulnerable && !(m->flags & MARIO_VANISH_CAP)
&& !(o->oInteractionSubtype & INT_SUBTYPE_DELAY_INVINCIBILITY)) { && !(o->oInteractionSubtype & INT_SUBTYPE_DELAY_INVINCIBILITY)) {
u32 actionArg = (m->action & (ACT_FLAG_AIR | ACT_FLAG_ON_POLE | ACT_FLAG_HANGING)) == 0; u32 actionArg = (m->action & (ACT_FLAG_AIR | ACT_FLAG_ON_POLE | ACT_FLAG_HANGING)) == 0;
@ -1731,6 +1774,7 @@ u32 interact_shock(struct MarioState *m, UNUSED u32 interactType, struct Object
} }
static u32 interact_stub(UNUSED struct MarioState *m, UNUSED u32 interactType, struct Object *o) { static u32 interact_stub(UNUSED struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
if (!m || !o) { return FALSE; }
if (!(o->oInteractionSubtype & INT_SUBTYPE_DELAY_INVINCIBILITY)) { if (!(o->oInteractionSubtype & INT_SUBTYPE_DELAY_INVINCIBILITY)) {
sDelayInvincTimer = TRUE; sDelayInvincTimer = TRUE;
} }
@ -1738,6 +1782,7 @@ static u32 interact_stub(UNUSED struct MarioState *m, UNUSED u32 interactType, s
} }
u32 interact_mr_blizzard(struct MarioState *m, UNUSED u32 interactType, struct Object *o) { u32 interact_mr_blizzard(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
if (!m || !o) { return FALSE; }
if (take_damage_and_knock_back(m, o)) { if (take_damage_and_knock_back(m, o)) {
return TRUE; return TRUE;
} }
@ -1750,6 +1795,7 @@ u32 interact_mr_blizzard(struct MarioState *m, UNUSED u32 interactType, struct O
} }
u32 interact_hit_from_below(struct MarioState *m, UNUSED u32 interactType, struct Object *o) { u32 interact_hit_from_below(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
if (!m || !o) { return FALSE; }
UNUSED u32 unused; UNUSED u32 unused;
u32 interaction; u32 interaction;
@ -1792,6 +1838,7 @@ u32 interact_hit_from_below(struct MarioState *m, UNUSED u32 interactType, struc
} }
u32 interact_bounce_top(struct MarioState *m, UNUSED u32 interactType, struct Object *o) { u32 interact_bounce_top(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
if (!m || !o) { return FALSE; }
u32 interaction; u32 interaction;
if (m->flags & MARIO_METAL_CAP) { if (m->flags & MARIO_METAL_CAP) {
interaction = INT_FAST_ATTACK_OR_SHELL; interaction = INT_FAST_ATTACK_OR_SHELL;
@ -1828,6 +1875,7 @@ u32 interact_bounce_top(struct MarioState *m, UNUSED u32 interactType, struct Ob
} }
u32 interact_unknown_08(struct MarioState *m, UNUSED u32 interactType, struct Object *o) { u32 interact_unknown_08(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
if (!m || !o) { return FALSE; }
u32 interaction = determine_interaction(m, o); u32 interaction = determine_interaction(m, o);
if (interaction & INT_PUNCH) { if (interaction & INT_PUNCH) {
@ -1845,6 +1893,7 @@ u32 interact_unknown_08(struct MarioState *m, UNUSED u32 interactType, struct Ob
} }
u32 interact_damage(struct MarioState *m, UNUSED u32 interactType, struct Object *o) { u32 interact_damage(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
if (!m || !o) { return FALSE; }
if (take_damage_and_knock_back(m, o)) { if (take_damage_and_knock_back(m, o)) {
return TRUE; return TRUE;
} }
@ -1857,6 +1906,7 @@ u32 interact_damage(struct MarioState *m, UNUSED u32 interactType, struct Object
} }
u32 interact_breakable(struct MarioState *m, UNUSED u32 interactType, struct Object *o) { u32 interact_breakable(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
if (!m || !o) { return FALSE; }
u32 interaction = determine_interaction(m, o); u32 interaction = determine_interaction(m, o);
if (interaction & INT_ATTACK_NOT_WEAK_FROM_ABOVE) { if (interaction & INT_ATTACK_NOT_WEAK_FROM_ABOVE) {
@ -1882,6 +1932,7 @@ u32 interact_breakable(struct MarioState *m, UNUSED u32 interactType, struct Obj
} }
u32 interact_koopa_shell(struct MarioState *m, UNUSED u32 interactType, struct Object *o) { u32 interact_koopa_shell(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
if (!m || !o) { return FALSE; }
if (m->playerIndex != 0) { return FALSE; } if (m->playerIndex != 0) { return FALSE; }
if (o->oInteractStatus & INT_STATUS_INTERACTED) { if (o->oInteractStatus & INT_STATUS_INTERACTED) {
@ -1919,6 +1970,7 @@ u32 interact_koopa_shell(struct MarioState *m, UNUSED u32 interactType, struct O
} }
u32 check_object_grab_mario(struct MarioState *m, UNUSED u32 interactType, struct Object *o) { u32 check_object_grab_mario(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
if (!m || !o) { return FALSE; }
if (m != &gMarioStates[0]) { return false; } if (m != &gMarioStates[0]) { return false; }
if ((!(m->action & (ACT_FLAG_AIR | ACT_FLAG_INVULNERABLE | ACT_FLAG_ATTACKING)) || !gInteractionInvulnerable) if ((!(m->action & (ACT_FLAG_AIR | ACT_FLAG_INVULNERABLE | ACT_FLAG_ATTACKING)) || !gInteractionInvulnerable)
@ -1944,6 +1996,7 @@ u32 check_object_grab_mario(struct MarioState *m, UNUSED u32 interactType, struc
} }
u32 interact_pole(struct MarioState *m, UNUSED u32 interactType, struct Object *o) { u32 interact_pole(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
if (!m || !o) { return FALSE; }
s32 actionId = m->action & ACT_ID_MASK; s32 actionId = m->action & ACT_ID_MASK;
if (actionId >= 0x080 && actionId < 0x0A0) { if (actionId >= 0x080 && actionId < 0x0A0) {
if (!(m->prevAction & ACT_FLAG_ON_POLE) || m->usedObj != o) { if (!(m->prevAction & ACT_FLAG_ON_POLE) || m->usedObj != o) {
@ -1992,6 +2045,7 @@ u32 interact_pole(struct MarioState *m, UNUSED u32 interactType, struct Object *
} }
u32 interact_hoot(struct MarioState *m, UNUSED u32 interactType, struct Object *o) { u32 interact_hoot(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
if (!m || !o) { return FALSE; }
s32 actionId = m->action & ACT_ID_MASK; s32 actionId = m->action & ACT_ID_MASK;
if (m != &gMarioStates[0]) { return FALSE; } if (m != &gMarioStates[0]) { return FALSE; }
@ -2015,6 +2069,7 @@ u32 interact_hoot(struct MarioState *m, UNUSED u32 interactType, struct Object *
} }
u32 interact_cap(struct MarioState *m, UNUSED u32 interactType, struct Object *o) { u32 interact_cap(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
if (!m || !o) { return FALSE; }
// only allow for local // only allow for local
if (m != &gMarioStates[0]) { return FALSE; } if (m != &gMarioStates[0]) { return FALSE; }
@ -2076,6 +2131,7 @@ u32 interact_cap(struct MarioState *m, UNUSED u32 interactType, struct Object *o
} }
u32 interact_grabbable(struct MarioState *m, u32 interactType, struct Object *o) { u32 interact_grabbable(struct MarioState *m, u32 interactType, struct Object *o) {
if (!m || !o) { return FALSE; }
const BehaviorScript *script = virtual_to_segmented(0x13, o->behavior); const BehaviorScript *script = virtual_to_segmented(0x13, o->behavior);
if (m->playerIndex != 0) { return FALSE; } if (m->playerIndex != 0) { return FALSE; }
@ -2113,6 +2169,7 @@ u32 interact_grabbable(struct MarioState *m, u32 interactType, struct Object *o)
} }
u32 mario_can_talk(struct MarioState *m, u32 arg) { u32 mario_can_talk(struct MarioState *m, u32 arg) {
if (!m) { return FALSE; }
s16 val6; s16 val6;
if ((m->action & ACT_FLAG_IDLE) != 0x00000000) { if ((m->action & ACT_FLAG_IDLE) != 0x00000000) {
@ -2147,6 +2204,7 @@ u32 mario_can_talk(struct MarioState *m, u32 arg) {
#endif #endif
u32 check_read_sign(struct MarioState *m, struct Object *o) { u32 check_read_sign(struct MarioState *m, struct Object *o) {
if (!m || !o) { return FALSE; }
if ((m->input & READ_MASK) && mario_can_talk(m, 0) && object_facing_mario(m, o, SIGN_RANGE)) { if ((m->input & READ_MASK) && mario_can_talk(m, 0) && object_facing_mario(m, o, SIGN_RANGE)) {
s16 facingDYaw = (s16)(o->oMoveAngleYaw + 0x8000) - m->faceAngle[1]; s16 facingDYaw = (s16)(o->oMoveAngleYaw + 0x8000) - m->faceAngle[1];
if (facingDYaw >= -SIGN_RANGE && facingDYaw <= SIGN_RANGE) { if (facingDYaw >= -SIGN_RANGE && facingDYaw <= SIGN_RANGE) {
@ -2167,6 +2225,7 @@ u32 check_read_sign(struct MarioState *m, struct Object *o) {
} }
u32 check_npc_talk(struct MarioState *m, struct Object *o) { u32 check_npc_talk(struct MarioState *m, struct Object *o) {
if (!m || !o) { return FALSE; }
if ((m->input & READ_MASK) && mario_can_talk(m, 1)) { if ((m->input & READ_MASK) && mario_can_talk(m, 1)) {
s16 facingDYaw = mario_obj_angle_to_object(m, o) - m->faceAngle[1]; s16 facingDYaw = mario_obj_angle_to_object(m, o) - m->faceAngle[1];
if (facingDYaw >= -0x4000 && facingDYaw <= 0x4000) { if (facingDYaw >= -0x4000 && facingDYaw <= 0x4000) {
@ -2185,6 +2244,7 @@ u32 check_npc_talk(struct MarioState *m, struct Object *o) {
} }
u32 interact_text(struct MarioState *m, UNUSED u32 interactType, struct Object *o) { u32 interact_text(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
if (!m || !o) { return FALSE; }
u32 interact = FALSE; u32 interact = FALSE;
if (o->oInteractionSubtype & INT_SUBTYPE_SIGN) { if (o->oInteractionSubtype & INT_SUBTYPE_SIGN) {
@ -2199,6 +2259,7 @@ u32 interact_text(struct MarioState *m, UNUSED u32 interactType, struct Object *
} }
void check_kick_or_punch_wall(struct MarioState *m) { void check_kick_or_punch_wall(struct MarioState *m) {
if (!m) { return; }
if (m->flags & (MARIO_PUNCHING | MARIO_KICKING | MARIO_TRIPPING)) { if (m->flags & (MARIO_PUNCHING | MARIO_KICKING | MARIO_TRIPPING)) {
Vec3f detector; Vec3f detector;
detector[0] = m->pos[0] + 50.0f * sins(m->faceAngle[1]); detector[0] = m->pos[0] + 50.0f * sins(m->faceAngle[1]);
@ -2226,6 +2287,7 @@ void check_kick_or_punch_wall(struct MarioState *m) {
} }
void mario_process_interactions(struct MarioState *m) { void mario_process_interactions(struct MarioState *m) {
if (!m) { return; }
sDelayInvincTimer = FALSE; sDelayInvincTimer = FALSE;
gInteractionInvulnerable = (m->action & ACT_FLAG_INVULNERABLE) || m->invincTimer != 0; gInteractionInvulnerable = (m->action & ACT_FLAG_INVULNERABLE) || m->invincTimer != 0;
@ -2288,7 +2350,7 @@ void mario_process_interactions(struct MarioState *m) {
} }
void check_death_barrier(struct MarioState *m) { void check_death_barrier(struct MarioState *m) {
if (m->playerIndex != 0) { return; } if (!m || m->playerIndex != 0) { return; }
if (m->pos[1] < m->floorHeight + 2048.0f) { if (m->pos[1] < m->floorHeight + 2048.0f) {
bool allowDeath = true; bool allowDeath = true;
@ -2321,6 +2383,7 @@ void check_death_barrier(struct MarioState *m) {
} }
void check_lava_boost(struct MarioState *m) { void check_lava_boost(struct MarioState *m) {
if (!m) { return; }
bool allow = true; bool allow = true;
smlua_call_event_hooks_mario_param_and_int_ret_bool(HOOK_ALLOW_HAZARD_SURFACE, m, HAZARD_TYPE_LAVA_FLOOR, &allow); smlua_call_event_hooks_mario_param_and_int_ret_bool(HOOK_ALLOW_HAZARD_SURFACE, m, HAZARD_TYPE_LAVA_FLOOR, &allow);
if (m->action == ACT_BUBBLED || (gServerSettings.enableCheats && gCheats.godMode) || (!allow)) { return; } if (m->action == ACT_BUBBLED || (gServerSettings.enableCheats && gCheats.godMode) || (!allow)) { return; }
@ -2335,6 +2398,7 @@ void check_lava_boost(struct MarioState *m) {
} }
void pss_begin_slide(UNUSED struct MarioState *m) { void pss_begin_slide(UNUSED struct MarioState *m) {
if (!m) { return; }
if (!m->visibleToEnemies) { return; } if (!m->visibleToEnemies) { return; }
if (!(gHudDisplay.flags & HUD_DISPLAY_FLAG_TIMER)) { if (!(gHudDisplay.flags & HUD_DISPLAY_FLAG_TIMER)) {
level_control_timer(TIMER_CONTROL_SHOW); level_control_timer(TIMER_CONTROL_SHOW);
@ -2344,6 +2408,7 @@ void pss_begin_slide(UNUSED struct MarioState *m) {
} }
void pss_end_slide(struct MarioState *m) { void pss_end_slide(struct MarioState *m) {
if (!m) { return; }
//! This flag isn't set on death or level entry, allowing double star spawn //! This flag isn't set on death or level entry, allowing double star spawn
if (gPssSlideStarted) { if (gPssSlideStarted) {
u16 slideTime = level_control_timer(TIMER_CONTROL_STOP); u16 slideTime = level_control_timer(TIMER_CONTROL_STOP);
@ -2360,6 +2425,7 @@ void pss_end_slide(struct MarioState *m) {
} }
void mario_handle_special_floors(struct MarioState *m) { void mario_handle_special_floors(struct MarioState *m) {
if (!m) { return; }
if ((m->action & ACT_GROUP_MASK) == ACT_GROUP_CUTSCENE) { if ((m->action & ACT_GROUP_MASK) == ACT_GROUP_CUTSCENE) {
return; return;
} }

View file

@ -63,6 +63,7 @@ u16 gLocalBubbleCounter = 0;
* Checks if Mario's animation has reached its end point. * Checks if Mario's animation has reached its end point.
*/ */
s32 is_anim_at_end(struct MarioState *m) { s32 is_anim_at_end(struct MarioState *m) {
if (!m) { return FALSE; }
struct Object *o = m->marioObj; struct Object *o = m->marioObj;
if (o->header.gfx.animInfo.curAnim == NULL) { return TRUE; } if (o->header.gfx.animInfo.curAnim == NULL) { return TRUE; }
@ -119,6 +120,7 @@ s16 set_mario_animation(struct MarioState *m, s32 targetAnimID) {
* slowed down via acceleration. * slowed down via acceleration.
*/ */
s16 set_mario_anim_with_accel(struct MarioState *m, s32 targetAnimID, s32 accel) { s16 set_mario_anim_with_accel(struct MarioState *m, s32 targetAnimID, s32 accel) {
if (!m) { return 0; }
struct Object *o = m->marioObj; struct Object *o = m->marioObj;
if (!o || !m->animation) { return 0; } if (!o || !m->animation) { return 0; }
struct Animation *targetAnim = m->animation->targetAnim; struct Animation *targetAnim = m->animation->targetAnim;
@ -212,6 +214,7 @@ s32 is_anim_past_frame(struct MarioState *m, s16 animFrame) {
* and returns the animation's flags. * and returns the animation's flags.
*/ */
s16 find_mario_anim_flags_and_translation(struct Object *obj, s32 yaw, Vec3s translation) { s16 find_mario_anim_flags_and_translation(struct Object *obj, s32 yaw, Vec3s translation) {
if (!obj) { return 0; }
f32 dx; f32 dx;
f32 dz; f32 dz;
@ -238,6 +241,7 @@ s16 find_mario_anim_flags_and_translation(struct Object *obj, s32 yaw, Vec3s tra
* Updates Mario's position from his animation's translation. * Updates Mario's position from his animation's translation.
*/ */
void update_mario_pos_for_anim(struct MarioState *m) { void update_mario_pos_for_anim(struct MarioState *m) {
if (!m) { return; }
Vec3s translation; Vec3s translation;
s16 flags; s16 flags;
@ -257,6 +261,7 @@ void update_mario_pos_for_anim(struct MarioState *m) {
* Finds the vertical translation from Mario's animation. * Finds the vertical translation from Mario's animation.
*/ */
s16 return_mario_anim_y_translation(struct MarioState *m) { s16 return_mario_anim_y_translation(struct MarioState *m) {
if (!m) { return 0; }
Vec3s translation = { 0 }; Vec3s translation = { 0 };
find_mario_anim_flags_and_translation(m->marioObj, 0, translation); find_mario_anim_flags_and_translation(m->marioObj, 0, translation);
@ -271,6 +276,7 @@ s16 return_mario_anim_y_translation(struct MarioState *m) {
* Plays a sound if if Mario doesn't have the flag being checked. * Plays a sound if if Mario doesn't have the flag being checked.
*/ */
void play_sound_if_no_flag(struct MarioState *m, u32 soundBits, u32 flags) { void play_sound_if_no_flag(struct MarioState *m, u32 soundBits, u32 flags) {
if (!m) { return; }
if (!(m->flags & flags)) { if (!(m->flags & flags)) {
play_sound(soundBits, m->marioObj->header.gfx.cameraToObject); play_sound(soundBits, m->marioObj->header.gfx.cameraToObject);
m->flags |= flags; m->flags |= flags;
@ -281,6 +287,7 @@ void play_sound_if_no_flag(struct MarioState *m, u32 soundBits, u32 flags) {
* Plays a jump sound if one has not been played since the last action change. * Plays a jump sound if one has not been played since the last action change.
*/ */
void play_mario_jump_sound(struct MarioState *m) { void play_mario_jump_sound(struct MarioState *m) {
if (!m) { return; }
if (!(m->flags & MARIO_MARIO_SOUND_PLAYED)) { if (!(m->flags & MARIO_MARIO_SOUND_PLAYED)) {
#ifndef VERSION_JP #ifndef VERSION_JP
if (m->action == ACT_TRIPLE_JUMP) { if (m->action == ACT_TRIPLE_JUMP) {
@ -655,6 +662,7 @@ void resolve_and_return_wall_collisions_data(Vec3f pos, f32 offset, f32 radius,
* Finds the ceiling from a vec3f horizontally and a height (with 80 vertical buffer). * Finds the ceiling from a vec3f horizontally and a height (with 80 vertical buffer).
*/ */
f32 vec3f_find_ceil(Vec3f pos, f32 height, struct Surface **ceil) { f32 vec3f_find_ceil(Vec3f pos, f32 height, struct Surface **ceil) {
if (!ceil) { return 0; }
UNUSED f32 unused; UNUSED f32 unused;
return find_ceil(pos[0], height + 80.0f, pos[2], ceil); return find_ceil(pos[0], height + 80.0f, pos[2], ceil);
@ -666,6 +674,7 @@ f32 vec3f_find_ceil(Vec3f pos, f32 height, struct Surface **ceil) {
*/ */
// Prevent exposed ceilings // Prevent exposed ceilings
f32 vec3f_mario_ceil(Vec3f pos, f32 height, struct Surface **ceil) { f32 vec3f_mario_ceil(Vec3f pos, f32 height, struct Surface **ceil) {
if (!ceil) { return 0; }
if (gLevelValues.fixCollisionBugs) { if (gLevelValues.fixCollisionBugs) {
height = MAX(height + 80.0f, pos[1] - 2); height = MAX(height + 80.0f, pos[1] - 2);
return find_ceil(pos[0], height, pos[2], ceil); return find_ceil(pos[0], height, pos[2], ceil);
@ -678,6 +687,7 @@ f32 vec3f_mario_ceil(Vec3f pos, f32 height, struct Surface **ceil) {
* Determines if Mario is facing "downhill." * Determines if Mario is facing "downhill."
*/ */
s32 mario_facing_downhill(struct MarioState *m, s32 turnYaw) { s32 mario_facing_downhill(struct MarioState *m, s32 turnYaw) {
if (!m) { return 0; }
s16 faceAngleYaw = m->faceAngle[1]; s16 faceAngleYaw = m->faceAngle[1];
// This is never used in practice, as turnYaw is // This is never used in practice, as turnYaw is
@ -695,6 +705,8 @@ s32 mario_facing_downhill(struct MarioState *m, s32 turnYaw) {
* Determines if a surface is slippery based on the surface class. * Determines if a surface is slippery based on the surface class.
*/ */
u32 mario_floor_is_slippery(struct MarioState *m) { u32 mario_floor_is_slippery(struct MarioState *m) {
if (!m) { return FALSE; }
f32 normY; f32 normY;
if ((m->area->terrainType & TERRAIN_MASK) == TERRAIN_SLIDE if ((m->area->terrainType & TERRAIN_MASK) == TERRAIN_SLIDE
@ -728,6 +740,7 @@ u32 mario_floor_is_slippery(struct MarioState *m) {
* Determines if a surface is a slope based on the surface class. * Determines if a surface is a slope based on the surface class.
*/ */
s32 mario_floor_is_slope(struct MarioState *m) { s32 mario_floor_is_slope(struct MarioState *m) {
if (!m) { return FALSE; }
f32 normY; f32 normY;
if ((m->area->terrainType & TERRAIN_MASK) == TERRAIN_SLIDE if ((m->area->terrainType & TERRAIN_MASK) == TERRAIN_SLIDE
@ -760,6 +773,7 @@ s32 mario_floor_is_slope(struct MarioState *m) {
* Determines if a surface is steep based on the surface class. * Determines if a surface is steep based on the surface class.
*/ */
s32 mario_floor_is_steep(struct MarioState *m) { s32 mario_floor_is_steep(struct MarioState *m) {
if (!m) { return FALSE; }
f32 normY; f32 normY;
s32 result = FALSE; s32 result = FALSE;
@ -913,6 +927,7 @@ void set_mario_y_vel_based_on_fspeed(struct MarioState *m, f32 initialVelY, f32
* Transitions for a variety of airborne actions. * Transitions for a variety of airborne actions.
*/ */
static u32 set_mario_action_airborne(struct MarioState *m, u32 action, u32 actionArg) { static u32 set_mario_action_airborne(struct MarioState *m, u32 action, u32 actionArg) {
if (!m) { return FALSE; }
f32 fowardVel; f32 fowardVel;
if ((m->squishTimer != 0 || m->quicksandDepth >= 1.0f) if ((m->squishTimer != 0 || m->quicksandDepth >= 1.0f)
@ -1033,6 +1048,7 @@ static u32 set_mario_action_airborne(struct MarioState *m, u32 action, u32 actio
* Transitions for a variety of moving actions. * Transitions for a variety of moving actions.
*/ */
static u32 set_mario_action_moving(struct MarioState *m, u32 action, UNUSED u32 actionArg) { static u32 set_mario_action_moving(struct MarioState *m, u32 action, UNUSED u32 actionArg) {
if (!m) { return FALSE; }
s16 floorClass = mario_get_floor_class(m); s16 floorClass = mario_get_floor_class(m);
f32 forwardVel = m->forwardVel; f32 forwardVel = m->forwardVel;
f32 mag = min(m->intendedMag, 8.0f); f32 mag = min(m->intendedMag, 8.0f);
@ -1078,6 +1094,7 @@ static u32 set_mario_action_moving(struct MarioState *m, u32 action, UNUSED u32
* Transition for certain submerged actions, which is actually just the metal jump actions. * Transition for certain submerged actions, which is actually just the metal jump actions.
*/ */
static u32 set_mario_action_submerged(struct MarioState *m, u32 action, UNUSED u32 actionArg) { static u32 set_mario_action_submerged(struct MarioState *m, u32 action, UNUSED u32 actionArg) {
if (!m) { return FALSE; }
if (action == ACT_METAL_WATER_JUMP || action == ACT_HOLD_METAL_WATER_JUMP) { if (action == ACT_METAL_WATER_JUMP || action == ACT_HOLD_METAL_WATER_JUMP) {
m->vel[1] = 32.0f; m->vel[1] = 32.0f;
} }
@ -1089,6 +1106,7 @@ static u32 set_mario_action_submerged(struct MarioState *m, u32 action, UNUSED u
* Transitions for a variety of cutscene actions. * Transitions for a variety of cutscene actions.
*/ */
static u32 set_mario_action_cutscene(struct MarioState *m, u32 action, UNUSED u32 actionArg) { static u32 set_mario_action_cutscene(struct MarioState *m, u32 action, UNUSED u32 actionArg) {
if (!m) { return FALSE; }
switch (action) { switch (action) {
case ACT_EMERGE_FROM_PIPE: case ACT_EMERGE_FROM_PIPE:
m->vel[1] = 52.0f; m->vel[1] = 52.0f;
@ -1459,6 +1477,7 @@ void update_mario_button_inputs(struct MarioState *m) {
* Updates the joystick intended magnitude. * Updates the joystick intended magnitude.
*/ */
void update_mario_joystick_inputs(struct MarioState *m) { void update_mario_joystick_inputs(struct MarioState *m) {
if (!m) { return; }
struct Controller *controller = m->controller; struct Controller *controller = m->controller;
f32 mag = ((controller->stickMag / 64.0f) * (controller->stickMag / 64.0f)) * 64.0f; f32 mag = ((controller->stickMag / 64.0f) * (controller->stickMag / 64.0f)) * 64.0f;
@ -1490,6 +1509,7 @@ void update_mario_joystick_inputs(struct MarioState *m) {
* Resolves wall collisions, and updates a variety of inputs. * Resolves wall collisions, and updates a variety of inputs.
*/ */
void update_mario_geometry_inputs(struct MarioState *m) { void update_mario_geometry_inputs(struct MarioState *m) {
if (!m) { return; }
u8 copiedPlayer = FALSE; u8 copiedPlayer = FALSE;
copyPlayerGoto:; copyPlayerGoto:;
@ -1565,6 +1585,7 @@ copyPlayerGoto:;
* Handles Mario's input flags as well as a couple timers. * Handles Mario's input flags as well as a couple timers.
*/ */
void update_mario_inputs(struct MarioState *m) { void update_mario_inputs(struct MarioState *m) {
if (!m) { return; }
if (m->playerIndex == 0) { m->input = 0; } if (m->playerIndex == 0) { m->input = 0; }
u8 localIsPaused = (m->playerIndex == 0) && (sCurrPlayMode == PLAY_MODE_PAUSED || m->freeze > 0); u8 localIsPaused = (m->playerIndex == 0) && (sCurrPlayMode == PLAY_MODE_PAUSED || m->freeze > 0);
@ -1658,6 +1679,7 @@ void update_mario_inputs(struct MarioState *m) {
* Set's the camera preset for submerged action behaviors. * Set's the camera preset for submerged action behaviors.
*/ */
void set_submerged_cam_preset_and_spawn_bubbles(struct MarioState *m) { void set_submerged_cam_preset_and_spawn_bubbles(struct MarioState *m) {
if (!m) { return; }
f32 heightBelowWater; f32 heightBelowWater;
s16 camPreset; s16 camPreset;
@ -1693,6 +1715,7 @@ void set_submerged_cam_preset_and_spawn_bubbles(struct MarioState *m) {
* Both increments and decrements Mario's HP. * Both increments and decrements Mario's HP.
*/ */
void update_mario_health(struct MarioState *m) { void update_mario_health(struct MarioState *m) {
if (!m) { return; }
s32 terrainIsSnow; s32 terrainIsSnow;
if (m->health >= 0x100) { if (m->health >= 0x100) {
@ -1761,6 +1784,7 @@ void update_mario_health(struct MarioState *m) {
* Updates some basic info for camera usage. * Updates some basic info for camera usage.
*/ */
void update_mario_info_for_cam(struct MarioState *m) { void update_mario_info_for_cam(struct MarioState *m) {
if (!m) { return; }
m->marioBodyState->action = m->action; m->marioBodyState->action = m->action;
m->statusForCamera->action = m->action; m->statusForCamera->action = m->action;
@ -1775,6 +1799,7 @@ void update_mario_info_for_cam(struct MarioState *m) {
* Resets Mario's model, done every time an action is executed. * Resets Mario's model, done every time an action is executed.
*/ */
void mario_reset_bodystate(struct MarioState *m) { void mario_reset_bodystate(struct MarioState *m) {
if (!m) { return; }
struct MarioBodyState *bodyState = m->marioBodyState; struct MarioBodyState *bodyState = m->marioBodyState;
bodyState->capState = MARIO_HAS_DEFAULT_CAP_OFF; bodyState->capState = MARIO_HAS_DEFAULT_CAP_OFF;
@ -1790,6 +1815,7 @@ void mario_reset_bodystate(struct MarioState *m) {
* Adjusts Mario's graphical height for quicksand. * Adjusts Mario's graphical height for quicksand.
*/ */
void sink_mario_in_quicksand(struct MarioState *m) { void sink_mario_in_quicksand(struct MarioState *m) {
if (!m) { return; }
struct Object *o = m->marioObj; struct Object *o = m->marioObj;
if (o->header.gfx.throwMatrix) { if (o->header.gfx.throwMatrix) {
@ -1812,6 +1838,7 @@ u64 sCapFlickerFrames = 0x4444449249255555;
* Updates the cap flags mainly based on the cap timer. * Updates the cap flags mainly based on the cap timer.
*/ */
u32 update_and_return_cap_flags(struct MarioState *m) { u32 update_and_return_cap_flags(struct MarioState *m) {
if (!m) { return 0; }
u32 flags = m->flags; u32 flags = m->flags;
u32 action; u32 action;
@ -1854,6 +1881,7 @@ u32 update_and_return_cap_flags(struct MarioState *m) {
* Updates the Mario's cap, rendering, and hitbox. * Updates the Mario's cap, rendering, and hitbox.
*/ */
void mario_update_hitbox_and_cap_model(struct MarioState *m) { void mario_update_hitbox_and_cap_model(struct MarioState *m) {
if (!m) { return; }
struct MarioBodyState *bodyState = m->marioBodyState; struct MarioBodyState *bodyState = m->marioBodyState;
s32 flags = update_and_return_cap_flags(m); s32 flags = update_and_return_cap_flags(m);
@ -1941,6 +1969,7 @@ void queue_particle_rumble(void) {
} }
static u8 prevent_hang(u32 hangPreventionActions[], u8* hangPreventionIndex) { static u8 prevent_hang(u32 hangPreventionActions[], u8* hangPreventionIndex) {
if (!hangPreventionActions) { return TRUE; }
// save the action sequence // save the action sequence
hangPreventionActions[*hangPreventionIndex] = gMarioState->action; hangPreventionActions[*hangPreventionIndex] = gMarioState->action;
*hangPreventionIndex = *hangPreventionIndex + 1; *hangPreventionIndex = *hangPreventionIndex + 1;
@ -2184,6 +2213,7 @@ s32 execute_mario_action(UNUSED struct Object *o) {
} }
s32 force_idle_state(struct MarioState* m) { s32 force_idle_state(struct MarioState* m) {
if (!m) { return 0; }
u8 underWater = (m->pos[1] < ((f32)m->waterLevel)); u8 underWater = (m->pos[1] < ((f32)m->waterLevel));
return set_mario_action(m, underWater ? ACT_WATER_IDLE : ACT_IDLE, 0); return set_mario_action(m, underWater ? ACT_WATER_IDLE : ACT_IDLE, 0);
} }
@ -2193,6 +2223,7 @@ s32 force_idle_state(struct MarioState* m) {
**************************************************/ **************************************************/
void init_single_mario(struct MarioState* m) { void init_single_mario(struct MarioState* m) {
if (!m) { return; }
u16 playerIndex = m->playerIndex; u16 playerIndex = m->playerIndex;
struct SpawnInfo* spawnInfo = &gPlayerSpawnInfos[playerIndex]; struct SpawnInfo* spawnInfo = &gPlayerSpawnInfos[playerIndex];
@ -2306,6 +2337,7 @@ void init_mario(void) {
} }
static void init_mario_single_from_save_file(struct MarioState* m, u16 index) { static void init_mario_single_from_save_file(struct MarioState* m, u16 index) {
if (!m) { return; }
m->playerIndex = index; m->playerIndex = index;
m->flags = 0; m->flags = 0;
m->action = 0; m->action = 0;
@ -2335,6 +2367,7 @@ void init_mario_from_save_file(void) {
} }
void set_mario_particle_flags(struct MarioState* m, u32 flags, u8 clear) { void set_mario_particle_flags(struct MarioState* m, u32 flags, u8 clear) {
if (!m) { return; }
if (m->playerIndex != 0) { if (m->playerIndex != 0) {
return; return;
} }

View file

@ -986,6 +986,7 @@ void obj_set_face_angle_to_move_angle(struct Object *obj) {
} }
u32 get_object_list_from_behavior(const BehaviorScript *behavior) { u32 get_object_list_from_behavior(const BehaviorScript *behavior) {
if (!behavior) { return OBJ_LIST_DEFAULT; }
u32 objectList; u32 objectList;
// If the first behavior command is "begin", then get the object list header // If the first behavior command is "begin", then get the object list header
@ -1000,6 +1001,7 @@ u32 get_object_list_from_behavior(const BehaviorScript *behavior) {
} }
struct Object *cur_obj_nearest_object_with_behavior(const BehaviorScript *behavior) { struct Object *cur_obj_nearest_object_with_behavior(const BehaviorScript *behavior) {
if (!behavior) { return NULL; }
struct Object *obj; struct Object *obj;
f32 dist; f32 dist;
@ -1009,6 +1011,7 @@ struct Object *cur_obj_nearest_object_with_behavior(const BehaviorScript *behavi
} }
f32 cur_obj_dist_to_nearest_object_with_behavior(const BehaviorScript *behavior) { f32 cur_obj_dist_to_nearest_object_with_behavior(const BehaviorScript *behavior) {
if (!behavior) { return 0; }
struct Object *obj; struct Object *obj;
f32 dist; f32 dist;

View file

@ -530,6 +530,7 @@ static void hud_rotate_and_translate_vec3f(Vec3f vec, Mat4* mtx, Vec3f out) {
} }
bool djui_hud_world_pos_to_screen_pos(Vec3f pos, Vec3f out) { bool djui_hud_world_pos_to_screen_pos(Vec3f pos, Vec3f out) {
if (!gCamera) { return false; }
hud_rotate_and_translate_vec3f(pos, &gCamera->mtx, out); hud_rotate_and_translate_vec3f(pos, &gCamera->mtx, out);
if (out[2] >= 0.0f) { if (out[2] >= 0.0f) {
return false; return false;