sm64pc/src/game/behaviors/falling_pillar.inc.c

145 lines
4.7 KiB
C

/**
* Behavior for the falling pillars inside the underwater cave area of
* Jolly Roger Bay.
*
* Also includes behavior for the invisible hitboxes they spawn.
*/
static struct ObjectHitbox sFallingPillarHitbox = {
/* interactType: */ INTERACT_DAMAGE,
/* downOffset: */ 150,
/* damageOrCoinValue: */ 3,
/* health: */ 0,
/* numLootCoins: */ 0,
/* radius: */ 150,
/* height: */ 300,
/* hurtboxRadius: */ 0,
/* hurtboxHeight: */ 0,
};
/**
* Initiates various physics params for the pillar.
*/
void bhv_falling_pillar_init(void) {
o->oGravity = 0.5f;
o->oFriction = 0.91f;
o->oBuoyancy = 1.3f;
}
/**
* Spawns 4 hitboxes with Y coordinates offset.
*/
void bhv_falling_pillar_spawn_hitboxes(void) {
s32 i;
for (i = 0; i < 4; i++) {
spawn_object_relative(i, 0, i * 400 + 300, 0, o, MODEL_NONE, bhvFallingPillarHitbox);
}
}
/**
* Computes the angle from current pillar position to 500 units in front of
* Mario.
*/
s16 bhv_falling_pillar_calculate_angle_in_front_of_mario(void) {
f32 targetX;
f32 targetZ;
// Calculate target to be 500 units in front of Mario in
// the direction he is facing (angle[1] is yaw).
targetX = sins(gMarioObject->header.gfx.angle[1]) * 500.0f + gMarioObject->header.gfx.pos[0];
targetZ = coss(gMarioObject->header.gfx.angle[1]) * 500.0f + gMarioObject->header.gfx.pos[2];
// Calculate the angle to the target from the pillar's current location.
return atan2s(targetZ - o->oPosZ, targetX - o->oPosX);
}
/**
* Falling pillar main logic loop.
*/
void bhv_falling_pillar_loop(void) {
s16 angleInFrontOfMario;
switch (o->oAction) {
case FALLING_PILLAR_ACT_IDLE:
// When Mario is within 1300 units of distance...
if (is_point_within_radius_of_mario(o->oPosX, o->oPosY, o->oPosZ, 1300)) {
// Begin slightly moving towards Mario.
o->oMoveAngleYaw = o->oAngleToMario;
o->oForwardVel = 1.0f;
// Spawn the invisible hitboxes.
bhv_falling_pillar_spawn_hitboxes();
// Start turning towards Mario.
o->oAction = FALLING_PILLAR_ACT_TURNING;
// Play the detaching sound.
PlaySound2(SOUND_GENERAL_POUND_ROCK);
}
break;
case FALLING_PILLAR_ACT_TURNING:
object_step_without_floor_orient();
// Calculate angle in front of Mario and turn towards it.
angleInFrontOfMario = bhv_falling_pillar_calculate_angle_in_front_of_mario();
o->oFaceAngleYaw = approach_s16_symmetric(o->oFaceAngleYaw, angleInFrontOfMario, 0x400);
// After 10 ticks, start falling.
if (o->oTimer > 10)
o->oAction = FALLING_PILLAR_ACT_FALLING;
break;
case FALLING_PILLAR_ACT_FALLING:
object_step_without_floor_orient();
// Start falling slowly, with increasing acceleration each frame.
o->oFallingPillarPitchAcceleration += 4.0f;
o->oAngleVelPitch += o->oFallingPillarPitchAcceleration;
o->oFaceAnglePitch += o->oAngleVelPitch;
// Once the pillar has turned nearly 90 degrees (after ~22 frames),
if (o->oFaceAnglePitch > 0x3900) {
// Move 500 units in the direction of falling.
o->oPosX += sins(o->oFaceAngleYaw) * 500.0f;
o->oPosZ += coss(o->oFaceAngleYaw) * 500.0f;
// Make the camera shake and spawn dust clouds.
set_camera_shake_from_point(SHAKE_POS_MEDIUM, o->oPosX, o->oPosY, o->oPosZ);
func_802AA618(0, 0, 92.0f);
// Go invisible.
o->activeFlags = 0;
// Play the hitting the ground sound.
create_sound_spawner(SOUND_GENERAL_BIG_POUND);
}
break;
}
}
/**
* Main loop for the invisible hitboxes.
*/
void bhv_falling_pillar_hitbox_loop(void) {
// Get the state of the pillar.
s32 pitch = o->parentObj->oFaceAnglePitch;
s32 yaw = o->parentObj->oFaceAngleYaw;
f32 x = o->parentObj->oPosX;
f32 y = o->parentObj->oPosY;
f32 z = o->parentObj->oPosZ;
f32 yOffset = o->oBehParams2ndByte * 400 + 300;
// Update position of hitboxes so they fall with the pillar.
o->oPosX = sins(pitch) * sins(yaw) * yOffset + x;
o->oPosY = coss(pitch) * yOffset + y;
o->oPosZ = sins(pitch) * coss(yaw) * yOffset + z;
// Give these a hitbox so they can collide with Mario.
set_object_hitbox(o, &sFallingPillarHitbox);
// When the pillar goes inactive, the hitboxes also go inactive.
if (o->parentObj->activeFlags == 0)
o->activeFlags = 0;
}