-
Notifications
You must be signed in to change notification settings - Fork 677
Document pass on WaterBox code #2695
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -30,7 +30,6 @@ typedef struct ScaleRotPos { | |||||||||||
| } ScaleRotPos; // size = 0x20 | ||||||||||||
|
|
||||||||||||
| // Macros for `CollisionPoly` | ||||||||||||
|
|
||||||||||||
| #define COLPOLY_NORMAL_FRAC (1.0f / SHT_MAX) | ||||||||||||
| #define COLPOLY_SNORMAL(x) ((s16)((x) * SHT_MAX)) | ||||||||||||
| #define COLPOLY_GET_NORMAL(n) ((n)*COLPOLY_NORMAL_FRAC) | ||||||||||||
|
|
@@ -39,14 +38,14 @@ typedef struct ScaleRotPos { | |||||||||||
| #define COLPOLY_VTX_INDEX(vI) ((vI) & 0x1FFF) | ||||||||||||
| #define COLPOLY_VTX(vtxId, flags) ((((flags) & 7) << 13) | ((vtxId) & 0x1FFF)) | ||||||||||||
|
|
||||||||||||
| // flags for flags_vIA | ||||||||||||
| // flags for variable flags_vIA | ||||||||||||
| // poly exclusion flags (xpFlags) | ||||||||||||
| #define COLPOLY_IGNORE_NONE 0 | ||||||||||||
| #define COLPOLY_IGNORE_CAMERA (1 << 0) | ||||||||||||
| #define COLPOLY_IGNORE_ENTITY (1 << 1) | ||||||||||||
| #define COLPOLY_IGNORE_PROJECTILES (1 << 2) | ||||||||||||
|
|
||||||||||||
| // flags for flags_vIB | ||||||||||||
| // flags for variable flags_vIB | ||||||||||||
| #define COLPOLY_IS_FLOOR_CONVEYOR (1 << 0) | ||||||||||||
|
|
||||||||||||
| typedef struct CollisionPoly { | ||||||||||||
|
|
@@ -87,23 +86,23 @@ typedef struct BgCamFuncData { | |||||||||||
| } BgCamFuncData; // size = 0x12 | ||||||||||||
|
|
||||||||||||
| // Macros for `WaterBox.properties` | ||||||||||||
| #define WATERBOX_PROPERTIES(bgCamIndex, lightIndex, roomIndex, isDisabled) \ | ||||||||||||
| ((((bgCamIndex) & 0xFF) << 0) | \ | ||||||||||||
| (((lightIndex) & 0x1F) << 8) | \ | ||||||||||||
| (((roomIndex) & 0x3F) << 13) | \ | ||||||||||||
| (((isDisabled) & 1) << 19)) | ||||||||||||
|
|
||||||||||||
| #define WATERBOX_LIGHT_INDEX_NONE 0x1F // warns and defaults to 0 | ||||||||||||
|
|
||||||||||||
| #define WATERBOX_ROOM(properties) (((properties) >> 13) & 0x3F) | ||||||||||||
| #define WATERBOX_LIGHT_INDEX_NONE 0x1F // Generates warning when built for debug and defaults to 0 | ||||||||||||
| #define WATERBOX_ROOM(properties) (((properties) >> 13) & 0x3F) // retrieves the room the waterbox is active in | ||||||||||||
| #define WATERBOX_ROOM_ALL 0x3F // value for "room index" indicating "all rooms" | ||||||||||||
|
|
||||||||||||
| #define WATERBOX_FLAG_19 (1 << 19) | ||||||||||||
|
|
||||||||||||
| #define WATERBOX_PROPERTIES(bgCamIndex, lightIndex, room, setFlag19) \ | ||||||||||||
| ((((bgCamIndex) & 0xFF) << 0) | \ | ||||||||||||
| (((lightIndex) & 0x1F) << 8) | \ | ||||||||||||
| (((room) & 0x3F) << 13) | \ | ||||||||||||
| (((setFlag19) & 1) << 19)) | ||||||||||||
| /* The true purpose of the flag is unknown. The state is never enabled on any waterbox, and functions that | ||||||||||||
| * pass on flag enabled are never called, so there is no direct usecase context. */ | ||||||||||||
| #define WATERBOX_IS_DISABLED (1 << 19) // Disables waterbox collision | ||||||||||||
|
Comment on lines
+99
to
+101
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. where does the name come from then?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So in functions However, my concern is that
So in short, I opted to choose a name that make sense within the scope of what we know now, but added a comment to highlight that the assumption could potentially be incorrect, because again, never used.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see. The comment game me the wrong impression that the flag was entirely unused outside of unused code Maybe:
Suggested change
+ formatting |
||||||||||||
|
|
||||||||||||
| typedef struct WaterBox { | ||||||||||||
| /* 0x00 */ s16 xMin; | ||||||||||||
| /* 0x02 */ s16 ySurface; | ||||||||||||
| /* 0x02 */ s16 ySurface; // Water is effectively infinitely deep. | ||||||||||||
| /* 0x04 */ s16 zMin; | ||||||||||||
| /* 0x06 */ s16 xLength; | ||||||||||||
| /* 0x08 */ s16 zLength; | ||||||||||||
|
|
@@ -458,11 +457,11 @@ s32 SurfaceType_IsFloorConveyor(CollisionContext* colCtx, CollisionPoly* poly, s | |||||||||||
| u32 SurfaceType_GetConveyorSpeed(CollisionContext* colCtx, CollisionPoly* poly, s32 bgId); | ||||||||||||
| u32 SurfaceType_GetConveyorDirection(CollisionContext* colCtx, CollisionPoly* poly, s32 bgId); | ||||||||||||
| u32 func_80042108(CollisionContext* colCtx, CollisionPoly* poly, s32 bgId); | ||||||||||||
| s32 WaterBox_GetSurface1(struct PlayState* play, CollisionContext* colCtx, f32 x, f32 z, f32* ySurface, | ||||||||||||
| WaterBox** outWaterBox); | ||||||||||||
| s32 WaterBox_GetSurface2(struct PlayState* play, CollisionContext* colCtx, Vec3f* pos, f32 surfaceChkDist, | ||||||||||||
| s32 BgCheck_GetWaterSurfaceAllHack(struct PlayState* play, CollisionContext* colCtx, f32 x, f32 z, f32* y, | ||||||||||||
| WaterBox** outWaterBox); | ||||||||||||
| s32 BgCheck_FindWaterBox(struct PlayState* play, CollisionContext* colCtx, Vec3f* pos, f32 surfaceChkDist, | ||||||||||||
| WaterBox** outWaterBox); | ||||||||||||
| s32 WaterBox_GetSurfaceImpl(struct PlayState* play, CollisionContext* colCtx, f32 x, f32 z, f32* ySurface, | ||||||||||||
| s32 BgCheck_GetWaterSurface(struct PlayState* play, CollisionContext* colCtx, f32 x, f32 z, f32* outWaterSurface, | ||||||||||||
| WaterBox** outWaterBox); | ||||||||||||
| u32 WaterBox_GetBgCamIndex(CollisionContext* colCtx, WaterBox* waterBox); | ||||||||||||
| u16 WaterBox_GetBgCamSetting(CollisionContext* colCtx, WaterBox* waterBox); | ||||||||||||
|
|
||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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 cannot overlap, as water has effectively infinite depth | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't understand the relation between not overlapping and having 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 cannot overlap, as water has effectively 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,28 +4310,31 @@ 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. | ||
| if (waterBox->xMin < x && x < waterBox->xMin + waterBox->xLength) { | ||
|
Comment on lines
+4319
to
+4320
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. did you forget to add details here?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep, I only added it in MM woops. |
||
| if (waterBox->zMin < z && z < waterBox->zMin + waterBox->zLength) { | ||
| *outWaterBox = waterBox; | ||
| *outWaterSurface = waterBox->ySurface; | ||
| return true; | ||
| } | ||
| } | ||
| } | ||
| return false; | ||
| } | ||
|
|
||
| /** | ||
| * 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 +4351,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 +4405,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 cannot 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 +4424,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; | ||
| } | ||
| } | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
did you mean "struct member" or just "member" instead of "variable" (I think it was fine as is in main)