mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2025-01-11 14:08:20 -05:00
commit
1cfa0a9623
@ -183,7 +183,7 @@ typedef struct {
|
||||
char ganonHintText[150];
|
||||
char ganonText[250];
|
||||
u8 seedIcons[5];
|
||||
u16 randomizerInf[2];
|
||||
u16 randomizerInf[4];
|
||||
u8 temporaryWeapon;
|
||||
u16 adultTradeItems;
|
||||
} SaveContext; // size = 0x1428
|
||||
|
@ -1039,6 +1039,19 @@ int Fill() {
|
||||
//Fast fill for the rest of the pool
|
||||
std::vector<uint32_t> remainingPool = FilterAndEraseFromPool(ItemPool, [](const auto i) { return true; });
|
||||
FastFill(remainingPool, GetAllEmptyLocations(), false);
|
||||
|
||||
//Add prices for scrubsanity, this is unique to SoH because we write/read scrub prices to/from the spoilerfile.
|
||||
if (Scrubsanity.Is(SCRUBSANITY_AFFORDABLE)) {
|
||||
for (size_t i = 0; i < ScrubLocations.size(); i++) {
|
||||
Location(ScrubLocations[i])->SetScrubsanityPrice(10);
|
||||
}
|
||||
} else if (Scrubsanity.Is(SCRUBSANITY_RANDOM_PRICES)) {
|
||||
for (size_t i = 0; i < ScrubLocations.size(); i++) {
|
||||
int randomPrice = GetRandomScrubPrice();
|
||||
Location(ScrubLocations[i])->SetScrubsanityPrice(randomPrice);
|
||||
}
|
||||
}
|
||||
|
||||
GeneratePlaythrough();
|
||||
//Successful placement, produced beatable result
|
||||
if(playthroughBeatable && !placementFailure) {
|
||||
|
@ -1011,6 +1011,56 @@ std::vector<std::vector<uint32_t>> ShopLocationLists = {
|
||||
GC_ShopLocations,
|
||||
};
|
||||
|
||||
//List of scrubs, used for pricing the scrubs
|
||||
std::vector<uint32_t> ScrubLocations = {
|
||||
LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT,
|
||||
LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT,
|
||||
LW_DEKU_SCRUB_NEAR_BRIDGE,
|
||||
LW_DEKU_SCRUB_GROTTO_REAR,
|
||||
LW_DEKU_SCRUB_GROTTO_FRONT,
|
||||
SFM_DEKU_SCRUB_GROTTO_REAR,
|
||||
SFM_DEKU_SCRUB_GROTTO_FRONT,
|
||||
HF_DEKU_SCRUB_GROTTO,
|
||||
LH_DEKU_SCRUB_GROTTO_LEFT,
|
||||
LH_DEKU_SCRUB_GROTTO_RIGHT,
|
||||
LH_DEKU_SCRUB_GROTTO_CENTER,
|
||||
GV_DEKU_SCRUB_GROTTO_REAR,
|
||||
GV_DEKU_SCRUB_GROTTO_FRONT,
|
||||
COLOSSUS_DEKU_SCRUB_GROTTO_REAR,
|
||||
COLOSSUS_DEKU_SCRUB_GROTTO_FRONT,
|
||||
GC_DEKU_SCRUB_GROTTO_LEFT,
|
||||
GC_DEKU_SCRUB_GROTTO_RIGHT,
|
||||
GC_DEKU_SCRUB_GROTTO_CENTER,
|
||||
DMC_DEKU_SCRUB,
|
||||
DMC_DEKU_SCRUB_GROTTO_LEFT,
|
||||
DMC_DEKU_SCRUB_GROTTO_RIGHT,
|
||||
DMC_DEKU_SCRUB_GROTTO_CENTER,
|
||||
ZR_DEKU_SCRUB_GROTTO_REAR,
|
||||
ZR_DEKU_SCRUB_GROTTO_FRONT,
|
||||
LLR_DEKU_SCRUB_GROTTO_LEFT,
|
||||
LLR_DEKU_SCRUB_GROTTO_RIGHT,
|
||||
LLR_DEKU_SCRUB_GROTTO_CENTER,
|
||||
DEKU_TREE_MQ_DEKU_SCRUB,
|
||||
DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT,
|
||||
DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS,
|
||||
DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT,
|
||||
DODONGOS_CAVERN_DEKU_SCRUB_LOBBY,
|
||||
DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR,
|
||||
DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT,
|
||||
DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE,
|
||||
DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS,
|
||||
JABU_JABUS_BELLY_DEKU_SCRUB,
|
||||
GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT,
|
||||
GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT,
|
||||
GANONS_CASTLE_DEKU_SCRUB_RIGHT,
|
||||
GANONS_CASTLE_DEKU_SCRUB_LEFT,
|
||||
GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT,
|
||||
GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT,
|
||||
GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER,
|
||||
GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT,
|
||||
GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT,
|
||||
};
|
||||
|
||||
//List of gossip stone locations for hints
|
||||
std::vector<uint32_t> gossipStoneLocations = {
|
||||
DMC_GOSSIP_STONE,
|
||||
|
@ -257,8 +257,8 @@ public:
|
||||
}
|
||||
|
||||
void SetPrice(uint16_t price_) {
|
||||
//don't override price if the price was set for shopsanity
|
||||
if (hasShopsanityPrice) {
|
||||
//don't override price if the price was set for shopsanity/scrubsanity
|
||||
if (hasShopsanityPrice || hasScrubsanityPrice) {
|
||||
return;
|
||||
}
|
||||
price = price_;
|
||||
@ -269,10 +269,19 @@ public:
|
||||
hasShopsanityPrice = true;
|
||||
}
|
||||
|
||||
void SetScrubsanityPrice(uint16_t price_) {
|
||||
price = price_;
|
||||
hasScrubsanityPrice = true;
|
||||
}
|
||||
|
||||
bool HasShopsanityPrice() const {
|
||||
return hasShopsanityPrice;
|
||||
}
|
||||
|
||||
bool HasScrubsanityPrice() const {
|
||||
return hasScrubsanityPrice;
|
||||
}
|
||||
|
||||
bool IsExcluded() const {
|
||||
return excludedOption.Value<bool>();
|
||||
}
|
||||
@ -426,6 +435,7 @@ public:
|
||||
isHintable = false;
|
||||
price = 0;
|
||||
hasShopsanityPrice = false;
|
||||
hasScrubsanityPrice = false;
|
||||
hidden = false;
|
||||
}
|
||||
|
||||
@ -451,6 +461,7 @@ private:
|
||||
bool isHintable = false;
|
||||
uint32_t parentRegion = NONE;
|
||||
bool hasShopsanityPrice = false;
|
||||
bool hasScrubsanityPrice = false;
|
||||
bool hidden = false;
|
||||
};
|
||||
|
||||
@ -467,6 +478,8 @@ ItemLocation* Location(uint32_t locKey);
|
||||
|
||||
extern std::vector<std::vector<uint32_t>> ShopLocationLists;
|
||||
|
||||
extern std::vector<uint32_t> ScrubLocations;
|
||||
|
||||
extern std::vector<uint32_t> gossipStoneLocations;
|
||||
|
||||
extern std::vector<uint32_t> dungeonRewardLocations;
|
||||
|
@ -2532,6 +2532,7 @@ namespace Settings {
|
||||
ShuffleRewards.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_DUNGEON_REWARDS]);
|
||||
ShuffleSongs.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_SONGS]);
|
||||
Tokensanity.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_TOKENS]);
|
||||
Scrubsanity.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_SCRUBS]);
|
||||
ShuffleCows.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_COWS]);
|
||||
ShuffleKokiriSword.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_KOKIRI_SWORD]);
|
||||
ShuffleOcarinas.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_OCARINA]);
|
||||
|
@ -673,15 +673,24 @@ static void WriteHints(int language) {
|
||||
static void WriteAllLocations(int language) {
|
||||
for (const uint32_t key : allLocations) {
|
||||
ItemLocation* location = Location(key);
|
||||
std::string placedItemName;
|
||||
|
||||
switch (language) {
|
||||
case 0:
|
||||
default:
|
||||
jsonData["locations"][location->GetName()] = location->GetPlacedItemName().english;
|
||||
break;
|
||||
case 2:
|
||||
jsonData["locations"][location->GetName()] = location->GetPlacedItemName().french;
|
||||
break;
|
||||
case 0:
|
||||
default:
|
||||
location->GetPlacedItemName().english;
|
||||
break;
|
||||
case 2:
|
||||
location->GetPlacedItemName().french;
|
||||
break;
|
||||
}
|
||||
|
||||
// Eventually check for other things here like fake name
|
||||
if (location->HasScrubsanityPrice() || location->HasShopsanityPrice()) {
|
||||
jsonData["locations"][location->GetName()]["item"] = placedItemName;
|
||||
jsonData["locations"][location->GetName()]["price"] = location->GetPrice();
|
||||
} else {
|
||||
jsonData["locations"][location->GetName()] = placedItemName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -104,6 +104,7 @@ Sprite* Randomizer::GetSeedTexture(uint8_t index) {
|
||||
Randomizer::~Randomizer() {
|
||||
this->randoSettings.clear();
|
||||
this->itemLocations.clear();
|
||||
this->randomizerMerchantPrices.clear();
|
||||
}
|
||||
|
||||
std::unordered_map<s16, s16> getItemIdToItemId = {
|
||||
@ -546,6 +547,7 @@ std::unordered_map<std::string, RandomizerSettingKey> SpoilerfileSettingNameToEn
|
||||
{ "Open Settings:Random Ganon's Trials", RSK_RANDOM_TRIALS },
|
||||
{ "Open Settings:Trial Count", RSK_TRIAL_COUNT },
|
||||
{ "Shuffle Settings:Shuffle Gerudo Card", RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD },
|
||||
{ "Shuffle Settings:Scrub Shuffle", RSK_SHUFFLE_SCRUBS },
|
||||
{ "Shuffle Settings:Shuffle Cows", RSK_SHUFFLE_COWS },
|
||||
{ "Shuffle Settings:Tokensanity", RSK_SHUFFLE_TOKENS },
|
||||
{ "Shuffle Settings:Shuffle Adult Trade", RSK_SHUFFLE_ADULT_TRADE },
|
||||
@ -772,6 +774,17 @@ void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) {
|
||||
numericValueString = it.value();
|
||||
gSaveContext.randoSettings[index].value = std::stoi(numericValueString);
|
||||
break;
|
||||
case RSK_SHUFFLE_SCRUBS:
|
||||
if(it.value() == "Off") {
|
||||
gSaveContext.randoSettings[index].value = 0;
|
||||
} else if(it.value() == "Affordable") {
|
||||
gSaveContext.randoSettings[index].value = 1;
|
||||
} else if(it.value() == "Expensive") {
|
||||
gSaveContext.randoSettings[index].value = 2;
|
||||
} else if(it.value() == "Random Prices") {
|
||||
gSaveContext.randoSettings[index].value = 3;
|
||||
}
|
||||
break;
|
||||
case RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD:
|
||||
case RSK_SHUFFLE_COWS:
|
||||
case RSK_SHUFFLE_ADULT_TRADE:
|
||||
@ -1102,9 +1115,10 @@ void Randomizer::ParseItemLocationsFile(const char* spoilerFileName, bool silent
|
||||
for (auto itemit = itemJson.begin(); itemit != itemJson.end(); ++itemit) {
|
||||
// todo handle prices
|
||||
if (itemit.key() == "item") {
|
||||
|
||||
gSaveContext.itemLocations[index].check = SpoilerfileCheckNameToEnum[it.key()];
|
||||
gSaveContext.itemLocations[index].get = SpoilerfileGetNameToEnum[itemit.value()];
|
||||
} else if (itemit.key() == "price") {
|
||||
randomizerMerchantPrices[gSaveContext.itemLocations[index].check] = itemit.value();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -1588,6 +1602,280 @@ std::string Randomizer::GetGanonHintText() const {
|
||||
return ganonHintText;
|
||||
}
|
||||
|
||||
ScrubIdentity Randomizer::IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respawnData) {
|
||||
struct ScrubIdentity scrubIdentity;
|
||||
|
||||
scrubIdentity.randomizerCheck = RC_UNKNOWN_CHECK;
|
||||
scrubIdentity.getItemId = GI_NONE;
|
||||
scrubIdentity.itemPrice = -1;
|
||||
scrubIdentity.isShuffled = GetRandoSettingValue(RSK_SHUFFLE_SCRUBS) > 0;
|
||||
|
||||
// Based on z_en_dns.c 93-113
|
||||
switch (actorParams) {
|
||||
case 0x00:
|
||||
scrubIdentity.getItemId = GI_NUTS_5_2;
|
||||
break;
|
||||
case 0x01:
|
||||
scrubIdentity.getItemId = GI_STICKS_1;
|
||||
break;
|
||||
case 0x02:
|
||||
scrubIdentity.getItemId = GI_HEART_PIECE;
|
||||
break;
|
||||
case 0x03:
|
||||
scrubIdentity.getItemId = GI_SEEDS_30;
|
||||
break;
|
||||
case 0x04:
|
||||
scrubIdentity.getItemId = GI_SHIELD_DEKU;
|
||||
break;
|
||||
case 0x05:
|
||||
scrubIdentity.getItemId = GI_BOMBS_5;
|
||||
break;
|
||||
case 0x06:
|
||||
scrubIdentity.getItemId = GI_ARROWS_LARGE;
|
||||
break;
|
||||
case 0x07:
|
||||
scrubIdentity.getItemId = GI_POTION_RED;
|
||||
break;
|
||||
case 0x08:
|
||||
scrubIdentity.getItemId = GI_POTION_GREEN;
|
||||
break;
|
||||
case 0x09:
|
||||
scrubIdentity.getItemId = GI_STICK_UPGRADE_20;
|
||||
break;
|
||||
case 0x0A:
|
||||
scrubIdentity.getItemId = GI_NUT_UPGRADE_30;
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO: Handle MQ scrubs
|
||||
switch (sceneNum) {
|
||||
case SCENE_DDAN: // Dodongo's Cavern
|
||||
switch (actorParams) {
|
||||
case 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;
|
||||
break;
|
||||
case 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;
|
||||
break;
|
||||
case 0x03:
|
||||
case 0x06:
|
||||
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;
|
||||
break;
|
||||
case 0x04:
|
||||
scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY;
|
||||
scrubIdentity.randomizerCheck = RC_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SCENE_BDAN: // Jabu Jabu's Belly
|
||||
switch (actorParams) {
|
||||
case 0x00:
|
||||
scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_JABU_JABUS_BELLY_DEKU_SCRUB;
|
||||
scrubIdentity.randomizerCheck = RC_JABU_JABUS_BELLY_DEKU_SCRUB;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SCENE_GANONTIKA: // Ganon's Castle
|
||||
switch (actorParams) {
|
||||
case 0x05:
|
||||
scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT;
|
||||
scrubIdentity.randomizerCheck = RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT;
|
||||
break;
|
||||
case 0x03:
|
||||
case 0x06:
|
||||
scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT;
|
||||
scrubIdentity.randomizerCheck = RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT;
|
||||
break;
|
||||
case 0x07:
|
||||
scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_RIGHT;
|
||||
scrubIdentity.randomizerCheck = RC_GANONS_CASTLE_DEKU_SCRUB_RIGHT;
|
||||
break;
|
||||
case 0x08:
|
||||
scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_GANONS_CASTLE_DEKU_SCRUB_LEFT;
|
||||
scrubIdentity.randomizerCheck = RC_GANONS_CASTLE_DEKU_SCRUB_LEFT;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SCENE_KAKUSIANA: // Grotto
|
||||
switch (respawnData) {
|
||||
case 0xE6: // Hyrule Field Scrub Grotto
|
||||
switch (actorParams) {
|
||||
case 0x02:
|
||||
scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_HF_DEKU_SCRUB_GROTTO;
|
||||
scrubIdentity.randomizerCheck = RC_HF_DEKU_SCRUB_GROTTO;
|
||||
scrubIdentity.isShuffled = true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0xEB: // ZR Scrub Grotto
|
||||
switch (actorParams) {
|
||||
case 0x07:
|
||||
scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_ZR_DEKU_SCRUB_GROTTO_REAR;
|
||||
scrubIdentity.randomizerCheck = RC_ZR_DEKU_SCRUB_GROTTO_REAR;
|
||||
break;
|
||||
case 0x08:
|
||||
scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_ZR_DEKU_SCRUB_GROTTO_FRONT;
|
||||
scrubIdentity.randomizerCheck = RC_ZR_DEKU_SCRUB_GROTTO_FRONT;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0xEE: // Sacred Forest Meadow Scrub Grotto
|
||||
switch (actorParams) {
|
||||
case 0x07:
|
||||
scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_SFM_DEKU_SCRUB_GROTTO_REAR;
|
||||
scrubIdentity.randomizerCheck = RC_SFM_DEKU_SCRUB_GROTTO_REAR;
|
||||
break;
|
||||
case 0x08:
|
||||
scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_SFM_DEKU_SCRUB_GROTTO_FRONT;
|
||||
scrubIdentity.randomizerCheck = RC_SFM_DEKU_SCRUB_GROTTO_FRONT;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0xEF: // Lake Hylia Scrub Grotto
|
||||
switch (actorParams) {
|
||||
case 0x00:
|
||||
scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_LH_DEKU_SCRUB_GROTTO_LEFT;
|
||||
scrubIdentity.randomizerCheck = RC_LH_DEKU_SCRUB_GROTTO_LEFT;
|
||||
break;
|
||||
case 0x05:
|
||||
scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_LH_DEKU_SCRUB_GROTTO_RIGHT;
|
||||
scrubIdentity.randomizerCheck = RC_LH_DEKU_SCRUB_GROTTO_RIGHT;
|
||||
break;
|
||||
case 0x03:
|
||||
case 0x06:
|
||||
scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_LH_DEKU_SCRUB_GROTTO_CENTER;
|
||||
scrubIdentity.randomizerCheck = RC_LH_DEKU_SCRUB_GROTTO_CENTER;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0xF0: // Gerudo Valley Scrub Grotto
|
||||
switch (actorParams) {
|
||||
case 0x07:
|
||||
scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_GV_DEKU_SCRUB_GROTTO_REAR;
|
||||
scrubIdentity.randomizerCheck = RC_GV_DEKU_SCRUB_GROTTO_REAR;
|
||||
break;
|
||||
case 0x08:
|
||||
scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_GV_DEKU_SCRUB_GROTTO_FRONT;
|
||||
scrubIdentity.randomizerCheck = RC_GV_DEKU_SCRUB_GROTTO_FRONT;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0xF5: // Lost Woods Scrub Grotto
|
||||
switch (actorParams) {
|
||||
case 0x03:
|
||||
case 0x06:
|
||||
scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_GROTTO_REAR;
|
||||
scrubIdentity.randomizerCheck = RC_LW_DEKU_SCRUB_GROTTO_REAR;
|
||||
break;
|
||||
case 0x0A:
|
||||
scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_GROTTO_FRONT;
|
||||
scrubIdentity.randomizerCheck = RC_LW_DEKU_SCRUB_GROTTO_FRONT;
|
||||
scrubIdentity.isShuffled = true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0xF9: // Death Mountain Crater Scrub Grotto
|
||||
switch (actorParams) {
|
||||
case 0x00:
|
||||
scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB_GROTTO_LEFT;
|
||||
scrubIdentity.randomizerCheck = RC_DMC_DEKU_SCRUB_GROTTO_LEFT;
|
||||
break;
|
||||
case 0x05:
|
||||
scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB_GROTTO_RIGHT;
|
||||
scrubIdentity.randomizerCheck = RC_DMC_DEKU_SCRUB_GROTTO_RIGHT;
|
||||
break;
|
||||
case 0x03:
|
||||
case 0x06:
|
||||
scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB_GROTTO_CENTER;
|
||||
scrubIdentity.randomizerCheck = RC_DMC_DEKU_SCRUB_GROTTO_CENTER;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0xFB: // Gerudo City Scrub Grotto
|
||||
switch (actorParams) {
|
||||
case 0x00:
|
||||
scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_GC_DEKU_SCRUB_GROTTO_LEFT;
|
||||
scrubIdentity.randomizerCheck = RC_GC_DEKU_SCRUB_GROTTO_LEFT;
|
||||
break;
|
||||
case 0x05:
|
||||
scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_GC_DEKU_SCRUB_GROTTO_RIGHT;
|
||||
scrubIdentity.randomizerCheck = RC_GC_DEKU_SCRUB_GROTTO_RIGHT;
|
||||
break;
|
||||
case 0x03:
|
||||
case 0x06:
|
||||
scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_GC_DEKU_SCRUB_GROTTO_CENTER;
|
||||
scrubIdentity.randomizerCheck = RC_GC_DEKU_SCRUB_GROTTO_CENTER;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0xFC: // Lon Lon Ranch Scrub Grotto
|
||||
switch (actorParams) {
|
||||
case 0x00:
|
||||
scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_LEFT;
|
||||
scrubIdentity.randomizerCheck = RC_LLR_DEKU_SCRUB_GROTTO_LEFT;
|
||||
break;
|
||||
case 0x05:
|
||||
scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_RIGHT;
|
||||
scrubIdentity.randomizerCheck = RC_LLR_DEKU_SCRUB_GROTTO_RIGHT;
|
||||
break;
|
||||
case 0x03:
|
||||
case 0x06:
|
||||
scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_LLR_DEKU_SCRUB_GROTTO_CENTER;
|
||||
scrubIdentity.randomizerCheck = RC_LLR_DEKU_SCRUB_GROTTO_CENTER;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0xFD: // Desert Colossus Scrub Grotto
|
||||
switch (actorParams) {
|
||||
case 0x07:
|
||||
scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_COLOSSUS_DEKU_SCRUB_GROTTO_REAR;
|
||||
scrubIdentity.randomizerCheck = RC_COLOSSUS_DEKU_SCRUB_GROTTO_REAR;
|
||||
break;
|
||||
case 0x08:
|
||||
scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT;
|
||||
scrubIdentity.randomizerCheck = RC_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SCENE_SPOT10: // Lost woods
|
||||
switch (actorParams) {
|
||||
case 0x00:
|
||||
scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT;
|
||||
scrubIdentity.randomizerCheck = RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT;
|
||||
break;
|
||||
case 0x01:
|
||||
scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT;
|
||||
scrubIdentity.randomizerCheck = RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT;
|
||||
break;
|
||||
case 0x09:
|
||||
scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_BRIDGE;
|
||||
scrubIdentity.randomizerCheck = RC_LW_DEKU_SCRUB_NEAR_BRIDGE;
|
||||
scrubIdentity.isShuffled = true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SCENE_SPOT17: // Death Mountain Crater
|
||||
switch (actorParams) {
|
||||
case 0x05:
|
||||
scrubIdentity.randomizerInf = RAND_INF_SCRUBS_PURCHASED_DMC_DEKU_SCRUB;
|
||||
scrubIdentity.randomizerCheck = RC_DMC_DEKU_SCRUB;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (randomizerMerchantPrices.find(scrubIdentity.randomizerCheck) != randomizerMerchantPrices.end()) {
|
||||
scrubIdentity.itemPrice = randomizerMerchantPrices[scrubIdentity.randomizerCheck];
|
||||
}
|
||||
|
||||
return scrubIdentity;
|
||||
}
|
||||
|
||||
u8 Randomizer::GetRandoSettingValue(RandomizerSettingKey randoSettingKey) {
|
||||
return this->randoSettings[randoSettingKey];
|
||||
}
|
||||
@ -2181,10 +2469,6 @@ RandomizerCheck Randomizer::GetCheckFromActor(s16 sceneNum, s16 actorId, s16 act
|
||||
break;
|
||||
case 62:
|
||||
switch (actorParams) {
|
||||
case 2:
|
||||
return RC_HF_DEKU_SCRUB_GROTTO;
|
||||
case 10:
|
||||
return RC_LW_DEKU_SCRUB_GROTTO_FRONT;
|
||||
case 22988:
|
||||
return RC_KF_STORMS_GROTTO_CHEST;
|
||||
case -22988:
|
||||
@ -2449,8 +2733,6 @@ RandomizerCheck Randomizer::GetCheckFromActor(s16 sceneNum, s16 actorId, s16 act
|
||||
break;
|
||||
case 91:
|
||||
switch (actorParams) {
|
||||
case 9:
|
||||
return RC_LW_DEKU_SCRUB_NEAR_BRIDGE;
|
||||
case 14365:
|
||||
return RC_LW_GOSSIP_STONE;
|
||||
case 27905:
|
||||
@ -2615,6 +2897,7 @@ void GenerateRandomizerImgui() {
|
||||
cvarSettings[RSK_SHUFFLE_DUNGEON_REWARDS] = CVar_GetS32("gRandomizeShuffleDungeonReward", 0);
|
||||
cvarSettings[RSK_SHUFFLE_SONGS] = CVar_GetS32("gRandomizeShuffleSongs", 0);
|
||||
cvarSettings[RSK_SHUFFLE_TOKENS] = CVar_GetS32("gRandomizeShuffleTokens", 0);
|
||||
cvarSettings[RSK_SHUFFLE_SCRUBS] = CVar_GetS32("gRandomizeShuffleScrubs", 0);
|
||||
cvarSettings[RSK_SHUFFLE_COWS] = CVar_GetS32("gRandomizeShuffleCows", 0);
|
||||
cvarSettings[RSK_SHUFFLE_ADULT_TRADE] = CVar_GetS32("gRandomizeShuffleAdultTrade", 0);
|
||||
cvarSettings[RSK_SKIP_CHILD_ZELDA] = CVar_GetS32("gRandomizeSkipChildZelda", 0);
|
||||
@ -3111,6 +3394,20 @@ void DrawRandoEditor(bool& open) {
|
||||
SohImGui::EnhancementCombobox("gRandomizeShuffleSongs", randoShuffleSongs, 3, 0);
|
||||
PaddedSeparator();
|
||||
|
||||
// Shuffle Scrubs
|
||||
ImGui::Text(Settings::Scrubsanity.GetName().c_str());
|
||||
InsertHelpHoverText(
|
||||
"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"
|
||||
"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);
|
||||
PaddedSeparator();
|
||||
|
||||
// Shuffle Tokens
|
||||
ImGui::Text(Settings::Tokensanity.GetName().c_str());
|
||||
InsertHelpHoverText("Shuffles Golden Skulltula Tokens into the item pool. This means "
|
||||
@ -3131,10 +3428,10 @@ void DrawRandoEditor(bool& open) {
|
||||
"expected to be collected after getting Sun's Song.");
|
||||
PaddedSeparator();
|
||||
|
||||
|
||||
// Shuffle Cows
|
||||
SohImGui::EnhancementCheckbox(Settings::ShuffleCows.GetName().c_str(), "gRandomizeShuffleCows");
|
||||
InsertHelpHoverText(
|
||||
"Cows give a randomized item from the pool upon performing Epona's Song in front of them.");
|
||||
InsertHelpHoverText("Cows give a randomized item from the pool upon performing Epona's Song in front of them.");
|
||||
PaddedSeparator();
|
||||
|
||||
// Shuffle Adult Trade Quest
|
||||
@ -3725,11 +4022,19 @@ 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() {
|
||||
CustomMessageManager* customMessageManager = CustomMessageManager::Instance;
|
||||
customMessageManager->AddCustomMessageTable(Randomizer::scrubMessageTableID);
|
||||
const std::vector<u8> prices = { 10, 40 };
|
||||
for (u8 price : prices) {
|
||||
customMessageManager->CreateMessage(Randomizer::scrubMessageTableID, 0,
|
||||
{ TEXTBOX_TYPE_BLACK, TEXTBOX_POS_BOTTOM,
|
||||
"\x12\x38\x82\All right! You win! In return for&sparing me, I will give you a&%gmysterious item%w!&Please, take it!\x07\x10\xA3",
|
||||
"\x12\x38\x82\In Ordnung! Du gewinnst! Im Austausch&dafür, dass du mich verschont hast,&werde ich dir einen %gmysteriösen&Gegenstand%w geben! Bitte nimm ihn!\x07\x10\xA3",
|
||||
"\x12\x38\x82\D'accord! Vous avez gagné! En échange&de m'épargner, je vous donnerai un &%gobjet mystérieux%w! S'il vous plaît,&prenez-le!\x07\x10\xA3",
|
||||
});
|
||||
|
||||
for (u32 price = 5; price <= 95; price += 5) {
|
||||
customMessageManager->CreateMessage(Randomizer::scrubMessageTableID, price,
|
||||
{ TEXTBOX_TYPE_BLACK, TEXTBOX_POS_BOTTOM,
|
||||
"\x12\x38\x82\All right! You win! In return for&sparing me, I will sell you a&%gmysterious item%w!&%r" +
|
||||
|
@ -19,6 +19,7 @@ class Randomizer {
|
||||
std::string ganonHintText;
|
||||
std::string ganonText;
|
||||
std::unordered_map<RandomizerSettingKey, u8> randoSettings;
|
||||
std::unordered_map<RandomizerCheck, u16> randomizerMerchantPrices;
|
||||
s16 GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId);
|
||||
s16 GetItemFromActor(s16 actorId, s16 actorParams, s16 sceneNum, GetItemID ogItemId);
|
||||
void ParseRandomizerSettingsFile(const char* spoilerFileName);
|
||||
@ -50,6 +51,7 @@ class Randomizer {
|
||||
std::string GetAdultAltarText() const;
|
||||
std::string GetGanonText() const;
|
||||
std::string GetGanonHintText() const;
|
||||
ScrubIdentity IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respawnData);
|
||||
s16 GetRandomizedItemIdFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogId);
|
||||
s16 GetRandomizedItemId(GetItemID ogId, s16 actorId, s16 actorParams, s16 sceneNum);
|
||||
static void CreateCustomMessages();
|
||||
|
@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "z64item.h"
|
||||
#include "randomizer_inf.h"
|
||||
|
||||
// This should probably go in a less rando-specific location
|
||||
// but the best location will probably be in the modding engine
|
||||
@ -987,6 +989,7 @@ typedef enum {
|
||||
RSK_SHUFFLE_DUNGEON_REWARDS,
|
||||
RSK_SHUFFLE_SONGS,
|
||||
RSK_SHUFFLE_TOKENS,
|
||||
RSK_SHUFFLE_SCRUBS,
|
||||
RSK_SHUFFLE_COWS,
|
||||
RSK_SHUFFLE_WEIRD_EGG,
|
||||
RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD,
|
||||
@ -1015,3 +1018,11 @@ typedef enum {
|
||||
RSK_SKULLS_SUNS_SONG,
|
||||
RSK_SHUFFLE_ADULT_TRADE
|
||||
} RandomizerSettingKey;
|
||||
|
||||
typedef struct ScrubIdentity {
|
||||
RandomizerInf randomizerInf;
|
||||
RandomizerCheck randomizerCheck;
|
||||
GetItemID getItemId;
|
||||
int32_t itemPrice;
|
||||
bool isShuffled;
|
||||
} ScrubIdentity;
|
||||
|
@ -29,6 +29,43 @@ typedef enum {
|
||||
RAND_INF_COWS_MILKED_JABU_JABUS_BELLY_MQ_COW,
|
||||
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)
|
||||
|
||||
RAND_INF_MAX,
|
||||
|
@ -1578,18 +1578,12 @@ extern "C" RandomizerCheck Randomizer_GetCheckFromActor(s16 sceneNum, s16 actorI
|
||||
return OTRGlobals::Instance->gRandomizer->GetCheckFromActor(sceneNum, actorId, actorParams);
|
||||
}
|
||||
|
||||
extern "C" CustomMessageEntry Randomizer_GetScrubMessage(u16 scrubTextId) {
|
||||
int price = 0;
|
||||
switch (scrubTextId) {
|
||||
case TEXT_SCRUB_POH:
|
||||
price = 10;
|
||||
break;
|
||||
case TEXT_SCRUB_STICK_UPGRADE:
|
||||
case TEXT_SCRUB_NUT_UPGRADE:
|
||||
price = 40;
|
||||
break;
|
||||
}
|
||||
return CustomMessageManager::Instance->RetrieveMessage(Randomizer::scrubMessageTableID, price);
|
||||
extern "C" ScrubIdentity Randomizer_IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respawnData) {
|
||||
return OTRGlobals::Instance->gRandomizer->IdentifyScrub(sceneNum, actorParams, respawnData);
|
||||
}
|
||||
|
||||
extern "C" CustomMessageEntry Randomizer_GetScrubMessage(s16 itemPrice) {
|
||||
return CustomMessageManager::Instance->RetrieveMessage(Randomizer::scrubMessageTableID, itemPrice);
|
||||
}
|
||||
|
||||
extern "C" CustomMessageEntry Randomizer_GetNaviMessage() {
|
||||
@ -1718,8 +1712,8 @@ extern "C" int CustomMessage_RetrieveIfExists(GlobalContext* globalCtx) {
|
||||
} else {
|
||||
messageEntry = Randomizer_GetGanonHintText();
|
||||
}
|
||||
} else if (textId == TEXT_SCRUB_POH || textId == TEXT_SCRUB_STICK_UPGRADE || textId == TEXT_SCRUB_NUT_UPGRADE) {
|
||||
messageEntry = Randomizer_GetScrubMessage(textId);
|
||||
} else if (textId >= 0x9000 && textId <= 0x905F) {
|
||||
messageEntry = Randomizer_GetScrubMessage((textId & ((1 << 8) - 1)));
|
||||
} else if (CVar_GetS32("gRandomizeRupeeNames", 0) &&
|
||||
(textId == TEXT_BLUE_RUPEE || textId == TEXT_RED_RUPEE || textId == TEXT_PURPLE_RUPEE ||
|
||||
textId == TEXT_HUGE_RUPEE)) {
|
||||
|
@ -96,6 +96,7 @@ Sprite* GetSeedTexture(uint8_t index);
|
||||
void Randomizer_LoadSettings(const char* spoilerFileName);
|
||||
u8 Randomizer_GetSettingValue(RandomizerSettingKey randoSettingKey);
|
||||
RandomizerCheck Randomizer_GetCheckFromActor(s16 actorId, s16 actorParams, s16 sceneNum);
|
||||
ScrubIdentity Randomizer_IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respawnData);
|
||||
void Randomizer_LoadHintLocations(const char* spoilerFileName);
|
||||
void Randomizer_LoadItemLocations(const char* spoilerFileName, bool silent);
|
||||
GetItemEntry Randomizer_GetRandomizedItem(GetItemID ogId, s16 actorId, s16 actorParams, s16 sceneNum);
|
||||
|
@ -8,6 +8,7 @@
|
||||
#define NUM_DUNGEONS 8
|
||||
#define NUM_TRIALS 6
|
||||
#define NUM_COWS 10
|
||||
#define NUM_SCRUBS 35
|
||||
|
||||
/**
|
||||
* Initialize new save.
|
||||
|
@ -15,6 +15,7 @@ void EnDns_Destroy(Actor* thisx, GlobalContext* globalCtx);
|
||||
void EnDns_Update(Actor* thisx, GlobalContext* globalCtx);
|
||||
void EnDns_Draw(Actor* thisx, GlobalContext* globalCtx);
|
||||
|
||||
u32 EnDns_RandomizerPurchaseableCheck(EnDns* this);
|
||||
u32 func_809EF5A4(EnDns* this);
|
||||
u32 func_809EF658(EnDns* this);
|
||||
u32 func_809EF70C(EnDns* this);
|
||||
@ -24,6 +25,7 @@ u32 func_809EF854(EnDns* this);
|
||||
u32 func_809EF8F4(EnDns* this);
|
||||
u32 func_809EF9A4(EnDns* this);
|
||||
|
||||
void EnDns_RandomizerPurchase(EnDns* this);
|
||||
void func_809EF9F8(EnDns* this);
|
||||
void func_809EFA28(EnDns* this);
|
||||
void func_809EFA58(EnDns* this);
|
||||
@ -155,7 +157,6 @@ void EnDns_Init(Actor* thisx, GlobalContext* globalCtx) {
|
||||
Collider_InitCylinder(globalCtx, &this->collider);
|
||||
Collider_SetCylinderType1(globalCtx, &this->collider, &this->actor, &sCylinderInit);
|
||||
ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 35.0f);
|
||||
this->actor.textId = D_809F040C[this->actor.params];
|
||||
Actor_SetScale(&this->actor, 0.01f);
|
||||
this->actor.colChkInfo.mass = MASS_IMMOVABLE;
|
||||
this->maintainCollider = 1;
|
||||
@ -164,7 +165,27 @@ void EnDns_Init(Actor* thisx, GlobalContext* globalCtx) {
|
||||
this->actor.speedXZ = 0.0f;
|
||||
this->actor.velocity.y = 0.0f;
|
||||
this->actor.gravity = -1.0f;
|
||||
this->actor.textId = D_809F040C[this->actor.params];
|
||||
this->dnsItemEntry = sItemEntries[this->actor.params];
|
||||
if (gSaveContext.n64ddFlag) {
|
||||
// Ugly, but the best way we can identify which grotto we are in, same method 3DRando uses, but we'll need to account for entrance rando
|
||||
s16 respawnData = gSaveContext.respawn[RESPAWN_MODE_RETURN].data & ((1 << 8) - 1);
|
||||
this->scrubIdentity = Randomizer_IdentifyScrub(globalCtx->sceneNum, this->actor.params, respawnData);
|
||||
|
||||
if (Randomizer_GetSettingValue(RSK_SHUFFLE_SCRUBS) == 1 || Randomizer_GetSettingValue(RSK_SHUFFLE_SCRUBS) == 3 && this->scrubIdentity.itemPrice != -1) {
|
||||
this->dnsItemEntry->itemPrice = this->scrubIdentity.itemPrice;
|
||||
}
|
||||
|
||||
if (this->scrubIdentity.isShuffled) {
|
||||
this->dnsItemEntry->getItemId = this->scrubIdentity.getItemId;
|
||||
this->dnsItemEntry->purchaseableCheck = EnDns_RandomizerPurchaseableCheck;
|
||||
this->dnsItemEntry->setRupeesAndFlags = EnDns_RandomizerPurchase;
|
||||
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->actionFunc = EnDns_SetupWait;
|
||||
}
|
||||
|
||||
@ -185,6 +206,13 @@ void EnDns_ChangeAnim(EnDns* this, u8 index) {
|
||||
|
||||
/* Item give checking functions */
|
||||
|
||||
u32 EnDns_RandomizerPurchaseableCheck(EnDns* this) {
|
||||
if (gSaveContext.rupees < this->dnsItemEntry->itemPrice || Flags_GetRandomizerInf(this->scrubIdentity.randomizerInf)) {
|
||||
return 0;
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
u32 func_809EF5A4(EnDns* this) {
|
||||
if ((CUR_CAPACITY(UPG_NUTS) != 0) && (AMMO(ITEM_NUT) >= CUR_CAPACITY(UPG_NUTS))) {
|
||||
return 1;
|
||||
@ -281,6 +309,10 @@ u32 func_809EF9A4(EnDns* this) {
|
||||
}
|
||||
|
||||
/* Paying and flagging functions */
|
||||
void EnDns_RandomizerPurchase(EnDns* this) {
|
||||
Rupees_ChangeBy(-this->dnsItemEntry->itemPrice);
|
||||
Flags_SetRandomizerInf(this->scrubIdentity.randomizerInf);
|
||||
}
|
||||
|
||||
void func_809EF9F8(EnDns* this) {
|
||||
Rupees_ChangeBy(-this->dnsItemEntry->itemPrice);
|
||||
@ -369,31 +401,25 @@ void EnDns_Talk(EnDns* this, GlobalContext* globalCtx) {
|
||||
}
|
||||
|
||||
void func_809EFDD0(EnDns* this, GlobalContext* globalCtx) {
|
||||
if (this->actor.params == 0x9) {
|
||||
if (gSaveContext.n64ddFlag) {
|
||||
GetItemEntry getItemEntry = Randomizer_GetRandomizedItem(GI_STICK_UPGRADE_30, this->actor.id, this->actor.params, globalCtx->sceneNum);
|
||||
GiveItemEntryFromActor(&this->actor, globalCtx, getItemEntry, 130.0f, 100.0f);
|
||||
} else if (CUR_UPG_VALUE(UPG_STICKS) < 2) {
|
||||
func_8002F434(&this->actor, globalCtx, GI_STICK_UPGRADE_20, 130.0f, 100.0f);
|
||||
if (!gSaveContext.n64ddFlag || !this->scrubIdentity.isShuffled) {
|
||||
if (this->actor.params == 0x9) {
|
||||
if (CUR_UPG_VALUE(UPG_STICKS) < 2) {
|
||||
func_8002F434(&this->actor, globalCtx, GI_STICK_UPGRADE_20, 130.0f, 100.0f);
|
||||
} else {
|
||||
func_8002F434(&this->actor, globalCtx, GI_STICK_UPGRADE_30, 130.0f, 100.0f);
|
||||
}
|
||||
} else if (this->actor.params == 0xA) {
|
||||
if (CUR_UPG_VALUE(UPG_NUTS) < 2) {
|
||||
func_8002F434(&this->actor, globalCtx, GI_NUT_UPGRADE_30, 130.0f, 100.0f);
|
||||
} else {
|
||||
func_8002F434(&this->actor, globalCtx, GI_NUT_UPGRADE_40, 130.0f, 100.0f);
|
||||
}
|
||||
} else {
|
||||
func_8002F434(&this->actor, globalCtx, GI_STICK_UPGRADE_30, 130.0f, 100.0f);
|
||||
}
|
||||
} else if (this->actor.params == 0xA) {
|
||||
if (gSaveContext.n64ddFlag) {
|
||||
GetItemEntry getItemEntry = Randomizer_GetRandomizedItem(GI_NUT_UPGRADE_40, this->actor.id, this->actor.params, globalCtx->sceneNum);
|
||||
GiveItemEntryFromActor(&this->actor, globalCtx, getItemEntry, 130.0f, 100.0f);
|
||||
} else if (CUR_UPG_VALUE(UPG_NUTS) < 2) {
|
||||
func_8002F434(&this->actor, globalCtx, GI_NUT_UPGRADE_30, 130.0f, 100.0f);
|
||||
} else {
|
||||
func_8002F434(&this->actor, globalCtx, GI_NUT_UPGRADE_40, 130.0f, 100.0f);
|
||||
func_8002F434(&this->actor, globalCtx, this->dnsItemEntry->getItemId, 130.0f, 100.0f);
|
||||
}
|
||||
} else {
|
||||
if (!gSaveContext.n64ddFlag) {
|
||||
func_8002F434(&this->actor, globalCtx, this->dnsItemEntry->getItemId, 130.0f, 100.0f);
|
||||
} else {
|
||||
GetItemEntry getItemEntry = Randomizer_GetRandomizedItem(this->dnsItemEntry->getItemId, this->actor.id, this->actor.params, globalCtx->sceneNum);
|
||||
GiveItemEntryFromActor(&this->actor, globalCtx, getItemEntry, 130.0f, 100.0f);
|
||||
}
|
||||
GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(this->scrubIdentity.randomizerCheck, this->scrubIdentity.getItemId);
|
||||
GiveItemEntryFromActor(&this->actor, globalCtx, itemEntry, 130.0f, 100.0f);
|
||||
}
|
||||
}
|
||||
|
||||
@ -489,6 +515,11 @@ void EnDns_Update(Actor* thisx, GlobalContext* globalCtx) {
|
||||
|
||||
this->dustTimer++;
|
||||
this->actor.textId = D_809F040C[this->actor.params];
|
||||
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;
|
||||
}
|
||||
Actor_SetFocus(&this->actor, 60.0f);
|
||||
Actor_SetScale(&this->actor, 0.01f);
|
||||
SkelAnime_Update(&this->skelAnime);
|
||||
|
@ -32,6 +32,7 @@ typedef struct EnDns {
|
||||
/* 0x02BD */ u8 dropCollectible;
|
||||
/* 0x02C0 */ DnsItemEntry* dnsItemEntry;
|
||||
/* 0x02C4 */ f32 yInitPos;
|
||||
/* */ ScrubIdentity scrubIdentity;
|
||||
} EnDns; // size = 0x02C8
|
||||
|
||||
#endif
|
||||
|
@ -69,6 +69,15 @@ void EnShopnuts_Init(Actor* thisx, GlobalContext* globalCtx) {
|
||||
CollisionCheck_SetInfo(&this->actor.colChkInfo, NULL, &sColChkInfoInit);
|
||||
Collider_UpdateCylinder(&this->actor, &this->collider);
|
||||
|
||||
if (gSaveContext.n64ddFlag) {
|
||||
s16 respawnData = gSaveContext.respawn[RESPAWN_MODE_RETURN].data & ((1 << 8) - 1);
|
||||
ScrubIdentity scrubIdentity = Randomizer_IdentifyScrub(globalCtx->sceneNum, this->actor.params, respawnData);
|
||||
|
||||
if (scrubIdentity.isShuffled && Flags_GetRandomizerInf(scrubIdentity.randomizerInf)) {
|
||||
Actor_Kill(&this->actor);
|
||||
}
|
||||
}
|
||||
|
||||
if (((this->actor.params == 0x0002) && (gSaveContext.itemGetInf[0] & 0x800)) ||
|
||||
((this->actor.params == 0x0009) && (gSaveContext.infTable[25] & 4)) ||
|
||||
((this->actor.params == 0x000A) && (gSaveContext.infTable[25] & 8))) {
|
||||
|
Loading…
Reference in New Issue
Block a user