diff --git a/src/code_80057C60.c b/src/code_80057C60.c index c16c72aa9..9c46e792b 100644 --- a/src/code_80057C60.c +++ b/src/code_80057C60.c @@ -1644,7 +1644,7 @@ void update_object(void) { // func_80074EE8(); // Grand prix balloons //} func_80076F2C(); - if ((s16) GetCourse() != GetFrappeSnowland()) { + if (!IsFrappeSnowland()) { update_leaf(); } } @@ -3638,7 +3638,7 @@ void func_800608E0(Player* player, s16 arg1, UNUSED s32 arg2, s8 arg3, UNUSED s8 var_f0 = 0.0f; } sp4C = (D_801652A0[arg3] - player->pos[1]) - 3.0f; - if ((player->unk_0DE & 1) && (IsKoopaTroopaBeach())) { + if ((player->unk_0DE & 1) && (!IsKoopaTroopaBeach())) { var_f0 = 2.5f; sp4C = (f32) ((f64) (D_801652A0[arg3] - player->pos[1]) + 0.1); } @@ -3658,7 +3658,7 @@ void func_800608E0(Player* player, s16 arg1, UNUSED s32 arg2, s8 arg3, UNUSED s8 } void func_80060B14(Player* player, s16 arg1, s32 arg2, s8 arg3, s8 arg4) { - if ((GetCourse() != GetSkyscraper()) && (!IsRainbowRoad())) { + if ((!IsSkyscraper()) && (!IsRainbowRoad())) { if ((arg1 == 0) && ((player->unk_258[arg2].unk_01E > 0) || (player->unk_258[arg2].unk_01C == 0))) { func_800608E0(player, arg1, arg2, arg3, arg4); } else if (player->unk_258[arg2].unk_01E > 0) { @@ -4628,7 +4628,7 @@ void func_80064184(Player* player, s16 arg1, s8 arg2, UNUSED s8 arg3) { f32 sp3C; sp40 = D_801652A0[arg2] - player->pos[1] - 3.0f; - if (((player->unk_0DE & 1) != 0) && (IsKoopaTroopaBeach())) { + if (((player->unk_0DE & 1) != 0) && (!IsKoopaTroopaBeach())) { sp40 = D_801652A0[arg2] - player->pos[1] + 0.1; } diff --git a/src/engine/World.cpp b/src/engine/World.cpp index 998e3ba71..39c3802c2 100644 --- a/src/engine/World.cpp +++ b/src/engine/World.cpp @@ -26,8 +26,10 @@ World::World() {} Course* CurrentCourse; Cup* CurrentCup; -void World::AddCourse(std::unique_ptr course) { - gWorldInstance.Courses.push_back(course); +Course* World::AddCourse(std::unique_ptr course) { + Course* ptr = course.get(); + gWorldInstance.Courses.push_back(std::move(course)); + return ptr; } void World::AddCup(Cup* cup) { @@ -97,17 +99,6 @@ void World::SetCourse(const char* name) { std::runtime_error("SetCourse() Course name not found in Courses list"); } -template -void World::SetCourseByType() { - for (const auto& course : Courses) { - if (dynamic_cast(course.get())) { - CurrentCourse = course.get(); - return; - } - } - printf("World::SetCourseByType() No course by the type found"); -} - void World::NextCourse() { if (CourseIndex < Courses.size() - 1) { CourseIndex++; diff --git a/src/engine/World.h b/src/engine/World.h index 440b14fb2..2255a3e6a 100644 --- a/src/engine/World.h +++ b/src/engine/World.h @@ -53,7 +53,7 @@ class World { public: explicit World(); - void AddCourse(std::unique_ptr course); + Course* AddCourse(std::unique_ptr course); AActor* AddActor(AActor* actor); struct Actor* AddBaseActor(); @@ -95,7 +95,15 @@ public: // These are only for browsing through the course list void SetCourse(const char*); template - void SetCourseByType(); + void SetCourseByType() { + for (const auto& course : Courses) { + if (dynamic_cast(course.get())) { + CurrentCourse = course.get(); + return; + } + } + printf("World::SetCourseByType() No course by the type found"); + } void NextCourse(void); void PreviousCourse(void); diff --git a/src/player_controller.c b/src/player_controller.c index 4f1a93441..46038dbda 100644 --- a/src/player_controller.c +++ b/src/player_controller.c @@ -1778,7 +1778,7 @@ void func_8002C4F8(Player* player, s8 arg1) { if ((player->unk_0DE & 4) != 4) { player->unk_0DE |= 8; player->unk_0DE |= 4; - if ((IsKoopaTroopaBeach()) && (GetCourse() != GetSkyscraper()) && + if ((!IsKoopaTroopaBeach()) && (!IsSkyscraper()) && (!IsRainbowRoad()) && ((player->type & PLAYER_HUMAN) == PLAYER_HUMAN)) { if ((IsBowsersCastle()) || (IsBigDonut())) { func_800C9060((u8) arg1, 0x1900801CU); diff --git a/src/port/Game.cpp b/src/port/Game.cpp index d4b2dae92..d72c5f120 100644 --- a/src/port/Game.cpp +++ b/src/port/Game.cpp @@ -69,29 +69,7 @@ extern "C" void Timer_Update(); // Create the world instance World gWorldInstance; -// auto gMarioRaceway; -// ChocoMountain* gChocoMountain; -// BowsersCastle* gBowsersCastle; -// BansheeBoardwalk* gBansheeBoardwalk; -// YoshiValley* gYoshiValley; -// FrappeSnowland* gFrappeSnowland; -// KoopaTroopaBeach* gKoopaTroopaBeach; -// RoyalRaceway* gRoyalRaceway; -// LuigiRaceway* gLuigiRaceway; -// MooMooFarm* gMooMooFarm; -// ToadsTurnpike* gToadsTurnpike; -// KalimariDesert* gKalimariDesert; -// SherbetLand* gSherbetLand; -// RainbowRoad* gRainbowRoad; -// WarioStadium* gWarioStadium; -// BlockFort* gBlockFort; -// Skyscraper* gSkyscraper; -// DoubleDeck* gDoubleDeck; -// DKJungle* gDkJungle; -// BigDonut* gBigDonut; -// PodiumCeremony* gPodiumCeremony; -// Harbour* gHarbour; -// TestCourse* gTestCourse; +std::unique_ptr gPodiumCeremony; Cup* gMushroomCup; Cup* gFlowerCup; @@ -134,47 +112,58 @@ void CustomEngineInit() { // gTestCourse = new TestCourse(); /* Add all courses to the global course list */ - gWorldInstance.AddCourse(std::make_unique()); - gWorldInstance.AddCourse(std::make_unique()); - gWorldInstance.AddCourse(std::make_unique()); - gWorldInstance.AddCourse(std::make_unique()); - gWorldInstance.AddCourse(std::make_unique()); - gWorldInstance.AddCourse(std::make_unique()); - gWorldInstance.AddCourse(std::make_unique()); - gWorldInstance.AddCourse(std::make_unique()); - gWorldInstance.AddCourse(std::make_unique()); - gWorldInstance.AddCourse(std::make_unique()); - gWorldInstance.AddCourse(std::make_unique()); - gWorldInstance.AddCourse(std::make_unique()); - gWorldInstance.AddCourse(std::make_unique()); - gWorldInstance.AddCourse(std::make_unique()); - gWorldInstance.AddCourse(std::make_unique()); - gWorldInstance.AddCourse(std::make_unique()); - gWorldInstance.AddCourse(std::make_unique()); - gWorldInstance.AddCourse(std::make_unique()); - gWorldInstance.AddCourse(std::make_unique()); - gWorldInstance.AddCourse(std::make_unique()); - gWorldInstance.AddCourse(std::make_unique()); - gWorldInstance.AddCourse(std::make_unique()); - gWorldInstance.AddCourse(std::make_unique()); + Course* mario = gWorldInstance.AddCourse(std::make_unique()); + Course* choco = gWorldInstance.AddCourse(std::make_unique()); + Course* bowser = gWorldInstance.AddCourse(std::make_unique()); + Course* banshee = gWorldInstance.AddCourse(std::make_unique()); + Course* yoshi = gWorldInstance.AddCourse(std::make_unique()); + Course* frappe = gWorldInstance.AddCourse(std::make_unique()); + Course* koopa = gWorldInstance.AddCourse(std::make_unique()); + Course* royal = gWorldInstance.AddCourse(std::make_unique()); + Course* luigi = gWorldInstance.AddCourse(std::make_unique()); + Course* mooMoo = gWorldInstance.AddCourse(std::make_unique()); + Course* toads = gWorldInstance.AddCourse(std::make_unique()); + Course* kalimari = gWorldInstance.AddCourse(std::make_unique()); + Course* sherbet = gWorldInstance.AddCourse(std::make_unique()); + Course* rainbow = gWorldInstance.AddCourse(std::make_unique()); + Course* wario = gWorldInstance.AddCourse(std::make_unique()); + Course* block = gWorldInstance.AddCourse(std::make_unique()); + Course* skyscraper = gWorldInstance.AddCourse(std::make_unique()); + Course* doubleDeck = gWorldInstance.AddCourse(std::make_unique()); + Course* dkJungle = gWorldInstance.AddCourse(std::make_unique()); + Course* bigDonut = gWorldInstance.AddCourse(std::make_unique()); + Course* harbour = gWorldInstance.AddCourse(std::make_unique()); + Course* testCourse = gWorldInstance.AddCourse(std::make_unique()); - // gMushroomCup = new Cup("mk:mushroom_cup", "mushroom cup", - // std::vector{ gLuigiRaceway, gMooMooFarm, gKoopaTroopaBeach, gKalimariDesert }); - // gFlowerCup = new Cup("mk:flower_cup", "flower cup", - // std::vector{ gToadsTurnpike, gFrappeSnowland, gChocoMountain, gMarioRaceway }); - // gStarCup = new Cup("mk:star_cup", "star cup", - // std::vector{ gWarioStadium, gSherbetLand, gRoyalRaceway, gBowsersCastle }); - // gSpecialCup = new Cup("mk:special_cup", "special cup", - // std::vector{ gDkJungle, gYoshiValley, gBansheeBoardwalk, gRainbowRoad }); - // gBattleCup = - // new Cup("mk:battle_cup", "battle", std::vector{ gBigDonut, gBlockFort, gDoubleDeck, gSkyscraper }); + gPodiumCeremony = std::make_unique(); + + // Construct cups with vectors of Course* (non-owning references) + gMushroomCup = new Cup("mk:mushroom_cup", "Mushroom Cup", { + luigi, mooMoo, koopa, kalimari + }); + + gFlowerCup = new Cup("mk:flower_cup", "Flower Cup", { + toads, frappe, choco, mario + }); + + gStarCup = new Cup("mk:star_cup", "Star Cup", { + wario, sherbet, royal, bowser + }); + + gSpecialCup = new Cup("mk:special_cup", "Special Cup", { + dkJungle, yoshi, banshee, rainbow + }); + + gBattleCup = new Cup("mk:battle_cup", "Battle Cup", { + bigDonut, block, doubleDeck, skyscraper + }); /* Instantiate Cups */ - // gWorldInstance.AddCup(gMushroomCup); - // gWorldInstance.AddCup(gFlowerCup); - // gWorldInstance.AddCup(gStarCup); - // gWorldInstance.AddCup(gSpecialCup); - // gWorldInstance.AddCup(gBattleCup); + gWorldInstance.AddCup(gMushroomCup); + gWorldInstance.AddCup(gFlowerCup); + gWorldInstance.AddCup(gStarCup); + gWorldInstance.AddCup(gSpecialCup); + gWorldInstance.AddCup(gBattleCup); /* Set default course; mario raceway */ SelectMarioRaceway(); @@ -767,7 +756,7 @@ void SelectSkyscraper() { gWorldInstance.SetCourseByType(); void SelectDoubleDeck() { gWorldInstance.SetCourseByType(); } void SelectDkJungle() { gWorldInstance.SetCourseByType(); } void SelectBigDonut() { gWorldInstance.SetCourseByType(); } -void SelectPodiumCeremony() { gWorldInstance.SetCourseByType(); } +void SelectPodiumCeremony() { gWorldInstance.CurrentCourse = gPodiumCeremony.get(); } // clang-format on void* GetMushroomCup(void) { diff --git a/src/port/Game.h b/src/port/Game.h index 46b52fe16..36b8ee0d4 100644 --- a/src/port/Game.h +++ b/src/port/Game.h @@ -177,6 +177,28 @@ bool IsDkJungle(); bool IsBigDonut(); bool IsPodiumCeremony(); +void SelectMarioRaceway(); +void SelectLuigiRaceway(); +void SelectChocoMountain(); +void SelectBowsersCastle(); +void SelectBansheeBoardwalk(); +void SelectYoshiValley(); +void SelectFrappeSnowland(); +void SelectKoopaTroopaBeach(); +void SelectRoyalRaceway(); +void SelectMooMooFarm(); +void SelectToadsTurnpike(); +void SelectKalimariDesert(); +void SelectSherbetLand(); +void SelectRainbowRoad(); +void SelectWarioStadium(); +void SelectBlockFort(); +void SelectSkyscraper(); +void SelectDoubleDeck(); +void SelectDkJungle(); +void SelectBigDonut(); +void SelectPodiumCeremony(); + void* GetMushroomCup(void); void* GetFlowerCup(void); diff --git a/src/port/ui/ContentBrowser.cpp b/src/port/ui/ContentBrowser.cpp index 826477ea5..5390d8a9d 100644 --- a/src/port/ui/ContentBrowser.cpp +++ b/src/port/ui/ContentBrowser.cpp @@ -147,12 +147,13 @@ namespace Editor { } } + // When resetting the known content, we need to also pop the custom courses + // out of World::Courses vector. Otherwise, duplicate courses would show up for users. void ContentBrowserWindow::RemoveCustomTracksFromTrackList() { for (auto& track : Tracks) { auto it = gWorldInstance.Courses.begin(); while (it != gWorldInstance.Courses.end()) { - if (track.course == *it) { - delete *it; + if (track.course == it->get()) { it = gWorldInstance.Courses.erase(it); } else { ++it; @@ -233,27 +234,31 @@ namespace Editor { std::string name = dir.substr(dir.find_last_of('/') + 1); std::string sceneFile = dir + "/scene.json"; std::string minimapFile = dir + "/minimap.png"; + // The track has a valid scene file if (manager->HasFile(sceneFile)) { auto archive = manager->GetArchiveFromFile(sceneFile); - Course* course = new Course(); + auto course = std::make_unique(); course->LoadO2R(dir); - gWorldInstance.Courses.push_back(course); - LoadLevel(archive, course, sceneFile); - LoadMinimap(archive, course, minimapFile); - Tracks.push_back({course, sceneFile, name, dir, archive}); - } else { + gWorldInstance.Courses.push_back(std::move(course)); + LoadLevel(archive, course.get(), sceneFile); + LoadMinimap(archive, course.get(), minimapFile); + Tracks.push_back({course.get(), sceneFile, name, dir, archive}); + } else { // The track does not have a valid scene file const std::string file = dir + "/data_track_sections"; + // If the track has a data_track_sections file, + // then it must at least be a valid track. + // So lets add it as an uninitialized track. if (manager->HasFile(file)) { - Course* course = new Course(); + auto course = std::make_unique(); course->Id = (std::string("mods:") + name).c_str(); course->Props.SetText(course->Props.Name, name.c_str(), sizeof(course->Props.Name)); course->Props.SetText(course->Props.DebugName, name.c_str(), sizeof(course->Props.Name)); auto archive = manager->GetArchiveFromFile(file); - Tracks.push_back({course, "", name, dir, archive}); + Tracks.push_back({course.get(), "", name, dir, archive}); } else { printf("ContentBrowser.cpp: Track '%s' missing required track files. Cannot add to game\n Missing %s/data_track_sections file\n", name.c_str(), dir.c_str()); }