From a039a2f34a65ec9b85763664b30981f715563558 Mon Sep 17 00:00:00 2001 From: Tom Overton Date: Sun, 19 Jun 2022 16:38:51 -0700 Subject: [PATCH] BgIkanaDharma (punchable pillar segments in STT) OK (#851) * Bg_Ikana_Dharma decompiled * Bg_Ikana_Dharma more stuff * remove & from function pointers * use THIS macro * use THIS macro * return -> else * GET_PLAYER * slightly better match (this2 only used once) * fix warnings; name variables * better match in BgIkanaDharma_Init; more param macros * Rebase to latest master and some minor cleanup * More cleanup * Document object * Respond to isghj5's review * Respond to Elliptic's review * Better pack macro * Respond to hensldm's review Co-authored-by: immibis --- assets/xml/objects/object_ikana_obj.xml | 6 +- spec | 4 +- .../ovl_Bg_Ikana_Dharma/z_bg_ikana_dharma.c | 232 ++++++++++++++++-- .../ovl_Bg_Ikana_Dharma/z_bg_ikana_dharma.h | 11 +- tools/disasm/functions.txt | 14 +- undefined_syms.txt | 5 - 6 files changed, 228 insertions(+), 44 deletions(-) diff --git a/assets/xml/objects/object_ikana_obj.xml b/assets/xml/objects/object_ikana_obj.xml index 66398991b..6040495ab 100644 --- a/assets/xml/objects/object_ikana_obj.xml +++ b/assets/xml/objects/object_ikana_obj.xml @@ -9,8 +9,8 @@ - - + + @@ -38,7 +38,7 @@ - + diff --git a/spec b/spec index 6dc4c4285..ac6a462aa 100644 --- a/spec +++ b/spec @@ -4802,9 +4802,7 @@ beginseg name "ovl_Bg_Ikana_Dharma" compress include "build/src/overlays/actors/ovl_Bg_Ikana_Dharma/z_bg_ikana_dharma.o" - include "build/data/ovl_Bg_Ikana_Dharma/ovl_Bg_Ikana_Dharma.data.o" - include "build/data/ovl_Bg_Ikana_Dharma/ovl_Bg_Ikana_Dharma.bss.o" - include "build/data/ovl_Bg_Ikana_Dharma/ovl_Bg_Ikana_Dharma.reloc.o" + include "build/src/overlays/actors/ovl_Bg_Ikana_Dharma/ovl_Bg_Ikana_Dharma_reloc.o" endseg beginseg diff --git a/src/overlays/actors/ovl_Bg_Ikana_Dharma/z_bg_ikana_dharma.c b/src/overlays/actors/ovl_Bg_Ikana_Dharma/z_bg_ikana_dharma.c index 2fb508c79..6048a8c9c 100644 --- a/src/overlays/actors/ovl_Bg_Ikana_Dharma/z_bg_ikana_dharma.c +++ b/src/overlays/actors/ovl_Bg_Ikana_Dharma/z_bg_ikana_dharma.c @@ -5,6 +5,7 @@ */ #include "z_bg_ikana_dharma.h" +#include "assets/objects/object_ikana_obj/object_ikana_obj.h" #define FLAGS (ACTOR_FLAG_10) @@ -15,7 +16,13 @@ void BgIkanaDharma_Destroy(Actor* thisx, GlobalContext* globalCtx); void BgIkanaDharma_Update(Actor* thisx, GlobalContext* globalCtx); void BgIkanaDharma_Draw(Actor* thisx, GlobalContext* globalCtx); -#if 0 +void BgIkanaDharma_SetupWaitForHit(BgIkanaDharma* this); +void BgIkanaDharma_WaitForHit(BgIkanaDharma* this, GlobalContext* globalCtx); +void BgIkanaDharma_SetupStartCutscene(BgIkanaDharma* this); +void BgIkanaDharma_StartCutscene(BgIkanaDharma* this, GlobalContext* globalCtx); +void BgIkanaDharma_SetupWaitForCutsceneToEnd(BgIkanaDharma* this); +void BgIkanaDharma_WaitForCutsceneToEnd(BgIkanaDharma* this, GlobalContext* globalCtx); + const ActorInit Bg_Ikana_Dharma_InitVars = { ACTOR_BG_IKANA_DHARMA, ACTORCAT_BG, @@ -28,47 +35,226 @@ const ActorInit Bg_Ikana_Dharma_InitVars = { (ActorFunc)BgIkanaDharma_Draw, }; -// static ColliderCylinderInit sCylinderInit = { -static ColliderCylinderInit D_80BECAD0 = { - { COLTYPE_NONE, AT_NONE, AC_ON | AC_TYPE_PLAYER, OC1_NONE, OC2_NONE, COLSHAPE_CYLINDER, }, - { ELEMTYPE_UNK0, { 0x00000000, 0x00, 0x00 }, { 0x00000100, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, }, +static ColliderCylinderInit sCylinderInit = { + { + COLTYPE_NONE, + AT_NONE, + AC_ON | AC_TYPE_PLAYER, + OC1_NONE, + OC2_NONE, + COLSHAPE_CYLINDER, + }, + { + ELEMTYPE_UNK0, + { 0x00000000, 0x00, 0x00 }, + { 0x00000100, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_NONE, + }, { 98, 10, 25, { 0, 0, 0 } }, }; -// static InitChainEntry sInitChain[] = { -static InitChainEntry D_80BECAFC[] = { +static InitChainEntry sInitChain[] = { ICHAIN_F32(uncullZoneForward, 4000, ICHAIN_CONTINUE), ICHAIN_F32(uncullZoneScale, 320, ICHAIN_CONTINUE), ICHAIN_F32(uncullZoneDownward, 320, ICHAIN_CONTINUE), ICHAIN_F32_DIV1000(gravity, -1100, ICHAIN_STOP), }; -#endif +static BgIkanaDharma* sFirstHitBgIkanaDharma; -extern ColliderCylinderInit D_80BECAD0; -extern InitChainEntry D_80BECAFC[]; +void BgIkanaDharma_SpawnEffects(BgIkanaDharma* this, GlobalContext* globalCtx) { + s32 pad; + Vec3f pos; + Vec3f velocity; + Vec3f accel; + s32 i; + f32 initialRadius = this->dyna.actor.scale.x * 200.0f; + f32 initialY = this->dyna.actor.scale.y * 50.0f; -extern UNK_TYPE D_060008C8; -extern UNK_TYPE D_06000C50; + for (i = 0; i < 4; i++) { + f32 speed = (Rand_ZeroOne() * 5.0f) + 5.0f; + s16 angle = ((u32)Rand_Next() >> 0x12) + this->dyna.actor.world.rot.y + 0x6000; + f32 dirX = Math_SinS(angle); + f32 dirZ = Math_CosS(angle); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Ikana_Dharma/func_80BEC240.s") + pos.x = (dirX * initialRadius) + this->dyna.actor.world.pos.x; + pos.y = this->dyna.actor.world.pos.y + initialY; + pos.z = (dirZ * initialRadius) + this->dyna.actor.world.pos.z; + velocity.x = speed * dirX; + velocity.y = Rand_ZeroOne() + 0.5f; + velocity.z = speed * dirZ; + accel.x = velocity.x * -0.05f; + accel.y = -0.15f; + accel.z = velocity.z * -0.05f; + EffectSsKirakira_SpawnSmallYellow(globalCtx, &pos, &velocity, &accel); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Ikana_Dharma/BgIkanaDharma_Init.s") +void BgIkanaDharma_Init(Actor* thisx, GlobalContext* globalCtx2) { + GlobalContext* globalCtx = globalCtx2; + BgIkanaDharma* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Ikana_Dharma/BgIkanaDharma_Destroy.s") + Actor_ProcessInitChain(&this->dyna.actor, sInitChain); + this->dyna.actor.scale.x = 0.3f; + this->dyna.actor.scale.y = 0.1f; + this->dyna.actor.scale.z = 0.3f; + DynaPolyActor_Init(&this->dyna, 0); + DynaPolyActor_LoadMesh(globalCtx, &this->dyna, &gStoneTowerTemplePunchablePillarCol); + Collider_InitCylinder(globalCtx, &this->collider); + Collider_SetCylinder(globalCtx, &this->collider, &this->dyna.actor, &sCylinderInit); + if (!BGIKANADHARMA_IS_CHILD(&this->dyna.actor)) { + f32 segmentY = this->dyna.actor.world.pos.y; + s32 numSegments = BGIKANADHARMA_NUM_SEGMENTS(&this->dyna.actor); + s32 i; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Ikana_Dharma/func_80BEC5C4.s") + for (i = 0; i < numSegments; i++) { + segmentY += 60.0f; + Actor_SpawnAsChildAndCutscene(&globalCtx->actorCtx, globalCtx, ACTOR_BG_IKANA_DHARMA, + this->dyna.actor.world.pos.x, segmentY, this->dyna.actor.world.pos.z, + this->dyna.actor.shape.rot.x, this->dyna.actor.shape.rot.y, + this->dyna.actor.shape.rot.z, BGIKANADHARMA_PARAMS(0, true, 0), + this->dyna.actor.cutscene, this->dyna.actor.unk20, NULL); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Ikana_Dharma/func_80BEC5E0.s") + this->dyna.actor.bgCheckFlags |= 1; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Ikana_Dharma/func_80BEC758.s") + BgIkanaDharma_SetupWaitForHit(this); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Ikana_Dharma/func_80BEC790.s") +void BgIkanaDharma_Destroy(Actor* thisx, GlobalContext* globalCtx) { + BgIkanaDharma* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Ikana_Dharma/func_80BEC7EC.s") + DynaPoly_DeleteBgActor(globalCtx, &globalCtx->colCtx.dyna, this->dyna.bgId); + Collider_DestroyCylinder(globalCtx, &this->collider); + if (sFirstHitBgIkanaDharma == this) { + sFirstHitBgIkanaDharma = NULL; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Ikana_Dharma/func_80BEC808.s") +void BgIkanaDharma_SetupWaitForHit(BgIkanaDharma* this) { + this->actionFunc = BgIkanaDharma_WaitForHit; + this->dyna.actor.speedXZ = 0.0f; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Ikana_Dharma/BgIkanaDharma_Update.s") +void BgIkanaDharma_WaitForHit(BgIkanaDharma* this, GlobalContext* globalCtx) { + s32 wasHit = (this->collider.base.acFlags & AC_HIT) != 0; + Player* player = GET_PLAYER(globalCtx); + BgIkanaDharma* this2 = this; + s32 tempAngle1; + s32 tempAngle2; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_Ikana_Dharma/BgIkanaDharma_Draw.s") + if (wasHit) { + this->collider.base.acFlags &= ~AC_HIT; + } + + if (wasHit && sFirstHitBgIkanaDharma == NULL) { + sFirstHitBgIkanaDharma = this2; + Flags_SetSwitch(globalCtx, BGIKANADHARMA_GET_SWITCHFLAG(&this->dyna.actor)); + tempAngle1 = BINANG_ADD(this->dyna.actor.yawTowardsPlayer, 0x8000); + tempAngle2 = (BINANG_SUB(player->actor.shape.rot.y, tempAngle1) >> 1); + this->dyna.actor.world.rot.y = tempAngle1 + tempAngle2 + 0xF000; + this->dyna.actor.speedXZ = 20.0f; + Actor_PlaySfxAtPos(&this->dyna.actor, NA_SE_EV_DARUMA_VANISH); + BgIkanaDharma_SetupStartCutscene(this); + } else if ((this->dyna.actor.flags & ACTOR_FLAG_40) == ACTOR_FLAG_40 && sFirstHitBgIkanaDharma == NULL && + this->dyna.actor.xzDistToPlayer < 420.0f) { + tempAngle1 = BINANG_SUB(this->dyna.actor.yawTowardsPlayer, player->actor.shape.rot.y); + tempAngle1 = ABS_ALT(tempAngle1); + + if (tempAngle1 > 0x4000) { + Collider_UpdateCylinder(&this->dyna.actor, &this->collider); + CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider.base); + } + } +} + +void BgIkanaDharma_SetupStartCutscene(BgIkanaDharma* this) { + ActorCutscene_SetIntentToPlay(this->dyna.actor.cutscene); + this->actionFunc = BgIkanaDharma_StartCutscene; +} + +void BgIkanaDharma_StartCutscene(BgIkanaDharma* this, GlobalContext* globalCtx) { + if (ActorCutscene_GetCanPlayNext(this->dyna.actor.cutscene)) { + ActorCutscene_StartAndSetUnkLinkFields(this->dyna.actor.cutscene, &this->dyna.actor); + BgIkanaDharma_SetupWaitForCutsceneToEnd(this); + } else { + ActorCutscene_SetIntentToPlay(this->dyna.actor.cutscene); + } +} + +void BgIkanaDharma_SetupWaitForCutsceneToEnd(BgIkanaDharma* this) { + this->cutsceneFramesRemaining = 10; + this->actionFunc = BgIkanaDharma_WaitForCutsceneToEnd; +} + +void BgIkanaDharma_WaitForCutsceneToEnd(BgIkanaDharma* this, GlobalContext* globalCtx) { + if (this->cutsceneFramesRemaining > 0) { + this->cutsceneFramesRemaining--; + + if (this->cutsceneFramesRemaining == 0) { + if (sFirstHitBgIkanaDharma == this) { + sFirstHitBgIkanaDharma = NULL; + } + + ActorCutscene_Stop(this->dyna.actor.cutscene); + } + } + + if (Math_StepToF(&this->dyna.actor.scale.y, 0.0f, 1.0f / 300.0f) != 0) { + Actor_MarkForDeath(&this->dyna.actor); + } else { + this->dyna.actor.scale.x = this->dyna.actor.scale.y * 3.0f; + this->dyna.actor.scale.z = this->dyna.actor.scale.y * 3.0f; + BgIkanaDharma_SpawnEffects(this, globalCtx); + } +} + +void BgIkanaDharma_Update(Actor* thisx, GlobalContext* globalCtx) { + BgIkanaDharma* this = THIS; + + this->actionFunc(this, globalCtx); + if (this->actionFunc == BgIkanaDharma_WaitForHit) { + DynaPolyActor* actorBelow; + s32 pad[2]; + + func_800B4AEC(globalCtx, &this->dyna.actor, 30.0f); + actorBelow = DynaPoly_GetActor(&globalCtx->colCtx, this->dyna.actor.floorBgId); + if (actorBelow == NULL) { + Actor_MoveWithGravity(&this->dyna.actor); + Actor_UpdateBgCheckInfo(globalCtx, &this->dyna.actor, 0.0f, 0.0f, 0.0f, 4); + if (this->dyna.actor.bgCheckFlags & 2) { + s16 quake = Quake_Add(globalCtx->cameraPtrs[globalCtx->activeCamera], 3); + + Quake_SetSpeed(quake, 21536); + Quake_SetQuakeValues(quake, 4, 0, 0, 0); + Quake_SetCountdown(quake, 12); + Actor_PlaySfxAtPos(&this->dyna.actor, NA_SE_EV_BLOCK_BOUND); + } + } else { + if (actorBelow->actor.id == ACTOR_BG_IKANA_DHARMA) { + this->dyna.actor.world.pos.y = actorBelow->actor.world.pos.y + 60.0f; + } else { + this->dyna.actor.world.pos.y = this->dyna.actor.floorHeight; + } + + this->dyna.actor.velocity.y = 0.0f; + } + } else { + f32 wallCheckRadius = this->dyna.actor.scale.x * 300.0f; + wallCheckRadius = CLAMP_MIN(wallCheckRadius, 2.0f); + + Actor_MoveWithGravity(&this->dyna.actor); + Actor_UpdateBgCheckInfo(globalCtx, &this->dyna.actor, 20.0f, wallCheckRadius, 0.0f, 5); + } + + Actor_SetFocus(&this->dyna.actor, 40.0f); +} + +void BgIkanaDharma_Draw(Actor* thisx, GlobalContext* globalCtx) { + BgIkanaDharma* this = THIS; + + Gfx_DrawDListOpa(globalCtx, gStoneTowerTemplePunchablePillarDL); +} diff --git a/src/overlays/actors/ovl_Bg_Ikana_Dharma/z_bg_ikana_dharma.h b/src/overlays/actors/ovl_Bg_Ikana_Dharma/z_bg_ikana_dharma.h index ddd81e7d8..bf769a1a1 100644 --- a/src/overlays/actors/ovl_Bg_Ikana_Dharma/z_bg_ikana_dharma.h +++ b/src/overlays/actors/ovl_Bg_Ikana_Dharma/z_bg_ikana_dharma.h @@ -3,15 +3,20 @@ #include "global.h" +#define BGIKANADHARMA_GET_SWITCHFLAG(thisx) (((thisx)->params >> 8) & 0x7F) +#define BGIKANADHARMA_IS_CHILD(thisx) (((thisx)->params >> 5) & 1) +#define BGIKANADHARMA_NUM_SEGMENTS(thisx) ((thisx)->params & 0xF) +#define BGIKANADHARMA_PARAMS(switchFlag, isChild, numSegments) (((switchFlag & 0x7F) << 8) | ((isChild & 1) << 5) | (numSegments & 0xF)) + struct BgIkanaDharma; typedef void (*BgIkanaDharmaActionFunc)(struct BgIkanaDharma*, GlobalContext*); typedef struct BgIkanaDharma { - /* 0x0000 */ Actor actor; - /* 0x0144 */ char unk_144[0x64]; + /* 0x0000 */ DynaPolyActor dyna; + /* 0x015C */ ColliderCylinder collider; /* 0x01A8 */ BgIkanaDharmaActionFunc actionFunc; - /* 0x01AC */ char unk_1AC[0x4]; + /* 0x01AC */ s8 cutsceneFramesRemaining; } BgIkanaDharma; // size = 0x1B0 extern const ActorInit Bg_Ikana_Dharma_InitVars; diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt index 87d94e6ea..2c74907d5 100644 --- a/tools/disasm/functions.txt +++ b/tools/disasm/functions.txt @@ -16220,15 +16220,15 @@ 0x80BEC080:("EffLastday_Update",), 0x80BEC0A4:("func_80BEC0A4",), 0x80BEC0DC:("EffLastday_Draw",), - 0x80BEC240:("func_80BEC240",), + 0x80BEC240:("BgIkanaDharma_SpawnEffects",), 0x80BEC3F4:("BgIkanaDharma_Init",), 0x80BEC560:("BgIkanaDharma_Destroy",), - 0x80BEC5C4:("func_80BEC5C4",), - 0x80BEC5E0:("func_80BEC5E0",), - 0x80BEC758:("func_80BEC758",), - 0x80BEC790:("func_80BEC790",), - 0x80BEC7EC:("func_80BEC7EC",), - 0x80BEC808:("func_80BEC808",), + 0x80BEC5C4:("BgIkanaDharma_SetupWaitForHit",), + 0x80BEC5E0:("BgIkanaDharma_WaitForHit",), + 0x80BEC758:("BgIkanaDharma_SetupStartCutscene",), + 0x80BEC790:("BgIkanaDharma_StartCutscene",), + 0x80BEC7EC:("BgIkanaDharma_SetupWaitForCutsceneToEnd",), + 0x80BEC808:("BgIkanaDharma_WaitForCutsceneToEnd",), 0x80BEC8C0:("BgIkanaDharma_Update",), 0x80BECA80:("BgIkanaDharma_Draw",), 0x80BECBE0:("func_80BECBE0",), diff --git a/undefined_syms.txt b/undefined_syms.txt index 403905235..f2f9c6af1 100644 --- a/undefined_syms.txt +++ b/undefined_syms.txt @@ -612,11 +612,6 @@ D_06000C90 = 0x06000C90; D_06000288 = 0x06000288; -// ovl_Bg_Ikana_Dharma - -D_060008C8 = 0x060008C8; -D_06000C50 = 0x06000C50; - // ovl_Bg_Ikana_Mirror D_060014B0 = 0x060014B0;