diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp index 4badd8279..f4f344b49 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp @@ -220,6 +220,7 @@ static std::map cosmeticOptions = { COSMETIC_OPTION("Consumable.DDHeartBorder", "DD Heart Border", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 255, 255, 255), false, true, true), COSMETIC_OPTION("Consumable.Magic", "Magic", COSMETICS_GROUP_CONSUMABLE, ImVec4( 0, 200, 0, 255), false, true, false), COSMETIC_OPTION("Consumable.MagicActive", "Magic Active", COSMETICS_GROUP_CONSUMABLE, ImVec4(250, 250, 0, 255), false, true, true), + COSMETIC_OPTION("Consumable_MagicInfinite", "Infinite Magic", COSMETICS_GROUP_CONSUMABLE, ImVec4( 0, 0, 200, 255), false, true, true), COSMETIC_OPTION("Consumable.MagicBorder", "Magic Border", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 255, 255, 255), false, false, true), COSMETIC_OPTION("Consumable.MagicBorderActive", "Magic Border Active", COSMETICS_GROUP_CONSUMABLE, ImVec4(255, 255, 255, 255), false, false, true), COSMETIC_OPTION("Consumable.GreenRupee", "Green Rupee", COSMETICS_GROUP_CONSUMABLE, ImVec4( 50, 255, 50, 255), false, true, true), diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.h b/soh/soh/Enhancements/debugger/debugSaveEditor.h index 661cf87be..4199b7172 100644 --- a/soh/soh/Enhancements/debugger/debugSaveEditor.h +++ b/soh/soh/Enhancements/debugger/debugSaveEditor.h @@ -596,6 +596,15 @@ const std::vector flagTables = { { RAND_INF_ZD_FISH_4, "RAND_INF_ZD_FISH_4" }, { RAND_INF_ZD_FISH_5, "RAND_INF_ZD_FISH_5" }, + { RAND_INF_HAS_INFINITE_QUIVER, "RAND_INF_HAS_INFINITE_QUIVER" }, + { RAND_INF_HAS_INFINITE_BOMB_BAG, "RAND_INF_HAS_INFINITE_BOMB_BAG" }, + { RAND_INF_HAS_INFINITE_BULLET_BAG, "RAND_INF_HAS_INFINITE_BULLET_BAG" }, + { RAND_INF_HAS_INFINITE_STICK_UPGRADE, "RAND_INF_HAS_INFINITE_STICK_UPGRADE" }, + { RAND_INF_HAS_INFINITE_NUT_UPGRADE, "RAND_INF_HAS_INFINITE_NUT_UPGRADE" }, + { RAND_INF_HAS_INFINITE_MAGIC_METER, "RAND_INF_HAS_INFINITE_MAGIC_METER" }, + { RAND_INF_HAS_INFINITE_BOMBCHUS, "RAND_INF_HAS_INFINITE_BOMBCHUS" }, + { RAND_INF_HAS_INFINITE_MONEY, "RAND_INF_HAS_INFINITE_MONEY" }, + { RAND_INF_HAS_SKELETON_KEY, "RAND_INF_HAS_SKELETON_KEY" }, { RAND_INF_LINKS_POCKET, "RAND_INF_LINKS_POCKET" }, diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index 57f1d1e5c..2323e7222 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -220,6 +220,28 @@ typedef enum { VB_GERUDOS_BE_FRIENDLY, // Vanilla condition: switch VB_GTG_GATE_BE_OPEN, + // Opt: *s16 (item id) + /* Vanilla condition: + In one case: + ``` + true + ``` + In the other case: + ``` + (i == ITEM_STICK) || + (i == ITEM_NUT) || + (i == ITEM_BOMB) || + (i == ITEM_BOW) || + ( + (i >= ITEM_BOW_ARROW_FIRE) && + (i <= ITEM_BOW_ARROW_LIGHT) + ) || + (i == ITEM_SLINGSHOT) || + (i == ITEM_BOMBCHU) || + (i == ITEM_BEAN) + ``` + */ + VB_DRAW_AMMO_COUNT, /*** Play Cutscenes ***/ diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index 098317bae..2571b7d96 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -1694,6 +1694,46 @@ void RegisterFishsanity() { }); } +void RegisterInfiniteUpgrades() { + GameInteractor::Instance->RegisterGameHook([]() { + if (!IS_RANDO) { + return; + } + + if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_QUIVER)) { + AMMO(ITEM_BOW) = CUR_CAPACITY(UPG_QUIVER); + } + + if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_BOMB_BAG)) { + AMMO(ITEM_BOMB) = CUR_CAPACITY(UPG_BOMB_BAG); + } + + if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_BULLET_BAG)) { + AMMO(ITEM_SLINGSHOT) = CUR_CAPACITY(UPG_BULLET_BAG); + } + + if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_STICK_UPGRADE)) { + AMMO(ITEM_STICK) = CUR_CAPACITY(UPG_STICKS); + } + + if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_NUT_UPGRADE)) { + AMMO(ITEM_NUT) = CUR_CAPACITY(UPG_NUTS); + } + + if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_MAGIC_METER)) { + gSaveContext.magic = gSaveContext.magicCapacity; + } + + if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_BOMBCHUS)) { + AMMO(ITEM_BOMBCHU) = 50; + } + + if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_MONEY)) { + gSaveContext.rupees = CUR_CAPACITY(UPG_WALLET); + } + }); +} + extern "C" u8 Randomizer_GetSettingValue(RandomizerSettingKey randoSettingKey); void PatchCompasses() { @@ -1774,6 +1814,7 @@ void InitMods() { RegisterNoSwim(); RegisterNoWallet(); RegisterFishsanity(); + RegisterInfiniteUpgrades(); RegisterRandomizerCompasses(); NameTag_RegisterHooks(); RegisterFloorSwitchesHook(); diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp index e99b6fd71..d6e2c2f9a 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp @@ -2058,6 +2058,54 @@ void StaticData::HintTable_Init_Item() { CustomMessage("a fish-puller", /*german*/"", /*french*/"(canne à pêche)")}); // /*spanish*/(caña de pescar) + hintTextTable[RHT_QUIVER_INF] = HintText(CustomMessage("", /*german*/"!!!", /*french*/"!!!"), + { + CustomMessage("", /*german*/"!!!", /*french*/"!!!"), + }, { + CustomMessage("", /*german*/"!!!", /*french*/"!!!")}); + + hintTextTable[RHT_BOMB_BAG_INF] = HintText(CustomMessage("", /*german*/"!!!", /*french*/"!!!"), + { + CustomMessage("", /*german*/"!!!", /*french*/"!!!"), + }, { + CustomMessage("", /*german*/"!!!", /*french*/"!!!")}); + + hintTextTable[RHT_BULLET_BAG_INF] = HintText(CustomMessage("", /*german*/"!!!", /*french*/"!!!"), + { + CustomMessage("", /*german*/"!!!", /*french*/"!!!"), + }, { + CustomMessage("", /*german*/"!!!", /*french*/"!!!")}); + + hintTextTable[RHT_STICK_UPGRADE_INF] = HintText(CustomMessage("", /*german*/"!!!", /*french*/"!!!"), + { + CustomMessage("", /*german*/"!!!", /*french*/"!!!"), + }, { + CustomMessage("", /*german*/"!!!", /*french*/"!!!")}); + + hintTextTable[RHT_NUT_UPGRADE_INF] = HintText(CustomMessage("", /*german*/"!!!", /*french*/"!!!"), + { + CustomMessage("", /*german*/"!!!", /*french*/"!!!"), + }, { + CustomMessage("", /*german*/"!!!", /*french*/"!!!")}); + + hintTextTable[RHT_MAGIC_INF] = HintText(CustomMessage("", /*german*/"!!!", /*french*/"!!!"), + { + CustomMessage("", /*german*/"!!!", /*french*/"!!!"), + }, { + CustomMessage("", /*german*/"!!!", /*french*/"!!!")}); + + hintTextTable[RHT_BOMBCHU_INF] = HintText(CustomMessage("", /*german*/"!!!", /*french*/"!!!"), + { + CustomMessage("", /*german*/"!!!", /*french*/"!!!"), + }, { + CustomMessage("", /*german*/"!!!", /*french*/"!!!")}); + + hintTextTable[RHT_WALLET_INF] = HintText(CustomMessage("", /*german*/"!!!", /*french*/"!!!"), + { + CustomMessage("", /*german*/"!!!", /*french*/"!!!"), + }, { + CustomMessage("", /*german*/"!!!", /*french*/"!!!")}); + hintTextTable[RHT_EPONA] = HintText(CustomMessage("Epona", /*german*/"", /*french*/"Epona"), // /*spanish*/a Epona { diff --git a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp index 6d2e44fbf..514e81ce4 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp @@ -845,6 +845,16 @@ void GenerateItemPool() { ctx->possibleIceTrapModels.push_back(RG_FISHING_POLE); } + if (ctx->GetOption(RSK_INFINITE_UPGRADES).Is(RO_INF_UPGRADES_PROGRESSIVE)) { + AddItemToMainPool(RG_PROGRESSIVE_BOMB_BAG); + AddItemToMainPool(RG_PROGRESSIVE_BOW); + AddItemToMainPool(RG_PROGRESSIVE_NUT_UPGRADE); + AddItemToMainPool(RG_PROGRESSIVE_SLINGSHOT); + AddItemToMainPool(RG_PROGRESSIVE_STICK_UPGRADE); + AddItemToMainPool(RG_PROGRESSIVE_MAGIC_METER); + AddItemToMainPool(RG_PROGRESSIVE_WALLET); + } + if (ctx->GetOption(RSK_SHUFFLE_MAGIC_BEANS)) { AddItemToMainPool(RG_MAGIC_BEAN_PACK); if (ctx->GetOption(RSK_ITEM_POOL).Is(RO_ITEM_POOL_PLENTIFUL)) { diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index 4f94e517a..d5737d33d 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -1113,6 +1113,24 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void } break; } + case VB_DRAW_AMMO_COUNT: { + s16 item = *static_cast(optionalArg); + // don't draw ammo count if you have the infinite upgrade + if ( + (item == ITEM_NUT && Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_NUT_UPGRADE)) || + (item == ITEM_STICK && Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_STICK_UPGRADE)) || + (item == ITEM_BOMB && Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_BOMB_BAG)) || + ( + (item == ITEM_BOW || item == ITEM_BOW_ARROW_FIRE || item == ITEM_BOW_ARROW_ICE || item == ITEM_BOW_ARROW_LIGHT) && + Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_QUIVER) + ) || + (item == ITEM_SLINGSHOT && Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_BULLET_BAG)) || + (item == ITEM_BOMBCHU && Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_BOMBCHUS)) + ) { + *should = false; + } + break; + } case VB_TRADE_TIMER_ODD_MUSHROOM: case VB_TRADE_TIMER_EYEDROPS: case VB_TRADE_TIMER_FROG: diff --git a/soh/soh/Enhancements/randomizer/item.cpp b/soh/soh/Enhancements/randomizer/item.cpp index 9be5551b8..2ffedbfeb 100644 --- a/soh/soh/Enhancements/randomizer/item.cpp +++ b/soh/soh/Enhancements/randomizer/item.cpp @@ -119,6 +119,7 @@ std::shared_ptr Item::GetGIEntry() const { // NOLINT(*-no-recursio RandomizerGet actual = RG_NONE; const bool tycoonWallet = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHOPSANITY) > RO_SHOPSANITY_ZERO_ITEMS; + const u8 infiniteUpgrades = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_INFINITE_UPGRADES); switch (randomizerGet) { case RG_PROGRESSIVE_STICK_UPGRADE: switch (CUR_UPG_VALUE(UPG_STICKS)) { @@ -128,12 +129,23 @@ std::shared_ptr Item::GetGIEntry() const { // NOLINT(*-no-recursio break; } case 1: - actual = RG_DEKU_STICK_CAPACITY_20; + if (infiniteUpgrades == RO_INF_UPGRADES_CONDENSED_PROGRESSIVE) { + actual = RG_STICK_UPGRADE_INF; + } else { + actual = RG_DEKU_STICK_CAPACITY_20; + } break; case 2: - case 3: actual = RG_DEKU_STICK_CAPACITY_30; break; + case 3: + case 4: + if (infiniteUpgrades == RO_INF_UPGRADES_PROGRESSIVE) { + actual = RG_STICK_UPGRADE_INF; + } else { + actual = RG_DEKU_STICK_CAPACITY_30; + } + break; default: break; } @@ -146,12 +158,23 @@ std::shared_ptr Item::GetGIEntry() const { // NOLINT(*-no-recursio break; } case 1: - actual = RG_DEKU_NUT_CAPACITY_30; + if (infiniteUpgrades == RO_INF_UPGRADES_CONDENSED_PROGRESSIVE) { + actual = RG_NUT_UPGRADE_INF; + } else { + actual = RG_DEKU_NUT_CAPACITY_30; + } break; case 2: - case 3: actual = RG_DEKU_NUT_CAPACITY_40; break; + case 3: + case 4: + if (infiniteUpgrades == RO_INF_UPGRADES_PROGRESSIVE) { + actual = RG_NUT_UPGRADE_INF; + } else { + actual = RG_DEKU_NUT_CAPACITY_40; + } + break; default: break; } @@ -162,12 +185,23 @@ std::shared_ptr Item::GetGIEntry() const { // NOLINT(*-no-recursio actual = RG_BOMB_BAG; break; case 1: - actual = RG_BIG_BOMB_BAG; + if (infiniteUpgrades == RO_INF_UPGRADES_CONDENSED_PROGRESSIVE) { + actual = RG_BOMB_BAG_INF; + } else { + actual = RG_BIG_BOMB_BAG; + } break; case 2: - case 3: actual = RG_BIGGEST_BOMB_BAG; break; + case 3: + case 4: + if (infiniteUpgrades == RO_INF_UPGRADES_PROGRESSIVE) { + actual = RG_BOMB_BAG_INF; + } else { + actual = RG_BIGGEST_BOMB_BAG; + } + break; default: break; } @@ -178,12 +212,23 @@ std::shared_ptr Item::GetGIEntry() const { // NOLINT(*-no-recursio actual = RG_FAIRY_BOW; break; case 1: - actual = RG_BIG_QUIVER; + if (infiniteUpgrades == RO_INF_UPGRADES_CONDENSED_PROGRESSIVE) { + actual = RG_QUIVER_INF; + } else { + actual = RG_BIG_QUIVER; + } break; case 2: - case 3: actual = RG_BIGGEST_QUIVER; break; + case 3: + case 4: + if (infiniteUpgrades == RO_INF_UPGRADES_PROGRESSIVE) { + actual = RG_QUIVER_INF; + } else { + actual = RG_BIGGEST_QUIVER; + } + break; default: break; } @@ -194,12 +239,23 @@ std::shared_ptr Item::GetGIEntry() const { // NOLINT(*-no-recursio actual = RG_FAIRY_SLINGSHOT; break; case 1: - actual = RG_BIG_BULLET_BAG; + if (infiniteUpgrades == RO_INF_UPGRADES_CONDENSED_PROGRESSIVE) { + actual = RG_BULLET_BAG_INF; + } else { + actual = RG_BIG_BULLET_BAG; + } break; case 2: - case 3: actual = RG_BIGGEST_BULLET_BAG; break; + case 3: + case 4: + if (infiniteUpgrades == RO_INF_UPGRADES_PROGRESSIVE) { + actual = RG_BULLET_BAG_INF; + } else { + actual = RG_BIGGEST_BULLET_BAG; + } + break; default: break; } @@ -259,9 +315,16 @@ std::shared_ptr Item::GetGIEntry() const { // NOLINT(*-no-recursio actual = RG_GIANT_WALLET; break; case 2: - case 3: actual = tycoonWallet ? RG_TYCOON_WALLET : RG_GIANT_WALLET; break; + case 3: + case 4: + if (infiniteUpgrades != RO_INF_UPGRADES_OFF) { + actual = RG_WALLET_INF; + } else { + actual = tycoonWallet ? RG_TYCOON_WALLET : RG_GIANT_WALLET; + } + break; default: break; } @@ -289,9 +352,16 @@ std::shared_ptr Item::GetGIEntry() const { // NOLINT(*-no-recursio actual = RG_MAGIC_SINGLE; break; case 1: - case 2: actual = RG_MAGIC_DOUBLE; break; + case 2: + case 3: + if (infiniteUpgrades != RO_INF_UPGRADES_OFF) { + actual = RG_MAGIC_INF; + } else { + actual = RG_MAGIC_DOUBLE; + } + break; default: break; } @@ -299,6 +369,17 @@ std::shared_ptr Item::GetGIEntry() const { // NOLINT(*-no-recursio case RG_PROGRESSIVE_GORONSWORD: // todo progressive? actual = RG_BIGGORON_SWORD; break; + case RG_PROGRESSIVE_BOMBCHUS: + if (INV_CONTENT(ITEM_BOMBCHU) == ITEM_NONE) { + actual = RG_BOMBCHU_20; + } else if (infiniteUpgrades != RO_INF_UPGRADES_OFF) { + actual = RG_BOMBCHU_INF; + } else if (AMMO(ITEM_BOMBCHU) < 5) { + actual = RG_BOMBCHU_10; + } else { + actual = RG_BOMBCHU_5; + } + break; default: actual = RG_NONE; break; diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp index b9bd9be22..7c86fcfd3 100644 --- a/soh/soh/Enhancements/randomizer/item_list.cpp +++ b/soh/soh/Enhancements/randomizer/item_list.cpp @@ -289,6 +289,15 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_BRONZE_SCALE] = Item(RG_BRONZE_SCALE, Text{ "Bronze Scale", "!!!", "!!!" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, &logic->ProgressiveWallet, 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_QUIVER_INF] = Item(RG_QUIVER_INF, Text{ "Infinite Quiver", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_QUIVER_INF, true, &logic->ProgressiveBow, 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", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_BOMB_BAG_INF, true, &logic->ProgressiveBombBag, 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); + itemTable[RG_BULLET_BAG_INF] = Item(RG_BULLET_BAG_INF, Text{ "Infinite Bullet Bag", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_BULLET_BAG_INF, true, &logic->ProgressiveBulletBag, RHT_BULLET_BAG_INF, RG_BULLET_BAG_INF, OBJECT_GI_DEKUPOUCH, GID_BULLET_BAG, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_STICK_UPGRADE_INF] = Item(RG_STICK_UPGRADE_INF, Text{ "Infinite Stick Capacity", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_STICK_UPGRADE_INF, true, &logic->noVariable, RHT_STICK_UPGRADE_INF, RG_STICK_UPGRADE_INF, OBJECT_GI_STICK, GID_STICK, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_NUT_UPGRADE_INF] = Item(RG_QUIVER_INF, Text{ "Infinite Nut Capacity", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_NUT_UPGRADE_INF, true, &logic->noVariable, RHT_NUT_UPGRADE_INF, RG_NUT_UPGRADE_INF, OBJECT_GI_NUTS, GID_NUTS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_MAGIC_INF] = Item(RG_QUIVER_INF, Text{ "Infinite Magic Meter", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_MAGIC_INF, true, &logic->ProgressiveMagic, RHT_MAGIC_INF, RG_MAGIC_INF, OBJECT_GI_MAGICPOT, GID_MAGIC_LARGE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_BOMBCHU_INF] = Item(RG_BOMBCHU_INF, Text{ "Infinite Bombchus", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_BOMBCHU_INF, true, &logic->Bombchus, RHT_BOMBCHU_INF, RG_BOMBCHU_INF, OBJECT_GI_BOMB_2, GID_BOMBCHU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_WALLET_INF] = Item(RG_WALLET_INF, Text{ "Infinite Wallet", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_WALLET_INF, true, &logic->ProgressiveWallet, RHT_WALLET_INF, RG_WALLET_INF, OBJECT_GI_PURSE, GID_WALLET_GIANT, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_SKELETON_KEY] = Item(RG_SKELETON_KEY, Text{ "Skeleton Key", "!!!", "!!!" }, ITEMTYPE_ITEM, GI_STONE_OF_AGONY, true, &logic->SkeletonKey, RHT_SKELETON_KEY, RG_SKELETON_KEY, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_SKELETON_KEY].SetCustomDrawFunc(Randomizer_DrawSkeletonKey); diff --git a/soh/soh/Enhancements/randomizer/option_descriptions.cpp b/soh/soh/Enhancements/randomizer/option_descriptions.cpp index e5b0722f3..6b5ebc893 100644 --- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp +++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp @@ -250,6 +250,11 @@ void Settings::CreateOptionDescriptions() { mOptionDescriptions[RSK_SHUFFLE_FISHING_POLE] = "Shuffles the fishing pole into the item pool.\n" "\n" "The fishing pole is required to play the fishing pond minigame."; + mOptionDescriptions[RSK_INFINITE_UPGRADES] = "Adds upgrades that hold infinite quanities of items (bombs, arrows, etc.)\n" + "\n" + "Progressive - The infinite upgrades are obtained after getting the last normal capacity upgrade\n" + "\n" + "Condensed Progressive - The infinite upgrades are obtained as the first capacity upgrade (doesn't apply to the infinite wallet or to infinite magic)"; mOptionDescriptions[RSK_SHUFFLE_DEKU_STICK_BAG] = "Shuffles the deku stick bag into the item pool.\n" "\n" "The deku stick bag is required to hold deku sticks."; diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index faac02d84..b2c047e63 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -360,6 +360,13 @@ ItemObtainability Randomizer::GetItemObtainabilityFromRandomizerGet(RandomizerGe // This is needed since Plentiful item pool also adds a third progressive wallet // but we should *not* get Tycoon's Wallet in that mode. bool tycoonWallet = GetRandoSettingValue(RSK_SHOPSANITY) > RO_SHOPSANITY_ZERO_ITEMS; + + // Same thing with the infinite upgrades, if we're not shuffling them + // and we're using the Plentiful item pool, we should prevent the infinite + // upgrades from being gotten + u8 infiniteUpgrades = GetRandoSettingValue(RSK_INFINITE_UPGRADES); + + u8 numWallets = 2 + (u8)tycoonWallet + (infiniteUpgrades != RO_INF_UPGRADES_OFF ? 1 : 0); switch (randoGet) { case RG_NONE: case RG_TRIFORCE: @@ -396,19 +403,25 @@ ItemObtainability Randomizer::GetItemObtainabilityFromRandomizerGet(RandomizerGe // Inventory Items case RG_PROGRESSIVE_STICK_UPGRADE: - return CUR_UPG_VALUE(UPG_STICKS) < 3 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + return infiniteUpgrades != RO_INF_UPGRADES_OFF ? + (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_STICK_UPGRADE) ? CANT_OBTAIN_ALREADY_HAVE : CAN_OBTAIN) : + (CUR_UPG_VALUE(UPG_STICKS) < 3 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE); case RG_DEKU_STICK_1: case RG_BUY_DEKU_STICK_1: return CUR_UPG_VALUE(UPG_STICKS) ? CAN_OBTAIN : CANT_OBTAIN_NEED_UPGRADE; case RG_PROGRESSIVE_NUT_UPGRADE: - return CUR_UPG_VALUE(UPG_NUTS) < 3 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + return infiniteUpgrades != RO_INF_UPGRADES_OFF ? + (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_NUT_UPGRADE) ? CANT_OBTAIN_ALREADY_HAVE : CAN_OBTAIN) : + (CUR_UPG_VALUE(UPG_NUTS) < 3 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE); case RG_DEKU_NUTS_5: case RG_DEKU_NUTS_10: case RG_BUY_DEKU_NUTS_5: case RG_BUY_DEKU_NUTS_10: return CUR_UPG_VALUE(UPG_NUTS) ? CAN_OBTAIN : CANT_OBTAIN_NEED_UPGRADE; case RG_PROGRESSIVE_BOMB_BAG: - return CUR_UPG_VALUE(UPG_BOMB_BAG) < 3 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + return infiniteUpgrades != RO_INF_UPGRADES_OFF ? + (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_BOMB_BAG) ? CANT_OBTAIN_ALREADY_HAVE : CAN_OBTAIN) : + (CUR_UPG_VALUE(UPG_BOMB_BAG) < 3 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE); case RG_BOMBS_5: case RG_BOMBS_10: case RG_BOMBS_20: @@ -419,7 +432,9 @@ ItemObtainability Randomizer::GetItemObtainabilityFromRandomizerGet(RandomizerGe case RG_BUY_BOMBS_30: return CUR_UPG_VALUE(UPG_BOMB_BAG) ? CAN_OBTAIN : CANT_OBTAIN_NEED_UPGRADE; case RG_PROGRESSIVE_BOW: - return CUR_UPG_VALUE(UPG_QUIVER) < 3 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + return infiniteUpgrades != RO_INF_UPGRADES_OFF ? + (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_QUIVER) ? CANT_OBTAIN_ALREADY_HAVE : CAN_OBTAIN) : + (CUR_UPG_VALUE(UPG_QUIVER) < 3 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE); case RG_ARROWS_5: case RG_ARROWS_10: case RG_ARROWS_30: @@ -428,7 +443,9 @@ ItemObtainability Randomizer::GetItemObtainabilityFromRandomizerGet(RandomizerGe case RG_BUY_ARROWS_50: return CUR_UPG_VALUE(UPG_QUIVER) ? CAN_OBTAIN : CANT_OBTAIN_NEED_UPGRADE; case RG_PROGRESSIVE_SLINGSHOT: - return CUR_UPG_VALUE(UPG_BULLET_BAG) < 3 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + return infiniteUpgrades != RO_INF_UPGRADES_OFF ? + (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_BULLET_BAG) ? CANT_OBTAIN_ALREADY_HAVE : CAN_OBTAIN) : + (CUR_UPG_VALUE(UPG_BULLET_BAG) < 3 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE); case RG_DEKU_SEEDS_30: case RG_BUY_DEKU_SEEDS_30: return CUR_UPG_VALUE(UPG_BULLET_BAG) ? CAN_OBTAIN : CANT_OBTAIN_NEED_UPGRADE; @@ -550,13 +567,15 @@ ItemObtainability Randomizer::GetItemObtainabilityFromRandomizerGet(RandomizerGe case RG_PROGRESSIVE_STRENGTH: return CUR_UPG_VALUE(UPG_STRENGTH) < 3 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; case RG_PROGRESSIVE_WALLET: - return CUR_UPG_VALUE(UPG_WALLET) < (tycoonWallet ? 3 : 2) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + return CUR_UPG_VALUE(UPG_WALLET) < numWallets ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; case RG_PROGRESSIVE_SCALE: return CUR_UPG_VALUE(UPG_SCALE) < 2 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; case RG_PROGRESSIVE_MAGIC_METER: case RG_MAGIC_SINGLE: case RG_MAGIC_DOUBLE: - return gSaveContext.magicLevel < 2 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + return infiniteUpgrades != RO_INF_UPGRADES_OFF ? + (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_MAGIC_METER) ? CANT_OBTAIN_ALREADY_HAVE : CAN_OBTAIN) : + (gSaveContext.magicLevel < 2 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE); case RG_FISHING_POLE: return !Flags_GetRandomizerInf(RAND_INF_FISHING_POLE_FOUND) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; @@ -716,6 +735,11 @@ GetItemID Randomizer::GetItemIdFromRandomizerGet(RandomizerGet randoGet, GetItem // This is needed since Plentiful item pool also adds a third progressive wallet // but we should *not* get Tycoon's Wallet in that mode. bool tycoonWallet = GetRandoSettingValue(RSK_SHOPSANITY) > RO_SHOPSANITY_ZERO_ITEMS; + + // Same thing with the infinite upgrades, if we're not shuffling them + //and we're using the Plentiful item pool, we should prevent the infinite + //upgrades from being gotten + u8 infiniteUpgrades = GetRandoSettingValue(RSK_INFINITE_UPGRADES); switch (randoGet) { case RG_NONE: return ogItemId; @@ -760,8 +784,10 @@ GetItemID Randomizer::GetItemIdFromRandomizerGet(RandomizerGet randoGet, GetItem case 1: return GI_STICK_UPGRADE_20; case 2: - case 3: return GI_STICK_UPGRADE_30; + case 3: + case 4: + return infiniteUpgrades == RO_INF_UPGRADES_PROGRESSIVE ? (GetItemID)RG_STICK_UPGRADE_INF : GI_STICK_UPGRADE_30; } case RG_PROGRESSIVE_NUT_UPGRADE: switch (CUR_UPG_VALUE(UPG_NUTS)) { @@ -769,8 +795,10 @@ GetItemID Randomizer::GetItemIdFromRandomizerGet(RandomizerGet randoGet, GetItem case 1: return GI_NUT_UPGRADE_30; case 2: - case 3: return GI_NUT_UPGRADE_40; + case 3: + case 4: + return infiniteUpgrades == RO_INF_UPGRADES_PROGRESSIVE ? (GetItemID)RG_NUT_UPGRADE_INF : GI_NUT_UPGRADE_40; } case RG_PROGRESSIVE_BOMB_BAG: switch (CUR_UPG_VALUE(UPG_BOMB_BAG)) { @@ -779,8 +807,10 @@ GetItemID Randomizer::GetItemIdFromRandomizerGet(RandomizerGet randoGet, GetItem case 1: return GI_BOMB_BAG_30; case 2: - case 3: return GI_BOMB_BAG_40; + case 3: + case 4: + return infiniteUpgrades == RO_INF_UPGRADES_PROGRESSIVE ? (GetItemID)RG_BOMB_BAG_INF : GI_BOMB_BAG_40; } case RG_BOMBS_5: case RG_BUY_BOMBS_525: @@ -801,8 +831,10 @@ GetItemID Randomizer::GetItemIdFromRandomizerGet(RandomizerGet randoGet, GetItem case 1: return GI_QUIVER_40; case 2: - case 3: return GI_QUIVER_50; + case 3: + case 4: + return infiniteUpgrades == RO_INF_UPGRADES_PROGRESSIVE ? (GetItemID)RG_QUIVER_INF : GI_QUIVER_50; } case RG_ARROWS_5: case RG_BUY_ARROWS_10: @@ -820,8 +852,10 @@ GetItemID Randomizer::GetItemIdFromRandomizerGet(RandomizerGet randoGet, GetItem case 1: return GI_BULLET_BAG_40; case 2: - case 3: return GI_BULLET_BAG_50; + case 3: + case 4: + return infiniteUpgrades == RO_INF_UPGRADES_PROGRESSIVE ? (GetItemID)RG_BULLET_BAG_INF : GI_BULLET_BAG_50; } case RG_DEKU_SEEDS_30: case RG_BUY_DEKU_SEEDS_30: @@ -843,6 +877,16 @@ GetItemID Randomizer::GetItemIdFromRandomizerGet(RandomizerGet randoGet, GetItem case RG_BOMBCHU_20: case RG_BUY_BOMBCHU_20: return GI_BOMBCHUS_20; + case RG_PROGRESSIVE_BOMBCHUS: + if (INV_CONTENT(ITEM_BOMBCHU) == ITEM_NONE) { + return (GetItemID)RG_PROGRESSIVE_BOMBCHUS; + } else if (infiniteUpgrades != RO_INF_UPGRADES_OFF) { + return (GetItemID)RG_BOMBCHU_INF; + } else if (AMMO(ITEM_BOMBCHU) < 5) { + return GI_BOMBCHUS_10; + } else { + return GI_BOMBCHUS_5; + } case RG_PROGRESSIVE_HOOKSHOT: switch (INV_CONTENT(ITEM_HOOKSHOT)) { case ITEM_NONE: @@ -959,8 +1003,10 @@ GetItemID Randomizer::GetItemIdFromRandomizerGet(RandomizerGet randoGet, GetItem case 1: return GI_WALLET_GIANT; case 2: + return tycoonWallet ? (GetItemID)RG_TYCOON_WALLET : infiniteUpgrades != RO_INF_UPGRADES_OFF ? (GetItemID)RG_WALLET_INF : GI_WALLET_GIANT; case 3: - return tycoonWallet ? (GetItemID)RG_TYCOON_WALLET : GI_WALLET_GIANT; + case 4: + return infiniteUpgrades != RO_INF_UPGRADES_OFF ? (GetItemID)RG_WALLET_INF : tycoonWallet ? (GetItemID)RG_TYCOON_WALLET : GI_WALLET_GIANT; } case RG_PROGRESSIVE_SCALE: if (!Flags_GetRandomizerInf(RAND_INF_CAN_SWIM)) { @@ -978,8 +1024,10 @@ GetItemID Randomizer::GetItemIdFromRandomizerGet(RandomizerGet randoGet, GetItem case 0: return (GetItemID)RG_MAGIC_SINGLE; case 1: - case 2: return (GetItemID)RG_MAGIC_DOUBLE; + case 2: + case 3: + return infiniteUpgrades != RO_INF_UPGRADES_OFF ? (GetItemID)RG_MAGIC_INF : (GetItemID)RG_MAGIC_DOUBLE; } case RG_RECOVERY_HEART: @@ -1077,11 +1125,37 @@ bool Randomizer::IsItemVanilla(RandomizerGet randoGet) { case RG_GOLD_SKULLTULA_TOKEN: case RG_PROGRESSIVE_HOOKSHOT: case RG_PROGRESSIVE_STRENGTH: + return true; case RG_PROGRESSIVE_BOMB_BAG: + if (CUR_UPG_VALUE(UPG_BOMB_BAG) < 3) { + return true; + } else { + return false; + } case RG_PROGRESSIVE_BOW: + if (CUR_UPG_VALUE(UPG_QUIVER) < 3) { + return true; + } else { + return false; + } case RG_PROGRESSIVE_SLINGSHOT: + if (CUR_UPG_VALUE(UPG_BULLET_BAG) < 3) { + return true; + } else { + return false; + } case RG_PROGRESSIVE_NUT_UPGRADE: + if (CUR_UPG_VALUE(UPG_NUTS) < 3) { + return true; + } else { + return false; + } case RG_PROGRESSIVE_STICK_UPGRADE: + if (CUR_UPG_VALUE(UPG_STICKS) < 3) { + return true; + } else { + return false; + } case RG_PROGRESSIVE_OCARINA: case RG_PROGRESSIVE_GORONSWORD: case RG_EMPTY_BOTTLE: @@ -1103,6 +1177,9 @@ bool Randomizer::IsItemVanilla(RandomizerGet randoGet) { case RG_BOMBCHU_10: case RG_BOMBCHU_20: case RG_BOMBCHU_DROP: + return true; + case RG_PROGRESSIVE_BOMBCHUS: + return INV_CONTENT(ITEM_BOMBCHU) != ITEM_NONE && !GetRandoSettingValue(RSK_INFINITE_UPGRADES); case RG_ARROWS_5: case RG_ARROWS_10: case RG_ARROWS_30: @@ -2954,7 +3031,7 @@ CustomMessage Randomizer::GetGoronMessage(u16 index) { void Randomizer::CreateCustomMessages() { // RANDTODO: Translate into french and german and replace GIMESSAGE_UNTRANSLATED // with GIMESSAGE(getItemID, itemID, english, german, french). - const std::array getItemMessages = {{ + const std::array getItemMessages = {{ GIMESSAGE(RG_GREG_RUPEE, ITEM_MASK_GORON, "You found %gGreg%w!", "%gGreg%w! Du hast ihn wirklich gefunden!", @@ -3226,6 +3303,14 @@ void Randomizer::CreateCustomMessages() { "Vous trouvez la %rtouche %y\xa6%r de&l'Ocarina%w! Vous pouvez&maintenant l'utiliser lorsque&vous en jouez!"), GIMESSAGE_UNTRANSLATED(RG_BRONZE_SCALE, ITEM_SCALE_SILVER, "You got the %rBronze Scale%w!&The power of buoyancy is yours!"), GIMESSAGE_UNTRANSLATED(RG_FISHING_POLE, ITEM_FISHING_POLE, "You found a lost %rFishing Pole%w!&Time to hit the pond!"), + GIMESSAGE_UNTRANSLATED(RG_BOMB_BAG_INF, ITEM_BOMB_BAG_40, "You got an %rInfinite Bomb Bag%w!&Now you have %yinfinite bombs%w!"), + GIMESSAGE_UNTRANSLATED(RG_QUIVER_INF, ITEM_QUIVER_50, "You got an %rInfinite Quiver%w!&Now you have %yinfinite arrows%w!"), + GIMESSAGE_UNTRANSLATED(RG_BULLET_BAG_INF, ITEM_BULLET_BAG_50, "You got an %rInfinite Bullet Bag%w!&Now you have %yinfinite&slingshot seeds%w!"), + GIMESSAGE_UNTRANSLATED(RG_STICK_UPGRADE_INF, ITEM_STICK, "You now have %yinfinite%w %rDeku Sticks%w!"), + GIMESSAGE_UNTRANSLATED(RG_NUT_UPGRADE_INF, ITEM_NUT, "You now have %yinfinite%w %rDeku Nuts%w!"), + GIMESSAGE_UNTRANSLATED(RG_MAGIC_INF, ITEM_MAGIC_LARGE, "You now have %yinfinite%w %rMagic%w!"), + GIMESSAGE_UNTRANSLATED(RG_BOMBCHU_INF, ITEM_BOMBCHU, "You now have %yinfinite%w %rBombchus%w!"), + GIMESSAGE_UNTRANSLATED(RG_WALLET_INF, ITEM_WALLET_GIANT, "You now have %yinfinite%w %rmoney%w!"), GIMESSAGE_UNTRANSLATED(RG_SKELETON_KEY, ITEM_KEY_SMALL, "You found the %rSkeleton Key%w!"), GIMESSAGE_UNTRANSLATED(RG_DEKU_STICK_BAG, ITEM_STICK, "You found the %rDeku Stick Bag%w!&You can now hold deku sticks!"), GIMESSAGE_UNTRANSLATED(RG_DEKU_NUT_BAG, ITEM_NUT, "You found the %rDeku Nut Bag%w!&You can now hold deku nuts!"), diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index e89059ecd..b423b5235 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -1987,6 +1987,14 @@ typedef enum { RG_TYCOON_WALLET, RG_BRONZE_SCALE, RG_CHILD_WALLET, + RG_QUIVER_INF, + RG_BOMB_BAG_INF, + RG_BULLET_BAG_INF, + RG_STICK_UPGRADE_INF, + RG_NUT_UPGRADE_INF, + RG_MAGIC_INF, + RG_BOMBCHU_INF, + RG_WALLET_INF, RG_FAIRY_OCARINA, RG_OCARINA_OF_TIME, RG_BOMB_BAG, @@ -3201,6 +3209,14 @@ typedef enum { RHT_BUY_RED_POTION_40, RHT_BUY_RED_POTION_50, RHT_TRIFORCE, + RHT_QUIVER_INF, + RHT_BOMB_BAG_INF, + RHT_BULLET_BAG_INF, + RHT_STICK_UPGRADE_INF, + RHT_NUT_UPGRADE_INF, + RHT_MAGIC_INF, + RHT_BOMBCHU_INF, + RHT_WALLET_INF, RHT_HINT, RHT_TYCOON_WALLET, RHT_CHILD_WALLET, @@ -3715,6 +3731,7 @@ typedef enum { RSK_FISHSANITY_POND_COUNT, RSK_FISHSANITY_AGE_SPLIT, RSK_SHUFFLE_FISHING_POLE, + RSK_INFINITE_UPGRADES, RSK_SKELETON_KEY, RSK_SHUFFLE_DEKU_STICK_BAG, RSK_SHUFFLE_DEKU_NUT_BAG, @@ -3856,6 +3873,13 @@ typedef enum { RO_FISHSANITY_BOTH } RandoOptionsFishsanity; +//Infinite Upgrades settings (off, progressive, condensed progressive) +typedef enum { + RO_INF_UPGRADES_OFF, + RO_INF_UPGRADES_PROGRESSIVE, + RO_INF_UPGRADES_CONDENSED_PROGRESSIVE, +} RandoOptionInfiniteUpgrades; + //Any Dungeon Item (start with, vanilla, own dungeon, any dungeon, //overworld, anywhere) typedef enum { diff --git a/soh/soh/Enhancements/randomizer/randomizer_inf.h b/soh/soh/Enhancements/randomizer/randomizer_inf.h index 72168f018..8a9e8be1f 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_inf.h +++ b/soh/soh/Enhancements/randomizer/randomizer_inf.h @@ -257,6 +257,15 @@ typedef enum { RAND_INF_ZD_FISH_4, RAND_INF_ZD_FISH_5, + RAND_INF_HAS_INFINITE_QUIVER, + RAND_INF_HAS_INFINITE_BOMB_BAG, + RAND_INF_HAS_INFINITE_BULLET_BAG, + RAND_INF_HAS_INFINITE_STICK_UPGRADE, + RAND_INF_HAS_INFINITE_NUT_UPGRADE, + RAND_INF_HAS_INFINITE_MAGIC_METER, + RAND_INF_HAS_INFINITE_BOMBCHUS, + RAND_INF_HAS_INFINITE_MONEY, + RAND_INF_HAS_SKELETON_KEY, RAND_INF_LINKS_POCKET, diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index 28f341631..f3077cf3e 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -184,6 +184,7 @@ void Settings::CreateOptions() { // TODO: Compasses show rewards/woth, maps show dungeon mode mOptions[RSK_BLUE_FIRE_ARROWS] = Option::Bool("Blue Fire Arrows", CVAR_RANDOMIZER_SETTING("BlueFireArrows"), mOptionDescriptions[RSK_BLUE_FIRE_ARROWS]); mOptions[RSK_SUNLIGHT_ARROWS] = Option::Bool("Sunlight Arrows", CVAR_RANDOMIZER_SETTING("SunlightArrows"), mOptionDescriptions[RSK_SUNLIGHT_ARROWS]); + mOptions[RSK_INFINITE_UPGRADES] = Option::U8("Infinite Upgrades", {"Off", "Progressive", "Condensed Progressive"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("InfiniteUpgrades"), mOptionDescriptions[RSK_INFINITE_UPGRADES]); mOptions[RSK_SKELETON_KEY] = Option::Bool("Skeleton Key", CVAR_RANDOMIZER_SETTING("SkeletonKey"), mOptionDescriptions[RSK_SKELETON_KEY]); mOptions[RSK_ITEM_POOL] = Option::U8("Item Pool", {"Plentiful", "Balanced", "Scarce", "Minimal"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ItemPool"), mOptionDescriptions[RSK_ITEM_POOL], WidgetType::Combobox, RO_ITEM_POOL_BALANCED); mOptions[RSK_ICE_TRAPS] = Option::U8("Ice Traps", {"Off", "Normal", "Extra", "Mayhem", "Onslaught"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("IceTraps"), mOptionDescriptions[RSK_ICE_TRAPS], WidgetType::Combobox, RO_ICE_TRAPS_NORMAL); @@ -766,6 +767,7 @@ void Settings::CreateOptions() { &mOptions[RSK_ENABLE_BOMBCHU_DROPS], &mOptions[RSK_BLUE_FIRE_ARROWS], &mOptions[RSK_SUNLIGHT_ARROWS], + &mOptions[RSK_INFINITE_UPGRADES], &mOptions[RSK_SKELETON_KEY], }, false, WidgetContainerType::COLUMN); mOptionGroups[RSG_GAMEPLAY_IMGUI_TABLE] = OptionGroup::SubGroup("Gameplay", { @@ -994,6 +996,7 @@ void Settings::CreateOptions() { &mOptions[RSK_DAMAGE_MULTIPLIER], &mOptions[RSK_BLUE_FIRE_ARROWS], &mOptions[RSK_SUNLIGHT_ARROWS], + &mOptions[RSK_INFINITE_UPGRADES], &mOptions[RSK_SKELETON_KEY], }); mOptionGroups[RSG_ITEM_POOL] = OptionGroup("Item Pool Settings", std::initializer_list({ @@ -1213,6 +1216,7 @@ void Settings::CreateOptions() { { "Miscellaneous Settings:Hint Distribution", RSK_HINT_DISTRIBUTION }, { "Miscellaneous Settings:Blue Fire Arrows", RSK_BLUE_FIRE_ARROWS }, { "Miscellaneous Settings:Sunlight Arrows", RSK_SUNLIGHT_ARROWS }, + { "Miscellaneous Settings:Infinite Upgrades", RSK_INFINITE_UPGRADES }, { "Miscellaneous Settings:Skeleton Key", RSK_SKELETON_KEY }, { "Timesaver Settings:Skip Child Zelda", RSK_SKIP_CHILD_ZELDA }, { "Start with Consumables", RSK_STARTING_CONSUMABLES }, @@ -2363,6 +2367,7 @@ void Settings::ParseJson(nlohmann::json spoilerFileJson) { case RSK_SKULLS_SUNS_SONG: case RSK_BLUE_FIRE_ARROWS: case RSK_SUNLIGHT_ARROWS: + case RSK_INFINITE_UPGRADES: case RSK_SKELETON_KEY: case RSK_BOMBCHUS_IN_LOGIC: case RSK_TOT_ALTAR_HINT: diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index 31b2a6d0b..0cfde00b7 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -2768,6 +2768,8 @@ u16 Randomizer_Item_Give(PlayState* play, GetItemEntry giEntry) { if (INV_CONTENT(ITEM_BOMBCHU) == ITEM_NONE) { INV_CONTENT(ITEM_BOMBCHU) = ITEM_BOMBCHU; AMMO(ITEM_BOMBCHU) = 20; + } else if (Randomizer_GetSettingValue(RSK_INFINITE_UPGRADES)) { + Flags_SetRandomizerInf(RAND_INF_HAS_INFINITE_BOMBCHUS); } else { AMMO(ITEM_BOMBCHU) += AMMO(ITEM_BOMBCHU) < 5 ? 10 : 5; if (AMMO(ITEM_BOMBCHU) > 50) { @@ -2796,6 +2798,46 @@ u16 Randomizer_Item_Give(PlayState* play, GetItemEntry giEntry) { return Return_Item_Entry(giEntry, RG_NONE); } + if (item == RG_QUIVER_INF) { + Flags_SetRandomizerInf(RAND_INF_HAS_INFINITE_QUIVER); + return Return_Item_Entry(giEntry, RG_NONE); + } + + if (item == RG_BOMB_BAG_INF) { + Flags_SetRandomizerInf(RAND_INF_HAS_INFINITE_BOMB_BAG); + return Return_Item_Entry(giEntry, RG_NONE); + } + + if (item == RG_BULLET_BAG_INF) { + Flags_SetRandomizerInf(RAND_INF_HAS_INFINITE_BULLET_BAG); + return Return_Item_Entry(giEntry, RG_NONE); + } + + if (item == RG_STICK_UPGRADE_INF) { + Flags_SetRandomizerInf(RAND_INF_HAS_INFINITE_STICK_UPGRADE); + return Return_Item_Entry(giEntry, RG_NONE); + } + + if (item == RG_NUT_UPGRADE_INF) { + Flags_SetRandomizerInf(RAND_INF_HAS_INFINITE_NUT_UPGRADE); + return Return_Item_Entry(giEntry, RG_NONE); + } + + if (item == RG_MAGIC_INF) { + Flags_SetRandomizerInf(RAND_INF_HAS_INFINITE_MAGIC_METER); + return Return_Item_Entry(giEntry, RG_NONE); + } + + if (item == RG_BOMBCHU_INF) { + Flags_SetRandomizerInf(RAND_INF_HAS_INFINITE_BOMBCHUS); + return Return_Item_Entry(giEntry, RG_NONE); + } + + if (item == RG_WALLET_INF) { + Flags_SetRandomizerInf(RAND_INF_HAS_INFINITE_MONEY); + return Return_Item_Entry(giEntry, RG_NONE); + } + if (item == RG_SKELETON_KEY) { Flags_SetRandomizerInf(RAND_INF_HAS_SKELETON_KEY); return Return_Item_Entry(giEntry, RG_NONE); @@ -3578,21 +3620,23 @@ void Interface_UpdateMagicBar(PlayState* play) { break; case MAGIC_STATE_CONSUME: - gSaveContext.magic -= 2; - if (gSaveContext.magic <= 0) { - gSaveContext.magic = 0; - gSaveContext.magicState = MAGIC_STATE_METER_FLASH_1; - if (CVarGetInteger(CVAR_COSMETIC("Consumable.MagicBorder.Changed"), 0)) { - sMagicBorder = CVarGetColor24(CVAR_COSMETIC("Consumable.MagicBorder.Value"), sMagicBorder_ori); - } else { - sMagicBorder = sMagicBorder_ori; - } - } else if (gSaveContext.magic == gSaveContext.magicTarget) { - gSaveContext.magicState = MAGIC_STATE_METER_FLASH_1; - if (CVarGetInteger(CVAR_COSMETIC("Consumable.MagicBorder.Changed"), 0)) { - sMagicBorder = CVarGetColor24(CVAR_COSMETIC("Consumable.MagicBorder.Value"), sMagicBorder_ori); - } else { - sMagicBorder = sMagicBorder_ori; + if (!Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_MAGIC_METER)) { + gSaveContext.magic -= 2; + if (gSaveContext.magic <= 0) { + gSaveContext.magic = 0; + gSaveContext.magicState = MAGIC_STATE_METER_FLASH_1; + if (CVarGetInteger(CVAR_COSMETIC("Consumable.MagicBorder.Changed"), 0)) { + sMagicBorder = CVarGetColor24(CVAR_COSMETIC("Consumable.MagicBorder.Value"), sMagicBorder_ori); + } else { + sMagicBorder = sMagicBorder_ori; + } + } else if (gSaveContext.magic == gSaveContext.magicTarget) { + gSaveContext.magicState = MAGIC_STATE_METER_FLASH_1; + if (CVarGetInteger(CVAR_COSMETIC("Consumable.MagicBorder.Changed"), 0)) { + sMagicBorder = CVarGetColor24(CVAR_COSMETIC("Consumable.MagicBorder.Value"), sMagicBorder_ori); + } else { + sMagicBorder = sMagicBorder_ori; + } } } case MAGIC_STATE_METER_FLASH_1: @@ -3756,6 +3800,7 @@ void Interface_DrawMagicBar(PlayState* play) { s16 magicBarY; Color_RGB8 magicbar_yellow = {250,250,0}; //Magic bar being used Color_RGB8 magicbar_green = {R_MAGIC_FILL_COLOR(0),R_MAGIC_FILL_COLOR(1),R_MAGIC_FILL_COLOR(2)}; //Magic bar fill + Color_RGB8 magicbar_blue = {0,0,200};//Infinite magic bar if (CVarGetInteger(CVAR_COSMETIC("Consumable.MagicActive.Changed"), 0)) { magicbar_yellow = CVarGetColor24(CVAR_COSMETIC("Consumable.MagicActive.Value"), magicbar_yellow); @@ -3763,6 +3808,9 @@ void Interface_DrawMagicBar(PlayState* play) { if (CVarGetInteger(CVAR_COSMETIC("Consumable.Magic.Changed"), 0)) { magicbar_green = CVarGetColor24(CVAR_COSMETIC("Consumable.Magic.Value"), magicbar_green); } + if (CVarGetInteger("gCosmetics.Consumable_MagicInfinite.Changed", 0)) { + magicbar_blue = CVarGetColor24("gCosmetics.Consumable_MagicInfinite.Value", magicbar_blue); + } OPEN_DISPS(play->state.gfxCtx); @@ -3870,14 +3918,26 @@ void Interface_DrawMagicBar(PlayState* play) { // Fill the rest of the bar with the normal magic color gDPPipeSync(OVERLAY_DISP++); - gDPSetPrimColor(OVERLAY_DISP++, 0, 0, magicbar_green.r, magicbar_green.g, magicbar_green.b, interfaceCtx->magicAlpha); + if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_MAGIC_METER)) { + // Blue magic + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, magicbar_blue.r, magicbar_blue.g, magicbar_blue.b, interfaceCtx->magicAlpha); + } else { + // Green magic (default) + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, magicbar_green.r, magicbar_green.g, magicbar_green.b, interfaceCtx->magicAlpha); + } gSPWideTextureRectangle(OVERLAY_DISP++, rMagicFillX << 2, (magicBarY + 3) << 2, (rMagicFillX + gSaveContext.magicTarget) << 2, (magicBarY + 10) << 2, G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10); } else { // Fill the whole bar with the normal magic color - gDPSetPrimColor(OVERLAY_DISP++, 0, 0, magicbar_green.r, magicbar_green.g, magicbar_green.b, interfaceCtx->magicAlpha); + if (Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_MAGIC_METER)) { + // Blue magic + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, magicbar_blue.r, magicbar_blue.g, magicbar_blue.b, interfaceCtx->magicAlpha); + } else { + // Green magic (default) + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, magicbar_green.r, magicbar_green.g, magicbar_green.b, interfaceCtx->magicAlpha); + } gDPLoadMultiBlock_4b(OVERLAY_DISP++, gMagicMeterFillTex, 0, G_TX_RENDERTILE, G_IM_FMT_I, 16, 16, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, @@ -5021,10 +5081,25 @@ void Interface_DrawAmmoCount(PlayState* play, s16 button, s16 alpha) { i = gSaveContext.equips.buttonItems[button]; - if ((i == ITEM_STICK) || (i == ITEM_NUT) || (i == ITEM_BOMB) || (i == ITEM_BOW) || - ((i >= ITEM_BOW_ARROW_FIRE) && (i <= ITEM_BOW_ARROW_LIGHT)) || (i == ITEM_SLINGSHOT) || (i == ITEM_BOMBCHU) || - (i == ITEM_BEAN)) { - + if ( + GameInteractor_Should( + VB_DRAW_AMMO_COUNT, + ( + (i == ITEM_STICK) || + (i == ITEM_NUT) || + (i == ITEM_BOMB) || + (i == ITEM_BOW) || + ( + (i >= ITEM_BOW_ARROW_FIRE) && + (i <= ITEM_BOW_ARROW_LIGHT) + ) || + (i == ITEM_SLINGSHOT) || + (i == ITEM_BOMBCHU) || + (i == ITEM_BEAN) + ), + &i + ) + ) { if ((i >= ITEM_BOW_ARROW_FIRE) && (i <= ITEM_BOW_ARROW_LIGHT)) { i = ITEM_BOW; } @@ -5297,8 +5372,8 @@ void Interface_Draw(PlayState* play) { if (fullUi) { s16 PosX_RC; s16 PosY_RC; - //when not having a wallet in rando, don't calculate the ruppe icon - if (!IS_RANDO || Flags_GetRandomizerInf(RAND_INF_HAS_WALLET)) { + //when not having a wallet (or infinite money) in rando, don't calculate the ruppe icon + if (!IS_RANDO || (Flags_GetRandomizerInf(RAND_INF_HAS_WALLET) && !Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_MONEY))) { // Rupee Icon if (CVarGetInteger(CVAR_ENHANCEMENT("DynamicWalletIcon"), 0)) { switch (CUR_UPG_VALUE(UPG_WALLET)) { diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c index 83b734156..d34ce4d8a 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c @@ -6,6 +6,9 @@ #include "soh/Enhancements/enhancementTypes.h" #include "soh/Enhancements/cosmetics/cosmeticsTypes.h" +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" + u8 gAmmoItems[] = { ITEM_STICK, ITEM_NUT, ITEM_BOMB, ITEM_BOW, ITEM_NONE, ITEM_NONE, ITEM_SLINGSHOT, ITEM_NONE, ITEM_BOMBCHU, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_BEAN, ITEM_NONE, @@ -37,6 +40,10 @@ s8 ItemInSlotUsesAmmo(s16 slot) { } void KaleidoScope_DrawAmmoCount(PauseContext* pauseCtx, GraphicsContext* gfxCtx, s16 item, int slot) { + if (!GameInteractor_Should(VB_DRAW_AMMO_COUNT, true, &item)) { + return; + } + s16 ammo; s16 i;