enemy_lakitu.inc.c (5944B)
1 2 /** 3 * Behavior for bhvEnemyLakitu. 4 * Lakitu comes before it spawned spinies in processing order. 5 * TODO: bhvCloud processing oredr 6 */ 7 8 /** 9 * Hitbox for evil lakitu. 10 */ 11 static struct ObjectHitbox sEnemyLakituHitbox = { 12 /* interactType: */ INTERACT_HIT_FROM_BELOW, 13 /* downOffset: */ 0, 14 /* damageOrCoinValue: */ 2, 15 /* health: */ 0, 16 /* numLootCoins: */ 5, 17 /* radius: */ 50, 18 /* height: */ 50, 19 /* hurtboxRadius: */ 40, 20 /* hurtboxHeight: */ 50, 21 }; 22 23 /** 24 * Wait for mario to approach, then spawn the cloud and become visible. 25 */ 26 static void enemy_lakitu_act_uninitialized(void) { 27 if (o->oDistanceToMario < 2000.0f) { 28 spawn_object_relative_with_scale(CLOUD_BP_LAKITU_CLOUD, 0, 0, 0, 2.0f, o, MODEL_MIST, bhvCloud); 29 30 cur_obj_unhide(); 31 o->oAction = ENEMY_LAKITU_ACT_MAIN; 32 } 33 } 34 35 /** 36 * Accelerate toward mario vertically. 37 */ 38 static void enemy_lakitu_update_vel_y(f32 offsetY) { 39 // In order to encourage oscillation, pass mario by a small margin before 40 // accelerating the opposite direction 41 f32 margin; 42 if (o->oVelY < 0.0f) { 43 margin = -3.0f; 44 } else { 45 margin = 3.0f; 46 } 47 48 if (o->oPosY < gMarioObject->oPosY + offsetY + margin) { 49 obj_y_vel_approach(4.0f, 0.4f); 50 } else { 51 obj_y_vel_approach(-4.0f, 0.4f); 52 } 53 } 54 55 /** 56 * Control speed based on distance to mario, turn toward mario, and change move 57 * angle toward mario. 58 */ 59 static void enemy_lakitu_update_speed_and_angle(void) { 60 f32 minSpeed; 61 s16 turnSpeed; 62 63 f32 distToMario = o->oDistanceToMario; 64 if (distToMario > 500.0f) { 65 distToMario = 500.0f; 66 } 67 68 // Move faster the farther away mario is and the faster mario is moving 69 if ((minSpeed = 1.2f * gMarioStates[0].forwardVel) < 8.0f) { 70 minSpeed = 8.0f; 71 } 72 o->oForwardVel = distToMario * 0.04f; 73 clamp_f32(&o->oForwardVel, minSpeed, 40.0f); 74 75 // Accelerate toward mario vertically 76 enemy_lakitu_update_vel_y(300.0f); 77 78 // Turn toward mario except right after throwing a spiny 79 if (o->oEnemyLakituFaceForwardCountdown != 0) { 80 o->oEnemyLakituFaceForwardCountdown--; 81 } else { 82 obj_face_yaw_approach(o->oAngleToMario, 0x600); 83 } 84 85 // Change move angle toward mario faster when farther from mario 86 turnSpeed = (s16)(distToMario * 2); 87 clamp_s16(&turnSpeed, 200, 4000); 88 cur_obj_rotate_yaw_toward(o->oAngleToMario, turnSpeed); 89 } 90 91 /** 92 * When close enough to mario and facing roughly toward him, spawn a spiny and 93 * hold it, then enter the hold spiny sub-action. 94 */ 95 static void enemy_lakitu_sub_act_no_spiny(void) { 96 cur_obj_init_animation_with_sound(1); 97 98 if (o->oEnemyLakituSpinyCooldown != 0) { 99 o->oEnemyLakituSpinyCooldown--; 100 } else if (o->oEnemyLakituNumSpinies < 3 && o->oDistanceToMario < 800.0f 101 && abs_angle_diff(o->oAngleToMario, o->oFaceAngleYaw) < 0x4000) { 102 struct Object *spiny = spawn_object(o, MODEL_SPINY_BALL, bhvSpiny); 103 if (spiny != NULL) { 104 o->prevObj = spiny; 105 spiny->oAction = SPINY_ACT_HELD_BY_LAKITU; 106 obj_init_animation_with_sound(spiny, spiny_egg_seg5_anims_050157E4, 0); 107 108 o->oEnemyLakituNumSpinies++; 109 o->oSubAction = ENEMY_LAKITU_SUB_ACT_HOLD_SPINY; 110 o->oEnemyLakituSpinyCooldown = 30; 111 } 112 } 113 } 114 115 /** 116 * When close to mario and facing toward him or when mario gets far enough away, 117 * enter the throw spiny sub-action. 118 */ 119 static void enemy_lakitu_sub_act_hold_spiny(void) { 120 cur_obj_init_anim_extend(3); 121 122 if (o->oEnemyLakituSpinyCooldown != 0) { 123 o->oEnemyLakituSpinyCooldown--; 124 } 125 // TODO: Check if anything interesting happens if we bypass this with speed 126 else if (o->oDistanceToMario > o->oDrawingDistance - 100.0f 127 || (o->oDistanceToMario < 500.0f 128 && abs_angle_diff(o->oAngleToMario, o->oFaceAngleYaw) < 0x2000)) { 129 o->oSubAction = ENEMY_LAKITU_SUB_ACT_THROW_SPINY; 130 o->oEnemyLakituFaceForwardCountdown = 20; 131 } 132 } 133 134 /** 135 * Throw the spiny, then enter the no spiny sub-action. 136 */ 137 static void enemy_lakitu_sub_act_throw_spiny(void) { 138 if (cur_obj_init_anim_check_frame(2, 2)) { 139 cur_obj_play_sound_2(SOUND_OBJ_EVIL_LAKITU_THROW); 140 o->prevObj = NULL; 141 } 142 143 if (cur_obj_check_if_near_animation_end()) { 144 o->oSubAction = ENEMY_LAKITU_SUB_ACT_NO_SPINY; 145 o->oEnemyLakituSpinyCooldown = random_linear_offset(100, 100); 146 } 147 } 148 149 /** 150 * Main update function. 151 */ 152 static void enemy_lakitu_act_main(void) { 153 cur_obj_play_sound_1(SOUND_AIR_LAKITU_FLY); 154 155 cur_obj_update_floor_and_walls(); 156 157 enemy_lakitu_update_speed_and_angle(); 158 if (o->oMoveFlags & OBJ_MOVE_HIT_WALL) { 159 o->oMoveAngleYaw = cur_obj_reflect_move_angle_off_wall(); 160 } 161 162 obj_update_blinking(&o->oEnemyLakituBlinkTimer, 20, 40, 4); 163 164 switch (o->oSubAction) { 165 case ENEMY_LAKITU_SUB_ACT_NO_SPINY: 166 enemy_lakitu_sub_act_no_spiny(); 167 break; 168 case ENEMY_LAKITU_SUB_ACT_HOLD_SPINY: 169 enemy_lakitu_sub_act_hold_spiny(); 170 break; 171 case ENEMY_LAKITU_SUB_ACT_THROW_SPINY: 172 enemy_lakitu_sub_act_throw_spiny(); 173 break; 174 } 175 176 cur_obj_move_standard(78); 177 178 // Die and drop held spiny when attacked by mario 179 if (obj_check_attacks(&sEnemyLakituHitbox, o->oAction) != 0) { 180 // The spiny uses this as a signal to get thrown 181 o->prevObj = NULL; 182 } 183 } 184 185 /** 186 * Update function for bhvEnemyLakitu. 187 */ 188 void bhv_enemy_lakitu_update(void) { 189 // PARTIAL_UPDATE 190 191 treat_far_home_as_mario(2000.0f); 192 193 switch (o->oAction) { 194 case ENEMY_LAKITU_ACT_UNINITIALIZED: 195 enemy_lakitu_act_uninitialized(); 196 break; 197 case ENEMY_LAKITU_ACT_MAIN: 198 enemy_lakitu_act_main(); 199 break; 200 } 201 }