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
20namespace al {
21
22SubActorKeeper::SubActorKeeper(LiveActor* rootActor) {
23 mRootActor = rootActor;
24}
25
26void SubActorKeeper::registerSubActor(LiveActor* subActor, u32 syncType) {
27 mBuffer[mCurActorCount] = new SubActorInfo(subActor, static_cast<SubActorSync>(syncType));
28 mCurActorCount++;
29}
30
31// NON_MATCHING
32void 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
235SubActorKeeper* SubActorKeeper::create(LiveActor* rootActor) {
236 return new SubActorKeeper(rootActor);
237}
238
239SubActorKeeper* 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