uking/ui: Add more PauseMenuDataMgr functions

This commit is contained in:
Léo Lam 2021-01-20 12:11:09 +01:00
parent 30bbc0c54a
commit 57d3a082c2
No known key found for this signature in database
GPG Key ID: 0DF30F9081000741
5 changed files with 578 additions and 80 deletions

View File

@ -56362,30 +56362,30 @@
0x0000007100973e7c,sub_7100973E7C,272,_ZNK5uking2ui16PauseMenuDataMgr16getFreeSlotCountEv 0x0000007100973e7c,sub_7100973E7C,272,_ZNK5uking2ui16PauseMenuDataMgr16getFreeSlotCountEv
0x0000007100973f8c,sub_7100973F8C,264,_ZNK5uking2ui16PauseMenuDataMgr26calculateEnemyMaterialMamoEv 0x0000007100973f8c,sub_7100973F8C,264,_ZNK5uking2ui16PauseMenuDataMgr26calculateEnemyMaterialMamoEv
0x0000007100974094,sub_7100974094,788,_ZN5uking2ui16PauseMenuDataMgr23removeAllEnemyMaterialsEv 0x0000007100974094,sub_7100974094,788,_ZN5uking2ui16PauseMenuDataMgr23removeAllEnemyMaterialsEv
0x00000071009743a8,PauseMenuDataMgr::countItemsWithCategory,836, 0x00000071009743a8,PauseMenuDataMgr::countItemsWithCategory,836,_ZNK5uking2ui16PauseMenuDataMgr21countItemsWithProfileERKN4sead14SafeStringBaseIcEEb
0x00000071009746ec,PauseMenuDataMgr::countItemsWithTag,412, 0x00000071009746ec,PauseMenuDataMgr::countItemsWithTag,412,_ZNK5uking2ui16PauseMenuDataMgr17countItemsWithTagEjb
0x0000007100974888,sub_7100974888,828, 0x0000007100974888,sub_7100974888,828,_ZNK5uking2ui16PauseMenuDataMgr16countCookResultsERKN4sead14SafeStringBaseIcEEib
0x0000007100974bc4,PauseMenuDataMgr::countItemsWithPouchCategory,228, 0x0000007100974bc4,PauseMenuDataMgr::countItemsWithPouchCategory,228,_ZNK5uking2ui16PauseMenuDataMgr22countItemsWithCategoryENS0_13PouchCategoryE
0x0000007100974ca8,sub_7100974CA8,68, 0x0000007100974ca8,sub_7100974CA8,68,_ZNK5uking2ui16PauseMenuDataMgr18getCategoryForTypeENS0_13PouchItemTypeE
0x0000007100974cec,sub_7100974CEC,1556, 0x0000007100974cec,sub_7100974CEC,1556,_ZN5uking2ui16PauseMenuDataMgr16removeCookResultERKN4sead14SafeStringBaseIcEEib?
0x0000007100975300,PauseMenuDataMgr::__auto13,852, 0x0000007100975300,PauseMenuDataMgr::__auto13,852,_ZN5uking2ui16PauseMenuDataMgr15switchEquipmentERKN4sead14SafeStringBaseIcEEPiPNS_3act18WeaponModifierInfoE
0x0000007100975654,sub_7100975654,872, 0x0000007100975654,sub_7100975654,872,_ZN5uking2ui16PauseMenuDataMgr17initPouchForQuestEv
0x00000071009759bc,sub_71009759BC,408, 0x00000071009759bc,sub_71009759BC,408,_ZN5uking2ui16PauseMenuDataMgr20restorePouchForQuestEv
0x0000007100975b54,sub_7100975B54,1876, 0x0000007100975b54,sub_7100975B54,1876,_ZN5uking2ui10getItemUseERKN4sead14SafeStringBaseIcEE
0x00000071009762a8,sub_71009762A8,504, 0x00000071009762a8,sub_71009762A8,504,
0x00000071009764a0,sub_71009764A0,568, 0x00000071009764a0,sub_71009764A0,568,
0x00000071009766d8,PauseMenuDataMgr::trashItem,1516, 0x00000071009766d8,PauseMenuDataMgr::trashItem,1516,
0x0000007100976cc4,PauseMenuDataMgr::useMaybe,1124, 0x0000007100976cc4,PauseMenuDataMgr::useMaybe,1124,
0x0000007100977128,sub_7100977128,868, 0x0000007100977128,sub_7100977128,868,
0x000000710097748c,sub_710097748C,628, 0x000000710097748c,sub_710097748C,628,_ZN5uking2ui16PauseMenuDataMgr9sortItemsENS0_13PouchCategoryEb
0x0000007100977700,sub_7100977700,248,_ZN5uking2ui22pouchItemSortPredicateEPKNS0_9PouchItemES3_ 0x0000007100977700,sub_7100977700,248,_ZN5uking2ui22pouchItemSortPredicateEPKNS0_9PouchItemES3_
0x00000071009777f8,sub_71009777F8,272, 0x00000071009777f8,sub_71009777F8,272,
0x0000007100977908,sub_7100977908,288, 0x0000007100977908,sub_7100977908,288,
0x0000007100977a28,sub_7100977A28,272, 0x0000007100977a28,sub_7100977A28,272,
0x0000007100977b38,sub_7100977B38,336,_ZN5uking2ui9sortArmorEPKNS0_9PouchItemES3_PN4ksys3act8InfoDataE 0x0000007100977b38,sub_7100977B38,336,_ZN5uking2ui12compareArmorEPKNS0_9PouchItemES3_PN4ksys3act8InfoDataE
0x0000007100977c88,sub_7100977C88,308, 0x0000007100977c88,sub_7100977C88,308,
0x0000007100977dbc,sub_7100977DBC,540, 0x0000007100977dbc,sub_7100977DBC,540,
0x0000007100977fd8,sub_7100977FD8,116,_ZN5uking2ui11sortKeyItemEPKNS0_9PouchItemES3_PN4ksys3act8InfoDataE 0x0000007100977fd8,sub_7100977FD8,116,_ZN5uking2ui14compareKeyItemEPKNS0_9PouchItemES3_PN4ksys3act8InfoDataE
0x000000710097804c,sub_710097804C,676, 0x000000710097804c,sub_710097804C,676,
0x00000071009782f0,sub_71009782F0,664, 0x00000071009782f0,sub_71009782F0,664,
0x0000007100978588,sub_7100978588,480,_ZN5uking2ui16getCookItemOrderEPKNS0_9PouchItemEPN4ksys3act8InfoDataE 0x0000007100978588,sub_7100978588,480,_ZN5uking2ui16getCookItemOrderEPKNS0_9PouchItemEPN4ksys3act8InfoDataE
@ -56395,15 +56395,15 @@
0x0000007100978c38,sub_7100978C38,488, 0x0000007100978c38,sub_7100978C38,488,
0x0000007100978e20,sub_7100978E20,548, 0x0000007100978e20,sub_7100978E20,548,
0x0000007100979044,PauseMenuDataMgr::__auto8,480, 0x0000007100979044,PauseMenuDataMgr::__auto8,480,
0x0000007100979224,PauseMenuDataMgr::__auto11,208, 0x0000007100979224,PauseMenuDataMgr::__auto11,208,_ZNK5uking2ui16PauseMenuDataMgr19getEquippedItemNameENS0_13PouchItemTypeE?
0x00000071009792f4,PauseMenuDataMgr::__auto12,212, 0x00000071009792f4,PauseMenuDataMgr::__auto12,212,_ZNK5uking2ui16PauseMenuDataMgr15getEquippedItemENS0_13PouchItemTypeE
0x00000071009793c8,sub_71009793C8,588, 0x00000071009793c8,sub_71009793C8,588,_ZNK5uking2ui16PauseMenuDataMgr12getItemValueERKN4sead14SafeStringBaseIcEE
0x0000007100979614,PauseMenuDataMgr::pouchGetFromShop,496, 0x0000007100979614,PauseMenuDataMgr::pouchGetFromShop,496,_ZN5uking2ui16PauseMenuDataMgr11getFromShopERKN4sead14SafeStringBaseIcEEiPKNS_3act18WeaponModifierInfoE
0x0000007100979804,sub_7100979804,316, 0x0000007100979804,sub_7100979804,316,
0x0000007100979940,sub_7100979940,120, 0x0000007100979940,sub_7100979940,120,
0x00000071009799b8,PauseMenuDataMgr::pouchUseFromRecipe,2688, 0x00000071009799b8,PauseMenuDataMgr::pouchUseFromRecipe,2688,
0x000000710097a438,PauseMenuDataMgr::__auto0,196, 0x000000710097a438,PauseMenuDataMgr::__auto0,196,_ZNK5uking2ui16PauseMenuDataMgr13countArmorDyeEv
0x000000710097a4fc,sub_710097A4FC,204, 0x000000710097a4fc,sub_710097A4FC,204,_ZNK5uking2ui16PauseMenuDataMgr21countAlreadyDyedArmorEv
0x000000710097a5c8,sub_710097A5C8,516, 0x000000710097a5c8,sub_710097A5C8,516,
0x000000710097a7cc,sub_710097A7CC,376, 0x000000710097a7cc,sub_710097A7CC,376,
0x000000710097a944,sub_710097A944,184, 0x000000710097a944,sub_710097A944,184,

Can't render this file because it is too large.

View File

@ -197,10 +197,7 @@ void PauseMenuDataMgr::initForNewSave() {
ksys::gdt::setFlag_DungeonClearSealNum(0); ksys::gdt::setFlag_DungeonClearSealNum(0);
ksys::gdt::setFlag_FairyCountCheck(false); ksys::gdt::setFlag_FairyCountCheck(false);
_444fc = {}; _444fc = {};
mLastAddedItem = {}; resetItemAndPointers();
mItem_444f0 = {};
_444f8 = -1;
resetItem();
mIsPouchForQuest = false; mIsPouchForQuest = false;
for (auto& x : mGrabbedItems) for (auto& x : mGrabbedItems)
x = {}; x = {};
@ -235,10 +232,7 @@ void PauseMenuDataMgr::loadFromGameData() {
for (auto& x : mGrabbedItems) for (auto& x : mGrabbedItems)
x = {}; x = {};
mLastAddedItem = {}; resetItemAndPointers();
mItem_444f0 = {};
_444f8 = -1;
resetItem();
_444fc = 0; _444fc = 0;
mIsPouchForQuest = false; mIsPouchForQuest = false;
_447e0 = {}; _447e0 = {};
@ -735,7 +729,7 @@ void PauseMenuDataMgr::updateAfterAddingItem(bool only_sort) {
if (getItems().isEmpty()) if (getItems().isEmpty())
return; return;
_44800 = PouchCategory::Invalid; mCategoryToSort = PouchCategory::Invalid;
auto& items = getItems(); auto& items = getItems();
items.sort(pouchItemSortPredicateForArrow); items.sort(pouchItemSortPredicateForArrow);
if (!only_sort) { if (!only_sort) {
@ -1040,16 +1034,7 @@ void PauseMenuDataMgr::unequipAll(PouchItemType type) {
KSYS_ALWAYS_INLINE inline void KSYS_ALWAYS_INLINE inline void
PauseMenuDataMgr::deleteItem_(const sead::OffsetList<PouchItem>& list, PouchItem* item, PauseMenuDataMgr::deleteItem_(const sead::OffsetList<PouchItem>& list, PouchItem* item,
const sead::SafeString& name) { const sead::SafeString& name) {
if (mItem_444f0 == item) destroyAndRecycleItem(mItemLists, item);
mItem_444f0 = nullptr;
if (mLastAddedItem == item)
mLastAddedItem = nullptr;
// Reset the PouchItem so that it is ready to be reused.
getItems().erase(item);
destroyAndRecycleItem(item);
ksys::PlayReportMgr::instance()->reportDebug("PouchDelete", name); ksys::PlayReportMgr::instance()->reportDebug("PouchDelete", name);
saveToGameData(list); saveToGameData(list);
updateInventoryInfo(list); updateInventoryInfo(list);
@ -1261,14 +1246,8 @@ void PauseMenuDataMgr::removeGrabbedItems() {
for (s32 i = 0, n = mGrabbedItems.size(); i < n; ++i) { for (s32 i = 0, n = mGrabbedItems.size(); i < n; ++i) {
auto& entry = mGrabbedItems[i]; auto& entry = mGrabbedItems[i];
auto* item = entry.item; auto* item = entry.item;
if (item && item->getValue() == 0 && !entry._9) { if (item && item->getValue() == 0 && !entry._9)
if (mItem_444f0 == item) destroyAndRecycleItem(mItemLists, item);
mItem_444f0 = nullptr;
if (mLastAddedItem == item)
mLastAddedItem = nullptr;
getItems().erase(item);
destroyAndRecycleItem(item);
}
entry = {}; entry = {};
} }
@ -1306,12 +1285,7 @@ bool PauseMenuDataMgr::addGrabbedItem(ksys::act::BaseProcLink* link) {
if (entry.item->getValue() == 0 && !entry._9) { if (entry.item->getValue() == 0 && !entry._9) {
const auto lock = sead::makeScopedLock(cs); const auto lock = sead::makeScopedLock(cs);
auto* item = entry.item; auto* item = entry.item;
if (mItem_444f0 == item) destroyAndRecycleItem(mItemLists, item);
mItem_444f0 = nullptr;
if (mLastAddedItem == item)
mLastAddedItem = nullptr;
getItems().erase(item);
destroyAndRecycleItem(item);
updateInventoryInfo(items); updateInventoryInfo(items);
updateListHeads(); updateListHeads();
saveToGameData(items); saveToGameData(items);
@ -1478,24 +1452,362 @@ void PauseMenuDataMgr::removeAllEnemyMaterials() {
info->hasTag(item.getName().cstr(), ksys::act::tags::EnemyMaterial) ? &item : nullptr; info->hasTag(item.getName().cstr(), ksys::act::tags::EnemyMaterial) ? &item : nullptr;
} }
if (material_to_remove) { if (material_to_remove)
if (mItem_444f0 == material_to_remove) destroyAndRecycleItem(mItemLists, material_to_remove);
mItem_444f0 = nullptr;
if (mLastAddedItem == material_to_remove)
mLastAddedItem = nullptr;
getItems().erase(material_to_remove);
destroyAndRecycleItem(material_to_remove);
}
saveToGameData(items); saveToGameData(items);
updateInventoryInfo(items); updateInventoryInfo(items);
updateListHeads(); updateListHeads();
} }
int PauseMenuDataMgr::countItemsWithProfile(const sead::SafeString& profile,
bool count_stacked_items) const {
const auto lock = sead::makeScopedLock(mCritSection);
s32 count = 0;
for (const auto& item : getItems()) {
const char* item_profile;
al::ByamlIter iter;
if (ksys::act::InfoData::instance()->getActorIter(&iter, item.getName().cstr()) &&
ksys::act::InfoData::instance()->getActorProfile(&item_profile, iter) &&
profile == item_profile) {
if (count_stacked_items &&
ksys::act::InfoData::instance()->hasTag(iter, ksys::act::tags::CanStack)) {
count += item.getValue();
} else {
count += 1;
}
}
}
return count;
}
int PauseMenuDataMgr::countItemsWithTag(u32 tag, bool count_stacked_items) const {
const auto lock = sead::makeScopedLock(mCritSection);
s32 count = 0;
for (const auto& item : getItems()) {
al::ByamlIter iter;
if (ksys::act::InfoData::instance()->getActorIter(&iter, item.getName().cstr()) &&
ksys::act::InfoData::instance()->hasTag(iter, tag)) {
if (count_stacked_items &&
ksys::act::InfoData::instance()->hasTag(iter, ksys::act::tags::CanStack)) {
count += item.getValue();
} else {
count += 1;
}
}
}
return count;
}
int PauseMenuDataMgr::countCookResults(const sead::SafeString& name, s32 effect_type,
bool check_effect_type) const {
const auto lock = sead::makeScopedLock(mCritSection);
auto* info = ksys::act::InfoData::instance();
if (!info)
return 0;
const bool check_name = !name.isEmpty();
if (check_name && !info->hasTag(name.cstr(), ksys::act::tags::CookResult))
return 0;
s32 count = 0;
for (auto* item = getItemHead(PouchCategory::Food); item; item = nextItem(item)) {
if (item->getType() != PouchItemType::Food)
break;
if (!item->get25())
continue;
if (!info->hasTag(item->getName().cstr(), ksys::act::tags::CookResult))
continue;
if (check_effect_type && item->getCookData().mCookEffect0.x != effect_type)
continue;
if (check_name && item->getName() != name)
continue;
++count;
}
return count;
}
int PauseMenuDataMgr::countItemsWithCategory(PouchCategory category) const {
const auto lock = sead::makeScopedLock(mCritSection);
if (u32(category) > 6)
return 0;
s32 count = 0;
for (auto* item = getItemHead(category); item; item = nextItem(item)) {
const auto type = item->getType();
if (getCategoryForType(type) != category)
break;
count += item->get25();
}
return count;
}
// NOLINTNEXTLINE(readability-convert-member-functions-to-static)
PouchCategory PauseMenuDataMgr::getCategoryForType(PouchItemType type) const {
if (type == PouchItemType::Sword)
return PouchCategory::Sword;
if (isPouchItemBowOrArrow(type))
return PouchCategory::Bow;
switch (type) {
case PouchItemType::Shield:
return PouchCategory::Shield;
case PouchItemType::ArmorHead:
case PouchItemType::ArmorUpper:
case PouchItemType::ArmorLower:
return PouchCategory::Armor;
case PouchItemType::Material:
return PouchCategory::Material;
case PouchItemType::Food:
return PouchCategory::Food;
case PouchItemType::KeyItem:
return PouchCategory::KeyItem;
default:
return PouchCategory::Invalid;
}
}
// NON_MATCHING: two harmless reorderings
void PauseMenuDataMgr::removeCookResult(const sead::SafeString& name, s32 effect_type,
bool check_effect) {
auto* info = ksys::act::InfoData::instance();
if (!info)
return;
const bool check_name = !name.isEmpty();
if (check_name && !info->hasTag(name.cstr(), ksys::act::tags::CookResult))
return;
const auto lock = sead::makeScopedLock(mCritSection);
const auto& items = getItems();
auto min_x = std::numeric_limits<s32>::max();
auto min_y = std::numeric_limits<f32>::infinity();
auto min_fx = std::numeric_limits<f32>::infinity();
PouchItem* to_remove = nullptr;
for (auto* item = getItemHead(PouchCategory::Food); item; item = items.next(item)) {
if (item->getType() != PouchItemType::Food)
break;
if (!item->get25())
continue;
if (!info->hasTag(item->getName().cstr(), ksys::act::tags::CookResult))
continue;
if (item->getCookData().mCookEffect0.x != effect_type && check_effect)
continue;
if (check_name && item->getName() != name)
continue;
const auto y = f32(item->getCookData().mStaminaRecoverY) * 30.0f;
if (y < min_y) {
min_x = item->getCookData().mStaminaRecoverX;
min_y = y;
to_remove = item;
min_fx = item->getCookData().mCookEffect0.y;
} else if (y == min_y) {
const auto x = item->getCookData().mStaminaRecoverX;
if (x < min_x) {
min_x = x;
to_remove = item;
min_fx = item->getCookData().mCookEffect0.y;
} else if (check_effect && x == min_x && item->getCookData().mCookEffect0.y < min_fx) {
min_fx = item->getCookData().mCookEffect0.y;
to_remove = item;
}
}
}
if (!to_remove)
return;
destroyAndRecycleItem(mItemLists, to_remove);
ksys::PlayReportMgr::instance()->reportDebug("PouchDeleteFromFlow", name);
saveToGameData(items);
updateInventoryInfo(items);
updateListHeads();
}
bool PauseMenuDataMgr::switchEquipment(const sead::SafeString& name, int* value,
act::WeaponModifierInfo* modifier) {
const auto lock = sead::makeScopedLock(mCritSection);
const auto& items = getItems();
sead::SafeString group_name;
getSameGroupActorName(&group_name, name);
PouchItem* target = nullptr;
const auto type = getType(group_name);
if (type <= PouchItemType::Shield) {
for (auto& item : items) {
if (item.getType() > PouchItemType::Shield)
break;
if (item.getName() == group_name && (!target || item.getValue() < target->getValue()))
target = &item;
}
} else {
if (type >= PouchItemType::Material)
return false;
for (auto& item : items) {
if (item.getType() >= PouchItemType::Material)
break;
if (item.getName() == group_name) {
target = &item;
break;
}
}
}
if (!target)
return false;
if (value)
*value = target->getValue();
if (type == PouchItemType::Arrow) {
if (target->getValue() > 0) {
autoEquip(target, items);
return true;
}
return false;
}
autoEquip(target, items);
const bool is_weapon = type <= PouchItemType::Shield;
if (modifier && is_weapon)
modifier->fromItem(*target);
return true;
}
void PauseMenuDataMgr::initPouchForQuest() {
mIsPouchForQuest = true;
resetItemAndPointers();
{
const auto lock = sead::makeScopedLock(mCritSection);
const auto& items = getItems();
PouchItem* to_remove = nullptr;
for (auto& item : items) {
if (to_remove != nullptr) {
getItems().erase(to_remove);
destroyAndRecycleItem(to_remove);
}
to_remove = item.getType() == PouchItemType::KeyItem ? nullptr : &item;
}
if (to_remove) {
getItems().erase(to_remove);
destroyAndRecycleItem(to_remove);
}
updateInventoryInfo(items);
updateListHeads();
}
ksys::gdt::setFlag_FairyCountCheck(false);
createPlayerEquipment();
}
void PauseMenuDataMgr::restorePouchForQuest() {
mIsPouchForQuest = false;
doLoadFromGameData();
for (auto& entry : mGrabbedItems)
entry = {};
resetItemAndPointers();
createPlayerEquipment();
}
ItemUse getItemUse(const sead::SafeString& name) {
const char* profile_c;
if (!ksys::act::InfoData::instance()->getActorProfile(&profile_c, name.cstr()))
return ItemUse::Invalid;
const sead::SafeString profile = profile_c;
if (profile == sValues.WeaponSmallSword)
return ItemUse::WeaponSmallSword;
if (profile == sValues.WeaponLargeSword)
return ItemUse::WeaponLargeSword;
if (profile == sValues.WeaponSpear)
return ItemUse::WeaponSpear;
if (profile == sValues.WeaponBow)
return ItemUse::WeaponBow;
if (profile == sValues.WeaponShield)
return ItemUse::WeaponShield;
if (profile == sValues.ArmorHead)
return ItemUse::ArmorHead;
if (profile == sValues.ArmorUpper)
return ItemUse::ArmorUpper;
if (profile == sValues.ArmorLower)
return ItemUse::ArmorLower;
if (profile != sValues.Item && profile != sValues.PlayerItem)
return ItemUse::Item;
al::ByamlIter iter;
if (!ksys::act::InfoData::instance()->getActorIter(&iter, name.cstr()))
return ItemUse::Item;
if (ksys::act::InfoData::instance()->hasTag(iter, ksys::act::tags::CureItem))
return ItemUse::CureItem;
if (ksys::act::InfoData::instance()->hasTag(iter, ksys::act::tags::Important))
return ItemUse::ImportantItem;
return ItemUse::Item;
}
void PauseMenuDataMgr::sortItems(PouchCategory category, bool do_not_save) {
const auto lock = sead::makeScopedLock(mCritSection);
auto& items = getItems();
if (items.isEmpty())
return;
mCategoryToSort = category;
items.mergeSort(pouchItemSortPredicate);
switch (category) {
case PouchCategory::Sword:
ksys::gdt::setFlag_SortTypeWeaponPouch(!ksys::gdt::getFlag_SortTypeWeaponPouch());
break;
case PouchCategory::Bow:
ksys::gdt::setFlag_SortTypeBowPouch(!ksys::gdt::getFlag_SortTypeBowPouch());
break;
case PouchCategory::Shield:
ksys::gdt::setFlag_SortTypeShieldPouch(!ksys::gdt::getFlag_SortTypeShieldPouch());
break;
case PouchCategory::Armor:
ksys::gdt::setFlag_SortTypeArmorPouch(!ksys::gdt::getFlag_SortTypeArmorPouch());
break;
default:
break;
}
if (do_not_save)
return;
updateInventoryInfo(items);
updateListHeads();
saveToGameData(items);
}
using SortPredicate = int (*)(const PouchItem* lhs, const PouchItem* rhs, using SortPredicate = int (*)(const PouchItem* lhs, const PouchItem* rhs,
ksys::act::InfoData* data); ksys::act::InfoData* data);
static PouchCategory getTypeForCategory(PouchItemType type) { static PouchCategory getCategoryForTypeWithLookupTable(PouchItemType type) {
static constexpr sead::SafeArray<PouchCategory, NumPouchItemTypes> sMap{{ static constexpr sead::SafeArray<PouchCategory, NumPouchItemTypes> sMap{{
PouchCategory::Sword, // Weapon PouchCategory::Sword, // Weapon
PouchCategory::Bow, // Bow PouchCategory::Bow, // Bow
@ -1512,8 +1824,8 @@ static PouchCategory getTypeForCategory(PouchItemType type) {
} }
static auto getSortPredicateTable() { static auto getSortPredicateTable() {
sead::SafeArray<SortPredicate, 7> table{ sead::SafeArray<SortPredicate, 7> table{{compareWeapon, compareBow, compareShield, compareArmor,
{sortWeapon, sortBow, sortShield, sortArmor, sortMaterial, sortFood, sortKeyItem}}; compareMaterial, compareFood, compareKeyItem}};
return table; return table;
} }
@ -1525,8 +1837,8 @@ int pouchItemSortPredicate(const PouchItem* lhs, const PouchItem* rhs) {
if (!info_data || !lhs->get25() || !rhs->get25()) if (!info_data || !lhs->get25() || !rhs->get25())
return 0; return 0;
const auto cat1 = getTypeForCategory(lhs->getType()); const auto cat1 = getCategoryForTypeWithLookupTable(lhs->getType());
const auto cat2 = getTypeForCategory(rhs->getType()); const auto cat2 = getCategoryForTypeWithLookupTable(rhs->getType());
if (cat1 != cat2) if (cat1 != cat2)
return 0; return 0;
@ -1551,7 +1863,7 @@ static s32 compareSortKeys(const PouchItem* lhs, const PouchItem* rhs, ksys::act
return 0; return 0;
} }
int sortArmor(const PouchItem* lhs, const PouchItem* rhs, ksys::act::InfoData* data) { int compareArmor(const PouchItem* lhs, const PouchItem* rhs, ksys::act::InfoData* data) {
if (ksys::gdt::getFlag_SortTypeArmorPouch()) { if (ksys::gdt::getFlag_SortTypeArmorPouch()) {
if (auto cmp = compareSortKeys(lhs, rhs, data)) if (auto cmp = compareSortKeys(lhs, rhs, data))
return cmp; return cmp;
@ -1578,7 +1890,7 @@ int sortArmor(const PouchItem* lhs, const PouchItem* rhs, ksys::act::InfoData* d
return 0; return 0;
} }
int sortKeyItem(const PouchItem* lhs, const PouchItem* rhs, ksys::act::InfoData* data) { int compareKeyItem(const PouchItem* lhs, const PouchItem* rhs, ksys::act::InfoData* data) {
if (auto cmp = compareSortKeys(lhs, rhs, data)) if (auto cmp = compareSortKeys(lhs, rhs, data))
return cmp; return cmp;
return 0; return 0;
@ -1620,8 +1932,8 @@ int pouchItemSortPredicateForArrow(const PouchItem* lhs, const PouchItem* rhs) {
if (!info_data || !lhs->get25() || !rhs->get25()) if (!info_data || !lhs->get25() || !rhs->get25())
return 0; return 0;
const auto cat1 = getTypeForCategory(lhs->getType()); const auto cat1 = getCategoryForTypeWithLookupTable(lhs->getType());
const auto cat2 = getTypeForCategory(rhs->getType()); const auto cat2 = getCategoryForTypeWithLookupTable(rhs->getType());
if (cat1 != cat2) if (cat1 != cat2)
return 0; return 0;
@ -1636,6 +1948,111 @@ int pouchItemSortPredicateForArrow(const PouchItem* lhs, const PouchItem* rhs) {
return (*fn)(lhs, rhs, info_data); return (*fn)(lhs, rhs, info_data);
} }
// NON_MATCHING: branching, but this is so trivial it isn't worth spending time on matching this
const sead::SafeString* PauseMenuDataMgr::getEquippedItemName(PouchItemType type) const {
const auto lock = sead::makeScopedLock(mCritSection);
const auto& items = getItems();
if (!isPouchItemEquipment(type) || items.isEmpty())
return nullptr;
auto* first = type <= PouchItemType::Shield ? items.nth(0) : getItemHead(PouchCategory::Armor);
for (auto* item = first; item; item = items.next(item)) {
if (item->isEquipped() && item->getType() == type)
return &item->getName();
}
return nullptr;
}
const PouchItem* PauseMenuDataMgr::getEquippedItem(PouchItemType type) const {
const auto lock = sead::makeScopedLock(mCritSection);
const auto& items = getItems();
if (!isPouchItemEquipment(type) || items.isEmpty())
return nullptr;
auto* first = type <= PouchItemType::Shield ? items.nth(0) : getItemHead(PouchCategory::Armor);
for (auto* item = first; item; item = items.next(item)) {
if (item->isEquipped() && item->getType() == type)
return item;
}
return nullptr;
}
int PauseMenuDataMgr::getItemValue(const sead::SafeString& name) const {
const auto type = getType(name);
if (isPouchItemInvalid(type))
return 0;
sead::SafeString group_name;
getSameGroupActorName(&group_name, name);
if (ksys::act::InfoData::instance()->hasTag(group_name.cstr(), ksys::act::tags::CanStack)) {
for (const auto& item : mItemLists.buffer) {
if (item.get25() && item.getType() == type && !group_name.comparen(item.getName(), 64))
return item.getValue();
}
return 0;
}
s32 count = 0;
for (const auto& item : mItemLists.buffer) {
if (item.get25() && item.getType() == type && !group_name.comparen(item.getName(), 64))
count++;
}
return count;
}
bool PauseMenuDataMgr::getFromShop(const sead::SafeString& name, int value,
const act::WeaponModifierInfo* modifier) {
const auto lock = sead::makeScopedLock(mCritSection);
auto& lists = mItemLists;
const auto type = getType(name);
al::ByamlIter iter;
namespace act = ksys::act;
act::InfoData::instance()->getActorIter(&iter, name.cstr());
if (iter.isValid() && act::InfoData::instance()->hasTag(iter, act::tags::CanStack)) {
addToPouch(name, type, lists, value, false, modifier);
} else if (iter.isValid() && act::InfoData::instance()->hasTag(iter, act::tags::ArmorDye)) {
addToPouch(name, type, lists, 0, false, modifier);
} else if (type > PouchItemType::Shield || type == PouchItemType::Arrow) {
addToPouch(name, type, lists, 1, false, modifier);
} else {
int life = getItemGeneralLife(name.cstr());
if (modifier)
life += modifier->flags.isOn(uking::act::WeaponModifier::AddLife) ? modifier->value : 0;
addToPouch(name, type, lists, life, false, modifier);
}
ksys::PlayReportMgr::instance()->reportDebug("PouchGetFromShop", name);
saveToGameData(lists.list1);
return true;
}
int PauseMenuDataMgr::countArmorDye() const {
int count = 0;
using namespace ksys::act;
for (const auto& item : getItems()) {
if (item.get25() && InfoData::instance()->hasTag(item.getName().cstr(), tags::ArmorDye))
++count;
}
return count;
}
int PauseMenuDataMgr::countAlreadyDyedArmor() const {
int count = 0;
using namespace ksys::act;
for (const auto& item : getItems()) {
if (item.get25() && InfoData::instance()->hasTag(item.getName().cstr(), tags::ArmorDye) &&
item.getValue() > 0) {
++count;
}
}
return count;
}
bool PauseMenuDataMgr::isHeroSoulEnabled(const sead::SafeString& name) const { bool PauseMenuDataMgr::isHeroSoulEnabled(const sead::SafeString& name) const {
if (name == sValues.Obj_HeroSoul_Zora || name == sValues.Obj_DLC_HeroSoul_Zora) { if (name == sValues.Obj_HeroSoul_Zora || name == sValues.Obj_DLC_HeroSoul_Zora) {
if (mZoraSoulItem) if (mZoraSoulItem)

View File

@ -18,7 +18,7 @@ class ByamlIter;
namespace ksys::act { namespace ksys::act {
class BaseProcLink; class BaseProcLink;
class InfoData; class InfoData;
} } // namespace ksys::act
namespace uking::act { namespace uking::act {
struct WeaponModifierInfo; struct WeaponModifierInfo;
@ -72,6 +72,10 @@ constexpr bool isPouchItemWeapon(PouchItemType type) {
type == PouchItemType::Arrow || type == PouchItemType::Shield; type == PouchItemType::Arrow || type == PouchItemType::Shield;
} }
constexpr bool isPouchItemBowOrArrow(PouchItemType type) {
return type == PouchItemType::Bow || type == PouchItemType::Arrow;
}
constexpr bool isPouchItemNotWeapon(PouchItemType type) { constexpr bool isPouchItemNotWeapon(PouchItemType type) {
return !isPouchItemWeapon(type); return !isPouchItemWeapon(type);
} }
@ -80,6 +84,10 @@ constexpr bool isPouchItemArmor(PouchItemType type) {
return PouchItemType::ArmorHead <= type && type <= PouchItemType::ArmorLower; return PouchItemType::ArmorHead <= type && type <= PouchItemType::ArmorLower;
} }
constexpr bool isPouchItemEquipment(PouchItemType type) {
return isPouchItemWeapon(type) || isPouchItemArmor(type);
}
constexpr bool isPouchItemInvalid(PouchItemType type) { constexpr bool isPouchItemInvalid(PouchItemType type) {
return u32(type) > u32(PouchItemType::KeyItem); return u32(type) > u32(PouchItemType::KeyItem);
} }
@ -107,6 +115,21 @@ enum class EquipmentSlot {
ArmorLower = 6, ArmorLower = 6,
}; };
enum class ItemUse {
WeaponSmallSword = 0,
WeaponLargeSword = 1,
WeaponSpear = 2,
WeaponBow = 3,
WeaponShield = 4,
ArmorHead = 5,
ArmorUpper = 6,
ArmorLower = 7,
Item = 8,
ImportantItem = 9,
CureItem = 10,
Invalid = -1,
};
struct CookTagInfo { struct CookTagInfo {
u32 is_tag; u32 is_tag;
sead::SafeString name; sead::SafeString name;
@ -257,12 +280,41 @@ public:
void breakMasterSword(); void breakMasterSword();
void restoreMasterSword(bool only_if_broken); void restoreMasterSword(bool only_if_broken);
bool checkAddOrRemoveItem(const sead::SafeString& name, int count, bool include_equipped_items) const; bool checkAddOrRemoveItem(const sead::SafeString& name, int count,
bool include_equipped_items) const;
int getFreeSlotCount() const; int getFreeSlotCount() const;
int calculateEnemyMaterialMamo() const; int calculateEnemyMaterialMamo() const;
void removeAllEnemyMaterials(); void removeAllEnemyMaterials();
int countItemsWithProfile(const sead::SafeString& profile, bool count_stacked_items) const;
int countItemsWithTag(u32 tag, bool count_stacked_items) const;
int countCookResults(const sead::SafeString& name = {}, s32 effect_type = 0x11,
bool check_effect_type = false) const;
int countItemsWithCategory(PouchCategory category) const;
PouchCategory getCategoryForType(PouchItemType type) const;
void removeCookResult(const sead::SafeString& name = {}, s32 effect_type = 0x11,
bool check_effect = false);
bool switchEquipment(const sead::SafeString& name, int* value = nullptr,
act::WeaponModifierInfo* modifier = nullptr);
void initPouchForQuest();
void restorePouchForQuest();
void sortItems(PouchCategory category, bool do_not_save = false);
const sead::SafeString* getEquippedItemName(PouchItemType type) const;
const PouchItem* getEquippedItem(PouchItemType type) const;
int getItemValue(const sead::SafeString& name) const;
bool getFromShop(const sead::SafeString& name, int value,
const act::WeaponModifierInfo* modifier = nullptr);
int countArmorDye() const;
int countAlreadyDyedArmor() const;
bool isHeroSoulEnabled(const sead::SafeString& name) const; bool isHeroSoulEnabled(const sead::SafeString& name) const;
bool hasRitoSoulPlus() const; bool hasRitoSoulPlus() const;
bool hasGoronSoulPlus() const; bool hasGoronSoulPlus() const;
@ -272,7 +324,7 @@ public:
bool isOverCategoryLimit(PouchItemType type) const; bool isOverCategoryLimit(PouchItemType type) const;
void openItemCategoryIfNeeded() const; void openItemCategoryIfNeeded() const;
auto get44800() const { return _44800; } auto get44800() const { return mCategoryToSort; }
private: private:
// TODO: rename // TODO: rename
@ -293,6 +345,13 @@ private:
} }
} }
void destroyAndRecycleItem(PouchItem* item) {
list1.erase(item);
item->~PouchItem();
new (item) PouchItem;
list2.pushFront(item);
}
sead::OffsetList<PouchItem> list1; sead::OffsetList<PouchItem> list1;
sead::OffsetList<PouchItem> list2; sead::OffsetList<PouchItem> list2;
sead::SafeArray<PouchItem, NumPouchItemsMax> buffer; sead::SafeArray<PouchItem, NumPouchItemsMax> buffer;
@ -319,7 +378,24 @@ private:
mItemLists.list2.pushFront(item); mItemLists.list2.pushFront(item);
} }
void destroyAndRecycleItem(Lists& lists, PouchItem* item) {
if (mItem_444f0 == item)
mItem_444f0 = nullptr;
if (mLastAddedItem == item)
mLastAddedItem = nullptr;
lists.destroyAndRecycleItem(item);
}
void resetItem(); void resetItem();
void resetItemAndPointers() {
mLastAddedItem = nullptr;
mItem_444f0 = nullptr;
_444f8 = -1;
resetItem();
}
void setItemModifier(PouchItem& item, const act::WeaponModifierInfo* modifier); void setItemModifier(PouchItem& item, const act::WeaponModifierInfo* modifier);
void doLoadFromGameData(); void doLoadFromGameData();
@ -378,18 +454,20 @@ private:
u64 _447e8; u64 _447e8;
u64 _447f0; u64 _447f0;
u64 _447f8; u64 _447f8;
PouchCategory _44800 = PouchCategory::Invalid; PouchCategory mCategoryToSort = PouchCategory::Invalid;
}; };
KSYS_CHECK_SIZE_NX150(PauseMenuDataMgr, 0x44808); KSYS_CHECK_SIZE_NX150(PauseMenuDataMgr, 0x44808);
int sortWeapon(const PouchItem* lhs, const PouchItem* rhs, ksys::act::InfoData* data); int compareWeapon(const PouchItem* lhs, const PouchItem* rhs, ksys::act::InfoData* data);
int sortBow(const PouchItem* lhs, const PouchItem* rhs, ksys::act::InfoData* data); int compareBow(const PouchItem* lhs, const PouchItem* rhs, ksys::act::InfoData* data);
int sortShield(const PouchItem* lhs, const PouchItem* rhs, ksys::act::InfoData* data); int compareShield(const PouchItem* lhs, const PouchItem* rhs, ksys::act::InfoData* data);
int sortArmor(const PouchItem* lhs, const PouchItem* rhs, ksys::act::InfoData* data); int compareArmor(const PouchItem* lhs, const PouchItem* rhs, ksys::act::InfoData* data);
int sortMaterial(const PouchItem* lhs, const PouchItem* rhs, ksys::act::InfoData* data); int compareMaterial(const PouchItem* lhs, const PouchItem* rhs, ksys::act::InfoData* data);
int sortFood(const PouchItem* lhs, const PouchItem* rhs, ksys::act::InfoData* data); int compareFood(const PouchItem* lhs, const PouchItem* rhs, ksys::act::InfoData* data);
int sortKeyItem(const PouchItem* lhs, const PouchItem* rhs, ksys::act::InfoData* data); int compareKeyItem(const PouchItem* lhs, const PouchItem* rhs, ksys::act::InfoData* data);
int getCookItemOrder(const PouchItem* item, ksys::act::InfoData* data); int getCookItemOrder(const PouchItem* item, ksys::act::InfoData* data);
ItemUse getItemUse(const sead::SafeString& name);
} // namespace uking::ui } // namespace uking::ui

View File

@ -7,4 +7,7 @@ namespace uking::ui {
int getWeaponInventoryLife(const sead::SafeString& name); int getWeaponInventoryLife(const sead::SafeString& name);
bool isMasterSwordActorName(const sead::SafeString& name); bool isMasterSwordActorName(const sead::SafeString& name);
// TODO: move this to another translation unit (TBD)
int getItemGeneralLife(const char* name);
} // namespace uking::ui } // namespace uking::ui