Remove destination warp node requirement (#788)

Also add assertions for common warp crashes and remove the hardcoded get_mario_spawn_type table size
This commit is contained in:
Gregory Heskett
2024-04-30 23:10:58 -04:00
committed by GitHub
parent f3e1496d29
commit aedae64e8b
4 changed files with 43 additions and 25 deletions

View File

@@ -523,8 +523,6 @@ static void level_cmd_create_warp_node(void) {
warpNode->node.destArea = CMD_GET(u8, 4); warpNode->node.destArea = CMD_GET(u8, 4);
warpNode->node.destNode = CMD_GET(u8, 5); warpNode->node.destNode = CMD_GET(u8, 5);
warpNode->object = NULL;
warpNode->next = gAreas[sCurrAreaIndex].warpNodes; warpNode->next = gAreas[sCurrAreaIndex].warpNodes;
gAreas[sCurrAreaIndex].warpNodes = warpNode; gAreas[sCurrAreaIndex].warpNodes = warpNode;
} }

View File

@@ -139,7 +139,7 @@ u32 get_mario_spawn_type(struct Object *obj) {
s32 i; s32 i;
const BehaviorScript *behavior = virtual_to_segmented(SEGMENT_BEHAVIOR_DATA, obj->behavior); const BehaviorScript *behavior = virtual_to_segmented(SEGMENT_BEHAVIOR_DATA, obj->behavior);
for (i = 0; i < 20; i++) { for (i = 0; i < ARRAY_COUNT(sWarpBhvSpawnTable); i++) {
if (sWarpBhvSpawnTable[i] == behavior) { if (sWarpBhvSpawnTable[i] == behavior) {
return sSpawnTypeFromWarpBhv[i]; return sSpawnTypeFromWarpBhv[i];
} }
@@ -158,25 +158,20 @@ struct ObjectWarpNode *area_get_warp_node(u8 id) {
return node; return node;
} }
struct ObjectWarpNode *area_get_warp_node_from_params(struct Object *obj) { struct Object *get_destination_warp_object(u8 warpDestId) {
return area_get_warp_node(GET_BPARAM2(obj->oBehParams));
}
void load_obj_warp_nodes(void) {
struct ObjectWarpNode *warpNode;
struct Object *children = (struct Object *) gObjParentGraphNode.children; struct Object *children = (struct Object *) gObjParentGraphNode.children;
do { do {
struct Object *obj = children; struct Object *obj = children;
if (obj->activeFlags != ACTIVE_FLAG_DEACTIVATED && get_mario_spawn_type(obj) != 0) { u8 bparam2 = GET_BPARAM2(obj->oBehParams);
warpNode = area_get_warp_node_from_params(obj); if (warpDestId == bparam2 && obj->activeFlags != ACTIVE_FLAG_DEACTIVATED && get_mario_spawn_type(obj) != MARIO_SPAWN_NONE) {
if (warpNode != NULL) { return obj;
warpNode->object = obj;
}
} }
} while ((children = (struct Object *) children->header.gfx.node.next) } while ((children = (struct Object *) children->header.gfx.node.next)
!= (struct Object *) gObjParentGraphNode.children); != (struct Object *) gObjParentGraphNode.children);
return NULL;
} }
void clear_areas(void) { void clear_areas(void) {
@@ -251,7 +246,6 @@ void load_area(s32 index) {
spawn_objects_from_info(0, gCurrentArea->objectSpawnInfos); spawn_objects_from_info(0, gCurrentArea->objectSpawnInfos);
} }
load_obj_warp_nodes();
geo_call_global_function_nodes(&gCurrentArea->graphNode->node, GEO_CONTEXT_AREA_LOAD); geo_call_global_function_nodes(&gCurrentArea->graphNode->node, GEO_CONTEXT_AREA_LOAD);
} }
} }

View File

@@ -16,8 +16,7 @@ struct WarpNode {
struct ObjectWarpNode { struct ObjectWarpNode {
/*0x00*/ struct WarpNode node; /*0x00*/ struct WarpNode node;
/*0x04*/ struct Object *object; /*0x04*/ struct ObjectWarpNode *next;
/*0x08*/ struct ObjectWarpNode *next;
}; };
struct InstantWarp { struct InstantWarp {
@@ -185,6 +184,7 @@ void override_viewport_and_clip(Vp *a, Vp *b, u8 c, u8 d, u8 e);
void print_intro_text(void); void print_intro_text(void);
u32 get_mario_spawn_type(struct Object *obj); u32 get_mario_spawn_type(struct Object *obj);
struct ObjectWarpNode *area_get_warp_node(u8 id); struct ObjectWarpNode *area_get_warp_node(u8 id);
struct Object *get_destination_warp_object(u8 warpDestId);
void clear_areas(void); void clear_areas(void);
void clear_area_graph_nodes(void); void clear_area_graph_nodes(void);
void load_area(s32 index); void load_area(s32 index);

View File

@@ -31,6 +31,7 @@
#include "puppycam2.h" #include "puppycam2.h"
#include "puppyprint.h" #include "puppyprint.h"
#include "level_commands.h" #include "level_commands.h"
#include "debug.h"
#include "config.h" #include "config.h"
@@ -348,16 +349,24 @@ void set_mario_initial_action(struct MarioState *m, u32 spawnType, u32 actionArg
} }
void init_mario_after_warp(void) { void init_mario_after_warp(void) {
struct ObjectWarpNode *spawnNode = area_get_warp_node(sWarpDest.nodeId); struct Object *object = get_destination_warp_object(sWarpDest.nodeId);
u32 marioSpawnType = get_mario_spawn_type(spawnNode->object);
#ifdef DEBUG_ASSERTIONS
if (!object) {
char errorMsg[40];
sprintf(errorMsg, "No dest warp object found for: 0x%02X", sWarpDest.nodeId);
error(errorMsg);
}
#endif
u32 marioSpawnType = get_mario_spawn_type(object);
if (gMarioState->action != ACT_UNINITIALIZED) { if (gMarioState->action != ACT_UNINITIALIZED) {
gPlayerSpawnInfos[0].startPos[0] = (s16) spawnNode->object->oPosX; gPlayerSpawnInfos[0].startPos[0] = (s16) object->oPosX;
gPlayerSpawnInfos[0].startPos[1] = (s16) spawnNode->object->oPosY; gPlayerSpawnInfos[0].startPos[1] = (s16) object->oPosY;
gPlayerSpawnInfos[0].startPos[2] = (s16) spawnNode->object->oPosZ; gPlayerSpawnInfos[0].startPos[2] = (s16) object->oPosZ;
gPlayerSpawnInfos[0].startAngle[0] = 0; gPlayerSpawnInfos[0].startAngle[0] = 0;
gPlayerSpawnInfos[0].startAngle[1] = spawnNode->object->oMoveAngleYaw; gPlayerSpawnInfos[0].startAngle[1] = object->oMoveAngleYaw;
gPlayerSpawnInfos[0].startAngle[2] = 0; gPlayerSpawnInfos[0].startAngle[2] = 0;
if (marioSpawnType == MARIO_SPAWN_DOOR_WARP) { if (marioSpawnType == MARIO_SPAWN_DOOR_WARP) {
@@ -372,8 +381,8 @@ void init_mario_after_warp(void) {
init_mario(); init_mario();
set_mario_initial_action(gMarioState, marioSpawnType, sWarpDest.arg); set_mario_initial_action(gMarioState, marioSpawnType, sWarpDest.arg);
gMarioState->interactObj = spawnNode->object; gMarioState->interactObj = object;
gMarioState->usedObj = spawnNode->object; gMarioState->usedObj = object;
} }
reset_camera(gCurrentArea->camera); reset_camera(gCurrentArea->camera);
@@ -569,6 +578,15 @@ void check_instant_warp(void) {
s16 music_unchanged_through_warp(s16 arg) { s16 music_unchanged_through_warp(s16 arg) {
struct ObjectWarpNode *warpNode = area_get_warp_node(arg); struct ObjectWarpNode *warpNode = area_get_warp_node(arg);
#ifdef DEBUG_ASSERTIONS
if (!warpNode) {
char errorMsg[40];
sprintf(errorMsg, "No source warp node found for: 0x%02X", (u8) arg);
error(errorMsg);
}
#endif
s16 levelNum = warpNode->node.destLevel & 0x7F; s16 levelNum = warpNode->node.destLevel & 0x7F;
s16 destArea = warpNode->node.destArea; s16 destArea = warpNode->node.destArea;
@@ -896,6 +914,14 @@ void initiate_delayed_warp(void) {
default: default:
warpNode = area_get_warp_node(sSourceWarpNodeId); warpNode = area_get_warp_node(sSourceWarpNodeId);
#ifdef DEBUG_ASSERTIONS
if (!warpNode) {
char errorMsg[40];
sprintf(errorMsg, "No source warp node found for: 0x%02X", (u8) sSourceWarpNodeId);
error(errorMsg);
}
#endif
initiate_warp(warpNode->node.destLevel & 0x7F, warpNode->node.destArea, initiate_warp(warpNode->node.destLevel & 0x7F, warpNode->node.destArea,
warpNode->node.destNode, sDelayedWarpArg); warpNode->node.destNode, sDelayedWarpArg);