1#include "Library/MapObj/ClockMapParts.h"
2
3#include "Library/Fluid/RippleCtrl.h"
4#include "Library/LiveActor/ActorActionFunction.h"
5#include "Library/LiveActor/ActorAreaFunction.h"
6#include "Library/LiveActor/ActorInitFunction.h"
7#include "Library/LiveActor/ActorInitUtil.h"
8#include "Library/LiveActor/ActorModelFunction.h"
9#include "Library/LiveActor/ActorMovementFunction.h"
10#include "Library/LiveActor/ActorPoseUtil.h"
11#include "Library/LiveActor/ActorSensorUtil.h"
12#include "Library/MapObj/ChildStep.h"
13#include "Library/Math/MathUtil.h"
14#include "Library/Nerve/NerveSetupUtil.h"
15#include "Library/Nerve/NerveUtil.h"
16#include "Library/Placement/PlacementFunction.h"
17#include "Library/Se/SeFunction.h"
18#include "Library/Stage/StageSwitchUtil.h"
19#include "Library/Thread/FunctorV0M.h"
20
21#include "MapObj/SubActorLodFixPartsScenarioAction.h"
22
23namespace {
24using namespace al;
25
26NERVE_ACTION_IMPL(ClockMapParts, StandBy)
27NERVE_ACTION_IMPL(ClockMapParts, Delay)
28NERVE_ACTION_IMPL(ClockMapParts, RotateSign)
29NERVE_ACTION_IMPL(ClockMapParts, Rotate)
30NERVE_ACTION_IMPL(ClockMapParts, Wait)
31NERVE_ACTION_IMPL(ClockMapParts, AssistStop)
32NERVE_ACTION_IMPL(ClockMapParts, AssistStopSync)
33NERVE_ACTION_IMPL(ClockMapParts, AssistStopEndWait)
34
35NERVE_ACTIONS_MAKE_STRUCT(ClockMapParts, StandBy, Delay, RotateSign, Rotate, Wait, AssistStop,
36 AssistStopSync, AssistStopEndWait)
37} // namespace
38
39namespace al {
40ClockMapParts::ClockMapParts(const char* name) : LiveActor(name) {}
41
42void ClockMapParts::init(const ActorInitInfo& info) {
43 using ClockMapPartsFunctor = FunctorV0M<ClockMapParts*, void (ClockMapParts::*)()>;
44
45 tryInitSubActorKeeperChildStep(actor: this, info);
46 initNerveAction(actor: this, actionName: "Rotate", collector: &NrvClockMapParts.collector, maxStates: 0);
47 initMapPartsActor(actor: this, initInfo: info, suffix: nullptr);
48 tryGetQuatPtr(actor: this);
49 registerAreaHostMtx(actor: this, initInfo: info);
50 registSupportFreezeSyncGroup(actor: this, info);
51
52 mQuat.set(getQuat(actor: this));
53
54 tryGetArg(arg: &mClockAngleDegree, initInfo: info, key: "ClockAngleDegree");
55
56 if (mClockAngleDegree == 0) {
57 mTurnStepCount = 1;
58 } else {
59 s32 lcm = sead::Mathi::lcm(x: sead::Mathi::abs(x: mClockAngleDegree), y: 360);
60 s32 clockAngleDegree = sead::Mathi::abs(x: mClockAngleDegree);
61
62 mTurnStepCount = lcm / clockAngleDegree;
63 }
64
65 tryGetArg(arg: &mRotateAxis, initInfo: info, key: "RotateAxis");
66 createChildStep(info, parent: this, isSyncClipping: true);
67 tryGetArg(arg: &mDelayTime, initInfo: info, key: "DelayTime");
68 tryGetArg(arg: &mWaitTime, initInfo: info, key: "WaitTime");
69 tryGetArg(arg: &mRotateTime, initInfo: info, key: "RotateTime");
70
71 initMaterialCode(actor: this, initInfo: info);
72
73 if (isExistAction(actor: this, actionName: "MiddleSign")) {
74 mRotateSignTime = (s32)getActionFrameMax(actor: this, actionName: "MiddleSign");
75 } else {
76 mRotateSignTime = 36;
77 tryGetArg(arg: &mRotateSignTime, initInfo: info, key: "RotateSignTime");
78 }
79
80 mRotateTimer = mRotateSignTime + mRotateTime + 1;
81 mActiveTimer = mRotateTimer + mWaitTime + 1;
82
83 if (mDelayTime >= 1) {
84 mTimer = 0;
85 startNerveAction(actor: this, actionName: "Delay");
86 } else {
87 mTimer = mRotateSignTime;
88 }
89
90 if (listenStageSwitchOnStart(user: this, action: ClockMapPartsFunctor(this, &ClockMapParts::start)))
91 startNerveAction(actor: this, actionName: "StandBy");
92
93 if (isExistModel(actor: this)) {
94 mRippleCtrl = RippleCtrl::tryCreate(parent: this);
95
96 if (mRippleCtrl != nullptr)
97 mRippleCtrl->init(info);
98 }
99
100 listenStageSwitchOn(user: this, eventName: "SwitchStop", action: ClockMapPartsFunctor(this, &ClockMapParts::standBy));
101
102 trySyncStageSwitchAppear(actor: this);
103}
104
105void ClockMapParts::start() {
106 if (!isNerve(user: this, nerve: NrvClockMapParts.StandBy.data()))
107 return;
108
109 if (mDelayTime >= 1) {
110 startNerveAction(actor: this, actionName: "Delay");
111
112 return;
113 }
114
115 setRotateStartNerve();
116}
117
118void ClockMapParts::standBy() {
119 startNerveAction(actor: this, actionName: "StandBy");
120}
121
122bool ClockMapParts::receiveMsg(const SensorMsg* message, HitSensor* other, HitSensor* self) {
123 if (isNerve(user: this, nerve: NrvClockMapParts.StandBy.data()))
124 return false;
125
126 if (isMsgTouchAssist(msg: message)) {
127 mAssistStopTimer = 45;
128 if (isNerve(user: this, nerve: NrvClockMapParts.AssistStop.data()))
129 return true;
130
131 if (isExistAction(actor: this))
132 stopAction(actor: this);
133
134 startNerveAction(actor: this, actionName: "AssistStop");
135
136 return true;
137 }
138
139 if (isMsgShowModel(msg: message)) {
140 showModelIfHide(actor: this);
141
142 return true;
143 }
144
145 if (isMsgHideModel(msg: message)) {
146 hideModelIfShow(actor: this);
147
148 return true;
149 }
150
151 if (isMsgRestart(msg: message)) {
152 appearAndSetStart();
153
154 return true;
155 }
156
157 if (isMsgIsNerveSupportFreeze(msg: message))
158 return isNerve(user: this, nerve: NrvClockMapParts.AssistStop.data());
159
160 if (isMsgOnSyncSupportFreeze(msg: message)) {
161 if (isNerve(user: this, nerve: NrvClockMapParts.AssistStop.data()))
162 return true;
163
164 if (isExistAction(actor: this))
165 stopAction(actor: this);
166
167 startNerveAction(actor: this, actionName: "AssistStopSync");
168
169 return true;
170 }
171
172 if (isMsgOffSyncSupportFreeze(msg: message)) {
173 if (!isNerve(user: this, nerve: NrvClockMapParts.AssistStopSync.data()))
174 return true;
175
176 setRestartNerve();
177
178 return true;
179 }
180
181 return false;
182}
183
184void ClockMapParts::appearAndSetStart() {
185 mCurrentStep = 0;
186 mTimer = 0;
187 mAssistStopTimer = 0;
188
189 setQuat(actor: this, quat: mQuat);
190
191 if (mDelayTime >= 1)
192 startNerveAction(actor: this, actionName: "Delay");
193 else
194 setRotateStartNerve();
195
196 makeActorAlive();
197}
198
199void ClockMapParts::setRestartNerve() {
200 if (isExistAction(actor: this))
201 restartAction(actor: this);
202
203 if (mTimer >= mRotateTimer)
204 startNerveAction(actor: this, actionName: "AssistStopEndWait");
205 else if (mTimer >= mRotateSignTime)
206 startNerveAction(actor: this, actionName: "Rotate");
207 else
208 startNerveAction(actor: this, actionName: "RotateSign");
209}
210
211void ClockMapParts::control() {
212 if (mRippleCtrl == nullptr)
213 return;
214
215 mRippleCtrl->update();
216}
217
218void ClockMapParts::setRotateStartNerve() {
219 if (mRotateSignTime > 0)
220 startNerveAction(actor: this, actionName: "RotateSign");
221 else
222 startNerveAction(actor: this, actionName: "Rotate");
223}
224
225void ClockMapParts::exeStandBy() {}
226
227void ClockMapParts::exeDelay() {
228 if (isGreaterEqualStep(user: this, step: mDelayTime - 1))
229 setRotateStartNerve();
230}
231
232void ClockMapParts::exeRotateSign() {
233 if (isFirstStep(user: this))
234 tryStartAction(actor: this, actionName: "MiddleSign");
235
236 f32 angle = modf(a: (f32)(mCurrentStep * mClockAngleDegree) + 360.0f, b: 360.0f) + 0.0f;
237
238 rotateQuatLocalDirDegree(actor: this, quat: mQuat, axis: mRotateAxis,
239 deg: angle + sead::Mathf::sin(t: (f32)mTimer * sead::Mathf::pi2() / 18.0f));
240
241 mTimer++;
242 if (mTimer >= mRotateSignTime)
243 startNerveAction(actor: this, actionName: "Rotate");
244}
245
246void ClockMapParts::exeRotate() {
247 f32 time = (f32)(mTimer - mRotateSignTime) / (f32)(mRotateTimer + ~mRotateSignTime);
248 f32 angle = modf(a: (time + (f32)mCurrentStep) * (f32)mClockAngleDegree + 360.0f, b: 360.0f) + 0.0f;
249 rotateQuatLocalDirDegree(actor: this, quat: mQuat, axis: mRotateAxis, deg: angle);
250
251 mTimer++;
252 if (mTimer >= mRotateTimer) {
253 mCurrentStep = modi(a: mCurrentStep + mTurnStepCount + 1, b: mTurnStepCount);
254 startNerveAction(actor: this, actionName: "Wait");
255 tryStartSe(this, "RotateEnd");
256 }
257}
258
259void ClockMapParts::exeWait() {
260 mTimer++;
261 if (mTimer >= mActiveTimer) {
262 mTimer -= mActiveTimer;
263 setRotateStartNerve();
264 }
265}
266
267void ClockMapParts::exeAssistStop() {
268 mAssistStopTimer--;
269 if (mAssistStopTimer <= 0) {
270 mAssistStopTimer = 0;
271 setRestartNerve();
272 }
273}
274
275void ClockMapParts::exeAssistStopSync() {}
276
277void ClockMapParts::exeAssistStopEndWait() {
278 exeWait();
279}
280} // namespace al
281