diff --git a/assets/xml/objects/object_um.xml b/assets/xml/objects/object_um.xml index 5717124a7c..aa979bf754 100644 --- a/assets/xml/objects/object_um.xml +++ b/assets/xml/objects/object_um.xml @@ -10,26 +10,31 @@ - + + + - + - + + + + @@ -49,31 +54,35 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -85,7 +94,19 @@ - + + + + + + + + + + + + + @@ -100,6 +121,6 @@ - + diff --git a/include/functions.h b/include/functions.h index 120af69306..a72b6da7d8 100644 --- a/include/functions.h +++ b/include/functions.h @@ -130,6 +130,7 @@ u32 StackCheck_Check(StackEntry* entry); void MtxConv_F2L(Mtx* m1, MtxF* m2); void MtxConv_L2F(MtxF* m1, Mtx* m2); + void __assert(const char* file, u32 lineNum); // void func_800862B4(void); void* SystemArena_MallocMin1(u32 size); diff --git a/spec b/spec index 209727c3d7..45aa1aec4d 100644 --- a/spec +++ b/spec @@ -4064,8 +4064,7 @@ beginseg name "ovl_Obj_Um" compress include "build/src/overlays/actors/ovl_Obj_Um/z_obj_um.o" - include "build/data/ovl_Obj_Um/ovl_Obj_Um.data.o" - include "build/data/ovl_Obj_Um/ovl_Obj_Um.reloc.o" + include "build/src/overlays/actors/ovl_Obj_Um/ovl_Obj_Um_reloc.o" endseg beginseg 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 0e63d87c1c..1922a2f4bb 100644 --- a/src/overlays/actors/ovl_En_Horse/z_en_horse.c +++ b/src/overlays/actors/ovl_En_Horse/z_en_horse.c @@ -6,6 +6,8 @@ #include "z_en_horse.h" #include "z64rumble.h" +#include "overlays/actors/ovl_En_In/z_en_in.h" +#include "overlays/actors/ovl_Obj_Um/z_obj_um.h" #include "overlays/actors/ovl_En_Horse_Game_Check/z_en_horse_game_check.h" #include "objects/object_horse_link_child/object_horse_link_child.h" @@ -122,7 +124,9 @@ static AnimationHeader** sAnimationHeaders[] = { NULL, NULL, sEponaAnimHeaders, sHniAnimHeaders, sHniAnimHeaders, }; -static f32 sPlaybackSpeeds[] = { 2.0f / 3.0f, 2.0f / 3.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 2.0f / 3.0f, 2.0f / 3.0f }; +static f32 sPlaybackSpeeds[] = { + 2.0f / 3.0f, 2.0f / 3.0f, 3.0f / 3.0f, 3.0f / 3.0f, 3.0f / 3.0f, 3.0f / 3.0f, 3.0f / 3.0f, 2.0f / 3.0f, 2.0f / 3.0f, +}; static SkeletonHeader* sSkeletonHeaders[] = { NULL, NULL, &object_horse_link_child_Skel_00A480, NULL, NULL, @@ -468,7 +472,7 @@ void EnHorse_PlayWalkingSound(EnHorse* this) { return; } - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_KID_HORSE_WALK); } else { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_HORSE_WALK); @@ -482,7 +486,7 @@ void EnHorse_PlayWalkingSound(EnHorse* this) { } void func_8087C178(EnHorse* this) { - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_KID_HORSE_RUN); } else { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_HORSE_RUN); @@ -490,7 +494,7 @@ void func_8087C178(EnHorse* this) { } void func_8087C1C0(EnHorse* this) { - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_KID_HORSE_RUN); } else { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_HORSE_RUN); @@ -546,19 +550,19 @@ s32 func_8087C38C(PlayState* play, EnHorse* this, Vec3f* arg2) { void EnHorse_IdleAnimSounds(EnHorse* this, PlayState* play) { if ((this->animationIdx == ENHORSE_ANIM_IDLE) && - (((this->curFrame > 35.0f) && (this->type == HORSE_EPONA)) || - ((this->curFrame > 28.0f) && (this->type == HORSE_HNI)) || - ((this->curFrame > 25.0f) && (this->type == HORSE_2))) && + (((this->curFrame > 35.0f) && (this->type == HORSE_TYPE_EPONA)) || + ((this->curFrame > 28.0f) && (this->type == HORSE_TYPE_HNI)) || + ((this->curFrame > 25.0f) && (this->type == HORSE_TYPE_2))) && !(this->stateFlags & ENHORSE_SANDDUST_SOUND)) { this->stateFlags |= ENHORSE_SANDDUST_SOUND; - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_KID_HORSE_SANDDUST); } else { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_KID_HORSE_SANDDUST); } } else if ((this->animationIdx == 3) && (this->curFrame > 25.0f) && !(this->stateFlags & ENHORSE_LAND2_SOUND)) { this->stateFlags |= ENHORSE_LAND2_SOUND; - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_KID_HORSE_LAND2); } else { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_KID_HORSE_LAND2); @@ -694,8 +698,8 @@ void EnHorse_Init(Actor* thisx, PlayState* play2) { this->unk_3E8 = 0.0f; this->unk_528 = 100.0f; - if (ENHORSE_GET_8000(&this->actor)) { - this->type = HORSE_4; + if (ENHORSE_IS_DONKEY_TYPE(&this->actor)) { + this->type = HORSE_TYPE_DONKEY; this->unk_528 = 80.0f; this->boostSpeed = 12; if ((this->bankIndex = Object_GetIndex(&play->objectCtx, OBJECT_HA)) < 0) { @@ -704,8 +708,8 @@ void EnHorse_Init(Actor* thisx, PlayState* play2) { } this->unk_1EC |= 1; thisx->update = func_8087D540; - } else if (ENHORSE_GET_4000(&this->actor)) { - this->type = HORSE_2; + } else if (ENHORSE_IS_4000_TYPE(&this->actor)) { + this->type = HORSE_TYPE_2; this->unk_528 = 64.8f; this->boostSpeed = 15; if ((this->bankIndex = Object_GetIndex(&play->objectCtx, OBJECT_HORSE_LINK_CHILD)) < 0) { @@ -717,8 +721,8 @@ void EnHorse_Init(Actor* thisx, PlayState* play2) { } else { thisx->update = func_8087D540; } - } else if (ENHORSE_GET_2000(&this->actor)) { - this->type = HORSE_3; + } else if (ENHORSE_IS_BANDIT_TYPE(&this->actor)) { + this->type = HORSE_TYPE_BANDIT; this->boostSpeed = 12; if ((this->bankIndex = Object_GetIndex(&play->objectCtx, OBJECT_HA)) < 0) { Actor_MarkForDeath(&this->actor); @@ -727,14 +731,14 @@ void EnHorse_Init(Actor* thisx, PlayState* play2) { this->unk_1EC |= 1; thisx->update = func_8087D540; } else { - this->type = HORSE_EPONA; + this->type = HORSE_TYPE_EPONA; this->boostSpeed = 15; Actor_MarkForDeath(&this->actor); } - thisx->params &= ~0xE000; - if (thisx->params == 0x1FFF) { - thisx->params = ENHORSE_1; + this->actor.params &= ~(ENHORSE_PARAM_DONKEY | ENHORSE_PARAM_4000 | ENHORSE_PARAM_BANDIT); + if (this->actor.params == 0x1FFF) { + this->actor.params = ENHORSE_1; } if (thisx->params == ENHORSE_3) { @@ -780,9 +784,9 @@ void EnHorse_Init(Actor* thisx, PlayState* play2) { this->action = ENHORSE_ACT_IDLE; thisx->speedXZ = 0.0f; - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { sJntSphInit.elements[0].dim.limb = 13; - } else if ((this->type == HORSE_3) || (this->type == HORSE_4)) { + } else if ((this->type == HORSE_TYPE_BANDIT) || (this->type == HORSE_TYPE_DONKEY)) { sJntSphInit.elements[0].dim.limb = 10; } @@ -793,19 +797,19 @@ void EnHorse_Init(Actor* thisx, PlayState* play2) { Collider_InitJntSph(play, &this->colliderJntSph); Collider_SetJntSph(play, &this->colliderJntSph, &this->actor, &sJntSphInit, this->colliderJntSphElements); - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { this->colliderCylinder1.dim.radius = this->colliderCylinder1.dim.radius * 0.8f; this->colliderCylinder2.dim.radius = this->colliderCylinder2.dim.radius * 0.8f; this->colliderJntSph.elements[0].dim.modelSphere.radius *= 0.6f; - } else if (this->type == HORSE_4) { + } else if (this->type == HORSE_TYPE_DONKEY) { this->colliderCylinder1.dim.radius = 50; } CollisionCheck_SetInfo(&thisx->colChkInfo, NULL, &sColChkInfoInit); - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Actor_SetScale(&this->actor, 0.00648f); - } else if (this->type == HORSE_4) { + } else if (this->type == HORSE_TYPE_DONKEY) { Actor_SetScale(&this->actor, 0.008f); } else { Actor_SetScale(&this->actor, 0.01f); @@ -889,7 +893,7 @@ void EnHorse_Init(Actor* thisx, PlayState* play2) { thisx->world.rot.z = thisx->shape.rot.z; thisx->home.rot.z = thisx->shape.rot.z; this->unk_3EC = thisx->world.rot.y; - this->unk_538 = 0; + this->unk_538 = OBJ_UM_ANIM_TROT; if (this->unk_1EC & 0x100) { this->colliderCylinder1.base.colType = COLTYPE_HIT3; @@ -903,6 +907,7 @@ void EnHorse_Init(Actor* thisx, PlayState* play2) { } } +// EnHorse_WaitForObject void func_8087D540(Actor* thisx, PlayState* play) { EnHorse* this = THIS; @@ -911,7 +916,7 @@ void func_8087D540(Actor* thisx, PlayState* play) { Actor_SetObjectDependency(play, &this->actor); this->actor.update = EnHorse_Update; if (this->unk_1EC & 1) { - if (this->type == HORSE_3) { + if (this->type == HORSE_TYPE_BANDIT) { SkelAnime_InitFlex(play, &this->skin.skelAnime, &object_ha_Skel_008C68, NULL, this->jointTable, this->morphTable, OBJECT_HA_1_LIMB_MAX); } else { @@ -1097,11 +1102,11 @@ void EnHorse_StartMountedIdle(EnHorse* this) { this->action = ENHORSE_ACT_MOUNTED_TURN; this->animationIdx = ENHORSE_ANIM_IDLE; - if (((this->curFrame > 35.0f) && (this->type == HORSE_EPONA)) || - ((this->curFrame > 28.0f) && (this->type == HORSE_HNI))) { + if (((this->curFrame > 35.0f) && (this->type == HORSE_TYPE_EPONA)) || + ((this->curFrame > 28.0f) && (this->type == HORSE_TYPE_HNI))) { if (!(this->stateFlags & ENHORSE_SANDDUST_SOUND)) { this->stateFlags |= ENHORSE_SANDDUST_SOUND; - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_KID_HORSE_SANDDUST); } else { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_KID_HORSE_SANDDUST); @@ -1152,7 +1157,7 @@ void EnHorse_MountedIdleWhinney(EnHorse* this) { Animation_Change(&this->skin.skelAnime, sAnimationHeaders[this->type][this->animationIdx], 1.0f, curFrame, Animation_GetLastFrame(sAnimationHeaders[this->type][1]), ANIMMODE_ONCE, -3.0f); if (this->stateFlags & ENHORSE_DRAW) { - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->unk_218, NA_SE_EV_KID_HORSE_GROAN); } else { Audio_PlaySfxAtPos(&this->unk_218, NA_SE_EV_HORSE_GROAN); @@ -1437,7 +1442,7 @@ void EnHorse_StartRearing(EnHorse* this) { if (sAnimationHeaders[this->type][this->animationIdx] == NULL) { if (Rand_ZeroOne() > 0.5f) { if (this->stateFlags & ENHORSE_DRAW) { - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->unk_218, NA_SE_EV_KID_HORSE_NEIGH); } else { Audio_PlaySfxAtPos(&this->unk_218, NA_SE_EV_HORSE_NEIGH); @@ -1451,7 +1456,7 @@ void EnHorse_StartRearing(EnHorse* this) { this->stateFlags &= ~ENHORSE_LAND2_SOUND; if (this->stateFlags & ENHORSE_DRAW) { - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->unk_218, NA_SE_EV_KID_HORSE_NEIGH); } else { Audio_PlaySfxAtPos(&this->unk_218, NA_SE_EV_HORSE_NEIGH); @@ -1471,7 +1476,7 @@ void EnHorse_MountedRearing(EnHorse* this, PlayState* play) { if (this->curFrame > 25.0f) { if (!(this->stateFlags & ENHORSE_LAND2_SOUND)) { this->stateFlags |= ENHORSE_LAND2_SOUND; - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_KID_HORSE_LAND2); } else { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_KID_HORSE_LAND2); @@ -1511,7 +1516,7 @@ void EnHorse_StartBraking(EnHorse* this, PlayState* play) { if (sAnimationHeaders[this->type][this->animationIdx] == NULL) { if (Rand_ZeroOne() > 0.5f) { if (this->stateFlags & ENHORSE_DRAW) { - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->unk_218, NA_SE_EV_KID_HORSE_NEIGH); } else { Audio_PlaySfxAtPos(&this->unk_218, NA_SE_EV_HORSE_NEIGH); @@ -1523,7 +1528,7 @@ void EnHorse_StartBraking(EnHorse* this, PlayState* play) { EnHorse_StartMountedIdleResetAnim(this); } - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_HORSE_SLIP); } else { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_HORSE_SLIP); @@ -1548,7 +1553,7 @@ void EnHorse_Stopping(EnHorse* this, PlayState* play) { if ((Rand_ZeroOne() > 0.5f) && ((gSaveContext.save.entranceIndex != 0x6400) || !Cutscene_GetSceneSetupIndex(play))) { if (this->stateFlags & ENHORSE_DRAW) { - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->unk_218, NA_SE_EV_KID_HORSE_NEIGH); } else { Audio_PlaySfxAtPos(&this->unk_218, NA_SE_EV_HORSE_NEIGH); @@ -1681,7 +1686,7 @@ void EnHorse_StartLowJump(EnHorse* this, PlayState* play) { y = jointTable->y; this->riderPos.y -= ((y * 0.01f) * this->unk_528) * 0.01f; - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_HORSE_JUMP); } else { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_HORSE_JUMP); @@ -1740,7 +1745,7 @@ void EnHorse_LowJump(EnHorse* this, PlayState* play) { if (SkelAnime_Update(&this->skin.skelAnime) || ((curFrame > 17.0f) && (this->actor.world.pos.y < ((this->actor.floorHeight - this->actor.velocity.y) + 80.0f)))) { - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_HORSE_LAND); } else { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_HORSE_LAND); @@ -1779,7 +1784,7 @@ void EnHorse_StartHighJump(EnHorse* this, PlayState* play) { this->riderPos.y -= ((y * 0.01f) * this->unk_528) * 0.01f; this->stateFlags |= ENHORSE_CALC_RIDER_POS; - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_HORSE_JUMP); } else { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_HORSE_JUMP); @@ -1837,7 +1842,7 @@ void EnHorse_HighJump(EnHorse* this, PlayState* play) { if (SkelAnime_Update(&this->skin.skelAnime) || ((curFrame > 23.0f) && (this->actor.world.pos.y < ((this->actor.floorHeight - this->actor.velocity.y) + 80.0f)))) { - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_HORSE_LAND); } else { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_HORSE_LAND); @@ -1862,10 +1867,10 @@ void EnHorse_InitInactive(EnHorse* this) { } void EnHorse_Inactive(EnHorse* this, PlayState* play) { - if ((D_801BDAA4 != 0) && (this->type == HORSE_2)) { + if ((D_801BDAA4 != 0) && (this->type == HORSE_TYPE_2)) { D_801BDAA4 = 0; if (EnHorse_Spawn(this, play)) { - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_KID_HORSE_NEIGH); } this->stateFlags &= ~ENHORSE_INACTIVE; @@ -1901,7 +1906,7 @@ void EnHorse_PlayIdleAnimation(EnHorse* this, s32 anim, f32 morphFrames, f32 sta } else { if (this->animationIdx == ENHORSE_ANIM_WHINNEY) { if (this->stateFlags & ENHORSE_DRAW) { - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->unk_218, NA_SE_EV_KID_HORSE_GROAN); } else { Audio_PlaySfxAtPos(&this->unk_218, NA_SE_EV_HORSE_GROAN); @@ -1909,7 +1914,7 @@ void EnHorse_PlayIdleAnimation(EnHorse* this, s32 anim, f32 morphFrames, f32 sta } } else if (this->animationIdx == ENHORSE_ANIM_REARING) { if (this->stateFlags & ENHORSE_DRAW) { - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->unk_218, NA_SE_EV_KID_HORSE_NEIGH); } else { Audio_PlaySfxAtPos(&this->unk_218, NA_SE_EV_HORSE_NEIGH); @@ -1942,11 +1947,11 @@ void EnHorse_Idle(EnHorse* this, PlayState* play) { this->actor.speedXZ = 0.0f; EnHorse_IdleAnimSounds(this, play); - if ((D_801BDAA4 != 0) && (this->type == HORSE_2)) { + if ((D_801BDAA4 != 0) && (this->type == HORSE_TYPE_2)) { D_801BDAA4 = 0; if (!func_8087C38C(play, this, &this->actor.world.pos)) { if (EnHorse_Spawn(this, play)) { - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_KID_HORSE_NEIGH); } else { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_HORSE_NEIGH); @@ -1955,7 +1960,7 @@ void EnHorse_Idle(EnHorse* this, PlayState* play) { EnHorse_SetFollowAnimation(this, play); } } else { - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_KID_HORSE_NEIGH); } else { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_HORSE_NEIGH); @@ -2067,7 +2072,7 @@ void EnHorse_FollowPlayer(EnHorse* this, PlayState* play) { this->actor.shape.rot.y = this->actor.world.rot.y; if ((this->curFrame > 25.0f) && !(this->stateFlags & ENHORSE_LAND2_SOUND)) { this->stateFlags |= ENHORSE_LAND2_SOUND; - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_KID_HORSE_LAND2); } else { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_KID_HORSE_LAND2); @@ -2099,7 +2104,7 @@ void EnHorse_FollowPlayer(EnHorse* this, PlayState* play) { if (this->followTimer > 300) { EnHorse_StartIdleRidable(this); if (this->stateFlags & ENHORSE_DRAW) { - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->unk_218, NA_SE_EV_KID_HORSE_NEIGH); } else { Audio_PlaySfxAtPos(&this->unk_218, NA_SE_EV_HORSE_NEIGH); @@ -2179,14 +2184,14 @@ void EnHorse_UpdateIngoHorseAnim(EnHorse* this) { animSpeed = this->actor.speedXZ * 0.5f; } else if (this->animationIdx == ENHORSE_ANIM_TROT) { animSpeed = this->actor.speedXZ * 0.25f; - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_KID_HORSE_RUN); } else { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_HORSE_RUN); } } else if (this->animationIdx == ENHORSE_ANIM_GALLOP) { animSpeed = this->actor.speedXZ * 0.2f; - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_KID_HORSE_RUN); } else { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_HORSE_RUN); @@ -2259,7 +2264,7 @@ void func_80881290(EnHorse* this, PlayState* play) { this->actor.gravity = 0.0f; this->actor.velocity.y = 0.0f; this->jumpStartY = this->actor.world.pos.y; - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_HORSE_JUMP); } else { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_HORSE_JUMP); @@ -2299,7 +2304,7 @@ void func_80881398(EnHorse* this, PlayState* play) { if (animeUpdated || ((curFrame > 17.0f) && (this->actor.world.pos.y < ((this->actor.floorHeight - this->actor.velocity.y) + 80.0f)))) { - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_HORSE_LAND); } else { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_HORSE_LAND); @@ -2371,14 +2376,14 @@ void func_8088168C(EnHorse* this) { animSpeed = this->actor.speedXZ * 0.5f; } else if (this->animationIdx == ENHORSE_ANIM_TROT) { animSpeed = this->actor.speedXZ * 0.25f; - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_KID_HORSE_RUN); } else { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_HORSE_RUN); } } else if (this->animationIdx == ENHORSE_ANIM_GALLOP) { animSpeed = this->actor.speedXZ * 0.2f; - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_KID_HORSE_RUN); } else { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_HORSE_RUN); @@ -2516,7 +2521,7 @@ void EnHorse_CsPlayHighJumpAnim(EnHorse* this, PlayState* play) { this->riderPos.y -= y * 0.01f * this->unk_528 * 0.01f; this->stateFlags |= ENHORSE_ANIM_HIGH_JUMP; - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_HORSE_JUMP); } else { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_HORSE_JUMP); @@ -2566,7 +2571,7 @@ void EnHorse_CsJump(EnHorse* this, PlayState* play, CsCmdActorAction* action) { ((curFrame > 19.0f) && (this->actor.world.pos.y < ((this->actor.floorHeight - this->actor.velocity.y) + 80.0f)))) { this->cutsceneFlags |= 1; - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_HORSE_LAND); } else { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_HORSE_LAND); @@ -2595,7 +2600,7 @@ void EnHorse_CsRearingInit(EnHorse* this, PlayState* play, CsCmdActorAction* act this->cutsceneFlags &= ~4; this->stateFlags &= ~ENHORSE_LAND2_SOUND; if (this->stateFlags & ENHORSE_DRAW) { - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->unk_218, NA_SE_EV_KID_HORSE_NEIGH); } else { Audio_PlaySfxAtPos(&this->unk_218, NA_SE_EV_HORSE_NEIGH); @@ -2610,7 +2615,7 @@ void EnHorse_CsRearing(EnHorse* this, PlayState* play, CsCmdActorAction* action) if (this->curFrame > 25.0f) { if (!(this->stateFlags & ENHORSE_LAND2_SOUND)) { this->stateFlags |= ENHORSE_LAND2_SOUND; - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_KID_HORSE_LAND2); } else { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_KID_HORSE_LAND2); @@ -2688,7 +2693,7 @@ void EnHorse_CsWarpRearingInit(EnHorse* this, PlayState* play, CsCmdActorAction* this->stateFlags &= ~ENHORSE_LAND2_SOUND; if (this->stateFlags & ENHORSE_DRAW) { - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->unk_218, NA_SE_EV_KID_HORSE_NEIGH); } else { Audio_PlaySfxAtPos(&this->unk_218, NA_SE_EV_HORSE_NEIGH); @@ -2703,7 +2708,7 @@ void EnHorse_CsWarpRearing(EnHorse* this, PlayState* play, CsCmdActorAction* act if (this->curFrame > 25.0f) { if (!(this->stateFlags & ENHORSE_LAND2_SOUND)) { this->stateFlags |= ENHORSE_LAND2_SOUND; - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_KID_HORSE_LAND2); } else { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_KID_HORSE_LAND2); @@ -2860,7 +2865,7 @@ void EnHorse_UpdateHbaAnim(EnHorse* this) { animSpeed = this->actor.speedXZ * 0.5f; } else if (this->animationIdx == ENHORSE_ANIM_TROT) { animSpeed = this->actor.speedXZ * 0.25f; - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_KID_HORSE_RUN); } else { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_HORSE_RUN); @@ -2868,7 +2873,7 @@ void EnHorse_UpdateHbaAnim(EnHorse* this) { Rumble_Request(0.0f, 60, 8, 255); } else if (this->animationIdx == ENHORSE_ANIM_GALLOP) { animSpeed = this->actor.speedXZ * 0.2f; - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_KID_HORSE_RUN); } else { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_HORSE_RUN); @@ -2952,9 +2957,9 @@ void EnHorse_FleePlayer(EnHorse* this, PlayState* play) { s32 animFinished; s16 yaw; - if ((D_801BDAA4 != 0) || (this->type == HORSE_HNI)) { + if ((D_801BDAA4 != 0) || (this->type == HORSE_TYPE_HNI)) { EnHorse_StartIdleRidable(this); - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_KID_HORSE_NEIGH); } else { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_HORSE_NEIGH); @@ -3059,7 +3064,7 @@ void EnHorse_FleePlayer(EnHorse* this, PlayState* play) { } else { this->animationIdx = ENHORSE_ANIM_WHINNEY; if (this->stateFlags & ENHORSE_DRAW) { - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->unk_218, NA_SE_EV_KID_HORSE_GROAN); } else { Audio_PlaySfxAtPos(&this->unk_218, NA_SE_EV_HORSE_GROAN); @@ -3331,12 +3336,12 @@ void func_80884994(EnHorse* this) { } void func_80884A40(EnHorse* this, PlayState* play) { - s32 sp44[] = { 5, 6, 0 }; + s32 sp44[] = { ENHORSE_ANIM_TROT, ENHORSE_ANIM_GALLOP, ENHORSE_ANIM_IDLE }; s32 sp40; s32 temp_v0; if (this->animationIdx == ENHORSE_ANIM_WHINNEY) { - temp_v0 = 0; + temp_v0 = ENHORSE_ANIM_IDLE; } else { temp_v0 = this->animationIdx; } @@ -3366,9 +3371,9 @@ void func_80884A40(EnHorse* this, PlayState* play) { 0.0f); } - if ((this->unk_538 == 0) || (this->unk_538 == 1)) { + if ((this->unk_538 == OBJ_UM_ANIM_TROT) || (this->unk_538 == OBJ_UM_ANIM_GALLOP)) { Actor_PlaySfxAtPos(&this->actor, NA_SE_EV_HORSE_RUN); - } else if (this->unk_538 == 2) { + } else if (this->unk_538 == OBJ_UM_ANIM_IDLE) { if (this->animationIdx == ENHORSE_ANIM_IDLE) { EnHorse_IdleAnimSounds(this, play); } else if (this->animationIdx == ENHORSE_ANIM_WHINNEY) { @@ -3392,6 +3397,7 @@ void func_80884D04(EnHorse* this, PlayState* play) { Animation_GetLastFrame(sAnimationHeaders[this->type][this->animationIdx]), ANIMMODE_ONCE, 0.0f); } +// Action func: EnHorse_UpdateBandit? void func_80884E0C(EnHorse* this, PlayState* play) { f32 playSpeed = (this->unk_56C * 0.2f * 0.5f) + 1.0f; Vec3f pos; @@ -3408,8 +3414,8 @@ void func_80884E0C(EnHorse* this, PlayState* play) { } this->unk_57C = this->actor.world.pos; - this->actor.world.pos.x = this->unk_570.x; - this->actor.world.pos.z = this->unk_570.z; + this->actor.world.pos.x = this->banditPosition.x; + this->actor.world.pos.z = this->banditPosition.z; this->unk_56C = Math3D_Distance(&this->actor.world.pos, &this->actor.prevPos); if (((this->unk_550 == 5) || (this->unk_550 == 7)) && (Player_GetMask(play) != PLAYER_MASK_CIRCUS_LEADER)) { @@ -3429,7 +3435,7 @@ void func_80884E0C(EnHorse* this, PlayState* play) { } this->actor.world.pos.y += this->actor.velocity.y * 0.5f; } else { - this->actor.world.pos.y = this->unk_570.y; + this->actor.world.pos.y = this->banditPosition.y; } } @@ -3536,7 +3542,7 @@ void EnHorse_CheckFloors(EnHorse* this, PlayState* play) { return; } - if (this->type != HORSE_2) { + if (this->type != HORSE_TYPE_2) { EnHorse_Vec3fOffset(&this->actor.world.pos, this->actor.shape.rot.y, 30.0f, 55.0f, &frontPos); } else { EnHorse_Vec3fOffset(&this->actor.world.pos, this->actor.shape.rot.y, 15.0f, 30.0f, &frontPos); @@ -3555,7 +3561,7 @@ void EnHorse_CheckFloors(EnHorse* this, PlayState* play) { return; } - if (this->type != HORSE_2) { + if (this->type != HORSE_TYPE_2) { EnHorse_Vec3fOffset(&this->actor.world.pos, this->actor.shape.rot.y, -30.0f, 55.0f, &backPos); } else { EnHorse_Vec3fOffset(&this->actor.world.pos, this->actor.shape.rot.y, -15.0f, 30.0f, &backPos); @@ -3732,7 +3738,7 @@ void EnHorse_UpdateBgCheckInfo(EnHorse* this, PlayState* play) { if ((this->actor.bgCheckFlags & 8) && (Math_CosS(this->actor.wallYaw - this->actor.world.rot.y) < -0.3f)) { if (this->actor.speedXZ > 4.0f) { this->actor.speedXZ -= 1.0f; - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_KID_HORSE_SANDDUST); } else { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_KID_HORSE_SANDDUST); @@ -3749,7 +3755,7 @@ void EnHorse_UpdateBgCheckInfo(EnHorse* this, PlayState* play) { this->unk_3E8 += ((-10.0f / this->actor.scale.y) - this->unk_3E8) * 0.5f; if (this->actor.speedXZ > 2.0f) { this->actor.speedXZ -= 1.0f; - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_KID_HORSE_SANDDUST); } else { Audio_PlaySfxAtPos(&this->actor.projectedPos, NA_SE_EV_KID_HORSE_SANDDUST); @@ -3990,7 +3996,7 @@ void func_80886C00(EnHorse* this, PlayState* play) { this->boostTimer = 0; if (this->numBoosts == 0) { this->boostRegenTime = 140; - } else if (this->type == HORSE_EPONA) { + } else if (this->type == HORSE_TYPE_EPONA) { if (this->stateFlags & ENHORSE_FIRST_BOOST_REGEN) { this->boostRegenTime = 60; this->stateFlags &= ~ENHORSE_FIRST_BOOST_REGEN; @@ -4001,7 +4007,7 @@ void func_80886C00(EnHorse* this, PlayState* play) { this->boostRegenTime = 70; } } else if ((this->stateFlags & ENHORSE_DRAW) && (Rand_ZeroOne() < 0.1f)) { - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->unk_218, NA_SE_EV_KID_HORSE_NEIGH); } else { Audio_PlaySfxAtPos(&this->unk_218, NA_SE_EV_HORSE_NEIGH); @@ -4056,7 +4062,7 @@ void EnHorse_RegenBoost(EnHorse* this, PlayState* play) { if (this->boostTimer == 8) { if ((Rand_ZeroOne() < 0.25f) && (this->stateFlags & ENHORSE_DRAW)) { - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->unk_218, NA_SE_EV_KID_HORSE_NEIGH); } else { Audio_PlaySfxAtPos(&this->unk_218, NA_SE_EV_HORSE_NEIGH); @@ -4175,9 +4181,9 @@ void EnHorse_Update(Actor* thisx, PlayState* play2) { Vec3f dustVel = { 0.0f, 1.0f, 0.0f }; Player* player = GET_PLAYER(play); - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Actor_SetScale(&this->actor, 0.00648f); - } else if (this->type == HORSE_4) { + } else if (this->type == HORSE_TYPE_DONKEY) { Actor_SetScale(&this->actor, 0.008f); } else { Actor_SetScale(&this->actor, 0.01f); @@ -4258,7 +4264,7 @@ void EnHorse_Update(Actor* thisx, PlayState* play2) { } if ((this->colliderJntSph.base.acFlags & AC_HIT) && (this->stateFlags & ENHORSE_DRAW)) { - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Audio_PlaySfxAtPos(&this->unk_218, NA_SE_EV_KID_HORSE_NEIGH); } else { Audio_PlaySfxAtPos(&this->unk_218, NA_SE_EV_HORSE_NEIGH); @@ -4290,7 +4296,7 @@ void EnHorse_Update(Actor* thisx, PlayState* play2) { Collider_UpdateCylinder(&this->actor, &this->colliderCylinder1); Collider_UpdateCylinder(&this->actor, &this->colliderCylinder2); - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { this->colliderCylinder1.dim.pos.x = (s16)(Math_SinS(thisx->shape.rot.y) * 11.0f) + this->colliderCylinder1.dim.pos.x; this->colliderCylinder1.dim.pos.z = @@ -4456,7 +4462,7 @@ void EnHorse_PostDraw(Actor* thisx, PlayState* play, Skin* skin) { f32 sp34; if (!(this->stateFlags & ENHORSE_CALC_RIDER_POS)) { - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Skin_GetVertexPos(skin, 5, 120, &this->riderPos); this->riderPos.y += 13.0f; } else { @@ -4471,7 +4477,7 @@ void EnHorse_PostDraw(Actor* thisx, PlayState* play, Skin* skin) { this->stateFlags &= ~ENHORSE_CALC_RIDER_POS; } - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Skin_GetLimbPos(skin, 13, &sp7C, &sp38); } else { Skin_GetLimbPos(skin, 13, &sp7C, &sp38); @@ -4492,7 +4498,7 @@ void EnHorse_PostDraw(Actor* thisx, PlayState* play, Skin* skin) { if (((curFrame > 10.0f) && (curFrame < 13.0f)) || ((curFrame > 25.0f) && (curFrame < 33.0f))) { if (Rand_ZeroOne() < 0.02f) { this->dustFlags |= 2; - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Skin_GetLimbPos(skin, 20, &hoofOffset, &sp64); } else { Skin_GetLimbPos(skin, 20, &hoofOffset, &sp64); @@ -4502,7 +4508,7 @@ void EnHorse_PostDraw(Actor* thisx, PlayState* play, Skin* skin) { if (Rand_ZeroOne() < 0.02f) { this->dustFlags |= 1; - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Skin_GetLimbPos(skin, 28, &hoofOffset, &sp64); } else { Skin_GetLimbPos(skin, 28, &hoofOffset, &sp64); @@ -4514,7 +4520,7 @@ void EnHorse_PostDraw(Actor* thisx, PlayState* play, Skin* skin) { if (((curFrame > 6.0f) && (curFrame < 10.0f)) || ((curFrame > 23.0f) && (curFrame < 29.0f))) { if (Rand_ZeroOne() < 0.02f) { this->dustFlags |= 8; - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Skin_GetLimbPos(skin, 36, &hoofOffset, &sp64); } else { Skin_GetLimbPos(skin, 37, &hoofOffset, &sp64); @@ -4526,7 +4532,7 @@ void EnHorse_PostDraw(Actor* thisx, PlayState* play, Skin* skin) { if ((((curFrame > 7.0f) && (curFrame < 14.0f)) || ((curFrame > 26.0f) && (curFrame < 30.0f))) && (Rand_ZeroOne() < 0.02f)) { this->dustFlags |= 4; - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Skin_GetLimbPos(skin, 44, &hoofOffset, &sp64); } else { Skin_GetLimbPos(skin, 45, &hoofOffset, &sp64); @@ -4536,7 +4542,7 @@ void EnHorse_PostDraw(Actor* thisx, PlayState* play, Skin* skin) { } else if (this->animationIdx == ENHORSE_ANIM_GALLOP) { if ((curFrame > 14.0f) && (curFrame < 16.0f) && (Rand_ZeroOne() < 0.02f)) { this->dustFlags |= 1; - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Skin_GetLimbPos(skin, 28, &hoofOffset, &sp64); } else { Skin_GetLimbPos(skin, 28, &hoofOffset, &sp64); @@ -4544,7 +4550,7 @@ void EnHorse_PostDraw(Actor* thisx, PlayState* play, Skin* skin) { EnHorse_RandomOffset(&sp64, 5.0f, &this->frontRightHoof); } else if ((curFrame > 8.0f) && (curFrame < 10.0f) && (Rand_ZeroOne() < 0.02f)) { this->dustFlags |= 2; - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Skin_GetLimbPos(skin, 20, &hoofOffset, &sp64); } else { Skin_GetLimbPos(skin, 20, &hoofOffset, &sp64); @@ -4552,7 +4558,7 @@ void EnHorse_PostDraw(Actor* thisx, PlayState* play, Skin* skin) { EnHorse_RandomOffset(&sp64, 10.0f, &this->frontLeftHoof); } else if ((curFrame > 1.0f) && (curFrame < 3.0f) && (Rand_ZeroOne() < 0.02f)) { this->dustFlags |= 4; - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Skin_GetLimbPos(skin, 44, &hoofOffset, &sp64); } else { Skin_GetLimbPos(skin, 45, &hoofOffset, &sp64); @@ -4560,7 +4566,7 @@ void EnHorse_PostDraw(Actor* thisx, PlayState* play, Skin* skin) { EnHorse_RandomOffset(&sp64, 10.0f, &this->backRightHoof); } else if ((curFrame > 26.0f) && (curFrame < 28.0f) && (Rand_ZeroOne() < 0.02f)) { this->dustFlags |= 8; - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Skin_GetLimbPos(skin, 36, &hoofOffset, &sp64); } else { Skin_GetLimbPos(skin, 37, &hoofOffset, &sp64); @@ -4571,7 +4577,7 @@ void EnHorse_PostDraw(Actor* thisx, PlayState* play, Skin* skin) { (Rand_ZeroOne() < (1.0f - ((curFrame - 6.0f) * (1.0f / 17.0f))))) { if (Rand_ZeroOne() < 0.05f) { this->dustFlags |= 8; - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Skin_GetLimbPos(skin, 36, &hoofOffset, &sp64); } else { Skin_GetLimbPos(skin, 37, &hoofOffset, &sp64); @@ -4580,7 +4586,7 @@ void EnHorse_PostDraw(Actor* thisx, PlayState* play, Skin* skin) { } if (Rand_ZeroOne() < 0.02f) { this->dustFlags |= 4; - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Skin_GetLimbPos(skin, 44, &hoofOffset, &sp64); } else { Skin_GetLimbPos(skin, 45, &hoofOffset, &sp64); @@ -4591,7 +4597,7 @@ void EnHorse_PostDraw(Actor* thisx, PlayState* play, Skin* skin) { if (Rand_ZeroOne() < (1.0f - ((curFrame - 5.0f) * 0.04f))) { if (Rand_ZeroOne() < 0.05f) { this->dustFlags |= 8; - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Skin_GetLimbPos(skin, 36, &hoofOffset, &sp64); } else { Skin_GetLimbPos(skin, 37, &hoofOffset, &sp64); @@ -4601,7 +4607,7 @@ void EnHorse_PostDraw(Actor* thisx, PlayState* play, Skin* skin) { if (Rand_ZeroOne() < 0.02f) { this->dustFlags |= 4; - if (this->type == HORSE_2) { + if (this->type == HORSE_TYPE_2) { Skin_GetLimbPos(skin, 44, &hoofOffset, &sp64); } else { Skin_GetLimbPos(skin, 45, &hoofOffset, &sp64); @@ -4649,12 +4655,12 @@ s32 EnHorse_OverrideLimbDraw(Actor* thisx, PlayState* play, s32 limbIndex, Skin* OPEN_DISPS(play->state.gfxCtx); - if ((limbIndex != 13) || (this->type != HORSE_EPONA)) { - if ((limbIndex == 13) && (this->type == HORSE_2)) { + if ((limbIndex != 13) || (this->type != HORSE_TYPE_EPONA)) { + if ((limbIndex == 13) && (this->type == HORSE_TYPE_2)) { u8 idx = D_80889210[this->blinkTimer]; gSPSegment(POLY_OPA_DISP++, 0x08, Lib_SegmentedToVirtual(D_80889204[idx])); - } else if ((this->type == HORSE_HNI) && (this->stateFlags & ENHORSE_FLAG_18) && (limbIndex == 30)) { + } else if ((this->type == HORSE_TYPE_HNI) && (this->stateFlags & ENHORSE_FLAG_18) && (limbIndex == 30)) { drawOriginalLimb = false; } } diff --git a/src/overlays/actors/ovl_En_Horse/z_en_horse.h b/src/overlays/actors/ovl_En_Horse/z_en_horse.h index a05e1a2c58..9f32331c6d 100644 --- a/src/overlays/actors/ovl_En_Horse/z_en_horse.h +++ b/src/overlays/actors/ovl_En_Horse/z_en_horse.h @@ -3,11 +3,11 @@ #include "global.h" #include "z64skin.h" -#include "overlays/actors/ovl_En_In/z_en_in.h" #include "objects/gameplay_keep/gameplay_keep.h" #include "objects/object_ha/object_ha.h" struct EnHorse; +struct EnIn; typedef void (*EnHorseActionFunc)(struct EnHorse*, PlayState*); typedef void (*EnHorsePostdrawFunc)(struct EnHorse*, PlayState*); @@ -97,18 +97,22 @@ typedef enum { } EnHorseAnimationIndex; typedef enum { - /* 0 */ HORSE_EPONA, - /* 1 */ HORSE_HNI, - /* 2 */ HORSE_2, - /* 3 */ HORSE_3, - /* 4 */ HORSE_4 + /* 0 */ HORSE_TYPE_EPONA, + /* 1 */ HORSE_TYPE_HNI, + /* 2 */ HORSE_TYPE_2, + /* 3 */ HORSE_TYPE_BANDIT, + /* 4 */ HORSE_TYPE_DONKEY // Cremia's donkey } HorseType; -#define ENHORSE_GET_2000(thisx) ((thisx)->params & 0x2000) -#define ENHORSE_GET_4000(thisx) ((thisx)->params & 0x4000) -#define ENHORSE_GET_8000(thisx) ((thisx)->params & 0x8000) +#define ENHORSE_PARAM_BANDIT 0x2000 +#define ENHORSE_PARAM_4000 0x4000 +#define ENHORSE_PARAM_DONKEY 0x8000 -enum { +#define ENHORSE_IS_BANDIT_TYPE(thisx) ((thisx)->params & ENHORSE_PARAM_BANDIT) +#define ENHORSE_IS_4000_TYPE(thisx) ((thisx)->params & ENHORSE_PARAM_4000) +#define ENHORSE_IS_DONKEY_TYPE(thisx) ((thisx)->params & ENHORSE_PARAM_DONKEY) + +typedef enum { /* 0 */ ENHORSE_0, /* 1 */ ENHORSE_1, /* 2 */ ENHORSE_2, @@ -130,7 +134,13 @@ enum { /* 18 */ ENHORSE_18, /* 19 */ ENHORSE_19, /* 20 */ ENHORSE_20, -}; +} EnHorseParam; + +/** + * `paramtype` should be `ENHORSE_PARAM_BANDIT`, `ENHORSE_PARAM_4000` or `ENHORSE_PARAM_DONKEY` + * `lower` should be a value of the enum `EnHorseParam` + */ +#define ENHORSE_PARAMS(type, lower) ((type) | (lower)) typedef struct EnHorse { /* 0x000 */ Actor actor; @@ -180,7 +190,7 @@ typedef struct EnHorse { /* 0x384 */ u16 cutsceneFlags; /* 0x388 */ s32 inRace; /* 0x38C */ struct EnIn* rider; - /* 0x390 */ UNK_TYPE1 unk390[0x4]; + /* 0x390 */ UNK_TYPE1 unk_390[0x4]; /* 0x394 */ u16 unk_394; /* 0x398 */ f32 unk_398; /* 0x39C */ s32 unk_39C; @@ -193,7 +203,7 @@ typedef struct EnHorse { /* 0x3C8 */ Vec3f backRightHoof; /* 0x3D4 */ Vec3f backLeftHoof; /* 0x3E0 */ s32 unk_3E0; - /* 0x3E4 */ UNK_TYPE1 unk3E4[0x4]; + /* 0x3E4 */ UNK_TYPE1 unk_3E4[0x4]; /* 0x3E8 */ f32 unk_3E8; /* 0x3EC */ s16 unk_3EC; /* 0x3EE */ Vec3s jointTable[OBJECT_HA_1_LIMB_MAX]; @@ -205,13 +215,19 @@ typedef struct EnHorse { /* 0x538 */ s32 unk_538; /* 0x53C */ s32 unk_53C; /* 0x540 */ Vec3f unk_540; - /* 0x54C */ UNK_TYPE1 unk54C[0x4]; + /* 0x54C */ UNK_TYPE unk_54C; /* 0x550 */ s32 unk_550; - /* 0x554 */ UNK_TYPE1 unk554[0x18]; + /* 0x554 */ UNK_TYPE unk_554; + /* 0x558 */ UNK_TYPE unk_558; + /* 0x55C */ s32 unk_55C; // maybe currentDistanceToCart... it isn't really a distance tho + /* 0x560 */ s32 unk_560; // maybe initialDistanceToCart + /* 0x564 */ s32 unk_564; // set but not used + /* 0x568 */ f32 unk_568; // set but not used /* 0x56C */ f32 unk_56C; - /* 0x570 */ Vec3f unk_570; + /* 0x570 */ Vec3f banditPosition; // Milk run minigame bandit /* 0x57C */ Vec3f unk_57C; - /* 0x588 */ UNK_TYPE1 unk588[0x4]; + /* 0x588 */ s16 unk_588; + /* 0x58A */ UNK_TYPE1 unk_58A[0x2]; // struct padding? /* 0x58C */ s32 unk_58C; /* 0x590 */ s32 unk_590; } EnHorse; // size = 0x594 diff --git a/src/overlays/actors/ovl_En_Horse_Game_Check/z_en_horse_game_check.c b/src/overlays/actors/ovl_En_Horse_Game_Check/z_en_horse_game_check.c index 278ec71441..f3ec0c245c 100644 --- a/src/overlays/actors/ovl_En_Horse_Game_Check/z_en_horse_game_check.c +++ b/src/overlays/actors/ovl_En_Horse_Game_Check/z_en_horse_game_check.c @@ -124,14 +124,14 @@ s32 func_808F8CCC(EnHorseGameCheck* this, PlayState* play2) { func_8010E9F0(4, 0); play->interfaceCtx.unk_280 = 1; - this->horse1 = - (EnHorse*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, -1149.0f, -106.0f, 470.0f, 0, 0x7FFF, 0, 0x2004); + this->horse1 = (EnHorse*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, -1149.0f, -106.0f, 470.0f, 0, 0x7FFF, 0, + ENHORSE_PARAMS(ENHORSE_PARAM_BANDIT, ENHORSE_4)); if (this->horse1 == NULL) { __assert("../z_en_horse_game_check.c", 1517); } - this->horse2 = - (EnHorse*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, -1376.0f, -106.0f, 470.0f, 0, 0x7FFF, 0, 0x2005); + this->horse2 = (EnHorse*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, -1376.0f, -106.0f, 470.0f, 0, 0x7FFF, 0, + ENHORSE_PARAMS(ENHORSE_PARAM_BANDIT, ENHORSE_5)); if (this->horse2 == NULL) { __assert("../z_en_horse_game_check.c", 1526); } diff --git a/src/overlays/actors/ovl_En_Test4/z_en_test4.c b/src/overlays/actors/ovl_En_Test4/z_en_test4.c index ef82244535..5311b35a6e 100644 --- a/src/overlays/actors/ovl_En_Test4/z_en_test4.c +++ b/src/overlays/actors/ovl_En_Test4/z_en_test4.c @@ -404,7 +404,7 @@ void func_80A42AB8(EnTest4* this, PlayState* play) { if (player->stateFlags1 & 0x800000) { EnHorse* rideActor = (EnHorse*)player->rideActor; - if ((rideActor->type == HORSE_EPONA) || (rideActor->type == HORSE_2)) { + if ((rideActor->type == HORSE_TYPE_EPONA) || (rideActor->type == HORSE_TYPE_2)) { if (CURRENT_DAY < 3) { D_801BDA9C = 1; } else { diff --git a/src/overlays/actors/ovl_Obj_Um/z_obj_um.c b/src/overlays/actors/ovl_Obj_Um/z_obj_um.c index 5175a8ee10..658cae6525 100644 --- a/src/overlays/actors/ovl_Obj_Um/z_obj_um.c +++ b/src/overlays/actors/ovl_Obj_Um/z_obj_um.c @@ -1,39 +1,66 @@ /* * File: z_obj_um.c * Overlay: ovl_Obj_Um - * Description: Cremia's cart and milk run quest + * Description: Cremia's Cart and milk run minigame */ #include "z_obj_um.h" +#include "overlays/actors/ovl_En_In/z_en_in.h" +#include "objects/gameplay_keep/gameplay_keep.h" #define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_8 | ACTOR_FLAG_10 | ACTOR_FLAG_20) #define THIS ((ObjUm*)thisx) +/** + * weekEventReg flags checked by this actor: + * - gSaveContext.save.weekEventReg[22] & 1: Aliens defeated + * If false: The actor doesn't spawn + * - gSaveContext.save.weekEventReg[31] & 0x40 + * If true: Cremia doesn't explain again she'll deliever milk to town + * - gSaveContext.save.weekEventReg[31] & 0x80 + * If true: Triggers cutscene on Romani's Ranch + * - gSaveContext.save.weekEventReg[34] & 0x80 + * If true: Doesn't spawn on Romani's Ranch + * - gSaveContext.save.weekEventReg[52] & 1 + * If true: Doesn't spawn on Romani's Ranch or Milk Road + * - gSaveContext.save.weekEventReg[52] & 2 + * If true: Doesn't spawn on Romani's Ranch or Milk Road + * - gSaveContext.save.weekEventReg[59] & 2 + * If true: Doesn't spawn again on Milk Road + * + * weekEventReg flags set by this actor: + * - gSaveContext.save.weekEventReg[31] |= 0x40: Cremia offered a ride + * Cremia offered a ride accross the Milk Road to Player + * - gSaveContext.save.weekEventReg[31] |= 0x80: Player is in Milk Run + * Player accepts the ride and is with Cremia during the Milk Run. + * - gSaveContext.save.weekEventReg[34] |= 0x80: Cremia does Milk Run alone + * Player didn't interact or didn't accept the ride + * - gSaveContext.save.weekEventReg[52] |= 1: Won Milk Run minigame + * At least one pot is safe. Turns off the "Lose Milk Run minigame" + * - gSaveContext.save.weekEventReg[52] |= 2: Lose Milk Run minigame + * Every pot was broken by bandits. Turns off the "Win Milk Run minigame" + * - gSaveContext.save.weekEventReg[59] |= 2: ? + * Passed through Milk Road after winning the Milk Run + * + * weekEventReg flags unset by this actor: + * - gSaveContext.save.weekEventReg[31] &= (u8)~0x80 + * Turned off when the Milk Run finishes + * - gSaveContext.save.weekEventReg[52] &= (u8)~1 + * Turned off if Player lose the Milk Run + * - gSaveContext.save.weekEventReg[52] &= (u8)~2 + * Turned off if Player wins the Milk Run + */ + void ObjUm_Init(Actor* thisx, PlayState* play); void ObjUm_Destroy(Actor* thisx, PlayState* play); void ObjUm_Update(Actor* thisx, PlayState* play); void ObjUm_Draw(Actor* thisx, PlayState* play); -void func_80B79A50(ObjUm* this, PlayState* play); -void func_80B79F10(ObjUm* this, PlayState* play); -void func_80B7A070(ObjUm* this, PlayState* play); -void func_80B7A0E0(ObjUm* this, PlayState* play); -void func_80B7A144(ObjUm* this, PlayState* play); -void func_80B7A2AC(ObjUm* this, PlayState* play); -void func_80B7A394(ObjUm* this, PlayState* play); -void func_80B7A400(ObjUm* this, PlayState* play); -void func_80B7A494(ObjUm* this, PlayState* play); -void func_80B7A614(ObjUm* this, PlayState* play); -void func_80B7A7AC(ObjUm* this, PlayState* play); -void func_80B7ABE4(ObjUm* this, PlayState* play); -void func_80B7AC94(ObjUm* this, PlayState* play); -void func_80B7AD34(ObjUm* this, PlayState* play); -void func_80B7AE58(ObjUm* this, PlayState* play); - +void ObjUm_DefaultAnim(ObjUm* this, PlayState* play); +void ObjUm_UpdateAnim(ObjUm* this, PlayState* play, ObjUmAnimimations index); void ObjUm_SetupAction(ObjUm* this, ObjUmActionFunc actionFunc); -#if 0 const ActorInit Obj_Um_InitVars = { ACTOR_OBJ_UM, ACTORCAT_NPC, @@ -46,131 +73,1949 @@ const ActorInit Obj_Um_InitVars = { (ActorFunc)ObjUm_Draw, }; -// static ColliderCylinderInit sCylinderInit = { -static ColliderCylinderInit D_80B7C138 = { - { COLTYPE_HIT3, AT_NONE, AC_ON | AC_TYPE_PLAYER, OC1_NONE, OC2_TYPE_1, COLSHAPE_CYLINDER, }, - { ELEMTYPE_UNK1, { 0x00000000, 0x00, 0x00 }, { 0x00000020, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, }, +static TexturePtr sEyeTextures[] = { + gUmCremiaEyeOpenTex, gUmCremiaEyeHalfTex, gUmCremiaEyeClosedTex, + gUmCremiaEyeHappyTex, gUmCremiaEyeAngryTex, gUmCremiaEyeSadTex, +}; + +static TexturePtr sMouthTextures[] = { + gUmMouthNormalTex, + gUmMouthHappyTex, + gUmMouthHangingOpenTex, + gUmMouthFrownTex, +}; + +static ColliderCylinderInit sCylinderInit = { + { + COLTYPE_HIT3, + AT_NONE, + AC_ON | AC_TYPE_PLAYER, + OC1_NONE, + OC2_TYPE_1, + COLSHAPE_CYLINDER, + }, + { + ELEMTYPE_UNK1, + { 0x00000000, 0x00, 0x00 }, + { 0x00000020, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_NONE, + }, { 40, 64, 0, { 0, 0, 0 } }, }; -// static InitChainEntry sInitChain[] = { -static InitChainEntry D_80B7C254[] = { +// actionfuncs +void func_80B7A144(ObjUm* this, PlayState* play); +void ObjUm_RanchWait(ObjUm* this, PlayState* play); +void ObjUm_PreMilkRunStartCs(ObjUm* this, PlayState* play); +void ObjUm_StartCs(ObjUm* this, PlayState* play); +void ObjUm_PostMilkRunStartCs(ObjUm* this, PlayState* play); +void ObjUm_TerminaFieldIdle(ObjUm* this, PlayState* play); +void ObjUm_RanchWaitPathFinished(ObjUm* this, PlayState* play); +void func_80B7A0E0(ObjUm* this, PlayState* play); +void func_80B7A070(ObjUm* this, PlayState* play); +void ObjUm_RanchStartCs(ObjUm* this, PlayState* play); +void func_80B7A2AC(ObjUm* this, PlayState* play); +void func_80B7A240(ObjUm* this, PlayState* play); +void func_80B7A394(ObjUm* this, PlayState* play); +void ObjUm_RunMinigame(ObjUm* this, PlayState* play); +void func_80B7A614(ObjUm* this, PlayState* play); +void func_80B7AB78(ObjUm* this, PlayState* play); +void func_80B7ABE4(ObjUm* this, PlayState* play); +void ObjUm_PostMilkRunWaitPathFinished(ObjUm* this, PlayState* play); + +// Maybe it is updating the bandits positions? +void func_80B77770(ObjUm* this, PlayState* play) { + s16 rotY = this->dyna.actor.shape.rot.y; + Vec3f sp108; + Vec3f spFC; + Vec3f spF0; + Vec3f spE4; + Vec3f spD8; + Vec3f spCC; + Vec3f spC0; + Vec3f spB4; + Vec3f spA8; + Vec3f sp9C; + Vec3f sp90; + Vec3f sp84; + Vec3f sp78; + Vec3f sp6C; + Vec3f sp60 = this->dyna.actor.world.pos; + + // Loop unroll? + this->unk_360[15] = sp60; + sp6C = sp60; + this->unk_360[14] = sp6C; + sp78 = sp6C; + this->unk_360[13] = sp78; + sp84 = sp78; + this->unk_360[12] = sp84; + sp90 = sp84; + this->unk_360[11] = sp90; + sp9C = sp90; + this->unk_360[10] = sp9C; + spA8 = sp9C; + this->unk_360[9] = spA8; + spB4 = spA8; + this->unk_360[8] = spB4; + spC0 = spB4; + this->unk_360[7] = spC0; + spCC = spC0; + this->unk_360[6] = spCC; + spD8 = spCC; + this->unk_360[5] = spD8; + spE4 = spD8; + this->unk_360[4] = spE4; + spF0 = spE4; + this->unk_360[3] = spF0; + spFC = spF0; + this->unk_360[2] = spFC; + sp108 = spFC; + this->unk_360[1] = sp108; + this->unk_360[0] = sp108; + + this->unk_360[0].x += 110.0f * Math_SinS(rotY + 0x4000); + this->unk_360[0].z += 110.0f * Math_CosS(rotY + 0x4000); + this->unk_360[1].x += 110.0f * Math_SinS(rotY - 0x4000); + this->unk_360[1].z += 110.0f * Math_CosS(rotY - 0x4000); + Math_Vec3f_Copy(&this->unk_360[2], &this->unk_360[0]); + this->unk_360[2].x -= 200.0f * Math_SinS(rotY); + this->unk_360[2].z -= 200.0f * Math_CosS(rotY); + Math_Vec3f_Copy(&this->unk_360[4], &this->unk_360[1]); + this->unk_360[4].x -= 200.0f * Math_SinS(rotY); + this->unk_360[4].z -= 200.0f * Math_CosS(rotY); + this->unk_360[3].x -= 220.0f * Math_SinS(rotY); + this->unk_360[3].z -= 220.0f * Math_CosS(rotY); + Math_Vec3f_Copy(&this->unk_360[5], &this->unk_360[0]); + this->unk_360[5].x -= 500.0f * Math_SinS(rotY); + this->unk_360[5].z -= 500.0f * Math_CosS(rotY); + Math_Vec3f_Copy(&this->unk_360[7], &this->unk_360[1]); + this->unk_360[7].x -= 500.0f * Math_SinS(rotY); + this->unk_360[7].z -= 500.0f * Math_CosS(rotY); + this->unk_360[6].x -= 500.0f * Math_SinS(rotY); + this->unk_360[6].z -= 500.0f * Math_CosS(rotY); + Math_Vec3f_Copy(&this->unk_360[8], &this->unk_360[0]); + this->unk_360[8].x -= 700.0f * Math_SinS(rotY); + this->unk_360[8].z -= 700.0f * Math_CosS(rotY); + Math_Vec3f_Copy(&this->unk_360[10], &this->unk_360[1]); + this->unk_360[10].x -= 700.0f * Math_SinS(rotY); + this->unk_360[10].z -= 700.0f * Math_CosS(rotY); + this->unk_360[9].x -= 700.0f * Math_SinS(rotY); + this->unk_360[9].z -= 700.0f * Math_CosS(rotY); + this->unk_360[11] = this->unk_360[3]; + this->unk_360[11].x += 40.0f * Math_SinS(rotY + 0x4000); + this->unk_360[11].z += 40.0f * Math_CosS(rotY + 0x4000); + this->unk_360[12] = this->unk_360[3]; + this->unk_360[12].x += 40.0f * Math_SinS(rotY - 0x4000); + this->unk_360[12].z += 40.0f * Math_CosS(rotY - 0x4000); + this->unk_360[13] = this->unk_360[2]; + this->unk_360[14] = this->unk_360[4]; +} + +s32 ObjUm_InitBandits(ObjUm* this, PlayState* play) { + Path* path = &play->setupPathList[this->pathIndex]; + s16 pad; + Vec3s* spawnPoints; + EnHorse* bandit1; + EnHorse* bandit2; + + spawnPoints = Lib_SegmentedToVirtual(path->points); + Audio_QueueSeqCmd(0x8000 | NA_BGM_CHASE); + + bandit1 = (EnHorse*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, spawnPoints[0].x, spawnPoints[0].y, + spawnPoints[0].z, 0, this->dyna.actor.shape.rot.y, 0, + ENHORSE_PARAMS(ENHORSE_PARAM_BANDIT, ENHORSE_19)); + this->bandit1 = bandit1; + + bandit1->unk_540 = bandit1->actor.world.pos; + + bandit1->unk_54C = 0xF; + bandit1->unk_550 = 10; + + bandit1->unk_554 = this->pathIndex; + bandit1->unk_568 = 0.0f; + bandit1->unk_56C = 0.0f; + bandit1->unk_558 = 0; + bandit1->unk_55C = 40; + bandit1->unk_560 = 40; + + bandit1->banditPosition = gZeroVec3f; + bandit1->unk_57C = gZeroVec3f; + + bandit1->unk_588 = this->dyna.actor.shape.rot.y; + bandit1->curRaceWaypoint = 1; + + bandit2 = (EnHorse*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, spawnPoints[1].x, spawnPoints[1].y, + spawnPoints[1].z, 0, this->dyna.actor.shape.rot.y, 0, + ENHORSE_PARAMS(ENHORSE_PARAM_BANDIT, ENHORSE_20)); + this->bandit2 = bandit2; + + bandit2->unk_540 = bandit2->actor.world.pos; + + bandit2->unk_54C = 0xF; + bandit2->unk_550 = 8; + + bandit2->unk_554 = this->pathIndex; + bandit2->unk_568 = 0.0f; + bandit2->unk_56C = 0.0f; + bandit2->unk_55C = 40; + bandit2->unk_560 = 40; + + bandit2->unk_57C = gZeroVec3f; + + bandit2->unk_588 = this->dyna.actor.shape.rot.y; + bandit2->curRaceWaypoint = 2; + + this->potsLife[0] = 4; + this->potsLife[1] = 4; + this->potsLife[2] = 4; + + return 0; +} + +typedef struct { + /* 0x00 */ s32 unk_00; + /* 0x04 */ s32 unk_04; + /* 0x08 */ s32 unk_08; + /* 0x0C */ f32 unk_0C; + /* 0x10 */ s32 unk_10; +} struct_80B7C254; // size = 0x14 + +struct_80B7C254 D_80B7C164[] = { + { 2, 0, 0, 1.0f, 40 }, { 4, 1, 0, 1.0f, 40 }, { 3, 2, 0, 1.0f, 40 }, { 3, 4, 0, 1.0f, 40 }, + { 5, 3, 1, -1.0f, 30 }, { 7, 3, 1, 1.0f, 30 }, { 0, 13, 1, -1.0f, 60 }, { 1, 14, 1, 1.0f, 60 }, + { 13, 10, 0, 1.0f, 40 }, { 14, 8, 0, 1.0f, 40 }, { 8, 5, 0, 1.0f, 30 }, { 10, 7, 0, 1.0f, 30 }, +}; + +// BanditAttack? +s32 func_80B781DC(ObjUm* this, EnHorse* bandit1, EnHorse* bandit2, PlayState* play) { + s32 temp_v0; + s32 phi_s3 = -1; + s32 phi_s4 = 0; + s32 phi_s2 = 0; + f32 phi_f20 = 0.0f; + s32 i; + s32 mask; + + for (i = 0; i < ARRAY_COUNT(D_80B7C164); i++) { + if (bandit1->unk_550 == D_80B7C164[i].unk_00) { + if (bandit2->unk_550 != D_80B7C164[i].unk_04) { + if (D_80B7C164[i].unk_00 != 3) { + if (D_80B7C164[i].unk_04 != 3 || + ((mask = Player_GetMask(play)), PLAYER_MASK_CIRCUS_LEADER != mask)) { + phi_s3 = D_80B7C164[i].unk_04; + phi_s4 = D_80B7C164[i].unk_08; + phi_f20 = D_80B7C164[i].unk_0C; + phi_s2 = D_80B7C164[i].unk_10; + } + } else if (((bandit1->unk_54C != 5) || (D_80B7C164[i].unk_04 != 2)) && + ((bandit1->unk_54C != 7) || (D_80B7C164[i].unk_04 != 4))) { + phi_s3 = D_80B7C164[i].unk_04; + phi_s4 = D_80B7C164[i].unk_08; + phi_f20 = D_80B7C164[i].unk_0C; + if ((2.0f * Rand_ZeroOne()) < 1.0f) { + phi_f20 *= -1.0f; + } + phi_s2 = D_80B7C164[i].unk_10; + } + //! FAKE: + ; + } + } + } + + if (phi_s3 == -1) { + return 0; + } + + bandit1->unk_540 = bandit1->actor.world.pos; + bandit1->unk_54C = bandit1->unk_550; + bandit1->unk_550 = phi_s3; + bandit1->unk_55C = phi_s2; + bandit1->unk_560 = phi_s2; + bandit1->unk_564 = phi_s4; + bandit1->unk_568 = phi_f20; + + if (phi_s3 == 3) { + f32 rand = Rand_ZeroOne(); + + bandit1->unk_558 = (s32)(rand * 3.0f); + } else { + bandit1->unk_558 = 0; + } + + return 0; +} + +// ObjUm_Bandit_UpdatePosition? +s32 func_80B783E0(ObjUm* this, PlayState* play, s32 banditIndex, EnHorse* bandit) { + Path* sp6C = &play->setupPathList[this->pathIndex]; + s32 sp68; + Vec3s* sp64; + f32 phi_f12; + s32 phi_v1_2; + Vec3f sp50; + f32 sp4C; + f32 sp48; + f32 sp44; + s32 temp_a1; + f32 sp3C; + f32 phi_f14; + + sp68 = sp6C->count; + sp64 = Lib_SegmentedToVirtual(sp6C->points); + + if (sp68 == 0) { + return 0; + } + + if (Math3D_Distance(&bandit->actor.world.pos, &this->dyna.actor.world.pos) < 800.0f) { + if (banditIndex == 0) { + this->flags |= OBJ_UM_FLAG_0200; + } else { + this->flags |= OBJ_UM_FLAG_0400; + } + bandit->unk_540 = bandit->actor.world.pos; + bandit->unk_55C = 50; + bandit->unk_560 = 50; + bandit->unk_564 = 1; + } + + Math_Vec3s_ToVec3f(&sp50, &sp64[bandit->curRaceWaypoint]); + + if (bandit->curRaceWaypoint == 0) { + phi_f12 = sp64[1].x - sp64[0].x; + phi_f14 = sp64[1].z - sp64[0].z; + } else { + if ((bandit->curRaceWaypoint + 1) == sp6C->count) { + phi_f12 = sp64[sp6C->count - 1].x - sp64[sp6C->count - 2].x; + phi_f14 = sp64[sp6C->count - 1].z - sp64[sp6C->count - 2].z; + } else { + phi_f12 = sp64[bandit->curRaceWaypoint + 1].x - sp64[bandit->curRaceWaypoint - 1].x; + phi_f14 = sp64[bandit->curRaceWaypoint + 1].z - sp64[bandit->curRaceWaypoint - 1].z; + } + } + + temp_a1 = Math_Atan2S(phi_f12, phi_f14); + + func_8017B7F8(&sp50, temp_a1, &sp4C, &sp48, &sp44); + if (((bandit->actor.world.pos.x * sp4C) + (sp48 * bandit->actor.world.pos.z) + sp44) > 0.0f) { + bandit->curRaceWaypoint++; + if (bandit->curRaceWaypoint >= sp68) { + bandit->curRaceWaypoint = 0; + } + Math_Vec3s_ToVec3f(&sp50, &sp64[bandit->curRaceWaypoint]); + } + + bandit->actor.world.rot.y = Math_Vec3f_Yaw(&bandit->actor.world.pos, &sp50); + bandit->actor.speedXZ = 45.0f; + + sp3C = Math_CosS(bandit->actor.world.rot.x) * bandit->actor.speedXZ; + bandit->actor.velocity.x = Math_SinS(bandit->actor.world.rot.y) * sp3C; + bandit->actor.velocity.y = Math_SinS(bandit->actor.world.rot.x) * bandit->actor.speedXZ; + bandit->actor.velocity.z = Math_CosS(bandit->actor.world.rot.y) * sp3C; + + bandit->banditPosition.x = + bandit->actor.world.pos.x + (bandit->actor.velocity.x * 0.5f) + bandit->actor.colChkInfo.displacement.x; + bandit->banditPosition.y = + bandit->actor.world.pos.y + (bandit->actor.velocity.y * 0.5f) + bandit->actor.colChkInfo.displacement.y; + bandit->banditPosition.z = + bandit->actor.world.pos.z + (bandit->actor.velocity.z * 0.5f) + bandit->actor.colChkInfo.displacement.z; + + phi_v1_2 = BINANG_SUB(bandit->actor.world.rot.y, bandit->actor.shape.rot.y); + + if (phi_v1_2 > 0x190) { + phi_v1_2 = 0x190; + } else if (phi_v1_2 < -0x190) { + phi_v1_2 = -0x190; + } + + bandit->actor.shape.rot.y = bandit->actor.shape.rot.y + phi_v1_2; + return 0; +} + +// ObjUm_Bandit_GetCloserAndAttack +s32 func_80B78764(ObjUm* this, PlayState* play, EnHorse* bandit1, EnHorse* bandit2) { + s32 pad; + Vec3f sp30; + s16 phi_v1_5; + + bandit1->unk_55C--; + if (bandit1->unk_55C <= 0) { + bandit1->unk_55C = 0; + + if ((bandit1->unk_550 == 3) && !(this->flags & OBJ_UM_FLAG_MINIGAME_FINISHED)) { + s32 potIndex = -1; + + if (this->potsLife[0] != 1) { + potIndex = 0; + } + + if (this->potsLife[1] != 1) { + if ((potIndex == -1) || (potIndex == 0 && Rand_ZeroOne() < 0.3f)) { + potIndex = 1; + } + } + + if (this->potsLife[2] != 1) { + if ((potIndex == -1) || (potIndex != -1 && Rand_ZeroOne() < 0.3f)) { + potIndex = 2; + } + } + + if (this->potsLife[potIndex] != 1) { + this->wasPotHit[potIndex] = true; + if (this->potsLife[potIndex] == 2) { + Audio_PlaySfxAtPos(&this->potPos[potIndex], NA_SE_EV_MILK_POT_BROKEN); + } else { + Audio_PlaySfxAtPos(&this->potPos[potIndex], NA_SE_EV_MILK_POT_DAMAGE); + } + + this->potsLife[potIndex]--; + if (this->potsLife[potIndex] < 1) { + this->potsLife[potIndex] = 1; + } + } + } + + func_80B781DC(this, bandit1, bandit2, play); + } + + Math3D_Lerp(&bandit1->unk_540, &this->unk_360[bandit1->unk_550], 1.0f - ((f32)bandit1->unk_55C / bandit1->unk_560), + &sp30); + bandit1->banditPosition = sp30; + bandit1->unk_588 = this->dyna.actor.shape.rot.y; + + if ((bandit1->unk_550 == 10) || ((bandit1->unk_550 == 8))) { + phi_v1_5 = bandit1->unk_588; + } else if (Math3D_Distance(&bandit1->actor.prevPos, &bandit1->actor.world.pos) < 10.0f) { + phi_v1_5 = bandit1->unk_588; + } else { + phi_v1_5 = Math_Vec3f_Yaw(&bandit1->actor.prevPos, &bandit1->actor.world.pos); + } + + if (1) {} + + phi_v1_5 -= bandit1->actor.shape.rot.y; + if (phi_v1_5 > 0x190) { + bandit1->actor.shape.rot.y += 0x190; + } else if (phi_v1_5 < -0x190) { + bandit1->actor.shape.rot.y -= 0x190; + } else { + bandit1->actor.shape.rot.y += phi_v1_5; + } + + return 0; +} + +// ObjUm_UpdateBanditsDamage? +s32 func_80B78A54(ObjUm* this, PlayState* play, s32 arg2, EnHorse* arg3, EnHorse* arg4) { + if (this->banditsCollisions[arg2].base.acFlags & AC_HIT) { + if (arg3->unk_550 == 3) { + s16 sp36 = + Math_Vec3f_Yaw(&this->dyna.actor.world.pos, &arg3->actor.world.pos) - this->dyna.actor.shape.rot.y; + + this->banditsCollisions[arg2].base.acFlags &= ~AC_HIT; + Audio_PlaySfxAtPos(&arg3->actor.projectedPos, NA_SE_EN_CUTBODY); + arg3->unk_54C = 0xF; + + if (Math_SinS(sp36) > 0.0f) { + arg3->unk_550 = arg4->unk_550 != 10 ? 10 : 8; + arg3->unk_568 = -1.0f; + } else { + arg3->unk_550 = arg4->unk_550 != 8 ? 8 : 10; + arg3->unk_568 = 1.0f; + } + + arg3->unk_540 = arg3->actor.world.pos; + arg3->unk_55C = 40; + arg3->unk_560 = 40; + arg3->unk_564 = 1; + if (arg3->rider != NULL) { + arg3->rider->actor.colorFilterTimer = 20; + Actor_SetColorFilter(&arg3->rider->actor, 0x4000, 0xFF, 0, 40); + } + } else { + if (arg3->rider != NULL) { + arg3->rider->actor.colorFilterTimer = 20; + Actor_SetColorFilter(&arg3->rider->actor, 0x4000, 0xFF, 0, 40); + } + Audio_PlaySfxAtPos(&arg3->actor.projectedPos, NA_SE_EN_CUTBODY); + } + } + + return 0; +} + +// ObjUm_UpdateBanditLogic? +s32 func_80B78C18(ObjUm* this, PlayState* play) { + EnHorse* bandit1 = this->bandit1; + EnHorse* bandit2 = this->bandit2; + + if (!(this->flags & OBJ_UM_FLAG_0200)) { + func_80B783E0(this, play, 0, bandit1); + } else { + func_80B78764(this, play, bandit1, bandit2); + } + + if (!(this->flags & OBJ_UM_FLAG_0400)) { + func_80B783E0(this, play, 1, bandit2); + } else { + func_80B78764(this, play, bandit2, bandit1); + } + + func_80B78A54(this, play, 0, bandit1, bandit2); + func_80B78A54(this, play, 1, bandit2, bandit1); + return 0; +} + +s32 ObjUm_UpdateBanditsCollisions(ObjUm* this, PlayState* play) { + s32 pad[3]; + + this->banditsCollisions[0].dim.pos.x = this->bandit1->actor.world.pos.x; + this->banditsCollisions[0].dim.pos.y = this->bandit1->actor.world.pos.y + 70.0f; + this->banditsCollisions[0].dim.pos.z = this->bandit1->actor.world.pos.z; + + this->banditsCollisions[1].dim.pos.x = this->bandit2->actor.world.pos.x; + this->banditsCollisions[1].dim.pos.y = this->bandit2->actor.world.pos.y + 70.0f; + this->banditsCollisions[1].dim.pos.z = this->bandit2->actor.world.pos.z; + + CollisionCheck_SetAC(play, &play->colChkCtx, &this->banditsCollisions[0].base); + CollisionCheck_SetAC(play, &play->colChkCtx, &this->banditsCollisions[1].base); + return 0; +} + +// ObjUm_UpdateBandits? +s32 func_80B78DF0(ObjUm* this, PlayState* play) { + func_80B78C18(this, play); + ObjUm_UpdateBanditsCollisions(this, play); + return 0; +} + +void ObjUm_SetupAction(ObjUm* this, ObjUmActionFunc actionFunc) { + this->actionFunc = actionFunc; +} + +void ObjUm_SetPlayerPosition(ObjUm* this, PlayState* play) { + Player* player = GET_PLAYER(play); + + if (this->flags & OBJ_UM_FLAG_DRAWN_FLOOR) { + player->actor.world.pos = this->unk_308; + player->actor.prevPos = this->unk_308; + } +} + +void ObjUm_RotatePlayer(ObjUm* this, PlayState* play, s16 angle) { + Player* player = GET_PLAYER(play); + + player->actor.shape.rot.y = player->actor.world.rot.y = player->currentYaw = this->dyna.actor.shape.rot.y + angle; +} + +void func_80B78EBC(ObjUm* this, PlayState* play) { + Player* player = GET_PLAYER(play); + + player->actor.focus.rot.x = 0; + player->actor.focus.rot.z = 0; + player->actor.focus.rot.y = player->actor.shape.rot.y; + + player->unk_AAC.x = 0; + player->unk_AAC.y = 0; + player->unk_AAC.z = 0; + + player->unk_AB2.x = 0; + player->unk_AB2.y = 0; + player->unk_AB2.z = 0; + + player->currentYaw = player->actor.focus.rot.y; +} + +void ObjUm_RotatePlayerView(ObjUm* this, PlayState* play, s16 angle) { + Player* player = GET_PLAYER(play); + + player->actor.focus.rot.y += angle; +} + +static InitChainEntry sInitChain[] = { ICHAIN_F32(uncullZoneScale, 1200, ICHAIN_CONTINUE), ICHAIN_F32(uncullZoneDownward, 300, ICHAIN_STOP), }; -#endif +void ObjUm_Init(Actor* thisx, PlayState* play) { + s32 pad; + ObjUm* this = THIS; + s32 sp54 = true; + s32 i; -extern ColliderCylinderInit D_80B7C138; -extern InitChainEntry D_80B7C254[]; + DynaPolyActor_Init(&this->dyna, 0); + this->unk_350 = 0; -extern UNK_TYPE D_06011DF8; -extern UNK_TYPE D_06012CC0; + this->unk_2C4 = this->dyna.actor.world.pos; + this->unk_2DC = this->dyna.actor.world.pos; + this->unk_308 = this->dyna.actor.world.pos; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B77770.s") + for (i = 0; i < MILK_POTS_COUNT; i++) { + this->potsLife[i] = 5; + this->wasPotHit[i] = false; + this->potPos[i] = gZeroVec3f; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B77FA4.s") + this->donkey = NULL; + this->unk_354 = 0; + this->unk_420 = 0; + this->cartBedPos = this->dyna.actor.world.pos; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B781DC.s") + this->unk_4CC = 0; + this->mouthTexIndex = 0; + this->flags = OBJ_UM_FLAG_NONE; + this->dyna.actor.gravity = -3.5f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B783E0.s") + Actor_ProcessInitChain(&this->dyna.actor, sInitChain); + ActorShape_Init(&this->dyna.actor.shape, 0.0f, NULL, 50.0f); + SkelAnime_InitFlex(play, &this->skelAnime, &gUmSkel, NULL, this->jointTable, this->morphTable, UM_LIMB_MAX); + Animation_PlayLoop(&this->skelAnime, &gUmTrotAnim); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B78764.s") + this->wheelRot = 0; + ObjUm_DefaultAnim(this, play); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B78A54.s") + this->type = OBJ_UM_PARSE_TYPE(thisx); + this->initialPathIndex = OBJ_UM_PARSE_PATH_INDEX(thisx); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B78C18.s") + // if (!AliensDefeated) + if (!(gSaveContext.save.weekEventReg[22] & 1)) { + Actor_MarkForDeath(&this->dyna.actor); + return; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B78D08.s") + if (this->type == OBJ_UM_TYPE_TERMINA_FIELD) { + ObjUm_SetupAction(this, ObjUm_TerminaFieldIdle); + } else if (this->type == OBJ_UM_TYPE_RANCH) { + this->pathIndex = this->initialPathIndex; + if (gSaveContext.save.weekEventReg[31] & 0x80) { + // In cutscene -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B78DF0.s") + sp54 = false; + this->flags |= OBJ_UM_FLAG_0100; + ObjUm_SetupAction(this, func_80B7A144); + func_800FE484(); + } else { + // Waiting for player -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/ObjUm_SetupAction.s") + if ((gSaveContext.save.weekEventReg[34] & 0x80) || gSaveContext.save.time >= CLOCK_TIME(19, 0) || + gSaveContext.save.time <= CLOCK_TIME(6, 0) || (gSaveContext.save.weekEventReg[52] & 1) || + (gSaveContext.save.weekEventReg[52] & 2)) { + Actor_MarkForDeath(&this->dyna.actor); + return; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B78E38.s") + this->dyna.actor.targetMode = 6; + this->unk_2B4 = 0; + ObjUm_SetupAction(this, ObjUm_RanchWait); + } + } else if (this->type == OBJ_UM_TYPE_PRE_MILK_RUN) { + if (!(gSaveContext.save.weekEventReg[31] & 0x80) || (gSaveContext.save.weekEventReg[52] & 1)) { + Actor_MarkForDeath(&this->dyna.actor); + return; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B78E88.s") + if (!(gSaveContext.save.weekEventReg[52] & 2)) { + this->pathIndex = this->initialPathIndex; + sp54 = false; + func_800FE484(); + ObjUm_SetupAction(this, ObjUm_PreMilkRunStartCs); + this->unk_354 = 0; + ObjUm_RotatePlayer(this, play, 0); + } + } else if (this->type == OBJ_UM_TYPE_MILK_RUN_MINIGAME) { + if (!(gSaveContext.save.weekEventReg[31] & 0x80)) { + Actor_MarkForDeath(&this->dyna.actor); + return; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B78EBC.s") + this->pathIndex = this->initialPathIndex; + sp54 = false; + func_800FE484(); + ObjUm_SetupAction(this, ObjUm_StartCs); + this->unk_354 = 0; + ObjUm_RotatePlayer(this, play, 0); + } else if (this->type == OBJ_UM_TYPE_POST_MILK_RUN) { + if (!(gSaveContext.save.weekEventReg[52] & 1) || (gSaveContext.save.weekEventReg[59] & 2)) { + Actor_MarkForDeath(&this->dyna.actor); + return; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B78EFC.s") + this->pathIndex = this->initialPathIndex; + sp54 = false; + func_800FE484(); + ObjUm_SetupAction(this, ObjUm_PostMilkRunStartCs); + this->unk_354 = 0; + ObjUm_RotatePlayer(this, play, 0); + func_801A3098(NA_BGM_CLEAR_EVENT); + } else { + this->type = OBJ_UM_TYPE_TERMINA_FIELD; + ObjUm_SetupAction(this, ObjUm_TerminaFieldIdle); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/ObjUm_Init.s") + this->unk_2F8 = this->unk_2FE = gZeroVec3s; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/ObjUm_Destroy.s") + if (sp54) { + DynaPolyActor_Init(&this->dyna, 0); + DynaPolyActor_LoadMesh(play, &this->dyna, &object_um_Colheader_007E20); + } else { + DynaPolyActor_Init(&this->dyna, 3); + DynaPolyActor_LoadMesh(play, &this->dyna, &object_um_Colheader_007F50); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B79524.s") + if (this->dyna.bgId == BGCHECK_SCENE) { + Actor_MarkForDeath(&this->dyna.actor); + return; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B79560.s") + func_800C636C(play, &play->colCtx.dyna, this->dyna.bgId); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B795A0.s") + this->donkey = + (EnHorse*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, this->dyna.actor.world.pos.x, + this->dyna.actor.world.pos.y, this->dyna.actor.world.pos.z, 0, + this->dyna.actor.shape.rot.y, 0, ENHORSE_PARAMS(ENHORSE_PARAM_DONKEY, ENHORSE_18)); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B79734.s") + if (this->donkey == NULL) { + Actor_MarkForDeath(&this->dyna.actor); + return; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B797EC.s") + Collider_InitAndSetCylinder(play, &this->banditsCollisions[0], &this->dyna.actor, &sCylinderInit); + Collider_InitAndSetCylinder(play, &this->banditsCollisions[1], &this->dyna.actor, &sCylinderInit); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B7984C.s") +void ObjUm_Destroy(Actor* thisx, PlayState* play) { + ObjUm* this = THIS; + s32 i; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B79A24.s") + DynaPoly_DeleteBgActor(play, &play->colCtx.dyna, this->dyna.bgId); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B79A50.s") + for (i = 0; i < ARRAY_COUNT(this->potPos); i++) { + Audio_StopSfxByPos(&this->potPos[i]); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B79BA0.s") + Collider_DestroyCylinder(play, &this->banditsCollisions[0]); + Collider_DestroyCylinder(play, &this->banditsCollisions[1]); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B79F10.s") +// ObjUm_MarkMyDonkeyAndMyselfForDeath, ObjUm_TerminateMe, ObjUmn't, ObjUm_Asinucide +void func_80B79524(ObjUm* this) { + Actor_MarkForDeath(&this->dyna.actor); + if (this->donkey != NULL) { + Actor_MarkForDeath(&this->donkey->actor); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B79FFC.s") +void func_80B79560(PlayState* play, ObjUm* this, s32 arg2, u16 textId) { + // "Thanks, I rely on you" + if (textId == 0x33BF) { + ObjUm_SetupAction(this, ObjUm_StartCs); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B7A070.s") +s32 func_80B795A0(PlayState* play, ObjUm* this, s32 arg2) { + s32 pad[2]; + s32 phi_v1 = true; + u16 textId = this->dyna.actor.textId; + Player* player; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B7A0E0.s") + switch (textId) { + // "I'll go to town" + case 0x33B4: + // "Want a ride?" + case 0x33CF: + gSaveContext.save.weekEventReg[31] |= 0x40; + if (play->msgCtx.choiceIndex == 0) { + player = GET_PLAYER(play); + func_8019F208(); + gSaveContext.save.weekEventReg[31] |= 0x80; + play->nextEntranceIndex = 0x64B0; + if (player->stateFlags1 & PLAYER_STATE1_800000) { + D_801BDAA0 = 1; + } + play->transitionType = TRANS_TYPE_64; + gSaveContext.nextTransitionType = TRANS_TYPE_03; + play->transitionTrigger = TRANS_TRIGGER_START; + phi_v1 = true; + } else { + Actor_ContinueText(play, &this->dyna.actor, 0x33B5); + func_8019F230(); + func_80151BB4(play, 6); + phi_v1 = false; + } + break; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B7A144.s") + // "I'll go as fast as I can!" + case 0x33BB: + Actor_ContinueText(play, &this->dyna.actor, 0x33BC); + phi_v1 = false; + break; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B7A1B4.s") + // "Chase pursuers with your arrows." + case 0x33BC: + Actor_ContinueText(play, &this->dyna.actor, 0x33BD); + phi_v1 = false; + break; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B7A240.s") + // "Understand?" + case 0x33BD: + if (play->msgCtx.choiceIndex == 0) { + Actor_ContinueText(play, &this->dyna.actor, 0x33BE); + func_8019F230(); + } else { + Actor_ContinueText(play, &this->dyna.actor, 0x33BF); + func_8019F208(); + } + phi_v1 = false; + break; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B7A2AC.s") + // "I'll tell you again!" + case 0x33BE: + Actor_ContinueText(play, &this->dyna.actor, 0x33BC); + phi_v1 = false; + break; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B7A394.s") + return phi_v1; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B7A400.s") +s32 func_80B79734(PlayState* play, ObjUm* this, s32 arg2) { + MessageContext* msgCtx = &play->msgCtx; + s32 ret = false; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B7A494.s") + switch (Message_GetState(msgCtx)) { + case TEXT_STATE_CLOSING: + func_80B79560(play, this, arg2, this->dyna.actor.textId); + return true; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B7A614.s") + case TEXT_STATE_CHOICE: + case TEXT_STATE_5: + if (Message_ShouldAdvance(play) && func_80B795A0(play, this, arg2)) { + msgCtx->msgMode = 0x43; + ret = true; + } + break; + } + return ret; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B7A7AC.s") +u16 ObjUm_RanchGetDialogue(PlayState* play, ObjUm* this, s32 arg2) { + u16 textId = 0; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B7A860.s") + if (gSaveContext.save.playerForm == PLAYER_FORM_HUMAN) { + if (gSaveContext.save.weekEventReg[31] & 0x40) { + // "Want a ride?" + textId = 0x33CF; + } else { + // "I'll deliver milk" + textId = 0x33B4; + } + } else { + textId = 0x33B7; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B7AB78.s") + if (textId == 0) { + textId = 1; + } + return textId; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B7ABE4.s") +s32 func_80B7984C(PlayState* play, ObjUm* this, s32 arg2, s32* arg3) { + s16 temp_v0_2; + s16 phi_v1; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B7AC94.s") + if (*arg3 == 4) { + return 0; + } + if (*arg3 == 2) { + Message_StartTextbox(play, this->dyna.actor.textId, &this->dyna.actor); + *arg3 = 1; + return 0; + } + if (*arg3 == 3) { + func_80151938(play, this->dyna.actor.textId); + *arg3 = 1; + return 0; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B7AD34.s") + if (Actor_ProcessTalkRequest(&this->dyna.actor, &play->state)) { + *arg3 = 1; + return 1; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B7AE58.s") + if (*arg3 == 1) { + if (func_80B79734(play, this, arg2)) { + *arg3 = 0; + } + return 0; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B7AEFC.s") + phi_v1 = this->dyna.actor.yawTowardsPlayer - this->dyna.actor.shape.rot.y; + temp_v0_2 = ABS_ALT(phi_v1); + if (temp_v0_2 >= 0x4E20) { + return 0; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B7AF30.s") + if ((this->dyna.actor.xyzDistToPlayerSq > SQ(100.0f)) && !this->dyna.actor.isTargeted) { + return 0; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B7B154.s") + if (this->dyna.actor.xyzDistToPlayerSq <= SQ(50.0f)) { + if (func_800B8614(&this->dyna.actor, play, 50.0f)) { + this->dyna.actor.textId = ObjUm_RanchGetDialogue(play, this, arg2); + } + } else if (func_800B863C(&this->dyna.actor, play)) { + this->dyna.actor.textId = ObjUm_RanchGetDialogue(play, this, arg2); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B7B18C.s") + return 0; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/ObjUm_Update.s") +s32 func_80B79A24(s32 arg0) { + switch (arg0) { + case 1: + case 2: + case 3: + return true; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B7B598.s") + default: + return false; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B7B93C.s") +void ObjUm_RanchWait(ObjUm* this, PlayState* play) { + Player* player = GET_PLAYER(play); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B7BABC.s") + this->dyna.actor.flags |= ACTOR_FLAG_1; + SkelAnime_Update(&this->skelAnime); + ObjUm_UpdateAnim(this, play, OBJ_UM_ANIM_IDLE); + this->flags |= OBJ_UM_FLAG_WAITING; + if ((gSaveContext.save.time > CLOCK_TIME(18, 0)) && (gSaveContext.save.time <= CLOCK_TIME(19, 0))) { + if (!(player->stateFlags1 & PLAYER_STATE1_800000)) { + func_80B7984C(play, this, 0, &this->unk_2B4); + } + } else if (!func_80B79A24(this->unk_2B4) && (gSaveContext.save.time > CLOCK_TIME(19, 0))) { + gSaveContext.save.weekEventReg[34] |= 0x80; + ObjUm_SetupAction(this, ObjUm_RanchWaitPathFinished); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/func_80B7BEA4.s") + switch (play->msgCtx.currentTextId) { + default: + this->unk_4CC = 0; + this->mouthTexIndex = 0; + break; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Um/ObjUm_Draw.s") + // "I'm worried about my sister" + case 0x33B7: + // "I'll deliver milk" + case 0x33B4: + this->unk_4CC = 0; + this->mouthTexIndex = 1; + break; + + // "I'll leave at 7" + case 0x33B5: + this->unk_4CC = 3; + this->mouthTexIndex = 1; + break; + } +} + +typedef enum ObjUmPathState { + /* 0 */ OBJUM_PATH_STATE_0, + /* 1 */ OBJUM_PATH_STATE_1, + /* 2 */ OBJUM_PATH_STATE_FINISH, + /* 3 */ OBJUM_PATH_STATE_3, + /* 4 */ OBJUM_PATH_STATE_4, +} ObjUmPathState; + +ObjUmPathState ObjUm_UpdatePath(ObjUm* this, PlayState* play) { + Path* path = &play->setupPathList[this->pathIndex]; + s32 pathCount; + Vec3s* pathPoints; + f32 xDiff; + f32 zDiff; + Vec3f sp50; + f32 sp4C; + f32 sp48; + f32 sp44; + s32 angle; + ObjUmPathState sp3C; + s16 yawDiff; + + pathCount = path->count; + pathPoints = Lib_SegmentedToVirtual(path->points); + sp3C = OBJUM_PATH_STATE_0; + + if (pathCount == 0) { + return 0; + } + + Math_Vec3s_ToVec3f(&sp50, &pathPoints[this->pointIndex]); + + if (this->pointIndex == 0) { + xDiff = pathPoints[1].x - pathPoints[0].x; + zDiff = pathPoints[1].z - pathPoints[0].z; + } else if ((this->pointIndex + 1) == path->count) { + xDiff = pathPoints[path->count - 1].x - pathPoints[path->count - 2].x; + zDiff = pathPoints[path->count - 1].z - pathPoints[path->count - 2].z; + } else { + xDiff = pathPoints[this->pointIndex + 1].x - pathPoints[this->pointIndex - 1].x; + zDiff = pathPoints[this->pointIndex + 1].z - pathPoints[this->pointIndex - 1].z; + } + + angle = Math_Atan2S(xDiff, zDiff); + + func_8017B7F8(&sp50, angle, &sp4C, &sp48, &sp44); + if (((this->dyna.actor.world.pos.x * sp4C) + (sp48 * this->dyna.actor.world.pos.z) + sp44) > 0.0f) { + this->pointIndex++; + + if (this->pointIndex >= (pathCount - 7)) { + sp3C = OBJUM_PATH_STATE_3; + } + if (this->pointIndex >= (pathCount - 3)) { + sp3C = OBJUM_PATH_STATE_1; + } + if (this->pointIndex >= (pathCount - 2)) { + sp3C = OBJUM_PATH_STATE_4; + } + if (this->pointIndex >= pathCount) { + this->pointIndex = 0; + sp3C = OBJUM_PATH_STATE_FINISH; + } + + Math_Vec3s_ToVec3f(&sp50, &pathPoints[this->pointIndex]); + } + + if (this->donkey != NULL) { + this->dyna.actor.world.rot.y = Math_Vec3f_Yaw(&this->dyna.actor.world.pos, &sp50); + func_800F415C(&this->donkey->actor, &sp50, 0x190); + + if (1) {} + + yawDiff = this->donkey->actor.shape.rot.y - this->dyna.actor.shape.rot.y; + if (fabsf(yawDiff) < 2730.0f) { + if (fabsf(yawDiff) < 100.0f) { + this->dyna.actor.shape.rot.y = this->donkey->actor.shape.rot.y; + } else if (yawDiff > 0) { + this->dyna.actor.shape.rot.y = this->dyna.actor.shape.rot.y + 0x64; + yawDiff = 0x64; + } else if (yawDiff < 0) { + this->dyna.actor.shape.rot.y = this->dyna.actor.shape.rot.y - 0x64; + yawDiff = -0x64; + } + } else if (yawDiff > 0) { + this->dyna.actor.shape.rot.y = this->dyna.actor.shape.rot.y + 0x190; + yawDiff = 0x190; + } else if (yawDiff < 0) { + this->dyna.actor.shape.rot.y = this->dyna.actor.shape.rot.y - 0x190; + yawDiff = -0x190; + } + + if (this->flags & (OBJ_UM_FLAG_0010 | OBJ_UM_FLAG_0004)) { + ObjUm_RotatePlayerView(this, play, yawDiff); + } + } + + if (this->currentAnimIndex == OBJ_UM_ANIM_TROT) { + this->dyna.actor.speedXZ = 4.0f; + } else if (this->currentAnimIndex == OBJ_UM_ANIM_GALLOP) { + this->dyna.actor.speedXZ = 8.0f; + } + + return sp3C; +} + +void ObjUm_RanchWaitPathFinished(ObjUm* this, PlayState* play) { + this->wheelRot += 0x3E8; + this->flags &= ~OBJ_UM_FLAG_WAITING; + ObjUm_UpdateAnim(this, play, OBJ_UM_ANIM_TROT); + + switch (ObjUm_UpdatePath(this, play)) { + case OBJUM_PATH_STATE_1: + case OBJUM_PATH_STATE_FINISH: + if (gSaveContext.save.weekEventReg[31] & 0x80) { + ActorCutscene_Stop(this->dyna.actor.cutscene); + play->nextEntranceIndex = 0x3E50; + play->transitionType = TRANS_TYPE_64; + gSaveContext.nextTransitionType = TRANS_TYPE_03; + play->transitionTrigger = TRANS_TRIGGER_START; + } else { + func_80B79524(this); + } + break; + + default: + Actor_MoveWithGravity(&this->dyna.actor); + break; + } +} + +void ObjUm_RanchStartCs(ObjUm* this, PlayState* play) { + ObjUm_UpdateAnim(this, play, OBJ_UM_ANIM_IDLE); + + if (ActorCutscene_GetCanPlayNext(this->dyna.actor.cutscene)) { + ActorCutscene_StartAndSetUnkLinkFields(this->dyna.actor.cutscene, &this->dyna.actor); + this->lastTime = gSaveContext.save.time; + ObjUm_SetupAction(this, func_80B7A0E0); + } else { + ActorCutscene_SetIntentToPlay(this->dyna.actor.cutscene); + } +} + +void func_80B7A070(ObjUm* this, PlayState* play) { + ObjUm_RanchWaitPathFinished(this, play); + ObjUm_RotatePlayer(this, play, 0); + + switch (play->msgCtx.currentTextId) { + case 0x33B6: + this->unk_4CC = 1; + this->mouthTexIndex = 1; + break; + + default: + this->unk_4CC = 0; + this->mouthTexIndex = 0; + break; + } +} + +void func_80B7A0E0(ObjUm* this, PlayState* play) { + ObjUm_UpdateAnim(this, play, OBJ_UM_ANIM_IDLE); + if (gSaveContext.save.time != this->lastTime) { + ObjUm_UpdateAnim(this, play, OBJ_UM_ANIM_TROT); + ObjUm_SetupAction(this, func_80B7A070); + } +} + +void func_80B7A144(ObjUm* this, PlayState* play) { + Player* player = GET_PLAYER(play); + + ObjUm_SetPlayerPosition(this, play); + this->flags |= OBJ_UM_FLAG_0100; + this->flags |= OBJ_UM_FLAG_0004; + player->stateFlags1 |= PLAYER_STATE1_20; + ObjUm_UpdateAnim(this, play, OBJ_UM_ANIM_IDLE); + ObjUm_SetupAction(this, ObjUm_RanchStartCs); +} + +void ObjUm_PreMilkRunDialogueHandler(ObjUm* this, PlayState* play) { + ObjUm_SetPlayerPosition(this, play); + this->flags |= OBJ_UM_FLAG_0004; + + switch (play->msgCtx.currentTextId) { + case 0x33B8: + this->unk_4CC = 0; + this->mouthTexIndex = 3; + break; + + case 0x33B9: + this->unk_4CC = 2; + this->mouthTexIndex = 0; + break; + + default: + this->flags &= ~OBJ_UM_FLAG_LOOK_BACK; + this->unk_4CC = 0; + this->mouthTexIndex = 0; + break; + } +} + +void func_80B7A240(ObjUm* this, PlayState* play) { + ObjUm_UpdateAnim(this, play, OBJ_UM_ANIM_IDLE); + if (gSaveContext.save.time != this->lastTime) { + ObjUm_SetupAction(this, func_80B7A2AC); + } + + this->lastTime = gSaveContext.save.time; + ObjUm_PreMilkRunDialogueHandler(this, play); +} + +void func_80B7A2AC(ObjUm* this, PlayState* play) { + this->wheelRot += 0x3E8; + ObjUm_UpdateAnim(this, play, OBJ_UM_ANIM_TROT); + + switch (ObjUm_UpdatePath(this, play)) { + case OBJUM_PATH_STATE_1: + case OBJUM_PATH_STATE_FINISH: + play->nextEntranceIndex = 0xCE40; + play->transitionType = TRANS_TYPE_64; + gSaveContext.nextTransitionType = TRANS_TYPE_03; + play->transitionTrigger = TRANS_TRIGGER_START; + break; + + default: + if (gSaveContext.save.time == this->lastTime) { + ObjUm_SetupAction(this, func_80B7A240); + } + + this->lastTime = gSaveContext.save.time; + Actor_MoveWithGravity(&this->dyna.actor); + ObjUm_PreMilkRunDialogueHandler(this, play); + break; + } +} + +void func_80B7A394(ObjUm* this, PlayState* play) { + ObjUm_SetPlayerPosition(this, play); + this->flags |= OBJ_UM_FLAG_0004; + if (gSaveContext.save.time != this->lastTime) { + ObjUm_UpdateAnim(this, play, OBJ_UM_ANIM_TROT); + ObjUm_SetupAction(this, func_80B7A2AC); + } +} + +void ObjUm_PreMilkRunStartCs(ObjUm* this, PlayState* play) { + Player* player = GET_PLAYER(play); + + ObjUm_SetPlayerPosition(this, play); + this->flags |= OBJ_UM_FLAG_0004; + player->stateFlags1 |= PLAYER_STATE1_20; + if (ActorCutscene_GetCanPlayNext(this->dyna.actor.cutscene)) { + ActorCutscene_StartAndSetUnkLinkFields(this->dyna.actor.cutscene, &this->dyna.actor); + this->lastTime = gSaveContext.save.time; + ObjUm_SetupAction(this, func_80B7A394); + } else { + ActorCutscene_SetIntentToPlay(this->dyna.actor.cutscene); + } +} + +void ObjUm_RunMinigame(ObjUm* this, PlayState* play) { + ObjUm_SetPlayerPosition(this, play); + ObjUm_RotatePlayer(this, play, 0x7FFF); + this->wheelRot += 0x7D0; + this->flags |= OBJ_UM_FLAG_0010; + ObjUm_UpdateAnim(this, play, OBJ_UM_ANIM_GALLOP); + + switch (ObjUm_UpdatePath(this, play)) { + case OBJUM_PATH_STATE_1: + case OBJUM_PATH_STATE_FINISH: + gSaveContext.seqIndex = 0xFF; + gSaveContext.save.weekEventReg[31] &= (u8)~0x80; + gSaveContext.nightSeqIndex = 0xFF; + + if (!(gSaveContext.save.weekEventReg[52] & 1) && !(gSaveContext.save.weekEventReg[52] & 2)) { + if (!this->areAllPotsBroken) { + play->nextEntranceIndex = 0x3E60; + play->transitionType = TRANS_TYPE_64; + gSaveContext.nextTransitionType = TRANS_TYPE_03; + play->transitionTrigger = TRANS_TRIGGER_START; + gSaveContext.save.weekEventReg[52] |= 1; + gSaveContext.save.weekEventReg[52] &= (u8)~2; + } else { + play->nextEntranceIndex = 0x6480; + play->transitionType = TRANS_TYPE_64; + gSaveContext.nextTransitionType = TRANS_TYPE_03; + play->transitionTrigger = TRANS_TRIGGER_START; + gSaveContext.save.weekEventReg[52] |= 2; + gSaveContext.save.weekEventReg[52] &= (u8)~1; + } + } + break; + + default: + Actor_MoveWithGravity(&this->dyna.actor); + func_80B78DF0(this, play); + break; + } +} + +void func_80B7A614(ObjUm* this, PlayState* play) { + s32 pad; + + ObjUm_SetPlayerPosition(this, play); + ObjUm_RotatePlayer(this, play, 0x7FFF); + this->wheelRot += 0x7D0; + this->flags |= OBJ_UM_FLAG_0010; + this->flags |= OBJ_UM_FLAG_PLAYING_MINIGAME; + ObjUm_UpdateAnim(this, play, OBJ_UM_ANIM_GALLOP); + + if (ObjUm_UpdatePath(this, play) == OBJUM_PATH_STATE_3 && this->unk_4DC == 0) { + this->unk_4DC = 1; + } else if (this->unk_4DC > 0) { + if (this->unk_4DC == 1) { + s32 i; + + this->areAllPotsBroken = true; + + for (i = 0; i < ARRAY_COUNT(this->potsLife); i++) { + if (this->potsLife[i] != 1) { + this->areAllPotsBroken = false; + break; + } + } + + this->flags |= OBJ_UM_FLAG_MINIGAME_FINISHED; + } + + this->unk_4DC++; + } + + if (this->flags & OBJ_UM_FLAG_MINIGAME_FINISHED) { + s32 sp20 = ActorCutscene_GetAdditionalCutscene(this->dyna.actor.cutscene); + + if (this->areAllPotsBroken) { + sp20 = ActorCutscene_GetAdditionalCutscene(sp20); + } + if (ActorCutscene_GetCanPlayNext(sp20)) { + ActorCutscene_StartAndSetUnkLinkFields(sp20, &this->dyna.actor); + ObjUm_SetupAction(this, ObjUm_RunMinigame); + this->flags &= ~OBJ_UM_FLAG_PLAYING_MINIGAME; + } else { + ActorCutscene_SetIntentToPlay(sp20); + } + } + + Actor_MoveWithGravity(&this->dyna.actor); + func_80B78DF0(this, play); +} + +void func_80B7A7AC(ObjUm* this, PlayState* play) { + Player* player = GET_PLAYER(play); + + this->unk_4DC = 0; + this->areAllPotsBroken = false; + player->stateFlags1 &= ~PLAYER_STATE1_20; + ObjUm_SetPlayerPosition(this, play); + ObjUm_RotatePlayer(this, play, 0x7FFF); + func_80B78EBC(this, play); + this->flags |= OBJ_UM_FLAG_0010; + func_80B78DF0(this, play); + this->flags |= 4; + ObjUm_UpdateAnim(this, play, OBJ_UM_ANIM_GALLOP); + ObjUm_SetupAction(this, func_80B7A614); +} + +void func_80B7A860(ObjUm* this, PlayState* play) { + ObjUm_SetPlayerPosition(this, play); + ObjUm_RotatePlayer(this, play, 0); + this->flags |= OBJ_UM_FLAG_0004; + + if (play->csCtx.frames == 449) { + ObjUm_InitBandits(this, play); + } else if (play->csCtx.frames >= 450) { + func_80B78DF0(this, play); + } + + if (play->csCtx.state == 0) { + ActorCutscene_Stop(this->dyna.actor.cutscene); + ObjUm_SetupAction(this, func_80B7A7AC); + } + + switch (play->msgCtx.currentTextId) { + case 0x33BA: + this->unk_4CC = 2; + this->mouthTexIndex = 3; + break; + + // "We'll go through here as fast as we can" + case 0x33BB: + if ((fabsf(this->skelAnime.curFrame) < 0.008f) && !(this->flags & OBJ_UM_FLAG_1000)) { + this->flags |= OBJ_UM_FLAG_1000; + this->unk_4CC = 4; + this->mouthTexIndex = 0; + } else if (fabsf(this->skelAnime.morphWeight) < 0.008f) { + this->unk_4CC = 2; + this->mouthTexIndex = 2; + } else { + this->unk_4CC = 5; + this->mouthTexIndex = 0; + } + + this->flags |= OBJ_UM_FLAG_LOOK_BACK; + break; + + // "Chase pursuers with your arrows" + case 0x33BC: + if ((fabsf(this->skelAnime.curFrame) < 0.008f) && !(this->flags & OBJ_UM_FLAG_1000)) { + this->flags |= OBJ_UM_FLAG_1000; + this->unk_4CC = 4; + this->mouthTexIndex = 0; + } else if (fabsf(this->skelAnime.morphWeight) < 0.008f) { + this->unk_4CC = 2; + this->mouthTexIndex = 2; + } else { + this->unk_4CC = 5; + this->mouthTexIndex = 0; + } + this->flags |= OBJ_UM_FLAG_LOOK_BACK; + break; + + // "Understand?" + case 0x33BD: + if ((fabsf(this->skelAnime.curFrame) < 0.008f) && !(this->flags & OBJ_UM_FLAG_1000)) { + this->flags |= OBJ_UM_FLAG_1000; + this->unk_4CC = 4; + this->mouthTexIndex = 0; + } else if (fabsf(this->skelAnime.morphWeight) < 0.008f) { + this->unk_4CC = 2; + } else { + this->unk_4CC = 5; + } + this->mouthTexIndex = 0; + this->unk_4D8 = 0; + this->flags |= OBJ_UM_FLAG_LOOK_BACK; + break; + + case 0x33BE: + this->flags |= OBJ_UM_FLAG_LOOK_BACK; + this->unk_4CC = 2; + this->mouthTexIndex = 3; + break; + + case 0x33BF: + this->unk_4D8++; + if ((fabsf(this->skelAnime.morphWeight) < 0.008f) && this->unk_4D8 >= 6) { + this->unk_4CC = 0; + this->mouthTexIndex = 0; + } else { + this->unk_4CC = 2; + this->mouthTexIndex = 2; + } + this->flags &= ~OBJ_UM_FLAG_LOOK_BACK; + break; + + default: + this->unk_4CC = 0; + this->mouthTexIndex = 0; + break; + } +} + +void func_80B7AB78(ObjUm* this, PlayState* play) { + ObjUm_UpdateAnim(this, play, OBJ_UM_ANIM_IDLE); + if (gSaveContext.save.time != this->lastTime) { + ObjUm_SetupAction(this, func_80B7ABE4); + } + + this->lastTime = gSaveContext.save.time; + func_80B7A860(this, play); +} + +void func_80B7ABE4(ObjUm* this, PlayState* play) { + this->wheelRot += 0x3E8; + + ObjUm_UpdateAnim(this, play, OBJ_UM_ANIM_TROT); + switch (ObjUm_UpdatePath(this, play)) { + case OBJUM_PATH_STATE_FINISH: + func_80B79524(this); + break; + + default: + if (gSaveContext.save.time == this->lastTime) { + ObjUm_SetupAction(this, func_80B7AB78); + } + + this->lastTime = gSaveContext.save.time; + Actor_MoveWithGravity(&this->dyna.actor); + func_80B7A860(this, play); + break; + } +} + +void ObjUm_StartCs(ObjUm* this, PlayState* play) { + Player* player = GET_PLAYER(play); + + player->stateFlags1 |= PLAYER_STATE1_20; + ObjUm_SetPlayerPosition(this, play); + ObjUm_RotatePlayer(this, play, 0); + this->flags |= OBJ_UM_FLAG_0004; + + if (ActorCutscene_GetCanPlayNext(this->dyna.actor.cutscene)) { + ActorCutscene_StartAndSetUnkLinkFields(this->dyna.actor.cutscene, &this->dyna.actor); + this->lastTime = gSaveContext.save.time; + ObjUm_SetupAction(this, func_80B7ABE4); + } else { + ActorCutscene_SetIntentToPlay(this->dyna.actor.cutscene); + } +} + +void ObjUm_PostMilkRunWaitPathFinished(ObjUm* this, PlayState* play) { + Player* player = GET_PLAYER(play); + + player->stateFlags1 |= PLAYER_STATE1_20; + ObjUm_SetPlayerPosition(this, play); + ObjUm_RotatePlayer(this, play, 0); + this->flags |= OBJ_UM_FLAG_0004; + this->wheelRot += 0x3E8; + ObjUm_UpdateAnim(this, play, OBJ_UM_ANIM_TROT); + + if ((ObjUm_UpdatePath(this, play) == OBJUM_PATH_STATE_4) && !(gSaveContext.save.weekEventReg[59] & 2)) { + ActorCutscene_Stop(this->dyna.actor.cutscene); + Audio_SetCutsceneFlag(false); + gSaveContext.save.weekEventReg[59] |= 2; + gSaveContext.nextCutsceneIndex = 0xFFF3; + play->nextEntranceIndex = 0x5400; + play->transitionType = TRANS_TYPE_64; + gSaveContext.nextTransitionType = TRANS_TYPE_03; + play->transitionTrigger = TRANS_TRIGGER_START; + gSaveContext.save.time += CLOCK_TIME(1, 0) + 2; + } + Actor_MoveWithGravity(&this->dyna.actor); +} + +void ObjUm_PostMilkRunStartCs(ObjUm* this, PlayState* play) { + Player* player = GET_PLAYER(play); + + player->stateFlags1 |= PLAYER_STATE1_20; + ObjUm_SetPlayerPosition(this, play); + ObjUm_RotatePlayer(this, play, 0); + this->flags |= OBJ_UM_FLAG_0004; + ObjUm_UpdateAnim(this, play, OBJ_UM_ANIM_IDLE); + + if (ActorCutscene_GetCanPlayNext(this->dyna.actor.cutscene)) { + ActorCutscene_StartAndSetUnkLinkFields(this->dyna.actor.cutscene, &this->dyna.actor); + ObjUm_SetupAction(this, ObjUm_PostMilkRunWaitPathFinished); + } else { + ActorCutscene_SetIntentToPlay(this->dyna.actor.cutscene); + } +} + +void ObjUm_TerminaFieldIdle(ObjUm* this, PlayState* play) { + ObjUm_UpdateAnim(this, play, OBJ_UM_ANIM_IDLE); + SkelAnime_Update(&this->skelAnime); +} + +void func_80B7AF30(ObjUm* this, PlayState* play) { + if (!(this->flags & OBJ_UM_FLAG_0001)) { + this->dyna.actor.shape.rot.x = 0; + this->dyna.actor.shape.rot.z = 0; + } else { + CollisionPoly* sp44; + s32 pad[2]; + Vec3f sp30; + + this->flags &= ~OBJ_UM_FLAG_0001; + + if (1) {} + + this->unk_2D0 = this->unk_2C4; + this->unk_2E8 = this->unk_2DC; + + this->unk_2D0.y = BgCheck_EntityRaycastFloor1(&play->colCtx, &sp44, &this->unk_2C4); + if (this->unk_2D0.y == BGCHECK_Y_MIN) { + this->unk_2D0.y = this->dyna.actor.floorHeight; + } + + if (1) {} + + this->unk_2E8.y = BgCheck_EntityRaycastFloor1(&play->colCtx, &sp44, &this->unk_2DC); + if (this->unk_2E8.y == BGCHECK_Y_MIN) { + this->unk_2E8.y = this->dyna.actor.floorHeight; + } + + sp30.x = (this->unk_2D0.x + this->unk_2E8.x) * 0.5f; + sp30.y = (this->unk_2D0.y + this->unk_2E8.y) * 0.5f; + sp30.z = (this->unk_2D0.z + this->unk_2E8.z) * 0.5f; + + this->dyna.actor.shape.rot.x = + (s16)Math_Atan2S(sp30.y - this->dyna.actor.world.pos.y, sqrtf(SQ(sp30.x - this->dyna.actor.world.pos.x) + + SQ(sp30.z - this->dyna.actor.world.pos.z))); + this->dyna.actor.shape.rot.z = (s16)-Math_Atan2S( + sp30.y - this->unk_2D0.y, sqrtf(SQ(sp30.x - this->unk_2D0.x) + SQ(sp30.z - this->unk_2D0.z))); + if (this->flags & OBJ_UM_FLAG_MOVING) { + this->dyna.actor.shape.rot.x += BINANG_SUB((Rand_ZeroOne() * 100.0f), 50.0f); + this->dyna.actor.shape.rot.z += BINANG_SUB((Rand_ZeroOne() * 100.0f), 50.0f); + } + } +} + +void ObjUm_DefaultAnim(ObjUm* this, PlayState* play) { + Animation_PlayOnce(&this->skelAnime, &gUmTrotAnim); + this->currentAnimIndex = OBJ_UM_ANIM_TROT; +} + +typedef struct { + /* 0x00 */ AnimationHeader* anim; + /* 0x04 */ s32 doesMove; // `true` if the animation is intended to be used while the actor is moving +} struct_80B7C25C; // size = 0x08 + +struct_80B7C25C sUmAnims[] = { + { &gUmTrotAnim, true }, // OBJ_UM_ANIM_TROT + { &gUmGallopAnim, true }, // OBJ_UM_ANIM_GALLOP + { &gUmIdleAnim, false }, // OBJ_UM_ANIM_IDLE + { NULL, false }, // OBJ_UM_ANIM_3 + { &gUmLookBackAnim, false }, // OBJ_UM_ANIM_LOOK_BACK +}; + +void ObjUm_UpdateAnim(ObjUm* this, PlayState* play, ObjUmAnimimations index) { + s32 changeAnim; + s32 temp; + s32 indexTemp = index; + f32 animPlaybackSpeed = 0.0f; + + if (sUmAnims[index].doesMove) { + this->flags |= OBJ_UM_FLAG_MOVING; + } else { + this->flags &= ~OBJ_UM_FLAG_MOVING; + } + + if (index == OBJ_UM_ANIM_TROT) { + animPlaybackSpeed = this->dyna.actor.speedXZ * 0.25f; + } else if (index == OBJ_UM_ANIM_GALLOP) { + animPlaybackSpeed = this->dyna.actor.speedXZ * 0.2f; + } else if (index == OBJ_UM_ANIM_IDLE) { + animPlaybackSpeed = 1.0f; + } + this->skelAnime.playSpeed = animPlaybackSpeed; + + if (this->flags & OBJ_UM_FLAG_LOOK_BACK) { + this->skelAnime.playSpeed = 1.0f; + index = OBJ_UM_ANIM_MINUS_1; + } + + changeAnim = (index != this->currentAnimIndex); + if (SkelAnime_Update(&this->skelAnime) || changeAnim) { + this->currentAnimIndex = index; + + if (index != OBJ_UM_ANIM_MINUS_1) { + if (this->donkey != NULL) { + this->donkey->unk_538 = index; + } + + if (changeAnim) { + Animation_MorphToPlayOnce(&this->skelAnime, sUmAnims[index].anim, -3.0f); + } else { + Animation_PlayOnce(&this->skelAnime, sUmAnims[index].anim); + } + } else { + EnHorse* donkey = this->donkey; + + if (donkey != NULL) { + donkey->unk_538 = indexTemp; + } + + if (changeAnim) { + temp = 3 - index; // OBJ_UM_ANIM_LOOK_BACK + Animation_MorphToPlayOnce(&this->skelAnime, sUmAnims[temp].anim, -10.0f); + } else { + temp = 3 - index; // OBJ_UM_ANIM_LOOK_BACK + Animation_PlayOnce(&this->skelAnime, sUmAnims[temp].anim); + } + } + } + + if (this->wheelRot / 0x199A != this->unk_420) { + this->unk_420 = this->wheelRot / 0x199A; + //! FAKE + if (!&sUmAnims[0]) {} + Actor_PlaySfxAtPos(&this->dyna.actor, NA_SE_EV_CART_WHEEL); + } +} + +void ObjUm_Update(Actor* thisx, PlayState* play) { + ObjUm* this = THIS; + + this->actionFunc(this, play); + this->unk_350++; + Actor_UpdateBgCheckInfo(play, &this->dyna.actor, 0.0f, 0.0f, 0.0f, 0x1C); + + if (this->donkey != NULL) { + this->donkey->actor.world.pos.x = this->dyna.actor.world.pos.x; + this->donkey->actor.world.pos.y = this->dyna.actor.floorHeight; + this->donkey->actor.world.pos.z = this->dyna.actor.world.pos.z; + } + + if (this->flags & OBJ_UM_FLAG_0010) { + func_80123F2C(play, 0x63); + this->flags &= ~OBJ_UM_FLAG_0010; + } else if (this->flags & OBJ_UM_FLAG_0004) { + func_80123F2C(play, -3); + this->flags &= ~OBJ_UM_FLAG_0004; + } + + if (this->flags & OBJ_UM_FLAG_0100) { + this->flags &= ~OBJ_UM_FLAG_0100; + ObjUm_RotatePlayer(this, play, 0); + func_80B78EBC(this, play); + } + + func_80B7AF30(this, play); + switch (this->unk_4CC) { + case 0: + switch (this->eyeTexIndex) { + case 0: + if (Rand_ZeroOne() < 0.025f) { + this->eyeTexIndex = 1; + } + break; + + case 1: + if (Rand_ZeroOne() < 0.6f) { + this->eyeTexIndex = 2; + } + break; + + case 2: + if (Rand_ZeroOne() < 0.6f) { + this->eyeTexIndex = 0; + } + break; + + default: + this->eyeTexIndex = 0; + break; + } + break; + + case 1: + this->eyeTexIndex = 3; + break; + case 2: + this->eyeTexIndex = 4; + break; + case 3: + this->eyeTexIndex = 5; + break; + case 4: + this->eyeTexIndex = 2; + break; + case 5: + this->eyeTexIndex = 0; + break; + default: + this->unk_4CC = 0; + this->eyeTexIndex = 0; + break; + } +} + +s32 ObjUm_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, Actor* thisx) { + ObjUm* this = THIS; + Player* player = GET_PLAYER(play); + s32 pad; + s16 temp_v0_3; + Vec3f sp5C = { 4223.0f, -979.0f, 4098.0f }; + Vec3f sp50 = { 4223.0f, -980.0f, -4083.0f }; + + if ((limbIndex >= UM_LIMB_CREMIA_ROOT) && (this->type == OBJ_UM_TYPE_TERMINA_FIELD)) { + *dList = NULL; + return false; + } + + if (limbIndex == UM_LIMB_CREMIA_HEAD) { + OPEN_DISPS(play->state.gfxCtx); + + gSPSegment(POLY_OPA_DISP++, 0x08, Lib_SegmentedToVirtual(sEyeTextures[this->eyeTexIndex])); + gSPSegment(POLY_OPA_DISP++, 0x09, Lib_SegmentedToVirtual(sMouthTextures[this->mouthTexIndex])); + + CLOSE_DISPS(play->state.gfxCtx); + } + + if (limbIndex == UM_LIMB_WAGON_RIGHT_WHEEL) { + if (this->flags & OBJ_UM_FLAG_MOVING) { + rot->x = -this->wheelRot; + } + Matrix_MultVec3f(&sp5C, &this->unk_2C4); + } else if (limbIndex == UM_LIMB_WAGON_LEFT_WHEEL) { + if (this->flags & OBJ_UM_FLAG_MOVING) { + rot->x = this->wheelRot; + } + Matrix_MultVec3f(&sp50, &this->unk_2DC); + } else if ((limbIndex == UM_LIMB_CREMIA_HEAD) && (this->flags & OBJ_UM_FLAG_WAITING)) { + if (SubS_AngleDiffLessEqual(this->dyna.actor.shape.rot.y, 0x4E20, this->dyna.actor.yawTowardsPlayer) && + (this->dyna.actor.xzDistToPlayer < 500.0f)) { + s16 sp3E; + Vec3f sp30 = player->actor.world.pos; + + sp30.y = player->bodyPartsPos[7].y + 3.0f; + sp3E = Math_Vec3f_Yaw(&this->dyna.actor.focus.pos, &sp30) - this->dyna.actor.shape.rot.y; + temp_v0_3 = Math_Atan2S( + this->dyna.actor.focus.pos.y - sp30.y, + Math3D_XZLength(sp30.x - this->dyna.actor.focus.pos.x, sp30.z - this->dyna.actor.focus.pos.z)); + this->unk_2FE.x = rot->x + sp3E; + this->unk_2FE.y = rot->y; + this->unk_2FE.z = rot->z + temp_v0_3; + Math_SmoothStepToS(&this->unk_2F8.x, this->unk_2FE.x, 4, 0x3E8, 1); + Math_SmoothStepToS(&this->unk_2F8.z, this->unk_2FE.z, 4, 0x3E8, 1); + this->unk_2F8.y = rot->y; + rot->x = this->unk_2F8.x; + rot->z = this->unk_2F8.z; + } else { + this->unk_2FE.x = rot->x; + this->unk_2FE.y = rot->y; + this->unk_2FE.z = rot->z; + Math_SmoothStepToS(&this->unk_2F8.x, this->unk_2FE.x, 4, 0x3E8, 1); + Math_SmoothStepToS(&this->unk_2F8.z, this->unk_2FE.z, 4, 0x3E8, 1); + this->unk_2F8.y = rot->y; + rot->x = this->unk_2F8.x; + rot->z = this->unk_2F8.z; + } + } else if ((limbIndex == UM_LIMB_WAGON_CART_COVER) && (this->flags & OBJ_UM_FLAG_PLAYING_MINIGAME)) { + *dList = NULL; + } + + return false; +} + +void ObjUm_SpawnFragments(PlayState* play, Vec3f* potPos) { + Vec3f sp8C = { 0.0f, -1.0f, 0.0f }; + Gfx* potFragments[] = { object_um_DL_000040, object_um_DL_000910, object_um_DL_0011E0 }; + s32 i; + Vec3f sp70; + + EffectSsHitmark_SpawnFixedScale(play, 0, potPos); + + for (i = 0; i < 20; i++) { + sp70.x = (Rand_ZeroOne() * 20.0f) - 10.0f; + sp70.y = -((Rand_ZeroOne() * 20.0f) - 10.0f); + sp70.z = (Rand_ZeroOne() * 20.0f) - 10.0f; + EffectSsHahen_Spawn(play, potPos, &sp70, &sp8C, 1, 100, OBJECT_UM, 10, + potFragments[(s32)(Rand_ZeroOne() * ARRAY_COUNT(potFragments))]); + } +} + +void ObjUm_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx) { + ObjUm* this = THIS; + GraphicsContext* gfxCtx = play->state.gfxCtx; + Mtx* mtx_s3; + Gfx* spFC[] = { + NULL, gUmBrokenMinigamePotDL, gUmMinigamePotDL, gUmMinigamePotDL, gUmMinigamePotDL, object_um_DL_0067C0 + }; + Gfx* spE4[] = { NULL, NULL, object_um_DL_004B60, object_um_DL_0043E0, NULL, NULL }; + f32 spCC[] = { 0.0f, 1070.0f, 1070.0f, 1070.0f, 1070.0f, 2100.0f }; + Vec3f spC0 = gZeroVec3f; + Vec3f calcPotPos; + f32 spB0; + + spC0.y += 1700.0f; + + if (limbIndex == UM_LIMB_WAGON_CART_BED) { + Vec3f spA4 = { 2000.0f, 1070.0f, 0.0f }; + + Matrix_MultVec3f(&spA4, &this->unk_308); + this->flags |= OBJ_UM_FLAG_DRAWN_FLOOR; + } + + if (limbIndex == UM_LIMB_WAGON_CART_BED) { + Vec3f sp98 = { 2500.0f, 200.0f, 0.0f }; + + Matrix_MultVec3f(&sp98, &this->cartBedPos); + } + + if (limbIndex == UM_LIMB_WAGON_CART_BED) { + Vec3f* potPos; + Vec3f sp88; + Vec3s sp80; + s32 i; + f32 sp70[] = { 2000.0f, 0.0f, -2000.0f }; + + //! FAKE + if (!i) {} + + sp80.x = 0; + sp80.z = 0; + sp88.x = 6800.0f; + OPEN_DISPS(gfxCtx); + + for (i = 0; i < ARRAY_COUNT(this->potsLife); i++) { + sp88.z = sp70[i]; + sp88.y = spCC[this->potsLife[i]]; + + if (this->potsLife[i] == 5) { + sp80.y = 0x4000; + } else { + sp80.y = -0x4000; + } + + Matrix_Push(); + Matrix_TranslateRotateZYX(&sp88, &sp80); + mtx_s3 = Matrix_NewMtx(gfxCtx); + potPos = &this->potPos[i]; + Matrix_MultVec3f(&spC0, &calcPotPos); + SkinMatrix_Vec3fMtxFMultXYZW(&play->viewProjectionMtxF, &calcPotPos, potPos, &spB0); + + if (this->wasPotHit[i]) { + this->wasPotHit[i] = false; + if (this->potsLife[i] == 1) { + ObjUm_SpawnFragments(play, &calcPotPos); + } else { + EffectSsHitmark_SpawnFixedScale(play, 0, &calcPotPos); + } + } + Matrix_Pop(); + + if (mtx_s3 != NULL) { + if (play) {} + gSPMatrix(POLY_OPA_DISP++, mtx_s3, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + if (spFC[this->potsLife[i]] != NULL) { + s32 pad; + + gSPDisplayList(POLY_OPA_DISP++, spFC[this->potsLife[i]]); + + if (spE4[this->potsLife[i]] != NULL) { + gSPDisplayList(POLY_OPA_DISP++, spE4[this->potsLife[i]]); + } + } + } else { + //! @bug skips CLOSE_DISPS + return; + } + } + + CLOSE_DISPS(gfxCtx); + } + + if (limbIndex == UM_LIMB_CREMIA_HEAD) { + Matrix_MultZero(&this->dyna.actor.focus.pos); + } +} + +void func_80B7BEA4(Vec3f* cartBedPos, s16 arg1, Vec3f* arg2, u8 alpha, PlayState* play) { + f32 temp; + Vec3f sp108; + CollisionPoly* sp104; + Mtx* sp100; + MtxF spC0; + MtxF sp80; + MtxF sp40; + + sp108.x = cartBedPos->x; + sp108.y = cartBedPos->y + 1.0f; + sp108.z = cartBedPos->z; + + temp = BgCheck_EntityRaycastFloor2(play, &play->colCtx, &sp104, &sp108); + if (sp104 != NULL) { + func_800C0094(sp104, cartBedPos->x, temp, cartBedPos->z, &spC0); + } else { + SkinMatrix_SetTranslate(&spC0, cartBedPos->x, cartBedPos->y, cartBedPos->z); + } + + SkinMatrix_MulYRotation(&spC0, arg1); + SkinMatrix_SetScale(&sp80, arg2->x, 1.0f, arg2->z); + SkinMatrix_MtxFMtxFMult(&spC0, &sp80, &sp40); + + sp100 = SkinMatrix_MtxFToNewMtx(play->state.gfxCtx, &sp40); + if (sp100 != NULL) { + OPEN_DISPS(play->state.gfxCtx); + + gSPMatrix(POLY_OPA_DISP++, &gIdentityMtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + POLY_OPA_DISP = Gfx_CallSetupDL(POLY_OPA_DISP, 0x2C); + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 0, 0, 0, alpha); + gSPMatrix(POLY_OPA_DISP++, sp100, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gSquareShadowDL); + + CLOSE_DISPS(play->state.gfxCtx); + } +} + +void ObjUm_Draw(Actor* thisx, PlayState* play) { + s32 pad; + ObjUm* this = THIS; + Vec3f sp34; + + this->flags |= OBJ_UM_FLAG_0001; + SkelAnime_DrawFlexOpa(play, this->skelAnime.skeleton, this->skelAnime.jointTable, this->skelAnime.dListCount, + ObjUm_OverrideLimbDraw, ObjUm_PostLimbDraw, &this->dyna.actor); + sp34.x = 0.45f; + sp34.y = 0.0f; + sp34.z = 0.7f; + func_80B7BEA4(&this->cartBedPos, this->dyna.actor.shape.rot.y, &sp34, 180, play); + func_80B77770(this, play); +} diff --git a/src/overlays/actors/ovl_Obj_Um/z_obj_um.h b/src/overlays/actors/ovl_Obj_Um/z_obj_um.h index d343d3a512..9d228eda85 100644 --- a/src/overlays/actors/ovl_Obj_Um/z_obj_um.h +++ b/src/overlays/actors/ovl_Obj_Um/z_obj_um.h @@ -2,18 +2,93 @@ #define Z_OBJ_UM_H #include "global.h" +#include "objects/object_um/object_um.h" +#include "overlays/actors/ovl_En_Horse/z_en_horse.h" struct ObjUm; typedef void (*ObjUmActionFunc)(struct ObjUm*, PlayState*); +#define MILK_POTS_COUNT 3 + +typedef enum ObjUmAnimimations { + /* -1 */ OBJ_UM_ANIM_MINUS_1 = -1, + /* 0 */ OBJ_UM_ANIM_TROT, + /* 1 */ OBJ_UM_ANIM_GALLOP, + /* 2 */ OBJ_UM_ANIM_IDLE, + /* 3 */ OBJ_UM_ANIM_3, // NULL pointer + /* 4 */ OBJ_UM_ANIM_LOOK_BACK +} ObjUmAnimimations; + typedef struct ObjUm { - /* 0x000 */ Actor actor; - /* 0x144 */ char unk_144[0x18]; + /* 0x000 */ DynaPolyActor dyna; /* 0x15C */ ObjUmActionFunc actionFunc; - /* 0x160 */ char unk_160[0x384]; + /* 0x160 */ SkelAnime skelAnime; + /* 0x1A4 */ Vec3s jointTable[UM_LIMB_MAX]; + /* 0x228 */ Vec3s morphTable[UM_LIMB_MAX]; + /* 0x2AC */ s16 wheelRot; + /* 0x2AE */ s16 type; + /* 0x2B0 */ s16 initialPathIndex; + /* 0x2B4 */ s32 unk_2B4; + /* 0x2B8 */ EnHorse* donkey; + /* 0x2BC */ s32 pathIndex; + /* 0x2BE */ s32 pointIndex; + /* 0x2C4 */ Vec3f unk_2C4; + /* 0x2D0 */ Vec3f unk_2D0; + /* 0x2DC */ Vec3f unk_2DC; + /* 0x2E8 */ Vec3f unk_2E8; + /* 0x2F4 */ s32 flags; + /* 0x2BC */ Vec3s unk_2F8; + /* 0x2FE */ Vec3s unk_2FE; + /* 0x304 */ ObjUmAnimimations currentAnimIndex; + /* 0x308 */ Vec3f unk_308; + /* 0x314 */ s32 potsLife[MILK_POTS_COUNT]; + /* 0x320 */ s32 wasPotHit[MILK_POTS_COUNT]; // resets to false in the same frame + /* 0x32C */ Vec3f potPos[MILK_POTS_COUNT]; + /* 0x350 */ s32 unk_350; // unused counter? + /* 0x354 */ s32 unk_354; // unused? + /* 0x358 */ EnHorse* bandit1; + /* 0x35C */ EnHorse* bandit2; + /* 0x360 */ Vec3f unk_360[16]; + /* 0x420 */ s32 unk_420; // ? + /* 0x424 */ ColliderCylinder banditsCollisions[2]; + /* 0x4BC */ Vec3f cartBedPos; + /* 0x4C8 */ u16 lastTime; + /* 0x4CC */ s32 unk_4CC; + /* 0x4D0 */ s32 eyeTexIndex; + /* 0x4D4 */ s32 mouthTexIndex; + /* 0x4D8 */ s32 unk_4D8; + /* 0x4DC */ s32 unk_4DC; + /* 0x4E0 */ s32 areAllPotsBroken; // true when all of the pots have been broken } ObjUm; // size = 0x4E4 extern const ActorInit Obj_Um_InitVars; +typedef enum { + /* 0 */ OBJ_UM_TYPE_TERMINA_FIELD, + /* 1 */ OBJ_UM_TYPE_RANCH, + /* 2 */ OBJ_UM_TYPE_PRE_MILK_RUN, // milk road, pre-minigame + /* 3 */ OBJ_UM_TYPE_MILK_RUN_MINIGAME, + /* 4 */ OBJ_UM_TYPE_POST_MILK_RUN // milk road, post-minigame +} ObjUmType; + +#define OBJ_UM_PARSE_TYPE(thisx) (((thisx)->params & 0xFF00) >> 8) +#define OBJ_UM_PARSE_PATH_INDEX(thisx) ((thisx)->params & 0xFF) + +#define OBJ_UM_FLAG_NONE (0) +#define OBJ_UM_FLAG_0001 (1 << 0) +#define OBJ_UM_FLAG_MOVING (1 << 1) +#define OBJ_UM_FLAG_0004 (1 << 2) +#define OBJ_UM_FLAG_WAITING (1 << 3) // Waiting in the Ranch +#define OBJ_UM_FLAG_0010 (1 << 4) +#define OBJ_UM_FLAG_DRAWN_FLOOR (1 << 5) +#define OBJ_UM_FLAG_0040 (1 << 6) +#define OBJ_UM_FLAG_PLAYING_MINIGAME (1 << 7) +#define OBJ_UM_FLAG_0100 (1 << 8) +#define OBJ_UM_FLAG_0200 (1 << 9) // Something bandit1 +#define OBJ_UM_FLAG_0400 (1 << 10) // Something bandit2 +#define OBJ_UM_FLAG_LOOK_BACK (1 << 11) +#define OBJ_UM_FLAG_1000 (1 << 12) +#define OBJ_UM_FLAG_MINIGAME_FINISHED (1 << 13) + #endif // Z_OBJ_UM_H diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt index ebcf5d2a4e..3f26ba062b 100644 --- a/tools/disasm/functions.txt +++ b/tools/disasm/functions.txt @@ -14462,57 +14462,57 @@ 0x80B77354:("EnTruMt_TransformLimbDraw",), 0x80B773D0:("EnTruMt_Draw",), 0x80B77770:("func_80B77770",), - 0x80B77FA4:("func_80B77FA4",), + 0x80B77FA4:("ObjUm_InitBandits",), 0x80B781DC:("func_80B781DC",), 0x80B783E0:("func_80B783E0",), 0x80B78764:("func_80B78764",), 0x80B78A54:("func_80B78A54",), 0x80B78C18:("func_80B78C18",), - 0x80B78D08:("func_80B78D08",), + 0x80B78D08:("ObjUm_UpdateBanditsCollisions",), 0x80B78DF0:("func_80B78DF0",), 0x80B78E2C:("ObjUm_SetupAction",), - 0x80B78E38:("func_80B78E38",), - 0x80B78E88:("func_80B78E88",), + 0x80B78E38:("ObjUm_SetPlayerPosition",), + 0x80B78E88:("ObjUm_RotatePlayer",), 0x80B78EBC:("func_80B78EBC",), - 0x80B78EFC:("func_80B78EFC",), + 0x80B78EFC:("ObjUm_RotatePlayerView",), 0x80B78F24:("ObjUm_Init",), 0x80B7949C:("ObjUm_Destroy",), 0x80B79524:("func_80B79524",), 0x80B79560:("func_80B79560",), 0x80B795A0:("func_80B795A0",), 0x80B79734:("func_80B79734",), - 0x80B797EC:("func_80B797EC",), + 0x80B797EC:("ObjUm_RanchGetDialogue",), 0x80B7984C:("func_80B7984C",), 0x80B79A24:("func_80B79A24",), - 0x80B79A50:("func_80B79A50",), - 0x80B79BA0:("func_80B79BA0",), - 0x80B79F10:("func_80B79F10",), - 0x80B79FFC:("func_80B79FFC",), + 0x80B79A50:("ObjUm_RanchWait",), + 0x80B79BA0:("ObjUm_UpdatePath",), + 0x80B79F10:("ObjUm_RanchWaitPathFinished",), + 0x80B79FFC:("ObjUm_RanchStartCs",), 0x80B7A070:("func_80B7A070",), 0x80B7A0E0:("func_80B7A0E0",), 0x80B7A144:("func_80B7A144",), - 0x80B7A1B4:("func_80B7A1B4",), + 0x80B7A1B4:("ObjUm_PreMilkRunDialogueHandler",), 0x80B7A240:("func_80B7A240",), 0x80B7A2AC:("func_80B7A2AC",), 0x80B7A394:("func_80B7A394",), - 0x80B7A400:("func_80B7A400",), - 0x80B7A494:("func_80B7A494",), + 0x80B7A400:("ObjUm_PreMilkRunStartCs",), + 0x80B7A494:("ObjUm_RunMinigame",), 0x80B7A614:("func_80B7A614",), 0x80B7A7AC:("func_80B7A7AC",), 0x80B7A860:("func_80B7A860",), 0x80B7AB78:("func_80B7AB78",), 0x80B7ABE4:("func_80B7ABE4",), - 0x80B7AC94:("func_80B7AC94",), - 0x80B7AD34:("func_80B7AD34",), - 0x80B7AE58:("func_80B7AE58",), - 0x80B7AEFC:("func_80B7AEFC",), + 0x80B7AC94:("ObjUm_StartCs",), + 0x80B7AD34:("ObjUm_PostMilkRunWaitPathFinished",), + 0x80B7AE58:("ObjUm_PostMilkRunStartCs",), + 0x80B7AEFC:("ObjUm_TerminaFieldIdle",), 0x80B7AF30:("func_80B7AF30",), - 0x80B7B154:("func_80B7B154",), - 0x80B7B18C:("func_80B7B18C",), + 0x80B7B154:("ObjUm_DefaultAnim",), + 0x80B7B18C:("ObjUm_UpdateAnim",), 0x80B7B368:("ObjUm_Update",), - 0x80B7B598:("func_80B7B598",), - 0x80B7B93C:("func_80B7B93C",), - 0x80B7BABC:("func_80B7BABC",), + 0x80B7B598:("ObjUm_OverrideLimbDraw",), + 0x80B7B93C:("ObjUm_SpawnFragments",), + 0x80B7BABC:("ObjUm_PostLimbDraw",), 0x80B7BEA4:("func_80B7BEA4",), 0x80B7C03C:("ObjUm_Draw",), 0x80B7C890:("EnNeoReeba_Init",), diff --git a/tools/disasm/variables.txt b/tools/disasm/variables.txt index d9ce9cf704..77f840dbe7 100644 --- a/tools/disasm/variables.txt +++ b/tools/disasm/variables.txt @@ -15003,14 +15003,12 @@ 0x80B77684:("D_80B77684","f32","",0x4), 0x80B77688:("D_80B77688","f32","",0x4), 0x80B7C0F0:("Obj_Um_InitVars","UNK_TYPE1","",0x1), - 0x80B7C110:("D_80B7C110","UNK_TYPE1","",0x1), - 0x80B7C128:("D_80B7C128","UNK_TYPE1","",0x1), - 0x80B7C138:("D_80B7C138","UNK_TYPE1","",0x1), + 0x80B7C110:("sEyeTextures","UNK_TYPE1","",0x1), + 0x80B7C128:("sMouthTextures","UNK_TYPE1","",0x1), + 0x80B7C138:("sCylinderInit","UNK_TYPE1","",0x1), 0x80B7C164:("D_80B7C164","UNK_TYPE4","",0x4), - 0x80B7C254:("D_80B7C254","UNK_TYPE4","",0x4), - 0x80B7C25C:("D_80B7C25C","UNK_TYPE1","",0x1), - 0x80B7C260:("D_80B7C260","UNK_TYPE1","",0x1), - 0x80B7C274:("D_80B7C274","UNK_TYPE1","",0x1), + 0x80B7C254:("sInitChain","UNK_TYPE4","",0x4), + 0x80B7C25C:("sUmAnims","UNK_TYPE1","[5]",0x28), 0x80B7C284:("D_80B7C284","UNK_TYPE4","",0x4), 0x80B7C290:("D_80B7C290","UNK_TYPE4","",0x4), 0x80B7C29C:("D_80B7C29C","UNK_TYPE4","",0x4), diff --git a/tools/namefixer.py b/tools/namefixer.py index aa77383115..d2cf4ba773 100755 --- a/tools/namefixer.py +++ b/tools/namefixer.py @@ -576,6 +576,7 @@ wordReplace = { "func_800E8F08": "Actor_TrackNone", "func_800E8FA4": "Actor_TrackPoint", "func_800E9250": "Actor_TrackPlayer", + "func_800E8EA0": "Actor_ContinueText", "func_8010A000": "Map_GetDungeonOrBossAreaIndex", "func_8010A074": "Map_IsInDungeonOrBossArea", diff --git a/tools/permuter_settings.toml b/tools/permuter_settings.toml index 9b1959be9a..bf61be3410 100644 --- a/tools/permuter_settings.toml +++ b/tools/permuter_settings.toml @@ -11,6 +11,8 @@ CLOSE_DISPS = "void" ABS = "int" ABS_ALT = "int" SQ = "int" +ARRAY_COUNT = "int" +ARRAY_COUNTU = "int" CLAMP = "int" CLOCK_TIME = "int" CURRENT_DAY = "int" diff --git a/undefined_syms.txt b/undefined_syms.txt index a9cc3e6f5e..c9a2964db2 100644 --- a/undefined_syms.txt +++ b/undefined_syms.txt @@ -1480,13 +1480,6 @@ D_06001100 = 0x06001100; D_06001140 = 0x06001140; D_06001CB0 = 0x06001CB0; -// ovl_Obj_Um - -D_06007E20 = 0x06007E20; -D_06007F50 = 0x06007F50; -D_06011DF8 = 0x06011DF8; -D_06012CC0 = 0x06012CC0; - // ovl_Obj_Usiyane D_06000098 = 0x06000098;