#include #include "Truck.h" #include #include "engine/vehicles/Utils.h" #include "port/Game.h" extern "C" { #include "macros.h" #include "main.h" #include "defines.h" #include "code_80005FD0.h" #include "racing/actors.h" #include "racing/math_util.h" #include "sounds.h" #include "update_objects.h" #include "render_player.h" #include "audio/external.h" extern s8 gPlayerCount; } size_t ATruck::_count = 0; std::map> ATruck::TruckCounts; ATruck::ATruck(const SpawnParams& params) : AActor(params) { Name = "Truck"; ResourceName = "mk:truck"; BoundingBoxSize = 2.0f; TrackPathPoint* temp_v0; u16 waypointOffset; s32 numWaypoints = gPathCountByPathIndex[0]; Index = _count; PathIndex = params.PathIndex.value_or(0); PathPoint = 0; SpawnType = static_cast(params.Type.value_or(0)); switch(SpawnType) { case SpawnMode::POINT: // Spawn truck at a specific path point PathPoint = params.PathPoint.value_or(0); TruckCounts[PathIndex].push_back(PathPoint); break; case SpawnMode::AUTO: // Automatically distribute trucks based on a specific path point printf("vehicle path size %zu\n", gVehiclePathSize); PathPoint = GetVehiclePathPointDistributed(TruckCounts[PathIndex], gVehiclePathSize); TruckCounts[PathIndex].push_back(PathPoint); printf("train spawn path point: %d\n", PathPoint); break; } waypointOffset = PathPoint; temp_v0 = &gTrackPaths[PathIndex][PathPoint]; Position[0] = (f32) temp_v0->x; Position[1] = (f32) temp_v0->y; Position[2] = (f32) temp_v0->z; ActorIndex = -1; WaypointIndex = waypointOffset; Velocity[0] = 0.0f; Velocity[1] = 0.0f; Velocity[2] = 0.0f; if (gModeSelection == TIME_TRIALS) { SomeType = ((Index - 1) % 3); } else { SomeType = random_int(3); } SomeMultiplierTheSequel = (f32) ((f64) (f32) (SomeType - 1) * 0.6); if (((gCCSelection > CC_50) || (gModeSelection == TIME_TRIALS)) && (SomeType == 2)) { Speed = params.Speed.value_or(0); } else { Speed = params.SpeedB.value_or(0); } Rotation[0] = 0; Rotation[2] = 0; if (gIsInExtra == 0) { Rotation[1] = func_8000D6D0(Position, (s16*) &WaypointIndex, Speed, SomeMultiplierTheSequel, 0, 3); } else { Rotation[1] = func_8000D940(Position, (s16*) &WaypointIndex, Speed, SomeMultiplierTheSequel, 0); } sVehicleSoundRenderCounter = 10; spawn_vehicle_on_road(Position, Rotation, Velocity, WaypointIndex, SomeMultiplierTheSequel, Speed); ActorIndex = add_actor_to_empty_slot(Position, Rotation, Velocity, ACTOR_BOX_TRUCK); _count++; } void ATruck::SetSpawnParams(SpawnParams& params) { params.Name = "mk:truck"; params.Type = static_cast(SpawnType); params.PathIndex = PathIndex; params.PathPoint = PathPoint; params.Speed = Speed; params.SpeedB = SpeedB; } bool ATruck::IsMod() { return true; } void ATruck::Draw(Camera* camera) { s32 var_v0; s32 var_s2; s32 waypointCount; u16 temp_a1; waypointCount = gPathCountByPathIndex[0]; if (!(gPlayers[camera->playerId].speed < 1.6666666666666667)) { temp_a1 = WaypointIndex; for (var_v0 = 0; var_v0 < 0x18; var_v0 += 3) { if (((sSomeNearestPathPoint + var_v0) % waypointCount) == temp_a1) { gPlayerTrackPositionFactorInstruction[camera->playerId].target = player_track_position_factor_vehicle(SomeType, gTrackPositionFactor[camera->playerId], temp_a1); return; } } } } void ATruck::Tick() { f32 temp_f0_2; f32 temp_f0_3; f32 sp5C; f32 sp58; f32 sp54; f32 temp_f2_2; s16 var_a1; s16 thing; Vec3f sp40; Vec3f sp34; sp5C = Position[0]; sp58 = Position[1]; sp54 = Position[2]; sp40[0] = sp58; sp40[1] = 0.0f; sp40[2] = 0.0f; temp_f0_2 = func_80013C74(SomeType, WaypointIndex); if (SomeMultiplierTheSequel < temp_f0_2) { SomeMultiplierTheSequel = SomeMultiplierTheSequel + 0.06; if (temp_f0_2 < SomeMultiplierTheSequel) { SomeMultiplierTheSequel = temp_f0_2; } } if (temp_f0_2 < SomeMultiplierTheSequel) { SomeMultiplierTheSequel = SomeMultiplierTheSequel - 0.06; if (SomeMultiplierTheSequel < temp_f0_2) { SomeMultiplierTheSequel = temp_f0_2; } } if (gIsInExtra == 0) { var_a1 = func_8000D6D0(Position, (s16*) &WaypointIndex, Speed, SomeMultiplierTheSequel, 0, 3); } else { var_a1 = func_8000D940(Position, (s16*) &WaypointIndex, Speed, SomeMultiplierTheSequel, 0); } adjust_angle(&Rotation[1], var_a1, 100); temp_f0_3 = Position[0] - sp5C; temp_f2_2 = Position[2] - sp54; sp34[0] = Position[1]; sp34[1] = 0.0f; sp34[2] = sqrtf((temp_f0_3 * temp_f0_3) + (temp_f2_2 * temp_f2_2)); thing = get_angle_between_two_vectors(sp40, sp34); adjust_angle(&Rotation[0], -thing, 100); Velocity[0] = Position[0] - sp5C; Velocity[1] = Position[1] - sp58; Velocity[2] = Position[2] - sp54; struct Actor* vehicleActor = GET_ACTOR(ActorIndex); vehicleActor->pos[0] = Position[0]; vehicleActor->pos[1] = Position[1]; vehicleActor->pos[2] = Position[2]; vehicleActor->rot[0] = Rotation[0]; if (gIsMirrorMode != 0) { vehicleActor->rot[1] = -Rotation[1]; } else { vehicleActor->rot[1] = Rotation[1]; } vehicleActor->rot[2] = Rotation[2]; vehicleActor->velocity[0] = Velocity[0]; vehicleActor->velocity[1] = Velocity[1]; vehicleActor->velocity[2] = Velocity[2]; } void ATruck::VehicleCollision(s32 playerId, Player* player) { f32 temp_f12; f32 temp_f14; f32 temp_f22; f32 spC4; f32 spC0; f32 spBC; if (((D_801631E0[playerId] != 1) || ((((player->type & PLAYER_HUMAN) != 0)) && !(player->type & PLAYER_CPU))) && !(player->effects & 0x01000000)) { spC4 = player->pos[0]; spC0 = player->pos[1]; spBC = player->pos[2]; temp_f12 = spC4 - Position[0]; temp_f22 = spC0 - Position[1]; temp_f14 = spBC - Position[2]; if (((temp_f12) > -100.0) && ((temp_f12) < 100.0)) { if ((temp_f22 > -20.0) && (temp_f22 < 20.0)) { if (((temp_f14) > -100.0) && ((temp_f14) < 100.0)) { if (is_collide_with_vehicle(Position[0], Position[2], Velocity[0], Velocity[2], SomeArg3, SomeArg4, spC4, spBC) == (s32) 1) { player->triggers |= VERTICAL_TUMBLE_TRIGGER; } } } } if ((player->type & PLAYER_HUMAN) && !(player->type & PLAYER_CPU)) { if (((temp_f12) > -300.0) && ((temp_f12) < 300.0) && ((temp_f22 > -20.0)) && (temp_f22 < 20.0) && (((temp_f14) > -300.0)) && ((temp_f14) < 300.0)) { if ((sVehicleSoundRenderCounter > 0) && (SomeFlags == 0)) { sVehicleSoundRenderCounter -= 1; SomeFlags |= (RENDER_VEHICLE << playerId); func_800C9D80(Position, Velocity, SoundBits); } } else { if (SomeFlags != 0) { SomeFlags &= ~(RENDER_VEHICLE << playerId); if (SomeFlags == 0) { sVehicleSoundRenderCounter += 1; func_800C9EF4(Position, SoundBits); } } } if (((temp_f12) > -200.0) && ((temp_f12) < 200.0) && ((temp_f22 > -20.0)) && (temp_f22 < 20.0) && (((temp_f14) > -200.0)) && ((temp_f14) < 200.0)) { if (!(SomeFlagsTheSequel & ((1 << playerId)))) { s32 var_s1 = 0; u16 path = gPathCountByPathIndex[0]; s32 t1; s32 t2; switch (gIsInExtra) { case 0: t1 = is_path_point_in_range(WaypointIndex, gNearestPathPointByPlayerId[playerId], 10, 0, path); if ((gIsPlayerWrongDirection[playerId] == 0) && (t1 > 0) && (player->speed < Speed)) { var_s1 = 1; } if ((gIsPlayerWrongDirection[playerId] == 1) && (t1 > 0)) { var_s1 = 1; } break; case 1: t2 = is_path_point_in_range(WaypointIndex, gNearestPathPointByPlayerId[playerId], 0, 10, path); if (t2 > 0) { if (random_int(2) == 0) { // temp_v1_2 = gIsPlayerWrongDirection[playerId]; if (gIsPlayerWrongDirection[playerId] == 0) { var_s1 = 1; } if ((gIsPlayerWrongDirection[playerId] == 1) && (player->speed < Speed)) { var_s1 = 1; } } else { SomeFlagsTheSequel |= ((1 << playerId)); } } break; } if (var_s1 == 1) { u32 soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x3B); switch (SoundBits) { case SOUND_ARG_LOAD(0x51, 0x01, 0x80, 0x05): soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x3B); if (random_int(4) == 0) { soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x3C); } break; case SOUND_ARG_LOAD(0x51, 0x01, 0x80, 0x02): if (random_int(2) != 0) { soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x3D); } else { soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x3E); } break; case SOUND_ARG_LOAD(0x51, 0x01, 0x80, 0x03): if (random_int(2) != 0) { soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x3F); } else { soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x40); } break; case SOUND_ARG_LOAD(0x51, 0x01, 0x80, 0x04): if (random_int(2) != 0) { soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x41); } else { soundBits2 = SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x42); } break; } SomeFlagsTheSequel |= ((1 << playerId)); func_800C98B8(Position, Velocity, soundBits2); } } } else { if (SomeFlagsTheSequel & ((1 << playerId))) { SomeFlagsTheSequel &= ~((1 << playerId)); } } } } } void ATruck::DrawEditorProperties() { ImGui::Text("Spawn Mode"); ImGui::SameLine(); int32_t type = static_cast(SpawnType); const char* items[] = { "POINT", "AUTO" }; if (ImGui::Combo("##Type", &type, items, IM_ARRAYSIZE(items))) { SpawnType = static_cast(type); } if (SpawnType == ATruck::SpawnMode::POINT) { ImGui::Text("Path Index"); ImGui::SameLine(); int pathIndex = static_cast(PathIndex); if (ImGui::InputInt("##PathIndex", &pathIndex)) { if (pathIndex < 0) pathIndex = 0; PathIndex = static_cast(pathIndex); } ImGui::SameLine(); if (ImGui::Button(ICON_FA_UNDO "##ResetPathIndex")) { PathIndex = 0; } ImGui::Text("Path Point"); ImGui::SameLine(); int pathPoint = static_cast(PathPoint); if (ImGui::InputInt("##PathPoint", &pathPoint)) { if (pathPoint < 0) pathPoint = 0; PathPoint = static_cast(pathPoint); } ImGui::SameLine(); if (ImGui::Button(ICON_FA_UNDO "##ResetPathPoint")) { PathPoint = 0; } } ImGui::Text("Speed"); ImGui::SameLine(); float speed = Speed; if (ImGui::DragFloat("##Speed", &speed, 0.1f)) { Speed = speed; } ImGui::SameLine(); if (ImGui::Button(ICON_FA_UNDO "##ResetSpeed")) { Speed = 0.0f; } ImGui::Text("SpeedB"); ImGui::SameLine(); float speed2 = SpeedB; if (ImGui::DragFloat("##SpeedB", &speed2, 0.1f)) { SpeedB = speed2; } ImGui::SameLine(); if (ImGui::Button(ICON_FA_UNDO "##ResetSpeedB")) { SpeedB = 0.0f; } }