diff options
Diffstat (limited to 'src/KingSystem/ActorSystem/actActorCreator.cpp')
| -rw-r--r-- | src/KingSystem/ActorSystem/actActorCreator.cpp | 224 |
1 files changed, 224 insertions, 0 deletions
diff --git a/src/KingSystem/ActorSystem/actActorCreator.cpp b/src/KingSystem/ActorSystem/actActorCreator.cpp index be6c43b4..e3203b5e 100644 --- a/src/KingSystem/ActorSystem/actActorCreator.cpp +++ b/src/KingSystem/ActorSystem/actActorCreator.cpp @@ -1,7 +1,231 @@ #include "KingSystem/ActorSystem/actActorCreator.h" +#include <prim/seadScopedLock.h> +#include "KingSystem/ActorSystem/actActor.h" +#include "KingSystem/ActorSystem/actActorTemplate.h" +#include "KingSystem/ActorSystem/actActorUtil.h" +#include "KingSystem/ActorSystem/actBaseProcCreateTask.h" +#include "KingSystem/ActorSystem/actBaseProcMgr.h" +#include "KingSystem/ActorSystem/actInfoData.h" +#include "KingSystem/Resource/resResourceMgrTask.h" +#include "KingSystem/Utils/HeapUtil.h" namespace ksys::act { SEAD_SINGLETON_DISPOSER_IMPL(ActorCreator) +ActorCreator::ActorCreator() { + mActorList.initOffset(Actor::getCreatorListNodeOffset()); + mActorFactory = nullptr; + mEnableDistanceChecks = false; + mBlockSpawns = false; + _5a = true; + mForBaseProcDualHeap = nullptr; + mPlacementMgrHeap = nullptr; } + +void ActorCreator::onTaskRemoved(const util::TaskRemoveCallbackContext& context) { + if (!context.mTask) + return; + + auto* task = sead::DynamicCast<BaseProcCreateTask>(context.mTask); + if (task) + task->onBaseProcCreationFailed(nullptr, true); +} + +ActorCreator::~ActorCreator() = default; + +bool ActorCreator::requestCreateMapActor(const char* name, sead::Heap* heap, + map::MubinIter* mubin_iter, map::Object* map_object, + BaseProcHandle* handle, int task_lane_id, + InstParamPack* params) { + const char* actor_profile; + if (!InfoData::instance()->getActorProfile(&actor_profile, name)) + return false; + + const char* actor_class; + ActorTemplate::instance()->getActorClass(&actor_class, actor_profile); + + return requestCreateActor_(actor_class, name, heap, mubin_iter, map_object, handle, + task_lane_id, params); +} + +BaseProc* ActorCreator::createActor_(const char* actor_class, const char* name, sead::Heap* heap, + InstParamPack* params, bool sleep_after_init, bool) { + auto* debug_heap = util::getDebugHeap(); + bool has_debug_heap = false; + if (debug_heap && (debug_heap == heap || debug_heap->isInclude(heap))) { + res::ResourceMgrTask::instance()->controlField9c0d88(false); + has_debug_heap = true; + } + + const bool is_high_priority_thread = BaseProcMgr::instance()->isHighPriorityThread(); + SEAD_ASSERT(is_high_priority_thread); + + BaseProcCreateTaskData data; + data.mHeap = heap; + data.mProcClass = actor_class; + data.mProcName = name; + data.mCreateDelegate = &mCreateProcDelegate; + data.mSleepAfterInit = sleep_after_init; + if (params) { + data.mParams = ¶ms->getBuffer(); + data.mOtherProc = params->getProc(); + } + + BaseProcCreateRequest req; + req.task_remove_callback = nullptr; + req.task_lane_id = static_cast<u32>(BaseProcCreateTask::LaneId::_1); + req.task_data = &data; + auto* actor = BaseProcMgr::instance()->createProc(req); + if (has_debug_heap) + res::ResourceMgrTask::instance()->controlField9c0d88(true); + return actor; +} + +Actor* ActorCreator::createActor(const char* name, sead::Heap* heap, InstParamPack* params, + bool sleep_after_init, bool block_other_synchronous_spawns) { + BaseProc* proc = nullptr; + if (block_other_synchronous_spawns) + mBlockSpawns = true; + + if (block_other_synchronous_spawns || !mBlockSpawns) { + const char* profile; + if (InfoData::instance()->getActorProfile(&profile, name)) { + const char* actor_class; + ActorTemplate::instance()->getActorClass(&actor_class, profile); + proc = createActor_(actor_class, name, heap, params, sleep_after_init); + } + } + + auto* actor = sead::DynamicCast<Actor>(proc); + if (!actor && proc) + proc->deleteLater(BaseProc::DeleteReason::_0); + + return actor; +} + +bool ActorCreator::requestCreateActor_(const char* actor_class, const char* name, sead::Heap* heap, + map::MubinIter* mubin_iter, map::Object* map_object, + BaseProcHandle* handle, int task_lane_id, + InstParamPack* params) { + BaseProcCreateTaskData data; + data.mHeap = heap; + data.mProcClass = actor_class; + data.mProcName = name; + data.mMubinIter = mubin_iter; + data.mMapObject = map_object; + data.mCreateDelegate = &mCreateProcDelegate; + data.mProcHandle = handle; + if (params) { + data.mParams = ¶ms->getBuffer(); + data.mOtherProc = params->getProc(); + } + + BaseProcCreateRequest req; + req.task_lane_id = task_lane_id; + req.task_data = &data; + req.task_remove_callback = &mTaskRemovedDelegate; + return BaseProcMgr::instance()->requestCreateProc(req); +} + +bool ActorCreator::requestCreateActor_(const char* actor_class, const char* name, sead::Heap* heap, + map::Object* map_object, BaseProcHandle* handle, + int task_lane_id, InstParamPack* params) { + BaseProcCreateTaskData data; + data.mHeap = heap; + data.mProcClass = actor_class; + data.mProcName = name; + data.mCreateDelegate = &mCreateProcDelegate; + data.mMapObject = map_object; + data.mProcHandle = handle; + if (params) { + data.mParams = ¶ms->getBuffer(); + data.mOtherProc = params->getProc(); + } + + BaseProcCreateRequest req; + req.task_lane_id = task_lane_id; + req.task_data = &data; + req.task_remove_callback = &mTaskRemovedDelegate; + return BaseProcMgr::instance()->requestCreateProc(req); +} + +bool ActorCreator::requestCreateActor(const char* name, sead::Heap* heap, BaseProcHandle* handle, + InstParamPack* params, map::Object* map_object, + int task_lane_id) { + const char* actor_profile; + if (!InfoData::instance()->getActorProfile(&actor_profile, name)) + return false; + + const char* actor_class; + ActorTemplate::instance()->getActorClass(&actor_class, actor_profile); + + if (mBlockSpawns) + return false; + + return requestCreateActor_(actor_class, name, heap, map_object, handle, task_lane_id, params); +} + +// NON_MATCHING: OffsetList iteration +void ActorCreator::enableDistanceUnloadChecks() { + const auto lock = sead::makeScopedLock(mActorListCS); + for (auto it = mActorList.robustBegin(); it != mActorList.robustEnd(); ++it) { + auto& actor = *it; + if (!isWeaponOrArmor(&actor) || actor.getProfile().include("ArmorExtra")) + actor.getActorFlags2().set(Actor::ActorFlag2::NoDistanceCheck); + } + mEnableDistanceChecks = true; +} + +void ActorCreator::eraseActor(Actor* actor) { + const auto lock = sead::makeScopedLock(mActorListCS); + mActorList.erase(actor); + actor->mCreator = nullptr; +} + +void ActorCreator::addScale(InstParamPack& pack, float scale) { + addScale(pack, {scale, scale, scale}); +} + +void ActorCreator::addScale(InstParamPack& pack, const sead::Vector3f& scale) { + sead::SafeString key = "@S"; + pack.getBuffer().add(scale, key); +} + +bool ActorCreator::isAITreeParam(const InstParamPack::Entry& entry) { + return sead::SafeString("=AT") == entry.key; +} + +void ActorCreator::addAITreeParam(InstParamPack& pack, const sead::SafeString& value, + const sead::SafeString& name) { + pack.getBuffer().add(true, "=AT"); + pack.getBuffer().add(value, name); +} + +void ActorCreator::addAITreeParam(InstParamPack& pack, int value, const sead::SafeString& name) { + pack.getBuffer().add(true, "=AT"); + pack.getBuffer().add(value, name); +} + +void ActorCreator::addAITreeParam(InstParamPack& pack, u32 value, const sead::SafeString& name) { + pack.getBuffer().add(true, "=AT"); + pack.getBuffer().add(value, name); +} + +void ActorCreator::addAITreeParam(InstParamPack& pack, bool value, const sead::SafeString& name) { + pack.getBuffer().add(true, "=AT"); + pack.getBuffer().add(value, name); +} + +void ActorCreator::setCreatePriorityState1(InstParamPack& pack, BaseProc* proc) { + pack.setProc(proc); + proc->setCreatePriorityState1(); +} + +void ActorCreator::setCreatePriorityState2(InstParamPack& pack, BaseProc* proc) { + pack.setProc(proc); + proc->setCreatePriorityState2(); + pack.getBuffer().add(true, "@W"); +} + +} // namespace ksys::act |
