summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/overlays/actors/ovl_En_Jg/z_en_jg.c2
-rw-r--r--src/overlays/actors/ovl_En_S_Goro/z_en_s_goro.c1424
-rw-r--r--src/overlays/actors/ovl_En_S_Goro/z_en_s_goro.h47
3 files changed, 1415 insertions, 58 deletions
diff --git a/src/overlays/actors/ovl_En_Jg/z_en_jg.c b/src/overlays/actors/ovl_En_Jg/z_en_jg.c
index add52b0e4..8dd44f5f3 100644
--- a/src/overlays/actors/ovl_En_Jg/z_en_jg.c
+++ b/src/overlays/actors/ovl_En_Jg/z_en_jg.c
@@ -177,7 +177,7 @@ Actor* EnJg_GetShrineGoronToFocusOn(PlayState* play, u8 focusedShrineGoronParam)
while (actorIterator != NULL) {
if ((actorIterator->id == ACTOR_EN_S_GORO) &&
- (EN_S_GORO_GET_PARAM_F(actorIterator) == focusedShrineGoronParam)) {
+ (EN_S_GORO_GET_MAIN_TYPE(actorIterator) == focusedShrineGoronParam)) {
return actorIterator;
}
diff --git a/src/overlays/actors/ovl_En_S_Goro/z_en_s_goro.c b/src/overlays/actors/ovl_En_S_Goro/z_en_s_goro.c
index 00637ba25..ccc11a002 100644
--- a/src/overlays/actors/ovl_En_S_Goro/z_en_s_goro.c
+++ b/src/overlays/actors/ovl_En_S_Goro/z_en_s_goro.c
@@ -4,18 +4,96 @@
* Description: Goron in Goron Shrine / Bomb Shop Goron
*/
+/*
+This actor appears to be used in three scenes.
+-- Goron Shrine: Winter
+ Three variants (one instance of each used in game).
+ Main behavior determined by whether the Goron Elder's Son is asleep, and whether they themselves have been put to
+sleep. One of them also has a dialogue tree that checks whether you have lit the chandelier (at least if the kid is not
+crying)
+-- Goron Shrine: Spring
+ Six variants - one instance of each appearing in a circle around the elder on the upper level of the shrine if
+you've beaten Goht during that cycle. Dialogue determined by whether you have talked to elder in that context as a goron
+at least once during that cycle. They have a cheering animation used while the elder is talking to you, otherwise they
+stand idle.
+-- Bomb Shop
+ Only one variant. Goron who sells you powder kegs in the bomb shop.
+*/
+
+/*
+Week Event Flags:
+ 22 Bit 2 -- Goron Elder's Son has been pacified (Winter)
+ 77 Bit 7 -- You have spoken to the Goron Elder in goron form during spring
+
+ 36 All Bits
+ 37 Bits 0 - 2
+ Track whether or not you have ever spoken to each of the three winter shrine gorons
+ in various forms. ("Ever" being since last time reset, of course)
+*/
+
#include "z_en_s_goro.h"
+#include "overlays/actors/ovl_En_Gk/z_en_gk.h" // Goron Elder's Son
+#include "overlays/actors/ovl_En_Jg/z_en_jg.h" // Goron Elder
+#include "objects/object_taisou/object_taisou.h"
#define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_8 | ACTOR_FLAG_10)
-
#define THIS ((EnSGoro*)thisx)
+#define EN_S_GORO_ROLLEDUP_YOFFSET 14.0f
+#define EN_S_GORO_OFTYPE_WSHRINE (EN_S_GORO_GET_MAIN_TYPE(&this->actor) < 3)
+
+#define EN_S_GORO_ACTIONFLAG_ROLLEDUP (1 << 0)
+#define EN_S_GORO_ACTIONFLAG_FACEPLAYER (1 << 1)
+#define EN_S_GORO_ACTIONFLAG_EYESOPEN (1 << 2)
+#define EN_S_GORO_ACTIONFLAG_EARSCOVERED (1 << 3)
+#define EN_S_GORO_ACTIONFLAG_ENGAGED (1 << 4)
+#define EN_S_GORO_ACTIONFLAG_LASTMESSAGE (1 << 5)
+#define EN_S_GORO_ACTIONFLAG_GKQUIET_ACKNOWLEDGED (1 << 6)
+#define EN_S_GORO_ACTIONFLAG_SNOREPHASE (1 << 7)
+#define EN_S_GORO_ACTIONFLAG_UNK0100 (1 << 8)
+#define EN_S_GORO_ACTIONFLAG_HANDTAP (1 << 9)
+#define EN_S_GORO_ACTIONFLAG_TIRED (1 << 10)
+#define EN_S_GORO_ACTIONFLAG_SUPPRESS_SNORE (1 << 11)
+
+#define EN_S_GORO_BOMBBUYFLAG_TALKED_HUMAN (1 << 0)
+#define EN_S_GORO_BOMBBUYFLAG_TALKED_GORONPK (1 << 1)
+#define EN_S_GORO_BOMBBUYFLAG_TALKED_DEKU (1 << 2)
+#define EN_S_GORO_BOMBBUYFLAG_TALKED_ZORA (1 << 3)
+#define EN_S_GORO_BOMBBUYFLAG_TALKED_HUMAN_FINALNIGHT (1 << 4)
+#define EN_S_GORO_BOMBBUYFLAG_TALKED_GOROKPK_FINALNIGHT (1 << 5)
+#define EN_S_GORO_BOMBBUYFLAG_TALKED_DEKU_FINALNIGHT (1 << 6)
+#define EN_S_GORO_BOMBBUYFLAG_TALKED_ZORA_FINALNIGHT (1 << 7)
+#define EN_S_GORO_BOMBBUYFLAG_TALKED_GORON (1 << 8)
+#define EN_S_GORO_BOMBBUYFLAG_TALKED_GORON_FINALNIGHT (1 << 9)
+#define EN_S_GORO_BOMBBUYFLAG_YESBUY (1 << 10)
+
void EnSGoro_Init(Actor* thisx, PlayState* play);
void EnSGoro_Destroy(Actor* thisx, PlayState* play);
void EnSGoro_Update(Actor* thisx, PlayState* play);
void EnSGoro_Draw(Actor* thisx, PlayState* play);
-#if 0
+typedef enum EnSGoroEyeTexture {
+ /* 0x0 */ EN_S_GORO_EYETEX_OPEN,
+ /* 0x1 */ EN_S_GORO_EYETEX_HALF,
+ /* 0x2 */ EN_S_GORO_EYETEX_CLOSED,
+ /* 0x3 */ EN_S_GORO_EYETEX_CLOSED2
+} EnSGoroEyeTexture;
+
+typedef enum EnSGoroAnimation {
+ /* 0x0 */ EN_S_GORO_ANIM_IDLE_LIEDOWN_A,
+ /* 0x1 */ EN_S_GORO_ANIM_IDLE_LIEDOWN_B,
+ /* 0x2 */ EN_S_GORO_ANIM_UNROLL_A,
+ /* 0x3 */ EN_S_GORO_ANIM_UNROLL_B,
+ /* 0x4 */ EN_S_GORO_ANIM_ROLLUP,
+ /* 0x5 */ EN_S_GORO_ANIM_SHIVER_A,
+ /* 0x6 */ EN_S_GORO_ANIM_SHIVER_B,
+ /* 0xB */ EN_S_GORO_ANIM_COVEREARS = 11,
+ /* 0xC */ EN_S_GORO_ANIM_TAISOU_CHEER,
+ /* 0xD */ EN_S_GORO_ANIM_STAND_HANDTAP,
+ /* 0xE */ EN_S_GORO_ANIM_SLEEPY,
+ /* 0xF */ EN_S_GORO_ANIM_IDLE_STAND
+} EnSGoroAnimation;
+
const ActorInit En_S_Goro_InitVars = {
ACTOR_EN_S_GORO,
ACTORCAT_NPC,
@@ -28,18 +106,29 @@ const ActorInit En_S_Goro_InitVars = {
(ActorFunc)EnSGoro_Draw,
};
-// static ColliderCylinderInit sCylinderInit = {
-static ColliderCylinderInit D_80BBF820 = {
- { COLTYPE_HIT1, AT_NONE, AC_ON | AC_TYPE_PLAYER, OC1_ON | OC1_TYPE_ALL, OC2_TYPE_1, COLSHAPE_CYLINDER, },
- { ELEMTYPE_UNK1, { 0x00000000, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, },
+static ColliderCylinderInit sCylinderInit = {
+ {
+ COLTYPE_HIT1,
+ AT_NONE,
+ AC_ON | AC_TYPE_PLAYER,
+ OC1_ON | OC1_TYPE_ALL,
+ OC2_TYPE_1,
+ COLSHAPE_CYLINDER,
+ },
+ {
+ ELEMTYPE_UNK1,
+ { 0x00000000, 0x00, 0x00 },
+ { 0xF7CFFFFF, 0x00, 0x00 },
+ TOUCH_ON,
+ BUMP_ON,
+ OCELEM_ON,
+ },
{ 0, 0, 0, { 0, 0, 0 } },
};
-// sColChkInfoInit
-static CollisionCheckInfoInit2 D_80BBF84C = { 0, 0, 0, 0, MASS_IMMOVABLE };
+static CollisionCheckInfoInit2 sColChkInfoInit = { 0, 0, 0, 0, MASS_IMMOVABLE };
-// static DamageTable sDamageTable = {
-static DamageTable D_80BBF858 = {
+static DamageTable sDamageTable = {
/* Deku Nut */ DMG_ENTRY(1, 0x0),
/* Deku Stick */ DMG_ENTRY(1, 0x0),
/* Horse trample */ DMG_ENTRY(1, 0x0),
@@ -74,85 +163,1314 @@ static DamageTable D_80BBF858 = {
/* Powder Keg */ DMG_ENTRY(1, 0x0),
};
-#endif
+static AnimationInfoS sAnimationInfo[] = {
+ { &gGoronLyingDownIdleAnim, 1.0f, 0, -1, ANIMMODE_LOOP, 0 },
+ { &gGoronLyingDownIdleAnim, 1.0f, 0, -1, ANIMMODE_LOOP, -4 },
+ { &gGoronUnrollAnim, 2.0f, 0, -1, ANIMMODE_ONCE, 0 },
+ { &gGoronUnrollAnim, 2.0f, 0, -1, ANIMMODE_ONCE, -4 },
+ { &gGoronUnrollAnim, -2.0f, 0, -1, ANIMMODE_ONCE, -4 },
+ { &gGoronShiverAnim, 1.0f, 0, -1, ANIMMODE_LOOP, 0 },
+ { &gGoronShiverAnim, 1.0f, 0, -1, ANIMMODE_LOOP, -4 },
+ { &object_taisou_Anim_004DD4, 1.0f, 0, -1, ANIMMODE_LOOP, 0 },
+ { &object_taisou_Anim_00283C, 1.0f, 0, -1, ANIMMODE_LOOP, 0 },
+ { &object_taisou_Anim_007764, 1.0f, 0, -1, ANIMMODE_LOOP, 0 },
+ { &object_taisou_Anim_005790, 1.0f, 0, -1, ANIMMODE_LOOP, 0 },
+ { &gGoronCoverEarsAnim, 1.0f, 0, -1, ANIMMODE_LOOP, 0 },
+ { &object_taisou_Anim_002C48, 1.0f, 0, -1, ANIMMODE_LOOP, -4 },
+ { &gGoronStandingHandTappingAnim, 1.0f, 0, -1, ANIMMODE_LOOP, -4 },
+ { &gGoronSleepyAnim, 1.0f, 0, -1, ANIMMODE_ONCE, -4 },
+ { &gGoronStandingIdleAnim, 1.0f, 0, -1, ANIMMODE_LOOP, -8 },
+};
+
+static TexturePtr sEyeTextures[] = {
+ gGoronEyeOpenTex,
+ gGoronEyeHalfTex,
+ gGoronEyeClosedTex,
+ gGoronEyeClosed2Tex,
+};
+
+u16 EnSGoro_ShrineGoron_NextTextId(EnSGoro* this, PlayState* play);
+u16 EnSGoro_BombshopGoron_NextTextId(EnSGoro* this, PlayState* play);
+
+s32 EnSGoro_FindGoronElder(EnSGoro* this, PlayState* play);
+s32 EnSGoro_FindGoronChild(EnSGoro* this, PlayState* play);
+s32 EnSGoro_CheckLullaby(EnSGoro* this, PlayState* play);
+s32 EnSGoro_CheckGKBehavior(EnSGoro* this, PlayState* play);
+
+void EnSGoro_SetupAction(EnSGoro* this, PlayState* play);
+void EnSGoro_WinterShrineGoron_Idle(EnSGoro* this, PlayState* play);
+void EnSGoro_WinterShrineGoron_Talk(EnSGoro* this, PlayState* play);
+void EnSGoro_SpringShrineGoron_Idle(EnSGoro* this, PlayState* play);
+void EnSGoro_SpringShrineGoron_Talk(EnSGoro* this, PlayState* play);
+void EnSGoro_ShopGoron_Idle(EnSGoro* this, PlayState* play);
+void EnSGoro_ShopGoron_FinishUnroll(EnSGoro* this, PlayState* play);
+void EnSGoro_ShopGoron_Talk(EnSGoro* this, PlayState* play);
+void EnSGoro_ShopGoron_TakePayment(EnSGoro* this, PlayState* play);
+void EnSGoro_ShopGoron_FinishTransaction(EnSGoro* this, PlayState* play);
+void EnSGoro_Sleep(EnSGoro* this, PlayState* play);
+void EnSGoro_SleepTalk(EnSGoro* this, PlayState* play);
+
+s32 EnSGoro_UpdateCheerAnimation(EnSGoro* this, PlayState* play);
+s32 EnSGoro_UpdateRotationToPlayer(EnSGoro* this, PlayState* play);
+s32 EnSGoro_UpdateAttentionTarget(EnSGoro* this, PlayState* play);
+void EnSGoro_UpdateToHandtapAnimation(EnSGoro* this);
+void EnSGoro_UpdateSleepyAnimation(EnSGoro* this);
+void EnSGoro_UpdateToIdleAnimation(EnSGoro* this);
+void EnSGoro_UpdateEyes(EnSGoro* this);
+void EnSGoro_UpdateActorFocus(EnSGoro* this);
+void EnSGoro_UpdateSleeping(EnSGoro* this, PlayState* play);
+void EnSGoro_UpdateCollider(EnSGoro* this, PlayState* play);
+
+s32 EnSGoro_UpdateLimb(s16 newRotZ, s16 newRotY, Vec3f* pos, Vec3s* rot, s32 stepRot, s32 overrideRot);
+s32 EnSGoro_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, Actor* thisx);
+void EnSGoro_TransformLimbDraw(PlayState* play, s32 limbIndex, Actor* thisx);
+void EnSGoro_DrawUnrolled(EnSGoro* this, PlayState* play);
+void EnSGoro_DrawRolledUp(EnSGoro* this, PlayState* play);
+
+/**
+ * Dialogue tree for EnSGoro when use in Goron Shrine context. Returns ID of next message to display.
+ */
+u16 EnSGoro_ShrineGoron_NextTextId(EnSGoro* this, PlayState* play) {
+ Player* player = GET_PLAYER(play);
+
+ switch (EN_S_GORO_GET_MAIN_TYPE(&this->actor)) {
+ case EN_S_GORO_TYPE_SHRINE_WINTER_A:
+ if (!(gSaveContext.save.weekEventReg[22] & 4)) {
+ if (player->transformation == PLAYER_FORM_GORON) {
+ if (!(gSaveContext.save.weekEventReg[36] & 2)) {
+ switch (this->textId) {
+ case 0xCFB:
+ return 0xCFC;
+ case 0xCFC:
+ return 0xCFD;
+ case 0xCFD:
+ gSaveContext.save.weekEventReg[36] |= 2;
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0xCFE;
+ default:
+ return 0xCFB;
+ }
+ } else {
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0xCFE;
+ }
+ } else {
+ if (!(gSaveContext.save.weekEventReg[36] & 1)) {
+ gSaveContext.save.weekEventReg[36] |= 1;
+ return 0xCF9;
+ }
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0xCFA;
+ }
+ } else {
+ // Scene flag - Checks whether the chandelier has been lit
+ if (!Flags_GetSwitch(play, EN_S_GORO_SCENEFLAG_INDEX(&this->actor))) {
+ if (player->transformation == PLAYER_FORM_GORON) {
+ if (!(gSaveContext.save.weekEventReg[36] & 8)) {
+ if (this->textId == 0xD02) {
+ gSaveContext.save.weekEventReg[36] |= 8;
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0xD03;
+ }
+ return 0xD02;
+ }
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0xD04;
+ }
+ if (!(gSaveContext.save.weekEventReg[36] & 4)) {
+ if (this->textId == 0xCFF) {
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ gSaveContext.save.weekEventReg[36] |= 4;
+ return 0xD00;
+ }
+ return 0xCFF;
+ }
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0xD01;
+ }
+ if (!(gSaveContext.save.weekEventReg[36] & 0x10)) {
+ if (this->textId == 0xD05) {
+ gSaveContext.save.weekEventReg[36] |= 0x10;
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0xD06;
+ }
+ return 0xD05;
+ }
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0xD07;
+ }
+ break;
+
+ case EN_S_GORO_TYPE_SHRINE_WINTER_B:
+ if (!(gSaveContext.save.weekEventReg[22] & 4)) {
+ if (player->transformation == PLAYER_FORM_GORON) {
+ if (!(gSaveContext.save.weekEventReg[36] & 0x40)) {
+ switch (this->textId) {
+ case 0xD15:
+ return 0xD16;
+ case 0xD16:
+ gSaveContext.save.weekEventReg[36] |= 0x40;
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0xD17;
+ default:
+ return 0xD15;
+ }
+ } else {
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0xD17;
+ }
+ } else {
+ if (!(gSaveContext.save.weekEventReg[36] & 0x20)) {
+ gSaveContext.save.weekEventReg[36] |= 0x20;
+ return 0xD13;
+ }
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0xD14;
+ }
+ } else if (player->transformation == PLAYER_FORM_GORON) {
+ if (!(gSaveContext.save.weekEventReg[37] & 1)) {
+ switch (this->textId) {
+ case 0xD1E:
+ return 0xD1F;
+ case 0xD1F:
+ gSaveContext.save.weekEventReg[37] |= 1;
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0xD20;
+ default:
+ return 0xD1E;
+ }
+ } else {
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0xD21;
+ }
+ } else {
+ if (!(gSaveContext.save.weekEventReg[36] & 0x80)) {
+ switch (this->textId) {
+ case 0xD18:
+ return 0xD19;
+ case 0xD19:
+ return 0xD1A;
+ case 0xD1A:
+ return 0xD1B;
+ case 0xD1B:
+ gSaveContext.save.weekEventReg[36] |= 0x80;
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0xD1C;
+ default:
+ return 0xD18;
+ }
+ } else {
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0xD1D;
+ }
+ }
+ break;
+
+ case EN_S_GORO_TYPE_SHRINE_WINTER_C:
+ if (!(gSaveContext.save.weekEventReg[22] & 4)) {
+ if (player->transformation == PLAYER_FORM_GORON) {
+ if (!(gSaveContext.save.weekEventReg[37] & 2)) {
+ switch (this->textId) {
+ case 0xD09:
+ return 0xD0A;
+ case 0xD0A:
+ return 0xD0B;
+ case 0xD0B:
+ gSaveContext.save.weekEventReg[37] |= 2;
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0xD0C;
+ default:
+ return 0xD09;
+ }
+ } else {
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0xD0D;
+ }
+ } else {
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0xD08;
+ }
+ } else if (player->transformation == PLAYER_FORM_GORON) {
+ if (!(gSaveContext.save.weekEventReg[37] & 4)) {
+ switch (this->textId) {
+ case 0xD0E:
+ return 0xD0F;
+ case 0xD0F:
+ gSaveContext.save.weekEventReg[37] |= 4;
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0xD10;
+ default:
+ return 0xD0E;
+ }
+ } else {
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0xD11;
+ }
+ } else {
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0xD12;
+ }
+ break;
+
+ case EN_S_GORO_TYPE_SHRINE_SPRING_A:
+ if (player->transformation == PLAYER_FORM_GORON) {
+ if (gSaveContext.save.weekEventReg[77] & 0x80) {
+ if (this->textId == 0xDE3) {
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0xDE4;
+ }
+ return 0xDE3;
+ }
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0xDE2;
+ }
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0xDE1;
+
+ case EN_S_GORO_TYPE_SHRINE_SPRING_B:
+ if (player->transformation == PLAYER_FORM_GORON) {
+ if (gSaveContext.save.weekEventReg[77] & 0x80) {
+ if (this->textId == 0xDE7) {
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0xDE8;
+ }
+ return 0xDE7;
+ }
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0xDE6;
+ }
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0xDE5;
+
+ case EN_S_GORO_TYPE_SHRINE_SPRING_C:
+ if (player->transformation == PLAYER_FORM_GORON) {
+ if (gSaveContext.save.weekEventReg[77] & 0x80) {
+ if (this->textId == 0xDEB) {
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0xDEC;
+ }
+ return 0xDEB;
+ }
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0xDEA;
+ }
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0xDE9;
+
+ case EN_S_GORO_TYPE_SHRINE_SPRING_D:
+ if (player->transformation == PLAYER_FORM_GORON) {
+ if (gSaveContext.save.weekEventReg[77] & 0x80) {
+ if (this->textId == 0xDF1) {
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0xDF2;
+ }
+ return 0xDF1;
+ }
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0xDF0;
+ }
+ switch (this->textId) {
+ case 0xDED:
+ return 0xDEE;
+ case 0xDEE:
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0xDEF;
+ default:
+ return 0xDED;
+ }
+ break;
+
+ case EN_S_GORO_TYPE_SHRINE_SPRING_E:
+ if (player->transformation == PLAYER_FORM_GORON) {
+ if (gSaveContext.save.weekEventReg[77] & 0x80) {
+ if (this->textId == 0xDF6) {
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0xDF7;
+ }
+ return 0xDF6;
+ }
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0xDF5;
+ }
+ if (this->textId == 0xDF3) {
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0xDF4;
+ }
+ return 0xDF3;
+
+ case EN_S_GORO_TYPE_SHRINE_SPRING_F:
+ if (player->transformation == PLAYER_FORM_GORON) {
+ if (gSaveContext.save.weekEventReg[77] & 0x80) {
+ switch (this->textId) {
+ case 0xDFB:
+ return 0xDFC;
+ case 0xDFC:
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0xDFD;
+ default:
+ return 0xDFB;
+ }
+ } else {
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0xDFA;
+ }
+ } else {
+ if (this->textId == 0xDF8) {
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0xDF9;
+ }
+ return 0xDF8;
+ }
+ break;
+
+ default:
+ return 0;
+ }
+}
+
+/**
+ * Dialogue tree for bomb shop goron. Returns ID of next message to display.
+ */
+u16 EnSGoro_BombshopGoron_NextTextId(EnSGoro* this, PlayState* play) {
+ Player* player = GET_PLAYER(play);
+
+ switch (this->textId) {
+ case 0x0:
+ switch (player->transformation) {
+ case PLAYER_FORM_GORON:
+ // Check if Powder Keg is in Powder Key slot.
+ if (INV_CONTENT(ITEM_POWDER_KEG) == ITEM_POWDER_KEG) {
+ if ((gSaveContext.save.day == 3) && gSaveContext.save.isNight) {
+ if (!(this->bombbuyFlags & EN_S_GORO_BOMBBUYFLAG_TALKED_GOROKPK_FINALNIGHT)) {
+ this->bombbuyFlags |= EN_S_GORO_BOMBBUYFLAG_TALKED_GOROKPK_FINALNIGHT;
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_HANDTAP;
+ return 0x677;
+ }
+ return 0x67A;
+ }
+ if (!(this->bombbuyFlags & EN_S_GORO_BOMBBUYFLAG_TALKED_GORONPK)) {
+ this->bombbuyFlags |= EN_S_GORO_BOMBBUYFLAG_TALKED_GORONPK;
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_HANDTAP;
+ return 0x66E;
+ }
+ return 0x679;
+ }
+
+ // No powder keg
+ if ((gSaveContext.save.day == 3) && gSaveContext.save.isNight) {
+ if (!(this->bombbuyFlags & EN_S_GORO_BOMBBUYFLAG_TALKED_GORON_FINALNIGHT)) {
+ this->bombbuyFlags |= EN_S_GORO_BOMBBUYFLAG_TALKED_GORON_FINALNIGHT;
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_HANDTAP;
+ return 0x67E;
+ }
+ return 0x683;
+ }
+ if (!(this->bombbuyFlags & EN_S_GORO_BOMBBUYFLAG_TALKED_GORON)) {
+ this->bombbuyFlags |= EN_S_GORO_BOMBBUYFLAG_TALKED_GORON;
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_HANDTAP;
+ return 0x67B;
+ }
+ return 0x681;
+
+ case PLAYER_FORM_ZORA:
+ if ((gSaveContext.save.day == 3) && gSaveContext.save.isNight) {
+ if (!(this->bombbuyFlags & EN_S_GORO_BOMBBUYFLAG_TALKED_ZORA_FINALNIGHT)) {
+ this->bombbuyFlags |= EN_S_GORO_BOMBBUYFLAG_TALKED_ZORA_FINALNIGHT;
+ return 0x668;
+ }
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_TIRED;
+ return 0x66D;
+ }
+ if (!(this->bombbuyFlags & EN_S_GORO_BOMBBUYFLAG_TALKED_ZORA)) {
+ this->bombbuyFlags |= EN_S_GORO_BOMBBUYFLAG_TALKED_ZORA;
+ return 0x664;
+ }
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_TIRED;
+ return 0x66C;
+
+ case PLAYER_FORM_DEKU:
+ if ((gSaveContext.save.day == 3) && gSaveContext.save.isNight) {
+ if (!(this->bombbuyFlags & EN_S_GORO_BOMBBUYFLAG_TALKED_DEKU_FINALNIGHT)) {
+ this->bombbuyFlags |= EN_S_GORO_BOMBBUYFLAG_TALKED_DEKU_FINALNIGHT;
+ return 0x668;
+ }
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0x66D;
+ }
+ if (!(this->bombbuyFlags & EN_S_GORO_BOMBBUYFLAG_TALKED_DEKU)) {
+ this->bombbuyFlags |= EN_S_GORO_BOMBBUYFLAG_TALKED_DEKU;
+ return 0x664;
+ }
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0x66C;
+
+ case PLAYER_FORM_HUMAN:
+ if ((gSaveContext.save.day == 3) && gSaveContext.save.isNight) {
+ if (!(this->bombbuyFlags & EN_S_GORO_BOMBBUYFLAG_TALKED_HUMAN_FINALNIGHT)) {
+ this->bombbuyFlags |= EN_S_GORO_BOMBBUYFLAG_TALKED_HUMAN_FINALNIGHT;
+ return 0x668;
+ }
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0x66D;
+ }
+ if (!(this->bombbuyFlags & EN_S_GORO_BOMBBUYFLAG_TALKED_HUMAN)) {
+ this->bombbuyFlags |= EN_S_GORO_BOMBBUYFLAG_TALKED_HUMAN;
+ return 0x664;
+ }
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0x66C;
+ }
+
+ case 0x664:
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_HANDTAP;
+ return 0x665;
+
+ case 0x665:
+ this->actionFlags &= ~EN_S_GORO_ACTIONFLAG_HANDTAP;
+ return 0x666;
+
+ case 0x666:
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_TIRED;
+ return 0x667;
+
+ case 0x668:
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_HANDTAP;
+ return 0x669;
+
+ case 0x669:
+ this->actionFlags &= ~EN_S_GORO_ACTIONFLAG_HANDTAP;
+ return 0x66A;
+
+ case 0x66A:
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_TIRED;
+ return 0x66B;
+
+ case 0x677:
+ this->actionFlags &= ~EN_S_GORO_ACTIONFLAG_HANDTAP;
+ return 0x678;
+
+ case 0x678:
+ return 0x670;
+
+ case 0x66E:
+ this->actionFlags &= ~EN_S_GORO_ACTIONFLAG_HANDTAP;
+ return 0x66F;
+
+ case 0x66F:
+ return 0x670;
+
+ case 0x679:
+ return 0x670;
+
+ case 0x67A:
+ return 0x670;
+
+ case 0x67E:
+ this->actionFlags &= ~EN_S_GORO_ACTIONFLAG_HANDTAP;
+ return 0x67F;
+
+ case 0x67F:
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0x680;
+
+ case 0x67B:
+ this->actionFlags &= ~EN_S_GORO_ACTIONFLAG_HANDTAP;
+ return 0x67C;
+
+ case 0x67C:
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0x67D;
+
+ case 0x681:
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0x682;
+
+ case 0x683:
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0x684;
-extern ColliderCylinderInit D_80BBF820;
-extern CollisionCheckInfoInit2 D_80BBF84C;
-extern DamageTable D_80BBF858;
+ case 0x670:
+ if (this->bombbuyFlags & EN_S_GORO_BOMBBUYFLAG_YESBUY) {
+ if (AMMO(ITEM_POWDER_KEG) != 0) {
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ play_sound(NA_SE_SY_ERROR);
+ return 0x673;
+ }
+ this->powderKegPrice = play->msgCtx.unk1206C;
+ if (gSaveContext.save.playerData.rupees < this->powderKegPrice) {
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_TIRED;
+ play_sound(NA_SE_SY_ERROR);
+ return 0x674;
+ }
+ if ((gSaveContext.save.day == 3) && gSaveContext.save.isNight) {
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ func_8019F208();
+ return 0x676;
+ }
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ func_8019F208();
+ return 0x675;
+ }
+ if ((gSaveContext.save.day == 3) && gSaveContext.save.isNight) {
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0x672;
+ }
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ return 0x671;
+ }
+ return 0;
+}
-extern UNK_TYPE D_060091A8;
-extern UNK_TYPE D_06012DE0;
+/**
+ * Links to actor of type EN_JG (Goron Elder), returns whether operation successful.
+ */
+s32 EnSGoro_FindGoronElder(EnSGoro* this, PlayState* play) {
+ this->otherGoron = SubS_FindActor(play, this->otherGoron, ACTORCAT_NPC, ACTOR_EN_JG);
+ if (this->otherGoron != NULL) {
+ return true;
+ }
+ return false;
+}
+
+/**
+ * Links to actor of type EN_GK (Goron Elder's Son), returns whether operation successful.
+ */
+s32 EnSGoro_FindGoronChild(EnSGoro* this, PlayState* play) {
+ this->otherGoron = NULL;
+ this->otherGoron = SubS_FindActor(play, this->otherGoron, ACTORCAT_NPC, ACTOR_EN_GK);
+ if (this->otherGoron != NULL) {
+ return true;
+ }
+ return false;
+}
+
+/**
+ * Looks like it manages the snoring cycle for when rolled up and asleep.
+ */
+void EnSGoro_UpdateSleeping(EnSGoro* this, PlayState* play) {
+ s16 curFrame = this->skelAnime.curFrame;
+
+ this->snorePhase += 0x400;
+ this->scaleFactor = Math_SinS(this->snorePhase) * 0.01f * 0.1f;
+ this->actor.scale.y = 0.01f - this->scaleFactor;
+ this->actor.scale.z = 0.01f - this->scaleFactor;
+ this->actor.scale.x = 0.01f + this->scaleFactor;
+
+ if (!(this->actionFlags & EN_S_GORO_ACTIONFLAG_SUPPRESS_SNORE)) {
+ if (this->snorePhase == 0) {
+ if (this->actionFlags & EN_S_GORO_ACTIONFLAG_SNOREPHASE) {
+ this->actionFlags &= ~EN_S_GORO_ACTIONFLAG_SNOREPHASE;
+ Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_GOLON_SNORE2);
+ } else {
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_SNOREPHASE;
+ Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_GOLON_SNORE1);
+ }
+ }
+ } else if (gSaveContext.save.weekEventReg[22] & 4) {
+ this->actionFlags &= ~EN_S_GORO_ACTIONFLAG_SUPPRESS_SNORE;
+ }
+
+ if (!(this->actionFlags & EN_S_GORO_ACTIONFLAG_ROLLEDUP) && (curFrame == 0)) {
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_ROLLEDUP;
+ this->actor.shape.yOffset = EN_S_GORO_ROLLEDUP_YOFFSET;
+ }
+
+ this->actor.shape.yOffset = (this->actor.scale.y / 0.01f) * EN_S_GORO_ROLLEDUP_YOFFSET;
+}
+
+s32 EnSGoro_UpdateCheerAnimation(EnSGoro* this, PlayState* play) {
+ if (this->animInfoIndex == EN_S_GORO_ANIM_IDLE_STAND) {
+ if (((EnJg*)this->otherGoron)->flags & 1) {
+ this->loadedObjIndex = Object_GetIndex(&play->objectCtx, OBJECT_TAISOU);
+ if (this->loadedObjIndex >= 0) {
+ gSegments[6] = PHYSICAL_TO_VIRTUAL(play->objectCtx.status[this->loadedObjIndex].segment);
+ this->animInfoIndex = EN_S_GORO_ANIM_TAISOU_CHEER;
+ SubS_ChangeAnimationByInfoS(&this->skelAnime, sAnimationInfo, this->animInfoIndex);
+ return true;
+ }
+ }
+ } else if ((this->animInfoIndex == EN_S_GORO_ANIM_TAISOU_CHEER) && !(((EnJg*)this->otherGoron)->flags & 1)) {
+ this->loadedObjIndex = Object_GetIndex(&play->objectCtx, OBJECT_OF1D_MAP);
+ if (this->loadedObjIndex >= 0) {
+ gSegments[6] = PHYSICAL_TO_VIRTUAL(play->objectCtx.status[this->loadedObjIndex].segment);
+ this->animInfoIndex = EN_S_GORO_ANIM_IDLE_STAND;
+ SubS_ChangeAnimationByInfoS(&this->skelAnime, sAnimationInfo, this->animInfoIndex);
+ this->skelAnime.curFrame = this->skelAnime.endFrame;
+ return true;
+ }
+ }
+ return false;
+}
+
+s32 EnSGoro_CheckLullaby(EnSGoro* this, PlayState* play) {
+ s32 actorType;
+ Player* player = GET_PLAYER(play);
+
+ if ((player->transformation == PLAYER_FORM_GORON) && (play->msgCtx.ocarinaMode == 3)) {
+ if (play->msgCtx.lastPlayedSong == OCARINA_SONG_GORON_LULLABY) {
+ this->animInfoIndex = EN_S_GORO_ANIM_ROLLUP;
+ SubS_ChangeAnimationByInfoS(&this->skelAnime, sAnimationInfo, this->animInfoIndex);
+
+ actorType = EN_S_GORO_GET_MAIN_TYPE(&this->actor);
+ this->snorePhase = 0x400 << (actorType + 1);
+
+ /*
+ * Should be:
+ * if ((actorType % 2) == 0)
+ * However, the original code checks the negative case whereas the above does not.
+ * So unfortunately, this is the only way to get it to match.
+ */
+ if (!(actorType % 2)) {
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_SNOREPHASE;
+ }
+ this->actionFunc = EnSGoro_Sleep;
+ return true;
+ }
+ }
+ return false;
+}
+
+s32 EnSGoro_CheckGKBehavior(EnSGoro* this, PlayState* play) {
+ s32 actorType;
+
+ if (!EnSGoro_FindGoronChild(this, play)) {
+ return false;
+ }
+ if ((!(this->actionFlags & EN_S_GORO_ACTIONFLAG_GKQUIET_ACKNOWLEDGED)) &&
+ ((((EnGk*)this->otherGoron)->unk_1E4 & 0x80) || (gSaveContext.save.weekEventReg[22] & 4))) {
+
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_GKQUIET_ACKNOWLEDGED;
+ this->animInfoIndex = EN_S_GORO_ANIM_ROLLUP;
+ SubS_ChangeAnimationByInfoS(&this->skelAnime, sAnimationInfo, this->animInfoIndex);
+
+ actorType = EN_S_GORO_GET_MAIN_TYPE(&this->actor);
+ this->snorePhase = 0x400 << (actorType + 1);
+
+ /*
+ * Should be:
+ * if ((actorType % 2) == 0)
+ * However, the original code checks the negative case whereas the above does not.
+ * So unfortunately, this is the only way to get it to match.
+ */
+ if (!(actorType % 2)) {
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_SNOREPHASE;
+ }
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_SUPPRESS_SNORE;
+ this->actionFunc = EnSGoro_Sleep;
+ return true;
+ }
+ return false;
+}
+
+void EnSGoro_UpdateToHandtapAnimation(EnSGoro* this) {
+ s16 curFrame = this->skelAnime.curFrame;
+ s16 lastFrame = Animation_GetLastFrame(sAnimationInfo[this->animInfoIndex].animation);
+
+ if ((this->animInfoIndex != EN_S_GORO_ANIM_STAND_HANDTAP) && (curFrame == lastFrame)) {
+ this->animInfoIndex = EN_S_GORO_ANIM_STAND_HANDTAP;
+ SubS_ChangeAnimationByInfoS(&this->skelAnime, sAnimationInfo, this->animInfoIndex);
+ }
+}
+
+void EnSGoro_UpdateSleepyAnimation(EnSGoro* this) {
+ s16 curFrame = this->skelAnime.curFrame;
+ s16 lastFrame = Animation_GetLastFrame(sAnimationInfo[this->animInfoIndex].animation);
+
+ if (this->animInfoIndex != EN_S_GORO_ANIM_SLEEPY) {
+ if (curFrame == lastFrame) {
+ this->animInfoIndex = EN_S_GORO_ANIM_SLEEPY;
+ SubS_ChangeAnimationByInfoS(&this->skelAnime, sAnimationInfo, this->animInfoIndex);
+ }
+ } else if (curFrame == lastFrame) {
+ this->actionFlags &= ~EN_S_GORO_ACTIONFLAG_TIRED;
+ this->animInfoIndex = EN_S_GORO_ANIM_IDLE_STAND;
+ SubS_ChangeAnimationByInfoS(&this->skelAnime, sAnimationInfo, this->animInfoIndex);
+ }
+}
+
+void EnSGoro_UpdateToIdleAnimation(EnSGoro* this) {
+ s16 curFrame = this->skelAnime.curFrame;
+ s16 lastFrame = Animation_GetLastFrame(sAnimationInfo[this->animInfoIndex].animation);
+
+ if ((this->animInfoIndex != EN_S_GORO_ANIM_IDLE_STAND) && (curFrame == lastFrame)) {
+ this->animInfoIndex = EN_S_GORO_ANIM_IDLE_STAND;
+ SubS_ChangeAnimationByInfoS(&this->skelAnime, sAnimationInfo, this->animInfoIndex);
+ }
+}
+
+void EnSGoro_UpdateCollider(EnSGoro* this, PlayState* play) {
+ Vec3f world_pos = this->actor.world.pos;
+ f32 radius = 24.0f;
+ f32 height = 62.0f;
+
+ this->collider.dim.pos.x = world_pos.x;
+ this->collider.dim.pos.y = world_pos.y;
+ this->collider.dim.pos.z = world_pos.z;
+ this->collider.dim.radius = radius;
+ this->collider.dim.height = height;
+
+ //! @bug: It is not clear what this is for.
+ if ((s32)this != -0x190) {
+ CollisionCheck_SetOC(play, &play->colChkCtx, &this->collider.base);
+ }
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_S_Goro/func_80BBCA80.s")
+void EnSGoro_UpdateEyes(EnSGoro* this) {
+ if (this->actionFlags & EN_S_GORO_ACTIONFLAG_EYESOPEN) {
+ if (DECR(this->eyeTimer) == 0) {
+ this->eyeTexIndex++;
+ if (this->eyeTexIndex > EN_S_GORO_EYETEX_CLOSED) {
+ this->eyeTimer = Rand_S16Offset(30, 30);
+ this->eyeTexIndex = EN_S_GORO_EYETEX_OPEN;
+ }
+ }
+ }
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_S_Goro/func_80BBD348.s")
+void EnSGoro_UpdateActorFocus(EnSGoro* this) {
+ f32 yDelta;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_S_Goro/func_80BBD8F0.s")
+ if (this->actionFlags & EN_S_GORO_ACTIONFLAG_ROLLEDUP) {
+ yDelta = this->actor.shape.yOffset;
+ } else {
+ yDelta = 58.0f;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_S_Goro/func_80BBD93C.s")
+ this->actor.focus.pos.x = this->actor.world.pos.x;
+ this->actor.focus.pos.y = this->actor.world.pos.y + yDelta;
+ this->actor.focus.pos.z = this->actor.world.pos.z;
+ this->actor.focus.rot.x = this->actor.world.rot.x;
+ this->actor.focus.rot.y = this->actor.world.rot.y;
+ this->actor.focus.rot.z = this->actor.world.rot.z;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_S_Goro/func_80BBD98C.s")
+s32 EnSGoro_UpdateRotationToPlayer(EnSGoro* this, PlayState* play) {
+ Player* player = GET_PLAYER(play);
+ Vec3f playerPos;
+ Vec3f thisPos;
+ s16 target = (this->actor.yawTowardsPlayer - this->bodyRotY) - this->actor.shape.rot.y;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_S_Goro/func_80BBDACC.s")
+ Math_SmoothStepToS(&this->headRotY, target, 4, 0x2AA8, 1);
+ this->headRotY = CLAMP(this->headRotY, -0x1FFE, 0x1FFE);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_S_Goro/func_80BBDC34.s")
+ target = (this->actor.yawTowardsPlayer - this->headRotY) - this->actor.shape.rot.y;
+ Math_SmoothStepToS(&this->bodyRotY, target, 4, 0x2AA8, 1);
+ this->bodyRotY = CLAMP(this->bodyRotY, -0x1C70, 0x1C70);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_S_Goro/func_80BBDCFC.s")
+ playerPos = player->actor.world.pos;
+ playerPos.y = player->bodyPartsPos[7].y + 3.0f;
+ thisPos = this->actor.world.pos;
+ thisPos.y += 70.0f;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_S_Goro/func_80BBDDF8.s")
+ target = Math_Vec3f_Pitch(&thisPos, &playerPos) - this->bodyRotZ;
+ Math_SmoothStepToS(&this->headRotZ, target, 4, 0x2AA8, 1);
+ this->headRotZ = CLAMP(this->headRotZ, -0x1C70, 0x1C70);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_S_Goro/func_80BBDE78.s")
+ target = Math_Vec3f_Pitch(&thisPos, &playerPos) - this->headRotZ;
+ Math_SmoothStepToS(&this->bodyRotZ, target, 4, 0x2AA8, 1);
+ this->bodyRotZ = CLAMP(this->bodyRotZ, -0x1C70, 0x1C70);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_S_Goro/func_80BBDF28.s")
+ return true;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_S_Goro/func_80BBDFA8.s")
+s32 EnSGoro_UpdateAttentionTarget(EnSGoro* this, PlayState* play) {
+ if (DECR(this->loseAttentionTimer) != 0) {
+ // EnSGoro is in the process of returning to idle position from previously looking at the player.
+ if ((this->actionFlags & EN_S_GORO_ACTIONFLAG_EARSCOVERED) &&
+ (this->actionFlags & EN_S_GORO_ACTIONFLAG_EYESOPEN)) {
+ // If ears are covered, but eyes are open, close eyes.
+ this->actionFlags &= ~EN_S_GORO_ACTIONFLAG_EYESOPEN;
+ this->eyeTexIndex = EN_S_GORO_EYETEX_CLOSED2;
+ }
+ // Reset position to idle. EnSGoro cannot return attention to player until the timer is up.
+ this->actionFlags &= ~EN_S_GORO_ACTIONFLAG_FACEPLAYER;
+ this->headRotZ = 0;
+ this->headRotY = 0;
+ this->bodyRotZ = 0;
+ this->bodyRotY = 0;
+ return true;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_S_Goro/func_80BBE05C.s")
+ // Turn to face player if either player has engaged EnSGoro or if player is in range and EnSGoro isn't covering his
+ // ears.
+ if (this->actionFlags & EN_S_GORO_ACTIONFLAG_ENGAGED) {
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_FACEPLAYER;
+ EnSGoro_UpdateRotationToPlayer(this, play);
+ } else if (!(this->actionFlags & EN_S_GORO_ACTIONFLAG_EARSCOVERED) &&
+ Actor_IsFacingAndNearPlayer(&this->actor, 120.0f, 0x3FFC)) {
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_FACEPLAYER;
+ EnSGoro_UpdateRotationToPlayer(this, play);
+ } else {
+ // Unengaged or player out of range.
+ if (this->actionFlags & EN_S_GORO_ACTIONFLAG_FACEPLAYER) {
+ // Previously facing player, but now player out of range.
+ // Start counter for frames/function calls to ignore player while in process of returning to idle.
+ this->loseAttentionTimer = 20;
+ }
+ // Start animation to return to idle position.
+ this->actionFlags &= ~EN_S_GORO_ACTIONFLAG_FACEPLAYER;
+ this->headRotZ = 0;
+ this->headRotY = 0;
+ this->bodyRotZ = 0;
+ this->bodyRotY = 0;
+ }
+ return true;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_S_Goro/func_80BBE0E4.s")
+void EnSGoro_SetupAction(EnSGoro* this, PlayState* play) {
+ if (Object_IsLoaded(&play->objectCtx, this->loadedObjIndex)) {
+ this->actionFlags = 0;
+ if (EN_S_GORO_OFTYPE_WSHRINE) {
+ if (gSaveContext.save.weekEventReg[22] & 4) {
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_GKQUIET_ACKNOWLEDGED;
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_EYESOPEN;
+ this->animInfoIndex = EN_S_GORO_ANIM_SHIVER_A;
+ SubS_ChangeAnimationByInfoS(&this->skelAnime, sAnimationInfo, this->animInfoIndex);
+ } else {
+ this->eyeTexIndex = EN_S_GORO_EYETEX_CLOSED2;
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_EARSCOVERED;
+ this->animInfoIndex = EN_S_GORO_ANIM_COVEREARS;
+ SubS_ChangeAnimationByInfoS(&this->skelAnime, sAnimationInfo, this->animInfoIndex);
+ }
+ } else {
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_EYESOPEN;
+ this->animInfoIndex = EN_S_GORO_ANIM_IDLE_STAND;
+ SubS_ChangeAnimationByInfoS(&this->skelAnime, sAnimationInfo, this->animInfoIndex);
+ }
+
+ this->scaleFactor = 0.01f;
+ Actor_SetScale(&this->actor, 0.01f);
+ this->actor.gravity = -1.0f;
+ this->actor.flags |= ACTOR_FLAG_10;
+ this->actor.flags |= ACTOR_FLAG_2000000;
+ this->actor.targetMode = 1;
+
+ switch (EN_S_GORO_GET_MAIN_TYPE(&this->actor)) {
+ case EN_S_GORO_TYPE_SHRINE_WINTER_A:
+ this->actionFunc = EnSGoro_WinterShrineGoron_Idle;
+ break;
+ case EN_S_GORO_TYPE_SHRINE_WINTER_B:
+ this->actionFunc = EnSGoro_WinterShrineGoron_Idle;
+ break;
+ case EN_S_GORO_TYPE_SHRINE_WINTER_C:
+ this->actionFunc = EnSGoro_WinterShrineGoron_Idle;
+ break;
+ case EN_S_GORO_TYPE_SHRINE_SPRING_A:
+ if (EnSGoro_FindGoronElder(this, play)) {
+ this->actionFunc = EnSGoro_SpringShrineGoron_Idle;
+ }
+ break;
+ case EN_S_GORO_TYPE_SHRINE_SPRING_B:
+ if (EnSGoro_FindGoronElder(this, play)) {
+ this->actionFunc = EnSGoro_SpringShrineGoron_Idle;
+ }
+ break;
+ case EN_S_GORO_TYPE_SHRINE_SPRING_C:
+ if (EnSGoro_FindGoronElder(this, play)) {
+ this->actionFunc = EnSGoro_SpringShrineGoron_Idle;
+ }
+ break;
+ case EN_S_GORO_TYPE_SHRINE_SPRING_D:
+ if (EnSGoro_FindGoronElder(this, play)) {
+ this->actionFunc = EnSGoro_SpringShrineGoron_Idle;
+ }
+ break;
+ case EN_S_GORO_TYPE_SHRINE_SPRING_E:
+ if (EnSGoro_FindGoronElder(this, play)) {
+ this->actionFunc = EnSGoro_SpringShrineGoron_Idle;
+ }
+ break;
+ case EN_S_GORO_TYPE_SHRINE_SPRING_F:
+ if (EnSGoro_FindGoronElder(this, play)) {
+ this->actionFunc = EnSGoro_SpringShrineGoron_Idle;
+ }
+ break;
+ case EN_S_GORO_TYPE_BOMBSHOP:
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_ROLLEDUP;
+ this->actionFunc = EnSGoro_ShopGoron_Idle;
+ this->actor.shape.yOffset = EN_S_GORO_ROLLEDUP_YOFFSET;
+ break;
+ default:
+ Actor_MarkForDeath(&this->actor);
+ break;
+ }
+ }
+}
+
+void EnSGoro_WinterShrineGoron_Idle(EnSGoro* this, PlayState* play) {
+ if (!EnSGoro_CheckLullaby(this, play) && !EnSGoro_CheckGKBehavior(this, play)) {
+ if (Actor_ProcessTalkRequest(&this->actor, &play->state)) {
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_ENGAGED;
+ if (this->actionFlags & EN_S_GORO_ACTIONFLAG_EARSCOVERED) {
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_EYESOPEN;
+ this->eyeTexIndex = EN_S_GORO_EYETEX_OPEN;
+ }
+ this->textId = EnSGoro_ShrineGoron_NextTextId(this, play);
+ Message_StartTextbox(play, this->textId, &this->actor);
+ this->actionFunc = EnSGoro_WinterShrineGoron_Talk;
+ } else if ((this->actor.xzDistToPlayer < 250.0f) || this->actor.isTargeted) {
+ func_800B863C(&this->actor, play);
+ }
+ Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.home.rot.y, 5, 0x1000, 0x100);
+ this->actor.world.rot.y = this->actor.shape.rot.y;
+ }
+}
+
+void EnSGoro_WinterShrineGoron_Talk(EnSGoro* this, PlayState* play) {
+ if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && (Message_ShouldAdvance(play))) {
+ if (this->actionFlags & EN_S_GORO_ACTIONFLAG_LASTMESSAGE) {
+ this->actionFlags &= ~EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ this->actionFlags &= ~EN_S_GORO_ACTIONFLAG_ENGAGED;
+ this->actionFunc = EnSGoro_WinterShrineGoron_Idle;
+ return;
+ }
+ this->textId = EnSGoro_ShrineGoron_NextTextId(this, play);
+ Message_StartTextbox(play, this->textId, &this->actor);
+ }
+ Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 5, 0x1000, 0x100);
+ this->actor.world.rot.y = this->actor.shape.rot.y;
+}
+
+void EnSGoro_SpringShrineGoron_Idle(EnSGoro* this, PlayState* play) {
+ if ((EN_S_GORO_GET_MAIN_TYPE(&this->actor) == EN_S_GORO_TYPE_SHRINE_SPRING_F) ||
+ !EnSGoro_UpdateCheerAnimation(this, play)) {
+ if (Actor_ProcessTalkRequest(&this->actor, &play->state)) {
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_ENGAGED;
+ this->textId = EnSGoro_ShrineGoron_NextTextId(this, play);
+ Message_StartTextbox(play, this->textId, &this->actor);
+ this->actionFunc = EnSGoro_SpringShrineGoron_Talk;
+ } else if ((this->actor.xzDistToPlayer < 250.0f) || (this->actor.isTargeted)) {
+ func_800B863C(&this->actor, play);
+ }
+ Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.home.rot.y, 5, 0x1000, 0x100);
+ this->actor.world.rot.y = this->actor.shape.rot.y;
+ }
+}
+
+void EnSGoro_SpringShrineGoron_Talk(EnSGoro* this, PlayState* play) {
+ if ((Message_GetState(&play->msgCtx) == TEXT_STATE_5) && Message_ShouldAdvance(play)) {
+ if (this->actionFlags & EN_S_GORO_ACTIONFLAG_LASTMESSAGE) {
+ this->actionFlags &= ~EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ this->actionFlags &= ~EN_S_GORO_ACTIONFLAG_ENGAGED;
+ play->msgCtx.msgMode = 0x43;
+ play->msgCtx.stateTimer = 4;
+ this->actionFunc = EnSGoro_SpringShrineGoron_Idle;
+ return;
+ }
+ this->textId = EnSGoro_ShrineGoron_NextTextId(this, play);
+ Message_StartTextbox(play, this->textId, &this->actor);
+ }
+ Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 5, 0x1000, 0x100);
+ this->actor.world.rot.y = this->actor.shape.rot.y;
+}
+
+void EnSGoro_ShopGoron_Idle(EnSGoro* this, PlayState* play) {
+ if (!(this->actionFlags & EN_S_GORO_ACTIONFLAG_ROLLEDUP)) {
+ EnSGoro_UpdateToIdleAnimation(this);
+ }
+ if (Actor_ProcessTalkRequest(&this->actor, &play->state)) {
+ this->actionFlags |= EN_S_GORO_ACTIONFLAG_ENGAGED;
+ this->textId = EnSGoro_BombshopGoron_NextTextId(this, play);
+ if (this->actionFlags & EN_S_GORO_ACTIONFLAG_ROLLEDUP) {
+ this->actionFlags &= ~EN_S_GORO_ACTIONFLAG_ROLLEDUP;
+ this->animInfoIndex = EN_S_GORO_ANIM_UNROLL_A;
+ SubS_ChangeAnimationByInfoS(&this->skelAnime, sAnimationInfo, this->animInfoIndex);
+ this->actionFunc = EnSGoro_ShopGoron_FinishUnroll;
+ } else {
+ Message_StartTextbox(play, this->textId, &this->actor);
+ this->actionFunc = EnSGoro_ShopGoron_Talk;
+ }
+ } else if ((this->actor.xzDistToPlayer < 250.0f) || this->actor.isTargeted) {
+ func_800B863C(&this->actor, play);
+ }
+ Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.home.rot.y, 5, 0x1000, 0x100);
+ this->actor.world.rot.y = this->actor.shape.rot.y;
+}
+
+void EnSGoro_ShopGoron_FinishUnroll(EnSGoro* this, PlayState* play) {
+ s16 curFrame = this->skelAnime.curFrame;
+ s16 lastFrame = Animation_GetLastFrame(sAnimationInfo[this->animInfoIndex].animation);
+
+ if ((this->animInfoIndex == EN_S_GORO_ANIM_UNROLL_A) && (curFrame == lastFrame)) {
+ this->animInfoIndex = EN_S_GORO_ANIM_IDLE_STAND;
+ SubS_ChangeAnimationByInfoS(&this->skelAnime, sAnimationInfo, this->animInfoIndex);
+ Message_StartTextbox(play, this->textId, &this->actor);
+ this->actionFunc = EnSGoro_ShopGoron_Talk;
+ }
+
+ Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 5, 0x1000, 0x100);
+ this->actor.world.rot.y = this->actor.shape.rot.y;
+}
+
+void EnSGoro_ShopGoron_Talk(EnSGoro* this, PlayState* play) {
+ u8 talkState = Message_GetState(&play->msgCtx);
+
+ if (this->actionFlags & EN_S_GORO_ACTIONFLAG_HANDTAP) {
+ EnSGoro_UpdateToHandtapAnimation(this);
+ } else if (this->actionFlags & EN_S_GORO_ACTIONFLAG_TIRED) {
+ EnSGoro_UpdateSleepyAnimation(this);
+ } else {
+ EnSGoro_UpdateToIdleAnimation(this);
+ }
+
+ if (talkState == TEXT_STATE_DONE) {
+ if (Message_ShouldAdvance(play)) {
+ if (this->actionFlags & EN_S_GORO_ACTIONFLAG_LASTMESSAGE) {
+ this->actionFlags &= ~EN_S_GORO_ACTIONFLAG_LASTMESSAGE;
+ this->actionFlags &= ~EN_S_GORO_ACTIONFLAG_ENGAGED;
+ this->textId = 0;
+ this->actionFunc = EnSGoro_ShopGoron_Idle;
+ return;
+ }
+ this->textId = EnSGoro_BombshopGoron_NextTextId(this, play);
+ Message_StartTextbox(play, this->textId, &this->actor);
+ }
+ } else if ((talkState == TEXT_STATE_CHOICE) && (Message_ShouldAdvance(play))) {
+ switch (play->msgCtx.choiceIndex) {
+ case 0:
+ this->bombbuyFlags |= EN_S_GORO_BOMBBUYFLAG_YESBUY;
+ break;
+ case 1:
+ func_8019F230();
+ this->bombbuyFlags &= ~EN_S_GORO_BOMBBUYFLAG_YESBUY;
+ break;
+ }
+
+ this->textId = EnSGoro_BombshopGoron_NextTextId(this, play);
+ if ((this->textId == 0x675) || (this->textId == 0x676)) {
+ play->msgCtx.msgMode = 0x43;
+ play->msgCtx.stateTimer = 4;
+ Actor_PickUp(&this->actor, play, GI_POWDER_KEG, 300.0f, 300.0f);
+ this->actionFunc = EnSGoro_ShopGoron_TakePayment;
+ } else {
+ Message_StartTextbox(play, this->textId, &this->actor);
+ }
+ }
+
+ Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 5, 0x1000, 0x100);
+ this->actor.world.rot.y = this->actor.shape.rot.y;
+}
+
+void EnSGoro_ShopGoron_TakePayment(EnSGoro* this, PlayState* play) {
+ if (Actor_HasParent(&this->actor, play)) {
+ this->actor.parent = NULL;
+ Rupees_ChangeBy(-this->powderKegPrice);
+ this->actionFunc = EnSGoro_ShopGoron_FinishTransaction;
+ } else {
+ Actor_PickUp(&this->actor, play, GI_POWDER_KEG, 300.0f, 300.0f);
+ }
+}
+
+void EnSGoro_ShopGoron_FinishTransaction(EnSGoro* this, PlayState* play) {
+ if (Actor_ProcessTalkRequest(&this->actor, &play->state)) {
+ Message_StartTextbox(play, this->textId, &this->actor);
+ this->actionFunc = EnSGoro_ShopGoron_Talk;
+ } else {
+ func_800B85E0(&this->actor, play, 400.0f, -1);
+ }
+}
+
+void EnSGoro_Sleep(EnSGoro* this, PlayState* play) {
+ if (Actor_ProcessTalkRequest(&this->actor, &play->state)) {
+ Message_StartTextbox(play, 0x23A, &this->actor);
+ this->actionFunc = EnSGoro_SleepTalk;
+ } else if (this->actor.isTargeted) {
+ func_800B863C(&this->actor, play);
+ }
+ EnSGoro_UpdateSleeping(this, play);
+}
+
+void EnSGoro_SleepTalk(EnSGoro* this, PlayState* play) {
+ if (Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) {
+ if (Message_ShouldAdvance(play)) {
+ play->msgCtx.msgMode = 0x43;
+ play->msgCtx.stateTimer = 4;
+ this->actionFunc = EnSGoro_Sleep;
+ }
+ }
+ EnSGoro_UpdateSleeping(this, play);
+}
+
+void EnSGoro_Init(Actor* thisx, PlayState* play) {
+ s32 pad;
+ EnSGoro* this = THIS;
+
+ ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 20.0f);
+ SkelAnime_InitFlex(play, &this->skelAnime, &gGoronSkel, &gGoronUnrollAnim, this->jointTable, this->morphTable,
+ GORON_LIMB_MAX);
+ Collider_InitCylinder(play, &this->collider);
+ Collider_SetCylinder(play, &this->collider, &this->actor, &sCylinderInit);
+ CollisionCheck_SetInfo2(&this->actor.colChkInfo, &sDamageTable, &sColChkInfoInit);
+ if (this->actor.update != NULL) {
+ s32 objIndex = Object_GetIndex(&play->objectCtx, OBJECT_OF1D_MAP);
+
+ this->loadedObjIndex = objIndex;
+ if (objIndex < 0) {
+ Actor_MarkForDeath(&this->actor);
+ }
+ }
+ this->actor.draw = EnSGoro_Draw;
+ this->actionFunc = EnSGoro_SetupAction;
+}
+
+void EnSGoro_Destroy(Actor* thisx, PlayState* play) {
+ EnSGoro* this = THIS;
+
+ Collider_DestroyCylinder(play, &this->collider);
+}
+
+void EnSGoro_Update(Actor* thisx, PlayState* play) {
+ EnSGoro* this = (EnSGoro*)thisx;
+
+ this->actionFunc(this, play);
+ Actor_UpdateBgCheckInfo(play, &this->actor, 30.0f, 12.0f, 0.0f, 5);
+ gSegments[6] = PHYSICAL_TO_VIRTUAL(play->objectCtx.status[this->loadedObjIndex].segment);
+ SkelAnime_Update(&this->skelAnime);
+ if (this->animInfoIndex != EN_S_GORO_ANIM_SLEEPY) {
+ EnSGoro_UpdateAttentionTarget(this, play);
+ }
+ EnSGoro_UpdateEyes(this);
+ EnSGoro_UpdateActorFocus(this);
+ EnSGoro_UpdateCollider(this, play);
+}
+
+/**
+ * This function appears to be identical to SubS_UpdateLimb. But it's here!
+ */
+s32 EnSGoro_UpdateLimb(s16 newRotZ, s16 newRotY, Vec3f* pos, Vec3s* rot, s32 stepRot, s32 overrideRot) {
+ Vec3f newPos;
+ Vec3f zeroVec = gZeroVec3f;
+ Vec3s newRot;
+ MtxF curState;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_S_Goro/func_80BBE144.s")
+ Matrix_MultVec3f(&zeroVec, &newPos);
+ Matrix_Get(&curState);
+ Matrix_MtxFToYXZRot(&curState, &newRot, MTXMODE_NEW);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_S_Goro/func_80BBE374.s")
+ *pos = newPos;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_S_Goro/func_80BBE498.s")
+ if (!stepRot && !overrideRot) {
+ rot->x = newRot.x;
+ rot->y = newRot.y;
+ rot->z = newRot.z;
+ return true;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_S_Goro/func_80BBE73C.s")
+ if (overrideRot) {
+ newRot.z = newRotZ;
+ newRot.y = newRotY;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_S_Goro/func_80BBE844.s")
+ Math_SmoothStepToS(&rot->x, newRot.x, 3, 0x2AA8, 0xB6);
+ Math_SmoothStepToS(&rot->y, newRot.y, 3, 0x2AA8, 0xB6);
+ Math_SmoothStepToS(&rot->z, newRot.z, 3, 0x2AA8, 0xB6);
+ return true;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_S_Goro/func_80BBE904.s")
+s32 EnSGoro_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, Actor* thisx) {
+ return false;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_S_Goro/func_80BBE9F8.s")
+void EnSGoro_TransformLimbDraw(PlayState* play, s32 limbIndex, Actor* thisx) {
+ s32 stepRot;
+ s32 overrideRot;
+ EnSGoro* this = THIS;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_S_Goro/func_80BBEAD8.s")
+ if (limbIndex != GORON_LIMB_BODY) {
+ if ((limbIndex == GORON_LIMB_HEAD) && (this->animInfoIndex != EN_S_GORO_ANIM_SLEEPY)) {
+ if (this->actionFlags & EN_S_GORO_ACTIONFLAG_FACEPLAYER) {
+ overrideRot = true;
+ } else {
+ overrideRot = false;
+ }
+ if (this->loseAttentionTimer != 0) {
+ stepRot = true;
+ } else {
+ stepRot = false;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_S_Goro/func_80BBEBF8.s")
+ EnSGoro_UpdateLimb(this->headRotZ + this->bodyRotZ + 0x4000,
+ this->headRotY + this->bodyRotY + this->actor.shape.rot.y + 0x4000, &this->headTranslate,
+ &this->headRotate, stepRot, overrideRot);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_S_Goro/func_80BBECBC.s")
+ Matrix_Pop();
+ Matrix_Translate(this->headTranslate.x, this->headTranslate.y, this->headTranslate.z, MTXMODE_NEW);
+ Matrix_Scale(this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, MTXMODE_APPLY);
+ Matrix_RotateYS(this->headRotate.y, MTXMODE_APPLY);
+ Matrix_RotateXS(this->headRotate.x, MTXMODE_APPLY);
+ Matrix_RotateZS(this->headRotate.z, MTXMODE_APPLY);
+ Matrix_Push();
+ }
+ } else if (this->animInfoIndex != EN_S_GORO_ANIM_SLEEPY) {
+ if (this->actionFlags & EN_S_GORO_ACTIONFLAG_FACEPLAYER) {
+ overrideRot = true;
+ } else {
+ overrideRot = false;
+ }
+ if (this->loseAttentionTimer != 0) {
+ stepRot = true;
+ } else {
+ stepRot = false;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_S_Goro/func_80BBEEB4.s")
+ EnSGoro_UpdateLimb(this->bodyRotZ + 0x4000, this->bodyRotY + this->actor.shape.rot.y + 0x4000,
+ &this->bodyTranslate, &this->bodyRotate, stepRot, overrideRot);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_S_Goro/func_80BBEF34.s")
+ Matrix_Pop();
+ Matrix_Translate(this->bodyTranslate.x, this->bodyTranslate.y, this->bodyTranslate.z, MTXMODE_NEW);
+ Matrix_Scale(this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, MTXMODE_APPLY);
+ Matrix_RotateYS(this->bodyRotate.y, MTXMODE_APPLY);
+ Matrix_RotateXS(this->bodyRotate.x, MTXMODE_APPLY);
+ Matrix_RotateZS(this->bodyRotate.z, MTXMODE_APPLY);
+ Matrix_Push();
+ }
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_S_Goro/func_80BBEFA0.s")
+void EnSGoro_DrawUnrolled(EnSGoro* this, PlayState* play) {
+ s32 pad;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_S_Goro/func_80BBF01C.s")
+ OPEN_DISPS(play->state.gfxCtx);
+ func_8012C28C(play->state.gfxCtx);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_S_Goro/EnSGoro_Init.s")
+ gSPSegment(POLY_OPA_DISP++, 0x8, Lib_SegmentedToVirtual(sEyeTextures[this->eyeTexIndex]));
+ gDPPipeSync(POLY_OPA_DISP++);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_S_Goro/EnSGoro_Destroy.s")
+ SkelAnime_DrawTransformFlexOpa(play, this->skelAnime.skeleton, this->skelAnime.jointTable,
+ this->skelAnime.dListCount, EnSGoro_OverrideLimbDraw, NULL,
+ EnSGoro_TransformLimbDraw, &this->actor);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_S_Goro/EnSGoro_Update.s")
+ CLOSE_DISPS(play->state.gfxCtx);
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_S_Goro/func_80BBF298.s")
+void EnSGoro_DrawRolledUp(EnSGoro* this, PlayState* play) {
+ OPEN_DISPS(play->state.gfxCtx);
+ func_8012C28C(play->state.gfxCtx);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_S_Goro/func_80BBF3D0.s")
+ Matrix_Translate(this->actor.world.pos.x, this->actor.world.pos.y + this->actor.shape.yOffset,
+ this->actor.world.pos.z, MTXMODE_NEW);
+ Matrix_RotateYS(this->actor.shape.rot.y, MTXMODE_APPLY);
+ Matrix_Translate(0.0f, -this->actor.shape.yOffset, 0.0f, MTXMODE_APPLY);
+ Matrix_RotateZS(this->actor.shape.rot.z, MTXMODE_APPLY);
+ Matrix_Translate(0.0f, this->actor.shape.yOffset, 0.0f, MTXMODE_APPLY);
+ Matrix_Scale(this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, MTXMODE_APPLY);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_S_Goro/func_80BBF3EC.s")
+ gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(POLY_OPA_DISP++, gGoronRolledUpDL);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_S_Goro/func_80BBF5F0.s")
+ CLOSE_DISPS(play->state.gfxCtx);
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_S_Goro/func_80BBF6BC.s")
+void EnSGoro_Draw(Actor* thisx, PlayState* play) {
+ EnSGoro* this = (EnSGoro*)thisx;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_S_Goro/EnSGoro_Draw.s")
+ if (this->actionFlags & EN_S_GORO_ACTIONFLAG_ROLLEDUP) {
+ EnSGoro_DrawRolledUp(this, play);
+ } else {
+ EnSGoro_DrawUnrolled(this, play);
+ }
+}
diff --git a/src/overlays/actors/ovl_En_S_Goro/z_en_s_goro.h b/src/overlays/actors/ovl_En_S_Goro/z_en_s_goro.h
index 7d8e7627f..0d7ac9edb 100644
--- a/src/overlays/actors/ovl_En_S_Goro/z_en_s_goro.h
+++ b/src/overlays/actors/ovl_En_S_Goro/z_en_s_goro.h
@@ -2,20 +2,59 @@
#define Z_EN_S_GORO_H
#include "global.h"
+#include "objects/object_oF1d_map/object_oF1d_map.h"
-#define EN_S_GORO_GET_PARAM_F(thisx) ((thisx)->params & 0xF)
+#define EN_S_GORO_GET_MAIN_TYPE(thisx) ((thisx)->params & 0xF)
+#define EN_S_GORO_SCENEFLAG_INDEX(thisx) (((thisx)->params & 0x7F0) >> 4)
struct EnSGoro;
typedef void (*EnSGoroActionFunc)(struct EnSGoro*, PlayState*);
+extern const ActorInit En_S_Goro_InitVars;
+
typedef struct EnSGoro {
/* 0x000 */ Actor actor;
- /* 0x144 */ char unk_144[0x48];
+ /* 0x144 */ Actor* otherGoron;
+ /* 0x148 */ SkelAnime skelAnime;
/* 0x18C */ EnSGoroActionFunc actionFunc;
- /* 0x190 */ char unk_190[0x180];
+ /* 0x190 */ ColliderCylinder collider;
+ /* 0x1DC */ u16 actionFlags;
+ /* 0x1DE */ u16 bombbuyFlags;
+ /* 0x1E0 */ UNK_TYPE1 unk_1E0[0xC];
+ /* 0x1EC */ s16 eyeTexIndex;
+ /* 0x1EE */ s16 eyeTimer;
+ /* 0x1F0 */ s16 loseAttentionTimer;
+ /* 0x1F4 */ s32 loadedObjIndex;
+ /* 0x1F8 */ Vec3s jointTable[GORON_LIMB_MAX];
+ /* 0x264 */ Vec3s morphTable[GORON_LIMB_MAX];
+ /* 0x2D0 */ f32 scaleFactor;
+ /* 0x2D4 */ s16 headRotZ;
+ /* 0x2D6 */ s16 headRotY;
+ /* 0x2D8 */ s16 bodyRotZ;
+ /* 0x2DA */ s16 bodyRotY;
+ /* 0x2DC */ Vec3f headTranslate;
+ /* 0x2E8 */ Vec3s headRotate;
+ /* 0x2F0 */ Vec3f bodyTranslate;
+ /* 0x2FC */ Vec3s bodyRotate;
+ /* 0x302 */ UNK_TYPE1 unk_302[2];
+ /* 0x304 */ u16 textId;
+ /* 0x306 */ s16 snorePhase;
+ /* 0x308 */ s32 animInfoIndex;
+ /* 0x30C */ s16 powderKegPrice;
} EnSGoro; // size = 0x310
-extern const ActorInit En_S_Goro_InitVars;
+typedef enum EnSGoroType {
+ /* 0x0 */ EN_S_GORO_TYPE_SHRINE_WINTER_A,
+ /* 0x1 */ EN_S_GORO_TYPE_SHRINE_WINTER_B,
+ /* 0x2 */ EN_S_GORO_TYPE_SHRINE_WINTER_C,
+ /* 0x3 */ EN_S_GORO_TYPE_SHRINE_SPRING_A,
+ /* 0x4 */ EN_S_GORO_TYPE_SHRINE_SPRING_B,
+ /* 0x5 */ EN_S_GORO_TYPE_SHRINE_SPRING_C,
+ /* 0x6 */ EN_S_GORO_TYPE_SHRINE_SPRING_D,
+ /* 0x7 */ EN_S_GORO_TYPE_SHRINE_SPRING_E,
+ /* 0x8 */ EN_S_GORO_TYPE_SHRINE_SPRING_F,
+ /* 0x9 */ EN_S_GORO_TYPE_BOMBSHOP
+} EnSGoroType;
#endif // Z_EN_S_GORO_H