diff --git a/spec b/spec index e2ea0c1b33..80141af9c4 100644 --- a/spec +++ b/spec @@ -3198,8 +3198,7 @@ beginseg name "ovl_En_Door_Etc" compress include "build/src/overlays/actors/ovl_En_Door_Etc/z_en_door_etc.o" - include "build/data/ovl_En_Door_Etc/ovl_En_Door_Etc.data.o" - include "build/data/ovl_En_Door_Etc/ovl_En_Door_Etc.reloc.o" + include "build/src/overlays/actors/ovl_En_Door_Etc/ovl_En_Door_Etc_reloc.o" endseg beginseg diff --git a/src/overlays/actors/ovl_En_Door_Etc/z_en_door_etc.c b/src/overlays/actors/ovl_En_Door_Etc/z_en_door_etc.c index 0d3612145f..98e9d2b8fa 100644 --- a/src/overlays/actors/ovl_En_Door_Etc/z_en_door_etc.c +++ b/src/overlays/actors/ovl_En_Door_Etc/z_en_door_etc.c @@ -5,6 +5,7 @@ */ #include "z_en_door_etc.h" +#include "objects/gameplay_keep/gameplay_keep.h" #define FLAGS (ACTOR_FLAG_10) @@ -14,7 +15,11 @@ void EnDoorEtc_Init(Actor* thisx, PlayState* play); void EnDoorEtc_Destroy(Actor* thisx, PlayState* play); void EnDoorEtc_Update(Actor* thisx, PlayState* play); -#if 0 +void EnDoorEtc_WaitForObject(EnDoorEtc* this, PlayState* play); +void func_80AC21A0(EnDoorEtc* this, PlayState* play); +void func_80AC2354(EnDoorEtc* this, PlayState* play); +void EnDoorEtc_Draw(Actor* thisx, PlayState* play); + const ActorInit En_Door_Etc_InitVars = { ACTOR_EN_DOOR_ETC, ACTORCAT_DOOR, @@ -27,42 +32,219 @@ const ActorInit En_Door_Etc_InitVars = { (ActorFunc)NULL, }; -// static ColliderCylinderInit sCylinderInit = { -static ColliderCylinderInit D_80AC25A0 = { - { COLTYPE_NONE, AT_NONE, AC_ON | AC_TYPE_PLAYER, OC1_ON | OC1_TYPE_ALL, OC2_TYPE_1, COLSHAPE_CYLINDER, }, - { ELEMTYPE_UNK0, { 0x00000000, 0x00, 0x00 }, { 0x00000000, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, +static ColliderCylinderInit sCylinderInit = { + { + COLTYPE_NONE, + AT_NONE, + AC_ON | AC_TYPE_PLAYER, + OC1_ON | OC1_TYPE_ALL, + OC2_TYPE_1, + COLSHAPE_CYLINDER, + }, + { + ELEMTYPE_UNK0, + { 0x00000000, 0x00, 0x00 }, + { 0x00000000, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, { 100, 40, 0, { 0, 0, 0 } }, }; -// static InitChainEntry sInitChain[] = { -static InitChainEntry D_80AC2634[] = { +typedef struct { + /* 0x0 */ s16 sceneId; + /* 0x2 */ u8 dListIndex; + /* 0x4 */ s16 objectId; +} EnDoorEtcInfo; // size = 0x6 + +EnDoorEtcInfo sObjInfo[] = { + { SCENE_MITURIN, 1, OBJECT_NUMA_OBJ }, + { -1, 0, GAMEPLAY_KEEP }, + { -1, 13, GAMEPLAY_FIELD_KEEP }, + { 0, 0, OBJECT_UNSET_0 }, + { 0, 0, OBJECT_UNSET_0 }, + { 0, 0, OBJECT_UNSET_0 }, + { 0, 0, OBJECT_UNSET_0 }, + { 0, 0, OBJECT_UNSET_0 }, + { 0, 0, OBJECT_UNSET_0 }, + { 0, 0, OBJECT_UNSET_0 }, + { 0, 0, OBJECT_UNSET_0 }, + { 0, 0, OBJECT_UNSET_0 }, + { 0, 0, OBJECT_UNSET_0 }, + { 0, 0, OBJECT_UNSET_0 }, + { 0, 0, OBJECT_UNSET_0 }, + { 0, 0, OBJECT_UNSET_0 }, + { 0, 0, OBJECT_UNSET_0 }, +}; + +static InitChainEntry sInitChain[] = { ICHAIN_U8(targetMode, 0, ICHAIN_CONTINUE), ICHAIN_F32(uncullZoneForward, 4000, ICHAIN_CONTINUE), ICHAIN_U16(shape.rot.x, 0, ICHAIN_CONTINUE), ICHAIN_U16(shape.rot.z, 0, ICHAIN_STOP), }; -#endif +void EnDoorEtc_Init(Actor* thisx, PlayState* play2) { + PlayState* play = play2; + s32 objectIndex; + EnDoorEtcInfo* objectInfo = sObjInfo; + s32 i; + EnDoorEtc* this = THIS; -extern ColliderCylinderInit D_80AC25A0; -extern InitChainEntry D_80AC2634[]; + Actor_ProcessInitChain(&this->actor, sInitChain); + Actor_SetScale(&this->actor, 0.01f); + this->actor.shape.rot.x = -0x4000; + this->angle = 0; + for (i = 0; i < 15; i++, objectInfo++) { + if (play->sceneId == objectInfo->sceneId) { + break; + } + } + if ((i >= 15) && (Object_GetIndex(&play->objectCtx, GAMEPLAY_FIELD_KEEP) >= 0)) { + objectInfo++; + } + objectIndex = Object_GetIndex(&play->objectCtx, objectInfo->objectId); + if (objectIndex < 0) { + Actor_MarkForDeath(&this->actor); + } else { + this->objectIndex = objectIndex; + this->dListIndex = objectInfo->dListIndex; + if (this->actor.objBankIndex == this->objectIndex) { + EnDoorEtc_WaitForObject(this, play); + } else { + this->actionFunc = EnDoorEtc_WaitForObject; + } + } + Collider_InitCylinder(play, &this->collider); + Collider_SetCylinder(play, &this->collider, &this->actor, &sCylinderInit); + this->actor.colChkInfo.mass = MASS_IMMOVABLE; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Door_Etc/EnDoorEtc_Init.s") +void EnDoorEtc_Destroy(Actor* thisx, PlayState* play) { + EnDoorEtc* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Door_Etc/EnDoorEtc_Destroy.s") + Collider_DestroyCylinder(play, &this->collider); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Door_Etc/func_80AC2044.s") +/** + * Calculates if the distance between `a` and `b` is greater than distance `c` + */ +s32 EnDoorEtc_IsDistanceGreater(Vec3f* a, Vec3f* b, f32 c) { + f32 dx = b->x - a->x; + f32 dy = b->y - a->y; + f32 dz = b->z - a->z; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Door_Etc/func_80AC20A8.s") + return ((SQ(dx) + SQ(dy) + SQ(dz)) < SQ(c)); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Door_Etc/func_80AC2118.s") +void EnDoorEtc_WaitForObject(EnDoorEtc* this, PlayState* play) { + if (Object_IsLoaded(&play->objectCtx, this->objectIndex)) { + this->actor.flags &= ~ACTOR_FLAG_10; + this->actor.objBankIndex = this->objectIndex; + this->actionFunc = func_80AC2354; + this->actor.draw = EnDoorEtc_Draw; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Door_Etc/func_80AC2154.s") +void func_80AC2118(EnDoorEtc* this, PlayState* play) { + if (this->angle < 0) { + this->angle += 0x100; + } else { + this->angle = 0; + this->actionFunc = func_80AC21A0; + this->unk_1F4 &= ~1; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Door_Etc/func_80AC21A0.s") +void func_80AC2154(EnDoorEtc* this, PlayState* play) { + if (this->timer > 0) { + this->timer--; + } else if (this->angle > -0x4000) { + this->angle -= 0x800; + } else { + this->angle = -0x4000; + this->actionFunc = func_80AC2118; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Door_Etc/func_80AC2354.s") +void func_80AC21A0(EnDoorEtc* this, PlayState* play) { + Player* player = GET_PLAYER(play); + Vec3f playerOffsetFromDoor; + s32 pad; + s16 yawDiff; + s32 yawDiffAbs; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Door_Etc/EnDoorEtc_Update.s") + Actor_OffsetOfPointInActorCoords(&this->actor, &playerOffsetFromDoor, &player->actor.world.pos); + if (this->unk_1A1 == 0) { + if ((!Player_InCsMode(play)) && + ((fabsf(playerOffsetFromDoor.y) < 20.0f) && fabsf(playerOffsetFromDoor.x) < 20.0f) && + (fabsf(playerOffsetFromDoor.z) < 50.0f)) { + yawDiff = player->actor.shape.rot.y - this->actor.shape.rot.y; + if (playerOffsetFromDoor.z > 0.0f) { + yawDiff = 0x8000 - yawDiff; + } + yawDiffAbs = ABS_ALT(yawDiff); + if (yawDiffAbs < 0x3000) { + player->doorDirection = (playerOffsetFromDoor.z >= 0.0f) ? 1.0f : -1.0f; + player->doorActor = &this->actor; + player->doorType = -1; + } + } + } + if ((this->actor.textId == 0x239B) && Flags_GetSwitch(play, ENDOORETC_GET_SWITCHFLAG(&this->actor))) { + Flags_UnsetSwitch(play, ENDOORETC_GET_SWITCHFLAG(&this->actor)); + this->actionFunc = func_80AC2154; + this->actor.textId = 0x1800; // "It won't budge!" + this->unk_1F4 |= 1; + this->timer = 0x5A; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Door_Etc/func_80AC24A8.s") +void func_80AC2354(EnDoorEtc* this, PlayState* play) { + Actor* door = play->actorCtx.actorLists[ACTORCAT_DOOR].first; + + while (door != NULL) { + if ((door->id != ACTOR_EN_DOOR) || + !EnDoorEtc_IsDistanceGreater(&door->world.pos, &this->actor.world.pos, 10.0f)) { + door = door->next; + } else { + this->actor.world.pos.x = door->world.pos.x; + this->actor.world.pos.y = door->world.pos.y; + this->actor.world.pos.z = door->world.pos.z; + this->actor.shape.rot.y = door->shape.rot.y; + this->actor.world.rot.y = door->world.rot.y; + Actor_MarkForDeath(door); + this->actionFunc = func_80AC21A0; + this->actor.textId = 0x239B; + Actor_SetFocus(&this->actor, 70.0f); + break; + } + } +} + +void EnDoorEtc_Update(Actor* thisx, PlayState* play) { + s32 pad; + EnDoorEtc* this = THIS; + + this->actionFunc(this, play); + if (this->unk_1F4 & 1) { + Collider_UpdateCylinder(&this->actor, &this->collider); + CollisionCheck_SetOC(play, &play->colChkCtx, &this->collider.base); + } +} + +void EnDoorEtc_Draw(Actor* thisx, PlayState* play) { + EnDoorEtc* this = THIS; + + OPEN_DISPS(play->state.gfxCtx); + + func_8012C28C(play->state.gfxCtx); + Matrix_Translate(-2900.0f, 0.0f, 0.0f, MTXMODE_APPLY); + Matrix_RotateZS(this->angle, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gDoorLeftDL); + gSPDisplayList(POLY_OPA_DISP++, gDoorRightDL); + + CLOSE_DISPS(play->state.gfxCtx); +} diff --git a/src/overlays/actors/ovl_En_Door_Etc/z_en_door_etc.h b/src/overlays/actors/ovl_En_Door_Etc/z_en_door_etc.h index 18d525f44a..cbcdf2f54f 100644 --- a/src/overlays/actors/ovl_En_Door_Etc/z_en_door_etc.h +++ b/src/overlays/actors/ovl_En_Door_Etc/z_en_door_etc.h @@ -5,11 +5,20 @@ struct EnDoorEtc; +#define ENDOORETC_GET_SWITCHFLAG(thisx) ((thisx)->params & 0x7F) + typedef void (*EnDoorEtcActionFunc)(struct EnDoorEtc*, PlayState*); typedef struct EnDoorEtc { /* 0x000 */ Actor actor; - /* 0x144 */ char unk_144[0xB4]; + /* 0x144 */ char pad_144[0x5D]; + /* 0x1A1 */ u8 unk_1A1; + /* 0x1A2 */ s8 objectIndex; + /* 0x1A3 */ u8 dListIndex; // Never read, inferred from ovl_En_Door + /* 0x1A4 */ s16 angle; + /* 0x1A6 */ s16 timer; + /* 0x1A8 */ ColliderCylinder collider; + /* 0x1F4 */ u8 unk_1F4; /* 0x1F8 */ EnDoorEtcActionFunc actionFunc; } EnDoorEtc; // size = 0x1FC diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt index a465f75992..594ce3427b 100644 --- a/tools/disasm/functions.txt +++ b/tools/disasm/functions.txt @@ -11902,14 +11902,14 @@ 0x80AC1D14:("EnPoFusen_Draw",), 0x80AC1ED0:("EnDoorEtc_Init",), 0x80AC2018:("EnDoorEtc_Destroy",), - 0x80AC2044:("func_80AC2044",), - 0x80AC20A8:("func_80AC20A8",), + 0x80AC2044:("EnDoorEtc_IsDistanceGreater",), + 0x80AC20A8:("EnDoorEtc_WaitForObject",), 0x80AC2118:("func_80AC2118",), 0x80AC2154:("func_80AC2154",), 0x80AC21A0:("func_80AC21A0",), 0x80AC2354:("func_80AC2354",), 0x80AC2430:("EnDoorEtc_Update",), - 0x80AC24A8:("func_80AC24A8",), + 0x80AC24A8:("EnDoorEtc_Draw",), 0x80AC26F0:("EnBigokuta_Init",), 0x80AC2874:("EnBigokuta_Destroy",), 0x80AC28B4:("EnBigokuta_SetupCutsceneCamera",), diff --git a/tools/disasm/variables.txt b/tools/disasm/variables.txt index 57d876acbb..97cf77e76c 100644 --- a/tools/disasm/variables.txt +++ b/tools/disasm/variables.txt @@ -12869,9 +12869,9 @@ 0x80AC1E00:("D_80AC1E00","f32","",0x4), 0x80AC1E04:("D_80AC1E04","f32","",0x4), 0x80AC2580:("En_Door_Etc_InitVars","UNK_TYPE1","",0x1), - 0x80AC25A0:("D_80AC25A0","UNK_TYPE1","",0x1), - 0x80AC25CC:("D_80AC25CC","UNK_TYPE2","",0x2), - 0x80AC2634:("D_80AC2634","UNK_TYPE1","",0x1), + 0x80AC25A0:("sCylinderInit","UNK_TYPE1","",0x1), + 0x80AC25CC:("sObjInfo","UNK_TYPE2","",0x2), + 0x80AC2634:("sInitChain","UNK_TYPE1","",0x1), 0x80AC2650:("D_80AC2650","f32","",0x4), 0x80AC4510:("En_Bigokuta_InitVars","UNK_TYPE1","",0x1), 0x80AC4530:("D_80AC4530","UNK_TYPE1","",0x1),