1#include "Library/MapObj/RollingCubeMapParts.h"
2
3#include "Library/Effect/EffectSystemInfo.h"
4#include "Library/LiveActor/ActorActionFunction.h"
5#include "Library/LiveActor/ActorClippingFunction.h"
6#include "Library/LiveActor/ActorInitFunction.h"
7#include "Library/LiveActor/ActorInitUtil.h"
8#include "Library/LiveActor/ActorMovementFunction.h"
9#include "Library/LiveActor/ActorPoseUtil.h"
10#include "Library/LiveActor/ActorResourceFunction.h"
11#include "Library/LiveActor/ActorSensorUtil.h"
12#include "Library/Math/MathUtil.h"
13#include "Library/Nerve/NerveSetupUtil.h"
14#include "Library/Nerve/NerveUtil.h"
15#include "Library/Obj/PartsModel.h"
16#include "Library/Placement/PlacementFunction.h"
17#include "Library/Yaml/ByamlIter.h"
18#include "Library/Yaml/ByamlUtil.h"
19#include "Project/Joint/RollingCubePoseKeeper.h"
20#include "Project/Joint/RollingCubePoseKeeperUtil.h"
21
22namespace {
23using namespace al;
24
25NERVE_ACTION_IMPL(RollingCubeMapParts, Wait)
26NERVE_ACTION_IMPL(RollingCubeMapParts, Start)
27NERVE_ACTION_IMPL(RollingCubeMapParts, Rotate)
28NERVE_ACTION_IMPL(RollingCubeMapParts, Fall)
29NERVE_ACTION_IMPL_(RollingCubeMapParts, SlideX, Slide)
30NERVE_ACTION_IMPL_(RollingCubeMapParts, SlideY, Slide)
31NERVE_ACTION_IMPL_(RollingCubeMapParts, SlideZ, Slide)
32NERVE_ACTION_IMPL_(RollingCubeMapParts, LandX, Land)
33NERVE_ACTION_IMPL_(RollingCubeMapParts, LandY, Land)
34NERVE_ACTION_IMPL_(RollingCubeMapParts, LandZ, Land)
35NERVE_ACTION_IMPL_(RollingCubeMapParts, FallLandX, FallLand)
36NERVE_ACTION_IMPL_(RollingCubeMapParts, FallLandY, FallLand)
37NERVE_ACTION_IMPL_(RollingCubeMapParts, FallLandZ, FallLand)
38NERVE_ACTION_IMPL(RollingCubeMapParts, Stop)
39
40NERVE_ACTIONS_MAKE_STRUCT(RollingCubeMapParts, Wait, Start, Rotate, Fall, SlideX, SlideY, SlideZ,
41 LandX, LandY, LandZ, FallLandX, FallLandY, FallLandZ, Stop)
42} // namespace
43
44namespace al {
45RollingCubeMapParts::RollingCubeMapParts(const char* name) : LiveActor(name) {}
46
47void RollingCubeMapParts::init(const ActorInitInfo& info) {
48 initNerveAction(actor: this, actionName: "Wait", collector: &NrvRollingCubeMapParts.collector, maxStates: 0);
49 initMapPartsActor(actor: this, initInfo: info, suffix: nullptr);
50 tryGetQuatPtr(actor: this);
51
52 mInitialPoseQuat = getQuat(actor: this);
53 mInitialPoseTrans = getTrans(actor: this);
54
55 bool isUseMoveLimit = false;
56 tryGetArg(arg: &isUseMoveLimit, initInfo: info, key: "IsUseMoveLimit");
57 if (isUseMoveLimit) {
58 mMoveLimitMtx = new sead::Matrix34f();
59 mMoveLimitMtx->makeQT(q: mInitialPoseQuat, t: mInitialPoseTrans);
60
61 mMoveLimitPartsModel = new PartsModel("");
62 sead::FixedSafeString<256> model;
63 sead::FixedSafeString<256> archive;
64 makeMapPartsModelName(modelName: &model, path: &archive, initInfo: info);
65 mMoveLimitPartsModel->initPartsSuffix(this, info, model.cstr(), "MoveLimit", mMoveLimitMtx,
66 false);
67 }
68
69 sead::BoundBox3f boundBox;
70 if (isExistModelResourceYaml(this, "BoxInfo", nullptr) &&
71 tryGetByamlBox3f(&boundBox, ByamlIter(getModelResourceYaml(this, "BoxInfo", nullptr))))
72 mRollingCubePoseKeeper = createRollingCubePoseKeeper(cubeSize: boundBox, initInfo: info);
73 else
74 mRollingCubePoseKeeper = createRollingCubePoseKeeper(actor: this, initInfo: info);
75
76 bool isFloorTouchStart = true;
77 tryGetArg(arg: &isFloorTouchStart, initInfo: info, key: "IsFloorTouchStart");
78 if (!isFloorTouchStart)
79 startNerveAction(actor: this, actionName: "Start");
80
81 trySetEffectNamedMtxPtr(this, "Land", &mLandEffectMtx);
82 initMaterialCode(actor: this, initInfo: info);
83
84 f32 clippingRadius = 0.0f;
85 calcRollingCubeClippingInfo(clippingTrans: &mClippingTrans, clippingRadius: &clippingRadius, keeper: mRollingCubePoseKeeper, offset: 0.0f);
86 setClippingInfo(actor: this, clippingRadius, &mClippingTrans);
87
88 tryListenStageSwitchKill(actor: this);
89 makeActorAlive();
90}
91
92void RollingCubeMapParts::kill() {
93 startHitReaction(actor: this, name: "消滅");
94
95 LiveActor::kill();
96}
97
98bool RollingCubeMapParts::receiveMsg(const SensorMsg* message, HitSensor* other, HitSensor* self) {
99 if (isMsgPlayerFloorTouch(msg: message) && isNerve(user: this, nerve: NrvRollingCubeMapParts.Wait.data())) {
100 startNerveAction(actor: this, actionName: "Start");
101
102 return true;
103 }
104
105 return false;
106}
107
108void RollingCubeMapParts::control() {
109 if (mMoveLimitMtx != nullptr)
110 mMoveLimitMtx->makeQT(q: mInitialPoseQuat, t: getTrans(actor: this));
111
112 calcMtxLandEffect(effectMtx: &mLandEffectMtx, keeper: mRollingCubePoseKeeper, quat: getQuat(actor: this), trans: getTrans(actor: this));
113}
114
115void RollingCubeMapParts::appearAndSetStart() {
116 mRollingCubePoseKeeper->setStart();
117 setQuat(actor: this, quat: mInitialPoseQuat);
118 setTrans(actor: this, trans: mInitialPoseTrans);
119 resetPosition(actor: this);
120 setNerveNextMovement(isNextFallKey());
121
122 appear();
123}
124
125void RollingCubeMapParts::setNerveNextMovement(bool isNextFallKey) {
126 if (isMovementCurrentKeyRotate(keeper: mRollingCubePoseKeeper)) {
127 startNerveAction(actor: this, actionName: "Rotate");
128
129 return;
130 }
131
132 if (isNextFallKey) {
133 startNerveAction(actor: this, actionName: "Fall");
134
135 return;
136 }
137
138 Axis axis = (Axis)sead::Mathi::abs(
139 x: (s32)calcNearVecFromAxis3(nullptr, sead::Vector3f::ey, getQuat(actor: this)));
140 switch (axis) {
141 default:
142 return;
143 case Axis::X:
144 startNerveAction(actor: this, actionName: "SlideX");
145
146 return;
147 case Axis::Y:
148 startNerveAction(actor: this, actionName: "SlideY");
149
150 return;
151 case Axis::Z:
152 startNerveAction(actor: this, actionName: "SlideZ");
153
154 return;
155 }
156}
157
158bool RollingCubeMapParts::isNextFallKey() const {
159 bool isNextFall = false;
160 tryGetArg(arg: &isNextFall, placementInfo: getCurrentKeyPlacementInfo(keeper: mRollingCubePoseKeeper), key: "isNextFall");
161
162 return isNextFall;
163}
164
165void RollingCubeMapParts::exeWait() {}
166
167void RollingCubeMapParts::exeStart() {
168 if (isGreaterEqualStep(user: this, step: 40))
169 setNerveNextMovement(isNextFallKey());
170}
171
172void RollingCubeMapParts::exeRotate() {
173 if (isFirstStep(user: this)) {
174 fittingToCurrentKeyBoundingBox(outQuat: getQuatPtr(actor: this), outTrans: getTransPtr(actor: this), keeper: mRollingCubePoseKeeper);
175 mCurrentPoseQuat = getQuat(actor: this);
176 mCurrentPoseTrans = getTrans(actor: this);
177 mMovementTime = getMovementTime() - 1;
178 }
179
180 calcCurrentKeyQT(outQuat: getQuatPtr(actor: this), outTrans: getTransPtr(actor: this), keeper: mRollingCubePoseKeeper, quat: mCurrentPoseQuat,
181 trans: mCurrentPoseTrans, rate: calcNerveSquareInRate(user: this, max: mMovementTime));
182
183 if (isGreaterEqualStep(user: this, step: mMovementTime)) {
184 if (nextRollingCubeKey(keeper: mRollingCubePoseKeeper)) {
185 if (!isNextFallKey())
186 setNerveNextLand();
187 else if (isMovementCurrentKeyRotate(keeper: mRollingCubePoseKeeper))
188 startNerveAction(actor: this, actionName: "Rotate");
189 else
190 startNerveAction(actor: this, actionName: "Fall");
191 } else {
192 startNerveAction(actor: this, actionName: "Stop");
193 }
194 }
195}
196
197s32 RollingCubeMapParts::getMovementTime() const {
198 s32 movementTime = 40;
199 tryGetArg(arg: &movementTime, placementInfo: getCurrentKeyPlacementInfo(keeper: mRollingCubePoseKeeper), key: "MovementTime");
200
201 return movementTime;
202}
203
204void RollingCubeMapParts::setNerveNextLand() {
205 Axis axis = (Axis)sead::Mathi::abs(
206 x: (s32)calcNearVecFromAxis3(nullptr, sead::Vector3f::ey, getQuat(actor: this)));
207 switch (axis) {
208 default:
209 return;
210 case Axis::X:
211 startNerveAction(actor: this, actionName: "LandX");
212
213 return;
214 case Axis::Y:
215 startNerveAction(actor: this, actionName: "LandY");
216
217 return;
218 case Axis::Z:
219 startNerveAction(actor: this, actionName: "LandZ");
220
221 return;
222 }
223}
224
225void RollingCubeMapParts::exeSlide() {
226 if (updateSlide()) {
227 if (nextRollingCubeKey(keeper: mRollingCubePoseKeeper)) {
228 if (!isNextFallKey())
229 setNerveNextLand();
230 else if (isMovementCurrentKeyRotate(keeper: mRollingCubePoseKeeper))
231 startNerveAction(actor: this, actionName: "Rotate");
232 else
233 startNerveAction(actor: this, actionName: "Fall");
234 } else {
235 startNerveAction(actor: this, actionName: "Stop");
236 }
237 }
238}
239
240bool RollingCubeMapParts::updateSlide() {
241 if (isFirstStep(user: this)) {
242 fittingToCurrentKeyBoundingBox(outQuat: getQuatPtr(actor: this), outTrans: getTransPtr(actor: this), keeper: mRollingCubePoseKeeper);
243 mCurrentPoseQuat = getQuat(actor: this);
244 mCurrentPoseTrans = getTrans(actor: this);
245 mMovementTime = getMovementTime() - 1;
246 }
247
248 calcCurrentKeyQT(outQuat: getQuatPtr(actor: this), outTrans: getTransPtr(actor: this), keeper: mRollingCubePoseKeeper, quat: mCurrentPoseQuat,
249 trans: mCurrentPoseTrans, rate: calcNerveSquareInRate(user: this, max: mMovementTime));
250
251 return isGreaterEqualStep(user: this, step: mMovementTime);
252}
253
254void RollingCubeMapParts::exeFall() {
255 if (updateSlide()) {
256 if (nextRollingCubeKey(keeper: mRollingCubePoseKeeper)) {
257 if (!isNextFallKey())
258 setNerveNextFallLand();
259 else if (isMovementCurrentKeyRotate(keeper: mRollingCubePoseKeeper))
260 startNerveAction(actor: this, actionName: "Rotate");
261 else
262 startNerveAction(actor: this, actionName: "Fall");
263 } else {
264 startNerveAction(actor: this, actionName: "Stop");
265 }
266 }
267}
268
269void RollingCubeMapParts::setNerveNextFallLand() {
270 Axis axis = (Axis)sead::Mathi::abs(
271 x: (s32)calcNearVecFromAxis3(nullptr, sead::Vector3f::ey, getQuat(actor: this)));
272 switch (axis) {
273 default:
274 return;
275 case Axis::X:
276 startNerveAction(actor: this, actionName: "FallLandX");
277
278 return;
279 case Axis::Y:
280 startNerveAction(actor: this, actionName: "FallLandY");
281
282 return;
283 case Axis::Z:
284 startNerveAction(actor: this, actionName: "FallLandZ");
285
286 return;
287 }
288}
289
290void RollingCubeMapParts::exeLand() {
291 if (isGreaterEqualStep(user: this, step: getLandTime() - 1))
292 setNerveNextMovement(false);
293}
294
295s32 RollingCubeMapParts::getLandTime() const {
296 s32 landTime = 40;
297 tryGetArg(arg: &landTime, placementInfo: getCurrentKeyPlacementInfo(keeper: mRollingCubePoseKeeper), key: "LandTime");
298
299 return landTime;
300}
301
302void RollingCubeMapParts::exeFallLand() {
303 if (isGreaterEqualStep(user: this, step: getLandTime()))
304 setNerveNextMovement(false);
305}
306
307void RollingCubeMapParts::exeStop() {
308 if (mIsStoppable) {
309 if (isFirstStep(user: this))
310 startHitReaction(actor: this, name: "消滅");
311
312 if (isStep(user: this, step: 1)) {
313 setQuat(actor: this, quat: mInitialPoseQuat);
314 setTrans(actor: this, trans: mInitialPoseTrans);
315 resetPosition(actor: this);
316
317 makeActorDead();
318 }
319 }
320}
321
322bool RollingCubeMapParts::isStop() const {
323 return isNerve(user: this, nerve: NrvRollingCubeMapParts.Stop.data());
324}
325} // namespace al
326