bowser_flame.inc.c (8026B)
1 // bowser_flame.inc.c 2 3 struct ObjectHitbox sGrowingBowserFlameHitbox = { 4 /* interactType: */ INTERACT_FLAME, 5 /* downOffset: */ 20, 6 /* damageOrCoinValue: */ 1, 7 /* health: */ 0, 8 /* numLootCoins: */ 0, 9 /* radius: */ 10, 10 /* height: */ 40, 11 /* hurtboxRadius: */ 0, 12 /* hurtboxHeight: */ 0, 13 }; 14 15 struct ObjectHitbox sBowserFlameHitbox = { 16 /* interactType: */ INTERACT_FLAME, 17 /* downOffset: */ 0, 18 /* damageOrCoinValue: */ 1, 19 /* health: */ 0, 20 /* numLootCoins: */ 0, 21 /* radius: */ 10, 22 /* height: */ 40, 23 /* hurtboxRadius: */ 0, 24 /* hurtboxHeight: */ 0, 25 }; 26 27 void bowser_flame_despawn(void) { 28 obj_mark_for_deletion(o); 29 spawn_object_with_scale(o, MODEL_NONE, bhvBlackSmokeUpward, 1.0f); 30 if (random_float() < 0.1) { 31 spawn_object(o, MODEL_YELLOW_COIN, bhvTemporaryYellowCoin); 32 } 33 } 34 35 s32 bowser_flame_should_despawn(s32 maxTime) { 36 if (maxTime < o->oTimer) { 37 return TRUE; 38 } 39 40 // Flames should despawn if they fall off the arena. 41 if (o->oFloorType == SURFACE_BURNING) { 42 return TRUE; 43 } 44 if (o->oFloorType == SURFACE_DEATH_PLANE) { 45 return TRUE; 46 } 47 48 return FALSE; 49 } 50 51 void bhv_flame_bowser_init(void) { 52 o->oAnimState = (s32)(random_float() * 10.0f); 53 o->oMoveAngleYaw = random_u16(); 54 o->oVelY = random_float() < 0.2 ? 80.0f : 20.0f; 55 o->oForwardVel = 10.0f; 56 o->oGravity = -1.0f; 57 o->oFlameScale = random_float() + 1.0f; 58 } 59 60 void bhv_flame_large_burning_out_init(void) { 61 o->oAnimState = (s32)(random_float() * 10.0f); 62 o->oMoveAngleYaw = random_u16(); 63 o->oVelY = 10.0f; 64 o->oForwardVel = 0.0f; 65 o->oFlameScale = 7.0f; 66 } 67 68 void bowser_flame_move(void) { 69 s32 timer = ((o->oFlameSpeedTimerOffset + gGlobalTimer) & 0x3F) << 10; 70 o->oPosX += sins(o->oMoveAngleYaw) * sins(timer) * 4.0f; 71 o->oPosZ += coss(o->oMoveAngleYaw) * sins(timer) * 4.0f; 72 } 73 74 void bhv_flame_bowser_loop(void) { 75 cur_obj_update_floor_and_walls(); 76 cur_obj_move_standard(78); 77 78 if (o->oVelY < -4.0f) { 79 o->oVelY = -4.0f; 80 } 81 82 if (o->oAction == 0) { 83 cur_obj_become_intangible(); 84 bowser_flame_move(); 85 86 if (o->oMoveFlags & OBJ_MOVE_LANDED) { 87 o->oAction++; 88 if (cur_obj_has_behavior(bhvFlameLargeBurningOut)) { 89 o->oFlameScale = 8.0f; 90 } else { 91 o->oFlameScale = random_float() * 2 + 6.0f; 92 } 93 o->oForwardVel = 0; 94 o->oVelY = 0; 95 o->oGravity = 0; 96 } 97 } else { 98 cur_obj_become_tangible(); 99 100 if (o->oTimer > o->oFlameScale * 10 + 5.0f) { 101 o->oFlameScale -= 0.15; 102 if (o->oFlameScale <= 0) { 103 bowser_flame_despawn(); 104 } 105 } 106 } 107 108 cur_obj_scale(o->oFlameScale); 109 o->oGraphYOffset = o->header.gfx.scale[1] * 14.0f; 110 obj_set_hitbox(o, &sBowserFlameHitbox); 111 } 112 113 void bhv_flame_moving_forward_growing_init(void) { 114 o->oForwardVel = 30.0f; 115 obj_translate_xz_random(o, 80.0f); 116 o->oAnimState = (s32)(random_float() * 10.0f); 117 o->oFlameScale = 3.0f; 118 } 119 120 void bhv_flame_moving_forward_growing_loop(void) { 121 UNUSED u8 filler[4]; 122 UNUSED struct Object *flame; 123 124 obj_set_hitbox(o, &sGrowingBowserFlameHitbox); 125 o->oFlameScale = o->oFlameScale + 0.5; 126 cur_obj_scale(o->oFlameScale); 127 128 if (o->oMoveAnglePitch > 0x800) { 129 o->oMoveAnglePitch -= 0x200; 130 } 131 132 cur_obj_set_pos_via_transform(); 133 cur_obj_update_floor_height(); 134 135 if (o->oFlameScale > 30.0f) { 136 obj_mark_for_deletion(o); 137 } 138 139 if (o->oPosY < o->oFloorHeight) { 140 o->oPosY = o->oFloorHeight; 141 flame = spawn_object(o, MODEL_RED_FLAME, bhvFlameBowser); 142 obj_mark_for_deletion(o); 143 } 144 } 145 146 void bhv_flame_floating_landing_init(void) { 147 o->oAnimState = (s32)(random_float() * 10.0f); 148 o->oMoveAngleYaw = random_u16(); 149 if (o->oBhvParams2ndByte != 0) { 150 o->oForwardVel = random_float() * 5.0f; 151 } else { 152 o->oForwardVel = random_float() * 70.0f; 153 } 154 o->oVelY = random_float() * 20.0f; 155 o->oGravity = -1.0f; 156 o->oFlameSpeedTimerOffset = random_float() * 64.0f; 157 } 158 159 f32 sFlameFloatingYLimit[] = { -8.0f, -6.0f, -3.0f }; 160 161 void bhv_flame_floating_landing_loop(void) { 162 UNUSED u8 filler[4]; 163 164 cur_obj_update_floor_and_walls(); 165 cur_obj_move_standard(78); 166 bowser_flame_move(); 167 168 if (bowser_flame_should_despawn(900)) { 169 obj_mark_for_deletion(o); 170 } 171 172 if (o->oVelY < sFlameFloatingYLimit[o->oBhvParams2ndByte]) { 173 o->oVelY = sFlameFloatingYLimit[o->oBhvParams2ndByte]; 174 } 175 176 if (o->oMoveFlags & OBJ_MOVE_LANDED) { 177 if (o->oBhvParams2ndByte == 0) { 178 spawn_object(o, MODEL_RED_FLAME, bhvFlameLargeBurningOut); 179 } else { 180 spawn_object(o, MODEL_NONE, bhvBlueFlamesGroup); //? wonder if they meant MODEL_BLUE_FLAME? 181 } 182 obj_mark_for_deletion(o); 183 } 184 185 o->oGraphYOffset = o->header.gfx.scale[1] * 14.0f; 186 } 187 188 void bhv_blue_bowser_flame_init(void) { 189 obj_translate_xz_random(o, 80.0f); 190 o->oAnimState = (s32)(random_float() * 10.0f); 191 o->oVelY = 7.0f; 192 o->oForwardVel = 35.0f; 193 o->oFlameScale = 3.0f; 194 o->oFlameUnusedRand = random_float() * 0.5; 195 o->oGravity = 1.0f; 196 o->oFlameSpeedTimerOffset = (s32)(random_float() * 64.0f); 197 } 198 199 void bhv_blue_bowser_flame_loop(void) { 200 s32 i; 201 202 obj_set_hitbox(o, &sGrowingBowserFlameHitbox); 203 204 if (o->oFlameScale < 16.0f) { 205 o->oFlameScale = o->oFlameScale + 0.5; 206 } 207 208 cur_obj_scale(o->oFlameScale); 209 cur_obj_update_floor_and_walls(); 210 cur_obj_move_standard(78); 211 212 if (o->oTimer > 20) { 213 if (o->oBhvParams2ndByte == 0) { 214 for (i = 0; i < 3; i++) { 215 spawn_object_relative_with_scale(0, 0, 0, 0, 5.0f, o, MODEL_RED_FLAME, 216 bhvFlameFloatingLanding); 217 } 218 } else { 219 spawn_object_relative_with_scale(1, 0, 0, 0, 8.0f, o, MODEL_BLUE_FLAME, 220 bhvFlameFloatingLanding); 221 spawn_object_relative_with_scale(2, 0, 0, 0, 8.0f, o, MODEL_BLUE_FLAME, 222 bhvFlameFloatingLanding); 223 } 224 obj_mark_for_deletion(o); 225 } 226 } 227 228 void bhv_flame_bouncing_init(void) { 229 o->oAnimState = (s32)(random_float() * 10.0f); 230 o->oVelY = 30.0f; 231 o->oForwardVel = 20.0f; 232 o->oFlameScale = o->header.gfx.scale[0]; 233 o->oFlameSpeedTimerOffset = (s32)(random_float() * 64.0f); 234 } 235 236 void bhv_flame_bouncing_loop(void) { 237 struct Object *bowser; 238 239 if (o->oTimer == 0) { 240 o->oFlameBowser = cur_obj_nearest_object_with_behavior(bhvBowser); 241 } 242 243 bowser = o->oFlameBowser; 244 o->oForwardVel = 15.0f; 245 o->oBounciness = -1.0f; 246 cur_obj_scale(o->oFlameScale); 247 obj_set_hitbox(o, &sGrowingBowserFlameHitbox); 248 cur_obj_update_floor_and_walls(); 249 cur_obj_move_standard(78); 250 251 if (bowser_flame_should_despawn(300)) { 252 obj_mark_for_deletion(o); 253 } 254 255 if (bowser != NULL) { 256 if (bowser->oHeldState == HELD_FREE) { 257 if (lateral_dist_between_objects(o, bowser) < 300.0f) { 258 obj_mark_for_deletion(o); 259 } 260 } 261 } 262 } 263 264 void bhv_blue_flames_group_loop(void) { 265 struct Object *flame; 266 s32 i; 267 268 if (o->oTimer == 0) { 269 o->oMoveAngleYaw = obj_angle_to_object(o, gMarioObject); 270 o->oBlueFlameNextScale = 5.0f; 271 } 272 273 if (o->oTimer < 16) { 274 if (!(o->oTimer & 1)) { 275 for (i = 0; i < 3; i++) { 276 flame = spawn_object(o, MODEL_BLUE_FLAME, bhvFlameBouncing); 277 flame->oMoveAngleYaw += i * 0x5555; 278 flame->header.gfx.scale[0] = o->oBlueFlameNextScale; 279 } 280 o->oBlueFlameNextScale -= 0.5; 281 } 282 } else { 283 obj_mark_for_deletion(o); 284 } 285 }