Add 5, 6 & 7 item shopsanity. (#4280)

* Format shops.cpp

* Add 5, 6 & 7 item shopsanity

* Guarantee a bombchu refill

* Fish first shop item index

* Clean up NonShopItems

* Split count options

* Improve item ordering

Ensure potions, blue fire and fairy on shopsanity 6 and less.
There are no hearts in the first 28 items (the ones from n64 rando).

* Post-merge fixes
This commit is contained in:
Pepe20129 2024-10-03 01:31:11 +02:00 committed by GitHub
parent 7110e40374
commit 84130b8046
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 1095 additions and 892 deletions

View File

@ -1320,7 +1320,16 @@ void DrawEquipmentTab() {
"Giant (500)", "Giant (500)",
}; };
// only display Tycoon wallet if you're in a save file that would allow it. // only display Tycoon wallet if you're in a save file that would allow it.
if (IS_RANDO && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHOPSANITY) > RO_SHOPSANITY_ZERO_ITEMS) { if (
IS_RANDO &&
!(
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHOPSANITY) == RO_SHOPSANITY_OFF ||
(
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHOPSANITY) == RO_SHOPSANITY_SPECIFIC_COUNT &&
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHOPSANITY_COUNT) == RO_SHOPSANITY_COUNT_ZERO_ITEMS
)
)
) {
const std::string walletName = "Tycoon (999)"; const std::string walletName = "Tycoon (999)";
walletNamesImpl.push_back(walletName); walletNamesImpl.push_back(walletName);
} }

View File

@ -1121,7 +1121,8 @@ const std::vector<PresetEntry> hellModePresetEntries = {
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("LinksPocket"), RO_LINKS_POCKET_NOTHING), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("LinksPocket"), RO_LINKS_POCKET_NOTHING),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("MQDungeons"), RO_MQ_DUNGEONS_RANDOM_NUMBER), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("MQDungeons"), RO_MQ_DUNGEONS_RANDOM_NUMBER),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("RainbowBridge"), RO_BRIDGE_DUNGEON_REWARDS), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("RainbowBridge"), RO_BRIDGE_DUNGEON_REWARDS),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("Shopsanity"), RO_SHOPSANITY_FOUR_ITEMS), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("Shopsanity"), RO_SHOPSANITY_SPECIFIC_COUNT),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShopsanityCount"), RO_SHOPSANITY_COUNT_FOUR_ITEMS),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShopsanityPrices"), RO_SHOPSANITY_PRICE_TYCOON), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShopsanityPrices"), RO_SHOPSANITY_PRICE_TYCOON),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleAdultTrade"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleAdultTrade"), 1),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleBeans"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleBeans"), 1),
@ -1177,7 +1178,7 @@ const std::vector<PresetEntry> BenchmarkPresetEntries = {
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleDungeonReward"), RO_DUNGEON_REWARDS_END_OF_DUNGEON), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleDungeonReward"), RO_DUNGEON_REWARDS_END_OF_DUNGEON),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("LinksPocket"), RO_LINKS_POCKET_DUNGEON_REWARD), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("LinksPocket"), RO_LINKS_POCKET_DUNGEON_REWARD),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleSongs"), RO_SONG_SHUFFLE_ANYWHERE), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleSongs"), RO_SONG_SHUFFLE_ANYWHERE),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("Shopsanity"), RO_SHOPSANITY_FOUR_ITEMS), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("Shopsanity"), RO_SHOPSANITY_COUNT_FOUR_ITEMS),
//RANDOTODO add refactored price/scrub/merchant settings //RANDOTODO add refactored price/scrub/merchant settings
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleTokens"), RO_TOKENSANITY_OFF), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleTokens"), RO_TOKENSANITY_OFF),
PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleBeehives"), RO_GENERIC_ON), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("ShuffleBeehives"), RO_GENERIC_ON),

View File

@ -1158,7 +1158,7 @@ int Fill() {
//Temporarily add shop items to the ItemPool so that entrance randomization //Temporarily add shop items to the ItemPool so that entrance randomization
//can validate the world using deku/hylian shields //can validate the world using deku/hylian shields
StartPerformanceTimer(PT_ENTRANCE_SHUFFLE); StartPerformanceTimer(PT_ENTRANCE_SHUFFLE);
AddElementsToPool(ItemPool, GetMinVanillaShopItems(32)); //assume worst case shopsanity 4 AddElementsToPool(ItemPool, GetMinVanillaShopItems(8)); //assume worst case shopsanity 7
if (ctx->GetOption(RSK_SHUFFLE_ENTRANCES)) { if (ctx->GetOption(RSK_SHUFFLE_ENTRANCES)) {
SPDLOG_INFO("Shuffling Entrances..."); SPDLOG_INFO("Shuffling Entrances...");
if (ctx->GetEntranceShuffler()->ShuffleAllEntrances() == ENTRANCE_SHUFFLE_FAILURE) { if (ctx->GetEntranceShuffler()->ShuffleAllEntrances() == ENTRANCE_SHUFFLE_FAILURE) {
@ -1177,34 +1177,39 @@ int Fill() {
//Place shop items first, since a buy shield is needed to place a dungeon reward on Gohma due to access //Place shop items first, since a buy shield is needed to place a dungeon reward on Gohma due to access
StartPerformanceTimer(PT_SHOPSANITY); StartPerformanceTimer(PT_SHOPSANITY);
NonShopItems = {}; NonShopItems.clear();
if (ctx->GetOption(RSK_SHOPSANITY).Is(RO_SHOPSANITY_OFF)) { if (ctx->GetOption(RSK_SHOPSANITY).Is(RO_SHOPSANITY_OFF)) {
SPDLOG_INFO("Placing Vanilla Shop Items..."); SPDLOG_INFO("Placing Vanilla Shop Items...");
PlaceVanillaShopItems(); //Place vanilla shop items in vanilla location PlaceVanillaShopItems(); //Place vanilla shop items in vanilla location
} else { } else {
SPDLOG_INFO("Shuffling Shop Items"); SPDLOG_INFO("Shuffling Shop Items");
int total_replaced = 0; int total_replaced = 0;
if (ctx->GetOption(RSK_SHOPSANITY).IsNot(RO_SHOPSANITY_ZERO_ITEMS)) { //Shopsanity 1-4, random if (ctx->GetOption(RSK_SHOPSANITY).Is(RO_SHOPSANITY_RANDOM) || ctx->GetOption(RSK_SHOPSANITY_COUNT).IsNot(RO_SHOPSANITY_COUNT_ZERO_ITEMS)) { //Shopsanity 1-7, random
//Initialize NonShopItems /*
ItemAndPrice init; Indices from OoTR. So shopsanity one will overwrite 7, three will overwrite 7, 5, 8, etc.
init.Name = Text{"No Item", "Sin objeto", "Pas d'objet"}; 8 6 2 4
init.Price = -1; 7 5 1 3
init.Repurchaseable = false; */
NonShopItems.assign(32, init); const std::array<int, 8> indices = { 7, 5, 8, 6, 3, 1, 4, 2 };
//Indices from OoTR. So shopsanity one will overwrite 7, three will overwrite 7, 5, 8, etc.
const std::array<int, 4> indices = {7, 5, 8, 6};
//Overwrite appropriate number of shop items //Overwrite appropriate number of shop items
#define LOCATIONS_PER_SHOP 8 #define LOCATIONS_PER_SHOP 8
for (size_t i = 0; i < Rando::StaticData::GetShopLocations().size() / LOCATIONS_PER_SHOP; i++) { for (size_t i = 0; i < Rando::StaticData::GetShopLocations().size() / LOCATIONS_PER_SHOP; i++) {
int num_to_replace = GetShopsanityReplaceAmount(); //1-4 shop items will be overwritten, depending on settings int num_to_replace = GetShopsanityReplaceAmount(); //1-7 shop items will be overwritten, depending on settings
total_replaced += num_to_replace; total_replaced += num_to_replace;
for (int j = 0; j < num_to_replace; j++) { for (int j = 0; j < num_to_replace; j++) {
int itemindex = indices[j]; int itemindex = indices[j];
int shopsanityPrice = GetRandomShopPrice(); int shopsanityPrice = GetRandomShopPrice();
NonShopItems[TransformShopIndex(i * LOCATIONS_PER_SHOP + itemindex - 1)].Price = NonShopItems[Rando::StaticData::GetShopLocations()[i * LOCATIONS_PER_SHOP + itemindex - 1]].Price = shopsanityPrice; // Set price to be retrieved by the patch and textboxes
shopsanityPrice; // Set price to be retrieved by the patch and textboxes
ctx->GetItemLocation(Rando::StaticData::GetShopLocations()[i * LOCATIONS_PER_SHOP + itemindex - 1])->SetCustomPrice(shopsanityPrice); ctx->GetItemLocation(Rando::StaticData::GetShopLocations()[i * LOCATIONS_PER_SHOP + itemindex - 1])->SetCustomPrice(shopsanityPrice);
} }
for (int j = num_to_replace; j < 8; j++) {
ItemAndPrice init;
init.Name = Text { "No Item", "Sin objeto", "Pas d'objet" };
init.Price = -1;
init.Repurchaseable = false;
int itemindex = indices[j];
NonShopItems[Rando::StaticData::GetShopLocations()[i * LOCATIONS_PER_SHOP + itemindex - 1]] = init; // Set price to be retrieved by the patch and textboxes
}
} }
#undef LOCATIONS_PER_SHOP #undef LOCATIONS_PER_SHOP
} }

View File

@ -1159,9 +1159,15 @@ void GenerateItemPool() {
} }
//Shopsanity //Shopsanity
if (ctx->GetOption(RSK_SHOPSANITY).Is(RO_SHOPSANITY_OFF) || ctx->GetOption(RSK_SHOPSANITY).Is(RO_SHOPSANITY_ZERO_ITEMS)) { if (
ctx->GetOption(RSK_SHOPSANITY).Is(RO_SHOPSANITY_OFF) ||
(
ctx->GetOption(RSK_SHOPSANITY).Is(RO_SHOPSANITY_SPECIFIC_COUNT) &&
ctx->GetOption(RSK_SHOPSANITY_COUNT).Is(RO_SHOPSANITY_COUNT_ZERO_ITEMS)
)
) {
AddItemsToPool(ItemPool, normalRupees); AddItemsToPool(ItemPool, normalRupees);
} else { //Shopsanity 1-4, random } else {
AddItemsToPool(ItemPool, shopsanityRupees); //Shopsanity gets extra large rupees AddItemsToPool(ItemPool, shopsanityRupees); //Shopsanity gets extra large rupees
} }

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,6 @@
#include "../context.h" #include "../context.h"
#include <vector> #include <vector>
#include <array>
struct ItemAndPrice { struct ItemAndPrice {
Text Name; Text Name;
@ -16,7 +15,5 @@ extern int GetRandomShopPrice();
extern int16_t GetRandomScrubPrice(); extern int16_t GetRandomScrubPrice();
extern int GetShopsanityReplaceAmount(); extern int GetShopsanityReplaceAmount();
extern Text GetIceTrapName(uint8_t id); extern Text GetIceTrapName(uint8_t id);
extern int GetShopIndex(RandomizerCheck loc);
extern int TransformShopIndex(int index);
extern std::vector<ItemAndPrice> NonShopItems; extern std::map<RandomizerCheck, ItemAndPrice> NonShopItems;

View File

@ -160,7 +160,7 @@ void WriteIngameSpoilerLog() {
// PURPLE TODO: LOCALIZATION // PURPLE TODO: LOCALIZATION
auto locItem = itemLocation->GetPlacedItemName().GetEnglish(); auto locItem = itemLocation->GetPlacedItemName().GetEnglish();
if (itemLocation->GetPlacedRandomizerGet() == RG_ICE_TRAP && loc->GetRCType() == RCTYPE_SHOP) { if (itemLocation->GetPlacedRandomizerGet() == RG_ICE_TRAP && loc->GetRCType() == RCTYPE_SHOP) {
locItem = NonShopItems[TransformShopIndex(GetShopIndex(key))].Name.GetEnglish(); locItem = NonShopItems[key].Name.GetEnglish();
} }
if (stringOffsetMap.find(locItem) == stringOffsetMap.end()) { if (stringOffsetMap.find(locItem) == stringOffsetMap.end()) {
if (spoilerStringOffset + locItem.size() + 1 >= SPOILER_STRING_DATA_SIZE) { if (spoilerStringOffset + locItem.size() + 1 >= SPOILER_STRING_DATA_SIZE) {

View File

@ -106,9 +106,8 @@ void Context::PlaceItemInLocation(const RandomizerCheck locKey, const Randomizer
// If we're placing a non-shop item in a shop location, we want to record it for custom messages // If we're placing a non-shop item in a shop location, we want to record it for custom messages
if (StaticData::RetrieveItem(item).GetItemType() != ITEMTYPE_SHOP && if (StaticData::RetrieveItem(item).GetItemType() != ITEMTYPE_SHOP &&
StaticData::GetLocation(locKey)->GetRCType() == RCTYPE_SHOP) { StaticData::GetLocation(locKey)->GetRCType() == RCTYPE_SHOP) {
const int index = TransformShopIndex(GetShopIndex(locKey)); NonShopItems[locKey].Name = StaticData::RetrieveItem(item).GetName();
NonShopItems[index].Name = StaticData::RetrieveItem(item).GetName(); NonShopItems[locKey].Repurchaseable =
NonShopItems[index].Repurchaseable =
StaticData::RetrieveItem(item).GetItemType() == ITEMTYPE_REFILL || StaticData::RetrieveItem(item).GetItemType() == ITEMTYPE_REFILL ||
StaticData::RetrieveItem(item).GetHintKey() == RHT_PROGRESSIVE_BOMBCHUS; StaticData::RetrieveItem(item).GetHintKey() == RHT_PROGRESSIVE_BOMBCHUS;
} }
@ -214,7 +213,7 @@ void Context::CreateItemOverrides() {
val.SetTrickName(GetIceTrapName(val.LooksLike())); val.SetTrickName(GetIceTrapName(val.LooksLike()));
// If this is ice trap is in a shop, change the name based on what the model will look like // If this is ice trap is in a shop, change the name based on what the model will look like
if (loc->GetRCType() == RCTYPE_SHOP) { if (loc->GetRCType() == RCTYPE_SHOP) {
NonShopItems[TransformShopIndex(GetShopIndex(locKey))].Name = val.GetTrickName(); NonShopItems[locKey].Name = val.GetTrickName();
} }
overrides[locKey] = val; overrides[locKey] = val;
} }

View File

@ -81,16 +81,22 @@ std::shared_ptr<GetItemEntry> Item::GetGIEntry() const { // NOLINT(*-no-recursio
if (giEntry != nullptr) { if (giEntry != nullptr) {
return giEntry; return giEntry;
} }
auto logic = Rando::Context::GetInstance()->GetLogic(); std::shared_ptr<Rando::Context> ctx = Rando::Context::GetInstance();
auto logic = ctx->GetLogic();
RandomizerGet actual = RG_NONE; RandomizerGet actual = RG_NONE;
const bool tycoonWallet = const bool tycoonWallet = !(
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHOPSANITY) > RO_SHOPSANITY_ZERO_ITEMS; ctx->GetOption(RSK_SHOPSANITY).Is(RO_SHOPSANITY_OFF) ||
const u8 infiniteUpgrades = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_INFINITE_UPGRADES); (
ctx->GetOption(RSK_SHOPSANITY).Is(RO_SHOPSANITY_SPECIFIC_COUNT) &&
ctx->GetOption(RSK_SHOPSANITY_COUNT).Is(RO_SHOPSANITY_COUNT_ZERO_ITEMS)
)
);
const u8 infiniteUpgrades = ctx->GetOption(RSK_INFINITE_UPGRADES).Value<u8>();
switch (randomizerGet) { switch (randomizerGet) {
case RG_PROGRESSIVE_STICK_UPGRADE: case RG_PROGRESSIVE_STICK_UPGRADE:
switch (logic->CurrentUpgrade(UPG_STICKS)) { switch (logic->CurrentUpgrade(UPG_STICKS)) {
case 0: case 0:
if (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_DEKU_STICK_BAG)) { if (ctx->GetOption(RSK_SHUFFLE_DEKU_STICK_BAG)) {
actual = RG_DEKU_STICK_BAG; actual = RG_DEKU_STICK_BAG;
break; break;
} }
@ -119,7 +125,7 @@ std::shared_ptr<GetItemEntry> Item::GetGIEntry() const { // NOLINT(*-no-recursio
case RG_PROGRESSIVE_NUT_UPGRADE: case RG_PROGRESSIVE_NUT_UPGRADE:
switch (logic->CurrentUpgrade(UPG_NUTS)) { switch (logic->CurrentUpgrade(UPG_NUTS)) {
case 0: case 0:
if (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_DEKU_NUT_BAG)) { if (ctx->GetOption(RSK_SHUFFLE_DEKU_NUT_BAG)) {
actual = RG_DEKU_NUT_BAG; actual = RG_DEKU_NUT_BAG;
break; break;
} }

View File

@ -263,13 +263,19 @@ void Settings::CreateOptionDescriptions() {
"The deku nut bag is required to hold deku nuts."; "The deku nut bag is required to hold deku nuts.";
mOptionDescriptions[RSK_SHOPSANITY] = "Off - All shop items will be the same as vanilla.\n" mOptionDescriptions[RSK_SHOPSANITY] = "Off - All shop items will be the same as vanilla.\n"
"\n" "\n"
"0 Items - Vanilla shop items will be shuffled among different shops.\n" "Specifc Count - Vanilla shop items will be shuffled among different shops, and "
"\n" "each shop will contain a specifc number (0-7) of non-vanilla shop items.\n"
"1-4 Items - Vanilla shop items will be shuffled among different shops, and "
"each shop will contain 1-4 non-vanilla shop items.\n"
"\n" "\n"
"Random - Vanilla shop items will be shuffled among different shops, and " "Random - Vanilla shop items will be shuffled among different shops, and "
"each shop will contain a random number(1-4) of non-vanilla shop items.\n"; "each shop will contain a random number (1-7) of non-vanilla shop items.";
mOptionDescriptions[RSK_SHOPSANITY_COUNT] = "0 Items - Vanilla shop items will be shuffled among different shops.\n"
"\n"
"1-7 Items - Vanilla shop items will be shuffled among different shops, and "
"each shop will contain 1-7 non-vanilla shop items.\n"
/*
"\n"
"8 Items - All shops will contain 8 non-vanilla shop items.\n"
*/;
mOptionDescriptions[RSK_SHOPSANITY_PRICES] = mOptionDescriptions[RSK_SHOPSANITY_PRICES] =
"Balanced - The default randomization. Shop prices for shopsanity items will range between 0 to 300 rupees, " "Balanced - The default randomization. Shop prices for shopsanity items will range between 0 to 300 rupees, "
"with a bias towards values slightly below the middle of the range, in multiples of 5.\n " "with a bias towards values slightly below the middle of the range, in multiples of 5.\n "

View File

@ -367,7 +367,13 @@ ItemObtainability Randomizer::GetItemObtainabilityFromRandomizerGet(RandomizerGe
// Shopsanity with at least one item shuffled allows for a third wallet upgrade. // Shopsanity with at least one item shuffled allows for a third wallet upgrade.
// This is needed since Plentiful item pool also adds a third progressive wallet // This is needed since Plentiful item pool also adds a third progressive wallet
// but we should *not* get Tycoon's Wallet in that mode. // but we should *not* get Tycoon's Wallet in that mode.
bool tycoonWallet = GetRandoSettingValue(RSK_SHOPSANITY) > RO_SHOPSANITY_ZERO_ITEMS; bool tycoonWallet = !(
GetRandoSettingValue(RSK_SHOPSANITY) == RO_SHOPSANITY_OFF ||
(
GetRandoSettingValue(RSK_SHOPSANITY) == RO_SHOPSANITY_SPECIFIC_COUNT &&
GetRandoSettingValue(RSK_SHOPSANITY_COUNT) == RO_SHOPSANITY_COUNT_ZERO_ITEMS
)
);
// Same thing with the infinite upgrades, if we're not shuffling them // 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 // and we're using the Plentiful item pool, we should prevent the infinite
@ -1138,9 +1144,13 @@ ShopItemIdentity Randomizer::IdentifyShopItem(s32 sceneNum, u8 slotIndex) {
shopItemIdentity.itemPrice = -1; shopItemIdentity.itemPrice = -1;
shopItemIdentity.enGirlAShopItem = 0x32; shopItemIdentity.enGirlAShopItem = 0x32;
if (slotIndex == 0) {
return shopItemIdentity;
}
Rando::Location* location = GetCheckObjectFromActor(ACTOR_EN_GIRLA, Rando::Location* location = GetCheckObjectFromActor(ACTOR_EN_GIRLA,
// Bazaar (SHOP1) scene is reused, so if entering from Kak use debug scene to identify // Bazaar (SHOP1) scene is reused, so if entering from Kak use debug scene to identify
(sceneNum == SCENE_BAZAAR && gSaveContext.entranceIndex == ENTR_BAZAAR_0) ? SCENE_TEST01 : sceneNum, slotIndex); (sceneNum == SCENE_BAZAAR && gSaveContext.entranceIndex == ENTR_BAZAAR_0) ? SCENE_TEST01 : sceneNum, slotIndex - 1);
if (location->GetRandomizerCheck() != RC_UNKNOWN_CHECK) { if (location->GetRandomizerCheck() != RC_UNKNOWN_CHECK) {
shopItemIdentity.randomizerInf = rcToRandomizerInf[location->GetRandomizerCheck()]; shopItemIdentity.randomizerInf = rcToRandomizerInf[location->GetRandomizerCheck()];

View File

@ -3767,6 +3767,7 @@ typedef enum {
RSK_SHUFFLE_SONGS, RSK_SHUFFLE_SONGS,
RSK_SHUFFLE_TOKENS, RSK_SHUFFLE_TOKENS,
RSK_SHOPSANITY, RSK_SHOPSANITY,
RSK_SHOPSANITY_COUNT,
RSK_SHOPSANITY_PRICES, RSK_SHOPSANITY_PRICES,
RSK_SHOPSANITY_PRICES_AFFORDABLE, RSK_SHOPSANITY_PRICES_AFFORDABLE,
RSK_SHUFFLE_SCRUBS, RSK_SHUFFLE_SCRUBS,
@ -3976,17 +3977,26 @@ typedef enum {
RO_BRIDGE_WILDCARD_REWARD, RO_BRIDGE_WILDCARD_REWARD,
} RandoOptionBridgeRewards; } RandoOptionBridgeRewards;
//Shopsanity settings (off, 0-4 items, random) //Shopsanity settings (off, specific count, random)
typedef enum { typedef enum {
RO_SHOPSANITY_OFF, RO_SHOPSANITY_OFF,
RO_SHOPSANITY_ZERO_ITEMS, RO_SHOPSANITY_SPECIFIC_COUNT,
RO_SHOPSANITY_ONE_ITEM,
RO_SHOPSANITY_TWO_ITEMS,
RO_SHOPSANITY_THREE_ITEMS,
RO_SHOPSANITY_FOUR_ITEMS,
RO_SHOPSANITY_RANDOM, RO_SHOPSANITY_RANDOM,
} RandoOptionShopsanity; } RandoOptionShopsanity;
//Shopsanity count settings (0-7 items)
typedef enum {
RO_SHOPSANITY_COUNT_ZERO_ITEMS,
RO_SHOPSANITY_COUNT_ONE_ITEM,
RO_SHOPSANITY_COUNT_TWO_ITEMS,
RO_SHOPSANITY_COUNT_THREE_ITEMS,
RO_SHOPSANITY_COUNT_FOUR_ITEMS,
RO_SHOPSANITY_COUNT_FIVE_ITEMS,
RO_SHOPSANITY_COUNT_SIX_ITEMS,
RO_SHOPSANITY_COUNT_SEVEN_ITEMS,
RO_SHOPSANITY_COUNT_EIGHT_ITEMS,
} RandoOptionShopsanityCount;
//Shopsanity price ranges //Shopsanity price ranges
typedef enum { typedef enum {
RO_SHOPSANITY_PRICE_BALANCED, //Balanced random from 0-300 RO_SHOPSANITY_PRICE_BALANCED, //Balanced random from 0-300

View File

@ -119,8 +119,16 @@ void RandomizerCheckObjects::UpdateImGuiVisibility() {
(CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeons"), RO_MQ_DUNGEONS_NONE) != RO_MQ_DUNGEONS_SET_NUMBER || (CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeons"), RO_MQ_DUNGEONS_NONE) != RO_MQ_DUNGEONS_SET_NUMBER ||
CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeonCount"), 12) < 12) // at least one vanilla dungeon CVarGetInteger(CVAR_RANDOMIZER_SETTING("MQDungeonCount"), 12) < 12) // at least one vanilla dungeon
) && ) &&
(location.GetRCType() != RCTYPE_SHOP || (
CVarGetInteger(CVAR_RANDOMIZER_SETTING("Shopsanity"), RO_SHOPSANITY_OFF) > RO_SHOPSANITY_ZERO_ITEMS) && location.GetRCType() != RCTYPE_SHOP ||
!(
ctx->GetOption(RSK_SHOPSANITY).Is(RO_SHOPSANITY_OFF) ||
(
ctx->GetOption(RSK_SHOPSANITY).Is(RO_SHOPSANITY_SPECIFIC_COUNT) &&
ctx->GetOption(RSK_SHOPSANITY_COUNT).Is(RO_SHOPSANITY_COUNT_ZERO_ITEMS)
)
)
) &&
(location.GetRCType() != RCTYPE_SCRUB || (location.GetRCType() != RCTYPE_SCRUB ||
CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleScrubs"), RO_SCRUBS_OFF) != RO_SCRUBS_OFF || CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleScrubs"), RO_SCRUBS_OFF) != RO_SCRUBS_OFF ||
location.GetRandomizerCheck() == RC_HF_DEKU_SCRUB_GROTTO || location.GetRandomizerCheck() == RC_HF_DEKU_SCRUB_GROTTO ||

View File

@ -1101,12 +1101,11 @@ void EndFloatWindows() {
} }
void LoadSettings() { void LoadSettings() {
//If in randomzer (n64ddFlag), then get the setting and check if in general we should be showing the settings //If in randomzer, then get the setting and check if in general we should be showing the settings
//If in vanilla, _try_ to show items that at least are needed for 100% //If in vanilla, _try_ to show items that at least are needed for 100%
showShops = IS_RANDO ? ( showShops = IS_RANDO ?
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHOPSANITY) != RO_SHOPSANITY_OFF && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHOPSANITY) != RO_SHOPSANITY_OFF
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHOPSANITY) != RO_SHOPSANITY_ZERO_ITEMS)
: false; : false;
showBeans = IS_RANDO ? showBeans = IS_RANDO ?
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_MAGIC_BEANS) == RO_GENERIC_YES OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_MAGIC_BEANS) == RO_GENERIC_YES

View File

@ -390,7 +390,13 @@ ItemTrackerNumbers GetItemCurrentAndMax(ItemTrackerItem item) {
case ITEM_WALLET_ADULT: case ITEM_WALLET_ADULT:
case ITEM_WALLET_GIANT: case ITEM_WALLET_GIANT:
result.currentCapacity = IS_RANDO && !Flags_GetRandomizerInf(RAND_INF_HAS_WALLET) ? 0 : CUR_CAPACITY(UPG_WALLET); result.currentCapacity = IS_RANDO && !Flags_GetRandomizerInf(RAND_INF_HAS_WALLET) ? 0 : CUR_CAPACITY(UPG_WALLET);
result.maxCapacity = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHOPSANITY) > RO_SHOPSANITY_ZERO_ITEMS ? 999 : 500; result.maxCapacity = !IS_RANDO || (
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHOPSANITY) == RO_SHOPSANITY_OFF ||
(
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHOPSANITY) == RO_SHOPSANITY_SPECIFIC_COUNT &&
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHOPSANITY_COUNT) == RO_SHOPSANITY_COUNT_ZERO_ITEMS
)
) ? 500 : 999;
result.currentAmmo = gSaveContext.rupees; result.currentAmmo = gSaveContext.rupees;
break; break;
case ITEM_BOMBCHU: case ITEM_BOMBCHU:

View File

@ -97,7 +97,8 @@ void Settings::CreateOptions() {
mOptions[RSK_SHUFFLE_DUNGEON_REWARDS] = Option::U8("Shuffle Dungeon Rewards", {"End of Dungeons", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleDungeonReward"), mOptionDescriptions[RSK_SHUFFLE_DUNGEON_REWARDS], WidgetType::Combobox, RO_DUNGEON_REWARDS_END_OF_DUNGEON); mOptions[RSK_SHUFFLE_DUNGEON_REWARDS] = Option::U8("Shuffle Dungeon Rewards", {"End of Dungeons", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleDungeonReward"), mOptionDescriptions[RSK_SHUFFLE_DUNGEON_REWARDS], WidgetType::Combobox, RO_DUNGEON_REWARDS_END_OF_DUNGEON);
mOptions[RSK_LINKS_POCKET] = Option::U8("Link's Pocket", {"Dungeon Reward", "Advancement", "Anything", "Nothing"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LinksPocket"), "", WidgetType::Combobox, RO_LINKS_POCKET_DUNGEON_REWARD); mOptions[RSK_LINKS_POCKET] = Option::U8("Link's Pocket", {"Dungeon Reward", "Advancement", "Anything", "Nothing"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LinksPocket"), "", WidgetType::Combobox, RO_LINKS_POCKET_DUNGEON_REWARD);
mOptions[RSK_SHUFFLE_SONGS] = Option::U8("Shuffle Songs", {"Song Locations", "Dungeon Rewards", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleSongs"), mOptionDescriptions[RSK_SHUFFLE_SONGS], WidgetType::Combobox, RO_SONG_SHUFFLE_SONG_LOCATIONS); mOptions[RSK_SHUFFLE_SONGS] = Option::U8("Shuffle Songs", {"Song Locations", "Dungeon Rewards", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleSongs"), mOptionDescriptions[RSK_SHUFFLE_SONGS], WidgetType::Combobox, RO_SONG_SHUFFLE_SONG_LOCATIONS);
mOptions[RSK_SHOPSANITY] = Option::U8("Shopsanity", {"Off", "0 Items", "1 Item", "2 Items", "3 Items", "4 Items", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("Shopsanity"), mOptionDescriptions[RSK_SHOPSANITY], WidgetType::Combobox, RO_SHOPSANITY_OFF); mOptions[RSK_SHOPSANITY] = Option::U8("Shopsanity", {"Off", "Specific Count", "Random"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("Shopsanity"), mOptionDescriptions[RSK_SHOPSANITY], WidgetType::Combobox, RO_SHOPSANITY_OFF);
mOptions[RSK_SHOPSANITY_COUNT] = Option::U8("Shopsanity Item Count", {NumOpts(0, 7/*8*/)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShopsanityCount"), mOptionDescriptions[RSK_SHOPSANITY_COUNT], WidgetType::Slider, 0, false, IMFLAG_NONE);
mOptions[RSK_SHOPSANITY_PRICES] = Option::U8("Shopsanity Prices", {"Balanced", "Starting Wallet", "Adult Wallet", "Giant's Wallet", "Tycoon's Wallet"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShopsanityPrices"), mOptionDescriptions[RSK_SHOPSANITY_PRICES], WidgetType::Combobox, RO_SHOPSANITY_PRICE_BALANCED, false, IMFLAG_NONE); mOptions[RSK_SHOPSANITY_PRICES] = Option::U8("Shopsanity Prices", {"Balanced", "Starting Wallet", "Adult Wallet", "Giant's Wallet", "Tycoon's Wallet"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShopsanityPrices"), mOptionDescriptions[RSK_SHOPSANITY_PRICES], WidgetType::Combobox, RO_SHOPSANITY_PRICE_BALANCED, false, IMFLAG_NONE);
mOptions[RSK_SHOPSANITY_PRICES_AFFORDABLE] = Option::Bool("Affordable Prices", CVAR_RANDOMIZER_SETTING("ShopsanityPricesAffordable"), mOptionDescriptions[RSK_SHOPSANITY_PRICES_AFFORDABLE]); mOptions[RSK_SHOPSANITY_PRICES_AFFORDABLE] = Option::Bool("Affordable Prices", CVAR_RANDOMIZER_SETTING("ShopsanityPricesAffordable"), mOptionDescriptions[RSK_SHOPSANITY_PRICES_AFFORDABLE]);
mOptions[RSK_SHUFFLE_TOKENS] = Option::U8("Tokensanity", {"Off", "Dungeons", "Overworld", "All Tokens"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleTokens"), mOptionDescriptions[RSK_SHUFFLE_TOKENS], WidgetType::Combobox, RO_TOKENSANITY_OFF); mOptions[RSK_SHUFFLE_TOKENS] = Option::U8("Tokensanity", {"Off", "Dungeons", "Overworld", "All Tokens"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleTokens"), mOptionDescriptions[RSK_SHUFFLE_TOKENS], WidgetType::Combobox, RO_TOKENSANITY_OFF);
@ -672,6 +673,7 @@ void Settings::CreateOptions() {
}, false, WidgetContainerType::COLUMN); }, false, WidgetContainerType::COLUMN);
mOptionGroups[RSG_SHUFFLE_NPCS_IMGUI] = OptionGroup::SubGroup("Shuffle NPCs & Merchants", { mOptionGroups[RSG_SHUFFLE_NPCS_IMGUI] = OptionGroup::SubGroup("Shuffle NPCs & Merchants", {
&mOptions[RSK_SHOPSANITY], &mOptions[RSK_SHOPSANITY],
&mOptions[RSK_SHOPSANITY_COUNT],
&mOptions[RSK_SHOPSANITY_PRICES], &mOptions[RSK_SHOPSANITY_PRICES],
&mOptions[RSK_SHOPSANITY_PRICES_AFFORDABLE], &mOptions[RSK_SHOPSANITY_PRICES_AFFORDABLE],
&mOptions[RSK_FISHSANITY], &mOptions[RSK_FISHSANITY],
@ -876,6 +878,7 @@ void Settings::CreateOptions() {
&mOptions[RSK_LINKS_POCKET], &mOptions[RSK_LINKS_POCKET],
&mOptions[RSK_SHUFFLE_SONGS], &mOptions[RSK_SHUFFLE_SONGS],
&mOptions[RSK_SHOPSANITY], &mOptions[RSK_SHOPSANITY],
&mOptions[RSK_SHOPSANITY_COUNT],
&mOptions[RSK_SHOPSANITY_PRICES], &mOptions[RSK_SHOPSANITY_PRICES],
&mOptions[RSK_SHOPSANITY_PRICES_AFFORDABLE], &mOptions[RSK_SHOPSANITY_PRICES_AFFORDABLE],
&mOptions[RSK_FISHSANITY], &mOptions[RSK_FISHSANITY],
@ -1084,6 +1087,7 @@ void Settings::CreateOptions() {
&mOptions[RSK_SHUFFLE_DUNGEON_REWARDS], &mOptions[RSK_SHUFFLE_DUNGEON_REWARDS],
&mOptions[RSK_SHUFFLE_SONGS], &mOptions[RSK_SHUFFLE_SONGS],
&mOptions[RSK_SHOPSANITY], &mOptions[RSK_SHOPSANITY],
&mOptions[RSK_SHOPSANITY_COUNT],
&mOptions[RSK_SHOPSANITY_PRICES], &mOptions[RSK_SHOPSANITY_PRICES],
&mOptions[RSK_SHOPSANITY_PRICES_AFFORDABLE], &mOptions[RSK_SHOPSANITY_PRICES_AFFORDABLE],
&mOptions[RSK_FISHSANITY], &mOptions[RSK_FISHSANITY],
@ -1125,6 +1129,7 @@ void Settings::CreateOptions() {
{ "Shuffle Settings:Shuffle Songs", RSK_SHUFFLE_SONGS }, { "Shuffle Settings:Shuffle Songs", RSK_SHUFFLE_SONGS },
{ "Shuffle Settings:Shuffle Gerudo Membership Card", RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD }, { "Shuffle Settings:Shuffle Gerudo Membership Card", RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD },
{ "Shuffle Settings:Shopsanity", RSK_SHOPSANITY }, { "Shuffle Settings:Shopsanity", RSK_SHOPSANITY },
{ "Shuffle Settings:Shopsanity Specific Count", RSK_SHOPSANITY_COUNT },
{ "Shuffle Settings:Shopsanity Prices", RSK_SHOPSANITY_PRICES }, { "Shuffle Settings:Shopsanity Prices", RSK_SHOPSANITY_PRICES },
{ "Shuffle Settings:Affordable Prices", RSK_SHOPSANITY_PRICES_AFFORDABLE }, { "Shuffle Settings:Affordable Prices", RSK_SHOPSANITY_PRICES_AFFORDABLE },
{ "Shuffle Settings:Fishsanity", RSK_FISHSANITY }, { "Shuffle Settings:Fishsanity", RSK_FISHSANITY },
@ -1605,13 +1610,20 @@ void Settings::UpdateOptionProperties() {
// Hide shopsanity prices if shopsanity is off or zero // Hide shopsanity prices if shopsanity is off or zero
switch (CVarGetInteger(CVAR_RANDOMIZER_SETTING("Shopsanity"), RO_SHOPSANITY_OFF)) { switch (CVarGetInteger(CVAR_RANDOMIZER_SETTING("Shopsanity"), RO_SHOPSANITY_OFF)) {
case RO_SHOPSANITY_OFF: case RO_SHOPSANITY_OFF:
case RO_SHOPSANITY_ZERO_ITEMS:
mOptions[RSK_SHOPSANITY].AddFlag(IMFLAG_SEPARATOR_BOTTOM); mOptions[RSK_SHOPSANITY].AddFlag(IMFLAG_SEPARATOR_BOTTOM);
mOptions[RSK_SHOPSANITY_COUNT].Hide();
mOptions[RSK_SHOPSANITY_PRICES].Hide(); mOptions[RSK_SHOPSANITY_PRICES].Hide();
mOptions[RSK_SHOPSANITY_PRICES_AFFORDABLE].Hide(); mOptions[RSK_SHOPSANITY_PRICES_AFFORDABLE].Hide();
break; break;
case RO_SHOPSANITY_SPECIFIC_COUNT:
mOptions[RSK_SHOPSANITY].RemoveFlag(IMFLAG_SEPARATOR_BOTTOM);
mOptions[RSK_SHOPSANITY_COUNT].Unhide();
mOptions[RSK_SHOPSANITY_PRICES].Unhide();
mOptions[RSK_SHOPSANITY_PRICES_AFFORDABLE].Unhide();
break;
default: default:
mOptions[RSK_SHOPSANITY].RemoveFlag(IMFLAG_SEPARATOR_BOTTOM); mOptions[RSK_SHOPSANITY].RemoveFlag(IMFLAG_SEPARATOR_BOTTOM);
mOptions[RSK_SHOPSANITY_COUNT].Hide();
mOptions[RSK_SHOPSANITY_PRICES].Unhide(); mOptions[RSK_SHOPSANITY_PRICES].Unhide();
mOptions[RSK_SHOPSANITY_PRICES_AFFORDABLE].Unhide(); mOptions[RSK_SHOPSANITY_PRICES_AFFORDABLE].Unhide();
break; break;
@ -2300,6 +2312,7 @@ void Settings::ParseJson(nlohmann::json spoilerFileJson) {
case RSK_CUCCO_COUNT: case RSK_CUCCO_COUNT:
case RSK_FISHSANITY_POND_COUNT: case RSK_FISHSANITY_POND_COUNT:
case RSK_STARTING_SKULLTULA_TOKEN: case RSK_STARTING_SKULLTULA_TOKEN:
case RSK_SHOPSANITY_COUNT:
numericValueString = it.value(); numericValueString = it.value();
mOptions[index].SetSelectedIndex(std::stoi(numericValueString)); mOptions[index].SetSelectedIndex(std::stoi(numericValueString));
break; break;
@ -2323,16 +2336,8 @@ void Settings::ParseJson(nlohmann::json spoilerFileJson) {
case RSK_SHOPSANITY: case RSK_SHOPSANITY:
if (it.value() == "Off") { if (it.value() == "Off") {
mOptions[index].SetSelectedIndex(RO_SHOPSANITY_OFF); mOptions[index].SetSelectedIndex(RO_SHOPSANITY_OFF);
} else if (it.value() == "0 Items") { } else if (it.value() == "Specific Count") {
mOptions[index].SetSelectedIndex(RO_SHOPSANITY_ZERO_ITEMS); mOptions[index].SetSelectedIndex(RO_SHOPSANITY_SPECIFIC_COUNT);
} else if (it.value() == "1 Item") {
mOptions[index].SetSelectedIndex(RO_SHOPSANITY_ONE_ITEM);
} else if (it.value() == "2 Items") {
mOptions[index].SetSelectedIndex(RO_SHOPSANITY_TWO_ITEMS);
} else if (it.value() == "3 Items") {
mOptions[index].SetSelectedIndex(RO_SHOPSANITY_THREE_ITEMS);
} else if (it.value() == "4 Items") {
mOptions[index].SetSelectedIndex(RO_SHOPSANITY_FOUR_ITEMS);
} else if (it.value() == "Random") { } else if (it.value() == "Random") {
mOptions[index].SetSelectedIndex(RO_SHOPSANITY_RANDOM); mOptions[index].SetSelectedIndex(RO_SHOPSANITY_RANDOM);
} }

View File

@ -432,7 +432,7 @@ void EnOssan_SpawnItemsOnShelves(EnOssan* this, PlayState* play, ShopItem* shopI
} else { } else {
itemParams = sShopItemReplaceFunc[shopItems->shopItemIndex](shopItems->shopItemIndex); itemParams = sShopItemReplaceFunc[shopItems->shopItemIndex](shopItems->shopItemIndex);
if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHOPSANITY) != RO_SHOPSANITY_OFF) { if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHOPSANITY) != RO_SHOPSANITY_OFF) {
ShopItemIdentity shopItemIdentity = Randomizer_IdentifyShopItem(play->sceneNum, i); ShopItemIdentity shopItemIdentity = Randomizer_IdentifyShopItem(play->sceneNum, i + 1);
if (shopItemIdentity.randomizerCheck != RC_UNKNOWN_CHECK) { if (shopItemIdentity.randomizerCheck != RC_UNKNOWN_CHECK) {
itemParams = shopItemIdentity.enGirlAShopItem; itemParams = shopItemIdentity.enGirlAShopItem;
@ -452,7 +452,7 @@ void EnOssan_SpawnItemsOnShelves(EnOssan* this, PlayState* play, ShopItem* shopI
shelves->actor.shape.rot.x, shelves->actor.shape.rot.y + sItemShelfRot[i], shelves->actor.shape.rot.x, shelves->actor.shape.rot.y + sItemShelfRot[i],
shelves->actor.shape.rot.z, itemParams, true); shelves->actor.shape.rot.z, itemParams, true);
if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHOPSANITY) != RO_SHOPSANITY_OFF) { if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHOPSANITY) != RO_SHOPSANITY_OFF) {
this->shelfSlots[i]->randoSlotIndex = i; this->shelfSlots[i]->randoSlotIndex = i + 1;
} }
} }
} }
@ -1391,7 +1391,7 @@ void EnOssan_GiveItemWithFanfare(PlayState* play, EnOssan* this) {
if (!IS_RANDO) { if (!IS_RANDO) {
Actor_OfferGetItem(&this->actor, play, this->shelfSlots[this->cursorIndex]->getItemId, 120.0f, 120.0f); Actor_OfferGetItem(&this->actor, play, this->shelfSlots[this->cursorIndex]->getItemId, 120.0f, 120.0f);
} else { } else {
ShopItemIdentity shopItemIdentity = Randomizer_IdentifyShopItem(play->sceneNum, this->cursorIndex); ShopItemIdentity shopItemIdentity = Randomizer_IdentifyShopItem(play->sceneNum, this->cursorIndex + 1);
// en_ossan/en_girla are also used for the happy mask shop, which never has randomized items // en_ossan/en_girla are also used for the happy mask shop, which never has randomized items
// and returns RC_UNKNOWN_CHECK, in which case we should fall back to vanilla logic // and returns RC_UNKNOWN_CHECK, in which case we should fall back to vanilla logic
if (shopItemIdentity.randomizerCheck != RC_UNKNOWN_CHECK) { if (shopItemIdentity.randomizerCheck != RC_UNKNOWN_CHECK) {
@ -1738,7 +1738,7 @@ void EnOssan_State_GiveItemWithFanfare(EnOssan* this, PlayState* play, Player* p
if (!IS_RANDO) { if (!IS_RANDO) {
Actor_OfferGetItem(&this->actor, play, this->shelfSlots[this->cursorIndex]->getItemId, 120.0f, 120.0f); Actor_OfferGetItem(&this->actor, play, this->shelfSlots[this->cursorIndex]->getItemId, 120.0f, 120.0f);
} else { } else {
ShopItemIdentity shopItemIdentity = Randomizer_IdentifyShopItem(play->sceneNum, this->cursorIndex); ShopItemIdentity shopItemIdentity = Randomizer_IdentifyShopItem(play->sceneNum, this->cursorIndex + 1);
// en_ossan/en_girla are also used for the happy mask shop, which never has randomized items // en_ossan/en_girla are also used for the happy mask shop, which never has randomized items
// and returns RC_UNKNOWN_CHECK, in which case we should fall back to vanilla logic // and returns RC_UNKNOWN_CHECK, in which case we should fall back to vanilla logic
if (shopItemIdentity.randomizerCheck != RC_UNKNOWN_CHECK) { if (shopItemIdentity.randomizerCheck != RC_UNKNOWN_CHECK) {
@ -1754,7 +1754,7 @@ void EnOssan_State_GiveItemWithFanfare(EnOssan* this, PlayState* play, Player* p
void EnOssan_State_ItemPurchased(EnOssan* this, PlayState* play, Player* player) { void EnOssan_State_ItemPurchased(EnOssan* this, PlayState* play, Player* player) {
EnGirlA* item; EnGirlA* item;
EnGirlA* itemTemp; EnGirlA* itemTemp;
ShopItemIdentity shopItemIdentity = Randomizer_IdentifyShopItem(play->sceneNum, this->cursorIndex); ShopItemIdentity shopItemIdentity = Randomizer_IdentifyShopItem(play->sceneNum, this->cursorIndex + 1);
GetItemEntry getItemEntry; GetItemEntry getItemEntry;
if (shopItemIdentity.randomizerCheck != RC_UNKNOWN_CHECK) { if (shopItemIdentity.randomizerCheck != RC_UNKNOWN_CHECK) {
getItemEntry = Randomizer_GetItemFromKnownCheck(shopItemIdentity.randomizerCheck, shopItemIdentity.ogItemId); getItemEntry = Randomizer_GetItemFromKnownCheck(shopItemIdentity.randomizerCheck, shopItemIdentity.ogItemId);