`EnDnk` Documented (#1831)

* Dnk: some docs

* Dnk: more docs

* Dnk: format

* Dnk: More docs

* Dnk: more docs

* Dnk: more docs

* Dnk: specify variants

* Pr2: requested changes
This commit is contained in:
Isghj 2025-12-09 02:51:03 -08:00 committed by GitHub
parent 7b96e58622
commit d6143abe52
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 160 additions and 144 deletions

View File

@ -2,6 +2,9 @@
* File: z_en_dnk.c * File: z_en_dnk.c
* Overlay: ovl_En_Dnk * Overlay: ovl_En_Dnk
* Description: Hallucinatory Mad Scrubs (Deku curse and healing cutscenes) * Description: Hallucinatory Mad Scrubs (Deku curse and healing cutscenes)
* This actor has two alternate objects that would use alternate models, unfinished
* Variant 0x2 (encircling link) and 0x6 (big, chases link, cutscene) both use object_dekunuts,
* instead of object_dnk and object_hintnuts
*/ */
#include "z_en_dnk.h" #include "z_en_dnk.h"
@ -14,10 +17,10 @@ void EnDnk_Update(Actor* thisx, PlayState* play);
void EnDnk_HandleCutscene(EnDnk* this, PlayState* play); void EnDnk_HandleCutscene(EnDnk* this, PlayState* play);
void EnDnk_DoNothing(EnDnk* this, PlayState* play); void EnDnk_DoNothing(EnDnk* this, PlayState* play);
void func_80A52018(Actor* thisx, PlayState* play); void EnDnk_Draw(Actor* thisx, PlayState* play);
void func_80A52134(EnDnk* this, PlayState* play); void EnDnk_UpdateCutscene(EnDnk* this, PlayState* play);
static s16 D_80A521A0 = 0; static s16 sScrubCount = 0;
ActorProfile En_Dnk_Profile = { ActorProfile En_Dnk_Profile = {
/**/ ACTOR_EN_DNK, /**/ ACTOR_EN_DNK,
@ -53,6 +56,8 @@ static ColliderCylinderInit sCylinderInit = {
static CollisionCheckInfoInit2 sColChkInfoInit = { 1, 0, 0, 0, MASS_IMMOVABLE }; static CollisionCheckInfoInit2 sColChkInfoInit = { 1, 0, 0, 0, MASS_IMMOVABLE };
// unfinished
// if spawned out of cutscene, you can indeed attack them and it results in blood but no interaction
static DamageTable sDamageTable = { static DamageTable sDamageTable = {
/* Deku Nut */ DMG_ENTRY(1, 0x0), /* Deku Nut */ DMG_ENTRY(1, 0x0),
/* Deku Stick */ DMG_ENTRY(1, 0x0), /* Deku Stick */ DMG_ENTRY(1, 0x0),
@ -125,10 +130,11 @@ typedef enum {
/* 32 */ ENDNK_ANIM_32, /* 32 */ ENDNK_ANIM_32,
/* 33 */ ENDNK_ANIM_33, /* 33 */ ENDNK_ANIM_33,
/* 34 */ ENDNK_ANIM_34, /* 34 */ ENDNK_ANIM_34,
/* 35 */ ENDNK_ANIM_35, /* 35 */ ENDNK_ANIM_IDLE,
/* 36 */ ENDNK_ANIM_MAX /* 36 */ ENDNK_ANIM_MAX
} EnDnkAnimation; } EnDnkAnimation;
// almost none of these animations get used
static AnimationInfoS sAnimationInfo[ENDNK_ANIM_MAX] = { static AnimationInfoS sAnimationInfo[ENDNK_ANIM_MAX] = {
{ &gDekuPalaceGuardStartAnim, 1.0f, 0, -1, ANIMMODE_ONCE, 0 }, // ENDNK_ANIM_0 { &gDekuPalaceGuardStartAnim, 1.0f, 0, -1, ANIMMODE_ONCE, 0 }, // ENDNK_ANIM_0
{ &gDekuPalaceGuardStartAnim, 1.0f, 0, -1, ANIMMODE_ONCE, -4 }, // ENDNK_ANIM_1 { &gDekuPalaceGuardStartAnim, 1.0f, 0, -1, ANIMMODE_ONCE, -4 }, // ENDNK_ANIM_1
@ -165,7 +171,7 @@ static AnimationInfoS sAnimationInfo[ENDNK_ANIM_MAX] = {
{ &gDekuScrubPantingAnim, 1.0f, 0, -1, ANIMMODE_LOOP, -4 }, // ENDNK_ANIM_32 { &gDekuScrubPantingAnim, 1.0f, 0, -1, ANIMMODE_LOOP, -4 }, // ENDNK_ANIM_32
{ &gDekuScrubRunAnim, 1.0f, 0, -1, ANIMMODE_LOOP, 0 }, // ENDNK_ANIM_33 { &gDekuScrubRunAnim, 1.0f, 0, -1, ANIMMODE_LOOP, 0 }, // ENDNK_ANIM_33
{ &gDekuScrubRunAnim, 1.0f, 0, -1, ANIMMODE_LOOP, -4 }, // ENDNK_ANIM_34 { &gDekuScrubRunAnim, 1.0f, 0, -1, ANIMMODE_LOOP, -4 }, // ENDNK_ANIM_34
{ &gDekuScrubStandingIdleAnim, 1.0f, 0, -1, ANIMMODE_LOOP, 0 }, // ENDNK_ANIM_35 { &gDekuScrubStandingIdleAnim, 1.0f, 0, -1, ANIMMODE_LOOP, 0 }, // ENDNK_ANIM_IDLE
}; };
s32 EnDnk_ChangeAnim(SkelAnime* skelAnime, s16 animIndex) { s32 EnDnk_ChangeAnim(SkelAnime* skelAnime, s16 animIndex) {
@ -192,51 +198,51 @@ s32 EnDnk_ChangeAnim(SkelAnime* skelAnime, s16 animIndex) {
return didAnimChange; return didAnimChange;
} }
s32 func_80A515C4(EnDnk* this) { s32 EnDnk_Blink(EnDnk* this) {
s32 ret = false; s32 ret = false;
if (DECR(this->unk_29E) == 0) { if (DECR(this->blinkTimer) == 0) {
this->unk_2A0++; this->eyeTexIndex++;
if (this->unk_2A0 >= 3) { if (this->eyeTexIndex >= 3) {
this->unk_29E = Rand_S16Offset(20, 20); this->blinkTimer = Rand_S16Offset(20, 20);
this->unk_2A0 = 0; this->eyeTexIndex = 0;
} }
ret = true; ret = true;
} }
return ret; return ret;
} }
void func_80A51648(EnDnk* this, PlayState* play) { void EnDnk_WaitForObject(EnDnk* this, PlayState* play) {
if (SubS_IsObjectLoaded(this->objectSlot, play) == true) { if (SubS_IsObjectLoaded(this->objectSlot, play) == true) {
gSegments[0x06] = OS_K0_TO_PHYSICAL(play->objectCtx.slots[this->objectSlot].segment); gSegments[0x06] = OS_K0_TO_PHYSICAL(play->objectCtx.slots[this->objectSlot].segment);
this->actor.draw = func_80A52018; this->actor.draw = EnDnk_Draw;
this->actor.objectSlot = this->objectSlot; this->actor.objectSlot = this->objectSlot;
ActorShape_Init(&this->actor.shape, 0.0f, NULL, 18.0f); ActorShape_Init(&this->actor.shape, 0.0f, NULL, 18.0f);
switch (ENDNK_GET_3(&this->actor)) { switch (ENDNK_GET_TYPE(&this->actor)) {
case ENDNK_GET_3_0: case ENDNK_TYPE_GUARD: // unused
SkelAnime_Init(play, &this->skelAnime, &gDekuPalaceGuardSkel, NULL, this->jointTable, this->morphTable, SkelAnime_Init(play, &this->skelAnime, &gDekuPalaceGuardSkel, NULL, this->jointTable, this->morphTable,
DEKU_PALACE_GUARD_LIMB_MAX); DEKU_PALACE_GUARD_LIMB_MAX);
EnDnk_ChangeAnim(&this->skelAnime, ENDNK_ANIM_7); EnDnk_ChangeAnim(&this->skelAnime, ENDNK_ANIM_7);
break; break;
case ENDNK_GET_3_1: case ENDNK_TYPE_HINT: // unused
SkelAnime_Init(play, &this->skelAnime, &object_hintnuts_Skel_0023B8.sh, NULL, this->jointTable, SkelAnime_Init(play, &this->skelAnime, &object_hintnuts_Skel_0023B8.sh, NULL, this->jointTable,
this->morphTable, OBJECT_HINTNUTS_LIMB_MAX); this->morphTable, OBJECT_HINTNUTS_LIMB_MAX);
EnDnk_ChangeAnim(&this->skelAnime, ENDNK_ANIM_18); EnDnk_ChangeAnim(&this->skelAnime, ENDNK_ANIM_18);
break; break;
case ENDNK_GET_3_2: case ENDNK_TYPE_ATTACK:
SkelAnime_Init(play, &this->skelAnime, &gDekuScrubSkel, NULL, this->jointTable, this->morphTable, SkelAnime_Init(play, &this->skelAnime, &gDekuScrubSkel, NULL, this->jointTable, this->morphTable,
DEKU_SCRUB_LIMB_MAX); DEKU_SCRUB_LIMB_MAX);
EnDnk_ChangeAnim(&this->skelAnime, ENDNK_ANIM_35); EnDnk_ChangeAnim(&this->skelAnime, ENDNK_ANIM_IDLE);
break; break;
} }
Collider_InitCylinder(play, &this->collider); Collider_InitCylinder(play, &this->collider);
Collider_SetCylinder(play, &this->collider, &this->actor, &sCylinderInit); Collider_SetCylinder(play, &this->collider, &this->actor, &sCylinderInit);
CollisionCheck_SetInfo2(&this->actor.colChkInfo, &sDamageTable, &sColChkInfoInit); CollisionCheck_SetInfo2(&this->actor.colChkInfo, &sDamageTable, &sColChkInfoInit);
if (ENDNK_GET_3C(&this->actor) == 4) { if (ENDNK_GET_CUTSCENE_BEHAVIOR(&this->actor) == ENDNK_CUTSCENE_CONTROL) {
this->actor.flags &= ~ACTOR_FLAG_ATTENTION_ENABLED; this->actor.flags &= ~ACTOR_FLAG_ATTENTION_ENABLED;
this->actor.flags |= (ACTOR_FLAG_UPDATE_CULLING_DISABLED | ACTOR_FLAG_DRAW_CULLING_DISABLED); this->actor.flags |= (ACTOR_FLAG_UPDATE_CULLING_DISABLED | ACTOR_FLAG_DRAW_CULLING_DISABLED);
this->actionFunc = EnDnk_HandleCutscene; this->actionFunc = EnDnk_HandleCutscene;
@ -255,6 +261,7 @@ void EnDnk_HandleCutscene(EnDnk* this, PlayState* play) {
} }
} }
// Regular scrubs in the cutscene have no job but to animate on the spot
void EnDnk_DoNothing(EnDnk* this, PlayState* play) { void EnDnk_DoNothing(EnDnk* this, PlayState* play) {
} }
@ -263,28 +270,28 @@ void EnDnk_Init(Actor* thisx, PlayState* play) {
this->objectSlot = OBJECT_SLOT_NONE; this->objectSlot = OBJECT_SLOT_NONE;
switch (ENDNK_GET_3(&this->actor)) { switch (ENDNK_GET_TYPE(&this->actor)) {
case ENDNK_GET_3_1: case ENDNK_TYPE_HINT:
this->objectSlot = SubS_GetObjectSlot(OBJECT_HINTNUTS, play); this->objectSlot = SubS_GetObjectSlot(OBJECT_HINTNUTS, play);
break; break;
case ENDNK_GET_3_0: case ENDNK_TYPE_GUARD:
this->objectSlot = SubS_GetObjectSlot(OBJECT_DNK, play); this->objectSlot = SubS_GetObjectSlot(OBJECT_DNK, play);
break; break;
case ENDNK_GET_3_2: case ENDNK_TYPE_ATTACK:
this->objectSlot = SubS_GetObjectSlot(OBJECT_DEKUNUTS, play); this->objectSlot = SubS_GetObjectSlot(OBJECT_DEKUNUTS, play);
break; break;
} }
if (this->objectSlot > OBJECT_SLOT_NONE) { if (this->objectSlot > OBJECT_SLOT_NONE) {
this->actionFunc = func_80A51648; this->actionFunc = EnDnk_WaitForObject;
} else { } else {
Actor_Kill(&this->actor); Actor_Kill(&this->actor);
} }
this->unk_2A2 = D_80A521A0; this->scrubId = sScrubCount;
D_80A521A0++; sScrubCount++;
} }
void EnDnk_Destroy(Actor* thisx, PlayState* play) { void EnDnk_Destroy(Actor* thisx, PlayState* play) {
@ -299,71 +306,74 @@ void EnDnk_Update(Actor* thisx, PlayState* play) {
this->actionFunc(this, play); this->actionFunc(this, play);
SkelAnime_Update(&this->skelAnime); SkelAnime_Update(&this->skelAnime);
func_80A515C4(this); EnDnk_Blink(this);
Actor_SetFocus(&this->actor, 34.0f); Actor_SetFocus(&this->actor, 34.0f);
Collider_UpdateCylinder(&this->actor, &this->collider); Collider_UpdateCylinder(&this->actor, &this->collider);
CollisionCheck_SetAC(play, &play->colChkCtx, &this->collider.base); CollisionCheck_SetAC(play, &play->colChkCtx, &this->collider.base);
CollisionCheck_SetOC(play, &play->colChkCtx, &this->collider.base); CollisionCheck_SetOC(play, &play->colChkCtx, &this->collider.base);
func_80A52134(this, play); EnDnk_UpdateCutscene(this, play);
} }
s32 EnDnk_OverrideLimbDraw2(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, Actor* thisx) { // Guard functions are unused
s32 EnDnk_Guard_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, Actor* thisx) {
EnDnk* this = (EnDnk*)thisx; EnDnk* this = (EnDnk*)thisx;
this->unk_260[limbIndex] = *dList; this->limbGfx[limbIndex] = *dList;
*dList = NULL; *dList = NULL;
return false; return false;
} }
void EnDnk_PostLimbDraw2(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx) { void EnDnk_Guard_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx) {
EnDnk* this = (EnDnk*)thisx; EnDnk* this = (EnDnk*)thisx;
MtxF sp5C; MtxF mtxFCopy;
Vec3f sp50 = gZeroVec3f; Vec3f zeroVec = gZeroVec3f;
Vec3f sp44; Vec3f headPos;
Vec3s sp3C; Vec3s headRot;
if (limbIndex == DEKU_PALACE_GUARD_LIMB_HEAD) { if (limbIndex == DEKU_PALACE_GUARD_LIMB_HEAD) {
Matrix_MultVec3f(&sp50, &sp44); Matrix_MultVec3f(&zeroVec, &headPos);
Matrix_Get(&sp5C); Matrix_Get(&mtxFCopy);
Matrix_MtxFToYXZRot(&sp5C, &sp3C, false); Matrix_MtxFToYXZRot(&mtxFCopy, &headRot, false);
Matrix_Translate(sp44.x, sp44.y, sp44.z, MTXMODE_NEW); Matrix_Translate(headPos.x, headPos.y, headPos.z, MTXMODE_NEW);
Matrix_Scale(this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, MTXMODE_APPLY); Matrix_Scale(this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, MTXMODE_APPLY);
if (this->unk_28C & 0x10) {
if (this->unk_28C & 0x20) { if (this->flags & DNK_FLAG_10) {
sp3C.x = this->unk_296; if (this->flags & DNK_FLAG_20) {
sp3C.y = this->unk_298; headRot.x = this->unk_296;
sp3C.y += this->actor.shape.rot.y; headRot.y = this->unk_298;
sp3C.z = 0; headRot.y += this->actor.shape.rot.y;
Math_SmoothStepToS(&this->unk_290, sp3C.x, 4, 0x1FFE, 1); headRot.z = 0;
Math_SmoothStepToS(&this->unk_292, sp3C.y, 4, 0x1FFE, 1); Math_SmoothStepToS(&this->currentHeadRot.x, headRot.x, 4, 0x1FFE, 1);
Math_SmoothStepToS(&this->unk_294, sp3C.z, 4, 0x1FFE, 1); Math_SmoothStepToS(&this->currentHeadRot.y, headRot.y, 4, 0x1FFE, 1);
Math_SmoothStepToS(&this->currentHeadRot.z, headRot.z, 4, 0x1FFE, 1);
} else { } else {
this->unk_290 = sp3C.x; this->currentHeadRot.x = headRot.x;
this->unk_292 = sp3C.y; this->currentHeadRot.y = headRot.y;
this->unk_294 = sp3C.z; this->currentHeadRot.z = headRot.z;
} }
} else { } else {
this->unk_28C |= 0x10; this->flags |= DNK_FLAG_10;
this->unk_290 = sp3C.x; this->currentHeadRot.x = headRot.x;
this->unk_292 = sp3C.y; this->currentHeadRot.y = headRot.y;
this->unk_294 = sp3C.z; this->currentHeadRot.z = headRot.z;
} }
Matrix_RotateYS(this->unk_292, MTXMODE_APPLY); Matrix_RotateYS(this->currentHeadRot.y, MTXMODE_APPLY);
Matrix_RotateXS(this->unk_290, MTXMODE_APPLY); Matrix_RotateXS(this->currentHeadRot.x, MTXMODE_APPLY);
Matrix_RotateZS(this->unk_294, MTXMODE_APPLY); Matrix_RotateZS(this->currentHeadRot.z, MTXMODE_APPLY);
} }
OPEN_DISPS(play->state.gfxCtx); OPEN_DISPS(play->state.gfxCtx);
MATRIX_FINALIZE_AND_LOAD(POLY_OPA_DISP++, play->state.gfxCtx); MATRIX_FINALIZE_AND_LOAD(POLY_OPA_DISP++, play->state.gfxCtx);
gSPDisplayList(POLY_OPA_DISP++, this->unk_260[limbIndex]); gSPDisplayList(POLY_OPA_DISP++, this->limbGfx[limbIndex]);
CLOSE_DISPS(play->state.gfxCtx); CLOSE_DISPS(play->state.gfxCtx);
} }
void func_80A51CB8(EnDnk* this, PlayState* play) { void EnDnk_Guard_Draw(EnDnk* this, PlayState* play) {
static TexturePtr D_80A5245C[] = { static TexturePtr sDnkEyes[] = {
gDekuPalaceGuardEyeOpenTex, gDekuPalaceGuardEyeOpenTex,
gDekuPalaceGuardEyeHalfTex, gDekuPalaceGuardEyeHalfTex,
gDekuPalaceGuardEyeClosedTex, gDekuPalaceGuardEyeClosedTex,
@ -374,90 +384,93 @@ void func_80A51CB8(EnDnk* this, PlayState* play) {
Gfx_SetupDL25_Opa(play->state.gfxCtx); Gfx_SetupDL25_Opa(play->state.gfxCtx);
gSPSegment(POLY_OPA_DISP++, 0x08, Lib_SegmentedToVirtual(D_80A5245C[this->unk_2A0])); gSPSegment(POLY_OPA_DISP++, 0x08, Lib_SegmentedToVirtual(sDnkEyes[this->eyeTexIndex]));
gDPPipeSync(POLY_OPA_DISP++); gDPPipeSync(POLY_OPA_DISP++);
SkelAnime_DrawOpa(play, this->skelAnime.skeleton, this->skelAnime.jointTable, EnDnk_OverrideLimbDraw2, SkelAnime_DrawOpa(play, this->skelAnime.skeleton, this->skelAnime.jointTable, EnDnk_Guard_OverrideLimbDraw,
EnDnk_PostLimbDraw2, &this->actor); EnDnk_Guard_PostLimbDraw, &this->actor);
CLOSE_DISPS(play->state.gfxCtx); CLOSE_DISPS(play->state.gfxCtx);
} }
s32 EnDnk_OverrideLimbDraw1(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, Actor* thisx) { s32 EnDnk_Nuts_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, Actor* thisx) {
EnDnk* this = (EnDnk*)thisx; EnDnk* this = (EnDnk*)thisx;
this->unk_260[limbIndex] = *dList; this->limbGfx[limbIndex] = *dList;
*dList = NULL; *dList = NULL;
return false; return false;
} }
void EnDnk_PostLimbDraw1(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx) { void EnDnk_Nuts_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx) {
EnDnk* this = (EnDnk*)thisx; EnDnk* this = (EnDnk*)thisx;
MtxF sp5C; MtxF mtxFCopy;
Vec3f sp50 = gZeroVec3f; Vec3f zeroVec = gZeroVec3f;
Vec3f sp44; Vec3f headPos;
Vec3s sp3C; Vec3s headRot;
// Note: Also for `limbIndex == OBJECT_HINTNUTS_LIMB_02` // Note: Also for `limbIndex == OBJECT_HINTNUTS_LIMB_02`
// Assumes `OBJECT_HINTNUTS_LIMB_02` is the same value as `DEKU_SCRUB_LIMB_HEAD` // Assumes `OBJECT_HINTNUTS_LIMB_02` is the same value as `DEKU_SCRUB_LIMB_HEAD`
// this is not head tracking, this is hair shaking with the animation to make his movement look more dynamic
if (limbIndex == DEKU_SCRUB_LIMB_HEAD) { if (limbIndex == DEKU_SCRUB_LIMB_HEAD) {
Matrix_MultVec3f(&sp50, &sp44); Matrix_MultVec3f(&zeroVec, &headPos);
Matrix_Get(&sp5C); Matrix_Get(&mtxFCopy);
Matrix_MtxFToYXZRot(&sp5C, &sp3C, false); Matrix_MtxFToYXZRot(&mtxFCopy, &headRot, false);
Matrix_Translate(sp44.x, sp44.y, sp44.z, MTXMODE_NEW); Matrix_Translate(headPos.x, headPos.y, headPos.z, MTXMODE_NEW);
Matrix_Scale(this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, MTXMODE_APPLY); Matrix_Scale(this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, MTXMODE_APPLY);
if (this->unk_28C & 0x10) { if (this->flags & DNK_FLAG_10) {
if (this->unk_28C & 0x20) { if (this->flags & DNK_FLAG_20) {
sp3C.z = this->unk_296 + 0x4000; headRot.z = this->unk_296 + 0x4000;
sp3C.y = this->unk_298 + 0x4000; headRot.y = this->unk_298 + 0x4000;
sp3C.y += this->actor.shape.rot.y; headRot.y += this->actor.shape.rot.y;
sp3C.x = 0; headRot.x = 0;
Math_SmoothStepToS(&this->unk_290, sp3C.x, 4, 0x1FFE, 1); Math_SmoothStepToS(&this->currentHeadRot.x, headRot.x, 4, 0x1FFE, 1);
Math_SmoothStepToS(&this->unk_292, sp3C.y, 4, 0x1FFE, 1); Math_SmoothStepToS(&this->currentHeadRot.y, headRot.y, 4, 0x1FFE, 1);
Math_SmoothStepToS(&this->unk_294, sp3C.z, 4, 0x1FFE, 1); Math_SmoothStepToS(&this->currentHeadRot.z, headRot.z, 4, 0x1FFE, 1);
} else { } else {
this->unk_290 = sp3C.x; this->currentHeadRot.x = headRot.x;
this->unk_292 = sp3C.y; this->currentHeadRot.y = headRot.y;
this->unk_294 = sp3C.z; this->currentHeadRot.z = headRot.z;
} }
} else { } else {
this->unk_28C |= 0x10; this->flags |= DNK_FLAG_10;
this->unk_290 = sp3C.x; this->currentHeadRot.x = headRot.x;
this->unk_292 = sp3C.y; this->currentHeadRot.y = headRot.y;
this->unk_294 = sp3C.z; this->currentHeadRot.z = headRot.z;
} }
Matrix_RotateYS(this->unk_292, MTXMODE_APPLY); Matrix_RotateYS(this->currentHeadRot.y, MTXMODE_APPLY);
Matrix_RotateXS(this->unk_290, MTXMODE_APPLY); Matrix_RotateXS(this->currentHeadRot.x, MTXMODE_APPLY);
Matrix_RotateZS(this->unk_294, MTXMODE_APPLY); Matrix_RotateZS(this->currentHeadRot.z, MTXMODE_APPLY);
} }
OPEN_DISPS(play->state.gfxCtx); OPEN_DISPS(play->state.gfxCtx);
MATRIX_FINALIZE_AND_LOAD(POLY_OPA_DISP++, play->state.gfxCtx); MATRIX_FINALIZE_AND_LOAD(POLY_OPA_DISP++, play->state.gfxCtx);
gSPDisplayList(POLY_OPA_DISP++, this->unk_260[limbIndex]); gSPDisplayList(POLY_OPA_DISP++, this->limbGfx[limbIndex]);
CLOSE_DISPS(play->state.gfxCtx); CLOSE_DISPS(play->state.gfxCtx);
} }
void func_80A51FC0(EnDnk* this, PlayState* play) { void EnDnk_Nuts_Draw(EnDnk* this, PlayState* play) {
Gfx_SetupDL25_Opa(play->state.gfxCtx); Gfx_SetupDL25_Opa(play->state.gfxCtx);
SkelAnime_DrawOpa(play, this->skelAnime.skeleton, this->skelAnime.jointTable, EnDnk_OverrideLimbDraw1, SkelAnime_DrawOpa(play, this->skelAnime.skeleton, this->skelAnime.jointTable, EnDnk_Nuts_OverrideLimbDraw,
EnDnk_PostLimbDraw1, &this->actor); EnDnk_Nuts_PostLimbDraw, &this->actor);
} }
void func_80A52018(Actor* thisx, PlayState* play) { void EnDnk_Draw(Actor* thisx, PlayState* play) {
EnDnk* this = (EnDnk*)thisx; EnDnk* this = (EnDnk*)thisx;
switch (ENDNK_GET_3(thisx)) { switch (ENDNK_GET_TYPE(thisx)) {
case ENDNK_GET_3_0: // palace guard type skeleton
func_80A51CB8(this, play); case ENDNK_TYPE_GUARD:
EnDnk_Guard_Draw(this, play);
break; break;
case ENDNK_GET_3_1: // deku nuts type skeleton
case ENDNK_GET_3_2: case ENDNK_TYPE_HINT:
func_80A51FC0(this, play); case ENDNK_TYPE_ATTACK:
EnDnk_Nuts_Draw(this, play);
break; break;
default: default:
@ -465,21 +478,21 @@ void func_80A52018(Actor* thisx, PlayState* play) {
} }
} }
void func_80A52074(EnDnk* this, PlayState* play) { void EnDnk_HandleCSAudio(EnDnk* this, PlayState* play) {
switch (play->csCtx.curFrame) { switch (play->csCtx.curFrame) {
case 80: case 4 * 20:
Audio_PlaySfx_2(NA_SE_EN_DEKNUTS_DANCE1); Audio_PlaySfx_2(NA_SE_EN_DEKNUTS_DANCE1);
break; break;
case 123: case 6 * 20 + 3:
Audio_PlaySfx_2(NA_SE_EN_DEKNUTS_DANCE2); Audio_PlaySfx_2(NA_SE_EN_DEKNUTS_DANCE2);
break; break;
case 438: case 21 * 20 + 18:
Actor_PlaySfx(&this->actor, NA_SE_EN_DEKNUTS_DANCE_BIG); Actor_PlaySfx(&this->actor, NA_SE_EN_DEKNUTS_DANCE_BIG);
break; break;
case 493: case 24 * 20 + 13:
Actor_PlaySfx(&this->actor, NA_SE_EN_STALKIDS_APPEAR); Actor_PlaySfx(&this->actor, NA_SE_EN_STALKIDS_APPEAR);
break; break;
@ -487,14 +500,16 @@ void func_80A52074(EnDnk* this, PlayState* play) {
break; break;
} }
// (200 - 2) and (440 - 2)? pre-delay the sfx?
if ((play->csCtx.curFrame >= 198) && (play->csCtx.curFrame < 438)) { if ((play->csCtx.curFrame >= 198) && (play->csCtx.curFrame < 438)) {
Audio_PlaySfx_2(NA_SE_EN_DEKNUTS_DANCE - SFX_FLAG); Audio_PlaySfx_2(NA_SE_EN_DEKNUTS_DANCE - SFX_FLAG);
} }
} }
void func_80A52134(EnDnk* this, PlayState* play) { void EnDnk_UpdateCutscene(EnDnk* this, PlayState* play) {
if ((play->csCtx.state != CS_STATE_IDLE) && (ENDNK_GET_3C(&this->actor) == 4) && (play->sceneId == SCENE_SPOT00) && // only play the sounds during the curse cutscene, not the healing cutscene
(gSaveContext.sceneLayer == 2)) { if ((play->csCtx.state != CS_STATE_IDLE) && (ENDNK_GET_CUTSCENE_BEHAVIOR(&this->actor) == ENDNK_CUTSCENE_CONTROL) &&
func_80A52074(this, play); (play->sceneId == SCENE_SPOT00) && (gSaveContext.sceneLayer == 2)) {
EnDnk_HandleCSAudio(this, play);
} }
} }

View File

@ -10,19 +10,22 @@ struct EnDnk;
typedef void (*EnDnkActionFunc)(struct EnDnk*, PlayState*); typedef void (*EnDnkActionFunc)(struct EnDnk*, PlayState*);
#define ENDNK_GET_3(thisx) ((thisx)->params & 0x3) #define ENDNK_GET_TYPE(thisx) ((thisx)->params & 0x3)
#define ENDNK_GET_3C(thisx) ((thisx)->params & 0x3C) #define ENDNK_GET_CUTSCENE_BEHAVIOR(thisx) ((thisx)->params & 0x3C)
typedef enum { #define ENDNK_CUTSCENE_CONTROL 0x4
/* 0 */ ENDNK_GET_3_0,
/* 1 */ ENDNK_GET_3_1, typedef enum EnDnkType{
/* 2 */ ENDNK_GET_3_2, /* 0 */ ENDNK_TYPE_GUARD, // dnk object, deku palace patroling guards
/* 3 */ ENDNK_GET_3_3, /* 1 */ ENDNK_TYPE_HINT, // hintnuts, used for sleeping scrub in swamp spiderhouse
/* 4 */ ENDNK_GET_3_4 /* 2 */ ENDNK_TYPE_ATTACK, // dekunuts, the one that gets used, attacking deku in woodfall
} EnDnkParam; } EnDnkType;
#define DNK_LIMB_MAX MAX(MAX((s32)DEKU_PALACE_GUARD_LIMB_MAX, (s32)OBJECT_HINTNUTS_LIMB_MAX), (s32)DEKU_SCRUB_LIMB_MAX) #define DNK_LIMB_MAX MAX(MAX((s32)DEKU_PALACE_GUARD_LIMB_MAX, (s32)OBJECT_HINTNUTS_LIMB_MAX), (s32)DEKU_SCRUB_LIMB_MAX)
#define DNK_FLAG_10 0x10
#define DNK_FLAG_20 0x20
typedef struct EnDnk { typedef struct EnDnk {
/* 0x000 */ Actor actor; /* 0x000 */ Actor actor;
/* 0x144 */ SkelAnime skelAnime; /* 0x144 */ SkelAnime skelAnime;
@ -31,18 +34,16 @@ typedef struct EnDnk {
/* 0x190 */ ColliderCylinder collider; /* 0x190 */ ColliderCylinder collider;
/* 0x1DC */ Vec3s jointTable[DNK_LIMB_MAX]; /* 0x1DC */ Vec3s jointTable[DNK_LIMB_MAX];
/* 0x21E */ Vec3s morphTable[DNK_LIMB_MAX]; /* 0x21E */ Vec3s morphTable[DNK_LIMB_MAX];
/* 0x260 */ Gfx* unk_260[DEKU_PALACE_GUARD_LIMB_MAX]; /* 0x260 */ Gfx* limbGfx[DEKU_PALACE_GUARD_LIMB_MAX];
/* 0x28C */ u16 unk_28C; /* 0x28C */ u16 flags; // head rotation flags, not sure they do anything
/* 0x28E */ s8 objectSlot; /* 0x28E */ s8 objectSlot;
/* 0x290 */ s16 unk_290; /* 0x290 */ Vec3s currentHeadRot;
/* 0x292 */ s16 unk_292; /* 0x296 */ s16 unk_296; // unused X, read but not set in head rotation
/* 0x294 */ s16 unk_294; /* 0x298 */ s16 unk_298; // unused Y, read but not set in head rotation
/* 0x296 */ s16 unk_296;
/* 0x298 */ s16 unk_298;
/* 0x29A */ UNK_TYPE1 unk_29A[0x4]; /* 0x29A */ UNK_TYPE1 unk_29A[0x4];
/* 0x29E */ s16 unk_29E; /* 0x29E */ s16 blinkTimer;
/* 0x2A0 */ s16 unk_2A0; /* 0x2A0 */ s16 eyeTexIndex;
/* 0x2A2 */ s16 unk_2A2; /* 0x2A2 */ s16 scrubId; // in order of spawning
} EnDnk; // size = 0x2A4 } EnDnk; // size = 0x2A4
#endif // Z_EN_DNK_H #endif // Z_EN_DNK_H

View File

@ -10572,22 +10572,22 @@ EnDnh_Update = 0x80A510E0; // type:func
EnDnh_OverrideLimbDraw = 0x80A51168; // type:func EnDnh_OverrideLimbDraw = 0x80A51168; // type:func
EnDnh_Draw = 0x80A511B4; // type:func EnDnh_Draw = 0x80A511B4; // type:func
EnDnk_ChangeAnim = 0x80A514F0; // type:func EnDnk_ChangeAnim = 0x80A514F0; // type:func
func_80A515C4 = 0x80A515C4; // type:func EnDnk_Blink = 0x80A515C4; // type:func
func_80A51648 = 0x80A51648; // type:func EnDnk_WaitForObject = 0x80A51648; // type:func
EnDnk_HandleCutscene = 0x80A51890; // type:func EnDnk_HandleCutscene = 0x80A51890; // type:func
EnDnk_DoNothing = 0x80A518DC; // type:func EnDnk_DoNothing = 0x80A518DC; // type:func
EnDnk_Init = 0x80A518EC; // type:func EnDnk_Init = 0x80A518EC; // type:func
EnDnk_Destroy = 0x80A519A8; // type:func EnDnk_Destroy = 0x80A519A8; // type:func
EnDnk_Update = 0x80A519D4; // type:func EnDnk_Update = 0x80A519D4; // type:func
EnDnk_OverrideLimbDraw2 = 0x80A51A78; // type:func EnDnk_Guard_OverrideLimbDraw = 0x80A51A78; // type:func
EnDnk_PostLimbDraw2 = 0x80A51AA4; // type:func EnDnk_Guard_PostLimbDraw = 0x80A51AA4; // type:func
func_80A51CB8 = 0x80A51CB8; // type:func EnDnk_Guard_Draw = 0x80A51CB8; // type:func
EnDnk_OverrideLimbDraw1 = 0x80A51D78; // type:func EnDnk_Nuts_OverrideLimbDraw = 0x80A51D78; // type:func
EnDnk_PostLimbDraw1 = 0x80A51DA4; // type:func EnDnk_Nuts_PostLimbDraw = 0x80A51DA4; // type:func
func_80A51FC0 = 0x80A51FC0; // type:func EnDnk_Nuts_Draw = 0x80A51FC0; // type:func
func_80A52018 = 0x80A52018; // type:func EnDnk_Draw = 0x80A52018; // type:func
func_80A52074 = 0x80A52074; // type:func EnDnk_HandleCSAudio = 0x80A52074; // type:func
func_80A52134 = 0x80A52134; // type:func EnDnk_UpdateCutscene = 0x80A52134; // type:func
EnDnq_ValidatePictograph = 0x80A52530; // type:func EnDnq_ValidatePictograph = 0x80A52530; // type:func
EnDnq_ChangeAnim = 0x80A5257C; // type:func EnDnq_ChangeAnim = 0x80A5257C; // type:func
func_80A52604 = 0x80A52604; // type:func func_80A52604 = 0x80A52604; // type:func