diff --git a/linker_scripts/undefined_syms.ld b/linker_scripts/undefined_syms.ld index e02eac8a1a..0a04d9db2e 100644 --- a/linker_scripts/undefined_syms.ld +++ b/linker_scripts/undefined_syms.ld @@ -161,11 +161,6 @@ D_0407D590 = 0x0407D590; // segment 0x06 -// ovl_Bg_Dblue_Elevator - -D_060002C8 = 0x060002C8; -D_060005C4 = 0x060005C4; - // ovl_Boss_07 D_06000194 = 0x06000194; diff --git a/spec b/spec index b4fd803de9..02f87f2585 100644 --- a/spec +++ b/spec @@ -3976,8 +3976,7 @@ beginseg name "ovl_Bg_Dblue_Elevator" compress include "$(BUILD_DIR)/src/overlays/actors/ovl_Bg_Dblue_Elevator/z_bg_dblue_elevator.o" - include "$(BUILD_DIR)/data/ovl_Bg_Dblue_Elevator/ovl_Bg_Dblue_Elevator.data.o" - include "$(BUILD_DIR)/data/ovl_Bg_Dblue_Elevator/ovl_Bg_Dblue_Elevator.reloc.o" + include "$(BUILD_DIR)/src/overlays/actors/ovl_Bg_Dblue_Elevator/ovl_Bg_Dblue_Elevator_reloc.o" endseg beginseg diff --git a/src/overlays/actors/ovl_Bg_Dblue_Elevator/z_bg_dblue_elevator.c b/src/overlays/actors/ovl_Bg_Dblue_Elevator/z_bg_dblue_elevator.c index a15460cc8f..5e935b0682 100644 --- a/src/overlays/actors/ovl_Bg_Dblue_Elevator/z_bg_dblue_elevator.c +++ b/src/overlays/actors/ovl_Bg_Dblue_Elevator/z_bg_dblue_elevator.c @@ -5,17 +5,29 @@ */ #include "z_bg_dblue_elevator.h" +#include "objects/object_dblue_object/object_dblue_object.h" #define FLAGS (ACTOR_FLAG_10) #define THIS ((BgDblueElevator*)thisx) -void BgDblueElevator_Init(Actor* thisx, PlayState* play); +void BgDblueElevator_SpawnRipplesAndSplashes(BgDblueElevator* this, PlayState* play); +void BgDblueElevator_CheckWaterBoxInfo(BgDblueElevator* this, PlayState* play2); +s32 BgDblueElevator_GetWaterFlowFromCeiling(BgDblueElevator* this, PlayState* play); +s32 BgDblueElevator_GetWaterFlowFromPipes(BgDblueElevator* this, PlayState* play); + +void BgDblueElevator_Init(Actor* thisx, PlayState* play2); void BgDblueElevator_Destroy(Actor* thisx, PlayState* play); void BgDblueElevator_Update(Actor* thisx, PlayState* play); void BgDblueElevator_Draw(Actor* thisx, PlayState* play); -#if 0 +void BgDblueElevator_SetupWaitActivation(BgDblueElevator* this); +void BgDblueElevator_WaitActivation(BgDblueElevator* this, PlayState* play); +void BgDblueElevator_SetupPause(BgDblueElevator* this); +void BgDblueElevator_Pause(BgDblueElevator* this, PlayState* play); +void BgDblueElevator_SetupMove(BgDblueElevator* this); +void BgDblueElevator_Move(BgDblueElevator* this, PlayState* play); + ActorInit Bg_Dblue_Elevator_InitVars = { /**/ ACTOR_BG_DBLUE_ELEVATOR, /**/ ACTORCAT_BG, @@ -28,45 +40,299 @@ ActorInit Bg_Dblue_Elevator_InitVars = { /**/ BgDblueElevator_Draw, }; -// static InitChainEntry sInitChain[] = { -static InitChainEntry D_80B929EC[] = { +static BgDblueElevatorStruct1 D_80B92960[] = { + { false, BgDblueElevator_GetWaterFlowFromCeiling, 320.0f, 30, 1, 1.0f, 0.1f, 6.0f }, + { true, BgDblueElevator_GetWaterFlowFromCeiling, 195.0f, 30, 1, 1.0f, 0.1f, 5.0f }, + { false, BgDblueElevator_GetWaterFlowFromPipes, 280.0f, 30, 1, 1.0f, 0.1f, 6.0f }, + { false, BgDblueElevator_GetWaterFlowFromPipes, 280.0f, 30, -1, 1.0f, 0.1f, 6.0f }, +}; + +static s16 D_80B929D0[] = { -90, -90, 90, 90 }; +static s16 D_80B929D8[] = { -100, 90, 90, -100 }; +static s8 sLargeRipplesLives[] = { 0, 2, 4 }; +static s8 sSmallRipplesLives[] = { 0, 1, 2, 3, 4, 5 }; + +static InitChainEntry sInitChain[] = { ICHAIN_F32(uncullZoneForward, 4000, ICHAIN_CONTINUE), ICHAIN_F32(uncullZoneScale, 250, ICHAIN_CONTINUE), ICHAIN_F32(uncullZoneDownward, 250, ICHAIN_CONTINUE), ICHAIN_VEC3F_DIV1000(scale, 100, ICHAIN_STOP), }; -#endif +void BgDblueElevator_CheckWaterBoxInfo(BgDblueElevator* this, PlayState* play2) { + PlayState* play = play2; + WaterBox* waterBox; + s32 bgId; -extern InitChainEntry D_80B929EC[]; + this->isWithinWaterBoxXZ = + WaterBox_GetSurfaceImpl(play, &play->colCtx, this->dyna.actor.world.pos.x, this->dyna.actor.world.pos.z, + &this->waterSurfacePosY, &waterBox, &bgId); +} -extern UNK_TYPE D_060002C8; -extern UNK_TYPE D_060005C4; +void BgDblueElevator_SpawnRipplesAndSplashes(BgDblueElevator* this, PlayState* play) { + s32 i; + Vec3f ripplePos; + Vec3f splashPos; + s32 j; + f32 d1; + f32 d2; + f32 v1; + f32 v2; + f32 var_fs0; + s32 rand; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Dblue_Elevator/func_80B91F20.s") + Matrix_Push(); + Matrix_RotateYS(this->dyna.actor.shape.rot.y, MTXMODE_NEW); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Dblue_Elevator/func_80B91F74.s") + for (i = 0; i < ARRAY_COUNT(D_80B929D0) - 1; i++) { + v1 = D_80B929D0[i]; + v2 = D_80B929D8[i]; + d1 = D_80B929D0[i + 1] - D_80B929D0[i]; + d2 = D_80B929D8[i + 1] - D_80B929D8[i]; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Dblue_Elevator/func_80B922C0.s") + for (j = 0; j < 7; j++) { + ripplePos.x = ((d1 * j) * (1.0f / 7.0f)) + v1; + ripplePos.y = this->waterSurfacePosY; + ripplePos.z = ((d2 * j) * (1.0f / 7.0f)) + v2; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Dblue_Elevator/func_80B922FC.s") + ripplePos.x += (Rand_ZeroOne() - 0.5f) * 20.0f; + ripplePos.z += (Rand_ZeroOne() - 0.5f) * 20.0f; + Matrix_MultVec3f(&ripplePos, &splashPos); + splashPos.x += this->dyna.actor.world.pos.x; + splashPos.z += this->dyna.actor.world.pos.z; + EffectSsGSplash_Spawn(play, &splashPos, NULL, NULL, 0, (Rand_ZeroOne() * 400.0f) + 210.0f); + } + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Dblue_Elevator/BgDblueElevator_Init.s") + for (i = 0; i < ARRAY_COUNT(sLargeRipplesLives); i++) { + ripplePos.x = ((Rand_ZeroOne() - 0.5f) * 60.0f) + this->dyna.actor.world.pos.x; + ripplePos.y = this->waterSurfacePosY; + ripplePos.z = ((Rand_ZeroOne() - 0.5f) * 60.0f) + this->dyna.actor.world.pos.z; + EffectSsGRipple_Spawn(play, &ripplePos, 1000, 3000, sLargeRipplesLives[i]); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Dblue_Elevator/BgDblueElevator_Destroy.s") + for (i = 0; i < ARRAY_COUNT(sSmallRipplesLives); i++) { + var_fs0 = Rand_ZeroOne(); + var_fs0 = 1.0f - (var_fs0 * var_fs0); + rand = Rand_Next(); + if (rand > 0) { + var_fs0 = -var_fs0; + } + ripplePos.x = (var_fs0 * 100.0f) + this->dyna.actor.world.pos.x; + ripplePos.y = this->waterSurfacePosY; + var_fs0 = Rand_ZeroOne(); + var_fs0 = 1.0f - (var_fs0 * var_fs0); + rand = Rand_Next(); + if (rand > 0) { + var_fs0 = -var_fs0; + } + ripplePos.z = (var_fs0 * 100.0f) + this->dyna.actor.world.pos.z; + EffectSsGRipple_Spawn(play, &ripplePos, 400, 800, sSmallRipplesLives[i]); + } + Matrix_Pop(); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Dblue_Elevator/func_80B924DC.s") +s32 BgDblueElevator_GetWaterFlowFromCeiling(BgDblueElevator* this, PlayState* play) { + Actor* thisx = &this->dyna.actor; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Dblue_Elevator/func_80B924F8.s") + if (Flags_GetSwitch(play, BG_DBLUE_ELEVATOR_GET_SWITCH_FLAG(thisx, 0))) { + return BG_DBLUE_ELEVATOR_WATER_FLOW_STOPPED; + } + return BG_DBLUE_ELEVATOR_WATER_FLOW_FORWARD; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Dblue_Elevator/func_80B9257C.s") +s32 BgDblueElevator_GetWaterFlowFromPipes(BgDblueElevator* this, PlayState* play) { + Actor* thisx = &this->dyna.actor; + s32 waterFlow = BG_DBLUE_ELEVATOR_WATER_FLOW_STOPPED; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Dblue_Elevator/func_80B925B8.s") + // This checks if the first the yellow tank turnkey is open. + if (!Flags_GetSwitch(play, BG_DBLUE_ELEVATOR_GET_SWITCH_FLAG(thisx, 0))) { + waterFlow = BG_DBLUE_ELEVATOR_WATER_FLOW_FORWARD; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Dblue_Elevator/func_80B92644.s") + // This checks if water is flowing from the red pipes. + if (Flags_GetSwitch(play, BG_DBLUE_ELEVATOR_GET_SWITCH_FLAG(thisx, 1)) && + Flags_GetSwitch(play, BG_DBLUE_ELEVATOR_GET_SWITCH_FLAG(thisx, 2)) && + Flags_GetSwitch(play, BG_DBLUE_ELEVATOR_GET_SWITCH_FLAG(thisx, 3))) { + waterFlow += BG_DBLUE_ELEVATOR_WATER_FLOW_REVERSED; + } + return waterFlow; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Dblue_Elevator/func_80B92660.s") +void BgDblueElevator_Init(Actor* thisx, PlayState* play2) { + BgDblueElevator* this = THIS; + PlayState* play = play2; + s32 index = BG_DBLUE_ELEVATOR_GET_INDEX(&this->dyna.actor); + BgDblueElevatorStruct1* ptr = &D_80B92960[index]; + s32 waterFlow; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Dblue_Elevator/BgDblueElevator_Update.s") + Actor_ProcessInitChain(&this->dyna.actor, sInitChain); + DynaPolyActor_Init(&this->dyna, DYNA_TRANSFORM_POS); + DynaPolyActor_LoadMesh(play, &this->dyna, &gGreatBayTempleObjectElevatorCol); + waterFlow = ptr->getWaterFlow(this, play); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Dblue_Elevator/BgDblueElevator_Draw.s") + if (waterFlow == BG_DBLUE_ELEVATOR_WATER_FLOW_REVERSED) { + this->direction = -ptr->initialDirection; + } else { + this->direction = ptr->initialDirection; + } + + BgDblueElevator_CheckWaterBoxInfo(this, play); + + if ((waterFlow == BG_DBLUE_ELEVATOR_WATER_FLOW_STOPPED) || + (waterFlow == BG_DBLUE_ELEVATOR_WATER_FLOW_BOTH_DIRECTIONS)) { + BgDblueElevator_SetupWaitActivation(this); + } else { + BgDblueElevator_SetupMove(this); + } +} + +void BgDblueElevator_Destroy(Actor* thisx, PlayState* play) { + BgDblueElevator* this = THIS; + + DynaPoly_DeleteBgActor(play, &play->colCtx.dyna, this->dyna.bgId); +} + +void BgDblueElevator_SetupWaitActivation(BgDblueElevator* this) { + this->activationTimer = 60; + this->actionFunc = BgDblueElevator_WaitActivation; +} + +/** + * The elevator waits for 3 seconds (60 frames) when water restarts flowing before resuming its halted cycle. + */ +void BgDblueElevator_WaitActivation(BgDblueElevator* this, PlayState* play) { + s32 waterFlow; + s32 index = BG_DBLUE_ELEVATOR_GET_INDEX(&this->dyna.actor); + + waterFlow = D_80B92960[index].getWaterFlow(this, play); + if ((waterFlow == BG_DBLUE_ELEVATOR_WATER_FLOW_STOPPED) || + (waterFlow == BG_DBLUE_ELEVATOR_WATER_FLOW_BOTH_DIRECTIONS)) { + this->activationTimer = 60; + } else { + this->activationTimer--; + if (this->activationTimer <= 0) { + BgDblueElevator_SetupMove(this); + } + } +} + +void BgDblueElevator_SetupPause(BgDblueElevator* this) { + s32 index = BG_DBLUE_ELEVATOR_GET_INDEX(&this->dyna.actor); + BgDblueElevatorStruct1* ptr = &D_80B92960[index]; + + this->pauseTimer = ptr->pauseDuration; + this->actionFunc = BgDblueElevator_Pause; +} + +/** + * As the elevator cycles up and down or sideways, it will pause for a set amount of time at each end of its path + * before moving again. + */ +void BgDblueElevator_Pause(BgDblueElevator* this, PlayState* play) { + s32 waterFlow; + s32 index = BG_DBLUE_ELEVATOR_GET_INDEX(&this->dyna.actor); + + waterFlow = D_80B92960[index].getWaterFlow(this, play); + if ((waterFlow == BG_DBLUE_ELEVATOR_WATER_FLOW_STOPPED) || + (waterFlow == BG_DBLUE_ELEVATOR_WATER_FLOW_BOTH_DIRECTIONS)) { + BgDblueElevator_SetupWaitActivation(this); + } else { + this->pauseTimer--; + if (this->pauseTimer <= 0) { + BgDblueElevator_SetupMove(this); + } + } +} + +void BgDblueElevator_SetupMove(BgDblueElevator* this) { + this->actionFunc = BgDblueElevator_Move; + this->posStep = 0.0f; +} + +void BgDblueElevator_Move(BgDblueElevator* this, PlayState* play) { + s32 index = BG_DBLUE_ELEVATOR_GET_INDEX(&this->dyna.actor); + BgDblueElevatorStruct1* ptr = &D_80B92960[index]; + s32 waterFlow = ptr->getWaterFlow(this, play); + + f32 targetPosOffset; + s32 hasReachedEnd; + s32 isDeactivated; + f32 posStep; + + Vec3f basePosOffset; + Vec3f posOffset; + f32 nearWaterSurfaceCheck; + + s32 pad; + + if ((waterFlow == BG_DBLUE_ELEVATOR_WATER_FLOW_STOPPED) || + (waterFlow == BG_DBLUE_ELEVATOR_WATER_FLOW_BOTH_DIRECTIONS)) { + isDeactivated = Math_StepToF(&this->posStep, 0.0f, ptr->decelerationStep); + } else { + isDeactivated = false; + Math_StepToF(&this->posStep, ptr->targetPosStep, ptr->accelerationStep); + } + + if (this->direction > 0) { + targetPosOffset = ptr->targetPosOffset; + } else { + targetPosOffset = -ptr->targetPosOffset; + } + + if (this->posStep <= 1.1f) { + posStep = 1.1f; + } else { + posStep = this->posStep; + } + + if (Math_SmoothStepToF(&this->posOffset, targetPosOffset, 0.4f, posStep, 1.0f) < 0.001f) { + hasReachedEnd = true; + } else { + hasReachedEnd = false; + } + + if (!ptr->isHorizontal) { + this->dyna.actor.world.pos.y = this->posOffset + this->dyna.actor.home.pos.y; + if (CHECK_FLAG_ALL(this->dyna.actor.flags, ACTOR_FLAG_40) && (this->isWithinWaterBoxXZ)) { + if (this->direction > 0) { + nearWaterSurfaceCheck = ((this->dyna.actor.world.pos.y + -10.0f) - this->waterSurfacePosY) * + ((this->dyna.actor.prevPos.y + -10.0f) - this->waterSurfacePosY); + } else { + nearWaterSurfaceCheck = ((this->dyna.actor.world.pos.y + -30.0f) - this->waterSurfacePosY) * + ((this->dyna.actor.prevPos.y + -30.0f) - this->waterSurfacePosY); + } + if (nearWaterSurfaceCheck <= 0.0f) { + BgDblueElevator_SpawnRipplesAndSplashes(this, play); + } + } + } else { + Matrix_RotateYS(this->dyna.actor.shape.rot.y, MTXMODE_NEW); + basePosOffset.x = this->posOffset; + basePosOffset.y = 0.0f; + basePosOffset.z = 0.0f; + Matrix_MultVec3f(&basePosOffset, &posOffset); + Math_Vec3f_Sum(&this->dyna.actor.home.pos, &posOffset, &this->dyna.actor.world.pos); + } + + if (isDeactivated) { + BgDblueElevator_SetupWaitActivation(this); + } else { + if (hasReachedEnd) { + this->direction = -this->direction; + BgDblueElevator_SetupPause(this); + } + } +} + +void BgDblueElevator_Update(Actor* thisx, PlayState* play) { + BgDblueElevator* this = THIS; + + this->actionFunc(this, play); +} + +void BgDblueElevator_Draw(Actor* thisx, PlayState* play) { + BgDblueElevator* this = THIS; + + Gfx_DrawDListOpa(play, gGreatBayTempleObjectElevatorDL); +} diff --git a/src/overlays/actors/ovl_Bg_Dblue_Elevator/z_bg_dblue_elevator.h b/src/overlays/actors/ovl_Bg_Dblue_Elevator/z_bg_dblue_elevator.h index 89a18dd0ca..dfec43c5cd 100644 --- a/src/overlays/actors/ovl_Bg_Dblue_Elevator/z_bg_dblue_elevator.h +++ b/src/overlays/actors/ovl_Bg_Dblue_Elevator/z_bg_dblue_elevator.h @@ -3,15 +3,45 @@ #include "global.h" +#define BG_DBLUE_ELEVATOR_GET_INDEX(thisx) (((thisx)->params >> 8) & 0x3) +#define BG_DBLUE_ELEVATOR_GET_SWITCH_FLAG(thisx, x) (((thisx)->params + (x)) & 0x7F) + +typedef enum { + /* 0 */ BG_DBLUE_ELEVATOR_WATER_FLOW_STOPPED, + /* 1 */ BG_DBLUE_ELEVATOR_WATER_FLOW_FORWARD, + /* 2 */ BG_DBLUE_ELEVATOR_WATER_FLOW_REVERSED, + /* 3 */ BG_DBLUE_ELEVATOR_WATER_FLOW_BOTH_DIRECTIONS +} BgDblueElevatorWaterFlow; + struct BgDblueElevator; typedef void (*BgDblueElevatorActionFunc)(struct BgDblueElevator*, PlayState*); typedef struct BgDblueElevator { - /* 0x000 */ Actor actor; - /* 0x144 */ char unk_144[0x18]; + /* 0x000 */ DynaPolyActor dyna; /* 0x15C */ BgDblueElevatorActionFunc actionFunc; - /* 0x160 */ char unk_160[0x10]; + /* 0x160 */ f32 posStep; + /* 0x164 */ f32 posOffset; + /* 0x168 */ s8 direction; + /* 0x169 */ s8 activationTimer; + /* 0x16A */ s8 pauseTimer; + /* 0x16B */ s8 isWithinWaterBoxXZ; + /* 0x16C */ f32 waterSurfacePosY; } BgDblueElevator; // size = 0x170 +struct BgDblueElevatorStruct1; + +typedef s32 (*BgDblueElevatorStruct1Func)(struct BgDblueElevator*, PlayState*); + +typedef struct BgDblueElevatorStruct1 { + /* 0x00 */ s32 isHorizontal; + /* 0x04 */ BgDblueElevatorStruct1Func getWaterFlow; + /* 0x08 */ f32 targetPosOffset; + /* 0x0C */ s8 pauseDuration; + /* 0x0D */ s8 initialDirection; + /* 0x10 */ f32 accelerationStep; + /* 0x14 */ f32 decelerationStep; + /* 0x18 */ f32 targetPosStep; +} BgDblueElevatorStruct1; // size = 0x1C + #endif // Z_BG_DBLUE_ELEVATOR_H diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt index f0383c304f..c8ff529b64 100644 --- a/tools/disasm/functions.txt +++ b/tools/disasm/functions.txt @@ -14819,18 +14819,18 @@ 0x80B91D80:("ObjTokeiTurret_Destroy",), 0x80B91DB4:("ObjTokeiTurret_Update",), 0x80B91DC4:("ObjTokeiTurret_Draw",), - 0x80B91F20:("func_80B91F20",), - 0x80B91F74:("func_80B91F74",), - 0x80B922C0:("func_80B922C0",), - 0x80B922FC:("func_80B922FC",), + 0x80B91F20:("BgDblueElevator_CheckWaterBoxInfo",), + 0x80B91F74:("BgDblueElevator_SpawnRipplesAndSplashes",), + 0x80B922C0:("BgDblueElevator_GetWaterFlowFromCeiling",), + 0x80B922FC:("BgDblueElevator_GetWaterFlowFromPipes",), 0x80B923A4:("BgDblueElevator_Init",), 0x80B924A8:("BgDblueElevator_Destroy",), - 0x80B924DC:("func_80B924DC",), - 0x80B924F8:("func_80B924F8",), - 0x80B9257C:("func_80B9257C",), - 0x80B925B8:("func_80B925B8",), - 0x80B92644:("func_80B92644",), - 0x80B92660:("func_80B92660",), + 0x80B924DC:("BgDblueElevator_SetupWaitActivation",), + 0x80B924F8:("BgDblueElevator_WaitActivation",), + 0x80B9257C:("BgDblueElevator_SetupPause",), + 0x80B925B8:("BgDblueElevator_Pause",), + 0x80B92644:("BgDblueElevator_SetupMove",), + 0x80B92660:("BgDblueElevator_Move",), 0x80B928E0:("BgDblueElevator_Update",), 0x80B92904:("BgDblueElevator_Draw",), 0x80B92B10:("ObjWarpstone_SetupAction",),