NSMBW-Decomp
A decompilation of New Super Mario Bros. Wii
Loading...
Searching...
No Matches
d_a_en_snake_block.cpp
1#include <game/bases/d_a_en_snake_block.hpp>
2#include <game/bases/d_rail.hpp>
3#include <game/bases/d_s_stage.hpp>
4
5#include <game/mLib/m_allocator_dummy_heap.hpp>
6#include <game/bases/d_bg_parameter.hpp>
10
11ACTOR_PROFILE(EN_SNAKEBLOCK, daEnSnakeBlock_c, 0);
12
13const float daEnSnakeBlock_c::sc_FallAccel = -0.1875f;
14const float daEnSnakeBlock_c::sc_FallMaxSpeed = -4.0f;
15
17 mResFile = dResMng_c::m_instance->getRes("block_snake_ice", "g3d/block_snake_ice.brres");
18
19 nw4r::g3d::ResMdl mdl = mResFile.GetResMdl("block_snake_ice");
20 mModel.create(mdl, allocator,
21 nw4r::g3d::ScnMdl::ANM_TEXSRT | nw4r::g3d::ScnMdl::ANM_MATCLR | nw4r::g3d::ScnMdl::BUFFER_RESMATMISC,
22 1, nullptr);
24
25 mResTexSrt = mResFile.GetResAnmTexSrt("block_snake_ice");
26 mAnmTexSrt.create(mdl, mResTexSrt, allocator, nullptr, 1);
28 mModel.setAnm(mAnmTexSrt, 0.0f);
29 mAnmTexSrt.setRate(1.0f, 0);
30
31 nw4r::g3d::ResAnmClr resAnmClr = mResFile.GetResAnmClr("ridden");
32 mAnmClr.create(mdl, resAnmClr, allocator, nullptr, 1);
33 mAnmClr.setAnm(mModel, resAnmClr, 0, m3d::FORWARD_ONCE);
34 mModel.setAnm(mAnmClr);
35 mAnmClr.setRate(0.0f, 0);
36}
37
39 mModel.remove();
40 mAnmClr.remove();
41 mAnmTexSrt.remove();
42}
43
45 mAnmClr.play();
46 mAnmTexSrt.play();
47}
48
50 nw4r::g3d::ResAnmClr res = mResFile.GetResAnmClr(name);
51 mAnmClr.setAnm(mModel, res, 0, m3d::FORWARD_ONCE);
52 mModel.setAnm(mAnmClr);
53 mAnmClr.setRate(1.0f, 0);
54}
55
57 mVec3_c drawPos = mPos + offset;
58 dActor_c::changePosAngle(&drawPos, nullptr, 1);
59
60 mMtx_c mtx = mMtx_c::createTrans(drawPos);
61 mModel.setLocalMtx(&mtx);
62
63 mModel.setScale(mVec3_c(1.0f, 1.0f, 1.0f));
64 mModel.calc(false);
65 mModel.entry();
66}
67
69 mVec3_c pos = blockPos;
70 mPos = pos;
71 if (mpOwner == nullptr) {
72 mpOwner = owner;
73 }
74
75 float dx = mPos.x - mpOwner->mPos.x;
76 float dy = mPos.y - mpOwner->mPos.y;
77
78 mBgCtr.set(mpOwner, dx - 8.0f, dy + 8.0f, dx + 8.0f, dy - 8.0f,
79 callBackF, callBackH, callBackW, 1, 0, nullptr);
80 mBgCtr.mFlags = 0;
81
82 // [The unused parameter was probably used to set the collision to icy before it was
83 // decided to always make it icy]
84 if (icy || true) {
85 mBgCtr.mFlags |= 4;
86 }
87
88 mBgCtr.entry();
89}
90
92 float dx = mPos.x - mpOwner->mPos.x;
93 float dy = mPos.y - mpOwner->mPos.y;
94 mBgCtr.setOfs(dx - 8.0f, dy + 8.0f, dx + 8.0f, dy - 8.0f, nullptr);
95 mBgCtr.mFlags |= 2;
96 mBgCtr.calc();
97}
98
105
107 static mVec2_c offsets[MOVE_DIR_COUNT] = {
108 mVec2_c(0.0f, 0.0f),
109 mVec2_c(0.0f, 2.0f),
110 mVec2_c(0.0f, -2.0f),
111 mVec2_c(-2.0f, 0.0f),
112 mVec2_c(2.0f, 0.0f)
113 };
114
115 releaseBgCtr();
116
117 u8 dir = moveSequence[mMoveSequenceIdx];
118 if (dir == MOVE_DIR_NONE) {
120 mPos += mSpeed;
121 } else {
122 mPos.x += offsets[dir].x;
123 mPos.y += offsets[dir].y;
124 mVec2_c delta(mPos.x - mLastPos.x, mPos.y - mLastPos.y);
125 if (delta.length() >= 16.0f) {
126 mLastPos = mPos;
128 }
129 }
130}
131
133 daEnSnakeBlock_c *snakeBlock = (daEnSnakeBlock_c *) self;
134
135 bool isPlayer = false;
136 if (other->mKind == dActor_c::STAGE_ACTOR_PLAYER) {
137 isPlayer = true;
138 } else if (other->mKind == dActor_c::STAGE_ACTOR_YOSHI && other->getPlrNo() != -1) {
139 isPlayer = true;
140 }
141
142 if (isPlayer && snakeBlock->isState(StateID_Wait)) {
143 snakeBlock->changeState(StateID_Move);
144 }
145}
146
149
150const mVec2_c daEnSnakeBlock_c::sc_TravelDirs[MOVE_DIR_COUNT] = {
151 mVec2_c(0.0f, 0.0f),
152 mVec2_c(0.0f, 1.0f),
153 mVec2_c(0.0f, -1.0f),
154 mVec2_c(-1.0f, 0.0f),
155 mVec2_c(1.0f, 0.0f)
156};
157
159
160const float daEnSnakeBlock_c::sc_SnakeSpeeds2[dCtrlBlock_c::SNAKE_SPEED_COUNT] = {
161 0.5f, 1.0f, 1.4f
162};
163
164const float daEnSnakeBlock_c::sc_SnakeSpeeds[dCtrlBlock_c::SNAKE_SPEED_COUNT] = {
165 0.5f, 1.0f, 1.4f
166};
167
175
177 float speed = sc_SnakeSpeeds[mSnakeSpeed];
178
179 mVec2_c dir;
180 dir.x = sc_TravelDirs[moveSequence[mMoveSequenceIdx]].x;
181 dir.y = sc_TravelDirs[moveSequence[mMoveSequenceIdx]].y;
182
183 mPos.x += speed * dir.x;
184 mPos.y += speed * dir.y;
185
186 if (std::fabs(mPos.x - mLastPos.x) >= 16.0f || std::fabs(mPos.y - mLastPos.y) >= 16.0f) {
187 return true;
188 }
189 return false;
190}
191
193 mVec2_c dir;
194 dir.x = sc_TravelDirs[moveSequence[mMoveSequenceIdx]].x;
195 dir.y = sc_TravelDirs[moveSequence[mMoveSequenceIdx]].y;
196
197 mPos.x = mLastPos.x + dir.x * 16.0f;
198 mPos.y = mLastPos.y + dir.y * 16.0f;
199 mLastPos = mPos;
200
202 return moveSequence[mMoveSequenceIdx] == MOVE_DIR_NONE;
203}
204
206 if (g_SnakeNum > 0 && ACTOR_PARAM(RailStartIdx) != 0) {
208 return NOT_READY;
209 }
210
211 g_SnakeNum++;
212 mBlockCount = ACTOR_PARAM(BlockCount) + 2;
213 mSnakeType = ACTOR_PARAM(SnakeType);
214
215 initBlocks();
217
218 setStopState();
220
221 return SUCCEEDED;
222}
223
225 mStateMgr.executeState();
226
227 calcAnm();
228 calcActorPos();
230
231 if (chkOffScreen()) {
232 deleteActor(0);
233 }
234
235 return SUCCEEDED;
236}
237
239 static const float sc_shakeOffsetX[2] = {
240 1.0f, -1.0f
241 };
242
243 mVec3_c offset(0.0f, 0.0f, 0.0f);
244 if (mShakeTimer > 0) {
245 offset.x += sc_shakeOffsetX[(mShakeTimer >> 1) & 1];
246 }
247
248 getHeadBlock().draw(offset);
249 getTailBlock().draw(offset);
250 for (int i = 0; i < mBlockCount; i++) {
251 mBlocks[i].draw(offset);
252 }
253
254 return SUCCEEDED;
255}
256
258
260 if (mAllocator.mpHeap != mAllocatorDummyHeap_c::getInstance()) {
261 deleteBlocks();
262 }
263
264 g_SnakeNum--;
265 if (g_SnakeNum < 0) {
266 g_SnakeNum = 0;
267 }
268
269 return SUCCEEDED;
270}
271
273 mAllocator.createFrmHeapToCurrent(-1, mHeap::g_gameHeaps[mHeap::GAME_HEAP_DEFAULT], nullptr, 0x20, mHeap::OPT_NONE);
274 createMdl();
276 mAllocator.adjustFrmHeapRestoreCurrent();
277}
278
280 sRailInfoData *rail = dRail_c::getRailInfoP(ACTOR_PARAM(RailID));
281 dCdFile_c *file = dCd_c::m_instance->getFileP(dScStage_c::m_instance->mCurrFile);
282
283 sRailNodeData *node = file->mpRailNodes + rail->mNodeIdx;
284 node = &node[ACTOR_PARAM(RailStartIdx)];
285 bool icy = ACTOR_PARAM(SnakeType);
286
287 float nodeX = node->mX;
288 float nodeY = node->mY;
289 float blockPosX = nodeX + mBlockCount * 16.0f + 8.0f;
290 float blockPosY = -nodeY - 8.0f;
291
292 mVec3_c headPos(blockPosX, blockPosY, 1516.0f);
293 getHeadBlock().initCollision(this, headPos, icy);
294
295 dBlock_c *block = mBlocks;
296 int i = 0;
297 if (mBlockCount > 0) {
298 while (i < mBlockCount) {
299 mVec3_c blockPos(blockPosX, blockPosY, 1500.0f);
300 block->initCollision(this, blockPos, icy);
301 blockPosX -= 16.0f;
302 block++;
303 i++;
304 }
305 }
306
307 mVec3_c tailPos = mVec3_c(blockPosX, blockPosY, 1516.0f);
308 getTailBlock().initCollision(this, tailPos, icy);
309
310 getHeadBlock().mMoveSequenceIdx = mBlockCount + 1;
311 getTailBlock().mMoveSequenceIdx = 1;
312
313 getHeadBlock().mSnakeSpeed = (dCtrlBlock_c::SnakeSpeed_e) ACTOR_PARAM(SnakeSpeed);
314 getTailBlock().mSnakeSpeed = (dCtrlBlock_c::SnakeSpeed_e) ACTOR_PARAM(SnakeSpeed);
315}
316
318 getHeadBlock().calcAnm();
319 getTailBlock().calcAnm();
320
321 for (int i = 0; i < mBlockCount; i++) {
322 mBlocks[i].calcAnm();
323 }
324}
325
327 getHeadBlock().createMdl(&mAllocator);
328 getTailBlock().createMdl(&mAllocator);
329
330 for (int i = 0; i < mBlockCount; i++) {
331 mBlocks[i].createMdl(&mAllocator);
332 }
333}
334
336 getHeadBlock().deleteBlock();
337 getTailBlock().deleteBlock();
338
339 for (int i = 0; i < mBlockCount; i++) {
340 mBlocks[i].deleteBlock();
341 }
342}
343
345 static sStateID_c *l_StopStates[4] = {
350 };
351
352 mpStopState = l_StopStates[ACTOR_PARAM(StopMode)];
353}
354
356 getHeadBlock().calcCollision();
357 getTailBlock().calcCollision();
358 getTailBlock().mBgCtr.mFlags |= 1;
359
360 for (int i = 0; i < mBlockCount; i++) {
361 mBlocks[i].calcCollision();
362 }
363}
364
366 sRailInfoData *rail = dRail_c::getRailInfoP(ACTOR_PARAM(RailID));
367 dCdFile_c *cdFile = dCd_c::m_instance->getFileP(dScStage_c::m_instance->mCurrFile);
368 sRailNodeData *node = cdFile->mpRailNodes + rail->mNodeIdx;
369
370 s16 dx;
371 s16 dy;
372 s16 dx_abs;
373 s16 dy_abs;
374
375 ulong dist = 0;
376 int startIdx = ACTOR_PARAM(RailStartIdx);
377 u16 railNodeCount = rail->mCount;
378
379 for (int i = startIdx; i < railNodeCount - 1; i++) {
380 sRailNodeData *currNode = node + i;
381 sRailNodeData *nextNode = node + i + 1;
382 dx = abs((nextNode->mX >> 4) - (currNode->mX >> 4));
383 dy = abs((nextNode->mY >> 4) - (currNode->mY >> 4));
384
385 dist += dx + dy;
386 }
387
388 mMoveSequenceIdx = dist;
389 mpMoveSequence = new s8[dist + 2]; // Add 2 for the dummy MOVE_DIR_NONE values at the start/end
390
391 ulong currIdx = 1;
392 for (int i = startIdx; i < rail->mCount - 1; i++) {
393 sRailNodeData *currNode = node + i;
394 sRailNodeData *nextNode = node + i + 1;
395 dx = (nextNode->mX >> 4) - (currNode->mX >> 4);
396 dy = (nextNode->mY >> 4) - (currNode->mY >> 4);
397
398 dx_abs = abs(dx);
399 dy_abs = abs(dy);
400
401 MoveDir_e xDir = MOVE_DIR_NONE;
402 MoveDir_e yDir = MOVE_DIR_NONE;
403
404 if (dx > 0) {
405 xDir = MOVE_DIR_RIGHT;
406 } else if (dx < 0) {
407 xDir = MOVE_DIR_LEFT;
408 }
409
410 if (dy < 0) {
411 yDir = MOVE_DIR_UP;
412 } else if (dy > 0) {
413 yDir = MOVE_DIR_DOWN;
414 }
415
416 ulong moveCount = 0;
417 ulong idx;
418 if (dx_abs <= dy_abs) {
419 for (int j = 0; j < dx_abs; j++) {
420 idx = currIdx + moveCount;
421 mpMoveSequence[idx] = xDir;
422 mpMoveSequence[idx + 1] = yDir;
423 moveCount += 2;
424 }
425 for (int j = 0; j < dy_abs - dx_abs; j++) {
426 idx = currIdx + moveCount;
427 mpMoveSequence[idx] = yDir;
428 moveCount++;
429 }
430 } else {
431 for (int j = 0; j < dy_abs; j++) {
432 idx = currIdx + moveCount;
433 mpMoveSequence[idx] = xDir;
434 mpMoveSequence[idx + 1] = yDir;
435 moveCount += 2;
436 }
437 for (int j = 0; j < dx_abs - dy_abs; j++) {
438 idx = currIdx + moveCount;
439 mpMoveSequence[idx] = xDir;
440 moveCount++;
441 }
442 }
443
444 currIdx += moveCount;
445 }
446
447 mpMoveSequence[0] = MOVE_DIR_NONE;
448 mpMoveSequence[dist + 1] = MOVE_DIR_NONE;
449}
450
452 dBlock_c *currBlock = &mBlocks[mBlockCount - 2];
453 dBlock_c *nextBlock = &mBlocks[mBlockCount - 1];
454 mVec3_c pos;
455 for (int i = 0; i < mBlockCount - 1; i++) {
456 pos.x = currBlock->getPos().x;
457 pos.y = currBlock->getPos().y;
458 pos.z = 1500.0f;
459 nextBlock->setPos(pos);
460
461 nextBlock--;
462 currBlock--;
463 }
464
465 // For the first body block, use the head block's position
466 pos.x = getHeadBlock().getPos().x;
467 pos.y = getHeadBlock().getPos().y;
468 pos.z = 1500.0f;
469 mBlocks[0].setPos(pos);
470}
471
473 mPos.x = getHeadBlock().getPos().x;
474 mPos.y = getHeadBlock().getPos().y;
475 mPos.z = 1500.0f;
476}
477
479 return getTailBlock().getPos().y < dBgParameter_c::ms_Instance_p->yEnd() - 16.0f;
480}
481
483 if (isState(StateID_Wait)) {
484 return false;
485 }
486
487 return mPos.x >= dBgParameter_c::ms_Instance_p->xEnd() + 512.0f;
488}
489
490void daEnSnakeBlock_c::initializeState_Wait() {}
491void daEnSnakeBlock_c::finalizeState_Wait() {}
492void daEnSnakeBlock_c::executeState_Wait() {}
493
494void daEnSnakeBlock_c::initializeState_Move() {
495 getHeadBlock().setAnmClr("create");
496 getHeadBlock().mAnmClr.setRate(0.0f, 0);
497 getHeadBlock().mAnmClr.setFrame(25.0f, 0);
498 getTailBlock().setAnmClr("ridden");
499
500 mBlocks[0].setAnmClr("create");
501 for (int i = 1; i < mBlockCount; i++) {
502 mBlocks[i].setAnmClr("ridden");
503 }
504
505 getHeadBlock().mLastPos = getHeadBlock().mPos;
506 getTailBlock().mLastPos = getTailBlock().mPos;
507
508 int framesPerBlock = 16.0f / sc_SnakeSpeeds[ACTOR_PARAM(SnakeSpeed)];
510 mGradientMaxBlocks = getHeadBlock().mAnmClr.getFrameMax(0) / framesPerBlock;
511}
512
513void daEnSnakeBlock_c::finalizeState_Move() {}
514
515void daEnSnakeBlock_c::executeState_Move() {
516 dBlock_c *block;
517 bool headBlockMoved = getHeadBlock().moveBlock(mpMoveSequence);
518 bool tailBlockMoved = getTailBlock().moveBlock(mpMoveSequence);
519 bool headBlockSeqCompleted = false;
520 bool tailBlockSeqCompleted = false;
521
522 if (headBlockMoved || tailBlockMoved) {
523 headBlockSeqCompleted = getHeadBlock().nextTravelMove(mpMoveSequence);
524 tailBlockSeqCompleted = getTailBlock().nextTravelMove(mpMoveSequence);
525
526 dAudio::SoundEffectID_t(scSnakeSoundID).playMapSound(mPos, 0);
527
528 calcBlockPos();
532 }
533
534 block = mBlocks;
535 int animFrame;
536 int framesPerBlock = 16.0f / sc_SnakeSpeeds[ACTOR_PARAM(SnakeSpeed)];
537 int i = 0;
538 animFrame = 0;
539
540 for (; i < mGradientActiveBlocks; i++) {
541 block->setAnmClr("create");
542 block->mAnmClr.setFrame(animFrame, 0);
543 block++;
544 animFrame += framesPerBlock;
545 }
546 }
547
548 if (headBlockSeqCompleted || tailBlockSeqCompleted) {
549 if (mpStopState->isEqual(StateID_Stop)) {
551 } else {
553 }
554 }
555}
556
557void daEnSnakeBlock_c::initializeState_Shake() {
558 getHeadBlock().setAnmClr("ridden");
559 getHeadBlock().mAnmClr.setRate(0.0f, 0);
560 getTailBlock().setAnmClr("ridden");
561 getTailBlock().mAnmClr.setRate(0.0f, 0);
562
563 for (int i = 0; i < mBlockCount; i++) {
564 dBlock_c &curr = mBlocks[i];
565 curr.setAnmClr("ridden");
566 curr.mAnmClr.setRate(0.0f, 0);
567 }
568
569 mShakeTimer = 60;
570}
571
572void daEnSnakeBlock_c::finalizeState_Shake() {}
573
574void daEnSnakeBlock_c::executeState_Shake() {
575 if (--mShakeTimer == 0) {
577 }
578}
579
580void daEnSnakeBlock_c::initializeState_Stop() {
581 getHeadBlock().setAnmClr("ridden");
582 getHeadBlock().mAnmClr.setRate(0.0f, 0);
583 getTailBlock().setAnmClr("ridden");
584 getTailBlock().mAnmClr.setRate(0.0f, 0);
585
586 for (int i = 0; i < mBlockCount; i++) {
587 dBlock_c &block = mBlocks[i];
588 block.setAnmClr("ridden");
589 block.mAnmClr.setRate(0.0f, 0);
590 }
591}
592
593void daEnSnakeBlock_c::finalizeState_Stop() {}
594void daEnSnakeBlock_c::executeState_Stop() {}
595
596void daEnSnakeBlock_c::initializeState_Collapse1() {
597 static mVec2_c sc_collapseSpeeds[MOVE_DIR_COUNT] = {
598 mVec2_c(0.0f, 0.0f),
599 mVec2_c(1.0f, 3.0f),
600 mVec2_c(0.0f, -1.0f),
601 mVec2_c(0.0f, 0.0f),
602 mVec2_c(0.0f, 0.0f)
603 };
604
605 getHeadBlock().mLastPos = getHeadBlock().mPos;
606 getTailBlock().mLastPos = getTailBlock().mPos;
607 for (int i = 0; (int) i < mBlockCount; i++) {
608 dBlock_c &block = mBlocks[i];
609 block.mLastPos = block.mPos;
610 }
611
612 dBlock_c *block = &getHeadBlock();
613 int idx = block->mMoveSequenceIdx;
614 for (u32 i = 0; (int) i < mBlockCount; i++) { // [fake match]
615 block = &mBlocks[i];
616 block->mMoveSequenceIdx = idx;
617 idx--;
618 }
619 getTailBlock().mMoveSequenceIdx = idx;
620
622 mVec2_c collapseSpeed = sc_collapseSpeeds[dir];
623 getHeadBlock().mSpeed.set(collapseSpeed.x, collapseSpeed.y, 0.0f);
624 getTailBlock().mSpeed.set(collapseSpeed.x, collapseSpeed.y, 0.0f);
625 for (u32 i = 0; (int) i < mBlockCount; i++) { // [fake match]
626 dBlock_c &block = mBlocks[i];
627 block.mSpeed.set(collapseSpeed.x, collapseSpeed.y, 0.0f);
628 }
629}
630
631void daEnSnakeBlock_c::finalizeState_Collapse1() {}
632
633void daEnSnakeBlock_c::executeState_Collapse1() {
634 getHeadBlock().calcCollapse1(mpMoveSequence);
635 getTailBlock().calcCollapse1(mpMoveSequence);
636 for (int i = 0; i < mBlockCount; i++) {
637 mBlocks[i].calcCollapse1(mpMoveSequence);
638 }
639
640 if (chkCollapseDelete()) {
641 deleteActor(1);
642 }
643}
644
645void daEnSnakeBlock_c::initializeState_Collapse2() {
646 mCollapseTimer = 0;
647 getHeadBlock().mSpeed.set(0.0f, 0.0f, 0.0f);
648 getTailBlock().mSpeed.set(0.0f, 0.0f, 0.0f);
649 for (int i = 0; i < mBlockCount; i++) {
650 dBlock_c &block = mBlocks[i];
651 block.mSpeed.set(0.0f, 0.0f, 0.0f);
652 }
653}
654
655void daEnSnakeBlock_c::finalizeState_Collapse2() {}
656
657void daEnSnakeBlock_c::executeState_Collapse2() {
658 getHeadBlock().releaseBgCtr();
659 getHeadBlock().calcFallSpeed();
660 getHeadBlock().posMove();
661
662 if (mCollapseTimer > mBlockCount * 8) {
663 getTailBlock().releaseBgCtr();
664 getTailBlock().calcFallSpeed();
665 getTailBlock().posMove();
666 }
667
668 int collapsingBlockCount = mCollapseTimer >> 3;
669 if (collapsingBlockCount > mBlockCount - 1) {
670 collapsingBlockCount = mBlockCount - 1;
671 }
672
673 for (int i = 0; i < collapsingBlockCount + 1; i++) {
674 dBlock_c &block = mBlocks[i];
675 block.mBgCtr.release(); // [oversight: collision released twice]
676 block.releaseBgCtr();
677 block.calcFallSpeed();
678 block.posMove();
679 }
680
682 if (chkCollapseDelete()) {
683 deleteActor(1);
684 }
685}
686
687void daEnSnakeBlock_c::initializeState_Collapse3() {
688 getHeadBlock().mSpeed.set(0.0f, 0.0f, 0.0f);
689 getTailBlock().mSpeed.set(0.0f, 0.0f, 0.0f);
690
691 for (int i = 0; i < mBlockCount; i++) {
692 dBlock_c &block = mBlocks[i];
693 block.mSpeed.set(0.0f, 0.0f, 0.0f);
694 }
695}
696
697void daEnSnakeBlock_c::finalizeState_Collapse3() {}
698
699void daEnSnakeBlock_c::executeState_Collapse3() {
700 getHeadBlock().releaseBgCtr();
701 getHeadBlock().calcFallSpeed();
702 getHeadBlock().mPos += getHeadBlock().mSpeed;
703
704 getTailBlock().releaseBgCtr();
705 getTailBlock().calcFallSpeed();
706 getTailBlock().mPos += getTailBlock().mSpeed;
707
708 for (int i = 0; i < mBlockCount; i++) {
709 dBlock_c &block = mBlocks[i];
710 block.releaseBgCtr();
711 block.calcFallSpeed();
712 block.mPos += block.mSpeed;
713 }
714
715 if (chkCollapseDelete()) {
716 deleteActor(1);
717 }
718}
719
720const int daEnSnakeBlock_c::scSnakeSoundID = SE_OBJ_SNAKE_BLOCK;
bool isState(const sStateIDIf_c &other) const
Checks if the actor is currently in the given state.
sFStateStateMgr_c< dActorMultiState_c, sStateMethodUsr_FI_c, sStateMethodUsr_FI_c > mStateMgr
The state manager.
void deleteActor(u8 deleteForever)
Deletes the actor and optionally disables respawn.
Definition d_actor.cpp:355
static void setSoftLight_MapObj(m3d::bmdl_c &mdl)
Sets the soft light effect for map objects.
Definition d_actor.cpp:333
virtual s8 & getPlrNo()
Gets the player number associated with the actor. See mPlayerNo.
Definition d_actor.hpp:105
u8 mKind
The actor's kind. Value is a STAGE_ACTOR_KIND_e.
Definition d_actor.hpp:374
static void changePosAngle(mVec3_c *pos, mAng3_c *ang, int param3)
Adjusts the actor's position to account for looping stages.
Definition d_actor.cpp:297
dActor_c()
Constructs a new actor.
Definition d_actor.cpp:46
@ STAGE_ACTOR_YOSHI
The Yoshi actor.
Definition d_actor.hpp:48
@ STAGE_ACTOR_PLAYER
The player actor.
Definition d_actor.hpp:47
mVec3_c mPos
The actor's position.
void calcFallSpeed()
Updates the actor's falling speed. See here for details.
Course data file holder. A course data file contains the actual course elements - areas,...
Definition d_cd.hpp:11
virtual void changeState(const sStateIDIf_c &newState)
Changes the actor's state to the given state.
static sRailInfoData * getRailInfoP(u8 id)
Gets the rail data for the specified ID.
Definition d_rail.cpp:4
static dResMng_c * m_instance
The instance of this class.
Definition d_res_mng.hpp:61
A single block segment within the Snake Block actor.
void deleteBlock()
Releases the model and associated animation resources.
mVec3_c mLastPos
The block's position in the previous movement.
void releaseBgCtr()
Releases the block's collision.
static dBg_ctr_c::CallbackH callBackH
The ceiling collision callback.
void draw(const mVec3_c &offset)
Renders the block model.
void calcCollapse1(s8 *moveSequence)
Updates the block's position when in the Collapse1 state.
mVec3_c mSpeed
The block' speed.
daEnSnakeBlock_c * mpOwner
The parent Snake Block actor.
int mMoveSequenceIdx
The block's current step in the movement sequence.
m3d::anmMatClr_c mAnmClr
The color animation.
void calcAnm()
Advances the animations for the block.
dBg_ctr_c mBgCtr
The collision.
mVec3_c mPos
The block's position (center of block).
nw4r::g3d::ResAnmTexSrt mResTexSrt
The texture animation resource.
nw4r::g3d::ResFile mResFile
The resource file.
void calcCollision()
Updates the block's collision based on its offset from the parent.
static dBg_ctr_c::CallbackW callBackW
The side collision callback.
void initCollision(daEnSnakeBlock_c *parent, mVec3_c &blockPos, bool icy)
Initializes the block's collision.
m3d::anmTexSrt_c mAnmTexSrt
The texture animation.
void calcFallSpeed()
Updates the block's falling speed.
void setAnmClr(const char *name)
Sets the color animation for the block.
void createMdl(mAllocator_c *allocator)
Initializes the 3D model, textures, and color animations.
m3d::mdl_c mModel
The block model.
static dBg_ctr_c::CallbackF callBackF
The floor collision callback.
SnakeSpeed_e
The possible speed modes of a Snake Block.
bool moveBlock(s8 *moveSequence)
Moves the block in the direction specified by the current sequence step.
SnakeSpeed_e mSnakeSpeed
The speed mode for this block.
bool nextTravelMove(s8 *moveSequence)
Snaps the block to the grid and advances the sequence index to the next step.
A Snake Block which travels along a rail.
int mBlockCount
The number of blocks between the head and tail.
sStateID_c * mpStopState
The state to transition to when the Snake Block stops.
int mSnakeType
The snake type.
bool chkOffScreen()
Checks whether the Snake Block is far past the right edge of the screen.
static const mVec2_c sc_TravelDirs[MOVE_DIR_COUNT]
The unit vector for each movement direction.
void initMoveSequence()
Rasterizes the rail path into the sequence of movements.
static const float sc_FallMaxSpeed
The terminal velocity applied during a collapse.
dHeapAllocator_c mAllocator
The allocator.
static const int scSnakeSoundID
The sound effect ID played while the snake moves.
static const float sc_FallAccel
The gravity acceleration applied during a collapse.
int mGradientActiveBlocks
The number of blocks currently displaying the gradient animation.
void createMdl()
Creates the model and animations for each block.
void calcAnm()
Advances the animations for all blocks in the Snake Block.
void deleteBlocks()
Releases the resources for each block.
int mMoveSequenceIdx
The current index into mpMoveSequence.
dBlock_c mBlocks[20]
The blocks between the head and tail. Only the first mBlockCount of these are used.
bool chkCollapseDelete()
Checks whether the tail block is below the screen edge.
virtual int execute()
do method for the execute operation.
int mCollapseTimer
The timer used by the Collapse2 state to delay the fall of each block.
virtual int create()
do method for the create operation.
static sFStateID_c< daEnSnakeBlock_c > StateID_Collapse1
Collapse mode 1: Blocks travel all the way to the final rail node and then fall.
s8 * mpMoveSequence
The precalculated sequence of movements each block has to perform to reach the end of the rail.
void calcActorPos()
Updates the Snake Block's position to match the head block's.
void calcBlockPos()
Updates each body block's position.
void calcCollision()
Updates each block's collision.
s16 mShakeTimer
Counts down frames for the shake animation at the end of the rail.
virtual int doDelete()
do method for the delete operation.
static const float sc_SnakeSpeeds2[dCtrlBlock_c::SNAKE_SPEED_COUNT]
Alternate array of speed values.
static sFStateID_c< daEnSnakeBlock_c > StateID_Stop
Stopped at the end of the rail.
void initBlockCollision()
Initializes the collision for the head, body, and tail segments.
virtual void deleteReady()
Informs the base that it's about to be deleted.
void setStopState()
Sets the state to transition to after the Snake Block reaches the end of the rail.
daEnSnakeBlock_c()
Creates a Snake Block.
static sFStateID_c< daEnSnakeBlock_c > StateID_Move
Moving along the rail.
void initBlocks()
Initializes various components.
static sFStateID_c< daEnSnakeBlock_c > StateID_Collapse3
Collapse mode 3: Blocks fall all at once.
static sFStateID_c< daEnSnakeBlock_c > StateID_Shake
Shaking before collapsing.
static const float sc_SnakeSpeeds[dCtrlBlock_c::SNAKE_SPEED_COUNT]
The speed values corresponding to SnakeSpeed_e.
static sFStateID_c< daEnSnakeBlock_c > StateID_Wait
Waiting for a player to land on the Snake Block to start moving.
int mGradientMaxBlocks
The maximum number of blocks the gradient animation can cover.
static sFStateID_c< daEnSnakeBlock_c > StateID_Collapse2
Collapse mode 2: Blocks fall one after another, with a delay between each.
static int g_SnakeNum
Global counter for the active Snake Blocks.
virtual int draw()
do method for the draw operation.
void deleteRequest()
Requests deletion of the base.
Definition f_base.cpp:289
@ NOT_READY
The step could not completed at this time.
Definition f_base.hpp:45
@ SUCCEEDED
The step was completed successfully.
Definition f_base.hpp:46
An allocator class that wraps an EGG:Allocator .
A 3x4 matrix.
Definition m_mtx.hpp:9
A two-dimensional floating point vector.
Definition m_vec.hpp:26
A three-dimensional floating point vector.
Definition m_vec.hpp:122
A generic implementation of a state ID.
Definition s_StateID.hpp:7
#define ACTOR_PROFILE(profName, className, properties)
Creates an actor profile, using the profile number as the execute and draw order value.
Definition f_profile.hpp:29
@ FORWARD_ONCE
Play the animation forward once.
Definition banm.hpp:9
@ FORWARD_LOOP
Play the animation forward in a loop.
Definition banm.hpp:8
@ GAME_HEAP_DEFAULT
The default game heap (alias of MEM1 or MEM2).
Definition m_heap.hpp:38
@ OPT_NONE
No special allocation options.
Definition m_heap.hpp:29
EGG::ExpHeap * g_gameHeaps[GAME_HEAP_COUNT]
The game heaps.
Definition m_heap.cpp:13
#define STATE_DEFINE(class, name)
Defines a state.
Definition s_State.hpp:36