pyramid_top.inc.c (5034B)
1 2 /** 3 * Behaviors for bhvPyramidTop, bhvPyramidTopFragment, and 4 * bhvPyramidPillarTouchDetector. 5 * 6 * bhvPyramidTop controls Shifting Sand Land's pyramid's top piece, which 7 * rotates and explodes when Mario stands on all four pillars. 8 * bhvPyramidTopFragment controls the shards that the pyramid's top emits when 9 * it is spinning and exploding. 10 * bhvPyramidPillarTouchDetector controls the intangible collision boxes that 11 * Mario touches when on top of each pillar. 12 */ 13 14 /** 15 * Spawn the four pillars' touch detectors. 16 */ 17 void bhv_pyramid_top_init(void) { 18 spawn_object_abs_with_rot(o, 0, MODEL_NONE, bhvPyramidPillarTouchDetector, 19 1789, 1024, 764, 0, 0, 0); 20 spawn_object_abs_with_rot(o, 0, MODEL_NONE, bhvPyramidPillarTouchDetector, 21 1789, 896, -2579, 0, 0, 0); 22 spawn_object_abs_with_rot(o, 0, MODEL_NONE, bhvPyramidPillarTouchDetector, 23 -5883, 1024, -2579, 0, 0, 0); 24 spawn_object_abs_with_rot(o, 0, MODEL_NONE, bhvPyramidPillarTouchDetector, 25 -5883, 1024, 764, 0, 0, 0); 26 } 27 28 /** 29 * Animate the pyramid top as rising and then spinning. Generate some pyramid 30 * fragments in the process. 31 */ 32 void bhv_pyramid_top_spinning(void) { 33 // (TODO: What is this doing) 34 o->oPosX = o->oHomeX + sins(o->oTimer * 0x4000) * 40.0f; 35 36 // At first, move upward smoothly without rotating. 37 if (o->oTimer < 60) { 38 o->oPosY = o->oHomeY + absf_2(sins(o->oTimer * 0x2000) * 10.0f); 39 } else { 40 // Then, rotate at an accelerating rate, and move upward at a constant rate. 41 o->oAngleVelYaw += 0x100; 42 if (o->oAngleVelYaw > 0x1800) { 43 o->oAngleVelYaw = 0x1800; 44 o->oVelY = 5.0f; 45 } 46 47 o->oFaceAngleYaw += o->oAngleVelYaw; 48 o->oPosY += o->oVelY; 49 } 50 51 // Every frame until 90 frames have passed, generate a pyramid fragment 52 // with a random velocity and angle. 53 if (o->oTimer < 90) { 54 struct Object *pyramidFragment = spawn_object(o, MODEL_DIRT_ANIMATION, bhvPyramidTopFragment); 55 pyramidFragment->oForwardVel = random_float() * 10.0f + 20.0f; 56 pyramidFragment->oMoveAngleYaw = random_u16(); 57 pyramidFragment->oPyramidTopFragmentsScale = 0.8f; 58 pyramidFragment->oGravity = random_float() + 2.0f; 59 } 60 61 // After enough time, transition to the exploding state. 62 if (o->oTimer == 150) { 63 o->oAction = PYRAMID_TOP_ACT_EXPLODE; 64 } 65 } 66 67 /** 68 * Explode the pyramid top, generating dust and pyramid fragments. 69 */ 70 void bhv_pyramid_top_explode(void) { 71 struct Object *pyramidFragment; 72 s16 i; 73 74 spawn_mist_particles_variable(0, 0, 690.0f); 75 76 // Generate 30 pyramid fragments with random properties. 77 for (i = 0; i < 30; i++) { 78 pyramidFragment = spawn_object(o, MODEL_DIRT_ANIMATION, bhvPyramidTopFragment); 79 pyramidFragment->oForwardVel = random_float() * 50 + 80; 80 pyramidFragment->oVelY = random_float() * 80 + 20; 81 pyramidFragment->oMoveAngleYaw = random_u16(); 82 pyramidFragment->oPyramidTopFragmentsScale = 3; 83 pyramidFragment->oGravity = random_float() * 2 + 5; 84 } 85 86 // Deactivate the pyramid top. 87 o->activeFlags = ACTIVE_FLAG_DEACTIVATED; 88 } 89 90 void bhv_pyramid_top_loop(void) { 91 switch (o->oAction) { 92 case PYRAMID_TOP_ACT_CHECK_IF_SOLVED: 93 if (o->oPyramidTopPillarsTouched == 4) { 94 play_puzzle_jingle(); 95 o->oAction = PYRAMID_TOP_ACT_SPINNING; 96 } 97 break; 98 99 case PYRAMID_TOP_ACT_SPINNING: 100 if (o->oTimer == 0) { 101 cur_obj_play_sound_2(SOUND_GENERAL2_PYRAMID_TOP_SPIN); 102 } 103 104 bhv_pyramid_top_spinning(); 105 break; 106 107 case PYRAMID_TOP_ACT_EXPLODE: 108 if (o->oTimer == 0) { 109 create_sound_spawner(SOUND_GENERAL2_PYRAMID_TOP_EXPLOSION); 110 } 111 112 bhv_pyramid_top_explode(); 113 break; 114 } 115 } 116 117 /** 118 * Initialize the pyramid fragment. 119 */ 120 void bhv_pyramid_top_fragment_init(void) { 121 o->oFriction = 0.999f; 122 o->oBuoyancy = 2.0f; 123 o->oAnimState = 3; 124 cur_obj_scale(o->oPyramidTopFragmentsScale); 125 } 126 127 /** 128 * Rotate the pyramid fragment along the yaw and pitch axes. After some time, 129 * deactivate it. 130 */ 131 void bhv_pyramid_top_fragment_loop(void) { 132 object_step(); 133 o->oFaceAngleYaw += 0x1000; 134 o->oFaceAnglePitch += 0x1000; 135 136 if (o->oTimer == 60) { 137 o->activeFlags = ACTIVE_FLAG_DEACTIVATED; 138 } 139 } 140 141 /** 142 * If Mario touches a pillar's touch detector, count it towards the pyramid 143 * top's total count of touched detectors, and deactivate the detector. 144 */ 145 void bhv_pyramid_pillar_touch_detector_loop(void) { 146 cur_obj_become_tangible(); 147 if (obj_check_if_collided_with_object(o, gMarioObject) == TRUE) { 148 // Increase the pyramid top's count of pillars touched. 149 o->parentObj->oPyramidTopPillarsTouched++; 150 o->activeFlags = ACTIVE_FLAG_DEACTIVATED; 151 } 152 }