diff --git a/src/engine/surface_collision.c b/src/engine/surface_collision.c index e12aacf9..fb4c7808 100644 --- a/src/engine/surface_collision.c +++ b/src/engine/surface_collision.c @@ -499,43 +499,45 @@ f32 find_floor(f32 xPos, f32 yPos, f32 zPos, struct Surface **pfloor) { #endif return height; } - // Each level is split into cells to limit load, find the appropriate cell. cellX = ((x + LEVEL_BOUNDARY_MAX) / CELL_SIZE) & NUM_CELLS_INDEX; cellZ = ((z + LEVEL_BOUNDARY_MAX) / CELL_SIZE) & NUM_CELLS_INDEX; - - // Check for surfaces belonging to objects. - surfaceList = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_FLOORS].next; - dynamicFloor = find_floor_from_list(surfaceList, x, y, z, &dynamicHeight); - // Check for surfaces that are a part of level geometry. surfaceList = gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_FLOORS].next; floor = find_floor_from_list(surfaceList, x, y, z, &height); - + if (!gFindFloorExcludeDynamic) { + // In the next check, only check for floors higher than the previous check + dynamicHeight = height; + // Check for surfaces belonging to objects. + surfaceList = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_FLOORS].next; + dynamicFloor = find_floor_from_list(surfaceList, x, y, z, &dynamicHeight); + if (dynamicHeight > height) { + floor = dynamicFloor; + height = dynamicHeight; + } + } // To prevent accidentally leaving the floor tangible, stop checking for it. gFindFloorIncludeSurfaceIntangible = FALSE; + gFindFloorExcludeDynamic = FALSE; // If a floor was missed, increment the debug counter. if (floor == NULL) { gNumFindFloorMisses++; } - - if (dynamicHeight > height) { - floor = dynamicFloor; - height = dynamicHeight; - } - *pfloor = floor; - // Increment the debug tracker. gNumCalls.floor++; - - #if PUPPYPRINT_DEBUG - collisionTime[perfIteration] += osGetTime()-first; - #endif - +#if PUPPYPRINT_DEBUG + collisionTime[perfIteration] += osGetTime() - first; +#endif return height; } +f32 find_room_floor(f32 x, f32 y, f32 z, struct Surface **pfloor) { + gFindFloorIncludeSurfaceIntangible = TRUE; + gFindFloorExcludeDynamic = TRUE; + return find_floor(x, y, z, pfloor); +} + /** * Find the highest water floor under a given position and return the height. */ diff --git a/src/engine/surface_collision.h b/src/engine/surface_collision.h index bd1ebd36..eb174505 100644 --- a/src/engine/surface_collision.h +++ b/src/engine/surface_collision.h @@ -41,6 +41,7 @@ void resolve_and_return_wall_collisions(Vec3f pos, f32 offset, f32 radius, struc f32 find_ceil(f32 posX, f32 posY, f32 posZ, struct Surface **pceil); f32 find_floor_height(f32 x, f32 y, f32 z); 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); s32 find_water_level_and_floor(s32 x, s32 z, struct Surface **pfloor); s32 find_water_level(s32 x, s32 z); s32 find_poison_gas_level(s32 x, s32 z); diff --git a/src/game/behaviors/door.inc.c b/src/game/behaviors/door.inc.c index 8685fdcb..9f529fbd 100644 --- a/src/game/behaviors/door.inc.c +++ b/src/game/behaviors/door.inc.c @@ -84,21 +84,21 @@ void bhv_door_init(void) { f32 x = o->oPosX; f32 z = o->oPosZ; struct Surface *floor; - find_floor(x, o->oPosY, z, &floor); + find_room_floor(x, o->oPosY, z, &floor); if (floor != NULL) { o->oDoorSelfRoom = floor->room; } x = o->oPosX + sins(o->oMoveAngleYaw) * 200.0f; z = o->oPosZ + coss(o->oMoveAngleYaw) * 200.0f; - find_floor(x, o->oPosY, z, &floor); + find_room_floor(x, o->oPosY, z, &floor); if (floor != NULL) { o->oDoorForwardRoom = floor->room; } x = o->oPosX + sins(o->oMoveAngleYaw) * -200.0f; z = o->oPosZ + coss(o->oMoveAngleYaw) * -200.0f; - find_floor(x, o->oPosY, z, &floor); + find_room_floor(x, o->oPosY, z, &floor); if (floor != NULL) { o->oDoorBackwardRoom = floor->room; } diff --git a/src/game/object_helpers.c b/src/game/object_helpers.c index 7351e090..dc1df145 100644 --- a/src/game/object_helpers.c +++ b/src/game/object_helpers.c @@ -155,9 +155,13 @@ Gfx *geo_switch_area(s32 callContext, struct GraphNode *node, UNUSED void *conte if (gMarioObject == NULL) { switchCase->selectedCase = 0; } else { - gFindFloorIncludeSurfaceIntangible = TRUE; - - find_floor(gMarioObject->oPosX, gMarioObject->oPosY, gMarioObject->oPosZ, &floor); + 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; + } if (floor) { gMarioCurrentRoom = floor->room; @@ -1981,28 +1985,15 @@ s32 is_item_in_array(s8 item, s8 *array) { } void bhv_init_room(void) { - struct Surface *floor; - f32 floorHeight; - + struct Surface *floor = NULL; if (is_item_in_array(gCurrLevelNum, sLevelsWithRooms)) { - floorHeight = find_floor(o->oPosX, o->oPosY, o->oPosZ, &floor); - + find_room_floor(o->oPosX, o->oPosY, o->oPosZ, &floor); if (floor != NULL) { - if (floor->room != 0) { - o->oRoom = floor->room; - } else { - // Floor probably belongs to a platform object. Try looking - // underneath it - find_floor(o->oPosX, floorHeight - 100.0f, o->oPosZ, &floor); - if (floor != NULL) { - //! Technically possible that the room could still be 0 here - o->oRoom = floor->room; - } - } + o->oRoom = floor->room; + return; } - } else { - o->oRoom = -1; } + o->oRoom = -1; } void cur_obj_enable_rendering_if_mario_in_room(void) { diff --git a/src/game/object_list_processor.c b/src/game/object_list_processor.c index ebdf8456..13c51f72 100644 --- a/src/game/object_list_processor.c +++ b/src/game/object_list_processor.c @@ -146,6 +146,7 @@ struct MemoryPool *gObjectMemoryPool; s16 gCheckingSurfaceCollisionsForCamera; s16 gFindFloorIncludeSurfaceIntangible; +s16 gFindFloorExcludeDynamic; TerrainData *gEnvironmentRegions; s32 gEnvironmentLevels[20]; RoomData gDoorAdjacentRooms[60][2]; diff --git a/src/game/object_list_processor.h b/src/game/object_list_processor.h index a5152fbd..7c3c6099 100644 --- a/src/game/object_list_processor.h +++ b/src/game/object_list_processor.h @@ -100,6 +100,7 @@ extern struct MemoryPool *gObjectMemoryPool; extern s16 gCheckingSurfaceCollisionsForCamera; extern s16 gFindFloorIncludeSurfaceIntangible; +extern s16 gFindFloorExcludeDynamic; extern TerrainData *gEnvironmentRegions; extern s32 gEnvironmentLevels[20]; extern RoomData gDoorAdjacentRooms[60][2];