summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorglank <tommy.bergman91@gmail.com>2020-03-18 20:42:43 +0100
committerglank <tommy.bergman91@gmail.com>2020-03-19 13:01:17 +0100
commit86c44726624cead111e64c488f464c8da81a0cd7 (patch)
tree19056dfa2303458488133e9e396dd7ff1cccbe38 /src
parentc5f388b2ac02b8f26a2ff551e03d186b5797181c (diff)
ovl_En_Tk OK
Diffstat (limited to 'src')
-rw-r--r--src/code/z_actor.c5
-rw-r--r--src/overlays/actors/ovl_En_Tk/z_en_tk.c1020
-rw-r--r--src/overlays/actors/ovl_En_Tk/z_en_tk.h49
3 files changed, 1029 insertions, 45 deletions
diff --git a/src/code/z_actor.c b/src/code/z_actor.c
index 71bba11f2..ba79db4ae 100644
--- a/src/code/z_actor.c
+++ b/src/code/z_actor.c
@@ -4040,10 +4040,7 @@ Hilite* func_8003435C(Vec3f* object, GlobalContext* globalCtx)
return func_8002EB44(object, &globalCtx->view.eye, &lightDir, globalCtx->state.gfxCtx);
}
-typedef s16 (*func_800343CC_arg4)(GlobalContext*, Actor*);
-typedef s16 (*func_800343CC_arg5)(GlobalContext*, Actor*);
-
-s32 func_800343CC(GlobalContext* globalCtx, Actor* actor, s16* arg2, f32 arg3, func_800343CC_arg4 unkFunc1, func_800343CC_arg5 unkFunc2)
+s32 func_800343CC(GlobalContext* globalCtx, Actor* actor, s16* arg2, f32 arg3, s16 (*unkFunc1)(GlobalContext*, Actor*), s16 (*unkFunc2)(GlobalContext*, Actor*))
{
s16 sp26;
s16 sp24;
diff --git a/src/overlays/actors/ovl_En_Tk/z_en_tk.c b/src/overlays/actors/ovl_En_Tk/z_en_tk.c
index 04943e872..5d9233314 100644
--- a/src/overlays/actors/ovl_En_Tk/z_en_tk.c
+++ b/src/overlays/actors/ovl_En_Tk/z_en_tk.c
@@ -1,14 +1,48 @@
+#include <ultra64.h>
+#include <global.h>
#include "z_en_tk.h"
-#define ROOM 0x00
+typedef struct
+{
+ /* 0x0000 */ u8 health; /* SubActorStruct98.health */
+ /* 0x0002 */ s16 h_2; /* SubActorStruct98.unk_10 */
+ /* 0x0004 */ s16 h_4; /* SubActorStruct98.unk_12 */
+ /* 0x0006 */ s16 h_6; /* SubActorStruct98.unk_14 */
+ /* 0x0008 */ u8 mass; /* SubActorStruct98.mass */
+ /* 0x000A */
+} EnTk_SubActorStruct98Init;
+
+#define ROOM 0x00
#define FLAGS 0x00000009
-void EnTk_Init(EnTk* this, GlobalContext* globalCtx);
-void EnTk_Destroy(EnTk* this, GlobalContext* globalCtx);
-void EnTk_Update(EnTk* this, GlobalContext* globalCtx);
-void EnTk_Draw(EnTk* this, GlobalContext* globalCtx);
+s32 EnTk_CheckNextSpot(EnTk *this, GlobalContext *ctxt);
+void EnTk_Init(Actor *this, GlobalContext *ctxt);
+void EnTk_Destroy(Actor *this, GlobalContext *ctxt);
+void EnTk_Stop_Update(EnTk *this, GlobalContext *ctxt);
+void EnTk_Walk_Update(EnTk *this, GlobalContext *ctxt);
+void EnTk_Dig_Update(EnTk *this, GlobalContext *ctxt);
+void EnTk_Update(Actor *this, GlobalContext *ctxt);
+void EnTk_Draw(Actor *this, GlobalContext *ctxt);
+
+extern UNK_TYPE D_04051DB0;
+extern UNK_TYPE D_040521B0;
+extern UNK_TYPE D_040525B0;
+extern UNK_TYPE D_040529B0;
+extern UNK_TYPE D_04052DB0;
+extern UNK_TYPE D_040531B0;
+extern UNK_TYPE D_040535B0;
+extern UNK_TYPE D_040539B0;
+extern UNK_TYPE D_06001144;
+extern UNK_TYPE D_06001FA8;
+extern UNK_TYPE D_06002F84;
+extern UNK_TYPE D_06003B40;
+extern UNK_TYPE D_06004340;
+extern UNK_TYPE D_06004B40;
+extern UNK_TYPE D_0600ACE0;
+extern UNK_TYPE D_0600BC90;
+extern UNK_TYPE D_0600BCA0;
+extern UNK_TYPE D_0600BE40;
-/*
const ActorInit En_Tk_InitVars =
{
ACTOR_EN_TK,
@@ -17,62 +51,972 @@ const ActorInit En_Tk_InitVars =
FLAGS,
OBJECT_TK,
sizeof(EnTk),
- (ActorFunc)EnTk_Init,
- (ActorFunc)EnTk_Destroy,
- (ActorFunc)EnTk_Update,
- (ActorFunc)EnTk_Draw,
+ EnTk_Init,
+ EnTk_Destroy,
+ EnTk_Update,
+ EnTk_Draw,
+};
+
+void EnTk_Eff_Create(EnTk *this, Vec3f *pos, Vec3f *speed, Vec3f *accel,
+ u8 duration, f32 size, f32 growth)
+{
+ s16 i;
+ EnTkEff *eff = this->eff;
+
+ for (i = 0; i < ARRAY_COUNT(this->eff); i++)
+ {
+ if (eff->active != 1)
+ {
+ eff->size = size;
+ eff->growth = growth;
+ eff->time_total = eff->time_left = duration;
+ eff->active = 1;
+ eff->pos = *pos;
+ eff->accel = *accel;
+ eff->speed = *speed;
+ break;
+ }
+ eff++;
+ }
+}
+
+void EnTk_Eff_Update(EnTk *this)
+{
+ s16 i;
+ EnTkEff *eff;
+
+ eff = this->eff;
+ for (i = 0; i < ARRAY_COUNT(this->eff); i++)
+ {
+ if (eff->active != 0)
+ {
+ eff->time_left--;
+ if (eff->time_left == 0)
+ {
+ eff->active = 0;
+ }
+ eff->accel.x = Math_Rand_ZeroOne() * 0.4f - 0.2f;
+ eff->accel.z = Math_Rand_ZeroOne() * 0.4f - 0.2f;
+ VEC3_ADD(eff->pos, eff->speed)
+ VEC3_ADD(eff->speed, eff->accel)
+ eff->size += eff->growth;
+ }
+ eff++;
+ }
+}
+
+void EnTk_Eff_Draw(EnTk *this, GlobalContext *ctxt)
+{
+ static u32 images[] =
+ {
+ (u32)&D_040539B0,
+ (u32)&D_040535B0,
+ (u32)&D_040531B0,
+ (u32)&D_04052DB0,
+ (u32)&D_040529B0,
+ (u32)&D_040525B0,
+ (u32)&D_040521B0,
+ (u32)&D_04051DB0,
+ };
+
+ EnTkEff *eff = this->eff;
+ GraphicsContext *gfx;
+ s16 gfx_setup;
+ s16 i;
+ s16 alpha;
+ s16 image_idx;
+ Gfx *pgdl[4];
+
+ /*
+ * This assignment always occurs before a call to func_800C6AC4 which
+ * makes me suspect that they're inside a macro where the function call
+ * is present only for debug builds. Same for func_800C6B54 most likely.
+ */
+ gfx = ctxt->state.gfxCtx;
+ func_800C6AC4(pgdl, ctxt->state.gfxCtx, "../z_en_tk_eff.c", 114);
+
+ gfx_setup = 0;
+
+ /*
+ * Same code is generated without the if,
+ * but that would make the do...while redundant so there's probably an if.
+ */
+ do { if (1) { func_80093D84(ctxt->state.gfxCtx); } } while (0);
+
+ for (i = 0; i < ARRAY_COUNT(this->eff); i++)
+ {
+ if (eff->active != 0)
+ {
+ if (gfx_setup == 0)
+ {
+ gfx->polyXlu.p = func_80093774(gfx->polyXlu.p, 0);
+ gSPDisplayList(gfx->polyXlu.p++, &D_0600BC90);
+ gDPSetEnvColor(gfx->polyXlu.p++, 0x64, 0x3C, 0x14, 0x00);
+ gfx_setup = 1;
+ }
+
+ alpha = eff->time_left * (255.f / eff->time_total);
+ gDPSetPrimColor(gfx->polyXlu.p++, 0, 0, 0xAA, 0x82, 0x5A, alpha);
+
+ gDPPipeSync(gfx->polyXlu.p++);
+ Matrix_Translate(eff->pos.x, eff->pos.y, eff->pos.z, 0);
+ func_800D1FD4(&ctxt->mf_11DA0);
+ Matrix_Scale(eff->size, eff->size, 1.f, 1);
+ gSPMatrix(gfx->polyXlu.p++,
+ Matrix_NewMtx(ctxt->state.gfxCtx, "../z_en_tk_eff.c",
+ 140),
+ G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+
+ image_idx = eff->time_left *
+ ((f32)ARRAY_COUNT(images) / eff->time_total);
+ gSPSegment(gfx->polyXlu.p++, 0x08,
+ SEGMENTED_TO_VIRTUAL(images[image_idx]));
+
+ gSPDisplayList(gfx->polyXlu.p++, &D_0600BCA0);
+ }
+ eff++;
+ }
+
+ func_800C6B54(pgdl, ctxt->state.gfxCtx, "../z_en_tk_eff.c", 154);
+}
+
+s32 EnTk_Eff_CreateDflt(EnTk *this, Vec3f *pos, u8 duration, f32 size,
+ f32 growth, f32 y_accel_max)
+{
+ Vec3f speed = {0.f, 0.f, 0.f};
+ Vec3f accel = {0.f, 0.3f, 0.f};
+
+ accel.y += Math_Rand_ZeroOne() * y_accel_max;
+
+ EnTk_Eff_Create(this, pos, &speed, &accel, duration, size, growth);
+
+ return 0;
+}
+
+/** z_en_tk_eff.c ends here probably **/
+
+static ColliderCylinderInit D_80B1D508 =
+{
+ {
+ 0x0A,
+ 0x00,
+ 0x00,
+ 0x39,
+ 0x20,
+ 0x01,
+ {
+ 0x00,
+ 0x00,
+ },
+ },
+ {
+ 0x00,
+ {
+ 0x00,
+ 0x00,
+ 0x00,
+ },
+ 0x00000000,
+ 0x00,
+ 0x00,
+ {
+ 0x00,
+ 0x00,
+ },
+ 0x00000000,
+ {
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ },
+ 0x00,
+ 0x00,
+ 0x01,
+ 0x00,
+ },
+ {
+ 0x001E,
+ 0x0034,
+ 0x0000,
+ {
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ },
+ },
};
-*/
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tk/func_80B1B900.s")
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tk/func_80B1B9A4.s")
+static EnTk_SubActorStruct98Init D_80B1D534 =
+{
+ 0x00,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0xFF,
+};
+
+void EnTk_Stop(EnTk *this, GlobalContext *ctxt)
+{
+ UNK_PTR anim = &D_06002F84;
+
+ SkelAnime_ChangeAnimation(&this->skel_anim, (u32)anim, 1.f, 0.f,
+ SkelAnime_GetFrameCount((u32)&D_06002F84), 0,
+ -10.f);
+
+ this->action_countdown = Math_Rand_S16Offset(60, 60);
+ this->actor.speedXZ = 0.f;
+}
+
+void EnTk_Walk(EnTk *this, GlobalContext *ctxt)
+{
+ UNK_PTR anim = &D_06001FA8;
+
+ SkelAnime_ChangeAnimation(&this->skel_anim, (u32)anim, 1.f, 0.f,
+ SkelAnime_GetFrameCount((u32)&D_06002F84), 0,
+ -10.f);
+
+ this->action_countdown = Math_Rand_S16Offset(240, 240);
+}
+
+void EnTk_Dig(EnTk *this, GlobalContext *ctxt)
+{
+ UNK_PTR anim = &D_06001144;
+
+ SkelAnime_ChangeAnimation(&this->skel_anim, (u32)anim, 1.f, 0.f,
+ SkelAnime_GetFrameCount((u32)&D_06001144), 0,
+ -10.f);
+
+ if (EnTk_CheckNextSpot(this, ctxt) >= 0)
+ {
+ this->valid_dig_here = 1;
+ }
+}
+
+void EnTk_UpdateEyes(EnTk *this)
+{
+ if (DECR(this->blink_countdown) == 0)
+ {
+ this->eye_image_idx++;
+ if (this->eye_image_idx > 2)
+ {
+ this->blink_cycles--;
+ if (this->blink_cycles < 0)
+ {
+ this->blink_countdown = Math_Rand_S16Offset(30, 30);
+ this->blink_cycles = 2;
+ if (Math_Rand_ZeroOne() > 0.5f)
+ {
+ this->blink_cycles++;
+ }
+ }
+ this->eye_image_idx = 0;
+ }
+ }
+}
+
+s32 EnTk_CheckFacingPlayer(EnTk *this)
+{
+ s16 v0;
+ s16 v1;
+
+ if (this->actor.waterSurfaceDist > 10000.f)
+ {
+ return 0;
+ }
+
+ v0 = this->actor.shape.rot.y;
+ v0 -= this->h_21E;
+ v0 -= this->head_rot;
+
+ v1 = this->actor.rotTowardsLinkY - v0;
+ if (ABS(v1) < 0x1554)
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+s32 EnTk_CheckNextSpot(EnTk *this, GlobalContext *ctxt)
+{
+ Actor *prop;
+ f32 dxz;
+ f32 dy;
+
+ prop = ctxt->actorCtx.actorList[ACTORTYPE_PROP].first;
+
+ while (prop != NULL)
+ {
+ if (prop->id != ACTOR_EN_IT)
+ {
+ prop = prop->next;
+ continue;
+ }
+
+ if (prop == this->current_spot)
+ {
+ prop = prop->next;
+ continue;
+ }
+
+ dy = prop->posRot.pos.y - this->actor.unk_80;
+ dxz = func_8002DB8C(&this->actor, prop);
+ if (dxz > 40.f || dy > 10.f)
+ {
+ prop = prop->next;
+ continue;
+ }
+
+ this->current_spot = prop;
+ return prop->params;
+ }
+
+ return -1;
+}
+
+void EnTk_CheckCurrentSpot(EnTk *this)
+{
+ f32 dxz;
+ f32 dy;
+
+ if (this->current_spot != NULL)
+ {
+ dy = this->current_spot->posRot.pos.y - this->actor.unk_80;
+ dxz = func_8002DB8C(&this->actor, this->current_spot);
+ if (dxz > 40.f || dy > 10.f)
+ {
+ this->current_spot = NULL;
+ }
+ }
+}
+
+f32 EnTk_Step(EnTk *this, GlobalContext *ctxt)
+{
+ f32 step_frames[] = {36.f, 10.f};
+ f32 a1_;
+ s32 i;
+
+ if (this->skel_anim.animCurrentFrame == 0.f ||
+ this->skel_anim.animCurrentFrame == 25.f)
+ {
+ /* NA_SE_EN_MORIBLIN_WALK */
+ Audio_PlayActorSound2(&this->actor, 0x38B8);
+ }
+
+ if (this->skel_anim.animCurrent != (u32)&D_06001FA8)
+ {
+ return 0.f;
+ }
+
+ a1_ = this->skel_anim.animCurrentFrame;
+ for (i = 0; i < ARRAY_COUNT(step_frames); i++)
+ {
+ if (a1_ < step_frames[i] + 12.f && a1_ >= step_frames[i])
+ {
+ break;
+ }
+ }
+ if (i >= ARRAY_COUNT(step_frames))
+ {
+ return 0.f;
+ }
+ else
+ {
+ a1_ = (0x8000 / 12.f) * (a1_ - step_frames[i]);
+ return Math_Sins(a1_) * 2.f;
+ }
+}
+
+s32 EnTk_Orient(EnTk *this, GlobalContext *ctxt)
+{
+ Path *path;
+ Vec3s *point;
+ f32 dx;
+ f32 dz;
+
+ if (this->actor.params < 0)
+ {
+ return 1;
+ }
+
+ path = &ctxt->setupPathList[0];
+ point = SEGMENTED_TO_VIRTUAL(path->point_array);
+ point += this->current_waypoint;
+
+ dx = point->x - this->actor.posRot.pos.x;
+ dz = point->z - this->actor.posRot.pos.z;
+
+ Math_SmoothScaleMaxMinS(&this->actor.shape.rot.y,
+ func_800FD250(dx, dz) * (0x8000 / M_PI),
+ 10, 1000, 1);
+ this->actor.posRot.rot = this->actor.shape.rot;
+
+ if (SQ(dx) + SQ(dz) < 10.f)
+ {
+ this->current_waypoint++;
+ if (this->current_waypoint >= path->n_points)
+ {
+ this->current_waypoint = 0;
+ }
+
+ return 0;
+ }
+ else
+ {
+ return 1;
+ }
+}
+
+u16 func_80B1C54C(GlobalContext *ctxt, Actor *a1)
+{
+ u16 ret;
+
+ ret = func_8006C360(ctxt, 14);
+ if (ret != 0)
+ {
+ return ret;
+ }
+
+ if (gSaveContext.inf_table[13] & 0x0200)
+ {
+ /* "Do you want me to dig here? ..." */
+ return 0x5019;
+ }
+ else
+ {
+ /* "Hey kid! ..." */
+ return 0x5018;
+ }
+}
+
+s16 func_80B1C5A0(GlobalContext *ctxt, Actor *actor)
+{
+ s32 ret = 1;
+
+ switch (func_8010BDBC(&ctxt->msgCtx))
+ {
+ case 0:
+ {
+ break;
+ }
+ case 1:
+ {
+ break;
+ }
+ case 2:
+ {
+ /* "I am the boss of the carpenters ..." (wtf?) */
+ if (actor->textId == 0x5028)
+ {
+ gSaveContext.inf_table[13] |= 0x0100;
+ }
+ ret = 0;
+ break;
+ }
+ case 3:
+ {
+ break;
+ }
+ case 4:
+ {
+ if (func_80106BC8(ctxt) != 0 &&
+ (actor->textId == 0x5018 || actor->textId == 0x5019))
+ {
+ if (ctxt->msgCtx.choiceIndex == 1)
+ {
+ /* "Thanks a lot!" */
+ actor->textId = 0x0084;
+ }
+ else if (gSaveContext.rupees < 10)
+ {
+ /* "You don't have enough Rupees!" */
+ actor->textId = 0x0085;
+ }
+ else
+ {
+ ctxt->msgCtx.msgMode = 0x37;
+ Rupees_ChangeBy(-10);
+ gSaveContext.inf_table[13] |= 0x0200;
+ return 2;
+ }
+ func_8010B720(ctxt, actor->textId);
+ gSaveContext.inf_table[13] |= 0x0200;
+ }
+ break;
+ }
+ case 5:
+ {
+ if (func_80106BC8(ctxt) != 0 &&
+ (actor->textId == 0x0084 || actor->textId == 0x0085))
+ {
+ func_80106CCC(ctxt);
+ ret = 0;
+ }
+ break;
+ }
+ case 6:
+ {
+ break;
+ }
+ case 7:
+ {
+ break;
+ }
+ case 8:
+ {
+ break;
+ }
+ case 9:
+ {
+ break;
+ }
+ }
+
+ return ret;
+}
+
+s32 EnTk_ChooseReward(EnTk *this)
+{
+ f32 luck;
+ s32 reward;
+
+ luck = Math_Rand_ZeroOne();
+
+ if (luck < 0.4f)
+ {
+ reward = 0;
+ }
+ else if (luck < 0.7)
+ {
+ reward = 1;
+ }
+ else if (luck < 0.9)
+ {
+ reward = 2;
+ }
+ else
+ {
+ reward = 3;
+ }
+
+ switch (reward)
+ {
+ case 0:
+ {
+ if (this->reward_count[0] < 8)
+ {
+ this->reward_count[0] += 1;
+ return reward;
+ }
+ break;
+ }
+ case 1:
+ {
+ if (this->reward_count[1] < 4)
+ {
+ this->reward_count[1] += 1;
+ return reward;
+ }
+ break;
+ }
+ case 2:
+ {
+ if (this->reward_count[2] < 2)
+ {
+ this->reward_count[2] += 1;
+ return reward;
+ }
+ break;
+ }
+ case 3:
+ {
+ if (this->reward_count[3] < 1)
+ {
+ this->reward_count[3] += 1;
+ return reward;
+ }
+ break;
+ }
+ }
+
+ if (this->reward_count[0] < 8)
+ {
+ this->reward_count[0] += 1;
+ reward = 0;
+ }
+ else if (this->reward_count[1] < 4)
+ {
+ this->reward_count[1] += 1;
+ reward = 1;
+ }
+ else if (this->reward_count[2] < 2)
+ {
+ this->reward_count[2] += 1;
+ reward = 2;
+ }
+ else if (this->reward_count[3] < 1)
+ {
+ this->reward_count[3] += 1;
+ reward = 3;
+ }
+ else
+ {
+ reward = 0;
+ this->reward_count[0] = 1;
+ this->reward_count[1] = 0;
+ this->reward_count[2] = 0;
+ this->reward_count[3] = 0;
+ }
+
+ return reward;
+}
+
+void EnTk_Dig_Eff(EnTk *this)
+{
+ Vec3f pos = {0.f, 0.f, 0.f};
+ Vec3f speed = {0.f, 0.f, 0.f};
+ Vec3f accel = {0.f, 0.3f, 0.f};
+
+ if (this->skel_anim.animCurrentFrame >= 32.f &&
+ this->skel_anim.animCurrentFrame < 40.f)
+ {
+ pos.x = (Math_Rand_ZeroOne() - 0.5f) * 12.f + this->v3f_304.x;
+ pos.y = (Math_Rand_ZeroOne() - 0.5f) * 8.f + this->v3f_304.y;
+ pos.z = (Math_Rand_ZeroOne() - 0.5f) * 12.f + this->v3f_304.z;
+ EnTk_Eff_CreateDflt(this, &pos, 12, 0.2f, 0.1f, 0.f);
+ }
+}
+
+void EnTk_Init(Actor *this, GlobalContext *ctxt)
+{
+ EnTk *tk = (EnTk *)this;
+ UNK_PTR anim = &D_06002F84;
+
+ ActorShape_Init(&tk->actor.shape, 0, ActorShadow_DrawFunc_Circle, 24.f);
+
+ func_800A46F8(ctxt, &tk->skel_anim, (u32)&D_0600BE40, 0, tk->hz_22A,
+ tk->hz_296, 18);
+ SkelAnime_ChangeAnimation(&tk->skel_anim, (u32)anim, 1.f, 0.f,
+ SkelAnime_GetFrameCount((u32)&D_06002F84),
+ 0, 0.f);
+
+ ActorCollider_AllocCylinder(ctxt, &tk->collider);
+ ActorCollider_InitCylinder(ctxt, &tk->collider, &tk->actor, &D_80B1D508);
+
+ func_80061EFC(&tk->actor.sub_98, NULL, &D_80B1D534);
+
+ if (gSaveContext.day_time <= 0xC000 ||
+ gSaveContext.day_time >= 0xE000 ||
+ !LINK_IS_CHILD ||
+ ctxt->sceneNum != SCENE_SPOT02)
+ {
+ Actor_Kill(&tk->actor);
+ return;
+ }
+
+ Actor_SetScale(&tk->actor, 0.01f);
+
+ tk->actor.unk_1F = 6;
+ tk->actor.gravity = -0.1f;
+ tk->current_reward = -1;
+ tk->current_spot = NULL;
+ tk->action_func = EnTk_Stop_Update;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tk/func_80B1BAB0.s")
+void EnTk_Destroy(Actor *this, GlobalContext *ctxt)
+{
+ EnTk *tk = (EnTk *)this;
+ ActorCollider_FreeCylinder(ctxt, &tk->collider);
+}
+
+void EnTk_Stop_Update(EnTk *this, GlobalContext *ctxt)
+{
+ s16 v1;
+ s16 a1_;
+
+ if (this->h_1E0 != 0)
+ {
+ v1 = this->actor.shape.rot.y;
+ v1 -= this->h_21E;
+ v1 = this->actor.rotTowardsLinkY - v1;
+
+ if (this->h_1E0 == 2)
+ {
+ EnTk_Dig(this, ctxt);
+ this->h_1E0 = 0;
+ this->action_func = EnTk_Dig_Update;
+ return;
+ }
+
+ func_800343CC(ctxt, &this->actor, &this->h_1E0,
+ this->collider.dim.radius + 30.f,
+ func_80B1C54C, func_80B1C5A0);
+ }
+ else if (EnTk_CheckFacingPlayer(this) != 0)
+ {
+ v1 = this->actor.shape.rot.y;
+ v1 -= this->h_21E;
+ v1 = this->actor.rotTowardsLinkY - v1;
+
+ this->action_countdown = 0;
+ func_800343CC(ctxt, &this->actor, &this->h_1E0,
+ this->collider.dim.radius + 30.f,
+ func_80B1C54C, func_80B1C5A0);
+ }
+ else if (func_8002F194(&this->actor, ctxt) != 0)
+ {
+ v1 = this->actor.shape.rot.y;
+ v1 -= this->h_21E;
+ v1 = this->actor.rotTowardsLinkY - v1;
+
+ this->action_countdown = 0;
+ this->h_1E0 = 1;
+ }
+ else if (DECR(this->action_countdown) == 0)
+ {
+ EnTk_Walk(this, ctxt);
+ this->action_func = EnTk_Walk_Update;
+
+ /*! @bug v1 is uninitialized past this branch */
+ }
+ else
+ {
+ v1 = 0;
+ }
+
+ a1_ = CLAMP(-v1, 1270, 10730);
+ Math_SmoothScaleMaxMinS(&this->head_rot, a1_, 6, 1000, 1);
+}
+
+void EnTk_Walk_Update(EnTk *this, GlobalContext *ctxt)
+{
+ if (this->h_1E0 == 2)
+ {
+ EnTk_Dig(this, ctxt);
+ this->h_1E0 = 0;
+ this->action_func = EnTk_Dig_Update;
+ }
+ else
+ {
+ this->actor.speedXZ = EnTk_Step(this, ctxt);
+ EnTk_Orient(this, ctxt);
+ Math_SmoothScaleMaxMinS(&this->head_rot, 0, 6, 1000, 1);
+ EnTk_CheckCurrentSpot(this);
+
+ DECR(this->action_countdown);
+ if (EnTk_CheckFacingPlayer(this) != 0 || this->action_countdown == 0)
+ {
+ EnTk_Stop(this, ctxt);
+ this->action_func = EnTk_Stop_Update;
+ }
+ }
+}
+
+void EnTk_Dig_Update(EnTk *this, GlobalContext *ctxt)
+{
+ Vec3f reward_origin;
+ Vec3f reward_pos;
+ s32 reward_params[] =
+ {
+ 0x0000, /* Green rupee */
+ 0x0001, /* Blue rupee */
+ 0x0002, /* Red rupee */
+ 0x0014, /* Purple rupee */
+ 0x0006, /* Heart piece */
+ };
+
+ EnTk_Dig_Eff(this);
+
+ if (this->skel_anim.animCurrentFrame == 32.f)
+ {
+ /* NA_SE_EV_DIG_UP - What's gonna come out? */
+ Audio_PlayActorSound2(&this->actor, 0x28C8);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tk/func_80B1BDDC.s")
+ this->reward_timer = 0;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tk/func_80B1BE94.s")
+ if (this->valid_dig_here == 1)
+ {
+ reward_origin.x = 0.f;
+ reward_origin.y = 0.f;
+ reward_origin.z = -40.f;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tk/func_80B1BF14.s")
+ Matrix_RotateY(this->actor.shape.rot.y, 0);
+ Matrix_MultVec3f(&reward_origin, &reward_pos);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tk/func_80B1BF8C.s")
+ VEC3_ADD(reward_pos, this->actor.posRot.pos)
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tk/func_80B1C00C.s")
+ this->current_reward = EnTk_ChooseReward(this);
+ if (this->current_reward == 3)
+ {
+ /*
+ * Upgrade the purple rupee reward to the heart piece if this
+ * is the first grand prize dig.
+ */
+ if ((gSaveContext.item_get_inf[1] & 0x1000) == 0)
+ {
+ gSaveContext.item_get_inf[1] |= 0x1000;
+ this->current_reward = 4;
+ }
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tk/func_80B1C0D0.s")
+ Item_DropCollectible(ctxt, &reward_pos,
+ reward_params[this->current_reward]);
+ }
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tk/func_80B1C154.s")
+ if (this->skel_anim.animCurrentFrame >= 32.f && this->reward_timer == 10)
+ {
+ /* Play a reward sound shortly after digging */
+ if (this->valid_dig_here == 0)
+ {
+ /* NA_SE_SY_ERROR - Bad dig spot */
+ Audio_PlayActorSound2(&this->actor, 0x4806);
+ }
+ else if (this->current_reward == 4)
+ {
+ /* NA_SE_SY_CORRECT_CHIME - Heart piece */
+ Audio_PlaySoundGeneral(0x4802, &D_801333D4, 4, &D_801333E0,
+ &D_801333E0, &D_801333E8);
+ }
+ else
+ {
+ /* NA_SE_SY_TRE_BOX_APPEAR - Rupee */
+ Audio_PlayActorSound2(&this->actor, 0x4807);
+ }
+ }
+ this->reward_timer++;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tk/func_80B1C23C.s")
+ if (func_800A56C8(&this->skel_anim, this->skel_anim.animFrameCount) != 0)
+ {
+ if (this->current_reward < 0)
+ {
+ /* "Nope, nothing here!" */
+ func_8010B680(ctxt, 0x501A, 0);
+ }
+ else
+ {
+ func_80106CCC(ctxt);
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tk/func_80B1C2B4.s")
+ EnTk_Stop(this, ctxt);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tk/func_80B1C3DC.s")
+ this->current_reward = -1;
+ this->valid_dig_here = 0;
+ this->action_func = EnTk_Stop_Update;
+ }
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tk/func_80B1C54C.s")
+void EnTk_Update(Actor *this, GlobalContext *ctxt)
+{
+ EnTk *tk = (EnTk *)this;
+ ColliderCylinderMain *collider = &tk->collider;
+
+ ActorCollider_Cylinder_Update(&tk->actor, collider);
+ Actor_CollisionCheck_SetOT(ctxt, &ctxt->sub_11E60, collider);
+
+ SkelAnime_FrameUpdateMatrix(&tk->skel_anim);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tk/func_80B1C5A0.s")
+ Actor_MoveForward(&tk->actor);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tk/func_80B1C738.s")
+ func_8002E4B4(ctxt, &tk->actor, 40.f, 10.f, 0.f, 5);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tk/func_80B1C8F0.s")
+ tk->action_func(tk, ctxt);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tk/EnTk_Init.s")
+ EnTk_Eff_Update(tk);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tk/EnTk_Destroy.s")
+ EnTk_UpdateEyes(tk);
+}
+
+void func_80B1D200(GlobalContext *ctxt)
+{
+ GraphicsContext *gfx;
+ Gfx *pgdl[4];
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tk/func_80B1CC04.s")
+ gfx = ctxt->state.gfxCtx;
+ func_800C6AC4(pgdl, ctxt->state.gfxCtx, "../z_en_tk.c", 1188);
+
+ gSPDisplayList(gfx->polyOpa.p++, &D_0600ACE0);
+
+ func_800C6B54(pgdl, ctxt->state.gfxCtx, "../z_en_tk.c", 1190);
+}
+
+s32 func_80B1D278(s16 a0, UNK_TYPE a1, UNK_TYPE a2, UNK_TYPE a3, Vec3s *sp10,
+ Actor *actor)
+{
+ EnTk *tk = (EnTk *)actor;
+
+ switch (a1)
+ {
+ /* Limb 15 - Head */
+ case 15:
+ {
+ tk->h_21E = sp10->y;
+ break;
+ }
+ /* Limb 16 - Jaw */
+ case 16:
+ {
+ tk->h_21E += sp10->y;
+ sp10->y += tk->head_rot;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+void func_80B1D2E4(GlobalContext *ctxt, UNK_TYPE a1, UNK_TYPE a2, UNK_TYPE a3,
+ Actor *actor)
+{
+ EnTk *this = (EnTk *)actor;
+ Vec3f sp28 = {0.f, 0.f, 4600.f};
+ Vec3f sp1C = {0.f, 0.f, 0.f};
+
+ /* Limb 16 - Jaw */
+ if (a1 == 16)
+ {
+ Matrix_MultVec3f(&sp1C, &this->actor.posRot2.pos);
+ }
+
+ /* Limb 14 - Neck */
+ if (a1 == 14)
+ {
+ Matrix_MultVec3f(&sp28, &this->v3f_304);
+ func_80B1D200(ctxt);
+ }
+}
+
+void EnTk_Draw(Actor *this, GlobalContext *ctxt)
+{
+ static u32 eye_images[] =
+ {
+ (u32)&D_06003B40,
+ (u32)&D_06004340,
+ (u32)&D_06004B40,
+ };
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tk/func_80B1CE28.s")
+ EnTk *tk = (EnTk *)this;
+ GraphicsContext *gfx;
+ Gfx *pgdl[4];
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tk/func_80B1CEF8.s")
+ Matrix_Push();
+ EnTk_Eff_Draw(tk, ctxt);
+ Matrix_Pull();
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tk/EnTk_Update.s")
+ gfx = ctxt->state.gfxCtx;
+ func_800C6AC4(pgdl, ctxt->state.gfxCtx, "../z_en_tk.c", 1294);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tk/func_80B1D200.s")
+ func_80093D18(ctxt->state.gfxCtx);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tk/func_80B1D278.s")
+ gSPSegment(gfx->polyOpa.p++, 0x08,
+ SEGMENTED_TO_VIRTUAL(eye_images[tk->eye_image_idx]));
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tk/func_80B1D2E4.s")
+ func_800A1AC8(ctxt, tk->skel_anim.limbIndex,
+ tk->skel_anim.actorDrawTbl, tk->skel_anim.dListCount,
+ func_80B1D278, func_80B1D2E4, &tk->actor);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Tk/EnTk_Draw.s")
+ func_800C6B54(pgdl, ctxt->state.gfxCtx, "../z_en_tk.c", 1312);
+}
diff --git a/src/overlays/actors/ovl_En_Tk/z_en_tk.h b/src/overlays/actors/ovl_En_Tk/z_en_tk.h
index 9f6b3323b..22c8ae5d4 100644
--- a/src/overlays/actors/ovl_En_Tk/z_en_tk.h
+++ b/src/overlays/actors/ovl_En_Tk/z_en_tk.h
@@ -4,11 +4,54 @@
#include <ultra64.h>
#include <global.h>
+/* Dust particle effect */
typedef struct
{
- /* 0x0000 */ Actor actor;
- /* 0x014C */ char unk_14C[0x624];
-} EnTk; // size = 0x0770
+ /* 0x0000 */ u8 active;
+ /* 0x0001 */ u8 time_left;
+ /* 0x0002 */ u8 time_total;
+ /* 0x0004 */ f32 size;
+ /* 0x0008 */ f32 growth;
+ /* 0x000C */ char unk_C[0x8];
+ /* 0x0014 */ Vec3f pos;
+ /* 0x0020 */ Vec3f speed;
+ /* 0x002C */ Vec3f accel;
+ /* 0x0038 */
+} EnTkEff;
+
+typedef struct EnTk EnTk;
+
+typedef void EnTkFunc(EnTk *this, GlobalContext *ctxt);
+
+struct EnTk
+{
+ /* 0x0000 */ Actor actor;
+ /* 0x014C */ SkelAnime skel_anim;
+ /* 0x018C */ char unk_18C[0x4];
+ /* 0x0190 */ EnTkFunc *action_func;
+ /* 0x0194 */ ColliderCylinderMain
+ collider;
+ /* 0x01E0 */ s16 h_1E0;
+ /* 0x01E2 */ char unk_1E2[0x26];
+ /* 0x0208 */ u8 valid_dig_here;
+ /* 0x0209 */ u8 reward_count[4];
+ /* 0x0210 */ Actor *current_spot;
+ /* 0x0214 */ s32 current_reward;
+ /* 0x0218 */ s16 blink_cycles;
+ /* 0x021A */ s16 reward_timer;
+ /* 0x021C */ s16 action_countdown;
+ /* 0x021E */ s16 h_21E;
+ /* 0x0220 */ char unk_220[0x2];
+ /* 0x0222 */ s16 eye_image_idx;
+ /* 0x0224 */ s16 blink_countdown;
+ /* 0x0226 */ s16 head_rot;
+ /* 0x0228 */ s16 current_waypoint;
+ /* 0x022A */ u16 hz_22A[54];
+ /* 0x022A */ u16 hz_296[55];
+ /* 0x0304 */ Vec3f v3f_304;
+ /* 0x0310 */ EnTkEff eff[20];
+ /* 0x0770 */
+};
extern const ActorInit En_Tk_InitVars;