diff --git a/data/uking_functions.csv b/data/uking_functions.csv index d7677c2d..b69d411c 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -56283,7 +56283,7 @@ 0x0000007100969f50,sub_7100969F50,204, 0x000000710096a01c,sub_710096A01C,92, 0x000000710096a078,sub_710096A078,204, -0x000000710096a144,sub_710096A144,92,w +0x000000710096a144,sub_710096A144,92, 0x000000710096a1a0,sub_710096A1A0,204, 0x000000710096a26c,sub_710096A26C,92, 0x000000710096a2c8,sub_710096A2C8,204, @@ -56320,7 +56320,7 @@ 0x000000710096b9c4,nullsub_2781,4,_ZN5uking2ui9PouchItemD2Ev 0x000000710096b9c8,sub_710096B9C8,52,_ZN5uking2ui16PauseMenuDataMgrD0Ev 0x000000710096b9fc,nullsub_2782,4,_ZN5uking2ui16PauseMenuDataMgr4initEPN4sead4HeapE -0x000000710096ba00,PauseMenuDataMgr::initForNewSave,1060, +0x000000710096ba00,PauseMenuDataMgr::initForNewSave,1060,_ZN5uking2ui16PauseMenuDataMgr14initForNewSaveEv 0x000000710096be24,PauseMenuDataMgr::loadFromGameData,492, 0x000000710096c010,PauseMenuDataMgr::loadFromGameData_,2372, 0x000000710096c954,PauseMenuDataMgr::updateInventoryCategories,3544, @@ -56343,7 +56343,7 @@ 0x0000007100970f84,PauseMenuDataMgr::getItemNum,1204, 0x0000007100971438,PauseMenuDataMgr::setPorchValue1,204,_ZN5uking2ui16PauseMenuDataMgr18setWeaponItemValueEiNS0_13PouchItemTypeE 0x0000007100971504,PauseMenuDataMgr::fromSaveDataMaybe,716, -0x00000071009717d0,sub_71009717D0,40,_ZNK5uking2ui16PauseMenuDataMgr19getDefaultEquipmentEj +0x00000071009717d0,sub_71009717D0,40,_ZNK5uking2ui16PauseMenuDataMgr19getDefaultEquipmentENS0_13EquipmentSlotE 0x00000071009717f8,PauseMenuDataMgr::hasItemMaybe,404,_ZNK5uking2ui16PauseMenuDataMgr7hasItemERKN4sead14SafeStringBaseIcEE 0x000000710097198c,sub_710097198C,372,_ZNK5uking2ui16PauseMenuDataMgr14getMasterSwordEv 0x0000007100971b00,PauseMenuDataMgr::__auto7,620, @@ -56375,18 +56375,18 @@ 0x0000007100976cc4,PauseMenuDataMgr::useMaybe,1124, 0x0000007100977128,sub_7100977128,868, 0x000000710097748c,sub_710097748C,628, -0x0000007100977700,sub_7100977700,248, +0x0000007100977700,sub_7100977700,248,_ZN5uking2ui22pouchItemSortPredicateEPKNS0_9PouchItemES3_ 0x00000071009777f8,sub_71009777F8,272, 0x0000007100977908,sub_7100977908,288, 0x0000007100977a28,sub_7100977A28,272, -0x0000007100977b38,sub_7100977B38,336, +0x0000007100977b38,sub_7100977B38,336,_ZN5uking2ui9sortArmorEPKNS0_9PouchItemES3_PN4ksys3act8InfoDataE 0x0000007100977c88,sub_7100977C88,308, 0x0000007100977dbc,sub_7100977DBC,540, -0x0000007100977fd8,sub_7100977FD8,116, +0x0000007100977fd8,sub_7100977FD8,116,_ZN5uking2ui11sortKeyItemEPKNS0_9PouchItemES3_PN4ksys3act8InfoDataE 0x000000710097804c,sub_710097804C,676, 0x00000071009782f0,sub_71009782F0,664, -0x0000007100978588,sub_7100978588,480, -0x0000007100978768,sub_7100978768,304, +0x0000007100978588,sub_7100978588,480,_ZN5uking2ui16getCookItemOrderEPKNS0_9PouchItemEPN4ksys3act8InfoDataE +0x0000007100978768,sub_7100978768,304,_ZN5uking2ui30pouchItemSortPredicateForArrowEPKNS0_9PouchItemES3_ 0x0000007100978898,sub_7100978898,440, 0x0000007100978a50,sub_7100978A50,488, 0x0000007100978c38,sub_7100978C38,488, @@ -56412,11 +56412,11 @@ 0x000000710097adfc,PauseMenuDataMgr::__auto14,596, 0x000000710097b050,sub_710097B050,868, 0x000000710097b3b4,sub_710097B3B4,1872, -0x000000710097bb04,PauseMenuDataMgr::hasItemMaybe_0,1364, -0x000000710097c058,sub_710097C058,60, -0x000000710097c094,sub_710097C094,60, -0x000000710097c0d0,sub_710097C0D0,60, -0x000000710097c10c,sub_710097C10C,60, +0x000000710097bb04,PauseMenuDataMgr::hasItemMaybe_0,1364,_ZNK5uking2ui16PauseMenuDataMgr17isHeroSoulEnabledERKN4sead14SafeStringBaseIcEE +0x000000710097c058,sub_710097C058,60,_ZNK5uking2ui16PauseMenuDataMgr15hasRitoSoulPlusEv +0x000000710097c094,sub_710097C094,60,_ZNK5uking2ui16PauseMenuDataMgr16hasGoronSoulPlusEv +0x000000710097c0d0,sub_710097C0D0,60,_ZNK5uking2ui16PauseMenuDataMgr17hasGerudoSoulPlusEv +0x000000710097c10c,sub_710097C10C,60,_ZNK5uking2ui16PauseMenuDataMgr15hasZoraSoulPlusEv 0x000000710097c148,sub_710097C148,140, 0x000000710097c1d4,sub_710097C1D4,1500, 0x000000710097c7b0,sub_710097C7B0,700, @@ -56429,12 +56429,12 @@ 0x000000710097d79c,PauseMenuDataMgr::dyeGoodsStuff,640, 0x000000710097da1c,PauseMenuDataMgr::__auto15,76, 0x000000710097da68,sub_710097DA68,188, -0x000000710097db58,sub_710097DB58,60, +0x000000710097db58,sub_710097DB58,0xbc,_ZNK5uking2ui16PauseMenuDataMgr19isOverCategoryLimitENS0_13PouchItemTypeE 0x000000710097db9c,sub_710097DB9C,8, 0x000000710097dc08,sub_710097DC08,12, 0x000000710097dc14,sub_710097DC14,912, 0x000000710097dfa4,sub_710097DFA4,240, -0x000000710097e094,PauseMenuDataMgr::openItemCategoryIfNeeded,204, +0x000000710097e094,PauseMenuDataMgr::openItemCategoryIfNeeded,204,_ZNK5uking2ui16PauseMenuDataMgr24openItemCategoryIfNeededEv 0x000000710097e160,PauseMenuDataMgr::giveDefaultSetItems,1804, 0x000000710097e86c,PauseMenuDataMgr::increasePouchNumNonCat9,6284, 0x00000071009800f8,sub_71009800F8,612, diff --git a/src/Game/UI/uiPauseMenuDataMgr.cpp b/src/Game/UI/uiPauseMenuDataMgr.cpp index e2d4e9dd..03006e8c 100644 --- a/src/Game/UI/uiPauseMenuDataMgr.cpp +++ b/src/Game/UI/uiPauseMenuDataMgr.cpp @@ -2,9 +2,12 @@ #include #include #include +#include "Game/DLC/aocManager.h" #include "Game/UI/uiUtils.h" +#include "KingSystem/ActorSystem/Profiles/actPlayerBase.h" #include "KingSystem/ActorSystem/actActorUtil.h" #include "KingSystem/ActorSystem/actInfoData.h" +#include "KingSystem/ActorSystem/actPlayerInfo.h" #include "KingSystem/GameData/gdtCommonFlagsUtils.h" #include "KingSystem/Utils/Byaml/Byaml.h" #include "KingSystem/Utils/InitTimeInfo.h" @@ -17,7 +20,7 @@ sead::Vector2f sDummyCookEffect0{-1, 0}; namespace { -sead::SafeArray sCookTagInfo_{{ +sead::SafeArray sCookItemOrder_{{ {1, "CookFruit", ksys::act::tags::CookFruit}, {1, "CookMushroom", ksys::act::tags::CookMushroom}, {1, "CookPlant", ksys::act::tags::CookPlant}, @@ -86,7 +89,8 @@ struct PouchConstants { sead::SafeString Armor_150_Upper = "Armor_150_Upper"; sead::SafeString Armor_151_Upper = "Armor_151_Upper"; - sead::Buffer cook_tag_info{sCookTagInfo_.size(), sCookTagInfo_.getBufferPtr()}; + sead::Buffer cook_item_order{sCookItemOrder_.size(), + sCookItemOrder_.getBufferPtr()}; sead::SafeArray default_equipment_names{{ "Weapon_Default_Right", @@ -128,7 +132,7 @@ PauseMenuDataMgr::PauseMenuDataMgr() { mListHeads.fill(nullptr); for (s32 i = 0; i < NumPouch50; ++i) { mArray1[i] = nullptr; - mArray2[i] = -1; + mArray2[i] = PouchItemType::Invalid; } for (auto& x : mArray3) x = {}; @@ -146,8 +150,72 @@ PouchItem::PouchItem() { mIngredients.emplaceBack(); } +void PauseMenuDataMgr::resetItem() { + mItem.mType = PouchItemType::Invalid; + mItem._1c = -1; + mItem.mValue = 0; + mItem.mValid = false; + mItem._25 = 0; + mItem.mName.clear(); + mItem.mData.cook = {}; + mItem.mData.cook.mCookEffect0 = sDummyCookEffect0; +} + void PauseMenuDataMgr::init(sead::Heap* heap) {} +void PauseMenuDataMgr::initForNewSave() { + const auto lock = sead::makeScopedLock(mCritSection); + + for (auto* item = getItems().popFront(); item; item = getItems().popFront()) { + item->~PouchItem(); + new (item) PouchItem; + mItemLists.list2.pushFront(item); + } + + mListHeads.fill(nullptr); + for (s32 i = 0; i < NumPouch50; ++i) { + mArray1[i] = nullptr; + mArray2[i] = PouchItemType::Invalid; + } + + _44498 = {}; + ksys::gdt::setFlag_KorokNutsNum(0); + ksys::gdt::setFlag_DungeonClearSealNum(0); + ksys::gdt::setFlag_FairyCountCheck(0); + _444fc = {}; + mItem_44488 = {}; + mItem_444f0 = {}; + _444f8 = -1; + resetItem(); + mIsPouchForQuest = false; + for (auto& x : mArray3) + x = {}; + _44504 = {}; + _44508 = {}; + _4450c = {}; + _44510 = {}; + _44514 = {}; + mRitoSoulItem = {}; + mGoronSoulItem = {}; + mZoraSoulItem = {}; + mGerudoSoulItem = {}; + _44538 = false; + _447e0 = {}; + _447e8 = {}; + _447f0 = {}; + _447f8 = {}; + + auto* player = ksys::act::PlayerInfo::instance()->getPlayer(); + if (player) { + player->switchEquipment(getDefaultEquipment(EquipmentSlot::WeaponRight), 1); + player->switchEquipment(getDefaultEquipment(EquipmentSlot::WeaponLeft), 1); + player->switchEquipment(getDefaultEquipment(EquipmentSlot::WeaponBow), 1); + player->switchEquipment(getDefaultEquipment(EquipmentSlot::ArmorHead), 30); + player->switchEquipment(getDefaultEquipment(EquipmentSlot::ArmorUpper), 30); + player->switchEquipment(getDefaultEquipment(EquipmentSlot::ArmorLower), 30); + } +} + PouchItemType PauseMenuDataMgr::getType(const sead::SafeString& item, al::ByamlIter* iter) { sead::SafeString group; if (iter) { @@ -290,9 +358,11 @@ void PauseMenuDataMgr::setWeaponItemValue(s32 value, PouchItemType type) { } } -const sead::SafeString& PauseMenuDataMgr::getDefaultEquipment(u32 idx) const { - if (idx != 2 && idx < u32(sValues.default_equipment_names.size())) - return sValues.default_equipment_names(idx); +const sead::SafeString& PauseMenuDataMgr::getDefaultEquipment(EquipmentSlot idx) const { + if (idx != EquipmentSlot::WeaponArrow && + u32(idx) < u32(sValues.default_equipment_names.size())) { + return sValues.default_equipment_names(u32(idx)); + } return sead::SafeString::cEmptyString; } @@ -391,6 +461,194 @@ void PauseMenuDataMgr::restoreMasterSword(bool only_if_broken) { } } +using SortPredicate = int (*)(const PouchItem* lhs, const PouchItem* rhs, + ksys::act::InfoData* data); + +static sead::SafeArray sSortPredicates{ + {sortWeapon, sortBow, sortShield, sortArmor, sortMaterial, sortFood, sortKeyItem}}; + +static PouchCategory getTypeForCategory(PouchItemType type) { + static constexpr sead::SafeArray sMap{{ + PouchCategory::Weapon, // Weapon + PouchCategory::Bow, // Bow + PouchCategory::Bow, // Arrow + PouchCategory::Shield, // Shield + PouchCategory::Armor, // ArmorHead + PouchCategory::Armor, // ArmorUpper + PouchCategory::Armor, // ArmorLower + PouchCategory::Material, // Material + PouchCategory::Food, // Food + PouchCategory::KeyItem, // KeyItem + }}; + return sMap[s32(type)]; +} + +int pouchItemSortPredicate(const PouchItem* lhs, const PouchItem* rhs) { + if (!lhs || !rhs) + return 0; + + auto* info_data = ksys::act::InfoData::instance(); + if (!info_data || !lhs->get25() || !rhs->get25()) + return 0; + + const auto cat1 = getTypeForCategory(lhs->getType()); + const auto cat2 = getTypeForCategory(rhs->getType()); + if (cat1 != cat2) + return 0; + + const auto cat3 = PauseMenuDataMgr::instance()->get44800(); + if (cat3 != PouchCategory::Invalid && cat1 != cat3) + return 0; + + decltype(sSortPredicates) predicate_table{}; + sead::MemUtil::copy(&predicate_table, &sSortPredicates, sizeof(predicate_table)); + const auto* fn = &predicate_table[0]; + if (u32(cat1) < u32(predicate_table.size())) + fn = &predicate_table(u32(cat1)); + return (*fn)(lhs, rhs, info_data); +} + +static s32 compareSortKeys(const PouchItem* lhs, const PouchItem* rhs, ksys::act::InfoData* data) { + const auto a = data->getSortKey(lhs->getName().cstr()); + const auto b = data->getSortKey(rhs->getName().cstr()); + if (a < b) + return -1; + if (a > b) + return 1; + return 0; +} + +int sortArmor(const PouchItem* lhs, const PouchItem* rhs, ksys::act::InfoData* data) { + if (ksys::gdt::getFlag_SortTypeArmorPouch()) { + if (auto cmp = compareSortKeys(lhs, rhs, data)) + return cmp; + + if (lhs->getType() < rhs->getType()) + return -1; + if (lhs->getType() > rhs->getType()) + return 1; + } else { + if (lhs->getType() < rhs->getType()) + return -1; + if (lhs->getType() > rhs->getType()) + return 1; + + if (auto cmp = compareSortKeys(lhs, rhs, data)) + return cmp; + } + + if (lhs->getCount() < rhs->getCount()) + return -1; + if (lhs->getCount() > rhs->getCount()) + return 1; + + return 0; +} + +int sortKeyItem(const PouchItem* lhs, const PouchItem* rhs, ksys::act::InfoData* data) { + if (auto cmp = compareSortKeys(lhs, rhs, data)) + return cmp; + return 0; +} + +int getCookItemOrder(const PouchItem* item, ksys::act::InfoData* data) { + const auto& order = sValues.cook_item_order; + al::ByamlIter iter; + if (data->getActorIter(&iter, item->getName().cstr())) { + for (auto it = order.begin(), end = order.end(); it != end; ++it) { + if (it->is_tag == 0 && item->getName() == it->name.cstr()) + return it.getIndex(); + } + + for (auto it = order.begin(), end = order.end(); it != end; ++it) { + if (it->is_tag == 1 && data->hasTag(iter, it->hash)) + return it.getIndex(); + } + } + return order.size(); +} + +int pouchItemSortPredicateForArrow(const PouchItem* lhs, const PouchItem* rhs) { + if (!lhs || !rhs) + return 0; + + static constexpr sead::SafeArray sMap{{0, 1, 2, 3, 4, 4, 4, 7, 8, 9}}; + const auto x1 = sMap[s32(lhs->getType())]; + const auto x2 = sMap[s32(rhs->getType())]; + if (x1 < x2) + return -1; + if (x1 > x2) + return 1; + + if (lhs->getType() != PouchItemType::Arrow) + return 0; + + auto* info_data = ksys::act::InfoData::instance(); + if (!info_data || !lhs->get25() || !rhs->get25()) + return 0; + + const auto cat1 = getTypeForCategory(lhs->getType()); + const auto cat2 = getTypeForCategory(rhs->getType()); + if (cat1 != cat2) + return 0; + + const auto cat3 = PauseMenuDataMgr::instance()->get44800(); + if (cat3 != PouchCategory::Invalid && cat1 != cat3) + return 0; + + decltype(sSortPredicates) predicate_table{}; + sead::MemUtil::copy(&predicate_table, &sSortPredicates, sizeof(predicate_table)); + const auto* fn = &predicate_table[0]; + if (u32(cat1) < u32(predicate_table.size())) + fn = &predicate_table(u32(cat1)); + return (*fn)(lhs, rhs, info_data); +} + +bool PauseMenuDataMgr::isHeroSoulEnabled(const sead::SafeString& name) const { + if (name == sValues.Obj_HeroSoul_Zora || name == sValues.Obj_DLC_HeroSoul_Zora) { + if (mZoraSoulItem) + return mZoraSoulItem->isValid(); + } + + if (name == sValues.Obj_HeroSoul_Rito || name == sValues.Obj_DLC_HeroSoul_Rito) { + if (mRitoSoulItem) + return mRitoSoulItem->isValid(); + } + + if (name == sValues.Obj_HeroSoul_Goron || name == sValues.Obj_DLC_HeroSoul_Goron) { + if (mGoronSoulItem) + return mGoronSoulItem->isValid(); + } + + if (name == sValues.Obj_HeroSoul_Gerudo || name == sValues.Obj_DLC_HeroSoul_Gerudo) { + if (mGerudoSoulItem) + return mGerudoSoulItem->isValid(); + } + + return false; +} + +// NOLINTNEXTLINE(readability-convert-member-functions-to-static) +bool PauseMenuDataMgr::hasRitoSoulPlus() const { + return ksys::gdt::getFlag_IsGet_Obj_DLC_HeroSoul_Rito() && aoc::Manager::instance()->hasAoc3(); +} + +// NOLINTNEXTLINE(readability-convert-member-functions-to-static) +bool PauseMenuDataMgr::hasGoronSoulPlus() const { + return ksys::gdt::getFlag_IsGet_Obj_DLC_HeroSoul_Goron() && aoc::Manager::instance()->hasAoc3(); +} + +// NOLINTNEXTLINE(readability-convert-member-functions-to-static) +bool PauseMenuDataMgr::hasGerudoSoulPlus() const { + return ksys::gdt::getFlag_IsGet_Obj_DLC_HeroSoul_Gerudo() && + aoc::Manager::instance()->hasAoc3(); +} + +// NOLINTNEXTLINE(readability-convert-member-functions-to-static) +bool PauseMenuDataMgr::hasZoraSoulPlus() const { + return ksys::gdt::getFlag_IsGet_Obj_DLC_HeroSoul_Zora() && aoc::Manager::instance()->hasAoc3(); +} + // NOLINTNEXTLINE(readability-convert-member-functions-to-static) void PauseMenuDataMgr::updateDivineBeastClearFlags(int num_cleared_beasts) { switch (num_cleared_beasts) { @@ -420,4 +678,63 @@ void PauseMenuDataMgr::updateDivineBeastClearFlags(int num_cleared_beasts) { } } +bool PauseMenuDataMgr::isOverCategoryLimit(PouchItemType type) const { + const auto count = countItemsWithType(type); + switch (type) { + case PouchItemType::Weapon: + return ksys::gdt::getFlag_WeaponPorchStockNum() <= count || count >= 20; + case PouchItemType::Bow: + return ksys::gdt::getFlag_BowPorchStockNum() <= count || count >= 14; + case PouchItemType::Arrow: + return count >= 6; + case PouchItemType::Shield: + return ksys::gdt::getFlag_ShieldPorchStockNum() <= count || count >= 20; + case PouchItemType::ArmorHead: + case PouchItemType::ArmorUpper: + case PouchItemType::ArmorLower: + return count >= 100; + case PouchItemType::Material: + return count >= 160; + case PouchItemType::Food: + return count >= 60; + case PouchItemType::KeyItem: + return count >= 40; + case PouchItemType::Invalid: + break; + } + return true; +} + +void PauseMenuDataMgr::openItemCategoryIfNeeded() const { + for (s32 i = 0; i < NumPouch50; ++i) { + const auto type = mArray2[i]; + if (isPouchItemArmor(type)) { + ksys::gdt::setFlag_IsOpenItemCategory(true, u32(PouchCategory::Armor)); + } else { + switch (type) { + case PouchItemType::Weapon: + ksys::gdt::setFlag_IsOpenItemCategory(true, u32(PouchCategory::Weapon)); + break; + case PouchItemType::Bow: + ksys::gdt::setFlag_IsOpenItemCategory(true, u32(PouchCategory::Bow)); + break; + case PouchItemType::Shield: + ksys::gdt::setFlag_IsOpenItemCategory(true, u32(PouchCategory::Shield)); + break; + case PouchItemType::Material: + ksys::gdt::setFlag_IsOpenItemCategory(true, u32(PouchCategory::Material)); + break; + case PouchItemType::Food: + ksys::gdt::setFlag_IsOpenItemCategory(true, u32(PouchCategory::Food)); + break; + case PouchItemType::KeyItem: + ksys::gdt::setFlag_IsOpenItemCategory(true, u32(PouchCategory::KeyItem)); + break; + default: + break; + } + } + } +} + } // namespace uking::ui diff --git a/src/Game/UI/uiPauseMenuDataMgr.h b/src/Game/UI/uiPauseMenuDataMgr.h index de49cf89..23b4fbb1 100644 --- a/src/Game/UI/uiPauseMenuDataMgr.h +++ b/src/Game/UI/uiPauseMenuDataMgr.h @@ -15,6 +15,10 @@ namespace al { class ByamlIter; } +namespace ksys::act { +class InfoData; +} + namespace uking::ui { constexpr int NumPouchItemsMax = 420; @@ -35,6 +39,8 @@ enum class PouchItemType { Invalid = -1, }; +constexpr int NumPouchItemTypes = 10; + constexpr bool isPouchItemWeapon(PouchItemType type) { return type == PouchItemType::Weapon || type == PouchItemType::Bow || type == PouchItemType::Arrow || type == PouchItemType::Shield; @@ -44,6 +50,10 @@ constexpr bool isPouchItemNotWeapon(PouchItemType type) { return !isPouchItemWeapon(type); } +constexpr bool isPouchItemArmor(PouchItemType type) { + return PouchItemType::ArmorHead <= type && type <= PouchItemType::ArmorLower; +} + constexpr bool isPouchItemInvalid(PouchItemType type) { return u32(type) > u32(PouchItemType::KeyItem); } @@ -56,10 +66,21 @@ enum class PouchCategory { Material = 4, Food = 5, KeyItem = 6, + Invalid = -1, }; constexpr int NumPouchCategories = 7; +enum class EquipmentSlot { + WeaponRight = 0, + WeaponBow = 1, + WeaponArrow = 2, + WeaponLeft = 3, + ArmorHead = 4, + ArmorUpper = 5, + ArmorLower = 6, +}; + struct CookTagInfo { u32 is_tag; sead::SafeString name; @@ -73,6 +94,7 @@ public: PouchItemType getType() const { return mType; } bool isValid() const { return mValid; } + u8 get25() const { return _25; } const sead::SafeString& getName() const { return mName; } // This is only valid if the item is not a weapon. @@ -128,14 +150,16 @@ class PauseMenuDataMgr { public: void init(sead::Heap* heap); + void initForNewSave(); static PouchItemType getType(const sead::SafeString& item, al::ByamlIter* iter = nullptr); + int countItemsWithType(PouchItemType type, bool x = false) const; bool isWeaponSectionFull(const sead::SafeString& get_flag) const; void removeArrow(const sead::SafeString& arrow_name, int count = 1); int getItemCount(const sead::SafeString& name, bool x = true) const; void setWeaponItemValue(s32 value, PouchItemType type); - const sead::SafeString& getDefaultEquipment(u32 idx) const; + const sead::SafeString& getDefaultEquipment(EquipmentSlot idx) const; bool hasItem(const sead::SafeString& name) const; PouchItem* getMasterSword() const; @@ -147,6 +171,17 @@ public: void breakMasterSword(); void restoreMasterSword(bool only_if_broken); + bool isHeroSoulEnabled(const sead::SafeString& name) const; + bool hasRitoSoulPlus() const; + bool hasGoronSoulPlus() const; + bool hasGerudoSoulPlus() const; + bool hasZoraSoulPlus() const; + + bool isOverCategoryLimit(PouchItemType type) const; + void openItemCategoryIfNeeded() const; + + auto get44800() const { return _44800; } + private: // TODO: rename struct ItemInfo { @@ -183,6 +218,8 @@ private: PouchItem* nextItem(const PouchItem* item) const { return getItems().next(item); } + void resetItem(); + /// @param num_cleared_beasts The number of divine beasts that have been done. void updateDivineBeastClearFlags(int num_cleared_beasts); @@ -190,7 +227,7 @@ private: Lists mItemLists; sead::SafeArray mListHeads; sead::SafeArray mArray1; - sead::SafeArray mArray2; + sead::SafeArray mArray2; PouchItem* mItem_44488{}; s32 _44490 = -1; s32 _44494 = -1; @@ -205,10 +242,10 @@ private: u32 _4450c{}; u32 _44510{}; u32 _44514{}; - u64 _44518{}; - u64 _44520{}; - u64 _44528{}; - PouchItem* _44530{}; + PouchItem* mRitoSoulItem{}; + PouchItem* mGoronSoulItem{}; + PouchItem* mZoraSoulItem{}; + PouchItem* mGerudoSoulItem{}; bool _44538 = false; PouchItem mItem; @@ -219,8 +256,18 @@ private: u64 _447e8; u64 _447f0; u64 _447f8; - s32 _44800 = -1; + PouchCategory _44800 = PouchCategory::Invalid; }; KSYS_CHECK_SIZE_NX150(PauseMenuDataMgr, 0x44808); +int sortWeapon(const PouchItem* lhs, const PouchItem* rhs, ksys::act::InfoData* data); +int sortBow(const PouchItem* lhs, const PouchItem* rhs, ksys::act::InfoData* data); +int sortShield(const PouchItem* lhs, const PouchItem* rhs, ksys::act::InfoData* data); +int sortArmor(const PouchItem* lhs, const PouchItem* rhs, ksys::act::InfoData* data); +int sortMaterial(const PouchItem* lhs, const PouchItem* rhs, ksys::act::InfoData* data); +int sortFood(const PouchItem* lhs, const PouchItem* rhs, ksys::act::InfoData* data); +int sortKeyItem(const PouchItem* lhs, const PouchItem* rhs, ksys::act::InfoData* data); + +int getCookItemOrder(const PouchItem* item, ksys::act::InfoData* data); + } // namespace uking::ui diff --git a/src/KingSystem/ActorSystem/CMakeLists.txt b/src/KingSystem/ActorSystem/CMakeLists.txt index abc4c10f..911a3277 100644 --- a/src/KingSystem/ActorSystem/CMakeLists.txt +++ b/src/KingSystem/ActorSystem/CMakeLists.txt @@ -1,4 +1,6 @@ target_sources(uking PRIVATE + Profiles/actPlayerBase.cpp + Profiles/actPlayerBase.h Profiles/actRopeBase.cpp Profiles/actRopeBase.h @@ -69,6 +71,8 @@ target_sources(uking PRIVATE actInstParamPack.cpp actInstParamPack.h actLifeRecoveryInfo.h + actPlayerInfo.cpp + actPlayerInfo.h actTag.h actionDummyAction.cpp diff --git a/src/KingSystem/ActorSystem/Profiles/actPlayerBase.cpp b/src/KingSystem/ActorSystem/Profiles/actPlayerBase.cpp new file mode 100644 index 00000000..abc059cd --- /dev/null +++ b/src/KingSystem/ActorSystem/Profiles/actPlayerBase.cpp @@ -0,0 +1 @@ +#include "KingSystem/ActorSystem/Profiles/actPlayerBase.h" diff --git a/src/KingSystem/ActorSystem/Profiles/actPlayerBase.h b/src/KingSystem/ActorSystem/Profiles/actPlayerBase.h new file mode 100644 index 00000000..47c9cace --- /dev/null +++ b/src/KingSystem/ActorSystem/Profiles/actPlayerBase.h @@ -0,0 +1,15 @@ +#pragma once + +#include + +namespace ksys::act { + +// TODO +class PlayerBase { +public: + // FIXME: name for x and name+type for y + void switchEquipment(const sead::SafeString& slot, int frames, int x = -1, + const uintptr_t& y = {}); +}; + +} // namespace ksys::act diff --git a/src/KingSystem/ActorSystem/actPlayerInfo.cpp b/src/KingSystem/ActorSystem/actPlayerInfo.cpp new file mode 100644 index 00000000..fca8b658 --- /dev/null +++ b/src/KingSystem/ActorSystem/actPlayerInfo.cpp @@ -0,0 +1 @@ +#include "KingSystem/ActorSystem/actPlayerInfo.h" diff --git a/src/KingSystem/ActorSystem/actPlayerInfo.h b/src/KingSystem/ActorSystem/actPlayerInfo.h new file mode 100644 index 00000000..9ceb53b2 --- /dev/null +++ b/src/KingSystem/ActorSystem/actPlayerInfo.h @@ -0,0 +1,19 @@ +#pragma once + +#include + +namespace ksys::act { + +class PlayerBase; + +// TODO +class PlayerInfo { + SEAD_SINGLETON_DISPOSER(PlayerInfo) + PlayerInfo(); + virtual ~PlayerInfo(); + +public: + PlayerBase* getPlayer() const; +}; + +} // namespace ksys::act