Prevented hundreds of additional crashes from the Mod API

This commit is contained in:
MysterD 2023-05-11 13:05:06 -07:00
parent 82945f9c0f
commit cc1ec3e81f
30 changed files with 842 additions and 5647 deletions

View file

@ -61,6 +61,8 @@ OPT_LEVEL ?= -1
DEBUG_INFO_LEVEL ?= 2
# Enable profiling
PROFILE ?= 0
# Enable address sanitizer
ASAN ?= 0
# Compile headless
HEADLESS ?= 0
# Enable Game ICON
@ -949,6 +951,12 @@ ifeq ($(WINDOWS_BUILD),999)
endif
endif
ifeq ($(ASAN),1)
EXTRA_CFLAGS += -fsanitize=address -fsanitize=bounds-strict -fsanitize=undefined -ggdb
EXTRA_CPP_FLAGS += -fsanitize=address -fsanitize=bounds-strict -fsanitize=undefined -ggdb
LDFLAGS += -fsanitize=address -fsanitize=bounds-strict -fsanitize=undefined -static-libasan
endif
# Coop specific libraries
# Zlib

View file

@ -806,7 +806,7 @@ def output_fuzz_function(fname, function):
comment = ' -- '
fid = function['identifier']
line = ' ' + fid + '('
line = ' function() return ' + fid + '('
for param in function['params']:
if first:
@ -822,18 +822,13 @@ def output_fuzz_function(fname, function):
ptype = 'integer'
line += 'rnd_' + ptype.strip().replace('`', '').replace(' ', '').split('<')[-1].split('>')[0].split('(')[0] + '()'
#if ptype == '`integer`' or ptype == '`number`' or 'enum' in ptype:
# print('0', end='')
#else:
# print('nil', end='')
comment += ptype
line += ')'
if len(line) >= 80:
line = line + '\n ' + comment + '\n'
else:
line = line.ljust(80) + comment + '\n'
line += ') end,\n'
#if len(line) >= 80:
# line = line + '\n ' + comment + '\n'
#else:
# line = line.ljust(80) + comment + '\n'
global fuzz_functions
fuzz_functions += line

View file

@ -50,7 +50,7 @@ end
--------
function rnd_string()
t = { 0, "test", "this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string" }
t = { 0, "test", "this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string" }
return t[math.random(#t)]
end
@ -65,7 +65,7 @@ function rnd_number()
end
function rnd_boolean()
t = { nil, false, true }
t = { false, true }
return t[math.random(#t)]
end
@ -100,12 +100,12 @@ function rnd_Object()
end
function rnd_MarioState()
t = { nil, gMarioStates[math.random(0, MAX_PLAYERS)] }
t = { nil, gMarioStates[0], gMarioStates[math.random(0, MAX_PLAYERS)] }
return t[math.random(#t)]
end
function rnd_NetworkPlayer()
t = { nil, gNetworkPlayers[math.random(0, MAX_PLAYERS)] }
t = { nil, gNetworkPlayers[0], gNetworkPlayers[math.random(0, MAX_PLAYERS)] }
return t[math.random(#t)]
end
@ -137,7 +137,18 @@ end
--------
function fuzz_functions()
local funcs = {
-- $[FUNCS]
}
for i = #funcs, 2, -1 do
local j = math.random(i)
funcs[i], funcs[j] = funcs[j], funcs[i]
end
for k,v in pairs(funcs) do
v()
end
end
id_bhvFuncs = hook_behavior(nil, OBJ_LIST_DEFAULT, true, fuzz_functions, nil, 'id_bhvFuncs')
@ -147,12 +158,33 @@ id_bhvFuncs = hook_behavior(nil, OBJ_LIST_DEFAULT, true, fuzz_functions, nil, 'i
function fuzz_structs()
end
function update()
--------
local sCountDown = 0
local sLevel = 15
function on_sync_valid()
fuzz_functions()
for i=0,10 do
spawn_non_sync_object(id_bhvFuncs, E_MODEL_SPINY_BALL, 0, 0, 0, nil)
end
end
function update()
sCountDown = sCountDown - 1
if sCountDown <= 0 then
print('warping to ', sLevel)
warp_to_level(sLevel, 1, 1)
sLevel = sLevel + 1
if sLevel > LEVEL_COUNT then
sLevel = 0
end
sCountDown = 10
end
end
hook_chat_command('fuzz-funcs', 'funcs', fuzz_functions)
hook_chat_command('fuzz-structs', 'structs', fuzz_structs)
hook_event(HOOK_UPDATE, update)
hook_event(HOOK_ON_SYNC_VALID, on_sync_valid)
spawn_non_sync_object(id_bhvFuncs, E_MODEL_SPINY_BALL, 0, 0, 0, nil)
print('!')

View file

@ -238,7 +238,9 @@ const s32 *DynOS_Level_GetList() {
}
s32 DynOS_Level_GetCourse(s32 aLevel) {
return (s32) gLevelToCourseNumTable[aLevel - 1];
u32 index = aLevel - 1;
if (index >= LEVEL_COUNT) { return COURSE_NONE; }
return (s32) gLevelToCourseNumTable[index];
}
void DynOS_Level_Override(void* originalScript, void* newScript, s32 modIndex) {
@ -908,7 +910,7 @@ s16 *DynOS_Level_GetWarp(s32 aLevel, s32 aArea, u8 aWarpId) {
}
DynOS_Level_Init();
if (aLevel < LEVEL_COUNT) {
if (aLevel >= 0 && aLevel < LEVEL_COUNT) {
for (const auto &_Warp : sDynosLevelWarps[aLevel]) {
if (_Warp.mArea == aArea) {
if (_Warp.mId == aWarpId) {
@ -925,7 +927,7 @@ s16 *DynOS_Level_GetWarpEntry(s32 aLevel, s32 aArea) {
if (aLevel == LEVEL_TTM && aArea > 2) return NULL;
// override vanilla castle warps
if (DynOS_Level_GetCourse(aLevel) == COURSE_NONE) {
if (DynOS_Level_GetCourse(aLevel) == COURSE_NONE && aLevel >= 0 && aLevel < LEVEL_COUNT) {
extern const LevelScript level_castle_grounds_entry[];
extern const LevelScript level_castle_inside_entry[];
extern const LevelScript level_castle_courtyard_entry[];

View file

@ -2,9 +2,9 @@
set -e
if [ $# -eq 0 ]; then
make DEBUG=1 DEVELOPMENT=1 STRICT=1 -j
make DEBUG=1 DEVELOPMENT=1 STRICT=1 ASAN=1 -j
else
make DEBUG=1 DEVELOPMENT=1 -j
make DEBUG=1 DEVELOPMENT=1 ASAN=1 -j
fi
# find file

5582
grind.log

File diff suppressed because it is too large Load diff

View file

@ -453,7 +453,8 @@ OSPiHandle DriveRomHandle; // used in osDriveRomInit.c. Why here?
s8 D_SH_80343E48_pad[0x8];
#endif
struct Sound sSoundRequests[0x100] = { 0 };
#define MAX_SOUND_REQUESTS 0x100
struct Sound sSoundRequests[MAX_SOUND_REQUESTS] = { 0 };
struct ChannelVolumeScaleFade sVolumeScaleFades[SEQUENCE_PLAYERS][CHANNELS_MAX] = { 0 };
u8 sUsedChannelsForSoundBank[SOUND_BANK_COUNT] = { 0 };
u8 sCurrentSound[SOUND_BANK_COUNT][MAX_CHANNELS_PER_SOUND_BANK] = { 0 }; // index into sSoundBanks
@ -669,6 +670,7 @@ void audio_reset_session_eu(s32 presetId) {
* Called from threads: thread3_main, thread5_game_loop
*/
static void seq_player_fade_to_zero_volume(s32 player, FadeT fadeDuration) {
if (player >= SEQUENCE_PLAYERS) { return; }
struct SequencePlayer *seqPlayer = &gSequencePlayers[player];
#ifndef VERSION_JP
@ -687,6 +689,7 @@ static void seq_player_fade_to_zero_volume(s32 player, FadeT fadeDuration) {
* Called from threads: thread4_sound, thread5_game_loop
*/
static void seq_player_fade_from_zero_volume(s32 player, FadeT fadeInTime) {
if (player >= SEQUENCE_PLAYERS) { return; }
struct SequencePlayer *seqPlayer = &gSequencePlayers[player];
if (fadeInTime == 0 || seqPlayer->state == SEQUENCE_PLAYER_STATE_FADE_OUT) {
@ -704,6 +707,7 @@ static void seq_player_fade_from_zero_volume(s32 player, FadeT fadeInTime) {
* Called from threads: thread5_game_loop
*/
static void seq_player_fade_to_percentage_of_volume(s32 player, FadeT fadeDuration, u8 percentage) {
if (player >= SEQUENCE_PLAYERS) { return; }
struct SequencePlayer *seqPlayer = &gSequencePlayers[player];
f32 targetVolume;
@ -739,6 +743,7 @@ static void seq_player_fade_to_percentage_of_volume(s32 player, FadeT fadeDurati
* Called from threads: thread3_main, thread4_sound, thread5_game_loop
*/
static void seq_player_fade_to_normal_volume(s32 player, FadeT fadeDuration) {
if (player >= SEQUENCE_PLAYERS) { return; }
struct SequencePlayer *seqPlayer = &gSequencePlayers[player];
#if defined(VERSION_EU) || defined(VERSION_SH)
@ -770,6 +775,7 @@ static void seq_player_fade_to_normal_volume(s32 player, FadeT fadeDuration) {
* Called from threads: thread3_main, thread4_sound, thread5_game_loop
*/
static void seq_player_fade_to_target_volume(s32 player, FadeT fadeDuration, u8 targetVolume) {
if (player >= SEQUENCE_PLAYERS) { return; }
struct SequencePlayer *seqPlayer = &gSequencePlayers[player];
#if defined(VERSION_JP) || defined(VERSION_US)
@ -871,6 +877,7 @@ void play_sound_with_freq_scale(s32 soundBits, f32* pos, f32 freqScale) {
* Called from threads: thread4_sound, thread5_game_loop (EU only)
*/
static void process_sound_request(u32 bits, f32 *pos, f32 freqScale) {
if (!pos) { return; }
u8 bank;
u8 soundIndex;
u8 counter = 0;
@ -881,6 +888,8 @@ static void process_sound_request(u32 bits, f32 *pos, f32 freqScale) {
bank = (bits & SOUNDARGS_MASK_BANK) >> SOUNDARGS_SHIFT_BANK;
soundId = (bits & SOUNDARGS_MASK_SOUNDID) >> SOUNDARGS_SHIFT_SOUNDID;
if (bank >= SOUND_BANK_COUNT) { return; }
if (soundId >= sNumSoundsPerBank[bank] || sSoundBankDisabled[bank]) {
return;
}
@ -975,6 +984,7 @@ static void process_all_sound_requests(void) {
* Called from threads: thread4_sound, thread5_game_loop (EU only)
*/
static void delete_sound_from_bank(u8 bank, u8 soundIndex) {
if (bank >= SOUND_BANK_COUNT || soundIndex >= SOUND_INDEX_COUNT) { return; }
if (sSoundBankUsedListBack[bank] == soundIndex) {
// Remove from end of used list
sSoundBankUsedListBack[bank] = sSoundBanks[bank][soundIndex].prev;
@ -997,6 +1007,7 @@ static void delete_sound_from_bank(u8 bank, u8 soundIndex) {
* Called from threads: thread3_main, thread4_sound, thread5_game_loop
*/
static void update_background_music_after_sound(u8 bank, u8 soundIndex) {
if (bank >= SOUND_BANK_COUNT || soundIndex >= SOUND_INDEX_COUNT) { return; }
if (sSoundBanks[bank][soundIndex].soundBits & SOUND_LOWER_BACKGROUND_MUSIC) {
sSoundBanksThatLowerBackgroundMusic &= (1 << bank) ^ 0xffff;
begin_background_music_fade(50);
@ -1007,6 +1018,7 @@ static void update_background_music_after_sound(u8 bank, u8 soundIndex) {
* Called from threads: thread4_sound, thread5_game_loop (EU only)
*/
static void select_current_sounds(u8 bank) {
if (bank >= SOUND_BANK_COUNT) { return; }
u32 isDiscreteAndStatus;
u8 latestSoundIndex;
u8 i;
@ -1252,6 +1264,7 @@ f32 get_sound_pan(f32 x, f32 z) {
* Called from threads: thread4_sound, thread5_game_loop (EU only)
*/
static f32 get_sound_volume(u8 bank, u8 soundIndex, f32 volumeRange) {
if (bank >= SOUND_BANK_COUNT || soundIndex >= SOUND_INDEX_COUNT) { return 0; }
f32 maxSoundDistance;
f32 intensity;
#ifndef VERSION_JP
@ -1307,6 +1320,7 @@ static f32 get_sound_volume(u8 bank, u8 soundIndex, f32 volumeRange) {
* Called from threads: thread4_sound, thread5_game_loop (EU only)
*/
static f32 get_sound_freq_scale(u8 bank, u8 item) {
if (bank >= SOUND_BANK_COUNT || item >= SOUND_INDEX_COUNT) { return 0; }
f32 amount;
if (!(sSoundBanks[bank][item].soundBits & SOUND_CONSTANT_FREQUENCY)) {
@ -1327,6 +1341,7 @@ static f32 get_sound_freq_scale(u8 bank, u8 item) {
* Called from threads: thread4_sound, thread5_game_loop (EU only)
*/
static u8 get_sound_reverb(UNUSED u8 bank, UNUSED u8 soundIndex, u8 channelIndex) {
if (bank >= SOUND_BANK_COUNT || soundIndex >= SOUND_INDEX_COUNT || channelIndex >= CHANNELS_MAX) { return 0; }
u8 area;
u8 level;
u8 reverb;
@ -1808,6 +1823,7 @@ static void seq_player_play_sequence(u8 player, u8 seqId, u16 arg2) {
* Called from threads: thread5_game_loop
*/
void seq_player_fade_out(u8 player, u16 fadeDuration) {
if (player >= SEQUENCE_PLAYERS) { return; }
#if defined(VERSION_EU) || defined(VERSION_SH)
#ifdef VERSION_EU
u32 fd = fadeDuration;
@ -2059,6 +2075,7 @@ void unused_8031FED0(u8 player, u32 bits, s8 arg2) {
* Called from threads: thread5_game_loop
*/
void seq_player_lower_volume(u8 player, u16 fadeDuration, u8 percentage) {
if (player >= SEQUENCE_PLAYERS) { return; }
if (player == SEQ_PLAYER_LEVEL) {
sLowerBackgroundMusicVolume = TRUE;
begin_background_music_fade(fadeDuration);
@ -2076,6 +2093,7 @@ void seq_player_lower_volume(u8 player, u16 fadeDuration, u8 percentage) {
* Called from threads: thread5_game_loop
*/
void seq_player_unlower_volume(u8 player, u16 fadeDuration) {
if (player >= SEQUENCE_PLAYERS) { return; }
sLowerBackgroundMusicVolume = FALSE;
if (player == SEQ_PLAYER_LEVEL) {
if (gSequencePlayers[player].state != SEQUENCE_PLAYER_STATE_FADE_OUT) {
@ -2170,7 +2188,7 @@ void sound_init(void) {
for (i = 0; i < SOUND_BANK_COUNT; i++) {
// Set each sound in the bank to STOPPED
for (j = 0; j < 40; j++) {
for (j = 0; j < SOUND_INDEX_COUNT; j++) {
sSoundBanks[i][j].soundStatus = SOUND_STATUS_STOPPED;
}
@ -2198,7 +2216,7 @@ void sound_init(void) {
sSoundBanks[i][j].next = 0xff;
}
for (j = 0; j < 3; j++) {
for (j = 0; j < SEQUENCE_PLAYERS; j++) {
for (i = 0; i < CHANNELS_MAX; i++) {
sVolumeScaleFades[j][i].remainingFrames = 0;
}
@ -2227,6 +2245,7 @@ void sound_init(void) {
// (unused)
void get_currently_playing_sound(u8 bank, u8 *numPlayingSounds, u8 *numSoundsInBank, u8 *soundId) {
if (bank >= SOUND_BANK_COUNT || !numPlayingSounds || !numSoundsInBank || !soundId) { return; }
u8 i;
u8 count = 0;
@ -2251,6 +2270,7 @@ void get_currently_playing_sound(u8 bank, u8 *numPlayingSounds, u8 *numSoundsInB
*/
void stop_sound(u32 soundBits, f32 *pos) {
u8 bank = (soundBits & SOUNDARGS_MASK_BANK) >> SOUNDARGS_SHIFT_BANK;
if (bank >= SOUND_BANK_COUNT) { return; }
u8 soundIndex = sSoundBanks[bank][0].next;
while (soundIndex != 0xff) {
@ -2295,6 +2315,7 @@ void stop_sounds_from_source(f32 *pos) {
* Called from threads: thread3_main, thread5_game_loop
*/
static void stop_sounds_in_bank(u8 bank) {
if (bank >= SOUND_BANK_COUNT) { return; }
u8 soundIndex = sSoundBanks[bank][0].next;
while (soundIndex != 0xff) {
@ -2357,6 +2378,7 @@ void sound_banks_enable(UNUSED u8 player, u16 bankMask) {
}
u8 unused_803209D8(u8 player, u8 channelIndex, u8 arg2) {
if (player >= SEQUENCE_PLAYERS || channelIndex >= CHANNELS_MAX) { return 0; }
u8 ret = 0;
if (gSequencePlayers[player].channels[channelIndex] != &gSequenceChannelNone) {
gSequencePlayers[player].channels[channelIndex]->stopSomething2 = arg2;
@ -2372,6 +2394,7 @@ u8 unused_803209D8(u8 player, u8 channelIndex, u8 arg2) {
* Called from threads: thread5_game_loop
*/
void set_sound_moving_speed(u8 bank, u8 speed) {
if (bank >= SOUND_BANK_COUNT) { return; }
sSoundMovingSpeed[bank] = speed;
}
@ -2427,6 +2450,7 @@ void set_sequence_player_volume(s32 player, f32 volume) {
* Called from threads: thread5_game_loop
*/
void play_music(u8 player, u16 seqArgs, u16 fadeTimer) {
if (player >= SEQUENCE_PLAYERS) { return; }
u8 seqId = seqArgs & 0xff;
u8 priority = seqArgs >> 8;
u8 i;
@ -2842,6 +2866,7 @@ void unused_80321474(UNUSED s32 arg0) {
}
void sound_reset_background_music_default_volume(u8 seqId) {
if (seqId >= sizeof(sBackgroundMusicDefaultVolume) / sizeof(sBackgroundMusicDefaultVolume[0])) { return; }
if (seqId >= SEQ_EVENT_CUTSCENE_LAKITU) {
sBackgroundMusicDefaultVolume[seqId] = 75;
return;

View file

@ -2303,8 +2303,10 @@ void sequence_channel_process_script(struct SequenceChannel *seqChannel) {
#ifdef VERSION_EU
if (1) {}
#endif
if (loBits < LAYERS_MAX) {
seqChannel->layers[loBits]->scriptState.pc = seqPlayer->seqData + sp5A;
}
}
break;
case 0xa0: // chan_freelayer
@ -2315,8 +2317,10 @@ void sequence_channel_process_script(struct SequenceChannel *seqChannel) {
if (value != -1 && seq_channel_set_layer(seqChannel, loBits) != -1) {
seqData = (*seqChannel->dynTable)[value];
sp5A = ((seqData[0] << 8) + seqData[1]);
if (loBits < LAYERS_MAX) {
seqChannel->layers[loBits]->scriptState.pc = seqPlayer->seqData + sp5A;
}
}
break;
#ifndef VERSION_EU

View file

@ -915,6 +915,7 @@ f32 atan2f(f32 y, f32 x) {
* TODO: verify the classification of the spline / figure out how polynomials were computed
*/
void spline_get_weights(struct MarioState* m, Vec4f result, f32 t, UNUSED s32 c) {
if (!m) { return; }
f32 tinv = 1 - t;
f32 tinv2 = tinv * tinv;
f32 tinv3 = tinv2 * tinv;
@ -964,6 +965,7 @@ void spline_get_weights(struct MarioState* m, Vec4f result, f32 t, UNUSED s32 c)
* That's because the spline has a 3rd degree polynomial, so it looks 3 points ahead.
*/
void anim_spline_init(struct MarioState* m, Vec4s *keyFrames) {
if (!m) { return; }
m->splineKeyframe = keyFrames;
m->splineKeyframeFraction = 0;
m->splineState = 1;
@ -975,6 +977,7 @@ void anim_spline_init(struct MarioState* m, Vec4s *keyFrames) {
* Returns TRUE when the last point is reached, FALSE otherwise.
*/
s32 anim_spline_poll(struct MarioState* m, Vec3f result) {
if (!m) { return 0; }
Vec4f weights = { 0 };
s32 i;
s32 hasEnded = FALSE;

View file

@ -33,7 +33,7 @@ SpatialPartitionCell gDynamicSurfacePartition[NUM_CELLS][NUM_CELLS];
/**
* Pools of data to contain either surface nodes or surfaces.
*/
struct SurfaceNode *sSurfaceNodePool;
struct SurfaceNode *sSurfaceNodePool = NULL;
struct Surface *sSurfacePool;
/**
@ -688,6 +688,7 @@ static void unused_80383604(void) {
* Applies an object's transformation to the object's vertices.
*/
void transform_object_vertices(s16 **data, s16 *vertexData) {
if (!gCurrentObject) { return; }
register s16 *vertices;
register f32 vx, vy, vz;
register s32 numVertices;
@ -728,6 +729,7 @@ void transform_object_vertices(s16 **data, s16 *vertexData) {
* Load in the surfaces for the gCurrentObject. This includes setting the flags, exertion, and room.
*/
void load_object_surfaces(s16** data, s16* vertexData) {
if (!gCurrentObject) { return; }
s32 surfaceType;
s32 i;
s32 numSurfaces;
@ -784,6 +786,7 @@ void load_object_surfaces(s16** data, s16* vertexData) {
* Transform an object's vertices, reload them, and render the object.
*/
void load_object_collision_model(void) {
if (!gCurrentObject) { return; }
if (gCurrentObject->collisionData == NULL) { return; }
UNUSED s32 unused;

View file

@ -1,7 +1,7 @@
// sound_birds.inc.c
void bhv_birds_sound_loop(void) {
if (gCamera->mode == CAMERA_MODE_BEHIND_MARIO)
if (gCamera && gCamera->mode == CAMERA_MODE_BEHIND_MARIO)
return;
switch (o->oBehParams2ndByte) {

File diff suppressed because it is too large Load diff

View file

@ -706,6 +706,7 @@ s32 mario_facing_downhill(struct MarioState *m, s32 turnYaw) {
*/
u32 mario_floor_is_slippery(struct MarioState *m) {
if (!m) { return FALSE; }
if (!m->floor) { return FALSE; }
f32 normY;
@ -741,6 +742,7 @@ u32 mario_floor_is_slippery(struct MarioState *m) {
*/
s32 mario_floor_is_slope(struct MarioState *m) {
if (!m) { return FALSE; }
if (!m->floor) { return FALSE; }
f32 normY;
if ((m->area->terrainType & TERRAIN_MASK) == TERRAIN_SLIDE
@ -774,6 +776,7 @@ s32 mario_floor_is_slope(struct MarioState *m) {
*/
s32 mario_floor_is_steep(struct MarioState *m) {
if (!m) { return FALSE; }
if (!m->floor) { return FALSE; }
f32 normY;
s32 result = FALSE;

View file

@ -25,6 +25,7 @@
#include "pc/cheats.h"
void play_flip_sounds(struct MarioState *m, s16 frame1, s16 frame2, s16 frame3) {
if (!m) { return; }
s32 animFrame = m->marioObj->header.gfx.animInfo.animFrame;
if (animFrame == frame1 || animFrame == frame2 || animFrame == frame3) {
play_sound(SOUND_ACTION_SPIN, m->marioObj->header.gfx.cameraToObject);
@ -32,6 +33,7 @@ void play_flip_sounds(struct MarioState *m, s16 frame1, s16 frame2, s16 frame3)
}
void play_far_fall_sound(struct MarioState *m) {
if (!m) { return; }
u32 action = m->action;
if (!(action & ACT_FLAG_INVULNERABLE) && action != ACT_TWIRLING && action != ACT_FLYING
&& !(m->flags & MARIO_UNKNOWN_18)) {
@ -44,6 +46,7 @@ void play_far_fall_sound(struct MarioState *m) {
#ifndef VERSION_JP
void play_knockback_sound(struct MarioState *m) {
if (!m) { return; }
if (m->actionArg == 0 && (m->forwardVel <= -28.0f || m->forwardVel >= 28.0f)) {
play_character_sound_if_no_flag(m, CHAR_SOUND_DOH, MARIO_MARIO_SOUND_PLAYED);
} else {
@ -53,6 +56,7 @@ void play_knockback_sound(struct MarioState *m) {
#endif
s32 lava_boost_on_wall(struct MarioState *m) {
if (!m) { return 0; }
bool allow = true;
smlua_call_event_hooks_mario_param_and_int_ret_bool(HOOK_ALLOW_HAZARD_SURFACE, m, HAZARD_TYPE_LAVA_WALL, &allow);
if ((gServerSettings.enableCheats && gCheats.godMode) || (!allow)) { return FALSE; }
@ -72,6 +76,7 @@ s32 lava_boost_on_wall(struct MarioState *m) {
}
s32 check_fall_damage(struct MarioState *m, u32 hardFallAction) {
if (!m) { return 0; }
if (gServerSettings.enableCheats && gCheats.godMode && m->playerIndex == 0) { return FALSE; }
f32 fallHeight;
@ -114,6 +119,7 @@ s32 check_fall_damage(struct MarioState *m, u32 hardFallAction) {
}
s32 check_kick_or_dive_in_air(struct MarioState *m) {
if (!m) { return 0; }
if (m->input & INPUT_B_PRESSED) {
return set_mario_action(m, m->forwardVel > 28.0f ? ACT_DIVE : ACT_JUMP_KICK, 0);
}
@ -121,6 +127,7 @@ s32 check_kick_or_dive_in_air(struct MarioState *m) {
}
s32 should_get_stuck_in_ground(struct MarioState *m) {
if (!m) { return 0; }
if (m->floor == NULL) { return FALSE; }
u32 terrainType = m->area->terrainType & TERRAIN_MASK;
@ -139,6 +146,7 @@ s32 should_get_stuck_in_ground(struct MarioState *m) {
}
s32 check_fall_damage_or_get_stuck(struct MarioState *m, u32 hardFallAction) {
if (!m) { return 0; }
if (should_get_stuck_in_ground(m)) {
#ifdef VERSION_JP
play_character_sound(m, CHAR_SOUND_OOOF);
@ -156,13 +164,14 @@ s32 check_fall_damage_or_get_stuck(struct MarioState *m, u32 hardFallAction) {
}
s32 check_horizontal_wind(struct MarioState *m) {
if (!m) { return 0; }
struct Surface *floor;
f32 speed;
s16 pushAngle;
floor = m->floor;
if (floor->type == SURFACE_HORIZONTAL_WIND) {
if (floor && floor->type == SURFACE_HORIZONTAL_WIND) {
pushAngle = floor->force << 8;
m->slideVelX += 1.2f * sins(pushAngle);
@ -193,6 +202,7 @@ s32 check_horizontal_wind(struct MarioState *m) {
}
void update_air_with_turn(struct MarioState *m) {
if (!m) { return; }
f32 dragThreshold;
s16 intendedDYaw;
f32 intendedMag;
@ -223,6 +233,7 @@ void update_air_with_turn(struct MarioState *m) {
}
void update_air_without_turn(struct MarioState *m) {
if (!m) { return; }
f32 sidewaysSpeed = 0.0f;
f32 dragThreshold;
s16 intendedDYaw;
@ -260,6 +271,7 @@ void update_air_without_turn(struct MarioState *m) {
}
void update_lava_boost_or_twirling(struct MarioState *m) {
if (!m) { return; }
s16 intendedDYaw;
f32 intendedMag;
@ -285,6 +297,7 @@ void update_lava_boost_or_twirling(struct MarioState *m) {
}
void update_flying_yaw(struct MarioState *m) {
if (!m) { return; }
s16 targetYawVel = -(s16)(m->controller->stickX * (m->forwardVel / 4.0f));
if (targetYawVel > 0) {
@ -314,6 +327,7 @@ void update_flying_yaw(struct MarioState *m) {
}
void update_flying_pitch(struct MarioState *m) {
if (!m) { return; }
s16 targetPitchVel = -(s16)(m->controller->stickY * (m->forwardVel / 5.0f));
if (targetPitchVel > 0) {
@ -340,6 +354,7 @@ void update_flying_pitch(struct MarioState *m) {
}
void update_flying(struct MarioState *m) {
if (!m) { return; }
UNUSED u32 unused;
update_flying_pitch(m);
@ -378,6 +393,7 @@ void update_flying(struct MarioState *m) {
}
u32 common_air_action_step(struct MarioState *m, u32 landAction, s32 animation, u32 stepArg) {
if (!m) { return 0; }
u32 stepResult;
update_air_without_turn(m);
@ -455,6 +471,7 @@ u32 common_air_action_step(struct MarioState *m, u32 landAction, s32 animation,
}
s32 act_jump(struct MarioState *m) {
if (!m) { return 0; }
if (check_kick_or_dive_in_air(m)) {
return TRUE;
}
@ -470,6 +487,7 @@ s32 act_jump(struct MarioState *m) {
}
s32 act_double_jump(struct MarioState *m) {
if (!m) { return 0; }
s32 animation = (m->vel[1] >= 0.0f)
? MARIO_ANIM_DOUBLE_JUMP_RISE
: MARIO_ANIM_DOUBLE_JUMP_FALL;
@ -489,6 +507,7 @@ s32 act_double_jump(struct MarioState *m) {
}
s32 act_triple_jump(struct MarioState *m) {
if (!m) { return 0; }
if (m == &gMarioStates[0] && m->specialTripleJump) {
return set_mario_action(m, ACT_SPECIAL_TRIPLE_JUMP, 0);
}
@ -516,6 +535,7 @@ s32 act_triple_jump(struct MarioState *m) {
}
s32 act_backflip(struct MarioState *m) {
if (!m) { return 0; }
if (m->input & INPUT_Z_PRESSED) {
return set_mario_action(m, ACT_GROUND_POUND, 0);
}
@ -531,6 +551,7 @@ s32 act_backflip(struct MarioState *m) {
}
s32 act_freefall(struct MarioState *m) {
if (!m) { return 0; }
s32 animation = 0;
if (m->input & INPUT_B_PRESSED) {
@ -558,6 +579,7 @@ s32 act_freefall(struct MarioState *m) {
}
s32 act_hold_jump(struct MarioState *m) {
if (!m) { return 0; }
if (m->marioObj->oInteractStatus & INT_STATUS_MARIO_DROP_OBJECT) {
return drop_and_set_mario_action(m, ACT_FREEFALL, 0);
}
@ -577,6 +599,7 @@ s32 act_hold_jump(struct MarioState *m) {
}
s32 act_hold_freefall(struct MarioState *m) {
if (!m) { return 0; }
s32 animation;
if (m->actionArg == 0) {
animation = MARIO_ANIM_FALL_WITH_LIGHT_OBJ;
@ -601,6 +624,7 @@ s32 act_hold_freefall(struct MarioState *m) {
}
s32 act_side_flip(struct MarioState *m) {
if (!m) { return 0; }
if (m->input & INPUT_B_PRESSED) {
return set_mario_action(m, ACT_DIVE, 0);
}
@ -624,6 +648,7 @@ s32 act_side_flip(struct MarioState *m) {
}
s32 act_wall_kick_air(struct MarioState *m) {
if (!m) { return 0; }
if (m->input & INPUT_B_PRESSED) {
return set_mario_action(m, ACT_DIVE, 0);
}
@ -638,6 +663,7 @@ s32 act_wall_kick_air(struct MarioState *m) {
}
s32 act_long_jump(struct MarioState *m) {
if (!m) { return 0; }
s32 animation;
if (!m->marioObj->oMarioLongJumpIsSlow) {
animation = MARIO_ANIM_FAST_LONGJUMP;
@ -661,6 +687,7 @@ s32 act_long_jump(struct MarioState *m) {
}
s32 act_riding_shell_air(struct MarioState *m) {
if (!m) { return 0; }
play_mario_sound(m, SOUND_ACTION_TERRAIN_JUMP, 0);
set_mario_animation(m, MARIO_ANIM_JUMP_RIDING_SHELL);
@ -685,6 +712,7 @@ s32 act_riding_shell_air(struct MarioState *m) {
}
s32 act_twirling(struct MarioState *m) {
if (!m) { return 0; }
s16 startTwirlYaw = m->twirlYaw;
s16 yawVelTarget;
@ -730,6 +758,7 @@ s32 act_twirling(struct MarioState *m) {
}
s32 act_dive(struct MarioState *m) {
if (!m) { return 0; }
if (m->actionArg == 0) {
play_mario_sound(m, SOUND_ACTION_THROW, CHAR_SOUND_HOOHOO);
} else {
@ -801,6 +830,7 @@ s32 act_dive(struct MarioState *m) {
}
s32 act_air_throw(struct MarioState *m) {
if (!m) { return 0; }
if (++(m->actionTimer) == 4) {
mario_throw_held_object(m);
}
@ -829,6 +859,7 @@ s32 act_air_throw(struct MarioState *m) {
}
s32 act_water_jump(struct MarioState *m) {
if (!m) { return 0; }
if (m->forwardVel < 15.0f) {
mario_set_forward_vel(m, 15.0f);
}
@ -863,6 +894,7 @@ s32 act_water_jump(struct MarioState *m) {
}
s32 act_hold_water_jump(struct MarioState *m) {
if (!m) { return 0; }
if (m->marioObj->oInteractStatus & INT_STATUS_MARIO_DROP_OBJECT) {
return drop_and_set_mario_action(m, ACT_FREEFALL, 0);
}
@ -893,6 +925,7 @@ s32 act_hold_water_jump(struct MarioState *m) {
}
s32 act_steep_jump(struct MarioState *m) {
if (!m) { return 0; }
if (m->input & INPUT_B_PRESSED) {
return set_mario_action(m, ACT_DIVE, 0);
}
@ -923,6 +956,7 @@ s32 act_steep_jump(struct MarioState *m) {
}
s32 act_ground_pound(struct MarioState *m) {
if (!m) { return 0; }
u32 stepResult;
f32 yOffset;
@ -989,6 +1023,7 @@ s32 act_ground_pound(struct MarioState *m) {
}
s32 act_burning_jump(struct MarioState *m) {
if (!m) { return 0; }
play_mario_sound(m, SOUND_ACTION_TERRAIN_JUMP, m->actionArg == 0 ? 0 : -1);
mario_set_forward_vel(m, m->forwardVel);
@ -1018,6 +1053,7 @@ s32 act_burning_jump(struct MarioState *m) {
}
s32 act_burning_fall(struct MarioState *m) {
if (!m) { return 0; }
mario_set_forward_vel(m, m->forwardVel);
if (perform_air_step(m, 0) == AIR_STEP_LANDED) {
@ -1044,6 +1080,7 @@ s32 act_burning_fall(struct MarioState *m) {
}
s32 act_crazy_box_bounce(struct MarioState *m) {
if (!m) { return 0; }
f32 minSpeed = 32;
if (m->actionTimer == 0) {
@ -1109,6 +1146,7 @@ s32 act_crazy_box_bounce(struct MarioState *m) {
u32 common_air_knockback_step(struct MarioState *m, u32 landAction, u32 hardFallAction, s32 animation,
f32 speed) {
if (!m) { return 0; }
u32 stepResult;
if (m->knockbackTimer == 0) {
@ -1162,6 +1200,7 @@ u32 common_air_knockback_step(struct MarioState *m, u32 landAction, u32 hardFall
}
s32 check_wall_kick(struct MarioState *m) {
if (!m) { return 0; }
if ((m->input & INPUT_A_PRESSED) && m->wallKickTimer != 0 && m->prevAction == ACT_AIR_HIT_WALL) {
m->faceAngle[1] += 0x8000;
return set_mario_action(m, ACT_WALL_KICK_AIR, 0);
@ -1220,6 +1259,7 @@ s32 act_hard_forward_air_kb(struct MarioState *m) {
}
s32 act_thrown_backward(struct MarioState *m) {
if (!m) { return 0; }
u32 landAction;
if (m->actionArg != 0) {
landAction = ACT_HARD_BACKWARD_GROUND_KB;
@ -1236,6 +1276,7 @@ s32 act_thrown_backward(struct MarioState *m) {
}
s32 act_thrown_forward(struct MarioState *m) {
if (!m) { return 0; }
s16 pitch;
u32 landAction;
@ -1277,6 +1318,7 @@ s32 act_soft_bonk(struct MarioState *m) {
}
s32 act_getting_blown(struct MarioState *m) {
if (!m) { return 0; }
if (m->actionState == 0) {
if (m->forwardVel > -60.0f) {
m->forwardVel -= 6.0f;
@ -1324,6 +1366,7 @@ s32 act_getting_blown(struct MarioState *m) {
}
s32 act_air_hit_wall(struct MarioState *m) {
if (!m) { return 0; }
if (m->heldObj != NULL) {
mario_drop_held_object(m);
}
@ -1368,6 +1411,7 @@ s32 act_air_hit_wall(struct MarioState *m) {
}
s32 act_forward_rollout(struct MarioState *m) {
if (!m) { return 0; }
if (m->actionState == 0) {
m->vel[1] = 30.0f;
m->actionState = 1;
@ -1409,6 +1453,7 @@ s32 act_forward_rollout(struct MarioState *m) {
}
s32 act_backward_rollout(struct MarioState *m) {
if (!m) { return 0; }
if (m->actionState == 0) {
m->vel[1] = 30.0f;
m->actionState = 1;
@ -1450,6 +1495,7 @@ s32 act_backward_rollout(struct MarioState *m) {
}
s32 act_butt_slide_air(struct MarioState *m) {
if (!m) { return 0; }
if (++(m->actionTimer) > 30 && m->pos[1] - m->floorHeight > 500.0f) {
return set_mario_action(m, ACT_FREEFALL, 1);
}
@ -1485,6 +1531,7 @@ s32 act_butt_slide_air(struct MarioState *m) {
}
s32 act_hold_butt_slide_air(struct MarioState *m) {
if (!m) { return 0; }
if (m->marioObj->oInteractStatus & INT_STATUS_MARIO_DROP_OBJECT) {
return drop_and_set_mario_action(m, ACT_HOLD_FREEFALL, 1);
}
@ -1526,6 +1573,7 @@ s32 act_hold_butt_slide_air(struct MarioState *m) {
}
s32 act_lava_boost(struct MarioState *m) {
if (!m) { return 0; }
if (!(m->flags & MARIO_MARIO_SOUND_PLAYED)) {
play_character_sound_if_no_flag(m, CHAR_SOUND_ON_FIRE, MARIO_MARIO_SOUND_PLAYED);
queue_rumble_data_mario(m, 5, 80);
@ -1606,6 +1654,7 @@ s32 act_lava_boost(struct MarioState *m) {
}
s32 act_slide_kick(struct MarioState *m) {
if (!m) { return 0; }
if (m->actionTimer == 0) {
play_mario_sound(m, SOUND_ACTION_TERRAIN_JUMP, CHAR_SOUND_HOOHOO);
set_mario_animation(m, MARIO_ANIM_SLIDE_KICK);
@ -1657,6 +1706,7 @@ s32 act_slide_kick(struct MarioState *m) {
}
s32 act_jump_kick(struct MarioState *m) {
if (!m) { return 0; }
s32 animFrame;
if (m->actionState == 0) {
@ -1692,6 +1742,7 @@ s32 act_jump_kick(struct MarioState *m) {
}
s32 act_shot_from_cannon(struct MarioState *m) {
if (!m) { return 0; }
// only allow for local player
u8 allowCameraChange = (m->playerIndex == 0);
@ -1776,6 +1827,7 @@ s32 act_shot_from_cannon(struct MarioState *m) {
}
s32 act_flying(struct MarioState *m) {
if (!m) { return 0; }
s16 startPitch = m->faceAngle[0];
if (m->input & INPUT_Z_PRESSED) {
@ -1961,6 +2013,7 @@ s32 act_flying(struct MarioState *m) {
}
s32 act_riding_hoot(struct MarioState *m) {
if (!m) { return 0; }
if (m->usedObj == NULL || m->usedObj->behavior != smlua_override_behavior(bhvHoot)) {
m->usedObj = cur_obj_nearest_object_with_behavior(bhvHoot);
if (m->usedObj == NULL) { return FALSE; }
@ -1999,6 +2052,7 @@ s32 act_riding_hoot(struct MarioState *m) {
}
s32 act_flying_triple_jump(struct MarioState *m) {
if (!m) { return 0; }
#ifndef VERSION_JP
if (m->input & (INPUT_B_PRESSED | INPUT_Z_PRESSED)) {
if (m->playerIndex == 0 && m->area->camera->mode == CAMERA_MODE_BEHIND_MARIO) {
@ -2105,6 +2159,7 @@ s32 act_top_of_pole_jump(struct MarioState *m) {
}
s32 act_vertical_wind(struct MarioState *m) {
if (!m) { return 0; }
s16 intendedDYaw = m->intendedYaw - m->faceAngle[1];
f32 intendedMag = m->intendedMag / 32.0f;
@ -2141,6 +2196,7 @@ s32 act_vertical_wind(struct MarioState *m) {
}
s32 act_special_triple_jump(struct MarioState *m) {
if (!m) { return 0; }
if (m->input & INPUT_B_PRESSED) {
return set_mario_action(m, ACT_DIVE, 0);
}
@ -2181,6 +2237,7 @@ s32 act_special_triple_jump(struct MarioState *m) {
}
s32 check_common_airborne_cancels(struct MarioState *m) {
if (!m) { return 0; }
if (m->pos[1] < m->waterLevel - 100) {
return set_water_plunge_action(m);
}
@ -2189,7 +2246,7 @@ s32 check_common_airborne_cancels(struct MarioState *m) {
return drop_and_set_mario_action(m, ACT_SQUISHED, 0);
}
if (m->floor->type == SURFACE_VERTICAL_WIND && (m->action & ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION)) {
if (m->floor && m->floor->type == SURFACE_VERTICAL_WIND && (m->action & ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION)) {
return drop_and_set_mario_action(m, ACT_VERTICAL_WIND, 0);
}

View file

@ -35,6 +35,7 @@
#define HANG_LEFT_CEIL 2
void add_tree_leaf_particles(struct MarioState *m) {
if (!m) { return; }
f32 leafHeight;
if (m->usedObj != NULL && m->usedObj->behavior == segmented_to_virtual(smlua_override_behavior(bhvTree))) {
@ -51,6 +52,7 @@ void add_tree_leaf_particles(struct MarioState *m) {
}
void play_climbing_sounds(struct MarioState *m, s32 b) {
if (!m) { return; }
s32 isOnTree = (m->usedObj != NULL && m->usedObj->behavior == segmented_to_virtual(smlua_override_behavior(bhvTree)));
if (b == 1) {
@ -65,6 +67,7 @@ void play_climbing_sounds(struct MarioState *m, s32 b) {
}
s32 set_pole_position(struct MarioState *m, f32 offsetY) {
if (!m) { return 0; }
if (m->usedObj == NULL) { m->usedObj = cur_obj_find_nearest_pole(); }
// This is here so if somehow a pole despawns while you are on it.
@ -132,6 +135,7 @@ s32 set_pole_position(struct MarioState *m, f32 offsetY) {
}
s32 act_holding_pole(struct MarioState *m) {
if (!m) { return 0; }
struct Object *marioObj = m->marioObj;
if (m->usedObj == NULL) { m->usedObj = cur_obj_find_nearest_pole(); }
if (m->usedObj == NULL) { return FALSE; }
@ -207,6 +211,7 @@ s32 act_holding_pole(struct MarioState *m) {
}
s32 act_climbing_pole(struct MarioState *m) {
if (!m) { return 0; }
if (m->usedObj == NULL) { m->usedObj = cur_obj_find_nearest_pole(); }
s32 sp24;
struct Object *marioObj = m->marioObj;
@ -245,6 +250,7 @@ s32 act_climbing_pole(struct MarioState *m) {
}
s32 act_grab_pole_slow(struct MarioState *m) {
if (!m) { return 0; }
if (m->usedObj == NULL) { m->usedObj = cur_obj_find_nearest_pole(); }
play_character_sound_if_no_flag(m, CHAR_SOUND_WHOA, MARIO_MARIO_SOUND_PLAYED);
@ -260,6 +266,7 @@ s32 act_grab_pole_slow(struct MarioState *m) {
}
s32 act_grab_pole_fast(struct MarioState *m) {
if (!m) { return 0; }
struct Object *marioObj = m->marioObj;
if (m->usedObj == NULL) { m->usedObj = cur_obj_find_nearest_pole(); }
@ -284,6 +291,7 @@ s32 act_grab_pole_fast(struct MarioState *m) {
}
s32 act_top_of_pole_transition(struct MarioState *m) {
if (!m) { return 0; }
struct Object *marioObj = m->marioObj;
if (m->usedObj == NULL) { m->usedObj = cur_obj_find_nearest_pole(); }
@ -305,6 +313,7 @@ s32 act_top_of_pole_transition(struct MarioState *m) {
}
s32 act_top_of_pole(struct MarioState *m) {
if (!m) { return 0; }
UNUSED struct Object *marioObj = m->marioObj;
if (m->usedObj == NULL) { m->usedObj = cur_obj_find_nearest_pole(); }
@ -380,8 +389,9 @@ s32 perform_hanging_step(struct MarioState *m, Vec3f nextPos) {
}
s32 update_hang_moving(struct MarioState *m) {
if (!m) { return 0; }
s32 stepResult;
Vec3f nextPos;
Vec3f nextPos = { 0 };
f32 maxSpeed = 4.0f;
m->forwardVel += 1.0f;
@ -400,9 +410,11 @@ s32 update_hang_moving(struct MarioState *m) {
m->vel[1] = 0.0f;
m->vel[2] = m->slideVelZ;
if (m->ceil) {
nextPos[0] = m->pos[0] - m->ceil->normal.y * m->vel[0];
nextPos[2] = m->pos[2] - m->ceil->normal.y * m->vel[2];
nextPos[1] = m->pos[1];
}
stepResult = perform_hanging_step(m, nextPos);
@ -412,6 +424,7 @@ s32 update_hang_moving(struct MarioState *m) {
}
void update_hang_stationary(struct MarioState *m) {
if (!m) { return; }
m->forwardVel = 0.0f;
m->slideVelX = 0.0f;
m->slideVelZ = 0.0f;
@ -422,6 +435,7 @@ void update_hang_stationary(struct MarioState *m) {
}
s32 act_start_hanging(struct MarioState *m) {
if (!m) { return 0; }
if (m->actionTimer++ == 0) {
queue_rumble_data_mario(m, 5, 80);
}
@ -454,6 +468,7 @@ s32 act_start_hanging(struct MarioState *m) {
}
s32 act_hanging(struct MarioState *m) {
if (!m) { return 0; }
if (m->input & INPUT_NONZERO_ANALOG) {
return set_mario_action(m, ACT_HANG_MOVING, m->actionArg);
}
@ -482,6 +497,7 @@ s32 act_hanging(struct MarioState *m) {
}
s32 act_hang_moving(struct MarioState *m) {
if (!m) { return 0; }
if (!(m->input & INPUT_A_DOWN)) {
return set_mario_action(m, ACT_FREEFALL, 0);
}
@ -520,6 +536,7 @@ s32 act_hang_moving(struct MarioState *m) {
}
s32 let_go_of_ledge(struct MarioState *m) {
if (!m) { return 0; }
f32 floorHeight;
struct Surface *floor;
@ -539,6 +556,7 @@ s32 let_go_of_ledge(struct MarioState *m) {
}
void climb_up_ledge(struct MarioState *m) {
if (!m) { return; }
set_mario_animation(m, MARIO_ANIM_IDLE_HEAD_LEFT);
m->pos[0] += 14.0f * sins(m->faceAngle[1]);
m->pos[2] += 14.0f * coss(m->faceAngle[1]);
@ -546,6 +564,7 @@ void climb_up_ledge(struct MarioState *m) {
}
void update_ledge_climb_camera(struct MarioState *m) {
if (!m) { return; }
f32 sp4;
if (m->actionTimer < 14) {
@ -573,6 +592,7 @@ void update_ledge_climb(struct MarioState *m, s32 animation, u32 endAction) {
}
s32 act_ledge_grab(struct MarioState *m) {
if (!m) { return 0; }
f32 heightAboveFloor;
s16 intendedDYaw = m->intendedYaw - m->faceAngle[1];
s32 hasSpaceForMario = (m->ceilHeight - m->floorHeight >= 160.0f);
@ -631,6 +651,7 @@ s32 act_ledge_grab(struct MarioState *m) {
}
s32 act_ledge_climb_slow(struct MarioState *m) {
if (!m) { return 0; }
if (m->input & INPUT_OFF_FLOOR) {
return let_go_of_ledge(m);
}
@ -657,6 +678,7 @@ s32 act_ledge_climb_slow(struct MarioState *m) {
}
s32 act_ledge_climb_down(struct MarioState *m) {
if (!m) { return 0; }
if (m->input & INPUT_OFF_FLOOR) {
return let_go_of_ledge(m);
}
@ -670,6 +692,7 @@ s32 act_ledge_climb_down(struct MarioState *m) {
}
s32 act_ledge_climb_fast(struct MarioState *m) {
if (!m) { return 0; }
if (m->input & INPUT_OFF_FLOOR) {
return let_go_of_ledge(m);
}
@ -687,6 +710,7 @@ s32 act_ledge_climb_fast(struct MarioState *m) {
}
s32 act_grabbed(struct MarioState *m) {
if (!m) { return 0; }
if (m->marioObj->oInteractStatus & INT_STATUS_MARIO_UNK2) {
s32 thrown = (m->marioObj->oInteractStatus & INT_STATUS_MARIO_UNK6) == 0;
@ -728,6 +752,7 @@ s32 act_grabbed(struct MarioState *m) {
}
s32 act_in_cannon(struct MarioState *m) {
if (!m) { return 0; }
struct Object *marioObj = m->marioObj;
s16 startFacePitch = m->faceAngle[0];
s16 startFaceYaw = m->faceAngle[1];
@ -822,6 +847,7 @@ s32 act_in_cannon(struct MarioState *m) {
}
s32 act_tornado_twirling(struct MarioState *m) {
if (!m) { return 0; }
if (m->usedObj == NULL) { return FALSE; }
struct Surface *floor;
@ -904,6 +930,7 @@ s32 act_tornado_twirling(struct MarioState *m) {
static void bubbled_offset_visual(struct MarioState* m) {
if (!m) { return; }
// scary 3d trig ahead
f32 forwardOffset = 25;
@ -941,6 +968,7 @@ static void bubbled_offset_visual(struct MarioState* m) {
}
s32 act_bubbled(struct MarioState* m) {
if (!m) { return 0; }
if (m->playerIndex == 0 && m->area->camera->mode == CAMERA_MODE_WATER_SURFACE) {
set_camera_mode(m->area->camera, CAMERA_MODE_FREE_ROAM, 1);
}
@ -1068,6 +1096,7 @@ s32 act_bubbled(struct MarioState* m) {
}
s32 check_common_automatic_cancels(struct MarioState *m) {
if (!m) { return 0; }
if (m->pos[1] < m->waterLevel - 100) {
return set_water_plunge_action(m);
}
@ -1076,6 +1105,7 @@ s32 check_common_automatic_cancels(struct MarioState *m) {
}
s32 mario_execute_automatic_action(struct MarioState *m) {
if (!m) { return 0; }
if (!m) { return FALSE; }
s32 cancel;

View file

@ -195,6 +195,7 @@ void bhv_end_peach_loop(void) {
}
void bhv_end_toad_loop(void) {
if (!gCurrentObject) { return; }
s32 toadAnimIndex = (gCurrentObject->oPosX >= 0.0f);
cur_obj_init_animation_with_sound(sEndToadAnims[toadAnimIndex]);
@ -435,7 +436,7 @@ s32 set_mario_npc_dialog(struct MarioState* m, s32 actionArg, u8 (*inContinueDia
// 9 - 22: looking away from npc
// 23: end
s32 act_reading_npc_dialog(struct MarioState *m) {
if (!m) { return 23; }
if (!m || !gCurrentObject) { return 23; }
s32 headTurnAmount = 0;
s16 angleToNPC;
@ -759,6 +760,7 @@ void general_star_dance_handler(struct MarioState *m, s32 isInWater) {
}
s32 act_star_dance(struct MarioState *m) {
if (!m) { return 0; }
if (m == &gMarioStates[0]) {
m->faceAngle[1] = m->area->camera->yaw;
}
@ -772,6 +774,7 @@ s32 act_star_dance(struct MarioState *m) {
}
s32 act_star_dance_water(struct MarioState *m) {
if (!m) { return 0; }
if (m == &gMarioStates[0]) {
m->faceAngle[1] = m->area->camera->yaw;
}
@ -786,6 +789,7 @@ s32 act_star_dance_water(struct MarioState *m) {
}
s32 act_fall_after_star_grab(struct MarioState *m) {
if (!m) { return 0; }
if (m->pos[1] < m->waterLevel - 130) {
play_sound(SOUND_ACTION_UNKNOWN430, m->marioObj->header.gfx.cameraToObject);
set_mario_particle_flags(m, PARTICLE_WATER_SPLASH, FALSE);
@ -800,6 +804,7 @@ s32 act_fall_after_star_grab(struct MarioState *m) {
}
s32 common_death_handler(struct MarioState *m, s32 animation, s32 frameToDeathWarp) {
if (!m) { return 0; }
s32 animFrame = set_mario_animation(m, animation);
if (animFrame == frameToDeathWarp) {
if (m->playerIndex != 0) {
@ -822,6 +827,7 @@ s32 common_death_handler(struct MarioState *m, s32 animation, s32 frameToDeathWa
}
s32 act_standing_death(struct MarioState *m) {
if (!m) { return 0; }
if (m->input & INPUT_IN_POISON_GAS) {
return set_mario_action(m, ACT_SUFFOCATION, 0);
}
@ -863,6 +869,7 @@ s32 act_death_on_stomach(struct MarioState *m) {
}
s32 act_quicksand_death(struct MarioState *m) {
if (!m) { return 0; }
if (m->actionState == 0) {
set_mario_animation(m, MARIO_ANIM_DYING_IN_QUICKSAND);
set_anim_to_frame(m, 60);
@ -895,6 +902,7 @@ s32 act_quicksand_death(struct MarioState *m) {
}
s32 act_eaten_by_bubba(struct MarioState *m) {
if (!m) { return 0; }
play_character_sound_if_no_flag(m, CHAR_SOUND_DYING, MARIO_ACTION_SOUND_PLAYED);
set_mario_animation(m, MARIO_ANIM_A_POSE);
@ -932,6 +940,7 @@ s32 launch_mario_until_land(struct MarioState *m, s32 endAction, s32 animation,
}
s32 act_unlocking_key_door(struct MarioState *m) {
if (!m) { return 0; }
if (m->usedObj != NULL) {
m->faceAngle[1] = m->usedObj->oMoveAngleYaw;
@ -943,7 +952,7 @@ s32 act_unlocking_key_door(struct MarioState *m) {
m->faceAngle[1] += 0x8000;
}
if ((m->actionTimer == 0) || (m->playerIndex != 0 && gCurrentObject->header.gfx.animInfo.animID == -1)) {
if ((m->actionTimer == 0) || (m->playerIndex != 0 && gCurrentObject && gCurrentObject->header.gfx.animInfo.animID == -1)) {
spawn_obj_at_mario_rel_yaw(m, MODEL_BOWSER_KEY_CUTSCENE, bhvBowserKeyUnlockDoor, 0);
set_mario_animation(m, MARIO_ANIM_UNLOCK_DOOR);
}
@ -976,6 +985,7 @@ s32 act_unlocking_key_door(struct MarioState *m) {
}
s32 act_unlocking_star_door(struct MarioState *m) {
if (!m) { return 0; }
static u8 allowRemoteStarSpawn = TRUE;
switch (m->actionState) {
case 0:
@ -1025,6 +1035,7 @@ s32 act_unlocking_star_door(struct MarioState *m) {
}
s32 act_entering_star_door(struct MarioState *m) {
if (!m) { return 0; }
f32 targetDX = 0;
f32 targetDZ = 0;
s16 targetAngle = 0;
@ -1087,6 +1098,7 @@ s32 act_entering_star_door(struct MarioState *m) {
}
s32 act_going_through_door(struct MarioState *m) {
if (!m) { return 0; }
if (m->actionTimer == 0) {
if (m->actionArg & 1) {
if (m->interactObj != NULL) {
@ -1125,6 +1137,7 @@ s32 act_going_through_door(struct MarioState *m) {
}
s32 act_warp_door_spawn(struct MarioState *m) {
if (!m) { return 0; }
if (m->actionState == 0) {
m->actionState = 1;
if (m->usedObj != NULL) {
@ -1149,6 +1162,7 @@ s32 act_warp_door_spawn(struct MarioState *m) {
}
static s32 launch_mario_until_land_no_collision(struct MarioState *m, s32 endAction, s32 animation, f32 forwardVel) {
if (!m) { return 0; }
mario_set_forward_vel(m, forwardVel);
set_mario_animation(m, animation);
m->pos[0] += m->vel[0];
@ -1170,6 +1184,7 @@ static s32 launch_mario_until_land_no_collision(struct MarioState *m, s32 endAct
}
s32 act_emerge_from_pipe(struct MarioState *m) {
if (!m) { return 0; }
struct Object *marioObj = m->marioObj;
if (m->actionTimer++ < 11) {
@ -1207,6 +1222,7 @@ s32 act_emerge_from_pipe(struct MarioState *m) {
}
s32 act_spawn_spin_airborne(struct MarioState *m) {
if (!m) { return 0; }
// entered water, exit action
if (m->pos[1] < m->waterLevel - 100) {
if (m == &gMarioStates[0]) {
@ -1260,6 +1276,7 @@ s32 act_spawn_spin_landing(struct MarioState *m) {
* particle flag that generates sparkles.
*/
s32 act_exit_airborne(struct MarioState *m) {
if (!m) { return 0; }
if (15 < m->actionTimer++
&& launch_mario_until_land(m, ACT_EXIT_LAND_SAVE_DIALOG, MARIO_ANIM_GENERAL_FALL, -32.0f)) {
// heal Mario
@ -1272,6 +1289,7 @@ s32 act_exit_airborne(struct MarioState *m) {
}
s32 act_falling_exit_airborne(struct MarioState *m) {
if (!m) { return 0; }
if (launch_mario_until_land(m, ACT_EXIT_LAND_SAVE_DIALOG, MARIO_ANIM_GENERAL_FALL, 0.0f)) {
// heal Mario
m->healCounter = 31;
@ -1283,6 +1301,7 @@ s32 act_falling_exit_airborne(struct MarioState *m) {
}
s32 act_exit_land_save_dialog(struct MarioState *m) {
if (!m) { return 0; }
s32 animFrame;
stationary_ground_step(m);
play_mario_landing_sound_once(m, SOUND_ACTION_TERRAIN_LANDING);
@ -1368,6 +1387,7 @@ s32 act_exit_land_save_dialog(struct MarioState *m) {
}
s32 act_death_exit(struct MarioState *m) {
if (!m) { return 0; }
if (15 < m->actionTimer++
&& launch_mario_until_land(m, ACT_DEATH_EXIT_LAND, MARIO_ANIM_GENERAL_FALL, -32.0f)) {
#ifdef VERSION_JP
@ -1385,6 +1405,7 @@ s32 act_death_exit(struct MarioState *m) {
}
s32 act_unused_death_exit(struct MarioState *m) {
if (!m) { return 0; }
if (launch_mario_until_land(m, ACT_FREEFALL_LAND_STOP, MARIO_ANIM_GENERAL_FALL, 0.0f)) {
#ifdef VERSION_JP
play_character_sound(m, CHAR_SOUND_OOOF);
@ -1400,6 +1421,7 @@ s32 act_unused_death_exit(struct MarioState *m) {
}
s32 act_falling_death_exit(struct MarioState *m) {
if (!m) { return 0; }
if (launch_mario_until_land(m, ACT_DEATH_EXIT_LAND, MARIO_ANIM_GENERAL_FALL, 0.0f)) {
#ifdef VERSION_JP
play_character_sound(m, CHAR_SOUND_OOOF);
@ -1417,6 +1439,7 @@ s32 act_falling_death_exit(struct MarioState *m) {
// waits 11 frames before actually executing, also has reduced fvel
s32 act_special_exit_airborne(struct MarioState *m) {
if (!m) { return 0; }
struct Object *marioObj = m->marioObj;
play_character_sound_if_no_flag(m, CHAR_SOUND_YAHOO, MARIO_MARIO_SOUND_PLAYED);
@ -1442,6 +1465,7 @@ s32 act_special_exit_airborne(struct MarioState *m) {
}
s32 act_special_death_exit(struct MarioState *m) {
if (!m) { return 0; }
struct Object *marioObj = m->marioObj;
if (m->actionTimer++ < 11) {
@ -1462,6 +1486,7 @@ s32 act_special_death_exit(struct MarioState *m) {
}
s32 act_spawn_no_spin_airborne(struct MarioState *m) {
if (!m) { return 0; }
launch_mario_until_land(m, ACT_SPAWN_NO_SPIN_LANDING, MARIO_ANIM_GENERAL_FALL, 0.0f);
if (m->pos[1] < m->waterLevel - 100) {
set_water_plunge_action(m);
@ -1483,6 +1508,7 @@ s32 act_spawn_no_spin_landing(struct MarioState *m) {
}
s32 act_bbh_enter_spin(struct MarioState *m) {
if (!m) { return 0; }
f32 cageDX = 0.0f;
f32 cageDZ = 0.0f;
f32 forwardVel = 0.0f;
@ -1569,6 +1595,7 @@ s32 act_bbh_enter_spin(struct MarioState *m) {
}
s32 act_bbh_enter_jump(struct MarioState *m) {
if (!m) { return 0; }
play_mario_action_sound(m, m->flags & MARIO_METAL_CAP ? SOUND_ACTION_METAL_JUMP : SOUND_ACTION_TERRAIN_JUMP, 1);
play_mario_jump_sound(m);
@ -1600,6 +1627,7 @@ s32 act_bbh_enter_jump(struct MarioState *m) {
}
s32 act_teleport_fade_out(struct MarioState *m) {
if (!m) { return 0; }
play_sound_if_no_flag(m, SOUND_ACTION_TELEPORT, MARIO_ACTION_SOUND_PLAYED);
set_mario_animation(m, m->prevAction == ACT_CROUCHING ? MARIO_ANIM_CROUCHING : MARIO_ANIM_FIRST_PERSON);
@ -1629,6 +1657,7 @@ s32 act_teleport_fade_out(struct MarioState *m) {
}
s32 act_teleport_fade_in(struct MarioState *m) {
if (!m) { return 0; }
play_sound_if_no_flag(m, SOUND_ACTION_TELEPORT, MARIO_ACTION_SOUND_PLAYED);
set_mario_animation(m, MARIO_ANIM_FIRST_PERSON);
@ -1664,6 +1693,7 @@ s32 act_teleport_fade_in(struct MarioState *m) {
}
s32 act_shocked(struct MarioState *m) {
if (!m) { return 0; }
play_character_sound_if_no_flag(m, CHAR_SOUND_WAAAOOOW, MARIO_MARIO_SOUND_PLAYED);
play_sound(SOUND_MOVING_SHOCKED, m->marioObj->header.gfx.cameraToObject);
if (m->playerIndex == 0) { set_camera_shake_from_hit(SHAKE_SHOCK); }
@ -1880,12 +1910,14 @@ s32 act_feet_stuck_in_ground(struct MarioState *m) {
* for keeping track of what step of the cutscene Mario is in.)
*/
static void advance_cutscene_step(struct MarioState *m) {
if (!m) { return; }
m->actionState = 0;
m->actionTimer = 0;
m->actionArg++;
}
static void intro_cutscene_hide_hud_and_mario(struct MarioState *m) {
if (!m) { return; }
gHudDisplay.flags = HUD_DISPLAY_NONE;
m->statusForCamera->cameraEvent = CAM_EVENT_START_INTRO;
m->marioObj->header.gfx.node.flags &= ~GRAPH_RENDER_ACTIVE;
@ -1900,6 +1932,7 @@ static void intro_cutscene_hide_hud_and_mario(struct MarioState *m) {
#endif
static void intro_cutscene_peach_lakitu_scene(struct MarioState *m) {
if (!m) { return; }
if ((s16) m->statusForCamera->cameraEvent != CAM_EVENT_START_INTRO) {
if (m->actionTimer++ == TIMER_SPAWN_PIPE) {
u8 globalIndex = gNetworkPlayers[m->playerIndex].globalIndex;
@ -1921,6 +1954,7 @@ static void intro_cutscene_peach_lakitu_scene(struct MarioState *m) {
#endif
static void intro_cutscene_raise_pipe(struct MarioState* m) {
if (!m) { return; }
u8 globalIndex = gNetworkPlayers[m->playerIndex].globalIndex;
if (globalIndex == UNKNOWN_GLOBAL_INDEX) { globalIndex = 0; }
@ -1939,6 +1973,7 @@ static void intro_cutscene_raise_pipe(struct MarioState* m) {
}
static void intro_cutscene_raise_pipe_main_menu(struct MarioState* m) {
if (!m) { return; }
u8 globalIndex = gNetworkPlayers[m->playerIndex].globalIndex;
if (globalIndex == UNKNOWN_GLOBAL_INDEX) { globalIndex = 0; }
if (sIntroWarpPipeObj[globalIndex] == NULL) {
@ -1958,6 +1993,7 @@ static void intro_cutscene_raise_pipe_main_menu(struct MarioState* m) {
#undef TIMER_RAISE_PIPE
static void intro_cutscene_jump_out_of_pipe(struct MarioState *m) {
if (!m) { return; }
if (m->actionTimer <= 1) {
u8 globalIndex = gNetworkPlayers[m->playerIndex].globalIndex;
if (globalIndex == UNKNOWN_GLOBAL_INDEX) { globalIndex = 0; }
@ -2010,6 +2046,7 @@ static void intro_cutscene_land_outside_pipe(struct MarioState *m) {
}
static void intro_cutscene_lower_pipe(struct MarioState *m) {
if (!m) { return; }
u8 globalIndex = gNetworkPlayers[m->playerIndex].globalIndex;
if (globalIndex == UNKNOWN_GLOBAL_INDEX) { globalIndex = 0; }
if (m->actionTimer++ == 0) {
@ -2033,6 +2070,7 @@ static void intro_cutscene_lower_pipe(struct MarioState *m) {
}
static void intro_cutscene_set_mario_to_idle(struct MarioState *m) {
if (!m || !gCamera) { return; }
if (gCamera->cutscene == 0) {
if (m->playerIndex == 0) {
gCameraMovementFlags &= ~CAM_MOVE_C_UP_MODE;
@ -2055,6 +2093,7 @@ enum {
};
static s32 act_intro_cutscene(struct MarioState *m) {
if (!m) { return 0; }
switch (m->actionArg) {
case INTRO_CUTSCENE_HIDE_HUD_AND_MARIO:
intro_cutscene_hide_hud_and_mario(m);
@ -2085,12 +2124,14 @@ static s32 act_intro_cutscene(struct MarioState *m) {
}
static void jumbo_star_offset(struct MarioState* m) {
if (!m) { return; }
m->pos[0] += 300.0f * sins(m->faceAngle[1] + 0x4000 * m->playerIndex);
m->pos[2] += 300.0f * coss(m->faceAngle[1] + 0x4000 * m->playerIndex);
}
// jumbo star cutscene: Mario lands after grabbing the jumbo star
static void jumbo_star_cutscene_falling(struct MarioState *m) {
if (!m) { return; }
if (m->actionState == 0) {
m->input |= INPUT_A_DOWN;
m->flags |= (MARIO_WING_CAP | MARIO_CAP_ON_HEAD);
@ -2118,6 +2159,7 @@ static void jumbo_star_cutscene_falling(struct MarioState *m) {
// jumbo star cutscene: Mario takes off
static s32 jumbo_star_cutscene_taking_off(struct MarioState *m) {
if (!m) { return 0; }
struct Object *marioObj = m->marioObj;
if (m->actionState == 0) {
@ -2171,6 +2213,7 @@ static s32 jumbo_star_cutscene_taking_off(struct MarioState *m) {
// jumbo star cutscene: Mario flying
static s32 jumbo_star_cutscene_flying(struct MarioState *m) {
if (!m) { return 0; }
Vec3f targetPos;
switch (m->actionState) {
@ -2221,6 +2264,7 @@ static s32 jumbo_star_cutscene_flying(struct MarioState *m) {
enum { JUMBO_STAR_CUTSCENE_FALLING, JUMBO_STAR_CUTSCENE_TAKING_OFF, JUMBO_STAR_CUTSCENE_FLYING };
static s32 act_jumbo_star_cutscene(struct MarioState *m) {
if (!m) { return 0; }
switch (m->actionArg) {
case JUMBO_STAR_CUTSCENE_FALLING:
jumbo_star_cutscene_falling(m);
@ -2275,6 +2319,7 @@ static f32 end_obj_set_visual_pos(struct Object *o) {
// make Mario fall and soften wing cap gravity
static void end_peach_cutscene_mario_falling(struct MarioState *m) {
if (!m) { return; }
if (m->actionTimer == 1) {
m->statusForCamera->cameraEvent = CAM_EVENT_START_ENDING;
}
@ -2293,6 +2338,7 @@ static void end_peach_cutscene_mario_falling(struct MarioState *m) {
// set Mario on the ground, wait and spawn the jumbo star outside the castle.
static void end_peach_cutscene_mario_landing(struct MarioState *m) {
if (!m) { return; }
set_mario_animation(m, MARIO_ANIM_GENERAL_LAND);
stop_and_set_height_to_floor(m);
@ -2313,6 +2359,7 @@ static void end_peach_cutscene_mario_landing(struct MarioState *m) {
// raise hand animation, lower hand animation, do some special effects
static void end_peach_cutscene_summon_jumbo_star(struct MarioState *m) {
if (!m) { return; }
set_mario_animation(m, m->actionState == 0 ? MARIO_ANIM_CREDITS_RAISE_HAND
: MARIO_ANIM_CREDITS_LOWER_HAND);
if (m->playerIndex != 0) { return; }
@ -2348,6 +2395,7 @@ static void end_peach_cutscene_summon_jumbo_star(struct MarioState *m) {
// free peach from the stained glass window
static void end_peach_cutscene_spawn_peach(struct MarioState *m) {
if (!m) { return; }
if (m->playerIndex != 0) { return; }
if (m->actionTimer == 1) {
play_transition(WARP_TRANSITION_FADE_INTO_COLOR, 14, 255, 255, 255);
@ -2407,6 +2455,7 @@ static void end_peach_cutscene_spawn_peach(struct MarioState *m) {
// descend peach
static void end_peach_cutscene_descend_peach(struct MarioState *m) {
if (!m) { return; }
if (m->playerIndex != 0) { return; }
generate_yellow_sparkles(0, sEndPeachObj->oPosY, -1300, 150.0f);
@ -2436,6 +2485,7 @@ static void end_peach_cutscene_descend_peach(struct MarioState *m) {
// Mario runs to peach
static void end_peach_cutscene_run_to_peach(struct MarioState *m) {
if (!m) { return; }
struct Surface *surf;
if (m->actionTimer == 22) {
@ -2460,6 +2510,7 @@ static void end_peach_cutscene_run_to_peach(struct MarioState *m) {
// "Mario!"
// "The power of the Stars is restored to the castle..."
static void end_peach_cutscene_dialog_1(struct MarioState *m) {
if (!m) { return; }
s32 animFrame = set_mario_animation(m, m->actionState == 0 ? MARIO_ANIM_CREDITS_TAKE_OFF_CAP
: MARIO_ANIM_CREDITS_LOOK_UP);
@ -2569,6 +2620,7 @@ static void end_peach_cutscene_dialog_1(struct MarioState *m) {
// "Thank you Mario!"
// "We have to do something special for you..."
static void end_peach_cutscene_dialog_2(struct MarioState *m) {
if (!m) { return; }
if (m->playerIndex != 0) { return; }
sEndPeachAnimation = 9;
@ -2629,6 +2681,7 @@ static u8 sMarioBlinkOverride[20] = {
};
static void end_peach_cutscene_kiss_from_peach(struct MarioState *m) {
if (!m) { return; }
sEndPeachAnimation = 10;
if (m->actionTimer >= 90) {
@ -2672,6 +2725,7 @@ static void end_peach_cutscene_kiss_from_peach(struct MarioState *m) {
}
static void end_peach_cutscene_star_dance(struct MarioState *m) {
if (!m) { return; }
u8 nonMario = (gNetworkPlayers[m->playerIndex].globalIndex != 0);
s32 animFrame = set_mario_animation(m, nonMario ? MARIO_ANIM_START_SLEEP_SITTING : MARIO_ANIM_CREDITS_PEACE_SIGN);
@ -2726,6 +2780,7 @@ static void end_peach_cutscene_star_dance(struct MarioState *m) {
// "let's bake a delicious cake..."
// "...for Mario..."
static void end_peach_cutscene_dialog_3(struct MarioState *m) {
if (!m) { return; }
u8 nonMario = (gNetworkPlayers[m->playerIndex].globalIndex != 0);
set_mario_animation(m, nonMario ? MARIO_ANIM_SLEEP_IDLE : MARIO_ANIM_FIRST_PERSON);
if (m->playerIndex != 0) { return; }
@ -2764,6 +2819,7 @@ static void end_peach_cutscene_dialog_3(struct MarioState *m) {
// "Mario!"
static void end_peach_cutscene_run_to_castle(struct MarioState *m) {
if (!m) { return; }
u8 nonMario = (gNetworkPlayers[m->playerIndex].globalIndex != 0);
if (nonMario) {
set_mario_animation(m, m->actionState == 0 ? MARIO_ANIM_SLEEP_START_LYING
@ -2790,6 +2846,7 @@ static void end_peach_cutscene_run_to_castle(struct MarioState *m) {
}
static void end_peach_cutscene_fade_out(struct MarioState *m) {
if (!m) { return; }
if (m->actionState == 0 && m->playerIndex == 0) {
level_trigger_warp(m, WARP_OP_CREDITS_NEXT);
gPaintingMarioYEntry = 1500.0f; // ensure medium water level in WDW credits cutscene
@ -2814,6 +2871,7 @@ enum {
};
static s32 act_end_peach_cutscene(struct MarioState *m) {
if (!m) { return 0; }
switch (m->actionArg) {
case END_PEACH_CUTSCENE_MARIO_FALLING:
end_peach_cutscene_mario_falling(m);
@ -2887,6 +2945,7 @@ static s32 act_end_peach_cutscene(struct MarioState *m) {
#endif
static s32 act_credits_cutscene(struct MarioState *m) {
if (!m) { return 0; }
m->statusForCamera->cameraEvent = CAM_EVENT_START_CREDITS;
// checks if Mario is underwater (JRB, DDD, SA, etc.)
if (m->pos[1] < m->waterLevel - 100) {
@ -2944,6 +3003,7 @@ static s32 act_credits_cutscene(struct MarioState *m) {
}
static s32 act_end_waving_cutscene(struct MarioState *m) {
if (!m) { return 0; }
if (m->actionState == 0) {
m->statusForCamera->cameraEvent = CAM_EVENT_START_END_WAVING;
@ -2982,6 +3042,7 @@ static s32 act_end_waving_cutscene(struct MarioState *m) {
}
static s32 check_for_instant_quicksand(struct MarioState *m) {
if (!m) { return 0; }
if (m != &gMarioStates[0]) {
// never kill remote marios
return FALSE;

View file

@ -31,6 +31,7 @@ void animated_stationary_ground_step(struct MarioState *m, s32 animation, u32 en
}
s32 mario_update_punch_sequence(struct MarioState *m) {
if (!m) { return 0; }
u32 endAction, crouchEndAction;
s32 animFrame;
@ -151,6 +152,7 @@ s32 mario_update_punch_sequence(struct MarioState *m) {
}
s32 act_punching(struct MarioState *m) {
if (!m) { return 0; }
if (m->input & INPUT_UNKNOWN_10) {
return drop_and_set_mario_action(m, ACT_SHOCKWAVE_BOUNCE, 0);
}
@ -179,6 +181,7 @@ s32 act_punching(struct MarioState *m) {
}
s32 act_picking_up(struct MarioState *m) {
if (!m) { return 0; }
if (m->input & INPUT_UNKNOWN_10) {
return drop_and_set_mario_action(m, ACT_SHOCKWAVE_BOUNCE, 0);
}
@ -222,6 +225,7 @@ s32 act_picking_up(struct MarioState *m) {
}
s32 act_dive_picking_up(struct MarioState *m) {
if (!m) { return 0; }
if (m->input & INPUT_UNKNOWN_10) {
return drop_and_set_mario_action(m, ACT_SHOCKWAVE_BOUNCE, 0);
}
@ -242,6 +246,7 @@ s32 act_dive_picking_up(struct MarioState *m) {
}
s32 act_placing_down(struct MarioState *m) {
if (!m) { return 0; }
if (m->input & INPUT_UNKNOWN_10) {
return drop_and_set_mario_action(m, ACT_SHOCKWAVE_BOUNCE, 0);
}
@ -259,6 +264,7 @@ s32 act_placing_down(struct MarioState *m) {
}
s32 act_throwing(struct MarioState *m) {
if (!m) { return 0; }
if (m->heldObj && (m->heldObj->oInteractionSubtype & INT_SUBTYPE_HOLDABLE_NPC)) {
return set_mario_action(m, ACT_PLACING_DOWN, 0);
}
@ -283,6 +289,7 @@ s32 act_throwing(struct MarioState *m) {
}
s32 act_heavy_throw(struct MarioState *m) {
if (!m) { return 0; }
if (m->input & INPUT_UNKNOWN_10) {
return drop_and_set_mario_action(m, ACT_SHOCKWAVE_BOUNCE, 0);
}
@ -303,6 +310,7 @@ s32 act_heavy_throw(struct MarioState *m) {
}
s32 act_stomach_slide_stop(struct MarioState *m) {
if (!m) { return 0; }
if (m->input & INPUT_UNKNOWN_10) {
return set_mario_action(m, ACT_SHOCKWAVE_BOUNCE, 0);
}
@ -320,6 +328,7 @@ s32 act_stomach_slide_stop(struct MarioState *m) {
}
s32 act_picking_up_bowser(struct MarioState *m) {
if (!m) { return 0; }
if (m->playerIndex != 0) {
m->usedObj = cur_obj_nearest_object_with_behavior(bhvBowser);
}
@ -350,6 +359,7 @@ s32 act_picking_up_bowser(struct MarioState *m) {
}
s32 act_holding_bowser(struct MarioState *m) {
if (!m) { return 0; }
if (m->playerIndex != 0) {
if (m->marioBodyState->grabPos != GRAB_POS_BOWSER) {
m->usedObj = cur_obj_nearest_object_with_behavior(bhvBowser);
@ -448,6 +458,7 @@ s32 act_holding_bowser(struct MarioState *m) {
}
s32 act_releasing_bowser(struct MarioState *m) {
if (!m) { return 0; }
if (++m->actionTimer == 1 && m->playerIndex == 0) {
if (m->actionArg == 0) {
queue_rumble_data_mario(m, 5, 50);
@ -464,6 +475,7 @@ s32 act_releasing_bowser(struct MarioState *m) {
}
s32 check_common_object_cancels(struct MarioState *m) {
if (!m) { return 0; }
if (m->playerIndex != 0) { return FALSE; }
f32 waterSurface = m->waterLevel - 100;

View file

@ -23,6 +23,7 @@
#include "hardcoded.h"
s32 check_common_idle_cancels(struct MarioState *m) {
if (!m) { return 0; }
mario_drop_held_object(m);
if (m->floor->normal.y < 0.29237169f) {
return mario_push_off_steep_floor(m, ACT_FREEFALL, 0);
@ -65,7 +66,8 @@ s32 check_common_idle_cancels(struct MarioState *m) {
}
s32 check_common_hold_idle_cancels(struct MarioState *m) {
if (m->floor->normal.y < 0.29237169f) {
if (!m) { return 0; }
if (m->floor && m->floor->normal.y < 0.29237169f) {
return mario_push_off_steep_floor(m, ACT_HOLD_FREEFALL, 0);
}
@ -108,6 +110,7 @@ s32 check_common_hold_idle_cancels(struct MarioState *m) {
}
s32 act_idle(struct MarioState *m) {
if (!m) { return 0; }
if (m->quicksandDepth > 30.0f) {
return set_mario_action(m, ACT_IN_QUICKSAND, 0);
}
@ -184,12 +187,14 @@ s32 act_idle(struct MarioState *m) {
}
void play_anim_sound(struct MarioState *m, u32 actionState, s32 animFrame, u32 sound) {
if (!m) { return; }
if (m->actionState == actionState && m->marioObj->header.gfx.animInfo.animFrame == animFrame) {
play_sound(sound, m->marioObj->header.gfx.cameraToObject);
}
}
s32 act_start_sleeping(struct MarioState *m) {
if (!m) { return 0; }
#ifndef VERSION_JP
s32 animFrame = 0;
#endif
@ -265,6 +270,7 @@ s32 act_start_sleeping(struct MarioState *m) {
}
s32 act_sleeping(struct MarioState *m) {
if (!m) { return 0; }
s32 animFrame;
if (m->playerIndex == 0) {
if (m->input
@ -342,6 +348,7 @@ s32 act_sleeping(struct MarioState *m) {
}
s32 act_waking_up(struct MarioState *m) {
if (!m) { return 0; }
if (!m->actionTimer) {
stop_sound(get_character(m)->soundSnoring1, m->marioObj->header.gfx.cameraToObject);
stop_sound(get_character(m)->soundSnoring2, m->marioObj->header.gfx.cameraToObject);
@ -379,6 +386,7 @@ s32 act_waking_up(struct MarioState *m) {
}
s32 act_shivering(struct MarioState *m) {
if (!m) { return 0; }
s32 animFrame;
if (m->input & INPUT_UNKNOWN_10) {
@ -433,6 +441,7 @@ s32 act_shivering(struct MarioState *m) {
}
s32 act_coughing(struct MarioState *m) {
if (!m) { return 0; }
s32 animFrame;
if (check_common_idle_cancels(m)) {
@ -457,6 +466,7 @@ s32 act_coughing(struct MarioState *m) {
}
s32 act_hold_idle(struct MarioState *m) {
if (!m) { return 0; }
if (m->heldObj != NULL && segmented_to_virtual(&bhvJumpingBox) == m->heldObj->behavior) {
return set_mario_action(m, ACT_CRAZY_BOX_BOUNCE, 0);
}
@ -479,6 +489,7 @@ s32 act_hold_idle(struct MarioState *m) {
}
s32 act_hold_heavy_idle(struct MarioState *m) {
if (!m) { return 0; }
if (m->input & INPUT_UNKNOWN_10) {
return drop_and_set_mario_action(m, ACT_SHOCKWAVE_BOUNCE, 0);
}
@ -505,6 +516,7 @@ s32 act_hold_heavy_idle(struct MarioState *m) {
}
s32 act_standing_against_wall(struct MarioState *m) {
if (!m) { return 0; }
if (m->input & INPUT_UNKNOWN_10) {
return set_mario_action(m, ACT_SHOCKWAVE_BOUNCE, 0);
}
@ -527,6 +539,7 @@ s32 act_standing_against_wall(struct MarioState *m) {
}
s32 act_in_quicksand(struct MarioState *m) {
if (!m) { return 0; }
if (m->quicksandDepth < 30.0f) {
return set_mario_action(m, ACT_IDLE, 0);
}
@ -546,6 +559,7 @@ s32 act_in_quicksand(struct MarioState *m) {
}
s32 act_crouching(struct MarioState *m) {
if (!m) { return 0; }
if (m->input & INPUT_UNKNOWN_10) {
return set_mario_action(m, ACT_SHOCKWAVE_BOUNCE, 0);
}
@ -584,6 +598,7 @@ s32 act_crouching(struct MarioState *m) {
}
s32 act_panting(struct MarioState *m) {
if (!m) { return 0; }
if (m->input & INPUT_UNKNOWN_10) {
return set_mario_action(m, ACT_SHOCKWAVE_BOUNCE, 0);
}
@ -606,6 +621,7 @@ s32 act_panting(struct MarioState *m) {
}
s32 act_hold_panting_unused(struct MarioState *m) {
if (!m) { return 0; }
if (m->marioObj->oInteractStatus & INT_STATUS_MARIO_DROP_OBJECT) {
return drop_and_set_mario_action(m, ACT_PANTING, 0);
}
@ -637,6 +653,7 @@ void stopping_step(struct MarioState *m, s32 animID, u32 action) {
}
s32 act_braking_stop(struct MarioState *m) {
if (!m) { return 0; }
if (m->input & INPUT_UNKNOWN_10) {
return set_mario_action(m, ACT_SHOCKWAVE_BOUNCE, 0);
}
@ -659,6 +676,7 @@ s32 act_braking_stop(struct MarioState *m) {
}
s32 act_butt_slide_stop(struct MarioState *m) {
if (!m) { return 0; }
if (m->input & INPUT_UNKNOWN_10) {
return set_mario_action(m, ACT_SHOCKWAVE_BOUNCE, 0);
}
@ -676,6 +694,7 @@ s32 act_butt_slide_stop(struct MarioState *m) {
}
s32 act_hold_butt_slide_stop(struct MarioState *m) {
if (!m) { return 0; }
if (m->marioObj->oInteractStatus & INT_STATUS_MARIO_DROP_OBJECT) {
return drop_and_set_mario_action(m, ACT_IDLE, 0);
}
@ -697,6 +716,7 @@ s32 act_hold_butt_slide_stop(struct MarioState *m) {
}
s32 act_slide_kick_slide_stop(struct MarioState *m) {
if (!m) { return 0; }
if (m->input & INPUT_UNKNOWN_10) {
return drop_and_set_mario_action(m, ACT_SHOCKWAVE_BOUNCE, 0);
}
@ -710,6 +730,7 @@ s32 act_slide_kick_slide_stop(struct MarioState *m) {
}
s32 act_start_crouching(struct MarioState *m) {
if (!m) { return 0; }
if (m->input & INPUT_UNKNOWN_10) {
return set_mario_action(m, ACT_SHOCKWAVE_BOUNCE, 0);
}
@ -735,6 +756,7 @@ s32 act_start_crouching(struct MarioState *m) {
}
s32 act_stop_crouching(struct MarioState *m) {
if (!m) { return 0; }
if (m->input & INPUT_UNKNOWN_10) {
return set_mario_action(m, ACT_SHOCKWAVE_BOUNCE, 0);
}
@ -760,6 +782,7 @@ s32 act_stop_crouching(struct MarioState *m) {
}
s32 act_start_crawling(struct MarioState *m) {
if (!m) { return 0; }
if (m->input & INPUT_FIRST_PERSON) {
return set_mario_action(m, ACT_STOP_CROUCHING, 0);
}
@ -786,6 +809,7 @@ s32 act_start_crawling(struct MarioState *m) {
}
s32 act_stop_crawling(struct MarioState *m) {
if (!m) { return 0; }
if (m->input & INPUT_UNKNOWN_10) {
return set_mario_action(m, ACT_SHOCKWAVE_BOUNCE, 0);
}
@ -807,6 +831,7 @@ s32 act_stop_crawling(struct MarioState *m) {
}
s32 act_shockwave_bounce(struct MarioState *m) {
if (!m) { return 0; }
s16 sp1E;
f32 sp18;
@ -852,6 +877,7 @@ s32 landing_step(struct MarioState *m, s32 arg1, u32 action) {
}
s32 check_common_landing_cancels(struct MarioState *m, u32 action) {
if (!m) { return 0; }
if (m->input & INPUT_UNKNOWN_10) {
return set_mario_action(m, ACT_SHOCKWAVE_BOUNCE, 0);
}
@ -880,6 +906,7 @@ s32 check_common_landing_cancels(struct MarioState *m, u32 action) {
}
s32 act_jump_land_stop(struct MarioState *m) {
if (!m) { return 0; }
if (check_common_landing_cancels(m, 0)) {
return TRUE;
}
@ -889,6 +916,7 @@ s32 act_jump_land_stop(struct MarioState *m) {
}
s32 act_double_jump_land_stop(struct MarioState *m) {
if (!m) { return 0; }
if (check_common_landing_cancels(m, 0)) {
return TRUE;
}
@ -898,6 +926,7 @@ s32 act_double_jump_land_stop(struct MarioState *m) {
}
s32 act_side_flip_land_stop(struct MarioState *m) {
if (!m) { return 0; }
if (check_common_landing_cancels(m, 0)) {
return TRUE;
}
@ -908,6 +937,7 @@ s32 act_side_flip_land_stop(struct MarioState *m) {
}
s32 act_freefall_land_stop(struct MarioState *m) {
if (!m) { return 0; }
if (check_common_landing_cancels(m, 0)) {
return TRUE;
}
@ -917,6 +947,7 @@ s32 act_freefall_land_stop(struct MarioState *m) {
}
s32 act_triple_jump_land_stop(struct MarioState *m) {
if (!m) { return 0; }
if (check_common_landing_cancels(m, ACT_JUMP)) {
return TRUE;
}
@ -926,6 +957,7 @@ s32 act_triple_jump_land_stop(struct MarioState *m) {
}
s32 act_backflip_land_stop(struct MarioState *m) {
if (!m) { return 0; }
if (!(m->input & INPUT_Z_DOWN) || m->marioObj->header.gfx.animInfo.animFrame >= 6) {
m->input &= ~INPUT_A_PRESSED;
}
@ -939,6 +971,7 @@ s32 act_backflip_land_stop(struct MarioState *m) {
}
s32 act_lava_boost_land(struct MarioState *m) {
if (!m) { return 0; }
m->input &= ~(INPUT_FIRST_PERSON | INPUT_B_PRESSED);
if (check_common_landing_cancels(m, 0)) {
@ -950,6 +983,7 @@ s32 act_lava_boost_land(struct MarioState *m) {
}
s32 act_long_jump_land_stop(struct MarioState *m) {
if (!m) { return 0; }
m->input &= ~INPUT_B_PRESSED;
if (check_common_landing_cancels(m, ACT_JUMP)) {
return TRUE;
@ -962,6 +996,7 @@ s32 act_long_jump_land_stop(struct MarioState *m) {
}
s32 act_hold_jump_land_stop(struct MarioState *m) {
if (!m) { return 0; }
if (m->marioObj->oInteractStatus & INT_STATUS_MARIO_DROP_OBJECT) {
return drop_and_set_mario_action(m, ACT_IDLE, 0);
}
@ -983,6 +1018,7 @@ s32 act_hold_jump_land_stop(struct MarioState *m) {
}
s32 act_hold_freefall_land_stop(struct MarioState *m) {
if (!m) { return 0; }
if (m->marioObj->oInteractStatus & INT_STATUS_MARIO_DROP_OBJECT) {
return drop_and_set_mario_action(m, ACT_IDLE, 0);
}
@ -1003,6 +1039,7 @@ s32 act_hold_freefall_land_stop(struct MarioState *m) {
}
s32 act_air_throw_land(struct MarioState *m) {
if (!m) { return 0; }
if (m->input & INPUT_UNKNOWN_10) {
return set_mario_action(m, ACT_SHOCKWAVE_BOUNCE, 0);
}
@ -1020,6 +1057,7 @@ s32 act_air_throw_land(struct MarioState *m) {
}
s32 act_twirl_land(struct MarioState *m) {
if (!m) { return 0; }
m->actionState = 1;
if (m->input & INPUT_UNKNOWN_10) {
return set_mario_action(m, ACT_SHOCKWAVE_BOUNCE, 0);
@ -1050,6 +1088,7 @@ s32 act_twirl_land(struct MarioState *m) {
}
s32 act_ground_pound_land(struct MarioState *m) {
if (!m) { return 0; }
m->actionState = 1;
if (m->input & INPUT_UNKNOWN_10) {
return drop_and_set_mario_action(m, ACT_SHOCKWAVE_BOUNCE, 0);
@ -1068,6 +1107,7 @@ s32 act_ground_pound_land(struct MarioState *m) {
}
s32 act_first_person(struct MarioState *m) {
if (!m) { return 0; }
s32 sp1C = (m->input & (INPUT_OFF_FLOOR | INPUT_ABOVE_SLIDE | INPUT_UNKNOWN_10)) != 0;
if (m->actionState == 0) {
@ -1100,6 +1140,7 @@ s32 act_first_person(struct MarioState *m) {
}
s32 check_common_stationary_cancels(struct MarioState *m) {
if (!m) { return 0; }
if (m->playerIndex != 0) { return FALSE; }
if (m->pos[1] < m->waterLevel - 100) {

View file

@ -42,6 +42,7 @@ static s16 D_80339FD2;
static f32 D_80339FD4;
void set_swimming_at_surface_particles(struct MarioState *m, u32 particleFlag) {
if (!m) { return; }
s16 atSurface = m->pos[1] >= m->waterLevel - 130;
u16 pIndex = m->playerIndex;
@ -56,6 +57,7 @@ void set_swimming_at_surface_particles(struct MarioState *m, u32 particleFlag) {
}
static s32 swimming_near_surface(struct MarioState *m) {
if (!m) { return 0; }
if (m->flags & MARIO_METAL_CAP) {
return FALSE;
}
@ -64,6 +66,7 @@ static s32 swimming_near_surface(struct MarioState *m) {
}
static f32 get_buoyancy(struct MarioState *m) {
if (!m) { return 0; }
f32 buoyancy = 0.0f;
if (m->flags & MARIO_METAL_CAP) {
@ -82,6 +85,7 @@ static f32 get_buoyancy(struct MarioState *m) {
}
u32 perform_water_full_step(struct MarioState *m, Vec3f nextPos) {
if (!m) { return 0; }
struct WallCollisionData wcd = { 0 };
struct Surface *ceil;
struct Surface *floor;
@ -131,6 +135,7 @@ u32 perform_water_full_step(struct MarioState *m, Vec3f nextPos) {
}
void apply_water_current(struct MarioState *m, Vec3f step) {
if (!m) { return; }
s32 i;
f32 whirlpoolRadius = 2000.0f;
@ -217,6 +222,7 @@ u32 perform_water_step(struct MarioState *m) {
}
static BAD_RETURN(u32) update_water_pitch(struct MarioState *m) {
if (!m) { return; }
struct Object *marioObj = m->marioObj;
if (marioObj->header.gfx.angle[0] > 0) {
@ -234,6 +240,7 @@ static BAD_RETURN(u32) update_water_pitch(struct MarioState *m) {
}
static void stationary_slow_down(struct MarioState *m) {
if (!m) { return; }
f32 buoyancy = get_buoyancy(m);
m->angleVel[0] = 0;
@ -250,6 +257,7 @@ static void stationary_slow_down(struct MarioState *m) {
}
static void update_swimming_speed(struct MarioState *m, f32 decelThreshold) {
if (!m) { return; }
f32 buoyancy = get_buoyancy(m);
f32 maxSpeed = 28.0f;
@ -275,6 +283,7 @@ static void update_swimming_speed(struct MarioState *m, f32 decelThreshold) {
}
static void update_swimming_yaw(struct MarioState *m) {
if (!m) { return; }
s16 targetYawVel = -(s16)(10.0f * m->controller->stickX);
if (targetYawVel > 0) {
@ -304,6 +313,7 @@ static void update_swimming_yaw(struct MarioState *m) {
}
static void update_swimming_pitch(struct MarioState *m) {
if (!m) { return; }
s16 targetPitch = -(s16)(252.0f * m->controller->stickY);
s16 pitchVel;
@ -325,6 +335,7 @@ static void update_swimming_pitch(struct MarioState *m) {
}
static void common_idle_step(struct MarioState *m, s32 animation, s32 arg) {
if (!m) { return; }
s16 *val = &m->marioBodyState->headAngle[0];
update_swimming_yaw(m);
@ -349,6 +360,7 @@ static void common_idle_step(struct MarioState *m, s32 animation, s32 arg) {
}
static s32 act_water_idle(struct MarioState *m) {
if (!m) { return 0; }
u32 val = 0x10000;
if (m->flags & MARIO_METAL_CAP) {
@ -372,6 +384,7 @@ static s32 act_water_idle(struct MarioState *m) {
}
static s32 act_hold_water_idle(struct MarioState *m) {
if (!m) { return 0; }
if (m->flags & MARIO_METAL_CAP) {
return set_mario_action(m, ACT_HOLD_METAL_WATER_FALLING, 0);
}
@ -393,6 +406,7 @@ static s32 act_hold_water_idle(struct MarioState *m) {
}
static s32 act_water_action_end(struct MarioState *m) {
if (!m) { return 0; }
if (m->flags & MARIO_METAL_CAP) {
return set_mario_action(m, ACT_METAL_WATER_FALLING, 1);
}
@ -413,6 +427,7 @@ static s32 act_water_action_end(struct MarioState *m) {
}
static s32 act_hold_water_action_end(struct MarioState *m) {
if (!m) { return 0; }
if (m->flags & MARIO_METAL_CAP) {
return set_mario_action(m, ACT_HOLD_METAL_WATER_FALLING, 0);
}
@ -439,12 +454,14 @@ static s32 act_hold_water_action_end(struct MarioState *m) {
}
static void reset_float_globals(struct MarioState *m) {
if (!m) { return; }
D_80339FD0 = 0;
D_80339FD2 = 0x800;
D_80339FD4 = m->faceAngle[0] / 256.0f + 20.0f;
}
void float_surface_gfx(struct MarioState *m) {
if (!m) { return; }
if (D_80339FD2 != 0 && m->pos[1] > m->waterLevel - 85 && m->faceAngle[0] >= 0) {
if ((D_80339FD0 += D_80339FD2) >= 0) {
m->marioObj->header.gfx.pos[1] += D_80339FD4 * sins(D_80339FD0);
@ -456,6 +473,7 @@ void float_surface_gfx(struct MarioState *m) {
}
static void common_swimming_step(struct MarioState *m, s16 swimStrength) {
if (!m) { return; }
s16 floorPitch;
UNUSED struct Object *marioObj = m->marioObj;
@ -502,6 +520,7 @@ static void common_swimming_step(struct MarioState *m, s16 swimStrength) {
}
static void play_swimming_noise(struct MarioState *m) {
if (!m) { return; }
s16 animFrame = m->marioObj->header.gfx.animInfo.animFrame;
// This must be one line to match on -O2
@ -509,6 +528,7 @@ static void play_swimming_noise(struct MarioState *m) {
}
static s32 check_water_jump(struct MarioState *m) {
if (!m) { return 0; }
s32 probe = (s32)(m->pos[1] + 1.5f);
if (m->input & INPUT_A_PRESSED) {
@ -529,6 +549,7 @@ static s32 check_water_jump(struct MarioState *m) {
}
static s32 act_breaststroke(struct MarioState *m) {
if (!m) { return 0; }
u16 pIndex = m->playerIndex;
if (m->actionArg == 0) {
@ -589,6 +610,7 @@ static s32 act_breaststroke(struct MarioState *m) {
}
static s32 act_swimming_end(struct MarioState *m) {
if (!m) { return 0; }
u16 pIndex = m->playerIndex;
if (m->flags & MARIO_METAL_CAP) {
@ -628,6 +650,7 @@ static s32 act_swimming_end(struct MarioState *m) {
}
static s32 act_flutter_kick(struct MarioState *m) {
if (!m) { return 0; }
u16 pIndex = m->playerIndex;
if (m->flags & MARIO_METAL_CAP) {
@ -659,6 +682,7 @@ static s32 act_flutter_kick(struct MarioState *m) {
}
static s32 act_hold_breaststroke(struct MarioState *m) {
if (!m) { return 0; }
if (m->flags & MARIO_METAL_CAP) {
return set_mario_action(m, ACT_HOLD_METAL_WATER_FALLING, 0);
}
@ -710,6 +734,7 @@ static s32 act_hold_breaststroke(struct MarioState *m) {
}
static s32 act_hold_swimming_end(struct MarioState *m) {
if (!m) { return 0; }
if (m->flags & MARIO_METAL_CAP) {
return set_mario_action(m, ACT_HOLD_METAL_WATER_FALLING, 0);
}
@ -743,6 +768,7 @@ static s32 act_hold_swimming_end(struct MarioState *m) {
}
static s32 act_hold_flutter_kick(struct MarioState *m) {
if (!m) { return 0; }
if (m->flags & MARIO_METAL_CAP) {
return set_mario_action(m, ACT_HOLD_METAL_WATER_FALLING, 0);
}
@ -769,6 +795,7 @@ static s32 act_hold_flutter_kick(struct MarioState *m) {
}
static s32 act_water_shell_swimming(struct MarioState *m) {
if (!m) { return 0; }
if (m->marioObj->oInteractStatus & INT_STATUS_MARIO_DROP_OBJECT) {
return drop_and_set_mario_action(m, ACT_WATER_IDLE, 0);
}
@ -796,6 +823,7 @@ static s32 act_water_shell_swimming(struct MarioState *m) {
}
static s32 check_water_grab(struct MarioState *m) {
if (!m) { return 0; }
//! Heave hos have the grabbable interaction type but are not normally
// grabbable. Since water grabbing doesn't check the appropriate input flag,
// you can use water grab to pick up heave ho.
@ -820,6 +848,7 @@ static s32 check_water_grab(struct MarioState *m) {
}
static s32 act_water_throw(struct MarioState *m) {
if (!m) { return 0; }
update_swimming_yaw(m);
update_swimming_pitch(m);
update_swimming_speed(m, MIN_SWIM_SPEED);
@ -844,6 +873,7 @@ static s32 act_water_throw(struct MarioState *m) {
}
static s32 act_water_punch(struct MarioState *m) {
if (!m) { return 0; }
if (m->forwardVel < 7.0f) {
m->forwardVel += 1.0f;
}
@ -890,6 +920,7 @@ static s32 act_water_punch(struct MarioState *m) {
}
static void common_water_knockback_step(struct MarioState *m, s32 animation, u32 endAction, s32 arg3) {
if (!m) { return; }
stationary_slow_down(m);
perform_water_step(m);
set_mario_animation(m, animation);
@ -906,16 +937,19 @@ static void common_water_knockback_step(struct MarioState *m, s32 animation, u32
}
static s32 act_backward_water_kb(struct MarioState *m) {
if (!m) { return 0; }
common_water_knockback_step(m, MARIO_ANIM_BACKWARDS_WATER_KB, ACT_WATER_IDLE, m->actionArg);
return FALSE;
}
static s32 act_forward_water_kb(struct MarioState *m) {
if (!m) { return 0; }
common_water_knockback_step(m, MARIO_ANIM_WATER_FORWARD_KB, ACT_WATER_IDLE, m->actionArg);
return FALSE;
}
static s32 act_water_shocked(struct MarioState *m) {
if (!m) { return 0; }
play_character_sound_if_no_flag(m, CHAR_SOUND_WAAAOOOW, MARIO_MARIO_SOUND_PLAYED);
play_sound(SOUND_MOVING_SHOCKED, m->marioObj->header.gfx.cameraToObject);
if (m->playerIndex == 0) { set_camera_shake_from_hit(SHAKE_SHOCK); }
@ -937,6 +971,7 @@ static s32 act_water_shocked(struct MarioState *m) {
}
static s32 act_drowning(struct MarioState *m) {
if (!m) { return 0; }
switch (m->actionState) {
case 0:
set_mario_animation(m, MARIO_ANIM_DROWNING_PART1);
@ -976,6 +1011,7 @@ static s32 act_drowning(struct MarioState *m) {
}
static s32 act_water_death(struct MarioState *m) {
if (!m) { return 0; }
stationary_slow_down(m);
perform_water_step(m);
@ -1003,6 +1039,7 @@ static s32 act_water_death(struct MarioState *m) {
}
static s32 act_water_plunge(struct MarioState *m) {
if (!m) { return 0; }
u32 stepResult;
s32 stateFlags = m->heldObj != NULL;
@ -1088,6 +1125,7 @@ static s32 act_water_plunge(struct MarioState *m) {
}
static s32 act_caught_in_whirlpool(struct MarioState *m) {
if (!m) { return 0; }
f32 sinAngleChange;
f32 cosAngleChange;
f32 newDistance;
@ -1163,6 +1201,7 @@ static s32 act_caught_in_whirlpool(struct MarioState *m) {
}
static void play_metal_water_jumping_sound(struct MarioState *m, u32 landing) {
if (!m) { return; }
if (!(m->flags & MARIO_ACTION_SOUND_PLAYED)) {
set_mario_particle_flags(m, PARTICLE_MIST_CIRCLE, FALSE);
}
@ -1179,6 +1218,7 @@ static void play_metal_water_walking_sound(struct MarioState *m) {
}
static void update_metal_water_walking_speed(struct MarioState *m) {
if (!m) { return; }
f32 val = m->intendedMag / 1.5f;
if (m->forwardVel <= 0.0f) {
@ -1205,6 +1245,7 @@ static void update_metal_water_walking_speed(struct MarioState *m) {
}
static s32 update_metal_water_jump_speed(struct MarioState *m) {
if (!m) { return 0; }
UNUSED f32 nextY = m->pos[1] + m->vel[1];
f32 waterSurface = m->waterLevel - 100;
@ -1234,6 +1275,7 @@ static s32 update_metal_water_jump_speed(struct MarioState *m) {
}
static s32 act_metal_water_standing(struct MarioState *m) {
if (!m) { return 0; }
if (!(m->flags & MARIO_METAL_CAP)) {
return set_mario_action(m, ACT_WATER_IDLE, 0);
}
@ -1271,6 +1313,7 @@ static s32 act_metal_water_standing(struct MarioState *m) {
}
static s32 act_hold_metal_water_standing(struct MarioState *m) {
if (!m) { return 0; }
if (m->marioObj->oInteractStatus & INT_STATUS_MARIO_DROP_OBJECT) {
return drop_and_set_mario_action(m, ACT_METAL_WATER_STANDING, 0);
}
@ -1293,6 +1336,7 @@ static s32 act_hold_metal_water_standing(struct MarioState *m) {
}
static s32 act_metal_water_walking(struct MarioState *m) {
if (!m) { return 0; }
s32 val04;
if (!(m->flags & MARIO_METAL_CAP)) {
@ -1333,6 +1377,7 @@ static s32 act_metal_water_walking(struct MarioState *m) {
}
static s32 act_hold_metal_water_walking(struct MarioState *m) {
if (!m) { return 0; }
s32 val04;
if (m->marioObj->oInteractStatus & INT_STATUS_MARIO_DROP_OBJECT) {
@ -1375,6 +1420,7 @@ static s32 act_hold_metal_water_walking(struct MarioState *m) {
}
static s32 act_metal_water_jump(struct MarioState *m) {
if (!m) { return 0; }
if (!(m->flags & MARIO_METAL_CAP)) {
return set_mario_action(m, ACT_WATER_IDLE, 0);
}
@ -1400,6 +1446,7 @@ static s32 act_metal_water_jump(struct MarioState *m) {
}
static s32 act_hold_metal_water_jump(struct MarioState *m) {
if (!m) { return 0; }
if (m->marioObj->oInteractStatus & INT_STATUS_MARIO_DROP_OBJECT) {
return drop_and_set_mario_action(m, ACT_METAL_WATER_FALLING, 0);
}
@ -1429,6 +1476,7 @@ static s32 act_hold_metal_water_jump(struct MarioState *m) {
}
static s32 act_metal_water_falling(struct MarioState *m) {
if (!m) { return 0; }
if (!(m->flags & MARIO_METAL_CAP)) {
return set_mario_action(m, ACT_WATER_IDLE, 0);
}
@ -1448,6 +1496,7 @@ static s32 act_metal_water_falling(struct MarioState *m) {
}
static s32 act_hold_metal_water_falling(struct MarioState *m) {
if (!m) { return 0; }
if (m->marioObj->oInteractStatus & INT_STATUS_MARIO_DROP_OBJECT) {
return drop_and_set_mario_action(m, ACT_METAL_WATER_FALLING, 0);
}
@ -1471,6 +1520,7 @@ static s32 act_hold_metal_water_falling(struct MarioState *m) {
}
static s32 act_metal_water_jump_land(struct MarioState *m) {
if (!m) { return 0; }
play_metal_water_jumping_sound(m, TRUE);
if (!(m->flags & MARIO_METAL_CAP)) {
@ -1492,6 +1542,7 @@ static s32 act_metal_water_jump_land(struct MarioState *m) {
}
static s32 act_hold_metal_water_jump_land(struct MarioState *m) {
if (!m) { return 0; }
play_metal_water_jumping_sound(m, TRUE);
if (m->marioObj->oInteractStatus & INT_STATUS_MARIO_DROP_OBJECT) {
@ -1517,6 +1568,7 @@ static s32 act_hold_metal_water_jump_land(struct MarioState *m) {
}
static s32 act_metal_water_fall_land(struct MarioState *m) {
if (!m) { return 0; }
play_metal_water_jumping_sound(m, TRUE);
if (!(m->flags & MARIO_METAL_CAP)) {
@ -1538,6 +1590,7 @@ static s32 act_metal_water_fall_land(struct MarioState *m) {
}
static s32 act_hold_metal_water_fall_land(struct MarioState *m) {
if (!m) { return 0; }
play_metal_water_jumping_sound(m, TRUE);
if (m->marioObj->oInteractStatus & INT_STATUS_MARIO_DROP_OBJECT) {
@ -1563,6 +1616,7 @@ static s32 act_hold_metal_water_fall_land(struct MarioState *m) {
}
static s32 check_common_submerged_cancels(struct MarioState *m) {
if (!m) { return 0; }
if (m->pos[1] > m->waterLevel - 80) {
if (m->waterLevel - 80 > m->floorHeight) {
m->pos[1] = m->waterLevel - 80;

View file

@ -107,6 +107,7 @@ Gfx *geo_draw_mario_head_goddard(s32 callContext, struct GraphNode *node, Mat4 *
}
static void toad_message_faded(void) {
if (!gCurrentObject) { return; }
if (gCurrentObject->oDistanceToMario > 700.0f) {
gCurrentObject->oToadMessageRecentlyTalked = FALSE;
}
@ -116,6 +117,7 @@ static void toad_message_faded(void) {
}
static void toad_message_opaque(void) {
if (!gCurrentObject) { return; }
if (gCurrentObject->oDistanceToMario > 700.0f) {
gCurrentObject->oToadMessageState = TOAD_MESSAGE_FADING;
} else if (!gCurrentObject->oToadMessageRecentlyTalked) {
@ -129,6 +131,7 @@ static void toad_message_opaque(void) {
}
static void toad_message_talking(void) {
if (!gCurrentObject) { return; }
if (cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 3, 1, CUTSCENE_DIALOG, gCurrentObject->oToadMessageDialogId, NULL)
!= 0) {
gCurrentObject->oToadMessageRecentlyTalked = TRUE;
@ -149,18 +152,21 @@ static void toad_message_talking(void) {
}
static void toad_message_opacifying(void) {
if (!gCurrentObject) { return; }
if ((gCurrentObject->oOpacity += 6) == 255) {
gCurrentObject->oToadMessageState = TOAD_MESSAGE_OPAQUE;
}
}
static void toad_message_fading(void) {
if (!gCurrentObject) { return; }
if ((gCurrentObject->oOpacity -= 6) == 81) {
gCurrentObject->oToadMessageState = TOAD_MESSAGE_FADED;
}
}
void bhv_toad_message_loop(void) {
if (!gCurrentObject) { return; }
if (gCurrentObject->header.gfx.node.flags & GRAPH_RENDER_ACTIVE) {
gCurrentObject->oInteractionSubtype = 0;
switch (gCurrentObject->oToadMessageState) {
@ -184,6 +190,7 @@ void bhv_toad_message_loop(void) {
}
void bhv_toad_message_init(void) {
if (!gCurrentObject) { return; }
s32 saveFlags = save_file_get_flags();
s32 starCount = save_file_get_total_star_count(gCurrSaveFileNum - 1, COURSE_MIN - 1, COURSE_MAX - 1);
s32 dialogId = (gCurrentObject->oBehParams >> 24) & 0xFF;
@ -217,6 +224,7 @@ void bhv_toad_message_init(void) {
}
static void star_door_unlock_spawn_particles(s16 angleOffset) {
if (!gCurrentObject) { return; }
struct Object *sparkleParticle = spawn_object(gCurrentObject, 0, bhvSparkleSpawn);
if (sparkleParticle == NULL) { return; }
@ -229,6 +237,7 @@ static void star_door_unlock_spawn_particles(s16 angleOffset) {
}
void bhv_unlock_door_star_init(void) {
if (!gCurrentObject) { return; }
gCurrentObject->oUnlockDoorStarState = UNLOCK_DOOR_STAR_RISING;
gCurrentObject->oUnlockDoorStarTimer = 0;
gCurrentObject->oUnlockDoorStarYawVel = 0x1000;
@ -240,6 +249,7 @@ void bhv_unlock_door_star_init(void) {
}
void bhv_unlock_door_star_loop(void) {
if (!gCurrentObject) { return; }
UNUSED u8 unused1[4];
s16 prevYaw = gCurrentObject->oMoveAngleYaw;
UNUSED u8 unused2[4];

View file

@ -91,6 +91,7 @@ BAD_RETURN(s32) init_bully_collision_data(struct BullyCollisionData *data, f32 p
}
void mario_bonk_reflection(struct MarioState *m, u32 negateSpeed) {
if (!m) { return; }
if (m->wall != NULL) {
s16 wallAngle = atan2s(m->wallNormal[2], m->wallNormal[0]);
m->faceAngle[1] = wallAngle - (s16)(m->faceAngle[1] - wallAngle);
@ -109,6 +110,7 @@ void mario_bonk_reflection(struct MarioState *m, u32 negateSpeed) {
}
u32 mario_update_quicksand(struct MarioState *m, f32 sinkingSpeed) {
if (!m) { return 0; }
bool allow = true;
smlua_call_event_hooks_mario_param_and_int_ret_bool(HOOK_ALLOW_HAZARD_SURFACE, m, HAZARD_TYPE_QUICKSAND, &allow);
if (m->action & ACT_FLAG_RIDING_SHELL || (gServerSettings.enableCheats && gCheats.godMode && m->playerIndex == 0) || (!allow)) {
@ -162,6 +164,7 @@ u32 mario_update_quicksand(struct MarioState *m, f32 sinkingSpeed) {
}
u32 mario_push_off_steep_floor(struct MarioState *m, u32 action, u32 actionArg) {
if (!m) { return 0; }
s16 floorDYaw = m->floorAngle - m->faceAngle[1];
if (floorDYaw > -0x4000 && floorDYaw < 0x4000) {
@ -176,7 +179,9 @@ u32 mario_push_off_steep_floor(struct MarioState *m, u32 action, u32 actionArg)
}
u32 mario_update_moving_sand(struct MarioState *m) {
if (!m) { return 0; }
struct Surface *floor = m->floor;
if (!floor) { return 0; }
s32 floorType = floor->type;
if (floorType == SURFACE_DEEP_MOVING_QUICKSAND || floorType == SURFACE_SHALLOW_MOVING_QUICKSAND
@ -194,7 +199,9 @@ u32 mario_update_moving_sand(struct MarioState *m) {
}
u32 mario_update_windy_ground(struct MarioState *m) {
if (!m) { return 0; }
struct Surface *floor = m->floor;
if (!floor) { return 0; }
extern bool gDjuiInMainMenu;
if (floor->type == SURFACE_HORIZONTAL_WIND && !gDjuiInMainMenu) {
@ -228,6 +235,7 @@ u32 mario_update_windy_ground(struct MarioState *m) {
}
void stop_and_set_height_to_floor(struct MarioState *m) {
if (!m) { return; }
struct Object *marioObj = m->marioObj;
mario_set_forward_vel(m, 0.0f);
@ -241,6 +249,7 @@ void stop_and_set_height_to_floor(struct MarioState *m) {
}
s32 stationary_ground_step(struct MarioState *m) {
if (!m) { return 0; }
u32 takeStep;
struct Object *marioObj = m->marioObj;
u32 stepResult = GROUND_STEP_NONE;
@ -263,6 +272,7 @@ s32 stationary_ground_step(struct MarioState *m) {
}
static s32 perform_ground_quarter_step(struct MarioState *m, Vec3f nextPos) {
if (!m) { return 0; }
struct WallCollisionData lowerWcd = { 0 };
struct WallCollisionData upperWcd = { 0 };
struct Surface *ceil;
@ -379,6 +389,7 @@ s32 perform_ground_step(struct MarioState *m) {
}
u32 check_ledge_grab(struct MarioState *m, struct Surface *wall, Vec3f intendedPos, Vec3f nextPos) {
if (!m) { return 0; }
struct Surface *ledgeFloor;
Vec3f ledgePos;
f32 displacementX;
@ -419,6 +430,7 @@ u32 check_ledge_grab(struct MarioState *m, struct Surface *wall, Vec3f intendedP
}
s32 perform_air_quarter_step(struct MarioState *m, Vec3f intendedPos, u32 stepArg) {
if (!m) { return 0; }
s16 wallDYaw;
Vec3f nextPos;
struct WallCollisionData lowerWcd = { 0 };
@ -572,6 +584,7 @@ s32 perform_air_quarter_step(struct MarioState *m, Vec3f intendedPos, u32 stepAr
}
void apply_twirl_gravity(struct MarioState *m) {
if (!m) { return; }
f32 terminalVelocity;
f32 heaviness = 1.0f;
@ -588,6 +601,7 @@ void apply_twirl_gravity(struct MarioState *m) {
}
u32 should_strengthen_gravity_for_jump_ascent(struct MarioState *m) {
if (!m) { return 0; }
if (!(m->flags & MARIO_UNKNOWN_08)) {
return FALSE;
}
@ -604,6 +618,7 @@ u32 should_strengthen_gravity_for_jump_ascent(struct MarioState *m) {
}
void apply_gravity(struct MarioState *m) {
if (!m) { return; }
s32 result;
if (m->action == ACT_TWIRLING && m->vel[1] < 0.0f) {
@ -656,6 +671,7 @@ void apply_gravity(struct MarioState *m) {
}
void apply_vertical_wind(struct MarioState *m) {
if (!m) { return; }
f32 maxVelY;
f32 offsetY;
@ -751,12 +767,14 @@ s32 perform_air_step(struct MarioState *m, u32 stepArg) {
// They had these functions the whole time and never used them? Lol
void set_vel_from_pitch_and_yaw(struct MarioState *m) {
if (!m) { return; }
m->vel[0] = m->forwardVel * coss(m->faceAngle[0]) * sins(m->faceAngle[1]);
m->vel[1] = m->forwardVel * sins(m->faceAngle[0]);
m->vel[2] = m->forwardVel * coss(m->faceAngle[0]) * coss(m->faceAngle[1]);
}
void set_vel_from_yaw(struct MarioState *m) {
if (!m) { return; }
m->vel[0] = m->slideVelX = m->forwardVel * sins(m->faceAngle[1]);
m->vel[1] = 0.0f;
m->vel[2] = m->slideVelZ = m->forwardVel * coss(m->faceAngle[1]);

View file

@ -157,6 +157,7 @@ void turn_obj_away_from_surface(f32 velX, f32 velZ, f32 nX, UNUSED f32 nY, f32 n
* Finds any wall collisions, applies them, and turns away from the surface.
*/
s8 obj_find_wall(f32 objNewX, f32 objY, f32 objNewZ, f32 objVelX, f32 objVelZ) {
if (!o) { return 0; }
struct WallCollisionData hitbox;
f32 wall_nX, wall_nY, wall_nZ, objVelXCopy, objVelZCopy, objYawX, objYawZ;
@ -198,6 +199,7 @@ s8 obj_find_wall(f32 objNewX, f32 objY, f32 objNewZ, f32 objVelX, f32 objVelZ) {
* Turns an object away from steep floors, similarly to walls.
*/
s8 turn_obj_away_from_steep_floor(struct Surface *objFloor, f32 floorY, f32 objVelX, f32 objVelZ) {
if (!o) { return 0; }
f32 floor_nX, floor_nY, floor_nZ, objVelXCopy, objVelZCopy, objYawX, objYawZ;
if (objFloor == NULL) {
@ -264,6 +266,7 @@ void obj_orient_graph(struct Object *obj, f32 normalX, f32 normalY, f32 normalZ)
* Determines an object's forward speed multiplier.
*/
void calc_obj_friction(f32 *objFriction, f32 floor_nY) {
if (!o) { return; }
if (!objFriction) { return; }
if (floor_nY < 0.2 && o->oFriction < 0.9999) {
*objFriction = 0;
@ -276,6 +279,7 @@ void calc_obj_friction(f32 *objFriction, f32 floor_nY) {
* Updates an objects speed for gravity and updates Y position.
*/
void calc_new_obj_vel_and_pos_y(struct Surface *objFloor, f32 objFloorY, f32 objVelX, f32 objVelZ) {
if (!o) { return; }
if (!objFloor) { return; }
f32 floor_nX = objFloor->normal.x;
f32 floor_nY = objFloor->normal.y;
@ -335,6 +339,7 @@ void calc_new_obj_vel_and_pos_y(struct Surface *objFloor, f32 objFloorY, f32 obj
void calc_new_obj_vel_and_pos_y_underwater(struct Surface *objFloor, f32 floorY, f32 objVelX, f32 objVelZ,
f32 waterY) {
if (!o) { return; }
if (!objFloor) { return; }
f32 floor_nX = objFloor->normal.x;
f32 floor_nY = objFloor->normal.y;
@ -405,6 +410,7 @@ void calc_new_obj_vel_and_pos_y_underwater(struct Surface *objFloor, f32 floorY,
* Updates an objects position from oForwardVel and oMoveAngleYaw.
*/
void obj_update_pos_vel_xz(void) {
if (!o) { return; }
f32 xVel = o->oForwardVel * sins(o->oMoveAngleYaw);
f32 zVel = o->oForwardVel * coss(o->oMoveAngleYaw);
@ -417,6 +423,7 @@ void obj_update_pos_vel_xz(void) {
* if underwater.
*/
void obj_splash(s32 waterY, s32 objY) {
if (!o) { return; }
u32 globalTimer = gGlobalTimer;
// Spawns waves if near surface of water and plays a noise if entering.
@ -439,6 +446,7 @@ void obj_splash(s32 waterY, s32 objY) {
* Returns flags for certain interactions.
*/
s16 object_step(void) {
if (!o) { return 0; }
f32 objX = o->oPosX;
f32 objY = o->oPosY;
f32 objZ = o->oPosZ;
@ -506,7 +514,7 @@ s16 object_step_without_floor_orient(void) {
* position.
*/
void obj_move_xyz_using_fvel_and_yaw(struct Object *obj) {
if (!obj) { return; }
if (!o || !obj) { return; }
o->oVelX = obj->oForwardVel * sins(obj->oMoveAngleYaw);
o->oVelZ = obj->oForwardVel * coss(obj->oMoveAngleYaw);
@ -705,6 +713,7 @@ u8 is_nearest_mario_state_to_object(struct MarioState *m, struct Object *obj) {
u8 is_nearest_player_to_object(struct Object *m, struct Object *obj) {
if (m == NULL || obj == NULL) { return FALSE; }
struct MarioState *nearest = nearest_mario_state_to_object(obj);
if (!nearest) { return FALSE; }
return m == nearest->marioObj;
}
@ -818,6 +827,7 @@ s8 obj_find_wall_displacement(Vec3f dist, f32 x, f32 y, f32 z, f32 radius) {
* with a random forward velocity, y velocity, and direction.
*/
void obj_spawn_yellow_coins(struct Object *obj, s8 nCoins) {
if (!o) { return; }
if (!obj) { return; }
struct Object *coin;
s8 count;
@ -888,6 +898,7 @@ s8 current_mario_room_check(s16 room) {
* Triggers dialog when Mario is facing an object and controls it while in the dialog.
*/
s16 trigger_obj_dialog_when_facing(struct MarioState* m, s32 *inDialog, s16 dialogID, f32 dist, s32 actionArg, u8 (*inContinueDialogFunction)(void)) {
if (!o) { return 0; }
if (!m || !inDialog) { return 0; }
s16 dialogueResponse;
@ -917,9 +928,8 @@ s16 trigger_obj_dialog_when_facing(struct MarioState* m, s32 *inDialog, s16 dial
*Checks if a floor is one that should cause an object to "die".
*/
void obj_check_floor_death(s16 collisionFlags, struct Surface *floor) {
if (floor == NULL) {
return;
}
if (!o) { return; }
if (floor == NULL) { return; }
if ((collisionFlags & OBJ_COL_FLAG_GROUNDED) == OBJ_COL_FLAG_GROUNDED) {
switch (floor->type) {
@ -941,6 +951,7 @@ void obj_check_floor_death(s16 collisionFlags, struct Surface *floor) {
* audio, and eventually despawning it. Returns TRUE when the obj is dead.
*/
s8 obj_lava_death(void) {
if (!o) { return 0; }
struct Object *deathSmoke;
if (o->oTimer >= 31) {

View file

@ -83,6 +83,7 @@ void wiggler_jumped_on_attack_handler(void);
void huge_goomba_weakly_attacked(void);
s32 obj_is_rendering_enabled(void) {
if (!o) { return 0; }
if (o->header.gfx.node.flags & GRAPH_RENDER_ACTIVE) {
return TRUE;
} else {
@ -91,6 +92,7 @@ s32 obj_is_rendering_enabled(void) {
}
s16 obj_get_pitch_from_vel(void) {
if (!o) { return 0; }
return -atan2s(o->oForwardVel, o->oVelY);
}
@ -113,11 +115,13 @@ static s32 obj_update_race_proposition_dialog(struct MarioState* m, s16 dialogID
}
void obj_set_dist_from_home(f32 distFromHome) {
if (!o) { return; }
o->oPosX = o->oHomeX + distFromHome * coss(o->oMoveAngleYaw);
o->oPosZ = o->oHomeZ + distFromHome * sins(o->oMoveAngleYaw);
}
s32 obj_is_near_to_and_facing_mario(struct MarioState* m, f32 maxDist, s16 maxAngleDiff) {
if (!o) { return 0; }
struct Object* player = m->marioObj;
s32 distanceToPlayer = dist_between_objects(o, player);
s32 angleToPlayer = obj_angle_to_object(o, player);
@ -131,6 +135,7 @@ s32 obj_is_near_to_and_facing_mario(struct MarioState* m, f32 maxDist, s16 maxAn
//! Although having no return value, this function
//! must be u32 to match other functions on -O2.
static BAD_RETURN(u32) obj_perform_position_op(s32 op) {
if (!o) { return; }
switch (op) {
case POS_OP_SAVE_POSITION:
sObjSavedPosX = o->oPosX;
@ -153,6 +158,7 @@ static BAD_RETURN(u32) obj_perform_position_op(s32 op) {
}
void platform_on_track_update_pos_or_spawn_ball(s32 ballIndex, f32 x, f32 y, f32 z) {
if (!o) { return; }
struct Object *trackBall;
struct Waypoint *initialPrevWaypoint;
struct Waypoint *nextWaypoint;
@ -250,6 +256,7 @@ void platform_on_track_update_pos_or_spawn_ball(s32 ballIndex, f32 x, f32 y, f32
}
void cur_obj_spin_all_dimensions(f32 arg0, f32 arg1) {
if (!o) { return; }
f32 val24;
f32 val20;
f32 val1C;
@ -305,6 +312,7 @@ void cur_obj_spin_all_dimensions(f32 arg0, f32 arg1) {
}
void obj_rotate_yaw_and_bounce_off_walls(s16 targetYaw, s16 turnAmount) {
if (!o) { return; }
if (o->oMoveFlags & OBJ_MOVE_HIT_WALL) {
targetYaw = cur_obj_reflect_move_angle_off_wall();
}
@ -312,10 +320,12 @@ void obj_rotate_yaw_and_bounce_off_walls(s16 targetYaw, s16 turnAmount) {
}
s16 obj_get_pitch_to_home(f32 latDistToHome) {
if (!o) { return 0; }
return atan2s(latDistToHome, o->oPosY - o->oHomeY);
}
void obj_compute_vel_from_move_pitch(f32 speed) {
if (!o) { return; }
o->oForwardVel = speed * coss(o->oMoveAnglePitch);
o->oVelY = speed * -sins(o->oMoveAnglePitch);
}
@ -368,6 +378,7 @@ s32 cur_obj_set_anim_if_at_end(s32 arg0) {
}
s32 cur_obj_play_sound_at_anim_range(s8 arg0, s8 arg1, u32 sound) {
if (!o) { return 0; }
s32 val04;
if ((val04 = o->header.gfx.animInfo.animAccel / 0x10000) <= 0) {
@ -383,6 +394,7 @@ s32 cur_obj_play_sound_at_anim_range(s8 arg0, s8 arg1, u32 sound) {
}
s16 obj_turn_pitch_toward_mario(struct MarioState* m, f32 targetOffsetY, s16 turnAmount) {
if (!o) { return 0; }
if (!m) { return 0; }
s16 targetPitch;
@ -394,6 +406,7 @@ s16 obj_turn_pitch_toward_mario(struct MarioState* m, f32 targetOffsetY, s16 tur
}
s32 approach_f32_ptr(f32 *px, f32 target, f32 delta) {
if (!px) { return FALSE; }
if (*px > target) {
delta = -delta;
}
@ -408,14 +421,17 @@ s32 approach_f32_ptr(f32 *px, f32 target, f32 delta) {
}
s32 obj_forward_vel_approach(f32 target, f32 delta) {
if (!o) { return 0; }
return approach_f32_ptr(&o->oForwardVel, target, delta);
}
s32 obj_y_vel_approach(f32 target, f32 delta) {
if (!o) { return 0; }
return approach_f32_ptr(&o->oVelY, target, delta);
}
s32 obj_move_pitch_approach(s16 target, s16 delta) {
if (!o) { return 0; }
o->oMoveAnglePitch = approach_s16_symmetric(o->oMoveAnglePitch, target, delta);
if ((s16) o->oMoveAnglePitch == target) {
@ -426,6 +442,7 @@ s32 obj_move_pitch_approach(s16 target, s16 delta) {
}
s32 obj_face_pitch_approach(s16 targetPitch, s16 deltaPitch) {
if (!o) { return 0; }
o->oFaceAnglePitch = approach_s16_symmetric(o->oFaceAnglePitch, targetPitch, deltaPitch);
if ((s16) o->oFaceAnglePitch == targetPitch) {
@ -436,6 +453,7 @@ s32 obj_face_pitch_approach(s16 targetPitch, s16 deltaPitch) {
}
s32 obj_face_yaw_approach(s16 targetYaw, s16 deltaYaw) {
if (!o) { return 0; }
o->oFaceAngleYaw = approach_s16_symmetric(o->oFaceAngleYaw, targetYaw, deltaYaw);
if ((s16) o->oFaceAngleYaw == targetYaw) {
@ -446,6 +464,7 @@ s32 obj_face_yaw_approach(s16 targetYaw, s16 deltaYaw) {
}
s32 obj_face_roll_approach(s16 targetRoll, s16 deltaRoll) {
if (!o) { return 0; }
o->oFaceAngleRoll = approach_s16_symmetric(o->oFaceAngleRoll, targetRoll, deltaRoll);
if ((s16) o->oFaceAngleRoll == targetRoll) {
@ -471,6 +490,7 @@ s32 obj_smooth_turn(s16 *angleVel, s32 *angle, s16 targetAngle, f32 targetSpeedP
}
void obj_roll_to_match_yaw_turn(s16 targetYaw, s16 maxRoll, s16 rollSpeed) {
if (!o) { return; }
s16 targetRoll = o->oMoveAngleYaw - targetYaw;
clamp_s16(&targetRoll, -maxRoll, maxRoll);
obj_face_roll_approach(targetRoll, rollSpeed);
@ -481,10 +501,12 @@ s16 random_linear_offset(s16 base, s16 range) {
}
s16 random_mod_offset(s16 base, s16 step, s16 mod) {
if (!mod) { return 0; }
return base + step * (random_u16() % mod);
}
s16 obj_random_fixed_turn(s16 delta) {
if (!o) { return 0; }
return o->oMoveAngleYaw + (s16) random_sign() * delta;
}
@ -496,6 +518,7 @@ s16 obj_random_fixed_turn(s16 delta) {
* Return -1 once it's reached endScale.
*/
s32 obj_grow_then_shrink(f32 *scaleVel, f32 shootFireScale, f32 endScale) {
if (!o) { return 0; }
if (o->oTimer < 2) {
o->header.gfx.scale[0] += *scaleVel;
@ -542,6 +565,7 @@ s32 oscillate_toward(s32 *value, f32 *vel, s32 target, f32 velCloseToZero, f32 a
void obj_update_blinking(s32 *blinkTimer, s16 baseCycleLength, s16 cycleLengthRange,
s16 blinkLength) {
if (!o) { return; }
if (*blinkTimer != 0) {
*blinkTimer -= 1;
} else {
@ -556,6 +580,7 @@ void obj_update_blinking(s32 *blinkTimer, s16 baseCycleLength, s16 cycleLengthRa
}
s32 obj_resolve_object_collisions(s32 *targetYaw) {
if (!o) { return 0; }
struct Object *otherObject;
f32 dx;
f32 dz;
@ -602,6 +627,7 @@ s32 obj_resolve_object_collisions(s32 *targetYaw) {
}
s32 obj_bounce_off_walls_edges_objects(s32 *targetYaw) {
if (!o) { return 0; }
if (o->oMoveFlags & OBJ_MOVE_HIT_WALL) {
*targetYaw = cur_obj_reflect_move_angle_off_wall();
} else if (o->oMoveFlags & OBJ_MOVE_HIT_EDGE) {
@ -624,6 +650,7 @@ s32 obj_resolve_collisions_and_turn(s16 targetYaw, s16 turnSpeed) {
}
void obj_die_if_health_non_positive(void) {
if (!o) { return; }
if (o->oHealth <= 0) {
if (o->oDeathSound == 0) {
spawn_mist_particles_with_sound(SOUND_OBJ_DEFAULT_DEATH);
@ -651,11 +678,13 @@ void obj_die_if_health_non_positive(void) {
}
void obj_unused_die(void) {
if (!o) { return; }
o->oHealth = 0;
obj_die_if_health_non_positive();
}
void obj_set_knockback_action(s32 attackType) {
if (!o) { return; }
switch (attackType) {
case ATTACK_KICK_OR_TRIP:
case ATTACK_FAST_ATTACK:
@ -680,11 +709,13 @@ void obj_set_knockback_action(s32 attackType) {
}
void obj_set_squished_action(void) {
if (!o) { return; }
cur_obj_play_sound_2(SOUND_OBJ_STOMPED);
o->oAction = OBJ_ACT_SQUISHED;
}
s32 obj_die_if_above_lava_and_health_non_positive(void) {
if (!o) { return 0; }
if (o->oMoveFlags & OBJ_MOVE_UNDERWATER_ON_GROUND) {
if (o->oGravity + o->oBuoyancy > 0.0f
|| find_water_level(o->oPosX, o->oPosZ) - o->oPosY < 150.0f) {
@ -707,6 +738,7 @@ s32 obj_die_if_above_lava_and_health_non_positive(void) {
s32 obj_handle_attacks(struct ObjectHitbox *hitbox, s32 attackedMarioAction,
u8 *attackHandlers) {
if (!o) { return 0; }
s32 attackType;
obj_set_hitbox(o, hitbox);
@ -771,6 +803,7 @@ s32 obj_handle_attacks(struct ObjectHitbox *hitbox, s32 attackedMarioAction,
}
void obj_act_knockback(UNUSED f32 baseScale) {
if (!o) { return; }
cur_obj_update_floor_and_walls();
if (o->header.gfx.animInfo.curAnim != NULL) {
@ -788,6 +821,7 @@ void obj_act_knockback(UNUSED f32 baseScale) {
}
void obj_act_squished(f32 baseScale) {
if (!o) { return; }
f32 targetScaleY = baseScale * 0.3f;
cur_obj_update_floor_and_walls();
@ -809,6 +843,7 @@ void obj_act_squished(f32 baseScale) {
}
s32 obj_update_standard_actions(f32 scale) {
if (!o) { return 0; }
if (o->oAction < 100) {
return TRUE;
} else {
@ -830,6 +865,7 @@ s32 obj_update_standard_actions(f32 scale) {
}
s32 obj_check_attacks(struct ObjectHitbox *hitbox, s32 attackedMarioAction) {
if (!o) { return 0; }
s32 attackType;
obj_set_hitbox(o, hitbox);
@ -856,6 +892,7 @@ s32 obj_check_attacks(struct ObjectHitbox *hitbox, s32 attackedMarioAction) {
}
s32 obj_move_for_one_second(s32 endAction) {
if (!o) { return 0; }
cur_obj_update_floor_and_walls();
cur_obj_extend_animation_if_at_end();
@ -887,6 +924,7 @@ s32 obj_move_for_one_second(s32 endAction) {
* with partial updates.
*/
void treat_far_home_as_mario(f32 threshold, s32* distanceToPlayer, s32* angleToPlayer) {
if (!o) { return; }
f32 dx = o->oHomeX - o->oPosX;
f32 dy = o->oHomeY - o->oPosY;
f32 dz = o->oHomeZ - o->oPosZ;

View file

@ -215,7 +215,7 @@ Gfx *geo_switch_area(s32 callContext, struct GraphNode *node) {
struct MarioState* m = &gMarioStates[i];
if (!is_player_active(m)) { continue; }
struct Object* door = m->interactObj;
struct Object* door = m ? m->interactObj : NULL;
if (door == NULL) { continue; }
if (door->oInteractType != INTERACT_DOOR) { continue; }
if (door->oAction == 0) { continue; }
@ -360,6 +360,7 @@ f32 dist_between_object_and_point(struct Object *obj, f32 pointX, f32 pointY, f3
}
void cur_obj_forward_vel_approach_upward(f32 target, f32 increment) {
if (!o) { return; }
if (o->oForwardVel >= target) {
o->oForwardVel = target;
} else {
@ -429,6 +430,7 @@ s16 approach_s16_symmetric(s16 value, s16 target, s16 increment) {
}
s32 cur_obj_rotate_yaw_toward(s16 target, s16 increment) {
if (!o) { return 0; }
s16 startYaw;
startYaw = (s16) o->oMoveAngleYaw;
@ -456,6 +458,7 @@ s16 obj_angle_to_object(struct Object *obj1, struct Object *obj2) {
s16 obj_pitch_to_object(struct Object* obj, struct Object* target) {
if (obj == NULL) { return 0; }
if (!target) { return 0; }
f32 a, b, c, d;
a = target->oPosX - obj->oPosX;
c = target->oPosZ - obj->oPosZ;
@ -480,7 +483,7 @@ s16 obj_angle_to_point(struct Object *obj, f32 pointX, f32 pointZ) {
}
s16 obj_turn_toward_object(struct Object *obj, struct Object *target, s16 angleIndex, s16 turnAmount) {
if (obj == NULL || target == NULL) { return 0; }
if (obj == NULL || target == NULL || !o) { return 0; }
f32 a, b, c, d;
UNUSED s32 unused;
s16 targetAngle = 0;
@ -751,6 +754,7 @@ struct Object *spawn_object_relative_with_scale(s16 behaviorParam, s16 relativeP
}
void cur_obj_move_using_vel(void) {
if (!o) { return; }
o->oPosX += o->oVelX;
o->oPosY += o->oVelY;
o->oPosZ += o->oVelZ;
@ -792,6 +796,7 @@ void obj_set_gfx_pos_from_pos(struct Object *obj) {
}
void obj_init_animation(struct Object *obj, s32 animIndex) {
if (!o || !obj) { return; }
struct AnimationTable *animations = o->oAnimations;
if (animations && (u32)animIndex < animations->count) {
geo_obj_init_animation(&obj->header.gfx, animations->anims[animIndex]);
@ -869,12 +874,14 @@ void obj_scale(struct Object *obj, f32 scale) {
}
void cur_obj_scale(f32 scale) {
if (!o) { return; }
o->header.gfx.scale[0] = scale;
o->header.gfx.scale[1] = scale;
o->header.gfx.scale[2] = scale;
}
void cur_obj_init_animation(s32 animIndex) {
if (!o) { return; }
struct AnimationTable *animations = o->oAnimations;
if (animations && (u32)animIndex < animations->count) {
geo_obj_init_animation(&o->header.gfx, animations->anims[animIndex]);
@ -882,6 +889,7 @@ void cur_obj_init_animation(s32 animIndex) {
}
void cur_obj_init_animation_with_sound(s32 animIndex) {
if (!o) { return; }
struct AnimationTable *animations = o->oAnimations;
if (animations && (u32)animIndex < animations->count) {
geo_obj_init_animation(&o->header.gfx, animations->anims[animIndex]);
@ -890,6 +898,7 @@ void cur_obj_init_animation_with_sound(s32 animIndex) {
}
void obj_init_animation_with_accel_and_sound(struct Object *obj, s32 animIndex, f32 accel) {
if (!o) { return; }
if (obj != NULL) {
struct AnimationTable *animations = o->oAnimations;
if (animations && (u32)animIndex < animations->count) {
@ -901,6 +910,7 @@ void obj_init_animation_with_accel_and_sound(struct Object *obj, s32 animIndex,
}
void cur_obj_init_animation_with_accel_and_sound(s32 animIndex, f32 accel) {
if (!o) { return; }
struct AnimationTable *animations = o->oAnimations;
if (animations && (u32)animIndex < animations->count) {
s32 animAccel = (s32)(accel * 65536.0f);
@ -924,6 +934,7 @@ void cur_obj_enable_rendering_and_become_tangible(struct Object *obj) {
}
void cur_obj_enable_rendering(void) {
if (!o) { return; }
o->header.gfx.node.flags |= GRAPH_RENDER_ACTIVE;
}
@ -934,18 +945,22 @@ void cur_obj_disable_rendering_and_become_intangible(struct Object *obj) {
}
void cur_obj_disable_rendering(void) {
if (!o) { return; }
o->header.gfx.node.flags &= ~GRAPH_RENDER_ACTIVE;
}
void cur_obj_unhide(void) {
if (!o) { return; }
o->header.gfx.node.flags &= ~GRAPH_RENDER_INVISIBLE;
}
void cur_obj_hide(void) {
if (!o) { return; }
o->header.gfx.node.flags |= GRAPH_RENDER_INVISIBLE;
}
void cur_obj_set_pos_relative(struct Object *other, f32 dleft, f32 dy, f32 dforward) {
if (!o) { return; }
if (other == NULL) { return; }
f32 facingZ = coss(other->oMoveAngleYaw);
f32 facingX = sins(other->oMoveAngleYaw);
@ -961,6 +976,7 @@ void cur_obj_set_pos_relative(struct Object *other, f32 dleft, f32 dy, f32 dforw
}
void cur_obj_set_pos_relative_to_parent(f32 dleft, f32 dy, f32 dforward) {
if (!o) { return; }
cur_obj_set_pos_relative(o->parentObj, dleft, dy, dforward);
}
@ -969,6 +985,7 @@ void cur_obj_enable_rendering_2(void) {
}
void cur_obj_unused_init_on_floor(void) {
if (!o) { return; }
cur_obj_enable_rendering();
o->oPosY = find_floor_height(o->oPosX, o->oPosY, o->oPosZ);
@ -1207,17 +1224,21 @@ struct Object *cur_obj_find_nearby_held_actor(const BehaviorScript *behavior, f3
}
void cur_obj_reset_timer_and_subaction(void) {
if (!o) { return; }
o->oTimer = 0;
o->oSubAction = 0;
}
void cur_obj_change_action(s32 action) {
if (!o) { return; }
o->oAction = action;
o->oPrevAction = action;
cur_obj_reset_timer_and_subaction();
}
void cur_obj_set_vel_from_mario_vel(struct MarioState* m, f32 f12, f32 f14) {
if (!o) { return; }
if (!m) { return; }
f32 sp4 = m->forwardVel;
f32 sp0 = f12 * f14;
@ -1229,12 +1250,14 @@ void cur_obj_set_vel_from_mario_vel(struct MarioState* m, f32 f12, f32 f14) {
}
BAD_RETURN(s16) cur_obj_reverse_animation(void) {
if (!o) { return; }
if (o->header.gfx.animInfo.animFrame >= 0) {
o->header.gfx.animInfo.animFrame--;
}
}
BAD_RETURN(s32) cur_obj_extend_animation_if_at_end(void) {
if (!o) { return; }
s32 sp4 = o->header.gfx.animInfo.animFrame;
s32 sp0 = o->header.gfx.animInfo.curAnim ? o->header.gfx.animInfo.curAnim->loopEnd - 2 : 0;
@ -1242,6 +1265,7 @@ BAD_RETURN(s32) cur_obj_extend_animation_if_at_end(void) {
}
s32 cur_obj_check_if_near_animation_end(void) {
if (!o) { return 0; }
u32 animFlags = o->header.gfx.animInfo.curAnim ? (s32) o->header.gfx.animInfo.curAnim->flags : 0;
s32 animFrame = o->header.gfx.animInfo.animFrame;
s32 nearLoopEnd = o->header.gfx.animInfo.curAnim ? o->header.gfx.animInfo.curAnim->loopEnd - 2 : 0;
@ -1259,6 +1283,7 @@ s32 cur_obj_check_if_near_animation_end(void) {
}
s32 cur_obj_check_if_at_animation_end(void) {
if (!o) { return 0; }
s32 animFrame = o->header.gfx.animInfo.animFrame;
s32 lastFrame = o->header.gfx.animInfo.curAnim ? o->header.gfx.animInfo.curAnim->loopEnd - 1 : 0;
@ -1270,6 +1295,7 @@ s32 cur_obj_check_if_at_animation_end(void) {
}
s32 cur_obj_check_anim_frame(s32 frame) {
if (!o) { return 0; }
s32 animFrame = o->header.gfx.animInfo.animFrame;
if (animFrame == frame) {
@ -1280,6 +1306,7 @@ s32 cur_obj_check_anim_frame(s32 frame) {
}
s32 cur_obj_check_anim_frame_in_range(s32 startFrame, s32 rangeLength) {
if (!o) { return 0; }
s32 animFrame = o->header.gfx.animInfo.animFrame;
if (animFrame >= startFrame && animFrame < startFrame + rangeLength) {
@ -1290,6 +1317,7 @@ s32 cur_obj_check_anim_frame_in_range(s32 startFrame, s32 rangeLength) {
}
s32 cur_obj_check_frame_prior_current_frame(s16 *a0) {
if (!o) { return 0; }
s16 sp6 = o->header.gfx.animInfo.animFrame;
while (*a0 != -1) {
@ -1304,6 +1332,7 @@ s32 cur_obj_check_frame_prior_current_frame(s16 *a0) {
}
s32 mario_is_in_air_action(struct MarioState* m) {
if (!m) { return 0; }
if (m->action & ACT_FLAG_AIR) {
return TRUE;
} else {
@ -1312,6 +1341,7 @@ s32 mario_is_in_air_action(struct MarioState* m) {
}
s32 mario_is_dive_sliding(struct MarioState* m) {
if (!m) { return 0; }
if (m->action == ACT_DIVE_SLIDE) {
return TRUE;
} else {
@ -1320,11 +1350,13 @@ s32 mario_is_dive_sliding(struct MarioState* m) {
}
void cur_obj_set_y_vel_and_animation(f32 sp18, s32 sp1C) {
if (!o) { return; }
o->oVelY = sp18;
cur_obj_init_animation_with_sound(sp1C);
}
void cur_obj_unrender_and_reset_state(s32 sp18, s32 sp1C) {
if (!o) { return; }
cur_obj_become_intangible();
cur_obj_disable_rendering();
@ -1336,6 +1368,7 @@ void cur_obj_unrender_and_reset_state(s32 sp18, s32 sp1C) {
}
void cur_obj_move_after_thrown_or_dropped(f32 forwardVel, f32 velY) {
if (!o) { return; }
o->oMoveFlags = 0;
o->oFloorHeight = find_floor_height(o->oPosX, o->oPosY + 160.0f, o->oPosZ);
@ -1356,6 +1389,7 @@ void cur_obj_move_after_thrown_or_dropped(f32 forwardVel, f32 velY) {
}
void cur_obj_get_thrown_or_placed(f32 forwardVel, f32 velY, s32 thrownAction) {
if (!o) { return; }
if (o->behavior == segmented_to_virtual(smlua_override_behavior(bhvBowser))) {
// Interestingly, when bowser is thrown, he is offset slightly to
// Mario's right
@ -1382,6 +1416,7 @@ void cur_obj_get_thrown_or_placed(f32 forwardVel, f32 velY, s32 thrownAction) {
}
void cur_obj_get_dropped(void) {
if (!o) { return; }
cur_obj_become_tangible();
cur_obj_enable_rendering();
@ -1410,6 +1445,7 @@ void mario_set_flag(s32 flag) {
}
s32 cur_obj_clear_interact_status_flag(s32 flag) {
if (!o) { return 0; }
if (o->oInteractStatus & flag) {
o->oInteractStatus &= flag ^ ~(0);
return TRUE;
@ -1437,25 +1473,30 @@ void cur_obj_disable(void) {
}
void cur_obj_become_intangible(void) {
if (!o) { return; }
// When the timer is negative, the object is intangible and the timer
// doesn't count down
o->oIntangibleTimer = -1;
}
void cur_obj_become_tangible(void) {
if (!o) { return; }
o->oIntangibleTimer = 0;
}
void obj_become_tangible(struct Object *obj) {
if (!obj) { return; }
obj->oIntangibleTimer = 0;
}
void cur_obj_update_floor_height(void) {
if (!o) { return; }
struct Surface *floor;
o->oFloorHeight = find_floor(o->oPosX, o->oPosY, o->oPosZ, &floor);
}
struct Surface *cur_obj_update_floor_height_and_get_floor(void) {
if (!o) { return NULL; }
struct Surface *floor;
o->oFloorHeight = find_floor(o->oPosX, o->oPosY, o->oPosZ, &floor);
return floor;
@ -1483,11 +1524,13 @@ void apply_drag_to_value(f32 *value, f32 dragStrength) {
}
void cur_obj_apply_drag_xz(f32 dragStrength) {
if (!o) { return; }
apply_drag_to_value(&o->oVelX, dragStrength);
apply_drag_to_value(&o->oVelZ, dragStrength);
}
s32 cur_obj_move_xz(f32 steepSlopeNormalY, s32 careAboutEdgesAndSteepSlopes) {
if (!o) { return 0; }
struct Surface *intendedFloor = NULL;
f32 intendedX = o->oPosX + o->oVelX;
@ -1547,6 +1590,7 @@ s32 cur_obj_move_xz(f32 steepSlopeNormalY, s32 careAboutEdgesAndSteepSlopes) {
}
void cur_obj_move_update_underwater_flags(void) {
if (!o) { return; }
f32 decelY = (f32)(sqrtf(o->oVelY * o->oVelY) * (o->oDragStrength * 7.0f)) / 100.0L;
if (o->oVelY > 0) {
@ -1564,6 +1608,7 @@ void cur_obj_move_update_underwater_flags(void) {
}
void cur_obj_move_update_ground_air_flags(UNUSED f32 gravity, f32 bounciness) {
if (!o) { return; }
o->oMoveFlags &= ~OBJ_MOVE_BOUNCE;
if (o->oPosY < o->oFloorHeight) {
@ -1599,6 +1644,7 @@ void cur_obj_move_update_ground_air_flags(UNUSED f32 gravity, f32 bounciness) {
}
f32 cur_obj_move_y_and_get_water_level(f32 gravity, f32 buoyancy) {
if (!o) { return 0; }
f32 waterLevel;
o->oVelY += gravity + buoyancy;
@ -1617,6 +1663,7 @@ f32 cur_obj_move_y_and_get_water_level(f32 gravity, f32 buoyancy) {
}
void cur_obj_move_y(f32 gravity, f32 bounciness, f32 buoyancy) {
if (!o) { return; }
f32 waterLevel;
o->oMoveFlags &= ~OBJ_MOVE_LEFT_GROUND;
@ -1670,6 +1717,7 @@ static void stub_obj_helpers_1(void) {
}
void cur_obj_unused_resolve_wall_collisions(f32 offsetY, f32 radius) {
if (!o) { return; }
if (radius > 0.1L) {
f32_find_wall_collision(&o->oPosX, &o->oPosY, &o->oPosZ, offsetY, radius);
}
@ -1690,6 +1738,7 @@ s16 abs_angle_diff(s16 x0, s16 x1) {
}
void cur_obj_move_xz_using_fvel_and_yaw(void) {
if (!o) { return; }
o->oVelX = o->oForwardVel * sins(o->oMoveAngleYaw);
o->oVelZ = o->oForwardVel * coss(o->oMoveAngleYaw);
@ -1698,6 +1747,7 @@ void cur_obj_move_xz_using_fvel_and_yaw(void) {
}
void cur_obj_move_y_with_terminal_vel(void) {
if (!o) { return; }
if (o->oVelY < -70.0f) {
o->oVelY = -70.0f;
}
@ -1706,6 +1756,7 @@ void cur_obj_move_y_with_terminal_vel(void) {
}
void cur_obj_compute_vel_xz(void) {
if (!o) { return; }
o->oVelX = o->oForwardVel * sins(o->oMoveAngleYaw);
o->oVelZ = o->oForwardVel * coss(o->oMoveAngleYaw);
}
@ -1740,14 +1791,17 @@ s32 obj_check_if_collided_with_object(struct Object *obj1, struct Object *obj2)
}
void cur_obj_set_behavior(const BehaviorScript *behavior) {
if (!o) { return; }
o->behavior = segmented_to_virtual(behavior);
}
void obj_set_behavior(struct Object *obj, const BehaviorScript *behavior) {
if (!obj) { return; }
obj->behavior = segmented_to_virtual(behavior);
}
s32 cur_obj_has_behavior(const BehaviorScript *behavior) {
if (!o) { return 0; }
behavior = smlua_override_behavior(behavior);
if (o->behavior == segmented_to_virtual(behavior)) {
return TRUE;
@ -1767,6 +1821,7 @@ s32 obj_has_behavior(struct Object *obj, const BehaviorScript *behavior) {
}
f32 cur_obj_lateral_dist_from_obj_to_home(struct Object *obj) {
if (!o) { return 0; }
f32 dist;
f32 dx = o->oHomeX - obj->oPosX;
f32 dz = o->oHomeZ - obj->oPosZ;
@ -1776,6 +1831,7 @@ f32 cur_obj_lateral_dist_from_obj_to_home(struct Object *obj) {
}
f32 cur_obj_lateral_dist_from_mario_to_home(void) {
if (!o) { return 0; }
struct Object* player = nearest_player_to_object(o);
if (!player) { return 10000; }
f32 dist;
@ -1787,6 +1843,7 @@ f32 cur_obj_lateral_dist_from_mario_to_home(void) {
}
f32 cur_obj_lateral_dist_to_home(void) {
if (!o) { return 0; }
f32 dist;
f32 dx = o->oHomeX - o->oPosX;
f32 dz = o->oHomeZ - o->oPosZ;
@ -1796,6 +1853,7 @@ f32 cur_obj_lateral_dist_to_home(void) {
}
s32 cur_obj_outside_home_square(f32 halfLength) {
if (!o) { return 0; }
if (o->oHomeX - halfLength > o->oPosX) {
return TRUE;
}
@ -1816,6 +1874,7 @@ s32 cur_obj_outside_home_square(f32 halfLength) {
}
s32 cur_obj_outside_home_rectangle(f32 minX, f32 maxX, f32 minZ, f32 maxZ) {
if (!o) { return 0; }
if (o->oHomeX + minX > o->oPosX) {
return TRUE;
}
@ -1836,6 +1895,7 @@ s32 cur_obj_outside_home_rectangle(f32 minX, f32 maxX, f32 minZ, f32 maxZ) {
}
void cur_obj_set_pos_to_home(void) {
if (!o) { return; }
o->oPosX = o->oHomeX;
o->oPosY = o->oHomeY;
o->oPosZ = o->oHomeZ;
@ -1843,6 +1903,7 @@ void cur_obj_set_pos_to_home(void) {
}
void cur_obj_set_pos_to_home_and_stop(void) {
if (!o) { return; }
cur_obj_set_pos_to_home();
o->oForwardVel = 0;
@ -1850,6 +1911,7 @@ void cur_obj_set_pos_to_home_and_stop(void) {
}
void cur_obj_shake_y(f32 amount) {
if (!o) { return; }
//! Technically could cause a bit of drift, but not much
if (o->oTimer % 2 == 0) {
o->oPosY += amount;
@ -1864,6 +1926,7 @@ void cur_obj_start_cam_event(UNUSED struct Object *obj, s32 cameraEvent) {
}
void set_mario_interact_hoot_if_in_range(UNUSED s32 sp0, UNUSED s32 sp4, f32 sp8) {
if (!o) { return; }
if (o->oDistanceToMario < sp8) {
gMarioObject->oInteractStatus = INT_STATUS_HOOT_GRABBED_BY_MARIO;
}
@ -1880,6 +1943,7 @@ void obj_set_cylboard(struct Object *obj) {
}
void cur_obj_set_billboard_if_vanilla_cam(void) {
if (!o) { return; }
if (configEnableCamera) {
o->header.gfx.node.flags &= ~GRAPH_RENDER_BILLBOARD;
o->header.gfx.node.flags |= GRAPH_RENDER_CYLBOARD;
@ -1904,11 +1968,13 @@ void obj_set_hurtbox_radius_and_height(struct Object *o, f32 radius, f32 height)
}
void cur_obj_set_hitbox_radius_and_height(f32 radius, f32 height) {
if (!o) { return; }
o->hitboxRadius = radius;
o->hitboxHeight = height;
}
void cur_obj_set_hurtbox_radius_and_height(f32 radius, f32 height) {
if (!o) { return; }
o->hurtboxRadius = radius;
o->hurtboxHeight = height;
}
@ -1952,11 +2018,14 @@ void obj_spawn_loot_yellow_coins(struct Object *obj, s32 numCoins, f32 sp28) {
void cur_obj_spawn_loot_coin_at_mario_pos(struct MarioState* m) {
struct Object *coin;
if (o->oNumLootCoins <= 0) {
if (!m) { return; }
if (o && o->oNumLootCoins <= 0) {
return;
}
if (o) {
o->oNumLootCoins--;
}
coin = spawn_object(o, MODEL_YELLOW_COIN, bhvSingleCoinGetsSpawned);
if (coin == NULL) { return; }
@ -1966,6 +2035,7 @@ void cur_obj_spawn_loot_coin_at_mario_pos(struct MarioState* m) {
}
f32 cur_obj_abs_y_dist_to_home(void) {
if (!o) { return 0; }
f32 dist = o->oHomeY - o->oPosY;
if (dist < 0) {
@ -1976,6 +2046,7 @@ f32 cur_obj_abs_y_dist_to_home(void) {
}
s32 cur_obj_advance_looping_anim(void) {
if (!o) { return 0; }
s32 animFrame = o->header.gfx.animInfo.animFrame;
s32 loopEnd = o->header.gfx.animInfo.curAnim->loopEnd;
s32 result;
@ -1994,6 +2065,7 @@ s32 cur_obj_advance_looping_anim(void) {
}
s32 cur_obj_detect_steep_floor(s16 steepAngleDegrees) {
if (!o) { return 0; }
struct Surface *intendedFloor;
f32 intendedX, intendedFloorHeight, intendedZ;
f32 deltaFloorHeight;
@ -2021,6 +2093,7 @@ s32 cur_obj_detect_steep_floor(s16 steepAngleDegrees) {
}
s32 cur_obj_resolve_wall_collisions(void) {
if (!o) { return 0; }
s32 numCollisions;
struct Surface *wall;
struct WallCollisionData collisionData;
@ -2055,6 +2128,7 @@ s32 cur_obj_resolve_wall_collisions(void) {
}
void cur_obj_update_floor(void) {
if (!o) { return; }
struct Surface *floor = cur_obj_update_floor_height_and_get_floor();
o->oFloor = floor;
@ -2078,6 +2152,7 @@ void cur_obj_update_floor(void) {
}
void cur_obj_update_floor_and_resolve_wall_collisions(s16 steepSlopeDegrees) {
if (!o) { return; }
#ifdef VERSION_JP
o->oMoveFlags &= ~OBJ_MOVE_ABOVE_LAVA;
#else
@ -2114,6 +2189,7 @@ void cur_obj_update_floor_and_walls(void) {
}
void cur_obj_move_standard(s16 steepSlopeAngleDegrees) {
if (!o) { return; }
f32 gravity = o->oGravity;
f32 bounciness = o->oBounciness;
f32 buoyancy = o->oBuoyancy;
@ -2154,6 +2230,7 @@ void cur_obj_move_standard(s16 steepSlopeAngleDegrees) {
}
s32 cur_obj_within_12k_bounds(void) {
if (!o) { return 0; }
if (o->oPosX < -12000.0f || 12000.0f < o->oPosX) {
return FALSE;
}
@ -2170,6 +2247,7 @@ s32 cur_obj_within_12k_bounds(void) {
}
void cur_obj_move_using_vel_and_gravity(void) {
if (!o) { return; }
//if (cur_obj_within_12k_bounds()) {
o->oPosX += o->oVelX;
o->oPosZ += o->oVelZ;
@ -2185,6 +2263,7 @@ void cur_obj_move_using_fvel_and_gravity(void) {
void obj_set_pos_relative(struct Object *obj, struct Object *other, f32 dleft, f32 dy,
f32 dforward) {
if (!obj || !other) { return; }
f32 facingZ = coss(other->oMoveAngleYaw);
f32 facingX = sins(other->oMoveAngleYaw);
@ -2199,6 +2278,7 @@ void obj_set_pos_relative(struct Object *obj, struct Object *other, f32 dleft, f
}
s16 cur_obj_angle_to_home(void) {
if (!o) { return 0; }
s16 angle;
f32 dx = o->oHomeX - o->oPosX;
f32 dz = o->oHomeZ - o->oPosZ;
@ -2208,6 +2288,7 @@ s16 cur_obj_angle_to_home(void) {
}
void obj_set_gfx_pos_at_obj_pos(struct Object *obj1, struct Object *obj2) {
if (!obj1 || !obj2) { return; }
obj1->header.gfx.pos[0] = obj2->oPosX;
obj1->header.gfx.pos[1] = obj2->oPosY + obj2->oGraphYOffset;
obj1->header.gfx.pos[2] = obj2->oPosZ;
@ -2296,24 +2377,28 @@ void obj_create_transform_from_self(struct Object *obj) {
}
void cur_obj_rotate_move_angle_using_vel(void) {
if (!o) { return; }
o->oMoveAnglePitch += o->oAngleVelPitch;
o->oMoveAngleYaw += o->oAngleVelYaw;
o->oMoveAngleRoll += o->oAngleVelRoll;
}
void cur_obj_rotate_face_angle_using_vel(void) {
if (!o) { return; }
o->oFaceAnglePitch += o->oAngleVelPitch;
o->oFaceAngleYaw += o->oAngleVelYaw;
o->oFaceAngleRoll += o->oAngleVelRoll;
}
void cur_obj_set_face_angle_to_move_angle(void) {
if (!o) { return; }
o->oFaceAnglePitch = o->oMoveAnglePitch;
o->oFaceAngleYaw = o->oMoveAngleYaw;
o->oFaceAngleRoll = o->oMoveAngleRoll;
}
s32 cur_obj_follow_path(UNUSED s32 unusedArg) {
if (!o) { return 0; }
struct Waypoint *startWaypoint;
struct Waypoint *lastWaypoint;
struct Waypoint *targetWaypoint;
@ -2378,6 +2463,7 @@ s32 cur_obj_follow_path(UNUSED s32 unusedArg) {
}
void chain_segment_init(struct ChainSegment *segment) {
if (!o) { return; }
if (segment == NULL) { return; }
segment->posX = 0.0f;
segment->posY = 0.0f;
@ -2422,6 +2508,7 @@ void obj_build_vel_from_transform(struct Object *a0) {
}
void cur_obj_set_pos_via_transform(void) {
if (!o) { return; }
obj_build_transform_from_pos_and_angle(o, O_PARENT_RELATIVE_POS_INDEX, O_MOVE_ANGLE_INDEX);
obj_build_vel_from_transform(o);
o->oPosX += o->oVelX;
@ -2430,6 +2517,7 @@ void cur_obj_set_pos_via_transform(void) {
}
s16 cur_obj_reflect_move_angle_off_wall(void) {
if (!o) { return 0; }
s16 angle = o->oWallAngle - ((s16) o->oMoveAngleYaw - (s16) o->oWallAngle) + 0x8000;
return angle;
}
@ -2517,6 +2605,7 @@ s32 absi(s32 x) {
}
s32 cur_obj_wait_then_blink(s32 timeUntilBlinking, s32 numBlinks) {
if (!o) { return 0; }
s32 done = FALSE;
s32 timeBlinking;
@ -2558,6 +2647,7 @@ void spawn_mist_particles_with_sound(u32 sp18) {
}
void cur_obj_push_mario_away(f32 radius) {
if (!o) { return; }
for (s32 i = 0; i < MAX_PLAYERS; i++) {
struct Object* player = gMarioStates[i].marioObj;
if (!player) { continue; }
@ -2575,6 +2665,7 @@ void cur_obj_push_mario_away(f32 radius) {
}
void cur_obj_push_mario_away_from_cylinder(f32 radius, f32 extentY) {
if (!o) { return; }
for (s32 i = 0; i < MAX_PLAYERS; i++) {
struct Object* player = gMarioStates[i].marioObj;
if (!player) { continue; }
@ -2600,6 +2691,7 @@ void cur_obj_push_mario_away_from_cylinder(f32 radius, f32 extentY) {
}
void bhv_dust_smoke_loop(void) {
if (!o) { return; }
o->oPosX += o->oVelX;
o->oPosY += o->oVelY;
o->oPosZ += o->oVelZ;
@ -2615,6 +2707,7 @@ static void stub_obj_helpers_2(void) {
}
s32 cur_obj_set_direction_table(s8 *a0) {
if (!o) { return 0; }
o->oToxBoxMovementPattern = a0;
o->oToxBoxMovementStep = 0;
@ -2622,6 +2715,7 @@ s32 cur_obj_set_direction_table(s8 *a0) {
}
s32 cur_obj_progress_direction_table(void) {
if (!o) { return 0; }
s8 spF;
s8 *sp8 = o->oToxBoxMovementPattern;
s32 sp4 = o->oToxBoxMovementStep + 1;
@ -2642,6 +2736,7 @@ void stub_obj_helpers_3(UNUSED s32 sp0, UNUSED s32 sp4) {
}
void cur_obj_scale_over_time(s32 a0, s32 a1, f32 sp10, f32 sp14) {
if (!o) { return; }
f32 sp4 = sp14 - sp10;
f32 sp0 = (f32) o->oTimer / a1;
@ -2659,6 +2754,7 @@ void cur_obj_scale_over_time(s32 a0, s32 a1, f32 sp10, f32 sp14) {
}
void cur_obj_set_pos_to_home_with_debug(void) {
if (!o) { return; }
o->oPosX = o->oHomeX + gDebugInfo[5][0];
o->oPosY = o->oHomeY + gDebugInfo[5][1];
o->oPosZ = o->oHomeZ + gDebugInfo[5][2];
@ -2687,6 +2783,7 @@ s32 cur_obj_is_any_player_on_platform(void) {
}
s32 cur_obj_shake_y_until(s32 cycles, s32 amount) {
if (!o) { return 0; }
if (o->oTimer % 2 != 0) {
o->oPosY -= amount;
} else {
@ -2701,6 +2798,7 @@ s32 cur_obj_shake_y_until(s32 cycles, s32 amount) {
}
s32 cur_obj_move_up_and_down(s32 a0) {
if (!o) { return 0; }
if (a0 >= 4 || a0 < 0) {
return TRUE;
}
@ -2710,6 +2808,7 @@ s32 cur_obj_move_up_and_down(s32 a0) {
}
void cur_obj_call_action_function(void (*actionFunctions[])(void), uint32_t actionFunctionsLength) {
if (!o) { return; }
if (!actionFunctions) { return; }
if ((uint32_t)o->oAction >= actionFunctionsLength) { return; }
void (*actionFunction)(void) = actionFunctions[o->oAction];
@ -2718,6 +2817,7 @@ void cur_obj_call_action_function(void (*actionFunctions[])(void), uint32_t acti
}
struct Object *spawn_star_with_no_lvl_exit(s32 sp20, s32 sp24) {
if (!o) { return NULL; }
struct Object *sp1C = spawn_object(o, MODEL_STAR, bhvSpawnedStarNoLevelExit);
if (sp1C == NULL) { return NULL; }
sp1C->oSparkleSpawnUnk1B0 = sp24;
@ -2738,6 +2838,7 @@ s32 bit_shift_left(s32 a0) {
}
s32 cur_obj_mario_far_away(void) {
if (!o) { return 0; }
for (s32 i = 0; i < MAX_PLAYERS; i++) {
if (!is_player_active(&gMarioStates[i])) { continue; }
struct Object* player = gMarioStates[i].marioObj;
@ -2784,6 +2885,7 @@ static void stub_obj_helpers_5(void) {
}
void bhv_init_room(void) {
if (!o) { return; }
struct Surface *floor;
f32 floorHeight;
@ -2809,6 +2911,7 @@ void bhv_init_room(void) {
}
void cur_obj_enable_rendering_if_mario_in_room(void) {
if (!o) { return; }
if (o->oRoom == -1) { return; }
if (gMarioCurrentRoom == 0) { return; }
@ -2842,6 +2945,7 @@ void cur_obj_enable_rendering_if_mario_in_room(void) {
}
s32 cur_obj_set_hitbox_and_die_if_attacked(struct ObjectHitbox *hitbox, s32 deathSound, s32 noLootCoins) {
if (!o) { return 0; }
s32 interacted = FALSE;
obj_set_hitbox(o, hitbox);
@ -2867,6 +2971,7 @@ s32 cur_obj_set_hitbox_and_die_if_attacked(struct ObjectHitbox *hitbox, s32 deat
void obj_explode_and_spawn_coins(f32 sp18, s32 sp1C) {
if (!o) { return; }
spawn_mist_particles_variable(0, 0, sp18);
spawn_triangle_break_particles(30, 138, 3.0f, 4);
obj_mark_for_deletion(o);
@ -2883,12 +2988,14 @@ void obj_set_collision_data(struct Object *obj, const void *segAddr) {
}
void cur_obj_if_hit_wall_bounce_away(void) {
if (!o) { return; }
if (o->oMoveFlags & OBJ_MOVE_HIT_WALL) {
o->oMoveAngleYaw = o->oWallAngle;
}
}
s32 cur_obj_hide_if_mario_far_away_y(f32 distY) {
if (!o) { return 0; }
if (!gMarioStates[0].marioObj) { return FALSE; }
if (absf(o->oPosY - gMarioStates[0].marioObj->oPosY) < distY * draw_distance_scalar()) {
cur_obj_unhide();
@ -2922,6 +3029,7 @@ s32 geo_offset_klepto_debug(s32 callContext, struct GraphNode *a1, UNUSED s32 sp
}
s32 obj_is_hidden(struct Object *obj) {
if (!obj) { return 0; }
if (obj->header.gfx.node.flags & GRAPH_RENDER_INVISIBLE) {
return TRUE;
} else {
@ -2960,6 +3068,7 @@ void clear_time_stop_flags(s32 flags) {
}
s32 cur_obj_can_mario_activate_textbox(struct MarioState* m, f32 radius, f32 height, UNUSED s32 unused) {
if (!o) { return 0; }
if (!m->visibleToEnemies) { return FALSE; }
if (o->oDistanceToMario < 1500.0f) {
f32 latDistToMario = lateral_dist_between_objects(o, m->marioObj);
@ -2981,6 +3090,7 @@ s32 cur_obj_can_mario_activate_textbox_2(struct MarioState* m, f32 radius, f32 h
}
void cur_obj_end_dialog(struct MarioState* m, s32 dialogFlags, s32 dialogResult) {
if (!o) { return; }
if (m->playerIndex != 0) { return; }
o->oDialogResponse = dialogResult;
@ -2992,6 +3102,7 @@ void cur_obj_end_dialog(struct MarioState* m, s32 dialogFlags, s32 dialogResult)
}
s32 cur_obj_update_dialog(struct MarioState* m, s32 actionArg, s32 dialogFlags, s32 dialogID, UNUSED s32 unused, u8 (*inContinueDialogFunction)(void)) {
if (!o) { return 0; }
s32 dialogResponse = 0;
UNUSED s32 doneTurning = TRUE;
@ -3071,6 +3182,7 @@ s32 cur_obj_update_dialog(struct MarioState* m, s32 actionArg, s32 dialogFlags,
}
s32 cur_obj_update_dialog_with_cutscene(struct MarioState* m, s32 actionArg, s32 dialogFlags, s32 cutsceneTable, s32 dialogID, u8 (*inContinueDialogFunction)(void)) {
if (!o) { return 0; }
s32 dialogResponse = 0;
s32 doneTurning = TRUE;
@ -3152,6 +3264,7 @@ s32 cur_obj_update_dialog_with_cutscene(struct MarioState* m, s32 actionArg, s32
}
s32 cur_obj_has_model(u16 modelID) {
if (!o) { return 0; }
if (modelID >= MAX_LOADED_GRAPH_NODES) { return FALSE; }
if (o->header.gfx.sharedChild == gLoadedGraphNodes[modelID]) {
return TRUE;
@ -3163,6 +3276,7 @@ s32 cur_obj_has_model(u16 modelID) {
}
void cur_obj_align_gfx_with_floor(void) {
if (!o) { return; }
struct Surface *floor;
Vec3f floorNormal;
Vec3f position;
@ -3195,6 +3309,7 @@ s32 mario_is_within_rectangle(s16 minX, s16 maxX, s16 minZ, s16 maxZ) {
}
void cur_obj_shake_screen(s32 shake) {
if (!o) { return; }
set_camera_shake_from_point(shake, o->oPosX, o->oPosY, o->oPosZ);
}
@ -3219,6 +3334,7 @@ s32 obj_attack_collided_from_other_object(struct Object *obj) {
}
s32 cur_obj_was_attacked_or_ground_pounded(void) {
if (!o) { return 0; }
s32 attacked = FALSE;
if ((o->oInteractStatus & INT_STATUS_INTERACTED)
@ -3241,6 +3357,7 @@ void obj_copy_behavior_params(struct Object *dst, struct Object *src) {
}
void cur_obj_init_animation_and_anim_frame(s32 animIndex, s32 animFrame) {
if (!o) { return; }
cur_obj_init_animation_with_sound(animIndex);
o->header.gfx.animInfo.animFrame = animFrame;
}
@ -3256,6 +3373,7 @@ void cur_obj_init_animation_and_extend_if_at_end(s32 animIndex) {
}
s32 cur_obj_check_grabbed_mario(void) {
if (!o) { return 0; }
if (o->oInteractStatus & INT_STATUS_GRABBED_MARIO) {
o->oKingBobombUnk88 = 1;
cur_obj_become_intangible();
@ -3293,15 +3411,20 @@ void cur_obj_unused_play_footstep_sound(s32 animFrame1, s32 animFrame2, s32 soun
void enable_time_stop_including_mario(void) {
gTimeStopState |= TIME_STOP_ENABLED | TIME_STOP_MARIO_AND_DOORS;
if (o) {
o->activeFlags |= ACTIVE_FLAG_INITIATED_TIME_STOP;
}
}
void disable_time_stop_including_mario(void) {
gTimeStopState &= ~(TIME_STOP_ENABLED | TIME_STOP_MARIO_AND_DOORS);
if (o) {
o->activeFlags &= ~ACTIVE_FLAG_INITIATED_TIME_STOP;
}
}
s32 cur_obj_check_interacted(void) {
if (!o) { return 0; }
if (o->oInteractStatus & INT_STATUS_INTERACTED) {
o->oInteractStatus = 0;
return TRUE;
@ -3311,7 +3434,7 @@ s32 cur_obj_check_interacted(void) {
}
void cur_obj_spawn_loot_blue_coin(void) {
if (o->oNumLootCoins >= 5) {
if (o && o->oNumLootCoins >= 5) {
spawn_object(o, MODEL_BLUE_COIN, bhvMrIBlueCoin);
o->oNumLootCoins -= 5;
}
@ -3319,6 +3442,7 @@ void cur_obj_spawn_loot_blue_coin(void) {
#ifndef VERSION_JP
void cur_obj_spawn_star_at_y_offset(f32 targetX, f32 targetY, f32 targetZ, f32 offsetY) {
if (!o) { return; }
f32 objectPosY = o->oPosY;
o->oPosY += offsetY + gDebugInfo[5][0];
spawn_default_star(targetX, targetY, targetZ);
@ -3327,6 +3451,7 @@ void cur_obj_spawn_star_at_y_offset(f32 targetX, f32 targetY, f32 targetZ, f32 o
#endif
void cur_obj_set_home_once(void) {
if (!o) { return; }
if (o->setHome) { return; }
o->setHome = TRUE;
o->oHomeX = o->oPosX;

View file

@ -160,7 +160,7 @@ void queue_rumble_data_object(struct Object* object, s16 a0, s16 a1) {
}
void queue_rumble_data_mario(struct MarioState* m, s16 a0, s16 a1) {
if (m->playerIndex != 0) { return; }
if (!m || m->playerIndex != 0) { return; }
queue_rumble_data(a0, a1);
}
@ -189,7 +189,7 @@ u8 is_rumble_finished_and_queue_empty(void) {
}
void reset_rumble_timers(struct MarioState* m) {
if (m->playerIndex != 0) { return; }
if (!m || m->playerIndex != 0) { return; }
if (gCurrDemoInput != NULL) {
return;
@ -207,7 +207,7 @@ void reset_rumble_timers(struct MarioState* m) {
}
void reset_rumble_timers_2(struct MarioState* m, s32 a0) {
if (m->playerIndex != 0) { return; }
if (!m || m->playerIndex != 0) { return; }
if (gCurrDemoInput != NULL) {
return;

View file

@ -22,6 +22,11 @@
#define MENU_DATA_MAGIC 0x4849
#define SAVE_FILE_MAGIC 0x4441
#define INVALID_FILE_INDEX(_fi) ((u32)_fi >= NUM_SAVE_FILES)
#define INVALID_SRC_SLOT(_ss) ((u32)_ss >= 2)
#define INVALID_LEVEL_NUM(_ln) ((u32)_ln >= LEVEL_COUNT)
#define INVALID_COURSE_INDEX(_ci) ((u32)_ci >= COURSE_STAGES_COUNT)
STATIC_ASSERT(sizeof(struct SaveBuffer) == EEPROM_SIZE, "eeprom buffer size must match");
extern struct SaveBuffer gSaveBuffer;
@ -57,10 +62,9 @@ s8 get_level_course_num(s16 levelNum) {
return (info ? info->courseNum : COURSE_NONE);
}
if (levelNum < 0 || levelNum >= LEVEL_COUNT) {
if (INVALID_LEVEL_NUM(levelNum)) {
return COURSE_NONE;
}
return gLevelToCourseNumTable[levelNum];
}
@ -155,6 +159,8 @@ static s32 write_eeprom_data(void *buffer, s32 size, const uintptr_t baseofs) {
*/
static inline s32 write_eeprom_savefile(const u32 file, const u32 slot, const u32 num) {
if (INVALID_FILE_INDEX(file)) { return 0; }
if (INVALID_SRC_SLOT(slot)) { return 0; }
// calculate the EEPROM address using the file number and slot
const uintptr_t ofs = (u8*)&gSaveBuffer.files[file][slot] - (u8*)&gSaveBuffer;
@ -170,6 +176,7 @@ static inline s32 write_eeprom_savefile(const u32 file, const u32 slot, const u3
}
static inline s32 write_eeprom_menudata(const u32 slot, const u32 num) {
if (INVALID_SRC_SLOT(slot)) { return 0; }
// calculate the EEPROM address using the slot
const uintptr_t ofs = (u8*)&gSaveBuffer.menuData[slot] - (u8*)&gSaveBuffer;
@ -226,7 +233,9 @@ static void add_save_block_signature(void *buffer, s32 size, u16 magic) {
* Copy main menu data from one backup slot to the other slot.
*/
UNUSED static void restore_main_menu_data(s32 srcSlot) {
if (INVALID_SRC_SLOT(srcSlot)) { return; }
s32 destSlot = srcSlot ^ 1;
if (INVALID_SRC_SLOT(destSlot)) { return; }
// Compute checksum on source data
add_save_block_signature(&gSaveBuffer.menuData[srcSlot], sizeof(gSaveBuffer.menuData[srcSlot]), MENU_DATA_MAGIC);
@ -266,10 +275,12 @@ UNUSED static void wipe_main_menu_data(void) {
}
static s32 get_coin_score_age(s32 fileIndex, s32 courseIndex) {
if (INVALID_FILE_INDEX(fileIndex)) { return 0; }
return (gSaveBuffer.menuData[0].coinScoreAges[fileIndex] >> (2 * courseIndex)) & 0x3;
}
static void set_coin_score_age(s32 fileIndex, s32 courseIndex, s32 age) {
if (INVALID_FILE_INDEX(fileIndex)) { return; }
s32 mask = 0x3 << (2 * courseIndex);
gSaveBuffer.menuData[0].coinScoreAges[fileIndex] &= ~mask;
@ -280,6 +291,7 @@ static void set_coin_score_age(s32 fileIndex, s32 courseIndex, s32 age) {
* Mark a coin score for a save file as the newest out of all save files.
*/
static void touch_coin_score_age(s32 fileIndex, s32 courseIndex) {
if (INVALID_FILE_INDEX(fileIndex)) { return; }
s32 i;
u32 age;
u32 currentAge = get_coin_score_age(fileIndex, courseIndex);
@ -301,6 +313,7 @@ static void touch_coin_score_age(s32 fileIndex, s32 courseIndex) {
* Mark all coin scores for a save file as new.
*/
static void touch_high_score_ages(s32 fileIndex) {
if (INVALID_FILE_INDEX(fileIndex)) { return; }
s32 i;
for (i = 0; i < 15; i++) {
@ -312,7 +325,10 @@ static void touch_high_score_ages(s32 fileIndex) {
* Copy save file data from one backup slot to the other slot.
*/
UNUSED static void restore_save_file_data(s32 fileIndex, s32 srcSlot) {
if (INVALID_FILE_INDEX(fileIndex)) { return; }
if (INVALID_SRC_SLOT(srcSlot)) { return; }
s32 destSlot = srcSlot ^ 1;
if (INVALID_SRC_SLOT(destSlot)) { return; }
// Compute checksum on source data
add_save_block_signature(&gSaveBuffer.files[fileIndex][srcSlot],
@ -355,6 +371,7 @@ static void save_file_bswap(struct SaveBuffer *buf) {
}
void save_file_do_save(s32 fileIndex, s8 forceSave) {
if (INVALID_FILE_INDEX(fileIndex)) { return; }
if (gNetworkType != NT_SERVER) {
if (gNetworkType == NT_CLIENT) { network_send_save_file(fileIndex); return; }
else if (gNetworkType == NT_NONE && !forceSave) { return; }
@ -381,8 +398,7 @@ void save_file_do_save(s32 fileIndex, s8 forceSave) {
}
void save_file_erase(s32 fileIndex) {
if (fileIndex < 0 || fileIndex >= NUM_SAVE_FILES)
return;
if (INVALID_FILE_INDEX(fileIndex)) { return; }
touch_high_score_ages(fileIndex);
bzero(&gSaveBuffer.files[fileIndex][0], sizeof(gSaveBuffer.files[fileIndex][0]));
@ -404,6 +420,7 @@ void save_file_reload(u8 load_all) {
}
void save_file_erase_current_backup_save(void) {
if (INVALID_FILE_INDEX(gCurrSaveFileNum-1)) { return; }
if (network_is_server()) {
bzero(&gSaveBuffer.files[gCurrSaveFileNum-1][1], sizeof(gSaveBuffer.files[gCurrSaveFileNum-1][1]));
@ -415,8 +432,8 @@ void save_file_erase_current_backup_save(void) {
//! Needs to be s32 to match on -O2, despite no return value.
BAD_RETURN(s32) save_file_copy(s32 srcFileIndex, s32 destFileIndex) {
if (srcFileIndex < 0 || srcFileIndex >= NUM_SAVE_FILES || destFileIndex < 0 || destFileIndex >= NUM_SAVE_FILES)
return;
if (INVALID_FILE_INDEX(srcFileIndex)) { return; }
if (INVALID_FILE_INDEX(destFileIndex)) { return; }
touch_high_score_ages(destFileIndex);
bcopy(&gSaveBuffer.files[srcFileIndex][0], &gSaveBuffer.files[destFileIndex][0],
@ -486,6 +503,8 @@ void save_file_collect_star_or_key(s16 coinScore, s16 starIndex, u8 fromNetwork)
s32 fileIndex = gCurrSaveFileNum - 1;
s32 courseIndex = gCurrCourseNum - 1;
if (INVALID_FILE_INDEX(fileIndex)) { return; }
if (INVALID_SRC_SLOT(gSaveFileUsingBackupSlot)) { return; }
s32 starFlag = 1 << starIndex;
UNUSED s32 flags = save_file_get_flags();
@ -497,7 +516,7 @@ void save_file_collect_star_or_key(s16 coinScore, s16 starIndex, u8 fromNetwork)
gGotFileCoinHiScore = FALSE;
}
if (courseIndex >= 0 && courseIndex < COURSE_STAGES_COUNT && !fromNetwork) {
if (!INVALID_COURSE_INDEX(courseIndex) && !fromNetwork) {
//! Compares the coin score as a 16 bit value, but only writes the 8 bit
// truncation. This can allow a high score to decrease.
@ -539,6 +558,7 @@ void save_file_collect_star_or_key(s16 coinScore, s16 starIndex, u8 fromNetwork)
}
s32 save_file_exists(s32 fileIndex) {
if (INVALID_FILE_INDEX(fileIndex)) { return 0; }
return (gSaveBuffer.files[fileIndex][0].flags & SAVE_FLAG_FILE_EXISTS) != 0;
}
@ -569,6 +589,7 @@ u32 save_file_get_max_coin_score(s32 courseIndex) {
}
s32 save_file_get_course_star_count(s32 fileIndex, s32 courseIndex) {
if (INVALID_FILE_INDEX(fileIndex)) { return 0; }
s32 i;
s32 count = 0;
u8 flag = 1;
@ -583,8 +604,12 @@ s32 save_file_get_course_star_count(s32 fileIndex, s32 courseIndex) {
}
s32 save_file_get_total_star_count(s32 fileIndex, s32 minCourse, s32 maxCourse) {
if (INVALID_FILE_INDEX(fileIndex)) { return 02; }
s32 count = 0;
if (minCourse < -1) { minCourse = -1; }
if (maxCourse >= COURSE_STAGES_COUNT) { maxCourse = COURSE_STAGES_COUNT; }
// Get standard course star count.
for (; minCourse <= maxCourse; minCourse++) {
count += save_file_get_course_star_count(fileIndex, minCourse);
@ -595,6 +620,8 @@ s32 save_file_get_total_star_count(s32 fileIndex, s32 minCourse, s32 maxCourse)
}
void save_file_set_flags(u32 flags) {
if (INVALID_FILE_INDEX(gCurrSaveFileNum - 1)) { return; }
if (INVALID_SRC_SLOT(gSaveFileUsingBackupSlot)) { return; }
// prevent saving any flag that would make the player hatless on level transition
flags &= ~(SAVE_FLAG_CAP_ON_GROUND | SAVE_FLAG_CAP_ON_KLEPTO | SAVE_FLAG_CAP_ON_MR_BLIZZARD | SAVE_FLAG_CAP_ON_UKIKI);
if (flags == 0) { return; }
@ -605,12 +632,16 @@ void save_file_set_flags(u32 flags) {
}
void save_file_clear_flags(u32 flags) {
if (INVALID_FILE_INDEX(gCurrSaveFileNum - 1)) { return; }
if (INVALID_SRC_SLOT(gSaveFileUsingBackupSlot)) { return; }
gSaveBuffer.files[gCurrSaveFileNum - 1][gSaveFileUsingBackupSlot].flags &= ~flags;
gSaveBuffer.files[gCurrSaveFileNum - 1][gSaveFileUsingBackupSlot].flags |= SAVE_FLAG_FILE_EXISTS;
gSaveFileModified = TRUE;
}
u32 save_file_get_flags(void) {
if (INVALID_FILE_INDEX(gCurrSaveFileNum - 1)) { return 0; }
if (INVALID_SRC_SLOT(gSaveFileUsingBackupSlot)) { return 0; }
if (gCurrCreditsEntry != NULL || gCurrDemoInput != NULL) {
return 0;
}
@ -622,11 +653,13 @@ u32 save_file_get_flags(void) {
* If course is -1, return the bitset of obtained castle secret stars.
*/
u32 save_file_get_star_flags(s32 fileIndex, s32 courseIndex) {
u32 starFlags;
if (INVALID_FILE_INDEX(fileIndex)) { return 0; }
if (INVALID_SRC_SLOT(gSaveFileUsingBackupSlot)) { return 0; }
u32 starFlags = 0;
if (courseIndex == -1) {
starFlags = SAVE_FLAG_TO_STAR_FLAG(gSaveBuffer.files[fileIndex][gSaveFileUsingBackupSlot].flags);
} else {
} else if (!INVALID_COURSE_INDEX(courseIndex)) {
starFlags = gSaveBuffer.files[fileIndex][gSaveFileUsingBackupSlot].courseStars[courseIndex] & 0x7F;
}
@ -638,10 +671,12 @@ u32 save_file_get_star_flags(s32 fileIndex, s32 courseIndex) {
* If course is -1, add to the bitset of obtained castle secret stars.
*/
void save_file_set_star_flags(s32 fileIndex, s32 courseIndex, u32 starFlags) {
if (INVALID_FILE_INDEX(fileIndex)) { return; }
if (INVALID_SRC_SLOT(gSaveFileUsingBackupSlot)) { return; }
if (courseIndex == -1) {
gSaveBuffer.files[fileIndex][gSaveFileUsingBackupSlot].flags |= STAR_FLAG_TO_SAVE_FLAG(starFlags);
network_send_save_set_flag(fileIndex, courseIndex, 0, (STAR_FLAG_TO_SAVE_FLAG(starFlags) | SAVE_FLAG_FILE_EXISTS));
} else {
} else if (!INVALID_COURSE_INDEX(courseIndex)) {
gSaveBuffer.files[fileIndex][gSaveFileUsingBackupSlot].courseStars[courseIndex] |= starFlags;
network_send_save_set_flag(fileIndex, courseIndex, starFlags, SAVE_FLAG_FILE_EXISTS);
}
@ -651,6 +686,9 @@ void save_file_set_star_flags(s32 fileIndex, s32 courseIndex, u32 starFlags) {
}
s32 save_file_get_course_coin_score(s32 fileIndex, s32 courseIndex) {
if (INVALID_FILE_INDEX(fileIndex)) { return 0; }
if (INVALID_SRC_SLOT(gSaveFileUsingBackupSlot)) { return 0; }
if (INVALID_COURSE_INDEX(courseIndex)) { return 0; }
return gSaveBuffer.files[fileIndex][gSaveFileUsingBackupSlot].courseCoinScores[courseIndex];
}
@ -658,6 +696,9 @@ s32 save_file_get_course_coin_score(s32 fileIndex, s32 courseIndex) {
* Return TRUE if the cannon is unlocked in the current course.
*/
s32 save_file_is_cannon_unlocked(void) {
if (INVALID_FILE_INDEX(gCurrSaveFileNum - 1)) { return 0; }
if (INVALID_SRC_SLOT(gSaveFileUsingBackupSlot)) { return 0; }
if (INVALID_COURSE_INDEX(gCurrCourseNum)) { return 0; }
return (gSaveBuffer.files[gCurrSaveFileNum - 1][gSaveFileUsingBackupSlot].courseStars[gCurrCourseNum] & 0x80) != 0;
}
@ -665,6 +706,9 @@ s32 save_file_is_cannon_unlocked(void) {
* Sets the cannon status to unlocked in the current course.
*/
void save_file_set_cannon_unlocked(void) {
if (INVALID_FILE_INDEX(gCurrSaveFileNum - 1)) { return; }
if (INVALID_SRC_SLOT(gSaveFileUsingBackupSlot)) { return; }
if (INVALID_COURSE_INDEX(gCurrCourseNum)) { return; }
gSaveBuffer.files[gCurrSaveFileNum - 1][gSaveFileUsingBackupSlot].courseStars[gCurrCourseNum] |= 0x80;
gSaveBuffer.files[gCurrSaveFileNum - 1][gSaveFileUsingBackupSlot].flags |= SAVE_FLAG_FILE_EXISTS;
gSaveFileModified = TRUE;
@ -672,6 +716,8 @@ void save_file_set_cannon_unlocked(void) {
}
void save_file_set_cap_pos(s16 x, s16 y, s16 z) {
if (INVALID_FILE_INDEX(gCurrSaveFileNum - 1)) { return; }
if (INVALID_SRC_SLOT(gSaveFileUsingBackupSlot)) { return; }
struct SaveFile *saveFile = &gSaveBuffer.files[gCurrSaveFileNum - 1][gSaveFileUsingBackupSlot];
saveFile->capLevel = gCurrLevelNum;
@ -681,6 +727,8 @@ void save_file_set_cap_pos(s16 x, s16 y, s16 z) {
}
s32 save_file_get_cap_pos(Vec3s capPos) {
if (INVALID_FILE_INDEX(gCurrSaveFileNum - 1)) { return 0; }
if (INVALID_SRC_SLOT(gSaveFileUsingBackupSlot)) { return 0; }
struct SaveFile *saveFile = &gSaveBuffer.files[gCurrSaveFileNum - 1][gSaveFileUsingBackupSlot];
s32 flags = save_file_get_flags();
@ -705,6 +753,8 @@ u16 save_file_get_sound_mode(void) {
}
void save_file_move_cap_to_default_location(void) {
if (INVALID_FILE_INDEX(gCurrSaveFileNum - 1)) { return; }
if (INVALID_SRC_SLOT(gSaveFileUsingBackupSlot)) { return; }
if (save_file_get_flags() & SAVE_FLAG_CAP_ON_GROUND || gMarioStates[0].cap == SAVE_FLAG_CAP_ON_GROUND) {
switch (gSaveBuffer.files[gCurrSaveFileNum - 1][gSaveFileUsingBackupSlot].capLevel) {
case LEVEL_SSL:

View file

@ -241,7 +241,7 @@ void draw_skybox_tile_grid(Gfx **dlist, s8 background, s8 player, s8 colorIndex)
if (tileIndex < 0) { tileIndex = 0; }
if (tileIndex > 79) { tileIndex = 79; }
Texture* texture = NULL;
if (background >= 10) {
if (background < 0 || background >= 10) {
texture = gCustomSkyboxPtrList[tileIndex];
} else {
texture = (Texture*)(*(SkyboxTexture *) segmented_to_virtual(sSkyboxTextures[background]))[tileIndex];

View file

@ -16,6 +16,7 @@
* objects. (King Bobomb, Bowser, King Whomp)
*/
void exec_anim_sound_state(struct SoundState *soundStates, u16 maxSoundStates) {
if (!gCurrentObject) { return; }
s32 stateIdx = gCurrentObject->oSoundStateID;
if (stateIdx >= maxSoundStates) { return; }
@ -62,12 +63,14 @@ void create_sound_spawner(s32 soundMagic) {
* separate left/right leg functions that went unused.
*/
void cur_obj_play_sound_1(s32 soundMagic) {
if (!gCurrentObject) { return; }
if (gCurrentObject->header.gfx.node.flags & GRAPH_RENDER_ACTIVE) {
play_sound(soundMagic, gCurrentObject->header.gfx.cameraToObject);
}
}
void cur_obj_play_sound_2(s32 soundMagic) {
if (!gCurrentObject) { return; }
if (gCurrentObject->header.gfx.node.flags & GRAPH_RENDER_ACTIVE) {
play_sound(soundMagic, gCurrentObject->header.gfx.cameraToObject);

View file

@ -352,16 +352,19 @@ u32 allocate_mario_action(u32 actFlags) {
///
f32 get_hand_foot_pos_x(struct MarioState* m, u8 index) {
if (!m) { return 0; }
if (index >= 4) { index = 0; }
return m->marioBodyState->handFootPos[index][0];
}
f32 get_hand_foot_pos_y(struct MarioState* m, u8 index) {
if (!m) { return 0; }
if (index >= 4) { index = 0; }
return m->marioBodyState->handFootPos[index][1];
}
f32 get_hand_foot_pos_z(struct MarioState* m, u8 index) {
if (!m) { return 0; }
if (index >= 4) { index = 0; }
return m->marioBodyState->handFootPos[index][2];
}

View file

@ -87,11 +87,13 @@ struct Object* spawn_non_sync_object(enum BehaviorId behaviorId, enum ModelExten
}
s32 obj_has_behavior_id(struct Object *o, enum BehaviorId behaviorId) {
if (!o) { return 0; }
const BehaviorScript *behavior = get_behavior_from_id(behaviorId);
return o->behavior == smlua_override_behavior(behavior);
}
s32 obj_has_model_extended(struct Object *o, enum ModelExtendedId modelId) {
if (!o) { return 0; }
u16 slot = smlua_model_util_load(modelId);
if (slot >= MAX_LOADED_GRAPH_NODES) { return false; }
struct GraphNode *model = gLoadedGraphNodes[slot];
@ -99,6 +101,7 @@ s32 obj_has_model_extended(struct Object *o, enum ModelExtendedId modelId) {
}
void obj_set_model_extended(struct Object *o, enum ModelExtendedId modelId) {
if (!o) { return; }
obj_set_model(o, smlua_model_util_load(modelId));
}
@ -138,6 +141,7 @@ struct Object *obj_get_first_with_behavior_id(enum BehaviorId behaviorId) {
}
struct Object *obj_get_first_with_behavior_id_and_field_s32(enum BehaviorId behaviorId, s32 fieldIndex, s32 value) {
if (fieldIndex < 0 || fieldIndex >= 0x50) { return NULL; }
const BehaviorScript* behavior = get_behavior_from_id(behaviorId);
u32 sanityDepth = 0;
behavior = smlua_override_behavior(behavior);
@ -154,6 +158,7 @@ struct Object *obj_get_first_with_behavior_id_and_field_s32(enum BehaviorId beha
}
struct Object *obj_get_first_with_behavior_id_and_field_f32(enum BehaviorId behaviorId, s32 fieldIndex, f32 value) {
if (fieldIndex < 0 || fieldIndex >= 0x50) { return NULL; }
const BehaviorScript* behavior = get_behavior_from_id(behaviorId);
behavior = smlua_override_behavior(behavior);
if (behavior) {
@ -227,6 +232,7 @@ struct Object *obj_get_next_with_same_behavior_id(struct Object *o) {
}
struct Object *obj_get_next_with_same_behavior_id_and_field_s32(struct Object *o, s32 fieldIndex, s32 value) {
if (fieldIndex < 0 || fieldIndex >= 0x50) { return NULL; }
if (o) {
for (struct Object *obj = obj_get_next(o); obj != NULL; obj = obj_get_next(obj)) {
if (obj->behavior == o->behavior && obj->activeFlags != ACTIVE_FLAG_DEACTIVATED && obj->OBJECT_FIELD_S32(fieldIndex) == value) {
@ -238,6 +244,7 @@ struct Object *obj_get_next_with_same_behavior_id_and_field_s32(struct Object *o
}
struct Object *obj_get_next_with_same_behavior_id_and_field_f32(struct Object *o, s32 fieldIndex, f32 value) {
if (fieldIndex < 0 || fieldIndex >= 0x50) { return NULL; }
if (o) {
for (struct Object *obj = obj_get_next(o); obj != NULL; obj = obj_get_next(obj)) {
if (obj->behavior == o->behavior && obj->activeFlags != ACTIVE_FLAG_DEACTIVATED && obj->OBJECT_FIELD_F32(fieldIndex) == value) {
@ -401,6 +408,7 @@ void obj_move_xyz(struct Object *o, f32 dx, f32 dy, f32 dz) {
void set_whirlpools(f32 x, f32 y, f32 z, s16 strength, s16 area, s32 index) {
static struct Whirlpool whirlpool;
if (index < 0 || index >= 2) { return; }
gAreas[area].whirlpools[index] = &whirlpool;
gAreas[area].whirlpools[index]->pos[0] = x;
@ -411,6 +419,7 @@ void set_whirlpools(f32 x, f32 y, f32 z, s16 strength, s16 area, s32 index) {
#ifdef DEVELOPMENT
void obj_randomize(struct Object* o) {
if (!o) { return; }
for (int i = 0; i < 80; i++) {
if (rand() % 10 < 5) {
o->rawData.asU32[i] = rand() % 10;