bg_haka_trap documentation pass (#2683)

* document pass on bg_haka_trap

* formatting

* suggestions

* dragorn suggestions
This commit is contained in:
mzxrules
2026-02-17 10:09:54 -05:00
committed by GitHub
parent 3d4e8e32c3
commit 1884569a98
3 changed files with 224 additions and 163 deletions
@@ -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);
}
}
@@ -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];