En_guard_nuts OK and Partially documented (#668)

* guard_nuts OK

* doing some documenting

* more docs

* more docs

* minor changes

* touch ups

* format

* pr feedback

* fixing a name

* ran actor_fixer
This commit is contained in:
Parker Burnett 2022-03-24 21:34:50 -04:00 committed by GitHub
parent cbfa42c070
commit 950f3a247e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 365 additions and 41 deletions

3
spec
View File

@ -3325,8 +3325,7 @@ beginseg
name "ovl_En_Guard_Nuts"
compress
include "build/src/overlays/actors/ovl_En_Guard_Nuts/z_en_guard_nuts.o"
include "build/data/ovl_En_Guard_Nuts/ovl_En_Guard_Nuts.data.o"
include "build/data/ovl_En_Guard_Nuts/ovl_En_Guard_Nuts.reloc.o"
include "build/src/overlays/actors/ovl_En_Guard_Nuts/ovl_En_Guard_Nuts_reloc.o"
endseg
beginseg

View File

@ -15,7 +15,15 @@ void EnGuardNuts_Destroy(Actor* thisx, GlobalContext* globalCtx);
void EnGuardNuts_Update(Actor* thisx, GlobalContext* globalCtx);
void EnGuardNuts_Draw(Actor* thisx, GlobalContext* globalCtx);
#if 0
void EnGuardNuts_ChangeAnim(EnGuardNuts* this, s32 index);
void EnGuardNuts_SetupWait(EnGuardNuts* this);
void EnGuardNuts_Wait(EnGuardNuts* this, GlobalContext* globalCtx);
void func_80ABB540(EnGuardNuts* this);
void func_80ABB590(EnGuardNuts* this, GlobalContext* globalCtx);
void EnGuardNuts_Burrow(EnGuardNuts* this, GlobalContext* globalCtx);
void EnGuardNuts_SetupUnburrow(EnGuardNuts* this, GlobalContext* globalCtx);
void EnGuardNuts_Unburrow(EnGuardNuts* this, GlobalContext* globalCtx);
const ActorInit En_Guard_Nuts_InitVars = {
ACTOR_EN_GUARD_NUTS,
ACTORCAT_NPC,
@ -28,42 +36,350 @@ const ActorInit En_Guard_Nuts_InitVars = {
(ActorFunc)EnGuardNuts_Draw,
};
// static ColliderCylinderInit sCylinderInit = {
static ColliderCylinderInit D_80ABBDF0 = {
{ COLTYPE_NONE, AT_NONE, AC_NONE, OC1_ON | OC1_TYPE_PLAYER, OC2_TYPE_2, COLSHAPE_CYLINDER, },
{ ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_NONE, OCELEM_ON | OCELEM_UNK3, },
static ColliderCylinderInit sCylinderInit = {
{
COLTYPE_NONE,
AT_NONE,
AC_NONE,
OC1_ON | OC1_TYPE_PLAYER,
OC2_TYPE_2,
COLSHAPE_CYLINDER,
},
{
ELEMTYPE_UNK0,
{ 0xF7CFFFFF, 0x00, 0x00 },
{ 0xF7CFFFFF, 0x00, 0x00 },
TOUCH_NONE | TOUCH_SFX_NORMAL,
BUMP_NONE,
OCELEM_ON | OCELEM_UNK3,
},
{ 50, 50, 0, { 0, 0, 0 } },
};
#endif
s32 sGuardCount = 0;
extern ColliderCylinderInit D_80ABBDF0;
s32 D_80ABBE20 = 0;
extern UNK_TYPE D_06002700;
extern UNK_TYPE D_06002A08;
static u16 sTextIDs[] = { 0x0824, 0x0825, 0x0826, 0x082D, 0x0827, 0x0828, 0x0829, 0x082A, 0x082B, 0x082C };
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Guard_Nuts/EnGuardNuts_Init.s")
s16 D_80ABBE38[] = { 0x0000, 0x0000, 0x0002, 0x0001, 0x0000, 0x0000, 0x0002, 0x0000, 0x0000, 0x0002 };
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Guard_Nuts/EnGuardNuts_Destroy.s")
static AnimationHeader* sAnimations[] = {
&gDekuPalaceGuardWaitAnim,
&gDekuPalaceGuardWalkAnim,
&gDekuPalaceGuardDigAnim,
&gDekuPalaceGuardWalkAnim,
};
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Guard_Nuts/func_80ABB210.s")
static u8 sAnimModes[] = { ANIMMODE_LOOP, ANIMMODE_LOOP, ANIMMODE_ONCE, ANIMMODE_ONCE };
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Guard_Nuts/func_80ABB29C.s")
static TexturePtr sEyeTextures[] = {
gDekuPalaceGuardEyeOpenTex,
gDekuPalaceGuardEyeHalfTex,
gDekuPalaceGuardEyeClosedTex,
};
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Guard_Nuts/func_80ABB2D4.s")
typedef enum {
/* 0 */ WAIT_HEAD_TILT_ANIM,
/* 1 */ WALK_ANIM,
/* 2 */ DIG_ANIM,
/* 3 */ WALK_ANIM_2,
} EnGuardNutsAnim;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Guard_Nuts/func_80ABB540.s")
typedef enum {
/* 0 */ GUARD_NUTS_WAIT_STATE,
/* 1 */ GUARD_NUTS_TALKING_STATE,
/* 3 */ GUARD_NUTS_BURROWED_STATE = 3,
/* 4 */ GUARD_NUTS_UNK_STATE
} EnGuardNutsState;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Guard_Nuts/func_80ABB590.s")
void EnGuardNuts_Init(Actor* thisx, GlobalContext* globalCtx) {
EnGuardNuts* this = THIS;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Guard_Nuts/func_80ABB854.s")
ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 20.0f);
SkelAnime_Init(globalCtx, &this->skelAnime, &gDekuPalaceGuardSkel, &gDekuPalaceGuardWaitAnim, this->jointTable,
this->morphTable, OBJECT_DNK_LIMB_MAX);
this->actor.colChkInfo.mass = MASS_IMMOVABLE;
this->actor.targetMode = 1;
Collider_InitAndSetCylinder(globalCtx, &this->collider, &this->actor, &sCylinderInit);
Actor_SetScale(&this->actor, 0.015f);
Math_Vec3f_Copy(&this->guardPos, &this->actor.world.pos);
this->guardNumber = sGuardCount;
sGuardCount++;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Guard_Nuts/func_80ABB91C.s")
// If you have returned deku princess guards will init burrowed.
if (!(gSaveContext.weekEventReg[23] & 0x20)) {
EnGuardNuts_SetupWait(this);
} else {
EnGuardNuts_Burrow(this, globalCtx);
}
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Guard_Nuts/func_80ABB990.s")
void EnGuardNuts_Destroy(Actor* thisx, GlobalContext* globalCtx) {
EnGuardNuts* this = THIS;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Guard_Nuts/EnGuardNuts_Update.s")
Collider_DestroyCylinder(globalCtx, &this->collider);
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Guard_Nuts/func_80ABBC60.s")
/**
* @brief Changes the animation to the provided index. Updates animIndex and animFrameCount for the animation.
*
* @param this
* @param index the index of sAnimations to change to
*/
void EnGuardNuts_ChangeAnim(EnGuardNuts* this, s32 index) {
this->animIndex = index;
this->animFrameCount = Animation_GetLastFrame(sAnimations[this->animIndex]);
Animation_Change(&this->skelAnime, sAnimations[this->animIndex], 1.0f, 0.0f, this->animFrameCount,
sAnimModes[this->animIndex], -2.0f);
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Guard_Nuts/EnGuardNuts_Draw.s")
void EnGuardNuts_SetupWait(EnGuardNuts* this) {
EnGuardNuts_ChangeAnim(this, WAIT_HEAD_TILT_ANIM);
this->state = GUARD_NUTS_WAIT_STATE;
this->actionFunc = EnGuardNuts_Wait;
}
void EnGuardNuts_Wait(EnGuardNuts* this, GlobalContext* globalCtx) {
Player* player = GET_PLAYER(globalCtx);
s16 phi_a1;
s16 yawDiff;
SkelAnime_Update(&this->skelAnime);
yawDiff = ABS_ALT(BINANG_SUB(this->actor.yawTowardsPlayer, this->actor.home.rot.y));
if (Actor_ProcessTalkRequest(&this->actor, &globalCtx->state)) {
func_80ABB540(this);
return;
}
if (yawDiff > 0x6000) {
D_80ABBE20 = 2;
}
if (player->transformation == PLAYER_FORM_DEKU) {
// this is the palace of...
this->guardTextIndex = 0;
if ((gSaveContext.weekEventReg[17] & 4) && (!this->hasCompletedConversation)) {
// I told you not to enter!!
this->guardTextIndex = 7;
} else if (gSaveContext.weekEventReg[12] & 0x40) {
// come to see the monkey again?
this->guardTextIndex = 4;
}
} else {
// No place for an outsider
this->guardTextIndex = 3;
}
this->actor.textId = sTextIDs[this->guardTextIndex];
phi_a1 = this->actor.world.rot.y;
if (D_80ABBE20 == 2) {
EnGuardNuts_Burrow(this, globalCtx);
return;
}
if (D_80ABBE20 == 1) {
if (this->animIndex != WALK_ANIM) {
EnGuardNuts_ChangeAnim(this, WALK_ANIM);
}
phi_a1 = (this->actor.home.rot.y + 0x8000);
}
if (fabsf((f32)(this->actor.shape.rot.y - phi_a1)) < 100.0f) {
this->actor.shape.rot.y = phi_a1;
if ((D_80ABBE20 == 1) && (this->animIndex != WALK_ANIM_2)) {
EnGuardNuts_ChangeAnim(this, WALK_ANIM_2);
}
} else {
Math_SmoothStepToS(&this->actor.shape.rot.y, phi_a1, 1, 0xBB8, 0);
}
if (this->targetHeadPos.x == 0) {
if (fabsf((f32)this->actor.world.rot.y - (f32)this->actor.yawTowardsPlayer) < 10000.0f) {
this->targetHeadPos.y = this->actor.world.rot.y - this->actor.yawTowardsPlayer;
this->targetHeadPos.y = -this->targetHeadPos.y;
}
}
func_800B8614(&this->actor, globalCtx, 70.0f);
}
void func_80ABB540(EnGuardNuts* this) {
EnGuardNuts_ChangeAnim(this, WALK_ANIM);
this->targetHeadPos.x = this->targetHeadPos.y = 0;
this->timer = 16;
this->state = GUARD_NUTS_TALKING_STATE;
this->actionFunc = func_80ABB590;
}
void func_80ABB590(EnGuardNuts* this, GlobalContext* globalCtx) {
s16 yaw = this->actor.yawTowardsPlayer;
f32 curFrame;
if (D_80ABBE20 == 1) {
yaw = (this->actor.home.rot.y + 0x8000);
}
if (fabsf((this->actor.shape.rot.y - yaw)) < 100.0f) {
this->actor.shape.rot.y = yaw;
curFrame = this->skelAnime.curFrame;
if ((curFrame < this->animFrameCount) || (this->guardTextIndex >= 7)) {
SkelAnime_Update(&this->skelAnime);
}
} else {
SkelAnime_Update(&this->skelAnime);
Math_SmoothStepToS(&this->actor.shape.rot.y, yaw, 1, 0xBB8, 0);
}
if (Message_GetState(&globalCtx->msgCtx) == 5) {
this->targetHeadPos.y = 0;
this->targetHeadPos.x = 0;
if ((this->guardTextIndex == 3) && (this->animIndex == WAIT_HEAD_TILT_ANIM)) {
EnGuardNuts_ChangeAnim(this, WAIT_HEAD_TILT_ANIM);
}
if (func_80147624(globalCtx) != 0) {
if (D_80ABBE38[this->guardTextIndex] != 1) {
if (D_80ABBE38[this->guardTextIndex] == 2) {
func_801477B4(globalCtx);
D_80ABBE20 = 2;
gSaveContext.weekEventReg[12] |= 0x40;
EnGuardNuts_Burrow(this, globalCtx);
} else {
this->guardTextIndex++;
Message_StartTextbox(globalCtx, sTextIDs[this->guardTextIndex], &this->actor);
if (D_80ABBE38[this->guardTextIndex] == 2) {
D_80ABBE20 = 1;
}
this->timer = 16;
}
} else if (this->guardTextIndex != 3) {
this->targetHeadPos.x = 0;
this->targetHeadPos.y = this->targetHeadPos.x;
func_801477B4(globalCtx);
this->state = GUARD_NUTS_UNK_STATE;
this->actionFunc = EnGuardNuts_Unburrow;
} else {
func_801477B4(globalCtx);
EnGuardNuts_SetupWait(this);
}
}
} else if ((Message_GetState(&globalCtx->msgCtx) >= 3) && (D_80ABBE20 == 0)) {
if ((this->guardTextIndex == 0) || (this->guardTextIndex == 3) || (this->guardTextIndex >= 7)) {
if (this->timer == 0) {
this->timer = 2;
this->targetHeadPos.y ^= 0x2000;
}
} else if (this->timer == 0) {
this->timer = 2;
this->targetHeadPos.x ^= 0x2000;
}
}
}
void EnGuardNuts_Burrow(EnGuardNuts* this, GlobalContext* globalCtx) {
Vec3f digPos;
EnGuardNuts_ChangeAnim(this, DIG_ANIM);
Math_Vec3f_Copy(&digPos, &this->actor.world.pos);
digPos.y = this->actor.floorHeight;
EffectSsHahen_SpawnBurst(globalCtx, &digPos, 4.0f, 0, 10, 3, 15, -1, 10, NULL);
this->targetHeadPos.y = 0;
this->actor.flags |= ACTOR_FLAG_8000000;
this->targetHeadPos.x = this->targetHeadPos.y;
Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_NUTS_DOWN);
Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_NUTS_UP);
this->actionFunc = EnGuardNuts_SetupUnburrow;
}
void EnGuardNuts_SetupUnburrow(EnGuardNuts* this, GlobalContext* globalCtx) {
f32 curFrame = this->skelAnime.curFrame;
SkelAnime_Update(&this->skelAnime);
if (this->animFrameCount <= curFrame) {
this->state = GUARD_NUTS_BURROWED_STATE;
this->actionFunc = EnGuardNuts_Unburrow;
this->actor.world.rot.y = this->actor.home.rot.y;
this->actor.shape.rot.y = this->actor.home.rot.y;
}
}
void EnGuardNuts_Unburrow(EnGuardNuts* this, GlobalContext* globalCtx) {
s16 yawDiff;
Vec3f digPos;
// If you have returned Deku Princess, guards will not unburrow
if (!(gSaveContext.weekEventReg[23] & 0x20)) {
yawDiff = ABS_ALT(BINANG_SUB(this->actor.yawTowardsPlayer, this->actor.home.rot.y));
if ((yawDiff < 0x4000) && ((D_80ABBE20 == 0) || (this->actor.xzDistToPlayer > 150.0f))) {
Math_Vec3f_Copy(&digPos, &this->actor.world.pos);
digPos.y = this->actor.floorHeight;
EffectSsHahen_SpawnBurst(globalCtx, &digPos, 4.0f, 0, 10, 3, 15, -1, 10, NULL);
Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_NUTS_UP);
D_80ABBE20 = 0;
if (this->guardTextIndex == 9) {
this->hasCompletedConversation = true;
}
this->actor.flags &= ~ACTOR_FLAG_8000000;
EnGuardNuts_SetupWait(this);
}
}
}
void EnGuardNuts_Update(Actor* thisx, GlobalContext* globalCtx) {
EnGuardNuts* this = THIS;
s32 pad;
if (this->blinkTimer == 0) {
if (++(this->eyeState) >= 3) {
this->eyeState = 0;
this->blinkTimer = (s16)Rand_ZeroFloat(60.0f) + 20;
}
}
if ((this->animIndex == WALK_ANIM) &&
((Animation_OnFrame(&this->skelAnime, 1.0f)) || (Animation_OnFrame(&this->skelAnime, 5.0f)))) {
Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_NUTS_WALK);
}
this->actionFunc(this, globalCtx);
Actor_SetFocus(&this->actor, 40.0f);
Math_SmoothStepToS(&this->headRot.x, this->targetHeadPos.x, 1, 0xBB8, 0);
Math_SmoothStepToS(&this->headRot.y, this->targetHeadPos.y, 1, 0xBB8, 0);
if (this->blinkTimer != 0) {
this->blinkTimer--;
}
if (this->timer != 0) {
this->timer--;
}
Actor_MoveWithGravity(&this->actor);
Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 20.0f, 20.0f, 60.0f, 0x1D);
if ((this->state != GUARD_NUTS_BURROWED_STATE) && (this->state != GUARD_NUTS_UNK_STATE)) {
Collider_UpdateCylinder(&this->actor, &this->collider);
CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
}
}
s32 EnGuardNuts_OverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot,
Actor* thisx) {
EnGuardNuts* this = THIS;
if (limbIndex == OBJECT_DNK_LIMB_HEAD) {
rot->x += this->headRot.x;
rot->y += this->headRot.y;
rot->z += this->headRot.z;
}
return false;
}
void EnGuardNuts_Draw(Actor* thisx, GlobalContext* globalCtx) {
EnGuardNuts* this = THIS;
OPEN_DISPS(globalCtx->state.gfxCtx);
func_8012C28C(globalCtx->state.gfxCtx);
gSPSegment(POLY_OPA_DISP++, 0x08, Lib_SegmentedToVirtual(sEyeTextures[this->eyeState]));
SkelAnime_DrawOpa(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable, EnGuardNuts_OverrideLimbDraw,
NULL, &this->actor);
Matrix_InsertTranslation(this->guardPos.x, this->actor.floorHeight, this->guardPos.z, MTXMODE_NEW);
Matrix_Scale(0.015f, 0.015f, 0.015f, 1);
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_OPA_DISP++, gDekuPalaceGuardFlower);
CLOSE_DISPS(globalCtx->state.gfxCtx);
}

View File

@ -2,16 +2,31 @@
#define Z_EN_GUARD_NUTS_H
#include "global.h"
#include "objects/object_dnk/object_dnk.h"
struct EnGuardNuts;
typedef void (*EnGuardNutsActionFunc)(struct EnGuardNuts*, GlobalContext*);
typedef struct EnGuardNuts {
/* 0x0000 */ Actor actor;
/* 0x0144 */ char unk_144[0xC8];
/* 0x020C */ EnGuardNutsActionFunc actionFunc;
/* 0x0210 */ char unk_210[0x80];
/* 0x000 */ Actor actor;
/* 0x144 */ SkelAnime skelAnime;
/* 0x188 */ Vec3s jointTable[OBJECT_DNK_LIMB_MAX];
/* 0x1CA */ Vec3s morphTable[OBJECT_DNK_LIMB_MAX];
/* 0x20C */ EnGuardNutsActionFunc actionFunc;
/* 0x210 */ s16 eyeState;
/* 0x212 */ s16 blinkTimer;
/* 0x214 */ s16 timer;
/* 0x218 */ s32 animIndex;
/* 0x21C */ s16 state;
/* 0x21E */ s16 guardNumber; // Unused - Number used to identify guard
/* 0x220 */ s32 guardTextIndex;
/* 0x224 */ u8 hasCompletedConversation; // Flag set when player has gone through all text.
/* 0x228 */ Vec3f guardPos;
/* 0x234 */ Vec3s headRot;
/* 0x23A */ Vec3s targetHeadPos;
/* 0x240 */ f32 animFrameCount;
/* 0x244 */ ColliderCylinder collider;
} EnGuardNuts; // size = 0x290
extern const ActorInit En_Guard_Nuts_InitVars;

View File

@ -11804,16 +11804,16 @@
0x80ABAE64:("func_80ABAE64",),
0x80ABB0E0:("EnGuardNuts_Init",),
0x80ABB1E4:("EnGuardNuts_Destroy",),
0x80ABB210:("func_80ABB210",),
0x80ABB29C:("func_80ABB29C",),
0x80ABB2D4:("func_80ABB2D4",),
0x80ABB210:("EnGuardNuts_ChangeAnim",),
0x80ABB29C:("EnGuardNuts_SetupWait",),
0x80ABB2D4:("EnGuardNuts_Wait",),
0x80ABB540:("func_80ABB540",),
0x80ABB590:("func_80ABB590",),
0x80ABB854:("func_80ABB854",),
0x80ABB91C:("func_80ABB91C",),
0x80ABB990:("func_80ABB990",),
0x80ABB854:("EnGuardNuts_Burrow",),
0x80ABB91C:("EnGuardNuts_SetupUnburrow",),
0x80ABB990:("EnGuardNuts_Unburrow",),
0x80ABBACC:("EnGuardNuts_Update",),
0x80ABBC60:("func_80ABBC60",),
0x80ABBC60:("EnGuardNuts_OverrideLimbDraw",),
0x80ABBCB8:("EnGuardNuts_Draw",),
0x80ABBFC0:("func_80ABBFC0",),
0x80ABC2E0:("func_80ABC2E0",),

View File

@ -1336,12 +1336,6 @@ D_0600A808 = 0x0600A808;
D_06000F9C = 0x06000F9C;
D_06003F00 = 0x06003F00;
// ovl_En_Guard_Nuts
D_06002700 = 0x06002700;
D_06002848 = 0x06002848;
D_06002A08 = 0x06002A08;
// ovl_En_Hata
D_060000C0 = 0x060000C0;