#include #include #include #include #include "racing/collision.h" #include "port/Game.h" /** * @brief Updates the green shell actor. * * @param shell */ void update_actor_green_shell(struct ShellActor* shell) { Player* player; UNUSED f32 pad9; UNUSED f32 padA; Vec3f somePos2; Vec3f somePosVel; f32 var_f2; struct Controller* controller; TripleShellParent* parent; f32 height; f32 z; UNUSED f32 pad2; UNUSED f32 pad3; UNUSED f32 pad4; UNUSED f32 pad5; f32 y; UNUSED f32 pad7; UNUSED f32 pad8; height = shell->pos[0]; y = shell->pos[1]; z = shell->pos[2]; if ((z < gTrackMinZ) || (gTrackMaxZ < z) || (height < gTrackMinX) || (gTrackMaxX < height) || (y < gTrackMinY)) { destroy_destructable_actor((struct Actor*) shell); } shell->rotVelocity += 0x71C; switch (shell->state) { case HELD_SHELL: player = &gPlayers[shell->playerId]; copy_collision(&player->collision, &shell->unk30); somePosVel[0] = 0.0f; somePosVel[1] = player->boundingBoxSize; somePosVel[2] = -(player->boundingBoxSize + shell->boundingBoxSize + 2.0f); mtxf_translate_vec3f_mat3(somePosVel, player->orientationMatrix); shell->pos[0] = player->pos[0] + somePosVel[0]; pad2 = player->pos[1] - somePosVel[1]; shell->pos[2] = player->pos[2] + somePosVel[2]; height = calculate_surface_height(shell->pos[0], pad2, shell->pos[2], player->collision.meshIndexZX); z = pad2 - height; if ((z < 5.0f) && (z > -5.0f)) { shell->pos[1] = shell->boundingBoxSize + height; } else { shell->pos[1] = pad2; } if ((player->type & PLAYER_HUMAN) != 0) { controller = &gControllers[shell->playerId]; if ((controller->buttonDepressed & Z_TRIG) != 0) { controller->buttonDepressed &= ~Z_TRIG; if (controller->rawStickY < THROW_SHELL_BACKWARDS) { var_f2 = 8.0f; if (player->speed > 8.0f) { var_f2 = player->speed * 1.2f; } somePosVel[0] = 0.0f; somePosVel[1] = 0.0f; somePosVel[2] = -var_f2; func_802B64C4(somePosVel, player->rotation[1] + player->unk_0C0); shell->velocity[0] = somePosVel[0]; shell->velocity[1] = somePosVel[1]; shell->velocity[2] = somePosVel[2]; shell->state = MOVING_SHELL; func_800C9060(shell->playerId, SOUND_ARG_LOAD(0x19, 0x00, 0x80, 0x04)); func_800C90F4(shell->playerId, (player->characterId * 0x10) + SOUND_ARG_LOAD(0x29, 0x00, 0x80, 0x00)); add_green_shell_in_unexpired_actor_list(CM_FindActorIndex(shell)); return; } else { shell->state = RELEASED_SHELL; if (player->unk_0C0 > 0) { shell->rotAngle = 0x78E3; } else { shell->rotAngle = -0x78E4; } } } } break; case RELEASED_SHELL: player = &gPlayers[shell->playerId]; if (shell->rotAngle > 0) { shell->rotAngle -= 0xE38; if (shell->rotAngle < 0) { shell->state = 2; shell->someTimer = 0x001E; func_800C9060(shell->playerId, SOUND_ARG_LOAD(0x19, 0x00, 0x80, 0x04)); func_800C90F4(shell->playerId, (player->characterId * 0x10) + SOUND_ARG_LOAD(0x29, 0x00, 0x80, 0x00)); add_green_shell_in_unexpired_actor_list(CM_FindActorIndex(shell)); } } else { shell->rotAngle += 0xE38; if (shell->rotAngle > 0) { shell->state = 2; shell->someTimer = 0x001E; func_800C9060(shell->playerId, SOUND_ARG_LOAD(0x19, 0x00, 0x80, 0x04)); func_800C90F4(shell->playerId, (player->characterId * 0x10) + SOUND_ARG_LOAD(0x29, 0x00, 0x80, 0x00)); add_green_shell_in_unexpired_actor_list(CM_FindActorIndex(shell)); } } if (shell->state == 2) { var_f2 = 8.0f; if (player->speed > 8.0f) { var_f2 = player->speed * 1.2f; } somePosVel[0] = 0.0f; somePosVel[1] = 0.0f; somePosVel[2] = var_f2; func_802B64C4(somePosVel, player->rotation[1] + player->unk_0C0); shell->velocity[0] = somePosVel[0]; shell->velocity[1] = somePosVel[1]; shell->velocity[2] = somePosVel[2]; } else { somePosVel[0] = sins(shell->rotAngle) * 6.0f; somePosVel[1] = shell->boundingBoxSize - player->boundingBoxSize; somePosVel[2] = coss(shell->rotAngle) * 6.0f; mtxf_translate_vec3f_mat3(somePosVel, player->orientationMatrix); shell->pos[0] = player->pos[0] + somePosVel[0]; shell->pos[1] = player->pos[1] + somePosVel[1]; shell->pos[2] = player->pos[2] + somePosVel[2]; } break; case MOVING_SHELL: if (shell->parentIndex > 0) { shell->parentIndex -= 1; if (shell->parentIndex == 0) { shell->flags &= ~0x1000; } } shell->velocity[1] -= 0.5f; if (shell->velocity[1] < -2.0f) { shell->velocity[1] = -2.0f; } somePos2[0] = shell->pos[0]; somePos2[1] = shell->pos[1]; somePos2[2] = shell->pos[2]; shell->pos[0] += shell->velocity[0]; shell->pos[1] += shell->velocity[1]; shell->pos[2] += shell->velocity[2]; actor_terrain_collision(&shell->unk30, 4.0f, shell->pos[0], shell->pos[1], shell->pos[2], somePos2[0], somePos2[1], somePos2[2]); func_802B4E30((struct Actor*) shell); if ((shell->unk30.surfaceDistance[0] < 0.0f) || (shell->unk30.surfaceDistance[1] < 0.0f)) { shell_collision(&shell->unk30, shell->velocity); func_800C98B8(shell->pos, shell->velocity, SOUND_ARG_LOAD(0x19, 0x00, 0x80, 0x54)); shell->flags |= 0x80; } break; case TRIPLE_GREEN_SHELL: player = &gPlayers[shell->playerId]; parent = (TripleShellParent*) GET_ACTOR(shell->parentIndex); if (parent->type != ACTOR_TRIPLE_GREEN_SHELL) { destroy_destructable_actor((struct Actor*) shell); } else { shell->rotAngle += parent->rotVelocity; somePosVel[0] = sins(shell->rotAngle) * 8.0f; somePosVel[1] = shell->boundingBoxSize - player->boundingBoxSize; somePosVel[2] = coss(shell->rotAngle) * 8.0f; mtxf_translate_vec3f_mat3(somePosVel, player->orientationMatrix); somePos2[0] = shell->pos[0]; somePos2[1] = shell->pos[1]; somePos2[2] = shell->pos[2]; shell->pos[0] = player->pos[0] + somePosVel[0]; shell->pos[1] = player->pos[1] + somePosVel[1]; shell->pos[2] = player->pos[2] + somePosVel[2]; actor_terrain_collision(&shell->unk30, 4.0f, shell->pos[0], shell->pos[1], shell->pos[2], somePos2[0], somePos2[1], somePos2[2]); func_802B4E30((struct Actor*) shell); } break; case GREEN_SHELL_HIT_A_RACER: // Somehow, this fake match affects stack management up in case 2 shell->velocity[1] -= (0, 0.3f); if (shell->velocity[1] < -5.0f) { shell->velocity[1] = -5.0f; } shell->rotAngle += 0x5B0; shell->someTimer -= 1; shell->pos[1] += shell->velocity[1]; if (shell->someTimer == 0) { destroy_actor((struct Actor*) shell); } break; default: break; } }