diff options
Diffstat (limited to 'src/engine/courses/Course.cpp')
| -rw-r--r-- | src/engine/courses/Course.cpp | 178 |
1 files changed, 162 insertions, 16 deletions
diff --git a/src/engine/courses/Course.cpp b/src/engine/courses/Course.cpp index 3e5c0b2ab..bbc9455fe 100644 --- a/src/engine/courses/Course.cpp +++ b/src/engine/courses/Course.cpp @@ -3,6 +3,9 @@ #include "Course.h" #include "MarioRaceway.h" #include "ChocoMountain.h" +#include "port/Game.h" +#include "port/resource/type/TrackWaypoint.h" +#include "port/resource/type/TrackSections.h" extern "C" { #include "main.h" @@ -18,20 +21,36 @@ extern "C" { #include "staff_ghosts.h" #include "code_800029B0.h" #include "render_courses.h" +#include "collision.h" +#include "actors.h" extern StaffGhost* d_mario_raceway_staff_ghost; } Course::Course() { // Props.Name = "Course Name"; // Props.DebugName = "CName"; - // Props.CourseLength = "567m"; + Props.SetText(Props.CourseLength, "100m", sizeof(Props.CourseLength)); // Props.Cup = FLOWER_CUP; // Props.CupIndex = 3; + Id = ""; + Props.Minimap.Texture = gTextureCourseOutlineMarioRaceway; + Props.Minimap.Width = ResourceGetTexWidthByName(Props.Minimap.Texture); + Props.Minimap.Height = ResourceGetTexHeightByName(Props.Minimap.Texture); + Props.Minimap.Pos[0].X = 257; + Props.Minimap.Pos[0].Y = 170; + Props.Minimap.PlayerX = 0; + Props.Minimap.PlayerY = 0; + Props.Minimap.PlayerScaleFactor = 0.22f; + Props.Minimap.FinishlineX = 0; + Props.Minimap.FinishlineY = 0; + Props.Minimap.Colour = {255, 255, 255}; + Props.WaterLevel = -10.0f; + Props.LakituTowType = (s32) OLakitu::LakituTowType::NORMAL; Props.AIBehaviour = D_0D008F28; Props.AIMaximumSeparation = 50.0f; Props.AIMinimumSeparation = 0.3f; - Props.SomePtr = D_800DCB34; + Props.AIDistance = gMarioRacewayAIDistances; Props.AISteeringSensitivity = 48; Props.NearPersp = 3.0f; @@ -71,11 +90,10 @@ Course::Course() { Props.Clouds = NULL; Props.CloudList = NULL; - Props.MinimapFinishlineX = 0; - Props.MinimapFinishlineY = 0; Props.Sequence = MusicSeq::MUSIC_SEQ_UNKNOWN; } +// Load custom track from code void Course::Load(Vtx* vtx, Gfx* gfx) { gSegmentTable[4] = reinterpret_cast<uintptr_t>(&vtx[0]); gSegmentTable[7] = reinterpret_cast<uintptr_t>(&gfx[0]); @@ -83,8 +101,60 @@ void Course::Load(Vtx* vtx, Gfx* gfx) { Course::Init(); } +void Course::LoadO2R(std::string trackPath) { + if (!trackPath.empty()) { + TrackSectionsPtr = (trackPath + "/data_track_sections"); + + std::string path_file = (trackPath + "/data_paths").c_str(); + + auto res = std::dynamic_pointer_cast<MK64::Paths>(ResourceLoad(path_file.c_str())); + + if (res != nullptr) { + auto& paths = res->PathList; + + size_t i = 0; + for (auto& path : paths) { + if (i == 0) { + Props.PathTable[0] = (TrackWaypoint*)path.data(); + Props.PathTable[1] = NULL; + Props.PathTable[2] = NULL; + Props.PathTable[3] = NULL; + Props.PathTable2[0] = (TrackWaypoint*)path.data(); + Props.PathTable2[1] = NULL; + Props.PathTable2[2] = NULL; + Props.PathTable2[3] = NULL; + } + + i += 1; + } + } + + } else { + printf("Course.cpp: LoadO2R: trackPath str is empty\n"); + } +} + +// Load stock track void Course::Load() { + // Load from O2R + if (!TrackSectionsPtr.empty()) { + bIsMod = true; + //auto res = std::dynamic_pointer_cast<MK64::TrackSectionsO2RClass>(ResourceLoad(TrackSectionsPtr.c_str())); + + TrackSectionsO2R* sections = (TrackSectionsO2R*) LOAD_ASSET_RAW(TrackSectionsPtr.c_str()); + size_t size = ResourceGetSizeByName(TrackSectionsPtr.c_str()); + + if (sections != nullptr) { + Course::Init(); + ParseCourseSections(sections, size); + func_80295C6C(); + Props.WaterLevel = gCourseMinY - 10.0f; + } + return; + } + + // Stock size_t vtxSize = (ResourceGetSizeByName(this->vtx) / sizeof(CourseVtx)) * sizeof(Vtx); size_t texSegSize; @@ -129,6 +199,53 @@ void Course::Load() { Course::Init(); } +// C++ version of parse_course_displaylists() +void Course::ParseCourseSections(TrackSectionsO2R* sections, size_t size) { + for (size_t i = 0; i < (size / sizeof(TrackSectionsO2R)); i++) { + if (sections[i].flags & 0x8000) { + D_8015F59C = 1; + } else { + D_8015F59C = 0; + } + if (sections[i].flags & 0x2000) { + D_8015F5A0 = 1; + } else { + D_8015F5A0 = 0; + } + if (sections[i].flags & 0x4000) { + D_8015F5A4 = 1; + } else { + D_8015F5A4 = 0; + } + printf("LOADING DL %s\n", sections[i].addr.c_str()); + generate_collision_mesh((Gfx*)LOAD_ASSET_RAW(sections[i].addr.c_str()), sections[i].surfaceType, sections[i].sectionId); + } +} + +void Course::TestPath() { + // DEBUG ONLY TO VISUALIZE PATH + return; + s16 x; + s16 y; + s16 z; + Vec3s rot = {0, 0, 0}; + Vec3f vel = {0, 0, 0}; + + for (size_t i = 0; i < gWaypointCountByPathIndex[0]; i++) { + x = D_80164550[0][i].posX; + y = D_80164550[0][i].posY; + z = D_80164550[0][i].posZ; + + if (((x & 0xFFFF) == 0x8000) && ((y & 0xFFFF) == 0x8000) && ((z & 0xFFFF) == 0x8000)) { + break; + } + + f32 height = spawn_actor_on_surface(x, 2000.0f, z); + Vec3f itemPos = {x, height, z}; + add_actor_to_empty_slot(itemPos, rot, vel, ACTOR_ITEM_BOX); + } +} + void Course::Init() { gNumActors = 0; gCourseMinX = 0; @@ -153,6 +270,7 @@ void Course::LoadTextures() { } void Course::BeginPlay() { + TestPath(); } void Course::InitClouds() { @@ -181,9 +299,6 @@ void Course::SomeCollisionThing(Player* player, Vec3f arg1, Vec3f arg2, Vec3f ar func_8003E048(player, arg1, arg2, arg3, arg4, arg5, arg6, arg7); } -void Course::MinimapSettings() { -} - void Course::InitCourseObjects() { } @@ -206,13 +321,6 @@ void Course::WhatDoesThisDo(Player* player, int8_t playerId) { void Course::WhatDoesThisDoAI(Player* player, int8_t playerId) { } -// Positions the finishline on the minimap -void Course::MinimapFinishlinePosition() { - //! todo: Place hard-coded values here. - draw_hud_2d_texture_8x8(this->Props.MinimapFinishlineX, this->Props.MinimapFinishlineY, - (u8*) common_texture_minimap_finish_line); -} - void Course::SetStaffGhost() { D_80162DD6 = 1; D_80162DF4 = 1; @@ -226,11 +334,49 @@ void Course::Waypoints(Player* player, int8_t playerId) { } void Course::Render(struct UnkStruct_800DC5EC* arg0) { + if (!TrackSectionsPtr.empty()) { + gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH); + gSPClearGeometryMode(gDisplayListHead++, G_LIGHTING); + // set_track_light_direction(D_800DC610, D_802B87D4, 0, 1); + gSPTexture(gDisplayListHead++, 0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON); + gSPSetGeometryMode(gDisplayListHead++, G_SHADING_SMOOTH); + + if (func_80290C20(arg0->camera) == 1) { + gDPSetCombineMode(gDisplayListHead++, G_CC_SHADE, G_CC_SHADE); + gDPSetRenderMode(gDisplayListHead++, G_RM_AA_ZB_OPA_SURF, G_RM_AA_ZB_OPA_SURF2); + // d_course_big_donut_packed_dl_DE8 + } + + TrackSectionsO2R* sections = (TrackSectionsO2R*)LOAD_ASSET_RAW(TrackSectionsPtr.c_str()); + size_t size = ResourceGetSizeByName(TrackSectionsPtr.c_str()); + for (size_t i = 0; i < (size / sizeof(TrackSectionsO2R)); i++) { + gSPDisplayList(gDisplayListHead++, (Gfx*)LOAD_ASSET_RAW(sections[i].addr.c_str())); + } + } } + void Course::RenderCredits() { } -void Course::Collision() { + +f32 Course::GetWaterLevel(FVector pos, Collision* collision) { + float highestWater = -FLT_MAX; + bool found = false; + + for (const auto& volume : gWorldInstance.CurrentCourse->WaterVolumes) { + if (pos.x >= volume.MinX && pos.x <= volume.MaxX && + pos.z >= volume.MinZ && pos.z <= volume.MaxZ) { + // Choose the highest water volume the player is over + if (!found || volume.Height > highestWater) { + highestWater = volume.Height; + found = true; + } + } + } + + // If player is not over-top of a water volume then return the courses default water level + return found ? highestWater : gWorldInstance.CurrentCourse->Props.WaterLevel; } + void Course::ScrollingTextures() { } void Course::DrawWater(struct UnkStruct_800DC5EC* screen, uint16_t pathCounter, uint16_t cameraRot, @@ -241,7 +387,7 @@ void Course::Destroy() { } bool Course::IsMod() { - return false; + return bIsMod; } Course* currentCourse = nullptr; |
