Add in Progressive Bombchu Bags (#5836)

* Adds new Progressive Bombchu Bags option

Also changes existing code to account for Bombchu Bags becoming
a drop down with 3 values instead of a checkbox

* Handle the new lower capacities for ammo refills

* Handle what happens when receiving a bombchu bag

* Remove the trick name of Progressive Bombchu Bag

Since, you know, that's an actual thing now.

* Implements Bombchu Bag handling next to Progressive Bombchu Handling

* clang-formatting

* Add extra bag for plentiful items

* Address review comment

* Move bombchu upgrade level to gSaveContext and add save/load

* Use logic's saveContext for correct logic calculations

* Remove RG_PROGRESSIVE_BOMBCHU

* Fix Bombchu Refill obtainability

* Don't add normal chus to the pool if chu bags are on.

* cmake-format

* Properly reset bombchuUpgradeLevel on savefile init

* Fix error with va_arg on linux

* Fixes small error in the Bombchu Bag description

* Fix bug with bombchu obtainability

* clang-format

* Fix infinite bombchu text

* fix clang-format
This commit is contained in:
Christopher Leggett
2025-12-04 15:14:32 +00:00
committed by GitHub
parent 098cb70460
commit 7e829a0780
28 changed files with 260 additions and 81 deletions

View File

@@ -164,6 +164,7 @@ typedef struct {
typedef struct ShipRandomizerSaveContextData {
u8 triforcePiecesCollected;
u8 bombchuUpgradeLevel;
} ShipRandomizerSaveContextData;
typedef struct ShipBossRushSaveContextData {

View File

@@ -2336,6 +2336,28 @@ typedef enum {
// #### `result`
// ```c
// false
// ```
// #### `args`
// - *EnGirlACanBuyResult
VB_CAN_BUY_BOMBCHUS,
// #### `result`
// ```c
// true
// ```
// #### `args`
// - None
VB_CHECK_BOMBCHU_CAPACITY,
// #### `result`
// ```c
// false
// ```
// #### `args`
// - int16_t
VB_COLOR_AMMO_GREEN,
// (this->collider.base.acFlags & AC_HIT) && !Player_InCsMode(play) &&
// (player->meleeWeaponAnimation == 22 || player->meleeWeaponAnimation == 23)
// ```

View File

@@ -316,7 +316,7 @@ std::vector<RandomizerCheck> GetAllEmptyLocations() {
}
bool IsBombchus(RandomizerGet item, bool includeShops = false) {
return (item >= RG_BOMBCHU_5 && item <= RG_BOMBCHU_20) || item == RG_PROGRESSIVE_BOMBCHUS ||
return (item >= RG_BOMBCHU_5 && item <= RG_BOMBCHU_20) || item == RG_PROGRESSIVE_BOMBCHU_BAG ||
(includeShops && (item == RG_BUY_BOMBCHUS_10 || item == RG_BUY_BOMBCHUS_20));
}

View File

@@ -408,7 +408,7 @@ static void PlaceItemsForType(RandomizerCheckType rctype, bool overworldActive,
}
static void SetScarceItemPool() {
ReplaceMaxItem(RG_PROGRESSIVE_BOMBCHUS, 3);
ReplaceMaxItem(RG_PROGRESSIVE_BOMBCHU_BAG, ctx->GetOption(RSK_BOMBCHU_BAG).Is(RO_BOMBCHU_BAG_SINGLE) ? 3 : 2);
ReplaceMaxItem(RG_BOMBCHU_5, 1);
ReplaceMaxItem(RG_BOMBCHU_10, 2);
ReplaceMaxItem(RG_BOMBCHU_20, 0);
@@ -424,7 +424,7 @@ static void SetScarceItemPool() {
static void SetMinimalItemPool() {
auto ctx = Rando::Context::GetInstance();
ReplaceMaxItem(RG_PROGRESSIVE_BOMBCHUS, 1);
ReplaceMaxItem(RG_PROGRESSIVE_BOMBCHU_BAG, 1);
ReplaceMaxItem(RG_BOMBCHU_5, 1);
ReplaceMaxItem(RG_BOMBCHU_10, 0);
ReplaceMaxItem(RG_BOMBCHU_20, 0);
@@ -653,6 +653,9 @@ void GenerateItemPool() {
AddItemToMainPool(RG_PROGRESSIVE_STICK_UPGRADE);
AddItemToMainPool(RG_PROGRESSIVE_MAGIC_METER);
AddItemToMainPool(RG_PROGRESSIVE_WALLET);
if (ctx->GetOption(RSK_BOMBCHU_BAG).Is(RO_BOMBCHU_BAG_PROGRESSIVE)) {
AddItemToMainPool(RG_PROGRESSIVE_BOMBCHU_BAG);
}
}
if (ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_BEANS_ONLY) ||
@@ -671,9 +674,9 @@ void GenerateItemPool() {
if (/*!ProgressiveGoronSword TODO: Implement Progressive Goron Sword*/ true) {
AddItemToMainPool(RG_GIANTS_KNIFE);
}
if (ctx->GetOption(RSK_BOMBCHU_BAG)) {
AddItemToMainPool(RG_PROGRESSIVE_BOMBCHUS);
} else {
if (ctx->GetOption(RSK_BOMBCHU_BAG).Is(RO_BOMBCHU_BAG_SINGLE)) {
AddItemToMainPool(RG_PROGRESSIVE_BOMBCHU_BAG);
} else if (ctx->GetOption(RSK_BOMBCHU_BAG).Is(RO_BOMBCHU_BAG_NONE)) {
AddItemToMainPool(RG_BOMBCHU_10);
}
} else {
@@ -785,8 +788,13 @@ void GenerateItemPool() {
AddItemToMainPool(RG_PROGRESSIVE_NUT_UPGRADE);
}
if (ctx->GetOption(RSK_BOMBCHU_BAG)) {
AddItemToMainPool(RG_PROGRESSIVE_BOMBCHUS, 5);
if (ctx->GetOption(RSK_BOMBCHU_BAG).Is(RO_BOMBCHU_BAG_SINGLE)) {
AddItemToMainPool(RG_PROGRESSIVE_BOMBCHU_BAG, 5);
} else if (ctx->GetOption(RSK_BOMBCHU_BAG).Is(RO_BOMBCHU_BAG_PROGRESSIVE)) {
AddItemToMainPool(RG_PROGRESSIVE_BOMBCHU_BAG, 3);
if (ctx->GetOption(RSK_ITEM_POOL).Is(RO_ITEM_POOL_PLENTIFUL)) {
AddItemToPool(PendingJunkPool, RG_PROGRESSIVE_BOMBCHU_BAG);
}
} else {
AddItemToMainPool(RG_BOMBCHU_5);
AddItemToMainPool(RG_BOMBCHU_10, 3);

View File

@@ -563,14 +563,12 @@ void InitTrickNames() {
Text{ "Progressive Rod Capacity", "Capacité de tiges (prog.)",
"Stock-Kapazität (prog.)" }, // "Mayor capacidad de cetros deku"
};
trickNameTable[RG_PROGRESSIVE_BOMBCHUS] = {
trickNameTable[RG_PROGRESSIVE_BOMBCHU_BAG] = {
Text{ "Progressive Bomblings", "Bombinsectes (prog.)", "Bombenmäuse (prog.)€" }, // "Bombinsectos progresivos"
Text{ "Progressive Sentrobe Bombs", "Bombe de Sphérodrone (prog.)",
"Rokopterbomben (prog.)€" }, // "Bomba de helicobot progresivo"
Text{ "Progressive Bomb-ombs", "Bombe Soldat (prog.)", "Bob-omb (prog.)" }, // "Soldado bomba progresivo"
Text{ "Progressive Missiles", "Missiles (prog.)", "Missiles (prog.)€" }, // "Misiles progresivos"
Text{ "Progressive Bombchu Bag", "Sac à Bombchu (prog.)",
"Krabbelminenbeutel (prog.)" }, // "Bombachus progresivos"
};
trickNameTable[RG_PROGRESSIVE_MAGIC_METER] = {
Text{ "Progressive Stamina Meter", "Jauge d'endurance (prog.)",

View File

@@ -73,8 +73,8 @@ void GenerateStartingInventory() {
// AddItemToInventory(RG_PROGRESSIVE_STICK_UPGRADE, StartingStickCapacity.Value<uint8_t>());
// AddItemToInventory(RG_PROGRESSIVE_NUT_UPGRADE, StartingNutCapacity.Value<uint8_t>());
// AddItemToInventory(RG_PROGRESSIVE_BOMB_BAG, StartingBombBag.Value<uint8_t>());
// AddItemToInventory((BombchuBag ? RG_PROGRESSIVE_BOMBCHUS : RG_BOMBCHU_20), StartingBombchus.Value<uint8_t>());
// AddItemToInventory(RG_PROGRESSIVE_BOW, StartingBow.Value<uint8_t>());
// AddItemToInventory((BombchuBag ? RG_PROGRESSIVE_BOMBCHU_BAG : RG_BOMBCHU_20),
// StartingBombchus.Value<uint8_t>()); AddItemToInventory(RG_PROGRESSIVE_BOW, StartingBow.Value<uint8_t>());
// AddItemToInventory(RG_FIRE_ARROWS, StartingFireArrows.Value<uint8_t>());
// AddItemToInventory(RG_ICE_ARROWS, StartingIceArrows.Value<uint8_t>());
// AddItemToInventory(RG_LIGHT_ARROWS, StartingLightArrows.Value<uint8_t>());

View File

@@ -0,0 +1,51 @@
#include <soh/OTRGlobals.h>
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/ShipInit.hpp"
#include "src/overlays/actors/ovl_En_GirlA/z_en_girla.h"
extern "C" {
#include "z64save.h"
}
void RegisterVBOverrides() {
bool shouldRegister = IS_RANDO && RAND_GET_OPTION(RSK_BOMBCHU_BAG) == RO_BOMBCHU_BAG_PROGRESSIVE;
COND_VB_SHOULD(VB_CAN_BUY_BOMBCHUS, IS_RANDO, {
EnGirlACanBuyResult* canBuy = va_arg(args, EnGirlACanBuyResult*);
u8 bombchuBag = RAND_GET_OPTION(RSK_BOMBCHU_BAG);
// When in rando, don't allow buying bombchus when the player doesn't have required explosives
// If bombchus are in logic, the player needs to have bombchus; otherwise they need a bomb bag
if ((!bombchuBag && CUR_CAPACITY(UPG_BOMB_BAG) == 0) ||
(bombchuBag && INV_CONTENT(ITEM_BOMBCHU) == ITEM_NONE)) {
*canBuy = CANBUY_RESULT_CANT_GET_NOW;
*should = true;
}
int8_t capacity = 50;
if (bombchuBag == RO_BOMBCHU_BAG_PROGRESSIVE) {
capacity = OTRGlobals::Instance->gRandoContext->GetBombchuCapacity();
}
if (AMMO(ITEM_BOMBCHU) >= capacity) {
*canBuy = CANBUY_RESULT_CANT_GET_NOW;
*should = true;
}
});
COND_VB_SHOULD(VB_CHECK_BOMBCHU_CAPACITY, shouldRegister, {
*should = false;
uint8_t capacity = OTRGlobals::Instance->gRandoContext->GetBombchuCapacity();
if (AMMO(ITEM_BOMBCHU) > capacity) {
AMMO(ITEM_BOMBCHU) = capacity;
}
});
COND_VB_SHOULD(VB_COLOR_AMMO_GREEN, shouldRegister, {
int16_t i = va_arg(args, int);
if (i == ITEM_BOMBCHU) {
uint8_t capacity = OTRGlobals::Instance->gRandoContext->GetBombchuCapacity();
if (AMMO(i) == capacity) {
*should = true;
}
}
});
}
static RegisterShipInitFunc initHooks(RegisterVBOverrides, { "IS_RANDO" });

View File

@@ -135,7 +135,7 @@ std::unordered_map<RandomizerGet, std::string> itemImageMap = {
{ RG_PROGRESSIVE_SCALE, "ITEM_SCALE_SILVER" },
{ RG_PROGRESSIVE_NUT_UPGRADE, "ITEM_NUT" },
{ RG_PROGRESSIVE_STICK_UPGRADE, "ITEM_STICK" },
{ RG_PROGRESSIVE_BOMBCHUS, "ITEM_BOMBCHU" },
{ RG_PROGRESSIVE_BOMBCHU_BAG, "ITEM_BOMBCHU" },
{ RG_PROGRESSIVE_MAGIC_METER, "ITEM_MAGIC_SMALL" },
{ RG_MAGIC_SINGLE, "ITEM_MAGIC_SMALL" },
{ RG_MAGIC_DOUBLE, "ITEM_MAGIC_LARGE" },

View File

@@ -44,7 +44,7 @@ extern "C" void ObjKibako2_RandomizerDraw(Actor* thisx, PlayState* play) {
// If they have bombchus, don't consider the bombchu item major
if (INV_CONTENT(ITEM_BOMBCHU) == ITEM_BOMBCHU &&
((crateItem.modIndex == MOD_RANDOMIZER && crateItem.getItemId == RG_PROGRESSIVE_BOMBCHUS) ||
((crateItem.modIndex == MOD_RANDOMIZER && crateItem.getItemId == RG_PROGRESSIVE_BOMBCHU_BAG) ||
(crateItem.modIndex == MOD_NONE &&
(crateItem.getItemId == GI_BOMBCHUS_5 || crateItem.getItemId == GI_BOMBCHUS_10 ||
crateItem.getItemId == GI_BOMBCHUS_20)))) {
@@ -118,7 +118,7 @@ extern "C" void ObjKibako_RandomizerDraw(Actor* thisx, PlayState* play) {
// If they have bombchus, don't consider the bombchu item major
if (INV_CONTENT(ITEM_BOMBCHU) == ITEM_BOMBCHU &&
((smallCrateItem.modIndex == MOD_RANDOMIZER && smallCrateItem.getItemId == RG_PROGRESSIVE_BOMBCHUS) ||
((smallCrateItem.modIndex == MOD_RANDOMIZER && smallCrateItem.getItemId == RG_PROGRESSIVE_BOMBCHU_BAG) ||
(smallCrateItem.modIndex == MOD_NONE &&
(smallCrateItem.getItemId == GI_BOMBCHUS_5 || smallCrateItem.getItemId == GI_BOMBCHUS_10 ||
smallCrateItem.getItemId == GI_BOMBCHUS_20)))) {

View File

@@ -69,7 +69,7 @@ extern "C" void EnWood02_RandomizerDraw(Actor* thisx, PlayState* play) {
// If they have bombchus, don't consider the bombchu item major
if (INV_CONTENT(ITEM_BOMBCHU) == ITEM_BOMBCHU &&
((smallCrateItem.modIndex == MOD_RANDOMIZER && smallCrateItem.getItemId == RG_PROGRESSIVE_BOMBCHUS) ||
((smallCrateItem.modIndex == MOD_RANDOMIZER && smallCrateItem.getItemId == RG_PROGRESSIVE_BOMBCHU_BAG) ||
(smallCrateItem.modIndex == MOD_NONE &&
(smallCrateItem.getItemId == GI_BOMBCHUS_5 || smallCrateItem.getItemId == GI_BOMBCHUS_10 ||
smallCrateItem.getItemId == GI_BOMBCHUS_20)))) {

View File

@@ -16,6 +16,9 @@
#include <fstream>
#include <spdlog/spdlog.h>
extern "C" {
#include <functions.h>
}
namespace Rando {
std::weak_ptr<Context> Context::mContext;
@@ -551,6 +554,56 @@ void Context::SetHash(std::string hash) {
mHash = std::move(hash);
}
uint8_t Context::GetBombchuCapacity() {
switch (mLogic->GetSaveContext()->ship.quest.data.randomizer.bombchuUpgradeLevel) {
case 0:
return 0;
case 1:
return 20;
case 2:
return 30;
case 3:
return 50;
default:
return 0;
}
}
void Context::HandleGetBombchuBag() {
if (GetOption(RSK_BOMBCHU_BAG).Is(RO_BOMBCHU_BAG_SINGLE)) {
if (INV_CONTENT(ITEM_BOMBCHU) == ITEM_NONE) {
INV_CONTENT(ITEM_BOMBCHU) = ITEM_BOMBCHU;
AMMO(ITEM_BOMBCHU) = 20;
} else if (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_INFINITE_UPGRADES)) {
Flags_SetRandomizerInf(RAND_INF_HAS_INFINITE_BOMBCHUS);
} else {
AMMO(ITEM_BOMBCHU) += 10;
if (AMMO(ITEM_BOMBCHU) > 50) {
AMMO(ITEM_BOMBCHU) = 50;
}
}
return;
}
switch (mLogic->GetSaveContext()->ship.quest.data.randomizer.bombchuUpgradeLevel) {
case 0:
case 1:
case 2:
mLogic->GetSaveContext()->ship.quest.data.randomizer.bombchuUpgradeLevel++;
if (INV_CONTENT(ITEM_BOMBCHU) == ITEM_NONE) {
INV_CONTENT(ITEM_BOMBCHU) = ITEM_BOMBCHU;
} else if (GetOption(RSK_INFINITE_UPGRADES).Is(RO_INF_UPGRADES_CONDENSED_PROGRESSIVE)) {
Flags_SetRandomizerInf(RAND_INF_HAS_INFINITE_BOMBCHUS);
}
AMMO(ITEM_BOMBCHU) = GetBombchuCapacity();
return;
case 3:
if (GetOption(RSK_INFINITE_UPGRADES).IsNot(RO_INF_UPGRADES_OFF)) {
Flags_SetRandomizerInf(RAND_INF_HAS_INFINITE_BOMBCHUS);
}
return;
}
}
const std::string& Context::GetSeedString() const {
return mSeedString;
}

View File

@@ -174,6 +174,8 @@ class Context {
* @param hash
*/
void SetHash(std::string hash);
uint8_t GetBombchuCapacity();
void HandleGetBombchuBag();
private:
static std::weak_ptr<Context> mContext;

View File

@@ -1196,7 +1196,7 @@ extern "C" void Randomizer_DrawBombchuBag(PlayState* play, GetItemEntry* getItem
}
extern "C" void Randomizer_DrawBombchuBagInLogic(PlayState* play, GetItemEntry* getItemEntry) {
if (IS_RANDO && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_BOMBCHU_BAG)) {
if (IS_RANDO && OTRGlobals::Instance->gRandoContext->GetOption(RSK_BOMBCHU_BAG).IsNot(RO_BOMBCHU_BAG_NONE)) {
Randomizer_DrawBombchuBag(play, getItemEntry);
} else {
OPEN_DISPS(play->state.gfxCtx);

View File

@@ -1183,7 +1183,8 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l
break;
}
case VB_GIVE_BOMBCHUS_FROM_CARPET_SALESMAN: {
*should = RAND_GET_OPTION(RSK_BOMBCHU_BAG) == false || INV_CONTENT(ITEM_BOMBCHU) == ITEM_BOMBCHU;
*should =
RAND_GET_OPTION(RSK_BOMBCHU_BAG) == RO_BOMBCHU_BAG_NONE || INV_CONTENT(ITEM_BOMBCHU) == ITEM_BOMBCHU;
break;
}
case VB_CHECK_RANDO_PRICE_OF_MEDIGORON: {

View File

@@ -93,7 +93,7 @@ uint16_t Item::GetPrice() const {
}
std::shared_ptr<GetItemEntry> Item::GetGIEntry() const { // NOLINT(*-no-recursion)
if (giEntry != nullptr) {
if (giEntry != nullptr && giEntry->itemId != RG_PROGRESSIVE_BOMBCHU_BAG) {
return giEntry;
}
std::shared_ptr<Rando::Context> ctx = Rando::Context::GetInstance();
@@ -355,19 +355,34 @@ std::shared_ptr<GetItemEntry> Item::GetGIEntry() const { // NOLINT(*-no-recursio
case RG_PROGRESSIVE_GORONSWORD: // todo progressive?
actual = RG_BIGGORON_SWORD;
break;
case RG_PROGRESSIVE_BOMBCHUS:
if (logic->CurrentInventory(ITEM_BOMBCHU) == ITEM_NONE) {
actual = RG_BOMBCHU_BAG;
} else if (infiniteUpgrades != RO_INF_UPGRADES_OFF) {
actual = RG_BOMBCHU_INF;
} else {
actual = RG_BOMBCHU_10;
case RG_PROGRESSIVE_BOMBCHU_BAG:
if (OTRGlobals::Instance->gRandoContext->GetOption(RSK_BOMBCHU_BAG).Is(RO_BOMBCHU_BAG_SINGLE)) {
if (logic->CurrentInventory(ITEM_BOMBCHU) != ITEM_NONE) {
if (infiniteUpgrades != RO_INF_UPGRADES_OFF) {
actual = RG_BOMBCHU_INF;
} else {
actual = RG_BOMBCHU_10;
}
}
} else if (OTRGlobals::Instance->gRandoContext->GetOption(RSK_BOMBCHU_BAG).Is(RO_BOMBCHU_BAG_PROGRESSIVE)) {
if (logic->CurrentInventory(ITEM_BOMBCHU) != ITEM_NONE) {
if (infiniteUpgrades == RO_INF_UPGRADES_CONDENSED_PROGRESSIVE) {
actual = RG_BOMBCHU_INF;
} else if (infiniteUpgrades == RO_INF_UPGRADES_PROGRESSIVE) {
if (logic->GetSaveContext()->ship.quest.data.randomizer.bombchuUpgradeLevel >= 3) {
actual = RG_BOMBCHU_INF;
}
}
}
}
break;
default:
actual = RG_NONE;
break;
}
if (giEntry != nullptr && actual == RG_NONE) {
return giEntry;
}
return StaticData::RetrieveItem(actual).GetGIEntry();
}
@@ -414,7 +429,7 @@ bool Item::IsMajorItem() const {
}
if ((randomizerGet == RG_BOMBCHU_5 || randomizerGet == RG_BOMBCHU_10 || randomizerGet == RG_BOMBCHU_20) &&
!ctx->GetOption(RSK_BOMBCHU_BAG)) {
ctx->GetOption(RSK_BOMBCHU_BAG).Is(RO_BOMBCHU_BAG_NONE)) {
return false;
}

View File

@@ -68,7 +68,6 @@ void Rando::StaticData::InitItemTable() {
itemTable[RG_PROGRESSIVE_SCALE] = Item(RG_PROGRESSIVE_SCALE, Text{ "Progressive Scale", "Écaille (prog.)", "Zora-Schuppe (prog.)" }, ITEMTYPE_ITEM, 0x86, true, LOGIC_PROGRESSIVE_SCALE, RHT_PROGRESSIVE_SCALE, ITEM_CATEGORY_MAJOR, true);
itemTable[RG_PROGRESSIVE_NUT_UPGRADE] = Item(RG_PROGRESSIVE_NUT_UPGRADE, Text{ "Progressive Nut Capacity", "Capacité de Noix (prog.)", "Nuß-Kapazität (prog.)" }, ITEMTYPE_ITEM, 0x87, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_PROGRESSIVE_NUT_UPGRADE, ITEM_CATEGORY_MAJOR, true);
itemTable[RG_PROGRESSIVE_STICK_UPGRADE] = Item(RG_PROGRESSIVE_STICK_UPGRADE, Text{ "Progressive Stick Capacity", "Capacité de Bâtons (prog.)", "Stab-Kapazität (prog.)" }, ITEMTYPE_ITEM, 0x88, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_PROGRESSIVE_STICK_UPGRADE, ITEM_CATEGORY_MAJOR, true);
itemTable[RG_PROGRESSIVE_BOMBCHUS] = Item(RG_PROGRESSIVE_BOMBCHUS, Text{ "Progressive Bombchu", "Missiles (prog.)", "Krabbelminen (prog.)" }, ITEMTYPE_ITEM, 0x89, true, LOGIC_BOMBCHUS, RHT_PROGRESSIVE_BOMBCHUS, ITEM_CATEGORY_MAJOR, true);
itemTable[RG_PROGRESSIVE_MAGIC_METER] = Item(RG_PROGRESSIVE_MAGIC_METER, Text{ "Progressive Magic Meter", "Jauge de Magie (prog.)", "Magische Kraft (prog.)" }, ITEMTYPE_ITEM, 0x8A, true, LOGIC_PROGRESSIVE_MAGIC, RHT_PROGRESSIVE_MAGIC_METER, ITEM_CATEGORY_MAJOR, true);
itemTable[RG_PROGRESSIVE_OCARINA] = Item(RG_PROGRESSIVE_OCARINA, Text{ "Progressive Ocarina", "Ocarina (prog.)", "Okarina (prog.)" }, ITEMTYPE_ITEM, 0x8B, true, LOGIC_PROGRESSIVE_OCARINA, RHT_PROGRESSIVE_OCARINA, ITEM_CATEGORY_MAJOR, true);
itemTable[RG_PROGRESSIVE_GORONSWORD] = Item(RG_PROGRESSIVE_GORONSWORD, Text{ "Progressive Goron Sword", "Épée Goron (prog.)", "Goronen-Schwert (prog.)" }, ITEMTYPE_ITEM, 0xD4, true, LOGIC_PROGRESSIVE_GIANT_KNIFE, RHT_PROGRESSIVE_GORONSWORD, ITEM_CATEGORY_MAJOR, true);
@@ -352,8 +351,8 @@ void Rando::StaticData::InitItemTable() {
itemTable[RG_BRONZE_SCALE] = Item(RG_BRONZE_SCALE, Text{ "Bronze Scale", "Écaille de Bronze", "Bronzene Schuppe" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_PROGRESSIVE_WALLET, RHT_BRONZE_SCALE, RG_BRONZE_SCALE, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_BRONZE_SCALE].SetCustomDrawFunc(Randomizer_DrawBronzeScale);
itemTable[RG_BOMBCHU_BAG] = Item(RG_BOMBCHU_BAG, Text{ "Bombchu Bag", "Sac de Missiles Teigneux", "Krabbelminentasche" }, ITEMTYPE_ITEM, RG_BOMBCHU_BAG, true, LOGIC_BOMBCHUS, RHT_BOMBCHU_BAG, RG_BOMBCHU_BAG, OBJECT_GI_BOMB_2, GID_BOMBCHU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_BOMBCHU_BAG].SetCustomDrawFunc(Randomizer_DrawBombchuBag);
itemTable[RG_PROGRESSIVE_BOMBCHU_BAG] = Item(RG_PROGRESSIVE_BOMBCHU_BAG, Text{ "Bombchu Bag", "Sac de Missiles Teigneux", "Krabbelminentasche" }, ITEMTYPE_ITEM, RG_PROGRESSIVE_BOMBCHU_BAG, true, LOGIC_BOMBCHUS, RHT_BOMBCHU_BAG, RG_PROGRESSIVE_BOMBCHU_BAG, OBJECT_GI_BOMB_2, GID_BOMBCHU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_PROGRESSIVE_BOMBCHU_BAG].SetCustomDrawFunc(Randomizer_DrawBombchuBag);
itemTable[RG_QUIVER_INF] = Item(RG_QUIVER_INF, Text{ "Infinite Quiver", "Carquois Infini", "Unendlicher Köcher" }, ITEMTYPE_ITEM, RG_QUIVER_INF, true, LOGIC_PROGRESSIVE_BOW, RHT_QUIVER_INF, RG_QUIVER_INF, OBJECT_GI_ARROWCASE, GID_QUIVER_50, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
itemTable[RG_BOMB_BAG_INF] = Item(RG_BOMB_BAG_INF, Text{ "Infinite Bomb Bag", "Sac de Bombes Infini", "Unendliche Bombentasche" }, ITEMTYPE_ITEM, RG_BOMB_BAG_INF, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_BOMB_BAG_INF, RG_BOMB_BAG_INF, OBJECT_GI_BOMBPOUCH, GID_BOMB_BAG_40, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);

View File

@@ -52,7 +52,7 @@ bool Logic::HasItem(RandomizerGet itemName) {
return CheckInventory(ITEM_ARROW_ICE, true);
case RG_LIGHT_ARROWS:
return CheckInventory(ITEM_ARROW_LIGHT, true);
case RG_PROGRESSIVE_BOMBCHUS:
case RG_PROGRESSIVE_BOMBCHU_BAG:
case RG_BOMBCHU_5:
case RG_BOMBCHU_10:
case RG_BOMBCHU_20:
@@ -332,7 +332,7 @@ bool Logic::CanUse(RandomizerGet itemName) {
case RG_PROGRESSIVE_BOMB_BAG:
case RG_BOMB_BAG:
return true; // AmmoCanDrop || Get(LOGIC_BUY_BOMB)
case RG_PROGRESSIVE_BOMBCHUS:
case RG_PROGRESSIVE_BOMBCHU_BAG:
case RG_BOMBCHU_5:
case RG_BOMBCHU_10:
case RG_BOMBCHU_20:
@@ -1129,7 +1129,8 @@ bool Logic::CanAttack() {
}
bool Logic::BombchusEnabled() {
return ctx->GetOption(RSK_BOMBCHU_BAG) ? CheckInventory(ITEM_BOMBCHU, true) : HasItem(RG_BOMB_BAG);
return ctx->GetOption(RSK_BOMBCHU_BAG).IsNot(RO_BOMBCHU_BAG_NONE) ? CheckInventory(ITEM_BOMBCHU, true)
: HasItem(RG_BOMB_BAG);
}
// TODO: Implement Ammo Drop Setting in place of bombchu drops
@@ -1686,7 +1687,7 @@ void Logic::ApplyItemEffect(Item& item, bool state) {
}
SetUpgrade(UPG_STICKS, newLevel);
} break;
case RG_PROGRESSIVE_BOMBCHUS: {
case RG_PROGRESSIVE_BOMBCHU_BAG: {
auto realGI = item.GetGIEntry();
if (realGI->itemId == RG_BOMBCHU_INF && realGI->modIndex == MOD_RANDOMIZER) {
SetRandoInf(RAND_INF_HAS_INFINITE_BOMBCHUS, true);

View File

@@ -738,13 +738,17 @@ void Settings::CreateOptionDescriptions() {
"Reading the mask shop sign will tell you rewards from showing masks at the Deku Theatre.";
mOptionDescriptions[RSK_FULL_WALLETS] = "Start with a full wallet. All wallet upgrades come filled with rupees.";
mOptionDescriptions[RSK_BOMBCHU_BAG] =
"Bombchus require their own bag to be found before use. Without this setting, any Bombchu requirement "
"is filled by Bomb Bag + a renewable source of Bombchus.\n"
"\n"
"The first Bombchu you find be a Bag containing 20 chus, and subsequent packs will have 10."
"Once found, they can be replenished at shops selling refills, Bombchu Bowling and the carpet merchant.\n"
"\n"
"Bombchu Bowling is opened by obtaining the Bombchu Bag.";
"None - Bombchus have vanilla behavior, any Bombchu requirement is filled by Bomb Bag + a renewable source of "
"Bombchus.\n\n"
"Single Bag - Bombchus require their own bag to be found before use. 5 of them are added to the pool "
"(6 if the Carpet Merchant is shuffled). The first Bombchu Bag you find will be a Bag containing 20 chus, "
"and subsequent bags will be replaced with Bombchu Ammo refills. Once found, they can be replenished at "
"shops selling refills, Bombchu Bowling and the carpet merchant. Bombchu Bowling is opened by obtaining "
"the Bombchu Bag.\n\n"
"Progressive Bags - 3 Bombchu Bags are added to the pool, the first one will unlock Bombchus with a capacity "
"of 20. The second one will upgrade this capacity to 30, and the final one will upgrade the capacity to the "
"usual 50.\n\n"
"Bombchu Bowling is opened by obtaining the first Bombchu bag.";
mOptionDescriptions[RSK_ENABLE_BOMBCHU_DROPS] = "Once you obtain a Bombchu Bag, refills will sometimes replace "
"Bomb drops that would spawn."
"\n"

View File

@@ -921,9 +921,36 @@ ItemObtainability Randomizer::GetItemObtainabilityFromRandomizerGet(RandomizerGe
case RG_BOMBCHU_20:
case RG_BUY_BOMBCHUS_10:
case RG_BUY_BOMBCHUS_20:
case RG_PROGRESSIVE_BOMBCHUS: // RANDOTODO Do we want bombchu refills to exist seperatly from bombchu bags? If
// so, this needs changing.
return CAN_OBTAIN;
return OTRGlobals::Instance->gRandoContext->GetOption(RSK_BOMBCHU_BAG).Is(RO_BOMBCHU_BAG_NONE)
? CAN_OBTAIN
: (INV_CONTENT(ITEM_BOMBCHU) != ITEM_NONE ? CAN_OBTAIN : CANT_OBTAIN_NEED_UPGRADE);
case RG_PROGRESSIVE_BOMBCHU_BAG: // RANDOTODO Do we want bombchu refills to exist seperatly from bombchu bags?
// If so, this needs changing.
switch (OTRGlobals::Instance->gRandoContext->GetOption(RSK_BOMBCHU_BAG).Get()) {
case RO_BOMBCHU_BAG_NONE:
return CANT_OBTAIN_MISC;
case RO_BOMBCHU_BAG_SINGLE:
return INV_CONTENT(ITEM_BOMBCHU) == ITEM_BOMBCHU
? (infiniteUpgrades != RO_INF_UPGRADES_OFF ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE)
: CAN_OBTAIN;
case RO_BOMBCHU_BAG_PROGRESSIVE:
if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_BOMBCHUS)) {
return CANT_OBTAIN_ALREADY_HAVE;
} else {
switch (gSaveContext.ship.quest.data.randomizer.bombchuUpgradeLevel) {
case 0:
case 1:
return CAN_OBTAIN;
case 2:
return infiniteUpgrades == RO_INF_UPGRADES_CONDENSED_PROGRESSIVE
? CANT_OBTAIN_ALREADY_HAVE
: CAN_OBTAIN;
case 3:
return infiniteUpgrades == RO_INF_UPGRADES_PROGRESSIVE ? CAN_OBTAIN
: CANT_OBTAIN_ALREADY_HAVE;
}
}
}
case RG_PROGRESSIVE_HOOKSHOT:
switch (INV_CONTENT(ITEM_HOOKSHOT)) {
case ITEM_NONE:
@@ -5815,7 +5842,7 @@ void Randomizer::CreateCustomMessages() {
GIMESSAGE(RG_FISHING_POLE, ITEM_FISHING_POLE, "You found a lost %rFishing Pole%w!&Time to hit the pond!",
"Du hast eine verlorene %rAngelrute%w&gefunden!&Zeit, im Teich&zu angeln!",
"Vous obtenez une %rCanne à pêche%w&perdue!&Il est temps d'aller à %gl'étang%w!"),
GIMESSAGE(RG_BOMBCHU_BAG, ITEM_BOMBCHU, "You found the %rBombchu Bag%w!",
GIMESSAGE(RG_PROGRESSIVE_BOMBCHU_BAG, ITEM_BOMBCHU, "You found the %rBombchu Bag%w!",
"Du hast die %rKrabbelminentasche%w&gefunden!", "Vous obtenez un %rSac de Missiles&Teigneux%w!"),
GIMESSAGE(
RG_BOMB_BAG_INF, ITEM_BOMB_BAG_40, "You got an %rInfinite Bomb Bag%w!&Now you have %yinfinite bombs%w!",
@@ -5958,7 +5985,7 @@ void Randomizer_GameplayStats_SetTimestamp(uint16_t item) {
}
// Count any bombchu pack as bombchus
if ((item >= RG_BOMBCHU_5 && item <= RG_BOMBCHU_20) || item == RG_PROGRESSIVE_BOMBCHUS) {
if ((item >= RG_BOMBCHU_5 && item <= RG_BOMBCHU_20) || item == RG_PROGRESSIVE_BOMBCHU_BAG) {
if (gSaveContext.ship.stats.itemTimestamp[ITEM_BOMBCHU] = 0) {
gSaveContext.ship.stats.itemTimestamp[ITEM_BOMBCHU] = time;
}
@@ -6273,19 +6300,8 @@ extern "C" u16 Randomizer_Item_Give(PlayState* play, GetItemEntry giEntry) {
}
break;
case RG_PROGRESSIVE_BOMBCHUS:
case RG_BOMBCHU_BAG:
if (INV_CONTENT(ITEM_BOMBCHU) == ITEM_NONE) {
INV_CONTENT(ITEM_BOMBCHU) = ITEM_BOMBCHU;
AMMO(ITEM_BOMBCHU) = 20;
} else if (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_INFINITE_UPGRADES)) {
Flags_SetRandomizerInf(RAND_INF_HAS_INFINITE_BOMBCHUS);
} else {
AMMO(ITEM_BOMBCHU) += 10;
if (AMMO(ITEM_BOMBCHU) > 50) {
AMMO(ITEM_BOMBCHU) = 50;
}
}
case RG_PROGRESSIVE_BOMBCHU_BAG:
OTRGlobals::Instance->gRandoContext->HandleGetBombchuBag();
break;
case RG_MASTER_SWORD:
if (!CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER)) {

View File

@@ -4105,7 +4105,6 @@ typedef enum {
RG_PROGRESSIVE_SCALE,
RG_PROGRESSIVE_NUT_UPGRADE,
RG_PROGRESSIVE_STICK_UPGRADE,
RG_PROGRESSIVE_BOMBCHUS,
RG_PROGRESSIVE_MAGIC_METER,
RG_MAGIC_SINGLE, // Added for refactor of GetItemEntries
RG_MAGIC_DOUBLE, // Added for refactor of GetItemEntries
@@ -4274,7 +4273,7 @@ typedef enum {
RG_TYCOON_WALLET,
RG_BRONZE_SCALE,
RG_CHILD_WALLET,
RG_BOMBCHU_BAG,
RG_PROGRESSIVE_BOMBCHU_BAG,
RG_QUIVER_INF,
RG_BOMB_BAG_INF,
RG_BULLET_BAG_INF,
@@ -6377,6 +6376,8 @@ typedef enum {
RO_AMMO_DROPS_ON,
} RandoOptionAmmoDrops;
typedef enum { RO_BOMBCHU_BAG_NONE, RO_BOMBCHU_BAG_SINGLE, RO_BOMBCHU_BAG_PROGRESSIVE } RandoOptionBombchuBag;
typedef enum {
RO_BOSS_SOULS_OFF,
RO_BOSS_SOULS_ON,

View File

@@ -232,6 +232,9 @@ extern "C" void Randomizer_InitSaveFile() {
// Reset triforce pieces collected.
gSaveContext.ship.quest.data.randomizer.triforcePiecesCollected = 0;
// Reset Bombchu Bag Upgrade
gSaveContext.ship.quest.data.randomizer.bombchuUpgradeLevel = 0;
SetStartingItems();
// Set Cutscene flags and texts to skip them.

View File

@@ -157,7 +157,7 @@ void Settings::CreateOptions() {
OPT_BOOL(RSK_MIX_THIEVES_HIDEOUT_ENTRANCES, "Mix Thieves' Hideout", CVAR_RANDOMIZER_SETTING("MixThievesHideout"), mOptionDescriptions[RSK_MIX_THIEVES_HIDEOUT_ENTRANCES]);
OPT_BOOL(RSK_MIX_GROTTO_ENTRANCES, "Mix Grottos", CVAR_RANDOMIZER_SETTING("MixGrottos"), mOptionDescriptions[RSK_MIX_GROTTO_ENTRANCES]);
OPT_BOOL(RSK_DECOUPLED_ENTRANCES, "Decouple Entrances", CVAR_RANDOMIZER_SETTING("DecoupleEntrances"), mOptionDescriptions[RSK_DECOUPLED_ENTRANCES]);
OPT_BOOL(RSK_BOMBCHU_BAG, "Bombchu Bag", CVAR_RANDOMIZER_SETTING("BombchuBag"), mOptionDescriptions[RSK_BOMBCHU_BAG]);
OPT_U8(RSK_BOMBCHU_BAG, "Bombchu Bag", {"None", "Single Bag", "Progressive Bags"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("BombchuBag"), mOptionDescriptions[RSK_BOMBCHU_BAG], WidgetType::Combobox, RO_BOMBCHU_BAG_NONE);
OPT_U8(RSK_ENABLE_BOMBCHU_DROPS, "Bombchu Drops", {"No", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("EnableBombchuDrops"), mOptionDescriptions[RSK_ENABLE_BOMBCHU_DROPS], WidgetType::Combobox, RO_AMMO_DROPS_ON);
// TODO: AmmoDrops and/or HeartDropRefill, combine with/separate Ammo Drops from Bombchu Drops?
OPT_BOOL(RSK_TRIFORCE_HUNT, "Triforce Hunt", CVAR_RANDOMIZER_SETTING("TriforceHunt"), mOptionDescriptions[RSK_TRIFORCE_HUNT], IMFLAG_NONE);

View File

@@ -229,6 +229,7 @@ void SaveManager::LoadRandomizer() {
SaveManager::Instance->LoadData("triforcePiecesCollected",
gSaveContext.ship.quest.data.randomizer.triforcePiecesCollected);
SaveManager::Instance->LoadData("bombchuUpgradeLevel", gSaveContext.ship.quest.data.randomizer.bombchuUpgradeLevel);
SaveManager::Instance->LoadData("pendingIceTrapCount", gSaveContext.ship.pendingIceTrapCount);
@@ -382,6 +383,7 @@ void SaveManager::SaveRandomizer(SaveContext* saveContext, int sectionID, bool f
SaveManager::Instance->SaveData("triforcePiecesCollected",
saveContext->ship.quest.data.randomizer.triforcePiecesCollected);
SaveManager::Instance->SaveData("bombchuUpgradeLevel", saveContext->ship.quest.data.randomizer.bombchuUpgradeLevel);
SaveManager::Instance->SaveData("pendingIceTrapCount", saveContext->ship.pendingIceTrapCount);

View File

@@ -1259,7 +1259,7 @@ void EnItem00_CustomItemsParticles(Actor* Parent, PlayState* play, GetItemEntry
case RG_DOUBLE_DEFENSE:
colorIndex = PARTICLE_WHITE;
break;
case RG_PROGRESSIVE_BOMBCHUS:
case RG_PROGRESSIVE_BOMBCHU_BAG:
colorIndex = PARTICLE_DARK_BLUE;
break;
case RG_BOTTLE_WITH_FAIRY:

View File

@@ -2211,8 +2211,10 @@ u8 Item_Give(PlayState* play, u8 item) {
AMMO(ITEM_BOMBCHU) = 10;
} else {
AMMO(ITEM_BOMBCHU) += 10;
if (AMMO(ITEM_BOMBCHU) > 50) {
AMMO(ITEM_BOMBCHU) = 50;
if (GameInteractor_Should(VB_CHECK_BOMBCHU_CAPACITY, true)) {
if (AMMO(ITEM_BOMBCHU) > 50) {
AMMO(ITEM_BOMBCHU) = 50;
}
}
}
return Return_Item(item, MOD_NONE, ITEM_NONE);
@@ -2222,8 +2224,10 @@ u8 Item_Give(PlayState* play, u8 item) {
AMMO(ITEM_BOMBCHU) += sAmmoRefillCounts[item - ITEM_BOMBCHUS_5 + 8];
} else {
AMMO(ITEM_BOMBCHU) += sAmmoRefillCounts[item - ITEM_BOMBCHUS_5 + 8];
if (AMMO(ITEM_BOMBCHU) > 50) {
AMMO(ITEM_BOMBCHU) = 50;
if (GameInteractor_Should(VB_CHECK_BOMBCHU_CAPACITY, true)) {
if (AMMO(ITEM_BOMBCHU) > 50) {
AMMO(ITEM_BOMBCHU) = 50;
}
}
}
return Return_Item(item, MOD_NONE, ITEM_NONE);
@@ -2996,8 +3000,10 @@ void Inventory_ChangeAmmo(s16 item, s16 ammoChange) {
} else if (item == ITEM_BOMBCHU) {
AMMO(ITEM_BOMBCHU) += ammoChange;
if (AMMO(ITEM_BOMBCHU) >= 50) {
AMMO(ITEM_BOMBCHU) = 50;
if (GameInteractor_Should(VB_CHECK_BOMBCHU_CAPACITY, true)) {
if (AMMO(ITEM_BOMBCHU) > 50) {
AMMO(ITEM_BOMBCHU) = 50;
}
} else if (AMMO(ITEM_BOMBCHU) < 0) {
AMMO(ITEM_BOMBCHU) = 0;
}
@@ -4908,7 +4914,7 @@ void Interface_DrawAmmoCount(PlayState* play, s16 button, s16 alpha) {
((i == ITEM_SLINGSHOT) && (AMMO(i) == CUR_CAPACITY(UPG_BULLET_BAG))) ||
((i == ITEM_STICK) && (AMMO(i) == CUR_CAPACITY(UPG_STICKS))) ||
((i == ITEM_NUT) && (AMMO(i) == CUR_CAPACITY(UPG_NUTS))) || ((i == ITEM_BOMBCHU) && (ammo == 50)) ||
((i == ITEM_BEAN) && (ammo == 15))) {
((i == ITEM_BEAN) && (ammo == 15)) || GameInteractor_Should(VB_COLOR_AMMO_GREEN, false, i)) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 120, 255, 0, alpha);
}

View File

@@ -591,7 +591,7 @@ void EnBox_UpdateSizeAndTexture(EnBox* this, PlayState* play) {
// If they have bombchus, don't consider the bombchu item major
if (INV_CONTENT(ITEM_BOMBCHU) == ITEM_BOMBCHU &&
((this->getItemEntry.modIndex == MOD_RANDOMIZER &&
this->getItemEntry.getItemId == RG_PROGRESSIVE_BOMBCHUS) ||
this->getItemEntry.getItemId == RG_PROGRESSIVE_BOMBCHU_BAG) ||
(this->getItemEntry.modIndex == MOD_NONE &&
(this->getItemEntry.getItemId == GI_BOMBCHUS_5 || this->getItemEntry.getItemId == GI_BOMBCHUS_10 ||
this->getItemEntry.getItemId == GI_BOMBCHUS_20)))) {

View File

@@ -762,15 +762,11 @@ s32 EnGirlA_CanBuy_Unk20(PlayState* play, EnGirlA* this) {
}
s32 EnGirlA_CanBuy_Bombchus(PlayState* play, EnGirlA* this) {
// When in rando, don't allow buying bombchus when the player doesn't have required explosives
// If bombchus are in logic, the player needs to have bombchus; otherwise they need a bomb bag
if (IS_RANDO) {
u8 bombchuBag = Randomizer_GetSettingValue(RSK_BOMBCHU_BAG);
if ((!bombchuBag && CUR_CAPACITY(UPG_BOMB_BAG) == 0) ||
(bombchuBag && INV_CONTENT(ITEM_BOMBCHU) == ITEM_NONE)) {
return CANBUY_RESULT_CANT_GET_NOW;
}
s32 canBuy;
if (GameInteractor_Should(VB_CAN_BUY_BOMBCHUS, false, &canBuy)) {
return canBuy;
}
if (AMMO(ITEM_BOMBCHU) >= 50) {
return CANBUY_RESULT_CANT_GET_NOW;
}

View File

@@ -61,7 +61,7 @@ void KaleidoScope_DrawAmmoCount(PauseContext* pauseCtx, GraphicsContext* gfxCtx,
(item == ITEM_SLINGSHOT && AMMO(item) == CUR_CAPACITY(UPG_BULLET_BAG)) ||
(item == ITEM_STICK && AMMO(item) == CUR_CAPACITY(UPG_STICKS)) ||
(item == ITEM_NUT && AMMO(item) == CUR_CAPACITY(UPG_NUTS)) || (item == ITEM_BOMBCHU && ammo == 50) ||
(item == ITEM_BEAN && ammo == 15)) {
(item == ITEM_BEAN && ammo == 15) || GameInteractor_Should(VB_COLOR_AMMO_GREEN, false, item)) {
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 120, 255, 0, pauseCtx->alpha);
}
}