mirror of
https://github.com/MonsterDruide1/OdysseyDecomp
synced 2026-04-29 20:14:41 +00:00
258 lines
11 KiB
C++
258 lines
11 KiB
C++
#include "Library/LiveActor/LiveActorKeeper.h"
|
|
|
|
#include "Library/Base/StringUtil.h"
|
|
#include "Library/LiveActor/ActorInitFunction.h"
|
|
#include "Library/LiveActor/ActorInitUtil.h"
|
|
#include "Library/LiveActor/ActorModelFunction.h"
|
|
#include "Library/LiveActor/ActorResourceFunction.h"
|
|
#include "Library/LiveActor/ActorSensorUtil.h"
|
|
#include "Library/LiveActor/LiveActorInfo.h"
|
|
#include "Library/Obj/BreakModel.h"
|
|
#include "Library/Obj/CollisionObj.h"
|
|
#include "Library/Obj/DepthShadowModel.h"
|
|
#include "Library/Obj/ModelDrawParts.h"
|
|
#include "Library/Obj/PartsFunction.h"
|
|
#include "Library/Obj/PartsModel.h"
|
|
#include "Library/Obj/SilhouetteModel.h"
|
|
#include "Library/Obj/SimpleCircleShadowXZ.h"
|
|
#include "Library/Yaml/ByamlUtil.h"
|
|
|
|
namespace al {
|
|
|
|
SubActorKeeper::SubActorKeeper(LiveActor* rootActor) {
|
|
mRootActor = rootActor;
|
|
}
|
|
|
|
void SubActorKeeper::registerSubActor(LiveActor* subActor, u32 syncType) {
|
|
mBuffer[mCurActorCount] = new SubActorInfo(subActor, static_cast<SubActorSync>(syncType));
|
|
mCurActorCount++;
|
|
}
|
|
|
|
// NON_MATCHING: https://decomp.me/scratch/9V8dS
|
|
void SubActorKeeper::init(const ActorInitInfo& initInfo, const char* suffix, s32 maxSubActors) {
|
|
sead::FixedSafeString<0x80> actorInitFileName;
|
|
s32 creatorCount;
|
|
const u8* modelResourceYaml;
|
|
|
|
if (isExistModelResource(mRootActor) &&
|
|
!tryGetActorInitFileName(&actorInitFileName, mRootActor, "InitSubActor", suffix))
|
|
createFileNameBySuffix(&actorInitFileName, "InitSubActor", suffix);
|
|
|
|
if (isExistModelResource(mRootActor) &&
|
|
isExistModelResourceYaml(mRootActor, actorInitFileName.cstr(), nullptr)) {
|
|
modelResourceYaml = getModelResourceYaml(mRootActor, actorInitFileName.cstr(), nullptr);
|
|
ByamlIter modelResourceIter(modelResourceYaml);
|
|
ByamlIter initInfoIter;
|
|
if (modelResourceIter.tryGetIterByKey(&initInfoIter, "InitInfo")) {
|
|
s32 addActorNum = 0;
|
|
if (initInfoIter.tryGetIntByKey(&addActorNum, "AddActorNum"))
|
|
maxSubActors += addActorNum;
|
|
}
|
|
ByamlIter creatorIter;
|
|
if (modelResourceIter.tryGetIterByKey(&creatorIter, "CreatorList"))
|
|
creatorCount = creatorIter.getSize();
|
|
else
|
|
creatorCount = 0;
|
|
} else {
|
|
modelResourceYaml = nullptr;
|
|
creatorCount = 0;
|
|
}
|
|
|
|
s32 actorCount = maxSubActors + creatorCount;
|
|
mMaxActorCount = actorCount;
|
|
mBuffer = new SubActorInfo*[maxSubActors + creatorCount];
|
|
|
|
if (actorCount >= 1 && mMaxActorCount >= 2)
|
|
for (s32 i = 1; i < mMaxActorCount; ++i)
|
|
mBuffer[i] = nullptr;
|
|
|
|
if (modelResourceYaml && creatorCount > 0) {
|
|
ByamlIter modelResourceIter(modelResourceYaml);
|
|
ByamlIter creatorIter;
|
|
modelResourceIter.tryGetIterByKey(&creatorIter, "CreatorList");
|
|
|
|
// TODO: finish the logic for this, it seems like theres some heavy optimizations going on,
|
|
// making it tough to figure out original logic
|
|
for (s32 i = 0; i < creatorCount; ++i) {
|
|
ByamlIter subActorIter;
|
|
creatorIter.tryGetIterByIndex(&subActorIter, i);
|
|
|
|
SubActorInfo* actorInfo = new SubActorInfo();
|
|
mBuffer[i] = actorInfo;
|
|
|
|
const char* actorObjectName = tryGetByamlKeyStringOrNULL(subActorIter, "ObjectName");
|
|
const char* actorModelName = tryGetByamlKeyStringOrNULL(subActorIter, "ModelName");
|
|
const char* actorSuffix =
|
|
tryGetByamlKeyStringOrNULL(subActorIter, "InitFileSuffixName");
|
|
const char* actorClassName = tryGetByamlKeyStringOrNULL(subActorIter, "ClassName");
|
|
const char* actorCategoryName =
|
|
tryGetByamlKeyStringOrNULL(subActorIter, "CategoryName");
|
|
|
|
bool isAlive = false;
|
|
bool isAliveResult = subActorIter.tryGetBoolByKey(&isAlive, "IsAlive");
|
|
|
|
bool isUseHostPlacementInfo = true;
|
|
subActorIter.tryGetBoolByKey(&isUseHostPlacementInfo, "IsUseHostPlacementInfo");
|
|
|
|
bool isSyncAppear = false;
|
|
bool isGotSyncAppear = tryGetByamlBool(&isSyncAppear, subActorIter, "IsSyncAppear");
|
|
if (isSyncAppear)
|
|
actorInfo->syncType |= SubActorSync::cAppear;
|
|
|
|
bool isSyncHide = false;
|
|
bool isGotSyncHide = tryGetByamlBool(&isSyncHide, subActorIter, "IsSyncHide");
|
|
if (isSyncHide)
|
|
actorInfo->syncType |= SubActorSync::cHide;
|
|
|
|
if (tryGetByamlKeyBoolOrFalse(subActorIter, "IsSyncAlphaMask"))
|
|
actorInfo->syncType |= SubActorSync::cAlphaMask;
|
|
|
|
if (tryGetByamlKeyBoolOrFalse(subActorIter, "IsSyncClipping"))
|
|
actorInfo->syncType |= SubActorSync::cClipping;
|
|
|
|
bool isCalcDepthShadowLength = true;
|
|
tryGetByamlBool(&isCalcDepthShadowLength, subActorIter, "IsCalcDepthShadowLength");
|
|
|
|
if (actorClassName && !isEqualString(actorClassName, "LiveActor")) {
|
|
if (isEqualString(actorClassName, "PartsModel")) {
|
|
const char* actorFixFileSuffixName =
|
|
tryGetByamlKeyStringOrNULL(subActorIter, "FixFileSuffixName");
|
|
PartsModel* partsModel = new PartsModel(actorObjectName);
|
|
partsModel->initPartsFixFileNoRegister(mRootActor, initInfo, actorModelName,
|
|
actorSuffix, actorFixFileSuffixName);
|
|
actorInfo->subActor = partsModel;
|
|
|
|
actorInfo->syncType =
|
|
(!isGotSyncAppear ? actorInfo->syncType | SubActorSync::cAppear :
|
|
actorInfo->syncType) |
|
|
SubActorSync::cClipping;
|
|
|
|
if (isExistModel(partsModel)) {
|
|
actorInfo->syncType =
|
|
(!isGotSyncHide ? actorInfo->syncType | SubActorSync::cHide :
|
|
actorInfo->syncType) |
|
|
SubActorSync::cAlphaMask;
|
|
}
|
|
} else if (isEqualString(actorClassName, "BreakModel")) {
|
|
const char* actionName = tryGetByamlKeyStringOrNULL(subActorIter, "ActionName");
|
|
const char* jointName = tryGetByamlKeyStringOrNULL(subActorIter, "JointName");
|
|
|
|
sead::Matrix34f* jointMtxPtr =
|
|
jointName ? getJointMtxPtr(mRootActor, jointName) : nullptr;
|
|
|
|
if (!actionName)
|
|
actionName = "Break";
|
|
|
|
BreakModel* breakModel =
|
|
new BreakModel(mRootActor, actorObjectName, actorModelName, actorSuffix,
|
|
jointMtxPtr, actionName);
|
|
|
|
initCreateActorNoPlacementInfo(breakModel, initInfo);
|
|
actorInfo->subActor = breakModel;
|
|
} else if (isEqualString(actorClassName, "SilhouetteModel")) {
|
|
actorInfo->subActor =
|
|
new SilhouetteModel(mRootActor, initInfo, actorCategoryName);
|
|
} else if (isEqualString(actorClassName, "DepthShadowModel")) {
|
|
actorInfo->subActor = new DepthShadowModel(
|
|
mRootActor, initInfo, actorCategoryName ? actorCategoryName : actorSuffix,
|
|
isCalcDepthShadowLength);
|
|
|
|
continue;
|
|
} else if (isEqualString(actorClassName, "InvincibleModel")) {
|
|
actorInfo->subActor =
|
|
new ModelDrawParts("無敵モデル", mRootActor, initInfo, actorCategoryName);
|
|
} else {
|
|
if (!isEqualString(actorClassName, "SimpleCircleShadowXZ")) {
|
|
if (isEqualString(actorClassName, "CollisionObj")) {
|
|
const char* collSuffixName =
|
|
tryGetByamlKeyStringOrNULL(subActorIter, "CollisionSuffixName");
|
|
const char* collName =
|
|
tryGetByamlKeyStringOrNULL(subActorIter, "CollisionName");
|
|
const char* sensorName =
|
|
tryGetByamlKeyStringOrNULL(subActorIter, "SensorName");
|
|
const char* fileSuffixName =
|
|
tryGetByamlKeyStringOrNULL(subActorIter, "InitFileSuffixName");
|
|
const char* jointName =
|
|
tryGetByamlKeyStringOrNULL(subActorIter, "JointName");
|
|
|
|
if (!collName)
|
|
collName = collSuffixName;
|
|
|
|
const char* newSensorName = sensorName ? sensorName : collSuffixName;
|
|
|
|
if (fileSuffixName)
|
|
collSuffixName = fileSuffixName;
|
|
|
|
auto* sensor = getHitSensor(mRootActor, newSensorName);
|
|
|
|
actorInfo->subActor = createCollisionObj(
|
|
mRootActor, initInfo, collName, sensor, jointName, collSuffixName);
|
|
if (actorObjectName)
|
|
actorInfo->subActor->setName(actorObjectName);
|
|
|
|
continue;
|
|
}
|
|
|
|
actorInfo->subActor = new LiveActor(actorObjectName);
|
|
initActorWithArchiveName(actorInfo->subActor, initInfo, actorModelName,
|
|
actorSuffix);
|
|
|
|
continue;
|
|
}
|
|
|
|
SimpleCircleShadowXZ* dropShadow = new SimpleCircleShadowXZ(actorObjectName);
|
|
dropShadow->initSimpleCircleShadow(mRootActor, initInfo, actorModelName,
|
|
actorSuffix);
|
|
actorInfo->subActor = dropShadow;
|
|
}
|
|
} else {
|
|
actorInfo->subActor = new LiveActor(actorObjectName);
|
|
|
|
if (isUseHostPlacementInfo) {
|
|
initActorWithArchiveName(actorInfo->subActor, initInfo, actorModelName,
|
|
actorSuffix);
|
|
} else {
|
|
initChildActorWithArchiveNameNoPlacementInfo(actorInfo->subActor, initInfo,
|
|
actorModelName, actorSuffix);
|
|
}
|
|
}
|
|
|
|
initActorModelForceCubeMap(actorInfo->subActor, initInfo);
|
|
|
|
if (isAliveResult) {
|
|
if (isAlive)
|
|
actorInfo->subActor->makeActorAlive();
|
|
else
|
|
actorInfo->subActor->makeActorDead();
|
|
}
|
|
bool isShow = false;
|
|
if (tryGetByamlBool(&isShow, subActorIter, "IsShow") && !isShow)
|
|
hideModel(actorInfo->subActor);
|
|
}
|
|
}
|
|
}
|
|
|
|
SubActorKeeper* SubActorKeeper::create(LiveActor* rootActor) {
|
|
return new SubActorKeeper(rootActor);
|
|
}
|
|
|
|
SubActorKeeper* SubActorKeeper::tryCreate(LiveActor* rootActor, const char* suffix,
|
|
s32 maxSubActors) {
|
|
sead::FixedSafeString<0x80> actorInitFileName;
|
|
|
|
if (!isExistModelResource(rootActor) ||
|
|
!tryGetActorInitFileName(&actorInitFileName, rootActor, "InitSubActor", suffix))
|
|
return nullptr;
|
|
|
|
if (maxSubActors <= 0) {
|
|
if (!isExistModelResource(rootActor))
|
|
return nullptr;
|
|
|
|
if (!isExistModelResourceYaml(rootActor, actorInitFileName.cstr(), nullptr))
|
|
return nullptr;
|
|
}
|
|
|
|
return new SubActorKeeper(rootActor);
|
|
}
|
|
} // namespace al
|