summaryrefslogtreecommitdiff
path: root/src/Game/UI
diff options
context:
space:
mode:
authorLéo Lam <leo@leolam.fr>2021-01-22 11:57:44 +0100
committerLéo Lam <leo@leolam.fr>2021-01-22 12:35:54 +0100
commitbb3f05e209e23d4497505e660d3a9b5995d34895 (patch)
treebf173dbd561620455f7ea6e935b06081482d3575 /src/Game/UI
parentd9f7561588b99a6b90315541e39dcf32371edd01 (diff)
uking/ui: Implement weapon and bow sorting in inventory
Diffstat (limited to 'src/Game/UI')
-rw-r--r--src/Game/UI/uiPauseMenuDataMgr.cpp88
-rw-r--r--src/Game/UI/uiPauseMenuDataMgr.h3
-rw-r--r--src/Game/UI/uiUtils.h12
3 files changed, 93 insertions, 10 deletions
diff --git a/src/Game/UI/uiPauseMenuDataMgr.cpp b/src/Game/UI/uiPauseMenuDataMgr.cpp
index 9628eee6..678e5484 100644
--- a/src/Game/UI/uiPauseMenuDataMgr.cpp
+++ b/src/Game/UI/uiPauseMenuDataMgr.cpp
@@ -204,6 +204,19 @@ int getFoodSortKey(int* effect_value, const PouchItem* item) {
}
}
+int getWeaponPowerSortValue(const PouchItem* item, ksys::act::InfoData* data) {
+#ifdef MATCHING_HACK_NX_CLANG
+ __builtin_assume(data); // Force LLVM to keep data (perhaps N had an "assume not null" macro?)
+#endif
+
+ WeaponStats stats;
+ getWeaponStats(*item, &stats);
+ int value = stats.power;
+ if (item->getType() == PouchItemType::Bow && stats.bow_add_value > 1)
+ value *= stats.bow_add_value;
+ return value;
+}
+
} // namespace
int pouchItemSortPredicate(const PouchItem* lhs, const PouchItem* rhs);
@@ -230,7 +243,7 @@ PouchItem::PouchItem() {
void PauseMenuDataMgr::resetItem() {
mNewlyAddedItem.mType = PouchItemType::Invalid;
- mNewlyAddedItem._1c = -1;
+ mNewlyAddedItem.mItemUse = ItemUse::Invalid;
mNewlyAddedItem.mValue = 0;
mNewlyAddedItem.mEquipped = false;
mNewlyAddedItem._25 = 0;
@@ -1928,6 +1941,56 @@ static s32 compareSortKeys(const PouchItem* lhs, const PouchItem* rhs, ksys::act
return 0;
}
+static s32 compareItemValues(const PouchItem* lhs, const PouchItem* rhs) {
+ const int val1 = lhs->getValue();
+ const int val2 = rhs->getValue();
+ // Higher is better
+ if (val1 > val2)
+ return -1;
+ if (val1 < val2)
+ return 1;
+ return 0;
+}
+
+static int doCompareWeapon(const PouchItem* lhs, const PouchItem* rhs, ksys::act::InfoData* data) {
+ const auto use1 = lhs->getItemUse();
+ const auto use2 = rhs->getItemUse();
+ if (use1 < use2)
+ return -1;
+ if (use1 > use2)
+ return 1;
+
+ const auto power1 = getWeaponPowerSortValue(lhs, data);
+ const auto power2 = getWeaponPowerSortValue(rhs, data);
+ if (power1 > power2)
+ return -1;
+ if (power1 < power2)
+ return 1;
+
+ const auto mod1 = getWeaponModifierSortKey(lhs->getWeaponAddFlags());
+ const auto mod2 = getWeaponModifierSortKey(rhs->getWeaponAddFlags());
+ if (mod1 < mod2)
+ return -1;
+ if (mod1 > mod2)
+ return 1;
+
+ return compareItemValues(lhs, rhs);
+}
+
+static int compareWeaponType0(const PouchItem* lhs, const PouchItem* rhs,
+ ksys::act::InfoData* data) {
+ if (auto cmp = doCompareWeapon(lhs, rhs, data))
+ return cmp;
+ return compareSortKeys(lhs, rhs, data);
+}
+
+static int compareWeaponType1(const PouchItem* lhs, const PouchItem* rhs,
+ ksys::act::InfoData* data) {
+ if (auto cmp = compareSortKeys(lhs, rhs, data))
+ return cmp;
+ return doCompareWeapon(lhs, rhs, data);
+}
+
static int getShieldGuardPower(const PouchItem* item, ksys::act::InfoData* data) {
int power = ksys::act::getWeaponCommonGuardPower(data, item->getName().cstr());
if (item->getWeaponAddFlags().isOn(act::WeaponModifier::AddGuard))
@@ -1952,15 +2015,22 @@ static int doCompareShield(const PouchItem* lhs, const PouchItem* rhs, ksys::act
if (mod1 > mod2)
return 1;
- const int val1 = lhs->getValue();
- const int val2 = rhs->getValue();
- // Higher is better
- if (val1 > val2)
- return -1;
- if (val1 < val2)
- return 1;
+ return compareItemValues(lhs, rhs);
+}
- return 0;
+int compareWeapon(const PouchItem* lhs, const PouchItem* rhs, ksys::act::InfoData* data) {
+ if (ksys::gdt::getFlag_SortTypeWeaponPouch())
+ return compareWeaponType1(lhs, rhs, data);
+ return compareWeaponType0(lhs, rhs, data);
+}
+
+int compareBow(const PouchItem* lhs, const PouchItem* rhs, ksys::act::InfoData* data) {
+ if (lhs->getType() == PouchItemType::Arrow)
+ return compareSortKeys(lhs, rhs, data);
+
+ if (ksys::gdt::getFlag_SortTypeBowPouch())
+ return compareWeaponType1(lhs, rhs, data);
+ return compareWeaponType0(lhs, rhs, data);
}
int compareShield(const PouchItem* lhs, const PouchItem* rhs, ksys::act::InfoData* data) {
diff --git a/src/Game/UI/uiPauseMenuDataMgr.h b/src/Game/UI/uiPauseMenuDataMgr.h
index 95fe25e2..88c4235f 100644
--- a/src/Game/UI/uiPauseMenuDataMgr.h
+++ b/src/Game/UI/uiPauseMenuDataMgr.h
@@ -175,6 +175,7 @@ public:
bool isEquipped() const { return mEquipped; }
u8 get25() const { return _25; }
const sead::SafeString& getName() const { return mName; }
+ ItemUse getItemUse() const { return mItemUse; }
bool isWeapon() const { return getType() <= PouchItemType::Shield; }
@@ -231,7 +232,7 @@ private:
sead::ListNode mListNode;
PouchItemType mType = PouchItemType::Invalid;
- s32 _1c = -1;
+ ItemUse mItemUse = ItemUse::Invalid;
s32 mValue = 0;
bool mEquipped = false;
u8 _25 = 1;
diff --git a/src/Game/UI/uiUtils.h b/src/Game/UI/uiUtils.h
index 43460eb2..08d43994 100644
--- a/src/Game/UI/uiUtils.h
+++ b/src/Game/UI/uiUtils.h
@@ -1,15 +1,27 @@
#pragma once
#include <prim/seadSafeString.h>
+#include "Game/Actor/actWeapon.h"
namespace uking::ui {
class PouchItem;
+struct WeaponStats {
+ int durability{};
+ /// Attack power (for offensive weapons) or guard power (for shields).
+ int power{};
+ act::WeaponModifierInfo modifier{};
+ /// Bow modifier value ("add value") or 0 for weapons that are not bows.
+ int bow_add_value{};
+};
+
bool isMasterSwordItem(const PouchItem& item);
int getItemHitPointRecover(const sead::SafeString& name);
+void getWeaponStats(const PouchItem& item, WeaponStats* stats);
+
int getWeaponInventoryLife(const sead::SafeString& name);
bool isMasterSwordActorName(const sead::SafeString& name);