NSMBW-Decomp
A decompilation of New Super Mario Bros. Wii
Loading...
Searching...
No Matches
d_a_en_shell.cpp
1#include <game/bases/d_a_en_shell.hpp>
3#include <game/bases/d_a_player_manager.hpp>
4#include <game/bases/d_a_yoshi.hpp>
5#include <game/bases/d_bg_parameter.hpp>
6#include <game/bases/d_enemy_manager.hpp>
7#include <game/bases/d_score_manager.hpp>
9#include <game/sLib/s_GlobalData.hpp>
11
16STATE_VIRTUAL_DEFINE(daEnShell_c, WakeupReverse);
19
20static const float l_slide_throw_speed[] = { 2.5f, -2.5f };
21static const float l_slide_max_speed[] = { 3.0f, -3.0f };
22
23template<>
25 0xc00,
26 0x1d00,
27 1.5f,1.0f
28};
29
30daEnShell_c::daEnShell_c() : mYoshiKickable(false), mJumpPlayerCarryActorID(BASE_ID_NULL), mIsMugenCombo(false), mMugenComboSpeed(0.0f) {
31 mFumiProc.refresh(new NonUniqueFumiCheck_c());
32 mEatBehavior = EAT_TYPE_EAT;
33 mFlags = EN_IS_SHELL | EN_IS_HARD;
34}
35
36void DUMMY_UNUSED() {
38}
39
40daEnShell_c::~daEnShell_c() {
41 for (int i = 0; i < PLAYER_COUNT; i++) {
42 dAcPy_c *player = daPyMng_c::getPlayer(i);
43 if (player != nullptr && fManager_c::searchBaseByID(player->mCarryActorID) == this) {
44 player->cancelCarry(this);
45 }
46 }
47}
48
49void daEnShell_c::createShell(const char *arcName, const char *resPath, const char *modelName, const char *anmTexName, float animFrame) {
50 mAllocator.createFrmHeap(-1, mHeap::g_gameHeaps[mHeap::GAME_HEAP_DEFAULT], nullptr, 0x20);
51
52 mResFile = dResMng_c::m_instance->getRes(arcName, resPath);
53 nw4r::g3d::ResMdl mdl = mResFile.GetResMdl(modelName);
54 mModel.create(mdl, &mAllocator, nw4r::g3d::ScnMdl::BUFFER_RESMATMISC | nw4r::g3d::ScnMdl::ANM_TEXPAT);
55
57
58 if (mProfName == fProfile::EN_NOKONOKO || mProfName == fProfile::EN_PATAPATA) {
59 nw4r::g3d::ResAnmChr anim = mResFile.GetResAnmChr("revival_shell");
60 mAnim.create(mdl, anim, &mAllocator);
61 }
62
63 if (anmTexName != nullptr) {
64 mResAnmTexPat = mResFile.GetResAnmTexPat(anmTexName);
65 mAnimTex.create(mdl, mResAnmTexPat, &mAllocator);
66 mAnimTex.setAnm(mModel, mResAnmTexPat, 0, m3d::FORWARD_ONCE);
67 mModel.setAnm(mAnimTex);
68 mAnimTex.setFrame(animFrame, 0);
69 mAnimTex.setRate(0.0f, 0);
70 }
71
72 mAllocator.adjustFrmHeap();
73}
74
75void daEnShell_c::calcShellMdl() {
76 mVec3_c pos = mPos;
77 mAng3_c angle = mAngle;
78
80 pos = calcCarryPos(mCarryPos);
81 mPos.x = pos.x;
82 mPos.y = pos.y;
83 } else if (mIsCarryFall) {
84 pos.z = 3248.0f;
85 }
86
87 changePosAngle(&pos, &angle, 1);
88
89 float wakeupShakeYOffset = 0.0f;
90 if (mSleepTimer < smc_SLEEP_TIMER_SHAKE && mSleepTimer != 0 && mSpeed.y == 0.0f && mIsFlipped != 0) {
91 wakeupShakeYOffset = 16.0f;
92 }
93
94 if (mIsFlipped) {
95 if (angle.y >= 0) {
96 angle.y = -angle.y.mAngle + 0x8000;
97 } else {
98 angle.y = -angle.y.mAngle - 0x8000;
99 }
100 }
101
102 mMatrix.trans(pos.x, pos.y, pos.z);
103 mMatrix.YrotM(l_EnMuki[mDirection] * 0x4000);
104
105 mMatrix.concat(mMtx_c::createTrans(0.0f, 7.0f, 0.0f));
106 mMatrix.XrotM(angle.x);
107 mMatrix.concat(mMtx_c::createTrans(0.0f, -7.0f, 0.0f));
108
109 mMatrix.concat(mMtx_c::createTrans(0.0f, wakeupShakeYOffset, 0.0f));
110 mMatrix.XrotM(mWakeupShakeAngle3D.x);
111 mMatrix.ZrotM(mWakeupShakeAngle3D.z);
112 mMatrix.concat(mMtx_c::createTrans(0.0f, -wakeupShakeYOffset, 0.0f));
113
114 mMatrix.YrotM(l_EnMuki[mDirection ^ 1] * 0x4000);
115 mMatrix.YrotM(angle.y);
116
117 mModel.setLocalMtx(&mMatrix);
118 mModel.setScale(mBoyoMng.getScale());
119 mModel.calc(false);
120
121 calcShellEffectPos();
122}
123
125 if (status == SUCCESS) {
126 if (!isState(StateID_Ice)) {
127 if (!mNoRespawn && hasamiCheck()) {
128 setDeathInfo_Hasami();
129 }
130 mVec3_c pos = mPos;
131 if (!mUseBaseIceBehaviour) {
132 pos = getCenterPos();
133 }
134 WaterCheck(pos, 1.0f);
135 if (mIsCarryFall && mBc.isFoot()) {
136 mIsCarryFall = 0;
137 }
138 }
139
144 if (actor != nullptr) {
145 actor->mCc.mpFriendActor = nullptr;
146 }
148 }
149 }
150 }
151
152 return dEn_c::postExecute(status);
153}
154
155bool daEnShell_c::drawShell() {
156 mModel.entry();
157 return true;
158}
159
160bool daEnShell_c::EtcDamageCheck(dCc_c *self, dCc_c *other) {
162 return false;
163 }
164 return dEn_c::EtcDamageCheck(self, other);
165}
166
167void daEnShell_c::Normal_VsEnHitCheck(dCc_c *self, dCc_c *other) {
168 dActor_c *otherActor = other->getOwner();
169 if (
171 other->mCcData.mVsDamage & (1 << CC_ATTACK_SHELL) &&
172 otherActor->mProfName != fProfile::EN_HATENA_BALLOON &&
173 hitCallback_Shell(self, other)
174 ) {
175 other->mInfo |= CC_NO_HIT;
176 return;
177 }
178 if (
180 (other->mCcData.mStatus & CC_STATUS_8 &&
181 hitCallback_Shell(self, other))
182 ) {
183 self->mInfo |= CC_NO_HIT;
184 return;
185 }
186 float collOffsetX = mCc.mCollOffsetX[CC_KIND_ENEMY];
187 if (
188 mDirection == DIR_LR_L && collOffsetX > 0.0f ||
189 mDirection == DIR_LR_R && collOffsetX < 0.0f
190 ) {
191 setEnemyTurn();
192 }
193}
194
195void daEnShell_c::Normal_VsPlHitCheck(dCc_c *self, dCc_c *other) {
196 dAcPy_c *player = (dAcPy_c *) other->getOwner();
197 if (fManager_c::searchBaseByID(player->mCarryActorID) == this) {
198 return;
199 }
200
201 if (!player->isStatus(0x2b) && isState(StateID_Sleep)) {
202 if (carry_check(player)) {
203 mCarriedBy = mPlayerNo;
204 mCarryPos.set(0.0f, -5.0f, 6.0f);
205 changeState(StateID_Carry);
206 return;
207 }
208 if (!player->isItemKinopio()) {
209 dScoreMng_c *scoreMng;
210 int fumiCount = dEnCombo_c::calcPlFumiCnt(player);
211 if (fumiCount < 1) {
212 fumiCount = 1;
213 }
214 scoreMng = dScoreMng_c::m_instance;
215 scoreMng->ScoreSet(this, fumiCount, player->getPlrNo());
216 }
217 dActor_c *actor = (dActor_c *) fManager_c::searchBaseByID(player->mCarryActorID);
218 if (actor != nullptr) {
219 if (actor->mKind == STAGE_ACTOR_PLAYER) {
220 mNoHitPlayer.mTimer[actor->getPlrNo()] = 10;
221 } else {
222 actor->mCc.mpFriendActor = this;
225 }
226 }
227 if (mInLiquid) {
228 mNoHitPlayer.mTimer[player->getPlrNo()] = 16;
229 }
230 setKickSlide(self, player);
232 return;
233 }
234
235 bool fumiInvalid = isFumiInvalid();
236 int x = 0;
237 if (fumiInvalid) {
238 x = 2;
239 }
240
241 int fumiRes = Enfumi_check(self, other, x);
242 if (fumiRes != 0) {
243 if (fumiRes == 1) {
244 mSpeed.y = 0.0f;
246 setDeathInfo_CarryBgIn(player);
247 } else if (!specialFumiProc(player)) {
248 mSpeed.set(0.0f, 0.0f, 0.0f);
249 mFootPush.set(0.0f, 0.0f, 0.0f);
250 if (mIsMugenCombo) {
251 mPos.x = mMugenComboPosX;
252 }
254 }
255 } else if (fumiRes == 3) {
256 if (fumiInvalid) {
257 dEn_c::Normal_VsPlHitCheck(self, other);
258 } else {
259 setDeathInfo_SpinFumi(player, 1);
260 }
261 } else if (fumiRes == 2 && fumiInvalid) {
262 dEn_c::Normal_VsPlHitCheck(self, other);
263 }
264 } else if (isState(StateID_Sleep)) {
265 if (!player->isItemKinopio()) {
266 dScoreMng_c *scoreMng;
267 int fumiCount = dEnCombo_c::calcPlFumiCnt(player);
268 if (fumiCount < 1) {
269 fumiCount = 1;
270 }
271 scoreMng = dScoreMng_c::m_instance;
272 scoreMng->ScoreSet(this, fumiCount, player->getPlrNo());
273 }
274 dActor_c *actor = (dActor_c *) fManager_c::searchBaseByID(player->mCarryActorID);
275 if (actor != nullptr) {
276 if (actor->mKind == STAGE_ACTOR_PLAYER) {
277 mNoHitPlayer.mTimer[actor->getPlrNo()] = 10;
278 } else {
279 actor->mCc.mpFriendActor = this;
282 }
283 }
284 setKickSlide(self, player);
286 } else if (!isState(daEnCarry_c::StateID_Carry) && !player->isNoDamage()) {
287 if (isState(StateID_Slide) && isSlideTowards(player)) {
288 if (!mIsMugenCombo) {
289 setKickSlide(self, player);
290 if (mInLiquid) {
291 mNoHitPlayer.mTimer[mPlayerNo] = 24;
292 mAccelF = 0.1f;
293 mSpeed.x = l_EnMuki[mDirection] * 7.0f;
294 }
295 }
296 } else {
297 dEn_c::Normal_VsPlHitCheck(self, other);
298 }
299 }
300}
301
302void daEnShell_c::Normal_VsYoshiHitCheck(dCc_c *self, dCc_c *other) {
303 daYoshi_c *yoshi = (daYoshi_c *) other->getOwner();
304
305 bool fumiInvalid = isFumiInvalid();
306 int x = 0;
307 if (fumiInvalid) {
308 x = 1;
309 }
310 int fumiRes = Enfumi_check(self, other, x);
311 if (fumiRes != 0) {
312 if (fumiRes == 1) {
313 mSpeed.y = 0.0f;
315 setDeathInfo_CarryBgIn(yoshi);
316 } else if (!specialFumiProc_Yoshi(yoshi)) {
317 setDeathInfo_YoshiFumi(yoshi);
318 }
319 }
320 } else if (isState(StateID_Sleep) || mYoshiKickable) {
321 dScoreMng_c *scoreMng;
322 int fumiCount = dEnCombo_c::calcPlFumiCnt(yoshi);
323 if (fumiCount < 1) {
324 fumiCount = 1;
325 }
326 scoreMng = dScoreMng_c::m_instance;
327 scoreMng->ScoreSet(this, fumiCount, yoshi->getPlrNo());
328 setKickSlide(self, yoshi);
330 } else if (!isState(daEnCarry_c::StateID_Carry) && !yoshi->isNoDamage()) {
331 if (isState(StateID_Slide) && isSlideTowards(yoshi)) {
332 if (!mIsMugenCombo) {
333 setKickSlide(self, yoshi);
334 }
335 } else {
336 dEn_c::Normal_VsYoshiHitCheck(self, other);
337 }
338 }
339}
340
341bool daEnShell_c::checkComboClap(int max) {
342 if (mIsMugenCombo) {
343 return max >= 8;
344 }
345 return dEn_c::checkComboClap(max);
346}
347
348void daEnShell_c::FumiJumpSet(dActor_c *actor) {
349 if (isFumiInvalid()) {
350 return;
351 }
352 float jumpSpeed = dAcPy_c::msc_JUMP_SPEED + 0.2815f;
353 float speedF = actor->mSpeedF;
354 if (mIsMugenCombo && std::fabs(speedF) < 1.0f) {
355 speedF = 0.0f;
356 }
357 ((daPlBase_c *) actor)->setJump(jumpSpeed, speedF, 1, 0, 2);
358 dEnemyMng_c::m_instance->m_138 = 1;
359}
360
361bool daEnShell_c::hitCallback_Shell(dCc_c *self, dCc_c *other) {
362 daPlBase_c *shell = (daPlBase_c *) other->getOwner();
363 u8 dir = getTrgToSrcDir_Main(getCenterX(), shell->getCenterX());
364 int plrNo = acmShellPlayerNo(shell);
365 shellDamageEffect(self, shell);
366
367 int score = -1;
368
369 if (plrNo < 0) {
370 dAudio::g_pSndObjEmy->startSound(SE_EMY_DOWN, mPos, 0);
371 } else {
372 shell->slideComboSE(shell->mComboMultiplier, false);
373 shell->mComboMultiplier++;
374 if (shell->mComboMultiplier >= 8) {
375 shell->mComboMultiplier = 8;
376 }
377 score = mCombo.getComboScore(shell->mComboMultiplier);
378 }
379
380 float speedMult = 1.0f;
382 speedMult = 0.7f;
383 }
384
385 mDeathInfo = (sDeathInfoData) {
386 speedMult * l_base_fall_speed_x[dir],
387 smc_DEADFALL_YSPEED,
388 smc_DEADFALL_YSPEED_MAX,
389 smc_DEADFALL_GRAVITY,
391 score,
392 -1,
393 dir,
394 (u8) plrNo
395 };
396
397 return true;
398}
399
400void daEnShell_c::FumiScoreSet(dActor_c *actor) {
401 if (isFumiInvalid()) {
402 return;
403 }
404 if (mIsMugenCombo && actor->mSpeed.y > 0.0f) {
405 return;
406 }
407 dEn_c::FumiScoreSet(actor);
408}
409
410void daEnShell_c::setCarryFall(dActor_c *carryingActor, int collisionDelay) {
411 int plrNo = carryingActor->getPlrNo();
412 if (plrNo >= 0 && plrNo < PLAYER_COUNT) {
413 mNoHitPlayer.mTimer[plrNo] = collisionDelay;
414 mIsCarryFall = 1;
415 }
416}
417
418bool daEnShell_c::setDamage(dActor_c *actor) {
419 return setPlayerDamage(actor);
420}
421
422void daEnShell_c::setKickSlide(dCc_c *self, dActor_c *other) {
423 mPlayerNo = other->getPlrNo();
424 mDirection = getTrgToSrcDir_Main(getCenterX(), other->getCenterX());
425 mNoHitPlayer.mTimer[mPlayerNo] = 4;
426 setSlideKickSpeed(other);
427 kickSE(mPlayerNo);
428 float collY = self->mCollPos.y;
429 float collX = self->mCollPos.x;
430 kickEffect(mVec3_c(collX, collY, 5500.0f));
431}
432
434 if (mPlayerNo == -1) {
435 return false;
436 }
437
438 if (!mBc.isFoot() && mPos.y >= actor->mPos.y + 4.0f) {
439 return false;
440 }
441
442 static const float dir[] = { 1.0f, -1.0f };
443
444 u8 idx = !(actor->mPos.x < mPos.x);
445 if (mSpeed.x * dir[idx] >= 0.0f) {
446 return true;
447 }
448
449 return false;
450}
451
453 daPlBase_c *player = (daPlBase_c *) actor;
454
455 if (!ACTOR_PARAM(MugenComboAllowed)) {
456 return false;
457 }
458 if (player->isNowBgCross(daPlBase_c::BGC_FOOT)) {
459 return false;
460 }
461 if (player->mSpeed.y > 0.0f) {
462 return false;
463 }
464
465 mVec3_c playerPos = player->mPos;
466 playerPos.x += l_EnMuki[mDirection] * 1.5f;
467
468 float height = 0.0f;
469 if (dBc_c::checkGround(&playerPos, &height, player->mLayer, 1, -1) && player->mPos.y < height + 16.0f) {
470 return false;
471 }
472
473 mVec3_c centerPos = getCenterPos();
474
475 mVec3_c tileOppositeSide(centerPos.x + l_EnMuki[mDirection ^ 1] * 16.0f, centerPos.y - 16.0f, centerPos.z);
476 if (dBc_c::checkBg(tileOppositeSide.x, tileOppositeSide.y, mLayer, 3, 0x819)) {
477 return false;
478 }
479
480 mVec3_c tileSameSide(centerPos.x + l_EnMuki[mDirection] * 16.0f, centerPos.y, centerPos.z);
481 float wallX = 0.0f;
482 if (!dBc_c::checkWall(&centerPos, &tileSameSide, &wallX, mLayer, 1, nullptr)) {
483 return false;
484 }
485
486 float wallDist = std::fabs(wallX - centerPos.x);
487 float minDist = 8.0f;
488 if (player->mTreadCount < 2) {
489 minDist = 10.0f;
490 }
491 if (wallDist < minDist || wallDist > 16.0f) {
492 return false;
493 }
494
495 if (mDirection == DIR_LR_R) {
496 mMugenComboPosX = wallX - 14.0f;
497 mPos.x = wallX - 15.0f;
498 } else {
499 mMugenComboPosX = wallX + 14.0f;
500 mPos.x = wallX + 15.0f;
501 }
502
503 return true;
504}
505
506bool daEnShell_c::hitCallback_Spin(dCc_c *self, dCc_c *other) {
507 if (!isFumiInvalid()) {
508 dActor_c *actor = other->getOwner();
509
510 setDeathSound_HipAttk();
511 hipatkEffect(actor->mPos);
512 SpinFumiScoreSet(actor);
513 setDeathInfo_SpinFumi(actor, 1);
514 return true;
515 }
516 return false;
517}
518
519bool daEnShell_c::hitCallback_HipAttk(dCc_c *self, dCc_c *other) {
520 if (isFumiInvalid()) {
521 return false;
522 }
523
524 dActor_c *actor = other->getOwner();
525
526 setDeathSound_HipAttk();
527 hipatkEffect(actor->mPos);
528 SpinFumiScoreSet(actor);
529
530 u8 dir = getTrgToSrcDir_Main(getCenterX(), actor->getCenterX());
531 u8 plrNo = actor->getPlrNo();
532
533 mDeathInfo = (sDeathInfoData) {
534 l_base_fall_speed_x[dir],
535 smc_DEADFALL_YSPEED,
536 smc_DEADFALL_YSPEED_MAX,
537 smc_DEADFALL_GRAVITY,
539 -1,
540 -1,
541 dir,
542 plrNo
543 };
544
545 return true;
546}
547
548bool daEnShell_c::hitCallback_YoshiHipAttk(dCc_c *self, dCc_c *other) {
549 daYoshi_c *yoshi = (daYoshi_c *) other->getOwner();
550
551 if (isFumiInvalid()) {
552 float speedF = 0.0f;
553 float jumpSpeed = 4.5f;
554 yoshi->setJump(jumpSpeed, speedF, 1, 0, 2);
555 yoshifumistepSE(yoshi);
556 mNoHitPlayer.mTimer[yoshi->getPlrNo()] = 5;
557 } else {
558 dEn_c::hitCallback_YoshiHipAttk(self, other);
559 }
560
561 return true;
562}
563
564bool daEnShell_c::cullCheck() {
565 if (isState(StateID_Slide) && cullCheck_Shell()) {
567 return true;
568 }
569
570 return ActorScrOutCheck(0);
571}
572
573bool daEnShell_c::cullCheck_Shell() {
574 dBgParameter_c *bgParam = dBgParameter_c::ms_Instance_p;
575
576 float xStart = bgParam->xStart();
577 float yStart = bgParam->yStart();
578 float xEnd = bgParam->xStart() + bgParam->xSize();
579 float yEnd = bgParam->yStart() - bgParam->ySize();
580
581 float right = mPos.x + mVisibleAreaSize.x * 0.5f;
582 float left = mPos.x - mVisibleAreaSize.x * 0.5f;
583 float bottom = mPos.y + mVisibleAreaSize.y;
584 float top = mPos.y;
585
586 if (right < xStart - 160.0f) {
587 return true;
588 }
589 if (left > xEnd + 160.0f) {
590 return true;
591 }
592 if (top > yStart + 256.0f) {
593 return true;
594 }
595
596 float offs = 256.0f;
597 if (mBc.mFlags & 0x8000) {
598 const dRide_ctr_c *ride = mRc.getRide();
599 if (ride != nullptr && ride->mOwner != nullptr && ride->mOwner->mProfName == fProfile::AC_FLOOR_GYRATION) {
600 offs = 64.0f;
601 }
602 }
603 if (bottom < yEnd - offs) {
604 return true;
605 }
606
607 return false;
608}
609
612 return false;
613 }
614
616}
617
620 if (isBlockHitDeath()) {
622 return;
623 }
624 mVec3_c efPos(mVec2_c(mPos.x, mPos.y), 5500.0f);
625 hitdamageEffect(efPos);
626 dAudio::g_pSndObjEmy->startSound(SE_EMY_DOWN, mPos, 0);
627 mIsFlipped = true;
628 mSpeed.set(l_base_fall_speed_x[mDirection] * 0.5f, 3.5f, 0.0f);
629 if (isState(StateID_Sleep)) {
630 mStateMgr.initializeState();
631 } else {
633 }
634}
635
636void daEnShell_c::setSlideThrowSpeed(dActor_c *actor) {
637 float baseSpeed = actor->mSpeed.x;
638 float speed = l_slide_throw_speed[mDirection];
639 if (mDirection == baseSpeed < 0.0f) {
640 speed += baseSpeed * 0.35f;
641 }
642 mCc.mpFriendActor = nullptr;
643 if (actor->mKind == STAGE_ACTOR_PLAYER) {
644 dAcPy_c *player = (dAcPy_c *) actor;
645 if (player->m_1308 == BASE_ID_NULL) {
646 mCc.mpFriendActor = player;
647 }
648 } else if (actor->mKind == STAGE_ACTOR_YOSHI) {
649 daYoshi_c *yoshi = (daYoshi_c *) actor;
650 if (yoshi->isStar()) {
651 mCc.mpFriendActor = yoshi;
652 }
653 }
654
655 if (speed < mSpeedMax.x) {
656 float tmp;
657 if (speed > mSpeedMax.x) {
658 tmp = mSpeedMax.x;
659 } else {
660 tmp = speed;
661 }
662 speed = tmp;
663 } else if (speed > mSpeedMax.x) {
664 float tmp;
665 if (speed < mSpeedMax.x) {
666 tmp = mSpeedMax.x;
667 } else {
668 tmp = speed;
669 }
670 speed = tmp;
671 }
672 mSpeed.set(speed, 0.2f, 0.0f);
673}
674
675void daEnShell_c::setSlideKickSpeed(dActor_c *actor) {
676 float baseSpeed = actor->mSpeed.x;
677 float speed = l_slide_throw_speed[mDirection];
678 if (mDirection == baseSpeed < 0.0f) {
679 speed += baseSpeed * 0.5f;
680 }
681 mSpeed.x = speed;
682}
683
684void daEnShell_c::slideSpin() {
685 float tmp = std::fabs(mSpeed.x) / 2.5f;
686 s16 angle = tmp * GLOBAL_DATA.mSpinSpeed;
687 if (mDirection == DIR_LR_L) {
688 angle = -angle;
689 }
690 mAngle.y += angle;
691}
692
693void daEnShell_c::kickSE(int plrNo) {
694 if (plrNo >= 0 && plrNo < PLAYER_COUNT) {
695 dAudio::SoundEffectID_t se(SE_EMY_KAME_KERU);
696 se.playEmySound(getCenterPos(), dAudio::getRemotePlayer(mPlayerNo));
697 }
698}
699
700void daEnShell_c::setDeathInfo_CarryBgIn(dActor_c *actor) {
701 mDeathInfo = (sDeathInfoData) {
702 0.0f,
703 3.0f,
704 -4.0f,
705 -0.1875f,
707 -1,
708 -1,
710 (u8) actor->getPlrNo()
711 };
712}
713
715 dEn_c::setEatTongue(actor);
716 mPlayerNo = actor->getPlrNo();
717}
718
720 calcSpitOutPos(actor);
721 reviveCc();
724 mDirection = actor->mDirection;
725 mPlayerNo = actor->getPlrNo();
726
727 u32 unit1 = dBc_c::getUnitType(mPos.x, mPos.y, mLayer);
728 u32 unit2 = dBc_c::getUnitType(mPos.x, mPos.y + 16.0f, mLayer);
729
730 bool smth = false;
731 if ((unit1 & 0x1001d) && !(unit2 & 0x1001d)) {
732 smth = true;
733 mPos.y = (int) (mPos.y / 16.0f) * 16.0f;
734 }
735 if (!smth && mBc.checkWallEnm(nullptr)) {
736 mPos.x = actor->mPos.x;
737 }
738
739 mNoHitPlayer.mTimer[mPlayerNo] = 16;
740 setSlideThrowSpeed(actor);
741 mSpeed.y = 1.4f;
742 mAccelY = -0.09375f;
743
744 daPlBase_c *player = (daPlBase_c *) actor;
745 if (player->isStatus(0x30)) {
746 static const float cs_slip_offset[] = { 8.0f, -8.0f };
747 mPos.x += cs_slip_offset[mDirection];
748 }
750
751 return true;
752}
753
754bool daEnShell_c::hitCallback_Ice(dCc_c *self, dCc_c *other) {
755 if (mIceMng.mActive) {
756 return true;
757 }
758
759 if (other->mpOwner->mSpeed.x >= 0.0f) {
760 mBoyoMng.mDirection = DIR_LR_R;
761 } else {
762 mBoyoMng.mDirection = DIR_LR_L;
763 }
764 for (int i = 0; i < PLAYER_COUNT; i++) {
765 dAcPy_c *player = daPyMng_c::getPlayer(i);
766 if (player != nullptr && fManager_c::searchBaseByID(player->mCarryActorID) == this) {
767 player->cancelCarry(this);
768 break;
769 }
770 }
771 if (!mUseBaseIceBehaviour) {
772 changeState(StateID_Ice);
773 mPlayerNo = -1;
774 } else {
775 dEn_c::hitCallback_Ice(self, other);
776 }
777 return true;
778}
779
780void daEnShell_c::returnState_Ice() {
781 if (!mUseBaseIceBehaviour) {
782 mPlayerNo = -1;
783 mSpeed.set(0.0f, 0.0f, 0.0f);
785 } else {
786 dEn_c::returnState_Ice();
787 }
788}
789
790void daEnShell_c::adjustCarryCc() {
791 const static float cs_check_ofs[] = { -8.0f, 8.0f };
792 bool dir = mAngle.y < 0;
793
794 mVec3_c pos(getCenterPos().x + cs_check_ofs[dir], getCenterPos().y, getCenterPos().z);
795 mVec3_c pos2(pos.x + l_EnMuki[dir] * 16.0f, pos.y, pos.z);
796
797 mCc.mCcData.mBase.mOffset.set(mCcOffset.x, mCcOffset.y);
798 mCc.mCcData.mBase.mSize.set(mCcSize.x, mCcSize.y);
799
800 float wallX = 0.0f;
801 if (dBc_c::checkWall(&pos, &pos2, &wallX, mLayer, 1, nullptr)) {
802 float offsX = (pos.x + wallX) * 0.5f;
803 float sizeX = std::fabs((pos.x - wallX) * 0.5f);
804
805 mCc.mCcData.mBase.mOffset.set(offsX - mPos.x, 8.0f);
806 mCc.mCcData.mBase.mSize.set(sizeX, 8.0f);
807 }
808}
809
810bool daEnShell_c::checkSleep() {
811 if (mCarryTimer > 0) {
812 mCarryTimer--;
813 return false;
814 }
815
816 if (isFunsui()) {
817 return false;
818 }
819
820 mSleepTimer--;
821 if (mSleepTimer < smc_SLEEP_TIMER_SHAKE) {
822 mWakeupShakeAngle += GLOBAL_DATA.mUnkSpeed;
823 float sin = mWakeupShakeAngle.sin();
824 float cos = mWakeupShakeAngle.cos();
825 mWakeupShakeAngle3D.x.mAngle = sin * (0x10000 / 128.0f * 5.0f);
826 mWakeupShakeAngle3D.z.mAngle = cos * (0x10000 / 128.0f * 5.0f);
827 if (mSleepTimer == 0) {
828 mWakeupShakeAngle3D.x = 0;
829 mWakeupShakeAngle3D.z = 0;
830 return true;
831 }
832 }
833 return false;
834}
835
837 s16 plrNo = carryingActor->getPlrNo();
838 mCarriedBy = plrNo;
839 mPlayerNo = plrNo;
840 mCarryPos.set(0.0f, 0.0f, 0.0f);
841 changeState(StateID_Carry);
842}
843
844bool daEnShell_c::hasamiCheck() {
845 if (mBgCollFlags != COLL_NONE) {
846 if ((mBgCollFlags & COLL_WALL_L) && mBc.isWallR() && !(mBc.mFlags & dBc_c::FLAG_8)) {
847 return true;
848 }
849
850 if ((mBgCollFlags & COLL_WALL_R) && mBc.isWallL() && !(mBc.mFlags & dBc_c::FLAG_8)) {
851 return true;
852 }
853
854 if ((mBgCollFlags & COLL_HEAD) && mBc.isFoot()) {
855 return true;
856 }
857
858 if ((mBgCollFlags & COLL_FOOT) && mBc.isHead() && !(mBc.getFlags() & dBc_c::FLAG_30)) {
859 return true;
860 }
861 }
862
863 return false;
864}
865
866void daEnShell_c::setDeathInfo_Hasami() {
867 u8 dir = !(mPos.x - mLastPos.x >= 0.0f);
868 mVec3_c efPos(mVec2_c(mPos.x, mPos.y + mCenterOffs.y), 5500.0f);
869 hitdamageEffect(efPos);
870 removeCc();
871 dAudio::g_pSndObjEmy->startSound(SE_EMY_DOWN, mPos, 0);
872 mDeathInfo = (sDeathInfoData) {
873 l_base_fall_speed_x[dir],
874 smc_DEADFALL_YSPEED,
875 smc_DEADFALL_YSPEED_MAX,
876 smc_DEADFALL_GRAVITY,
878 -1,
879 -1,
880 dir,
881 (u8) -1
882 };
883}
884
885void daEnShell_c::initializeState_Sleep() {
886 mSleepTimer = smc_SLEEP_TIMER;
887 mSpeedMax.y = -4.0f;
888 mAccelY = -0.1875f;
889 clrComboCnt();
890 mUseBaseIceBehaviour = 0;
891 mCc.mCcData.mVsDamage |= (1 << CC_ATTACK_SPIN_LIFT_UP);
892 mWakeupShakeAngle = 0;
893 mWakeupShakeAngle3D.x = 0;
894 mWakeupShakeAngle3D.y = 0;
895 mWakeupShakeAngle3D.z = 0;
896}
897
898void daEnShell_c::finalizeState_Sleep() {
899 mCc.mCcData.mVsDamage &= ~(1 << CC_ATTACK_SPIN_LIFT_UP);
900 mActorProperties &= ~BIT_FLAG(2);
902}
903
904void daEnShell_c::executeState_Sleep() {
905 if (mIsFlipped) {
906 u16 ang = mAngle.x;
907 if (mDirection) {
908 ang -= 0x800;
909 if (ang < 0x8000) {
910 ang = 0x8000;
911 }
912 } else {
913 ang += 0x800;
914 if (ang > 0x8000) {
915 ang = -0x8000;
916 }
917 }
918 mAngle.x = ang;
919 }
920 calcSpeedY();
921 posMove();
922
923 u32 bgCheckRes = EnBgCheck();
924 if (bgCheckRes & 1) {
925 Bound(0.1875f, 0.5f, 0.5f);
926 }
927 if (bgCheckRes & 2) {
928 mSpeed.y = 0.0f;
929 }
930 if (bgCheckRes & 4) {
931 mSpeed.x = 0.0f;
932 }
933
934 if (checkSleep()) {
935 if (mIsFlipped) {
937 } else {
939 }
940 }
941}
942
943void daEnShell_c::initializeState_Carry() {
944 mPlayerNo = mCarriedBy;
945 dAcPy_c *player = daPyMng_c::getPlayer(mPlayerNo);
946 if (player->mAmiLayer == 1) {
947 mAmiLayer = 0;
948 } else {
949 mAmiLayer = 1;
950 }
951 mCc.mAmiLine = l_Ami_Line[mAmiLayer];
952 mBc.mAmiLine = l_Ami_Line[mAmiLayer];
953 float x = mCc.mCcData.mBase.mOffset.x;
954 float y = mCc.mCcData.mBase.mOffset.y;
955 mCcOffset.set(x, y);
956 float w = mCc.mCcData.mBase.mSize.x;
957 float h = mCc.mCcData.mBase.mSize.y;
958 mCcSize.set(w, h);
959 if (player->mPowerup != POWERUP_MINI_MUSHROOM && player->mPowerup != POWERUP_NONE) {
960 mCc.mCcData.mBase.mOffset.set(0.0f, 5.0f);
961 mCc.mCcData.mBase.mSize.set(7.0f, 9.0f);
962 }
963 mCc.mCcData.mVsKind |= (1 << CC_KIND_KILLER);
964 mCc.mCcData.mAttack = CC_ATTACK_SHELL;
965 mRc.setRide(nullptr);
966 if (mSleepTimer > smc_SLEEP_TIMER_SHAKE) {
968 }
969 mUseBaseIceBehaviour = 0;
970 mWakeupShakeAngle = 0;
971 mWakeupShakeAngle3D.x = 0;
972 mWakeupShakeAngle3D.y = 0;
973 mWakeupShakeAngle3D.z = 0;
974 mFootAttr3 = false;
975}
976
977void daEnShell_c::finalizeState_Carry() {
978 dAcPy_c *player = daPyMng_c::getPlayer(mCarriedBy);
979 player->cancelCarry(this);
980 mCc.mCcData.mBase.mOffset.set(mCcOffset.x, mCcOffset.y);
981 mCc.mCcData.mBase.mSize.set(mCcSize.x, mCcSize.y);
982 mCc.mCcData.mVsKind &= ~(1 << CC_KIND_KILLER);
983 mCc.mCcData.mAttack = CC_ATTACK_NONE;
984 mRc.setRide(nullptr);
985 mBc.mFlags = 0;
987 mCarryTimer = 0;
988 if (mPos.z >= 0.0f) {
989 mAmiLayer = 0;
990 } else {
991 mAmiLayer = 1;
992 }
993}
994
995void daEnShell_c::executeState_Carry() {
996 dAcPy_c *player = daPyMng_c::getPlayer(mCarriedBy);
999 mAngle.y = l_base_angleY[mDirection];
1000 if (checkWallAndBg()) {
1001 setDeathInfo_CarryBgIn(player);
1002 } else {
1003 if (!(mBc.mFlags & (0x15 << mDirection))) {
1004 mPos.x += l_EnMuki[mDirection] * 6.0f;
1005 }
1007 setSlideThrowSpeed(player);
1009 } else {
1011 }
1012 }
1013 } else if (checkSleep()) {
1014 mDirection = player->mDirection;
1015 if (checkWallAndBg()) {
1016 setDeathInfo_CarryBgIn(player);
1017 } else if (mIsFlipped) {
1019 } else {
1021 }
1022 } else {
1023 mAngle.y = player->mAngle.y;
1024 adjustCarryCc();
1025 }
1026}
1027
1028void daEnShell_c::initializeState_Slide() {
1029 mSensorFootSlide.mBase.mFlags = 1;
1030 mSensorFootSlide.mLineA = -0x3000;
1031 mSensorFootSlide.mLineB = 0x2000;
1032 mSensorFootSlide.mDistanceFromCenter = 0;
1033
1034 if (mPlayerNo >= 0 && mPlayerNo < PLAYER_COUNT) {
1035 dAcPy_c *player = daPyMng_c::getPlayer(mPlayerNo);
1036
1037 mCc.mAmiLine = player->mCc.mAmiLine;
1038 mBc.mAmiLine = player->mCc.mAmiLine;
1039
1040 mIsMugenCombo = checkMugenCombo(player);
1041 if (mIsMugenCombo) {
1042 mMugenComboSpeed = 0.0f;
1043 if (player->mPowerup == POWERUP_NONE) {
1044 mSpeed.x = l_EnMuki[mDirection] * GLOBAL_DATA.mSlideSpeedNoPowerup;
1045 } else {
1046 mSpeed.x = l_EnMuki[mDirection] * GLOBAL_DATA.mSlideSpeedPowerup;
1047 }
1048 mNoHitPlayer.mTimer[mPlayerNo] = 3;
1049 mFumiProc.refresh(new MugenComboFumiCheck_c());
1050 } else if (!player->mBc.isFoot()) {
1051 mNoHitPlayer.mTimer[mPlayerNo] = 18;
1052 } else {
1053 mNoHitPlayer.mTimer[mPlayerNo] = 10;
1054 }
1055
1056 mSensorHead.mBase.mFlags |= 0xc0000;
1057 mSensorFootNormal.mBase.mFlags |= 0xc0000;
1058 mSensorWall.mBase.mFlags |= 0xc0000;
1059 mSensorFootSlide.mBase.mFlags |= 0xc0000;
1060 }
1061
1062 mSlideAirAfterThrow = 0;
1063 if (*mStateMgr.getOldStateID() == StateID_Carry) {
1064 mSlideAirAfterThrow = 1;
1065 }
1066
1067 mCc.mCcData.mVsKind |= (1 << CC_KIND_BALLOON) | (1 << CC_KIND_ITEM) | (1 << CC_KIND_KILLER);
1068 mCc.mCcData.mAttack = CC_ATTACK_SHELL;
1069
1070 mUseBaseIceBehaviour = 0;
1071 mAccelF = 1 / 1024.0f;
1072 mAccelY = -0.1875f;
1073 mSpeedMax.set(mSpeed.x, -4.0f, 0.0f);
1074
1075 mSensorHead.mBase.mFlags |= 0x900000;
1076 mSensorWall.mBase.mFlags |= 0x900000;
1078 mSensorHead.mBase.mFlags |= 0x400;
1079 mSensorWall.mBase.mFlags |= 0x400;
1080 }
1081 mBc.set(this, mSensorFootSlide, mSensorHead, mSensorWall);
1082
1083 mBc.mOwningPlrNo = mPlayerNo;
1084 mWakeupShakeAngle = 0;
1085 mWakeupShakeAngle3D.x = 0;
1086 mWakeupShakeAngle3D.y = 0;
1087 mWakeupShakeAngle3D.z = 0;
1088 if (mIsFlipped) {
1089 mAngle.x = -0x8000;
1090 } else {
1091 mAngle.x = 0;
1092 }
1093}
1094
1095void daEnShell_c::finalizeState_Slide() {
1096 if (mIsMugenCombo) {
1097 static const float speeds[] = { 0.375f, -0.375f };
1098 mSpeed.x = speeds[mDirection];
1099 mFumiProc.refresh(new NonUniqueFumiCheck_c());
1100 } else {
1101 clrComboCnt();
1102 }
1103 mIsMugenCombo = 0;
1104 mCc.mCcData.mVsKind &= ~((1 << CC_KIND_BALLOON) | (1 << CC_KIND_ITEM) | (1 << CC_KIND_KILLER));
1105 mCc.mCcData.mAttack = CC_ATTACK_NONE;
1106 mAccelF = 0.0f;
1107 mSpeedMax.set(0.0f, -4.0f, 0.0f);
1108 mSensorHead.mBase.mFlags &= ~0x49c0400;
1109 mSensorFootNormal.mBase.mFlags &= ~0xc0000;
1110 mSensorWall.mBase.mFlags &= ~0x9c0400;
1111 mSensorFootSlide.mBase.mFlags &= ~0xc0000;
1112 mBc.set(this, mSensorFootNormal, mSensorHead, mSensorWall);
1113 mBc.mOwningPlrNo = -1;
1114 mPlayerNo = -1;
1115}
1116
1117void daEnShell_c::executeState_Slide() {
1118 mRc.mFlags &= ~0x8;
1119 calcSpeedX();
1120 calcSpeedY();
1121 posMove();
1122 slideSpin();
1123 slideEffect();
1124 if (mJumpPlayerNoCarryHitTimer == 0) {
1125 mSensorHead.mBase.mFlags &= ~0x400;
1126 mSensorWall.mBase.mFlags &= ~0x400;
1127 }
1128 EnBgCheckWall();
1129 EnBgCheckFoot();
1130 mBc.checkHead(mBc.mFlags);
1131 if (mIsMugenCombo) {
1132 float max = 14.0f;
1133 mMugenComboSpeed += std::fabs(mSpeed.x);
1134 if (std::fabs(mMugenComboSpeed) > max) {
1135 mAccelF = 0.15f;
1136 mNoHitPlayer.mTimer[mPlayerNo] = 16;
1137 mSpeedMax.x = l_slide_max_speed[mDirection];
1138 mIsMugenCombo = 0;
1139 } else {
1140 dAcPy_c *player = daPyMng_c::getPlayer(mPlayerNo);
1141 if (player->isNowBgCross(daPlBase_c::BGC_FOOT)) {
1142 mAccelF = 0.15f;
1143 mSpeedMax.x = l_slide_max_speed[mDirection];
1144 mIsMugenCombo = 0;
1145 mNoHitPlayer.mTimer[mPlayerNo] = 16;
1146 }
1147 }
1148 }
1149 if (mBc.isFoot()) {
1150 mAccelY = -0.1875f;
1151 mSpeed.y = 0.0f;
1152 mSlideAirAfterThrow = 0;
1153 mCc.mpFriendActor = nullptr;
1154 if (mBc.getFootAttr() == 3) {
1155 mCc.release();
1156 mPos.y -= 0.25f;
1157 }
1158 } else {
1159 if (mSlideAirAfterThrow) {
1160 mVec3_c pos(mPos.x, mPos.y + 6.0f, mPos.z);
1161 float height;
1162 if (dBc_c::checkGround(&pos, &height, mLayer, 1, -1) && mPos.y < height) {
1163 mSlideAirAfterThrow = 0;
1164 mCc.mpFriendActor = nullptr;
1165 u32 unitKind = dBc_c::getUnitKind(mPos.x, mPos.y - 1.0f, mLayer);
1166 if (((unitKind >> 16) & 0xFF) != 8 && height <= pos.y) {
1167 mPos.y = height;
1168 }
1169 }
1170 }
1171 if (mBc.isHead()) {
1172 mSpeed.y = -0.625f;
1173 }
1174 }
1175
1176 if (mBc.mFlags & (0x15 << mDirection)) {
1177 mDirection ^= 1;
1178 mSpeed.x = -mSpeed.x;
1179 mSpeedMax.x = -mSpeedMax.x;
1180 mSpeed.y -= 0.8125f;
1181 dAudio::g_pSndObjEmy->startSound(SE_OBJ_KOURA, getCenterPos(), 0);
1182 }
1183}
1184
1185void daEnShell_c::initializeState_Wakeup() {
1187 mIsFlipped = 0;
1188 mAngle.x = 0;
1189 mSpeed.set(0.0f, 0.0f, 0.0f);
1190 mSpeedMax.set(0.0f, -4.0f, 0.0f);
1191}
1192
1193void daEnShell_c::finalizeState_Wakeup() {}
1194
1195void daEnShell_c::executeState_Wakeup() {
1196 calcSpeedY();
1197 posMove();
1198 u32 bgCheckRes = EnBgCheck();
1199 if (bgCheckRes & 1) {
1200 mSpeed.y = 0.0f;
1201 }
1202 if (bgCheckRes & 4) {
1203 mSpeed.x = 0.0f;
1204 }
1206}
1207
1208void daEnShell_c::initializeState_WakeupTurn() {
1210}
1211
1212void daEnShell_c::finalizeState_WakeupTurn() {}
1213
1214void daEnShell_c::executeState_WakeupTurn() {
1215 calcSpeedY();
1216 posMove();
1217 u32 bgCheckRes = EnBgCheck();
1218 if (bgCheckRes & 1) {
1219 mSpeed.y = 0.0f;
1220 }
1221 if (bgCheckRes & 4) {
1222 mSpeed.x = 0.0f;
1223 }
1224 if (turnProc()) {
1225 setAfterSleepState();
1226 }
1227}
1228
1229void daEnShell_c::initializeState_WakeupReverse() {
1230 mSpeed.set(0.0f, 3.0f, 0.0f);
1231}
1232
1233void daEnShell_c::finalizeState_WakeupReverse() {}
1234
1235void daEnShell_c::executeState_WakeupReverse() {
1236 calcSpeedY();
1237 posMove();
1238 mAngle.x += 0x400;
1239 u32 bgCheckRes = EnBgCheck();
1240 if (bgCheckRes & 1) {
1241 mSpeed.y = 0.0f;
1242 }
1243 if (bgCheckRes & 4) {
1244 mSpeed.x = 0.0f;
1245 }
1246 if (mBc.isFoot()) {
1248 }
1249}
1250
1251void daEnShell_c::initializeState_DieFall() {
1252 if (isDieShell()) {
1253 mUseBaseIceBehaviour = 0;
1254 }
1255 mFootAttr3 = false;
1256 dEn_c::initializeState_DieFall();
1257}
1258
1259void daEnShell_c::finalizeState_DieFall() {
1260 dEn_c::finalizeState_DieFall();
1261}
1262
1263void daEnShell_c::executeState_DieFall() {
1264 const static s16 cs_spin_speed[] = { 0x400, -0x400 };
1265 s16 spinX, spinY;
1267 spinX = smc_DEADFALL_SPINSPEED;
1268 spinY = -cs_spin_speed[mIceDeathDirection];
1269 } else {
1270 spinX = -smc_DEADFALL_SPINSPEED;
1271 spinY = cs_spin_speed[mIceDeathDirection];
1272 }
1273 if (mInLiquid) {
1274 spinX *= smc_WATER_ROLL_DEC_RATE;
1275 spinY *= smc_WATER_ROLL_DEC_RATE;
1276 }
1277 mAngle.x += spinX;
1278 mAngle.y += spinY;
1279 calcSpeedY();
1280 posMove();
1281}
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.
The minimum required implementation for a stage actor.
Definition d_actor.hpp:15
void deleteActor(u8 deleteForever)
Deletes the actor and optionally disables respawn.
Definition d_actor.cpp:355
void slideComboSE(int multiplier, bool shortCombo)
Plays the combo kill sound effect.
Definition d_actor.cpp:700
@ CARRY_RELEASE
The actor is being released from carry.
Definition d_actor.hpp:54
@ CARRY_THROW
The actor is being actively thrown by the player.
Definition d_actor.hpp:55
virtual s8 & getPlrNo()
Gets the player number associated with the actor. See mPlayerNo.
Definition d_actor.hpp:105
bool mNoRespawn
Whether the actor should not respawn after being deleted.
Definition d_actor.hpp:378
virtual void reviveCc()
Enables the actor's collision.
Definition d_actor.cpp:804
dBc_c mBc
The actor-to-tile collision sensor.
Definition d_actor.hpp:342
static bool getTrgToSrcDir_Main(float trgX, float srcX)
See getTrgToSrcDirFunc.
Definition d_actor.cpp:276
static void setSoftLight_Enemy(m3d::bmdl_c &mdl)
Sets the soft light effect for enemies.
Definition d_actor.cpp:325
void clrComboCnt()
Clears the actor's combo counter.
Definition d_actor.cpp:727
u32 mCarryingFlags
The actor's carry actions. See CARRY_ACTION_e.
Definition d_actor.hpp:333
u8 mKind
The actor's kind. Value is a STAGE_ACTOR_KIND_e.
Definition d_actor.hpp:374
u8 mEatState
The actor's eat state. Value is a EAT_STATE_e.
Definition d_actor.hpp:365
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
u8 mAmiLayer
The actor's layer for chainlink fences.
Definition d_actor.hpp:379
u8 mDirection
The actor's facing direction.
Definition d_actor.hpp:351
dCc_c mCc
The actor-to-actor collision sensor.
Definition d_actor.hpp:341
virtual bool ActorDrawCullCheck()
Checks if the actor is out of view.
Definition d_actor.cpp:444
mVec2_c mVisibleAreaSize
The size of the area inside which the actor is visible.
Definition d_actor.hpp:347
virtual void removeCc()
Disables the actor's collision.
Definition d_actor.cpp:800
u8 mThrowDirection
The actor's direction when thrown or dropped after carrying.
Definition d_actor.hpp:334
int mComboMultiplier
The current combo multiplier obtained by the actor by colliding with other actors.
Definition d_actor.hpp:335
s8 mPlayerNo
The player associated with the actor, -1 if not associated to any player.
Definition d_actor.hpp:375
bool ActorScrOutCheck(u16 flags)
Checks if the actor is out of gameplay and optionally deletes it.
Definition d_actor.cpp:413
@ EAT_STATE_NONE
The actor is not being eaten.
Definition d_actor.hpp:27
dActor_c()
Constructs a new actor.
Definition d_actor.cpp:46
@ COLL_FOOT
The actor collided with the ground.
Definition d_actor.hpp:63
@ COLL_HEAD
The actor collided with a ceiling.
Definition d_actor.hpp:64
@ COLL_WALL_L
The actor collided with a wall on its left.
Definition d_actor.hpp:61
@ COLL_WALL_R
The actor collided with a wall on its right.
Definition d_actor.hpp:62
@ COLL_NONE
The actor did not collide with any surface.
Definition d_actor.hpp:60
dRc_c mRc
The actor's ride surface manager.
Definition d_actor.hpp:343
virtual void setAfterEatScale()
Restores the actor's scale once spat out.
Definition d_actor.cpp:647
@ STAGE_ACTOR_YOSHI
The Yoshi actor.
Definition d_actor.hpp:48
@ STAGE_ACTOR_PLAYER
The player actor.
Definition d_actor.hpp:47
virtual void calcSpitOutPos(dActor_c *eatingActor)
Calculates the position where the actor will be spat out.
Definition d_actor.cpp:651
u8 mLayer
The actor's layer.
Definition d_actor.hpp:377
u8 mBgCollFlags
The collision directions that the actor collided with in the previous frame. Value is a BG_COLL_FLAG_...
Definition d_actor.hpp:353
mMtx_c mMatrix
The actor's partial transformation matrix. See makeMtx() for details.
float mAccelF
The actor's horizontal acceleration.
mVec3_c mSpeed
The actor's speed.
mVec3_c mLastPos
The actor's position in the previous frame.
mVec3_c mPos
The actor's position.
mVec3_c mSpeedMax
The actor's maximum speed.
void calcSpeedX()
Updates the actor's X speed. See here for details.
mVec3_c mCenterOffs
The offset from the position to the center of the actor (defaults to 0).
float mSpeedF
The actor's horizontal speed.
void posMove()
Moves the actor by its speed.
mVec3_c getCenterPos() const
Gets the actor's centered position.
mAng3_c mAngle
The actor's rotation (for 2D actors).
u32 mActorProperties
The actor's properties. See fProfile::fActorProfile_c::mActorProperties.
float mAccelY
The actor's vertical acceleration.
void calcSpeedY()
Updates the actor's Y speed. See here for details.
Collider ("Collision Check") class - handles collisions between actors.
Definition d_cc.hpp:118
dActor_c * mpOwner
The actor this collider belongs to.
Definition d_cc.hpp:263
u8 mInfo
Info flags for this collider. See CC_INFO_e.
Definition d_cc.hpp:322
mVec2_c mCollPos
The position where the last collision occurred.
Definition d_cc.hpp:299
dActor_c * getOwner() const
Gets the owner actor of this collider.
Definition d_cc.hpp:163
sCcDatNewF mCcData
The collision data of this collider.
Definition d_cc.hpp:273
u8 mAmiLine
The non-collide mask for this collider.
Definition d_cc.hpp:313
dActor_c * mpFriendActor
A second actor that this collider will not collide with.
Definition d_cc.hpp:264
bool getPl_LRflag(const mVec3_c &pos)
Checks whether the nearest player is to the left of pos.
Definition d_enemy.cpp:398
u8 mDeathFallDirection
The X direction to move towards on death.
Definition d_enemy.hpp:276
u8 mIceDeathDirection
The X direction to move towards on ice death.
Definition d_enemy.hpp:277
void WaterCheck(mVec3_c &pos, float h)
Definition d_enemy.cpp:729
u32 checkWallAndBg()
Definition d_enemy.cpp:429
dDeathInfo_c mDeathInfo
The parameters for the death animation.
Definition d_enemy.hpp:270
dIceMng_c mIceMng
The ice manager for this enemy.
Definition d_enemy.hpp:285
dEnCombo_c mCombo
The enemy combo manager.
Definition d_enemy.hpp:299
virtual void changeState(const sStateIDIf_c &newState)
Changes the actor's state to the given state.
static sFStateVirtualID_c< dEn_c > StateID_DieFall
Falling out of the screen.
Definition d_enemy.hpp:168
virtual void block_hit_init()
Callback for when a block directly beneath the actor is hit.
Definition d_enemy.cpp:1005
dPlayerDownTimer_c mNoHitPlayer
Hit cooldown timers for each player. This is used to prevent, for example, a thrown shell from hittin...
Definition d_enemy.hpp:296
virtual void postExecute(fBase_c::MAIN_STATE_e status)
post method for the execute operation.
Definition d_enemy.cpp:108
virtual void setEatTongue(dActor_c *)
Callback for when the actor is targeted by Yoshi's tongue.
Definition d_enemy.cpp:945
bool mInLiquid
Whether the enemy is in a liquid.
Definition d_enemy.hpp:281
virtual bool checkComboClap(int max)
Definition d_enemy.cpp:544
static dResMng_c * m_instance
The instance of this class.
Definition d_res_mng.hpp:61
static sFStateVirtualID_c< daEnCarry_c > StateID_Carry
The enemy is being carried.
Base implementation of a shell enemy.
virtual bool setEatSpitOut(dActor_c *actor)
Callback for when the actor is about to be spat out.
virtual void setEatTongue(dActor_c *actor)
Callback for when the actor is targeted by Yoshi's tongue.
u16 mSleepTimer
How many frames longer the shell will remain asleep.
virtual bool ActorDrawCullCheck()
Checks if the actor is out of view.
virtual void postExecute(fBase_c::MAIN_STATE_e status)
post method for the execute operation.
bool mIsFlipped
Whether the shell is flipped upside down from a block hit.
static sFStateVirtualID_c< daEnShell_c > StateID_Wakeup
Waking up from the sleep state.
fBaseID_e mJumpPlayerCarryActorID
The actor which the player who jumped on the shell is currently carrying.
u16 mCarryTimer
How many more frames the sleep timer will remain paused while being carried.
static sFStateVirtualID_c< daEnShell_c > StateID_Slide
Sliding across the ground after being kicked.
int mYoshiKickable
Whether the shell can be kicked in any state by Yoshi.
static sFStateVirtualID_c< daEnShell_c > StateID_WakeupReverse
Waking up after being flipped upside down.
int mJumpPlayerNoCarryHitTimer
For how long the shell will ignore collisions with the carried item.
static sFStateVirtualID_c< daEnShell_c > StateID_Sleep
Remaining stationary after being jumped on.
void createShell(const char *arcName, const char *resPath, const char *modelName, const char *anmTexName, float animFrame)
Loads the resources for the shell model and animation.
virtual void setCarryFall(dActor_c *carryingActor, int collisionDelay)
Callback for when the actor is dropped by the carrying actor.
static sFStateVirtualID_c< daEnShell_c > StateID_WakeupTurn
Turning around after waking up.
bool isSlideTowards(dActor_c *actor)
virtual void setSpinLiftUpActor(dActor_c *carryingActor)
Callback for when the actor is picked up by another actor.
virtual void block_hit_init()
Callback for when a block directly beneath the actor is hit.
bool checkMugenCombo(dActor_c *player)
Checks if the player is performing the staircase infinite jump trick.
The base class for the player and Yoshi.
@ BGC_FOOT
Colliding with the foot sensor.
virtual bool setJump(float jumpSpeed, float speedF, bool allowSteer, int keyMode, int jumpMode)
Starts a jump action with the given parameters.
bool isStatus(int id)
MAIN_STATE_e
The possible operation results.
Definition f_base.hpp:36
@ SUCCESS
The operation was completed successfully.
Definition f_base.hpp:39
ProfileName mProfName
The base's profile name.
Definition f_base.hpp:63
fBaseID_e mUniqueID
The base's unique identifier.
Definition f_base.hpp:61
static fBase_c * searchBaseByID(fBaseID_e id)
Searches for a base with the given ID.
Definition f_manager.cpp:18
A three-dimensional short angle vector.
Definition m_angle.hpp:68
mAng y
The rotation on the Y axis.
Definition m_angle.hpp:126
mAng x
The rotation on the X axis.
Definition m_angle.hpp:125
A two-dimensional floating point vector.
Definition m_vec.hpp:26
A three-dimensional floating point vector.
Definition m_vec.hpp:122
static const T::GlobalData_t mData
const u8 l_Ami_Line[]
The sub-layer for each side of chainlink fences.
Definition d_actor.cpp:38
@ BASE_ID_NULL
Represents the null base.
Definition f_base_id.hpp:7
@ FORWARD_ONCE
Play the animation forward once.
Definition banm.hpp:9
@ GAME_HEAP_DEFAULT
The default game heap (alias of MEM1 or MEM2).
Definition m_heap.hpp:38
EGG::ExpHeap * g_gameHeaps[GAME_HEAP_COUNT]
The game heaps.
Definition m_heap.cpp:13
#define STATE_VIRTUAL_DEFINE(class, name)
Defines a virtual state.
Definition s_State.hpp:46
s16 mAngle
The rotation.
Definition m_angle.hpp:60
u16 mStatus
Status flags for this collider. See CC_STATUS_FLAG_e.
Definition d_cc.hpp:107