1
0
Fork 0
mirror of https://github.com/zeldaret/oot.git synced 2025-08-06 06:10:21 +00:00

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>
This commit is contained in:
Zelllll 2021-02-12 19:51:59 -06:00 committed by GitHub
parent 6d01247f34
commit 4d30626033
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 275 additions and 910 deletions

View file

@ -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 },
};
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Bg_Breakwall/BgBreakwall_Destroy.s")
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),
};
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Bg_Breakwall/func_8086FDC0.s")
void BgBreakwall_SetupAction(BgBreakwall* this, BgBreakwallActionFunc actionFunc) {
this->actionFunc = actionFunc;
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Bg_Breakwall/func_80870290.s")
void BgBreakwall_Init(Actor* thisx, GlobalContext* globalCtx) {
BgBreakwall* this = THIS;
s32 pad;
s32 wallType = ((this->dyna.actor.params >> 13) & 3) & 0xFF;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Bg_Breakwall/func_80870394.s")
Actor_ProcessInitChain(&this->dyna.actor, sInitChain);
DynaPolyActor_Init(&this->dyna, DPM_UNK);
this->bombableWallDList = sBombableWallInfo[wallType].dList;
this->colType = sBombableWallInfo[wallType].colType;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Bg_Breakwall/func_80870564.s")
if (this->colType == 1) {
this->dyna.actor.world.rot.x = 0x4000;
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Bg_Breakwall/BgBreakwall_Update.s")
if (this->bombableWallDList != NULL) {
if (Flags_GetSwitch(globalCtx, this->dyna.actor.params & 0x3F)) {
Actor_Kill(&this->dyna.actor);
return;
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Bg_Breakwall/func_808705D8.s")
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 } },
};
void BgBreakwall_Draw(Actor* thisx, GlobalContext* globalCtx) {
s32 pad;
BgBreakwall* this = THIS;
if (this->bombableWallDList != NULL) {
OPEN_DISPS(globalCtx->state.gfxCtx, "../z_bg_breakwall.c", 767);
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);
if (this->colType >= 0) {
Vec3f colQuad[4];
Vec3f* src = &sColQuadList[this->colType][0];
Vec3f* dst = &colQuad[0];
s32 i;
for (i = 0; i < 4; i++) {
Matrix_MultVec3f(src++, dst++);
}
Collider_SetQuadVertices(&this->collider, &colQuad[0], &colQuad[1], &colQuad[2], &colQuad[3]);
CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
}
CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_bg_breakwall.c", 822);
}
}

View file

@ -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