Rando: Infinite upgrades (Rando V3) (#3942)

* Infinite Upgrades

* Add "Condensed Progressive"

* VB & fix build

* Update settings.cpp
This commit is contained in:
Pepe20129 2024-07-22 18:54:14 +02:00 committed by GitHub
parent 081a55ab29
commit 3bcd93428e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 499 additions and 50 deletions

View File

@ -220,6 +220,7 @@ static std::map<std::string, CosmeticOption> 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),

View File

@ -596,6 +596,15 @@ const std::vector<FlagTable> 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" },

View File

@ -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 ***/

View File

@ -1694,6 +1694,46 @@ void RegisterFishsanity() {
});
}
void RegisterInfiniteUpgrades() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
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();

View File

@ -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
{

View File

@ -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)) {

View File

@ -1113,6 +1113,24 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void
}
break;
}
case VB_DRAW_AMMO_COUNT: {
s16 item = *static_cast<s16*>(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:

View File

@ -119,6 +119,7 @@ std::shared_ptr<GetItemEntry> 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<GetItemEntry> Item::GetGIEntry() const { // NOLINT(*-no-recursio
break;
}
case 1:
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<GetItemEntry> Item::GetGIEntry() const { // NOLINT(*-no-recursio
break;
}
case 1:
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<GetItemEntry> Item::GetGIEntry() const { // NOLINT(*-no-recursio
actual = RG_BOMB_BAG;
break;
case 1:
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<GetItemEntry> Item::GetGIEntry() const { // NOLINT(*-no-recursio
actual = RG_FAIRY_BOW;
break;
case 1:
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<GetItemEntry> Item::GetGIEntry() const { // NOLINT(*-no-recursio
actual = RG_FAIRY_SLINGSHOT;
break;
case 1:
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<GetItemEntry> 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<GetItemEntry> 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<GetItemEntry> 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;

View File

@ -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);

View File

@ -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.";

View File

@ -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<GetItemMessage, 77> getItemMessages = {{
const std::array<GetItemMessage, 85> 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!"),

View File

@ -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 {

View File

@ -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,

View File

@ -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<Option*>({
@ -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:

View File

@ -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,6 +3620,7 @@ void Interface_UpdateMagicBar(PlayState* play) {
break;
case MAGIC_STATE_CONSUME:
if (!Flags_GetRandomizerInf(RAND_INF_HAS_INFINITE_MAGIC_METER)) {
gSaveContext.magic -= 2;
if (gSaveContext.magic <= 0) {
gSaveContext.magic = 0;
@ -3595,6 +3638,7 @@ void Interface_UpdateMagicBar(PlayState* play) {
sMagicBorder = sMagicBorder_ori;
}
}
}
case MAGIC_STATE_METER_FLASH_1:
case MAGIC_STATE_METER_FLASH_2:
case MAGIC_STATE_METER_FLASH_3:
@ -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++);
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
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)) {

View File

@ -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;