diff options
| author | MegaMech <MegaMech@users.noreply.github.com> | 2025-12-18 11:24:38 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-12-18 11:24:38 -0700 |
| commit | f0c2cea0eec6c49a335e9c044fcc28218e1ab749 (patch) | |
| tree | 422128eeb081feffca8ad3ac87566a35358e077f /src/update_objects.c | |
| parent | 99b56300556434580ed23edc27e5e7d982751e47 (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/update_objects.c')
| -rw-r--r-- | src/update_objects.c | 716 |
1 files changed, 5 insertions, 711 deletions
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) { |
