mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2025-12-11 10:32:30 +00:00
Prevent even more possible crashes from the mod api
This commit is contained in:
parent
f785050ccb
commit
039be71266
12 changed files with 5735 additions and 6 deletions
|
|
@ -64,6 +64,11 @@ function rnd_number()
|
|||
return t[math.random(#t)]
|
||||
end
|
||||
|
||||
function rnd_boolean()
|
||||
t = { nil, false, true }
|
||||
return t[math.random(#t)]
|
||||
end
|
||||
|
||||
function rnd_Vec3s()
|
||||
t = { nil, { x = rnd_integer(), y = rnd_integer(), z = rnd_integer() } }
|
||||
return t[math.random(#t)]
|
||||
|
|
@ -124,18 +129,30 @@ function rnd_PlayerGeometry()
|
|||
return t[math.random(#t)]
|
||||
end
|
||||
|
||||
function rnd_Surface()
|
||||
t = { nil, gMarioStates[0].ceil, gMarioStates[0].floor }
|
||||
return t[math.random(#t)]
|
||||
end
|
||||
|
||||
--------
|
||||
|
||||
function fuzz_functions()
|
||||
-- $[FUNCS]
|
||||
end
|
||||
|
||||
id_bhvFuncs = hook_behavior(nil, OBJ_LIST_DEFAULT, true, fuzz_functions, nil, 'id_bhvFuncs')
|
||||
|
||||
--------
|
||||
|
||||
function fuzz_structs()
|
||||
end
|
||||
|
||||
function update()
|
||||
fuzz_functions()
|
||||
end
|
||||
|
||||
hook_chat_command('fuzz-funcs', 'funcs', fuzz_functions)
|
||||
hook_chat_command('fuzz-structs', 'structs', fuzz_structs)
|
||||
fuzz_functions()
|
||||
print('!')
|
||||
hook_event(HOOK_UPDATE, update)
|
||||
|
||||
spawn_non_sync_object(id_bhvFuncs, E_MODEL_SPINY_BALL, 0, 0, 0, nil)
|
||||
|
|
|
|||
|
|
@ -1762,6 +1762,7 @@ static void update_game_sound(void) {
|
|||
* Called from threads: thread4_sound, thread5_game_loop
|
||||
*/
|
||||
static void seq_player_play_sequence(u8 player, u8 seqId, u16 arg2) {
|
||||
if (player >= SEQUENCE_PLAYERS) { return; }
|
||||
u8 targetVolume;
|
||||
u8 i;
|
||||
|
||||
|
|
@ -1840,6 +1841,8 @@ void fade_volume_scale(u8 player, u8 targetScale, u16 fadeDuration) {
|
|||
*/
|
||||
static void fade_channel_volume_scale(u8 player, u8 channelIndex, u8 targetScale, u16 fadeDuration) {
|
||||
struct ChannelVolumeScaleFade *temp;
|
||||
if (player >= SEQUENCE_PLAYERS) { return; }
|
||||
if (channelIndex >= CHANNELS_MAX) { return; }
|
||||
|
||||
if (gSequencePlayers[player].channels[channelIndex] != &gSequenceChannelNone) {
|
||||
temp = &sVolumeScaleFades[player][channelIndex];
|
||||
|
|
@ -1856,6 +1859,7 @@ static void fade_channel_volume_scale(u8 player, u8 channelIndex, u8 targetScale
|
|||
* Called from threads: thread4_sound, thread5_game_loop (EU only)
|
||||
*/
|
||||
static void fade_seqplayer_channels(u8 player) {
|
||||
if (player >= SEQUENCE_PLAYERS) { return; }
|
||||
// Loop over channels
|
||||
for (u8 i = 0; i < CHANNELS_MAX; i++) {
|
||||
if (gSequencePlayers[player].channels[i] != &gSequenceChannelNone
|
||||
|
|
@ -2260,6 +2264,9 @@ void stop_sound(u32 soundBits, f32 *pos) {
|
|||
sSoundBanks[bank][soundIndex].soundBits = NO_SOUND;
|
||||
soundIndex = 0xff; // break
|
||||
} else {
|
||||
if (soundIndex == sSoundBanks[bank][soundIndex].next) {
|
||||
break;
|
||||
}
|
||||
soundIndex = sSoundBanks[bank][soundIndex].next;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
#define PRELOAD_BANKS 2
|
||||
#define PRELOAD_SEQUENCE 1
|
||||
|
||||
#define IS_SEQUENCE_CHANNEL_VALID(ptr) ((uintptr_t)(ptr) != (uintptr_t)&gSequenceChannelNone)
|
||||
#define IS_SEQUENCE_CHANNEL_VALID(ptr) ((uintptr_t)(ptr) != (uintptr_t)&gSequenceChannelNone && ptr != NULL)
|
||||
|
||||
extern struct Note *gNotes;
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ u8 get_instrument(struct SequenceChannel *seqChannel, u8 instId, struct Instrume
|
|||
struct AdsrSettings *adsr);
|
||||
|
||||
void sequence_channel_init(struct SequenceChannel *seqChannel) {
|
||||
if (!seqChannel) { return; }
|
||||
s32 i;
|
||||
|
||||
seqChannel->enabled = FALSE;
|
||||
|
|
@ -101,6 +102,7 @@ void sequence_channel_init(struct SequenceChannel *seqChannel) {
|
|||
}
|
||||
|
||||
s32 seq_channel_set_layer(struct SequenceChannel *seqChannel, s32 layerIndex) {
|
||||
if (layerIndex >= LAYERS_MAX) { return 0; }
|
||||
struct SequenceChannelLayer *layer;
|
||||
|
||||
if (seqChannel->layers[layerIndex] == NULL) {
|
||||
|
|
@ -167,6 +169,7 @@ void seq_channel_layer_disable(struct SequenceChannelLayer *layer) {
|
|||
}
|
||||
|
||||
void seq_channel_layer_free(struct SequenceChannel *seqChannel, s32 layerIndex) {
|
||||
if (layerIndex >= LAYERS_MAX) { return; }
|
||||
struct SequenceChannelLayer *layer = seqChannel->layers[layerIndex];
|
||||
|
||||
if (layer != NULL) {
|
||||
|
|
@ -189,6 +192,7 @@ void seq_channel_layer_free(struct SequenceChannel *seqChannel, s32 layerIndex)
|
|||
}
|
||||
|
||||
void sequence_channel_disable(struct SequenceChannel *seqChannel) {
|
||||
if (!seqChannel) { return; }
|
||||
for (s32 i = 0; i < LAYERS_MAX; i++) {
|
||||
seq_channel_layer_free(seqChannel, i);
|
||||
}
|
||||
|
|
@ -214,6 +218,7 @@ struct SequenceChannel *allocate_sequence_channel(void) {
|
|||
}
|
||||
|
||||
void sequence_player_init_channels(struct SequencePlayer *seqPlayer, u16 channelBits) {
|
||||
if (!seqPlayer) { return; }
|
||||
for (u32 i = 0; i < CHANNELS_MAX; i++) {
|
||||
if (channelBits & 1) {
|
||||
struct SequenceChannel *seqChannel = seqPlayer->channels[i];
|
||||
|
|
@ -244,6 +249,7 @@ void sequence_player_init_channels(struct SequencePlayer *seqPlayer, u16 channel
|
|||
}
|
||||
|
||||
void sequence_player_disable_channels(struct SequencePlayer *seqPlayer, u16 channelBits) {
|
||||
if (!seqPlayer) { return; }
|
||||
eu_stubbed_printf_0("SUBTRACK DIM\n");
|
||||
for (u32 i = 0; i < CHANNELS_MAX; i++) {
|
||||
if (channelBits & 1) {
|
||||
|
|
@ -272,6 +278,7 @@ void sequence_player_disable_channels(struct SequencePlayer *seqPlayer, u16 chan
|
|||
}
|
||||
|
||||
void sequence_player_init_channels_extended(struct SequencePlayer* seqPlayer, u64 channelBits) {
|
||||
if (!seqPlayer) { return; }
|
||||
LOG_DEBUG("Enabling channels (extended) with corresponding bits %llX", channelBits);
|
||||
|
||||
for (u32 i = 0; i < CHANNELS_MAX; i++) {
|
||||
|
|
@ -309,6 +316,7 @@ void sequence_player_init_channels_extended(struct SequencePlayer* seqPlayer, u6
|
|||
}
|
||||
|
||||
void sequence_player_disable_channels_extended(struct SequencePlayer* seqPlayer, u64 channelBits) {
|
||||
if (!seqPlayer) { return; }
|
||||
LOG_DEBUG("Disabling channels (extended) with corresponding bits %llX", channelBits);
|
||||
|
||||
for (u32 i = 0; i < CHANNELS_MAX; i++) {
|
||||
|
|
@ -331,6 +339,7 @@ void sequence_player_disable_channels_extended(struct SequencePlayer* seqPlayer,
|
|||
}
|
||||
|
||||
void sequence_player_disable_all_channels(struct SequencePlayer *seqPlayer) {
|
||||
if (!seqPlayer) { return; }
|
||||
eu_stubbed_printf_0("SUBTRACK DIM\n");
|
||||
for (u32 i = 0; i < CHANNELS_MAX; i++) {
|
||||
struct SequenceChannel *seqChannel = seqPlayer->channels[i];
|
||||
|
|
@ -352,6 +361,8 @@ void sequence_player_disable_all_channels(struct SequencePlayer *seqPlayer) {
|
|||
}
|
||||
|
||||
void sequence_channel_enable(struct SequencePlayer *seqPlayer, u8 channelIndex, void *script) {
|
||||
if (!seqPlayer) { return; }
|
||||
if (channelIndex >= CHANNELS_MAX) { return; }
|
||||
struct SequenceChannel *seqChannel = seqPlayer->channels[channelIndex];
|
||||
s32 i;
|
||||
if (IS_SEQUENCE_CHANNEL_VALID(seqChannel) == FALSE) {
|
||||
|
|
@ -386,6 +397,7 @@ void sequence_channel_enable(struct SequencePlayer *seqPlayer, u8 channelIndex,
|
|||
}
|
||||
|
||||
void sequence_player_disable(struct SequencePlayer *seqPlayer) {
|
||||
if (!seqPlayer) { return; }
|
||||
LOG_DEBUG("Disabling sequence player %p", seqPlayer);
|
||||
|
||||
sequence_player_disable_all_channels(seqPlayer);
|
||||
|
|
@ -435,6 +447,7 @@ void sequence_player_disable(struct SequencePlayer *seqPlayer) {
|
|||
* Add an item to the end of a list, if it's not already in any list.
|
||||
*/
|
||||
void audio_list_push_back(struct AudioListItem *list, struct AudioListItem *item) {
|
||||
if (!list || !item) { return; }
|
||||
if (item->prev != NULL) {
|
||||
eu_stubbed_printf_0("Error:Same List Add\n");
|
||||
} else {
|
||||
|
|
@ -451,6 +464,7 @@ void audio_list_push_back(struct AudioListItem *list, struct AudioListItem *item
|
|||
* Remove the last item from a list, and return it (or NULL if empty).
|
||||
*/
|
||||
void *audio_list_pop_back(struct AudioListItem *list) {
|
||||
if (!list) { return NULL; }
|
||||
struct AudioListItem *item = list->prev;
|
||||
if (item == list) {
|
||||
return NULL;
|
||||
|
|
@ -2902,6 +2916,7 @@ void process_sequences(UNUSED s32 iterationsRemaining) {
|
|||
}
|
||||
|
||||
void init_sequence_player(u32 player) {
|
||||
if (player >= SEQUENCE_PLAYERS) { return; }
|
||||
struct SequencePlayer *seqPlayer = &gSequencePlayers[player];
|
||||
#if defined(VERSION_EU) || defined(VERSION_SH)
|
||||
sequence_player_disable(seqPlayer);
|
||||
|
|
|
|||
|
|
@ -1269,6 +1269,7 @@ static BhvCommandProc BehaviorCmdTable[BEHAVIOR_CMD_TABLE_MAX] = {
|
|||
|
||||
// Execute the behavior script of the current object, process the object flags, and other miscellaneous code for updating objects.
|
||||
void cur_obj_update(void) {
|
||||
if (!gCurrentObject) { return; }
|
||||
// Don't update if dormant
|
||||
if (gCurrentObject->activeFlags & ACTIVE_FLAG_DORMANT) {
|
||||
gCurrentObject->header.gfx.node.flags &= ~GRAPH_RENDER_ACTIVE;
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ void bhv_spawned_star_loop(void) {
|
|||
}
|
||||
spawn_object(o, MODEL_NONE, bhvSparkleSpawn);
|
||||
} else if (o->oAction == 2) {
|
||||
if (gCamera->cutscene == 0 && gRecentCutscene == 0) {
|
||||
if (gCamera && gCamera->cutscene == 0 && gRecentCutscene == 0) {
|
||||
gMarioStates[0].freeze = 0;
|
||||
clear_time_stop_flags(TIME_STOP_ENABLED | TIME_STOP_MARIO_AND_DOORS);
|
||||
o->activeFlags &= ~ACTIVE_FLAG_INITIATED_TIME_STOP;
|
||||
|
|
|
|||
|
|
@ -2871,6 +2871,7 @@ void transition_to_camera_mode(struct Camera *c, s16 newMode, s16 numFrames) {
|
|||
* @param frames number of frames the transition should last, only used when entering C_UP
|
||||
*/
|
||||
void set_camera_mode(struct Camera *c, s16 mode, s16 frames) {
|
||||
if (!c) { return; }
|
||||
struct LinearTransitionPoint *start = &sModeInfo.transitionStart;
|
||||
struct LinearTransitionPoint *end = &sModeInfo.transitionEnd;
|
||||
|
||||
|
|
@ -5183,6 +5184,7 @@ void clear_cutscene_vars(UNUSED struct Camera *c) {
|
|||
* Start the cutscene, `cutscene`, if it is not already playing.
|
||||
*/
|
||||
void start_cutscene(struct Camera *c, u8 cutscene) {
|
||||
if (!c) { return; }
|
||||
if (c->cutscene != cutscene) {
|
||||
c->cutscene = cutscene;
|
||||
clear_cutscene_vars(c);
|
||||
|
|
@ -11448,6 +11450,7 @@ struct CutsceneSplinePoint sCcmOutsideCreditsSplineFocus[] = {
|
|||
* the duration they want the flag to be active.
|
||||
*/
|
||||
void play_cutscene(struct Camera *c) {
|
||||
if (!c) { return; }
|
||||
UNUSED u32 pad[3];
|
||||
UNUSED s16 unusedYawFocToMario;
|
||||
s16 cutsceneDuration = 0;
|
||||
|
|
@ -11828,6 +11831,7 @@ static UNUSED void unused_rotate_obj_randomly(struct Object *o, f32 pitchRange,
|
|||
* Rotate the object towards the point `point`.
|
||||
*/
|
||||
void obj_rotate_towards_point(struct Object *o, Vec3f point, s16 pitchOff, s16 yawOff, s16 pitchDiv, s16 yawDiv) {
|
||||
if (!o) { return; }
|
||||
f32 dist;
|
||||
s16 pitch, yaw;
|
||||
Vec3f oPos;
|
||||
|
|
|
|||
|
|
@ -127,6 +127,7 @@ extern u8 gLastCollectedStarOrKey;
|
|||
* Returns the type of cap Mario is wearing.
|
||||
*/
|
||||
u32 get_mario_cap_flag(struct Object *capObject) {
|
||||
if (!capObject) { return 0; }
|
||||
const BehaviorScript *script = virtual_to_segmented(0x13, capObject->behavior);
|
||||
|
||||
if (script == bhvNormalCap) {
|
||||
|
|
@ -147,6 +148,7 @@ u32 get_mario_cap_flag(struct Object *capObject) {
|
|||
* in the angular range given towards Mario.
|
||||
*/
|
||||
u32 object_facing_mario(struct MarioState *m, struct Object *o, s16 angleRange) {
|
||||
if (!m || !o) { return FALSE; }
|
||||
f32 dx = m->pos[0] - o->oPosX;
|
||||
f32 dz = m->pos[2] - o->oPosZ;
|
||||
|
||||
|
|
@ -161,6 +163,7 @@ u32 object_facing_mario(struct MarioState *m, struct Object *o, s16 angleRange)
|
|||
}
|
||||
|
||||
s16 mario_obj_angle_to_object(struct MarioState *m, struct Object *o) {
|
||||
if (!m || !o) { return 0; }
|
||||
f32 dx = o->oPosX - m->pos[0];
|
||||
f32 dz = o->oPosZ - m->pos[2];
|
||||
|
||||
|
|
@ -172,6 +175,8 @@ s16 mario_obj_angle_to_object(struct MarioState *m, struct Object *o) {
|
|||
* action, speed, and position.
|
||||
*/
|
||||
static u32 determine_interaction_internal(struct MarioState *m, struct Object *o, u8 isPVP) {
|
||||
if (!m || !o) { return 0; }
|
||||
|
||||
u32 interaction = 0;
|
||||
u32 action = m->action;
|
||||
|
||||
|
|
@ -268,6 +273,7 @@ u32 determine_interaction_pvp(struct MarioState *m, struct Object *o) {
|
|||
* Sets the interaction types for INT_STATUS_INTERACTED, INT_STATUS_WAS_ATTACKED
|
||||
*/
|
||||
u32 attack_object(struct Object *o, s32 interaction) {
|
||||
if (!o) { return 0; }
|
||||
u32 attackType = 0;
|
||||
|
||||
switch (interaction) {
|
||||
|
|
@ -300,6 +306,7 @@ u32 attack_object(struct Object *o, s32 interaction) {
|
|||
}
|
||||
|
||||
void mario_stop_riding_object(struct MarioState *m) {
|
||||
if (!m) { return; }
|
||||
if (m->riddenObj != NULL && m->playerIndex == 0) {
|
||||
m->riddenObj->oInteractStatus = INT_STATUS_STOP_RIDING;
|
||||
if (m->riddenObj->oSyncID != 0) {
|
||||
|
|
@ -311,6 +318,7 @@ void mario_stop_riding_object(struct MarioState *m) {
|
|||
}
|
||||
|
||||
void mario_grab_used_object(struct MarioState *m) {
|
||||
if (!m) { return; }
|
||||
if (m->usedObj == NULL || m->usedObj->oHeldState == HELD_HELD) { return; }
|
||||
if (m->heldObj == NULL && m->usedObj != NULL) {
|
||||
// prevent grabbing a non-grabbable object
|
||||
|
|
@ -467,6 +475,7 @@ u32 able_to_grab_object(struct MarioState *m, UNUSED struct Object *o) {
|
|||
}
|
||||
|
||||
struct Object *mario_get_collided_object(struct MarioState *m, u32 interactType) {
|
||||
if (!m) { return NULL; }
|
||||
s32 i;
|
||||
struct Object *object;
|
||||
|
||||
|
|
@ -482,6 +491,7 @@ struct Object *mario_get_collided_object(struct MarioState *m, u32 interactType)
|
|||
}
|
||||
|
||||
u32 mario_check_object_grab(struct MarioState *m) {
|
||||
if (!m) { return 0; }
|
||||
u32 result = FALSE;
|
||||
const BehaviorScript *script;
|
||||
|
||||
|
|
@ -517,6 +527,7 @@ u32 mario_check_object_grab(struct MarioState *m) {
|
|||
}
|
||||
|
||||
u32 bully_knock_back_mario(struct MarioState *mario) {
|
||||
if (!mario) { return 0; }
|
||||
struct BullyCollisionData marioData;
|
||||
struct BullyCollisionData bullyData;
|
||||
s16 newMarioYaw;
|
||||
|
|
@ -582,6 +593,7 @@ u32 bully_knock_back_mario(struct MarioState *mario) {
|
|||
}
|
||||
|
||||
void bounce_off_object(struct MarioState *m, struct Object *o, f32 velY) {
|
||||
if (!m || !o) { return; }
|
||||
m->pos[1] = o->oPosY + o->hitboxHeight;
|
||||
m->vel[1] = velY;
|
||||
|
||||
|
|
@ -591,11 +603,13 @@ void bounce_off_object(struct MarioState *m, struct Object *o, f32 velY) {
|
|||
}
|
||||
|
||||
void hit_object_from_below(struct MarioState *m, UNUSED struct Object *o) {
|
||||
if (!m) { return; }
|
||||
m->vel[1] = 0.0f;
|
||||
if (m->playerIndex == 0) { set_camera_shake_from_hit(SHAKE_HIT_FROM_BELOW); }
|
||||
}
|
||||
|
||||
static u32 unused_determine_knockback_action(struct MarioState *m) {
|
||||
if (!m) { return 0; }
|
||||
u32 bonkAction;
|
||||
s16 angleToObject = mario_obj_angle_to_object(m, m->interactObj);
|
||||
s16 facingDYaw = angleToObject - m->faceAngle[1];
|
||||
|
|
@ -626,6 +640,7 @@ static u32 unused_determine_knockback_action(struct MarioState *m) {
|
|||
}
|
||||
|
||||
u32 determine_knockback_action(struct MarioState *m, UNUSED s32 arg) {
|
||||
if (!m) { return 0; }
|
||||
if (m->interactObj == NULL) {
|
||||
return sForwardKnockbackActions[0][0];
|
||||
}
|
||||
|
|
@ -720,6 +735,7 @@ u32 determine_knockback_action(struct MarioState *m, UNUSED s32 arg) {
|
|||
}
|
||||
|
||||
void push_mario_out_of_object(struct MarioState *m, struct Object *o, f32 padding) {
|
||||
if (!m || !o) { return; }
|
||||
f32 minDistance = o->hitboxRadius + m->marioObj->hitboxRadius + padding;
|
||||
|
||||
f32 offsetX = m->pos[0] - o->oPosX;
|
||||
|
|
@ -758,6 +774,7 @@ void push_mario_out_of_object(struct MarioState *m, struct Object *o, f32 paddin
|
|||
}
|
||||
|
||||
void bounce_back_from_attack(struct MarioState *m, u32 interaction) {
|
||||
if (!m) { return; }
|
||||
if (interaction & (INT_PUNCH | INT_KICK | INT_TRIP)) {
|
||||
if (m->action == ACT_PUNCHING) {
|
||||
m->action = ACT_MOVE_PUNCHING;
|
||||
|
|
@ -779,6 +796,7 @@ void bounce_back_from_attack(struct MarioState *m, u32 interaction) {
|
|||
}
|
||||
|
||||
u32 should_push_or_pull_door(struct MarioState *m, struct Object *o) {
|
||||
if (!m || !o) { return 0; }
|
||||
f32 dx = o->oPosX - m->pos[0];
|
||||
f32 dz = o->oPosZ - m->pos[2];
|
||||
|
||||
|
|
@ -788,7 +806,7 @@ u32 should_push_or_pull_door(struct MarioState *m, struct Object *o) {
|
|||
}
|
||||
|
||||
u32 take_damage_from_interact_object(struct MarioState *m) {
|
||||
if (m->interactObj == NULL) { return 0; }
|
||||
if (!m || m->interactObj == NULL) { return 0; }
|
||||
s32 shake;
|
||||
s32 damage = m->interactObj->oDamageOrCoinValue;
|
||||
|
||||
|
|
@ -823,6 +841,7 @@ u32 take_damage_from_interact_object(struct MarioState *m) {
|
|||
}
|
||||
|
||||
u32 take_damage_and_knock_back(struct MarioState *m, struct Object *o) {
|
||||
if (!m || !o) { return FALSE; }
|
||||
u32 damage;
|
||||
|
||||
if (!gInteractionInvulnerable && !(m->flags & MARIO_VANISH_CAP)
|
||||
|
|
@ -849,6 +868,7 @@ u32 take_damage_and_knock_back(struct MarioState *m, struct Object *o) {
|
|||
}
|
||||
|
||||
void reset_mario_pitch(struct MarioState *m) {
|
||||
if (!m) { return; }
|
||||
if (m->action == ACT_WATER_JUMP || m->action == ACT_SHOT_FROM_CANNON || m->action == ACT_FLYING) {
|
||||
if (m->playerIndex == 0) {
|
||||
set_camera_mode(m->area->camera, m->area->camera->defMode, 1);
|
||||
|
|
@ -858,6 +878,7 @@ void reset_mario_pitch(struct MarioState *m) {
|
|||
}
|
||||
|
||||
u32 interact_coin(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
|
||||
if (!m || !o) { return FALSE; }
|
||||
if (m != &gMarioStates[0] || (gDjuiInMainMenu && gCurrLevelNum == LEVEL_TTM)) {
|
||||
// only collect locally
|
||||
return FALSE;
|
||||
|
|
@ -883,12 +904,14 @@ u32 interact_coin(struct MarioState *m, UNUSED u32 interactType, struct Object *
|
|||
}
|
||||
|
||||
u32 interact_water_ring(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
|
||||
if (!m || !o) { return FALSE; }
|
||||
m->healCounter += 4 * o->oDamageOrCoinValue;
|
||||
o->oInteractStatus = INT_STATUS_INTERACTED;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
u32 interact_star_or_key(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
|
||||
if (!m || !o) { return FALSE; }
|
||||
// only allow for local player
|
||||
if (m != &gMarioStates[0]) { return FALSE; }
|
||||
|
||||
|
|
@ -992,6 +1015,7 @@ u32 interact_star_or_key(struct MarioState *m, UNUSED u32 interactType, struct O
|
|||
}
|
||||
|
||||
u32 interact_bbh_entrance(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
|
||||
if (!m || !o) { return FALSE; }
|
||||
if (m->playerIndex != 0) { return FALSE; }
|
||||
if (m->action != ACT_BBH_ENTER_SPIN && m->action != ACT_BBH_ENTER_JUMP) {
|
||||
mario_stop_riding_and_holding(m);
|
||||
|
|
@ -1011,6 +1035,7 @@ u32 interact_bbh_entrance(struct MarioState *m, UNUSED u32 interactType, struct
|
|||
}
|
||||
|
||||
u32 interact_warp(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
|
||||
if (!m || !o) { return FALSE; }
|
||||
u32 action;
|
||||
|
||||
if (m != &gMarioStates[0]) {
|
||||
|
|
@ -1057,6 +1082,7 @@ u32 interact_warp(struct MarioState *m, UNUSED u32 interactType, struct Object *
|
|||
}
|
||||
|
||||
u32 display_door_dialog(struct MarioState *m, u32 actionArg) {
|
||||
if (!m) { return FALSE; }
|
||||
if (m != &gMarioStates[0]) { return FALSE; }
|
||||
// ugly hack: save the last place we opened a dialog to prevent dialog spam
|
||||
static f32 lastDialogPosition[3] = { 0 };
|
||||
|
|
@ -1071,6 +1097,7 @@ u32 display_door_dialog(struct MarioState *m, u32 actionArg) {
|
|||
}
|
||||
|
||||
u8 prevent_interact_door(struct MarioState* m, struct Object* o) {
|
||||
if (!m) { return FALSE; }
|
||||
// prevent multiple star/key unlocks on the same door
|
||||
for (s32 i = 0; i < MAX_PLAYERS; i++) {
|
||||
struct MarioState* m2 = &gMarioStates[i];
|
||||
|
|
@ -1087,6 +1114,7 @@ u8 prevent_interact_door(struct MarioState* m, struct Object* o) {
|
|||
}
|
||||
|
||||
u32 interact_warp_door(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
|
||||
if (!m || !o) { return FALSE; }
|
||||
u32 doorAction = 0;
|
||||
u32 saveFlags = save_file_get_flags();
|
||||
s16 warpDoorId = o->oBehParams >> 24;
|
||||
|
|
@ -1179,6 +1207,7 @@ u32 get_door_save_file_flag(struct Object *door) {
|
|||
}
|
||||
|
||||
u32 interact_door(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
|
||||
if (!m || !o) { return FALSE; }
|
||||
if (m->playerIndex != 0 && o == NULL) { return FALSE; }
|
||||
s16 requiredNumStars = o->oBehParams >> 24;
|
||||
s16 numStars = save_file_get_total_star_count(gCurrSaveFileNum - 1, COURSE_MIN - 1, COURSE_MAX - 1);
|
||||
|
|
@ -1259,6 +1288,7 @@ u32 interact_door(struct MarioState *m, UNUSED u32 interactType, struct Object *
|
|||
}
|
||||
|
||||
u32 interact_cannon_base(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
|
||||
if (!m || !o) { return FALSE; }
|
||||
if (o->oAction != 0) { return FALSE; }
|
||||
if (m->playerIndex != 0) { return FALSE; }
|
||||
|
||||
|
|
@ -1275,6 +1305,7 @@ u32 interact_cannon_base(struct MarioState *m, UNUSED u32 interactType, struct O
|
|||
}
|
||||
|
||||
static u8 resolve_player_collision(struct MarioState* m, struct MarioState* m2) {
|
||||
if (!m || !m2) { return FALSE; }
|
||||
// move player outside of other player
|
||||
f32 extentY = m->marioObj->hitboxHeight;
|
||||
f32 radius = m->marioObj->hitboxRadius * 2.0f;
|
||||
|
|
@ -1341,6 +1372,7 @@ u8 determine_player_damage_value(u32 interaction) {
|
|||
}
|
||||
|
||||
u8 player_is_sliding(struct MarioState* m) {
|
||||
if (!m) { return FALSE; }
|
||||
if (m->action & (ACT_FLAG_BUTT_OR_STOMACH_SLIDE | ACT_FLAG_DIVING)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -1378,6 +1410,7 @@ u8 passes_pvp_interaction_checks(struct MarioState* attacker, struct MarioState*
|
|||
}
|
||||
|
||||
u32 interact_player(struct MarioState* m, UNUSED u32 interactType, struct Object* o) {
|
||||
if (!m || !o) { return FALSE; }
|
||||
if (!is_player_active(m)) { return FALSE; }
|
||||
if (gServerSettings.playerInteractions == PLAYER_INTERACTIONS_NONE) { return FALSE; }
|
||||
if (m->action == ACT_JUMBO_STAR_CUTSCENE) { return FALSE; }
|
||||
|
|
@ -1416,6 +1449,7 @@ u32 interact_player(struct MarioState* m, UNUSED u32 interactType, struct Object
|
|||
}
|
||||
|
||||
u32 interact_player_pvp(struct MarioState* attacker, struct MarioState* victim) {
|
||||
if (!attacker || !victim) { return false; }
|
||||
if (!is_player_active(attacker)) { return FALSE; }
|
||||
if (!is_player_active(victim)) { return FALSE; }
|
||||
if (gServerSettings.playerInteractions == PLAYER_INTERACTIONS_NONE) { return FALSE; }
|
||||
|
|
@ -1512,6 +1546,7 @@ u32 interact_player_pvp(struct MarioState* attacker, struct MarioState* victim)
|
|||
}
|
||||
|
||||
u32 interact_igloo_barrier(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
|
||||
if (!m || !o) { return FALSE; }
|
||||
//! Sets used object without changing action (LOTS of interesting glitches,
|
||||
// but unfortunately the igloo barrier is the only object with this interaction
|
||||
// type)
|
||||
|
|
@ -1522,6 +1557,7 @@ u32 interact_igloo_barrier(struct MarioState *m, UNUSED u32 interactType, struct
|
|||
}
|
||||
|
||||
u32 interact_tornado(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
|
||||
if (!m || !o) { return FALSE; }
|
||||
struct Object *marioObj = m->marioObj;
|
||||
|
||||
if (m->action != ACT_TORNADO_TWIRLING && m->action != ACT_SQUISHED) {
|
||||
|
|
@ -1546,6 +1582,7 @@ u32 interact_tornado(struct MarioState *m, UNUSED u32 interactType, struct Objec
|
|||
}
|
||||
|
||||
u32 interact_whirlpool(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
|
||||
if (!m || !o) { return FALSE; }
|
||||
struct Object *marioObj = m->marioObj;
|
||||
|
||||
if (m->action != ACT_CAUGHT_IN_WHIRLPOOL) {
|
||||
|
|
@ -1568,6 +1605,7 @@ u32 interact_whirlpool(struct MarioState *m, UNUSED u32 interactType, struct Obj
|
|||
}
|
||||
|
||||
u32 interact_strong_wind(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
|
||||
if (!m || !o) { return FALSE; }
|
||||
UNUSED struct Object *marioObj = m->marioObj;
|
||||
|
||||
if (m->action != ACT_GETTING_BLOWN) {
|
||||
|
|
@ -1590,6 +1628,7 @@ u32 interact_strong_wind(struct MarioState *m, UNUSED u32 interactType, struct O
|
|||
}
|
||||
|
||||
u32 interact_flame(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
|
||||
if (!m || !o) { return FALSE; }
|
||||
u32 burningAction = ACT_BURNING_JUMP;
|
||||
|
||||
if (!gInteractionInvulnerable && !(m->flags & MARIO_METAL_CAP) && !(m->flags & MARIO_VANISH_CAP)
|
||||
|
|
@ -1619,6 +1658,7 @@ u32 interact_flame(struct MarioState *m, UNUSED u32 interactType, struct Object
|
|||
}
|
||||
|
||||
u32 interact_snufit_bullet(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
|
||||
if (!m || !o) { return FALSE; }
|
||||
if (!gInteractionInvulnerable && !(m->flags & MARIO_VANISH_CAP)) {
|
||||
if (m->flags & MARIO_METAL_CAP) {
|
||||
o->oInteractStatus = INT_STATUS_INTERACTED | INT_STATUS_WAS_ATTACKED;
|
||||
|
|
@ -1644,6 +1684,7 @@ u32 interact_snufit_bullet(struct MarioState *m, UNUSED u32 interactType, struct
|
|||
}
|
||||
|
||||
u32 interact_clam_or_bubba(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
|
||||
if (!m || !o) { return FALSE; }
|
||||
if (o->oInteractionSubtype & INT_SUBTYPE_EATS_MARIO) {
|
||||
o->oInteractStatus = INT_STATUS_INTERACTED;
|
||||
m->interactObj = o;
|
||||
|
|
@ -1660,6 +1701,7 @@ u32 interact_clam_or_bubba(struct MarioState *m, UNUSED u32 interactType, struct
|
|||
}
|
||||
|
||||
u32 interact_bully(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
|
||||
if (!m || !o) { return FALSE; }
|
||||
UNUSED u32 unused;
|
||||
|
||||
u32 interaction;
|
||||
|
|
@ -1704,6 +1746,7 @@ u32 interact_bully(struct MarioState *m, UNUSED u32 interactType, struct Object
|
|||
}
|
||||
|
||||
u32 interact_shock(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
|
||||
if (!m || !o) { return FALSE; }
|
||||
if (!gInteractionInvulnerable && !(m->flags & MARIO_VANISH_CAP)
|
||||
&& !(o->oInteractionSubtype & INT_SUBTYPE_DELAY_INVINCIBILITY)) {
|
||||
u32 actionArg = (m->action & (ACT_FLAG_AIR | ACT_FLAG_ON_POLE | ACT_FLAG_HANGING)) == 0;
|
||||
|
|
@ -1731,6 +1774,7 @@ u32 interact_shock(struct MarioState *m, UNUSED u32 interactType, struct Object
|
|||
}
|
||||
|
||||
static u32 interact_stub(UNUSED struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
|
||||
if (!m || !o) { return FALSE; }
|
||||
if (!(o->oInteractionSubtype & INT_SUBTYPE_DELAY_INVINCIBILITY)) {
|
||||
sDelayInvincTimer = TRUE;
|
||||
}
|
||||
|
|
@ -1738,6 +1782,7 @@ static u32 interact_stub(UNUSED struct MarioState *m, UNUSED u32 interactType, s
|
|||
}
|
||||
|
||||
u32 interact_mr_blizzard(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
|
||||
if (!m || !o) { return FALSE; }
|
||||
if (take_damage_and_knock_back(m, o)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -1750,6 +1795,7 @@ u32 interact_mr_blizzard(struct MarioState *m, UNUSED u32 interactType, struct O
|
|||
}
|
||||
|
||||
u32 interact_hit_from_below(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
|
||||
if (!m || !o) { return FALSE; }
|
||||
UNUSED u32 unused;
|
||||
|
||||
u32 interaction;
|
||||
|
|
@ -1792,6 +1838,7 @@ u32 interact_hit_from_below(struct MarioState *m, UNUSED u32 interactType, struc
|
|||
}
|
||||
|
||||
u32 interact_bounce_top(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
|
||||
if (!m || !o) { return FALSE; }
|
||||
u32 interaction;
|
||||
if (m->flags & MARIO_METAL_CAP) {
|
||||
interaction = INT_FAST_ATTACK_OR_SHELL;
|
||||
|
|
@ -1828,6 +1875,7 @@ u32 interact_bounce_top(struct MarioState *m, UNUSED u32 interactType, struct Ob
|
|||
}
|
||||
|
||||
u32 interact_unknown_08(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
|
||||
if (!m || !o) { return FALSE; }
|
||||
u32 interaction = determine_interaction(m, o);
|
||||
|
||||
if (interaction & INT_PUNCH) {
|
||||
|
|
@ -1845,6 +1893,7 @@ u32 interact_unknown_08(struct MarioState *m, UNUSED u32 interactType, struct Ob
|
|||
}
|
||||
|
||||
u32 interact_damage(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
|
||||
if (!m || !o) { return FALSE; }
|
||||
if (take_damage_and_knock_back(m, o)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -1857,6 +1906,7 @@ u32 interact_damage(struct MarioState *m, UNUSED u32 interactType, struct Object
|
|||
}
|
||||
|
||||
u32 interact_breakable(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
|
||||
if (!m || !o) { return FALSE; }
|
||||
u32 interaction = determine_interaction(m, o);
|
||||
|
||||
if (interaction & INT_ATTACK_NOT_WEAK_FROM_ABOVE) {
|
||||
|
|
@ -1882,6 +1932,7 @@ u32 interact_breakable(struct MarioState *m, UNUSED u32 interactType, struct Obj
|
|||
}
|
||||
|
||||
u32 interact_koopa_shell(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
|
||||
if (!m || !o) { return FALSE; }
|
||||
if (m->playerIndex != 0) { return FALSE; }
|
||||
|
||||
if (o->oInteractStatus & INT_STATUS_INTERACTED) {
|
||||
|
|
@ -1919,6 +1970,7 @@ u32 interact_koopa_shell(struct MarioState *m, UNUSED u32 interactType, struct O
|
|||
}
|
||||
|
||||
u32 check_object_grab_mario(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
|
||||
if (!m || !o) { return FALSE; }
|
||||
if (m != &gMarioStates[0]) { return false; }
|
||||
|
||||
if ((!(m->action & (ACT_FLAG_AIR | ACT_FLAG_INVULNERABLE | ACT_FLAG_ATTACKING)) || !gInteractionInvulnerable)
|
||||
|
|
@ -1944,6 +1996,7 @@ u32 check_object_grab_mario(struct MarioState *m, UNUSED u32 interactType, struc
|
|||
}
|
||||
|
||||
u32 interact_pole(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
|
||||
if (!m || !o) { return FALSE; }
|
||||
s32 actionId = m->action & ACT_ID_MASK;
|
||||
if (actionId >= 0x080 && actionId < 0x0A0) {
|
||||
if (!(m->prevAction & ACT_FLAG_ON_POLE) || m->usedObj != o) {
|
||||
|
|
@ -1992,6 +2045,7 @@ u32 interact_pole(struct MarioState *m, UNUSED u32 interactType, struct Object *
|
|||
}
|
||||
|
||||
u32 interact_hoot(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
|
||||
if (!m || !o) { return FALSE; }
|
||||
s32 actionId = m->action & ACT_ID_MASK;
|
||||
|
||||
if (m != &gMarioStates[0]) { return FALSE; }
|
||||
|
|
@ -2015,6 +2069,7 @@ u32 interact_hoot(struct MarioState *m, UNUSED u32 interactType, struct Object *
|
|||
}
|
||||
|
||||
u32 interact_cap(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
|
||||
if (!m || !o) { return FALSE; }
|
||||
// only allow for local
|
||||
if (m != &gMarioStates[0]) { return FALSE; }
|
||||
|
||||
|
|
@ -2076,6 +2131,7 @@ u32 interact_cap(struct MarioState *m, UNUSED u32 interactType, struct Object *o
|
|||
}
|
||||
|
||||
u32 interact_grabbable(struct MarioState *m, u32 interactType, struct Object *o) {
|
||||
if (!m || !o) { return FALSE; }
|
||||
const BehaviorScript *script = virtual_to_segmented(0x13, o->behavior);
|
||||
|
||||
if (m->playerIndex != 0) { return FALSE; }
|
||||
|
|
@ -2113,6 +2169,7 @@ u32 interact_grabbable(struct MarioState *m, u32 interactType, struct Object *o)
|
|||
}
|
||||
|
||||
u32 mario_can_talk(struct MarioState *m, u32 arg) {
|
||||
if (!m) { return FALSE; }
|
||||
s16 val6;
|
||||
|
||||
if ((m->action & ACT_FLAG_IDLE) != 0x00000000) {
|
||||
|
|
@ -2147,6 +2204,7 @@ u32 mario_can_talk(struct MarioState *m, u32 arg) {
|
|||
#endif
|
||||
|
||||
u32 check_read_sign(struct MarioState *m, struct Object *o) {
|
||||
if (!m || !o) { return FALSE; }
|
||||
if ((m->input & READ_MASK) && mario_can_talk(m, 0) && object_facing_mario(m, o, SIGN_RANGE)) {
|
||||
s16 facingDYaw = (s16)(o->oMoveAngleYaw + 0x8000) - m->faceAngle[1];
|
||||
if (facingDYaw >= -SIGN_RANGE && facingDYaw <= SIGN_RANGE) {
|
||||
|
|
@ -2167,6 +2225,7 @@ u32 check_read_sign(struct MarioState *m, struct Object *o) {
|
|||
}
|
||||
|
||||
u32 check_npc_talk(struct MarioState *m, struct Object *o) {
|
||||
if (!m || !o) { return FALSE; }
|
||||
if ((m->input & READ_MASK) && mario_can_talk(m, 1)) {
|
||||
s16 facingDYaw = mario_obj_angle_to_object(m, o) - m->faceAngle[1];
|
||||
if (facingDYaw >= -0x4000 && facingDYaw <= 0x4000) {
|
||||
|
|
@ -2185,6 +2244,7 @@ u32 check_npc_talk(struct MarioState *m, struct Object *o) {
|
|||
}
|
||||
|
||||
u32 interact_text(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
|
||||
if (!m || !o) { return FALSE; }
|
||||
u32 interact = FALSE;
|
||||
|
||||
if (o->oInteractionSubtype & INT_SUBTYPE_SIGN) {
|
||||
|
|
@ -2199,6 +2259,7 @@ u32 interact_text(struct MarioState *m, UNUSED u32 interactType, struct Object *
|
|||
}
|
||||
|
||||
void check_kick_or_punch_wall(struct MarioState *m) {
|
||||
if (!m) { return; }
|
||||
if (m->flags & (MARIO_PUNCHING | MARIO_KICKING | MARIO_TRIPPING)) {
|
||||
Vec3f detector;
|
||||
detector[0] = m->pos[0] + 50.0f * sins(m->faceAngle[1]);
|
||||
|
|
@ -2226,6 +2287,7 @@ void check_kick_or_punch_wall(struct MarioState *m) {
|
|||
}
|
||||
|
||||
void mario_process_interactions(struct MarioState *m) {
|
||||
if (!m) { return; }
|
||||
sDelayInvincTimer = FALSE;
|
||||
gInteractionInvulnerable = (m->action & ACT_FLAG_INVULNERABLE) || m->invincTimer != 0;
|
||||
|
||||
|
|
@ -2288,7 +2350,7 @@ void mario_process_interactions(struct MarioState *m) {
|
|||
}
|
||||
|
||||
void check_death_barrier(struct MarioState *m) {
|
||||
if (m->playerIndex != 0) { return; }
|
||||
if (!m || m->playerIndex != 0) { return; }
|
||||
|
||||
if (m->pos[1] < m->floorHeight + 2048.0f) {
|
||||
bool allowDeath = true;
|
||||
|
|
@ -2321,6 +2383,7 @@ void check_death_barrier(struct MarioState *m) {
|
|||
}
|
||||
|
||||
void check_lava_boost(struct MarioState *m) {
|
||||
if (!m) { return; }
|
||||
bool allow = true;
|
||||
smlua_call_event_hooks_mario_param_and_int_ret_bool(HOOK_ALLOW_HAZARD_SURFACE, m, HAZARD_TYPE_LAVA_FLOOR, &allow);
|
||||
if (m->action == ACT_BUBBLED || (gServerSettings.enableCheats && gCheats.godMode) || (!allow)) { return; }
|
||||
|
|
@ -2335,6 +2398,7 @@ void check_lava_boost(struct MarioState *m) {
|
|||
}
|
||||
|
||||
void pss_begin_slide(UNUSED struct MarioState *m) {
|
||||
if (!m) { return; }
|
||||
if (!m->visibleToEnemies) { return; }
|
||||
if (!(gHudDisplay.flags & HUD_DISPLAY_FLAG_TIMER)) {
|
||||
level_control_timer(TIMER_CONTROL_SHOW);
|
||||
|
|
@ -2344,6 +2408,7 @@ void pss_begin_slide(UNUSED struct MarioState *m) {
|
|||
}
|
||||
|
||||
void pss_end_slide(struct MarioState *m) {
|
||||
if (!m) { return; }
|
||||
//! This flag isn't set on death or level entry, allowing double star spawn
|
||||
if (gPssSlideStarted) {
|
||||
u16 slideTime = level_control_timer(TIMER_CONTROL_STOP);
|
||||
|
|
@ -2360,6 +2425,7 @@ void pss_end_slide(struct MarioState *m) {
|
|||
}
|
||||
|
||||
void mario_handle_special_floors(struct MarioState *m) {
|
||||
if (!m) { return; }
|
||||
if ((m->action & ACT_GROUP_MASK) == ACT_GROUP_CUTSCENE) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ u16 gLocalBubbleCounter = 0;
|
|||
* Checks if Mario's animation has reached its end point.
|
||||
*/
|
||||
s32 is_anim_at_end(struct MarioState *m) {
|
||||
if (!m) { return FALSE; }
|
||||
struct Object *o = m->marioObj;
|
||||
|
||||
if (o->header.gfx.animInfo.curAnim == NULL) { return TRUE; }
|
||||
|
|
@ -119,6 +120,7 @@ s16 set_mario_animation(struct MarioState *m, s32 targetAnimID) {
|
|||
* slowed down via acceleration.
|
||||
*/
|
||||
s16 set_mario_anim_with_accel(struct MarioState *m, s32 targetAnimID, s32 accel) {
|
||||
if (!m) { return 0; }
|
||||
struct Object *o = m->marioObj;
|
||||
if (!o || !m->animation) { return 0; }
|
||||
struct Animation *targetAnim = m->animation->targetAnim;
|
||||
|
|
@ -212,6 +214,7 @@ s32 is_anim_past_frame(struct MarioState *m, s16 animFrame) {
|
|||
* and returns the animation's flags.
|
||||
*/
|
||||
s16 find_mario_anim_flags_and_translation(struct Object *obj, s32 yaw, Vec3s translation) {
|
||||
if (!obj) { return 0; }
|
||||
f32 dx;
|
||||
f32 dz;
|
||||
|
||||
|
|
@ -238,6 +241,7 @@ s16 find_mario_anim_flags_and_translation(struct Object *obj, s32 yaw, Vec3s tra
|
|||
* Updates Mario's position from his animation's translation.
|
||||
*/
|
||||
void update_mario_pos_for_anim(struct MarioState *m) {
|
||||
if (!m) { return; }
|
||||
Vec3s translation;
|
||||
s16 flags;
|
||||
|
||||
|
|
@ -257,6 +261,7 @@ void update_mario_pos_for_anim(struct MarioState *m) {
|
|||
* Finds the vertical translation from Mario's animation.
|
||||
*/
|
||||
s16 return_mario_anim_y_translation(struct MarioState *m) {
|
||||
if (!m) { return 0; }
|
||||
Vec3s translation = { 0 };
|
||||
find_mario_anim_flags_and_translation(m->marioObj, 0, translation);
|
||||
|
||||
|
|
@ -271,6 +276,7 @@ s16 return_mario_anim_y_translation(struct MarioState *m) {
|
|||
* Plays a sound if if Mario doesn't have the flag being checked.
|
||||
*/
|
||||
void play_sound_if_no_flag(struct MarioState *m, u32 soundBits, u32 flags) {
|
||||
if (!m) { return; }
|
||||
if (!(m->flags & flags)) {
|
||||
play_sound(soundBits, m->marioObj->header.gfx.cameraToObject);
|
||||
m->flags |= flags;
|
||||
|
|
@ -281,6 +287,7 @@ void play_sound_if_no_flag(struct MarioState *m, u32 soundBits, u32 flags) {
|
|||
* Plays a jump sound if one has not been played since the last action change.
|
||||
*/
|
||||
void play_mario_jump_sound(struct MarioState *m) {
|
||||
if (!m) { return; }
|
||||
if (!(m->flags & MARIO_MARIO_SOUND_PLAYED)) {
|
||||
#ifndef VERSION_JP
|
||||
if (m->action == ACT_TRIPLE_JUMP) {
|
||||
|
|
@ -655,6 +662,7 @@ void resolve_and_return_wall_collisions_data(Vec3f pos, f32 offset, f32 radius,
|
|||
* Finds the ceiling from a vec3f horizontally and a height (with 80 vertical buffer).
|
||||
*/
|
||||
f32 vec3f_find_ceil(Vec3f pos, f32 height, struct Surface **ceil) {
|
||||
if (!ceil) { return 0; }
|
||||
UNUSED f32 unused;
|
||||
|
||||
return find_ceil(pos[0], height + 80.0f, pos[2], ceil);
|
||||
|
|
@ -666,6 +674,7 @@ f32 vec3f_find_ceil(Vec3f pos, f32 height, struct Surface **ceil) {
|
|||
*/
|
||||
// Prevent exposed ceilings
|
||||
f32 vec3f_mario_ceil(Vec3f pos, f32 height, struct Surface **ceil) {
|
||||
if (!ceil) { return 0; }
|
||||
if (gLevelValues.fixCollisionBugs) {
|
||||
height = MAX(height + 80.0f, pos[1] - 2);
|
||||
return find_ceil(pos[0], height, pos[2], ceil);
|
||||
|
|
@ -678,6 +687,7 @@ f32 vec3f_mario_ceil(Vec3f pos, f32 height, struct Surface **ceil) {
|
|||
* Determines if Mario is facing "downhill."
|
||||
*/
|
||||
s32 mario_facing_downhill(struct MarioState *m, s32 turnYaw) {
|
||||
if (!m) { return 0; }
|
||||
s16 faceAngleYaw = m->faceAngle[1];
|
||||
|
||||
// This is never used in practice, as turnYaw is
|
||||
|
|
@ -695,6 +705,8 @@ s32 mario_facing_downhill(struct MarioState *m, s32 turnYaw) {
|
|||
* Determines if a surface is slippery based on the surface class.
|
||||
*/
|
||||
u32 mario_floor_is_slippery(struct MarioState *m) {
|
||||
if (!m) { return FALSE; }
|
||||
|
||||
f32 normY;
|
||||
|
||||
if ((m->area->terrainType & TERRAIN_MASK) == TERRAIN_SLIDE
|
||||
|
|
@ -728,6 +740,7 @@ u32 mario_floor_is_slippery(struct MarioState *m) {
|
|||
* Determines if a surface is a slope based on the surface class.
|
||||
*/
|
||||
s32 mario_floor_is_slope(struct MarioState *m) {
|
||||
if (!m) { return FALSE; }
|
||||
f32 normY;
|
||||
|
||||
if ((m->area->terrainType & TERRAIN_MASK) == TERRAIN_SLIDE
|
||||
|
|
@ -760,6 +773,7 @@ s32 mario_floor_is_slope(struct MarioState *m) {
|
|||
* Determines if a surface is steep based on the surface class.
|
||||
*/
|
||||
s32 mario_floor_is_steep(struct MarioState *m) {
|
||||
if (!m) { return FALSE; }
|
||||
f32 normY;
|
||||
s32 result = FALSE;
|
||||
|
||||
|
|
@ -913,6 +927,7 @@ void set_mario_y_vel_based_on_fspeed(struct MarioState *m, f32 initialVelY, f32
|
|||
* Transitions for a variety of airborne actions.
|
||||
*/
|
||||
static u32 set_mario_action_airborne(struct MarioState *m, u32 action, u32 actionArg) {
|
||||
if (!m) { return FALSE; }
|
||||
f32 fowardVel;
|
||||
|
||||
if ((m->squishTimer != 0 || m->quicksandDepth >= 1.0f)
|
||||
|
|
@ -1033,6 +1048,7 @@ static u32 set_mario_action_airborne(struct MarioState *m, u32 action, u32 actio
|
|||
* Transitions for a variety of moving actions.
|
||||
*/
|
||||
static u32 set_mario_action_moving(struct MarioState *m, u32 action, UNUSED u32 actionArg) {
|
||||
if (!m) { return FALSE; }
|
||||
s16 floorClass = mario_get_floor_class(m);
|
||||
f32 forwardVel = m->forwardVel;
|
||||
f32 mag = min(m->intendedMag, 8.0f);
|
||||
|
|
@ -1078,6 +1094,7 @@ static u32 set_mario_action_moving(struct MarioState *m, u32 action, UNUSED u32
|
|||
* Transition for certain submerged actions, which is actually just the metal jump actions.
|
||||
*/
|
||||
static u32 set_mario_action_submerged(struct MarioState *m, u32 action, UNUSED u32 actionArg) {
|
||||
if (!m) { return FALSE; }
|
||||
if (action == ACT_METAL_WATER_JUMP || action == ACT_HOLD_METAL_WATER_JUMP) {
|
||||
m->vel[1] = 32.0f;
|
||||
}
|
||||
|
|
@ -1089,6 +1106,7 @@ static u32 set_mario_action_submerged(struct MarioState *m, u32 action, UNUSED u
|
|||
* Transitions for a variety of cutscene actions.
|
||||
*/
|
||||
static u32 set_mario_action_cutscene(struct MarioState *m, u32 action, UNUSED u32 actionArg) {
|
||||
if (!m) { return FALSE; }
|
||||
switch (action) {
|
||||
case ACT_EMERGE_FROM_PIPE:
|
||||
m->vel[1] = 52.0f;
|
||||
|
|
@ -1459,6 +1477,7 @@ void update_mario_button_inputs(struct MarioState *m) {
|
|||
* Updates the joystick intended magnitude.
|
||||
*/
|
||||
void update_mario_joystick_inputs(struct MarioState *m) {
|
||||
if (!m) { return; }
|
||||
struct Controller *controller = m->controller;
|
||||
f32 mag = ((controller->stickMag / 64.0f) * (controller->stickMag / 64.0f)) * 64.0f;
|
||||
|
||||
|
|
@ -1490,6 +1509,7 @@ void update_mario_joystick_inputs(struct MarioState *m) {
|
|||
* Resolves wall collisions, and updates a variety of inputs.
|
||||
*/
|
||||
void update_mario_geometry_inputs(struct MarioState *m) {
|
||||
if (!m) { return; }
|
||||
u8 copiedPlayer = FALSE;
|
||||
copyPlayerGoto:;
|
||||
|
||||
|
|
@ -1565,6 +1585,7 @@ copyPlayerGoto:;
|
|||
* Handles Mario's input flags as well as a couple timers.
|
||||
*/
|
||||
void update_mario_inputs(struct MarioState *m) {
|
||||
if (!m) { return; }
|
||||
if (m->playerIndex == 0) { m->input = 0; }
|
||||
|
||||
u8 localIsPaused = (m->playerIndex == 0) && (sCurrPlayMode == PLAY_MODE_PAUSED || m->freeze > 0);
|
||||
|
|
@ -1658,6 +1679,7 @@ void update_mario_inputs(struct MarioState *m) {
|
|||
* Set's the camera preset for submerged action behaviors.
|
||||
*/
|
||||
void set_submerged_cam_preset_and_spawn_bubbles(struct MarioState *m) {
|
||||
if (!m) { return; }
|
||||
f32 heightBelowWater;
|
||||
s16 camPreset;
|
||||
|
||||
|
|
@ -1693,6 +1715,7 @@ void set_submerged_cam_preset_and_spawn_bubbles(struct MarioState *m) {
|
|||
* Both increments and decrements Mario's HP.
|
||||
*/
|
||||
void update_mario_health(struct MarioState *m) {
|
||||
if (!m) { return; }
|
||||
s32 terrainIsSnow;
|
||||
|
||||
if (m->health >= 0x100) {
|
||||
|
|
@ -1761,6 +1784,7 @@ void update_mario_health(struct MarioState *m) {
|
|||
* Updates some basic info for camera usage.
|
||||
*/
|
||||
void update_mario_info_for_cam(struct MarioState *m) {
|
||||
if (!m) { return; }
|
||||
m->marioBodyState->action = m->action;
|
||||
m->statusForCamera->action = m->action;
|
||||
|
||||
|
|
@ -1775,6 +1799,7 @@ void update_mario_info_for_cam(struct MarioState *m) {
|
|||
* Resets Mario's model, done every time an action is executed.
|
||||
*/
|
||||
void mario_reset_bodystate(struct MarioState *m) {
|
||||
if (!m) { return; }
|
||||
struct MarioBodyState *bodyState = m->marioBodyState;
|
||||
|
||||
bodyState->capState = MARIO_HAS_DEFAULT_CAP_OFF;
|
||||
|
|
@ -1790,6 +1815,7 @@ void mario_reset_bodystate(struct MarioState *m) {
|
|||
* Adjusts Mario's graphical height for quicksand.
|
||||
*/
|
||||
void sink_mario_in_quicksand(struct MarioState *m) {
|
||||
if (!m) { return; }
|
||||
struct Object *o = m->marioObj;
|
||||
|
||||
if (o->header.gfx.throwMatrix) {
|
||||
|
|
@ -1812,6 +1838,7 @@ u64 sCapFlickerFrames = 0x4444449249255555;
|
|||
* Updates the cap flags mainly based on the cap timer.
|
||||
*/
|
||||
u32 update_and_return_cap_flags(struct MarioState *m) {
|
||||
if (!m) { return 0; }
|
||||
u32 flags = m->flags;
|
||||
u32 action;
|
||||
|
||||
|
|
@ -1854,6 +1881,7 @@ u32 update_and_return_cap_flags(struct MarioState *m) {
|
|||
* Updates the Mario's cap, rendering, and hitbox.
|
||||
*/
|
||||
void mario_update_hitbox_and_cap_model(struct MarioState *m) {
|
||||
if (!m) { return; }
|
||||
struct MarioBodyState *bodyState = m->marioBodyState;
|
||||
s32 flags = update_and_return_cap_flags(m);
|
||||
|
||||
|
|
@ -1941,6 +1969,7 @@ void queue_particle_rumble(void) {
|
|||
}
|
||||
|
||||
static u8 prevent_hang(u32 hangPreventionActions[], u8* hangPreventionIndex) {
|
||||
if (!hangPreventionActions) { return TRUE; }
|
||||
// save the action sequence
|
||||
hangPreventionActions[*hangPreventionIndex] = gMarioState->action;
|
||||
*hangPreventionIndex = *hangPreventionIndex + 1;
|
||||
|
|
@ -2184,6 +2213,7 @@ s32 execute_mario_action(UNUSED struct Object *o) {
|
|||
}
|
||||
|
||||
s32 force_idle_state(struct MarioState* m) {
|
||||
if (!m) { return 0; }
|
||||
u8 underWater = (m->pos[1] < ((f32)m->waterLevel));
|
||||
return set_mario_action(m, underWater ? ACT_WATER_IDLE : ACT_IDLE, 0);
|
||||
}
|
||||
|
|
@ -2193,6 +2223,7 @@ s32 force_idle_state(struct MarioState* m) {
|
|||
**************************************************/
|
||||
|
||||
void init_single_mario(struct MarioState* m) {
|
||||
if (!m) { return; }
|
||||
|
||||
u16 playerIndex = m->playerIndex;
|
||||
struct SpawnInfo* spawnInfo = &gPlayerSpawnInfos[playerIndex];
|
||||
|
|
@ -2306,6 +2337,7 @@ void init_mario(void) {
|
|||
}
|
||||
|
||||
static void init_mario_single_from_save_file(struct MarioState* m, u16 index) {
|
||||
if (!m) { return; }
|
||||
m->playerIndex = index;
|
||||
m->flags = 0;
|
||||
m->action = 0;
|
||||
|
|
@ -2335,6 +2367,7 @@ void init_mario_from_save_file(void) {
|
|||
}
|
||||
|
||||
void set_mario_particle_flags(struct MarioState* m, u32 flags, u8 clear) {
|
||||
if (!m) { return; }
|
||||
if (m->playerIndex != 0) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -986,6 +986,7 @@ void obj_set_face_angle_to_move_angle(struct Object *obj) {
|
|||
}
|
||||
|
||||
u32 get_object_list_from_behavior(const BehaviorScript *behavior) {
|
||||
if (!behavior) { return OBJ_LIST_DEFAULT; }
|
||||
u32 objectList;
|
||||
|
||||
// If the first behavior command is "begin", then get the object list header
|
||||
|
|
@ -1000,6 +1001,7 @@ u32 get_object_list_from_behavior(const BehaviorScript *behavior) {
|
|||
}
|
||||
|
||||
struct Object *cur_obj_nearest_object_with_behavior(const BehaviorScript *behavior) {
|
||||
if (!behavior) { return NULL; }
|
||||
struct Object *obj;
|
||||
f32 dist;
|
||||
|
||||
|
|
@ -1009,6 +1011,7 @@ struct Object *cur_obj_nearest_object_with_behavior(const BehaviorScript *behavi
|
|||
}
|
||||
|
||||
f32 cur_obj_dist_to_nearest_object_with_behavior(const BehaviorScript *behavior) {
|
||||
if (!behavior) { return 0; }
|
||||
struct Object *obj;
|
||||
f32 dist;
|
||||
|
||||
|
|
|
|||
|
|
@ -530,6 +530,7 @@ static void hud_rotate_and_translate_vec3f(Vec3f vec, Mat4* mtx, Vec3f out) {
|
|||
}
|
||||
|
||||
bool djui_hud_world_pos_to_screen_pos(Vec3f pos, Vec3f out) {
|
||||
if (!gCamera) { return false; }
|
||||
hud_rotate_and_translate_vec3f(pos, &gCamera->mtx, out);
|
||||
if (out[2] >= 0.0f) {
|
||||
return false;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue