summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Game/Actor/CMakeLists.txt2
-rw-r--r--src/Game/Actor/actCreatePlayerEquipActorMgr.cpp121
-rw-r--r--src/Game/Actor/actCreatePlayerEquipActorMgr.h51
-rw-r--r--src/Game/UI/uiPauseMenuDataMgr.cpp68
-rw-r--r--src/Game/UI/uiPauseMenuDataMgr.h3
5 files changed, 244 insertions, 1 deletions
diff --git a/src/Game/Actor/CMakeLists.txt b/src/Game/Actor/CMakeLists.txt
index a1f3d648..34fec1a6 100644
--- a/src/Game/Actor/CMakeLists.txt
+++ b/src/Game/Actor/CMakeLists.txt
@@ -1,4 +1,6 @@
target_sources(uking PRIVATE
+ actCreatePlayerEquipActorMgr.cpp
+ actCreatePlayerEquipActorMgr.h
actDragon.cpp
actDragon.h
actWeapon.cpp
diff --git a/src/Game/Actor/actCreatePlayerEquipActorMgr.cpp b/src/Game/Actor/actCreatePlayerEquipActorMgr.cpp
new file mode 100644
index 00000000..b9cccf34
--- /dev/null
+++ b/src/Game/Actor/actCreatePlayerEquipActorMgr.cpp
@@ -0,0 +1,121 @@
+#include "Game/Actor/actCreatePlayerEquipActorMgr.h"
+#include <prim/seadStringBuilder.h>
+#include "Game/Actor/actWeapon.h"
+#include "Game/UI/uiPauseMenuDataMgr.h"
+#include "KingSystem/ActorSystem/actInfoCommon.h"
+#include "KingSystem/ActorSystem/actInfoData.h"
+
+namespace uking::act {
+
+SEAD_SINGLETON_DISPOSER_IMPL(CreatePlayerEquipActorMgr)
+
+void CreatePlayerEquipActorMgr::requestCreateDefaultArmor(s32 slot,
+ const sead::SafeString& caller) {
+ switch (slot) {
+ case (int)CreateEquipmentSlot::ArmorHead:
+ doRequestCreateArmor(3, "Armor_Default_Head", -1, caller);
+ break;
+ case (int)CreateEquipmentSlot::ArmorUpper:
+ doRequestCreateArmor(4, "Armor_Default_Upper", -1, caller);
+ break;
+ case (int)CreateEquipmentSlot::ArmorLower:
+ doRequestCreateArmor(5, "Armor_Default_Lower", -1, caller);
+ break;
+ default:
+ break;
+ }
+}
+
+void CreatePlayerEquipActorMgr::requestCreateArmorHeadB(const sead::SafeString& name, int dye_color,
+ const sead::SafeString& caller) {
+ sead::FixedStringBuilder<0x40> s;
+ s.copy(name.cstr());
+ s.append("_B", -1);
+ doRequestCreateArmor((int)CreateEquipmentSlot::ArmorHead, s, dye_color, caller);
+}
+
+bool needsArmorHeadB(const sead::SafeString& armor_head_name,
+ const sead::SafeString& armor_upper_name) {
+ if (armor_upper_name.isEmpty()) {
+ return false;
+ }
+ if (!ksys::act::InfoData::instance() ||
+ ksys::act::getArmorHeadMantleType(ksys::act::InfoData::instance(),
+ armor_head_name.cstr()) != 2) {
+ return false;
+ }
+ if (!ksys::act::InfoData::instance() ||
+ ksys::act::getArmorUpperUseMantleType(ksys::act::InfoData::instance(),
+ armor_upper_name.cstr()) == 0) {
+ return false;
+ }
+ return true;
+}
+
+CreateEquipmentSlot getCreateEquipmentSlot(ui::PouchItemType type) {
+ switch (type) {
+ case ui::PouchItemType::Sword:
+ return CreateEquipmentSlot::WeaponSword;
+ case ui::PouchItemType::Bow:
+ return CreateEquipmentSlot::WeaponBow;
+ case ui::PouchItemType::Shield:
+ return CreateEquipmentSlot::WeaponShield;
+ case ui::PouchItemType::ArmorHead:
+ return CreateEquipmentSlot::ArmorHead;
+ case ui::PouchItemType::ArmorUpper:
+ return CreateEquipmentSlot::ArmorUpper;
+ case ui::PouchItemType::ArmorLower:
+ return CreateEquipmentSlot::ArmorLower;
+ default:
+ return CreateEquipmentSlot::Length;
+ }
+}
+
+ui::EquipmentSlot getEquipmentSlot(CreateEquipmentSlot slot) {
+ switch (slot) {
+ case CreateEquipmentSlot::WeaponSword:
+ return ui::EquipmentSlot::WeaponRight;
+ case CreateEquipmentSlot::WeaponShield:
+ return ui::EquipmentSlot::WeaponLeft;
+ case CreateEquipmentSlot::WeaponBow:
+ return ui::EquipmentSlot::WeaponBow;
+ case CreateEquipmentSlot::ArmorHead:
+ return ui::EquipmentSlot::ArmorHead;
+ case CreateEquipmentSlot::ArmorUpper:
+ return ui::EquipmentSlot::ArmorUpper;
+ case CreateEquipmentSlot::ArmorLower:
+ return ui::EquipmentSlot::ArmorLower;
+ default:
+ return ui::EquipmentSlot::Invalid;
+ }
+}
+
+bool createEquipmentFromItem(const ui::PouchItem* item, const sead::SafeString& caller) {
+ if (!item) {
+ return false;
+ }
+
+ auto* mgr = CreatePlayerEquipActorMgr::instance();
+ if (!mgr) {
+ return false;
+ }
+
+ auto type = item->getType();
+ auto slot = getCreateEquipmentSlot(type);
+ int slot_idx = (int)slot;
+
+ if (slot <= CreateEquipmentSlot::WeaponBow) {
+ WeaponModifierInfo modifier(*item);
+ mgr->doRequestCreateWeapon(slot_idx, item->getName(), item->getValue(), &modifier, caller);
+ return true;
+ }
+
+ if (slot <= CreateEquipmentSlot::ArmorLower) {
+ mgr->doRequestCreateArmor(slot_idx, item->getName(), item->getValue(), caller);
+ return true;
+ }
+
+ return false;
+}
+
+} // namespace uking::act
diff --git a/src/Game/Actor/actCreatePlayerEquipActorMgr.h b/src/Game/Actor/actCreatePlayerEquipActorMgr.h
new file mode 100644
index 00000000..832de3cc
--- /dev/null
+++ b/src/Game/Actor/actCreatePlayerEquipActorMgr.h
@@ -0,0 +1,51 @@
+#pragma once
+
+#include <heap/seadDisposer.h>
+#include <prim/seadSafeString.h>
+namespace uking::ui {
+
+class PouchItem;
+enum class PouchItemType;
+enum class EquipmentSlot;
+
+} // namespace uking::ui
+
+namespace uking::act {
+struct WeaponModifierInfo;
+
+enum class CreateEquipmentSlot : u8 {
+ WeaponSword = 0,
+ WeaponShield = 1,
+ WeaponBow = 2,
+ ArmorHead = 3,
+ ArmorUpper = 4,
+ ArmorLower = 5,
+ Length = 6,
+};
+
+class CreatePlayerEquipActorMgr {
+ SEAD_SINGLETON_DISPOSER(CreatePlayerEquipActorMgr)
+ CreatePlayerEquipActorMgr();
+ virtual ~CreatePlayerEquipActorMgr();
+
+public:
+ // TODO 0x71006669F8
+ void doRequestCreateWeapon(int slot_idx, const sead::SafeString& name, int value,
+ const WeaponModifierInfo* modifier, const sead::SafeString& caller);
+
+ // TODO 0x7100666CF8
+ void doRequestCreateArmor(int slot_idx, const sead::SafeString& name, int dye_color,
+ const sead::SafeString& caller);
+
+ void requestCreateDefaultArmor(s32 slot_idx, const sead::SafeString& caller);
+ void requestCreateArmorHeadB(const sead::SafeString& name, int dye_color,
+ const sead::SafeString& caller);
+};
+
+bool needsArmorHeadB(const sead::SafeString& armor_head_name,
+ const sead::SafeString& armor_upper_name);
+CreateEquipmentSlot getCreateEquipmentSlot(ui::PouchItemType type);
+ui::EquipmentSlot getEquipmentSlot(CreateEquipmentSlot slot);
+bool createEquipmentFromItem(const ui::PouchItem* item, const sead::SafeString& caller);
+
+} // namespace uking::act
diff --git a/src/Game/UI/uiPauseMenuDataMgr.cpp b/src/Game/UI/uiPauseMenuDataMgr.cpp
index 11e6dc93..6c591237 100644
--- a/src/Game/UI/uiPauseMenuDataMgr.cpp
+++ b/src/Game/UI/uiPauseMenuDataMgr.cpp
@@ -4,6 +4,7 @@
#include <limits>
#include <math/seadMathCalcCommon.h>
#include <prim/seadScopedLock.h>
+#include "Game/Actor/actCreatePlayerEquipActorMgr.h"
#include "Game/Actor/actWeapon.h"
#include "Game/Cooking/cookManager.h"
#include "Game/DLC/aocManager.h"
@@ -1269,6 +1270,71 @@ int PauseMenuDataMgr::getItemCount(const sead::SafeString& name, bool count_equi
return count;
}
+void PauseMenuDataMgr::createPlayerEquipment() {
+ constexpr const char* Caller = "PauseMenuDataMgr_FromSaveData";
+ const auto lock = sead::makeScopedLock(mCritSection);
+
+ auto* create_mgr = act::CreatePlayerEquipActorMgr::instance();
+ if (!create_mgr) {
+ return;
+ }
+
+ std::array<PouchItem*, (u64)act::CreateEquipmentSlot::Length> equipment_items{};
+
+ const auto& items = getItems();
+ PouchItem* item = items.isEmpty() ? nullptr : items.nth(0);
+
+ bool need_head_b = false;
+ if (item) {
+ for (; item; item = items.next(item)) {
+ auto type = item->getType();
+ if (type > PouchItemType::Material) {
+ break;
+ }
+ if (item->isInInventory() && item->isEquipped()) {
+ u64 slot = (u64)act::getCreateEquipmentSlot(type);
+ if (slot < equipment_items.size()) {
+ equipment_items[slot] = item;
+ }
+ }
+ }
+ const auto* head = equipment_items[(u64)act::CreateEquipmentSlot::ArmorHead];
+ if (head && equipment_items[(u64)act::CreateEquipmentSlot::ArmorUpper]) {
+ need_head_b = act::needsArmorHeadB(
+ head->getName(),
+ equipment_items[(u64)act::CreateEquipmentSlot::ArmorUpper]->getName());
+ }
+ }
+
+ auto* player = ksys::act::PlayerInfo::instance()->getPlayer();
+
+ s32 slot = 0; // <- this is required to match
+ for (u64 i = 0; i != equipment_items.size(); slot = s32(++i)) {
+ if (equipment_items[i]) {
+ if (!need_head_b || i != (u64)act::CreateEquipmentSlot::ArmorHead) {
+ act::createEquipmentFromItem(equipment_items[i], Caller);
+ } else {
+ create_mgr->requestCreateArmorHeadB(equipment_items[i]->getName(),
+ equipment_items[i]->getValue(), Caller);
+ }
+ continue;
+ }
+ if (i > (u64)act::CreateEquipmentSlot::WeaponBow) {
+ create_mgr->requestCreateDefaultArmor(slot, Caller);
+ continue;
+ }
+
+ if (player) {
+ auto equipment_slot = getEquipmentSlot((act::CreateEquipmentSlot)i);
+ player->switchEquipment(getDefaultEquipment(equipment_slot), 30);
+ }
+
+#ifdef MATCHING_HACK_NX_CLANG
+ asm(""); // force no unroll
+#endif
+ }
+}
+
void PauseMenuDataMgr::setEquippedWeaponItemValue(s32 value, PouchItemType type) {
if (isPouchItemNotWeapon(type))
return;
@@ -1294,7 +1360,7 @@ void PauseMenuDataMgr::setEquippedWeaponItemValue(s32 value, PouchItemType type)
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 sValues.default_equipment_names(s32(idx));
}
return sead::SafeString::cEmptyString;
}
diff --git a/src/Game/UI/uiPauseMenuDataMgr.h b/src/Game/UI/uiPauseMenuDataMgr.h
index 422dadf3..fd2efb30 100644
--- a/src/Game/UI/uiPauseMenuDataMgr.h
+++ b/src/Game/UI/uiPauseMenuDataMgr.h
@@ -34,6 +34,8 @@ struct CookItem;
namespace uking::ui {
+enum class CreateEquipmentSlot : u8;
+
constexpr int NumSwordsMax = 20;
constexpr int NumBowsMax = 14;
constexpr int NumArrowItemsMax = 6;
@@ -118,6 +120,7 @@ enum class EquipmentSlot {
ArmorHead = 4,
ArmorUpper = 5,
ArmorLower = 6,
+ Invalid = -1,
};
enum class ItemUse {