From cd19e8cd9618a610766f703dfb2436fc94760912 Mon Sep 17 00:00:00 2001 From: Pistonight Date: Thu, 1 May 2025 01:07:12 -0700 Subject: [PATCH] PauseMenuDataMgr createPlayerEquipment --- data/data_symbols.csv | 1 + data/uking_functions.csv | 26 ++-- src/Game/Actor/CMakeLists.txt | 2 + .../Actor/actCreatePlayerEquipActorMgr.cpp | 121 ++++++++++++++++++ src/Game/Actor/actCreatePlayerEquipActorMgr.h | 51 ++++++++ src/Game/UI/uiPauseMenuDataMgr.cpp | 68 +++++++++- src/Game/UI/uiPauseMenuDataMgr.h | 3 + 7 files changed, 258 insertions(+), 14 deletions(-) create mode 100644 src/Game/Actor/actCreatePlayerEquipActorMgr.cpp create mode 100644 src/Game/Actor/actCreatePlayerEquipActorMgr.h diff --git a/data/data_symbols.csv b/data/data_symbols.csv index cd3bb820..3b6afbba 100644 --- a/data/data_symbols.csv +++ b/data/data_symbols.csv @@ -26,6 +26,7 @@ 0x00000071024D8D58,_ZTVN4ksys3act2ai10ActionBaseE 0x00000071025129E0,_ZTVN4ksys3act2ai6ActionE 0x0000007102513268,_ZTVN4ksys3act2ai2AiE +0x00000071025C5A20,_ZN5uking3act25CreatePlayerEquipActorMgr9sInstanceE 0x00000071025CDB60,_ZN4ksys3act10PlayerInfo9sInstanceE 0x00000071025D0878,_ZN5uking10CookingMgr9sInstanceE 0x00000071025D75B8,_ZN5uking2ui16PauseMenuDataMgr9sInstanceE diff --git a/data/uking_functions.csv b/data/uking_functions.csv index f8a15783..215d527a 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -39993,28 +39993,28 @@ Address,Quality,Size,Name 0x0000007100665b20,U,000068, 0x0000007100665b64,U,000488, 0x0000007100665d4c,W,000100,_ZN4sead10GameConfig18SingletonDisposer_D1Ev -0x0000007100665db0,U,000108, +0x0000007100665db0,U,000108,CreatePlayerEquipActorMgr::deleteInstance 0x0000007100665e1c,U,000136,CreatePlayerEquipActorMgr::createInstance -0x0000007100665ea4,U,000172, +0x0000007100665ea4,O,000172,_ZN5uking3act15needsArmorHeadBERKN4sead14SafeStringBaseIcEES5_ 0x0000007100665f50,U,000088, 0x0000007100665fa8,U,000088, 0x0000007100666000,U,000556,CreatePlayerEquipActorMgr::ctor -0x000000710066622c,U,000152, +0x000000710066622c,U,000152,CreatePlayerEquipActorMgr::dtor 0x00000071006662c4,U,000004,nullsub_2163 0x00000071006662c8,U,000036, 0x00000071006662ec,U,000296, 0x0000007100666414,U,000412,CreatePlayerEquipActorMgr::postCalc -0x00000071006665b0,U,000172,CreatePlayerEquipActorMgr::__auto1 -0x000000710066665c,U,000140, +0x00000071006665b0,U,000172,CreatePlayerEquipActorMgr::resetAllEquipmentLoading +0x000000710066665c,U,000140,CreatePlayerEquipActorMgr::resetEquipmentLoading 0x00000071006666e8,U,000272,CreatePlayerEquipActorMgr::playerEquipmentActorsReady -0x00000071006667f8,U,000068,CreatePlayerEquipActorMgr::__auto2 -0x000000710066683c,U,000444, +0x00000071006667f8,U,000068,CreatePlayerEquipActorMgr::isEquipmentProcReady +0x000000710066683c,U,000444,CreatePlayerEquipActorMgr::wakeEquipment 0x00000071006669f8,U,000408,CreatePlayerEquipActorMgr::requestCreateWeapon 0x0000007100666b90,U,000360,CreatePlayerEquipActorMgr::requestCreateWeaponCaller 0x0000007100666cf8,U,000688,CreatePlayerEquipActorMgr::requestCreateArmor 0x0000007100666fa8,U,000352,CreatePlayerEquipActorMgr::requestCreateArmorWrap -0x0000007100667108,U,000180,PauseMenuDataMgr::switchPlayerArmorToDefault -0x00000071006671bc,U,000192,CreatePlayerEquipActorMgr::x +0x0000007100667108,O,000180,_ZN5uking3act25CreatePlayerEquipActorMgr25requestCreateDefaultArmorEiRKN4sead14SafeStringBaseIcEE +0x00000071006671bc,O,000192,_ZN5uking3act25CreatePlayerEquipActorMgr23requestCreateArmorHeadBERKN4sead14SafeStringBaseIcEEiS6_ 0x000000710066727c,U,000004,j__ZdlPv_287 0x0000007100667280,U,000324, 0x00000071006673c4,U,000100,_ZN4sead17PrimitiveRenderer18SingletonDisposer_D1Ev @@ -56396,7 +56396,7 @@ Address,Quality,Size,Name 0x0000007100970d84,O,000512,_ZN5uking2ui16PauseMenuDataMgr11removeArrowERKN4sead14SafeStringBaseIcEEi 0x0000007100970f84,M,001204,_ZNK5uking2ui16PauseMenuDataMgr12getItemCountERKN4sead14SafeStringBaseIcEEb 0x0000007100971438,O,000204,_ZN5uking2ui16PauseMenuDataMgr26setEquippedWeaponItemValueEiNS0_13PouchItemTypeE -0x0000007100971504,U,000716,PauseMenuDataMgr::fromSaveDataMaybe +0x0000007100971504,O,000716,_ZN5uking2ui16PauseMenuDataMgr21createPlayerEquipmentEv 0x00000071009717d0,O,000040,_ZNK5uking2ui16PauseMenuDataMgr19getDefaultEquipmentENS0_13EquipmentSlotE 0x00000071009717f8,O,000404,_ZNK5uking2ui16PauseMenuDataMgr7hasItemERKN4sead14SafeStringBaseIcEE 0x000000710097198c,O,000372,_ZNK5uking2ui16PauseMenuDataMgr14getMasterSwordEv @@ -61787,9 +61787,9 @@ Address,Quality,Size,Name 0x0000007100aa814c,U,000008,setColorChangeMaterialIndex 0x0000007100aa8154,U,000012, 0x0000007100aa8160,U,000008, -0x0000007100aa8168,U,000048, -0x0000007100aa8198,U,000040, -0x0000007100aa81c0,U,000212, +0x0000007100aa8168,O,000048,_ZN5uking3act22getCreateEquipmentSlotENS_2ui13PouchItemTypeE +0x0000007100aa8198,O,000040,_ZN5uking3act16getEquipmentSlotENS0_19CreateEquipmentSlotE +0x0000007100aa81c0,O,000212,_ZN5uking3act23createEquipmentFromItemEPKNS_2ui9PouchItemERKN4sead14SafeStringBaseIcEE 0x0000007100aa8294,U,000028, 0x0000007100aa82b0,U,000132,trashPouchItem 0x0000007100aa8334,U,000028, 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 +#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 +#include +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 #include #include +#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 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 {