Fix several more possible crashes from the Lua API

This commit is contained in:
MysterD 2023-05-15 15:55:16 -07:00
parent ed163203d8
commit 60d70d0d38
28 changed files with 87 additions and 47 deletions

View file

@ -952,9 +952,17 @@ ifeq ($(WINDOWS_BUILD),999)
endif endif
ifeq ($(ASAN),1) ifeq ($(ASAN),1)
EXTRA_CFLAGS += -fsanitize=address -fsanitize=bounds-strict -fsanitize=undefined -ggdb
EXTRA_CPP_FLAGS += -fsanitize=address -fsanitize=bounds-strict -fsanitize=undefined -ggdb ifeq ($(COMPILER),gcc)
LDFLAGS += -fsanitize=address -fsanitize=bounds-strict -fsanitize=undefined -static-libasan 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
else ifeq ($(COMPILER),clang)
EXTRA_CFLAGS += -fsanitize=address -fsanitize=undefined -ggdb
EXTRA_CPP_FLAGS += -fsanitize=address -fsanitize=undefined -ggdb
LDFLAGS += -fsanitize=address -fsanitize=undefined
endif
endif endif
# Coop specific libraries # Coop specific libraries

View file

@ -93,7 +93,7 @@ override_field_immutable = {
"GlobalObjectAnimations": [ "*"], "GlobalObjectAnimations": [ "*"],
"SpawnParticlesInfo": [ "model" ], "SpawnParticlesInfo": [ "model" ],
"MarioBodyState": [ "updateTorsoTime" ], "MarioBodyState": [ "updateTorsoTime" ],
"Area": [ "localAreaTimer", "nextSyncID", "unk04" ], "Area": [ "localAreaTimer", "nextSyncID", "unk04", "objectSpawnInfos", "paintingWarpNodes", "warpNodes" ],
"Mod": [ "*" ], "Mod": [ "*" ],
"ModFile": [ "*" ], "ModFile": [ "*" ],
"BassAudio": [ "*" ], "BassAudio": [ "*" ],

View file

@ -84,6 +84,9 @@ void DynOS_Anim_Swap(void *aPtr) {
if (_AnimIndex == -1) { if (_AnimIndex == -1) {
return; return;
} }
if (_AnimIndex >= _GfxData->mAnimationTable.Count()) {
return;
}
// Animation data // Animation data
const AnimData *_AnimData = (const AnimData *) _GfxData->mAnimationTable[_AnimIndex].second; const AnimData *_AnimData = (const AnimData *) _GfxData->mAnimationTable[_AnimIndex].second;

View file

@ -13,7 +13,8 @@ struct ScheduledFreePool {
}; };
static struct DynamicPool* sModelPools[MODEL_POOL_MAX] = { 0 }; static struct DynamicPool* sModelPools[MODEL_POOL_MAX] = { 0 };
static std::map<void*, struct GraphNode*> sModelMap[MODEL_POOL_MAX]; static std::map<void*, struct GraphNode*> sGraphNodeMap[MODEL_POOL_MAX];
static std::map<u32, struct GraphNode*> sModelIdMap;
static std::vector<struct ScheduledFreePool> sPoolsToFree; static std::vector<struct ScheduledFreePool> sPoolsToFree;
struct GraphNode* DynOS_Model_LoadGeo(enum ModelPool aModelPool, void* aAsset) { struct GraphNode* DynOS_Model_LoadGeo(enum ModelPool aModelPool, void* aAsset) {
@ -26,7 +27,7 @@ struct GraphNode* DynOS_Model_LoadGeo(enum ModelPool aModelPool, void* aAsset) {
} }
// check map // check map
auto& map = sModelMap[aModelPool]; auto& map = sGraphNodeMap[aModelPool];
if (map.count(aAsset)) { if (map.count(aAsset)) {
return map[aAsset]; return map[aAsset];
} }
@ -49,7 +50,7 @@ struct GraphNode* DynOS_Model_LoadDl(enum ModelPool aModelPool, u8 aLayer, void*
} }
// check map // check map
auto& map = sModelMap[aModelPool]; auto& map = sGraphNodeMap[aModelPool];
if (map.count(aAsset)) { if (map.count(aAsset)) {
return map[aAsset]; return map[aAsset];
} }
@ -75,7 +76,7 @@ void DynOS_Model_ClearPool(enum ModelPool aModelPool) {
sModelPools[aModelPool] = NULL; sModelPools[aModelPool] = NULL;
// clear map // clear map
auto& map = sModelMap[aModelPool]; auto& map = sGraphNodeMap[aModelPool];
map.clear(); map.clear();
} }

View file

@ -145,12 +145,12 @@
| nextSyncID | `integer` | read-only | | nextSyncID | `integer` | read-only |
| numRedCoins | `integer` | | | numRedCoins | `integer` | |
| numSecrets | `integer` | | | numSecrets | `integer` | |
| objectSpawnInfos | [SpawnInfo](structs.md#SpawnInfo) | | | objectSpawnInfos | [SpawnInfo](structs.md#SpawnInfo) | read-only |
| paintingWarpNodes | [WarpNode](structs.md#WarpNode) | | | paintingWarpNodes | [WarpNode](structs.md#WarpNode) | read-only |
| surfaceRooms | `Pointer` <`integer`> | read-only | | surfaceRooms | `Pointer` <`integer`> | read-only |
| terrainData | `Pointer` <`integer`> | read-only | | terrainData | `Pointer` <`integer`> | read-only |
| terrainType | `integer` | | | terrainType | `integer` | |
| warpNodes | [ObjectWarpNode](structs.md#ObjectWarpNode) | | | warpNodes | [ObjectWarpNode](structs.md#ObjectWarpNode) | read-only |
[:arrow_up_small:](#) [:arrow_up_small:](#)

View file

@ -1064,6 +1064,7 @@ void audio_list_push_front(struct AudioListItem *list, struct AudioListItem *ite
} }
void audio_list_remove(struct AudioListItem *item) { void audio_list_remove(struct AudioListItem *item) {
if (!item) { return; }
// remove 'item' from the list it's in, if any // remove 'item' from the list it's in, if any
if (item->prev == NULL) { if (item->prev == NULL) {
eu_stubbed_printf_0("Already Cut\n"); eu_stubbed_printf_0("Already Cut\n");

View file

@ -25,7 +25,9 @@ static void handle_merry_go_round_music(void) {
struct Object *marioObject = gMarioObjects[0]; struct Object *marioObject = gMarioObjects[0];
u16 marioFloorType = 0; u16 marioFloorType = 0;
find_floor(marioObject->oPosX, marioObject->oPosY, marioObject->oPosZ, &marioFloor); if (marioObject) {
find_floor(marioObject->oPosX, marioObject->oPosY, marioObject->oPosZ, &marioFloor);
}
if (marioFloor != NULL) { if (marioFloor != NULL) {
marioFloorType = marioFloor->type; marioFloorType = marioFloor->type;

View file

@ -130,7 +130,7 @@ static void beta_boo_key_drop(void) {
// Make the key move laterally away from Mario at 3 units/frame // Make the key move laterally away from Mario at 3 units/frame
// (as if he transferred kinetic energy to it) // (as if he transferred kinetic energy to it)
velocityDirection = gMarioObject->oMoveAngleYaw; velocityDirection = gMarioObject ? gMarioObject->oMoveAngleYaw : 0;
velocityMagnitude = 3.0f; velocityMagnitude = 3.0f;
o->oVelX = sins(velocityDirection) * velocityMagnitude; o->oVelX = sins(velocityDirection) * velocityMagnitude;

View file

@ -75,7 +75,7 @@ void bhv_beta_trampoline_top_loop(void) {
// Since the trampoline never moves, this doesn't do anything. // Since the trampoline never moves, this doesn't do anything.
// Maybe they intended to decrease the trampoline's position // Maybe they intended to decrease the trampoline's position
// when Mario's on it in this if statement? // when Mario's on it in this if statement?
if (gMarioObject->platform == o) { if (gMarioObject && gMarioObject->platform == o) {
o->oBetaTrampolineMarioOnTrampoline = TRUE; o->oBetaTrampolineMarioOnTrampoline = TRUE;
} else { } else {
o->oBetaTrampolineMarioOnTrampoline = FALSE; o->oBetaTrampolineMarioOnTrampoline = FALSE;

View file

@ -135,7 +135,7 @@ void bhv_blue_coin_switch_loop(void) {
case BLUE_COIN_SWITCH_ACT_IDLE: case BLUE_COIN_SWITCH_ACT_IDLE:
// If Mario is on the switch and has ground-pounded, // If Mario is on the switch and has ground-pounded,
// recede and get ready to start ticking. // recede and get ready to start ticking.
if (gMarioObject->platform == o) { if (gMarioObject && gMarioObject->platform == o) {
if (determine_interaction(&gMarioStates[0], o) & INT_GROUND_POUND) { if (determine_interaction(&gMarioStates[0], o) & INT_GROUND_POUND) {
// Set to BLUE_COIN_SWITCH_ACT_RECEDING // Set to BLUE_COIN_SWITCH_ACT_RECEDING
o->oAction++; o->oAction++;
@ -164,7 +164,9 @@ void bhv_blue_coin_switch_loop(void) {
// Set to BLUE_COIN_SWITCH_ACT_TICKING // Set to BLUE_COIN_SWITCH_ACT_TICKING
o->oAction++; o->oAction++;
// ??? // ???
o->oPosY = gMarioObject->oPosY - 40.0f; if (gMarioObject) {
o->oPosY = gMarioObject->oPosY - 40.0f;
}
// Spawn particles. There's a function that calls this same function // Spawn particles. There's a function that calls this same function
// with the same arguments, spawn_mist_particles, why didn't they just call that? // with the same arguments, spawn_mist_particles, why didn't they just call that?

View file

@ -1029,7 +1029,7 @@ void bhv_boo_in_castle_loop(void) {
} }
void bhv_boo_boss_spawned_bridge_loop(void) { void bhv_boo_boss_spawned_bridge_loop(void) {
f32 targetY; f32 targetY = 0;
switch (o->oBehParams2ndByte) { switch (o->oBehParams2ndByte) {
case 1: case 1:

View file

@ -75,7 +75,7 @@ void opened_cannon_act_6(void) {
o->oMoveAngleYaw = sins(o->oCannonUnkF4) * 0x4000 + ((s16)(o->oBehParams2ndByte << 8)); o->oMoveAngleYaw = sins(o->oCannonUnkF4) * 0x4000 + ((s16)(o->oBehParams2ndByte << 8));
o->oCannonUnkF4 += 0x400; o->oCannonUnkF4 += 0x400;
} else if (o->oTimer < 26) { } else if (o->oTimer < 26) {
} else if (o->oCannonPlayerIndex < MAX_PLAYERS) { } else if (o->oCannonPlayerIndex >= 0 && o->oCannonPlayerIndex < MAX_PLAYERS) {
struct MarioState* controlledBy = &gMarioStates[o->oCannonPlayerIndex]; struct MarioState* controlledBy = &gMarioStates[o->oCannonPlayerIndex];
if (controlledBy && controlledBy->marioObj != NULL) { if (controlledBy && controlledBy->marioObj != NULL) {
controlledBy->marioObj->oMarioCannonObjectYaw = o->oMoveAngleYaw; controlledBy->marioObj->oMarioCannonObjectYaw = o->oMoveAngleYaw;
@ -110,7 +110,7 @@ void opened_cannon_act_1(void) {
if (o->oCannonPlayerIndex == 0) { if (o->oCannonPlayerIndex == 0) {
cur_obj_become_intangible(); cur_obj_become_intangible();
cur_obj_disable_rendering(); cur_obj_disable_rendering();
} else if (o->oCannonPlayerIndex < MAX_PLAYERS) { } else if (o->oCannonPlayerIndex >= 0 && o->oCannonPlayerIndex < MAX_PLAYERS) {
struct MarioState* controlledBy = &gMarioStates[o->oCannonPlayerIndex]; struct MarioState* controlledBy = &gMarioStates[o->oCannonPlayerIndex];
o->oMoveAnglePitch = 14563 + controlledBy->faceAngle[0] * -0.5f; o->oMoveAnglePitch = 14563 + controlledBy->faceAngle[0] * -0.5f;
if (controlledBy->marioObj != NULL) { if (controlledBy->marioObj != NULL) {

View file

@ -450,7 +450,6 @@ static void chain_chomp_act_move(void) {
*/ */
static void chain_chomp_act_unload_chain(void) { static void chain_chomp_act_unload_chain(void) {
cur_obj_hide(); cur_obj_hide();
dynamic_pool_free(gLevelPool, o->oChainChompSegments);
o->oAction = CHAIN_CHOMP_ACT_UNINITIALIZED; o->oAction = CHAIN_CHOMP_ACT_UNINITIALIZED;

View file

@ -244,7 +244,7 @@ void coin_inside_boo_act_0(void) {
obj_copy_pos(o, parent); obj_copy_pos(o, parent);
if (parent->oBooDeathStatus == BOO_DEATH_STATUS_DYING) { if (parent->oBooDeathStatus == BOO_DEATH_STATUS_DYING) {
o->oAction = 1; o->oAction = 1;
s16 sp26 = gMarioObject->oMoveAngleYaw; s16 sp26 = gMarioObject ? gMarioObject->oMoveAngleYaw : 0;
f32 sp20 = 3.0f; f32 sp20 = 3.0f;
o->oVelX = sins(sp26) * sp20; o->oVelX = sins(sp26) * sp20;
o->oVelZ = coss(sp26) * sp20; o->oVelZ = coss(sp26) * sp20;

View file

@ -8,7 +8,9 @@ void bhv_hidden_star_init(void) {
o->activeFlags = ACTIVE_FLAG_DEACTIVATED; o->activeFlags = ACTIVE_FLAG_DEACTIVATED;
} }
o->oHiddenStarTriggerCounter = gCurrentArea->numSecrets - count; if (gCurrentArea) {
o->oHiddenStarTriggerCounter = gCurrentArea->numSecrets - count;
}
// We haven't interacted with a player yet. // We haven't interacted with a player yet.
// We also don't sync this as not only is it not required // We also don't sync this as not only is it not required
@ -34,7 +36,7 @@ void bhv_hidden_star_init(void) {
void bhv_hidden_star_loop(void) { void bhv_hidden_star_loop(void) {
switch (o->oAction) { switch (o->oAction) {
case 0: case 0:
if (o->oHiddenStarTriggerCounter >= gCurrentArea->numSecrets) { if (gCurrentArea && o->oHiddenStarTriggerCounter >= gCurrentArea->numSecrets) {
o->oAction = 1; o->oAction = 1;
} }
break; break;
@ -63,7 +65,9 @@ void bhv_hidden_star_trigger_loop(void) {
if (hiddenStar != NULL) { if (hiddenStar != NULL) {
s16 count = (count_objects_with_behavior(bhvHiddenStarTrigger) - 1); s16 count = (count_objects_with_behavior(bhvHiddenStarTrigger) - 1);
hiddenStar->oHiddenStarTriggerCounter = gCurrentArea->numSecrets - count; if (gCurrentArea) {
hiddenStar->oHiddenStarTriggerCounter = gCurrentArea->numSecrets - count;
}
spawn_orange_number(hiddenStar->oHiddenStarTriggerCounter, 0, 0, 0); spawn_orange_number(hiddenStar->oHiddenStarTriggerCounter, 0, 0, 0);
// Set the last person who interacted with a secret to the // Set the last person who interacted with a secret to the
@ -98,7 +102,7 @@ void bhv_hidden_star_trigger_loop(void) {
void bhv_bowser_course_red_coin_star_loop(void) { void bhv_bowser_course_red_coin_star_loop(void) {
switch (o->oAction) { switch (o->oAction) {
case 0: case 0:
if (o->oHiddenStarTriggerCounter >= gCurrentArea->numRedCoins) { if (gCurrentArea && o->oHiddenStarTriggerCounter >= gCurrentArea->numRedCoins) {
o->oAction = 1; o->oAction = 1;
} }
break; break;

View file

@ -39,8 +39,9 @@ void bhv_ship_part_3_loop(void) {
o->oFaceAngleRoll = sins(o->oShipPart3UnkF8) * 1024.0f; o->oFaceAngleRoll = sins(o->oShipPart3UnkF8) * 1024.0f;
o->oAngleVelPitch = o->oFaceAnglePitch - sp1E; o->oAngleVelPitch = o->oFaceAnglePitch - sp1E;
o->oAngleVelRoll = o->oFaceAngleRoll - sp1C; o->oAngleVelRoll = o->oFaceAngleRoll - sp1C;
if (gMarioObject->oPosY > 1000.0f) if (gMarioObject && gMarioObject->oPosY > 1000.0f) {
cur_obj_play_sound_1(SOUND_ENV_BOAT_ROCKING1); cur_obj_play_sound_1(SOUND_ENV_BOAT_ROCKING1);
}
} }
void bhv_jrb_sliding_box_loop(void) { void bhv_jrb_sliding_box_loop(void) {
@ -103,13 +104,18 @@ void bhv_jrb_sliding_box_loop(void) {
o->oJrbSlidingBoxUnkFC = sins(o->oJrbSlidingBoxUnkF8) * 20.0f; o->oJrbSlidingBoxUnkFC = sins(o->oJrbSlidingBoxUnkF8) * 20.0f;
o->oJrbSlidingBoxUnkF8 += 0x100; o->oJrbSlidingBoxUnkF8 += 0x100;
o->oParentRelativePosZ += o->oJrbSlidingBoxUnkFC; o->oParentRelativePosZ += o->oJrbSlidingBoxUnkFC;
if (gMarioObject->oPosY > 1000.0f) if (gMarioObject && gMarioObject->oPosY > 1000.0f) {
if (absf(o->oJrbSlidingBoxUnkFC) > 3.0f) if (absf(o->oJrbSlidingBoxUnkFC) > 3.0f) {
cur_obj_play_sound_1(SOUND_AIR_ROUGH_SLIDE); cur_obj_play_sound_1(SOUND_AIR_ROUGH_SLIDE);
}
}
obj_set_hitbox(o, &sSkullSlidingBoxHitbox); obj_set_hitbox(o, &sSkullSlidingBoxHitbox);
if (!(o->oJrbSlidingBoxUnkF8 & 0x7FFF)) if (!(o->oJrbSlidingBoxUnkF8 & 0x7FFF)) {
cur_obj_become_tangible(); cur_obj_become_tangible();
if (obj_check_if_collided_with_object(o, gMarioObject)) { }
if (gMarioObject && obj_check_if_collided_with_object(o, gMarioObject)) {
o->oInteractStatus = 0; o->oInteractStatus = 0;
cur_obj_become_intangible(); cur_obj_become_intangible();
} }

View file

@ -2,9 +2,11 @@
void bhv_pole_base_loop(void) { void bhv_pole_base_loop(void) {
if (!gMarioObject) { return; } if (!gMarioObject) { return; }
if (o->oPosY - 10.0f < gMarioObject->oPosY if (o->oPosY - 10.0f < gMarioObject->oPosY && gMarioObject->oPosY < o->oPosY + o->hitboxHeight + 30.0f) {
&& gMarioObject->oPosY < o->oPosY + o->hitboxHeight + 30.0f) if (o->oTimer > 10) {
if (o->oTimer > 10) if (!(gMarioStates[0].action & MARIO_PUNCHING)) {
if (!(gMarioStates[0].action & MARIO_PUNCHING))
cur_obj_push_mario_away(70.0f); cur_obj_push_mario_away(70.0f);
}
}
}
} }

View file

@ -31,7 +31,7 @@ void bhv_purple_switch_loop(void) {
case PURPLE_SWITCH_IDLE: case PURPLE_SWITCH_IDLE:
cur_obj_set_model(smlua_model_util_load(E_MODEL_PURPLE_SWITCH)); cur_obj_set_model(smlua_model_util_load(E_MODEL_PURPLE_SWITCH));
cur_obj_scale(1.5f); cur_obj_scale(1.5f);
if (gMarioObject->platform == o && !(gMarioStates[0].action & MARIO_UNKNOWN_13)) { if (gMarioObject && gMarioObject->platform == o && !(gMarioStates[0].action & MARIO_UNKNOWN_13)) {
if (lateral_dist_between_objects(o, gMarioObject) < 127.5) { if (lateral_dist_between_objects(o, gMarioObject) < 127.5) {
o->oAction = PURPLE_SWITCH_PRESSED; o->oAction = PURPLE_SWITCH_PRESSED;
network_send_object(o); network_send_object(o);

View file

@ -50,7 +50,9 @@ void bhv_red_coin_loop(void) {
// ...and there is a red coin star in the level... // ...and there is a red coin star in the level...
if (o->parentObj != NULL) { if (o->parentObj != NULL) {
s16 redCoins = count_objects_with_behavior(bhvRedCoin) - 1; s16 redCoins = count_objects_with_behavior(bhvRedCoin) - 1;
o->parentObj->oHiddenStarTriggerCounter = gCurrentArea->numRedCoins - redCoins; if (gCurrentArea) {
o->parentObj->oHiddenStarTriggerCounter = gCurrentArea->numRedCoins - redCoins;
}
// Set the last person who interacted with a red coin to the // Set the last person who interacted with a red coin to the
// parent so only they get the star cutscene. // parent so only they get the star cutscene.

View file

@ -288,7 +288,9 @@ void bhv_hidden_red_coin_star_init(void) {
o->activeFlags = ACTIVE_FLAG_DEACTIVATED; o->activeFlags = ACTIVE_FLAG_DEACTIVATED;
} }
o->oHiddenStarTriggerCounter = gCurrentArea->numRedCoins - redCoins; if (gCurrentArea) {
o->oHiddenStarTriggerCounter = gCurrentArea->numRedCoins - redCoins;
}
// We haven't interacted with a player yet. // We haven't interacted with a player yet.
// We also don't sync this as not only is it not required // We also don't sync this as not only is it not required
@ -313,7 +315,7 @@ void bhv_hidden_red_coin_star_init(void) {
void bhv_hidden_red_coin_star_loop(void) { void bhv_hidden_red_coin_star_loop(void) {
switch (o->oAction) { switch (o->oAction) {
case 0: case 0:
if (o->oHiddenStarTriggerCounter >= gCurrentArea->numRedCoins) { if (gCurrentArea && o->oHiddenStarTriggerCounter >= gCurrentArea->numRedCoins) {
o->oAction = 1; o->oAction = 1;
} }
break; break;

View file

@ -21,7 +21,7 @@ void bhv_wf_elevator_tower_platform_loop(void) {
switch (o->oAction) { switch (o->oAction) {
case 0: case 0:
if (gMarioObject->platform == o) { if (gMarioObject && gMarioObject->platform == o) {
o->oAction++; o->oAction++;
network_send_object(o); network_send_object(o);
} }

View file

@ -66,7 +66,13 @@ void bhv_ttc_treadmill_update(void) {
approach_f32_ptr(&o->oTTCTreadmillSpeed, o->oTTCTreadmillTargetSpeed, 10.0f); approach_f32_ptr(&o->oTTCTreadmillSpeed, o->oTTCTreadmillTargetSpeed, 10.0f);
} }
*o->oTTCTreadmillBigSurface = *o->oTTCTreadmillSmallSurface = o->oTTCTreadmillSpeed; if (o->oTTCTreadmillSmallSurface) {
*o->oTTCTreadmillSmallSurface = o->oTTCTreadmillSpeed;
}
if (o->oTTCTreadmillBigSurface) {
*o->oTTCTreadmillBigSurface = o->oTTCTreadmillSpeed;
}
} }
} }

View file

@ -5429,7 +5429,7 @@ void warp_camera(f32 displacementX, f32 displacementY, f32 displacementZ) {
struct LinearTransitionPoint *start = &sModeInfo.transitionStart; struct LinearTransitionPoint *start = &sModeInfo.transitionStart;
struct LinearTransitionPoint *end = &sModeInfo.transitionEnd; struct LinearTransitionPoint *end = &sModeInfo.transitionEnd;
gCurrLevelArea = gCurrLevelNum * 16 + gCurrentArea->index; gCurrLevelArea = gCurrLevelNum * 16 + (gCurrentArea ? gCurrentArea->index : 0);
displacement[0] = displacementX; displacement[0] = displacementX;
displacement[1] = displacementY; displacement[1] = displacementY;
displacement[2] = displacementZ; displacement[2] = displacementZ;

View file

@ -865,6 +865,7 @@ void update_mario_sound_and_camera(struct MarioState *m) {
// only update for local player // only update for local player
if (m != &gMarioStates[0]) { return; } if (m != &gMarioStates[0]) { return; }
if (!m->area || !m->area->camera) { return; }
u32 action = m->action; u32 action = m->action;
s32 camPreset = m->area->camera->mode; s32 camPreset = m->area->camera->mode;
@ -1332,7 +1333,7 @@ s32 check_common_hold_action_exits(struct MarioState *m) {
*/ */
s32 transition_submerged_to_walking(struct MarioState *m) { s32 transition_submerged_to_walking(struct MarioState *m) {
if (!m) { return FALSE; } if (!m) { return FALSE; }
if (m->playerIndex == 0) { if (m->playerIndex == 0 && m->area && m->area->camera) {
set_camera_mode(m->area->camera, m->area->camera->defMode, 1); set_camera_mode(m->area->camera, m->area->camera->defMode, 1);
} }

View file

@ -3049,8 +3049,7 @@ static s32 check_for_instant_quicksand(struct MarioState *m) {
} }
if (m->action == ACT_BUBBLED) { return FALSE; } if (m->action == ACT_BUBBLED) { return FALSE; }
if (m->floor->type == SURFACE_INSTANT_QUICKSAND && m->action & ACT_FLAG_INVULNERABLE if (m->floor && m->floor->type == SURFACE_INSTANT_QUICKSAND && m->action & ACT_FLAG_INVULNERABLE && m->action != ACT_QUICKSAND_DEATH && m->action != ACT_SHOCKED) {
&& m->action != ACT_QUICKSAND_DEATH && m->action != ACT_SHOCKED) {
update_mario_sound_and_camera(m); update_mario_sound_and_camera(m);
return drop_and_set_mario_action(m, ACT_QUICKSAND_DEATH, 0); return drop_and_set_mario_action(m, ACT_QUICKSAND_DEATH, 0);
} }

View file

@ -696,6 +696,7 @@ void anim_and_audio_for_hold_walk(struct MarioState *m) {
break; break;
default: default:
val08 = FALSE;
break; break;
} }
} }

View file

@ -147,6 +147,7 @@ void apply_water_current(struct MarioState *m, Vec3f step) {
step[2] += currentSpeed * coss(currentAngle); step[2] += currentSpeed * coss(currentAngle);
} }
if (!gCurrentArea) { return; }
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
struct Whirlpool *whirlpool = gCurrentArea->whirlpools[i]; struct Whirlpool *whirlpool = gCurrentArea->whirlpools[i];
if (whirlpool != NULL) { if (whirlpool != NULL) {

View file

@ -72,14 +72,14 @@ static struct LuaObjectField sAreaFields[LUA_AREA_FIELD_COUNT] = {
{ "nextSyncID", LVT_U32, offsetof(struct Area, nextSyncID), true, LOT_NONE }, { "nextSyncID", LVT_U32, offsetof(struct Area, nextSyncID), true, LOT_NONE },
{ "numRedCoins", LVT_U8, offsetof(struct Area, numRedCoins), false, LOT_NONE }, { "numRedCoins", LVT_U8, offsetof(struct Area, numRedCoins), false, LOT_NONE },
{ "numSecrets", LVT_U8, offsetof(struct Area, numSecrets), false, LOT_NONE }, { "numSecrets", LVT_U8, offsetof(struct Area, numSecrets), false, LOT_NONE },
{ "objectSpawnInfos", LVT_COBJECT_P, offsetof(struct Area, objectSpawnInfos), false, LOT_SPAWNINFO }, { "objectSpawnInfos", LVT_COBJECT_P, offsetof(struct Area, objectSpawnInfos), true, LOT_SPAWNINFO },
{ "paintingWarpNodes", LVT_COBJECT_P, offsetof(struct Area, paintingWarpNodes), false, LOT_WARPNODE }, { "paintingWarpNodes", LVT_COBJECT_P, offsetof(struct Area, paintingWarpNodes), true, LOT_WARPNODE },
{ "surfaceRooms", LVT_S8_P, offsetof(struct Area, surfaceRooms), true, LOT_POINTER }, { "surfaceRooms", LVT_S8_P, offsetof(struct Area, surfaceRooms), true, LOT_POINTER },
{ "terrainData", LVT_S16_P, offsetof(struct Area, terrainData), true, LOT_POINTER }, { "terrainData", LVT_S16_P, offsetof(struct Area, terrainData), true, LOT_POINTER },
{ "terrainType", LVT_U16, offsetof(struct Area, terrainType), false, LOT_NONE }, { "terrainType", LVT_U16, offsetof(struct Area, terrainType), false, LOT_NONE },
// { "unk04", LVT_COBJECT_P, offsetof(struct Area, unk04), true, LOT_??? }, <--- UNIMPLEMENTED // { "unk04", LVT_COBJECT_P, offsetof(struct Area, unk04), true, LOT_??? }, <--- UNIMPLEMENTED
// { "unused28", LVT_COBJECT_P, offsetof(struct Area, unused28), false, LOT_??? }, <--- UNIMPLEMENTED // { "unused28", LVT_COBJECT_P, offsetof(struct Area, unused28), false, LOT_??? }, <--- UNIMPLEMENTED
{ "warpNodes", LVT_COBJECT_P, offsetof(struct Area, warpNodes), false, LOT_OBJECTWARPNODE }, { "warpNodes", LVT_COBJECT_P, offsetof(struct Area, warpNodes), true, LOT_OBJECTWARPNODE },
// { "whirlpools", LOT_???, offsetof(struct Area, whirlpools), false, LOT_??? }, <--- UNIMPLEMENTED // { "whirlpools", LOT_???, offsetof(struct Area, whirlpools), false, LOT_??? }, <--- UNIMPLEMENTED
}; };