mirror of
https://github.com/zeldaret/botw
synced 2026-07-27 22:59:34 -04:00
Merge branch 'master' into placement
This commit is contained in:
@@ -22,6 +22,8 @@ target_sources(uking PRIVATE
|
||||
actAiClass.h
|
||||
actAiParam.cpp
|
||||
actAiParam.h
|
||||
actAttention.cpp
|
||||
actAttention.h
|
||||
actBaseProc.cpp
|
||||
actBaseProc.h
|
||||
actBaseProcHandle.cpp
|
||||
@@ -40,7 +42,10 @@ target_sources(uking PRIVATE
|
||||
actBaseProcUnit.h
|
||||
actDebug.cpp
|
||||
actDebug.h
|
||||
actInfoData.cpp
|
||||
actInfoData.h
|
||||
actInstParamPack.cpp
|
||||
actInstParamPack.h
|
||||
actLifeRecoveryInfo.h
|
||||
actTag.h
|
||||
)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <prim/seadScopedLock.h>
|
||||
#include "KingSystem/ActorSystem/actActorParamMgr.h"
|
||||
#include "KingSystem/ActorSystem/actActorTemplate.h"
|
||||
#include "KingSystem/Utils/Byaml.h"
|
||||
#include "KingSystem/Utils/Byaml/Byaml.h"
|
||||
|
||||
namespace ksys::act {
|
||||
|
||||
@@ -49,8 +49,8 @@ void ActorParam::deleteResHandles() {
|
||||
handles.freeBuffer();
|
||||
}
|
||||
|
||||
bool ActorParam::isDummyParam(res::ActorLink::Users::User user) const {
|
||||
return mRes.mActorLink->getUsers().getUserName(user) == "Dummy";
|
||||
bool ActorParam::isDummyParam(res::ActorLink::User user) const {
|
||||
return sead::SafeString(mRes.mActorLink->getUserName(user)) == "Dummy";
|
||||
}
|
||||
|
||||
void ActorParam::allocResHandles(sead::Heap* heap, u32 buffer_idx, s32 count) {
|
||||
@@ -154,4 +154,6 @@ void ActorParam::setProfileAndPriority(const char* profile, const char* priority
|
||||
}
|
||||
}
|
||||
|
||||
void ActorParam::onLoadFinished(ActorParamMgr*) {}
|
||||
|
||||
} // namespace ksys::act
|
||||
|
||||
@@ -40,6 +40,8 @@ class UMii;
|
||||
|
||||
namespace act {
|
||||
|
||||
class ActorParamMgr;
|
||||
|
||||
// FIXME: incomplete
|
||||
class ActorParam : public sead::hostio::Node {
|
||||
public:
|
||||
@@ -69,7 +71,15 @@ public:
|
||||
LifeCondition = 22,
|
||||
UMii = 23,
|
||||
AnimationInfo = 24,
|
||||
AS = 25,
|
||||
AttClient = 26,
|
||||
RagdollConfig = 27,
|
||||
};
|
||||
static constexpr s32 NumResourceTypes = 28;
|
||||
|
||||
static constexpr bool isValidType(ResourceType type) {
|
||||
return type <= ResourceType::AnimationInfo;
|
||||
}
|
||||
|
||||
union Resources {
|
||||
struct {
|
||||
@@ -112,7 +122,7 @@ public:
|
||||
Priority getPriority() const { return mPriority; }
|
||||
const Resources& getRes() const { return mRes; }
|
||||
|
||||
bool isDummyParam(res::ActorLink::Users::User user) const;
|
||||
bool isDummyParam(res::ActorLink::User user) const;
|
||||
|
||||
static void resetDummyResources();
|
||||
|
||||
@@ -141,7 +151,15 @@ private:
|
||||
bool setPriority(const sead::SafeString& priority);
|
||||
void setProfileAndPriority(const char* profile, const char* priority);
|
||||
|
||||
u16 _8 = 0;
|
||||
void setResourceIfValidType(ResourceType type, ParamIO* param_io) {
|
||||
if (isValidType(type))
|
||||
setResource(type, param_io);
|
||||
}
|
||||
|
||||
void onLoadFinished(ActorParamMgr* mgr);
|
||||
|
||||
u8 _8 = 0;
|
||||
u8 _9 = 0;
|
||||
u8 _a = 0;
|
||||
sead::FixedSafeString<64> mActorName;
|
||||
sead::SafeString mProfile;
|
||||
|
||||
@@ -3,18 +3,75 @@
|
||||
#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 {
|
||||
|
||||
SEAD_SINGLETON_DISPOSER_IMPL(ActorParamMgr)
|
||||
|
||||
using Type = ActorParam::ResourceType;
|
||||
using User = res::ActorLink::User;
|
||||
|
||||
ActorParamMgr::ActorParamMgr() = default;
|
||||
|
||||
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);
|
||||
@@ -30,33 +87,13 @@ ActorParam* ActorParamMgr::getParam(const char* actor_name, ActorParam** out_fre
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ActorParam* ActorParamMgr::loadParam(const char* actor_name, res::Handle* handle, void* x,
|
||||
ActorParam* ActorParamMgr::loadParam(const char* actor_name, res::Handle* pack_handle, void* x,
|
||||
u32 load_req_c) {
|
||||
ActorParam* param;
|
||||
bool existing = false;
|
||||
bool allocated_new = false;
|
||||
ActorParam* param = allocParam(actor_name, &allocated_new);
|
||||
|
||||
{
|
||||
auto lock = sead::makeScopedLock(mCS);
|
||||
|
||||
ActorParam* free_param = nullptr;
|
||||
param = getParam(actor_name, &free_param);
|
||||
|
||||
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) {
|
||||
loadFiles(param, mTmpActorParamMgrHeap, handle, x, load_req_c);
|
||||
if (allocated_new) {
|
||||
loadFiles(param, mTmpActorParamMgrHeap, pack_handle, x, load_req_c);
|
||||
param->setEventSignal();
|
||||
} else {
|
||||
param->waitForEvent();
|
||||
@@ -65,8 +102,40 @@ 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, ActorParam::NumResourceTypes + 1);
|
||||
param->mActiveBufferIdx = 0;
|
||||
|
||||
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,9 +150,638 @@ bool ActorParamMgr::loadActorPack(res::Handle* handle, const sead::SafeString& a
|
||||
return handle->requestLoad(path, &req);
|
||||
}
|
||||
|
||||
ActorParam* ActorParamMgr::loadParamAsync(const char* actor_name, res::Handle* pack_handle,
|
||||
bool* allocated_new, void* x, u32 load_req_c) {
|
||||
auto* param = allocParam(actor_name, allocated_new);
|
||||
if (!*allocated_new)
|
||||
return param;
|
||||
|
||||
param->deleteResHandles();
|
||||
param->allocResHandles(mTmpActorParamMgrHeap, 0, ActorParam::NumResourceTypes + 1);
|
||||
param->mActiveBufferIdx = 0;
|
||||
|
||||
loadFileAsync<res::ActorLink>(param, Type::ActorLink, "Actor/ActorLink", "xml",
|
||||
param->getActorName().cstr(), pack_handle, x, load_req_c);
|
||||
return param;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool ActorParamMgr::loadFileAsync(ActorParam* param, ActorParam::ResourceType type,
|
||||
const sead::SafeString& dir_name,
|
||||
const sead::SafeString& extension, const sead::SafeString& name,
|
||||
res::Handle* pack_handle, void* x, u32 load_req_c) {
|
||||
auto* handle = param->allocHandle();
|
||||
|
||||
if (name != "Dummy" && !name.isEmpty()) {
|
||||
sead::FixedSafeString<128> path;
|
||||
res::LoadRequest req;
|
||||
prepareLoadFromActorPack(&path, &req, x, dir_name, extension, name, pack_handle, load_req_c,
|
||||
param->getActorName());
|
||||
return handle->requestLoad(path, &req);
|
||||
}
|
||||
|
||||
if (ActorParam::isValidType(type)) {
|
||||
auto* res = sead::DynamicCast<T>(mDummyResources[u32(type)].getResource());
|
||||
param->setResource(type, res);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// NON_MATCHING: different address calculation for static_cast<ParamIO*>(res)->getPath()
|
||||
template <typename T>
|
||||
T* ActorParamMgr::handleAsyncFileLoad(ActorParam* param, s32* idx, ActorParam::ResourceType type,
|
||||
void*) {
|
||||
const s32 current_idx = *idx;
|
||||
auto& handle = param->mHandles[param->mActiveBufferIdx][current_idx];
|
||||
*idx = current_idx + 1;
|
||||
|
||||
if (ActorParam::isValidType(type)) {
|
||||
if (auto* res = static_cast<T*>(param->getRes().mArray[u32(type)]))
|
||||
return res;
|
||||
}
|
||||
|
||||
if (handle.isFlag8Set())
|
||||
return sead::DynamicCast<T>(handle.getResource());
|
||||
|
||||
if (!handle.isReadyOrNeedsParse())
|
||||
return nullptr;
|
||||
|
||||
handle.parseResource(nullptr);
|
||||
|
||||
if (handle.checkLoadStatus() && type != Type::EventFlow)
|
||||
param->_a = 1;
|
||||
|
||||
auto* res = sead::DynamicCast<T>(handle.getResource());
|
||||
if (res) {
|
||||
auto* unit = handle.getUnit();
|
||||
if (unit)
|
||||
static_cast<ParamIO*>(res)->getPath().copy(unit->getPath());
|
||||
} else {
|
||||
res = sead::DynamicCast<T>(mDummyResources[s32(type)].getResource());
|
||||
}
|
||||
|
||||
if (ActorParam::isValidType(type) && res)
|
||||
param->setResource(type, res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool ActorParamMgr::finishLoadingActorLink(ActorParam* param, void* x) {
|
||||
s32 idx = 0;
|
||||
if (!handleAsyncFileLoad<res::ActorLink>(param, &idx, Type::ActorLink, x))
|
||||
return param->_a != 0;
|
||||
|
||||
const auto* link = param->getRes().mActorLink;
|
||||
if (!link)
|
||||
return true;
|
||||
|
||||
param->setProfileAndPriority(link->getUsers().getProfile(), link->getPriority().cstr());
|
||||
return true;
|
||||
}
|
||||
|
||||
void ActorParamMgr::loadParamAsyncStep2(ActorParam* param, res::Handle* pack_handle, void* x,
|
||||
u32 load_req_c) {
|
||||
const auto* link = param->getRes().mActorLink;
|
||||
|
||||
loadFileAsync<res::ModelList>(param, Type::ModelList, "Actor/ModelList", "modellist",
|
||||
link->getUsers().getModel(), pack_handle, x, load_req_c);
|
||||
|
||||
loadFileAsync<res::UMii>(param, Type::UMii, "Actor/UMii", "umii", link->getUsers().getUMii(),
|
||||
pack_handle, x, load_req_c);
|
||||
|
||||
loadFileAsync<res::ASList>(param, Type::ASList, "Actor/ASList", "aslist",
|
||||
link->getUsers().getAS(), pack_handle, x, load_req_c);
|
||||
|
||||
loadFileAsync<res::AttClientList>(param, Type::AttClientList, "Actor/AttClientList", "atcllist",
|
||||
link->getUserName(User::Attention), pack_handle, x,
|
||||
load_req_c);
|
||||
|
||||
loadFileAsync<res::RagdollConfigList>(param, Type::RagdollConfigList, "Actor/RagdollConfigList",
|
||||
"rgconfiglist", link->getUserName(User::RgConfigList),
|
||||
pack_handle, x, load_req_c);
|
||||
|
||||
loadFileAsync<res::AIProgram>(param, Type::AIProgram, "Actor/AIProgram", "aiprog",
|
||||
link->getUsers().getAIProgram(), pack_handle, x, load_req_c);
|
||||
|
||||
loadFileAsync<res::GParamList>(param, Type::GParamList, "Actor/GeneralParamList", "gparamlist",
|
||||
link->getUsers().getGParam(), pack_handle, x, load_req_c);
|
||||
|
||||
loadFileAsync<res::Physics>(param, Type::Physics, "Actor/Physics", "physics",
|
||||
link->getUsers().getPhysics(), pack_handle, x, load_req_c);
|
||||
|
||||
loadFileAsync<res::Chemical>(param, Type::Chemical, "Actor/Chemical", "chemical",
|
||||
link->getUsers().getChemical(), pack_handle, x, load_req_c);
|
||||
|
||||
loadFileAsync<res::DamageParam>(param, Type::DamageParam, "Actor/DamageParam", "dmgparam",
|
||||
link->getUsers().getDamageParam(), pack_handle, x, load_req_c);
|
||||
|
||||
loadFileAsync<res::RagdollBlendWeight>(
|
||||
param, Type::RagdollBlendWeight, "Actor/RagdollBlendWeight", "rgbw",
|
||||
link->getUsers().getRgBlendWeight(), pack_handle, x, load_req_c);
|
||||
|
||||
loadFileAsync<res::Awareness>(param, Type::Awareness, "Actor/Awareness", "awareness",
|
||||
link->getUsers().getAwareness(), pack_handle, x, load_req_c);
|
||||
|
||||
loadFileAsync<res::Drop>(param, Type::DropTable, "Actor/DropTable", "drop",
|
||||
link->getUsers().getDropTable(), pack_handle, x, load_req_c);
|
||||
|
||||
loadFileAsync<res::Shop>(param, Type::ShopData, "Actor/ShopData", "shop",
|
||||
link->getUsers().getShopData(), pack_handle, x, load_req_c);
|
||||
|
||||
loadFileAsync<res::Recipe>(param, Type::Recipe, "Actor/Recipe", "recipe",
|
||||
link->getUsers().getRecipe(), pack_handle, x, load_req_c);
|
||||
|
||||
loadFileAsync<res::Lod>(param, Type::Lod, "Actor/LOD", "lod", link->getUsers().getLOD(),
|
||||
pack_handle, x, load_req_c);
|
||||
|
||||
loadFileAsync<res::AISchedule>(param, Type::AISchedule, "Actor/AISchedule", "aischedule",
|
||||
link->getUsers().getAISchedule(), pack_handle, x, load_req_c);
|
||||
|
||||
loadFileAsync<res::BoneControl>(param, Type::BoneControl, "Actor/BoneControl", "bonectrl",
|
||||
link->getUsers().getBoneControl(), pack_handle, x, load_req_c);
|
||||
|
||||
loadFileAsync<res::LifeCondition>(param, Type::LifeCondition, "Actor/LifeCondition",
|
||||
"lifecondition", link->getUsers().getLifeCondition(),
|
||||
pack_handle, x, load_req_c);
|
||||
|
||||
loadFileAsync<res::AnimInfo>(param, Type::AnimationInfo, "Actor/AnimationInfo", "animinfo",
|
||||
link->getUsers().getAnimationInfo(), pack_handle, x, load_req_c);
|
||||
}
|
||||
|
||||
bool ActorParamMgr::finishLoadingStep2(ActorParam* param, void* x) {
|
||||
s32 idx = 1;
|
||||
|
||||
if (!handleAsyncFileLoad<res::ModelList>(param, &idx, Type::ModelList, x))
|
||||
return false;
|
||||
|
||||
if (!handleAsyncFileLoad<res::UMii>(param, &idx, Type::UMii, x))
|
||||
return false;
|
||||
|
||||
if (!handleAsyncFileLoad<res::ASList>(param, &idx, Type::ASList, x))
|
||||
return false;
|
||||
|
||||
if (!handleAsyncFileLoad<res::AttClientList>(param, &idx, Type::AttClientList, x))
|
||||
return false;
|
||||
|
||||
if (!handleAsyncFileLoad<res::RagdollConfigList>(param, &idx, Type::RagdollConfigList, x))
|
||||
return false;
|
||||
|
||||
if (!handleAsyncFileLoad<res::AIProgram>(param, &idx, Type::AIProgram, x))
|
||||
return false;
|
||||
|
||||
if (!handleAsyncFileLoad<res::GParamList>(param, &idx, Type::GParamList, x))
|
||||
return false;
|
||||
|
||||
if (!handleAsyncFileLoad<res::Physics>(param, &idx, Type::Physics, x))
|
||||
return false;
|
||||
|
||||
if (!handleAsyncFileLoad<res::Chemical>(param, &idx, Type::Chemical, x))
|
||||
return false;
|
||||
|
||||
if (!handleAsyncFileLoad<res::DamageParam>(param, &idx, Type::DamageParam, x))
|
||||
return false;
|
||||
|
||||
if (!handleAsyncFileLoad<res::RagdollBlendWeight>(param, &idx, Type::RagdollBlendWeight, x))
|
||||
return false;
|
||||
|
||||
if (!handleAsyncFileLoad<res::Awareness>(param, &idx, Type::Awareness, x))
|
||||
return false;
|
||||
|
||||
if (!handleAsyncFileLoad<res::Drop>(param, &idx, Type::DropTable, x))
|
||||
return false;
|
||||
|
||||
if (!handleAsyncFileLoad<res::Shop>(param, &idx, Type::ShopData, x))
|
||||
return false;
|
||||
|
||||
if (!handleAsyncFileLoad<res::Recipe>(param, &idx, Type::Recipe, x))
|
||||
return false;
|
||||
|
||||
if (!handleAsyncFileLoad<res::Lod>(param, &idx, Type::Lod, x))
|
||||
return false;
|
||||
|
||||
if (!handleAsyncFileLoad<res::AISchedule>(param, &idx, Type::AISchedule, x))
|
||||
return false;
|
||||
|
||||
if (!handleAsyncFileLoad<res::BoneControl>(param, &idx, Type::BoneControl, x))
|
||||
return false;
|
||||
|
||||
if (!handleAsyncFileLoad<res::LifeCondition>(param, &idx, Type::LifeCondition, x))
|
||||
return false;
|
||||
|
||||
if (!handleAsyncFileLoad<res::AnimInfo>(param, &idx, Type::AnimationInfo, x))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ActorParamMgr::loadExtraResAsync(ActorParam* param, res::Handle* pack_handle, void* x,
|
||||
u32 load_req_c) {
|
||||
const auto* aslist = param->getRes().mASList;
|
||||
const auto* atcllist = param->getRes().mAttClientList;
|
||||
const auto* rgconfiglist = param->getRes().mRagdollConfigList;
|
||||
|
||||
const auto num_as = aslist ? aslist->getASDefines().size() : 0;
|
||||
const auto num_att = atcllist ? atcllist->getClients().size() : 0;
|
||||
const auto num_rg = rgconfiglist ? rgconfiglist->getImpulseParams().size() : 0;
|
||||
|
||||
param->allocResHandles(mTmpActorParamMgrHeap, 1, num_as + num_att + num_rg);
|
||||
param->mActiveBufferIdx = 1;
|
||||
|
||||
if (aslist) {
|
||||
for (s32 i = 0; i < num_as; ++i) {
|
||||
loadFileAsync<res::AS>(param, Type::AS, "Actor/AS", "as",
|
||||
aslist->getASDefines()[i].getFileName(), pack_handle, x,
|
||||
load_req_c);
|
||||
}
|
||||
}
|
||||
|
||||
if (atcllist) {
|
||||
for (s32 i = 0; i < num_att; ++i) {
|
||||
loadFileAsync<res::AttClient>(param, Type::AttClient, "Actor/AttClient", "atcl",
|
||||
atcllist->getClients()[i].getFileName(), pack_handle, x,
|
||||
load_req_c);
|
||||
}
|
||||
}
|
||||
|
||||
if (rgconfiglist) {
|
||||
for (s32 i = 0; i < num_rg; ++i) {
|
||||
loadFileAsync<res::RagdollConfig>(
|
||||
param, Type::RagdollConfig, "Actor/RagdollConfig", "rgconfig",
|
||||
rgconfiglist->getImpulseParams()[i].getFileName(), pack_handle, x, load_req_c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ActorParamMgr::finishLoadingExtraRes(ActorParam* param, void* x) {
|
||||
s32 idx = 0;
|
||||
|
||||
auto* aslist = param->getRes().mASList;
|
||||
if (aslist) {
|
||||
for (s32 i = 0, n = aslist->getASDefines().size(); i < n; ++i) {
|
||||
const sead::SafeString file_name = aslist->getASDefines()[i].getFileName();
|
||||
if (file_name == "Dummy" || file_name.isEmpty()) {
|
||||
auto* as = sead::DynamicCast<res::AS>(mDummyResources[u32(Type::AS)].getResource());
|
||||
as->setIndex(u32(Type::AS));
|
||||
aslist->addAS_(i, as);
|
||||
++idx;
|
||||
} else {
|
||||
const res::Handle& handle = param->mHandles[1][idx];
|
||||
if (handle.isFlag8Set()) {
|
||||
++idx;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto* as = handleAsyncFileLoad<res::AS>(param, &idx, Type::AS, x);
|
||||
if (!as)
|
||||
return false;
|
||||
|
||||
as->setIndex(u32(Type::AS));
|
||||
aslist->addAS_(i, as);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto* atcllist = param->getRes().mAttClientList;
|
||||
if (atcllist) {
|
||||
for (s32 i = 0, n = atcllist->getClients().size(); i < n; ++i) {
|
||||
const sead::SafeString file_name = atcllist->getClients()[i].getFileName();
|
||||
if (file_name == "Dummy" || file_name.isEmpty()) {
|
||||
auto* res = sead::DynamicCast<res::AttClient>(
|
||||
mDummyResources[u32(Type::AttClient)].getResource());
|
||||
/// @bug This should be Type::AttClient. Copy paste error?
|
||||
res->setIndex(u32(Type::AS));
|
||||
atcllist->addClient_(i, res);
|
||||
++idx;
|
||||
} else {
|
||||
const res::Handle& handle = param->mHandles[1][idx];
|
||||
if (handle.isFlag8Set()) {
|
||||
++idx;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto* res = handleAsyncFileLoad<res::AttClient>(param, &idx, Type::AttClient, x);
|
||||
if (!res)
|
||||
return false;
|
||||
|
||||
res->setIndex(u32(Type::AttClient));
|
||||
atcllist->addClient_(i, res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto* rgconfiglist = param->getRes().mRagdollConfigList;
|
||||
if (rgconfiglist) {
|
||||
for (s32 i = 0, n = rgconfiglist->getImpulseParams().size(); i < n; ++i) {
|
||||
const sead::SafeString file_name = rgconfiglist->getImpulseParams()[i].getFileName();
|
||||
if (file_name == "Dummy" || file_name.isEmpty()) {
|
||||
auto* res = sead::DynamicCast<res::RagdollConfig>(
|
||||
mDummyResources[u32(Type::RagdollConfig)].getResource());
|
||||
res->setIndex(u32(Type::RagdollConfig));
|
||||
rgconfiglist->addImpulseParamConfig_(i, res);
|
||||
++idx;
|
||||
} else {
|
||||
const res::Handle& handle = param->mHandles[1][idx];
|
||||
if (handle.isFlag8Set()) {
|
||||
++idx;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto* res =
|
||||
handleAsyncFileLoad<res::RagdollConfig>(param, &idx, Type::RagdollConfig, x);
|
||||
if (!res)
|
||||
return false;
|
||||
|
||||
res->setIndex(u32(Type::RagdollConfig));
|
||||
rgconfiglist->addImpulseParamConfig_(i, res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
param->_9 = 0;
|
||||
param->onLoadFinished(this);
|
||||
param->setEventSignal();
|
||||
return true;
|
||||
}
|
||||
|
||||
void ActorParamMgr::allocExtraResHandles(ActorParam* param, sead::Heap* heap) const {
|
||||
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->getASDefines().size();
|
||||
|
||||
if (atcllist)
|
||||
num_extra_handles += atcllist->getClients().size();
|
||||
|
||||
if (rgconfiglist)
|
||||
num_extra_handles += rgconfiglist->getImpulseParams().size();
|
||||
|
||||
param->allocResHandles(heap, 1, num_extra_handles);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
// Start loading the extra ActorParam files.
|
||||
allocExtraResHandles(param, heap);
|
||||
param->mActiveBufferIdx = 1;
|
||||
|
||||
if (auto* aslist = param->getRes().mASList) {
|
||||
for (s32 i = 0; i < aslist->getASDefines().size(); ++i) {
|
||||
auto* as = loadFile<res::AS>(param, Type::AS, "Actor/AS", "as",
|
||||
aslist->getASDefines()[i].getFileName(), 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].getFileName(),
|
||||
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].getFileName(), 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>(mDummyResources[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>(mDummyResources[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());
|
||||
mDummyResources[u32(ActorParam::ResourceType::GParamList)].getResourceUnchecked());
|
||||
}
|
||||
|
||||
} // namespace ksys::act
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <prim/seadSafeString.h>
|
||||
#include <prim/seadTypedBitFlag.h>
|
||||
#include <thread/seadCriticalSection.h>
|
||||
#include "KingSystem/ActorSystem/actActorParam.h"
|
||||
#include "KingSystem/Resource/resHandle.h"
|
||||
#include "KingSystem/System/DebugMessage.h"
|
||||
#include "KingSystem/System/KingEditor.h"
|
||||
@@ -14,13 +15,13 @@
|
||||
namespace ksys {
|
||||
|
||||
namespace res {
|
||||
class Archive;
|
||||
class GParamList;
|
||||
class LoadRequest;
|
||||
} // namespace res
|
||||
|
||||
namespace act {
|
||||
|
||||
class ActorParam;
|
||||
|
||||
// FIXME: incomplete
|
||||
class ActorParamMgr final : public sead::hostio::Node, public KingEditorComponent {
|
||||
SEAD_SINGLETON_DISPOSER(ActorParamMgr)
|
||||
@@ -35,11 +36,23 @@ public:
|
||||
sead::Heap* getDebugHeap() const { return mDebugHeap; }
|
||||
sead::Heap* getTmpActorParamMgrHeap() const { return mTmpActorParamMgrHeap; }
|
||||
|
||||
bool checkPath(const sead::SafeString& path) const;
|
||||
|
||||
void init(sead::Heap* heap, sead::Heap* debug_heap);
|
||||
|
||||
ActorParam* allocParam(const char* actor_name, bool* allocated_new);
|
||||
ActorParam* getParam(const char* actor_name, ActorParam** out_free_param) const;
|
||||
ActorParam* loadParam(const char* actor_name, res::Handle* handle, void* x, u32 load_req_c);
|
||||
ActorParam* loadParam(const char* actor_name, res::Handle* pack_handle, void* x,
|
||||
u32 load_req_c);
|
||||
void unloadParam(ActorParam* param);
|
||||
|
||||
ActorParam* loadParamAsync(const char* actor_name, res::Handle* pack_handle,
|
||||
bool* allocated_new, void* x, u32 load_req_c);
|
||||
bool finishLoadingActorLink(ActorParam* param, void* x);
|
||||
void loadParamAsyncStep2(ActorParam* param, res::Handle* pack_handle, void* x, u32 load_req_c);
|
||||
bool finishLoadingStep2(ActorParam* param, void* x);
|
||||
void loadExtraResAsync(ActorParam* param, res::Handle* pack_handle, void* x, u32 load_req_c);
|
||||
bool finishLoadingExtraRes(ActorParam* param, void* x);
|
||||
res::GParamList* getDummyGParamList() const;
|
||||
|
||||
private:
|
||||
@@ -50,9 +63,36 @@ private:
|
||||
_5 = _1 | _4,
|
||||
};
|
||||
|
||||
void loadFiles(ActorParam* param, sead::Heap* heap, res::Handle* handle, void* x,
|
||||
void loadFiles(ActorParam* param, sead::Heap* heap, res::Handle* pack_handle, void* x,
|
||||
u32 load_req_c);
|
||||
bool loadActorPack(res::Handle* handle, const sead::SafeString& actor_name, u32 load_req_c);
|
||||
bool requestLoadActorPack(res::Handle* handle, const sead::SafeString& actor_name,
|
||||
u32 load_req_c);
|
||||
bool prepareLoadFromActorPack(sead::BufferedSafeString* path, res::LoadRequest* req, void* x,
|
||||
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);
|
||||
res::Archive* loadActorPack(res::Handle* handle, const sead::SafeString& actor_name,
|
||||
u32 load_req_c);
|
||||
|
||||
template <typename T>
|
||||
T* 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);
|
||||
|
||||
template <typename T>
|
||||
bool loadFileAsync(ActorParam* param, ActorParam::ResourceType type,
|
||||
const sead::SafeString& dir_name, const sead::SafeString& extension,
|
||||
const sead::SafeString& name, res::Handle* pack_handle, void* x,
|
||||
u32 load_req_c);
|
||||
|
||||
template <typename T>
|
||||
T* handleAsyncFileLoad(ActorParam* param, s32* idx, ActorParam::ResourceType type, void* x);
|
||||
|
||||
void loadFilesStep2(ActorParam* param, sead::Heap* heap, res::Handle* pack_handle, void* x,
|
||||
u32 load_req_c);
|
||||
|
||||
void allocExtraResHandles(ActorParam* param, sead::Heap* heap) const;
|
||||
|
||||
static constexpr s32 NumParams = 0x400;
|
||||
|
||||
@@ -63,7 +103,7 @@ private:
|
||||
void* _e8 = nullptr;
|
||||
sead::Heap* mDebugHeap = nullptr;
|
||||
sead::Heap* mTmpActorParamMgrHeap = nullptr;
|
||||
sead::SafeArray<res::Handle, 28> mResHandles;
|
||||
sead::SafeArray<res::Handle, ActorParam::NumResourceTypes> mDummyResources;
|
||||
mutable sead::CriticalSection mCS;
|
||||
};
|
||||
KSYS_CHECK_SIZE_NX150(ActorParamMgr, 0xa00);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "KingSystem/ActorSystem/actActorTemplate.h"
|
||||
#include "KingSystem/ActorSystem/actActorParamMgr.h"
|
||||
#include "KingSystem/Utils/Byaml.h"
|
||||
#include "KingSystem/Utils/Byaml/Byaml.h"
|
||||
#include "KingSystem/Utils/SafeDelete.h"
|
||||
|
||||
namespace ksys::act {
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
#include "KingSystem/ActorSystem/actAttention.h"
|
||||
|
||||
namespace ksys::act {
|
||||
|
||||
SEAD_ENUM_IMPL(AttActionType)
|
||||
|
||||
SEAD_ENUM_IMPL(AttPriorityType)
|
||||
|
||||
} // namespace ksys::act
|
||||
@@ -0,0 +1,70 @@
|
||||
#pragma once
|
||||
|
||||
#include <prim/seadEnum.h>
|
||||
|
||||
namespace ksys::act {
|
||||
|
||||
enum class AttType {
|
||||
Action = 0,
|
||||
Lock = 1,
|
||||
SwordSearch = 2,
|
||||
Attack = 3,
|
||||
Appeal = 4,
|
||||
JumpRide = 5,
|
||||
NameBalloon = 6,
|
||||
LookOnly = 7,
|
||||
Invalid = 8,
|
||||
};
|
||||
|
||||
// Make sure to update AttActionType if this is changed
|
||||
enum class AttActionCode {
|
||||
None = 0x1800000,
|
||||
Talk,
|
||||
Listen,
|
||||
Awake,
|
||||
Grab,
|
||||
Open,
|
||||
Pick,
|
||||
Catch,
|
||||
CheckCatch,
|
||||
CatchWeapon,
|
||||
Skin,
|
||||
Sleep,
|
||||
Sit,
|
||||
Lumber,
|
||||
Pushpull,
|
||||
Read,
|
||||
Check,
|
||||
Boot,
|
||||
BootPStop,
|
||||
Leave,
|
||||
Remind,
|
||||
Buy,
|
||||
Ride,
|
||||
Wakeboard,
|
||||
WakeboardRide,
|
||||
RideRito,
|
||||
RideZora,
|
||||
Cook,
|
||||
KillTime,
|
||||
Display,
|
||||
DisplayBow,
|
||||
DisplayShield,
|
||||
PickUp,
|
||||
Pray,
|
||||
PullOut,
|
||||
Waterfall,
|
||||
CommandWait,
|
||||
CommandCome,
|
||||
Thrust,
|
||||
Put,
|
||||
PickToEvent,
|
||||
Dummy,
|
||||
};
|
||||
|
||||
// clang-format off
|
||||
SEAD_ENUM(AttActionType, None,Talk,Listen,Awake,Grab,Open,Pick,Catch,CheckCatch,CatchWeapon,Skin,Sleep,Sit,Lumber,Pushpull,Read,Check,Boot,BootPStop,Leave,Remind,Buy,Ride,Wakeboard,WakeboardRide,RideRito,RideZora,Cook,KillTime,Display,DisplayBow,DisplayShield,PickUp,Pray,PullOut,Waterfall,CommandWait,CommandCome,Thrust,Put,PickToEvent,Dummy)
|
||||
SEAD_ENUM(AttPriorityType, Default,Enemy,Npc,Obj,ObjLow,ObjMiddle,ObjHigh,Bullet)
|
||||
// clang-format on
|
||||
|
||||
} // namespace ksys::act
|
||||
@@ -0,0 +1,296 @@
|
||||
#include "KingSystem/ActorSystem/actInfoData.h"
|
||||
#include <codec/seadHashCRC32.h>
|
||||
#include <math/seadMathNumbers.h>
|
||||
#include "KingSystem/Utils/Byaml/Byaml.h"
|
||||
#include "KingSystem/Utils/Byaml/ByamlArrayIter.h"
|
||||
#include "KingSystem/Utils/Byaml/ByamlData.h"
|
||||
#include "KingSystem/Utils/Byaml/ByamlHashIter.h"
|
||||
|
||||
namespace ksys::act {
|
||||
|
||||
SEAD_SINGLETON_DISPOSER_IMPL(InfoData)
|
||||
|
||||
InfoData::~InfoData() {
|
||||
if (mHashesIter)
|
||||
delete mHashesIter;
|
||||
|
||||
if (mActorsIter)
|
||||
delete mActorsIter;
|
||||
|
||||
if (mRootIter)
|
||||
delete mRootIter;
|
||||
|
||||
mRootIter = nullptr;
|
||||
mHashesIter = nullptr;
|
||||
mActorsIter = nullptr;
|
||||
mHashesBytes = nullptr;
|
||||
mHashes = nullptr;
|
||||
mActorsBytes = nullptr;
|
||||
mActorOffsets = nullptr;
|
||||
}
|
||||
|
||||
void InfoData::init(u8* data, sead::Heap* heap, sead::Heap* debug_heap) {
|
||||
mRootIter = new (heap) al::ByamlIter(data);
|
||||
mHashesIter = new (heap) al::ByamlIter();
|
||||
mActorsIter = new (heap) al::ByamlIter();
|
||||
|
||||
if (debug_heap) {
|
||||
mDebugEntries = new (debug_heap) DebugEntry[NumDebugEntries];
|
||||
for (s32 i = 0; i != NumDebugEntries; ++i)
|
||||
mDebugEntries[i].used = false;
|
||||
} else {
|
||||
mDebugEntries = nullptr;
|
||||
}
|
||||
|
||||
if (mRootIter->tryGetIterByKey(mHashesIter, "Hashes")) {
|
||||
mHashesBytes = mHashesIter->getData();
|
||||
mHashes = al::ByamlArrayIter(mHashesIter->getRootNode()).getDataTable();
|
||||
}
|
||||
|
||||
if (mRootIter->tryGetIterByKey(mActorsIter, "Actors")) {
|
||||
mActorsBytes = mActorsIter->getData();
|
||||
mActorOffsets = al::ByamlArrayIter(mActorsIter->getRootNode()).getDataTable();
|
||||
}
|
||||
|
||||
mNumActors = mActorsIter->getSize();
|
||||
_88 = 0;
|
||||
mDebugHeap = debug_heap;
|
||||
mTagsIdx = mRootIter->getKeyIndex("tags");
|
||||
mProfileIdx = mRootIter->getKeyIndex("profile");
|
||||
mInvalidWeathersIdx = mRootIter->getKeyIndex("invalidWeathers");
|
||||
mInvalidTimesIdx = mRootIter->getKeyIndex("invalidTimes");
|
||||
mNameIdx = mRootIter->getKeyIndex("name");
|
||||
mSystemSameGroupActorNameIdx = mRootIter->getKeyIndex("systemSameGroupActorName");
|
||||
}
|
||||
|
||||
bool InfoData::getActorIter(al::ByamlIter* iter, const char* actor, bool x) const {
|
||||
const u32 hash = sead::HashCRC32::calcStringHash(actor);
|
||||
|
||||
// Perform a binary search.
|
||||
s32 a = 0;
|
||||
s32 b = mNumActors;
|
||||
while (a < b) {
|
||||
const s32 idx = (a + b) / 2;
|
||||
const u32 hash_i = mHashes[idx];
|
||||
|
||||
if (hash_i == hash) {
|
||||
*iter = al::ByamlIter(mActorsBytes, mActorsBytes + mActorOffsets[idx]);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (hash_i >= hash)
|
||||
b = idx;
|
||||
else
|
||||
a = idx + 1;
|
||||
}
|
||||
|
||||
if (x)
|
||||
static_cast<void>(logFailure(actor));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void InfoData::getRecipeInfo(const char* actor, InfoData::RecipeInfo& info) const {
|
||||
al::ByamlIter iter;
|
||||
if (getActorIter(&iter, actor)) {
|
||||
info.num_items = iter.getIntByKey("normal0StuffNum");
|
||||
|
||||
info.items[0].name = iter.getStringByKey("normal0ItemName01");
|
||||
info.items[0].num = iter.getIntByKey("normal0ItemNum01");
|
||||
|
||||
info.items[1].name = iter.getStringByKey("normal0ItemName02");
|
||||
info.items[1].num = iter.getIntByKey("normal0ItemNum02");
|
||||
|
||||
info.items[2].name = iter.getStringByKey("normal0ItemName03");
|
||||
info.items[2].num = iter.getIntByKey("normal0ItemNum03");
|
||||
|
||||
} else {
|
||||
info.num_items = 0;
|
||||
|
||||
info.items[0].name = sead::SafeString::cEmptyString;
|
||||
info.items[0].num = 0;
|
||||
|
||||
info.items[1].name = sead::SafeString::cEmptyString;
|
||||
info.items[1].num = 0;
|
||||
|
||||
info.items[2].name = sead::SafeString::cEmptyString;
|
||||
info.items[2].num = 0;
|
||||
}
|
||||
}
|
||||
|
||||
s32 InfoData::getIntByKey(const al::ByamlIter& iter, const char* key, s32 default_) {
|
||||
s32 value;
|
||||
return iter.tryGetIntByKey(&value, key) ? value : default_;
|
||||
}
|
||||
|
||||
const char* InfoData::getStringByKey(const al::ByamlIter& iter, const char* key,
|
||||
const sead::SafeString& default_) {
|
||||
const char* value;
|
||||
return iter.tryGetStringByKey(&value, key) ? value : default_.cstr();
|
||||
}
|
||||
|
||||
[[gnu::noinline]] static InfoData::Locator::Type
|
||||
getLocatorTypeFromStr(const sead::SafeString& type) {
|
||||
static constexpr const char* types[] = {"Trunk", "Branch", "GlowStone",
|
||||
"OnTree", "MagnePos", "StopTimerPos"};
|
||||
for (s32 i = 0; i < s32(std::size(types)); ++i) {
|
||||
if (type == types[i])
|
||||
return InfoData::Locator::Type(i);
|
||||
}
|
||||
return InfoData::Locator::Type::Invalid;
|
||||
}
|
||||
|
||||
void InfoData::getLocators(const char* actor, Locators& info) const {
|
||||
info.num = 0;
|
||||
|
||||
al::ByamlIter iter;
|
||||
if (!getActorIter(&iter, actor))
|
||||
return;
|
||||
|
||||
al::ByamlIter iter_locators;
|
||||
if (!iter.tryGetIterByKey(&iter_locators, "locators"))
|
||||
return;
|
||||
|
||||
info.num = iter_locators.getSize();
|
||||
for (s32 i = 0; i < info.num; ++i) {
|
||||
al::ByamlIter it;
|
||||
if (!iter_locators.tryGetIterByIndex(&it, i))
|
||||
continue;
|
||||
|
||||
const char* type_str{};
|
||||
auto& locator = info.locators[i];
|
||||
|
||||
it.tryGetFloatByKey(&locator.pos.x, "pos_x");
|
||||
it.tryGetFloatByKey(&locator.pos.y, "pos_y");
|
||||
it.tryGetFloatByKey(&locator.pos.z, "pos_z");
|
||||
|
||||
it.tryGetFloatByKey(&locator.rot.x, "rot_x");
|
||||
it.tryGetFloatByKey(&locator.rot.y, "rot_y");
|
||||
it.tryGetFloatByKey(&locator.rot.z, "rot_z");
|
||||
|
||||
it.tryGetStringByKey(&type_str, "type");
|
||||
locator.type = type_str ? getLocatorTypeFromStr(type_str) : Locator::Type::Invalid;
|
||||
|
||||
locator.rot *= 2 * sead::numbers::pi / 360.0;
|
||||
}
|
||||
}
|
||||
|
||||
void InfoData::getHomeAreas(const char* actor, HomeAreas& info) const {
|
||||
info.names.fill("");
|
||||
|
||||
al::ByamlIter iter;
|
||||
if (!getActorIter(&iter, actor))
|
||||
return;
|
||||
|
||||
al::ByamlIter home_area;
|
||||
if (!iter.tryGetIterByKey(&home_area, "homeArea"))
|
||||
return;
|
||||
|
||||
for (s32 i = 0, n = home_area.getSize(); i < info.names.size() && i < n; ++i) {
|
||||
al::ByamlIter it;
|
||||
if (home_area.tryGetIterByIndex(&it, i))
|
||||
it.tryGetStringByKey(&info.names[i], "name");
|
||||
}
|
||||
}
|
||||
|
||||
const char* InfoData::getSameGroupActorName(const char* actor) const {
|
||||
al::ByamlIter iter;
|
||||
return [&] {
|
||||
if (getActorIter(&iter, actor, false)) {
|
||||
al::ByamlHashIter hash_iter{iter.getRootNode()};
|
||||
al::ByamlData data;
|
||||
if (hash_iter.getDataByKey(&data, mSystemSameGroupActorNameIdx)) {
|
||||
const char* name;
|
||||
if (iter.tryConvertString(&name, &data))
|
||||
return name;
|
||||
}
|
||||
}
|
||||
return sead::SafeString::cEmptyString.cstr();
|
||||
}();
|
||||
}
|
||||
|
||||
const char* InfoData::getString(const char* actor, const char* key,
|
||||
const sead::SafeString& default_, bool x) const {
|
||||
al::ByamlIter iter;
|
||||
if (!getActorIter(&iter, actor, x))
|
||||
return default_.cstr();
|
||||
|
||||
return getStringByKey(iter, key, default_);
|
||||
}
|
||||
|
||||
const char* InfoData::getSLinkUser(const char* actor) const {
|
||||
al::ByamlIter iter;
|
||||
if (!getActorIter(&iter, actor))
|
||||
return "Dummy";
|
||||
|
||||
return getStringByKey(iter, "slink", "Dummy");
|
||||
}
|
||||
|
||||
bool InfoData::getSLinkAndELinkUsers(const char* actor, const char** elink,
|
||||
const char** slink) const {
|
||||
al::ByamlIter iter;
|
||||
if (getActorIter(&iter, actor)) {
|
||||
*elink = getStringByKey(iter, "elink", "Dummy");
|
||||
*slink = getStringByKey(iter, "slink", "Dummy");
|
||||
return true;
|
||||
}
|
||||
*elink = "Dummy";
|
||||
*slink = "Dummy";
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* InfoData::getXLinkUser(const char* actor) const {
|
||||
return getString(actor, "xlink", "Dummy");
|
||||
}
|
||||
|
||||
bool InfoData::getActorProfile(const char** profile, const char* actor) const {
|
||||
al::ByamlIter iter;
|
||||
if (getActorIter(&iter, actor)) {
|
||||
al::ByamlHashIter hash_iter{iter.getRootNode()};
|
||||
al::ByamlData data;
|
||||
if (hash_iter.getDataByKey(&data, mProfileIdx))
|
||||
return iter.tryConvertString(profile, &data);
|
||||
}
|
||||
*profile = "Dummy";
|
||||
return false;
|
||||
}
|
||||
|
||||
s32 InfoData::getInt(const char* actor, const char* key, s32 default_, bool x) const {
|
||||
al::ByamlIter iter;
|
||||
if (!getActorIter(&iter, actor, x))
|
||||
return default_;
|
||||
|
||||
return getIntByKey(iter, key, default_);
|
||||
}
|
||||
|
||||
f32 InfoData::getFloat(const char* actor, const char* key, f32 default_, bool x) const {
|
||||
al::ByamlIter iter;
|
||||
if (!getActorIter(&iter, actor, x))
|
||||
return default_;
|
||||
|
||||
return getFloatByKey(iter, key, default_);
|
||||
}
|
||||
|
||||
bool InfoData::getBool(const char* actor, const char* key, bool default_, bool x) const {
|
||||
al::ByamlIter iter;
|
||||
if (!getActorIter(&iter, actor, x))
|
||||
return default_;
|
||||
|
||||
return getBoolByKey(iter, key, default_);
|
||||
}
|
||||
|
||||
f32 InfoData::getFloatByKey(const al::ByamlIter& iter, const char* key, f32 default_) {
|
||||
f32 value;
|
||||
return iter.tryGetFloatByKey(&value, key) ? value : default_;
|
||||
}
|
||||
|
||||
bool InfoData::getBoolByKey(const al::ByamlIter& iter, const char* key, bool default_) {
|
||||
bool value;
|
||||
return iter.tryGetBoolByKey(&value, key) ? value != 0 : default_;
|
||||
}
|
||||
|
||||
f32 InfoData::getScale(const char* actor) const {
|
||||
return getFloat(actor, "actorScale", 1.0);
|
||||
}
|
||||
|
||||
} // namespace ksys::act
|
||||
@@ -0,0 +1,135 @@
|
||||
#pragma once
|
||||
|
||||
#include <basis/seadTypes.h>
|
||||
#include <container/seadSafeArray.h>
|
||||
#include <gfx/seadColor.h>
|
||||
#include <heap/seadDisposer.h>
|
||||
#include <math/seadVector.h>
|
||||
#include <prim/seadSafeString.h>
|
||||
#include "KingSystem/Utils/Types.h"
|
||||
|
||||
namespace al {
|
||||
class ByamlIter;
|
||||
}
|
||||
|
||||
namespace ksys::act {
|
||||
|
||||
class InfoData {
|
||||
SEAD_SINGLETON_DISPOSER(InfoData)
|
||||
InfoData() = default;
|
||||
virtual ~InfoData();
|
||||
|
||||
public:
|
||||
struct ModelInfo {
|
||||
sead::Vector3f baseScale;
|
||||
sead::Color4f addColor;
|
||||
sead::Color4f mulColor;
|
||||
const char* bfres;
|
||||
const char* mainModel;
|
||||
};
|
||||
KSYS_CHECK_SIZE_NX150(ModelInfo, 0x40);
|
||||
|
||||
struct RecipeInfo {
|
||||
struct Item {
|
||||
sead::FixedSafeString<64> name;
|
||||
s32 num;
|
||||
};
|
||||
|
||||
s32 num_items;
|
||||
Item items[3];
|
||||
};
|
||||
KSYS_CHECK_SIZE_NX150(RecipeInfo, 0x128);
|
||||
|
||||
struct Locator {
|
||||
enum class Type {
|
||||
Invalid = -1,
|
||||
Trunk = 0,
|
||||
Branch = 1,
|
||||
GlowStone = 2,
|
||||
OnTree = 3,
|
||||
MagnePos = 4,
|
||||
StopTimerPos = 5,
|
||||
};
|
||||
|
||||
Type type;
|
||||
sead::Vector3f pos;
|
||||
sead::Vector3f rot;
|
||||
};
|
||||
KSYS_CHECK_SIZE_NX150(Locator, 0x1c);
|
||||
|
||||
struct Locators {
|
||||
s32 num;
|
||||
sead::SafeArray<Locator, 8> locators;
|
||||
};
|
||||
KSYS_CHECK_SIZE_NX150(Locators, 0xe4);
|
||||
|
||||
struct HomeAreas {
|
||||
sead::SafeArray<const char*, 3> names;
|
||||
};
|
||||
KSYS_CHECK_SIZE_NX150(HomeAreas, 0x18);
|
||||
|
||||
void init(u8* data, sead::Heap* heap, sead::Heap* debug_heap);
|
||||
|
||||
void getModelInfo(const char* actor, ModelInfo& info) const;
|
||||
bool getActorIter(al::ByamlIter* iter, const char* actor, bool x = true) const;
|
||||
bool logFailure(const sead::SafeString& actor_name) const;
|
||||
void getRecipeInfo(const char* actor, RecipeInfo& info) const;
|
||||
void getLocators(const char* actor, Locators& info) const;
|
||||
void getHomeAreas(const char* actor, HomeAreas& info) const;
|
||||
// TODO: invalid time function
|
||||
// TODO: tag functions
|
||||
const char* getSameGroupActorName(const char* actor) const;
|
||||
// TODO: more functions
|
||||
const char* getSLinkUser(const char* actor) const;
|
||||
bool getSLinkAndELinkUsers(const char* actor, const char** elink, const char** slink) const;
|
||||
const char* getXLinkUser(const char* actor) const;
|
||||
bool getActorProfile(const char** profile, const char* actor) const;
|
||||
// TODO: more functions
|
||||
f32 getScale(const char* actor) const;
|
||||
|
||||
const char* getString(const char* actor, const char* key, const sead::SafeString& default_,
|
||||
bool x = true) const;
|
||||
s32 getInt(const char* actor, const char* key, s32 default_ = 0, bool x = true) const;
|
||||
f32 getFloat(const char* actor, const char* key, f32 default_ = 0, bool x = true) const;
|
||||
bool getBool(const char* actor, const char* key, bool default_ = false, bool x = true) const;
|
||||
|
||||
static s32 getIntByKey(const al::ByamlIter& iter, const char* key, s32 default_ = 0);
|
||||
static f32 getFloatByKey(const al::ByamlIter& iter, const char* key, f32 default_ = 0);
|
||||
static bool getBoolByKey(const al::ByamlIter& iter, const char* key, bool default_ = false);
|
||||
static const char* getStringByKey(const al::ByamlIter& iter, const char* key,
|
||||
const sead::SafeString& default_);
|
||||
|
||||
private:
|
||||
struct DebugEntry {
|
||||
sead::FixedSafeString<64> str;
|
||||
bool used;
|
||||
};
|
||||
KSYS_CHECK_SIZE_NX150(DebugEntry, 0x60);
|
||||
|
||||
al::ByamlIter* mRootIter{};
|
||||
al::ByamlIter* mHashesIter{};
|
||||
al::ByamlIter* mActorsIter{};
|
||||
|
||||
const u8* mHashesBytes{};
|
||||
const u32* mHashes{};
|
||||
|
||||
const u8* mActorsBytes{};
|
||||
const u32* mActorOffsets{};
|
||||
|
||||
s32 mTagsIdx = -1;
|
||||
s32 mInvalidWeathersIdx = -1;
|
||||
s32 mInvalidTimesIdx = -1;
|
||||
s32 mSystemSameGroupActorNameIdx = -1;
|
||||
s32 mNameIdx = -1;
|
||||
s32 mProfileIdx = -1;
|
||||
|
||||
s32 mNumActors = 0;
|
||||
DebugEntry* mDebugEntries{};
|
||||
u32 _88 = 0;
|
||||
sead::Heap* mDebugHeap{};
|
||||
|
||||
static constexpr s32 NumDebugEntries = 512;
|
||||
};
|
||||
KSYS_CHECK_SIZE_NX150(InfoData, 0x98);
|
||||
|
||||
} // namespace ksys::act
|
||||
Reference in New Issue
Block a user