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>
20static const float l_slide_throw_speed[] = { 2.5f, -2.5f };
21static const float l_slide_max_speed[] = { 3.0f, -3.0f };
30daEnShell_c::daEnShell_c() : mYoshiKickable(false), mJumpPlayerCarryActorID(
BASE_ID_NULL), mIsMugenCombo(false), mMugenComboSpeed(0.0f) {
32 mEatBehavior = EAT_TYPE_EAT;
33 mFlags = EN_IS_SHELL | EN_IS_HARD;
40daEnShell_c::~daEnShell_c() {
41 for (
int i = 0; i < PLAYER_COUNT; i++) {
42 dAcPy_c *player = daPyMng_c::getPlayer(i);
44 player->cancelCarry(
this);
49void daEnShell_c::createShell(
const char *arcName,
const char *resPath,
const char *modelName,
const char *anmTexName,
float animFrame) {
53 nw4r::g3d::ResMdl mdl = mResFile.GetResMdl(modelName);
54 mModel.create(mdl, &mAllocator, nw4r::g3d::ScnMdl::BUFFER_RESMATMISC | nw4r::g3d::ScnMdl::ANM_TEXPAT);
59 nw4r::g3d::ResAnmChr anim = mResFile.GetResAnmChr(
"revival_shell");
60 mAnim.create(mdl, anim, &mAllocator);
63 if (anmTexName !=
nullptr) {
64 mResAnmTexPat = mResFile.GetResAnmTexPat(anmTexName);
65 mAnimTex.create(mdl, mResAnmTexPat, &mAllocator);
67 mModel.setAnm(mAnimTex);
68 mAnimTex.setFrame(animFrame, 0);
69 mAnimTex.setRate(0.0f, 0);
72 mAllocator.adjustFrmHeap();
75void daEnShell_c::calcShellMdl() {
80 pos = calcCarryPos(mCarryPos);
83 }
else if (mIsCarryFall) {
89 float wakeupShakeYOffset = 0.0f;
91 wakeupShakeYOffset = 16.0f;
102 mMatrix.trans(pos.x, pos.y, pos.z);
105 mMatrix.concat(mMtx_c::createTrans(0.0f, 7.0f, 0.0f));
107 mMatrix.concat(mMtx_c::createTrans(0.0f, -7.0f, 0.0f));
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));
118 mModel.setScale(mBoyoMng.getScale());
121 calcShellEffectPos();
128 setDeathInfo_Hasami();
131 if (!mUseBaseIceBehaviour) {
135 if (mIsCarryFall &&
mBc.isFoot()) {
144 if (actor !=
nullptr) {
155bool daEnShell_c::drawShell() {
160bool daEnShell_c::EtcDamageCheck(
dCc_c *self,
dCc_c *other) {
164 return dEn_c::EtcDamageCheck(self, other);
167void daEnShell_c::Normal_VsEnHitCheck(
dCc_c *self,
dCc_c *other) {
171 other->
mCcData.mVsDamage & (1 << CC_ATTACK_SHELL) &&
172 otherActor->
mProfName != fProfile::EN_HATENA_BALLOON &&
173 hitCallback_Shell(self, other)
175 other->
mInfo |= CC_NO_HIT;
181 hitCallback_Shell(self, other))
183 self->
mInfo |= CC_NO_HIT;
186 float collOffsetX =
mCc.mCollOffsetX[CC_KIND_ENEMY];
188 mDirection == DIR_LR_L && collOffsetX > 0.0f ||
195void daEnShell_c::Normal_VsPlHitCheck(
dCc_c *self,
dCc_c *other) {
196 dAcPy_c *player = (dAcPy_c *) other->
getOwner();
202 if (carry_check(player)) {
204 mCarryPos.set(0.0f, -5.0f, 6.0f);
208 if (!player->isItemKinopio()) {
209 dScoreMng_c *scoreMng;
210 int fumiCount = dEnCombo_c::calcPlFumiCnt(player);
214 scoreMng = dScoreMng_c::m_instance;
215 scoreMng->ScoreSet(
this, fumiCount, player->
getPlrNo());
218 if (actor !=
nullptr) {
230 setKickSlide(self, player);
235 bool fumiInvalid = isFumiInvalid();
241 int fumiRes = Enfumi_check(self, other, x);
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);
251 mPos.x = mMugenComboPosX;
255 }
else if (fumiRes == 3) {
257 dEn_c::Normal_VsPlHitCheck(self, other);
259 setDeathInfo_SpinFumi(player, 1);
261 }
else if (fumiRes == 2 && fumiInvalid) {
262 dEn_c::Normal_VsPlHitCheck(self, other);
265 if (!player->isItemKinopio()) {
266 dScoreMng_c *scoreMng;
267 int fumiCount = dEnCombo_c::calcPlFumiCnt(player);
271 scoreMng = dScoreMng_c::m_instance;
272 scoreMng->ScoreSet(
this, fumiCount, player->
getPlrNo());
275 if (actor !=
nullptr) {
284 setKickSlide(self, player);
288 if (!mIsMugenCombo) {
289 setKickSlide(self, player);
297 dEn_c::Normal_VsPlHitCheck(self, other);
302void daEnShell_c::Normal_VsYoshiHitCheck(
dCc_c *self,
dCc_c *other) {
303 daYoshi_c *yoshi = (daYoshi_c *) other->
getOwner();
305 bool fumiInvalid = isFumiInvalid();
310 int fumiRes = Enfumi_check(self, other, x);
315 setDeathInfo_CarryBgIn(yoshi);
316 }
else if (!specialFumiProc_Yoshi(yoshi)) {
317 setDeathInfo_YoshiFumi(yoshi);
321 dScoreMng_c *scoreMng;
322 int fumiCount = dEnCombo_c::calcPlFumiCnt(yoshi);
326 scoreMng = dScoreMng_c::m_instance;
327 scoreMng->ScoreSet(
this, fumiCount, yoshi->
getPlrNo());
328 setKickSlide(self, yoshi);
332 if (!mIsMugenCombo) {
333 setKickSlide(self, yoshi);
336 dEn_c::Normal_VsYoshiHitCheck(self, other);
341bool daEnShell_c::checkComboClap(
int max) {
348void daEnShell_c::FumiJumpSet(
dActor_c *actor) {
349 if (isFumiInvalid()) {
352 float jumpSpeed = dAcPy_c::msc_JUMP_SPEED + 0.2815f;
354 if (mIsMugenCombo && std::fabs(speedF) < 1.0f) {
357 ((daPlBase_c *) actor)->setJump(jumpSpeed, speedF, 1, 0, 2);
358 dEnemyMng_c::m_instance->m_138 = 1;
361bool daEnShell_c::hitCallback_Shell(
dCc_c *self,
dCc_c *other) {
362 daPlBase_c *shell = (daPlBase_c *) other->
getOwner();
364 int plrNo = acmShellPlayerNo(shell);
365 shellDamageEffect(self, shell);
370 dAudio::g_pSndObjEmy->startSound(SE_EMY_DOWN,
mPos, 0);
380 float speedMult = 1.0f;
386 speedMult * l_base_fall_speed_x[dir],
388 smc_DEADFALL_YSPEED_MAX,
389 smc_DEADFALL_GRAVITY,
400void daEnShell_c::FumiScoreSet(
dActor_c *actor) {
401 if (isFumiInvalid()) {
404 if (mIsMugenCombo && actor->
mSpeed.y > 0.0f) {
407 dEn_c::FumiScoreSet(actor);
411 int plrNo = carryingActor->
getPlrNo();
412 if (plrNo >= 0 && plrNo < PLAYER_COUNT) {
418bool daEnShell_c::setDamage(
dActor_c *actor) {
419 return setPlayerDamage(actor);
422void daEnShell_c::setKickSlide(
dCc_c *self,
dActor_c *other) {
426 setSlideKickSpeed(other);
430 kickEffect(mVec3_c(collX, collY, 5500.0f));
438 if (!
mBc.isFoot() &&
mPos.y >= actor->
mPos.y + 4.0f) {
442 static const float dir[] = { 1.0f, -1.0f };
445 if (
mSpeed.x * dir[idx] >= 0.0f) {
455 if (!ACTOR_PARAM(MugenComboAllowed)) {
461 if (player->
mSpeed.y > 0.0f) {
469 if (dBc_c::checkGround(&playerPos, &height, player->
mLayer, 1, -1) && player->
mPos.y < height + 16.0f) {
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)) {
480 mVec3_c tileSameSide(centerPos.x + l_EnMuki[
mDirection] * 16.0f, centerPos.y, centerPos.z);
482 if (!dBc_c::checkWall(¢erPos, &tileSameSide, &wallX,
mLayer, 1,
nullptr)) {
486 float wallDist = std::fabs(wallX - centerPos.x);
487 float minDist = 8.0f;
488 if (player->mTreadCount < 2) {
491 if (wallDist < minDist || wallDist > 16.0f) {
496 mMugenComboPosX = wallX - 14.0f;
497 mPos.x = wallX - 15.0f;
499 mMugenComboPosX = wallX + 14.0f;
500 mPos.x = wallX + 15.0f;
506bool daEnShell_c::hitCallback_Spin(
dCc_c *self,
dCc_c *other) {
507 if (!isFumiInvalid()) {
510 setDeathSound_HipAttk();
511 hipatkEffect(actor->
mPos);
512 SpinFumiScoreSet(actor);
513 setDeathInfo_SpinFumi(actor, 1);
519bool daEnShell_c::hitCallback_HipAttk(
dCc_c *self,
dCc_c *other) {
520 if (isFumiInvalid()) {
526 setDeathSound_HipAttk();
527 hipatkEffect(actor->
mPos);
528 SpinFumiScoreSet(actor);
534 l_base_fall_speed_x[dir],
536 smc_DEADFALL_YSPEED_MAX,
537 smc_DEADFALL_GRAVITY,
548bool daEnShell_c::hitCallback_YoshiHipAttk(
dCc_c *self,
dCc_c *other) {
549 daYoshi_c *yoshi = (daYoshi_c *) other->
getOwner();
551 if (isFumiInvalid()) {
553 float jumpSpeed = 4.5f;
554 yoshi->
setJump(jumpSpeed, speedF, 1, 0, 2);
555 yoshifumistepSE(yoshi);
558 dEn_c::hitCallback_YoshiHipAttk(self, other);
564bool daEnShell_c::cullCheck() {
573bool daEnShell_c::cullCheck_Shell() {
574 dBgParameter_c *bgParam = dBgParameter_c::ms_Instance_p;
576 float xStart = bgParam->xStart();
577 float yStart = bgParam->yStart();
578 float xEnd = bgParam->xStart() + bgParam->xSize();
579 float yEnd = bgParam->yStart() - bgParam->ySize();
586 if (right < xStart - 160.0f) {
589 if (left > xEnd + 160.0f) {
592 if (top > yStart + 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) {
603 if (bottom < yEnd - offs) {
620 if (isBlockHitDeath()) {
625 hitdamageEffect(efPos);
626 dAudio::g_pSndObjEmy->startSound(SE_EMY_DOWN,
mPos, 0);
636void daEnShell_c::setSlideThrowSpeed(
dActor_c *actor) {
637 float baseSpeed = actor->
mSpeed.x;
638 float speed = l_slide_throw_speed[
mDirection];
640 speed += baseSpeed * 0.35f;
642 mCc.mpFriendActor =
nullptr;
644 dAcPy_c *player = (dAcPy_c *) actor;
646 mCc.mpFriendActor = player;
649 daYoshi_c *yoshi = (daYoshi_c *) actor;
650 if (yoshi->isStar()) {
651 mCc.mpFriendActor = yoshi;
672 mSpeed.set(speed, 0.2f, 0.0f);
675void daEnShell_c::setSlideKickSpeed(
dActor_c *actor) {
676 float baseSpeed = actor->
mSpeed.x;
677 float speed = l_slide_throw_speed[
mDirection];
679 speed += baseSpeed * 0.5f;
684void daEnShell_c::slideSpin() {
685 float tmp = std::fabs(
mSpeed.x) / 2.5f;
686 s16 angle = tmp * GLOBAL_DATA.mSpinSpeed;
693void daEnShell_c::kickSE(
int plrNo) {
694 if (plrNo >= 0 && plrNo < PLAYER_COUNT) {
695 dAudio::SoundEffectID_t se(SE_EMY_KAME_KERU);
700void daEnShell_c::setDeathInfo_CarryBgIn(
dActor_c *actor) {
731 if ((unit1 & 0x1001d) && !(unit2 & 0x1001d)) {
735 if (!smth &&
mBc.checkWallEnm(
nullptr)) {
740 setSlideThrowSpeed(actor);
746 static const float cs_slip_offset[] = { 8.0f, -8.0f };
754bool daEnShell_c::hitCallback_Ice(
dCc_c *self,
dCc_c *other) {
760 mBoyoMng.mDirection = DIR_LR_R;
762 mBoyoMng.mDirection = DIR_LR_L;
764 for (
int i = 0; i < PLAYER_COUNT; i++) {
765 dAcPy_c *player = daPyMng_c::getPlayer(i);
767 player->cancelCarry(
this);
771 if (!mUseBaseIceBehaviour) {
775 dEn_c::hitCallback_Ice(self, other);
780void daEnShell_c::returnState_Ice() {
781 if (!mUseBaseIceBehaviour) {
783 mSpeed.set(0.0f, 0.0f, 0.0f);
786 dEn_c::returnState_Ice();
790void daEnShell_c::adjustCarryCc() {
791 const static float cs_check_ofs[] = { -8.0f, 8.0f };
795 mVec3_c pos2(pos.x + l_EnMuki[dir] * 16.0f, pos.y, pos.z);
797 mCc.mCcData.mBase.mOffset.set(mCcOffset.x, mCcOffset.y);
798 mCc.mCcData.mBase.mSize.set(mCcSize.x, mCcSize.y);
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);
805 mCc.mCcData.mBase.mOffset.set(offsX -
mPos.x, 8.0f);
806 mCc.mCcData.mBase.mSize.set(sizeX, 8.0f);
810bool daEnShell_c::checkSleep() {
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);
828 mWakeupShakeAngle3D.x = 0;
829 mWakeupShakeAngle3D.z = 0;
837 s16 plrNo = carryingActor->
getPlrNo();
840 mCarryPos.set(0.0f, 0.0f, 0.0f);
844bool daEnShell_c::hasamiCheck() {
866void daEnShell_c::setDeathInfo_Hasami() {
869 hitdamageEffect(efPos);
871 dAudio::g_pSndObjEmy->startSound(SE_EMY_DOWN,
mPos, 0);
873 l_base_fall_speed_x[dir],
875 smc_DEADFALL_YSPEED_MAX,
876 smc_DEADFALL_GRAVITY,
885void daEnShell_c::initializeState_Sleep() {
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;
898void daEnShell_c::finalizeState_Sleep() {
899 mCc.mCcData.mVsDamage &= ~(1 << CC_ATTACK_SPIN_LIFT_UP);
904void daEnShell_c::executeState_Sleep() {
923 u32 bgCheckRes = EnBgCheck();
924 if (bgCheckRes & 1) {
925 Bound(0.1875f, 0.5f, 0.5f);
927 if (bgCheckRes & 2) {
930 if (bgCheckRes & 4) {
943void daEnShell_c::initializeState_Carry() {
945 dAcPy_c *player = daPyMng_c::getPlayer(
mPlayerNo);
946 if (player->mAmiLayer == 1) {
953 float x =
mCc.mCcData.mBase.mOffset.x;
954 float y =
mCc.mCcData.mBase.mOffset.y;
956 float w =
mCc.mCcData.mBase.mSize.x;
957 float h =
mCc.mCcData.mBase.mSize.y;
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);
963 mCc.mCcData.mVsKind |= (1 << CC_KIND_KILLER);
964 mCc.mCcData.mAttack = CC_ATTACK_SHELL;
965 mRc.setRide(
nullptr);
969 mUseBaseIceBehaviour = 0;
970 mWakeupShakeAngle = 0;
971 mWakeupShakeAngle3D.x = 0;
972 mWakeupShakeAngle3D.y = 0;
973 mWakeupShakeAngle3D.z = 0;
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);
988 if (
mPos.z >= 0.0f) {
995void daEnShell_c::executeState_Carry() {
996 dAcPy_c *player = daPyMng_c::getPlayer(mCarriedBy);
1001 setDeathInfo_CarryBgIn(player);
1007 setSlideThrowSpeed(player);
1013 }
else if (checkSleep()) {
1016 setDeathInfo_CarryBgIn(player);
1028void daEnShell_c::initializeState_Slide() {
1029 mSensorFootSlide.mBase.mFlags = 1;
1030 mSensorFootSlide.mLineA = -0x3000;
1031 mSensorFootSlide.mLineB = 0x2000;
1032 mSensorFootSlide.mDistanceFromCenter = 0;
1035 dAcPy_c *player = daPyMng_c::getPlayer(
mPlayerNo);
1041 if (mIsMugenCombo) {
1042 mMugenComboSpeed = 0.0f;
1043 if (player->mPowerup == POWERUP_NONE) {
1049 mFumiProc.refresh(
new MugenComboFumiCheck_c());
1050 }
else if (!player->
mBc.isFoot()) {
1056 mSensorHead.mBase.mFlags |= 0xc0000;
1057 mSensorFootNormal.mBase.mFlags |= 0xc0000;
1058 mSensorWall.mBase.mFlags |= 0xc0000;
1059 mSensorFootSlide.mBase.mFlags |= 0xc0000;
1062 mSlideAirAfterThrow = 0;
1063 if (*
mStateMgr.getOldStateID() == StateID_Carry) {
1064 mSlideAirAfterThrow = 1;
1067 mCc.mCcData.mVsKind |= (1 << CC_KIND_BALLOON) | (1 << CC_KIND_ITEM) | (1 << CC_KIND_KILLER);
1068 mCc.mCcData.mAttack = CC_ATTACK_SHELL;
1070 mUseBaseIceBehaviour = 0;
1075 mSensorHead.mBase.mFlags |= 0x900000;
1076 mSensorWall.mBase.mFlags |= 0x900000;
1078 mSensorHead.mBase.mFlags |= 0x400;
1079 mSensorWall.mBase.mFlags |= 0x400;
1081 mBc.set(
this, mSensorFootSlide, mSensorHead, mSensorWall);
1084 mWakeupShakeAngle = 0;
1085 mWakeupShakeAngle3D.x = 0;
1086 mWakeupShakeAngle3D.y = 0;
1087 mWakeupShakeAngle3D.z = 0;
1095void daEnShell_c::finalizeState_Slide() {
1096 if (mIsMugenCombo) {
1097 static const float speeds[] = { 0.375f, -0.375f };
1099 mFumiProc.refresh(
new NonUniqueFumiCheck_c());
1104 mCc.mCcData.mVsKind &= ~((1 << CC_KIND_BALLOON) | (1 << CC_KIND_ITEM) | (1 << CC_KIND_KILLER));
1105 mCc.mCcData.mAttack = CC_ATTACK_NONE;
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;
1117void daEnShell_c::executeState_Slide() {
1125 mSensorHead.mBase.mFlags &= ~0x400;
1126 mSensorWall.mBase.mFlags &= ~0x400;
1130 mBc.checkHead(
mBc.mFlags);
1131 if (mIsMugenCombo) {
1133 mMugenComboSpeed += std::fabs(
mSpeed.x);
1134 if (std::fabs(mMugenComboSpeed) > max) {
1140 dAcPy_c *player = daPyMng_c::getPlayer(
mPlayerNo);
1152 mSlideAirAfterThrow = 0;
1153 mCc.mpFriendActor =
nullptr;
1154 if (
mBc.getFootAttr() == 3) {
1159 if (mSlideAirAfterThrow) {
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) {
1181 dAudio::g_pSndObjEmy->startSound(SE_OBJ_KOURA,
getCenterPos(), 0);
1185void daEnShell_c::initializeState_Wakeup() {
1189 mSpeed.set(0.0f, 0.0f, 0.0f);
1193void daEnShell_c::finalizeState_Wakeup() {}
1195void daEnShell_c::executeState_Wakeup() {
1198 u32 bgCheckRes = EnBgCheck();
1199 if (bgCheckRes & 1) {
1202 if (bgCheckRes & 4) {
1208void daEnShell_c::initializeState_WakeupTurn() {
1212void daEnShell_c::finalizeState_WakeupTurn() {}
1214void daEnShell_c::executeState_WakeupTurn() {
1217 u32 bgCheckRes = EnBgCheck();
1218 if (bgCheckRes & 1) {
1221 if (bgCheckRes & 4) {
1225 setAfterSleepState();
1229void daEnShell_c::initializeState_WakeupReverse() {
1230 mSpeed.set(0.0f, 3.0f, 0.0f);
1233void daEnShell_c::finalizeState_WakeupReverse() {}
1235void daEnShell_c::executeState_WakeupReverse() {
1239 u32 bgCheckRes = EnBgCheck();
1240 if (bgCheckRes & 1) {
1243 if (bgCheckRes & 4) {
1251void daEnShell_c::initializeState_DieFall() {
1253 mUseBaseIceBehaviour = 0;
1256 dEn_c::initializeState_DieFall();
1259void daEnShell_c::finalizeState_DieFall() {
1260 dEn_c::finalizeState_DieFall();
1263void daEnShell_c::executeState_DieFall() {
1264 const static s16 cs_spin_speed[] = { 0x400, -0x400 };
1267 spinX = smc_DEADFALL_SPINSPEED;
1270 spinX = -smc_DEADFALL_SPINSPEED;
1274 spinX *= smc_WATER_ROLL_DEC_RATE;
1275 spinY *= smc_WATER_ROLL_DEC_RATE;
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.
void deleteActor(u8 deleteForever)
Deletes the actor and optionally disables respawn.
void slideComboSE(int multiplier, bool shortCombo)
Plays the combo kill sound effect.
@ CARRY_RELEASE
The actor is being released from carry.
@ CARRY_THROW
The actor is being actively thrown by the player.
virtual s8 & getPlrNo()
Gets the player number associated with the actor. See mPlayerNo.
bool mNoRespawn
Whether the actor should not respawn after being deleted.
virtual void reviveCc()
Enables the actor's collision.
dBc_c mBc
The actor-to-tile collision sensor.
static bool getTrgToSrcDir_Main(float trgX, float srcX)
See getTrgToSrcDirFunc.
static void setSoftLight_Enemy(m3d::bmdl_c &mdl)
Sets the soft light effect for enemies.
void clrComboCnt()
Clears the actor's combo counter.
u32 mCarryingFlags
The actor's carry actions. See CARRY_ACTION_e.
u8 mKind
The actor's kind. Value is a STAGE_ACTOR_KIND_e.
u8 mEatState
The actor's eat state. Value is a EAT_STATE_e.
static void changePosAngle(mVec3_c *pos, mAng3_c *ang, int param3)
Adjusts the actor's position to account for looping stages.
u8 mAmiLayer
The actor's layer for chainlink fences.
u8 mDirection
The actor's facing direction.
dCc_c mCc
The actor-to-actor collision sensor.
virtual bool ActorDrawCullCheck()
Checks if the actor is out of view.
mVec2_c mVisibleAreaSize
The size of the area inside which the actor is visible.
virtual void removeCc()
Disables the actor's collision.
u8 mThrowDirection
The actor's direction when thrown or dropped after carrying.
int mComboMultiplier
The current combo multiplier obtained by the actor by colliding with other actors.
s8 mPlayerNo
The player associated with the actor, -1 if not associated to any player.
bool ActorScrOutCheck(u16 flags)
Checks if the actor is out of gameplay and optionally deletes it.
@ EAT_STATE_NONE
The actor is not being eaten.
dActor_c()
Constructs a new actor.
@ COLL_FOOT
The actor collided with the ground.
@ COLL_HEAD
The actor collided with a ceiling.
@ COLL_WALL_L
The actor collided with a wall on its left.
@ COLL_WALL_R
The actor collided with a wall on its right.
@ COLL_NONE
The actor did not collide with any surface.
dRc_c mRc
The actor's ride surface manager.
virtual void setAfterEatScale()
Restores the actor's scale once spat out.
@ STAGE_ACTOR_YOSHI
The Yoshi actor.
@ STAGE_ACTOR_PLAYER
The player actor.
virtual void calcSpitOutPos(dActor_c *eatingActor)
Calculates the position where the actor will be spat out.
u8 mLayer
The actor's layer.
u8 mBgCollFlags
The collision directions that the actor collided with in the previous frame. Value is a BG_COLL_FLAG_...
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.
dActor_c * mpOwner
The actor this collider belongs to.
u8 mInfo
Info flags for this collider. See CC_INFO_e.
mVec2_c mCollPos
The position where the last collision occurred.
dActor_c * getOwner() const
Gets the owner actor of this collider.
sCcDatNewF mCcData
The collision data of this collider.
u8 mAmiLine
The non-collide mask for this collider.
dActor_c * mpFriendActor
A second actor that this collider will not collide with.
bool getPl_LRflag(const mVec3_c &pos)
Checks whether the nearest player is to the left of pos.
u8 mDeathFallDirection
The X direction to move towards on death.
u8 mIceDeathDirection
The X direction to move towards on ice death.
void WaterCheck(mVec3_c &pos, float h)
dDeathInfo_c mDeathInfo
The parameters for the death animation.
dIceMng_c mIceMng
The ice manager for this enemy.
dEnCombo_c mCombo
The enemy combo manager.
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.
virtual void block_hit_init()
Callback for when a block directly beneath the actor is hit.
dPlayerDownTimer_c mNoHitPlayer
Hit cooldown timers for each player. This is used to prevent, for example, a thrown shell from hittin...
virtual void postExecute(fBase_c::MAIN_STATE_e status)
post method for the execute operation.
virtual void setEatTongue(dActor_c *)
Callback for when the actor is targeted by Yoshi's tongue.
bool mInLiquid
Whether the enemy is in a liquid.
virtual bool checkComboClap(int max)
static dResMng_c * m_instance
The instance of this class.
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.
MAIN_STATE_e
The possible operation results.
@ SUCCESS
The operation was completed successfully.
ProfileName mProfName
The base's profile name.
fBaseID_e mUniqueID
The base's unique identifier.
static fBase_c * searchBaseByID(fBaseID_e id)
Searches for a base with the given ID.
A three-dimensional short angle vector.
mAng y
The rotation on the Y axis.
mAng x
The rotation on the X axis.
A two-dimensional floating point vector.
A three-dimensional floating point vector.
static const T::GlobalData_t mData
const u8 l_Ami_Line[]
The sub-layer for each side of chainlink fences.
@ BASE_ID_NULL
Represents the null base.
@ FORWARD_ONCE
Play the animation forward once.
@ GAME_HEAP_DEFAULT
The default game heap (alias of MEM1 or MEM2).
EGG::ExpHeap * g_gameHeaps[GAME_HEAP_COUNT]
The game heaps.
#define STATE_VIRTUAL_DEFINE(class, name)
Defines a virtual state.
u16 mStatus
Status flags for this collider. See CC_STATUS_FLAG_e.