1#include "Library/MapObj/WobbleMapParts.h"
2
3#include "Library/LiveActor/ActorActionFunction.h"
4#include "Library/LiveActor/ActorAreaFunction.h"
5#include "Library/LiveActor/ActorInitUtil.h"
6#include "Library/LiveActor/ActorModelFunction.h"
7#include "Library/LiveActor/ActorPoseUtil.h"
8#include "Library/LiveActor/ActorSensorUtil.h"
9#include "Library/MapObj/ChildStep.h"
10#include "Library/Math/MathUtil.h"
11#include "Library/Nerve/NerveSetupUtil.h"
12#include "Library/Nerve/NerveUtil.h"
13#include "Library/Placement/PlacementFunction.h"
14#include "Library/Se/SeFunction.h"
15
16namespace {
17using namespace al;
18
19NERVE_ACTION_IMPL(WobbleMapParts, Wait)
20NERVE_ACTION_IMPL(WobbleMapParts, Move)
21NERVE_ACTION_IMPL(WobbleMapParts, AssistStop)
22
23NERVE_ACTIONS_MAKE_STRUCT(WobbleMapParts, Wait, Move, AssistStop)
24} // namespace
25
26namespace al {
27WobbleMapParts::WobbleMapParts(const char* name) : LiveActor(name) {}
28
29void WobbleMapParts::init(const ActorInitInfo& info) {
30 tryInitSubActorKeeperChildStep(actor: this, info);
31 initNerveAction(actor: this, actionName: "Wait", collector: &NrvWobbleMapParts.collector, maxStates: 0);
32 initMapPartsActor(actor: this, initInfo: info, suffix: nullptr);
33 tryGetQuatPtr(actor: this);
34 registerAreaHostMtx(actor: this, initInfo: info);
35
36 mInitialQuat = getQuat(actor: this);
37 mCurrentQuat = mInitialQuat;
38 calcQuatUp(out: &mInitialUp, quat: mInitialQuat);
39 mTargetUp.set(mInitialUp);
40 tryGetArg(arg: &mMaxRotate, initInfo: info, key: "MaxRotate");
41
42 initMaterialCode(actor: this, initInfo: info);
43 createChildStep(info, parent: this, isSyncClipping: true);
44
45 trySyncStageSwitchAppear(actor: this);
46}
47
48bool WobbleMapParts::receiveMsg(const SensorMsg* message, HitSensor* other, HitSensor* self) {
49 if (isMsgTouchAssist(msg: message)) {
50 mAssistStopTimer = 45;
51 if (!isNerve(user: this, nerve: NrvWobbleMapParts.AssistStop.data()))
52 startNerveAction(actor: this, actionName: "AssistStop");
53
54 return true;
55 }
56
57 if (isMsgFloorTouch(msg: message)) {
58 sead::Vector3f pos;
59 if (isMySensor(self, this))
60 pos.set(getSensorPos(other));
61 else
62 pos.set(getActorTrans(self));
63
64 sead::Vector3f currentHorizontal;
65 sead::Vector3f currentUp;
66 calcQuatUp(out: &currentUp, quat: mCurrentQuat);
67 verticalizeVec(out: &currentHorizontal, vertical: currentUp, vec: pos - getTrans(actor: this));
68
69 f32 hDist = currentHorizontal.length();
70 f32 normHDist = normalize(x: hDist, min: 0.0f, max: 100.0f);
71
72 if (isNearZero(value: hDist))
73 currentHorizontal = sead::Vector3f::zero;
74 else
75 currentHorizontal *=
76 sead::Mathf::sin(t: sead::Mathf::deg2rad(deg: normHDist * mMaxRotate)) / hDist;
77
78 f32 cos = sead::Mathf::cos(t: sead::Mathf::deg2rad(deg: normHDist * mMaxRotate));
79 mTargetUp.set(cos * mInitialUp + currentHorizontal);
80
81 return true;
82 }
83
84 if (isMsgShowModel(msg: message)) {
85 showModelIfHide(actor: this);
86
87 return true;
88 }
89
90 if (isMsgHideModel(msg: message)) {
91 hideModelIfShow(actor: this);
92
93 return true;
94 }
95
96 if (isMsgRestart(msg: message)) {
97 appearAndSetStart();
98
99 return true;
100 }
101
102 return false;
103}
104
105void WobbleMapParts::appearAndSetStart() {
106 mIsStop = false;
107 mTiltSpeed = 0.0f;
108 mAssistStopTimer = 0;
109 mMoment.set(sead::Vector3f::zero);
110 mCurrentQuat.set(mInitialQuat);
111 mTargetUp.set(mInitialUp);
112
113 setQuat(actor: this, quat: mInitialQuat);
114 startNerveAction(actor: this, actionName: "Wait");
115
116 makeActorAlive();
117}
118
119void WobbleMapParts::exeWait() {
120 updateMove();
121
122 if (mTiltSpeed > 0.1f)
123 startNerveAction(actor: this, actionName: "Move");
124}
125
126void WobbleMapParts::updateMove() {
127 sead::Vector3f currentHorizontal;
128 sead::Vector3f currentUp;
129 calcQuatUp(out: &currentUp, quat: mCurrentQuat);
130 currentHorizontal.setCross(a: currentUp, b: mTargetUp);
131 currentHorizontal *= 180.0f / sead::Mathf::pi();
132 limitLength(out: &currentHorizontal, vec: currentHorizontal, limit: mMaxRotate * (1.0f / 750.0f));
133
134 mMoment = (mMoment + currentHorizontal) * 0.92f;
135 rotateQuatMomentDegree(&mCurrentQuat, mCurrentQuat, mMoment);
136
137 sead::Vector3f currentUp2;
138 calcQuatUp(out: &currentUp2, quat: mCurrentQuat);
139
140 sead::Vector3f newUp;
141 bool isStop = !turnVecToVecDegree(&newUp, mInitialUp, currentUp2, mMaxRotate);
142 turnQuatYDirRate(getQuatPtr(actor: this), mInitialQuat, newUp, 1.0f);
143
144 if (isStop)
145 mCurrentQuat = getQuat(actor: this);
146
147 mTargetUp.set(mInitialUp);
148 mTiltSpeed = mMoment.length();
149 if (mIsStop != isStop)
150 tryStartSeWithParam(this, "Stop", mTiltSpeed, "");
151
152 mIsStop = isStop;
153}
154
155void WobbleMapParts::exeMove() {
156 updateMove();
157
158 tryStartSeWithParam(this, "Rotate", mTiltSpeed, "");
159 if (mTiltSpeed < 0.1f)
160 startNerveAction(actor: this, actionName: "Wait");
161}
162
163void WobbleMapParts::exeAssistStop() {
164 mAssistStopTimer--;
165 if (mAssistStopTimer <= 0) {
166 mAssistStopTimer = 0;
167 if (mTiltSpeed > 0.1f)
168 startNerveAction(actor: this, actionName: "Move");
169 else
170 startNerveAction(actor: this, actionName: "Wait");
171 }
172}
173} // namespace al
174