1
0
Fork 0
mirror of https://github.com/zeldaret/oot.git synced 2025-05-11 11:33:48 +00:00

Document Crawlspaces (#1286)

* Crawlspace docs, first draft

* Add wall docs

* OnePointDemo, fix

* format

* More player docs

* Document bgCamData

* Magic docs WIP

* More docs, first round finished

* Better docs

* More renaming

* Simpler name

* Another small adjustment

* rm if(1)

* Better names again after in-game testing

* Change comments

* change comment

* Big rename based on all the suggestions

* Small touch-up

* More PR Suggestions

* RESTORE_IDLE -> RESET

* More docs

* Capitalization

* PR suggestions

* Make declaration consistent

* Health_ChangeBy (amount)

* cleanup

* Document bgCamData

* More changes and cleanup

* More docs

* Clarify comments

* PR Suggestions

* Missed one

* More PR Suggestions

* Change comment

* Add another clarity comment

* format

* PR Feedback, rename bgcheck functions

* remove fallthrough cleanup (other pr that deals with that)

* PR Suggestions

* bug report

* sync with bgCamData PR

* small cleanup

* Another comment

* bgCamDataIndexBeforeUnderwater

* PR/Discord Discussions

* Missed some

* sync function header args

* Another suggestion

* cleanup

* Comments

* Change bgCamData to s16 for now

* PR suggestions

* the

* use "info"

* Missed a suggestion

* Discord Discussion

* Document playerFlag

* typo

* Revert bgCamFuncData to Vec3s

* format

* format

* First PR suggestion

* Some PR Suggestions, still need to test

* followup docs

* small cleanup

* target offset

* more PR

* forwardYaw

* crawlspace func/flag

* comment

* format

* Update include/z64player.h

Co-authored-by: Dragorn421 <Dragorn421@users.noreply.github.com>

* More PR Suggestions

* Update src/overlays/actors/ovl_player_actor/z_player.c

Co-authored-by: EllipticEllipsis <elliptic.ellipsis@gmail.com>

Co-authored-by: Dragorn421 <Dragorn421@users.noreply.github.com>
Co-authored-by: EllipticEllipsis <elliptic.ellipsis@gmail.com>
This commit is contained in:
engineer124 2022-10-23 17:32:51 -04:00 committed by GitHub
parent 2cb423d9ec
commit e4c1a4b512
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 261 additions and 192 deletions

View file

@ -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);

View file

@ -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,

View file

@ -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 {

View file

@ -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)

View file

@ -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
};

View file

@ -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) {

View file

@ -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;

View file

@ -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 } },

View file

@ -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;

View file

@ -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;
}

View file

@ -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;

View file

@ -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;
}

View file

@ -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);
}