diff --git a/include/defines.h b/include/defines.h index 0d2d306c7..5a784aa3c 100644 --- a/include/defines.h +++ b/include/defines.h @@ -1,6 +1,16 @@ #ifndef DEFINES_H #define DEFINES_H +#ifdef __cplusplus +#define EXTERN_C extern "C" +#define EXTERN_C_START extern "C" { +#define EXTERN_C_END } +#else +#define EXTERN_C extern +#define EXTERN_C_START +#define EXTERN_C_END +#endif + /** * @brief Options for Controller Pak state */ diff --git a/src/code_80005FD0.c b/src/code_80005FD0.c index 9d49040d7..5949b589a 100644 --- a/src/code_80005FD0.c +++ b/src/code_80005FD0.c @@ -42,6 +42,7 @@ #include "port/Game.h" #include "engine/tracks/Track.h" +#include "engine/RaceManager.h" s32 unk_code_80005FD0_pad[24]; Collision D_80162E70; @@ -7177,14 +7178,13 @@ void cpu_use_item_strategy(s32 playerId) { (CVarGetInteger("gHarderCPU", 0) == true)) { cpu_decisions_branch_item(playerId, &cpuStrategy->branch, - hard_cpu_gen_random_item((s16) gLapCountByPlayerId[playerId], - gGPCurrentRaceRankByPlayerId[playerId])); + RaceManager_GetRandomCPUItem(gGPCurrentRaceRankByPlayerId[playerId])); // Stock CPU Items } else if ((((playerId * 20) + 100) < gNumPathPointsTraversed[playerId]) && (cpuStrategy->timer >= 0x259) && (cpuStrategy->numItemUse < 3) && (gLapCountByPlayerId[playerId] < 3)) { cpu_decisions_branch_item( playerId, &cpuStrategy->branch, - cpu_gen_random_item((s16) gLapCountByPlayerId[playerId], gGPCurrentRaceRankByPlayerId[playerId])); + RaceManager_GetRandomCPUItem(gGPCurrentRaceRankByPlayerId[playerId])); } else { func_8001ABE0(playerId, cpuStrategy); } diff --git a/src/engine/RaceManager.cpp b/src/engine/RaceManager.cpp index 03ad157e3..96d0ad2ff 100644 --- a/src/engine/RaceManager.cpp +++ b/src/engine/RaceManager.cpp @@ -5,6 +5,7 @@ #include "port/Game.h" #include "engine/editor/Editor.h" #include "engine/editor/SceneManager.h" +#include "engine/RandomItemTable.h" extern "C" { #include "render_courses.h" @@ -68,6 +69,8 @@ void RaceManager::PreInit() { } else { gPlaceItemBoxes = true; } + + RaceManager::SetItemTables(); } void RaceManager::BeginPlay() { @@ -114,3 +117,67 @@ void RaceManager::PostInit() { OTrophy::Spawn(FVector(0,0,0), OTrophy::TrophyType::GOLD, OTrophy::Behaviour::GO_FISH); } } + +void RaceManager::SetItemTables() { + std::string humanTableName = ""; + std::string cpuTableName = ""; + + switch(gModeSelection) { + case GRAND_PRIX: + if (CVarGetInteger("gHarderCPU", false) == true) { + humanTableName = "mk:hard_cpu_grand_prix"; + cpuTableName = "mk:hard_cpu_grand_prix"; + } else { // normal gameplay + humanTableName = "mk:human_grand_prix"; + cpuTableName = "mk:cpu_grand_prix"; + } + case VERSUS: + switch (gPlayerCountSelection1) { + case TWO_PLAYERS_SELECTED: + humanTableName = "mk:versus_2p"; + cpuTableName = "none selected"; + break; + case THREE_PLAYERS_SELECTED: + humanTableName = "mk:versus_3p"; + cpuTableName = "none selected"; + break; + case FOUR_PLAYERS_SELECTED: + humanTableName = "mk:versus_4p"; + cpuTableName = "none selected"; + break; + } + break; + case BATTLE: + humanTableName = "mk:battle"; + cpuTableName = "none selected"; + break; + } + + mHumanItemTable = gItemTableRegistry.Get(humanTableName); + mCPUItemTable = gItemTableRegistry.Get(cpuTableName); + printf("[RaceManager] Selected human item probability table %s\n", humanTableName.c_str()); + printf("[RaceManager] Selected cpu item probability table %s\n", cpuTableName.c_str()); +} + +extern "C" int16_t RaceManager_GetRandomHumanItem(uint32_t rank) { + auto& raceManager = GetWorld()->GetRaceManager(); + + auto* table = raceManager.GetHumanItemTable(); + if (nullptr == table) { + printf("[RaceManager_GetRandomHumanItem] Item table nullptr, giving player a none item\n"); + return ITEM_NONE; + } + + return table->Roll(rank); +} + +extern "C" int16_t RaceManager_GetRandomCPUItem(uint32_t rank) { + auto& raceManager = GetWorld()->GetRaceManager(); + auto* table = raceManager.GetCPUItemTable(); + if (nullptr == table) { + printf("[RaceManager_GetRandomCPUItem] Item table nullptr, giving player a none item\n"); + return ITEM_NONE; + } + + return table->Roll(rank); +} diff --git a/src/engine/RaceManager.h b/src/engine/RaceManager.h index d7ac23a29..5897e55bc 100644 --- a/src/engine/RaceManager.h +++ b/src/engine/RaceManager.h @@ -1,6 +1,10 @@ -#pragma once +#ifndef RACE_MANAGER_H +#define RACE_MANAGER_H + +#include "defines.h" #ifdef __cplusplus +#include "engine/RandomItemTable.h" extern "C" { #endif #include @@ -37,8 +41,19 @@ public: virtual void PreInit(); virtual void BeginPlay(); virtual void PostInit(); + virtual void SetItemTables(); + RandomItemTable* GetHumanItemTable() { return mHumanItemTable; } + RandomItemTable* GetCPUItemTable() { return mCPUItemTable; } protected: World& WorldContext; + RandomItemTable* mHumanItemTable; + RandomItemTable* mCPUItemTable; + std::unordered_map mItemTables; }; -#endif \ No newline at end of file +#endif // __cplusplus + +EXTERN_C int16_t RaceManager_GetRandomHumanItem(uint32_t rank); +EXTERN_C int16_t RaceManager_GetRandomCPUItem(uint32_t rank); + +#endif // RACE_MANAGER_H diff --git a/src/engine/RandomItemTable.cpp b/src/engine/RandomItemTable.cpp new file mode 100644 index 000000000..603dc5c1e --- /dev/null +++ b/src/engine/RandomItemTable.cpp @@ -0,0 +1,104 @@ +#include "RandomItemTable.h" +#include "port/Game.h" + +extern "C" { +#include "math_util.h" +} + +RandomItemTable::RandomItemTable() { + mDistanceEnabled = false; +} + +bool RandomItemTable::Add(const std::string& resourceName, uint32_t rank, uint32_t weight, float distance) { + const ItemInfo* info = gItemRegistry.GetInfo(resourceName); + if (!info) { + printf("[ItemTables] Failed to add %s to table,\n item name passed into resourceName does not exist!\n", resourceName.c_str()); + return false; + } + + if (rank >= mTable.size()) { + if (rank >= NUM_PLAYERS) { + printf("[ItemTables] Failed to add item table, rank value too high!\n"); + return false; + } + mTable.resize(rank + 1); + } + + // Check if already exists + for (const ItemEntry& entry : mTable[rank]) { + if (entry.Id == info->Id) { + printf("[ItemTables] %s already exists for this rank, skipping...\n", resourceName.c_str()); + return false; + } + } + + mTable[rank].push_back(ItemEntry{info->Id, weight, distance}); + + return true; +} + +uint8_t RandomItemTable::Roll(uint32_t rank) const { + if (rank >= mTable.size()) { + printf("[ItemTables] [Roll] Invalid rank input %d. Giving player a none item\n", rank); + return ITEM_NONE; + } + + // Items that could be selected for this rank + const std::vector& itemList = mTable.at(rank); + if (itemList.empty()) { + printf("[ItemTables] [Roll] itemList empty. Giving player a none item\n"); + return ITEM_NONE; + } + + // Calculate total weight + uint32_t totalWeight = 0; + for (const ItemEntry& entry : itemList) { + if (this->IsBlacklisted(entry.Id)) { + continue; + } + totalWeight += entry.Weight; + } + + // Avoid division by zero + if (totalWeight == 0) { + printf("[ItemTables] [Roll] No items to give out for this rank. Giving player a none item\n"); + return ITEM_NONE; + } + + // Pick a random number from zero to (totalWeight - 1) + uint32_t rand = random_int(totalWeight - 1); + + // Cumulative sum over weights + uint32_t accumulated = 0; + for (const ItemEntry& entry : itemList) { + if (this->IsBlacklisted(entry.Id)) { + continue; + } + accumulated += entry.Weight; + if (rand < accumulated) { + return static_cast(entry.Id); + } + } + + // Fallback (should not happen) + printf("[ItemTables] [Roll] Reached unreachable code\n"); + [[unlikely]] return ITEM_NONE; +} + +void RandomItemTable::Blacklist(const std::string& resourceName) { + const ItemInfo* info = gItemRegistry.GetInfo(resourceName); + if (!info) { + return; + } + + mBlacklist.insert(info->Id); +} + +bool RandomItemTable::IsBlacklisted(uint32_t itemId) const { + //return mBlacklist.contains(itemId); + return mBlacklist.find(itemId) != mBlacklist.end(); +} + +void RandomItemTable::ClearBlacklist() { + mBlacklist.clear(); +} diff --git a/src/engine/RandomItemTable.h b/src/engine/RandomItemTable.h new file mode 100644 index 000000000..384014b82 --- /dev/null +++ b/src/engine/RandomItemTable.h @@ -0,0 +1,33 @@ +#pragma once + +#include +#include + +/** + * Uses weighted random picking + * + * This allows stock game to work identically + * while allowing mods to add items which equalizes + * the stock items without requiring addition chance editing + */ + +class RandomItemTable { +public: + RandomItemTable(); + bool Add(const std::string& resourceName, uint32_t rank, uint32_t weight, float distance); + uint8_t Roll(uint32_t rank) const; + void Blacklist(const std::string& resourceName); + bool IsBlacklisted(uint32_t id) const; + void ClearBlacklist(); +protected: + bool mDistanceEnabled; + struct ItemEntry { + uint32_t Id; + uint32_t Weight; + float Distance; + }; + + // Rank index item_id, chance + std::vector> mTable; + std::unordered_set mBlacklist; +}; diff --git a/src/engine/actors/Cloud.h b/src/engine/actors/Cloud.h index 68603e06f..e154a2b1c 100644 --- a/src/engine/actors/Cloud.h +++ b/src/engine/actors/Cloud.h @@ -1,7 +1,7 @@ #pragma once #include -#include "RegisterContent.h" +#include "engine/registry/RegisterContent.h" #include "engine/Actor.h" #include "CoreMath.h" diff --git a/src/engine/actors/FallingRock.h b/src/engine/actors/FallingRock.h index e4442a1a6..2bbbd7443 100644 --- a/src/engine/actors/FallingRock.h +++ b/src/engine/actors/FallingRock.h @@ -1,7 +1,7 @@ #pragma once #include -#include "RegisterContent.h" +#include "engine/registry/RegisterContent.h" #include "engine/Actor.h" #include "CoreMath.h" #include "engine/SpawnParams.h" diff --git a/src/engine/actors/Finishline.h b/src/engine/actors/Finishline.h index 867e728ef..192aca6a4 100644 --- a/src/engine/actors/Finishline.h +++ b/src/engine/actors/Finishline.h @@ -2,7 +2,7 @@ #include #include "CoreMath.h" -#include "RegisterContent.h" +#include "engine/registry/RegisterContent.h" #include "engine/Actor.h" extern "C" { diff --git a/src/engine/actors/MarioSign.h b/src/engine/actors/MarioSign.h index 453058f18..57b6c38aa 100644 --- a/src/engine/actors/MarioSign.h +++ b/src/engine/actors/MarioSign.h @@ -4,7 +4,7 @@ #include "engine/Actor.h" #include "CoreMath.h" #include "engine/World.h" -#include "RegisterContent.h" +#include "engine/registry/RegisterContent.h" extern "C" { #include "common_structs.h" diff --git a/src/engine/actors/Ship.h b/src/engine/actors/Ship.h index b16767d12..e650c4e2f 100644 --- a/src/engine/actors/Ship.h +++ b/src/engine/actors/Ship.h @@ -3,7 +3,7 @@ #include #include #include "CoreMath.h" -#include "RegisterContent.h" +#include "engine/registry/RegisterContent.h" #include "engine/Actor.h" class AShip : public AActor { diff --git a/src/engine/actors/SpaghettiShip.h b/src/engine/actors/SpaghettiShip.h index afc41fc95..7fb328ea3 100644 --- a/src/engine/actors/SpaghettiShip.h +++ b/src/engine/actors/SpaghettiShip.h @@ -3,7 +3,7 @@ #include #include #include "CoreMath.h" -#include "RegisterContent.h" +#include "engine/registry/RegisterContent.h" #include "engine/Actor.h" #include "engine/World.h" diff --git a/src/engine/actors/Starship.h b/src/engine/actors/Starship.h index 13539d7b8..0ed400a67 100644 --- a/src/engine/actors/Starship.h +++ b/src/engine/actors/Starship.h @@ -3,7 +3,7 @@ #include #include #include "CoreMath.h" -#include "RegisterContent.h" +#include "engine/registry/RegisterContent.h" #include "engine/Actor.h" #include "engine/World.h" diff --git a/src/engine/actors/Text.h b/src/engine/actors/Text.h index 9f0a4ab92..554f35c7f 100644 --- a/src/engine/actors/Text.h +++ b/src/engine/actors/Text.h @@ -1,7 +1,7 @@ #pragma once #include -#include "RegisterContent.h" +#include "engine/registry/RegisterContent.h" #include "engine/Actor.h" #include "src/textures.h" #include "engine/CoreMath.h" diff --git a/src/engine/actors/WarioSign.h b/src/engine/actors/WarioSign.h index 4bed2de67..112222570 100644 --- a/src/engine/actors/WarioSign.h +++ b/src/engine/actors/WarioSign.h @@ -1,7 +1,7 @@ #pragma once #include -#include "RegisterContent.h" +#include "engine/registry/RegisterContent.h" #include "engine/Actor.h" #include "CoreMath.h" diff --git a/src/engine/editor/Editor.h b/src/engine/editor/Editor.h index bfd7b1290..956d795b7 100644 --- a/src/engine/editor/Editor.h +++ b/src/engine/editor/Editor.h @@ -4,6 +4,7 @@ #include #include +#include "defines.h" #ifdef __cplusplus #include "GameObject.h" @@ -57,13 +58,6 @@ private: } // namespace TrackEditor #endif // __cplusplus - -#ifdef __cplusplus -#define EXTERN_C extern "C" -#else -#define EXTERN_C -#endif - EXTERN_C void Editor_Launch(const char* resourceName); EXTERN_C void Editor_SetLevelDimensions(s16 minX, s16 maxX, s16 minZ, s16 maxZ, s16 minY, s16 maxY); EXTERN_C bool Editor_IsEnabled(); diff --git a/src/engine/editor/SceneManager.cpp b/src/engine/editor/SceneManager.cpp index 1a0c129c0..02951e3dc 100644 --- a/src/engine/editor/SceneManager.cpp +++ b/src/engine/editor/SceneManager.cpp @@ -104,7 +104,7 @@ namespace TrackEditor { /** Do not use GetWorld()->CurrentCourse during loading! The current track is not guaranteed! **/ void LoadTrackDataFromJson(Track* track, const std::string& trackPath) { - SPDLOG_INFO("[SceneManager] [LoadTrackDataFromJson] Loading track scenefile..."); + SPDLOG_INFO("[SceneManager] [LoadTrackDataFromJson] Loading Track SceneFile..."); if (trackPath.empty()) { SPDLOG_INFO(" Unable to load track. trackPath empty."); @@ -147,7 +147,7 @@ namespace TrackEditor { LoadActors(track, data); LoadStaticMeshActors(track, data); LoadTour(track, data); - SPDLOG_INFO("[SceneManager] [LoadTrackDataFromJson] Scene File Loaded!"); + SPDLOG_INFO("[SceneManager] [LoadTrackDataFromJson] SceneFile Loaded!\n"); } void LoadTrackInfo(TrackInfo& info, std::shared_ptr archive, std::string sceneFile) { @@ -155,6 +155,7 @@ namespace TrackEditor { SPDLOG_INFO("[SceneManager] [LoadTrackDataFromJson] Failed to load scenefile, track or rootarchive were null"); return; } + SPDLOG_INFO("[SceneManager] [LoadTrackInfo] Loading TrackInfo..."); /* * Manually loading a custom asset file (scene.json) with no extractor class means that @@ -179,7 +180,7 @@ namespace TrackEditor { LoadTrackInfoData(info, data); - SPDLOG_INFO("[SceneManager] [LoadTrackInfo] Loaded track info!"); + SPDLOG_INFO("[SceneManager] [LoadTrackInfo] Loaded TrackInfo!\n"); } void Load_AddStaticMeshActor(const nlohmann::json& actorJson) { diff --git a/src/engine/objects/Bat.h b/src/engine/objects/Bat.h index d38f3e8a2..67c5a0d74 100644 --- a/src/engine/objects/Bat.h +++ b/src/engine/objects/Bat.h @@ -4,7 +4,7 @@ #include #include "Object.h" -#include "RegisterContent.h" +#include "engine/registry/RegisterContent.h" #include "World.h" #include "CoreMath.h" diff --git a/src/engine/objects/BombKart.h b/src/engine/objects/BombKart.h index 5d59eeb1a..3ce2d35b2 100644 --- a/src/engine/objects/BombKart.h +++ b/src/engine/objects/BombKart.h @@ -1,7 +1,7 @@ #pragma once #include -#include "RegisterContent.h" +#include "engine/registry/RegisterContent.h" #include "engine/objects/Object.h" #include "World.h" diff --git a/src/engine/objects/Boos.h b/src/engine/objects/Boos.h index 175fd45fc..b29757fa7 100644 --- a/src/engine/objects/Boos.h +++ b/src/engine/objects/Boos.h @@ -4,7 +4,7 @@ #include #include "Object.h" -#include "RegisterContent.h" +#include "engine/registry/RegisterContent.h" #include "World.h" #include "CoreMath.h" diff --git a/src/engine/objects/CheepCheep.h b/src/engine/objects/CheepCheep.h index 45b0ff435..bca65d100 100644 --- a/src/engine/objects/CheepCheep.h +++ b/src/engine/objects/CheepCheep.h @@ -3,7 +3,7 @@ #include #include #include "Object.h" -#include "RegisterContent.h" +#include "engine/registry/RegisterContent.h" #include "engine/CoreMath.h" #include "World.h" diff --git a/src/engine/objects/Crab.h b/src/engine/objects/Crab.h index 0c285e92c..425361b02 100644 --- a/src/engine/objects/Crab.h +++ b/src/engine/objects/Crab.h @@ -2,7 +2,7 @@ #include #include -#include "RegisterContent.h" +#include "engine/registry/RegisterContent.h" #include "engine/objects/Object.h" #include "CoreMath.h" #include "World.h" diff --git a/src/engine/objects/Flagpole.h b/src/engine/objects/Flagpole.h index 218c2a6bf..99ef151ba 100644 --- a/src/engine/objects/Flagpole.h +++ b/src/engine/objects/Flagpole.h @@ -4,7 +4,7 @@ #include #include "Object.h" -#include "RegisterContent.h" +#include "engine/registry/RegisterContent.h" #include "World.h" extern "C" { diff --git a/src/engine/objects/GrandPrixBalloons.h b/src/engine/objects/GrandPrixBalloons.h index 91bbb24b9..f807fb350 100644 --- a/src/engine/objects/GrandPrixBalloons.h +++ b/src/engine/objects/GrandPrixBalloons.h @@ -2,7 +2,7 @@ #include -#include "RegisterContent.h" +#include "engine/registry/RegisterContent.h" #include "engine/World.h" #include "engine/objects/Object.h" diff --git a/src/engine/objects/Hedgehog.h b/src/engine/objects/Hedgehog.h index 560639f26..c5df0ea6f 100644 --- a/src/engine/objects/Hedgehog.h +++ b/src/engine/objects/Hedgehog.h @@ -4,7 +4,7 @@ #include #include "Object.h" -#include "RegisterContent.h" +#include "engine/registry/RegisterContent.h" #include "engine/World.h" extern "C" { diff --git a/src/engine/objects/HotAirBalloon.h b/src/engine/objects/HotAirBalloon.h index 49b5c7e82..dfbe3cfdb 100644 --- a/src/engine/objects/HotAirBalloon.h +++ b/src/engine/objects/HotAirBalloon.h @@ -3,7 +3,7 @@ #include #include "Object.h" -#include "RegisterContent.h" +#include "engine/registry/RegisterContent.h" #include "World.h" class OHotAirBalloon : public OObject { diff --git a/src/engine/objects/Penguin.h b/src/engine/objects/Penguin.h index f4f79d461..e40cc7bdb 100644 --- a/src/engine/objects/Penguin.h +++ b/src/engine/objects/Penguin.h @@ -1,7 +1,7 @@ #pragma once #include -#include "RegisterContent.h" +#include "engine/registry/RegisterContent.h" #include "engine/World.h" #include "engine/objects/Object.h" diff --git a/src/engine/objects/Podium.h b/src/engine/objects/Podium.h index 2f00bb50d..52cef0761 100644 --- a/src/engine/objects/Podium.h +++ b/src/engine/objects/Podium.h @@ -2,7 +2,7 @@ #include -#include "RegisterContent.h" +#include "engine/registry/RegisterContent.h" #include "World.h" diff --git a/src/engine/objects/Seagull.h b/src/engine/objects/Seagull.h index b944c1348..11b59e41c 100644 --- a/src/engine/objects/Seagull.h +++ b/src/engine/objects/Seagull.h @@ -3,7 +3,7 @@ #include #include "Object.h" -#include "RegisterContent.h" +#include "engine/registry/RegisterContent.h" #include "engine/World.h" //! @todo unk_0D5 needs to be a struct variable probably. What does it do? Behaviour? diff --git a/src/engine/objects/Snowman.h b/src/engine/objects/Snowman.h index cc08c443a..2aac7366a 100644 --- a/src/engine/objects/Snowman.h +++ b/src/engine/objects/Snowman.h @@ -3,7 +3,7 @@ #include #include "Object.h" -#include "RegisterContent.h" +#include "engine/registry/RegisterContent.h" #include "World.h" extern "C" { diff --git a/src/engine/objects/Thwomp.h b/src/engine/objects/Thwomp.h index e46e682c5..52996a018 100644 --- a/src/engine/objects/Thwomp.h +++ b/src/engine/objects/Thwomp.h @@ -1,7 +1,7 @@ #pragma once #include -#include "RegisterContent.h" +#include "engine/registry/RegisterContent.h" #include "engine/World.h" #include "engine/SpawnParams.h" #include "engine/CoreMath.h" diff --git a/src/engine/objects/TrashBin.h b/src/engine/objects/TrashBin.h index d516cbe2c..551f2d44e 100644 --- a/src/engine/objects/TrashBin.h +++ b/src/engine/objects/TrashBin.h @@ -3,7 +3,7 @@ #include #include "Object.h" -#include "RegisterContent.h" +#include "engine/registry/RegisterContent.h" #include "World.h" class OTrashBin : public OObject { diff --git a/src/engine/objects/Trophy.h b/src/engine/objects/Trophy.h index aedfef48c..a6747aedc 100644 --- a/src/engine/objects/Trophy.h +++ b/src/engine/objects/Trophy.h @@ -2,7 +2,7 @@ #include #include "Object.h" -#include "RegisterContent.h" +#include "engine/registry/RegisterContent.h" #include "World.h" #include "engine/particles/StarEmitter.h" diff --git a/src/engine/registry/DataRegistry.h b/src/engine/registry/DataRegistry.h new file mode 100644 index 000000000..2b3b9c9ac --- /dev/null +++ b/src/engine/registry/DataRegistry.h @@ -0,0 +1,44 @@ +#pragma once +#include +#include +#include +#include + +template +class DataRegistry { +public: + // Add object by copy or move; overwrites if exists + void Add(const std::string& resourceName, TObject&& object) { + mMap[resourceName] = std::make_unique(std::forward(object)); + } + + void Add(const std::string& resourceName, const TObject& object) { + mMap[resourceName] = std::make_unique(object); + } + + // Get pointer to object (nullptr if not found) + TObject* Get(const std::string& resourceName) { + auto it = mMap.find(resourceName); + return it != mMap.end() ? it->second.get() : nullptr; + } + + const TObject* Get(const std::string& resourceName) const { + auto it = mMap.find(resourceName); + return it != mMap.end() ? it->second.get() : nullptr; + } + + bool Remove(const std::string& resourceName) { + return mMap.erase(resourceName) > 0; + } + + size_t Size() const { + return mMap.size(); + } + + void Clear() { + mMap.clear(); + } + +private: + std::unordered_map> mMap; +}; diff --git a/src/engine/RegisterContent.cpp b/src/engine/registry/RegisterActors.cpp similarity index 63% rename from src/engine/RegisterContent.cpp rename to src/engine/registry/RegisterActors.cpp index d2dba2675..7409f2b06 100644 --- a/src/engine/RegisterContent.cpp +++ b/src/engine/registry/RegisterActors.cpp @@ -1,11 +1,6 @@ -#include "SpawnParams.h" +#include "engine/registry/RegisterContent.h" #include "engine/CoreMath.h" -#include "Registry.h" -#include "engine/World.h" -#include "RegisterContent.h" - -#include "AllTracks.h" -#include "AllActors.h" +#include "engine/AllActors.h" extern "C" { #include "common_structs.h" @@ -15,20 +10,11 @@ extern "C" { } /** - * @file RegisterContent - * This file is responsible for registering the games stock content - */ - - -/** + * DO NOT RE-ORDER ANYTHING IN THESE FILES * - * DO NOT RE-ORDER ANYTHING IN THIS FILE. - * IT WILL MIX UP THE IDS - * - * Add new content to the end of the function + * It will result in differing Ids */ - void RegisterActors(Registry& r) { ActorInfo info; @@ -290,216 +276,3 @@ void RegisterActors(Registry& r) { info = { .ResourceName = "mk:bowser_statue", .Name = "Bowser Statue" }; r.Add(info, AddActorToWorld); } - -void RegisterTracks(Registry& r) { - TrackInfo info; - - info = { - .ResourceName = "mk:mario_raceway", - .Name = "mario raceway", - .DebugName = "m circuit", - .Length = "567m", - .MinimapTexture = minimap_mario_raceway, - }; - - r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); - - info = { - .ResourceName = "mk:choco_mountain", - .Name = "choco mountain", - .DebugName = "mountain", - .Length = "687m", - .MinimapTexture = minimap_choco_mountain, - }; - - r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); - - info = { - .ResourceName = "mk:bowsers_castle", - .Name = "bowser's castle", - .DebugName = "castle", - .Length = "777m", - .MinimapTexture = minimap_bowsers_castle, - }; - - r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); - - info = { - .ResourceName = "mk:banshee_boardwalk", - .Name = "banshee boardwalk", - .DebugName = "ghost", - .Length = "747m", - .MinimapTexture = minimap_banshee_boardwalk, - }; - - r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); - - info = { - .ResourceName = "mk:yoshi_valley", - .Name = "yoshi valley", - .DebugName = "maze", - .Length = "772m", - .MinimapTexture = minimap_yoshi_valley, - }; - - r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); - - info = { - .ResourceName = "mk:frappe_snowland", - .Name = "frappe snowland", - .DebugName = "snow", - .Length = "734m", - .MinimapTexture = minimap_frappe_snowland, - }; - - r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); - - info = { - .ResourceName = "mk:koopa_beach", - .Name = "koopa troopa beach", - .DebugName = "beach", - .Length = "691m", - .MinimapTexture = minimap_koopa_troopa_beach, - }; - - r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); - - info = { - .ResourceName = "mk:royal_raceway", - .Name = "royal raceway", - .DebugName = "p circuit", - .Length = "1025m", - .MinimapTexture = minimap_royal_raceway, - }; - - r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); - - info = { - .ResourceName = "mk:luigi_raceway", - .Name = "luigi raceway", - .DebugName = "l circuit", - .Length = "717m", - .MinimapTexture = minimap_luigi_raceway, - }; - - r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); - - info = { - .ResourceName = "mk:moo_moo_farm", - .Name = "moo moo farm", - .DebugName = "farm", - .Length = "527m", - .MinimapTexture = minimap_moo_moo_farm, - }; - - r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); - - info = { - .ResourceName = "mk:toads_turnpike", - .Name = "toad's turnpike", - .DebugName = "highway", - .Length = "1036m", - .MinimapTexture = minimap_toads_turnpike, - }; - - r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); - - info = { - .ResourceName = "mk:kalimari_desert", - .Name = "kalimari desert", - .DebugName = "desert", - .Length = "753m", - .MinimapTexture = minimap_kalimari_desert, - }; - - r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); - - info = { - .ResourceName = "mk:sherbet_land", - .Name = "sherbet land", - .DebugName = "sherbet", - .Length = "756m", - .MinimapTexture = minimap_sherbet_land, - }; - - r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); - - info = { - .ResourceName = "mk:rainbow_road", - .Name = "rainbow road", - .DebugName = "rainbow", - .Length = "2000m", - .MinimapTexture = minimap_rainbow_road, - }; - - r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); - - info = { - .ResourceName = "mk:wario_stadium", - .Name = "wario stadium", - .DebugName = "stadium", - .Length = "1591m", - .MinimapTexture = minimap_wario_stadium, - }; - - r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); - - info = { - .ResourceName = "mk:block_fort", - .Name = "block fort", - .DebugName = "block", - .Length = "", - .MinimapTexture = minimap_block_fort, - }; - - r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); - - info = { - .ResourceName = "mk:skyscraper", - .Name = "skyscraper", - .DebugName = "skyscraper", - .Length = "", - .MinimapTexture = minimap_skyscraper, - }; - - r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); - - info = { - .ResourceName = "mk:double_deck", - .Name = "double deck", - .DebugName = "deck", - .Length = "", - .MinimapTexture = minimap_double_deck, - }; - - r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); - - info = { - .ResourceName = "mk:dk_jungle", - .Name = "d.k.'s jungle parkway", - .DebugName = "jungle", - .Length = "893m", - .MinimapTexture = minimap_dks_jungle_parkway, - }; - - r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); - - info = { - .ResourceName = "mk:big_donut", - .Name = "big donut", - .DebugName = "doughnut", - .Length = "", - .MinimapTexture = minimap_big_donut, - }; - - r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); - - info = { - .ResourceName = "hm:test_track", - .Name = "test track", - .DebugName = "test track", - .Length = "100m", - }; - - r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); -} diff --git a/src/engine/RegisterContent.h b/src/engine/registry/RegisterContent.h similarity index 63% rename from src/engine/RegisterContent.h rename to src/engine/registry/RegisterContent.h index 9afcc13b9..4678c16a4 100644 --- a/src/engine/RegisterContent.h +++ b/src/engine/registry/RegisterContent.h @@ -1,10 +1,11 @@ #pragma once -#include "Object.h" #include "Registry.h" -#include "SpawnParams.h" -#include "port/Game.h" -#include +#include "DataRegistry.h" +#include "src/port/Game.h" +#include "engine/objects/Object.h" +#include "engine/Actor.h" +#include "engine/SpawnParams.h" template static OObject* AddObjectToWorld(const SpawnParams& params) { return GetWorld()->AddObject(std::make_unique(params)); @@ -14,5 +15,7 @@ template static AActor* AddActorToWorld(const SpawnParams& params) { return GetWorld()->AddActor(std::make_unique(params)); } -void RegisterActors(Registry& r); void RegisterTracks(Registry& r); +void RegisterActors(Registry& r); +void RegisterItems(Registry& r); +void RegisterItemTables(DataRegistry& r); diff --git a/src/engine/registry/RegisterItemTables.cpp b/src/engine/registry/RegisterItemTables.cpp new file mode 100644 index 000000000..5d9b39bd3 --- /dev/null +++ b/src/engine/registry/RegisterItemTables.cpp @@ -0,0 +1,379 @@ +#include "RegisterContent.h" +#include +#include "engine/RandomItemTable.h" + +/** + * DO NOT RE-ORDER ANYTHING IN THESE FILES + * + * It will result in differing Ids + */ + +enum RANK { + RANK_ONE, + RANK_TWO, + RANK_THREE, + RANK_FOUR, + RANK_FIVE, + RANK_SIX, + RANK_SEVEN, + RANK_EIGHT +}; + +void RegisterHumanItemTable(DataRegistry& r); +void RegisterCPUItemTable(DataRegistry& r); +void RegisterHardCPUItemTable(DataRegistry& r); +void RegisterVersus2PItemTable(DataRegistry& r); +void RegisterVersus3PItemTable(DataRegistry& r); +void RegisterVersus4PItemTable(DataRegistry& r); +void RegisterBattleItemTable(DataRegistry& r); + +void RegisterItemTables(DataRegistry& r) { + RegisterHumanItemTable(r); + RegisterCPUItemTable(r); + RegisterHardCPUItemTable(r); + RegisterVersus2PItemTable(r); + RegisterVersus3PItemTable(r); + RegisterVersus4PItemTable(r); + RegisterBattleItemTable(r); +} + +void RegisterHumanItemTable(DataRegistry& r) { + RandomItemTable table; + + table.Add("mk:banana", RANK_ONE, 30, 0.0f); + table.Add("mk:banana_bunch", RANK_ONE, 5, 0.0f); + table.Add("mk:green_shell", RANK_ONE, 30, 0.0f); + table.Add("mk:triple_green_shell", RANK_ONE, 5, 0.0f); + table.Add("mk:red_shell", RANK_ONE, 5, 0.0f); + table.Add("mk:fake_item_box", RANK_ONE, 10, 0.0f); + table.Add("mk:boo", RANK_ONE, 5, 0.0f); + table.Add("mk:mushroom", RANK_ONE, 10, 0.0f); + + table.Add("mk:banana_bunch", RANK_TWO, 5, 0.0f); + table.Add("mk:green_shell", RANK_TWO, 5, 0.0f); + table.Add("mk:triple_green_shell", RANK_TWO, 10, 0.0f); + table.Add("mk:red_shell", RANK_TWO, 15, 0.0f); + table.Add("mk:triple_red_shell", RANK_TWO, 20, 0.0f); + table.Add("mk:thunderbolt", RANK_TWO, 5, 0.0f); + table.Add("mk:fake_item_box", RANK_TWO, 5, 0.0f); + table.Add("mk:star", RANK_TWO, 5, 0.0f); + table.Add("mk:boo", RANK_TWO, 5, 0.0f); + table.Add("mk:mushroom", RANK_TWO, 5, 0.0f); + table.Add("mk:triple_mushroom",RANK_TWO, 15, 0.0f); + table.Add("mk:super_mushroom", RANK_TWO, 5, 0.0f); + + table.Add("mk:triple_green_shell", RANK_THREE, 10, 0.0f); + table.Add("mk:red_shell", RANK_THREE, 20, 0.0f); + table.Add("mk:triple_red_shell", RANK_THREE, 20, 0.0f); + table.Add("mk:thunderbolt", RANK_THREE, 5, 0.0f); + table.Add("mk:star", RANK_THREE, 10, 0.0f); + table.Add("mk:mushroom", RANK_THREE, 5, 0.0f); + table.Add("mk:triple_mushroom",RANK_THREE, 20, 0.0f); + table.Add("mk:super_mushroom", RANK_THREE, 10, 0.0f); + + table.Add("mk:red_shell", RANK_FOUR, 15, 0.0f); + table.Add("mk:triple_red_shell", RANK_FOUR, 20, 0.0f); + table.Add("mk:blue_spiny_shell", RANK_FOUR, 5, 0.0f); + table.Add("mk:thunderbolt", RANK_FOUR, 10, 0.0f); + table.Add("mk:star", RANK_FOUR, 15, 0.0f); + table.Add("mk:mushroom", RANK_FOUR, 5, 0.0f); + table.Add("mk:triple_mushroom",RANK_FOUR, 20, 0.0f); + table.Add("mk:super_mushroom", RANK_FOUR, 10, 0.0f); + + table.Add("mk:red_shell", RANK_FIVE, 10, 0.0f); + table.Add("mk:triple_red_shell", RANK_FIVE, 20, 0.0f); + table.Add("mk:blue_spiny_shell", RANK_FIVE, 5, 0.0f); + table.Add("mk:thunderbolt", RANK_FIVE, 10, 0.0f); + table.Add("mk:star", RANK_FIVE, 15, 0.0f); + table.Add("mk:mushroom", RANK_FIVE, 5, 0.0f); + table.Add("mk:triple_mushroom",RANK_FIVE, 25, 0.0f); + table.Add("mk:super_mushroom", RANK_FIVE, 10, 0.0f); + + table.Add("mk:triple_red_shell", RANK_SIX, 20, 0.0f); + table.Add("mk:blue_spiny_shell", RANK_SIX, 10, 0.0f); + table.Add("mk:thunderbolt", RANK_SIX, 15, 0.0f); + table.Add("mk:star", RANK_SIX, 20, 0.0f); + table.Add("mk:triple_mushroom",RANK_SIX, 25, 0.0f); + table.Add("mk:super_mushroom", RANK_SIX, 10, 0.0f); + + table.Add("mk:triple_red_shell", RANK_SEVEN, 20, 0.0f); + table.Add("mk:blue_spiny_shell", RANK_SEVEN, 10, 0.0f); + table.Add("mk:thunderbolt", RANK_SEVEN, 20, 0.0f); + table.Add("mk:star", RANK_SEVEN, 30, 0.0f); + table.Add("mk:triple_mushroom",RANK_SEVEN, 10, 0.0f); + table.Add("mk:super_mushroom", RANK_SEVEN, 10, 0.0f); + + table.Add("mk:triple_red_shell", RANK_EIGHT, 20, 0.0f); + table.Add("mk:blue_spiny_shell", RANK_EIGHT, 15, 0.0f); + table.Add("mk:thunderbolt", RANK_EIGHT, 20, 0.0f); + table.Add("mk:star", RANK_EIGHT, 30, 0.0f); + table.Add("mk:triple_mushroom",RANK_EIGHT, 5, 0.0f); + table.Add("mk:super_mushroom", RANK_EIGHT, 10, 0.0f); + + r.Add("mk:human_grand_prix", std::move(table)); +} + +void RegisterCPUItemTable(DataRegistry& r) { + RandomItemTable table; + + table.Add("mk:banana", RANK_ONE, 60, 0.0f); + table.Add("mk:green_shell", RANK_ONE, 25, 0.0f); + table.Add("mk:fake_item_box", RANK_ONE, 10, 0.0f); + table.Add("mk:boo", RANK_ONE, 5, 0.0f); + + table.Add("mk:banana", RANK_TWO, 50, 0.0f); + table.Add("mk:green_shell", RANK_TWO, 25, 0.0f); + table.Add("mk:triple_green_shell", RANK_TWO, 5, 0.0f); + table.Add("mk:fake_item_box", RANK_TWO, 10, 0.0f); + table.Add("mk:boo", RANK_TWO, 5, 0.0f); + table.Add("mk:mushroom", RANK_TWO, 5, 0.0f); + + table.Add("mk:banana", RANK_THREE, 40, 0.0f); + table.Add("mk:green_shell", RANK_THREE, 25, 0.0f); + table.Add("mk:triple_green_shell", RANK_THREE, 10, 0.0f); + table.Add("mk:fake_item_box", RANK_THREE, 10, 0.0f); + table.Add("mk:boo", RANK_THREE, 5, 0.0f); + table.Add("mk:mushroom", RANK_THREE, 10, 0.0f); + + table.Add("mk:banana", RANK_FOUR, 35, 0.0f); + table.Add("mk:green_shell", RANK_FOUR, 25, 0.0f); + table.Add("mk:triple_green_shell", RANK_FOUR, 15, 0.0f); + table.Add("mk:fake_item_box", RANK_FOUR, 10, 0.0f); + table.Add("mk:boo", RANK_FOUR, 5, 0.0f); + table.Add("mk:mushroom", RANK_FOUR, 10, 0.0f); + + table.Add("mk:banana", RANK_FIVE, 30, 0.0f); + table.Add("mk:green_shell", RANK_FIVE, 20, 0.0f); + table.Add("mk:triple_green_shell", RANK_FIVE, 20, 0.0f); + table.Add("mk:fake_item_box", RANK_FIVE, 5, 0.0f); + table.Add("mk:star", RANK_FIVE, 5, 0.0f); + table.Add("mk:mushroom", RANK_FIVE, 20, 0.0f); + + table.Add("mk:banana", RANK_SIX, 30, 0.0f); + table.Add("mk:green_shell", RANK_SIX, 20, 0.0f); + table.Add("mk:triple_green_shell", RANK_SIX, 20, 0.0f); + table.Add("mk:fake_item_box", RANK_SIX, 5, 0.0f); + table.Add("mk:star", RANK_SIX, 5, 0.0f); + table.Add("mk:mushroom", RANK_SIX, 20, 0.0f); + + table.Add("mk:banana", RANK_SEVEN, 30, 0.0f); + table.Add("mk:green_shell", RANK_SEVEN, 20, 0.0f); + table.Add("mk:triple_green_shell", RANK_SEVEN, 20, 0.0f); + table.Add("mk:star", RANK_SEVEN, 10, 0.0f); + table.Add("mk:mushroom", RANK_SEVEN, 20, 0.0f); + + table.Add("mk:banana", RANK_EIGHT, 25, 0.0f); + table.Add("mk:green_shell", RANK_EIGHT, 20, 0.0f); + table.Add("mk:triple_green_shell", RANK_EIGHT, 20, 0.0f); + table.Add("mk:thunderbolt", RANK_EIGHT, 1, 0.0f); + table.Add("mk:star", RANK_EIGHT, 10, 0.0f); + table.Add("mk:mushroom", RANK_EIGHT, 24, 0.0f); + + r.Add("mk:cpu_grand_prix", std::move(table)); +} + +void RegisterHardCPUItemTable(DataRegistry& r) { + RandomItemTable table; + + table.Add("mk:none", RANK_ONE, 4, 0.0f); + table.Add("mk:banana", RANK_ONE, 30, 0.0f); + table.Add("mk:banana_bunch", RANK_ONE, 5, 0.0f); + table.Add("mk:green_shell", RANK_ONE, 30, 0.0f); + table.Add("mk:triple_green_shell", RANK_ONE, 5, 0.0f); + table.Add("mk:red_shell", RANK_ONE, 5, 0.0f); + table.Add("mk:fake_item_box", RANK_ONE, 10, 0.0f); + table.Add("mk:boo", RANK_ONE, 5, 0.0f); + table.Add("mk:mushroom", RANK_ONE, 10, 0.0f); + + table.Add("mk:banana", RANK_TWO, 5, 0.0f); + table.Add("mk:banana_bunch", RANK_TWO, 5, 0.0f); + table.Add("mk:green_shell", RANK_TWO, 5, 0.0f); + table.Add("mk:triple_green_shell", RANK_TWO, 10, 0.0f); + table.Add("mk:red_shell", RANK_TWO, 15, 0.0f); + table.Add("mk:triple_red_shell", RANK_TWO, 20, 0.0f); + table.Add("mk:fake_item_box", RANK_TWO, 5, 0.0f); + table.Add("mk:star", RANK_TWO, 5, 0.0f); + table.Add("mk:boo", RANK_TWO, 5, 0.0f); + table.Add("mk:mushroom", RANK_TWO, 5, 0.0f); + table.Add("mk:triple_mushroom",RANK_TWO, 15, 0.0f); + table.Add("mk:super_mushroom", RANK_TWO, 5, 0.0f); + + table.Add("mk:banana", RANK_THREE, 5, 0.0f); + table.Add("mk:banana_bunch", RANK_THREE, 3, 0.0f); + table.Add("mk:triple_green_shell", RANK_THREE, 10, 0.0f); + table.Add("mk:red_shell", RANK_THREE, 20, 0.0f); + table.Add("mk:triple_red_shell", RANK_THREE, 19, 0.0f); + table.Add("mk:star", RANK_THREE, 10, 0.0f); + table.Add("mk:mushroom", RANK_THREE, 5, 0.0f); + table.Add("mk:triple_mushroom",RANK_THREE, 19, 0.0f); + table.Add("mk:super_mushroom", RANK_THREE, 9, 0.0f); + + table.Add("mk:banana", RANK_FOUR, 5, 0.0f); + table.Add("mk:green_shell", RANK_FOUR, 5, 0.0f); + table.Add("mk:triple_green_shell", RANK_FOUR, 5, 0.0f); + table.Add("mk:red_shell", RANK_FOUR, 15, 0.0f); + table.Add("mk:triple_red_shell", RANK_FOUR, 10, 0.0f); + table.Add("mk:fake_item_box", RANK_FOUR, 5, 0.0f); + table.Add("mk:star", RANK_FOUR, 15, 0.0f); + table.Add("mk:boo", RANK_FOUR, 5, 0.0f); + table.Add("mk:mushroom", RANK_FOUR, 5, 0.0f); + table.Add("mk:triple_mushroom",RANK_FOUR, 20, 0.0f); + table.Add("mk:super_mushroom", RANK_FOUR, 10, 0.0f); + + table.Add("mk:red_shell", RANK_FIVE, 10, 0.0f); + table.Add("mk:triple_red_shell", RANK_FIVE, 20, 0.0f); + table.Add("mk:blue_spiny_shell", RANK_FIVE, 5, 0.0f); + table.Add("mk:fake_item_box", RANK_FIVE, 5, 0.0f); + table.Add("mk:star", RANK_FIVE, 15, 0.0f); + table.Add("mk:mushroom", RANK_FIVE, 10, 0.0f); + table.Add("mk:triple_mushroom",RANK_FIVE, 25, 0.0f); + table.Add("mk:super_mushroom", RANK_FIVE, 10, 0.0f); + + table.Add("mk:red_shell", RANK_SIX, 5, 0.0f); + table.Add("mk:triple_red_shell", RANK_SIX, 25, 0.0f); + table.Add("mk:blue_spiny_shell", RANK_SIX, 10, 0.0f); + table.Add("mk:star", RANK_SIX, 20, 0.0f); + table.Add("mk:mushroom", RANK_SIX, 5, 0.0f); + table.Add("mk:triple_mushroom",RANK_SIX, 25, 0.0f); + table.Add("mk:super_mushroom", RANK_SIX, 10, 0.0f); + + table.Add("mk:green_shell", RANK_SEVEN, 5, 0.0f); + table.Add("mk:red_shell", RANK_SEVEN, 5, 0.0f); + table.Add("mk:triple_red_shell", RANK_SEVEN, 25, 0.0f); + table.Add("mk:blue_spiny_shell", RANK_SEVEN, 10, 0.0f); + table.Add("mk:star", RANK_SEVEN, 30, 0.0f); + table.Add("mk:mushroom", RANK_SEVEN, 5, 0.0f); + table.Add("mk:triple_mushroom",RANK_SEVEN, 10, 0.0f); + table.Add("mk:super_mushroom", RANK_SEVEN, 10, 0.0f); + + table.Add("mk:triple_green_shell", RANK_EIGHT, 5, 0.0f); + table.Add("mk:red_shell", RANK_EIGHT, 5, 0.0f); + table.Add("mk:triple_red_shell", RANK_EIGHT, 20, 0.0f); + table.Add("mk:blue_spiny_shell", RANK_EIGHT, 15, 0.0f); + table.Add("mk:thunderbolt", RANK_EIGHT, 10, 0.0f); + table.Add("mk:star", RANK_EIGHT, 30, 0.0f); + table.Add("mk:triple_mushroom",RANK_EIGHT, 5, 0.0f); + table.Add("mk:super_mushroom", RANK_EIGHT, 10, 0.0f); + + r.Add("mk:hard_cpu_grand_prix", std::move(table)); +} + +void RegisterVersus2PItemTable(DataRegistry& r) { + RandomItemTable table; + + table.Add("mk:banana", RANK_ONE, 25, 0.0f); + table.Add("mk:banana_bunch", RANK_ONE, 10, 0.0f); + table.Add("mk:green_shell", RANK_ONE, 30, 0.0f); + table.Add("mk:triple_green_shell", RANK_ONE, 5, 0.0f); + table.Add("mk:red_shell", RANK_ONE, 5, 0.0f); + table.Add("mk:fake_item_box", RANK_ONE, 10, 0.0f); + table.Add("mk:boo", RANK_ONE, 5, 0.0f); + table.Add("mk:mushroom", RANK_ONE, 10, 0.0f); + + table.Add("mk:banana_bunch", RANK_TWO, 5, 0.0f); + table.Add("mk:triple_green_shell", RANK_TWO, 5, 0.0f); + table.Add("mk:red_shell", RANK_TWO, 5, 0.0f); + table.Add("mk:triple_red_shell", RANK_TWO, 15, 0.0f); + table.Add("mk:blue_spiny_shell", RANK_TWO, 5, 0.0f); + table.Add("mk:thunderbolt", RANK_TWO, 15, 0.0f); + table.Add("mk:star", RANK_TWO, 15, 0.0f); + table.Add("mk:triple_mushroom",RANK_TWO, 15, 0.0f); + table.Add("mk:super_mushroom", RANK_TWO, 20, 0.0f); + + r.Add("mk:versus_2p", std::move(table)); +} + +void RegisterVersus3PItemTable(DataRegistry& r) { + RandomItemTable table; + + table.Add("mk:banana", RANK_ONE, 35, 0.0f); + table.Add("mk:banana_bunch", RANK_ONE, 5, 0.0f); + table.Add("mk:green_shell", RANK_ONE, 30, 0.0f); + table.Add("mk:red_shell", RANK_ONE, 5, 0.0f); + table.Add("mk:fake_item_box", RANK_ONE, 10, 0.0f); + table.Add("mk:boo", RANK_ONE, 5, 0.0f); + table.Add("mk:mushroom", RANK_ONE, 10, 0.0f); + + table.Add("mk:banana", RANK_TWO, 5, 0.0f); + table.Add("mk:banana_bunch", RANK_TWO, 5, 0.0f); + table.Add("mk:triple_green_shell", RANK_TWO, 10, 0.0f); + table.Add("mk:red_shell", RANK_TWO, 15, 0.0f); + table.Add("mk:triple_red_shell", RANK_TWO, 15, 0.0f); + table.Add("mk:thunderbolt", RANK_TWO, 5, 0.0f); + table.Add("mk:fake_item_box", RANK_TWO, 5, 0.0f); + table.Add("mk:star", RANK_TWO, 5, 0.0f); + table.Add("mk:boo", RANK_TWO, 5, 0.0f); + table.Add("mk:mushroom", RANK_TWO, 5, 0.0f); + table.Add("mk:triple_mushroom",RANK_TWO, 20, 0.0f); + table.Add("mk:super_mushroom", RANK_TWO, 5, 0.0f); + + table.Add("mk:red_shell", RANK_THREE, 10, 0.0f); + table.Add("mk:triple_red_shell", RANK_THREE, 20, 0.0f); + table.Add("mk:blue_spiny_shell", RANK_THREE, 10, 0.0f); + table.Add("mk:thunderbolt", RANK_THREE, 15, 0.0f); + table.Add("mk:star", RANK_THREE, 15, 0.0f); + table.Add("mk:triple_mushroom",RANK_THREE, 20, 0.0f); + table.Add("mk:super_mushroom", RANK_THREE, 10, 0.0f); + + r.Add("mk:versus_3p", std::move(table)); +} + +void RegisterVersus4PItemTable(DataRegistry& r) { + RandomItemTable table; + + table.Add("mk:banana", RANK_ONE, 35, 0.0f); + table.Add("mk:banana_bunch", RANK_ONE, 5, 0.0f); + table.Add("mk:green_shell", RANK_ONE, 30, 0.0f); + table.Add("mk:red_shell", RANK_ONE, 5, 0.0f); + table.Add("mk:fake_item_box", RANK_ONE, 10, 0.0f); + table.Add("mk:boo", RANK_ONE, 5, 0.0f); + table.Add("mk:mushroom", RANK_ONE, 10, 0.0f); + + table.Add("mk:banana", RANK_TWO, 5, 0.0f); + table.Add("mk:banana_bunch", RANK_TWO, 5, 0.0f); + table.Add("mk:green_shell", RANK_TWO, 5, 0.0f); + table.Add("mk:triple_green_shell", RANK_TWO, 10, 0.0f); + table.Add("mk:red_shell", RANK_TWO, 15, 0.0f); + table.Add("mk:triple_red_shell", RANK_TWO, 15, 0.0f); + table.Add("mk:fake_item_box", RANK_TWO, 5, 0.0f); + table.Add("mk:star", RANK_TWO, 5, 0.0f); + table.Add("mk:boo", RANK_TWO, 5, 0.0f); + table.Add("mk:mushroom", RANK_TWO, 5, 0.0f); + table.Add("mk:triple_mushroom",RANK_TWO, 25, 0.0f); + + table.Add("mk:banana_bunch", RANK_THREE, 5, 0.0f); + table.Add("mk:triple_green_shell", RANK_THREE, 5, 0.0f); + table.Add("mk:red_shell", RANK_THREE, 10, 0.0f); + table.Add("mk:triple_red_shell", RANK_THREE, 15, 0.0f); + table.Add("mk:blue_spiny_shell", RANK_THREE, 5, 0.0f); + table.Add("mk:thunderbolt", RANK_THREE, 10, 0.0f); + table.Add("mk:fake_item_box", RANK_THREE, 5, 0.0f); + table.Add("mk:star", RANK_THREE, 10, 0.0f); + table.Add("mk:mushroom", RANK_THREE, 5, 0.0f); + table.Add("mk:triple_mushroom",RANK_THREE, 25, 0.0f); + table.Add("mk:super_mushroom", RANK_THREE, 5, 0.0f); + + table.Add("mk:triple_red_shell", RANK_FOUR, 20, 0.0f); + table.Add("mk:blue_spiny_shell", RANK_FOUR, 10, 0.0f); + table.Add("mk:thunderbolt", RANK_FOUR, 15, 0.0f); + table.Add("mk:star", RANK_FOUR, 20, 0.0f); + table.Add("mk:triple_mushroom",RANK_FOUR, 25, 0.0f); + table.Add("mk:super_mushroom", RANK_FOUR, 10, 0.0f); + + r.Add("mk:versus_4p", std::move(table)); +} + +void RegisterBattleItemTable(DataRegistry& r) { + RandomItemTable table; + + table.Add("mk:banana", RANK_ONE, 10, 0.0f); + table.Add("mk:banana_bunch", RANK_ONE, 5, 0.0f); + table.Add("mk:green_shell", RANK_ONE, 5, 0.0f); + table.Add("mk:triple_green_shell", RANK_ONE, 20, 0.0f); + table.Add("mk:red_shell", RANK_ONE, 20, 0.0f); + table.Add("mk:fake_item_box", RANK_ONE, 15, 0.0f); + table.Add("mk:star", RANK_ONE, 20, 0.0f); + table.Add("mk:boo", RANK_ONE, 5, 0.0f); + + r.Add("mk:battle", std::move(table)); +} diff --git a/src/engine/registry/RegisterItems.cpp b/src/engine/registry/RegisterItems.cpp new file mode 100644 index 000000000..bd5cd17c8 --- /dev/null +++ b/src/engine/registry/RegisterItems.cpp @@ -0,0 +1,55 @@ +#include "RegisterContent.h" +#include "Registry.h" + +//! @todo turn items into a class +void RegisterItems(Registry& r) { + ItemInfo info; + + info = { .ResourceName = "mk:none", .Name = "No Item" }; + r.Add(info, {}); + + info = { .ResourceName = "mk:banana", .Name = "Banana" }; + r.Add(info, {}); + + info = { .ResourceName = "mk:banana_bunch", .Name = "Banana Bunch" }; + r.Add(info, {}); + + info = { .ResourceName = "mk:green_shell", .Name = "Green Shell" }; + r.Add(info, {}); + + info = { .ResourceName = "mk:triple_green_shell", .Name = "Triple Green Shell" }; + r.Add(info, {}); + + info = { .ResourceName = "mk:red_shell", .Name = "Red Shell" }; + r.Add(info, {}); + + info = { .ResourceName = "mk:triple_red_shell", .Name = "Triple Red Shell" }; + r.Add(info, {}); + + info = { .ResourceName = "mk:blue_spiny_shell", .Name = "Blue Spiny Shell" }; + r.Add(info, {}); + + info = { .ResourceName = "mk:thunderbolt", .Name = "Thunderbolt" }; + r.Add(info, {}); + + info = { .ResourceName = "mk:fake_item_box", .Name = "Fake Item Box" }; + r.Add(info, {}); + + info = { .ResourceName = "mk:star", .Name = "Star" }; + r.Add(info, {}); + + info = { .ResourceName = "mk:boo", .Name = "Boo" }; + r.Add(info, {}); + + info = { .ResourceName = "mk:mushroom", .Name = "Mushroom" }; + r.Add(info, {}); + + info = { .ResourceName = "mk:double_mushroom", .Name = "Double Mushroom" }; + r.Add(info, {}); + + info = { .ResourceName = "mk:triple_mushroom", .Name = "Triple Mushroom" }; + r.Add(info, {}); + + info = { .ResourceName = "mk:super_mushroom", .Name = "Super Mushroom" }; + r.Add(info, {}); +} \ No newline at end of file diff --git a/src/engine/registry/RegisterTracks.cpp b/src/engine/registry/RegisterTracks.cpp new file mode 100644 index 000000000..7b078ed5e --- /dev/null +++ b/src/engine/registry/RegisterTracks.cpp @@ -0,0 +1,224 @@ +#include "engine/registry/RegisterContent.h" +#include + +#include "port/Game.h" +#include "engine/AllTracks.h" + +/** + * DO NOT RE-ORDER ANYTHING IN THESE FILES + * + * It will result in differing Ids + */ + +void RegisterTracks(Registry& r) { + TrackInfo info; + + info = { + .ResourceName = "mk:mario_raceway", + .Name = "mario raceway", + .DebugName = "m circuit", + .Length = "567m", + .MinimapTexture = minimap_mario_raceway, + }; + + r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); + + info = { + .ResourceName = "mk:choco_mountain", + .Name = "choco mountain", + .DebugName = "mountain", + .Length = "687m", + .MinimapTexture = minimap_choco_mountain, + }; + + r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); + + info = { + .ResourceName = "mk:bowsers_castle", + .Name = "bowser's castle", + .DebugName = "castle", + .Length = "777m", + .MinimapTexture = minimap_bowsers_castle, + }; + + r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); + + info = { + .ResourceName = "mk:banshee_boardwalk", + .Name = "banshee boardwalk", + .DebugName = "ghost", + .Length = "747m", + .MinimapTexture = minimap_banshee_boardwalk, + }; + + r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); + + info = { + .ResourceName = "mk:yoshi_valley", + .Name = "yoshi valley", + .DebugName = "maze", + .Length = "772m", + .MinimapTexture = minimap_yoshi_valley, + }; + + r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); + + info = { + .ResourceName = "mk:frappe_snowland", + .Name = "frappe snowland", + .DebugName = "snow", + .Length = "734m", + .MinimapTexture = minimap_frappe_snowland, + }; + + r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); + + info = { + .ResourceName = "mk:koopa_beach", + .Name = "koopa troopa beach", + .DebugName = "beach", + .Length = "691m", + .MinimapTexture = minimap_koopa_troopa_beach, + }; + + r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); + + info = { + .ResourceName = "mk:royal_raceway", + .Name = "royal raceway", + .DebugName = "p circuit", + .Length = "1025m", + .MinimapTexture = minimap_royal_raceway, + }; + + r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); + + info = { + .ResourceName = "mk:luigi_raceway", + .Name = "luigi raceway", + .DebugName = "l circuit", + .Length = "717m", + .MinimapTexture = minimap_luigi_raceway, + }; + + r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); + + info = { + .ResourceName = "mk:moo_moo_farm", + .Name = "moo moo farm", + .DebugName = "farm", + .Length = "527m", + .MinimapTexture = minimap_moo_moo_farm, + }; + + r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); + + info = { + .ResourceName = "mk:toads_turnpike", + .Name = "toad's turnpike", + .DebugName = "highway", + .Length = "1036m", + .MinimapTexture = minimap_toads_turnpike, + }; + + r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); + + info = { + .ResourceName = "mk:kalimari_desert", + .Name = "kalimari desert", + .DebugName = "desert", + .Length = "753m", + .MinimapTexture = minimap_kalimari_desert, + }; + + r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); + + info = { + .ResourceName = "mk:sherbet_land", + .Name = "sherbet land", + .DebugName = "sherbet", + .Length = "756m", + .MinimapTexture = minimap_sherbet_land, + }; + + r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); + + info = { + .ResourceName = "mk:rainbow_road", + .Name = "rainbow road", + .DebugName = "rainbow", + .Length = "2000m", + .MinimapTexture = minimap_rainbow_road, + }; + + r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); + + info = { + .ResourceName = "mk:wario_stadium", + .Name = "wario stadium", + .DebugName = "stadium", + .Length = "1591m", + .MinimapTexture = minimap_wario_stadium, + }; + + r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); + + info = { + .ResourceName = "mk:block_fort", + .Name = "block fort", + .DebugName = "block", + .Length = "", + .MinimapTexture = minimap_block_fort, + }; + + r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); + + info = { + .ResourceName = "mk:skyscraper", + .Name = "skyscraper", + .DebugName = "skyscraper", + .Length = "", + .MinimapTexture = minimap_skyscraper, + }; + + r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); + + info = { + .ResourceName = "mk:double_deck", + .Name = "double deck", + .DebugName = "deck", + .Length = "", + .MinimapTexture = minimap_double_deck, + }; + + r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); + + info = { + .ResourceName = "mk:dk_jungle", + .Name = "d.k.'s jungle parkway", + .DebugName = "jungle", + .Length = "893m", + .MinimapTexture = minimap_dks_jungle_parkway, + }; + + r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); + + info = { + .ResourceName = "mk:big_donut", + .Name = "big donut", + .DebugName = "doughnut", + .Length = "", + .MinimapTexture = minimap_big_donut, + }; + + r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); + + info = { + .ResourceName = "hm:test_track", + .Name = "test track", + .DebugName = "test track", + .Length = "100m", + }; + + r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique()); }); +} diff --git a/src/engine/Registry.h b/src/engine/registry/Registry.h similarity index 94% rename from src/engine/Registry.h rename to src/engine/registry/Registry.h index 7b4af0f2b..86b352894 100644 --- a/src/engine/Registry.h +++ b/src/engine/registry/Registry.h @@ -7,7 +7,7 @@ #include struct TrackInfo { - int32_t Id; + uint32_t Id; std::string Path; // Path to the custom track std::string ResourceName; std::string Name; @@ -18,12 +18,18 @@ struct TrackInfo { }; struct ActorInfo { - int32_t Id; + uint32_t Id; std::string ResourceName; std::string Name; std::set Tags; // Category for filtering }; +struct ItemInfo { + uint32_t Id; + std::string ResourceName; + std::string Name; +}; + /** * TInfo must have a ResourceName member of type std::string * This should be a unique string such as hm:cloud or hm:harbour @@ -88,6 +94,10 @@ public: return mMap.find(resourceName) != mMap.end(); } + size_t Size() { + return mMap.size(); + } + std::vector GetAllInfo() const { std::vector list; list.reserve(mMap.size()); diff --git a/src/engine/tracks/Track.cpp b/src/engine/tracks/Track.cpp index 29215b4a6..d2ca6e3c4 100644 --- a/src/engine/tracks/Track.cpp +++ b/src/engine/tracks/Track.cpp @@ -8,7 +8,7 @@ #include "ChocoMountain.h" #include "port/Game.h" #include "engine/editor/SceneManager.h" -#include "Registry.h" +#include "engine/registry/Registry.h" #include "libultraship/bridge/resourcebridge.h" #include "align_asset_macro.h" diff --git a/src/engine/vehicles/Boat.h b/src/engine/vehicles/Boat.h index 80e818da4..0be119504 100644 --- a/src/engine/vehicles/Boat.h +++ b/src/engine/vehicles/Boat.h @@ -3,7 +3,7 @@ #include #include "Actor.h" #include -#include "RegisterContent.h" +#include "engine/registry/RegisterContent.h" #include "engine/SpawnParams.h" #include "engine/CoreMath.h" #include "engine/World.h" diff --git a/src/engine/vehicles/Bus.h b/src/engine/vehicles/Bus.h index f29b87c4a..efcbe224a 100644 --- a/src/engine/vehicles/Bus.h +++ b/src/engine/vehicles/Bus.h @@ -3,7 +3,7 @@ #include #include "Actor.h" #include -#include "RegisterContent.h" +#include "engine/registry/RegisterContent.h" #include "engine/SpawnParams.h" extern "C" { diff --git a/src/engine/vehicles/Car.h b/src/engine/vehicles/Car.h index c1a23385f..993506aa6 100644 --- a/src/engine/vehicles/Car.h +++ b/src/engine/vehicles/Car.h @@ -3,7 +3,7 @@ #include #include "Actor.h" #include -#include "RegisterContent.h" +#include "engine/registry/RegisterContent.h" #include "engine/SpawnParams.h" extern "C" { diff --git a/src/engine/vehicles/TankerTruck.h b/src/engine/vehicles/TankerTruck.h index eeedd11ae..8f3a44511 100644 --- a/src/engine/vehicles/TankerTruck.h +++ b/src/engine/vehicles/TankerTruck.h @@ -3,7 +3,7 @@ #include #include "Actor.h" #include -#include "RegisterContent.h" +#include "engine/registry/RegisterContent.h" #include "engine/SpawnParams.h" extern "C" { diff --git a/src/engine/vehicles/Train.h b/src/engine/vehicles/Train.h index a451f940a..be1d00bdc 100644 --- a/src/engine/vehicles/Train.h +++ b/src/engine/vehicles/Train.h @@ -2,7 +2,7 @@ #include #include -#include "RegisterContent.h" +#include "engine/registry/RegisterContent.h" #include "engine/SpawnParams.h" #include "engine/CoreMath.h" #include "engine/World.h" diff --git a/src/engine/vehicles/Truck.h b/src/engine/vehicles/Truck.h index 6780e35f5..bf567e240 100644 --- a/src/engine/vehicles/Truck.h +++ b/src/engine/vehicles/Truck.h @@ -3,7 +3,7 @@ #include #include "Actor.h" #include -#include "RegisterContent.h" +#include "engine/registry/RegisterContent.h" #include "engine/SpawnParams.h" extern "C" { diff --git a/src/port/Game.cpp b/src/port/Game.cpp index 9f96182d4..8f50da220 100644 --- a/src/port/Game.cpp +++ b/src/port/Game.cpp @@ -23,7 +23,7 @@ #include "engine/editor/Editor.h" #include "engine/editor/SceneManager.h" -#include "RegisterContent.h" +#include "engine/registry/RegisterContent.h" #include "engine/cameras/GameCamera.h" #include "engine/cameras/FreeCamera.h" @@ -31,6 +31,7 @@ #include "engine/cameras/LookBehindCamera.h" #include "engine/TrackBrowser.h" +#include "engine/RandomItemTable.h" #ifdef _WIN32 #include @@ -73,8 +74,13 @@ TrackEditor::Editor gEditor; s32 gTrophyIndex = NULL; +/** Spawner Registries **/ Registry gTrackRegistry; Registry gActorRegistry; +Registry gItemRegistry; + +/** Data Registries **/ +DataRegistry gItemTableRegistry; std::unique_ptr gTrackBrowser; @@ -138,7 +144,11 @@ void CustomEngineInit() { SetMarioRaceway(); + printf("[Game] Registering Game Content...\n"); RegisterActors(gActorRegistry); + RegisterItems(gItemRegistry); + RegisterItemTables(gItemTableRegistry); + printf("[Game] Game Content Registered!\n"); } void CustomEngineDestroy() { diff --git a/src/port/Game.h b/src/port/Game.h index d1f6ec3df..dbf2a7cea 100644 --- a/src/port/Game.h +++ b/src/port/Game.h @@ -7,7 +7,8 @@ #ifdef __cplusplus #include "engine/editor/Editor.h" -#include "engine/Registry.h" +#include "engine/registry/Registry.h" +#include "engine/registry/DataRegistry.h" class Track; struct Properties; class World; @@ -30,6 +31,8 @@ extern HarbourMastersIntro gMenuIntro; extern bool bCleanWorld; extern Registry gTrackRegistry; extern Registry gActorRegistry; +extern Registry gItemRegistry; +extern DataRegistry gItemTableRegistry; World* GetWorld(void); // Retrieve the world instance #endif // NOLINTBEGIN(readability-identifier-naming) diff --git a/src/port/ui/TrackProperties.cpp b/src/port/ui/TrackProperties.cpp index d3ef44ad4..18a2c4655 100644 --- a/src/port/ui/TrackProperties.cpp +++ b/src/port/ui/TrackProperties.cpp @@ -16,7 +16,7 @@ #include "engine/cameras/TourCamera.h" #include "engine/TrackBrowser.h" #include "engine/editor/SceneManager.h" -#include "engine/Registry.h" +#include "engine/registry/Registry.h" extern "C" { #include "code_800029B0.h" diff --git a/src/update_objects.c b/src/update_objects.c index 94867102f..75e1671de 100644 --- a/src/update_objects.c +++ b/src/update_objects.c @@ -44,6 +44,8 @@ #include #include +#include "engine/RaceManager.h" + float OTRGetAspectRatio(void); //! @todo unused? @@ -2609,719 +2611,11 @@ void consume_item(s32 playerId) { } } -typedef struct { - u8 none; // ITEM_NONE - u8 banana; // ITEM_BANANA - u8 bananaBunch; // ITEM_BANANA_BUNCH - u8 greenShell; // ITEM_GREEN_SHELL - u8 tripleGreenShell; // ITEM_TRIPLE_GREEN_SHELL - u8 redShell; // ITEM_RED_SHELL - u8 tripleRedShell; // ITEM_TRIPLE_RED_SHELL - u8 blueSpinyShell; // ITEM_BLUE_SPINY_SHELL - u8 thunderbolt; // ITEM_THUNDERBOLT - u8 fakeItemBox; // ITEM_FAKE_ITEM_BOX - u8 star; // ITEM_STAR - u8 boo; // ITEM_BOO - u8 mushroom; // ITEM_MUSHROOM - u8 doubleMushroom; // ITEM_DOUBLE_MUSHROOM - u8 tripleMushroom; // ITEM_TRIPLE_MUSHROOM - u8 superMushroom; // ITEM_SUPER_MUSHROOM -} ItemProbabilities; - -// Each row corresponds to a rank, each column to an item -ItemProbabilities grandPrixHumanProbabilityTable[] = { - { .none = 0, - .banana = 30, - .bananaBunch = 5, - .greenShell = 30, - .tripleGreenShell = 5, - .redShell = 5, - .tripleRedShell = 0, - .blueSpinyShell = 0, - .thunderbolt = 0, - .fakeItemBox = 10, - .star = 0, - .boo = 5, - .mushroom = 10, - .doubleMushroom = 0, - .tripleMushroom = 0, - .superMushroom = 0 }, - { .none = 0, - .banana = 0, - .bananaBunch = 5, - .greenShell = 5, - .tripleGreenShell = 10, - .redShell = 15, - .tripleRedShell = 20, - .blueSpinyShell = 0, - .thunderbolt = 5, - .fakeItemBox = 5, - .star = 5, - .boo = 5, - .mushroom = 5, - .doubleMushroom = 0, - .tripleMushroom = 15, - .superMushroom = 5 }, - { .none = 0, - .banana = 0, - .bananaBunch = 0, - .greenShell = 0, - .tripleGreenShell = 10, - .redShell = 20, - .tripleRedShell = 20, - .blueSpinyShell = 0, - .thunderbolt = 5, - .fakeItemBox = 0, - .star = 10, - .boo = 0, - .mushroom = 5, - .doubleMushroom = 0, - .tripleMushroom = 20, - .superMushroom = 10 }, - { .none = 0, - .banana = 0, - .bananaBunch = 0, - .greenShell = 0, - .tripleGreenShell = 0, - .redShell = 15, - .tripleRedShell = 20, - .blueSpinyShell = 5, - .thunderbolt = 10, - .fakeItemBox = 0, - .star = 15, - .boo = 0, - .mushroom = 5, - .doubleMushroom = 0, - .tripleMushroom = 20, - .superMushroom = 10 }, - { .none = 0, - .banana = 0, - .bananaBunch = 0, - .greenShell = 0, - .tripleGreenShell = 0, - .redShell = 10, - .tripleRedShell = 20, - .blueSpinyShell = 5, - .thunderbolt = 10, - .fakeItemBox = 0, - .star = 15, - .boo = 0, - .mushroom = 5, - .doubleMushroom = 0, - .tripleMushroom = 25, - .superMushroom = 10 }, - { .none = 0, - .banana = 0, - .bananaBunch = 0, - .greenShell = 0, - .tripleGreenShell = 0, - .redShell = 0, - .tripleRedShell = 20, - .blueSpinyShell = 10, - .thunderbolt = 15, - .fakeItemBox = 0, - .star = 20, - .boo = 0, - .mushroom = 0, - .doubleMushroom = 0, - .tripleMushroom = 25, - .superMushroom = 10 }, - { .none = 0, - .banana = 0, - .bananaBunch = 0, - .greenShell = 0, - .tripleGreenShell = 0, - .redShell = 0, - .tripleRedShell = 20, - .blueSpinyShell = 10, - .thunderbolt = 20, - .fakeItemBox = 0, - .star = 30, - .boo = 0, - .mushroom = 0, - .doubleMushroom = 0, - .tripleMushroom = 10, - .superMushroom = 10 }, - { .none = 0, - .banana = 0, - .bananaBunch = 0, - .greenShell = 0, - .tripleGreenShell = 0, - .redShell = 0, - .tripleRedShell = 20, - .blueSpinyShell = 15, - .thunderbolt = 20, - .fakeItemBox = 0, - .star = 30, - .boo = 0, - .mushroom = 0, - .doubleMushroom = 0, - .tripleMushroom = 5, - .superMushroom = 10 }, -}; - -ItemProbabilities grandPrixCPUProbabilityTable[] = { - { .none = 0, - .banana = 60, - .bananaBunch = 0, - .greenShell = 25, - .tripleGreenShell = 0, - .redShell = 0, - .tripleRedShell = 0, - .blueSpinyShell = 0, - .thunderbolt = 0, - .fakeItemBox = 10, - .star = 0, - .boo = 5, - .mushroom = 0, - .doubleMushroom = 0, - .tripleMushroom = 0, - .superMushroom = 0 }, - { .none = 0, - .banana = 50, - .bananaBunch = 0, - .greenShell = 25, - .tripleGreenShell = 5, - .redShell = 0, - .tripleRedShell = 0, - .blueSpinyShell = 0, - .thunderbolt = 0, - .fakeItemBox = 10, - .star = 0, - .boo = 5, - .mushroom = 5, - .doubleMushroom = 0, - .tripleMushroom = 0, - .superMushroom = 0 }, - { .none = 0, - .banana = 40, - .bananaBunch = 0, - .greenShell = 25, - .tripleGreenShell = 10, - .redShell = 0, - .tripleRedShell = 0, - .blueSpinyShell = 0, - .thunderbolt = 0, - .fakeItemBox = 10, - .star = 0, - .boo = 5, - .mushroom = 10, - .doubleMushroom = 0, - .tripleMushroom = 0, - .superMushroom = 0 }, - { .none = 0, - .banana = 35, - .bananaBunch = 0, - .greenShell = 25, - .tripleGreenShell = 15, - .redShell = 0, - .tripleRedShell = 0, - .blueSpinyShell = 0, - .thunderbolt = 0, - .fakeItemBox = 10, - .star = 0, - .boo = 5, - .mushroom = 10, - .doubleMushroom = 0, - .tripleMushroom = 0, - .superMushroom = 0 }, - { .none = 0, - .banana = 30, - .bananaBunch = 0, - .greenShell = 20, - .tripleGreenShell = 20, - .redShell = 0, - .tripleRedShell = 0, - .blueSpinyShell = 0, - .thunderbolt = 0, - .fakeItemBox = 5, - .star = 5, - .boo = 0, - .mushroom = 20, - .doubleMushroom = 0, - .tripleMushroom = 0, - .superMushroom = 0 }, - { .none = 0, - .banana = 30, - .bananaBunch = 0, - .greenShell = 20, - .tripleGreenShell = 20, - .redShell = 0, - .tripleRedShell = 0, - .blueSpinyShell = 0, - .thunderbolt = 0, - .fakeItemBox = 5, - .star = 5, - .boo = 0, - .mushroom = 20, - .doubleMushroom = 0, - .tripleMushroom = 0, - .superMushroom = 0 }, - { .none = 0, - .banana = 30, - .bananaBunch = 0, - .greenShell = 20, - .tripleGreenShell = 20, - .redShell = 0, - .tripleRedShell = 0, - .blueSpinyShell = 0, - .thunderbolt = 0, - .fakeItemBox = 0, - .star = 10, - .boo = 0, - .mushroom = 20, - .doubleMushroom = 0, - .tripleMushroom = 0, - .superMushroom = 0 }, - { .none = 0, - .banana = 25, - .bananaBunch = 0, - .greenShell = 20, - .tripleGreenShell = 20, - .redShell = 0, - .tripleRedShell = 0, - .blueSpinyShell = 0, - .thunderbolt = 1, - .fakeItemBox = 0, - .star = 10, - .boo = 0, - .mushroom = 24, - .doubleMushroom = 0, - .tripleMushroom = 0, - .superMushroom = 0 }, -}; - -ItemProbabilities grandPrixHardCPUProbabilityTable[] = { - { .none = 5, - .banana = 25, - .bananaBunch = 5, - .greenShell = 30, - .tripleGreenShell = 5, - .redShell = 5, - .tripleRedShell = 0, - .blueSpinyShell = 0, - .thunderbolt = 0, - .fakeItemBox = 10, - .star = 0, - .boo = 5, - .mushroom = 10, - .doubleMushroom = 0, - .tripleMushroom = 0, - .superMushroom = 0 }, - { .none = 0, - .banana = 5, - .bananaBunch = 5, - .greenShell = 5, - .tripleGreenShell = 10, - .redShell = 15, - .tripleRedShell = 20, - .blueSpinyShell = 0, - .thunderbolt = 0, - .fakeItemBox = 5, - .star = 5, - .boo = 5, - .mushroom = 5, - .doubleMushroom = 0, - .tripleMushroom = 15, - .superMushroom = 5 }, - { .none = 0, - .banana = 5, - .bananaBunch = 3, - .greenShell = 0, - .tripleGreenShell = 10, - .redShell = 20, - .tripleRedShell = 19, - .blueSpinyShell = 0, - .thunderbolt = 0, - .fakeItemBox = 0, - .star = 10, - .boo = 0, - .mushroom = 5, - .doubleMushroom = 0, - .tripleMushroom = 19, - .superMushroom = 9 }, - { .none = 0, - .banana = 5, - .bananaBunch = 0, - .greenShell = 5, - .tripleGreenShell = 5, - .redShell = 15, - .tripleRedShell = 10, - .blueSpinyShell = 0, - .thunderbolt = 0, - .fakeItemBox = 5, - .star = 15, - .boo = 5, - .mushroom = 5, - .doubleMushroom = 0, - .tripleMushroom = 20, - .superMushroom = 10 }, - { .none = 0, - .banana = 0, - .bananaBunch = 0, - .greenShell = 0, - .tripleGreenShell = 0, - .redShell = 10, - .tripleRedShell = 20, - .blueSpinyShell = 5, - .thunderbolt = 0, - .fakeItemBox = 5, - .star = 15, - .boo = 0, - .mushroom = 10, - .doubleMushroom = 0, - .tripleMushroom = 25, - .superMushroom = 10 }, - { .none = 0, - .banana = 0, - .bananaBunch = 0, - .greenShell = 0, - .tripleGreenShell = 0, - .redShell = 5, - .tripleRedShell = 25, - .blueSpinyShell = 10, - .thunderbolt = 0, - .fakeItemBox = 0, - .star = 20, - .boo = 0, - .mushroom = 5, - .doubleMushroom = 0, - .tripleMushroom = 25, - .superMushroom = 10 }, - { .none = 0, - .banana = 0, - .bananaBunch = 0, - .greenShell = 5, - .tripleGreenShell = 0, - .redShell = 5, - .tripleRedShell = 25, - .blueSpinyShell = 10, - .thunderbolt = 0, - .fakeItemBox = 0, - .star = 30, - .boo = 0, - .mushroom = 5, - .doubleMushroom = 0, - .tripleMushroom = 10, - .superMushroom = 10 }, - { .none = 0, - .banana = 0, - .bananaBunch = 0, - .greenShell = 0, - .tripleGreenShell = 5, - .redShell = 5, - .tripleRedShell = 20, - .blueSpinyShell = 15, - .thunderbolt = 10, - .fakeItemBox = 0, - .star = 30, - .boo = 0, - .mushroom = 0, - .doubleMushroom = 0, - .tripleMushroom = 5, - .superMushroom = 10 }, -}; - -ItemProbabilities versus2PlayerProbabilityTable[] = { - { .none = 0, - .banana = 25, - .bananaBunch = 10, - .greenShell = 30, - .tripleGreenShell = 5, - .redShell = 5, - .tripleRedShell = 0, - .blueSpinyShell = 0, - .thunderbolt = 0, - .fakeItemBox = 10, - .star = 0, - .boo = 5, - .mushroom = 10, - .doubleMushroom = 0, - .tripleMushroom = 0, - .superMushroom = 0 }, - { .none = 0, - .banana = 0, - .bananaBunch = 5, - .greenShell = 0, - .tripleGreenShell = 5, - .redShell = 5, - .tripleRedShell = 15, - .blueSpinyShell = 5, - .thunderbolt = 15, - .fakeItemBox = 0, - .star = 15, - .boo = 0, - .mushroom = 0, - .doubleMushroom = 0, - .tripleMushroom = 15, - .superMushroom = 20 }, -}; - -ItemProbabilities versus3PlayerProbabilityTable[] = { - { .none = 0, - .banana = 35, - .bananaBunch = 5, - .greenShell = 30, - .tripleGreenShell = 0, - .redShell = 5, - .tripleRedShell = 0, - .blueSpinyShell = 0, - .thunderbolt = 0, - .fakeItemBox = 10, - .star = 0, - .boo = 5, - .mushroom = 10, - .doubleMushroom = 0, - .tripleMushroom = 0, - .superMushroom = 0 }, - { .none = 0, - .banana = 5, - .bananaBunch = 5, - .greenShell = 0, - .tripleGreenShell = 10, - .redShell = 15, - .tripleRedShell = 15, - .blueSpinyShell = 0, - .thunderbolt = 5, - .fakeItemBox = 5, - .star = 5, - .boo = 5, - .mushroom = 5, - .doubleMushroom = 0, - .tripleMushroom = 20, - .superMushroom = 5 }, - { .none = 0, - .banana = 0, - .bananaBunch = 0, - .greenShell = 0, - .tripleGreenShell = 0, - .redShell = 10, - .tripleRedShell = 20, - .blueSpinyShell = 10, - .thunderbolt = 15, - .fakeItemBox = 0, - .star = 15, - .boo = 0, - .mushroom = 0, - .doubleMushroom = 0, - .tripleMushroom = 20, - .superMushroom = 10 }, -}; - -ItemProbabilities versus4PlayerProbabilityTable[] = { - { .none = 0, - .banana = 35, - .bananaBunch = 5, - .greenShell = 30, - .tripleGreenShell = 0, - .redShell = 5, - .tripleRedShell = 0, - .blueSpinyShell = 0, - .thunderbolt = 0, - .fakeItemBox = 10, - .star = 0, - .boo = 5, - .mushroom = 10, - .doubleMushroom = 0, - .tripleMushroom = 0, - .superMushroom = 0 }, - { .none = 0, - .banana = 5, - .bananaBunch = 5, - .greenShell = 5, - .tripleGreenShell = 10, - .redShell = 15, - .tripleRedShell = 15, - .blueSpinyShell = 0, - .thunderbolt = 0, - .fakeItemBox = 5, - .star = 5, - .boo = 5, - .mushroom = 5, - .doubleMushroom = 0, - .tripleMushroom = 25, - .superMushroom = 0 }, - { .none = 0, - .banana = 0, - .bananaBunch = 5, - .greenShell = 0, - .tripleGreenShell = 5, - .redShell = 10, - .tripleRedShell = 15, - .blueSpinyShell = 5, - .thunderbolt = 10, - .fakeItemBox = 5, - .star = 10, - .boo = 0, - .mushroom = 5, - .doubleMushroom = 0, - .tripleMushroom = 25, - .superMushroom = 5 }, - { .none = 0, - .banana = 0, - .bananaBunch = 0, - .greenShell = 0, - .tripleGreenShell = 0, - .redShell = 0, - .tripleRedShell = 20, - .blueSpinyShell = 10, - .thunderbolt = 15, - .fakeItemBox = 0, - .star = 20, - .boo = 0, - .mushroom = 0, - .doubleMushroom = 0, - .tripleMushroom = 25, - .superMushroom = 10 }, -}; - -ItemProbabilities battleProbabilityCurve[] = { { .none = 0, - .banana = 10, - .bananaBunch = 5, - .greenShell = 5, - .tripleGreenShell = 20, - .redShell = 20, - .tripleRedShell = 0, - .blueSpinyShell = 0, - .thunderbolt = 0, - .fakeItemBox = 15, - .star = 20, - .boo = 5, - .mushroom = 0, - .doubleMushroom = 0, - .tripleMushroom = 0, - .superMushroom = 0 } }; - -void getProbabilityArray(const ItemProbabilities* probStruct, u8* probArray) { - probArray[ITEM_NONE] = probStruct->none; - probArray[ITEM_BANANA] = probStruct->banana; - probArray[ITEM_BANANA_BUNCH] = probStruct->bananaBunch; - probArray[ITEM_GREEN_SHELL] = probStruct->greenShell; - probArray[ITEM_TRIPLE_GREEN_SHELL] = probStruct->tripleGreenShell; - probArray[ITEM_RED_SHELL] = probStruct->redShell; - probArray[ITEM_TRIPLE_RED_SHELL] = probStruct->tripleRedShell; - probArray[ITEM_BLUE_SPINY_SHELL] = probStruct->blueSpinyShell; - probArray[ITEM_THUNDERBOLT] = probStruct->thunderbolt; - probArray[ITEM_FAKE_ITEM_BOX] = probStruct->fakeItemBox; - probArray[ITEM_STAR] = probStruct->star; - probArray[ITEM_BOO] = probStruct->boo; - probArray[ITEM_MUSHROOM] = probStruct->mushroom; - probArray[ITEM_DOUBLE_MUSHROOM] = probStruct->doubleMushroom; - probArray[ITEM_TRIPLE_MUSHROOM] = probStruct->tripleMushroom; - probArray[ITEM_SUPER_MUSHROOM] = probStruct->superMushroom; -} - -// Output a warning if a probability table does not add up to 100 -void verify_probability_table(char* str, const ItemProbabilities* probs, int16_t rank) { -#ifndef _DEBUG - return; -#endif - u8 itemProbabilities[ITEM_MAX]; - - getProbabilityArray(probs, itemProbabilities); - size_t count = 0; - for (size_t i = 0; i < ITEM_MAX; i++) { - // printf("prob %d ", itemProbabilities[i]); - count += itemProbabilities[i]; - } - // printf("\n"); - - if (count != 100) { - printf("update_objects.c::verify_probability_table\n %s table for rank %d is imba %d/100\n", str, rank, count); - } -} - -enum RandomItemOption { - HUMAN_TABLE, - CPU_TABLE, - HARD_CPU_TABLE, -}; - -/** - * New random item system uses chance based on percent - * Likely functionally equivallent to the old system but easier to modify - */ -u8 gen_random_item(s16 rank, s16 option) { -#define PERCENTAGE_BASE 100 - u16 rand = random_int(PERCENTAGE_BASE); -#undef PERCENTAGE_BASE - ItemProbabilities* distributionTable; - u8 randomItem = 0; - u8 cumulativeProbability = 0; - - switch (gModeSelection) { - case GRAND_PRIX: - switch (option) { - case HUMAN_TABLE: - distributionTable = &grandPrixHumanProbabilityTable[rank]; - verify_probability_table("Human", distributionTable, rank); - break; - case CPU_TABLE: - distributionTable = &grandPrixCPUProbabilityTable[rank]; - verify_probability_table("CPU", distributionTable, rank); - break; - case HARD_CPU_TABLE: - distributionTable = &grandPrixHardCPUProbabilityTable[rank]; - verify_probability_table("Hard CPU", distributionTable, rank); - break; - } - break; - case VERSUS: - switch (gPlayerCountSelection1) { - case TWO_PLAYERS_SELECTED: - distributionTable = &versus2PlayerProbabilityTable[rank]; - verify_probability_table("Versus 2P", distributionTable, rank); - break; - case THREE_PLAYERS_SELECTED: - distributionTable = &versus3PlayerProbabilityTable[rank]; - verify_probability_table("Versus 3P", distributionTable, rank); - break; - case FOUR_PLAYERS_SELECTED: - distributionTable = &versus4PlayerProbabilityTable[rank]; - verify_probability_table("Versus 4P", distributionTable, rank); - break; - } - break; - case BATTLE: - distributionTable = &battleProbabilityCurve[0]; - verify_probability_table("Battle", distributionTable, rank); - break; - } - - u8 itemProbabilities[ITEM_MAX]; - getProbabilityArray(distributionTable, itemProbabilities); - - for (size_t i = 0; i < ITEM_MAX; i++) { - cumulativeProbability += itemProbabilities[i]; - if (rand < cumulativeProbability) { - randomItem = i; - break; - } - } - return randomItem; -} - -u8 gen_random_item_human(UNUSED s16 arg0, s16 rank) { - if (CVarGetInteger("gHarderCPU", 0) == true) { - return gen_random_item(rank, HARD_CPU_TABLE); - } else { - return gen_random_item(rank, HUMAN_TABLE); - } -} - -u8 cpu_gen_random_item(UNUSED s32 arg0, s16 rank) { - return gen_random_item(rank, CPU_TABLE); -} - -u8 hard_cpu_gen_random_item(UNUSED s32 arg0, s16 rank) { - return gen_random_item(rank, HARD_CPU_TABLE); -} - s16 func_8007AFB0(s32 objectIndex, s32 playerId) { UNUSED s32 pad[3]; s16 randomItem; - randomItem = gen_random_item_human(gLapCountByPlayerId[playerId], gGPCurrentRaceRankByPlayerId[playerId]); + randomItem = RaceManager_GetRandomHumanItem(gGPCurrentRaceRankByPlayerId[playerId]); if (randomItem == ITEM_NONE) { play_sound2(SOUND_MENU_FILE_NOT_FOUND); @@ -3355,11 +2649,11 @@ s32 func_8007B040(s32 objectIndex, s32 playerId) { if (gModeSelection == GRAND_PRIX) { // Boo item if (random_int(0x0064U) < 0x51) { - item = gen_random_item_human(gLapCountByPlayerId[playerId], gGPCurrentRaceRankByPlayerId[playerId]); + item = RaceManager_GetRandomHumanItem(gGPCurrentRaceRankByPlayerId[playerId]); // ITEM_NONE is not a valid item for ghost, randomize again size_t attempts = 0; while (item == ITEM_NONE && attempts < 200) { - item = gen_random_item_human(gLapCountByPlayerId[playerId], gGPCurrentRaceRankByPlayerId[playerId]); + item = RaceManager_GetRandomHumanItem(gGPCurrentRaceRankByPlayerId[playerId]); attempts++; } if (attempts >= 200) { diff --git a/src/update_objects.h b/src/update_objects.h index 66cd2ea6e..228d40bf2 100644 --- a/src/update_objects.h +++ b/src/update_objects.h @@ -198,10 +198,6 @@ void update_object_lakitu(s32); void func_8007AA44(s32); void func_8007ABFC(s32, s32); void consume_item(s32); -u8 gen_random_item(s16, s16); -u8 gen_random_item_human(s16, s16); -u8 cpu_gen_random_item(s32, s16); -u8 hard_cpu_gen_random_item(UNUSED s32 arg0, s16 rank); s16 func_8007AFB0(s32, s32); s32 func_8007B040(s32, s32); void func_8007B254(s32, s32);