diff --git a/assets/xml/objects/object_ahg.xml b/assets/xml/objects/object_ahg.xml index 7eb4c71263..8233a5b27e 100644 --- a/assets/xml/objects/object_ahg.xml +++ b/assets/xml/objects/object_ahg.xml @@ -1,53 +1,62 @@  + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/xml/objects/object_sth.xml b/assets/xml/objects/object_sth.xml index b176cd8cc4..53040ae053 100644 --- a/assets/xml/objects/object_sth.xml +++ b/assets/xml/objects/object_sth.xml @@ -1,42 +1,53 @@  + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/xml/overlays/ovl_En_Sth.xml b/assets/xml/overlays/ovl_En_Sth.xml index 51b29870da..a0d90d9e86 100644 --- a/assets/xml/overlays/ovl_En_Sth.xml +++ b/assets/xml/overlays/ovl_En_Sth.xml @@ -1,14 +1,15 @@ - - - - - - - - - - + + + + + + + + + + + diff --git a/include/z64save.h b/include/z64save.h index 1b5531540b..60d3a9a2b2 100644 --- a/include/z64save.h +++ b/include/z64save.h @@ -622,9 +622,18 @@ typedef enum SunsSongState { #define WEEKEVENTREG_13_04 PACK_WEEKEVENTREG_FLAG(13, 0x04) #define WEEKEVENTREG_13_08 PACK_WEEKEVENTREG_FLAG(13, 0x08) #define WEEKEVENTREG_13_10 PACK_WEEKEVENTREG_FLAG(13, 0x10) -#define WEEKEVENTREG_13_20 PACK_WEEKEVENTREG_FLAG(13, 0x20) -#define WEEKEVENTREG_13_40 PACK_WEEKEVENTREG_FLAG(13, 0x40) -#define WEEKEVENTREG_13_80 PACK_WEEKEVENTREG_FLAG(13, 0x80) + +// This flag marks that the player has finished the Oceanside Spider House and has exited. +// Used to identify if EnSth should be moved deeper into the house. +// This does NOT flag: +// A) that the player has completed the house (Inventory_GetSkullTokenCount(play->sceneId)) +// B) that the player has collected a reward (WEEKEVENTREG_OCEANSIDE_SPIDER_HOUSE_COLLECTED_REWARD) +// C) that the player has collected the wallet (WEEKEVENTREG_RECEIVED_OCEANSIDE_WALLET_UPGRADE) +#define WEEKEVENTREG_OCEANSIDE_SPIDER_HOUSE_BUYER_MOVED_IN PACK_WEEKEVENTREG_FLAG(13, 0x20) + +#define WEEKEVENTREG_RECEIVED_OCEANSIDE_WALLET_UPGRADE PACK_WEEKEVENTREG_FLAG(13, 0x40) +// You only get a wallet if completed on Day 1: repeat gets silver rupee, other days get less +#define WEEKEVENTREG_OCEANSIDE_SPIDER_HOUSE_COLLECTED_REWARD PACK_WEEKEVENTREG_FLAG(13, 0x80) // PlayedMilkMinigame // Attempted Cremia Cart Ride @@ -830,10 +839,10 @@ typedef enum SunsSongState { #define WEEKEVENTREG_34_02 PACK_WEEKEVENTREG_FLAG(34, 0x02) #define WEEKEVENTREG_34_04 PACK_WEEKEVENTREG_FLAG(34, 0x04) -#define WEEKEVENTREG_34_08 PACK_WEEKEVENTREG_FLAG(34, 0x08) +#define WEEKEVENTREG_SWAMP_SPIDER_HOUSE_TALKED PACK_WEEKEVENTREG_FLAG(34, 0x08) #define WEEKEVENTREG_34_10 PACK_WEEKEVENTREG_FLAG(34, 0x10) #define WEEKEVENTREG_34_20 PACK_WEEKEVENTREG_FLAG(34, 0x20) -#define WEEKEVENTREG_34_40 PACK_WEEKEVENTREG_FLAG(34, 0x40) +#define WEEKEVENTREG_RECEIVED_MASK_OF_TRUTH PACK_WEEKEVENTREG_FLAG(34, 0x40) // Cremia did Milk Run alone. Player didn't interact or didn't accept the ride #define WEEKEVENTREG_34_80 PACK_WEEKEVENTREG_FLAG(34, 0x80) diff --git a/src/overlays/actors/ovl_En_Sekihi/z_en_sekihi.c b/src/overlays/actors/ovl_En_Sekihi/z_en_sekihi.c index 88fab32987..aa780cddfb 100644 --- a/src/overlays/actors/ovl_En_Sekihi/z_en_sekihi.c +++ b/src/overlays/actors/ovl_En_Sekihi/z_en_sekihi.c @@ -59,8 +59,9 @@ void EnSekihi_Init(Actor* thisx, PlayState* play) { return; } - if ((params == SEKIHI_TYPE_4) && (((gSaveContext.save.skullTokenCount & 0xFFFF)) >= 30)) { - SET_WEEKEVENTREG(WEEKEVENTREG_13_20); + if ((params == SEKIHI_TYPE_4) && (((gSaveContext.save.skullTokenCount & 0xFFFF)) >= SPIDER_HOUSE_TOKENS_REQUIRED)) { + // For some reason the mikau grave sets the flag instead of something in the spider house on exit. + SET_WEEKEVENTREG(WEEKEVENTREG_OCEANSIDE_SPIDER_HOUSE_BUYER_MOVED_IN); } objectIndex = Object_GetIndex(&play->objectCtx, sObjectIds[params]); diff --git a/src/overlays/actors/ovl_En_Sekihi/z_en_sekihi.h b/src/overlays/actors/ovl_En_Sekihi/z_en_sekihi.h index fb4ad7e608..0c26dab71b 100644 --- a/src/overlays/actors/ovl_En_Sekihi/z_en_sekihi.h +++ b/src/overlays/actors/ovl_En_Sekihi/z_en_sekihi.h @@ -2,6 +2,8 @@ #define Z_EN_SEKIHI_H #include "global.h" +#include "overlays/actors/ovl_En_Si/z_en_si.h" + #define ENSIKIHI_GET_TYPE(thisx) ((thisx)->params & 0xF) diff --git a/src/overlays/actors/ovl_En_Si/z_en_si.c b/src/overlays/actors/ovl_En_Si/z_en_si.c index 74a55261f7..cf44d641b7 100644 --- a/src/overlays/actors/ovl_En_Si/z_en_si.c +++ b/src/overlays/actors/ovl_En_Si/z_en_si.c @@ -104,11 +104,11 @@ void EnSi_GiveToken(EnSi* this, PlayState* play) { Flags_SetTreasure(play, chestFlag); } Item_Give(play, ITEM_SKULL_TOKEN); - if (Inventory_GetSkullTokenCount(play->sceneId) >= 30) { - Message_StartTextbox(play, 0xFC, NULL); + if (Inventory_GetSkullTokenCount(play->sceneId) >= SPIDER_HOUSE_TOKENS_REQUIRED) { + Message_StartTextbox(play, 0xFC, NULL); // You collected all tokens, curse lifted Audio_PlayFanfare(NA_BGM_GET_ITEM | 0x900); } else { - Message_StartTextbox(play, 0x52, NULL); + Message_StartTextbox(play, 0x52, NULL); // You got one more gold token, your [count] one! Audio_PlayFanfare(NA_BGM_GET_SMALL_ITEM); } } diff --git a/src/overlays/actors/ovl_En_Si/z_en_si.h b/src/overlays/actors/ovl_En_Si/z_en_si.h index 07628bf86e..f1b089ddda 100644 --- a/src/overlays/actors/ovl_En_Si/z_en_si.h +++ b/src/overlays/actors/ovl_En_Si/z_en_si.h @@ -5,6 +5,8 @@ #define ENSI_GET_CHEST_FLAG(thisx) (((thisx)->params & 0xFC) >> 2) +#define SPIDER_HOUSE_TOKENS_REQUIRED 30 + struct EnSi; typedef void (*EnSiActionFunc)(struct EnSi*, PlayState*); diff --git a/src/overlays/actors/ovl_En_Ssh/z_en_ssh.c b/src/overlays/actors/ovl_En_Ssh/z_en_ssh.c index d47d665886..14617e2aec 100644 --- a/src/overlays/actors/ovl_En_Ssh/z_en_ssh.c +++ b/src/overlays/actors/ovl_En_Ssh/z_en_ssh.c @@ -654,7 +654,7 @@ void EnSsh_Init(Actor* thisx, PlayState* play) { this->actor.gravity = 0.0f; this->initialYaw = this->actor.world.rot.y; EnSsh_SetupAction(this, EnSsh_Start); - if (Inventory_GetSkullTokenCount(play->sceneId) >= 30) { + if (Inventory_GetSkullTokenCount(play->sceneId) >= SPIDER_HOUSE_TOKENS_REQUIRED) { Actor_Kill(&this->actor); } } @@ -686,18 +686,18 @@ void EnSsh_Talk(EnSsh* this, PlayState* play) { if ((Message_GetState(&play->msgCtx) == TEXT_STATE_5) && Message_ShouldAdvance(play)) { switch (play->msgCtx.currentTextId) { - case 0x904: - case 0x905: - case 0x906: - case 0x908: - case 0x910: - case 0x911: - case 0x912: - case 0x914: + case 0x904: // (does not exist) + case 0x905: // (does not exist) + case 0x906: // (does not exist) + case 0x908: // (does not exist) + case 0x910: // Help me! I am not a monster, I was cursed this way + case 0x911: // Find all in here and defeat them + case 0x912: // Don't forget to collect their token + case 0x914: // In here, cursed spiders, defeat them to make me normal func_80151938(play, play->msgCtx.currentTextId + 1); break; - default: + default: // intended case 0x915 from above (914+1) func_801477B4(play); this->actionFunc = EnSsh_Idle; break; @@ -706,15 +706,15 @@ void EnSsh_Talk(EnSsh* this, PlayState* play) { } void func_809756D0(EnSsh* this, PlayState* play) { - u16 phi_a1; + u16 nextTextId; - if (CHECK_WEEKEVENTREG(WEEKEVENTREG_34_08)) { - phi_a1 = 0x914; + if (CHECK_WEEKEVENTREG(WEEKEVENTREG_SWAMP_SPIDER_HOUSE_TALKED)) { + nextTextId = 0x914; // In here, cursed spiders, defeat them to make me normal } else { - phi_a1 = 0x910; - SET_WEEKEVENTREG(WEEKEVENTREG_34_08); + nextTextId = 0x910; // Help me! I am not a monster, I was cursed this way + SET_WEEKEVENTREG(WEEKEVENTREG_SWAMP_SPIDER_HOUSE_TALKED); } - Message_StartTextbox(play, phi_a1, &this->actor); + Message_StartTextbox(play, nextTextId, &this->actor); } void EnSsh_Idle(EnSsh* this, PlayState* play) { diff --git a/src/overlays/actors/ovl_En_Ssh/z_en_ssh.h b/src/overlays/actors/ovl_En_Ssh/z_en_ssh.h index 094c63f7e7..6f19a5e51a 100644 --- a/src/overlays/actors/ovl_En_Ssh/z_en_ssh.h +++ b/src/overlays/actors/ovl_En_Ssh/z_en_ssh.h @@ -2,6 +2,8 @@ #define Z_EN_SSH_H #include "global.h" +#include "overlays/actors/ovl_En_Si/z_en_si.h" +#include "overlays/actors/ovl_En_Sth/z_en_sth.h" struct EnSsh; diff --git a/src/overlays/actors/ovl_En_Sth/z_en_sth.c b/src/overlays/actors/ovl_En_Sth/z_en_sth.c index 5d1bd14714..4cca2770fd 100644 --- a/src/overlays/actors/ovl_En_Sth/z_en_sth.c +++ b/src/overlays/actors/ovl_En_Sth/z_en_sth.c @@ -1,13 +1,13 @@ /* * File: z_en_sth.c * Overlay: ovl_En_Sth - * Description: Guy looking at moon in South Clock Town + * Description: Guy looking at moon in South Clock Town, + * And the Cured Swamp Spider House man who gives you Mask of Truth + * (the cursed version is EnSsh) + * And the man who wants to buy Oceanside Spider House from you with rupees or Wallet */ #include "z_en_sth.h" -#include "objects/object_sth/object_sth.h" -#include "objects/object_ahg/object_ahg.h" -#include "objects/object_mask_truth/object_mask_truth.h" #define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_8) @@ -15,17 +15,17 @@ void EnSth_Init(Actor* thisx, PlayState* play); void EnSth_Destroy(Actor* thisx, PlayState* play); -void EnSth_Update(Actor* thisx, PlayState* play); +void EnSth_UpdateWaitForObject(Actor* thisx, PlayState* play); -void func_80B67208(EnSth* this, PlayState* play); -void func_80B67540(EnSth* this, PlayState* play); -void func_80B677BC(EnSth* this, PlayState* play); -void func_80B678A8(EnSth* this, PlayState* play); -void func_80B67958(EnSth* this, PlayState* play); -void func_80B67C1C(EnSth* this, PlayState* play); -void func_80B67DA0(EnSth* this, PlayState* play); -void func_80B680A8(Actor* thisx, PlayState* play); -void func_80B6849C(Actor* thisx, PlayState* play); +void EnSth_PanicIdle(EnSth* this, PlayState* play); +void EnSth_HandleOceansideSpiderHouseConversation(EnSth* this, PlayState* play); +void EnSth_OceansideSpiderHouseIdle(EnSth* this, PlayState* play); +void EnSth_MoonLookingIdle(EnSth* this, PlayState* play); +void EnSth_DefaultIdle(EnSth* this, PlayState* play); +void EnSth_HandleSwampSpiderHouseConversation(EnSth* this, PlayState* play); +void EnSth_SwampSpiderHouseIdle(EnSth* this, PlayState* play); +void EnSth_Update(Actor* thisx, PlayState* play); +void EnSth_Draw(Actor* thisx, PlayState* play); ActorInit En_Sth_InitVars = { ACTOR_EN_STH, @@ -35,7 +35,7 @@ ActorInit En_Sth_InitVars = { sizeof(EnSth), (ActorFunc)EnSth_Init, (ActorFunc)EnSth_Destroy, - (ActorFunc)EnSth_Update, + (ActorFunc)EnSth_UpdateWaitForObject, (ActorFunc)NULL, }; @@ -61,21 +61,48 @@ static ColliderCylinderInit sCylinderInit = { { 30, 40, 0, { 0, 0, 0 } }, }; -AnimationHeader* D_80B6D1C8[] = { - &ovl_En_Sth_Anim_003F50, &ovl_En_Sth_Anim_0045B4, &ovl_En_Sth_Anim_004CC0, &ovl_En_Sth_Anim_00533C, - &ovl_En_Sth_Anim_0059B8, &ovl_En_Sth_Anim_005E40, &ovl_En_Sth_Anim_006354, &ovl_En_Sth_Anim_00645C, +typedef enum { + /* 0 */ STH_ANIM_SIGNALLING, // default, waving arms at you from telescope, OOT: cured happy animation + /* 1 */ STH_ANIM_BENDING_DOWN, // default anim of cured spider house, but never seen before wait overrides it + /* 2 */ STH_ANIM_TALK, + /* 3 */ STH_ANIM_WAIT, + /* 4 */ STH_ANIM_LOOK_UP, // South Clock Town, looking at moon + /* 5 */ STH_ANIM_LOOK_AROUND, // checking out Oceanside Spider House + /* 6 */ STH_ANIM_PLEAD, // wants to buy Oceanside Spider House + /* 7 */ STH_ANIM_PANIC, // after buying Oceanside Spider House, can be found at bottom of slide, + /* 8 */ STH_ANIM_START, // set in init, not an actual index to the array +} EnSthAnimation; + +static AnimationHeader* sAnimationInfo[] = { + &gEnSthSignalAnim, &gEnSthBendDownAnim, &gEnSthTalkWithHandUpAnim, &gEnSthWaitAnim, + &gEnSthLookUpAnim, &gEnSthLookAroundAnim, &gEnSthPleadAnim, &gEnSthPanicAnim, }; -u16 D_80B6D1E8[] = { 0x1144, 0x1145, 0x1146 }; +// three slightly different variants of "Only a little time left, oh goddess please save me" +static u16 sSthOceanspiderhousePanicText[] = { 0x1144, 0x1145, 0x1146 }; -u16 D_80B6D1F0[] = { 0x1139, 0x113E, 0x1143 }; +static u16 sSthFirstOceansideSpiderHouseGreet2TextIds[] = { + 0x1139, // I thought I heard noises... I'm glad I found it early + 0x113E, // I had no idea this place was here, perhaps it can keep me safe + 0x1143 // There's no time we have to hide! +}; -u16 D_80B6D1F8[] = { 0x1132, 0x113A, 0x113F }; +static u16 sSthFirstOceansideSpiderHouseGreet1TextIds[] = { + 0x1132, // I thought I heard some noise.. is this some sort of underground shelter? + 0x113A, // I had no idea there was a basement here.. + 0x113F // I heard loud noises.. I never thought I'd find a place like this.. +}; -Vec3f D_80B6D200 = { 700.0f, 400.0f, 0.0f }; +static Vec3f sFocusOffset = { 700.0f, 400.0f, 0.0f }; -Color_RGB8 D_80B6D20C[] = { - { 190, 110, 0 }, { 0, 180, 110 }, { 0, 255, 0x50 }, { 255, 160, 60 }, { 190, 230, 250 }, { 240, 230, 120 }, +// Sth is hardcoded to only use element [1]. +static Color_RGB8 sShirtColors[] = { + { 190, 110, 0 }, // darker orange + { 0, 180, 110 }, // green + { 0, 255, 80 }, // lime green + { 255, 160, 60 }, // brighter orange + { 190, 230, 250 }, // white + { 240, 230, 120 }, // pale yellow }; void EnSth_Init(Actor* thisx, PlayState* play) { @@ -83,82 +110,88 @@ void EnSth_Init(Actor* thisx, PlayState* play) { EnSth* this = THIS; s32 objectId; - if (ENSTH_GET_100(&this->actor)) { + // this actor can draw two separate bodies that use different objects + if (STH_GET_SWAMP_BODY(&this->actor)) { objectId = Object_GetIndex(&play->objectCtx, OBJECT_AHG); } else { objectId = Object_GetIndex(&play->objectCtx, OBJECT_STH); } - this->unk_29E = objectId; - this->unk_29F = Object_GetIndex(&play->objectCtx, OBJECT_MASK_TRUTH); + this->mainObjectId = objectId; + this->maskOfTruthObjectId = Object_GetIndex(&play->objectCtx, OBJECT_MASK_TRUTH); Actor_SetScale(&this->actor, 0.01f); Collider_InitAndSetCylinder(play, &this->collider, &this->actor, &sCylinderInit); this->actor.colChkInfo.mass = MASS_IMMOVABLE; ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 36.0f); - this->unk_29C = 0; - this->unk_29A = 8; + this->sthFlags = 0; // clear + this->animIndex = STH_ANIM_START; this->actor.terminalVelocity = -9.0f; this->actor.gravity = -1.0f; - switch (ENSTH_GET_F(&this->actor)) { - case ENSTH_F_1: + switch (STH_GET_TYPE(&this->actor)) { + case STH_TYPE_UNUSED_1: if (play->actorCtx.flags & ACTORCTX_FLAG_1) { this->actor.flags |= (ACTOR_FLAG_10 | ACTOR_FLAG_20); - this->actionFunc = func_80B67958; + this->actionFunc = EnSth_DefaultIdle; } else { Actor_Kill(&this->actor); return; } break; - case ENSTH_F_2: - if (Inventory_GetSkullTokenCount(play->sceneId) >= 30) { - this->actionFunc = func_80B67DA0; + case STH_TYPE_SWAMP_SPIDER_HOUSE_CURED: + if (Inventory_GetSkullTokenCount(play->sceneId) >= SPIDER_HOUSE_TOKENS_REQUIRED) { + this->actionFunc = EnSth_SwampSpiderHouseIdle; } else { Actor_Kill(&this->actor); } this->actor.textId = 0; - if (!CHECK_WEEKEVENTREG(WEEKEVENTREG_34_40) || !CHECK_WEEKEVENTREG(WEEKEVENTREG_34_08)) { - this->unk_29C |= 1; + if (!CHECK_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_MASK_OF_TRUTH) || + !CHECK_WEEKEVENTREG(WEEKEVENTREG_SWAMP_SPIDER_HOUSE_TALKED)) { + this->sthFlags |= STH_FLAG_DRAW_MASK_OF_TRUTH; } break; - case ENSTH_F_3: - if ((gSaveContext.save.skullTokenCount & 0xFFFF) >= 30) { + case STH_TYPE_MOON_LOOKING: // South Clock Town + if ((gSaveContext.save.skullTokenCount & 0xFFFF) >= SPIDER_HOUSE_TOKENS_REQUIRED) { Actor_Kill(&this->actor); return; } - this->actionFunc = func_80B678A8; - this->unk_29C |= 8; + + this->actionFunc = EnSth_MoonLookingIdle; + this->sthFlags |= STH_FLAG_DISABLE_HEAD_TRACK; this->actor.targetMode = 3; this->actor.uncullZoneForward = 800.0f; break; - case ENSTH_F_4: - if (CHECK_WEEKEVENTREG(WEEKEVENTREG_13_20)) { + case STH_TYPE_OCEANSIDE_SPIDER_HOUSE_GREET: + if (CHECK_WEEKEVENTREG(WEEKEVENTREG_OCEANSIDE_SPIDER_HOUSE_BUYER_MOVED_IN)) { + // The player has already exited the house after complete; EnSth has moved deeper into the house. Actor_Kill(&this->actor); return; } this->actor.textId = 0; - this->actionFunc = func_80B677BC; - if (CHECK_WEEKEVENTREG(WEEKEVENTREG_13_80)) { - this->unk_29C |= 2; + this->actionFunc = EnSth_OceansideSpiderHouseIdle; + if (CHECK_WEEKEVENTREG(WEEKEVENTREG_OCEANSIDE_SPIDER_HOUSE_COLLECTED_REWARD)) { + this->sthFlags |= STH_FLAG_OCEANSIDE_SPIDER_HOUSE_GREET; } break; - case ENSTH_F_5: - if (!CHECK_WEEKEVENTREG(WEEKEVENTREG_13_20) || (Inventory_GetSkullTokenCount(play->sceneId) < 30)) { + case STH_TYPE_OCEANSIDE_SPIDER_HOUSE_PANIC: + if (!CHECK_WEEKEVENTREG(WEEKEVENTREG_OCEANSIDE_SPIDER_HOUSE_BUYER_MOVED_IN) || + (Inventory_GetSkullTokenCount(play->sceneId) < SPIDER_HOUSE_TOKENS_REQUIRED)) { + // Has not moved in, and has not completed the house; do NOT spawn yet. Actor_Kill(&this->actor); return; } - this->actionFunc = func_80B67208; + this->actionFunc = EnSth_PanicIdle; this->actor.textId = 0; - this->unk_29C |= 8; + this->sthFlags |= STH_FLAG_DISABLE_HEAD_TRACK; break; default: - this->actionFunc = func_80B67958; + this->actionFunc = EnSth_DefaultIdle; break; } } @@ -169,142 +202,144 @@ void EnSth_Destroy(Actor* thisx, PlayState* play) { Collider_DestroyCylinder(play, &this->collider); } -s32 func_80B6703C(EnSth* this, PlayState* play) { +s32 EnSth_CanSpeakToPlayer(EnSth* this, PlayState* play) { if ((this->actor.xzDistToPlayer < 100.0f) && Player_IsFacingActor(&this->actor, 0x3000, play) && Actor_IsFacingPlayer(&this->actor, 0x2000)) { return true; - } - return false; -} - -void func_80B670A4(EnSth* this, s16 arg1) { - if ((arg1 >= 0) && (arg1 < ARRAY_COUNT(D_80B6D1C8)) && (arg1 != this->unk_29A)) { - Animation_Change(&this->skelAnime, D_80B6D1C8[arg1], 1.0f, 0.0f, Animation_GetLastFrame(D_80B6D1C8[arg1]), - ANIMMODE_LOOP, -5.0f); - this->unk_29A = arg1; + } else { + return false; } } -void func_80B67148(EnSth* this, PlayState* play) { +void EnSth_ChangeAnim(EnSth* this, s16 animIndex) { + if ((animIndex >= 0) && (animIndex < ARRAY_COUNT(sAnimationInfo)) && (animIndex != this->animIndex)) { + Animation_Change(&this->skelAnime, sAnimationInfo[animIndex], 1.0f, 0.0f, + Animation_GetLastFrame(sAnimationInfo[animIndex]), ANIMMODE_LOOP, -5.0f); + this->animIndex = animIndex; + } +} + +void EnSth_GetInitialPanicText(EnSth* this, PlayState* play) { s32 day = CURRENT_DAY - 1; - u16 val; + u16 nextTextId; if (day < 0) { day = 0; } - val = D_80B6D1E8[day]; + nextTextId = sSthOceanspiderhousePanicText[day]; - Message_StartTextbox(play, val, &this->actor); + Message_StartTextbox(play, nextTextId, &this->actor); } -void func_80B671A0(EnSth* this, PlayState* play) { +void EnSth_HandlePanicConversation(EnSth* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); if ((Message_GetState(&play->msgCtx) == TEXT_STATE_5) && Message_ShouldAdvance(play)) { - this->actionFunc = func_80B67208; + this->actionFunc = EnSth_PanicIdle; func_801477B4(play); } } -void func_80B67208(EnSth* this, PlayState* play) { +void EnSth_PanicIdle(EnSth* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); if (Actor_ProcessTalkRequest(&this->actor, &play->state)) { - func_80B67148(this, play); - this->actionFunc = func_80B671A0; + EnSth_GetInitialPanicText(this, play); + this->actionFunc = EnSth_HandlePanicConversation; } else if ((this->actor.xzDistToPlayer < 100.0f) && Player_IsFacingActor(&this->actor, 0x3000, play)) { func_800B8614(&this->actor, play, 110.0f); } } -void func_80B672A4(EnSth* this, PlayState* play) { - u16 sp1E; +void EnSth_GetInitialOceansideSpiderHouseText(EnSth* this, PlayState* play) { + u16 nextTextId; s32 day = CURRENT_DAY - 1; if (day < 0) { day = 0; } - if (this->unk_29C & 2) { + if (this->sthFlags & STH_FLAG_OCEANSIDE_SPIDER_HOUSE_GREET) { s32 pad; - sp1E = D_80B6D1F0[day]; + nextTextId = sSthFirstOceansideSpiderHouseGreet2TextIds[day]; if (day == 2) { - func_80B670A4(this, 5); + EnSth_ChangeAnim(this, STH_ANIM_LOOK_AROUND); } } else { - sp1E = D_80B6D1F8[day]; + nextTextId = sSthFirstOceansideSpiderHouseGreet1TextIds[day]; } - Message_StartTextbox(play, sp1E, &this->actor); + Message_StartTextbox(play, nextTextId, &this->actor); } -void func_80B67348(EnSth* this, PlayState* play) { - u16 phi_a1; +void EnSth_PostOceanspiderhouseReward(EnSth* this, PlayState* play) { + u16 nextTextId; SkelAnime_Update(&this->skelAnime); if (Actor_ProcessTalkRequest(&this->actor, &play->state)) { this->actor.flags &= ~ACTOR_FLAG_10000; - this->actionFunc = func_80B67540; + this->actionFunc = EnSth_HandleOceansideSpiderHouseConversation; - switch (this->actor.home.rot.z) { - case 8: - case 9: - phi_a1 = 0x1137; + switch (STH_GI_ID(&this->actor)) { + case GI_WALLET_ADULT: + case GI_WALLET_GIANT: + nextTextId = 0x1137; // I'm just glad it was something you needed break; - case 6: - phi_a1 = 0x1138; + case GI_RUPEE_SILVER: + // unused code, as he only gives wallet, purple and red, silver is never assigned to STH_GI_ID + nextTextId = 0x1138; // That's my life's fortune break; - case 5: - if (CHECK_WEEKEVENTREG(WEEKEVENTREG_13_40)) { - phi_a1 = 0x113D; + case GI_RUPEE_PURPLE: + if (CHECK_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_OCEANSIDE_WALLET_UPGRADE)) { + nextTextId = 0x113D; // That's my life's savings } else { - phi_a1 = 0x113C; + nextTextId = 0x113C; // That's my life's savings (2) } break; default: - if (CHECK_WEEKEVENTREG(WEEKEVENTREG_13_40)) { - phi_a1 = 0x1142; + if (CHECK_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_OCEANSIDE_WALLET_UPGRADE)) { + nextTextId = 0x1142; // Well, thats all I have on me } else { - phi_a1 = 0x1141; + nextTextId = 0x1141; // Well, thats all I have on me } break; } - Message_StartTextbox(play, phi_a1, &this->actor); + Message_StartTextbox(play, nextTextId, &this->actor); } else { func_800B8500(&this->actor, play, 1000.0f, 1000.0f, PLAYER_IA_MINUS1); } } -void func_80B67458(EnSth* this, PlayState* play) { +void EnSth_GiveOceansideSpiderHouseReward(EnSth* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); if (Actor_HasParent(&this->actor, play)) { this->actor.parent = NULL; - this->actionFunc = func_80B67348; + this->actionFunc = EnSth_PostOceanspiderhouseReward; this->actor.flags |= ACTOR_FLAG_10000; func_800B8500(&this->actor, play, 1000.0f, 1000.0f, PLAYER_IA_MINUS1); if (CURRENT_DAY == 3) { - func_80B670A4(this, 6); + EnSth_ChangeAnim(this, STH_ANIM_PLEAD); } else { - func_80B670A4(this, 3); + EnSth_ChangeAnim(this, STH_ANIM_WAIT); } } else { - Actor_PickUp(&this->actor, play, this->actor.home.rot.z, 10000.0f, 500.0f); + Actor_PickUp(&this->actor, play, STH_GI_ID(&this->actor), 10000.0f, 500.0f); } } -void func_80B67540(EnSth* this, PlayState* play) { - s32 sp2C = CURRENT_DAY - 1; +void EnSth_HandleOceansideSpiderHouseConversation(EnSth* this, PlayState* play) { + s32 day = CURRENT_DAY - 1; - if (sp2C < 0) { - sp2C = 0; + if (day < 0) { + day = 0; } - if (this->unk_29A == 6) { + if (this->animIndex == STH_ANIM_PLEAD) { Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 2, 0x1000, 0x200); this->actor.world.rot.y = this->actor.shape.rot.y; } @@ -315,313 +350,329 @@ void func_80B67540(EnSth* this, PlayState* play) { case TEXT_STATE_5: if (Message_ShouldAdvance(play)) { switch (play->msgCtx.currentTextId) { - case 0x1134: + case 0x1134: // (does not exist) func_80151938(play, play->msgCtx.currentTextId + 1); break; - case 0x1132: - case 0x113A: - case 0x113F: - func_80151938(play, 0x1133); + case 0x1132: // Heard noise, came in to see + case 0x113A: // Had no idea there was a basement here + case 0x113F: // Heard noise... I never thought I'd find a place like this + func_80151938(play, 0x1133); // did you find this place? break; - case 0x1133: - func_80151938(play, 0x1136); - func_80B670A4(this, 6); + case 0x1133: // did you find this place? + func_80151938(play, 0x1136); // I want to buy this place from you + EnSth_ChangeAnim(this, STH_ANIM_PLEAD); break; - case 0x1136: - SET_WEEKEVENTREG(WEEKEVENTREG_13_80); + case 0x1136: // I want to buy this house from you + // This flag prevents multiple rewards, switching to secondary dialogue after + SET_WEEKEVENTREG(WEEKEVENTREG_OCEANSIDE_SPIDER_HOUSE_COLLECTED_REWARD); - switch (sp2C) { - case 0: - if (CHECK_WEEKEVENTREG(WEEKEVENTREG_13_40)) { - this->actor.home.rot.z = 6; + switch (day) { + case 0: // first day + if (CHECK_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_OCEANSIDE_WALLET_UPGRADE)) { + STH_GI_ID(&this->actor) = GI_RUPEE_SILVER; } else { - SET_WEEKEVENTREG(WEEKEVENTREG_13_40); + // This flag prevents getting two wallets from the same place. + // Instead, getting silver rupee above. + SET_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_OCEANSIDE_WALLET_UPGRADE); switch (CUR_UPG_VALUE(UPG_WALLET)) { case 0: - this->actor.home.rot.z = 8; + STH_GI_ID(&this->actor) = GI_WALLET_ADULT; break; case 1: - this->actor.home.rot.z = 9; + STH_GI_ID(&this->actor) = GI_WALLET_GIANT; break; } } break; - case 1: - this->actor.home.rot.z = 5; + case 1: // second day + STH_GI_ID(&this->actor) = GI_RUPEE_PURPLE; break; - default: - this->actor.home.rot.z = 4; + default: // final day + STH_GI_ID(&this->actor) = GI_RUPEE_RED; break; } func_801477B4(play); - this->actionFunc = func_80B67458; - func_80B67458(this, play); + this->actionFunc = EnSth_GiveOceansideSpiderHouseReward; + EnSth_GiveOceansideSpiderHouseReward(this, play); break; - case 0x113C: - func_80151938(play, 0x113B); + case 0x113C: // (Second day) I am giving you my life savings + func_80151938(play, 0x113B); // If only I had gotten here yesterday... break; - case 0x1141: - func_80151938(play, 0x1140); - func_80B670A4(this, 3); + case 0x1141: // (Final day) This is all I have + func_80151938(play, 0x1140); // If only I had gotten here two days ago... + EnSth_ChangeAnim(this, STH_ANIM_WAIT); break; default: - this->actionFunc = func_80B677BC; + this->actionFunc = EnSth_OceansideSpiderHouseIdle; func_801477B4(play); - this->unk_29C |= 2; + this->sthFlags |= STH_FLAG_OCEANSIDE_SPIDER_HOUSE_GREET; break; } } break; case TEXT_STATE_CLOSING: - this->actionFunc = func_80B677BC; - this->unk_29C |= 2; + this->actionFunc = EnSth_OceansideSpiderHouseIdle; + this->sthFlags |= STH_FLAG_OCEANSIDE_SPIDER_HOUSE_GREET; break; } } -void func_80B677BC(EnSth* this, PlayState* play) { +void EnSth_OceansideSpiderHouseIdle(EnSth* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); if (Actor_ProcessTalkRequest(&this->actor, &play->state)) { - func_80B672A4(this, play); - this->actionFunc = func_80B67540; - } else if (func_80B6703C(this, play)) { + EnSth_GetInitialOceansideSpiderHouseText(this, play); + this->actionFunc = EnSth_HandleOceansideSpiderHouseConversation; + } else if (EnSth_CanSpeakToPlayer(this, play)) { func_800B8614(&this->actor, play, 110.0f); } } -void func_80B67838(EnSth* this, PlayState* play) { +void EnSth_HandleMoonLookingConversation(EnSth* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); if ((Message_GetState(&play->msgCtx) == TEXT_STATE_5) && Message_ShouldAdvance(play)) { - this->actionFunc = func_80B678A8; + this->actionFunc = EnSth_MoonLookingIdle; func_801477B4(play); } - this->unk_294.x = -0x1388; + this->headRot.x = -0x1388; } -void func_80B678A8(EnSth* this, PlayState* play) { +void EnSth_MoonLookingIdle(EnSth* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); if (Actor_ProcessTalkRequest(&this->actor, &play->state)) { - this->actionFunc = func_80B67838; - } else if (func_80B6703C(this, play) || this->actor.isTargeted) { + this->actionFunc = EnSth_HandleMoonLookingConversation; + } else if (EnSth_CanSpeakToPlayer(this, play) || this->actor.isTargeted) { if ((gSaveContext.save.time >= CLOCK_TIME(6, 0)) && (gSaveContext.save.time <= CLOCK_TIME(18, 0))) { - this->actor.textId = 0x1130; + this->actor.textId = 0x1130; // Huh? The Moon... } else { - this->actor.textId = 0x1131; + this->actor.textId = 0x1131; // (The Moon) gotten bigger again } func_800B8614(&this->actor, play, 110.0f); } - this->unk_294.x = -0x1388; + this->headRot.x = -0x1388; } -void func_80B67958(EnSth* this, PlayState* play) { +// used by type: STH_TYPE_UNUSED_1 and undefined types +void EnSth_DefaultIdle(EnSth* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); } -void func_80B67984(EnSth* this, PlayState* play) { - u16 sp1E; +void EnSth_GetInitialSwampSpiderHouseText(EnSth* this, PlayState* play) { + u16 nextTextId; if (CHECK_WEEKEVENTREG(WEEKEVENTREG_34_10)) { - sp1E = 0x903; - func_80B670A4(this, 2); + nextTextId = 0x903; // (does not exist) + EnSth_ChangeAnim(this, STH_ANIM_TALK); } else if (CHECK_WEEKEVENTREG(WEEKEVENTREG_34_20)) { - sp1E = 0x90F; - func_80B670A4(this, 2); - } else if (CHECK_WEEKEVENTREG(WEEKEVENTREG_34_40)) { - if (!CHECK_WEEKEVENTREG(WEEKEVENTREG_34_08)) { - sp1E = 0x91B; + nextTextId = 0x90F; // (does not exist) + EnSth_ChangeAnim(this, STH_ANIM_TALK); + } else if (CHECK_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_MASK_OF_TRUTH)) { + if (!CHECK_WEEKEVENTREG(WEEKEVENTREG_SWAMP_SPIDER_HOUSE_TALKED)) { + nextTextId = 0x91B; // As soon as I calm down, getting rid of it } else { - sp1E = 0x918; + nextTextId = 0x918; // I've had enough of this, going home } - func_80B670A4(this, 2); - } else if (Inventory_GetSkullTokenCount(play->sceneId) >= 30) { + EnSth_ChangeAnim(this, STH_ANIM_TALK); + } else if (Inventory_GetSkullTokenCount(play->sceneId) >= SPIDER_HOUSE_TOKENS_REQUIRED) { if (INV_CONTENT(ITEM_MASK_TRUTH) == ITEM_MASK_TRUTH) { - this->unk_29C |= 4; - sp1E = 0x919; + this->sthFlags |= STH_FLAG_SWAMP_SPIDER_HOUSE_SAVED; + nextTextId = 0x919; // I've been saved! } else { - sp1E = 0x916; + nextTextId = 0x916; // I've been saved! (Duplicate) } } else if (CHECK_WEEKEVENTREG(WEEKEVENTREG_34_02)) { - sp1E = 0x8FF; + nextTextId = 0x8FF; // (does not exist) } else { - sp1E = 0x8FC; + nextTextId = 0x8FC; // (does not exist) SET_WEEKEVENTREG(WEEKEVENTREG_34_02); } - Message_StartTextbox(play, sp1E, &this->actor); + + Message_StartTextbox(play, nextTextId, &this->actor); } -void func_80B67AB4(EnSth* this, PlayState* play) { +void EnSth_TalkAfterSwampSpiderHouseGiveMask(EnSth* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); if (Actor_ProcessTalkRequest(&this->actor, &play->state)) { - this->actionFunc = func_80B67C1C; - SET_WEEKEVENTREG(WEEKEVENTREG_34_40); - Message_StartTextbox(play, 0x918, &this->actor); + this->actionFunc = EnSth_HandleSwampSpiderHouseConversation; + SET_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_MASK_OF_TRUTH); + Message_StartTextbox(play, 0x918, &this->actor); // I've had enough of this, going home } else { func_800B8500(&this->actor, play, 1000.0f, 1000.0f, PLAYER_IA_MINUS1); } } -void func_80B67B50(EnSth* this, PlayState* play) { +void EnSth_SwampSpiderHouseGiveMask(EnSth* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); if (Actor_HasParent(&this->actor, play)) { this->actor.parent = NULL; - this->actionFunc = func_80B67AB4; + this->actionFunc = EnSth_TalkAfterSwampSpiderHouseGiveMask; this->actor.flags |= ACTOR_FLAG_10000; func_800B8500(&this->actor, play, 1000.0f, 1000.0f, PLAYER_IA_MINUS1); } else { - this->unk_29C &= ~1; - SET_WEEKEVENTREG(WEEKEVENTREG_34_08); + this->sthFlags &= ~STH_FLAG_DRAW_MASK_OF_TRUTH; + // This flag is used to keep track if the player has already spoken to the actor, triggering secondary dialogue. + SET_WEEKEVENTREG(WEEKEVENTREG_SWAMP_SPIDER_HOUSE_TALKED); Actor_PickUp(&this->actor, play, GI_MASK_TRUTH, 10000.0f, 50.0f); } } -void func_80B67C1C(EnSth* this, PlayState* play) { +void EnSth_HandleSwampSpiderHouseConversation(EnSth* this, PlayState* play) { s32 pad; SkelAnime_Update(&this->skelAnime); if ((Message_GetState(&play->msgCtx) == TEXT_STATE_5) && Message_ShouldAdvance(play)) { switch (play->msgCtx.currentTextId) { - case 0x90C: - func_80B670A4(this, 2); + case 0x90C: // (does not exist) + EnSth_ChangeAnim(this, STH_ANIM_TALK); func_80151938(play, play->msgCtx.currentTextId + 1); break; - case 0x916: - case 0x919: - func_80B670A4(this, 3); + case 0x916: // I have been saved! I thought I was doomed + case 0x919: // I have been saved! I thought I was doomed (duplicate) + EnSth_ChangeAnim(this, STH_ANIM_WAIT); func_80151938(play, play->msgCtx.currentTextId + 1); break; - case 0x8FC: - case 0x8FD: - case 0x900: - case 0x90A: - case 0x90D: + case 0x8FC: // (does not exist) + case 0x8FD: // (does not exist) + case 0x900: // (does not exist) + case 0x90A: // (does not exist) + case 0x90D: // (does not exist) func_80151938(play, play->msgCtx.currentTextId + 1); break; - case 0x901: - case 0x90B: - case 0x917: + case 0x901: // (does not exist) + case 0x90B: // (does not exist) + case 0x917: // Someone gave me this mask and said it would make me rich, Take it func_801477B4(play); - this->actionFunc = func_80B67B50; - func_80B67B50(this, play); + this->actionFunc = EnSth_SwampSpiderHouseGiveMask; + EnSth_SwampSpiderHouseGiveMask(this, play); break; - case 0x91A: - SET_WEEKEVENTREG(WEEKEVENTREG_34_40); - CLEAR_WEEKEVENTREG(WEEKEVENTREG_34_08); + case 0x91A: // Someone gave me this mask and said it would make me rich, getting rid of it + SET_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_MASK_OF_TRUTH); + CLEAR_WEEKEVENTREG(WEEKEVENTREG_SWAMP_SPIDER_HOUSE_TALKED); - case 0x902: - case 0x903: - case 0x90E: - case 0x90F: - case 0x918: - case 0x91B: - func_80B670A4(this, 3); + case 0x902: // (does not exist) + case 0x903: // (does not exist) + case 0x90E: // (does not exist) + case 0x90F: // (does not exist) + case 0x918: // I have had enough, going home + case 0x91B: // As soon as I calm down, getting rid of it + EnSth_ChangeAnim(this, STH_ANIM_WAIT); default: this->actor.flags &= ~ACTOR_FLAG_10000; func_801477B4(play); - this->actionFunc = func_80B67DA0; + this->actionFunc = EnSth_SwampSpiderHouseIdle; break; } } } -void func_80B67DA0(EnSth* this, PlayState* play) { +void EnSth_SwampSpiderHouseIdle(EnSth* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); if (Actor_ProcessTalkRequest(&this->actor, &play->state)) { - func_80B67984(this, play); - this->actionFunc = func_80B67C1C; - } else if (func_80B6703C(this, play)) { + EnSth_GetInitialSwampSpiderHouseText(this, play); + this->actionFunc = EnSth_HandleSwampSpiderHouseConversation; + } else if (EnSth_CanSpeakToPlayer(this, play)) { this->actor.textId = 0; func_800B8614(&this->actor, play, 110.0f); } } -void func_80B67E20(Actor* thisx, PlayState* play) { +/** + * Oceanside Spider House EnSth shows up after you collect all 30 tokens. + * Here we wait invisible until the player has finished. + */ +void EnSth_UpdateOceansideSpiderHouseWaitForTokens(Actor* thisx, PlayState* play) { EnSth* this = THIS; - if (Inventory_GetSkullTokenCount(play->sceneId) >= 30) { - this->actor.update = func_80B680A8; - this->actor.draw = func_80B6849C; + if (Inventory_GetSkullTokenCount(play->sceneId) >= SPIDER_HOUSE_TOKENS_REQUIRED) { + this->actor.update = EnSth_Update; + this->actor.draw = EnSth_Draw; this->actor.flags |= ACTOR_FLAG_1; } } -void EnSth_Update(Actor* thisx, PlayState* play) { +/** + * Dual object actors have to wait for the object to finish loading. + * This dev chose to use a temporary update instead of temporary actionFunc. + */ +void EnSth_UpdateWaitForObject(Actor* thisx, PlayState* play) { s32 pad; EnSth* this = THIS; - if (Object_IsLoaded(&play->objectCtx, this->unk_29E)) { - this->actor.objBankIndex = this->unk_29E; + if (Object_IsLoaded(&play->objectCtx, this->mainObjectId)) { + this->actor.objBankIndex = this->mainObjectId; Actor_SetObjectDependency(play, &this->actor); - if (ENSTH_GET_100(&this->actor)) { - SkelAnime_InitFlex(play, &this->skelAnime, &object_ahg_Skel_005998, &ovl_En_Sth_Anim_0045B4, - this->jointTable, this->morphTable, 16); - Animation_PlayLoop(&this->skelAnime, &ovl_En_Sth_Anim_0045B4); - this->unk_29A = 1; + if (STH_GET_SWAMP_BODY(&this->actor)) { + SkelAnime_InitFlex(play, &this->skelAnime, &gAhgSkel, &gEnSthBendDownAnim, this->jointTable, + this->morphTable, AHG_LIMB_MAX); + Animation_PlayLoop(&this->skelAnime, &gEnSthBendDownAnim); + this->animIndex = STH_ANIM_BENDING_DOWN; if (CHECK_WEEKEVENTREG(WEEKEVENTREG_34_10) || CHECK_WEEKEVENTREG(WEEKEVENTREG_34_20) || - CHECK_WEEKEVENTREG(WEEKEVENTREG_34_40) || (Inventory_GetSkullTokenCount(play->sceneId) >= 30)) { - func_80B670A4(this, 3); + CHECK_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_MASK_OF_TRUTH) || + (Inventory_GetSkullTokenCount(play->sceneId) >= SPIDER_HOUSE_TOKENS_REQUIRED)) { + EnSth_ChangeAnim(this, STH_ANIM_WAIT); } } else { - SkelAnime_InitFlex(play, &this->skelAnime, &object_sth_Skel_0031F8, &ovl_En_Sth_Anim_003F50, - this->jointTable, this->morphTable, 16); - Animation_PlayLoop(&this->skelAnime, &ovl_En_Sth_Anim_003F50); + SkelAnime_InitFlex(play, &this->skelAnime, &gSthSkel, &gEnSthSignalAnim, this->jointTable, this->morphTable, + STH_LIMB_MAX); + Animation_PlayLoop(&this->skelAnime, &gEnSthSignalAnim); } - this->actor.update = func_80B680A8; - this->actor.draw = func_80B6849C; + this->actor.update = EnSth_Update; + this->actor.draw = EnSth_Draw; - switch (ENSTH_GET_F(&this->actor)) { - case ENSTH_F_3: - func_80B670A4(this, 4); + switch (STH_GET_TYPE(&this->actor)) { + case STH_TYPE_MOON_LOOKING: + EnSth_ChangeAnim(this, STH_ANIM_LOOK_UP); break; - case ENSTH_F_4: - if (CHECK_WEEKEVENTREG(WEEKEVENTREG_13_80)) { - func_80B670A4(this, 5); + case STH_TYPE_OCEANSIDE_SPIDER_HOUSE_GREET: + if (CHECK_WEEKEVENTREG(WEEKEVENTREG_OCEANSIDE_SPIDER_HOUSE_COLLECTED_REWARD)) { + EnSth_ChangeAnim(this, STH_ANIM_LOOK_AROUND); } else { - func_80B670A4(this, 5); + EnSth_ChangeAnim(this, STH_ANIM_LOOK_AROUND); } break; - case ENSTH_F_5: - func_80B670A4(this, 7); + case STH_TYPE_OCEANSIDE_SPIDER_HOUSE_PANIC: + EnSth_ChangeAnim(this, STH_ANIM_PANIC); break; } - if ((ENSTH_GET_F(&this->actor) == ENSTH_F_4) && (Inventory_GetSkullTokenCount(play->sceneId) < 30)) { - this->actor.update = func_80B67E20; + // not ready to appear yet + if ((STH_GET_TYPE(&this->actor) == STH_TYPE_OCEANSIDE_SPIDER_HOUSE_GREET) && + (Inventory_GetSkullTokenCount(play->sceneId) < SPIDER_HOUSE_TOKENS_REQUIRED)) { + this->actor.update = EnSth_UpdateOceansideSpiderHouseWaitForTokens; this->actor.draw = NULL; this->actor.flags &= ~ACTOR_FLAG_1; } } } -void func_80B680A8(Actor* thisx, PlayState* play) { +void EnSth_Update(Actor* thisx, PlayState* play) { s32 pad; EnSth* this = THIS; - Vec3s sp38; Actor_MoveWithGravity(&this->actor); Collider_UpdateCylinder(&this->actor, &this->collider); @@ -630,59 +681,66 @@ void func_80B680A8(Actor* thisx, PlayState* play) { this->actionFunc(this, play); - if (func_80B6703C(this, play) && !(this->unk_29C & 8) && (this->unk_29A != 5)) { - sp38.x = sp38.y = sp38.z = 0; + if (EnSth_CanSpeakToPlayer(this, play) && !(this->sthFlags & STH_FLAG_DISABLE_HEAD_TRACK) && + (this->animIndex != STH_ANIM_LOOK_AROUND)) { + Vec3s torsoRot; - Actor_TrackPlayer(play, &this->actor, &this->unk_294, &sp38, this->actor.focus.pos); + torsoRot.x = torsoRot.y = torsoRot.z = 0; // this should block torso rot from working + + Actor_TrackPlayer(play, &this->actor, &this->headRot, &torsoRot, this->actor.focus.pos); } else { - Math_SmoothStepToS(&this->unk_294.x, 0, 6, 6200, 100); - Math_SmoothStepToS(&this->unk_294.y, 0, 6, 6200, 100); + Math_SmoothStepToS(&this->headRot.x, 0, 6, 6200, 100); + Math_SmoothStepToS(&this->headRot.y, 0, 6, 6200, 100); } } -s32 func_80B681E8(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, Actor* thisx) { +s32 EnSth_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, Actor* thisx) { s32 pad; EnSth* this = THIS; - if (limbIndex == 15) { - rot->x += this->unk_294.y; - rot->z += this->unk_294.x; - *dList = ovl_En_Sth_DL_0034A0; + if (limbIndex == STH_LIMB_HEAD) { + rot->x += this->headRot.y; + rot->z += this->headRot.x; + + // object_sth body has no head by default, forced here from overlay data + *dList = gEnSthHeadDL; } - if ((limbIndex == 8) || (limbIndex == 10) || (limbIndex == 13)) { + if ((limbIndex == STH_LIMB_CHEST) || (limbIndex == STH_LIMB_LEFT_FOREARM) || + (limbIndex == STH_LIMB_RIGHT_FOREARM)) { rot->y += (s16)(Math_SinS(play->state.frames * ((limbIndex * 50) + 0x814)) * 200.0f); rot->z += (s16)(Math_CosS(play->state.frames * ((limbIndex * 50) + 0x940)) * 200.0f); } + return false; } -void func_80B68310(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx) { +void EnSth_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx) { EnSth* this = THIS; - if (limbIndex == 15) { + if (limbIndex == STH_LIMB_HEAD) { s32 pad; - Matrix_MultVec3f(&D_80B6D200, &this->actor.focus.pos); + Matrix_MultVec3f(&sFocusOffset, &this->actor.focus.pos); - if (!ENSTH_GET_100(&this->actor)) { + if (!STH_GET_SWAMP_BODY(&this->actor)) { OPEN_DISPS(play->state.gfxCtx); - gSPDisplayList(POLY_OPA_DISP++, ovl_En_Sth_DL_0037C0); + gSPDisplayList(POLY_OPA_DISP++, gEnSthExtraHairDL); CLOSE_DISPS(play->state.gfxCtx); } else { OPEN_DISPS(play->state.gfxCtx); - if (this->unk_29C & 1) { - if (Object_IsLoaded(&play->objectCtx, this->unk_29F)) { + if (this->sthFlags & STH_FLAG_DRAW_MASK_OF_TRUTH) { + if (Object_IsLoaded(&play->objectCtx, this->maskOfTruthObjectId)) { Matrix_Push(); Matrix_RotateZS(0x3A98, MTXMODE_APPLY); Matrix_Translate(0.0f, 190.0f, 0.0f, MTXMODE_APPLY); gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gSPSegment(POLY_OPA_DISP++, 0x0A, play->objectCtx.status[this->unk_29F].segment); + gSPSegment(POLY_OPA_DISP++, 0x0A, play->objectCtx.status[this->maskOfTruthObjectId].segment); gSPDisplayList(POLY_OPA_DISP++, object_mask_truth_DL_0001A0); Matrix_Pop(); @@ -694,7 +752,7 @@ void func_80B68310(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, Acto } } -void func_80B6849C(Actor* thisx, PlayState* play) { +void EnSth_Draw(Actor* thisx, PlayState* play) { s32 pad; EnSth* this = THIS; @@ -703,11 +761,11 @@ void func_80B6849C(Actor* thisx, PlayState* play) { func_8012C28C(play->state.gfxCtx); gSPSegment(POLY_OPA_DISP++, 0x08, - Gfx_EnvColor(play->state.gfxCtx, D_80B6D20C[1].r, D_80B6D20C[1].g, D_80B6D20C[1].b, 255)); + Gfx_EnvColor(play->state.gfxCtx, sShirtColors[1].r, sShirtColors[1].g, sShirtColors[1].b, 255)); gSPSegment(POLY_OPA_DISP++, 0x09, Gfx_EnvColor(play->state.gfxCtx, 90, 110, 130, 255)); SkelAnime_DrawFlexOpa(play, this->skelAnime.skeleton, this->skelAnime.jointTable, this->skelAnime.dListCount, - func_80B681E8, func_80B68310, &this->actor); + EnSth_OverrideLimbDraw, EnSth_PostLimbDraw, &this->actor); CLOSE_DISPS(play->state.gfxCtx); } diff --git a/src/overlays/actors/ovl_En_Sth/z_en_sth.h b/src/overlays/actors/ovl_En_Sth/z_en_sth.h index 857b925053..1c8c92852d 100644 --- a/src/overlays/actors/ovl_En_Sth/z_en_sth.h +++ b/src/overlays/actors/ovl_En_Sth/z_en_sth.h @@ -2,33 +2,48 @@ #define Z_EN_STH_H #include "global.h" +#include "overlays/actors/ovl_En_Si/z_en_si.h" +#include "objects/object_sth/object_sth.h" +#include "objects/object_ahg/object_ahg.h" +#include "objects/object_mask_truth/object_mask_truth.h" struct EnSth; typedef void (*EnSthActionFunc)(struct EnSth*, PlayState*); -#define ENSTH_GET_F(thisx) ((thisx)->params & 0xF) -#define ENSTH_GET_100(thisx) ((thisx)->params & 0x100) +typedef enum { + /* 1 */ STH_TYPE_UNUSED_1 = 1, + /* 2 */ STH_TYPE_SWAMP_SPIDER_HOUSE_CURED, // cursed is EnSsh + /* 3 */ STH_TYPE_MOON_LOOKING, // South Clock Town, looking up at the moon + /* 4 */ STH_TYPE_OCEANSIDE_SPIDER_HOUSE_GREET, // looking for shelter + /* 5 */ STH_TYPE_OCEANSIDE_SPIDER_HOUSE_PANIC, // shelter was not enough + // Other values: Actor will spawn and animate with arm waving, no further interaction. +} EnSthTypes; -enum { - /* 1 */ ENSTH_F_1 = 1, - /* 2 */ ENSTH_F_2, - /* 3 */ ENSTH_F_3, - /* 4 */ ENSTH_F_4, - /* 5 */ ENSTH_F_5, -}; +// Note: Vanilla types usually have 0xFEXX typing, but this upper section is unused by the code, reason unknown +#define STH_GET_TYPE(thisx) ((thisx)->params & 0xF) +#define STH_GET_SWAMP_BODY(thisx) ((thisx)->params & 0x100) + +// The get item ID for the reward for Oceanside Spider House (wallet, or rupees) is set here +#define STH_GI_ID(thisx) ((thisx)->home.rot.z) + +// This actor has its own flags system +#define STH_FLAG_DRAW_MASK_OF_TRUTH (1 << 0) +#define STH_FLAG_OCEANSIDE_SPIDER_HOUSE_GREET (1 << 1) +#define STH_FLAG_SWAMP_SPIDER_HOUSE_SAVED (1 << 2) // set, but not read +#define STH_FLAG_DISABLE_HEAD_TRACK (1 << 3) typedef struct EnSth { /* 0x000 */ Actor actor; /* 0x144 */ ColliderCylinder collider; /* 0x190 */ SkelAnime skelAnime; - /* 0x1D4 */ Vec3s jointTable[16]; - /* 0x234 */ Vec3s morphTable[16]; - /* 0x294 */ Vec3s unk_294; - /* 0x29A */ s16 unk_29A; - /* 0x29C */ u16 unk_29C; - /* 0x29E */ u8 unk_29E; - /* 0x29F */ u8 unk_29F; + /* 0x1D4 */ Vec3s jointTable[STH_LIMB_MAX]; + /* 0x234 */ Vec3s morphTable[STH_LIMB_MAX]; + /* 0x294 */ Vec3s headRot; + /* 0x29A */ s16 animIndex; + /* 0x29C */ u16 sthFlags; + /* 0x29E */ u8 mainObjectId; + /* 0x29F */ u8 maskOfTruthObjectId; /* 0x2A0 */ EnSthActionFunc actionFunc; } EnSth; // size = 0x2A4 diff --git a/src/overlays/actors/ovl_En_Sth2/z_en_sth2.c b/src/overlays/actors/ovl_En_Sth2/z_en_sth2.c index ac615a8dd8..ba6d72cb61 100644 --- a/src/overlays/actors/ovl_En_Sth2/z_en_sth2.c +++ b/src/overlays/actors/ovl_En_Sth2/z_en_sth2.c @@ -63,8 +63,8 @@ void EnSth2_Update(Actor* thisx, PlayState* play) { if (Object_IsLoaded(&play->objectCtx, this->objIndex)) { this->actor.objBankIndex = this->objIndex; Actor_SetObjectDependency(play, &this->actor); - SkelAnime_InitFlex(play, &this->skelAnime, &object_sth_Skel_0031F8, &gEnSth2WavingHandAnim, this->jointTable, - this->morphTable, OBJECT_STH_LIMB_MAX); + SkelAnime_InitFlex(play, &this->skelAnime, &gSthSkel, &gEnSth2WavingHandAnim, this->jointTable, + this->morphTable, STH_LIMB_MAX); Animation_PlayLoop(&this->skelAnime, &gEnSth2WavingHandAnim); this->actor.update = EnSth2_UpdateActionFunc; this->actor.draw = EnSth2_Draw; @@ -80,10 +80,11 @@ void EnSth2_UpdateActionFunc(Actor* thisx, PlayState* play) { s32 EnSth2_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, Actor* thisx) { s32 pad; - if (limbIndex == OBJECT_STH_LIMB_0F) { + if (limbIndex == STH_LIMB_HEAD) { *dList = gEnSth2HeadDL; } - if ((limbIndex == OBJECT_STH_LIMB_08) || (limbIndex == OBJECT_STH_LIMB_0A) || (limbIndex == OBJECT_STH_LIMB_0D)) { + if ((limbIndex == STH_LIMB_CHEST) || (limbIndex == STH_LIMB_LEFT_FOREARM) || + (limbIndex == STH_LIMB_RIGHT_FOREARM)) { rot->y += (s16)(Math_SinS((play->state.frames * ((limbIndex * 50) + 0x814))) * 200.0f); rot->z += (s16)(Math_CosS((play->state.frames * ((limbIndex * 50) + 0x940))) * 200.0f); } @@ -93,7 +94,7 @@ s32 EnSth2_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* void EnSth2_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx) { static Vec3f focusOffset = { 700.0f, 400.0f, 0.0f }; - if (limbIndex == OBJECT_STH_LIMB_0F) { + if (limbIndex == STH_LIMB_HEAD) { Matrix_MultVec3f(&focusOffset, &thisx->focus.pos); OPEN_DISPS(play->state.gfxCtx); diff --git a/src/overlays/actors/ovl_En_Sth2/z_en_sth2.h b/src/overlays/actors/ovl_En_Sth2/z_en_sth2.h index 265332ffd8..d8ecc9cdbe 100644 --- a/src/overlays/actors/ovl_En_Sth2/z_en_sth2.h +++ b/src/overlays/actors/ovl_En_Sth2/z_en_sth2.h @@ -11,8 +11,8 @@ typedef void (*EnSth2ActionFunc)(struct EnSth2*, PlayState*); typedef struct EnSth2 { /* 0x000 */ Actor actor; /* 0x144 */ SkelAnime skelAnime; - /* 0x188 */ Vec3s jointTable[OBJECT_STH_LIMB_MAX]; - /* 0x1E8 */ Vec3s morphTable[OBJECT_STH_LIMB_MAX]; + /* 0x188 */ Vec3s jointTable[STH_LIMB_MAX]; + /* 0x1E8 */ Vec3s morphTable[STH_LIMB_MAX]; /* 0x248 */ s16 unused; /* 0x24A */ u8 objIndex; /* 0x24C */ EnSth2ActionFunc actionFunc; diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt index 81eaf24484..0cada88236 100644 --- a/tools/disasm/functions.txt +++ b/tools/disasm/functions.txt @@ -14252,30 +14252,30 @@ 0x80B66BDC:("ObjHariko_Draw",), 0x80B66D30:("EnSth_Init",), 0x80B67010:("EnSth_Destroy",), - 0x80B6703C:("func_80B6703C",), - 0x80B670A4:("func_80B670A4",), - 0x80B67148:("func_80B67148",), - 0x80B671A0:("func_80B671A0",), - 0x80B67208:("func_80B67208",), - 0x80B672A4:("func_80B672A4",), - 0x80B67348:("func_80B67348",), - 0x80B67458:("func_80B67458",), - 0x80B67540:("func_80B67540",), - 0x80B677BC:("func_80B677BC",), - 0x80B67838:("func_80B67838",), - 0x80B678A8:("func_80B678A8",), - 0x80B67958:("func_80B67958",), - 0x80B67984:("func_80B67984",), - 0x80B67AB4:("func_80B67AB4",), - 0x80B67B50:("func_80B67B50",), - 0x80B67C1C:("func_80B67C1C",), - 0x80B67DA0:("func_80B67DA0",), - 0x80B67E20:("func_80B67E20",), - 0x80B67E78:("EnSth_Update",), - 0x80B680A8:("func_80B680A8",), - 0x80B681E8:("func_80B681E8",), - 0x80B68310:("func_80B68310",), - 0x80B6849C:("func_80B6849C",), + 0x80B6703C:("EnSth_CanSpeakToPlayer",), + 0x80B670A4:("EnSth_ChangeAnim",), + 0x80B67148:("EnSth_GetInitialPanicText",), + 0x80B671A0:("EnSth_HandlePanicConversation",), + 0x80B67208:("EnSth_PanicIdle",), + 0x80B672A4:("EnSth_GetInitialOceansideSpiderHouseText",), + 0x80B67348:("EnSth_PostOceanspiderhouseReward",), + 0x80B67458:("EnSth_GiveOceansideSpiderHouseReward",), + 0x80B67540:("EnSth_HandleOceansideSpiderHouseConversation",), + 0x80B677BC:("EnSth_OceansideSpiderHouseIdle",), + 0x80B67838:("EnSth_HandleMoonLookingConversation",), + 0x80B678A8:("EnSth_MoonLookingIdle",), + 0x80B67958:("EnSth_DefaultIdle",), + 0x80B67984:("EnSth_GetInitialSwampSpiderHouseText",), + 0x80B67AB4:("EnSth_TalkAfterSwampSpiderHouseGiveMask",), + 0x80B67B50:("EnSth_SwampSpiderHouseGiveMask",), + 0x80B67C1C:("EnSth_HandleSwampSpiderHouseConversation",), + 0x80B67DA0:("EnSth_SwampSpiderHouseIdle",), + 0x80B67E20:("EnSth_UpdateOceansideSpiderHouseWaitForTokens",), + 0x80B67E78:("EnSth_UpdateWaitForObject",), + 0x80B680A8:("EnSth_Update",), + 0x80B681E8:("EnSth_OverrideLimbDraw",), + 0x80B68310:("EnSth_PostLimbDraw",), + 0x80B6849C:("EnSth_Draw",), 0x80B6D660:("BgSinkaiKabe_Init",), 0x80B6D9EC:("BgSinkaiKabe_Destroy",), 0x80B6DA20:("BgSinkaiKabe_WaitForPlayer",), diff --git a/tools/weekeventregconvert.py b/tools/weekeventregconvert.py index fbefc1b3db..131dda4b82 100755 --- a/tools/weekeventregconvert.py +++ b/tools/weekeventregconvert.py @@ -113,9 +113,9 @@ weekEventReg = { (13 << 8) | 0x04: "WEEKEVENTREG_13_04", (13 << 8) | 0x08: "WEEKEVENTREG_13_08", (13 << 8) | 0x10: "WEEKEVENTREG_13_10", - (13 << 8) | 0x20: "WEEKEVENTREG_13_20", - (13 << 8) | 0x40: "WEEKEVENTREG_13_40", - (13 << 8) | 0x80: "WEEKEVENTREG_13_80", + (13 << 8) | 0x20: "WEEKEVENTREG_OCEANSIDE_SPIDER_HOUSE_BUYER_MOVED_IN", + (13 << 8) | 0x40: "WEEKEVENTREG_RECEIVED_OCEANSIDE_WALLET_UPGRADE", + (13 << 8) | 0x80: "WEEKEVENTREG_OCEANSIDE_SPIDER_HOUSE_COLLECTED_REWARD", (14 << 8) | 0x01: "WEEKEVENTREG_14_01", (14 << 8) | 0x02: "WEEKEVENTREG_14_02", (14 << 8) | 0x04: "WEEKEVENTREG_14_04", @@ -279,10 +279,10 @@ weekEventReg = { (34 << 8) | 0x01: "WEEKEVENTREG_34_01", (34 << 8) | 0x02: "WEEKEVENTREG_34_02", (34 << 8) | 0x04: "WEEKEVENTREG_34_04", - (34 << 8) | 0x08: "WEEKEVENTREG_34_08", + (34 << 8) | 0x08: "WEEKEVENTREG_SWAMP_SPIDER_HOUSE_TALKED", (34 << 8) | 0x10: "WEEKEVENTREG_34_10", (34 << 8) | 0x20: "WEEKEVENTREG_34_20", - (34 << 8) | 0x40: "WEEKEVENTREG_34_40", + (34 << 8) | 0x40: "WEEKEVENTREG_RECEIVED_MASK_OF_TRUTH", (34 << 8) | 0x80: "WEEKEVENTREG_34_80", (35 << 8) | 0x01: "WEEKEVENTREG_35_01", (35 << 8) | 0x02: "WEEKEVENTREG_35_02",