/** * 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. cur_obj_play_sound_2(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); spawn_mist_particles_variable(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. obj_set_hitbox(o, &sFallingPillarHitbox); // When the pillar goes inactive, the hitboxes also go inactive. if (o->parentObj->activeFlags == 0) o->activeFlags = 0; }