coin.inc.c (8538B)
1 // coin.inc.c 2 3 struct ObjectHitbox sYellowCoinHitbox = { 4 /* interactType: */ INTERACT_COIN, 5 /* downOffset: */ 0, 6 /* damageOrCoinValue: */ 1, 7 /* health: */ 0, 8 /* numLootCoins: */ 0, 9 /* radius: */ 100, 10 /* height: */ 64, 11 /* hurtboxRadius: */ 0, 12 /* hurtboxHeight: */ 0, 13 }; 14 15 s32 bhv_coin_sparkles_init(void) { 16 if (o->oInteractStatus & INT_STATUS_INTERACTED 17 && !(o->oInteractStatus & INT_STATUS_TOUCHED_BOB_OMB)) { 18 spawn_object(o, MODEL_SPARKLES, bhvGoldenCoinSparkles); 19 obj_mark_for_deletion(o); 20 return TRUE; 21 } 22 23 o->oInteractStatus = 0; 24 25 return FALSE; 26 } 27 28 void bhv_yellow_coin_init(void) { 29 cur_obj_set_behavior(bhvYellowCoin); 30 obj_set_hitbox(o, &sYellowCoinHitbox); 31 bhv_init_room(); 32 cur_obj_update_floor_height(); 33 34 if (500.0f < absf(o->oPosY - o->oFloorHeight)) { 35 cur_obj_set_model(MODEL_YELLOW_COIN_NO_SHADOW); 36 } 37 38 if (o->oFloorHeight < FLOOR_LOWER_LIMIT_MISC) { 39 obj_mark_for_deletion(o); 40 } 41 } 42 43 void bhv_yellow_coin_loop(void) { 44 bhv_coin_sparkles_init(); 45 o->oAnimState++; 46 } 47 48 void bhv_temp_coin_loop(void) { 49 o->oAnimState++; 50 51 if (cur_obj_wait_then_blink(200, 20)) { 52 obj_mark_for_deletion(o); 53 } 54 55 bhv_coin_sparkles_init(); 56 } 57 58 void bhv_spawned_coin_init(void) { 59 o->oVelY = random_float() * 10.0f + 30.0f + o->oCoinBaseVelY; 60 o->oForwardVel = random_float() * 10.0f; 61 o->oMoveAngleYaw = random_u16(); 62 63 cur_obj_set_behavior(bhvYellowCoin); 64 obj_set_hitbox(o, &sYellowCoinHitbox); 65 cur_obj_become_intangible(); 66 } 67 68 void bhv_spawned_coin_loop(void) { 69 struct Surface *floor; 70 71 cur_obj_update_floor_and_walls(); 72 cur_obj_if_hit_wall_bounce_away(); 73 cur_obj_move_standard(-62); 74 75 if ((floor = o->oFloor) != NULL) { 76 if (o->oMoveFlags & OBJ_MOVE_ON_GROUND) { 77 o->oSubAction = 1; 78 } 79 if (o->oSubAction == 1) { 80 o->oBounciness = 0; 81 if (floor->normal.y < 0.9) { 82 s16 sp1A = atan2s(floor->normal.z, floor->normal.x); 83 cur_obj_rotate_yaw_toward(sp1A, 0x400); 84 } 85 } 86 } 87 88 if (o->oTimer == 0) { 89 cur_obj_play_sound_2(SOUND_GENERAL_COIN_SPURT); 90 } 91 92 if (o->oVelY < 0.0f) { 93 cur_obj_become_tangible(); 94 } 95 96 if (o->oMoveFlags & OBJ_MOVE_LANDED) { 97 #ifndef VERSION_JP 98 if (o->oMoveFlags & (OBJ_MOVE_ABOVE_DEATH_BARRIER | OBJ_MOVE_ABOVE_LAVA)) 99 #else 100 if (o->oMoveFlags & OBJ_MOVE_ABOVE_LAVA) 101 #endif 102 { 103 obj_mark_for_deletion(o); 104 } 105 } 106 107 if (o->oMoveFlags & OBJ_MOVE_BOUNCE) { 108 #ifndef VERSION_JP 109 if (o->oCoinNumBounceSoundPlayed < 5) { 110 #endif 111 cur_obj_play_sound_2(SOUND_GENERAL_COIN_DROP); 112 #ifndef VERSION_JP 113 } 114 o->oCoinNumBounceSoundPlayed++; 115 #endif 116 } 117 118 if (cur_obj_wait_then_blink(400, 20)) { 119 obj_mark_for_deletion(o); 120 } 121 122 bhv_coin_sparkles_init(); 123 } 124 125 void bhv_coin_formation_spawn_loop(void) { 126 if (o->oTimer == 0) { 127 cur_obj_set_behavior(bhvYellowCoin); 128 obj_set_hitbox(o, &sYellowCoinHitbox); 129 bhv_init_room(); 130 131 if (o->oCoinOnGround) { 132 o->oPosY += 300.0f; 133 cur_obj_update_floor_height(); 134 135 if (o->oPosY < o->oFloorHeight || o->oFloorHeight < FLOOR_LOWER_LIMIT_MISC) { 136 obj_mark_for_deletion(o); 137 } else { 138 o->oPosY = o->oFloorHeight; 139 } 140 } else { 141 cur_obj_update_floor_height(); 142 143 if (absf(o->oPosY - o->oFloorHeight) > 250.0f) { 144 cur_obj_set_model(MODEL_YELLOW_COIN_NO_SHADOW); 145 } 146 } 147 } else { 148 if (bhv_coin_sparkles_init()) { 149 o->parentObj->oCoinCollectedFlags |= bit_shift_left(o->oBhvParams2ndByte); 150 } 151 o->oAnimState++; 152 } 153 154 if (o->parentObj->oAction == COIN_FORMATION_ACT_RESPAWN_COINS) { 155 obj_mark_for_deletion(o); 156 } 157 } 158 159 s16 sCoinArrowPositions[][2] = { 160 { 0, -150 }, 161 { 0, -50 }, 162 { 0, 50 }, 163 { 0, 150 }, 164 { -50, 100 }, 165 { -100, 50 }, 166 { 50, 100 }, 167 { 100, 50 }, 168 }; 169 170 void spawn_coin_in_formation(s32 coinIndex, s32 coinFormationFlags) { 171 struct Object *coinSpawner; 172 Vec3i pos; 173 s32 setSpawner = TRUE; 174 s32 onGround = TRUE; 175 176 pos[0] = pos[1] = pos[2] = 0; 177 178 switch (coinFormationFlags & COIN_FORMATION_BP_FLAG_MASK) { 179 case COIN_FORMATION_BP_LINE_HORIZONTAL: 180 pos[2] = 160 * (coinIndex - 2); 181 if (coinIndex > 4) { 182 setSpawner = FALSE; 183 } 184 break; 185 186 case COIN_FORMATION_BP_LINE_VERTICAL: 187 onGround = FALSE; 188 pos[1] = 160 * coinIndex * 0.8; // 128 * coinIndex 189 if (coinIndex > 4) { 190 setSpawner = FALSE; 191 } 192 break; 193 194 case COIN_FORMATION_BP_RING_HORIZONTAL: 195 pos[0] = sins(coinIndex << 13) * 300.0f; 196 pos[2] = coss(coinIndex << 13) * 300.0f; 197 break; 198 199 case COIN_FORMATION_BP_RING_VERTICAL: 200 onGround = FALSE; 201 pos[0] = coss(coinIndex << 13) * 200.0f; 202 pos[1] = sins(coinIndex << 13) * 200.0f + 200.0f; 203 break; 204 205 case COIN_FORMATION_BP_ARROW: 206 pos[0] = sCoinArrowPositions[coinIndex][0]; 207 pos[2] = sCoinArrowPositions[coinIndex][1]; 208 break; 209 } 210 211 if (coinFormationFlags & COIN_FORMATION_BP_FLAG_FLYING) { 212 onGround = FALSE; 213 } 214 215 if (setSpawner) { 216 coinSpawner = spawn_object_relative(coinIndex, pos[0], pos[1], pos[2], o, 217 MODEL_YELLOW_COIN, bhvCoinFormationSpawn); 218 coinSpawner->oCoinOnGround = onGround; 219 } 220 } 221 222 void bhv_coin_formation_init(void) { 223 o->oCoinCollectedFlags = (o->oBhvParams >> 8) & 0xFF; 224 } 225 226 void bhv_coin_formation_loop(void) { 227 s32 coinIndex; 228 229 switch (o->oAction) { 230 case COIN_FORMATION_ACT_SPAWN_COINS: 231 if (o->oDistanceToMario < 2000.0f) { 232 for (coinIndex = 0; coinIndex <= 7; coinIndex++) { 233 if (!(o->oCoinCollectedFlags & (1 << coinIndex))) { 234 spawn_coin_in_formation(coinIndex, o->oBhvParams2ndByte); 235 } 236 } 237 o->oAction++; 238 } 239 break; 240 241 case COIN_FORMATION_ACT_IDLE: 242 if (o->oDistanceToMario > 2100.0f) { 243 o->oAction++; 244 } 245 break; 246 247 case COIN_FORMATION_ACT_RESPAWN_COINS: 248 o->oAction = COIN_FORMATION_ACT_SPAWN_COINS; 249 break; 250 } 251 252 set_object_respawn_info_bits(o, o->oCoinCollectedFlags & 0xFF); 253 } 254 255 void coin_inside_boo_act_1(void) { 256 cur_obj_update_floor_and_walls(); 257 cur_obj_if_hit_wall_bounce_away(); 258 259 if (o->oMoveFlags & OBJ_MOVE_BOUNCE) { 260 cur_obj_play_sound_2(SOUND_GENERAL_COIN_DROP); 261 } 262 263 if (o->oTimer > 90 || (o->oMoveFlags & OBJ_MOVE_LANDED)) { 264 obj_set_hitbox(o, &sYellowCoinHitbox); 265 cur_obj_become_tangible(); 266 cur_obj_set_behavior(bhvYellowCoin); 267 } 268 269 cur_obj_move_standard(-30); 270 bhv_coin_sparkles_init(); 271 272 if (cur_obj_has_model(MODEL_BLUE_COIN)) { 273 o->oDamageOrCoinValue = 5; 274 } 275 276 if (cur_obj_wait_then_blink(400, 20)) { 277 obj_mark_for_deletion(o); 278 } 279 } 280 281 void coin_inside_boo_act_0(void) { 282 s16 sp26; 283 f32 sp20; 284 struct Object *parent = o->parentObj; 285 286 cur_obj_become_intangible(); 287 288 if (o->oTimer == 0 && gCurrLevelNum == LEVEL_BBH) { 289 cur_obj_set_model(MODEL_BLUE_COIN); 290 cur_obj_scale(0.7f); 291 } 292 293 obj_copy_pos(o, parent); 294 295 if (parent->oBooDeathStatus == BOO_DEATH_STATUS_DYING) { 296 o->oAction = 1; 297 sp26 = gMarioObject->oMoveAngleYaw; 298 sp20 = 3.0f; 299 o->oVelX = sins(sp26) * sp20; 300 o->oVelZ = coss(sp26) * sp20; 301 o->oVelY = 35.0f; 302 } 303 } 304 305 void (*sCoinInsideBooActions[])(void) = { 306 coin_inside_boo_act_0, 307 coin_inside_boo_act_1, 308 }; 309 310 void bhv_coin_inside_boo_loop(void) { 311 cur_obj_call_action_function(sCoinInsideBooActions); 312 } 313 314 void bhv_coin_sparkles_loop(void) { 315 cur_obj_scale(0.6f); 316 } 317 318 void bhv_golden_coin_sparkles_loop(void) { 319 struct Object *sparkles; 320 UNUSED u8 filler[4]; 321 f32 sp24 = 30.0f; 322 323 sparkles = spawn_object(o, MODEL_SPARKLES, bhvCoinSparkles); 324 sparkles->oPosX += random_float() * sp24 - sp24 / 2; 325 sparkles->oPosZ += random_float() * sp24 - sp24 / 2; 326 }