diff --git a/assets/xml/objects/gameplay_keep.xml b/assets/xml/objects/gameplay_keep.xml index bb3f966706..79940f1cb4 100644 --- a/assets/xml/objects/gameplay_keep.xml +++ b/assets/xml/objects/gameplay_keep.xml @@ -922,9 +922,9 @@ - - - + + + @@ -937,13 +937,13 @@ - - - - + + + + - - + + diff --git a/include/z64actor.h b/include/z64actor.h index fee3ffbd0f..96ffec9ef4 100644 --- a/include/z64actor.h +++ b/include/z64actor.h @@ -463,7 +463,7 @@ typedef enum ActorId { #undef DEFINE_ACTOR_INTERNAL #undef DEFINE_ACTOR_UNSET -typedef enum { +typedef enum DoorLockType { /* 0 */ DOORLOCK_NORMAL, /* 1 */ DOORLOCK_BOSS, /* 2 */ DOORLOCK_2, // DOORLOCK_NORMAL_SPIRIT on OoT diff --git a/include/z64door.h b/include/z64door.h index 93dff5ea95..7e91905c27 100644 --- a/include/z64door.h +++ b/include/z64door.h @@ -7,8 +7,8 @@ typedef struct KnobDoorActor { /* 0x000 */ DynaPolyActor dyna; /* 0x15C */ SkelAnime skelAnime; - /* 0x1A0 */ u8 animIndex; - /* 0x1A1 */ u8 playOpenAnim; + /* 0x1A0 */ u8 animIndex; // Value between 0 ~ 9. 0 ~ 4 are for left doors while 5 ~ 9 are for right doors. Each value maps to a PlayerTransformation + /* 0x1A1 */ u8 requestOpen; // An actor can set this member to `true` to request this door to open. It must also set `animIndex` /* 0x1A2 */ s8 objectSlot; /* 0x1A3 */ s8 dlIndex; } KnobDoorActor; // size = 0x1A4 @@ -19,6 +19,9 @@ typedef struct SlidingDoorActor { /* 0x15E */ s16 unk_15E; } SlidingDoorActor; // size = 0x160 -#define DOOR_GET_TRANSITION_ID(thisx) ((u16)(thisx)->params >> 10) +#define TRANSITION_ACTOR_PARAMS_INDEX_SHIFT 10 +#define TRANSITION_ACTOR_PARAMS(index, params) ((index) << TRANSITION_ACTOR_PARAMS_INDEX_SHIFT) + ((params) & 0x3FF) + +#define DOOR_GET_TRANSITION_ID(thisx) ((u16)(thisx)->params >> TRANSITION_ACTOR_PARAMS_INDEX_SHIFT) #endif diff --git a/include/z64subs.h b/include/z64subs.h index a6873ff976..91b44ee9f1 100644 --- a/include/z64subs.h +++ b/include/z64subs.h @@ -97,7 +97,7 @@ typedef struct ActorPathing { /* 0x68 */ ActorPathingUpdateFunc setNextPointFunc; // Return true if should compute and update again } ActorPathing; // size = 0x6C -struct EnDoor* SubS_FindDoor(struct PlayState* play, s32 switchFlag); +struct EnDoor* SubS_FindScheduleDoor(struct PlayState* play, s32 schType); Gfx* SubS_DrawTransformFlexLimb(struct PlayState* play, s32 limbIndex, void** skeleton, Vec3s* jointTable, OverrideLimbDraw overrideLimbDraw, PostLimbDraw postLimbDraw, TransformLimbDraw transformLimbDraw, Actor* actor, Mtx** mtx, Gfx* gfx); Gfx* SubS_DrawTransformFlex(struct PlayState* play, void** skeleton, Vec3s* jointTable, s32 dListCount, OverrideLimbDraw overrideLimbDraw, PostLimbDraw postLimbDraw, TransformLimbDraw transformLimbDraw, Actor* actor, Gfx* gfx); diff --git a/include/z64view.h b/include/z64view.h index 92375e1589..b5474147f8 100644 --- a/include/z64view.h +++ b/include/z64view.h @@ -95,7 +95,7 @@ s32 View_InitDistortion(View* view); s32 View_ClearDistortion(View* view); s32 View_SetDistortion(View* view, Vec3f orientation, Vec3f scale, f32 speed); -void View_Apply(View* view, s32 mask); +s32 View_Apply(View* view, s32 mask); s32 View_ApplyOrthoToOverlay(View* view); s32 View_ApplyPerspectiveToOverlay(View* view); s32 View_UpdateViewingMatrix(View* view); diff --git a/src/code/z_actor.c b/src/code/z_actor.c index 2cf96f760f..845215c5e2 100644 --- a/src/code/z_actor.c +++ b/src/code/z_actor.c @@ -30,6 +30,7 @@ struct Actor* D_801ED920; // 2 funcs. 1 out of z_actor #include "z64actor.h" +#include "z64door.h" #include "z64circle_tex.h" #include "z64horse.h" #include "z64malloc.h" @@ -3428,7 +3429,7 @@ void Actor_SpawnTransitionActors(PlayState* play, ActorContext* actorCtx) { if (Actor_SpawnAsChildAndCutscene(actorCtx, play, transitionActorList->id & 0x1FFF, transitionActorList->pos.x, transitionActorList->pos.y, transitionActorList->pos.z, 0, rotY, 0, - (i << 0xA) + (transitionActorList->params & 0x3FF), + TRANSITION_ACTOR_PARAMS(i, transitionActorList->params), transitionActorList->rotY & 0x7F, HALFDAYBIT_ALL, 0) != NULL) { transitionActorList->id = -transitionActorList->id; } diff --git a/src/code/z_en_hy_code.c b/src/code/z_en_hy_code.c index cee1d9466d..d1653bb447 100644 --- a/src/code/z_en_hy_code.c +++ b/src/code/z_en_hy_code.c @@ -191,7 +191,7 @@ void func_800F0BB4(EnHy* enHy, PlayState* play, EnDoor* door, s16 arg3, s16 arg4 enHy->skelAnime.prevTransl = enHy->skelAnime.jointTable[LIMB_ROOT_POS]; enHy->skelAnime.moveFlags |= (ANIM_FLAG_UPDATE_Y | ANIM_FLAG_1); AnimationContext_SetMoveActor(play, &enHy->actor, &enHy->skelAnime, 1.0f); - door->knobDoor.playOpenAnim = true; + door->knobDoor.requestOpen = true; door->knobDoor.animIndex = animIndex; } diff --git a/src/code/z_scene.c b/src/code/z_scene.c index a7f274a522..acfc182e59 100644 --- a/src/code/z_scene.c +++ b/src/code/z_scene.c @@ -108,7 +108,7 @@ s32 Object_GetSlot(ObjectContext* objectCtx, s16 objectId) { } } - return -1; + return OBJECT_SLOT_NONE; } s32 Object_IsLoaded(ObjectContext* objectCtx, s32 slot) { diff --git a/src/code/z_sub_s.c b/src/code/z_sub_s.c index 7117e1da21..11f97c7d0f 100644 --- a/src/code/z_sub_s.c +++ b/src/code/z_sub_s.c @@ -15,9 +15,10 @@ Vec3f gOneVec3f = { 1.0f, 1.0f, 1.0f }; s32 D_801C5DBC[] = { 0, 1 }; // Unused /** - * Finds the first EnDoor instance with doorType == ENDOOR_TYPE_5 and the specified switchFlag. + * Finds the first EnDoor instance of type `ENDOOR_TYPE_SCHEDULE` and the specified schType (a value from the + * EnDoorScheduleType enum). */ -EnDoor* SubS_FindDoor(PlayState* play, s32 switchFlag) { +EnDoor* SubS_FindScheduleDoor(PlayState* play, s32 schType) { Actor* actor = NULL; EnDoor* door; @@ -29,7 +30,7 @@ EnDoor* SubS_FindDoor(PlayState* play, s32 switchFlag) { break; } - if ((door->doorType == ENDOOR_TYPE_5) && (door->switchFlag == (u8)switchFlag)) { + if ((door->doorType == ENDOOR_TYPE_SCHEDULE) && (door->typeVar.schType == (u8)schType)) { break; } diff --git a/src/code/z_view.c b/src/code/z_view.c index 4adc00b8d0..56af72134e 100644 --- a/src/code/z_view.c +++ b/src/code/z_view.c @@ -299,13 +299,13 @@ s32 View_StepDistortion(View* view, Mtx* projectionMtx) { /** * Apply view to POLY_OPA_DISP, POLY_XLU_DISP (and OVERLAY_DISP if ortho) */ -void View_Apply(View* view, s32 mask) { +s32 View_Apply(View* view, s32 mask) { mask = (view->flags & mask) | (mask >> 4); if (mask & VIEW_PROJECTION_ORTHO) { - View_ApplyOrtho(view); + return View_ApplyOrtho(view); } else { - View_ApplyPerspective(view); + return View_ApplyPerspective(view); } } diff --git a/src/overlays/actors/ovl_En_An/z_en_an.c b/src/overlays/actors/ovl_En_An/z_en_an.c index a5e9d878f9..5a53eb19ac 100644 --- a/src/overlays/actors/ovl_En_An/z_en_an.c +++ b/src/overlays/actors/ovl_En_An/z_en_an.c @@ -71,7 +71,7 @@ typedef enum AnjuScheduleResult { /* 20 */ ANJU_SCH_20, // 12:00 ~ 12:15, Day 1 and Day 2 (if did had the Midnight meeting). Give lunch to Granny /* 21 */ ANJU_SCH_GIVE_LUNCH_TO_GRANNY, - // Day 3, 06:00 ~ 11:00. Sweeping the Suite room. TODO: maybe rename to "cleaning Suite room"? + // Day 3, 06:00 ~ 11:00. Sweeping the Large Suite. /* 22 */ ANJU_SCH_SWEEPING, // Day 1, 00:00 ~ 06:00. Waiting for player at the kitchen to have the Midnight meeting. /* 23 */ ANJU_SCH_MIDNIGHT_MEETING, @@ -444,24 +444,24 @@ Actor* func_80B53A7C(EnAn* this, PlayState* play, u8 actorCategory, s16 actorId) return actorIter; } -EnDoor* EnAn_FindDoor(PlayState* play, AnjuScheduleResult scheduleOutputResult) { - s32 switchFlag; +EnDoor* EnAn_FindScheduleDoor(PlayState* play, AnjuScheduleResult scheduleOutputResult) { + EnDoorScheduleType schType; switch (scheduleOutputResult) { case ANJU_SCH_DOOR_26: case ANJU_SCH_DOOR_27: - switchFlag = 0xD; + schType = ENDOOR_SCH_TYPE_INN_GRANNYS; break; case ANJU_SCH_DOOR_33: case ANJU_SCH_DOOR_34: case ANJU_SCH_DOOR_37: case ANJU_SCH_DOOR_38: - switchFlag = 0xB; + schType = ENDOOR_SCH_TYPE_INN_MAIN_ENTRANCE; break; case ANJU_SCH_DOOR_36: - switchFlag = 0x10; + schType = ENDOOR_SCH_TYPE_INN_LARGE_SUITE; break; case ANJU_SCH_DOOR_28: @@ -471,14 +471,14 @@ EnDoor* EnAn_FindDoor(PlayState* play, AnjuScheduleResult scheduleOutputResult) case ANJU_SCH_DOOR_32: case ANJU_SCH_DOOR_35: case ANJU_SCH_DOOR_39: - switchFlag = 0xE; + schType = ENDOOR_SCH_TYPE_INN_STAFF_ROOM; break; default: return NULL; } - return SubS_FindDoor(play, switchFlag); + return SubS_FindScheduleDoor(play, schType); } /** @@ -1933,7 +1933,7 @@ s32 EnAn_ProcessSchedule_Door(EnAn* this, PlayState* play, ScheduleOutput* sched s32 ret = false; this->timePath = NULL; - door = EnAn_FindDoor(play, scheduleOutput->result); + door = EnAn_FindScheduleDoor(play, scheduleOutput->result); limit = sSearchTimePathLimit[scheduleOutput->result]; if (limit >= 0) { @@ -2437,7 +2437,7 @@ s32 EnAn_HandleSch_InteractActor(EnAn* this, PlayState* play) { } s32 EnAn_HandleSch_Door(EnAn* this, PlayState* play) { - EnDoor* door = EnAn_FindDoor(play, this->scheduleResult); + EnDoor* door = EnAn_FindScheduleDoor(play, this->scheduleResult); Vec3f sp38; f32 distance; s32 pad; diff --git a/src/overlays/actors/ovl_En_Door/scheduleScripts.schl b/src/overlays/actors/ovl_En_Door/scheduleScripts.schl index 7f6c2ea081..ab52716182 100644 --- a/src/overlays/actors/ovl_En_Door/scheduleScripts.schl +++ b/src/overlays/actors/ovl_En_Door/scheduleScripts.schl @@ -1,231 +1,310 @@ -D_808675D0 { +/** + * Schedules for EnDoor + * + * EnDoor uses the schedule system to determine if it should be open or closed + * (and prompt a message) when the Player tries to open it. + * + * If a schedule returns `none` it means the door should be openable by Player. + * A non-`none` value means the door should be closed and prompt a message. + * Which message is used is determined by using the returned value from the + * schedule as an offset into text id 0x1800. + */ + +// Swordsman's School +sDoorSch_SwordsmansSchool { + // The Swordsman's School is closed between 23:00 ~ 00:00 and says + // the teacher is "focusing his spirit" if_day (3) { not if_time_range (6, 0, 23, 0) { not if_time_range (0, 0, 6, 0) { - return_s (7) + return_s (0x7) } } } return_none } -D_808675E4 { +// Post Office +sDoorSch_PostOffice { if_before_time (9, 0) { - return_s (9) + // Closed between 00:00 ~ 09:00 + return_s (0x9) } else if_before_time (12, 0) { - branch (label_0x1D) + // Delivering mail between 09:00 ~ 12:00 + branch (delivering_mail_msg) } else { if_day (1) { branch (label_0x0E) label_0x0E: if_before_time (13, 0) { - branch (label_0x1C) + // Open between 12:00 ~ 13:00 + branch (open_post_office) } else if_before_time (15, 0) { - branch (label_0x1D) - } else if_before_time (0, 0) { - branch (label_0x1C) - } else { - return_s (9) + // Delivering mail between 13:00 ~ 15:00 + branch (delivering_mail_msg) + } else if_since_time (0, 0) { + // Closed between 00:00 ~ 09:00 + return_s (0x9) } + // Open between 15:00 ~ 00:00 - label_0x1C: + open_post_office: return_none - label_0x1D: - return_s (8) + delivering_mail_msg: + // "Out delivering mail" + return_s (0x8) } else if_day (2) { if_week_event_reg (WEEKEVENTREG_28_08) { + // Related to letter to Kafei + if_before_time (13, 0) { - branch (label_0x1C) + // Open between 12:00 ~ 13:00 + branch (open_post_office) } else if_before_time (17, 0) { - branch (label_0x1D) - } else if_before_time (0, 0) { - branch (label_0x1C) + // Delivering mail between 13:00 ~ 17:00 + branch (delivering_mail_msg) + } else if_since_time (0, 0) { + // Closed between 00:00 ~ 09:00 + return_s (0x9) } else { - return_s (9) + // Open between 15:00 ~ 00:00 + branch (open_post_office) } - } else if_since_time (13, 0) { - return_s (9) } else { + if_since_time (13, 0) { + //! @bug The in-game message expliclty says the office should be open up to 15:00 (3 p.m.) + //! Maybe it was a typo between 3 (p.m.) and 13? + // Closed between 13:00 ~ 09:00 + return_s (0x9) + } else { + // Open between 12:00 ~ 13:00 + return_none + } + } + } else { // day 3 + if_before_time (13, 0) { + // Open between 12:00 ~ 13:00 + branch (open_post_office) + } else if_before_time (13, 0) { + //! @bug? unreachable code + branch (delivering_mail_msg) + } else if_before_time (18, 0) { + // Closed between 13:00 ~ 18:00 + return_s (0x9) + } else { + // Open since 18:00 return_none } - } else if_before_time (13, 0) { - branch (label_0x1C) - } else if_before_time (13, 0) { - branch (label_0x1D) - } else if_before_time (18, 0) { - return_s (9) - } else { - return_none } } } -D_80867634 { +// Lottery Shop +sDoorSch_LotteryShop { + // Open between 06:00 ~ 23:00 if_time_range (6, 0, 23, 0) { return_none } else { - return_s (28) + return_s (0x1C) } } -D_80867640 { +// Trading Post +sDoorSch_TradingPost { if_time_range (21, 0, 22, 0) { - return_s (11) + return_s (0xB) } else { return_none } } -D_8086764C { +// Curiosity Shop +sDoorSch_CuriosityShop { not if_time_range (22, 0, 5, 0) { - return_s (10) + return_s (0xA) } else { return_none } } -D_80867658 { +// Laundry Pool +sDoorSch_LaundryPool { if_day (2) { not if_week_event_reg (WEEKEVENTREG_28_08) { - return_s (12) + return_s (0xC) } else if_time_range (15, 10, 22, 0) { return_none } else { - return_s (12) + return_s (0xC) } } if_day (3) { if_since_time (13, 0) { not if_week_event_reg (WEEKEVENTREG_51_08) { - return_s (12) + return_s (0xC) } else if_since_time (22, 0) { - return_s (12) + return_s (0xC) } else { return_none } } } - return_s (12) + + // Day 1 + return_s (0xC) } -D_80867684 { +// Bomb Shop +sDoorSch_BombShop { return_none } -D_80867688 { +// Town Shooting Gallery +sDoorSch_TownShootingGallery { if_since_time (22, 0) { - return_s (15) + return_s (0xF) } else { return_none } } -D_80867690 { +// Treasure Chest Shop +sDoorSch_TreasureChestShop { if_since_time (22, 0) { - return_s (16) + return_s (0x10) } else { return_none } } -D_80867698 { +// Honey & Darling's Shop +sDoorSch_HoneyDarlingShop { if_since_time (22, 0) { - return_s (17) + return_s (0x11) } else { return_none } } -D_808676A0 { +// Milk Bar +sDoorSch_MilkBar { if_time_range (10, 0, 21, 0) { + // Open without requirements between 10:00 ~ 21:00 return_none } else if_time_range (22, 0, 5, 0) { if_misc (SCHEDULE_CHECK_MISC_MASK_ROMANI) { - return_s (33) + // Player is a member of the Milk bar and can enter + return_s (0x21) } else { - return_s (34) + // "Show you are a member" + return_s (0x22) } } else { - return_s (18) + // Closed between 21:00 ~ 22:00 and 05:00 ~ 10:00 + + // Message saying when the Bar opens + return_s (0x12) } } -D_808676B8 { +// Stock Pot Inn: Main door +sDoorSch_InnMainEntrance { not if_misc (SCHEDULE_CHECK_MISC_ROOM_KEY) { if_day (3) { + // Door is unlocked at night 3 + if_before_time (8, 0) { - return_s (19) + return_s (0x13) } else { return_none } - } else if_time_range (8, 0, 20, 30) { - return_none } else { - return_s (19) + not if_time_range (8, 0, 20, 30) { + return_s (0x13) + } else { + return_none + } } } else { + // If player has the Room Key then they can enter the Inn at any time return_none } } -D_808676D0 { +// Stock Pot Inn: Entrance at the second floor +sDoorSch_InnUpperEntrance { return_none } -D_808676D4 { +// Stock Pot Inn: Granny's door +sDoorSch_InnGrannys { return_none } -D_808676D8 { +// Stock Pot Inn: Staff room door +sDoorSch_InnStaffRoom { + // It is open at night 3 + if_day (3) { if_since_time (18, 0) { return_none } } - return_s (20) + + // "Only employees can enter" + return_s (0x14) } -D_808676E4 { +// Stock Pot Inn: Knife Chamber door +sDoorSch_InnKnifeChamber { not if_misc (SCHEDULE_CHECK_MISC_ROOM_KEY) { - return_s (22) + return_s (0x16) } else { return_none } } -D_808676EC { +// Stock Pot Inn: Large Suite door +sDoorSch_InnLargeSuite { return_none } -D_808676F0 { +// The Mayor's Residence: Main entrance +sDoorSch_MayorsResidenceMainEntrance { + // Day 1 and 2: Open between 10:00 ~ 20:00 + // Day 3: Open since 10:00 + if_day (3) { if_since_time (10, 0) { - label_0x8: + open_residence: return_none } else { - branch (label_0xF) + branch (closed_residence) } } else { if_time_range (10, 0, 20, 0) { - branch (label_0x8) + branch (open_residence) } else { - label_0xF: - return_s (21) + closed_residence: + return_s (0x15) } } } -D_80867704 { +// The Mayor's Residence: Mayor Dotour +sDoorSch_MayorsResidenceMayorDotour { return_none } -D_80867708 { +// The Mayor's Residence: Madame Aroma +sDoorSch_MayorsResidenceMadameAroma { return_none } -D_8086770C { +// The Mayor's Residence: Bedroom +sDoorSch_MayorsResidenceBedroom { return_none } @@ -233,50 +312,70 @@ D_80867710 { return_none } -D_80867714 { +// Romani Ranch: Mama's House +sDoorSch_RomaniRanchMamasHouse { if_since_time (20, 0) { - return_s (23) + return_s (0x17) } else { return_none } } -D_8086771C { +// Romani Ranch: Barn +sDoorSch_RomaniRanchBarn { if_day (1) { if_since_time (2, 30) { - return_s (24) + // Cremia is in the Barn during the Alien invasion + + // "locked from inside" message + return_s (0x18) } else { - label_0x0A: + open_barn: return_none } } else if_day (3) { if_since_time (20, 0) { - return_s (12) + // Cremia and Romani left the Barn locked on night 3. + // Them leaving the Barn at night 3 only happens if the + // aliens were defeated on night 1, so if player did not + // do that then the door would be mysteriously locked + + // "locked door" message + return_s (0xC) } else { - branch (label_0x0A) + branch (open_barn) } - } else { - branch (label_0x0A) + } else { // day 2 + branch (open_barn) } } -D_80867734 { +// Romani Ranch: Cucco Shack +sDoorSch_RomaniRanchCuccoShack { + // Closed between 20:00 ~ 06:00 if_since_time (20, 0) { - return_s (25) + return_s (0x19) } else { return_none } } -D_8086773C { +// Romani Ranch: Doggy Racetrack +sDoorSch_RomaniRanchDoggyRacetrack { + // Closed between 20:00 ~ 06:00 if_since_time (20, 0) { - return_s (26) + return_s (0x1A) } else { return_none } } -D_80867744 { +// Romani Ranch: Bedroom +sDoorSch_RomaniRanchBedroom { + //! @bug? All the codepaths that lead to a non none return are unreachable + //! in the base game, since nothing sets WEEKEVENTREG_99_80 and the player + //! is kicked out at 20:00 + not if_day (2) { branch (label_0x08) } else { @@ -287,7 +386,7 @@ D_80867744 { if_before_time (20, 0) { branch (label_0x14) } else { - return_s (27) + return_s (0x1B) } } } @@ -296,23 +395,24 @@ D_80867744 { if_before_time (18, 0) { branch (label_0x14) } else { - return_s (27) + return_s (0x1B) } label_0x14: return_none } -D_8086775C { +// Ikana Canyom: Music Box House +sDoorSch_IkanaCanyonMusicBoxHouse { not if_week_event_reg (WEEKEVENTREG_CLEARED_STONE_TOWER_TEMPLE) { not if_week_event_reg (WEEKEVENTREG_75_20) { not if_week_event_reg (WEEKEVENTREG_14_04) { - return_s (29) + return_s (0x1D) } else not if_week_event_reg (WEEKEVENTREG_59_01) { if_week_event_reg (WEEKEVENTREG_61_02) { - return_s (31) + return_s (0x1F) } else { - return_s (30) + return_s (0x1E) } } else { return_none @@ -323,11 +423,13 @@ D_8086775C { return_none } -D_80867778 { - return_s (32) +// Ikana Graveyard: Dampé's House +sDoorSch_DampesHouse { + return_s (0x20) } -D_8086777C{ +// Magic Hags' Potion Shop +sDoorSch_MagicHagsPotionShop{ return_none } @@ -335,9 +437,10 @@ D_80867780 { return_none } -D_80867784 { +// Swamp Shooting Gallery +sDoorSch_SwampShootingGallery { if_since_time (22, 0) { - return_s (35) + return_s (0x23) } else { return_none } diff --git a/src/overlays/actors/ovl_En_Door/z_en_door.c b/src/overlays/actors/ovl_En_Door/z_en_door.c index 75c6249d86..b395d6e59e 100644 --- a/src/overlays/actors/ovl_En_Door/z_en_door.c +++ b/src/overlays/actors/ovl_En_Door/z_en_door.c @@ -5,6 +5,9 @@ */ #include "z_en_door.h" + +#include "libc/assert.h" + #include "objects/object_kinsta2_obj/object_kinsta2_obj.h" #include "objects/object_dor01/object_dor01.h" #include "objects/object_dor02/object_dor02.h" @@ -21,6 +24,9 @@ #define FLAGS (ACTOR_FLAG_10) +#define DOOR_AJAR_SLAM_RANGE 120.0f +#define DOOR_AJAR_OPEN_RANGE (2 * DOOR_AJAR_SLAM_RANGE) + #define THIS ((EnDoor*)thisx) void EnDoor_Init(Actor* thisx, PlayState* play2); @@ -28,22 +34,56 @@ void EnDoor_Destroy(Actor* thisx, PlayState* play); void EnDoor_Update(Actor* thisx, PlayState* play); void EnDoor_Draw(Actor* thisx, PlayState* play); -void func_80866B20(EnDoor* this, PlayState* play); -void func_8086704C(EnDoor* this, PlayState* play); -void func_80866F94(EnDoor* this, PlayState* play); -void func_80867080(EnDoor* this, PlayState* play); -void func_80867144(EnDoor* this, PlayState* play); -void func_808670F0(EnDoor* this, PlayState* play); -void func_80866A5C(EnDoor* this, PlayState* play); +void EnDoor_Idle(EnDoor* this, PlayState* play); +void EnDoor_AjarWait(EnDoor* this, PlayState* play); +void EnDoor_OpenScheduleActor(EnDoor* this, PlayState* play); +void EnDoor_AjarOpen(EnDoor* this, PlayState* play); +void EnDoor_Open(EnDoor* this, PlayState* play); +void EnDoor_AjarClose(EnDoor* this, PlayState* play); +void EnDoor_WaitForObject(EnDoor* this, PlayState* play); #include "src/overlays/actors/ovl_En_Door/scheduleScripts.schl.inc" -ScheduleScript* D_8086778C[] = { - D_808675D0, D_808675E4, D_80867634, D_80867640, D_8086764C, D_80867658, D_80867684, D_80867688, - D_80867690, D_80867698, D_808676A0, D_808676B8, D_808676D0, D_808676D4, D_808676D8, D_808676E4, - D_808676EC, D_808676F0, D_80867704, D_80867708, D_8086770C, D_80867710, D_80867714, D_8086771C, - D_80867734, D_8086773C, D_80867744, D_8086775C, D_80867778, D_8086777C, D_80867780, D_80867784, +/** + * A schedule returning none means the door can be used normally. + * Otherwise the result will be used as an offset relative to text message 0x1800 + */ +ScheduleScript* sDoorSchedules[] = { + sDoorSch_SwordsmansSchool, // ENDOOR_SCH_TYPE_SWORDSMANS_SCHOOL + sDoorSch_PostOffice, // ENDOOR_SCH_TYPE_POST_OFFICE + sDoorSch_LotteryShop, // ENDOOR_SCH_TYPE_LOTTERY_SHOP + sDoorSch_TradingPost, // ENDOOR_SCH_TYPE_TRADING_POST + sDoorSch_CuriosityShop, // ENDOOR_SCH_TYPE_CURIOSITY_SHOP + sDoorSch_LaundryPool, // ENDOOR_SCH_TYPE_LAUNDRY_POOL + sDoorSch_BombShop, // ENDOOR_SCH_TYPE_BOMB_SHOP + sDoorSch_TownShootingGallery, // ENDOOR_SCH_TYPE_TOWN_SHOOTING_GALLERY + sDoorSch_TreasureChestShop, // ENDOOR_SCH_TYPE_TREASURE_CHEST_SHOP + sDoorSch_HoneyDarlingShop, // ENDOOR_SCH_TYPE_HONEY_DARLING_SHOP + sDoorSch_MilkBar, // ENDOOR_SCH_TYPE_MILK_BAR + sDoorSch_InnMainEntrance, // ENDOOR_SCH_TYPE_INN_MAIN_ENTRANCE + sDoorSch_InnUpperEntrance, // ENDOOR_SCH_TYPE_INN_UPPER_ENTRANCE + sDoorSch_InnGrannys, // ENDOOR_SCH_TYPE_INN_GRANNYS + sDoorSch_InnStaffRoom, // ENDOOR_SCH_TYPE_INN_STAFF_ROOM + sDoorSch_InnKnifeChamber, // ENDOOR_SCH_TYPE_INN_KNIFE_CHAMBER + sDoorSch_InnLargeSuite, // ENDOOR_SCH_TYPE_INN_LARGE_SUITE + sDoorSch_MayorsResidenceMainEntrance, // ENDOOR_SCH_TYPE_MAYORS_RESIDENCE_MAIN_ENTRANCE + sDoorSch_MayorsResidenceMayorDotour, // ENDOOR_SCH_TYPE_MAYORS_RESIDENCE_MAYOR_DOTOUR + sDoorSch_MayorsResidenceMadameAroma, // ENDOOR_SCH_TYPE_MAYORS_RESIDENCE_MADAME_AROMA + sDoorSch_MayorsResidenceBedroom, // ENDOOR_SCH_TYPE_MAYORS_RESIDENCE_BEDROOM + D_80867710, // ENDOOR_SCH_TYPE_21 + sDoorSch_RomaniRanchMamasHouse, // ENDOOR_SCH_TYPE_ROMANI_RANCH_MAMAS_HOUSE + sDoorSch_RomaniRanchBarn, // ENDOOR_SCH_TYPE_ROMANI_RANCH_BARN + sDoorSch_RomaniRanchCuccoShack, // ENDOOR_SCH_TYPE_ROMANI_RANCH_CUCCO_SHACK + sDoorSch_RomaniRanchDoggyRacetrack, // ENDOOR_SCH_TYPE_ROMANI_RANCH_DOGGY_RACETRACK + sDoorSch_RomaniRanchBedroom, // ENDOOR_SCH_TYPE_ROMANI_RANCH_BEDROOM + sDoorSch_IkanaCanyonMusicBoxHouse, // ENDOOR_SCH_TYPE_IKANA_CANYON_MUSIC_BOX_HOUSE + sDoorSch_DampesHouse, // ENDOOR_SCH_TYPE_DAMPES_HOUSE + sDoorSch_MagicHagsPotionShop, // ENDOOR_SCH_TYPE_MAGIC_HAGS_POTION_SHOP + D_80867780, // ENDOOR_SCH_TYPE_30 + sDoorSch_SwampShootingGallery, // ENDOOR_SCH_TYPE_SWAMP_SHOOTING_GALLERY }; +static_assert(ARRAY_COUNT(sDoorSchedules) == ENDOOR_SCH_TYPE_MAX, + "The entry count of `sDoorSchedules` should match the `EnDoorScheduleType` enum"); ActorInit En_Door_InitVars = { /**/ ACTOR_EN_DOOR, @@ -57,63 +97,155 @@ ActorInit En_Door_InitVars = { /**/ EnDoor_Draw, }; -typedef struct { +typedef enum EnDoorDListIndex { + /* 0 */ DOOR_DL_DEFAULT, + /* 1 */ DOOR_DL_WOODFALL, + /* 2 */ DOOR_DL_OBSERVATORY_LAB, + /* 3 */ DOOR_DL_ZORA_HALL, + /* 4 */ DOOR_DL_SWAMP, + /* 5 */ DOOR_DL_MAGIC_HAG_POTION_SHOP, + /* 6 */ DOOR_DL_LOTTERY_CURIOSITY_SHIP_MAYOR_HOUSE, + /* 7 */ DOOR_DL_POST_OFFICE_TRAIDING_POST, + /* 8 */ DOOR_DL_INN_SCHOOL, + /* 9 */ DOOR_DL_MILK_BAR, + /* 10 */ DOOR_DL_MUSIC_BOX, + /* 11 */ DOOR_DL_PIRATES_FORTESS, + /* 12 */ DOOR_DL_OCEANSIDE_SPIDER_HOUSE, + /* 13 */ DOOR_DL_DEFAULT_FIELD_KEEP, + /* 14 */ DOOR_DL_MAX +} EnDoorDListIndex; + +typedef struct EnDoorInfo { /* 0x0 */ s16 sceneId; /* 0x2 */ u8 dListIndex; /* 0x4 */ s16 objectId; } EnDoorInfo; // size = 0x6 +// TODO: This enum feels kinda overkill... +typedef enum EnDoorObjectInfoIndex { + /* 0 */ DOOR_OBJKIND_DEFAULT, + /* 0 */ DOOR_OBJINFO_0 = DOOR_OBJKIND_DEFAULT, + /* 1 */ DOOR_OBJINFO_1, + /* 2 */ DOOR_OBJINFO_2, + /* 3 */ DOOR_OBJINFO_3, + /* 4 */ DOOR_OBJINFO_4, + /* 5 */ DOOR_OBJINFO_5, + /* 6 */ DOOR_OBJINFO_6, + /* 7 */ DOOR_OBJINFO_7, + /* 8 */ DOOR_OBJINFO_8, + /* 9 */ DOOR_OBJINFO_9, + /* 10 */ DOOR_OBJINFO_10, + /* 11 */ DOOR_OBJINFO_11, + /* 12 */ DOOR_OBJINFO_12, + /* 13 */ DOOR_OBJINFO_13, + /* 14 */ DOOR_OBJINFO_14, + + /* 15 */ DOOR_OBJKIND_KEEP, + /* 15 */ DOOR_OBJINFO_15 = DOOR_OBJKIND_KEEP, + /* 16 */ DOOR_OBJINFO_16, + + /* 17 */ DOOR_OBJKIND_SCHEDULE, + /* 17 */ DOOR_OBJINFO_17 = DOOR_OBJKIND_SCHEDULE, // ENDOOR_SCH_TYPE_SWORDSMANS_SCHOOL + /* 18 */ DOOR_OBJINFO_18, // ENDOOR_SCH_TYPE_POST_OFFICE + /* 19 */ DOOR_OBJINFO_19, // ENDOOR_SCH_TYPE_LOTTERY_SHOP + /* 20 */ DOOR_OBJINFO_20, // ENDOOR_SCH_TYPE_TRADING_POST + /* 21 */ DOOR_OBJINFO_21, // ENDOOR_SCH_TYPE_CURIOSITY_SHOP + /* 22 */ DOOR_OBJINFO_22, // ENDOOR_SCH_TYPE_LAUNDRY_POOL + /* 23 */ DOOR_OBJINFO_23, // ENDOOR_SCH_TYPE_BOMB_SHOP + /* 24 */ DOOR_OBJINFO_24, // ENDOOR_SCH_TYPE_TOWN_SHOOTING_GALLERY + /* 25 */ DOOR_OBJINFO_25, // ENDOOR_SCH_TYPE_TREASURE_CHEST_SHOP + /* 26 */ DOOR_OBJINFO_26, // ENDOOR_SCH_TYPE_HONEY_DARLING_SHOP + /* 27 */ DOOR_OBJINFO_27, // ENDOOR_SCH_TYPE_MILK_BAR + /* 28 */ DOOR_OBJINFO_28, // ENDOOR_SCH_TYPE_INN_MAIN_ENTRANCE + /* 29 */ DOOR_OBJINFO_29, // ENDOOR_SCH_TYPE_INN_UPPER_ENTRANCE + /* 30 */ DOOR_OBJINFO_30, // ENDOOR_SCH_TYPE_INN_GRANNYS + /* 31 */ DOOR_OBJINFO_31, // ENDOOR_SCH_TYPE_INN_STAFF_ROOM + /* 32 */ DOOR_OBJINFO_32, // ENDOOR_SCH_TYPE_INN_KNIFE_CHAMBER + /* 33 */ DOOR_OBJINFO_33, // ENDOOR_SCH_TYPE_INN_LARGE_SUITE + /* 34 */ DOOR_OBJINFO_34, // ENDOOR_SCH_TYPE_MAYORS_RESIDENCE_MAIN_ENTRANCE + /* 35 */ DOOR_OBJINFO_35, // ENDOOR_SCH_TYPE_MAYORS_RESIDENCE_MAYOR_DOTOUR + /* 36 */ DOOR_OBJINFO_36, // ENDOOR_SCH_TYPE_MAYORS_RESIDENCE_MADAME_AROMA + /* 37 */ DOOR_OBJINFO_37, // ENDOOR_SCH_TYPE_MAYORS_RESIDENCE_BEDROOM + /* 38 */ DOOR_OBJINFO_38, // ENDOOR_SCH_TYPE_21 + /* 39 */ DOOR_OBJINFO_39, // ENDOOR_SCH_TYPE_ROMANI_RANCH_MAMAS_HOUSE + /* 40 */ DOOR_OBJINFO_40, // ENDOOR_SCH_TYPE_ROMANI_RANCH_BARN + /* 41 */ DOOR_OBJINFO_41, // ENDOOR_SCH_TYPE_ROMANI_RANCH_CUCCO_SHACK + /* 42 */ DOOR_OBJINFO_42, // ENDOOR_SCH_TYPE_ROMANI_RANCH_DOGGY_RACETRACK + /* 43 */ DOOR_OBJINFO_43, // ENDOOR_SCH_TYPE_ROMANI_RANCH_BEDROOM + /* 44 */ DOOR_OBJINFO_44, // ENDOOR_SCH_TYPE_IKANA_CANYON_MUSIC_BOX_HOUSE + /* 45 */ DOOR_OBJINFO_45, // ENDOOR_SCH_TYPE_DAMPES_HOUSE + /* 46 */ DOOR_OBJINFO_46, // ENDOOR_SCH_TYPE_MAGIC_HAGS_POTION_SHOP + /* 47 */ DOOR_OBJINFO_47, // ENDOOR_SCH_TYPE_30 + /* 48 */ DOOR_OBJINFO_48, // ENDOOR_SCH_TYPE_SWAMP_SHOOTING_GALLERY + /* 49 */ DOOR_OBJINFO_MAX +} EnDoorObjectInfoIndex; + +// These static asserts try to ensure the two enums don't get out of sync +static_assert(ENDOOR_SCH_TYPE_SWORDSMANS_SCHOOL == DOOR_OBJINFO_17 - DOOR_OBJKIND_SCHEDULE, + "The enums values of `EnDoorScheduleType` and `EnDoorObjectInfoIndex` (from `DOOR_OBJKIND_SCHEDULE` " + "onwards) must be synced."); +static_assert(ENDOOR_SCH_TYPE_MAX == DOOR_OBJINFO_MAX - DOOR_OBJKIND_SCHEDULE, + "The enums values of `EnDoorScheduleType` and `EnDoorObjectInfoIndex` (from `DOOR_OBJKIND_SCHEDULE` " + "onwards) must be synced."); + static EnDoorInfo sObjectInfo[] = { - { SCENE_MITURIN, 0x01, OBJECT_NUMA_OBJ }, - { SCENE_TENMON_DAI, 0x02, OBJECT_DOR01 }, - { SCENE_00KEIKOKU, 0x02, OBJECT_DOR01 }, - { SCENE_30GYOSON, 0x02, OBJECT_DOR01 }, - { SCENE_LABO, 0x02, OBJECT_DOR01 }, - { SCENE_33ZORACITY, 0x03, OBJECT_DOR02 }, - { SCENE_UNSET_31, 0x03, OBJECT_DOR02 }, - { SCENE_BANDROOM, 0x03, OBJECT_DOR02 }, - { SCENE_20SICHITAI, 0x04, OBJECT_DOR03 }, - { SCENE_20SICHITAI2, 0x04, OBJECT_DOR03 }, - { SCENE_MAP_SHOP, 0x04, OBJECT_DOR03 }, - { SCENE_KAIZOKU, 0x0B, OBJECT_KAIZOKU_OBJ }, - { SCENE_PIRATE, 0x0B, OBJECT_KAIZOKU_OBJ }, - { SCENE_TORIDE, 0x0B, OBJECT_KAIZOKU_OBJ }, - { SCENE_KINDAN2, 0x0C, OBJECT_KINSTA2_OBJ }, - { -1, 0x00, GAMEPLAY_KEEP }, - { -1, 0x0D, GAMEPLAY_FIELD_KEEP }, - { -1, 0x08, OBJECT_WDOR03 }, - { -1, 0x07, OBJECT_WDOR02 }, - { -1, 0x06, OBJECT_WDOR01 }, - { -1, 0x07, OBJECT_WDOR02 }, - { -1, 0x06, OBJECT_WDOR01 }, - { -1, 0x00, GAMEPLAY_KEEP }, - { -1, 0x00, GAMEPLAY_KEEP }, - { -1, 0x00, GAMEPLAY_KEEP }, - { -1, 0x00, GAMEPLAY_KEEP }, - { -1, 0x00, GAMEPLAY_KEEP }, - { -1, 0x09, OBJECT_WDOR04 }, - { -1, 0x08, OBJECT_WDOR03 }, - { -1, 0x08, OBJECT_WDOR03 }, - { -1, 0x0D, GAMEPLAY_FIELD_KEEP }, - { -1, 0x0D, GAMEPLAY_FIELD_KEEP }, - { -1, 0x0D, GAMEPLAY_FIELD_KEEP }, - { -1, 0x0D, GAMEPLAY_FIELD_KEEP }, - { -1, 0x06, OBJECT_WDOR01 }, - { -1, 0x00, GAMEPLAY_KEEP }, - { -1, 0x00, GAMEPLAY_KEEP }, - { -1, 0x00, GAMEPLAY_KEEP }, - { -1, 0x00, GAMEPLAY_KEEP }, - { -1, 0x0D, GAMEPLAY_FIELD_KEEP }, - { -1, 0x0D, GAMEPLAY_FIELD_KEEP }, - { -1, 0x0D, GAMEPLAY_FIELD_KEEP }, - { -1, 0x0D, GAMEPLAY_FIELD_KEEP }, - { -1, 0x00, GAMEPLAY_KEEP }, - { -1, 0x0A, OBJECT_WDOR05 }, - { -1, 0x0D, GAMEPLAY_FIELD_KEEP }, - { -1, 0x05, OBJECT_DOR04 }, - { -1, 0x09, OBJECT_WDOR04 }, - { -1, 0x04, OBJECT_DOR03 }, + // DOOR_OBJKIND_DEFAULT + { SCENE_MITURIN, DOOR_DL_WOODFALL, OBJECT_NUMA_OBJ }, // DOOR_OBJINFO_0 + { SCENE_TENMON_DAI, DOOR_DL_OBSERVATORY_LAB, OBJECT_DOR01 }, // DOOR_OBJINFO_1 + { SCENE_00KEIKOKU, DOOR_DL_OBSERVATORY_LAB, OBJECT_DOR01 }, // DOOR_OBJINFO_2 + { SCENE_30GYOSON, DOOR_DL_OBSERVATORY_LAB, OBJECT_DOR01 }, // DOOR_OBJINFO_3 + { SCENE_LABO, DOOR_DL_OBSERVATORY_LAB, OBJECT_DOR01 }, // DOOR_OBJINFO_4 + { SCENE_33ZORACITY, DOOR_DL_ZORA_HALL, OBJECT_DOR02 }, // DOOR_OBJINFO_5 + { SCENE_UNSET_31, DOOR_DL_ZORA_HALL, OBJECT_DOR02 }, // DOOR_OBJINFO_6 + { SCENE_BANDROOM, DOOR_DL_ZORA_HALL, OBJECT_DOR02 }, // DOOR_OBJINFO_7 + { SCENE_20SICHITAI, DOOR_DL_SWAMP, OBJECT_DOR03 }, // DOOR_OBJINFO_8 + { SCENE_20SICHITAI2, DOOR_DL_SWAMP, OBJECT_DOR03 }, // DOOR_OBJINFO_9 + { SCENE_MAP_SHOP, DOOR_DL_SWAMP, OBJECT_DOR03 }, // DOOR_OBJINFO_10 + { SCENE_KAIZOKU, DOOR_DL_PIRATES_FORTESS, OBJECT_KAIZOKU_OBJ }, // DOOR_OBJINFO_11 + { SCENE_PIRATE, DOOR_DL_PIRATES_FORTESS, OBJECT_KAIZOKU_OBJ }, // DOOR_OBJINFO_12 + { SCENE_TORIDE, DOOR_DL_PIRATES_FORTESS, OBJECT_KAIZOKU_OBJ }, // DOOR_OBJINFO_13 + { SCENE_KINDAN2, DOOR_DL_OCEANSIDE_SPIDER_HOUSE, OBJECT_KINSTA2_OBJ }, // DOOR_OBJINFO_14 + + // DOOR_OBJKIND_KEEP + { -1, DOOR_DL_DEFAULT, GAMEPLAY_KEEP }, // DOOR_OBJINFO_15 + { -1, DOOR_DL_DEFAULT_FIELD_KEEP, GAMEPLAY_FIELD_KEEP }, // DOOR_OBJINFO_16 + + // DOOR_OBJKIND_SCHEDULE + { -1, DOOR_DL_INN_SCHOOL, OBJECT_WDOR03 }, // DOOR_OBJINFO_17 + { -1, DOOR_DL_POST_OFFICE_TRAIDING_POST, OBJECT_WDOR02 }, // DOOR_OBJINFO_18 + { -1, DOOR_DL_LOTTERY_CURIOSITY_SHIP_MAYOR_HOUSE, OBJECT_WDOR01 }, // DOOR_OBJINFO_19 + { -1, DOOR_DL_POST_OFFICE_TRAIDING_POST, OBJECT_WDOR02 }, // DOOR_OBJINFO_20 + { -1, DOOR_DL_LOTTERY_CURIOSITY_SHIP_MAYOR_HOUSE, OBJECT_WDOR01 }, // DOOR_OBJINFO_21 + { -1, DOOR_DL_DEFAULT, GAMEPLAY_KEEP }, // DOOR_OBJINFO_22 + { -1, DOOR_DL_DEFAULT, GAMEPLAY_KEEP }, // DOOR_OBJINFO_23 + { -1, DOOR_DL_DEFAULT, GAMEPLAY_KEEP }, // DOOR_OBJINFO_24 + { -1, DOOR_DL_DEFAULT, GAMEPLAY_KEEP }, // DOOR_OBJINFO_25 + { -1, DOOR_DL_DEFAULT, GAMEPLAY_KEEP }, // DOOR_OBJINFO_26 + { -1, DOOR_DL_MILK_BAR, OBJECT_WDOR04 }, // DOOR_OBJINFO_27 + { -1, DOOR_DL_INN_SCHOOL, OBJECT_WDOR03 }, // DOOR_OBJINFO_28 + { -1, DOOR_DL_INN_SCHOOL, OBJECT_WDOR03 }, // DOOR_OBJINFO_29 + { -1, DOOR_DL_DEFAULT_FIELD_KEEP, GAMEPLAY_FIELD_KEEP }, // DOOR_OBJINFO_30 + { -1, DOOR_DL_DEFAULT_FIELD_KEEP, GAMEPLAY_FIELD_KEEP }, // DOOR_OBJINFO_31 + { -1, DOOR_DL_DEFAULT_FIELD_KEEP, GAMEPLAY_FIELD_KEEP }, // DOOR_OBJINFO_32 + { -1, DOOR_DL_DEFAULT_FIELD_KEEP, GAMEPLAY_FIELD_KEEP }, // DOOR_OBJINFO_33 + { -1, DOOR_DL_LOTTERY_CURIOSITY_SHIP_MAYOR_HOUSE, OBJECT_WDOR01 }, // DOOR_OBJINFO_34 + { -1, DOOR_DL_DEFAULT, GAMEPLAY_KEEP }, // DOOR_OBJINFO_35 + { -1, DOOR_DL_DEFAULT, GAMEPLAY_KEEP }, // DOOR_OBJINFO_36 + { -1, DOOR_DL_DEFAULT, GAMEPLAY_KEEP }, // DOOR_OBJINFO_37 + { -1, DOOR_DL_DEFAULT, GAMEPLAY_KEEP }, // DOOR_OBJINFO_38 + { -1, DOOR_DL_DEFAULT_FIELD_KEEP, GAMEPLAY_FIELD_KEEP }, // DOOR_OBJINFO_39 + { -1, DOOR_DL_DEFAULT_FIELD_KEEP, GAMEPLAY_FIELD_KEEP }, // DOOR_OBJINFO_40 + { -1, DOOR_DL_DEFAULT_FIELD_KEEP, GAMEPLAY_FIELD_KEEP }, // DOOR_OBJINFO_41 + { -1, DOOR_DL_DEFAULT_FIELD_KEEP, GAMEPLAY_FIELD_KEEP }, // DOOR_OBJINFO_42 + { -1, DOOR_DL_DEFAULT, GAMEPLAY_KEEP }, // DOOR_OBJINFO_43 + { -1, DOOR_DL_MUSIC_BOX, OBJECT_WDOR05 }, // DOOR_OBJINFO_44 + { -1, DOOR_DL_DEFAULT_FIELD_KEEP, GAMEPLAY_FIELD_KEEP }, // DOOR_OBJINFO_45 + { -1, DOOR_DL_MAGIC_HAG_POTION_SHOP, OBJECT_DOR04 }, // DOOR_OBJINFO_46 + { -1, DOOR_DL_MILK_BAR, OBJECT_WDOR04 }, // DOOR_OBJINFO_47 + { -1, DOOR_DL_SWAMP, OBJECT_DOR03 }, // DOOR_OBJINFO_48 }; +static_assert(ARRAY_COUNT(sObjectInfo) == DOOR_OBJINFO_MAX, + "The entry count of `sObjectInfo` should match the `EnDoorObjectInfoIndex` enum"); static InitChainEntry sInitChain[] = { ICHAIN_U8(targetMode, TARGET_MODE_0, ICHAIN_CONTINUE), @@ -122,36 +254,41 @@ static InitChainEntry sInitChain[] = { ICHAIN_U16(shape.rot.z, 0, ICHAIN_STOP), }; -static AnimationHeader* sAnimations[2 * PLAYER_FORM_MAX] = { +static AnimationHeader* sAnimations[] = { // left - &gameplay_keep_Anim_020658, // PLAYER_FORM_FIERCE_DEITY - &gameplay_keep_Anim_022CA8, // PLAYER_FORM_GORON - &gameplay_keep_Anim_020658, // PLAYER_FORM_ZORA - &gameplay_keep_Anim_022E68, // PLAYER_FORM_DEKU - &gameplay_keep_Anim_0204B4, // PLAYER_FORM_HUMAN + &gDoorFierceDeityZoraOpenLeftAnim, // PLAYER_FORM_FIERCE_DEITY + &gDoorGoronOpenLeftAnim, // PLAYER_FORM_GORON + &gDoorFierceDeityZoraOpenLeftAnim, // PLAYER_FORM_ZORA + &gDoorDekuOpenLeftAnim, // PLAYER_FORM_DEKU + &gDoorHumanOpenLeftAnim, // PLAYER_FORM_HUMAN // right - &gameplay_keep_Anim_022BE8, // PLAYER_FORM_FIERCE_DEITY - &gameplay_keep_Anim_022D90, // PLAYER_FORM_GORON - &gameplay_keep_Anim_022BE8, // PLAYER_FORM_ZORA - &gameplay_keep_Anim_022FF0, // PLAYER_FORM_DEKU - &gameplay_keep_Anim_0205A0, // PLAYER_FORM_HUMAN -}; -static u8 sAnimOpenFrames[2 * PLAYER_FORM_MAX] = { - // left - 25, // PLAYER_FORM_FIERCE_DEITY - 25, // PLAYER_FORM_GORON - 25, // PLAYER_FORM_ZORA - 25, // PLAYER_FORM_DEKU - 25, // PLAYER_FORM_HUMAN - // right - 25, // PLAYER_FORM_FIERCE_DEITY - 25, // PLAYER_FORM_GORON - 25, // PLAYER_FORM_ZORA - 25, // PLAYER_FORM_DEKU - 25, // PLAYER_FORM_HUMAN + &gDoorFierceDeityZoraOpenRightAnim, // PLAYER_FORM_FIERCE_DEITY + &gDoorGoronOpenRightAnim, // PLAYER_FORM_GORON + &gDoorFierceDeityZoraOpenRightAnim, // PLAYER_FORM_ZORA + &gDoorDekuOpenRightAnim, // PLAYER_FORM_DEKU + &gDoorHumanOpenRightAnim, // PLAYER_FORM_HUMAN }; +static_assert(ARRAY_COUNT(sAnimations) == 2 * PLAYER_FORM_MAX, + "The entry count of `sAnimations` should be exactly twice as PLAYER_FORM_MAX"); -static u8 sAnimCloseFrames[2 * PLAYER_FORM_MAX] = { +static u8 sAnimOpenFrames[] = { + // left + 25, // PLAYER_FORM_FIERCE_DEITY + 25, // PLAYER_FORM_GORON + 25, // PLAYER_FORM_ZORA + 25, // PLAYER_FORM_DEKU + 25, // PLAYER_FORM_HUMAN + // right + 25, // PLAYER_FORM_FIERCE_DEITY + 25, // PLAYER_FORM_GORON + 25, // PLAYER_FORM_ZORA + 25, // PLAYER_FORM_DEKU + 25, // PLAYER_FORM_HUMAN +}; +static_assert(ARRAY_COUNT(sAnimOpenFrames) == 2 * PLAYER_FORM_MAX, + "The entry count of `sAnimOpenFrames` should be exactly twice as PLAYER_FORM_MAX"); + +static u8 sAnimCloseFrames[] = { // left 60, // PLAYER_FORM_FIERCE_DEITY 60, // PLAYER_FORM_GORON @@ -165,23 +302,28 @@ static u8 sAnimCloseFrames[2 * PLAYER_FORM_MAX] = { 60, // PLAYER_FORM_DEKU 70, // PLAYER_FORM_HUMAN }; +static_assert(ARRAY_COUNT(sAnimCloseFrames) == 2 * PLAYER_FORM_MAX, + "The entry count of `sAnimCloseFrames` should be exactly twice as PLAYER_FORM_MAX"); -static Gfx* D_808679A4[14][2] = { - { gDoorLeftDL, gDoorRightDL }, - { gWoodfallDoorDL, gWoodfallDoorDL }, - { gObservatoryLabDoorDL, gObservatoryLabDoorDL }, - { gZoraHallDoorDL, gZoraHallDoorDL }, - { gSwampDoorDL, gSwampDoorDL }, - { gMagicHagPotionShopDoorDL, gMagicHagPotionShopDoorDL }, - { gLotteryCuriosityShopMayorHouseDoorDL, gLotteryCuriosityShopMayorHouseDoorDL }, - { gPostOfficeTradingPostDoorDL, gPostOfficeTradingPostDoorDL }, - { gInnSchoolDoorDL, gInnSchoolDoorDL }, - { gMilkBarDoorDL, gMilkBarDoorDL }, - { gMusicBoxHouseDoorDL, gMusicBoxHouseDoorDL }, - { gPiratesFortressDoorDL, gPiratesFortressDoorDL }, - { gOceansideSpiderHouseDoorDL, gOceansideSpiderHouseDoorDL }, - { gFieldWoodDoorLeftDL, gFieldWoodDoorRightDL }, +static Gfx* sDoorDLists[][2] = { + { gDoorLeftDL, gDoorRightDL }, // DOOR_DL_DEFAULT + { gWoodfallDoorDL, gWoodfallDoorDL }, // DOOR_DL_WOODFALL + { gObservatoryLabDoorDL, gObservatoryLabDoorDL }, // DOOR_DL_OBSERVATORY_LAB + { gZoraHallDoorDL, gZoraHallDoorDL }, // DOOR_DL_ZORA_HALL + { gSwampDoorDL, gSwampDoorDL }, // DOOR_DL_SWAMP + { gMagicHagPotionShopDoorDL, gMagicHagPotionShopDoorDL }, // DOOR_DL_MAGIC_HAG_POTION_SHOP + { gLotteryCuriosityShopMayorHouseDoorDL, + gLotteryCuriosityShopMayorHouseDoorDL }, // DOOR_DL_LOTTERY_CURIOSITY_SHIP_MAYOR_HOUSE + { gPostOfficeTradingPostDoorDL, gPostOfficeTradingPostDoorDL }, // DOOR_DL_POST_OFFICE_TRAIDING_POST + { gInnSchoolDoorDL, gInnSchoolDoorDL }, // DOOR_DL_INN_SCHOOL + { gMilkBarDoorDL, gMilkBarDoorDL }, // DOOR_DL_MILK_BAR + { gMusicBoxHouseDoorDL, gMusicBoxHouseDoorDL }, // DOOR_DL_MUSIC_BOX + { gPiratesFortressDoorDL, gPiratesFortressDoorDL }, // DOOR_DL_PIRATES_FORTESS + { gOceansideSpiderHouseDoorDL, gOceansideSpiderHouseDoorDL }, // DOOR_DL_OCEANSIDE_SPIDER_HOUSE + { gFieldWoodDoorLeftDL, gFieldWoodDoorRightDL }, // DOOR_DL_DEFAULT_FIELD_KEEP }; +static_assert(ARRAY_COUNT(sDoorDLists) == DOOR_DL_MAX, + "The entry count of `sDoorDLists` should match the `EnDoorDListIndex` enum"); void EnDoor_Init(Actor* thisx, PlayState* play2) { PlayState* play = play2; @@ -193,165 +335,240 @@ void EnDoor_Init(Actor* thisx, PlayState* play2) { Actor_ProcessInitChain(&this->knobDoor.dyna.actor, sInitChain); this->doorType = ENDOOR_GET_TYPE(thisx); + this->typeVar.data = ENDOOR_GET_TYPE_VAR(thisx); - this->switchFlag = ENDOOR_GET_SWITCH_FLAG(thisx); - if ((this->doorType == ENDOOR_TYPE_7) && (this->switchFlag == 0)) { + if ((this->doorType == ENDOOR_TYPE_FRAMED) && (this->typeVar.frameType == ENDOOR_FRAMED_FRAME)) { DynaPolyActor_Init(&this->knobDoor.dyna, 0); - DynaPolyActor_LoadMesh(play, &this->knobDoor.dyna, &gDoorCol); + DynaPolyActor_LoadMesh(play, &this->knobDoor.dyna, &gFramedDoorCol); } - SkelAnime_Init(play, &this->knobDoor.skelAnime, &gDoorSkel, &gameplay_keep_Anim_020658, this->limbTable, + + SkelAnime_Init(play, &this->knobDoor.skelAnime, &gDoorSkel, &gDoorFierceDeityZoraOpenLeftAnim, this->limbTable, this->limbTable, DOOR_LIMB_MAX); - if (this->doorType == ENDOOR_TYPE_5) { - objectInfo = &sObjectInfo[17 + this->switchFlag]; + + if (this->doorType == ENDOOR_TYPE_SCHEDULE) { + objectInfo = &sObjectInfo[DOOR_OBJKIND_SCHEDULE + this->typeVar.schType]; } else { - for (i = 0; i < ARRAY_COUNT(sObjectInfo) - 34; i++, objectInfo++) { + // Look for the EnDoorInfo corresponding to the current scene. + // If no EnDoorInfo matches the current scene then objectInfo will point to the GAMEPLAY_KEEP one + for (i = 0; i < DOOR_OBJKIND_KEEP; i++, objectInfo++) { if (play->sceneId == objectInfo->sceneId) { break; } } - if ((i >= ARRAY_COUNT(sObjectInfo) - 34) && - (Object_GetSlot(&play->objectCtx, GAMEPLAY_FIELD_KEEP) > OBJECT_SLOT_NONE)) { + + // If objectInfo is pointing to the GAMEPLAY_KEEP's EnDoorInfo one and GAMEPLAY_FIELD_KEEP is loaded then use + // that one instead + if ((i >= DOOR_OBJKIND_KEEP) && (Object_GetSlot(&play->objectCtx, GAMEPLAY_FIELD_KEEP) > OBJECT_SLOT_NONE)) { objectInfo++; } } + // This assignment is redundant since it is set later again this->knobDoor.dlIndex = objectInfo->dListIndex; + + // Check if the object for the selected EnDoorInfo is loaded. + // If it isn't, then fallback to GAMEPLAY_KEEP objectSlot = Object_GetSlot(&play->objectCtx, objectInfo->objectId); if (objectSlot <= OBJECT_SLOT_NONE) { - objectInfo = &sObjectInfo[15]; + objectInfo = &sObjectInfo[DOOR_OBJINFO_15]; objectSlot = Object_GetSlot(&play->objectCtx, objectInfo->objectId); if (objectSlot != 0) { Actor_Kill(&this->knobDoor.dyna.actor); return; } } + this->knobDoor.objectSlot = objectSlot; - this->knobDoor.dlIndex = objectInfo->dListIndex; // Set twice? + this->knobDoor.dlIndex = objectInfo->dListIndex; + + // If the object that will be used is the one from the InitVars then call EnDoor_WaitForObject directly since we + // know the object will be loaded before this actor has spawned if (this->knobDoor.dyna.actor.objectSlot == this->knobDoor.objectSlot) { - func_80866A5C(this, play); + EnDoor_WaitForObject(this, play); } else { - this->actionFunc = func_80866A5C; + this->actionFunc = EnDoor_WaitForObject; } + Actor_SetFocus(&this->knobDoor.dyna.actor, 35.0f); } void EnDoor_Destroy(Actor* thisx, PlayState* play) { EnDoor* this = (EnDoor*)thisx; - if (this->doorType != ENDOOR_TYPE_7) { + if (this->doorType != ENDOOR_TYPE_FRAMED) { TransitionActorEntry* transitionEntry = &play->doorCtx.transitionActorList[DOOR_GET_TRANSITION_ID(&this->knobDoor.dyna.actor)]; + if (transitionEntry->id < 0) { transitionEntry->id = -transitionEntry->id; } - } else if (this->switchFlag == 0) { + } else if (this->typeVar.frameType == ENDOOR_FRAMED_FRAME) { DynaPoly_DeleteBgActor(play, &play->colCtx.dyna, this->knobDoor.dyna.bgId); } } -void func_80866A5C(EnDoor* this, PlayState* play) { - if (Object_IsLoaded(&play->objectCtx, this->knobDoor.objectSlot)) { - this->knobDoor.dyna.actor.objectSlot = this->knobDoor.objectSlot; - this->actionFunc = func_80866B20; - this->knobDoor.dyna.actor.world.rot.y = 0; - if (this->doorType == ENDOOR_TYPE_1) { - if (!Flags_GetSwitch(play, this->switchFlag)) { - this->unk_1A6 = 10; - } - } else if ((this->doorType == ENDOOR_TYPE_4) && - (Actor_WorldDistXZToActor(&this->knobDoor.dyna.actor, &GET_PLAYER(play)->actor) > 120.0f)) { - this->actionFunc = func_8086704C; - this->knobDoor.dyna.actor.world.rot.y = -0x1800; +void EnDoor_WaitForObject(EnDoor* this, PlayState* play) { + if (!Object_IsLoaded(&play->objectCtx, this->knobDoor.objectSlot)) { + return; + } + + this->knobDoor.dyna.actor.objectSlot = this->knobDoor.objectSlot; + this->actionFunc = EnDoor_Idle; + this->knobDoor.dyna.actor.world.rot.y = 0; + + if (this->doorType == ENDOOR_TYPE_LOCKED) { + if (!Flags_GetSwitch(play, this->typeVar.switchFlag)) { + this->lockTimer = 10; } + } else if ((this->doorType == ENDOOR_TYPE_AJAR) && + (Actor_WorldDistXZToActor(&this->knobDoor.dyna.actor, &GET_PLAYER(play)->actor) > + DOOR_AJAR_SLAM_RANGE)) { + this->actionFunc = EnDoor_AjarWait; + this->knobDoor.dyna.actor.world.rot.y = -0x1800; } } -void func_80866B20(EnDoor* this, PlayState* play) { - static s32 D_80867BC0; +// Set to true when the MilkBar door acknowledges player is a member +s32 sDoorIsMilkBarMember; + +/** + * Closed door waiting for interaction. + * + * General flow of this function and what is prioritized: + * - Handle opening request from player + * - Handle opening request from schedule actor + * - If not on cs mode: + * - If sDoorIsMilkBarMember or player is near the door and looking at it + * - Set this door as the one Player can interact with + * - If it is a locked door + * - Handle loocked door + * - Otherwise if the door is an AJAR one + * - Display a message saying it won't open + * - Otherwise if ENDOOR_TYPE_WHOLE_DAY? or ENDOOR_TYPE_DAY? or ENDOOR_TYPE_NIGHT? + * - Left the door closed depending on the day/night state expected by the door + * - Otherwise if ENDOOR_TYPE_SCHEDULE + * - Run schedule + * - Possibly not allow to open the door and prompt a message depending on the schedule result. + * - Otherwise if ENDOOR_TYPE_AJAR + * - If player is further than DOOR_AJAR_OPEN_RANGE + * - Play Ajar's open/close loop + */ +void EnDoor_Idle(EnDoor* this, PlayState* play) { Player* player = GET_PLAYER(play); + // 0x1821: Player is a member of the Milk bar if (Actor_TalkOfferAccepted(&this->knobDoor.dyna.actor, &play->state) && (this->knobDoor.dyna.actor.textId == 0x1821)) { - D_80867BC0 = true; + sDoorIsMilkBarMember = true; } - if (this->knobDoor.playOpenAnim) { - this->actionFunc = func_80867144; + + if (this->knobDoor.requestOpen) { + // Player or an NPC has requested this door to open + + this->actionFunc = EnDoor_Open; Animation_PlayOnceSetSpeed(&this->knobDoor.skelAnime, sAnimations[this->knobDoor.animIndex], (player->stateFlags1 & PLAYER_STATE1_8000000) ? 0.75f : 1.5f); - if (this->unk_1A6 != 0) { + + // If this is a locked door then handle small key counts, sfx and switch flag + if (this->lockTimer != 0) { DUNGEON_KEY_COUNT(gSaveContext.mapIndex) = DUNGEON_KEY_COUNT(gSaveContext.mapIndex) - 1; - Flags_SetSwitch(play, this->switchFlag); + Flags_SetSwitch(play, this->typeVar.switchFlag); Actor_PlaySfx(&this->knobDoor.dyna.actor, NA_SE_EV_CHAIN_KEY_UNLOCK); } } else if (this->openTimer != 0) { - this->actionFunc = func_80866F94; + // An schedule actor has requested to open this door + + this->actionFunc = EnDoor_OpenScheduleActor; Actor_PlaySfx(&this->knobDoor.dyna.actor, NA_SE_EV_DOOR_OPEN); } else if (!Player_InCsMode(play)) { Vec3f playerPosRelToDoor; + // Check if player is near this door and looking at it Actor_OffsetOfPointInActorCoords(&this->knobDoor.dyna.actor, &playerPosRelToDoor, &player->actor.world.pos); - if (D_80867BC0 || ((fabsf(playerPosRelToDoor.y) < 20.0f) && (fabsf(playerPosRelToDoor.x) < 20.0f) && - (fabsf(playerPosRelToDoor.z) < 50.0f))) { + if (sDoorIsMilkBarMember || ((fabsf(playerPosRelToDoor.y) < 20.0f) && (fabsf(playerPosRelToDoor.x) < 20.0f) && + (fabsf(playerPosRelToDoor.z) < 50.0f))) { s16 yawDiff = player->actor.shape.rot.y - this->knobDoor.dyna.actor.shape.rot.y; if (playerPosRelToDoor.z > 0.0f) { - yawDiff = (0x8000 - yawDiff); + yawDiff = 0x8000 - yawDiff; } if (ABS_ALT(yawDiff) < 0x3000) { + // Set this door as the one Player can interact with player->doorType = PLAYER_DOORTYPE_HANDLE; player->doorDirection = playerPosRelToDoor.z >= 0.0f ? 1.0f : -1.0f; player->doorActor = &this->knobDoor.dyna.actor; - if (this->unk_1A6 != 0) { + + if (this->lockTimer != 0) { if (DUNGEON_KEY_COUNT(gSaveContext.mapIndex) <= 0) { player->doorType = PLAYER_DOORTYPE_TALKING; + // 0x1802: "Missing small key" this->knobDoor.dyna.actor.textId = 0x1802; } else { player->doorTimer = 10; } - } else if (this->doorType == ENDOOR_TYPE_4) { + } else if (this->doorType == ENDOOR_TYPE_AJAR) { player->doorType = PLAYER_DOORTYPE_TALKING; + // 0x1800: "It won't open" this->knobDoor.dyna.actor.textId = 0x1800; - } else if ((this->doorType == ENDOOR_TYPE_0) || (this->doorType == ENDOOR_TYPE_2) || - (this->doorType == ENDOOR_TYPE_3)) { + } else if ((this->doorType == ENDOOR_TYPE_WHOLE_DAY) || (this->doorType == ENDOOR_TYPE_DAY) || + (this->doorType == ENDOOR_TYPE_NIGHT)) { s32 halfDaysDayBit = (play->actorCtx.halfDaysBit & HALFDAYBIT_DAWNS) >> 1; s32 halfDaysNightBit = play->actorCtx.halfDaysBit & HALFDAYBIT_NIGHTS; - s16 temp_a2 = D_801AED48[this->switchFlag & 7]; - s32 textIdOffset = (this->switchFlag >> 3) & 0xF; + s16 openBit = D_801AED48[ENDOOR_GET_HALFDAYBIT_INDEX_FROM_HALFDAYCHECK(this->typeVar.halfDayCheck)]; + s32 textIdOffset = ENDOOR_GET_TEXTOFFSET_FROM_HALFDAYCHECK(this->typeVar.halfDayCheck); - if (((this->doorType == ENDOOR_TYPE_0) && !((halfDaysDayBit | halfDaysNightBit) & temp_a2)) || - ((this->doorType == ENDOOR_TYPE_2) && !(halfDaysNightBit & temp_a2)) || - ((this->doorType == ENDOOR_TYPE_3) && !(halfDaysDayBit & temp_a2))) { + // Check if the door should be closed, and prompt a message if its the case + if (((this->doorType == ENDOOR_TYPE_WHOLE_DAY) && + !((halfDaysDayBit | halfDaysNightBit) & openBit)) || + ((this->doorType == ENDOOR_TYPE_DAY) && !(halfDaysNightBit & openBit)) || + ((this->doorType == ENDOOR_TYPE_NIGHT) && !(halfDaysDayBit & openBit))) { + //! @bug 0x182D does not exist, and there's no message for like 86 entries s16 baseTextId = 0x182D; - if (this->doorType == ENDOOR_TYPE_3) { + if (this->doorType == ENDOOR_TYPE_NIGHT) { + // 0x180D to 0x181C: messages indicating certain building are closed at night baseTextId = 0x180D; - } else if (this->doorType == ENDOOR_TYPE_2) { + } else if (this->doorType == ENDOOR_TYPE_DAY) { + // 0x181D to 0x1820: messages for when Pamela is inside the Music Box house with the door + // closed baseTextId = 0x181D; } player->doorType = PLAYER_DOORTYPE_TALKING; this->knobDoor.dyna.actor.textId = baseTextId + textIdOffset; } - } else if ((this->doorType == ENDOOR_TYPE_5) && (playerPosRelToDoor.z > 0.0f)) { + } else if ((this->doorType == ENDOOR_TYPE_SCHEDULE) && (playerPosRelToDoor.z > 0.0f)) { ScheduleOutput scheduleOutput; - if (Schedule_RunScript(play, D_8086778C[this->switchFlag], &scheduleOutput)) { + if (Schedule_RunScript(play, sDoorSchedules[this->typeVar.schType], &scheduleOutput)) { this->knobDoor.dyna.actor.textId = scheduleOutput.result + 0x1800; - player->doorType = ((this->knobDoor.dyna.actor.textId == 0x1821) && D_80867BC0) + // 0x1821: Player is a member of the Milk bar + // When player closes this specific message then the door changes to PLAYER_DOORTYPE_PROXIMITY, + // allowing player to open the door without having to press the A button again + player->doorType = ((this->knobDoor.dyna.actor.textId == 0x1821) && sDoorIsMilkBarMember) ? PLAYER_DOORTYPE_PROXIMITY : PLAYER_DOORTYPE_TALKING; } } func_80122F28(player); } - } else if ((this->doorType == ENDOOR_TYPE_4) && (this->knobDoor.dyna.actor.xzDistToPlayer > 240.0f)) { + } else if ((this->doorType == ENDOOR_TYPE_AJAR) && + (this->knobDoor.dyna.actor.xzDistToPlayer > DOOR_AJAR_OPEN_RANGE)) { Actor_PlaySfx(&this->knobDoor.dyna.actor, NA_SE_EV_DOOR_OPEN); - this->actionFunc = func_80867080; + this->actionFunc = EnDoor_AjarOpen; } } } -void func_80866F94(EnDoor* this, PlayState* play) { +/** + * Handle opening and closing request from an schedule actor. + * + * To trigger this an schedule actor must set the `openTimer` member, where its magnitude specifies for how many frames + * the door will be open (after the opening animation) and its sign indicates which direction the door will open. When + * the specified amount of frames has passed the door will closed automatically, without needing intervention from the + * schedule actor. + */ +void EnDoor_OpenScheduleActor(EnDoor* this, PlayState* play) { s32 direction; if (this->openTimer != 0) { @@ -365,41 +582,41 @@ void func_80866F94(EnDoor* this, PlayState* play) { } } else { if (Math_ScaledStepToS(&this->knobDoor.dyna.actor.world.rot.y, 0, 0x7D0)) { - this->actionFunc = func_80866B20; + this->actionFunc = EnDoor_Idle; Actor_PlaySfx(&this->knobDoor.dyna.actor, NA_SE_EV_AUTO_DOOR_CLOSE); } } } -void func_8086704C(EnDoor* this, PlayState* play) { - if (this->knobDoor.dyna.actor.xzDistToPlayer < 120.0f) { - this->actionFunc = func_808670F0; +void EnDoor_AjarWait(EnDoor* this, PlayState* play) { + if (this->knobDoor.dyna.actor.xzDistToPlayer < DOOR_AJAR_SLAM_RANGE) { + this->actionFunc = EnDoor_AjarClose; } } -void func_80867080(EnDoor* this, PlayState* play) { - if (this->knobDoor.dyna.actor.xzDistToPlayer < 120.0f) { - this->actionFunc = func_808670F0; +void EnDoor_AjarOpen(EnDoor* this, PlayState* play) { + if (this->knobDoor.dyna.actor.xzDistToPlayer < DOOR_AJAR_SLAM_RANGE) { + this->actionFunc = EnDoor_AjarClose; } else if (Math_ScaledStepToS(&this->knobDoor.dyna.actor.world.rot.y, -0x1800, 0x100)) { - this->actionFunc = func_8086704C; + this->actionFunc = EnDoor_AjarWait; } } -void func_808670F0(EnDoor* this, PlayState* play) { +void EnDoor_AjarClose(EnDoor* this, PlayState* play) { if (Math_ScaledStepToS(&this->knobDoor.dyna.actor.world.rot.y, 0, 0x700)) { Actor_PlaySfx(&this->knobDoor.dyna.actor, NA_SE_EV_DOOR_CLOSE); - this->actionFunc = func_80866B20; + this->actionFunc = EnDoor_Idle; } } -void func_80867144(EnDoor* this, PlayState* play) { +void EnDoor_Open(EnDoor* this, PlayState* play) { s32 numEffects; s32 i; - if (DECR(this->unk_1A6) == 0) { + if (DECR(this->lockTimer) == 0) { if (SkelAnime_Update(&this->knobDoor.skelAnime)) { - this->actionFunc = func_80866B20; - this->knobDoor.playOpenAnim = false; + this->actionFunc = EnDoor_Idle; + this->knobDoor.requestOpen = false; } else if (Animation_OnFrame(&this->knobDoor.skelAnime, sAnimOpenFrames[this->knobDoor.animIndex])) { Actor_PlaySfx(&this->knobDoor.dyna.actor, NA_SE_OC_DOOR_OPEN); if (this->knobDoor.skelAnime.playSpeed < 1.5f) { @@ -425,22 +642,21 @@ s32 EnDoor_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* EnDoor* this = THIS; if (limbIndex == DOOR_LIMB_4) { - Gfx** sideDLists = D_808679A4[this->knobDoor.dlIndex]; + Gfx** sideDLists = sDoorDLists[this->knobDoor.dlIndex]; transitionEntry = NULL; - - if (this->doorType != ENDOOR_TYPE_7) { + if (this->doorType != ENDOOR_TYPE_FRAMED) { transitionEntry = &play->doorCtx.transitionActorList[DOOR_GET_TRANSITION_ID(&this->knobDoor.dyna.actor)]; } + rot->z += this->knobDoor.dyna.actor.world.rot.y; - if ((this->doorType == ENDOOR_TYPE_7) || (play->roomCtx.prevRoom.num >= 0) || + if ((this->doorType == ENDOOR_TYPE_FRAMED) || (play->roomCtx.prevRoom.num >= 0) || (transitionEntry->sides[0].room == transitionEntry->sides[1].room)) { s16 temp = (this->knobDoor.dyna.actor.shape.rot.y + this->knobDoor.skelAnime.jointTable[DOOR_LIMB_3].z + rot->z) - Math_Vec3f_Yaw(&play->view.eye, &this->knobDoor.dyna.actor.world.pos); *dList = (ABS_ALT(temp) < 0x4000) ? sideDLists[0] : sideDLists[1]; - } else { s32 index = 0; @@ -450,22 +666,26 @@ s32 EnDoor_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* *dList = sideDLists[index]; } } + return false; } void EnDoor_Draw(Actor* thisx, PlayState* play) { EnDoor* this = THIS; + // Ensure the object that will be used is loaded if (this->knobDoor.dyna.actor.objectSlot == this->knobDoor.objectSlot) { OPEN_DISPS(play->state.gfxCtx); - if ((this->doorType == ENDOOR_TYPE_7) && (this->switchFlag == 0)) { + if ((this->doorType == ENDOOR_TYPE_FRAMED) && (this->typeVar.frameType == ENDOOR_FRAMED_FRAME)) { Gfx_DrawDListOpa(play, gameplay_keep_DL_0221B8); } else { Gfx_SetupDL25_Opa(play->state.gfxCtx); } + SkelAnime_DrawOpa(play, this->knobDoor.skelAnime.skeleton, this->knobDoor.skelAnime.jointTable, EnDoor_OverrideLimbDraw, NULL, &this->knobDoor.dyna.actor); + if (this->knobDoor.dyna.actor.world.rot.y != 0) { if (this->knobDoor.dyna.actor.world.rot.y > 0) { gSPDisplayList(POLY_OPA_DISP++, gDoorRightDL); @@ -473,8 +693,8 @@ void EnDoor_Draw(Actor* thisx, PlayState* play) { gSPDisplayList(POLY_OPA_DISP++, gDoorLeftDL); } } - if (this->unk_1A6) { - Actor_DrawDoorLock(play, this->unk_1A6, 0); + if (this->lockTimer) { + Actor_DrawDoorLock(play, this->lockTimer, DOORLOCK_NORMAL); } CLOSE_DISPS(play->state.gfxCtx); diff --git a/src/overlays/actors/ovl_En_Door/z_en_door.h b/src/overlays/actors/ovl_En_Door/z_en_door.h index 8d13e3d76c..fc0ee7ac68 100644 --- a/src/overlays/actors/ovl_En_Door/z_en_door.h +++ b/src/overlays/actors/ovl_En_Door/z_en_door.h @@ -5,30 +5,126 @@ #include "z64door.h" #include "objects/gameplay_keep/gameplay_keep.h" +/** + * Actor Parameters + * + * | | | + * | Transition Index | Type | Type var + * |------------------|-------|--------------- + * | 0 0 0 0 0 0 | 0 0 0 | 0 0 0 0 0 0 0 + * | 6 | 3 | 7 + * | + * + * Transition Index 1111110000000000 Set by the actor engine when the door is spawned (See Actor_SpawnTransitionActors and DOOR_GET_TRANSITION_ID) + * Type 0000001110000000 Values of the EnDoorType enum + * Type var 0000000001111111 Generic extra parameter. It is used differently by each door Type (or not used at all) + * + * + * If type is either ENDOOR_TYPE_WHOLE_DAY, ENDOOR_TYPE_DAY or ENDOOR_TYPE_NIGHT then the Type var is bitpacked like this: + * + * | | + * | Text offset | Half day bit index + * |-------------|-------------------- + * | 0 0 0 0 | 0 0 0 + * | 4 | 3 + * | + * + * Text offset 0000000001111000 Used as an offset relative to a base text id. The base text id is different depending on the door type. + * Half day bit index 0000000000000111 Index into the D_801AED48 array + * + * + * The rest of the door types either don't use the actionv var or don't bitpack extra parameters on it (using the full 7 bits) + */ + struct EnDoor; typedef void (*EnDoorActionFunc)(struct EnDoor*, PlayState*); -#define ENDOOR_GET_TYPE(thisx) (((thisx)->params >> 7) & 7) -#define ENDOOR_GET_SWITCH_FLAG(thisx) (((thisx)->params) & 0x7F) - typedef enum EnDoorType { - /* 0 */ ENDOOR_TYPE_0, - /* 1 */ ENDOOR_TYPE_1, - /* 2 */ ENDOOR_TYPE_2, - /* 3 */ ENDOOR_TYPE_3, - /* 4 */ ENDOOR_TYPE_4, - /* 5 */ ENDOOR_TYPE_5, - /* 6 */ ENDOOR_TYPE_6, - /* 7 */ ENDOOR_TYPE_7 + /* 0 */ ENDOOR_TYPE_WHOLE_DAY, // Allows to specify the door may be closed for full specific days. Which days the door is closed is controlled by the "half day bit index" part of the parameter + /* 1 */ ENDOOR_TYPE_LOCKED, + /* 2 */ ENDOOR_TYPE_DAY, // Allows to specify the door may be closed for specific dawns. Which dawns the door is closed is controlled by the "half day bit index" part of the parameter + /* 3 */ ENDOOR_TYPE_NIGHT, // Allows to specify the door may be closed for specific nights. Which nights the door is closed is controlled by the "half day bit index" part of the parameter + /* 4 */ ENDOOR_TYPE_AJAR, // unused + /* 5 */ ENDOOR_TYPE_SCHEDULE, + /* 6 */ ENDOOR_TYPE_6, // unreferenced + /* 7 */ ENDOOR_TYPE_FRAMED // unused } EnDoorType; +typedef enum EnDoorScheduleType { + /* 0 */ ENDOOR_SCH_TYPE_SWORDSMANS_SCHOOL, + /* 1 */ ENDOOR_SCH_TYPE_POST_OFFICE, + /* 2 */ ENDOOR_SCH_TYPE_LOTTERY_SHOP, + /* 3 */ ENDOOR_SCH_TYPE_TRADING_POST, + /* 4 */ ENDOOR_SCH_TYPE_CURIOSITY_SHOP, + /* 5 */ ENDOOR_SCH_TYPE_LAUNDRY_POOL, + /* 6 */ ENDOOR_SCH_TYPE_BOMB_SHOP, + /* 7 */ ENDOOR_SCH_TYPE_TOWN_SHOOTING_GALLERY, + /* 8 */ ENDOOR_SCH_TYPE_TREASURE_CHEST_SHOP, + /* 9 */ ENDOOR_SCH_TYPE_HONEY_DARLING_SHOP, + /* 10 */ ENDOOR_SCH_TYPE_MILK_BAR, + /* 11 */ ENDOOR_SCH_TYPE_INN_MAIN_ENTRANCE, + /* 12 */ ENDOOR_SCH_TYPE_INN_UPPER_ENTRANCE, + /* 13 */ ENDOOR_SCH_TYPE_INN_GRANNYS, + /* 14 */ ENDOOR_SCH_TYPE_INN_STAFF_ROOM, + /* 15 */ ENDOOR_SCH_TYPE_INN_KNIFE_CHAMBER, + /* 16 */ ENDOOR_SCH_TYPE_INN_LARGE_SUITE, + /* 17 */ ENDOOR_SCH_TYPE_MAYORS_RESIDENCE_MAIN_ENTRANCE, + /* 18 */ ENDOOR_SCH_TYPE_MAYORS_RESIDENCE_MAYOR_DOTOUR, + /* 19 */ ENDOOR_SCH_TYPE_MAYORS_RESIDENCE_MADAME_AROMA, + /* 20 */ ENDOOR_SCH_TYPE_MAYORS_RESIDENCE_BEDROOM, + /* 21 */ ENDOOR_SCH_TYPE_21, // unused + /* 22 */ ENDOOR_SCH_TYPE_ROMANI_RANCH_MAMAS_HOUSE, + /* 23 */ ENDOOR_SCH_TYPE_ROMANI_RANCH_BARN, + /* 24 */ ENDOOR_SCH_TYPE_ROMANI_RANCH_CUCCO_SHACK, + /* 25 */ ENDOOR_SCH_TYPE_ROMANI_RANCH_DOGGY_RACETRACK, + /* 26 */ ENDOOR_SCH_TYPE_ROMANI_RANCH_BEDROOM, + /* 27 */ ENDOOR_SCH_TYPE_IKANA_CANYON_MUSIC_BOX_HOUSE, + /* 28 */ ENDOOR_SCH_TYPE_DAMPES_HOUSE, + /* 29 */ ENDOOR_SCH_TYPE_MAGIC_HAGS_POTION_SHOP, + /* 30 */ ENDOOR_SCH_TYPE_30, // unused + /* 31 */ ENDOOR_SCH_TYPE_SWAMP_SHOOTING_GALLERY, + /* 32 */ ENDOOR_SCH_TYPE_MAX +} EnDoorScheduleType; + +typedef enum EnDoorFramedType { + /* 0 */ ENDOOR_FRAMED_FRAME, + /* 1 */ ENDOOR_FRAMED_NOFRAME +} EnDoorFramedType; + +#define ENDOOR_GET_TYPE(thisx) (((thisx)->params >> 7) & 7) +#define ENDOOR_GET_TYPE_VAR(thisx) (((thisx)->params) & 0x7F) + +// TODO: rename after D_801AED48 +#define ENDOOR_GET_HALFDAYBIT_INDEX_FROM_HALFDAYCHECK(typeVar) ((typeVar) & 0x7) +#define ENDOOR_GET_TEXTOFFSET_FROM_HALFDAYCHECK(typeVar) (((typeVar) >> 3) & 0xF) + +#define ENDOOR_PACK_HALFDAYCHECK(halfDayBitIndex, textOffset) ((((textOffset) & 0xF) << 3) | ((halfDayBitIndex) & 0x7)) + +#define ENDOOR_PARAMS(type, typeVar) ((((type) & 7) << 7) | ((typeVar) & 0x7F)) + +/** + * `scheduleType` must be a value of the `EnDoorScheduleType` enum + */ +#define ENDOOR_PARAMS_SCHEDULE(scheduleType) ENDOOR_PARAMS(ENDOOR_TYPE_SCHEDULE, scheduleType) + +/** + * `scheduleType` must be a value of the `EnDoorFramedType` enum + */ +#define ENDOOR_PARAMS_FRAMED(frameType) ENDOOR_PARAMS(ENDOOR_TYPE_FRAMED, frameType) + typedef struct EnDoor { /* 0x000 */ KnobDoorActor knobDoor; /* 0x1A4 */ u8 doorType; // EnDoorType enum - /* 0x1A5 */ u8 switchFlag; - /* 0x1A6 */ u8 unk_1A6; - /* 0x1A7 */ s8 openTimer; // For how long the door will be open. positive/negative means the opening direction + /* 0x1A5 */ union { + u8 data; // generic + u8 halfDayCheck; // ENDOOR_TYPE_WHOLE_DAY, ENDOOR_TYPE_DAY and ENDOOR_TYPE_NIGHT + u8 switchFlag; // ENDOOR_TYPE_LOCKED + u8 schType; // ENDOOR_TYPE_SCHEDULE + u8 frameType; // ENDOOR_TYPE_FRAMED + } typeVar; + /* 0x1A6 */ u8 lockTimer; // Used by ENDOOR_TYPE_LOCKED. Also controls drawing the lock on the door and side effects of opening a locked door, like decreasing the key count and updating the switch flag + /* 0x1A7 */ s8 openTimer; // For how long the door will be open. positive/negative means the opening direction. It is meant to be used only by ENDOOR_TYPE_SCHEDULE, and set by schedule actors. See EnDoor_OpenScheduleActor. /* 0x1A8 */ Vec3s limbTable[DOOR_LIMB_MAX]; /* 0x1C8 */ EnDoorActionFunc actionFunc; } EnDoor; 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 a14f18f8e7..d5eb8ee114 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 @@ -176,7 +176,7 @@ void func_80AC21A0(EnDoorEtc* this, PlayState* play) { s32 yawDiffAbs; Actor_OffsetOfPointInActorCoords(&this->knobDoor.dyna.actor, &playerOffsetFromDoor, &player->actor.world.pos); - if (!this->knobDoor.playOpenAnim) { + if (!this->knobDoor.requestOpen) { if ((!Player_InCsMode(play)) && ((fabsf(playerOffsetFromDoor.y) < 20.0f) && fabsf(playerOffsetFromDoor.x) < 20.0f) && (fabsf(playerOffsetFromDoor.z) < 50.0f)) { diff --git a/src/overlays/actors/ovl_En_Gm/z_en_gm.c b/src/overlays/actors/ovl_En_Gm/z_en_gm.c index 68e68d2364..fed5040cc8 100644 --- a/src/overlays/actors/ovl_En_Gm/z_en_gm.c +++ b/src/overlays/actors/ovl_En_Gm/z_en_gm.c @@ -171,39 +171,40 @@ Actor* EnGm_FindActor(EnGm* this, PlayState* play, u8 actorCategory, s16 actorId return actorIter; } -EnDoor* func_8094DF90(PlayState* play, s32 arg1) { - s32 phi_a1; +EnDoor* EnGm_FindScheduleDoor(PlayState* play, s32 scheduleOutputResult) { + EnDoorScheduleType schType; - switch (arg1) { + switch (scheduleOutputResult) { case 9: case 13: case 15: - phi_a1 = 11; + schType = ENDOOR_SCH_TYPE_INN_MAIN_ENTRANCE; break; case 10: case 11: case 16: case 17: - phi_a1 = 17; + schType = ENDOOR_SCH_TYPE_MAYORS_RESIDENCE_MAIN_ENTRANCE; break; case 12: case 14: case 20: - phi_a1 = 10; + schType = ENDOOR_SCH_TYPE_MILK_BAR; break; case 18: case 19: - phi_a1 = 19; + schType = ENDOOR_SCH_TYPE_MAYORS_RESIDENCE_MADAME_AROMA; break; default: - phi_a1 = -1; + schType = -1; + break; } - return SubS_FindDoor(play, phi_a1); + return SubS_FindScheduleDoor(play, schType); } s32 EnGm_UpdateSkelAnime(EnGm* this, PlayState* play) { @@ -942,7 +943,7 @@ s32 func_8094F904(EnGm* this, PlayState* play, ScheduleOutput* scheduleOutput) { s32 ret = false; this->timePath = NULL; - door = func_8094DF90(play, scheduleOutput->result); + door = EnGm_FindScheduleDoor(play, scheduleOutput->result); if (D_80951A0C[scheduleOutput->result] >= 0) { this->timePath = SubS_GetAdditionalPath(play, pathIndex, D_80951A0C[scheduleOutput->result]); @@ -1379,7 +1380,7 @@ s32 func_80950804(EnGm* this, PlayState* play) { s32 pad; f32 temp_f0; - door = func_8094DF90(play, this->unk_258); + door = EnGm_FindScheduleDoor(play, this->unk_258); if (!SubS_InCsMode(play) && (this->timePathTimeSpeed != 0)) { if ((door != NULL) && (door->knobDoor.dyna.actor.update != NULL)) { if ((this->unk_3BA / (f32)this->unk_3B8) <= 0.9f) { diff --git a/src/overlays/actors/ovl_En_Ig/z_en_ig.c b/src/overlays/actors/ovl_En_Ig/z_en_ig.c index c971c71e9d..aae7ea47db 100644 --- a/src/overlays/actors/ovl_En_Ig/z_en_ig.c +++ b/src/overlays/actors/ovl_En_Ig/z_en_ig.c @@ -156,26 +156,27 @@ Actor* EnIg_FindActor(EnIg* this, PlayState* play, u8 actorCategory, s16 actorId return actorIter; } -EnDoor* func_80BF1200(PlayState* play, s32 arg1) { - s32 phi_a1; +EnDoor* EnIg_FindScheduleDoor(PlayState* play, s32 scheduleOutputResult) { + EnDoorScheduleType schType; - switch (arg1) { + switch (scheduleOutputResult) { case 5: case 6: case 7: case 9: - phi_a1 = 11; + schType = ENDOOR_SCH_TYPE_INN_MAIN_ENTRANCE; break; case 8: - phi_a1 = 15; + schType = ENDOOR_SCH_TYPE_INN_KNIFE_CHAMBER; break; default: - phi_a1 = -1; + schType = -1; break; } - return SubS_FindDoor(play, phi_a1); + + return SubS_FindScheduleDoor(play, schType); } void EnIg_UpdateSkelAnime(EnIg* this) { @@ -534,7 +535,7 @@ s32 func_80BF1DF4(EnIg* this, PlayState* play, ScheduleOutput* scheduleOutput) { s32 ret = false; this->timePath = NULL; - door = func_80BF1200(play, scheduleOutput->result); + door = EnIg_FindScheduleDoor(play, scheduleOutput->result); if (D_80BF3318[scheduleOutput->result] >= 0) { this->timePath = SubS_GetAdditionalPath(play, pathIndex, D_80BF3318[scheduleOutput->result]); @@ -719,7 +720,7 @@ s32 func_80BF2400(EnIg* this, PlayState* play) { } s32 func_80BF2470(EnIg* this, PlayState* play) { - EnDoor* door = func_80BF1200(play, this->scheduleResult); + EnDoor* door = EnIg_FindScheduleDoor(play, this->scheduleResult); Vec3f sp38; f32 temp; s32 pad; diff --git a/src/overlays/actors/ovl_En_Pm/z_en_pm.c b/src/overlays/actors/ovl_En_Pm/z_en_pm.c index 1388575eb7..62ba14d1ce 100644 --- a/src/overlays/actors/ovl_En_Pm/z_en_pm.c +++ b/src/overlays/actors/ovl_En_Pm/z_en_pm.c @@ -263,36 +263,36 @@ Actor* EnPm_FindActor(EnPm* this, PlayState* play, u8 actorCategory, s16 actorId return actorIter; } -EnDoor* func_80AF7D60(PlayState* play, s32 arg1) { - s32 phi_a1; +EnDoor* EnPm_FindScheduleDoor(PlayState* play, s32 scheduleOutputResult) { + EnDoorScheduleType schType; - switch (arg1) { + switch (scheduleOutputResult) { case 1: case 2: case 32: case 33: - phi_a1 = 1; + schType = ENDOOR_SCH_TYPE_POST_OFFICE; break; case 34: case 35: case 36: case 37: - phi_a1 = 10; + schType = ENDOOR_SCH_TYPE_MILK_BAR; break; case 10: case 11: case 12: case 13: - phi_a1 = 11; + schType = ENDOOR_SCH_TYPE_INN_MAIN_ENTRANCE; break; default: return NULL; } - return SubS_FindDoor(play, phi_a1); + return SubS_FindScheduleDoor(play, schType); } Actor* func_80AF7DC4(EnPm* this, PlayState* play, s32 arg2) { @@ -877,7 +877,7 @@ s32 func_80AF9008(EnPm* this, PlayState* play, ScheduleOutput* scheduleOutput) { s32 ret = false; this->timePath = NULL; - door = func_80AF7D60(play, scheduleOutput->result); + door = EnPm_FindScheduleDoor(play, scheduleOutput->result); if (D_80AFB430[scheduleOutput->result] >= 0) { this->timePath = SubS_GetAdditionalPath(play, pathIndex, D_80AFB430[scheduleOutput->result]); } @@ -1338,7 +1338,7 @@ s32 func_80AF9BF8(EnPm* this, PlayState* play, ScheduleOutput* scheduleOutput) { } s32 func_80AF9D04(EnPm* this, PlayState* play) { - EnDoor* door = (EnDoor*)func_80AF7D60(play, this->unk_258); + EnDoor* door = EnPm_FindScheduleDoor(play, this->unk_258); Vec3f sp38; s32 pad; f32 temp; diff --git a/src/overlays/actors/ovl_En_Suttari/z_en_suttari.c b/src/overlays/actors/ovl_En_Suttari/z_en_suttari.c index 8f9a3ac9d0..44282ef407 100644 --- a/src/overlays/actors/ovl_En_Suttari/z_en_suttari.c +++ b/src/overlays/actors/ovl_En_Suttari/z_en_suttari.c @@ -717,7 +717,7 @@ s32 func_80BABC48(EnSuttari* this, PlayState* play, ScheduleOutput* scheduleOutp s32 func_80BABDD8(EnSuttari* this, PlayState* play, ScheduleOutput* scheduleOutput) { s32 pad; - EnDoor* sp48; + EnDoor* door; u8 pathIndex = ENSUTTARI_GET_PATH_INDEX(&this->actor); u16 sp44 = SCHEDULE_TIME_NOW; Vec3f sp38; @@ -728,12 +728,12 @@ s32 func_80BABDD8(EnSuttari* this, PlayState* play, ScheduleOutput* scheduleOutp if ((this->unk428 == 10) || (this->unk428 == 11) || (this->unk428 == 2)) { return false; } - sp48 = (EnDoor*)SubS_FindNearestActor(&this->actor, play, ACTORCAT_DOOR, ACTOR_EN_DOOR); + door = (EnDoor*)SubS_FindNearestActor(&this->actor, play, ACTORCAT_DOOR, ACTOR_EN_DOOR); sp24 = D_80BAE8F8[scheduleOutput->result]; - if ((sp48 != NULL) && (sp24 >= 0)) { + if ((door != NULL) && (sp24 >= 0)) { this->timePath = SubS_GetAdditionalPath(play, pathIndex, sp24); } - if ((sp48 == NULL) || (this->timePath == NULL)) { + if ((door == NULL) || (this->timePath == NULL)) { return false; } sp28 = Lib_SegmentedToVirtual(this->timePath->points); @@ -742,7 +742,7 @@ s32 func_80BABDD8(EnSuttari* this, PlayState* play, ScheduleOutput* scheduleOutp this->unk434 = sp44 - scheduleOutput->time0; this->unk436 = scheduleOutput->time1 - scheduleOutput->time0; if ((scheduleOutput->result != 10) && (scheduleOutput->result != 11)) { - sp48->openTimer = 75; + door->openTimer = 75; } Math_Vec3f_Copy(&this->unk438, &sp38); Math_Vec3f_Copy(&this->unk444, &sp2C); diff --git a/src/overlays/actors/ovl_En_Test3/z_en_test3.c b/src/overlays/actors/ovl_En_Test3/z_en_test3.c index 51911d9aea..af9840373f 100644 --- a/src/overlays/actors/ovl_En_Test3/z_en_test3.c +++ b/src/overlays/actors/ovl_En_Test3/z_en_test3.c @@ -518,7 +518,7 @@ s32 func_80A3F384(EnTest3* this, PlayState* play) { EnDoor* door = (EnDoor*)func_80A3F2BC(play, this, ACTOR_EN_DOOR, ACTORCAT_DOOR, 55.0f, 20.0f); Vec3f offset; - if ((door != NULL) && !door->knobDoor.playOpenAnim && + if ((door != NULL) && !door->knobDoor.requestOpen && ((player->doorType == PLAYER_DOORTYPE_NONE) || (&door->knobDoor.dyna.actor != player->doorActor)) && Actor_ActorAIsFacingActorB(&this->player.actor, &door->knobDoor.dyna.actor, 0x3000)) { Actor_OffsetOfPointInActorCoords(&door->knobDoor.dyna.actor, &offset, &this->player.actor.world.pos); diff --git a/src/overlays/actors/ovl_player_actor/z_player.c b/src/overlays/actors/ovl_player_actor/z_player.c index ea179c4685..a539feeca2 100644 --- a/src/overlays/actors/ovl_player_actor/z_player.c +++ b/src/overlays/actors/ovl_player_actor/z_player.c @@ -6456,12 +6456,12 @@ void Player_Door_Knob(PlayState* play, Player* this, Actor* door) { func_8082DAD4(this); Player_AnimReplace_Setup( play, this, ANIM_FLAG_1 | ANIM_FLAG_UPDATE_Y | ANIM_FLAG_4 | ANIM_FLAG_8 | ANIM_FLAG_80 | ANIM_FLAG_200); - knobDoor->playOpenAnim = true; + knobDoor->requestOpen = true; if (this->doorType != PLAYER_DOORTYPE_FAKE) { CollisionPoly* poly; s32 bgId; Vec3f pos; - s32 enDoorType = ENDOOR_GET_TYPE(&knobDoor->dyna.actor); + EnDoorType enDoorType = ENDOOR_GET_TYPE(&knobDoor->dyna.actor); this->stateFlags1 |= PLAYER_STATE1_20000000; @@ -6473,7 +6473,7 @@ void Player_Door_Knob(PlayState* play, Player* this, Actor* door) { if (Player_HandleExitsAndVoids(play, this, poly, BGCHECK_SCENE)) { gSaveContext.entranceSpeed = 2.0f; - } else if (enDoorType != ENDOOR_TYPE_7) { + } else if (enDoorType != ENDOOR_TYPE_FRAMED) { Camera* mainCam; this->av1.actionVar1 = 38.0f * D_8085C3E8; @@ -6526,7 +6526,8 @@ s32 Player_ActionChange_1(Player* this, PlayState* play) { if (this->actor.category == ACTORCAT_PLAYER) { if ((this->doorType < PLAYER_DOORTYPE_FAKE) && (doorActor->category == ACTORCAT_DOOR) && - ((this->doorType != PLAYER_DOORTYPE_HANDLE) || (ENDOOR_GET_TYPE(doorActor) != ENDOOR_TYPE_7))) { + ((this->doorType != PLAYER_DOORTYPE_HANDLE) || + (ENDOOR_GET_TYPE(doorActor) != ENDOOR_TYPE_FRAMED))) { s8 roomNum = play->doorCtx.transitionActorList[DOOR_GET_TRANSITION_ID(doorActor)] .sides[(this->doorDirection > 0) ? 0 : 1] .room; @@ -15308,7 +15309,7 @@ void Player_Action_35(Player* this, PlayState* play) { // door stuff void Player_Action_36(Player* this, PlayState* play) { EnDoor* doorActor = (EnDoor*)this->doorActor; - s32 sp38 = (doorActor != NULL) && (doorActor->doorType == ENDOOR_TYPE_7); + s32 framedDoor = (doorActor != NULL) && (doorActor->doorType == ENDOOR_TYPE_FRAMED); s32 animFinished; CollisionPoly* poly; s32 bgId; @@ -15332,7 +15333,7 @@ void Player_Action_36(Player* this, PlayState* play) { Player_StopCutscene(this); func_80839E74(this, play); - if ((this->actor.category == ACTORCAT_PLAYER) && !sp38) { + if ((this->actor.category == ACTORCAT_PLAYER) && !framedDoor) { if (play->roomCtx.prevRoom.num >= 0) { func_8012EBF8(play, &play->roomCtx); } @@ -15344,7 +15345,7 @@ void Player_Action_36(Player* this, PlayState* play) { } else if (!(this->stateFlags1 & PLAYER_STATE1_20000000) && PlayerAnimation_OnFrame(&this->skelAnime, 15.0f)) { Player_StopCutscene(this); play->func_18780(this, play); - } else if (sp38 && PlayerAnimation_OnFrame(&this->skelAnime, 15.0f)) { + } else if (framedDoor && PlayerAnimation_OnFrame(&this->skelAnime, 15.0f)) { s16 exitIndexPlusOne = (this->doorDirection < 0) ? doorActor->knobDoor.dyna.actor.world.rot.x : doorActor->knobDoor.dyna.actor.world.rot.z; diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt index 2f96973538..0e61fef07d 100644 --- a/tools/disasm/functions.txt +++ b/tools/disasm/functions.txt @@ -2655,7 +2655,7 @@ 0x8013A4C4:("Snap_CheckFlag",), 0x8013A504:("Snap_AbsS",), 0x8013A530:("Snap_ValidatePictograph",), - 0x8013A7C0:("SubS_FindDoor",), + 0x8013A7C0:("SubS_FindScheduleDoor",), 0x8013A860:("SubS_DrawTransformFlexLimb",), 0x8013AB00:("SubS_DrawTransformFlex",), 0x8013AD6C:("SubS_InCsMode",), @@ -4952,13 +4952,13 @@ 0x80866398:("EnLight_Draw",), 0x80866800:("EnDoor_Init",), 0x808669E0:("EnDoor_Destroy",), - 0x80866A5C:("func_80866A5C",), - 0x80866B20:("func_80866B20",), - 0x80866F94:("func_80866F94",), - 0x8086704C:("func_8086704C",), - 0x80867080:("func_80867080",), - 0x808670F0:("func_808670F0",), - 0x80867144:("func_80867144",), + 0x80866A5C:("EnDoor_WaitForObject",), + 0x80866B20:("EnDoor_Idle",), + 0x80866F94:("EnDoor_OpenScheduleActor",), + 0x8086704C:("EnDoor_AjarWait",), + 0x80867080:("EnDoor_AjarOpen",), + 0x808670F0:("EnDoor_AjarClose",), + 0x80867144:("EnDoor_Open",), 0x8086732C:("EnDoor_Update",), 0x80867350:("EnDoor_OverrideLimbDraw",), 0x808674B0:("EnDoor_Draw",), @@ -7579,7 +7579,7 @@ 0x809495F8:("EnClearTag_UpdateEffects",), 0x80949BD4:("EnClearTag_DrawEffects",), 0x8094DEE0:("EnGm_FindActor",), - 0x8094DF90:("func_8094DF90",), + 0x8094DF90:("EnGm_FindScheduleDoor",), 0x8094DFF8:("EnGm_UpdateSkelAnime",), 0x8094E054:("EnGm_ChangeAnim",), 0x8094E0F8:("func_8094E0F8",), @@ -12729,7 +12729,7 @@ 0x80AF7B40:("func_80AF7B40",), 0x80AF7BAC:("func_80AF7BAC",), 0x80AF7CB0:("EnPm_FindActor",), - 0x80AF7D60:("func_80AF7D60",), + 0x80AF7D60:("EnPm_FindScheduleDoor",), 0x80AF7DC4:("func_80AF7DC4",), 0x80AF7E6C:("func_80AF7E6C",), 0x80AF7E98:("func_80AF7E98",), @@ -14010,7 +14010,7 @@ 0x80B53840:("EnAn_InitObjectSlots",), 0x80B539CC:("EnAn_FindActor",), 0x80B53A7C:("func_80B53A7C",), - 0x80B53B3C:("EnAn_FindDoor",), + 0x80B53B3C:("EnAn_FindScheduleDoor",), 0x80B53BA8:("EnAn_UpdateSkelAnime",), 0x80B53CE8:("EnAn_ChangeAnim",), 0x80B53ED4:("EnAn_UpdateCollider",), @@ -16282,7 +16282,7 @@ 0x80BF0EEC:("EffStk_Update",), 0x80BF0F10:("EffStk_Draw",), 0x80BF1150:("EnIg_FindActor",), - 0x80BF1200:("func_80BF1200",), + 0x80BF1200:("EnIg_FindActor",), 0x80BF1258:("EnIg_UpdateSkelAnime",), 0x80BF1284:("EnIg_ChangeAnim",), 0x80BF1354:("func_80BF1354",), diff --git a/tools/disasm/variables.txt b/tools/disasm/variables.txt index 91efbd8e20..f88dfdbcdd 100644 --- a/tools/disasm/variables.txt +++ b/tools/disasm/variables.txt @@ -5357,48 +5357,48 @@ 0x8086675C:("D_8086675C","f32","",0x4), 0x80866760:("D_80866760","f32","",0x4), 0x80866764:("D_80866764","f32","",0x4), - 0x808675D0:("D_808675D0","UNK_TYPE1","",0x1), - 0x808675E4:("D_808675E4","UNK_TYPE1","",0x1), - 0x80867634:("D_80867634","UNK_TYPE1","",0x1), - 0x80867640:("D_80867640","UNK_TYPE1","",0x1), - 0x8086764C:("D_8086764C","UNK_TYPE1","",0x1), - 0x80867658:("D_80867658","UNK_TYPE1","",0x1), - 0x80867684:("D_80867684","UNK_TYPE1","",0x1), - 0x80867688:("D_80867688","UNK_TYPE1","",0x1), - 0x80867690:("D_80867690","UNK_TYPE1","",0x1), - 0x80867698:("D_80867698","UNK_TYPE1","",0x1), - 0x808676A0:("D_808676A0","UNK_TYPE1","",0x1), - 0x808676B8:("D_808676B8","UNK_TYPE1","",0x1), - 0x808676D0:("D_808676D0","UNK_TYPE1","",0x1), - 0x808676D4:("D_808676D4","UNK_TYPE1","",0x1), - 0x808676D8:("D_808676D8","UNK_TYPE1","",0x1), - 0x808676E4:("D_808676E4","UNK_TYPE1","",0x1), - 0x808676EC:("D_808676EC","UNK_TYPE1","",0x1), - 0x808676F0:("D_808676F0","UNK_TYPE1","",0x1), - 0x80867704:("D_80867704","UNK_TYPE1","",0x1), - 0x80867708:("D_80867708","UNK_TYPE1","",0x1), - 0x8086770C:("D_8086770C","UNK_TYPE1","",0x1), + 0x808675D0:("sDoorSch_SwordsmansSchool","UNK_TYPE1","",0x1), + 0x808675E4:("sDoorSch_PostOffice","UNK_TYPE1","",0x1), + 0x80867634:("sDoorSch_LotteryShop","UNK_TYPE1","",0x1), + 0x80867640:("sDoorSch_TradingPost","UNK_TYPE1","",0x1), + 0x8086764C:("sDoorSch_CuriosityShop","UNK_TYPE1","",0x1), + 0x80867658:("sDoorSch_LaundryPool","UNK_TYPE1","",0x1), + 0x80867684:("sDoorSch_BombShop","UNK_TYPE1","",0x1), + 0x80867688:("sDoorSch_TownShootingGallery","UNK_TYPE1","",0x1), + 0x80867690:("sDoorSch_TreasureChestShop","UNK_TYPE1","",0x1), + 0x80867698:("sDoorSch_HoneyDarlingShop","UNK_TYPE1","",0x1), + 0x808676A0:("sDoorSch_MilkBar","UNK_TYPE1","",0x1), + 0x808676B8:("sDoorSch_InnMainEntrance","UNK_TYPE1","",0x1), + 0x808676D0:("sDoorSch_InnUpperEntrance","UNK_TYPE1","",0x1), + 0x808676D4:("sDoorSch_InnGrannys","UNK_TYPE1","",0x1), + 0x808676D8:("sDoorSch_InnStaffRoom","UNK_TYPE1","",0x1), + 0x808676E4:("sDoorSch_InnKnifeChamber","UNK_TYPE1","",0x1), + 0x808676EC:("sDoorSch_InnLargeSuite","UNK_TYPE1","",0x1), + 0x808676F0:("sDoorSch_MayorsResidenceMainEntrance","UNK_TYPE1","",0x1), + 0x80867704:("sDoorSch_MayorsResidenceMayorDotour","UNK_TYPE1","",0x1), + 0x80867708:("sDoorSch_MayorsResidenceMadameAroma","UNK_TYPE1","",0x1), + 0x8086770C:("sDoorSch_MayorsResidenceBedroom","UNK_TYPE1","",0x1), 0x80867710:("D_80867710","UNK_TYPE1","",0x1), - 0x80867714:("D_80867714","UNK_TYPE1","",0x1), - 0x8086771C:("D_8086771C","UNK_TYPE1","",0x1), - 0x80867734:("D_80867734","UNK_TYPE1","",0x1), - 0x8086773C:("D_8086773C","UNK_TYPE1","",0x1), - 0x80867744:("D_80867744","UNK_TYPE1","",0x1), - 0x8086775C:("D_8086775C","UNK_TYPE1","",0x1), - 0x80867778:("D_80867778","UNK_TYPE1","",0x1), - 0x8086777C:("D_8086777C","UNK_TYPE1","",0x1), + 0x80867714:("sDoorSch_RomaniRanchMamasHouse","UNK_TYPE1","",0x1), + 0x8086771C:("sDoorSch_RomaniRanchBarn","UNK_TYPE1","",0x1), + 0x80867734:("sDoorSch_RomaniRanchCuccoShack","UNK_TYPE1","",0x1), + 0x8086773C:("sDoorSch_RomaniRanchDoggyRacetrack","UNK_TYPE1","",0x1), + 0x80867744:("sDoorSch_RomaniRanchBedroom","UNK_TYPE1","",0x1), + 0x8086775C:("sDoorSch_IkanaCanyonMusicBoxHouse","UNK_TYPE1","",0x1), + 0x80867778:("sDoorSch_DampesHouse","UNK_TYPE1","",0x1), + 0x8086777C:("sDoorSch_MagicHagsPotionShop","UNK_TYPE1","",0x1), 0x80867780:("D_80867780","UNK_TYPE1","",0x1), - 0x80867784:("D_80867784","UNK_TYPE1","",0x1), - 0x8086778C:("D_8086778C","UNK_PTR","",0x4), + 0x80867784:("sDoorSch_SwampShootingGallery","UNK_TYPE1","",0x1), + 0x8086778C:("sDoorSchedules","UNK_PTR","",0x4), 0x8086780C:("En_Door_InitVars","UNK_TYPE1","",0x1), 0x8086782C:("sObjectInfo","UNK_TYPE2","",0x126), 0x80867954:("sInitChain","UNK_TYPE1","",0x1), 0x80867964:("sAnimations","AnimationHeader","[10]",0x28), 0x8086798C:("sAnimOpenFrames","u8","[10]",0x10), 0x80867998:("sAnimCloseFrames","u8","[10]",0x10), - 0x808679A4:("D_808679A4","UNK_TYPE1","",0x1), + 0x808679A4:("sDoorDLists","UNK_TYPE1","",0x1), 0x80867A20:("D_80867A20","f32","",0x4), - 0x80867BC0:("D_80867BC0","UNK_TYPE1","",0x1), + 0x80867BC0:("sDoorIsMilkBarMember","UNK_TYPE1","",0x1), 0x80869B30:("En_Box_InitVars","UNK_TYPE1","",0x1), 0x80869B50:("D_80869B50","UNK_TYPE1","",0x1), 0x80869B54:("D_80869B54","UNK_TYPE4","",0x4), diff --git a/tools/namefixer.py b/tools/namefixer.py index a77063608d..bde36eec1d 100755 --- a/tools/namefixer.py +++ b/tools/namefixer.py @@ -798,7 +798,8 @@ wordReplace = { "func_8013E1C8": "SubS_ChangeAnimationBySpeedInfo", "func_8013D9C8": "SubS_UpdateFidgetTables", "SubS_FillLimbRotTables": "SubS_UpdateFidgetTables", - "func_8013A7C0": "SubS_FindDoor", + "func_8013A7C0": "SubS_FindScheduleDoor", + "SubS_FindDoor": "SubS_FindScheduleDoor", "func_8013E640": "SubS_FindActorCustom", "func_ActorCategoryIterateById": "SubS_FindActor", "func_8013BB7C": "SubS_FindNearestActor", diff --git a/tools/sizes/code_functions.csv b/tools/sizes/code_functions.csv index 115329be18..8687d3f2cf 100644 --- a/tools/sizes/code_functions.csv +++ b/tools/sizes/code_functions.csv @@ -2169,7 +2169,7 @@ asm/non_matchings/code/z_snap/func_8013A46C.s,func_8013A46C,0x8013A46C,0x16 asm/non_matchings/code/z_snap/func_8013A4C4.s,func_8013A4C4,0x8013A4C4,0x10 asm/non_matchings/code/z_snap/func_8013A504.s,func_8013A504,0x8013A504,0xB asm/non_matchings/code/z_snap/func_8013A530.s,func_8013A530,0x8013A530,0xA4 -asm/non_matchings/code/z_sub_s/SubS_FindDoor.s,SubS_FindDoor,0x8013A7C0,0x28 +asm/non_matchings/code/z_sub_s/SubS_FindScheduleDoor.s,SubS_FindScheduleDoor,0x8013A7C0,0x28 asm/non_matchings/code/z_sub_s/SubS_DrawTransformFlexLimb.s,SubS_DrawTransformFlexLimb,0x8013A860,0xA8 asm/non_matchings/code/z_sub_s/SubS_DrawTransformFlex.s,SubS_DrawTransformFlex,0x8013AB00,0x9B asm/non_matchings/code/z_sub_s/SubS_InCsMode.s,SubS_InCsMode,0x8013AD6C,0xC