| 1 | #include "Library/LiveActor/LiveActorKeeper.h" |
| 2 | |
| 3 | #include "Library/Base/StringUtil.h" |
| 4 | #include "Library/LiveActor/ActorInitFunction.h" |
| 5 | #include "Library/LiveActor/ActorInitUtil.h" |
| 6 | #include "Library/LiveActor/ActorModelFunction.h" |
| 7 | #include "Library/LiveActor/ActorResourceFunction.h" |
| 8 | #include "Library/LiveActor/ActorSensorUtil.h" |
| 9 | #include "Library/LiveActor/LiveActorInfo.h" |
| 10 | #include "Library/Obj/BreakModel.h" |
| 11 | #include "Library/Obj/CollisionObj.h" |
| 12 | #include "Library/Obj/DepthShadowModel.h" |
| 13 | #include "Library/Obj/ModelDrawParts.h" |
| 14 | #include "Library/Obj/PartsFunction.h" |
| 15 | #include "Library/Obj/PartsModel.h" |
| 16 | #include "Library/Obj/SilhouetteModel.h" |
| 17 | #include "Library/Obj/SimpleCircleShadowXZ.h" |
| 18 | #include "Library/Yaml/ByamlUtil.h" |
| 19 | |
| 20 | namespace al { |
| 21 | |
| 22 | SubActorKeeper::SubActorKeeper(LiveActor* rootActor) { |
| 23 | mRootActor = rootActor; |
| 24 | } |
| 25 | |
| 26 | void SubActorKeeper::registerSubActor(LiveActor* subActor, u32 syncType) { |
| 27 | mBuffer[mCurActorCount] = new SubActorInfo(subActor, static_cast<SubActorSync>(syncType)); |
| 28 | mCurActorCount++; |
| 29 | } |
| 30 | |
| 31 | // NON_MATCHING |
| 32 | void SubActorKeeper::init(const ActorInitInfo& initInfo, const char* suffix, s32 maxSubActors) { |
| 33 | sead::FixedSafeString<0x80> actorInitFileName; |
| 34 | s32 creatorCount; |
| 35 | u8* modelResourceYaml; |
| 36 | |
| 37 | if (isExistModelResource(mRootActor) && |
| 38 | !tryGetActorInitFileName(&actorInitFileName, mRootActor, "InitSubActor" , suffix)) |
| 39 | createFileNameBySuffix(out: &actorInitFileName, name: "InitSubActor" , suffix); |
| 40 | |
| 41 | if (isExistModelResource(mRootActor) && |
| 42 | isExistModelResourceYaml(mRootActor, actorInitFileName.cstr(), nullptr)) { |
| 43 | modelResourceYaml = getModelResourceYaml(mRootActor, actorInitFileName.cstr(), nullptr); |
| 44 | ByamlIter modelResourceIter(modelResourceYaml); |
| 45 | ByamlIter initInfoIter; |
| 46 | if (modelResourceIter.tryGetIterByKey(iter: &initInfoIter, key: "InitInfo" )) { |
| 47 | s32 addActorNum = 0; |
| 48 | if (initInfoIter.tryGetIntByKey(val: &addActorNum, key: "AddActorNum" )) |
| 49 | maxSubActors += addActorNum; |
| 50 | } |
| 51 | ByamlIter creatorIter; |
| 52 | if (modelResourceIter.tryGetIterByKey(iter: &creatorIter, key: "CreatorList" )) |
| 53 | creatorCount = creatorIter.getSize(); |
| 54 | else |
| 55 | creatorCount = 0; |
| 56 | } else { |
| 57 | modelResourceYaml = nullptr; |
| 58 | creatorCount = 0; |
| 59 | } |
| 60 | |
| 61 | s32 actorCount = maxSubActors + creatorCount; |
| 62 | mMaxActorCount = actorCount; |
| 63 | mBuffer = new SubActorInfo*[maxSubActors + creatorCount]; |
| 64 | |
| 65 | if (actorCount >= 1 && mMaxActorCount >= 2) |
| 66 | for (s32 i = 1; i < mMaxActorCount; ++i) |
| 67 | mBuffer[i] = nullptr; |
| 68 | |
| 69 | if (modelResourceYaml && creatorCount > 0) { |
| 70 | ByamlIter modelResourceIter(modelResourceYaml); |
| 71 | ByamlIter creatorIter; |
| 72 | modelResourceIter.tryGetIterByKey(iter: &creatorIter, key: "CreatorList" ); |
| 73 | |
| 74 | // TODO: finish the logic for this, it seems like theres some heavy optimizations going on, |
| 75 | // making it tough to figure out original logic |
| 76 | for (s32 i = 0; i < creatorCount; ++i) { |
| 77 | ByamlIter subActorIter; |
| 78 | creatorIter.tryGetIterByIndex(iter: &subActorIter, index: i); |
| 79 | |
| 80 | SubActorInfo* actorInfo = new SubActorInfo(); |
| 81 | mBuffer[i] = actorInfo; |
| 82 | |
| 83 | const char* actorObjectName = tryGetByamlKeyStringOrNULL(subActorIter, "ObjectName" ); |
| 84 | const char* actorModelName = tryGetByamlKeyStringOrNULL(subActorIter, "ModelName" ); |
| 85 | const char* actorSuffix = |
| 86 | tryGetByamlKeyStringOrNULL(subActorIter, "InitFileSuffixName" ); |
| 87 | const char* actorClassName = tryGetByamlKeyStringOrNULL(subActorIter, "ClassName" ); |
| 88 | const char* actorCategoryName = |
| 89 | tryGetByamlKeyStringOrNULL(subActorIter, "CategoryName" ); |
| 90 | |
| 91 | bool isAlive = false; |
| 92 | bool isAliveResult = subActorIter.tryGetBoolByKey(val: &isAlive, key: "IsAlive" ); |
| 93 | |
| 94 | bool isUseHostPlacementInfo = true; |
| 95 | subActorIter.tryGetBoolByKey(val: &isUseHostPlacementInfo, key: "IsUseHostPlacementInfo" ); |
| 96 | |
| 97 | bool isSyncAppear = false; |
| 98 | bool isGotSyncAppear = tryGetByamlBool(&isSyncAppear, subActorIter, "IsSyncAppear" ); |
| 99 | if (isSyncAppear) |
| 100 | actorInfo->syncType |= SubActorSync::cAppear; |
| 101 | |
| 102 | bool isSyncHide = false; |
| 103 | bool isGotSyncHide = tryGetByamlBool(&isSyncHide, subActorIter, "IsSyncHide" ); |
| 104 | if (isSyncHide) |
| 105 | actorInfo->syncType |= SubActorSync::cHide; |
| 106 | |
| 107 | if (tryGetByamlKeyBoolOrFalse(subActorIter, "IsSyncAlphaMask" )) |
| 108 | actorInfo->syncType |= SubActorSync::cAlphaMask; |
| 109 | |
| 110 | if (tryGetByamlKeyBoolOrFalse(subActorIter, "IsSyncClipping" )) |
| 111 | actorInfo->syncType |= SubActorSync::cClipping; |
| 112 | |
| 113 | bool isCalcDepthShadowLength = true; |
| 114 | tryGetByamlBool(&isCalcDepthShadowLength, subActorIter, "IsCalcDepthShadowLength" ); |
| 115 | |
| 116 | if (actorClassName && !isEqualString(str1: actorClassName, str2: "LiveActor" )) { |
| 117 | if (isEqualString(str1: actorClassName, str2: "PartsModel" )) { |
| 118 | const char* actorFixFileSuffixName = |
| 119 | tryGetByamlKeyStringOrNULL(subActorIter, "FixFileSuffixName" ); |
| 120 | PartsModel* partsModel = new PartsModel(actorObjectName); |
| 121 | partsModel->initPartsFixFileNoRegister(mRootActor, initInfo, actorModelName, |
| 122 | actorSuffix, actorFixFileSuffixName); |
| 123 | actorInfo->subActor = partsModel; |
| 124 | |
| 125 | actorInfo->syncType = |
| 126 | (!isGotSyncAppear ? actorInfo->syncType | SubActorSync::cAppear : |
| 127 | actorInfo->syncType) | |
| 128 | SubActorSync::cClipping; |
| 129 | |
| 130 | if (isExistModel(actor: partsModel)) { |
| 131 | actorInfo->syncType = |
| 132 | (!isGotSyncHide ? actorInfo->syncType | SubActorSync::cHide : |
| 133 | actorInfo->syncType) | |
| 134 | SubActorSync::cAlphaMask; |
| 135 | } |
| 136 | } else if (isEqualString(str1: actorClassName, str2: "BreakModel" )) { |
| 137 | const char* actionName = tryGetByamlKeyStringOrNULL(subActorIter, "ActionName" ); |
| 138 | const char* jointName = tryGetByamlKeyStringOrNULL(subActorIter, "JointName" ); |
| 139 | |
| 140 | sead::Matrix34f* jointMtxPtr = |
| 141 | jointName ? getJointMtxPtr(actor: mRootActor, jointName) : nullptr; |
| 142 | |
| 143 | if (!actionName) |
| 144 | actionName = "Break" ; |
| 145 | |
| 146 | BreakModel* breakModel = |
| 147 | new BreakModel(mRootActor, actorObjectName, actorModelName, actorSuffix, |
| 148 | jointMtxPtr, actionName); |
| 149 | |
| 150 | initCreateActorNoPlacementInfo(actor: breakModel, initInfo); |
| 151 | actorInfo->subActor = breakModel; |
| 152 | } else if (isEqualString(str1: actorClassName, str2: "SilhouetteModel" )) { |
| 153 | actorInfo->subActor = |
| 154 | new SilhouetteModel(mRootActor, initInfo, actorCategoryName); |
| 155 | } else if (isEqualString(str1: actorClassName, str2: "DepthShadowModel" )) { |
| 156 | actorInfo->subActor = new DepthShadowModel( |
| 157 | mRootActor, initInfo, actorCategoryName ? actorCategoryName : actorSuffix, |
| 158 | isCalcDepthShadowLength); |
| 159 | |
| 160 | continue; |
| 161 | } else if (isEqualString(str1: actorClassName, str2: "InvincibleModel" )) { |
| 162 | actorInfo->subActor = |
| 163 | new ModelDrawParts("無敵モデル" , mRootActor, initInfo, actorCategoryName); |
| 164 | } else { |
| 165 | if (!isEqualString(str1: actorClassName, str2: "SimpleCircleShadowXZ" )) { |
| 166 | if (isEqualString(str1: actorClassName, str2: "CollisionObj" )) { |
| 167 | const char* collSuffixName = |
| 168 | tryGetByamlKeyStringOrNULL(subActorIter, "CollisionSuffixName" ); |
| 169 | const char* collName = |
| 170 | tryGetByamlKeyStringOrNULL(subActorIter, "CollisionName" ); |
| 171 | const char* sensorName = |
| 172 | tryGetByamlKeyStringOrNULL(subActorIter, "SensorName" ); |
| 173 | const char* fileSuffixName = |
| 174 | tryGetByamlKeyStringOrNULL(subActorIter, "InitFileSuffixName" ); |
| 175 | const char* jointName = |
| 176 | tryGetByamlKeyStringOrNULL(subActorIter, "JointName" ); |
| 177 | |
| 178 | if (!collName) |
| 179 | collName = collSuffixName; |
| 180 | |
| 181 | const char* newSensorName = sensorName ? sensorName : collSuffixName; |
| 182 | |
| 183 | if (fileSuffixName) |
| 184 | collSuffixName = fileSuffixName; |
| 185 | |
| 186 | auto* sensor = getHitSensor(mRootActor, newSensorName); |
| 187 | |
| 188 | actorInfo->subActor = createCollisionObj( |
| 189 | parent: mRootActor, info: initInfo, collisionFileName: collName, hitSensor: sensor, joinMtxName: jointName, suffix: collSuffixName); |
| 190 | if (actorObjectName) |
| 191 | actorInfo->subActor->setName(actorObjectName); |
| 192 | |
| 193 | continue; |
| 194 | } |
| 195 | |
| 196 | actorInfo->subActor = new LiveActor(actorObjectName); |
| 197 | initActorWithArchiveName(actor: actorInfo->subActor, initInfo, archiveName: actorModelName, |
| 198 | suffix: actorSuffix); |
| 199 | |
| 200 | continue; |
| 201 | } |
| 202 | |
| 203 | SimpleCircleShadowXZ* dropShadow = new SimpleCircleShadowXZ(actorObjectName); |
| 204 | dropShadow->initSimpleCircleShadow(mRootActor, initInfo, actorModelName, |
| 205 | actorSuffix); |
| 206 | actorInfo->subActor = dropShadow; |
| 207 | } |
| 208 | } else { |
| 209 | actorInfo->subActor = new LiveActor(actorObjectName); |
| 210 | |
| 211 | if (isUseHostPlacementInfo) { |
| 212 | initActorWithArchiveName(actor: actorInfo->subActor, initInfo, archiveName: actorModelName, |
| 213 | suffix: actorSuffix); |
| 214 | } else { |
| 215 | initChildActorWithArchiveNameNoPlacementInfo(actor: actorInfo->subActor, initInfo, |
| 216 | archiveName: actorModelName, suffix: actorSuffix); |
| 217 | } |
| 218 | } |
| 219 | |
| 220 | initActorModelForceCubeMap(actorInfo->subActor, initInfo); |
| 221 | |
| 222 | if (isAliveResult) { |
| 223 | if (isAlive) |
| 224 | actorInfo->subActor->makeActorAlive(); |
| 225 | else |
| 226 | actorInfo->subActor->makeActorDead(); |
| 227 | } |
| 228 | bool isShow = false; |
| 229 | if (tryGetByamlBool(&isShow, subActorIter, "IsShow" ) && !isShow) |
| 230 | hideModel(actor: actorInfo->subActor); |
| 231 | } |
| 232 | } |
| 233 | } |
| 234 | |
| 235 | SubActorKeeper* SubActorKeeper::create(LiveActor* rootActor) { |
| 236 | return new SubActorKeeper(rootActor); |
| 237 | } |
| 238 | |
| 239 | SubActorKeeper* SubActorKeeper::tryCreate(LiveActor* rootActor, const char* suffix, |
| 240 | s32 maxSubActors) { |
| 241 | sead::FixedSafeString<0x80> actorInitFileName; |
| 242 | |
| 243 | if (!isExistModelResource(rootActor) || |
| 244 | !tryGetActorInitFileName(&actorInitFileName, rootActor, "InitSubActor" , suffix)) |
| 245 | return nullptr; |
| 246 | |
| 247 | if (maxSubActors <= 0) { |
| 248 | if (!isExistModelResource(rootActor)) |
| 249 | return nullptr; |
| 250 | |
| 251 | if (!isExistModelResourceYaml(rootActor, actorInitFileName.cstr(), nullptr)) |
| 252 | return nullptr; |
| 253 | } |
| 254 | |
| 255 | return new SubActorKeeper(rootActor); |
| 256 | } |
| 257 | } // namespace al |
| 258 | |