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.destNode = CMD_GET(u8, 5);
warpNode->object = NULL;
warpNode->next = gAreas[sCurrAreaIndex].warpNodes;
gAreas[sCurrAreaIndex].warpNodes = warpNode;
}

View File

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

View File

@@ -16,8 +16,7 @@ struct WarpNode {
struct ObjectWarpNode {
/*0x00*/ struct WarpNode node;
/*0x04*/ struct Object *object;
/*0x08*/ struct ObjectWarpNode *next;
/*0x04*/ struct ObjectWarpNode *next;
};
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);
u32 get_mario_spawn_type(struct Object *obj);
struct ObjectWarpNode *area_get_warp_node(u8 id);
struct Object *get_destination_warp_object(u8 warpDestId);
void clear_areas(void);
void clear_area_graph_nodes(void);
void load_area(s32 index);

View File

@@ -31,6 +31,7 @@
#include "puppycam2.h"
#include "puppyprint.h"
#include "level_commands.h"
#include "debug.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) {
struct ObjectWarpNode *spawnNode = area_get_warp_node(sWarpDest.nodeId);
u32 marioSpawnType = get_mario_spawn_type(spawnNode->object);
struct Object *object = get_destination_warp_object(sWarpDest.nodeId);
#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) {
gPlayerSpawnInfos[0].startPos[0] = (s16) spawnNode->object->oPosX;
gPlayerSpawnInfos[0].startPos[1] = (s16) spawnNode->object->oPosY;
gPlayerSpawnInfos[0].startPos[2] = (s16) spawnNode->object->oPosZ;
gPlayerSpawnInfos[0].startPos[0] = (s16) object->oPosX;
gPlayerSpawnInfos[0].startPos[1] = (s16) object->oPosY;
gPlayerSpawnInfos[0].startPos[2] = (s16) object->oPosZ;
gPlayerSpawnInfos[0].startAngle[0] = 0;
gPlayerSpawnInfos[0].startAngle[1] = spawnNode->object->oMoveAngleYaw;
gPlayerSpawnInfos[0].startAngle[1] = object->oMoveAngleYaw;
gPlayerSpawnInfos[0].startAngle[2] = 0;
if (marioSpawnType == MARIO_SPAWN_DOOR_WARP) {
@@ -372,8 +381,8 @@ void init_mario_after_warp(void) {
init_mario();
set_mario_initial_action(gMarioState, marioSpawnType, sWarpDest.arg);
gMarioState->interactObj = spawnNode->object;
gMarioState->usedObj = spawnNode->object;
gMarioState->interactObj = object;
gMarioState->usedObj = object;
}
reset_camera(gCurrentArea->camera);
@@ -569,6 +578,15 @@ void check_instant_warp(void) {
s16 music_unchanged_through_warp(s16 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 destArea = warpNode->node.destArea;
@@ -896,6 +914,14 @@ void initiate_delayed_warp(void) {
default:
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,
warpNode->node.destNode, sDelayedWarpArg);