Prevent several possible crashes and hangs, limit more struct fields to read-only

This commit is contained in:
MysterD 2023-05-10 13:25:41 -07:00
parent cb499491f4
commit b863cc80c8
16 changed files with 141 additions and 53 deletions

View file

@ -83,7 +83,8 @@ override_field_invisible = {
} }
override_field_immutable = { override_field_immutable = {
"MarioState": [ "playerIndex", "controller" ], "MarioState": [ "playerIndex", "controller", "marioObj", "marioBodyState", "statusForCamera" ],
"ObjectNode": [ "next", "prev" ],
"Character": [ "*" ], "Character": [ "*" ],
"NetworkPlayer": [ "*" ], "NetworkPlayer": [ "*" ],
"TextureInfo": [ "*" ], "TextureInfo": [ "*" ],
@ -96,7 +97,11 @@ override_field_immutable = {
"ModFile": [ "*" ], "ModFile": [ "*" ],
"BassAudio": [ "*" ], "BassAudio": [ "*" ],
"Painting": [ "id", "imageCount", "textureType", "textureWidth", "textureHeight" ], "Painting": [ "id", "imageCount", "textureType", "textureWidth", "textureHeight" ],
"SpawnInfo": [ "syncID" ] "SpawnInfo": [ "syncID" ],
"CustomLevelInfo": [ "next" ],
"GraphNode": [ "next", "prev", "parent" ],
"ObjectWarpNode": [ "next "],
"SpawnInfo": [ "next" ],
} }
override_field_version_excludes = { override_field_version_excludes = {
@ -265,7 +270,29 @@ def get_struct_field_info(struct, field):
return fid, ftype, fimmutable, lvt, lot return fid, ftype, fimmutable, lvt, lot
def output_nuke_struct(struct):
sid = struct['identifier']
print('function Nuke' + sid + "(struct)")
for field in struct['fields']:
fid, ftype, fimmutable, lvt, lot = get_struct_field_info(struct, field)
if fimmutable == 'true':
continue
if sid in override_field_invisible:
if fid in override_field_invisible[sid]:
continue
if lvt == 'LVT_COBJECT':
print(' Nuke' + ftype.replace('struct ', '') + '(struct.' + fid + ')')
elif lvt == 'LVT_COBJECT_P':
print(' struct.' + fid + ' = nil')
else:
print(' struct.' + fid + ' = 0')
print('end')
print('')
def build_struct(struct): def build_struct(struct):
# debug print out lua nuke functions
# output_nuke_struct(struct)
sid = struct['identifier'] sid = struct['identifier']
# build up table and track column width # build up table and track column width

View file

@ -539,7 +539,7 @@
| fullName | `string` | read-only | | fullName | `string` | read-only |
| levelNum | `integer` | | | levelNum | `integer` | |
| modIndex | `integer` | | | modIndex | `integer` | |
| next | [CustomLevelInfo](structs.md#CustomLevelInfo) | | | next | [CustomLevelInfo](structs.md#CustomLevelInfo) | read-only |
| script | `Pointer` <`LevelScript`> | read-only | | script | `Pointer` <`LevelScript`> | read-only |
| scriptEntryName | `string` | read-only | | scriptEntryName | `string` | read-only |
| shortName | `string` | read-only | | shortName | `string` | read-only |
@ -802,9 +802,9 @@
| children | [GraphNode](structs.md#GraphNode) | | | children | [GraphNode](structs.md#GraphNode) | |
| extraFlags | `integer` | | | extraFlags | `integer` | |
| flags | `integer` | | | flags | `integer` | |
| next | [GraphNode](structs.md#GraphNode) | | | next | [GraphNode](structs.md#GraphNode) | read-only |
| parent | [GraphNode](structs.md#GraphNode) | | | parent | [GraphNode](structs.md#GraphNode) | read-only |
| prev | [GraphNode](structs.md#GraphNode) | | | prev | [GraphNode](structs.md#GraphNode) | read-only |
| type | `integer` | | | type | `integer` | |
[:arrow_up_small:](#) [:arrow_up_small:](#)
@ -1070,8 +1070,8 @@
| invincTimer | `integer` | | | invincTimer | `integer` | |
| isSnoring | `integer` | | | isSnoring | `integer` | |
| knockbackTimer | `integer` | | | knockbackTimer | `integer` | |
| marioBodyState | [MarioBodyState](structs.md#MarioBodyState) | | | marioBodyState | [MarioBodyState](structs.md#MarioBodyState) | read-only |
| marioObj | [Object](structs.md#Object) | | | marioObj | [Object](structs.md#Object) | read-only |
| minimumBoneY | `number` | | | minimumBoneY | `number` | |
| nonInstantWarpPos | [Vec3f](structs.md#Vec3f) | read-only | | nonInstantWarpPos | [Vec3f](structs.md#Vec3f) | read-only |
| numCoins | `integer` | | | numCoins | `integer` | |
@ -1095,7 +1095,7 @@
| splineKeyframeFraction | `number` | | | splineKeyframeFraction | `number` | |
| splineState | `integer` | | | splineState | `integer` | |
| squishTimer | `integer` | | | squishTimer | `integer` | |
| statusForCamera | [PlayerCameraState](structs.md#PlayerCameraState) | | | statusForCamera | [PlayerCameraState](structs.md#PlayerCameraState) | read-only |
| terrainSoundAddend | `integer` | | | terrainSoundAddend | `integer` | |
| twirlYaw | `integer` | | | twirlYaw | `integer` | |
| unkB0 | `integer` | | | unkB0 | `integer` | |
@ -1996,8 +1996,8 @@
| Field | Type | Access | | Field | Type | Access |
| ----- | ---- | ------ | | ----- | ---- | ------ |
| gfx | [GraphNodeObject](structs.md#GraphNodeObject) | read-only | | gfx | [GraphNodeObject](structs.md#GraphNodeObject) | read-only |
| next | [ObjectNode](structs.md#ObjectNode) | | | next | [ObjectNode](structs.md#ObjectNode) | read-only |
| prev | [ObjectNode](structs.md#ObjectNode) | | | prev | [ObjectNode](structs.md#ObjectNode) | read-only |
[:arrow_up_small:](#) [:arrow_up_small:](#)
@ -2214,10 +2214,10 @@
| activeAreaIndex | `integer` | | | activeAreaIndex | `integer` | |
| areaIndex | `integer` | | | areaIndex | `integer` | |
| behaviorArg | `integer` | | | behaviorArg | `integer` | |
| next | [SpawnInfo](structs.md#SpawnInfo) | | | next | [SpawnInfo](structs.md#SpawnInfo) | read-only |
| startAngle | [Vec3s](structs.md#Vec3s) | read-only | | startAngle | [Vec3s](structs.md#Vec3s) | read-only |
| startPos | [Vec3s](structs.md#Vec3s) | read-only | | startPos | [Vec3s](structs.md#Vec3s) | read-only |
| syncID | `integer` | read-only | | syncID | `integer` | |
| unk18 | [GraphNode](structs.md#GraphNode) | | | unk18 | [GraphNode](structs.md#GraphNode) | |
[:arrow_up_small:](#) [:arrow_up_small:](#)

View file

@ -594,6 +594,7 @@ struct GraphNode *geo_remove_child(struct GraphNode *graphNode) {
if (graphNode == NULL) { return NULL; } if (graphNode == NULL) { return NULL; }
parent = graphNode->parent; parent = graphNode->parent;
if (!parent) { return NULL; }
firstChild = &parent->children; firstChild = &parent->children;
// Remove link with siblings // Remove link with siblings

View file

@ -296,7 +296,10 @@ void load_mario_area(void) {
stop_sounds_in_continuous_banks(); stop_sounds_in_continuous_banks();
load_area(gMarioSpawnInfo->areaIndex); load_area(gMarioSpawnInfo->areaIndex);
if (!gCurrentArea) { return; }
for (s32 i = 0; i < MAX_PLAYERS; i++) { for (s32 i = 0; i < MAX_PLAYERS; i++) {
if (!gMarioStates[i].spawnInfo) { continue; }
gMarioStates[i].spawnInfo->areaIndex = gCurrentArea->index; gMarioStates[i].spawnInfo->areaIndex = gCurrentArea->index;
} }

View file

@ -16,7 +16,7 @@ void bhv_purple_switch_loop(void) {
u8 anyPlayerOnPlatform = FALSE; u8 anyPlayerOnPlatform = FALSE;
for (s32 i = 0; i < MAX_PLAYERS; i++) { for (s32 i = 0; i < MAX_PLAYERS; i++) {
if (!is_player_active(&gMarioStates[i])) { continue; } if (!is_player_active(&gMarioStates[i])) { continue; }
if (gMarioStates[i].marioObj->platform == o) { if (gMarioStates[i].marioObj && gMarioStates[i].marioObj->platform == o) {
anyPlayerOnPlatform = TRUE; anyPlayerOnPlatform = TRUE;
break; break;
} }

View file

@ -11579,7 +11579,7 @@ void fov_default(struct MarioState *m) {
camera_approach_f32_symmetric_bool(&gFOVState.fov, 45.f, (45.f - gFOVState.fov) / 30.f); camera_approach_f32_symmetric_bool(&gFOVState.fov, 45.f, (45.f - gFOVState.fov) / 30.f);
gFOVState.unusedIsSleeping = 0; gFOVState.unusedIsSleeping = 0;
} }
if (m->area->camera->cutscene == CUTSCENE_0F_UNUSED) { if (m->area && m->area->camera && m->area->camera->cutscene == CUTSCENE_0F_UNUSED) {
gFOVState.fov = 45.f; gFOVState.fov = 45.f;
} }
} }
@ -11600,7 +11600,7 @@ void approach_fov_60(UNUSED struct MarioState *m) {
void approach_fov_45(struct MarioState *m) { void approach_fov_45(struct MarioState *m) {
f32 targetFoV = gFOVState.fov; f32 targetFoV = gFOVState.fov;
if (m->area->camera->mode == CAMERA_MODE_FIXED && m->area->camera->cutscene == 0) { if (m->area && m->area->camera && m->area->camera->mode == CAMERA_MODE_FIXED && m->area->camera->cutscene == 0) {
targetFoV = 45.f; targetFoV = 45.f;
} else { } else {
targetFoV = 45.f; targetFoV = 45.f;
@ -11620,7 +11620,7 @@ void approach_fov_80(UNUSED struct MarioState *m) {
void set_fov_bbh(struct MarioState *m) { void set_fov_bbh(struct MarioState *m) {
f32 targetFoV = gFOVState.fov; f32 targetFoV = gFOVState.fov;
if (m->area->camera->mode == CAMERA_MODE_FIXED && m->area->camera->cutscene == 0) { if (m->area && m->area->camera && m->area->camera->mode == CAMERA_MODE_FIXED && m->area->camera->cutscene == 0) {
targetFoV = 60.f; targetFoV = 60.f;
} else { } else {
targetFoV = 45.f; targetFoV = 45.f;

View file

@ -345,9 +345,11 @@ void mario_drop_held_object(struct MarioState *m) {
// ! When dropping an object instead of throwing it, it will be put at Mario's // ! When dropping an object instead of throwing it, it will be put at Mario's
// y-positon instead of the HOLP's y-position. This fact is often exploited when // y-positon instead of the HOLP's y-position. This fact is often exploited when
// cloning objects. // cloning objects.
m->heldObj->oPosX = m->marioBodyState->heldObjLastPosition[0]; if (m->marioBodyState) {
m->heldObj->oPosY = m->pos[1]; m->heldObj->oPosX = m->marioBodyState->heldObjLastPosition[0];
m->heldObj->oPosZ = m->marioBodyState->heldObjLastPosition[2]; m->heldObj->oPosY = m->pos[1];
m->heldObj->oPosZ = m->marioBodyState->heldObjLastPosition[2];
}
m->heldObj->oMoveAngleYaw = m->faceAngle[1]; m->heldObj->oMoveAngleYaw = m->faceAngle[1];
@ -369,9 +371,11 @@ void mario_throw_held_object(struct MarioState *m) {
obj_set_held_state(m->heldObj, bhvCarrySomething5); obj_set_held_state(m->heldObj, bhvCarrySomething5);
m->heldObj->oPosX = m->marioBodyState->heldObjLastPosition[0] + 32.0f * sins(m->faceAngle[1]); if (m->marioBodyState) {
m->heldObj->oPosY = m->marioBodyState->heldObjLastPosition[1]; m->heldObj->oPosX = m->marioBodyState->heldObjLastPosition[0] + 32.0f * sins(m->faceAngle[1]);
m->heldObj->oPosZ = m->marioBodyState->heldObjLastPosition[2] + 32.0f * coss(m->faceAngle[1]); m->heldObj->oPosY = m->marioBodyState->heldObjLastPosition[1];
m->heldObj->oPosZ = m->marioBodyState->heldObjLastPosition[2] + 32.0f * coss(m->faceAngle[1]);
}
m->heldObj->oMoveAngleYaw = m->faceAngle[1]; m->heldObj->oMoveAngleYaw = m->faceAngle[1];
@ -1278,6 +1282,8 @@ static u8 resolve_player_collision(struct MarioState* m, struct MarioState* m2)
f32 extentY = m->marioObj->hitboxHeight; f32 extentY = m->marioObj->hitboxHeight;
f32 radius = m->marioObj->hitboxRadius * 2.0f; f32 radius = m->marioObj->hitboxRadius * 2.0f;
if (!m->marioBodyState || !m2->marioBodyState) { return FALSE; }
f32* localTorso = m->marioBodyState->torsoPos; f32* localTorso = m->marioBodyState->torsoPos;
f32* remoteTorso = m2->marioBodyState->torsoPos; f32* remoteTorso = m2->marioBodyState->torsoPos;

View file

@ -85,6 +85,7 @@ s32 is_anim_past_end(struct MarioState *m) {
*/ */
s16 set_mario_animation(struct MarioState *m, s32 targetAnimID) { s16 set_mario_animation(struct MarioState *m, s32 targetAnimID) {
struct Object *o = m->marioObj; struct Object *o = m->marioObj;
if (!o || !m->animation) { return 0; }
struct Animation *targetAnim = m->animation->targetAnim; struct Animation *targetAnim = m->animation->targetAnim;
if (load_patchable_table(m->animation, targetAnimID)) { if (load_patchable_table(m->animation, targetAnimID)) {
@ -118,6 +119,7 @@ s16 set_mario_animation(struct MarioState *m, s32 targetAnimID) {
*/ */
s16 set_mario_anim_with_accel(struct MarioState *m, s32 targetAnimID, s32 accel) { s16 set_mario_anim_with_accel(struct MarioState *m, s32 targetAnimID, s32 accel) {
struct Object *o = m->marioObj; struct Object *o = m->marioObj;
if (!o || !m->animation) { return 0; }
struct Animation *targetAnim = m->animation->targetAnim; struct Animation *targetAnim = m->animation->targetAnim;
if (load_patchable_table(m->animation, targetAnimID)) { if (load_patchable_table(m->animation, targetAnimID)) {

View file

@ -523,6 +523,7 @@ s8 is_point_within_radius_of_mario(f32 x, f32 y, f32 z, s32 dist) {
if (!is_player_active(&gMarioStates[i])) { continue; } if (!is_player_active(&gMarioStates[i])) { continue; }
if (!gMarioStates[i].visibleToEnemies) { continue; } if (!gMarioStates[i].visibleToEnemies) { continue; }
struct Object* player = gMarioStates[i].marioObj; struct Object* player = gMarioStates[i].marioObj;
if (!player) { continue; }
f32 mGfxX = player->header.gfx.pos[0]; f32 mGfxX = player->header.gfx.pos[0];
f32 mGfxY = player->header.gfx.pos[1]; f32 mGfxY = player->header.gfx.pos[1];
f32 mGfxZ = player->header.gfx.pos[2]; f32 mGfxZ = player->header.gfx.pos[2];
@ -540,6 +541,7 @@ s8 is_point_within_radius_of_any_player(f32 x, f32 y, f32 z, s32 dist) {
for (s32 i = 0; i < MAX_PLAYERS; i++) { for (s32 i = 0; i < MAX_PLAYERS; i++) {
if (!is_player_active(&gMarioStates[i])) { continue; } if (!is_player_active(&gMarioStates[i])) { continue; }
struct Object* player = gMarioStates[i].marioObj; struct Object* player = gMarioStates[i].marioObj;
if (!player) { continue; }
f32 mGfxX = player->header.gfx.pos[0]; f32 mGfxX = player->header.gfx.pos[0];
f32 mGfxY = player->header.gfx.pos[1]; f32 mGfxY = player->header.gfx.pos[1];
f32 mGfxZ = player->header.gfx.pos[2]; f32 mGfxZ = player->header.gfx.pos[2];
@ -606,6 +608,7 @@ struct MarioState* nearest_mario_state_to_object(struct Object *obj) {
struct MarioState* nearest = NULL; struct MarioState* nearest = NULL;
f32 nearestDist = 0; f32 nearestDist = 0;
for (s32 i = 0; i < MAX_PLAYERS; i++) { for (s32 i = 0; i < MAX_PLAYERS; i++) {
if (!gMarioStates[i].marioObj) { continue; }
if (gMarioStates[i].marioObj == obj) { continue; } if (gMarioStates[i].marioObj == obj) { continue; }
if (!gMarioStates[i].visibleToEnemies) { continue; } if (!gMarioStates[i].visibleToEnemies) { continue; }
if (!is_player_active(&gMarioStates[i])) { continue; } if (!is_player_active(&gMarioStates[i])) { continue; }
@ -624,6 +627,7 @@ struct MarioState* nearest_possible_mario_state_to_object(struct Object *obj) {
struct MarioState* nearest = NULL; struct MarioState* nearest = NULL;
f32 nearestDist = 0; f32 nearestDist = 0;
for (s32 i = 0; i < MAX_PLAYERS; i++) { for (s32 i = 0; i < MAX_PLAYERS; i++) {
if (!gMarioStates[i].marioObj) { continue; }
if (gMarioStates[i].marioObj == obj) { continue; } if (gMarioStates[i].marioObj == obj) { continue; }
if (!is_player_active(&gMarioStates[i])) { continue; } if (!is_player_active(&gMarioStates[i])) { continue; }
float dist = dist_between_objects(obj, gMarioStates[i].marioObj); float dist = dist_between_objects(obj, gMarioStates[i].marioObj);
@ -655,6 +659,7 @@ struct MarioState *nearest_interacting_mario_state_to_object(struct Object *obj)
f32 nearestDist = 0; f32 nearestDist = 0;
for (s32 i = 0; i < MAX_PLAYERS; i++) { for (s32 i = 0; i < MAX_PLAYERS; i++) {
if (!gMarioStates[i].marioObj) { continue; }
if (gMarioStates[i].marioObj == obj) { continue; } if (gMarioStates[i].marioObj == obj) { continue; }
if (gMarioStates[i].interactObj != obj) { continue; } if (gMarioStates[i].interactObj != obj) { continue; }
if (!gMarioStates[i].visibleToEnemies) { continue; } if (!gMarioStates[i].visibleToEnemies) { continue; }

View file

@ -9,6 +9,7 @@
#include "pc/network/network_player.h" #include "pc/network/network_player.h"
struct Object *debug_print_obj_collision(struct Object *a) { struct Object *debug_print_obj_collision(struct Object *a) {
if (!a) { return NULL; }
struct Object *sp24; struct Object *sp24;
for (s32 i = 0; i < a->numCollidedObjs; i++) { for (s32 i = 0; i < a->numCollidedObjs; i++) {
@ -22,6 +23,7 @@ struct Object *debug_print_obj_collision(struct Object *a) {
} }
int detect_player_hitbox_overlap(struct MarioState* local, struct MarioState* remote, f32 scale) { int detect_player_hitbox_overlap(struct MarioState* local, struct MarioState* remote, f32 scale) {
if (!local || !remote) { return FALSE; }
if (local->marioObj == NULL || local->marioObj->oIntangibleTimer != 0) { return FALSE; } if (local->marioObj == NULL || local->marioObj->oIntangibleTimer != 0) { return FALSE; }
if (remote->marioObj == NULL || remote->marioObj->oIntangibleTimer != 0) { return FALSE; } if (remote->marioObj == NULL || remote->marioObj->oIntangibleTimer != 0) { return FALSE; }
@ -63,6 +65,7 @@ int detect_player_hitbox_overlap(struct MarioState* local, struct MarioState* re
} }
s32 detect_object_hitbox_overlap(struct Object *a, struct Object *b) { s32 detect_object_hitbox_overlap(struct Object *a, struct Object *b) {
if (!a || !b) { return 0; }
f32 sp3C = a->oPosY - a->hitboxDownOffset; f32 sp3C = a->oPosY - a->hitboxDownOffset;
f32 sp38 = b->oPosY - b->hitboxDownOffset; f32 sp38 = b->oPosY - b->hitboxDownOffset;
f32 dx = a->oPosX - b->oPosX; f32 dx = a->oPosX - b->oPosX;
@ -105,6 +108,8 @@ s32 detect_object_hitbox_overlap(struct Object *a, struct Object *b) {
} }
s32 detect_object_hurtbox_overlap(struct Object *a, struct Object *b) { s32 detect_object_hurtbox_overlap(struct Object *a, struct Object *b) {
if (!a || !b) { return 0; }
f32 sp3C = a->oPosY - a->hitboxDownOffset; f32 sp3C = a->oPosY - a->hitboxDownOffset;
f32 sp38 = b->oPosY - b->hitboxDownOffset; f32 sp38 = b->oPosY - b->hitboxDownOffset;
f32 sp34 = a->oPosX - b->oPosX; f32 sp34 = a->oPosX - b->oPosX;
@ -137,26 +142,30 @@ s32 detect_object_hurtbox_overlap(struct Object *a, struct Object *b) {
} }
void clear_object_collision(struct Object *a) { void clear_object_collision(struct Object *a) {
if (!a) { return; }
struct Object *sp4 = (struct Object *) a->header.next; struct Object *sp4 = (struct Object *) a->header.next;
while (sp4 != a) { while (sp4 && sp4 != a) {
sp4->numCollidedObjs = 0; sp4->numCollidedObjs = 0;
sp4->collidedObjInteractTypes = 0; sp4->collidedObjInteractTypes = 0;
if (sp4->oIntangibleTimer > 0) { if (sp4->oIntangibleTimer > 0) {
sp4->oIntangibleTimer--; sp4->oIntangibleTimer--;
} }
if (sp4 == (struct Object *)sp4->header.next) { break; }
sp4 = (struct Object *) sp4->header.next; sp4 = (struct Object *) sp4->header.next;
} }
} }
void check_collision_in_list(struct Object *a, struct Object *b, struct Object *c) { void check_collision_in_list(struct Object *a, struct Object *b, struct Object *c) {
if (!a) { return; }
if (a->oIntangibleTimer == 0) { if (a->oIntangibleTimer == 0) {
while (b != c) { while (b && b != c) {
if (b->oIntangibleTimer == 0) { if (b->oIntangibleTimer == 0) {
if (detect_object_hitbox_overlap(a, b) && b->hurtboxRadius != 0.0f) { if (detect_object_hitbox_overlap(a, b) && b->hurtboxRadius != 0.0f) {
detect_object_hurtbox_overlap(a, b); detect_object_hurtbox_overlap(a, b);
} }
} }
if (b == (struct Object *)b->header.next) { break; }
b = (struct Object *) b->header.next; b = (struct Object *) b->header.next;
} }
} }
@ -166,7 +175,7 @@ void check_player_object_collision(void) {
struct Object *sp1C = (struct Object *) &gObjectLists[OBJ_LIST_PLAYER]; struct Object *sp1C = (struct Object *) &gObjectLists[OBJ_LIST_PLAYER];
struct Object *sp18 = (struct Object *) sp1C->header.next; struct Object *sp18 = (struct Object *) sp1C->header.next;
while (sp18 != sp1C) { while (sp18 && sp18 != sp1C) {
check_collision_in_list(sp18, (struct Object *) sp18->header.next, sp1C); check_collision_in_list(sp18, (struct Object *) sp18->header.next, sp1C);
check_collision_in_list(sp18, (struct Object *) gObjectLists[OBJ_LIST_POLELIKE].next, check_collision_in_list(sp18, (struct Object *) gObjectLists[OBJ_LIST_POLELIKE].next,
(struct Object *) &gObjectLists[OBJ_LIST_POLELIKE]); (struct Object *) &gObjectLists[OBJ_LIST_POLELIKE]);
@ -202,8 +211,9 @@ void check_pushable_object_collision(void) {
struct Object *sp1C = (struct Object *) &gObjectLists[OBJ_LIST_PUSHABLE]; struct Object *sp1C = (struct Object *) &gObjectLists[OBJ_LIST_PUSHABLE];
struct Object *sp18 = (struct Object *) sp1C->header.next; struct Object *sp18 = (struct Object *) sp1C->header.next;
while (sp18 != sp1C) { while (sp18 && sp18 != sp1C) {
check_collision_in_list(sp18, (struct Object *) sp18->header.next, sp1C); check_collision_in_list(sp18, (struct Object *) sp18->header.next, sp1C);
if (sp18 == (struct Object *)sp18->header.next) { break; }
sp18 = (struct Object *) sp18->header.next; sp18 = (struct Object *) sp18->header.next;
} }
} }
@ -212,7 +222,7 @@ void check_destructive_object_collision(void) {
struct Object *sp1C = (struct Object *) &gObjectLists[OBJ_LIST_DESTRUCTIVE]; struct Object *sp1C = (struct Object *) &gObjectLists[OBJ_LIST_DESTRUCTIVE];
struct Object *sp18 = (struct Object *) sp1C->header.next; struct Object *sp18 = (struct Object *) sp1C->header.next;
while (sp18 != sp1C) { while (sp18 && sp18 != sp1C) {
if (sp18->oDistanceToMario < 2000.0f && !(sp18->activeFlags & ACTIVE_FLAG_UNK9)) { if (sp18->oDistanceToMario < 2000.0f && !(sp18->activeFlags & ACTIVE_FLAG_UNK9)) {
check_collision_in_list(sp18, (struct Object *) sp18->header.next, sp1C); check_collision_in_list(sp18, (struct Object *) sp18->header.next, sp1C);
check_collision_in_list(sp18, (struct Object *) gObjectLists[OBJ_LIST_GENACTOR].next, check_collision_in_list(sp18, (struct Object *) gObjectLists[OBJ_LIST_GENACTOR].next,
@ -222,6 +232,7 @@ void check_destructive_object_collision(void) {
check_collision_in_list(sp18, (struct Object *) gObjectLists[OBJ_LIST_SURFACE].next, check_collision_in_list(sp18, (struct Object *) gObjectLists[OBJ_LIST_SURFACE].next,
(struct Object *) &gObjectLists[OBJ_LIST_SURFACE]); (struct Object *) &gObjectLists[OBJ_LIST_SURFACE]);
} }
if (sp18 == (struct Object *)sp18->header.next) { break; }
sp18 = (struct Object *) sp18->header.next; sp18 = (struct Object *) sp18->header.next;
} }
} }

View file

@ -2532,6 +2532,7 @@ s32 cur_obj_wait_then_blink(s32 timeUntilBlinking, s32 numBlinks) {
s32 cur_obj_is_mario_ground_pounding_platform(void) { s32 cur_obj_is_mario_ground_pounding_platform(void) {
for (s32 i = 0; i < MAX_PLAYERS; i++) { for (s32 i = 0; i < MAX_PLAYERS; i++) {
if (!is_player_active(&gMarioStates[i])) { continue; } if (!is_player_active(&gMarioStates[i])) { continue; }
if (!gMarioStates[i].marioObj) { continue; }
if (gMarioStates[i].marioObj->platform == o) { if (gMarioStates[i].marioObj->platform == o) {
if (gMarioStates[i].action == ACT_GROUND_POUND_LAND) { if (gMarioStates[i].action == ACT_GROUND_POUND_LAND) {
return TRUE; return TRUE;
@ -2554,6 +2555,7 @@ void spawn_mist_particles_with_sound(u32 sp18) {
void cur_obj_push_mario_away(f32 radius) { void cur_obj_push_mario_away(f32 radius) {
for (s32 i = 0; i < MAX_PLAYERS; i++) { for (s32 i = 0; i < MAX_PLAYERS; i++) {
struct Object* player = gMarioStates[i].marioObj; struct Object* player = gMarioStates[i].marioObj;
if (!player) { continue; }
f32 marioRelX = player->oPosX - o->oPosX; f32 marioRelX = player->oPosX - o->oPosX;
f32 marioRelZ = player->oPosZ - o->oPosZ; f32 marioRelZ = player->oPosZ - o->oPosZ;
f32 marioDist = sqrtf(sqr(marioRelX) + sqr(marioRelZ)); f32 marioDist = sqrtf(sqr(marioRelX) + sqr(marioRelZ));
@ -2570,6 +2572,7 @@ void cur_obj_push_mario_away(f32 radius) {
void cur_obj_push_mario_away_from_cylinder(f32 radius, f32 extentY) { void cur_obj_push_mario_away_from_cylinder(f32 radius, f32 extentY) {
for (s32 i = 0; i < MAX_PLAYERS; i++) { for (s32 i = 0; i < MAX_PLAYERS; i++) {
struct Object* player = gMarioStates[i].marioObj; struct Object* player = gMarioStates[i].marioObj;
if (!player) { continue; }
f32 marioRelY = player->oPosY - o->oPosY; f32 marioRelY = player->oPosY - o->oPosY;
if (marioRelY < 0.0f) { if (marioRelY < 0.0f) {
@ -2733,6 +2736,7 @@ s32 cur_obj_mario_far_away(void) {
for (s32 i = 0; i < MAX_PLAYERS; i++) { for (s32 i = 0; i < MAX_PLAYERS; i++) {
if (!is_player_active(&gMarioStates[i])) { continue; } if (!is_player_active(&gMarioStates[i])) { continue; }
struct Object* player = gMarioStates[i].marioObj; struct Object* player = gMarioStates[i].marioObj;
if (!player) { continue; }
f32 dx = o->oHomeX - player->oPosX; f32 dx = o->oHomeX - player->oPosX;
f32 dy = o->oHomeY - player->oPosY; f32 dy = o->oHomeY - player->oPosY;
f32 dz = o->oHomeZ - player->oPosZ; f32 dz = o->oHomeZ - player->oPosZ;
@ -2880,6 +2884,7 @@ void cur_obj_if_hit_wall_bounce_away(void) {
} }
s32 cur_obj_hide_if_mario_far_away_y(f32 distY) { s32 cur_obj_hide_if_mario_far_away_y(f32 distY) {
if (!gMarioStates[0].marioObj) { return FALSE; }
if (absf(o->oPosY - gMarioStates[0].marioObj->oPosY) < distY * draw_distance_scalar()) { if (absf(o->oPosY - gMarioStates[0].marioObj->oPosY) < distY * draw_distance_scalar()) {
cur_obj_unhide(); cur_obj_unhide();
return FALSE; return FALSE;

View file

@ -347,10 +347,13 @@ void bhv_mario_update(void) {
* including firstObj itself. Return the number of objects that were updated. * including firstObj itself. Return the number of objects that were updated.
*/ */
s32 update_objects_starting_at(struct ObjectNode *objList, struct ObjectNode *firstObj) { s32 update_objects_starting_at(struct ObjectNode *objList, struct ObjectNode *firstObj) {
if (!firstObj) { return 0; }
s32 count = 0; s32 count = 0;
while (objList != firstObj) { while (objList != firstObj) {
gCurrentObject = (struct Object *) firstObj; gCurrentObject = (struct Object *) firstObj;
if (!gCurrentObject) { break; }
gCurrentObject->header.gfx.node.flags |= GRAPH_RENDER_HAS_ANIMATION; gCurrentObject->header.gfx.node.flags |= GRAPH_RENDER_HAS_ANIMATION;
cur_obj_update(); cur_obj_update();
@ -372,11 +375,13 @@ s32 update_objects_starting_at(struct ObjectNode *objList, struct ObjectNode *fi
* updated) * updated)
*/ */
s32 update_objects_during_time_stop(struct ObjectNode *objList, struct ObjectNode *firstObj) { s32 update_objects_during_time_stop(struct ObjectNode *objList, struct ObjectNode *firstObj) {
if (!firstObj) { return 0; }
s32 count = 0; s32 count = 0;
s32 unfrozen; s32 unfrozen;
while (objList != firstObj) { while (objList != firstObj) {
gCurrentObject = (struct Object *) firstObj; gCurrentObject = (struct Object *) firstObj;
if (!gCurrentObject) { break; }
unfrozen = FALSE; unfrozen = FALSE;
@ -433,10 +438,12 @@ s32 update_objects_in_list(struct ObjectNode *objList) {
* Unload any objects in the list that have been deactivated. * Unload any objects in the list that have been deactivated.
*/ */
s32 unload_deactivated_objects_in_list(struct ObjectNode *objList) { s32 unload_deactivated_objects_in_list(struct ObjectNode *objList) {
if (!objList) { return 0; }
struct ObjectNode *obj = objList->next; struct ObjectNode *obj = objList->next;
while (objList != obj) { while (objList != obj) {
gCurrentObject = (struct Object *) obj; gCurrentObject = (struct Object *) obj;
if (!gCurrentObject) { break; }
obj = obj->next; obj = obj->next;

View file

@ -42,7 +42,7 @@
* *
*/ */
#define MATRIX_STACK_SIZE 32 #define MATRIX_STACK_SIZE 64
f32 gProjectionMaxNearValue = 5; f32 gProjectionMaxNearValue = 5;
s16 gProjectionVanillaNearValue = 100; s16 gProjectionVanillaNearValue = 100;
@ -327,9 +327,18 @@ void patch_mtx_interpolated(f32 delta) {
static u8 increment_mat_stack() { static u8 increment_mat_stack() {
Mtx *mtx = alloc_display_list(sizeof(*mtx)); Mtx *mtx = alloc_display_list(sizeof(*mtx));
Mtx *mtxPrev = alloc_display_list(sizeof(*mtxPrev)); Mtx *mtxPrev = alloc_display_list(sizeof(*mtxPrev));
if (mtx == NULL || mtxPrev == NULL) { LOG_ERROR("Failed to allocate our matrices for the matrix stack."); return FALSE; } if (mtx == NULL || mtxPrev == NULL) {
LOG_ERROR("Failed to allocate our matrices for the matrix stack.");
return FALSE;
}
gMatStackIndex++; gMatStackIndex++;
if (gMatStackIndex >= MATRIX_STACK_SIZE) {
LOG_ERROR("Exceeded matrix stack size.");
gMatStackIndex = MATRIX_STACK_SIZE - 1;
return FALSE;
}
mtxf_to_mtx(mtx, gMatStack[gMatStackIndex]); mtxf_to_mtx(mtx, gMatStack[gMatStackIndex]);
mtxf_to_mtx(mtxPrev, gMatStackPrev[gMatStackIndex]); mtxf_to_mtx(mtxPrev, gMatStackPrev[gMatStackIndex]);
gMatStackFixed[gMatStackIndex] = mtx; gMatStackFixed[gMatStackIndex] = mtx;
@ -529,7 +538,7 @@ static void geo_process_camera(struct GraphNodeCamera *node) {
Mat4 cameraTransform; Mat4 cameraTransform;
// Sanity check our stack index, If we above or equal to our stack size. Return to prevent OOB. // Sanity check our stack index, If we above or equal to our stack size. Return to prevent OOB.
if (gMatStackIndex >= MATRIX_STACK_SIZE) { LOG_ERROR("Preventing attempt to exceed the maximum size %i for our matrix stack with size of %i.", MATRIX_STACK_SIZE - 1, gMatStackIndex); return; } if ((gMatStackIndex + 1) >= MATRIX_STACK_SIZE) { LOG_ERROR("Preventing attempt to exceed the maximum size %i for our matrix stack with size of %i.", MATRIX_STACK_SIZE - 1, gMatStackIndex); return; }
Mtx *rollMtx = alloc_display_list(sizeof(*rollMtx)); Mtx *rollMtx = alloc_display_list(sizeof(*rollMtx));
if (rollMtx == NULL) { return; } if (rollMtx == NULL) { return; }
@ -588,7 +597,7 @@ static void geo_process_translation_rotation(struct GraphNodeTranslationRotation
Vec3f translation; Vec3f translation;
// Sanity check our stack index, If we above or equal to our stack size. Return to prevent OOB\. // Sanity check our stack index, If we above or equal to our stack size. Return to prevent OOB\.
if (gMatStackIndex >= MATRIX_STACK_SIZE) { LOG_ERROR("Preventing attempt to exceed the maximum size %i for our matrix stack with size of %i.", MATRIX_STACK_SIZE - 1, gMatStackIndex); return; } if ((gMatStackIndex + 1) >= MATRIX_STACK_SIZE) { LOG_ERROR("Preventing attempt to exceed the maximum size %i for our matrix stack with size of %i.", MATRIX_STACK_SIZE - 1, gMatStackIndex); return; }
vec3s_to_vec3f(translation, node->translation); vec3s_to_vec3f(translation, node->translation);
mtxf_rotate_zxy_and_translate(mtxf, translation, node->rotation); mtxf_rotate_zxy_and_translate(mtxf, translation, node->rotation);
@ -617,7 +626,7 @@ static void geo_process_translation(struct GraphNodeTranslation *node) {
Vec3f translation; Vec3f translation;
// Sanity check our stack index, If we above or equal to our stack size. Return to prevent OOB\. // Sanity check our stack index, If we above or equal to our stack size. Return to prevent OOB\.
if (gMatStackIndex >= MATRIX_STACK_SIZE) { LOG_ERROR("Preventing attempt to exceed the maximum size %i for our matrix stack with size of %i.", MATRIX_STACK_SIZE - 1, gMatStackIndex); return; } if ((gMatStackIndex + 1) >= MATRIX_STACK_SIZE) { LOG_ERROR("Preventing attempt to exceed the maximum size %i for our matrix stack with size of %i.", MATRIX_STACK_SIZE - 1, gMatStackIndex); return; }
vec3s_to_vec3f(translation, node->translation); vec3s_to_vec3f(translation, node->translation);
mtxf_rotate_zxy_and_translate(mtxf, translation, gVec3sZero); mtxf_rotate_zxy_and_translate(mtxf, translation, gVec3sZero);
@ -645,7 +654,7 @@ static void geo_process_rotation(struct GraphNodeRotation *node) {
Mat4 mtxf; Mat4 mtxf;
// Sanity check our stack index, If we above or equal to our stack size. Return to prevent OOB\. // Sanity check our stack index, If we above or equal to our stack size. Return to prevent OOB\.
if (gMatStackIndex >= MATRIX_STACK_SIZE) { LOG_ERROR("Preventing attempt to exceed the maximum size %i for our matrix stack with size of %i.", MATRIX_STACK_SIZE - 1, gMatStackIndex); return; } if ((gMatStackIndex + 1) >= MATRIX_STACK_SIZE) { LOG_ERROR("Preventing attempt to exceed the maximum size %i for our matrix stack with size of %i.", MATRIX_STACK_SIZE - 1, gMatStackIndex); return; }
mtxf_rotate_zxy_and_translate(mtxf, gVec3fZero, node->rotation); mtxf_rotate_zxy_and_translate(mtxf, gVec3fZero, node->rotation);
mtxf_mul(gMatStack[gMatStackIndex + 1], mtxf, gMatStack[gMatStackIndex]); mtxf_mul(gMatStack[gMatStackIndex + 1], mtxf, gMatStack[gMatStackIndex]);
@ -681,7 +690,7 @@ static void geo_process_scale(struct GraphNodeScale *node) {
Vec3f prevScaleVec; Vec3f prevScaleVec;
// Sanity check our stack index, If we above or equal to our stack size. Return to prevent OOB\. // Sanity check our stack index, If we above or equal to our stack size. Return to prevent OOB\.
if (gMatStackIndex >= MATRIX_STACK_SIZE) { LOG_ERROR("Preventing attempt to exceed the maximum size %i for our matrix stack with size of %i.", MATRIX_STACK_SIZE - 1, gMatStackIndex); return; } if ((gMatStackIndex + 1) >= MATRIX_STACK_SIZE) { LOG_ERROR("Preventing attempt to exceed the maximum size %i for our matrix stack with size of %i.", MATRIX_STACK_SIZE - 1, gMatStackIndex); return; }
vec3f_set(scaleVec, node->scale, node->scale, node->scale); vec3f_set(scaleVec, node->scale, node->scale, node->scale);
mtxf_scale_vec3f(gMatStack[gMatStackIndex + 1], gMatStack[gMatStackIndex], scaleVec); mtxf_scale_vec3f(gMatStack[gMatStackIndex + 1], gMatStack[gMatStackIndex], scaleVec);
@ -717,7 +726,7 @@ static void geo_process_billboard(struct GraphNodeBillboard *node) {
Vec3f translation; Vec3f translation;
// Sanity check our stack index, If we above or equal to our stack size. Return to prevent OOB\. // Sanity check our stack index, If we above or equal to our stack size. Return to prevent OOB\.
if (gMatStackIndex >= MATRIX_STACK_SIZE) { LOG_ERROR("Preventing attempt to exceed the maximum size %i for our matrix stack with size of %i.", MATRIX_STACK_SIZE - 1, gMatStackIndex); return; } if ((gMatStackIndex + 1) >= MATRIX_STACK_SIZE) { LOG_ERROR("Preventing attempt to exceed the maximum size %i for our matrix stack with size of %i.", MATRIX_STACK_SIZE - 1, gMatStackIndex); return; }
s16 nextMatStackIndex = gMatStackIndex + 1; s16 nextMatStackIndex = gMatStackIndex + 1;
@ -890,7 +899,7 @@ static void geo_process_animated_part(struct GraphNodeAnimatedPart *node) {
Vec3f translationPrev; Vec3f translationPrev;
// Sanity check our stack index, If we above or equal to our stack size. Return to prevent OOB\. // Sanity check our stack index, If we above or equal to our stack size. Return to prevent OOB\.
if (gMatStackIndex >= MATRIX_STACK_SIZE) { LOG_ERROR("Preventing attempt to exceed the maximum size %i for our matrix stack with size of %i.", MATRIX_STACK_SIZE - 1, gMatStackIndex); return; } if ((gMatStackIndex + 1) >= MATRIX_STACK_SIZE) { LOG_ERROR("Preventing attempt to exceed the maximum size %i for our matrix stack with size of %i.", MATRIX_STACK_SIZE - 1, gMatStackIndex); return; }
u16 *animAttribute = gCurrAnimAttribute; u16 *animAttribute = gCurrAnimAttribute;
u8 animType = gCurAnimType; u8 animType = gCurAnimType;
@ -983,7 +992,7 @@ static void geo_process_shadow(struct GraphNodeShadow *node) {
f32 shadowScale; f32 shadowScale;
// Sanity check our stack index, If we above or equal to our stack size. Return to prevent OOB\. // Sanity check our stack index, If we above or equal to our stack size. Return to prevent OOB\.
if (gMatStackIndex >= MATRIX_STACK_SIZE) { LOG_ERROR("Preventing attempt to exceed the maximum size %i for our matrix stack with size of %i.", MATRIX_STACK_SIZE - 1, gMatStackIndex); return; } if ((gMatStackIndex + 1) >= MATRIX_STACK_SIZE) { LOG_ERROR("Preventing attempt to exceed the maximum size %i for our matrix stack with size of %i.", MATRIX_STACK_SIZE - 1, gMatStackIndex); return; }
if (gCurGraphNodeCamera != NULL && gCurGraphNodeObject != NULL) { if (gCurGraphNodeCamera != NULL && gCurGraphNodeObject != NULL) {
if (gCurGraphNodeHeldObject != NULL) { if (gCurGraphNodeHeldObject != NULL) {
@ -1191,6 +1200,9 @@ static void geo_process_object(struct Object *node) {
s32 hasAnimation = (node->header.gfx.node.flags & GRAPH_RENDER_HAS_ANIMATION) != 0; s32 hasAnimation = (node->header.gfx.node.flags & GRAPH_RENDER_HAS_ANIMATION) != 0;
Vec3f scalePrev; Vec3f scalePrev;
// Sanity check our stack index, If we above or equal to our stack size. Return to prevent OOB\.
if ((gMatStackIndex + 1) >= MATRIX_STACK_SIZE) { LOG_ERROR("Preventing attempt to exceed the maximum size %i for our matrix stack with size of %i.", MATRIX_STACK_SIZE - 1, gMatStackIndex); return; }
if (node->hookRender) { if (node->hookRender) {
smlua_call_event_hooks_object_param(HOOK_ON_OBJECT_RENDER, node); smlua_call_event_hooks_object_param(HOOK_ON_OBJECT_RENDER, node);
} }
@ -1379,7 +1391,7 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) {
Vec3f scalePrev; Vec3f scalePrev;
// Sanity check our stack index, If we above or equal to our stack size. Return to prevent OOB\. // Sanity check our stack index, If we above or equal to our stack size. Return to prevent OOB\.
if (gMatStackIndex >= MATRIX_STACK_SIZE) { LOG_ERROR("Preventing attempt to exceed the maximum size %i for our matrix stack with size of %i.", MATRIX_STACK_SIZE - 1, gMatStackIndex); return; } if ((gMatStackIndex + 1) >= MATRIX_STACK_SIZE) { LOG_ERROR("Preventing attempt to exceed the maximum size %i for our matrix stack with size of %i.", MATRIX_STACK_SIZE - 1, gMatStackIndex); return; }
#ifdef F3DEX_GBI_2 #ifdef F3DEX_GBI_2
gSPLookAt(gDisplayListHead++, &lookAt); gSPLookAt(gDisplayListHead++, &lookAt);
@ -1476,6 +1488,7 @@ void geo_process_node_and_siblings(struct GraphNode *firstNode) {
s16 iterateChildren = TRUE; s16 iterateChildren = TRUE;
struct GraphNode *curGraphNode = firstNode; struct GraphNode *curGraphNode = firstNode;
if (curGraphNode == NULL) { return; } if (curGraphNode == NULL) { return; }
u32 depthSanity = 0;
struct GraphNode *parent = curGraphNode->parent; struct GraphNode *parent = curGraphNode->parent;
@ -1489,6 +1502,13 @@ void geo_process_node_and_siblings(struct GraphNode *firstNode) {
if (curGraphNode == NULL) { if (curGraphNode == NULL) {
break; break;
} }
// Sanity check our stack index, If we above or equal to our stack size. Return to prevent OOB\.
if ((gMatStackIndex + 1) >= MATRIX_STACK_SIZE) { break; }
// Break out of endless loops
if (++depthSanity > 5000) { break; }
if (curGraphNode->flags & GRAPH_RENDER_ACTIVE) { if (curGraphNode->flags & GRAPH_RENDER_ACTIVE) {
if (curGraphNode->flags & GRAPH_RENDER_CHILDREN_FIRST) { if (curGraphNode->flags & GRAPH_RENDER_CHILDREN_FIRST) {
geo_try_process_children(curGraphNode); geo_try_process_children(curGraphNode);

View file

@ -583,6 +583,7 @@ s8 correct_shadow_solidity_for_animations(s32 playerIndex, u8 initialSolidity, s
extern struct MarioState gMarioStates[]; extern struct MarioState gMarioStates[];
player = gMarioStates[playerIndex].marioObj; player = gMarioStates[playerIndex].marioObj;
if (!player) { return SHADOW_SOLIDITY_NO_SHADOW; }
animFrame = player->header.gfx.animInfo.animFrame; animFrame = player->header.gfx.animInfo.animFrame;
switch (player->header.gfx.animInfo.animID) { switch (player->header.gfx.animInfo.animID) {

View file

@ -141,8 +141,8 @@ void unused_deallocate(struct LinkedList *freeList, struct LinkedList *node) {
static void deallocate_object(struct ObjectNode *freeList, struct ObjectNode *obj) { static void deallocate_object(struct ObjectNode *freeList, struct ObjectNode *obj) {
if (!obj || !freeList) { return; } if (!obj || !freeList) { return; }
// Remove from object list // Remove from object list
obj->next->prev = obj->prev; if (obj->next) { obj->next->prev = obj->prev; }
obj->prev->next = obj->next; if (obj->prev) { obj->prev->next = obj->next; }
// Insert at beginning of free list // Insert at beginning of free list
obj->next = freeList->next; obj->next = freeList->next;

View file

@ -404,7 +404,7 @@ static struct LuaObjectField sCustomLevelInfoFields[LUA_CUSTOM_LEVEL_INFO_FIELD_
{ "fullName", LVT_STRING_P, offsetof(struct CustomLevelInfo, fullName), true, LOT_NONE }, { "fullName", LVT_STRING_P, offsetof(struct CustomLevelInfo, fullName), true, LOT_NONE },
{ "levelNum", LVT_S16, offsetof(struct CustomLevelInfo, levelNum), false, LOT_NONE }, { "levelNum", LVT_S16, offsetof(struct CustomLevelInfo, levelNum), false, LOT_NONE },
{ "modIndex", LVT_S32, offsetof(struct CustomLevelInfo, modIndex), false, LOT_NONE }, { "modIndex", LVT_S32, offsetof(struct CustomLevelInfo, modIndex), false, LOT_NONE },
{ "next", LVT_COBJECT_P, offsetof(struct CustomLevelInfo, next), false, LOT_CUSTOMLEVELINFO }, { "next", LVT_COBJECT_P, offsetof(struct CustomLevelInfo, next), true, LOT_CUSTOMLEVELINFO },
{ "script", LVT_LEVELSCRIPT_P, offsetof(struct CustomLevelInfo, script), true, LOT_POINTER }, { "script", LVT_LEVELSCRIPT_P, offsetof(struct CustomLevelInfo, script), true, LOT_POINTER },
{ "scriptEntryName", LVT_STRING_P, offsetof(struct CustomLevelInfo, scriptEntryName), true, LOT_NONE }, { "scriptEntryName", LVT_STRING_P, offsetof(struct CustomLevelInfo, scriptEntryName), true, LOT_NONE },
{ "shortName", LVT_STRING_P, offsetof(struct CustomLevelInfo, shortName), true, LOT_NONE }, { "shortName", LVT_STRING_P, offsetof(struct CustomLevelInfo, shortName), true, LOT_NONE },
@ -630,9 +630,9 @@ static struct LuaObjectField sGraphNodeFields[LUA_GRAPH_NODE_FIELD_COUNT] = {
{ "extraFlags", LVT_U8, offsetof(struct GraphNode, extraFlags), false, LOT_NONE }, { "extraFlags", LVT_U8, offsetof(struct GraphNode, extraFlags), false, LOT_NONE },
{ "flags", LVT_S16, offsetof(struct GraphNode, flags), false, LOT_NONE }, { "flags", LVT_S16, offsetof(struct GraphNode, flags), false, LOT_NONE },
// { "georef", LVT_???, offsetof(struct GraphNode, georef), true, LOT_??? }, <--- UNIMPLEMENTED // { "georef", LVT_???, offsetof(struct GraphNode, georef), true, LOT_??? }, <--- UNIMPLEMENTED
{ "next", LVT_COBJECT_P, offsetof(struct GraphNode, next), false, LOT_GRAPHNODE }, { "next", LVT_COBJECT_P, offsetof(struct GraphNode, next), true, LOT_GRAPHNODE },
{ "parent", LVT_COBJECT_P, offsetof(struct GraphNode, parent), false, LOT_GRAPHNODE }, { "parent", LVT_COBJECT_P, offsetof(struct GraphNode, parent), true, LOT_GRAPHNODE },
{ "prev", LVT_COBJECT_P, offsetof(struct GraphNode, prev), false, LOT_GRAPHNODE }, { "prev", LVT_COBJECT_P, offsetof(struct GraphNode, prev), true, LOT_GRAPHNODE },
{ "type", LVT_S16, offsetof(struct GraphNode, type), false, LOT_NONE }, { "type", LVT_S16, offsetof(struct GraphNode, type), false, LOT_NONE },
}; };
@ -855,8 +855,8 @@ static struct LuaObjectField sMarioStateFields[LUA_MARIO_STATE_FIELD_COUNT] = {
{ "invincTimer", LVT_S16, offsetof(struct MarioState, invincTimer), false, LOT_NONE }, { "invincTimer", LVT_S16, offsetof(struct MarioState, invincTimer), false, LOT_NONE },
{ "isSnoring", LVT_U8, offsetof(struct MarioState, isSnoring), false, LOT_NONE }, { "isSnoring", LVT_U8, offsetof(struct MarioState, isSnoring), false, LOT_NONE },
{ "knockbackTimer", LVT_U8, offsetof(struct MarioState, knockbackTimer), false, LOT_NONE }, { "knockbackTimer", LVT_U8, offsetof(struct MarioState, knockbackTimer), false, LOT_NONE },
{ "marioBodyState", LVT_COBJECT_P, offsetof(struct MarioState, marioBodyState), false, LOT_MARIOBODYSTATE }, { "marioBodyState", LVT_COBJECT_P, offsetof(struct MarioState, marioBodyState), true, LOT_MARIOBODYSTATE },
{ "marioObj", LVT_COBJECT_P, offsetof(struct MarioState, marioObj), false, LOT_OBJECT }, { "marioObj", LVT_COBJECT_P, offsetof(struct MarioState, marioObj), true, LOT_OBJECT },
{ "minimumBoneY", LVT_F32, offsetof(struct MarioState, minimumBoneY), false, LOT_NONE }, { "minimumBoneY", LVT_F32, offsetof(struct MarioState, minimumBoneY), false, LOT_NONE },
{ "nonInstantWarpPos", LVT_COBJECT, offsetof(struct MarioState, nonInstantWarpPos), true, LOT_VEC3F }, { "nonInstantWarpPos", LVT_COBJECT, offsetof(struct MarioState, nonInstantWarpPos), true, LOT_VEC3F },
{ "numCoins", LVT_S16, offsetof(struct MarioState, numCoins), false, LOT_NONE }, { "numCoins", LVT_S16, offsetof(struct MarioState, numCoins), false, LOT_NONE },
@ -880,7 +880,7 @@ static struct LuaObjectField sMarioStateFields[LUA_MARIO_STATE_FIELD_COUNT] = {
{ "splineKeyframeFraction", LVT_F32, offsetof(struct MarioState, splineKeyframeFraction), false, LOT_NONE }, { "splineKeyframeFraction", LVT_F32, offsetof(struct MarioState, splineKeyframeFraction), false, LOT_NONE },
{ "splineState", LVT_S32, offsetof(struct MarioState, splineState), false, LOT_NONE }, { "splineState", LVT_S32, offsetof(struct MarioState, splineState), false, LOT_NONE },
{ "squishTimer", LVT_U8, offsetof(struct MarioState, squishTimer), false, LOT_NONE }, { "squishTimer", LVT_U8, offsetof(struct MarioState, squishTimer), false, LOT_NONE },
{ "statusForCamera", LVT_COBJECT_P, offsetof(struct MarioState, statusForCamera), false, LOT_PLAYERCAMERASTATE }, { "statusForCamera", LVT_COBJECT_P, offsetof(struct MarioState, statusForCamera), true, LOT_PLAYERCAMERASTATE },
{ "terrainSoundAddend", LVT_U32, offsetof(struct MarioState, terrainSoundAddend), false, LOT_NONE }, { "terrainSoundAddend", LVT_U32, offsetof(struct MarioState, terrainSoundAddend), false, LOT_NONE },
{ "twirlYaw", LVT_S16, offsetof(struct MarioState, twirlYaw), false, LOT_NONE }, { "twirlYaw", LVT_S16, offsetof(struct MarioState, twirlYaw), false, LOT_NONE },
{ "unkB0", LVT_S16, offsetof(struct MarioState, unkB0), false, LOT_NONE }, { "unkB0", LVT_S16, offsetof(struct MarioState, unkB0), false, LOT_NONE },
@ -1759,9 +1759,9 @@ static struct LuaObjectField sObjectHitboxFields[LUA_OBJECT_HITBOX_FIELD_COUNT]
#define LUA_OBJECT_NODE_FIELD_COUNT 3 #define LUA_OBJECT_NODE_FIELD_COUNT 3
static struct LuaObjectField sObjectNodeFields[LUA_OBJECT_NODE_FIELD_COUNT] = { static struct LuaObjectField sObjectNodeFields[LUA_OBJECT_NODE_FIELD_COUNT] = {
{ "gfx", LVT_COBJECT, offsetof(struct ObjectNode, gfx), true, LOT_GRAPHNODEOBJECT }, { "gfx", LVT_COBJECT, offsetof(struct ObjectNode, gfx), true, LOT_GRAPHNODEOBJECT },
{ "next", LVT_COBJECT_P, offsetof(struct ObjectNode, next), false, LOT_OBJECTNODE }, { "next", LVT_COBJECT_P, offsetof(struct ObjectNode, next), true, LOT_OBJECTNODE },
{ "prev", LVT_COBJECT_P, offsetof(struct ObjectNode, prev), false, LOT_OBJECTNODE }, { "prev", LVT_COBJECT_P, offsetof(struct ObjectNode, prev), true, LOT_OBJECTNODE },
}; };
#define LUA_OBJECT_WARP_NODE_FIELD_COUNT 3 #define LUA_OBJECT_WARP_NODE_FIELD_COUNT 3
@ -1922,10 +1922,10 @@ static struct LuaObjectField sSpawnInfoFields[LUA_SPAWN_INFO_FIELD_COUNT] = {
{ "areaIndex", LVT_S8, offsetof(struct SpawnInfo, areaIndex), false, LOT_NONE }, { "areaIndex", LVT_S8, offsetof(struct SpawnInfo, areaIndex), false, LOT_NONE },
{ "behaviorArg", LVT_U32, offsetof(struct SpawnInfo, behaviorArg), false, LOT_NONE }, { "behaviorArg", LVT_U32, offsetof(struct SpawnInfo, behaviorArg), false, LOT_NONE },
// { "behaviorScript", LVT_???, offsetof(struct SpawnInfo, behaviorScript), false, LOT_??? }, <--- UNIMPLEMENTED // { "behaviorScript", LVT_???, offsetof(struct SpawnInfo, behaviorScript), false, LOT_??? }, <--- UNIMPLEMENTED
{ "next", LVT_COBJECT_P, offsetof(struct SpawnInfo, next), false, LOT_SPAWNINFO }, { "next", LVT_COBJECT_P, offsetof(struct SpawnInfo, next), true, LOT_SPAWNINFO },
{ "startAngle", LVT_COBJECT, offsetof(struct SpawnInfo, startAngle), true, LOT_VEC3S }, { "startAngle", LVT_COBJECT, offsetof(struct SpawnInfo, startAngle), true, LOT_VEC3S },
{ "startPos", LVT_COBJECT, offsetof(struct SpawnInfo, startPos), true, LOT_VEC3S }, { "startPos", LVT_COBJECT, offsetof(struct SpawnInfo, startPos), true, LOT_VEC3S },
{ "syncID", LVT_U32, offsetof(struct SpawnInfo, syncID), true, LOT_NONE }, { "syncID", LVT_U32, offsetof(struct SpawnInfo, syncID), false, LOT_NONE },
{ "unk18", LVT_COBJECT_P, offsetof(struct SpawnInfo, unk18), false, LOT_GRAPHNODE }, { "unk18", LVT_COBJECT_P, offsetof(struct SpawnInfo, unk18), false, LOT_GRAPHNODE },
}; };