SMG-Decomp
A decompilation of Super Mario Galaxy 1
Loading...
Searching...
No Matches
BreakableCage.cpp
1#include "Game/MapObj/BreakableCage.hpp"
2#include "Game/MapObj/PowerStar.hpp"
3
4inline f32 normalizeAngle(f32 a1, f32 a2) {
5 return a1 + (f32)fmod(360.0f + (a2 - a1), 360.0f);
6}
7
8BreakableCage::BreakableCage(const char *pName) : LiveActor(pName) {
9 mBreakModel = nullptr;
10 mCageType = CAGE_INVALID;
11 mRotationSpeed = 0.0f;
12 mItemModel = nullptr;
13 mIgnoreGravity = false;
14 mDelayDeadActivate = false;
15 mCameraInfo = nullptr;
16 mMtx.identity();
17}
18
19/*
20void BreakableCage::init(const JMapInfoIter &rIter) {
21 TVec3f stack_C;
22 stack_C.setInlinePS(cHitSensorOffsetCage);
23 const char* name;
24 f32 v7 = 300.0f;
25 stack_C.z = 0.0f;
26 MR::getObjectName(&name, rIter);
27 const char* modelName = name;
28
29 if (MR::isEqualString(modelName, "BreakableCageRotate")) {
30 name = "BreakableCage";
31 mCageType = CAGE_NORMAL;
32 }
33 else if (MR::isEqualString(name, "BreakableCageL")) {
34 v7 = 600.0f;
35 mCageType = CAGE_LARGE;
36 }
37 else if (MR::isEqualString(name, "BreakableFixation")) {
38 mCageType = CAGE_FIX;
39 stack_C.setInline(cHitSensorOffsetFixation);
40 v7 = 425.0f;
41 }
42 else if (MR::isEqualString(name, "BreakableTrash")) {
43 mCageType = CAGE_TRASH;
44 MR::joinToGroupArray(this, rIter, "ゴミ管理", 32);
45 }
46
47 f32 v9 = v7 * mScale.x;
48 stack_C.x = stack_C.x * mScale.x;
49 stack_C.y = stack_C.y * mScale.x;
50 stack_C.z = stack_C.z * mScale.x;
51 initMapToolInfo(rIter);
52 initModel(modelName, rIter);
53 MR::connectToSceneMapObjStrongLight(this);
54 initHitSensor(1);
55 MR::addHitSensor(this, "body", 82, 8, v9, stack_C);
56 MR::initCollisionParts(this, modelName, getSensor("body"), nullptr);
57
58 if (!isTypeCage()) {
59 initEffectKeeper(0, name, false);
60 }
61
62 MR::setClippingTypeSphere(this, 100.0f + v9);
63 MR::setGroupClipping(this, rIter, 0x20);
64 initSound(4, false);
65 if (mIgnoreGravity) {
66 MR::makeMtxTR(mMtx.toMtxPtr(), this);
67 }
68 else {
69 initBaseMtxForCage();
70 }
71
72 if (MR::tryRegisterDemoCast(this, rIter)) {
73 if (isTypeCage()) {
74 MR::tryRegisterDemoCast(mBreakModel, rIter);
75 }
76
77 if (mItemModel) {
78 MR::tryRegisterDemoCast(mItemModel, rIter);
79 }
80 }
81
82 MR::addToAttributeGroupSearchTurtle(this);
83
84 if (isAppearPowerStar()) {
85 MR::declarePowerStar(this);
86 }
87
88 if (MR::createActorCameraInfoIfExist(rIter, &mCameraInfo)) {
89 MR::initActorCamera(this, rIter, &mCameraInfo);
90 }
91
92 initNerve(&NrvBreakableCage::BreakableCageNrvWait::sInstance);
93 if (MR::isExistStageSwitchSleep(rIter)) {
94 MR::useStageSwitchSleep(this, rIter);
95 makeActorDead();
96 }
97 else if (MR::useStageSwitchReadAppear(this, rIter)) {
98 MR::syncStageSwitchAppear(this);
99 makeActorDead();
100 }
101 else {
102 makeActorAppeared();
103 }
104}
105*/
106
107void BreakableCage::appear() {
108 mRotation.x = 0.0f;
109 mRotation.y = 0.0f;
110 mRotation.z = 0.0f;
111 MR::showModel(this);
112 getSensor("body")->validate();
113 MR::validateClipping(this);
114
115 if (isTypeCage()) {
116 mBreakModel->kill();
117 }
118
119 if (mCageType == CAGE_TRASH && MR::isValidSwitchDead(this)) {
120 MR::offSwitchDead(this);
121 }
122
123 setNerve(&NrvBreakableCage::BreakableCageNrvWait::sInstance);
124 LiveActor::appear();
125}
126
127void BreakableCage::kill() {
128 LiveActor::kill();
129
130 if (isTypeCage()) {
131 mBreakModel->kill();
132 }
133
134 if (mItemModel != nullptr) {
135 mItemModel->kill();
136 }
137}
138
139#ifndef NON_MATCHING
141 if (mCageType == CAGE_NORMAL) {
142 f32 v2 = (0.017453292f * mRotation.y);
143 TVec3f stack_C;
144 TVec3f stack_14(0.0f, 1.0f, 0.0f);
145 TPos3f stack_20;
146 stack_20.mMtx[0][3] = 0.0f;
147 stack_20.mMtx[1][3] = 0.0f;
148 stack_20.mMtx[2][3] = 0.0f;
149 stack_C.set(stack_14);
150 PSVECMag(stack_C.toCVec());
151 PSVECNormalize(stack_C.toCVec(), stack_C.toVec());
152 TPos3f stack_50;
153 f32 v3 = sin(v2);
154 f32 v4 = cos(v2);
155 stack_50.mMtx[0][0] = v4 + ((1.0f - v4) * (stack_C.x * stack_C.x));
156 stack_50.mMtx[1][1] = v4 + ((1.0f - v4) * (stack_C.y * stack_C.y));
157 stack_50.mMtx[2][2] = v4 + ((1.0f - v4) * (stack_C.z * stack_C.z));
158 stack_50.mMtx[0][1] = (stack_C.y * ((1.0f - v4) * stack_C.x)) - (v3 * stack_C.z);
159 stack_50.mMtx[0][2] = (stack_C.z * ((1.0f - v4) * stack_C.x)) + (v3 * stack_C.y);
160 stack_50.mMtx[1][0] = (stack_C.y * ((1.0f - v4) * stack_C.x)) + (v3 * stack_C.z);
161 stack_50.mMtx[2][0] = (stack_C.z * ((1.0f - v4) * stack_C.x)) - (v3 * stack_C.y);
162 stack_50.mMtx[1][2] = (stack_C.z * ((1.0f - v4) * stack_C.y)) - (v3 * stack_C.x);
163 stack_50.mMtx[2][1] = (stack_C.z * ((1.0f - v4) * stack_C.y)) + (v3 * stack_C.x);
164
165 stack_20.concat(mMtx, stack_50);
166 MR::setBaseTRMtx(this, stack_20);
167 }
168 else {
169 MR::setBaseTRMtx(this, mMtx);
170 }
171}
172#endif
173
174bool BreakableCage::receiveMsgPlayerAttack(u32 msg, HitSensor *a2, HitSensor *a3) {
175 bool result;
176 if (MR::isMsgJetTurtleAttack(msg)) {
177 result = tryBreak();
178 }
179 else {
180 result = false;
181 }
182
183 return result;
184}
185
186bool BreakableCage::receiveMsgEnemyAttack(u32 msg, HitSensor *a2, HitSensor *a3) {
187 bool result;
188
189 if (MR::isMsgEnemyAttackFire(msg) || MR::isMsgEnemyAttackFireStrong(msg)) {
190 result = false;
191 }
192 else {
193 result = tryBreak();
194 }
195
196 return result;
197}
198
199void BreakableCage::initMapToolInfo(const JMapInfoIter &rIter) {
200 MR::initDefaultPos(this, rIter);
201 MR::useStageSwitchReadAppear(this, rIter);
202 MR::useStageSwitchWriteA(this, rIter);
203 MR::useStageSwitchWriteB(this, rIter);
204 MR::useStageSwitchWriteDead(this, rIter);
205
206 if (mCageType == CAGE_NORMAL) {
207 MR::getJMapInfoArg0WithInit(rIter, &mRotationSpeed);
208 mRotationSpeed *= 0.0099999998f;
209 }
210
211 if (isTypeCage()) {
212 MR::getJMapInfoArg1NoInit(rIter, &mIgnoreGravity);
213 }
214 else {
215 mIgnoreGravity = true;
216 }
217
218 MR::getJMapInfoArg2NoInit(rIter, &mDelayDeadActivate);
219}
220
221void BreakableCage::initModel(const char *pName, const JMapInfoIter &rIter) {
222 initModelManagerWithAnm(pName, nullptr, false);
223 if (isTypeCage()) {
224 ModelObj* obj = MR::createModelObjMapObjStrongLight("壊れる籠壊れモデル", "BreakableCageBreak", mMtx.toMtxPtr());
225 mBreakModel = obj;
226 obj->initWithoutIter();
227 mBreakModel->mScale.set(mScale);
228 MR::invalidateClipping(mBreakModel);
229 MR::registerDemoSimpleCastAll(mBreakModel);
230 mBreakModel->makeActorDead();
231 mItemModel = MR::createDummyDisplayModel(this, rIter, -1, TVec3f(0.0f, 150.0f, 0.0f), TVec3f(0.0f, 0.0f, 0.0f));
232 if (mItemModel != nullptr) {
233 s32 model_id = MR::getDummyDisplayModelId(rIter, -1);
234
235 switch (model_id) {
236 case 4:
237 MR::startBck(mItemModel, "Rotation", nullptr);
238 break;
239 case 7:
240 break;
241 }
242 }
243 }
244}
245
246void BreakableCage::initBaseMtxForCage() {
247 MR::calcGravity(this);
248
249 TMtx34f stack_20;
250 MR::makeMtxRotate(stack_20.toMtxPtr(), mRotation);
251 TVec3f stack_14;
252 f32 z = stack_20.mMtx[2][2];
253 f32 y = stack_20.mMtx[1][2];
254 f32 x = stack_20.mMtx[0][2];
255 stack_14.set(x, y, z);
256 TVec3f stack_8;
257 stack_8.negateInline_2(mGravity);
258 MR::makeMtxUpFrontPos(&mMtx, stack_8, stack_14, mPosition);
259}
260
261bool BreakableCage::isTypeCage() const {
262 bool res = true;
263 bool v3 = true;
264 bool v4 = true;
265 CageType type = mCageType;
266
267 if (type && type != CAGE_LARGE) {
268 v4 = false;
269 }
270
271 if (!v4 && type != CAGE_NORMAL) {
272 v3 = false;
273 }
274
275 if (!v3 && type != CAGE_TRASH) {
276 res = false;
277 }
278
279 return res;
280}
281
282bool BreakableCage::isAppearPowerStar() const {
283 bool res = false;
284 if (mItemModel != nullptr && MR::getDummyDisplayModelId(mItemModel) == 7) {
285 res = true;
286 }
287
288 return res;
289}
290
291bool BreakableCage::tryBreak() {
292 if (isNerve(&NrvBreakableCage::BreakableCageNrvWait::sInstance)) {
293 if (mCameraInfo != nullptr) {
294 MR::requestStartDemoWithoutCinemaFrame(this, "破壊", &NrvBreakableCage::BreakableCageNrvBreak::sInstance, &NrvBreakableCage::BreakableCageNrvWaitStartDemoBreak::sInstance);
295 }
296 else {
297 setNerve(&NrvBreakableCage::BreakableCageNrvBreak::sInstance);
298 }
299
300 return true;
301 }
302
303 return false;
304}
305
306void BreakableCage::exeWait() {
307 if (mCageType == CAGE_NORMAL) {
308 mRotation.y = normalizeAngle(0.0f, mRotationSpeed + mRotation.y);
309 }
310
311 if (mItemModel != nullptr) {
312 if (isAppearPowerStar()) {
313 DummyDisplayModel* model = mItemModel;
314 mItemModel->mRotation.y = normalizeAngle(0.0f, model->mRotation.y + PowerStar::getPowerStarWaitRotateSpeed());
315 }
316 }
317}
318
319void BreakableCage::exeBreak() {
320 u32 v2 = 1;
321 u32 v3 = 0;
322 ActorCameraInfo* inf;
323
324 if (mDelayDeadActivate || mItemModel != nullptr || mCageType == (s32)3 || mCageType == CAGE_TRASH) {
325 v3 = 1;
326 }
327
328 if (!v3 && mCageType != CAGE_NORMAL) {
329 v2 = 0;
330 }
331
332 if (MR::isFirstStep(this)) {
333 switch(mCageType) {
334 case CAGE_FIX:
335 MR::startSound(this, "SE_OJ_BREAK_FIXATION_BREAK", -1, -1);
336 break;
337 default:
338 MR::startSound(this, "SE_OJ_IRON_CAGE_BREAK", -1, -1);
339 break;
340 }
341
342 MR::hideModel(this);
343 getSensor("body")->invalidate();
344 MR::invalidateCollisionParts(this);
345 MR::invalidateClipping(this);
346
347 const ActorCameraInfo* camera = mCameraInfo;
348
349 if (camera) {
350 MR::startActorCameraTargetSelf(this, getCamInfo(), -1);
351 if (mBreakModel != nullptr) {
352 MR::requestMovementOn(mBreakModel);
353 }
354 }
355
356 if (isTypeCage()) {
357 mBreakModel->appear();
358 MR::startBck(mBreakModel, "Break", nullptr);
359 }
360 else {
361 MR::emitEffect(this, "Break");
362 }
363
364 if (isAppearPowerStar()) {
365 if (mItemModel != nullptr) {
366 MR::requestAppearPowerStar(this, mItemModel->mPosition);
367 }
368 else {
369 MR::requestAppearPowerStar(this, this, 150.0f);
370 }
371
372 MR::requestMovementOn(this);
373 }
374
375 if (mItemModel != nullptr) {
376 mItemModel->kill();
377 }
378
379 if (v2 && MR::isValidSwitchDead(this)) {
380 MR::onSwitchDead(this);
381 }
382 }
383
384 if (isAppearPowerStar() || mCameraInfo != nullptr) {
385 MR::stopSceneAtStep(this, 2, 16);
386 }
387 else if (MR::isNearPlayer(this, 1500.0f)) {
388 f32 radius = getSensor("body")->mRadius;
389 if (!MR::isJudgedToClipFrustum(mPosition, radius)) {
390 MR::stopSceneAtStep(this, 2, 6);
391 }
392 }
393
394 bool canDoSwitch;
395
396 if (mCameraInfo != nullptr) {
397 canDoSwitch = MR::isStep(this, 120);
398 }
399 else if (isTypeCage()) {
400 canDoSwitch = MR::isBckStopped(mBreakModel);
401 }
402 else {
403 canDoSwitch = MR::isEffectValid(this, "Break") == false;
404 }
405
406 if (canDoSwitch) {
407 if (!v2 && MR::isValidSwitchDead(this)) {
408 MR::onSwitchDead(this);
409 }
410
411 if (MR::isValidSwitchB(this)) {
412 MR::offSwitchB(this);
413 }
414
415 if (mCameraInfo != nullptr) {
416 MR::endActorCamera(this, getCamInfo(), false, -1);
417 MR::endDemo(this, "破壊");
418 }
419
420 kill();
421 }
422}
423
424BreakableCage::~BreakableCage() {
425
426}
427
428namespace NrvBreakableCage {
429 INIT_NERVE(BreakableCageNrvWait);
430 INIT_NERVE(BreakableCageNrvWaitStartDemoBreak);
431 INIT_NERVE(BreakableCageNrvBreak);
432
433 void BreakableCageNrvBreak::execute(Spine *pSpine) const {
434 BreakableCage* cage = reinterpret_cast<BreakableCage*>(pSpine->mExecutor);
435 cage->exeBreak();
436 }
437
438 void BreakableCageNrvWaitStartDemoBreak::execute(Spine *pSpine) const {
439
440 }
441
442 void BreakableCageNrvWait::execute(Spine *pSpine) const {
443 BreakableCage* cage = reinterpret_cast<BreakableCage*>(pSpine->mExecutor);
444 cage->exeWait();
445 }
446};
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 mRotation
3D vector of the actor's rotation.
Definition LiveActor.hpp:96
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
TVec3f mGravity
3D vector of the actor's gravity.
Definition LiveActor.hpp:99
HitSensor * getSensor(const char *pSensorName) const
Gets a sensor.
void initWithoutIter()
Initializes a NameObj without a JMapInfoIter instance.
Definition NameObj.cpp:41
Definition Spine.hpp:9