SMG-Decomp
A decompilation of Super Mario Galaxy 1
Loading...
Searching...
No Matches
ArrowSwitch.cpp
1#include "Game/MapObj/ArrowSwitch.hpp"
2#include <cmath>
3
4namespace {
5 const f32 sRotYTargetList[4] = { 0.0f, 90.0f, 180.0f, -90.0f };
6};
7
8ArrowSwitch::ArrowSwitch(const char *pName) : LiveActor(pName) {
9 _8C = 0.0f;
10 mRotationIdx = 0;
11 _94 = 0.0f;
12 _98 = -1;
13 _9C = 0;
14 _9D = 1;
15 _9E = 0;
16 _9F = 0;
17}
18
19void ArrowSwitch::init(const JMapInfoIter &rIter) {
20 MR::initDefaultPos(this, rIter);
21 mScale.x = 1.0f;
22 mScale.y = 1.0f;
23 mScale.z = 1.0f;
24 initModelManagerWithAnm("ArrowSwitch", nullptr, false);
25 MR::connectToSceneNoShadowedMapObjStrongLight(this);
26 TVec3f up_vec;
27 MR::calcUpVec(&up_vec, this);
28 TVec3f neg_up_vec;
29 neg_up_vec.negateInlineAndStore(up_vec, mGravity);
30 MR::initShadowFromCSV(this, "Shadow");
31 MR::onCalcShadow(this, nullptr);
32 MR::onCalcGravity(this);
33 if (MR::isInAreaObj("PlaneModeCube", mPosition)) {
34 initHitSensor(1);
35 MR::addHitSensorMapObj(this, "body", 8, 100.0f, TVec3f(0.0f, 50.0f, 250.0f));
36 }
37 else {
38 initHitSensor(2);
39 MR::addHitSensorMapObj(this, "body", 8, 100.0f, TVec3f(0.0f, 50.0f, 250.0f));
40 MR::addHitSensorMapObjMoveCollision(this, "collision", 8, 0.0f, TVec3f(0.0f, 0.0f, 0.0f));
41 MR::initCollisionParts(this, "ArrowSwitch", getSensor("collision"), nullptr);
42 }
43
44 initSound(4, false);
45 initNerve(&NrvArrowSwitch::ArrowSwitchNrvWait::sInstance);
46 MR::getJMapInfoArg0WithInit(rIter, &_98);
47 MR::getJMapInfoArg1WithInit(rIter, &_9C);
48 s32 arg = -1;
49 MR::getJMapInfoArg2WithInit(rIter, &arg);
50
51 if (arg >= 0) {
52 MR::setShadowDropLength(this, nullptr, arg);
53 }
54
55 MR::needStageSwitchWriteA(this, rIter);
56
57 if (!_9C) {
58 void (ArrowSwitch::*switchOff)(void) = &ArrowSwitch::listenOffSwitch;
59 void (ArrowSwitch::*switchOn)(void) = &ArrowSwitch::listenOnSwitch;
60 MR::listenStageSwitchOnOffB(this, MR::Functor(this, switchOff), MR::Functor(this, switchOn));
61 }
62
63 makeActorAppeared();
64}
65
66void ArrowSwitch::control() {
67
68}
69
72 MtxPtr baseMtx = getBaseMtx();
73 TPos3f pos;
74 pos.setInline(baseMtx);
75 TMtx34f tr_mtx;
76 tr_mtx.identity();
77 f32 v11 = _8C;
78 v11 = v11 * PI_180;
79 f32 v12 = sin(v11);
80 f32 v13 = cos(v11);
81 tr_mtx.mMtx[0][2] = v12;
82 tr_mtx.mMtx[1][1] = 1.0f;
83 tr_mtx.mMtx[0][0] = v13;
84 tr_mtx.mMtx[2][0] = -v12;
85 tr_mtx.mMtx[2][2] = v13;
86 tr_mtx.mMtx[2][1] = 0.0f;
87 tr_mtx.mMtx[1][2] = 0.0f;
88 tr_mtx.mMtx[1][0] = 0.0f;
89 tr_mtx.mMtx[0][1] = 0.0f;
90 pos.concat(pos, tr_mtx);
91 MR::setBaseTRMtx(this, pos);
92}
93
94void ArrowSwitch::attackSensor(HitSensor *a1, HitSensor *a2) {
95 if (MR::isSensorPlayer(a2)) {
96 MR::sendMsgPush(a2, a1);
97 }
98}
99
100bool ArrowSwitch::receiveMsgPlayerAttack(u32 msg, HitSensor *a2, HitSensor *a3) {
101 if (MR::isMsgPlayerHitAll(msg)) {
102 return requestPunch(a2, a3);
103 }
104
105 return false;
106}
107
108bool ArrowSwitch::receiveMsgPush(HitSensor *, HitSensor *) {
109 return false;
110}
111
112bool ArrowSwitch::requestPunch(HitSensor *a1, HitSensor *a2) {
113 if (getSensor("body") != a2) {
114 return false;
115 }
116
117 if (!isNerve(&NrvArrowSwitch::ArrowSwitchNrvWait::sInstance)) {
118 return false;
119 }
120
121 TVec3f side;
122 TVec3f direction;
123 MR::calcSideVec(&side, this);
124 MR::calcSensorDirection(&direction, a1, a2);
125
126 if (isPlusLimit()) {
127 _9D = 0;
128 }
129 else if (isMinusLimit()) {
130 _9D = 1;
131 }
132 else {
133 f32 dot = side.dot(direction);
134
135 if (dot > 0.0f) {
136 _9D = 1;
137 }
138 else {
139 _9D = 0;
140 }
141 }
142
143 s32 step = _9D ? getOneStep() : -getOneStep();
144 mRotationIdx += step;
145 mRotationIdx = (mRotationIdx + 4) % 4;
146 _94 = _9D ? -6.0f : 6.0f;
147 _9F = 1;
148 MR::invalidateClipping(this);
149 setNerve(&NrvArrowSwitch::ArrowSwitchNrvRotate::sInstance);
150 return true;
151}
152
153void ArrowSwitch::listenOnSwitch() {
154 if (mRotationIdx == 0) {
155 switch(_98) {
156 case 2:
157 case -1:
158 _9D = 1;
159 _94 = 6.0f;
160 mRotationIdx = 2;
161 break;
162 case 3:
163 _9D = 0;
164 _94 = 6.0f;
165 mRotationIdx = 2;
166 break;
167 case 0:
168 _9D = 1;
169 _94 = -6.0f;
170 mRotationIdx = 1;
171 break;
172 case 1:
173 _9D = 0;
174 _94 = -6.0f;
175 mRotationIdx = 3;
176 break;
177 default:
178 return;
179 }
180
181 MR::invalidateClipping(this);
182 setNerve(&NrvArrowSwitch::ArrowSwitchNrvRotate::sInstance);
183 }
184}
185
186void ArrowSwitch::listenOffSwitch() {
187 if (mRotationIdx != 0) {
188 mRotationIdx = 0;
189
190 switch(_98) {
191 case 2:
192 case 0:
193 case -1:
194 _9D = 0;
195 _94 = -6.0f;
196 break;
197 case 1:
198 case 3:
199 _9D = 1;
200 _94 = 6.0f;
201 break;
202 default:
203 return;
204 }
205
206 MR::invalidateClipping(this);
207 setNerve(&NrvArrowSwitch::ArrowSwitchNrvRotate::sInstance);
208 }
209}
210
211void ArrowSwitch::exeWait() {
212 if (MR::isFirstStep(this)) {
213 if (mRotationIdx != 0) {
214 MR::startBtk(this, "On");
215 }
216 else {
217 MR::startBtk(this, "Off");
218 }
219
220 MR::validateClipping(this);
221 MR::onCalcShadow(this, nullptr);
222 }
223}
224
225#ifdef NON_MATCHING
226void ArrowSwitch::exeRotate() {
227 if (MR::isFirstStep(this)) {
228 MR::startSound(this, "SE_OJ_ARROW_SWITCH_ON", -1, -1);
229 MR::onCalcShadow(this, nullptr);
230
231 if (_9C) {
232 MR::invalidateHitSensors(this);
233 if (MR::isExistCollisionParts(this)) {
234 MR::invalidateCollisionParts(this);
235 }
236 }
237 }
238
239 MR::startLevelSound(this, "SE_OJ_LV_ARROW_SWITCH_MOVE", -1, -1, -1);
240 f32 v2 = (_8C + _94) - -180.0f;
241 _8C += _94;
242 f32 v3 = fmod(360.0 + v2, 360.0);
243 f32 v4 = (-180.0f + v3);
244 f32 v5 = (sRotYTargetList[mRotationIdx] - (-180.0f + v3));
245 _8C = v4;
246 f32 v6 = (-180.0 + fmod((360.0 + (v5 - -180.0)), 360.0));
247
248 if (_9D && v6 < 0.0f || !_9D && v6 > 0.0f) {
249 f32 rot = sRotYTargetList[mRotationIdx];
250 _94 = 0.0f;
251 _8C = rot;
252 if (MR::isValidSwitchA(this) && _9F) {
253 if (mRotationIdx != 0) {
254 MR::onSwitchA(this);
255 }
256 else {
257 MR::offSwitchA(this);
258 }
259
260 MR::startSystemSE("SE_SY_GRAVITY_SWITCHED", -1, -1);
261 }
262
263 MR::startSound(this, "SE_OJ_ARROW_SWITCH_STOP", -1, -1);
264 _9F = 0;
265 if (_9C) {
266 setNerve(&NrvArrowSwitch::ArrowSwitchNrvLock::sInstance);
267 }
268 else {
269 setNerve(&NrvArrowSwitch::ArrowSwitchNrvWait::sInstance);
270 }
271 }
272}
273#endif
274
275void ArrowSwitch::exeLock() {
276 if (MR::isFirstStep(this)) {
277 if (mRotationIdx == 0) {
278 MR::startBtk(this, "Off");
279 }
280 else {
281 MR::startBtk(this, "On");
282 }
283
284 MR::validateClipping(this);
285 MR::onCalcShadow(this, nullptr);
286 }
287}
288
289bool ArrowSwitch::isPlusLimit() const {
290 switch (_98) {
291 case 2:
292 return mRotationIdx == 2;
293 case 0:
294 return mRotationIdx == 1;
295 case 1:
296 return mRotationIdx == 0;
297 case 3:
298 return mRotationIdx == 0;
299 default:
300 return false;
301 }
302}
303
304bool ArrowSwitch::isMinusLimit() const {
305 switch (_98) {
306 case 2:
307 return mRotationIdx == 0;
308 case 0:
309 return mRotationIdx == 0;
310 case 1:
311 return mRotationIdx == 3;
312 case 3:
313 return mRotationIdx == 2;
314 default:
315 return false;
316 }
317}
318
319/*
320s32 ArrowSwitch::getOneStep() const {
321 switch (_98) {
322 case 2:
323 case 3:
324 return 1;
325 case -1:
326 return 2;
327 }
328
329 return 0;
330}
331*/
332
333namespace NrvArrowSwitch {
334 INIT_NERVE(ArrowSwitchNrvWait);
335 INIT_NERVE(ArrowSwitchNrvRotate);
336 INIT_NERVE(ArrowSwitchNrvLock);
337
338 void ArrowSwitchNrvLock::execute(Spine *pSpine) const {
339 ArrowSwitch* sw = reinterpret_cast<ArrowSwitch*>(pSpine->mExecutor);
340 sw->exeLock();
341 }
342
343 void ArrowSwitchNrvRotate::execute(Spine *pSpine) const {
344 ArrowSwitch* sw = reinterpret_cast<ArrowSwitch*>(pSpine->mExecutor);
345 sw->exeRotate();
346 }
347
348 void ArrowSwitchNrvWait::execute(Spine *pSpine) const {
349 ArrowSwitch* sw = reinterpret_cast<ArrowSwitch*>(pSpine->mExecutor);
350 sw->exeWait();
351 }
352};
353
354ArrowSwitch::~ArrowSwitch() {
355
356}
virtual void init(const JMapInfoIter &)
Intializes the NameObj and can set various settings and construct necessary classes.
virtual void calcAndSetBaseMtx()
Calculates and sets the base matrix of the actor.
The basis of a drawable actor that can contain states (see: Nerve)
Definition LiveActor.hpp:24
TVec3f mPosition
3D vector of the actor's position.
Definition LiveActor.hpp:95
TVec3f mScale
3D vector of the actor's scale.
Definition LiveActor.hpp:97
virtual void calcAndSetBaseMtx()
Calculates and sets the base matrix of the actor.
TVec3f mGravity
3D vector of the actor's gravity.
Definition LiveActor.hpp:99
virtual MtxPtr getBaseMtx() const
Gets the base matrix of the model used for the actor.
HitSensor * getSensor(const char *pSensorName) const
Gets a sensor.
Definition Spine.hpp:9