Refactor GenerateItemPool and Ice Trap settings (#5773)

Refactors the item pool to fix numerous bugs, especially with Plentiful item pools, makes ship exclusive items affected by item pool, and changes ice trap settings to be more clear and consistent to the user.
This commit is contained in:
Pepper0ni
2026-01-03 18:42:26 +00:00
committed by GitHub
parent 9af262c1bb
commit db91fd37e1
16 changed files with 1064 additions and 1079 deletions

View File

@@ -60,29 +60,6 @@ PriceSettingsStruct merchantPrices = {
RSK_MERCHANT_PRICES_AFFORDABLE,
};
static void RemoveStartingItemsFromPool() {
for (RandomizerGet startingItem : StartingInventory) {
for (size_t i = 0; i < ItemPool.size(); i++) {
if (startingItem == RG_BIGGORON_SWORD) {
if (ItemPool[i] == RG_GIANTS_KNIFE || ItemPool[i] == RG_BIGGORON_SWORD) {
ItemPool[i] = GetJunkItem();
}
continue;
} else if (startingItem == ItemPool[i] || (Rando::StaticData::RetrieveItem(startingItem).IsBottleItem() &&
Rando::StaticData::RetrieveItem(ItemPool[i]).IsBottleItem())) {
if (AdditionalHeartContainers > 0 &&
(startingItem == RG_PIECE_OF_HEART || startingItem == RG_TREASURE_GAME_HEART)) {
ItemPool[i] = RG_HEART_CONTAINER;
AdditionalHeartContainers--;
} else {
ItemPool[i] = GetJunkItem();
}
break;
}
}
}
}
static void PropagateTimeTravel(GetAccessibleLocationsStruct& gals, RandomizerGet ignore = RG_NONE,
bool stopOnBeatable = false, bool addToPlaythrough = false) {
// special check for temple of time
@@ -163,7 +140,7 @@ static void ValidateOtherEntrance(GetAccessibleLocationsStruct& gals) {
// Apply all items that are necessary for checking all location access
static void ApplyAllAdvancmentItems() {
std::vector<RandomizerGet> itemsToPlace =
FilterFromPool(ItemPool, [](const auto i) { return Rando::StaticData::RetrieveItem(i).IsAdvancement(); });
FilterFromPool(itemPool, [](const auto i) { return Rando::StaticData::RetrieveItem(i).IsAdvancement(); });
for (RandomizerGet unplacedItem : itemsToPlace) {
Rando::StaticData::RetrieveItem(unplacedItem).ApplyEffect();
}
@@ -321,7 +298,7 @@ bool IsBombchus(RandomizerGet item, bool includeShops = false) {
}
bool IsBeatableWithout(RandomizerCheck excludedCheck, bool replaceItem,
RandomizerGet ignore = RG_NONE) { // RANDOTODO make excludCheck an ItemLocation
RandomizerGet ignore = RG_NONE) { // RANDOTODO make excludedCheck an ItemLocation
auto ctx = Rando::Context::GetInstance();
RandomizerGet copy = ctx->GetItemLocation(excludedCheck)->GetPlacedRandomizerGet(); // Copy out item
ctx->GetItemLocation(excludedCheck)->SetPlacedItem(RG_NONE); // Write in empty item
@@ -890,7 +867,7 @@ static void AssumedFill(const std::vector<RandomizerGet>& items, const std::vect
// copy all not yet placed advancement items so that we can apply their effects for the fill algorithm
std::vector<RandomizerGet> itemsToNotPlace =
FilterFromPool(ItemPool, [](const auto i) { return Rando::StaticData::RetrieveItem(i).IsAdvancement(); });
FilterFromPool(itemPool, [](const auto i) { return Rando::StaticData::RetrieveItem(i).IsAdvancement(); });
// shuffle the order of items to place
Shuffle(itemsToPlace);
@@ -978,7 +955,7 @@ static void RandomizeDungeonRewards() {
if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON) ||
ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_VANILLA)) {
// get stones and medallions
std::vector<RandomizerGet> rewards = FilterAndEraseFromPool(ItemPool, [](const auto i) {
std::vector<RandomizerGet> rewards = FilterAndEraseFromPool(itemPool, [](const auto i) {
return Rando::StaticData::RetrieveItem(i).GetItemType() == ITEMTYPE_DUNGEONREWARD;
});
@@ -1000,7 +977,7 @@ static void RandomizeDungeonRewards() {
}
} else if (ctx->GetOption(RSK_LINKS_POCKET).Is(RO_LINKS_POCKET_DUNGEON_REWARD)) {
// get 1 stone/medallion
std::vector<RandomizerGet> rewards = FilterFromPool(ItemPool, [](const auto i) {
std::vector<RandomizerGet> rewards = FilterFromPool(itemPool, [](const auto i) {
return Rando::StaticData::RetrieveItem(i).GetItemType() == ITEMTYPE_DUNGEONREWARD;
});
// If there are no remaining stones/medallions, then Link's pocket won't get one
@@ -1014,7 +991,7 @@ static void RandomizeDungeonRewards() {
// baseOffset];
ctx->PlaceItemInLocation(RC_LINKS_POCKET, startingReward);
// erase the stone/medallion from the Item Pool
FilterAndEraseFromPool(ItemPool, [startingReward](const RandomizerGet i) { return i == startingReward; });
FilterAndEraseFromPool(itemPool, [startingReward](const RandomizerGet i) { return i == startingReward; });
}
}
@@ -1059,7 +1036,7 @@ static void RandomizeOwnDungeon(const Rando::DungeonInfo* dungeon) {
// Add specific items that need be randomized within this dungeon
if (ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OWN_DUNGEON) && dungeon->GetSmallKey() != RG_NONE) {
std::vector<RandomizerGet> dungeonSmallKeys =
FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i) {
FilterAndEraseFromPool(itemPool, [dungeon](const RandomizerGet i) {
return (i == dungeon->GetSmallKey()) || (i == dungeon->GetKeyRing());
});
AddElementsToPool(dungeonItems, dungeonSmallKeys);
@@ -1070,7 +1047,7 @@ static void RandomizeOwnDungeon(const Rando::DungeonInfo* dungeon) {
(ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_OWN_DUNGEON) &&
dungeon->GetBossKey() == RG_GANONS_CASTLE_BOSS_KEY)) {
auto dungeonBossKey =
FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i) { return i == dungeon->GetBossKey(); });
FilterAndEraseFromPool(itemPool, [dungeon](const RandomizerGet i) { return i == dungeon->GetBossKey(); });
AddElementsToPool(dungeonItems, dungeonBossKey);
}
@@ -1080,7 +1057,7 @@ static void RandomizeOwnDungeon(const Rando::DungeonInfo* dungeon) {
// randomize map and compass separately since they're not progressive
if (ctx->GetOption(RSK_SHUFFLE_MAPANDCOMPASS).Is(RO_DUNGEON_ITEM_LOC_OWN_DUNGEON) && dungeon->GetMap() != RG_NONE &&
dungeon->GetCompass() != RG_NONE) {
auto dungeonMapAndCompass = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i) {
auto dungeonMapAndCompass = FilterAndEraseFromPool(itemPool, [dungeon](const RandomizerGet i) {
return i == dungeon->GetMap() || i == dungeon->GetCompass();
});
AssumedFill(dungeonMapAndCompass, dungeonLocations);
@@ -1107,12 +1084,12 @@ static void RandomizeDungeonItems() {
for (auto dungeon : ctx->GetDungeons()->GetDungeonList()) {
if (ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANY_DUNGEON)) {
auto dungeonKeys = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i) {
auto dungeonKeys = FilterAndEraseFromPool(itemPool, [dungeon](const RandomizerGet i) {
return (i == dungeon->GetSmallKey()) || (i == dungeon->GetKeyRing());
});
AddElementsToPool(anyDungeonItems, dungeonKeys);
} else if (ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OVERWORLD)) {
auto dungeonKeys = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i) {
auto dungeonKeys = FilterAndEraseFromPool(itemPool, [dungeon](const RandomizerGet i) {
return (i == dungeon->GetSmallKey()) || (i == dungeon->GetKeyRing());
});
AddElementsToPool(overworldItems, dungeonKeys);
@@ -1121,45 +1098,45 @@ static void RandomizeDungeonItems() {
if (ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANY_DUNGEON) &&
dungeon->GetBossKey() != RG_GANONS_CASTLE_BOSS_KEY) {
auto bossKey = FilterAndEraseFromPool(
ItemPool, [dungeon](const RandomizerGet i) { return i == dungeon->GetBossKey(); });
itemPool, [dungeon](const RandomizerGet i) { return i == dungeon->GetBossKey(); });
AddElementsToPool(anyDungeonItems, bossKey);
} else if (ctx->GetOption(RSK_BOSS_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OVERWORLD) &&
dungeon->GetBossKey() != RG_GANONS_CASTLE_BOSS_KEY) {
auto bossKey = FilterAndEraseFromPool(
ItemPool, [dungeon](const RandomizerGet i) { return i == dungeon->GetBossKey(); });
itemPool, [dungeon](const RandomizerGet i) { return i == dungeon->GetBossKey(); });
AddElementsToPool(overworldItems, bossKey);
}
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_ANY_DUNGEON)) {
auto ganonBossKey =
FilterAndEraseFromPool(ItemPool, [](const auto i) { return i == RG_GANONS_CASTLE_BOSS_KEY; });
FilterAndEraseFromPool(itemPool, [](const auto i) { return i == RG_GANONS_CASTLE_BOSS_KEY; });
AddElementsToPool(anyDungeonItems, ganonBossKey);
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_OVERWORLD)) {
auto ganonBossKey =
FilterAndEraseFromPool(ItemPool, [](const auto i) { return i == RG_GANONS_CASTLE_BOSS_KEY; });
FilterAndEraseFromPool(itemPool, [](const auto i) { return i == RG_GANONS_CASTLE_BOSS_KEY; });
AddElementsToPool(overworldItems, ganonBossKey);
}
}
if (ctx->GetOption(RSK_GERUDO_KEYS).Is(RO_GERUDO_KEYS_ANY_DUNGEON)) {
auto gerudoKeys = FilterAndEraseFromPool(ItemPool, [](const auto i) {
auto gerudoKeys = FilterAndEraseFromPool(itemPool, [](const auto i) {
return i == RG_GERUDO_FORTRESS_SMALL_KEY || i == RG_GERUDO_FORTRESS_KEY_RING;
});
AddElementsToPool(anyDungeonItems, gerudoKeys);
} else if (ctx->GetOption(RSK_GERUDO_KEYS).Is(RO_GERUDO_KEYS_OVERWORLD)) {
auto gerudoKeys = FilterAndEraseFromPool(ItemPool, [](const auto i) {
auto gerudoKeys = FilterAndEraseFromPool(itemPool, [](const auto i) {
return i == RG_GERUDO_FORTRESS_SMALL_KEY || i == RG_GERUDO_FORTRESS_KEY_RING;
});
AddElementsToPool(overworldItems, gerudoKeys);
}
if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_ANY_DUNGEON)) {
auto rewards = FilterAndEraseFromPool(ItemPool, [](const auto i) {
auto rewards = FilterAndEraseFromPool(itemPool, [](const auto i) {
return Rando::StaticData::RetrieveItem(i).GetItemType() == ITEMTYPE_DUNGEONREWARD;
});
AddElementsToPool(anyDungeonItems, rewards);
} else if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_OVERWORLD)) {
auto rewards = FilterAndEraseFromPool(ItemPool, [](const auto i) {
auto rewards = FilterAndEraseFromPool(itemPool, [](const auto i) {
return Rando::StaticData::RetrieveItem(i).GetItemType() == ITEMTYPE_DUNGEONREWARD;
});
AddElementsToPool(overworldItems, rewards);
@@ -1172,12 +1149,12 @@ static void RandomizeDungeonItems() {
// Randomize maps and compasses after since they're not advancement items
for (auto dungeon : ctx->GetDungeons()->GetDungeonList()) {
if (ctx->GetOption(RSK_SHUFFLE_MAPANDCOMPASS).Is(RO_DUNGEON_ITEM_LOC_ANY_DUNGEON)) {
auto mapAndCompassItems = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i) {
auto mapAndCompassItems = FilterAndEraseFromPool(itemPool, [dungeon](const RandomizerGet i) {
return i == dungeon->GetMap() || i == dungeon->GetCompass();
});
AssumedFill(mapAndCompassItems, anyDungeonLocations, true);
} else if (ctx->GetOption(RSK_SHUFFLE_MAPANDCOMPASS).Is(RO_DUNGEON_ITEM_LOC_OVERWORLD)) {
auto mapAndCompassItems = FilterAndEraseFromPool(ItemPool, [dungeon](const RandomizerGet i) {
auto mapAndCompassItems = FilterAndEraseFromPool(itemPool, [dungeon](const RandomizerGet i) {
return i == dungeon->GetMap() || i == dungeon->GetCompass();
});
AssumedFill(mapAndCompassItems, ctx->overworldLocations, true);
@@ -1189,14 +1166,14 @@ static void RandomizeLinksPocket() {
auto ctx = Rando::Context::GetInstance();
if (ctx->GetOption(RSK_LINKS_POCKET).Is(RO_LINKS_POCKET_ADVANCEMENT)) {
// Get all the advancement items don't include tokens
std::vector<RandomizerGet> advancementItems = FilterAndEraseFromPool(ItemPool, [](const auto i) {
std::vector<RandomizerGet> advancementItems = FilterAndEraseFromPool(itemPool, [](const auto i) {
return Rando::StaticData::RetrieveItem(i).IsAdvancement() &&
Rando::StaticData::RetrieveItem(i).GetItemType() != ITEMTYPE_TOKEN;
});
// select a random one
RandomizerGet startingItem = RandomElement(advancementItems, true);
// add the others back
AddElementsToPool(ItemPool, advancementItems);
AddElementsToPool(itemPool, advancementItems);
ctx->PlaceItemInLocation(RC_LINKS_POCKET, startingItem);
} else if (ctx->GetOption(RSK_LINKS_POCKET).Is(RO_LINKS_POCKET_NOTHING)) {
@@ -1248,13 +1225,12 @@ int Fill() {
ctx->GenerateLocationPool();
GenerateItemPool();
GenerateStartingInventory();
RemoveStartingItemsFromPool();
FillExcludedLocations();
// Temporarily add shop items to the ItemPool so that entrance randomization
// Temporarily add shop items to the itemPool so that entrance randomization
// can validate the world using deku/hylian shields
StartPerformanceTimer(PT_ENTRANCE_SHUFFLE);
AddElementsToPool(ItemPool, GetMinVanillaShopItems(8)); // assume worst case shopsanity 7
AddElementsToPool(itemPool, GetMinVanillaShopItems(8)); // assume worst case shopsanity 7
if (ctx->GetOption(RSK_SHUFFLE_ENTRANCES)) {
SPDLOG_INFO("Shuffling Entrances...");
if (ctx->GetEntranceShuffler()->ShuffleAllEntrances() == ENTRANCE_SHUFFLE_FAILURE) {
@@ -1266,7 +1242,7 @@ int Fill() {
}
SetAreas();
// erase temporary shop items
FilterAndEraseFromPool(ItemPool, [](const auto item) {
FilterAndEraseFromPool(itemPool, [](const auto item) {
return Rando::StaticData::RetrieveItem(item).GetItemType() == ITEMTYPE_SHOP;
});
StopPerformanceTimer(PT_ENTRANCE_SHUFFLE);
@@ -1378,7 +1354,7 @@ int Fill() {
if (ctx->GetOption(RSK_SHUFFLE_SONGS).IsNot(RO_SONG_SHUFFLE_ANYWHERE) &&
ctx->GetOption(RSK_SHUFFLE_SONGS).IsNot(RO_SONG_SHUFFLE_OFF)) {
// Get each song
std::vector<RandomizerGet> songs = FilterAndEraseFromPool(ItemPool, [](const auto i) {
std::vector<RandomizerGet> songs = FilterAndEraseFromPool(itemPool, [](const auto i) {
return Rando::StaticData::RetrieveItem(i).GetItemType() == ITEMTYPE_SONG;
});
@@ -1411,14 +1387,14 @@ int Fill() {
SPDLOG_INFO("Shuffling Advancement Items");
// Then place the rest of the advancement items
std::vector<RandomizerGet> remainingAdvancementItems = FilterAndEraseFromPool(
ItemPool, [](const auto i) { return Rando::StaticData::RetrieveItem(i).IsAdvancement(); });
itemPool, [](const auto i) { return Rando::StaticData::RetrieveItem(i).IsAdvancement(); });
AssumedFill(remainingAdvancementItems, ctx->allLocations, true);
StopPerformanceTimer(PT_ADVANCEMENT_ITEMS);
StartPerformanceTimer(PT_REMAINING_ITEMS);
// Fast fill for the rest of the pool
SPDLOG_INFO("Shuffling Remaining Items");
std::vector<RandomizerGet> remainingPool = FilterAndEraseFromPool(ItemPool, [](const auto i) { return true; });
std::vector<RandomizerGet> remainingPool = FilterAndEraseFromPool(itemPool, [](const auto i) { return true; });
FastFill(remainingPool, GetAllEmptyLocations(), false);
StopPerformanceTimer(PT_REMAINING_ITEMS);

File diff suppressed because it is too large Load Diff

View File

@@ -11,4 +11,4 @@ void AddItemToPool(std::vector<RandomizerGet>& pool, const RandomizerGet item, s
RandomizerGet GetJunkItem();
void GenerateItemPool();
extern std::vector<RandomizerGet> ItemPool;
extern std::vector<RandomizerGet> itemPool;

View File

@@ -27,7 +27,7 @@ PriceSettingsStruct::PriceSettingsStruct(RandomizerSettingKey _main, RandomizerS
affordable = _affordable;
}
static std::array<std::vector<Text>, 0xF1> trickNameTable; // Table of trick names for ice traps
static std::array<std::vector<Text>, RG_MAX> trickNameTable; // Table of trick names for ice traps
bool initTrickNames = false; // Indicates if trick ice trap names have been initialized yet
// Set vanilla shop item locations before potentially shuffling
@@ -887,6 +887,56 @@ void InitTrickNames() {
Text{ "Triforce Shard", "Éclat de Triforce", "Triforce-Fragment" }, // "Triforce Shard"
Text{ "Shiny Rock", "Caillou Brillant", "glänzender Stein" }, // "Shiny Rock"
};
trickNameTable[RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL] = {
// TODO_TRANSLATE
Text{ "Volcano Seed Spirit" },
Text{ "Bolero Sprout Platform" },
};
trickNameTable[RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL] = {
// TODO_TRANSLATE
Text{ "Dodongo's Seed Spirit" },
Text{ "Boulder Sprout Platform" },
};
trickNameTable[RG_DESERT_COLOSSUS_BEAN_SOUL] = {
// TODO_TRANSLATE
Text{ "Spirit Temple Seed Spirit" },
Text{ "Colossus Arch Sprout Platform" },
};
trickNameTable[RG_GERUDO_VALLEY_BEAN_SOUL] = {
// TODO_TRANSLATE
Text{ "Waterfall Seed Spirit" },
Text{ "Gerudo Cow Sprout Platform" },
};
trickNameTable[RG_GRAVEYARD_BEAN_SOUL] = {
// TODO_TRANSLATE
Text{ "GY Crate Seed Spirit" },
Text{ "Dampe's Sprout Platform" },
};
trickNameTable[RG_KOKIRI_FOREST_BEAN_SOUL] = {
// TODO_TRANSLATE
Text{ "Rupee Ledge Seed Spirit" },
Text{ "KF Shop Sprout Platform" },
};
trickNameTable[RG_LAKE_HYLIA_BEAN_SOUL] = {
// TODO_TRANSLATE
Text{ "Hylia Lab Seed Spirit" },
Text{ "Fishing Sprout Platform" },
};
trickNameTable[RG_LOST_WOODS_BRIDGE_BEAN_SOUL] = {
// TODO_TRANSLATE
Text{ "LW Bridge Seed Spirit" },
Text{ "Skull Kid Sprout Platform" },
};
trickNameTable[RG_LOST_WOODS_BEAN_SOUL] = {
// TODO_TRANSLATE
Text{ "Deku Theatre Seed Spirit" },
Text{ "Deku Scrubs Sprout Platform" },
};
trickNameTable[RG_ZORAS_RIVER_BEAN_SOUL] = {
// TODO_TRANSLATE
Text{ "River Ride Seed Spirit" },
Text{ "Bean Salesman Sprout Platform" },
};
trickNameTable[RG_GOHMA_SOUL] = {
Text{ "Spider Sense", "Sens de l'Araignée", "Spinnensinn" },
Text{ "Deku Spirit", "Parasite Mojo", "Deku Geist" },
@@ -937,6 +987,11 @@ void InitTrickNames() {
Text{ "Floating Lure", "Floating Lure", "Schwimmer" },
Text{ "Fishing Reel", "Fishing Reel", "Angelschnur" },
};
trickNameTable[RG_SKELETON_KEY] = {
// TODO_TRANSLATE
Text{ "Stalfos Key" }, Text{ "Nightmare Key" }, Text{ "Graveyard Key" },
Text{ "King's Key" }, Text{ "Hero's Key" },
};
trickNameTable[RG_OCARINA_A_BUTTON] = {
Text{ "Ocarina J Button", "Touche Ha de l'Ocarina", "J-Taste der Okarina" },
Text{ "Ocarina Ayy Button", "Touche Ah de l'Ocarina", "A-Taste der Flöte" },
@@ -965,6 +1020,331 @@ void InitTrickNames() {
Text{ "Overworld C Right Button", "Trou Droit de l'Ocarina", "C-Rechts-Taste der E-Gitarre" },
};
trickNameTable[RG_GREG_RUPEE] = {
// TODO_TRANSALTE
Text{ "Morshu the Green Ruby", "Morshu the Green Ruby", "Morshu the Green Ruby" },
Text{ "Geoffrey the Gray Rupoor", "Geoffrey the Gray Rupoor", "Geoffrey the Gray Rupoor" },
Text{ "Validation Rupee", "Validation Rupee", "Validation Rupee" },
Text{ "Gary, just Gary", "Gary, just Gary", "Gary, just Gary" },
Text{ "Ike the Indigo Ice Trap", "Ike the Indigo Ice Trap", "Ike the Indigo Ice Trap" },
};
trickNameTable[RG_FOREST_TEMPLE_SMALL_KEY] = {
// TODO_TRANSALTE
Text{ "Wind Temple Smol Key", "Wind Temple Smol Key", "Wind Temple Smol Key" },
Text{ "Woodfall Temple Small Key", "Woodfall Temple Small Key", "Woodfall Temple Small Key" },
Text{ "Skull Woods Small Key", "Skull Woods Small Key", "Skull Woods Small Key" },
};
trickNameTable[RG_FIRE_TEMPLE_SMALL_KEY] = {
// TODO_TRANSALTE
Text{ "Ice Cavern Small Keese", "Ice Cavern Small Keese", "Ice Cavern Small Keese" },
Text{ "Goron Temple Small Key", "Goron Temple Small Key", "Goron Temple Small Key" },
Text{ "Eldin Temple Salmon Koi", "Eldin Temple Salmon Koi", "Eldin Temple Salmon Koi" },
};
trickNameTable[RG_WATER_TEMPLE_SMALL_KEY] = {
// TODO_TRANSALTE
Text{ "Swamp Palace Small Keese", "Swamp Palace Small Keese", "Swamp Palace Small Keese" },
Text{ "Great Bay Temple Small Key", "Great Bay Temple Small Key", "Great Bay Temple Small Key" },
Text{ "Lakebed Temple Small Key", "Lakebed Temple Small Key", "Lakebed Temple Small Key" },
};
trickNameTable[RG_SPIRIT_TEMPLE_SMALL_KEY] = {
// TODO_TRANSALTE
Text{ "Light Temple Small Key", "Light Temple Small Key", "Light Temple Small Key" },
Text{ "Lightning Temple Smol Key", "Lightning Temple Smol Key", "Lightning Temple Smol Key" },
Text{ "Desert Palace Small Key", "Desert Palace Small Key", "Desert Palace Small Key" },
Text{ "Stone Tower Small Keese", "Stone Tower Small Keese", "Stone Tower Small Keese" },
};
trickNameTable[RG_SHADOW_TEMPLE_SMALL_KEY] = {
// TODO_TRANSALTE
Text{ "Palace of Darkness Small Key", "Palace of Darkness Small Key", "Palace of Darkness Small Key" },
Text{ "Shrine of Illusion Salmon Koi", "Shrine of Illusion Salmon Koi", "Shrine of Illusion Salmon Koi" },
Text{ "Palace of Twilight Small Key", "Palace of Twilight Small Key", "Palace of Twilight Small Key" },
};
trickNameTable[RG_BOTTOM_OF_THE_WELL_SMALL_KEY] = {
// TODO_TRANSALTE
Text{ "Top of the Wall Small Key", "Top of the Wall Small Key", "Top of the Wall Small Key" },
Text{ "Breath of the Wild Small Key", "Breath of the Wild Small Key", "Breath of the Wild Small Key" },
Text{ "Beneath the Well Small Key", "Beneath the Well Small Key", "Beneath the Well Small Key" },
};
trickNameTable[RG_GERUDO_TRAINING_GROUND_SMALL_KEY] = {
// TODO_TRANSALTE
Text{ "Gerudo Sanctum Small Key", "Gerudo Sanctum Small Key", "Gerudo Sanctum Small Key" },
Text{ "Lady's Lair Small Keese", "Lady's Lair Small Keese", "Lady's Lair Small Keese" },
Text{ "Knight Acadamy Small Key", "Knight Acadamy Small Key", "Knight Acadamy Small Key" },
};
trickNameTable[RG_GERUDO_FORTRESS_SMALL_KEY] = {
// TODO_TRANSALTE
Text{ "Fortress of Winds Small Key", "Fortress of Winds Small Key", "Fortress of Winds Small Key" },
Text{ "Thieve's Town Small Key", "Thieve's Town Small Key", "Thieve's Town Small Key" },
Text{ "Fortress Centrum Small Key", "Fortress Centrum Small Key", "Fortress Centrum Small Key" },
Text{ "Forsaken Fortress Smol Key", "Forsaken Fortress Smol Key", "Forsaken Fortress Smol Key" },
Text{ "Pirate's Fortress Small Key", "Pirate's Fortress Small Key", "Pirate's Fortress Small Key" },
};
trickNameTable[RG_GANONS_CASTLE_SMALL_KEY] = {
// TODO_TRANSALTE
Text{ "Hyrule Castle Salmon Koi", "Hyrule Castle Salmon Koi", "Hyrule Castle Salmon Koi" },
Text{ "Onox's Castle Small Key", "Onox's Castle Small Key", "Onox's Castle Small Key" },
Text{ "Vaati's Palace Small Key", "Vaati's Palace Small Key", "Vaati's Palace Small Key" },
};
trickNameTable[RG_FOREST_TEMPLE_KEY_RING] = {
// TODO_TRANSALTE
Text{ "Wind Temple Key Ring", "Wind Temple Key Ring", "Wind Temple Key Ring" },
Text{ "Woodfall Temple Key Ring", "Woodfall Temple Key Ring", "Woodfall Temple Key Ring" },
Text{ "Skull Woods Key Ring", "Skull Woods Key Ring", "Skull Woods Key Ring" },
};
trickNameTable[RG_FIRE_TEMPLE_KEY_RING] = {
// TODO_TRANSALTE
Text{ "Ice Cavern Keese Ring", "Ice Cavern Keese Ring", "Ice Cavern Keese Ring" },
Text{ "Goron Temple Key Ring", "Goron Temple Key Ring", "Goron Temple Key Ring" },
Text{ "Eldin Temple Koi Ray", "Eldin Temple Koi Ray", "Eldin Temple Koi Ray" },
};
trickNameTable[RG_WATER_TEMPLE_KEY_RING] = {
// TODO_TRANSALTE
Text{ "Swamp Palace Keese Ring", "Swamp Palace Keese Ring", "Swamp Palace Keese Ring" },
Text{ "Great Bay Temple Key Ring", "Great Bay Temple Key Ring", "Great Bay Temple Key Ring" },
Text{ "Lakebed Temple Key Ring", "Lakebed Temple Key Ring", "Lakebed Temple Key Ring" },
};
trickNameTable[RG_SPIRIT_TEMPLE_KEY_RING] = {
// TODO_TRANSALTE
Text{ "Light Temple Key Ring", "Light Temple Key Ring", "Light Temple Key Ring" },
Text{ "Lightning Temple Key Ring", "Lightning Temple Key Ring", "Lightning Temple Key Ring" },
Text{ "Desert Palace Key Ring", "Desert Palace Key Ring", "Desert Palace Key Ring" },
Text{ "Stone Tower Keese Ring", "Stone Tower Keese Ring", "Stone Tower Keese Ring" },
};
trickNameTable[RG_SHADOW_TEMPLE_KEY_RING] = {
// TODO_TRANSALTE
Text{ "Palace of Darkness Key Ring", "Palace of Darkness Key Ring", "Palace of Darkness Key Ring" },
Text{ "Shrine of Illusion Koi Ray", "Shrine of Illusion Koi Ray", "Shrine of Illusion Koi Ray" },
Text{ "Palace of Twilight Key Ring", "Palace of Twilight Key Ring", "Palace of Twilight Key Ring" },
};
trickNameTable[RG_BOTTOM_OF_THE_WELL_KEY_RING] = {
// TODO_TRANSALTE
Text{ "Top of the Wall Key Ring", "Top of the Wall Key Ring", "Top of the Wall Key Ring" },
Text{ "Breath of the Wild Key Ring", "Breath of the Wild Key Ring", "Breath of the Wild Key Ring" },
Text{ "Beneath the Well Key Ring", "Beneath the Well Key Ring", "Beneath the Well Key Ring" },
};
trickNameTable[RG_GERUDO_TRAINING_GROUND_KEY_RING] = {
// TODO_TRANSALTE
Text{ "Gerudo Sanctum Key Ring", "Gerudo Sanctum Key Ring", "Gerudo Sanctum Key Ring" },
Text{ "Lady's Lair Keese Ring", "Lady's Lair Keese Ring", "Lady's Lair Keese Ring" },
Text{ "Knight Acadamy Key Ring", "Knight Acadamy Key Ring", "Knight Acadamy Key Ring" },
};
trickNameTable[RG_GERUDO_FORTRESS_KEY_RING] = {
// TODO_TRANSALTE
Text{ "Fortress of Winds Key Ring", "Fortress of Winds Key Ring", "Fortress of Winds Key Ring" },
Text{ "Thieve's Town Key Ring", "Thieve's Town Key Ring", "Thieve's Town Key Ring" },
Text{ "Fortress Centrum Key Ring", "Fortress Centrum Key Ring", "Fortress Centrum Key Ring" },
Text{ "Forsaken Fortress Key Ring", "Forsaken Fortress Key Ring", "Forsaken Fortresse Key Ring" },
Text{ "Pirate's Fortress Key Ring", "Pirate's Fortress Key Ring", "Pirate's Fortress Key Ring" },
};
trickNameTable[RG_GANONS_CASTLE_KEY_RING] = {
// TODO_TRANSALTE
Text{ "Hyrule Castle Koi Ray", "Hyrule Castle Koi Ray", "Hyrule Castle Koi Ray" },
Text{ "Onox's Castle Key Ring", "Onox's Castle Key Ring", "Onox's Castle Key Ring" },
Text{ "Vaati's Palace Key Ring", "Vaati's Palace Key Ring", "Vaati's Palace Key Ring" },
};
trickNameTable[RG_FOREST_TEMPLE_BOSS_KEY] = {
// TODO_TRANSALTE
Text{ "Wind Temple Boss Key", "Wind Temple Boss Key", "Wind Temple Boss Key" },
Text{ "Woodfall Temple Boss Key", "Woodfall Temple Boss Key", "Woodfall Temple Boss Key" },
Text{ "Skull Woods Boss Key", "Skull Woods Boss Key", "Skull Woods Boss Key" },
Text{ "Phantom Ganon's Key", "Phantom Ganon's Key", "Phantom Ganon's Key" },
Text{ "Deku Tree's Boss Key", "Deku Tree's Boss Key", "Deku Tree's Boss Key" },
};
trickNameTable[RG_FIRE_TEMPLE_BOSS_KEY] = {
// TODO_TRANSALTE
Text{ "Ice Cavern Boss Keese", "Ice Cavern Boss Keese", "Ice Cavern Boss Keese" },
Text{ "Goron Temple Boss Key", "Goron Temple Boss Key", "Goron Temple Boss Key" },
Text{ "Eldin Temple Boss Koi", "Eldin Temple Boss Koi", "Eldin Temple Boss Koi" },
Text{ "Volvagia's Key", "Volvagia's Key", "Volvagia's Key" },
Text{ "Dodongo's Cavern Boss Key", "Dodongo's Cavern Boss Key", "Dodongo's Cavern Boss Key" },
};
trickNameTable[RG_WATER_TEMPLE_BOSS_KEY] = {
// TODO_TRANSALTE
Text{ "Swamp Palace Boss Keese", "Swamp Palace Boss Keese", "Swamp Palace Boss Keese" },
Text{ "Great Bay Temple Boss Key", "Great Bay Temple Boss Key", "Great Bay Temple Boss Key" },
Text{ "Lakebed Temple Boss Key", "Lakebed Temple Boss Key", "Lakebed Temple Boss Key" },
Text{ "Morpha's Key", "Morpha's Key", "Morpha's Key" },
Text{ "Jabu Jabu's Belly Boss Key", "Jabu Jabu's Belly Boss Key", "Jabu Jabu's Belly Boss Key" },
};
trickNameTable[RG_SPIRIT_TEMPLE_BOSS_KEY] = {
// TODO_TRANSALTE
Text{ "Light Temple Boss Key", "Light Temple Boss Key", "Light Temple Boss Key" },
Text{ "Lightning Temple Boss Key", "Lightning Temple Boss Key", "Lightning Temple Boss Key" },
Text{ "Desert Palace Boss Key", "Desert Palace Boss Key", "Desert Palace Boss Key" },
Text{ "Stone Tower Boss Keese", "Stone Tower Boss Keese", "Stone Tower Boss Keese" },
Text{ "Twinrova's Key", "Twinrova's Key", "Twinrova's Key" },
};
trickNameTable[RG_SHADOW_TEMPLE_BOSS_KEY] = {
// TODO_TRANSALTE
Text{ "Palace of Darkness Boss Key", "Palace of Darkness Boss Key", "Palace of Darkness Boss Key" },
Text{ "Shrine of Illusion Bass Koi", "Shrine of Illusion Bass Koi", "Shrine of Illusion Bass Koi" },
Text{ "Palace of Twilight Boss Key", "Palace of Twilight Boss Key", "Palace of Twilight Boss Key" },
Text{ "Bongo Bongo's Key", "Bongo Bongo's Key", "Bongo Bongo's Key" },
};
trickNameTable[RG_GANONS_CASTLE_BOSS_KEY] = {
// TODO_TRANSALTE
Text{ "Hyrule Castle Bass Koi", "Hyrule Castle Bass Koi", "Hyrule Castle Bass Koi" },
Text{ "Onox's Castle Boss Key", "Onox's Castle Boss Key", "Onox's Castle Boss Key" },
Text{ "Vaati's Palace Boss Key", "Vaati's Palace Boss Key", "Vaati's Palace Boss Key" },
Text{ "Ganondorf's Key", "Ganondorf's Key", "Ganondorf's Key" },
};
trickNameTable[RG_GUARD_HOUSE_KEY] = {
// TODO_TRANSLATE
Text{ "Pot Room Key", "Pot Room Key", "Pot Room Key" },
Text{ "Poe Shop Keese", "Poe Shop Keese", "Poe Shop Keese" },
Text{ "Pot Collectors Club Key", "Pot Collectors Club Key", "Pot Collectors Club Key" },
};
trickNameTable[RG_MARKET_BAZAAR_KEY] = {
// TODO_TRANSLATE
Text{ "Malo Mart Key", "Malo Mart Key", "Malo Mart Key" },
Text{ "Zora Shop Key", "Zora Shop Key", "Zora Shop Key" },
Text{ "Goronu General Store Key", "Goronu General Store Key", "Goronu General Store Key" },
Text{ "Chudly's Fine Goods Key", "Chudly's Fine Goods Key", "Chudly's Fine Goods Key" },
};
trickNameTable[RG_MARKET_POTION_SHOP_KEY] = {
// TODO_TRANSLATE
Text{ "Market Medicine Shop Koi", "Market Medicine Shop Koi", "Market Medicine Shop Koi" },
Text{ "Market Pharmacy Key", "Market Pharmacy Key", "Market Pharmacy Key" },
Text{ "Market Drug Store Keese", "Market Drug Store Keese", "Market Drug Store Keese" },
};
trickNameTable[RG_MASK_SHOP_KEY] = {
// TODO_TRANSLATE
Text{ "Masked Ship Koi", "Masked Ship Koi", "Masked Ship Koi" },
Text{ "Madame Couture's Key", "Madame Couture's Key", "Madame Couture's Key" },
Text{ "South Clock Town Key", "South Clock Town Key", "South Clock Town Key" },
};
trickNameTable[RG_MARKET_SHOOTING_GALLERY_KEY] = {
// TODO_TRANSLATE
Text{ "Swamp Shooting Gallery Key", "Swamp Shooting Gallery Key", "Swamp Shooting Gallery Key" },
Text{ "Koume's Target Shooting Key", "Koume's Target Shooting Key", "Koume's Target Shooting Key" },
Text{ "Pumpkin Pull Key", "Pumpkin Pull Key", "Pumpkin Pull Key" },
};
trickNameTable[RG_BOMBCHU_BOWLING_KEY] = {
// TODO_TRANSLATE
Text{ "Bombchu Gallery Key", "Bombchu Gallery Key", "Bombchu Gallery Key" },
Text{ "Cucco Bowling Ally Key", "Cucco Bowling Ally Key", "Cucco Bowling Ally Key" },
Text{ "Snowball Bowling Key", "Snowball Bowling Key", "Snowball Bowling Key" },
Text{ "Bombsketball Key", "Bombsketball Key", "Bombsketball Key" },
};
trickNameTable[RG_TREASURE_CHEST_GAME_BUILDING_KEY] = {
// TODO_TRANSLATE
Text{ "Lucky Treasure Game Koi", "Lucky Treasure Game Koi", "Lucky Treasure Game Koi" },
Text{ "1 in 32 Key", "1 in 32 Key", "1 in 32 Key" },
Text{ "Fortune's Coice Key", "Fortune's Coice Key", "Fortune's Coice Key" },
Text{ "Money Making Game Key", "Money Making Game Key", "Money Making Game Key" },
Text{ "Trading Card Game Key", "Trading Card Game Key", "Trading Card Game Key" },
};
trickNameTable[RG_BOMBCHU_SHOP_KEY] = {
// TODO_TRANSLATE
Text{ "Curiosity Shop Key", "Curiosity Shop Key", "Curiosity Shop Key" },
Text{ "Barnes Bomb Shop Key", "Barnes Bomb Shop Key", "Barnes Bomb Shop Key" },
Text{ "Bomb Flower Shop Key", "Bomb Flower Shop Key", "Bomb Flower Shop Key" },
};
trickNameTable[RG_RICHARDS_HOUSE_KEY] = {
// TODO_TRANSLATE
Text{ "Stockwell's House Key", "Stockwell's House Key", "Stockwell's House Key" },
Text{ "Blue Dog's House Key", "Blue Dog's House Key", "Blue Dog's House Key" },
Text{ "Barkle's House Key", "Barkle's House Key", "Barkle's House Key" },
Text{ "Chimimi's House Key", "Chimimi's House Key", "Chimimi's House Key" },
};
trickNameTable[RG_ALLEY_HOUSE_KEY] = {
// TODO_TRANSLATE
Text{ "Mido's House Key", "Mido's House Key", "Mido's House Key" },
Text{ "Saria's House Key", "Saria's House Key", "Saria's House Key" },
Text{ "@'s House Key", "@'s House Key", "@'s House Key" },
};
trickNameTable[RG_KAK_BAZAAR_KEY] = {
// TODO_TRANSLATE
Text{ "Skyloft Bazaar Key", "Skyloft Bazaar Key", "Skyloft Bazaar Key" },
Text{ "Harlequin Bazaar Key", "Harlequin Bazaar Key", "Harlequin Bazaar Key" },
Text{ "Kokiri Shop Key", "Kokiri Shop Key", "Kokiri Shop Key" },
Text{ "Goron Shop Key", "Goron Shop Key", "Goron Shop Key" },
};
trickNameTable[RG_KAK_POTION_SHOP_KEY] = {
// TODO_TRANSLATE
Text{ "Kak Medicine Shop Keep", "Kak Medicine Shop Keep", "Kak Medicine Shop Keep" },
Text{ "Kak Pharmacy Key", "Kak Pharmacy Key", "Kak Pharmacy Key" },
Text{ "Kak Drug Store Keese", "Kak Drug Store Keese", "Kak Drug Store Keese" },
};
trickNameTable[RG_BOSS_HOUSE_KEY] = {
// TODO_TRANSLATE
Text{ "Kakariko Village Boss Key", "Kakariko Village Boss Key", "Kakariko Village Boss Key" },
Text{ "Lord Kohga's House Key", "Lord Kohga's House Key", "Lord Kohga's House Key" },
Text{ "Twinrova's House Key", "Twinrova's House Key", "Twinrova's House Key" },
};
trickNameTable[RG_GRANNYS_POTION_SHOP_KEY] = {
// TODO_TRANSLATE
Text{ "Grandpa's Potion Shop Key", "Grandpa's Potion Shop Key", "Grandpa's Potion Shop Key" },
Text{ "Witch's Hut Key", "Witch's Hut Key", "Witch's Hut Key" },
Text{ "Hags's Potion Shop Key", "Hags's Potion Shop Key", "Hags's Potion Shop Key" },
Text{ "Syrup's Potion Shop Key", "Syrup's Potion Shop Key", "Syrup's Potion Shop Key" },
};
trickNameTable[RG_SKULLTULA_HOUSE_KEY] = {
// TODO_TRANSLATE
Text{ "Town Spider House Key", "Town Spider House Key", "Town Spider House Key" },
Text{ "Jovani's House Key", "Jovani's House Key", "Jovani's House Key" },
Text{ "Maiamai House Key", "Maiamai House Key", "Maiamai House Key" },
};
trickNameTable[RG_IMPAS_HOUSE_KEY] = {
// TODO_TRANSLATE
Text{ "Zelda's House Key", "Zelda's House Key", "Zelda's House Key" },
Text{ "Sheik's House Key", "Sheik's House Key", "Sheik's House Key" },
Text{ "Purah's House Key", "Purah's House Key", "Purah's House Key" },
};
trickNameTable[RG_WINDMILL_KEY] = {
// TODO_TRANSLATE
Text{ "Wind Switch Key", "Wind Switch Key", "Wind Switch Key" },
Text{ "Weather Vane Key", "Weather Vane Key", "Weather Vane Key" },
};
trickNameTable[RG_KAK_SHOOTING_GALLERY_KEY] = {
// TODO_TRANSLATE
Text{ "Firing Range Key", "Firing Range Key", "Firing Range Key" },
Text{ "Crossbow Training Key", "Crossbow Training Key", "Crossbow Training Key" },
Text{ "Goron Target Range Key", "Goron Target Range Key", "Goron Target Range Key" },
};
trickNameTable[RG_DAMPES_HUT_KEY] = {
// TODO_TRANSLATE
Text{ "Dampe's Grave Key", "Dampe's Grave Key", "Dampe's Grave Key" },
Text{ "Dampe Studio Key", "Dampe Studio Key", "Dampe Studio Key" },
Text{ "Old Man's Cabin Key", "Old Man's Cabin Key", "Old Man's Cabin Key" },
};
trickNameTable[RG_TALONS_HOUSE_KEY] = {
// TODO_TRANSLATE
Text{ "Malon's House Koi", "Malon's House Koi", "Malon's House Koi" },
Text{ "Ingo's House Keese", "Ingo's House Keese", "Ingo's House Keese" },
Text{ "Mario's House Key", "Mario's House Key", "Mario's House Key" },
};
trickNameTable[RG_STABLES_KEY] = {
// TODO_TRANSLATE
Text{ "Corral Key", "Corral Key", "Corral Key" },
Text{ "Foothill Stable Key", "Foothill Stable Key", "Foothill Stable Key" },
Text{ "Goat Barn Key", "Goat Barn Key", "Goat Barn Key" },
};
trickNameTable[RG_BACK_TOWER_KEY] = {
// TODO_TRANSLATE
Text{ "Tower of Hera Key", "Tower of Hera Key", "Tower of Hera Key" },
Text{ "Clock Tower Key", "Clock Tower Key", "Clock Tower Key" },
Text{ "Tingle Tower Key", "Tingle Tower Key", "Tingle Tower Key" },
Text{ "Skyview Tower Key", "Skyview Tower Key", "Skyview Tower Key" },
Text{ "Sheikah Tower Key", "Sheikah Tower Key", "Sheikah Tower Key" },
};
trickNameTable[RG_HYLIA_LAB_KEY] = {
// TODO_TRANSLATE
Text{ "Marine Research Lab Key", "Marine Research Lab Key", "Marine Research Lab Key" },
Text{ "Hateno Tech Lab Key", "Hateno Tech Lab Key", "Hateno Tech Lab Key" },
Text{ "Tough Mango Lab Key", "Tough Mango Lab Key", "Tough Mango Lab Key" },
};
trickNameTable[RG_FISHING_HOLE_KEY] = {
// TODO_TRANSLATE
Text{ "Swamp Fishing Hole Key", "Swamp Fishing Hole Key", "Swamp Fishing Hole Key" },
Text{ "Beaver Race Key", "Beaver Race Key", "Beaver Race Key" },
Text{ "Squid-Hunt Key", "Squid-Hunt Key", "Squid-Hunt Key" },
};
/*
//Names for individual upgrades, in case progressive names are replaced
trickNameTable[GI_HOOKSHOT] = {
@@ -1159,12 +1539,16 @@ void InitTrickNames() {
}
// Generate a fake name for the ice trap based on the item it's displayed as
Text GetIceTrapName(uint8_t id) {
Text GetIceTrapName(int id) {
// If the trick names table has not been initialized, do so
if (!initTrickNames) {
InitTrickNames();
initTrickNames = true;
}
if (trickNameTable[id].empty()) {
assert(false);
return Text{ "not an Ice Trap" };
}
// Randomly get the easy, medium, or hard name for the given item id
return RandomElement(trickNameTable[id]);
}

View File

@@ -27,4 +27,4 @@ extern std::vector<RandomizerGet> GetMinVanillaShopItems(int total_replaced);
extern uint16_t GetRandomPrice(Rando::Location* loc, PriceSettingsStruct priceSettings);
extern uint16_t GetCheapBalancedPrice();
extern int GetShopsanityReplaceAmount();
extern Text GetIceTrapName(uint8_t id);
extern Text GetIceTrapName(int id);

View File

@@ -22,7 +22,6 @@ void GenerateStartingInventory() {
if (dungeon->GetMap() != RG_NONE) {
AddItemToInventory(dungeon->GetMap());
}
if (dungeon->GetCompass() != RG_NONE) {
AddItemToInventory(dungeon->GetCompass());
}
@@ -155,32 +154,6 @@ void GenerateStartingInventory() {
// AddItemToInventory(RG_SHADOW_MEDALLION, StartingShadowMedallion.Value<uint8_t>());
// AddItemToInventory(RG_LIGHT_MEDALLION, StartingLightMedallion.Value<uint8_t>());
AddItemToInventory(RG_GOLD_SKULLTULA_TOKEN, ctx->GetOption(RSK_STARTING_SKULLTULA_TOKEN).Get());
int8_t hearts = ctx->GetOption(RSK_STARTING_HEARTS).Get() - 2;
AdditionalHeartContainers = 0;
if (hearts < 0) {
AddItemToInventory(RG_PIECE_OF_HEART, 4);
// Plentiful and minimal have less than 4 standard pieces of heart so also replace the winner heart
if (ctx->GetOption(RSK_ITEM_POOL).Get() == 0 || ctx->GetOption(RSK_ITEM_POOL).Get() == 3) {
AddItemToInventory(RG_TREASURE_GAME_HEART);
}
AdditionalHeartContainers = 1 - hearts;
} else if (hearts > 0) {
// 16 containers in plentiful, 8 in balanced and 0 in the others
uint8_t maxContainers = 8 * std::max(0, 2 - ctx->GetOption(RSK_ITEM_POOL).Get());
if (hearts <= maxContainers) {
AddItemToInventory(RG_HEART_CONTAINER, hearts);
} else {
AddItemToInventory(RG_HEART_CONTAINER, maxContainers);
AddItemToInventory(RG_PIECE_OF_HEART, (hearts - maxContainers) * 4);
}
if (hearts == 17) {
AddItemToInventory(RG_TREASURE_GAME_HEART);
}
}
}
bool StartingInventoryHasBottle() {

View File

@@ -67,6 +67,14 @@ RandomizerArea Context::GetAreaFromString(std::string str) {
return (RandomizerArea)StaticData::areaNameToEnum[str];
}
int Context::CountEmptyLocations(const bool countShops) {
auto ctx = Rando::Context::GetInstance();
return count_if(allLocations.begin(), allLocations.end(), [ctx, countShops](const auto loc) {
return ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == RG_NONE &&
(countShops || Rando::StaticData::GetLocation(loc)->GetRCType() != RCTYPE_SHOP);
});
}
void Context::InitStaticData() {
StaticData::HintTable_Init();
StaticData::trialNameToEnum = StaticData::PopulateTranslationMap(StaticData::trialData);
@@ -329,7 +337,17 @@ void Context::CreateItemOverrides() {
// If this is an ice trap, store the disguise model in iceTrapModels
const auto itemLoc = GetItemLocation(locKey);
if (itemLoc->GetPlacedRandomizerGet() == RG_ICE_TRAP) {
ItemOverride val(locKey, RandomElement(possibleIceTrapModels));
RandomizerGet trickModel = RandomElementFromSet(possibleIceTrapModels);
if (trickModel == RG_EMPTY_BOTTLE) {
trickModel = RandomElement(StaticData::normalBottles);
}
if (trickModel == RG_GUARD_HOUSE_KEY) {
trickModel = RandomElement(StaticData::overworldKeys);
}
if (trickModel == RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL) {
trickModel = RandomElement(StaticData::beanSouls);
}
ItemOverride val(locKey, trickModel);
iceTrapModels[locKey] = val.LooksLike();
val.SetTrickName(GetIceTrapName(val.LooksLike()));
// If this is ice trap is in a shop, change the name based on what the model will look like

View File

@@ -12,6 +12,7 @@
#include <memory>
#include <array>
#include <map>
#include <set>
#include <nlohmann/json.hpp>
#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).Get()
@@ -125,13 +126,14 @@ class Context {
std::map<RandomizerCheck, ItemOverride> overrides = {};
std::vector<std::vector<RandomizerCheck>> playthroughLocations = {};
std::vector<RandomizerCheck> everyPossibleLocation = {};
std::vector<RandomizerGet> possibleIceTrapModels = {};
std::set<RandomizerGet> possibleIceTrapModels = {};
std::unordered_map<RandomizerCheck, RandomizerGet> iceTrapModels = {};
std::vector<OptionValue*> VanillaLogicDefaults = {};
std::array<uint8_t, 5> hashIconIndexes = {};
bool playthroughBeatable = false;
bool allLocationsReachable = false;
RandomizerArea GetAreaFromString(std::string str);
int CountEmptyLocations(bool countShops);
/**
* @brief Get the hash for the current seed.

View File

@@ -1074,7 +1074,7 @@ static std::array<std::vector<Entrance*>, 2> SplitEntrancesByRequirements(std::v
logic->Reset();
// Apply the effects of all advancement items to search for entrance accessibility
std::vector<RandomizerGet> items = FilterFromPool(
ItemPool, [](const RandomizerGet i) { return Rando::StaticData::RetrieveItem(i).IsAdvancement(); });
itemPool, [](const RandomizerGet i) { return Rando::StaticData::RetrieveItem(i).IsAdvancement(); });
for (RandomizerGet unplacedItem : items) {
Rando::StaticData::RetrieveItem(unplacedItem).ApplyEffect();
}

View File

@@ -20,6 +20,8 @@ void RegionTable_Init_Root() {
LOCATION(RC_TRIFORCE_COMPLETED, logic->GetSaveContext()->ship.quest.data.randomizer.triforcePiecesCollected >= ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_REQUIRED).Get() + 1;),
LOCATION(RC_SARIA_SONG_HINT, logic->CanUse(RG_SARIAS_SONG)),
LOCATION(RC_SONG_FROM_IMPA, (bool)ctx->GetOption(RSK_SKIP_CHILD_ZELDA)),
LOCATION(RC_HC_MALON_EGG, (bool)ctx->GetOption(RSK_SKIP_CHILD_ZELDA)),
LOCATION(RC_HC_ZELDAS_LETTER, (bool)ctx->GetOption(RSK_SKIP_CHILD_ZELDA)),
LOCATION(RC_TOT_MASTER_SWORD, (bool)ctx->GetOption(RSK_SELECTED_STARTING_AGE).Is(RO_AGE_ADULT)),
}, {
//Exits

View File

@@ -641,18 +641,18 @@ void Settings::CreateOptionDescriptions() {
"Scarce - Some excess items are removed, including health upgrades.\n"
"\n"
"Minimal - Most excess items are removed.";
mOptionDescriptions[RSK_ICE_TRAPS] = "Sets how many items are replaced by ice traps.\n"
"\n"
"Off - No ice traps.\n"
"\n"
"Normal - Only Ice Traps from the base item pool are shuffled in.\n"
"\n"
"Extra - Chance to replace added junk items with additional ice traps.\n"
"\n"
"Mayhem - All added junk items will be Ice Traps.\n"
"\n"
"Onslaught - All junk items will be replaced by Ice Traps, even those "
"in the base pool.";
mOptionDescriptions[RSK_BASE_ICE_TRAPS] =
"Sets if ice traps that exist in vanilla are shuffled into the item pool.\n"
"If this is on, 1 Trap will always be added to the pool,\n"
"an additional trap will be added if Gerudo Training Grounds\n"
"is NOT master quest,\n"
"and 4 more will be added if Ganon's Castle is NOT Master Quest.";
mOptionDescriptions[RSK_ADDITIONAL_ICE_TRAPS] =
"Sets how many more Ice Traps will be added to item pool,\n"
"assuming there is enough space after placing Progression Items.\n\n"
"You do not need to have base ice traps on for this setting to work.";
mOptionDescriptions[RSK_ICE_TRAP_PERCENT] =
"If set above 0, each Junk item has that chance of being replaced with an extra Ice Trap.";
mOptionDescriptions[RSK_GOSSIP_STONE_HINTS] =
"Allows Gossip Stones to provide hints on item locations. Hints mentioning "
"\"Way of the Hero\" indicate a location that holds an item required to beat "

View File

@@ -6453,7 +6453,9 @@ typedef enum {
RSK_SHUFFLE_BUSHES,
RSK_SHUFFLE_FROG_SONG_RUPEES,
RSK_ITEM_POOL,
RSK_ICE_TRAPS,
RSK_BASE_ICE_TRAPS,
RSK_ADDITIONAL_ICE_TRAPS,
RSK_ICE_TRAP_PERCENT,
RSK_GOSSIP_STONE_HINTS,
RSK_TOT_ALTAR_HINT,
RSK_GANONDORF_HINT,
@@ -6885,13 +6887,7 @@ typedef enum {
} RandoOptionItemPool;
// Ice Trap Settings
typedef enum {
RO_ICE_TRAPS_OFF,
RO_ICE_TRAPS_NORMAL,
RO_ICE_TRAPS_EXTRA,
RO_ICE_TRAPS_MAYHEM,
RO_ICE_TRAPS_ONSLAUGHT,
} RandoOptionIceTraps;
typedef enum { RO_ICE_TRAPS_OFF, RO_ICE_TRAPS_NORMAL, RO_ICE_TRAPS_COUNT, RO_ICE_TRAPS_PERCENT } RandoOptionIceTraps;
// Gossip Stone Hint Settings (no hints, needs nothing,
// needs mask of truth, needs stone of agony)

View File

@@ -363,6 +363,10 @@ extern "C" void Randomizer_InitSaveFile() {
if (Randomizer_GetSettingValue(RSK_SKIP_CHILD_ZELDA)) {
GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_SONG_FROM_IMPA, (GetItemID)RG_ZELDAS_LULLABY);
StartingItemGive(getItemEntry, RC_SONG_FROM_IMPA);
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_HC_MALON_EGG, (GetItemID)RG_WEIRD_EGG);
StartingItemGive(getItemEntry, RC_HC_ZELDAS_LETTER);
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_HC_ZELDAS_LETTER, (GetItemID)RG_ZELDAS_LETTER);
StartingItemGive(getItemEntry, RC_HC_MALON_EGG);
// Malon/Talon back at ranch.
Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_POCKET_EGG);

View File

@@ -1236,7 +1236,9 @@ void Settings::CreateOptions() {
OPT_BOOL(RSK_SKELETON_KEY, "Skeleton Key", CVAR_RANDOMIZER_SETTING("SkeletonKey"), mOptionDescriptions[RSK_SKELETON_KEY]);
OPT_BOOL(RSK_SLINGBOW_BREAK_BEEHIVES, "Slingshot/Bow Can Break Beehives", CVAR_RANDOMIZER_SETTING("SlingBowBeehives"), mOptionDescriptions[RSK_SLINGBOW_BREAK_BEEHIVES]);
OPT_U8(RSK_ITEM_POOL, "Item Pool", {"Plentiful", "Balanced", "Scarce", "Minimal"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ItemPool"), mOptionDescriptions[RSK_ITEM_POOL], WIDGET_CVAR_COMBOBOX, RO_ITEM_POOL_BALANCED);
OPT_U8(RSK_ICE_TRAPS, "Ice Traps", {"Off", "Normal", "Extra", "Mayhem", "Onslaught"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("IceTraps"), mOptionDescriptions[RSK_ICE_TRAPS], WIDGET_CVAR_COMBOBOX, RO_ICE_TRAPS_NORMAL);
OPT_BOOL(RSK_BASE_ICE_TRAPS, "Base Ice Traps", CVAR_RANDOMIZER_SETTING("BaseIceTraps"), mOptionDescriptions[RSK_BASE_ICE_TRAPS], IMFLAG_NONE, WIDGET_CVAR_COMBOBOX, RO_GENERIC_ON);
OPT_U8(RSK_ADDITIONAL_ICE_TRAPS, "Additional Ice Traps", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("AdditionalIceTraps"), mOptionDescriptions[RSK_ADDITIONAL_ICE_TRAPS], WIDGET_CVAR_SLIDER_INT, 0);
OPT_U8(RSK_ICE_TRAP_PERCENT, "Ice Trap Percent", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("IceTrapPercent"), mOptionDescriptions[RSK_ICE_TRAP_PERCENT], WIDGET_CVAR_SLIDER_INT, 0);
// TODO: Remove Double Defense, Progressive Goron Sword
OPT_U8(RSK_STARTING_OCARINA, "Start with Ocarina", {"Off", "Fairy Ocarina", "Ocarina of Time"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StartingOcarina"), "", WIDGET_CVAR_COMBOBOX, RO_STARTING_OCARINA_OFF);
OPT_BOOL(RSK_STARTING_DEKU_SHIELD, "Start with Deku Shield", CVAR_RANDOMIZER_SETTING("StartingDekuShield"));
@@ -2422,7 +2424,9 @@ void Settings::CreateOptions() {
WidgetContainerType::SECTION);
mOptionGroups[RSG_MENU_SECTION_TRAPS] = OptionGroup::SubGroup("Traps",
{
&mOptions[RSK_ICE_TRAPS],
&mOptions[RSK_BASE_ICE_TRAPS],
&mOptions[RSK_ADDITIONAL_ICE_TRAPS],
&mOptions[RSK_ICE_TRAP_PERCENT],
},
WidgetContainerType::SECTION);
mOptionGroups[RSG_MENU_COLUMN_HINTS_TRAPS] =
@@ -2744,8 +2748,8 @@ void Settings::CreateOptions() {
&mOptions[RSK_SKELETON_KEY],
&mOptions[RSK_SLINGBOW_BREAK_BEEHIVES],
});
mOptionGroups[RSG_ITEM_POOL] = OptionGroup(
"Item Pool Settings", std::initializer_list<Option*>({ &mOptions[RSK_ITEM_POOL], &mOptions[RSK_ICE_TRAPS] }));
mOptionGroups[RSG_ITEM_POOL] =
OptionGroup("Item Pool Settings", std::initializer_list<Option*>({ &mOptions[RSK_ITEM_POOL] }));
// TODO: Progressive Goron Sword, Remove Double Defense
mOptionGroups[RSG_EXCLUDES_KOKIRI_FOREST] =
OptionGroup::SubGroup("Kokiri Forest", mExcludeLocationsOptionsAreas[RCAREA_KOKIRI_FOREST]);

View File

@@ -317,4 +317,58 @@ std::unordered_map<u32, RandomizerHint> StaticData::grottoChestParamsToHint{
};
std::array<HintText, RHT_MAX> StaticData::hintTextTable = {};
std::vector<RandomizerGet> StaticData::normalBottles = {
RG_EMPTY_BOTTLE,
RG_BOTTLE_WITH_MILK,
RG_BOTTLE_WITH_RED_POTION,
RG_BOTTLE_WITH_GREEN_POTION,
RG_BOTTLE_WITH_BLUE_POTION,
RG_BOTTLE_WITH_FAIRY,
RG_BOTTLE_WITH_FISH,
RG_BOTTLE_WITH_BUGS,
RG_BOTTLE_WITH_POE,
RG_BOTTLE_WITH_BIG_POE,
RG_BOTTLE_WITH_BLUE_FIRE,
};
std::vector<RandomizerGet> StaticData::beanSouls = {
RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL,
RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL,
RG_DESERT_COLOSSUS_BEAN_SOUL,
RG_GERUDO_VALLEY_BEAN_SOUL,
RG_GRAVEYARD_BEAN_SOUL,
RG_KOKIRI_FOREST_BEAN_SOUL,
RG_LAKE_HYLIA_BEAN_SOUL,
RG_LOST_WOODS_BRIDGE_BEAN_SOUL,
RG_LOST_WOODS_BEAN_SOUL,
RG_ZORAS_RIVER_BEAN_SOUL,
};
std::vector<RandomizerGet> StaticData::overworldKeys = {
RG_GUARD_HOUSE_KEY,
RG_MARKET_BAZAAR_KEY,
RG_MARKET_POTION_SHOP_KEY,
RG_MASK_SHOP_KEY,
RG_MARKET_SHOOTING_GALLERY_KEY,
RG_BOMBCHU_BOWLING_KEY,
RG_TREASURE_CHEST_GAME_BUILDING_KEY,
RG_BOMBCHU_SHOP_KEY,
RG_RICHARDS_HOUSE_KEY,
RG_ALLEY_HOUSE_KEY,
RG_KAK_BAZAAR_KEY,
RG_KAK_POTION_SHOP_KEY,
RG_BOSS_HOUSE_KEY,
RG_GRANNYS_POTION_SHOP_KEY,
RG_SKULLTULA_HOUSE_KEY,
RG_IMPAS_HOUSE_KEY,
RG_WINDMILL_KEY,
RG_KAK_SHOOTING_GALLERY_KEY,
RG_DAMPES_HUT_KEY,
RG_TALONS_HOUSE_KEY,
RG_STABLES_KEY,
RG_BACK_TOWER_KEY,
RG_HYLIA_LAB_KEY,
RG_FISHING_HOLE_KEY,
};
} // namespace Rando

View File

@@ -83,6 +83,9 @@ class StaticData {
static std::unordered_map<u32, RandomizerHint> stoneParamsToHint;
static std::unordered_map<u32, RandomizerHint> grottoChestParamsToHint;
static std::array<HintText, RHT_MAX> hintTextTable;
static std::vector<RandomizerGet> normalBottles;
static std::vector<RandomizerGet> beanSouls;
static std::vector<RandomizerGet> overworldKeys;
StaticData();
~StaticData();