diff --git a/linker_scripts/code_script.txt b/linker_scripts/code_script.txt index c78e37e0b1..b87ba27fb4 100644 --- a/linker_scripts/code_script.txt +++ b/linker_scripts/code_script.txt @@ -1754,9 +1754,9 @@ SECTIONS ovl_Bg_Ctower_Rot : AT(RomLocation) { build/src/overlays/actors/ovl_Bg_Ctower_Rot/z_bg_ctower_rot.o(.text) - build/asm/overlays/ovl_Bg_Ctower_Rot_data.o(.data) + build/src/overlays/actors/ovl_Bg_Ctower_Rot/z_bg_ctower_rot.o(.data) build/src/overlays/actors/ovl_Bg_Ctower_Rot/z_bg_ctower_rot.o(.rodata) - build/asm/overlays/ovl_Bg_Ctower_Rot_rodata.o(.rodata) + build/src/overlays/actors/ovl_Bg_Ctower_Rot/z_bg_ctower_rot_overlay.o(.ovl) } SegmentEnd = .; SegmentSize = SegmentEnd - SegmentStart; diff --git a/linker_scripts/object_script.txt b/linker_scripts/object_script.txt index 48c8242143..3c5cf38a82 100644 --- a/linker_scripts/object_script.txt +++ b/linker_scripts/object_script.txt @@ -227,6 +227,15 @@ D_06017018 = 0x06017018; D_06018118 = 0x06018118; D_06018588 = 0x06018588; +/* z_bg_ctower_rot */ +D_060129D0 = 0x060129D0; +D_06012DA0 = 0x06012DA0; +D_060142E8 = 0x060142E8; +D_06017220 = 0x06017220; +D_06017410 = 0x06017410; +D_060174E0 = 0x060174E0; +D_06017650 = 0x06017650; + /* z_en_warp_uzu */ D_06000EC0 = 0x06000EC0; diff --git a/src/overlays/actors/ovl_Bg_Ctower_Rot/z_bg_ctower_rot.c b/src/overlays/actors/ovl_Bg_Ctower_Rot/z_bg_ctower_rot.c index e64a9948f4..9083fa13d8 100644 --- a/src/overlays/actors/ovl_Bg_Ctower_Rot/z_bg_ctower_rot.c +++ b/src/overlays/actors/ovl_Bg_Ctower_Rot/z_bg_ctower_rot.c @@ -1,3 +1,9 @@ +/* + * File: z_bg_ctower_rot.c + * Overlay: ovl_Bg_CtowerRot + * Description: Twisting path along with the Doors to Clocktower + */ + #include "z_bg_ctower_rot.h" #define FLAGS 0x00000030 @@ -9,7 +15,11 @@ void BgCtowerRot_Destroy(Actor* thisx, GlobalContext* globalCtx); void BgCtowerRot_Update(Actor* thisx, GlobalContext* globalCtx); void BgCtowerRot_Draw(Actor* thisx, GlobalContext* globalCtx); -/* +void BgCtowerRot_CorridorRotate(BgCtowerRot* this, GlobalContext* globalCtx); +void BgCtowerRot_DoorDoNothing(BgCtowerRot* this, GlobalContext* globalCtx); +void BgCtowerRot_DoorIdle(BgCtowerRot* this, GlobalContext* globalCtx); +void BgCtowerRot_SetupDoorClose(BgCtowerRot* this, GlobalContext* globalCtx); + const ActorInit Bg_Ctower_Rot_InitVars = { ACTOR_BG_CTOWER_ROT, ACTORCAT_BG, @@ -21,22 +31,142 @@ const ActorInit Bg_Ctower_Rot_InitVars = { (ActorFunc)BgCtowerRot_Update, (ActorFunc)BgCtowerRot_Draw, }; -*/ -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Bg_Ctower_Rot_0x808E2070/BgCtowerRot_Init.asm") +extern Gfx D_060129D0[]; -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Bg_Ctower_Rot_0x808E2070/BgCtowerRot_Destroy.asm") +extern Gfx D_06012DA0[]; -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Bg_Ctower_Rot_0x808E2070/func_808E21FC.asm") +extern CollisionHeader D_060142E8; -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Bg_Ctower_Rot_0x808E2070/func_808E22DC.asm") +extern Gfx D_06017220[]; -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Bg_Ctower_Rot_0x808E2070/func_808E22EC.asm") +extern CollisionHeader D_06017410; -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Bg_Ctower_Rot_0x808E2070/func_808E23D0.asm") +extern Gfx D_060174E0[]; -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Bg_Ctower_Rot_0x808E2070/func_808E2444.asm") +extern CollisionHeader D_06017650; -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Bg_Ctower_Rot_0x808E2070/BgCtowerRot_Update.asm") +static InitChainEntry sInitChain[] = { + ICHAIN_VEC3F_DIV1000(scale, 100, ICHAIN_STOP), +}; -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Bg_Ctower_Rot_0x808E2070/BgCtowerRot_Draw.asm") +static Gfx* bgCtowerRotDlists[] = { D_06012DA0, D_06017220, D_060174E0 }; + +void BgCtowerRot_Init(Actor* thisx, GlobalContext* globalCtx) { + BgCtowerRot* this = THIS; + s32 pad; + ActorPlayer* player; + Vec3f offset; + + Actor_ProcessInitChain(&this->dyna.actor, sInitChain); + BcCheck3_BgActorInit(&this->dyna, 1); + if (this->dyna.actor.params == CORRIDOR) { + BgCheck3_LoadMesh(globalCtx, &this->dyna, &D_060142E8); + this->actionFunc = BgCtowerRot_CorridorRotate; + return; + } + player = PLAYER; + if (this->dyna.actor.params == MAIN_DOOR) { + BgCheck3_LoadMesh(globalCtx, &this->dyna, &D_06017410); + this->dyna.actor.world.rot.y = this->dyna.actor.shape.rot.y + 0x4000; + } else { + BgCheck3_LoadMesh(globalCtx, &this->dyna, &D_06017650); + this->dyna.actor.world.rot.y = this->dyna.actor.shape.rot.y - 0x4000; + } + Actor_CalcOffsetOrientedToDrawRotation(&this->dyna.actor, &offset, &player->base.world.pos); + if (offset.z < 0.0f) { + this->dyna.actor.world.pos.x = this->dyna.actor.home.pos.x + (Math_SinS(this->dyna.actor.world.rot.y) * 80.0f); + this->dyna.actor.world.pos.z = this->dyna.actor.home.pos.z + (Math_CosS(this->dyna.actor.world.rot.y) * 80.0f); + this->timer = 80.0f; + this->actionFunc = BgCtowerRot_DoorIdle; + } else { + this->actionFunc = BgCtowerRot_DoorDoNothing; + } +} + +void BgCtowerRot_Destroy(Actor* thisx, GlobalContext* globalCtx) { + BgCtowerRot* this = THIS; + + BgCheck_RemoveActorMesh(globalCtx, &globalCtx->colCtx.dyna, this->dyna.bgId); +} + +void BgCtowerRot_CorridorRotate(BgCtowerRot* this, GlobalContext* globalCtx) { + ActorPlayer* player = PLAYER; + Vec3f offset; + f32 rotZ; + f32 offsetDiffZ; + f32 rotZtmp; + + Actor_CalcOffsetOrientedToDrawRotation(&this->dyna.actor, &offset, &player->base.world.pos); + if (offset.z > 1100.0f) { + rotZ = 0.0f; + } else { + offsetDiffZ = 1100.0f - offset.z; + rotZtmp = (offsetDiffZ > 1000.0f) + ? 1000.0f + : offsetDiffZ; // Removing rotZtmp just causes regalloc issues and a missing instruction + rotZ = rotZtmp; + } + func_800DFAC8(globalCtx->cameraPtrs[0], 0x11); + this->dyna.actor.shape.rot.z = rotZ * 16.384f; + if (globalCtx->csCtx.frames == 0x84) { + play_sound(0x4859); + } +} + +void BgCtowerRot_DoorDoNothing(BgCtowerRot* this, GlobalContext* globalCtx) { +} + +void BgCtowerRot_DoorClose(BgCtowerRot* this, GlobalContext* globalCtx) { + if (!Math_SmoothStepToF(&this->timer, 0.0f, 0.1f, 15.0f, 0.1f)) { + if (this->dyna.actor.params == MAIN_DOOR) { + Audio_PlayActorSound2(&this->dyna.actor, 0x2893); + ActorCutscene_Stop(this->dyna.actor.cutscene); + } + this->actionFunc = BgCtowerRot_DoorDoNothing; + } else if (this->dyna.actor.params == 1) { + func_800B9010(&this->dyna.actor, 0x201E); + } + this->dyna.actor.world.pos.x = + this->dyna.actor.home.pos.x + (Math_SinS(this->dyna.actor.world.rot.y) * this->timer); + this->dyna.actor.world.pos.z = + this->dyna.actor.home.pos.z + (Math_CosS(this->dyna.actor.world.rot.y) * this->timer); +} + +void BgCtowerRot_DoorIdle(BgCtowerRot* this, GlobalContext* globalCtx) { + ActorPlayer* player = PLAYER; + Vec3f offset; + + Actor_CalcOffsetOrientedToDrawRotation(&this->dyna.actor, &offset, &player->base.world.pos); + if (offset.z > 30.0f) { + this->unk160 = 0.0f; + ActorCutscene_SetIntentToPlay(this->dyna.actor.cutscene); + this->actionFunc = BgCtowerRot_SetupDoorClose; + } +} + +void BgCtowerRot_SetupDoorClose(BgCtowerRot* this, GlobalContext* globalCtx) { + if (ActorCutscene_GetCanPlayNext(this->dyna.actor.cutscene)) { + if (this->dyna.actor.params == MAIN_DOOR) { + ActorCutscene_StartAndSetUnkLinkFields(this->dyna.actor.cutscene, &this->dyna.actor); + } + this->actionFunc = BgCtowerRot_DoorClose; + } else { + ActorCutscene_SetIntentToPlay(this->dyna.actor.cutscene); + } +} + +void BgCtowerRot_Update(Actor* thisx, GlobalContext* globalCtx) { + BgCtowerRot* this = THIS; + + this->actionFunc(this, globalCtx); +} + +void BgCtowerRot_Draw(Actor* thisx, GlobalContext* globalCtx) { + BgCtowerRot* this = THIS; + + func_800BDFC0(globalCtx, bgCtowerRotDlists[this->dyna.actor.params]); + if (this->dyna.actor.params == CORRIDOR) { + func_800BE03C(globalCtx, D_060129D0); + } +} diff --git a/src/overlays/actors/ovl_Bg_Ctower_Rot/z_bg_ctower_rot.h b/src/overlays/actors/ovl_Bg_Ctower_Rot/z_bg_ctower_rot.h index cb2ac760c0..bef34f6ecb 100644 --- a/src/overlays/actors/ovl_Bg_Ctower_Rot/z_bg_ctower_rot.h +++ b/src/overlays/actors/ovl_Bg_Ctower_Rot/z_bg_ctower_rot.h @@ -5,9 +5,20 @@ struct BgCtowerRot; +typedef void (*BgCtowerRotActionFunc)(struct BgCtowerRot*, GlobalContext*); + +typedef enum { + /* 0 */ CORRIDOR, + /* 1 */ MAIN_DOOR, // Main door controls cutscene flow (updating Link fields and playing sounds). It is the one on + // the left when entering from the Lost Woods + /* 2 */ DOOR, +} BgCtowerRotType; + typedef struct BgCtowerRot { - /* 0x000 */ Actor actor; - /* 0x144 */ char unk_144[0x24]; + /* 0x000 */ DynaPolyActor dyna; + /* 0x15C */ BgCtowerRotActionFunc actionFunc; + /* 0x160 */ f32 unk160; // Set to 0 but never used + /* 0x164 */ f32 timer; } BgCtowerRot; // size = 0x168 extern const ActorInit Bg_Ctower_Rot_InitVars;