NSMBW-Decomp
A decompilation of New Super Mario Bros. Wii
Loading...
Searching...
No Matches
d_a_player_base.cpp
1#include <game/bases/d_a_player_base.hpp>
2#include <game/bases/d_a_player_demo_manager.hpp>
3#include <game/bases/d_a_player_manager.hpp>
4#include <game/bases/d_bg.hpp>
5#include <game/bases/d_bg_parameter.hpp>
6#include <game/bases/d_cd.hpp>
7#include <game/bases/d_game_com.hpp>
8#include <game/bases/d_game_key.hpp>
9#include <game/bases/d_info.hpp>
10#include <game/bases/d_next.hpp>
11#include <game/bases/d_s_stage.hpp>
12#include <game/bases/d_stage_timer.hpp>
13#include <game/bases/d_score_manager.hpp>
14#include <game/bases/d_attention.hpp>
15#include <game/bases/d_mask_manager.hpp>
16#include <game/bases/d_multi_manager.hpp>
17#include <game/bases/d_quake.hpp>
18#include <game/bases/d_rail.hpp>
19#include <game/bases/d_remocon_manager.hpp>
20#include <game/mLib/m_fader.hpp>
21#include <game/cLib/c_math.hpp>
22#include <game/sLib/s_lib.hpp>
24
25const float daPlBase_c::sc_DirSpeed[] = { 1.0f, -1.0f };
26const float daPlBase_c::sc_JumpSpeed = 3.628f;
27const float daPlBase_c::sc_JumpSpeedNuma1 = 3.5f;
28const float daPlBase_c::sc_JumpSpeedNuma2 = 2.3f;
29const float daPlBase_c::sc_WaterWalkSpeed = 0.5625f;
30const float daPlBase_c::sc_WaterSwimSpeed = 1.125f;
31const float daPlBase_c::sc_WaterJumpSpeed = 1.25f;
32const float daPlBase_c::sc_WaterMaxFallSpeed = -3.0f;
33const float daPlBase_c::sc_MaxFallSpeed = -4.0f;
34const float daPlBase_c::sc_MaxFallSpeed_Foot = -2.0f;
35const float daPlBase_c::sc_MaxFallDownSpeed = -8.5f;
36const float daPlBase_c::scTurnPowerUpRate = 3.0f;
37
38namespace {
39 const float l_sakaMaxSpeedRatio[][3] = {
40 { 1.0f, 1.0f, 1.0f },
41 { 1.25f, 0.6875f, 1.0f },
42 { 1.25f, 0.6875f, 1.0f },
43 { 1.44f, 0.5f, 1.0f },
44 { 1.62f, 0.3f, 1.0f },
45 };
46 const float l_sakaStopAccele[][3] = {
47 { 0.035f, 0.035f, 0.035f },
48 { 0.0315f, 0.046f, 0.035f },
49 { 0.028f, 0.06f, 0.035f },
50 { 0.021f, 0.123f, 0.035f },
51 { 0.014f, 0.175f, 0.035f },
52 };
53 const float l_sakaMoveAccele[][3] = {
54 { 0.1f, 0.03f, 0.03f },
55 { 0.04f, 0.03f, 0.03f },
56 { 0.05f, 0.045f, 0.03f },
57 { 0.07f, 0.12f, 0.03f },
58 { 0.17f, 0.17, 0.03f },
59 };
60 const float l_sakaSlipOffSpeed[][3] = {
61 { 0.0f, 0.0f, 0.0f },
62 { 0.0f, 0.0f, 0.0f },
63 { 0.2f, -0.2f, 0.0f },
64 { 0.4f, -0.4f, 0.0f },
65 { 0.4f, -0.4f, 0.0f },
66 };
67}
68
69daPlBase_c::daPlBase_c() :
70 mpMdlMng(nullptr),
71 mDemoStateMgr(*this, sStateID::null),
72 mStateMgr(*this, sStateID::null)
73{
74 mAreaNo = dScStage_c::m_instance->mCurrAreaNo;
75 mLayer = dScStage_c::m_instance->mCurrLayer;
76 mAmiLayer = 1;
77 mBc.mOwningPlrNo = mPlayerNo;
78 changeDemoState(StateID_DemoNone, false);
79 changeState(StateID_None);
80 mAttentionMode = 3;
81 mViewLimitPadding = 16.0f;
82 mEatBehavior = EAT_TYPE_NONE;
83}
84
85daPlBase_c::~daPlBase_c() {
86 releaseCcData();
87 mpMdlMng = nullptr;
88}
89
91 mKey.init();
92 if (dScStage_c::m_gameMode == dInfo_c::GAME_MODE_TITLE) {
93 mKey.onStatus(dAcPyKey_c::STATUS_FORCE_RIGHT);
94 }
95 setZPosition();
96 return SUCCEEDED;
97}
98
102 return NOT_READY;
103 }
105 return NOT_READY;
106 }
108 if (isNowBgCross(BGC_LIFT)) {
109 mLastPos = mLiftRelatedPos;
110 }
111 mBgPressFlags = 0;
112 offStatus(STATUS_84);
113 offStatus(STATUS_B7);
116 if (isStatus(STATUS_83)) {
117 onStatus(STATUS_82);
118 offStatus(STATUS_83);
119 }
120 return SUCCEEDED;
121}
122
124 updateEndingDance();
126 mKey.onStatus(dAcPyKey_c::STATUS_NO_INPUT);
127 }
128 mKey.update();
129 setZPosition();
130 releaseCcData();
131 executeMain();
132 mKey.updateEnd();
133 mSndObj.calculate(dAudio::cvtSndObjctPos(getCenterPos()));
134 return SUCCEEDED;
135}
136
138 if (status == SUCCESS) {
139 mLastPosDelta = mLastPos - mPos;
140 mLiftRelatedPos = mPos;
143 offStatus(STATUS_BE);
144 offStatus(STATUS_RIDE_NUT);
145 offStatus(STATUS_62);
146 offStatus(STATUS_5B);
147 offStatus(STATUS_5C);
148 offStatus(STATUS_89);
153 offStatus(STATUS_82);
154 if (isStatus(STATUS_8D)) {
158 }
159 }
161 if (isStatus(STATUS_TWIRL)) {
164 }
165 offStatus(STATUS_A4);
166 clearFollowMameKuribo();
167 clearCcPlayerRev();
168 clearCcData();
169 }
170 dActor_c::postExecute(status);
171}
172
174 mIsBeingDeleted = true;
176 mStateMgr.finalizeState();
177 return SUCCEEDED;
178}
179
182 mVisible = false;
183 } else {
184 mVisible = true;
185 }
187 return NOT_READY;
188 }
189 return SUCCEEDED;
190}
191
193 return SUCCEEDED;
194}
195
208STATE_VIRTUAL_DEFINE(daPlBase_c, PlayerJumpDai);
214
215void daPlBase_c::changeState(const sStateIDIf_c &stateID, void *arg) {
217 return;
218 }
219 clearComboCount();
220 mSubstate = 0;
221 mSubstateTimer = 0;
222 mSubstateValue = 0;
223 offStatus(STATUS_97);
224 offStatus(STATUS_98);
225 mStateArg = arg;
226 mStateMgr.changeState(stateID);
227}
228
229void daPlBase_c::executeState() {
230 if (mSubstateTimer != 0) {
232 }
233 mStateMgr.executeState();
234}
235
236short daPlBase_c::getMukiAngle(u8 direction) {
237 static const short scMukiAngle[] = { 0x3000, -0x3000 };
238 return scMukiAngle[direction];
239}
240
241int daPlBase_c::turnAngle() {
242 return mAngle.y.chase(getMukiAngle(mDirection), 0x2000);
243}
244
245int daPlBase_c::addCalcAngleY(short p1, short p2) {
246 return sLib::addCalcAngle(&mAngle.y.mAngle, p1, p2, 0x2000, 0x400);
247}
248
249short daPlBase_c::getBesideMukiAngle(u8 direction) {
250 static const short scMukiAngle[] = { 0x4000, -0x4000 };
251 return scMukiAngle[direction];
252}
253
254void daPlBase_c::turnBesideAngle() {
255 mAngle.y.chase(getBesideMukiAngle(mDirection), 0x2000);
256}
257
258bool daPlBase_c::checkRideActor(daPlBase_c *other) {
259 if (mRideActorID == other->mUniqueID || other->mRideActorID == mUniqueID) {
260 return true;
261 }
262 return false;
263}
264
265void daPlBase_c::initializeState_None() {}
266void daPlBase_c::finalizeState_None() {}
267void daPlBase_c::executeState_None() {}
268
269void daPlBase_c::setWaitActionAnm(AnmBlend_e blendMode) {}
270void daPlBase_c::setWalkActionAnm(AnmBlend_e blendMode) {}
271
272void daPlBase_c::walkActionInit_Wait(AnmBlend_e blendMode) {}
273void daPlBase_c::walkAction_Wait() {}
274
275void daPlBase_c::walkActionInit_Move(AnmBlend_e blendMode) {}
276void daPlBase_c::walkAction_Move() {
277 AnmBlend_e blendMode = BLEND_DEFAULT;
278 if (!mSpeedF) {
279 if (isNowBgCross(BGC_11) || mTimer_f4 != 0 || mWindSpeed) {
280 if (mKey.buttonWalk(nullptr)) {
281 blendMode = BLEND_NONE;
282 } else {
283 walkActionInit_Wait(BLEND_DEFAULT);
284 return;
285 }
286 } else {
287 if (isNowBgCross(BGC_WALL)) {
288 if (mPowerup == POWERUP_MINI_MUSHROOM && mBc.getSakaUpDown(mDirection) == 1) {
289 blendMode = BLEND_NONE;
290 } else {
291 walkActionInit_Wait(BLEND_DEFAULT);
292 return;
293 }
294 }
295 if (isNowBgCross(BGC_SLOPE_AND_HEAD) || !mKey.buttonWalk(nullptr)) {
296 walkActionInit_Wait(BLEND_DEFAULT);
297 return;
298 }
299 }
300 } else if (isNowBgCross(BGC_LIFT)) {
301 mTimer_f4 = 3;
302 }
303 setWalkActionAnm(blendMode);
304 setRunFootEffect();
305}
306
307void daPlBase_c::initializeState_Walk() {}
308
309void daPlBase_c::finalizeState_Walk() {
310 offStatus(STATUS_52);
311}
312
313void daPlBase_c::executeState_Walk() {
314 if (isStatus(STATUS_52)) {
315 offStatus(STATUS_52);
316 }
317}
318
320 /// @unofficial
321 static const float csSpeedMult[] = { 0.5f, 0.8f };
322 /// @unofficial
323 static const float csSpeedMultNoMove[] = { 0.3f, 1.0f };
324 if (
325 mPowerup != POWERUP_PENGUIN_SUIT &&
326 isNowBgCross(BGC_LIFT) &&
327 isNowBgCross(BGC_ON_ICE) &&
328 std::fabs(mBc.mIceSpeed) > 1.0f
329 ) {
330 u8 idx = 0;
331 if (mBc.mIceSpeed < 0.0f) {
332 idx = 1;
333 }
334 if (mKey.buttonWalk(nullptr)) {
335 mSpeedF *= csSpeedMult[idx];
336 } else {
337 mSpeedF *= csSpeedMultNoMove[idx];
338 }
339
340 float newSpeedF = std::fabs(mSpeedF);
341 if (newSpeedF < 0.3f) {
342 newSpeedF = 0.3f;
343 } else if (newSpeedF > 1.5f) {
344 newSpeedF = 1.5f;
345 }
346
347 if (mSpeedF < 0.0f) {
348 mSpeedF = -newSpeedF;
349 } else {
350 mSpeedF = newSpeedF;
351 }
352 }
353}
354
355void daPlBase_c::calcAccOnIceLift() {
356 if (
357 isNowBgCross(BGC_LIFT) &&
358 isNowBgCross(BGC_ON_ICE) &&
359 !mKey.buttonWalk(nullptr) &&
360 std::fabs(mBc.mIceSpeed) > 1.0f
361 ) {
362 mAccelF = calcSomeAccel(mAccelF);
363 }
364}
365
366void daPlBase_c::initializeState_Jump() {
367 onStatus(STATUS_A0);
369 offStatus(STATUS_88);
370 if (mJumpDaiFallTimer != 0) {
372 }
373}
374void daPlBase_c::finalizeState_Jump() {
375 mAngle.x = 0;
376 if (isStatus(STATUS_A5)) {
377 mSndObj.stopPlyJumpSound();
378 }
380 offStatus(STATUS_88);
382 offStatus(STATUS_AB);
383 offStatus(STATUS_A0);
386 mKey.offStatus(dAcPyKey_c::STATUS_FORCE_JUMP);
387 mKey.offStatus(dAcPyKey_c::STATUS_FORCE_NO_JUMP);
388 mKey.offStatus(dAcPyKey_c::STATUS_DISABLE_LR);
389}
390void daPlBase_c::executeState_Jump() {
391 if (mJumpDaiFallTimer == 0) {
393 }
394 if (isStatus(STATUS_A5)) {
395 if (!mKey.buttonJump() || isNowBgCross(BGC_HEAD)) {
396 mSndObj.stopPlyJumpSound();
398 }
399 if (mSpeed.y <= 1.0f) {
401 }
402 }
404}
405
406bool daPlBase_c::setCrouchJump() {
407 if (mKey.triggerJump()) {
409 return true;
410 }
411 return false;
412}
413
414void daPlBase_c::initializeState_SitJump() {}
415void daPlBase_c::finalizeState_SitJump() {}
416void daPlBase_c::executeState_SitJump() {}
417
418void daPlBase_c::setFallAction() {
419 if (isNowBgCross(BGC_FOOT)) {
420 return;
421 }
423}
424
425void daPlBase_c::initializeState_Fall() {
426 onStatus(STATUS_A0);
427 if (mJumpDaiFallTimer != 0) {
429 }
430 if (!stateArg<bool>()) {
431 mpMdlMng->setAnm(PLAYER_ANIM_JUMP2, 10.0f, 0.0f);
432 }
433 if (isOldBgCross(BGC_LIFT)) {
434 if (m_1134 * mSpeedF > 0.0f) {
435 m_1138 = m_1134;
436 m_1134 = 0.0f;
437 m_113c = std::fabs(m_1138 / 10.0f);
438 }
439 }
440}
441void daPlBase_c::finalizeState_Fall() {
442 offStatus(STATUS_A0);
443 offStatus(STATUS_88);
446}
447void daPlBase_c::executeState_Fall() {
448 if (mJumpDaiFallTimer == 0) {
450 }
451}
452
453void daPlBase_c::initializeState_Land() {}
454void daPlBase_c::finalizeState_Land() {}
455void daPlBase_c::executeState_Land() {}
456
457bool daPlBase_c::checkCrouch() {
458 return false;
459}
460
461bool daPlBase_c::setCancelCrouch() {
462 if (checkStandUpRoofOnLift()) {
463 return false;
464 }
465 if (mpMdlMng->getAnm() != PLAYER_ANIM_STOOP_START) {
466 mpMdlMng->setAnm(PLAYER_ANIM_STOOP_START);
467 mpMdlMng->mpMdl->setFrame(mpMdlMng->getLastFrame());
468 }
469 if (!isNowBgCross(BGC_WATER_SHALLOW)) {
470 mpMdlMng->mpMdl->setRate(-1.0f);
471 } else {
472 mpMdlMng->mpMdl->setRate(-dPyMdlBase_c::scWaterCrouchAnmSpeed);
473 }
474 onStatus(STATUS_52);
476 return true;
477}
478
479bool daPlBase_c::checkStandUpRoofOnLift() {
480 if (isNowBgCross(BGC_FOOT) && !isNowBgCross(BGC_LIFT)) {
481 return false;
482 }
483 return checkStandUpRoof();
484}
485
486bool daPlBase_c::checkStandUpRoof() {
487 const sBcPointData *headBgP = getHeadBgPointData();
488 if (headBgP == nullptr) {
489 return false;
490 }
491 float standHeadBgY = getStandHeadBgPointY();
492 float tmpCalc = mPos.y + standHeadBgY - 1.0f;
493 mVec3_c p = mVec3_c(
494 mPos.x + headBgP->mInfMargin / 4096.0f,
495 mPos.y + 4.0f,
496 mPos.z
497 );
498 float res;
499 if (dBc_c::checkTenjou(&p, &res, mLayer, mAmiLayer) && res < tmpCalc) {
500 return true;
501 }
502 p.x = mPos.x + headBgP->mSupMargin / 4096.0f;
503 if (dBc_c::checkTenjou(&p, &res, mLayer, mAmiLayer) && res < tmpCalc) {
504 return true;
505 }
506 return false;
507}
508
509void daPlBase_c::initializeState_Crouch() {}
510void daPlBase_c::finalizeState_Crouch() {}
511void daPlBase_c::executeState_Crouch() {}
512
513void daPlBase_c::initializeState_Slip() {
514 mSubstate = SLIP_ACTION_NONE;
515 mpMdlMng->setAnm(PLAYER_ANIM_SLIP);
516 mMaxSpeedF = getSlipMaxSpeedF();
517 mSubstateTimer = 8;
518 mAutoSlipTimer = 0;
520 onStatus(STATUS_97);
521}
522void daPlBase_c::finalizeState_Slip() {
524 offStatus(STATUS_97);
525 mAngle.x = 0;
526}
527void daPlBase_c::executeState_Slip() {
528 gravitySet();
529 maxFallSpeedSet();
530 moveSpeedSet();
531 powerSet();
532 sLib::calcTimer(&mAutoSlipTimer);
533 mAng ang = 0;
534 if (isNowBgCross(BGC_FOOT)) {
535 ang = mBc.getSakaAngle(mDirection) * 0.3f;
536 }
537 sLib::addCalcAngle(&mAngle.x.mAngle, ang.mAngle, 4, 0x2000, 0x100);
538 int angle = turnAngle();
539 if (isNowBgCross(BGC_AUTOSLIP)) {
540 mAutoSlipTimer = 9;
541 } else if (checkJumpTrigger()) {
542 return;
543 } else if (angle && mAutoSlipTimer == 0 && checkSlipEndKey()) {
544 changeActionSlipEnd(BLEND_NONE);
545 return;
546 }
547 switch ((SlipSubstate_e) mSubstate) {
548 case SLIP_ACTION_NONE:
549 if (!isNowBgCross(BGC_FOOT) && (mKey.triggerJump() || mKey.triggerCross())) {
551 } else {
552 slipActionMove(angle);
553 }
554 break;
555 case SLIP_ACTION_STOOP:
556 mMaxSpeedF = 0.0f;
557 if (mpMdlMng->mpMdl->mAnm.isStop()) {
559 }
560 break;
561 case SLIP_ACTION_END:
562 if (mpMdlMng->mpMdl->mAnm.isStop()) {
563 changeActionSlipEnd(BLEND_DEFAULT);
564 }
565 default:
566 break;
567 }
568}
569
570void daPlBase_c::setSlipAction_ToStoop() {
571 if (checkStandUpRoofOnLift()) {
572 return;
573 }
577 }
578 mSubstate = SLIP_ACTION_STOOP;
579 mpMdlMng->setAnm(PLAYER_ANIM_SLIP_TO_STOOP);
580}
581
582void daPlBase_c::setSlipAction_ToEnd() {
583 if (checkStandUpRoofOnLift()) {
584 return;
585 }
589 }
590 mSubstate = SLIP_ACTION_END;
591 mSpeedF = 0.0f;
592 mMaxSpeedF = 0.0f;
593 mpMdlMng->setAnm(PLAYER_ANIM_SLIPED);
594}
595
596void daPlBase_c::setSlipActionEnd() {
598 if (!mKey.buttonCrouch()) {
599 setSlipAction_ToEnd();
600 }
601}
602
603void daPlBase_c::setSlipActionViewLimitEnd() {
605 if (!mKey.buttonCrouch()) {
606 setSlipAction_ToEnd();
607 } else if (dScStage_c::m_instance->mCurrWorld == WORLD_1 && dScStage_c::m_instance->mCurrCourse == STAGE_6 && dScStage_c::m_instance->mCurrFile == 1) {
608 if (isNowBgCross(BGC_LIFT)) {
609 setSlipAction_ToEnd();
610 }
611 }
612}
613
614void daPlBase_c::slipActionMove(int param) {
616 if (mSpeedF) {
617 if (mPowerup != POWERUP_PENGUIN_SUIT) {
618 setCcAtSlip();
619 } else {
620 setCcAtPenguinSlip();
621 }
622 }
623 if (isOldBgCross(BGC_FOOT) && mPrevMoveSakaAngle > 0 && mStillSakaAngle * mPrevStillSakaAngle <= 0) {
624 offNowBgCross(BGC_FOOT);
625 float baseSpeed = mSpeedF;
626 float cos = mAng(mPrevMoveSakaAngle).cos();
627 mMaxSpeedF = baseSpeed;
628 mSpeedF = baseSpeed * cos;
629 mSpeed.y = std::fabs(baseSpeed) * mAng(mPrevMoveSakaAngle).sin();
630 }
631 if (isNowBgCross(BGC_FOOT)) {
632 if (mSpeedF <= 0.0f && isNowBgCross(BGC_SIDE_LIMIT_L)) {
633 setSlipActionViewLimitEnd();
634 } else if (checkSakaReverse()) {
635 setSlipActionEnd();
636 } else if (isNowBgCross(BGC_SLOPE)) {
637 mSlipEndTimer = 3;
638 mSubstateTimer = 8;
639 mMaxSpeedF = getSlipMaxSpeedF();
640 if (!mBc.getSakaUpDown(mDirection)) {
641 if (param == 0) {
642 mAccelF = 0.5f * mAccelF;
643 }
644 if (std::fabs(mSpeedF) < 1.0f &&
645 ((mCc.getXOffset(0) < 0.0f && mSpeedF >= 0.0f) ||
646 (mCc.getXOffset(0) > 0.0f && mSpeedF <= 0.0f)))
647 {
648 setSlipActionEnd();
649 }
650 if (!mSpeedF && checkBGCrossWall(mDirection)) {
651 setSlipActionEnd();
652 }
653 }
654 } else {
655 mSubstateTimer = 0;
656 mMaxSpeedF = 0.0f;
657 if (mSlipEndTimer == 0 && std::fabs(mSpeedF) < 1.1f) {
658 if (!mKey.buttonCrouch()) {
659 setSlipAction_ToEnd();
660 } else {
661 setSlipAction_ToStoop();
662 }
663 }
664 }
665 } else {
666 if (mSubstateTimer != 0) {
667 mAccelY = 0.0f;
668 onStatus(STATUS_98);
669 } else {
670 offStatus(STATUS_98);
671 }
672 }
673}
674
675void daPlBase_c::changeActionSlipEnd(AnmBlend_e param) {
676 if (
677 (mKey.buttonLeft() && mDirection == 0 && mSpeedF > 0.0f) ||
678 (mKey.buttonRight() &&mDirection == 1 && mSpeedF < 0.0f)
679 ) {
680 mAngle.y = getMukiAngle(mDirection);
681 mDirection ^= 1;
683 return;
684 }
685 if (
686 (mKey.buttonLeft() && mDirection == 0 && mSpeedF < 0.0f) ||
687 (mKey.buttonRight() && mDirection == 1 && mSpeedF > 0.0f)
688 ) {
689 mAngle.y = getMukiAngle(mDirection);
690 mDirection ^= 1;
691 }
693}
694
695bool daPlBase_c::checkTurn() {
696 if (!isCarry() && !isStatus(STATUS_74) && std::fabs(mSpeedF) >= 2.5f) {
697 if (isNowBgCross(BGC_ON_ICE)) {
698 if (
699 (mSpeedF < 0.0f && mKey.buttonRight() && mDirection == 0) ||
700 (mSpeedF > 0.0f && mKey.buttonLeft() && mDirection == 1)
701 ) {
703 return true;
704 }
705 } else {
707 return true;
708 }
709 }
710 return false;
711}
712
713void daPlBase_c::setTurnEnd() {
714 mAngle.y = getMukiAngle(mDirection);
716}
717
718void daPlBase_c::initializeState_Turn() {}
719void daPlBase_c::finalizeState_Turn() {}
720void daPlBase_c::executeState_Turn() {}
721
722bool daPlBase_c::setHipAttackOnEnemy(mVec3_c *) {
723 return 0;
724}
725
726void daPlBase_c::setVsPlHipAttackEffect() {
727 dEf::createPlayerEffect(mPlayerNo, "Wm_mr_misshit", 0, &mPos, nullptr, nullptr);
728}
729
730void daPlBase_c::setHipAttackEffect() {
731 if (mRideActorID) {
732 return;
733 }
734 if (!isOnSinkSand()) {
735 setLandSmokeEffect(getTallType(-1));
736 }
737 if (mGroundType == GROUND_TYPE_WATER) {
738 startSound(SE_PLY_HPDP_SPLASH, false);
739 }
740 if (mPowerup == POWERUP_MINI_MUSHROOM) {
741 startSound(SE_PLY_HIP_ATTACK_M, false);
742 return;
743 }
744
745 if (
746 !(GROUND_TYPE_DEFAULT <= mGroundType && mGroundType <= GROUND_TYPE_CLOUD) &&
747 !(GROUND_TYPE_MANTA <= mGroundType && mGroundType <= GROUND_TYPE_CARPET)
748 ) {
749 switch (mGroundType) {
750 case GROUND_TYPE_FUNSUI:
751 case GROUND_TYPE_LEAF:
752 startSound(SE_PLY_HIP_ATTACK_SOFT, false);
753 default:
754 return;
755 case GROUND_TYPE_WOOD:
756 break;
757 }
758 }
759 startSound(SE_PLY_HIP_ATTACK, false);
760}
761
762void daPlBase_c::setHipAttackDropEffect() {
763 static const float sc_dropEffectScale[] = { 0.7f, 0.8f, 1.0f };
764 mVec3_c pos;
765 mpMdlMng->mpMdl->getJointPos(&pos, 1);
766 float scale = sc_dropEffectScale[getTallType(-1)];
767 mVec3_c scaleVec(scale, scale, scale);
768 dEf::createPlayerEffect(mPlayerNo, &mHitAttackDropEffect, "Wm_mr_drop", 0, &pos, nullptr, &scaleVec);
769}
770
771void daPlBase_c::setHipBlockBreak() {
772 if (mPowerup == POWERUP_MINI_MUSHROOM || mPowerup == POWERUP_NONE) {
773 offStatus(STATUS_C4);
774 } else {
775 onStatus(STATUS_C4);
776 }
777}
778
779void daPlBase_c::setHipAttack_Ready() {
780 mSubstate = HIP_ACTION_READY;
781 mpMdlMng->setAnm(PLAYER_ANIM_HIPSR);
782 mSpeed.y = 1.0f;
783}
784
785void daPlBase_c::setHipAttack_KinopioStart() {
786 setHipAttack_AttackStart();
787 onStatus(STATUS_7F);
788 onStatus(STATUS_7A);
789 if (isItemKinopio()) {
790 startSound(SE_VOC_ITEM_KO_FOUND, false);
791 }
792}
793
794void daPlBase_c::setHipAttack_AttackStart() {
795 mSubstate = HIP_ACTION_ATTACK_START;
796 mpMdlMng->setAnm(PLAYER_ANIM_HIPAT);
797 mSubstateTimer = 5;
798 mSpeed.y = 0.0f;
799}
800
801void daPlBase_c::setHipAttack_AttackFall() {
802 mSubstate = HIP_ACTION_ATTACK_FALL;
803 mAccelF = 0.1f;
804 mMaxSpeedF = 0.0f;
805 mAccelY = *getGravityData();
806 mMaxFallSpeed = -6.0f;
807 if (stateArg<HipAttackArg_e>() == HIP_ATTACK_ARG_ITEM_KINOPIO) {
808 mSpeed.y = -2.0f;
809 } else {
810 mSpeed.y = -6.0f;
811 }
813 setHipBlockBreak();
814 mSubstateTimer = 5;
815}
816
817void daPlBase_c::setHipAttack_StandNormal() {
818 mSubstateTimer = 20;
819 mSubstate = HIP_ACTION_STAND_NORMAL;
820 mpMdlMng->setAnm(PLAYER_ANIM_HIPED);
824 mAccelY = *getGravityData();
825 mMaxFallSpeed = -6.0f;
826 mSpeed.y = 0.0f;
827}
828
829void daPlBase_c::setHipAttack_StandNormalEnd() {
830 mSubstate = HIP_ACTION_STAND_NORMAL_END;
831 mpMdlMng->setAnm(PLAYER_ANIM_SLIPED);
833}
834
835void daPlBase_c::setHipAttack_ToStoop() {
836 mSubstate = HIP_ACTION_TO_STOOP;
837 mpMdlMng->setAnm(PLAYER_ANIM_HIP_TO_STOOP);
839}
840
841void daPlBase_c::HipAction_Ready() {
842 if (mpMdlMng->mpMdl->mAnm.isStop()) {
843 setHipAttack_AttackStart();
844 }
845}
846
847void daPlBase_c::HipAction_AttackStart() {
848 if (mSubstateTimer == 0) {
849 setHipAttack_AttackFall();
850 }
851}
852
853void daPlBase_c::HipAction_AttackFall() {
854 setHipAttackDropEffect();
855 if (mSubstateTimer == 0 || isNowBgCross(BGC_FOOT)) {
856 offStatus(STATUS_7F);
857 offStatus(STATUS_7A);
858 }
859 if (!isNowBgCross(BGC_FOOT)) {
860 if (isNowBgCross(BGC_WATER_SHALLOW)) {
861 mMaxFallSpeed = -3.0f;
862 } else {
863 mMaxFallSpeed = -6.0f;
864 }
865 mAccelY = *getGravityData();
866 int dir;
867 if (mKey.buttonWalk(&dir)) {
868 mMaxSpeedF = sc_DirSpeed[dir] * 0.3f;
869 }
870 if (mKey.buttonDown() && mSpeed.y < 0.0f) {
871 setHipBlockBreak();
872 }
873 if (!isStatus(STATUS_PRESS_ATTACH) && mKey.buttonUp()) {
875 }
876 } else {
877 if (!mKey.buttonDown()) {
878 offStatus(STATUS_C4);
879 }
880 setHipAttackEffect();
881 int quakeType = 0;
882 if (mPowerup == POWERUP_MINI_MUSHROOM) {
883 quakeType = 2;
884 }
885 daPyMng_c::setHipAttackQuake(quakeType, mPlayerNo);
887 offStatus(STATUS_91);
888 if (isNowBgCross(BGC_CLIFF)) {
890 } else if (isSlipSaka()) {
891 if (!isNowBgCross(BGC_WATER_TOUCH)) {
892 if (mBc.getSakaType() >= 2) {
893 mSpeedF = getSlipMaxSpeedF();
894 } else {
895 mSpeedF = getSlipMaxSpeedF() * 0.5f;
896 }
897 }
898 setSlipAction();
899 } else {
900 mMaxSpeedF = 0.0f;
901 mSpeedF = 0.0f;
902 mSpeed.y = 0.0f;
903 mAccelY = 0.0f;
904 mSubstate = HIP_ACTION_GROUND;
905 }
906 }
907}
908
909void daPlBase_c::HipAction_Ground() {
910 if (!mKey.buttonDown() && !isNowBgCross(BGC_FOOT)) {
912 } else {
913 setHipAttack_StandNormal();
914 }
915}
916
917void daPlBase_c::HipAction_StandNormal() {
918 if (mpMdlMng->getAnm() != PLAYER_ANIM_HIPED) {
919 mpMdlMng->setAnm(PLAYER_ANIM_HIPED);
920 }
921 if (isNowBgCross(BGC_FOOT)) {
922 if (mpMdlMng->isAnmStop()) {
923 if (!mKey.buttonDown()) {
925 setHipAttack_StandNormalEnd();
926 } else {
927 setHipBlockBreak();
929 if (isNowBgCross(BGC_COIN_BLOCK_HIT)) {
930 mSubstateTimer = 15;
931 }
932 if (dScStage_c::m_isStaffCredit && isNowBgCross(BGC_FOOT) && !isNowBgCross(BGC_LIFT)) {
934 }
935 }
936 if (mSubstateTimer == 0) {
938 setHipAttack_ToStoop();
939 }
940 }
941 } else if (isSlipSaka()) {
942 mSpeedF = getSlipMaxSpeedF();
943 setSlipAction();
944 } else {
945 turnAngle();
946 }
947 } else {
948 if (mKey.buttonCrouch()) {
949 setHipAttack_AttackFall();
950 }
951 }
952}
953
954void daPlBase_c::HipAction_StandNormalEnd() {
955 if (!checkCrouch()) {
956 if (mpMdlMng->mpMdl->mAnm.isStop()) {
958 } else {
959 turnAngle();
960 }
961 }
962}
963
964void daPlBase_c::HipAction_ToStoop() {
965 if (mpMdlMng->mpMdl->mAnm.isStop()) {
967 } else {
968 turnAngle();
969 }
970}
971
972void daPlBase_c::initializeState_HipAttack() {
973 mAngle.y = getMukiAngle(mDirection);
974 mSpeedF = 0.0f;
975 mMaxSpeedF = 0.0f;
976 mAccelY = 0.0f;
977 switch (stateArg<HipAttackArg_e>()) {
979 setHipAttack_Ready();
980 break;
982 setHipAttack_KinopioStart();
983 break;
984 }
985 onStatus(STATUS_A8);
986 onStatus(STATUS_AA);
988}
989
990void daPlBase_c::finalizeState_HipAttack() {
991 mMaxFallSpeed = -4.0f;
993 offStatus(STATUS_A8);
994 offStatus(STATUS_AA);
995 offStatus(STATUS_C4);
1001 offStatus(STATUS_7F);
1002 offStatus(STATUS_7A);
1004}
1005
1006void daPlBase_c::executeState_HipAttack() {
1007 static ProcFunc l_HipActionProc[] = {
1008 &daPlBase_c::HipAction_Ready,
1009 &daPlBase_c::HipAction_AttackStart,
1010 &daPlBase_c::HipAction_AttackFall,
1011 &daPlBase_c::HipAction_Ground,
1012 &daPlBase_c::HipAction_StandNormal,
1013 &daPlBase_c::HipAction_StandNormalEnd,
1014 &daPlBase_c::HipAction_ToStoop
1015 };
1016
1019 setCcAtHipAttack();
1020 }
1021 if (isNowBgCross(BGC_WATER_SUBMERGED)) {
1022 offStatus(STATUS_AA);
1023 }
1024 if (mSubstate < HIP_ACTION_STAND_NORMAL || !checkJumpTrigger()) {
1025 (this->*l_HipActionProc[mSubstate])();
1028 mPos.x = mPressAttachPos.x;
1029 mPos.y = mPressAttachPos.y;
1030 }
1031 }
1032}
1033
1034void daPlBase_c::initializeState_Swim() {}
1035void daPlBase_c::finalizeState_Swim() {}
1036void daPlBase_c::executeState_Swim() {}
1037
1038bool daPlBase_c::setJumpDaiRide() {
1039 if (isStatus(STATUS_45) || isNowBgCross(BGC_HEAD)) {
1040 return false;
1041 }
1043 return true;
1044}
1045
1046void daPlBase_c::initializeState_JumpDai() {
1048 onStatus(STATUS_86);
1050 mKey.onStatus(dAcPyKey_c::STATUS_NO_INPUT);
1051 mSpeed.y = 0.0f;
1052 mSpeedF = 0.0f;
1053 if (mpMdlMng->getAnm() == PLAYER_ANIM_STOOP) {
1055 } else {
1056 mpMdlMng->setAnm(PLAYER_ANIM_JUMPED);
1057 }
1058}
1059
1060void daPlBase_c::finalizeState_JumpDai() {
1063 mKey.offStatus(dAcPyKey_c::STATUS_NO_INPUT);
1064}
1065
1066void daPlBase_c::executeState_JumpDai() {
1067 if (!isStatus(STATUS_86)) {
1068 changeState(StateID_Fall, false);
1069 } else {
1070 turnAngle();
1071 switch ((JumpDaiSubstate_e) mSubstate) {
1072 case JUMP_DAI_MOVE_DOWN:
1073 if (mpMdlMng->mpMdl->mAnm.isStop()) {
1074 setWaitActionAnm(BLEND_DEFAULT);
1076 }
1077 break;
1078 case JUMP_DAI_HIGH_JUMP:
1079 break;
1080 }
1081 }
1082}
1083
1084bool daPlBase_c::setPlayerJumpDai(daPlBase_c *other) {
1085 if (mRideActorID == 0) {
1086 float topPos = other->getHeadTopPosP()->y - 4.0f;
1087 mVec3_c pos = mVec3_c(
1088 mPos.x,
1089 topPos,
1090 mPos.z
1091 );
1092 float f;
1093 if (mBc.checkRoofPlayer(&pos, &f) && f < topPos + getModelHeight()) {
1094 return false;
1095 }
1096 mRideActorID = other->mUniqueID;
1098 return true;
1099 }
1100 return false;
1101}
1102
1103void daPlBase_c::setPlayerJumoDaiPos() {
1104 daPlBase_c *rideActor = (daPlBase_c *) fManager_c::searchBaseByID(mRideActorID);
1105 if (rideActor == nullptr) {
1106 return;
1107 }
1108 mPos.set(
1109 mJumpDaiOffset.x + rideActor->mPos.x,
1110 rideActor->getHeadTopPosP()->y - 4.0f,
1111 mJumpDaiOffset.z + rideActor->mPos.z
1112 );
1113}
1114
1115void daPlBase_c::initializeState_PlayerJumpDai() {
1118 daPlBase_c *rideActor = (daPlBase_c *) fManager_c::searchBaseByID(mRideActorID);
1119 if (rideActor != nullptr) {
1120 rideActor->initStampReduction();
1121 setNoHitPlayer(rideActor, 5);
1122 mJumpDaiOffset = mPos - rideActor->mPos;
1123 }
1125 mSpeedF = 0.0f;
1126 mSpeed.y = 0.0f;
1127 if (mpMdlMng->getAnm() != PLAYER_ANIM_STOOP) {
1128 mpMdlMng->setAnm(PLAYER_ANIM_JUMPED);
1129 }
1130 if (mKey.triggerJumpBuf(5)) {
1132 } else {
1134 }
1135 mSubstateValue = 0;
1136}
1137
1138void daPlBase_c::finalizeState_PlayerJumpDai() {
1141 mRideActorID = (fBaseID_e) 0;
1142}
1143
1144void daPlBase_c::executeState_PlayerJumpDai() {
1145 daPlBase_c *rideActor = (daPlBase_c *) fManager_c::searchBaseByID(mRideActorID);
1146 if (rideActor == nullptr) {
1147 changeState(StateID_Fall, false);
1148 } else if (isNowBgCross(BGC_HEAD)) {
1149 changeState(StateID_Fall, false);
1150 mJumpDaiFallTimer = 30;
1151 } else {
1152 setNoHitPlayer(rideActor, 5);
1153 turnAngle();
1154 if (mpMdlMng->mpMdl->mCurrAnmID == PLAYER_ANIM_JUMPED && mpMdlMng->mpMdl->mAnm.isStop()) {
1155 setWaitActionAnm(BLEND_DEFAULT);
1156 }
1157 switch ((JumpDaiSubstate_e) mSubstate) {
1158 case JUMP_DAI_MOVE_DOWN:
1159 if (mSubstateValue < 5) {
1160 if (mKey.triggerJump()) {
1162 }
1163 } else if (isMameAction()) {
1164 setJump(daPlBase_c::sc_JumpSpeed - 0.35f, mJumpDaiSpeedF, true, 0, 0);
1165 return;
1166 } else if (mKey.buttonJump()) {
1167 setJump(daPlBase_c::sc_JumpSpeed + 0.2f, mJumpDaiSpeedF, true, 0, 2);
1168 return;
1169 } else {
1170 setJump(daPlBase_c::sc_JumpSpeed + 1.0f, mJumpDaiSpeedF, true, 2, 0);
1171 return;
1172 }
1173 break;
1174 case JUMP_DAI_HIGH_JUMP:
1175 if (mSubstateValue > 5) {
1176 float jumpSpeed = daPlBase_c::sc_JumpSpeed + 0.8f;
1177 if (isMameAction()) {
1178 jumpSpeed = daPlBase_c::sc_JumpSpeed + 0.2f;
1179 }
1180 setJump(jumpSpeed, 0.0f, true, 1, 2);
1181 return;
1182 }
1183 break;
1184 }
1185 rideActor->calcJumpDaiReductionScale(mSubstateValue, 5);
1187 }
1188}
1189
1190bool daPlBase_c::setFunsui() {
1191 if (isDemo()) {
1192 return false;
1193 }
1194 if (!isState(StateID_Funsui)) {
1196 }
1197 return true;
1198}
1199
1200bool daPlBase_c::updateFunsuiPos(float x, float y) {
1201 if (isState(StateID_Funsui)) {
1202 mPos.x = x;
1203 mPos.y = y;
1204 return true;
1205 }
1206 return false;
1207}
1208
1209bool daPlBase_c::releaseFunsui(float f) {
1210 if (isState(StateID_Funsui)) {
1211 mSpeed.y = f;
1212 mSubstate = FUNSUI_ACTION_START;
1213 mKey.onStatus(dAcPyKey_c::STATUS_FORCE_NO_JUMP);
1214 offStatus(STATUS_7F);
1215 }
1216 return true;
1217}
1218
1219void daPlBase_c::releaseFunsuiAction() {
1220 changeState(StateID_Fall, false);
1221}
1222
1223void daPlBase_c::initializeState_Funsui() {
1224 onStatus(STATUS_7F);
1225 mAccelY = 0.0f;
1226 mSpeedF *= 0.7f;
1227 mSpeed.y = 0.0f;
1228 mSubstate = FUNSUI_ACTION_NONE;
1229 mpMdlMng->setAnm(PLAYER_ANIM_BLOW_UP);
1230 if (mPlayerNo >= 0) {
1231 startPlayerVoice(VOICE_INTO_SANDPILLAR, 0);
1232 dQuake_c::m_instance->shockMotor(mPlayerNo, dQuake_c::TYPE_7, 0, false);
1233 mSubstateTimer = 8;
1234 }
1235}
1236
1237void daPlBase_c::finalizeState_Funsui() {
1238 offStatus(STATUS_7F);
1239 mKey.offStatus(dAcPyKey_c::STATUS_FORCE_NO_JUMP);
1240}
1241
1242void daPlBase_c::executeState_Funsui() {
1243 if (mPlayerNo >= 0) {
1244 dEf::createPlayerEffect(mPlayerNo, &mSmokeEffect, "Wm_mr_sprisesmoke", 0, &mPos, nullptr, nullptr);
1245 if (mSubstateTimer == 0) {
1246 mSubstateTimer = 8;
1247 dQuake_c::m_instance->shockMotor(mPlayerNo, dQuake_c::TYPE_8, 0, false);
1248 }
1249 }
1250 turnAngle();
1251 if (mSubstate == FUNSUI_ACTION_START) {
1252 gravitySet();
1253 maxFallSpeedSet();
1254 if (mSpeed.y <= 0.0f || isNowBgCross(BGC_HEAD)) {
1255 releaseFunsuiAction();
1256 return;
1257 }
1258 }
1259 int dir;
1260 if (mKey.buttonWalk(&dir)) {
1261 mMaxSpeedF = sc_DirSpeed[dir] * 0.35f;
1262 } else {
1263 mMaxSpeedF = 0.0f;
1264 }
1265 if (std::fabs(mSpeedF) > 0.35f) {
1266 mAccelF = 0.1f;
1267 } else {
1268 mAccelF = 0.04f;
1269 }
1270}
1271
1272void daPlBase_c::initializeState_Kani() {}
1273void daPlBase_c::finalizeState_Kani() {}
1274void daPlBase_c::executeState_Kani() {}
1275
1276bool daPlBase_c::setCloudOn(dActor_c *cloudActor) {
1277 if (isNowBgCross(BGC_FOOT) || isStatus(STATUS_7E) || isStatus(STATUS_VINE)) {
1278 return false;
1279 }
1280 if (cloudActor->mPos.y + getCloudOffsetY() >= mPos.y && mSpeed.y < 0.0f && mRideActorID == 0) {
1281 mRideActorID = cloudActor->mUniqueID;
1283 return true;
1284 }
1285 return false;
1286}
1287
1288void daPlBase_c::cancelCloudOn() {
1289 mRideActorID = (fBaseID_e) 0;
1290}
1291
1292float daPlBase_c::getCloudOffsetY() {
1293 return 0.0f;
1294}
1295
1296mVec3_c daPlBase_c::getCloudPos() {
1297 return mVec3_c(
1298 mPos.x,
1299 mPos.y - getCloudOffsetY(),
1300 mPos.z
1301 );
1302}
1303
1304void daPlBase_c::initializeState_Cloud() {
1305 startSound(SE_PLY_RIDE_CLOUD, 0);
1306 onStatus(STATUS_4E);
1307 mAccelY = 0.0f;
1308 mSpeed.y = 0.1f;
1309 mSpeedF = 0.0f;
1310 mMaxSpeedF = 0.0f;
1311 mpMdlMng->setAnm(PLAYER_ANIM_JUMPED);
1312 mRc.mFlags |= 4;
1313}
1314
1315void daPlBase_c::finalizeState_Cloud() {
1316 mAngle.x = 0;
1317 cancelCloudOn();
1318 offStatus(STATUS_4E);
1319 offStatus(STATUS_51);
1320 mRc.mFlags &= ~4;
1321}
1322
1323bool daPlBase_c::updateCloudMove() {
1324 daPlBase_c *rideActor = (daPlBase_c *) fManager_c::searchBaseByID(mRideActorID);
1325 if (rideActor == nullptr) {
1326 changeState(StateID_Fall, false);
1327 return true;
1328 }
1329 if (mKey.triggerJump()) {
1330 changeState(StateID_Jump, nullptr);
1331 return true;
1332 }
1333 onStatus(STATUS_82);
1334 mPos = rideActor->mPos;
1335 mPos.y += getCloudOffsetY();
1336 mSpeed.y = 0.0f;
1337 if (!isStatus(STATUS_SPIN)) {
1338 mAngle.set(rideActor->mAngle);
1339 mDirection = rideActor->mDirection;
1340 }
1341 return false;
1342}
1343
1344void daPlBase_c::executeState_Cloud() {}
1345
1346void daPlBase_c::initializeState_AnimePlay() {
1347 mDemoAnime = stateArg<AnimePlayArg_e>();
1348 if (mDemoAnime != DEMO_ANIME_NORMAL) {
1350 }
1351}
1352
1353void daPlBase_c::finalizeState_AnimePlay() {
1355 offStatus(STATUS_24);
1356}
1357
1358void daPlBase_c::executeState_AnimePlay() {
1359 static const ProcFunc scDemoAnmFunc[] = {
1360 &daPlBase_c::DemoAnmNormal,
1361 &daPlBase_c::DemoAnmBossSetUp,
1362 &daPlBase_c::DemoAnmBossGlad,
1363 &daPlBase_c::DemoAnmBossAttention,
1364 &daPlBase_c::DemoAnmBossKeyGet,
1365 &daPlBase_c::DemoAnmBossGlad
1366 };
1367
1368 mAccelY = *getGravityData();
1369 maxFallSpeedSet();
1370 moveSpeedSet();
1371 powerSet();
1372 if (isStatus(STATUS_DISABLE_STATE_CHANGE) || !checkWalkNextAction()) {
1373 (this->*scDemoAnmFunc[mDemoAnime])();
1374 }
1375}
1376
1377void daPlBase_c::DemoAnmNormal() {
1378 if (isStatus(STATUS_24)) {
1379 addCalcAngleY(0, 10);
1380 } else {
1381 turnAngle();
1382 }
1383 if (mpMdlMng->mpMdl->mAnm.isStop()) {
1384 setControlDemoWait();
1385 }
1386}
1387
1388void daPlBase_c::DemoAnmBossSetUp() {
1389 if (mSubstate == ANIME_PLAY_ACTION_0) {
1390 mpMdlMng->setAnm(PLAYER_ANIM_WAIT_L3);
1391 mSubstate++;
1393 }
1394}
1395
1396void daPlBase_c::DemoAnmBossGlad() {
1397 addCalcAngleY(0, 10);
1398 switch (mSubstate) {
1399 case 0:
1400 mSubstateTimer = 15;
1401 mSubstate++;
1402 // fallthrough
1403 case 1:
1404 if (mSubstateTimer == 0) {
1405 initDemoKimePose();
1406 mSubstate++;
1407 }
1408 break;
1409 case 2: {
1410 ClearType_e clearType = CLEAR_TYPE_BOSS;
1411 if (mDemoAnime == DEMO_ANIME_BOSS_GLAD_2) {
1412 clearType = CLEAR_TYPE_FINAL_BOSS;
1413 }
1414 if (!updateDemoKimePose(clearType)) {
1415 break;
1416 }
1417 mpMdlMng->setAnm(PLAYER_ANIM_WAIT, 5.0f, 0.0f);
1418 mSubstate++;
1420 break;
1421 }
1422 default:
1423 break;
1424 }
1425}
1426
1427void daPlBase_c::DemoAnmBossAttention() {
1428 daPlBase_c *boss = (daPlBase_c *) dAttention_c::mspInstance->search(mpMdlMng->mpMdl->mHatPosMaybe);
1429 if (boss != nullptr) {
1430 if (boss->getLookatPos().x > mPos.x) {
1431 mDirection = DIR_LR_R;
1432 } else {
1433 mDirection = DIR_LR_L;
1434 }
1435 }
1436 switch (mSubstate) {
1437 default:
1438 break;
1439 case HIP_ACTION_READY:
1440 if (mDirection == DIR_LR_R) {
1441 mpMdlMng->setAnm(PLAYER_ANIM_WAIT_L_DUPLICATE);
1442 } else {
1443 mpMdlMng->setAnm(PLAYER_ANIM_WAIT_R_DUPLICATE);
1444 }
1445 mSubstate++;
1446 break;
1447 case HIP_ACTION_ATTACK_START:
1448 if (mAngle.y.chase(getMukiAngle(mDirection), 0x800)) {
1449 mSubstate++;
1451 }
1452 break;
1453 }
1454}
1455
1456void daPlBase_c::DemoAnmBossKeyGet() {
1457 addCalcAngleY(0, 10);
1458 switch (mSubstate) {
1459 case 0:
1460 mSubstateTimer = 15;
1461 mSubstate++;
1462 // [Fallthrough]
1463 case 1:
1464 if (mSubstateTimer == 0) {
1465 mpMdlMng->setAnm(PLAYER_ANIM_BOSS_KEY_GET);
1466 startKimePoseVoice(CLEAR_TYPE_BOSS);
1467 mSubstate++;
1469 }
1470 break;
1471 default:
1472 break;
1473 }
1474}
1475
1476void daPlBase_c::initializeState_WaitJump() {
1477 startQuakeShock(dQuake_c::TYPE_5);
1479 mKey.onStatus(dAcPyKey_c::STATUS_FORCE_NO_JUMP);
1480
1481 mSpeedF = 0.0f;
1482 mpMdlMng->setAnm(PLAYER_ANIM_WAIT);
1483 mAngle.y = getMukiAngle(mDirection);
1484}
1485
1486void daPlBase_c::finalizeState_WaitJump() {
1488 mKey.offStatus(dAcPyKey_c::STATUS_FORCE_NO_JUMP);
1489}
1490
1491void daPlBase_c::executeState_WaitJump() {
1492 gravitySet();
1493 maxFallSpeedSet();
1494 moveSpeedSet();
1495 airPowerSet();
1496 if (mSpeed.y <= 0.0f) {
1497 changeState(StateID_Fall, false);
1498 }
1499}
1500
1501bool daPlBase_c::checkSakaReverse() {
1502 if (std::fabs(mSpeedF) < 0.5f && mBc.mPlayerFlags & 4) {
1503 return true;
1504 }
1505 return false;
1506}
1507
1508bool daPlBase_c::isSaka() {
1509 if (isNowBgCross(BGC_SLOPE) ? 1 : 0) {
1510 return true;
1511 }
1512 return false;
1513}
1514
1515bool daPlBase_c::isSlipSaka() {
1516 if (isSaka() && mBc.getFootAttr() != 10) {
1517 return true;
1518 }
1519 return false;
1520}
1521
1522void daPlBase_c::setSlipAction() {
1523 mMoveSakaAngle = mBc.getSakaAngle(mSpeedF);
1525}
1526
1527bool daPlBase_c::checkSlip() {
1528 if (
1529 (mSpeedF > 0.0f || !isNowBgCross(BGC_SIDE_LIMIT_L)) &&
1530 isNowBgCross(BGC_AUTOSLIP)
1531 ) {
1532 setSlipAction();
1533 return true;
1534 }
1535 return false;
1536}
1537
1538bool daPlBase_c::checkCrouchSlip() {
1539 if (isNowBgCross(BGC_WATER_SHALLOW)) {
1540 return false;
1541 }
1542 if (
1543 (mSpeedF > 0.0f || !isNowBgCross(BGC_SIDE_LIMIT_L)) &&
1544 (isNowBgCross(BGC_AUTOSLIP) || isSlipSaka())
1545 ) {
1546 setSlipAction();
1547 return true;
1548 }
1549 return false;
1550}
1551
1552bool daPlBase_c::checkSlipEndKey() {
1553 if (isNowBgCross(BGC_FOOT)) {
1554 if (!mKey.buttonDown()) {
1555 if (mBc.getSakaType() == 0) {
1556 if (mKey.buttonCross()) {
1557 return true;
1558 }
1559 } else if (mBc.getSakaType() != 4) {
1560 if (
1561 mKey.buttonLeft() && mBc.getSakaDir() == 0 ||
1562 mKey.buttonRight() && mBc.getSakaDir() == 1
1563 ) {
1564 return true;
1565 }
1566 }
1567 }
1568 if (mKey.buttonUp()) {
1569 return true;
1570 }
1571 }
1572 return false;
1573}
1574
1575float daPlBase_c::getSlipMaxSpeedF() {
1576 if (isSaka()) {
1577 return sc_DirSpeed[mBc.getSakaDir()] * 4.0f;
1578 }
1579 return 0.0f;
1580}
1581
1582float daPlBase_c::getSakaMaxSpeedRatio(u8 direction) {
1583 return l_sakaMaxSpeedRatio[mBc.getSakaType()][mBc.getSakaUpDown(direction)];
1584}
1585
1586float daPlBase_c::getSakaStopAccele(u8 direction) {
1587 return l_sakaStopAccele[mBc.getSakaType()][mBc.getSakaUpDown(direction)];
1588}
1589
1590float daPlBase_c::getSakaMoveAccele(u8 direction) {
1591 return l_sakaMoveAccele[mBc.getSakaType()][mBc.getSakaUpDown(direction)];
1592}
1593
1594float daPlBase_c::getIceSakaSlipOffSpeed() {
1595 return l_sakaSlipOffSpeed[mBc.getSakaType()][mBc.getSakaDir()];
1596}
1597
1598bool daPlBase_c::setSandMoveSpeed() {
1599 if (isOnSinkSand()) {
1600 int dir;
1601 if (mKey.buttonWalk(&dir)) {
1602 if (isStatus(STATUS_SPIN)) {
1603 mMaxSpeedF = sc_DirSpeed[dir];
1604 } else {
1605 mMaxSpeedF = sc_DirSpeed[dir] * 0.5f;
1606 }
1607 } else {
1608 mMaxSpeedF = 0.0f;
1609 }
1610 if (mSpeedF * mMaxSpeedF >= 0.0f) {
1611 if (std::fabs(mSpeedF) > std::fabs(mMaxSpeedF)) {
1613 }
1614 } else {
1615 mSpeedF = 0.0f;
1616 }
1617 return true;
1618 }
1619 return false;
1620}
1621
1622void daPlBase_c::moveSpeedSet() {
1623 if (!setSandMoveSpeed() && !isStatus(STATUS_96)) {
1624 int dir;
1625 if (mKey.buttonWalk(&dir)) {
1626 if (!isNowBgCross(BGC_FOOT)) {
1627 float absSpeed = std::fabs(mSpeedF);
1628 float speed1 = sc_DirSpeed[dir] * getSpeedData()->mLowSpeed;
1629 float speed2 = sc_DirSpeed[dir] * getSpeedData()->mHighSpeed;
1630 float tmp = sc_DirSpeed[dir] * absSpeed;
1631 if (absSpeed >= std::fabs(speed2) || mKey.buttonDush()) {
1632 mMaxSpeedF = speed2;
1633 } else if (absSpeed > std::fabs(speed1)) {
1634 mMaxSpeedF = tmp;
1635 } else {
1636 mMaxSpeedF = speed1;
1637 }
1638 } else {
1639 float speed;
1640 if (mKey.buttonDush()) {
1641 speed = sc_DirSpeed[dir] * getSpeedData()->mHighSpeed;
1642 } else {
1643 speed = sc_DirSpeed[dir] * getSpeedData()->mLowSpeed;
1644 }
1645 mMaxSpeedF = speed * getSakaMaxSpeedRatio(dir);
1646 }
1647 } else {
1648 mMaxSpeedF = 0.0f;
1649 if (checkSakaReverse()) {
1650 mSpeedF = 0.0f;
1651 } else if (getPowerChangeType(false) == POWER_CHANGE_ICE) {
1652 mMaxSpeedF = getIceSakaSlipOffSpeed();
1653 }
1654 }
1655 if (!isNowBgCross(BGC_FOOT) && !isStatus(STATUS_88) && std::fabs(mSpeedF) > getSpeedData()->mHighSpeed) {
1656 if (mSpeedF < 0.0f) {
1657 mSpeedF = -getSpeedData()->mHighSpeed;
1658 } else {
1659 mSpeedF = getSpeedData()->mHighSpeed;
1660 }
1661 }
1662 }
1663}
1664
1665void daPlBase_c::simpleMoveSpeedSet() {
1666 if (!setSandMoveSpeed()) {
1667 int dir;
1668 if (mKey.buttonWalk(&dir)) {
1669 if (mKey.buttonDush()) {
1670 mMaxSpeedF = sc_DirSpeed[dir] * getSpeedData()->mHighSpeed;
1671 } else {
1672 mMaxSpeedF = sc_DirSpeed[dir] * getSpeedData()->mLowSpeed;
1673 }
1674 } else {
1675 mMaxSpeedF = 0.0f;
1676 }
1677 }
1678}
1679
1680void daPlBase_c::grandPowerSet() {
1681 if (isOnSinkSand()) {
1682 mAccelF = getSpeedData()->mPowerChangeNormal.mVerySlowAccel;
1683 } else if (isStatus(STATUS_SLIP_ACTIVE)) {
1684 slipPowerSet(1);
1685 } else {
1686 slipPowerSet(0);
1687 }
1688}
1689
1691 /// @unofficial
1692 static const float sc_data[] = { 1.1f, 0.9f, 1.0f };
1693 if (isSaka()) {
1694 int dir = 0;
1695 if (mSpeedF < 0.0f) {
1696 dir = 1;
1697 }
1698 mAccelF = getSakaMoveAccele(dir);
1699 int dir2;
1700 if (mKey.buttonWalk(&dir2)) {
1701 mAccelF *= sc_data[mBc.getSakaUpDown(dir2)];
1702 }
1703 if (mode == 0) {
1704 if (!mKey.buttonWalk(&dir)) {
1705 mAccelF = getSakaStopAccele(dir);
1706 if (isStatus(STATUS_89)) {
1707 mAccelF = calcSomeAccel(mAccelF);
1708 }
1709 } else if (mSpeedF * sc_DirSpeed[mDirection] < 0.0f) {
1710 mAccelF = getSpeedData()->mPowerChangeNormal.mTurnAccel;
1711 if (isStatus(STATUS_89)) {
1712 mAccelF = calcSomeAccel(mAccelF);
1713 }
1714 return;
1715 }
1716 }
1717 icePowerChange(mode);
1718 } else {
1719 if (mode == 1) {
1720 if (isStatus(STATUS_31)) {
1721 mAccelF = 0.05f;
1722 } else {
1723 mAccelF = 0.09f;
1724 }
1725 icePowerChange(1);
1726 } else {
1727 normalPowerSet();
1728 }
1729 }
1730}
1731
1732void daPlBase_c::normalPowerSet() {
1733 if (std::fabs(mSpeedF) > getSpeedData()->mHighSpeed) {
1734 mAccelF = 0.75f;
1735 return;
1736 }
1737 PowerChangeType_e powerChangeType = getPowerChangeType(false);
1738 sPowerChangeSpeedData data;
1740 if (!mKey.buttonWalk(nullptr)) {
1741 if (mSpeedF * sc_DirSpeed[mDirection] < 0.0f) {
1742 mAccelF = data.mTurnNoInputAccel;
1743 } else if (std::fabs(mSpeedF) < getSpeedData()->mLowSpeed) {
1744 mAccelF = data.mNoInputAccel;
1745 } else {
1746 mAccelF = data.mDefaultAccel;
1747 }
1748 if (powerChangeType == POWER_CHANGE_ICE && std::fabs(mSpeedF) < 0.5f) {
1749 mAccelF = 0.004f;
1750 }
1751 if (isStatus(STATUS_89)) {
1752 mAccelF = calcSomeAccel(mAccelF);
1753 }
1754 return;
1755 }
1756 if (mSpeedF * sc_DirSpeed[mDirection] < 0.0f) {
1757 mAccelF = data.mTurnAccel;
1758 if (isStatus(STATUS_89)) {
1759 mAccelF = calcSomeAccel(mAccelF);
1760 }
1761 return;
1762 }
1763
1764 float absMaxSpeed = std::fabs(mMaxSpeedF);
1765 float absSpeed = std::fabs(mSpeedF);
1766
1767 if (absSpeed < 0.5f) {
1768 mAccelF = data.mVerySlowAccel;
1769 } else if (absSpeed < getSpeedData()->mLowSpeed) {
1770 if (mKey.buttonDush()) {
1771 mAccelF = data.mRunSlowAccel;
1772 } else {
1773 mAccelF = data.mSlowAccel;
1774 }
1775 } else if (absSpeed < getSpeedData()->mMediumSpeed) {
1776 if (absMaxSpeed < getSpeedData()->mMediumSpeed) {
1777 mAccelF = data.mDefaultAccel;
1778 } else {
1779 mAccelF = data.mMediumAccel;
1780 }
1781 } else {
1782 if (absMaxSpeed < getSpeedData()->mMediumSpeed) {
1783 mAccelF = data.mDefaultAccel;
1784 } else {
1785 mAccelF = data.mFastAccel;
1786 }
1787 }
1788}
1789
1790daPlBase_c::PowerChangeType_e daPlBase_c::getPowerChangeType(bool affectPenguin) {
1791 if (!affectPenguin && isStatus(STATUS_IS_PENGUIN)) {
1792 return POWER_CHANGE_NORMAL;
1793 }
1794 if (isNowBgCross(BGC_ON_ICE)) {
1795 return POWER_CHANGE_ICE;
1796 }
1797 if (isNowBgCross(BGC_ON_ICE_LOW_SLIP)) {
1798 return POWER_CHANGE_LOW_SLIP;
1799 }
1800 if (isNowBgCross(BGC_ON_SNOW) ? 1 : 0) {
1801 return POWER_CHANGE_LOW_SLIP;
1802 }
1803 return POWER_CHANGE_NORMAL;
1804}
1805
1807 switch (getPowerChangeType(false)) {
1808 case POWER_CHANGE_NORMAL:
1809 data = getSpeedData()->mPowerChangeNormal;
1810 break;
1811 case POWER_CHANGE_ICE:
1812 data = getSpeedData()->mPowerChangeIce;
1813 break;
1814 case POWER_CHANGE_LOW_SLIP:
1815 data = getSpeedData()->mPowerChangeLowSlip;
1816 break;
1817 }
1818}
1819
1821 const sPowerChangeData &data = daPlayerData_c::smc_POWER_CHANGE_DATA;
1822 int idx = isStar() ? 1 : 0;
1823 switch (getPowerChangeType(false)) {
1824 case POWER_CHANGE_NORMAL:
1825 bb = data.mTurnPowerNormal[idx];
1826 break;
1827 case POWER_CHANGE_ICE:
1828 bb = data.mTurnPowerIce[idx];
1829 break;
1830 case POWER_CHANGE_LOW_SLIP:
1831 bb = data.mTurnPowerLowSlip[idx];
1832 break;
1833 }
1834}
1835
1836void daPlBase_c::icePowerChange(int mode) {
1837 PowerChangeType_e powerChangeType = getPowerChangeType(false);
1838 if (powerChangeType == POWER_CHANGE_ICE || (powerChangeType == POWER_CHANGE_LOW_SLIP && mode == 1)) {
1839 if (mMaxSpeedF) {
1840 if (mSpeedF * mMaxSpeedF < 0.0f) {
1841 mAccelF = mAccelF * 0.375f;
1842 } else if (mode == 0) {
1843 if (isSaka()) {
1844 mAccelF = mAccelF * 0.375f;
1845 } else if (std::fabs(mSpeedF) < 0.5f) {
1846 mAccelF = mAccelF * 0.25f;
1847 }
1848 }
1849 } else if (!isSaka() && std::fabs(mSpeedF) < 0.5f) {
1850 mAccelF = 0.004;
1851 } else {
1852 mAccelF = mAccelF * 0.375f;
1853 }
1854 }
1855}
1856
1857void daPlBase_c::airPowerSet() {
1858 const sPowerChangeData *data = &daPlayerData_c::smc_POWER_CHANGE_DATA;
1859 u8 idx = isStar() ? 1 : 0;
1860 const sAirTurnPowerData &airPowerData = data->mAirPower[idx];
1861 int dir;
1862 if (mKey.buttonWalk(&dir)) {
1863 if (mSpeedF * sc_DirSpeed[dir] < 0.0f) {
1864 mAccelF = airPowerData.mTurnAround;
1865 return;
1866 } else if (std::fabs(mSpeedF) < 0.5f) {
1867 mAccelF = airPowerData.mStand;
1868 return;
1869 }
1870
1871 float absSpeed = std::fabs(mSpeedF);
1872
1873 if (absSpeed < getSpeedData()->mLowSpeed) {
1874 if (mKey.buttonDush()) {
1875 mAccelF = airPowerData.mSlowDash;
1876 } else {
1877 mAccelF = airPowerData.mSlowNoDash;
1878 }
1879 } else if (absSpeed < getSpeedData()->mMediumSpeed) {
1880 mAccelF = airPowerData.mMedium;
1881 } else {
1882 mAccelF = airPowerData.mFast;
1883 }
1884 } else {
1885 mAccelF = airPowerData.mNoButton;
1886 }
1887}
1888
1889void daPlBase_c::powerSet() {
1890 if (isNowBgCross(BGC_FOOT)) {
1891 grandPowerSet();
1892 } else {
1893 airPowerSet();
1894 }
1895}
1896
1897void daPlBase_c::maxFallSpeedSet() {
1898 mMaxFallSpeed = -4.0f;
1899}
1900
1901void daPlBase_c::gravitySet() {
1902 if (isStatus(STATUS_98)) {
1903 return;
1904 }
1905 if (isNowBgCross(BGC_FOOT)) {
1906 mAccelY = *getGravityData();
1907 } else {
1908 setJumpGravity();
1909 }
1910}
1911
1912void daPlBase_c::setJumpGravity() {
1913 if (mNoGravityTimer != 0) {
1914 mAccelY = 0.0f;
1915 } else if (mKey.buttonJump()) {
1916 setButtonJumpGravity();
1917 } else {
1918 setNormalJumpGravity();
1919 }
1920}
1921
1922void daPlBase_c::setButtonJumpGravity() {
1923 mAccelY = *(getGravityData() + 17);
1924 for (int i = 0; i < 5; i++) {
1925 if (mSpeed.y > *(getGravityData() + i + 1)) {
1926 mAccelY = *(getGravityData() + i + 12);
1927 break;
1928 }
1929 }
1930}
1931
1932void daPlBase_c::setNormalJumpGravity() {
1933 if (mSpeed.y <= 1.5f) {
1934 mKey.offStatus(dAcPyKey_c::STATUS_FORCE_NO_JUMP);
1935 }
1936 mAccelY = *(getGravityData() + 11);
1937 for (int i = 0; i < 5; i++) {
1938 if (mSpeed.y > *(getGravityData() + i + 1)) {
1939 mAccelY = *(getGravityData() + i + 6);
1940 break;
1941 }
1942 }
1943}
1944
1945float fn_8004c700(float v) {
1946 bool isNeg = false;
1947 if (v < 0.0f) {
1948 v = -v;
1949 isNeg = true;
1950 }
1951 if (v < 0.1f) {
1952 v = 0.0f;
1953 } else {
1954 v = (v - 0.1f) / 0.9f;
1955 }
1956 float tmp;
1957 float lim2 = 0.1f;
1958 if (v < lim2) {
1959 v = 0.0f;
1960 } else {
1961 tmp = 1.0f;
1962 v = (v - 0.1f) / (tmp - 0.1f);
1963 }
1964 if (isNeg == true) {
1965 v = -v;
1966 }
1967 v *= 1.11111f;
1968 return v;
1969}
1970
1971class daTagWind_c : public dActor_c {
1972public:
1973 float m_00;
1974};
1975
1976void daPlBase_c::calcWindSpeed() {
1977 daTagWind_c *windActor = (daTagWind_c *) fManager_c::searchBaseByProfName(fProfile::TAG_WIND, nullptr);
1978 if (windActor == nullptr) {
1979 mWindSpeed = 0.0f;
1980 return;
1981 }
1982 if (isStatus(STATUS_A0) && !isOnSinkSand()) {
1983 float windSpeed = fn_8004c700(windActor->m_00);
1984 float halfWindSpeed = windSpeed * 0.5f;
1985 windSpeed = std::fabs(windSpeed) * 3.0f;
1986 if (
1987 mWindSpeed > 0.0f && isNowBgCross(BGC_WALL_TOUCH_R_2) ||
1988 mWindSpeed < 0.0f && isNowBgCross(BGC_WALL_TOUCH_L_2)
1989 ) {
1990 mWindSpeed = 0.0f;
1991 }
1992 if (isNowBgCross(BGC_FOOT)) {
1995 mSpeedF += mWindSpeed;
1996 mWindSpeed = 0.0f;
1997 }
1998 float scale;
1999 if (isStatus(STATUS_5B)) {
2000 windSpeed = 0.45f * windSpeed;
2001 } else {
2002 windSpeed = 0.55f * windSpeed;
2003 }
2004 mWindGroundTimer = 3;
2005 mWindSpeed += halfWindSpeed;
2006 } else {
2009 }
2010 if (mWindGroundTimer != 0) {
2011 mWindGroundTimer--;
2012 } else if (mSpeedF * mWindSpeed < 0.0f) {
2013 mSpeedF += halfWindSpeed;
2014 } else {
2015 mWindSpeed += halfWindSpeed;
2016 }
2017 }
2018 if (mWindSpeed > windSpeed) {
2019 mWindSpeed = windSpeed;
2020 } else if (mWindSpeed < -windSpeed) {
2021 mWindSpeed = -windSpeed;
2022 }
2023 } else {
2024 mWindSpeed = 0.0f;
2025 return;
2026 }
2027}
2028
2029void daPlBase_c::setLandSE() {
2030 if (mPowerup == POWERUP_PENGUIN_SUIT) {
2031 startFootSoundPlayer(SE_PLY_LAND_PNGN);
2032 return;
2033 }
2034 static const dAudio::SoundEffectID_t scLandSeID[] = {
2035 SE_PLY_LAND_ROCK,
2036 SE_PLY_LAND_SNOW,
2037 SE_PLY_LAND_SAND,
2038 SE_PLY_LAND_ROCK,
2039 SE_PLY_LAND_DIRT,
2040 SE_PLY_LAND_WATER,
2041 SE_PLY_LAND_CLOUD,
2042 SE_PLY_LAND_BLOWSAND,
2043 SE_PLY_LAND_MANTA,
2044 SE_PLY_LAND_SAND,
2045 SE_PLY_LAND_ROCK,
2046 SE_PLY_LAND_LEAF,
2047 SE_PLY_LAND_ROCK
2048 };
2049 startFootSoundPlayer(scLandSeID[mGroundType]);
2050}
2051
2052void daPlBase_c::setSlipSE() {
2053 if (mGroundType == GROUND_TYPE_WATER) {
2054 holdSound(SE_PLY_PNGN_SLIP_SEA, std::fabs(mSpeedF), false);
2055 return;
2056 }
2057 static const dAudio::SoundEffectID_t scSlipSeID[] = {
2058 SE_PLY_SLIP,
2059 SE_PLY_SLIP_SNOW,
2060 SE_PLY_SLIP_SAND,
2061 SE_PLY_SLIP_ICE,
2062 SE_PLY_SLIP,
2063 SE_PLY_SLIP,
2064 SE_PLY_SLIP,
2065 SE_PLY_SLIP_SAND,
2066 SE_PLY_SLIP,
2067 SE_PLY_SLIP_SAND,
2068 SE_PLY_SLIP,
2069 SE_PLY_SLIP,
2070 SE_PLY_SLIP
2071 };
2072 holdSound(scSlipSeID[mGroundType], false);
2073}
2074
2075void daPlBase_c::setLandSmokeEffect(int param1) {
2076 static const char *sc_landSmokeEffectID[][3] = {
2077 {"Wm_mr_landsmoke_ss", "Wm_mr_landsmoke_s", "Wm_mr_landsmoke" },
2078 {"Wm_mr_landsmoke_ss", "Wm_mr_landsmoke_s", "Wm_mr_landsmoke" },
2079 {"Wm_mr_sndlandsmk_ss", "Wm_mr_sndlandsmk_s", "Wm_mr_sndlandsmk" },
2080 {"Wm_mr_landsmoke_ss", "Wm_mr_landsmoke_s", "Wm_mr_landsmoke" },
2081 {"Wm_mr_landsmoke_ss", "Wm_mr_landsmoke_s", "Wm_mr_landsmoke" },
2082 {"Wm_mr_watersplash", "Wm_mr_watersplash", "Wm_mr_watersplash" },
2083 {"Wm_mr_landsmoke_ss", "Wm_mr_landsmoke_s", "Wm_mr_landsmoke" },
2084 {"Wm_mr_sndlandsmk_ss", "Wm_mr_sndlandsmk_s", "Wm_mr_sndlandsmk" },
2085 {"Wm_mr_landsmoke_ss", "Wm_mr_landsmoke_s", "Wm_mr_landsmoke" },
2086 {"Wm_mr_beachlandsmk_ss", "Wm_mr_beachlandsmk_s", "Wm_mr_beachlandsmk" },
2087 {"Wm_mr_landsmoke_ss", "Wm_mr_landsmoke_s", "Wm_mr_landsmoke" },
2088 {"Wm_mr_landsmoke_ss", "Wm_mr_landsmoke_s", "Wm_mr_landsmoke" },
2089 {"Wm_mr_landsmoke_ss", "Wm_mr_landsmoke_s", "Wm_mr_landsmoke" }
2090 };
2091 if (mGroundType == GROUND_TYPE_FUNSUI) {
2092 setSandFunsuiLandEffect();
2093 } else if (mGroundType == GROUND_TYPE_WATER) {
2094 PLAYER_POWERUP_e powerup = mPowerup;
2095 float sz = 1.0f;
2096 if (powerup == POWERUP_MINI_MUSHROOM) {
2097 sz = 0.6f;
2098 } else if (powerup == POWERUP_NONE) {
2099 sz = 0.8f;
2100 }
2101 mVec3_c size(sz, sz, sz);
2102 dEf::createPlayerEffect(mPlayerNo, sc_landSmokeEffectID[mGroundType][param1], 0, &mPos, nullptr, &size);
2103 } else {
2104 dEf::createPlayerEffect_change(mPlayerNo, sc_landSmokeEffectID[mGroundType][param1], 0, &mPos, nullptr, nullptr);
2105 }
2106}
2107
2108void daPlBase_c::setLandSmokeEffectLight() {
2109 mVec3_c pos = mPos;
2110 if (dMaskMng::isCaveMask() && mLayer == 0) {
2111 if (mAmiLayer == 1) {
2112 pos.z = 3700.0f;
2113 }
2114 }
2115 float sz = dPyMdlMng_c::m_hio.m_08[mpMdlMng->mpMdl->m_152];
2116 mVec3_c size(sz, sz, sz);
2117 if (isNowBgCross(BGC_ON_SAND)) {
2118 if (mGroundType == GROUND_TYPE_FUNSUI) {
2119 setSandFunsuiLandEffect();
2120 } else if (!isOnSinkSand()) {
2121 dEf::createPlayerEffect(mPlayerNo, "Wm_mr_cmnsndlandsmk", 0, &pos, nullptr, &size);
2122 }
2123 } else {
2124 dEf::createPlayerEffect(mPlayerNo, "Wm_mr_cmnlandsmoke", 0, &pos, nullptr, &size);
2125 }
2126}
2127
2128bool daPlBase_c::setSandFunsuiLandEffect() {
2129 if (mGroundType == GROUND_TYPE_FUNSUI) {
2130 dEf::createPlayerEffect(mPlayerNo, "Wm_mr_spsmoke", 0, &mPos, nullptr, nullptr);
2131 return true;
2132 }
2133 return false;
2134}
2135
2136void daPlBase_c::setStartJumpEffect(int param1) {
2137 if (isNowBgCross(BGC_FOOT)) {
2138 if (isOnSinkSand()) {
2139 setSandJumpEffect();
2141 } else if (!setSandFunsuiLandEffect() && param1 == 1) {
2142 setLandSmokeEffectLight();
2143 }
2144 }
2145}
2146
2147void daPlBase_c::setLandJumpEffect(int param1) {
2148 setLandSE();
2149 if (!setSandFunsuiLandEffect() && param1 == 1) {
2150 setLandSmokeEffectLight();
2151 }
2152}
2153
2154void daPlBase_c::setSlipOnWaterEffect(mEf::levelEffect_c *effect) {
2155 static const float sc_runFootScale[] = { 0.5f, 0.8f, 1.0f };
2156 float sz = sc_runFootScale[getTallType(-1)];
2157 mVec3_c size(sz, sz, sz);
2158 mVec3_c pos(
2159 mPos.x,
2160 mPos.y + sz * 10.0f,
2161 mPos.z
2162 );
2163 dEf::createPlayerEffect(mPlayerNo, effect, "Wm_mr_foot_water", 0, &pos, nullptr, &size);
2164}
2165
2166void daPlBase_c::setSlipSmokeEffect() {
2167 static const char *sc_slipSmokeEffectID[][2] = {
2168 { "Wm_mr_slipsmoke_ss", "Wm_mr_slipsmoke" },
2169 { "Wm_mr_slipsmoke_ss", "Wm_mr_slipsmoke" },
2170 { "Wm_mr_sndslipsmk_ss", "Wm_mr_sndslipsmk" },
2171 { "Wm_mr_iceslipsmk_ss", "Wm_mr_iceslipsmk" },
2172 { "Wm_mr_slipsmoke_ss", "Wm_mr_slipsmoke" },
2173 { "Wm_mr_slipsmoke_ss", "Wm_mr_slipsmoke" },
2174 { "Wm_mr_slipsmoke_ss", "Wm_mr_slipsmoke" },
2175 { "Wm_mr_slipsmoke_ss", "Wm_mr_slipsmoke" },
2176 { "Wm_mr_slipsmoke_ss", "Wm_mr_slipsmoke" },
2177 { "Wm_mr_beachslipsmk_ss", "Wm_mr_beachslipsmk" },
2178 { "Wm_mr_slipsmoke_ss", "Wm_mr_slipsmoke" },
2179 { "Wm_mr_slipsmoke_ss", "Wm_mr_slipsmoke" },
2180 { "Wm_mr_slipsmoke_ss", "Wm_mr_slipsmoke" }
2181 };
2182
2183 if (mGroundType == GROUND_TYPE_WATER) {
2184 setSlipOnWaterEffect(&mSlipSmokeEffect);
2185 return;
2186 }
2187 mVec3_c pos;
2188 mpMdlMng->mpMdl->getJointPos(&pos, 1);
2189 int idx = 0;
2190 if (mPowerup != POWERUP_MINI_MUSHROOM) {
2191 idx = 1;
2192 }
2193 dEf::createPlayerEffect_change(mPlayerNo, &mSlipSmokeEffect, sc_slipSmokeEffectID[mGroundType][idx], 0, &pos, nullptr, nullptr);
2194}
2195
2196void daPlBase_c::setBrakeSmokeEffect(mVec3_c &offset) {
2197 static const char *sc_brakeSmokeEffectID[][2] = {
2198 { "Wm_mr_brakesmoke_ss", "Wm_mr_brakesmoke" },
2199 { "Wm_mr_brakesmoke_ss", "Wm_mr_brakesmoke" },
2200 { "Wm_mr_sndbrakesmk_ss", "Wm_mr_sndbrakesmk" },
2201 { "Wm_mr_icebrakesmk_ss", "Wm_mr_icebrakesmk" },
2202 { "Wm_mr_brakesmoke_ss", "Wm_mr_brakesmoke" },
2203 { "Wm_mr_brakesmoke_ss", "Wm_mr_brakesmoke" },
2204 { "Wm_mr_brakesmoke_ss", "Wm_mr_brakesmoke" },
2205 { "Wm_mr_brakesmoke_ss", "Wm_mr_brakesmoke" },
2206 { "Wm_mr_brakesmoke_ss", "Wm_mr_brakesmoke" },
2207 { "Wm_mr_beachbrakesmk_ss", "Wm_mr_beachbrakesmk" },
2208 { "Wm_mr_brakesmoke_ss", "Wm_mr_brakesmoke" },
2209 { "Wm_mr_brakesmoke_ss", "Wm_mr_brakesmoke" },
2210 { "Wm_mr_brakesmoke_ss", "Wm_mr_brakesmoke" }
2211 };
2212
2213 if (mGroundType == GROUND_TYPE_WATER) {
2214 setSlipOnWaterEffect(&mBrakeSmokeEffect);
2215 return;
2216 }
2217 int idx = 0;
2218 if (mPowerup != POWERUP_MINI_MUSHROOM) {
2219 idx = 1;
2220 }
2221 dEf::createPlayerEffect_change(mPlayerNo, &mBrakeSmokeEffect, sc_brakeSmokeEffectID[mGroundType][idx], 0, &offset, nullptr, nullptr);
2222}
2223
2224void daPlBase_c::setTurnSmokeEffect() {
2225 if (mSpeedF) {
2226 static const dAudio::SoundEffectID_t scTurnSeID[] = {
2227 SE_PLY_BRAKE,
2228 SE_PLY_BRAKE_SNOW,
2229 SE_PLY_BRAKE_SAND,
2230 SE_PLY_BRAKE_ICE,
2231 SE_PLY_BRAKE,
2232 SE_PLY_BRAKE_WATER,
2233 SE_PLY_BRAKE,
2234 SE_PLY_BRAKE_SAND,
2235 SE_PLY_BRAKE,
2236 SE_PLY_BRAKE_SAND,
2237 SE_PLY_BRAKE,
2238 SE_PLY_BRAKE,
2239 SE_PLY_BRAKE
2240 };
2241 holdSound(scTurnSeID[mGroundType], 0);
2242 }
2243 static const char *sc_turnSmokeEffectID[][2] = {
2244 { "Wm_mr_turn_usual_r", "Wm_mr_turn_usual_l" },
2245 { "Wm_mr_turn_snow_r", "Wm_mr_turn_snow_l" },
2246 { "Wm_mr_turn_sand_r", "Wm_mr_turn_sand_l" },
2247 { "Wm_mr_turn_ice_r", "Wm_mr_turn_ice_l" },
2248 { "Wm_mr_turn_usual_r", "Wm_mr_turn_usual_l" },
2249 { "Wm_mr_turn_water_r", "Wm_mr_turn_water_l" },
2250 { "Wm_mr_turn_usual_r", "Wm_mr_turn_usual_l" },
2251 { "Wm_mr_turn_sand_r", "Wm_mr_turn_sand_l" },
2252 { "Wm_mr_turn_usual_r", "Wm_mr_turn_usual_l" },
2253 { "Wm_mr_turn_beach_r", "Wm_mr_turn_beach_l" },
2254 { "Wm_mr_turn_usual_r", "Wm_mr_turn_usual_l" },
2255 { "Wm_mr_turn_usual_r", "Wm_mr_turn_usual_l" },
2256 { "Wm_mr_turn_usual_r", "Wm_mr_turn_usual_l" }
2257 };
2258 static const float sc_turnSmokeScale[] = { 0.5f, 0.8f, 1.0f };
2259 mVec3_c pos;
2260 mpMdlMng->mpMdl->getJointPos(&pos, 1);
2261 if (mGroundType == GROUND_TYPE_WATER) {
2262 if (mPos.y < mWaterHeight - 4.0f) {
2263 fadeOutTurnEffect();
2264 return;
2265 }
2266 pos.y = mWaterHeight;
2267 }
2268 float sz = sc_turnSmokeScale[getTallType(-1)];
2269 mVec3_c size(sz, sz, sz);
2270 if (mTurnEffectFade == 1 && mTurnGroundType == mGroundType) {
2271 mTurnSmokeEffect.follow(&pos, 0, 0);
2272 } else {
2273 dEf::createPlayerEffect(mPlayerNo, &mTurnSmokeEffect, sc_turnSmokeEffectID[mGroundType][mDirection], 0, &pos, nullptr, &size);
2274 mTurnGroundType = mGroundType;
2275 mTurnEffectFade = 1;
2276 }
2277}
2278
2279void daPlBase_c::fadeOutTurnEffect() {
2280 if (mTurnEffectFade != 1) {
2281 return;
2282 }
2283 mTurnSmokeEffect.followFade();
2284 mTurnEffectFade = 0;
2285}
2286
2287void daPlBase_c::setRunFootEffect() {
2288 static const char *sc_runFootEffectID[] = {
2289 nullptr,
2290 "Wm_mr_foot_snow",
2291 "Wm_mr_foot_sand",
2292 "Wm_mr_foot_ice",
2293 nullptr,
2294 "Wm_mr_foot_water",
2295 nullptr,
2296 "Wm_mr_foot_sand",
2297 nullptr,
2298 "Wm_mr_foot_beach",
2299 nullptr,
2300 nullptr,
2301 nullptr
2302 };
2303 if (!isOnSinkSand() && isStatus(STATUS_62)) {
2304 if (
2305 GROUND_TYPE_SNOW <= mGroundType && mGroundType <= GROUND_TYPE_ICE ||
2306 mGroundType == GROUND_TYPE_WATER ||
2307 mGroundType == GROUND_TYPE_FUNSUI ||
2308 mGroundType == GROUND_TYPE_BEACH
2309 ) {
2310 mVec3_c pos;
2311 mpMdlMng->mpMdl->getJointPos(&pos, 1);
2312 static const float sc_runFootScale[] = { 0.5f, 0.8f, 1.0f };
2313 float sz = sc_runFootScale[getTallType(-1)];
2314 mVec3_c size(sz, sz, sz);
2315 dEf::createPlayerEffect(mPlayerNo, &mRunEffect, sc_runFootEffectID[mGroundType], 0, &pos, nullptr, &size);
2316 }
2317 }
2318}
2319
2320void daPlBase_c::setSandEffect() {
2321 if (isStatus(STATUS_4E) || isStatus(STATUS_RIDE_YOSHI)) {
2322 return;
2323 }
2324 if (isOnSinkSand() && !isNowBgCross(BGC_INSIDE_SINK_SAND) || isStatus(STATUS_SINK_SAND_JUMP)) {
2325 mVec3_c pos;
2326 mpMdlMng->mpMdl->getJointPos(&pos, 8);
2327 dEf::createPlayerEffect(mPlayerNo, &mQuicksandSplashEffect, "Wm_mr_sandsplash", 0, &pos, nullptr, nullptr);
2328 }
2329 if (isNowBgCross(BGC_IN_SINK_SAND)) {
2330 mVec3_c pos = getCenterPos();
2331 dEf::createPlayerEffect(mPlayerNo, &mQuicksandSinkEffect, "Wm_mr_quicksand", 0, &pos, nullptr, nullptr);
2332 }
2333 if (isOnSinkSand() && !wasOnSinkSand()) {
2334 if (mPos.y > mSinkSandHeight - 8.0f && mPrevSpeedY < 0.0f) {
2335 int idx = 2;
2336 if ((mPrevSpeedY < -4.0f || mAirTopHeight > mSinkSandHeight + 58.0f) && mPowerup != POWERUP_MINI_MUSHROOM) {
2337 mSpeedF = 0.0f;
2338 idx = (mPowerup == POWERUP_NONE) ? 1 : 0;
2339 }
2340 mVec3_c pos(
2341 mPos.x,
2342 mSinkSandHeight,
2343 mPos.z
2344 );
2345 static const char *scSandDiveEffectID[] = {
2346 "Wm_mr_sanddive",
2347 "Wm_mr_sanddive_m",
2348 "Wm_mr_sanddive_s"
2349 };
2350 dEf::createPlayerEffect(mPlayerNo, scSandDiveEffectID[idx], 0, &pos, nullptr, nullptr);
2351 }
2352 }
2353}
2354
2355bool daPlBase_c::setSandJumpEffect() {
2356 if (isOnSinkSand() && mPos.y + getModelHeight() + 16.0f > mSinkSandHeight) {
2357 mVec3_c pos = mPos;
2358 pos.y = mSinkSandHeight;
2359 dEf::createPlayerEffect(mPlayerNo, "Wm_mr_sanddive_s", 0, &pos, nullptr, nullptr);
2360 return true;
2361 }
2362 return false;
2363}
2364
2365void daPlBase_c::setSoundPlyMode() {
2366 static const int scPlayerSound[] = {
2367 0, 1, 2, 3, 4, 5, 1
2368 };
2369 mSndObj.m_04 = scPlayerSound[mPowerup];
2370}
2371
2372void daPlBase_c::setFootSound() {
2373 if (
2374 (isDemo() || isNowBgCross(BGC_FOOT)) &&
2375 dScStage_c::m_gameMode != dInfo_c::GAME_MODE_TITLE &&
2376 mpMdlMng->mpMdl->isFootStepTiming()
2377 ) {
2378 if (mPowerup == POWERUP_PENGUIN_SUIT) {
2379 startFootSoundPlayer(SE_PLY_FOOTNOTE_PNGN);
2380 return;
2381 }
2382 static const dAudio::SoundEffectID_t scFootSeID[] = {
2383 SE_PLY_FOOTNOTE_ROCK,
2384 SE_PLY_FOOTNOTE_SNOW,
2385 SE_PLY_FOOTNOTE_SAND,
2386 SE_PLY_FOOTNOTE_ROCK,
2387 SE_PLY_FOOTNOTE_DIRT,
2388 SE_PLY_FOOTNOTE_WATER,
2389 SE_PLY_FOOTNOTE_CLOUD,
2390 SE_PLY_FOOTNOTE_BLOWSAND,
2391 SE_PLY_FOOTNOTE_MANTA,
2392 SE_PLY_FOOTNOTE_SAND,
2393 SE_PLY_FOOTNOTE_CARPET,
2394 SE_PLY_FOOTNOTE_LEAF,
2395 SE_PLY_FOOTNOTE_WOOD
2396 };
2397 startFootSoundPlayer(scFootSeID[mGroundType]);
2398 }
2399}
2400
2402STATE_VIRTUAL_DEFINE(daPlBase_c, DemoStartWait);
2404STATE_VIRTUAL_DEFINE(daPlBase_c, DemoInDokanU);
2405STATE_VIRTUAL_DEFINE(daPlBase_c, DemoInDokanD);
2406STATE_VIRTUAL_DEFINE(daPlBase_c, DemoInDokanR);
2407STATE_VIRTUAL_DEFINE(daPlBase_c, DemoInDokanL);
2408STATE_VIRTUAL_DEFINE(daPlBase_c, DemoOutDokanU);
2409STATE_VIRTUAL_DEFINE(daPlBase_c, DemoOutDokanD);
2410STATE_VIRTUAL_DEFINE(daPlBase_c, DemoOutDokanR);
2411STATE_VIRTUAL_DEFINE(daPlBase_c, DemoOutDokanL);
2412STATE_VIRTUAL_DEFINE(daPlBase_c, DemoOutDokanRoll);
2413STATE_VIRTUAL_DEFINE(daPlBase_c, DemoInWaterTank);
2414STATE_VIRTUAL_DEFINE(daPlBase_c, DemoOutWaterTank);
2415STATE_VIRTUAL_DEFINE(daPlBase_c, DemoRailDokan);
2417STATE_VIRTUAL_DEFINE(daPlBase_c, DemoNextGotoBlock);
2419STATE_VIRTUAL_DEFINE(daPlBase_c, DemoControl);
2420
2421void daPlBase_c::initialDokanUnder() {
2422 changeDemoState(StateID_DemoInDokanD, DOKAN_TYPE_NORMAL);
2423}
2424void daPlBase_c::initialDokanUper() {
2425 changeDemoState(StateID_DemoInDokanU, DOKAN_TYPE_NORMAL);
2426}
2427void daPlBase_c::initialDokanRight() {
2428 changeDemoState(StateID_DemoInDokanR, DOKAN_TYPE_NORMAL);
2429}
2430void daPlBase_c::initialDokanLeft() {
2431 changeDemoState(StateID_DemoInDokanL, DOKAN_TYPE_NORMAL);
2432}
2433
2434void daPlBase_c::initialDokanUnderM() {
2435 changeDemoState(StateID_DemoInDokanD, DOKAN_TYPE_MINI);
2436}
2437void daPlBase_c::initialDokanUperM() {
2438 changeDemoState(StateID_DemoInDokanU, DOKAN_TYPE_MINI);
2439}
2440void daPlBase_c::initialDokanRightM() {
2441 changeDemoState(StateID_DemoInDokanR, DOKAN_TYPE_MINI);
2442}
2443void daPlBase_c::initialDokanLeftM() {
2444 changeDemoState(StateID_DemoInDokanL, DOKAN_TYPE_MINI);
2445}
2446
2447void daPlBase_c::initialDokanDepth() {
2448 changeDemoState(StateID_DemoInWaterTank, DOKAN_TYPE_NORMAL);
2449}
2450
2451void daPlBase_c::initialDoor() {}
2452void daPlBase_c::initialJumpRight() {}
2453void daPlBase_c::initialJumpLeft() {}
2454void daPlBase_c::initialVine() {}
2455
2456void daPlBase_c::initialFall() {
2457 changeState(StateID_Fall, false);
2459 mSpeed.y = -1.0f;
2460 bgCheck(0);
2461}
2462
2463void daPlBase_c::initialHipAttack() {
2465 changeDemoState(StateID_DemoWait, DEMO_WAIT_ARG_TO_NONE);
2466}
2467
2468void daPlBase_c::initialSlip() {
2470 setSlipAction();
2471 changeDemoState(StateID_DemoWait, DEMO_WAIT_ARG_TO_CONTROL);
2472}
2473
2474void daPlBase_c::initialSwim() {}
2475
2476void daPlBase_c::initialTorideBoss() {
2477 initialNormal();
2478 startControlDemo();
2479}
2480
2481void daPlBase_c::initialBlockJump() {}
2482void daPlBase_c::initialBlockJumpBelow() {}
2483
2484void daPlBase_c::initialNormal() {
2487 mSpeed.y = -1.0f;
2488 bgCheck(0);
2489}
2490
2491void daPlBase_c::setCreateAction(int action) {
2492 static ProcFunc l_createActionProc[] = {
2493 &daPlBase_c::initialNormal,
2494 &daPlBase_c::initialNormal,
2495 &daPlBase_c::initialDoor,
2496 &daPlBase_c::initialDokanUnder,
2497 &daPlBase_c::initialDokanUper,
2498 &daPlBase_c::initialDokanRight,
2499 &daPlBase_c::initialDokanLeft,
2500 &daPlBase_c::initialFall,
2501 &daPlBase_c::initialHipAttack,
2502 &daPlBase_c::initialSlip,
2503 &daPlBase_c::initialSwim,
2504 &daPlBase_c::initialNormal,
2505 &daPlBase_c::initialNormal,
2506 &daPlBase_c::initialNormal,
2507 &daPlBase_c::initialDoor,
2508 &daPlBase_c::initialDoor,
2509 &daPlBase_c::initialDokanUnderM,
2510 &daPlBase_c::initialDokanUperM,
2511 &daPlBase_c::initialDokanRightM,
2512 &daPlBase_c::initialDokanLeftM,
2513 &daPlBase_c::initialJumpRight,
2514 &daPlBase_c::initialVine,
2515 &daPlBase_c::initialDokanDepth,
2516 &daPlBase_c::initialTorideBoss,
2517 &daPlBase_c::initialJumpLeft,
2518 &daPlBase_c::initialBlockJump,
2519 &daPlBase_c::initialBlockJumpBelow,
2520 &daPlBase_c::initialNormal
2521 };
2522 (this->*l_createActionProc[action])();
2523}
2524
2525bool daPlBase_c::isDemoType(DemoType_e type) {
2526 switch (type) {
2527 case DEMO_1:
2528 if (isDemoMode() && isStatus(STATUS_OUT_OF_PLAY)) {
2529 return true;
2530 }
2531 break;
2532 case DEMO_2:
2533 if (isChange()) {
2534 return true;
2535 }
2536 break;
2537 case DEMO_3:
2538 if (isStatus(STATUS_DEMO_NEXT_GOTO_BLOCK) || isDemoMode()) {
2539 return true;
2540 }
2541 break;
2542 case DEMO_PLAYER:
2543 if (!isItemKinopio() && (isStatus(STATUS_72) || isStatus(STATUS_71)) && mDemoState >= CONTROL_DEMO_WAIT && mDemoState <= CONTROL_DEMO_4) {
2544 return true;
2545 }
2546 break;
2547 case DEMO_KINOPIO:
2548 if (isItemKinopio() && (isStatus(STATUS_72) || isStatus(STATUS_71)) && mDemoState >= CONTROL_DEMO_WAIT && mDemoState <= CONTROL_DEMO_KINOPIO_SINK_SAND) {
2549 return true;
2550 }
2551 break;
2552 case DEMO_ENDING_DANCE:
2553 if ((isStatus(STATUS_72) || isStatus(STATUS_71)) && mDemoState == CONTROL_DEMO_ENDING_DANCE) {
2554 return true;
2555 }
2556 break;
2557 default:
2558 break;
2559 }
2560 return false;
2561}
2562
2563bool daPlBase_c::isDemo() {
2564 if (isDemoType(DEMO_1) || isDemoType(DEMO_2) || isDemoType(DEMO_3)) {
2565 return true;
2566 }
2567 return false;
2568}
2569
2570bool daPlBase_c::isControlDemoAll() {
2571 if (isDemoType(DEMO_PLAYER) || isDemoType(DEMO_KINOPIO) || isDemoType(DEMO_ENDING_DANCE)) {
2572 return true;
2573 }
2574 return false;
2575}
2576
2577bool daPlBase_c::isDemoAll() {
2578 if (isDemo() || isControlDemoAll()) {
2579 return true;
2580 }
2581 return false;
2582}
2583
2584bool daPlBase_c::isDemoMode() const {
2585 return mIsDemoMode != false;
2586}
2587
2588void daPlBase_c::onDemo() {
2589 if (mPlayerNo == -1) {
2590 return;
2591 }
2592 daPlBase_c *pl = daPyMng_c::getPlayer(mPlayerNo);
2593 if (pl != nullptr && !pl->isItemKinopio()) {
2594 daPyMng_c::mPauseEnableInfo &= ~(1 << mPlayerNo);
2595 daPyMng_c::mStopTimerInfo |= (1 << mPlayerNo);
2596 }
2597 mIsDemoMode = true;
2598}
2599
2600void daPlBase_c::offDemo() {
2601 if (mPlayerNo == -1) {
2602 return;
2603 }
2604 daPlBase_c *pl = daPyMng_c::getPlayer(mPlayerNo);
2605 if (pl != nullptr && !pl->isItemKinopio()) {
2606 daPyMng_c::mPauseEnableInfo |= (1 << mPlayerNo);
2607 daPyMng_c::mStopTimerInfo &= ~(1 << mPlayerNo);
2608 }
2609 mIsDemoMode = false;
2610}
2611
2612void daPlBase_c::changeNextScene(int param1) {
2613 onStatus(STATUS_64);
2614 daPyMng_c::mPauseDisable = true;
2615 daPyDemoMng_c::mspInstance->setCourseOutList(mPlayerNo);
2616 if (mPlayerNo == daPyDemoMng_c::mspInstance->m_70) {
2618 daPyDemoMng_c::mspInstance->mPlayerNo = mPlayerNo;
2619 }
2620 if (param1 == 1) {
2621 daPlBase_c *pl = daPyMng_c::getPlayer(mPlayerNo);
2622 if (pl != nullptr) {
2624 }
2625 daPlBase_c *yoshi = daPyMng_c::getYoshi(mPlayerNo);
2626 if (yoshi != nullptr) {
2628 }
2629 }
2630}
2631
2632bool daPlBase_c::isPlayerGameStop() {
2633 return (dInfo_c::mGameFlag >> 1) & 1;
2634}
2635
2636void daPlBase_c::stopOther() {
2637 if (!isPlayerGameStop()) {
2638 return;
2639 }
2641 if (mPlayerNo != -1) {
2642 daPlBase_c *pl = daPyMng_c::getPlayer(mPlayerNo);
2643 if (pl != nullptr) {
2644 pl->mExecStopMask &= ~2;
2645 }
2646 daPlBase_c *yoshi = daPyMng_c::getYoshi(mPlayerNo);
2647 if (yoshi != nullptr) {
2648 yoshi->mExecStopMask &= ~2;
2649 }
2650 } else if (mKind == STAGE_ACTOR_YOSHI) {
2651 mExecStopMask &= ~4;
2652 }
2653}
2654
2655void daPlBase_c::playOther() {
2656 dActor_c::mExecStopReq &= ~0xf;
2657 if (mPlayerNo != -1) {
2658 daPlBase_c *pl = daPyMng_c::getPlayer(mPlayerNo);
2659 if (pl != nullptr) {
2660 pl->mExecStopMask |= 2;
2661 }
2662 daPlBase_c *yoshi = daPyMng_c::getYoshi(mPlayerNo);
2663 if (yoshi != nullptr) {
2664 yoshi->mExecStopMask |= 2;
2665 }
2666 } else if (mKind == STAGE_ACTOR_YOSHI) {
2667 mExecStopMask |= 4;
2668 }
2669}
2670
2671void daPlBase_c::changeNormalAction() {
2672 bgCheck(0);
2673 offZPosSetNone();
2676}
2677
2678bool daPlBase_c::checkTimeOut() {
2679 if (dStageTimer_c::m_instance->convertToIGT() == 0) {
2680 if (setTimeOverDemo()) {
2681 return true;
2682 }
2683 }
2684 return false;
2685}
2686
2687void daPlBase_c::changeDemoState(const sStateIDIf_c &stateID, int arg) {
2688 if (stateID == StateID_DemoNone && isItemKinopio()) {
2689 changeDemoState(StateID_DemoControl, CONTROL_DEMO_KINOPIO_WALK);
2690 } else {
2691 onDemo();
2692 mDemoSubstate = 0;
2693 mDemoStateArg = arg;
2694 mDemoStateMgr.changeState(stateID);
2695 }
2696}
2697
2698bool daPlBase_c::executeDemoState() {
2699 offStatus(STATUS_79);
2700 if (mDemoSubstateTimer != 0) {
2702 }
2703 mDemoStateMgr.executeState();
2704 if (isStatus(STATUS_71)) {
2705 if (isDemoState(StateID_DemoNone)) {
2706 changeDemoState(StateID_DemoControl, CONTROL_DEMO_WAIT);
2707 }
2708 }
2709 if (!isDemoMode()) {
2710 return false;
2711 }
2712 if (isStatus(STATUS_79)) {
2713 onStatus(STATUS_77);
2714 }
2715 return true;
2716}
2717
2718void daPlBase_c::initializeState_DemoNone() {
2719 mDemoSubstateTimer = 15;
2720 daPyDemoMng_c::mspInstance->clearDemoNo(mPlayerNo);
2721 offDemo();
2722 if (mDemoStateArg != 1) {
2723 playOther();
2724 }
2726}
2727
2728void daPlBase_c::finalizeState_DemoNone() {}
2729
2730void daPlBase_c::executeState_DemoNone() {
2732 if (isDemoMode()) {
2733 offDemo();
2734 }
2735 if (mPlayerNo == daPyDemoMng_c::mspInstance->getPlrNo()) {
2736 daPyDemoMng_c::mspInstance->setPlrNo(-1);
2737 }
2738 }
2739 if (checkTimeOut()) {
2740 return;
2741 }
2742 if (isNowBgCross(BGC_FOOT) || isStatus(STATUS_SWIM)) {
2743 if (mKey.buttonRight()) {
2747 }
2748 } else {
2749 mDokanCounterR = 0;
2750 }
2751 if (mKey.buttonLeft()) {
2755 }
2756 } else {
2757 mDokanCounterL = 0;
2758 }
2759 } else {
2760 mDokanCounterR = 0;
2761 mDokanCounterL = 0;
2762 }
2763 if (mDemoSubstateTimer == 0 && isEnableDokanInStatus()) {
2764 if (setDokanIn(DOKAN_D)) {
2765 return;
2766 }
2767 if (setDokanIn(DOKAN_U)) {
2768 return;
2769 }
2770 if (mDokanCounterR >= sc_DokanEnterThreshold && mDirection == DIR_LR_R) {
2771 if (setDokanIn(DOKAN_R)) {
2772 return;
2773 }
2774 }
2775 if (mDokanCounterL >= sc_DokanEnterThreshold && mDirection == DIR_LR_L) {
2776 if (setDokanIn(DOKAN_L)) {
2777 return;
2778 }
2779 }
2780 if (mKey.buttonDown()) {
2781 onStatus(STATUS_A4);
2782 }
2783 }
2784}
2785
2786void daPlBase_c::initializeState_DemoStartWait() {}
2787
2788void daPlBase_c::executeState_DemoStartWait() {
2789 if (dScStage_c::m_gameMode == dInfo_c::GAME_MODE_TITLE) {
2791 } else {
2793 bgCheck(0);
2795 }
2796 }
2797}
2798
2799void daPlBase_c::finalizeState_DemoStartWait() {}
2800
2801void daPlBase_c::initializeState_DemoWait() {
2802 if (daPyDemoMng_c::mspInstance->checkDemoNo(mPlayerNo)) {
2803 mDemoSubstate = DEMO_WAIT_TRANSITION;
2805 } else {
2806 mDemoSubstate = DEMO_WAIT_DELAY;
2807 }
2808}
2809
2810void daPlBase_c::finalizeState_DemoWait() {}
2811
2812void daPlBase_c::executeState_DemoWait() {
2815 case DEMO_WAIT_DELAY:
2816 if (daPyDemoMng_c::mspInstance->checkDemoNo(mPlayerNo)) {
2817 mDemoSubstate = DEMO_WAIT_TRANSITION;
2819 }
2820 break;
2821 case DEMO_WAIT_TRANSITION:
2822 if (mDemoSubstateTimer == 0) {
2823 daPyDemoMng_c::mspInstance->turnNextDemoNo();
2824 switch ((DemoWaitArg_e) mDemoStateArg) {
2825 case DEMO_WAIT_ARG_TO_NONE:
2827 onDemo();
2828 bgCheck(0);
2829 break;
2830 case DEMO_WAIT_ARG_TO_CONTROL:
2831 changeDemoState(StateID_DemoControl, CONTROL_DEMO_4);
2832 break;
2833 }
2834 }
2835 break;
2836 }
2837 }
2838}
2839
2840const float daPlBase_c::scDokanInSpeedX = 1.0f;
2841const float daPlBase_c::scDokanInWidthX = 0.0f;
2842const float daPlBase_c::scDokanInMoveSpeed = 0.75f;
2843const float daPlBase_c::scDokanWaitAnmFixFrame = 85.0f;
2844
2845namespace {
2846 const float scDokanOutTurnSpeed[] = { 2048.0f };
2847}
2848
2850 /// @unofficial
2851 static const float l_maxOffsets[] = { 12.0f, 15.0f, 13.0f, 13.0f };
2852 float max = 16.0f;
2853 if (mKind == 1) {
2854 max = l_maxOffsets[mPlayerType];
2855 }
2856 float pos = getCenterY() - mPos.y;
2857 if (pos > max) {
2858 pos = max;
2859 }
2860 return param1 + 16.0f - pos;
2861}
2862
2863void daPlBase_c::initDemoInDokan() {
2864 onStatus(STATUS_5E);
2865 mSpeedF = 0.0f;
2866 mSpeed.y = 0.0f;
2867 setZPosition(-1800.0f);
2868 if (mDemoStateArg == DOKAN_TYPE_CONNECTED) {
2869 mDamageInvulnTimer = 0;
2870 } else {
2871 mDamageInvulnTimer = 35;
2872 if (daPyDemoMng_c::mspInstance->checkDemoNo(mPlayerNo)) {
2873 stopOther();
2874 }
2875 }
2876 mDemoSubstate = 0;
2877}
2878
2879void daPlBase_c::endDemoInDokan() {
2880 mDamageInvulnTimer = 0;
2881 mPowerupChangeInvulnTimer = 0;
2884 offStatus(STATUS_5E);
2885}
2886
2887void daPlBase_c::executeDemoInDokan(u8 dir) {
2888 // 0: Play the pipe sound effect
2889 // 1: Wait for a bit
2890 // 2: Move the player out of the pipe
2891 // 3: Finalize the transition
2892 switch (mDemoSubstate) {
2893 case 0:
2895 break;
2896 }
2897 if (!daPyDemoMng_c::mspInstance->checkDemoNo(mPlayerNo)) {
2898 break;
2899 }
2901 mDemoSubstate = 1;
2902 mDemoSubstateTimer = 40;
2903 if (mBc.checkWater(mWarpPos.x, mWarpPos.y, mLayer, nullptr)) {
2904 onNowBgCross(BGC_WATER_SHALLOW);
2905 }
2906 if (isNowBgCross(BGC_WATER_SHALLOW)) {
2907 if (isDemoState(StateID_DemoInDokanL) || isDemoState(StateID_DemoInDokanR)) {
2908 mpMdlMng->setAnm(PLAYER_ANIM_SWIM_PIPE);
2909 if (mDemoStateArg != DOKAN_TYPE_CONNECTED) {
2911 mWarpPos.y = mPos.y;
2912 }
2913 }
2914 startSound(SE_PLY_WATER_DOKAN_IN_OUT, false);
2915 } else {
2916 startSound(SE_PLY_DOKAN_IN_OUT, false);
2917 }
2918 break;
2919 case 1:
2920 if (mDemoSubstateTimer == 0) {
2921 daPyDemoMng_c::mspInstance->turnNextDemoNo();
2922 mDemoSubstate = 2;
2923 }
2924 case 2:
2925 onStatus(STATUS_79);
2926 if (isStatus(STATUS_PROPEL_NO_ROLL) && (dir == 2 || dir == 3) && std::fabs(mPos.x - mWarpPos.x) <= 20.0f) {
2928 }
2929 if (isStatus(STATUS_5E) && std::fabs(mPos.x - mWarpPos.x) <= 20.0f) {
2930 offStatus(STATUS_5E);
2931 }
2932 if (!demo_dokan_move_x(0.75f, 0.0f)) {
2933 break;
2934 }
2935 if (!demo_dokan_move_y(0.75f, 0.0f)) {
2936 break;
2937 }
2938 if (mDemoSubstate == 1) {
2939 daPyDemoMng_c::mspInstance->turnNextDemoNo();
2940 }
2941 mDemoSubstate = 3;
2942 break;
2943 case 3:
2944 if (!mKey.buttonWalk(nullptr)) {
2945 if (!mAngle.y.chase(getMukiAngle(mDirection), scDokanOutTurnSpeed[0])) {
2946 break;
2947 }
2948 }
2949 changeNormalAction();
2950 if (isNowBgCross(BGC_WATER_SHALLOW)) {
2951 onOldBgCross(BGC_WATER_SHALLOW);
2952 }
2953 break;
2954 }
2955}
2956
2958 /// @unofficial
2959 static const float tmps[] = { 34.0f, 36.0f, 38.0f, 38.0f };
2960 /// @unofficial
2961 static const float tmps_big[] = { 40.0f, 42.0f, 44.0f, 44.0f };
2962 mpMdlMng->setAnm(PLAYER_ANIM_WAIT);
2963 mWarpPos = mPos;
2964 if (dir == 1) {
2965 if (mDemoStateArg == DOKAN_TYPE_MINI) {
2966 mWarpPos.y = mPos.y + 16.0f;
2967 } else {
2968 mWarpPos.y = mPos.y + 32.0f;
2969 }
2970 if (mKind == STAGE_ACTOR_YOSHI) {
2971 mPos.y -= 16.0f;
2972 } else {
2973 mPos.y -= 8.0f;
2974 }
2975 } else {
2977 float tmp;
2978 if (mKind == STAGE_ACTOR_YOSHI) {
2979 tmp = 30.0f;
2980 daPlBase_c *pl = ((daYoshi_c *) this)->getPlayerRideOn();
2981 if (pl != nullptr) {
2982 int t = pl->mPlayerType;
2983 switch (pl->mPowerup) {
2984 case POWERUP_NONE:
2985 tmp = tmps[t];
2986 break;
2987 case POWERUP_MINI_MUSHROOM:
2988 tmp = 30.0f;
2989 break;
2990 default:
2991 tmp = tmps_big[t];
2992 break;
2993 }
2994 }
2995 } else {
2996 switch (mPowerup) {
2997 case POWERUP_NONE:
2998 tmp = 20.0f;
2999 break;
3000 case POWERUP_MINI_MUSHROOM:
3001 tmp = 12.0f;
3002 break;
3003 case POWERUP_PROPELLER_SHROOM:
3004 tmp = getModelHeight() + 8.0f;
3005 break;
3006 default:
3007 tmp = getModelHeight();
3008 break;
3009 }
3010 }
3011 mWarpPos.y = -tmp + mPos.y;
3012 mPos.y += 2.0f;
3013 }
3014 if (mKind == STAGE_ACTOR_YOSHI) {
3015 mAngle.y = 0;
3016 }
3017 initDemoInDokan();
3018}
3019
3020void daPlBase_c::initDemoInDokanLR(u8 dir) {
3021 static const float l_dokanOffset[] = { 32.0f, 32.0f, 20.0f };
3022 mpMdlMng->setAnm(PLAYER_ANIM_LOW_WALK);
3024 if (dir == DOKAN_R) {
3025 mPos.x += 8.0f;
3026 } else {
3027 mPos.x -= 8.0f;
3028 }
3029 float tmp;
3030 if (mKind == STAGE_ACTOR_YOSHI) {
3031 tmp = 32.0f;
3032 } else {
3033 tmp = l_dokanOffset[mDemoStateArg];
3034 }
3035 if (dir == 3) {
3036 tmp = -tmp;
3037 }
3038 mWarpPos.set(mPos.x + tmp, mPos.y, mPos.z);
3039 if (dir == DOKAN_R) {
3040 mDirection = DIR_LR_L;
3041 } else {
3042 mDirection = DIR_LR_R;
3043 }
3044 mAngle.y = getMukiAngle(mDirection);
3045 initDemoInDokan();
3046}
3047
3048void daPlBase_c::initializeState_DemoInDokanU() { initDemoInDokanUD(DOKAN_U); }
3049void daPlBase_c::finalizeState_DemoInDokanU() { endDemoInDokan(); }
3050void daPlBase_c::executeState_DemoInDokanU() { executeDemoInDokan(DOKAN_U); }
3051
3052void daPlBase_c::initializeState_DemoInDokanD() { initDemoInDokanUD(DOKAN_D); }
3053void daPlBase_c::finalizeState_DemoInDokanD() { endDemoInDokan(); }
3054void daPlBase_c::executeState_DemoInDokanD() { executeDemoInDokan(DOKAN_D); }
3055
3056void daPlBase_c::initializeState_DemoInDokanL() { initDemoInDokanLR(DOKAN_L); }
3057void daPlBase_c::finalizeState_DemoInDokanL() { endDemoInDokan(); }
3058void daPlBase_c::executeState_DemoInDokanL() { executeDemoInDokan(DOKAN_L); }
3059
3060void daPlBase_c::initializeState_DemoInDokanR() { initDemoInDokanLR(DOKAN_R); }
3061void daPlBase_c::finalizeState_DemoInDokanR() { endDemoInDokan(); }
3062void daPlBase_c::executeState_DemoInDokanR() { executeDemoInDokan(DOKAN_R); }
3063
3064BOOL daPlBase_c::demo_dokan_move_x(float moveStep, float epsilon) {
3065 sLib::chase(&mPos.x, mWarpPos.x, moveStep);
3066 return std::fabs(mPos.x - mWarpPos.x) <= epsilon;
3067}
3068
3069BOOL daPlBase_c::demo_dokan_move_y(float moveStep, float offset) {
3070 return sLib::chase(&mPos.y, mWarpPos.y + offset, moveStep);
3071}
3072
3073bool daPlBase_c::isEnableDokanInStatus() {
3074 if (isDemo()) {
3075 return false;
3076 }
3077 if (
3081 isStatus(STATUS_53)
3082 ) {
3083 return false;
3084 }
3085 return true;
3086}
3087
3088bool daPlBase_c::setDokanIn(DokanDir_e dir) {
3089 if (isStatus(STATUS_7E)) {
3090 return false;
3091 }
3092 int res = 0;
3093 int entranceNextGotoID;
3094 switch (dir) {
3095 case DOKAN_D:
3096 if (mKey.buttonDown()) {
3097 res = mBc.checkDokanDown(&mWarpPos, &entranceNextGotoID);
3098 }
3099 break;
3100 case DOKAN_U:
3101 if (mKey.buttonUp()) {
3102 res = mBc.checkDokanUp(&mWarpPos, &entranceNextGotoID);
3103 }
3104 break;
3105 case DOKAN_L:
3106 case DOKAN_R: {
3107 float x = 0.0f;
3108 float y = x;
3109 if (isStatus(STATUS_SWIM)) {
3110 x = 2.0f;
3111 y = -2.0f;
3112 } else {
3113 if (isStatus(STATUS_17)) {
3114 x = 8.0f;
3115 y = 8.0f;
3116 }
3117 }
3118 res = mBc.checkDokanLR(&mWarpPos, mDirection, &entranceNextGotoID, x, y);
3119 break;
3120 }
3121 case DOKAN_ROLL:
3122 break;
3123 }
3124 if (res == 1 && setDemoOutDokanAction(entranceNextGotoID, dir)) {
3125 return true;
3126 }
3127 return false;
3128}
3129
3130bool daPlBase_c::setDemoOutDokanAction(int entranceNextGotoID, DokanDir_e dir) {
3131 mDokanEnterNextGotoID = entranceNextGotoID;
3132 dCdFile_c *cdFile = dCd_c::m_instance->getFileP(dScStage_c::m_instance->mCurrFile);
3133 sNextGotoData *nextGoto = cdFile->getNextGotoP(mDokanEnterNextGotoID);
3134
3135 mDokanMode = DEMO_DOKAN_NORMAL;
3136 if (nextGoto->mFlags & NEXT_GOTO_FLAG_RAIL) {
3137 mDokanMode = DEMO_DOKAN_RAIL;
3138 } else if (nextGoto->mFlags & NEXT_GOTO_FLAG_WATER_TANK) {
3139 mDokanMode = DEMO_DOKAN_WATER_TANK;
3140 }
3141
3142 static sStateIDIf_c *l_dokanInAction[] = {
3148 };
3149 switch (mDokanMode) {
3150 case DEMO_DOKAN_NORMAL:
3151 if (dNext_c::m_instance->isNextDifferent(dScStage_c::m_instance->mCurrFile, mDokanEnterNextGotoID)) {
3152 return false;
3153 }
3154 if (daPyDemoMng_c::mspInstance->m_5c) {
3155 return false;
3156 }
3157 dNext_c::m_instance->setChangeSceneNextDat(dScStage_c::m_instance->mCurrFile, mDokanEnterNextGotoID, dFader_c::FADER_CIRCLE_TARGET);
3158 if (nextGoto->mType == NEXT_GOTO_TYPE_WATER_TANK) {
3160 } else {
3161 changeDemoState(*l_dokanInAction[dir]);
3162 }
3163 return true;
3164 case DEMO_DOKAN_RAIL:
3165 dRail_c::getRailInfoP(nextGoto->mRailID); // [Unused return value]
3166 changeDemoState(*l_dokanInAction[dir]);
3167 return true;
3168 case DEMO_DOKAN_WATER_TANK:
3169 if (nextGoto->mType == NEXT_GOTO_TYPE_WATER_TANK) {
3171 } else {
3172 changeDemoState(*l_dokanInAction[dir]);
3173 }
3174 return true;
3175 }
3176 return false;
3177}
3178
3179void daPlBase_c::initDemoOutDokan() {
3180 mSpeedF = 0.0f;
3181 mMaxSpeedF = 0.0f;
3182 mSpeed.set(0.0f, 0.0f, 0.0f);
3183 mAngle.x = 0.0f;
3184 setZPosition(-1800.0f);
3185 if (isNowBgCross(BGC_WATER_SHALLOW)) {
3186 startSound(SE_PLY_WATER_DOKAN_IN_OUT, false);
3187 } else {
3188 startSound(SE_PLY_DOKAN_IN_OUT, false);
3189 }
3190}
3191
3192void daPlBase_c::endDemoOutDokan() {
3194 offStatus(STATUS_5E);
3195}
3196
3197void daPlBase_c::initDemoOutDokanUD(u8 dir) {
3198 mDokanDir = dir;
3199 changeState(StateID_Walk, nullptr);
3200 mpMdlMng->setAnm(PLAYER_ANIM_WAIT, 0.0f, 5.0f, 85.0f);
3201 if (mDokanMode == DEMO_DOKAN_RAIL) {
3202 if (dir == DOKAN_U) {
3203 mDokanOffsetY = 0.0f;
3204 } else {
3205 mDokanOffsetY = -34.0f;
3206 }
3207 } else if (dir == DOKAN_U) {
3208 mDokanOffsetY = 2.0f;
3209 } else if (mKind == STAGE_ACTOR_YOSHI) {
3210 mDokanOffsetY = -16.0f;
3211 } else {
3212 mDokanOffsetY = -10.0f;
3213 }
3214 mDokanShiftXEpsilon = 0.0f;
3215 if (mDokanMode == DEMO_DOKAN_NORMAL && daPyMng_c::mNum == 1) {
3216 stopOther();
3217 }
3218 initDemoOutDokan();
3219}
3220
3221void daPlBase_c::executeDemoOutDokanUD() {
3222 // 0: Move to the center of the pipe
3223 // 1: Move into the pipe
3224 // 2: Water tank only: move to Y target, then transition to in-tank state
3225 // 3: Done
3226 switch (mDemoSubstate) {
3227 case 0: {
3228 int cond = 0;
3229 if (mKind == STAGE_ACTOR_YOSHI) {
3230 if (mAngle.y.chase(0, scDokanOutTurnSpeed[0])) {
3231 cond = 1;
3232 }
3233 } else {
3234 if (mAngle.y.chase(getMukiAngle(mDirection), 0x2000)) {
3235 cond = 1;
3236 }
3237 }
3238 if (demo_dokan_move_x(1.0f, mDokanShiftXEpsilon) && cond == 1) {
3239 mDemoSubstate = 1;
3240 mDemoSubstateTimer = 10;
3241 }
3242 break;
3243 }
3244 case 1:
3245 if (demo_dokan_move_y(0.75f, mDokanOffsetY)) {
3246 onStatus(STATUS_5E);
3247 switch (mDokanMode) {
3248 case DEMO_DOKAN_RAIL:
3250 break;
3251 case DEMO_DOKAN_WATER_TANK:
3253 mLayer = 0;
3254 if (mDokanDir == DOKAN_U) {
3255 mWarpPos.y = mPos.y + 80.0f;
3256 } else {
3257 mWarpPos.y = mPos.y - 80.0f;
3258 }
3259 mDemoSubstate = 2;
3260 break;
3261 default:
3262 changeNextScene(1);
3263 mDemoSubstate = 3;
3264 break;
3265 }
3266 }
3267 break;
3268 case 2:
3269 if (sLib::chase(&mPos.y, mWarpPos.y, 1.0f)) {
3270 changeState(StateID_Walk, nullptr);
3271 changeDemoState(StateID_DemoInWaterTank, DOKAN_TYPE_CONNECTED);
3272 }
3273 break;
3274 }
3275}
3276
3277void daPlBase_c::initDemoOutDokanLR(u8 dir) {
3278 mDokanDir = dir;
3279 if (isStatus(STATUS_SWIM)) {
3280 mpMdlMng->setAnm(PLAYER_ANIM_SWIM_PIPE);
3281 } else {
3282 mpMdlMng->setAnm(PLAYER_ANIM_LOW_WALK_START);
3283 }
3285 if (mDokanMode == DEMO_DOKAN_NORMAL && daPyMng_c::mNum == 1) {
3286 stopOther();
3287 }
3289 if (dir == DOKAN_R) {
3290 mWarpPos.x += 8.0f;
3291 } else {
3292 mWarpPos.x -= 8.0f;
3293 }
3294 }
3295 initDemoOutDokan();
3296}
3297
3298void daPlBase_c::executeDemoOutDokanLR() {
3299 // 0: Move into the pipe, possibly shifting in the Y direction if needed
3300 // 1: Water tank only: move to X target
3301 // 2: Water tank only: move down slightly
3302 // 3: Water tank only: move to final X target, then transition to in-tank state
3303 if (mpMdlMng->mpMdl->mAnm.isStop()) {
3304 mpMdlMng->setAnm(PLAYER_ANIM_LOW_WALK);
3305 }
3306 switch (mDemoSubstate) {
3307 case 0: {
3308 bool yTargetReached = false;
3309 if (!addCalcAngleY(getMukiAngle(mDirection), 10)) {
3310 float offset = 0.0f;
3311 if (isStatus(STATUS_SWIM)) {
3313 }
3314 if (demo_dokan_move_y(0.75f, offset)) {
3315 yTargetReached = true;
3316 }
3317 }
3318 if (yTargetReached && demo_dokan_move_x(0.75f, 0.0f)) {
3319 onStatus(STATUS_5E);
3320 switch (mDokanMode) {
3321 case DEMO_DOKAN_RAIL:
3323 break;
3324 case DEMO_DOKAN_WATER_TANK:
3326 mLayer = LAYER_1;
3327 mWarpPos.x = mPos.x + sc_DirSpeed[mDirection] * 48.0f;
3328 mDemoSubstate = 1;
3329 break;
3330 default:
3331 changeNextScene(1);
3332 break;
3333 }
3334 }
3335 break;
3336 }
3337 case 1:
3338 if (sLib::chase(&mPos.x, mWarpPos.x, 1.0f)) {
3339 mWarpPos.y -= 16.0f;
3340 mDemoSubstate = 2;
3341 }
3342 break;
3343 case 2:
3344 if (sLib::chase(&mPos.y, mWarpPos.y, 1.0f)) {
3345 mWarpPos.x = mPos.x + sc_DirSpeed[mDirection] * 32.0f;
3346 mDemoSubstate = 3;
3347 }
3348 break;
3349 case 3:
3350 if (sLib::chase(&mPos.x, mWarpPos.x, 1.0f)) {
3351 changeState(StateID_Walk, nullptr);
3352 changeDemoState(StateID_DemoInWaterTank, DOKAN_TYPE_CONNECTED);
3353 }
3354 break;
3355 }
3356}
3357
3358void daPlBase_c::initializeState_DemoOutDokanU() { initDemoOutDokanUD(DOKAN_U); }
3359void daPlBase_c::finalizeState_DemoOutDokanU() { endDemoOutDokan(); }
3360void daPlBase_c::executeState_DemoOutDokanU() { executeDemoOutDokanUD(); }
3361
3362void daPlBase_c::initializeState_DemoOutDokanD() { initDemoOutDokanUD(DOKAN_D); }
3363void daPlBase_c::finalizeState_DemoOutDokanD() { endDemoOutDokan(); }
3364void daPlBase_c::executeState_DemoOutDokanD() { executeDemoOutDokanUD(); }
3365
3366void daPlBase_c::initializeState_DemoOutDokanL() { initDemoOutDokanLR(DOKAN_L); }
3367void daPlBase_c::finalizeState_DemoOutDokanL() { endDemoOutDokan(); }
3368void daPlBase_c::executeState_DemoOutDokanL() { executeDemoOutDokanLR(); }
3369
3370void daPlBase_c::initializeState_DemoOutDokanR() { initDemoOutDokanLR(DOKAN_R); }
3371void daPlBase_c::finalizeState_DemoOutDokanR() { endDemoOutDokan(); }
3372void daPlBase_c::executeState_DemoOutDokanR() { executeDemoOutDokanLR(); }
3373
3374void daPlBase_c::initializeState_DemoOutDokanRoll() {
3375 initDemoOutDokanUD(DOKAN_ROLL);
3376 mDokanMode = DEMO_DOKAN_NORMAL;
3377 mDokanMoveSpeed.x = 0.0f;
3378 mDokanMoveSpeed.y = 0.0f;
3379 mBc.setRideOnObjBg(mpDokanBgCtr, mPos);
3380 mpDokanBgCtr->addDokanMoveDiff(&mWarpPos);
3381}
3382
3383void daPlBase_c::finalizeState_DemoOutDokanRoll() {}
3384
3385void daPlBase_c::executeState_DemoOutDokanRoll() {
3386 mBc.setRideOnObjBg(mpDokanBgCtr, mPos);
3387 mpDokanBgCtr->addDokanMoveDiff(&mWarpPos);
3388 mVec3_c warpPos(mWarpPos.x, mWarpPos.y, mPos.z);
3389 switch (mDemoSubstate) {
3390 case 0: {
3391 int cond = 0;
3392 if (mKind == STAGE_ACTOR_YOSHI) {
3393 if (mAngle.y.chase(0, scDokanOutTurnSpeed[0])) {
3394 cond = 1;
3395 }
3396 } else {
3397 if (mAngle.y.chase(getMukiAngle(mDirection), 0x2000)) {
3398 cond = 1;
3399 }
3400 }
3401 mVec3_c copy;
3402 mVec3_c diff1 = warpPos - mPos;
3403 copy.set(diff1.x, diff1.y, diff1.z);
3404 copy.normalize();
3405 mPos += 1.0f * copy;
3406
3407 if ((mPos - warpPos).isSmallerThan1()) {
3408 if (cond == 1) {
3409 mPos = warpPos;
3410 mDemoSubstate = 1;
3411 }
3412 }
3413 break;
3414 }
3415 case 1: {
3416 mAng v = *mpDokanBgCtr->mRotation;
3417 if (mDirection == DIR_LR_L) {
3418 v = -v;
3419 }
3420 sLib::addCalcAngle(&mAngle.x.mAngle, v.mAngle, 4, 0x1000, 0x100);
3421 float tmp = mDokanOffsetY + -32.0f;
3422 sLib::chase(&mDokanMoveSpeed.y, tmp, 0.75f);
3423 mMtx_c m1, m2;
3424 m1.trans(warpPos);
3425 m1.ZrotM(*mpDokanBgCtr->mRotation);
3426 m2.trans(0.0f, mDokanMoveSpeed.y, 0.0f);
3427 m1.concat(m2);
3428 m1.multVecZero(mPos);
3429 if (mDokanMoveSpeed.y <= tmp) {
3430 changeNextScene(1);
3431 mDemoSubstate = 3;
3433 }
3434 break;
3435 }
3436 }
3437}
3438
3439void daPlBase_c::initializeState_DemoInWaterTank() {
3442 mpMdlMng->setAnm(PLAYER_ANIM_LOW_WALK);
3443 mAngle.y = 0;
3444 if (mDemoStateArg == 1) {
3445 mDamageInvulnTimer = 0;
3446 mLayer = 0;
3447 setZPosition(3000.0f);
3448 } else {
3449 mDamageInvulnTimer = 35;
3450 if (daPyDemoMng_c::mspInstance->checkDemoNo(mPlayerNo)) {
3451 stopOther();
3452 }
3453 }
3454 mDemoSubstate = 0;
3455}
3456
3457void daPlBase_c::finalizeState_DemoInWaterTank() {}
3458
3459void daPlBase_c::executeState_DemoInWaterTank() {
3460 // 0: Animation in
3461 // 1: Wait for animation end, then change to normal action
3462 switch (mDemoSubstate) {
3463 case 0:
3465 break;
3466 }
3467 if (!daPyDemoMng_c::mspInstance->checkDemoNo(mPlayerNo)) {
3468 break;
3469 }
3471 mDemoSubstate = 1;
3472 mDemoSubstateTimer = 60;
3473 clearNowBgCross();
3474 checkWater();
3475 if (isNowBgCross(BGC_WATER_SHALLOW)) {
3476 mpMdlMng->setAnm(PLAYER_ANIM_SWIM_PIPE);
3478 startSound(SE_PLY_WATER_DOKAN_IN_OUT, false);
3479 } else {
3480 startSound(SE_PLY_DOKAN_IN_OUT, false);
3481 }
3482 break;
3483 case 1:
3484 if (mDemoSubstateTimer == 0) {
3485 changeNormalAction();
3486 }
3487 break;
3488 }
3489}
3490
3491void daPlBase_c::initializeState_DemoOutWaterTank() {
3492 mpMdlMng->setAnm(PLAYER_ANIM_WAIT);
3493 mSpeedF = 0.0f;
3494 mMaxSpeedF = 0.0f;
3495 mSpeed.set(0.0f, 0.0f, 0.0f);
3496 mAngle.x = 0.0f;
3497 mAngle.y = 0x8000;
3498}
3499
3500void daPlBase_c::finalizeState_DemoOutWaterTank() {}
3501
3502void daPlBase_c::executeState_DemoOutWaterTank() {
3503 // 0: Shift towards the center of the pipe
3504 // 1: Wait for animation to finish
3505 // 2: Move inside of the pipe horizontally
3506 // 3: Move down the pipe vertically
3507 // 4: Move to the final target position, then switch to the pipe exit state
3508 switch (mDemoSubstate) {
3509 case 0:
3510 if (sLib::chase(&mPos.x, mWarpPos.x, 1.0f)) {
3511 mpMdlMng->setAnm(PLAYER_ANIM_LOW_WALK_START);
3512 startSound(SE_PLY_DOKAN_IN_OUT, false);
3513 mDemoSubstateTimer = 60;
3514 mDemoSubstate = 1;
3515 }
3516 break;
3517 case 1:
3518 if (mpMdlMng->mpMdl->mAnm.isStop()) {
3519 mpMdlMng->setAnm(PLAYER_ANIM_LOW_WALK);
3520 }
3521 if (mDemoSubstateTimer == 0) {
3523 if (mDokanMode == DEMO_DOKAN_WATER_TANK) {
3524 setZPosition(-1800.0f);
3525 if (mDemoStateArg <= 1) {
3526 mWarpPos.x = mPos.x + sc_DirSpeed[mDemoStateArg] * 32.0f;
3527 mDemoSubstate = 2;
3528 } else {
3529 mWarpPos.y = mPos.y - sc_DirSpeed[mDemoStateArg & 1] * 80.0f;
3530 mDemoSubstate = 4;
3531 }
3532 } else {
3533 changeNextScene(1);
3534 }
3535 break;
3536 }
3537 break;
3538 case 2:
3539 if (sLib::chase(&mPos.x, mWarpPos.x, 1.0f)) {
3541 mDemoSubstate = 3;
3542 }
3543 break;
3544 case 3:
3545 if (sLib::chase(&mPos.y, mWarpPos.y, 1.0f)) {
3546 mWarpPos.x = mPos.x + sc_DirSpeed[mDemoStateArg] * 48.0f;
3547 mDemoSubstate = 4;
3548 }
3549 break;
3550 case 4:
3551 if (
3552 sLib::chase(&mPos.x, mWarpPos.x, 1.0f) &&
3553 sLib::chase(&mPos.y, mWarpPos.y, 1.0f)
3554 ) {
3555 mLayer = LAYER_2;
3556 mAngle.y = 0;
3557 switch (mDemoStateArg) {
3558 case 0:
3559 changeDemoState(StateID_DemoInDokanL, DOKAN_TYPE_CONNECTED);
3560 break;
3561 case 1:
3562 changeDemoState(StateID_DemoInDokanR, DOKAN_TYPE_CONNECTED);
3563 break;
3564 case 2:
3565 changeDemoState(StateID_DemoInDokanU, DOKAN_TYPE_CONNECTED);
3566 break;
3567 case 3:
3568 changeDemoState(StateID_DemoInDokanD, DOKAN_TYPE_CONNECTED);
3569 break;
3570 }
3571 setZPosition(-1800.0f);
3572 }
3573 break;
3574 }
3575}
3576
3577void daPlBase_c::initializeState_DemoRailDokan() {
3579 sNextGotoData *nextGoto = dCd_c::m_instance->
3580 getFileP(dScStage_c::m_instance->mCurrFile)->
3581 getNextGotoP(mDokanEnterNextGotoID);
3582
3583 sRailInfoData *rail = dRail_c::getRailInfoP(nextGoto->mRailID);
3584
3585 // @bug This line should appear after setting mRailDokanRailIndex, not before.
3586 sRailNodeData *node = &dCd_c::m_instance->
3587 getFileP(dScStage_c::m_instance->mCurrFile)->
3588 mpRailNodes[rail->mNodeIdx + mRailDokanRailIndex];
3589
3590 if (nextGoto->mFlags & NEXT_GOTO_FLAG_RAIL_REVERSE) {
3591 mRailDokanRailIndex = rail->mCount - 2;
3592 } else {
3593 mRailDokanRailIndex = 1;
3594 }
3595
3596 mVec2_c delta(node->mX - mPos.x, -node->mY - mPos.y);
3597
3598 float size = delta.length();
3599 mRailDokanNextNodeTimer = size / 2.0f;
3600 mDokanMoveSpeed.set(delta.x / size * 2.0f, delta.y / size * 2.0f);
3601}
3602
3603void daPlBase_c::finalizeState_DemoRailDokan() {
3605}
3606
3607void daPlBase_c::setExitRailDokan() {
3608 dCdFile_c *cdFile = dCd_c::m_instance->getFileP(dScStage_c::m_instance->mCurrFile);
3609
3610 sNextGotoData *nextGoto = cdFile->getNextGotoP(mDokanEnterNextGotoID);
3611
3612 // @bug This will the entered next-goto, not the one the player will exit from.
3613 // To fix this, we'd need to do
3614 // nextGoto = cdFile->getNextGotoP(nextGoto->mDestID);
3615 // here.
3616
3617 mLayer = nextGoto->mLayer;
3618
3619 switch (nextGoto->mType) {
3620 case NEXT_GOTO_TYPE_PIPE_U:
3621 // @bug This should be StateID_DemoInDokanD.
3622 changeDemoState(StateID_DemoInDokanU, DOKAN_TYPE_CONNECTED);
3623 break;
3624 case NEXT_GOTO_TYPE_PIPE_D:
3625 changeDemoState(StateID_DemoInDokanU, DOKAN_TYPE_CONNECTED);
3626 break;
3627 case NEXT_GOTO_TYPE_PIPE_L:
3628 changeDemoState(StateID_DemoInDokanR, DOKAN_TYPE_CONNECTED);
3629 break;
3630 case NEXT_GOTO_TYPE_PIPE_R:
3631 changeDemoState(StateID_DemoInDokanL, DOKAN_TYPE_CONNECTED);
3632 break;
3633 }
3634}
3635
3636void daPlBase_c::executeState_DemoRailDokan() {
3637 if (--mRailDokanNextNodeTimer < 0) {
3638 sNextGotoData *ngt = dCd_c::m_instance->
3639 getFileP(dScStage_c::m_instance->mCurrFile)->
3640 getNextGotoP(mDokanEnterNextGotoID);
3641 sRailInfoData *rail = dRail_c::getRailInfoP(ngt->mRailID);
3642
3643 sRailNodeData *currNode = &dCd_c::m_instance->
3644 getFileP(dScStage_c::m_instance->mCurrFile)->
3645 mpRailNodes[rail->mNodeIdx + mRailDokanRailIndex];
3646 mPos.x = currNode->mX;
3647 mPos.y = -currNode->mY;
3648
3649 int done = 0;
3650 if (ngt->mFlags & 1) {
3651 mRailDokanRailIndex--;
3652 if (mRailDokanRailIndex < 0) {
3653 done = 1;
3654 }
3655 } else {
3656 mRailDokanRailIndex++;
3657 if (mRailDokanRailIndex >= rail->mCount) {
3658 done = 1;
3659 }
3660 }
3661
3662 if (done == 1) {
3663 setExitRailDokan();
3664 return;
3665 }
3666
3667 sRailNodeData *nextNode = &dCd_c::m_instance->
3668 getFileP(dScStage_c::m_instance->mCurrFile)->
3669 mpRailNodes[rail->mNodeIdx + mRailDokanRailIndex];
3670
3671 mVec2_c distToNext(nextNode->mX - mPos.x, -nextNode->mY - mPos.y);
3672
3673 float distLen = distToNext.length();
3674 mRailDokanNextNodeTimer = distLen / 2.0f;
3675 mDokanMoveSpeed.set(distToNext.x / distLen * 2.0f, distToNext.y / distLen * 2.0f);
3676 } else {
3677 mPos.x += mDokanMoveSpeed.x;
3678 mPos.y += mDokanMoveSpeed.y;
3679 }
3680}
3681
3682void daPlBase_c::setObjDokanIn(dBg_ctr_c *bgCtr, mVec3_c &pos, int nextGotoID) {
3683 mpDokanBgCtr = bgCtr;
3684 mWarpPos.set(pos.x, pos.y, mPos.z);
3685 mRollDokanAngle = *bgCtr->mRotation;
3686 setDemoOutDokanAction(nextGotoID, DOKAN_ROLL);
3687}
3688
3689bool daPlBase_c::isDispOutCheckOn() {
3692 isStatus(STATUS_53) ||
3696 ) {
3697 return false;
3698 }
3699 return true;
3700}
3701
3702void daPlBase_c::initializeState_DemoDown() {}
3703void daPlBase_c::finalizeState_DemoDown() {}
3704void daPlBase_c::executeState_DemoDown() {}
3705
3706int daPlBase_c::setDemoGoal(mVec3_c &landPos, float goalCastleX, u8 goalType) {
3707 if (daPyDemoMng_c::mspInstance->mFlags & 4) {
3708 return -1;
3709 }
3710
3711 mPos.x = landPos.x;
3714
3715 mWarpPos.x = goalCastleX;
3716 mWarpPos.y = landPos.y;
3717 mWarpPos.z = landPos.x + 80.0f;
3718
3719 mGoalDemoIndex = daPyDemoMng_c::mspInstance->setGoalDemoList(mPlayerNo);
3720 if (mGoalDemoIndex == 0) {
3721 // Only set once, when the first player reaches the goal
3722 daPyDemoMng_c::mspInstance->setDemoMode(daPyDemoMng_c::MODE_1, 0);
3723 daPyDemoMng_c::mspInstance->mGoalType = goalType;
3724 daPyDemoMng_c::mspInstance->mPlayerNo = mPlayerNo;
3725
3726 mVec3_c fireworkPos(goalCastleX - 112.0f, landPos.y, 5500.0f);
3727 float height;
3728 if (dBc_c::checkGround(&fireworkPos, &height, mLayer, 1, -1)) {
3729 fireworkPos.y = height + 112.0f;
3730 }
3731 daPyDemoMng_c::mspInstance->mFireworkPos = fireworkPos;
3732 }
3733
3734 if (!daPyMng_c::isItemKinopio(mPlayerNo)) {
3735 if (mGoalDemoIndex != 0 && mGoalDemoIndex + 1 == daPyMng_c::getNumInGame()) {
3736 // All players have reached the goal
3738 }
3739 } else {
3740 daPyDemoMng_c::mspInstance->m_42 = 1;
3742 }
3743
3744 int totalPlayers = daPyMng_c::getNumInGame() + daPyMng_c::getItemKinopioNum();
3745 if (totalPlayers == mGoalDemoIndex + 1) {
3746 daPyDemoMng_c::mspInstance->stopBgmGoalDemo();
3747 }
3748
3749 return -1;
3750}
3751
3752bool daPlBase_c::setHideNotGoalPlayer() {
3754 mSpeedF = 0.0f;
3755 mSpeed.y = 0.0f;
3757 setFallAction();
3758 return true;
3759 }
3760 return false;
3761}
3762
3763void daPlBase_c::stopGoalOther() {
3764 if (!isPlayerGameStop()) {
3765 return;
3766 }
3768 for (int i = 0; i < PLAYER_COUNT; i++) {
3769 daPlBase_c *ctrlPl = daPyMng_c::getCtrlPlayer(i);
3770 if (ctrlPl == nullptr || !ctrlPl->isStatus(STATUS_GOAL_POLE_TOUCHED)) {
3771 continue;
3772 }
3773
3774 daPlBase_c *pl = daPyMng_c::getPlayer(i);
3775 if (pl != nullptr) {
3776 pl->mExecStopMask &= ~2;
3777 }
3778 daPlBase_c *yoshi = daPyMng_c::getYoshi(i);
3779 if (yoshi != nullptr) {
3780 yoshi->mExecStopMask &= ~2;
3781 }
3782 }
3783}
3784
3785void daPlBase_c::playGoalOther() {
3786 dActor_c::mExecStopReq &= ~0xf;
3787 for (int i = 0; i < PLAYER_COUNT; i++) {
3788 daPlBase_c *ctrlPl = daPyMng_c::getCtrlPlayer(i);
3789 if (ctrlPl == nullptr || ctrlPl->isStatus(STATUS_GOAL_POLE_TOUCHED)) {
3790 continue;
3791 }
3792
3793 daPlBase_c *pl = daPyMng_c::getPlayer(i);
3794 if (pl != nullptr) {
3795 pl->mExecStopMask |= 2;
3796 }
3797 daPlBase_c *yoshi = daPyMng_c::getYoshi(i);
3798 if (yoshi != nullptr) {
3799 yoshi->mExecStopMask |= 2;
3800 }
3801 }
3802}
3803
3804void daPlBase_c::initDemoGoalBase() {
3806 if (!mDemoStateArg) {
3807 startPlayerVoice(VOICE_GOAL_POLE_CATCH, 0);
3808 onStatus(STATUS_7E);
3809 }
3810 clearJumpActionInfo(0);
3811 endStar();
3812 setDemoGoalMode(0, 0);
3813 mpMdlMng->setAnm(PLAYER_ANIM_RTREE_START);
3814 mAngle.x = 0;
3815 setZPositionDirect(3000.0f);
3816 mSpeed.x = 0.0f;
3817 mSpeedF = 0.0f;
3818 mSpeed.y = 0.0f;
3819 mAccelY = 0.0f;
3820 mMaxFallSpeed = -4.0f;
3821}
3822
3823void daPlBase_c::finalizeDemoGoalBase() {
3829 offStatus(STATUS_6C);
3830 offStatus(STATUS_6D);
3831 offStatus(STATUS_6E);
3832 offStatus(STATUS_7E);
3833}
3834
3835void daPlBase_c::initializeState_DemoGoal() { initDemoGoalBase(); }
3836void daPlBase_c::finalizeState_DemoGoal() { finalizeDemoGoalBase(); }
3837
3838float daPlBase_c::getDemoGoalLandPos() {
3839 float pos = mWarpPos.z + daPyDemoMng_c::mspInstance->m_1c * 16.0f;
3840 if (daPyDemoMng_c::mspInstance->m_1c > 1) {
3841 pos -= mGoalTouchOrder * 32.0f;
3842 }
3843 return pos;
3844}
3845
3846void daPlBase_c::setDemoGoal_MultiJump() {
3847 offStatus(STATUS_7E);
3848 mVec3_c pos(
3849 getDemoGoalLandPos(),
3850 mPos.y,
3851 mPos.z
3852 );
3853 dBc_c::checkGround(&pos, &pos.y, mLayer, 1, -1);
3854 mAngle.y = 0x4000;
3855 mDemoState = GOAL_DEMO_POLE_JUMP;
3856 mpMdlMng->setAnm(PLAYER_ANIM_GOAL_JUMP);
3857 if (daPyDemoMng_c::mspInstance->m_1c > 1) {
3858 initGoalJump(pos, daPlBase_c::sc_JumpSpeed + 1.5f);
3859 } else {
3860 initGoalJump(pos, daPlBase_c::sc_JumpSpeed + 1.3f);
3861 }
3862}
3863
3864void daPlBase_c::executeDemoGoal_Pole() {
3865 switch ((DemoGoalState_Pole_e) mDemoState) {
3867 if (!addCalcAngleY(-0x4000, 10) && mpMdlMng->mpMdl->mAnm.isStop()) {
3868 mDemoState = GOAL_DEMO_WAIT_BELOW_PLAYER;
3869 mpMdlMng->setAnm(PLAYER_ANIM_RTREE_WAIT);
3871 }
3872 break;
3875 int polePlayer = daPyDemoMng_c::mspInstance->getPoleBelowPlayer(mPlayerNo);
3876 if (polePlayer != -1) {
3877 daPlBase_c *ctrlPl = daPyMng_c::getCtrlPlayer(polePlayer);
3878 if (ctrlPl != nullptr) {
3879 float l = 0.7f * ctrlPl->getModelHeight() + ctrlPl->mPos.y;
3880 if (!(mPos.y > l || ctrlPl->isStatus(STATUS_GOAL_POLE_FINISHED_SLIDE_DOWN))) {
3881 break;
3882 }
3883 }
3884 }
3885 mDemoState = GOAL_DEMO_POLE_SLIDE;
3887 daPyDemoMng_c::mspInstance->mFlags |= 1;
3888 mSpeed.y = -1.9f;
3889 }
3890 break;
3891 case GOAL_DEMO_POLE_SLIDE: {
3892 mPos.y += mSpeed.y;
3893 if (mPos.y < mGoalPoleEndY) {
3894 mPos.y = mGoalPoleEndY;
3896 mSpeed.y = 0.0f;
3897 mDemoState = GOAL_DEMO_POLE_WAIT_JUMP;
3898 mpMdlMng->setAnm(PLAYER_ANIM_RTREE_POSE);
3899 }
3900 break;
3901 }
3904 setDemoGoal_MultiJump();
3905 }
3906 break;
3908 if (calcGoalJump()) {
3909 mDemoState = GOAL_DEMO_POLE_LAND;
3910 mpMdlMng->setAnm(PLAYER_ANIM_GOAL_JUMP_ED);
3911 setLandSE();
3912 }
3913 break;
3915 if (mpMdlMng->mpMdl->mAnm.isStop()) {
3916 mpMdlMng->setAnm(PLAYER_ANIM_STAMP);
3917 mDemoState = GOAL_DEMO_POLE_WAIT_TURN;
3919 }
3920 break;
3922 if (mDemoSubstateTimer == 0) {
3924 mDemoState = GOAL_DEMO_POLE_TURN;
3925 }
3926 break;
3928 if (daPyDemoMng_c::mspInstance->mFlags & 8 && !addCalcAngleY(0, 10)) {
3930 mDemoState = GOAL_DEMO_POLE_WAIT_END;
3931 }
3932 break;
3934 if (mDemoSubstateTimer == 0) {
3935 setDemoGoalMode(GOAL_DEMO_ACTION_WAIT, 0);
3936 }
3937 break;
3938 }
3939}
3940
3941void daPlBase_c::executeDemoGoal_Wait() {
3942 if (isStatus(STATUS_6B)) {
3943 offStatus(STATUS_6B);
3944 onStatus(STATUS_6C);
3945 setDemoGoalMode(GOAL_DEMO_ACTION_KIME_POSE, 0);
3946 }
3947 if (isStatus(STATUS_6D)) {
3948 setDemoGoalMode(GOAL_DEMO_ACTION_RUN, 0);
3949 }
3950}
3951
3952void daPlBase_c::executeDemoGoal_KimePose() {
3953 if (mKimePoseMode != KIME_POSE_NONE && mpMdlMng->mpMdl->mAnm.checkFrame(107.0f)) {
3954 daPlBase_c *pl = daPyMng_c::getPlayer(mPlayerNo);
3955 if (pl != nullptr) {
3956 if (pl->isItemKinopio()) {
3957 if (mKimePoseMode == KIME_POSE_PENGUIN || mKimePoseMode == KIME_POSE_NO_HAT) {
3958 if (pl->mPowerup == POWERUP_NONE) {
3959 dScoreMng_c::m_instance->fn_800e25a0(8, mPlayerNo, 1);
3960 } else {
3961 dScoreMng_c::m_instance->fn_800e25a0(9, mPlayerNo, 1);
3962 }
3963 }
3964 } else {
3966 if (mGoalDemoIndex == 0) {
3967 SndAudioMgr::sInstance->startSystemSe(SE_OBJ_GOAL_GET_COIN_BONUS, 1);
3968 }
3969 static const int scGoalCoin[] = {20, 15, 10, 5 };
3970 dMultiMng_c::mspInstance->setBattleCoin(mPlayerNo, scGoalCoin[mGoalTouchOrder]);
3971 }
3972 }
3973 }
3974 }
3975 if (updateDemoKimePose(CLEAR_TYPE_GOAL)) {
3976 setDemoGoalMode(GOAL_DEMO_ACTION_WAIT, 0);
3977 }
3978}
3979
3980void daPlBase_c::executeDemoGoal_Run() {}
3981
3982void daPlBase_c::setDemoGoalMode(int mode, int param) {
3983 mDemoSubstate = mode;
3984 mDemoState = param;
3985}
3986
3987void daPlBase_c::executeState_DemoGoal() {
3989 case GOAL_DEMO_ACTION_POLE:
3990 executeDemoGoal_Pole();
3991 break;
3992 case GOAL_DEMO_ACTION_WAIT:
3993 executeDemoGoal_Wait();
3994 break;
3995 case GOAL_DEMO_ACTION_KIME_POSE:
3996 executeDemoGoal_KimePose();
3997 break;
3998 case GOAL_DEMO_ACTION_RUN:
3999 executeDemoGoal_Run();
4000 break;
4001 }
4002 bgCheck(0);
4003}
4004
4005void daPlBase_c::initGoalJump(mVec3_c &pos, float ySpeed) {
4006 mSpeed.y = ySpeed;
4007 int count = 0;
4008 float yPos = mPos.y;
4009 while (true) {
4010 mAccelY = -0.28f;
4011 mSpeed.y += mAccelY;
4012 if (mSpeed.y < -4.0f) {
4013 mSpeed.y = -4.0f;
4014 }
4015 yPos += mSpeed.y;
4016 if (mSpeed.y < 0.0f && yPos <= pos.y) {
4017 break;
4018 }
4019 count++;
4020 }
4021 mGoalJumpTarget = pos;
4022 mGoalJumpFrameCount = count;
4023 mSpeed.y = ySpeed;
4024}
4025
4026bool daPlBase_c::calcGoalJump() {
4027 if (mGoalJumpFrameCount != 0) {
4028 sLib::chase(&mPos.x, mGoalJumpTarget.x, (mGoalJumpTarget.x - mPos.x) / mGoalJumpFrameCount);
4029 mGoalJumpFrameCount--;
4030 }
4031 mAccelY = -0.28f;
4032 mSpeed.y += mAccelY;
4033 if (mSpeed.y < -4.0f) {
4034 mSpeed.y = -4.0f;
4035 }
4036 mPos.y += mSpeed.y;
4037 if (mSpeed.y < 0.0f && isNowBgCross(BGC_FOOT)) {
4038 mPos = mGoalJumpTarget;
4039 return true;
4040 }
4041 return false;
4042}
4043
4044void daPlBase_c::initDemoKimePose() {
4045 onStatus(STATUS_6C);
4046 mKimePoseMode = KIME_POSE_NONE;
4047}
4048
4049bool daPlBase_c::updateDemoKimePose(ClearType_e clearType) {
4050 return false;
4051}
4052
4053void daPlBase_c::startKimePoseVoice(ClearType_e clearType) {
4054 int playerCount;
4055 if (clearType == CLEAR_TYPE_GOAL) {
4056 playerCount = daPyDemoMng_c::mspInstance->m_1c;
4057 } else {
4058 playerCount = daPyDemoMng_c::mspInstance->getControlDemoPlayerNum();
4059 }
4060 if (dInfo_c::m_startGameInfo.mGameMode == dInfo_c::GAME_MODE_SUPER_GUIDE) {
4061 if (playerCount >= 2) {
4062 startPlayerVoice(VOICE_CLEAR_MULTI, 0);
4063 } else {
4064 startPlayerVoice(VOICE_CLEAR_HELPED, 0);
4065 }
4066 } else if (clearType == CLEAR_TYPE_FINAL_BOSS) {
4067 startPlayerVoice(VOICE_CLEAR_LAST_BOSS, 0);
4068 } else if (playerCount >= 2) {
4069 startPlayerVoice(VOICE_CLEAR_MULTI, 0);
4070 } else if (clearType == CLEAR_TYPE_GOAL) {
4071 if (daPyDemoMng_c::mspInstance->mGoalType == 0) {
4072 startPlayerVoice(VOICE_CLEAR_NORMAL, 0);
4073 } else {
4074 startPlayerVoice(VOICE_CLEAR_ANOTHER, 0);
4075 }
4076 } else {
4077 startPlayerVoice(VOICE_CLEAR_BOSS, 0);
4078 }
4079}
4080
4081bool daPlBase_c::startControlDemo() {
4082 if (isDemoType(DEMO_PLAYER)) {
4083 return true;
4084 } else if (isDemoType(DEMO_ENDING_DANCE)) {
4085 changeDemoState(StateID_DemoControl, CONTROL_DEMO_WAIT);
4086 return true;
4087 } else {
4088 onStatus(STATUS_71);
4089 return false;
4090 }
4091}
4092
4093void daPlBase_c::endControlDemo(int p) {
4094 if (isStatus(STATUS_72)) {
4095 changeNormalAction();
4096 }
4097}
4098
4099void daPlBase_c::setControlDemoDir(u8 dir) {
4100 if (isStatus(STATUS_72)) {
4101 mDirection = dir;
4102 if (!isState(StateID_Walk)) {
4103 changeState(StateID_Walk, (void *) 1);
4104 }
4105 }
4106}
4107
4108void daPlBase_c::setControlDemoWait() {
4109 if (isStatus(STATUS_72)) {
4110 mDemoState = CONTROL_DEMO_WAIT;
4111 changeState(StateID_Walk, (void *) 1);
4112 }
4113}
4114
4115bool daPlBase_c::isControlDemoWait() {
4116 if (isStatus(STATUS_72)) {
4117 if (mDemoState == CONTROL_DEMO_WAIT) {
4118 return true;
4119 }
4120 }
4121 return false;
4122}
4123
4124void daPlBase_c::setControlDemoWalk(const float &f1, const float &f2) {
4125 if (isStatus(STATUS_72)) {
4126 mControlDemoTargetPos.x = f1;
4127 mDemoState = CONTROL_DEMO_WALK;
4128 mControlDemoSpeedF = std::fabs(f2);
4129 if (mControlDemoSpeedF > getSpeedData()->mHighSpeed) {
4130 mControlDemoSpeedF = getSpeedData()->mHighSpeed;
4131 }
4132 }
4133}
4134
4135bool daPlBase_c::isControlDemoWalk() {
4136 if (isStatus(STATUS_72)) {
4137 if (mDemoState == CONTROL_DEMO_WALK) {
4138 return true;
4139 }
4140 }
4141 return false;
4142}
4143
4144void daPlBase_c::setControlDemoAnm(int anmNo) {
4145 if (isStatus(STATUS_72)) {
4146 mDemoState = CONTROL_DEMO_REGULAR_ANIM;
4147 changeState(StateID_AnimePlay, DEMO_ANIME_NORMAL);
4148 mpMdlMng->setAnm(anmNo);
4149 }
4150}
4151bool daPlBase_c::isControlDemoAnm(int anmNo) {
4152 if (isStatus(STATUS_72) && mDemoState == CONTROL_DEMO_REGULAR_ANIM && anmNo == mpMdlMng->mpMdl->mCurrAnmID) {
4153 return true;
4154 }
4155 return false;
4156}
4157
4159 if (isStatus(STATUS_72)) {
4160 mDemoState = CONTROL_DEMO_CUTSCENE_ANIM;
4162 }
4163}
4164
4165void daPlBase_c::setControlDemoKinopioWalk() {
4166 if (isDemoState(StateID_DemoNone) || (isDemoType(DEMO_KINOPIO) && mDemoState != CONTROL_DEMO_KINOPIO_WALK)) {
4167 changeDemoState(StateID_DemoControl, CONTROL_DEMO_KINOPIO_WALK);
4168 }
4169}
4170
4171void daPlBase_c::setControlDemoKinopioSwim() {
4172 if (isDemoState(StateID_DemoNone) || (isDemoType(DEMO_KINOPIO) && mDemoState != CONTROL_DEMO_KINOPIO_SWIM)) {
4173 changeDemoState(StateID_DemoControl, CONTROL_DEMO_KINOPIO_SWIM);
4174 }
4175}
4176
4177void daPlBase_c::setControlDemoEndingDance() {
4178 if (!isControlDemoAll()) {
4179 changeDemoState(StateID_DemoControl, CONTROL_DEMO_ENDING_DANCE);
4180 }
4181}
4182
4183bool daPlBase_c::isBossDemoLand() {
4184 if (!isNowBgCross(BGC_FOOT)) {
4185 return false;
4186 }
4187 if (isStatus(STATUS_BIG_JUMP) || isStatus(STATUS_4E) || isOnSinkSand() || mBossDemoLandTimer != 0) {
4188 return false;
4189 }
4190 return true;
4191}
4192
4193bool daPlBase_c::isHitGroundKinopioWalk(int dir, float f, int i2) {
4194 mVec3_c tmp(
4195 mPos.x + f * sc_DirSpeed[dir],
4196 mPos.y,
4197 mPos.z
4198 );
4199 float a = 4.0f;
4200 if (a < 1.2f * f) {
4201 a = 1.2f * f;
4202 }
4203 tmp.y = mPos.y + a;
4204 float y;
4205 if (mBc.checkGround(&tmp, &y, mLayer, mAmiLayer, -1) && std::fabs(y - mPos.y) < a) {
4206 if (i2 == 1) {
4207 tmp.y = mPos.y - 4.0f;
4208 float y2;
4209 if (dBc_c::checkWater(tmp.x, tmp.y, mLayer, &y2) &&
4210 mLastPosDelta.y >= 0.0f &&
4211 y <= y2 &&
4212 mPos.y <= y2 - 4.0f
4213 ) {
4214 return false;
4215 }
4216 }
4217 return true;
4218 }
4219 return false;
4220}
4221
4222bool daPlBase_c::isHitWallKinopioWalk(int dir) {
4223 static const BgCross1_e scViewHitFlag[] = { BGC_SIDE_LIMIT_R, BGC_SIDE_LIMIT_L };
4224 if (checkBGCrossWall(dir) || isNowBgCross(scViewHitFlag[dir])) {
4225 return true;
4226 }
4227 return false;
4228}
4229
4230bool daPlBase_c::checkKinopioWaitBG(int dir) {
4231 if (isHitWallKinopioWalk(dir)) {
4232 return true;
4233 }
4234 return !isHitGroundKinopioWalk(dir, 10.0, 0);
4235}
4236
4237void daPlBase_c::initializeState_DemoControl() {
4238 if (isStatus(STATUS_5F)) {
4239 offStatus(STATUS_5F);
4240 }
4241 mKey.onStatus(dAcPyKey_c::STATUS_DEMO);
4242 onStatus(STATUS_72);
4243 offStatus(STATUS_71);
4244 mIsDemoMode = false;
4245 initializeDemoControl();
4246 mDemoState = mDemoStateArg;
4247 switch (mDemoState) {
4248 case CONTROL_DEMO_4:
4249 mDemoSubstateTimer = 60;
4250 onStatus(STATUS_7A);
4251 break;
4252 case CONTROL_DEMO_KINOPIO_WALK:
4253 mControlDemoTargetPos.x = mPos.x;
4254 mControlDemoSpeedF = 0.9f;
4255 mItemKinopioDirection = mDirection;
4256 mItemKinopioTurnTimer = 150;
4257 if (!isHitGroundKinopioWalk(mDirection, 8.0f, 1)) {
4258 mItemKinopioDirection ^= 1;
4259 }
4260 break;
4261 case CONTROL_DEMO_KINOPIO_SWIM:
4262 if (mSpeedF > 0.0f) {
4263 mItemKinopioDirection = 0;
4264 } else {
4265 mItemKinopioDirection = 1;
4266 }
4267 break;
4268 default:
4269 break;
4270 }
4271}
4272
4273void daPlBase_c::finalizeState_DemoControl() {
4274 mKey.offStatus(dAcPyKey_c::STATUS_DEMO);
4275 offStatus(STATUS_72);
4276 offStatus(STATUS_74);
4277 offStatus(STATUS_63);
4278 offStatus(STATUS_73);
4279 if (mDemoState == CONTROL_DEMO_4) {
4280 offStatus(STATUS_7A);
4281 }
4282}
4283
4284void daPlBase_c::executeState_DemoControl() {
4285 offStatus(STATUS_74);
4286 if (isStatus(STATUS_73)) {
4287 if (isNowBgCross(BGC_FOOT)) {
4288 offStatus(STATUS_73);
4289 } else {
4290 mSpeedF *= 0.98f;
4291 }
4292 }
4293
4294 switch ((ControlDemoSubstate_e) mDemoState) {
4295 case CONTROL_DEMO_WALK: {
4296 onStatus(STATUS_74);
4297 if (isNowBgCross(BGC_FOOT)) {
4298 if (!isState(StateID_Walk) && !isState(StateID_Turn)) {
4300 }
4301 } else {
4302 if (!isState(StateID_Fall)) {
4303 changeState(StateID_Fall, false);
4304 }
4305 }
4306 if (std::fabs(mPos.x - mControlDemoTargetPos.x) < mControlDemoSpeedF) {
4307 mDemoState = CONTROL_DEMO_WAIT;
4308 mSpeedF = 0.0f;
4309 mPos.x = mControlDemoTargetPos.x;
4310 break;
4311 }
4312 if (mPos.x < mControlDemoTargetPos.x) {
4313 mKey.onDemoTrigger(dAcPyKey_c::BUTTON_RIGHT);
4314 mSpeedF = mControlDemoSpeedF;
4315 break;
4316 }
4317 mKey.onDemoTrigger(dAcPyKey_c::BUTTON_LEFT);
4318 mSpeedF = -mControlDemoSpeedF;
4319 break;
4320 }
4321 case CONTROL_DEMO_4: {
4322 if (mDemoSubstateTimer == 0) {
4324 }
4325 break;
4326 }
4327 case CONTROL_DEMO_KINOPIO_WALK: {
4328 if (
4329 !isNowBgCross(BGC_FOOT) ||
4330 !mStateMgr.getStateID()->isEqual(StateID_Walk) && !mStateMgr.getStateID()->isEqual(StateID_Turn)
4331 ) {
4332 mDemoState = CONTROL_DEMO_WAIT;
4333 break;
4334 }
4335 onStatus(STATUS_74);
4336 if (isOnSinkSand() || (checkKinopioWaitBG(0) && checkKinopioWaitBG(1))) {
4337 mDemoState = CONTROL_DEMO_KINOPIO_SINK_SAND;
4338 mControlDemoSpeedF = 0.0f;
4339 mSpeedF = 0.0f;
4340 break;
4341 }
4342 int prevDirection = (int) (short) mItemKinopioDirection;
4343 sLib::calcTimer(&mItemKinopioTurnTimer);
4344 if (isHitWallKinopioWalk(mItemKinopioDirection) || mItemKinopioTurnTimer == 0) {
4345 mItemKinopioDirection ^= 1;
4346 mControlDemoTargetPos.x = mPos.x + sc_DirSpeed[mItemKinopioDirection] * 24.0f;
4347 } else if (!isHitGroundKinopioWalk(mItemKinopioDirection, 4.0f, 1) && !isHitGroundKinopioWalk(mItemKinopioDirection, 8.0f, 1)) {
4348 mItemKinopioDirection ^= 1;
4349 mControlDemoTargetPos.x = mPos.x + sc_DirSpeed[mItemKinopioDirection] * 24.0f;
4350 }
4351 float tmp = mControlDemoTargetPos.x + sc_DirSpeed[mItemKinopioDirection] * 24.0f;
4352 if (mPos.x < tmp) {
4353 mKey.onDemoTrigger(dAcPyKey_c::BUTTON_RIGHT);
4354 mSpeedF = mControlDemoSpeedF;
4355 mItemKinopioDirection = 0;
4356 } else {
4357 mKey.onDemoTrigger(dAcPyKey_c::BUTTON_LEFT);
4358 mItemKinopioDirection = 1;
4359 mSpeedF = -mControlDemoSpeedF;
4360 }
4361 if (prevDirection != mItemKinopioDirection) {
4362 mItemKinopioTurnTimer = 180;
4363 }
4364 break;
4365 }
4366 case CONTROL_DEMO_KINOPIO_SWIM: {
4367 if (!mStateMgr.getStateID()->isEqual(StateID_Swim)) {
4368 mDemoState = CONTROL_DEMO_WAIT;
4369 break;
4370 }
4371 onStatus(STATUS_74);
4372 if (isNowBgCross(BGC_FOOT) && isHitWallKinopioWalk(mItemKinopioDirection)) {
4373 mItemKinopioDirection ^= 1;
4374 }
4375 if (mItemKinopioDirection == 0) {
4376 mKey.onDemoTrigger(dAcPyKey_c::BUTTON_RIGHT);
4377 sLib::chase(&mSpeedF, 0.5625f, 0.1f);
4378 } else {
4379 mKey.onDemoTrigger(dAcPyKey_c::BUTTON_LEFT);
4380 sLib::chase(&mSpeedF, -0.5625f, 0.1f);
4381 }
4382 break;
4383 }
4384 case CONTROL_DEMO_KINOPIO_SINK_SAND: {
4385 if (
4386 !isNowBgCross(BGC_FOOT) ||
4387 !mStateMgr.getStateID()->isEqual(StateID_Walk) && !mStateMgr.getStateID()->isEqual(StateID_Turn)
4388 ) {
4389 mDemoState = CONTROL_DEMO_WAIT;
4390 break;
4391 }
4392 onStatus(STATUS_74);
4393 onStatus(STATUS_63);
4394 if (!checkKinopioWaitBG(0) || !checkKinopioWaitBG(1)) {
4395 setControlDemoKinopioWalk();
4396 }
4397 break;
4398 }
4399 default:
4400 break;
4401 }
4402}
4403
4404void daPlBase_c::setDemoOutNextGotoBlock(int nextGotoID, int delay, int fadeType) {
4405 if (mDemoStateMgr.getStateID()->isEqual(StateID_DemoNextGotoBlock)) {
4406 return;
4407 }
4408 changeDemoState(StateID_DemoNextGotoBlock, nextGotoID | ((fadeType & 0xFF) << 8));
4409 mDemoSubstateTimer = delay;
4410 switch (fadeType) {
4411 case 3:
4412 startSound(SE_PLY_DOKAN_IN_OUT, false);
4413 break;
4414 case 1:
4415 mIsDemoMode = false;
4417 changeState(StateID_Fall, false);
4418 }
4419 break;
4420 default:
4421 break;
4422 }
4423}
4424
4425void daPlBase_c::initializeState_DemoNextGotoBlock() {
4428 onStatus(STATUS_7A);
4429 initializeDemoControl();
4430}
4431
4432void daPlBase_c::finalizeState_DemoNextGotoBlock() {
4433 mKey.offStatus(dAcPyKey_c::STATUS_DEMO);
4435 offStatus(STATUS_7A);
4436}
4437
4438void daPlBase_c::executeState_DemoNextGotoBlock() {
4439 switch (mDemoSubstate) {
4440 case 0:
4441 if (mDemoSubstateTimer == 0) {
4442 dFader_c::fader_type_e f = dFader_c::FADER_DRIP_DOWN;
4443 int param = (int) mDemoStateArg;
4444 int nextGotoID = param & 0xff;
4445 if (((param >> 8) & 0xff) == 3) {
4446 f = dFader_c::FADER_CIRCLE_TARGET;
4447 }
4448 dNext_c::m_instance->setChangeSceneNextDat(dScStage_c::m_instance->mCurrFile, nextGotoID, f);
4449 changeNextScene(0);
4450 mDemoSubstate = 1;
4451 }
4452 break;
4453 case 1:
4454 break;
4455 }
4456}
4457
4458void daPlBase_c::updateEndingDance() {
4459 offStatus(STATUS_ENDING_DANCE_AUTO);
4460 if (!dScStage_c::m_isStaffCredit || isDemoType(DEMO_PLAYER)) {
4461 return;
4462 }
4463 int isActive = 0;
4464 if (dGameKey_c::m_instance->checkButtonsDown(mPlayerNo) || dGameKey_c::m_instance->checkShaking(mPlayerNo)) {
4465 isActive = 1;
4466 }
4467 if (!isDemoType(DEMO_ENDING_DANCE)) {
4468 if (isActive == 1) {
4469 mEndingDanceInactivityTimer = 0;
4470 } else {
4471 mEndingDanceInactivityTimer++;
4472 if (mEndingDanceInactivityTimer >= 180) {
4473 setControlDemoEndingDance();
4474 mEndingDanceInactivityTimer = 0;
4475 }
4476 }
4477 } else if (isActive == 1) {
4478 endControlDemo(0);
4479 } else if (isStatus(STATUS_45)) {
4480 for (int i = 0; i < ARRAY_SIZE(mEndingDanceKeyTimers); i++) {
4481 mEndingDanceKeyTimers[i] = 0;
4482 }
4483 } else {
4484 onStatus(STATUS_ENDING_DANCE_AUTO);
4485 if (dAudio::isBgmAccentSign(2)) {
4486 mDirection = 0;
4487 } else if (dAudio::isBgmAccentSign(4)) {
4488 mDirection = 1;
4489 } else if (dAudio::isBgmAccentSign(8)) {
4490 mKey.onDemoButton(dAcPyKey_c::BUTTON_DOWN);
4491 mEndingDanceKeyTimers[2] = 6;
4492 } else if (dAudio::isBgmAccentSign(16)) {
4493 mKey.onDemoTrigger(dAcPyKey_c::BUTTON_TWO);
4494 mKey.onDemoButton(dAcPyKey_c::BUTTON_TWO);
4495 mEndingDanceKeyTimers[3] = 5;
4496 } else if (dAudio::isBgmAccentSign(32)) {
4497 mKey.onDemoTrigger(dAcPyKey_c::BUTTON_TWO);
4498 mKey.onDemoButton(dAcPyKey_c::BUTTON_TWO);
4499 mEndingDanceKeyTimers[4] = 30;
4500 } else if (dAudio::isBgmAccentSign(64)) {
4501 mKey.onDemoShake();
4502 } else if (dAudio::isBgmAccentSign(128)) {
4503 if (dBgParameter_c::ms_Instance_p->m_48 > mPos.x) {
4504 mDirection = 0;
4505 } else {
4506 mDirection = 1;
4507 }
4508 }
4509
4510 for (int i = 0; i < 5; i++) {
4511 if (mEndingDanceKeyTimers[i] != 0 && --mEndingDanceKeyTimers[i] == 0) {
4512 switch (i) {
4513 case 2:
4514 mKey.offDemoButton(dAcPyKey_c::BUTTON_DOWN);
4515 break;
4516 case 3:
4517 case 4:
4518 mKey.offDemoButton(dAcPyKey_c::BUTTON_TWO);
4519 break;
4520 }
4521 }
4522 }
4523 }
4524}
4525
4526bool daPlBase_c::setEnemyStageClearDemo() {
4528 if (
4529 isNowBgCross(BGC_LIFT) &&
4530 mBc.mpCtrHead != nullptr &&
4531 mBc.mpCtrHead->mpActor != nullptr &&
4532 mBc.mpCtrHead->mpActor->mProfName == fProfile::EN_CHIKUWA_BLOCK
4533 ) {
4534 return false;
4535 }
4536 if (!isDemoType(DEMO_PLAYER)) {
4537 changeDemoState(StateID_DemoControl, CONTROL_DEMO_WAIT);
4538 }
4539 mSpeed.y = 0.0f;
4540 mSpeedF = 0.0f;
4541 return true;
4542 }
4543 return false;
4544}
4545
4546int daPlBase_c::getCcLineKind() {
4547 if (isNowBgCross(BgCross2_e(BGC_VINE_TOUCH_L | BGC_VINE_TOUCH_R))) {
4548 return mAmiLayer;
4549 }
4550 return 3;
4551}
4552
4553void daPlBase_c::initCollision(sCcDatNewF *dat1, sCcDatNewF *dat2) {
4554 mCc.set(this, dat1);
4555 mCc1.set(this, dat1);
4556 mAttCc1.set(this, dat2);
4557 mAttCc2.set(this, dat2);
4558 mAttCc3.set(this, dat2);
4559}
4560
4561void daPlBase_c::releaseCcData() {
4562 u32 mVsKind =
4563 BIT_FLAG(CC_KIND_PLAYER) |
4564 BIT_FLAG(CC_KIND_PLAYER_ATTACK) |
4565 BIT_FLAG(CC_KIND_YOSHI) |
4566 BIT_FLAG(CC_KIND_ENEMY) |
4567 BIT_FLAG(CC_KIND_BALLOON) |
4568 BIT_FLAG(CC_KIND_ITEM) |
4569 BIT_FLAG(CC_KIND_TAMA) |
4570 BIT_FLAG(CC_KIND_KILLER) |
4571 BIT_FLAG(CC_KIND_GOAL_POLE);
4572
4573 u32 mVsKindAttack =
4574 BIT_FLAG(CC_KIND_PLAYER) |
4575 BIT_FLAG(CC_KIND_YOSHI) |
4576 BIT_FLAG(CC_KIND_ENEMY) |
4577 BIT_FLAG(CC_KIND_BALLOON) |
4578 BIT_FLAG(CC_KIND_ITEM) |
4579 BIT_FLAG(CC_KIND_KILLER);
4580
4581 u32 vsDamage =
4582 ~BIT_FLAG(CC_ATTACK_NONE) &
4583 ~BIT_FLAG(CC_ATTACK_YOSHI_MOUTH) &
4584 ~BIT_FLAG(CC_ATTACK_SAND_PILLAR);
4585
4586 mCc.release();
4587 mCc.mCcData.mVsKind = mVsKind;
4588 mCc.mCcData.mAttack = 0;
4589 mCc.mCcData.mVsDamage = vsDamage;
4590
4591 mCc1.release();
4592 mCc1.mCcData.mVsKind = mVsKind;
4593 mCc1.mCcData.mAttack = 0;
4594 mCc1.mCcData.mVsDamage = vsDamage;
4595
4596 mAttCc1.release();
4597 mAttCc1.mCcData.mVsKind = mVsKindAttack;
4598 mAttCc1.mCcData.mAttack = 0;
4599 mAttCc1.mCcData.mVsDamage = 0;
4600
4601 mAttCc2.release();
4602 mAttCc2.mCcData.mVsKind = mVsKindAttack;
4603 mAttCc2.mCcData.mAttack = 0;
4604 mAttCc2.mCcData.mVsDamage = 0;
4605
4606 mAttCc3.release();
4607 mAttCc3.mCcData.mVsKind = mVsKindAttack;
4608 mAttCc3.mCcData.mAttack = 0;
4609 mAttCc3.mCcData.mVsDamage = 0;
4610}
4611
4612void daPlBase_c::clearCcData() {
4613 mCc.clear();
4614 mCc1.clear();
4615 mAttCc1.clear();
4616 mAttCc2.clear();
4617 mAttCc3.clear();
4618}
4619
4620void daPlBase_c::setCcAtBody(int attackCategory) {
4621 mAttCc2.mCcData.mBase.mOffset.set(mCc.mCcData.mBase.mOffset);
4622 mAttCc2.mCcData.mBase.mSize.set(mCc.mCcData.mBase.mSize);
4623 mAttCc2.mCcData.mAttack = attackCategory;
4624 mAttCc2.mCcData.mVsKind =
4625 BIT_FLAG(CC_KIND_PLAYER) |
4626 BIT_FLAG(CC_KIND_PLAYER_ATTACK) |
4627 BIT_FLAG(CC_KIND_YOSHI);
4628
4629 mAttCc1.mCcData.mBase.mOffset.set(mCc.mCcData.mBase.mOffset);
4630 mAttCc1.mCcData.mBase.mSize.set(mCc.mCcData.mBase.mSize);
4631 mAttCc1.mCcData.mAttack = attackCategory;
4632 mAttCc1.mCcData.mVsKind = mCc.mCcData.mVsKind & ~(
4633 BIT_FLAG(CC_KIND_PLAYER) |
4634 BIT_FLAG(CC_KIND_PLAYER_ATTACK) |
4635 BIT_FLAG(CC_KIND_YOSHI)
4636 );
4637}
4638
4639void daPlBase_c::setCcAtSlip() {
4640 setCcAtBody(CC_ATTACK_SLIP);
4641}
4642
4643void daPlBase_c::setCcAtPenguinSlip() {
4645 setCcAtBody(CC_ATTACK_PENGUIN_SLIDE);
4646 mAttCc2.mCcData.mVsDamage = BIT_FLAG(CC_ATTACK_PENGUIN_SLIDE);
4647 mAttCc1.mCcData.mVsDamage = BIT_FLAG(CC_ATTACK_PENGUIN_SLIDE);
4648 }
4649}
4650
4651void daPlBase_c::setCcAtHipAttack() {
4652 setCcAtBody(CC_ATTACK_HIP_ATTACK);
4653 mAttCc2.mCcData.mVsDamage = 0;
4654 mAttCc1.mCcData.mVsDamage = 0;
4655}
4656
4657void daPlBase_c::setCcAtStar() {
4658 mCc.mCcData.mAttack = CC_ATTACK_STAR;
4659 if ((mAttCc2.mCcData.mVsKind & (
4660 BIT_FLAG(CC_KIND_PLAYER) |
4661 BIT_FLAG(CC_KIND_PLAYER_ATTACK) |
4662 BIT_FLAG(CC_KIND_YOSHI)
4663 )) == 0) {
4664 mCc1.mCcData.mAttack = CC_ATTACK_STAR;
4665 }
4666 if (mAttCc1.mCcData.mAttack != CC_ATTACK_NONE &&
4667 mAttCc1.mCcData.mAttack != CC_ATTACK_YOSHI_EAT
4668 ) {
4669 mAttCc3.mCcData.mBase.mOffset.set(mAttCc1.mCcData.mBase.mOffset);
4670 mAttCc3.mCcData.mBase.mSize.set(mAttCc1.mCcData.mBase.mSize);
4671 mAttCc3.mCcData.mAttack = CC_ATTACK_STAR;
4672 }
4673 onStatus(STATUS_84);
4674}
4675
4676void daPlBase_c::setCcAtCannon() {
4677 setCcAtBody(CC_ATTACK_CANNON);
4678}
4679
4680void daPlBase_c::entryCollision() {
4682 int lineKind = getCcLineKind();
4683 mCc.mAmiLine = lineKind;
4684 if (mAttCc1.mCcData.mAttack == CC_ATTACK_WIRE_NET) {
4685 lineKind ^= 3;
4686 }
4687 mAttCc1.mAmiLine = lineKind;
4688 mAttCc3.mAmiLine = lineKind;
4689 mCc.mLayer = mLayer;
4690 mAttCc1.mLayer = mLayer;
4691 mAttCc3.mLayer = mLayer;
4692 if (isStatus(STATUS_74)) {
4693 mCc.mCcData.mStatus |= CC_STATUS_NO_REVISION;
4694 } else {
4695 mCc.mCcData.mStatus &= ~CC_STATUS_NO_REVISION;
4696 }
4697 if (!isStatus(STATUS_7A)) {
4698 mCc.entry();
4699 if (isStatus(STATUS_78)) {
4700 mCc1.entry();
4701 }
4702 }
4703 if (mAttCc1.mCcData.mAttack != CC_ATTACK_NONE) {
4704 mAttCc1.entry();
4705 }
4706 if (mAttCc2.mCcData.mAttack != CC_ATTACK_NONE) {
4707 mAttCc2.entry();
4708 }
4709 if (mAttCc3.mCcData.mAttack != CC_ATTACK_NONE) {
4710 mAttCc3.entry();
4711 }
4712 }
4713}
4714
4715bool daPlBase_c::isActionRevisionY() {
4716 if (isStatus(STATUS_POLE) || isStatus(STATUS_TARZAN_ROPE)) {
4717 return true;
4718 }
4719 return false;
4720}
4721
4722void daPlBase_c::setCcPlayerRev(dCc_c *cc1, dCc_c *cc2, float revRate, int ccKind) {
4723 daPlBase_c *other = (daPlBase_c *) cc2->mpOwner;
4724 float colliderSpeedF = other->mSpeedF;
4725 float offsX = cc1->mCollOffsetX[ccKind];
4726 float offsY = cc1->mCollOffsetY[ccKind];
4727 if (isActionRevisionY()) {
4728 if (other->isActionRevisionY()) {
4729 if (mCcHasInitialRevY) {
4730 mCcRevTotalOffsY = offsY + mCcRevTotalOffsY;
4731 } else {
4732 mCcHasInitialRevY = true;
4733 mCcRevTotalOffsY = offsY * revRate;
4734 }
4735 }
4736 } else if (!(std::fabs(offsY) < 1.0f || other->isActionRevisionY())) {
4737 if (mCcRevSet) {
4738 float prevOffsX = getCcRevOffsX() * getCcRevRate();
4739 float currOffsX = offsX * revRate;
4740 if (std::fabs(prevOffsX) < std::fabs(currOffsX)) {
4741 mCcRevSpeedF = colliderSpeedF;
4742 }
4743 mCcRevRate = 1.0f;
4744 mCcRevTotalOffsX = prevOffsX + currOffsX;
4745 } else {
4746 mCcRevRate = revRate;
4747 mCcRevSpeedF = colliderSpeedF;
4748 mCcRevTotalOffsX = offsX;
4749 mCcRevSet = true;
4750 }
4751 }
4752}
4753
4754void daPlBase_c::clearCcPlayerRev() {
4755 mCcRevRate = 0.0f;
4756 mCcRevSpeedF = 0.0f;
4757 mCcRevTotalOffsX = 0.0f;
4758 mCcRevTotalOffsY = 0.0f;
4759 mCcRevSet = false;
4760 mCcHasInitialRevY = false;
4761}
4762
4763bool daPlBase_c::calcCcPlayerRev(float *outShiftX) {
4764 if (mCcRevSet) {
4765 float rate = mCcRevRate;
4766 if (isStatus(STATUS_IS_SPIN_HOLD_REQ) || mCcRevDisabledTimer != 0) {
4767 rate = 0.0f;
4768 }
4769 if (isDemoType(DEMO_PLAYER) && isNowBgCross(BGC_FOOT)) {
4770 rate = 0.0f;
4771 }
4772 float prevOffsX = mCcRevTotalOffsX;
4773 mCcRevTotalOffsX = 0.0f;
4774 if (prevOffsX) {
4775 float shiftX = prevOffsX * rate;
4776 float tmp2 = 3.0f;
4777 if (shiftX > 3.0f) {
4778 shiftX = 3.0f;
4779 } else if (shiftX < -3.0f) {
4780 shiftX = -3.0f;
4781 }
4782 if (mSpeedF * prevOffsX <= 0.0f) {
4783 *outShiftX = shiftX;
4784 if (isDemoType(DEMO_PLAYER) || isStatus(STATUS_5F)) {
4785 return false;
4786 }
4787 float revSpeedF = mCcRevSpeedF;
4788 float speedF = mSpeedF;
4789 if (
4790 speedF * revSpeedF <= 0.0f &&
4791 std::fabs(mSpeedF) + std::fabs(mCcRevSpeedF) > 2.5f
4792 ) {
4793 mSpeedF = mCcRevSpeedF * 0.4f;
4794 return true;
4795 }
4796 if (
4797 std::fabs(mSpeedF) > std::fabs(mCcRevSpeedF) &&
4798 std::fabs(mSpeedF) > 1.5f
4799 ) {
4800 mSpeedF = 0.0f;
4801 return true;
4802 }
4803 }
4804 }
4805 }
4806 return false;
4807}
4808
4809bool daPlBase_c::isEnableStampPlayerJump(dCc_c *cc1, dCc_c *cc2) {
4810 daPlBase_c *other = (daPlBase_c *) cc2->mpOwner;
4811 if (isNowBgCross(BGC_FOOT)) {
4812 return false;
4813 }
4814 if (mSpeed.y >= 0.0f) {
4815 return false;
4816 }
4818 return false;
4819 }
4820 if (other->isLiftUp() || other->mSquishCooldownTimer != 0) {
4821 return false;
4822 }
4823 if (isDemoType(DEMO_PLAYER) || other->isDemoType(DEMO_PLAYER)) {
4824 return false;
4825 }
4826 float topPos = cc2->getTopPos() - 16.0f;
4827 if (topPos < cc2->getCenterPosY()) {
4828 topPos = cc2->getCenterPosY();
4829 }
4830 if (cc1->getUnderPos() > topPos) {
4831 return true;
4832 }
4833 return false;
4834}
4835
4836void daPlBase_c::setStampReduction() {
4837 if (!isStatus(STATUS_SWIM)) {
4838 if (mSpeed.y > 0.0f) {
4839 mSpeed.y = 0.0f;
4840 }
4841 setReductionScale();
4842 } else {
4843 mSpeed.y = -1.0f;
4844 }
4845}
4846
4847void daPlBase_c::setStampPlayerJump(bool b, float yOffset) {
4848 if (!isStatus(STATUS_SWIM)) {
4849 float jumpSpeed = daPlBase_c::sc_JumpSpeed;
4850 if (isMameAction()) {
4851 jumpSpeed = daPlBase_c::sc_JumpSpeed - 0.35f;
4852 }
4853 if (b) {
4854 dQuake_c::m_instance->shockMotor(mPlayerNo, dQuake_c::TYPE_7, 0, false);
4855 if (mKey.buttonJump()) {
4856 jumpSpeed = daPlBase_c::sc_JumpSpeed + 0.5f;
4857 }
4858 setJump(jumpSpeed, mSpeedF, true, 1, 0);
4859 } else {
4860 setJump(jumpSpeed, mSpeedF, true, 0, 0);
4861 }
4862 mPos.y += yOffset;
4863 } else {
4864 mSpeed.y = 1.0f;
4865 }
4866}
4867
4868void daPlBase_c::setReductionScale() {
4869 setReductionBoyon();
4870 initStampReduction();
4871}
4872
4873void daPlBase_c::initStampReduction() {
4874 if (!isStatus(STATUS_JUMP) || mSquishKeyframeIdx == 0) {
4876 }
4878 startPlayerVoice(VOICE_STOMPED, 0);
4879 dQuake_c::m_instance->shockMotor(mPlayerNo, dQuake_c::TYPE_7, 0, false);
4880}
4881
4882void daPlBase_c::calcJumpDaiReductionScale(int i1, int i2) {
4883 if (i1 > i2) {
4884 i1 = i2;
4885 }
4886 mSquishScale = i1 * 0.6f / i2;
4887 mSquishState = SQUISH_INIT;
4888}
4889
4890void daPlBase_c::setReductionBoyon() {
4891 mSquishState = SQUISH_ANIMATION;
4893}
4894
4895void daPlBase_c::calcReductionScale() {
4896 switch (mSquishState) {
4897 case SQUISH_OFF:
4898 break;
4899 case SQUISH_INIT:
4900 mSquishState = SQUISH_SET_REDUCTION;
4901 break;
4902 case SQUISH_SET_REDUCTION:
4903 setReductionBoyon();
4904 break;
4905 case SQUISH_ANIMATION:
4906 if (mSquishKeyframeIdx) {
4907 int idx = mSquishKeyframeIdx - 1;
4908 static const float scStampScaleDt[] = { 0.0f, 0.2f, 0.0f, 0.4f };
4909 static const float scStampAcceleDt[] = { 0.02f, 0.025f, 0.04f, 0.06f };
4910 if (sLib::chase(&mSquishScale, scStampScaleDt[idx], scStampAcceleDt[idx])) {
4912 }
4913 }
4914 if (mSquishKeyframeIdx == 0) {
4915 mSquishState = SQUISH_OFF;
4916 }
4917 break;
4918 }
4919}
4920
4921mVec3_c daPlBase_c::getReductionModelScale() {
4922 return mVec3_c(
4923 1.0f + mSquishScale,
4924 1.0f - mSquishScale,
4925 1.0f + mSquishScale
4926 );
4927}
4928
4929void daPlBase_c::setNoHitPlayer(const daPlBase_c *player, int duration) {
4930 mpNoHitPlayer = player;
4931 mNoHitTimer = duration;
4932}
4933
4934void daPlBase_c::updateNoHitPlayer() {
4935 if (mNoHitTimer != 0) {
4936 mNoHitTimer--;
4937 }
4938 if (mNoHitTimer == 0) {
4939 mpNoHitPlayer = nullptr;
4940 }
4941}
4942
4943daPlBase_c *daPlBase_c::getHipAttackDamagePlayer() {
4944 return (daPlBase_c *) fManager_c::searchBaseByID(mHipAttackPlayerID);
4945}
4946
4947void daPlBase_c::setHipAttackDamagePlayer(daPlBase_c *player) {
4949 mHipAttackPlayerID = player->mUniqueID;
4950}
4951
4952void daPlBase_c::clearHipAttackDamagePlayer() {
4954 mHipAttackPlayerID = (fBaseID_e) 0;
4955}
4956
4957void daPlBase_c::setNoHitObjBg(dActor_c *obj, int duration) {
4958 mBc.mpNoHitActor = obj;
4959 mNoHitObjTimer = duration;
4960}
4961
4962void daPlBase_c::calcNoHitObjBgTimer() {
4963 if (mNoHitObjTimer == 0) {
4964 return;
4965 }
4966 if (--mNoHitObjTimer == 0) {
4967 mBc.mpNoHitActor = nullptr;
4968 }
4969}
4970
4971void daPlBase_c::setOldBGCross() {
4972 mOldBgCross1 = mNowBgCross1;
4973 mOldBgCross2 = mNowBgCross2;
4974 for (int i = 9; i > 0; i--) {
4975 mBgFootHistory[i] = mBgFootHistory[i - 1];
4976 }
4977 mBgFootHistory[0] = isNowBgCross(BGC_FOOT) ? 1 : 0;
4978}
4979
4980void daPlBase_c::clearBgCheckInfo() {
4981 setOldBGCross();
4982 clearNowBgCross();
4983 mPrevStandOnUnitType = mStandOnUnitType;
4984 mStandOnUnitType = 0;
4985 mBgPushForce.set(0.0f, 0.0f, 0.0f);
4986 mExtraPushForceX = 0.0f;
4987 mGroundType = GROUND_TYPE_DEFAULT;
4988 mWaterDepth = 0;
4989 m_d80[0] = 0.0f;
4990 m_d80[1] = 0.0f;
4991}
4992
4993void daPlBase_c::bgCheck(int i) {
4994 offStatus(STATUS_AUTO_BOUNCE);
4995 offStatus(STATUS_86);
4997 offStatus(STATUS_EXTRA_PUSH_FORCE);
4998 if (isNowBgCross(BGC_FOOT)) {
4999 m_d8c = mPos.y;
5000 }
5001 clearBgCheckInfo();
5003 if (i == 1) {
5004 checkSideViewLemit();
5005 }
5006 if (!isStatus(STATUS_7E)) {
5007 checkBgCross();
5008 checkBgCrossSub();
5009 }
5010 checkWater();
5011 if (!isStatus(STATUS_7E)) {
5012 checkDamageBg();
5013 }
5014 postBgCross();
5015}
5016
5017void daPlBase_c::checkBgCross() {
5018 if (mPowerup == POWERUP_MINI_MUSHROOM && (isOldBgCross(BGC_WALL_TOUCH_L_2) | isOldBgCross(BGC_WALL_TOUCH_R_2)) == 0) {
5019 float dir = 1.0f;
5020 if (mLastPos.x > mPos.x) {
5021 dir = -1.0f;
5022 }
5023 const sBcPointData *wallData = getWallBgPointData();
5024 int wallSize = wallData->mInfMargin + wallData->mSupMargin;
5025 float offset = ((float) wallSize / 4096.0f) / 2.0f;
5026 mVec3_c p1(
5027 mLastPos.x - dir * 3.0f,
5028 mLastPos.y + offset,
5029 mLastPos.z
5030 );
5031 mVec3_c p2(
5032 mPos.x + dir * 3.0f,
5033 mPos.y + offset,
5034 mPos.z
5035 );
5036 float outX;
5037 if (mBc.checkWallPlayer(&p1, &p2, &outX) && outX != p1.x) {
5038 mPos.x = outX - dir * 3.0f;
5039 }
5040 }
5041
5042 onStatus(STATUS_80);
5043 u32 bgFlags = mBc.checkBgPlr(this);
5044 offStatus(STATUS_80);
5045
5046 if (isStatus(STATUS_7F)) {
5047 return;
5048 }
5049 mPrevMoveSakaAngle = mMoveSakaAngle;
5050 mPrevStillSakaAngle = mStillSakaAngle;
5051 mStillSakaAngle = 0;
5052 mMoveSakaAngle = 0;
5053 mStandOnUnitType = mBc.mLastUnitType;
5054
5055 if ((bgFlags & 0x3c000000) != 0) {
5056 onNowBgCross(BGC_HEAD);
5057 if (bgFlags & 0x4000000) {
5058 onNowBgCross(BGC_PRESS_HEAD_HIT);
5059 }
5060 if (bgFlags & 0x40000000) {
5061 onNowBgCross(BGC_63);
5062 }
5063 if (bgFlags & 0x80000000) {
5064 onNowBgCross(BGC_NON_BREAK_BLOCK_HIT);
5065 }
5066 if (mBc.getHeadAttr() == 6) {
5067 onNowBgCross(BGC_HANG_ROPE);
5068 }
5069 if (bgFlags & 0x20000000) {
5070 onNowBgCross(BGC_BLOCK_HIT);
5071 switch (mBc.m_c4) {
5072 case 1:
5073 onNowBgCross(BGC_58);
5074 break;
5075 case 2:
5076 onNowBgCross(BGC_57);
5077 break;
5078 }
5079 if (mBc.mpCtrFoot != nullptr &&
5080 mBc.mpCtrFoot->mpActor != nullptr &&
5081 !(
5082 mBc.mpCtrFoot->mpActor->mProfName != fProfile::EN_HATENA_BLOCK_LINE &&
5083 mBc.mpCtrFoot->mpActor->mProfName != fProfile::EN_RENGA_BLOCK_LINE
5084 )
5085 ) {
5086 onNowBgCross(BGC_LINE_BLOCK_HIT);
5087 }
5088 }
5089 }
5090
5091 if (bgFlags & 0x1fe000) {
5092 mMoveSakaAngle = mBc.getSakaAngleBySpeed(mSpeedF);
5093 mStillSakaAngle = mBc.getSakaAngle(0);
5094 if (bgFlags & 0x4000) {
5095 onNowBgCross(BGC_SLOPE);
5096 }
5097 if (bgFlags & 0x400000) {
5098 onNowBgCross(BGC_62);
5099 }
5100 if (bgFlags & 0x800000) {
5101 onNowBgCross(BGC_COIN_BLOCK_HIT);
5102 }
5103 if (bgFlags & 0x1000000) {
5104 onNowBgCross(BGC_36);
5105 }
5106 if (mMoveSakaAngle > 0 && isNowBgCross(BGC_HEAD)) {
5107 onNowBgCross(BGC_SLOPE_AND_HEAD);
5108 mSpeedF = 0.0f;
5109 }
5110 u16 footAttr = mBc.getFootAttr();
5111 switch (footAttr) {
5112 case 3:
5113 onNowBgCross(BGC_ON_SINK_SAND);
5114 break;
5115 case 7:
5116 onNowBgCross(BGC_AUTOSLIP);
5117 break;
5118 case 4:
5119 onNowBgCross(BGC_ON_BELT_R);
5120 break;
5121 case 5:
5122 onNowBgCross(BGC_ON_BELT_L);
5123 break;
5124 }
5125 if (mSpeed.y <= 0.0f) {
5126 onNowBgCross(BGC_FOOT);
5127 if (bgFlags & 0x200000) {
5128 onNowBgCross(BGC_SEMISOLID);
5129 }
5130 if (bgFlags & 0x18000) {
5131 onNowBgCross(BGC_LIFT);
5132 }
5133 if (mPos.y > mLastPos.y && !isNowBgCross(BGC_SLOPE)) {
5134 onNowBgCross(BGC_GROUNDED_MOVE_UP);
5135 }
5136 switch (footAttr) {
5137 case 2:
5138 mGroundType = GROUND_TYPE_SNOW;
5139 onNowBgCross(BGC_ON_SNOW);
5140 break;
5141 case 3:
5142 case 12:
5143 onNowBgCross(BGC_ON_SAND);
5144 if (isNowBgCross(BGC_LIFT)) {
5145 mGroundType = GROUND_TYPE_FUNSUI;
5146 } else {
5147 mGroundType = GROUND_TYPE_SAND;
5148 }
5149 break;
5150 case 15:
5151 onNowBgCross(BGC_ON_SAND);
5152 mGroundType = GROUND_TYPE_BEACH;
5153 break;
5154 case 13:
5155 mGroundType = GROUND_TYPE_DIRT;
5156 break;
5157 case 1:
5158 mGroundType = GROUND_TYPE_ICE;
5159 if (bgFlags & 0x2000000) {
5160 onNowBgCross(BGC_ON_ICE_LOW_SLIP);
5161 } else {
5162 onNowBgCross(BGC_ON_ICE);
5163 }
5164 break;
5165 case 8:
5167 mVec3_c tmp(
5168 mPos.x,
5169 mPos.y + 4.0f,
5170 mPos.z
5171 );
5172 float groundHeight;
5173 if (dBc_c::checkGround(&tmp, &groundHeight, mLayer, mAmiLayer, 8)) {
5174 if (std::fabs(groundHeight - mPos.y) < 2.0f) {
5175 onNowBgCross(BGC_CLIFF);
5176 }
5177 }
5178 } else {
5179 onNowBgCross(BGC_CLIFF);
5180 }
5181 break;
5182 case 14:
5183 mGroundType = GROUND_TYPE_CLOUD;
5184 break;
5185 case 11:
5186 mGroundType = GROUND_TYPE_CARPET;
5187 break;
5188 }
5189 if (isNowBgCross(BGC_LIFT)) {
5190 if (bgFlags & 0x40000) {
5191 mGroundType = GROUND_TYPE_MANTA;
5192 }
5193 if (bgFlags & 0x80000) {
5194 mGroundType = GROUND_TYPE_LEAF;
5195 }
5196 if (bgFlags & 0x100000) {
5197 mGroundType = GROUND_TYPE_WOOD;
5198 }
5199 }
5200 }
5201 } else {
5202 if (isStatus(STATUS_RIDE_NUT_2)) {
5203 mPos.y = mRideNutHeight;
5204 mMoveSakaAngle = 0;
5205 onNowBgCross(BGC_FOOT);
5206 }
5207 float s = getModelHeight() + mPos.y;
5208 mVec3_c checkPos(mPos.x, s + 8.0f, mPos.z);
5209 float groundHeight;
5210 int groundType;
5211 if (dBc_c::checkGround(&checkPos, &groundHeight, &groundType, mLayer, mAmiLayer, 8)) {
5212 if (checkPos.y >= groundHeight && s <= groundHeight) {
5213 if (groundType == 2) {
5214 onNowBgCross(BGC_CLIFF_ABOVE_2);
5215 } else {
5216 onNowBgCross(BGC_CLIFF_ABOVE_1);
5217 }
5218 mKaniHeight = groundHeight;
5219 }
5220 }
5221 }
5222
5223 if (mSpeed.y < 0.0f && (isStatus(STATUS_BIG_JUMP) || isStatus(STATUS_4E))) {
5224 onNowBgCross(BGC_LIFT);
5225 onNowBgCross(BGC_FOOT);
5226 onNowBgCross(BGC_37);
5227 }
5228
5229 if (bgFlags & 0x1fe000) {
5230 onNowBgCross(BGC_37);
5231 } else {
5232 float groundY3;
5233 if (dBc_c::checkGroundHalf(&mPos, &groundY3, mLayer, mAmiLayer) && (mPos.y - 16.0f < groundY3)) {
5234 onNowBgCross(BGC_37);
5235 }
5236 }
5237
5238 if (bgFlags & 0x100) {
5239 onNowBgCross(BGC_61);
5240 }
5241 if ((bgFlags & 8) || isStatus(STATUS_SLOPE_HEAD_PUSH_L)) {
5242 onNowBgCross(BGC_WALL_TOUCH_L_2);
5243 }
5244 if ((bgFlags & 4) || isStatus(STATUS_SLOPE_HEAD_PUSH_R)) {
5245 onNowBgCross(BGC_WALL_TOUCH_R_2);
5246 }
5247
5248 if ((isNowBgCross(BGC_WALL_TOUCH_L_2) | isNowBgCross(BGC_WALL_TOUCH_R_2)) != 0) {
5249 float sx = mSpeed.x;
5250 mAdjacentSlopeAngle = mBc.mAdjacentSlopeAngle;
5251 if (sx < 0.0f) {
5252 if (isNowBgCross(BGC_WALL_TOUCH_L_2)) {
5253 onNowBgCross(BGC_WALL);
5254 }
5255 } else if (sx > 0.0f) {
5256 if (isNowBgCross(BGC_WALL_TOUCH_R_2)) {
5257 onNowBgCross(BGC_WALL);
5258 }
5259 } else {
5260 static const int flags[] = { 0x1, 0x2 };
5261 if (bgFlags & flags[mDirection]) {
5262 onNowBgCross(BGC_WALL);
5263 }
5264 }
5265 }
5266
5267 if (bgFlags & 0xc0) {
5268 dBg_ctr_c *ctrWall = mBc.mpCtrWall;
5269 if (ctrWall) {
5270 if (ctrWall->m_d0 & 0x800000) {
5271 onNowBgCross(BGC_11);
5272 }
5273 if (ctrWall->m_c8 == 0 && *ctrWall->mRotation != 0) {
5274 onNowBgCross(BGC_11);
5275 }
5276 }
5277 if (bgFlags & 0x80) {
5278 onNowBgCross(BGC_OBJBG_TOUCH_L);
5279 if (isCarryObjBgCarried(1)) {
5280 onNowBgCross(BGC_OBJBG_TOUCH_CARRIED_L);
5281 }
5282 }
5283 if (bgFlags & 0x40) {
5284 onNowBgCross(BGC_OBJBG_TOUCH_R);
5285 if (isCarryObjBgCarried(0)) {
5286 onNowBgCross(BGC_OBJBG_TOUCH_CARRIED_R);
5287 }
5288 }
5289 }
5290
5291 if (bgFlags & 0x2a) {
5292 onNowBgCross(BGC_WALL_TOUCH_L);
5293 }
5294 if (bgFlags & 0x15) {
5295 onNowBgCross(BGC_WALL_TOUCH_R);
5296 }
5297 if (bgFlags & 0x800) {
5298 onNowBgCross(BGC_12);
5299 }
5300 if (bgFlags & 0x1000) {
5301 onNowBgCross(BGC_13);
5302 }
5303
5304 if (isNowBgCross(BGC_ON_SINK_SAND)) {
5305 checkSinkSand();
5306 }
5307
5308 if (!isNowBgCross(BGC_FOOT)) {
5309 if (mTopHeight < mPos.y) {
5310 mTopHeight = mPos.y;
5311 }
5313 } else {
5314 mTopHeight = mPos.y;
5315 }
5316
5317 if (isNowBgCross(BGC_HEAD) && isNowBgCross(BGC_PRESS_HEAD_HIT) && !isNowBgCross(BGC_63)) {
5318 setBgPressReq(nullptr, BG_PRESS_HEAD);
5319 }
5320 if (isNowBgCross(BGC_FOOT) && !isNowBgCross(BGC_LIFT)) {
5321 setBgPressReq(nullptr, BG_PRESS_FOOT);
5322 }
5323 if (isNowBgCross(BGC_WALL_TOUCH_L_2) && !isNowBgCross(BGC_OBJBG_TOUCH_L)) {
5324 setBgPressReq(nullptr, BG_PRESS_L);
5325 }
5326 if (isNowBgCross(BGC_WALL_TOUCH_R_2) && !isNowBgCross(BGC_OBJBG_TOUCH_R)) {
5327 setBgPressReq(nullptr, BG_PRESS_R);
5328 }
5329}
5330
5331bool daPlBase_c::isCarryObjBgCarried(u8 side) {
5332 dBg_ctr_c *ctrWall = mBc.mpCtrWalls[side];
5333 if (ctrWall != nullptr) {
5334 mVec2_c diff = ctrWall->m_a0 - ctrWall->m_ac;
5335 set_m_d80(side, diff.x);
5336 if (ctrWall->m_d0 & 0x800) {
5337 dActor_c* carriedActor = ctrWall->mpActor;
5338 if (carriedActor != nullptr && carriedActor->checkCarried(nullptr)) {
5339 return true;
5340 }
5341 }
5342 }
5343
5344 return false;
5345}
5346
5347void daPlBase_c::postBgCross() {
5348 if (isNowBgCross(BGC_HEAD)) {
5349 if (mSpeed.y > 0.0f || isStatus(STATUS_4E)) {
5350 if (
5351 !isOldBgCross(BGC_HEAD) &&
5352 !isNowBgCross(BGC_57) &&
5353 !isNowBgCross(BGC_63) &&
5354 !isNowBgCross(BGC_HANG_ROPE)
5355 ) {
5356 bool m = false;
5357 if (mPowerup == POWERUP_MINI_MUSHROOM) {
5358 m = true;
5359 }
5360 if (isNowBgCross(BGC_NON_BREAK_BLOCK_HIT)) {
5361 startSound(SE_PLY_HIT_BLOCK_BOUND, m, false);
5362 } else if (isNowBgCross(BGC_BLOCK_HIT)) {
5363 if (isNowBgCross(BGC_58)) {
5364 startSound(SE_PLY_HIT_BLOCK, m, false);
5365 } else {
5366 startSound(SE_PLY_HIT_GENERAL_OBJ, m, false);
5367 }
5368 } else {
5369 startSound(SE_PLY_HIT_BLOCK, m, false);
5370 }
5371 }
5372 }
5373 if (mSpeed.y > 0.0f) {
5374 mSpeed.y = 0.0f;
5375 mNoGravityTimer = 0;
5376 onStatus(STATUS_BF);
5377 }
5378 }
5379 if (isNowBgCross(BGC_FOOT)) {
5380 if (isNowBgCross(BGC_ON_BELT_L) | isNowBgCross(BGC_ON_BELT_R)) {
5381 mBgPushForce = mBc.mPushForce;
5382 }
5383 if (isNowBgCross(BGC_WATER_SHALLOW) || isNowBgCross(BGC_HANG_ROPE)) {
5384 mSpeed.y = 0.0f;
5385 } else if (isNowBgCross(BGC_ON_SINK_SAND)) {
5386 mSpeed.y = 0.0f;
5387 mBgPushForce.set(0.0f, mBc.mPushForce.y * getSandSinkRate(), 0.0f);
5388 } else if (isSaka() || isStatus(STATUS_SLIP_ACTIVE)) {
5389 mSpeed.y = 0.0f;
5390 } else {
5391 mSpeed.y = -2.0f;
5392 }
5393 if (isStatus(STATUS_5F)) {
5394 mSpeedF = 0.0f;
5395 }
5396 if (isNowBgCross(BGC_WATER_TOUCH) && !isNowBgCross(BGC_WATER_SHALLOW)) {
5397 mGroundType = GROUND_TYPE_WATER;
5398 }
5399 if (!isNowBgCross(BGC_LIFT) && isNowBgCross(BGC_HEAD)) {
5400 if (mBc.getSakaType() != 0 && mBc.getSakaUpDown(mDirection) == 1) {
5401 if (mDirection == DIR_LR_R) {
5403 } else {
5405 }
5406 mSpeedF = 0.0f;
5407 mPos.x = mLastPos.x;
5408 }
5409 }
5410 }
5411 if (!isNowBgCross(BGC_FOOT) && !isNowBgCross(BGC_LIFT)) {
5412 if (isOldBgCross(BGC_FOOT) && isOldBgCross(BGC_LIFT)) {
5413 m_1134 = 0.0f;
5414 if (std::fabs(mSpeedF) >= 0.01f && m_1eb.x * mSpeedF > 0.0f) {
5415 m_1134 = m_1eb.x;
5416 float add = m_1eb.x;
5417 if (std::fabs(add) > 0.01f && std::fabs(add) < 1.0f) {
5418 if (add > 1.0f) {
5419 add = 1.0f;
5420 } else {
5421 add = -1.0f;
5422 }
5423 }
5424 mPos.x += add;
5425 }
5426 }
5427 }
5428}
5429
5430float daPlBase_c::getWaterCheckPosY() {
5431 static const float scWaterOffsetY[] = { 4.0f, 8.0f, 16.0f };
5432 return mPos.y + scWaterOffsetY[getTallType(-1)];
5433}
5434
5435void daPlBase_c::checkWater() {
5436 mWaterType = dBc_c::WATER_CHECK_NONE;
5437 mPrevWaterHeight = mWaterHeight;
5438 mWaterHeight = dBg_c::m_bg_p->m_8fe00;
5439 u8 waterCheck = dBc_c::checkWater(mPos.x, mPos.y, mLayer, &mWaterHeight);
5440 if (waterCheck != dBc_c::WATER_CHECK_NONE && mPos.y <= mWaterHeight) {
5441 onNowBgCross(BGC_WATER_TOUCH);
5442 if (waterCheck == dBc_c::WATER_CHECK_WATER_BUBBLE) {
5443 onNowBgCross(BGC_WATER_BUBBLE);
5444 }
5445 }
5446 if (waterCheck == dBc_c::WATER_CHECK_NONE || waterCheck == dBc_c::WATER_CHECK_WATER_BUBBLE) {
5447 waterCheck = dBc_c::checkWater(mPos.x, getWaterCheckPosY(), mLayer, &mWaterHeight);
5448 if (waterCheck != dBc_c::WATER_CHECK_WATER_BUBBLE) {
5449 return;
5450 }
5451 onNowBgCross(BGC_WATER_SHALLOW);
5452 onNowBgCross(BGC_WATER_SUBMERGED);
5453 }
5454 switch (waterCheck) {
5455 case dBc_c::WATER_CHECK_WATER_BUBBLE: {
5456 onNowBgCross(BGC_WATER_BUBBLE);
5457 mVec2_c pos;
5458 dBc_c::getAirWaterHitPos(&pos);
5459 mAirWaterHitPos.set(pos.x, pos.y, mPos.z);
5460 short s;
5461 dBc_c::getAirWaterHitAngle(&s);
5462 mAirWaterHitAngle = s;
5463 break;
5464 }
5465 case dBc_c::WATER_CHECK_WATER: {
5466 if (getWaterCheckPosY() <= mWaterHeight) {
5467 onNowBgCross(BGC_WATER_SHALLOW);
5468 }
5469 const sBcPointData *p = getHeadBgPointData();
5470 float f = p->mOffset;
5471 if (mPos.y + f / 4096.0f <= mWaterHeight) {
5472 onNowBgCross(BGC_WATER_SUBMERGED);
5473 }
5474 mWaterDepth = dBc_c::checkWaterDepth(mPos.x, mWaterHeight, mLayer, mAmiLayer, nullptr);
5475 break;
5476 }
5477 case dBc_c::WATER_CHECK_YOGAN:
5478 case dBc_c::WATER_CHECK_POISON:
5479 if (!isStatus(STATUS_7E)) {
5480 mWaterType = waterCheck;
5481 }
5482 break;
5483 }
5484}
5485
5486void daPlBase_c::checkDamageBg() {
5489 isStatus(STATUS_53) ||
5491 ) {
5492 return;
5493 }
5494 if (!isDemoAll() || isDemoType(DEMO_KINOPIO)) {
5495 mIsBgDamage = mBc.m_e0;
5496 mBgDamageType = mBc.m_e1;
5497 switch (mWaterType) {
5498 case dBc_c::WATER_CHECK_YOGAN:
5499 mIsBgDamage = 1;
5500 mBgDamageType = 7;
5501 break;
5502 case dBc_c::WATER_CHECK_POISON:
5503 mIsBgDamage = 1;
5504 mBgDamageType = 8;
5505 break;
5506 }
5507 }
5508}
5509
5510bool daPlBase_c::setBgDamage() {
5511 if (mIsBgDamage) {
5512 mIsBgDamage = false;
5513 DamageType_e damageType = DAMAGE_BG;
5514 switch (mBgDamageType) {
5515 case 7:
5516 damageType = DAMAGE_YOGAN;
5517 break;
5518 case 8:
5519 damageType = DAMAGE_POISON;
5520 break;
5521 case 9:
5522 damageType = DAMAGE_SQUISH;
5523 break;
5524 }
5525 if (damageType == DAMAGE_BG && isNoDamage()) {
5526 return false;
5527 }
5528 return setDamage2(nullptr, damageType);
5529 }
5530 return false;
5531}
5532
5533bool daPlBase_c::checkSinkSand() {
5534 mVec3_c pos = mPos;
5535 pos.y += 128.0f;
5536 if (dBc_c::checkGround(&pos, &mSinkSandHeight, mLayer, mAmiLayer, 3)) {
5537 if (mSinkSandHeight > mPos.y) {
5538 onNowBgCross(BGC_ON_SINK_SAND);
5539 }
5540 if (mSinkSandHeight > getCenterPos().y) {
5541 onNowBgCross(BGC_IN_SINK_SAND);
5542 }
5543 if (mSinkSandHeight > mPos.y + getModelHeight()) {
5544 onNowBgCross(BGC_INSIDE_SINK_SAND);
5545 }
5546 return true;
5547 }
5548 return false;
5549}
5550
5551
5552bool daPlBase_c::checkBGCrossWall(u8 direction) {
5553 static const BgCross1_e flags[] = { BGC_WALL_TOUCH_R_2, BGC_WALL_TOUCH_L_2 };
5554 return isNowBgCross(flags[direction]);
5555}
5556
5557void daPlBase_c::checkSideViewLemit() {
5558 if (!daPyDemoMng_c::mspInstance->m_94 && isDemoType(DEMO_PLAYER)) {
5559 return;
5560 }
5562 return;
5563 }
5564 if (dScStage_c::m_loopType == 0) {
5565 float tmpL = dBg_c::m_bg_p->getLeftLimit() + mViewLimitPadding;
5566 if (mPos.x <= tmpL) {
5567 calcSideLimitMultL(tmpL);
5568 }
5569 float tmpR = dBg_c::m_bg_p->getRightLimit() - mViewLimitPadding;
5570 if (mPos.x >= tmpR) {
5571 calcSideLimitMultR(tmpR);
5572 }
5573 }
5574 checkDispSideLemit();
5575}
5576
5577bool daPlBase_c::revSideLimitCommon(float limitX) {
5578 if (mPos.x != limitX) {
5579 u8 dir = 0;
5580 if (mPos.x <= limitX) {
5581 dir = 1;
5582 }
5583 if (!isStatus(STATUS_7E)) {
5584 u16 ang = mBc.getSakaMoveAngle(dir);
5585 if (ang != 0) {
5586 mPos.y += (limitX - mPos.x) * (mAng(ang).sin() / mAng(ang).cos());
5587 }
5588 }
5589 mPos.x = limitX;
5590 return true;
5591 }
5592 return false;
5593}
5594
5595bool daPlBase_c::calcSideLimitMultL(float limitX) {
5596 onNowBgCross(BGC_SIDE_LIMIT_L);
5597 revSideLimitCommon(limitX);
5598 if (mSpeedF < 0.0f) {
5599 if (mDirection == 1) {
5600 mSpeedF = -0.01f;
5601 } else {
5602 mSpeedF = 0.0f;
5603 }
5604 return true;
5605 }
5606 return false;
5607}
5608
5609bool daPlBase_c::calcSideLimitMultR(float limitX) {
5610 onNowBgCross(BGC_SIDE_LIMIT_R);
5611 revSideLimitCommon(limitX);
5612 if (mSpeedF > 0.0f) {
5613 if (mDirection == 0) {
5614 mSpeedF = 0.01f;
5615 } else {
5616 mSpeedF = 0.0f;
5617 }
5618 return true;
5619 }
5620 return false;
5621}
5622
5623bool daPlBase_c::checkDispSideLemit() {
5624 if (isStatus(STATUS_B8) || isStatus(STATUS_81)) {
5625 return false;
5626 }
5627 if (dScStage_c::m_loopType == 1) {
5628 return false;
5629 }
5630 float dispX = dBgParameter_c::ms_Instance_p->getLoopScrollDispPosX(mPos.x);
5631 float leftLimit = dispX + mViewLimitPadding;
5632 float rightLimit = dispX + dBgParameter_c::ms_Instance_p->xSize() - mViewLimitPadding + 1.0f;
5633 switch (mIsDispLimitL) {
5634 case 0:
5635 if (mPos.x < leftLimit) {
5636 if (isOldBgCross(BGC_OBJBG_TOUCH_CARRIED_R) || !isOldBgCross(BGC_WALL_TOUCH_R_2)) {
5637 calcSideLimitMultL(leftLimit);
5638 return true;
5639 }
5640 mIsDispLimitL = 1;
5641 mDispLimitAdjL = mPos.x - leftLimit;
5642 }
5643 break;
5644 case 1: {
5645 if (mPos.x > leftLimit) {
5646 mIsDispLimitL = 0;
5647 }
5648 float diff = mPos.x - leftLimit;
5649 if (mDispLimitAdjL < diff || isOldBgCross(BGC_WALL_TOUCH_R_2)) {
5650 mDispLimitAdjL = diff;
5651 }
5652 if (mPos.x < leftLimit + mDispLimitAdjL) {
5653 calcSideLimitMultL(leftLimit + mDispLimitAdjL);
5654 return true;
5655 }
5656 break;
5657 }
5658 }
5659 switch (mIsDispLimitR) {
5660 case 0:
5661 if (mPos.x > rightLimit) {
5662 if (isOldBgCross(BGC_OBJBG_TOUCH_CARRIED_L) || !isOldBgCross(BGC_WALL_TOUCH_L_2)) {
5663 calcSideLimitMultR(rightLimit);
5664 return true;
5665 }
5666 mIsDispLimitR = 1;
5667 mDispLimitAdjR = mLastPos.x - rightLimit;
5668 }
5669 break;
5670 case 1: {
5671 if (mPos.x < rightLimit) {
5672 mIsDispLimitR = 0;
5673 }
5674 float diff = mPos.x - rightLimit;
5675 if (mDispLimitAdjR > diff || isOldBgCross(BGC_WALL_TOUCH_L_2)) {
5676 mDispLimitAdjR = diff;
5677 }
5678 if (mPos.x > rightLimit + mDispLimitAdjR) {
5679 calcSideLimitMultR(rightLimit + mDispLimitAdjR);
5680 return true;
5681 }
5682 }
5683 }
5684 return false;
5685}
5686
5688 if (dBg_c::m_bg_p->mAutoscrolls[0].mActive) {
5689 return;
5690 }
5691 float dispX = dBgParameter_c::ms_Instance_p->getLoopScrollDispPosX(mPos.x);
5692 float leftLimit = dispX + mViewLimitPadding;
5693 float rightLimit = dispX + dBgParameter_c::ms_Instance_p->xSize() - mViewLimitPadding + 1.0f;
5694 if (mPos.x < leftLimit) {
5695 mIsDispLimitL = 1;
5696 mDispLimitAdjL = mPos.x - leftLimit;
5697 }
5698 if (mPos.x > rightLimit) {
5699 mIsDispLimitR = 1;
5700 mDispLimitAdjR = mLastPos.x - rightLimit;
5701 }
5702}
5703
5704void daPlBase_c::underOverCheck() {
5705 float tmp = dBgParameter_c::ms_Instance_p->yStart() - dBgParameter_c::ms_Instance_p->ySize();
5706 float bgTop = tmp - 24.0f;
5707 float selfTop = mPos.y + getVisOffsetY() + getVisSizeY();
5708 int cond = 0;
5709 if (isItemKinopio()) {
5710 cond = 1;
5711 }
5712 if (!dBg_c::m_bg_p->mAutoscrolls[0].mActive) {
5713 if (dBg_c::m_bg_p->m_90009 == 1 || dBg_c::m_bg_p->m_90009 == 3 || daPyMng_c::mNum > 1) {
5714 cond = true;
5715 }
5716 }
5717 if (cond == 1) {
5718 if (selfTop < bgTop && selfTop < dBg_c::m_bg_p->m_8fe00) {
5719 setFallDownDemo();
5720 }
5721 } else if (selfTop < bgTop) {
5722 setFallDownDemo();
5723 }
5724}
5725
5726void daPlBase_c::checkDispOver() {
5729 offStatus(STATUS_ITEM_KINOPIO_DISPLAY_OUT);
5730 if (isStatus(STATUS_OUT_OF_PLAY) || isStatus(STATUS_53)) {
5731 return;
5732 }
5733 if (!isStatus(STATUS_7E)) {
5734 float adj = dBgParameter_c::ms_Instance_p->yStart() + 96.0f;
5735 if (dScStage_c::m_instance->mCurrWorld == WORLD_1 &&
5736 dScStage_c::m_instance->mCurrCourse == STAGE_CASTLE &&
5737 dScStage_c::m_instance->mCurrFile == 0
5738 ) {
5739 adj = dBgParameter_c::ms_Instance_p->yStart() + 192.0f;
5740 }
5741 if (mPos.y > adj) {
5742 mPos.y = adj;
5743 }
5744 underOverCheck();
5745 checkPressBg();
5746 mBgPressActive = 0;
5747 setBgDamage();
5748 }
5749 checkDisplayOutDead();
5750}
5751
5752void daPlBase_c::checkDisplayOutDead() {
5753 float offset = 20.0f;
5754 if (daPyMng_c::mNum > 1 || dBg_c::m_bg_p->m_90009 == 1 || dBg_c::m_bg_p->m_90009 == 3) {
5755 offset = 64.0f;
5756 }
5757
5758 float bgBottom = dBgParameter_c::ms_Instance_p->yStart() - dBgParameter_c::ms_Instance_p->ySize();
5759 float bgSide1 = bgBottom - 16.0f;
5760 float bgSide2 = bgBottom - offset;
5761 float edgePos = mPos.y + getVisOffsetY() + getVisSizeY();
5762 if (edgePos < bgSide1) {
5765 if (isItemKinopio()) {
5766 onStatus(STATUS_ITEM_KINOPIO_DISPLAY_OUT);
5767 }
5768 }
5769 if (edgePos < bgSide2) {
5770 setBalloonInDispOut(3);
5771 }
5772
5773 float bgTop = dBgParameter_c::ms_Instance_p->yStart();
5774 bgSide1 = bgTop + 16.0f;
5775 edgePos = mPos.y + getVisOffsetY() - getVisSizeY();
5776 if (edgePos > bgSide1) {
5778 }
5779
5780 if (isItemKinopio() && edgePos > dBgParameter_c::ms_Instance_p->yStart() + 128.0f) {
5781 onStatus(STATUS_ITEM_KINOPIO_DISPLAY_OUT);
5782 }
5783 if (isStatus(STATUS_81)) {
5784 return;
5785 }
5786
5787 offset = 0.0f;
5788 if (!isStatus(STATUS_B8)) {
5789 if (dBg_c::m_bg_p->mAutoscrolls[0].mActive && dBg_c::m_bg_p->m_9008e != 4) {
5790 offset = -(mWallBcData.mOffset / 4096.0f - 1.0f + getVisSizeX());
5791 } else if (daPyMng_c::mNum > 1) {
5792 offset = 16.0f;
5793 }
5794 }
5795
5796 float bgLeft = dBgParameter_c::ms_Instance_p->getLoopScrollDispPosX(mPos.x);
5797 bgSide1 = bgLeft - 16.0f;
5798 bgSide2 = bgLeft - offset;
5799 edgePos = mPos.x + getVisOffsetX() + getVisSizeX();
5800 if (edgePos < bgSide1) {
5803 if (isItemKinopio()) {
5804 onStatus(STATUS_ITEM_KINOPIO_DISPLAY_OUT);
5805 }
5806 }
5807 if (edgePos < bgSide2) {
5808 setBalloonInDispOut(2);
5809 }
5810
5811 bgSide1 = bgLeft + dBgParameter_c::ms_Instance_p->xSize() + 16.0f;
5812 bgSide2 = bgLeft + dBgParameter_c::ms_Instance_p->xSize() + offset;
5813 edgePos = mPos.x + getVisOffsetX() - getVisSizeX();
5814 if (edgePos > bgSide1) {
5817 if (isItemKinopio()) {
5818 onStatus(STATUS_ITEM_KINOPIO_DISPLAY_OUT);
5819 }
5820 }
5821 if (edgePos > bgSide2) {
5822 setBalloonInDispOut(0);
5823 }
5824}
5825
5826void daPlBase_c::setBgPressReq(dActor_c *actor, BgPress_e i) {
5827 mBgPressActive |= (1 << i);
5828 if (actor != nullptr) {
5829 mBgPressIDs[i] = actor->mUniqueID;
5830 } else {
5832 }
5833}
5834
5835bool daPlBase_c::isBgPress(dActor_c *actor) {
5836 u32 param = mBgPressFlags;
5837 if (param == 0) {
5838 return false;
5839 }
5840 for (int i = 1; i < BG_PRESS_COUNT; i++) {
5841 if (param & (1 << i) && mBgPressIDs[i] == actor->getID()) {
5842 return true;
5843 }
5844 }
5845 return false;
5846}
5847
5848bool daPlBase_c::setPressBgDamage(int i1, int i2) {
5849 if (i1 == DAMAGE_SQUISH) {
5850 if (setDamage2(nullptr, DAMAGE_SQUISH)) {
5851 mBc.clearBgcSaveAll();
5852 return true;
5853 }
5854 } else {
5855 if (setDamage2(nullptr, DAMAGE_DEFAULT)) {
5856 mBc.clearBgcSaveAll();
5857 dQuake_c::m_instance->shockMotor(mPlayerNo, dQuake_c::TYPE_4, 0, false);
5858 return true;
5859 }
5860 }
5861 return false;
5862}
5863
5864bool daPlBase_c::isEnablePressUD() {
5865 dBg_ctr_c *ctrHead = mBc.mpCtrHead;
5866 dBg_ctr_c *ctrFoot = mBc.mpCtrFoot;
5867 if (ctrHead != nullptr && ctrFoot != nullptr) {
5868 if (ctrHead == ctrFoot || ctrHead->m_e0 == ctrFoot->m_e0) {
5869 return false;
5870 }
5871 }
5872 return true;
5873}
5874
5875bool daPlBase_c::isEnablePressLR() {
5876 dBg_ctr_c *ctrL = mBc.mpCtrWalls[1];
5877 dBg_ctr_c *ctrR = mBc.mpCtrWalls[0];
5878 if (ctrL != nullptr && ctrR != nullptr) {
5879 if (ctrL == ctrR || ctrL->m_e0 == ctrR->m_e0) {
5880 return false;
5881 }
5882 }
5883 return true;
5884}
5885
5886bool daPlBase_c::checkPressBg() {
5887 if (
5888 (isNowBgCross(BGC_SIDE_LIMIT_L) && isNowBgCross(BGC_WALL_TOUCH_R_2)) ||
5889 (isNowBgCross(BGC_SIDE_LIMIT_R) && isNowBgCross(BGC_WALL_TOUCH_L_2))
5890 ) {
5891 return true;
5892 }
5893 if (dScStage_c::m_instance->mCurrWorld == WORLD_6 &&
5894 dScStage_c::m_instance->mCurrCourse == STAGE_CASTLE &&
5895 dScStage_c::m_instance->mCurrFile == 1 &&
5896 mPos.y >= -1420.0f
5897 ) {
5898 if (setPressBgDamage(DAMAGE_SQUISH, 1)) {
5899 mBgPressFlags |= 0x8;
5900 return true;
5901 }
5902 }
5903 if (mBgPressActive & 0x20a && mBgPressActive & 0x414 && isEnablePressUD()) {
5904 if (mBgPressActive & 0x18 && setPressBgDamage(DAMAGE_SQUISH, 1)) {
5905 if (mBgPressActive & 0x8) {
5906 mBgPressFlags |= 0x8;
5907 }
5908 if (mBgPressActive & 0x10) {
5909 mBgPressFlags |= 0x10;
5910 }
5911 return true;
5912 }
5913 if (mBgPressActive & 6 && setPressBgDamage(DAMAGE_BG, 1)) {
5914 if (mBgPressActive & 2) {
5915 mBgPressFlags |= 0x2;
5916 }
5917 if (mBgPressActive & 4) {
5918 mBgPressFlags |= 0x4;
5919 }
5920 return true;
5921 }
5922 }
5924 return false;
5925 }
5926 if (mBgPressActive & 0x1140 && mBgPressActive & 0x8a0 && isEnablePressLR()) {
5927 if (mBgPressActive & 0x60 && setPressBgDamage(DAMAGE_SQUISH, 0)) {
5928 if (mBgPressActive & 0x20) {
5929 mBgPressFlags |= 0x20;
5930 }
5931 if (mBgPressActive & 0x40) {
5932 mBgPressFlags |= 0x40;
5933 }
5934 return true;
5935 }
5936 if (mBgPressActive & 0x180 && setPressBgDamage(DAMAGE_BG, 0)) {
5937 if (mBgPressActive & 0x80) {
5938 mBgPressFlags |= 0x80;
5939 }
5940 if (mBgPressActive & 0x100) {
5941 mBgPressFlags |= 0x100;
5942 }
5943 return true;
5944 }
5945 }
5946 return false;
5947}
5948
5950 onStatus(STATUS_AUTO_BOUNCE);
5951}
5952
5953bool daPlBase_c::isRideCheckEnable() {
5954 if (mSpeed.y > 0.0f) {
5955 return false;
5956 }
5957 if (isStatus(STATUS_4E)) {
5958 dActor_c *rideActor = (dActor_c *) fManager_c::searchBaseByID(mRideActorID);
5959 if (rideActor != nullptr && rideActor->mSpeed.y > 0.0f) {
5960 return false;
5961 }
5962 }
5963 return true;
5964}
5965
5967 onStatus(STATUS_EXTRA_PUSH_FORCE);
5968 mExtraPushForceX = f;
5969}
5970
5971bool daPlBase_c::checkInsideCrossBg(float f) {
5972 const sBcPointData *wallBg = getWallBgPointData();
5973 if (wallBg == nullptr) {
5974 return false;
5975 }
5976 const sBcPointData *footBg = getFootBgPointData();
5977 if (footBg == nullptr) {
5978 return false;
5979 }
5980 float offs2[] = {
5981 footBg->mInfMargin / 4096.0f + f,
5982 footBg->mSupMargin / 4096.0f - f
5983 };
5984 float offs[] = {
5985 wallBg->mInfMargin / 4096.0f,
5986 wallBg->mSupMargin / 4096.0f
5987 };
5988 for (int i = 0; i < 2; i++) {
5989 mVec3_c modPos = mVec3_c(
5990 mPos.x,
5991 mPos.y + offs[i],
5992 mPos.z
5993 );
5994 mVec3_c copy;
5995 copy.set(
5996 modPos.x + offs2[0],
5997 modPos.y,
5998 modPos.z
5999 );
6000 if (mBc.checkWallPlayer(&modPos, &copy, nullptr)) {
6001 return true;
6002 }
6003 copy.set(
6004 modPos.x + offs2[1],
6005 modPos.y,
6006 modPos.z
6007 );
6008 if (mBc.checkWallPlayer(&modPos, &copy, nullptr)) {
6009 return true;
6010 }
6011 }
6012 return false;
6013}
6014
6016 mPowerup = powerup;
6017}
6018
6019bool daPlBase_c::isMameAction() {
6020 if (mPowerup == POWERUP_MINI_MUSHROOM && !isLiftUpExceptMame()) {
6021 return true;
6022 }
6023 return false;
6024}
6025
6027 mStatusFlags[id / 32] = (1 << (id % 32));
6028}
6029
6031 mStatusFlags[id / 32] |= (1 << (id % 32));
6032}
6033
6035 mStatusFlags[id / 32] &= ~(1 << (id % 32));
6036}
6037
6039 return mStatusFlags[id / 32] & (1 << (id % 32));
6040}
6041
6042u8 daPlBase_c::getTallType(s8) {
6043 return 2;
6044}
6045
6046void daPlBase_c::calcTimerProc() {
6047 if (sLib::calcTimer(&mDamageInvulnTimer) != 0) {
6048 if (mDamageInvulnTimer < 60) {
6049 if (mDamageInvulnTimer & 4) {
6051 }
6052 } else if (mDamageInvulnTimer & 8) {
6054 }
6055 }
6056
6057 sLib::calcTimer(&mPowerupChangeInvulnTimer);
6059 sLib::calcTimer(&mNoGravityTimer);
6064 sLib::calcTimer(&mCcRevDisabledTimer);
6065 sLib::calcTimer(&mBossDemoLandTimer);
6066 sLib::calcTimer(&mTimer_f4);
6067 sLib::calcTimer(&mSlipEndTimer);
6068
6069 updateNoHitPlayer();
6070 calcNoHitObjBgTimer();
6071}
6072
6073dPyMdlBase_c * daPlBase_c::getModel() {
6074 return mpMdlMng->mpMdl;
6075}
6076
6077void daPlBase_c::calcPlayerSpeedXY() {
6078 static const float ratios[] = { 0.6f, 0.55f, 0.5f, 0.45f, 0.4f };
6079 float extraXAccel = 0.0f;
6080 float ccRevShiftX = 0.0f;
6081 bool x = calcCcPlayerRev(&ccRevShiftX);
6082
6083 float c = 1.0f;
6084 float b = mMaxSpeedF;
6085
6087 int v = getFollowMameKuribo() - 1;
6088
6089 if (v < 0) {
6090 v = 0;
6091 }
6092 if (v > 4) {
6093 v = 4;
6094 }
6095
6096 b = mMaxSpeedF * ratios[v];
6097 }
6098
6099 if (x) {
6100 if (b < -0.5f) {
6101 b = -0.5f;
6102 }
6103 if (b > 0.5f) {
6104 b = 0.5f;
6105 }
6106 if (std::fabs(mSpeedF) > std::fabs(b)) {
6107 c = 1.0f;
6108 } else {
6109 c = 1.8f;
6110 }
6111 }
6112
6113 sLib::chase(&mSpeedF, b, mAccelF * c);
6114 calcWindSpeed();
6115
6116 float d = 5.0f;
6117 if (isStatus(STATUS_88)) {
6118 if (std::fabs(b) > 5.0f) {
6119 d = std::fabs(b);
6120 }
6121 }
6122
6123 float f = mSpeedF + mWindSpeed;
6124 if (f < -d) {
6125 f = -d;
6126 } else if (f > d) {
6127 f = d;
6128 }
6129
6130 mSpeed.x = f;
6131
6132 if (f * ccRevShiftX >= 0.0f) {
6133 mVec3_c wallvec1(mPos.x + f + ccRevShiftX, mPos.y + getModelHeight() / 2.0f, mPos.z);
6134 mVec3_c wallvec2(wallvec1.x + f + ccRevShiftX, wallvec1.y, wallvec1.z);
6135
6136 float g;
6137
6138 if (dBc_c::checkWall(&wallvec1, &wallvec2, &g, mLayer, mAmiLayer, nullptr)) {
6139 ccRevShiftX = 0.0f;
6140 }
6141 }
6142
6143 extraXAccel += ccRevShiftX;
6144
6145 if (mFinalAirPushForceX != 0.0f) {
6146 if (!isNowBgCross(BGC_FOOT)) {
6147 extraXAccel += mFinalAirPushForceX;
6148 } else {
6149 if (mFinalAirPushForceX * mSpeedF < 0.0f) {
6150 mSpeedF += mFinalAirPushForceX;
6151 }
6152 mFinalAirPushForceX = 0.0f;
6153 }
6154 }
6155
6156 if (m_1138 != 0.0f) {
6157 if (!isNowBgCross(BGC_FOOT)) {
6158 extraXAccel += m_1138;
6159 sLib::chase(&m_1138, 0.0f, m_113c);
6160 } else {
6161 m_1138 = 0.0f;
6162 }
6163 }
6164
6165 if (isNowBgCross(BGC_FOOT) && isStatus(STATUS_5F)) {
6166 mSpeedF = 0.0f;
6167 }
6168 mPrevSpeedF = mSpeedF;
6169
6170 float k = mMaxFallSpeed;
6171 if (isNowBgCross(BGC_ON_SINK_SAND) | isNowBgCross(BGC_IN_SINK_SAND)) {
6172 k = 0.0f;
6173 }
6174
6175 setSandEffect();
6176
6177 mPos += mVec3_c(mBgPushForce.x, mBgPushForce.y, mBgPushForce.z);
6178
6179 mPrevSpeedY = mSpeed.y;
6180 mSpeed.y += mAccelY;
6181
6182 if (mSpeed.y < k) {
6183 mSpeed.y = k;
6184 }
6185
6186 mVec3_c speed(
6187 mSpeed.x + extraXAccel,
6188 mSpeed.y,
6189 mSpeed.z
6190 );
6191
6192 posMoveAnglePlayer(speed);
6193}
6194
6195void daPlBase_c::posMoveAnglePenguin(mVec3_c a, unsigned short b) {
6196 mVec3_c _40(0.0f, a.y, 0.0f);
6197
6198 if (isNowBgCross(BGC_HEAD) && (_40.y > 0.0f)) {
6199 mAng angle = mBc.getHeadSakaMoveAngle(mDirection);
6200
6201 if (angle.mAngle > 0) {
6202 _40.x = sc_DirSpeed[mDirection] * std::fabs(a.y * angle.sin());
6203 }
6204
6205 _40.y = a.y * std::fabs(angle.cos());
6206 }
6207
6208 if (isNowBgCross(BGC_FOOT) && (a.y < 0.0f)) {
6209 mAng angle = mBc.getSakaMoveAngle(mDirection);
6210
6211 if (angle.mAngle < 0) {
6212 _40.x = sc_DirSpeed[mDirection] * std::fabs(a.y * angle.sin());
6213 }
6214
6215 _40.y = a.y * std::fabs(angle.cos());
6216 }
6217
6218 float x_mag = std::fabs(a.x);
6219
6220 mVec3_c delta(
6221 _40.x + x_mag * mAng(b).cos(),
6222 _40.y + x_mag * mAng(b).sin(),
6223 a.z
6224 );
6225
6226 posMove(delta);
6227}
6228
6229void daPlBase_c::posMoveAnglePlayer(mVec3_c a) {
6230 if (
6231 ((a.x > 0.0f && isNowBgCross(BGC_WALL_TOUCH_R_2)) || (a.x < 0.0f && isNowBgCross(BGC_WALL_TOUCH_L_2))) &&
6232 (std::fabs(a.x) > 2.5f)
6233 ) {
6234 if (a.x > 0.0f) {
6235 a.x = 2.5f;
6236 } else {
6237 a.x = -2.5f;
6238 }
6239 }
6240
6241 u8 dir = 0;
6242 if (a.x < 0.0f) {
6243 dir = 1;
6244 }
6245
6246 u16 x = mBc.getSakaMoveAngle(dir);
6247 if (isNowBgCross(BGC_HEAD)) {
6248 x = mBc.getHeadSakaMoveAngle(dir);
6249 }
6250
6252 posMoveAnglePenguin(a, x);
6253 return;
6254 }
6255
6256 u16 x2 = 0;
6258 x2 = mAdjacentSlopeAngle;
6259 }
6260
6261 float x_mag = std::fabs(a.x);
6262 float y = a.y;
6263
6264 mVec3_c delta(
6265 x_mag * mAng(x).cos() - y * mAng(x2).sin(),
6266 x_mag * mAng(x).sin() + y * std::fabs(mAng(x2).cos()),
6267 a.z
6268 );
6269
6270 posMove(delta);
6271}
6272
6273const sSpeedData *daPlBase_c::getSpeedData() {
6274 if (isStar()) {
6275 return mSpeedDataStar;
6276 } else {
6277 return mSpeedDataNormal;
6278 }
6279}
6280
6281void daPlBase_c::setZPosition() {
6282 if (isStatus(STATUS_99)) {
6283 return;
6284 }
6285
6286 if ((mAmiLayer == 1) && (mLayer == 0)) {
6287 mPos.z = 3000.0f - (float) (mPlayerLayer * 32);
6288 } else {
6289 mPos.z = -1800.0f - (float) (mPlayerLayer * 32);
6290 }
6291}
6292
6293void daPlBase_c::setZPosition(float a) {
6294 onStatus(STATUS_99);
6295 mPos.z = a - (float) (mPlayerLayer * 32);
6296}
6297
6298void daPlBase_c::setZPositionDirect(float a) {
6299 onStatus(STATUS_99);
6300 mPos.z = a;
6301}
6302
6303void daPlBase_c::offZPosSetNone() {
6304 offStatus(STATUS_99);
6305}
6306
6307float daPlBase_c::setJumpAddSpeedF(float a) {
6308 if (isNowBgCross(BGC_FOOT)) {
6309 return a;
6310 }
6311
6312 if (a >= 2.0f) {
6313 a = 2.0f;
6314 }
6315
6316 if (a <= -2.0f) {
6317 a = -2.0f;
6318 }
6319
6320 mFinalAirPushForceX = a;
6321 return a;
6322}
6323
6324float daPlBase_c::setAddLiftSpeedF() {
6325 float t = mExtraPushForceX;
6326
6327 if (isStatus(STATUS_EXTRA_PUSH_FORCE)) {
6328 t = mExtraPushForceX * 0.4f;
6329 }
6330
6331 return setJumpAddSpeedF(mBgPushForce.x + t);
6332}
6333
6334bool daPlBase_c::setDelayHelpJump() {
6335 if (mKey.triggerJump() && std::fabs(mSpeedF) > 1.3f) {
6336 bool x = false;
6337
6338 if (mBgFootHistory[0]) {
6339 x = true;
6340 } else if (mBgFootHistory[1]) {
6341 x = true;
6342 }
6343
6344 if (x && startJump(BLEND_DEFAULT, 1)) {
6345 return true;
6346 }
6347 }
6348 return false;
6349}
6350
6351bool daPlBase_c::startJump(AnmBlend_e blendMode, int jumpType) {
6352 if (isNowBgCross(BGC_WATER_SHALLOW) || isStatus(STATUS_AUTO_BOUNCE)) {
6353 return false;
6354 }
6355
6356 if (isNowBgCross(BGC_HEAD) && !isNowBgCross(BGC_LINE_BLOCK_HIT)) {
6357 return false;
6358 }
6359
6360 if ((mpMdlMng->mpMdl->mFlags & 1) && checkStandUpRoofOnLift()) {
6361 return setCrouchJump();
6362 }
6363
6364 if (mKey.triggerJump()) {
6365 daPlBase_c::jmpInf_c info(0.0f, jumpType, blendMode);
6366 changeState(StateID_Jump, &info);
6367 return true;
6368 }
6369
6370 return false;
6371}
6372
6373bool daPlBase_c::checkJumpTrigger() {
6374 if (isNowBgCross(BGC_FOOT) && !isNowBgCross(BGC_CLIFF)) {
6375 if (startJump(BLEND_DEFAULT, 1)) {
6376 return true;
6377 }
6378 }
6379 return false;
6380}
6381
6382bool daPlBase_c::isNoDamage() {
6383 return false;
6384}
6385
6386bool daPlBase_c::setDamage(dActor_c *, daPlBase_c::DamageType_e) {
6387 return false;
6388}
6389
6390bool daPlBase_c::setForcedDamage(dActor_c *, daPlBase_c::DamageType_e) {
6391 return false;
6392}
6393
6394bool daPlBase_c::setDamage2(dActor_c *, daPlBase_c::DamageType_e) {
6395 return false;
6396}
6397
6398bool daPlBase_c::setJump(float jumpSpeed, float speedF, bool allowSteer, int keyMode, int jumpMode) {
6399 return false;
6400}
6401
6402bool daPlBase_c::_setJump(float jumpSpeed, float speedF, bool allowSteer, int keyMode, int jumpMode) {
6403 return false;
6404}
6405
6406bool daPlBase_c::setWaitJump(float jumpSpeed) {
6407 if (isDemo() || isStatus(STATUS_OUT_OF_PLAY)) {
6408 return false;
6409 }
6410
6411 mSpeedF = 0.0f;
6412 mSpeed.y = jumpSpeed;
6414 return true;
6415}
6416
6417bool daPlBase_c::setSwimSpeed(float a, float b) {
6418 return false;
6419}
6420
6421void daPlBase_c::onFollowMameKuribo() {
6423 mNewFollowMameKuribo++;
6424}
6425
6426void daPlBase_c::clearFollowMameKuribo() {
6428 mFollowMameKuribo = mNewFollowMameKuribo;
6429 mNewFollowMameKuribo = 0;
6430}
6431
6432u32 daPlBase_c::getFollowMameKuribo() {
6433 return mFollowMameKuribo;
6434}
6435
6436bool daPlBase_c::isMaskDraw() {
6437 if (isStatus(STATUS_53) || isStatus(STATUS_64)) {
6438 return false;
6439 }
6440 return true;
6441}
6442
6443void daPlBase_c::setRideNat(float nutHeight) {
6444 onStatus(STATUS_RIDE_NUT);
6445 mRideNutHeight = nutHeight;
6446}
6447
6448void daPlBase_c::updateRideNat() {
6449 if (isStatus(STATUS_RIDE_NUT) && mSpeed.y <= 0) {
6450 if (!isStatus(STATUS_RIDE_NUT_2) && mPos.y <= mRideNutHeight) {
6451 onStatus(STATUS_RIDE_NUT_2);
6452 }
6453 } else {
6454 offStatus(STATUS_RIDE_NUT_2);
6455 }
6456}
6457
6458bool daPlBase_c::suppressSound(int suppressionMode) {
6459 if (suppressionMode == 1 && isStatus(STATUS_ENDING_DANCE_AUTO)) {
6460 return true;
6461 }
6462
6464 return true;
6465 }
6466
6467 return false;
6468}
6469
6470void daPlBase_c::startSound(ulong soundID, bool b) {
6471 if (!suppressSound(b)) {
6472 mSndObj.startSound(soundID, 0);
6473 }
6474}
6475
6476void daPlBase_c::startSound(ulong soundID, short s, bool b) {
6477 if (!suppressSound(b)) {
6478 mSndObj.startSound(soundID, s, 0);
6479 }
6480}
6481
6482void daPlBase_c::holdSound(ulong soundID, bool b) {
6483 if (!suppressSound(b)) {
6484 mSndObj.holdSound(soundID, 0);
6485 }
6486}
6487
6488void daPlBase_c::holdSound(ulong soundID, short s, bool b) {
6489 if (!suppressSound(b)) {
6490 mSndObj.holdSound(soundID, s, 0);
6491 }
6492}
6493
6495 if (!suppressSound(b)) {
6496 mSndObj.fn_8019AAB0(a, 0);
6497 }
6498}
6499
6501 if (!suppressSound(b)) {
6502 mSndObj.fn_8019ABB0(a, 0);
6503 }
6504}
6505
6506void daPlBase_c::startFootSoundPlayer(unsigned long a) {
6507 if (!suppressSound(1)) {
6508 mSndObj.startFootSound(a, std::fabs(mSpeedF), 0);
6509 }
6510}
6511
6512void daPlBase_c::setItemCompleteVoice() {
6513 startPlayerVoice(VOICE_ITEM_COMPLETE, 0);
6514}
6515
6516void daPlBase_c::setStar(daPlBase_c::StarSet_e, int) {}
6517
6518void daPlBase_c::clearTreadCount() {
6519 mTreadCount = 0;
6520}
6521
6522s8 daPlBase_c::calcTreadCount(int max) {
6523 if (mTreadCount < max) {
6524 mTreadCount++;
6525 }
6526
6527 return mTreadCount;
6528}
6529
6530void daPlBase_c::clearStarCount() {
6531 mStarCount = 0;
6532}
6533
6534s8 daPlBase_c::calcStarCount(int max) {
6535 if (isStar() && mStarCount < max) {
6536 mStarCount++;
6537 }
6538
6539 return mStarCount;
6540}
6541
6542void daPlBase_c::clearComboCount() {
6543 mPlComboCount = 0;
6544}
6545
6546s8 daPlBase_c::calcComboCount(int max) {
6547 if (mPlComboCount < max) {
6548 mPlComboCount++;
6549 }
6550 return mPlComboCount;
6551}
6552
6553void daPlBase_c::startQuakeShock(dQuake_c::TYPE_SHOCK_e arg) {
6554 dQuake_c::m_instance->shockMotor(mPlayerNo, arg, 0, false);
6555}
6556
6557void daPlBase_c::startPatternRumble(const char *pattern) {
6558 if (dRemoconMng_c::m_instance->mRemocons[mPlayerNo]->mIsRumbleEnabled) {
6559 mPad::g_core[dRemoconMng_c::m_instance->mRemocons[mPlayerNo]->mControllerID]->startPatternRumble(pattern, 0, false);
6560 }
6561}
6562
6563mVec3_c daPlBase_c::getAnkleCenterPos() {
6564 mVec3_c joint7Pos;
6565 mVec3_c joint4Pos;
6566
6567 mpMdlMng->mpMdl->getJointPos(&joint4Pos, 4);
6568 mpMdlMng->mpMdl->getJointPos(&joint7Pos, 7);
6569
6570 return (joint4Pos + joint7Pos) / 2.0f;
6571}
6572
6573void daPlBase_c::calcHeadAttentionAngle() {
6574 if (isStatus(STATUS_NO_ANIM)) {
6575 return;
6576 }
6577
6578 mAng3_c angle(
6579 mAng(0),
6580 mpMdlMng->getAng().y,
6581 mpMdlMng->getAng().z
6582 );
6583
6584 if (!isLiftUp() && !isStatus(STATUS_94) && !isStatus(STATUS_WAS_TWIRL)) {
6585 if ((mpMdlMng->mpMdl->mFlags & 0x80) || (mpMdlMng->mpMdl->mFlags & 0x100)) {
6586 mAng r31 = mAngle.y;
6587 mAng r30 = 0;
6588 bool cond = false;
6589 daPlBase_c *pdVar10 = nullptr;
6590
6591 if (mpMdlMng->mpMdl->mFlags & 0x100) {
6592 if (isStatus(STATUS_95)) {
6593 pdVar10 = (daPlBase_c *) dAttention_c::mspInstance->searchPlayer(this, mpMdlMng->getHatPos());
6594 }
6595 } else {
6596 pdVar10 = (daPlBase_c *) dAttention_c::mspInstance->search(mpMdlMng->getHatPos());
6597 }
6598
6599 if (pdVar10 != nullptr) {
6600 mVec3_c hatPos = mpMdlMng->getHatPos();
6601 mVec3_c _60 = mVec3_c(
6602 pdVar10->getLookatPos().x - hatPos.x,
6603 pdVar10->getLookatPos().y - hatPos.y,
6604 8.0f
6605 );
6606
6607 int tmp = cM::atan2s(_60.y, _60.xzLen());
6608 short r27 = -tmp;
6609 short r4 = 0x2000;
6610
6611 if (pdVar10->mAttentionFlags & 2) {
6612 r4 = 0xC00;
6613 }
6614
6615 if (r27 > r4) {
6616 r27 = r4;
6617 }
6618
6619 int neg = -r4;
6620 if (r27 < neg) {
6621 r27 = neg;
6622 }
6623
6624 int temp = cM::atan2s(_60.x, _60.z);
6625 short iVar2 = (temp - mAngle.y.mAngle);
6626
6627 if (pdVar10->mAttentionMode == 3) {
6628 mpMdlMng->mpMdl->m_204 = 2;
6629
6630 int r29 = mpMdlMng->mpMdl->mFlags & 0x100;
6631 s16 r30_tmp = 0x5000;
6632 if (r29) {
6633 r30_tmp = 0x2000;
6634 }
6635
6636 int r3 = abs(iVar2);
6637
6638 if (r3 > r30_tmp) {
6639 if (iVar2 > 0) {
6640 temp = (mAng(r30_tmp) + mAngle.y).mAngle;
6641 } else {
6642 temp = (mAngle.y - mAng(r30_tmp)).mAngle;
6643 }
6644 }
6645
6646 r31 = temp;
6647
6648 if (r29) {
6649 r30 = r27;
6650 } else {
6651 float tmpf = std::fabs(mAng(r3 / 2.0f).cos());
6652 r30 = r27 * tmpf;
6653 }
6654 cond = true;
6655 } else if (abs(iVar2) < 0x4000) {
6656 mpMdlMng->mpMdl->m_204 = 1;
6657 r30 = r27;
6658 cond = true;
6659 }
6660 }
6661
6662 sLib::addCalcAngle(&angle.y.mAngle, r31.mAngle, 8, 0x400, 0x40);
6663 if (pdVar10 != nullptr && (pdVar10->mAttentionFlags & 1)) {
6664 sLib::addCalcAngle(&angle.z.mAngle, r30.mAngle, 8, 0x180, 0x40);
6665 } else {
6666 sLib::addCalcAngle(&angle.z.mAngle, r30.mAngle, 8, 0x400, 0x40);
6667 }
6668
6669 mpMdlMng->setAng(angle);
6670
6671 if (!cond && angle.z == 0 && abs(angle.y.mAngle - mAngle.y.mAngle) < 0x100) {
6672 mpMdlMng->mpMdl->m_204 = 0;
6673 }
6674
6675 return;
6676 }
6677 }
6678
6679 angle.y = 0;
6680 angle.z = 0;
6681 mpMdlMng->setAng(angle);
6682 mpMdlMng->mpMdl->m_204 = 0;
6683}
void add(cOwnerSetNd_c *nd, void *owner)
Adds a node to the set.
void onStatus(u16 status)
Enables a status flag. status is a STATUS_e.
bool buttonWalk(int *direction) const
Returns whether left / right is pressed down. Sets the direction to 0 for right and 1 for left.
@ STATUS_FORCE_NO_JUMP
Force a jump input to be ignored.
@ STATUS_FORCE_RIGHT
Override the input to always only be the right button.
@ STATUS_DISABLE_LR
Disable left and right directional buttons.
@ STATUS_FORCE_JUMP
Force the jump button to be pressed down.
@ STATUS_DEMO
Do not use inputs from the remote.
@ STATUS_NO_INPUT
Disable all inputs.
The minimum required implementation for a stage actor.
Definition d_actor.hpp:15
static u8 mExecStopReq
The actors for which the execute operation is requested to be disabled.
Definition d_actor.hpp:407
u8 mExecStopMask
The mask required to disable the execute operation for the actor.
Definition d_actor.hpp:376
virtual s8 & getPlrNo()
Gets the player number associated with the actor. See mPlayerNo.
Definition d_actor.hpp:105
dBc_c mBc
The actor-to-tile collision sensor.
Definition d_actor.hpp:342
virtual mVec2_c getLookatPos() const
Gets the position players look to when focused on the actor.
Definition d_actor.cpp:575
mVec2_c m_1eb
Definition d_actor.hpp:345
u8 mKind
The actor's kind. Value is a STAGE_ACTOR_KIND_e.
Definition d_actor.hpp:374
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 void postExecute(fBase_c::MAIN_STATE_e status)
post method for the execute operation.
Definition d_actor.cpp:122
int mAttentionMode
Definition d_actor.hpp:370
virtual int preExecute()
pre method for the execute operation.
Definition d_actor.cpp:104
s8 mPlayerNo
The player associated with the actor, -1 if not associated to any player.
Definition d_actor.hpp:375
bool checkCarried(int *playerNum)
Returns whether the actor is being carried by a player.
Definition d_actor.cpp:784
dActor_c()
Constructs a new actor.
Definition d_actor.cpp:46
dRc_c mRc
The actor's ride surface manager.
Definition d_actor.hpp:343
u32 mAttentionFlags
Definition d_actor.hpp:371
@ STAGE_ACTOR_YOSHI
The Yoshi actor.
Definition d_actor.hpp:48
u8 mLayer
The actor's layer.
Definition d_actor.hpp:377
bool mVisible
Whether the actor should be visible or not. Defaults to true .
virtual int preDraw()
pre method for the draw operation.
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.
float mSpeedF
The actor's horizontal speed.
void posMove()
Moves the actor by its speed.
float mMaxFallSpeed
The actor's maximum fall speed.
mVec3_c getCenterPos() const
Gets the actor's centered position.
mAng3_c mAngle
The actor's rotation (for 2D actors).
float mAccelY
The actor's vertical acceleration.
float mMaxSpeedF
The actor's maximum horizontal speed.
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
static unsigned int mGameFlag
See GAME_FLAG_e.
Definition d_info.hpp:92
@ GAME_FLAG_MULTIPLAYER_MODE
Whether the game is in a multiplayer mode.
Definition d_info.hpp:35
@ GAME_FLAG_IS_COIN_BATTLE
Whether the game is in Coin Battle mode.
Definition d_info.hpp:37
void setBattleCoin(int plrNo, int value)
Rewards a battle coin to a player.
void setClapSE()
Plays the clap sound effect.
static dMultiMng_c * mspInstance
The instance of this class.
static dNext_c * m_instance
The singleton instance of this class.
Definition d_next.hpp:74
bool mStartSceneChange
Whether a scene change should be performed next time execute() is called.
Definition d_next.hpp:69
void setChangeSceneNextDat(u8 fileIdx, u8 nextGoto, dFader_c::fader_type_e faderType)
Updates the saved entrance data for the next scene change if not already set.
Definition d_next.cpp:39
static sRailInfoData * getRailInfoP(u8 id)
Gets the rail data for the specified ID.
Definition d_rail.cpp:4
void fn_800e25a0(ulong, int, int)
The base class for the player and Yoshi.
virtual void changeState(const sStateIDIf_c &stateID, void *arg)
Transitions to a new state with the given state ID and argument.
int mDokanEnterNextGotoID
Value is a ControlDemoState_e.
bool suppressSound(int suppressionMode)
void onStatus(int id)
Enables the status with the given ID. See Status_e.
static sFStateVirtualID_c< daPlBase_c > StateID_DemoInWaterTank
Entering an area via a water tank pipe.
virtual void setPowerup(PLAYER_POWERUP_e, int)
void offStatus(int id)
Disables the status with the given ID. See Status_e.
int mTimer_a8
[Seems unused - set to 0 when leaving a rolling hill].
float mSquishScale
The current scale of the player during the squish animation.
void startSound(ulong soundID, bool)
int mSquishNoMoveTimer
Timer for how long to freeze the squished player in position.
@ KANI_ARG_JUMP_HANG
Falling onto the cliff, immediately hang from it.
virtual void holdPlayerVoice(int, int)
void holdSound(ulong soundID, bool)
void setExtraPushForce(float f)
static sFStateVirtualID_c< daPlBase_c > StateID_DemoOutWaterTank
Leaving an area via a water tank pipe.
void setDemoOutNextGotoBlock(int nextGotoID, int delay, int fadeType)
@ BGC_WATER_SUBMERGED
Fully submerged in water.
@ BGC_WATER_SHALLOW
At least slightly inside of water (hip height or higher).
@ BGC_HEAD
Colliding with the head sensor.
@ BGC_OBJBG_TOUCH_CARRIED_L
The touching background object on the left is being carried by a player.
@ BGC_OBJBG_TOUCH_R
Touching a background object on the right.
@ BGC_FOOT
Colliding with the foot sensor.
@ BGC_WALL
Colliding with the wall sensor.
@ BGC_OBJBG_TOUCH_CARRIED_R
The touching background object on the right is being carried by a player.
@ BGC_WATER_BUBBLE
Inside a floating water bubble.
@ BGC_OBJBG_TOUCH_L
Touching a background object on the left.
@ BGC_WATER_TOUCH
At least touching water.
sFStateMgr_c< daPlBase_c, sStateMethodUsr_FI_c > mStateMgr
The state manager for regular player states.
float mCcRevRate
Multiplier for position revision for colliders. 1.0f moves to the target immediately.
int mGoalDemoIndex
Indicates where the player is in the order of players which have touched the goal pole,...
mVec3_c mBgPushForce
Belts, quicksand etc.
virtual int create()
do method for the create operation.
bool mIsDemoMode
Whether the player is currently in a demo (cutscene) state.
static sFStateVirtualID_c< daPlBase_c > StateID_DemoOutDokanRoll
Leaving an area via a rolling hill pipe. Argument: None.
int mSquishKeyframeIdx
The current target index for the squishing animation keyframes.
float mDispLimitAdjR
The distance by which the player is too far right.
mEf::levelEffect_c mBrakeSmokeEffect
Smoke when turning around after running.
bool startJump(AnmBlend_e blendMode, int jumpType)
static sFStateVirtualID_c< daPlBase_c > StateID_HipAttack
Ground pounding. Argument: See HipAttackArg_e.
mEf::levelEffect_c mRunEffect
E.g. sand particles / snowflakes when running.
mEf::levelEffect_c mSlipSmokeEffect
Smoke when sliding down a slope or into a cannon.
void getPowerChangeSpeedData(sPowerChangeSpeedData &data)
static sFStateVirtualID_c< daPlBase_c > StateID_Fall
Falling. Argument: Should play animation (bool).
static sFStateVirtualID_c< daPlBase_c > StateID_DemoInDokanU
Entering an area via a pipe above the player. Argument: Pipe type (DokanType_e).
static sFStateVirtualID_c< daPlBase_c > StateID_Kani
Moving on a cliff. Argument: See KaniArg_e.
@ HIP_ATTACK_ARG_PLAYER
A regular player is doing a ground pound.
@ HIP_ATTACK_ARG_ITEM_KINOPIO
The rescue Toad is doing a ground pound out of the item block.
virtual void startPlayerVoice(int, int)
void initDemoInDokanUD(u8)
static sFStateVirtualID_c< daPlBase_c > StateID_JumpDai
Jumping on a spring. Argument: None.
u8 mWaterType
Value is a dBc_c::WATER_TYPE_e.
static sFStateVirtualID_c< daPlBase_c > StateID_Jump
Jumping. Argument: Jump information (jmpInf_c *).
mEf::levelEffect_c mQuicksandSinkEffect
Sand particles when the player is submerged in quicksand.
mVec3_c mJumpDaiOffset
The difference vector between this player and the player being jumped on.
virtual bool _setJump(float jumpSpeed, float speedF, bool allowSteer, int keyMode, int jumpMode)
Starts a jump action unconditionally. See setJump().
@ GOAL_DEMO_POLE_JUMP
Jumping off the pole.
@ GOAL_DEMO_POLE_TURN
Turning toward the screen.
@ GOAL_DEMO_POLE_SWING
Swinging around the pole to the other side.
@ GOAL_DEMO_POLE_WAIT_END
Waiting sc_DemoPoleWaitEnd frames before transitioning to the course clear dance.
@ GOAL_DEMO_POLE_WAIT_JUMP
Waiting at the bottom of the pole to jump off.
@ GOAL_DEMO_POLE_SLIDE
Sliding down the pole.
@ GOAL_DEMO_WAIT_BELOW_PLAYER
Waiting for the player below to slide far enough down the pole to not be in the way of this player.
@ GOAL_DEMO_POLE_WAIT_TURN
Waiting sc_DemoPoleWaitTurn frames to turn toward the screen.
@ GOAL_DEMO_POLE_LAND
Playing the landing animation after landing.
virtual int doDelete()
do method for the delete operation.
int mNoHitTimer
Timer for how long the no-hit status lasts.
static sFStateVirtualID_c< daPlBase_c > StateID_Swim
Swimming. Argument: See SwimArg_e.
static sFStateVirtualID_c< daPlBase_c > StateID_DemoStartWait
Course in default state. Argument: None.
static sFStateVirtualID_c< daPlBase_c > StateID_DemoGoal
Goal pole cutscene. Argument: Is Yoshi (bool).
static sFStateVirtualID_c< daPlBase_c > StateID_DemoControl
Cutscene controlling the player. Argument: See ControlDemoSubstate_e.
virtual int preExecute()
pre method for the execute operation.
sFStateMgr_c< daPlBase_c, sStateMethodUsr_FI_c > mDemoStateMgr
The state manager for demo (cutscene) states.
void calcSpeedOnIceLift()
int mAirWalkTimer
Timer to wait before changing to the falling state after walking off a ledge.
SquishState_e mSquishState
The player's current squish state for being jumped on by another player.
mEf::levelEffect_c mQuicksandSplashEffect
Sand splash effect when landing on quicksand.
float mKaniHeight
The height of the last cliff the player interacted with.
void setStatus(int id)
AnimePlayArg_e
Arguments for transitioning to the animation state.
dEf::followEffect_c mTurnSmokeEffect
The wind effect when turning around after running.
static sFStateVirtualID_c< daPlBase_c > StateID_AnimePlay
Playing a cutscene animation. Argument: See AnimePlayArg_e.
static sFStateVirtualID_c< daPlBase_c > StateID_DemoInDokanD
Entering an area via a pipe below the player. Argument: Pipe type (DokanType_e).
static sFStateVirtualID_c< daPlBase_c > StateID_DemoInDokanL
Entering an area via a pipe to the left of the player. Argument: Pipe type (DokanType_e).
static const int sc_DemoPoleWaitEnd
Number of frames to wait before doing the course clear pose in the goal pole animation.
DemoWaitArg_e
Arguments for transitioning to the demo wait state.
@ JUMP_DAI_HIGH_JUMP
The jump button was pressed to do a higher jump.
@ JUMP_DAI_MOVE_DOWN
Moving down on the player or spring.
static const int sc_DemoWaitDuration
Number of frames to wait before transitioning from StateID_DemoWait.
static sFStateVirtualID_c< daPlBase_c > StateID_DemoNextGotoBlock
Transition to a new area. Argument: Lower 8 bits: next goto ID, upper 8 bits: fader type (dFader_c::f...
static sFStateVirtualID_c< daPlBase_c > StateID_PlayerJumpDai
Jumping on a player. Argument: None.
float mAirTopHeight
The highest Y position since being on the ground last. Not reset when landing on the ground.
static sFStateVirtualID_c< daPlBase_c > StateID_DemoOutDokanU
Leaving an area via a pipe above the player. Argument: None.
int mDemoStateArg
To be used as an argument to the new demo state.
static const int sc_DokanEnterThreshold
static sFStateVirtualID_c< daPlBase_c > StateID_DemoOutDokanR
Leaving an area via a pipe to the right of the player. Argument: None.
bool isHitGroundKinopioWalk(int, float, int)
mEf::levelEffect_c mSmokeEffect
static sFStateVirtualID_c< daPlBase_c > StateID_DemoInDokanR
Entering an area via a pipe to the right of the player. Argument: Pipe type (DokanType_e).
mEf::levelEffect_c mHitAttackDropEffect
The wind effect when doing a ground pound.
fBaseID_e mBgPressIDs[13]
Index into this array with BgPress_e.
float mDispLimitAdjL
The distance by which the player is too far left.
mVec2_c mDokanMoveSpeed
Direction to move the player while entering a rolling hill pipe or a rail pipe.
static sFStateVirtualID_c< daPlBase_c > StateID_DemoNone
Default demo state, checking for pipe entry. Argument: Whether to not force execution start (bool).
virtual int draw()
do method for the draw operation.
void getTurnPower(sTurnPowerData &)
virtual bool setJump(float jumpSpeed, float speedF, bool allowSteer, int keyMode, int jumpMode)
Starts a jump action with the given parameters.
int mTimer_ce8
[Related to balloon break jump]
const daPlBase_c * mpNoHitPlayer
The player that cannot collide with this player.
float getWaterDokanCenterOffset(float)
float mTopHeight
Stores the highest Y position reached, resets when landing on the ground again.
@ STATUS_SPIN
The player is spinning, either from a spin jump, a propeller spin (upwards or downwards) or screw spi...
@ STATUS_POLE
The player is climbing a pole.
@ STATUS_TWIRL
The player is twirling in midair.
@ STATUS_INVULNERABLILITY_BLINK
Skip drawing the player this frame to create a blinking effect.
@ STATUS_PENGUIN_SWIM
The player is swimming with the penguin suit.
@ STATUS_DISPLAY_OUT_NO_DAMAGE
The player is outside of the screen bounds and should not be able to be attacked.
@ STATUS_17
[Dokan related]
@ STATUS_WAIT_JUMP
The player is doing a small hop after being affected by a small quake.
@ STATUS_SINK_SAND_JUMP
The player is jumping while in sinking sand.
@ STATUS_SLOPE_HEAD_PUSH_R
The player cannot move further right on a slope because of a ceiling.
@ STATUS_IS_SPIN_HOLD_REQ
If the player spins, stay in place. [Used for the twisting screws].
@ STATUS_GOAL_POLE_TOUCHED
The player has touched the goal pole.
@ STATUS_VINE
The player is clinging to a vine / mesh net / rock wall.
@ STATUS_8D
[Cannon shot related]
@ STATUS_ENEMY_STAGE_CLEAR
The player has cleared an enemy ambush.
@ STATUS_INITIAL_SLIDE
The player is in an initial slide action. [Used in 6-6 to slide all the way down automatically].
@ STATUS_SPRING_JUMP
The player is doing a jump on a springboard.
@ STATUS_QUAKE_SMALL
A small quake that makes the player do a hop was triggered.
@ STATUS_PRESS_ATTACH
The player is is attached to a enemy while ground pounding or doing a down spin. [Used for the big go...
@ STATUS_DISPLAY_OUT_DEAD
The player is outside of the screen bounds and should die as a result.
@ STATUS_GOAL_POLE_CAN_SLIDE
The player can start sliding down the goal pole.
@ STATUS_PLAYER_JUMP
The player is doing a jump on another player.
@ STATUS_INVISIBLE
The player is invisible.
@ STATUS_ABOUT_TO_BE_DELETED
[Yoshi only?]
@ STATUS_QUAKE
The player was stunned by an earthquake.
@ STATUS_HIP_ATTACK
The player is in the ground pound action and is not yet about to stand back up.
@ STATUS_HIP_ATTACK_LAND
The player has landed after ground pounding. Only active on one frame.
@ STATUS_PENGUIN_SLIDE
The player is sliding with the penguin suit.
@ STATUS_WAS_TWIRL
The player was twirling in midair the previous frame.
@ STATUS_GOAL_POLE_TURN
The player is turning toward the screen after jumping off the goal pole.
@ STATUS_JUMP
The player is jumping.
@ STATUS_STOP_EXECUTE
Stop executing this player indefinitely.
@ STATUS_FOLLOW_MAME_KURIBO
Mini Goombas are attached to the player.
@ STATUS_SPIN_HIP_ATTACK_FALL
The player is falling while doing a down spin.
@ STATUS_CAN_SPIN
The player can shake the controller to do a spin jump or a propeller spin.
@ STATUS_GOAL_POLE_READY_FOR_JUMP_OFF
The player is ready to jump off the goal pole.
@ STATUS_BIG_JUMP
The player is doing a jump on a spring or another player.
@ STATUS_HIP_ATTACK_DAMAGE_PLAYER
The player was ground pounded by another player.
@ STATUS_JUMP_DAI_COOLDOWN
The player recently failed to perform a big jump because of a ceiling.
@ STATUS_RIDE_YOSHI
The player is riding Yoshi.
@ STATUS_HIP_ATTACK_STAND_UP
The player is standing up after ground pounding. Only active on one frame.
@ STATUS_CAN_WATER_WALK
The player can walk on water because of the mini mushroom.
@ STATUS_OUT_OF_PLAY
The player is in a bubble or has died.
@ STATUS_QUAKE_BIG
A big quake that stuns the player was triggered.
@ STATUS_HIP_ATTACK_FALL
The player is falling while ground pounding.
@ STATUS_CAN_EXECUTE
The player can execute this frame or not.
@ STATUS_IS_PENGUIN
The player is in the penguin suit.
@ STATUS_SLOPE_HEAD_PUSH_L
The player cannot move further left on a slope because of a ceiling.
@ STATUS_DISABLE_STATE_CHANGE
Disallow state changes.
@ STATUS_WIND_AIRBORNE
The player is airborne while in a wind zone.
@ STATUS_STUNNED
Stunned by electric shock or ice.
@ STATUS_WALL_SLIDE
The player is sliding down a wall.
@ STATUS_DEMO_NEXT_GOTO_BLOCK
The player is transitioning after touching a next goto area.
@ STATUS_GOAL_POLE_WAIT_BELOW_PLAYER
The player is waiting for the player below to slide down the goal pole.
@ STATUS_SWIM_AGAINST_JET_H
The player is swimming against a horizontal water jet stream.
@ STATUS_PROPEL_NO_ROLL
Don't rotate the player because of the propeller suit.
@ STATUS_GOAL_POLE_FINISHED_SLIDE_DOWN
The player has reached the bottom of the goal pole after sliding down.
@ STATUS_SWIM
The player is swimming.
@ STATUS_SLIP_ACTIVE
The player is sliding.
@ STATUS_GOAL_POLE_NOT_GOAL_NO_MOVE
The player did not reach the goal pole in time and mustn't move anymore.
@ STATUS_SWIM_AGAINST_JET_V
The player is swimming against a vertical water jet stream.
@ STATUS_JUMP_COUNT_INCREASED
The jump combo counter was incremented this frame.
@ STATUS_40
[Water jump?]
@ STATUS_NO_ANIM
Don't play any animations.
@ STATUS_A5
[Jump moving up?]
static sFStateVirtualID_c< daPlBase_c > StateID_DemoOutDokanD
Leaving an area via a pipe below the player. Argument: None.
virtual int preDraw()
pre method for the draw operation.
void * mStateArg
To be used as an argument to the new state.
static sFStateVirtualID_c< daPlBase_c > StateID_Turn
Turning around after running fast. Argument: None.
static sFStateVirtualID_c< daPlBase_c > StateID_DemoWait
Waiting before transitioning to StateID_DemoNone or StateID_DemoControl. Argument: See DemoWaitArg_e.
static sFStateVirtualID_c< daPlBase_c > StateID_Slip
Sliding down a slope. Argument: None.
int wasStaffCreditGroundHipAttack
Whether the floor was ground pounded during the staff credits. [Used to allow for the coin block grou...
void setControlDemoCutscene(AnimePlayArg_e animID)
virtual int execute()
do method for the execute operation.
void slipPowerSet(int)
static const int sc_DemoPoleWaitTurn
Number of frames to wait before turning towards the screen in the goal pole animation.
int mSubstateValue
States can use this field for various purposes - as a timer, boolean flag, etc.
static sFStateVirtualID_c< daPlBase_c > StateID_Crouch
Crouching on the ground. Argument: See CrouchArg_e.
virtual void postExecute(fBase_c::MAIN_STATE_e status)
post method for the execute operation.
static sFStateVirtualID_c< daPlBase_c > StateID_SitJump
Crouch jump. Argument: Should initiate jump (bool).
u8 mIsDispLimitR
Whether the player is too far to the right and should be pushed to the left.
static sFStateVirtualID_c< daPlBase_c > StateID_WaitJump
Doing a hop caused by a small quake. Argument: None.
static sFStateVirtualID_c< daPlBase_c > StateID_Cloud
Riding a cloud. Argument: None.
static sFStateVirtualID_c< daPlBase_c > StateID_Funsui
Being blown upwards by a fountain. Argument: None.
static sFStateVirtualID_c< daPlBase_c > StateID_None
Default state, does nothing. Argument: None.
bool isStatus(int id)
u8 mIsDispLimitL
Whether the player is too far to the left and should be pushed to the right.
static sFStateVirtualID_c< daPlBase_c > StateID_Walk
Player on the ground. Argument: Blending mode (AnmBlend_e).
void changeDemoState(const sStateIDIf_c &stateID, int arg)
Transitions to a new state with the given state ID and argument.
int mSquishCooldownTimer
Cooldown for another player to squish this player.
@ CROUCH_ARG_FROM_OTHER
Crouching after a slide or a ground pound.
static sFStateVirtualID_c< daPlBase_c > StateID_DemoOutDokanL
Leaving an area via a pipe to the left of the player. Argument: None.
static sFStateVirtualID_c< daPlBase_c > StateID_DemoRailDokan
Transitioning between two rail pipes without leaving the area. Argument: None.
AnmBlend_e
Blending modes for animations.
@ BLEND_DEFAULT
Use the default blend duration specified in the animation HIO.
@ BLEND_NONE
Do not blend between animations.
@ BGC_37
Cannot wall kick or ground pound while this is set.
@ BGC_VINE_TOUCH_R
Touching a vine / mesh net / rock wall on the right.
@ BGC_LIFT
[Figure out a better name for this].
@ BGC_VINE_TOUCH_L
Touching a vine / mesh net / rock wall on the left.
MAIN_STATE_e
The possible operation results.
Definition f_base.hpp:36
@ SUCCESS
The operation was completed successfully.
Definition f_base.hpp:39
@ 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
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
static fBase_c * searchBaseByProfName(ProfileName profID, const fBase_c *parent)
Searches for a base with a given profile name, optionally under a given parent.
Definition f_manager.cpp:26
@ HIDDEN
The screen is completely unblocked.
static mFaderBase_c * mFader
The fader currently in use.
Definition m_fader.hpp:18
void multVecZero(nw4r::math::VEC3 &out) const
Extracts the translation vector from the matrix.
Definition m_mtx.cpp:135
void ZrotM(mAng angle)
Rotates the matrix on the Z axis by the given angle.
Definition m_mtx.cpp:93
A three-dimensional floating point vector.
Definition m_vec.hpp:122
float normalize()
Normalizes the vector.
Definition m_vec.cpp:17
The interface for state IDs.
PLAYER_POWERUP_e
The identifiers for each powerup.
fBaseID_e
A unique identifier for each base.
Definition f_base_id.hpp:6
@ BASE_ID_NULL
Represents the null base.
Definition f_base_id.hpp:7
sStateID_c null
A null state instance.
s16 atan2s(float sin, float cos)
Converts a sine and a cosine to an angle in units.
Definition c_math.cpp:167
void hideFukidashiForSession(int playerId, int fukidashiAction)
Hides the given action prompt for the given player for the rest of the current session.
T calcTimer(T *value)
Decrements a timer value.
Definition s_lib.hpp:21
s16 addCalcAngle(s16 *value, s16 target, s16 smoothing, s16 maxStep, s16 minStep)
Smoothly moves value towards target using proportional scaling.
Definition s_lib.cpp:76
BOOL chase(s16 *value, s16 target, s16 step)
Moves value towards target by a fixed step amount.
Definition s_lib.cpp:119
#define STATE_VIRTUAL_DEFINE(class, name)
Defines a virtual state.
Definition s_State.hpp:46
float cos() const
Computes the cosine of the angle.
Definition m_angle.hpp:58
float sin() const
Computes the sine of the angle.
Definition m_angle.hpp:55
s16 mAngle
The rotation.
Definition m_angle.hpp:60
A structure that contains information about a collider.
Definition d_cc.hpp:93
u8 mType
See NextGotoType_e.
u16 mFlags
See NextGotoFlags_e.