Various changes from feedback, and use new randomizerInf table

This commit is contained in:
Garrett Cox 2022-08-25 13:49:02 -05:00
parent 936513a9c4
commit 1e31d108e6
11 changed files with 106 additions and 69 deletions

View File

@ -184,7 +184,6 @@ typedef struct {
char ganonText[250]; char ganonText[250];
u8 seedIcons[5]; u8 seedIcons[5];
u16 randomizerInf[2]; u16 randomizerInf[2];
u8 scrubsPurchased[35];
u8 temporaryWeapon; u8 temporaryWeapon;
u16 adultTradeItems; u16 adultTradeItems;
} SaveContext; // size = 0x1428 } SaveContext; // size = 0x1428

View File

@ -1040,7 +1040,7 @@ int Fill() {
std::vector<uint32_t> remainingPool = FilterAndEraseFromPool(ItemPool, [](const auto i) { return true; }); std::vector<uint32_t> remainingPool = FilterAndEraseFromPool(ItemPool, [](const auto i) { return true; });
FastFill(remainingPool, GetAllEmptyLocations(), false); FastFill(remainingPool, GetAllEmptyLocations(), false);
// Add prices for scrubsanity //Add prices for scrubsanity, this is unique to SoH because we write/read scrub prices to/from the spoilerfile.
if (Scrubsanity.Is(SCRUBSANITY_AFFORDABLE)) { if (Scrubsanity.Is(SCRUBSANITY_AFFORDABLE)) {
for (size_t i = 0; i < ScrubLocations.size(); i++) { for (size_t i = 0; i < ScrubLocations.size(); i++) {
Location(ScrubLocations[i])->SetScrubsanityPrice(10); Location(ScrubLocations[i])->SetScrubsanityPrice(10);

View File

@ -673,12 +673,20 @@ static void WriteHints(int language) {
static void WriteAllLocations(int language) { static void WriteAllLocations(int language) {
for (const uint32_t key : allLocations) { for (const uint32_t key : allLocations) {
ItemLocation* location = Location(key); ItemLocation* location = Location(key);
std::string placedItemName = language == 2 ? location->GetPlacedItemName().french : location->GetPlacedItemName().english; std::string placedItemName;
switch (language) {
case 0:
default:
location->GetPlacedItemName().english;
case 2:
location->GetPlacedItemName().french;
}
// Eventually check for other things here like fake name // Eventually check for other things here like fake name
if (location->HasScrubsanityPrice() || location->HasShopsanityPrice()) { if (location->HasScrubsanityPrice() || location->HasShopsanityPrice()) {
jsonData["locations"][location->GetName()]["item"] = placedItemName; jsonData["locations"][location->GetName()]["item"] = placedItemName;
jsonData["locations"][location->GetName()]["price"] = location->GetPrice();; jsonData["locations"][location->GetName()]["price"] = location->GetPrice();
} else { } else {
jsonData["locations"][location->GetName()] = placedItemName; jsonData["locations"][location->GetName()] = placedItemName;
} }

View File

@ -104,7 +104,7 @@ Sprite* Randomizer::GetSeedTexture(uint8_t index) {
Randomizer::~Randomizer() { Randomizer::~Randomizer() {
this->randoSettings.clear(); this->randoSettings.clear();
this->itemLocations.clear(); this->itemLocations.clear();
this->scrubPrices.clear(); this->randomizerMerchantPrices.clear();
} }
std::unordered_map<s16, s16> getItemIdToItemId = { std::unordered_map<s16, s16> getItemIdToItemId = {
@ -1118,8 +1118,7 @@ void Randomizer::ParseItemLocationsFile(const char* spoilerFileName, bool silent
gSaveContext.itemLocations[index].check = SpoilerfileCheckNameToEnum[it.key()]; gSaveContext.itemLocations[index].check = SpoilerfileCheckNameToEnum[it.key()];
gSaveContext.itemLocations[index].get = SpoilerfileGetNameToEnum[itemit.value()]; gSaveContext.itemLocations[index].get = SpoilerfileGetNameToEnum[itemit.value()];
} else if (itemit.key() == "price") { } else if (itemit.key() == "price") {
scrubPrices[gSaveContext.itemLocations[index].check] = itemit.value(); randomizerMerchantPrices[gSaveContext.itemLocations[index].check] = itemit.value();
// TODO: Handle shop prices
} }
} }
} else { } else {
@ -1606,12 +1605,12 @@ std::string Randomizer::GetGanonHintText() const {
ScrubIdentity Randomizer::IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respawnData) { ScrubIdentity Randomizer::IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respawnData) {
struct ScrubIdentity scrubIdentity; struct ScrubIdentity scrubIdentity;
scrubIdentity.scrubId = -1;
scrubIdentity.randomizerCheck = RC_UNKNOWN_CHECK; scrubIdentity.randomizerCheck = RC_UNKNOWN_CHECK;
scrubIdentity.getItemId = GI_NONE; scrubIdentity.getItemId = GI_NONE;
scrubIdentity.itemPrice = -1; scrubIdentity.itemPrice = -1;
scrubIdentity.isShuffled = GetRandoSettingValue(RSK_SHUFFLE_SCRUBS) > 0; scrubIdentity.isShuffled = GetRandoSettingValue(RSK_SHUFFLE_SCRUBS) > 0;
// Based on z_en_dns.c 93-113
switch (actorParams) { switch (actorParams) {
case 0x00: case 0x00:
scrubIdentity.getItemId = GI_NUTS_5_2; scrubIdentity.getItemId = GI_NUTS_5_2;
@ -1653,20 +1652,20 @@ ScrubIdentity Randomizer::IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respa
case SCENE_DDAN: // Dodongo's Cavern case SCENE_DDAN: // Dodongo's Cavern
switch (actorParams) { switch (actorParams) {
case 0x00: case 0x00:
scrubIdentity.scrubId = 0x00; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT;
scrubIdentity.randomizerCheck = RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT; scrubIdentity.randomizerCheck = RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT;
break; break;
case 0x01: case 0x01:
scrubIdentity.scrubId = 0x01; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS;
scrubIdentity.randomizerCheck = RC_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS; scrubIdentity.randomizerCheck = RC_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS;
break; break;
case 0x03: case 0x03:
case 0x06: case 0x06:
scrubIdentity.scrubId = 0x02; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT;
scrubIdentity.randomizerCheck = RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT; scrubIdentity.randomizerCheck = RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT;
break; break;
case 0x04: case 0x04:
scrubIdentity.scrubId = 0x03; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY;
scrubIdentity.randomizerCheck = RC_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY; scrubIdentity.randomizerCheck = RC_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY;
break; break;
} }
@ -1674,7 +1673,7 @@ ScrubIdentity Randomizer::IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respa
case SCENE_BDAN: // Jabu Jabu's Belly case SCENE_BDAN: // Jabu Jabu's Belly
switch (actorParams) { switch (actorParams) {
case 0x00: case 0x00:
scrubIdentity.scrubId = 0x04; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_JABU_JABUS_BELLY_DEKU_SCRUB;
scrubIdentity.randomizerCheck = RC_JABU_JABUS_BELLY_DEKU_SCRUB; scrubIdentity.randomizerCheck = RC_JABU_JABUS_BELLY_DEKU_SCRUB;
break; break;
} }
@ -1682,20 +1681,20 @@ ScrubIdentity Randomizer::IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respa
case SCENE_GANONTIKA: // Ganon's Castle case SCENE_GANONTIKA: // Ganon's Castle
switch (actorParams) { switch (actorParams) {
case 0x05: case 0x05:
scrubIdentity.scrubId = 0x05; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT;
scrubIdentity.randomizerCheck = RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT; scrubIdentity.randomizerCheck = RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT;
break; break;
case 0x03: case 0x03:
case 0x06: case 0x06:
scrubIdentity.scrubId = 0x06; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT;
scrubIdentity.randomizerCheck = RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT; scrubIdentity.randomizerCheck = RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT;
break; break;
case 0x07: case 0x07:
scrubIdentity.scrubId = 0x07; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_RIGHT;
scrubIdentity.randomizerCheck = RC_GANONS_CASTLE_DEKU_SCRUB_RIGHT; scrubIdentity.randomizerCheck = RC_GANONS_CASTLE_DEKU_SCRUB_RIGHT;
break; break;
case 0x08: case 0x08:
scrubIdentity.scrubId = 0x08; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_LEFT;
scrubIdentity.randomizerCheck = RC_GANONS_CASTLE_DEKU_SCRUB_LEFT; scrubIdentity.randomizerCheck = RC_GANONS_CASTLE_DEKU_SCRUB_LEFT;
break; break;
} }
@ -1705,7 +1704,7 @@ ScrubIdentity Randomizer::IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respa
case 0xE6: // Hyrule Field Scrub Grotto case 0xE6: // Hyrule Field Scrub Grotto
switch (actorParams) { switch (actorParams) {
case 0x02: case 0x02:
scrubIdentity.scrubId = 0x09; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_HF_DEKU_SCRUB_GROTTO;
scrubIdentity.randomizerCheck = RC_HF_DEKU_SCRUB_GROTTO; scrubIdentity.randomizerCheck = RC_HF_DEKU_SCRUB_GROTTO;
scrubIdentity.isShuffled = true; scrubIdentity.isShuffled = true;
break; break;
@ -1714,11 +1713,11 @@ ScrubIdentity Randomizer::IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respa
case 0xEB: // ZR Scrub Grotto case 0xEB: // ZR Scrub Grotto
switch (actorParams) { switch (actorParams) {
case 0x07: case 0x07:
scrubIdentity.scrubId = 0x0A; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_ZR_DEKU_SCRUB_GROTTO_REAR;
scrubIdentity.randomizerCheck = RC_ZR_DEKU_SCRUB_GROTTO_REAR; scrubIdentity.randomizerCheck = RC_ZR_DEKU_SCRUB_GROTTO_REAR;
break; break;
case 0x08: case 0x08:
scrubIdentity.scrubId = 0x0B; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_ZR_DEKU_SCRUB_GROTTO_FRONT;
scrubIdentity.randomizerCheck = RC_ZR_DEKU_SCRUB_GROTTO_FRONT; scrubIdentity.randomizerCheck = RC_ZR_DEKU_SCRUB_GROTTO_FRONT;
break; break;
} }
@ -1726,11 +1725,11 @@ ScrubIdentity Randomizer::IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respa
case 0xEE: // Sacred Forest Meadow Scrub Grotto case 0xEE: // Sacred Forest Meadow Scrub Grotto
switch (actorParams) { switch (actorParams) {
case 0x07: case 0x07:
scrubIdentity.scrubId = 0x0C; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_SFM_DEKU_SCRUB_GROTTO_REAR;
scrubIdentity.randomizerCheck = RC_SFM_DEKU_SCRUB_GROTTO_REAR; scrubIdentity.randomizerCheck = RC_SFM_DEKU_SCRUB_GROTTO_REAR;
break; break;
case 0x08: case 0x08:
scrubIdentity.scrubId = 0x0D; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_SFM_DEKU_SCRUB_GROTTO_FRONT;
scrubIdentity.randomizerCheck = RC_SFM_DEKU_SCRUB_GROTTO_FRONT; scrubIdentity.randomizerCheck = RC_SFM_DEKU_SCRUB_GROTTO_FRONT;
break; break;
} }
@ -1738,16 +1737,16 @@ ScrubIdentity Randomizer::IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respa
case 0xEF: // Lake Hylia Scrub Grotto case 0xEF: // Lake Hylia Scrub Grotto
switch (actorParams) { switch (actorParams) {
case 0x00: case 0x00:
scrubIdentity.scrubId = 0x0E; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_LH_DEKU_SCRUB_GROTTO_LEFT;
scrubIdentity.randomizerCheck = RC_LH_DEKU_SCRUB_GROTTO_LEFT; scrubIdentity.randomizerCheck = RC_LH_DEKU_SCRUB_GROTTO_LEFT;
break; break;
case 0x05: case 0x05:
scrubIdentity.scrubId = 0x0F; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_LH_DEKU_SCRUB_GROTTO_RIGHT;
scrubIdentity.randomizerCheck = RC_LH_DEKU_SCRUB_GROTTO_RIGHT; scrubIdentity.randomizerCheck = RC_LH_DEKU_SCRUB_GROTTO_RIGHT;
break; break;
case 0x03: case 0x03:
case 0x06: case 0x06:
scrubIdentity.scrubId = 0x10; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_LH_DEKU_SCRUB_GROTTO_CENTER;
scrubIdentity.randomizerCheck = RC_LH_DEKU_SCRUB_GROTTO_CENTER; scrubIdentity.randomizerCheck = RC_LH_DEKU_SCRUB_GROTTO_CENTER;
break; break;
} }
@ -1755,11 +1754,11 @@ ScrubIdentity Randomizer::IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respa
case 0xF0: // Gerudo Valley Scrub Grotto case 0xF0: // Gerudo Valley Scrub Grotto
switch (actorParams) { switch (actorParams) {
case 0x07: case 0x07:
scrubIdentity.scrubId = 0x11; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_GV_DEKU_SCRUB_GROTTO_REAR;
scrubIdentity.randomizerCheck = RC_GV_DEKU_SCRUB_GROTTO_REAR; scrubIdentity.randomizerCheck = RC_GV_DEKU_SCRUB_GROTTO_REAR;
break; break;
case 0x08: case 0x08:
scrubIdentity.scrubId = 0x12; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_GV_DEKU_SCRUB_GROTTO_FRONT;
scrubIdentity.randomizerCheck = RC_GV_DEKU_SCRUB_GROTTO_FRONT; scrubIdentity.randomizerCheck = RC_GV_DEKU_SCRUB_GROTTO_FRONT;
break; break;
} }
@ -1768,11 +1767,11 @@ ScrubIdentity Randomizer::IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respa
switch (actorParams) { switch (actorParams) {
case 0x03: case 0x03:
case 0x06: case 0x06:
scrubIdentity.scrubId = 0x13; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_GROTTO_REAR;
scrubIdentity.randomizerCheck = RC_LW_DEKU_SCRUB_GROTTO_REAR; scrubIdentity.randomizerCheck = RC_LW_DEKU_SCRUB_GROTTO_REAR;
break; break;
case 0x0A: case 0x0A:
scrubIdentity.scrubId = 0x14; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_GROTTO_FRONT;
scrubIdentity.randomizerCheck = RC_LW_DEKU_SCRUB_GROTTO_FRONT; scrubIdentity.randomizerCheck = RC_LW_DEKU_SCRUB_GROTTO_FRONT;
scrubIdentity.isShuffled = true; scrubIdentity.isShuffled = true;
break; break;
@ -1781,16 +1780,16 @@ ScrubIdentity Randomizer::IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respa
case 0xF9: // Death Mountain Crater Scrub Grotto case 0xF9: // Death Mountain Crater Scrub Grotto
switch (actorParams) { switch (actorParams) {
case 0x00: case 0x00:
scrubIdentity.scrubId = 0x15; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB_GROTTO_LEFT;
scrubIdentity.randomizerCheck = RC_DMC_DEKU_SCRUB_GROTTO_LEFT; scrubIdentity.randomizerCheck = RC_DMC_DEKU_SCRUB_GROTTO_LEFT;
break; break;
case 0x05: case 0x05:
scrubIdentity.scrubId = 0x16; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB_GROTTO_RIGHT;
scrubIdentity.randomizerCheck = RC_DMC_DEKU_SCRUB_GROTTO_RIGHT; scrubIdentity.randomizerCheck = RC_DMC_DEKU_SCRUB_GROTTO_RIGHT;
break; break;
case 0x03: case 0x03:
case 0x06: case 0x06:
scrubIdentity.scrubId = 0x17; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB_GROTTO_CENTER;
scrubIdentity.randomizerCheck = RC_DMC_DEKU_SCRUB_GROTTO_CENTER; scrubIdentity.randomizerCheck = RC_DMC_DEKU_SCRUB_GROTTO_CENTER;
break; break;
} }
@ -1798,16 +1797,16 @@ ScrubIdentity Randomizer::IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respa
case 0xFB: // Gerudo City Scrub Grotto case 0xFB: // Gerudo City Scrub Grotto
switch (actorParams) { switch (actorParams) {
case 0x00: case 0x00:
scrubIdentity.scrubId = 0x18; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_GC_DEKU_SCRUB_GROTTO_LEFT;
scrubIdentity.randomizerCheck = RC_GC_DEKU_SCRUB_GROTTO_LEFT; scrubIdentity.randomizerCheck = RC_GC_DEKU_SCRUB_GROTTO_LEFT;
break; break;
case 0x05: case 0x05:
scrubIdentity.scrubId = 0x19; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_GC_DEKU_SCRUB_GROTTO_RIGHT;
scrubIdentity.randomizerCheck = RC_GC_DEKU_SCRUB_GROTTO_RIGHT; scrubIdentity.randomizerCheck = RC_GC_DEKU_SCRUB_GROTTO_RIGHT;
break; break;
case 0x03: case 0x03:
case 0x06: case 0x06:
scrubIdentity.scrubId = 0x1A; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_GC_DEKU_SCRUB_GROTTO_CENTER;
scrubIdentity.randomizerCheck = RC_GC_DEKU_SCRUB_GROTTO_CENTER; scrubIdentity.randomizerCheck = RC_GC_DEKU_SCRUB_GROTTO_CENTER;
break; break;
} }
@ -1815,16 +1814,16 @@ ScrubIdentity Randomizer::IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respa
case 0xFC: // Lon Lon Ranch Scrub Grotto case 0xFC: // Lon Lon Ranch Scrub Grotto
switch (actorParams) { switch (actorParams) {
case 0x00: case 0x00:
scrubIdentity.scrubId = 0x1B; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_LEFT;
scrubIdentity.randomizerCheck = RC_LLR_DEKU_SCRUB_GROTTO_LEFT; scrubIdentity.randomizerCheck = RC_LLR_DEKU_SCRUB_GROTTO_LEFT;
break; break;
case 0x05: case 0x05:
scrubIdentity.scrubId = 0x1C; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_RIGHT;
scrubIdentity.randomizerCheck = RC_LLR_DEKU_SCRUB_GROTTO_RIGHT; scrubIdentity.randomizerCheck = RC_LLR_DEKU_SCRUB_GROTTO_RIGHT;
break; break;
case 0x03: case 0x03:
case 0x06: case 0x06:
scrubIdentity.scrubId = 0x1D; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_CENTER;
scrubIdentity.randomizerCheck = RC_LLR_DEKU_SCRUB_GROTTO_CENTER; scrubIdentity.randomizerCheck = RC_LLR_DEKU_SCRUB_GROTTO_CENTER;
break; break;
} }
@ -1832,11 +1831,11 @@ ScrubIdentity Randomizer::IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respa
case 0xFD: // Desert Colossus Scrub Grotto case 0xFD: // Desert Colossus Scrub Grotto
switch (actorParams) { switch (actorParams) {
case 0x07: case 0x07:
scrubIdentity.scrubId = 0x1E; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_COLOSSUS_DEKU_SCRUB_GROTTO_REAR;
scrubIdentity.randomizerCheck = RC_COLOSSUS_DEKU_SCRUB_GROTTO_REAR; scrubIdentity.randomizerCheck = RC_COLOSSUS_DEKU_SCRUB_GROTTO_REAR;
break; break;
case 0x08: case 0x08:
scrubIdentity.scrubId = 0x1F; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT;
scrubIdentity.randomizerCheck = RC_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT; scrubIdentity.randomizerCheck = RC_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT;
break; break;
} }
@ -1846,15 +1845,15 @@ ScrubIdentity Randomizer::IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respa
case SCENE_SPOT10: // Lost woods case SCENE_SPOT10: // Lost woods
switch (actorParams) { switch (actorParams) {
case 0x00: case 0x00:
scrubIdentity.scrubId = 0x20; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT;
scrubIdentity.randomizerCheck = RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT; scrubIdentity.randomizerCheck = RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT;
break; break;
case 0x01: case 0x01:
scrubIdentity.scrubId = 0x21; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT;
scrubIdentity.randomizerCheck = RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT; scrubIdentity.randomizerCheck = RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT;
break; break;
case 0x09: case 0x09:
scrubIdentity.scrubId = 0x22; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_BRIDGE;
scrubIdentity.randomizerCheck = RC_LW_DEKU_SCRUB_NEAR_BRIDGE; scrubIdentity.randomizerCheck = RC_LW_DEKU_SCRUB_NEAR_BRIDGE;
scrubIdentity.isShuffled = true; scrubIdentity.isShuffled = true;
break; break;
@ -1863,15 +1862,15 @@ ScrubIdentity Randomizer::IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respa
case SCENE_SPOT17: // Death Mountain Crater case SCENE_SPOT17: // Death Mountain Crater
switch (actorParams) { switch (actorParams) {
case 0x05: case 0x05:
scrubIdentity.scrubId = 0x23; scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB;
scrubIdentity.randomizerCheck = RC_DMC_DEKU_SCRUB; scrubIdentity.randomizerCheck = RC_DMC_DEKU_SCRUB;
break; break;
} }
break; break;
} }
if (scrubPrices.find(scrubIdentity.randomizerCheck) != scrubPrices.end()) { if (randomizerMerchantPrices.find(scrubIdentity.randomizerCheck) != randomizerMerchantPrices.end()) {
scrubIdentity.itemPrice = scrubPrices[scrubIdentity.randomizerCheck]; scrubIdentity.itemPrice = randomizerMerchantPrices[scrubIdentity.randomizerCheck];
} }
return scrubIdentity; return scrubIdentity;
@ -3398,9 +3397,13 @@ void DrawRandoEditor(bool& open) {
// Shuffle Scrubs // Shuffle Scrubs
ImGui::Text(Settings::Scrubsanity.GetName().c_str()); ImGui::Text(Settings::Scrubsanity.GetName().c_str());
InsertHelpHoverText( InsertHelpHoverText(
"Off - Scrubs will not be shuffled.\n" "Off - Scrubs will not be shuffled. The 3 Scrubs that give one-time items in the vanilla game (PoH, Deku Nut capacity, and Deku Stick capacity) will have random items.\n"
"\n" "\n"
"Affordable - Scrubs will be shuffled and their item will cost 10 rupees.\n" "Affordable - Scrubs will be shuffled and their item will cost 10 rupees.\n"
"\n"
"Expensive - Scrubs will be shuffled and their item will cost the vanilla price.\n"
"\n"
"Random - Scrubs will be shuffled and their item will cost will be between 0-95 rupees.\n"
); );
SohImGui::EnhancementCombobox("gRandomizeShuffleScrubs", randoShuffleScrubs, 4, 0); SohImGui::EnhancementCombobox("gRandomizeShuffleScrubs", randoShuffleScrubs, 4, 0);
PaddedSeparator(); PaddedSeparator();
@ -4019,6 +4022,8 @@ void CreateGetItemMessages(std::vector<GetItemMessage> messageEntries) {
} }
} }
// Currently these are generated at runtime, one for each price between 0-95. We're soon going to migrate this
// to being generated at save load, with only messages specific to each scrub.
void CreateScrubMessages() { void CreateScrubMessages() {
CustomMessageManager* customMessageManager = CustomMessageManager::Instance; CustomMessageManager* customMessageManager = CustomMessageManager::Instance;
customMessageManager->AddCustomMessageTable(Randomizer::scrubMessageTableID); customMessageManager->AddCustomMessageTable(Randomizer::scrubMessageTableID);

View File

@ -19,7 +19,7 @@ class Randomizer {
std::string ganonHintText; std::string ganonHintText;
std::string ganonText; std::string ganonText;
std::unordered_map<RandomizerSettingKey, u8> randoSettings; std::unordered_map<RandomizerSettingKey, u8> randoSettings;
std::unordered_map<RandomizerCheck, u16> scrubPrices; std::unordered_map<RandomizerCheck, u16> randomizerMerchantPrices;
s16 GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId); s16 GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId);
s16 GetItemFromActor(s16 actorId, s16 actorParams, s16 sceneNum, GetItemID ogItemId); s16 GetItemFromActor(s16 actorId, s16 actorParams, s16 sceneNum, GetItemID ogItemId);
void ParseRandomizerSettingsFile(const char* spoilerFileName); void ParseRandomizerSettingsFile(const char* spoilerFileName);

View File

@ -2,6 +2,7 @@
#include <stdint.h> #include <stdint.h>
#include "z64item.h" #include "z64item.h"
#include "randomizer_inf.h"
// This should probably go in a less rando-specific location // This should probably go in a less rando-specific location
// but the best location will probably be in the modding engine // but the best location will probably be in the modding engine
@ -1019,7 +1020,7 @@ typedef enum {
} RandomizerSettingKey; } RandomizerSettingKey;
typedef struct ScrubIdentity { typedef struct ScrubIdentity {
int32_t scrubId; RandomizerInf randomizerInf;
RandomizerCheck randomizerCheck; RandomizerCheck randomizerCheck;
GetItemID getItemId; GetItemID getItemId;
int32_t itemPrice; int32_t itemPrice;

View File

@ -29,6 +29,43 @@ typedef enum {
RAND_INF_COWS_MILKED_JABU_JABUS_BELLY_MQ_COW, RAND_INF_COWS_MILKED_JABU_JABUS_BELLY_MQ_COW,
RAND_INF_COWS_MILKED_HF_COW_GROTTO_GOSSIP_STONE, RAND_INF_COWS_MILKED_HF_COW_GROTTO_GOSSIP_STONE,
RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT,
RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS,
RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT,
RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY,
RAND_INF_SCRUBS_PURCHASED_JABU_JABUS_BELLY_DEKU_SCRUB,
RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT,
RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT,
RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_RIGHT,
RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_LEFT,
RAND_INF_SCRUBS_PURCHASED_HF_DEKU_SCRUB_GROTTO,
RAND_INF_SCRUBS_PURCHASED_ZR_DEKU_SCRUB_GROTTO_REAR,
RAND_INF_SCRUBS_PURCHASED_ZR_DEKU_SCRUB_GROTTO_FRONT,
RAND_INF_SCRUBS_PURCHASED_SFM_DEKU_SCRUB_GROTTO_REAR,
RAND_INF_SCRUBS_PURCHASED_SFM_DEKU_SCRUB_GROTTO_FRONT,
RAND_INF_SCRUBS_PURCHASED_LH_DEKU_SCRUB_GROTTO_LEFT,
RAND_INF_SCRUBS_PURCHASED_LH_DEKU_SCRUB_GROTTO_RIGHT,
RAND_INF_SCRUBS_PURCHASED_LH_DEKU_SCRUB_GROTTO_CENTER,
RAND_INF_SCRUBS_PURCHASED_GV_DEKU_SCRUB_GROTTO_REAR,
RAND_INF_SCRUBS_PURCHASED_GV_DEKU_SCRUB_GROTTO_FRONT,
RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_GROTTO_REAR,
RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_GROTTO_FRONT,
RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB_GROTTO_LEFT,
RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB_GROTTO_RIGHT,
RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB_GROTTO_CENTER,
RAND_INF_SCRUBS_PURCHASED_GC_DEKU_SCRUB_GROTTO_LEFT,
RAND_INF_SCRUBS_PURCHASED_GC_DEKU_SCRUB_GROTTO_RIGHT,
RAND_INF_SCRUBS_PURCHASED_GC_DEKU_SCRUB_GROTTO_CENTER,
RAND_INF_SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_LEFT,
RAND_INF_SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_RIGHT,
RAND_INF_SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_CENTER,
RAND_INF_SCRUBS_PURCHASED_COLOSSUS_DEKU_SCRUB_GROTTO_REAR,
RAND_INF_SCRUBS_PURCHASED_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT,
RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT,
RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT,
RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_BRIDGE,
RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB,
// If you add anything to this list, you need to update the size of randomizerInf in z64save.h to be ceil(RAND_INF_MAX / 16) // If you add anything to this list, you need to update the size of randomizerInf in z64save.h to be ceil(RAND_INF_MAX / 16)
RAND_INF_MAX, RAND_INF_MAX,

View File

@ -761,10 +761,6 @@ void SaveManager::LoadBaseVersion1() {
SaveManager::Instance->LoadArray("randomizerInf", ARRAY_COUNT(gSaveContext.randomizerInf), [](size_t i) { SaveManager::Instance->LoadArray("randomizerInf", ARRAY_COUNT(gSaveContext.randomizerInf), [](size_t i) {
SaveManager::Instance->LoadData("", gSaveContext.randomizerInf[i]); SaveManager::Instance->LoadData("", gSaveContext.randomizerInf[i]);
}); });
SaveManager::Instance->LoadArray("scrubsPurchased", ARRAY_COUNT(gSaveContext.scrubsPurchased), [](size_t i) {
SaveManager::Instance->LoadData("", gSaveContext.scrubsPurchased[i]);
});
} }
void SaveManager::LoadBaseVersion2() { void SaveManager::LoadBaseVersion2() {
@ -922,10 +918,6 @@ void SaveManager::LoadBaseVersion2() {
SaveManager::Instance->LoadArray("randomizerInf", ARRAY_COUNT(gSaveContext.randomizerInf), [](size_t i) { SaveManager::Instance->LoadArray("randomizerInf", ARRAY_COUNT(gSaveContext.randomizerInf), [](size_t i) {
SaveManager::Instance->LoadData("", gSaveContext.randomizerInf[i]); SaveManager::Instance->LoadData("", gSaveContext.randomizerInf[i]);
}); });
SaveManager::Instance->LoadArray("scrubsPurchased", ARRAY_COUNT(gSaveContext.scrubsPurchased), [](size_t i) {
SaveManager::Instance->LoadData("", gSaveContext.scrubsPurchased[i]);
});
} }
void SaveManager::SaveBase() { void SaveManager::SaveBase() {
@ -1079,10 +1071,6 @@ void SaveManager::SaveBase() {
SaveManager::Instance->SaveArray("randomizerInf", ARRAY_COUNT(gSaveContext.randomizerInf), [](size_t i) { SaveManager::Instance->SaveArray("randomizerInf", ARRAY_COUNT(gSaveContext.randomizerInf), [](size_t i) {
SaveManager::Instance->SaveData("", gSaveContext.randomizerInf[i]); SaveManager::Instance->SaveData("", gSaveContext.randomizerInf[i]);
}); });
SaveManager::Instance->SaveArray("scrubsPurchased", ARRAY_COUNT(gSaveContext.scrubsPurchased), [](size_t i) {
SaveManager::Instance->SaveData("", gSaveContext.scrubsPurchased[i]);
});
} }
void SaveManager::SaveArray(const std::string& name, const size_t size, SaveArrayFunc func) { void SaveManager::SaveArray(const std::string& name, const size_t size, SaveArrayFunc func) {

View File

@ -709,11 +709,6 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) {
gSaveContext.randomizerInf[i] = 0; gSaveContext.randomizerInf[i] = 0;
} }
// Sets all scrubs to not purchased when generating a rando save.
for (u8 i = 0; i < NUM_SCRUBS; i++) {
gSaveContext.scrubsPurchased[i] = 0;
}
// Set Cutscene flags to skip them // Set Cutscene flags to skip them
gSaveContext.eventChkInf[0xC] |= 0x10; // returned to tot with medallions gSaveContext.eventChkInf[0xC] |= 0x10; // returned to tot with medallions
gSaveContext.eventChkInf[0xC] |= 0x20; //sheik at tot pedestal gSaveContext.eventChkInf[0xC] |= 0x20; //sheik at tot pedestal

View File

@ -181,6 +181,8 @@ void EnDns_Init(Actor* thisx, GlobalContext* globalCtx) {
this->dnsItemEntry->purchaseableCheck = EnDns_RandomizerPurchaseableCheck; this->dnsItemEntry->purchaseableCheck = EnDns_RandomizerPurchaseableCheck;
this->dnsItemEntry->setRupeesAndFlags = EnDns_RandomizerPurchase; this->dnsItemEntry->setRupeesAndFlags = EnDns_RandomizerPurchase;
this->dnsItemEntry->itemAmount = 1; this->dnsItemEntry->itemAmount = 1;
// Currently the textID is simply identified by the item price since that is the only thing
// unique to it, later on this will change to identifying by scrubIdentity.randomizerInf
this->actor.textId = 0x9000 + this->dnsItemEntry->itemPrice; this->actor.textId = 0x9000 + this->dnsItemEntry->itemPrice;
} }
} }
@ -205,7 +207,7 @@ void EnDns_ChangeAnim(EnDns* this, u8 index) {
/* Item give checking functions */ /* Item give checking functions */
u32 EnDns_RandomizerPurchaseableCheck(EnDns* this) { u32 EnDns_RandomizerPurchaseableCheck(EnDns* this) {
if (gSaveContext.rupees < this->dnsItemEntry->itemPrice || gSaveContext.scrubsPurchased[this->scrubIdentity.scrubId] == 1) { if (gSaveContext.rupees < this->dnsItemEntry->itemPrice || Flags_GetRandomizerInf(this->scrubIdentity.randomizerInf)) {
return 0; return 0;
} }
return 4; return 4;
@ -309,7 +311,7 @@ u32 func_809EF9A4(EnDns* this) {
/* Paying and flagging functions */ /* Paying and flagging functions */
void EnDns_RandomizerPurchase(EnDns* this) { void EnDns_RandomizerPurchase(EnDns* this) {
Rupees_ChangeBy(-this->dnsItemEntry->itemPrice); Rupees_ChangeBy(-this->dnsItemEntry->itemPrice);
gSaveContext.scrubsPurchased[this->scrubIdentity.scrubId] = 1; Flags_SetRandomizerInf(this->scrubIdentity.randomizerInf);
} }
void func_809EF9F8(EnDns* this) { void func_809EF9F8(EnDns* this) {
@ -514,6 +516,8 @@ void EnDns_Update(Actor* thisx, GlobalContext* globalCtx) {
this->dustTimer++; this->dustTimer++;
this->actor.textId = D_809F040C[this->actor.params]; this->actor.textId = D_809F040C[this->actor.params];
if (gSaveContext.n64ddFlag && this->scrubIdentity.isShuffled) { if (gSaveContext.n64ddFlag && this->scrubIdentity.isShuffled) {
// Currently the textID is simply identified by the item price since that is the only thing
// unique to it, later on this will change to identifying by scrubIdentity.randomizerInf
this->actor.textId = 0x9000 + this->dnsItemEntry->itemPrice; this->actor.textId = 0x9000 + this->dnsItemEntry->itemPrice;
} }
Actor_SetFocus(&this->actor, 60.0f); Actor_SetFocus(&this->actor, 60.0f);

View File

@ -73,7 +73,7 @@ void EnShopnuts_Init(Actor* thisx, GlobalContext* globalCtx) {
s16 respawnData = gSaveContext.respawn[RESPAWN_MODE_RETURN].data & ((1 << 8) - 1); s16 respawnData = gSaveContext.respawn[RESPAWN_MODE_RETURN].data & ((1 << 8) - 1);
ScrubIdentity scrubIdentity = Randomizer_IdentifyScrub(globalCtx->sceneNum, this->actor.params, respawnData); ScrubIdentity scrubIdentity = Randomizer_IdentifyScrub(globalCtx->sceneNum, this->actor.params, respawnData);
if (scrubIdentity.isShuffled && gSaveContext.scrubsPurchased[scrubIdentity.scrubId] == 1) { if (scrubIdentity.isShuffled && Flags_GetRandomizerInf(scrubIdentity.randomizerInf)) {
Actor_Kill(&this->actor); Actor_Kill(&this->actor);
} }
} }