summaryrefslogtreecommitdiff
path: root/src/Game/UI
diff options
context:
space:
mode:
authorLéo Lam <leo@leolam.fr>2021-01-11 16:13:41 +0100
committerLéo Lam <leo@leolam.fr>2021-01-11 19:00:31 +0100
commitee713ab899b8e0f0ba1679f258a4d8ca20b16262 (patch)
tree9afb19e396fdcc4ec0b1f47e01f0c82a94e3ff88 /src/Game/UI
parentc28e7ace3d85820fb2a1bdd010bffbfc371a24a3 (diff)
uking/ui: Add "can get item" inventory functions
Diffstat (limited to 'src/Game/UI')
-rw-r--r--src/Game/UI/uiPauseMenuDataMgr.cpp112
-rw-r--r--src/Game/UI/uiPauseMenuDataMgr.h14
2 files changed, 122 insertions, 4 deletions
diff --git a/src/Game/UI/uiPauseMenuDataMgr.cpp b/src/Game/UI/uiPauseMenuDataMgr.cpp
index d8d200d0..a12fa7ca 100644
--- a/src/Game/UI/uiPauseMenuDataMgr.cpp
+++ b/src/Game/UI/uiPauseMenuDataMgr.cpp
@@ -113,7 +113,7 @@ struct PouchConstants {
PouchConstants sValues;
void getSameGroupActorName(sead::SafeString* group, const sead::SafeString& item,
- al::ByamlIter* iter) {
+ al::ByamlIter* iter = nullptr) {
if (iter) {
ksys::act::getSameGroupActorName(group, item, iter);
} else {
@@ -211,6 +211,78 @@ void PauseMenuDataMgr::initForNewSave() {
}
}
+void PauseMenuDataMgr::loadFromGameData() {
+ doLoadFromGameData();
+
+ for (auto& x : mArray3)
+ x = {};
+ mItem_44488 = {};
+ mItem_444f0 = {};
+ _444f8 = -1;
+ resetItem();
+ _444fc = 0;
+ mIsPouchForQuest = false;
+ _447e0 = {};
+ _447e8 = {};
+ _447f0 = {};
+ _447f8 = {};
+
+ const auto lock = sead::makeScopedLock(mCritSection);
+ updateInventoryInfo(getItems());
+}
+
+bool PauseMenuDataMgr::cannotGetItem(const sead::SafeString& name, int n) const {
+ namespace act = ksys::act;
+
+ al::ByamlIter iter;
+ if (!act::InfoData::instance()->getActorIter(&iter, name.cstr()))
+ return true;
+
+ if (!act::InfoData::instance()->hasTag(iter, act::tags::CanGetPouch))
+ return true;
+
+ if (act::InfoData::instance()->getSortKey(name.cstr()) == 99999)
+ return true;
+
+ const auto lock = sead::makeScopedLock(mCritSection);
+ const auto type = getType(name);
+
+ if (act::InfoData::instance()->hasTag(iter, act::tags::CanStack))
+ return !hasFreeSpaceForItem(mItemLists, name, n);
+
+ if (type <= PouchItemType::Shield) {
+ switch (type) {
+ case PouchItemType::Weapon: {
+ const auto limit = ksys::gdt::getFlag_WeaponPorchStockNum();
+ return isList2Empty() || limit < countItems(PouchItemType::Weapon) + n;
+ }
+ case PouchItemType::Shield: {
+ const auto limit = ksys::gdt::getFlag_ShieldPorchStockNum();
+ return isList2Empty() || limit < countItems(PouchItemType::Shield) + n;
+ }
+ case PouchItemType::Bow: {
+ const auto limit = ksys::gdt::getFlag_BowPorchStockNum();
+ return isList2Empty() || limit < countItems(PouchItemType::Bow) + n;
+ }
+ default: {
+ const auto limit = ksys::gdt::getFlag_WeaponPorchStockNum();
+ return isList2Empty() || limit < countItems(PouchItemType::Weapon, true) + n;
+ }
+ }
+ }
+
+ if (type == PouchItemType::Food)
+ return isList2Empty() || countItems(PouchItemType::Food, true) + n > NumFoodMax;
+
+ if (type == PouchItemType::Material)
+ return isList2Empty() || countItems(PouchItemType::Material) + n > NumMaterialsMax;
+
+ if (type == PouchItemType::KeyItem)
+ return isList2Empty() || countItems(PouchItemType::KeyItem) + n > NumKeyItemsMax;
+
+ return isList2Empty() || countItems(PouchItemType::ArmorHead) + n > NumArmorsMax;
+}
+
PouchItemType PauseMenuDataMgr::getType(const sead::SafeString& item, al::ByamlIter* iter) {
sead::SafeString group;
getSameGroupActorName(&group, item, iter);
@@ -266,6 +338,42 @@ PouchItemType PauseMenuDataMgr::getType(const sead::SafeString& item, al::ByamlI
return PouchItemType::Material;
}
+bool PauseMenuDataMgr::hasFreeSpaceForItem(const PauseMenuDataMgr::Lists& lists,
+ const sead::SafeString& name, int n) const {
+ sead::SafeString group_name;
+ getSameGroupActorName(&group_name, name);
+
+ const int count = getItemCount(group_name);
+ const bool is_arrow =
+ ksys::act::InfoData::instance()->hasTag(name.cstr(), ksys::act::tags::Arrow);
+
+ if (count == 0 && is_arrow) {
+ for (const auto& item : lists.list1) {
+ if (item.getType() == PouchItemType::Arrow && group_name == item.getName())
+ return true;
+ }
+
+ return countItems(PouchItemType::Arrow) < NumArrowItemsMax;
+ }
+
+ if (count == 0) {
+ const auto type = getType(name);
+
+ if (type == PouchItemType::Food)
+ return !lists.list2.isEmpty() && countItems(PouchItemType::Food, true) < NumFoodMax;
+
+ if (type == PouchItemType::Material)
+ return !lists.list2.isEmpty() && countItems(PouchItemType::Material) < NumMaterialsMax;
+
+ if (type == PouchItemType::KeyItem)
+ return !lists.list2.isEmpty() && countItems(PouchItemType::KeyItem) < NumKeyItemsMax;
+
+ return false;
+ }
+
+ return count + n <= ItemStackSizeMax;
+}
+
int PauseMenuDataMgr::countItems(PouchItemType type, bool count_any_weapon) const {
if (isPouchItemInvalid(type) || getItems().isEmpty())
return 0;
@@ -780,7 +888,7 @@ bool PauseMenuDataMgr::isOverCategoryLimit(PouchItemType type) const {
case PouchItemType::Bow:
return ksys::gdt::getFlag_BowPorchStockNum() <= count || count >= NumBowsMax;
case PouchItemType::Arrow:
- return count >= NumArrowsMax;
+ return count >= NumArrowItemsMax;
case PouchItemType::Shield:
return ksys::gdt::getFlag_ShieldPorchStockNum() <= count || count >= NumShieldsMax;
case PouchItemType::ArmorHead:
diff --git a/src/Game/UI/uiPauseMenuDataMgr.h b/src/Game/UI/uiPauseMenuDataMgr.h
index bc18b523..1e4525dc 100644
--- a/src/Game/UI/uiPauseMenuDataMgr.h
+++ b/src/Game/UI/uiPauseMenuDataMgr.h
@@ -23,18 +23,20 @@ namespace uking::ui {
constexpr int NumWeaponsMax = 20;
constexpr int NumBowsMax = 14;
-constexpr int NumArrowsMax = 6;
+constexpr int NumArrowItemsMax = 6;
constexpr int NumShieldsMax = 20;
constexpr int NumArmorsMax = 100;
constexpr int NumMaterialsMax = 160;
constexpr int NumFoodMax = 60;
constexpr int NumKeyItemsMax = 40;
-constexpr int NumPouchItemsMax = NumWeaponsMax + NumBowsMax + NumArrowsMax + NumShieldsMax +
+constexpr int NumPouchItemsMax = NumWeaponsMax + NumBowsMax + NumArrowItemsMax + NumShieldsMax +
NumArmorsMax + NumMaterialsMax + NumFoodMax + NumKeyItemsMax;
static_assert(NumPouchItemsMax == 420, "NumPouchItemsMax must be 420 for now");
+constexpr int ItemStackSizeMax = 999;
+
// TODO: figure out what this is
constexpr int NumPouch50 = 50;
@@ -172,6 +174,9 @@ class PauseMenuDataMgr {
public:
void init(sead::Heap* heap);
void initForNewSave();
+ void loadFromGameData();
+
+ bool cannotGetItem(const sead::SafeString& name, int n) const;
static PouchItemType getType(const sead::SafeString& item, al::ByamlIter* iter = nullptr);
@@ -241,8 +246,13 @@ private:
PouchItem** getItemHeadp(PouchCategory category) const { return mListHeads[u32(category)]; }
PouchItem* nextItem(const PouchItem* item) const { return getItems().next(item); }
+ bool isList2Empty() const { return mItemLists.list2.isEmpty(); }
void resetItem();
+ void doLoadFromGameData();
+ void updateInventoryInfo(const sead::OffsetList<PouchItem>& list);
+
+ bool hasFreeSpaceForItem(const Lists& lists, const sead::SafeString& name, int n = 1) const;
/// @param num_cleared_beasts The number of divine beasts that have been done.
void updateDivineBeastClearFlags(int num_cleared_beasts);