En_Cow 🐮 (#493)

* OK

* Address feedback

* Adjust comparison
This commit is contained in:
Rozelette 2021-12-01 11:32:15 -06:00 committed by GitHub
parent ce1de034df
commit 56d76d6458
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 430 additions and 52 deletions

View File

@ -533,7 +533,7 @@ void func_800AE5E4(GlobalContext* globalCtx, Color_RGBA8* arg1, s16 arg2, s16 ar
void func_800AE778(GlobalContext* globalCtx, Color_RGBA8* color, s16 param_3, s16 param_4);
void func_800AE8EC(GlobalContext* globalCtx);
void func_800AE930(CollisionContext* colCtx, s32 param_2, Vec3f* param_3, f32 param_4, s16 param_5, CollisionPoly* param_6, s32 param_7);
void func_800AEF44(s32 arg0);
void func_800AEF44(s32 arg0);
void EffectTireMark_InitParticle(EffTireMarkParticle* particle);
void EffectTireMark_Init(EffTireMarkParams* params, EffTireMarkInit* init);
void EffectTireMark_Destroy(EffTireMarkParams* params);
@ -2754,11 +2754,11 @@ void func_801420C0(void* arg0);
void func_801420F4(void* arg0);
void func_80142100(void* arg0, Gfx** gfx, u32 arg2);
s32 func_80142440(SkyboxContext* skyboxCtx, Vtx* vtx, s32 arg2, s32 arg3, s32 arg4, s32 arg5, s32 arg6, s32 arg7,
s32 arg8);
void func_80143148(SkyboxContext* skyboxCtx, s32 arg1);
void func_801431E8(GameState* gameState, SkyboxContext* skyboxCtx, s16 skyType);
s32 arg8);
void func_80143148(SkyboxContext* skyboxCtx, s32 arg1);
void func_801431E8(GameState* gameState, SkyboxContext* skyboxCtx, s16 skyType);
void func_80143324(GlobalContext* globalCtx, SkyboxContext* skyboxCtx, s16 skyType);
void func_801434E4(GameState* gameState, SkyboxContext* skyboxCtx, s16 skyType);
void func_801434E4(GameState* gameState, SkyboxContext* skyboxCtx, s16 skyType);
// void func_801435A0(void);
// void func_80143624(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE1 param_5, UNK_TYPE1 param_6, UNK_TYPE1 param_7);
// void func_80143668(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE4 param_5, UNK_TYPE4 param_6, UNK_TYPE4 param_7);
@ -3192,7 +3192,7 @@ void Sched_Init(SchedContext* sched, void* stack, OSPri pri, UNK_TYPE arg3, UNK_
void func_801773A0(void* arg0);
void func_801773C4(void* arg0);
void SpeedMeter_DrawTimeEntries(void* displayList, GraphicsContext* gfxCtx);
// void func_80177A84(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE2 param_5, UNK_TYPE4 param_6, UNK_TYPE4 param_7, UNK_TYPE4 param_8, UNK_TYPE4 param_9);
// void func_80177A84(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE2 param_5, UNK_TYPE4 param_6, UNK_TYPE4 param_7, UNK_TYPE4 param_8, UNK_TYPE4 param_9);
//void func_80177AC8(void);
void SpeedMeter_DrawAllocEntries(void* displayList, GraphicsContext* gfxCtx, GameState* gameState);
void func_801780F0(Mtx* param_1, f32 param_2, f32 param_3, f32 param_4, f32 param_5, f32 param_6, f32 param_7);
@ -3932,8 +3932,8 @@ void func_801A4D00(void);
// void func_801A4EB0(void);
// void func_801A4EB8(void);
// void func_801A4FD8(void);
// void func_801A5080(void);
// void func_801A5100(void);
void func_801A5080(u16 arg0);
u16 func_801A5100(void);
// void func_801A5118(void);
UNK_TYPE func_801A51F0(UNK_TYPE arg0);
// void func_801A5228(void);

View File

@ -912,7 +912,7 @@ extern s32 graphNumGameStates;
// extern UNK_TYPE2 D_801BDA7C;
extern s32 D_801BDA9C;
extern UNK_TYPE4 D_801BDAA0;
// extern UNK_TYPE4 D_801BDAA4;
extern UNK_TYPE4 D_801BDAA4;
// extern UNK_TYPE2 D_801BDAA8;
// extern UNK_TYPE2 D_801BDAAA;
// extern UNK_TYPE2 D_801BDAAC;

View File

@ -327,6 +327,7 @@ typedef enum {
/* 0x8D */ GI_MASK_BLAST,
/* 0x8E */ GI_MASK_SCENTS,
/* 0x8F */ GI_MASK_GIANT,
/* 0x92 */ GI_MILK = 0x92,
/* 0x96 */ GI_MOON_TEAR = 0x96,
/* 0x97 */ GI_DEED_LAND,
/* 0x98 */ GI_DEED_SWAMP,

3
spec
View File

@ -2229,8 +2229,7 @@ beginseg
name "ovl_En_Cow"
compress
include "build/src/overlays/actors/ovl_En_Cow/z_en_cow.o"
include "build/data/ovl_En_Cow/ovl_En_Cow.data.o"
include "build/data/ovl_En_Cow/ovl_En_Cow.reloc.o"
include "build/src/overlays/actors/ovl_En_Cow/ovl_En_Cow_reloc.o"
endseg
beginseg

View File

@ -15,16 +15,18 @@ void EnCow_Destroy(Actor* thisx, GlobalContext* globalCtx);
void EnCow_Update(Actor* thisx, GlobalContext* globalCtx);
void EnCow_Draw(Actor* thisx, GlobalContext* globalCtx);
void func_8099CAA8(EnCow* this, GlobalContext* globalCtx);
void func_8099CB20(EnCow* this, GlobalContext* globalCtx);
void func_8099CB68(EnCow* this, GlobalContext* globalCtx);
void func_8099CBCC(EnCow* this, GlobalContext* globalCtx);
void func_8099CC68(EnCow* this, GlobalContext* globalCtx);
void func_8099CCF8(EnCow* this, GlobalContext* globalCtx);
void func_8099CDA0(EnCow* this, GlobalContext* globalCtx);
void func_8099CFAC(EnCow* this, GlobalContext* globalCtx);
void EnCow_TalkEnd(EnCow* this, GlobalContext* globalCtx);
void EnCow_GiveMilkEnd(EnCow* this, GlobalContext* globalCtx);
void EnCow_GiveMilkWait(EnCow* this, GlobalContext* globalCtx);
void EnCow_GiveMilk(EnCow* this, GlobalContext* globalCtx);
void EnCow_CheckForEmptyBottle(EnCow* this, GlobalContext* globalCtx);
void EnCow_Talk(EnCow* this, GlobalContext* globalCtx);
void EnCow_Idle(EnCow* this, GlobalContext* globalCtx);
void EnCow_DoTail(EnCow* this, GlobalContext* globalCtx);
void EnCow_UpdateTail(Actor* this, GlobalContext* globalCtx);
void EnCow_DrawTail(Actor* this, GlobalContext* globalCtx);
#if 0
const ActorInit En_Cow_InitVars = {
ACTOR_EN_COW,
ACTORCAT_NPC,
@ -37,57 +39,404 @@ const ActorInit En_Cow_InitVars = {
(ActorFunc)EnCow_Draw,
};
// static ColliderCylinderInit sCylinderInit = {
static ColliderCylinderInit D_8099D610 = {
{ COLTYPE_NONE, AT_NONE, AC_ON | AC_TYPE_ENEMY, OC1_ON | OC1_TYPE_ALL, OC2_TYPE_1, COLSHAPE_CYLINDER, },
{ ELEMTYPE_UNK0, { 0x00000000, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, },
static ColliderCylinderInit sCylinderInit = {
{
COLTYPE_NONE,
AT_NONE,
AC_ON | AC_TYPE_ENEMY,
OC1_ON | OC1_TYPE_ALL,
OC2_TYPE_1,
COLSHAPE_CYLINDER,
},
{
ELEMTYPE_UNK0,
{ 0x00000000, 0x00, 0x00 },
{ 0xF7CFFFFF, 0x00, 0x00 },
TOUCH_NONE | TOUCH_SFX_NORMAL,
BUMP_ON,
OCELEM_ON,
},
{ 30, 40, 0, { 0, 0, 0 } },
};
#endif
Vec3f D_8099D63C = { 0.0f, -1300.0f, 1100.0f };
extern ColliderCylinderInit D_8099D610;
extern AnimationHeader D_060001CC; // gCowBodyChewAnim
extern FlexSkeletonHeader D_06004010; // gCowBodySkel
extern AnimationHeader D_06004264; // gCowBodyMoveHeadAnim
extern AnimationHeader D_06004348; // gCowTailIdleAnim
extern FlexSkeletonHeader D_06004C30; // gCowTailSkel
extern AnimationHeader D_06004E98; // gCowTailSwishAnim
extern UNK_TYPE D_060001CC;
extern UNK_TYPE D_06004010;
extern UNK_TYPE D_06004348;
void EnCow_RotatePoint(Vec3f* vec, s16 angle) {
f32 x = (Math_CosS(angle) * vec->x) + (Math_SinS(angle) * vec->z);
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Cow/func_8099C290.s")
vec->z = (-Math_SinS(angle) * vec->x) + (Math_CosS(angle) * vec->z);
vec->x = x;
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Cow/func_8099C328.s")
void EnCow_SetColliderPos(EnCow* this) {
Vec3f vec;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Cow/func_8099C41C.s")
vec.x = vec.y = 0.0f;
vec.z = 30.0f;
EnCow_RotatePoint(&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;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Cow/EnCow_Init.s")
vec.x = vec.y = 0.0f;
vec.z = -20.0f;
EnCow_RotatePoint(&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;
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Cow/EnCow_Destroy.s")
void EnCow_SetTailPos(EnCow* this) {
Vec3f vec;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Cow/func_8099C880.s")
VEC_SET(vec, 0.0f, 57.0f, -36.0f);
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Cow/func_8099CAA8.s")
EnCow_RotatePoint(&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;
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Cow/func_8099CB20.s")
void EnCow_Init(Actor* thisx, GlobalContext* globalCtx) {
s32 pad;
EnCow* this = THIS;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Cow/func_8099CB68.s")
ActorShape_Init(&this->actor.shape, 0.0f, func_800B3FC0, 72.0f);
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Cow/func_8099CBCC.s")
switch (EN_COW_TYPE(thisx)) {
case EN_COW_TYPE_DEFAULT:
case EN_COW_TYPE_ABDUCTED:
SkelAnime_InitFlex(globalCtx, &this->skelAnime, &D_06004010, NULL, this->jointTable, this->morphTable,
COW_LIMB_MAX);
Animation_PlayLoop(&this->skelAnime, &D_060001CC);
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Cow/func_8099CC68.s")
Collider_InitAndSetCylinder(globalCtx, &this->colliders[0], &this->actor, &sCylinderInit);
Collider_InitAndSetCylinder(globalCtx, &this->colliders[1], &this->actor, &sCylinderInit);
EnCow_SetColliderPos(this);
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Cow/func_8099CCF8.s")
this->actionFunc = EnCow_Idle;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Cow/func_8099CDA0.s")
if (!(gSaveContext.weekEventReg[22] & 1) && (CURRENT_DAY != 1) &&
(EN_COW_TYPE(thisx) == EN_COW_TYPE_ABDUCTED)) {
Actor_MarkForDeath(&this->actor);
return;
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Cow/func_8099CFAC.s")
Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, 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,
EN_COW_TYPE_TAIL);
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Cow/EnCow_Update.s")
this->animationTimer = Rand_ZeroFloat(1000.0f) + 40.0f;
this->animationCycle = 0;
this->actor.targetMode = 6;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Cow/func_8099D3C0.s")
D_801BDAA4 = 0;
func_801A5080(4);
break;
case EN_COW_TYPE_TAIL:
SkelAnime_InitFlex(globalCtx, &this->skelAnime, &D_06004C30, NULL, this->jointTable, this->morphTable,
COW_LIMB_MAX);
Animation_PlayLoop(&this->skelAnime, &D_06004348);
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Cow/func_8099D4AC.s")
this->actor.update = EnCow_UpdateTail;
this->actor.draw = EnCow_DrawTail;
this->actionFunc = EnCow_DoTail;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Cow/func_8099D4FC.s")
EnCow_SetTailPos(this);
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Cow/EnCow_Draw.s")
this->actor.flags &= ~EN_COW_FLAG_IS_TAIL;
this->animationTimer = Rand_ZeroFloat(1000.0f) + 40.0f;
break;
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Cow/func_8099D59C.s")
this->actor.colChkInfo.mass = MASS_IMMOVABLE;
Actor_SetScale(&this->actor, 0.01f);
this->flags = 0;
gSaveContext.weekEventReg[87] &= (u8)~1;
}
void EnCow_Destroy(Actor* thisx, GlobalContext* globalCtx) {
EnCow* this = THIS;
if (this->actor.params == EN_COW_TYPE_DEFAULT) { //! @bug EN_COW_TYPE_ABDUCTED do not destroy their cylinders
Collider_DestroyCylinder(globalCtx, &this->colliders[0]);
Collider_DestroyCylinder(globalCtx, &this->colliders[1]);
}
}
void EnCow_UpdateAnimation(EnCow* this, GlobalContext* globalCtx) {
if (this->animationTimer > 0) {
this->animationTimer--;
} else {
this->animationTimer = Rand_ZeroFloat(500.0f) + 40.0f;
Animation_Change(&this->skelAnime, &D_060001CC, 1.0f, this->skelAnime.curFrame,
Animation_GetLastFrame(&D_060001CC), ANIMMODE_ONCE, 1.0f);
}
if (this->actor.xzDistToPlayer < 150.0f) {
if (!(this->flags & EN_COW_FLAG_PLAYER_HAS_APPROACHED)) {
this->flags |= EN_COW_FLAG_PLAYER_HAS_APPROACHED;
if (this->skelAnime.animation == &D_060001CC) {
this->animationTimer = 0;
}
}
}
this->animationCycle++;
if (this->animationCycle > 0x30) {
this->animationCycle = 0;
}
if (this->animationCycle < 0x20) {
this->actor.scale.x = ((Math_SinS(this->animationCycle * 0x400) * (1.0f / 100.0f)) + 1.0f) * 0.01f;
} else {
this->actor.scale.x = 0.01f;
}
if (this->animationCycle > 0x10) {
this->actor.scale.y = ((Math_SinS((this->animationCycle * 0x400) - 0x4000) * (1.0f / 100.0f)) + 1.0f) * 0.01f;
} else {
this->actor.scale.y = 0.01f;
}
}
void EnCow_TalkEnd(EnCow* this, GlobalContext* globalCtx) {
if ((func_80152498(&globalCtx->msgCtx) == 5) && func_80147624(globalCtx)) {
this->actor.flags &= ~0x10000;
func_801477B4(globalCtx);
this->actionFunc = EnCow_Idle;
}
}
void EnCow_GiveMilkEnd(EnCow* this, GlobalContext* globalCtx) {
if (func_800B867C(&this->actor, globalCtx)) {
this->actor.flags &= ~0x10000;
this->actionFunc = EnCow_Idle;
}
}
void EnCow_GiveMilkWait(EnCow* this, GlobalContext* globalCtx) {
if (Actor_HasParent(&this->actor, globalCtx)) {
this->actor.parent = NULL;
this->actionFunc = EnCow_GiveMilkEnd;
} else {
func_800B8A1C(&this->actor, globalCtx, GI_MILK, 10000.0f, 100.0f);
}
}
void EnCow_GiveMilk(EnCow* this, GlobalContext* globalCtx) {
if ((func_80152498(&globalCtx->msgCtx) == 5) && func_80147624(globalCtx)) {
this->actor.flags &= ~0x10000;
func_801477B4(globalCtx);
this->actionFunc = EnCow_GiveMilkWait;
func_800B8A1C(&this->actor, globalCtx, GI_MILK, 10000.0f, 100.0f);
}
}
void EnCow_CheckForEmptyBottle(EnCow* this, GlobalContext* globalCtx) {
if ((func_80152498(&globalCtx->msgCtx) == 5) && func_80147624(globalCtx)) {
if (func_80114E90()) {
func_80151938(globalCtx, 0x32C9); // Text to give milk.
this->actionFunc = EnCow_GiveMilk;
} else {
func_80151938(globalCtx, 0x32CA); // Text if you don't have an empty bottle.
this->actionFunc = EnCow_TalkEnd;
}
}
}
void EnCow_Talk(EnCow* this, GlobalContext* globalCtx) {
if (func_800B84D0(&this->actor, globalCtx)) {
if (this->actor.textId == 0x32C8) { // Text to give milk after playing Epona's Song.
this->actionFunc = EnCow_CheckForEmptyBottle;
} else if (this->actor.textId == 0x32C9) { // Text to give milk.
this->actionFunc = EnCow_GiveMilk;
} else {
this->actionFunc = EnCow_TalkEnd;
}
} else {
this->actor.flags |= 0x10000;
func_800B8614(&this->actor, globalCtx, 170.0f);
this->actor.textId = 0x32C8; //! @bug textId is reset to this no matter the intial value
}
EnCow_UpdateAnimation(this, globalCtx);
}
void EnCow_Idle(EnCow* this, GlobalContext* globalCtx) {
if ((globalCtx->msgCtx.unk1202A == 0) || (globalCtx->msgCtx.unk1202A == 4)) {
if (D_801BDAA4 != 0) {
if (this->flags & EN_COW_FLAG_WONT_GIVE_MILK) {
this->flags &= ~EN_COW_FLAG_WONT_GIVE_MILK;
D_801BDAA4 = 0;
} else if ((this->actor.xzDistToPlayer < 150.0f) &&
ABS_ALT((s16)(this->actor.yawTowardsPlayer - this->actor.shape.rot.y)) < 25000) {
D_801BDAA4 = 0;
this->actionFunc = EnCow_Talk;
this->actor.flags |= 0x10000;
func_800B8614(&this->actor, globalCtx, 170.0f);
this->actor.textId = 0x32C8; // Text to give milk after playing Epona's Song.
EnCow_UpdateAnimation(this, globalCtx);
return;
} else {
this->flags |= EN_COW_FLAG_WONT_GIVE_MILK;
}
} else {
this->flags &= ~EN_COW_FLAG_WONT_GIVE_MILK;
}
}
if (this->actor.xzDistToPlayer < 150.0f &&
ABS_ALT((s16)(this->actor.yawTowardsPlayer - this->actor.shape.rot.y)) < 25000) {
if (func_801A5100() == 4) {
if (!(gSaveContext.weekEventReg[87] & 1)) {
gSaveContext.weekEventReg[87] |= 1;
if (func_80114E90()) {
this->actor.textId = 0x32C9; // Text to give milk.
} else {
this->actor.textId = 0x32CA; // Text if you don't have an empty bottle.
}
this->actor.flags |= 0x10000;
func_800B8614(&this->actor, globalCtx, 170.0f);
this->actionFunc = EnCow_Talk;
}
} else {
gSaveContext.weekEventReg[87] &= (u8)~1;
}
}
EnCow_UpdateAnimation(this, globalCtx);
}
void EnCow_DoTail(EnCow* this, GlobalContext* globalCtx) {
if (this->animationTimer > 0) {
this->animationTimer--;
} else {
this->animationTimer = Rand_ZeroFloat(200.0f) + 40.0f;
Animation_Change(&this->skelAnime, &D_06004348, 1.0f, this->skelAnime.curFrame,
Animation_GetLastFrame(&D_06004348), ANIMMODE_ONCE, 1.0f);
}
if (this->actor.xzDistToPlayer < 150.0f &&
ABS_ALT((s16)(this->actor.yawTowardsPlayer - this->actor.shape.rot.y)) > 25000) {
if (!(this->flags & EN_COW_FLAG_PLAYER_HAS_APPROACHED)) {
this->flags |= EN_COW_FLAG_PLAYER_HAS_APPROACHED;
if (this->skelAnime.animation == &D_06004348) {
this->animationTimer = 0;
}
}
}
}
void EnCow_Update(Actor* thisx, GlobalContext* globalCtx2) {
GlobalContext* globalCtx = globalCtx2;
EnCow* this = THIS;
s16 targetX;
s16 targetY;
Player* player = GET_PLAYER(globalCtx);
CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->colliders[0].base);
CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->colliders[1].base);
Actor_SetVelocityAndMoveYRotationAndGravity(&this->actor);
Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 0.0f, 0.0f, 0.0f, 4);
if (SkelAnime_Update(&this->skelAnime)) {
if (this->skelAnime.animation == &D_060001CC) {
Audio_PlayActorSound2(&this->actor, NA_SE_EV_COW_CRY);
Animation_Change(&this->skelAnime, &D_06004264, 1.0f, 0.0f, Animation_GetLastFrame(&D_06004264),
ANIMMODE_ONCE, 1.0f);
} else {
Animation_Change(&this->skelAnime, &D_060001CC, 1.0f, 0.0f, Animation_GetLastFrame(&D_060001CC),
ANIMMODE_LOOP, 1.0f);
}
}
this->actionFunc(this, globalCtx);
if (this->actor.xzDistToPlayer < 150.0f &&
ABS_ALT(Math_Vec3f_Yaw(&thisx->world.pos, &player->actor.world.pos)) < 0xC000) {
targetX = Math_Vec3f_Pitch(&thisx->focus.pos, &player->actor.focus.pos);
targetY = Math_Vec3f_Yaw(&thisx->focus.pos, &player->actor.focus.pos) - this->actor.shape.rot.y;
if (targetX > 0x1000) {
targetX = 0x1000;
} else if (targetX < -0x1000) {
targetX = -0x1000;
}
if (targetY > 0x2500) {
targetY = 0x2500;
} else if (targetY < -0x2500) {
targetY = -0x2500;
}
} else {
targetX = targetY = 0;
}
Math_SmoothStepToS(&this->headTilt.x, targetX, 10, 200, 10);
Math_SmoothStepToS(&this->headTilt.y, targetY, 10, 200, 10);
}
void EnCow_UpdateTail(Actor* thisx, GlobalContext* globalCtx) {
s32 pad;
EnCow* this = THIS;
if (SkelAnime_Update(&this->skelAnime)) {
if (this->skelAnime.animation == &D_06004348) {
Animation_Change(&this->skelAnime, &D_06004E98, 1.0f, 0.0f, Animation_GetLastFrame(&D_06004E98),
ANIMMODE_ONCE, 1.0f);
} else {
Animation_Change(&this->skelAnime, &D_06004348, 1.0f, 0.0f, Animation_GetLastFrame(&D_06004348),
ANIMMODE_LOOP, 1.0f);
}
}
this->actionFunc(this, globalCtx);
}
s32 EnCow_OverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, Actor* thisx) {
EnCow* this = THIS;
if (limbIndex == COW_LIMB_HEAD) {
rot->y += this->headTilt.y;
rot->x += this->headTilt.x;
}
if (limbIndex == COW_LIMB_NOSE_RING) {
*dList = NULL;
}
return false;
}
void EnCow_PostLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx) {
EnCow* this = THIS;
if (limbIndex == COW_LIMB_HEAD) {
Matrix_MultiplyVector3fByState(&D_8099D63C, &this->actor.focus.pos);
}
}
void EnCow_Draw(Actor* thisx, GlobalContext* globalCtx) {
EnCow* this = THIS;
func_8012C5B0(globalCtx->state.gfxCtx);
SkelAnime_DrawFlexOpa(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable, this->skelAnime.dListCount,
EnCow_OverrideLimbDraw, EnCow_PostLimbDraw, &this->actor);
}
void EnCow_DrawTail(Actor* thisx, GlobalContext* globalCtx) {
EnCow* this = THIS;
func_8012C5B0(globalCtx->state.gfxCtx);
SkelAnime_DrawFlexOpa(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable, this->skelAnime.dListCount,
NULL, NULL, &this->actor);
}

View File

@ -3,13 +3,42 @@
#include "global.h"
#define EN_COW_TYPE(thisx) ((thisx)->params & 0xF)
#define EN_COW_FLAG_IS_TAIL (1 << 0) // This is never set but it is cleared for tail types
#define EN_COW_FLAG_PLAYER_HAS_APPROACHED (1 << 1)
#define EN_COW_FLAG_WONT_GIVE_MILK (1 << 2)
typedef enum {
/* 0 */ EN_COW_TYPE_DEFAULT,
/* 1 */ EN_COW_TYPE_TAIL,
/* 2 */ EN_COW_TYPE_ABDUCTED,
} EnCowType;
struct EnCow;
typedef void (*EnCowActionFunc)(struct EnCow*, GlobalContext*);
typedef enum {
/* 0 */ COW_LIMB_NONE,
/* 1 */ COW_LIMB_ROOT,
/* 2 */ COW_LIMB_HEAD,
/* 3 */ COW_LIMB_JAW,
/* 4 */ COW_LIMB_NOSE,
/* 5 */ COW_LIMB_NOSE_RING,
/* 6 */ COW_LIMB_MAX,
} ObjectCowLimbs;
typedef struct EnCow {
/* 0x0000 */ Actor actor;
/* 0x0144 */ char unk_144[0x130];
/* 0x0144 */ ColliderCylinder colliders[2];
/* 0x01DC */ SkelAnime skelAnime;
/* 0x0220 */ Vec3s jointTable[COW_LIMB_MAX];
/* 0x0244 */ Vec3s morphTable[COW_LIMB_MAX];
/* 0x0268 */ Vec3s headTilt;
/* 0x026E */ u16 flags;
/* 0x0270 */ u16 animationTimer;
/* 0x0272 */ u16 animationCycle;
/* 0x0274 */ EnCowActionFunc actionFunc;
} EnCow; // size = 0x278

View File

@ -4,8 +4,8 @@ D_80000000 = 0x80000000; // __osExceptionPreamble
D_80000004 = 0x80000004; // __osExceptionPreamble
D_80000008 = 0x80000008; // __osExceptionPreamble
D_8000000C = 0x8000000C; // __osExceptionPreamble
D_80000010 = 0x80000010; //
D_80000020 = 0x80000020; //
D_80000010 = 0x80000010; //
D_80000020 = 0x80000020; //
osTvType = 0x80000300;
osRomType = 0x80000304;