Skip to content

Commit

Permalink
BossRemainsShuffle (#100)
Browse files Browse the repository at this point in the history
Implements Boss Remains Shuffle
- Adds Boss Remains Shuffle settings under Dungeon Settings
- Adjusts Item Pool to add Boss Remains to pool
- Adjusts Fill Algorithm to accomidate shuffling boss remains
- Adjusts Boss Remains entries in the Location Table as following
 - Adjusted Hint Table entries as they were incorrectly pointing to the item not the location
 - Adds categories for item placement and location selections.
 - Adjusts override type to Base and "Flag" value to be the correct GetItemID
- Adjusts Heart Container Categories as they incorrectly had the DungeonReward Category
  • Loading branch information
Tacoman369 authored Jun 18, 2024
1 parent fee5e4c commit 35f3e7a
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 94 deletions.
94 changes: 28 additions & 66 deletions source/fill.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -531,62 +531,14 @@ std::vector<ItemKey> rewards = FilterAndEraseFromPool(ItemPool, [](const ItemKey
Location(loc)->PlaceVanillaItem();
}
}
else { //Randomize dungeon rewards with assumed fill -- for now both place vanilla as random dungeon rewards is not implemented yet
else if (ShuffleRewards.Is((u8)RewardShuffleSetting::REWARDSHUFFLE_END_OF_DUNGEON)){ //Randomize dungeon rewards with assumed fill -- End of Dungeon = Vanilla
for (LocationKey loc : dungeonRewardLocations) {
Location(loc)->PlaceVanillaItem();
}
// AssumedFill(rewards, dungeonRewardLocations);
}
/*
//quest item bit mask of each stone/medallion for the savefile
static constexpr std::array<u32, 9> bitMaskTable = {
0x00040000, //Kokiri Emerald
0x00080000, //Goron Ruby
0x00100000, //Zora Sapphire
0x00000001, //Forest Medallion
0x00000002, //Fire Medallion
0x00000004, //Water Medallion
0x00000008, //Spirit Medallion
0x00000010, //Shadow Medallion
0x00000020, //Light Medallion
};
int baseOffset = ItemTable(KOKIRI_EMERALD).GetItemID();
//End of Dungeons includes Link's Pocket
if (ShuffleRewards.Is(REWARDSHUFFLE_END_OF_DUNGEON)) {
//get stones and medallions
std::vector<ItemKey> rewards = FilterAndEraseFromPool(ItemPool, [](const ItemKey i) {return ItemTable(i).GetItemType() == ITEMTYPE_DUNGEONREWARD;});
if (Settings::Logic.Is(LOGIC_VANILLA)) { //Place dungeon rewards in vanilla locations
for (LocationKey loc : dungeonRewardLocations) {
Location(loc)->PlaceVanillaItem();
}
}
else { //Randomize dungeon rewards with assumed fill
AssumedFill(rewards, dungeonRewardLocations);
else if (ShuffleRewards.Is((u8)RewardShuffleSetting::REWARDSHUFFLE_ANYWHERE)){
AssumedFill(rewards, allLocations);
}
for (size_t i = 0; i < dungeonRewardLocations.size(); i++) {
const auto index = Location(dungeonRewardLocations[i])->GetPlacedItem().GetItemID() - baseOffset;
rDungeonRewardOverrides[i] = index;
//set the player's dungeon reward on file creation instead of pushing it to them at the start.
//This is done mainly because players are already familiar with seeing their dungeon reward
//before opening up their file
if (i == dungeonRewardLocations.size() - 1) {
LinksPocketRewardBitMask = bitMaskTable[index];
}
}
}
else if (LinksPocketItem.Is(LINKSPOCKETITEM_DUNGEON_REWARD)) {
//get 1 stone/medallion
std::vector<ItemKey> rewards = FilterFromPool(ItemPool, [](const ItemKey i) {return ItemTable(i).GetItemType() == ITEMTYPE_DUNGEONREWARD;});
ItemKey startingReward = RandomElement(rewards, true);
LinksPocketRewardBitMask = bitMaskTable[ItemTable(startingReward).GetItemID() - baseOffset];
PlaceItemInLocation(LINKS_POCKET, startingReward);
//erase the stone/medallion from the Item Pool
FilterAndEraseFromPool(ItemPool, [startingReward](const ItemKey i) {return i == startingReward;});
}*/
}

//Fills any locations excluded by the player with junk items so that advancement items
Expand All @@ -610,13 +562,13 @@ static void RandomizeOwnDungeon(const Dungeon::DungeonInfo* dungeon) {
//filter out locations that may be required to have songs placed at them

dungeonLocations = FilterFromPool(dungeonLocations, [](const LocationKey loc) {
if (ShuffleSongs.Is(rnd::SongShuffleSetting::SONGSHUFFLE_SONG_LOCATIONS)) {
return !(Location(loc)->IsCategory(Category::cSong));
}
if (ShuffleSongs.Is(rnd::SongShuffleSetting::SONGSHUFFLE_DUNGEON_REWARDS)) {
return !(Location(loc)->IsCategory(Category::cDungeonReward));
}
return true;
//if (ShuffleSongs.Is(rnd::SongShuffleSetting::SONGSHUFFLE_SONG_LOCATIONS)) {
return !(Location(loc)->IsCategory(Category::cSong)) && !(Location(loc)->IsCategory(Category::cDungeonReward));
//}
//if (ShuffleSongs.Is(rnd::SongShuffleSetting::SONGSHUFFLE_DUNGEON_REWARDS)) {
// return !(Location(loc)->IsCategory(Category::cDungeonReward));
//}
// true;
});
/*
PlacementLog_Msg("\nAllowed Locations are: \n");
Expand Down Expand Up @@ -687,16 +639,26 @@ static void RandomizeDungeonItems() {
}

}
/*
if (ShuffleRewards.Is(rnd::RewardShuffleSetting::REWARDSHUFFLE_ANY_DUNGEON)) {
auto rewards = FilterAndEraseFromPool(ItemPool, [](const ItemKey i) {return ItemTable(i).GetItemType() == ITEMTYPE_DUNGEONREWARD;});
AddElementsToPool(anyDungeonItems, rewards);

const std::array<ItemKey, 4> dungeonRewards = {
ODOLWAS_REMAINS,
GOHTS_REMAINS,
GYORGS_REMAINS,
TWINMOLDS_REMAINS,
//MAJORAS_MASK,
}; for (ItemKey item : dungeonRewards) {
CitraPrint("Rewards:\n");
CitraPrint(ItemTable(item).GetName().GetEnglish() + "\n");
}
//CitraPrint("About to start attempting Reward Shuffle Any Dungeon");
if (ShuffleRewards.Is((u8)RewardShuffleSetting::REWARDSHUFFLE_ANY_DUNGEON)) {
AddElementsToPool(anyDungeonItems, dungeonRewards);
}
else if (ShuffleRewards.Is(rnd::RewardShuffleSetting::REWARDSHUFFLE_OVERWORLD)) {
auto rewards = FilterAndEraseFromPool(ItemPool, [](const ItemKey i) {return ItemTable(i).GetItemType() == ITEMTYPE_DUNGEONREWARD;});
AddElementsToPool(overworldItems, rewards);
//CitraPrint("About to start attempting Reward Shuffle Overworld");
if (ShuffleRewards.Is((u8)RewardShuffleSetting::REWARDSHUFFLE_OVERWORLD)) {
AddElementsToPool(overworldItems, dungeonRewards);
}
*/

//Randomize Any Dungeon and Overworld pools
AssumedFill(anyDungeonItems, anyDungeonLocations, true);
AssumedFill(overworldItems, overworldLocations, true);
Expand Down
16 changes: 8 additions & 8 deletions source/item_location.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -354,10 +354,10 @@ void LocationTable_Init() {
-------------------------------*/

locationTable[LINKS_POCKET] = ItemLocation::Base (0x63, 0x00, false, "Link's Pocket", LINKS_POCKET, NONE, {}, SpoilerCollectionCheck::AlwaysCollected(), SpoilerCollectionCheckGroup::GROUP_NO_GROUP );
locationTable[ODOLWA] = ItemLocation::Base (0x1F, 0x2D, false, "Woodfall Temple Odolwa's Remains", ODOLWAS_REMAINS, ODOLWAS_REMAINS, {}, SpoilerCollectionCheck::EventChkInf(0), SpoilerCollectionCheckGroup::GROUP_DUNGEON_WOODFALL_TEMPLE );
locationTable[GOHT] = ItemLocation::Base (0x44, 0x2F, false, "Snowhead Temple Goht's Remains", GOHTS_REMAINS, GOHTS_REMAINS, {}, SpoilerCollectionCheck::EventChkInf(0), SpoilerCollectionCheckGroup::GROUP_DUNGEON_SNOWHEAD_TEMPLE );
locationTable[GYORG] = ItemLocation::Base (0x5F, 0x30, false, "Great Bay Temple Gyorg's Remains", GYORGS_REMAINS, GYORGS_REMAINS, {}, SpoilerCollectionCheck::EventChkInf(0), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GREAT_BAY );
locationTable[TWINMOLD] = ItemLocation::Base (0x36, 0x31, false, "Stone Tower Temple Twinmold's Remains", TWINMOLDS_REMAINS, TWINMOLDS_REMAINS, {}, SpoilerCollectionCheck::EventChkInf(0), SpoilerCollectionCheckGroup::GROUP_DUNGEON_STONE_TOWER );
locationTable[ODOLWA] = ItemLocation::Base (0x1F, 0x55, false, "Woodfall Temple Odolwa's Remains", ODOLWA, ODOLWAS_REMAINS, {Category::cWoodfallTemple, Category::cDayOne, Category::cDungeonReward}, SpoilerCollectionCheck::EventChkInf(0), SpoilerCollectionCheckGroup::GROUP_DUNGEON_WOODFALL_TEMPLE );
locationTable[GOHT] = ItemLocation::Base (0x44, 0x56, false, "Snowhead Temple Goht's Remains", GOHT, GOHTS_REMAINS, {Category::cSnowheadTemple, Category::cDayOne, Category::cDungeonReward}, SpoilerCollectionCheck::EventChkInf(0), SpoilerCollectionCheckGroup::GROUP_DUNGEON_SNOWHEAD_TEMPLE );
locationTable[GYORG] = ItemLocation::Base (0x5F, 0x57, false, "Great Bay Temple Gyorg's Remains", GYORG, GYORGS_REMAINS, {Category::cGreatBayTemple, Category::cDayOne, Category::cDungeonReward}, SpoilerCollectionCheck::EventChkInf(0), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GREAT_BAY );
locationTable[TWINMOLD] = ItemLocation::Base (0x36, 0x58, false, "Stone Tower Temple Twinmold's Remains", TWINMOLD, TWINMOLDS_REMAINS, {Category::cStoneTowerTemple, Category::cDayOne, Category::cDungeonReward}, SpoilerCollectionCheck::EventChkInf(0), SpoilerCollectionCheckGroup::GROUP_DUNGEON_STONE_TOWER );
locationTable[MAJORA] = ItemLocation::Reward (0x0B, 0x00, false, "Majora", MAJORA, MAJORAS_MASK, {}, SpoilerCollectionCheck::None(), SpoilerCollectionCheckGroup::GROUP_DUNGEON_THE_MOON );

/*-------------------------------
Expand Down Expand Up @@ -507,10 +507,10 @@ void LocationTable_Init() {
/*-------------------------------
---HEART CONTAINERS ---
-------------------------------*/
locationTable[ODOLWA_HEART_CONTAINER] = ItemLocation::Base (0x1F, 0x0D, false, "Woodfall Temple Odolwa Heart Container", ODOLWA_HEART_CONTAINER, HEART_CONTAINER, {Category::cWoodfall, Category::cWoodfallTemple,Category::cBossHeart, Category::cDungeonReward,Category::cDayOne}, SpoilerCollectionCheck::Collectable(0x00,0x00), SpoilerCollectionCheckGroup::GROUP_DUNGEON_WOODFALL_TEMPLE );
locationTable[GOHT_HEART_CONTAINER] = ItemLocation::Base (0x44, 0x0D, false, "Snowhead Temple Goht Heart Container", GOHT_HEART_CONTAINER, HEART_CONTAINER, {Category::cSnowhead, Category::cSnowheadTemple, Category::cBossHeart, Category::cDungeonReward,Category::cDayOne}, SpoilerCollectionCheck::Collectable(0x00,0x00), SpoilerCollectionCheckGroup::GROUP_DUNGEON_SNOWHEAD_TEMPLE );
locationTable[GYORG_HEART_CONTAINER] = ItemLocation::Base (0x5F, 0x0D, false, "Great Bay Temple Gyorg Heart Container", GYORG_HEART_CONTAINER, HEART_CONTAINER, {Category::cZoraCape, Category::cGreatBayTemple, Category::cBossHeart, Category::cDungeonReward,Category::cDayOne}, SpoilerCollectionCheck::Collectable(0x00,0x00), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GREAT_BAY );
locationTable[TWINMOLD_HEART_CONTAINER] = ItemLocation::Base (0x36, 0x0D, false, "Stone Tower Temple Twinmold Heart Container", TWINMOLD_HEART_CONTAINER, HEART_CONTAINER, {Category::cStoneTower, Category::cStoneTowerTemple,Category::cBossHeart, Category::cDungeonReward,Category::cDayOne}, SpoilerCollectionCheck::Collectable(0x00,0x00), SpoilerCollectionCheckGroup::GROUP_DUNGEON_STONE_TOWER );
locationTable[ODOLWA_HEART_CONTAINER] = ItemLocation::Base (0x1F, 0x0D, false, "Woodfall Temple Odolwa Heart Container", ODOLWA_HEART_CONTAINER, HEART_CONTAINER, {Category::cWoodfall, Category::cWoodfallTemple,Category::cBossHeart, Category::cDayOne}, SpoilerCollectionCheck::Collectable(0x00,0x00), SpoilerCollectionCheckGroup::GROUP_DUNGEON_WOODFALL_TEMPLE );
locationTable[GOHT_HEART_CONTAINER] = ItemLocation::Base (0x44, 0x0D, false, "Snowhead Temple Goht Heart Container", GOHT_HEART_CONTAINER, HEART_CONTAINER, {Category::cSnowhead, Category::cSnowheadTemple, Category::cBossHeart, Category::cDayOne}, SpoilerCollectionCheck::Collectable(0x00,0x00), SpoilerCollectionCheckGroup::GROUP_DUNGEON_SNOWHEAD_TEMPLE );
locationTable[GYORG_HEART_CONTAINER] = ItemLocation::Base (0x5F, 0x0D, false, "Great Bay Temple Gyorg Heart Container", GYORG_HEART_CONTAINER, HEART_CONTAINER, {Category::cZoraCape, Category::cGreatBayTemple, Category::cBossHeart, Category::cDayOne}, SpoilerCollectionCheck::Collectable(0x00,0x00), SpoilerCollectionCheckGroup::GROUP_DUNGEON_GREAT_BAY );
locationTable[TWINMOLD_HEART_CONTAINER] = ItemLocation::Base (0x36, 0x0D, false, "Stone Tower Temple Twinmold Heart Container", TWINMOLD_HEART_CONTAINER, HEART_CONTAINER, {Category::cStoneTower, Category::cStoneTowerTemple,Category::cBossHeart, Category::cDayOne}, SpoilerCollectionCheck::Collectable(0x00,0x00), SpoilerCollectionCheckGroup::GROUP_DUNGEON_STONE_TOWER );

/*-------------------------------
--- COWS ---
Expand Down
10 changes: 5 additions & 5 deletions source/item_pool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ using namespace rnd;
std::vector<ItemKey> ItemPool = {};
std::vector<ItemKey> PendingJunkPool = {};
std::vector<u8> IceTrapModels = {};
const std::array<ItemKey, 5> dungeonRewards = {
const std::array<ItemKey, 4> dungeonRewards = {
ODOLWAS_REMAINS,
GOHTS_REMAINS,
GYORGS_REMAINS,
Expand Down Expand Up @@ -877,15 +877,15 @@ void GenerateItemPool() {
IceTrapModels.push_back(0x54);
//IceTrapModels.push_back(0x53); // should be song of time but not included yet
//IceTrapModels.push_back(0xC6);
}
}*/
if (ShuffleRewards.Is(rnd::RewardShuffleSetting::REWARDSHUFFLE_ANYWHERE)) {
//Push item ids for dungeon rewards
IceTrapModels.push_back(0x55);
IceTrapModels.push_back(0x56);
IceTrapModels.push_back(0x57);
IceTrapModels.push_back(0x58);
}
*/

//Fixed Item Locations
PlaceItemInLocation(MAJORA, MAJORAS_MASK, true);
PlaceItemInLocation(CLOCK_TOWER_OCARINA_OF_TIME, OCARINA_OF_TIME, true);
Expand Down Expand Up @@ -1236,8 +1236,8 @@ void GenerateItemPool() {
AddItemToMainPool(ST_STRAY_FAIRY, 15);
}

//TO-DO--DungeonRewards
//AddItemsToPool(ItemPool, dungeonRewards);
//DungeonRewards
AddItemsToPool(ItemPool, dungeonRewards);


// TO-DO ItemPool for extra items & Scarce and Minimal pools
Expand Down
12 changes: 4 additions & 8 deletions source/setting_descriptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,18 +203,14 @@ string_view fairyAnywhere = "**OPTION CURRENTLY WIP**\n"
/*------------------------------ //
| SHUFFLE DUNGEON REWARDS | //
------------------------------*/ //
string_view shuffleRewardsEndOfDungeon = "**OPTION CURRENTLY WIP**\n" //
"Boss Remains will be given as\n" //
string_view shuffleRewardsEndOfDungeon = "Boss Remains will be given as\n" //
"rewards for beating dungeons.\n"; //
//
string_view shuffleRewardsAnyDungeon = "**OPTION CURRENTLY WIP**\n" //
"Boss Remains can only appear inside of dungeons.\n";
string_view shuffleRewardsAnyDungeon = "Boss Remains can only appear inside of dungeons.\n";
//
string_view shuffleRewardsOverworld = "**OPTION CURRENTLY WIP**\n" //
"Boss Remains can only appear outside of dungeons.\n";
string_view shuffleRewardsOverworld = "Boss Remains can only appear outside of dungeons.\n";
//
string_view shuffleRewardsAnywhere = "**OPTION CURRENTLY WIP**\n" //
"Boss Remains can appear anywhere.\n"; //
string_view shuffleRewardsAnywhere = "Boss Remains can appear anywhere.\n"; //
//
/*------------------------------ //
| SHUFFLE MAGIC BEANS | //
Expand Down
Loading

0 comments on commit 35f3e7a

Please sign in to comment.