From 4a576f45eebbe4195162e916d8da6e342d854045 Mon Sep 17 00:00:00 2001 From: inspectredc <78732756+inspectredc@users.noreply.github.com> Date: Sat, 20 Apr 2024 15:43:35 +0100 Subject: [PATCH 1/7] Fix and Clean Up Swap Age Logic (#4061) * Split and clean up swap age logic * reorganise conditions into one statement --- soh/src/code/z_parameter.c | 278 ++++++++++++++++++++++++------------- 1 file changed, 178 insertions(+), 100 deletions(-) diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index a4d61f877..449ee2854 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -1436,64 +1436,62 @@ Gfx* Gfx_TextureI8(Gfx* displayListHead, void* texture, s16 textureWidth, s16 te return displayListHead; } -void Inventory_SwapAgeEquipment(void) { +void Rando_Inventory_SwapAgeEquipment(void) { s16 i; u16 shieldEquipValue; if (LINK_AGE_IN_YEARS == YEARS_CHILD) { - - for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { if (i != 0) { - gSaveContext.childEquips.buttonItems[i] = gSaveContext.equips.buttonItems[i]; + gSaveContext.childEquips.buttonItems[i] = + gSaveContext.equips.buttonItems[i]; } else { gSaveContext.childEquips.buttonItems[i] = ITEM_SWORD_KOKIRI; } if (i != 0) { - gSaveContext.childEquips.cButtonSlots[i - 1] = gSaveContext.equips.cButtonSlots[i - 1]; + gSaveContext.childEquips.cButtonSlots[i - 1] = + gSaveContext.equips.cButtonSlots[i - 1]; } } - // When becoming adult, remove swordless flag since we'll get master sword - // (Unless Master Sword is shuffled) - // Only in rando to keep swordless link bugs in vanilla - if (IS_RANDO && !Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD)) { - Flags_UnsetInfTable(INFTABLE_SWORDLESS); - } - gSaveContext.childEquips.equipment = gSaveContext.equips.equipment; - if (gSaveContext.adultEquips.buttonItems[0] == ITEM_NONE && !(IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD) && gSaveContext.adultEquips.equipment)) { - if (!IS_RANDO || !Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD)) { - gSaveContext.equips.buttonItems[0] = ITEM_SWORD_MASTER; - } else { - gSaveContext.equips.buttonItems[0] = ITEM_NONE; - Flags_SetInfTable(INFTABLE_SWORDLESS); - } + // When becoming adult, remove swordless flag since we'll get master sword + // This gets set back appropriately later in the case of master sword shuffle + Flags_UnsetInfTable(INFTABLE_SWORDLESS); + + // This section sets up the equipment on the first time going adult. + // On master sword shuffle the check for the B button is insufficient, and so checking the equipment is completely zero-ed is needed + // (Could just always use `gSaveContext.adultEquips.equipment == 0` for rando?) + if (gSaveContext.adultEquips.buttonItems[0] == ITEM_NONE && ((IS_RANDO && !Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD)) || (gSaveContext.adultEquips.equipment == 0))) { + gSaveContext.equips.buttonItems[0] = ITEM_SWORD_MASTER; if (gSaveContext.inventory.items[SLOT_NUT] != ITEM_NONE) { gSaveContext.equips.buttonItems[1] = ITEM_NUT; gSaveContext.equips.cButtonSlots[0] = SLOT_NUT; } else { - gSaveContext.equips.buttonItems[1] = gSaveContext.equips.cButtonSlots[0] = ITEM_NONE; + gSaveContext.equips.buttonItems[1] = gSaveContext.equips.cButtonSlots[0] = + ITEM_NONE; } gSaveContext.equips.buttonItems[2] = ITEM_BOMB; gSaveContext.equips.buttonItems[3] = gSaveContext.inventory.items[SLOT_OCARINA]; gSaveContext.equips.cButtonSlots[1] = SLOT_BOMB; gSaveContext.equips.cButtonSlots[2] = SLOT_OCARINA; - gSaveContext.equips.equipment = (EQUIP_VALUE_SWORD_MASTER << (EQUIP_TYPE_SWORD * 4)) | - (EQUIP_VALUE_SHIELD_HYLIAN << (EQUIP_TYPE_SHIELD * 4)) | - (EQUIP_VALUE_TUNIC_KOKIRI << (EQUIP_TYPE_TUNIC * 4)) | - (EQUIP_VALUE_BOOTS_KOKIRI << (EQUIP_TYPE_BOOTS * 4)); + (EQUIP_VALUE_SHIELD_HYLIAN << (EQUIP_TYPE_SHIELD * 4)) | + (EQUIP_VALUE_TUNIC_KOKIRI << (EQUIP_TYPE_TUNIC * 4)) | + (EQUIP_VALUE_BOOTS_KOKIRI << (EQUIP_TYPE_BOOTS * 4)); + // In Master Sword Shuffle we want to override the equip of the master sword from the vanilla code + // First check we have the Master sword in our inventory, and if not, then unequip if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD) && - gSaveContext.equips.buttonItems[0] == ITEM_NONE) { + !CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER)) { gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4)); + gSaveContext.equips.buttonItems[0] = ITEM_NONE; + Flags_SetInfTable(INFTABLE_SWORDLESS); } - // Set the dpad to nothing gSaveContext.equips.buttonItems[4] = ITEM_NONE; gSaveContext.equips.buttonItems[5] = ITEM_NONE; @@ -1505,25 +1503,25 @@ void Inventory_SwapAgeEquipment(void) { gSaveContext.equips.cButtonSlots[6] = SLOT_NONE; } else { for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { - gSaveContext.equips.buttonItems[i] = gSaveContext.adultEquips.buttonItems[i]; + gSaveContext.equips.buttonItems[i] = + gSaveContext.adultEquips.buttonItems[i]; if (i != 0) { - gSaveContext.equips.cButtonSlots[i - 1] = gSaveContext.adultEquips.cButtonSlots[i - 1]; + gSaveContext.equips.cButtonSlots[i - 1] = + gSaveContext.adultEquips.cButtonSlots[i - 1]; } if (((gSaveContext.equips.buttonItems[i] >= ITEM_BOTTLE) && (gSaveContext.equips.buttonItems[i] <= ITEM_POE)) || ((gSaveContext.equips.buttonItems[i] >= ITEM_WEIRD_EGG) && (gSaveContext.equips.buttonItems[i] <= ITEM_CLAIM_CHECK))) { - osSyncPrintf("Register_Item_Pt(%d)=%d\n", i, gSaveContext.equips.cButtonSlots[i - 1]); gSaveContext.equips.buttonItems[i] = gSaveContext.inventory.items[gSaveContext.equips.cButtonSlots[i - 1]]; } } - // In Rando, when switching to adult for the second+ time, if a sword was not previously - // equiped in MS shuffle, then we need to set the swordless flag again - if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD) && + // In Master Sword Shuffle we want to set the swordless flag if no item is on the B button + if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD) && gSaveContext.equips.buttonItems[0] == ITEM_NONE) { Flags_SetInfTable(INFTABLE_SWORDLESS); } @@ -1531,90 +1529,43 @@ void Inventory_SwapAgeEquipment(void) { gSaveContext.equips.equipment = gSaveContext.adultEquips.equipment; } } else { - // When becoming child, set swordless flag if player doesn't have kokiri sword - // Only in rando to keep swordless link bugs in vanilla - if (IS_RANDO && CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_KOKIRI) == 0) { - Flags_SetInfTable(INFTABLE_SWORDLESS); - } - - // When using enhancements, set swordless flag if player doesn't have kokiri sword or hasn't equipped a sword yet. - // Then set the child equips button items to item none to ensure kokiri sword is not equipped - if ((CVarGetInteger("gSwitchAge", 0) || CVarGetInteger("gSwitchTimeline", 0)) && (CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_KOKIRI) == 0 || Flags_GetInfTable(INFTABLE_SWORDLESS))) { - Flags_SetInfTable(INFTABLE_SWORDLESS); - gSaveContext.childEquips.buttonItems[0] = ITEM_NONE; - } for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { gSaveContext.adultEquips.buttonItems[i] = gSaveContext.equips.buttonItems[i]; if (i != 0) { - gSaveContext.adultEquips.cButtonSlots[i - 1] = gSaveContext.equips.cButtonSlots[i - 1]; + gSaveContext.adultEquips.cButtonSlots[i - 1] = + gSaveContext.equips.cButtonSlots[i - 1]; } } gSaveContext.adultEquips.equipment = gSaveContext.equips.equipment; - // Switching age using enhancements separated out to make vanilla flow clear - if (CVarGetInteger("gSwitchAge", 0) || CVarGetInteger("gSwitchTimeline", 0)) { + + if (gSaveContext.childEquips.buttonItems[0] != ITEM_NONE) { for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { - gSaveContext.equips.buttonItems[i] = gSaveContext.childEquips.buttonItems[i]; + gSaveContext.equips.buttonItems[i] = + gSaveContext.childEquips.buttonItems[i]; if (i != 0) { - gSaveContext.equips.cButtonSlots[i - 1] = gSaveContext.childEquips.cButtonSlots[i - 1]; + gSaveContext.equips.cButtonSlots[i - 1] = + gSaveContext.childEquips.cButtonSlots[i - 1]; } if (((gSaveContext.equips.buttonItems[i] >= ITEM_BOTTLE) && (gSaveContext.equips.buttonItems[i] <= ITEM_POE)) || ((gSaveContext.equips.buttonItems[i] >= ITEM_WEIRD_EGG) && (gSaveContext.equips.buttonItems[i] <= ITEM_CLAIM_CHECK))) { - osSyncPrintf("Register_Item_Pt(%d)=%d\n", i, gSaveContext.equips.cButtonSlots[i - 1]); gSaveContext.equips.buttonItems[i] = gSaveContext.inventory.items[gSaveContext.equips.cButtonSlots[i - 1]]; } } - gSaveContext.equips.equipment = gSaveContext.childEquips.equipment; - gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4)); - // Equips kokiri sword in the inventory screen only if kokiri sword exists in inventory and a sword has been equipped already - if (!(CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_KOKIRI) == 0) && !Flags_GetInfTable(INFTABLE_SWORDLESS)) { - gSaveContext.equips.equipment |= EQUIP_VALUE_SWORD_KOKIRI << (EQUIP_TYPE_SWORD * 4); - } - } else if (gSaveContext.childEquips.buttonItems[0] != ITEM_NONE) { - for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { - gSaveContext.equips.buttonItems[i] = gSaveContext.childEquips.buttonItems[i]; - - if (i != 0) { - gSaveContext.equips.cButtonSlots[i - 1] = gSaveContext.childEquips.cButtonSlots[i - 1]; - } - - if (((gSaveContext.equips.buttonItems[i] >= ITEM_BOTTLE) && - (gSaveContext.equips.buttonItems[i] <= ITEM_POE)) || - ((gSaveContext.equips.buttonItems[i] >= ITEM_WEIRD_EGG) && - (gSaveContext.equips.buttonItems[i] <= ITEM_CLAIM_CHECK))) { - osSyncPrintf("Register_Item_Pt(%d)=%d\n", i, gSaveContext.equips.cButtonSlots[i - 1]); - gSaveContext.equips.buttonItems[i] = - gSaveContext.inventory.items[gSaveContext.equips.cButtonSlots[i - 1]]; - } - } - - // In Rando, when switching to child from a swordless adult, and child Link previously had a - // sword equiped, then we need to unset the swordless flag to match - if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD) && - gSaveContext.equips.buttonItems[0] != ITEM_NONE) { - Flags_UnsetInfTable(INFTABLE_SWORDLESS); - } - gSaveContext.equips.equipment = gSaveContext.childEquips.equipment; gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4)); gSaveContext.equips.equipment |= EQUIP_VALUE_SWORD_KOKIRI << (EQUIP_TYPE_SWORD * 4); - } else if (IS_RANDO && Randomizer_GetSettingValue(RSK_STARTING_AGE) == RO_AGE_ADULT) { - /*If in rando and starting age is adult, childEquips is not initialized and buttonItems[0] - will be ITEM_NONE. When changing age from adult -> child, reset equips to "default" - (only kokiri tunic/boots equipped, no sword, no C-button items, no D-Pad items). - When becoming child, set swordless flag if player doesn't have kokiri sword - Only in rando to keep swordless link bugs in vanilla*/ - if (CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_KOKIRI) == 0) { - Flags_SetInfTable(INFTABLE_SWORDLESS); - } + } + // In Rando we need an extra case to handle starting as adult. We can use the fact that the childEquips will be uninitialised (i.e. 0) at this point + else if (gSaveContext.childEquips.equipment == 0) { //zero out items for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { @@ -1629,20 +1580,147 @@ void Inventory_SwapAgeEquipment(void) { (EQUIP_VALUE_BOOTS_KOKIRI << (EQUIP_TYPE_BOOTS * 4)); } - if ((CVarGetInteger("gSwitchAge", 0) || CVarGetInteger("gSwitchTimeline", 0)) && - (gSaveContext.equips.buttonItems[0] == ITEM_NONE)) { + // When becoming child in rando, set swordless flag and clear B button if player doesn't have kokiri sword + // Otherwise, equip sword and unset flag + if (!CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_KOKIRI)) { + gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4)); + gSaveContext.equips.buttonItems[0] = ITEM_NONE; Flags_SetInfTable(INFTABLE_SWORDLESS); - if (gSaveContext.childEquips.equipment == 0) { - // force equip kokiri tunic and boots in scenario gSaveContext.childEquips.equipment is uninitialized - gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4)); - gSaveContext.equips.equipment |= (EQUIP_VALUE_TUNIC_KOKIRI << (EQUIP_TYPE_TUNIC * 4)) | - (EQUIP_VALUE_BOOTS_KOKIRI << (EQUIP_TYPE_BOOTS * 4)); - } + } else { + gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4)); + gSaveContext.equips.equipment |= (EQUIP_VALUE_SWORD_KOKIRI << (EQUIP_TYPE_SWORD * 4)); + gSaveContext.equips.buttonItems[0] = ITEM_SWORD_KOKIRI; + Flags_UnsetInfTable(INFTABLE_SWORDLESS); } } - CVarSetInteger("gSwitchTimeline", 0); + shieldEquipValue = gEquipMasks[EQUIP_TYPE_SHIELD] & gSaveContext.equips.equipment; - if (shieldEquipValue != 0) { + if (shieldEquipValue) { + shieldEquipValue >>= gEquipShifts[EQUIP_TYPE_SHIELD]; + if (!CHECK_OWNED_EQUIP_ALT(EQUIP_TYPE_SHIELD, shieldEquipValue - 1)) { + gSaveContext.equips.equipment &= gEquipNegMasks[EQUIP_TYPE_SHIELD]; + } + } +} + +void Inventory_SwapAgeEquipment(void) { + s16 i; + u16 shieldEquipValue; + + // Mod Enhancments can utilise the rando flow path + if (IS_RANDO || CVarGetInteger("gSwitchAge", 0) || CVarGetInteger("gSwitchTimeline", 0)) { + Rando_Inventory_SwapAgeEquipment(); + CVarSetInteger("gSwitchTimeline", 0); + return; + } + + if (LINK_AGE_IN_YEARS == YEARS_CHILD) { + for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { + if (i != 0) { + gSaveContext.childEquips.buttonItems[i] = + gSaveContext.equips.buttonItems[i]; + } else { + gSaveContext.childEquips.buttonItems[i] = ITEM_SWORD_KOKIRI; + } + + if (i != 0) { + gSaveContext.childEquips.cButtonSlots[i - 1] = + gSaveContext.equips.cButtonSlots[i - 1]; + } + } + + gSaveContext.childEquips.equipment = gSaveContext.equips.equipment; + + if (gSaveContext.adultEquips.buttonItems[0] == ITEM_NONE) { + gSaveContext.equips.buttonItems[0] = ITEM_SWORD_MASTER; + + if (gSaveContext.inventory.items[SLOT_NUT] != ITEM_NONE) { + gSaveContext.equips.buttonItems[1] = ITEM_NUT; + gSaveContext.equips.cButtonSlots[0] = SLOT_NUT; + } else { + gSaveContext.equips.buttonItems[1] = gSaveContext.equips.cButtonSlots[0] = + ITEM_NONE; + } + + gSaveContext.equips.buttonItems[2] = ITEM_BOMB; + gSaveContext.equips.buttonItems[3] = gSaveContext.inventory.items[SLOT_OCARINA]; + gSaveContext.equips.cButtonSlots[1] = SLOT_BOMB; + gSaveContext.equips.cButtonSlots[2] = SLOT_OCARINA; + gSaveContext.equips.equipment = (EQUIP_VALUE_SWORD_MASTER << (EQUIP_TYPE_SWORD * 4)) | + (EQUIP_VALUE_SHIELD_HYLIAN << (EQUIP_TYPE_SHIELD * 4)) | + (EQUIP_VALUE_TUNIC_KOKIRI << (EQUIP_TYPE_TUNIC * 4)) | + (EQUIP_VALUE_BOOTS_KOKIRI << (EQUIP_TYPE_BOOTS * 4)); + // Set the dpad to nothing + gSaveContext.equips.buttonItems[4] = ITEM_NONE; + gSaveContext.equips.buttonItems[5] = ITEM_NONE; + gSaveContext.equips.buttonItems[6] = ITEM_NONE; + gSaveContext.equips.buttonItems[7] = ITEM_NONE; + gSaveContext.equips.cButtonSlots[3] = SLOT_NONE; + gSaveContext.equips.cButtonSlots[4] = SLOT_NONE; + gSaveContext.equips.cButtonSlots[5] = SLOT_NONE; + gSaveContext.equips.cButtonSlots[6] = SLOT_NONE; + } else { + for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { + gSaveContext.equips.buttonItems[i] = + gSaveContext.adultEquips.buttonItems[i]; + + if (i != 0) { + gSaveContext.equips.cButtonSlots[i - 1] = + gSaveContext.adultEquips.cButtonSlots[i - 1]; + } + + if (((gSaveContext.equips.buttonItems[i] >= ITEM_BOTTLE) && + (gSaveContext.equips.buttonItems[i] <= ITEM_POE)) || + ((gSaveContext.equips.buttonItems[i] >= ITEM_WEIRD_EGG) && + (gSaveContext.equips.buttonItems[i] <= ITEM_CLAIM_CHECK))) { + osSyncPrintf("Register_Item_Pt(%d)=%d\n", i, gSaveContext.equips.cButtonSlots[i - 1]); + gSaveContext.equips.buttonItems[i] = + gSaveContext.inventory.items[gSaveContext.equips.cButtonSlots[i - 1]]; + } + } + + gSaveContext.equips.equipment = gSaveContext.adultEquips.equipment; + } + } else { + for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { + gSaveContext.adultEquips.buttonItems[i] = gSaveContext.equips.buttonItems[i]; + + if (i != 0) { + gSaveContext.adultEquips.cButtonSlots[i - 1] = + gSaveContext.equips.cButtonSlots[i - 1]; + } + } + + gSaveContext.adultEquips.equipment = gSaveContext.equips.equipment; + + if (gSaveContext.childEquips.buttonItems[0] != ITEM_NONE) { + for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { + gSaveContext.equips.buttonItems[i] = + gSaveContext.childEquips.buttonItems[i]; + + if (i != 0) { + gSaveContext.equips.cButtonSlots[i - 1] = + gSaveContext.childEquips.cButtonSlots[i - 1]; + } + + if (((gSaveContext.equips.buttonItems[i] >= ITEM_BOTTLE) && + (gSaveContext.equips.buttonItems[i] <= ITEM_POE)) || + ((gSaveContext.equips.buttonItems[i] >= ITEM_WEIRD_EGG) && + (gSaveContext.equips.buttonItems[i] <= ITEM_CLAIM_CHECK))) { + osSyncPrintf("Register_Item_Pt(%d)=%d\n", i, gSaveContext.equips.cButtonSlots[i - 1]); + gSaveContext.equips.buttonItems[i] = + gSaveContext.inventory.items[gSaveContext.equips.cButtonSlots[i - 1]]; + } + } + + gSaveContext.equips.equipment = gSaveContext.childEquips.equipment; + gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4)); + gSaveContext.equips.equipment |= EQUIP_VALUE_SWORD_KOKIRI << (EQUIP_TYPE_SWORD * 4); + } + } + + shieldEquipValue = gEquipMasks[EQUIP_TYPE_SHIELD] & gSaveContext.equips.equipment; + if (shieldEquipValue) { shieldEquipValue >>= gEquipShifts[EQUIP_TYPE_SHIELD]; if (!CHECK_OWNED_EQUIP_ALT(EQUIP_TYPE_SHIELD, shieldEquipValue - 1)) { gSaveContext.equips.equipment &= gEquipNegMasks[EQUIP_TYPE_SHIELD]; From fd9cd9c5ebf611ed1c3f42c6406182c0534c8099 Mon Sep 17 00:00:00 2001 From: Archez Date: Wed, 1 May 2024 16:41:17 -0400 Subject: [PATCH 2/7] Fix: add workaround for boost versions >=1.84.0 (#4098) --- .../container_hash/detail/hash_range_32.hpp | 15 ++++++++++-- .../boost_custom/container_hash/hash_32.hpp | 24 +++++++++++++++---- .../boost_custom/container_hash/version.hpp | 2 ++ 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/soh/include/boost_custom/container_hash/detail/hash_range_32.hpp b/soh/include/boost_custom/container_hash/detail/hash_range_32.hpp index 7430152ab..cfa0a2a2d 100644 --- a/soh/include/boost_custom/container_hash/detail/hash_range_32.hpp +++ b/soh/include/boost_custom/container_hash/detail/hash_range_32.hpp @@ -46,10 +46,18 @@ template<> struct is_char_type: public boost::true_type {}; #endif // #if !BOOST_VERSION_HAS_HASH_RANGE +#if BOOST_USE_STD_TYPES +#define BOOST_ENABLE_IF std::enable_if +#define BOOST_IS_SAME std::is_same +#else +#define BOOST_ENABLE_IF boost::enable_if_ +#define BOOST_IS_SAME is_same +#endif + template -inline typename boost::enable_if_< +inline typename BOOST_ENABLE_IF< is_char_type::value_type>::value && - is_same::iterator_category, std::random_access_iterator_tag>::value, + BOOST_IS_SAME::iterator_category, std::random_access_iterator_tag>::value, std::size_t>::type hash_range_32( uint32_t seed, It first, It last ) { @@ -114,4 +122,7 @@ std::size_t>::type } // namespace hash_detail } // namespace boost +#undef BOOST_ENABLE_IF +#undef BOOST_IS_SAME + #endif // #ifndef BOOST_HASH_DETAIL_HASH_RANGE_32_HPP diff --git a/soh/include/boost_custom/container_hash/hash_32.hpp b/soh/include/boost_custom/container_hash/hash_32.hpp index 4b955c43a..eaf459a34 100644 --- a/soh/include/boost_custom/container_hash/hash_32.hpp +++ b/soh/include/boost_custom/container_hash/hash_32.hpp @@ -23,6 +23,18 @@ #endif // #if !BOOST_VERSION_HAS_HASH_RANGE +#if BOOST_USE_STD_TYPES +#define BOOST_ENABLE_IF std::enable_if +#define BOOST_IS_INTEGRAL hash_detail::is_integral +#define BOOST_IS_UNSIGNED is_unsigned +#define BOOST_MAKE_UNSIGNED make_unsigned +#else +#define BOOST_ENABLE_IF boost::enable_if_ +#define BOOST_IS_INTEGRAL boost::is_integral +#define BOOST_IS_UNSIGNED boost::is_unsigned +#define BOOST_MAKE_UNSIGNED boost::make_unsigned +#endif + namespace boost { @@ -36,7 +48,7 @@ namespace boost { template sizeof(uint32_t)), - bool is_unsigned = boost::is_unsigned::value, + bool is_unsigned = BOOST_IS_UNSIGNED::value, std::size_t size_t_bits = sizeof(uint32_t) * CHAR_BIT, std::size_t type_bits = sizeof(T) * CHAR_BIT> struct hash_integral_impl_32; @@ -53,7 +65,7 @@ namespace boost { static uint32_t fn( T v ) { - typedef typename boost::make_unsigned::type U; + typedef typename BOOST_MAKE_UNSIGNED::type U; if( v >= 0 ) { @@ -97,7 +109,7 @@ namespace boost } // namespace hash_detail template - typename boost::enable_if_::value, uint32_t>::type + typename BOOST_ENABLE_IF::value, uint32_t>::type hash_value_32( T v ) { return hash_detail::hash_integral_impl_32::fn( v ); @@ -106,7 +118,7 @@ namespace boost // contiguous ranges (string, vector, array) #if BOOST_VERSION_HAS_HASH_RANGE template - typename boost::enable_if_::value, uint32_t>::type + typename BOOST_ENABLE_IF::value, uint32_t>::type hash_value_32( T const& v ) { return boost::hash_range_32( v.data(), v.data() + v.size() ); @@ -168,5 +180,9 @@ namespace boost } // namespace boost #undef BOOST_HASH_CHAR_TRAITS +#undef BOOST_ENABLE_IF +#undef BOOST_IS_INTEGRAL +#undef BOOST_IS_UNSIGNED +#undef BOOST_MAKE_UNSIGNED #endif // #ifndef BOOST_FUNCTIONAL_HASH_HASH_32_HPP diff --git a/soh/include/boost_custom/container_hash/version.hpp b/soh/include/boost_custom/container_hash/version.hpp index 22ad6634c..3863b507c 100644 --- a/soh/include/boost_custom/container_hash/version.hpp +++ b/soh/include/boost_custom/container_hash/version.hpp @@ -6,4 +6,6 @@ #define BOOST_VERSION_HAS_HASH_RANGE ((BOOST_VERSION / 100 % 1000) >= 81) +#define BOOST_USE_STD_TYPES ((BOOST_VERSION / 100 % 1000) >= 84) + #endif // #ifndef BOOST_CONTAINER_HASH_VERSION_HPP From 27dd303a57da376847fae6d223ba6f2dfe5cd351 Mon Sep 17 00:00:00 2001 From: Eric Hoey <121978037+A-Green-Spoon@users.noreply.github.com> Date: Mon, 6 May 2024 15:10:22 -0400 Subject: [PATCH 3/7] Limit crawl speed to modifier to 4 (#4113) --- soh/soh/SohMenuBar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index b847988dc..f56c23c7f 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -572,7 +572,7 @@ void DrawEnhancementsMenu() { UIWidgets::PaddedEnhancementSliderInt("King Zora Speed: %dx", "##MWEEPSPEED", CVAR_ENHANCEMENT("MweepSpeed"), 1, 5, "", 1, true, false, true); UIWidgets::PaddedEnhancementSliderInt("Vine/Ladder Climb speed +%d", "##CLIMBSPEED", CVAR_ENHANCEMENT("ClimbSpeed"), 0, 12, "", 0, true, false, true); UIWidgets::PaddedEnhancementSliderInt("Block pushing speed +%d", "##BLOCKSPEED", CVAR_ENHANCEMENT("FasterBlockPush"), 0, 5, "", 0, true, false, true); - UIWidgets::PaddedEnhancementSliderInt("Crawl speed %dx", "##CRAWLSPEED", CVAR_ENHANCEMENT("CrawlSpeed"), 1, 5, "", 1, true, false, true); + UIWidgets::PaddedEnhancementSliderInt("Crawl speed %dx", "##CRAWLSPEED", CVAR_ENHANCEMENT("CrawlSpeed"), 1, 4, "", 1, true, false, true); UIWidgets::PaddedEnhancementCheckbox("Faster Heavy Block Lift", CVAR_ENHANCEMENT("FasterHeavyBlockLift"), false, false); UIWidgets::Tooltip("Speeds up lifting silver rocks and obelisks"); UIWidgets::PaddedEnhancementCheckbox("Skip Pickup Messages", CVAR_ENHANCEMENT("FastDrops"), true, false); From 438dede792b236c12d37d3d67c54d0765f758a1e Mon Sep 17 00:00:00 2001 From: Malkierian Date: Mon, 6 May 2024 15:10:06 -0700 Subject: [PATCH 4/7] Change "AnubixFix" back to "AnubisFix". (#4124) --- soh/soh/Enhancements/presets.h | 6 +++--- soh/soh/SohMenuBar.cpp | 2 +- .../overlays/actors/ovl_En_Anubice_Fire/z_en_anubice_fire.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h index aea4bb1fd..a502dc3da 100644 --- a/soh/soh/Enhancements/presets.h +++ b/soh/soh/Enhancements/presets.h @@ -163,7 +163,7 @@ const std::vector enhancementsCvars = { CVAR_ENHANCEMENT("GravediggingTourFix"), CVAR_ENHANCEMENT("DekuNutUpgradeFix"), CVAR_ENHANCEMENT("NaviTextFix"), - CVAR_ENHANCEMENT("AnubixFix"), + CVAR_ENHANCEMENT("AnubisFix"), CVAR_ENHANCEMENT("CrouchStabHammerFix"), CVAR_ENHANCEMENT("CrouchStabFix"), CVAR_ENHANCEMENT("GerudoWarriorClothingFix"), @@ -682,7 +682,7 @@ const std::vector enhancedPresetEntries = { PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NewDrops"), 1), // Fix Anubis fireballs - PRESET_ENTRY_S32(CVAR_ENHANCEMENT("AnubixFix"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("AnubisFix"), 1), // Autosave PRESET_ENTRY_S32(CVAR_ENHANCEMENT("Autosave"), AUTOSAVE_LOCATION_AND_MAJOR_ITEMS), @@ -808,7 +808,7 @@ const std::vector randomizerPresetEntries = { PRESET_ENTRY_S32(CVAR_ENHANCEMENT("NewDrops"), 1), // Fix Anubis fireballs - PRESET_ENTRY_S32(CVAR_ENHANCEMENT("AnubixFix"), 1), + PRESET_ENTRY_S32(CVAR_ENHANCEMENT("AnubisFix"), 1), // Autosave PRESET_ENTRY_S32(CVAR_ENHANCEMENT("Autosave"), AUTOSAVE_LOCATION_AND_MAJOR_ITEMS), diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index f56c23c7f..c396de738 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -1201,7 +1201,7 @@ void DrawEnhancementsMenu() { UIWidgets::Tooltip("Prevents the Forest Stage Deku Nut upgrade from becoming unobtainable after receiving the Poacher's Saw"); UIWidgets::PaddedEnhancementCheckbox("Fix Navi text HUD position", CVAR_ENHANCEMENT("NaviTextFix"), true, false); UIWidgets::Tooltip("Correctly centers the Navi text prompt on the HUD's C-Up button"); - UIWidgets::PaddedEnhancementCheckbox("Fix Anubis fireballs", CVAR_ENHANCEMENT("AnubixFix"), true, false); + UIWidgets::PaddedEnhancementCheckbox("Fix Anubis fireballs", CVAR_ENHANCEMENT("AnubisFix"), true, false); UIWidgets::Tooltip("Make Anubis fireballs do fire damage when reflected back at them with the Mirror Shield"); if (UIWidgets::PaddedEnhancementCheckbox("Fix Megaton Hammer crouch stab", CVAR_ENHANCEMENT("CrouchStabHammerFix"), true, false)) { if (!CVarGetInteger(CVAR_ENHANCEMENT("CrouchStabHammerFix"), 0)) { diff --git a/soh/src/overlays/actors/ovl_En_Anubice_Fire/z_en_anubice_fire.c b/soh/src/overlays/actors/ovl_En_Anubice_Fire/z_en_anubice_fire.c index 0b1a2b0b7..a26f5a08b 100644 --- a/soh/src/overlays/actors/ovl_En_Anubice_Fire/z_en_anubice_fire.c +++ b/soh/src/overlays/actors/ovl_En_Anubice_Fire/z_en_anubice_fire.c @@ -116,7 +116,7 @@ void func_809B27D8(EnAnubiceFire* this, PlayState* play) { Audio_PlayActorSound2(&this->actor, NA_SE_IT_SHIELD_REFLECT_SW); this->cylinder.base.atFlags &= 0xFFE9; this->cylinder.base.atFlags |= 8; - this->cylinder.info.toucher.dmgFlags = CVarGetInteger(CVAR_ENHANCEMENT("AnubixFix"), 0) ? 0x800 : 2; + this->cylinder.info.toucher.dmgFlags = CVarGetInteger(CVAR_ENHANCEMENT("AnubisFix"), 0) ? 0x800 : 2; this->unk_15A = 30; this->actor.params = 1; this->actor.velocity.x *= -1.0f; From f3b948226b11bca9c59715b27b404b3c1ec32c51 Mon Sep 17 00:00:00 2001 From: Lywx Date: Mon, 6 May 2024 17:19:15 -0600 Subject: [PATCH 5/7] Bump lus and fixed PatchGfx (#4125) * Bump lus and fixed PatchGfx * Bump libultraship to main --- libultraship | 2 +- soh/soh/OTRGlobals.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libultraship b/libultraship index 7d71a2906..a5d84b294 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit 7d71a290657a2d3b09a83e8b33025e807f4fb38e +Subproject commit a5d84b29429dcd9b32fb1d8b169b6dd269e6c979 diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 0a0b83d4a..b61bb65cc 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -1791,7 +1791,7 @@ extern "C" void ResourceMgr_PatchGfxCopyCommandByName(const char* path, const ch } Gfx* destinationGfx = (Gfx*)&res->Instructions[destinationIndex]; - Gfx sourceGfx = res->Instructions[sourceIndex]; + Gfx sourceGfx = *(Gfx*)&res->Instructions[sourceIndex]; if (!originalGfx.contains(path) || !originalGfx[path].contains(patchName)) { originalGfx[path][patchName] = { From b3d51441eb8759f607a9448c535c46f6a9cddecd Mon Sep 17 00:00:00 2001 From: Malkierian Date: Mon, 6 May 2024 17:17:08 -0700 Subject: [PATCH 6/7] Rando Enhancement: Mysterious Shuffled Items (#3227) * Add rando enhancement "Mysterious Shuffled Items", which obfuscates shuffled freestanding/drawn-in-world items (PoH, tokens, shop items) with a custom question mark model (thanks Hato), and uses the "mysterious item" functionality of `GetMerchantMessage` for everything that supports it, regardless of hint status on generation. * Reverted back to rando enhancement, but added condition for Mysterious Shuffle not being on for the gem rotation fix to apply. * First attempt at changing to fake GetItemEntry instead of directly calling the mystery draw function. Needs more work. * Updated CVar to reflect CVar rework values. Added `IsCheckShuffled` as preliminary function for checking *only* if a check is shuffled, not necessarily if it is just visible on the tracker. This accounts for the difference between tokensanity and "Always Show GS On Tracker", where you don't want to obfuscate the latter. * Bit of cleanup. * Cross-platform building edits. If anyone has a better idea of how to handle this fake GIE, I'm all ears. * Update to CVar macros. * Fix freestanding item gives. Fix mysterious item model colors. * Fix bombchu bowling mystery. * Remove bowling bomchus check obfuscation (unused, removed in v3). --- .../object_mystery_item/gMysteryItemDL | 16 + .../object_mystery_item/gMysteryItemDL_tri_0 | 56 +++ .../object_mystery_item/gMysteryItemDL_tri_1 | 120 +++++ .../object_mystery_item/gMysteryItemDL_vtx_0 | 119 +++++ .../object_mystery_item/gMysteryItemDL_vtx_1 | 416 ++++++++++++++++++ .../gMysteryItemDL_vtx_cull | 10 + ...yItemDL_f3dlite_mysteryItem_light_material | 21 + ...MysteryItemDL_f3dlite_mysteryItem_material | 21 + .../objects/object_mystery_item/noise_tex | Bin 0 -> 1116 bytes soh/assets/soh_assets.h | 3 + soh/include/variables.h | 3 +- .../cosmetics/CosmeticsEditor.cpp | 1 + soh/soh/Enhancements/randomizer/draw.cpp | 25 +- soh/soh/Enhancements/randomizer/draw.h | 4 + .../Enhancements/randomizer/randomizer.cpp | 20 +- soh/soh/Enhancements/randomizer/randomizer.h | 1 + .../randomizer/randomizer_check_tracker.cpp | 19 +- .../randomizer/randomizer_check_tracker.h | 1 + soh/soh/OTRGlobals.cpp | 9 + soh/soh/OTRGlobals.h | 2 + soh/soh/SohMenuBar.cpp | 5 + soh/src/code/z_en_item00.c | 28 +- .../actors/ovl_Demo_Effect/z_demo_effect.c | 3 +- .../actors/ovl_En_Ex_Item/z_en_ex_item.c | 11 +- .../overlays/actors/ovl_En_GirlA/z_en_girla.c | 7 +- soh/src/overlays/actors/ovl_En_Si/z_en_si.c | 3 +- .../actors/ovl_Item_B_Heart/z_item_b_heart.c | 4 +- .../ovl_Item_Etcetera/z_item_etcetera.c | 7 +- .../actors/ovl_Item_Ocarina/z_item_ocarina.c | 2 +- 29 files changed, 896 insertions(+), 41 deletions(-) create mode 100644 soh/assets/custom/objects/object_mystery_item/gMysteryItemDL create mode 100644 soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_tri_0 create mode 100644 soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_tri_1 create mode 100644 soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_vtx_0 create mode 100644 soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_vtx_1 create mode 100644 soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_vtx_cull create mode 100644 soh/assets/custom/objects/object_mystery_item/mat_gMysteryItemDL_f3dlite_mysteryItem_light_material create mode 100644 soh/assets/custom/objects/object_mystery_item/mat_gMysteryItemDL_f3dlite_mysteryItem_material create mode 100644 soh/assets/custom/objects/object_mystery_item/noise_tex diff --git a/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL b/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL new file mode 100644 index 000000000..939042daa --- /dev/null +++ b/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_tri_0 b/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_tri_0 new file mode 100644 index 000000000..8c320d243 --- /dev/null +++ b/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_tri_0 @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_tri_1 b/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_tri_1 new file mode 100644 index 000000000..0990859d5 --- /dev/null +++ b/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_tri_1 @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_vtx_0 b/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_vtx_0 new file mode 100644 index 000000000..37e6186e9 --- /dev/null +++ b/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_vtx_0 @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_vtx_1 b/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_vtx_1 new file mode 100644 index 000000000..4360eedc5 --- /dev/null +++ b/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_vtx_1 @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_vtx_cull b/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_vtx_cull new file mode 100644 index 000000000..cedf6351d --- /dev/null +++ b/soh/assets/custom/objects/object_mystery_item/gMysteryItemDL_vtx_cull @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_mystery_item/mat_gMysteryItemDL_f3dlite_mysteryItem_light_material b/soh/assets/custom/objects/object_mystery_item/mat_gMysteryItemDL_f3dlite_mysteryItem_light_material new file mode 100644 index 000000000..4dc39e811 --- /dev/null +++ b/soh/assets/custom/objects/object_mystery_item/mat_gMysteryItemDL_f3dlite_mysteryItem_light_material @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_mystery_item/mat_gMysteryItemDL_f3dlite_mysteryItem_material b/soh/assets/custom/objects/object_mystery_item/mat_gMysteryItemDL_f3dlite_mysteryItem_material new file mode 100644 index 000000000..6941bb55f --- /dev/null +++ b/soh/assets/custom/objects/object_mystery_item/mat_gMysteryItemDL_f3dlite_mysteryItem_material @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/soh/assets/custom/objects/object_mystery_item/noise_tex b/soh/assets/custom/objects/object_mystery_item/noise_tex new file mode 100644 index 0000000000000000000000000000000000000000..aaf4e331f15f797a3b1122b58c57b3767e66bc0f GIT binary patch literal 1116 zcma)5S&rmH5G^FcIk*X5eDlKxBf5LKx?JVw&9uYY}ZlKyY|id266pZ|L)_-3^t z{^e>VIz`u(`^dKQ%g2w`bDu%x{^r%I8%i=wg`pMy&>oT`wvAwTeqNf)RT*l1cl(+W z4O3wm5FDBuCz%Uiv0TQ&*Cj#VNy!7F8h~R}KQ9uTqZsmTyW<5x_pt+H9l4&R zNV*$EuA#8o9Vc?s{bsv;)Pm5GMBTP6z|sQ5v2V)EX1(5QHV?AIOLmqzz`$u>%G@KX zAm1U#Q1`b#-cdY`0zWyHA&UB`uvJOq1z;j%s@!gUchADQtBSnLBiuZ{ObIeINsvAl zKp>GPf~X&wGE1T`oqzfLxlOSLfeJL;gpe$uxkXczdF&C0F2DWpa%!p~b}e0&RKxLI z%T231NzwpnD1Z9&={oddS76r=ISB@l@A&(Ji`>A~6jZ+b`Tf)mbH67OcwTj)5Scc{ zK!pLxobvMFI`+$@k4zv-0AY+25fE@S6z$W{&&H?oX}(_jP*+sLjS^qu9wmr;+rj%{ zAEy-|@BH@CVH4;m%+kORMa{#BXIWla6lGO6!#wp(?ire4hv`1{96uqtA;^bi)3$9t zo$9i#W2i_9OzJvM;xx4+nwI?IFm%JTj73}=LclXD2+J}FLmcRYNZGH3zUij9O&r(N zIC{GkOwTb52m2bcW%RfiySf=qM4ckHqqfwB78L>#iUN&&l-#mE4Q;=iy9hjP)*G6p zcAUU-vK4wNFT$)pja`3!_q^mt=2&vXvP9&Xrb8$zFlv{%J+_yZm#3OgWf__(%K$o# zDT@+s;Ci{tRaQ>d>(W(+JVHPr6kC2^iS&+v`RR%Lt01bUX&g>t6B|4yh?4GjP~1K+ zRyjYNyVUUyr+Hf5EKR78{fMr0WJ>e{hl cosmeticOptions = { COSMETIC_OPTION("World.Moon", "Moon", COSMETICS_GROUP_WORLD, ImVec4(240, 255, 180, 255), false, true, true), COSMETIC_OPTION("World.GossipStone", "Gossip Stone", COSMETICS_GROUP_WORLD, ImVec4(200, 200, 200, 255), false, true, true), COSMETIC_OPTION("World.RedIce", "Red Ice", COSMETICS_GROUP_WORLD, ImVec4(255, 0, 0, 255), false, true, false), + COSMETIC_OPTION("World.MysteryItem", "Mystery Item", COSMETICS_GROUP_WORLD, ImVec4(0, 60, 100, 255), false, true, false), COSMETIC_OPTION("Navi.IdlePrimary", "Idle Primary", COSMETICS_GROUP_NAVI, ImVec4(255, 255, 255, 255), false, true, false), COSMETIC_OPTION("Navi.IdleSecondary", "Idle Secondary", COSMETICS_GROUP_NAVI, ImVec4( 0, 0, 255, 0), false, true, true), diff --git a/soh/soh/Enhancements/randomizer/draw.cpp b/soh/soh/Enhancements/randomizer/draw.cpp index 4fbe489d2..7a970b895 100644 --- a/soh/soh/Enhancements/randomizer/draw.cpp +++ b/soh/soh/Enhancements/randomizer/draw.cpp @@ -248,7 +248,7 @@ extern "C" void Randomizer_DrawTriforcePieceGI(PlayState* play, GetItemEntry get if (triforcePieceScale < 0.0001f) { triforcePieceScale += 0.00003f; } - + // Animation. When not the completed triforce, create delay before showing the piece to bypass interpolation. // If the completed triforce, make it grow slowly. if (current != required) { @@ -275,5 +275,28 @@ extern "C" void Randomizer_DrawTriforcePieceGI(PlayState* play, GetItemEntry get } else if (current == required && triforcePieceScale > 0.00008f) { gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gTriforcePieceCompletedDL); } + + CLOSE_DISPS(play->state.gfxCtx); +} + +extern "C" void Randomizer_DrawMysteryItem(PlayState* play, GetItemEntry getItemEntry) { + Color_RGB8 color = { 0, 60, 100 }; + if (CVarGetInteger(CVAR_COSMETIC("World.MysteryItem.Changed"), 0)) { + color = CVarGetColor24(CVAR_COSMETIC("World.MysteryItem.Value"), color); + } + + OPEN_DISPS(play->state.gfxCtx); + + Gfx_SetupDL_25Xlu(play->state.gfxCtx); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), G_MTX_MODELVIEW | G_MTX_LOAD); + + gDPSetGrayscaleColor(POLY_XLU_DISP++, color.r, color.g, color.b, 255); + gSPGrayscale(POLY_XLU_DISP++, true); + + gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gMysteryItemDL); + + gSPGrayscale(POLY_XLU_DISP++, false); + CLOSE_DISPS(play->state.gfxCtx); } diff --git a/soh/soh/Enhancements/randomizer/draw.h b/soh/soh/Enhancements/randomizer/draw.h index d9134573d..8c152a4f9 100644 --- a/soh/soh/Enhancements/randomizer/draw.h +++ b/soh/soh/Enhancements/randomizer/draw.h @@ -16,6 +16,10 @@ void Randomizer_DrawDoubleDefense(PlayState* play, GetItemEntry getItemEntry); void Randomizer_DrawMasterSword(PlayState* play, GetItemEntry getItemEntry); void Randomizer_DrawTriforcePiece(PlayState* play, GetItemEntry getItemEntry); void Randomizer_DrawTriforcePieceGI(PlayState* play, GetItemEntry getItemEntry); +void Randomizer_DrawMysteryItem(PlayState* play, GetItemEntry getItemEntry); + +#define GET_ITEM_MYSTERY \ + { ITEM_NONE, 0, 0, 0, 0, 0, 0, 0, 0, false, ITEM_FROM_NPC, ITEM_CATEGORY_JUNK, Randomizer_DrawMysteryItem } #ifdef __cplusplus }; #endif diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index f5c522ddc..107e23e83 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -5412,12 +5412,20 @@ CustomMessage Randomizer::GetMerchantMessage(RandomizerInf randomizerInf, u16 te RandomizerCheck rc = GetCheckFromRandomizerInf(randomizerInf); RandomizerGet shopItemGet = this->itemLocations[rc].rgID; std::array shopItemName; - if (mysterious) { - shopItemName = { - "mysterious item", - "mysteriösen Gegenstand", - "objet mystérieux" - }; + if (mysterious || CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0)) { + if (randomizerInf >= RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1 && randomizerInf <= RAND_INF_SHOP_ITEMS_MARKET_BOMBCHU_SHOP_ITEM_8) { + shopItemName = { + "Mysterious Item", + "Mysteriösen Gegenstand", + "Objet Mystérieux" + }; + } else { + shopItemName = { + "mysterious item", + "mysteriösen Gegenstand", + "objet mystérieux" + }; + } // TODO: This should eventually be replaced with a full fledged trick model & trick name system } else if (shopItemGet == RG_ICE_TRAP) { shopItemGet = this->itemLocations[rc].fakeRgID; diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index a726cecde..ce8f5c45b 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -9,6 +9,7 @@ #include #include #include "soh/Enhancements/randomizer/randomizer_check_objects.h" +#include "soh/Enhancements/randomizer/randomizer_check_tracker.h" #include "soh/Enhancements/randomizer/randomizer_tricks.h" #include #include "soh/Enhancements/item-tables/ItemTableTypes.h" diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index 4ca8c7993..a53b838f3 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -1223,7 +1223,7 @@ void LoadSettings() { } } -bool IsVisibleInCheckTracker(RandomizerCheckObject rcObj) { +bool IsCheckShuffled(RandomizerCheckObject rcObj) { if (IS_RANDO && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_LOGIC_RULES) != RO_LOGIC_VANILLA) { return (rcObj.rcArea != RCAREA_INVALID) && // don't show Invalid locations @@ -1236,7 +1236,7 @@ bool IsVisibleInCheckTracker(RandomizerCheckObject rcObj) { rcObj.vOrMQ == RCVORMQ_MQ && OTRGlobals::Instance->gRandomizer->masterQuestDungeons.contains(rcObj.sceneId) || rcObj.vOrMQ == RCVORMQ_VANILLA && !OTRGlobals::Instance->gRandomizer->masterQuestDungeons.contains(rcObj.sceneId) ) && - (rcObj.rcType != RCTYPE_SHOP || (showShops && (!hideShopRightChecks || hideShopRightChecks && rcObj.actorParams > 0x03))) && + (rcObj.rcType != RCTYPE_SHOP || (showShops && rcObj.actorParams > 0x03)) && (rcObj.rcType != RCTYPE_SCRUB || showScrubs || rcObj.rc == RC_LW_DEKU_SCRUB_NEAR_BRIDGE || // The 3 scrubs that are always randomized @@ -1245,7 +1245,7 @@ bool IsVisibleInCheckTracker(RandomizerCheckObject rcObj) { ) && (rcObj.rcType != RCTYPE_MERCHANT || showMerchants) && (rcObj.rcType != RCTYPE_OCARINA || showOcarinas) && - (rcObj.rcType != RCTYPE_SKULL_TOKEN || alwaysShowGS || + (rcObj.rcType != RCTYPE_SKULL_TOKEN || (showOverworldTokens && RandomizerCheckObjects::AreaIsOverworld(rcObj.rcArea)) || (showDungeonTokens && RandomizerCheckObjects::AreaIsDungeon(rcObj.rcArea)) ) && @@ -1265,6 +1265,7 @@ bool IsVisibleInCheckTracker(RandomizerCheckObject rcObj) { (rcObj.rcType != RCTYPE_BOSS_KEY || showBossKeysanity) && (rcObj.rcType != RCTYPE_GANON_BOSS_KEY || showGanonBossKey) && (rcObj.rc != RC_KAK_100_GOLD_SKULLTULA_REWARD || show100SkullReward) && + (rcObj.rc != RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS) && (rcObj.rcType != RCTYPE_GF_KEY && rcObj.rc != RC_GF_GERUDO_MEMBERSHIP_CARD || (showGerudoCard && rcObj.rc == RC_GF_GERUDO_MEMBERSHIP_CARD) || (fortressNormal && showGerudoFortressKeys && rcObj.rcType == RCTYPE_GF_KEY) || @@ -1280,6 +1281,10 @@ bool IsVisibleInCheckTracker(RandomizerCheckObject rcObj) { return false; } +bool IsVisibleInCheckTracker(RandomizerCheckObject rcObj) { + return IsCheckShuffled(rcObj) || (rcObj.rcType == RCTYPE_SKULL_TOKEN && alwaysShowGS) || (rcObj.rcType == RCTYPE_SHOP && (showShops && (!hideShopRightChecks))); +} + void UpdateInventoryChecks() { //For all the areas with maps, if you have one, spoil the area for (auto [scene, area] : DungeonRCAreasBySceneID) { @@ -1444,6 +1449,8 @@ void DrawLocation(RandomizerCheckObject rcObj) { //Draw the extra info txt = ""; + bool mystery = CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && OTRGlobals::Instance->gRandomizer->merchantPrices.contains(rcObj.rc); + if (checkData.hintItem != 0) { // TODO hints } else if (status != RCSHOW_UNCHECKED) { @@ -1466,16 +1473,16 @@ void DrawLocation(RandomizerCheckObject rcObj) { case RCSHOW_IDENTIFIED: case RCSHOW_SEEN: if (IS_RANDO) { - if (gSaveContext.itemLocations[rcObj.rc].get.rgID == RG_ICE_TRAP) { + if (gSaveContext.itemLocations[rcObj.rc].get.rgID == RG_ICE_TRAP && !mystery) { if (status == RCSHOW_IDENTIFIED) { txt = gSaveContext.itemLocations[rcObj.rc].get.trickName; } else { txt = OTRGlobals::Instance->gRandomizer->EnumToSpoilerfileGetName[gSaveContext.itemLocations[rcObj.rc].get.fakeRgID][gSaveContext.language]; } - } else { + } else if (!mystery) { txt = OTRGlobals::Instance->gRandomizer->EnumToSpoilerfileGetName[gSaveContext.itemLocations[rcObj.rc].get.rgID][gSaveContext.language]; } - if (status == RCSHOW_IDENTIFIED) { + if (!IsVisibleInCheckTracker(rcObj) && status == RCSHOW_IDENTIFIED && !mystery) { txt += fmt::format(" - {}", gSaveContext.checkTrackerData[rcObj.rc].price); } } else { diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.h b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.h index 216da367f..be1ae441c 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.h +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.h @@ -47,6 +47,7 @@ void DefaultCheckData(RandomizerCheck rc); void Teardown(); void UpdateAllOrdering(); bool IsVisibleInCheckTracker(RandomizerCheckObject rcObj); +bool IsCheckShuffled(RandomizerCheckObject check); void InitTrackerData(bool isDebug); RandomizerCheckArea GetCheckArea(); void UpdateCheck(uint32_t, RandomizerCheckTrackerData); diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index b61bb65cc..518e9c1f3 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -84,6 +84,7 @@ GameInteractorSail* GameInteractorSail::Instance; #include "Enhancements/mods.h" #include "Enhancements/game-interactor/GameInteractor.h" +#include "Enhancements/randomizer/draw.h" #include // Resource Types/Factories @@ -2437,6 +2438,14 @@ extern "C" ItemObtainability Randomizer_GetItemObtainabilityFromRandomizerCheck( return OTRGlobals::Instance->gRandomizer->GetItemObtainabilityFromRandomizerCheck(randomizerCheck); } +extern "C" bool Randomizer_IsCheckShuffled(RandomizerCheck randomizerCheck) { + return CheckTracker::IsCheckShuffled(RandomizerCheckObjects::GetAllRCObjects().find(randomizerCheck)->second); +} + +extern "C" GetItemEntry GetItemMystery() { + return { ITEM_NONE_FE, 0, 0, 0, 0, 0, 0, ITEM_NONE_FE, 0, false, ITEM_FROM_NPC, ITEM_CATEGORY_JUNK, NULL, MOD_RANDOMIZER, (CustomDrawFunc)Randomizer_DrawMysteryItem }; +} + CustomMessage Randomizer_GetCustomGetItemMessage(Player* player) { s16 giid; if (player->getItemEntry.objectId != OBJECT_INVALID) { diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h index 73cb58d97..e0b5c7a38 100644 --- a/soh/soh/OTRGlobals.h +++ b/soh/soh/OTRGlobals.h @@ -179,6 +179,8 @@ GetItemEntry Randomizer_GetItemFromActor(s16 actorId, s16 sceneNum, s16 actorPar GetItemEntry Randomizer_GetItemFromActorWithoutObtainabilityCheck(s16 actorId, s16 sceneNum, s16 actorParams, GetItemID ogId); GetItemEntry Randomizer_GetItemFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogId); GetItemEntry Randomizer_GetItemFromKnownCheckWithoutObtainabilityCheck(RandomizerCheck randomizerCheck, GetItemID ogId); +bool Randomizer_IsCheckShuffled(RandomizerCheck check); +GetItemEntry GetItemMystery(); ItemObtainability Randomizer_GetItemObtainabilityFromRandomizerCheck(RandomizerCheck randomizerCheck); int CustomMessage_RetrieveIfExists(PlayState* play); void Overlay_DisplayText(float duration, const char* text); diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index c396de738..35274e5ac 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -1972,6 +1972,11 @@ void DrawRandomizerMenu() { "Play unique fanfares when obtaining quest items " "(medallions/stones/songs). Note that these fanfares are longer than usual." ); + UIWidgets::PaddedEnhancementCheckbox("Mysterious Shuffled Items", CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), true, false); + UIWidgets::Tooltip( + "Displays a \"Mystery Item\" model in place of any freestanding/GS/shop items that were shuffled, " + "and replaces item names for them and scrubs and merchants, regardless of hint settings, " + "so you never know what you're getting."); ImGui::EndMenu(); } diff --git a/soh/src/code/z_en_item00.c b/soh/src/code/z_en_item00.c index db344d39e..772817716 100644 --- a/soh/src/code/z_en_item00.c +++ b/soh/src/code/z_en_item00.c @@ -1366,17 +1366,19 @@ void EnItem00_DrawCollectible(EnItem00* this, PlayState* play) { if (IS_RANDO && (this->getItemId != GI_NONE || this->actor.params == ITEM00_SMALL_KEY)) { RandomizerCheck randoCheck = Randomizer_GetCheckFromActor(this->actor.id, play->sceneNum, this->ogParams); + GetItemEntry giEntry = this->randoGiEntry; if (randoCheck != RC_UNKNOWN_CHECK) { - this->randoGiEntry = - Randomizer_GetItemFromKnownCheck(randoCheck, GI_NONE); - this->randoGiEntry.getItemFrom = ITEM_FROM_FREESTANDING; + this->randoGiEntry = Randomizer_GetItemFromKnownCheck(randoCheck, GI_NONE); + giEntry = (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(randoCheck)) + ? GetItemMystery() : this->randoGiEntry; + giEntry.getItemFrom = ITEM_FROM_FREESTANDING; } - - f32 mtxScale = 10.67f; + + f32 mtxScale = 16.0f; Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); - EnItem00_CustomItemsParticles(&this->actor, play, this->randoGiEntry); - GetItemEntry_Draw(play, this->randoGiEntry); + EnItem00_CustomItemsParticles(&this->actor, play, giEntry); + GetItemEntry_Draw(play, giEntry); } else if (this->actor.params == ITEM00_BOMBCHU) { OPEN_DISPS(play->state.gfxCtx); @@ -1460,17 +1462,19 @@ void EnItem00_DrawHeartPiece(EnItem00* this, PlayState* play) { if (IS_RANDO) { RandomizerCheck randoCheck = Randomizer_GetCheckFromActor(this->actor.id, play->sceneNum, this->ogParams); + GetItemEntry giEntry = this->randoGiEntry; if (randoCheck != RC_UNKNOWN_CHECK) { - this->randoGiEntry = - Randomizer_GetItemFromKnownCheck(randoCheck, GI_NONE); - this->randoGiEntry.getItemFrom = ITEM_FROM_FREESTANDING; + this->randoGiEntry = Randomizer_GetItemFromKnownCheck(randoCheck, GI_NONE); + giEntry = (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(randoCheck)) + ? GetItemMystery() : this->randoGiEntry; + giEntry.getItemFrom = ITEM_FROM_FREESTANDING; } f32 mtxScale = 16.0f; Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); - EnItem00_CustomItemsParticles(&this->actor, play, this->randoGiEntry); - GetItemEntry_Draw(play, this->randoGiEntry); + EnItem00_CustomItemsParticles(&this->actor, play, giEntry); + GetItemEntry_Draw(play, giEntry); } else { s32 pad; diff --git a/soh/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c b/soh/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c index 149c176c7..edab23ae8 100644 --- a/soh/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c +++ b/soh/src/overlays/actors/ovl_Demo_Effect/z_demo_effect.c @@ -2088,7 +2088,8 @@ void DemoEffect_DrawGetItem(Actor* thisx, PlayState* play) { return; } if (IS_RANDO && play->sceneNum == SCENE_JABU_JABU) { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_BARINADE, RG_ZORA_SAPPHIRE); + GetItemEntry getItemEntry = (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(RC_BARINADE)) + ? GetItemMystery() : Randomizer_GetItemFromKnownCheck(RC_BARINADE, RG_ZORA_SAPPHIRE); this->getItem.drawId = getItemEntry.gid; func_8002EBCC(thisx, play, 0); func_8002ED80(thisx, play, 0); diff --git a/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c b/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c index a3a196e31..b2d23984c 100644 --- a/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c +++ b/soh/src/overlays/actors/ovl_En_Ex_Item/z_en_ex_item.c @@ -515,14 +515,17 @@ void EnExItem_DrawItems(EnExItem* this, PlayState* play) { switch (this->type) { case EXITEM_BOMB_BAG_BOWLING: case EXITEM_BOMB_BAG_COUNTER: - randoGetItem = Randomizer_GetItemFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, GI_BOMB_BAG_20); + randoGetItem = (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE)) + ? GetItemMystery() + : Randomizer_GetItemFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, GI_BOMB_BAG_20); break; case EXITEM_BOMBCHUS_BOWLING: case EXITEM_BOMBCHUS_COUNTER: randoGetItem = Randomizer_GetItemFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS, GI_BOMBCHUS_10); break; case EXITEM_BULLET_BAG: - randoGetItem = Randomizer_GetItemFromKnownCheck(RC_LW_TARGET_IN_WOODS, GI_BULLET_BAG_50); + randoGetItem = (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(RC_LW_TARGET_IN_WOODS)) + ? GetItemMystery() : Randomizer_GetItemFromKnownCheck(RC_LW_TARGET_IN_WOODS, GI_BULLET_BAG_50); break; } @@ -540,8 +543,8 @@ void EnExItem_DrawHeartPiece(EnExItem* this, PlayState* play) { func_8002ED80(&this->actor, play, 0); if (IS_RANDO) { - GetItemEntry randoGetItem = - Randomizer_GetItemFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, GI_HEART_PIECE); + GetItemEntry randoGetItem = (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE)) + ? GetItemMystery() : Randomizer_GetItemFromKnownCheck(RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, GI_HEART_PIECE); EnItem00_CustomItemsParticles(&this->actor, play, randoGetItem); GetItemEntry_Draw(play, randoGetItem); } else { diff --git a/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c b/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c index 11c29227f..0382735a3 100644 --- a/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c +++ b/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c @@ -1286,8 +1286,8 @@ void EnGirlA_InitializeItemAction(EnGirlA* this, PlayState* play) { this->basePrice = shopItemIdentity.itemPrice; this->giDrawId = getItemEntry.gid; - // Correct the rotation for spiritual stones - if (getItemEntry.getItemId >= RG_KOKIRI_EMERALD && getItemEntry.getItemId <= RG_ZORA_SAPPHIRE) { + // Correct the rotation for spiritual stones, but only if mysterious shuffle isn't on, else it's obvious what's there in shops + if (!CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && (getItemEntry.getItemId >= RG_KOKIRI_EMERALD && getItemEntry.getItemId <= RG_ZORA_SAPPHIRE)) { this->actor.shape.rot.y = this->actor.shape.rot.y + 20000; } } @@ -1332,7 +1332,8 @@ void EnGirlA_Draw(Actor* thisx, PlayState* play) { if (this->actor.params == SI_RANDOMIZED_ITEM) { ShopItemIdentity shopItemIdentity = Randomizer_IdentifyShopItem(play->sceneNum, this->randoSlotIndex); - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheckWithoutObtainabilityCheck(shopItemIdentity.randomizerCheck, shopItemIdentity.ogItemId); + GetItemEntry getItemEntry = (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && this->actor.params == SI_RANDOMIZED_ITEM) ? GetItemMystery() : + Randomizer_GetItemFromKnownCheckWithoutObtainabilityCheck(shopItemIdentity.randomizerCheck, shopItemIdentity.ogItemId); EnItem00_CustomItemsParticles(&this->actor, play, getItemEntry); GetItemEntry_Draw(play, getItemEntry); diff --git a/soh/src/overlays/actors/ovl_En_Si/z_en_si.c b/soh/src/overlays/actors/ovl_En_Si/z_en_si.c index 185a39c51..98e8f4116 100644 --- a/soh/src/overlays/actors/ovl_En_Si/z_en_si.c +++ b/soh/src/overlays/actors/ovl_En_Si/z_en_si.c @@ -214,7 +214,8 @@ void EnSi_Draw(Actor* thisx, PlayState* play) { if (!IS_RANDO) { GetItem_Draw(play, GID_SKULL_TOKEN_2); } else { - getItem = Randomizer_GetItemFromActor(this->actor.id, play->sceneNum, this->actor.params, GI_SKULL_TOKEN); + RandomizerCheck check = Randomizer_GetCheckFromActor(this->actor.id, play->sceneNum, this->actor.params); + getItem = (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(check)) ? GetItemMystery() : Randomizer_GetItemFromKnownCheck(check, GI_SKULL_TOKEN); EnItem00_CustomItemsParticles(&this->actor, play, getItem); if (getItem.itemId != ITEM_SKULL_TOKEN) { f32 mtxScale = 1.5f; diff --git a/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c b/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c index abb65c191..bea2f608f 100644 --- a/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c +++ b/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c @@ -99,8 +99,8 @@ void ItemBHeart_Draw(Actor* thisx, PlayState* play) { } if (IS_RANDO) { - GetItemEntry_Draw(play, Randomizer_GetItemFromActor(this->actor.id, - play->sceneNum,this->actor.params, GI_HEART_CONTAINER_2)); + RandomizerCheck check = Randomizer_GetCheckFromActor(this->actor.id, play->sceneNum, this->actor.params); + GetItemEntry_Draw(play, (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(check)) ? GetItemMystery() : Randomizer_GetItemFromKnownCheck(check, GI_HEART_CONTAINER_2)); } else { if (flag) { Gfx_SetupDL_25Xlu(play->state.gfxCtx); diff --git a/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c b/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c index b12d7b4b0..fb93702ab 100644 --- a/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c +++ b/soh/src/overlays/actors/ovl_Item_Etcetera/z_item_etcetera.c @@ -230,7 +230,8 @@ void ItemEtcetera_DrawThroughLens(Actor* thisx, PlayState* play) { func_8002ED80(&this->actor, play, 0); if(IS_RANDO && play->sceneNum == SCENE_TREASURE_BOX_SHOP) { - GetItemEntry randoGetItem = GetChestGameRandoGetItem(this->actor.room, this->giDrawId, play); + RandomizerCheck check = RC_MAX; + GetItemEntry randoGetItem = GetChestGameRandoGetItem(this->actor.room, this->giDrawId, play); //TODO Rando: add mysterious shuffle when chest minigame keys get shuffled EnItem00_CustomItemsParticles(&this->actor, play, randoGetItem); if (randoGetItem.itemId != ITEM_NONE) { GetItemEntry_Draw(play, randoGetItem); @@ -249,9 +250,9 @@ void ItemEtcetera_Draw(Actor* thisx, PlayState* play) { if (IS_RANDO) { GetItemEntry randoGetItem = (GetItemEntry)GET_ITEM_NONE; if (type == ITEM_ETC_ARROW_FIRE) { - randoGetItem = Randomizer_GetItemFromKnownCheck(RC_LH_SUN, GI_ARROW_FIRE); + randoGetItem = (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(RC_LH_SUN)) ? GetItemMystery() : Randomizer_GetItemFromKnownCheck(RC_LH_SUN, GI_ARROW_FIRE); } else if (type == ITEM_ETC_LETTER) { - randoGetItem = Randomizer_GetItemFromKnownCheck(RC_LH_UNDERWATER_ITEM, GI_LETTER_RUTO); + randoGetItem = (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(RC_LH_UNDERWATER_ITEM)) ? GetItemMystery() : Randomizer_GetItemFromKnownCheck(RC_LH_UNDERWATER_ITEM, GI_LETTER_RUTO); } EnItem00_CustomItemsParticles(&this->actor, play, randoGetItem); diff --git a/soh/src/overlays/actors/ovl_Item_Ocarina/z_item_ocarina.c b/soh/src/overlays/actors/ovl_Item_Ocarina/z_item_ocarina.c index a9cd36446..c1a0d67ec 100644 --- a/soh/src/overlays/actors/ovl_Item_Ocarina/z_item_ocarina.c +++ b/soh/src/overlays/actors/ovl_Item_Ocarina/z_item_ocarina.c @@ -215,7 +215,7 @@ void ItemOcarina_Draw(Actor* thisx, PlayState* play) { func_8002ED80(thisx, play, 0); if (IS_RANDO) { - GetItemEntry randoGetItem = Randomizer_GetItemFromKnownCheck(RC_HF_OCARINA_OF_TIME_ITEM, GI_OCARINA_OOT); + GetItemEntry randoGetItem = (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0) && Randomizer_IsCheckShuffled(RC_HF_OCARINA_OF_TIME_ITEM)) ? GetItemMystery() : Randomizer_GetItemFromKnownCheck(RC_HF_OCARINA_OF_TIME_ITEM, GI_OCARINA_OOT); EnItem00_CustomItemsParticles(&this->actor, play, randoGetItem); GetItemEntry_Draw(play, randoGetItem); return; From 8d3902a256cb07b9f8e65e9ba90b3f0c20c89a45 Mon Sep 17 00:00:00 2001 From: Malkierian Date: Mon, 6 May 2024 17:27:35 -0700 Subject: [PATCH 7/7] Remove unnecessary and redundant checks and references. (#4111) Stop passing checksByArea to functions in the same namespace. Only get value of `HideFilteredAreas` once per frame. Gate area and check evaluations behind checks being visible and search filter size greater than 0. Proper function capitalization. --- .../randomizer/randomizer_check_tracker.cpp | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index a53b838f3..aca75ef93 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -133,8 +133,8 @@ RandomizerCheckArea previousArea = RCAREA_INVALID; RandomizerCheckArea currentArea = RCAREA_INVALID; OSContPad* trackerButtonsPressed; -bool passesTextFilter(ImGuiTextFilter& checkSearch, const RandomizerCheckObject rcObject); -bool shouldHideArea(ImGuiTextFilter& checkSearch, std::map> checksByArea, const RandomizerCheckArea rcArea); +bool ShouldShowCheck(RandomizerCheckObject rcObject); +bool ShouldHideArea(RandomizerCheckArea rcArea); void BeginFloatWindows(std::string UniqueName, bool& open, ImGuiWindowFlags flags = 0); bool CompareChecks(RandomizerCheckObject, RandomizerCheckObject); bool CheckByArea(RandomizerCheckArea); @@ -202,6 +202,7 @@ Color_RGBA8 Color_Saved_Extra = { 0, 185, 0, 255 }; // Green std::vector buttons = { BTN_A, BTN_B, BTN_CUP, BTN_CDOWN, BTN_CLEFT, BTN_CRIGHT, BTN_L, BTN_Z, BTN_R, BTN_START, BTN_DUP, BTN_DDOWN, BTN_DLEFT, BTN_DRIGHT }; +static ImGuiTextFilter checkSearch; void DefaultCheckData(RandomizerCheck rc) { gSaveContext.checkTrackerData[rc].status = RCSHOW_UNCHECKED; @@ -930,9 +931,9 @@ void CheckTrackerWindow::DrawElement() { optCollapseAll = true; } ImGui::SameLine(); - static ImGuiTextFilter checkSearch; if (ImGui::Button("Clear")) { checkSearch.Clear(); + doAreaScroll = true; } UIWidgets::Tooltip("Clear the search field"); checkSearch.Draw(); @@ -970,6 +971,8 @@ void CheckTrackerWindow::DrawElement() { Color_RGBA8 extraColor; std::string stemp; + bool shouldHideFilteredAreas = CVarGetInteger(CVAR_TRACKER_CHECK("HideFilteredAreas"), 1); + for (auto& [rcArea, objs] : checksByArea) { RandomizerCheckArea thisArea = currentArea; @@ -983,7 +986,7 @@ void CheckTrackerWindow::DrawElement() { previousShowHidden = showHidden; doAreaScroll = true; } - if (shouldHideArea(checkSearch, checksByArea, rcArea) || + if ((shouldHideFilteredAreas && ShouldHideArea(rcArea)) || (!showHidden && ((hideComplete && thisAreaFullyChecked) || (hideIncomplete && !thisAreaFullyChecked))) ) { doDraw = false; @@ -1046,7 +1049,8 @@ void CheckTrackerWindow::DrawElement() { } for (auto rcObject : objs) { - if (IsVisibleInCheckTracker(rcObject) && passesTextFilter(checkSearch, rcObject) && doDraw && + if (ShouldShowCheck(rcObject) && + doDraw && isThisAreaSpoiled) { DrawLocation(rcObject); } @@ -1067,14 +1071,12 @@ void CheckTrackerWindow::DrawElement() { } } -bool shouldHideArea(ImGuiTextFilter& checkSearch, std::map> checksByArea, RandomizerCheckArea rcArea) { - bool shouldHideFilteredAreas = CVarGetInteger(CVAR_TRACKER_CHECK("HideFilteredAreas"), 1); - if (!shouldHideFilteredAreas) { +bool ShouldHideArea(RandomizerCheckArea rcArea) { + if (checkSearch.Filters.Size == 0 || checkSearch.PassFilter(RandomizerCheckObjects::GetRCAreaName(rcArea).c_str())) { return false; } - for (auto check : checksByArea[rcArea]) { - if (IsVisibleInCheckTracker(check) && passesTextFilter(checkSearch, check)) { + if (ShouldShowCheck(check)) { return false; } } @@ -1082,10 +1084,12 @@ bool shouldHideArea(ImGuiTextFilter& checkSearch, std::map