diff options
Diffstat (limited to 'src/code')
| -rw-r--r-- | src/code/z_actor.c | 4 | ||||
| -rw-r--r-- | src/code/z_bgcheck.c | 125 | ||||
| -rw-r--r-- | src/code/z_camera.c | 7 | ||||
| -rw-r--r-- | src/code/z_play.c | 4 |
4 files changed, 84 insertions, 56 deletions
diff --git a/src/code/z_actor.c b/src/code/z_actor.c index 13cd13160..4fb43be5b 100644 --- a/src/code/z_actor.c +++ b/src/code/z_actor.c @@ -1489,8 +1489,8 @@ void Actor_UpdateBgCheckInfo(PlayState* play, Actor* actor, f32 wallCheckHeight, sp64.y = actor->prevPos.y; func_8002E2AC(play, actor, &sp64, flags); waterBoxYSurface = actor->world.pos.y; - if (WaterBox_GetSurface1(play, &play->colCtx, actor->world.pos.x, actor->world.pos.z, &waterBoxYSurface, - &waterBox)) { + if (BgCheck_GetWaterSurfaceAllHack(play, &play->colCtx, actor->world.pos.x, actor->world.pos.z, + &waterBoxYSurface, &waterBox)) { actor->depthInWater = waterBoxYSurface - actor->world.pos.y; if (actor->depthInWater < 0.0f) { actor->bgCheckFlags &= ~(BGCHECKFLAG_WATER | BGCHECKFLAG_WATER_TOUCH); diff --git a/src/code/z_bgcheck.c b/src/code/z_bgcheck.c index 656bb04b5..0cd8ab9e2 100644 --- a/src/code/z_bgcheck.c +++ b/src/code/z_bgcheck.c @@ -4247,7 +4247,14 @@ u32 func_80042108(CollisionContext* colCtx, CollisionPoly* poly, s32 bgId) { /** * Zora's Domain WaterBox in King Zora's Room */ -WaterBox sZorasDomainWaterBox = { -348, 877, -1746, 553, 780, 0x2104 }; +WaterBox sZorasDomainWaterBox = { + -348, // xMin + 877, // ySurface + -1746, // zMin + 553, // xLength + 780, // zLength + WATERBOX_PROPERTIES(/* bgCamIndex */ 4, /* lightIndex */ 1, /* roomIndex */ 1, /* isDisabled */ false), +}; /** * WaterBox's effective bounding box @@ -4260,31 +4267,38 @@ f32 sZorasDomainWaterBoxMaxY = 977.0f; f32 sZorasDomainWaterBoxMaxZ = -967.0f; /** - * Public. Get the water surface at point (`x`, `ySurface`, `z`). `ySurface` doubles as position y input - * returns true if point is within the xz boundaries of an active water box, else false - * `ySurface` returns the water box's surface, while `outWaterBox` returns a pointer to the WaterBox + * Get the water surface at point (`x`, `y`, `z`). `y` doubles as `outWaterSurface` result + * returns true if point is within the xz boundaries of an active WaterBox, else false + * `y` returns the WaterBox's surface + * `outWaterBox` returns a pointer to the WaterBox + * + * This performs a special case check on a custom waterbox in Zora's Domain that has a finite depth + * Otherwise, the search performed assumes waterboxes do not overlap, and have infinite depth. */ -s32 WaterBox_GetSurface1(PlayState* play, CollisionContext* colCtx, f32 x, f32 z, f32* ySurface, - WaterBox** outWaterBox) { +s32 BgCheck_GetWaterSurfaceAllHack(PlayState* play, CollisionContext* colCtx, f32 x, f32 z, f32* y, + WaterBox** outWaterBox) { if (play->sceneId == SCENE_ZORAS_DOMAIN) { s32 pad; - if (sZorasDomainWaterBoxMinX < x && x < sZorasDomainWaterBoxMaxX && sZorasDomainWaterBoxMinY < *ySurface && - *ySurface < sZorasDomainWaterBoxMaxY && sZorasDomainWaterBoxMinZ < z && z < sZorasDomainWaterBoxMaxZ) { + if (sZorasDomainWaterBoxMinX < x && x < sZorasDomainWaterBoxMaxX && sZorasDomainWaterBoxMinY < *y && + *y < sZorasDomainWaterBoxMaxY && sZorasDomainWaterBoxMinZ < z && z < sZorasDomainWaterBoxMaxZ) { *outWaterBox = &sZorasDomainWaterBox; - *ySurface = sZorasDomainWaterBox.ySurface; + *y = sZorasDomainWaterBox.ySurface; return true; } } - return WaterBox_GetSurfaceImpl(play, colCtx, x, z, ySurface, outWaterBox); + return BgCheck_GetWaterSurface(play, colCtx, x, z, y, outWaterBox); } /** - * Internal. Get the water surface at point (`x`, `ySurface`, `z`). `ySurface` doubles as position y input - * returns true if point is within the xz boundaries of an active water box, else false - * `ySurface` returns the water box's surface, while `outWaterBox` returns a pointer to the WaterBox + * Get the water surface at point (`x`, `z`). + * returns true if point is within the xz boundaries of an active WaterBox, else false + * `outWaterSurface` returns the WaterBox's surface + * `outWaterBox` returns a pointer to the WaterBox + * + * The search performed assumes waterboxes do not overlap, and have infinite depth. */ -s32 WaterBox_GetSurfaceImpl(PlayState* play, CollisionContext* colCtx, f32 x, f32 z, f32* ySurface, +s32 BgCheck_GetWaterSurface(PlayState* play, CollisionContext* colCtx, f32 x, f32 z, f32* outWaterSurface, WaterBox** outWaterBox) { CollisionHeader* colHeader = colCtx->colHeader; s32 room; @@ -4296,15 +4310,20 @@ s32 WaterBox_GetSurfaceImpl(PlayState* play, CollisionContext* colCtx, f32 x, f3 for (waterBox = colHeader->waterBoxes; waterBox < colHeader->waterBoxes + colHeader->numWaterBoxes; waterBox++) { room = WATERBOX_ROOM(waterBox->properties); - if (room == play->roomCtx.curRoom.num || room == WATERBOX_ROOM_ALL) { - if (!(waterBox->properties & WATERBOX_FLAG_19)) { - if (waterBox->xMin < x && x < waterBox->xMin + waterBox->xLength) { - if (waterBox->zMin < z && z < waterBox->zMin + waterBox->zLength) { - *outWaterBox = waterBox; - *ySurface = waterBox->ySurface; - return true; - } - } + if (room != play->roomCtx.curRoom.num && room != WATERBOX_ROOM_ALL) { + continue; + } + if (waterBox->properties & WATERBOX_IS_DISABLED) { + continue; + } + //! @bug: WaterBox bounds check issue. This range check excludes all points falling exactly on the border of the + //! WaterBox. Thus, when two waterboxes are flush against each other, a seam will exist between them where no + //! water is detected. + if (waterBox->xMin < x && x < waterBox->xMin + waterBox->xLength) { + if (waterBox->zMin < z && z < waterBox->zMin + waterBox->zLength) { + *outWaterBox = waterBox; + *outWaterSurface = waterBox->ySurface; + return true; } } } @@ -4312,12 +4331,12 @@ s32 WaterBox_GetSurfaceImpl(PlayState* play, CollisionContext* colCtx, f32 x, f3 } /** - * Gets the first active WaterBox at `pos` with WATERBOX_FLAG_19 not set + * Gets the first active WaterBox at `pos`, within +- `surfaceChkDist` * `surfaceChkDist` is the absolute y distance from the water surface to check * returns the index of the waterbox found, or -1 if no waterbox is found * `outWaterBox` returns the pointer to the waterbox found, or NULL if none is found */ -s32 WaterBox_GetSurface2(PlayState* play, CollisionContext* colCtx, Vec3f* pos, f32 surfaceChkDist, +s32 BgCheck_FindWaterBox(PlayState* play, CollisionContext* colCtx, Vec3f* pos, f32 surfaceChkDist, WaterBox** outWaterBox) { CollisionHeader* colHeader = colCtx->colHeader; s32 room; @@ -4334,16 +4353,18 @@ s32 WaterBox_GetSurface2(PlayState* play, CollisionContext* colCtx, Vec3f* pos, waterBox = &colHeader->waterBoxes[i]; room = WATERBOX_ROOM(waterBox->properties); - if (room == play->roomCtx.curRoom.num || room == WATERBOX_ROOM_ALL) { - if (!(waterBox->properties & WATERBOX_FLAG_19)) { - if (waterBox->xMin < pos->x && pos->x < waterBox->xMin + waterBox->xLength) { - if (waterBox->zMin < pos->z && pos->z < waterBox->zMin + waterBox->zLength) { - if (pos->y - surfaceChkDist < waterBox->ySurface && - waterBox->ySurface < pos->y + surfaceChkDist) { - *outWaterBox = waterBox; - return i; - } - } + if (room != play->roomCtx.curRoom.num && room != WATERBOX_ROOM_ALL) { + continue; + } + if (waterBox->properties & WATERBOX_IS_DISABLED) { + continue; + } + //! @bug: WaterBox bounds check issue. See BgCheck_GetWaterSurface for more details. + if ((waterBox->xMin < pos->x) && (pos->x < waterBox->xMin + waterBox->xLength)) { + if ((waterBox->zMin < pos->z) && (pos->z < waterBox->zMin + waterBox->zLength)) { + if (pos->y - surfaceChkDist < waterBox->ySurface && waterBox->ySurface < pos->y + surfaceChkDist) { + *outWaterBox = waterBox; + return i; } } } @@ -4386,12 +4407,15 @@ u32 WaterBox_GetLightIndex(CollisionContext* colCtx, WaterBox* waterBox) { } /** - * Get the water surface at point (`x`, `ySurface`, `z`). `ySurface` doubles as position y input - * same as WaterBox_GetSurfaceImpl, but tests if WATERBOX_FLAG_19 is set - * returns true if point is within the xz boundaries of an active water box, else false - * `ySurface` returns the water box's surface, while `outWaterBox` returns a pointer to the WaterBox + * Unused. Gets the water surface? at point (`x`, `z`) for disabled? waterboxes only. + * returns true if point is within the xz boundaries of a disabled? WaterBox, else false + * `outWaterSurface` returns the WaterBox's surface + * `outWaterBox` returns a pointer to the WaterBox + * + * The search performed assumes waterboxes do not overlap. */ -s32 func_800425B0(PlayState* play, CollisionContext* colCtx, f32 x, f32 z, f32* ySurface, WaterBox** outWaterBox) { +s32 func_800425B0(PlayState* play, CollisionContext* colCtx, f32 x, f32 z, f32* outWaterSurface, + WaterBox** outWaterBox) { CollisionHeader* colHeader = colCtx->colHeader; s32 room; WaterBox* waterBox; @@ -4402,15 +4426,18 @@ s32 func_800425B0(PlayState* play, CollisionContext* colCtx, f32 x, f32 z, f32* for (waterBox = colHeader->waterBoxes; waterBox < colHeader->waterBoxes + colHeader->numWaterBoxes; waterBox++) { room = WATERBOX_ROOM(waterBox->properties); - if ((room == play->roomCtx.curRoom.num) || (room == WATERBOX_ROOM_ALL)) { - if (waterBox->properties & WATERBOX_FLAG_19) { - if (waterBox->xMin < x && x < (waterBox->xMin + waterBox->xLength)) { - if (waterBox->zMin < z && z < (waterBox->zMin + waterBox->zLength)) { - *outWaterBox = waterBox; - *ySurface = waterBox->ySurface; - return true; - } - } + if ((room != play->roomCtx.curRoom.num) && (room != WATERBOX_ROOM_ALL)) { + continue; + } + if (!(waterBox->properties & WATERBOX_IS_DISABLED)) { + continue; + } + //! @bug: WaterBox bounds check issue. See BgCheck_GetWaterSurface for more details. + if (waterBox->xMin < x && x < (waterBox->xMin + waterBox->xLength)) { + if (waterBox->zMin < z && z < (waterBox->zMin + waterBox->zLength)) { + *outWaterBox = waterBox; + *outWaterSurface = waterBox->ySurface; + return true; } } } diff --git a/src/code/z_camera.c b/src/code/z_camera.c index b94c5beda..fb8b1ccf1 100644 --- a/src/code/z_camera.c +++ b/src/code/z_camera.c @@ -685,8 +685,8 @@ s32 Camera_GetWaterBoxBgCamIndex(Camera* camera, f32* waterY) { playerPosRot = Actor_GetWorldPosShapeRot(&camera->player->actor); *waterY = playerPosRot.pos.y; - if (!WaterBox_GetSurface1(camera->play, &camera->play->colCtx, playerPosRot.pos.x, playerPosRot.pos.z, waterY, - &waterBox)) { + if (!BgCheck_GetWaterSurfaceAllHack(camera->play, &camera->play->colCtx, playerPosRot.pos.x, playerPosRot.pos.z, + waterY, &waterBox)) { // player's position is not within the x/z boundaries of a water box. *waterY = BGCHECK_Y_MIN; return -1; @@ -722,7 +722,8 @@ f32 Camera_GetWaterSurface(Camera* camera, Vec3f* chkPos, s32* lightIndex) { playerPosRot = Actor_GetWorldPosShapeRot(&camera->player->actor); waterY = playerPosRot.pos.y; - if (!WaterBox_GetSurface1(camera->play, &camera->play->colCtx, chkPos->x, chkPos->z, &waterY, &waterBox)) { + if (!BgCheck_GetWaterSurfaceAllHack(camera->play, &camera->play->colCtx, chkPos->x, chkPos->z, &waterY, + &waterBox)) { // chkPos is not within the x/z boundaries of a water box. return BGCHECK_Y_MIN; } diff --git a/src/code/z_play.c b/src/code/z_play.c index ad0023e2d..acacb7174 100644 --- a/src/code/z_play.c +++ b/src/code/z_play.c @@ -1974,8 +1974,8 @@ s32 func_800C0DB4(PlayState* this, Vec3f* pos) { waterSurfacePos = *pos; - if (WaterBox_GetSurface1(this, &this->colCtx, waterSurfacePos.x, waterSurfacePos.z, &waterSurfacePos.y, - &waterBox) == true && + if (BgCheck_GetWaterSurfaceAllHack(this, &this->colCtx, waterSurfacePos.x, waterSurfacePos.z, &waterSurfacePos.y, + &waterBox) == true && pos->y < waterSurfacePos.y && BgCheck_EntityRaycastDown3(&this->colCtx, &poly, &bgId, &waterSurfacePos) != BGCHECK_Y_MIN) { return true; |
