diff options
| author | Léo Lam <leo@leolam.fr> | 2025-06-22 23:48:19 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-06-22 23:48:19 +0200 |
| commit | 5dda15014c0ae35c31b7b0dc6c56c828752baba1 (patch) | |
| tree | 3db6e21a0025e9a0b20d88199e781c95c7947878 /src/Game | |
| parent | 71530ca9b1b9a5d974f28a97ebe52ae8b29c208f (diff) | |
| parent | 3d920314042fc84ccffc5f4b503e85e3b77fc4a2 (diff) | |
Merge pull request #141 from Pistonight/cpeam
CreatePlayerEquipActorMgr
Diffstat (limited to 'src/Game')
| -rw-r--r-- | src/Game/Actor/CMakeLists.txt | 8 | ||||
| -rw-r--r-- | src/Game/Actor/actCreatePlayerEquipActorMgr.cpp | 121 | ||||
| -rw-r--r-- | src/Game/Actor/actCreatePlayerEquipActorMgr.h | 51 | ||||
| -rw-r--r-- | src/Game/Actor/actPlayerCreateMgr.cpp | 321 | ||||
| -rw-r--r-- | src/Game/Actor/actPlayerCreateMgr.h | 151 | ||||
| -rw-r--r-- | src/Game/Actor/actPlayerCreateTrace.cpp | 22 | ||||
| -rw-r--r-- | src/Game/Actor/actPlayerCreateTrace.h | 49 | ||||
| -rw-r--r-- | src/Game/Actor/actPlayerCreateUtils.cpp | 25 | ||||
| -rw-r--r-- | src/Game/Actor/actPlayerCreateUtils.h | 28 | ||||
| -rw-r--r-- | src/Game/UI/uiPauseMenuDataMgr.cpp | 7 | ||||
| -rw-r--r-- | src/Game/UI/uiUtils.cpp | 67 | ||||
| -rw-r--r-- | src/Game/UI/uiUtils.h | 10 |
12 files changed, 683 insertions, 177 deletions
diff --git a/src/Game/Actor/CMakeLists.txt b/src/Game/Actor/CMakeLists.txt index 34fec1a6..a391c4be 100644 --- a/src/Game/Actor/CMakeLists.txt +++ b/src/Game/Actor/CMakeLists.txt @@ -1,8 +1,12 @@ target_sources(uking PRIVATE - actCreatePlayerEquipActorMgr.cpp - actCreatePlayerEquipActorMgr.h actDragon.cpp actDragon.h + actPlayerCreateMgr.cpp + actPlayerCreateMgr.h + actPlayerCreateTrace.cpp + actPlayerCreateTrace.h + actPlayerCreateUtils.cpp + actPlayerCreateUtils.h actWeapon.cpp actWeapon.h ) diff --git a/src/Game/Actor/actCreatePlayerEquipActorMgr.cpp b/src/Game/Actor/actCreatePlayerEquipActorMgr.cpp deleted file mode 100644 index b9cccf34..00000000 --- a/src/Game/Actor/actCreatePlayerEquipActorMgr.cpp +++ /dev/null @@ -1,121 +0,0 @@ -#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 deleted file mode 100644 index 832de3cc..00000000 --- a/src/Game/Actor/actCreatePlayerEquipActorMgr.h +++ /dev/null @@ -1,51 +0,0 @@ -#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/Actor/actPlayerCreateMgr.cpp b/src/Game/Actor/actPlayerCreateMgr.cpp new file mode 100644 index 00000000..f573f245 --- /dev/null +++ b/src/Game/Actor/actPlayerCreateMgr.cpp @@ -0,0 +1,321 @@ +#include "Game/Actor/actPlayerCreateMgr.h" +#include <prim/seadRuntimeTypeInfo.h> +#include <prim/seadStringBuilder.h> +#include "Game/Actor/actPlayerCreateUtils.h" +#include "Game/Actor/actWeapon.h" +#include "Game/UI/uiPauseMenuDataMgr.h" +#include "KingSystem/ActorSystem/Profiles/actPlayerBase.h" +#include "KingSystem/ActorSystem/Profiles/actWeaponBase.h" +#include "KingSystem/ActorSystem/actActorConstDataAccess.h" +#include "KingSystem/ActorSystem/actActorCreator.h" +#include "KingSystem/ActorSystem/actActorHeapUtil.h" +#include "KingSystem/ActorSystem/actActorLinkConstDataAccess.h" +#include "KingSystem/ActorSystem/actInfoCommon.h" +#include "KingSystem/ActorSystem/actInfoData.h" +#include "KingSystem/ActorSystem/actInstParamPack.h" +#include "KingSystem/ActorSystem/actPlayerInfo.h" +#include "KingSystem/GameData/gdtCommonFlagsUtils.h" + +namespace uking::act { + +void PlayerCreateDebugStub::init() { + struct MsgStub { + sead::SafeString msg; + u64 unused{}; + } stub{}; + stub.msg = "読み込み中デバッグボード"; // Loading Debug Board + _0 = 3; + mDebugStatus = "◎読み込み中◎"; // Loading + _18 = 0.9; + _1c = 0; + mColor20 = {1.0f, 1.0f, 1.0f, 1.0f}; + mColor30 = {0.2f, 0.2f, 0.2f, 1.0f}; + _40.set(1.8, 0); + _48.set(198.638428, 34.742115); + mColor50 = {0.0f, 0.8f, 0.8f, 0.3f}; + _60 = 0; + _68 = 0; + _70 = 0; + _78 = {-506.679992, -256.519989, 0}; + mColor84 = {0.0f, 0.0f, 0.0f, 1.0f}; +} + +SEAD_SINGLETON_DISPOSER_IMPL(CreatePlayerEquipActorMgr) + +CreatePlayerEquipActorMgr::CreatePlayerEquipActorMgr() { + mTracer.init("CreatePlayerEquipActorMgr"); +} + +CreatePlayerEquipActorMgr::~CreatePlayerEquipActorMgr() { + mTracer.finish(); +} + +void CreatePlayerEquipActorMgr::init() { + mDebugStub.init(); +} + +// NON_MATCHING single reorder +void CreatePlayerEquipActorMgr::postCalc() { + if (mIsLoading.isZero()) { + // nothing is loading + return; + } + auto* handle = &mProcHandles[0]; + for (s32 i = 0; i < (s32)CreateEquipmentSlot::Length; ++i, ++handle) { + if (!isSlotLoading(i)) { + continue; + } + if (handle->hasProcCreationFailed()) { + handle->isProcCreationCancelled(); + handle->deleteProc(); + mEntries[i].reset(); + mIsLoading.resetBit(i); + continue; + } + + if (handle->isProcReady()) { + if (isArmorCreateEquipmentSlot(i)) { + auto* actor = sead::DynamicCast<ksys::act::Actor>(handle->releaseAndWakeProc()); + mEntries[i].mProcLink.acquire(actor, false); + } + mEntries[i].mStatus = EntryStatus::Ready; + } + } +} + +void CreatePlayerEquipActorMgr::resetAll() { + for (s32 i = 0; i < (s32)CreateEquipmentSlot::Length; ++i) { + reset(i); + } + mIsLoading.makeAllZero(); +} + +void CreatePlayerEquipActorMgr::reset(s32 slot_idx) { + auto& handle = mProcHandles[slot_idx]; + if (handle.isAllocatedOrFailed()) { + handle.deleteProc(); + } + mIsLoading.resetBit(slot_idx); + mEntries[slot_idx].reset(); +} + +bool CreatePlayerEquipActorMgr::areAllWeaponActorsReady() const { + if (mIsLoading.isZero()) { + return true; + } + auto* handle = &mProcHandles[0]; + for (u32 i = 0; i < (u32)CreateEquipmentSlot::Length; ++i, ++handle) { + if (isSlotLoading((s32)i)) { + return false; + } + auto* weapon = sead::DynamicCast<ksys::act::WeaponBase>(handle->getProc()); + if (weapon && !weapon->areExtraActorsReady()) { + return false; + } + } + return true; +} + +bool CreatePlayerEquipActorMgr::isEquipmentProcReady(s32 slot_idx) const { + const auto& entry = mEntries[slot_idx]; + if (entry.mStatus != EntryStatus::Ready) { + return false; + } + const auto& handle = mProcHandles[slot_idx]; + if (handle.isAllocatedOrFailed()) { + return handle.isProcReady(); + } + return false; +} + +ksys::act::Actor* CreatePlayerEquipActorMgr::tryGetEquipmentActor(s32 slot_idx) { + if (mEntries[slot_idx].mStatus != EntryStatus::Ready) { + return nullptr; + } + auto& handle = mProcHandles[slot_idx]; + if (handle.isAllocatedOrFailed()) { + if (handle.isProcReady()) { + auto* actor = sead::DynamicCast<ksys::act::Actor>(handle.releaseAndWakeProc()); + mEntries[slot_idx].mProcLink.acquire(actor, false); + } + } + + auto* actor = + sead::DynamicCast<ksys::act::Actor>(mEntries[slot_idx].mProcLink.getProc(nullptr, nullptr)); + + mEntries[slot_idx].reset(); + + return actor; +} + +void CreatePlayerEquipActorMgr::requestCreateWeapon(s32 slot_idx, const sead::SafeString& name, + int value, const WeaponModifierInfo* modifier, + const sead::SafeString& caller) { + auto scope = mTracer.trace()->makeScope("requestCreateWeapon", caller, 1); + + deleteLoadingProc(slot_idx); + auto* player = ksys::act::PlayerInfo::instance()->getPlayer(); + + sead::Matrix34f pos; + pos.makeT(player->getMtx().getTranslation()); + + requestCreateWeaponByRawLife(name.cstr(), pos, 1.0, + ksys::act::ActorHeapUtil::instance()->getBaseProcHeap(), + &mProcHandles[slot_idx], value, false, modifier, 2, 2); + + onSlotLoadingRequested(slot_idx, name); +} + +void CreatePlayerEquipActorMgr::requestCreateWeapon(const sead::SafeString& name, int value, + const WeaponModifierInfo* modifier, + const sead::SafeString& caller) { + auto scope = mTracer.trace()->makeScope("requestCreateWeapon", caller, 1); + auto* info_data = ksys::act::InfoData::instance(); + if (!info_data) { + return; + } + const char* profile_raw; + if (!info_data->getActorProfile(&profile_raw, name.cstr())) { + return; + } + sead::SafeString profile = profile_raw; + auto slot = CreateEquipmentSlot::WeaponSword; + if (profile == "WeaponBow") { + slot = CreateEquipmentSlot::WeaponBow; + } else if (profile == "WeaponShield") { + slot = CreateEquipmentSlot::WeaponShield; + } + + requestCreateWeapon((s32)slot, name, value, modifier, caller); +} + +// TODO: initialized in sInitArmorStrings (0x7100E2D0F0) +// find a better place to put these +// NOLINTNEXTLINE(misc-use-internal-linkage) doesn't match with static +sead::SafeString ArmorDyeColor; // "ArmorDyeColor" +// NOLINTNEXTLINE(misc-use-internal-linkage) doesn't match with static +sead::SafeString EnableDynamicColorChange; // "EnableDynamicColorChange" + +void CreatePlayerEquipActorMgr::requestCreateArmor(s32 slot_idx, const sead::SafeString& name, + int dye_color, const sead::SafeString& caller) { + auto scope = mTracer.trace()->makeScope("requestCreateArmor", caller, 1); + + deleteLoadingProc(slot_idx); + + ksys::act::InstParamPack params; + bool is_dye = ksys::act::InfoData::instance()->hasTag(name.cstr(), ksys::act::tags::ArmorDye); + if (is_dye) { + params->add(dye_color, ArmorDyeColor); + if (ksys::gdt::getFlag_ColorChange_EnablePreview()) { + params->add(true, EnableDynamicColorChange); + } + } + + { + ksys::act::ActorConstDataAccess access; + ksys::act::acquireActor(&ksys::act::PlayerInfo::instance()->getPlayerLink(), &access); + sead::Vector3f pos; + access.getActorMtx().getTranslation(pos); + params->addPosition(pos); + params->addResourceLane(2); + ksys::act::ActorCreator::instance()->requestCreateActor( + name.cstr(), ksys::act::ActorHeapUtil::instance()->getBaseProcHeap(), + &mProcHandles[slot_idx], ¶ms, nullptr, 2); + } + + onSlotLoadingRequested(slot_idx, name); +} + +void CreatePlayerEquipActorMgr::requestCreateArmor(const sead::SafeString& name, int dye_color, + const sead::SafeString& caller) { + auto scope = mTracer.trace()->makeScope("requestCreateArmor", caller, 1); + auto* info_data = ksys::act::InfoData::instance(); + if (!info_data) { + return; + } + const char* profile_raw; + if (!info_data->getActorProfile(&profile_raw, name.cstr())) { + return; + } + + sead::SafeString profile = profile_raw; + auto slot = CreateEquipmentSlot::ArmorHead; + if (profile == "Armor_Upper") { + slot = CreateEquipmentSlot::ArmorUpper; + } else if (profile == "Armor_Lower") { + slot = CreateEquipmentSlot::ArmorLower; + } + + requestCreateArmor((s32)slot, name, dye_color, caller); +} + +void CreatePlayerEquipActorMgr::requestCreateDefaultArmor(s32 slot, + const sead::SafeString& caller) { + switch (slot) { + case (s32)CreateEquipmentSlot::ArmorHead: + requestCreateArmor(slot, "Armor_Default_Head", -1, caller); + break; + case (s32)CreateEquipmentSlot::ArmorUpper: + requestCreateArmor(slot, "Armor_Default_Upper", -1, caller); + break; + case (s32)CreateEquipmentSlot::ArmorLower: + requestCreateArmor(slot, "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); + requestCreateArmor((s32)CreateEquipmentSlot::ArmorHead, s, dye_color, caller); +} + +bool CreatePlayerEquipActorMgr::isSlotLoading(s32 slot_idx) const { + return mIsLoading.isOnBit(slot_idx) && mEntries[slot_idx].mStatus == EntryStatus::Loading; +} + +void CreatePlayerEquipActorMgr::deleteLoadingProc(s32 slot_idx) { + if (mIsLoading.isOnBit(slot_idx)) { + mProcHandles[slot_idx].deleteProc(); + } +} + +void CreatePlayerEquipActorMgr::onSlotLoadingRequested(s32 slot_idx, const sead::SafeString& name) { + if (mProcHandles[slot_idx].isAllocatedOrFailed()) { + auto& entry = mEntries[slot_idx]; + entry.mActorName.copy(name.cstr()); + mIsLoading.setBit(slot_idx); + entry.mStatus = EntryStatus::Loading; + } +} + +bool needsArmorHeadB(const sead::SafeString& armor_head_name, + const sead::SafeString& armor_upper_name) { + if (armor_upper_name.isEmpty()) { + return false; + } + return isArmorHeadMantleType2(armor_head_name) && + isArmorUpperNotUseMantleType0(armor_upper_name); +} + +bool isArmorHeadMantleType2(const sead::SafeString& armor_head_name) { + if (!ksys::act::InfoData::instance()) { + return false; + } + return ksys::act::getArmorHeadMantleType(ksys::act::InfoData::instance(), + armor_head_name.cstr()) == 2; +} + +bool isArmorUpperNotUseMantleType0(const sead::SafeString& armor_upper_name) { + if (!ksys::act::InfoData::instance()) { + return false; + } + return ksys::act::getArmorUpperUseMantleType(ksys::act::InfoData::instance(), + armor_upper_name.cstr()) != 0; +} + +} // namespace uking::act diff --git a/src/Game/Actor/actPlayerCreateMgr.h b/src/Game/Actor/actPlayerCreateMgr.h new file mode 100644 index 00000000..f31c7304 --- /dev/null +++ b/src/Game/Actor/actPlayerCreateMgr.h @@ -0,0 +1,151 @@ +#pragma once + +#include <container/seadSafeArray.h> +#include <gfx/seadColor.h> +#include <heap/seadDisposer.h> +#include <math/seadMatrix.h> +#include <prim/seadBitFlag.h> +#include <prim/seadSafeString.h> +#include <prim/seadStringBuilder.h> +#include "Game/Actor/actPlayerCreateTrace.h" +#include "KingSystem/ActorSystem/actBaseProcHandle.h" +#include "KingSystem/ActorSystem/actBaseProcLink.h" +#include "KingSystem/System/StringBoard.h" +#include "KingSystem/Utils/Types.h" + +namespace ksys::act { +class InstParamPack; +class Actor; +} // namespace ksys::act + +namespace uking::ui { +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, +}; + +inline bool isArmorCreateEquipmentSlot(s32 slot) { + return slot == (s32)CreateEquipmentSlot::ArmorHead || + slot == (s32)CreateEquipmentSlot::ArmorUpper || + slot == (s32)CreateEquipmentSlot::ArmorLower; +} + +// Used in both CreatePlayerEquipActorMgr and CreatePlayerTrashActorMgr, +// but stubbed out other than constructor and init +class PlayerCreateDebugStub { +public: + void init(); + +private: + s32 _0 = 3; + sead::SafeString mDebugStatus; + f32 _18 = 1; + u32 _1c = 0; + sead::Color4f mColor20 = sead::Color4f::cBlack; + sead::Color4f mColor30 = sead::Color4f::cBlack; + sead::Vector2f _40{0, 0}; + sead::Vector2f _48{1, 1}; + sead::Color4f mColor50 = sead::Color4f::cBlue; + u64 _60 = 0; + u64 _68 = 0; + u64 _70 = 0; + sead::Vector3f _78{0, 0, 0}; + sead::Color4f mColor84 = sead::Color4f::cBlack; +}; +KSYS_CHECK_SIZE_NX150(PlayerCreateDebugStub, 0x98); + +class CreatePlayerEquipActorMgr { + SEAD_SINGLETON_DISPOSER(CreatePlayerEquipActorMgr) + CreatePlayerEquipActorMgr(); + virtual ~CreatePlayerEquipActorMgr(); + +public: + void init(); + void postCalc(); + void resetAll(); + void reset(s32 slot_idx); + bool areAllWeaponActorsReady() const; + bool isEquipmentProcReady(s32 slot_idx) const; + ksys::act::Actor* tryGetEquipmentActor(s32 slot_idx); + + void requestCreateWeapon(s32 slot_idx, const sead::SafeString& name, int value, + const WeaponModifierInfo* modifier, const sead::SafeString& caller); + void requestCreateWeapon(const sead::SafeString& name, int value, + const WeaponModifierInfo* modifier, const sead::SafeString& caller); + + void requestCreateArmor(s32 slot_idx, const sead::SafeString& name, int dye_color, + const sead::SafeString& caller); + void requestCreateArmor(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); + +private: + enum class EntryStatus : s32 { Idle = 0, Loading = 1, Ready = 2 }; + + template <typename T> + class Slots { + private: + sead::SafeArray<T, (s32)CreateEquipmentSlot::Length> mArray; + + public: + T& operator[](s32 idx) { return mArray[idx]; } + const T& operator[](s32 idx) const { return mArray[idx]; } + s32 size() const { return mArray.size(); } + }; + + class Entry { + friend class CreatePlayerEquipActorMgr; + sead::FixedStringBuilder<64> mActorName; + EntryStatus mStatus = EntryStatus::Idle; + ksys::act::BaseProcLink mProcLink; + + void reset() { + mActorName.clear(); + mStatus = EntryStatus::Idle; + mProcLink.reset(); + } + }; + KSYS_CHECK_SIZE_NX150(Entry, 0x68); + + // inlined helpers + bool isSlotLoading(s32 slot_idx) const; + void deleteLoadingProc(s32 slot_idx); + void onSlotLoadingRequested(s32 slot_idx, const sead::SafeString& name); + + Slots<ksys::act::BaseProcHandle> mProcHandles{}; + sead::BitFlag8 mIsLoading; + PlayerCreateTracer mTracer; + Slots<Entry> mEntries{}; + + // stubbed in release builds + ksys::StringBoard mStringBoard; + u64 _310 = 0; + + PlayerCreateDebugStub mDebugStub; +}; +KSYS_CHECK_SIZE_NX150(CreatePlayerEquipActorMgr, 0x3B0); + +// TODO +class CreatePlayerTrachActorMgr {}; + +bool needsArmorHeadB(const sead::SafeString& armor_head_name, + const sead::SafeString& armor_upper_name); +bool isArmorHeadMantleType2(const sead::SafeString& armor_head_name); +bool isArmorUpperNotUseMantleType0(const sead::SafeString& armor_upper_name); + +} // namespace uking::act diff --git a/src/Game/Actor/actPlayerCreateTrace.cpp b/src/Game/Actor/actPlayerCreateTrace.cpp new file mode 100644 index 00000000..2278e4f3 --- /dev/null +++ b/src/Game/Actor/actPlayerCreateTrace.cpp @@ -0,0 +1,22 @@ +#include "Game/Actor/actPlayerCreateTrace.h" + +namespace uking::act { + +PlayerCreateTraceScope::PlayerCreateTraceScope(PlayerCreateTrace* trace, + const sead::SafeString& name, + const sead::SafeString& caller, s32 level) { + mTrace = trace; +} + +PlayerCreateTraceScope::~PlayerCreateTraceScope() { + // force D1 to be non-trivial + ; +} + +PlayerCreateTrace* PlayerCreateTrace::make(const sead::SafeString& name, s32 level) { + return nullptr; +} + +void PlayerCreateTracer::finish() {} + +} // namespace uking::act diff --git a/src/Game/Actor/actPlayerCreateTrace.h b/src/Game/Actor/actPlayerCreateTrace.h new file mode 100644 index 00000000..8614b277 --- /dev/null +++ b/src/Game/Actor/actPlayerCreateTrace.h @@ -0,0 +1,49 @@ + +#pragma once + +#include <prim/seadSafeString.h> +#include "KingSystem/Utils/Types.h" + +namespace uking::act { + +// This is used in CreatePlayerEquipActorMgr and CreatePlayerTrashActorMgr +// and nowhere else. It's completely stubbed out, so the implementation is purely by usage-based +// guess + +// This exists because makeScope doesn't match +// when made an inlined function in PlayerCreateTracer +// i.e. tracer.trace()->makeScope() matches but not tracer.makeScope() +class PlayerCreateTrace; + +class PlayerCreateTraceScope { +public: + PlayerCreateTraceScope(PlayerCreateTrace* trace, const sead::SafeString& name, + const sead::SafeString& caller, s32 level); + virtual ~PlayerCreateTraceScope(); + +private: + PlayerCreateTrace* mTrace = nullptr; +}; +KSYS_CHECK_SIZE_NX150(PlayerCreateTraceScope, 0x10); + +class PlayerCreateTrace { +public: + PlayerCreateTraceScope makeScope(const sead::SafeString& name, const sead::SafeString& caller, + s32 level) { + return {this, name, caller, level}; + } + static PlayerCreateTrace* make(const sead::SafeString& name, s32 level); +}; + +class PlayerCreateTracer { +public: + void init(const sead::SafeString& name) { mTrace = PlayerCreateTrace::make(name, 0); } + void finish(); + PlayerCreateTrace* trace() { return mTrace; } + +private: + PlayerCreateTrace* mTrace = nullptr; +}; +KSYS_CHECK_SIZE_NX150(PlayerCreateTracer, 0x8); + +} // namespace uking::act diff --git a/src/Game/Actor/actPlayerCreateUtils.cpp b/src/Game/Actor/actPlayerCreateUtils.cpp new file mode 100644 index 00000000..0ba229e7 --- /dev/null +++ b/src/Game/Actor/actPlayerCreateUtils.cpp @@ -0,0 +1,25 @@ +#include "Game/Actor/actPlayerCreateUtils.h" +#include "Game/Actor/actPlayerCreateMgr.h" +#include "Game/Actor/actWeapon.h" +#include "Game/UI/uiPauseMenuDataMgr.h" +#include "KingSystem/ActorSystem/Profiles/actWeaponBase.h" + +namespace uking::act { + +void requestCreateWeaponByRawLife(const char* actor_class, const sead::Matrix34f& matrix, f32 scale, + sead::Heap* heap, ksys::act::BaseProcHandle* handle, s32 life, + bool is_player_put, const WeaponModifierInfo* modifier, + s32 task_lane_id, s32 res_lane_id) { + ksys::act::InstParamPack params; + params->add(is_player_put, "IsPlayerPut"); + if (modifier) { + modifier->addModifierParams(params); + } + params->add(true, "IsWeaponCreateByRawLife"); + params->addResourceLane(res_lane_id); + + ksys::act::WeaponBase::requestCreateWeaponActor(actor_class, matrix, scale, heap, handle, life, + ¶ms, task_lane_id); +} + +} // namespace uking::act diff --git a/src/Game/Actor/actPlayerCreateUtils.h b/src/Game/Actor/actPlayerCreateUtils.h new file mode 100644 index 00000000..2277d73f --- /dev/null +++ b/src/Game/Actor/actPlayerCreateUtils.h @@ -0,0 +1,28 @@ +#pragma once + +#include <math/seadMatrix.h> +#include <prim/seadSafeString.h> + +namespace sead { +class Heap; +} + +namespace ksys::act { +class BaseProcHandle; +class InstParamPack; +} // namespace ksys::act + +namespace uking::ui { +class PouchItem; +} // namespace uking::ui + +namespace uking::act { + +enum class CreateEquipmentSlot : u8; +struct WeaponModifierInfo; +void requestCreateWeaponByRawLife(const char* actor_class, const sead::Matrix34f& matrix, f32 scale, + sead::Heap* heap, ksys::act::BaseProcHandle* handle, s32 life, + bool is_player_put, const WeaponModifierInfo* modifier, + s32 task_lane_id, s32 res_lane_id); + +} // namespace uking::act diff --git a/src/Game/UI/uiPauseMenuDataMgr.cpp b/src/Game/UI/uiPauseMenuDataMgr.cpp index 3840501e..6c815e70 100644 --- a/src/Game/UI/uiPauseMenuDataMgr.cpp +++ b/src/Game/UI/uiPauseMenuDataMgr.cpp @@ -4,7 +4,8 @@ #include <limits> #include <math/seadMathCalcCommon.h> #include <prim/seadScopedLock.h> -#include "Game/Actor/actCreatePlayerEquipActorMgr.h" +#include "Game/Actor/actPlayerCreateMgr.h" +#include "Game/Actor/actPlayerCreateUtils.h" #include "Game/Actor/actWeapon.h" #include "Game/Cooking/cookManager.h" #include "Game/DLC/aocManager.h" @@ -1481,7 +1482,7 @@ void PauseMenuDataMgr::createPlayerEquipment() { break; } if (item->isInInventory() && item->isEquipped()) { - u64 slot = (u64)act::getCreateEquipmentSlot(type); + u64 slot = (u64)getCreateEquipmentSlot(type); if (slot < equipment_items.size()) { equipment_items[slot] = item; } @@ -1501,7 +1502,7 @@ void PauseMenuDataMgr::createPlayerEquipment() { 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); + createEquipmentFromItem(equipment_items[i], Caller); } else { create_mgr->requestCreateArmorHeadB(equipment_items[i]->getName(), equipment_items[i]->getValue(), Caller); diff --git a/src/Game/UI/uiUtils.cpp b/src/Game/UI/uiUtils.cpp index c26117fa..49ea4852 100644 --- a/src/Game/UI/uiUtils.cpp +++ b/src/Game/UI/uiUtils.cpp @@ -1,4 +1,5 @@ #include "Game/UI/uiUtils.h" +#include "Game/Actor/actPlayerCreateMgr.h" #include "Game/Actor/actWeapon.h" #include "Game/DLC/aocHardModeManager.h" #include "Game/Damage/dmgInfoManager.h" @@ -114,4 +115,70 @@ bool isMasterSwordActorName(const sead::SafeString& name) { return name == "Weapon_Sword_070"; } +act::CreateEquipmentSlot getCreateEquipmentSlot(ui::PouchItemType type) { + switch (type) { + case ui::PouchItemType::Sword: + return act::CreateEquipmentSlot::WeaponSword; + case ui::PouchItemType::Bow: + return act::CreateEquipmentSlot::WeaponBow; + case ui::PouchItemType::Shield: + return act::CreateEquipmentSlot::WeaponShield; + case ui::PouchItemType::ArmorHead: + return act::CreateEquipmentSlot::ArmorHead; + case ui::PouchItemType::ArmorUpper: + return act::CreateEquipmentSlot::ArmorUpper; + case ui::PouchItemType::ArmorLower: + return act::CreateEquipmentSlot::ArmorLower; + default: + return act::CreateEquipmentSlot::Length; + } +} + +ui::EquipmentSlot getEquipmentSlot(act::CreateEquipmentSlot slot) { + switch (slot) { + case act::CreateEquipmentSlot::WeaponSword: + return ui::EquipmentSlot::WeaponRight; + case act::CreateEquipmentSlot::WeaponShield: + return ui::EquipmentSlot::WeaponLeft; + case act::CreateEquipmentSlot::WeaponBow: + return ui::EquipmentSlot::WeaponBow; + case act::CreateEquipmentSlot::ArmorHead: + return ui::EquipmentSlot::ArmorHead; + case act::CreateEquipmentSlot::ArmorUpper: + return ui::EquipmentSlot::ArmorUpper; + case act::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 = act::CreatePlayerEquipActorMgr::instance(); + if (!mgr) { + return false; + } + + auto type = item->getType(); + auto slot = getCreateEquipmentSlot(type); + int slot_idx = (int)slot; + + if (slot <= act::CreateEquipmentSlot::WeaponBow) { + act::WeaponModifierInfo modifier(*item); + mgr->requestCreateWeapon(slot_idx, item->getName(), item->getValue(), &modifier, caller); + return true; + } + + if (slot <= act::CreateEquipmentSlot::ArmorLower) { + mgr->requestCreateArmor(slot_idx, item->getName(), item->getValue(), caller); + return true; + } + + return false; +} + } // namespace uking::ui diff --git a/src/Game/UI/uiUtils.h b/src/Game/UI/uiUtils.h index b68a1d58..288b7996 100644 --- a/src/Game/UI/uiUtils.h +++ b/src/Game/UI/uiUtils.h @@ -3,8 +3,14 @@ #include <prim/seadSafeString.h> #include "Game/Actor/actWeapon.h" +namespace uking::act { +enum class CreateEquipmentSlot : u8; +} + namespace uking::ui { +enum class EquipmentSlot; +enum class PouchItemType; class PouchItem; struct WeaponStats { @@ -47,4 +53,8 @@ int getItemValue(const sead::SafeString& name); // Do not implement until the location is figured out void applyScreenFade(float progress); +act::CreateEquipmentSlot getCreateEquipmentSlot(ui::PouchItemType type); +ui::EquipmentSlot getEquipmentSlot(act::CreateEquipmentSlot slot); +bool createEquipmentFromItem(const ui::PouchItem* item, const sead::SafeString& caller); + } // namespace uking::ui |
