diff options
| author | Pistonight <pistonknight@outlook.com> | 2025-05-03 21:27:10 -0700 |
|---|---|---|
| committer | Pistonight <pistonknight@outlook.com> | 2025-06-19 12:18:30 -0700 |
| commit | 3d920314042fc84ccffc5f4b503e85e3b77fc4a2 (patch) | |
| tree | 2be90adf201ed3e7ea9c9da68cf4699d1c190f5e /src | |
| parent | f18a3f4f9410e6eedb85b0434dbedc119e49d81b (diff) | |
CreatePlayerEquipActorMgr
Diffstat (limited to 'src')
21 files changed, 751 insertions, 178 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 diff --git a/src/KingSystem/ActorSystem/CMakeLists.txt b/src/KingSystem/ActorSystem/CMakeLists.txt index d956ebfa..5a5dd758 100644 --- a/src/KingSystem/ActorSystem/CMakeLists.txt +++ b/src/KingSystem/ActorSystem/CMakeLists.txt @@ -20,6 +20,8 @@ target_sources(uking PRIVATE Profiles/actPlayerBase.h Profiles/actRopeBase.cpp Profiles/actRopeBase.h + Profiles/actWeaponBase.cpp + Profiles/actWeaponBase.h actActor.cpp actActor.h diff --git a/src/KingSystem/ActorSystem/Profiles/actWeaponBase.cpp b/src/KingSystem/ActorSystem/Profiles/actWeaponBase.cpp new file mode 100644 index 00000000..d206224e --- /dev/null +++ b/src/KingSystem/ActorSystem/Profiles/actWeaponBase.cpp @@ -0,0 +1,23 @@ +#include "KingSystem/ActorSystem/Profiles/actWeaponBase.h" +#include "KingSystem/ActorSystem/actActorCreator.h" +#include "KingSystem/ActorSystem/actInstParamPack.h" + +namespace ksys::act { + +void WeaponBase::requestCreateWeaponActor(const char* actor, const sead::Matrix34f& matrix, + f32 scale, sead::Heap* heap, + ksys::act::BaseProcHandle* handle, s32 life, + ksys::act::InstParamPack* params_in, s32 task_lane_id) { + ksys::act::InstParamPack params; + if (params_in) { + params = *params_in; + } + + ksys::act::ActorCreator::addScale(params, scale); + params->add(life, "Life"); + params->addMatrix(matrix); + ksys::act::ActorCreator::instance()->requestCreateActor(actor, heap, handle, ¶ms, nullptr, + task_lane_id); +} + +} // namespace ksys::act diff --git a/src/KingSystem/ActorSystem/Profiles/actWeaponBase.h b/src/KingSystem/ActorSystem/Profiles/actWeaponBase.h new file mode 100644 index 00000000..ca13d0aa --- /dev/null +++ b/src/KingSystem/ActorSystem/Profiles/actWeaponBase.h @@ -0,0 +1,21 @@ +#pragma once + +#include "KingSystem/ActorSystem/actActor.h" + +namespace ksys::act { + +class BaseProcHandle; +class InstParamPack; + +// TODO +class WeaponBase : public Actor { +public: + bool areExtraActorsReady() const; + + static void requestCreateWeaponActor(const char* actor, const sead::Matrix34f& matrix, + f32 scale, sead::Heap* heap, + ksys::act::BaseProcHandle* handle, s32 life, + ksys::act::InstParamPack* params, s32 task_lane_id); +}; + +} // namespace ksys::act diff --git a/src/KingSystem/ActorSystem/actActorCreator.h b/src/KingSystem/ActorSystem/actActorCreator.h index ae80dd23..3368e765 100644 --- a/src/KingSystem/ActorSystem/actActorCreator.h +++ b/src/KingSystem/ActorSystem/actActorCreator.h @@ -12,7 +12,6 @@ namespace ksys::map { class MubinIter; class Object; -; } // namespace ksys::map namespace ksys::act { diff --git a/src/KingSystem/ActorSystem/actActorLinkConstDataAccess.cpp b/src/KingSystem/ActorSystem/actActorLinkConstDataAccess.cpp index c44d5717..06694bbf 100644 --- a/src/KingSystem/ActorSystem/actActorLinkConstDataAccess.cpp +++ b/src/KingSystem/ActorSystem/actActorLinkConstDataAccess.cpp @@ -1,4 +1,6 @@ #include "KingSystem/ActorSystem/actActorLinkConstDataAccess.h" +#include <prim/seadRuntimeTypeInfo.h> +#include "KingSystem/ActorSystem/actActor.h" #include "KingSystem/ActorSystem/actBaseProc.h" #include "KingSystem/ActorSystem/actBaseProcMgr.h" #include "KingSystem/Utils/Debug.h" @@ -25,6 +27,19 @@ bool ActorLinkConstDataAccess::acquire(BaseProc* proc) { return proc && proc->acquire(*this); } +const Actor* ActorLinkConstDataAccess::getActor() const { + if (!mProc) + return nullptr; + return sead::DynamicCast<Actor>(mProc); +} + +const sead::Matrix34f& ActorLinkConstDataAccess::getActorMtx() { + const Actor* actor = getActor(); + if (actor) + return actor->getMtx(); + return sead::Matrix34f::ident; +} + bool acquireProc(ActorLinkConstDataAccess* accessor, BaseProc* proc, const sead::SafeString& from, s32) { bool acquired = false; diff --git a/src/KingSystem/ActorSystem/actActorLinkConstDataAccess.h b/src/KingSystem/ActorSystem/actActorLinkConstDataAccess.h index c17eadb8..4c67c686 100644 --- a/src/KingSystem/ActorSystem/actActorLinkConstDataAccess.h +++ b/src/KingSystem/ActorSystem/actActorLinkConstDataAccess.h @@ -1,12 +1,14 @@ #pragma once #include <basis/seadTypes.h> +#include <math/seadMatrix.h> #include <prim/seadSafeString.h> namespace ksys { struct MesTransceiverId; namespace act { +class Actor; class BaseProc; /// Provides read-only access to actor data for safe, multi-threaded access. @@ -37,6 +39,8 @@ public: bool hasProc() const { return mProc != nullptr; } const MesTransceiverId* getMessageTransceiverId() const; + const Actor* getActor() const; + const sead::Matrix34f& getActorMtx(); protected: friend class ActorConstDataAccess; diff --git a/src/KingSystem/ActorSystem/actBaseProcHandle.h b/src/KingSystem/ActorSystem/actBaseProcHandle.h index 5911cb64..68964e78 100644 --- a/src/KingSystem/ActorSystem/actBaseProcHandle.h +++ b/src/KingSystem/ActorSystem/actBaseProcHandle.h @@ -26,6 +26,7 @@ public: bool isProcReady() const; bool hasProcCreationFailed() const; bool isProcCreationCancelled() const; + bool isAllocatedOrFailed() const { return mUnit || mFailed; } void deleteProcIfFailed(); void deleteProc(); diff --git a/src/KingSystem/ActorSystem/actInstParamPack.h b/src/KingSystem/ActorSystem/actInstParamPack.h index 0e68dfb6..52d47479 100644 --- a/src/KingSystem/ActorSystem/actInstParamPack.h +++ b/src/KingSystem/ActorSystem/actInstParamPack.h @@ -147,6 +147,7 @@ public: InstParamPack() = default; virtual ~InstParamPack() = default; + InstParamPack& operator=(const InstParamPack& other) = default; Buffer& getBuffer() { return mBuffer; } const Buffer& getBuffer() const { return mBuffer; } diff --git a/src/KingSystem/ActorSystem/actPlayerInfo.h b/src/KingSystem/ActorSystem/actPlayerInfo.h index 317b126b..a47475c9 100644 --- a/src/KingSystem/ActorSystem/actPlayerInfo.h +++ b/src/KingSystem/ActorSystem/actPlayerInfo.h @@ -22,6 +22,7 @@ class PlayerInfo : public PlayerInfoBase { ~PlayerInfo() override; public: + BaseProcLink& getPlayerLink() { return mPlayerLink; } bool init(); void setAndAcquirePlayer(PlayerBase* player); // requires PlayerOrEnemy and PlayerBase void resetPlayer(PlayerBase* player); |
