mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2024-11-10 11:35:19 -05:00
Initial work towards scrubsanity, got affordable prices mostly functional
Write and read prices from spoiler, move IdentifyScrub up to Randomizer In a semi working state Fix bug when going from c to cpp Kill scrubs before they spawn if already purchased Woopsie from rebase Update soh/soh/OTRGlobals.cpp
This commit is contained in:
parent
d17e4dc042
commit
9f63aaae99
@ -185,6 +185,7 @@ typedef struct {
|
|||||||
u8 dungeonsDone[8];
|
u8 dungeonsDone[8];
|
||||||
u8 trialsDone[6];
|
u8 trialsDone[6];
|
||||||
u8 cowsMilked[10];
|
u8 cowsMilked[10];
|
||||||
|
u8 scrubsPurchased[35];
|
||||||
u8 temporaryWeapon;
|
u8 temporaryWeapon;
|
||||||
u16 adultTradeItems;
|
u16 adultTradeItems;
|
||||||
} SaveContext; // size = 0x1428
|
} SaveContext; // size = 0x1428
|
||||||
|
@ -1039,6 +1039,19 @@ int Fill() {
|
|||||||
//Fast fill for the rest of the pool
|
//Fast fill for the rest of the pool
|
||||||
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
|
||||||
|
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();
|
GeneratePlaythrough();
|
||||||
//Successful placement, produced beatable result
|
//Successful placement, produced beatable result
|
||||||
if(playthroughBeatable && !placementFailure) {
|
if(playthroughBeatable && !placementFailure) {
|
||||||
|
@ -1011,6 +1011,56 @@ std::vector<std::vector<uint32_t>> ShopLocationLists = {
|
|||||||
GC_ShopLocations,
|
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
|
//List of gossip stone locations for hints
|
||||||
std::vector<uint32_t> gossipStoneLocations = {
|
std::vector<uint32_t> gossipStoneLocations = {
|
||||||
DMC_GOSSIP_STONE,
|
DMC_GOSSIP_STONE,
|
||||||
|
@ -257,8 +257,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SetPrice(uint16_t price_) {
|
void SetPrice(uint16_t price_) {
|
||||||
//don't override price if the price was set for shopsanity
|
//don't override price if the price was set for shopsanity/scrubsanity
|
||||||
if (hasShopsanityPrice) {
|
if (hasShopsanityPrice || hasScrubsanityPrice) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
price = price_;
|
price = price_;
|
||||||
@ -269,10 +269,19 @@ public:
|
|||||||
hasShopsanityPrice = true;
|
hasShopsanityPrice = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetScrubsanityPrice(uint16_t price_) {
|
||||||
|
price = price_;
|
||||||
|
hasScrubsanityPrice = true;
|
||||||
|
}
|
||||||
|
|
||||||
bool HasShopsanityPrice() const {
|
bool HasShopsanityPrice() const {
|
||||||
return hasShopsanityPrice;
|
return hasShopsanityPrice;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HasScrubsanityPrice() const {
|
||||||
|
return hasScrubsanityPrice;
|
||||||
|
}
|
||||||
|
|
||||||
bool IsExcluded() const {
|
bool IsExcluded() const {
|
||||||
return excludedOption.Value<bool>();
|
return excludedOption.Value<bool>();
|
||||||
}
|
}
|
||||||
@ -426,6 +435,7 @@ public:
|
|||||||
isHintable = false;
|
isHintable = false;
|
||||||
price = 0;
|
price = 0;
|
||||||
hasShopsanityPrice = false;
|
hasShopsanityPrice = false;
|
||||||
|
hasScrubsanityPrice = false;
|
||||||
hidden = false;
|
hidden = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -451,6 +461,7 @@ private:
|
|||||||
bool isHintable = false;
|
bool isHintable = false;
|
||||||
uint32_t parentRegion = NONE;
|
uint32_t parentRegion = NONE;
|
||||||
bool hasShopsanityPrice = false;
|
bool hasShopsanityPrice = false;
|
||||||
|
bool hasScrubsanityPrice = false;
|
||||||
bool hidden = false;
|
bool hidden = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -467,6 +478,8 @@ ItemLocation* Location(uint32_t locKey);
|
|||||||
|
|
||||||
extern std::vector<std::vector<uint32_t>> ShopLocationLists;
|
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> gossipStoneLocations;
|
||||||
|
|
||||||
extern std::vector<uint32_t> dungeonRewardLocations;
|
extern std::vector<uint32_t> dungeonRewardLocations;
|
||||||
|
@ -2532,6 +2532,7 @@ namespace Settings {
|
|||||||
ShuffleRewards.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_DUNGEON_REWARDS]);
|
ShuffleRewards.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_DUNGEON_REWARDS]);
|
||||||
ShuffleSongs.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_SONGS]);
|
ShuffleSongs.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_SONGS]);
|
||||||
Tokensanity.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_TOKENS]);
|
Tokensanity.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_TOKENS]);
|
||||||
|
Scrubsanity.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_SCRUBS]);
|
||||||
ShuffleCows.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_COWS]);
|
ShuffleCows.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_COWS]);
|
||||||
ShuffleKokiriSword.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_KOKIRI_SWORD]);
|
ShuffleKokiriSword.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_KOKIRI_SWORD]);
|
||||||
ShuffleOcarinas.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_OCARINA]);
|
ShuffleOcarinas.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_OCARINA]);
|
||||||
|
@ -675,15 +675,14 @@ 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;
|
||||||
|
|
||||||
switch (language) {
|
// Eventually check for other things here like fake name
|
||||||
case 0:
|
if (location->HasScrubsanityPrice() || location->HasShopsanityPrice()) {
|
||||||
default:
|
jsonData["locations"][location->GetName()]["item"] = placedItemName;
|
||||||
jsonData["locations"][location->GetName()] = location->GetPlacedItemName().english;
|
jsonData["locations"][location->GetName()]["price"] = location->GetPrice();;
|
||||||
break;
|
} else {
|
||||||
case 2:
|
jsonData["locations"][location->GetName()] = placedItemName;
|
||||||
jsonData["locations"][location->GetName()] = location->GetPlacedItemName().french;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,6 +81,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();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_map<s16, s16> getItemIdToItemId = {
|
std::unordered_map<s16, s16> getItemIdToItemId = {
|
||||||
@ -523,6 +524,7 @@ std::unordered_map<std::string, RandomizerSettingKey> SpoilerfileSettingNameToEn
|
|||||||
{ "Open Settings:Random Ganon's Trials", RSK_RANDOM_TRIALS },
|
{ "Open Settings:Random Ganon's Trials", RSK_RANDOM_TRIALS },
|
||||||
{ "Open Settings:Trial Count", RSK_TRIAL_COUNT },
|
{ "Open Settings:Trial Count", RSK_TRIAL_COUNT },
|
||||||
{ "Shuffle Settings:Shuffle Gerudo Card", RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD },
|
{ "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:Shuffle Cows", RSK_SHUFFLE_COWS },
|
||||||
{ "Shuffle Settings:Tokensanity", RSK_SHUFFLE_TOKENS },
|
{ "Shuffle Settings:Tokensanity", RSK_SHUFFLE_TOKENS },
|
||||||
{ "Shuffle Settings:Shuffle Adult Trade", RSK_SHUFFLE_ADULT_TRADE },
|
{ "Shuffle Settings:Shuffle Adult Trade", RSK_SHUFFLE_ADULT_TRADE },
|
||||||
@ -749,6 +751,17 @@ void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) {
|
|||||||
numericValueString = it.value();
|
numericValueString = it.value();
|
||||||
gSaveContext.randoSettings[index].value = std::stoi(numericValueString);
|
gSaveContext.randoSettings[index].value = std::stoi(numericValueString);
|
||||||
break;
|
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_GERUDO_MEMBERSHIP_CARD:
|
||||||
case RSK_SHUFFLE_COWS:
|
case RSK_SHUFFLE_COWS:
|
||||||
case RSK_SHUFFLE_ADULT_TRADE:
|
case RSK_SHUFFLE_ADULT_TRADE:
|
||||||
@ -1079,9 +1092,11 @@ void Randomizer::ParseItemLocationsFile(const char* spoilerFileName, bool silent
|
|||||||
for (auto itemit = itemJson.begin(); itemit != itemJson.end(); ++itemit) {
|
for (auto itemit = itemJson.begin(); itemit != itemJson.end(); ++itemit) {
|
||||||
// todo handle prices
|
// todo handle prices
|
||||||
if (itemit.key() == "item") {
|
if (itemit.key() == "item") {
|
||||||
|
|
||||||
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") {
|
||||||
|
scrubPrices[gSaveContext.itemLocations[index].check] = itemit.value();
|
||||||
|
// TODO: Handle shop prices
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1565,6 +1580,281 @@ std::string Randomizer::GetGanonHintText() const {
|
|||||||
return ganonHintText;
|
return ganonHintText;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ScrubIdentity Randomizer::IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respawnData) {
|
||||||
|
struct ScrubIdentity scrubIdentity;
|
||||||
|
|
||||||
|
scrubIdentity.scrubId = -1;
|
||||||
|
scrubIdentity.randomizerCheck = RC_UNKNOWN_CHECK;
|
||||||
|
scrubIdentity.getItemId = GI_NONE;
|
||||||
|
scrubIdentity.itemPrice = -1;
|
||||||
|
scrubIdentity.isShuffled = GetRandoSettingValue(RSK_SHUFFLE_SCRUBS) > 0;
|
||||||
|
|
||||||
|
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.scrubId = 0x00;
|
||||||
|
scrubIdentity.randomizerCheck = RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT;
|
||||||
|
break;
|
||||||
|
case 0x01:
|
||||||
|
scrubIdentity.scrubId = 0x01;
|
||||||
|
scrubIdentity.randomizerCheck = RC_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS;
|
||||||
|
break;
|
||||||
|
case 0x03:
|
||||||
|
case 0x06:
|
||||||
|
scrubIdentity.scrubId = 0x02;
|
||||||
|
scrubIdentity.randomizerCheck = RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT;
|
||||||
|
break;
|
||||||
|
case 0x04:
|
||||||
|
scrubIdentity.scrubId = 0x03;
|
||||||
|
scrubIdentity.randomizerCheck = RC_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SCENE_BDAN: // Jabu Jabu's Belly
|
||||||
|
switch (actorParams) {
|
||||||
|
case 0x00:
|
||||||
|
scrubIdentity.scrubId = 0x04;
|
||||||
|
scrubIdentity.randomizerCheck = RC_JABU_JABUS_BELLY_DEKU_SCRUB;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SCENE_GANONTIKA: // Ganon's Castle
|
||||||
|
switch (actorParams) {
|
||||||
|
case 0x05:
|
||||||
|
scrubIdentity.scrubId = 0x05;
|
||||||
|
scrubIdentity.randomizerCheck = RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT;
|
||||||
|
break;
|
||||||
|
case 0x03:
|
||||||
|
case 0x06:
|
||||||
|
scrubIdentity.scrubId = 0x06;
|
||||||
|
scrubIdentity.randomizerCheck = RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT;
|
||||||
|
break;
|
||||||
|
case 0x07:
|
||||||
|
scrubIdentity.scrubId = 0x07;
|
||||||
|
scrubIdentity.randomizerCheck = RC_GANONS_CASTLE_DEKU_SCRUB_RIGHT;
|
||||||
|
break;
|
||||||
|
case 0x08:
|
||||||
|
scrubIdentity.scrubId = 0x08;
|
||||||
|
scrubIdentity.randomizerCheck = RC_GANONS_CASTLE_DEKU_SCRUB_LEFT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SCENE_KAKUSIANA: // Grotto
|
||||||
|
// 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
|
||||||
|
switch (respawnData) {
|
||||||
|
case 0xE6: // Hyrule Field Scrub Grotto
|
||||||
|
switch (actorParams) {
|
||||||
|
case 0x02:
|
||||||
|
scrubIdentity.scrubId = 0x09;
|
||||||
|
scrubIdentity.randomizerCheck = RC_HF_DEKU_SCRUB_GROTTO;
|
||||||
|
scrubIdentity.isShuffled = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0xEB: // ZR Scrub Grotto
|
||||||
|
switch (actorParams) {
|
||||||
|
case 0x07:
|
||||||
|
scrubIdentity.scrubId = 0x0A;
|
||||||
|
scrubIdentity.randomizerCheck = RC_ZR_DEKU_SCRUB_GROTTO_REAR;
|
||||||
|
break;
|
||||||
|
case 0x08:
|
||||||
|
scrubIdentity.scrubId = 0x0B;
|
||||||
|
scrubIdentity.randomizerCheck = RC_ZR_DEKU_SCRUB_GROTTO_FRONT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0xEE: // Sacred Forest Meadow Scrub Grotto
|
||||||
|
switch (actorParams) {
|
||||||
|
case 0x07:
|
||||||
|
scrubIdentity.scrubId = 0x0C;
|
||||||
|
scrubIdentity.randomizerCheck = RC_SFM_DEKU_SCRUB_GROTTO_REAR;
|
||||||
|
break;
|
||||||
|
case 0x08:
|
||||||
|
scrubIdentity.scrubId = 0x0D;
|
||||||
|
scrubIdentity.randomizerCheck = RC_SFM_DEKU_SCRUB_GROTTO_FRONT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0xEF: // Lake Hylia Scrub Grotto
|
||||||
|
switch (actorParams) {
|
||||||
|
case 0x00:
|
||||||
|
scrubIdentity.scrubId = 0x0E;
|
||||||
|
scrubIdentity.randomizerCheck = RC_LH_DEKU_SCRUB_GROTTO_LEFT;
|
||||||
|
break;
|
||||||
|
case 0x05:
|
||||||
|
scrubIdentity.scrubId = 0x0F;
|
||||||
|
scrubIdentity.randomizerCheck = RC_LH_DEKU_SCRUB_GROTTO_RIGHT;
|
||||||
|
break;
|
||||||
|
case 0x03:
|
||||||
|
case 0x06:
|
||||||
|
scrubIdentity.scrubId = 0x10;
|
||||||
|
scrubIdentity.randomizerCheck = RC_LH_DEKU_SCRUB_GROTTO_CENTER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0xF0: // Gerudo Valley Scrub Grotto
|
||||||
|
switch (actorParams) {
|
||||||
|
case 0x07:
|
||||||
|
scrubIdentity.scrubId = 0x11;
|
||||||
|
scrubIdentity.randomizerCheck = RC_GV_DEKU_SCRUB_GROTTO_REAR;
|
||||||
|
break;
|
||||||
|
case 0x08:
|
||||||
|
scrubIdentity.scrubId = 0x12;
|
||||||
|
scrubIdentity.randomizerCheck = RC_GV_DEKU_SCRUB_GROTTO_FRONT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0xF5: // Lost Woods Scrub Grotto
|
||||||
|
switch (actorParams) {
|
||||||
|
case 0x03:
|
||||||
|
case 0x06:
|
||||||
|
scrubIdentity.scrubId = 0x13;
|
||||||
|
scrubIdentity.randomizerCheck = RC_LW_DEKU_SCRUB_GROTTO_REAR;
|
||||||
|
break;
|
||||||
|
case 0x0A:
|
||||||
|
scrubIdentity.scrubId = 0x14;
|
||||||
|
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.scrubId = 0x15;
|
||||||
|
scrubIdentity.randomizerCheck = RC_DMC_DEKU_SCRUB_GROTTO_LEFT;
|
||||||
|
break;
|
||||||
|
case 0x05:
|
||||||
|
scrubIdentity.scrubId = 0x16;
|
||||||
|
scrubIdentity.randomizerCheck = RC_DMC_DEKU_SCRUB_GROTTO_RIGHT;
|
||||||
|
break;
|
||||||
|
case 0x03:
|
||||||
|
case 0x06:
|
||||||
|
scrubIdentity.scrubId = 0x17;
|
||||||
|
scrubIdentity.randomizerCheck = RC_DMC_DEKU_SCRUB_GROTTO_CENTER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0xFB: // Gerudo City Scrub Grotto
|
||||||
|
switch (actorParams) {
|
||||||
|
case 0x00:
|
||||||
|
scrubIdentity.scrubId = 0x18;
|
||||||
|
scrubIdentity.randomizerCheck = RC_GC_DEKU_SCRUB_GROTTO_LEFT;
|
||||||
|
break;
|
||||||
|
case 0x05:
|
||||||
|
scrubIdentity.scrubId = 0x19;
|
||||||
|
scrubIdentity.randomizerCheck = RC_GC_DEKU_SCRUB_GROTTO_RIGHT;
|
||||||
|
break;
|
||||||
|
case 0x03:
|
||||||
|
case 0x06:
|
||||||
|
scrubIdentity.scrubId = 0x1A;
|
||||||
|
scrubIdentity.randomizerCheck = RC_GC_DEKU_SCRUB_GROTTO_CENTER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0xFC: // Lon Lon Ranch Scrub Grotto
|
||||||
|
switch (actorParams) {
|
||||||
|
case 0x00:
|
||||||
|
scrubIdentity.scrubId = 0x1B;
|
||||||
|
scrubIdentity.randomizerCheck = RC_LLR_DEKU_SCRUB_GROTTO_LEFT;
|
||||||
|
break;
|
||||||
|
case 0x05:
|
||||||
|
scrubIdentity.scrubId = 0x1C;
|
||||||
|
scrubIdentity.randomizerCheck = RC_LLR_DEKU_SCRUB_GROTTO_RIGHT;
|
||||||
|
break;
|
||||||
|
case 0x03:
|
||||||
|
case 0x06:
|
||||||
|
scrubIdentity.scrubId = 0x1D;
|
||||||
|
scrubIdentity.randomizerCheck = RC_LLR_DEKU_SCRUB_GROTTO_CENTER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0xFD: // Desert Colossus Scrub Grotto
|
||||||
|
switch (actorParams) {
|
||||||
|
case 0x07:
|
||||||
|
scrubIdentity.scrubId = 0x1E;
|
||||||
|
scrubIdentity.randomizerCheck = RC_COLOSSUS_DEKU_SCRUB_GROTTO_REAR;
|
||||||
|
break;
|
||||||
|
case 0x08:
|
||||||
|
scrubIdentity.scrubId = 0x1F;
|
||||||
|
scrubIdentity.randomizerCheck = RC_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SCENE_SPOT10: // Lost woods
|
||||||
|
switch (actorParams) {
|
||||||
|
case 0x00:
|
||||||
|
scrubIdentity.scrubId = 0x20;
|
||||||
|
scrubIdentity.randomizerCheck = RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT;
|
||||||
|
break;
|
||||||
|
case 0x01:
|
||||||
|
scrubIdentity.scrubId = 0x21;
|
||||||
|
scrubIdentity.randomizerCheck = RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT;
|
||||||
|
break;
|
||||||
|
case 0x09:
|
||||||
|
scrubIdentity.scrubId = 0x22;
|
||||||
|
scrubIdentity.randomizerCheck = RC_LW_DEKU_SCRUB_NEAR_BRIDGE;
|
||||||
|
scrubIdentity.isShuffled = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SCENE_SPOT17: // Death Mountain Crater
|
||||||
|
switch (actorParams) {
|
||||||
|
case 0x05:
|
||||||
|
scrubIdentity.scrubId = 0x23;
|
||||||
|
scrubIdentity.randomizerCheck = RC_DMC_DEKU_SCRUB;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scrubPrices.find(scrubIdentity.randomizerCheck) != scrubPrices.end()) {
|
||||||
|
scrubIdentity.itemPrice = scrubPrices[scrubIdentity.randomizerCheck];
|
||||||
|
}
|
||||||
|
|
||||||
|
return scrubIdentity;
|
||||||
|
}
|
||||||
|
|
||||||
u8 Randomizer::GetRandoSettingValue(RandomizerSettingKey randoSettingKey) {
|
u8 Randomizer::GetRandoSettingValue(RandomizerSettingKey randoSettingKey) {
|
||||||
return this->randoSettings[randoSettingKey];
|
return this->randoSettings[randoSettingKey];
|
||||||
}
|
}
|
||||||
@ -2158,10 +2448,6 @@ RandomizerCheck Randomizer::GetCheckFromActor(s16 sceneNum, s16 actorId, s16 act
|
|||||||
break;
|
break;
|
||||||
case 62:
|
case 62:
|
||||||
switch (actorParams) {
|
switch (actorParams) {
|
||||||
case 2:
|
|
||||||
return RC_HF_DEKU_SCRUB_GROTTO;
|
|
||||||
case 10:
|
|
||||||
return RC_LW_DEKU_SCRUB_GROTTO_FRONT;
|
|
||||||
case 22988:
|
case 22988:
|
||||||
return RC_KF_STORMS_GROTTO_CHEST;
|
return RC_KF_STORMS_GROTTO_CHEST;
|
||||||
case -22988:
|
case -22988:
|
||||||
@ -2426,8 +2712,6 @@ RandomizerCheck Randomizer::GetCheckFromActor(s16 sceneNum, s16 actorId, s16 act
|
|||||||
break;
|
break;
|
||||||
case 91:
|
case 91:
|
||||||
switch (actorParams) {
|
switch (actorParams) {
|
||||||
case 9:
|
|
||||||
return RC_LW_DEKU_SCRUB_NEAR_BRIDGE;
|
|
||||||
case 14365:
|
case 14365:
|
||||||
return RC_LW_GOSSIP_STONE;
|
return RC_LW_GOSSIP_STONE;
|
||||||
case 27905:
|
case 27905:
|
||||||
@ -2592,6 +2876,7 @@ void GenerateRandomizerImgui() {
|
|||||||
cvarSettings[RSK_SHUFFLE_DUNGEON_REWARDS] = CVar_GetS32("gRandomizeShuffleDungeonReward", 0);
|
cvarSettings[RSK_SHUFFLE_DUNGEON_REWARDS] = CVar_GetS32("gRandomizeShuffleDungeonReward", 0);
|
||||||
cvarSettings[RSK_SHUFFLE_SONGS] = CVar_GetS32("gRandomizeShuffleSongs", 0);
|
cvarSettings[RSK_SHUFFLE_SONGS] = CVar_GetS32("gRandomizeShuffleSongs", 0);
|
||||||
cvarSettings[RSK_SHUFFLE_TOKENS] = CVar_GetS32("gRandomizeShuffleTokens", 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_COWS] = CVar_GetS32("gRandomizeShuffleCows", 0);
|
||||||
cvarSettings[RSK_SHUFFLE_ADULT_TRADE] = CVar_GetS32("gRandomizeShuffleAdultTrade", 0);
|
cvarSettings[RSK_SHUFFLE_ADULT_TRADE] = CVar_GetS32("gRandomizeShuffleAdultTrade", 0);
|
||||||
cvarSettings[RSK_SKIP_CHILD_ZELDA] = CVar_GetS32("gRandomizeSkipChildZelda", 0);
|
cvarSettings[RSK_SKIP_CHILD_ZELDA] = CVar_GetS32("gRandomizeSkipChildZelda", 0);
|
||||||
@ -3108,11 +3393,20 @@ void DrawRandoEditor(bool& open) {
|
|||||||
"expected to be collected after getting Sun's Song.");
|
"expected to be collected after getting Sun's Song.");
|
||||||
PaddedSeparator();
|
PaddedSeparator();
|
||||||
|
|
||||||
// Shuffle Cows
|
// Shuffle Scrubs
|
||||||
SohImGui::EnhancementCheckbox(Settings::ShuffleCows.GetName().c_str(), "gRandomizeShuffleCows");
|
ImGui::Text(Settings::Scrubsanity.GetName().c_str());
|
||||||
InsertHelpHoverText(
|
InsertHelpHoverText(
|
||||||
"Cows give a randomized item from the pool upon performing Epona's Song in front of them.");
|
"Off - Scrubs will not be shuffled.\n"
|
||||||
PaddedSeparator();
|
"\n"
|
||||||
|
"Affordable - Scrubs will be shuffled and their item will cost 10 rupees.\n"
|
||||||
|
);
|
||||||
|
SohImGui::EnhancementCombobox("gRandomizeShuffleScrubs", randoShuffleScrubs, 4, 0);
|
||||||
|
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.");
|
||||||
|
PaddedSeparator();
|
||||||
|
|
||||||
// Shuffle Adult Trade Quest
|
// Shuffle Adult Trade Quest
|
||||||
SohImGui::EnhancementCheckbox(Settings::ShuffleAdultTradeQuest.GetName().c_str(),
|
SohImGui::EnhancementCheckbox(Settings::ShuffleAdultTradeQuest.GetName().c_str(),
|
||||||
@ -3699,8 +3993,7 @@ void CreateGetItemMessages(std::vector<GetItemMessage> messageEntries) {
|
|||||||
void CreateScrubMessages() {
|
void CreateScrubMessages() {
|
||||||
CustomMessageManager* customMessageManager = CustomMessageManager::Instance;
|
CustomMessageManager* customMessageManager = CustomMessageManager::Instance;
|
||||||
customMessageManager->AddCustomMessageTable(Randomizer::scrubMessageTableID);
|
customMessageManager->AddCustomMessageTable(Randomizer::scrubMessageTableID);
|
||||||
const std::vector<u8> prices = { 10, 40 };
|
for (u32 price = 0; price <= 95; price += 5) {
|
||||||
for (u8 price : prices) {
|
|
||||||
customMessageManager->CreateMessage(Randomizer::scrubMessageTableID, price,
|
customMessageManager->CreateMessage(Randomizer::scrubMessageTableID, price,
|
||||||
{ TEXTBOX_TYPE_BLACK, TEXTBOX_POS_BOTTOM,
|
{ 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" +
|
"\x12\x38\x82\All right! You win! In return for&sparing me, I will sell you a&%gmysterious item%w!&%r" +
|
||||||
|
@ -16,6 +16,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;
|
||||||
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);
|
||||||
@ -45,6 +46,7 @@ class Randomizer {
|
|||||||
std::string GetAdultAltarText() const;
|
std::string GetAdultAltarText() const;
|
||||||
std::string GetGanonText() const;
|
std::string GetGanonText() const;
|
||||||
std::string GetGanonHintText() const;
|
std::string GetGanonHintText() const;
|
||||||
|
ScrubIdentity IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respawnData);
|
||||||
s16 GetRandomizedItemIdFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogId);
|
s16 GetRandomizedItemIdFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogId);
|
||||||
s16 GetRandomizedItemId(GetItemID ogId, s16 actorId, s16 actorParams, s16 sceneNum);
|
s16 GetRandomizedItemId(GetItemID ogId, s16 actorId, s16 actorParams, s16 sceneNum);
|
||||||
static void CreateCustomMessages();
|
static void CreateCustomMessages();
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include "z64item.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
|
||||||
@ -987,6 +988,7 @@ typedef enum {
|
|||||||
RSK_SHUFFLE_DUNGEON_REWARDS,
|
RSK_SHUFFLE_DUNGEON_REWARDS,
|
||||||
RSK_SHUFFLE_SONGS,
|
RSK_SHUFFLE_SONGS,
|
||||||
RSK_SHUFFLE_TOKENS,
|
RSK_SHUFFLE_TOKENS,
|
||||||
|
RSK_SHUFFLE_SCRUBS,
|
||||||
RSK_SHUFFLE_COWS,
|
RSK_SHUFFLE_COWS,
|
||||||
RSK_SHUFFLE_WEIRD_EGG,
|
RSK_SHUFFLE_WEIRD_EGG,
|
||||||
RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD,
|
RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD,
|
||||||
@ -1015,3 +1017,11 @@ typedef enum {
|
|||||||
RSK_SKULLS_SUNS_SONG,
|
RSK_SKULLS_SUNS_SONG,
|
||||||
RSK_SHUFFLE_ADULT_TRADE
|
RSK_SHUFFLE_ADULT_TRADE
|
||||||
} RandomizerSettingKey;
|
} RandomizerSettingKey;
|
||||||
|
|
||||||
|
typedef struct ScrubIdentity {
|
||||||
|
int32_t scrubId;
|
||||||
|
RandomizerCheck randomizerCheck;
|
||||||
|
GetItemID getItemId;
|
||||||
|
int32_t itemPrice;
|
||||||
|
bool isShuffled;
|
||||||
|
} ScrubIdentity;
|
@ -1568,18 +1568,12 @@ extern "C" RandomizerCheck Randomizer_GetCheckFromActor(s16 sceneNum, s16 actorI
|
|||||||
return OTRGlobals::Instance->gRandomizer->GetCheckFromActor(sceneNum, actorId, actorParams);
|
return OTRGlobals::Instance->gRandomizer->GetCheckFromActor(sceneNum, actorId, actorParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" CustomMessageEntry Randomizer_GetScrubMessage(u16 scrubTextId) {
|
extern "C" ScrubIdentity Randomizer_IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respawnData) {
|
||||||
int price = 0;
|
return OTRGlobals::Instance->gRandomizer->IdentifyScrub(sceneNum, actorParams, respawnData);
|
||||||
switch (scrubTextId) {
|
}
|
||||||
case TEXT_SCRUB_POH:
|
|
||||||
price = 10;
|
extern "C" CustomMessageEntry Randomizer_GetScrubMessage(s16 itemPrice) {
|
||||||
break;
|
return CustomMessageManager::Instance->RetrieveMessage(Randomizer::scrubMessageTableID, itemPrice);
|
||||||
case TEXT_SCRUB_STICK_UPGRADE:
|
|
||||||
case TEXT_SCRUB_NUT_UPGRADE:
|
|
||||||
price = 40;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return CustomMessageManager::Instance->RetrieveMessage(Randomizer::scrubMessageTableID, price);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" CustomMessageEntry Randomizer_GetAltarMessage() {
|
extern "C" CustomMessageEntry Randomizer_GetAltarMessage() {
|
||||||
@ -1703,8 +1697,8 @@ extern "C" int CustomMessage_RetrieveIfExists(GlobalContext* globalCtx) {
|
|||||||
} else {
|
} else {
|
||||||
messageEntry = Randomizer_GetGanonHintText();
|
messageEntry = Randomizer_GetGanonHintText();
|
||||||
}
|
}
|
||||||
} else if (textId == TEXT_SCRUB_POH || textId == TEXT_SCRUB_STICK_UPGRADE || textId == TEXT_SCRUB_NUT_UPGRADE) {
|
} else if (textId >= 0x9000 && textId <= 0x905F) {
|
||||||
messageEntry = Randomizer_GetScrubMessage(textId);
|
messageEntry = Randomizer_GetScrubMessage((textId & ((1 << 8) - 1)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (textId == TEXT_GS_NO_FREEZE || textId == TEXT_GS_FREEZE) {
|
if (textId == TEXT_GS_NO_FREEZE || textId == TEXT_GS_FREEZE) {
|
||||||
|
@ -96,6 +96,7 @@ Sprite* GetSeedTexture(uint8_t index);
|
|||||||
void Randomizer_LoadSettings(const char* spoilerFileName);
|
void Randomizer_LoadSettings(const char* spoilerFileName);
|
||||||
u8 Randomizer_GetSettingValue(RandomizerSettingKey randoSettingKey);
|
u8 Randomizer_GetSettingValue(RandomizerSettingKey randoSettingKey);
|
||||||
RandomizerCheck Randomizer_GetCheckFromActor(s16 actorId, s16 actorParams, s16 sceneNum);
|
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_LoadHintLocations(const char* spoilerFileName);
|
||||||
void Randomizer_LoadItemLocations(const char* spoilerFileName, bool silent);
|
void Randomizer_LoadItemLocations(const char* spoilerFileName, bool silent);
|
||||||
GetItemEntry Randomizer_GetRandomizedItem(GetItemID ogId, s16 actorId, s16 actorParams, s16 sceneNum);
|
GetItemEntry Randomizer_GetRandomizedItem(GetItemID ogId, s16 actorId, s16 actorParams, s16 sceneNum);
|
||||||
|
@ -768,6 +768,10 @@ void SaveManager::LoadBaseVersion1() {
|
|||||||
SaveManager::Instance->LoadArray("cowsMilked", ARRAY_COUNT(gSaveContext.cowsMilked), [](size_t i) {
|
SaveManager::Instance->LoadArray("cowsMilked", ARRAY_COUNT(gSaveContext.cowsMilked), [](size_t i) {
|
||||||
SaveManager::Instance->LoadData("", gSaveContext.cowsMilked[i]);
|
SaveManager::Instance->LoadData("", gSaveContext.cowsMilked[i]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
SaveManager::Instance->LoadArray("scrubsPurchased", ARRAY_COUNT(gSaveContext.scrubsPurchased), [](size_t i) {
|
||||||
|
SaveManager::Instance->LoadData("", gSaveContext.scrubsPurchased[i]);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void SaveManager::LoadBaseVersion2() {
|
void SaveManager::LoadBaseVersion2() {
|
||||||
@ -932,6 +936,10 @@ void SaveManager::LoadBaseVersion2() {
|
|||||||
SaveManager::Instance->LoadArray("cowsMilked", ARRAY_COUNT(gSaveContext.cowsMilked), [](size_t i) {
|
SaveManager::Instance->LoadArray("cowsMilked", ARRAY_COUNT(gSaveContext.cowsMilked), [](size_t i) {
|
||||||
SaveManager::Instance->LoadData("", gSaveContext.cowsMilked[i]);
|
SaveManager::Instance->LoadData("", gSaveContext.cowsMilked[i]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
SaveManager::Instance->LoadArray("scrubsPurchased", ARRAY_COUNT(gSaveContext.scrubsPurchased), [](size_t i) {
|
||||||
|
SaveManager::Instance->LoadData("", gSaveContext.scrubsPurchased[i]);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void SaveManager::SaveBase() {
|
void SaveManager::SaveBase() {
|
||||||
@ -1092,6 +1100,10 @@ void SaveManager::SaveBase() {
|
|||||||
SaveManager::Instance->SaveArray("cowsMilked", ARRAY_COUNT(gSaveContext.cowsMilked), [](size_t i) {
|
SaveManager::Instance->SaveArray("cowsMilked", ARRAY_COUNT(gSaveContext.cowsMilked), [](size_t i) {
|
||||||
SaveManager::Instance->SaveData("", gSaveContext.cowsMilked[i]);
|
SaveManager::Instance->SaveData("", gSaveContext.cowsMilked[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) {
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#define NUM_DUNGEONS 8
|
#define NUM_DUNGEONS 8
|
||||||
#define NUM_TRIALS 6
|
#define NUM_TRIALS 6
|
||||||
#define NUM_COWS 10
|
#define NUM_COWS 10
|
||||||
|
#define NUM_SCRUBS 35
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize new save.
|
* Initialize new save.
|
||||||
@ -717,6 +718,11 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) {
|
|||||||
gSaveContext.cowsMilked[i] = 0;
|
gSaveContext.cowsMilked[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
|
||||||
|
@ -15,6 +15,7 @@ void EnDns_Destroy(Actor* thisx, GlobalContext* globalCtx);
|
|||||||
void EnDns_Update(Actor* thisx, GlobalContext* globalCtx);
|
void EnDns_Update(Actor* thisx, GlobalContext* globalCtx);
|
||||||
void EnDns_Draw(Actor* thisx, GlobalContext* globalCtx);
|
void EnDns_Draw(Actor* thisx, GlobalContext* globalCtx);
|
||||||
|
|
||||||
|
u32 EnDns_RandomizerPurchaseableCheck(EnDns* this);
|
||||||
u32 func_809EF5A4(EnDns* this);
|
u32 func_809EF5A4(EnDns* this);
|
||||||
u32 func_809EF658(EnDns* this);
|
u32 func_809EF658(EnDns* this);
|
||||||
u32 func_809EF70C(EnDns* this);
|
u32 func_809EF70C(EnDns* this);
|
||||||
@ -24,6 +25,7 @@ u32 func_809EF854(EnDns* this);
|
|||||||
u32 func_809EF8F4(EnDns* this);
|
u32 func_809EF8F4(EnDns* this);
|
||||||
u32 func_809EF9A4(EnDns* this);
|
u32 func_809EF9A4(EnDns* this);
|
||||||
|
|
||||||
|
void EnDns_RandomizerPurchase(EnDns* this);
|
||||||
void func_809EF9F8(EnDns* this);
|
void func_809EF9F8(EnDns* this);
|
||||||
void func_809EFA28(EnDns* this);
|
void func_809EFA28(EnDns* this);
|
||||||
void func_809EFA58(EnDns* this);
|
void func_809EFA58(EnDns* this);
|
||||||
@ -155,7 +157,6 @@ void EnDns_Init(Actor* thisx, GlobalContext* globalCtx) {
|
|||||||
Collider_InitCylinder(globalCtx, &this->collider);
|
Collider_InitCylinder(globalCtx, &this->collider);
|
||||||
Collider_SetCylinderType1(globalCtx, &this->collider, &this->actor, &sCylinderInit);
|
Collider_SetCylinderType1(globalCtx, &this->collider, &this->actor, &sCylinderInit);
|
||||||
ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 35.0f);
|
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);
|
Actor_SetScale(&this->actor, 0.01f);
|
||||||
this->actor.colChkInfo.mass = MASS_IMMOVABLE;
|
this->actor.colChkInfo.mass = MASS_IMMOVABLE;
|
||||||
this->maintainCollider = 1;
|
this->maintainCollider = 1;
|
||||||
@ -164,7 +165,24 @@ void EnDns_Init(Actor* thisx, GlobalContext* globalCtx) {
|
|||||||
this->actor.speedXZ = 0.0f;
|
this->actor.speedXZ = 0.0f;
|
||||||
this->actor.velocity.y = 0.0f;
|
this->actor.velocity.y = 0.0f;
|
||||||
this->actor.gravity = -1.0f;
|
this->actor.gravity = -1.0f;
|
||||||
|
this->actor.textId = D_809F040C[this->actor.params];
|
||||||
this->dnsItemEntry = sItemEntries[this->actor.params];
|
this->dnsItemEntry = sItemEntries[this->actor.params];
|
||||||
|
if (gSaveContext.n64ddFlag) {
|
||||||
|
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;
|
||||||
|
this->actor.textId = 0x9000 + this->dnsItemEntry->itemPrice;
|
||||||
|
}
|
||||||
|
}
|
||||||
this->actionFunc = EnDns_SetupWait;
|
this->actionFunc = EnDns_SetupWait;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,6 +203,13 @@ void EnDns_ChangeAnim(EnDns* this, u8 index) {
|
|||||||
|
|
||||||
/* Item give checking functions */
|
/* Item give checking functions */
|
||||||
|
|
||||||
|
u32 EnDns_RandomizerPurchaseableCheck(EnDns* this) {
|
||||||
|
if (gSaveContext.rupees < this->dnsItemEntry->itemPrice || gSaveContext.scrubsPurchased[this->scrubIdentity.scrubId] == 1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
u32 func_809EF5A4(EnDns* this) {
|
u32 func_809EF5A4(EnDns* this) {
|
||||||
if ((CUR_CAPACITY(UPG_NUTS) != 0) && (AMMO(ITEM_NUT) >= CUR_CAPACITY(UPG_NUTS))) {
|
if ((CUR_CAPACITY(UPG_NUTS) != 0) && (AMMO(ITEM_NUT) >= CUR_CAPACITY(UPG_NUTS))) {
|
||||||
return 1;
|
return 1;
|
||||||
@ -281,6 +306,10 @@ u32 func_809EF9A4(EnDns* this) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Paying and flagging functions */
|
/* Paying and flagging functions */
|
||||||
|
void EnDns_RandomizerPurchase(EnDns* this) {
|
||||||
|
Rupees_ChangeBy(-this->dnsItemEntry->itemPrice);
|
||||||
|
gSaveContext.scrubsPurchased[this->scrubIdentity.scrubId] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
void func_809EF9F8(EnDns* this) {
|
void func_809EF9F8(EnDns* this) {
|
||||||
Rupees_ChangeBy(-this->dnsItemEntry->itemPrice);
|
Rupees_ChangeBy(-this->dnsItemEntry->itemPrice);
|
||||||
@ -369,31 +398,25 @@ void EnDns_Talk(EnDns* this, GlobalContext* globalCtx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void func_809EFDD0(EnDns* this, GlobalContext* globalCtx) {
|
void func_809EFDD0(EnDns* this, GlobalContext* globalCtx) {
|
||||||
if (this->actor.params == 0x9) {
|
if (!gSaveContext.n64ddFlag || !this->scrubIdentity.isShuffled) {
|
||||||
if (gSaveContext.n64ddFlag) {
|
if (this->actor.params == 0x9) {
|
||||||
GetItemEntry getItemEntry = Randomizer_GetRandomizedItem(GI_STICK_UPGRADE_30, this->actor.id, this->actor.params, globalCtx->sceneNum);
|
if (CUR_UPG_VALUE(UPG_STICKS) < 2) {
|
||||||
GiveItemEntryFromActor(&this->actor, globalCtx, getItemEntry, 130.0f, 100.0f);
|
func_8002F434(&this->actor, globalCtx, GI_STICK_UPGRADE_20, 130.0f, 100.0f);
|
||||||
} else if (CUR_UPG_VALUE(UPG_STICKS) < 2) {
|
} else {
|
||||||
func_8002F434(&this->actor, globalCtx, GI_STICK_UPGRADE_20, 130.0f, 100.0f);
|
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 {
|
} else {
|
||||||
func_8002F434(&this->actor, globalCtx, GI_STICK_UPGRADE_30, 130.0f, 100.0f);
|
func_8002F434(&this->actor, globalCtx, this->dnsItemEntry->getItemId, 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);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!gSaveContext.n64ddFlag) {
|
GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(this->scrubIdentity.randomizerCheck, this->scrubIdentity.getItemId);
|
||||||
func_8002F434(&this->actor, globalCtx, this->dnsItemEntry->getItemId, 130.0f, 100.0f);
|
GiveItemEntryFromActor(&this->actor, globalCtx, itemEntry, 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -489,6 +512,9 @@ 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) {
|
||||||
|
this->actor.textId = 0x9000 + this->dnsItemEntry->itemPrice;
|
||||||
|
}
|
||||||
Actor_SetFocus(&this->actor, 60.0f);
|
Actor_SetFocus(&this->actor, 60.0f);
|
||||||
Actor_SetScale(&this->actor, 0.01f);
|
Actor_SetScale(&this->actor, 0.01f);
|
||||||
SkelAnime_Update(&this->skelAnime);
|
SkelAnime_Update(&this->skelAnime);
|
||||||
|
@ -32,6 +32,7 @@ typedef struct EnDns {
|
|||||||
/* 0x02BD */ u8 dropCollectible;
|
/* 0x02BD */ u8 dropCollectible;
|
||||||
/* 0x02C0 */ DnsItemEntry* dnsItemEntry;
|
/* 0x02C0 */ DnsItemEntry* dnsItemEntry;
|
||||||
/* 0x02C4 */ f32 yInitPos;
|
/* 0x02C4 */ f32 yInitPos;
|
||||||
|
/* */ ScrubIdentity scrubIdentity;
|
||||||
} EnDns; // size = 0x02C8
|
} EnDns; // size = 0x02C8
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -69,6 +69,15 @@ void EnShopnuts_Init(Actor* thisx, GlobalContext* globalCtx) {
|
|||||||
CollisionCheck_SetInfo(&this->actor.colChkInfo, NULL, &sColChkInfoInit);
|
CollisionCheck_SetInfo(&this->actor.colChkInfo, NULL, &sColChkInfoInit);
|
||||||
Collider_UpdateCylinder(&this->actor, &this->collider);
|
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 && gSaveContext.scrubsPurchased[scrubIdentity.scrubId] == 1) {
|
||||||
|
Actor_Kill(&this->actor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (((this->actor.params == 0x0002) && (gSaveContext.itemGetInf[0] & 0x800)) ||
|
if (((this->actor.params == 0x0002) && (gSaveContext.itemGetInf[0] & 0x800)) ||
|
||||||
((this->actor.params == 0x0009) && (gSaveContext.infTable[25] & 4)) ||
|
((this->actor.params == 0x0009) && (gSaveContext.infTable[25] & 4)) ||
|
||||||
((this->actor.params == 0x000A) && (gSaveContext.infTable[25] & 8))) {
|
((this->actor.params == 0x000A) && (gSaveContext.infTable[25] & 8))) {
|
||||||
|
Loading…
Reference in New Issue
Block a user