diff --git a/data/behavior_data.c b/data/behavior_data.c index 6a02545d..50d6791b 100644 --- a/data/behavior_data.c +++ b/data/behavior_data.c @@ -403,8 +403,8 @@ const BehaviorScript bhvStarDoor[] = { SET_INT(oIntangibleTimer, 0), BEGIN_LOOP(), CALL_NATIVE(bhv_star_door_loop), - CALL_NATIVE(bhv_door_rendering_loop), CALL_NATIVE(load_object_collision_model), + CALL_NATIVE(bhv_door_rendering_loop), END_LOOP(), }; diff --git a/levels/castle_inside/areas/1/room.inc.c b/levels/castle_inside/areas/1/room.inc.c index fb101699..12312186 100644 --- a/levels/castle_inside/areas/1/room.inc.c +++ b/levels/castle_inside/areas/1/room.inc.c @@ -2,8 +2,8 @@ const RoomData inside_castle_seg7_area_1_rooms[] = { 1, 9, 9, 1, 9, 9, 9, 9, // 0-7 9, 9, 1, 1, 1, 9, 9, 17, // 8-15 - 1, 9, 9, 9, 9, 9, 17, 9, // 16-23 - 9, 9, 9, 9, 9, 9, 9, 9, // 24-31 + 1, 17, 17, 9, 17, 9, 17, 9, // 16-23 + 9, 9, 17, 9, 9, 9, 9, 9, // 24-31 8, 8, 8, 8, 8, 8, 8, 8, // 32-39 8, 8, 8, 8, 8, 8, 8, 8, // 40-47 8, 8, 8, 8, 8, 8, 8, 8, // 48-55 diff --git a/src/engine/behavior_script.c b/src/engine/behavior_script.c index 5831e19b..5bc76f69 100644 --- a/src/engine/behavior_script.c +++ b/src/engine/behavior_script.c @@ -820,13 +820,11 @@ void cur_obj_update(void) { BhvCommandProc bhvCmdProc; s32 bhvProcResult; - s32 inRoom = is_mario_in_room(); + s32 inRoom = cur_obj_is_mario_in_room(); - if (objFlags & OBJ_FLAG_ONLY_PROCESS_INSIDE_ROOM) { - if (inRoom == MARIO_OUTSIDE_ROOM) { - cur_obj_enable_disable_room_rendering(MARIO_OUTSIDE_ROOM); - return; - } + if (inRoom == MARIO_OUTSIDE_ROOM && (objFlags & OBJ_FLAG_ONLY_PROCESS_INSIDE_ROOM)) { + cur_obj_disable_rendering_in_room(); + return; } // Calculate the distance from the object to Mario. @@ -932,7 +930,11 @@ void cur_obj_update(void) { (objFlags & OBJ_FLAG_ACTIVE_FROM_AFAR) || distanceFromMario < o->oDrawingDistance ) { - cur_obj_enable_disable_room_rendering(inRoom); + if (inRoom == MARIO_OUTSIDE_ROOM) { + cur_obj_disable_rendering_in_room(); + } else if (inRoom == MARIO_INSIDE_ROOM) { + cur_obj_enable_rendering_in_room(); + } o->activeFlags &= ~ACTIVE_FLAG_FAR_AWAY; } else { o->header.gfx.node.flags &= ~GRAPH_RENDER_ACTIVE; diff --git a/src/engine/surface_collision.c b/src/engine/surface_collision.c index 8a40c8b4..007c5748 100644 --- a/src/engine/surface_collision.c +++ b/src/engine/surface_collision.c @@ -650,7 +650,8 @@ f32 find_floor(f32 xPos, f32 yPos, f32 zPos, struct Surface **pfloor) { } f32 find_room_floor(f32 x, f32 y, f32 z, struct Surface **pfloor) { - gCollisionFlags |= (COLLISION_FLAG_RETURN_FIRST | COLLISION_FLAG_EXCLUDE_DYNAMIC | COLLISION_FLAG_INCLUDE_INTANGIBLE); + gCollisionFlags |= (COLLISION_FLAG_EXCLUDE_DYNAMIC | COLLISION_FLAG_INCLUDE_INTANGIBLE); + return find_floor(x, y, z, pfloor); } @@ -660,11 +661,14 @@ f32 find_room_floor(f32 x, f32 y, f32 z, struct Surface **pfloor) { s32 get_room_at_pos(f32 x, f32 y, f32 z) { if (gCurrentArea->surfaceRooms != NULL) { struct Surface *floor; + find_room_floor(x, y, z, &floor); - if (floor) { + + if (floor != NULL) { return floor->room; } } + return -1; } diff --git a/src/game/behaviors/door.inc.c b/src/game/behaviors/door.inc.c index c75bf238..17c84832 100644 --- a/src/game/behaviors/door.inc.c +++ b/src/game/behaviors/door.inc.c @@ -65,6 +65,7 @@ void bhv_door_loop(void) { switch (o->oAction) { case DOOR_ACT_CLOSED: cur_obj_init_animation_with_sound(DOOR_ANIM_CLOSED); + load_object_collision_model(); break; case DOOR_ACT_PULLED: door_animation_and_reset(DOOR_ANIM_PULLED); @@ -83,49 +84,55 @@ void bhv_door_loop(void) { play_warp_door_open_noise(); break; } - if (o->oAction == DOOR_ACT_CLOSED) { - load_object_collision_model(); - } + bhv_door_rendering_loop(); } void bhv_door_init(void) { + const f32 checkDist = 200.0f; + f32 x = o->oPosX; f32 y = o->oPosY; f32 z = o->oPosZ; - struct Surface *floor; - find_room_floor(x, y, z, &floor); - if (floor != NULL) o->oDoorSelfRoom = floor->room; + o->oDoorSelfRoom = get_room_at_pos(x, y, z); - x = o->oPosX + sins(o->oMoveAngleYaw) * 200.0f; - z = o->oPosZ + coss(o->oMoveAngleYaw) * 200.0f; + x = o->oPosX + (sins(o->oMoveAngleYaw) * checkDist); + z = o->oPosZ + (coss(o->oMoveAngleYaw) * checkDist); - find_room_floor(x, y, z, &floor); - if (floor != NULL) o->oDoorForwardRoom = floor->room; + o->oDoorForwardRoom = get_room_at_pos(x, y, z); - x = o->oPosX + sins(o->oMoveAngleYaw) * -200.0f; - z = o->oPosZ + coss(o->oMoveAngleYaw) * -200.0f; + x = o->oPosX + (sins(o->oMoveAngleYaw) * -checkDist); + z = o->oPosZ + (coss(o->oMoveAngleYaw) * -checkDist); - find_room_floor(x, y, z, &floor); - if (floor != NULL) o->oDoorBackwardRoom = floor->room; + o->oDoorBackwardRoom = get_room_at_pos(x, y, z); - if (o->oDoorSelfRoom > 0 && o->oDoorSelfRoom < 60) { - gDoorAdjacentRooms[o->oDoorSelfRoom][0] = o->oDoorForwardRoom; - gDoorAdjacentRooms[o->oDoorSelfRoom][1] = o->oDoorBackwardRoom; + if ( + // Ensure the room number is in bounds. + o->oDoorSelfRoom > 0 && o->oDoorSelfRoom < ARRAY_COUNT(gDoorAdjacentRooms) + // Only set gDoorAdjacentRooms for transition rooms. + && o->oDoorSelfRoom != o->oDoorForwardRoom + && o->oDoorSelfRoom != o->oDoorBackwardRoom + && o->oDoorForwardRoom != o->oDoorBackwardRoom + ) { + gDoorAdjacentRooms[o->oDoorSelfRoom].forwardRoom = o->oDoorForwardRoom; + gDoorAdjacentRooms[o->oDoorSelfRoom].backwardRoom = o->oDoorBackwardRoom; } } void bhv_door_rendering_loop(void) { + struct TransitionRoomData* transitionRoom = &gDoorAdjacentRooms[gMarioCurrentRoom]; + o->oDoorIsRendering = ( - gMarioCurrentRoom == 0 - || gMarioCurrentRoom == o->oDoorSelfRoom - || gMarioCurrentRoom == o->oDoorForwardRoom - || gMarioCurrentRoom == o->oDoorBackwardRoom - || gDoorAdjacentRooms[gMarioCurrentRoom][0] == o->oDoorForwardRoom - || gDoorAdjacentRooms[gMarioCurrentRoom][0] == o->oDoorBackwardRoom - || gDoorAdjacentRooms[gMarioCurrentRoom][1] == o->oDoorForwardRoom - || gDoorAdjacentRooms[gMarioCurrentRoom][1] == o->oDoorBackwardRoom + gMarioCurrentRoom == 0 || // Mario is in the "global" room. + gMarioCurrentRoom == o->oDoorSelfRoom || // Mario is in the same room as the door. + gMarioCurrentRoom == o->oDoorForwardRoom || // Mario is in the door's forward room. + gMarioCurrentRoom == o->oDoorBackwardRoom || // Mario is in the door's backward room. + transitionRoom->forwardRoom == o->oDoorForwardRoom || // The transition room's forward room is in the same room as this door's forward room. + transitionRoom->forwardRoom == o->oDoorBackwardRoom || // The transition room's forward room is in the same room as this door's backward room. + transitionRoom->backwardRoom == o->oDoorForwardRoom || // The transition room's backward room is in the same room as this door's forward room. + transitionRoom->backwardRoom == o->oDoorBackwardRoom // The transition room's backward room is in the same room as this door's backward room. ); + COND_BIT(o->oDoorIsRendering, o->header.gfx.node.flags, GRAPH_RENDER_ACTIVE); } diff --git a/src/game/object_helpers.c b/src/game/object_helpers.c index 64cdb0b2..6af30231 100644 --- a/src/game/object_helpers.c +++ b/src/game/object_helpers.c @@ -119,33 +119,21 @@ Gfx *geo_switch_anim_state(s32 callContext, struct GraphNode *node, UNUSED void } Gfx *geo_switch_area(s32 callContext, struct GraphNode *node, UNUSED void *context) { - struct Surface *floor; struct GraphNodeSwitchCase *switchCase = (struct GraphNodeSwitchCase *) node; + RoomData room; - if (callContext == GEO_CONTEXT_RENDER) { - if (gMarioObject == NULL) { - switchCase->selectedCase = 0; - } else { -#ifdef ENABLE_VANILLA_LEVEL_SPECIFIC_CHECKS - if (gCurrLevelNum == LEVEL_BBH) { - // In BBH, check for a floor manually, since there is an intangible floor. In custom hacks this can be removed. - find_room_floor(gMarioObject->oPosX, gMarioObject->oPosY, gMarioObject->oPosZ, &floor); - } else { - // Since no intangible floors are nearby, use Mario's floor instead. - floor = gMarioState->floor; - } -#else - floor = gMarioState->floor; -#endif - if (floor) { - gMarioCurrentRoom = floor->room; - s16 roomCase = floor->room - 1; - print_debug_top_down_objectinfo("areainfo %d", floor->room); + if (callContext == GEO_CONTEXT_RENDER && gMarioObject != NULL) { + room = get_room_at_pos( + gMarioObject->oPosX, + gMarioObject->oPosY, + gMarioObject->oPosZ + ); - if (roomCase >= 0) { - switchCase->selectedCase = roomCase; - } - } + gMarioCurrentRoom = room; + print_debug_top_down_objectinfo("areainfo %d", room); + + if (room > 0) { + switchCase->selectedCase = (room - 1); } } else { switchCase->selectedCase = 0; @@ -1880,30 +1868,31 @@ void bhv_init_room(void) { o->oRoom = get_room_at_pos(o->oPosX, o->oPosY, o->oPosZ); } -s32 is_mario_in_room(void) { +s32 cur_obj_is_mario_in_room(void) { if (o->oRoom != -1 && gMarioCurrentRoom != 0) { - if ( - gMarioCurrentRoom == o->oRoom || - gDoorAdjacentRooms[gMarioCurrentRoom][0] == o->oRoom || - gDoorAdjacentRooms[gMarioCurrentRoom][1] == o->oRoom + if (gMarioCurrentRoom == o->oRoom // Object is in Mario's room. + || gDoorAdjacentRooms[gMarioCurrentRoom].forwardRoom == o->oRoom // Object is in the transition room's forward room. + || gDoorAdjacentRooms[gMarioCurrentRoom].backwardRoom == o->oRoom // Object is in the transition room's backward room. ) { return MARIO_INSIDE_ROOM; } + return MARIO_OUTSIDE_ROOM; } + return MARIO_ROOM_UNDEFINED; } -void cur_obj_enable_disable_room_rendering(s32 inRoom) { - if (inRoom == MARIO_INSIDE_ROOM) { - cur_obj_enable_rendering(); - o->activeFlags &= ~ACTIVE_FLAG_IN_DIFFERENT_ROOM; - gNumRoomedObjectsInMarioRoom++; - } else if (inRoom == MARIO_OUTSIDE_ROOM) { - cur_obj_disable_rendering(); - o->activeFlags |= ACTIVE_FLAG_IN_DIFFERENT_ROOM; - gNumRoomedObjectsNotInMarioRoom++; - } +void cur_obj_enable_rendering_in_room(void) { + cur_obj_enable_rendering(); + o->activeFlags &= ~ACTIVE_FLAG_IN_DIFFERENT_ROOM; + gNumRoomedObjectsInMarioRoom++; +} + +void cur_obj_disable_rendering_in_room(void) { + cur_obj_disable_rendering(); + o->activeFlags |= ACTIVE_FLAG_IN_DIFFERENT_ROOM; + gNumRoomedObjectsNotInMarioRoom++; } s32 cur_obj_set_hitbox_and_die_if_attacked(struct ObjectHitbox *hitbox, s32 deathSound, s32 noLootCoins) { diff --git a/src/game/object_helpers.h b/src/game/object_helpers.h index 3c257b34..f6858b8a 100644 --- a/src/game/object_helpers.h +++ b/src/game/object_helpers.h @@ -241,8 +241,9 @@ void cur_obj_call_action_function(ObjActionFunc actionFunctions[]); s32 cur_obj_mario_far_away(void); s32 is_mario_moving_fast_or_in_air(s32 speedThreshold); s32 is_item_in_array(s8 item, s8 *array); -s32 is_mario_in_room(void); -void cur_obj_enable_disable_room_rendering(s32 inRoom); +s32 cur_obj_is_mario_in_room(void); +void cur_obj_enable_rendering_in_room(void); +void cur_obj_disable_rendering_in_room(void); s32 cur_obj_set_hitbox_and_die_if_attacked(struct ObjectHitbox *hitbox, s32 deathSound, s32 noLootCoins); void obj_explode_and_spawn_coins(f32 mistSize, s32 coinType); void obj_set_collision_data(struct Object *obj, const void *segAddr); diff --git a/src/game/object_list_processor.c b/src/game/object_list_processor.c index 47f7967b..2b8bfe81 100644 --- a/src/game/object_list_processor.c +++ b/src/game/object_list_processor.c @@ -147,7 +147,7 @@ struct MemoryPool *gObjectMemoryPool; s16 gCollisionFlags = COLLISION_FLAGS_NONE; TerrainData *gEnvironmentRegions; s32 gEnvironmentLevels[20]; -RoomData gDoorAdjacentRooms[60][2]; +struct TransitionRoomData gDoorAdjacentRooms[MAX_NUM_TRANSITION_ROOMS]; s16 gMarioCurrentRoom; s16 gTHIWaterDrained; s16 gTTCSpeedSetting; @@ -522,10 +522,7 @@ void clear_objects(void) { gMarioObject = NULL; gMarioCurrentRoom = 0; - for (i = 0; i < 60; i++) { - gDoorAdjacentRooms[i][0] = 0; - gDoorAdjacentRooms[i][1] = 0; - } + bzero(gDoorAdjacentRooms, sizeof(gDoorAdjacentRooms)); debug_unknown_level_select_check(); diff --git a/src/game/object_list_processor.h b/src/game/object_list_processor.h index d8fe0251..a5cb4b85 100644 --- a/src/game/object_list_processor.h +++ b/src/game/object_list_processor.h @@ -109,9 +109,22 @@ enum CollisionFlags { }; extern s16 gCollisionFlags; + extern TerrainData *gEnvironmentRegions; extern s32 gEnvironmentLevels[20]; -extern RoomData gDoorAdjacentRooms[60][2]; + +/** + * The maximum number of door/transition rooms that load two rooms of objects at once. + */ +#define MAX_NUM_TRANSITION_ROOMS 60 + +struct TransitionRoomData { + /*0x00*/ RoomData forwardRoom; + /*0x01*/ RoomData backwardRoom; +}; /*0x02*/ + +extern struct TransitionRoomData gDoorAdjacentRooms[MAX_NUM_TRANSITION_ROOMS]; + extern s16 gMarioCurrentRoom; extern s16 gTHIWaterDrained; extern s16 gTTCSpeedSetting;