summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/code/z_message_PAL.c2
-rw-r--r--src/overlays/actors/ovl_En_Cow/z_en_cow.c265
-rw-r--r--src/overlays/actors/ovl_En_Cow/z_en_cow.h31
-rw-r--r--src/overlays/actors/ovl_En_Horse/z_en_horse.c14
-rw-r--r--src/overlays/actors/ovl_En_Horse_Link_Child/z_en_horse_link_child.c8
-rw-r--r--src/overlays/actors/ovl_En_Ma3/z_en_ma3.c6
-rw-r--r--src/overlays/actors/ovl_En_Niw/z_en_niw.c2
7 files changed, 193 insertions, 135 deletions
diff --git a/src/code/z_message_PAL.c b/src/code/z_message_PAL.c
index db9837569..36a1333ed 100644
--- a/src/code/z_message_PAL.c
+++ b/src/code/z_message_PAL.c
@@ -2486,7 +2486,7 @@ void Message_DrawMain(PlayState* play, Gfx** p) {
} else {
Message_CloseTextbox(play);
if (msgCtx->lastPlayedSong == OCARINA_SONG_EPONAS) {
- DREG(53) = 1;
+ R_EPONAS_SONG_PLAYED = true;
}
osSyncPrintf(VT_FGCOL(YELLOW));
osSyncPrintf("☆☆☆ocarina=%d message->ocarina_no=%d ", msgCtx->lastPlayedSong,
diff --git a/src/overlays/actors/ovl_En_Cow/z_en_cow.c b/src/overlays/actors/ovl_En_Cow/z_en_cow.c
index c3879516e..0f42827ed 100644
--- a/src/overlays/actors/ovl_En_Cow/z_en_cow.c
+++ b/src/overlays/actors/ovl_En_Cow/z_en_cow.c
@@ -5,7 +5,6 @@
*/
#include "z_en_cow.h"
-#include "assets/objects/object_cow/object_cow.h"
#define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3)
@@ -13,17 +12,19 @@ void EnCow_Init(Actor* thisx, PlayState* play);
void EnCow_Destroy(Actor* thisx, PlayState* play);
void EnCow_Update(Actor* thisx, PlayState* play2);
void EnCow_Draw(Actor* thisx, PlayState* play);
-void func_809DFE98(Actor* thisx, PlayState* play);
-void func_809E0070(Actor* thisx, PlayState* play);
-
-void func_809DF494(EnCow* this, PlayState* play);
-void func_809DF6BC(EnCow* this, PlayState* play);
-void func_809DF778(EnCow* this, PlayState* play);
-void func_809DF7D8(EnCow* this, PlayState* play);
-void func_809DF870(EnCow* this, PlayState* play);
-void func_809DF8FC(EnCow* this, PlayState* play);
-void func_809DF96C(EnCow* this, PlayState* play);
-void func_809DFA84(EnCow* this, PlayState* play);
+
+void EnCow_TalkEnd(EnCow* this, PlayState* play);
+void EnCow_GiveMilkEnd(EnCow* this, PlayState* play);
+void EnCow_GiveMilkWait(EnCow* this, PlayState* play);
+void EnCow_GiveMilk(EnCow* this, PlayState* play);
+void EnCow_CheckForEmptyBottle(EnCow* this, PlayState* play);
+void EnCow_UpdateAnimation(EnCow* this, PlayState* play);
+void EnCow_Talk(EnCow* this, PlayState* play);
+void EnCow_Idle(EnCow* this, PlayState* play);
+
+void EnCow_DrawTail(Actor* thisx, PlayState* play);
+void EnCow_UpdateTail(Actor* thisx, PlayState* play);
+void EnCow_IdleTail(EnCow* this, PlayState* play);
ActorInit En_Cow_InitVars = {
ACTOR_EN_COW,
@@ -57,45 +58,50 @@ static ColliderCylinderInit sCylinderInit = {
{ 30, 40, 0, { 0, 0, 0 } },
};
-static Vec3f D_809E010C = { 0.0f, -1300.0f, 1100.0f };
+static Vec3f sHeadFocusOffset = { 0.0f, -1300.0f, 1100.0f };
-void func_809DEE00(Vec3f* vec, s16 rotY) {
+void EnCow_RotateY(Vec3f* vec, s16 rotY) {
f32 xCalc;
f32 rotCalcTemp;
rotCalcTemp = Math_CosS(rotY);
xCalc = (Math_SinS(rotY) * vec->z) + (rotCalcTemp * vec->x);
rotCalcTemp = Math_SinS(rotY);
+
vec->z = (Math_CosS(rotY) * vec->z) + (-rotCalcTemp * vec->x);
vec->x = xCalc;
}
-void func_809DEE9C(EnCow* this) {
+void EnCow_SetColliderPos(EnCow* this) {
Vec3f vec;
vec.y = 0.0f;
vec.x = 0.0f;
vec.z = 30.0f;
- func_809DEE00(&vec, this->actor.shape.rot.y);
- this->colliders[0].dim.pos.x = this->actor.world.pos.x + vec.x;
- this->colliders[0].dim.pos.y = this->actor.world.pos.y;
- this->colliders[0].dim.pos.z = this->actor.world.pos.z + vec.z;
+
+ EnCow_RotateY(&vec, this->actor.shape.rot.y);
+
+ this->colliders[COW_COLLIDER_FRONT].dim.pos.x = this->actor.world.pos.x + vec.x;
+ this->colliders[COW_COLLIDER_FRONT].dim.pos.y = this->actor.world.pos.y;
+ this->colliders[COW_COLLIDER_FRONT].dim.pos.z = this->actor.world.pos.z + vec.z;
vec.x = 0.0f;
vec.y = 0.0f;
vec.z = -20.0f;
- func_809DEE00(&vec, this->actor.shape.rot.y);
- this->colliders[1].dim.pos.x = this->actor.world.pos.x + vec.x;
- this->colliders[1].dim.pos.y = this->actor.world.pos.y;
- this->colliders[1].dim.pos.z = this->actor.world.pos.z + vec.z;
+
+ EnCow_RotateY(&vec, this->actor.shape.rot.y);
+
+ this->colliders[COW_COLLIDER_REAR].dim.pos.x = this->actor.world.pos.x + vec.x;
+ this->colliders[COW_COLLIDER_REAR].dim.pos.y = this->actor.world.pos.y;
+ this->colliders[COW_COLLIDER_REAR].dim.pos.z = this->actor.world.pos.z + vec.z;
}
-void func_809DEF94(EnCow* this) {
+void EnCow_SetTailPos(EnCow* this) {
Vec3f vec;
VEC_SET(vec, 0.0f, 57.0f, -36.0f);
+ EnCow_RotateY(&vec, this->actor.shape.rot.y);
- func_809DEE00(&vec, this->actor.shape.rot.y);
this->actor.world.pos.x += vec.x;
this->actor.world.pos.y += vec.y;
this->actor.world.pos.z += vec.z;
@@ -106,188 +112,216 @@ void EnCow_Init(Actor* thisx, PlayState* play) {
s32 pad;
ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 72.0f);
- switch (this->actor.params) {
- case 0:
- SkelAnime_InitFlex(play, &this->skelAnime, &gCowBodySkel, NULL, this->jointTable, this->morphTable, 6);
+
+ switch (COW_GET_TYPE(this)) {
+ case COW_TYPE_BODY:
+ SkelAnime_InitFlex(play, &this->skelAnime, &gCowBodySkel, NULL, this->jointTable, this->morphTable,
+ COW_LIMB_MAX);
Animation_PlayLoop(&this->skelAnime, &gCowBodyChewAnim);
- Collider_InitCylinder(play, &this->colliders[0]);
- Collider_SetCylinder(play, &this->colliders[0], &this->actor, &sCylinderInit);
- Collider_InitCylinder(play, &this->colliders[1]);
- Collider_SetCylinder(play, &this->colliders[1], &this->actor, &sCylinderInit);
- func_809DEE9C(this);
- this->actionFunc = func_809DF96C;
+
+ Collider_InitCylinder(play, &this->colliders[COW_COLLIDER_FRONT]);
+ Collider_SetCylinder(play, &this->colliders[COW_COLLIDER_FRONT], &this->actor, &sCylinderInit);
+
+ Collider_InitCylinder(play, &this->colliders[COW_COLLIDER_REAR]);
+ Collider_SetCylinder(play, &this->colliders[COW_COLLIDER_REAR], &this->actor, &sCylinderInit);
+
+ EnCow_SetColliderPos(this);
+
+ this->actionFunc = EnCow_Idle;
+
if (play->sceneId == SCENE_LINKS_HOUSE) {
if (!LINK_IS_ADULT) {
Actor_Kill(&this->actor);
return;
}
- if (!GET_EVENTCHKINF(EVENTCHKINF_1E)) {
+
+ if (!GET_EVENTCHKINF(EVENTCHKINF_HORSE_RACE_COW_UNLOCK)) {
Actor_Kill(&this->actor);
return;
}
}
+
Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_EN_COW, this->actor.world.pos.x,
- this->actor.world.pos.y, this->actor.world.pos.z, 0, this->actor.shape.rot.y, 0, 1);
- this->unk_278 = Rand_ZeroFloat(1000.0f) + 40.0f;
- this->unk_27A = 0;
+ this->actor.world.pos.y, this->actor.world.pos.z, 0, this->actor.shape.rot.y, 0,
+ COW_TYPE_TAIL);
+ this->animationTimer = Rand_ZeroFloat(1000.0f) + 40.0f;
+ this->breathTimer = 0;
this->actor.targetMode = 6;
- DREG(53) = 0;
+ R_EPONAS_SONG_PLAYED = false;
break;
- case 1:
- SkelAnime_InitFlex(play, &this->skelAnime, &gCowTailSkel, NULL, this->jointTable, this->morphTable, 6);
+
+ case COW_TYPE_TAIL:
+ SkelAnime_InitFlex(play, &this->skelAnime, &gCowTailSkel, NULL, this->jointTable, this->morphTable,
+ COW_TAIL_LIMB_MAX);
Animation_PlayLoop(&this->skelAnime, &gCowTailIdleAnim);
- this->actor.update = func_809DFE98;
- this->actor.draw = func_809E0070;
- this->actionFunc = func_809DFA84;
- func_809DEF94(this);
+ this->actor.update = EnCow_UpdateTail;
+ this->actor.draw = EnCow_DrawTail;
+ this->actionFunc = EnCow_IdleTail;
+ EnCow_SetTailPos(this);
this->actor.flags &= ~ACTOR_FLAG_0;
- this->unk_278 = ((u32)(Rand_ZeroFloat(1000.0f)) & 0xFFFF) + 40.0f;
+ this->animationTimer = (u16)Rand_ZeroFloat(1000.0f) + 40.0f;
break;
}
+
this->actor.colChkInfo.mass = MASS_IMMOVABLE;
Actor_SetScale(&this->actor, 0.01f);
- this->unk_276 = 0;
+ this->cowFlags = 0;
}
void EnCow_Destroy(Actor* thisx, PlayState* play) {
EnCow* this = (EnCow*)thisx;
- if (this->actor.params == 0) {
- Collider_DestroyCylinder(play, &this->colliders[0]);
- Collider_DestroyCylinder(play, &this->colliders[1]);
+ if (COW_GET_TYPE(this) == COW_TYPE_BODY) {
+ Collider_DestroyCylinder(play, &this->colliders[COW_COLLIDER_FRONT]);
+ Collider_DestroyCylinder(play, &this->colliders[COW_COLLIDER_REAR]);
}
}
-void func_809DF494(EnCow* this, PlayState* play) {
- if (this->unk_278 > 0) {
- this->unk_278--;
+void EnCow_UpdateAnimation(EnCow* this, PlayState* play) {
+ if (this->animationTimer > 0) {
+ this->animationTimer--;
} else {
- this->unk_278 = Rand_ZeroFloat(500.0f) + 40.0f;
+ this->animationTimer = Rand_ZeroFloat(500.0f) + 40.0f;
Animation_Change(&this->skelAnime, &gCowBodyChewAnim, 1.0f, this->skelAnime.curFrame,
Animation_GetLastFrame(&gCowBodyChewAnim), ANIMMODE_ONCE, 1.0f);
}
- if ((this->actor.xzDistToPlayer < 150.0f) && !(this->unk_276 & 2)) {
- this->unk_276 |= 2;
- if (this->skelAnime.animation == &gCowBodyChewAnim) {
- this->unk_278 = 0;
+ if (this->actor.xzDistToPlayer < 150.0f) {
+ if (!(this->cowFlags & COW_FLAG_PLAYER_NEARBY)) {
+ this->cowFlags |= COW_FLAG_PLAYER_NEARBY;
+
+ if (this->skelAnime.animation == &gCowBodyChewAnim) {
+ this->animationTimer = 0;
+ }
}
}
- this->unk_27A++;
- if (this->unk_27A > 48) {
- this->unk_27A = 0;
+ this->breathTimer++;
+
+ if (this->breathTimer > 48) {
+ this->breathTimer = 0;
}
- // (1.0f / 100.0f) instead of 0.01f below is necessary so 0.01f doesn't get reused mistakenly
- if (this->unk_27A < 0x20) {
- this->actor.scale.x = ((Math_SinS(this->unk_27A << 0xA) * (1.0f / 100.0f)) + 1.0f) * 0.01f;
+ if (this->breathTimer < 32) {
+ this->actor.scale.x = ((Math_SinS(this->breathTimer * 0x0400) * (1.0f / 100.0f)) + 1.0f) * 0.01f;
} else {
this->actor.scale.x = 0.01f;
}
- if (this->unk_27A >= 0x11) {
- this->actor.scale.y = ((Math_SinS((this->unk_27A << 0xA) - 0x4000) * (1.0f / 100.0f)) + 1.0f) * 0.01f;
+ if (this->breathTimer > 16) {
+ this->actor.scale.y = ((Math_SinS((this->breathTimer * 0x0400) - 0x4000) * (1.0f / 100.0f)) + 1.0f) * 0.01f;
} else {
this->actor.scale.y = 0.01f;
}
}
-void func_809DF6BC(EnCow* this, PlayState* play) {
+void EnCow_TalkEnd(EnCow* this, PlayState* play) {
if ((Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(play)) {
this->actor.flags &= ~ACTOR_FLAG_16;
Message_CloseTextbox(play);
- this->actionFunc = func_809DF96C;
+ this->actionFunc = EnCow_Idle;
}
}
-void func_809DF730(EnCow* this, PlayState* play) {
+void EnCow_GiveMilkEnd(EnCow* this, PlayState* play) {
if (Actor_TextboxIsClosing(&this->actor, play)) {
this->actor.flags &= ~ACTOR_FLAG_16;
- this->actionFunc = func_809DF96C;
+ this->actionFunc = EnCow_Idle;
}
}
-void func_809DF778(EnCow* this, PlayState* play) {
+void EnCow_GiveMilkWait(EnCow* this, PlayState* play) {
if (Actor_HasParent(&this->actor, play)) {
this->actor.parent = NULL;
- this->actionFunc = func_809DF730;
+ this->actionFunc = EnCow_GiveMilkEnd;
} else {
Actor_OfferGetItem(&this->actor, play, GI_MILK, 10000.0f, 100.0f);
}
}
-void func_809DF7D8(EnCow* this, PlayState* play) {
+void EnCow_GiveMilk(EnCow* this, PlayState* play) {
if ((Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(play)) {
this->actor.flags &= ~ACTOR_FLAG_16;
Message_CloseTextbox(play);
- this->actionFunc = func_809DF778;
+ this->actionFunc = EnCow_GiveMilkWait;
Actor_OfferGetItem(&this->actor, play, GI_MILK, 10000.0f, 100.0f);
}
}
-void func_809DF870(EnCow* this, PlayState* play) {
+void EnCow_CheckForEmptyBottle(EnCow* this, PlayState* play) {
if ((Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(play)) {
if (Inventory_HasEmptyBottle()) {
Message_ContinueTextbox(play, 0x2007);
- this->actionFunc = func_809DF7D8;
+ this->actionFunc = EnCow_GiveMilk;
} else {
Message_ContinueTextbox(play, 0x2013);
- this->actionFunc = func_809DF6BC;
+ this->actionFunc = EnCow_TalkEnd;
}
}
}
-void func_809DF8FC(EnCow* this, PlayState* play) {
+void EnCow_Talk(EnCow* this, PlayState* play) {
if (Actor_ProcessTalkRequest(&this->actor, play)) {
- this->actionFunc = func_809DF870;
+ this->actionFunc = EnCow_CheckForEmptyBottle;
} else {
this->actor.flags |= ACTOR_FLAG_16;
func_8002F2CC(&this->actor, play, 170.0f);
this->actor.textId = 0x2006;
}
- func_809DF494(this, play);
+
+ EnCow_UpdateAnimation(this, play);
}
-void func_809DF96C(EnCow* this, PlayState* play) {
+void EnCow_Idle(EnCow* this, PlayState* play) {
if ((play->msgCtx.ocarinaMode == OCARINA_MODE_00) || (play->msgCtx.ocarinaMode == OCARINA_MODE_04)) {
- if (DREG(53) != 0) {
- if (this->unk_276 & 4) {
- this->unk_276 &= ~0x4;
- DREG(53) = 0;
+ // There is a complex interaction between `R_EPONAS_SONG_PLAYED` and `COW_FLAG_FAILED_TO_GIVE_MILK` to allow
+ // multiple cows to try and give milk on the same frame.
+ // `COW_FLAG_FAILED_TO_GIVE_MILK` gets set if this cow is not in range with the player to interact.
+ // In the case of a failure, `R_EPONAS_SONG_PLAYED` is not set to false in case another cow can succeed.
+ // On the following frame, if both `R_EPONAS_SONG_PLAYED` and `COW_FLAG_FAILED_TO_GIVE_MILK` are set, the
+ // first cow that updates can assume all other cows also failed and can safely unset `R_EPONAS_SONG_PLAYED`.
+ // All cows also unset their own `COW_FLAG_FAILED_TO_GIVE_MILK` flag.
+ if (R_EPONAS_SONG_PLAYED) {
+ if (this->cowFlags & COW_FLAG_FAILED_TO_GIVE_MILK) {
+ this->cowFlags &= ~COW_FLAG_FAILED_TO_GIVE_MILK;
+ R_EPONAS_SONG_PLAYED = false;
} else {
if ((this->actor.xzDistToPlayer < 150.0f) &&
- (ABS((s16)(this->actor.yawTowardsPlayer - this->actor.shape.rot.y)) < 0x61A8)) {
- DREG(53) = 0;
- this->actionFunc = func_809DF8FC;
+ (ABS((s16)(this->actor.yawTowardsPlayer - this->actor.shape.rot.y)) < 25000)) {
+ R_EPONAS_SONG_PLAYED = false;
+ this->actionFunc = EnCow_Talk;
this->actor.flags |= ACTOR_FLAG_16;
func_8002F2CC(&this->actor, play, 170.0f);
this->actor.textId = 0x2006;
} else {
- this->unk_276 |= 4;
+ this->cowFlags |= COW_FLAG_FAILED_TO_GIVE_MILK;
}
}
} else {
- this->unk_276 &= ~0x4;
+ this->cowFlags &= ~COW_FLAG_FAILED_TO_GIVE_MILK;
}
}
- func_809DF494(this, play);
+
+ EnCow_UpdateAnimation(this, play);
}
-void func_809DFA84(EnCow* this, PlayState* play) {
- if (this->unk_278 > 0) {
- this->unk_278--;
+void EnCow_IdleTail(EnCow* this, PlayState* play) {
+ if (this->animationTimer > 0) {
+ this->animationTimer--;
} else {
- this->unk_278 = Rand_ZeroFloat(200.0f) + 40.0f;
+ this->animationTimer = Rand_ZeroFloat(200.0f) + 40.0f;
Animation_Change(&this->skelAnime, &gCowTailIdleAnim, 1.0f, this->skelAnime.curFrame,
Animation_GetLastFrame(&gCowTailIdleAnim), ANIMMODE_ONCE, 1.0f);
}
if ((this->actor.xzDistToPlayer < 150.0f) &&
- (ABS((s16)(this->actor.yawTowardsPlayer - this->actor.shape.rot.y)) >= 0x61A9) && !(this->unk_276 & 2)) {
- this->unk_276 |= 2;
- if (this->skelAnime.animation == &gCowTailIdleAnim) {
- this->unk_278 = 0;
+ (ABS((s16)(this->actor.yawTowardsPlayer - this->actor.shape.rot.y)) > 25000)) {
+ if (!(this->cowFlags & COW_FLAG_PLAYER_NEARBY)) {
+ this->cowFlags |= COW_FLAG_PLAYER_NEARBY;
+
+ if (this->skelAnime.animation == &gCowTailIdleAnim) {
+ this->animationTimer = 0;
+ }
}
}
}
@@ -299,10 +333,12 @@ void EnCow_Update(Actor* thisx, PlayState* play2) {
s16 targetY;
Player* player = GET_PLAYER(play);
- CollisionCheck_SetOC(play, &play->colChkCtx, &this->colliders[0].base);
- CollisionCheck_SetOC(play, &play->colChkCtx, &this->colliders[1].base);
+ CollisionCheck_SetOC(play, &play->colChkCtx, &this->colliders[COW_COLLIDER_FRONT].base);
+ CollisionCheck_SetOC(play, &play->colChkCtx, &this->colliders[COW_COLLIDER_REAR].base);
+
Actor_MoveXZGravity(thisx);
Actor_UpdateBgCheckInfo(play, thisx, 0.0f, 0.0f, 0.0f, UPDBGCHECKINFO_FLAG_2);
+
if (SkelAnime_Update(&this->skelAnime)) {
if (this->skelAnime.animation == &gCowBodyChewAnim) {
Actor_PlaySfx(thisx, NA_SE_EV_COW_CRY);
@@ -313,7 +349,9 @@ void EnCow_Update(Actor* thisx, PlayState* play2) {
ANIMMODE_LOOP, 1.0f);
}
}
+
this->actionFunc(this, play);
+
if ((thisx->xzDistToPlayer < 150.0f) &&
(ABS(Math_Vec3f_Yaw(&thisx->world.pos, &player->actor.world.pos)) < 0xC000)) {
targetX = Math_Vec3f_Pitch(&thisx->focus.pos, &player->actor.focus.pos);
@@ -330,16 +368,16 @@ void EnCow_Update(Actor* thisx, PlayState* play2) {
} else if (targetY < -0x2500) {
targetY = -0x2500;
}
-
} else {
targetY = 0;
targetX = 0;
}
- Math_SmoothStepToS(&this->someRot.x, targetX, 0xA, 0xC8, 0xA);
- Math_SmoothStepToS(&this->someRot.y, targetY, 0xA, 0xC8, 0xA);
+
+ Math_SmoothStepToS(&this->headRot.x, targetX, 10, 200, 10);
+ Math_SmoothStepToS(&this->headRot.y, targetY, 10, 200, 10);
}
-void func_809DFE98(Actor* thisx, PlayState* play) {
+void EnCow_UpdateTail(Actor* thisx, PlayState* play) {
EnCow* this = (EnCow*)thisx;
s32 pad;
@@ -352,27 +390,30 @@ void func_809DFE98(Actor* thisx, PlayState* play) {
ANIMMODE_LOOP, 1.0f);
}
}
+
this->actionFunc(this, play);
}
s32 EnCow_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, void* thisx) {
EnCow* this = (EnCow*)thisx;
- if (limbIndex == 2) {
- rot->y += this->someRot.y;
- rot->x += this->someRot.x;
+ if (limbIndex == COW_LIMB_HEAD) {
+ rot->y += this->headRot.y;
+ rot->x += this->headRot.x;
}
- if (limbIndex == 5) {
+
+ if (limbIndex == COW_LIMB_NOSE_RING) {
*dList = NULL;
}
+
return false;
}
void EnCow_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx) {
EnCow* this = (EnCow*)thisx;
- if (limbIndex == 2) {
- Matrix_MultVec3f(&D_809E010C, &this->actor.focus.pos);
+ if (limbIndex == COW_LIMB_HEAD) {
+ Matrix_MultVec3f(&sHeadFocusOffset, &this->actor.focus.pos);
}
}
@@ -384,7 +425,7 @@ void EnCow_Draw(Actor* thisx, PlayState* play) {
EnCow_OverrideLimbDraw, EnCow_PostLimbDraw, this);
}
-void func_809E0070(Actor* thisx, PlayState* play) {
+void EnCow_DrawTail(Actor* thisx, PlayState* play) {
EnCow* this = (EnCow*)thisx;
Gfx_SetupDL_37Opa(play->state.gfxCtx);
diff --git a/src/overlays/actors/ovl_En_Cow/z_en_cow.h b/src/overlays/actors/ovl_En_Cow/z_en_cow.h
index 9fcc67c79..145d937f6 100644
--- a/src/overlays/actors/ovl_En_Cow/z_en_cow.h
+++ b/src/overlays/actors/ovl_En_Cow/z_en_cow.h
@@ -3,6 +3,23 @@
#include "ultra64.h"
#include "global.h"
+#include "assets/objects/object_cow/object_cow.h"
+
+#define COW_FLAG_PLAYER_NEARBY (1 << 1)
+#define COW_FLAG_FAILED_TO_GIVE_MILK (1 << 2)
+
+#define COW_GET_TYPE(thisx) ((thisx)->actor.params)
+
+typedef enum {
+ /* 0 */ COW_TYPE_BODY,
+ /* 1 */ COW_TYPE_TAIL
+} CowType;
+
+typedef enum {
+ /* 0 */ COW_COLLIDER_FRONT,
+ /* 1 */ COW_COLLIDER_REAR,
+ /* 2 */ COW_COLLIDER_MAX
+} CowCollider;
struct EnCow;
@@ -10,14 +27,14 @@ typedef void (*EnCowActionFunc)(struct EnCow*, PlayState*);
typedef struct EnCow {
/* 0x0000 */ Actor actor;
- /* 0x014C */ ColliderCylinder colliders[2];
+ /* 0x014C */ ColliderCylinder colliders[COW_COLLIDER_MAX];
/* 0x01E4 */ SkelAnime skelAnime;
- /* 0x0228 */ Vec3s jointTable[6];
- /* 0x024C */ Vec3s morphTable[6];
- /* 0x0270 */ Vec3s someRot;
- /* 0x0276 */ u16 unk_276;
- /* 0x0278 */ u16 unk_278;
- /* 0x027A */ u16 unk_27A;
+ /* 0x0228 */ Vec3s jointTable[COW_LIMB_MAX];
+ /* 0x024C */ Vec3s morphTable[COW_LIMB_MAX];
+ /* 0x0270 */ Vec3s headRot;
+ /* 0x0276 */ u16 cowFlags;
+ /* 0x0278 */ u16 animationTimer;
+ /* 0x027A */ u16 breathTimer;
/* 0x027C */ EnCowActionFunc actionFunc;
} EnCow; // size = 0x0280
diff --git a/src/overlays/actors/ovl_En_Horse/z_en_horse.c b/src/overlays/actors/ovl_En_Horse/z_en_horse.c
index edeb55195..cd87b114a 100644
--- a/src/overlays/actors/ovl_En_Horse/z_en_horse.c
+++ b/src/overlays/actors/ovl_En_Horse/z_en_horse.c
@@ -743,7 +743,7 @@ void EnHorse_Init(Actor* thisx, PlayState* play2) {
AREG(6) = 0;
Actor_ProcessInitChain(&this->actor, sInitChain);
EnHorse_ClearDustFlags(&this->dustFlags);
- DREG(53) = 0;
+ R_EPONAS_SONG_PLAYED = false;
this->riderPos = this->actor.world.pos;
this->noInputTimer = 0;
this->noInputTimerMax = 0;
@@ -1735,8 +1735,8 @@ void EnHorse_SetFollowAnimation(EnHorse* this, PlayState* play);
void EnHorse_Inactive(EnHorse* this, PlayState* play2) {
PlayState* play = play2;
- if (DREG(53) != 0 && this->type == HORSE_EPONA) {
- DREG(53) = 0;
+ if (R_EPONAS_SONG_PLAYED && this->type == HORSE_EPONA) {
+ R_EPONAS_SONG_PLAYED = false;
if (EnHorse_Spawn(this, play) != 0) {
Audio_PlaySfxGeneral(NA_SE_EV_HORSE_NEIGH, &this->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
@@ -1810,8 +1810,8 @@ void EnHorse_Idle(EnHorse* this, PlayState* play) {
this->actor.speed = 0.0f;
EnHorse_IdleAnimSounds(this, play);
- if (DREG(53) && this->type == HORSE_EPONA) {
- DREG(53) = 0;
+ if (R_EPONAS_SONG_PLAYED && this->type == HORSE_EPONA) {
+ R_EPONAS_SONG_PLAYED = false;
if (!func_80A5BBBC(play, this, &this->actor.world.pos)) {
if (EnHorse_Spawn(this, play)) {
Audio_PlaySfxGeneral(NA_SE_EV_HORSE_NEIGH, &this->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale,
@@ -1905,7 +1905,7 @@ void EnHorse_FollowPlayer(EnHorse* this, PlayState* play) {
f32 distToPlayer;
f32 angleDiff;
- DREG(53) = 0;
+ R_EPONAS_SONG_PLAYED = false;
distToPlayer = Actor_WorldDistXZToActor(&this->actor, &GET_PLAYER(play)->actor);
// First rotate if the player is behind
@@ -2597,7 +2597,7 @@ void EnHorse_FleePlayer(EnHorse* this, PlayState* play) {
s32 animFinished;
s16 yaw;
- if (DREG(53) || this->type == HORSE_HNI) {
+ if (R_EPONAS_SONG_PLAYED || this->type == HORSE_HNI) {
EnHorse_StartIdleRidable(this);
Audio_PlaySfxGeneral(NA_SE_EV_HORSE_NEIGH, &this->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
diff --git a/src/overlays/actors/ovl_En_Horse_Link_Child/z_en_horse_link_child.c b/src/overlays/actors/ovl_En_Horse_Link_Child/z_en_horse_link_child.c
index 13d0cc410..64c15537d 100644
--- a/src/overlays/actors/ovl_En_Horse_Link_Child/z_en_horse_link_child.c
+++ b/src/overlays/actors/ovl_En_Horse_Link_Child/z_en_horse_link_child.c
@@ -358,7 +358,7 @@ void func_80A6A068(EnHorseLinkChild* this, PlayState* play) {
return;
}
- if ((GET_EVENTCHKINF(EVENTCHKINF_16) && (DREG(53) != 0)) ||
+ if ((GET_EVENTCHKINF(EVENTCHKINF_16) && R_EPONAS_SONG_PLAYED) ||
((play->sceneId == SCENE_LON_LON_RANCH) && (gSaveContext.save.cutsceneIndex == 0xFFF1))) {
func_80A6A4DC(this);
} else {
@@ -434,7 +434,7 @@ void func_80A6A068(EnHorseLinkChild* this, PlayState* play) {
void func_80A6A4DC(EnHorseLinkChild* this) {
this->action = 5;
this->animationIdx = Rand_ZeroOne() > 0.5f ? 0 : 1;
- DREG(53) = 0;
+ R_EPONAS_SONG_PLAYED = false;
Animation_Change(&this->skin.skelAnime, sAnimations[this->animationIdx], func_80A695A4(this), 0.0f,
Animation_GetLastFrame(sAnimations[this->animationIdx]), ANIMMODE_ONCE, 0.0f);
}
@@ -442,8 +442,8 @@ void func_80A6A4DC(EnHorseLinkChild* this) {
void func_80A6A5A4(EnHorseLinkChild* this, PlayState* play) {
s16 yawDiff;
- if (DREG(53) != 0) {
- DREG(53) = 0;
+ if (R_EPONAS_SONG_PLAYED) {
+ R_EPONAS_SONG_PLAYED = false;
Audio_PlaySfxGeneral(NA_SE_EV_KID_HORSE_NEIGH, &this->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale,
&gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
func_80A6A724(this);
diff --git a/src/overlays/actors/ovl_En_Ma3/z_en_ma3.c b/src/overlays/actors/ovl_En_Ma3/z_en_ma3.c
index 43c19df76..caccc853f 100644
--- a/src/overlays/actors/ovl_En_Ma3/z_en_ma3.c
+++ b/src/overlays/actors/ovl_En_Ma3/z_en_ma3.c
@@ -87,7 +87,7 @@ u16 EnMa3_GetTextId(PlayState* play, Actor* thisx) {
HIGH_SCORE(HS_HORSE_RACE) = 180;
}
- if (!GET_EVENTCHKINF(EVENTCHKINF_1E) && (((void)0, gSaveContext.timerSeconds) < 50)) {
+ if (!GET_EVENTCHKINF(EVENTCHKINF_HORSE_RACE_COW_UNLOCK) && (((void)0, gSaveContext.timerSeconds) < 50)) {
return 0x208F;
}
@@ -128,7 +128,7 @@ s16 EnMa3_UpdateTalkState(PlayState* play, Actor* thisx) {
if (Message_ShouldAdvance(play)) {
SET_INFTABLE(INFTABLE_B9);
if (play->msgCtx.choiceIndex == 0) {
- if (GET_EVENTCHKINF(EVENTCHKINF_1E)) {
+ if (GET_EVENTCHKINF(EVENTCHKINF_HORSE_RACE_COW_UNLOCK)) {
Message_ContinueTextbox(play, 0x2091);
} else if (HIGH_SCORE(HS_HORSE_RACE) == 0) {
Message_ContinueTextbox(play, 0x2092);
@@ -145,7 +145,7 @@ s16 EnMa3_UpdateTalkState(PlayState* play, Actor* thisx) {
talkState = NPC_TALK_STATE_IDLE;
break;
case 0x208F:
- SET_EVENTCHKINF(EVENTCHKINF_1E);
+ SET_EVENTCHKINF(EVENTCHKINF_HORSE_RACE_COW_UNLOCK);
FALLTHROUGH;
case 0x2004:
case 0x2012:
diff --git a/src/overlays/actors/ovl_En_Niw/z_en_niw.c b/src/overlays/actors/ovl_En_Niw/z_en_niw.c
index dd9a4da1f..8c05a3636 100644
--- a/src/overlays/actors/ovl_En_Niw/z_en_niw.c
+++ b/src/overlays/actors/ovl_En_Niw/z_en_niw.c
@@ -229,7 +229,7 @@ void EnNiw_Init(Actor* thisx, PlayState* play) {
case 0xD:
case 0xE:
Collider_SetCylinder(play, &this->collider, &this->actor, &sCylinderInit2);
- if (play->sceneId == SCENE_LINKS_HOUSE && !GET_EVENTCHKINF(EVENTCHKINF_1E)) {
+ if (play->sceneId == SCENE_LINKS_HOUSE && !GET_EVENTCHKINF(EVENTCHKINF_HORSE_RACE_COW_UNLOCK)) {
Actor_Kill(&this->actor);
}
break;