1
0
Fork 0
mirror of https://github.com/zeldaret/oot.git synced 2025-06-08 09:31:52 +00:00
This commit is contained in:
hiisuya 2025-06-08 00:27:36 +09:00 committed by GitHub
commit b231b04a9b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 87 additions and 69 deletions

View file

@ -782,9 +782,9 @@ typedef enum LinkAge {
#define INFTABLE_TALKED_TO_MALON_FIRST_TIME 0x84 #define INFTABLE_TALKED_TO_MALON_FIRST_TIME 0x84
#define INFTABLE_TOLD_EPONA_IS_SCARED 0x85 #define INFTABLE_TOLD_EPONA_IS_SCARED 0x85
#define INFTABLE_MALON_SPAWNED_AT_HYRULE_CASTLE 0x8B #define INFTABLE_MALON_SPAWNED_AT_HYRULE_CASTLE 0x8B
#define INFTABLE_8C 0x8C #define INFTABLE_TALKED_TO_ADULT_MALON_AFTER_SONG 0x8C
#define INFTABLE_8D 0x8D #define INFTABLE_8D 0x8D // unreachable flag in EnMa2
#define INFTABLE_8E 0x8E #define INFTABLE_PLAYED_SONG_FOR_ADULT_MALON 0x8E
#define INFTABLE_94 0x94 #define INFTABLE_94 0x94
#define INFTABLE_97 0x97 #define INFTABLE_97 0x97
#define INFTABLE_9A 0x9A #define INFTABLE_9A 0x9A

View file

@ -1,3 +1,9 @@
/*
* File: z_en_ma2.c
* Overlay: En_Ma2
* Description: Adult Malon (Stables / Ranch Pre-Epona)
*/
#include "z_en_ma2.h" #include "z_en_ma2.h"
#include "gfx.h" #include "gfx.h"
@ -25,14 +31,14 @@ void EnMa2_Destroy(Actor* thisx, PlayState* play);
void EnMa2_Update(Actor* thisx, PlayState* play); void EnMa2_Update(Actor* thisx, PlayState* play);
void EnMa2_Draw(Actor* thisx, PlayState* play); void EnMa2_Draw(Actor* thisx, PlayState* play);
void func_80AA1AE4(EnMa2* this, PlayState* play); void EnMa2_UpdateTracking(EnMa2* this, PlayState* play);
s32 func_80AA1C68(EnMa2* this); s32 EnMa2_IsSinging(EnMa2* this);
void EnMa2_UpdateEyes(EnMa2* this); void EnMa2_UpdateEyes(EnMa2* this);
void func_80AA1DB4(EnMa2* this, PlayState* play); void EnMa2_UpdateSinging(EnMa2* this, PlayState* play);
void func_80AA2018(EnMa2* this, PlayState* play); void EnMa2_WaitToEndTalk(EnMa2* this, PlayState* play);
void func_80AA204C(EnMa2* this, PlayState* play); void EnMa2_WaitForOcarina(EnMa2* this, PlayState* play);
void func_80AA20E4(EnMa2* this, PlayState* play); void EnMa2_WaitForEponasSong(EnMa2* this, PlayState* play);
void func_80AA21C8(EnMa2* this, PlayState* play); void EnMa2_ForceTalkAfterSong(EnMa2* this, PlayState* play);
ActorProfile En_Ma2_Profile = { ActorProfile En_Ma2_Profile = {
/**/ ACTOR_EN_MA2, /**/ ACTOR_EN_MA2,
@ -69,11 +75,11 @@ static ColliderCylinderInit sCylinderInit = {
static CollisionCheckInfoInit2 sColChkInfoInit = { 0, 0, 0, 0, MASS_IMMOVABLE }; static CollisionCheckInfoInit2 sColChkInfoInit = { 0, 0, 0, 0, MASS_IMMOVABLE };
typedef enum EnMa2Animation { typedef enum EnMa2Animation {
/* 0 */ ENMA2_ANIM_0, /* 0 */ MALON_ADULT_ANIM_IDLE,
/* 1 */ ENMA2_ANIM_1, /* 1 */ MALON_ADULT_ANIM_IDLE_NOMORPH,
/* 2 */ ENMA2_ANIM_2, /* 2 */ MALON_ADULT_ANIM_STANDING,
/* 3 */ ENMA2_ANIM_3, /* 3 */ MALON_ADULT_ANIM_SING,
/* 4 */ ENMA2_ANIM_4 /* 4 */ MALON_ADULT_ANIM_SING_NOMORPH
} EnMa2Animation; } EnMa2Animation;
static AnimationFrameCountInfo sAnimationInfo[] = { static AnimationFrameCountInfo sAnimationInfo[] = {
@ -92,9 +98,9 @@ u16 EnMa2_GetTextId(PlayState* play, Actor* thisx) {
return 0x2056; return 0x2056;
} }
if (IS_NIGHT) { if (IS_NIGHT) {
if (GET_INFTABLE(INFTABLE_8C)) { if (GET_INFTABLE(INFTABLE_TALKED_TO_ADULT_MALON_AFTER_SONG)) {
return 0x2052; return 0x2052;
} else if (GET_INFTABLE(INFTABLE_8E)) { } else if (GET_INFTABLE(INFTABLE_PLAYED_SONG_FOR_ADULT_MALON)) {
return 0x2051; return 0x2051;
} else { } else {
return 0x2050; return 0x2050;
@ -110,9 +116,10 @@ s16 EnMa2_UpdateTalkState(PlayState* play, Actor* thisx) {
case TEXT_STATE_CLOSING: case TEXT_STATE_CLOSING:
switch (thisx->textId) { switch (thisx->textId) {
case 0x2051: case 0x2051:
SET_INFTABLE(INFTABLE_8C); SET_INFTABLE(INFTABLE_TALKED_TO_ADULT_MALON_AFTER_SONG);
talkState = NPC_TALK_STATE_ACTION; talkState = NPC_TALK_STATE_ACTION;
break; break;
// unreachable, 0x2053 is a text id for Gossip Stones, which EnMa2 never sets
case 0x2053: case 0x2053:
SET_INFTABLE(INFTABLE_8D); SET_INFTABLE(INFTABLE_8D);
talkState = NPC_TALK_STATE_IDLE; talkState = NPC_TALK_STATE_IDLE;
@ -135,7 +142,7 @@ s16 EnMa2_UpdateTalkState(PlayState* play, Actor* thisx) {
return talkState; return talkState;
} }
void func_80AA1AE4(EnMa2* this, PlayState* play) { void EnMa2_UpdateTracking(EnMa2* this, PlayState* play) {
Player* player = GET_PLAYER(play); Player* player = GET_PLAYER(play);
s16 trackingMode; s16 trackingMode;
@ -151,47 +158,58 @@ void func_80AA1AE4(EnMa2* this, PlayState* play) {
Npc_TrackPoint(&this->actor, &this->interactInfo, 0, trackingMode); Npc_TrackPoint(&this->actor, &this->interactInfo, 0, trackingMode);
} }
u16 func_80AA1B58(EnMa2* this, PlayState* play) { typedef enum {
MALON_ADULT_SPAWN_NONE = 0,
MALON_ADULT_SPAWN_DAY_STABLES_NO_EPONA,
MALON_ADULT_SPAWN_NIGHT_RANCH_NO_EPONA,
MALON_ADULT_SPAWN_ALWAYS
} EnMa2SpawnIndex;
u16 EnMa2_GetSpawnIndex(EnMa2* this, PlayState* play) {
if (LINK_IS_CHILD) { if (LINK_IS_CHILD) {
return 0; return MALON_ADULT_SPAWN_NONE;
} }
if (!GET_EVENTCHKINF(EVENTCHKINF_EPONA_OBTAINED) && (play->sceneId == SCENE_STABLE) && IS_DAY && if (!GET_EVENTCHKINF(EVENTCHKINF_EPONA_OBTAINED) && (play->sceneId == SCENE_STABLE) && IS_DAY &&
(this->actor.shape.rot.z == 5)) { (this->actor.shape.rot.z == 5)) {
return 1; return MALON_ADULT_SPAWN_DAY_STABLES_NO_EPONA;
} }
if (!GET_EVENTCHKINF(EVENTCHKINF_EPONA_OBTAINED) && (play->sceneId == SCENE_LON_LON_RANCH) && IS_NIGHT && if (!GET_EVENTCHKINF(EVENTCHKINF_EPONA_OBTAINED) && (play->sceneId == SCENE_LON_LON_RANCH) && IS_NIGHT &&
(this->actor.shape.rot.z == 6)) { (this->actor.shape.rot.z == 6)) {
return 2; return MALON_ADULT_SPAWN_NIGHT_RANCH_NO_EPONA;
} }
if (!GET_EVENTCHKINF(EVENTCHKINF_EPONA_OBTAINED) || (play->sceneId != SCENE_LON_LON_RANCH)) { if (!GET_EVENTCHKINF(EVENTCHKINF_EPONA_OBTAINED) || (play->sceneId != SCENE_LON_LON_RANCH)) {
return 0; return MALON_ADULT_SPAWN_NONE;
} }
if ((this->actor.shape.rot.z == 7) && IS_DAY) { if ((this->actor.shape.rot.z == 7) && IS_DAY) {
return 3; return MALON_ADULT_SPAWN_ALWAYS;
} }
if ((this->actor.shape.rot.z == 8) && IS_NIGHT) { if ((this->actor.shape.rot.z == 8) && IS_NIGHT) {
return 3; return MALON_ADULT_SPAWN_ALWAYS;
} }
return 0; return MALON_ADULT_SPAWN_NONE;
} }
s32 func_80AA1C68(EnMa2* this) { s32 EnMa2_IsSinging(EnMa2* this) {
if (this->skelAnime.animation != &gMalonAdultSingAnim) { if (this->skelAnime.animation != &gMalonAdultSingAnim) {
return 0; return false;
} }
if (this->interactInfo.talkState != NPC_TALK_STATE_IDLE) { if (this->interactInfo.talkState != NPC_TALK_STATE_IDLE) {
return 0; return false;
} }
this->blinkTimer = 0; this->blinkTimer = 0;
if (this->eyeIndex != 2) { if (this->eyeIndex != 2) {
return 0; return false;
} }
this->mouthIndex = 2; this->mouthIndex = 2;
return 1; return true;
} }
void EnMa2_UpdateEyes(EnMa2* this) { void EnMa2_UpdateEyes(EnMa2* this) {
if ((!func_80AA1C68(this)) && (DECR(this->blinkTimer) == 0)) { if ((!EnMa2_IsSinging(this)) && (DECR(this->blinkTimer) == 0)) {
this->eyeIndex++; this->eyeIndex++;
if (this->eyeIndex >= 3) { if (this->eyeIndex >= 3) {
this->blinkTimer = Rand_S16Offset(30, 30); this->blinkTimer = Rand_S16Offset(30, 30);
@ -207,19 +225,19 @@ void EnMa2_ChangeAnim(EnMa2* this, s32 index) {
sAnimationInfo[index].mode, sAnimationInfo[index].morphFrames); sAnimationInfo[index].mode, sAnimationInfo[index].morphFrames);
} }
void func_80AA1DB4(EnMa2* this, PlayState* play) { void EnMa2_UpdateSinging(EnMa2* this, PlayState* play) {
if (this->skelAnime.animation == &gMalonAdultSingAnim) { if (this->skelAnime.animation == &gMalonAdultSingAnim) {
if (this->interactInfo.talkState == NPC_TALK_STATE_IDLE) { if (this->interactInfo.talkState == NPC_TALK_STATE_IDLE) {
if (this->isNotSinging) { if (this->singingDisabled) {
// Turn on singing // Turn on singing
Audio_ToggleMalonSinging(false); Audio_ToggleMalonSinging(false);
this->isNotSinging = false; this->singingDisabled = false;
} }
} else { } else {
if (!this->isNotSinging) { if (!this->singingDisabled) {
// Turn off singing // Turn off singing
Audio_ToggleMalonSinging(true); Audio_ToggleMalonSinging(true);
this->isNotSinging = true; this->singingDisabled = true;
} }
} }
} }
@ -235,24 +253,24 @@ void EnMa2_Init(Actor* thisx, PlayState* play) {
Collider_SetCylinder(play, &this->collider, &this->actor, &sCylinderInit); Collider_SetCylinder(play, &this->collider, &this->actor, &sCylinderInit);
CollisionCheck_SetInfo2(&this->actor.colChkInfo, DamageTable_Get(22), &sColChkInfoInit); CollisionCheck_SetInfo2(&this->actor.colChkInfo, DamageTable_Get(22), &sColChkInfoInit);
switch (func_80AA1B58(this, play)) { switch (EnMa2_GetSpawnIndex(this, play)) {
case 1: case MALON_ADULT_SPAWN_DAY_STABLES_NO_EPONA:
EnMa2_ChangeAnim(this, ENMA2_ANIM_2); EnMa2_ChangeAnim(this, MALON_ADULT_ANIM_STANDING);
this->actionFunc = func_80AA2018; this->actionFunc = EnMa2_WaitToEndTalk;
break; break;
case 2: case MALON_ADULT_SPAWN_NIGHT_RANCH_NO_EPONA:
EnMa2_ChangeAnim(this, ENMA2_ANIM_3); EnMa2_ChangeAnim(this, MALON_ADULT_ANIM_SING);
this->actionFunc = func_80AA204C; this->actionFunc = EnMa2_WaitForOcarina;
break; break;
case 3: case MALON_ADULT_SPAWN_ALWAYS:
if (GET_INFTABLE(INFTABLE_8D)) { if (GET_INFTABLE(INFTABLE_8D)) {
EnMa2_ChangeAnim(this, ENMA2_ANIM_0); EnMa2_ChangeAnim(this, MALON_ADULT_ANIM_IDLE);
} else { } else {
EnMa2_ChangeAnim(this, ENMA2_ANIM_3); EnMa2_ChangeAnim(this, MALON_ADULT_ANIM_SING);
} }
this->actionFunc = func_80AA2018; this->actionFunc = EnMa2_WaitToEndTalk;
break; break;
case 0: case MALON_ADULT_SPAWN_NONE:
Actor_Kill(&this->actor); Actor_Kill(&this->actor);
return; return;
} }
@ -270,48 +288,48 @@ void EnMa2_Destroy(Actor* thisx, PlayState* play) {
Collider_DestroyCylinder(play, &this->collider); Collider_DestroyCylinder(play, &this->collider);
} }
void func_80AA2018(EnMa2* this, PlayState* play) { void EnMa2_WaitToEndTalk(EnMa2* this, PlayState* play) {
if (this->interactInfo.talkState == NPC_TALK_STATE_ACTION) { if (this->interactInfo.talkState == NPC_TALK_STATE_ACTION) {
this->actor.flags &= ~ACTOR_FLAG_TALK_OFFER_AUTO_ACCEPTED; this->actor.flags &= ~ACTOR_FLAG_TALK_OFFER_AUTO_ACCEPTED;
this->interactInfo.talkState = NPC_TALK_STATE_IDLE; this->interactInfo.talkState = NPC_TALK_STATE_IDLE;
} }
} }
void func_80AA204C(EnMa2* this, PlayState* play) { void EnMa2_WaitForOcarina(EnMa2* this, PlayState* play) {
Player* player = GET_PLAYER(play); Player* player = GET_PLAYER(play);
if (player->stateFlags2 & PLAYER_STATE2_24) { if (player->stateFlags2 & PLAYER_STATE2_24) {
player->stateFlags2 |= PLAYER_STATE2_25; player->stateFlags2 |= PLAYER_STATE2_25;
player->unk_6A8 = &this->actor; player->unk_6A8 = &this->actor;
Message_StartOcarina(play, OCARINA_ACTION_CHECK_EPONA); Message_StartOcarina(play, OCARINA_ACTION_CHECK_EPONA);
this->actionFunc = func_80AA20E4; this->actionFunc = EnMa2_WaitForEponasSong;
} else if (this->actor.xzDistToPlayer < 30.0f + this->collider.dim.radius) { } else if (this->actor.xzDistToPlayer < 30.0f + this->collider.dim.radius) {
player->stateFlags2 |= PLAYER_STATE2_23; player->stateFlags2 |= PLAYER_STATE2_23;
} }
} }
void func_80AA20E4(EnMa2* this, PlayState* play) { void EnMa2_WaitForEponasSong(EnMa2* this, PlayState* play) {
Player* player = GET_PLAYER(play); Player* player = GET_PLAYER(play);
if (play->msgCtx.ocarinaMode >= OCARINA_MODE_04) { if (play->msgCtx.ocarinaMode >= OCARINA_MODE_04) {
this->actionFunc = func_80AA204C; this->actionFunc = EnMa2_WaitForOcarina;
play->msgCtx.ocarinaMode = OCARINA_MODE_04; play->msgCtx.ocarinaMode = OCARINA_MODE_04;
} else if (play->msgCtx.ocarinaMode == OCARINA_MODE_03) { } else if (play->msgCtx.ocarinaMode == OCARINA_MODE_03) {
Audio_PlaySfxGeneral(NA_SE_SY_CORRECT_CHIME, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, Audio_PlaySfxGeneral(NA_SE_SY_CORRECT_CHIME, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
this->unk_208 = 0x1E; this->timer = 0x1E;
SET_INFTABLE(INFTABLE_8E); SET_INFTABLE(INFTABLE_PLAYED_SONG_FOR_ADULT_MALON);
this->actionFunc = func_80AA21C8; this->actionFunc = EnMa2_ForceTalkAfterSong;
play->msgCtx.ocarinaMode = OCARINA_MODE_04; play->msgCtx.ocarinaMode = OCARINA_MODE_04;
} else { } else {
player->stateFlags2 |= PLAYER_STATE2_23; player->stateFlags2 |= PLAYER_STATE2_23;
} }
} }
void func_80AA21C8(EnMa2* this, PlayState* play) { void EnMa2_ForceTalkAfterSong(EnMa2* this, PlayState* play) {
Player* player = GET_PLAYER(play); Player* player = GET_PLAYER(play);
if (DECR(this->unk_208)) { if (DECR(this->timer)) {
player->stateFlags2 |= PLAYER_STATE2_23; player->stateFlags2 |= PLAYER_STATE2_23;
} else { } else {
if (this->interactInfo.talkState == NPC_TALK_STATE_IDLE) { if (this->interactInfo.talkState == NPC_TALK_STATE_IDLE) {
@ -319,7 +337,7 @@ void func_80AA21C8(EnMa2* this, PlayState* play) {
Message_CloseTextbox(play); Message_CloseTextbox(play);
} else { } else {
this->actor.flags &= ~ACTOR_FLAG_TALK_OFFER_AUTO_ACCEPTED; this->actor.flags &= ~ACTOR_FLAG_TALK_OFFER_AUTO_ACCEPTED;
this->actionFunc = func_80AA2018; this->actionFunc = EnMa2_WaitToEndTalk;
} }
} }
} }
@ -333,9 +351,9 @@ void EnMa2_Update(Actor* thisx, PlayState* play) {
SkelAnime_Update(&this->skelAnime); SkelAnime_Update(&this->skelAnime);
EnMa2_UpdateEyes(this); EnMa2_UpdateEyes(this);
this->actionFunc(this, play); this->actionFunc(this, play);
func_80AA1DB4(this, play); EnMa2_UpdateSinging(this, play);
func_80AA1AE4(this, play); EnMa2_UpdateTracking(this, play);
if (this->actionFunc != func_80AA20E4) { if (this->actionFunc != EnMa2_WaitForEponasSong) {
Npc_UpdateTalking(play, &this->actor, &this->interactInfo.talkState, this->collider.dim.radius + 30.0f, Npc_UpdateTalking(play, &this->actor, &this->interactInfo.talkState, this->collider.dim.radius + 30.0f,
EnMa2_GetTextId, EnMa2_UpdateTalkState); EnMa2_GetTextId, EnMa2_UpdateTalkState);
} }
@ -362,8 +380,8 @@ s32 EnMa2_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* p
} }
if ((limbIndex == MALON_ADULT_CHEST_AND_NECK_LIMB) || (limbIndex == MALON_ADULT_LEFT_SHOULDER_LIMB) || if ((limbIndex == MALON_ADULT_CHEST_AND_NECK_LIMB) || (limbIndex == MALON_ADULT_LEFT_SHOULDER_LIMB) ||
(limbIndex == MALON_ADULT_RIGHT_SHOULDER_LIMB)) { (limbIndex == MALON_ADULT_RIGHT_SHOULDER_LIMB)) {
rot->y += Math_SinS(this->unk_212[limbIndex].y) * 200.0f; rot->y += Math_SinS(this->upperBodyRot[limbIndex].y) * 200.0f;
rot->z += Math_CosS(this->unk_212[limbIndex].z) * 200.0f; rot->z += Math_CosS(this->upperBodyRot[limbIndex].z) * 200.0f;
} }
return false; return false;
} }

View file

@ -37,12 +37,12 @@ typedef struct EnMa2 {
/* 0x0190 */ EnMa2ActionFunc actionFunc; /* 0x0190 */ EnMa2ActionFunc actionFunc;
/* 0x0194 */ ColliderCylinder collider; /* 0x0194 */ ColliderCylinder collider;
/* 0x01E0 */ NpcInteractInfo interactInfo; /* 0x01E0 */ NpcInteractInfo interactInfo;
/* 0x0208 */ s16 unk_208; /* 0x0208 */ s16 timer;
/* 0x020A */ s16 isNotSinging; /* 0x020A */ s16 singingDisabled;
/* 0x020C */ s16 blinkTimer; /* 0x020C */ s16 blinkTimer;
/* 0x020E */ s16 eyeIndex; /* 0x020E */ s16 eyeIndex;
/* 0x0210 */ s16 mouthIndex; /* 0x0210 */ s16 mouthIndex;
/* 0x0212 */ Vec3s unk_212[MALON_ADULT_LIMB_MAX]; /* 0x0212 */ Vec3s upperBodyRot[MALON_ADULT_LIMB_MAX];
} EnMa2; // size = 0x0284 } EnMa2; // size = 0x0284
#endif #endif