2019-08-25 04:46:40 +00:00
|
|
|
/**
|
|
|
|
* Behaviors for bhvPyramidTop, bhvPyramidTopFragment, and
|
|
|
|
* bhvPyramidPillarTouchDetector.
|
|
|
|
*
|
|
|
|
* bhvPyramidTop controls Shifting Sand Land's pyramid's top piece, which
|
|
|
|
* rotates and explodes when Mario stands on all four pillars.
|
|
|
|
* bhvPyramidTopFragment controls the shards that the pyramid's top emits when
|
|
|
|
* it is spinning and exploding.
|
|
|
|
* bhvPyramidPillarTouchDetector controls the intangible collision boxes that
|
|
|
|
* Mario touches when on top of each pillar.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Spawn the four pillars' touch detectors.
|
|
|
|
*/
|
|
|
|
void bhv_pyramid_top_init(void) {
|
|
|
|
spawn_object_abs_with_rot(o, 0, MODEL_NONE, bhvPyramidPillarTouchDetector, 1789, 1024, 764, 0, 0,
|
|
|
|
0);
|
|
|
|
spawn_object_abs_with_rot(o, 0, MODEL_NONE, bhvPyramidPillarTouchDetector, 1789, 896, -2579, 0, 0,
|
|
|
|
0);
|
|
|
|
spawn_object_abs_with_rot(o, 0, MODEL_NONE, bhvPyramidPillarTouchDetector, -5883, 1024, -2579, 0, 0,
|
|
|
|
0);
|
|
|
|
spawn_object_abs_with_rot(o, 0, MODEL_NONE, bhvPyramidPillarTouchDetector, -5883, 1024, 764, 0, 0,
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Animate the pyramid top as rising and then spinning. Generate some pyramid
|
|
|
|
* fragments in the process.
|
|
|
|
*/
|
|
|
|
void bhv_pyramid_top_spinning(void) {
|
|
|
|
struct Object *pyramidFragment;
|
|
|
|
|
|
|
|
// (TODO: What is this doing)
|
|
|
|
o->oPosX = o->oHomeX + sins(o->oTimer * 0x4000) * 40.0f;
|
|
|
|
|
|
|
|
// At first, move upward smoothly without rotating.
|
|
|
|
if (o->oTimer < 60) {
|
|
|
|
o->oPosY = o->oHomeY + absf_2(sins(o->oTimer * 0x2000) * 10.0f);
|
|
|
|
} else {
|
|
|
|
// Then, rotate at an accelerating rate, and move upward at a constant rate.
|
|
|
|
o->oAngleVelYaw += 0x100;
|
|
|
|
if (o->oAngleVelYaw > 0x1800) {
|
|
|
|
o->oAngleVelYaw = 0x1800;
|
|
|
|
o->oVelY = 5.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
o->oFaceAngleYaw += o->oAngleVelYaw;
|
|
|
|
o->oPosY += o->oVelY;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Every frame until 90 frames have passed, generate a pyramid fragment
|
|
|
|
// with a random velocity and angle.
|
|
|
|
if (o->oTimer < 90) {
|
|
|
|
pyramidFragment = spawn_object(o, MODEL_DIRT_ANIMATION, bhvPyramidTopFragment);
|
|
|
|
pyramidFragment->oForwardVel = RandomFloat() * 10.0f + 20.0f;
|
|
|
|
pyramidFragment->oMoveAngleYaw = RandomU16();
|
2019-10-05 19:08:05 +00:00
|
|
|
pyramidFragment->oPyramidTopFragmentsScale = 0.8f;
|
2019-08-25 04:46:40 +00:00
|
|
|
pyramidFragment->oGravity = RandomFloat() + 2.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
// After enough time, transition to the exploding state.
|
|
|
|
if (o->oTimer == 150) {
|
|
|
|
o->oAction = PYRAMID_TOP_ACT_EXPLODE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Explode the pyramid top, generating dust and pyramid fragments.
|
|
|
|
*/
|
|
|
|
void bhv_pyramid_top_explode(void) {
|
|
|
|
struct Object *pyramidFragment;
|
|
|
|
s16 i;
|
|
|
|
|
2019-09-01 19:50:50 +00:00
|
|
|
func_802AA618(0, 0, 690);
|
2019-08-25 04:46:40 +00:00
|
|
|
|
|
|
|
// Generate 30 pyramid fragments with random properties.
|
|
|
|
for (i = 0; i < 30; i++) {
|
2019-09-01 19:50:50 +00:00
|
|
|
pyramidFragment = spawn_object(
|
|
|
|
o, MODEL_DIRT_ANIMATION, bhvPyramidTopFragment
|
|
|
|
);
|
|
|
|
pyramidFragment->oForwardVel = RandomFloat() * 50 + 80;
|
|
|
|
pyramidFragment->oVelY = RandomFloat() * 80 + 20;
|
2019-08-25 04:46:40 +00:00
|
|
|
pyramidFragment->oMoveAngleYaw = RandomU16();
|
2019-10-05 19:08:05 +00:00
|
|
|
pyramidFragment->oPyramidTopFragmentsScale = 3;
|
2019-09-01 19:50:50 +00:00
|
|
|
pyramidFragment->oGravity = RandomFloat() * 2 + 5;
|
2019-08-25 04:46:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Deactivate the pyramid top.
|
|
|
|
o->activeFlags = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void bhv_pyramid_top_loop(void) {
|
|
|
|
switch (o->oAction) {
|
|
|
|
case PYRAMID_TOP_ACT_CHECK_IF_SOLVED:
|
|
|
|
if (o->oPyramidTopPillarsTouched == 4) {
|
|
|
|
play_puzzle_jingle();
|
|
|
|
o->oAction = PYRAMID_TOP_ACT_SPINNING;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PYRAMID_TOP_ACT_SPINNING:
|
|
|
|
if (o->oTimer == 0) {
|
2019-10-05 19:08:05 +00:00
|
|
|
PlaySound2(SOUND_GENERAL2_PYRAMID_TOP_SPIN);
|
2019-08-25 04:46:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bhv_pyramid_top_spinning();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PYRAMID_TOP_ACT_EXPLODE:
|
|
|
|
if (o->oTimer == 0) {
|
2019-10-05 19:08:05 +00:00
|
|
|
create_sound_spawner(SOUND_GENERAL2_PYRAMID_TOP_EXPLOSION);
|
2019-08-25 04:46:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bhv_pyramid_top_explode();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Initialize the pyramid fragment.
|
|
|
|
*/
|
|
|
|
void bhv_pyramid_top_fragment_init(void) {
|
|
|
|
o->oFriction = 0.999f;
|
|
|
|
o->oBuoyancy = 2.0f;
|
|
|
|
o->oAnimState = 3;
|
|
|
|
obj_scale(o->oPyramidTopFragmentsScale);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Rotate the pyramid fragment along the yaw and pitch axes. After some time,
|
|
|
|
* deactivate it.
|
|
|
|
*/
|
|
|
|
void bhv_pyramid_top_fragment_loop(void) {
|
2019-12-02 02:52:53 +00:00
|
|
|
object_step();
|
2019-08-25 04:46:40 +00:00
|
|
|
o->oFaceAngleYaw += 0x1000;
|
|
|
|
o->oFaceAnglePitch += 0x1000;
|
|
|
|
|
|
|
|
if (o->oTimer == 60) {
|
|
|
|
o->activeFlags = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If Mario touches a pillar's touch detector, count it towards the pyramid
|
|
|
|
* top's total count of touched detectors, and deactivate the detector.
|
|
|
|
*/
|
|
|
|
void bhv_pyramid_pillar_touch_detector_loop(void) {
|
|
|
|
obj_become_tangible();
|
|
|
|
if (are_objects_collided(o, gMarioObject) == 1) {
|
|
|
|
// Increase the pyramid top's count of pillars touched.
|
|
|
|
o->parentObj->oPyramidTopPillarsTouched++;
|
|
|
|
o->activeFlags = 0;
|
|
|
|
}
|
|
|
|
}
|