diff options
| author | Zelllll <56516451+Zelllll@users.noreply.github.com> | 2021-02-12 19:51:59 -0600 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-02-12 20:51:59 -0500 |
| commit | 4d306260338ec4ebef7c7a7e3e22311efdff9724 (patch) | |
| tree | ddddf87d15878bba68356fe7b968284c8031487a /src | |
| parent | 6d01247f3400c42a06780f7ceae0a7b4a730539c (diff) | |
Bg_Breakwall OK and documented (#684)
* cleanup breakwall
* fix mistake in header
* make some data static
* reloc stuffs
* ready for pr
* Remove asm
* Update src/overlays/actors/ovl_Bg_Breakwall/z_bg_breakwall.c
Co-authored-by: petrie911 <69443847+petrie911@users.noreply.github.com>
* fix petrie's stuff
* fixed all feedback
* Update src/overlays/actors/ovl_Bg_Breakwall/z_bg_breakwall.h
Co-authored-by: Roman971 <32455037+Roman971@users.noreply.github.com>
Co-authored-by: petrie911 <69443847+petrie911@users.noreply.github.com>
Co-authored-by: Roman971 <32455037+Roman971@users.noreply.github.com>
Diffstat (limited to 'src')
| -rw-r--r-- | src/overlays/actors/ovl_Bg_Breakwall/z_bg_breakwall.c | 279 | ||||
| -rw-r--r-- | src/overlays/actors/ovl_Bg_Breakwall/z_bg_breakwall.h | 12 |
2 files changed, 274 insertions, 17 deletions
diff --git a/src/overlays/actors/ovl_Bg_Breakwall/z_bg_breakwall.c b/src/overlays/actors/ovl_Bg_Breakwall/z_bg_breakwall.c index 08362ae1b..296f9199c 100644 --- a/src/overlays/actors/ovl_Bg_Breakwall/z_bg_breakwall.c +++ b/src/overlays/actors/ovl_Bg_Breakwall/z_bg_breakwall.c @@ -10,18 +10,23 @@ #define THIS ((BgBreakwall*)thisx) +typedef struct { + /* 0x00 */ CollisionHeader* colHeader; + /* 0x04 */ Gfx* dList; + /* 0x08 */ s8 colType; +} BombableWallInfo; + void BgBreakwall_Init(Actor* thisx, GlobalContext* globalCtx); void BgBreakwall_Destroy(Actor* thisx, GlobalContext* globalCtx); void BgBreakwall_Update(Actor* thisx, GlobalContext* globalCtx); +void BgBreakwall_Draw(Actor* thisx, GlobalContext* globalCtx); -void func_80870290(BgBreakwall* this, GlobalContext* globalCtx); -void func_80870394(BgBreakwall* this, GlobalContext* globalCtx); -void func_80870564(BgBreakwall* this, GlobalContext* globalCtx); -void func_808705D8(BgBreakwall* this, GlobalContext* globalCtx); +void BgBreakwall_WaitForObject(BgBreakwall* this, GlobalContext* globalCtx); +void BgBreakwall_Wait(BgBreakwall* this, GlobalContext* globalCtx); +void BgBreakwall_LavaCoverMove(BgBreakwall* this, GlobalContext* globalCtx); extern UNK_TYPE D_02014F80; -/* const ActorInit Bg_Breakwall_InitVars = { ACTOR_BG_BREAKWALL, ACTORCAT_BG, @@ -34,7 +39,7 @@ const ActorInit Bg_Breakwall_InitVars = { NULL, }; -static ColliderQuadInit D_80870760 = { +static ColliderQuadInit sQuadInit = { { COLTYPE_NONE, AT_NONE, @@ -53,21 +58,263 @@ static ColliderQuadInit D_80870760 = { }, { { { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } } }, }; -*/ -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Bg_Breakwall/BgBreakwall_SetupAction.s") -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Bg_Breakwall/BgBreakwall_Init.s") +static BombableWallInfo sBombableWallInfo[] = { + { 0x06000118, 0x06000040, 0 }, + { 0x06000118, 0x06000040, 0 }, + { 0x060264A8, 0x06025BD0, 1 }, + { 0x06025B64, NULL, -1 }, +}; + +static InitChainEntry sInitChain[] = { + ICHAIN_VEC3F_DIV1000(scale, 100, ICHAIN_CONTINUE), + ICHAIN_F32(uncullZoneForward, 4000, ICHAIN_CONTINUE), + ICHAIN_F32(uncullZoneScale, 400, ICHAIN_CONTINUE), + ICHAIN_F32(uncullZoneDownward, 400, ICHAIN_STOP), +}; + +void BgBreakwall_SetupAction(BgBreakwall* this, BgBreakwallActionFunc actionFunc) { + this->actionFunc = actionFunc; +} + +void BgBreakwall_Init(Actor* thisx, GlobalContext* globalCtx) { + BgBreakwall* this = THIS; + s32 pad; + s32 wallType = ((this->dyna.actor.params >> 13) & 3) & 0xFF; + + Actor_ProcessInitChain(&this->dyna.actor, sInitChain); + DynaPolyActor_Init(&this->dyna, DPM_UNK); + this->bombableWallDList = sBombableWallInfo[wallType].dList; + this->colType = sBombableWallInfo[wallType].colType; + + if (this->colType == 1) { + this->dyna.actor.world.rot.x = 0x4000; + } + + if (this->bombableWallDList != NULL) { + if (Flags_GetSwitch(globalCtx, this->dyna.actor.params & 0x3F)) { + Actor_Kill(&this->dyna.actor); + return; + } + + ActorShape_Init(&this->dyna.actor.shape, 0.0f, NULL, 0.0f); + Collider_InitQuad(globalCtx, &this->collider); + Collider_SetQuad(globalCtx, &this->collider, &this->dyna.actor, &sQuadInit); + } else { + this->dyna.actor.world.pos.y -= 40.0f; + } + + this->bankIndex = (wallType >= BWALL_KD_FLOOR) ? Object_GetIndex(&globalCtx->objectCtx, OBJECT_KINGDODONGO) + : Object_GetIndex(&globalCtx->objectCtx, OBJECT_BWALL); + + if (this->bankIndex < 0) { + Actor_Kill(&this->dyna.actor); + } else { + BgBreakwall_SetupAction(this, BgBreakwall_WaitForObject); + } +} + +void BgBreakwall_Destroy(Actor* thisx, GlobalContext* globalCtx) { + BgBreakwall* this = THIS; + + DynaPoly_DeleteBgActor(globalCtx, &globalCtx->colCtx.dyna, this->dyna.bgId); +} + +/** + * Spawns fragments using ACTOR_EN_A_OBJ whenever the wall or floor is exploded. + * Returns the last spawned actor + */ +Actor* BgBreakwall_SpawnFragments(GlobalContext* globalCtx, BgBreakwall* this, Vec3f* pos, f32 velocity, f32 scaleY, + f32 scaleX, s32 count, f32 accel) { + Actor* actor; + Vec3f actorPos; + s32 k; + s32 j; + s32 i; + s16 angle1; + s16 angle2 = 0; + Vec3f zeroVec = { 0.0f, 0.0f, 0.0f }; // unused + Vec3s actorRotList[] = { { 0, 0, 0 }, { 0, 0, 0x4000 }, { 0, 0, -0x4000 }, { 0, 0, 0 } }; + Vec3f actorScaleList[] = { + { 0.004f, 0.004f, 0.004f }, + { 0.004f, 0.004f, 0.004f }, + { 0.004f, 0.004f, 0.004f }, + { 0.004f, 0.004f, 0.004f }, + }; + Vec3f actorPosList[][4] = { + { { 40.0f, 15.0f, 0.0f }, { 30.0f, 57.0f, 0.0f }, { 50.0f, 57.0f, 0.0f }, { 40.0f, 70.0f, 0.0f } }, + { { 55.0f, -15.0f, 0.0f }, { 30.0f, -32.0f, 0.0f }, { 50.0f, -32.0f, 0.0f }, { 20.0f, -10.0f, 0.0f } }, + { { -40.0f, 14.0f, 0.0f }, { -50.0f, 57.0f, 0.0f }, { -30.0f, 57.0f, 0.0f }, { -40.0f, 70.0f, 0.0f } }, + { { -55.0f, -15.0f, 0.0f }, { -55.0f, -32.0f, 0.0f }, { -30.0f, -32.0f, 0.0f }, { -20.0f, -10.0f, 0.0f } }, + }; + s32 pad; + + for (k = 3; k >= 0; k--) { + if ((k == 0) || (k == 3)) { + actorScaleList[k].x *= scaleX; + actorScaleList[k].y *= scaleY; + actorScaleList[k].z *= scaleY; + } else { + actorScaleList[k].x *= scaleY; + actorScaleList[k].y *= scaleX; + actorScaleList[k].z *= scaleX; + } + } + + for (i = 0; i < count; angle2 += 0x4000, i++) { + angle1 = ABS(this->dyna.actor.world.rot.y) + angle2; + Matrix_Translate(this->dyna.actor.world.pos.x, this->dyna.actor.world.pos.y, this->dyna.actor.world.pos.z, + MTXMODE_NEW); + Matrix_RotateRPY(this->dyna.actor.world.rot.x, this->dyna.actor.world.rot.y, this->dyna.actor.world.rot.z, + MTXMODE_APPLY); + Matrix_Translate(pos->x, pos->y, pos->z, MTXMODE_APPLY); + + for (j = 3; j >= 0; j--) { + for (k = 3; k >= 0; k--) { + Matrix_MultVec3f(&actorPosList[j][k], &actorPos); + actor = + Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_A_OBJ, Rand_CenteredFloat(20.0f) + actorPos.x, + Rand_CenteredFloat(20.0f) + actorPos.y, Rand_CenteredFloat(20.0f) + actorPos.z, + actorRotList[k].x, actorRotList[k].y + angle1, actorRotList[k].z, 0x000B); + + if ((j & 1) == 0) { + func_80033480(globalCtx, &actorPos, velocity * 200.0f, 1, 650, 150, 1); + } + + if (actor != NULL) { + actor->speedXZ = Rand_ZeroOne() + (accel * 0.6f); + actor->velocity.y = Rand_ZeroOne() + (accel * 0.6f); + actor->world.rot.y += (s16)((Rand_ZeroOne() - 0.5f) * 3000.0f); + actor->world.rot.x = (s16)(Rand_ZeroOne() * 3500.0f) + 2000; + actor->world.rot.z = (s16)(Rand_ZeroOne() * 3500.0f) + 2000; + actor->parent = &this->dyna.actor; + actor->scale.x = actorScaleList[k].x + Rand_CenteredFloat(0.001f); + actor->scale.y = actorScaleList[k].y + Rand_CenteredFloat(0.001f); + actor->scale.z = actorScaleList[k].z + Rand_CenteredFloat(0.001f); + } + } + } + } + + return actor; +} + +/** + * Sets up the collision model as well is the object dependency and action function to use. + */ +void BgBreakwall_WaitForObject(BgBreakwall* this, GlobalContext* globalCtx) { + if (Object_IsLoaded(&globalCtx->objectCtx, this->bankIndex)) { + CollisionHeader* colHeader = NULL; + s32 wallType = ((this->dyna.actor.params >> 13) & 3) & 0xFF; + + this->dyna.actor.objBankIndex = this->bankIndex; + Actor_SetObjectDependency(globalCtx, &this->dyna.actor); + this->dyna.actor.flags &= ~0x10; + this->dyna.actor.draw = BgBreakwall_Draw; + CollisionHeader_GetVirtual(sBombableWallInfo[wallType].colHeader, &colHeader); + this->dyna.bgId = DynaPoly_SetBgActor(globalCtx, &globalCtx->colCtx.dyna, &this->dyna.actor, colHeader); + + if (wallType == BWALL_KD_LAVA_COVER) { + BgBreakwall_SetupAction(this, BgBreakwall_LavaCoverMove); + } else { + BgBreakwall_SetupAction(this, BgBreakwall_Wait); + } + } +} + +/** + * Checks for an explosion using quad collision. If the wall or floor is exploded then it will spawn fragments and + * despawn itself. + */ +void BgBreakwall_Wait(BgBreakwall* this, GlobalContext* globalCtx) { + if (this->collider.base.acFlags & 2) { + Vec3f effectPos; + s32 wallType = ((this->dyna.actor.params >> 13) & 3) & 0xFF; + + DynaPoly_DeleteBgActor(globalCtx, &globalCtx->colCtx.dyna, this->dyna.bgId); + effectPos.y = effectPos.z = effectPos.x = 0.0f; + + if (this->dyna.actor.world.rot.x == 0) { + effectPos.y = 55.0f; + } else { + effectPos.z = 25.0f; + effectPos.y = -10.0f; + } + + BgBreakwall_SpawnFragments(globalCtx, this, &effectPos, 0.0f, 6.4f, 5.0f, 1, 2.0f); + Flags_SetSwitch(globalCtx, this->dyna.actor.params & 0x3F); + + if (wallType == BWALL_KD_FLOOR) { + Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_EXPLOSION); + } else { + Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_WALL_BROKEN); + } + + if ((wallType == BWALL_DC_ENTRANCE) && (!(Flags_GetEventChkInf(0xB0)))) { + Flags_SetEventChkInf(0xB0); + Cutscene_SetSegment(globalCtx, &D_02014F80); + gSaveContext.cutsceneTrigger = 1; + Audio_PlaySoundGeneral(NA_SE_SY_CORRECT_CHIME, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + func_8002DF54(globalCtx, NULL, 0x31); + } + + if (this->dyna.actor.params < 0) { + Audio_PlaySoundGeneral(NA_SE_SY_TRE_BOX_APPEAR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + } + + Actor_Kill(&this->dyna.actor); + } +} + +/** + * Moves the actor's y position to cover the lava floor in King Dodongo's lair after he is defeated so the player is no + * longer hurt by the lava. + */ +void BgBreakwall_LavaCoverMove(BgBreakwall* this, GlobalContext* globalCtx) { + Math_StepToF(&this->dyna.actor.world.pos.y, KREG(80) + this->dyna.actor.home.pos.y, 1.0f); +} + +void BgBreakwall_Update(Actor* thisx, GlobalContext* globalCtx) { + BgBreakwall* this = THIS; + + this->actionFunc(this, globalCtx); +} + +/** + * These are the quads used for the wall and floor collision. These are used for the detecting when a bomb explosion has + * collided with a wall, and can be adjusted for different wall or floor sizes. + */ +static Vec3f sColQuadList[][4] = { + { { 800.0f, 1600.0f, 100.0f }, { -800.0f, 1600.0f, 100.0f }, { 800.0f, 0.0f, 100.0f }, { -800.0f, 0.0f, 100.0f } }, + { { 10.0f, 0.0f, 10.0f }, { -10.0f, 0.0f, 10.0f }, { 10.0f, 0.0f, -10.0f }, { -10.0f, 0.0f, -10.0f } }, +}; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Bg_Breakwall/BgBreakwall_Destroy.s") +void BgBreakwall_Draw(Actor* thisx, GlobalContext* globalCtx) { + s32 pad; + BgBreakwall* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Bg_Breakwall/func_8086FDC0.s") + if (this->bombableWallDList != NULL) { + OPEN_DISPS(globalCtx->state.gfxCtx, "../z_bg_breakwall.c", 767); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Bg_Breakwall/func_80870290.s") + func_80093D18(globalCtx->state.gfxCtx); + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_bg_breakwall.c", 771), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, this->bombableWallDList); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Bg_Breakwall/func_80870394.s") + if (this->colType >= 0) { + Vec3f colQuad[4]; + Vec3f* src = &sColQuadList[this->colType][0]; + Vec3f* dst = &colQuad[0]; + s32 i; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Bg_Breakwall/func_80870564.s") + for (i = 0; i < 4; i++) { + Matrix_MultVec3f(src++, dst++); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Bg_Breakwall/BgBreakwall_Update.s") + Collider_SetQuadVertices(&this->collider, &colQuad[0], &colQuad[1], &colQuad[2], &colQuad[3]); + CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider.base); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Bg_Breakwall/func_808705D8.s") + CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_bg_breakwall.c", 822); + } +} diff --git a/src/overlays/actors/ovl_Bg_Breakwall/z_bg_breakwall.h b/src/overlays/actors/ovl_Bg_Breakwall/z_bg_breakwall.h index b69110e8c..f8d19e0aa 100644 --- a/src/overlays/actors/ovl_Bg_Breakwall/z_bg_breakwall.h +++ b/src/overlays/actors/ovl_Bg_Breakwall/z_bg_breakwall.h @@ -10,10 +10,20 @@ typedef void (*BgBreakwallActionFunc)(struct BgBreakwall*, GlobalContext*); typedef struct BgBreakwall { /* 0x0000 */ DynaPolyActor dyna; - /* 0x0164 */ char unk_164[0x88]; + /* 0x0164 */ Gfx* bombableWallDList; + /* 0x0168 */ s8 colType; + /* 0x0169 */ s8 bankIndex; + /* 0x016C */ ColliderQuad collider; /* 0x01EC */ BgBreakwallActionFunc actionFunc; } BgBreakwall; // size = 0x01F0 +typedef enum { + /* 0 */ BWALL_DC_ENTRANCE, // When exploded it will play the Dodongo's Cavern intro cutscene + /* 1 */ BWALL_WALL, // Used a lot in Dodongo's Cavern and other places + /* 2 */ BWALL_KD_FLOOR, // Used in the King Dodongo boss room + /* 3 */ BWALL_KD_LAVA_COVER // Spawned after the KD fight in order to cover the lava floor to disable damage +} BombableWallType; + extern const ActorInit Bg_Breakwall_InitVars; #endif |
