diff --git a/data/uking_functions.csv b/data/uking_functions.csv index 671075ef..dab233d4 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -39992,36 +39992,36 @@ Address,Quality,Size,Name 0x0000007100665a84,U,000156, 0x0000007100665b20,U,000068, 0x0000007100665b64,U,000488, -0x0000007100665d4c,W,000100,_ZN4sead10GameConfig18SingletonDisposer_D1Ev -0x0000007100665db0,U,000108,CreatePlayerEquipActorMgr::deleteInstance -0x0000007100665e1c,U,000136,CreatePlayerEquipActorMgr::createInstance +0x0000007100665d4c,O,000100,_ZN5uking3act25CreatePlayerEquipActorMgr18SingletonDisposer_D1Ev +0x0000007100665db0,O,000108,_ZN5uking3act25CreatePlayerEquipActorMgr18SingletonDisposer_D0Ev +0x0000007100665e1c,O,000136,_ZN5uking3act25CreatePlayerEquipActorMgr14createInstanceEPN4sead4HeapE 0x0000007100665ea4,O,000172,_ZN5uking3act15needsArmorHeadBERKN4sead14SafeStringBaseIcEES5_ -0x0000007100665f50,U,000088, -0x0000007100665fa8,U,000088, -0x0000007100666000,U,000556,CreatePlayerEquipActorMgr::ctor -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::resetAllEquipmentLoading -0x000000710066665c,U,000140,CreatePlayerEquipActorMgr::resetEquipmentLoading -0x00000071006666e8,U,000272,CreatePlayerEquipActorMgr::playerEquipmentActorsReady -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 +0x0000007100665f50,O,000088,_ZN5uking3act22isArmorHeadMantleType2ERKN4sead14SafeStringBaseIcEE +0x0000007100665fa8,O,000088,_ZN5uking3act29isArmorUpperNotUseMantleType0ERKN4sead14SafeStringBaseIcEE +0x0000007100666000,O,000556,_ZN5uking3act25CreatePlayerEquipActorMgrC1Ev +0x000000710066622c,O,000152,_ZN5uking3act25CreatePlayerEquipActorMgrD1Ev +0x00000071006662c4,O,000004,_ZN4ksys11StringBoardD2Ev +0x00000071006662c8,O,000036,_ZN5uking3act25CreatePlayerEquipActorMgrD0Ev +0x00000071006662ec,O,000296,_ZN5uking3act25CreatePlayerEquipActorMgr4initEv +0x0000007100666414,m,000412,_ZN5uking3act25CreatePlayerEquipActorMgr8postCalcEv +0x00000071006665b0,O,000172,_ZN5uking3act25CreatePlayerEquipActorMgr8resetAllEv +0x000000710066665c,O,000140,_ZN5uking3act25CreatePlayerEquipActorMgr5resetEi +0x00000071006666e8,O,000272,_ZNK5uking3act25CreatePlayerEquipActorMgr23areAllWeaponActorsReadyEv +0x00000071006667f8,O,000068,_ZNK5uking3act25CreatePlayerEquipActorMgr20isEquipmentProcReadyEi +0x000000710066683c,O,000444,_ZN5uking3act25CreatePlayerEquipActorMgr20tryGetEquipmentActorEi +0x00000071006669f8,O,000408,_ZN5uking3act25CreatePlayerEquipActorMgr19requestCreateWeaponEiRKN4sead14SafeStringBaseIcEEiPKNS0_18WeaponModifierInfoES6_ +0x0000007100666b90,O,000360,_ZN5uking3act25CreatePlayerEquipActorMgr19requestCreateWeaponERKN4sead14SafeStringBaseIcEEiPKNS0_18WeaponModifierInfoES6_ +0x0000007100666cf8,O,000688,_ZN5uking3act25CreatePlayerEquipActorMgr18requestCreateArmorEiRKN4sead14SafeStringBaseIcEEiS6_ +0x0000007100666fa8,O,000352,_ZN5uking3act25CreatePlayerEquipActorMgr18requestCreateArmorERKN4sead14SafeStringBaseIcEEiS6_ 0x0000007100667108,O,000180,_ZN5uking3act25CreatePlayerEquipActorMgr25requestCreateDefaultArmorEiRKN4sead14SafeStringBaseIcEE 0x00000071006671bc,O,000192,_ZN5uking3act25CreatePlayerEquipActorMgr23requestCreateArmorHeadBERKN4sead14SafeStringBaseIcEEiS6_ -0x000000710066727c,U,000004,j__ZdlPv_287 +0x000000710066727c,O,000004,_ZN4ksys11StringBoardD0Ev 0x0000007100667280,U,000324, 0x00000071006673c4,U,000100,_ZN4sead17PrimitiveRenderer18SingletonDisposer_D1Ev 0x0000007100667428,U,000108, 0x0000007100667494,U,000448,CreatePlayerTrashActorMgr::createInstance -0x0000007100667654,U,000020,_ZN2nn4ui2d7TextBoxD2Ev -0x0000007100667668,U,000052, +0x0000007100667654,U,000020,CreatePlayerTrashActorMgr::dtor +0x0000007100667668,U,000052,CreatePlayerTrashActorMgr::dtor0 0x000000710066769c,U,000300, 0x00000071006677c8,U,000424,CreatePlayerTrashActorMgr::postCalc 0x0000007100667970,U,000004,nullsub_2164 @@ -46811,7 +46811,7 @@ Address,Quality,Size,Name 0x000000710073c5b4,U,000732,spawnDroppedInventoryItem 0x000000710073c890,U,000292, 0x000000710073c9b4,U,000600,createActorPickOutFromPorch -0x000000710073cc0c,U,000336,requestCreateWeaponByRawLife +0x000000710073cc0c,O,000336,_ZN5uking3act28requestCreateWeaponByRawLifeEPKcRKN4sead8Matrix34IfEEfPNS3_4HeapEPN4ksys3act14BaseProcHandleEibPKNS0_18WeaponModifierInfoEii 0x000000710073cd5c,U,000160, 0x000000710073cdfc,U,000184, 0x000000710073ceb4,U,000368,requestCreateActorForTreasureChestDrop @@ -61787,9 +61787,9 @@ Address,Quality,Size,Name 0x0000007100aa814c,U,000008,setColorChangeMaterialIndex 0x0000007100aa8154,U,000012, 0x0000007100aa8160,U,000008, -0x0000007100aa8168,O,000048,_ZN5uking3act22getCreateEquipmentSlotENS_2ui13PouchItemTypeE -0x0000007100aa8198,O,000040,_ZN5uking3act16getEquipmentSlotENS0_19CreateEquipmentSlotE -0x0000007100aa81c0,O,000212,_ZN5uking3act23createEquipmentFromItemEPKNS_2ui9PouchItemERKN4sead14SafeStringBaseIcEE +0x0000007100aa8168,O,000048,_ZN5uking2ui22getCreateEquipmentSlotENS0_13PouchItemTypeE +0x0000007100aa8198,O,000040,_ZN5uking2ui16getEquipmentSlotENS_3act19CreateEquipmentSlotE +0x0000007100aa81c0,O,000212,_ZN5uking2ui23createEquipmentFromItemEPKNS0_9PouchItemERKN4sead14SafeStringBaseIcEE 0x0000007100aa8294,U,000028, 0x0000007100aa82b0,U,000132,trashPouchItem 0x0000007100aa8334,U,000028, @@ -72982,7 +72982,7 @@ Address,Quality,Size,Name 0x0000007100d104f0,U,000184,act::acc::Actor::getHomeMtx 0x0000007100d105a8,U,000188,act::acc::Actor::getHomePos 0x0000007100d10664,U,000156,act::acc::Actor::getFieldBodyGroup -0x0000007100d10700,U,000156,act::acc::getActorMtx +0x0000007100d10700,O,000156,_ZN4ksys3act24ActorLinkConstDataAccess11getActorMtxEv 0x0000007100d1079c,O,000004,_ZNK4ksys3act20ActorConstDataAccess8debugLogEiRKN4sead14SafeStringBaseIcEE 0x0000007100d107a0,U,000148,ActorAccessor::getPosition2 0x0000007100d10834,U,000156,act::acc::getPreviousPos2 @@ -80965,7 +80965,7 @@ Address,Quality,Size,Name 0x0000007100ef2784,U,000132, 0x0000007100ef2808,U,000204,getRandomWeaponModifier 0x0000007100ef28d4,U,000452,createWeaponND -0x0000007100ef2a98,U,000300,requestCreateActor +0x0000007100ef2a98,O,000300,_ZN4ksys3act10WeaponBase24requestCreateWeaponActorEPKcRKN4sead8Matrix34IfEEfPNS4_4HeapEPNS0_14BaseProcHandleEiPNS0_13InstParamPackEi 0x0000007100ef2bc4,U,000408,WeaponBase::ctor 0x0000007100ef2d5c,U,000180,WeaponBase::m0 0x0000007100ef2e10,U,000180, @@ -81018,7 +81018,7 @@ Address,Quality,Size,Name 0x0000007100ef8668,U,000008,WeaponBase::m208 0x0000007100ef8670,U,000216,WeaponBase::m48 0x0000007100ef8748,U,002512,WeaponBase::m147 -0x0000007100ef9118,U,000152, +0x0000007100ef9118,U,000152,WeaponBase::areExtraActorsReady 0x0000007100ef91b0,U,000056, 0x0000007100ef91e8,U,000092,WeaponBase::m230 0x0000007100ef9244,U,000144,WeaponBase::m231 @@ -89103,11 +89103,11 @@ Address,Quality,Size,Name 0x00000071010c2924,O,000032,_ZN4ksys4util13TaskQueueLock4lockEPNS0_13TaskQueueBaseE 0x00000071010c2944,O,000112,_ZNK4ksys4util13TaskQueueLock27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE 0x00000071010c29b4,O,000092,_ZNK4ksys4util13TaskQueueLock18getRuntimeTypeInfoEv -0x00000071010c2a10,U,000008, -0x00000071010c2a18,U,000004,nullsub_4513 -0x00000071010c2a1c,U,000024, -0x00000071010c2a34,U,000020, -0x00000071010c2a48,U,000004,j__ZdlPv_1198 +0x00000071010c2a10,O,000008,_ZN5uking3act17PlayerCreateTrace4makeERKN4sead14SafeStringBaseIcEEi +0x00000071010c2a18,O,000004,_ZN5uking3act18PlayerCreateTracer6finishEv +0x00000071010c2a1c,O,000024,_ZN5uking3act22PlayerCreateTraceScopeC1EPNS0_17PlayerCreateTraceERKN4sead14SafeStringBaseIcEES8_i +0x00000071010c2a34,O,000020,_ZN5uking3act22PlayerCreateTraceScopeD1Ev +0x00000071010c2a48,O,000004,_ZN5uking3act22PlayerCreateTraceScopeD0Ev 0x00000071010c2a4c,O,000032,_ZN4ksys4util17ManagedTaskHandleC1Ev 0x00000071010c2a6c,O,000128,_ZN4ksys4util17ManagedTaskHandleD1Ev 0x00000071010c2aec,O,000160,_ZN4ksys4util17ManagedTaskHandle19removeTaskFromQueueEv diff --git a/lib/sead b/lib/sead index d8b55c01..66ab5f8b 160000 --- a/lib/sead +++ b/lib/sead @@ -1 +1 @@ -Subproject commit d8b55c018d2249a6c993b2db09620b774015d9d0 +Subproject commit 66ab5f8b9c751a1def1aed69fd573cd0bda01739 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 -#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 -#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/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 +#include +#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(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(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(handle.releaseAndWakeProc()); + mEntries[slot_idx].mProcLink.acquire(actor, false); + } + } + + auto* actor = + sead::DynamicCast(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 +#include +#include +#include +#include +#include +#include +#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 + class Slots { + private: + sead::SafeArray 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 mProcHandles{}; + sead::BitFlag8 mIsLoading; + PlayerCreateTracer mTracer; + Slots 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 +#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 +#include + +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 #include #include -#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 #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 +#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(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 +#include #include 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);