diff --git a/assets/xml/objects/object_haka_objects.xml b/assets/xml/objects/object_haka_objects.xml
index 615f67b3b5..ac301fe500 100644
--- a/assets/xml/objects/object_haka_objects.xml
+++ b/assets/xml/objects/object_haka_objects.xml
@@ -70,34 +70,34 @@
-
+
-
-
+
+
-
-
+
+
-
-
-
+
+
+
-
-
+
+
-
+
-
-
+
+
diff --git a/src/overlays/actors/ovl_Bg_Haka_Trap/z_bg_haka_trap.c b/src/overlays/actors/ovl_Bg_Haka_Trap/z_bg_haka_trap.c
index afb0f19043..a91df648c1 100644
--- a/src/overlays/actors/ovl_Bg_Haka_Trap/z_bg_haka_trap.c
+++ b/src/overlays/actors/ovl_Bg_Haka_Trap/z_bg_haka_trap.c
@@ -1,7 +1,27 @@
/*
* File: z_bg_haka_trap.c
* Overlay: ovl_Bg_Haka_Trap
- * Description: Shadow Temple Objects
+ * Description: Shadow Temple traps
+ *
+ * HAKA_TRAP_GUILLOTINE:
+ * A guillotine blade attached to a chain, drops from the ceiling.
+ *
+ * HAKA_TRAP_GUILLOTINE_FAST: (spawn only param)
+ * Enables a flag making the guillotine move faster.
+ *
+ * HAKA_TRAP_SPIKED_CRUSHER:
+ * A square shaped platform suspended by a chain with spikes underneath, intended to crush the player. A pushblock can
+ * be used to prevent it from decending completely. Rotating this actor may prevent correct hit detection of the block.
+ *
+ * HAKA_TRAP_SPIKED_WALL_EAST:
+ * HAKA_TRAP_SPIKED_WALL_WEST:
+ *
+ * Two wooden spike walls that come together to crush the player. The one to the east has extra holes to reveal the
+ * chest behind it.
+ *
+ * HAKA_TRAP_FAN_BLADE:
+ * A small fan blade that pushes the player away when turned on. `world.rot.z` is used to store the angular
+ * velocity of the fan
*/
#include "z_bg_haka_trap.h"
@@ -26,20 +46,20 @@ void BgHakaTrap_Destroy(Actor* thisx, PlayState* play);
void BgHakaTrap_Update(Actor* thisx, PlayState* play);
void BgHakaTrap_Draw(Actor* thisx, PlayState* play);
-void func_8087FFC0(BgHakaTrap* this, PlayState* play);
-void func_808801B8(BgHakaTrap* this, PlayState* play);
-void func_808802D8(BgHakaTrap* this, PlayState* play);
-void func_80880484(BgHakaTrap* this, PlayState* play);
-void func_808805C0(BgHakaTrap* this, PlayState* play);
-void func_808806BC(BgHakaTrap* this, PlayState* play);
-void func_808808F4(BgHakaTrap* this, PlayState* play);
-void func_808809B0(BgHakaTrap* this, PlayState* play);
-void func_808809E4(BgHakaTrap* this, PlayState* play, s16 arg2);
-void func_80880AE8(BgHakaTrap* this, PlayState* play);
-void func_80880C0C(BgHakaTrap* this, PlayState* play);
-void func_80880D68(BgHakaTrap* this);
+void BgHakaTrap_UpdateBodyColliderPos(BgHakaTrap* this, PlayState* play);
+void BgHakaTrap_SpikedWall_CloseIn(BgHakaTrap* this, PlayState* play);
+void BgHakaTrap_SpikedWall_Burn(BgHakaTrap* this, PlayState* play);
+void BgHakaTrap_Guillotine_Fall(BgHakaTrap* this, PlayState* play);
+void BgHakaTrap_Guillotine_Lift(BgHakaTrap* this, PlayState* play);
+void BgHakaTrap_SpikedCrusher_Fall(BgHakaTrap* this, PlayState* play);
+void BgHakaTrap_SpikedCrusher_Lift(BgHakaTrap* this, PlayState* play);
+void BgHakaTrap_FanBlade_Idle(BgHakaTrap* this, PlayState* play);
+void BgHakaTrap_PushPlayer(BgHakaTrap* this, PlayState* play, s16 angularVelocity);
+void BgHakaTrap_FanBlade_ToggleFanGust(BgHakaTrap* this, PlayState* play);
+void BgHakaTrap_FanBlade_FullGust(BgHakaTrap* this, PlayState* play);
+void BgHakaTrap_SpikedWall_UpdateCollider(BgHakaTrap* this);
-static UNK_TYPE D_80880F30 = 0;
+static s32 sIsSpikeWallBurning = false;
ActorProfile Bg_Haka_Trap_Profile = {
/**/ ACTOR_BG_HAKA_TRAP,
@@ -73,7 +93,7 @@ static ColliderCylinderInit sCylinderInit = {
{ 30, 90, 0, { 0, 0, 0 } },
};
-static ColliderTrisElementInit sTrisElementsInit[] = {
+static ColliderTrisElementInit sSpikedWallTrisElementsInit[] = {
{
{
ELEM_MATERIAL_UNK0,
@@ -98,7 +118,7 @@ static ColliderTrisElementInit sTrisElementsInit[] = {
},
};
-static ColliderTrisInit sTrisInit = {
+static ColliderTrisInit sSpikedWallTrisInit = {
{
COL_MATERIAL_NONE,
AT_NONE,
@@ -107,8 +127,8 @@ static ColliderTrisInit sTrisInit = {
OC2_TYPE_2,
COLSHAPE_TRIS,
},
- ARRAY_COUNT(sTrisElementsInit),
- sTrisElementsInit,
+ ARRAY_COUNT(sSpikedWallTrisElementsInit),
+ sSpikedWallTrisElementsInit,
};
static CollisionCheckInfoInit sColChkInfoInit = { 0, 80, 100, MASS_IMMOVABLE };
@@ -118,7 +138,7 @@ static InitChainEntry sInitChain[] = {
};
void BgHakaTrap_Init(Actor* thisx, PlayState* play) {
- static UNK_TYPE D_80881014 = 0;
+ static s32 sSpikedCrusherFlip = false;
BgHakaTrap* this = (BgHakaTrap*)thisx;
s32 pad;
CollisionHeader* colHeader = NULL;
@@ -126,54 +146,65 @@ void BgHakaTrap_Init(Actor* thisx, PlayState* play) {
Actor_ProcessInitChain(thisx, sInitChain);
thisx->params &= 0xFF;
- if (thisx->params != HAKA_TRAP_PROPELLER) {
+ if (thisx->params != HAKA_TRAP_FAN_BLADE) {
Collider_InitCylinder(play, &this->colliderCylinder);
Collider_SetCylinder(play, &this->colliderCylinder, thisx, &sCylinderInit);
- if ((thisx->params == HAKA_TRAP_GUILLOTINE_SLOW) || (thisx->params == HAKA_TRAP_GUILLOTINE_FAST)) {
+ if ((thisx->params == HAKA_TRAP_GUILLOTINE) || (thisx->params == HAKA_TRAP_GUILLOTINE_FAST)) {
this->timer = 20;
this->colliderCylinder.dim.yShift = 10;
thisx->velocity.y = 0.1f;
if (thisx->params == HAKA_TRAP_GUILLOTINE_FAST) {
- thisx->params = HAKA_TRAP_GUILLOTINE_SLOW;
- this->unk_16A = 1;
+ thisx->params = HAKA_TRAP_GUILLOTINE;
+ this->isGuillotineFast = true;
}
- this->actionFunc = func_80880484;
+ this->actionFunc = BgHakaTrap_Guillotine_Fall;
} else {
DynaPolyActor_Init(&this->dyna, DYNA_TRANSFORM_POS);
thisx->flags |= ACTOR_FLAG_UPDATE_CULLING_DISABLED;
- if (thisx->params == HAKA_TRAP_SPIKED_BOX) {
- CollisionHeader_GetVirtual(&object_haka_objects_Col_009CD0, &colHeader);
+ if (thisx->params == HAKA_TRAP_SPIKED_CRUSHER) {
+ CollisionHeader_GetVirtual(&gShadowTempleSpikedCrusherCol, &colHeader);
this->timer = 30;
- if (D_80881014 != 0) {
- this->actionFunc = func_808808F4;
- D_80881014 = 0;
+ // Instances alternate between starting off in the up or down position.
+ if (sSpikedCrusherFlip) {
+ this->actionFunc = BgHakaTrap_SpikedCrusher_Lift;
+ sSpikedCrusherFlip = false;
} else {
- D_80881014 = 1;
- this->actionFunc = func_808806BC;
+ sSpikedCrusherFlip = true;
+ this->actionFunc = BgHakaTrap_SpikedCrusher_Fall;
thisx->velocity.y = 0.5f;
}
- thisx->floorHeight = thisx->home.pos.y - 225.0f;
- this->unk_16A = (thisx->floorHeight + 50.0f) - 25.0f;
+ // Assign the minimum height of the crusher. The crusher intentionally clips through the floor by 25
+ // units to allow the spikes to pierce the floor
+ thisx->floorHeight = thisx->home.pos.y - (200 + 25);
+
+ // Assigns the height the crusher rises on first "tug". The final -25 offset is missing in other
+ // calculations of this variable.
+ this->spikedCrusherStepY = (thisx->floorHeight + 50.0f) - 25.0f;
this->colliderCylinder.dim.radius = 10;
this->colliderCylinder.dim.height = 40;
} else {
- if (thisx->params == HAKA_TRAP_SPIKED_WALL) {
- CollisionHeader_GetVirtual(&object_haka_objects_Col_0081D0, &colHeader);
+ if (thisx->params == HAKA_TRAP_SPIKED_WALL_EAST) {
+ CollisionHeader_GetVirtual(&gShadowTempleSpikedWallEastCol, &colHeader);
+ // Shift the home position toward the center of the room. This will become the target position that
+ // triggers the crush.
thisx->home.pos.x -= 200.0f;
- } else {
+ } else /* HAKA_TRAP_SPIKED_WALL_WEST */ {
+ // Shift the home position toward the center of the room. This will become the target position that
+ // triggers the crush.
thisx->home.pos.x += 200.0f;
- CollisionHeader_GetVirtual(&object_haka_objects_Col_008D10, &colHeader);
+ CollisionHeader_GetVirtual(&gShadowTempleSpikedWallWestCol, &colHeader);
}
Collider_InitTris(play, &this->spikesCollider);
- Collider_SetTris(play, &this->spikesCollider, thisx, &sTrisInit, this->spikesColliderElements);
+ Collider_SetTris(play, &this->spikesCollider, thisx, &sSpikedWallTrisInit,
+ this->spikesColliderElements);
this->colliderCylinder.dim.radius = 18;
this->colliderCylinder.dim.height = 115;
@@ -181,14 +212,15 @@ void BgHakaTrap_Init(Actor* thisx, PlayState* play) {
this->colliderCylinder.elem.atElemFlags &= ~ATELEM_SFX_NORMAL;
this->colliderCylinder.elem.atElemFlags |= ATELEM_SFX_WOOD;
- this->actionFunc = func_808801B8;
+ this->actionFunc = BgHakaTrap_SpikedWall_CloseIn;
}
this->dyna.bgId = DynaPoly_SetBgActor(play, &play->colCtx.dyna, thisx, colHeader);
}
} else {
+ // Initialize HAKA_TRAP_FAN_BLADE
this->timer = 40;
- this->actionFunc = func_808809B0;
+ this->actionFunc = BgHakaTrap_FanBlade_Idle;
thisx->cullingVolumeScale = 500.0f;
}
@@ -198,11 +230,11 @@ void BgHakaTrap_Init(Actor* thisx, PlayState* play) {
void BgHakaTrap_Destroy(Actor* thisx, PlayState* play) {
BgHakaTrap* this = (BgHakaTrap*)thisx;
- if (this->dyna.actor.params != HAKA_TRAP_PROPELLER) {
- if (this->dyna.actor.params != HAKA_TRAP_GUILLOTINE_SLOW) {
+ if (this->dyna.actor.params != HAKA_TRAP_FAN_BLADE) {
+ if (this->dyna.actor.params != HAKA_TRAP_GUILLOTINE) {
DynaPoly_DeleteBgActor(play, &play->colCtx.dyna, this->dyna.bgId);
- if ((this->dyna.actor.params == HAKA_TRAP_SPIKED_WALL) ||
- (this->dyna.actor.params == HAKA_TRAP_SPIKED_WALL_2)) {
+ if ((this->dyna.actor.params == HAKA_TRAP_SPIKED_WALL_EAST) ||
+ (this->dyna.actor.params == HAKA_TRAP_SPIKED_WALL_WEST)) {
Collider_DestroyTris(play, &this->spikesCollider);
}
}
@@ -210,61 +242,68 @@ void BgHakaTrap_Destroy(Actor* thisx, PlayState* play) {
Collider_DestroyCylinder(play, &this->colliderCylinder);
}
- Audio_StopSfxByPos(&this->unk_16C);
+ Audio_StopSfxByPos(&this->chainLiftSfxPos);
}
-void func_8087FFC0(BgHakaTrap* this, PlayState* play) {
- f32 cosine;
- Vec3f sp28;
- f32 sine;
- f32 zNonNegative;
+// Updates body collider for HAKA_TRAP_GUILLOTINE, HAKA_TRAP_SPIKED_WALL_EAST, HAKA_TRAP_SPIKED_WALL_WEST
+void BgHakaTrap_UpdateBodyColliderPos(BgHakaTrap* this, PlayState* play) {
+ f32 cos;
+ Vec3f colOff;
+ f32 sin;
+ f32 zSign;
Player* player = GET_PLAYER(play);
- Actor_WorldToActorCoords(&this->dyna.actor, &sp28, &player->actor.world.pos);
+ Actor_WorldToActorCoords(&this->dyna.actor, &colOff, &player->actor.world.pos);
- sine = Math_SinS(this->dyna.actor.shape.rot.y);
- cosine = Math_CosS(this->dyna.actor.shape.rot.y);
- if (this->dyna.actor.params == HAKA_TRAP_GUILLOTINE_SLOW) {
- sp28.x = CLAMP(sp28.x, -50.0f, 50.0f);
- zNonNegative = (sp28.z >= 0.0f) ? 1.0f : -1.0f;
- sp28.z = zNonNegative * -15.0f;
+ sin = Math_SinS(this->dyna.actor.shape.rot.y);
+ cos = Math_CosS(this->dyna.actor.shape.rot.y);
+
+ if (this->dyna.actor.params == HAKA_TRAP_GUILLOTINE) {
+ colOff.x = CLAMP(colOff.x, -50.0f, 50.0f);
+ zSign = (colOff.z >= 0.0f) ? 1.0f : -1.0f;
+ colOff.z = zSign * -15.0f;
} else {
- sp28.x = -CLAMP(sp28.x, -162.0f, 162.0f);
- zNonNegative = (sp28.z >= 0.0f) ? 1.0f : -1.0f;
- sp28.z = zNonNegative * 15.0f;
+ colOff.x = -CLAMP(colOff.x, -162.0f, 162.0f);
+ zSign = (colOff.z >= 0.0f) ? 1.0f : -1.0f;
+ colOff.z = zSign * 15.0f;
}
- this->colliderCylinder.dim.pos.x = this->dyna.actor.world.pos.x + sp28.x * cosine + sp28.z * sine;
- this->colliderCylinder.dim.pos.z = this->dyna.actor.world.pos.z + sp28.x * sine + sp28.z * cosine;
+ this->colliderCylinder.dim.pos.x = this->dyna.actor.world.pos.x + colOff.x * cos + colOff.z * sin;
+ this->colliderCylinder.dim.pos.z = this->dyna.actor.world.pos.z + colOff.x * sin + colOff.z * cos;
}
-void func_808801B8(BgHakaTrap* this, PlayState* play) {
- static UNK_TYPE D_80881018 = 0;
+#define BGHAKATRAP_SPIKEDWALL_HITEAST (1 << 0)
+#define BGHAKATRAP_SPIKEDWALL_HITWEST (1 << 1)
+#define BGHAKATRAP_SPIKEDWALL_CRUSH_PLAYER 4
+
+void BgHakaTrap_SpikedWall_CloseIn(BgHakaTrap* this, PlayState* play) {
+ static s32 sSpikedWallFlags = 0;
Player* player = GET_PLAYER(play);
- if ((D_80880F30 == 0) && (!Player_InCsMode(play))) {
+ if (!sIsSpikeWallBurning && !Player_InCsMode(play)) {
+ // Step towards the home position. If we haven't reached it, play the sliding sfx
if (!Math_StepToF(&this->dyna.actor.world.pos.x, this->dyna.actor.home.pos.x, 0.5f)) {
Actor_PlaySfx_Flagged(&this->dyna.actor, NA_SE_EV_TRAP_OBJ_SLIDE - SFX_FLAG);
- } else if (this->dyna.actor.params == HAKA_TRAP_SPIKED_WALL) {
- D_80881018 |= 1;
- } else if (this->dyna.actor.params == HAKA_TRAP_SPIKED_WALL_2) {
- D_80881018 |= 2;
+ } else if (this->dyna.actor.params == HAKA_TRAP_SPIKED_WALL_EAST) {
+ sSpikedWallFlags |= BGHAKATRAP_SPIKEDWALL_HITEAST;
+ } else if (this->dyna.actor.params == HAKA_TRAP_SPIKED_WALL_WEST) {
+ sSpikedWallFlags |= BGHAKATRAP_SPIKEDWALL_HITWEST;
}
}
- func_8087FFC0(this, play);
+ BgHakaTrap_UpdateBodyColliderPos(this, play);
if (this->spikesCollider.base.acFlags & AC_HIT) {
this->timer = 20;
- D_80880F30 = 1;
- this->actionFunc = func_808802D8;
- } else if (D_80881018 == 3) {
- D_80881018 = 4;
+ sIsSpikeWallBurning = true;
+ this->actionFunc = BgHakaTrap_SpikedWall_Burn;
+ } else if (sSpikedWallFlags == (BGHAKATRAP_SPIKEDWALL_HITEAST | BGHAKATRAP_SPIKEDWALL_HITWEST)) {
+ sSpikedWallFlags = BGHAKATRAP_SPIKEDWALL_CRUSH_PLAYER;
player->actor.bgCheckFlags |= BGCHECKFLAG_CRUSHED;
}
}
-void func_808802D8(BgHakaTrap* this, PlayState* play) {
+void BgHakaTrap_SpikedWall_Burn(BgHakaTrap* this, PlayState* play) {
static Vec3f zeroVec = { 0.0f, 0.0f, 0.0f };
Vec3f vector;
f32 xScale;
@@ -279,7 +318,7 @@ void func_808802D8(BgHakaTrap* this, PlayState* play) {
for (i = 0; i < 2; i++) {
f32 rand = Rand_ZeroOne();
- xScale = (this->dyna.actor.params == HAKA_TRAP_SPIKED_WALL) ? -30.0f : 30.0f;
+ xScale = (this->dyna.actor.params == HAKA_TRAP_SPIKED_WALL_EAST) ? -30.0f : 30.0f;
vector.x = xScale * rand + this->dyna.actor.world.pos.x;
vector.y = Rand_ZeroOne() * 10.0f + this->dyna.actor.world.pos.y + 30.0f;
@@ -289,16 +328,16 @@ void func_808802D8(BgHakaTrap* this, PlayState* play) {
}
if (this->timer == 0) {
- D_80880F30 = 0;
+ sIsSpikeWallBurning = false;
Actor_Kill(&this->dyna.actor);
}
}
-void func_80880484(BgHakaTrap* this, PlayState* play) {
- s32 sp24;
+void BgHakaTrap_Guillotine_Fall(BgHakaTrap* this, PlayState* play) {
+ s32 isDoneFalling;
s32 timer;
- if (this->unk_16A) {
+ if (this->isGuillotineFast) {
this->dyna.actor.velocity.y *= 3.0f;
} else {
this->dyna.actor.velocity.y *= 2.0f;
@@ -308,34 +347,35 @@ void func_80880484(BgHakaTrap* this, PlayState* play) {
this->timer -= 1;
}
- sp24 =
+ isDoneFalling =
Math_StepToF(&this->dyna.actor.world.pos.y, this->dyna.actor.home.pos.y - 185.0f, this->dyna.actor.velocity.y);
timer = this->timer;
- if ((timer == 10 && !this->unk_16A) || (timer == 13 && this->unk_16A)) {
+ if ((timer == 10 && !this->isGuillotineFast) || (timer == 13 && this->isGuillotineFast)) {
Actor_PlaySfx(&this->dyna.actor, NA_SE_EV_GUILLOTINE_BOUND);
}
if (this->timer == 0) {
this->dyna.actor.velocity.y = 0.0f;
- this->timer = (this->unk_16A) ? 10 : 40;
+ this->timer = (this->isGuillotineFast) ? 10 : 40;
Actor_PlaySfx(&this->dyna.actor, NA_SE_EV_GUILLOTINE_UP);
- this->actionFunc = func_808805C0;
+ this->actionFunc = BgHakaTrap_Guillotine_Lift;
}
- func_8087FFC0(this, play);
+ BgHakaTrap_UpdateBodyColliderPos(this, play);
- if (sp24 == 0) {
+ if (!isDoneFalling) {
CollisionCheck_SetAT(play, &play->colChkCtx, &this->colliderCylinder.base);
}
}
-void func_808805C0(BgHakaTrap* this, PlayState* play) {
+void BgHakaTrap_Guillotine_Lift(BgHakaTrap* this, PlayState* play) {
if (this->timer != 0) {
this->timer--;
}
- if (this->unk_16A) {
+ if (this->isGuillotineFast) {
+
Math_StepToF(&this->dyna.actor.world.pos.y, this->dyna.actor.home.pos.y, 27.0f);
} else {
if (this->timer > 20) {
@@ -353,13 +393,13 @@ void func_808805C0(BgHakaTrap* this, PlayState* play) {
this->timer = 20;
this->dyna.actor.world.pos.y = this->dyna.actor.home.pos.y;
this->dyna.actor.velocity.y = 0.1f;
- this->actionFunc = func_80880484;
+ this->actionFunc = BgHakaTrap_Guillotine_Fall;
}
- func_8087FFC0(this, play);
+ BgHakaTrap_UpdateBodyColliderPos(this, play);
}
-void func_808806BC(BgHakaTrap* this, PlayState* play) {
+void BgHakaTrap_SpikedCrusher_Fall(BgHakaTrap* this, PlayState* play) {
Vec3f vector;
f32 floorHeight;
f32 yIntersect;
@@ -372,10 +412,17 @@ void func_808806BC(BgHakaTrap* this, PlayState* play) {
this->timer--;
}
+ // Perform a collision check for the "stone umbrella" block
+ // Because of the shape of the room and the size of the block we only need to check three positions,
+ // the center of the east edge, the centerpoint, and the center of the west edge of the crusher.
+ //
+ // The y coordinate is offset by 25 units, as the crusher is allowed to clip into the floor for visual effect.
+
vector.x = this->dyna.actor.world.pos.x + 90.0f;
vector.y = (this->dyna.actor.world.pos.y + 1.0f) + 25.0f;
vector.z = this->dyna.actor.world.pos.z;
+ // actor.floorHeight is storing the minimum y position of the crusher
floorHeight = this->dyna.actor.floorHeight;
for (i = 0; i < 3; i++) {
@@ -403,77 +450,87 @@ void func_808806BC(BgHakaTrap* this, PlayState* play) {
if (this->timer == 0) {
this->dyna.actor.velocity.y = 0.0f;
this->timer = 30;
- this->unk_16A = (s16)this->dyna.actor.world.pos.y + 50.0f;
- this->unk_16A = CLAMP_MAX(this->unk_16A, this->dyna.actor.home.pos.y);
+ this->spikedCrusherStepY = (s16)this->dyna.actor.world.pos.y + 50.0f;
+ this->spikedCrusherStepY = CLAMP_MAX(this->spikedCrusherStepY, this->dyna.actor.home.pos.y);
- this->actionFunc = func_808808F4;
+ this->actionFunc = BgHakaTrap_SpikedCrusher_Lift;
}
}
-void func_808808F4(BgHakaTrap* this, PlayState* play) {
+void BgHakaTrap_SpikedCrusher_Lift(BgHakaTrap* this, PlayState* play) {
if (this->timer != 0) {
this->timer--;
}
if (this->timer > 20) {
- this->unk_169 = Math_StepToF(&this->dyna.actor.world.pos.y, this->unk_16A, 15.0f);
+ this->isSpikedCrusherStationary = Math_StepToF(&this->dyna.actor.world.pos.y, this->spikedCrusherStepY, 15.0f);
} else {
- this->unk_169 = Math_StepToF(&this->dyna.actor.world.pos.y, this->dyna.actor.home.pos.y, 20.0f);
+ this->isSpikedCrusherStationary =
+ Math_StepToF(&this->dyna.actor.world.pos.y, this->dyna.actor.home.pos.y, 20.0f);
}
if (this->timer == 0) {
this->timer = 30;
this->dyna.actor.world.pos.y = this->dyna.actor.home.pos.y;
this->dyna.actor.velocity.y = 0.5f;
- this->actionFunc = func_808806BC;
+ this->actionFunc = BgHakaTrap_SpikedCrusher_Fall;
}
}
-void func_808809B0(BgHakaTrap* this, PlayState* play) {
+void BgHakaTrap_FanBlade_Idle(BgHakaTrap* this, PlayState* play) {
if (this->timer != 0) {
this->timer -= 1;
}
if (this->timer == 0) {
- this->actionFunc = func_80880AE8;
+ // this->timer = 0, which signals the fan to turn on and speed up
+ this->actionFunc = BgHakaTrap_FanBlade_ToggleFanGust;
}
}
-void func_808809E4(BgHakaTrap* this, PlayState* play, s16 arg2) {
+void BgHakaTrap_PushPlayer(BgHakaTrap* this, PlayState* play, s16 angularVelocity) {
Player* player = GET_PLAYER(play);
- Vec3f sp18;
+ Vec3f playerRelOff;
- Actor_WorldToActorCoords(&this->dyna.actor, &sp18, &player->actor.world.pos);
+ Actor_WorldToActorCoords(&this->dyna.actor, &playerRelOff, &player->actor.world.pos);
- if ((fabsf(sp18.x) < 70.0f) && (fabsf(sp18.y) < 100.0f) && (sp18.z < 500.0f) &&
+ if ((fabsf(playerRelOff.x) < 70.0f) && (fabsf(playerRelOff.y) < 100.0f) && (playerRelOff.z < 500.0f) &&
(GET_PLAYER(play)->currentBoots != PLAYER_BOOTS_IRON)) {
- player->pushedSpeed = ((500.0f - sp18.z) * 0.06f + 5.0f) * arg2 * (1.0f / 0x3A00) * (2.0f / 3.0f);
+ player->pushedSpeed =
+ ((500.0f - playerRelOff.z) * 0.06f + 5.0f) * angularVelocity * (1.0f / 0x3A00) * (2.0f / 3.0f);
player->pushedYaw = this->dyna.actor.shape.rot.y;
}
}
-void func_80880AE8(BgHakaTrap* this, PlayState* play) {
+void BgHakaTrap_FanBlade_ToggleFanGust(BgHakaTrap* this, PlayState* play) {
+ // this->timer stores the current fan behavior.
+ // if 1, the fan is on and is ramping down to the off state.
+ // if 0, the fan is off and is ramping up to the full on state.
+
+ // world.rot.z is the current angular velocity of the fan
if (this->timer != 0) {
+ // Fan winds down
if (Math_ScaledStepToS(&this->dyna.actor.world.rot.z, 0, this->dyna.actor.world.rot.z * 0.03f + 5.0f)) {
this->timer = 40;
- this->actionFunc = func_808809B0;
+ this->actionFunc = BgHakaTrap_FanBlade_Idle;
}
} else {
+ // Fan speeds up
if (Math_ScaledStepToS(&this->dyna.actor.world.rot.z, 0x3A00, this->dyna.actor.world.rot.z * 0.03f + 5.0f)) {
this->timer = 100;
- this->actionFunc = func_80880C0C;
+ this->actionFunc = BgHakaTrap_FanBlade_FullGust;
}
}
this->dyna.actor.shape.rot.z += this->dyna.actor.world.rot.z;
- if (this->dyna.actor.world.rot.z >= 0x1801) {
+ if (this->dyna.actor.world.rot.z > 0x1800) {
Actor_PlaySfx_Flagged(&this->dyna.actor, NA_SE_EV_WIND_TRAP - SFX_FLAG);
}
- func_808809E4(this, play, this->dyna.actor.world.rot.z);
+ BgHakaTrap_PushPlayer(this, play, this->dyna.actor.world.rot.z);
}
-void func_80880C0C(BgHakaTrap* this, PlayState* play) {
+void BgHakaTrap_FanBlade_FullGust(BgHakaTrap* this, PlayState* play) {
if (this->timer != 0) {
this->timer--;
}
@@ -481,12 +538,13 @@ void func_80880C0C(BgHakaTrap* this, PlayState* play) {
Actor_PlaySfx_Flagged(&this->dyna.actor, NA_SE_EV_WIND_TRAP - SFX_FLAG);
if (this->timer == 0) {
- this->timer = 1;
- this->actionFunc = func_80880AE8;
+ this->timer = 1; // setting this signals the fan to turn off and slow down
+ this->actionFunc = BgHakaTrap_FanBlade_ToggleFanGust;
}
+ // world.rot.z is the current angular velocity of the fan
this->dyna.actor.shape.rot.z += this->dyna.actor.world.rot.z;
- func_808809E4(this, play, this->dyna.actor.world.rot.z);
+ BgHakaTrap_PushPlayer(this, play, this->dyna.actor.world.rot.z);
}
void BgHakaTrap_Update(Actor* thisx, PlayState* play) {
@@ -495,14 +553,14 @@ void BgHakaTrap_Update(Actor* thisx, PlayState* play) {
this->actionFunc(this, play);
- if ((this->dyna.actor.params != HAKA_TRAP_PROPELLER) && (thisx->params != HAKA_TRAP_SPIKED_BOX)) {
+ if ((this->dyna.actor.params != HAKA_TRAP_FAN_BLADE) && (thisx->params != HAKA_TRAP_SPIKED_CRUSHER)) {
this->colliderCylinder.dim.pos.y = actorPos->y;
- if ((thisx->params == HAKA_TRAP_GUILLOTINE_SLOW) || (thisx->params == HAKA_TRAP_GUILLOTINE_FAST)) {
+ if ((thisx->params == HAKA_TRAP_GUILLOTINE) || (thisx->params == HAKA_TRAP_GUILLOTINE_FAST)) {
CollisionCheck_SetAC(play, &play->colChkCtx, &this->colliderCylinder.base);
CollisionCheck_SetOC(play, &play->colChkCtx, &this->colliderCylinder.base);
} else {
- if (this->actionFunc == func_808801B8) {
+ if (this->actionFunc == BgHakaTrap_SpikedWall_CloseIn) {
CollisionCheck_SetAC(play, &play->colChkCtx, &this->spikesCollider.base);
}
@@ -511,50 +569,49 @@ void BgHakaTrap_Update(Actor* thisx, PlayState* play) {
}
}
-void func_80880D68(BgHakaTrap* this) {
- Vec3f vec3;
- Vec3f vec2;
- Vec3f vec1;
+void BgHakaTrap_SpikedWall_UpdateCollider(BgHakaTrap* this) {
+ Vec3f vtx[3];
- Matrix_MultVec3f(&sTrisElementsInit[0].dim.vtx[0], &vec1);
- Matrix_MultVec3f(&sTrisElementsInit[0].dim.vtx[1], &vec2);
- Matrix_MultVec3f(&sTrisElementsInit[0].dim.vtx[2], &vec3);
- Collider_SetTrisVertices(&this->spikesCollider, 0, &vec1, &vec2, &vec3);
+ Matrix_MultVec3f(&sSpikedWallTrisElementsInit[0].dim.vtx[0], &vtx[0]);
+ Matrix_MultVec3f(&sSpikedWallTrisElementsInit[0].dim.vtx[1], &vtx[1]);
+ Matrix_MultVec3f(&sSpikedWallTrisElementsInit[0].dim.vtx[2], &vtx[2]);
+ Collider_SetTrisVertices(&this->spikesCollider, 0, &vtx[0], &vtx[1], &vtx[2]);
- Matrix_MultVec3f(&sTrisElementsInit[1].dim.vtx[2], &vec2);
- Collider_SetTrisVertices(&this->spikesCollider, 1, &vec1, &vec3, &vec2);
+ Matrix_MultVec3f(&sSpikedWallTrisElementsInit[1].dim.vtx[2], &vtx[1]);
+ Collider_SetTrisVertices(&this->spikesCollider, 1, &vtx[0], &vtx[2], &vtx[1]);
}
void BgHakaTrap_Draw(Actor* thisx, PlayState* play) {
static Gfx* sDLists[5] = {
- object_haka_objects_DL_007610, object_haka_objects_DL_009860, object_haka_objects_DL_007EF0,
- object_haka_objects_DL_008A20, object_haka_objects_DL_0072C0,
+ gShadowTempleGuillotineDL, gShadowTempleSpikedCrusherDL, gShadowTempleSpikedWallEastDL,
+ gShadowTempleSpikedWallWestDL, gShadowTempleFanBladeDL,
};
- static Color_RGBA8 D_8088103C = { 0, 0, 0, 0 };
+ static Color_RGBA8 sFogBlack = { 0, 0, 0, 0 };
BgHakaTrap* this = (BgHakaTrap*)thisx;
s32 pad;
- Vec3f sp2C;
- if (this->actionFunc == func_808802D8) {
- func_80026230(play, &D_8088103C, this->timer + 20, 0x28);
+ if (this->actionFunc == BgHakaTrap_SpikedWall_Burn) {
+ func_80026230(play, &sFogBlack, this->timer + 20, 40);
}
Gfx_DrawDListOpa(play, sDLists[this->dyna.actor.params]);
- if (this->actionFunc == func_808801B8) {
- func_80880D68(this);
+ if (this->actionFunc == BgHakaTrap_SpikedWall_CloseIn) {
+ BgHakaTrap_SpikedWall_UpdateCollider(this);
}
- if (this->actionFunc == func_808802D8) {
+ if (this->actionFunc == BgHakaTrap_SpikedWall_Burn) {
func_80026608(play);
}
- if ((this->actionFunc == func_808808F4) && !this->unk_169) {
- sp2C.x = this->dyna.actor.world.pos.x;
- sp2C.z = this->dyna.actor.world.pos.z;
- sp2C.y = this->dyna.actor.world.pos.y + 110.0f;
+ if ((this->actionFunc == BgHakaTrap_SpikedCrusher_Lift) && !this->isSpikedCrusherStationary) {
+ Vec3f sfxPos;
- SkinMatrix_Vec3fMtxFMultXYZ(&play->viewProjectionMtxF, &sp2C, &this->unk_16C);
- Sfx_PlaySfxAtPos(&this->unk_16C, NA_SE_EV_BRIDGE_CLOSE - SFX_FLAG);
+ sfxPos.x = this->dyna.actor.world.pos.x;
+ sfxPos.z = this->dyna.actor.world.pos.z;
+ sfxPos.y = this->dyna.actor.world.pos.y + 110.0f;
+
+ SkinMatrix_Vec3fMtxFMultXYZ(&play->viewProjectionMtxF, &sfxPos, &this->chainLiftSfxPos);
+ Sfx_PlaySfxAtPos(&this->chainLiftSfxPos, NA_SE_EV_BRIDGE_CLOSE - SFX_FLAG);
}
}
diff --git a/src/overlays/actors/ovl_Bg_Haka_Trap/z_bg_haka_trap.h b/src/overlays/actors/ovl_Bg_Haka_Trap/z_bg_haka_trap.h
index a75c877ed3..14c7c7a1a3 100644
--- a/src/overlays/actors/ovl_Bg_Haka_Trap/z_bg_haka_trap.h
+++ b/src/overlays/actors/ovl_Bg_Haka_Trap/z_bg_haka_trap.h
@@ -5,11 +5,11 @@
#include "actor.h"
typedef enum HakaTrapType {
- /* 0x00 */ HAKA_TRAP_GUILLOTINE_SLOW,
- /* 0x01 */ HAKA_TRAP_SPIKED_BOX,
- /* 0x02 */ HAKA_TRAP_SPIKED_WALL,
- /* 0x03 */ HAKA_TRAP_SPIKED_WALL_2,
- /* 0x04 */ HAKA_TRAP_PROPELLER,
+ /* 0x00 */ HAKA_TRAP_GUILLOTINE,
+ /* 0x01 */ HAKA_TRAP_SPIKED_CRUSHER,
+ /* 0x02 */ HAKA_TRAP_SPIKED_WALL_EAST,
+ /* 0x03 */ HAKA_TRAP_SPIKED_WALL_WEST,
+ /* 0x04 */ HAKA_TRAP_FAN_BLADE,
/* 0x05 */ HAKA_TRAP_GUILLOTINE_FAST
} HakaTrapType;
@@ -21,9 +21,13 @@ typedef struct BgHakaTrap {
/* 0x0000 */ DynaPolyActor dyna;
/* 0x0164 */ BgHakaTrapActionFunc actionFunc;
/* 0x0168 */ u8 timer;
- /* 0x0169 */ u8 unk_169;
- /* 0x016A */ s16 unk_16A; // used as boolean for HAKA_TRAP_GUILLOTINE_SLOW/FAST, s16 for HAKA_TRAP_SPIKED_BOX
- /* 0x016C */ Vec3f unk_16C;
+ /* 0x0169 */ u8 isSpikedCrusherStationary;
+ /* 0x016A */ union {
+ s16 isGuillotineFast; // 0 slow, 1 fast
+ s16 spikedCrusherStepY; // when lifting the crusher, it will pause briefly at this height before being
+ // lifted to its maximum height
+ };
+ /* 0x016C */ Vec3f chainLiftSfxPos;
/* 0x0178 */ ColliderCylinder colliderCylinder;
/* 0x01C4 */ ColliderTris spikesCollider;
/* 0x01E4 */ ColliderTrisElement spikesColliderElements[2];