diff options
| author | Léo Lam <leo@leolam.fr> | 2020-11-12 16:03:03 +0100 |
|---|---|---|
| committer | Léo Lam <leo@leolam.fr> | 2020-11-14 21:06:08 +0100 |
| commit | ffe38d0076fd487bae46edd092171469ec08d439 (patch) | |
| tree | 16c4f06dc454e2c81d67133355184022397198d6 /src/KingSystem/ActorSystem/actActorParamMgr.cpp | |
| parent | d9356ffa90f2b6c819b00bfc7905763aea8c39bc (diff) | |
ksys/act: Implement more ActorParamMgr functions
Diffstat (limited to 'src/KingSystem/ActorSystem/actActorParamMgr.cpp')
| -rw-r--r-- | src/KingSystem/ActorSystem/actActorParamMgr.cpp | 392 |
1 files changed, 367 insertions, 25 deletions
diff --git a/src/KingSystem/ActorSystem/actActorParamMgr.cpp b/src/KingSystem/ActorSystem/actActorParamMgr.cpp index 82fa697e..17c6404d 100644 --- a/src/KingSystem/ActorSystem/actActorParamMgr.cpp +++ b/src/KingSystem/ActorSystem/actActorParamMgr.cpp @@ -3,7 +3,36 @@ #include "KingSystem/ActorSystem/actASSetting.h" #include "KingSystem/ActorSystem/actActorParam.h" #include "KingSystem/Resource/resLoadRequest.h" +#include "KingSystem/Resource/resResourceAIProgram.h" +#include "KingSystem/Resource/resResourceAISchedule.h" +#include "KingSystem/Resource/resResourceAS.h" +#include "KingSystem/Resource/resResourceASList.h" +#include "KingSystem/Resource/resResourceActorLink.h" +#include "KingSystem/Resource/resResourceAnimInfo.h" +#include "KingSystem/Resource/resResourceArchive.h" +#include "KingSystem/Resource/resResourceAttClient.h" +#include "KingSystem/Resource/resResourceAttClientList.h" +#include "KingSystem/Resource/resResourceAwareness.h" +#include "KingSystem/Resource/resResourceBoneControl.h" +#include "KingSystem/Resource/resResourceChemical.h" +#include "KingSystem/Resource/resResourceDamageParam.h" +#include "KingSystem/Resource/resResourceDrop.h" #include "KingSystem/Resource/resResourceGParamList.h" +#include "KingSystem/Resource/resResourceLifeCondition.h" +#include "KingSystem/Resource/resResourceLod.h" +#include "KingSystem/Resource/resResourceMgrTask.h" +#include "KingSystem/Resource/resResourceModelList.h" +#include "KingSystem/Resource/resResourcePhysics.h" +#include "KingSystem/Resource/resResourceRagdollBlendWeight.h" +#include "KingSystem/Resource/resResourceRagdollConfig.h" +#include "KingSystem/Resource/resResourceRagdollConfigList.h" +#include "KingSystem/Resource/resResourceRecipe.h" +#include "KingSystem/Resource/resResourceShop.h" +#include "KingSystem/Resource/resResourceUMii.h" +#include "KingSystem/Resource/resSystem.h" +#include "KingSystem/Resource/resTempResourceLoader.h" +#include "KingSystem/Utils/Debug.h" +#include "KingSystem/Utils/ParamIO.h" namespace ksys::act { @@ -15,6 +44,31 @@ ActorParamMgr::~ActorParamMgr() { ASSetting::deleteInstance(); } +bool ActorParamMgr::checkPath(const sead::SafeString& path) const { + return res::returnFalse3(path); +} + +ActorParam* ActorParamMgr::allocParam(const char* actor_name, bool* allocated_new) { + auto lock = sead::makeScopedLock(mCS); + + ActorParam* free_param = nullptr; + auto* param = getParam(actor_name, &free_param); + + if (!param) { + param = free_param; + if (free_param) + free_param->mRes = {}; + else + param = &mParams[NumParams - 1]; + + param->mActorName = actor_name; + *allocated_new = true; + } + + param->incrementRef(); + return param; +} + // NON_MATCHING: addressing mode ActorParam* ActorParamMgr::getParam(const char* actor_name, ActorParam** out_free_param) const { auto lock = sead::makeScopedLock(mCS); @@ -32,30 +86,10 @@ ActorParam* ActorParamMgr::getParam(const char* actor_name, ActorParam** out_fre ActorParam* ActorParamMgr::loadParam(const char* actor_name, res::Handle* handle, void* x, u32 load_req_c) { - ActorParam* param; - bool existing = false; - - { - auto lock = sead::makeScopedLock(mCS); - - ActorParam* free_param = nullptr; - param = getParam(actor_name, &free_param); + bool allocated_new = false; + ActorParam* param = allocParam(actor_name, &allocated_new); - if (param) { - existing = true; - } else { - param = free_param; - if (free_param) - free_param->mRes = {}; - else - param = &mParams[NumParams - 1]; - - param->mActorName = actor_name; - } - param->incrementRef(); - } - - if (!existing) { + if (allocated_new) { loadFiles(param, mTmpActorParamMgrHeap, handle, x, load_req_c); param->setEventSignal(); } else { @@ -65,8 +99,43 @@ ActorParam* ActorParamMgr::loadParam(const char* actor_name, res::Handle* handle return param; } -bool ActorParamMgr::loadActorPack(res::Handle* handle, const sead::SafeString& actor_name, - u32 load_req_c) { +void ActorParamMgr::loadFiles(ActorParam* param, sead::Heap* heap, res::Handle* pack_handle, + void* x, u32 load_req_c) { + param->deleteResHandles(); + param->allocResHandles(heap, 0, 29); + param->mActiveBufferIdx = 0; + + using Type = ActorParam::ResourceType; + using User = res::ActorLink::User; + + const auto* link = + loadFile<res::ActorLink>(param, Type::ActorLink, "Actor/ActorLink", "xml", + param->getActorName().cstr(), pack_handle, x, load_req_c); + + if (link) + param->setProfileAndPriority(link->getUserName(User::Profile), link->getPriority().cstr()); + + const auto* actor_link = param->getRes().mActorLink; + if (!actor_link) + return; + + param->mActiveBufferIdx = 0; + + loadFile<res::ModelList>(param, Type::ModelList, "Actor/ModelList", "modellist", + actor_link->getUserName(User::Model), pack_handle, x, load_req_c); + + loadFile<res::UMii>(param, Type::UMii, "Actor/UMii", "umii", + actor_link->getUserName(User::UMii), pack_handle, x, load_req_c); + + loadFile<res::ASList>(param, Type::ASList, "Actor/ASList", "aslist", + actor_link->getUserName(res::ActorLink::User::AS), pack_handle, x, + load_req_c); + + loadFilesStep2(param, heap, pack_handle, x, load_req_c); +} + +bool ActorParamMgr::requestLoadActorPack(res::Handle* handle, const sead::SafeString& actor_name, + u32 load_req_c) { sead::FixedSafeString<128> path; res::LoadRequest req; @@ -81,6 +150,279 @@ bool ActorParamMgr::loadActorPack(res::Handle* handle, const sead::SafeString& a return handle->requestLoad(path, &req); } +void ActorParamMgr::loadFilesStep2(ActorParam* param, sead::Heap* heap, res::Handle* pack_handle, + void* x, u32 load_req_c) { + const auto* link = param->getRes().mActorLink; + param->mActiveBufferIdx = 0; + + using Type = ActorParam::ResourceType; + using User = res::ActorLink::User; + + loadFile<res::AttClientList>(param, Type::AttClientList, "Actor/AttClientList", "atcllist", + link->getUserName(User::Attention), pack_handle, x, load_req_c); + + loadFile<res::RagdollConfigList>(param, Type::RagdollConfigList, "Actor/RagdollConfigList", + "rgconfiglist", link->getUserName(User::RgConfigList), + pack_handle, x, load_req_c); + + { + s32 num_extra_handles = 0; + auto* aslist = param->getRes().mASList; + auto* atcllist = param->getRes().mAttClientList; + auto* rgconfiglist = param->getRes().mRagdollConfigList; + if (aslist) + num_extra_handles += aslist->getBuffers().as_defines.size(); + if (atcllist) + num_extra_handles += atcllist->getClients().size(); + if (rgconfiglist) + num_extra_handles += rgconfiglist->getImpulseParams().size(); + + param->allocResHandles(heap, 1, num_extra_handles); + } + + // Start loading the extra ActorParam files. + param->mActiveBufferIdx = 1; + + if (auto* aslist = param->getRes().mASList) { + for (s32 i = 0; i < aslist->getBuffers().as_defines.size(); ++i) { + auto* as = loadFile<res::AS>(param, Type::AS, "Actor/AS", "as", + aslist->getBuffers().as_defines[i].file_name.ref().cstr(), + pack_handle, x, load_req_c); + if (as) { + as->setIndex(u32(Type::AS)); + aslist->addAS_(i, as); + } + } + } + + if (auto* list = param->getRes().mAttClientList) { + for (s32 i = 0; i < list->getClients().size(); ++i) { + auto* client = loadFile<res::AttClient>( + param, Type::AttClient, "Actor/AttClient", "atcl", + list->getClients()[i].file_name.ref().cstr(), pack_handle, x, load_req_c); + if (client) { + client->setIndex(u32(Type::AttClient)); + list->addClient_(i, client); + } + } + } + + if (auto* list = param->getRes().mRagdollConfigList) { + for (s32 i = 0; i < list->getImpulseParams().size(); ++i) { + auto* config = loadFile<res::RagdollConfig>( + param, Type::RagdollConfig, "Actor/RagdollConfig", "rgconfig", + list->getImpulseParams()[i].file_name.ref().cstr(), pack_handle, x, load_req_c); + if (config) { + config->setIndex(u32(Type::RagdollConfig)); + list->addImpulseParamConfig_(i, config); + } + } + } + + // We have now finished loading the extra ActorParam files. + // Go back to using the main resource handle buffer. + param->mActiveBufferIdx = 0; + + loadFile<res::AIProgram>(param, Type::AIProgram, "Actor/AIProgram", "aiprog", + link->getUsers().getAIProgram(), pack_handle, x, load_req_c); + + loadFile<res::GParamList>(param, Type::GParamList, "Actor/GeneralParamList", "gparamlist", + link->getUsers().getGParam(), pack_handle, x, load_req_c); + + loadFile<res::Physics>(param, Type::Physics, "Actor/Physics", "physics", + link->getUsers().getPhysics(), pack_handle, x, load_req_c); + + loadFile<res::Chemical>(param, Type::Chemical, "Actor/Chemical", "chemical", + link->getUsers().getChemical(), pack_handle, x, load_req_c); + + loadFile<res::DamageParam>(param, Type::DamageParam, "Actor/DamageParam", "dmgparam", + link->getUsers().getDamageParam(), pack_handle, x, load_req_c); + + loadFile<res::RagdollBlendWeight>(param, Type::RagdollBlendWeight, "Actor/RagdollBlendWeight", + "rgbw", link->getUsers().getRgBlendWeight(), pack_handle, x, + load_req_c); + + loadFile<res::Awareness>(param, Type::Awareness, "Actor/Awareness", "awareness", + link->getUsers().getAwareness(), pack_handle, x, load_req_c); + + loadFile<res::Drop>(param, Type::DropTable, "Actor/DropTable", "drop", + link->getUsers().getDropTable(), pack_handle, x, load_req_c); + + loadFile<res::Shop>(param, Type::ShopData, "Actor/ShopData", "shop", + link->getUsers().getShopData(), pack_handle, x, load_req_c); + + loadFile<res::Recipe>(param, Type::Recipe, "Actor/Recipe", "recipe", + link->getUsers().getRecipe(), pack_handle, x, load_req_c); + + loadFile<res::Lod>(param, Type::Lod, "Actor/LOD", "lod", link->getUsers().getLOD(), pack_handle, + x, load_req_c); + + loadFile<res::AISchedule>(param, Type::AISchedule, "Actor/AISchedule", "aischedule", + link->getUsers().getAISchedule(), pack_handle, x, load_req_c); + + loadFile<res::BoneControl>(param, Type::BoneControl, "Actor/BoneControl", "bonectrl", + link->getUsers().getBoneControl(), pack_handle, x, load_req_c); + + loadFile<res::LifeCondition>(param, Type::LifeCondition, "Actor/LifeCondition", "lifecondition", + link->getUsers().getLifeCondition(), pack_handle, x, load_req_c); + + loadFile<res::AnimInfo>(param, Type::AnimationInfo, "Actor/AnimationInfo", "animinfo", + link->getUsers().getAnimationInfo(), pack_handle, x, load_req_c); + + param->_9 = 0; + param->onLoadFinished(this); +} + +void ActorParamMgr::unloadParam(ActorParam* param) { + auto lock = sead::makeScopedLock(mCS); + param->decrementRef(); +} + +bool ActorParamMgr::prepareLoadFromActorPack(sead::BufferedSafeString* path, res::LoadRequest* req, + void*, const sead::SafeString& dir_name, + const sead::SafeString& extension, + const sead::SafeString& file_name, + res::Handle* pack_handle, u32 load_req_c, + const sead::SafeString& requester) { + path->format("%s/%s.b%s", dir_name.cstr(), file_name.cstr(), extension.cstr()); + + bool in_pack = false; + if (pack_handle && pack_handle->isSuccess()) { + auto* pack = static_cast<sead::ArchiveRes*>(pack_handle->getResourceUnchecked()); + in_pack = pack->getFile(*path) != nullptr; + } + + const bool cond1 = res::returnFalse3(*path); + const bool is_host_path = res::isHostPath(*path); + if (!in_pack && !cond1 && !is_host_path && path->include("bxml")) { + sead::FormatFixedSafeString<256> message("↓↓↓\nファイルパス : %s\n↑↑↑\n", path->cstr()); + util::PrintDebug(message); + } + + const bool ret = res::returnFalse3(*path); + if (!ret && pack_handle && pack_handle->isSuccess()) { + req->mPackHandle = pack_handle; + req->_24 = false; + } + + req->_c = load_req_c; + req->mRequester = requester; + req->_8 = true; + return ret; +} + +res::Archive* ActorParamMgr::loadActorPack(res::Handle* handle, const sead::SafeString& actor_name, + u32 load_req_c) { + sead::FixedSafeString<128> path; + res::TempResourceLoader::LoadArg arg; + arg.retry_on_failure = true; + arg.use_handle = true; + + if (mFlags.isOn(Flag::_5)) + return nullptr; + + path.format("Actor/Pack/%s.bactorpack", actor_name.cstr()); + arg.load_req.mRequester = actor_name; + arg.load_req._c = load_req_c; + arg.load_req._8 = true; + arg.load_req._28 = false; + arg.load_req.mPath = path; + + res::TempResourceLoader loader; + { + res::TempResourceLoader::InitArg init_arg{}; + res::ResourceMgrTask::instance()->initTempResourceLoader(&loader, init_arg); + } + loader.load(arg); + + res::SimpleLoadRequest req; + req.mRequester = "tap::ActorParamMgr"; + req.mPath = path; + req._c = 2; + return sead::DynamicCast<res::Archive>(handle->load(path, &req)); +} + +template <typename T> +T* ActorParamMgr::loadFile(ActorParam* param, ActorParam::ResourceType type, const char* dir_name_c, + const char* extension_c, const char* name_c, res::Handle* pack_handle, + void* x, u32 load_req_c) { + const sead::SafeString name = name_c; + const sead::SafeString extension = extension_c; + sead::FixedSafeString<128> path; + + T* res = nullptr; + + if (name != "Dummy" && !name.isEmpty()) { + auto* temp_handle = param->allocHandle(); + const sead::SafeString* actor_name; + path.format("%s/%s.b%s", dir_name_c, name_c, extension_c); + { + res::SimpleLoadRequest req; + req._8 = true; + actor_name = ¶m->getActorName(); + req.mRequester = *actor_name; + req.mPath = path; + req._c = 2; + res = sead::DynamicCast<T>(temp_handle->load(path, &req)); + } + + // If loading the resource from the RomFS has failed, try to load it from the actor pack. + if (!res) { + if (!pack_handle->isSuccess()) + loadActorPack(pack_handle, *actor_name, load_req_c); + + res::LoadRequest req; + prepareLoadFromActorPack(&path, &req, x, dir_name_c, extension_c, name_c, pack_handle, + load_req_c, *actor_name); + res = sead::DynamicCast<T>(temp_handle->load(path, &req)); + + if (!res) { + static_cast<void>(temp_handle->isSuccess()); + // Try again without the pack. + if (req.mPackHandle) { + req.mPackHandle = nullptr; + req._24 = false; + res = sead::DynamicCast<T>(temp_handle->load(path, &req)); + if (!res) + static_cast<void>(temp_handle->isSuccess()); + } + } + } + + if (!res) + param->freeLastHandle(); + else if (type == ActorParam::ResourceType::EventFlow) + temp_handle->requestUnload2(); + + } else { + path.format("%s/%s.b%s", dir_name_c, name_c, extension_c); + res = sead::DynamicCast<T>(mResHandles[s32(type)].getResource()); + } + + if (res) { + if (type == ActorParam::ResourceType::EventFlow) + return res; + + static_cast<ParamIO*>(res)->getPath().copy(path); + param->setResourceIfValidType(type, res); + return res; + } + + if (extension != "fevfl") + param->_a = 1; + + // Fall back to using the dummy resource. + res = sead::DynamicCast<T>(mResHandles[s32(type)].getResource()); + sead::FixedSafeString<128> dummy_path; + dummy_path.format("%s/Dummy.b%s", dir_name_c, extension_c); + if (res) { + static_cast<ParamIO*>(res)->getPath().copy(dummy_path); + param->setResourceIfValidType(type, res); + } + + return res; +} + res::GParamList* ActorParamMgr::getDummyGParamList() const { return static_cast<res::GParamList*>( mResHandles[u32(ActorParam::ResourceType::GParamList)].getResourceUnchecked()); |
