summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMegaMech <MegaMech@users.noreply.github.com>2025-12-18 11:24:38 -0700
committerGitHub <noreply@github.com>2025-12-18 11:24:38 -0700
commitf0c2cea0eec6c49a335e9c044fcc28218e1ab749 (patch)
tree422128eeb081feffca8ad3ac87566a35358e077f /src
parent99b56300556434580ed23edc27e5e7d982751e47 (diff)
Impl RandomItemTable class (#598)
* Impl RandomItem class * Refactor func * Impl RandomItemTable * Revert probability inaccuracy * Remove unnecessary comment * Fix compile, probably * As per review 1 --------- Co-authored-by: MegaMech <7255464+MegaMech@users.noreply.github.com>
Diffstat (limited to 'src')
-rw-r--r--src/code_80005FD0.c6
-rw-r--r--src/engine/RaceManager.cpp67
-rw-r--r--src/engine/RaceManager.h19
-rw-r--r--src/engine/RandomItemTable.cpp104
-rw-r--r--src/engine/RandomItemTable.h33
-rw-r--r--src/engine/actors/Cloud.h2
-rw-r--r--src/engine/actors/FallingRock.h2
-rw-r--r--src/engine/actors/Finishline.h2
-rw-r--r--src/engine/actors/MarioSign.h2
-rw-r--r--src/engine/actors/Ship.h2
-rw-r--r--src/engine/actors/SpaghettiShip.h2
-rw-r--r--src/engine/actors/Starship.h2
-rw-r--r--src/engine/actors/Text.h2
-rw-r--r--src/engine/actors/WarioSign.h2
-rw-r--r--src/engine/editor/Editor.h8
-rw-r--r--src/engine/editor/SceneManager.cpp7
-rw-r--r--src/engine/objects/Bat.h2
-rw-r--r--src/engine/objects/BombKart.h2
-rw-r--r--src/engine/objects/Boos.h2
-rw-r--r--src/engine/objects/CheepCheep.h2
-rw-r--r--src/engine/objects/Crab.h2
-rw-r--r--src/engine/objects/Flagpole.h2
-rw-r--r--src/engine/objects/GrandPrixBalloons.h2
-rw-r--r--src/engine/objects/Hedgehog.h2
-rw-r--r--src/engine/objects/HotAirBalloon.h2
-rw-r--r--src/engine/objects/Penguin.h2
-rw-r--r--src/engine/objects/Podium.h2
-rw-r--r--src/engine/objects/Seagull.h2
-rw-r--r--src/engine/objects/Snowman.h2
-rw-r--r--src/engine/objects/Thwomp.h2
-rw-r--r--src/engine/objects/TrashBin.h2
-rw-r--r--src/engine/objects/Trophy.h2
-rw-r--r--src/engine/registry/DataRegistry.h44
-rw-r--r--src/engine/registry/RegisterActors.cpp (renamed from src/engine/RegisterContent.cpp)235
-rw-r--r--src/engine/registry/RegisterContent.h (renamed from src/engine/RegisterContent.h)13
-rw-r--r--src/engine/registry/RegisterItemTables.cpp379
-rw-r--r--src/engine/registry/RegisterItems.cpp55
-rw-r--r--src/engine/registry/RegisterTracks.cpp224
-rw-r--r--src/engine/registry/Registry.h (renamed from src/engine/Registry.h)14
-rw-r--r--src/engine/tracks/Track.cpp2
-rw-r--r--src/engine/vehicles/Boat.h2
-rw-r--r--src/engine/vehicles/Bus.h2
-rw-r--r--src/engine/vehicles/Car.h2
-rw-r--r--src/engine/vehicles/TankerTruck.h2
-rw-r--r--src/engine/vehicles/Train.h2
-rw-r--r--src/engine/vehicles/Truck.h2
-rw-r--r--src/port/Game.cpp12
-rw-r--r--src/port/Game.h5
-rw-r--r--src/port/ui/TrackProperties.cpp2
-rw-r--r--src/update_objects.c716
-rw-r--r--src/update_objects.h4
51 files changed, 1008 insertions, 1003 deletions
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 <libultraship/libultra/gbi.h>
@@ -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<std::string, RandomItemTable> 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<ItemEntry>& 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<uint8_t>(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 <libultraship/libultraship.h>
+#include <utility>
+
+/**
+ * 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<std::vector<ItemEntry>> mTable;
+ std::unordered_set<uint32_t> 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 <libultraship.h>
-#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 <libultraship.h>
-#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 <libultraship.h>
#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 <libultraship.h>
#include <libultra/gbi.h>
#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 <libultraship.h>
#include <libultra/gbi.h>
#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 <libultraship.h>
#include <libultra/gbi.h>
#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 <libultraship.h>
-#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 <libultraship.h>
-#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 <libultraship/libultraship.h>
#include <libultra/gbi.h>
+#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<Ship::Archive> 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 <vector>
#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 <libultraship.h>
-#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 <vector>
#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 <libultraship.h>
#include <vector>
#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 <libultraship.h>
#include <vector>
-#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 <vector>
#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 <libultraship.h>
-#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 <vector>
#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 <libultraship.h>
#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 <libultraship.h>
-#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 <libultraship.h>
-#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 <libultraship.h>
#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 <libultraship.h>
#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 <libultraship.h>
-#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 <libultraship.h>
#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 <libultraship.h>
#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 <string>
+#include <unordered_map>
+#include <memory>
+#include <cstdint>
+
+template<typename TObject>
+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<TObject>(std::forward<TObject>(object));
+ }
+
+ void Add(const std::string& resourceName, const TObject& object) {
+ mMap[resourceName] = std::make_unique<TObject>(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<std::string, std::unique_ptr<TObject>> mMap;
+};
diff --git a/src/engine/RegisterContent.cpp b/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<ActorInfo, const SpawnParams&>& r) {
ActorInfo info;
@@ -290,216 +276,3 @@ void RegisterActors(Registry<ActorInfo, const SpawnParams&>& r) {
info = { .ResourceName = "mk:bowser_statue", .Name = "Bowser Statue" };
r.Add(info, AddActorToWorld<ABowserStatue>);
}
-
-void RegisterTracks(Registry<TrackInfo>& 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<MarioRaceway>()); });
-
- info = {
- .ResourceName = "mk:choco_mountain",
- .Name = "choco mountain",
- .DebugName = "mountain",
- .Length = "687m",
- .MinimapTexture = minimap_choco_mountain,
- };
-
- r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<ChocoMountain>()); });
-
- 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<BowsersCastle>()); });
-
- info = {
- .ResourceName = "mk:banshee_boardwalk",
- .Name = "banshee boardwalk",
- .DebugName = "ghost",
- .Length = "747m",
- .MinimapTexture = minimap_banshee_boardwalk,
- };
-
- r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<BansheeBoardwalk>()); });
-
- info = {
- .ResourceName = "mk:yoshi_valley",
- .Name = "yoshi valley",
- .DebugName = "maze",
- .Length = "772m",
- .MinimapTexture = minimap_yoshi_valley,
- };
-
- r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<YoshiValley>()); });
-
- info = {
- .ResourceName = "mk:frappe_snowland",
- .Name = "frappe snowland",
- .DebugName = "snow",
- .Length = "734m",
- .MinimapTexture = minimap_frappe_snowland,
- };
-
- r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<FrappeSnowland>()); });
-
- 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<KoopaTroopaBeach>()); });
-
- 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<RoyalRaceway>()); });
-
- 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<LuigiRaceway>()); });
-
- 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<MooMooFarm>()); });
-
- 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<ToadsTurnpike>()); });
-
- info = {
- .ResourceName = "mk:kalimari_desert",
- .Name = "kalimari desert",
- .DebugName = "desert",
- .Length = "753m",
- .MinimapTexture = minimap_kalimari_desert,
- };
-
- r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<KalimariDesert>()); });
-
- info = {
- .ResourceName = "mk:sherbet_land",
- .Name = "sherbet land",
- .DebugName = "sherbet",
- .Length = "756m",
- .MinimapTexture = minimap_sherbet_land,
- };
-
- r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<SherbetLand>()); });
-
- info = {
- .ResourceName = "mk:rainbow_road",
- .Name = "rainbow road",
- .DebugName = "rainbow",
- .Length = "2000m",
- .MinimapTexture = minimap_rainbow_road,
- };
-
- r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<RainbowRoad>()); });
-
- info = {
- .ResourceName = "mk:wario_stadium",
- .Name = "wario stadium",
- .DebugName = "stadium",
- .Length = "1591m",
- .MinimapTexture = minimap_wario_stadium,
- };
-
- r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<WarioStadium>()); });
-
- info = {
- .ResourceName = "mk:block_fort",
- .Name = "block fort",
- .DebugName = "block",
- .Length = "",
- .MinimapTexture = minimap_block_fort,
- };
-
- r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<BlockFort>()); });
-
- info = {
- .ResourceName = "mk:skyscraper",
- .Name = "skyscraper",
- .DebugName = "skyscraper",
- .Length = "",
- .MinimapTexture = minimap_skyscraper,
- };
-
- r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<Skyscraper>()); });
-
- info = {
- .ResourceName = "mk:double_deck",
- .Name = "double deck",
- .DebugName = "deck",
- .Length = "",
- .MinimapTexture = minimap_double_deck,
- };
-
- r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<DoubleDeck>()); });
-
- 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<DKJungle>()); });
-
- info = {
- .ResourceName = "mk:big_donut",
- .Name = "big donut",
- .DebugName = "doughnut",
- .Length = "",
- .MinimapTexture = minimap_big_donut,
- };
-
- r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<BigDonut>()); });
-
- info = {
- .ResourceName = "hm:test_track",
- .Name = "test track",
- .DebugName = "test track",
- .Length = "100m",
- };
-
- r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<TestTrack>()); });
-}
diff --git a/src/engine/RegisterContent.h b/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 <memory>
+#include "DataRegistry.h"
+#include "src/port/Game.h"
+#include "engine/objects/Object.h"
+#include "engine/Actor.h"
+#include "engine/SpawnParams.h"
template<class T> static OObject* AddObjectToWorld(const SpawnParams& params) {
return GetWorld()->AddObject(std::make_unique<T>(params));
@@ -14,5 +15,7 @@ template<class T> static AActor* AddActorToWorld(const SpawnParams& params) {
return GetWorld()->AddActor(std::make_unique<T>(params));
}
-void RegisterActors(Registry<ActorInfo, const SpawnParams&>& r);
void RegisterTracks(Registry<TrackInfo>& r);
+void RegisterActors(Registry<ActorInfo, const SpawnParams&>& r);
+void RegisterItems(Registry<ItemInfo>& r);
+void RegisterItemTables(DataRegistry<RandomItemTable>& 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 <utility>
+#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<RandomItemTable>& r);
+void RegisterCPUItemTable(DataRegistry<RandomItemTable>& r);
+void RegisterHardCPUItemTable(DataRegistry<RandomItemTable>& r);
+void RegisterVersus2PItemTable(DataRegistry<RandomItemTable>& r);
+void RegisterVersus3PItemTable(DataRegistry<RandomItemTable>& r);
+void RegisterVersus4PItemTable(DataRegistry<RandomItemTable>& r);
+void RegisterBattleItemTable(DataRegistry<RandomItemTable>& r);
+
+void RegisterItemTables(DataRegistry<RandomItemTable>& r) {
+ RegisterHumanItemTable(r);
+ RegisterCPUItemTable(r);
+ RegisterHardCPUItemTable(r);
+ RegisterVersus2PItemTable(r);
+ RegisterVersus3PItemTable(r);
+ RegisterVersus4PItemTable(r);
+ RegisterBattleItemTable(r);
+}
+
+void RegisterHumanItemTable(DataRegistry<RandomItemTable>& 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<RandomItemTable>& 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<RandomItemTable>& 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<RandomItemTable>& 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<RandomItemTable>& 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<RandomItemTable>& 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<RandomItemTable>& 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<ItemInfo>& 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 <memory>
+
+#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<TrackInfo>& 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<MarioRaceway>()); });
+
+ info = {
+ .ResourceName = "mk:choco_mountain",
+ .Name = "choco mountain",
+ .DebugName = "mountain",
+ .Length = "687m",
+ .MinimapTexture = minimap_choco_mountain,
+ };
+
+ r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<ChocoMountain>()); });
+
+ 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<BowsersCastle>()); });
+
+ info = {
+ .ResourceName = "mk:banshee_boardwalk",
+ .Name = "banshee boardwalk",
+ .DebugName = "ghost",
+ .Length = "747m",
+ .MinimapTexture = minimap_banshee_boardwalk,
+ };
+
+ r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<BansheeBoardwalk>()); });
+
+ info = {
+ .ResourceName = "mk:yoshi_valley",
+ .Name = "yoshi valley",
+ .DebugName = "maze",
+ .Length = "772m",
+ .MinimapTexture = minimap_yoshi_valley,
+ };
+
+ r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<YoshiValley>()); });
+
+ info = {
+ .ResourceName = "mk:frappe_snowland",
+ .Name = "frappe snowland",
+ .DebugName = "snow",
+ .Length = "734m",
+ .MinimapTexture = minimap_frappe_snowland,
+ };
+
+ r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<FrappeSnowland>()); });
+
+ 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<KoopaTroopaBeach>()); });
+
+ 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<RoyalRaceway>()); });
+
+ 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<LuigiRaceway>()); });
+
+ 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<MooMooFarm>()); });
+
+ 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<ToadsTurnpike>()); });
+
+ info = {
+ .ResourceName = "mk:kalimari_desert",
+ .Name = "kalimari desert",
+ .DebugName = "desert",
+ .Length = "753m",
+ .MinimapTexture = minimap_kalimari_desert,
+ };
+
+ r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<KalimariDesert>()); });
+
+ info = {
+ .ResourceName = "mk:sherbet_land",
+ .Name = "sherbet land",
+ .DebugName = "sherbet",
+ .Length = "756m",
+ .MinimapTexture = minimap_sherbet_land,
+ };
+
+ r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<SherbetLand>()); });
+
+ info = {
+ .ResourceName = "mk:rainbow_road",
+ .Name = "rainbow road",
+ .DebugName = "rainbow",
+ .Length = "2000m",
+ .MinimapTexture = minimap_rainbow_road,
+ };
+
+ r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<RainbowRoad>()); });
+
+ info = {
+ .ResourceName = "mk:wario_stadium",
+ .Name = "wario stadium",
+ .DebugName = "stadium",
+ .Length = "1591m",
+ .MinimapTexture = minimap_wario_stadium,
+ };
+
+ r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<WarioStadium>()); });
+
+ info = {
+ .ResourceName = "mk:block_fort",
+ .Name = "block fort",
+ .DebugName = "block",
+ .Length = "",
+ .MinimapTexture = minimap_block_fort,
+ };
+
+ r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<BlockFort>()); });
+
+ info = {
+ .ResourceName = "mk:skyscraper",
+ .Name = "skyscraper",
+ .DebugName = "skyscraper",
+ .Length = "",
+ .MinimapTexture = minimap_skyscraper,
+ };
+
+ r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<Skyscraper>()); });
+
+ info = {
+ .ResourceName = "mk:double_deck",
+ .Name = "double deck",
+ .DebugName = "deck",
+ .Length = "",
+ .MinimapTexture = minimap_double_deck,
+ };
+
+ r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<DoubleDeck>()); });
+
+ 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<DKJungle>()); });
+
+ info = {
+ .ResourceName = "mk:big_donut",
+ .Name = "big donut",
+ .DebugName = "doughnut",
+ .Length = "",
+ .MinimapTexture = minimap_big_donut,
+ };
+
+ r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<BigDonut>()); });
+
+ info = {
+ .ResourceName = "hm:test_track",
+ .Name = "test track",
+ .DebugName = "test track",
+ .Length = "100m",
+ };
+
+ r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<TestTrack>()); });
+}
diff --git a/src/engine/Registry.h b/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 <set>
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<std::string> 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<const TInfo*> GetAllInfo() const {
std::vector<const TInfo*> 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 <libultraship.h>
#include "Actor.h"
#include <vector>
-#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 <libultraship.h>
#include "Actor.h"
#include <vector>
-#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 <libultraship.h>
#include "Actor.h"
#include <vector>
-#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 <libultraship.h>
#include "Actor.h"
#include <vector>
-#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 <libultraship.h>
#include <vector>
-#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 <libultraship.h>
#include "Actor.h"
#include <vector>
-#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 <locale.h>
@@ -73,8 +74,13 @@ TrackEditor::Editor gEditor;
s32 gTrophyIndex = NULL;
+/** Spawner Registries **/
Registry<TrackInfo> gTrackRegistry;
Registry<ActorInfo, const SpawnParams&> gActorRegistry;
+Registry<ItemInfo> gItemRegistry;
+
+/** Data Registries **/
+DataRegistry<RandomItemTable> gItemTableRegistry;
std::unique_ptr<TrackBrowser> 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<TrackInfo> gTrackRegistry;
extern Registry<ActorInfo, const SpawnParams&> gActorRegistry;
+extern Registry<ItemInfo> gItemRegistry;
+extern DataRegistry<RandomItemTable> 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 <assets/textures/tracks/sherbet_land/sherbet_land_data.h>
#include <assets/textures/tracks/rainbow_road/rainbow_road_data.h>
+#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);