diff --git a/linker_scripts/code_script.txt b/linker_scripts/code_script.txt index a3afc53ba..fdb3d7429 100644 --- a/linker_scripts/code_script.txt +++ b/linker_scripts/code_script.txt @@ -5949,9 +5949,9 @@ SECTIONS ovl_Obj_Tokei_Step : AT(RomLocation) { build/src/overlays/actors/ovl_Obj_Tokei_Step/z_obj_tokei_step.o(.text) - build/asm/overlays/ovl_Obj_Tokei_Step_data.o(.data) + build/src/overlays/actors/ovl_Obj_Tokei_Step/z_obj_tokei_step.o(.data) build/src/overlays/actors/ovl_Obj_Tokei_Step/z_obj_tokei_step.o(.rodata) - build/asm/overlays/ovl_Obj_Tokei_Step_rodata.o(.rodata) + build/src/overlays/actors/ovl_Obj_Tokei_Step/z_obj_tokei_step_overlay.o(.ovl) } SegmentEnd = .; SegmentSize = SegmentEnd - SegmentStart; diff --git a/linker_scripts/object_script.txt b/linker_scripts/object_script.txt index 42b8acad8..2a5f047b9 100644 --- a/linker_scripts/object_script.txt +++ b/linker_scripts/object_script.txt @@ -214,6 +214,10 @@ D_06000140 = 0x06000140; D_06000A20 = 0x06000A20; D_06000040 = 0x06000040; +/* obj_tokei_step */ +D_06000088 = 0x06000088; +D_06000968 = 0x06000968; + /* z_bg_ctower_gear */ D_06010828 = 0x06010828; D_06015F30 = 0x06015F30; diff --git a/src/overlays/actors/ovl_Obj_Tokei_Step/z_obj_tokei_step.c b/src/overlays/actors/ovl_Obj_Tokei_Step/z_obj_tokei_step.c index a2a423a17..518a90a11 100644 --- a/src/overlays/actors/ovl_Obj_Tokei_Step/z_obj_tokei_step.c +++ b/src/overlays/actors/ovl_Obj_Tokei_Step/z_obj_tokei_step.c @@ -1,3 +1,9 @@ +/* + * File: z_obj_tokei_step.c + * Overlay: obj_Tokei_Step + * Description: Door to Top of Clock Tower + */ + #include "z_obj_tokei_step.h" #define FLAGS 0x00400010 @@ -9,7 +15,16 @@ void ObjTokeiStep_Destroy(Actor* thisx, GlobalContext* globalCtx); void ObjTokeiStep_Update(Actor* thisx, GlobalContext* globalCtx); void ObjTokeiStep_Draw(Actor* thisx, GlobalContext* globalCtx); -/* +void ObjTokeiStep_SetupBeginOpen(ObjTokeiStep* this); +void ObjTokeiStep_BeginOpen(ObjTokeiStep* this, GlobalContext* globalCtx); +void ObjTokeiStep_SetupDoNothing(ObjTokeiStep* this); +void ObjTokeiStep_DoNothing(ObjTokeiStep* this, GlobalContext* globalCtx); +void ObjTokeiStep_SetupOpen(ObjTokeiStep* this); +void ObjTokeiStep_Open(ObjTokeiStep* this, GlobalContext* globalCtx); +void ObjTokeiStep_SetupDoNothingOpen(ObjTokeiStep* this); +void ObjTokeiStep_DoNothingOpen(ObjTokeiStep* this, GlobalContext* globalCtx); +void ObjTokeiStep_DrawOpen(Actor* thisx, GlobalContext* globalCtx); + const ActorInit Obj_Tokei_Step_InitVars = { ACTOR_OBJ_TOKEI_STEP, ACTORCAT_BG, @@ -21,44 +36,260 @@ const ActorInit Obj_Tokei_Step_InitVars = { (ActorFunc)ObjTokeiStep_Update, (ActorFunc)ObjTokeiStep_Draw, }; -*/ -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Tokei_Step_0x80AD5BB0/func_80AD5BB0.asm") +extern Gfx D_06000088[]; -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Tokei_Step_0x80AD5BB0/func_80AD5BE8.asm") +extern CollisionHeader D_06000968; -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Tokei_Step_0x80AD5BB0/func_80AD5C70.asm") +static f32 panelXOffsets[] = { -105.0f, -90.0f, -75.0f, -60.0f, -45.0f, -30.0f, -15.0f }; -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Tokei_Step_0x80AD5BB0/func_80AD5DFC.asm") +static f32 dustSpawnXOffsets[] = { -60.0f, -40.0f, -20.0f, 0.0f, 20.0f, 40.0f, 60.0f }; -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Tokei_Step_0x80AD5BB0/func_80AD5EB8.asm") +static Vec3f dustEffectAccel = { 0.0f, 0.3f, 0.0f }; -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Tokei_Step_0x80AD5BB0/func_80AD5F70.asm") +static InitChainEntry sInitChain[] = { + ICHAIN_F32(uncullZoneForward, 4000, ICHAIN_CONTINUE), + ICHAIN_F32(uncullZoneScale, 300, ICHAIN_CONTINUE), + ICHAIN_F32(uncullZoneDownward, 300, ICHAIN_CONTINUE), + ICHAIN_VEC3F_DIV1000(scale, 100, ICHAIN_STOP), +}; -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Tokei_Step_0x80AD5BB0/func_80AD5FB0.asm") +void ObjTokeiStep_SetSysMatrix(ObjTokeiStepPanel* panel) { + MtxF* sysMatrix; -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Tokei_Step_0x80AD5BB0/ObjTokeiStep_Init.asm") + sysMatrix = SysMatrix_GetCurrentState(); + sysMatrix->wx = panel->pos.x; + sysMatrix->wy = panel->pos.y; + sysMatrix->wz = panel->pos.z; +} -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Tokei_Step_0x80AD5BB0/ObjTokeiStep_Destroy.asm") +void ObjTokeiStep_AddQuake(ObjTokeiStep* this, GlobalContext* globalCtx) { + s32 pad[2]; + s16 quake; -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Tokei_Step_0x80AD5BB0/func_80AD6348.asm") + quake = Quake_Add(ACTIVE_CAM, 3); + Quake_SetSpeed(quake, 0x4E20); + Quake_SetQuakeValues(quake, 1, 0, 0, 0); + Quake_SetCountdown(quake, 7); + func_8013ECE0(this->dyna.actor.xyzDistToPlayerSq, 0x78, 0x14, 0xA); +} -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Tokei_Step_0x80AD5BB0/func_80AD635C.asm") +void ObjTokeiStep_SpawnDust(ObjTokeiStep* this, ObjTokeiStepPanel* panel, GlobalContext* globalCtx) { + s32 i; + s32 pad; + Vec3f dustSpawnOffset; + Vec3f dustSpawnPos; -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Tokei_Step_0x80AD5BB0/func_80AD63D4.asm") + Matrix_RotateY(this->dyna.actor.shape.rot.y, 0); -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Tokei_Step_0x80AD5BB0/func_80AD63E8.asm") + dustSpawnOffset.y = 115.0f; + dustSpawnOffset.z = -10.0f; + for (i = 0; i < 7; i++) { + dustSpawnOffset.x = dustSpawnXOffsets[i]; + SysMatrix_MultiplyVector3fByState(&dustSpawnOffset, &dustSpawnPos); + dustSpawnPos.x += panel->pos.x; + dustSpawnPos.y += panel->pos.y; + dustSpawnPos.z += panel->pos.z; + func_800B1210(globalCtx, &dustSpawnPos, &D_801D15B0, &dustEffectAccel, (s32)((Rand_ZeroOne() * 40.0f) + 80.0f), + (s32)((Rand_ZeroOne() * 20.0f) + 50.0f)); + } +} -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Tokei_Step_0x80AD5BB0/func_80AD63F8.asm") +void ObjTokeiStep_InitSteps(ObjTokeiStep* this) { + s32 i; + ObjTokeiStepPanel* panel; + Vec3f panelOffset; + s32 pad; -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Tokei_Step_0x80AD5BB0/func_80AD642C.asm") + SysMatrix_SetStateRotationAndTranslation(this->dyna.actor.world.pos.x, this->dyna.actor.world.pos.y, + this->dyna.actor.world.pos.z, &this->dyna.actor.shape.rot); -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Tokei_Step_0x80AD5BB0/func_80AD6480.asm") + panelOffset.x = 0.0f; + panelOffset.y = 0.0f; + for (i = 0; i < 7; i++) { + panel = &this->panels[i]; + panelOffset.z = i * -20.0f; + SysMatrix_MultiplyVector3fByState(&panelOffset, &panel->pos); + panel->posChangeY = 0.0f; + panel->numBounces = 0; + } +} -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Tokei_Step_0x80AD5BB0/func_80AD64A4.asm") +void ObjTokeiStep_InitStepsOpen(ObjTokeiStep* this) { + s32 i; + ObjTokeiStepPanel* panel; + Vec3f panelOffset; -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Tokei_Step_0x80AD5BB0/ObjTokeiStep_Update.asm") + SysMatrix_SetStateRotationAndTranslation(this->dyna.actor.world.pos.x, this->dyna.actor.world.pos.y, + this->dyna.actor.world.pos.z, &this->dyna.actor.shape.rot); -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Tokei_Step_0x80AD5BB0/ObjTokeiStep_Draw.asm") + panelOffset.x = 0.0f; + for (i = 0; i < 7; i++) { + panel = &this->panels[i]; + panelOffset.y = panelXOffsets[i]; + panelOffset.z = i * -20.0f; + SysMatrix_MultiplyVector3fByState(&panelOffset, &panel->pos); + } +} -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Tokei_Step_0x80AD5BB0/func_80AD6508.asm") +void ObjTokeiStep_InitTimers(ObjTokeiStep* this) { + s32 i; + + this->panels[0].startFallingTimer = 0; + for (i = 1; i < 7; i++) { + this->panels[i].startFallingTimer = 10; + } +} + +s32 ObjTokeiStep_OpenProcess(ObjTokeiStep* this, GlobalContext* globalCtx) { + ObjTokeiStep* this2 = this; + s32 i; + ObjTokeiStepPanel* panel; + f32 finalPosY; + s32 isOpen = 1; + s32 prevBounced = 1; + + for (i = 0; i < 7; i++) { + panel = &this->panels[i]; + if (prevBounced && panel->startFallingTimer > 0) { + panel->startFallingTimer--; + isOpen = 0; + } + if (prevBounced && panel->numBounces < 3 && panel->startFallingTimer <= 0) { + finalPosY = panelXOffsets[i] + this->dyna.actor.world.pos.y; + if (!panel->hasSoundPlayed) { + Audio_PlayActorSound2(&this->dyna.actor, 0x2945); + panel->hasSoundPlayed = true; + } + panel->posChangeY += -2.5f; + panel->posChangeY *= 0.83f; + panel->pos.y += panel->posChangeY; + isOpen = 0; + if (panel->pos.y < finalPosY) { + panel->numBounces++; + if (panel->numBounces >= 3) { + panel->pos.y = finalPosY; + } else { + panel->posChangeY *= -0.4f; + if (panel->posChangeY > 4.0f) { + panel->posChangeY = 4.0f; + } + panel->pos.y = (panel->pos.y - finalPosY) * -0.4f; + if (panel->posChangeY < panel->pos.y) { + panel->pos.y = panel->posChangeY + finalPosY; + } else { + panel->pos.y += finalPosY; + } + if (panel->numBounces == 1) { + ObjTokeiStep_SpawnDust(this2, panel, globalCtx); + ObjTokeiStep_AddQuake(this2, globalCtx); + } + } + } + } + prevBounced = panel->numBounces > 0; + } + return isOpen; +} + +void ObjTokeiStep_Init(Actor* thisx, GlobalContext* globalCtx) { + ObjTokeiStep* this = THIS; + + Actor_ProcessInitChain(&this->dyna.actor, sInitChain); + BcCheck3_BgActorInit(&this->dyna, 0); + if ((globalCtx->sceneNum == 0x6F) && (gSaveContext.extra.sceneSetupIndex == 2) && (globalCtx->csCtx.unk12 == 0)) { + BgCheck3_LoadMesh(globalCtx, &this->dyna, &D_06000968); + ObjTokeiStep_InitSteps(this); + ObjTokeiStep_SetupBeginOpen(this); + } else if (!((((s32)gSaveContext.perm.day % 5) != 3) || (gSaveContext.perm.time >= 0x4000)) || + (s32)gSaveContext.perm.day >= 4) { + this->dyna.actor.draw = ObjTokeiStep_DrawOpen; + ObjTokeiStep_InitStepsOpen(this); + ObjTokeiStep_SetupDoNothingOpen(this); + } else { + BgCheck3_LoadMesh(globalCtx, &this->dyna, &D_06000968); + ObjTokeiStep_InitSteps(this); + ObjTokeiStep_SetupDoNothing(this); + } +} + +void ObjTokeiStep_Destroy(Actor* thisx, GlobalContext* globalCtx) { + ObjTokeiStep* this = THIS; + + BgCheck_RemoveActorMesh(globalCtx, &globalCtx->colCtx.dyna, this->dyna.bgId); +} + +void ObjTokeiStep_SetupBeginOpen(ObjTokeiStep* this) { + this->actionFunc = ObjTokeiStep_BeginOpen; +} + +void ObjTokeiStep_BeginOpen(ObjTokeiStep* this, GlobalContext* globalCtx) { + CsCmdActorAction* action; + + if (func_800EE29C(globalCtx, 0x86)) { + action = globalCtx->csCtx.actorActions[func_800EE200(globalCtx, 0x86)]; + if ((globalCtx->csCtx.frames == (*action).startFrame) && action->unk0) { + this->dyna.actor.draw = ObjTokeiStep_DrawOpen; + ObjTokeiStep_SetupOpen(this); + } + } +} + +void ObjTokeiStep_SetupDoNothing(ObjTokeiStep* this) { + this->actionFunc = ObjTokeiStep_DoNothing; +} + +void ObjTokeiStep_DoNothing(ObjTokeiStep* this, GlobalContext* globalCtx) { +} + +void ObjTokeiStep_SetupOpen(ObjTokeiStep* this) { + ObjTokeiStep_InitTimers(this); + this->actionFunc = ObjTokeiStep_Open; +} + +void ObjTokeiStep_Open(ObjTokeiStep* this, GlobalContext* globalCtx) { + if (ObjTokeiStep_OpenProcess(this, globalCtx)) { + func_800C62BC(globalCtx, &globalCtx->colCtx.dyna, this->dyna.bgId); + ObjTokeiStep_SetupDoNothingOpen(this); + } +} + +void ObjTokeiStep_SetupDoNothingOpen(ObjTokeiStep* this) { + this->dyna.actor.flags &= ~0x10; + this->actionFunc = ObjTokeiStep_DoNothingOpen; +} + +void ObjTokeiStep_DoNothingOpen(ObjTokeiStep* this, GlobalContext* globalCtx) { +} + +void ObjTokeiStep_Update(Actor* thisx, GlobalContext* globalCtx) { + ObjTokeiStep* this = THIS; + + this->actionFunc(this, globalCtx); +} + +void ObjTokeiStep_Draw(Actor* thisx, GlobalContext* globalCtx) { + ObjTokeiStep* this = THIS; + + func_800BDFC0(globalCtx, D_06000088); +} + +void ObjTokeiStep_DrawOpen(Actor* thisx, GlobalContext* globalCtx) { + ObjTokeiStep* this = THIS; + int i; + ObjTokeiStepPanel* panel; + Gfx* gfx; + + OPEN_DISPS(globalCtx->state.gfxCtx); + gfx = POLY_OPA_DISP; + gSPDisplayList(gfx++, &sSetupDL[6 * 0x19]); + + for (i = 0; i < 7; i++) { + panel = &this->panels[i]; + ObjTokeiStep_SetSysMatrix(panel); + gSPMatrix(gfx++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(gfx++, D_06000088); + } + POLY_OPA_DISP = gfx; + CLOSE_DISPS(globalCtx->state.gfxCtx); +} diff --git a/src/overlays/actors/ovl_Obj_Tokei_Step/z_obj_tokei_step.h b/src/overlays/actors/ovl_Obj_Tokei_Step/z_obj_tokei_step.h index dac311185..04deba690 100644 --- a/src/overlays/actors/ovl_Obj_Tokei_Step/z_obj_tokei_step.h +++ b/src/overlays/actors/ovl_Obj_Tokei_Step/z_obj_tokei_step.h @@ -5,9 +5,22 @@ struct ObjTokeiStep; +typedef void (*ObjTokeiStepFunc)(struct ObjTokeiStep*, struct GlobalContext*); + +typedef struct ObjTokeiStepPanel { + /* 0x00 */ Vec3f pos; + /* 0x0C */ f32 posChangeY; + /* 0x10 */ s16 startFallingTimer; // Timer for when a step starts falling after the previous step has started + // bouncing during opening cutscene + /* 0x12 */ s8 numBounces; // Counter for times the step falls below its final Y pos, and thus will bounce back up + // during opening cutscene + /* 0x13 */ s8 hasSoundPlayed; +} ObjTokeiStepPanel; // size = 0x14 + typedef struct ObjTokeiStep { - /* 0x000 */ Actor actor; - /* 0x144 */ char unk_144[0xA8]; + /* 0x000 */ DynaPolyActor dyna; + /* 0x15c */ ObjTokeiStepFunc actionFunc; + /* 0x160 */ ObjTokeiStepPanel panels[7]; } ObjTokeiStep; // size = 0x1EC extern const ActorInit Obj_Tokei_Step_InitVars; diff --git a/tables/functions.txt b/tables/functions.txt index 24035a7a3..d75205e1a 100644 --- a/tables/functions.txt +++ b/tables/functions.txt @@ -12223,26 +12223,26 @@ 0x80AD5584:("func_80AD5584",), 0x80AD566C:("func_80AD566C",), 0x80AD56E8:("func_80AD56E8",), - 0x80AD5BB0:("func_80AD5BB0",), - 0x80AD5BE8:("func_80AD5BE8",), - 0x80AD5C70:("func_80AD5C70",), - 0x80AD5DFC:("func_80AD5DFC",), - 0x80AD5EB8:("func_80AD5EB8",), - 0x80AD5F70:("func_80AD5F70",), - 0x80AD5FB0:("func_80AD5FB0",), + 0x80AD5BB0:("ObjTokeiStep_SetSysMatrix",), + 0x80AD5BE8:("ObjTokeiStep_AddQuake",), + 0x80AD5C70:("ObjTokeiStep_SpawnDust",), + 0x80AD5DFC:("ObjTokeiStep_InitSteps",), + 0x80AD5EB8:("ObjTokeiStep_InitStepsOpen",), + 0x80AD5F70:("ObjTokeiStep_InitTimers",), + 0x80AD5FB0:("ObjTokeiStep_OpenProcess",), 0x80AD61EC:("ObjTokeiStep_Init",), 0x80AD6314:("ObjTokeiStep_Destroy",), - 0x80AD6348:("func_80AD6348",), - 0x80AD635C:("func_80AD635C",), - 0x80AD63D4:("func_80AD63D4",), - 0x80AD63E8:("func_80AD63E8",), - 0x80AD63F8:("func_80AD63F8",), - 0x80AD642C:("func_80AD642C",), - 0x80AD6480:("func_80AD6480",), - 0x80AD64A4:("func_80AD64A4",), + 0x80AD6348:("ObjTokeiStep_SetupBeginOpen",), + 0x80AD635C:("ObjTokeiStep_BeginOpen",), + 0x80AD63D4:("ObjTokeiStep_SetupDoNothing",), + 0x80AD63E8:("ObjTokeiStep_DoNothing",), + 0x80AD63F8:("ObjTokeiStep_SetupOpen",), + 0x80AD642C:("ObjTokeiStep_Open",), + 0x80AD6480:("ObjTokeiStep_SetupDoNothingOpen",), + 0x80AD64A4:("ObjTokeiStep_DoNothingOpen",), 0x80AD64B4:("ObjTokeiStep_Update",), 0x80AD64D8:("ObjTokeiStep_Draw",), - 0x80AD6508:("func_80AD6508",), + 0x80AD6508:("ObjTokeiStep_DrawOpen",), 0x80AD6760:("BgLotus_Init",), 0x80AD67FC:("BgLotus_Destroy",), 0x80AD6830:("func_80AD6830",),