1#include "Library/MapObj/KeyMoveMapParts.h"
2
3#include "Library/Area/SwitchKeepOnAreaGroup.h"
4#include "Library/Area/SwitchOnAreaGroup.h"
5#include "Library/Demo/DemoFunction.h"
6#include "Library/Fluid/RippleCtrl.h"
7#include "Library/KeyPose/KeyPoseKeeper.h"
8#include "Library/KeyPose/KeyPoseKeeperUtil.h"
9#include "Library/LiveActor/ActorActionFunction.h"
10#include "Library/LiveActor/ActorAreaFunction.h"
11#include "Library/LiveActor/ActorClippingFunction.h"
12#include "Library/LiveActor/ActorInitUtil.h"
13#include "Library/LiveActor/ActorModelFunction.h"
14#include "Library/LiveActor/ActorMovementFunction.h"
15#include "Library/LiveActor/ActorPoseUtil.h"
16#include "Library/LiveActor/ActorSensorUtil.h"
17#include "Library/MapObj/ChildStep.h"
18#include "Library/Nerve/NerveSetupUtil.h"
19#include "Library/Nerve/NerveUtil.h"
20#include "Library/Placement/PlacementFunction.h"
21#include "Library/Se/SeFunction.h"
22#include "Library/Stage/StageSwitchUtil.h"
23#include "Library/Thread/FunctorV0M.h"
24
25namespace al {
26namespace {
27NERVE_ACTION_IMPL(KeyMoveMapParts, StandBy)
28NERVE_ACTION_IMPL(KeyMoveMapParts, Delay)
29NERVE_ACTION_IMPL(KeyMoveMapParts, Wait)
30NERVE_ACTION_IMPL(KeyMoveMapParts, MoveSign)
31NERVE_ACTION_IMPL(KeyMoveMapParts, Move)
32NERVE_ACTION_IMPL(KeyMoveMapParts, StopSign)
33NERVE_ACTION_IMPL(KeyMoveMapParts, Stop)
34
35NERVE_ACTIONS_MAKE_STRUCT(KeyMoveMapParts, StandBy, Delay, Wait, MoveSign, Move, StopSign, Stop)
36} // namespace
37
38KeyMoveMapParts::KeyMoveMapParts(const char* name) : LiveActor(name) {}
39
40void KeyMoveMapParts::init(const ActorInitInfo& info) {
41 using KeyMoveMapPartsFunctor = FunctorV0M<KeyMoveMapParts*, void (KeyMoveMapParts::*)()>;
42
43 initNerveAction(actor: this, actionName: "Wait", collector: &NrvKeyMoveMapParts.collector, maxStates: 0);
44
45 const char* suffix = nullptr;
46 tryGetStringArg(arg: &suffix, initInfo: info, key: "SuffixName");
47 initMapPartsActor(actor: this, initInfo: info, suffix);
48
49 tryGetQuatPtr(actor: this);
50
51 mKeyPoseKeeper = createKeyPoseKeeper(info);
52
53 registerAreaHostMtx(actor: this, initInfo: info);
54
55 setKeyMoveClippingInfo(this, &mClippingOffset, mKeyPoseKeeper);
56
57 tryGetArg(arg: &mIsFloorTouchStart, initInfo: info, key: "IsFloorTouchStart");
58 tryGetArg(arg: &mIsHipDropStart, initInfo: info, key: "IsHipDropStart");
59 tryGetArg(arg: &mIsStopKill, initInfo: info, key: "IsStopKill");
60 tryGetArg(arg: &mDelayTime, initInfo: info, key: "DelayTime");
61
62 if (mDelayTime > 0)
63 startNerveAction(actor: this, actionName: "Delay");
64
65 bool isListenStart =
66 listenStageSwitchOnStart(user: this, action: KeyMoveMapPartsFunctor(this, &KeyMoveMapParts::start));
67
68 if (getKeyPoseCount(keyPoseKeeper: mKeyPoseKeeper) < 2 || mIsFloorTouchStart || mIsHipDropStart ||
69 isListenStart)
70 startNerveAction(actor: this, actionName: "StandBy");
71
72 mSwitchKeepOnAreaGroup = tryCreateSwitchKeepOnAreaGroup(actor: this, initInfo: info);
73 mSwitchOnAreaGroup = tryCreateSwitchOnAreaGroup(actor: this, initInfo: info);
74
75 trySyncStageSwitchAppear(actor: this);
76 tryListenStageSwitchKill(actor: this);
77 listenStageSwitchOn(user: this, eventName: "SwitchStop", action: KeyMoveMapPartsFunctor(this, &KeyMoveMapParts::stop));
78 listenStageSwitchOn(user: this, eventName: "SwitchReset",
79 action: KeyMoveMapPartsFunctor(this, &KeyMoveMapParts::appearAndSetStart));
80
81 registActorToDemoInfo(actor: this, initInfo: info);
82
83 tryInitSubActorKeeperChildStep(actor: this, info);
84 createChildStep(info, parent: this, isSyncClipping: true);
85 if (!isExistModel(actor: this))
86 return;
87
88 mRippleCtrl = RippleCtrl::tryCreate(parent: this);
89 if (mRippleCtrl != nullptr)
90 mRippleCtrl->init(info);
91}
92
93void KeyMoveMapParts::start() {
94 if (!isNerve(user: this, nerve: NrvKeyMoveMapParts.StandBy.data()) || getKeyPoseCount(keyPoseKeeper: mKeyPoseKeeper) <= 1)
95 return;
96
97 if (isExistAction(actor: this, actionName: "Start"))
98 startAction(actor: this, actionName: "Start");
99
100 if (mDelayTime >= 1)
101 startNerveAction(actor: this, actionName: "Delay");
102 else
103 startNerveAction(actor: this, actionName: "Wait");
104}
105
106void KeyMoveMapParts::stop() {
107 if (isNerve(user: this, nerve: NrvKeyMoveMapParts.StopSign.data()) ||
108 isNerve(user: this, nerve: NrvKeyMoveMapParts.Stop.data()))
109 return;
110
111 if (isExistAction(actor: this, actionName: "StopSign"))
112 startNerveAction(actor: this, actionName: "StopSign");
113 else
114 startNerveAction(actor: this, actionName: "Stop");
115
116 if (mSeMoveName != nullptr) {
117 tryStopSe(this, mSeMoveName, -1, nullptr);
118 mSeMoveName = nullptr;
119 }
120
121 tryStartSe(this, "MoveEnd");
122}
123
124void KeyMoveMapParts::appearAndSetStart() {
125 resetKeyPose(keyPoseKeeper: mKeyPoseKeeper);
126 setQuat(actor: this, quat: getCurrentKeyQuat(keyPoseKeeper: mKeyPoseKeeper));
127 setTrans(actor: this, trans: getCurrentKeyTrans(keyPoseKeeper: mKeyPoseKeeper));
128 resetPosition(actor: this);
129
130 if (mDelayTime >= 1)
131 startNerveAction(actor: this, actionName: "Delay");
132 else
133 startNerveAction(actor: this, actionName: "Wait");
134
135 if (getKeyPoseCount(keyPoseKeeper: mKeyPoseKeeper) < 2 || mIsFloorTouchStart || mIsHipDropStart ||
136 isValidStageSwitch(user: this, linkName: "SwitchStart"))
137 startNerveAction(actor: this, actionName: "StandBy");
138
139 makeActorAlive();
140}
141
142bool KeyMoveMapParts::receiveMsg(const SensorMsg* message, HitSensor* other, HitSensor* self) {
143 if (mIsFloorTouchStart && isMsgFloorTouch(msg: message)) {
144 start();
145
146 return true;
147 }
148
149 if (mIsHipDropStart && isMsgPlayerHipDropAll(msg: message)) {
150 start();
151
152 return false;
153 }
154
155 if (isMsgShowModel(msg: message)) {
156 showModelIfHide(actor: this);
157
158 return true;
159 }
160
161 if (isMsgHideModel(msg: message)) {
162 hideModelIfShow(actor: this);
163
164 return true;
165 }
166
167 if (isMsgRestart(msg: message)) {
168 appearAndSetStart();
169
170 return true;
171 }
172
173 return false;
174}
175
176void KeyMoveMapParts::control() {
177 if (mSwitchKeepOnAreaGroup != nullptr)
178 mSwitchKeepOnAreaGroup->update(playerPos: getTrans(actor: this));
179
180 if (mSwitchOnAreaGroup != nullptr)
181 mSwitchOnAreaGroup->update(trans: getTrans(actor: this));
182
183 if (mRippleCtrl != nullptr)
184 mRippleCtrl->update();
185}
186
187void KeyMoveMapParts::appearAndSetEnd() {
188 resetKeyPose(keyPoseKeeper: mKeyPoseKeeper);
189 while (!isLastKey(keyPoseKeeper: mKeyPoseKeeper))
190 nextKeyPose(keyPoseKeeper: mKeyPoseKeeper);
191
192 setQuat(actor: this, quat: getCurrentKeyQuat(keyPoseKeeper: mKeyPoseKeeper));
193 setTrans(actor: this, trans: getCurrentKeyTrans(keyPoseKeeper: mKeyPoseKeeper));
194 resetPosition(actor: this);
195
196 startNerveAction(actor: this, actionName: "Stop");
197
198 if (getKeyPoseCount(keyPoseKeeper: mKeyPoseKeeper) < 2 || mIsFloorTouchStart || mIsHipDropStart ||
199 isValidStageSwitch(user: this, linkName: "SwitchStart"))
200 startNerveAction(actor: this, actionName: "StandBy");
201
202 makeActorAlive();
203}
204
205void KeyMoveMapParts::exeStandBy() {}
206
207void KeyMoveMapParts::exeDelay() {
208 if (isGreaterEqualStep(user: this, step: mDelayTime - 1))
209 startNerveAction(actor: this, actionName: "Wait");
210}
211
212void KeyMoveMapParts::exeWait() {
213 if (isFirstStep(user: this)) {
214 s32 moveWaitTime = calcKeyMoveWaitTime(keyPoseKeeper: mKeyPoseKeeper);
215 if (moveWaitTime > -1)
216 mKeyMoveWaitTime = moveWaitTime;
217 }
218
219 if (isGreaterEqualStep(user: this, step: mKeyMoveWaitTime))
220 setWaitEndNerve();
221}
222
223void KeyMoveMapParts::setWaitEndNerve() {
224 if (isRestart(keyPoseKeeper: mKeyPoseKeeper)) {
225 restartKeyPose(keyPoseKeeper: mKeyPoseKeeper, pos: getTransPtr(actor: this), orientation: getQuatPtr(actor: this));
226 resetPosition(actor: this);
227 startNerveAction(actor: this, actionName: "Wait");
228
229 return;
230 }
231
232 if (isMoveSignKey(keyPoseKeeper: mKeyPoseKeeper) && isExistAction(actor: this, actionName: "MoveKeySign")) {
233 startNerveAction(actor: this, actionName: "MoveSign");
234
235 return;
236 }
237
238 startNerveAction(actor: this, actionName: "Move");
239}
240
241void KeyMoveMapParts::exeMoveSign() {
242 if (isFirstStep(user: this))
243 startAction(actor: this, actionName: "MoveKeySign");
244
245 if (isActionEnd(actor: this))
246 startNerveAction(actor: this, actionName: "Move");
247}
248
249void KeyMoveMapParts::exeMove() {
250 if (isFirstStep(user: this)) {
251 if (isExistAction(actor: this, actionName: "MoveLoop"))
252 tryStartActionIfNotPlaying(actor: this, actionName: "MoveLoop");
253
254 mKeyMoveMoveTime = calcKeyMoveMoveTime(keyPoseKeeper: mKeyPoseKeeper);
255
256 mSeMoveName = getSeNameByIndex(index: mKeyPoseKeeper->getKeyPoseCurrentIdx());
257 if (mSeMoveName != nullptr)
258 tryStartSe(this, mSeMoveName);
259 }
260
261 f32 rate = calcNerveRate(user: this, max: mKeyMoveMoveTime);
262 calcLerpKeyTrans(out: getTransPtr(actor: this), keyPoseKeeper: mKeyPoseKeeper, rate);
263 calcSlerpKeyQuat(out: getQuatPtr(actor: this), keyPoseKeeper: mKeyPoseKeeper, rate);
264
265 if (isGreaterEqualStep(user: this, step: mKeyMoveMoveTime)) {
266 nextKeyPose(keyPoseKeeper: mKeyPoseKeeper);
267 if (isStop(keyPoseKeeper: mKeyPoseKeeper))
268 stop();
269 else if (calcKeyMoveWaitTime(keyPoseKeeper: mKeyPoseKeeper) == 0)
270 setWaitEndNerve();
271 else {
272 startNerveAction(actor: this, actionName: "Wait");
273 if (mSeMoveName != nullptr) {
274 tryStopSe(this, mSeMoveName, -1, nullptr);
275 mSeMoveName = nullptr;
276 }
277
278 tryStartSe(this, "MoveEnd");
279 }
280 }
281}
282
283void KeyMoveMapParts::exeStopSign() {
284 if (isFirstStep(user: this))
285 startAction(actor: this, actionName: "StopSign");
286
287 if (isActionEnd(actor: this))
288 startNerveAction(actor: this, actionName: "Stop");
289}
290
291void KeyMoveMapParts::exeStop() {
292 if (isFirstStep(user: this)) {
293 if (isExistAction(actor: this, actionName: "Stop"))
294 tryStartAction(actor: this, actionName: "Stop");
295
296 if (isInvalidClipping(this))
297 validateClipping(actor: this);
298
299 if (mIsStopKill)
300 kill();
301 }
302}
303} // namespace al
304