diff --git a/include/functions.h b/include/functions.h index a1caecaece..9c1ce7b084 100644 --- a/include/functions.h +++ b/include/functions.h @@ -1050,8 +1050,8 @@ s32 Player_OverrideLimbDrawGameplayDefault(PlayState* play, s32 limbIndex, Gfx** void* thisx); s32 Player_OverrideLimbDrawGameplayFirstPerson(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, void* thisx); -s32 Player_OverrideLimbDrawGameplay_80090440(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, - void* thisx); +s32 Player_OverrideLimbDrawGameplayCrawling(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, + void* thisx); u8 func_80090480(PlayState* play, ColliderQuad* collider, WeaponInfo* weaponInfo, Vec3f* newTip, Vec3f* newBase); void Player_DrawGetItem(PlayState* play, Player* this); void Player_PostLimbDrawGameplay(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx); diff --git a/include/z64bgcheck.h b/include/z64bgcheck.h index 8b52364061..6d04483475 100644 --- a/include/z64bgcheck.h +++ b/include/z64bgcheck.h @@ -143,9 +143,10 @@ typedef enum { #define WALL_FLAG_1 (1 << 1) #define WALL_FLAG_2 (1 << 2) #define WALL_FLAG_3 (1 << 3) -#define WALL_FLAG_4 (1 << 4) -#define WALL_FLAG_5 (1 << 5) +#define WALL_FLAG_CRAWLSPACE_1 (1 << 4) +#define WALL_FLAG_CRAWLSPACE_2 (1 << 5) #define WALL_FLAG_6 (1 << 6) +#define WALL_FLAG_CRAWLSPACE (WALL_FLAG_CRAWLSPACE_1 | WALL_FLAG_CRAWLSPACE_2) typedef enum { /* 0 */ FLOOR_PROPERTY_0, diff --git a/include/z64camera.h b/include/z64camera.h index 9550ee11b0..d04a4869ba 100644 --- a/include/z64camera.h +++ b/include/z64camera.h @@ -888,16 +888,14 @@ typedef struct { } Subj4ReadOnlyData; // size = 0x4 typedef struct { - /* 0x00 */ InfiniteLine unk_00; - /* 0x18 */ f32 unk_18; - /* 0x1C */ f32 unk_1C; - /* 0x20 */ f32 unk_20; - /* 0x24 */ f32 unk_24; - /* 0x28 */ f32 unk_28; - /* 0x2C */ s16 unk_2C; - /* 0x2E */ s16 unk_2E; - /* 0x30 */ s16 unk_30; - /* 0x32 */ s16 unk_32; + /* 0x00 */ InfiniteLine crawlspaceLine; + /* 0x18 */ Vec3f unk_18; // unused + /* 0x24 */ f32 xzSpeed; + /* 0x28 */ f32 eyeLerp; + /* 0x2C */ s16 eyeLerpPhase; + /* 0x2E */ s16 isSfxOff; + /* 0x30 */ s16 forwardYaw; // yaw to the forwards crawling direction + /* 0x32 */ s16 zoomTimer; } Subj4ReadWriteData; // size = 0x34 typedef struct { diff --git a/include/z64player.h b/include/z64player.h index cbeb641f5d..f5cf0c03ec 100644 --- a/include/z64player.h +++ b/include/z64player.h @@ -432,9 +432,9 @@ typedef struct { #define PLAYER_STATE2_13 (1 << 13) #define PLAYER_STATE2_14 (1 << 14) #define PLAYER_STATE2_15 (1 << 15) -#define PLAYER_STATE2_16 (1 << 16) +#define PLAYER_STATE2_DO_ACTION_ENTER (1 << 16) // Turns on the "Enter On A" DoAction #define PLAYER_STATE2_17 (1 << 17) -#define PLAYER_STATE2_18 (1 << 18) +#define PLAYER_STATE2_CRAWLING (1 << 18) // Crawling through a crawlspace #define PLAYER_STATE2_19 (1 << 19) #define PLAYER_STATE2_20 (1 << 20) #define PLAYER_STATE2_21 (1 << 21) diff --git a/src/code/z_bgcheck.c b/src/code/z_bgcheck.c index 69c6cd7ae1..22cc9c782e 100644 --- a/src/code/z_bgcheck.c +++ b/src/code/z_bgcheck.c @@ -63,8 +63,8 @@ s32 D_80119D90[WALL_TYPE_MAX] = { WALL_FLAG_0 | WALL_FLAG_1, // WALL_TYPE_2 WALL_FLAG_0 | WALL_FLAG_2, // WALL_TYPE_3 WALL_FLAG_3, // WALL_TYPE_4 - WALL_FLAG_4, // WALL_TYPE_5 - WALL_FLAG_5, // WALL_TYPE_6 + WALL_FLAG_CRAWLSPACE_1, // WALL_TYPE_5 + WALL_FLAG_CRAWLSPACE_2, // WALL_TYPE_6 WALL_FLAG_6, // WALL_TYPE_7 }; diff --git a/src/code/z_camera.c b/src/code/z_camera.c index 035d25706e..a31cfd43a1 100644 --- a/src/code/z_camera.c +++ b/src/code/z_camera.c @@ -4372,21 +4372,25 @@ s32 Camera_Subj4(Camera* camera) { Vec3f* at = &camera->at; u16 crawlspaceNumPoints; Vec3s* crawlspacePoints; - Vec3f sp98; - Vec3f sp8C; - f32 sp88; - s16 pad2; - f32 temp_f16; - PosRot sp6C; - VecGeo sp64; - VecGeo sp5C; - s16 temp_a0; - f32 tx; + Vec3f temp1; + Vec3f zoomAtTarget; + f32 temp2; Player* player; - PosRot* playerPosRot = &camera->playerPosRot; + f32 eyeLerp; + PosRot playerPosRot; + VecGeo targetOffset; + VecGeo atEyeOffset; + s16 eyeToAtYaw; + s32 pad[2]; + f32 temp; Subj4ReadOnlyData* roData = &camera->paramData.subj4.roData; Subj4ReadWriteData* rwData = &camera->paramData.subj4.rwData; +#define vCrawlSpaceBackPos temp1 +#define vEyeTarget temp1 +#define vPlayerDistToFront temp2 +#define vZoomTimer temp2 + if (RELOAD_PARAMS(camera) || R_RELOAD_CAM_PARAMS) { CameraModeValue* values = sCameraSettings[camera->setting].cameraModes[camera->mode].values; @@ -4398,99 +4402,126 @@ s32 Camera_Subj4(Camera* camera) { } if (camera->play->view.unk_124 == 0) { - camera->play->view.unk_124 = (camera->camId | 0x50); - rwData->unk_24 = camera->xzSpeed; + camera->play->view.unk_124 = camera->camId | 0x50; + rwData->xzSpeed = camera->xzSpeed; return true; } - Actor_GetWorldPosShapeRot(&sp6C, &camera->player->actor); + Actor_GetWorldPosShapeRot(&playerPosRot, &camera->player->actor); + OLib_Vec3fDiffToVecGeo(&atEyeOffset, at, eye); - OLib_Vec3fDiffToVecGeo(&sp5C, at, eye); sCameraInterfaceFlags = roData->interfaceFlags; + + // Crawlspace setup (runs for only 1 frame) if (camera->animState == 0) { crawlspacePoints = (Vec3s*)Camera_GetBgCamFuncDataUnderPlayer(camera, &crawlspaceNumPoints); - Camera_Vec3sToVec3f(&rwData->unk_00.point, &crawlspacePoints[1]); - Camera_Vec3sToVec3f(&sp98, &crawlspacePoints[crawlspaceNumPoints - 2]); + // Second entry of crawlspacePoints contains the front position + Camera_Vec3sToVec3f(&rwData->crawlspaceLine.point, &crawlspacePoints[1]); + // Second last entry of crawlspacePoints contains the back position + Camera_Vec3sToVec3f(&vCrawlSpaceBackPos, &crawlspacePoints[crawlspaceNumPoints - 2]); - sp64.r = 10.0f; - // 0x238C ~ 50 degrees - sp64.pitch = 0x238C; - sp64.yaw = Camera_XZAngle(&sp98, &rwData->unk_00.point); - sp88 = OLib_Vec3fDist(&playerPosRot->pos, &rwData->unk_00.point); - if (OLib_Vec3fDist(&playerPosRot->pos, &sp98) < sp88) { - rwData->unk_00.dir.x = rwData->unk_00.point.x - sp98.x; - rwData->unk_00.dir.y = rwData->unk_00.point.y - sp98.y; - rwData->unk_00.dir.z = rwData->unk_00.point.z - sp98.z; - rwData->unk_00.point = sp98; + targetOffset.r = 10.0f; + targetOffset.pitch = 0x238C; // ~50 degrees + targetOffset.yaw = Camera_XZAngle(&vCrawlSpaceBackPos, &rwData->crawlspaceLine.point); + + vPlayerDistToFront = OLib_Vec3fDist(&camera->playerPosRot.pos, &rwData->crawlspaceLine.point); + if (OLib_Vec3fDist(&camera->playerPosRot.pos, &vCrawlSpaceBackPos) < vPlayerDistToFront) { + // Player is entering the crawlspace from the back + rwData->crawlspaceLine.dir.x = rwData->crawlspaceLine.point.x - vCrawlSpaceBackPos.x; + rwData->crawlspaceLine.dir.y = rwData->crawlspaceLine.point.y - vCrawlSpaceBackPos.y; + rwData->crawlspaceLine.dir.z = rwData->crawlspaceLine.point.z - vCrawlSpaceBackPos.z; + rwData->crawlspaceLine.point = vCrawlSpaceBackPos; } else { - rwData->unk_00.dir.x = sp98.x - rwData->unk_00.point.x; - rwData->unk_00.dir.y = sp98.y - rwData->unk_00.point.y; - rwData->unk_00.dir.z = sp98.z - rwData->unk_00.point.z; - sp64.yaw = sp64.yaw - 0x7FFF; + // Player is entering the crawlspace from the front + rwData->crawlspaceLine.dir.x = vCrawlSpaceBackPos.x - rwData->crawlspaceLine.point.x; + rwData->crawlspaceLine.dir.y = vCrawlSpaceBackPos.y - rwData->crawlspaceLine.point.y; + rwData->crawlspaceLine.dir.z = vCrawlSpaceBackPos.z - rwData->crawlspaceLine.point.z; + targetOffset.yaw -= 0x7FFF; } - rwData->unk_30 = sp64.yaw; - rwData->unk_32 = 0xA; - rwData->unk_2C = 0; - rwData->unk_2E = false; - rwData->unk_28 = 0.0f; + + rwData->forwardYaw = targetOffset.yaw; + rwData->zoomTimer = 10; + rwData->eyeLerpPhase = 0; + rwData->isSfxOff = false; + rwData->eyeLerp = 0.0f; camera->animState++; } - if (rwData->unk_32 != 0) { - sp64.r = 10.0f; - sp64.pitch = 0x238C; - sp64.yaw = rwData->unk_30; - Camera_AddVecGeoToVec3f(&sp8C, &sp6C.pos, &sp64); - sp88 = (rwData->unk_32 + 1.0f); - at->x += (sp8C.x - at->x) / sp88; - at->y += (sp8C.y - at->y) / sp88; - at->z += (sp8C.z - at->z) / sp88; - sp5C.r -= (sp5C.r / sp88); - sp5C.yaw = BINANG_LERPIMPINV(sp5C.yaw, (s16)(sp6C.rot.y - 0x7FFF), rwData->unk_32); - sp5C.pitch = BINANG_LERPIMPINV(sp5C.pitch, sp6C.rot.x, rwData->unk_32); - Camera_AddVecGeoToVec3f(eyeNext, at, &sp5C); + // Camera zooms in from third person to first person over 10 frames + if (rwData->zoomTimer != 0) { + targetOffset.r = 10.0f; + targetOffset.pitch = 0x238C; // ~50 degrees + targetOffset.yaw = rwData->forwardYaw; + Camera_AddVecGeoToVec3f(&zoomAtTarget, &playerPosRot.pos, &targetOffset); + + vZoomTimer = rwData->zoomTimer + 1.0f; + at->x = F32_LERPIMPINV(at->x, zoomAtTarget.x, vZoomTimer); + at->y = F32_LERPIMPINV(at->y, zoomAtTarget.y, vZoomTimer); + at->z = F32_LERPIMPINV(at->z, zoomAtTarget.z, vZoomTimer); + + atEyeOffset.r -= (atEyeOffset.r / vZoomTimer); + atEyeOffset.yaw = BINANG_LERPIMPINV(atEyeOffset.yaw, (s16)(playerPosRot.rot.y - 0x7FFF), rwData->zoomTimer); + atEyeOffset.pitch = BINANG_LERPIMPINV(atEyeOffset.pitch, playerPosRot.rot.x, rwData->zoomTimer); + Camera_AddVecGeoToVec3f(eyeNext, at, &atEyeOffset); *eye = *eyeNext; - rwData->unk_32--; - return false; - } else if (rwData->unk_24 < 0.5f) { + rwData->zoomTimer--; return false; } - Actor_GetWorldPosShapeRot(&sp6C, &camera->player->actor); - Math3D_LineClosestToPoint(&rwData->unk_00, &sp6C.pos, eyeNext); - at->x = eyeNext->x + rwData->unk_00.dir.x; - at->y = eyeNext->y + rwData->unk_00.dir.y; - at->z = eyeNext->z + rwData->unk_00.dir.z; + if (rwData->xzSpeed < 0.5f) { + return false; + } + + Actor_GetWorldPosShapeRot(&playerPosRot, &camera->player->actor); + Math3D_LineClosestToPoint(&rwData->crawlspaceLine, &playerPosRot.pos, eyeNext); + + // *at is unused before getting overwritten later this function + at->x = eyeNext->x + rwData->crawlspaceLine.dir.x; + at->y = eyeNext->y + rwData->crawlspaceLine.dir.y; + at->z = eyeNext->z + rwData->crawlspaceLine.dir.z; + *eye = *eyeNext; - sp64.yaw = rwData->unk_30; - sp64.r = 5.0f; - sp64.pitch = 0x238C; - Camera_AddVecGeoToVec3f(&sp98, eyeNext, &sp64); - rwData->unk_2C += 0xBB8; - temp_f16 = Math_CosS(rwData->unk_2C); - eye->x += (sp98.x - eye->x) * fabsf(temp_f16); - eye->y += (sp98.y - eye->y) * fabsf(temp_f16); - eye->z += (sp98.z - eye->z) * fabsf(temp_f16); - if ((rwData->unk_28 < temp_f16) && !rwData->unk_2E) { + targetOffset.yaw = rwData->forwardYaw; + targetOffset.r = 5.0f; + targetOffset.pitch = 0x238C; // ~50 degrees + + Camera_AddVecGeoToVec3f(&vEyeTarget, eyeNext, &targetOffset); + + rwData->eyeLerpPhase += 0xBB8; + eyeLerp = Math_CosS(rwData->eyeLerpPhase); + + // VEC3F_LERPIMPDST(eye, eye, &vEyeTarget, fabsf(eyeLerp)) + eye->x += (vEyeTarget.x - eye->x) * fabsf(eyeLerp); + eye->y += (vEyeTarget.y - eye->y) * fabsf(eyeLerp); + eye->z += (vEyeTarget.z - eye->z) * fabsf(eyeLerp); + + // When camera reaches the peak of offset and starts to move down + // && alternating cycles (sfx plays only every 2nd cycle) + if ((eyeLerp > rwData->eyeLerp) && !rwData->isSfxOff) { player = camera->player; - rwData->unk_2E = true; - func_800F4010(&player->actor.projectedPos, player->unk_89E + 0x8B0, 4.0f); - } else if (rwData->unk_28 > temp_f16) { - rwData->unk_2E = false; + rwData->isSfxOff = true; + func_800F4010(&player->actor.projectedPos, NA_SE_PL_CRAWL + player->unk_89E, 4.0f); + } else if (eyeLerp < rwData->eyeLerp) { + rwData->isSfxOff = false; } - rwData->unk_28 = temp_f16; + rwData->eyeLerp = eyeLerp; + camera->player->actor.world.pos = *eyeNext; camera->player->actor.world.pos.y = camera->playerGroundY; - camera->player->actor.shape.rot.y = sp64.yaw; - temp_f16 = ((240.0f * temp_f16) * (rwData->unk_24 * 0.416667f)); - temp_a0 = temp_f16 + rwData->unk_30; - at->x = eye->x + (Math_SinS(temp_a0) * 10.0f); + camera->player->actor.shape.rot.y = targetOffset.yaw; + + eyeLerp = (240.0f * eyeLerp) * (rwData->xzSpeed * 0.416667f); + eyeToAtYaw = rwData->forwardYaw + eyeLerp; + + at->x = eye->x + (Math_SinS(eyeToAtYaw) * 10.0f); at->y = eye->y; - at->z = eye->z + (Math_CosS(temp_a0) * 10.0f); + at->z = eye->z + (Math_CosS(eyeToAtYaw) * 10.0f); + camera->roll = Camera_LERPCeilS(0, camera->roll, 0.5f, 0xA); - return 1; + + return true; } s32 Camera_Subj0(Camera* camera) { diff --git a/src/code/z_onepointdemo.c b/src/code/z_onepointdemo.c index dc3a67531f..76d353418a 100644 --- a/src/code/z_onepointdemo.c +++ b/src/code/z_onepointdemo.c @@ -331,14 +331,18 @@ s32 OnePointCutscene_SetInfo(PlayState* play, s16 subCamId, s16 csId, Actor* act Play_SetCameraRoll(play, subCamId, childCam->roll); break; case 9601: + // Leaving a crawlspace forwards Play_CameraChangeSetting(play, subCamId, CAM_SET_CS_3); Play_CameraChangeSetting(play, CAM_ID_MAIN, mainCam->prevSetting); - OnePointCutscene_SetCsCamPoints(subCam, D_80120430 | 0x1000, D_8012042C, D_80120308, D_80120398); + OnePointCutscene_SetCsCamPoints(subCam, sCrawlspaceActionParam | 0x1000, sCrawlspaceTimer, + sCrawlspaceAtPoints, sCrawlspaceForwardsEyePoints); break; case 9602: + // Leaving a crawlspace backwards Play_CameraChangeSetting(play, subCamId, CAM_SET_CS_3); Play_CameraChangeSetting(play, CAM_ID_MAIN, mainCam->prevSetting); - OnePointCutscene_SetCsCamPoints(subCam, D_80120430 | 0x1000, D_8012042C, D_80120308, D_80120434); + OnePointCutscene_SetCsCamPoints(subCam, sCrawlspaceActionParam | 0x1000, sCrawlspaceTimer, + sCrawlspaceAtPoints, sCrawlspaceBackwardsEyePoints); break; case 4175: csInfo->keyFrames = D_8012147C; diff --git a/src/code/z_onepointdemo_data.inc.c b/src/code/z_onepointdemo_data.inc.c index 1d1838b058..c3dc204942 100644 --- a/src/code/z_onepointdemo_data.inc.c +++ b/src/code/z_onepointdemo_data.inc.c @@ -29,24 +29,24 @@ static s16 D_801202FC = 13; static s16 D_80120300 = 210; static s16 D_80120304 = 0; -static CutsceneCameraPoint D_80120308[9] = { +static CutsceneCameraPoint sCrawlspaceAtPoints[9] = { { CS_CMD_CONTINUE, 0, 10, 40.0f, { 0, 4, 0 } }, { CS_CMD_CONTINUE, 0, 10, 40.000004f, { 0, 4, 0 } }, { CS_CMD_CONTINUE, 0, 10, 50.0f, { 0, 9, 0 } }, { CS_CMD_CONTINUE, 0, 12, 55.0f, { 0, 12, 0 } }, { CS_CMD_CONTINUE, 0, 15, 61.0f, { 0, 18, 0 } }, { CS_CMD_CONTINUE, 0, 20, 65.0f, { 0, 29, 0 } }, { CS_CMD_CONTINUE, 0, 40, 60.0f, { 0, 34, 0 } }, { CS_CMD_STOP, 0, 40, 60.0f, { 0, 34, 0 } }, { CS_CMD_STOP, 0, 10, 60.0f, { 0, 34, 0 } }, }; -static CutsceneCameraPoint D_80120398[9] = { +static CutsceneCameraPoint sCrawlspaceForwardsEyePoints[9] = { { CS_CMD_CONTINUE, 0, 0, 60.0f, { 0, 9, 45 } }, { CS_CMD_CONTINUE, 0, 0, 60.0f, { 0, 8, 50 } }, { CS_CMD_CONTINUE, 0, 0, 60.0f, { 0, 17, 58 } }, { CS_CMD_CONTINUE, 0, 0, 60.0f, { 0, 21, 78 } }, { CS_CMD_CONTINUE, 0, 0, 60.0f, { 0, 46, 109 } }, { CS_CMD_CONTINUE, 0, 0, 60.0f, { 0, 58, 118 } }, { CS_CMD_CONTINUE, 0, 0, 60.0f, { 0, 63, 119 } }, { CS_CMD_STOP, 0, 0, 60.0f, { 0, 62, 119 } }, { CS_CMD_STOP, 0, 0, 60.0f, { 0, 62, 119 } }, }; -static s16 D_80120428 = 9; -static s16 D_8012042C = 90; -static s16 D_80120430 = 1; -static CutsceneCameraPoint D_80120434[10] = { +static s16 sCrawlspaceUnused = 9; +static s16 sCrawlspaceTimer = 90; +static s16 sCrawlspaceActionParam = 1; +static CutsceneCameraPoint sCrawlspaceBackwardsEyePoints[10] = { { CS_CMD_CONTINUE, 0, 0, 60.0f, { 0, 9, -45 } }, { CS_CMD_CONTINUE, 0, 0, 60.0f, { 0, 9, -45 } }, { CS_CMD_CONTINUE, 0, 0, 60.0f, { 0, 8, -50 } }, { CS_CMD_CONTINUE, 0, 0, 60.0f, { 0, 17, -58 } }, { CS_CMD_CONTINUE, 0, 0, 60.0f, { 0, 21, -78 } }, { CS_CMD_CONTINUE, 0, 0, 60.0f, { 0, 46, -109 } }, diff --git a/src/code/z_parameter.c b/src/code/z_parameter.c index 416ff89cdb..a120332d50 100644 --- a/src/code/z_parameter.c +++ b/src/code/z_parameter.c @@ -759,7 +759,7 @@ void func_80083108(PlayState* play) { } Interface_ChangeAlpha(50); - } else if ((player->stateFlags1 & PLAYER_STATE1_21) || (player->stateFlags2 & PLAYER_STATE2_18)) { + } else if ((player->stateFlags1 & PLAYER_STATE1_21) || (player->stateFlags2 & PLAYER_STATE2_CRAWLING)) { if (gSaveContext.buttonStatus[0] != BTN_DISABLED) { gSaveContext.buttonStatus[0] = BTN_DISABLED; gSaveContext.buttonStatus[1] = BTN_DISABLED; @@ -2803,7 +2803,7 @@ void Interface_DrawItemButtons(PlayState* play) { if ((gSaveContext.unk_13EA == 1) || (gSaveContext.unk_13EA == 2) || (gSaveContext.unk_13EA == 5)) { temp = 0; } else if ((player->stateFlags1 & PLAYER_STATE1_21) || (func_8008F2F8(play) == 4) || - (player->stateFlags2 & PLAYER_STATE2_18)) { + (player->stateFlags2 & PLAYER_STATE2_CRAWLING)) { temp = 70; } else { temp = interfaceCtx->healthAlpha; diff --git a/src/code/z_player_lib.c b/src/code/z_player_lib.c index be8e2a40dd..8a3ab95637 100644 --- a/src/code/z_player_lib.c +++ b/src/code/z_player_lib.c @@ -899,7 +899,7 @@ void Player_DrawImpl(PlayState* play, void** skeleton, Vec3s* jointTable, s32 dL SkelAnime_DrawFlexLod(play, skeleton, jointTable, dListCount, overrideLimbDraw, postLimbDraw, data, lod); if ((overrideLimbDraw != Player_OverrideLimbDrawGameplayFirstPerson) && - (overrideLimbDraw != Player_OverrideLimbDrawGameplay_80090440) && + (overrideLimbDraw != Player_OverrideLimbDrawGameplayCrawling) && (gSaveContext.gameMode != GAMEMODE_END_CREDITS)) { if (LINK_IS_ADULT) { s32 strengthUpgrade = CUR_UPG_VALUE(UPG_STRENGTH); @@ -1198,8 +1198,8 @@ s32 Player_OverrideLimbDrawGameplayFirstPerson(PlayState* play, s32 limbIndex, G return false; } -s32 Player_OverrideLimbDrawGameplay_80090440(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, - void* thisx) { +s32 Player_OverrideLimbDrawGameplayCrawling(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, + void* thisx) { if (!Player_OverrideLimbDrawGameplayCommon(play, limbIndex, dList, pos, rot, thisx)) { *dList = NULL; } diff --git a/src/overlays/actors/ovl_En_Bom_Chu/z_en_bom_chu.c b/src/overlays/actors/ovl_En_Bom_Chu/z_en_bom_chu.c index e4e5bf0d45..4d5556077d 100644 --- a/src/overlays/actors/ovl_En_Bom_Chu/z_en_bom_chu.c +++ b/src/overlays/actors/ovl_En_Bom_Chu/z_en_bom_chu.c @@ -275,8 +275,7 @@ void EnBomChu_Move(EnBomChu* this, PlayState* play) { if (BgCheck_EntityLineTest1(&play->colCtx, &posA, &posB, &posUpDown, &polyUpDown, true, true, true, true, &bgIdUpDown) && - !(SurfaceType_GetWallFlags(&play->colCtx, polyUpDown, bgIdUpDown) & - (WALL_FLAG_4 | WALL_FLAG_5)) && // && not crawl space? + !(SurfaceType_GetWallFlags(&play->colCtx, polyUpDown, bgIdUpDown) & WALL_FLAG_CRAWLSPACE) && !SurfaceType_IsIgnoredByProjectiles(&play->colCtx, polyUpDown, bgIdUpDown)) { // forwards posB.x = (this->axisForwards.x * lineLength) + posA.x; @@ -285,7 +284,7 @@ void EnBomChu_Move(EnBomChu* this, PlayState* play) { if (BgCheck_EntityLineTest1(&play->colCtx, &posA, &posB, &posSide, &polySide, true, true, true, true, &bgIdSide) && - !(SurfaceType_GetWallFlags(&play->colCtx, polySide, bgIdSide) & (WALL_FLAG_4 | WALL_FLAG_5)) && + !(SurfaceType_GetWallFlags(&play->colCtx, polySide, bgIdSide) & WALL_FLAG_CRAWLSPACE) && !SurfaceType_IsIgnoredByProjectiles(&play->colCtx, polySide, bgIdSide)) { EnBomChu_UpdateFloorPoly(this, polySide, play); this->actor.world.pos = posSide; @@ -324,7 +323,7 @@ void EnBomChu_Move(EnBomChu* this, PlayState* play) { if (BgCheck_EntityLineTest1(&play->colCtx, &posA, &posB, &posSide, &polySide, true, true, true, true, &bgIdSide) && - !(SurfaceType_GetWallFlags(&play->colCtx, polySide, bgIdSide) & (WALL_FLAG_4 | WALL_FLAG_5)) && + !(SurfaceType_GetWallFlags(&play->colCtx, polySide, bgIdSide) & WALL_FLAG_CRAWLSPACE) && !SurfaceType_IsIgnoredByProjectiles(&play->colCtx, polySide, bgIdSide)) { EnBomChu_UpdateFloorPoly(this, polySide, play); this->actor.world.pos = posSide; diff --git a/src/overlays/actors/ovl_En_Sw/z_en_sw.c b/src/overlays/actors/ovl_En_Sw/z_en_sw.c index c95f4f4d62..782cb8993c 100644 --- a/src/overlays/actors/ovl_En_Sw/z_en_sw.c +++ b/src/overlays/actors/ovl_En_Sw/z_en_sw.c @@ -122,7 +122,7 @@ CollisionPoly* func_80B0C020(PlayState* play, Vec3f* arg1, Vec3f* arg2, Vec3f* a return NULL; } - if (SurfaceType_GetWallFlags(&play->colCtx, sp3C, *arg4) & (WALL_FLAG_4 | WALL_FLAG_5)) { + if (SurfaceType_GetWallFlags(&play->colCtx, sp3C, *arg4) & WALL_FLAG_CRAWLSPACE) { return NULL; } diff --git a/src/overlays/actors/ovl_player_actor/z_player.c b/src/overlays/actors/ovl_player_actor/z_player.c index 9ccf5999c7..474ee4eccb 100644 --- a/src/overlays/actors/ovl_player_actor/z_player.c +++ b/src/overlays/actors/ovl_player_actor/z_player.c @@ -473,7 +473,7 @@ static s32 D_808535E0 = 0; static s32 D_808535E4 = FLOOR_TYPE_0; static f32 D_808535E8 = 1.0f; static f32 D_808535EC = 1.0f; -static u32 D_808535F0 = 0; +static u32 sInteractWallFlags = 0; static u32 sConveyorSpeedIndex = CONVEYOR_SPEED_DISABLED; static s16 sIsFloorConveyor = false; static s16 sConveyorYaw = 0; @@ -1667,7 +1667,7 @@ void func_80832440(PlayState* play, Player* this) { func_8005B1A4(Play_GetCamera(play, CAM_ID_MAIN)); this->stateFlags1 &= ~(PLAYER_STATE1_13 | PLAYER_STATE1_14 | PLAYER_STATE1_20 | PLAYER_STATE1_21); - this->stateFlags2 &= ~(PLAYER_STATE2_4 | PLAYER_STATE2_7 | PLAYER_STATE2_18); + this->stateFlags2 &= ~(PLAYER_STATE2_4 | PLAYER_STATE2_7 | PLAYER_STATE2_CRAWLING); this->actor.shape.rot.x = 0; this->actor.shape.yOffset = 0.0f; @@ -4242,7 +4242,7 @@ s32 func_80838A14(Player* this, PlayState* play) { return 0; } - if ((this->actor.wallBgId != BGCHECK_SCENE) && (D_808535F0 & WALL_FLAG_6)) { + if ((this->actor.wallBgId != BGCHECK_SCENE) && (sInteractWallFlags & WALL_FLAG_6)) { if (this->unk_88D >= 6) { this->stateFlags2 |= PLAYER_STATE2_2; if (CHECK_BTN_ALL(sControlInput->press.button, BTN_A)) { @@ -4456,7 +4456,7 @@ s32 func_80839034(PlayState* play, Player* this, CollisionPoly* poly, u32 bgId) } if (!(this->stateFlags1 & (PLAYER_STATE1_23 | PLAYER_STATE1_29)) && - !(this->stateFlags2 & PLAYER_STATE2_18) && !func_808332B8(this) && + !(this->stateFlags2 & PLAYER_STATE2_CRAWLING) && !func_808332B8(this) && (temp = SurfaceType_GetFloorType(&play->colCtx, poly, bgId), (temp != FLOOR_TYPE_10)) && ((sp34 < 100) || (this->actor.bgCheckFlags & BGCHECKFLAG_GROUND))) { @@ -6547,13 +6547,13 @@ s32 func_8083EB44(Player* this, PlayState* play) { return 0; } -s32 func_8083EC18(Player* this, PlayState* play, u32 arg2) { +s32 func_8083EC18(Player* this, PlayState* play, u32 interactWallFlags) { if (this->wallHeight >= 79.0f) { if (!(this->stateFlags1 & PLAYER_STATE1_27) || (this->currentBoots == PLAYER_BOOTS_IRON) || (this->actor.yDistToWater < this->ageProperties->unk_2C)) { - s32 sp8C = (arg2 & WALL_FLAG_3) ? 2 : 0; + s32 sp8C = (interactWallFlags & WALL_FLAG_3) ? 2 : 0; - if ((sp8C != 0) || (arg2 & WALL_FLAG_1) || + if ((sp8C != 0) || (interactWallFlags & WALL_FLAG_1) || SurfaceType_CheckWallFlag2(&play->colCtx, this->actor.wallPoly, this->actor.wallBgId)) { f32 phi_f20; CollisionPoly* wallPoly = this->actor.wallPoly; @@ -6619,7 +6619,7 @@ s32 func_8083EC18(Player* this, PlayState* play, u32 arg2) { this->stateFlags1 |= PLAYER_STATE1_21; this->stateFlags1 &= ~PLAYER_STATE1_27; - if ((sp8C != 0) || (arg2 & WALL_FLAG_1)) { + if ((sp8C != 0) || (interactWallFlags & WALL_FLAG_1)) { if ((this->unk_84F = sp8C) != 0) { if (this->actor.bgCheckFlags & BGCHECKFLAG_GROUND) { sp30 = &gPlayerAnim_link_normal_Fclimb_startA; @@ -6647,13 +6647,13 @@ s32 func_8083EC18(Player* this, PlayState* play, u32 arg2) { func_80832264(play, this, sp30); func_80832F54(play, this, 0x9F); - return 1; + return true; } } } } - return 0; + return false; } void func_8083F070(Player* this, LinkAnimationHeader* anim, PlayState* play) { @@ -6661,70 +6661,82 @@ void func_8083F070(Player* this, LinkAnimationHeader* anim, PlayState* play) { LinkAnimation_PlayOnceSetSpeed(play, &this->skelAnime, anim, (4.0f / 3.0f)); } -s32 func_8083F0C8(Player* this, PlayState* play, u32 arg2) { +/** + * @return true if Player chooses to enter crawlspace + */ +s32 Player_TryEnteringCrawlspace(Player* this, PlayState* play, u32 interactWallFlags) { CollisionPoly* wallPoly; - Vec3f sp50[3]; - f32 sp4C; - f32 phi_f2; - f32 sp44; - f32 phi_f12; + Vec3f wallVertices[3]; + f32 xVertex1; + f32 xVertex2; + f32 zVertex1; + f32 zVertex2; s32 i; - if (!LINK_IS_ADULT && !(this->stateFlags1 & PLAYER_STATE1_27) && (arg2 & (WALL_FLAG_4 | WALL_FLAG_5))) { + if (!LINK_IS_ADULT && !(this->stateFlags1 & PLAYER_STATE1_27) && (interactWallFlags & WALL_FLAG_CRAWLSPACE)) { wallPoly = this->actor.wallPoly; - CollisionPoly_GetVerticesByBgId(wallPoly, this->actor.wallBgId, &play->colCtx, sp50); + CollisionPoly_GetVerticesByBgId(wallPoly, this->actor.wallBgId, &play->colCtx, wallVertices); - sp4C = phi_f2 = sp50[0].x; - sp44 = phi_f12 = sp50[0].z; + // Determines min and max vertices for x & z (edges of the crawlspace hole) + xVertex1 = xVertex2 = wallVertices[0].x; + zVertex1 = zVertex2 = wallVertices[0].z; for (i = 1; i < 3; i++) { - if (sp4C > sp50[i].x) { - sp4C = sp50[i].x; - } else if (phi_f2 < sp50[i].x) { - phi_f2 = sp50[i].x; + if (xVertex1 > wallVertices[i].x) { + // Update x min + xVertex1 = wallVertices[i].x; + } else if (xVertex2 < wallVertices[i].x) { + // Update x max + xVertex2 = wallVertices[i].x; } - - if (sp44 > sp50[i].z) { - sp44 = sp50[i].z; - } else if (phi_f12 < sp50[i].z) { - phi_f12 = sp50[i].z; + if (zVertex1 > wallVertices[i].z) { + // Update z min + zVertex1 = wallVertices[i].z; + } else if (zVertex2 < wallVertices[i].z) { + // Update z max + zVertex2 = wallVertices[i].z; } } - sp4C = (sp4C + phi_f2) * 0.5f; - sp44 = (sp44 + phi_f12) * 0.5f; + // XZ Center of the crawlspace hole + xVertex1 = (xVertex1 + xVertex2) * 0.5f; + zVertex1 = (zVertex1 + zVertex2) * 0.5f; - phi_f2 = ((this->actor.world.pos.x - sp4C) * COLPOLY_GET_NORMAL(wallPoly->normal.z)) - - ((this->actor.world.pos.z - sp44) * COLPOLY_GET_NORMAL(wallPoly->normal.x)); + // Perpendicular (sideways) XZ-Distance from player pos to crawlspace line + // Uses y-component of crossproduct formula for the distance from a point to a line + xVertex2 = ((this->actor.world.pos.x - xVertex1) * COLPOLY_GET_NORMAL(wallPoly->normal.z)) - + ((this->actor.world.pos.z - zVertex1) * COLPOLY_GET_NORMAL(wallPoly->normal.x)); - if (fabsf(phi_f2) < 8.0f) { - this->stateFlags2 |= PLAYER_STATE2_16; + if (fabsf(xVertex2) < 8.0f) { + // Give do-action prompt to "Enter on A" for the crawlspace + this->stateFlags2 |= PLAYER_STATE2_DO_ACTION_ENTER; if (CHECK_BTN_ALL(sControlInput->press.button, BTN_A)) { + // Enter Crawlspace f32 wallPolyNormalX = COLPOLY_GET_NORMAL(wallPoly->normal.x); f32 wallPolyNormalZ = COLPOLY_GET_NORMAL(wallPoly->normal.z); - f32 sp30 = this->wallDistance; + f32 wallDistance = this->wallDistance; func_80836898(play, this, func_8083A40C); - this->stateFlags2 |= PLAYER_STATE2_18; + this->stateFlags2 |= PLAYER_STATE2_CRAWLING; this->actor.shape.rot.y = this->currentYaw = this->actor.wallYaw + 0x8000; - this->actor.world.pos.x = sp4C + (sp30 * wallPolyNormalX); - this->actor.world.pos.z = sp44 + (sp30 * wallPolyNormalZ); + this->actor.world.pos.x = xVertex1 + (wallDistance * wallPolyNormalX); + this->actor.world.pos.z = zVertex1 + (wallDistance * wallPolyNormalZ); func_80832224(this); this->actor.prevPos = this->actor.world.pos; func_80832264(play, this, &gPlayerAnim_link_child_tunnel_start); func_80832F54(play, this, 0x9D); - return 1; + return true; } } } - return 0; + return false; } s32 func_8083F360(PlayState* play, Player* this, f32 arg1, f32 arg2, f32 arg3, f32 arg4) { CollisionPoly* wallPoly; - s32 sp78; + s32 wallBgId; Vec3f sp6C; Vec3f sp60; Vec3f sp54; @@ -6744,13 +6756,13 @@ s32 func_8083F360(PlayState* play, Player* this, f32 arg1, f32 arg2, f32 arg3, f sp60.y = sp6C.y = this->actor.world.pos.y + arg1; if (BgCheck_EntityLineTest1(&play->colCtx, &sp6C, &sp60, &sp54, &this->actor.wallPoly, true, false, false, true, - &sp78)) { + &wallBgId)) { wallPoly = this->actor.wallPoly; this->actor.bgCheckFlags |= BGCHECKFLAG_PLAYER_WALL_INTERACT; - this->actor.wallBgId = sp78; + this->actor.wallBgId = wallBgId; - D_808535F0 = SurfaceType_GetWallFlags(&play->colCtx, wallPoly, sp78); + sInteractWallFlags = SurfaceType_GetWallFlags(&play->colCtx, wallPoly, wallBgId); wallPolyNormalX = COLPOLY_GET_NORMAL(wallPoly->normal.x); wallPolyNormalZ = COLPOLY_GET_NORMAL(wallPoly->normal.z); @@ -6773,26 +6785,37 @@ s32 func_8083F524(PlayState* play, Player* this) { return func_8083F360(play, this, 26.0f, this->ageProperties->unk_38 + 5.0f, 30.0f, 0.0f); } -s32 func_8083F570(Player* this, PlayState* play) { - s16 temp; +/** + * Two exit walls are placed at each end of the crawlspace, separate to the two entrance walls used to enter the + * crawlspace. These front and back exit walls are futher into the crawlspace than the front and + * back entrance walls. When player interacts with either of these two interior exit walls, start the leaving-crawlspace + * cutscene and return true. Else, return false + */ +s32 Player_TryLeavingCrawlspace(Player* this, PlayState* play) { + s16 yawToWall; if ((this->linearVelocity != 0.0f) && (this->actor.bgCheckFlags & BGCHECKFLAG_WALL) && - (D_808535F0 & (WALL_FLAG_4 | WALL_FLAG_5))) { + (sInteractWallFlags & WALL_FLAG_CRAWLSPACE)) { - temp = this->actor.shape.rot.y - this->actor.wallYaw; + // The exit wallYaws will always point inward on the crawlline + // Interacting with the exit wall in front will have a yaw diff of 0x8000 + // Interacting with the exit wall behind will have a yaw diff of 0 + yawToWall = this->actor.shape.rot.y - this->actor.wallYaw; if (this->linearVelocity < 0.0f) { - temp += 0x8000; + yawToWall += 0x8000; } - if (ABS(temp) > 0x4000) { + if (ABS(yawToWall) > 0x4000) { func_80835C58(play, this, func_8084C81C, 0); if (this->linearVelocity > 0.0f) { + // Leaving a crawlspace forwards this->actor.shape.rot.y = this->actor.wallYaw + 0x8000; func_80832264(play, this, &gPlayerAnim_link_child_tunnel_end); func_80832F54(play, this, 0x9D); OnePointCutscene_Init(play, 9601, 999, NULL, CAM_ID_MAIN); } else { + // Leaving a crawlspace backwards this->actor.shape.rot.y = this->actor.wallYaw; LinkAnimation_Change(play, &this->skelAnime, &gPlayerAnim_link_child_tunnel_start, -1.0f, Animation_GetLastFrame(&gPlayerAnim_link_child_tunnel_start), 0.0f, ANIMMODE_ONCE, @@ -6804,11 +6827,11 @@ s32 func_8083F570(Player* this, PlayState* play) { this->currentYaw = this->actor.shape.rot.y; func_80832210(this); - return 1; + return true; } } - return 0; + return false; } void func_8083F72C(Player* this, LinkAnimationHeader* anim, PlayState* play) { @@ -6828,13 +6851,13 @@ s32 func_8083F7BC(Player* this, PlayState* play) { if (!(this->stateFlags1 & PLAYER_STATE1_11) && (this->actor.bgCheckFlags & BGCHECKFLAG_PLAYER_WALL_INTERACT) && (D_80853608 < 0x3000)) { - if (((this->linearVelocity > 0.0f) && func_8083EC18(this, play, D_808535F0)) || - func_8083F0C8(this, play, D_808535F0)) { + if (((this->linearVelocity > 0.0f) && func_8083EC18(this, play, sInteractWallFlags)) || + Player_TryEnteringCrawlspace(this, play, sInteractWallFlags)) { return 1; } if (!func_808332B8(this) && ((this->linearVelocity == 0.0f) || !(this->stateFlags2 & PLAYER_STATE2_2)) && - (D_808535F0 & WALL_FLAG_6) && (this->actor.bgCheckFlags & BGCHECKFLAG_GROUND) && + (sInteractWallFlags & WALL_FLAG_6) && (this->actor.bgCheckFlags & BGCHECKFLAG_GROUND) && (this->wallHeight >= 39.0f)) { this->stateFlags2 |= PLAYER_STATE2_0; @@ -6919,14 +6942,14 @@ void func_8083FB7C(Player* this, PlayState* play) { s32 func_8083FBC0(Player* this, PlayState* play) { if (!CHECK_BTN_ALL(sControlInput->press.button, BTN_A) && (this->actor.bgCheckFlags & BGCHECKFLAG_PLAYER_WALL_INTERACT) && - ((D_808535F0 & WALL_FLAG_3) || (D_808535F0 & WALL_FLAG_1) || + ((sInteractWallFlags & WALL_FLAG_3) || (sInteractWallFlags & WALL_FLAG_1) || SurfaceType_CheckWallFlag2(&play->colCtx, this->actor.wallPoly, this->actor.wallBgId))) { - return 0; + return false; } func_8083FB7C(this, play); func_80832698(this, NA_SE_VO_LI_AUTO_JUMP); - return 1; + return true; } s32 func_8083FC68(Player* this, f32 arg1, s16 arg2) { @@ -8568,7 +8591,7 @@ void func_8084411C(Player* this, PlayState* play) { !(this->stateFlags2 & PLAYER_STATE2_19) && !(this->stateFlags1 & (PLAYER_STATE1_11 | PLAYER_STATE1_27)) && (this->linearVelocity > 0.0f)) { if ((this->wallHeight >= 150.0f) && (this->unk_84B[this->unk_846] == 0)) { - func_8083EC18(this, play, D_808535F0); + func_8083EC18(this, play, sInteractWallFlags); } else if ((this->unk_88C >= 2) && (this->wallHeight < 150.0f) && (((this->actor.world.pos.y - this->actor.floorHeight) + this->wallHeight) > (70.0f * this->ageProperties->unk_08))) { @@ -9790,7 +9813,7 @@ void func_808473D4(PlayState* play, Player* this) { if (this->unk_860 == 2) { doAction = DO_ACTION_REEL; } - } else if ((func_8084E3C4 != this->func_674) && !(this->stateFlags2 & PLAYER_STATE2_18)) { + } else if ((func_8084E3C4 != this->func_674) && !(this->stateFlags2 & PLAYER_STATE2_CRAWLING)) { if ((this->doorType != PLAYER_DOORTYPE_NONE) && (!(this->stateFlags1 & PLAYER_STATE1_11) || ((heldActor != NULL) && (heldActor->id == ACTOR_EN_RU1)))) { @@ -9831,7 +9854,7 @@ void func_808473D4(PlayState* play, Player* this) { } else if ((this->stateFlags1 & (PLAYER_STATE1_13 | PLAYER_STATE1_21)) || ((this->stateFlags1 & PLAYER_STATE1_23) && (this->stateFlags2 & PLAYER_STATE2_22))) { doAction = DO_ACTION_DOWN; - } else if (this->stateFlags2 & PLAYER_STATE2_16) { + } else if (this->stateFlags2 & PLAYER_STATE2_DO_ACTION_ENTER) { doAction = DO_ACTION_ENTER; } else if ((this->stateFlags1 & PLAYER_STATE1_11) && (this->getItemId == GI_NONE) && (heldActor != NULL)) { @@ -9935,7 +9958,7 @@ void func_80847BA0(PlayState* play, Player* this) { D_80853604 = this->unk_A7A; - if (this->stateFlags2 & PLAYER_STATE2_18) { + if (this->stateFlags2 & PLAYER_STATE2_CRAWLING) { spB0 = 10.0f; spAC = 15.0f; spA8 = 30.0f; @@ -10034,27 +10057,27 @@ void func_80847BA0(PlayState* play, Player* this) { this->actor.bgCheckFlags &= ~BGCHECKFLAG_PLAYER_WALL_INTERACT; if (this->actor.bgCheckFlags & BGCHECKFLAG_WALL) { - CollisionPoly* spA0; - s32 sp9C; + CollisionPoly* wallPoly; + s32 wallBgId; s16 sp9A; s32 pad; D_80854798.y = 18.0f; D_80854798.z = this->ageProperties->unk_38 + 10.0f; - if (!(this->stateFlags2 & PLAYER_STATE2_18) && - func_80839768(play, this, &D_80854798, &spA0, &sp9C, &D_80858AA8)) { + if (!(this->stateFlags2 & PLAYER_STATE2_CRAWLING) && + func_80839768(play, this, &D_80854798, &wallPoly, &wallBgId, &D_80858AA8)) { this->actor.bgCheckFlags |= BGCHECKFLAG_PLAYER_WALL_INTERACT; - if (this->actor.wallPoly != spA0) { - this->actor.wallPoly = spA0; - this->actor.wallBgId = sp9C; - this->actor.wallYaw = Math_Atan2S(spA0->normal.z, spA0->normal.x); + if (this->actor.wallPoly != wallPoly) { + this->actor.wallPoly = wallPoly; + this->actor.wallBgId = wallBgId; + this->actor.wallYaw = Math_Atan2S(wallPoly->normal.z, wallPoly->normal.x); } } sp9A = this->actor.shape.rot.y - (s16)(this->actor.wallYaw + 0x8000); - D_808535F0 = SurfaceType_GetWallFlags(&play->colCtx, this->actor.wallPoly, this->actor.wallBgId); + sInteractWallFlags = SurfaceType_GetWallFlags(&play->colCtx, this->actor.wallPoly, this->actor.wallBgId); D_80853608 = ABS(sp9A); @@ -10665,7 +10688,7 @@ void Player_UpdateCommon(Player* this, PlayState* play, Input* input) { Math_StepToF(&this->pushedSpeed, 0.0f, (this->stateFlags1 & PLAYER_STATE1_27) ? 0.5f : 1.0f); } - if (!Player_InBlockingCsMode(play, this) && !(this->stateFlags2 & PLAYER_STATE2_18)) { + if (!Player_InBlockingCsMode(play, this) && !(this->stateFlags2 & PLAYER_STATE2_CRAWLING)) { func_8083D53C(play, this); if ((this->actor.category == ACTORCAT_PLAYER) && (gSaveContext.health == 0)) { @@ -10723,7 +10746,7 @@ void Player_UpdateCommon(Player* this, PlayState* play, Input* input) { this->stateFlags1 &= ~(PLAYER_STATE1_SWINGING_BOTTLE | PLAYER_STATE1_9 | PLAYER_STATE1_12 | PLAYER_STATE1_22); this->stateFlags2 &= ~(PLAYER_STATE2_0 | PLAYER_STATE2_2 | PLAYER_STATE2_3 | PLAYER_STATE2_5 | PLAYER_STATE2_6 | PLAYER_STATE2_8 | PLAYER_STATE2_9 | PLAYER_STATE2_12 | PLAYER_STATE2_14 | - PLAYER_STATE2_16 | PLAYER_STATE2_22 | PLAYER_STATE2_26); + PLAYER_STATE2_DO_ACTION_ENTER | PLAYER_STATE2_22 | PLAYER_STATE2_26); this->stateFlags3 &= ~PLAYER_STATE3_4; func_80847298(this); @@ -11016,9 +11039,10 @@ void Player_Draw(Actor* thisx, PlayState* play2) { if (projectedHeadPos.z < -4.0f) { overrideLimbDraw = Player_OverrideLimbDrawGameplayFirstPerson; } - } else if (this->stateFlags2 & PLAYER_STATE2_18) { + } else if (this->stateFlags2 & PLAYER_STATE2_CRAWLING) { if (this->actor.projectedPos.z < 0.0f) { - overrideLimbDraw = Player_OverrideLimbDrawGameplay_80090440; + // Player is behind the camera + overrideLimbDraw = Player_OverrideLimbDrawGameplayCrawling; } } @@ -11742,23 +11766,30 @@ static struct_80832924 D_808548B4[] = { { 0, 0x3050 }, { 0, 0x3058 }, { 0, 0x3060 }, { 0, -0x3068 }, }; +/** + * Update player's animation while entering the crawlspace. + * Once inside, stop all player animations and update player's movement. + */ void func_8084C760(Player* this, PlayState* play) { this->stateFlags2 |= PLAYER_STATE2_6; if (LinkAnimation_Update(play, &this->skelAnime)) { if (!(this->stateFlags1 & PLAYER_STATE1_0)) { + // While inside a crawlspace, player's skeleton does not move if (this->skelAnime.moveFlags != 0) { this->skelAnime.moveFlags = 0; return; } - if (!func_8083F570(this, play)) { + if (!Player_TryLeavingCrawlspace(this, play)) { + // Move forward and back while inside the crawlspace this->linearVelocity = sControlInput->rel.stick_y * 0.03f; } } return; } + // Still entering crawlspace func_80832924(this, D_808548B4); } @@ -11767,15 +11798,20 @@ static struct_80832924 D_808548D8[] = { { 0, 0x303C }, { 0, 0x3044 }, { 0, 0x304C }, { 0, -0x3054 }, }; +/** + * Update player's animation while leaving the crawlspace. + */ void func_8084C81C(Player* this, PlayState* play) { this->stateFlags2 |= PLAYER_STATE2_6; if (LinkAnimation_Update(play, &this->skelAnime)) { + // Player is finished exiting the crawlspace and control is returned func_8083C0E8(this, play); - this->stateFlags2 &= ~PLAYER_STATE2_18; + this->stateFlags2 &= ~PLAYER_STATE2_CRAWLING; return; } + // Continue animation of leaving crawlspace func_80832924(this, D_808548D8); }