NSMBW-Decomp
A decompilation of New Super Mario Bros. Wii
Loading...
Searching...
No Matches
d_a_player.cpp
1#include <game/bases/d_a_player.hpp>
2#include <game/bases/d_a_en_door.hpp>
3#include <game/bases/d_a_fireball_player.hpp>
4#include <game/bases/d_a_player_ice.hpp>
5#include <game/bases/d_a_iceball.hpp>
6#include <game/bases/d_a_player_manager.hpp>
7#include <game/bases/d_a_player_demo_manager.hpp>
8#include <game/bases/d_player_effect_manager.hpp>
9#include <game/bases/d_bg.hpp>
10#include <game/bases/d_bg_parameter.hpp>
11#include <game/bases/d_enemy_manager.hpp>
12#include <game/bases/d_game_com.hpp>
13#include <game/bases/d_info.hpp>
14#include <game/bases/d_next.hpp>
15#include <game/bases/d_mask_manager.hpp>
16#include <game/bases/d_mario_mdl.hpp>
17#include <game/bases/d_water_entry_manager.hpp>
18#include <game/bases/d_s_stage.hpp>
19#include <game/bases/d_save_mng.hpp>
20#include <game/bases/d_yoshi_mdl.hpp>
21#include <game/mLib/m_fader.hpp>
22#include <game/sLib/s_GlobalData.hpp>
24
25const float dAcPy_c::msc_JUMP_SPEED = daPlBase_c::sc_JumpSpeed;
26
27inline float getSomeData(int idx) {
28 return dAcPy_c::data_802f5a0c[idx];
29}
30
31inline float getData(int idx) {
32 return dAcPy_c::data_802f5a48[idx];
33}
34
35bool dAcPy_c::setHipAttackOnEnemy(mVec3_c *hitPos) {
36 if (isState(StateID_HipAttack) && isStatus(STATUS_HIP_ATTACK_FALL)) {
38 mPressAttachPos = *hitPos;
39 return true;
40 } else if (isState(StateID_SpinHipAttack) && isStatus(STATUS_SPIN_HIP_ATTACK_FALL)) {
42 mPressAttachPos = *hitPos;
43 return true;
44 }
45 return false;
46}
47
48void dAcPy_c::setHipAttackEffect() {
49 if (isNowBgCross(BGC_WATER_SHALLOW)) {
50 setSeaLandSmokeEffect();
51 startSound(SE_PLY_HPDP_SPLASH, 0);
52 if (mPowerup == POWERUP_MINI_MUSHROOM) {
53 startSound(SE_PLY_HIP_ATTACK_M, 0);
54 } else {
55 startSound(SE_PLY_HIP_ATTACK, 0);
56 }
57 } else {
58 daPlBase_c::setHipAttackEffect();
59 }
60}
61
62bool dAcPy_c::setHipAttackAction() {
63 if (
64 !isStatus(STATUS_A7) &&
65 !isNowBgCross(BGC_FOOT) && !isNowBgCross(BGC_37) &&
66 mKey.checkHipAttack() &&
67 !isDemoType(DEMO_ENDING_DANCE)
68 ) {
69 if (!isStatus(STATUS_PROPEL)) {
70 if (!isCarry()) {
71 changeState(StateID_HipAttack, HIP_ATTACK_ARG_PLAYER);
72 return true;
73 }
74 } else {
75 changeState(StateID_SpinHipAttack, 0);
76 return true;
77 }
78 }
79 return false;
80}
81
82void dAcPy_c::setHipAttack_AttackStart() {
83 daPlBase_c::setHipAttack_AttackStart();
84 startSound(SE_PLY_ROLLING, 0);
85}
86
87void dAcPy_c::initializeState_HipAttack() {
88 daPlBase_c::initializeState_HipAttack();
89 mJumpCounter = 0;
92}
93
94void dAcPy_c::finalizeState_HipAttack() {
95 daPlBase_c::finalizeState_HipAttack();
97}
98
99void dAcPy_c::executeState_HipAttack() {
100 if (isNowBgCross(BGC_WATER_SHALLOW) && isOldBgCross(BGC_WATER_SHALLOW) == 0) {
101 setWaterInEffect();
102 }
103 daPlBase_c::executeState_HipAttack();
104}
105
106void dAcPy_c::setSpinHipAttackEffect() {
107 dEf::createPlayerEffect(mPlayerNo, &mLevelEf1, "Wm_mr_spindown", 0, &mPos, nullptr, nullptr);
108 dEf::createPlayerEffect(mPlayerNo, &mLevelEf2, "Wm_mr_spindownline", 0, &mPos, nullptr, nullptr);
109}
110
111void dAcPy_c::initializeState_SpinHipAttack() {
112 mSubstate = SPIN_HIP_ATTACK_ACTION_0;
113 mPyMdlMng.setAnm(PLAYER_ANIM_SPIN_JUMP2);
115 onStatus(STATUS_A8);
119 int changeParam = (int) mStateArg;
120 mSpeedF = 0.0f;
121 mMaxSpeedF = 0.0f;
122 mAccelY = 0.0f;
123 if (changeParam == 0) {
124 mSubstateValue = 0;
125 mSpeed.y = 0.0f;
126 float v = data_802f5a0c[13];
127 mMaxFallSpeed = v;
128 } else {
129 mSubstateValue = 1;
130 mSpeed.y = -6.0f;
131 mMaxFallSpeed = -6.0f;
132 }
133 m_2e8 = 0x1000;
134 mSubstateTimer = 10;
135 setScrollMode(2);
136}
137
138void dAcPy_c::executeState_SpinHipAttack() {
139 offStatus(STATUS_SPIN_HIP_ATTACK_LANDING);
141 setCcAtSpinFall();
142 }
143 if (isNowBgCross(BGC_WATER_SHALLOW) && isOldBgCross(BGC_WATER_SHALLOW) == 0) {
144 setWaterInEffect();
145 }
146 if (mPowerup != POWERUP_PROPELLER_SHROOM && getCarryPropelActor() == nullptr) {
147 changeState(StateID_Fall, false);
148 return;
149 }
151 case SPIN_HIP_ATTACK_ACTION_0:
152 holdSound(SE_PLY_PRPL_LETDOWN_FAST, 0);
153 if (isNowBgCross(BGC_WATER_SHALLOW)) {
154 mMaxFallSpeed = sc_WaterMaxFallSpeed;
155 } else {
156 sLib::chase(&mMaxFallSpeed, data_802f5a0c[13], 0.1f);
157 }
158 mAccelY = getGravityData()[0];
159 onStatus(STATUS_AA);
160 if (isNowBgCross(BGC_WATER_SUBMERGED)) {
161 offStatus(STATUS_AA);
162 }
163 if (isNowBgCross(BGC_62)) {
164 mSpeed.y = 0.0f;
165 m_2e8 = 0x1000;
166 offNowBgCross(BGC_FOOT);
167 }
168 if (isNowBgCross(BGC_FOOT) && !isOldBgCross(BGC_62)) {
169 startQuakeShock(dQuake_c::TYPE_7);
170 startSound(SE_PLY_PRPL_LETDOWN_FAST_LAND, 0);
171 if (isNowBgCross(BGC_CLIFF)) {
173 return;
174 }
175 s16 curr = m_2e8;
176 if (checkCrouch()) {
177 m_2e8 = curr;
178 return;
179 }
180 mSubstate = SPIN_HIP_ATTACK_ACTION_1;
181 mAngle.y = getMukiAngle(mDirection);
182 mPyMdlMng.setAnm(PLAYER_ANIM_SPIN_JUMP_END);
183 mSubstateTimer = 20;
187 onStatus(STATUS_SPIN_HIP_ATTACK_LANDED);
188 onStatus(STATUS_SPIN_HIP_ATTACK_LANDING);
189 return;
190 }
191 if (!mKey.buttonDown() && mSubstateTimer == 0) {
192 if (mSubstateValue == 0) {
193 mMaxFallSpeed = data_802f5a0c[5];
194 }
195 changeState(StateID_Propel, (void *) 1);
196 return;
197 }
198 if (isNowBgCross(BGC_WATER_TOUCH)) {
199 m_2e8.chase(0, 0x1000);
200 } else {
201 m_2e8.chase(0x2000, 0x400);
202 }
203 mAngle.y += m_2e8;
204 setSpinHipAttackEffect();
205 setPropelSpinSmokeEffect();
206 break;
207 case SPIN_HIP_ATTACK_ACTION_1:
208 m_2e8.chase(0, 0x200);
209 mAngle.y += m_2e8;
210 if (checkJumpTrigger()) {
211 return;
212 }
213 if (mSubstateTimer == 0 || mPyMdlMng.isAnmStop() || mSpeedF) {
214 changeState(StateID_Walk, BLEND_DEFAULT);
215 return;
216 }
217 break;
218 }
221 mPos.x = mPressAttachPos.x;
222 mPos.y = mPressAttachPos.y;
223 }
224}
225
226void dAcPy_c::finalizeState_SpinHipAttack() {
227 m_2e8 = 0;
230 offStatus(STATUS_SPIN_HIP_ATTACK_LANDED);
231 offStatus(STATUS_SPIN_HIP_ATTACK_LANDING);
232 offStatus(STATUS_A8);
233 offStatus(STATUS_AA);
237 mKey.offStatus(dAcPyKey_c::STATUS_FORCE_NO_JUMP);
238 setScrollMode(0);
239}
240
241void dAcPy_c::initializeState_Fall() {
242 daPlBase_c::initializeState_Fall();
243 onStatus(STATUS_9B);
244 onStatus(STATUS_9C);
245 onStatus(STATUS_9D);
246 onStatus(STATUS_9E);
248 onStatus(STATUS_92);
250 onStatus(STATUS_A1);
251 if (!isNowBgCross(BGC_WATER_TOUCH)) {
252 setWaterWalkFlag();
253 }
254 mSpeedMax.x = 0.0;
255 mJumpCounter = 0;
256 mSubstate = FALL_ACTION_1;
257 setAddLiftSpeedF();
259 mSpeed.y = 0.5f;
260 }
261 setJumpGravity();
262 maxFallSpeedSet();
263 moveSpeedSet();
264 powerSet();
265}
266
267void dAcPy_c::finalizeState_Fall() {
268 daPlBase_c::finalizeState_Fall();
269 mAngle.x = 0;
270 offStatus(STATUS_9B);
271 offStatus(STATUS_9C);
272 offStatus(STATUS_9D);
273 offStatus(STATUS_9E);
275 offStatus(STATUS_92);
278 offStatus(STATUS_A1);
279}
280
281void dAcPy_c::executeState_Fall() {
282 daPlBase_c::executeState_Fall();
283 setJumpGravity();
284 maxFallSpeedSet();
285 moveSpeedSet();
286 powerSet();
287 if (!setKaniActionInitHangHand()) {
288 jump_common();
289 if (setDelayHelpJump()) {
290 return;
291 }
292 }
293}
294
295void dAcPy_c::initializeState_Jump() {
296 daPlBase_c::initializeState_Jump();
297 onStatus(STATUS_9B);
298 onStatus(STATUS_9C);
299 onStatus(STATUS_9D);
300 if (mStartSpinCooldown == 0) {
302 }
303 onStatus(STATUS_92);
305 onStatus(STATUS_A1);
306 m_12f4 = mDirection;
307 mSpeedMax.x = 0.0f;
308 setStartJumpEffect(0);
309 _jumpSet(stateArg<jmpInf_c *>());
310 if (mJumpCounter != 2) {
311 onStatus(STATUS_9E);
312 }
313}
314
315void dAcPy_c::finalizeState_Jump() {
316 daPlBase_c::finalizeState_Jump();
318 mJumpComboTimer = 8;
321 calcJumpCount();
322 }
324 offStatus(STATUS_96);
325 offStatus(STATUS_48);
326 offStatus(STATUS_BF);
327 offStatus(STATUS_A8);
328 offStatus(STATUS_9B);
329 offStatus(STATUS_9C);
330 offStatus(STATUS_9D);
331 offStatus(STATUS_9E);
333 offStatus(STATUS_92);
335 offStatus(STATUS_A1);
336}
337
338void dAcPy_c::executeState_Jump() {
339 daPlBase_c::executeState_Jump();
340 if (mStartSpinCooldown != 0) {
341 if (--mStartSpinCooldown == 0) {
343 }
344 }
345 if (isStatus(STATUS_A8) && mSpeed.y < 2.0f) {
346 offStatus(STATUS_A8);
347 }
348 gravitySet();
349 maxFallSpeedSet();
350 moveSpeedSet();
351 airPowerSet();
352 if (!setKaniActionInitHangHand()) {
353 jump_common();
354 }
355}
356
357void dAcPy_c::calcJumpCount() {
358 if (!isStatus(STATUS_AB)) {
359 mJumpCounter++;
360 if (mJumpCounter > 2) {
361 mJumpCounter = 0;
362 }
363 }
364}
365
366float dAcPy_c::getJumpSpeed() {
367 float baseSpeed;
368 float absSpeed = std::fabs(mSpeedF);
369 if (absSpeed < daPlayerData_c::smc_POWER_CHANGE_DATA.mJumpSpeedValues1[0]) {
370 baseSpeed = daPlayerData_c::smc_POWER_CHANGE_DATA.mJumpSpeedValues2[0];
371 } else if (absSpeed < daPlayerData_c::smc_POWER_CHANGE_DATA.mJumpSpeedValues1[1]) {
372 baseSpeed = daPlayerData_c::smc_POWER_CHANGE_DATA.mJumpSpeedValues2[1];
373 } else if (absSpeed < daPlayerData_c::smc_POWER_CHANGE_DATA.mJumpSpeedValues1[2]) {
374 baseSpeed = daPlayerData_c::smc_POWER_CHANGE_DATA.mJumpSpeedValues2[2];
375 } else {
376 baseSpeed = daPlayerData_c::smc_POWER_CHANGE_DATA.mJumpSpeedValues2[3];
377 }
378 if (std::fabs(mSpeedF) >= getSpeedData()->mHighSpeed) {
379 baseSpeed = daPlayerData_c::smc_POWER_CHANGE_DATA.mJumpSpeedValues2[3];
380 }
381 float jumpSpeed;
382 if (isNowBgCross(BgCross1_e(BGC_IN_SINK_SAND | BGC_ON_SINK_SAND))) {
383 if (isNowBgCross(BGC_IN_SINK_SAND)) {
384 jumpSpeed = sc_JumpSpeedNuma2;
385 } else {
386 jumpSpeed = sc_JumpSpeedNuma1;
387 if (mPos.y < mSinkSandHeight - 4.0f) {
388 jumpSpeed += -0.15f;
389 }
390 }
391 } else {
392 jumpSpeed = sc_JumpSpeed + baseSpeed;
393 }
394 if (isMameAction()) {
395 jumpSpeed *= 0.8125f;
396 }
397 return jumpSpeed;
398}
399
400void dAcPy_c::setJumpSpeed() {
401 float jumpSpeed = getJumpSpeed();
402 if (mJumpCounter == 2) {
403 jumpSpeed *= 1.05f;
404 }
405 mSpeed.y = jumpSpeed;
406}
407
408void dAcPy_c::fn_80127740(int jumpType, AnmBlend_e blendMode) {
409 mSubstate = JUMP_TAKE_OFF;
410 fn_80145fd0(jumpType);
412 mPyMdlMng.setAnm(PLAYER_ANIM_GET_DOWN, 0.0f, 0.0f);
413 } else if (isStatus(STATUS_SPIN)) {
414 mPyMdlMng.setAnm(PLAYER_ANIM_SPIN_ST);
415 } else if (isStatus(STATUS_KANI_JUMP)) {
416 mPyMdlMng.setAnm(PLAYER_ANIM_W_JUMP1, 0.0f, 0.0f);
417 } else if (isStatus(STATUS_STAR_JUMP) && !isCarry()) {
418 mPyMdlMng.setAnm(PLAYER_ANIM_STAR_ROLL_DUPLICATE);
419 } else if (isStatus(STATUS_SIT_JUMP)) {
420 mPyMdlMng.setAnm(PLAYER_ANIM_S_JUMP);
421 } else {
422 int anmNum;
423 switch (mJumpCounter) {
424 case 0:
425 anmNum = PLAYER_ANIM_JUMP;
426 break;
427 case 1:
428 startPlayerVoice(VOICE_JUMP_2ND, 0);
429 anmNum = PLAYER_ANIM_2JMP_C_1;
430 break;
431 default:
432 startPlayerVoice(VOICE_JUMP_3RD, 0);
433 anmNum = PLAYER_ANIM_ROLL_JUMP;
434 break;
435 }
436 if (!isCarry()) {
437 if (mJumpCounter == 1) {
438 mPyMdlMng.mpMdl->fn_800d5e00(1);
439 } else {
440 mPyMdlMng.mpMdl->fn_800d5e00(0);
441 }
442 }
443 if (blendMode == BLEND_NONE) {
444 mPyMdlMng.setAnm(anmNum, 0.0f, 0.0f);
445 } else {
446 mPyMdlMng.setAnm(anmNum);
447 }
448 }
449}
450
451bool dAcPy_c::jump_common() {
452 if (checkCarryThrow()) {
453 return true;
454 }
455 if (setHipAttackAction()) {
456 return true;
457 }
458 if (isNowBgCross(BGC_WALL_TOUCH_L_2) | isNowBgCross(BGC_WALL_TOUCH_R_2)) {
459 mKey.offStatus(dAcPyKey_c::STATUS_DISABLE_LR);
460 }
461 if (mSpeed.y <= 0.0f) {
462 mKey.offStatus(dAcPyKey_c::STATUS_FORCE_JUMP);
463 }
464 typedef void (dAcPy_c::*JumpActionProc)();
465 static JumpActionProc l_JumpActionProc[] = {
467 &dAcPy_c::jumpExecAir
468 };
469 (this->*l_JumpActionProc[mSubstate])();
470 return false;
471}
472
475 mSubstate = JUMP_AIR;
477 if (mPyMdlMng.isAnmStop()) {
478 mPyMdlMng.setAnm(PLAYER_ANIM_JUMP2, 3.0f, 0.0f);
479 mSubstate = JUMP_AIR;
480 }
481 } else if (mSpeed.y < 0.0f) {
483 mPyMdlMng.setAnm(PLAYER_ANIM_W_JUMP2, 10.0f, 0.0f);
484 } else if (isStatus(STATUS_SIT_JUMP)) {
485 mPyMdlMng.setAnm(PLAYER_ANIM_S_JUMP2);
486 } else if (mJumpCounter != 2) {
487 /// @unofficial
488 static const int l_AnmIDs[] = { PLAYER_ANIM_JUMP2, PLAYER_ANIM_2JMP_C_2, PLAYER_ANIM_2JUMP2 };
489 mPyMdlMng.setAnm(l_AnmIDs[mJumpCounter]);
490 }
491 mSubstate = JUMP_AIR;
492 }
493 jumpExecAir();
494}
495
496void dAcPy_c::jumpExecAir() {
497 if (isStatus(STATUS_STAR_JUMP) && !isStar()) {
499 mPyMdlMng.setAnm(PLAYER_ANIM_JUMP2, 10.0f, 0.0f);
500 }
501 if (mJumpCounter == 2) {
502 if (mSubstate == JUMP_AIR) {
503 turnAngle();
504 if (mDirection != m_12f4 || isNowBgCross(BGC_HEAD)) {
505 float f = mPyMdlMng.getLastFrame();
506 mPyMdlMng.setAnm(PLAYER_ANIM_ROLL_JUMP, 0.0f, f);
507 }
508 }
509 } else if (!isStatus(STATUS_KANI_JUMP)) {
510 turnAngle();
511 }
512 setJumpGravity();
513 maxFallSpeedSet();
514 if (isStatus(STATUS_TWIRL) && mSpeed.y < 0.0f) {
515 mAccelY = 0.0f;
516 float f = std::fabs(mSpeed.y * 0.15f);
517 if (f < 0.1f) {
518 f = 0.1f;
519 }
520 if (f > 1.0f) {
521 f = 1.0f;
522 }
523 sLib::chase(&mSpeed.y, 0.0f, f);
524 }
525 if (
526 isNowBgCross(BGC_FOOT) &&
527 !checkSlip() &&
528 !checkJumpTrigger() &&
529 !checkCrouch()
530 ) {
531 mAngle.x = 0;
533 changeState(StateID_Crouch, CROUCH_ARG_FROM_SIT_JUMP);
534 return;
535 }
536 if (
537 mPowerup != POWERUP_MINI_MUSHROOM &&
538 !isCarry() &&
540 isNowBgCross(BGC_GROUNDED_MOVE_UP)
541 ) {
542 changeState(StateID_Land, true);
543 return;
544 }
545 if ((isStatus(STATUS_YOSHI_DISMOUNT_JUMP) || mJumpCounter == 2) && !mKey.buttonWalk(nullptr)) {
546 mSpeedF = 0.0f;
547 }
548 setLandJumpEffect(0);
549 if (mSpeedF) {
551 return;
552 }
554 mPyMdlMng.setAnm(PLAYER_ANIM_2JUMPED_DUPLICATE, 10.0f, 0.0f);
555 } else {
556 if (mJumpCounter == 0) {
557 mPyMdlMng.setAnm(PLAYER_ANIM_JUMPED);
558 } else {
559 mPyMdlMng.setAnm(PLAYER_ANIM_2JUMPED);
560 }
561 }
562 changeState(StateID_Land, false);
563 }
564}
565
568 int v = getFollowMameKuribo() - 1;
569 if (v < 0) {
570 v = 0;
571 }
572 if (v > 4) {
573 v = 4;
574 }
575 /// @unofficial
576 static const float speedMultiplier[] = { 0.84f, 0.81f, 0.78f, 0.75f, 0.72f };
577 mSpeed.y *= speedMultiplier[v];
578 }
579 offNowBgCross(BGC_FOOT);
580 setAddLiftSpeedF();
581 setJumpGravity();
582 maxFallSpeedSet();
583}
584
585void dAcPy_c::_jumpSet(jmpInf_c *jumpInf) {
586 setWaterWalkFlag();
587 mAngle.x = 0;
588 offStatus(STATUS_88);
589 if (isStar()) {
591 } else {
593 }
594 if (isOnSinkSand()) {
596 }
597 int jumpMode = 1;
598 if (jumpInf != nullptr) {
599 jumpMode = jumpInf->mJumpMode;
600 }
601 if (isStatus(STATUS_C0)) {
602 jumpMode = 0;
603 }
604 if (
605 isOnSinkSand() ||
606 mJumpComboTimer == 0 ||
607 isCarry() ||
608 std::fabs(mSpeedF) < 3.0f ||
609 jumpMode == 0
610 ) {
611 mJumpCounter = 0;
612 }
613 if (getCarryPlayer() != nullptr && isStatus(STATUS_47)) {
614 onStatus(STATUS_48);
615 }
616 if (jumpInf != nullptr) {
617 if (jumpInf->mSpeed) {
618 mSpeed.y = jumpInf->mSpeed;
619 } else {
620 setJumpSpeed();
621 }
622 } else {
623 setJumpSpeed();
624 }
625 AnmBlend_e blendMode = BLEND_DEFAULT;
626 if (jumpInf != nullptr) {
627 blendMode = jumpInf->mBlendMode;
628 }
629
630 fn_80127740(jumpMode, blendMode);
631 mAngle.y = getMukiAngle(mDirection);
633}
634
636 if (mKey.buttonWalk(nullptr) && mSpeedF * mMaxSpeedF < 0.0f && checkTurn()) {
637 return;
638 }
639 changeState(StateID_Walk, blendMode);
640}
641
642void dAcPy_c::initializeState_Land() {
643 if (mSubstate == LAND_ACTION_1) {
644 mSpeedF = 0.0f;
645 mPyMdlMng.setAnm(PLAYER_ANIM_2JUMPED, 2.0f, 0.0f, 0.0f);
646 }
647 onStatus(STATUS_9B);
648 onStatus(STATUS_9D);
649 onStatus(STATUS_9E);
651 onStatus(STATUS_92);
652 onStatus(STATUS_A0);
653 onStatus(STATUS_A2);
654 onStatus(STATUS_A3);
655}
656
657void dAcPy_c::finalizeState_Land() {
658 offStatus(STATUS_9B);
659 offStatus(STATUS_9D);
660 offStatus(STATUS_9E);
662 offStatus(STATUS_92);
663 offStatus(STATUS_A0);
664 offStatus(STATUS_A2);
665 offStatus(STATUS_A3);
666}
667
668void dAcPy_c::executeState_Land() {
669 gravitySet();
670 maxFallSpeedSet();
671 moveSpeedSet();
672 airPowerSet();
673 if (checkWalkNextAction()) {
674 return;
675 }
676 if (isNowBgCross(BgCross1_e(BGC_WALL_TOUCH_L_2 | BGC_WALL_TOUCH_R_2))) {
677 mKey.offStatus(dAcPyKey_c::STATUS_DISABLE_LR);
678 }
679 if (isIceSlipAnmPlay()) {
680 changeState(StateID_Walk, BLEND_DEFAULT);
681 return;
682 }
683 if (mSubstate == LAND_ACTION_0) {
684 if (!mSpeedF && !mPyMdlMng.isAnmStop()) {
685 return;
686 }
688 } else {
689 mSpeedF = 0.0f;
690 if ((mKey.buttonWalk(nullptr) && mPyMdlMng.mpMdl->mAnm.getFrame() >= 10.0f) || mPyMdlMng.isAnmStop()) {
692 }
693 }
694}
695
697 if (
698 !isNowBgCross(BGC_WATER_SHALLOW) &&
699 mWallSlideCooldown == 0 &&
701 !isStatus(STATUS_A8) &&
702 !isNowBgCross(BGC_37) &&
703 !isNowBgCross(BGC_FOOT) &&
704 !mIsBgDamage &&
705 mBc.getWallAttr(dir) != 7 &&
706 !isNowBgCross(BGC_HEAD) &&
707 !isCarry()
708 ) {
709 /// @unofficial
710 static const BgCross1_e flags[] = {
711 BGC_WALL_TOUCH_R,
712 BGC_WALL_TOUCH_L
713 };
714 if (isNowBgCross(flags[mDirection]) && dir == mDirection) {
715 return 0;
716 } else {
717 return 1;
718 }
719 }
720 return 2;
721}
722
723bool dAcPy_c::checkWallJump() {
725 return false;
726 }
727 int dir;
728 if (
729 mKey.buttonWalk(&dir) &&
730 !isNowBgCross(BGC_37) &&
732 ) {
733 if (!isStatus(STATUS_A9) && mSpeed.y < 0.0f) {
734 changeState(StateID_WallSlide, 0);
735 return true;
736 }
737 if (mKey.triggerJump()) {
738 changeState(StateID_WallJump, 0);
739 return true;
740 }
741 }
742 return false;
743}
744
745void dAcPy_c::initializeState_WallSlide() {
746 mPyMdlMng.setAnm(PLAYER_ANIM_WSLD, 0.0f, 0.0f);
747 onStatus(STATUS_97);
751 mBc.mPlayerFlags |= 2;
752 mAccelY = getGravityData()[0];
753 mAngle.y = getMukiAngle(mDirection);
754 mMaxSpeedF = 0.0f;
755 mSpeedF = 0.0f;
756 mAccelF = 0.0f;
757}
758
759void dAcPy_c::finalizeState_WallSlide() {
763 mBc.mPlayerFlags &= ~2;
764 mAccelY = getGravityData()[0];
766}
767
769 holdSound(SE_PLY_SLIP_TATE, 0);
770 if (getTallType(-1) > 2) {
771 return;
772 }
773 u8 idx = (mDirection ^ 1) + getTallType(-1) * 2;
774 if (idx >= 6) {
775 return;
776 }
777 mVec3_c jnt;
778 mPyMdlMng.mpMdl->getJointPos(&jnt, 14);
779 if (mDirection == 0) {
780 jnt.x = mPos.x + mWallBcData.mOffset / 4096.0f;
781 } else {
782 jnt.x = mPos.x - mWallBcData.mOffset / 4096.0f;
783 }
784 /// @unofficial
785 static const char *sc_wallSlidEffectID[] = {
786 "Wm_mr_wallslip_ss_r",
787 "Wm_mr_wallslip_ss_l",
788 "Wm_mr_wallslip_s_r",
789 "Wm_mr_wallslip_s_l",
790 "Wm_mr_wallslip_r",
791 "Wm_mr_wallslip_l"
792 };
793 dEf::createPlayerEffect(mPlayerNo, &mSmokeEffect, sc_wallSlidEffectID[idx], 0, &jnt, nullptr, nullptr);
794}
795
796void dAcPy_c::executeState_WallSlide() {
797 if (isNowBgCross(BGC_FOOT)) {
799 return;
800 }
801 if (mKey.triggerJump()) {
802 changeState(StateID_WallJump, 0);
803 return;
804 }
805 if (setHipAttackAction()) {
806 return;
807 }
808 int dir;
809 if (mKey.buttonWalk(&dir) && dir != mDirection) {
810 mSubstateValue += 1;
811 if (mSubstateValue >= 15) {
812 changeState(StateID_Fall, false);
813 }
814 } else {
815 mSubstateValue = 0;
816 }
818 changeState(StateID_Fall, false);
819 return;
820 }
821 if (isMameAction()) {
822 mMaxFallSpeed = -0.75f;
823 } else {
824 mMaxFallSpeed = -2.0f;
825 }
827 mSpeedF = sc_DirSpeed[mDirection];
828}
829
830void dAcPy_c::initializeState_WallJump() {
831 onStatus(STATUS_97);
832 offStatus(STATUS_A7);
833 setWaterWalkFlag();
834 mAccelY = 0.0f;
835 mSpeed.y = 0.0f;
836 mDirection ^= 1;
837 mAngle.y = getMukiAngle(mDirection);
838 mMaxSpeedF = 0.0f;
839 mSpeedF = 0.0f;
840 if (getTallType(-1) <= 2) {
841 u8 dir = mDirection;
842 u8 idx = dir + getTallType(-1) * 2;
843 if (idx < 6) {
844 float thing = mWallBcData.mOffset / 4096.0f;
845 mVec3_c pos(mPos.x - thing * sc_DirSpeed[dir], mPos.y, mPos.z);
846 mVec3_c pos2(pos.x - sc_DirSpeed[mDirection] * 8.0f, pos.y, pos.z);
847 if (!dBc_c::checkWall(&mPos, &pos2, nullptr, mLayer, mAmiLayer, nullptr)) {
848 pos.y += 8.0f;
849 float f;
850 if (dBc_c::checkTenjou(&pos2, &f, mLayer, mAmiLayer) && f < mPos.y + getModelHeight()) {
851 pos.y = f + 8.0f;
852 }
853 }
854 /// @unofficial
855 static const char *sc_wallKickEffectID[] = {
856 "Wm_mr_wallkick_ss_r",
857 "Wm_mr_wallkick_ss_l",
858 "Wm_mr_wallkick_s_r",
859 "Wm_mr_wallkick_s_l",
860 "Wm_mr_wallkick_r",
861 "Wm_mr_wallkick_l"
862 };
863 dEf::createPlayerEffect(mPlayerNo, sc_wallKickEffectID[idx], 0, &pos, nullptr, nullptr);
864 }
865 }
866 mKey.offStatus(dAcPyKey_c::STATUS_FORCE_JUMP);
867 m_15b0 = 35;
868}
869
870void dAcPy_c::finalizeState_WallJump() {
871 mAccelY = getGravityData()[0];
872}
873
874void dAcPy_c::executeState_WallJump() {
875 mSpeedF = sc_DirSpeed[mDirection] * 2.25f;
877 onStatus(STATUS_96);
878 float f = 3.5f;
879 if (isMameAction()) {
880 f *= 0.8125f;
881 }
882 jmpInf_c jumpInf(f, 0, BLEND_DEFAULT);
883 changeState(StateID_Jump, &jumpInf);
884 startPlayerVoice(VOICE_WALL_KICK, 0);
885 startSound(SE_PLY_KABE_KICK, false);
887}
888
889void dAcPy_c::setSpinHoldReq(float targetX) {
891 mSpinHoldReqTarget = targetX;
892}
893
894bool dAcPy_c::setSpinSpeed(float speedF, float speedY) {
895 if (isState(StateID_SpinJump)) {
896 if (isStatus(STATUS_IS_SPIN_HOLD_REQ) || m_15ae != 0) {
897 return false;
898 }
899 mSpeed.y = speedY;
900 mSpeedF = speedF;
901 mKey.onStatus(dAcPyKey_c::STATUS_NO_INPUT);
902 m_15ae = 30;
903 mSpinTimer = 30;
904 m_1048 = 0x2000;
905 offNowBgCross(BGC_FOOT);
906 dQuake_c::getInstance()->shockMotor(getPlrNo(), dQuake_c::TYPE_7, 0, false);
907 return true;
908 }
909 return false;
910}
911
912void dAcPy_c::setSpinJumpEffect(int i) {
913 if (!isStatus(STATUS_SPIN)) {
914 endSpinJumpEffect();
915 } else if (fManager_c::searchBaseByID(mCarryActorID) != nullptr) {
916 dAcPy_c *carryPlayer = getCarryPlayer();
917 if (carryPlayer != nullptr) {
918 carryPlayer->setSpinJumpEffectSub(i);
919 }
920 } else {
921 setSpinJumpEffectSub(i);
922 }
923}
924
925void dAcPy_c::setSpinJumpEffectSub(int i) {
926 if (dScStage_c::m_isStaffCredit) {
927 return;
928 }
929 mVec3_c jnt1, jnt2;
930 mPyMdlMng.mpMdl->getJointPos(&jnt1, 11);
931 mPyMdlMng.mpMdl->getJointPos(&jnt2, 14);
932 mVec3_c pos(mPos.x, 4.0f + (jnt1.y + jnt2.y) / 2, mPos.z);
933 float s;
934 static const float scSpinJumpEffectScale[3] = { 0.6f, 0.8f, 1.0f };
935 static const float scSpinJumpEffectScale_K[3] = { 0.6f, 0.7f, 0.8f };
936 if (PLAYER_YELLOW_TOAD <= mPlayerType && mPlayerType <= PLAYER_BLUE_TOAD) {
937 s = scSpinJumpEffectScale_K[getTallType(-1)];
938 } else {
939 s = scSpinJumpEffectScale[getTallType(-1)];
940 }
941 mVec3_c scale(s, s, s);
942 if (i == 1) {
943 if (m_1288 == 0) {
944 static const char *sc_spinEffectID[] = {
945 "Wm_mr_normalspin",
946 "Wm_mr_normalspin_pm"
947 };
948 int idx = 0;
949 if (mPowerup == POWERUP_PENGUIN_SUIT) {
950 idx = 1;
951 }
952 dEf::createPlayerEffect(mPlayerNo, &mFollowEf2, sc_spinEffectID[idx], 0, &pos, nullptr, &scale);
953 m_1288 = 1;
954 }
955 } else if (m_1288 != 0) {
956 if (!mFollowEf2.follow(&pos, nullptr, &scale)) {
957 m_1288 = 0;
958 }
959 }
960}
961
962void dAcPy_c::endSpinJumpEffect() {
963 if (m_1288 != 0) {
964 m_1288 = 0;
965 mFollowEf2.kill();
966 }
967}
968
969void dAcPy_c::setMissSpinJumpEffect(int i) {
970 dAcPy_c *carryPlayer = getCarryPlayer();
971 if (carryPlayer != nullptr) {
972 carryPlayer->setMissSpinJumpEffect(i);
973 return;
974 }
975 if (i == 0 && !m_128c) {
976 return;
977 }
978 mVec3_c jnt;
979 mPyMdlMng.mpMdl->getJointPos(&jnt, 1);
980 float s = mPyMdlMng.getSomeScale2();
981 mVec3_c scale(s, s, s);
982 if (i == 1) {
983 dEf::createPlayerEffect(mPlayerNo, &mFollowEf3, "Wm_mr_halfspin", 0, &jnt, nullptr, &scale);
984 m_128c = 1;
985 } else if (m_128c != 0) {
986 if (!mFollowEf3.follow(&jnt, nullptr, &scale)) {
987 m_128c = 0;
988 }
989 }
990}
991
992void dAcPy_c::initializeState_SpinJump() {
993 m_12f4 = mDirection;
994 onStatus(STATUS_9B);
995 onStatus(STATUS_9C);
996 onStatus(STATUS_9D);
997 onStatus(STATUS_92);
998 onStatus(STATUS_A9);
1000 onStatus(STATUS_A1);
1003 mSpinTimer = 30;
1004 m_1048 = 0x2000;
1005 setSpinJumpEffect(1);
1006 u32 substate = (u32) mStateArg;
1007 if (substate <= SPIN_JUMP_ACTION_1) {
1008 startSound(SE_PLY_SPIN_ATTACK, true);
1009 }
1011 mPyMdlMng.setAnm(PLAYER_ANIM_SPIN_ST, 0.0f, 0.0f);
1012 } else {
1013 mKey.onStatus(dAcPyKey_c::STATUS_FORCE_JUMP);
1014 jmpInf_c jumpInf(mSpeed.y, 0, BLEND_DEFAULT);
1015 if (substate == SPIN_JUMP_ACTION_0) {
1016 jumpInf.mSpeed = sc_JumpSpeed - 0.4f;
1017 }
1018 if (
1019 isNowBgCross(BgCross1_e(BGC_IN_SINK_SAND | BGC_ON_SINK_SAND)) &&
1020 (isNowBgCross(BGC_IN_SINK_SAND) || mPos.y < mSinkSandHeight - 4.0f)
1021 ) {
1022 jumpInf.mSpeed = sc_JumpSpeed - 0.7f;
1023 }
1024 _jumpSet(&jumpInf);
1025 }
1026 setStartJumpEffect(1);
1027 dAcPy_c *carryPlayer = getCarryPlayer();
1028 if (carryPlayer != nullptr) {
1029 carryPlayer->initRideSpinMove();
1030 }
1031}
1032
1033void dAcPy_c::executeState_SpinJump() {
1034 mAngle.y += m_1048;
1035 setCcAtSpin();
1036 if (mSpinFireBallCooldown != 0) {
1038 }
1039 if (mSpinTimer != 0) {
1040 mSpinTimer--;
1041 if (mSpinFireBallCooldown == 0) {
1042 if (mSpinTimer == 21) {
1043 setSpinFireBall();
1044 } else if (mSpinTimer == 15) {
1045 m_12f4 ^= 1;
1046 setSpinFireBall();
1048 }
1049 }
1050 }
1052 mKey.onStatus(dAcPyKey_c::STATUS_5);
1053 if (mKey.triggerShakeJump() && mSpinTimer < 10) {
1054 mSpinTimer = 30;
1055 m_1048 = 0x2000;
1056 }
1057 mSpeed.y = 0.0f;
1058 mSpeedF = 0.0f;
1059 mAccelY = 0.0f;
1060 mAccelF = 0.0f;
1062 if (!checkJumpTrigger()) {
1063 if (
1064 mKey.buttonWalk(nullptr) &&
1065 (mKey.triggerRight() || mKey.triggerLeft())
1066 ) {
1067 changeState(StateID_Walk, BLEND_DEFAULT);
1068 } else {
1069 if (mSpinTimer == 0) {
1070 mPyMdlMng.setAnm(PLAYER_ANIM_SPIN_END);
1071 changeState(StateID_Land, false);
1072 }
1073 }
1074 }
1075 } else {
1076 setJumpGravity();
1077 maxFallSpeedSet();
1078 moveSpeedSet();
1079 airPowerSet();
1081 if (isNowBgCross(BGC_HEAD)) {
1082 mSpinTimer = 0;
1083 }
1084 if (isNowBgCross(BGC_FOOT)) {
1085 setLandJumpEffect(1);
1086 mPyMdlMng.setAnm(PLAYER_ANIM_SPIN_END, 0.0f, 0.0f);
1087 changeState(StateID_Land, false);
1088 }
1089 }
1090}
1091
1092void dAcPy_c::finalizeState_SpinJump() {
1093 mSpinTimer = 0;
1095 offStatus(STATUS_9B);
1096 offStatus(STATUS_9C);
1097 offStatus(STATUS_9D);
1100 offStatus(STATUS_92);
1101 offStatus(STATUS_A9);
1104 offStatus(STATUS_A1);
1105 mKey.offStatus(dAcPyKey_c::STATUS_FORCE_JUMP);
1106 mKey.offStatus(dAcPyKey_c::STATUS_FORCE_NO_JUMP);
1107 mKey.offStatus(dAcPyKey_c::STATUS_DISABLE_LR);
1108 mKey.offStatus(dAcPyKey_c::STATUS_NO_INPUT);
1109 mKey.offStatus(dAcPyKey_c::STATUS_5);
1110 mAngle.y = getMukiAngle(mDirection);
1111 dAcPy_c *carryPlayer = getCarryPlayer();
1112 if (carryPlayer != nullptr) {
1113 carryPlayer->endRideSpinMove();
1114 }
1115}
1116
1117bool dAcPy_c::isMissSpinEnableAnm() {
1118 if (mPyMdlMng.getAnm() == PLAYER_ANIM_STAR_ROLL_DUPLICATE) {
1119 return false;
1120 }
1121 if (mPyMdlMng.getAnm() == PLAYER_ANIM_ROLL_JUMP && !mPyMdlMng.isAnmStop()) {
1122 return false;
1123 }
1124 return true;
1125}
1126
1127s16 dAcPy_c::getMissSpinAngle() {
1128 if (isMissSpinEnableAnm()) {
1129 return m_105c;
1130 }
1131 return 0;
1132}
1133
1134void dAcPy_c::setMissSpin() {
1135 m_105c = 0x1400;
1136 startSound(SE_PLY_SPIN_ONCE, true);
1137 if (isMissSpinEnableAnm()) {
1138 setMissSpinJumpEffect(1);
1139 }
1140}
1141
1142void dAcPy_c::resetMissSpin() {
1143 m_105c = 0;
1144}
1145
1146void dAcPy_c::updateMissSpin() {
1147 if (m_105c == 0) {
1148 return;
1149 }
1150 s16 prevAngle = m_105c;
1151 m_105c += 0x1400;
1152 if (prevAngle < 0 && m_105c >= 0) {
1153 m_105c = 0;
1154 return;
1155 }
1157}
1158
1159void dAcPy_c::initializeState_RideOffJump() {
1160 onStatus(STATUS_9B);
1161 onStatus(STATUS_9C);
1162 onStatus(STATUS_9D);
1163 onStatus(STATUS_9E);
1165 onStatus(STATUS_97);
1167 onStatus(STATUS_A1);
1168 m_12f4 = mDirection;
1169 mSpeedMax.x = 0.0f;
1170 mSubstateTimer = 30;
1171 mKey.onStatus(dAcPyKey_c::STATUS_FORCE_NO_JUMP);
1172 mAngle.y = getMukiAngle(mDirection);
1173 mSpeedF = sc_DirSpeed[mDirection] * -1.0f;
1174 jmpInf_c jumpInf(2.85f, 0, BLEND_DEFAULT);
1175 _jumpSet(&jumpInf);
1176 startSound(SE_PLY_BREAK_FREE_YOSHI, false);
1177}
1178
1179void dAcPy_c::finalizeState_RideOffJump() {
1180 mAngle.x = 0;
1181 mAngle.y = getMukiAngle(mDirection);
1183 offStatus(STATUS_48);
1184 offStatus(STATUS_9B);
1185 offStatus(STATUS_9C);
1186 offStatus(STATUS_9D);
1187 offStatus(STATUS_9E);
1189 offStatus(STATUS_88);
1192 offStatus(STATUS_97);
1193 offStatus(STATUS_A1);
1194 mKey.offStatus(dAcPyKey_c::STATUS_FORCE_JUMP);
1195 mKey.offStatus(dAcPyKey_c::STATUS_FORCE_NO_JUMP);
1196}
1197
1198void dAcPy_c::executeState_RideOffJump() {
1199 gravitySet();
1200 maxFallSpeedSet();
1201 moveSpeedSet();
1202 airPowerSet();
1203 if (mSubstateTimer == 0) {
1206 }
1207 jump_common();
1208}
1209
1210void dAcPy_c::initializeState_SitJump() {
1211 onStatus(STATUS_9B);
1212 onStatus(STATUS_9C);
1213 onStatus(STATUS_9D);
1215 onStatus(STATUS_9E);
1218 onStatus(STATUS_A0);
1219 onStatus(STATUS_A1);
1220 m_12f4 = mDirection;
1221 mSpeedMax.x = 0.0f;
1222 if (!stateArg<bool>()) {
1223 _jumpSet(nullptr);
1224 } else {
1225 mPyMdlMng.setAnm(PLAYER_ANIM_S_JUMP2);
1226 mAngle.y = getMukiAngle(mDirection);
1227 }
1228}
1229
1230void dAcPy_c::finalizeState_SitJump() {
1231 mAngle.x = 0;
1232 mAngle.y = getMukiAngle(mDirection);
1234 offStatus(STATUS_48);
1235 offStatus(STATUS_9B);
1236 offStatus(STATUS_9C);
1237 offStatus(STATUS_9D);
1238 offStatus(STATUS_9E);
1240 offStatus(STATUS_88);
1243 offStatus(STATUS_A0);
1244 offStatus(STATUS_A1);
1245 offStatus(STATUS_AA);
1246 mKey.offStatus(dAcPyKey_c::STATUS_FORCE_JUMP);
1247 mKey.offStatus(dAcPyKey_c::STATUS_FORCE_NO_JUMP);
1248}
1249
1250void dAcPy_c::executeState_SitJump() {
1251 gravitySet();
1252 maxFallSpeedSet();
1253 moveSpeedSet();
1254 airPowerSet();
1256 if (dScStage_c::m_instance->mCurrWorld == WORLD_5 && dScStage_c::m_instance->mCurrCourse == STAGE_GHOST_HOUSE) {
1257 if (isNowBgCross(BGC_BLOCK_HIT) && isOldBgCross(BGC_SEMISOLID)) {
1258 if (mLastPosDelta.x < 0.0f) {
1259 mPos.x -= 4.0f;
1260 } else {
1261 mPos.x += 4.0f;
1262 }
1263 mSpeedF = 0.0f;
1264 }
1265 }
1266 jump_common();
1267 if (mSpeed.y < 0.0f) {
1268 offStatus(STATUS_AA);
1269 if (!mKey.buttonCrouch() && !checkStandUpRoof()) {
1270 jmpInf_c jumpInf(mSpeed.y, 0, BLEND_DEFAULT);
1271 changeState(StateID_Jump, &jumpInf);
1272 }
1273 }
1274}
1275
1276void dAcPy_c::initializeState_KaniJump() {
1277 onStatus(STATUS_9B);
1278 onStatus(STATUS_9C);
1279 onStatus(STATUS_9D);
1281 onStatus(STATUS_9E);
1284 onStatus(STATUS_A2);
1285 jmpInf_c jumpInf(3.0f, 1, BLEND_DEFAULT);
1286 _jumpSet(&jumpInf);
1287 mSpeedMax.x = 0.0f;
1288 mAngle.y = 0;
1289}
1290
1291void dAcPy_c::finalizeState_KaniJump() {
1292 mAngle.x = 0;
1294 offStatus(STATUS_48);
1295 offStatus(STATUS_9B);
1296 offStatus(STATUS_9C);
1297 offStatus(STATUS_9D);
1298 offStatus(STATUS_9E);
1300 offStatus(STATUS_88);
1303 offStatus(STATUS_A2);
1304}
1305
1306void dAcPy_c::executeState_KaniJump() {
1307 gravitySet();
1308 maxFallSpeedSet();
1309 setKaniMoveSpeed(true);
1311 jump_common();
1312 if (mPos.y < m_d8c - 4.0f) {
1313 changeState(StateID_Fall, false);
1314 }
1315}
1316
1317void dAcPy_c::initializeState_CannonJump() {
1318 onStatus(STATUS_BD);
1320 onStatus(STATUS_88);
1321 onStatus(STATUS_7F);
1322 if (m_68 == 1) {
1323 onStatus(STATUS_7A);
1324 }
1325 clearNowBgCross();
1326 dQuake_c::m_instance->shockMotor(mPlayerNo, dQuake_c::TYPE_5, 0, false);
1327 startPlayerVoice(VOICE_CANNON_SHOT_S, 0);
1328 mPyMdlMng.setAnm(PLAYER_ANIM_SHOOT);
1329 mKey.onStatus(dAcPyKey_c::STATUS_DISABLE_LR);
1330 mKey.onStatus(dAcPyKey_c::STATUS_FORCE_NO_JUMP);
1331 mAngle.y = getMukiAngle(mDirection);
1332 int ang = cM::atan2s(std::fabs(mSpeedF), mSpeed.y);
1333 mAngle.x = 0x4000 - ang;
1334 mSubstateValue = 0;
1335 m_12b4 = (u32) mStateArg;
1336 m_12a8 = mPos;
1337}
1338
1339void dAcPy_c::finalizeState_CannonJump() {
1340 float data = getSpeedData()->mHighSpeed;
1341 if (mSpeedF > data) {
1342 mSpeedF = data;
1343 }
1344 if (mSpeedF < -data) {
1345 mSpeedF = -data;
1346 }
1347 offStatus(STATUS_7F);
1349 offStatus(STATUS_BD);
1350 offStatus(STATUS_88);
1352 offStatus(STATUS_7A);
1353 mKey.offStatus(dAcPyKey_c::STATUS_DISABLE_LR);
1354 mKey.offStatus(dAcPyKey_c::STATUS_FORCE_NO_JUMP);
1355 mAngle.x = 0;
1356}
1357
1358void dAcPy_c::executeState_CannonJump() {
1359 if (isStatus(STATUS_8E)) {
1361 }
1362 switch ((CannonJumpSubstate_e) mSubstate) {
1363 case CANNON_JUMP_ACTION_0: {
1364 setCcAtCannon();
1365 if (m_12b4 != 0) {
1366 m_12b4--;
1367 mAccelF = 0.0f;
1368 mAccelY = 0.0f;
1369 } else {
1370 mAccelY = -0.5f;
1371 if (std::fabs(mSpeedF) >= 1.0f) {
1372 mAccelF = 0.03f;
1373 } else {
1374 mAccelF = 0.0f;
1375 }
1376 }
1377 mVec3_c tmp(m_12a8.x - mPos.x, m_12a8.y - mPos.y, 0.0f);
1378 if (PSVECMag(tmp) >= 8.0f) {
1379 if (!isStatus(STATUS_8E)) {
1380 offStatus(STATUS_7F);
1381 }
1382 offZPosSetNone();
1383 }
1384 int ang = cM::atan2s(std::fabs(mSpeedF), mSpeed.y);
1385 mAngle.x = 0x4000 - ang;
1386 if (isNowBgCross(BGC_HEAD) || isNowBgCross(BgCross1_e(BGC_WALL_TOUCH_L_2 | BGC_WALL_TOUCH_R_2))) {
1387 mSpeed.y = 0.0f;
1388 changeState(StateID_Fall, false);
1389 } else {
1390 if (mSpeed.y <= 0.0f && std::fabs(mSpeedF) < 0.1f) {
1391 changeState(StateID_Fall, false);
1392 }
1393 if (isNowBgCross(BGC_FOOT)) {
1394 mPyMdlMng.setAnm(PLAYER_ANIM_SHOOT_SLIP);
1395 mSubstate = CANNON_JUMP_ACTION_1;
1396 mAngle.x = 0;
1397 offStatus(STATUS_BD);
1398 }
1399 }
1400 break;
1401 }
1402 case CANNON_JUMP_ACTION_1:
1403 if (mSpeedF) {
1404 setCcAtCannon();
1405 }
1406 gravitySet();
1407 maxFallSpeedSet();
1408 mMaxSpeedF = 0.0f;
1409 powerSet();
1410 if (isNowBgCross(BGC_FOOT)) {
1411 setCrouchSmokeEffect();
1412 if (!(std::fabs(mSpeedF) < 1.0f && checkJumpTrigger()) && std::fabs(mSpeedF) <= 0.1f) {
1413 mPyMdlMng.setAnm(PLAYER_ANIM_SHOOT_SLIP_END);
1414 mSubstate = CANNON_JUMP_ACTION_2;
1415 mSpeedF = 0.0f;
1416 }
1417 } else {
1418 mSubstate = CANNON_JUMP_ACTION_0;
1419 mPyMdlMng.setAnm(PLAYER_ANIM_SHOOT);
1420 }
1421 break;
1422 case CANNON_JUMP_ACTION_2:
1423 if (isNowBgCross(BGC_FOOT)) {
1424 if (checkJumpTrigger()) {
1425 return;
1426 }
1427 } else {
1428 changeState(StateID_Fall, false);
1429 return;
1430 }
1431 if (mPyMdlMng.isAnmStop()) {
1432 changeState(StateID_Walk, BLEND_DEFAULT);
1433 }
1434 break;
1435 }
1436}
1437
1438void dAcPy_c::initializeState_BlockJump() {
1439 onStatus(STATUS_7F);
1440 onStatus(STATUS_7A);
1441 mSubstate = (int) mStateArg;
1442 if (mSubstate == BLOCK_JUMP_ACTION_0) {
1443 jmpInf_c jumpInf(sc_JumpSpeed, 0, BLEND_DEFAULT);
1444 _jumpSet(&jumpInf);
1445 } else {
1446 mSubstateTimer = 10;
1447 }
1448 mSpeedF = 0.5f;
1449 mKey.onStatus(dAcPyKey_c::STATUS_FORCE_JUMP);
1450 if (isItemKinopio()) {
1451 startSound(SE_VOC_ITEM_KO_FOUND, false);
1452 }
1453}
1454
1455void dAcPy_c::finalizeState_BlockJump() {
1456 offStatus(STATUS_7F);
1457 offStatus(STATUS_7A);
1458 mKey.offStatus(dAcPyKey_c::STATUS_FORCE_JUMP);
1459}
1460
1461void dAcPy_c::executeState_BlockJump() {
1462 gravitySet();
1463 maxFallSpeedSet();
1464 moveSpeedSet();
1465 airPowerSet();
1466 jump_common();
1467 if (mSubstate == BLOCK_JUMP_ACTION_0) {
1468 if (mSpeed.y < 0.0f) {
1469 changeState(StateID_Fall, false);
1470 }
1471 if (mSubstateTimer == 0) {
1472 offStatus(STATUS_7F);
1473 if (isNowBgCross(BGC_HEAD)) {
1474 changeState(StateID_Fall, false);
1475 }
1476 }
1477 } else if (mSubstateTimer == 0) {
1478 changeState(StateID_Fall, false);
1479 }
1480}
1481
1482void dAcPy_c::setSlipAction() {
1483 mMoveSakaAngle = mBc.getSakaAngleBySpeed(mSpeedF);
1484 if (mPowerup == POWERUP_PENGUIN_SUIT) {
1485 if (isState(StateID_HipAttack)) {
1486 mDirection = mBc.getSakaDir();
1487 }
1488 changeState(StateID_PenguinSlide, 0);
1489 } else {
1490 changeState(daPlBase_c::StateID_Slip, 0); // [why daPlBase_c version?]
1491 }
1492}
1493
1494void dAcPy_c::setSlipSE() {
1495 if (!mSpeedF) {
1496 return;
1497 }
1498 if (isNowBgCross(BGC_WATER_TOUCH) && mPowerup == POWERUP_MINI_MUSHROOM) {
1499 holdSound(SE_PLY_SLIP_W, 0);
1500 } else {
1501 daPlBase_c::setSlipSE();
1502 }
1503}
1504
1505void dAcPy_c::setSlipEffect() {
1506 daPlBase_c::setSlipSmokeEffect();
1507 setSlipSE();
1508}
1509
1510void dAcPy_c::slipActionMove(int mode) {
1511 if (isNowBgCross(BGC_FOOT) && std::fabs(mSpeedF) > 0.1f) {
1512 setSlipEffect();
1513 }
1514 daPlBase_c::slipActionMove(mode);
1515}
1516
1517void dAcPy_c::initializeState_Slip() {
1518 daPlBase_c::initializeState_Slip();
1519 releaseCarryActor();
1521 setWaterWalkFlag();
1522}
1523
1524void dAcPy_c::finalizeState_Slip() {
1525 daPlBase_c::finalizeState_Slip();
1527}
1528
1529void dAcPy_c::executeState_Slip() {
1530 daPlBase_c::executeState_Slip();
1531}
1532
1533void dAcPy_c::initializeState_RollSlip() {
1534 m_d8c = mPos.y;
1535 mSubstate = ROLL_SLIP_ACTION_0;
1536 mPyMdlMng.setAnm(PLAYER_ANIM_STAR_ROLL_DUPLICATE);
1537 mMaxSpeedF = getSlipMaxSpeedF();
1538 mMaxFallSpeed = -3.0f;
1539 m_94 = 2.0f;
1540 mSubstateTimer = 4;
1541 mNoInteractTimer = 10;
1542 setInvalidKeyTimer_LR(10, 1);
1543 releaseCarryActor();
1544 onStatus(STATUS_32);
1545 onStatus(STATUS_97);
1547 onStatus(STATUS_31);
1548 onStatus(STATUS_88);
1550 onStatus(STATUS_A1);
1551 mKey.onStatus(dAcPyKey_c::STATUS_FORCE_JUMP);
1552}
1553
1554void dAcPy_c::finalizeState_RollSlip() {
1555 offStatus(STATUS_32);
1558 offStatus(STATUS_31);
1559 offStatus(STATUS_88);
1561 offStatus(STATUS_A1);
1562 mNoInteractTimer = 0;
1563 mTimer_a8 = 0;
1564 mKey.offStatus(dAcPyKey_c::STATUS_FORCE_JUMP);
1565 if (std::fabs(mSpeedF) > 1.0f) {
1566 mSpeedF = sc_DirSpeed[mDirection];
1567 }
1568}
1569
1570void dAcPy_c::executeState_RollSlip() {
1571 if (mSubstateTimer == 0) {
1573 }
1574 gravitySet();
1575 moveSpeedSet();
1576 powerSet();
1577 turnAngle();
1578 if (mSubstateValue != 0 && mKey.triggerJump()) {
1579 setJump(sc_JumpSpeed, mSpeedF * 0.8f, true, 0, 1);
1580 return;
1581 }
1582 switch ((RollSlipSubstate_e) mSubstate) {
1583 case ROLL_SLIP_ACTION_0:
1584 holdSound(SE_PLY_MOVE_ROLLING, false);
1585 switch (mSubstateValue) {
1586 case 0:
1587 mAccelF = 0.0f;
1588 m_94 = 1.5f;
1589 mPyMdlMng.mpMdl->setRate(m_94);
1590 if (isNowBgCross(BGC_FOOT)) {
1591 mSubstateValue = 1;
1592 mSpeedF = sc_DirSpeed[mDirection];
1593 mSpeed.y = 2.0f;
1594 mPyMdlMng.mpMdl->setFrame(0.0f);
1595 } else if (isNowBgCross(BgCross1_e(BGC_WALL_TOUCH_L_2 | BGC_WALL_TOUCH_R_2))) {
1596 mSubstateValue = 1;
1597 mDirection = mDirection ^ 1;
1598 mSpeedF = sc_DirSpeed[mDirection];
1599 mSpeed.y = 0.0f;
1600 mPyMdlMng.mpMdl->setFrame(0.0f);
1601 }
1602 break;
1603 case 1:
1604 mPyMdlMng.mpMdl->setRate(0.5f);
1605 if (isNowBgCross(BGC_FOOT)) {
1606 if (isNowBgCross(BGC_FOOT)) {
1607 if (!mKey.buttonCrouch()) {
1608 setSlipAction_ToEnd();
1609 } else {
1610 setSlipAction_ToStoop();
1611 }
1612 }
1613 }
1614 break;
1615 case 2:
1616 if (!isNowBgCross(BGC_FOOT)) {
1617 changeState(StateID_Fall, false);
1618 return;
1619 }
1620 float s = std::fabs(mSpeedF) * 0.5f;
1621 if (s > 1.0f) {
1622 s = 1.0f;
1623 }
1624 if (s < 0.1f) {
1625 s = 0.1f;
1626 }
1627 if (mSpeedF * sc_DirSpeed[mDirection] < 0.0f) {
1628 s = -s;
1629 }
1630 mPyMdlMng.mpMdl->setRate(s);
1631 if (std::fabs(mSpeedF) < 1.1f) {
1632 if (!mKey.buttonCrouch()) {
1633 setSlipAction_ToEnd();
1634 } else {
1635 setSlipAction_ToStoop();
1636 }
1637 }
1638 }
1639 // [Fallthrough...?]
1640 case ROLL_SLIP_ACTION_1:
1641 mMaxSpeedF = 0.0f;
1642 if (mPyMdlMng.isAnmStop()) {
1643 changeState(StateID_Crouch, CROUCH_ARG_FROM_OTHER);
1644 }
1645 break;
1646 case ROLL_SLIP_ACTION_2:
1647 mSpeedF = 0.0f;
1648 mMaxSpeedF = 0.0f;
1649 if (mPyMdlMng.isAnmStop()) {
1650 changeActionSlipEnd(BLEND_DEFAULT);
1651 }
1652 break;
1653 }
1654}
1655
1656void dAcPy_c::initializeState_PenguinSlide() {
1657 mSubstate = PENGUIN_SLIDE_ACTION_0;
1658 mMaxSpeedF = getSlipMaxSpeedF();
1659 if (isNowBgCross(BGC_FOOT) && !isSlipSaka()) {
1660 float f = std::fabs(mSpeedF) / getSpeedData()->mHighSpeed + 0.2f;
1661 if (f > 1.0f) {
1662 f = 1.0f;
1663 }
1664 if (f < 0.5f) {
1665 f = 0.5f;
1666 }
1667 m_54c = mSpeedF + f * sc_DirSpeed[mDirection];
1668 if (m_54c > 4.0f) {
1669 m_54c = 4.0f;
1670 }
1671 if (m_54c < -4.0f) {
1672 m_54c = -4.0f;
1673 }
1674 m_548 = 1;
1675 }
1676 if (mPos.y >= mWaterHeight - 4.0f) {
1678 }
1679 mSubstateTimer = 8;
1680 releaseCarryActor();
1682 onStatus(STATUS_97);
1684 onStatus(STATUS_A2);
1686 onStatus(STATUS_88);
1687
1688 mPyMdlMng.setAnm(PLAYER_ANIM_P_SLIP);
1689 startPlayerVoice(VOICE_PNGN_SLIDE, 0);
1690 m_540 = 30;
1691 m_544 = getData(0);
1692}
1693
1694void dAcPy_c::finalizeState_PenguinSlide() {
1697 offStatus(STATUS_A2);
1699 offStatus(STATUS_88);
1702 m_1598 = 0.0f;
1703 mAngle.x = 0;
1704 m_b98 = 10;
1705}
1706
1707bool dAcPy_c::checkPenguinSlideJump() {
1708 if (isNowBgCross(BGC_FOOT) && mKey.triggerJump()) {
1709 int dir = -1;
1710 if (mKey.buttonDown() || (mKey.buttonWalk(&dir) && dir == mDirection)) {
1711 mPyMdlMng.setAnm(PLAYER_ANIM_P_SLIP_JUMP);
1712 startSound(SE_PLY_PNGN_JUMP, false);
1714 offNowBgCross(BGC_FOOT);
1715 float tmp = std::fabs(mSpeedF) - 1.5f;
1716 mSpeed.y = data_802f5a48[2] + tmp * data_802f5a48[3];
1717 if (mSpeed.y > data_802f5a48[1]) {
1718 mSpeed.y = data_802f5a48[1];
1719 }
1720 if (mSpeed.y < data_802f5a48[2]) {
1721 mSpeed.y = data_802f5a48[2];
1722 }
1723 } else {
1724 setJump(sc_JumpSpeed, mSpeedF * 0.8f, true, 0, 1);
1725 }
1726 return true;
1727 }
1728 return false;
1729}
1730
1731void dAcPy_c::executeState_PenguinSlide() {
1732 gravitySet();
1733 maxFallSpeedSet();
1734 moveSpeedSet();
1735 powerSet();
1736 m_1598 = 0.0f;
1737 if (!isStatus(STATUS_CAN_WATER_SLIDE) && mPos.y >= mWaterHeight - 1.0f) {
1739 }
1740 if (isNowBgCross(BGC_ON_WATER_MOVE)) {
1741 mSpeed.y = sc_MaxFallSpeed_Foot;
1742 }
1743 if (m_544 != 0) {
1744 m_544--;
1745 }
1746 if (isNowBgCross(BGC_FOOT) && m_540 != 0) {
1747 m_540--;
1748 }
1749 s16 newAng = 0;
1750 if (isNowBgCross(BGC_FOOT)) {
1751 newAng = mBc.getSakaAngle(mDirection);
1752 }
1753 sLib::addCalcAngle(&mAngle.x.mAngle, newAng, 4, 0x2000, 0x40);
1754 if (isNowBgCross(BGC_FOOT)) {
1756 case PENGUIN_SLIDE_ACTION_0:
1757 if (checkPenguinSlideJump()) {
1758 return;
1759 }
1760 break;
1761 case PENGUIN_SLIDE_ACTION_1:
1762 if (setCrouchJump()) {
1763 return;
1764 }
1765 break;
1766 case PENGUIN_SLIDE_ACTION_2:
1767 if (checkJumpTrigger()) {
1768 return;
1769 }
1770 break;
1771 }
1772 }
1773 if (mPowerup != POWERUP_PENGUIN_SUIT) {
1774 changeState(StateID_Walk, BLEND_NONE);
1775 return;
1776 }
1777 if (mSpeedF * sc_DirSpeed[mDirection] < 0.0f) {
1778 mDirection = mDirection ^ 1;
1779 }
1780 int ang = turnAngle();
1782 case PENGUIN_SLIDE_ACTION_0:
1783 if (mPlayerType == PLAYER_LUIGI) {
1784 m_1598 = -0.5f;
1785 } else {
1786 m_1598 = 1.0f;
1787 }
1788 if (!isStatus(STATUS_DEMO_NEXT_GOTO_BLOCK) && m_540 == 0) {
1789 if (!isNowBgCross(BGC_FOOT)) {
1791 }
1792 if (!isStatus(STATUS_INITIAL_SLIDE) && (isNowBgCross(BGC_FOOT) || mSpeed.y < 0.0f)) {
1793 int dir = -1;
1794 if (!(mKey.buttonDown() || (mKey.buttonWalk(&dir) && dir == mDirection))) {
1795 onStatus(STATUS_52);
1796 changeState(StateID_Walk, BLEND_NONE);
1797 return;
1798 }
1799 }
1800 }
1801 if (isNowBgCross(BGC_FOOT)) {
1802 setPenguinSlideEffect();
1803 if (mPyMdlMng.getAnm() != PLAYER_ANIM_P_SLIP) {
1804 mPyMdlMng.setAnm(PLAYER_ANIM_P_SLIP);
1805 }
1808 setPenguinSlideLandEffect();
1809 }
1810 } else if (isStatus(STATUS_PENGUIN_SLIDE_JUMP)) {
1811 if (mSpeed.y < 0.0f && mPyMdlMng.getAnm() != PLAYER_ANIM_P_SLIP_JUMP2) {
1812 mPyMdlMng.setAnm(PLAYER_ANIM_P_SLIP_JUMP2);
1813 }
1814 }
1815 daPlBase_c::slipActionMove(ang);
1816 if (isNowBgCross(BGC_FOOT)) {
1817 if (mGroundType == GROUND_TYPE_WATER) {
1818 holdSound(SE_PLY_PNGN_SLIP_SEA, std::fabs(mSpeedF), false);
1819 } else {
1820 holdSound(SE_PLY_PNGN_SLIP, false);
1821 }
1822 }
1823 break;
1824 case PENGUIN_SLIDE_ACTION_1:
1825 mMaxSpeedF = 0.0f;
1826 if (mPyMdlMng.isAnmStop()) {
1827 changeState(StateID_Crouch, CROUCH_ARG_FROM_OTHER);
1828 return;
1829 }
1830 break;
1831 case PENGUIN_SLIDE_ACTION_2:
1832 if (mPyMdlMng.isAnmStop()) {
1833 changeActionSlipEnd(BLEND_DEFAULT);
1834 return;
1835 }
1836 break;
1837 }
1838 if (isNowBgCross(BGC_FOOT)) {
1839 if (isSlipSaka()) {
1840 if (mMaxSpeedF * mSpeedF > 0.0f) {
1841 mAccelF = 1.2f * mAccelF;
1842 m_544 = data_802f5a48[0];
1843 } else {
1844 m_548 = 0;
1845 if (getPowerChangeType(true) != POWER_CHANGE_NORMAL) {
1846 mAccelF = 0.01f;
1847 }
1848 }
1849 } else {
1850 if (getPowerChangeType(true) != POWER_CHANGE_NORMAL) {
1851 mAccelF = 0.005f;
1852 }
1853 if (m_544 && mMaxSpeedF == 0.0f) {
1854 mAccelF = 0.0f;
1855 }
1856 }
1857 } else {
1858 mAccelF = 0.0f;
1859 mMaxSpeedF = std::fabs(mSpeedF);
1860 }
1861 if (m_548 == 1) {
1862 if (isStatus(STATUS_FOLLOW_MAME_KURIBO) || std::fabs(mSpeedF) >= std::fabs(m_54c)) {
1863 m_548 = 0;
1864 } else {
1865 mAccelF = 0.1f;
1866 mMaxSpeedF = m_54c;
1867 }
1868 }
1869}
1870
1871void dAcPy_c::setPenguinSlideEffect() {
1872 if (!isNowBgCross(BGC_FOOT)) {
1873 return;
1874 }
1875 mAng3_c ang(0, 0, 0);
1876 if (mDirection == 1) {
1877 ang.y = 0x8000;
1878 }
1879 mVec3_c efPos;
1880 if (mGroundType == GROUND_TYPE_WATER) {
1881 efPos.set(mPos.x, mWaterHeight, mPos.z);
1882 dEf::createPlayerEffect(mPlayerNo, &mLevelEf4, "Wm_mr_waterswim", 0, &efPos, nullptr, nullptr);
1883 dEf::createPlayerEffect(mPlayerNo, &mLevelEf5, "Wm_en_cmnwater02", 0, &efPos, &ang, nullptr);
1884 } else {
1885 mpMdlMng->mpMdl->getJointPos(&efPos, 1);
1886 static const char *sc_penguinSlidEffectID[] = {
1887 "Wm_mr_penguinsmoke",
1888 "Wm_mr_penguinsnow",
1889 "Wm_mr_pdesertsmoke",
1890 "Wm_mr_penguinice",
1891 "Wm_mr_penguinsmoke",
1892 "Wm_mr_waterswim",
1893 "Wm_mr_penguinsmoke",
1894 "Wm_mr_pdesertsmoke",
1895 "Wm_mr_penguinsmoke",
1896 "Wm_mr_pbeachsmoke",
1897 "Wm_mr_penguinsmoke",
1898 "Wm_mr_penguinsmoke",
1899 "Wm_mr_penguinsmoke"
1900 };
1901 dEf::createPlayerEffect(mPlayerNo, &mLevelEf4, sc_penguinSlidEffectID[mGroundType], 0, &efPos, nullptr, nullptr);
1902 switch (mGroundType) {
1903 case GROUND_TYPE_SNOW:
1904 dEf::createPlayerEffect(mPlayerNo, &mLevelEf5, "Wm_mr_p_snowslip", 0, &efPos, &ang, nullptr);
1905 break;
1906 case GROUND_TYPE_ICE:
1907 dEf::createPlayerEffect(mPlayerNo, &mLevelEf5, "Wm_mr_p_iceslip", 0, &efPos, &ang, nullptr);
1908 break;
1909 default:
1910 break;
1911 }
1912 }
1913}
1914
1915void dAcPy_c::setPenguinSlideLandEffect() {
1916 setLandSmokeEffect(0);
1917 if (mGroundType == GROUND_TYPE_WATER) {
1918 startSound(SE_PLY_SPLASH_SHALLOW, false);
1919 }
1920}
1921
1922bool dAcPy_c::isWaitFrameCountMax() {
1923 return mWaitFrameCount >= 80;
1924}
1925
1926bool dAcPy_c::checkWalkNextAction() {
1927 if (checkCarryThrow()) {
1928 return true;
1929 }
1930 if (checkSlip()) {
1931 return true;
1932 }
1933 if (checkJumpTrigger()) {
1934 return true;
1935 }
1936 if (!isNowBgCross(BGC_FOOT)) {
1937 mSpeed.y = 0.0f;
1938 if (setDelayHelpJump()) {
1939 return true;
1940 }
1941 if (mAirWalkTimer == 0) {
1942 changeState(StateID_Fall, false);
1943 return true;
1944 }
1945 }
1946 if (isState(StateID_Walk) && mKey.buttonWalk(nullptr) && mDirection != mPrevDirection) {
1947 mKey.onStatus(dAcPyKey_c::STATUS_SHAKE_COOLDOWN);
1948 if (checkTurn()) {
1949 return true;
1950 }
1951 }
1952 if (isState(daPlBase_c::StateID_Walk) || isState(StateID_Land)) { // [why daPlBase_c?]
1953 if (checkCrouch()) {
1954 return true;
1955 }
1956 }
1957 return false;
1958}
1959
1960void dAcPy_c::setWalkActionAnm(AnmBlend_e blendMode) {
1961 float speed = std::fabs(mSpeedF);
1962 float f;
1963 if (mPowerup == POWERUP_MINI_MUSHROOM) {
1964 if (speed <= getSpeedData()->mLowSpeed) {
1965 float tmp = speed * 2.0f * 1.45f;
1966 f = (tmp < 2.0f) ? 2.0f : tmp;
1967 } else {
1968 float tmp = speed * 1.5f * 1.45f;
1969 f = (tmp < 0.5f) ? 0.5f : tmp;
1970 }
1971 } else {
1972 if (speed <= getSpeedData()->mLowSpeed) {
1973 float tmp = speed * 2.0f;
1974 f = (tmp < 2.0f) ? 2.0f : tmp;
1975 } else {
1976 float tmp = speed * 1.5f;
1977 f = (tmp < 0.5f) ? 0.5f : tmp;
1978 }
1979 }
1980 float g = 4.0f;
1981 if (mPowerup == POWERUP_MINI_MUSHROOM) {
1982 if (speed <= getSpeedData()->mLowSpeed) {
1983 g = 8.7f;
1984 } else {
1985 g = 5.8f;
1986 }
1987 }
1988 if (
1989 isNowBgCross(BGC_ON_BELT_L) && mSpeedF > 0.0f ||
1990 isNowBgCross(BGC_ON_BELT_R) && mSpeedF < 0.0f
1991 ) {
1992 float tmp = speed * 2.5f;
1993 f = (tmp < 2.0f) ? 2.0f : ((tmp > g) ? g : tmp);
1994 }
1995 float h = f;
1996 if (isSaka() && mBc.getSakaUpDown(mDirection) == 1 && mMaxSpeedF && mSpeedF * sc_DirSpeed[mDirection] >= 0.0f) {
1997 h = f * 2.0f;
1998 if (h > g) {
1999 h = g;
2000 }
2001 }
2002 if (mPowerup != POWERUP_PENGUIN_SUIT && isNowBgCross(BGC_ON_ICE) && speed < getSpeedData()->mMediumSpeed) {
2003 float tmp = h * 8.0f;
2004 h = (tmp > g) ? g : tmp;
2005 }
2006 if (isNowBgCross(BgCross1_e(BGC_ON_SINK_SAND | BGC_IN_SINK_SAND))) {
2007 if (isNowBgCross(BGC_IN_SINK_SAND)) {
2008 h *= 0.5f;
2009 } else {
2010 h *= 0.7f;
2011 }
2012 }
2013 setNormalWalkAnm(blendMode, h);
2014}
2015
2017 if (dScStage_c::m_isStaffCredit && isStatus(STATUS_ENDING_DANCE_AUTO)) {
2018 mPyMdlMng.setAnm(PLAYER_ANIM_ENDING_WAIT);
2019 return;
2020 }
2021 if (isStatus(STATUS_63)) {
2022 mPyMdlMng.setAnm(PLAYER_ANIM_WAIT_DUPLICATE2);
2023 return;
2024 }
2025 /// @unofficial
2026 static const float scSakaCheckOffset[] = { 2.0f, 0.0f, -2.0f, 4.0f, 0.0f, -4.0f };
2027 s16 ang = mStillSakaAngle;
2028 int count = 0;
2029 float sum = 0.0f;
2030 for (int i = 0; i < 3; i++) {
2031 mVec3_c p(mPos.x + scSakaCheckOffset[3 + i], mPos.y + 5.0f, mPos.z);
2032 s16 tmpAng;
2033 float f;
2034 if (dBc_c::checkGroundAngle(&p, &f, &tmpAng, mLayer, mAmiLayer, -1, nullptr, 0) && std::fabs(f - mPos.y) < 8.0f) {
2035 count++;
2036 sum += tmpAng;
2037 }
2038 }
2039 if (count != 0) {
2040 ang = sum / count;
2041 }
2042 static const int scSlopeWaitAnm[] = { PLAYER_ANIM_SLOPE_WAIT_L, PLAYER_ANIM_SLOPE_WAIT_R };
2043 static const int scLongWaitAnm[] = { PLAYER_ANIM_WAIT_L, PLAYER_ANIM_WAIT_R };
2044 if (ang != 0 || m_80 != 0) {
2045 ang = -ang * sc_DirSpeed[mDirection];
2046 float f = ang * mAng::AngleToDegreeCoefficient + 70.0f;
2047 if (f < 0.0f) {
2048 f = 0.0f;
2049 }
2050 if (f > 140.0f) {
2051 f = 140.0f;
2052 }
2053 if (blendMode == BLEND_DEFAULT) {
2054 mPyMdlMng.setAnm(scSlopeWaitAnm[mDirection], f);
2055 } else {
2056 mPyMdlMng.setAnm(scSlopeWaitAnm[mDirection], 0.0f, f);
2057 }
2058 mPyMdlMng.mpMdl->m_17c |= 0x40;
2059 m_80 = 1;
2060 } else {
2061 if (blendMode == BLEND_DEFAULT) {
2062 mPyMdlMng.setAnm(scLongWaitAnm[mDirection]);
2063 } else {
2064 mPyMdlMng.setAnm(scLongWaitAnm[mDirection], 0.0f, 0.0f);
2065 }
2066 }
2067}
2068
2069bool dAcPy_c::isIceSlipAnmPlay() {
2070 if (isNowBgCross(BGC_ON_ICE) && !mKey.buttonWalk(nullptr) && mPowerup != POWERUP_PENGUIN_SUIT) {
2071 return true;
2072 }
2073 return false;
2074}
2075
2076void dAcPy_c::setNormalWalkAnm(AnmBlend_e blendMode, float speedRate) {
2077 if (isIceSlipAnmPlay()) {
2078 switch (mWalkAnmState) {
2079 case 0:
2080 if (isNowBgCross(BGC_LIFT) && std::fabs(mBc.mIceSpeed) > 1.0f || std::fabs(mSpeedF) > 0.82f) {
2081 if (mSpeedF * sc_DirSpeed[mDirection] < 0.0f) {
2082 mPyMdlMng.setAnm(PLAYER_ANIM_ICE_SLIP_B);
2083 } else {
2084 mPyMdlMng.setAnm(PLAYER_ANIM_ICE_SLIP_F);
2085 }
2086 mWalkAnmState = 1;
2087 } else {
2088 setWaitActionAnm(blendMode);
2089 }
2090 break;
2091 case 1:
2092 calcAccOnIceLift();
2093 if (mPyMdlMng.isAnmStop()) {
2094 setWaitActionAnm(blendMode);
2095 mWalkAnmState = 2;
2096 }
2097 break;
2098 case 2:
2099 calcAccOnIceLift();
2100 setWaitActionAnm(blendMode);
2101 break;
2102 }
2103 holdSound(SE_PLY_ICE_SLIP, std::fabs(mSpeedF), false);
2104 } else {
2105 mWalkAnmState = 0;
2106 onStatus(STATUS_62);
2107 int anmID;
2108 if (isCarry()) {
2109 anmID = (mPyMdlMng.mpMdl->m_17c & 0x4) ? PLAYER_ANIM_CARRY_P_WALK : PLAYER_ANIM_CARRY_WALK;
2110 blendMode = BLEND_NONE;
2111 } else {
2112 if (
2113 isNowBgCross(BGC_ON_BELT_L) && mSpeedF > 0.0f ||
2114 isNowBgCross(BGC_ON_BELT_R) && mSpeedF < 0.0f
2115 ) {
2116 anmID = PLAYER_ANIM_RUN;
2117 } else {
2118 float speed = std::fabs(mSpeedF);
2119 if (speed <= getSpeedData()->mLowSpeed) {
2120 anmID = PLAYER_ANIM_RUN;
2121 } else if (speed < getSpeedData()->mHighSpeed) {
2122 anmID = PLAYER_ANIM_B_DASH;
2123 } else {
2124 anmID = PLAYER_ANIM_B_DASH2;
2125 }
2126 }
2127 }
2128 if (!mPyMdlMng.isAnm(anmID)) {
2129 float blendDuration = 0.0f;
2130 if (blendMode == BLEND_DEFAULT) {
2131 blendDuration = dPyMdlMng_c::getHIO(anmID).mBlendDuration;
2132 }
2133 mPyMdlMng.setAnm(anmID, speedRate, blendDuration, 0.0f);
2134 } else {
2135 mPyMdlMng.mpMdl->setRate(speedRate);
2136 }
2137 }
2138}
2139
2140void dAcPy_c::walkActionInit_Wait(AnmBlend_e blendMode) {
2141 mSubstate = 0;
2142 mSubstateTimer = 150;
2143 mWaterWalkTimer = 8;
2144 setWaitActionAnm(blendMode);
2145}
2146
2147void dAcPy_c::walkAction_Wait() {
2148 if (!isWaitFrameCountMax()) {
2149 mWaitFrameCount++;
2150 }
2151 if (mSpeedF) {
2152 walkActionInit_Move(BLEND_DEFAULT);
2153 return;
2154 }
2156 if (isStatus(STATUS_63)) {
2157 mAngle.y.chase(0, 0x400);
2158 } else {
2159 turnAngle();
2160 }
2161 if (mSubstateTimer == 0) {
2162 m_15b2 = 8;
2163 }
2165 if (!sLib::calcTimer(&mWaterWalkTimer)) {
2167 m_15b6 = 30;
2168 }
2169 }
2170}
2171
2172void dAcPy_c::walkActionInit_Move(AnmBlend_e blendMode) {
2173 mSubstate = 1;
2174 setWalkActionAnm(blendMode);
2175}
2176
2177void dAcPy_c::walkAction_Move() {
2178 m_80 = 0;
2179 mWaitFrameCount = 0;
2180 turnAngle();
2181 setRunOnWaterEffect();
2182 daPlBase_c::walkAction_Move();
2183 if (m_88 == 0 && !isNowBgCross(BGC_WATER_TOUCH)) {
2184 m_88 = 1;
2185 }
2186 if (m_88 == 1) {
2187 setWaterWalkFlag();
2188 }
2189}
2190
2191void dAcPy_c::initializeState_Walk() {
2192 AnmBlend_e blendMode = stateArg<AnmBlend_e>();
2194 m_88 = 1;
2195 if (isOldBgCross(BGC_WATER_SHALLOW)) {
2196 m_88 = 0;
2197 }
2198 if (mSpeedF) {
2199 walkActionInit_Move(blendMode);
2200 } else {
2201 walkActionInit_Wait(blendMode);
2202 }
2203 if (isItemKinopio()) {
2204 setControlDemoKinopioWalk();
2205 }
2206 onStatus(STATUS_9B);
2207 onStatus(STATUS_9D);
2208 onStatus(STATUS_9E);
2210 onStatus(STATUS_92);
2211 onStatus(STATUS_A0);
2213 onStatus(STATUS_A2);
2214 onStatus(STATUS_A3);
2215 m_80 = 0;
2216}
2217
2218void dAcPy_c::executeState_Walk() {
2219 daPlBase_c::executeState_Walk();
2220 mAccelY = getGravityData()[0];
2221 maxFallSpeedSet();
2222 moveSpeedSet();
2223 grandPowerSet();
2224 if (isNowBgCross(BGC_FOOT)) {
2225 if (isNowBgCross(BGC_ON_WATER_MOVE)) {
2227 } else {
2229 }
2230 }
2232 if (isOnSinkSand()) {
2234 }
2235 if (!checkWalkNextAction()) {
2236 switch (mSubstate) {
2237 case 0:
2238 walkAction_Wait();
2239 break;
2240 case 1:
2241 walkAction_Move();
2242 break;
2243 }
2244 if (!(mPyMdlMng.getFlags() & 0x1000) && mPyMdlMng.getFlags2() & 0x40) {
2245 mPyMdlMng.mpMdl->m_17c &= ~0x40;
2246 mPyMdlMng.mpMdl->releaseBodyAnm(0.0f);
2247 }
2248 }
2249}
2250
2251void dAcPy_c::finalizeState_Walk() {
2252 daPlBase_c::finalizeState_Walk();
2253 mWaitFrameCount = 0;
2254 offStatus(STATUS_9B);
2255 offStatus(STATUS_9D);
2256 offStatus(STATUS_9E);
2258 offStatus(STATUS_92);
2259 offStatus(STATUS_A0);
2260 offStatus(STATUS_A2);
2262 offStatus(STATUS_A3);
2263 mWalkAnmState = 0;
2264 if (mPyMdlMng.getFlags2() & 0x40) {
2265 mPyMdlMng.mpMdl->m_17c &= ~0x40;
2266 mPyMdlMng.mpMdl->releaseBodyAnm(0.0f);
2267 }
2268}
2269
2270void dAcPy_c::setRunOnWaterEffect() {
2271 if (isNowBgCross(BGC_ON_WATER_MOVE)) {
2272 static const char *sc_waterRunEffectID[] = {
2273 "Wm_mr_waterrun_l_ss",
2274 "Wm_mr_waterrun_r_ss"
2275 };
2276 dEf::createPlayerEffect(mPlayerNo, &mSmokeEffect, sc_waterRunEffectID[mDirection], 0, &mPos, nullptr, nullptr);
2277 }
2278}
2279
2280void dAcPy_c::initializeState_Turn() {
2282 onStatus(STATUS_A2);
2283 mSubstate = 0;
2284 if (getPowerChangeType(false) == POWER_CHANGE_ICE) {
2285 mPyMdlMng.setAnm(PLAYER_ANIM_ICE_TURN, 0.0f, 0.0f);
2286 } else {
2287 mPyMdlMng.setAnm(PLAYER_ANIM_TURN, 0.0f, 0.0f);
2288 }
2289 mAngle.y = getMukiAngle((mSpeedF < 0.0f) ? DIR_LR_L : DIR_LR_R);
2290 mDirection ^= 1;
2291 mMaxSpeedF = 0.0f;
2292 mAccelY = getGravityData()[0];
2293 maxFallSpeedSet();
2294 turnPowerSet();
2295 mKey.onStatus(dAcPyKey_c::STATUS_SHAKE_COOLDOWN);
2296}
2297
2298void dAcPy_c::finalizeState_Turn() {
2300 offStatus(STATUS_A2);
2301 fadeOutTurnEffect();
2302}
2303
2304void dAcPy_c::turnPowerSet() {
2305 u8 dir;
2306 if (mSpeedF < 0.0f) {
2307 dir = 1;
2308 } else if (mSpeedF > 0.0f) {
2309 dir = 0;
2310 } else {
2311 dir = mDirection;
2312 }
2313 sTurnPowerData data;
2314 getTurnPower(data);
2315 switch (mSubstate) {
2316 case 0:
2317 case 1:
2318 if (isSaka()) {
2319 if (mBc.getSakaUpDown(dir) == 1) {
2320 mAccelF = data.mSakaUp;
2321 } else {
2322 mAccelF = data.mSakaDown;
2323 }
2324 } else {
2325 mAccelF = data.mNormal;
2326 }
2327 if (isStatus(STATUS_89)) {
2328 mAccelF = getAccelF() * scTurnPowerUpRate;
2329 }
2330 break;
2331 case 2:
2332 mAccelF = data.mAir;
2333 break;
2334 }
2335}
2336
2337void dAcPy_c::setTurnSmokeEffect() {
2338 mVec3_c efPos;
2339 mPyMdlMng.mpMdl->getJointPos(&efPos, 7);
2340 setBrakeSmokeEffect(efPos);
2341 daPlBase_c::setTurnSmokeEffect();
2342}
2343
2344void dAcPy_c::executeState_Turn() {
2345 turnPowerSet();
2346 if (!checkWalkNextAction()) {
2347 switch (mSubstate) {
2348 case 0:
2349 setTurnSmokeEffect();
2350 if (mSpeedF == 0.0f) {
2351 mSubstateTimer = 8;
2352 mSubstate = 1;
2353 }
2354 if (!mKey.buttonWalk(nullptr)) {
2355 if (mSpeedF) {
2356 mDirection = mSpeedF < 0.0f ? DIR_LR_L : DIR_LR_R;
2357 }
2358 setTurnEnd();
2359 }
2360 break;
2361 case 1:
2362 setTurnSmokeEffect();
2363 if (mDirection != mPrevDirection) {
2364 setTurnEnd();
2365 } else if (mSubstateTimer == 0) {
2366 fadeOutTurnEffect();
2367 mSubstate = 2;
2368 if (getPowerChangeType(false) == POWER_CHANGE_ICE) {
2369 mPyMdlMng.setAnm(PLAYER_ANIM_ICE_TURNED, 0.0f, 0.0f);
2370 } else {
2371 mPyMdlMng.setAnm(PLAYER_ANIM_TURNED, 0.0f, 0.0f);
2372 }
2373 }
2374 break;
2375 case 2:
2376 float maxSpeed = 0.0f;
2377 int dir;
2378 if (mKey.buttonWalk(&dir)) {
2379 if (mKey.buttonDush()) {
2380 maxSpeed = sc_DirSpeed[dir] * getSpeedData()->mHighSpeed;
2381 } else {
2382 maxSpeed = sc_DirSpeed[dir] * getSpeedData()->mLowSpeed;
2383 }
2384 }
2385 mMaxSpeedF = maxSpeed;
2386 if (mDirection != mPrevDirection || mPyMdlMng.isAnmStop()) {
2387 setTurnEnd();
2388 }
2389 }
2390 }
2391}
2392
2393bool dAcPy_c::checkCrouch() {
2394 if (
2395 !isStatus(STATUS_51) &&
2397 !isOnSinkSand() &&
2398 !isStatus(STATUS_BE)
2399 ) {
2400 if (isCarry()) {
2401 return false;
2402 }
2403 if (mKey.buttonCrouch()) {
2404 if (mPowerup == POWERUP_PENGUIN_SUIT && isStatus(STATUS_CAN_PENGUIN_SLIDE)) {
2405 changeState(StateID_PenguinSlide, 0);
2406 return true;
2407 }
2408 changeState(StateID_Crouch, CROUCH_ARG_FROM_WALK);
2409 return true;
2410 }
2411 }
2412 return false;
2413}
2414
2415void dAcPy_c::setCrouchSmokeEffect() {
2416 if (!mSpeedF) {
2417 return;
2418 }
2419 if (!isNowBgCross(BGC_WATER_SHALLOW)) {
2420 mVec3_c efPos;
2421 mPyMdlMng.mpMdl->getJointPos(&efPos, 1);
2422 setBrakeSmokeEffect(efPos);
2423 }
2424 setSlipSE();
2425}
2426
2427void dAcPy_c::initializeState_Crouch() {
2428 if (!isNowBgCross(BGC_WATER_SHALLOW)) {
2429 mSubstate = CROUCH_GROUND;
2431 } else {
2432 mSubstate = CROUCH_WATER;
2433 onStatus(STATUS_AA);
2434 }
2435 switch (stateArg<CrouchArg_e>()) {
2437 if (!isNowBgCross(BGC_WATER_SHALLOW)) {
2438 mPyMdlMng.setAnm(PLAYER_ANIM_STOOP_START);
2439 } else {
2440 mPyMdlMng.setAnm(PLAYER_ANIM_STOOP_START, dPyMdlBase_c::scWaterCrouchAnmSpeed, 3.0f, 0.0f);
2441 }
2442 break;
2444 mPyMdlMng.setAnm(PLAYER_ANIM_STOOP, 3.0f, 0.0f);
2445 break;
2447 mPyMdlMng.setAnm(PLAYER_ANIM_S_JUMPED);
2448 break;
2449 }
2450 mAngle.y = getMukiAngle(mDirection);
2451 startSound(SE_PLY_QUAT, true);
2452 onStatus(STATUS_A8);
2453 onStatus(STATUS_51);
2454 onStatus(STATUS_A2);
2455 onStatus(STATUS_A3);
2456}
2457
2458void dAcPy_c::finalizeState_Crouch() {
2459 offStatus(STATUS_A8);
2460 offStatus(STATUS_9D);
2462 offStatus(STATUS_AA);
2463 offStatus(STATUS_51);
2465 offStatus(STATUS_A2);
2466 offStatus(STATUS_A3);
2467 m_2e8 = 0;
2468}
2469
2470void dAcPy_c::CrouchActionGround() {
2471 if (isOnSinkSand() && setCancelCrouch()) {
2472 return;
2473 }
2474 if (!setCrouchJump() && !checkCrouchSlip()) {
2475 if (!isNowBgCross(BGC_FOOT)) {
2476 mSpeed.y = 0.0f;
2477 changeState(StateID_SitJump, true);
2478 } else {
2479 setCrouchSmokeEffect();
2480 if (mKey.buttonCrouch() || !setCancelCrouch()) {
2482 }
2483 }
2484 }
2485}
2486
2487void dAcPy_c::CrouchActionWater() {
2488 if (mKey.triggerJump()) {
2489 if (!isNowBgCross(BGC_WATER_SUBMERGED)) {
2490 setCrouchJump();
2491 onStatus(STATUS_AA);
2492 } else {
2493 if (!checkStandUpRoofOnLift()) {
2494 changeState(StateID_Swim, SWIM_ARG_INITIAL);
2495 setWaterGroundJump();
2496 }
2497 }
2498 } else {
2499 if (!isNowBgCross(BGC_FOOT)) {
2500 changeState(StateID_Swim, SWIM_ARG_INITIAL);
2501 } else {
2502 if (!mKey.buttonCrouch() && setCancelCrouch()) {
2503 changeState(StateID_Swim, SWIM_ARG_INITIAL);
2504 }
2505 }
2506 }
2507}
2508
2509void dAcPy_c::executeState_Crouch() {
2510 gravitySet();
2511 maxFallSpeedSet();
2512 if (isNowBgCross(BGC_FOOT)) {
2513 mMaxSpeedF = 0.0f;
2515 } else {
2516 simpleMoveSpeedSet();
2518 }
2519 powerSet();
2520 turnAngle();
2521 m_2e8.chase(0, 0x200);
2522 mAngle.y += m_2e8;
2523 typedef void (dAcPy_c::*ActionProc)();
2524 static ActionProc l_CrouchActionProc[] = {
2525 &dAcPy_c::CrouchActionGround,
2526 &dAcPy_c::CrouchActionWater
2527 };
2528 (this->*l_CrouchActionProc[mSubstate])();
2529 int anmID = mPyMdlMng.getAnm();
2530 if (anmID == PLAYER_ANIM_STOOP_START || anmID == PLAYER_ANIM_S_JUMPED) {
2531 if (mPyMdlMng.isAnmStop()) {
2532 mPyMdlMng.setAnm(PLAYER_ANIM_STOOP);
2533 }
2534 }
2535}
2536
2537bool dAcPy_c::setCancelCrouch() {
2538 mAngle.y = getMukiAngle(mDirection);
2539 return daPlBase_c::setCancelCrouch();
2540}
2541
2542dAcPy_c *dAcPy_c::getCarryPlayer() {
2543 dActor_c *actor = (dActor_c *) fManager_c::searchBaseByID(mCarryActorID);
2544 if (actor != nullptr && actor->mKind == STAGE_ACTOR_PLAYER) {
2545 return (dAcPy_c *) actor;
2546 }
2547 return nullptr;
2548}
2549
2550dActor_c *dAcPy_c::getCarryPropelBlock() {
2551 dActor_c *actor = (dActor_c *) fManager_c::searchBaseByID(mCarryActorID);
2552 if (actor != nullptr && actor->mProfName == fProfile::AC_PROP_BLOCK) {
2553 return actor;
2554 }
2555 return nullptr;
2556}
2557
2558dActor_c *dAcPy_c::getCarryPropelActor() {
2559 dActor_c *actor = (dActor_c *) fManager_c::searchBaseByID(mCarryActorID);
2560 if (actor != nullptr) {
2561 if (actor->mKind == STAGE_ACTOR_PLAYER) {
2562 dAcPy_c *player = (dAcPy_c *) actor;
2563 if (player->mPowerup == POWERUP_PROPELLER_SHROOM) {
2564 return actor;
2565 }
2566 } else if (actor->mProfName == fProfile::AC_PROP_BLOCK) {
2567 return actor;
2568 }
2569 }
2570 return nullptr;
2571}
2572
2573dActor_c *dAcPy_c::getCarryHardBlock() {
2574 dActor_c *actor = (dActor_c *) fManager_c::searchBaseByID(mCarryActorID);
2575 if (actor != nullptr && (
2576 actor->mProfName == fProfile::AC_LIGHT_BLOCK ||
2577 actor->mProfName == fProfile::AC_PROP_BLOCK
2578 )) {
2579 return actor;
2580 }
2581 return nullptr;
2582}
2583
2584bool dAcPy_c::isLiftUp() {
2585 if (isCarry() && m_1308 == 0) {
2586 return true;
2587 }
2588 return false;
2589}
2590
2591bool dAcPy_c::isCarryMamePlayer() {
2592 dAcPy_c *player = getCarryPlayer();
2593 if (player != nullptr && player->mPowerup == POWERUP_MINI_MUSHROOM) {
2594 return true;
2595 }
2596 return false;
2597}
2598
2599bool dAcPy_c::isLiftUpExceptMame() {
2600 if (isLiftUp() && !isCarryMamePlayer()) {
2601 return true;
2602 }
2603 return false;
2604}
2605
2606float dAcPy_c::getLiftUpOffset() {
2607 return m_1304 * sGlobalData_c<dAcPy_c>::mData.mPos[getTallType(-1)].y;
2608}
2609
2610mVec3_c dAcPy_c::getCarryPos() {
2611 mVec3_c jnt1, jnt2;
2612 mPyMdlMng.mpMdl->getJointPos(&jnt1, 11);
2613 mPyMdlMng.mpMdl->getJointPos(&jnt2, 14);
2614 if (isCarry()) {
2615 mVec3_c res = (jnt1 + jnt2) / 2.0f;
2616 res.x = dScStage_c::getLoopPosX(res.x);
2617 if (mPyMdlMng.getFlags2() & 4) {
2618 res.y = mPos.y + getLiftUpOffset();
2619 }
2620 return res;
2621 } else {
2622 jnt2.x = dScStage_c::getLoopPosX(jnt2.x);
2623 return jnt2;
2624 }
2625}
2626
2627mVec3_c dAcPy_c::getLiftUpPos() {
2628 mMtx_c mtx;
2629 getModel()->getJointMtx(&mtx, 11);
2630 mtx.concat(mMtx_c::createTrans(5.0f, 0.0f, 0.0f));
2631 mVec3_c tmp;
2632 mtx.multVecZero(tmp);
2633
2634 getModel()->getJointMtx(&mtx, 14);
2635 mtx.concat(mMtx_c::createTrans(5.0f, 0.0f, 0.0f));
2636 mVec3_c tmp2;
2637 mtx.multVecZero(tmp2);
2638
2639 mVec3_c res = (tmp + tmp2) / 2.0f;
2640 res.x = dScStage_c::getLoopPosX(res.x);
2641 if (mPyMdlMng.getFlags2() & 4) {
2642 res.y = mPos.y + getLiftUpOffset();
2643 if (res.y < mPos.y + 2.0f) {
2644 res.y = mPos.y + 2.0f;
2645 }
2646 }
2647 return res;
2648}
2649
2650void dAcPy_c::clearSpinLiftUpReserve() {
2651 m_12fc = BASE_ID_NULL;
2652 m_1300 = 256.0f;
2653}
2654
2655void dAcPy_c::checkSpinLiftUpReserve(dCc_c *cc) {
2656 daPlBase_c *actor = (daPlBase_c *) cc->getOwner();
2657 if (
2658 actor == nullptr ||
2659 !actor->isSpinLiftUpEnable() ||
2660 !spinLiftUp(actor, false)
2661 ) {
2662 return;
2663 }
2664 float f = std::fabs(mPos.x - cc->getCenterPosX());
2665 if (m_1300 > f) {
2666 m_12fc = actor->mUniqueID;
2667 m_1300 = f;
2668 }
2669}
2670
2671void dAcPy_c::setSpinLiftUpReserve() {
2672 if (
2673 !isStatus(STATUS_7A) &&
2674 !isDemo() &&
2675 !isCarry() &&
2679 ) {
2680 dActor_c *actor = (dActor_c *) fManager_c::searchBaseByID(m_12fc);
2681 if (actor != nullptr && actor->isSpinLiftUpEnable()) {
2682 mCarryActorID = actor->mUniqueID;
2683 m_1308 = 0;
2684 mPyMdlMng.mpMdl->m_17c |= 4;
2685 if (actor->mKind == STAGE_ACTOR_PLAYER) {
2686 dAcPy_c *player = (dAcPy_c *) actor;
2687 mPyMdlMng.mpMdl->mpSpinLiftParentMdl = player->getModel();
2688 }
2690 dQuake_c::m_instance->shockMotor(mPlayerNo, dQuake_c::TYPE_7, 0, false);
2691 actor->setSpinLiftUpActor(this);
2692 }
2693 clearSpinLiftUpReserve();
2694 }
2695}
2696
2697void dAcPy_c::checkSpinLiftUpRoofHeight() {
2698 mVec3_c pos(mPos.x, mPos.y + 4.0f, mPos.z);
2699 float _unused = mWallBcData.mOffset;
2700 float height;
2701 float f = 0.0f;
2702 if (dBc_c::checkTenjou(&pos, &height, mLayer, 1) && f > height) {
2703 f = height;
2704 }
2705 m_12f8 = f;
2706}
2707
2708bool dAcPy_c::spinLiftUp(dActor_c *actor, bool b) {
2709 if (actor == nullptr || isCarry() || !mKey.buttonCarry()) {
2710 return false;
2711 }
2712 if (!b) {
2713 return true;
2714 }
2715 if (isStatus(STATUS_92)) {
2716 mCarryActorID = actor->mUniqueID;
2717 m_1308 = 1;
2718 mPyMdlMng.mpMdl->m_17c |= 2;
2719 mPyMdlMng.mpMdl->setBodyAnm(PLAYER_ANIM_RCARRY_WAIT, 1.0f, 0.0f, 0.0f);
2720 startPlayerVoice(VOICE_MOTIAGE, 0);
2721 return true;
2722 }
2723 return false;
2724}
2725
2726bool dAcPy_c::cancelCarry(dActor_c *carriedActor) {
2727 dActor_c *actor = (dActor_c *) fManager_c::searchBaseByID(mCarryActorID);
2728 if (actor == carriedActor || carriedActor == nullptr) {
2729 mPyMdlMng.mpMdl->m_17c &= ~0x6;
2730 mPyMdlMng.mpMdl->releaseBodyAnm(0.0f);
2731 mPyMdlMng.mpMdl->mpSpinLiftParentMdl = nullptr;
2732 mCarryActorID = BASE_ID_NULL;
2733 return true;
2734 }
2735 return false;
2736}
2737
2738void dAcPy_c::releaseCarryActor() {
2739 if (!isCarry()) {
2740 return;
2741 }
2742 dActor_c *actor = (dActor_c *) fManager_c::searchBaseByID(mCarryActorID);
2743 if (actor != nullptr) {
2744 if (actor->mKind == STAGE_ACTOR_PLAYER) {
2745 dAcPy_c *player = (dAcPy_c *) actor;
2746 player->setCarryOffFall(this);
2747 } else {
2748 actor->setCarryFall(this, 20);
2749 actor->mCarryingFlags |= CARRY_RELEASE;
2750 actor->mThrowDirection = mDirection;
2751 }
2752 }
2753 cancelCarry(actor);
2754}
2755
2756void dAcPy_c::setCarryOffFall(const dAcPy_c *carrier) {
2757 m_d8c = mPos.y;
2758 mDirection = carrier->mDirection;
2759 mSpeedF = sc_DirSpeed[mDirection];
2760 mPos.x += sc_DirSpeed[mDirection] * 5.0f;
2761
2762 *(const dAcPy_c **) &carrier = nullptr; // [nice fake match]
2763
2764 changeState(StateID_Fall, false);
2766}
2767
2768bool dAcPy_c::checkEnableThrow() {
2769 if (!isCarry()) {
2770 return false;
2771 }
2772 dActor_c *actor = (dActor_c *) fManager_c::searchBaseByID(mCarryActorID);
2773 if (actor == nullptr) {
2774 cancelCarry(nullptr);
2775 return false;
2776 }
2777 return !mKey.buttonCarry();
2778}
2779
2780bool dAcPy_c::checkCarryThrow() {
2781 if (checkEnableThrow()) {
2782 if (isState(StateID_Propel)) {
2783 changeState(StateID_PropelThrow, 0);
2784 return true;
2785 } else {
2786 changeState(StateID_Throw, 0);
2787 return true;
2788 }
2789 }
2790 return false;
2791}
2792
2793void dAcPy_c::initializeThrowCommonBase() {
2794 startPlayerVoice(VOICE_NAGERU, 0);
2795 if (isNowBgCross(BGC_WATER_SHALLOW)) {
2796 mPyMdlMng.setAnm(PLAYER_ANIM_SWIM_THROW);
2797 } else {
2798 dActor_c *actor = (dActor_c *) fManager_c::searchBaseByID(mCarryActorID);
2799 if (actor->mKind == STAGE_ACTOR_PLAYER) {
2800 mPyMdlMng.setAnm(PLAYER_ANIM_CARRY_P_THROW, 0.0f, 0.0f);
2801 } else {
2802 mPyMdlMng.setAnm(PLAYER_ANIM_CARRY_THROW, 0.0f, 0.0f);
2803 }
2804 }
2805 mAngle.y = getMukiAngle(mDirection);
2807}
2808
2809void dAcPy_c::initializeThrowCommon() {
2810 initializeThrowCommonBase();
2811 onStatus(STATUS_AA);
2812 onStatus(STATUS_97);
2813}
2814
2815void dAcPy_c::finalizeThrowCommonBase() {
2817}
2818
2819void dAcPy_c::finalizeThrowCommon() {
2820 finalizeThrowCommonBase();
2821 if (mSubstate == 0) {
2822 releaseCarryActor();
2823 }
2824 offStatus(STATUS_AA);
2825 offStatus(STATUS_97);
2826 offStatus(STATUS_92);
2828}
2829
2830void dAcPy_c::setThrowActor() {
2831 if (!isCarry()) {
2832 return;
2833 }
2834 dActor_c *actor = (dActor_c *) fManager_c::searchBaseByID(mCarryActorID);
2835 if (actor != nullptr) {
2836 if (actor->mKind == STAGE_ACTOR_PLAYER) {
2837 dAcPy_c *player = (dAcPy_c *) actor;
2838 player->changeState(StateID_RollSlip, 0);
2839
2840 player->mSpeed.y = sGlobalData_c<dAcPy_c>::mData.mThrowSpeed1;
2841 float speed = getDirSpeed();
2842 speed *= sGlobalData_c<dAcPy_c>::mData.mThrowSpeed2;
2843 if (getDirSpeed() * mSpeedF >= 0.0f) {
2844 speed += mSpeedF * 0.35f;
2845 if (speed > sGlobalData_c<dAcPy_c>::mData.mThrowSpeedMax) {
2846 speed = sGlobalData_c<dAcPy_c>::mData.mThrowSpeedMax;
2847 }
2848 }
2849 player->mSpeedF = speed;
2850 player->setNoHitPlayer(this, 10);
2851
2852 mVec3_c pos = player->mPos;
2853
2854 float spd = speed + sc_DirSpeed[mDirection] * 5.0f;
2855 if (spd < -8.0f) {
2856 spd = -8.0f;
2857 } else if (spd > 8.0f) {
2858 spd = 8.0f;
2859 }
2860
2861 mVec3_c p(mPos.x, pos.y, pos.z);
2862 pos.x += spd;
2863
2864 float thing = sc_DirSpeed[mDirection] * std::fabs(getWallBgPointData()->mOffset / 4096.0f);
2865 mVec3_c playerPos(pos.x + thing, pos.y, pos.z);
2866 float hitX;
2867 if (dBc_c::checkWall(&p, &playerPos, &hitX, mLayer, 1, nullptr)) {
2868 bool stop = false;
2869 if (mPowerup == POWERUP_NONE) {
2870 mVec3_c revPos(hitX, pos.y + 16.0f, pos.z);
2871 float hitY;
2872 if (dBc_c::checkGround(&revPos, &hitY, mLayer, 1, -1)) {
2873 if (hitY <= mPos.y + 16.0f) {
2874 pos.y = mPos.y + 16.0f;
2875 stop = true;
2876 }
2877 }
2878 }
2879 if (!stop) {
2880 player->mSpeedF = 0.0f;
2881 pos.x = hitX - thing;
2882 }
2883 }
2884 p.set(pos.x, pos.y + 1.0f, pos.z);
2885 if (dBc_c::checkTenjou(&p, &hitX, mLayer, 1)) {
2886 float offsX = std::fabs(getHeadBgPointData()->mOffset / 4096.0f);
2887 // float tmp = hitX - offsX;
2888 if (pos.y > hitX - offsX) {
2889 pos.y = hitX - offsX;
2890 player->mSpeed.y = 0.0f;
2891 }
2892 }
2893 player->mPos = pos;
2894 player->mLastPos = player->mPos;
2896 } else {
2898 actor->mThrowDirection = mDirection;
2899 }
2900 }
2901 cancelCarry(actor);
2902}
2903
2904void dAcPy_c::executeThrowCommon() {
2905 if (isNowBgCross(BGC_FOOT)) {
2907 } else {
2909 }
2910 switch ((ThrowSubstate_e) mSubstate) {
2911 case THROW_ACTION_0:
2912 if (mPyMdlMng.mpMdl->mCurrAnmID == PLAYER_ANIM_SWIM_THROW) {
2913 if (mPyMdlMng.mpMdl->mAnm.checkFrame(12.0f)) {
2914 mSubstate = THROW_ACTION_2;
2915 setThrowActor();
2916 }
2917 } else {
2918 if (isNowBgCross(BGC_FOOT) && mKey.triggerJump()) {
2919 fn_80145fd0(1);
2920 setJumpSpeed();
2922 }
2923 if (mPyMdlMng.mpMdl->mAnm.checkFrame(5.0f)) {
2924 mSubstate = THROW_ACTION_1;
2925 setThrowActor();
2926 onStatus(STATUS_92);
2927 }
2928 }
2929 break;
2930 case THROW_ACTION_1:
2931 if (isNowBgCross(BGC_FOOT) && checkJumpTrigger()) {
2932 break;
2933 }
2934 if (mPyMdlMng.mpMdl->mAnm.getFrame() >= 20.0f) {
2935 if (isNowBgCross(BGC_FOOT)) {
2936 if (mSpeedF) {
2937 changeState(StateID_Walk, BLEND_DEFAULT);
2938 break;
2939 }
2940 } else {
2941 changeState(StateID_Fall, false);
2942 }
2943 }
2944 if (mPyMdlMng.isAnmStop()) {
2945 changeState(StateID_Walk, BLEND_DEFAULT);
2946 }
2947 break;
2948 case THROW_ACTION_2:
2949 if (mPyMdlMng.isAnmStop()) {
2950 changeState(StateID_Swim, SWIM_ARG_INITIAL);
2951 }
2952 break;
2953 }
2954}
2955
2956void dAcPy_c::initializeState_Throw() {
2957 initializeThrowCommon();
2958}
2959
2960void dAcPy_c::finalizeState_Throw() {
2961 finalizeThrowCommon();
2962}
2963
2964void dAcPy_c::executeState_Throw() {
2965 if (isNowBgCross(BGC_WATER_SHALLOW)) {
2966 setWaterMoveSpeed();
2967 } else {
2968 gravitySet();
2969 maxFallSpeedSet();
2970 simpleMoveSpeedSet();
2971 powerSet();
2972 }
2973 executeThrowCommon();
2974}
2975
2976void dAcPy_c::initializeState_PropelThrow() {
2977 initializeThrowCommon();
2978}
2979
2980void dAcPy_c::finalizeState_PropelThrow() {
2981 finalizeThrowCommon();
2982}
2983
2984void dAcPy_c::executeState_PropelThrow() {
2985 if (!isNowBgCross(BGC_FOOT) && mKey.buttonJump()) {
2986 mAccelY = getSomeData(7);
2987 mMaxFallSpeed = getSomeData(5);
2988 } else {
2989 mAccelY = getGravityData()[0];
2990 mMaxFallSpeed = sc_MaxFallSpeed;
2991 }
2992 mAccelF = getSpeedData()->mPowerChangeNormal.mSlowAccel;
2993 mMaxSpeedF = 0.0f;
2994 executeThrowCommon();
2995}
2996
2998 if (
2999 isStatus(STATUS_7A) ||
3000 isDemo() ||
3001 isCarry() ||
3002 mRideActorID != BASE_ID_NULL ||
3003 isStatus(STATUS_93) ||
3007 ) {
3008 return false;
3009 }
3010 return true;
3011}
3012
3014 if (mRideActorID != BASE_ID_NULL) {
3015 return;
3016 }
3017 mRideActorID = carryingActor->mUniqueID;
3018 if (!isState(StateID_CarryPlayer)) {
3020 }
3021
3022 dQuake_c::getInstance()->shockMotor(getPlrNo(), dQuake_c::TYPE_7, 0, false);
3023}
3024
3025void dAcPy_c::initializeState_LiftUp() {
3026 offStatus(STATUS_8A);
3027 onStatus(STATUS_97);
3028 onStatus(STATUS_46);
3029 m_1304 = 0.0f;
3030 dAcPy_c *carryPlayer = getCarryPlayer();
3031 setVirusStar(carryPlayer);
3032 if (carryPlayer != nullptr) {
3033 startPlayerVoice(VOICE_MOTIAGE_PLAYER, 0);
3034 } else {
3035 startPlayerVoice(VOICE_MOTIAGE, 0);
3036 }
3037 startSound(SE_PLY_OTHER_ON, false);
3038 mPyMdlMng.setAnm(PLAYER_ANIM_CARRY_P_START, 0.0f, 0.0f);
3039 mSpeedF = 0.0f;
3040 mSpeed.y = 0.3f;
3041 m_1048 = 10000;
3042 m_130c = 0;
3043}
3044
3045void dAcPy_c::finalizeState_LiftUp() {
3046 offStatus(STATUS_97);
3047 offStatus(STATUS_46);
3048 m_1304 = 1.0f;
3049 mAngle.y = getMukiAngle(mDirection);
3050}
3051
3052void dAcPy_c::executeState_LiftUp() {
3053 m_130c++;
3054 float f = m_130c / 30.0f;
3055 if (f > 1.0f) {
3056 f = 1.0f;
3057 }
3058 m_1304 = f;
3059 sLib::chase(&m_1048, 0, 250);
3060 if (m_1048 != 0) {
3061 mAngle.y += m_1048;
3062 } else {
3063 turnAngle();
3064 }
3065 setCcAtSpin();
3066 gravitySet();
3067 maxFallSpeedSet();
3068 if (m_130c <= 18) {
3069 mMaxSpeedF = 0.0f;
3070 powerSet();
3071 } else {
3072 simpleMoveSpeedSet();
3073 powerSet();
3074 if (checkCarryThrow()) {
3075 int dir;
3076 if (mKey.buttonWalk(&dir)) {
3077 mDirection = dir;
3078 mAngle.y = getMukiAngle(mDirection);
3079 }
3080 return;
3081 } else if (checkJumpTrigger()) {
3082 sBcPointData d1 = mWallBcData;
3083 sBcPointData d2 = mHeadBcData;
3084 fn_80143060(d1, d2, true);
3085 if (!fn_80143220(d1, d2)) {
3086 return;
3087 }
3088 onStatus(STATUS_48);
3089 return;
3090 }
3091 }
3092 if (mPyMdlMng.isAnmStop()) {
3093 changeState(StateID_Walk, BLEND_DEFAULT);
3094 }
3095}
3096
3097void dAcPy_c::calcUzuSwimSpeed(float f1, float f2, float *fOut) {
3099 return;
3100 }
3101
3102 *fOut *= data_802f5a48[15];
3103 if (*fOut * f1 >= 0.0f && std::fabs(f2) > data_802f5a48[17]) {
3104 *fOut = 0.0f;
3105 return;
3106 }
3107
3108 if (*fOut * f1 < 0.0f) {
3109 if (f2 * f1 > 0.0f) {
3110 if (std::fabs(f2) > 0.5f) {
3111 return;
3112 }
3113 } else {
3114 *fOut *= data_802f5a48[16];
3115 }
3116 float lim = data_802f5a48[11] - 0.01f;
3117 if (std::fabs(*fOut) > lim) {
3118 if (*fOut < 0.0f) {
3119 *fOut = -lim;
3120 } else {
3121 *fOut = lim;
3122 }
3123 }
3124 }
3125}
3126
3127void dAcPy_c::setUzuSpeedY(float f) {
3128 if (std::fabs(mSpeed.y) < 2.0f) {
3129 if (f > 0.0f) {
3130 if (isNowBgCross(BGC_FOOT)) {
3131 setUzuSwimAction();
3132 }
3133 if (isNowBgCross(BGC_HEAD)) {
3134 return;
3135 }
3136 }
3137 calcUzuSwimSpeed(mUzuSwimSpeed.y, mSpeed.y, &f);
3138 if (f > 0.0f) {
3139 m_b88 = 20;
3140 }
3141 if (f * mUzuSwimSpeed.y < 0.0f) {
3143 }
3144 mSpeed.y += f;
3145 }
3146}
3147
3148void dAcPy_c::setUzuSpeedF(float f) {
3149 if (std::fabs(mSpeedF) < 2.0f) {
3150 calcUzuSwimSpeed(mUzuSwimSpeed.x, mSpeedF, &f);
3151 if (f * mUzuSwimSpeed.x < 0.0f) {
3153 }
3154 mSpeedF += f;
3155 }
3156}
3157
3158bool dAcPy_c::setUzuSwimAction() {
3159 if (isNowBgCross(BGC_WATER_SHALLOW) && isState(StateID_Swim) && mSubstate == 1) {
3160 setSwimAction_Swim(BLEND_DEFAULT);
3161 return true;
3162 }
3163 return false;
3164}
3165
3166bool dAcPy_c::setSwimAction() {
3167 if (isStatus(STATUS_45) || isStatus(STATUS_AA) || isStatus(STATUS_SWIM)) {
3168 return false;
3169 }
3170 if (isNowBgCross(BGC_WATER_SHALLOW)) {
3171 if (isOldBgCross(BGC_WATER_SHALLOW)) {
3172 changeState(StateID_Swim, SWIM_ARG_INITIAL);
3174 changeState(StateID_Swim, SWIM_ARG_FIREBALL);
3175 } else {
3176 changeState(StateID_Swim, SWIM_ARG_ENTERING);
3177 }
3178 return true;
3179 }
3180 return false;
3181}
3182
3183void dAcPy_c::setWaterInEffect() {
3184 dScStage_c *stage = dScStage_c::m_instance;
3185 bool bigSplash = false;
3186
3187 if (isNowBgCross(BGC_WATER_BUBBLE)) {
3188 startSound(SE_PLY_SPLASH_GEL, false);
3189 mAng3_c efAng(0, 0, -mAirWaterHitAngle);
3190 dEf::createPlayerEffect(mPlayerNo, "Wm_mr_wfloatsplash", 0, &mAirWaterHitPos, &efAng, nullptr);
3191 return;
3192 }
3193 if (
3194 stage->mCurrWorld == WORLD_4 &&
3195 stage->mCurrCourse == STAGE_CASTLE &&
3196 stage->mCurrFile == 1
3197 ) {
3198 bigSplash = true;
3199 }
3200 mVec3_c efPos(mPos.x, mWaterHeight, mPos.z);
3201 if (bigSplash || mWaterDepth == 3) {
3202 float f = 1.0f;
3203 u32 i;
3204 if (mPowerup == POWERUP_MINI_MUSHROOM) {
3205 startSound(SE_PLY_SPLASH_MAME, false);
3206 i = 3;
3207 } else {
3208 startSound(SE_PLY_SPLASH, false);
3209 i = 2;
3210 if (mPowerup == POWERUP_NONE) {
3211 f = 0.8f;
3212 }
3213 }
3214 dPyEffectMng_c::mspInstance->fn_800d2de0(f, i, efPos, mLayer);
3215 dBg_c::m_bg_p->setWaterInWave(efPos.x, efPos.y, 1);
3216 } else {
3217 float f = 1.0f;
3218 if (mPowerup == POWERUP_MINI_MUSHROOM) {
3219 f = 0.6f;
3220 } else if (mPowerup == POWERUP_NONE) {
3221 f = 0.8f;
3222 }
3223 dPyEffectMng_c::mspInstance->fn_800d2de0(f, 4, efPos, mLayer);
3224 if (mPowerup == POWERUP_MINI_MUSHROOM) {
3225 startSound(SE_PLY_SPLASH_SHALLOW_MAME, false);
3226 } else {
3227 startSound(SE_PLY_SPLASH_SHALLOW, false);
3228 }
3229 dBg_c::m_bg_p->setWaterInWave(efPos.x, efPos.y, 0);
3230 }
3231}
3232
3233void dAcPy_c::setWaterOutEffect() {
3234 if (isOldBgCross(BGC_WATER_BUBBLE)) {
3235 startSound(SE_PLY_SPLASH_GEL_OUT, false);
3236 mAng3_c efAng(0, 0, -mAirWaterHitAngle);
3237 dEf::createPlayerEffect(mPlayerNo, "Wm_mr_wfloatsplash", 0, &mAirWaterHitPos, &efAng, nullptr);
3238 return;
3239 }
3240 mVec3_c efPos(mPos.x, mPrevWaterHeight, mPos.z);
3241
3242 if (mWaterDepth == 3) {
3243 float f = 1.0f;
3244 u32 i;
3245 if (mPowerup == POWERUP_MINI_MUSHROOM) {
3246 i = 1;
3247 } else {
3248 i = 0;
3249 if (mPowerup == POWERUP_NONE) {
3250 f = 0.8f;
3251 }
3252 }
3253 dPyEffectMng_c::mspInstance->fn_800d2de0(f, i, efPos, mLayer);
3254 dBg_c::m_bg_p->setWaterInWave(efPos.x, efPos.y, 3);
3255 startSound(SE_PLY_SPLASH_OUT, false);
3256 } else {
3257 float f = 1.0f;
3258 if (mPowerup == POWERUP_MINI_MUSHROOM) {
3259 f = 0.6f;
3260 } else if (mPowerup == POWERUP_NONE) {
3261 f = 0.8f;
3262 }
3263 dPyEffectMng_c::mspInstance->fn_800d2de0(f, 4, efPos, mLayer);
3264 startSound(SE_PLY_SPLASH_SHALLOW_OUT, false);
3265 dBg_c::m_bg_p->setWaterInWave(efPos.x, efPos.y, 2);
3266 }
3267}
3268
3269void dAcPy_c::setPaddleSwimEffect() {
3270 mVec3_c efPos;
3271 mPyMdlMng.mpMdl->getJointPos(&efPos, 11);
3272 dEf::createPlayerEffect(mPlayerNo, &mLevelEf9, "Wm_mr_swimpaddle", 0, &efPos, nullptr, nullptr);
3273 mPyMdlMng.mpMdl->getJointPos(&efPos, 14);
3274 dEf::createPlayerEffect(mPlayerNo, &mLevelEf10, "Wm_mr_swimpaddle", 0, &efPos, nullptr, nullptr);
3275}
3276
3277void dAcPy_c::resetPaddleSwimEffect() {
3278 mLevelEf9.fade();
3279 mLevelEf10.fade();
3280}
3281
3282void dAcPy_c::setWaterSurfaceSwimEffect() {
3283 if (getWaterCheckPosY() < mWaterHeight - 4.0f) {
3284 return;
3285 }
3286 mVec3_c efPos(mPos.x, mWaterHeight, mPos.z);
3287 mAng3_c efAng(0, 0, 0);
3288 if (mDirection == DIR_LR_L) {
3289 efAng.y = 0x8000;
3290 }
3291 static const float sc_waterFaceEffectScale[] = { 0.65f, 0.8f, 1.0f };
3292 float s = sc_waterFaceEffectScale[getTallType(-1)];
3293 mVec3_c scale(s, s, s);
3294 dEf::createPlayerEffect(mPlayerNo, &mLevelEf11, "Wm_mr_waterswim", 0, &efPos, nullptr, &scale);
3295 dEf::createPlayerEffect(mPlayerNo, &mLevelEf12, "Wm_en_cmnwater02", 0, &efPos, &efAng, &scale);
3296}
3297
3298void dAcPy_c::setFlutterKickEffect() {
3299 mVec3_c efPos;
3300 mPyMdlMng.mpMdl->getJointPos(&efPos, 4);
3301 dEf::createPlayerEffect(mPlayerNo, &mLevelEf9, "Wm_mr_flutterkick", 0, &efPos, nullptr, nullptr);
3302 mPyMdlMng.mpMdl->getJointPos(&efPos, 7);
3303 dEf::createPlayerEffect(mPlayerNo, &mLevelEf10, "Wm_mr_flutterkick", 0, &efPos, nullptr, nullptr);
3304}
3305
3306void dAcPy_c::initializeState_Swim() {
3308 onStatus(STATUS_AA);
3309 onStatus(STATUS_A8);
3310 onStatus(STATUS_92);
3312 SwimArg_e param = stateArg<SwimArg_e>();
3313 m_b84 = 0;
3314 m_b88 = 0;
3315 m_b80 = 0.0f;
3316 if (param == SWIM_ARG_ENTERING || param == SWIM_ARG_FIREBALL || param == SWIM_ARG_CLIFF_HANG) {
3317 m_b80 = 1;
3318 m_15b6 = 30;
3319 if (mSpeed.y < -1.5f) {
3320 mSpeed.y = -1.5f;
3321 }
3322 if (m_b98 != 0 && mSpeed.y < -0.5f) {
3323 mSpeed.y = -0.5f;
3324 }
3325 }
3326 if (param == SWIM_ARG_FIREBALL) {
3327 setInitSwimAction_FireBall();
3328 } else {
3329 dAcPy_c *carryPlayer = getCarryPlayer();
3330 if (carryPlayer != nullptr) {
3331 mVec3_c pos(mPos.x, mPos.y + 4.0f, mPos.z);
3332 float height;
3333 if (dBc_c::checkTenjou(&pos, &height, mLayer, mAmiLayer)) {
3334 if (mPos.y + getModelHeight() + getBgPointData_Powerup(mPowerup, 1)->mHead.mOffset / 4096.0f > height) {
3335 releaseCarryActor();
3336 }
3337 }
3338 }
3339 AnmBlend_e blendMode = BLEND_DEFAULT;
3340 if (param == SWIM_ARG_CLIFF_HANG) {
3341 blendMode = BLEND_NONE;
3342 }
3343 if (mPowerup == POWERUP_PENGUIN_SUIT) {
3344 if (!isCarry()) {
3345 setSwimAction_Penguin(blendMode);
3346 } else {
3347 setSwimAction_Swim(blendMode);
3348 }
3349 } else if (isNowBgCross(BGC_FOOT)) {
3350 setSwimAction_Walk(blendMode);
3351 } else {
3352 setSwimAction_Swim(blendMode);
3353 }
3354 }
3355 if (isNowBgCross(BGC_WATER_SHALLOW) && isOldBgCross(BGC_WATER_SHALLOW) == 0) {
3356 setWaterInEffect();
3357 }
3358 if (isItemKinopio()) {
3359 setControlDemoKinopioSwim();
3360 }
3361}
3362
3363bool dAcPy_c::setWaterSurfaceJump() {
3364 if (mKey.triggerJump()) {
3365 if (mSubstate == SWIM_ACTION_2) {
3366 if (mKey.buttonUp()) {
3367 m_b88 = 20;
3368 }
3369 } else {
3370 m_b88 = 20;
3371 }
3372 }
3373 if (!isNowBgCross(BGC_WATER_SHALLOW)) {
3374 if (!isNowBgCross(BGC_WATER_TOUCH) && (!isCarry() || mPowerup != POWERUP_MINI_MUSHROOM)) {
3375 if (mSubstate == SWIM_ACTION_3 && m_b89 == 0) {
3376 createFireBall(0);
3377 }
3378 changeState(StateID_Fall, false);
3379 return true;
3380 }
3381 if (m_b88 != 0) {
3382 if (mSubstate == SWIM_ACTION_3 && m_b89 == 0) {
3383 createFireBall(0);
3384 }
3385 float h = 3.5f;
3386 if (isMameAction()) {
3387 h = 2.625f;
3388 }
3389 jmpInf_c jmpInf(h, 1, BLEND_DEFAULT);
3390 if (mSubstate == SWIM_ACTION_2) {
3391 jmpInf.mBlendMode = BLEND_NONE;
3392 }
3393 changeState(StateID_Jump, &jmpInf);
3394 mKey.onStatus(dAcPyKey_c::STATUS_FORCE_JUMP);
3395 onStatus(STATUS_A8);
3396 return true;
3397 }
3398 }
3399 return false;
3400}
3401
3402void dAcPy_c::setSwimAction_Swim(AnmBlend_e blendMode) {
3403 m_b89 = 0;
3404 mSubstate = SWIM_ACTION_0;
3405 m_b84 = 4;
3406 m_b88 = 0;
3407 if (blendMode == BLEND_DEFAULT) {
3408 mPyMdlMng.setAnm(PLAYER_ANIM_SWIM_WAIT);
3409 } else {
3410 mPyMdlMng.setAnm(PLAYER_ANIM_SWIM_WAIT, 0.0f, 0.0f);
3411 }
3412 mAngle.x = 0;
3413}
3414
3415void dAcPy_c::SwimAction_Swim() {
3416 if (mPowerup == POWERUP_PENGUIN_SUIT && !isCarry()) {
3417 setSwimAction_Penguin(BLEND_DEFAULT);
3418 return;
3419 }
3420 setWaterMoveSpeed();
3421 turnAngle();
3422 if (checkEnableThrow()) {
3423 startPlayerVoice(VOICE_NAGERU, 0);
3424 setThrowActor();
3425 return;
3426 }
3427 if (setWaterSurfaceJump()) {
3428 return;
3429 }
3430 if (isNowBgCross(BGC_FOOT) && mPowerup != POWERUP_PENGUIN_SUIT) {
3431 setSwimAction_Walk(BLEND_DEFAULT);
3432 return;
3433 }
3434 setWaterSurfaceSwimEffect();
3435 if (isNowBgCross(BGC_WATER_SHALLOW)) {
3436 if (mKey.triggerJump()) {
3437 startSound(SE_PLY_SWIM, 0);
3438 mSpeed.y += 1.0f;
3439 if (mSpeed.y > 1.8f) {
3440 mSpeed.y = 1.8f;
3441 }
3442 }
3443 if (isNowBgCross(BGC_NON_BREAK_BLOCK_HIT)) {
3444 mSpeed.y = -1.875f;
3445 }
3446 }
3447 switch (m_b89) {
3448 case 0:
3449 if (mKey.triggerJump()) {
3450 m_b89 = 1;
3451 mPyMdlMng.setAnm(PLAYER_ANIM_PADDLE_1);
3453 } else if (mKey.buttonJump()) {
3454 m_b89 = 3;
3455 mPyMdlMng.setAnm(PLAYER_ANIM_SWIM);
3456 }
3457 break;
3458 case 1:
3459 setPaddleSwimEffect();
3460 if (mKey.triggerJump() && mPyMdlMng.mpMdl->mAnm.getFrame() > 9.0f) {
3461 mPyMdlMng.mpMdl->setFrame(0.0f);
3462 resetPaddleSwimEffect();
3464 }
3465 if (mPyMdlMng.isAnmStop()) {
3466 if (mKey.buttonJump()) {
3467 m_b89 = 3;
3468 mPyMdlMng.setAnm(PLAYER_ANIM_SWIM);
3469 } else {
3470 m_b89 = 2;
3471 mPyMdlMng.setAnm(PLAYER_ANIM_PADDLE_2);
3472 }
3473 }
3474 break;
3475 case 3:
3476 mPyMdlMng.mpMdl->setRate(1.0f);
3477 if (mPyMdlMng.mpMdl->mAnm.checkFrame(1.0f) || mPyMdlMng.mpMdl->mAnm.checkFrame(9.0f)) {
3478 startSound(SE_PLY_SWIM_KICK, 0);
3479 }
3480 setFlutterKickEffect();
3481 if (!mKey.buttonJump()) {
3482 m_b89 = 2;
3483 mPyMdlMng.setAnm(PLAYER_ANIM_PADDLE_2);
3484 }
3485 break;
3486 case 2:
3487 if (mPyMdlMng.isAnmStop()) {
3488 m_b89 = 0;
3489 mPyMdlMng.setAnm(PLAYER_ANIM_SWIM_WAIT);
3490 }
3491 break;
3492 case 4:
3493 if (!isCarry()) {
3494 m_b89 = 0;
3495 mPyMdlMng.setAnm(PLAYER_ANIM_SWIM_WAIT);
3496 }
3497 break;
3498 }
3499}
3500
3501void dAcPy_c::setSeaLandSmokeEffect() {
3502 static const char *sc_hipAttackEffectID[] = {
3503 "Wm_mr_sealandsmk_ss",
3504 "Wm_mr_sealandsmk_s",
3505 "Wm_mr_sealandsmk",
3506 };
3507 dEf::createPlayerEffect_change(mPlayerNo, sc_hipAttackEffectID[getTallType(-1)], 0, &mPos, nullptr, nullptr);
3508}
3509
3510void dAcPy_c::setSwimActionWalkAnm() {
3511 if (!mSpeedF) {
3512 mPyMdlMng.setAnm(PLAYER_ANIM_SWIM_STANDING);
3513 return;
3514 }
3515 float f = 1.0f;
3516 if (mMaxSpeedF && mSpeedF * mMaxSpeedF < 0.0f) {
3517 f = std::fabs(mSpeedF) - sc_WaterWalkSpeed + 1.0f;
3518 if (f < 1.0f) {
3519 f = 1.0f;
3520 } else if (f > 2.0f) {
3521 f = 2.0f;
3522 }
3523 }
3524 mPyMdlMng.setAnm(PLAYER_ANIM_SWIM_WALK, f, 10.0f, 0.0f);
3525}
3526
3527void dAcPy_c::setSwimAction_Walk(AnmBlend_e blendMode) {
3528 if (!isOldBgCross(BGC_FOOT)) {
3529 setSeaLandSmokeEffect();
3530 }
3531 m_b89 = 0;
3532 mSubstate = SWIM_ACTION_1;
3533 if (blendMode == BLEND_DEFAULT) {
3534 setSwimActionWalkAnm();
3535 } else {
3536 mPyMdlMng.setAnm(PLAYER_ANIM_SWIM_STANDING);
3537 }
3538}
3539
3540void dAcPy_c::setWaterGroundJump() {
3541 mSpeed.y = sc_WaterJumpSpeed;
3542 setSwimAction_Swim(BLEND_DEFAULT);
3543 startSound(SE_PLY_SWIM, 0);
3544 m_b88 = 20;
3545}
3546
3547void dAcPy_c::SwimAction_Walk() {
3548 if (mPowerup == POWERUP_PENGUIN_SUIT) {
3549 setSwimAction_Penguin(BLEND_DEFAULT);
3550 return;
3551 }
3552 setWaterMoveSpeed();
3553 turnAngle();
3554 if (mKey.triggerJump()) {
3555 if (!setWaterSurfaceJump()) {
3556 setWaterGroundJump();
3557 }
3558 } else {
3559 if (!isNowBgCross(BGC_FOOT)) {
3560 setSwimAction_Swim(BLEND_DEFAULT);
3561 } else {
3562 if (!checkCrouch()) {
3563 setSwimActionWalkAnm();
3564 }
3565 }
3566 }
3567}
3568
3569s16 dAcPy_c::getPenguinSwinAngleX() {
3570 float f = std::fabs(mUzuSwimSpeed.x);
3571 if (f < 0.1f) {
3572 f = 0.1f;
3573 }
3574 float cos = mUzuSwimSpeed.y;
3575 if (mKey.buttonUp()) {
3576 if (cos < 0.0f) {
3577 cos = 0.0f;
3578 }
3579 }
3580 if (mKey.buttonDown()) {
3581 if (cos < 0.0f) {
3582 cos = 0.0f;
3583 }
3584 }
3585 // [cos gets discarded here?]
3586 return -(cM::atan2s(f, mUzuSwimSpeed.y) - 0x4000);
3587}
3588
3589void dAcPy_c::setSwimAction_Penguin(AnmBlend_e blendMode) {
3590 mSubstate = SWIM_ACTION_2;
3591 m_b88 = 0;
3592 if (m_b80 != 0 || getOldState() == StateID_HipAttack) {
3593 m_b80 = 0;
3594 if (blendMode == BLEND_DEFAULT) {
3595 mPyMdlMng.setAnm(PLAYER_ANIM_P_SWIM);
3596 } else {
3597 mPyMdlMng.setAnm(PLAYER_ANIM_P_SWIM, 0.0f, 0.0f);
3598 }
3599 mSubstateTimer = 15;
3600 m_b89 = 0;
3601 return;
3602 }
3603 if (mSpeedF > 0.1f || mSpeed.y > 0.1f) {
3604 m_b8c = 1.0f;
3605 } else {
3606 m_b8c = 0.0f;
3607 }
3608 m_b89 = 1;
3609 if (blendMode == BLEND_DEFAULT) {
3610 mPyMdlMng.setAnm(PLAYER_ANIM_P_SWIM);
3611 } else {
3612 mPyMdlMng.setAnm(PLAYER_ANIM_P_SWIM, 0.0f, 0.0f);
3613 }
3614}
3615
3616void dAcPy_c::setPenWaterMoveSpeed(int i) {
3617 if (m_b98 != 0 && mKey.triggerDown()) {
3618 m_b98 = 0;
3619 }
3620 bool noUpDown = false;
3621 if (mKey.buttonUp() || m_b98 == 0 && mKey.buttonDown()) {
3622 noUpDown = true;
3623 }
3624 bool b = 0;
3625 if (mKey.buttonWalk(nullptr)) {
3626 b = 1;
3627 }
3628 s16 ang = 0;
3629 if (noUpDown) {
3630 ang = 0x3e00;
3631 if (b) {
3632 ang = 0x2000;
3633 }
3634 if (mKey.buttonDown()) {
3635 ang = -ang;
3636 }
3637 }
3638 mAngle.y.chase(getMukiAngle(mDirection), 0x400);
3639 mAngle.x.chase(getPenguinSwinAngleX(), 0x300);
3640 float f3 = getData(9);
3641 float f2 = 0.0f;
3642 if (i != 0) {
3643 if (noUpDown) {
3644 f2 = getData(6);
3646 f3 = getData(18);
3647 } else {
3648 f3 = getData(12);
3649 }
3650 }
3651 } else {
3652 if (noUpDown) {
3653 f2 = getData(5);
3654 f3 = getData(11);
3655 } else if (b) {
3656 f3 = getData(14);
3657 }
3658 float d = getData(5);
3659 if (std::fabs(mSpeed.y) >= d) {
3660 f3 = getData(13);
3661 }
3662 }
3663 float target = mAng(ang).sin() * f2;
3664 mUzuSwimSpeed.y = target;
3665 float offs = mPos.y + getModelHeight() / 2.0f;
3666 if (mWaterHeight <= offs) {
3667 target = -1.5f;
3668 if (mSpeed.y > 0.0f) {
3669 f3 = std::fabs(-24.0f / 256.0f);
3670 } else {
3671 f3 = std::fabs(-7.0f / 256.0f);
3672 }
3673 } else {
3674 if (mSpeed.y < -getData(6)) {
3675 f3 = std::fabs(-24.0f / 256.0f);
3676 }
3677 }
3678 sLib::addCalc(&mSpeed.y, target, 0.5f, f3, 0.01f);
3679 mMaxFallSpeed = sc_MaxFallSpeed;
3680 mAccelY = 0.0f;
3681 if (i != 0) {
3682 f2 = getData(8);
3684 f3 = getData(18);
3685 } else {
3686 f3 = getData(12);
3687 }
3688 } else {
3689 if (b) {
3690 f2 = getData(7);
3691 f3 = getData(11);
3692 } else {
3693 f2 = 0.3f;
3694 if (std::fabs(mSpeedF) < 0.3f) {
3695 f3 = 0.005f;
3696 } else if (noUpDown) {
3697 f3 = getData(14);
3698 } else {
3699 f3 = getData(10);
3700 }
3701 }
3702 float d = getData(7);
3703 if (std::fabs(mSpeedF) >= d) {
3704 f3 = getData(13);
3705 }
3706 }
3707 f3 = sc_DirSpeed[mDirection] * f3;
3708 mUzuSwimSpeed.x = mAng(ang).cos() * f2 * sc_DirSpeed[mDirection];
3709 float f4 = 0.0f;
3710 if (dWaterEntryMng_c::m_instance->m_8c0) {
3711 f4 = 8.25f;
3712 }
3713 float f5 = mUzuSwimSpeed.x + f4 * 0.3f;
3714 float f10 = f3 + f4 * 0.005f;
3715 if (mUzuSwimSpeed.x * f4 < 0.0f) {
3716 if (i != 0) {
3717 f5 = mUzuSwimSpeed.x + f4 * 0.1f;
3718 f10 = f3 + f4 * 0.0001f;
3719 } else if (b) {
3720 f5 = mUzuSwimSpeed.x + f4 * 0.13f;
3721 if (std::fabs(mSpeedF) < 1.0f) {
3722 f10 = f10;
3723 } else {
3724 f10 = f3 + f4 * 0.003f;
3725 }
3726 }
3727 }
3728 mMaxSpeedF = f5;
3729 if (f3 < 0.0f) {
3730 f3 = f3;
3731 }
3732 mAccelF = std::fabs(f10);
3733 if (b || noUpDown || i != 0) {
3734 m_b8c = 1.0f;
3735 } else {
3736 m_b8c = 0.3f;
3737 }
3738}
3739
3740bool dAcPy_c::setPenguinPaddleSwim() {
3741 if (mKey.triggerJump()) {
3742 m_b89 = 2;
3743 mPyMdlMng.setAnm(PLAYER_ANIM_P_PADDLE_1);
3744 startSound(SE_PLY_PNGN_SWIM, false);
3746 return true;
3747 }
3748 return false;
3749}
3750
3751void dAcPy_c::SwimAction_Penguin() {
3752 if (mPowerup != POWERUP_PENGUIN_SUIT || isCarry()) {
3753 setSwimAction_Swim(BLEND_DEFAULT);
3754 return;
3755 }
3756 if (setWaterSurfaceJump()) {
3757 return;
3758 }
3759 setWaterSurfaceSwimEffect();
3760 int moveMode = 0;
3761 switch (m_b89) {
3762 case 0:
3763 if (mSubstateTimer == 0) {
3764 m_b8c = 1.0f;
3765 m_b89 = 1;
3766 mPyMdlMng.setAnm(PLAYER_ANIM_P_SWIM);
3767 }
3768 break;
3769 case 1: {
3770 if (mPyMdlMng.mpMdl->mAnm.checkFrame(1.0f) || mPyMdlMng.mpMdl->mAnm.checkFrame(9.0f)) {
3771 startSound(SE_PLY_SWIM_KICK_PENGUIN, false);
3772 }
3773 float rate = mPyMdlMng.mpMdl->mAnm.getRate();
3774 if (m_b8c == 1.0f) {
3775 setFlutterKickEffect();
3776 sLib::chase(&rate, m_b8c, 0.1f);
3777 } else {
3778 sLib::chase(&rate, m_b8c, 0.03f);
3779 }
3780 mPyMdlMng.mpMdl->setRate(rate);
3781 if (setPenguinPaddleSwim()) {
3782 return;
3783 }
3784 break;
3785 }
3786 case 2:
3787 setPaddleSwimEffect();
3788 if (mPyMdlMng.mpMdl->mAnm.getFrame() < 9.0f) {
3789 moveMode = 1;
3790 }
3791 if (mPyMdlMng.isAnmStop()) {
3792 m_b89 = 3;
3793 mPyMdlMng.setAnm(PLAYER_ANIM_P_PADDLE_2);
3794 }
3795 break;
3796 case 3:
3797 if (setPenguinPaddleSwim()) {
3798 return;
3799 }
3800 if (mPyMdlMng.isAnmStop()) {
3801 m_b8c = 1.0f;
3802 m_b89 = 1;
3803 mPyMdlMng.setAnm(PLAYER_ANIM_P_SWIM);
3804 }
3805 break;
3806 }
3808 setPenWaterMoveSpeed(moveMode);
3809}
3810
3811void dAcPy_c::setInitSwimAction_FireBall() {
3812 mSubstate = SWIM_ACTION_3;
3813 m_b89 = 1;
3814 createFireBall(0);
3815 mPyMdlMng.setAnm(PLAYER_ANIM_SWIM_FIRE_AT, dPyMdlBase_c::scFireShootFrame);
3816 mAngle.y = getMukiAngle(mDirection);
3817 m_12f4 = mDirection;
3818}
3819
3820void dAcPy_c::setSwimAction_FireBall() {
3821 mSubstate = SWIM_ACTION_3;
3822 m_b89 = 0;
3823 if (mAngle.x > 0x1800) {
3824 mPyMdlMng.setAnm(PLAYER_ANIM_SWIM_FIRE_AT2);
3825 } else {
3826 mPyMdlMng.setAnm(PLAYER_ANIM_SWIM_FIRE_AT);
3827 }
3828 mPyMdlMng.mpMdl->setFrame(0.0f);
3829 mAngle.y = getMukiAngle(mDirection);
3830 m_12f4 = mDirection;
3831}
3832
3833void dAcPy_c::SwimAction_FireBall() {
3834 if (setWaterSurfaceJump()) {
3835 return;
3836 }
3837 if (mPowerup != POWERUP_PENGUIN_SUIT) {
3838 setWaterMoveSpeed();
3839 } else {
3841 setPenWaterMoveSpeed(0);
3842 }
3843 switch (m_b89) {
3844 case 0:
3845 if (mPyMdlMng.mpMdl->mAnm.checkFrame(dPyMdlBase_c::scFireShootFrame)) {
3846 createFireBall(0);
3847 m_b89 = 1;
3848 }
3849 break;
3850 case 1:
3851 if (checkSetFireBall()) {
3852 setSwimAction_FireBall();
3853 } else if (mPyMdlMng.isAnmStop()) {
3854 if (mPowerup == POWERUP_PENGUIN_SUIT) {
3855 setSwimAction_Penguin(BLEND_DEFAULT);
3856 } else if (isNowBgCross(BGC_FOOT)) {
3857 setSwimAction_Walk(BLEND_DEFAULT);
3858 } else {
3859 setSwimAction_Swim(BLEND_DEFAULT);
3860 }
3861 }
3862 break;
3863 }
3864}
3865
3866void dAcPy_c::setWaterMoveSpeed() {
3867 float targetY = -1.5f;
3868 float accelY = getGravityData()[0];
3869 if (isCarry()) {
3870 float posY = mPos.y + getModelHeight() / 2.0f;
3871 if (std::fabs(mWaterHeight - posY) < 0.2f && std::fabs(mSpeed.y) < 0.1f) {
3872 targetY = 0.0f;
3873 mSpeed.y = 0.0f;
3874 accelY = targetY;
3875 } else if (mWaterHeight > posY) {
3876 targetY = 1.0f;
3877 accelY = -0.04296875f;
3878 } else {
3879 targetY = -1.5f;
3880 accelY = -0.04296875f;
3881 if (mSpeed.y > 0.0f) {
3882 sLib::chase(&mSpeed.y, 0.0f, 0.1f);
3883 }
3884 }
3885 } else {
3886 if (isNowBgCross(BGC_WATER_SHALLOW)) {
3887 if (isStatus(STATUS_39)) {
3888 targetY = 1.0f;
3889 } else if (!mKey.buttonJump()) {
3890 targetY = -1.5f;
3891 } else {
3892 targetY = -0.5f;
3893 }
3894 float speedY = mSpeed.y;
3895 if (speedY < 0.0f) {
3896 if (speedY < targetY) {
3897 accelY = -0.09375f;
3898 } else {
3899 accelY = -0.02734375f;
3900 }
3901 } else {
3902 accelY = -0.04296875f;
3903 }
3904 }
3905 }
3906 sLib::chase(&mSpeed.y, targetY, std::fabs(accelY));
3907 mMaxFallSpeed = sc_MaxFallSpeed;
3908 mAccelY = 0.0f;
3909 float maxSpeedF;
3910 if (mPowerup == POWERUP_PENGUIN_SUIT) {
3911 if (isNowBgCross(BGC_FOOT)) {
3912 maxSpeedF = 0.84375f;
3913 } else {
3914 maxSpeedF = 1.6875f;
3915 }
3916 } else if (isNowBgCross(BGC_FOOT)) {
3917 maxSpeedF = sc_WaterWalkSpeed;
3918 } else {
3919 maxSpeedF = sc_WaterSwimSpeed;
3920 if (m_b84 != 0 && std::fabs(mSpeedF) > std::fabs(sc_WaterSwimSpeed)) {
3921 sLib::chase(&mSpeedF, sc_WaterSwimSpeed, 0.5f);
3922 }
3923 }
3924 float targetF = 0.0f;
3925 if (mKey.buttonWalk(nullptr)) {
3926 targetF = maxSpeedF * sc_DirSpeed[mDirection];
3927 }
3928 targetF += dWaterEntryMng_c::m_instance->get_8c0() * 0.3f;
3929 mMaxSpeedF = targetF;
3930 float absSpeedF = std::fabs(mSpeedF);
3931 float speedF = mSpeedF;
3932 if (mPowerup == POWERUP_PENGUIN_SUIT) {
3933 if (targetF) {
3934 if (speedF * targetF < 0.0f) {
3935 mAccelF = 0.0625f;
3936 } else if (absSpeedF > std::fabs(targetF)) {
3937 mAccelF = 0.0625f;
3938 } else {
3939 mAccelF = 0.0546875f;
3940 }
3941 } else if (isState(StateID_Crouch)) {
3942 mAccelF = 0.0546875f;
3943 } else {
3944 mAccelF = 0.015625f;
3945 }
3946 } else {
3947 if (targetF) {
3948 if (speedF * targetF < 0.0f) {
3949 mAccelF = 0.017f;
3950 } else if (absSpeedF > std::fabs(targetF)) {
3951 if (isNowBgCross(BGC_FOOT)) {
3952 mAccelF = 0.05f;
3953 } else {
3954 mAccelF = 0.017f;
3955 }
3956 } else {
3957 mAccelF = 0.025f;
3958 }
3959 } else if (absSpeedF > std::fabs(targetF)) {
3960 if (isNowBgCross(BGC_FOOT)) {
3961 mAccelF = 0.05f;
3962 } else {
3963 mAccelF = 0.017f;
3964 }
3965 } else if (isState(StateID_Crouch)) {
3966 mAccelF = 0.027f;
3967 } else {
3968 mAccelF = 0.004f;
3969 }
3970 }
3971 if (mKey.buttonWalk(nullptr)) {
3972 mAccelF = std::fabs(sc_DirSpeed[mDirection] * mAccelF + dWaterEntryMng_c::m_instance->get_8c0() * 0.003f);
3973 }
3974}
3975
3976void dAcPy_c::executeState_Swim() {
3977 if (isStatus(STATUS_ENEMY_STAGE_CLEAR) && isNowBgCross(BGC_FOOT)) {
3978 offNowBgCross(BGC_FOOT);
3979 mSpeed.y = 1.0f;
3980 }
3981 if (m_b84 != 0) {
3982 m_b84--;
3983 }
3984 if (m_b88 != 0) {
3985 m_b88--;
3986 }
3987 if (isStatus(STATUS_39)) {
3988 if (mSpeed.y >= -0.25f) {
3990 }
3991 }
3992 if (!isNowBgCross(BGC_WATER_SHALLOW) && isNowBgCross(BGC_FOOT)) {
3993 changeState(StateID_Walk, BLEND_NONE);
3994 } else {
3995 if (mSubstate != SWIM_ACTION_3 && checkSetFireBall()) {
3996 setSwimAction_FireBall();
3997 }
3999 typedef void (dAcPy_c::*SwimActionProc)();
4000 static SwimActionProc l_SwimActionProc[] = {
4001 &dAcPy_c::SwimAction_Swim,
4002 &dAcPy_c::SwimAction_Walk,
4003 &dAcPy_c::SwimAction_Penguin,
4004 &dAcPy_c::SwimAction_FireBall,
4005 };
4006 (this->*l_SwimActionProc[mSubstate])();
4007 calcPenguinSwimGroundRev();
4008 }
4009}
4010
4011void dAcPy_c::calcPenguinSwimGroundRev() {
4013 m_1594 = 0.0f;
4014 m_1598 = 0.0f;
4015 return;
4016 }
4017 float f1 = 0.0f;
4018 float f2 = 0.0f;
4019 mMtx_c rotMtx;
4020 rotMtx.trans(mPos);
4021 rotMtx.YrotM(mAngle.y);
4022 rotMtx.concat(mMtx_c::createTrans(0.0f, 8.0f, 0.0f));
4023 rotMtx.XrotM(-mAngle.x);
4024 rotMtx.concat(mMtx_c::createTrans(0.0f, 8.0f, 0.0f));
4025 rotMtx.ZrotM(mAngle.z);
4026 rotMtx.concat(mMtx_c::createTrans(0.0f, 0.0f, 20.0f));
4027 mVec3_c resVec;
4028 rotMtx.multVecZero(resVec);
4029 const sBcPointData *bgPointData = getWallBgPointData();
4030 if (bgPointData != nullptr) {
4031 float bgOffs[2];
4032 bgOffs[0] = bgPointData->mInfMargin / 4096.0f;
4033 bgOffs[1] = bgPointData->mSupMargin / 4096.0f;
4034 mVec3_c wallPos1(mPos.x, mPos.y + bgOffs[0], mPos.z);
4035 mVec3_c wallPos2(resVec.x, mPos.y + bgOffs[0], resVec.z);
4036 for (int i = 0; i < 2; i++) {
4037 wallPos1.set(mPos.x, mPos.y + bgOffs[i], mPos.z);
4038 wallPos2.set(resVec.x, mPos.y + bgOffs[i], resVec.z);
4039 float wallX;
4040 if (dBc_c::checkWall(&wallPos1, &wallPos2, &wallX, mLayer, 1, nullptr)) {
4041 f1 = wallX - resVec.x;
4042 if (mPos.x < resVec.x) {
4043 resVec.x = wallX - 1.0f;
4044 } else {
4045 resVec.x = wallX + 1.0f;
4046 }
4047 }
4048 }
4049 }
4050 mVec3_c groundPos(resVec.x, mPos.y + 4.0f, resVec.z);
4051 float groundHeight;
4052 if (dBc_c::checkGround(&groundPos, &groundHeight, mLayer, 1, -1) && groundHeight > resVec.y) {
4053 f2 = groundHeight - resVec.y;
4054 }
4055 sLib::chase(&m_1594, f1, 1.0f);
4056 sLib::chase(&m_1598, f2, 1.0f);
4057}
4058
4059void dAcPy_c::finalizeState_Swim() {
4060 m_1594 = 0.0f;
4061 m_1598 = 0.0f;
4062 m_b88 = 0;
4063 mAngle.z = 0;
4064 mAngle.x = 0;
4067 float groundHeight;
4068 mVec3_c checkPos(mPos.x, mPos.y - 5.0f, mPos.z);
4069 if (dBc_c::checkGround(&mPos, &groundHeight, mLayer, 1, -1)) {
4070 if (mPos.y <= groundHeight) {
4071 mPos.y = groundHeight;
4072 mLastPos.y = mPos.y;
4073 }
4074 }
4076 }
4077 offStatus(STATUS_97);
4078 offStatus(STATUS_AA);
4079 offStatus(STATUS_A8);
4080 offStatus(STATUS_92);
4081 if (!isNowBgCross(BGC_WATER_SHALLOW)) {
4082 setWaterOutEffect();
4083 }
4084}
4085
4086void dAcPy_c::setIvyHangEffect() {
4087 mMtx_c jntMtx;
4088 mPyMdlMng.mpMdl->getJointMtx(&jntMtx, 11);
4089 mVec3_c v1;
4090 jntMtx.multVecZero(v1);
4091 mPyMdlMng.mpMdl->getJointMtx(&jntMtx, 14);
4092 mVec3_c v2;
4093 jntMtx.multVecZero(v2);
4094 mVec3_c efPos = (v1 + v2) / 2.0f;
4095 efPos.z = mPos.z;
4096 dEf::createPlayerEffect(mPlayerNo, &mLevelEf6, "Wm_mr_ivy", 0, &efPos, nullptr, nullptr);
4097}
4098
4099bool dAcPy_c::setVineAction() {
4100 if (isStatus(STATUS_9B)) {
4101 if (isCarry()) {
4102 return false;
4103 }
4104 if (mSpeed.y <= 0.0f && mKey.buttonUp() && isNowBgCross(BGC_VINE_TOUCH_U)) {
4105 if (mBc.mFenceType == 1) {
4106 changeState(StateID_Vine, (void *) 2);
4107 } else {
4108 changeState(StateID_Vine, (void *) 0);
4109 }
4110 return true;
4111 }
4112 }
4113 return false;
4114}
4115
4116float dAcPy_c::getHangBcOffsetY() {
4117 static const float scHangOffsetY[] = {
4118 16.0f, 27.0f, 27.0f, 12.0f, 27.0f, 27.0f, 27.0f
4119 };
4120 static const float scKinopioHangOffsetY[] = {
4121 13.0f, 21.0f, 21.0f, 9.0f, 21.0f, 21.0f, 21.0f
4122 };
4123 // [probably some inline?]
4124 if (!(mPlayerType != PLAYER_MARIO && mPlayerType != PLAYER_LUIGI)) {
4125 return scHangOffsetY[mPowerup];
4126 } else {
4127 return scKinopioHangOffsetY[mPowerup];
4128 }
4129}
4130
4131bool dAcPy_c::setKaniHangToVineAction() {
4132 if (mKey.buttonDown()) {
4133 float y = mPos.y - 1.0f;
4134 float x2 = mPos.x + (mVineBcData.mOffset / 4096.0f);
4135 float x1 = mPos.x - (mVineBcData.mOffset / 4096.0f + 1.0f);
4136 if (
4137 dBc_c::getUnitType(x1, y, mLayer) & 0x400 ||
4138 dBc_c::getUnitType(x2, y, mLayer) & 0x400
4139 ) {
4140 mPos.y -= getHangBcOffsetY();
4141 m_60 = 10;
4142 changeState(StateID_Vine, (void *) 3);
4143 return true;
4144 }
4145 }
4146 return false;
4147}
4148
4149bool dAcPy_c::setVineToKaniHangAction() {
4150 if (mKey.buttonUp()) {
4151 sBcPointData r = mVineBcData;
4152 r.mInfMargin = getHangBcOffsetY() * 4096.0f;
4153 if (!(mBc.checkVineCollision(&r) & 3)) {
4154 float y = mPos.y + getHangBcOffsetY();
4155 float x = mPos.x;
4156 short groundY = (((short) y) & 0xfff0) - 16;
4157 u32 unitKind = dBc_c::getUnitKind(x, groundY + 1.0f, mLayer);
4158 if ((unitKind >> 16 & 0xff) == 8) {
4159 mPos.y += getHangBcOffsetY();
4160 m_60 = 10;
4161 changeState(StateID_Kani, KANI_ARG_HANG_UP_VINE);
4162 return true;
4163 }
4164 }
4165 }
4166 return false;
4167}
4168
4169void dAcPy_c::initializeState_Vine() {
4170 setScrollMode(2);
4172 mAccelY = 0.0f;
4173 mSpeedF = 0.0f;
4174 mAccelF = 0.0f;
4175 mMaxSpeedF = 0.0f;
4176 mSpeed.x = 0.0f;
4177 mSpeed.y = 0.0f;
4178 m_7c4 = 0;
4179 if (mAmiLayer == 1) {
4180 m_7c0 = 0x8000;
4181 } else {
4182 m_7c0 = 0;
4183 }
4184 int changeParam = (int) mStateArg;
4185 mAngle.y = m_7c0;
4186 mBc.mPlayerFlags |= 1;
4187 switch (changeParam) {
4188 case 0:
4189 case 2:
4190 startPlayerVoice(VOICE_ROPE_CATCH, 0);
4191 switch (mBc.mFenceType) {
4192 case 0:
4193 startSound(SE_PLY_CATCH_IVY, 0);
4194 if (!isNowBgCross(BGC_FOOT)) {
4195 mPyMdlMng.setAnm(PLAYER_ANIM_PEA_PLANT_ST);
4196 mSubstate = VINE_ACTION_IVY;
4197 mSubstateValue = 0;
4198 } else {
4199 mPyMdlMng.setAnm(PLAYER_ANIM_PEA_PLANT_WAIT);
4200 mSubstate = VINE_ACTION_IVY;
4201 mSubstateValue = 1;
4202 }
4203 break;
4204 case 1:
4205 mPyMdlMng.setAnm(PLAYER_ANIM_NET_WAIT);
4206 mSubstate = VINE_ACTION_NET;
4207 break;
4208 case 2:
4209 startSound(SE_PLY_LAND_FENCE, 0);
4210 mPyMdlMng.setAnm(PLAYER_ANIM_NET_WAIT);
4211 mSubstate = VINE_ACTION_NET;
4212 break;
4213 }
4214 break;
4215 case 1:
4216 mPyMdlMng.setAnm(PLAYER_ANIM_PEA_PLANT_WAIT);
4217 mSubstate = VINE_ACTION_IVY;
4218 mSubstateValue = 1;
4219 break;
4220 case 3:
4221 mPyMdlMng.setAnm(PLAYER_ANIM_NET_WAIT, 0.0f, 0.0f);
4222 mSubstate = VINE_ACTION_NET;
4223 break;
4224 }
4225}
4226
4227void dAcPy_c::calcVineSpeed() {
4228 float speed;
4229 switch (mBc.mFenceType) {
4230 case 0:
4231 case 2:
4232 if (mKey.buttonDush()) {
4233 speed = 1.5f;
4234 } else {
4235 speed = 1.0f;
4236 }
4237 break;
4238 case 1:
4239 if (mKey.buttonDush()) {
4240 speed = sGlobalData_c<dAcPy_c>::mData.mVineSpeedRelated[1];
4241 } else {
4242 speed = sGlobalData_c<dAcPy_c>::mData.mVineSpeedRelated[0];
4243 }
4244 break;
4245 }
4246 mSpeed.y = 0.0f;
4247 if (mKey.buttonUp()) {
4248 if (isNowBgCross(BGC_VINE_TOUCH_U) && isNowBgCross(BGC_VINE_TOUCH_2)) {
4249 mSpeed.y = speed;
4250 }
4251 } else if (mKey.buttonDown()) {
4252 mSpeed.y = -speed;
4253 }
4254 mSpeedF = 0.0f;
4255 float tmp = 0.0f;
4256 switch (mBc.mFenceType) {
4257 case 0:
4258 if (mKey.buttonDush()) {
4259 tmp = 0.7f;
4260 } else {
4261 tmp = 0.5f;
4262 }
4263 if (mKey.buttonUp() || mKey.buttonDown()) {
4264 tmp = 0.0f;
4265 }
4266 break;
4267 case 1:
4268 if (mKey.buttonDush()) {
4269 tmp = sGlobalData_c<dAcPy_c>::mData.mVineSpeedRelated[3];
4270 } else {
4271 tmp = sGlobalData_c<dAcPy_c>::mData.mVineSpeedRelated[2];
4272 }
4273 break;
4274 case 2:
4275 if (mKey.buttonDush()) {
4276 tmp = 1.25f;
4277 } else {
4278 tmp = 0.875f;
4279 }
4280 break;
4281 }
4282 if (mKey.buttonLeft()) {
4283 if (!isNowBgCross(BGC_WALL_TOUCH_L_2)) {
4284 mSpeedF = -tmp;
4285 }
4286 } else if (mKey.buttonRight()) {
4287 if (!isNowBgCross(BGC_WALL_TOUCH_R_2)) {
4288 mSpeedF = tmp;
4289 }
4290 }
4291}
4292
4293bool dAcPy_c::checkVineEnd() {
4294 if (!isNowBgCross(BGC_VINE_TOUCH_FULL) || isNowBgCross(BGC_FOOT) && !mKey.buttonUp()) {
4295 mAngle.y = getMukiAngle(mDirection);
4296 if (isNowBgCross(BGC_CLIFF)) {
4297 changeState(StateID_Kani, KANI_ARG_WALK_FORCE);
4298 return true;
4299 } else {
4300 changeState(StateID_Walk, BLEND_NONE);
4301 return true;
4302 }
4303 }
4304 return false;
4305}
4306
4307void dAcPy_c::setVineWalkSE() {
4308 if (mPyMdlMng.mpMdl->mAnm.checkFrame(10.0f) || mPyMdlMng.mpMdl->mAnm.checkFrame(30.0f)) {
4309 switch (mBc.mFenceType) {
4310 case 0:
4311 startSound(SE_PLY_MOVE_IVY, false);
4312 break;
4313 case 2:
4314 startSound(SE_PLY_WALK_METAL, false);
4315 break;
4316 case 1:
4317 startSound(SE_PLY_FOOTNOTE_ROCK_CLIMB, false);
4318 break;
4319 }
4320 }
4321}
4322
4323void dAcPy_c::VineActionIvy() {
4324 if (setRideOffPlayerJump(sc_JumpSpeed, 0.0f) || startJump(BLEND_NONE, 1)) {
4325 return;
4326 }
4327 if (checkVineEnd()) {
4328 return;
4329 }
4330 calcVineSpeed();
4331 if (mSubstateValue == 0) {
4332 if (mPyMdlMng.isAnmStop()) {
4334 }
4335 } else {
4336 if (mSpeed.x || mSpeed.y) {
4337 float blend = 0.0f;
4338 if (mKey.buttonDush()) {
4339 blend = 1.875f;
4340 } else {
4341 blend = 1.5f;
4342 }
4343 if (mSpeed.y < 0.0f) {
4344 blend = -blend;
4345 }
4346 mPyMdlMng.setAnm(PLAYER_ANIM_PEA_PLANT, blend, 0.0f, 0.0f);
4347 if (mBc.mFenceType == 0 && m_7c4 == 0) {
4348 setIvyHangEffect();
4349 setVineWalkSE();
4350 }
4351 } else {
4352 mPyMdlMng.setAnm(PLAYER_ANIM_PEA_PLANT_WAIT, 0.0f);
4353 m_7c4 = 3;
4354 }
4355 }
4356}
4357
4358void dAcPy_c::VineActionNet() {
4359 if (checkVineEnd()) {
4360 return;
4361 }
4362 switch (mBc.mFenceType) {
4363 default:
4364 if (setRideOffPlayerJump(sc_JumpSpeed, 0.0f) || startJump(BLEND_NONE, 0)) {
4365 switch (mPowerup) {
4366 case POWERUP_NONE:
4367 startSound(SE_PLY_JUMP_FENCE_S, false);
4368 break;
4369 case POWERUP_MINI_MUSHROOM:
4370 startSound(SE_PLY_JUMP_FENCE_SS, false);
4371 break;
4372 default:
4373 startSound(SE_PLY_JUMP_FENCE, false);
4374 break;
4375 }
4376 mAngle.y = getMukiAngle(mDirection);
4377 return;
4378 }
4379 if (mKey.triggerAttack()) {
4380 mSubstate = VINE_ACTION_ATTACK;
4381 mSubstateValue = 0;
4382 mPyMdlMng.setAnm(PLAYER_ANIM_NET_ATTACK);
4383 mSpeed.y = 0.0f;
4384 mSpeedF = 0.0f;
4385 onStatus(STATUS_4A);
4386 return;
4387 }
4388 break;
4389 case 1:
4390 if (setVineToKaniHangAction()) {
4391 return;
4392 }
4393 break;
4394 }
4395 calcVineSpeed();
4396 float f = 1.0f;
4397 if (mBc.mpFenceCollision != nullptr) {
4398 short s = abs(mBc.mpFenceCollision->m_c2);
4399 if (s > 128) {
4400 s = 128;
4401 }
4402 float tmp = s * 0.5f;
4403 f = tmp / 128.0f + 1.0f;
4404 }
4405 if (!mKey.buttonUp()) {
4406 m_7c4 = 0;
4407 }
4408 if (mSpeed.y) {
4409 float rate;
4410 if (mKey.buttonDush()) {
4411 rate = 1.875f;
4412 } else {
4413 rate = 1.5f;
4414 }
4415 rate = rate * f;
4416 if (mSpeed.y < 0.0f) {
4417 rate = -rate;
4418 }
4419 mPyMdlMng.setAnm(PLAYER_ANIM_NET_WALK1, rate, 0.0f, 0.0f);
4420 m_7c4 = 5;
4421 setVineWalkSE();
4422 } else if (mSpeed.x) {
4423 if (m_7c4 == 0) {
4424 float rate;
4425 if (mKey.buttonDush()) {
4426 rate = 1.875f;
4427 } else {
4428 rate = 1.5f;
4429 }
4430 rate = rate * f;
4431 mPyMdlMng.setAnm(PLAYER_ANIM_NET_WALK2, rate, 0.0f, 0.0f);
4432 }
4433 setVineWalkSE();
4434 } else if (f > 1.0f) {
4435 if (mKey.buttonLeft() || mKey.buttonRight()) {
4436 mPyMdlMng.setAnm(PLAYER_ANIM_NET_WALK2, 0.6f * f, 0.0f, 0.0f);
4437 } else {
4438 mPyMdlMng.setAnm(PLAYER_ANIM_NET_WALK1, 0.6f * f, 0.0f, 0.0f);
4439 }
4440 } else {
4441 mPyMdlMng.setAnm(PLAYER_ANIM_NET_WAIT);
4442 }
4443}
4444
4445void dAcPy_c::VineActionAttack() {
4446 if (checkVineEnd()) {
4447 return;
4448 }
4449 u16 frame = mPyMdlMng.mpMdl->mAnm.getFrame();
4450 if (mPyMdlMng.mpMdl->mAnm.checkFrame(3.0f)) {
4451 onStatus(STATUS_49);
4452 mMtx_c jntMtx;
4453 mPyMdlMng.mpMdl->getJointMtx(&jntMtx, 14);
4454 jntMtx.concat(mMtx_c::createTrans(3.0f, 0.0f, 0.0f));
4455 mVec3_c efPos;
4456 jntMtx.multVecZero(efPos);
4457 dEf::createPlayerEffect_change(mPlayerNo, "Wm_mr_wirehit", 0, &efPos, nullptr, nullptr);
4458 startSound(SE_PLY_ATTACK_FENCE, false);
4459 }
4460 if (!isStatus(STATUS_85)) {
4461 if (frame >= 12.0f && mKey.buttonCross() || mPyMdlMng.isAnmStop()) {
4462 mSubstate = VINE_ACTION_NET;
4463 return;
4464 }
4465 if (mKey.triggerAttack()) {
4466 mSubstateValue = 1;
4467 }
4468 if (frame >= 23.0f && mSubstateValue != 0) {
4469 mPyMdlMng.mpMdl->setFrame(0.0f);
4470 mSubstateValue = 0;
4471 }
4472 }
4473 if (frame < 24.0f) {
4474 onStatus(STATUS_4A);
4475 setCcAtNetPunch();
4476 }
4477}
4478
4479void dAcPy_c::VineActionRoll() {
4480 onStatus(STATUS_7A);
4481 switch (m_7bc) {
4482 case 0:
4483 if (mPyMdlMng.isAnmStop()) {
4484 m_7bc = 1;
4485 mPyMdlMng.setAnm(PLAYER_ANIM_NET_WAIT);
4486 }
4487 break;
4488 case 2:
4489 offStatus(STATUS_7A);
4490 mPyMdlMng.setAnm(PLAYER_ANIM_NET_WAIT);
4491 mSubstate = VINE_ACTION_NET;
4492 break;
4493 }
4494}
4495
4496void dAcPy_c::executeState_Vine() {
4497 offStatus(STATUS_49);
4498 offStatus(STATUS_4A);
4499 if (m_7c4 != 0) {
4500 m_7c4--;
4501 }
4502 typedef void (dAcPy_c::*VineActionProc_t)();
4503 static VineActionProc_t l_VineActionProc[] = {
4504 &dAcPy_c::VineActionIvy,
4505 &dAcPy_c::VineActionNet,
4506 &dAcPy_c::VineActionAttack,
4507 &dAcPy_c::VineActionRoll
4508 };
4509 (this->*l_VineActionProc[mSubstate])();
4510}
4511
4512bool dAcPy_c::checkNetPunch() {
4513 if (
4514 isState(StateID_Vine) &&
4515 mSubstate == VINE_ACTION_ATTACK &&
4516 mPyMdlMng.mpMdl->mAnm.getFrame() >= 10.0f
4517 ) {
4518 mSubstate = VINE_ACTION_ROLL;
4519 m_7bc = 0;
4520 return true;
4521 }
4522 return false;
4523}
4524
4525bool dAcPy_c::setAmiRollAction(mVec3_c *pos) {
4526 if (isState(StateID_Vine)) {
4527 if (mSubstate != VINE_ACTION_ROLL) {
4528 mSubstate = VINE_ACTION_ROLL;
4529 m_7bc = 1;
4530 mPyMdlMng.setAnm(PLAYER_ANIM_NET_WAIT);
4531 }
4532 mPos.z = 0.0f;
4533 mAmiRollPos = *pos;
4534 mAmiAng = mAngle.y;
4535 mAmiXDiff = mPos.x - mAmiRollPos.x;
4536 mAmiRelated = 0.7f;
4537 return true;
4538 }
4539 return false;
4540}
4541
4542bool dAcPy_c::isAmiRollAction() {
4543 if (isState(StateID_Vine) && mSubstate == VINE_ACTION_ROLL) {
4544 return true;
4545 }
4546 return false;
4547}
4548
4549void dAcPy_c::setAmiRollPos(short ang, float f) {
4550 float cos = mAng(ang).cos();
4551 float sin = mAng(ang).sin();
4552 mVec3_c v(
4553 mAmiRollPos.x + cos * mAmiXDiff + sin * mAmiRelated,
4554 mPos.y,
4555 mAmiRollPos.z + cos * mAmiRelated - sin * mAmiXDiff
4556 );
4557 setAmiRollPos(ang, f, v);
4558}
4559
4560void dAcPy_c::setAmiRollPos(short ang, float f, mVec3_c &v) {
4561 if (isAmiRollAction()) {
4562 mAngle.y = mAmiAng + ang;
4563 mPos = v;
4564 mAmiRelated2 = f;
4565 }
4566}
4567
4568void dAcPy_c::endAmiRollAction(short ang) {
4569 if (isAmiRollAction()) {
4570 mAng newAng = m_7c0 + ang;
4571 m_7c0 = newAng;
4572 mAngle.y = newAng;
4573 if (m_7c0 == 0x8000) {
4574 mAmiLayer = 1;
4575 } else {
4576 mAmiLayer = 2;
4577 }
4578 mAmiRelated2 = 1.0f;
4579 m_7bc = 2;
4580 }
4581}
4582
4583void dAcPy_c::finalizeState_Vine() {
4584 mAccelY = getGravityData()[0];
4586 offStatus(STATUS_7A);
4587 offStatus(STATUS_49);
4588 offStatus(STATUS_4A);
4589 mBc.mPlayerFlags &= ~1;
4590}
4591
4592void dAcPy_c::setCarryPlayerHang(float height) {
4593 mPos.y = height - mHeadBcData.mOffset / 4096.0f;
4594 onNowBgCross(BGC_HANG_ROPE);
4595 changeState(StateID_Hang, 0);
4596}
4597
4598bool dAcPy_c::setHangAction() {
4599 if (isNowBgCross(BGC_HANG_ROPE)) {
4600 dAcPy_c *carryPlayer = getCarryPlayer();
4601 if (carryPlayer != nullptr && carryPlayer->isStatus(STATUS_9C) && !carryPlayer->isCarry()) {
4602 float hangHeight = mPos.y + mHeadBcData.mOffset / 4096.0f;
4603 releaseCarryActor();
4604 carryPlayer->setCarryPlayerHang(hangHeight);
4605 return true;
4606 }
4607 if (isStatus(STATUS_9C) && !isCarry() && mSpeed.y >= 0.0f) {
4608 changeState(StateID_Hang, 0);
4609 return true;
4610 }
4611 }
4612 return false;
4613}
4614
4615void dAcPy_c::initializeState_Hang() {
4617 mAccelY = 0.0f;
4618 mSpeedF = 0.0f;
4619 mMaxSpeedF = 0.0f;
4620 mSpeed.x = 0.0f;
4621 mSpeed.y = 0.0f;
4622 m_1598 = 0.0f;
4623 if (mPlayerType == PLAYER_YELLOW_TOAD || mPlayerType == PLAYER_BLUE_TOAD) {
4624 static const float scHangOffsetY[POWERUP_COUNT] = { 4.5f, 10.0f, 10.0f, 1.0f, 10.0f, 9.0f, 10.0f };
4625 m_1598 = scHangOffsetY[mPowerup];
4626 }
4627 mPyMdlMng.setAnm(PLAYER_ANIM_MONKEY_START);
4628 setZPositionDirect(400.0f);
4629 startPlayerVoice(VOICE_ROPE_CATCH, 0);
4630}
4631
4632void dAcPy_c::HangActionStart() {
4633 mSpeedF = 0.0f;
4634 m_8f0 = 0;
4635 if (mPyMdlMng.isAnmStop()) {
4636 setHangActionWait();
4637 } else if (mKey.buttonRight() || mKey.buttonLeft()) {
4638 setHangActionMove();
4639 }
4640}
4641
4642void dAcPy_c::setHangActionWait() {
4643 mSubstate = HANG_ACTION_WAIT;
4644 static const int scHangWaitAnm[] = { PLAYER_ANIM_MONKEY_WAIT_R, PLAYER_ANIM_MONKEY_WAIT_L };
4645 mPyMdlMng.setAnm(scHangWaitAnm[m_8f0]);
4646}
4647
4648void dAcPy_c::HangActionWait() {
4649 mSpeedF = 0.0f;
4650 if (mKey.buttonRight() || mKey.buttonLeft()) {
4651 setHangActionMove();
4652 }
4653}
4654
4655void dAcPy_c::setHangActionMove() {
4656 mSubstate = HANG_ACTION_MOVE;
4657 static const int scHangMoveAnm[] = { PLAYER_ANIM_MONKEY_R_TO_L, PLAYER_ANIM_MONKEY_L_TO_R };
4658 mPyMdlMng.setAnm(scHangMoveAnm[m_8f0]);
4659 m_8f0 ^= 1;
4660 startSound(SE_PLY_MONKEY_BARS, false);
4661}
4662
4663void dAcPy_c::HangActionMove() {
4664 if (mKey.buttonDush()) {
4665 mSpeedF = sc_DirSpeed[mDirection] * 1.125f;
4666 mPyMdlMng.mpMdl->setRate(1.5f);
4667 } else {
4668 mSpeedF = sc_DirSpeed[mDirection] * 0.875f;
4669 mPyMdlMng.mpMdl->setRate(1.0f);
4670 }
4671 if (mPyMdlMng.isAnmStop()) {
4672 if (mKey.buttonRight() || mKey.buttonLeft()) {
4673 setHangActionMove();
4674 } else {
4675 setHangActionWait();
4676 }
4677 }
4678}
4679
4680void dAcPy_c::executeState_Hang() {
4681 if (!isNowBgCross(BGC_HANG_ROPE) || mKey.buttonDown()) {
4682 changeState(StateID_Fall, false);
4683 startPlayerVoice(VOICE_ROPE_RELEASE, 0);
4684 } else {
4685 turnBesideAngle();
4686 typedef void (dAcPy_c::*HangActionProc_t)();
4687 static HangActionProc_t l_HangActionProc[] = {
4688 &dAcPy_c::HangActionStart,
4689 &dAcPy_c::HangActionWait,
4690 &dAcPy_c::HangActionMove,
4691 };
4692 (this->*l_HangActionProc[mSubstate])();
4693 }
4694}
4695
4696void dAcPy_c::finalizeState_Hang() {
4697 m_1598 = 0.0f;
4698 setScrollMode(0);
4700 offZPosSetNone();
4701}
4702
4703void dAcPy_c::setPoleTurnAngle() {
4704 short target = getBesideMukiAngle(mDirection ^ 1);
4705 mAngle.y.chase(target, 0x2000);
4706}
4707
4708bool dAcPy_c::setPoleAction() {
4709 if (isStatus(STATUS_9D)) {
4710 if (mPoleGrabCooldown != 0 || isCarry()) {
4711 return false;
4712 }
4713 if (mSpeed.y <= 3.0f && mKey.buttonUp() && isNowBgCross(BGC_CAN_CLIMB)) {
4714 changeState(StateID_Pole, 0);
4715 return true;
4716 }
4717 }
4718 return false;
4719}
4720
4721void dAcPy_c::initializeState_Pole() {
4723 onStatus(STATUS_97);
4725 mAccelY = 0.0f;
4726 mSpeedF = 0.0f;
4727 mAccelF = 0.0f;
4728 mMaxSpeedF = 0.0f;
4729 mSpeed.x = 0.0f;
4730 mSpeed.y = 0.0f;
4731 mAngle.y = getBesideMukiAngle(mDirection);
4732 m_8f4.x = (int) (mPos.x / 16.0f) * 16.0f + 8.0f;
4733 setZPositionDirect(400.0f);
4734 if (isNowBgCross(BGC_CAN_CLIMB)) {
4735 m_8f4.y = mPos.y;
4736 }
4737 if (isNowBgCross(BGC_FOOT)) {
4738 setPoleActionUp();
4739 mSpeed.y = 1.0f;
4740 offNowBgCross(BGC_FOOT);
4741 mDirection ^= 1;
4742 offStatus(STATUS_97);
4743 } else {
4744 mPyMdlMng.setAnm(PLAYER_ANIM_TREE_START);
4745 startSound(SE_PLY_POLE_CATCH, false);
4746 startPlayerVoice(VOICE_ROPE_CATCH, 0);
4747 mSubstate = 0;
4748 }
4749}
4750
4751void dAcPy_c::PoleActionStart() {
4752 if (mKey.triggerJump()) {
4753 mSubstateValue = 1;
4754 }
4755 if (mPyMdlMng.mpMdl->mAnm.getFrame() >= 5.0f && mSubstateValue != 0) {
4756 int dir;
4757 if (mKey.buttonWalk(&dir)) {
4758 mDirection = dir;
4759 }
4760 setPoleJump();
4761
4762 } else if (mPyMdlMng.isAnmStop()) {
4763 setPoleActionWait();
4764 mDirection ^= 1;
4765 offStatus(STATUS_97);
4766 }
4767}
4768
4769void dAcPy_c::setPoleActionWait() {
4770 mSubstate = 1;
4771 mPyMdlMng.setAnm(PLAYER_ANIM_TREE_WAIT);
4772}
4773
4774void dAcPy_c::PoleActionWait() {
4775 if (!isNowBgCross(BGC_CAN_CLIMB)) {
4776 mDirection ^= 1;
4777 changeState(StateID_Fall, false);
4778 } else {
4779 setPoleTurnAngle();
4780 mSpeed.y = 0.0f;
4781 if (mKey.buttonDown()) {
4782 setPoleActionDown();
4783 } else if (mKey.buttonUp()) {
4784 setPoleActionUp();
4785 }
4786 }
4787}
4788
4789void dAcPy_c::setPoleActionUp() {
4790 mSubstate = 2;
4791 mPyMdlMng.setAnm(PLAYER_ANIM_TREE_CLIMB);
4792}
4793
4794void dAcPy_c::PoleActionUp() {
4795 setPoleTurnAngle();
4796 if (mPyMdlMng.mpMdl->mAnm.checkFrame(0.0f)) {
4797 startSound(SE_PLY_POLE_CLIMB, false);
4798 }
4799 mSpeed.y = 0.0f;
4800 if (!isNowBgCross(BGC_CAN_CLIMB)) {
4801 mPos.y = m_8f4.y;
4802 }
4803 if (mKey.buttonDown()) {
4804 setPoleActionDown();
4805 } else if (!mKey.buttonUp()) {
4806 setPoleActionWait();
4807 } else if (mKey.buttonDush()) {
4808 mPyMdlMng.mpMdl->setRate(1.875f);
4809 mSpeed.y = 1.5f;
4810 } else {
4811 mPyMdlMng.mpMdl->setRate(1.5f);
4812 mSpeed.y = 1.0f;
4813 }
4814}
4815
4816void dAcPy_c::setPoleActionDown() {
4817 mSubstate = 3;
4818 mPyMdlMng.setAnm(PLAYER_ANIM_TREE_POSE);
4819}
4820
4821void dAcPy_c::PoleActionDown() {
4822 if (!isNowBgCross(BGC_CAN_CLIMB)) {
4823 mDirection ^= 1;
4824 changeState(StateID_Fall, false);
4825 return;
4826 }
4827 setPoleTurnAngle();
4828 mSpeed.y = 0.0f;
4829 if (mKey.buttonUp()) {
4830 setPoleActionUp();
4831 } else if (!mKey.buttonDown()) {
4832 setPoleActionWait();
4833 } else {
4834 if (mKey.buttonDush()) {
4835 float rate = 1.6f;
4836 mSpeed.y = rate * -2.0f;
4837 mPyMdlMng.mpMdl->setRate(rate);
4838 } else {
4839 mSpeed.y = -2.0f;
4840 mPyMdlMng.mpMdl->setRate(1.0f);
4841 }
4842 holdSound(SE_PLY_POLE_SLIDE, false);
4843 }
4844}
4845
4846void dAcPy_c::setPoleJump() {
4847 startPlayerVoice(VOICE_ROPE_RELEASE, 0);
4849 changeState(StateID_Jump, nullptr);
4850 u8 dir = mDirection;
4851 float baseSpeed = getSpeedData()->mLowSpeed;
4852 mSpeedF = baseSpeed * sc_DirSpeed[dir];
4853}
4854
4855bool dAcPy_c::setPoleShakeJump() {
4856 u8 dir = mDirection;
4857 float baseSpeed = getSpeedData()->mLowSpeed;
4858 if (setRideOffPlayerJump(sc_JumpSpeed, baseSpeed * sc_DirSpeed[dir])) {
4859 startPlayerVoice(VOICE_ROPE_RELEASE, 0);
4861 return true;
4862 }
4863 return false;
4864}
4865
4866void dAcPy_c::executeState_Pole() {
4867 if (isNowBgCross(BGC_FOOT)) {
4868 mDirection ^= 1;
4869 changeState(StateID_Walk, BLEND_DEFAULT);
4870 } else if (isNowBgCross(BgCross1_e(BGC_SIDE_LIMIT_L | BGC_SIDE_LIMIT_R))) {
4871 mDirection ^= 1;
4872 changeState(StateID_Fall, false);
4873 } else {
4874 if (!setPoleShakeJump()) {
4875 if (mSubstate != 0 && mKey.triggerJump()) {
4876 setPoleJump();
4877 return;
4878 }
4879 mPos.x = m_8f4.x;
4880 if (isNowBgCross(BGC_CAN_CLIMB)) {
4881 m_8f4.y = mPos.y;
4882 }
4883 typedef void (dAcPy_c::*PoleActionProc_t)();
4884 static PoleActionProc_t l_PoleActionProc[] = {
4885 &dAcPy_c::PoleActionStart,
4886 &dAcPy_c::PoleActionWait,
4887 &dAcPy_c::PoleActionUp,
4888 &dAcPy_c::PoleActionDown,
4889 };
4890 (this->*l_PoleActionProc[mSubstate])();
4891 float yDelta = mCcRevTotalOffsY;
4892 mPos.y += yDelta;
4893 }
4894 }
4895}
4896
4897void dAcPy_c::finalizeState_Pole() {
4899 offStatus(STATUS_97);
4901 offZPosSetNone();
4902}
4903
4904bool dAcPy_c::setKaniActionInitHangHand() {
4905 if (isCarry()) {
4906 return false;
4907 }
4908 if (
4909 !isNowBgCross(BGC_FOOT) &&
4910 mSpeed.y < 0.0f &&
4911 !isOldBgCross(BgCross2_e(BGC_CLIFF_ABOVE_1 | BGC_CLIFF_ABOVE_2)) &&
4912 isNowBgCross(BgCross2_e(BGC_CLIFF_ABOVE_1 | BGC_CLIFF_ABOVE_2))
4913 ) {
4914 mPos.y = mKaniHeight;
4915 changeState(StateID_Kani, KANI_ARG_HANG_HAND);
4916 return true;
4917 }
4918 return false;
4919}
4920
4921bool dAcPy_c::setKaniHangAction() {
4922 if (isNowBgCross(BGC_CLIFF) && mSpeed.y <= 0.0f) {
4923 if (isStatus(STATUS_A1)) {
4924 changeState(StateID_Kani, KANI_ARG_JUMP_HANG);
4925 return true;
4926 }
4927 if (isStatus(STATUS_A2)) {
4928 changeState(StateID_Kani, KANI_ARG_WALK);
4929 return true;
4930 }
4931 }
4932 return false;
4933}
4934
4935void dAcPy_c::setKaniWalkEffect() {
4936 if (m_b70 != 1) {
4937 mVec3_c efPos;
4938 mPyMdlMng.mpMdl->getJointPos(&efPos, 4);
4939 dEf::createPlayerEffect(mPlayerNo, &mLevelEf7, "Wm_mr_movecliff", 0, &efPos, nullptr, nullptr);
4940 mPyMdlMng.mpMdl->getJointPos(&efPos, 7);
4941 dEf::createPlayerEffect(mPlayerNo, &mLevelEf7, "Wm_mr_movecliff", 0, &efPos, nullptr, nullptr);
4942 }
4943}
4944
4945void dAcPy_c::setKaniHangEffect() {
4946 if (m_b70 != 1) {
4947 mVec3_c efPos;
4948 mPyMdlMng.mpMdl->getJointPos(&efPos, 11);
4949 dEf::createPlayerEffect(mPlayerNo, &mLevelEf7, "Wm_mr_movecliff", 0, &efPos, nullptr, nullptr);
4950 mPyMdlMng.mpMdl->getJointPos(&efPos, 14);
4951 dEf::createPlayerEffect(mPlayerNo, &mLevelEf7, "Wm_mr_movecliff", 0, &efPos, nullptr, nullptr);
4952 }
4953}
4954
4955void dAcPy_c::setKaniCliffCatchEffect() {
4956 static const char *scCliffCatchEffectID[] = {
4957 "Wm_mr_cliffcatch",
4958 "Wm_en_landsmoke_s"
4959 };
4960 static const float sc_cliffCatchScale[] = { 0.5f, 0.8f, 1.0f };
4961 u8 tallType = getTallType(-1);
4962 float scale = sc_cliffCatchScale[tallType];
4963 mVec3_c efSize(scale, scale, scale);
4964 mVec3_c efPos;
4965 mPyMdlMng.mpMdl->getJointPos(&efPos, 11);
4966 efPos.y = mPos.y;
4967 dEf::createPlayerEffect(mPlayerNo, scCliffCatchEffectID[m_b70], 0, &efPos, nullptr, &efSize);
4968 mPyMdlMng.mpMdl->getJointPos(&efPos, 14);
4969 efPos.y = mPos.y;
4970 dEf::createPlayerEffect(mPlayerNo, scCliffCatchEffectID[m_b70], 0, &efPos, nullptr, &efSize);
4971}
4972
4973void dAcPy_c::initializeState_Kani() {
4974 onStatus(STATUS_A8);
4975 mSpeed.y = 0.0f;
4976 m_b70 = 0;
4977 if (isNowBgCross(BGC_LIFT)) {
4978 m_b70 = 1;
4979 }
4980 m_b74 = m_b70;
4981 m_b78 = mPos.y;
4982 m_b7c = 0;
4983
4984 KaniArg_e arg = stateArg<KaniArg_e>();
4985 if (arg == KANI_ARG_WALK && mKey.buttonDown()) {
4986 arg = KANI_ARG_HANG;
4987 }
4988 switch (arg) {
4989 case KANI_ARG_WALK: setKaniAction_Walk(); break;
4990 case KANI_ARG_HANG: setKaniAction_Hang(); break;
4991 case KANI_ARG_JUMP_HANG: setKaniAction_JumpHang(); break;
4992 case KANI_ARG_WALK_FORCE: setKaniAction_Walk(); break;
4993 case KANI_ARG_HANG_UP_VINE: setKaniAction_HangUpVine(); break;
4994 case KANI_ARG_HANG_HAND: setKaniAction_HangHand(); break;
4995 }
4996}
4997
4998void dAcPy_c::finalizeState_Kani() {
4999 offStatus(STATUS_9B);
5003 offStatus(STATUS_A8);
5004 mAngle.y = getMukiAngle(mDirection);
5005 offZPosSetNone();
5006}
5007
5008void dAcPy_c::setKaniMoveSpeed(bool b) {
5009 float scale = 0.0f;
5010 int dir;
5011 if (mKey.buttonWalk(&dir)) {
5012 float f;
5013 if (isStar()) {
5014 if (mKey.buttonDush()) {
5015 f = 1.3f;
5016 } else {
5017 f = 1.05f;
5018 }
5019 } else {
5020 if (mKey.buttonDush()) {
5021 f = sGlobalData_c<dAcPy_c>::mData.mKaniSpeedRelated[1];
5022 } else {
5023 f = sGlobalData_c<dAcPy_c>::mData.mKaniSpeedRelated[0];
5024 }
5025 }
5026 scale = f * sc_DirSpeed[dir];
5027 }
5028 if (b == true) {
5029 scale *= 0.8f;
5030 } else {
5031 scale *= 1.2f;
5032 }
5033 mMaxSpeedF = scale;
5034 normalPowerSet();
5035}
5036
5037void dAcPy_c::setKaniHangStartEffect() {}
5038
5039void dAcPy_c::setKaniAction_Walk() {
5040 mAngle.y = 0;
5041 setKaniMoveSpeed(true);
5042 if (!mMaxSpeedF) {
5043 mSpeedF = 0.0f;
5044 } else if (mMaxSpeedF < 0.0f) {
5045 if (mSpeedF < mMaxSpeedF) {
5047 }
5048 } else if (mSpeedF > mMaxSpeedF) {
5050 }
5051 mSubstate = KANI_ACTION_WALK;
5052}
5053
5054void dAcPy_c::setKaniAction_Hang() {
5055 releaseCarryActor();
5056 mAngle.y = 0x8000;
5057 mSpeedF = 0.0f;
5058 mPyMdlMng.setAnm(PLAYER_ANIM_HANG_START);
5059 startPlayerVoice(VOICE_CLIFF_DOWN, 0);
5060 mSubstate = KANI_ACTION_HANG_INIT;
5062}
5063
5064void dAcPy_c::setKaniAction_JumpHang() {
5065 releaseCarryActor();
5066 mAngle.y = 0x8000;
5067 mSpeedF = 0.0f;
5068 mPyMdlMng.setAnm(PLAYER_ANIM_JUMP_HANG);
5069 setKaniCliffCatchEffect();
5070 startPlayerVoice(VOICE_CLIFF_DIVE, 0);
5071 mSubstate = KANI_ACTION_JUMP_HANG_INIT;
5072}
5073
5074void dAcPy_c::setKaniAction_HangFall() {
5075 mPyMdlMng.setAnm(PLAYER_ANIM_HANG_WAIT);
5076 mSubstate = KANI_ACTION_HANG_FALL;
5077}
5078
5079void dAcPy_c::setKaniAction_HangUp() {
5080 releaseCarryActor();
5081 mSpeedF = 0.0f;
5082 setKaniHangStartEffect();
5083 mPyMdlMng.setAnm(PLAYER_ANIM_HANG_UP);
5084 startPlayerVoice(VOICE_CLIFF_UP, 0);
5085 mSubstate = KANI_ACTION_HANG_UP;
5086}
5087
5088void dAcPy_c::setKaniAction_HangHand() {
5089 if (isNowBgCross(BGC_CLIFF_ABOVE_2)) {
5090 m_b70 = 1;
5091 }
5092 releaseCarryActor();
5093 mAngle.y = 0x8000;
5094 mSpeedF = 0.0f;
5095 mPyMdlMng.setAnm(PLAYER_ANIM_JUMP_HANG, 0.0f, 0.0f);
5096 setKaniCliffCatchEffect();
5097 mSubstate = KANI_ACTION_JUMP_HANG_INIT;
5098}
5099
5100void dAcPy_c::setKaniAction_HangUpVine() {
5101 releaseCarryActor();
5102 mSpeedF = 0.0f;
5103 mPyMdlMng.setAnm(PLAYER_ANIM_HANG_WAIT, 0.5f, 0.0f, 0.0f);
5104 mSubstate = KANI_ACTION_HANG_UP_VINE;
5105}
5106
5107void dAcPy_c::KaniAction_Walk() {
5109 onStatus(STATUS_9B);
5110 if (!isNowBgCross(BGC_CLIFF)) {
5111 changeState(StateID_Walk, BLEND_NONE);
5112 return;
5113 }
5114 if (mKey.triggerDown()) {
5115 setKaniAction_Hang();
5116 } else if (mKey.triggerJump()) {
5117 changeState(StateID_KaniJump);
5118 } else {
5119 setKaniMoveSpeed(true);
5120 if (!mSpeedF) {
5121 if (mPyMdlMng.getAnm() != PLAYER_ANIM_WALL_WAIT) {
5122 mPyMdlMng.setAnm(PLAYER_ANIM_WALL_WAIT);
5123 }
5124 } else {
5125 setKaniWalkEffect();
5126 float absSpeed = std::fabs(mSpeedF) - 0.5f;
5127 if (absSpeed < 0.0f) {
5128 absSpeed = 0.0f;
5129 }
5130 if (absSpeed > 1.0f) {
5131 absSpeed = 1.0f;
5132 }
5133 float rate = absSpeed * 2.0f + 1.0f;
5134 static const int sc_WallWalkAnm[] = { PLAYER_ANIM_WALL_WALK_L, PLAYER_ANIM_WALL_WALK_R };
5135 if (!mPyMdlMng.isAnm(sc_WallWalkAnm[mDirection])) {
5136 mPyMdlMng.setAnm(sc_WallWalkAnm[mDirection], rate, 10.0f, 0.0f);
5137 }
5138 mPyMdlMng.mpMdl->setRate(rate);
5139 if (mPyMdlMng.mpMdl->mAnm.checkFrame(1.0f)) {
5140 startSound(SE_PLY_SHUFFLE, false);
5141 }
5142 }
5143 }
5144}
5145
5146void dAcPy_c::KaniAction_HangInit() {
5148 if (mPyMdlMng.isAnmStop()) {
5149 setKaniHangStartEffect();
5150 mSubstate = KANI_ACTION_HANG;
5151 mPyMdlMng.setAnm(PLAYER_ANIM_HANG_WAIT, 0.0f, 0.0f);
5153 }
5154}
5155
5156void dAcPy_c::KaniAction_JumpHangInit() {
5158 mPyMdlMng.mpMdl->mAnm.checkFrame(3.0f);
5159 if (mPyMdlMng.mpMdl->mAnm.getFrame() > 9.0f) {
5160 mSubstate = KANI_ACTION_HANG;
5161 }
5162}
5163
5164bool dAcPy_c::checkCliffHangFootGround() {
5165 float height;
5166 if (dBc_c::checkGround(&mPos, &height, mLayer, 1, -1)) {
5167 float currHeight = mPos.y - getHangBcOffsetY();
5168 if (height > currHeight && (u8) (dBc_c::getUnitKind(mPos.x, height, mLayer) >> 16) != 8) {
5169 mPos.y = currHeight;
5170 m_60 = 10;
5171 changeState(StateID_Walk, BLEND_NONE);
5172 return true;
5173 }
5174 }
5175 return false;
5176}
5177
5178bool dAcPy_c::checkCliffHangWater() {
5179 float waterHeight;
5180 float currHeight = mPos.y - getHangBcOffsetY();
5181 u8 waterType = dBc_c::checkWater(mPos.x, currHeight, mLayer, &waterHeight);
5182 if (waterType == dBc_c::WATER_CHECK_WATER) {
5183 if (getWaterCheckPosY() - getHangBcOffsetY() <= waterHeight) {
5184 onNowBgCross(BGC_WATER_SHALLOW);
5185 mPos.y = currHeight;
5186 m_60 = 10;
5187 changeState(StateID_Swim, SWIM_ARG_CLIFF_HANG);
5188 return true;
5189 }
5190 }
5191 return false;
5192}
5193
5194void dAcPy_c::KaniAction_Hang() {
5196 if (!checkCliffHangFootGround() && !checkCliffHangWater() && !setKaniHangToVineAction()) {
5197 if (!isNowBgCross(BGC_FOOT)) {
5198 setKaniAction_HangFall();
5199 } else if (m_b74 == 1 && m_b70 == 0 && m_b7c == 1) {
5200 setKaniAction_JumpHang();
5201 } else {
5202 setKaniMoveSpeed(false);
5204 if (!mSpeedF) {
5205 if (mPyMdlMng.isAnm(PLAYER_ANIM_JUMP_HANG)) {
5206 if (mPyMdlMng.isAnmStop()) {
5207 mPyMdlMng.setAnm(PLAYER_ANIM_HANG_WAIT);
5208 }
5209 } else if (!mPyMdlMng.isAnm(PLAYER_ANIM_HANG_WAIT)) {
5210 mPyMdlMng.setAnm(PLAYER_ANIM_HANG_WAIT);
5211 }
5212 } else {
5213 setKaniHangEffect();
5214 float rate = std::fabs(mSpeedF);
5215 if (rate < 0.5f) {
5216 rate = 0.5f;
5217 }
5218 if (rate > 1.5f) {
5219 rate = 1.5f;
5220 }
5221 static const int sc_WallHangAnm[] = { PLAYER_ANIM_HANG_WALK_R, PLAYER_ANIM_HANG_WALK_L };
5222 if (!mPyMdlMng.isAnm(sc_WallHangAnm[mDirection])) {
5223 mPyMdlMng.setAnm(sc_WallHangAnm[mDirection], rate, 10.0f, 0.0f);
5224 }
5225 mPyMdlMng.mpMdl->setRate(rate);
5226 if (mPyMdlMng.mpMdl->mAnm.checkFrame(1.0f)) {
5227 startSound(SE_PLY_HANG_MOVE, false);
5228 }
5229 }
5230 int dir;
5231 if (
5232 !isNowBgCross(BGC_HEAD) &&
5233 (
5234 mKey.buttonUp() ||
5235 mKey.buttonWalk(&dir) && checkBGCrossWall(dir)
5236 )
5237 ) {
5238 setKaniAction_HangUp();
5239 }
5240 }
5241 }
5242}
5243
5244void dAcPy_c::KaniAction_HangFall() {
5246 if (!checkCliffHangFootGround() && !checkCliffHangWater()) {
5247 if (isNowBgCross(BGC_FOOT)) {
5248 setKaniAction_JumpHang();
5249 } else {
5250 setKaniMoveSpeed(false);
5252 }
5253 }
5254}
5255
5256void dAcPy_c::KaniAction_HangUp() {
5258 if (mPyMdlMng.isAnmStop()) {
5259 mPyMdlMng.setAnm(PLAYER_ANIM_WALL_WAIT, 0.0f, 0.0f);
5260 setKaniAction_Walk();
5261 }
5262}
5263
5264void dAcPy_c::KaniAction_HangUpVine() {
5265 setKaniAction_HangUp();
5266}
5267
5268void dAcPy_c::executeState_Kani() {
5269 if (checkEnableThrow()) {
5270 releaseCarryActor();
5271 return;
5272 }
5273 m_b74 = m_b70;
5274 m_b70 = 0;
5275 if (isNowBgCross(BGC_LIFT)) {
5276 m_b70 = 1;
5277 m_b7c = 0;
5278 if (m_b78 > mPos.y) {
5279 m_b7c = 1;
5280 }
5281 }
5282 offStatus(STATUS_9B);
5285 mMaxSpeedF = 0.0f;
5286 mAccelF = 0.0f;
5287 mAccelY = getGravityData()[0];
5288 maxFallSpeedSet();
5289 offZPosSetNone();
5290 if (mSubstate != KANI_ACTION_WALK) {
5291 setZPosition(3200.0f);
5292 }
5293 typedef void (dAcPy_c::*KaniActionProc_t)();
5294 static KaniActionProc_t l_KaniActionProc[] = {
5295 &dAcPy_c::KaniAction_Walk,
5296 &dAcPy_c::KaniAction_HangInit,
5297 &dAcPy_c::KaniAction_JumpHangInit,
5298 &dAcPy_c::KaniAction_Hang,
5299 &dAcPy_c::KaniAction_HangFall,
5300 &dAcPy_c::KaniAction_HangUp,
5301 &dAcPy_c::KaniAction_HangUpVine,
5302 };
5303 (this->*l_KaniActionProc[mSubstate])();
5304 m_b78 = mPos.y;
5305}
5306
5307void dAcPy_c::setCatchRopeSE() {
5308 switch (m_914) {
5309 case 0:
5310 case 2:
5311 startSound(SE_PLY_CATCH_ROPE, false);
5312 break;
5313 default:
5314 startSound(SE_PLY_CATCH_KUSARI, false);
5315 break;
5316 }
5317 startPlayerVoice(VOICE_ROPE_CATCH, 0);
5318}
5319
5320void dAcPy_c::setClimbRopeSE() {
5321 switch (m_914) {
5322 case 0:
5323 case 2:
5324 startSound(SE_PLY_CLIMB_ROPE, false);
5325 break;
5326 default:
5327 startSound(SE_PLY_CLIMB_KUSARI, false);
5328 break;
5329 }
5330}
5331
5332void dAcPy_c::setSlideRopeSE() {
5333 switch (m_914) {
5334 case 0:
5335 case 2:
5336 holdSound(SE_PLY_SLIDE_ROPE, false);
5337 break;
5338 default:
5339 holdSound(SE_PLY_SLIDE_KUSARI, false);
5340 break;
5341 }
5342}
5343
5344void dAcPy_c::setRopeHasigoSE() {
5345 if (mPyMdlMng.mpMdl->mAnm.checkFrame(10.0f) || mPyMdlMng.mpMdl->mAnm.checkFrame(30.0f)) {
5346 startSound(SE_PLY_FOOTNOTE_HASHIGO_NAWA, false);
5347 }
5348}
5349
5350void dAcPy_c::releasePoleCheck() {
5351 mPc.release();
5352 mPc.m_2d = 0;
5353}
5354
5355bool dAcPy_c::setTarzanRopeAction() {
5356 if (isCarry()) {
5357 return false;
5358 }
5359 if (mTarzanRopeCooldown != 0) {
5360 return false;
5361 }
5362 if (isStatus(STATUS_9C) && mPc.check(0)) {
5363 if (mPc.mpCtr->m_20 == 3) {
5364 if (mPos.y + mCenterOffs.y < mPc.mpCtr->m_28->y) {
5365 changeState(StateID_TarzanRope, (void *) 1);
5366 return true;
5367 }
5368 } else {
5369 changeState(StateID_TarzanRope, (void *) 0);
5370 return true;
5371 }
5372 releasePoleCheck();
5373 }
5374 if (isStatus(STATUS_A3) && mKey.buttonDown() && mPc.check(0)) {
5375 if (mPc.mpCtr->m_20 == 3) {
5376 changeState(StateID_TarzanRope, (void *) 2);
5377 return true;
5378 }
5379 releasePoleCheck();
5380 }
5381 return false;
5382}
5383
5384void dAcPy_c::initializeState_TarzanRope() {
5385 onStatus(STATUS_97);
5386 onStatus(STATUS_7F);
5387 onStatus(STATUS_TARZAN_ROPE);
5388 mAccelY = 0.0f;
5389 mSpeedF = 0.0f;
5390 mAccelF = 0.0f;
5391 mMaxSpeedF = 0.0f;
5392 mSpeed.x = 0.0f;
5393 mSpeed.y = 0.0f;
5394 m_918 = 0.0f;
5395 setZPositionDirect(400.0f);
5396 switch ((int) mStateArg) {
5397 case 0:
5398 mAngle.y = getBesideMukiAngle(mDirection);
5399 mPyMdlMng.setAnm(PLAYER_ANIM_TREE_START);
5400 if (mPc.mpCtr->m_20 == 2) {
5401 m_914 = 1;
5402 } else {
5403 m_914 = 0;
5404 }
5405 mSubstate = 0;
5406 setCatchRopeSE();
5407 break;
5408 case 1:
5409 mAngle.y = 0x8000;
5410 m_914 = 2;
5411 setTarzanRopeActionHasigoMove();
5412 setCatchRopeSE();
5413 break;
5414 case 2:
5415 offStatus(STATUS_TARZAN_ROPE);
5416 releasePoleCheck();
5417 mAngle.y = 0x8000;
5418 mPyMdlMng.setAnm(PLAYER_ANIM_HANG_START);
5419 startPlayerVoice(VOICE_CLIFF_DOWN, 0);
5420 m_914 = 2;
5421 mSubstate = 5;
5422 }
5423}
5424
5425void dAcPy_c::finalizeState_TarzanRope() {
5426 offStatus(STATUS_97);
5427 offStatus(STATUS_7F);
5428 offStatus(STATUS_TARZAN_ROPE);
5429 mPc.release();
5430 m_1594 = 0.0f;
5431 m_1598 = 0.0f;
5432 mAngle.x = 0;
5433 mAngle.z = 0,
5434 offZPosSetNone();
5435}
5436
5437bool dAcPy_c::setTarzanRopeJump() {
5438 if (!mKey.triggerShakeJump() && !mKey.triggerJump()) {
5439 return false;
5440 }
5441 float jumpSpeed = sc_JumpSpeed;
5442 float h = 0.0f;
5443 if (!isNowBgCross(BGC_HEAD)) {
5444 h = mPc.getPos().x;
5445 if (mKey.buttonLeft()) {
5446 h -= 1.5f;
5447 } else if (mKey.buttonRight()) {
5448 h += 1.5f;
5449 }
5450 if (h < 0.0f) {
5451 jumpSpeed = -4.0f;
5452 if (h < -4.0f) {
5453 h = -4.0f;
5454 } else if (h > -0.5f) {
5455 h = -0.5f;
5456 }
5457 } else if (h > 0.0f) {
5458 jumpSpeed = 4.0f;
5459 if (h > 4.0f) {
5460 h = 4.0f;
5461 } else if (h < 0.5f) {
5462 h = 0.5f;
5463 }
5464 } else {
5465 h = sc_DirSpeed[mDirection] * getSpeedData()->mLowSpeed;
5466 }
5467 jumpSpeed = mPc.getPos().y;
5468 }
5469 if (setRideOffPlayerJump(jumpSpeed, h)) {
5470 startPlayerVoice(VOICE_ROPE_RELEASE, 0);
5471 if (h * sc_DirSpeed[mDirection] < 0.0f) {
5472 mDirection ^= 1;
5473 }
5474 mNoGravityTimer = 10;
5475 return true;
5476 } else {
5477 if (mKey.triggerJump()) {
5478 startPlayerVoice(VOICE_ROPE_RELEASE, 0);
5479 if (h * sc_DirSpeed[mDirection] < 0.0f) {
5480 mDirection ^= 1;
5481 }
5482 mNoGravityTimer = 10;
5483 mSpeedF = h;
5484 jmpInf_c jump(jumpSpeed, 1, BLEND_DEFAULT);
5485 changeState(StateID_Jump, &jump);
5486 onStatus(STATUS_88);
5487 return true;
5488 }
5489 }
5490 return false;
5491}
5492
5493bool dAcPy_c::updateRopeAngle() {
5494 m_906 = m_904;
5495 m_904 = mPc.getAngle();
5496 m_902 = m_900;
5497 if (mPc.mpCtr != nullptr) {
5498 if (mPc.mpCtr->m_20 == 1 || mPc.mpCtr->m_20 == 2) {
5499 m_900 = mPc.mpCtr->m_34[mPlayerNo];
5500 return true;
5501 }
5502 }
5503 return false;
5504}
5505
5506void dAcPy_c::setRopeSwingAnm(float a, float b) {
5507 mPyMdlMng.mpMdl->mCurrAnmID = PLAYER_ANIM_WALK;
5508 mPyMdlMng.setAnm(PLAYER_ANIM_ROPE_SWING, a, 10.0f, b);
5509}
5510
5511bool dAcPy_c::checkStartSwingUp() {
5512 int baseAngle = m_900;
5513 int absAngle = abs(baseAngle);
5514 if (absAngle > 128 && absAngle < abs(m_902)) {
5515 if (sc_DirSpeed[mDirection] * baseAngle >= 0.0f) {
5516 m_90c = ROPE_SWING_1;
5517 setRopeSwingAnm(1.0f, 1.0f);
5518 return true;
5519 }
5520 }
5521 return false;
5522}
5523
5524bool dAcPy_c::checkStartSwingDown() {
5525 int baseAngle = m_900;
5526 int absAngle = abs(baseAngle);
5527 if (absAngle > 128 && absAngle < abs(m_902)) {
5528 if (sc_DirSpeed[mDirection] * baseAngle <= 0.0f) {
5529 int dir;
5530 bool ok = mKey.buttonWalk(&dir) && dir != mDirection;
5531 if (ok) {
5532 setRopeSwingAnm(1.0f, 64.0f);
5533 m_90c = ROPE_SWING_7;
5534 return true;
5535 }
5536 m_90c = ROPE_SWING_0;
5537 }
5538 }
5539 return false;
5540}
5541
5542void dAcPy_c::updateRopeSwingAnm() {
5543 if (updateRopeAngle()) {
5544 switch (m_90c) {
5545 case ROPE_SWING_0:
5546 checkStartSwingUp();
5547 break;
5548 case ROPE_SWING_1:
5549 if (mPyMdlMng.mpMdl->mAnm.checkFrame(32.0f)) {
5550 mPyMdlMng.mpMdl->setRate(0.0f);
5551 m_90c = ROPE_SWING_2;
5552 }
5553 // fallthrough
5554 case ROPE_SWING_2:
5555 if (m_900 * m_902 <= 0) {
5556 setRopeSwingAnm(1.0f, 32.0f);
5557 m_90c = ROPE_SWING_3;
5558 }
5559 break;
5560 case ROPE_SWING_3:
5561 if (mPyMdlMng.mpMdl->mAnm.checkFrame(64.0f)) {
5562 mPyMdlMng.mpMdl->setRate(0.0f);
5563 m_90c = ROPE_SWING_4;
5564 }
5565 // fallthrough
5566 case ROPE_SWING_4:
5567 checkStartSwingDown();
5568 break;
5569 case ROPE_SWING_7:
5570 if (mPyMdlMng.mpMdl->mAnm.checkFrame(96.0f)) {
5571 mPyMdlMng.mpMdl->setRate(0.0f);
5572 m_90c = ROPE_SWING_8;
5573 }
5574 // fallthrough
5575 case ROPE_SWING_8:
5576 if (m_900 * m_902 <= 0) {
5577 setRopeSwingAnm(1.0f, 96.0f);
5578 m_90c = ROPE_SWING_10;
5579 }
5580 break;
5581 case ROPE_SWING_10:
5582 if (mPyMdlMng.isAnmStop()) {
5583 m_90c = ROPE_SWING_0;
5584 }
5585 checkStartSwingUp();
5586 break;
5587 case ROPE_SWING_5:
5588 if (mPyMdlMng.mpMdl->mAnm.checkFrame(86.0f)) {
5589 mPyMdlMng.mpMdl->setRate(0.0f);
5590 m_90c = ROPE_SWING_6;
5591 }
5592 // fallthrough
5593 case ROPE_SWING_6:
5594 if (m_900 * m_902 <= 0) {
5595 setRopeSwingAnm(-0.5f, 86.0f);
5596 m_90c = ROPE_SWING_9;
5597 }
5598 break;
5599 case ROPE_SWING_9:
5600 if (mPyMdlMng.mpMdl->mAnm.checkFrame(64.0f)) {
5601 m_90c = ROPE_SWING_0;
5602 }
5603 checkStartSwingUp();
5604 break;
5605 }
5606 } else {
5607 m_90c = ROPE_SWING_0;
5608 }
5609 if (m_90c == ROPE_SWING_0) {
5610 mPyMdlMng.setAnm(PLAYER_ANIM_TREE_WAIT, 10.0f, 0.0f);
5611 }
5612}
5613
5614void dAcPy_c::TarzanRopeActionStart() {
5615 if (mPyMdlMng.isAnmStop()) {
5616 setTarzanRopeActionWait();
5617 }
5618}
5619
5620void dAcPy_c::setTarzanRopeActionWait() {
5621 mSubstate = 1;
5622 m_918 = 0;
5623 updateRopeAngle();
5624 m_906 = m_904;
5625 m_902 = m_900;
5626 m_90c = ROPE_SWING_0;
5627 m_908 = 0;
5628}
5629
5630void dAcPy_c::TarzanRopeActionWait() {
5631 turnBesideAngle();
5632 updateRopeSwingAnm();
5633 if (!(mPc.m_2a & 4) && mKey.buttonDown()) {
5634 setTarzanRopeActionDown();
5635 } else if (!(mPc.m_2a & 2) && mKey.buttonUp()) {
5636 setTarzanRopeActionUp();
5637 }
5638}
5639
5640void dAcPy_c::setTarzanRopeActionUp() {
5641 mSubstate = 2;
5642 mPyMdlMng.setAnm(PLAYER_ANIM_TREE_CLIMB);
5643}
5644
5645void dAcPy_c::TarzanRopeActionUp() {
5646 turnBesideAngle();
5647 if (m_914 == 0) {
5648 setIvyHangEffect();
5649 }
5650 if (mPyMdlMng.mpMdl->mAnm.checkFrame(1.0f)) {
5651 setClimbRopeSE();
5652 }
5653 if (mKey.buttonDush()) {
5654 mPyMdlMng.mpMdl->setRate(1.875f);
5655 m_918 = 1.5f;
5656 } else {
5657 mPyMdlMng.mpMdl->setRate(1.5f);
5658 m_918 = 1.0f;
5659 }
5660 if (!(mPc.m_2a & 4) && mKey.buttonDown()) {
5661 setTarzanRopeActionDown();
5662 } else if (!mKey.buttonUp()) {
5663 setTarzanRopeActionWait();
5664 }
5665}
5666
5667void dAcPy_c::setTarzanRopeActionDown() {
5668 mSubstate = 3;
5669 mPyMdlMng.setAnm(PLAYER_ANIM_TREE_POSE);
5670}
5671
5672void dAcPy_c::TarzanRopeActionDown() {
5673 turnBesideAngle();
5674 if (m_914 == 0) {
5675 setIvyHangEffect();
5676 }
5677 setSlideRopeSE();
5678 m_918 = -2.0f;
5679 if (!(mPc.m_2a & 2) && mKey.buttonUp()) {
5680 setTarzanRopeActionUp();
5681 } else if (!mKey.buttonDown()) {
5682 setTarzanRopeActionWait();
5683 }
5684}
5685
5686void dAcPy_c::setTarzanRopeActionHasigoMove() {
5687 mSubstate = 4;
5688}
5689
5690void dAcPy_c::TarzanRopeActionHasigoMove() {
5691 if (mKey.buttonUp() && (mPc.m_2a & 2)) {
5692 setTarzanRopeActionHasigoHangUp();
5693 return;
5694 }
5695 float f1 = mKey.buttonDush() ? 1.5f : 1.0f;
5696 float f2 = mKey.buttonDush() ? 1.875f : 1.5f;
5697 if (mKey.buttonUp() && !(mPc.m_2a & 2)) {
5698 m_918 = f1;
5699 mPyMdlMng.setAnm(PLAYER_ANIM_NET_WALK1, f2, 0.0f, 0.0f);
5700 setRopeHasigoSE();
5701 } else if (mKey.buttonDown() && !(mPc.m_2a & 4)) {
5702 m_918 = -f1;
5703 mPyMdlMng.setAnm(PLAYER_ANIM_NET_WALK1, -f2, 0.0f, 0.0f);
5704 setRopeHasigoSE();
5705 } else {
5706 m_918 = 0.0f;
5707 mPyMdlMng.setAnm(PLAYER_ANIM_NET_WAIT);
5708 }
5709}
5710
5711void dAcPy_c::TarzanRopeActionHasigoHangDown() {
5712 if (!mPyMdlMng.isAnmStop()) {
5713 return;
5714 }
5715 mPyMdlMng.setAnm(PLAYER_ANIM_NET_WAIT, 0.0f, 0.0f);
5716 mPos.y -= getHangBcOffsetY();
5717 m_60 = 10;
5718 onStatus(STATUS_TARZAN_ROPE);
5719 setTarzanRopeActionHasigoMove();
5720 if (!mPc.check(1)) {
5722 mPyMdlMng.setAnm(PLAYER_ANIM_JUMP2, 0.0f, 0.0f);
5723 changeState(StateID_Fall, true);
5724 }
5725}
5726
5727void dAcPy_c::setTarzanRopeActionHasigoHangUp() {
5728 mVec3_c pos = mPos;
5729 pos.y += getHangBcOffsetY() + 8.0f;
5730 float h;
5731 if (dBc_c::checkGround(&pos, &h, mLayer, 1, -1)) {
5732 if (mPos.y < h) {
5733 mPos.y = h;
5734 }
5735 }
5736 m_60 = 10;
5737 mSubstate = 6;
5738 m_91c = 0;
5739 mPyMdlMng.setAnmOnlyRate(PLAYER_ANIM_HANG_WAIT, 0.0f, 0.0f);
5740 startPlayerVoice(VOICE_CLIFF_UP, 0);
5741 offStatus(STATUS_TARZAN_ROPE);
5742 releasePoleCheck();
5743}
5744
5745void dAcPy_c::TarzanRopeActionHasigoHangUp() {
5746 switch (m_91c) {
5747 case 0:
5748 mPyMdlMng.setAnm(PLAYER_ANIM_HANG_UP);
5749 m_91c = 1;
5750 break;
5751 case 1:
5752 if (mPyMdlMng.isAnmStop()) {
5753 mPyMdlMng.setAnmOnlyRate(PLAYER_ANIM_WALL_WAIT, 0.0f, 0.0f);
5754 mAngle.y = 0;
5755 m_91c = 2;
5756 }
5757 break;
5758 case 2:
5759 changeState(StateID_Walk, BLEND_DEFAULT);
5760 break;
5761 }
5762}
5763
5764void dAcPy_c::executeState_TarzanRope() {
5765 typedef void (dAcPy_c::*TarzanRopeActionProc_t)();
5766 static TarzanRopeActionProc_t l_TarzanRopeActionProc[] = {
5767 &dAcPy_c::TarzanRopeActionStart,
5768 &dAcPy_c::TarzanRopeActionWait,
5769 &dAcPy_c::TarzanRopeActionUp,
5770 &dAcPy_c::TarzanRopeActionDown,
5771 &dAcPy_c::TarzanRopeActionHasigoMove,
5772 &dAcPy_c::TarzanRopeActionHasigoHangDown,
5773 &dAcPy_c::TarzanRopeActionHasigoHangUp
5774 };
5775 if (!isStatus(STATUS_TARZAN_ROPE)) {
5776 (this->*l_TarzanRopeActionProc[mSubstate])();
5777 } else if (isNowBgCross(BgCross1_e(BGC_SIDE_LIMIT_L | BGC_SIDE_LIMIT_R)) || mPc.mpCtr == nullptr) {
5778 changeState(StateID_Fall, false);
5779 } else {
5780 s16 ang = mPc.getAngle();
5781 if (m_914 == 0 || m_914 == 1) {
5782 if (mDirection == DIR_LR_L) {
5783 ang = -mPc.getAngle();
5784 }
5785 mAngle.x = ang;
5786 float f = -2.5f;
5787 if (mPowerup == POWERUP_NONE) {
5788 f = -1.5f;
5789 }
5790 m_1594 = f * mAng(ang).cos() * mAng(mAngle.y).sin();
5791 m_1598 = f * mAng(ang).sin();
5792 } else {
5793 mAngle.z = -ang;
5794 }
5795 if (!setTarzanRopeJump()) {
5796 (this->*l_TarzanRopeActionProc[mSubstate])();
5797 mPc.move(getCcRevOffsY() + m_918);
5798 if (mPc.m_2a & 1) {
5799 changeState(StateID_Fall, false);
5800 }
5801 }
5802 }
5803}
5804
5805void dAcPy_c::startQuakeAction(QuakeMode_e mode) {
5806 setQuakeActionLocal(0, mode);
5807 mSubstateValue = 1;
5808}
5809
5810void dAcPy_c::setQuakeAction(int i, QuakeMode_e mode) {
5811 setQuakeActionLocal(i, mode);
5812 mSubstateValue = 0;
5813}
5814
5815void dAcPy_c::setQuakeActionLocal(int i, QuakeMode_e mode) {
5816 if (!isDemo() && isNowBgCross(BGC_FOOT) && !isState(StateID_Quake)) {
5817 changeState(StateID_Quake, (void *) mode);
5818 mSubstateTimer = i;
5819 }
5820}
5821
5822void dAcPy_c::endQuakeAction() {
5823 if (isState(StateID_Quake)) {
5824 changeState(StateID_Walk, BLEND_DEFAULT);
5825 }
5826}
5827
5828void dAcPy_c::initializeState_Quake() {
5829 mSpeedF = 0.0f;
5830 mMaxSpeedF = 0.0f;
5831 mAccelY = 0.0f;
5832 mSpeed.y = 0.0f;
5833 mAngle.y = 0.0f;
5834 mPyMdlMng.setAnm(PLAYER_ANIM_E_SHOCK);
5836 mKey.onStatus(dAcPyKey_c::STATUS_NO_INPUT);
5837 startPlayerVoice(VOICE_QUAKE, 0);
5838 startQuakeShock(dQuake_c::TYPE_6);
5839 m_1040 = 8;
5840 mSubstate = (int) mStateArg;
5841}
5842
5843void dAcPy_c::finalizeState_Quake() {
5844 mKey.offStatus(dAcPyKey_c::STATUS_NO_INPUT);
5845 mAngle.y = getMukiAngle(mDirection);
5847}
5848
5849void dAcPy_c::executeState_Quake() {
5850 if (m_1040 != 0) {
5851 m_1040--;
5852 }
5853 if (m_1040 == 0) {
5854 m_1040 = 5;
5855 startQuakeShock(dQuake_c::TYPE_8);
5856 }
5857 setQuakeNumbEffect();
5858 if (mSubstateValue == 0 && mSubstateTimer == 0) {
5859 changeState(StateID_Walk, BLEND_DEFAULT);
5860 }
5861}
5862
5863void dAcPy_c::setQuakeNumbEffect() {
5864 mVec3_c center = getCenterPos();
5865 static const float sc_QuakeNumbScale[] = { 0.6f, 0.8f, 1.0f };
5866 u8 tallType = getTallType(-1);
5867 float scale = sc_QuakeNumbScale[tallType];
5868 mVec3_c size(scale, scale, scale);
5869 static const char *sc_QuakeEffectID[] = {
5870 "Wm_mr_brosquake",
5871 "Wm_mr_quakewait"
5872 };
5873 dEf::createPlayerEffect(mPlayerNo, &mSmokeEffect, sc_QuakeEffectID[mSubstate], 0, &center, nullptr, &size);
5874}
5875
5876void dAcPy_c::initializeState_ElecShock() {
5877 initElecShock();
5878 mSpeedF = 0.0f;
5879 mMaxSpeedF = 0.0f;
5880 mAccelY = 0.0f;
5881 mSpeed.y = 0.0f;
5882 mAngle.y = 0;
5884 mKey.onStatus(dAcPyKey_c::STATUS_NO_INPUT);
5885}
5886
5887void dAcPy_c::finalizeState_ElecShock() {
5889 mKey.offStatus(dAcPyKey_c::STATUS_NO_INPUT);
5890}
5891
5892void dAcPy_c::executeState_ElecShock() {
5893 if (!executeElecShock()) {
5894 changeState(StateID_Walk, BLEND_DEFAULT);
5895 mPyMdlMng.setAnm(PLAYER_ANIM_E_SHOCK);
5896 setDamage2(nullptr, DAMAGE_BG);
5897 }
5898}
5899
5900void dAcPy_c::initElecShock() {
5901 startPlayerVoice(VOICE_DAMAGE_ELEC, 0);
5902 startSound(SE_PLY_TOUCH_BIRI, false);
5903 mPyMdlMng.setAnm(PLAYER_ANIM_E_SHOCK);
5904 mSubstateTimer = 60;
5905}
5906
5907bool dAcPy_c::executeElecShock() {
5908 setElecEffect();
5909 return mSubstateTimer != 0;
5910}
5911
5912void dAcPy_c::setElecEffect() {
5913 mVec3_c efPos;
5914 mPyMdlMng.mpMdl->getJointPos(&efPos, 1);
5915 float s = mPyMdlMng.getSomeScale();
5916 mVec3_c efScale(s, s, s);
5917 int shockType = 0;
5918 if (mPowerup == POWERUP_MINI_MUSHROOM || mPowerup == POWERUP_NONE) {
5919 shockType = 1;
5920 }
5921 static const char *sc_elecEffectID[] = {
5922 "Wm_mr_electricshock",
5923 "Wm_mr_electricshock_s"
5924 };
5925 dEf::createPlayerEffect(mPlayerNo, &mSmokeEffect, sc_elecEffectID[shockType], 0, &efPos, nullptr, &efScale);
5926}
5927
5928bool dAcPy_c::setFlyDamageAction(int action, dActor_c *actor) {
5929 if (isState(StateID_FlyDamage)) {
5930 return false;
5931 }
5932 bool changeParam = false;
5933 if (actor != nullptr) {
5934 if (action == 4) {
5935 mPos.y += 12.0f;
5936 mPos.x = mPos.x - 4.0f * sc_DirSpeed[mDirection];
5937 } else {
5938 switch ((u32) actor->mKind) {
5939 case STAGE_ACTOR_PLAYER:
5940 case STAGE_ACTOR_ENEMY:
5941 if (actor->mProfName == fProfile::EN_SLIP_PENGUIN2) {
5942 bool dir = 0;
5943 if (actor->mSpeed.x < 0.0f) {
5944 dir = 1;
5945 }
5946 if (dir == mDirection && (actor->mLastPos.x - mLastPos.x) * sc_DirSpeed[mDirection] < 0.0f) {
5947 changeParam = true;
5948 }
5949 } else if ((actor->mLastPos.x - mLastPos.x) * sc_DirSpeed[mDirection] < 0.0f) {
5950 changeParam = true;
5951 }
5952 break;
5953 default:
5954 if (mDirection == actor->mDirection) {
5955 changeParam = true;
5956 }
5957 }
5958 }
5959 }
5960 int isAction6 = 0;
5961 u32 finalChangeParam = 0;
5962 if (action == 2) {
5963 finalChangeParam = 2;
5964 } else if (action == 3 || action == 4) {
5965 finalChangeParam = 4;
5966 } else if (action == 5) {
5967 finalChangeParam = 0;
5968 } else if (action == 6) {
5969 finalChangeParam = 0;
5970 isAction6 = 1;
5971 }
5972 finalChangeParam = (finalChangeParam + changeParam) & 0xFF;
5973 if (isAction6 == 1) {
5974 finalChangeParam |= 0x100;
5975 }
5976 changeState(StateID_FlyDamage, (void *) finalChangeParam);
5977 return true;
5978}
5979
5980void dAcPy_c::initializeState_FlyDamage() {
5981 static const u8 sc_DamageAnmID[] = {
5982 PLAYER_ANIM_DAM_F, PLAYER_ANIM_DAM_B,
5983 PLAYER_ANIM_DOW_F, PLAYER_ANIM_DOW_B,
5984 PLAYER_ANIM_DOW_F, PLAYER_ANIM_DOW_B,
5985 PLAYER_ANIM_DOW_F
5986 };
5987 m_103c = ((int) mStateArg) & 0xFF;
5988 u32 crash = ((int) mStateArg) & 0x100;
5989 mPyMdlMng.setAnm(sc_DamageAnmID[m_103c], 0.0f, 0.0f);
5990 if (crash == 0) {
5991 startPlayerVoice(VOICE_HIP_ATTACKED, 0);
5992 if (m_103c == 0 || m_103c == 1) {
5993 startSound(SE_PLY_CRASH_S, false);
5994 } else {
5995 startSound(SE_PLY_CRASH_L, false);
5996 }
5997 }
5998 if (m_103c == 0 || m_103c == 1) {
5999 float speed1 = sc_DirSpeed[(m_103c ^ 1) & 1];
6000 float speed2 = getDirSpeed();
6001 speed2 *= sGlobalData_c<dAcPy_c>::mData.f8;
6002 mSpeedF = speed1 * speed2;
6003 mSpeed.y = 0.0f;
6004 mSubstate = 5;
6005 } else {
6006 mKey.onStatus(dAcPyKey_c::STATUS_DISABLE_LR);
6007 float speed = sc_DirSpeed[mDirection] * sc_DirSpeed[(m_103c ^ 1) & 1];
6008 mSubstate = 0;
6009 if (mPowerup == POWERUP_MINI_MUSHROOM) {
6010 mPyMdlMng.setAnm(PLAYER_ANIM_STAR_ROLL_DUPLICATE);
6011 mSubstateTimer = 30;
6012 if (speed < 0.0f) {
6013 mDirection = DIR_LR_L;
6014 } else {
6015 mDirection = DIR_LR_R;
6016 }
6017 }
6018 switch (m_103c) {
6019 case 2:
6020 case 3:
6023 break;
6024 case 4:
6025 case 5:
6026 if (isNowBgCross(BGC_FOOT)) {
6028 } else {
6029 mSpeedF = speed;
6030 }
6032 break;
6033 case 6:
6034 mSpeedF = speed;
6035 mSpeed.y = 2.0f;
6036 break;
6037 }
6038 }
6040 mAccelY = getGravityData()[0];
6041 mMaxFallSpeed = sc_MaxFallSpeed;
6042 mAngle.y = getMukiAngle(mDirection);
6043}
6044
6045void dAcPy_c::finalizeState_FlyDamage() {
6046 offStatus(STATUS_9B);
6047 offStatus(STATUS_9C);
6048 offStatus(STATUS_9D);
6049 offStatus(STATUS_A1);
6050 mKey.offStatus(dAcPyKey_c::STATUS_DISABLE_LR);
6052}
6053
6054void dAcPy_c::executeState_FlyDamage() {
6055 int dir;
6056 mAccelF = 0.08f;
6057 if (mSubstate == 5 && mKey.buttonWalk(&dir) && mSpeedF * sc_DirSpeed[dir] < 0.0f) {
6058 mAccelF = 0.15f;
6059 }
6060
6061 icePowerChange(0);
6063 if (isNowBgCross(BGC_FOOT)) {
6064 mMaxSpeedF = 0.0f;
6065 }
6066 static const u8 sc_damageStopFrame[] = { 0, 0, 9, 10, 9, 10, 9 };
6067 switch (mSubstate) {
6068 case 0:
6069 onStatus(STATUS_A1);
6070 if (mPowerup != POWERUP_MINI_MUSHROOM) {
6071 mSubstate = 2;
6072 } else {
6073 mSubstate = 1;
6074 }
6075 break;
6076 case 1:
6077 if (mSubstateTimer == 0 || mPowerup != POWERUP_MINI_MUSHROOM) {
6078 changeState(StateID_Fall, false);
6079 }
6080 break;
6081 case 2:
6082 if (mPyMdlMng.mpMdl->mAnm.getFrame() >= sc_damageStopFrame[m_103c]) {
6083 mPyMdlMng.mpMdl->setRate(0.0f);
6084 mSubstate = 3;
6085 mSubstateValue = 10;
6086 }
6087 break;
6088 case 3:
6089 if (isNowBgCross(BGC_FOOT)) {
6090 if (mSubstateValue != 0) {
6092 }
6093 if (mSubstateValue == 0) {
6094 onStatus(STATUS_9B);
6095 onStatus(STATUS_9C);
6096 onStatus(STATUS_9D);
6097 if (checkJumpTrigger()) {
6098 break;
6099 }
6100 }
6101 if (std::fabs(mSpeedF) < 0.5f) {
6102 mPyMdlMng.mpMdl->setRate(1.0f);
6103 mSubstate = 4;
6104 }
6105 }
6106 break;
6107 case 4:
6108 if (!isNowBgCross(BGC_FOOT)) {
6109 changeState(StateID_Fall, false);
6110 } else if (!checkJumpTrigger() && mPyMdlMng.isAnmStop()) {
6111 changeState(StateID_Walk, BLEND_DEFAULT);
6112 }
6113 break;
6114 case 5:
6115 if (!isNowBgCross(BGC_FOOT)) {
6116 if (mPyMdlMng.mpMdl->mAnm.getFrame() > 17.0f) {
6117 mPyMdlMng.setAnm(PLAYER_ANIM_JUMP2, 10.0f, 0.0f);
6118 changeState(StateID_Fall, false);
6119 }
6120 } else if (mPyMdlMng.mpMdl->mAnm.getFrame() > 17.0f) {
6121 if (checkJumpTrigger()) {
6122 break;
6123 }
6124 if (mKey.buttonWalk(nullptr)) {
6125 changeState(StateID_Walk, BLEND_DEFAULT);
6126 break;
6127 }
6128 }
6129 if (mPyMdlMng.isAnmStop()) {
6130 changeState(StateID_Walk, BLEND_DEFAULT);
6131 }
6132 break;
6133 }
6134}
6135
6136void dAcPy_c::setBreakBalloonJump(u8 playerNo, short angle) {
6138 startPlayerVoice(VOICE_HUKKATSU, 0);
6139 startSound(SE_PLY_BALLOON_BRAKE, false);
6140 dQuake_c::m_instance->shockMotor(mPlayerNo, dQuake_c::TYPE_4, 0, false);
6141 mJumpDaiFallTimer = 30;
6142 mTimer_ce8 = 30;
6143 mCcRevDisabledTimer = 30;
6144 if (isNowBgCross(BGC_WATER_SHALLOW)) {
6145 changeState(StateID_Swim, SWIM_ARG_INITIAL);
6146 float cos = mAng(angle).cos();
6147 float sin = mAng(angle).sin();
6148 setSwimSpeed(cos * 2.0f, sin * 2.0f);
6149 } else {
6150 float sin = mAng(angle).sin() * 4.0f;
6151 float cos = mAng(angle).cos() * sc_JumpSpeed;
6152 if (cos < 0.0f) {
6153 cos = 0.0f;
6154 }
6155 setJump(cos, sin, true, 1, 0);
6156 }
6157}
6158
6159void dAcPy_c::setDrawBalloonInPlayer(mVec3_c &pos) {
6160 if (!isStatus(STATUS_53)) {
6161 return;
6162 }
6163 onStatus(STATUS_54);
6164 static const float scBalloonOffsetY[] = {
6165 0.0f, -4.0f, -4.0f, 4.0f, -6.0f, -2.0f, -4.0f
6166 };
6167 pos.y += scBalloonOffsetY[mPowerup];
6168 mPos = mLastPos = pos;
6169}
6170
6171bool dAcPy_c::isNotBalloonCourse() {
6172 return daPyMng_c::mRest[daPyMng_c::mPlayerType[mPlayerNo]] <= 0;
6173}
6174
6175void dAcPy_c::initializeState_Balloon() {
6176 clearJumpActionInfo(1);
6177 releaseCarryActor();
6178 endStar();
6179 mActorProperties |= BIT_FLAG(6);
6180 mPyMdlMng.setAnm(PLAYER_ANIM_BALLOON_WAIT);
6181 onStatus(STATUS_7E);
6182 onStatus(STATUS_7A);
6183 onStatus(STATUS_AA);
6188 mAccelY = 0.0f;
6189 mMaxFallSpeed = sc_MaxFallSpeed;
6190 mAccelF = 0.0f;
6191 mSpeed.y = 0.0f;
6192 mSpeedF = 0.0f;
6193 mSubstate = (int) mStateArg;
6194 switch (mSubstate) {
6195 case 0:
6196 mSubstateTimer = 150;
6197 if (isNotBalloonCourse()) {
6198 mSubstate = 4;
6199 }
6200 break;
6201 case 3:
6202 startSound(SE_PLY_BALLOON_SELF, false);
6203 break;
6204 }
6205 m_12b8 = 0;
6206 daPyMng_c::decNum(mPlayerNo);
6207 if (daPyMng_c::mNum == 0) {
6208 onStatus(STATUS_57);
6209 mAllBalloonFadeTimer = 210;
6210 daPyMng_c::mAllBalloon = true;
6211 }
6212 if (mPlayerType == PLAYER_MARIO && mPyMdlMng.mpMdl->m_151 == 0) {
6213 ((dMarioMdl_c *) mPyMdlMng.mpMdl)->fn_800cab00(0);
6214 }
6215 if (mPowerup != POWERUP_NONE && mPowerup != POWERUP_MINI_MUSHROOM) {
6216 mAmiRelated2 = 0.9f;
6217 }
6218 setScrollMode(1);
6219 setZPosition(8000.0f);
6220 mPlayerOrchestra.init(mPlayerNo);
6221}
6222
6223void dAcPy_c::finalizeState_Balloon() {
6224 mActorProperties &= ~BIT_FLAG(6);
6225 offStatus(STATUS_53);
6226 offStatus(STATUS_54);
6227 offStatus(STATUS_95);
6228 offStatus(STATUS_7E);
6229 offStatus(STATUS_7A);
6230 offStatus(STATUS_AA);
6234 mCc.mCcData.mStatus &= ~CC_STATUS_NO_PASS_INFO;
6235 daPyMng_c::addNum(mPlayerNo);
6236 mAmiRelated2 = 1.0f;
6237 setScrollMode(0);
6238 mDamageInvulnTimer = 127;
6239 offZPosSetNone();
6240 daPyMng_c::mPauseEnableInfo |= 1 << mPlayerNo;
6241}
6242
6243void dAcPy_c::executeState_Balloon() {
6245 SndSceneMgr::sInstance->moveMissFin();
6246 }
6247 sLib::calcTimer(&m_12b8);
6248 if (mAllBalloonFadeTimer != 0) {
6249 mAllBalloonFadeTimer--;
6250 if (mAllBalloonFadeTimer == 0) {
6251 checkAllBalloonFade();
6252 }
6253 }
6254 mAngle.y = 0;
6255 switch (mSubstate) {
6256 case 2:
6258 mSubstate = 0;
6259 mSubstateTimer = dGameCom::rndInt(5) * 30;
6260 }
6261 break;
6262 case 0:
6263 if (mSubstateTimer != 0) {
6264 break;
6265 }
6266 if (!isNotBalloonCourse()) {
6267 onStatus(STATUS_53);
6268 onStatus(STATUS_95);
6269 m_12b8 = 600;
6271 mSubstate = 1;
6272 dEnemyMng_c::m_instance->createRevivalBallon(mPos, 0, mPlayerNo);
6273 } else {
6274 mSubstate = 4;
6275 }
6276 break;
6277 case 3: {
6278 onStatus(STATUS_53);
6279 onStatus(STATUS_95);
6280 m_12b8 = 180;
6282 mSubstate = 1;
6283 mVec3_c pos(mPos.x, mPos.y + 4.0f, mPos.z);
6284 dEnemyMng_c::m_instance->createRevivalBallon(mPos, 2, mPlayerNo);
6285 break;
6286 }
6287 case 1:
6289 if (isStatus(STATUS_54)) {
6291 offStatus(STATUS_54);
6292 }
6293 break;
6294 case 4:
6295 mPlayerOrchestra.update();
6296 daPyMng_c::mPauseEnableInfo &= ~(1 << mPlayerNo);
6297 if (isNotBalloonCourse()) {
6298 break;
6299 }
6300 startPlayerVoice(VOICE_CONTINUE_COURSE, 0);
6301 mSubstate = 0;
6302 mSubstateTimer = 60;
6303 daPyMng_c::mPauseEnableInfo |= 1 << mPlayerNo;
6304 }
6305}
6306
6307void dAcPy_c::setBalloonHelpVoice() {
6308 if (isStatus(STATUS_53) && mSubstate == 1 && !isStatus(STATUS_DISPLAY_OUT_DEAD) && mBalloonHelpVoiceCooldown == 0) {
6309 startPlayerVoice(VOICE_BALLOON_HELP_2, 0);
6311 }
6312}
6313
6314bool dAcPy_c::setBalloonInNextgoto() {
6315 if (daPyMng_c::isEntryNum1() || isStatus(STATUS_53)) {
6316 return false;
6317 }
6319 changeState(StateID_Balloon, (void *) 2);
6320 return true;
6321}
6322
6323bool dAcPy_c::setBalloonInDamage() {
6324 if (daPyMng_c::mNum == 0 || daPyMng_c::isEntryNum1() || isStatus(STATUS_53)) {
6325 return false;
6326 }
6328 fn_801416c0(POWERUP_NONE);
6329 if (!isState(StateID_Balloon)) {
6330 changeState(StateID_Balloon, 0);
6331 }
6332 return true;
6333}
6334
6335bool dAcPy_c::setBalloonButtonA() {
6336 if (!mKey.triggerA()) {
6337 return false;
6338 }
6339 if (dNext_c::m_instance->mNextDataSet) {
6340 return false;
6341 }
6343 return false;
6344 }
6345 if (daPyMng_c::isEntryNum1()) {
6346 return false;
6347 }
6348 if (
6349 isDemoAll() ||
6350 isStatus(STATUS_CA) ||
6351 isStatus(STATUS_56) ||
6354 isStatus(STATUS_50) ||
6356 isStatus(STATUS_53) ||
6357 isNotBalloonCourse() ||
6359 ) {
6360 return false;
6361 }
6362 if (dEnemyMng_c::m_instance->m_15c == 1 || dEnemyMng_c::m_instance->m_15c == 2) {
6363 return false;
6364 }
6365 if (dScStage_c::m_miniGame) {
6366 return false;
6367 }
6368 int level = dScStage_c::m_instance->mCurrCourse;
6369 if (level == STAGE_TITLE || level == STAGE_PEACH_CASTLE || level == STAGE_STAFFROLL) {
6370 return false;
6371 }
6372 if (getFollowMameKuribo()) {
6373 startSound(SE_EMY_MAMEKURIBO_CLINGING_NOW, false);
6374 return false;
6375 }
6377 if (!isState(StateID_Balloon)) {
6378 changeState(StateID_Balloon, (void *) 3);
6379 }
6380 return true;
6381}
6382
6383bool dAcPy_c::checkAllBalloonFade() {
6386 dScStage_c::setNextScene(3, 0, dScStage_c::EXIT_1, dFader_c::FADER_BOWSER);
6387 return true;
6388 }
6389 return false;
6390}
6391
6392bool dAcPy_c::setBalloonInDispOutByYoshi(int i) {
6393 return setBalloonInDispOutBase(i, 1);
6394}
6395
6396bool dAcPy_c::setBalloonInDispOut(int i) {
6397 return setBalloonInDispOutBase(i, 0);
6398}
6399
6400bool dAcPy_c::setBalloonInDispOutBase(int i, int j) {
6401 if (!isDispOutCheckOn()) {
6402 return false;
6403 }
6404 if (i == 2 || i == 0) {
6405 if (isDemoAll() && !isStatus(STATUS_5A)) {
6406 return false;
6407 }
6408 if (isStatus(STATUS_B8)) {
6409 return false;
6410 }
6411 } else {
6412 if (isItemKinopio() && !dBg_c::m_bg_p->mAutoscrolls[0].mActive) {
6413 return false;
6414 }
6415 }
6416 if (getCarryPlayer() != nullptr) {
6417 getCarryPlayer()->setBalloonInDispOut(i);
6418 }
6419 if (j == 1) {
6420 onStatus(STATUS_B8);
6421 }
6423 setFallDownDemo();
6424 } else {
6425 setPressBgDamage(11, 0);
6426 }
6427 if (i == 2 || i == 0) {
6428 startPlayerVoice(VOICE_SCROLL_OUT, 0);
6429 dQuake_c::m_instance->shockMotor(mPlayerNo, dQuake_c::TYPE_4, 0, false);
6430 }
6431 return true;
6432}
6433
6434void dAcPy_c::setShakeIce(float f) {
6435 if (isStatus(STATUS_07)) {
6436 m_1594 = f;
6437 }
6438}
6439
6440mVec3_c dAcPy_c::getIceDrawPos() {
6441 return mVec3_c(
6442 mPos.x + m_1594,
6443 mPos.y + m_1598 + m_159c,
6444 mPos.z
6445 );
6446}
6447
6450 setRideOffPlayerJump(sc_JumpSpeed, 0.0f);
6451}
6452
6453void dAcPy_c::initializeState_IceDamage() {
6454 mSpeedF = 0.0f;
6455 mMaxSpeedF = 0.0f;
6456 mAccelY = 0.0f;
6457 mSpeed.y = 0.0f;
6458 mSubstateTimer = 300;
6459 startPlayerVoice(VOICE_DAMAGE_FREEZE, 0);
6460 onStatus(STATUS_7E);
6461 onStatus(STATUS_7A);
6466 dActor_c *ice = dActor_c::construct(fProfile::PLAYER_ICE, this, 0,& mPos, nullptr, 0);
6467 mIceActorID = ice->mUniqueID;
6468 dQuake_c::m_instance->shockMotor(mPlayerNo, dQuake_c::TYPE_4, 0, false);
6469 mPyMdlMng.setAnm(PLAYER_ANIM_JUMP, 0.0f, 0.0f, 0.0f);
6470 mPyMdlMng.mpMdl->setFrame(0.0f);
6471}
6472
6473void dAcPy_c::finalizeState_IceDamage() {
6474 m_1594 = 0.0f;
6475 offStatus(STATUS_7E);
6476 offStatus(STATUS_7A);
6481 mDamageInvulnTimer = 127;
6482}
6483
6484void dAcPy_c::executeState_IceDamage() {
6485 daPlyIce_c *ice = (daPlyIce_c *) fManager_c::searchBaseByID(mIceActorID);
6486 if (ice == nullptr) {
6488 changeState(StateID_Walk, BLEND_NONE);
6489 } else if (isNowBgCross(BgCross1_e(BGC_SIDE_LIMIT_L | BGC_SIDE_LIMIT_R))) {
6490 ice->setRevivalBreakIce();
6491 }
6492}
6493
6494bool dAcPy_c::setRideOffPlayerJump(float a, float b) {
6495 if (mKey.triggerShakeJump()) {
6496 mVec3_c pos(mPos.x, mPos.y + 1.0f, mPos.z);
6497 float height;
6498 if (dBc_c::checkTenjou(&pos, &height, mLayer, 1)) {
6499 float tmp = getStandHeadBgPointY() + 1.0f;
6500 if (mPos.y > height - tmp) {
6501 mPos.y = height - tmp;
6502 mLastPos = mPos;
6503 a = 0.0f;
6504 }
6505 }
6507 return fn_80146e40(a, b, false);
6508 }
6509 return false;
6510}
6511
6512bool dAcPy_c::setRideOffYoshiJump(daPlBase_c *yoshi) {
6513 if (!((daYoshi_c *) yoshi)->checkRideOffAble()) {
6514 return false;
6515 }
6516
6517 if (mKey.triggerShakeJump()) {
6518 if (isDemo() || isStatus(STATUS_OUT_OF_PLAY)) {
6519 return false;
6520 }
6521 if (!yoshi->isNowBgCross(BGC_FOOT)) {
6522 mStartSpinCooldown = 10;
6523 setJump(sc_JumpSpeed + 0.1f, yoshi->mSpeedF, true, 1, 1);
6524 startPlayerVoice(VOICE_YOSHI_JUMP, 0);
6525 } else {
6526 float speed = 0.0f;
6527 if (std::fabs(yoshi->mSpeedF) < 1.5f) {
6528 if (yoshi->mDirection == DIR_LR_L) {
6529 speed = 1.0f;
6530 } else {
6531 speed = -1.0f;
6532 }
6533 }
6534 mSpeedF = speed;
6535 mSpeed.y = sc_JumpSpeed - 0.2f;
6536 changeState(StateID_RideOffJump, 0);
6537 mKey.onStatus(dAcPyKey_c::STATUS_FORCE_JUMP);
6538 }
6540 return true;
6541 }
6542 return false;
6543}
6544
6545daYoshi_c *dAcPy_c::getRideYoshi() {
6547 return (daYoshi_c *) fManager_c::searchBaseByID(mRideActorID);
6548 }
6549 return nullptr;
6550}
6551
6552void dAcPy_c::setRideOnYoshi(daYoshi_c *yoshi) {
6553 if (mRideActorID != 0) {
6554 return;
6555 }
6556 mRideActorID = yoshi->mUniqueID;
6558 changeState(StateID_RideYoshi, 0);
6559}
6560
6561void dAcPy_c::initializeState_RideYoshi() {
6562 daPyMng_c::startYoshiBGM();
6563 mKey.onStatus(dAcPyKey_c::STATUS_DISABLE_LR);
6564 onStatus(STATUS_7A);
6565 onStatus(STATUS_7E);
6566 onStatus(STATUS_93);
6567 onStatus(STATUS_81);
6568 mAccelY = 0.0f;
6569 mSubstateTimer = 10;
6570 m_60 = 10;
6571}
6572
6573void dAcPy_c::finalizeState_RideYoshi() {
6574 mAngle.x = 0;
6575 daYoshi_c *yoshi = (daYoshi_c *) fManager_c::searchBaseByID(mRideActorID);
6576 if (yoshi != nullptr) {
6577 if (mIsBeingDeleted == 1) {
6579 }
6580 yoshi->setRideOffPlayer();
6581 mTreadCount = yoshi->mTreadCount;
6582 }
6583 mRideActorID = BASE_ID_NULL;
6584 mKey.offStatus(dAcPyKey_c::STATUS_DISABLE_LR);
6586 offStatus(STATUS_7A);
6587 offStatus(STATUS_7E);
6588 offStatus(STATUS_93);
6589 offStatus(STATUS_81);
6590 mNoInteractTimer = 10;
6591 if (!isStatus(STATUS_C5)) {
6592 daPyMng_c::stopYoshiBGM();
6593 }
6595}
6596
6597void dAcPy_c::executeState_RideYoshi() {
6599 daYoshi_c *yoshi = getRideYoshi();
6600 if (yoshi == nullptr) {
6601 changeState(StateID_Jump, nullptr);
6602 return;
6603 }
6604 turnAngle();
6605 if (yoshi->isStatus(STATUS_B3)) {
6607 return;
6608 }
6609 if (mSubstateTimer == 0 && setRideOffYoshiJump(yoshi)) {
6610 return;
6611 }
6612}
6613
6614void dAcPy_c::initializeState_Cloud() {
6615 daPlBase_c::initializeState_Cloud();
6616 setScrollMode(6);
6617}
6618
6619void dAcPy_c::finalizeState_Cloud() {
6620 daPlBase_c::finalizeState_Cloud();
6621 setScrollMode(0);
6622 if (mSubstate == 7) {
6623 releaseCarryActor();
6624 } else if (mSubstate == 4 && mIsBeingDeleted == 0) {
6625 createFireBall(0);
6626 }
6627}
6628
6629float dAcPy_c::getCloudOffsetY() {
6630 return dPyMdlMng_c::m_hio.getValue(mPlayerType, 2, mPowerup);
6631}
6632
6633void dAcPy_c::setCloudStateMove() {
6634 mPyMdlMng.setAnm(PLAYER_ANIM_WAIT);
6635 mSubstate = 1;
6636}
6637
6638bool dAcPy_c::checkCloudStateCrouch() {
6639 if (!mKey.buttonCrouch()) {
6640 return false;
6641 }
6642 if (isCarry()) {
6643 return false;
6644 }
6645 onStatus(STATUS_51);
6646 mPyMdlMng.setAnm(PLAYER_ANIM_STOOP_START);
6647 mSubstate = 2;
6648 return true;
6649}
6650
6651void dAcPy_c::setCloudStateFireCreate() {
6652 mPyMdlMng.setAnm(PLAYER_ANIM_FIRE_AT);
6653 mPyMdlMng.mpMdl->setFrame(0.0f);
6654 mAngle.y = getMukiAngle(mDirection);
6655 m_12f4 = mDirection;
6656 mSubstate = 4;
6657}
6658
6659void dAcPy_c::executeState_Cloud() {
6660 if (updateCloudMove()) {
6661 return;
6662 }
6663 switch (mSubstate) {
6664 case 0:
6665 case 5:
6666 case 8:
6667 if (mPyMdlMng.isAnmStop()) {
6668 finalizeThrowCommonBase();
6669 setCloudStateMove();
6670 }
6671 // fallthrough
6672 case 1:
6673 if (!setRideOffPlayerJump(sc_JumpSpeed - 0.2f, 0.0f)) {
6674 if (checkSetFireBall()) {
6675 setCloudStateFireCreate();
6676 } else if (checkEnableThrow()) {
6677 initializeThrowCommonBase();
6678 mSubstate = 7;
6679 } else if (checkCloudStateCrouch()) {
6680 return;
6681 }
6682 }
6683 break;
6684 case 2:
6685 if (mPyMdlMng.isAnmStop()) {
6686 mPyMdlMng.setAnm(PLAYER_ANIM_STOOP);
6687 }
6688 if (!mKey.buttonCrouch()) {
6689 mPyMdlMng.setAnm(PLAYER_ANIM_WAIT, 10.0f, 0.0f);
6690 mSubstateTimer = 10;
6691 offStatus(STATUS_51);
6692 mSubstate = 3;
6693 }
6694 break;
6695 case 3:
6696 if (checkSetFireBall()) {
6697 setCloudStateFireCreate();
6698 }
6699 if (mSubstateTimer == 0) {
6700 setCloudStateMove();
6701 }
6702 break;
6703 case 4:
6704 if (mPyMdlMng.mpMdl->mAnm.checkFrame(4.0f)) {
6705 createFireBall(0);
6706 mSubstate = 5;
6707 }
6708 break;
6709 case 7:
6710 if (mPyMdlMng.mpMdl->mAnm.checkFrame(5.0f)) {
6711 mSubstate = 8;
6712 setThrowActor();
6713 }
6714 break;
6715 }
6716}
6717
6718bool dAcPy_c::checkCarryActor(dAcPy_c *player) {
6719 if (mCarryActorID == player->mUniqueID && player->mRideActorID == mUniqueID) {
6720 return true;
6721 }
6722 return false;
6723}
6724
6725bool dAcPy_c::setDropCarryPlayer() {
6726 dAcPy_c *ridePlayer = getRidePlayer();
6727 if (ridePlayer == nullptr) {
6728 return false;
6729 }
6730 if (ridePlayer->isNowBgCross(BGC_FOOT) && !ridePlayer->isStatus(STATUS_JUMP)) {
6731 if (ridePlayer->isStatus(STATUS_46)) {
6732 if (ridePlayer->isNowBgCross(BGC_HEAD)) {
6733 setJump(0.0f, ridePlayer->mSpeedF / 2.0f, true, 0, 0);
6735 return true;
6736 }
6737 mVec3_c pos(ridePlayer->mPos.x, ridePlayer->mPos.y + 4.0f, ridePlayer->mPos.z);
6738 mVec3_c pos2(mPos.x, mPos.y + 4.0f, mPos.z);
6739 if (!dBc_c::checkWall(&pos, &pos2, nullptr, mLayer, mAmiLayer, nullptr)) {
6740 float height;
6741 if (dBc_c::checkTenjou(&pos2, &height, mLayer, mAmiLayer)) {
6742 const sBcPlayerPointData *p = getBgPointData_Powerup(mPowerup, 1);
6743 if (mPos.y + p->mHead.mOffset / 4096.0f + 2.0f > height) {
6744 setJump(0.0f, ridePlayer->mSpeedF / 2.0f, true, 0, 0);
6746 return true;
6747 }
6748 }
6749 }
6750 }
6751 if (!ridePlayer->isStatus(STATUS_46)) {
6752 if (ridePlayer->isNowBgCross(BGC_12) && !ridePlayer->isNowBgCross(BGC_13)) {
6753 float f;
6754 if (ridePlayer->isNowBgCross(BGC_WALL_TOUCH_R_2)) {
6755 f = -1.0f;
6756 mPos.x -= 3.0f;
6757 } else {
6758 f = 1.0f;
6759 mPos.x += 3.0f;
6760 }
6761 setJump(ridePlayer->mSpeed.y, f, true, 0, 0);
6763 return true;
6764 }
6765 if (ridePlayer->isNowBgCross(BGC_SLOPE_AND_HEAD)) {
6766 setJump(0.0f, 0.0f, true, 0, 0);
6768 }
6769 }
6770 }
6771 return false;
6772}
6773
6774void dAcPy_c::initializeState_CarryPlayer() {
6775 onStatus(STATUS_45);
6776 onStatus(STATUS_97);
6777 onStatus(STATUS_7F);
6778 onStatus(STATUS_93);
6780 onStatus(STATUS_9C);
6781 onStatus(STATUS_81);
6782 mAccelY = 0.0f;
6783 mSpeedF = 0.0f;
6784 mPyMdlMng.setAnm(PLAYER_ANIM_WAIT);
6785 mSubstateTimer = 55;
6786 mSubstate = 0;
6787 if (isItemKinopio()) {
6788 if (daPyMng_c::mKinopioCarryCount < 2) {
6789 daPyMng_c::mKinopioCarryCount++;
6790 }
6791 if (daPyMng_c::mKinopioCarryCount >= 2) {
6793 }
6794 }
6795}
6796
6797void dAcPy_c::finalizeState_CarryPlayer() {
6798 mAngle.x = 0;
6799 dAcPy_c *ridePlayer = getRidePlayer();
6800 if (ridePlayer != nullptr) {
6801 ridePlayer->cancelCarry(this);
6802 }
6803 offStatus(STATUS_45);
6804 offStatus(STATUS_97);
6805 offStatus(STATUS_7F);
6807 offStatus(STATUS_93);
6809 offStatus(STATUS_51);
6810 offStatus(STATUS_9C);
6811 offStatus(STATUS_81);
6812 offZPosSetNone();
6813 mNoInteractTimer = 20;
6814 mPyMdlMng.mpMdl->m_17c &= ~BIT_FLAG(7);
6815 mPyMdlMng.setAnm(PLAYER_ANIM_JUMP2, 0.0f, 0.0f);
6816 mRideActorID = BASE_ID_NULL;
6817 mKey.offStatus(dAcPyKey_c::STATUS_DISABLE_LR);
6819}
6820
6821void dAcPy_c::executeState_CarryPlayer() {
6822 dAcPy_c *ridePlayer = getRidePlayer();
6823 if (ridePlayer == nullptr || fManager_c::searchBaseByID(ridePlayer->mCarryActorID) != this) {
6824 changeState(StateID_Fall, false);
6825 return;
6826 }
6827 setZPositionDirect(ridePlayer->mPos.z);
6828 if (setDropCarryPlayer()) {
6829 return;
6830 }
6831 if (isNowBgCross(BGC_VINE_TOUCH_FULL)) {
6832 mAmiLayer = ridePlayer->mAmiLayer;
6833 }
6834 if (!ridePlayer->isStatus(STATUS_46)) {
6835 if (setRideOffPlayerJump(sc_JumpSpeed - 0.2f, 0.0f)) {
6836 return;
6837 }
6838 }
6839 switch (mSubstate) {
6840 case 4:
6841 case 2:
6842 if (mPyMdlMng.isAnmStop()) {
6843 setCarryPlayerMode_Move(0.0f);
6844 }
6845 // fallthrough
6846 case 0:
6847 if (checkSetFireBall()) {
6848 setCarryPlayerMode_Fire();
6849 } else if (ridePlayer->isStatus(STATUS_47)) {
6850 setCarryPlayerMode_Crouch();
6851 }
6852 break;
6853 case 3:
6854 if (!mPyMdlMng.mpMdl->mAnm.checkFrame(dPyMdlBase_c::scFireShootFrame)) {
6855 break;
6856 }
6857 createFireBall(0);
6858 mSubstate = 4;
6859 break;
6860 case 1:
6861 if (mPyMdlMng.isAnmStop()) {
6862 mPyMdlMng.setAnm(PLAYER_ANIM_STOOP);
6863 }
6864 if (ridePlayer->isStatus(STATUS_47)) {
6865 break;
6866 }
6867 setCarryPlayerMode_Move(10.0f);
6868 offStatus(STATUS_51);
6869 break;
6870 }
6871}
6872
6873void dAcPy_c::setCarryPlayerMode_Move(float f) {
6874 mPyMdlMng.mpMdl->m_17c &= ~BIT_FLAG(7);
6875 mPyMdlMng.setAnmOnlyRate(PLAYER_ANIM_WAIT, f, 0.0f);
6876 mSubstate = 0;
6877 dAcPy_c *ridePlayer = getRidePlayer();
6878 if (ridePlayer != nullptr) {
6879 ridePlayer->mpMdlMng->mpMdl->copyLinkAnm(f);
6880 }
6881}
6882
6883void dAcPy_c::setCarryPlayerMode_Fire() {
6884 mPyMdlMng.mpMdl->m_17c |= BIT_FLAG(7);
6885 mPyMdlMng.setAnmOnlyRate(PLAYER_ANIM_FIRE_AT2, 0.0f, 0.0f);
6886 mPyMdlMng.mpMdl->setFrame(0.0f);
6887 mAngle.y = getMukiAngle(mDirection);
6888 m_12f4 = mDirection;
6889 mSubstate = 3;
6890}
6891
6892void dAcPy_c::setCarryPlayerMode_Crouch() {
6893 mPyMdlMng.mpMdl->m_17c |= BIT_FLAG(7);
6894 mPyMdlMng.setAnm(PLAYER_ANIM_STOOP_START, 3.0f, 0.0f, 0.0f);
6895 mSubstate = 1;
6896 onStatus(STATUS_51);
6897}
6898
6899void dAcPy_c::initRideSpinMove() {
6900 if (!isStatus(STATUS_51)) {
6902 }
6903}
6904
6905void dAcPy_c::endRideSpinMove() {
6907}
6908
6909dAcPy_c *dAcPy_c::getRidePlayer() {
6910 if (isStatus(STATUS_45)) {
6911 return (dAcPy_c *) fManager_c::searchBaseByID(mRideActorID);
6912 }
6913 return nullptr;
6914}
6915
6916void dAcPy_c::setYoshiBackPos() {
6917 daYoshi_c *yoshi = getRideYoshi();
6918 if (yoshi == nullptr) {
6919 return;
6920 }
6921
6922 mMtx_c mtx;
6923 mVec3_c pos;
6924 yoshi->getModel()->getJointMtx(&mtx, 8);
6925 mtx.concat(mMtx_c::createTrans(0.0f, -5.0f, 0.0f));
6926 mtx.multVecZero(pos);
6927
6928 mPos.x = yoshi->mPos.x;
6929 mPos.y = pos.y - 8.0f;
6930 mDirection = yoshi->mDirection;
6931}
6932
6933void dAcPy_c::setPlayerHandPos() {
6934 dAcPy_c *ridePlayer = getRidePlayer();
6935 if (ridePlayer == nullptr) {
6936 return;
6937 }
6938
6939 mVec3_c liftPos = ridePlayer->getLiftUpPos();
6940 liftPos.z = mPos.z;
6941 mPos = mLastPos = liftPos;
6942 if (isStatus(STATUS_97)) {
6943 mDirection = ridePlayer->mDirection;
6944 int newAng = ridePlayer->mAngle.y.mAngle + ridePlayer->getMissSpinAngle();
6945 mAngle.y = newAng;
6946 }
6947}
6948
6950 changeState(StateID_PlayerEat, 0);
6951}
6952
6954 changeState(StateID_Fall, false);
6955}
6956
6957void dAcPy_c::setEatMouth(dActor_c *eatingActor) {
6958 daYoshi_c *yoshi = (daYoshi_c *) eatingActor;
6959 if (isState(StateID_PlayerEat)) {
6961 onStatus(STATUS_C9);
6962 yoshi->setVirusStar(this);
6963 }
6964}
6965
6967 daYoshi_c *yoshi = (daYoshi_c *) eatingActor;
6968 if (isState(StateID_PlayerEat)) {
6969 setNoHitPlayer(yoshi, 10);
6970 dQuake_c::m_instance->shockMotor(mPlayerNo, dQuake_c::TYPE_4, 0, false);
6971 mDirection = yoshi->mDirection;
6972 mAngle.y = getMukiAngle(mDirection);
6973 if (m_1298 == 1) {
6974 mSpeed.y = sGlobalData_c<dAcPy_c>::mData.mSpitRelated[2];
6975 float f = getDirSpeed();
6976 f *= sGlobalData_c<dAcPy_c>::mData.mSpitRelated[3];
6977 mSpeedF = 0.5f * yoshi->getSpeedF() + f;
6978 setRideOffPlayerJump(mSpeed.y, mSpeedF);
6979 } else {
6980 mSpeed.y = sGlobalData_c<dAcPy_c>::mData.mSpitRelated[0];
6981 float f = getDirSpeed();
6982 f *= sGlobalData_c<dAcPy_c>::mData.mSpitRelated[1];
6983 mSpeedF = 0.5f * yoshi->getSpeedF() + f;
6985 }
6986 mMtx_c mtx;
6987 yoshi->getMouthMtx(&mtx);
6988 mtx.concat(mMtx_c::createTrans(10.0f, 0.0f, 0.0f));
6989 mPos.x = mtx.transX();
6990 mPos.y = mtx.transY();
6991 float f = yoshi->mPos.y + 4.0f;
6992 if (mPos.y < f) {
6993 mPos.y = f;
6994 }
6995 mVec3_c posCopy(yoshi->mPos.x, mPos.y, mPos.z);
6996 float offs = sc_DirSpeed[mDirection] * std::fabs(getWallBgPointData()->mOffset / 4096.0f);
6997 mVec3_c posCopy2(mPos.x + offs, mPos.y, mPos.z);
6998 float height;
6999 if (dBc_c::checkWall(&posCopy, &posCopy2, &height, mLayer, 1, nullptr)) {
7000 mSpeedF = 0.0f;
7001 mPos.x = height - offs;
7002 }
7003 float offs2 = getHeadBgPointData()->mOffset / 4096.0f;
7004 posCopy.set(mPos.x, offs2 + yoshi->mPos.y, mPos.z);
7005 if (dBc_c::checkTenjou(&posCopy, &height, mLayer, 1)) {
7006 if (mPos.y > height - offs2) {
7007 mPos.y = height - offs2;
7008 mSpeed.y = 0.0f;
7009 }
7010 }
7011 mLastPos = mPos;
7013 }
7014 return true;
7015}
7016
7017void dAcPy_c::setPlayerEatPos(dActor_c *eatingActor) {
7018 daYoshi_c *yoshi = (daYoshi_c *) eatingActor;
7019 mMtx_c mtx;
7020 if (yoshi != nullptr && yoshi->getTongueTipMtx(&mtx)) {
7021 mPos.x = mtx.transX();
7022 mPos.y = mtx.transY();
7023 m_129c.x = (mPos.x - yoshi->mPos.x) / mAng(yoshi->mAngle.y).sin();
7024 m_129c.y = mPos.y - yoshi->mPos.y;
7025 }
7026}
7027
7028void dAcPy_c::eatMove(dActor_c *eatingActor) {
7029 if (eatingActor != nullptr && isStatus(STATUS_C8)) {
7030 if (isStatus(STATUS_C9)) {
7031 mPos.x = eatingActor->mPos.x + m_129c.x * mAng(eatingActor->mAngle.y).sin();
7032 mPos.y = eatingActor->mPos.y + m_129c.y;
7033 } else {
7034 setPlayerEatPos(eatingActor);
7035 }
7036 }
7037}
7038
7039void dAcPy_c::initializeState_PlayerEat() {
7040 releaseCarryActor();
7041 endPowerUpEffect();
7042 onStatus(STATUS_97);
7043 onStatus(STATUS_AA);
7044 onStatus(STATUS_7A);
7045 onStatus(STATUS_7E);
7046 onStatus(STATUS_81);
7047 onStatus(STATUS_C8);
7049 if (eatingActor == nullptr) {
7050 setPlayerEatPos(eatingActor);
7051 }
7052 onStatus(STATUS_CA);
7053 mPyMdlMng.setAnm(PLAYER_ANIM_STAR_ROLL_DUPLICATE);
7054 mSpeedF = 0.0f;
7055 mAccelY = 0.0f;
7056 mSpeed.y = 0.0f;
7057 m_1298 = 0;
7058}
7059
7060void dAcPy_c::finalizeState_PlayerEat() {
7063 offStatus(STATUS_97);
7064 offStatus(STATUS_AA);
7065 offStatus(STATUS_7A);
7066 offStatus(STATUS_7E);
7067 offStatus(STATUS_81);
7069 offStatus(STATUS_C8);
7070 offStatus(STATUS_C9);
7071 offStatus(STATUS_CA);
7073}
7074
7075void dAcPy_c::executeState_PlayerEat() {
7076 daYoshi_c *yoshi = (daYoshi_c *) fManager_c::searchBaseByID(mEatenByID);
7077 if (yoshi == nullptr) {
7078 changeState(StateID_Jump, nullptr);
7079 return;
7080 }
7081 if (mSubstateValue != 0) {
7083 }
7084 if (mKey.triggerShakeJump() && yoshi->fn_8014f030(this)) {
7085 m_1298 = 1;
7086 }
7087}
7088
7089void dAcPy_c::setPlayerEatReact() {
7091 if (
7092 isDemo() ||
7093 isChange() ||
7094 (mDamageInvulnTimer | mPowerupChangeInvulnTimer) != 0 || // [maybe an inline?]
7095 mNoInteractTimer != 0 ||
7100 ) {
7101 return;
7102 }
7104}
7105
7106bool dAcPy_c::setRideJrCrown(const dActor_c *actor) {
7107 if (mRideActorID == 0) {
7108 mRideActorID = actor->mUniqueID;
7109 changeState(StateID_JrCrown, 0);
7110 return true;
7111 }
7112 return false;
7113}
7114
7115bool dAcPy_c::isRideJrCrownOwn(const dActor_c *actor) {
7116 if (isStatus(STATUS_4F) && mRideActorID == actor->mUniqueID) {
7117 return true;
7118 }
7119 return false;
7120}
7121
7122void dAcPy_c::setRideJrCrownMtx(const mMtx_c *mtx) {
7123 if (isStatus(STATUS_4F)) {
7124 mRideJrClownMtx = *mtx;
7125 }
7126}
7127
7128void dAcPy_c::setJrCrownPos() {
7129 if (isStatus(STATUS_4F)) {
7130 mRideJrClownMtx.multVecZero(mPos);
7131 }
7132}
7133
7134void dAcPy_c::setRideJrCrownAnm(int i) {
7135 if (isStatus(STATUS_4F) && !isStatus(STATUS_50)) {
7136 mPyMdlMng.setAnm(i);
7137 }
7138}
7139
7140void dAcPy_c::initializeState_JrCrown() {
7141 releaseCarryActor();
7142 onStatus(STATUS_4F);
7143 onStatus(STATUS_7E);
7144 onStatus(STATUS_93);
7146 mAccelY = 0.0f;
7147 mSpeedF = 0.0f;
7148 mMaxSpeedF = 0.0f;
7149 mPyMdlMng.setAnm(PLAYER_ANIM_RIDE_WAIT);
7150 mRc.mFlags |= BIT_FLAG(2);
7151}
7152
7153void dAcPy_c::finalizeState_JrCrown() {
7154 offStatus(STATUS_4F);
7155 offStatus(STATUS_50);
7156 offStatus(STATUS_7E);
7157 offStatus(STATUS_93);
7159 mRideActorID = BASE_ID_NULL;
7160 mRc.mFlags &= ~BIT_FLAG(2);
7161}
7162
7163void dAcPy_c::executeState_JrCrown() {
7164 switch (mSubstate) {
7165 case 0:
7166 offStatus(STATUS_50);
7167 break;
7168 case 1:
7169 if (!executeElecShock()) {
7170 setDamage2(nullptr, DAMAGE_BG);
7171 mSubstate = 2;
7172 }
7173 break;
7174 case 2:
7175 mSubstate = 0;
7176 mPyMdlMng.setAnm(PLAYER_ANIM_RIDE_WAIT);
7177 break;
7178 }
7179}
7180
7181void dAcPy_c::setJrCrownElecDamage() {
7182 onStatus(STATUS_50);
7183 initElecShock();
7184 mSubstate = 1;
7185}
7186
7187bool dAcPy_c::checkSetFireBall() {
7188 if (mKey.triggerFire()) {
7189 if (isCarry()) {
7190 return false;
7191 }
7192 if (mPowerup == POWERUP_FIRE_FLOWER) {
7193 if (daFireBall_Player_c::CheckFireBallLimit(mPlayerNo, 0)) {
7194 return true;
7195 }
7196 } else if (mPowerup == POWERUP_PENGUIN_SUIT || mPowerup == POWERUP_ICE_FLOWER) {
7198 return true;
7199 }
7200 }
7201 }
7202 return false;
7203}
7204
7205bool dAcPy_c::setFireBallAction() {
7206 if (isStatus(STATUS_9E) && checkSetFireBall()) {
7207 changeState(StateID_Fire, 0);
7208 return true;
7209 }
7210 return false;
7211}
7212
7213bool dAcPy_c::checkFireJump() {
7214 if (isNowBgCross(BGC_FOOT) && mKey.triggerJump()) {
7215 if (isNowBgCross(BGC_WATER_SHALLOW)) {
7216 mSpeed.y = sc_WaterJumpSpeed;
7217 } else {
7218 fn_80145fd0(1);
7219 setJumpSpeed();
7220 }
7222 return true;
7223 }
7224 return false;
7225}
7226
7227void dAcPy_c::createFireBall(int i) {
7228 mMtx_c mtx;
7229 mVec3_c pos;
7230 mVec3_c loopPos;
7231 mVec3_c pos2;
7232 mPyMdlMng.mpMdl->getJointMtx(&mtx, 11);
7233 mtx.concat(mMtx_c::createTrans(-1.0f, 4.0f, 4.0f));
7234 mtx.multVecZero(pos);
7235 mPyMdlMng.mpMdl->getJointMtx(&mtx, 0);
7236 mtx.multVecZero(pos2);
7237 mVec3_c diff = pos - pos2;
7238 float dist = diff.xzLen();
7239 float dirSpeed = sc_DirSpeed[m_12f4];
7240 loopPos.set(
7241 dScStage_c::getLoopPosX(pos2.x + dirSpeed * dist),
7242 pos.y,
7243 mPos.z
7244 );
7245 if (mPowerup == POWERUP_FIRE_FLOWER) {
7246 startSound(SE_PLY_THROW_FIRE, false);
7247 pos = loopPos;
7248 u32 param = (i << 16) | (mAmiLayer << 12) | (mLayer << 8) | (m_12f4 << 4) | mPlayerNo;
7249 dActor_c::construct(fProfile::PL_FIREBALL, param, &pos, nullptr, 0);
7250 } else if (mPowerup == POWERUP_PENGUIN_SUIT || mPowerup == POWERUP_ICE_FLOWER) {
7251 startSound(SE_PLY_THROW_ICEBALL, false);
7252 pos = loopPos;
7253 u32 param = (i << 16) | (mAmiLayer << 12) | (mLayer << 8) | (m_12f4 << 4) | mPlayerNo;
7254 dActor_c::construct(fProfile::ICEBALL, param, &pos, nullptr, 0);
7255 }
7256}
7257
7258void dAcPy_c::initializeState_Fire() {
7259 mSubstate = 0;
7260 mPyMdlMng.setAnm(PLAYER_ANIM_FIRE_AT);
7261 mAngle.y = getMukiAngle(mDirection);
7262 m_12f4 = mDirection;
7263 onStatus(STATUS_A0);
7266}
7267
7268void dAcPy_c::finalizeState_Fire() {
7270 offStatus(STATUS_A0);
7272 offStatus(STATUS_9B);
7273 offStatus(STATUS_9C);
7274 offStatus(STATUS_9D);
7276 offStatus(STATUS_A1);
7277}
7278
7279void dAcPy_c::executeState_Fire() {
7280 gravitySet();
7281 maxFallSpeedSet();
7282 simpleMoveSpeedSet();
7283 powerSet();
7284 if (isNowBgCross(BGC_FOOT)) {
7286 offStatus(STATUS_9B);
7287 offStatus(STATUS_9C);
7288 offStatus(STATUS_9D);
7289 offStatus(STATUS_A1);
7290 } else {
7292 onStatus(STATUS_9B);
7293 onStatus(STATUS_9C);
7294 onStatus(STATUS_9D);
7295 onStatus(STATUS_A1);
7296 }
7297 switch (mSubstate) {
7298 case 0:
7299 checkFireJump();
7300 if (mPyMdlMng.mpMdl->mAnm.checkFrame(dPyMdlBase_c::scFireShootFrame)) {
7301 createFireBall(0);
7302 mSubstate = 1;
7304 }
7305 break;
7306 case 1:
7307 if (checkSetFireBall()) {
7308 m_12f4 = getDirection();
7309 mAngle.y = getMukiAngle(mDirection);
7310 mSubstate = 0;
7311 mPyMdlMng.setAnm(PLAYER_ANIM_FIRE_AT);
7312 mPyMdlMng.mpMdl->setFrame(0.0f);
7313 } else if (isNowBgCross(BGC_FOOT)) {
7314 if (
7315 !checkJumpTrigger() &&
7316 (
7317 mPyMdlMng.mpMdl->mAnm.getFrame() >= 10.0f && mSpeedF ||
7318 mPyMdlMng.isAnmStop()
7319 )
7320 ) {
7321 changeState(StateID_Walk, BLEND_DEFAULT);
7322 }
7323 } else {
7324 if (
7325 mPyMdlMng.mpMdl->mAnm.getFrame() >= 10.0f ||
7326 (mPyMdlMng.isAnmStop() && mSpeed.y <= 0.0f)
7327 ) {
7328 changeState(StateID_Fall, false);
7329 }
7330 }
7331 break;
7332 }
7333}
7334
7335void dAcPy_c::setSpinFireBall() {
7336 if (isCarry()) {
7337 dAcPy_c *carryPlayer = getCarryPlayer();
7338 if (carryPlayer != nullptr) {
7339 carryPlayer->m_12f4 = m_12f4;
7340 carryPlayer->setSpinFireBall();
7341 }
7342 } else if (mPowerup == POWERUP_FIRE_FLOWER) {
7343 if (daFireBall_Player_c::CheckFireBallLimit(mPlayerNo, 1)) {
7344 createFireBall(1);
7345 }
7346 } else if (mPowerup == POWERUP_PENGUIN_SUIT || mPowerup == POWERUP_ICE_FLOWER) {
7348 createFireBall(1);
7349 }
7350 }
7351}
7352
7353bool dAcPy_c::setPropelAction() {
7354 if (isStatus(STATUS_IS_SPIN_HOLD_REQ) || isOnSinkSand()) {
7355 changeState(StateID_SpinJump, 0);
7356 return false;
7357 }
7358 if (m_2f4 == 1) {
7359 if (!getCarryPropelBlock() && dScStage_c::m_miniGame == 0) {
7361 }
7362 if (isNowBgCross(BGC_FOOT)) {
7363 changeState(StateID_Propel, (void *) 2);
7364 } else {
7365 changeState(StateID_Propel, (void *) 0);
7366 }
7367 return true;
7368 }
7369 return false;
7370}
7371
7372void dAcPy_c::resetPropelFlyTime() {
7373 if (m_2f4 == 0) {
7374 m_2f4 = 1;
7375 }
7376}
7377
7378void dAcPy_c::clearPropelFlyUpTime() {
7379 if (isStatus(STATUS_PROPEL_UP) && m_2ec > 10) {
7380 m_2ec = 10;
7381 }
7382}
7383
7384void dAcPy_c::calcPropelMoveSpeedF() {
7385 int dir;
7386 u8 wasWalk = mKey.buttonWalk(&dir);
7387 if (wasWalk) {
7388 mDirection = dir;
7389 }
7390 float f;
7391 if (!isStatus(STATUS_PROPEL_UP)) {
7392 mAccelF = data_802f5a0c[2];
7393 if (wasWalk && mSpeedF * sc_DirSpeed[mDirection] < 0.0f) {
7394 mAccelF = data_802f5a0c[3];
7395 }
7397 f = data_802f5a0c[8];
7398 } else {
7399 f = data_802f5a0c[9];
7400 }
7401 } else {
7402 mAccelF = data_802f5a0c[1];
7403 f = data_802f5a0c[10];
7404 }
7405 if (!wasWalk) {
7406 float oldF = f;
7407 f = std::fabs(mSpeedF);
7408 mAccelF = 0.05f;
7409 if (f > oldF) {
7410 f = oldF;
7411 }
7412 }
7413 if (mDirection == DIR_LR_L) {
7414 f = -f;
7415 }
7416 mMaxSpeedF = f;
7417}
7418
7419void dAcPy_c::setPropelActionFlyInit() {
7420 m_2f4 = 0;
7421 m_2f0 = 25;
7423 mPropelRollSpeed = 12000;
7424 mIsPropelFall = 0;
7425 startPlayerVoice(VOICE_PRPL_JUMP, 0);
7426 startSound(SE_PLY_PRPL_JUMP, false);
7427 mPyMdlMng.setAnm(PLAYER_ANIM_PL_SPIN_JUMP);
7428 mAccelY = 0.0f;
7429 mMaxFallSpeed = data_802f5a0c[5];
7430}
7431
7432void dAcPy_c::setPropelActionBigFly() {
7433 setPropelActionFlyInit();
7434 mSubstate = 0;
7435 mSpeed.y = 0.5f;
7436 m_2ec = 38;
7437 setStartPropelJumpEffect();
7438 startPatternRumble("****--****--**----**----**----**----**----**----**");
7439}
7440
7441void dAcPy_c::setPropelActionFly() {
7442 setPropelActionFlyInit();
7443 mSubstate = 1;
7444 m_2ec = 50;
7445 startPatternRumble("***---***---*----**-----*----**-----*-----**-----*");
7446}
7447
7448void dAcPy_c::PropelActionFly() {
7449 setCcAtSpin();
7450 setPropelSpinSmokeEffect();
7451 if (mPropelRollSpeed < 3000) {
7452 mPropelRollSpeed = 3000;
7453 }
7454 if (isNowBgCross(BGC_HEAD)) {
7455 mSpeed.y = data_802f5a0c[4];
7456 }
7457 if (isNowBgCross(BGC_FOOT)) {
7458 m_2ec = 0;
7459 }
7460 if (mSubstate == 0) {
7461 sLib::chase(&mSpeed.y, 3.0f, 0.7f);
7462 } else {
7463 sLib::chase(&mSpeed.y, data_802f5a0c[11], data_802f5a0c[12]);
7464 }
7465 if (m_2ec != 0) {
7466 m_2ec--;
7467 }
7468 if (m_2ec == 0) {
7469 setPropelActionFall();
7470 if (mSubstate == 0) {
7471 mSubstateTimer = 30;
7472 } else {
7473 mSubstateTimer = 10;
7474 }
7475 }
7476}
7477
7478void dAcPy_c::setPropelActionFall() {
7480 mPyMdlMng.setAnm(PLAYER_ANIM_PL_SPIN_JUMP, 30.0f, 0.0f);
7481 setAddLiftSpeedF();
7482 mSubstate = 2;
7483 mPropelRollSpeed = 3000;
7484 mIsPropelFall = 1;
7485 mAccelY = data_802f5a0c[7];
7486}
7487
7488void dAcPy_c::PropelActionFall() {
7489 if (mSpeed.y < 0.0f) {
7491 }
7493 mMaxFallSpeed = data_802f5a0c[6];
7494 } else {
7495 mMaxFallSpeed = data_802f5a0c[5];
7496 }
7497 offStatus(STATUS_A8);
7498 onStatus(STATUS_A9);
7499 onStatus(STATUS_92);
7500 if (isNowBgCross(BGC_FOOT)) {
7501 setLandSE();
7502 mPyMdlMng.setAnm(PLAYER_ANIM_JUMPED);
7503 changeState(StateID_Land, false);
7504 } else {
7505 if (mPropelRollSpeed < 2000) {
7507 } else {
7509 }
7510 calcPropelFallSpinEffect();
7511 if (mPropelRollSpeed < 1000) {
7512 mPropelRollSpeed = 1000;
7513 if (mPyMdlMng.getAnm() != PLAYER_ANIM_SPIN_JUMP3) {
7514 mPyMdlMng.setAnm(PLAYER_ANIM_SPIN_JUMP3);
7515 }
7516 }
7517 if (
7518 mPyMdlMng.mpMdl->mCurrAnmID == PLAYER_ANIM_SPIN_JUMP3 &&
7519 (
7520 mPyMdlMng.mpMdl->mAnm.checkFrame(8.0f) ||
7521 mPyMdlMng.mpMdl->mAnm.checkFrame(19.0f)
7522 )
7523 ) {
7524 startSound(SE_PLY_PRPL_FLY, false);
7525 }
7526 if (mKey.triggerShakeJump()) {
7527 mPropelRollSpeed = 5000;
7528 mIsPropelFall = 1;
7529 mPyMdlMng.setAnm(PLAYER_ANIM_PL_SPIN_JUMP);
7530 setPropelFallSpinEffect();
7531 }
7532 }
7533}
7534
7535void dAcPy_c::initializeState_Propel() {
7536 m_2ec = 0;
7537 switch ((int) mStateArg) {
7538 case 0:
7539 setPropelActionFly();
7540 break;
7541 case 1:
7542 setPropelActionFall();
7543 break;
7544 case 2:
7545 setPropelActionBigFly();
7546 break;
7547 }
7548 if (isNowBgCross(BGC_FOOT)) {
7549 offNowBgCross(BGC_FOOT);
7550 }
7553 onStatus(STATUS_9B);
7554 onStatus(STATUS_9C);
7555 onStatus(STATUS_9D);
7556 onStatus(STATUS_A0);
7557 onStatus(STATUS_A8);
7559 mSubstateValue = 0;
7560 if (getCarryPropelActor() != nullptr) {
7561 mSubstateValue = 1;
7562 }
7563 setScrollMode(2);
7564}
7565
7566void dAcPy_c::finalizeState_Propel() {
7567 endPropelFlyPartsMove();
7568 stopPropelFallSpinEffect();
7569 mPropelRollSpeed = 0;
7570 mAngle.x = 0;
7571 mAngle.y = getMukiAngle(mDirection);
7575 offStatus(STATUS_9B);
7576 offStatus(STATUS_9C);
7577 offStatus(STATUS_9D);
7578 offStatus(STATUS_A0);
7579 offStatus(STATUS_A8);
7580 offStatus(STATUS_A9);
7583 offStatus(STATUS_92);
7584 setScrollMode(0);
7585}
7586
7587void dAcPy_c::executeState_Propel() {
7588 offStatus(STATUS_92);
7589 if (mSubstateValue == 0) {
7590 if (mPowerup != POWERUP_PROPELLER_SHROOM) {
7591 changeState(StateID_Fall, false);
7592 return;
7593 }
7594 } else if (getCarryPropelActor() == nullptr) {
7595 changeState(StateID_Fall, false);
7596 return;
7597 }
7598 if (mPropelRollSpeed != 0) {
7599 mAngle.y += mPropelRollSpeed;
7600 if (!mIsPropelFall) {
7601 mPropelRollSpeed -= 200;
7602 } else {
7603 mPropelRollSpeed -= 80;
7604 }
7605 }
7606 if (mPropelRollSpeed <= 0) {
7607 mPropelRollSpeed = 0;
7608 mAngle.y = getMukiAngle(mDirection);
7610 }
7611 typedef void (dAcPy_c::*PropelActionProc)();
7612 static PropelActionProc l_PropelActionProc[] = {
7613 &dAcPy_c::PropelActionFly,
7614 &dAcPy_c::PropelActionFly,
7615 &dAcPy_c::PropelActionFall
7616 };
7617 (this->*l_PropelActionProc[mSubstate])();
7618 calcPropelMoveSpeedF();
7619 sLib::addCalcAngle(&mAngle.x.mAngle, 0, 0x100, 0x2000, 0x200);
7620 if (!checkCarryThrow() && setHipAttackAction()) {
7621 return;
7622 }
7623}
7624
7625void dAcPy_c::updatePropelParts() {
7626 if (!isStatus(STATUS_45)) {
7627 if (isStatus(STATUS_PROPEL)) {
7628 updatePropelFlyPartsMove();
7629 } else if (isLiftUp()) {
7630 mpPropelParts->mMode = 3;
7631 } else if (isStatus(STATUS_70)) {
7632 mpPropelParts->mMode = 5;
7633 } else {
7634 mpPropelParts->mMode = 4;
7635 }
7636 }
7637 mMtx_c mtx;
7638 mPyMdlMng.mpMdl->getHeadPropelJointMtx(&mtx);
7639 mpPropelParts->update(mtx);
7640 if (!mpPropelParts->isMode(dPropelParts_c::PROPEL_MODE_3) && !isStatus(STATUS_PROPEL_NO_ROLL)) {
7641 mPyMdlMng.mpMdl->setPropelRollSpeed(mpPropelParts->mRollSpeed);
7642 } else {
7643 mPyMdlMng.mpMdl->setPropelRollSpeed(0);
7644 mPyMdlMng.mpMdl->setPropelRollAngle(0);
7645 }
7646 mPyMdlMng.mpMdl->setPropelScale(mpPropelParts->mScale);
7647}
7648
7649void dAcPy_c::updatePropelFlyPartsMove() {
7650 int v = 4;
7651 if (isStatus(STATUS_PROPEL)) {
7652 switch (mSubstate) {
7653 case 0:
7654 case 1:
7655 v = 0;
7656 break;
7657 default:
7658 v = 2;
7659 if (mPropelRollSpeed < 3000) {
7660 v = 1;
7661 }
7662 break;
7663 }
7664 }
7665 dActor_c *propelActor = getCarryPropelActor();
7666 if (propelActor == nullptr) {
7667 mpPropelParts->mMode = v;
7668 } else {
7669 mpPropelParts->mMode = 3;
7670 propelActor->mpPropelParts->mMode = v;
7671 }
7672}
7673
7674void dAcPy_c::endPropelFlyPartsMove() {
7675 dActor_c *propelActor = getCarryPropelActor();
7676 if (propelActor != nullptr) {
7677 propelActor->mpPropelParts->finalizePropelFly(mPropelRollSpeed);
7678 }
7679 mpPropelParts->finalizePropelFly(mPropelRollSpeed);
7680}
7681
7682void dAcPy_c::setPropelSpinSmokeEffect() {
7683 mVec3_c efPos = mPos;
7684 efPos.y += 10.0f;
7685 if (dMaskMng::isCaveMask() && mLayer == 0 && mAmiLayer == 1) {
7686 efPos.z = 2000.0f;
7687 }
7688 float height;
7689 if (dBc_c::checkGround(&efPos, &height, mLayer, 1, -1) && mPos.y < height + 64.0f) {
7690 efPos.y = height;
7691 dEf::createPlayerEffect(mPlayerNo, &mLevelEf3, "Wm_mr_spinsmoke", 0, &efPos, nullptr, nullptr);
7692 }
7693}
7694
7695void dAcPy_c::setStartPropelJumpEffect() {
7696 if (isNowBgCross(BGC_FOOT)) {
7697 mVec3_c efPos = mPos;
7698 if (dMaskMng::isCaveMask() && mLayer == 0 && mAmiLayer == 1) {
7699 efPos.z = 2000.0f;
7700 }
7701 dEf::createPlayerEffect(mPlayerNo, "Wm_mr_spindepart", 0, &efPos, nullptr, nullptr);
7702 }
7703}
7704
7705void dAcPy_c::setPropelFallSpinEffect() {
7706 startSound(SE_PLY_PRPL_LETDOWN_SPIN, false);
7707 if (m_538 == 0) {
7708 m_538 = 1;
7709 }
7710}
7711
7712bool dAcPy_c::calcPropelFallSpinEffect() {
7713 if (m_53c != 0) {
7714 m_53c--;
7715 }
7716 switch (m_538) {
7717 case 1:
7718 case 2:
7719 case 3: {
7721 dAcPy_c *carryPlayer = getCarryPlayer();
7722 mVec3_c efPos;
7723 if (carryPlayer != nullptr) {
7724 carryPlayer->getModel()->getJointPos(&efPos, 1);
7725 } else {
7726 mPyMdlMng.mpMdl->getJointPos(&efPos, 1);
7727 }
7728 if (m_538 == 1) {
7729 dEf::createPlayerEffect(mPlayerNo, &mFollowEf, "Wm_mr_spinjump_re", 0, &efPos, nullptr, nullptr);
7730 if (carryPlayer != nullptr) {
7731 m_538 = 3;
7732 } else {
7733 m_538 = 2;
7734 }
7735 return true;
7736 }
7737 if (m_538 == 3 && carryPlayer == nullptr) {
7738 stopPropelFallSpinEffect();
7739 return false;
7740 }
7741 if (mFollowEf.follow(&efPos, nullptr, nullptr)) {
7742 return true;
7743 }
7744 }
7745 m_538 = 4;
7746 m_53c = 20;
7747 break;
7748 }
7749 case 4:
7750 if (m_53c == 0) {
7751 m_538 = 0;
7752 }
7753 break;
7754 }
7755 return false;
7756}
7757
7758void dAcPy_c::stopPropelFallSpinEffect() {
7759 mFollowEf.kill();
7760 m_53c = 0;
7761 m_538 = 0;
7762}
7763
7764void dAcPy_c::initDemo_DownPose() {
7765 if (mPyMdlMng.mpMdl->mFlags & 4) {
7766 mPos.y = getAnkleCenterPos().y;
7767 }
7768 mPyMdlMng.setAnm(PLAYER_ANIM_DEAD_POSE);
7769 mSpeedF = 0.0f;
7770 mAngle.set(0, 0, 0);
7771 mPos.y += 2.0f;
7772 setZPosition(5000.0f);
7773 mMaxFallSpeed = 0.0f;
7774 mSpeed.set(0.0f, 0.0f, 0.0f);
7775 mAccelY = 0.0f;
7776 calcModel();
7777}
7778
7779void dAcPy_c::initDemo_DownFall() {
7780 switch ((DemoDownArg_e) mDemoStateArg) {
7781 case DEMO_DOWN_ARG_HIT:
7782 startPlayerVoice(VOICE_DAMAGE_LAST_2, 0);
7783 break;
7784 case DEMO_DOWN_ARG_TIME_UP:
7785 if (daPyMng_c::mTimeUpPlayerNum >= 2) {
7786 startPlayerVoice(VOICE_TIMEUP_MULTI, 0);
7787 } else {
7788 startPlayerVoice(VOICE_TIMEUP, 0);
7789 }
7790 break;
7791 case DEMO_DOWN_ARG_POISON:
7792 case DEMO_DOWN_ARG_POISON_FOG:
7793 startPlayerVoice(VOICE_DAMAGE_POISON, 0);
7794 break;
7795 }
7796 mPyMdlMng.setAnm(PLAYER_ANIM_DEAD);
7797 mSpeed.x = 0.0f;
7798 mSpeed.y = 3.25f;
7799 mSpeed.z = 0.0f;
7800 mMaxFallSpeed = sc_MaxFallSpeed;
7801 mAccelY = -0.125f;
7802}
7803
7804void dAcPy_c::exeDemo_DownFall() {
7805 if (mSpeed.y > 2.5f) {
7806 mAccelY = -0.06f;
7807 } else if (mSpeed.y > 0.5f) {
7808 mAccelY = -0.25f;
7809 } else if (mSpeed.y > -0.5f) {
7810 mAccelY = -0.047f;
7811 } else {
7812 mAccelY = -0.1f;
7813 }
7814 mPos.y += mSpeed.y;
7815 calcFallSpeed();
7816}
7817
7818void dAcPy_c::checkRest() {
7819 if (isItemKinopio()) {
7820 deleteRequest();
7821 return;
7822 }
7823 if (!m_7c) {
7824 setBalloonInDamage();
7825 return;
7826 }
7828 return;
7829 }
7831 bool allDown = true;
7832 for (int i = 0; i < PLAYER_COUNT; i++) {
7833 if (daPyMng_c::mPlayerEntry[i] && daPyMng_c::mRest[daPyMng_c::mPlayerType[i]] != 0) {
7834 allDown = false;
7835 break;
7836 }
7837 }
7838 if (!allDown) {
7839 dScStage_c::setNextScene(3, 0, dScStage_c::EXIT_1, dFader_c::FADER_BOWSER);
7840 } else {
7841 dScStage_c::setNextScene(9, 0, dScStage_c::EXIT_1, dFader_c::FADER_BOWSER);
7842 }
7843}
7844
7845void dAcPy_c::initPlayerDownCommon() {
7846 m_7c = 0;
7847 if (daPyMng_c::decNum(mPlayerNo) && daPyMng_c::mNum == 0) {
7848 m_7c = 1;
7849 }
7851 releaseCarryActor();
7852 resetMissSpin();
7853 endStar();
7854 setScrollMode(3);
7856 mDamageInvulnTimer = 0;
7857 mStarTimer = 0;
7858 mVisible = true;
7859 if (!isItemKinopio()) {
7860 daPyMng_c::decRest(mPlayerNo);
7861 if (m_7c) {
7862 SndSceneMgr::sInstance->fn_8019be60(1);
7863 }
7864 }
7865 mDemoSubstateTimer = 30;
7866}
7867
7868void dAcPy_c::stopOtherDownDemo() {
7869 if (isItemKinopio()) {
7870 return;
7871 }
7872 if (!m_7c) {
7873 stopOther();
7874 return;
7875 }
7876 daPyDemoMng_c::mspInstance->m_84 = mPlayerNo;
7877 mExecStopReq |= 0b1111;
7878
7879 dAcPy_c *player;
7880 for (int i = 0; i < PLAYER_COUNT; i++) {
7881 player = daPyMng_c::getPlayer(i);
7882 if (player != nullptr && !player->isStatus(STATUS_53) && !player->isItemKinopio()) {
7883 player->mExecStopMask &= ~BIT_FLAG(1);
7884 }
7885 daYoshi_c *yoshi = daPyMng_c::getYoshi(i);
7886 if (yoshi != nullptr) {
7887 yoshi->mExecStopMask &= ~BIT_FLAG(1);
7888 }
7889 }
7890 mExecStopReq |= 0b1101;
7891}
7892
7893void dAcPy_c::playOtherDownDemo() {
7894 if (!isItemKinopio() && daPyDemoMng_c::mspInstance->m_84 == -1 && !m_7c) {
7895 playOther();
7896 }
7897}
7898
7899bool dAcPy_c::setTimeOverDemo() {
7900 if (
7901 !isStatus(STATUS_53) &&
7905 ) {
7906 changeDemoState(StateID_DemoDown, DEMO_DOWN_ARG_TIME_UP);
7907 return true;
7908 }
7909 return false;
7910}
7911
7912void dAcPy_c::initializeState_DemoDown() {
7913 initPlayerDownCommon();
7914 initDemo_DownPose();
7915 startSound(SE_PLY_DOWN, false);
7916 switch ((DemoDownArg_e) mDemoStateArg) {
7917 case DEMO_DOWN_ARG_HIT:
7918 case DEMO_DOWN_ARG_POISON_FOG:
7919 stopOtherDownDemo();
7920 break;
7921 case DEMO_DOWN_ARG_POISON: {
7922 mVec3_c efPos(
7923 mPos.x,
7924 mWaterHeight,
7925 mPos.z
7926 );
7927 dEf::createPlayerEffect(mPlayerNo, "Wm_mr_poisonwave", nullptr, &efPos, nullptr, nullptr);
7928 startSound(SE_PLY_SPLASH_POISON, 0);
7929 dBg_c::m_bg_p->setWaterInWave(mPos.x, mWaterHeight, 20);
7930 stopOtherDownDemo();
7931 break;
7932 }
7933 case DEMO_DOWN_ARG_TIME_UP:
7934 daPyMng_c::mTimeUpPlayerNum++;
7935 stopOtherDownDemo();
7936 break;
7937 }
7938 dQuake_c::m_instance->shockMotor(mPlayerNo, dQuake_c::TYPE_4, 0, false);
7939}
7940
7941void dAcPy_c::finalizeState_DemoDown() {
7942 mMaxFallSpeed = sc_MaxFallSpeed;
7943}
7944
7945void dAcPy_c::executeState_DemoDown() {
7946 switch (mDemoSubstate) {
7947 case 0:
7948 if (mDemoSubstateTimer == 0) {
7949 daPyMng_c::startMissBGM(mPlayerNo);
7950 mDemoSubstate = 1;
7951 initDemo_DownFall();
7952 if (dBg_c::m_bg_p->m_90009 == 3) {
7953 mMaxFallSpeed = sc_MaxFallDownSpeed;
7954 }
7955 if ((int) mDemoStateArg != 1) {
7956 playOtherDownDemo();
7957 mDemoSubstateTimer = 80;
7958 } else {
7959 mDemoSubstateTimer = 150;
7960 }
7961 }
7962 break;
7963 case 1: {
7964 exeDemo_DownFall();
7965 if (!m_7c) {
7966 dBgParameter_c *bgParam = dBgParameter_c::ms_Instance_p;
7967 dBg_c *bg = dBg_c::m_bg_p;
7968 float t = getVisTop();
7969 u8 val = bg->m_90009;
7970 float f = bgParam->yStart() - bgParam->ySize() - 24.0f;
7971 if (val == 3) {
7972 f = bgParam->yStart() - bgParam->ySize() - 8.0f;
7973 }
7974 if (t < f) {
7975 checkRest();
7976 mDemoSubstate = 2;
7977 break;
7978 }
7979 if (val != 3) {
7980 break;
7981 }
7982 if (getVisBottom() > bgParam->yStart() + 64.0f) {
7983 checkRest();
7984 mDemoSubstate = 2;
7985 }
7986 } else if (mDemoSubstateTimer == 0) {
7987 checkRest();
7988 mDemoSubstate = 2;
7989 }
7990 break;
7991 }
7992 case 2:
7993 exeDemo_DownFall();
7994 }
7995 checkSideViewLemit();
7996}
7997
7998void dAcPy_c::setFallDownDemo() {
7999 if (isDispOutCheckOn()) {
8000 mAccelY = 0.0f;
8001 mSpeedF = 0.0f;
8002 mBgPushForce.set(0.0f, 0.0f, 0.0f);
8003 mExtraPushForceX = 0.0f;
8004 mSpeed.y = 0.0f;
8005 changeDemoState(StateID_DemoFallDown, 0);
8006 }
8007}
8008
8009void dAcPy_c::initializeState_DemoFallDown() {
8010 initPlayerDownCommon();
8011 mPyMdlMng.setAnm(PLAYER_ANIM_JUMP2, 1.0f, 0.0f, 0.0f);
8012 mAccelY = 0.0f;
8013 mSpeedF = 0.0f;
8014 mBgPushForce.set(0.0f, 0.0f, 0.0f);
8015 mExtraPushForceX = 0.0f;
8016 mSpeed.y = 0.0f;
8017 mAngle.y = 0;
8018 setZPosition(5000.0f);
8019 float f = dBgParameter_c::ms_Instance_p->getLoopScrollDispPosX(mPos.x);
8020 float f1 = f - 96.0f;
8021 float f2 = f + dBgParameter_c::ms_Instance_p->xSize() + 96.0f;
8022 if (f1 <= mPos.x && mPos.x < f2) {
8023 startSound(SE_PLY_DOWN, false);
8024 }
8025 stopOtherDownDemo();
8027 mVisible = false;
8028}
8029
8030void dAcPy_c::finalizeState_DemoFallDown() {
8032}
8033
8034void dAcPy_c::executeState_DemoFallDown() {
8035 switch (mDemoSubstate) {
8036 case 0:
8037 if (mDemoSubstateTimer == 0) {
8038 mDemoSubstate = 1;
8039 daPyMng_c::startMissBGM(mPlayerNo);
8040 if (!m_7c) {
8041 playOtherDownDemo();
8042 mDemoSubstateTimer = 50;
8043 } else {
8044 mDemoSubstateTimer = 80;
8045 }
8046 }
8047 break;
8048 case 1:
8049 if (mDemoSubstateTimer == 0) {
8050 checkRest();
8051 mDemoSubstate = 2;
8052 }
8053 }
8054 checkSideViewLemit();
8055}
8056
8057void dAcPy_c::initializeState_DemoFireDown() {
8058 dScStage_c *stage = dScStage_c::m_instance;
8059 initPlayerDownCommon();
8060 if (mBgDamageType == 7) {
8061 mVec3_c efPos(
8062 mPos.x,
8063 mWaterHeight,
8064 6500.0f
8065 );
8066 if (stage != nullptr) {
8067 if (
8068 stage->mCurrWorld == WORLD_8 && stage->mCurrCourse == STAGE_3 ||
8069 stage->mCurrWorld == WORLD_8 && stage->mCurrCourse == STAGE_CASTLE && stage->mCurrFile == 3
8070 ) {
8071 dEf::createPlayerEffect(mPlayerNo, "Wm_en_cmnmagmawave", 0, &efPos, nullptr, nullptr);
8072 } else {
8073 dEf::createPlayerEffect(mPlayerNo, "Wm_mr_magmawave", 0, &efPos, nullptr, nullptr);
8074 }
8075 }
8076 dBg_c::m_bg_p->setWaterInWave(mPos.x, mWaterHeight, 13);
8077 }
8078 initDemo_DownPose();
8079 setZPosition(3000.0f);
8080 startSound(SE_PLY_SPLASH_LAVA, false);
8081 startSound(SE_PLY_DOWN, false);
8082 dQuake_c::m_instance->shockMotor(mPlayerNo, dQuake_c::TYPE_4, 0, false);
8083 stopOtherDownDemo();
8084}
8085
8086void dAcPy_c::finalizeState_DemoFireDown() {}
8087
8088void dAcPy_c::executeState_DemoFireDown() {
8089 switch (mDemoSubstate) {
8090 case 0:
8091 if (mDemoSubstateTimer == 0) {
8092 daPyMng_c::startMissBGM(mPlayerNo);
8093 mDemoSubstateTimer = 80;
8094 startPlayerVoice(VOICE_DAMAGE_FIRE, 0);
8095 startSound(SE_PLY_BURN_DOWN, false);
8096 setZPosition(5000.0f);
8097 mPyMdlMng.setAnm(PLAYER_ANIM_FIREJMP);
8098 mSpeed.x = 0.0f;
8099 mSpeed.y = 3.25f;
8100 mSpeed.z = 0.0f;
8101 mMaxFallSpeed = sc_MaxFallSpeed;
8102 mAccelY = -0.125f;
8103 mAngle.y = getMukiAngle(mDirection);
8104 mDemoSubstate = 1;
8105 playOtherDownDemo();
8106 }
8107 break;
8108 case 1:
8109 exeDemo_DownFall();
8110 if (!m_7c) {
8111 dBgParameter_c *bgParam = dBgParameter_c::ms_Instance_p;
8112 float edgePos = getVisTop();
8113 float bgBottom = bgParam->yStart() - bgParam->ySize() - 24.0f;
8114 if (edgePos < bgBottom) {
8115 checkRest();
8116 mDemoSubstate = 2;
8117 }
8118 } else if (mDemoSubstateTimer == 0) {
8119 checkRest();
8120 mDemoSubstate = 2;
8121 }
8122 break;
8123 case 2:
8124 exeDemo_DownFall();
8125 break;
8126 }
8127 if (mDemoSubstate != 0) {
8128 mVec3_c efScale(1.0f, 1.0f, 1.0f);
8129 if (mPowerup == POWERUP_MINI_MUSHROOM) {
8130 efScale.set(0.6f, 0.6f, 0.6f);
8131 }
8132 dEf::createPlayerEffect(mPlayerNo, &mSmokeEffect, "Wm_mr_atitismoke", 0, &mPos, nullptr, &efScale);
8133 }
8134 checkSideViewLemit();
8135}
8136
8137void dAcPy_c::setPlayerEatDie() {
8138 m_15a8 = 0;
8139 if ((int) mDemoStateArg == 12) {
8140 m_15a8 = 1;
8141 } else {
8142 if (!isStar() && (mPowerup == POWERUP_NONE || mPowerup == POWERUP_MINI_MUSHROOM)) {
8143 m_15a8 = 1;
8144 }
8145 }
8146}
8147
8148void dAcPy_c::initializeState_DemoEatDie() {
8149 setPlayerEatDie();
8150 if (m_15a8 != 0) {
8151 initPlayerDownCommon();
8152 }
8154 mSpeedF = 0.0f;
8155 mMaxFallSpeed = 0.0f;
8156 mSpeed.set(0.0f, 0.0f, 0.0f);
8157 mAccelY = 0.0f;
8158 mDemoSubstate = 0;
8159}
8160
8161void dAcPy_c::finalizeState_DemoEatDie() {
8164}
8165
8166void dAcPy_c::executeState_DemoEatDie() {
8167 switch (mDemoSubstate) {
8168 case 2:
8169 if (mDemoSubstateTimer == 0) {
8170 if (m_15a8 != 0) {
8171 startSound(SE_PLY_DOWN, false);
8172 } else if (!isStar()) {
8173 if (mPowerup == POWERUP_MUSHROOM) {
8174 fn_801416c0(POWERUP_NONE);
8175 } else {
8176 fn_801416c0(POWERUP_MUSHROOM);
8177 }
8178 startSound(SE_PLY_CHANGE_SMALL, false);
8179 mDamageInvulnTimer = 127;
8180 }
8181 mDemoSubstate = 1;
8182 }
8183 break;
8184 case 0:
8185 case 1:
8187 releaseEatDie();
8188 }
8189 break;
8190 case 3:
8191 if (mDemoSubstateTimer == 0) {
8192 checkRest();
8193 mDemoSubstate = 4;
8194 }
8195 break;
8196 }
8197}
8198
8199void dAcPy_c::releaseEatDie() {
8200 if (!isItemKinopio() && m_7c) {
8201 SndSceneMgr::sInstance->fn_8019bd90(1);
8202 }
8203 changeNormalAction();
8204 checkDisplayOutDead();
8205}
8206
8207bool dAcPy_c::setEatDieHide() {
8208 if (isDemoState(StateID_DemoEatDie)) {
8209 mPyMdlMng.mpMdl->offStarEffect();
8211 mDemoSubstate = 1;
8212 return true;
8213 }
8214 return false;
8215}
8216
8217bool dAcPy_c::setEatDieFadeOut() {
8218 if (isDemoState(StateID_DemoEatDie)) {
8219 daPyMng_c::startMissBGM(mPlayerNo);
8220 mDemoSubstate = 3;
8221 mDemoSubstateTimer = 80;
8222 return true;
8223 }
8224 return false;
8225}
8226
8227bool dAcPy_c::setEatDieSpitOut() {
8228 if (isDemoState(StateID_DemoEatDie)) {
8229 releaseEatDie();
8230 return true;
8231 }
8232 return false;
8233}
8234
8235void dAcPy_c::setEatDieScreamVoice() {
8236 if (isDemoState(StateID_DemoEatDie)) {
8237 startPlayerVoice(VOICE_DAMAGE_EATEN, 0);
8238 mDemoSubstate = 2;
8239 mDemoSubstateTimer = 30;
8240 }
8241}
8242
8243bool dAcPy_c::searchDoorActor() {
8244 dActor_c *door = nullptr;
8245 while ((door = (dActor_c *) fManager_c::searchBaseByGroupType(ACTOR, door)) != nullptr) {
8246 if (
8247 door->mProfName == fProfile::EN_DOOR ||
8248 door->mProfName == fProfile::EN_OBAKEDOOR ||
8249 door->mProfName == fProfile::EN_TORIDEDOOR ||
8250 door->mProfName == fProfile::EN_CASTLEDOOR
8251 ) {
8252 if (std::fabs(door->mPos.x - mPos.x) < 16.0f && std::fabs(door->mPos.y - mPos.y) < 16.0f) {
8253 mRelatedActorID = door->mUniqueID;
8254 return true;
8255 }
8256 }
8257 }
8259 return false;
8260}
8261
8262void dAcPy_c::initializeState_DemoInDoor() {
8264 m_74 = 255;
8265 changeState(StateID_Walk, BLEND_DEFAULT);
8266 mPyMdlMng.setAnm(PLAYER_ANIM_DOOR_WALK);
8267 mAngle.y = 0;
8268 if (mLayer == 0) {
8269 setZPosition(2800.0f);
8270 } else {
8271 setZPosition(-2000.0f);
8272 }
8273 mDamageInvulnTimer = 35;
8274 searchDoorActor();
8275 if (daPyDemoMng_c::mspInstance->checkDemoNo(mPlayerNo) != 0) {
8276 mDemoSubstate = 0;
8277 } else {
8278 mDemoSubstate = 2;
8279 }
8280}
8281
8282void dAcPy_c::finalizeState_DemoInDoor() {
8283 mDamageInvulnTimer = 0;
8284 mPowerupChangeInvulnTimer = 0;
8285 m_74 = 0;
8287}
8288
8289void dAcPy_c::setDemoInDoor_Walk() {
8291 mDemoSubstate = 4;
8292 mDemoSubstateTimer = 10;
8293}
8294
8295void dAcPy_c::executeState_DemoInDoor() {
8296 daEnDoor_c *door = nullptr;
8298 door = (daEnDoor_c *) fManager_c::searchBaseByID(mRelatedActorID);
8299 }
8300 if (door == nullptr) {
8302 searchDoorActor();
8303 } else {
8304 changeNormalAction();
8305 }
8306 return;
8307 }
8308 switch (mDemoSubstate) {
8309 case 0:
8311 door->m_5d4 = 1;
8312 if (door->m_5cc == 0) {
8313 door->m_5cc = 2;
8314 }
8315 mDemoSubstate++;
8316 }
8317 break;
8318 case 1:
8319 if (door->m_5d0 != 0) {
8320 setDemoInDoor_Walk();
8321 }
8322 break;
8323 case 2:
8324 if (daPyDemoMng_c::mspInstance->checkDemoNo(mPlayerNo)) {
8325 setDemoInDoor_Walk();
8326 }
8327 break;
8328 case 4:
8329 sLib::chase(&m_74, 0, 15);
8330 onStatus(STATUS_79);
8331 if (mDemoSubstateTimer == 0) {
8332 if (daPyDemoMng_c::mspInstance->getNextDemoNo() == -1) {
8333 mDemoSubstate = 5;
8335 daEnDoor_c *tmpDoor = (daEnDoor_c *) fManager_c::searchBaseByID(mRelatedActorID);
8336 if (tmpDoor != nullptr && (tmpDoor->m_5cc == 1 || tmpDoor->m_5cc == 2)) {
8337 tmpDoor->m_5cc = 3;
8338 }
8339 }
8340 } else {
8341 mDemoSubstate = 6;
8342 }
8343 }
8344 break;
8345 case 5:
8346 sLib::chase(&m_74, 0, 15);
8347 onStatus(STATUS_79);
8348 if (door->isClosed()) {
8349 mDemoSubstate = 6;
8350 }
8351 break;
8352 case 6:
8353 sLib::chase(&m_74, 0, 15);
8354 onStatus(STATUS_79);
8355 short ang = getMukiAngle(mDirection);
8356 if (!addCalcAngleY(ang, 10)) {
8357 daPyDemoMng_c::mspInstance->turnNextDemoNo();
8358 mAngle.y = ang;
8359 changeNormalAction();
8360 }
8361 }
8362}
8363
8364void dAcPy_c::initializeState_DemoInJump() {
8366 mDemoSubstateTimer = 30;
8367 mPyMdlMng.setAnm(PLAYER_ANIM_JUMP, 0.0f, 0.0f);
8368 u8 jumpDir = (int) mDemoStateArg;
8369 mDirection = jumpDir;
8370 mSpeedF = sc_DirSpeed[jumpDir] * 0.5f;
8371 mMaxSpeedF = sc_DirSpeed[jumpDir] * 0.5f;
8372 if (mPowerup == POWERUP_MINI_MUSHROOM) {
8373 mSpeed.y = 4.2f;
8374 } else {
8375 mSpeed.y = 5.0f;
8376 }
8377 mMaxFallSpeed = sc_MaxFallSpeed;
8378 setButtonJumpGravity();
8379 mAngle.y = getMukiAngle(mDirection);
8380}
8381
8382void dAcPy_c::finalizeState_DemoInJump() {}
8383
8384void dAcPy_c::executeState_DemoInJump() {
8385 switch (mDemoSubstate) {
8386 case 0:
8387 if (mDemoSubstateTimer == 0 && daPyDemoMng_c::mspInstance->checkDemoNo(mPlayerNo)) {
8388 mDemoSubstateTimer = 30;
8389 mDemoSubstate++;
8390 }
8391 break;
8392 case 1:
8393 if (mDemoSubstateTimer == 0) {
8394 daPyDemoMng_c::mspInstance->turnNextDemoNo();
8395 mDemoSubstateTimer = 95;
8396 mDemoSubstate++;
8397 int world = dScStage_c::m_instance->mCurrWorld;
8398 if (world == WORLD_4 || world == WORLD_6 || world == WORLD_8) {
8399 if (dScStage_c::m_instance->mCurrCourse == STAGE_DOOMSHIP) {
8400 startPlayerVoice(VOICE_JR_A_BATTLE_APP, 0);
8401 }
8402 }
8403 }
8404 break;
8405 case 2:
8406 setButtonJumpGravity();
8407 calcSpeedXY();
8408 posMove();
8409 if (mSpeed.y < 0.0f) {
8410 changeNormalAction();
8411 changeState(StateID_Fall, false);
8412 }
8413 break;
8414 }
8415}
8416
8417void dAcPy_c::initializeState_DemoInVine() {
8418 mPyMdlMng.setAnm(PLAYER_ANIM_PEA_PLANT, 0.0f, 0.0f);
8420 mDemoSubstateTimer = 30;
8421 mDirection = DIR_LR_R;
8422 mAngle.y = 0x8000;
8423 dEnemyMng_c::m_instance->demo_ivy_create(&mPos);
8424}
8425
8426void dAcPy_c::finalizeState_DemoInVine() {}
8427
8428void dAcPy_c::executeState_DemoInVine() {
8429 switch (mDemoSubstate) {
8430 case 0:
8431 if (mDemoSubstateTimer == 0 && daPyDemoMng_c::mspInstance->checkDemoNo(mPlayerNo) != 0) {
8432 mDemoSubstateTimer = 30;
8433 mDemoSubstate++;
8434 }
8435 break;
8436 case 1:
8437 if (mDemoSubstateTimer == 0) {
8438 daPyDemoMng_c::mspInstance->turnNextDemoNo();
8439 mDemoSubstateTimer = 95;
8440 mDemoSubstate++;
8441 }
8442 break;
8443 case 2:
8444 mPos.y += 1.0f;
8445 setIvyHangEffect();
8446 setVineWalkSE();
8447 mBc.checkHead(0);
8448 if (mDemoSubstateTimer == 0) {
8449 changeNormalAction();
8450 changeState(StateID_Vine, (void *) 1);
8451 }
8452 break;
8453 }
8454}
8455
8456bool dAcPy_c::isDoorDemoEnable() {
8457 if (!isEnableDokanInStatus()) {
8458 return false;
8459 }
8460 if (mKey.buttonDoor()) {
8461 if (isDemoState(StateID_DemoNone) && isOldBgCross(BGC_FOOT) && ((int) mPos.y & 0xf) == 0) {
8462 return true;
8463 }
8464 }
8465 return false;
8466}
8467
8468bool dAcPy_c::setDoorDemo(dActor_c *door) {
8469 if (isDoorDemoEnable()) {
8470 mVec3_c doorEnterPos(
8471 door->mPos.x,
8472 (int) mPos.y,
8473 mPos.z
8474 );
8475 int nextGoto;
8476 if (dNext_c::m_instance->searchNextNum(dScStage_c::m_instance->mCurrFile, doorEnterPos.x, doorEnterPos.y + 1.0f, &nextGoto)) {
8477 mDokanEnterNextGotoID = nextGoto;
8478 if (dNext_c::m_instance->isNextDifferent(dScStage_c::m_instance->mCurrFile, mDokanEnterNextGotoID)) {
8479 return false;
8480 }
8481 if (daPyDemoMng_c::mspInstance->m_5c != 0) {
8482 return false;
8483 }
8484 dNext_c::m_instance->setChangeSceneNextDat(dScStage_c::m_instance->mCurrFile, mDokanEnterNextGotoID, dFader_c::FADER_CIRCLE_TARGET);
8485 mRelatedActorID = door->mUniqueID;
8486 mWarpPos = doorEnterPos;
8487 mDoorSize = 0;
8488 int profName = door->mProfName;
8489 if (
8490 profName == fProfile::EN_TORIDEDOOR ||
8491 profName == fProfile::EN_CASTLEDOOR
8492 // || profName == fProfile::EN_KOOPADOOR
8493 ) {
8494 mDoorSize = 1;
8495 }
8496 changeDemoState(StateID_DemoOutDoor, 0);
8498 return true;
8499 }
8500 }
8501 return false;
8502}
8503
8504void dAcPy_c::initializeState_DemoOutDoor() {
8505 dAcPy_c *carryPlayer = getCarryPlayer();
8506 if (carryPlayer != nullptr) {
8507 releaseCarryActor();
8508 }
8509 mDemoSubstate = DEMO_OUT_DOOR_OPEN_DOOR;
8510 mSpeedF = 0.0f;
8511 mMaxSpeedF = 0.0f;
8512 mSpeed.set(0.0f, 0.0f, 0.0f);
8513 float z = daPyDemoMng_c::mspInstance->get_88() * 64.0f;
8514 daPyDemoMng_c::mspInstance->inc_88();
8515 if (mLayer == 0) {
8516 setZPosition(2800.0f + z);
8517 } else {
8518 setZPosition(-2000.0f + z);
8519 }
8520 mPyMdlMng.setAnm(PLAYER_ANIM_WAIT);
8521 mAngle.x = 0;
8522 if (daPyMng_c::mNum == 1) {
8523 stopOther();
8524 }
8525 mVec3_c pos(mWarpPos.x, mWarpPos.y, 0.0f);
8526 if (mRelatedActorID != 0) {
8527 daEnDoor_c *door = (daEnDoor_c *) fManager_c::searchBaseByID(mRelatedActorID);
8528 if (door != nullptr && door->m_5cc == 0) {
8529 door->m_5cc = 1;
8530 }
8531 }
8532}
8533
8534void dAcPy_c::finalizeState_DemoOutDoor() {
8536}
8537
8538void dAcPy_c::exeDemoOutDoor_OpenDoor() {
8539 addCalcAngleY(0x8000, 2);
8540 if (mRelatedActorID != 0) {
8541 daEnDoor_c *door = (daEnDoor_c *) fManager_c::searchBaseByID(mRelatedActorID);
8542 if (door != nullptr && door->m_5d0 != 0) {
8543 static const float scDoorEnterWidth[] = { 8.0f, 10.0f };
8544 if (std::fabs(mPos.x - mWarpPos.x) > scDoorEnterWidth[mDoorSize]) {
8545 initDemoOutDoor_MoveCenter();
8546 } else {
8547 initDemoOutDoor_MoveInter();
8548 }
8549 }
8550 }
8551}
8552
8553void dAcPy_c::initDemoOutDoor_MoveCenter() {
8554 mDemoSubstateTimer = 10;
8555 float speed = std::fabs(mPos.x - mWarpPos.x) / mDemoSubstateTimer;
8556 if (speed > 1.0f) {
8557 speed = 1.0f;
8558 }
8559 mSpeedF = speed;
8560 mDemoSubstate = DEMO_OUT_DOOR_MOVE_CENTER;
8561
8562 float animSpeed = (speed * 2.0f < 2.0f) ? 2.0f : speed * 2.0f;
8563 mPyMdlMng.setAnm(PLAYER_ANIM_RUN, animSpeed, 0.0f, 0.0f);
8564}
8565
8566void dAcPy_c::exeDemoOutDoor_MoveCenter() {
8567 if (std::fabs(mPos.x - mWarpPos.x) < 1.0f) {
8568 initDemoOutDoor_MoveInter();
8569 return;
8570 }
8571 if (mPos.x < mWarpPos.x) {
8572 addCalcAngleY(getMukiAngle(DIR_LR_R), 2);
8573 } else {
8574 addCalcAngleY(getMukiAngle(DIR_LR_L), 2);
8575 }
8577}
8578
8579void dAcPy_c::initDemoOutDoor_MoveInter() {
8580 mDemoSubstateTimer = 30;
8581 mDemoSubstate = DEMO_OUT_DOOR_MOVE_INTER;
8582 mPyMdlMng.setAnm(PLAYER_ANIM_DOOR_WALK);
8583 endPowerUpEffect();
8584}
8585
8586void dAcPy_c::exeDemoOutDoor_MoveInter() {
8587 addCalcAngleY(0x8000, 2);
8588 sLib::chase(&m_1598, 2.0f, 0.2f);
8589 sLib::chase(&m_74, 255, 15);
8590 if (mDoorSize == 0) {
8591 sLib::chase(&mPos.x, mWarpPos.x, 0.4f);
8592 }
8593 if (mDemoSubstateTimer != 0) {
8594 return;
8595 }
8596 bool hasNonEnteredPlayer = false;
8597 int count = 0;
8598 for (int i = 0; i < PLAYER_COUNT; i++) {
8599 dAcPy_c *player = daPyMng_c::getCtrlPlayer(i);
8600 if (player == nullptr || player == this) {
8601 continue;
8602 }
8603 if (daPyMng_c::mActPlayerInfo & (1 << (u8) i)) {
8604 if (!player->isStatus(STATUS_64)) {
8605 hasNonEnteredPlayer = true;
8606 }
8607 } else {
8608 if (player->isStatus(STATUS_53)) {
8609 count++;
8610 }
8611 }
8612 }
8613 if (!hasNonEnteredPlayer && count == 0) {
8615 daEnDoor_c *door = (daEnDoor_c *) fManager_c::searchBaseByID(mRelatedActorID);
8616 if (door != nullptr) {
8617 if ((door->m_5cc == 1 || door->m_5cc == 2)) {
8618 door->m_5cc = 3;
8619 }
8620 mDemoSubstate = DEMO_OUT_DOOR_WAIT_CLOSE;
8621 }
8622 }
8623 } else {
8624 mDemoSubstate = DEMO_OUT_DOOR_WAIT_ENTER;
8625 }
8626 m_1598 = 0.0f;
8628 mDemoSubstateTimer = 20;
8629}
8630
8631void dAcPy_c::exeDemoOutDoor_WaitClose() {
8632 addCalcAngleY(0x8000, 2);
8633 if (mDemoSubstateTimer != 0) {
8634 return;
8635 }
8636 if (mRelatedActorID != nullptr) {
8637 daEnDoor_c *door = (daEnDoor_c *) fManager_c::searchBaseByID(mRelatedActorID);
8638 if (door != nullptr && door->isClosed()) {
8639 changeNextScene(1);
8640 mDemoSubstate = DEMO_OUT_DOOR_FINISHED;
8641 }
8642 }
8643}
8644
8645void dAcPy_c::exeDemoOutDoor_WaitEnter() {
8646 if (mDemoSubstateTimer == 0) {
8647 changeNextScene(1);
8648 mDemoSubstate = DEMO_OUT_DOOR_FINISHED;
8649 }
8650}
8651
8652void dAcPy_c::executeState_DemoOutDoor() {
8653 typedef void (dAcPy_c::*DemoOutDoorProc)();
8654 static DemoOutDoorProc sDemoOutDoorProc[] = {
8655 &dAcPy_c::exeDemoOutDoor_OpenDoor,
8656 &dAcPy_c::exeDemoOutDoor_MoveCenter,
8657 &dAcPy_c::exeDemoOutDoor_MoveInter,
8658 &dAcPy_c::exeDemoOutDoor_WaitClose,
8659 &dAcPy_c::exeDemoOutDoor_WaitEnter,
8660 };
8661 if (mDemoSubstate != DEMO_OUT_DOOR_FINISHED) {
8662 (this->*sDemoOutDoorProc[mDemoSubstate])();
8663 }
8664}
8665
8666bool dAcPy_c::initDemoDokanCannon(mVec3_c &pos, int cannonMode) {
8667 if (isEnableDokanInStatus()) {
8668 m_68 = cannonMode;
8669 mWarpPos = pos;
8670 changeDemoState(StateID_DemoDokanCannon, 0);
8672 return true;
8673 }
8674 return false;
8675}
8676
8677void dAcPy_c::endDemoDokanCannon(mVec3_c &pos) {
8678 mPos.x = pos.x;
8679 mPos.y = pos.y;
8681}
8682
8683bool dAcPy_c::isDokanCannonIn() {
8684 if (isDemoState(StateID_DemoDokanCannon) && isStatus(STATUS_INVISIBLE)) {
8685 return true;
8686 }
8687 return false;
8688}
8689
8690void dAcPy_c::initializeState_DemoDokanCannon() {
8691 onStatus(STATUS_5A);
8692 mpMdlMng->setAnm(PLAYER_ANIM_WAIT, 0.0f, 5.0f, scDokanWaitAnmFixFrame);
8693 initDemoOutDokan();
8694}
8695
8696void dAcPy_c::finalizeState_DemoDokanCannon() {
8697 offStatus(STATUS_5A);
8699}
8700
8701void dAcPy_c::executeState_DemoDokanCannon() {
8702 switch (mDemoSubstate) {
8703 case 0:
8704 sLib::chase(&mPos.x, mWarpPos.x, scDokanInSpeedX);
8705 if (std::fabs(mPos.x - mWarpPos.x) <= scDokanInWidthX) {
8706 if (m_68 != 2) {
8707 setScrollMode(4);
8708 }
8709 mDemoSubstate++;
8710 }
8711 break;
8712 case 1:
8713 if (sLib::chase(&mPos.y, mWarpPos.y - 32.0f, scDokanInMoveSpeed)) {
8715 mDemoSubstate++;
8716 }
8717 break;
8718 case 2:
8719 checkDisplayOutDead();
8720 break;
8721 }
8722}
8723
8724int dAcPy_c::setDemoGoal(mVec3_c &landPos, float goalCastleX, u8 goalType) {
8725 daYoshi_c *yoshi = getRideYoshi();
8726 if (yoshi != nullptr) {
8727 return yoshi->setDemoGoal(landPos, goalCastleX, goalType);
8728 } else {
8729 return daPlBase_c::setDemoGoal(landPos, goalCastleX, goalType);
8730 }
8731}
8732
8733void dAcPy_c::setOffYoshiInGoal(daPlBase_c *yoshi) {
8734 changeState(StateID_RideOffJump, 0);
8737 mGoalTouchOrder = yoshi->mGoalTouchOrder;
8738 mWarpPos = yoshi->mWarpPos;
8739}
8740
8741bool dAcPy_c::setHideNotGoalPlayer() {
8742 if (isStatus(STATUS_OUT_OF_PLAY) || isStatus(STATUS_53) || isItemKinopio()) {
8743 return false;
8744 }
8745 return daPlBase_c::setHideNotGoalPlayer();
8746}
8747
8748void dAcPy_c::initDemoGoalBase() {
8749 mDirection = DIR_LR_R;
8750 endPowerUpEffect();
8751 dActor_c *carryActor = (dActor_c *) fManager_c::searchBaseByID(mCarryActorID);
8752 if (carryActor != nullptr) {
8753 carryActor->mPos.x = mPos.x;
8754 }
8755 releaseCarryActor();
8756 daPlBase_c::initDemoGoalBase();
8757 if ((int) mDemoStateArg == 1) {
8758 setDemoGoalMode(3, 6);
8759 mPyMdlMng.setAnm(PLAYER_ANIM_GET_DOWN, 0.0f, 0.0f);
8760 mSpeed.y = sc_JumpSpeed - 0.2f;
8761 mSpeedF = 1.0f;
8762 mDemoState = CONTROL_DEMO_KINOPIO_SWIM;
8763 mDirection = DIR_LR_L;
8764 mAngle.y = getMukiAngle(DIR_LR_L);
8765 }
8766}
8767
8768void dAcPy_c::executeDemoGoal_Run() {
8769 switch (mDemoState) {
8770 case 0:
8771 if (mGoalTouchOrder >= 3 && dGameCom::rnd() < 0.5f) {
8772 mDemoSubstateTimer = 60;
8773 mDemoState = 2;
8774 } else {
8775 mDemoSubstateTimer = mGoalTouchOrder * 5 + 10;
8776 mDemoState = 1;
8777 }
8778 for (int i = 0; i < PLAYER_COUNT; i++) {
8779 daYoshi_c *yoshi = daPyMng_c::getYoshi(i);
8780 if (yoshi != nullptr && yoshi->isStatus(STATUS_GOAL_POLE_TOUCHED)) {
8781 mDemoSubstateTimer += 14;
8782 break;
8783 }
8784 }
8785 case 1:
8786 case 2:
8787 if (mDemoSubstateTimer == 0) {
8788 daPyDemoMng_c::mspInstance->mFlags |= 0x20;
8789 if (mGoalTouchOrder == 0) {
8790 daPyDemoMng_c::mspInstance->setDemoMode(daPyDemoMng_c::MODE_2, 0);
8791 }
8792 mDirection = DIR_LR_R;
8793 mSpeed.set(0.0f, 0.0f, 0.0f);
8794 mDemoSubstateTimer = 60;
8795 mSpeedF = 1.9499999f;
8796 float f = 2.6f;
8797 if (mPowerup == POWERUP_MINI_MUSHROOM) {
8798 f = 2.0f * f;
8799 } else if (mDemoState == 2) {
8800 mSpeedF = 2.25f;
8801 f = 3.0f;
8802 }
8803 mPyMdlMng.setAnm(PLAYER_ANIM_RUN, f, 5.0f, 0.0f);
8804 mDemoState = 3;
8805 }
8806 break;
8807 case 3:
8808 turnAngle();
8809 if (mPos.x > mWarpPos.x) {
8810 float height;
8811 if (dBc_c::checkGround(&mPos, &height, 0, 1, -1)) {
8812 if (mPos.y < height + 1.0f) {
8813 mPos.y = height + 1.0f;
8814 }
8815 }
8816 mPos.z = -1800.0f;
8817 }
8818 if (sLib::chase(&mPos.x, mWarpPos.x + 32.0f, mSpeedF)) {
8819 mPyMdlMng.setAnm(PLAYER_ANIM_WAIT);
8820 mDemoState = 4;
8821 onStatus(STATUS_6E);
8822 }
8823 break;
8824 case 4:
8825 mPos.z = -1800.0f;
8826 break;
8827 case 6:
8828 setNormalJumpGravity();
8829 mSpeed.y += mAccelY;
8830 if (mSpeed.y < sc_MaxFallSpeed) {
8831 mSpeed.y = sc_MaxFallSpeed;
8832 }
8833 mPos.y += mSpeed.y;
8834 mPos.x += mSpeedF;
8835 if (isNowBgCross(BGC_FOOT)) {
8836 mSpeedF = 0.0f;
8837 mPyMdlMng.setAnm(PLAYER_ANIM_JUMPED);
8838 setLandSE();
8839 mDemoState = 7;
8840 }
8841 break;
8842 case 7:
8843 if (mPyMdlMng.isAnmStop()) {
8844 mPyMdlMng.setAnm(PLAYER_ANIM_WAIT);
8845 mDemoState = 1;
8846 mDemoSubstateTimer = mGoalTouchOrder * 5;
8847 }
8848 break;
8849 }
8850}
8851
8852bool dAcPy_c::updateDemoKimePose(ClearType_e clearType) {
8853 switch (mKimePoseMode) {
8854 case KIME_POSE_NONE:
8855 mPyMdlMng.setAnm(PLAYER_ANIM_WAIT);
8856 if (mPowerup == POWERUP_PROPELLER_SHROOM) {
8857 mKimePoseMode = KIME_POSE_PROPELLER;
8858 mPyMdlMng.setAnm(PLAYER_ANIM_PL_GOAL_PUTON_CAP);
8859 } else if (mPowerup == POWERUP_PENGUIN_SUIT) {
8860 mKimePoseMode = KIME_POSE_PENGUIN;
8861 mPyMdlMng.setAnm(PLAYER_ANIM_P_GOAL_PUTON_CAP);
8862 } else {
8863 if (
8864 mPyMdlMng.mpMdl->m_151 == mPyMdlMng.mpMdl->get151CheckVal() ||
8865 mPyMdlMng.mpMdl->m_151 == 3 ||
8866 mPyMdlMng.mpMdl->m_151 == 4
8867 ) {
8868 mKimePoseMode = KIME_POSE_NO_HAT;
8869 } else {
8870 mKimePoseMode = KIME_POSE_WITH_HAT;
8871 }
8872 mPyMdlMng.setAnm(PLAYER_ANIM_GOAL_PUTON_CAP);
8873 }
8874 startKimePoseVoice(clearType);
8875 // fallthrough
8876 case KIME_POSE_WITH_HAT: {
8877 dMarioMdl_c *mdl = (dMarioMdl_c *) mPyMdlMng.mpMdl;
8878 if (mPyMdlMng.mpMdl->mAnm.checkFrame(41.0f)) {
8879 mdl->fn_800cab00(1);
8880 break;
8881 }
8882 if (mPyMdlMng.mpMdl->mAnm.checkFrame(107.0f)) {
8883 mdl->fn_800cab00(0);
8884 break;
8885 }
8886 if (mPyMdlMng.isAnmStop()) {
8887 offStatus(STATUS_6C);
8888 return true;
8889 }
8890 break;
8891 }
8892 case KIME_POSE_PROPELLER:
8893 if (mPyMdlMng.mpMdl->mAnm.checkFrame(5.0f)) {
8894 onStatus(STATUS_70);
8895 break;
8896 }
8897 if (mPyMdlMng.mpMdl->mAnm.checkFrame(12.0f)) {
8898 offStatus(STATUS_70);
8899 break;
8900 }
8901 if (mPyMdlMng.isAnmStop()) {
8902 offStatus(STATUS_6C);
8903 return true;
8904 }
8905 break;
8906 case KIME_POSE_PENGUIN:
8907 case KIME_POSE_NO_HAT:
8908 if (mPyMdlMng.isAnmStop()) {
8909 offStatus(STATUS_6C);
8910 return true;
8911 }
8912 break;
8913 }
8914 return false;
8915}
8916
8917void dAcPy_c::initializeDemoControl() {
8918 releaseCarryActor();
8919 if (isStatus(STATUS_72)) {
8920 clearPropelFlyUpTime();
8921 }
8922}
8923
8924bool dAcPy_c::setDemoCannonWarp(int delay, short angX, short angY) {
8925 if (!isDemo()) {
8926 changeDemoState(StateID_DemoCannonWarp, 0);
8927 mAngle.x = angX + 0x2000;
8928 mAngle.y = angY + 0x6000;
8929 mDemoSubstateTimer = delay;
8930 return true;
8931 }
8932 return false;
8933}
8934
8935void dAcPy_c::initializeState_DemoCannonWarp() {
8936 mPyMdlMng.setAnm(PLAYER_ANIM_SHOOT);
8937 mAccelY = 0.0f;
8938 mMaxFallSpeed = sc_MaxFallSpeed;
8939 m_78 = 60;
8940}
8941
8942void dAcPy_c::finalizeState_DemoCannonWarp() {}
8943
8944void dAcPy_c::executeState_DemoCannonWarp() {
8945 switch (mDemoSubstate) {
8946 case 0:
8947 if (mDemoSubstateTimer == 0) {
8948 mDemoSubstate = 1;
8949 mAccelF = 0.0f;
8950 mSpeed.y = mAng(mAngle.x).sin() * 4.0f;
8951 mSpeedF = mAng(mAngle.x).cos() * 4.0f;
8952 mSpeed.x = mSpeedF * mAng(mAngle.y).sin();
8953 mSpeed.z = mSpeedF * mAng(mAngle.y).cos();
8954 mAmiRelated2 = 1.0f;
8955 dQuake_c::m_instance->shockMotor(mPlayerNo, dQuake_c::TYPE_5, 0, false);
8956 startPlayerVoice(VOICE_CANNON_SHOT, 0);
8957 }
8958 break;
8959 case 1: {
8960 int ang = cM::atan2s(std::fabs(mSpeedF), mSpeed.y);
8961 mAngle.x = 0x4000 - ang;
8962 if (m_78 != 0) {
8963 m_78--;
8964 mAccelY = 0.0f;
8965 } else {
8966 if (mSpeed.y < 1.0f) {
8967 mAccelY = -0.0625f;
8968 } else {
8969 mAccelY = -0.125f;
8970 }
8971 }
8972 mSpeed.y += mAccelY;
8973 if (mSpeed.y < sc_MaxFallSpeed) {
8974 mSpeed.y = sc_MaxFallSpeed;
8975 }
8976 posMove();
8977 mVec3_c efPos;
8978 mPyMdlMng.mpMdl->getJointPos(&efPos, 1);
8979 static const float sc_slipEffectScale[] = { 0.5f, 0.8f, 1.0f };
8980 float s = mAmiRelated2 * sc_slipEffectScale[getTallType(-1)];
8981 mVec3_c efScale(s, s, s);
8982 dEf::createPlayerEffect(mPlayerNo, &mSlipSmokeEffect, "Wm_mr_slipsmoke", 0, &efPos, nullptr, &efScale);
8983 if (sLib::chase(&mAmiRelated2, 0.0f, 0.008f)) {
8985 mDemoSubstate = 2;
8986 mDemoSubstateTimer = 30;
8987 }
8988 break;
8989 }
8990 case 2:
8991 if (mDemoSubstateTimer == 0) {
8992 mDemoSubstate = 3;
8993 mDemoSubstateTimer = 90;
8994 dEf::createPlayerEffect(mPlayerNo, "Wm_ob_warpcannonkira", 0, &mPos, nullptr, nullptr);
8995 dAudio::g_pSndObjMap->startSound(SE_OBJ_WARP_CANNON_SHINE, mPos, 0);
8996 }
8997 break;
8998 case 3:
8999 if (mDemoSubstateTimer == 0) {
9000 mDemoSubstate = 4;
9001 dScStage_c::setNextScene(3, 0, dScStage_c::EXIT_0, dFader_c::FADER_CIRCLE_TARGET);
9002 if (daPyDemoMng_c::mspInstance->mPlayerNo < 0) {
9003 daPyDemoMng_c::mspInstance->mPlayerNo = mPlayerNo;
9004 }
9005 }
9006 break;
9007 }
9008}
9009
9010bool dAcPy_c::isEnableDokanInStatus() {
9011 if (!daPlBase_c::isEnableDokanInStatus()) {
9012 return false;
9013 }
9014
9015 if (isCarry() && getCarryPlayer() == nullptr) {
9016 return false;
9017 }
9018
9019 if (getRidePlayer() != nullptr) {
9020 return false;
9021 }
9022
9023 if (isChange()) {
9024 return false;
9025 }
9026
9027 return !isStatus(STATUS_RIDE_YOSHI);
9028}
9029
9030bool dAcPy_c::setDokanIn(DokanDir_e dir) {
9031 if (isStatus(STATUS_7E)) {
9032 return false;
9033 }
9034
9035 dAcPy_c *carryPlayer = getCarryPlayer();
9036 if (carryPlayer != nullptr) {
9037 int nextGotoNum;
9038 switch (dir) {
9039 case DOKAN_D:
9040 if (mKey.buttonDown() && mBc.checkDokanDown(&mWarpPos, &nextGotoNum)) {
9041 if (setDemoOutDokanAction(nextGotoNum, dir)) {
9042 return true;
9043 }
9044 }
9045 break;
9046 case DOKAN_U:
9047 if (carryPlayer->mKey.buttonUp() && mBc.checkDokanUp(&mWarpPos, &nextGotoNum)) {
9048 carryPlayer->mWarpPos = mWarpPos;
9049 if (carryPlayer->setDemoOutDokanAction(nextGotoNum, dir)) {
9050 return true;
9051 }
9052 }
9053 break;
9054 default:
9055 break;
9056 }
9057 return false;
9058 }
9059
9060 return daPlBase_c::setDokanIn(dir);
9061}
9062
9063void dAcPy_c::initDemoOutDokan() {
9064 daPlBase_c::initDemoOutDokan();
9065
9066 if (getCarryPlayer() != nullptr) {
9067 releaseCarryActor();
9068 }
9069
9070 dAcPy_c *ridePlayer = getRidePlayer();
9071 if (ridePlayer != nullptr) {
9072 ridePlayer->cancelCarry(this);
9073 }
9074}
9075
9076void dAcPy_c::initialDoor() {
9077 changeDemoState(StateID_DemoInDoor, 0);
9078}
9079
9080void dAcPy_c::initialJumpRight() {
9081 changeDemoState(StateID_DemoInJump, 0);
9082}
9083
9084void dAcPy_c::initialJumpLeft() {
9085 changeDemoState(StateID_DemoInJump, 1);
9086}
9087
9088void dAcPy_c::initialVine() {
9089 changeDemoState(StateID_DemoInVine, 0);
9090}
9091
9092void dAcPy_c::initialSwim() {
9093 changeState(StateID_Swim, SWIM_ARG_INITIAL);
9095 onDemo();
9096 mSpeed.y = -1.0f;
9097 bgCheck(0);
9098}
9099
9100void dAcPy_c::initialBlockJump() {
9101 playOther();
9103 changeDemoState(StateID_DemoControl, CONTROL_DEMO_WAIT);
9104}
9105
9106void dAcPy_c::initialBlockJumpBelow() {
9107 playOther();
9108 changeState(StateID_BlockJump, (void *) 1); // [This might have initially meant to be StateID_HipAttack].
9109 changeDemoState(StateID_DemoControl, CONTROL_DEMO_WAIT);
9110}
9111
9112void dAcPy_c::setCreateAction(int action) {
9113 mExecStopReq |= BIT_FLAG(0) | BIT_FLAG(3);
9114 if (daPyMng_c::isCreateBalloon(mPlayerNo) && setBalloonInNextgoto()) {
9115 return;
9116 }
9117 if (daPyMng_c::mCreateItem[daPyMng_c::mPlayerType[mPlayerNo]] & 2) {
9118 daYoshi_c *yoshi = daPyMng_c::createYoshi(mPos, daPyMng_c::getYoshiColor(mPlayerNo), this);
9119 if (yoshi != nullptr) {
9120 yoshi->mFruitCount = daPyMng_c::getYoshiFruit(mPlayerNo);
9121 }
9122 } else {
9123 daPlBase_c::setCreateAction(action);
9124 }
9125}
9126
9127void dAcPy_c::initChangeInit() {
9129 playOther();
9130 } else {
9131 playGoalOther();
9132 }
9133 dAudio::pauseOffMove(mPlayerNo);
9134}
9135
9136bool dAcPy_c::executeChangeInit() {
9137 if (mPowerup == mPowerupCopy2) {
9138 return false;
9139 }
9140 setPowerup(mPowerupCopy2, 0);
9141 stopOther();
9142 dAudio::pauseMove(mPlayerNo);
9143 setChange(1);
9144 if (mPowerup == POWERUP_MINI_MUSHROOM) {
9145 float jumpSpeed = getJumpSpeed();
9146 if (mSpeed.y > jumpSpeed) {
9147 mSpeed.y = jumpSpeed;
9148 }
9149 releaseCarryActor();
9150 }
9151 return isPlayerGameStop();
9152}
9153
9155 int res = 6 - mChangeTimer / 6;
9156 if (res < 0) {
9157 res = 0;
9158 }
9159 /// @unofficial
9160 static const float ratios[] = {
9161 0.4f, 0.2f, 0.6f, 0.4f, 0.8f, 0.6f, 1.0f
9162 };
9163 /// @unofficial
9164 struct Keyframe {
9165 float startScaleY, endScaleY;
9166 float startScaleX, endScaleX;
9167 float unk;
9168 };
9169 /// @unofficial
9170 static const Keyframe data[] = {
9171 {
9172 0.6f, 1.0f,
9173 0.6f, 1.0f,
9174 6.0f
9175 },
9176 {
9177 0.36f, 1.0f,
9178 0.6f, 1.0f,
9179 20.0f
9180 },
9181 {
9182 1.0f, 0.6f,
9183 1.0f, 0.6f,
9184 -10.0f
9185 },
9186 {
9187 0.6f, 1.0f,
9188 1.0f, 1.0f,
9189 10.0f
9190 },
9191 {
9192 1.0f, 0.36f,
9193 1.0f, 0.6f,
9194 -20.0f
9195 },
9196 {
9197 1.0f, 0.6f,
9198 1.0f, 1.0f,
9199 -10.0f
9200 },
9201 {
9202 1.0f, 1.0f,
9203 1.0f, 1.0f,
9204 0.0f
9205 },
9206 {
9207 0.0f, 0.0f,
9208 0.0f, 0.0f,
9209 0.0f
9210 }
9211 };
9212 if (mChangeTimer != 0) {
9213 if (m_67 != 7) {
9214 float ratioA = 1.0f - ratios[res];
9215 float ratioB = ratios[res];
9216 Keyframe curr = data[m_67];
9217 float x = curr.startScaleX * ratioA + curr.endScaleX * ratioB;
9218 float y = curr.startScaleY * ratioA + curr.endScaleY * ratioB;
9219 mScale.set(x, y, x);
9220 m_159c = 0.0f;
9221 if (isStatus(STATUS_HANG)) {
9222 m_159c = curr.unk * ratioA;
9223 }
9224 }
9225 } else {
9226 mScale.set(1.0f, 1.0f, 1.0f);
9227 m_159c = 0.0f;
9228 }
9229 return res;
9230}
9231
9232void dAcPy_c::initChangeNormal() {
9233 mChangeTimer = 30;
9234 int prevTallType = getTallType(mPowerupCopy);
9235 int currTallType = getTallType(-1);
9236 if (isStatus(STATUS_HANG)) {
9237 static const float offsets[3] = { 21.0f, 11.0f, 0.0f };
9238 mPos.y += offsets[currTallType] - offsets[prevTallType];
9239 }
9240 static const int tallTypeChange[3][3] = {
9241 {7, 7, 1},
9242 {2, 7, 3},
9243 {4, 5, 6}
9244 };
9245 m_67 = tallTypeChange[prevTallType][currTallType];
9246 switch (m_67) {
9247 case 0:
9248 case 1:
9249 case 3:
9250 if (mPowerup == POWERUP_PROPELLER_SHROOM) {
9251 startSound(SE_PLY_CHANGE_PRPL, false);
9252 } else if (mPowerup == POWERUP_PENGUIN_SUIT) {
9253 startSound(SE_PLY_CHANGE_PNGN, false);
9254 } else {
9255 startSound(SE_PLY_CHANGE_BIG, false);
9256 }
9257 break;
9258 case 2:
9259 case 4:
9260 startSound(SE_PLY_CHANGE_MAME, false);
9261 break;
9262 case 5:
9263 case 6:
9264 if (mPowerup == POWERUP_PROPELLER_SHROOM) {
9265 startSound(SE_PLY_CHANGE_PRPL, false);
9266 } else if (mPowerup == POWERUP_PENGUIN_SUIT) {
9267 startSound(SE_PLY_CHANGE_PNGN, false);
9268 } else if (mPowerup == POWERUP_FIRE_FLOWER || mPowerup == POWERUP_ICE_FLOWER) {
9269 startSound(SE_PLY_CHANGE_BIG, false);
9270 } else {
9271 startSound(SE_PLY_CHANGE_SMALL, false);
9272 }
9273 break;
9274 }
9275}
9276
9277bool dAcPy_c::executeChangeNormal() {
9278 int frame = change_reverse_scale_set();
9279 PLAYER_POWERUP_e powerup = mPowerup;
9280 if (mChangeTimer != 0) {
9281 if ((frame & 1) != 0) {
9282 powerup = mPowerupCopy;
9283 }
9284 if (powerup == POWERUP_NONE || powerup == POWERUP_MINI_MUSHROOM) {
9285 powerup = mPowerup;
9286 if (
9287 mPowerup == POWERUP_NONE && mPowerupCopy == POWERUP_MINI_MUSHROOM ||
9288 mPowerup == POWERUP_MINI_MUSHROOM && mPowerupCopy == POWERUP_NONE
9289 ) {
9290 powerup = POWERUP_NONE;
9291 } else {
9292 powerup = POWERUP_MUSHROOM;
9293 }
9294 }
9295 } else {
9296 setChange(0);
9297 mPowerupChangeInvulnTimer = 8;
9298 }
9299 mPyMdlMng.mpMdl->setPlayerMode(powerup);
9300 switch (powerup) {
9301 case POWERUP_FIRE_FLOWER:
9302 mPyMdlMng.mpMdl->setColorType(1);
9303 break;
9304 case POWERUP_ICE_FLOWER:
9305 mPyMdlMng.mpMdl->setColorType(2);
9306 break;
9307 default:
9308 mPyMdlMng.mpMdl->setColorType(0);
9309 break;
9310 }
9311 return isPlayerGameStop();
9312}
9313
9314void dAcPy_c::setChange(int mode) {
9315 mChangeType = mode;
9316 typedef void (dAcPy_c::*ChangeInitProc)();
9317 static ChangeInitProc l_changeInitProc[] = {
9318 &dAcPy_c::initChangeInit,
9319 &dAcPy_c::initChangeNormal
9320 };
9321 (this->*l_changeInitProc[mChangeType])();
9322 updateChange();
9323 setCcData();
9324}
9325
9326bool dAcPy_c::updateChange() {
9327 typedef bool (dAcPy_c::*ChangeActionProc)();
9328 static ChangeActionProc l_changeActionProc[] = {
9329 &dAcPy_c::executeChangeInit,
9330 &dAcPy_c::executeChangeNormal
9331 };
9332 if (mChangeType >= 2) {
9333 setChange(0);
9334 return false;
9335 }
9336 if (mChangeTimer != 0) {
9337 mChangeTimer--;
9338 }
9339 if ((this->*l_changeActionProc[mChangeType])()) {
9340 mVisible = true;
9341 setBcData(0);
9342 bgCheck(1);
9343 mBgPressActive = 0;
9344 return true;
9345 }
9346 return false;
9347}
9348
9350 mPowerupCopy2 = powerup;
9351 setPowerup(powerup, 0);
9352}
9353
9354void dAcPy_c::initializeState_DemoStartWait() {
9355 daPlBase_c::initializeState_DemoStartWait();
9356}
9357
9358void dAcPy_c::executeState_DemoStartWait() {
9359 if (!isNowBgCross(BGC_WATER_SHALLOW)) {
9360 bgCheck(0);
9361 if (isNowBgCross(BGC_WATER_SHALLOW)) {
9362 onOldBgCross(BGC_WATER_SHALLOW);
9364 }
9365 }
9366 daPlBase_c::executeState_DemoStartWait();
9367}
9368
9369void dAcPy_c::finalizeState_DemoStartWait() {
9370 daPlBase_c::finalizeState_DemoStartWait();
9371}
9372
9374 switch (type) {
9375 case 1:
9376 startPlayerVoice(VOICE_DAMAGE_FIRE, 0);
9377 break;
9378 case 2:
9379 startPlayerVoice(VOICE_DAMAGE_FREEZE, 0);
9380 break;
9381 default:
9382 startPlayerVoice(VOICE_HIP_ATTACKED, 0);
9383 break;
9384 }
9385 dQuake_c::m_instance->shockMotor(mPlayerNo, dQuake_c::TYPE_7, 0, false);
9386}
9387
9388///< @unofficial
9389const int l_tall_type_offsets[] = { 0x8000, 0xF800, 0x1F800 };
9390
9391const sCcDatNew l_cc_data_mame = {
9392 { 0.0f, 4.0f },
9393 { 2.0f, 4.0f }
9394};
9395
9396const sCcDatNew l_cc_data_normal = {
9397 { 0.0f, 7.0f },
9398 { 4.0f, 7.0f }
9399};
9400
9401const sCcDatNew l_cc_data_super = {
9402 { 0.0f, 12.0f },
9403 { 6.0f, 12.0f }
9404};
9405
9406const sCcDatNew l_cc_data_propel = {
9407 { 0.0f, 12.0f },
9408 { 6.0f, 12.0f }
9409};
9410
9411const sCcDatNew l_cc_data_normal_sit = {
9412 { 0.0f, 3.5f },
9413 { 4.0f, 3.5f }
9414};
9415
9416const sCcDatNew l_cc_data_super_sit = {
9417 { 0.0f, 7.0f },
9418 { 6.0f, 7.0f }
9419};
9420
9421const sCcDatNew l_cc_data_normal_swim = {
9422 { 0.0f, 8.0f },
9423 { 4.0f, 6.0f }
9424};
9425
9426const sCcDatNew l_cc_data_super_swim = {
9427 { 0.0f, 15.0f },
9428 { 6.0f, 9.0f }
9429};
9430
9431const sCcDatNew l_cc_data_normal_waterwalk = {
9432 { 0.0f, 7.5f },
9433 { 4.0f, 7.5f }
9434};
9435
9436const sCcDatNew l_cc_data_super_waterwalk = {
9437 { 0.0f, 14.0f },
9438 { 6.0f, 14.0f }
9439};
9440
9441const sCcDatNew l_cc_data_penguin_slid = {
9442 { 6.0f, 8.0f },
9443 { 12.0f, 8.0f }
9444};
9445
9446enum CcSizeDataIndex_e {
9447 CC_SIZE_DATA_MAME,
9448 CC_SIZE_DATA_NORMAL,
9449 CC_SIZE_DATA_SUPER,
9450 CC_SIZE_DATA_PROPEL,
9451 CC_SIZE_DATA_NORMAL_SIT,
9452 CC_SIZE_DATA_SUPER_SIT,
9453 CC_SIZE_DATA_NORMAL_SWIM,
9454 CC_SIZE_DATA_SUPER_SWIM,
9455 CC_SIZE_DATA_NORMAL_WATERWALK,
9456 CC_SIZE_DATA_SUPER_WATERWALK,
9457 CC_SIZE_DATA_PENGUIN_SLID
9458};
9459
9460const sCcDatNew *l_cc_size_data[] = {
9461 &l_cc_data_mame,
9462 &l_cc_data_normal,
9463 &l_cc_data_super,
9464 &l_cc_data_propel,
9465 &l_cc_data_normal_sit,
9466 &l_cc_data_super_sit,
9467 &l_cc_data_normal_swim,
9468 &l_cc_data_super_swim,
9469 &l_cc_data_normal_waterwalk,
9470 &l_cc_data_super_waterwalk,
9471 &l_cc_data_penguin_slid
9472};
9473
9474const CcSizeDataIndex_e l_mode_cc_size_data[] = {
9475 CC_SIZE_DATA_NORMAL, CC_SIZE_DATA_SUPER, CC_SIZE_DATA_SUPER, CC_SIZE_DATA_MAME, CC_SIZE_DATA_PROPEL, CC_SIZE_DATA_SUPER, CC_SIZE_DATA_SUPER
9476};
9477
9478const sCcDatNewF scCcData = {
9479 {
9480 { 0.0f, 8.0f },
9481 { 3.0f, 8.0f }
9482 },
9483 CC_KIND_PLAYER,
9484 CC_ATTACK_NONE,
9485 (u8) ~BIT_FLAG(CC_KIND_YOSHI),
9486 (u32) ~(BIT_FLAG(CC_ATTACK_NONE) | BIT_FLAG(CC_ATTACK_YOSHI_MOUTH) | BIT_FLAG(CC_ATTACK_SAND_PILLAR)),
9487 CC_STATUS_NONE,
9488 dAcPy_c::ccCallBack
9489};
9490
9491const sCcDatNewF scAtCcData = {
9492 {
9493 { 0.0f, 8.0f },
9494 { 6.0f, 6.0f }
9495 },
9496 CC_KIND_PLAYER_ATTACK,
9497 CC_ATTACK_NONE,
9498 (u8) ~(BIT_FLAG(CC_KIND_YOSHI) | BIT_FLAG(CC_KIND_ITEM) | BIT_FLAG(CC_KIND_TAMA)),
9499 0,
9500 CC_STATUS_NONE,
9501 dAcPy_c::atCcCallBack
9502};
9503
9504bool dAcPy_c::ccCheckAttack(dCc_c *self, dCc_c *other) {
9505 dAcPy_c *selfPlayer = (dAcPy_c *) self->getOwner();
9506 dActor_c *otherActor = (dActor_c *) other->getOwner();
9507
9508 if (other->mCcData.mKind == CC_KIND_PLAYER || other->mCcData.mKind == CC_KIND_PLAYER_ATTACK) {
9509 if (selfPlayer->mNoInteractTimer != 0) {
9510 return false;
9511 }
9512 if (otherActor->mKind == STAGE_ACTOR_PLAYER) {
9513 dAcPy_c *otherPlayer = (dAcPy_c *) otherActor;
9514 if (otherPlayer->mNoInteractTimer != 0) {
9515 return false;
9516 }
9517 if (selfPlayer->checkRideActor(otherPlayer)) {
9518 return false;
9519 }
9520 }
9521 }
9522
9523 if (other->mCcData.mAttack == CC_ATTACK_SPIN) {
9524 if (otherActor->mKind == STAGE_ACTOR_PLAYER) {
9525 dAcPy_c *otherPlayer = (dAcPy_c *) otherActor;
9526 if (!otherPlayer->checkCarryActor(selfPlayer)) {
9527 selfPlayer->checkCarryActor(otherPlayer);
9528 }
9529 return true;
9530 }
9531 return true;
9532 }
9533
9534 if (selfPlayer->isNoDamage()) {
9535 return false;
9536 }
9537
9538 dAcPy_c *otherPlayer = (dAcPy_c *) otherActor;
9539
9540 switch (other->mCcData.mAttack) {
9541 case CC_ATTACK_HIP_ATTACK:
9542 case CC_ATTACK_SPIN_FALL: {
9543 DamageType_e damageType = DAMAGE_HIP_ATTACK;
9544 if (selfPlayer->isClimbing()) {
9545 damageType = DAMAGE_CLIMB;
9546 }
9547 if (selfPlayer->setDamage(otherActor, damageType)) {
9548 if (other->mCcData.mAttack == CC_ATTACK_HIP_ATTACK) {
9549 otherPlayer->setVsPlHipAttackEffect();
9550 }
9551
9552 selfPlayer->setHipAttackDamagePlayer(otherPlayer);
9553 }
9554 return true;
9555 }
9556 case CC_ATTACK_WIRE_NET:
9557 selfPlayer->setDamage(other->getOwner(), DAMAGE_CLIMB);
9558 return true;
9559 case CC_ATTACK_FIREBALL:
9560 case CC_ATTACK_ICEBALL:
9561 if (selfPlayer->getPlrNo() != otherActor->getPlrNo() && !selfPlayer->isStatus(STATUS_IS_SPIN_HOLD_REQ)) {
9562 selfPlayer->setFireBallDamage(other->mCcData.mAttack);
9563 }
9564 return true;
9565 case CC_ATTACK_YOSHI_BULLET:
9566 case CC_ATTACK_YOSHI_FIRE:
9567 case CC_ATTACK_ICE_2:
9568 if (selfPlayer->getPlrNo() != otherActor->getPlrNo() && !selfPlayer->isStatus(STATUS_IS_SPIN_HOLD_REQ)) {
9569 if (selfPlayer->isStatus(STATUS_51)) {
9570 selfPlayer->mSpeedF = daPlBase_c::sc_DirSpeed[other->getOwner()->mDirection];
9571 selfPlayer->mNoInteractTimer = 0;
9572 } else {
9573 selfPlayer->mNoInteractTimer = 30;
9574 if (!selfPlayer->setDamage(other->getOwner(), DAMAGE_6)) {
9575 return false;
9576 }
9577 }
9578 selfPlayer->setFireBallDamage(other->mCcData.mAttack);
9579 }
9580 return true;
9581 default:
9582 return false;
9583 }
9584}
9585
9586bool dAcPy_c::ccCheckStamp(dCc_c *self, dCc_c *other) {
9587 dAcPy_c *selfPlayer = (dAcPy_c *) self->getOwner();
9588 daPlBase_c *otherActor = (daPlBase_c *) other->getOwner();
9589
9590 if (
9591 selfPlayer->mSpeed.y <= 0.0f &&
9592 !selfPlayer->isStatus(STATUS_JUMP_DAI_COOLDOWN) &&
9593 !selfPlayer->isDemoType(DEMO_PLAYER) &&
9594 selfPlayer->isStatus(STATUS_CAN_LAND)
9595 ) {
9596 if (otherActor->mKind == STAGE_ACTOR_YOSHI) {
9597 daYoshi_c *yoshi = (daYoshi_c *) otherActor;
9598 if (
9599 self->getCenterPosY() > other->getUnderPos() &&
9600 (!selfPlayer->isNowBgCross(BGC_FOOT) || selfPlayer->isOnSinkSand()) &&
9601 yoshi->m_94 == 0
9602 ) {
9603 return yoshi->fn_8014eb70(selfPlayer, 0);
9604 }
9605 }
9606 if (selfPlayer->isEnableStampPlayerJump(self, other)) {
9607 if (otherActor->isStatus(STATUS_JUMP) && otherActor->mSpeed.y > 0.0f) {
9608 selfPlayer->setStampPlayerJump(true, self->mCollOffsetY[CC_KIND_PLAYER]);
9609 otherActor->setStampReduction();
9610 return true;
9611 }
9612 if (selfPlayer->setPlayerJumpDai(otherActor)) {
9613 return true;
9614 }
9615 }
9616 }
9617 return false;
9618}
9619
9620bool dAcPy_c::ccCheckSideHit(dCc_c *self, dCc_c *other) {
9621 dAcPy_c *selfPlayer = (dAcPy_c *) self->getOwner();
9622 daPlBase_c *otherActor = (daPlBase_c *) other->getOwner();
9623
9624 if (otherActor->isDemo()) {
9625 selfPlayer->setCcPlayerRev(self, other, 1.0f, CC_KIND_PLAYER);
9626 return true;
9627 }
9628
9629 static const float sCcRevRate[3][3] = {
9630 { 0.5f, 1.0f, 1.0f },
9631 { 0.0f, 0.5f, 0.5f },
9632 { 0.0f, 0.5f, 0.5f },
9633 };
9634 u8 selfTallType = selfPlayer->getTallType(-1);
9635 u8 otherTallType = otherActor->getTallType(-1);
9636 selfPlayer->setCcPlayerRev(self, other, sCcRevRate[selfTallType][otherTallType], CC_KIND_PLAYER);
9637
9638 return true;
9639}
9640
9641void dAcPy_c::ccCallBack(dCc_c *self, dCc_c *other) {
9642 dActor_c *otherActor;
9643 dAcPy_c *selfPlayer;
9644
9645 selfPlayer = (dAcPy_c *) self->getOwner();
9646 otherActor = (dActor_c *) other->getOwner();
9647
9648 if (other->mCcData.mKind == CC_KIND_PLAYER || other->mCcData.mKind == CC_KIND_YOSHI) {
9649 daPlBase_c *otherPlayer = (daPlBase_c *) otherActor;
9650 if (selfPlayer == otherPlayer->mpNoHitPlayer || otherPlayer == selfPlayer->mpNoHitPlayer) {
9651 return;
9652 }
9653 }
9654
9655 if (ccCheckAttack(self, other)) {
9656 return;
9657 }
9658
9659 if (other->mCcData.mKind == CC_KIND_PLAYER && otherActor->mKind == STAGE_ACTOR_PLAYER) {
9660 daPlBase_c *otherPlayer = (daPlBase_c *) otherActor;
9661 if (selfPlayer->checkRideActor(otherPlayer)) {
9662 return;
9663 }
9664 if (ccCheckStamp(self, other)) {
9665 return;
9666 }
9667 if (ccCheckSideHit(self, other)) {
9668 return;
9669 }
9670 }
9671
9672 if (other->mCcData.mKind == CC_KIND_YOSHI) {
9673 daYoshi_c *yoshi = (daYoshi_c *) otherActor;
9674 if (selfPlayer->checkRideActor(yoshi)) {
9675 return;
9676 }
9677 if (ccCheckStamp(self, other)) {
9678 return;
9679 }
9680 if (yoshi->m_94 == 0) {
9681 return;
9682 }
9683
9684 static const float sCcRevRate[] = { 1.0f, 0.8f, 0.6f };
9685 selfPlayer->setCcPlayerRev(self, other, sCcRevRate[selfPlayer->getTallType(-1)], CC_KIND_YOSHI);
9686 }
9687}
9688
9689void dAcPy_c::setCcDataDirect() {
9690 const sCcDatNew *ccData = l_cc_size_data[l_mode_cc_size_data[mPowerup]];
9691 m_0c.x = ccData->mOffset.x;
9692 m_0c.y = ccData->mOffset.y + m_1598 + m_159c;
9693 mCc.mCcData.mBase.mOffset.set(m_0c.x, m_0c.y);
9694 mCc.mCcData.mBase.mSize.set(ccData->mSize.x, ccData->mSize.y);
9695}
9696
9697void dAcPy_c::setCcAtNetPunch() {
9698 float s = mPyMdlMng.getSomeScale();
9699 mAttCc1.mCcData.mAttack = CC_ATTACK_WIRE_NET;
9700 mAttCc1.mCcData.mBase.mOffset.set(s * 8.0f, s * 16.0f);
9701 mAttCc1.mCcData.mBase.mSize.set(s * 12.0f, s * 12.0f);
9702}
9703
9704void dAcPy_c::setCcAtSpin() {
9705 float y = (getModelHeight() + 4.0f) / 2.0f;
9706 mAttCc1.mCcData.mBase.mOffset.set(mCc.mCcData.mBase.mOffset.x, y);
9707 float x = mCc.mCcData.mBase.mSize.x;
9708 mAttCc1.mCcData.mBase.mSize.set(x * 3.5f, y);
9709 mAttCc1.mCcData.mVsKind |= BIT_FLAG(CC_KIND_PLAYER_ATTACK);
9710 mAttCc1.mCcData.mAttack = CC_ATTACK_SPIN;
9711 mAttCc1.mCcData.mVsDamage = BIT_FLAG(CC_ATTACK_SPIN);
9712 mCc.mCcData.mVsDamage &= ~BIT_FLAG(CC_ATTACK_SPIN);
9713}
9714
9715void dAcPy_c::setCcAtSpinFall() {
9716 mAttCc1.mCcData.mBase.mOffset.set(0.0f, 10.0f);
9717 mAttCc1.mCcData.mBase.mSize.set(12.0f, 10.0f);
9718 mAttCc1.mCcData.mAttack = CC_ATTACK_SPIN_FALL;
9719 setCcAtBody(CC_ATTACK_SPIN_FALL);
9720}
9721
9723 float f = 18.0f;
9724 if (mPowerup == POWERUP_MINI_MUSHROOM) {
9725 f = 8.0f;
9726 } else if (mPowerup == POWERUP_NONE) {
9727 f = 16.0f;
9728 }
9729 if (bounds == nullptr) {
9730 return;
9731 }
9732 float h = (getModelHeight() + 4.0f) / 2.0f;
9733 bounds->mOffset.x = 0.0f;
9734 bounds->mSize.x = f;
9735 bounds->mOffset.y = h;
9736 bounds->mSize.y = h;
9737}
9738
9739void dAcPy_c::setCcAtSpinLiftUp() {
9740 sRangeDataF bounds;
9741 getCcBounds(&bounds);
9742 mAttCc1.mCcData.mBase.mOffset.x = bounds.mOffset.x;
9743 mAttCc1.mCcData.mBase.mOffset.y = bounds.mOffset.y;
9744 mAttCc1.mCcData.mBase.mSize.x = bounds.mSize.x;
9745 mAttCc1.mCcData.mBase.mSize.y = bounds.mSize.y;
9746 mAttCc1.mCcData.mAttack = CC_ATTACK_SPIN_LIFT_UP;
9747 checkSpinLiftUpRoofHeight();
9748}
9749
9750void dAcPy_c::setCcData() {
9751 int sizeIndex = l_mode_cc_size_data[mPowerup];
9752 if (mPyMdlMng.getFlags() & 1) {
9753 switch (getPowerup()) {
9754 case POWERUP_MINI_MUSHROOM:
9755 break;
9756 case POWERUP_NONE:
9757 sizeIndex = CC_SIZE_DATA_NORMAL_SIT;
9758 break;
9759 default:
9760 sizeIndex = CC_SIZE_DATA_SUPER_SIT;
9761 break;
9762 }
9763 } else if (mPyMdlMng.getFlags() & 0x10) {
9764 switch (getPowerup()) {
9765 case POWERUP_MINI_MUSHROOM:
9766 break;
9767 case POWERUP_NONE:
9768 sizeIndex = CC_SIZE_DATA_NORMAL_SWIM;
9769 break;
9770 default:
9771 sizeIndex = CC_SIZE_DATA_SUPER_SWIM;
9772 break;
9773 }
9774 } else if (isStatus(STATUS_PENGUIN_SLIDE)) {
9775 sizeIndex = CC_SIZE_DATA_PENGUIN_SLID;
9776 } else if (isStatus(STATUS_SWIM)) {
9777 switch (getPowerup()) {
9778 case POWERUP_MINI_MUSHROOM:
9779 break;
9780 case POWERUP_NONE:
9781 sizeIndex = CC_SIZE_DATA_NORMAL_WATERWALK;
9782 break;
9783 default:
9784 sizeIndex = CC_SIZE_DATA_SUPER_WATERWALK;
9785 break;
9786 }
9787 }
9788
9790 onStatus(STATUS_78);
9791 mMtx_c mtx;
9792 mVec3_c pos;
9793 mPyMdlMng.mpMdl->getJointMtx(&mtx, 1);
9794 mtx.concat(mMtx_c::createTrans(2.0f, 0.0f, 0.0f));
9795 mtx.multVecZero(pos);
9796 mCc.mCcData.mBase.mSize.set(6.0f, 6.0f);
9797 mCc.mCcData.mBase.mOffset.set(pos.x - mPos.x, pos.y - mPos.y);
9798 mPyMdlMng.mpMdl->getJointMtx(&mtx, mPyMdlMng.mpMdl->getFaceJointIdx());
9799 mtx.concat(mMtx_c::createTrans(0.0f, -4.0f, 0.0f));
9800 mtx.multVecZero(pos);
9801 mCc1.mCcData.mBase.mSize.set(6.0f, 6.0f);
9802 mCc1.mCcData.mBase.mOffset.set(pos.x - mPos.x, pos.y - mPos.y);
9803 return;
9804 }
9805
9806 const sCcDatNew *ccData = l_cc_size_data[sizeIndex];
9807 float x = ccData->mOffset.x;
9808 if (mDirection == DIR_LR_L) {
9809 x = -x;
9810 }
9811 float sx = ccData->mSize.x;
9812 float sy = ccData->mSize.y;
9813 m_0c.set(x, ccData->mOffset.y + m_1598 + m_159c);
9814 mCc.mCcData.mBase.mSize.set(sx, sy);
9815 mCc.mCcData.mBase.mOffset.setX(m_0c.x);
9816 if (mPyMdlMng.mpMdl->mFlags & 4) {
9817 mMtx_c mtx;
9818 mVec3_c pos;
9819 mVec3_c anklePos = getAnkleCenterPos();
9820 float tmp = anklePos.y - 2.0f;
9821 if (tmp > mPos.y) {
9822 tmp = mPos.y;
9823 }
9824 mPyMdlMng.mpMdl->getJointMtx(&mtx, mPyMdlMng.mpMdl->getFaceJointIdx());
9825 mtx.concat(mMtx_c::createTrans(0.0f, -4.0f, 0.0f));
9826 mtx.multVecZero(pos);
9827 float tmp1 = (pos.y + tmp) / 2.0f;
9828 mCc.mCcData.mBase.mOffset.y = tmp1 - mPos.y;
9829 float tmp2 = (pos.y - tmp) / 2.0f;
9830 mCc.mCcData.mBase.mSize.y = std::fabs(tmp2);
9831 } else {
9832 mCc.mCcData.mBase.mOffset.y = m_0c.y;
9833 }
9834 dAcPy_c *ridePlayer = getRidePlayer();
9835 if (ridePlayer != nullptr && ridePlayer->mPowerup == POWERUP_NONE) {
9836 if (sizeIndex == 2) {
9837 mCc.mCcData.mBase.mOffset.y = 16.0f;
9838 mCc.mCcData.mBase.mSize.y = 8.0f;
9839 mCc.mCcData.mBase.mSize.x = 4.0f;
9840 } else if (sizeIndex == 1) {
9841 mCc.mCcData.mBase.mOffset.y = 9.0f;
9842 mCc.mCcData.mBase.mSize.y = 5.0f;
9843 mCc.mCcData.mBase.mSize.x = 4.0f;
9844 }
9845 }
9846 if (isStatus(STATUS_8E) || isStatus(STATUS_4F)) {
9847 mCc.mCcData.mVsKind &= ~(BIT_FLAG(CC_KIND_YOSHI) | BIT_FLAG(CC_KIND_PLAYER) | BIT_FLAG(CC_KIND_PLAYER_ATTACK));
9848 } else {
9849 mCc.mCcData.mVsKind |= (BIT_FLAG(CC_KIND_YOSHI) | BIT_FLAG(CC_KIND_PLAYER) | BIT_FLAG(CC_KIND_PLAYER_ATTACK));
9850 }
9851}
9852
9853void dAcPy_c::atCcCallBack(dCc_c *self, dCc_c *other) {
9854 dActor_c *otherActor;
9855 dAcPy_c *selfPlayer;
9856
9857 selfPlayer = (dAcPy_c *) self->getOwner();
9858 otherActor = (dActor_c *) other->getOwner();
9859
9860 if (self->mCcData.mAttack == CC_ATTACK_SPIN_LIFT_UP) {
9861 selfPlayer->checkSpinLiftUpReserve(other);
9862 return;
9863 }
9864
9865 if (selfPlayer->isNoDamage()) {
9866 return;
9867 }
9868
9869 if (other->mCcData.mKind == CC_KIND_PLAYER) {
9870 dAcPy_c *otherPlayer = (dAcPy_c *) otherActor;
9871 if (selfPlayer->mNoInteractTimer != 0 || otherPlayer->mNoInteractTimer != 0) {
9872 return;
9873 }
9874 }
9875
9876 if (self->mCcData.mAttack != CC_ATTACK_PENGUIN_SLIDE) {
9877 return;
9878 }
9879
9880 if (other->mCcData.mAttack != CC_ATTACK_PENGUIN_SLIDE) {
9881 return;
9882 }
9883
9884 selfPlayer->setDamage(otherActor, DAMAGE_CLIMB);
9885}
9886
9887const sBcPlayerPointData scBgPointData_Mame[5] = {
9888 {
9889 { 0xC8001, -0x1800, 0x1000, 0x0 },
9890 { 0x5C0001, -0x1000, 0x0, 0x7A00 },
9891 { 0xC0001, 0x3000, 0x4000, 0x5000 },
9892 { 0xC0001, 0x4000, 0x1000, 0x0 }
9893 },
9894 {
9895 { 0xC8001, -0x1800, 0x1000, 0x0 },
9896 { 0x5C0001, -0x1000, 0x0, 0x7A00 },
9897 { 0xC0001, 0x2800, 0x3800, 0x5000 },
9898 { 0xC0001, 0x4000, 0x1000, 0x0 }
9899 },
9900 {
9901 { 0xC8001, -0x2000, 0x1000, 0x0 },
9902 { 0x5C0001, -0x1000, 0x0, 0x1000 },
9903 { 0xC0001, -0x4000, -0x4000, 0x3000 },
9904 { 0xC0001, 0x4000, 0x1000, 0x0 }
9905 },
9906 {
9907 { 0xC8001, -0x1800, 0x1000, 0x0 },
9908 { 0x5C0001, -0x1000, 0x0, 0x7800 },
9909 { 0xC0001, 0x3000, 0x4000, 0x5000 },
9910 { 0xC0001, 0x4000, 0x1000, 0x0 }
9911 },
9912 {
9913 { 0xC8001, -0x1800, 0x1000, 0x0 },
9914 { 0x5C0001, -0x1000, 0x0, 0x7800 },
9915 { 0xC0001, 0x2800, 0x3800, 0x5000 },
9916 { 0xC0001, 0x4000, 0x1000, 0x0 }
9917 }
9918};
9919
9920const sBcPlayerPointData scBgPointData_Normal[5] = {
9921 {
9922 { 0xC8001, -0x5000, 0x4000, 0x0 },
9923 { 0x5C0001, -0x2000, 0x1000, 0x10000 },
9924 { 0xC0001, 0x4000, 0xB000, 0x8000 },
9925 { 0xC0001, 0x8000, 0x1000, 0x2000 }
9926 },
9927 {
9928 { 0xC8001, -0x5000, 0x4000, 0x0 },
9929 { 0x5C0001, -0x2000, 0x1000, 0xC000 },
9930 { 0xC0001, 0x4000, 0x8800, 0x8000 },
9931 { 0xC0001, 0x8000, 0x1000, 0x2000 }
9932 },
9933 {
9934 { 0xC8001, -0x5000, 0x4000, 0x0 },
9935 { 0x5C0001, -0x2000, 0x1000, 0x1000 },
9936 { 0xC0001, -0x4000, -0xE000, 0x8000 },
9937 { 0xC0001, 0x8000, 0x1000, 0x2000 }
9938 },
9939 {
9940 { 0xC8001, -0x5000, 0x4000, 0x0 },
9941 { 0x5C0001, -0x2000, 0x1000, 0x10000 },
9942 { 0xC0001, 0x4000, 0xA000, 0x8000 },
9943 { 0xC0001, 0x8000, 0x1000, 0x2000 }
9944 },
9945 {
9946 { 0xC8001, -0x5000, 0x4000, 0x0 },
9947 { 0x5C0001, -0x2000, 0x1000, 0xC000 },
9948 { 0xC0001, 0x4000, 0xA000, 0x8000 },
9949 { 0xC0001, 0x8000, 0x1000, 0x2000 }
9950 }
9951};
9952
9953const sBcPlayerPointData scBgPointData_Super[5] = {
9954 {
9955 { 0xC8001, -0x5000, 0x4000, 0x0 },
9956 { 0x9C0001, -0x2000, 0x1000, 0x1B000 },
9957 { 0xC0001, 0x4000, 0x13000, 0x8000 },
9958 { 0xC0001, 0x10000, 0x1000, 0x2000 }
9959 },
9960 {
9961 { 0xC8001, -0x5000, 0x4000, 0x0 },
9962 { 0x9C0001, -0x2000, 0x1000, 0x10000 },
9963 { 0xC0001, 0x4000, 0xB000, 0x8000 },
9964 { 0xC0001, 0xC000, 0x1000, 0x2000 }
9965 },
9966 {
9967 { 0xC8001, -0x5000, 0x4000, 0x0 },
9968 { 0x9C0001, -0x2000, 0x1000, 0x1000 },
9969 { 0xC0001, -0x4000, -0x18000, 0x8000 },
9970 { 0xC0001, 0x10000, 0x1000, 0x2000 }
9971 },
9972 {
9973 { 0xC8001, -0x5000, 0x4000, 0x0 },
9974 { 0x9C0001, -0x2000, 0x1000, 0x1B000 },
9975 { 0xC0001, 0x4000, 0x13000, 0x8000 },
9976 { 0xC0001, 0x10000, 0x1000, 0x2000 }
9977 },
9978 {
9979 { 0xC8001, -0x5000, 0x4000, 0x0 },
9980 { 0x9C0001, -0x2000, 0x1000, 0x12000 },
9981 { 0xC0001, 0x4000, 0x10000, 0x8000 },
9982 { 0xC0001, 0x10000, 0x1000, 0x2000 }
9983 }
9984};
9985
9986const sBcPlayerPointData scBgPointData_PenguinSlide = {
9987 { 0xC8101, -0xA000, 0x9000, 0x0 },
9988 { 0x9C0101, -0x7000, 0x6000, 0x12000 },
9989 { 0x129C0101, 0x4000, 0xD000, 0x10000 },
9990 { 0x0, 0x0, 0x0, 0x0 }
9991};
9992
9993const sBcPlayerPointData scBgPointData_PenguinSwim = {
9994 { 0xC8001, -0x5000, 0x4000, 0x4000 },
9995 { 0x9C0001, -0x2000, 0x1000, 0x1B000 },
9996 { 0xC0001, 0x8000, 0x17000, 0x8000 },
9997 { 0x0, 0x0, 0x0, 0x0 }
9998};
9999
10000const sBcPlayerPointData *scBgPointData[POWERUP_COUNT] = {
10001 scBgPointData_Normal,
10002 scBgPointData_Super,
10003 scBgPointData_Super,
10004 scBgPointData_Mame,
10005 scBgPointData_Super,
10006 scBgPointData_Super,
10007 scBgPointData_Super,
10008};
10009
10011 return &scBgPointData[powerup][index];
10012}
10013
10014float dAcPy_c::getStandHeadBgPointY() {
10015 return getBgPointData_Powerup(mPowerup, 0)->mHead.mOffset / 4096.0f;
10016}
10017
10018const sBcPlayerPointData *dAcPy_c::getBgPointData() {
10020 return &scBgPointData_PenguinSlide;
10021 }
10023 return &scBgPointData_PenguinSwim;
10024 }
10025 u32 flags = mPyMdlMng.mpMdl->mFlags;
10026 int bgDataIndex = 0;
10027 if (flags & BIT_FLAG(0)) {
10028 if (mPowerup != POWERUP_MINI_MUSHROOM) {
10029 bgDataIndex = 1;
10030 }
10031 } else if (flags & BIT_FLAG(2)) {
10032 bgDataIndex = 2;
10033 } else if (flags & BIT_FLAG(4)) {
10034 bgDataIndex = 3;
10035 } else if (mPyMdlMng.mpMdl->mCurrAnmID == PLAYER_ANIM_STAR_ROLL_DUPLICATE) {
10036 bgDataIndex = 4;
10037 }
10038 return getBgPointData_Powerup(mPowerup, bgDataIndex);
10039}
10040
10041void dAcPy_c::setBcData(int setInstant) {
10042 offStatus(STATUS_B8);
10043 if (isItemKinopio()) {
10044 onStatus(STATUS_B8);
10045 }
10046 const sBcPlayerPointData *data = getBgPointData();
10047 sBcPointData footData = data->mFoot;
10048 sBcPointData headData = data->mHead;
10049 sBcPointData wallData = data->mWall;
10050 sBcPointData vineData = data->mVine;
10051 if (!isMameAction() && !isStatus(STATUS_4E) && !isStatus(STATUS_ENEMY_STAGE_CLEAR)) {
10052 footData.mFlags |= 0x200000;
10053 }
10054 if (isStatus(STATUS_BD)) {
10055 footData.mFlags |= 0x10900100;
10056 wallData.mFlags |= 0x10900100;
10057 headData.mFlags |= 0x10900100;
10058 m_15b8 = 5;
10059 } else if (isStatus(STATUS_HANG)) {
10060 footData.mFlags |= 0x80000000;
10061 } else if (isStatus(STATUS_VINE)) {
10062 footData.mFlags |= 0x2000;
10063 wallData.mSupMargin = headData.mOffset - 0x2000;
10065 footData.mFlags |= 0xd00000;
10066 } else if (isState(StateID_HipAttack)) {
10067 switch (mPyMdlMng.mpMdl->mCurrAnmID) {
10068 case PLAYER_ANIM_HIPAT:
10069 if (mSpeed.y < 0.0f) {
10070 footData.mFlags |= 0x500000;
10071 if (isStatus(STATUS_C4)) {
10072 footData.mFlags |= 0x800000;
10073 }
10074 }
10075 break;
10076 case PLAYER_ANIM_HIPED:
10077 if (isStatus(STATUS_C4)) {
10078 footData.mFlags |= 0x900000;
10079 }
10080 break;
10081 }
10082 } else {
10083 if (isStatus(STATUS_52)) {
10084 headData.mFlags |= 0x4000000;
10085 wallData = getBgPointData_Powerup(mPowerup, 1)->mWall;
10086 float y = mPos.y + getStandHeadBgPointY() - 1.0f;
10087 mVec3_c pos(mPos.x, mPos.y + 4.0f, mPos.z);
10088 float height;
10089 if (dBc_c::checkTenjou(&pos, &height, mLayer, mAmiLayer)) {
10090 if (height < y && !dBc_c::checkBg(pos.x, height + 4.0f, mLayer, mAmiLayer, 0x10)) {
10091 footData.mFlags |= 0x800000;
10092 }
10093 }
10094 }
10095 }
10096 if (isChange()) {
10097 headData.mFlags |= 0x4000000;
10098 }
10100 footData.mFlags |= 0x10000;
10101 }
10102 if (isStatus(STATUS_A4)) {
10103 footData.mFlags |= 8;
10104 }
10105 if (isStatus(STATUS_7F)) {
10106 footData.mFlags |= 0x80000000;
10107 wallData.mFlags |= 0x80000000;
10108 headData.mFlags |= 0x80000000;
10109 }
10110 if (m_15b8 != 0) {
10111 footData.mFlags |= 0x100;
10112 wallData.mFlags |= 0x100;
10113 headData.mFlags |= 0x100;
10114 }
10115 if (mPowerup == POWERUP_PENGUIN_SUIT) {
10116 footData.mFlags |= 0x10;
10117 }
10118 if (isStatus(STATUS_EXTRA_PUSH_FORCE)) {
10119 footData.mFlags |= 0x20;
10120 }
10121 if (isStar()) {
10122 wallData.mFlags |= 0x2000000;
10123 headData.mFlags |= 0x2000000;
10124 }
10125 if (isStatus(STATUS_82)) {
10126 headData.mFlags |= 0x4000000;
10127 }
10128 reviseBcDataCarryHardBlock(wallData, headData);
10129 reviseBcDataCarryPlayer(wallData, headData);
10131 float angY = mAngle.y.sin() * 19456.0f;
10132 mAng x = mAngle.x;
10133 if (x > 0x2000) {
10134 x -= 0x2000;
10135 angY -= x.sin() * mAngle.y.sin() * 81920.0f;
10136 }
10137 headData.mInfMargin += angY;
10138 headData.mSupMargin += angY;
10139 }
10140 if (setInstant == 1) {
10141 mFootBcData = footData;
10142 mHeadBcData = headData;
10143 mWallBcData = wallData;
10144 mVineBcData = vineData;
10145 } else {
10146 sLib::chase(&mFootBcData.mInfMargin, footData.mInfMargin, 0x1000);
10147 sLib::chase(&mFootBcData.mSupMargin, footData.mSupMargin, 0x1000);
10148 sLib::chase(&mFootBcData.mOffset, footData.mOffset, 0x1000);
10149
10150 sLib::chase(&mHeadBcData.mInfMargin, headData.mInfMargin, 0x1000);
10151 sLib::chase(&mHeadBcData.mSupMargin, headData.mSupMargin, 0x1000);
10152
10153 sLib::chase(&mWallBcData.mInfMargin, wallData.mInfMargin, 0x1000);
10154 sLib::chase(&mWallBcData.mSupMargin, wallData.mSupMargin, 0x1000);
10155 sLib::chase(&mWallBcData.mOffset, wallData.mOffset, 0x1000);
10156
10157 sLib::chase(&mVineBcData.mInfMargin, vineData.mInfMargin, 0x1000);
10158 sLib::chase(&mVineBcData.mSupMargin, vineData.mSupMargin, 0x1000);
10159 sLib::chase(&mVineBcData.mOffset, vineData.mOffset, 0x1000);
10160
10161 if (mHeadBcData.mOffset < headData.mOffset) {
10162 mVec3_c pos(mPos.x, mPos.y + mHeadBcData.mOffset / 4096.0f + 1.0f, mPos.z);
10163 float height;
10164 if (dBc_c::checkTenjou(&pos, &height, mLayer, mAmiLayer)) {
10165 if (height < mPos.y + headData.mOffset / 4096.0f) {
10166 float tmp = height - mPos.y;
10167 if (tmp < 0.0f) {
10168 tmp = 0.0f;
10169 }
10170 headData.mOffset = (int) (tmp * 4096.0f);
10171 }
10172 }
10173 }
10174 sLib::chase(&mHeadBcData.mOffset, headData.mOffset, 0x1000);
10175 mFootBcData.mFlags = footData.mFlags;
10176 mHeadBcData.mFlags = headData.mFlags;
10177 mWallBcData.mFlags = wallData.mFlags;
10178 mVineBcData.mFlags = vineData.mFlags;
10179 }
10180 mBc.set(this, mFootBcData, mHeadBcData, mWallBcData);
10181 mBc.mAmiLine = getCcLineKind();
10182 mRc.mLineKind = getCcLineKind();
10183 mBc.mLayer = mLayer;
10184 mRc.mLayer = mLayer;
10185 if (m_15b2 != 0) {
10186 mRc.mFlags |= BIT_FLAG(1);
10187 } else {
10188 mRc.mFlags &= ~BIT_FLAG(1);
10189 }
10190}
10191
10192void dAcPy_c::fn_80143060(sBcPointData &data1, sBcPointData &data2, bool mode) {
10193 dAcPy_c *carryPlayer = getCarryPlayer();
10194 if (carryPlayer == nullptr) {
10195 return;
10196 }
10197
10198 const sBcPlayerPointData *data;
10199 if (mode) {
10200 data = getBgPointData_Powerup(carryPlayer->mPowerup, 1);
10201 } else {
10202 data = getBgPointData_Powerup(carryPlayer->mPowerup, 0);
10203 }
10204
10205 if (data1.mOffset < data->mWall.mOffset) {
10206 data1.mOffset = data->mWall.mOffset;
10207 }
10208
10209 int headOffset = data->mHead.mOffset + l_tall_type_offsets[getTallType(-1)];
10210 int wallLMargin = data->mWall.mSupMargin + l_tall_type_offsets[getTallType(-1)];
10211
10212 if (isStatus(STATUS_46)) {
10213 int thing = (int) (carryPlayer->mPos.y * 4096.0f) - (int) (mPos.y * 4096.0f);
10214 int tmp = data->mHead.mOffset + thing;
10215 if (headOffset > tmp) {
10216 headOffset = tmp;
10217 }
10218 if (headOffset < data2.mOffset) {
10219 headOffset = data2.mOffset;
10220 }
10221 int tmp2 = data->mWall.mSupMargin + thing;
10222 if (wallLMargin > tmp2) {
10223 wallLMargin = tmp2;
10224 }
10225 if (wallLMargin < data1.mSupMargin) {
10226 wallLMargin = data1.mSupMargin;
10227 }
10228 }
10229
10230 data2.mFlags = data->mHead.mFlags;
10231 data2.mInfMargin = data->mHead.mInfMargin;
10232 data2.mSupMargin = data->mHead.mSupMargin;
10233 data2.mOffset = headOffset;
10234 data1.mSupMargin = wallLMargin;
10235 if (!isMameAction()) {
10236 data2.mFlags = 0x9c0001;
10237 }
10238}
10239
10241 dAcPy_c *carryPlayer = getCarryPlayer();
10242 if (carryPlayer == nullptr) {
10243 return false;
10244 }
10245 mVec3_c pos(mPos.x, mPos.y + data2.mOffset / 4096.0f - 3.0f, mPos.z);
10246 PLAYER_POWERUP_e powerup = carryPlayer->mPowerup;
10247 float tmp = getBgPointData_Powerup(powerup, 0)->mHead.mOffset - getBgPointData_Powerup(powerup, 1)->mHead.mOffset;
10248 float val = mPos.y + data2.mOffset / 4096.0f + tmp / 4096.0f;
10249 float someOffset = data1.mOffset / 4096.0f - 1.0f;
10250 pos.x = mPos.x + someOffset;
10251 float height;
10252 if (dBc_c::checkTenjou(&pos, &height, mLayer, 1)) {
10253 if (height > pos.y && height <= val) {
10254 return true;
10255 }
10256 }
10257 if (!isStatus(STATUS_47)) {
10258 pos.x = mPos.x - (someOffset + 1.0f);
10259 if (dBc_c::checkTenjou(&pos, &height, mLayer, 1)) {
10260 if (height > pos.y && height <= val) {
10261 return true;
10262 }
10263 }
10264 }
10265 return false;
10266}
10267
10269 dAcPy_c *ridePlayer = getRidePlayer();
10270 if (ridePlayer != nullptr && !ridePlayer->isMameAction()) {
10271 data2.mFlags = 0x9c0001;
10272 }
10273 mBc.mRidePlrNo = -1;
10274 offStatus(STATUS_47);
10275 dAcPy_c *carryPlayer = getCarryPlayer();
10276 if (carryPlayer != nullptr) {
10277 mBc.mRidePlrNo = carryPlayer->getPlrNo();
10278 if (isStatus(STATUS_JUMP) && !isStatus(STATUS_48)) {
10279 fn_80143060(data1, data2, false);
10280 } else {
10281 fn_80143060(data1, data2, true);
10282 if (fn_80143220(data1, data2)) {
10283 onStatus(STATUS_47);
10284 }
10285 }
10286 }
10287}
10288
10290 if (getCarryHardBlock()) {
10291 const sBcPlayerPointData *data = getBgPointData_Powerup(mPowerup, 0);
10292 if (data1.mOffset < data->mWall.mOffset) {
10293 data1.mOffset = data->mWall.mOffset;
10294 }
10295 data2.mInfMargin = data->mHead.mInfMargin;
10296 data2.mSupMargin = data->mHead.mSupMargin;
10297 data2.mOffset += 0xc000;
10298 data2.mFlags = 0x9c0001;
10299 data1.mSupMargin += 0xc000;
10300 }
10301}
10302
10303void dAcPy_c::initCcData() {
10304 initCollision((sCcDatNewF *) &scCcData, (sCcDatNewF *) &scAtCcData);
10305}
10306
10307void dAcPy_c::initBcData() {
10308 mBc.init();
10309 setBcData(1);
10310 clearNowBgCross();
10311 clearOldBgCross();
10312}
10313
10314void dAcPy_c::maxFallSpeedSet() {
10315 if (isMameAction()) {
10316 mMaxFallSpeed = -2.5f;
10317 } else {
10318 mMaxFallSpeed = sc_MaxFallSpeed;
10319 }
10320}
10321
10322void dAcPy_c::set1UpKinokoEffect() {
10323 setFollowEffect(1);
10324}
10325
10326void dAcPy_c::setFlagGetEffect() {
10327 startPlayerVoice(VOICE_TYUKAN, 0);
10328 setFollowEffect(2);
10329}
10330
10331void dAcPy_c::setFollowEffect(int followType) {
10332 mFollowType = followType;
10333 if (mFollowType == 0) {
10334 return;
10335 }
10336 int efSizeType = 0;
10337 if (mPowerup == POWERUP_NONE) {
10338 efSizeType = 1;
10339 } else if (mPowerup == POWERUP_MINI_MUSHROOM) {
10340 efSizeType = 2;
10341 }
10342 mVec3_c efPos;
10343 mPyMdlMng.mpMdl->getJointPos(&efPos, 0);
10344 float s = mPyMdlMng.getSomeScale();
10345 mVec3_c efScale(s, s, s);
10346 if (mFollowType == 1) {
10347 static const char *sc_oneUpEffectID[] = {
10348 "Wm_mr_1upkira",
10349 "Wm_mr_1upkira_s",
10350 "Wm_mr_1upkira_ss"
10351 };
10352 dEf::createPlayerEffect_change(mPlayerNo, &mFollowEf4, sc_oneUpEffectID[efSizeType], 0, &efPos, nullptr, &efScale);
10353 } else if (mFollowType == 2) {
10354 static const char *sc_flagGetEffectID[] = {
10355 "Wm_mr_flaggetkira",
10356 "Wm_mr_flaggetkira_s",
10357 "Wm_mr_flaggetkira_ss"
10358 };
10359 dEf::createPlayerEffect(mPlayerNo, &mFollowEf4, sc_flagGetEffectID[efSizeType], 0, &efPos, nullptr, &efScale);
10360 }
10361}
10362
10363void dAcPy_c::updateFollowEffect() {
10364 if (mFollowType == 0) {
10365 return;
10366 }
10367
10368 mVec3_c efPos;
10369 mPyMdlMng.mpMdl->getJointPos(&efPos, 0);
10370 float s = mPyMdlMng.getSomeScale();
10371 mVec3_c efScale(s, s, s);
10372 if (!mFollowEf4.follow(&efPos, nullptr, &efScale)) {
10373 mFollowType = 0;
10374 }
10375}
10376
10377void dAcPy_c::calcTimerProc() {
10379 return;
10380 }
10381
10382 daPlBase_c::calcTimerProc();
10383 calcInvalidKeyTimer();
10384
10385 sLib::calcTimer(&mStarTimer);
10390 sLib::calcTimer(&m_15b2);
10391 sLib::calcTimer(&m_15ae);
10392 sLib::calcTimer(&m_2f0);
10394 sLib::calcTimer(&m_15b6);
10395 sLib::calcTimer(&m_60);
10396 sLib::calcTimer(&m_15b8);
10399 sLib::calcTimer(&m_b98);
10401 if (m_15b0 != 0 && !sLib::calcTimer(&m_15b0)) {
10402 mKey.clearShakeJump();
10403 }
10404}
10405
10406void dAcPy_c::executeMain() {
10407 mPc.chkTimer();
10408 setCenterOffset();
10409 updateItemGetEffect();
10410 managePropelFukidashi();
10411 if (updateChange()) {
10412 return;
10413 }
10414 calcReductionScale();
10415 if (!isStatus(STATUS_NO_ANIM)) {
10416 mPyMdlMng.play();
10417 }
10418 setFootSound();
10419 updatePropelParts();
10420 updateMissSpin();
10421 updateFollowEffect();
10422 calcStarTimer();
10423 daYoshi_c *yoshi = getRideYoshi();
10424 if (yoshi != nullptr) {
10425 if (yoshi->isDemo()) {
10426 return;
10427 }
10428 } else {
10429 if (executeDemoState()) {
10430 setCcDataDirect();
10431 return;
10432 }
10433 }
10434 calcTimerProc();
10435 selectAction();
10436 if (mSpeed.y < 0.75f) {
10437 offStatus(STATUS_96);
10438 }
10439 mPrevDirection = mDirection;
10440 int dir;
10441 if (!isStatus(STATUS_96) && !isStatus(STATUS_97) && mKey.buttonWalk(&dir)) {
10442 mDirection = dir;
10443 }
10444 executeState();
10445 if (mSquishNoMoveTimer == 0) {
10446 calcPlayerSpeedXY();
10447 }
10448 updateRideNat();
10449 setCcData();
10450 if (isStar()) {
10451 setCcAtStar();
10452 }
10453 setBcData(1);
10454 bgCheck(1);
10455 checkDispOver();
10456 onStatus(STATUS_77);
10457 if (mKey.mActionTriggered) {
10458 mKey.onStatus(dAcPyKey_c::STATUS_SHAKE_COOLDOWN);
10459 }
10460}
10461
10462void dAcPy_c::checkBgCrossSub() {
10463 if (mBc.checkPoleCollision(&mVineBcData)) {
10464 onNowBgCross(BGC_CAN_CLIMB);
10465 }
10466 u32 resFlags = mBc.checkVineCollision(&mVineBcData);
10467 if (resFlags & 0x0F) {
10468 onNowBgCross(BGC_VINE_TOUCH_FULL);
10469 if (resFlags & 0b1100) {
10470 onNowBgCross(BGC_VINE_TOUCH_D);
10471 }
10472 if (resFlags & 0b0011) {
10473 onNowBgCross(BGC_VINE_TOUCH_U);
10474 }
10475 }
10476 if (resFlags & 0x30) {
10477 onNowBgCross(BGC_VINE_TOUCH_2);
10478 }
10479 if (isAmiRollAction()) {
10480 onNowBgCross(BGC_VINE_TOUCH_L);
10481 onNowBgCross(BGC_VINE_TOUCH_R);
10482 return;
10483 }
10484 sBcPointData vineData = mVineBcData;
10485 int v = mWallBcData.mOffset * 0.7f;
10486 if (vineData.mOffset < v) {
10487 vineData.mOffset = v;
10488 }
10489 u32 resFlags2 = mBc.checkVineCollision(&vineData);
10490 if (resFlags2 & 1 || resFlags2 & 2) {
10491 onNowBgCross(BGC_VINE_TOUCH);
10492 }
10493 if (resFlags2 & 4 || resFlags2 & 8) {
10494 onNowBgCross(BGC_VINE_TOUCH);
10495 }
10496 if (resFlags2 & 1 || resFlags2 & 4) {
10497 onNowBgCross(BGC_VINE_TOUCH_L);
10498 }
10499 if (resFlags2 & 2 || resFlags2 & 8) {
10500 onNowBgCross(BGC_VINE_TOUCH_R);
10501 }
10502}
10503
10504void dAcPy_c::postBgCross() {
10505 if (!isMameAction()) {
10507 }
10508 if (isNowBgCross(BGC_WATER_TOUCH) && !isNowBgCross(BGC_WATER_BUBBLE)) {
10509 if (isNowBgCross(BGC_HEAD)) {
10510 m_15b6 = 10;
10513 if (mSpeed.y < 0.0f && m_15b6 == 0) {
10514 mPos.y = mWaterHeight;
10515 onNowBgCross(BGC_ON_WATER_MOVE);
10516 onNowBgCross(BGC_FOOT);
10518 onNowBgCross(BGC_ON_ICE);
10519 }
10520 offNowBgCross(BGC_WATER_SHALLOW);
10521 offNowBgCross(BGC_WATER_SUBMERGED);
10522 mWaterDepth = 0;
10523 mBc.mpCtrHead = nullptr;
10524 mRc.clrLink();
10525 }
10526 }
10527 }
10528
10529 if (isNowBgCross(BGC_ON_SINK_SAND)) {
10530 if (isStatus(STATUS_PENGUIN_SLIDE) && mSpeed.y < 0.0f) {
10531 mPos.y = mSinkSandHeight;
10532 onNowBgCross(BGC_FOOT);
10533 offNowBgCross(BGC_ON_SINK_SAND);
10534 offNowBgCross(BGC_IN_SINK_SAND);
10535 offNowBgCross(BGC_INSIDE_SINK_SAND);
10536 }
10537 }
10538
10539 daPlBase_c::postBgCross();
10540
10541 if (!isNowBgCross(BGC_61)) {
10543 if (
10544 isNowBgCross(BGC_WALL_TOUCH_L_2) && mSpeedF < 0.0f ||
10545 isNowBgCross(BGC_WALL_TOUCH_R_2) && mSpeedF > 0.0f
10546 ) {
10547 mSpeedF = 0.0f;
10548 mMaxSpeedF = 0.0f;
10549 mFinalAirPushForceX = 0;
10550 m_1138 = 0;
10551 }
10552 if (
10553 isNowBgCross(BGC_FOOT) &&
10554 isNowBgCross(BGC_ON_ICE) &&
10555 (isNowBgCross(BGC_OBJBG_TOUCH_L) || isNowBgCross(BGC_OBJBG_TOUCH_R)) &&
10556 mBc.mpCtrWall != nullptr
10557 ) {
10558 float f = mBc.mpCtrWall->mpActor->mPos.x - mBc.mpCtrWall->mpActor->mLastPos.x;
10559 if (f > 1.0f) {
10560 f = 1.0f;
10561 }
10562 if (f < -1.0f) {
10563 f = -1.0f;
10564 }
10565 if (isNowBgCross(BGC_OBJBG_TOUCH_L)) {
10566 if (mSpeedF < f) {
10567 mSpeedF = f;
10568 }
10569 } else {
10570 if (mSpeedF > f) {
10571 mSpeedF = f;
10572 }
10573 }
10574 }
10575 }
10576 }
10577
10578 if (isNowBgCross(BGC_FOOT)) {
10579 if (isNowBgCross(BGC_ON_WATER_MOVE)) {
10581 } else {
10583 }
10584 }
10585
10586 if (
10587 isNowBgCross(BGC_FOOT) ||
10588 isNowBgCross(BGC_WATER_SHALLOW) ||
10589 (isStatus(STATUS_VINE) && mBc.mFenceType == 1) ||
10590 isStatus(STATUS_53) ||
10594 ) {
10595 if (!isNowBgCross(BGC_62)) {
10596 clearTreadCount();
10597 }
10598 }
10599
10600 if (
10601 isNowBgCross(BGC_FOOT) ||
10602 isNowBgCross(BGC_WATER_SHALLOW) ||
10608 isStatus(STATUS_TARZAN_ROPE)
10609 ) {
10610 setEnemyStageClearDemo();
10611 clearJumpActionInfo(1);
10612 resetPropelFlyTime();
10613 mKey.offStatus(dAcPyKey_c::STATUS_FORCE_JUMP);
10614 mKey.offStatus(dAcPyKey_c::STATUS_FORCE_NO_JUMP);
10615 }
10616}
10617
10618void dAcPy_c::clearJumpActionInfo(int) {
10619 offStatus(STATUS_A7);
10622
10623 bool checkRes = false;
10624 if (mBc.mpCtrHead != nullptr && mBc.mpCtrHead->mpActor != nullptr) {
10625 if (mBc.mpCtrHead->mpActor->mProfName == fProfile::EN_GOALPOLE) {
10626 checkRes = true;
10627 }
10628 if (mBc.mpCtrHead->mpActor->mActorProperties & 0x10 || mBc.mpCtrHead->mpActor->mActorProperties & 0x20) {
10629 checkRes = true;
10630 }
10631 }
10632 if (!checkRes) {
10633 onStatus(STATUS_B7);
10634 }
10635 if (mScrollMode == 4 || mScrollMode == 2) {
10636 setScrollMode(0);
10637 }
10638 resetMissSpin();
10639}
10640
10641float dAcPy_c::getSandSinkRate() {
10642 return sGlobalData_c<dAcPy_c>::mData.mSandSinkRate;
10643}
10644
10645bool dAcPy_c::setPressBgDamage(int a, int b) {
10646 dAcPy_c *carryPlayer = getCarryPlayer();
10647 if (carryPlayer != nullptr) {
10648 if (b == 0) {
10649 cancelCarry(getCarryPlayer());
10650 return false;
10651 }
10652 if (mPowerup == POWERUP_MINI_MUSHROOM || carryPlayer->mPowerup == POWERUP_MINI_MUSHROOM) {
10653 carryPlayer->setPressBgDamage(a, b);
10654 } else {
10655 mVec3_c pos = carryPlayer->mPos;
10656 float height;
10657 if (dBc_c::checkTenjou(&pos, &height, mLayer, mAmiLayer)) {
10658 const sBcPlayerPointData *data = getBgPointData_Powerup(mPowerup, 0);
10659 pos.y = height - data->mHead.mOffset / 4096.0f - 2.0f;
10660 carryPlayer->mPos = pos;
10661 }
10662 cancelCarry(carryPlayer);
10663 return false;
10664 }
10665 }
10666 return daPlBase_c::setPressBgDamage(a, b);
10667}
10668
10669const sPowerChangeData daPlayerData_c::smc_POWER_CHANGE_DATA = {
10670 {
10671 // no star
10672 0.0f, 0.08f,
10673 0.03f, 0.06f,
10674 0.029f, 0.021f,
10675 0.09f,
10676 // star
10677 0.0f, 0.11f,
10678 0.04f, 0.078f,
10679 0.039f, 0.027f,
10680 0.12f
10681 },
10682 {
10683 // no star
10684 0.12f, 0.12f, 0.094f, 0.25f,
10685 // star
10686 0.12f, 0.12f, 0.094f, 0.25f
10687 },
10688 {
10689 // no star
10690 0.028f, 0.028f, 0.032f, 0.25f,
10691 // star
10692 0.038f, 0.038f, 0.042f, 0.25f
10693 },
10694 {
10695 // no star
10696 0.07f, 0.07f, 0.07f, 0.25f,
10697 // star
10698 0.07f, 0.07f, 0.07f, 0.25f
10699 },
10700 // gravity normal
10701 -0.34f,
10702 2.5f,
10703 1.5f,
10704 0.3f,
10705 -0.12f,
10706 -3.0f,
10707 -0.34f,
10708 -0.34f,
10709 -0.34f,
10710 -0.25f,
10711 -0.34f,
10712 -0.34f,
10713 -0.06f,
10714 -0.25f,
10715 -0.34f,
10716 -0.08f,
10717 -0.31f,
10718 -0.34f,
10719 // gravity mini
10720 -0.09f,
10721 2.5f,
10722 1.5f,
10723 0.0f,
10724 -2.0f,
10725 -2.0f,
10726 -0.09f,
10727 -0.09f,
10728 -0.09f,
10729 -0.06f,
10730 -0.09f,
10731 -0.09f,
10732 -0.04f,
10733 -0.06f,
10734 -0.09f,
10735 -0.06f,
10736 -0.09f,
10737 -0.09f,
10738 -0.34f,
10739 2.5f,
10740 1.5f,
10741 0.3f,
10742 -0.12f,
10743 -3.0f,
10744 -0.34f,
10745 -0.34f,
10746 -0.34f,
10747 -0.25f,
10748 -0.34f,
10749 -0.34f,
10750 -0.06f,
10751 -0.25f,
10752 -0.34f,
10753 -0.1f,
10754 -0.1f,
10755 -0.1f,
10756 { 0.7f, 1.5f, 2.8f },
10757 { 0.0f, 0.18f, 0.24f, 0.3f }
10758};
10759
10760const float dAcPy_c::data_802f5a0c[] = {
10761 0.0f, 0.08f, 0.07f, 0.11f, -1.5f, -1.25f,
10762 -1.0f, -0.1f, 1.5f, 1.5f, 2.5f, 2.5f,
10763 1.0f, -6.0f, 3.214242E-39 // [-> not just floats?]
10764};
10765
10766const float dAcPy_c::data_802f5a48[] = {
10767 25.0f, 3.627f, 3.0f, 0.6f, 2.3509887E-38, // [-> not just floats?]
10768 1.2f, 2.0f, 1.5f, 2.4f, 0.02f, 0.01f,
10769 0.05f, 0.2f, 0.03f, 0.03f, 0.8f, 0.7f,
10770 0.8f, 0.14f, 4.0f, 0.07f, 40.0f
10771};
10772
10781STATE_VIRTUAL_DEFINE(dAcPy_c, HipAttack);
10785
10786STATE_DEFINE(dAcPy_c, RideOffJump);
10787STATE_DEFINE(dAcPy_c, SpinHipAttack);
10788STATE_DEFINE(dAcPy_c, RollSlip);
10789STATE_DEFINE(dAcPy_c, Vine);
10790STATE_DEFINE(dAcPy_c, Hang);
10791STATE_DEFINE(dAcPy_c, Pole);
10792STATE_DEFINE(dAcPy_c, Fire);
10793STATE_DEFINE(dAcPy_c, LiftUp);
10794STATE_DEFINE(dAcPy_c, Throw);
10795STATE_DEFINE(dAcPy_c, PropelThrow);
10796STATE_DEFINE(dAcPy_c, WallJump);
10797STATE_DEFINE(dAcPy_c, WallSlide);
10798STATE_DEFINE(dAcPy_c, Propel);
10799STATE_DEFINE(dAcPy_c, CarryPlayer);
10800STATE_DEFINE(dAcPy_c, RideYoshi);
10801STATE_DEFINE(dAcPy_c, SpinJump);
10802STATE_DEFINE(dAcPy_c, PenguinSlide);
10803STATE_DEFINE(dAcPy_c, KaniJump);
10804STATE_DEFINE(dAcPy_c, Quake);
10805STATE_DEFINE(dAcPy_c, ElecShock);
10806STATE_DEFINE(dAcPy_c, FlyDamage);
10807STATE_DEFINE(dAcPy_c, IceDamage);
10808STATE_DEFINE(dAcPy_c, CannonJump);
10809STATE_DEFINE(dAcPy_c, TarzanRope);
10810STATE_DEFINE(dAcPy_c, PlayerEat);
10811STATE_DEFINE(dAcPy_c, Balloon);
10812STATE_DEFINE(dAcPy_c, BlockJump);
10813STATE_DEFINE(dAcPy_c, JrCrown);
10814
10815STATE_VIRTUAL_DEFINE(dAcPy_c, DemoDown);
10816STATE_DEFINE(dAcPy_c, DemoInDoor);
10817STATE_DEFINE(dAcPy_c, DemoInJump);
10818STATE_DEFINE(dAcPy_c, DemoInVine);
10819STATE_DEFINE(dAcPy_c, DemoOutDoor);
10820STATE_DEFINE(dAcPy_c, DemoFallDown);
10821STATE_DEFINE(dAcPy_c, DemoFireDown);
10822STATE_DEFINE(dAcPy_c, DemoEatDie);
10823STATE_DEFINE(dAcPy_c, DemoDokanCannon);
10824STATE_DEFINE(dAcPy_c, DemoCannonWarp);
10825// STATE_VIRTUAL_DEFINE(dAcPy_c, DemoStartWait); // [TODO: intentionally left out?]
10826
10827ACTOR_PROFILE(PLAYER, dAcPy_c, 0);
10828
10829template <>
10831 0.0f, 0.0f,
10832 1.5f, 4.5f, 0.5f, 4.0f, 1.4f, 1.0f,
10833 {
10834 mVec3_c(0.0f, 10.0f, 0.0f),
10835 mVec3_c(0.0f, 16.0f, 0.0f),
10836 mVec3_c(0.0f, 28.0f, 0.0f)
10837 },
10838 -3.0f, 3.0f, 3.2f,
10839 0.5f, 3.2f, 3.0f, 1.2f,
10840 0.5f, 0.625f, 0.5f, 0.625f,
10841 0.8f, 1.0f, 1.3f, 2.0f
10842};
10843
10844dAcPy_HIO_Speed_c dAcPy_c::m_speed_hio[2];
10845
10846dAcPy_c::dAcPy_c() : mPyMdlMng(daPyMng_c::getCourseInPlayerModelType(ACTOR_PARAM(PlayerNo))) {
10849 mpMdlMng = &mPyMdlMng;
10850 mPyMdlMng.mpMdl->mpOwner = this;
10851 mPlayerNo = ACTOR_PARAM(PlayerNo);
10852 mPlayerType = daPyMng_c::getPlayerType(mPlayerNo);
10853 mPowerup = daPyMng_c::mPlayerMode[daPyMng_c::getPlayerType(mPlayerNo)];
10854 mIsRescueKinopio = 0;
10855 if (daPyMng_c::mCreateItem[daPyMng_c::getPlayerType(mPlayerNo)] & 8) {
10856 mIsRescueKinopio = 1;
10857 dInfo_c::m_instance->m_6c = true;
10858 mPlayerType = PLAYER_BLUE_TOAD;
10859 mPowerup = daPyMng_c::mKinopioMode;
10860 daPyMng_c::mPlayerEntry[mPlayerNo] = 0;
10861 daPyMng_c::mCreateItem[daPyMng_c::getPlayerType(mPlayerNo)] &= ~CREATE_ITEM_RESCUE_TOAD;
10862 }
10863 daPyMng_c::setPlayer(mPlayerNo, this);
10864 mPlayerLayer = mPlayerNo;
10865}
10866
10867dAcPy_c::~dAcPy_c() {
10868 daPyMng_c::setPlayer(mPlayerNo, nullptr);
10869}
10870
10872 if (fn_801477c0() && !isItemKinopio()) {
10874 }
10875 setSceneChangeInfo();
10877 return SUCCEEDED;
10878}
10879
10880void dAcPy_c::setSceneChangeInfo() {
10881 if (isItemKinopio()) {
10882 if (dScStage_c::getExitMode() == dScStage_c::EXIT_3) {
10883 dAcPy_c *ctrlPlayer = daPyMng_c::getCtrlPlayer(mPlayerNo);
10884 if (
10885 ctrlPlayer != nullptr &&
10886 !ctrlPlayer->isStatus(STATUS_GOAL_POLE_TOUCHED) &&
10888 !isStatus(STATUS_ITEM_KINOPIO_DISPLAY_OUT)
10889 ) {
10891 }
10892 }
10893 return;
10894 }
10895
10896 PLAYER_POWERUP_e powerup = mPowerup;
10897 u32 createItem = CREATE_ITEM_NONE;
10898
10899 switch (dScStage_c::getExitMode()) {
10900 case dScStage_c::EXIT_3: {
10901 if (!isStatus(STATUS_55) || isNotBalloonCourse()) {
10902 if (isStatus(STATUS_53)) {
10903 createItem = CREATE_ITEM_BUBBLE;
10904 } else if (isStatus(STATUS_OUT_OF_PLAY)) {
10905 powerup = POWERUP_NONE;
10906 createItem = CREATE_ITEM_BUBBLE;
10907 }
10908 }
10909 daYoshi_c *yoshi = getRideYoshi();
10910 if (yoshi != nullptr) {
10911 createItem = CREATE_ITEM_YOSHI;
10912 int fruitCount = yoshi->getFruitCount();
10913 u8 yoshiColor = yoshi->getModel()->getColor();
10914 daPyMng_c::setCarryOverYoshiInfo(mPlayerNo, yoshiColor, fruitCount);
10915 onStatus(STATUS_C5);
10916 }
10917 break;
10918 }
10919 case dScStage_c::EXIT_2:
10920 powerup = daPyMng_c::mPlayerMode[daPyMng_c::getPlayerType(mPlayerNo)];
10921 createItem = daPyMng_c::mCreateItem[daPyMng_c::getPlayerType(mPlayerNo)];
10922 break;
10923 case dScStage_c::EXIT_1:
10924 powerup = POWERUP_NONE;
10925 break;
10926 default:
10927 break;
10928 }
10929
10930 daPyMng_c::mPlayerEntry[mPlayerNo] = 1;
10931 daPyMng_c::mPlayerMode[daPyMng_c::getPlayerType(mPlayerNo)] = powerup;
10932 daPyMng_c::mCreateItem[daPyMng_c::getPlayerType(mPlayerNo)] = createItem;
10933 daPyMng_c::m_star_time[mPlayerNo] = mStarTimer;
10934 daPyMng_c::m_star_count[mPlayerNo] = mStarCount;
10935}
10936
10938 mPyMdlMng.create(mPlayerNo, mPowerup, dPyMdlMng_c::SCENE_TYPE_0);
10939 mPowerupCopy2 = mPowerup;
10940 mPowerupCopy = mPowerup;
10941 setPowerup(mPowerup, 1);
10942 mDirection = ACTOR_PARAM(Direction);
10943 mAngle.y = getMukiAngle(mDirection);
10944 mSpeedMax.set(0.0f, 0.0f, 0.0f);
10945 mMaxFallSpeed = sc_MaxFallSpeed;
10946 mAccelY = getGravityData()[0];
10947 mScale.set(1.0f, 1.0f, 1.0f);
10948 mAmiRelated2 = 1.0f;
10950 mCarryActorID = BASE_ID_NULL;
10951 mRideActorID = BASE_ID_NULL;
10953 if (isItemKinopio()) {
10954 setScrollMode(1);
10955 } else {
10956 setScrollMode(0);
10957 }
10958 mPc.m_30 = mPos;
10959 mPropelParts.create(this);
10960 initCcData();
10961 initBcData();
10962 setCreateAction(ACTOR_PARAM(CreateAction));
10963 calcModel();
10964 mPc.set(this, 1);
10965 if (dScStage_c::m_miniGame == 0 && dScStage_c::m_instance->mCurrCourse != STAGE_PEACH_CASTLE) {
10966 if ((daPyMng_c::mCreateItem[daPyMng_c::mPlayerType[mPlayerNo]] & CREATE_ITEM_STAR_POWER)) {
10967 setStar(STAR_SET_2, 660);
10968 } else {
10969 if (daPyMng_c::m_star_time[mPlayerNo] != 0) {
10970 setStar(STAR_SET_2, daPyMng_c::m_star_time[mPlayerNo]);
10971 }
10972 mStarCount = daPyMng_c::m_star_count[mPlayerNo];
10973 }
10974 }
10975 if (!isItemKinopio() && dScStage_c::m_gameMode == dInfo_c::GAME_MODE_NORMAL) {
10976 mSndObj.m_58 = dAudio::getRemotePlayer(mPlayerNo);
10977 }
10978 int x = 0;
10979 switch (mPlayerType) {
10980 case PLAYER_MARIO: x = 0; break;
10981 case PLAYER_LUIGI: x = 1; break;
10982 case PLAYER_YELLOW_TOAD: x = 2; break;
10983 case PLAYER_BLUE_TOAD: x = 3; break;
10984 default: break;
10985 }
10986 mSndObj.m_00 = x;
10987 setSoundPlyMode();
10989 mKey.mRemoconID = mPlayerNo;
10990 return SUCCEEDED;
10991}
10992
10994 u32 oldExecStopMask = mExecStopMask;
10995 daYoshi_c *yoshi = getRideYoshi();
10996 if (yoshi != nullptr) {
10998 }
10999 int res = daPlBase_c::preExecute();
11000 mExecStopMask = oldExecStopMask;
11001 return res;
11002}
11003
11005 if (status == SUCCESS) {
11006 mVec3_c pos = mPos;
11007 dAcPy_c *ridePlayer = getRidePlayer();
11008 if (ridePlayer != nullptr) {
11009 pos.x = ridePlayer->mPos.x;
11010 }
11011 if (mScrollMode != 3) {
11012 if (m_60 != 0) {
11013 bool notDone = false;
11014 if (!sLib::chase(&mPc.m_30.x, pos.x, 3.0f)) {
11015 notDone = true;
11016 }
11017 if (!sLib::chase(&mPc.m_30.y, pos.y, 3.0f)) {
11018 notDone = true;
11019 }
11020 if (!notDone) {
11021 m_60 = 0;
11022 }
11023 } else {
11024 sLib::addCalc(&mPc.m_30.x, pos.x, 0.25f, 6.0f, 0.1f);
11025 sLib::addCalc(&mPc.m_30.y, pos.y, 0.25f, 6.0f, 0.1f);
11026 }
11027 if (isStatus(STATUS_5C)) {
11028 setScrollMode(5);
11029 } else {
11030 if (mScrollMode == 5) {
11031 setScrollMode(0);
11032 }
11033 }
11034 }
11035 }
11037}
11038
11039void dAcPy_c::selectAction() {
11041 if (std::fabs(mSpeedF) >= 1.0f) {
11043 if (mFastRunFrames >= 0) {
11045 }
11046 } else {
11047 mFastRunFrames = 0;
11048 }
11049
11050 if (isStatus(STATUS_07) && setSpinActionReq()) {
11051 return;
11052 }
11053 if (isDemo() || isStatus(STATUS_53)) {
11054 return;
11055 }
11056 if (setBalloonButtonA()) {
11057 return;
11058 }
11061 setQuakeAction(60, QUAKE_MODE_0);
11062 } else if (isStatus(STATUS_QUAKE_SMALL)) {
11064 if (isNowBgCross(BGC_FOOT)) {
11065 setWaitJump(4.0f);
11066 }
11067 } else if (isStatus(STATUS_RIDE_YOSHI) && !isState(StateID_RideYoshi)) {
11068 changeState(StateID_RideYoshi, 0);
11069 } else if (setVineAction()) {
11070 return;
11071 } else if (setHangAction()) {
11072 return;
11073 } else if (setPoleAction()) {
11074 return;
11075 } else if (setKaniHangAction()) {
11076 return;
11077 } else if (checkWallJump()) {
11078 return;
11079 } else if (setSpinActionReq()) {
11080 return;
11081 } else if (setSwimAction()) {
11082 return;
11083 } else if (setFireBallAction()) {
11084 return;
11085 } else if (setTarzanRopeAction()) {
11086 return;
11087 }
11088}
11089
11090void dAcPy_c::executeLastPlayer() {
11092 return;
11093 }
11094 clearHipAttackDamagePlayer();
11096 setYoshiBackPos();
11097 }
11099 setPlayerJumoDaiPos();
11100 }
11101 if (isStatus(STATUS_4F)) {
11102 setJrCrownPos();
11103 }
11104 calcModel();
11105 if (isStatus(STATUS_77)) {
11106 setPlayerEatReact();
11107 entryCollision();
11108 offStatus(STATUS_77);
11109 offStatus(STATUS_78);
11110 }
11111}
11112
11113void dAcPy_c::executeLastAll() {
11115 return;
11116 }
11117 setSpinLiftUpReserve();
11118 setSpinAction();
11119 offStatus(STATUS_8A);
11120 if (isStatus(STATUS_45)) {
11121 setPlayerHandPos();
11122 mAng3_c ang = mAngle;
11123 ang.y += getMissSpinAngle();
11124 mPyMdlMng.calc(
11125 mPos,
11126 ang,
11127 getModelScale()
11128 );
11129 }
11130 if (!isChange()) {
11131 calcHeadAttentionAngle();
11132 }
11133 setSpinJumpEffect(0);
11134 setMissSpinJumpEffect(0);
11135 mPyMdlMng.calc2();
11136}
11137
11138void dAcPy_c::calcModel() {
11139 mPyMdlMng.mpMdl->setDark(m_74);
11140
11141 if (isNowBgCross(BGC_36)) {
11142 mPyMdlMng.mpMdl->m_17c |= 0x400;
11143 } else {
11144 mPyMdlMng.mpMdl->m_17c &= ~0x400;
11145 }
11146
11147 daYoshi_c *yoshi = getRideYoshi();
11148
11149 if (yoshi != nullptr) {
11150 mMtx_c mtx;
11151 yoshi->getModel()->getJointMtx(&mtx, 1);
11152
11153 mtx.concat(mMtx_c::createTrans(
11154 dPyMdlMng_c::m_hio.getValue(mPlayerType, 0, mPowerup),
11155 dPyMdlMng_c::m_hio.getValue(mPlayerType, 1, mPowerup),
11156 0.0f
11157 ));
11158
11159 mtx.ZrotM(-0x58E3);
11160 mtx.YrotM(0xC000);
11161
11162 mtx.concat(mMtx_c::createTrans(0.0f, 0.0f, 15.0f));
11163 mtx.concat(mMtx_c::createScale(daPlBase_c::getReductionModelScale()));
11164 mtx.concat(mMtx_c::createTrans(0.0f, 0.0f, -15.0f));
11165 mtx.concat(mMtx_c::createScale(getModelScaleBase()));
11166
11167 mPyMdlMng.calc(mtx);
11168 return;
11169 }
11170
11171 if (daPlBase_c::isStatus(STATUS_4F)) {
11172 mPyMdlMng.calc(mRideJrClownMtx);
11173 return;
11174 }
11175
11176 mVec3_c pos(
11177 mPos.x + m_1594,
11178 mPos.y + m_1598 + m_159c,
11179 mPos.z
11180 );
11181
11182 mAng3_c rot(
11183 mAngle.x.mAngle,
11184 mAngle.y.mAngle + getMissSpinAngle(),
11185 mAngle.z.mAngle
11186 );
11187
11188 mPyMdlMng.calc(pos, rot, getModelScale());
11189}
11190
11191mVec3_c dAcPy_c::getModelScaleBase() {
11192 float scale = mAmiRelated2;
11193 mVec3_c res(
11194 mScale.x * scale,
11195 mScale.y * scale,
11196 mScale.z * scale
11197 );
11198 return res;
11199}
11200
11201mVec3_c dAcPy_c::getModelScale() {
11202 return mVec3_c(
11203 getModelScaleBase().x * getReductionModelScale().x,
11204 getModelScaleBase().y * getReductionModelScale().y,
11205 getModelScaleBase().z * getReductionModelScale().z
11206 );
11207}
11208
11212 return SUCCEEDED;
11213 }
11214
11215 mPyMdlMng.draw();
11216 return SUCCEEDED;
11217}
11218
11221 return false;
11222 }
11223
11224 if (mPowerupCopy2 == powerup) {
11225 return false;
11226 }
11227
11228 mPowerupCopy2 = powerup;
11229 return mPowerup != powerup;
11230}
11231
11232void dAcPy_c::setStar(StarSet_e starSet, int timer) {
11233 setStarBase(starSet, timer);
11234 if (starSet == STAR_SET_0) {
11235 setVirusStar(getRidePlayer());
11236 setVirusStar(getCarryPlayer());
11237 }
11238}
11239
11240void dAcPy_c::setStarBase(StarSet_e starSet, int timer) {
11241 if (starSet == STAR_SET_0) {
11242 startPlayerVoice(VOICE_GET_STAR, 0);
11243 }
11244 if (timer != 0) {
11245 mStarTimer = timer;
11246 if (timer >= 60) {
11247 daPyMng_c::startStarBGM();
11248 }
11249 mPyMdlMng.mpMdl->onStarAnm();
11250 }
11251}
11252
11253void dAcPy_c::endStar() {
11254 if (mStarTimer != 0) {
11255 mStarTimer = 0;
11256 mPyMdlMng.mpMdl->offStarAnm();
11257 mPyMdlMng.mpMdl->offStarEffect();
11258 daPyMng_c::stopStarBGM();
11259 }
11260}
11261
11262void dAcPy_c::calcStarTimer() {
11263 mPyMdlMng.mpMdl->offStarEffect();
11264 if (mStarTimer != 0) {
11265 mPyMdlMng.mpMdl->mScale = mVec3_c(mAmiRelated2, mAmiRelated2, mAmiRelated2);
11266 if (!isStatus(STATUS_INVISIBLE) && !isStatus(STATUS_5E) && mStarTimer > 25) {
11267 mPyMdlMng.mpMdl->onStarEffect();
11268 }
11269 if (mStarTimer < 10) {
11270 mPyMdlMng.mpMdl->offStarAnm();
11271 }
11272 if (mStarTimer == 120) {
11273 mStarTimer--;
11274 startSound(SE_SYS_STAR_FINISH, false);
11275 startSound(SE_SYS_STAR_FINISH_RC, false);
11276 }
11277 if (mStarTimer < 60) {
11278 daPyMng_c::stopStarBGM();
11279 }
11280 } else {
11281 clearStarCount();
11282 }
11283}
11284
11285void dAcPy_c::setVirusStar(daPlBase_c *otherPlayer) {
11286 if (otherPlayer == nullptr) {
11287 return;
11288 }
11289
11290 int selfTimer = mStarTimer;
11291 int otherTimer = otherPlayer->mStarTimer;
11292
11293 if (selfTimer == otherTimer) {
11294 return;
11295 }
11296
11297 if (selfTimer > otherTimer) {
11298 otherPlayer->setStar(STAR_SET_1, selfTimer);
11299 } else {
11300 setStar(STAR_SET_1, otherTimer);
11301 }
11302}
11303
11304void dAcPy_c::setWaterWalkFlag() {
11305 if (isMameAction() && !isNowBgCross(BGC_WATER_SHALLOW)) {
11307 }
11308}
11309
11310void dAcPy_c::fn_80145fd0(int jumpType) {
11311 static const dAudio::SoundEffectID_t sc_JumpSoundNormal[] = { SE_PLY_JUMP, SE_PLY_2NDJUMP, SE_PLY_3RDJUMP };
11312 static const dAudio::SoundEffectID_t sc_JumpSoundSuper[] = { SE_PLY_JUMP_S, SE_PLY_2NDJUMP_S, SE_PLY_3RDJUMP_S };
11313 static const dAudio::SoundEffectID_t sc_JumpSoundMame[] = { SE_PLY_JUMP_SS, SE_PLY_2NDJUMP_SS, SE_PLY_3RDJUMP_SS };
11314 if (jumpType == 2 && !mKey.buttonJump()) {
11315 jumpType = 0;
11316 }
11317 switch (jumpType) {
11318 case 1:
11319 switch (mPowerup) {
11320 case POWERUP_NONE:
11321 startSound(sc_JumpSoundSuper[mJumpCounter], true);
11322 break;
11323 case POWERUP_MINI_MUSHROOM:
11324 startSound(sc_JumpSoundMame[mJumpCounter], true);
11325 break;
11326 default:
11327 startSound(sc_JumpSoundNormal[mJumpCounter], true);
11328 break;
11329 }
11330 break;
11331 case 2:
11332 switch (mPowerup) {
11333 case POWERUP_NONE:
11334 startSound(SE_PLY_JUMP_SS_HIGH, false);
11335 break;
11336 case POWERUP_MINI_MUSHROOM:
11337 startSound(SE_PLY_JUMP_S_HIGH, false);
11338 break;
11339 default:
11340 startSound(SE_PLY_JUMP_HIGH, false);
11341 break;
11342 }
11343 }
11344}
11345
11346bool dAcPy_c::isNoDamage() {
11347 if (
11348 (mDamageInvulnTimer | mPowerupChangeInvulnTimer) != 0 ||
11349 isDemo() ||
11350 isDemoType(DEMO_PLAYER) ||
11352 isStatus(STATUS_84)
11353 ) {
11354 return true;
11355 }
11356 return false;
11357}
11358
11359bool dAcPy_c::setDamage(dActor_c *actor, daPlBase_c::DamageType_e damageType) {
11360 if (mPowerup != mPowerupCopy2 || isChange()) {
11361 return false;
11362 }
11363
11364 if (isNoDamage()) {
11365 return false;
11366 }
11367
11368 if (setDamage2(actor, damageType)) {
11369 dQuake_c::m_instance->shockMotor(mPlayerNo, dQuake_c::TYPE_4, 0, false);
11370 return true;
11371 }
11372
11373 return false;
11374}
11375
11376bool dAcPy_c::setForcedDamage(dActor_c *actor, daPlBase_c::DamageType_e damageType) {
11377 if (isDemo() || mPowerup != mPowerupCopy2 || isChange()) {
11378 return false;
11379 }
11380
11381 if (setDamage2(actor, damageType)) {
11382 dQuake_c::m_instance->shockMotor(mPlayerNo, dQuake_c::TYPE_4, 0, false);
11383 return true;
11384 }
11385
11386 return false;
11387}
11388
11389bool dAcPy_c::setDamage2(dActor_c *actor, daPlBase_c::DamageType_e damageType) {
11391 return false;
11392 }
11393 releaseCarryActor();
11394 if (damageType == DAMAGE_DEFAULT && isStatus(STATUS_PENGUIN_SLIDE) && actor != nullptr && actor->mActorProperties & 0x200) {
11395 if (setFlyDamageAction(3, actor)) {
11397 return true;
11398 }
11399 return false;
11400 }
11401 switch (damageType) {
11402 case DAMAGE_YOGAN:
11403 changeDemoState(StateID_DemoFireDown, 0);
11404 break;
11405 case DAMAGE_ELEC_SHOCK:
11406 if (isStatus(STATUS_4F)) {
11407 setJrCrownElecDamage();
11408 } else {
11409 changeState(StateID_ElecShock, 0);
11410 }
11411 break;
11412 case DAMAGE_POISON:
11413 changeDemoState(StateID_DemoDown, DEMO_DOWN_ARG_POISON);
11414 break;
11415 case DAMAGE_SQUISH:
11416 changeDemoState(StateID_DemoDown, DEMO_DOWN_ARG_HIT);
11417 break;
11418 case DAMAGE_POISON_FOG:
11419 changeDemoState(StateID_DemoDown, DEMO_DOWN_ARG_POISON_FOG);
11420 break;
11421 case DAMAGE_EAT_DIE:
11422 case DAMAGE_D:
11423 changeDemoState(StateID_DemoEatDie, damageType);
11424 mRelatedActorID = actor->mUniqueID;
11425 break;
11426 case DAMAGE_HIP_ATTACK:
11427 case DAMAGE_4:
11428 case DAMAGE_CLIMB:
11429 case DAMAGE_6:
11430 return setFlyDamageAction(damageType, actor);
11431 case DAMAGE_11:
11432 setReductionScale();
11433 break;
11434 case DAMAGE_10:
11435 changeState(StateID_IceDamage, 0);
11436 break;
11437 default:
11438 if (mPowerup == POWERUP_NONE || mPowerup == POWERUP_MINI_MUSHROOM) {
11439 if (damageType == DAMAGE_8) {
11440 changeDemoState(StateID_DemoFireDown, 0);
11441 } else {
11442 changeDemoState(StateID_DemoDown, DEMO_DOWN_ARG_HIT);
11443 }
11444 } else {
11445 if (mPowerup == POWERUP_MUSHROOM) {
11446 fn_80145c00(POWERUP_NONE);
11447 } else {
11448 fn_80145c00(POWERUP_MUSHROOM);
11449 }
11450 if (damageType == DAMAGE_2) {
11451 mDamageInvulnTimer = 127;
11452 return setFlyDamageAction(damageType, actor);
11453 }
11454 if (damageType == DAMAGE_FREEZE) {
11455 changeState(StateID_IceDamage, 0);
11456 } else {
11457 mDamageInvulnTimer = 127;
11458 }
11459 }
11460 break;
11461 }
11462 return true;
11463}
11464
11465u8 dAcPy_c::getTallType(s8 powerup) {
11466 const u8 l_tall_type[] = {
11467 1, 2, 2, 0, 2, 2, 2
11468 };
11469
11470 if (powerup == -1) {
11471 powerup = mPowerup;
11472 }
11473 return l_tall_type[powerup];
11474}
11475
11476void dAcPy_c::setCenterOffset() {
11477 float l_powerup_offsets[] = {
11478 16.0f, 31.0f, 31.0f, 6.0f, 34.0f, 31.0f, 31.0f
11479 };
11480
11481 mModelHeight = l_powerup_offsets[mPowerup];
11482
11483 mVec3_c offset(0.0f, 0.0f, 0.0f);
11484 if (mPyMdlMng.mpMdl->mFlags & 1) {
11485 offset.y = mModelHeight / 4.0f;
11486 } else if (mPyMdlMng.mpMdl->mFlags & 4) {
11487 offset.y = -(mModelHeight / 2.0f);
11488 } else {
11489 offset.y = mModelHeight / 2.0f;
11490 }
11491 mCenterOffs = offset;
11492
11493 float target = 16.0f;
11494 if (mPowerup == POWERUP_MINI_MUSHROOM) {
11495 target = 8.0f;
11496 }
11497 sLib::chase(&mViewLimitPadding, target, 0.1f);
11498}
11499
11500void dAcPy_c::setPlayerData() {
11501 static const mVec2_POD_c l_player_cull_data[] = {
11502 {0.0f, 20.0f},
11503 {15.0f, 22.0f}
11504 };
11505 setVisibleArea(l_player_cull_data[0], l_player_cull_data[1]);
11506}
11507
11508void dAcPy_c::setSpeedData() {
11509 static const int scSpeedHioData[] = { 1, 1, 1, 0, 1, 1, 1 };
11510 u8 index = scSpeedHioData[mPowerup];
11511 mSpeedDataNormal = &m_speed_hio[index].mDataNormal;
11512 mSpeedDataStar = &m_speed_hio[index].mDataStar;
11513}
11514
11515void dAcPy_c::setModeGravity() {
11516 int index = 0;
11517 if (mPowerup == POWERUP_MINI_MUSHROOM) {
11518 index = 1;
11519 }
11520 mGravityData = daPlayerData_c::smc_POWER_CHANGE_DATA.mGravityData[index];
11521}
11522
11523const float *dAcPy_c::getGravityData() {
11524 if (isMameAction()) {
11525 return daPlayerData_c::smc_POWER_CHANGE_DATA.mGravityData[1];
11526 } else {
11527 return daPlayerData_c::smc_POWER_CHANGE_DATA.mGravityData[0];
11528 }
11529}
11530
11532 mPowerupCopy = mPowerup;
11533 mPowerup = powerup;
11534 mPyMdlMng.mpMdl->setPlayerMode(mPowerup);
11535 setPlayerData();
11536 setCenterOffset();
11537 setSpeedData();
11538 mAccelF = getSpeedData()->mPowerChangeNormal.mSlowAccel;
11539 setModeGravity();
11541 switch (mPowerup) {
11542 case POWERUP_PROPELLER_SHROOM:
11543 if (!isItemKinopio()) {
11544 if (fn_801477c0()) {
11546 }
11547 m_1580 = 0;
11548 }
11549 resetPropelFlyTime();
11550 break;
11551 case POWERUP_PENGUIN_SUIT:
11553 break;
11554 default:
11555 break;
11556 }
11557 mBc.mPlayerFlags &= ~BIT_FLAG(3);
11558 if (mPowerup == POWERUP_MINI_MUSHROOM) {
11559 mBc.mPlayerFlags |= BIT_FLAG(3);
11560 }
11561 setSoundPlyMode();
11562}
11563
11564bool dAcPy_c::setJump(float jumpSpeed, float speedF, bool allowSteer, int keyMode, int jumpMode) {
11565 if (mPowerup != POWERUP_MINI_MUSHROOM && isClimbing()) {
11566 return false;
11567 }
11568 return _setJump(jumpSpeed, speedF, allowSteer, keyMode, jumpMode);
11569}
11570
11571bool dAcPy_c::_setJump(float jumpSpeed, float speedF, bool allowSteer, int keyMode, int jumpMode) {
11572 if (isDemo() || isStatus(STATUS_OUT_OF_PLAY)) {
11573 return false;
11574 }
11575 if (isStatus(STATUS_DISABLE_STATE_CHANGE) && isStatus(STATUS_53)) {
11576 return false;
11577 }
11578 if (setSwimSpeed(jumpSpeed * 0.5f, speedF * 0.5f)) {
11579 return true;
11580 }
11581 clearJumpActionInfo(0);
11583 changeState(StateID_KaniJump);
11584 } else {
11585 bool res = false;
11586 mSpeedF = speedF;
11587 if (jumpSpeed <= 0.0f) {
11588 if (isStatus(STATUS_80)) {
11589 if (isOldBgCross(BGC_FOOT)) {
11590 res = true;
11591 }
11592 } else {
11593 if (isNowBgCross(BGC_FOOT)) {
11594 res = false;
11595 }
11596 }
11597 }
11598 if (!res) {
11599 bool isSpinJump = false;
11600 bool isSitJump = false;
11602 isSpinJump = true;
11603 } else if (isStatus(STATUS_SIT_JUMP)) {
11604 isSitJump = true;
11605 }
11606 if (jumpSpeed == 0.0f) {
11607 changeState(StateID_Fall, false);
11608 } else {
11609 jmpInf_c jump(jumpSpeed, jumpMode, BLEND_DEFAULT);
11610 changeState(StateID_Jump, &jump);
11611 }
11612 onStatus(STATUS_AB);
11613 onStatus(STATUS_88);
11614 if (isSpinJump) {
11615 int param = 2;
11616 if (jumpMode == 1) {
11617 param = 1;
11618 }
11619 changeState(StateID_SpinJump, (void *) param);
11620 } else if (isSitJump) {
11621 changeState(StateID_SitJump, true);
11622 }
11623 }
11624 }
11625 offStatus(STATUS_A7);
11626 offNowBgCross(BGC_FOOT);
11628 if (!allowSteer) {
11629 mKey.onStatus(dAcPyKey_c::STATUS_DISABLE_LR);
11630 onStatus(STATUS_A7);
11631 }
11632 if (keyMode == 1) {
11633 mKey.onStatus(dAcPyKey_c::STATUS_FORCE_JUMP);
11634 } else if (keyMode == 2) {
11635 mKey.onStatus(dAcPyKey_c::STATUS_FORCE_NO_JUMP);
11636 }
11637
11638 return true;
11639}
11640
11641bool dAcPy_c::fn_80146e40(float a, float b, bool c) {
11642 if (isDemo() || isStatus(STATUS_OUT_OF_PLAY) || isNowBgCross(BGC_WATER_SHALLOW)) {
11643 return false;
11644 }
11645 checkSinkSand();
11646 if (getSpinActionMode() == 0 || isOnSinkSand()) {
11647 mSpeed.y = a;
11648 mSpeedF = b;
11649 changeState(StateID_SpinJump, (void *) 1);
11651 mKey.onStatus(dAcPyKey_c::STATUS_FORCE_JUMP);
11652 offNowBgCross(BGC_FOOT);
11654 offStatus(STATUS_A7);
11655 } else {
11656 mSpeedF = b;
11657 changeState(StateID_Propel, (void *) 2);
11658 }
11659 return true;
11660}
11661
11662bool dAcPy_c::setCannonJump(float speedY, float speedF, int jumpType) {
11663 mSpeedF = speedF;
11664 mMaxSpeedF = speedF;
11665 mSpeed.y = speedY;
11666 if (mSpeedF > 0.0f) {
11667 mDirection = DIR_LR_R;
11668 } else {
11669 mDirection = DIR_LR_L;
11670 }
11671 changeState(StateID_CannonJump, (void *) jumpType);
11672 return true;
11673}
11674
11675bool dAcPy_c::setSwimSpeed(float speedY, float speedF) {
11676 if (isNowBgCross(BGC_WATER_SHALLOW)) {
11677 setUzuSwimAction();
11678 mSpeed.y = speedY;
11679 mSpeedF = speedF;
11680 m_b88 = 20;
11681 return true;
11682 }
11683 return false;
11684}
11685
11686bool dAcPy_c::isEnablePropelJump() {
11687 if (mSpinCooldown != 0 || isNowBgCross(BGC_WATER_SHALLOW) || !isStatus(STATUS_CAN_SPIN)) {
11688 return false;
11689 }
11690
11691 if (isDemo() || isStatus(STATUS_AUTO_BOUNCE)) {
11692 return false;
11693 }
11694
11695 return getSpinActionMode() == 1;
11696}
11697
11698int dAcPy_c::getSpinActionMode() {
11699 s8 tmp = getPowerup();
11700 if (getCarryPropelActor() != nullptr) {
11701 tmp = POWERUP_PROPELLER_SHROOM;
11702 } else {
11703 dAcPy_c *carryPlayer = getCarryPlayer();
11704 if (carryPlayer != nullptr) {
11705 tmp = carryPlayer->getPowerup();
11706 } else {
11707 if (tmp == POWERUP_PROPELLER_SHROOM && isLiftUp()) {
11708 tmp = POWERUP_MUSHROOM;
11709 }
11710 }
11711 }
11712 return tmp == POWERUP_PROPELLER_SHROOM ? 1 : 0;
11713}
11714
11715bool dAcPy_c::setSpinActionReq() {
11716 mKey.offStatus(dAcPyKey_c::STATUS_2);
11717 if (mPowerup == POWERUP_PROPELLER_SHROOM) {
11718 mKey.onStatus(dAcPyKey_c::STATUS_2);
11719 }
11720
11721 if (
11722 mSpinCooldown != 0 ||
11723 !mKey.triggerShakeJump() ||
11724 isNowBgCross(BGC_WATER_SHALLOW) ||
11726 ) {
11727 return false;
11728 }
11729
11730 if (isNowBgCross(BGC_FOOT)) {
11731 setCcAtSpinLiftUp();
11732 clearSpinLiftUpReserve();
11733 }
11734 onStatus(STATUS_8A);
11735 return true;
11736}
11737
11738bool dAcPy_c::setSpinAction() {
11739 if (
11740 isDemo() ||
11744 isStatus(STATUS_AUTO_BOUNCE) ||
11745 !isStatus(STATUS_8A)
11746 ) {
11747 return false;
11748 }
11749
11750 if (checkStandUpRoof()) {
11751 return false;
11752 }
11753
11754 if (isNowBgCross(BGC_HEAD)) {
11755 return false;
11756 }
11757
11758 mSpinCooldown = 30;
11759 resetMissSpin();
11760 if (getSpinActionMode() == 0) {
11761 if (isNowBgCross(BGC_FOOT)) {
11762 changeState(StateID_SpinJump, 0);
11763 return true;
11764 }
11765 } else {
11766 if (setPropelAction()) {
11767 return true;
11768 }
11769 }
11770
11771 setMissSpin();
11772 return true;
11773}
11774
11775void dAcPy_c::setScrollMode(s8 mode) {
11776 if (!isItemKinopio()) {
11777 mScrollMode = mode;
11778 } else {
11779 mScrollMode = 1;
11780 }
11781}
11782
11783void dAcPy_c::setInvalidKeyTimer(int p1, int p2) {
11784 m_1318[0] = p1;
11785 m_1310[0] = p2;
11786 mKey.onStatus(dAcPyKey_c::STATUS_NO_INPUT);
11787}
11788
11789void dAcPy_c::setInvalidKeyTimer_LR(int p1, int p2) {
11790 m_1318[1] = p1;
11791 m_1310[1] = p2;
11792 mKey.onStatus(dAcPyKey_c::STATUS_DISABLE_LR);
11793}
11794
11795void dAcPy_c::calcInvalidKeyTimer() {
11796 for (int i = 0; i < 2; i++) {
11797 if (m_1318[i] != 0) {
11798 if (m_1310[i] == 2) {
11799 if (mSpeed.y <= 0.0f || isNowBgCross(BGC_FOOT)) {
11800 m_1318[i] = 0;
11801 }
11802 } else if (m_1310[i] == 1) {
11803 if (isNowBgCross(BGC_FOOT)) {
11804 m_1318[i] = 0;
11805 }
11806 }
11807 sLib::calcTimer(&m_1318[i]);
11808 if (m_1318[i] == 0) {
11809 if (i == 0) {
11810 mKey.offStatus(dAcPyKey_c::STATUS_NO_INPUT);
11811 } else {
11812 mKey.offStatus(dAcPyKey_c::STATUS_DISABLE_LR);
11813 }
11814 }
11815 }
11816 }
11817}
11818
11819void dAcPy_c::startQuakeShock(dQuake_c::TYPE_SHOCK_e type) {
11820 daPlBase_c::startQuakeShock(type);
11821 dAcPy_c *carryPlayer = getCarryPlayer();
11822 if (carryPlayer != nullptr) {
11823 carryPlayer->startQuakeShock(type);
11824 }
11825}
11826
11827void dAcPy_c::startPatternRumble(const char *pattern) {
11828 daPlBase_c::startPatternRumble(pattern);
11829 dAcPy_c *carryPlayer = getCarryPlayer();
11830 if (carryPlayer != nullptr) {
11831 carryPlayer->startPatternRumble(pattern);
11832 }
11833}
11834
11835void dAcPy_c::setItemGetEffect() {
11837 mPowerUpType = 0;
11838}
11839
11840void dAcPy_c::setChukanPowerUpEffect() {
11842 mPowerUpType = 1;
11843}
11844
11845void dAcPy_c::endPowerUpEffect() {
11846 if (mPowerUpEffectTimer != 0) {
11847 mItemGetEffect1.fade();
11848 if (mPowerUpType == 0) {
11849 mItemGetEffect2.fade();
11850 }
11851 }
11853}
11854
11855void dAcPy_c::updateItemGetEffect() {
11856 if (mPowerUpEffectTimer == 0) {
11857 return;
11858 }
11859 mVec3_c efPos = getCenterPos();
11860 mVec3_c efScale(1.0f, 1.0f, 1.0f);
11861 if (mPowerup == POWERUP_MINI_MUSHROOM) {
11862 efScale.set(0.7f, 0.7f, 0.7f);
11863 }
11864 mItemGetEffect1.createEffect("Wm_mr_itemget01", 0, &efPos, nullptr, &efScale);
11865 if (mPowerUpType == 0) {
11866 int alpha = mPowerUpEffectTimer * 8;
11867 if (alpha > 255) {
11868 alpha = 255;
11869 }
11870 mItemGetEffect1.setColor(255, 255, 255, alpha, EGG::Effect::RECURSIVE_3);
11871 mItemGetEffect1.copyExEffectParam();
11872 mItemGetEffect2.createEffect("Wm_mr_itemget02", 0, &efPos, nullptr, &efScale);
11873 }
11874}
11875
11878 return false;
11879 }
11880 if (
11881 dScStage_c::m_instance->mCurrWorld == WORLD_1 &
11882 dScStage_c::m_instance->mCurrCourse == STAGE_1 &&
11883 !dSaveMng_c::m_instance->getSaveGame(-1)->isCourseDataFlag(0, 0, 0x10)
11884 ) {
11885 return true;
11886 }
11887 return false;
11888}
11889
11890bool dAcPy_c::searchKinopioNearPlayer(float *dist) {
11891 dAcPy_c *player;
11892 float closest = 1600.0f;
11893 for (int i = 0; i < PLAYER_COUNT; i++) {
11894 if (!(daPyMng_c::mActPlayerInfo & (1 << (u8) i))) {
11895 continue;
11896 }
11897 player = daPyMng_c::getPlayer(i);
11898 if (player == nullptr) {
11899 continue;
11900 }
11901 if (player == this || !player->isDrawingCarryFukidashi()) {
11902 continue;
11903 }
11904 mVec2_c diff(
11905 player->mPos.x - mPos.x,
11906 player->mPos.y - mPos.y
11907 );
11908 if (closest > diff.length()) {
11909 closest = diff.length();
11910 }
11911 }
11912 if (closest >= 1600.0f) {
11913 return false;
11914 }
11915 if (dist != nullptr) {
11916 *dist = closest;
11917 }
11918 return true;
11919}
11920
11921void dAcPy_c::managePropelFukidashi() {
11922 if (m_157c != 0) {
11923 m_157c--;
11924 }
11925 if (m_1584 != 0) {
11926 m_1584--;
11927 }
11928 if (isItemKinopio()) {
11929 int check = false;
11930 float dist;
11931 if (isSpinLiftUpEnable() && searchKinopioNearPlayer(&dist)) {
11932 if (m_1580 == 0) {
11933 if (dist < 48.0f) {
11934 check = true;
11935 }
11936 } else if (dist < 80.0f) {
11937 check = true;
11938 }
11939 }
11940 if (check == true) {
11941 if (m_157c != 0) {
11942 check = false;
11943 }
11944 } else {
11945 m_157c = 3;
11946 }
11947 if (m_1580 == 0) {
11948 if (check == true) {
11949 m_1580 = 1;
11951 m_1584 = 240;
11952 }
11953 } else {
11954 if (m_1584 == 0) {
11956 }
11957 if (!check) {
11958 m_1580 = 0;
11960 }
11961 }
11962 } else {
11963 int check = false;
11964 if (isDrawingFukidashi() && isEnablePropelJump() && getCarryPropelBlock() == nullptr) {
11965 if (m_157c == 0) {
11966 check = true;
11967 }
11968 } else {
11969 m_157c = 3;
11970 }
11971 if (m_1580 == 0) {
11972 if (check == true) {
11973 m_1580 = 1;
11974 m_1584 = 480;
11975 }
11976 } else if (m_1584 == 0 && !fn_801477c0()) {
11978 } else if (!check) {
11980 } else {
11982 }
11983 }
11984}
11985
11986bool dAcPy_c::isDrawingFukidashi() {
11987 if (
11988 isItemKinopio() ||
11990 isDemoAll() ||
11991 mSpinCooldown != 0 ||
11992 isNowBgCross(BGC_WATER_SHALLOW) ||
11995 dScStage_c::m_miniGame != 0
11996 ) {
11997 return false;
11998 }
11999 int level = dScStage_c::m_instance->mCurrCourse;
12000 return level != STAGE_TITLE &&
12001 level != STAGE_PEACH_CASTLE &&
12002 level != STAGE_STAFFROLL;
12003}
12004
12005bool dAcPy_c::isDrawingCarryFukidashi() {
12006 if (
12007 !isDrawingFukidashi() ||
12008 !mBc.isFoot() ||
12009 fManager_c::searchBaseByID(mCarryActorID) != nullptr
12010 ) {
12011 return false;
12012 }
12013 return true;
12014}
void fn_8019be60(int)
void fn_8019bd90(int)
int buttonUp() const
Returns whether the up button is pressed down.
bool buttonWalk(int *direction) const
Returns whether left / right is pressed down. Sets the direction to 0 for right and 1 for left.
@ STATUS_SHAKE_COOLDOWN
Is in cooldown for shake events.
@ STATUS_FORCE_NO_JUMP
Force a jump input to be ignored.
@ STATUS_DISABLE_LR
Disable left and right directional buttons.
@ STATUS_FORCE_JUMP
Force the jump button to be pressed down.
@ STATUS_NO_INPUT
Disable all inputs.
The player class for Mario, Luigi and the Toads.
bool initDemoDokanCannon(mVec3_c &pos, int cannonMode)
static sFStateID_c< dAcPy_c > StateID_CarryPlayer
Being carried by another player.
static sFStateID_c< dAcPy_c > StateID_RollSlip
Flying through the air after being thrown by another player.
virtual bool setJump(float jumpSpeed, float speedF, bool allowSteer, int keyMode, int jumpMode)
Starts a jump action with the given parameters.
short mNoInteractTimer
Disables interaction with other players and enemies while the timer is non-zero.
virtual bool setEatSpitOut(dActor_c *eatingActor)
Callback for when the actor is about to be spat out.
void jumpExeTakeOff()
virtual void setEatTongue(dActor_c *eatingActor)
Callback for when the actor is targeted by Yoshi's tongue.
void reviseBcDataCarryPlayer(sBcPointData &data1, sBcPointData &data2)
PenguinSlideSubstate_e
int mTarzanRopeCooldown
Timer to disable swinging on a vine while active.
int checkWallSlideEnable(int)
int mPowerUpType
0: Touching an item, 1: Touching the midway point.
void fn_80145fd0(int jumpType)
Jump voice, some enum as param.
SpinHipAttackSubstate_e
const sBcPlayerPointData * getBgPointData_Powerup(PLAYER_POWERUP_e, int)
virtual void setWaitActionAnm(AnmBlend_e)
static sFStateID_c< dAcPy_c > StateID_LiftUp
Lifting up another player.
void setJumpCommonBase()
u32 mSpinFireBallCooldown
Timer to control how often fireballs the player automatically shoots while spinning.
bool fn_80143220(sBcPointData &data1, sBcPointData &data2)
virtual int doDelete()
do method for the delete operation.
u32 mStartSpinCooldown
Timer to disable spin jumps and propeller spins while active.
u8 mJumpComboTimer
Timer for allowing a slight delay between jumps to still count as a combo.
virtual bool isSpinLiftUpEnable()
Returns whether the actor can be carried.
virtual void setPowerup(PLAYER_POWERUP_e, int)
void fn_80127740(int jumpType, AnmBlend_e blendMode)
Jump animation set, some enum as first param.
int mPoleGrabCooldown
Timer to disable grabbing a pole while active.
u8 mWallSlideCooldown
Timer to disable wall sliding while active.
virtual int preExecute()
pre method for the execute operation.
void fn_801395a0()
void fn_80143060(sBcPointData &data1, sBcPointData &data2, bool)
int mSpinTimer
Timer for the duration of a spin jump.
bool fn_801477c0()
int mSpinCooldown
Timer to disable another spin action while active.
bool fn_80145c00(PLAYER_POWERUP_e)
void getCcBounds(sRangeDataF *bounds)
static sFStateID_c< dAcPy_c > StateID_BlockJump
Rescue Toad jumping out of his block.
virtual void eatMove(dActor_c *eatingActor)
Updates the actor's position during eating actions.
CannonJumpSubstate_e
bool spinLiftUp(dActor_c *, bool)
virtual int draw()
do method for the draw operation.
virtual void setEatTongueOff(dActor_c *eatingActor)
Callback for when the eating action is canceled.
void fn_801282d0(AnmBlend_e blendMode)
void setFireBallDamage(u8 type)
int mFastRunFrames
How many frames the player has been running at over 1 unit/frame.
void setWallSlideEffect()
virtual int create()
do method for the create operation.
virtual bool _setJump(float jumpSpeed, float speedF, bool allowSteer, int keyMode, int jumpMode)
Starts a jump action unconditionally. See setJump().
int change_reverse_scale_set()
float mSpinHoldReqTarget
The target X position to move to while doing a spin in place.
virtual void setSpinLiftUpActor(dActor_c *carryingActor)
Callback for when the actor is picked up by another actor.
virtual void setEatMouth(dActor_c *eatingActor)
Callback for when the actor is being eaten.
bool fn_80146e40(float, float, bool)
void fn_801416c0(PLAYER_POWERUP_e)
void reviseBcDataCarryHardBlock(sBcPointData &data1, sBcPointData &data2)
short mBalloonHelpVoiceCooldown
Timer to only allow the help voice to play every 2 seconds.
void calcUzuSwimSpeed(float, float, float *)
int mPowerUpEffectTimer
Timer controlling the powerup effect duration and opacity.
virtual void postExecute(MAIN_STATE_e status)
post method for the execute operation.
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
static dActor_c * construct(ProfileName profName, unsigned long param, const mVec3_c *position, const mAng3_c *rotation, u8 layer)
Creates a stage actor without a parent.
Definition d_actor.cpp:166
virtual void setCarryFall(dActor_c *carryingActor, int collisionDelay)
Callback for when the actor is dropped by the carrying actor.
Definition d_actor.hpp:118
@ CARRY_RELEASE
The actor is being released from carry.
Definition d_actor.hpp:54
@ CARRY_THROW
The actor is being actively thrown by the player.
Definition d_actor.hpp:55
fBaseID_e mEatenByID
The unique identifier of the eating actor.
Definition d_actor.hpp:364
virtual s8 & getPlrNo()
Gets the player number associated with the actor. See mPlayerNo.
Definition d_actor.hpp:105
virtual void setSpinLiftUpActor(dActor_c *carryingActor)
Callback for when the actor is picked up by another actor.
Definition d_actor.cpp:612
dBc_c mBc
The actor-to-tile collision sensor.
Definition d_actor.hpp:342
virtual bool isSpinLiftUpEnable()
Returns whether the actor can be carried.
Definition d_actor.hpp:109
u32 mCarryingFlags
The actor's carry actions. See CARRY_ACTION_e.
Definition d_actor.hpp:333
u8 mKind
The actor's kind. Value is a STAGE_ACTOR_KIND_e.
Definition d_actor.hpp:374
u8 mEatState
The actor's eat state. Value is a EAT_STATE_e.
Definition d_actor.hpp:365
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
@ EAT_TYPE_EAT
The actor can be eaten and then spat out.
Definition d_actor.hpp:37
@ EAT_TYPE_NONE
The actor cannot be eaten.
Definition d_actor.hpp:36
u8 mThrowDirection
The actor's direction when thrown or dropped after carrying.
Definition d_actor.hpp:334
void setKind(u8 kind)
Sets the actor's kind. See STAGE_ACTOR_KIND_e.
Definition d_actor.cpp:176
u8 mEatBehavior
The actor's eat behaviour. Value is a EAT_BEHAVIOR_e.
Definition d_actor.hpp:366
s8 mPlayerNo
The player associated with the actor, -1 if not associated to any player.
Definition d_actor.hpp:375
dPropelParts_c * mpPropelParts
The actor's propeller effect manager.
Definition d_actor.hpp:373
@ EAT_STATE_NONE
The actor is not being eaten.
Definition d_actor.hpp:27
dActor_c()
Constructs a new actor.
Definition d_actor.cpp:46
dRc_c mRc
The actor's ride surface manager.
Definition d_actor.hpp:343
@ STAGE_ACTOR_ENEMY
An enemy actor.
Definition d_actor.hpp:49
@ STAGE_ACTOR_YOSHI
The Yoshi actor.
Definition d_actor.hpp:48
@ STAGE_ACTOR_PLAYER
The player actor.
Definition d_actor.hpp:47
u8 mLayer
The actor's layer.
Definition d_actor.hpp:377
bool mVisible
Whether the actor should be visible or not. Defaults to true .
void calcSpeedXY()
Updates the actor's speed (2D actors). See here for details.
mVec3_c mScale
The actor's scale (defaults to 1).
float mAccelF
The actor's horizontal acceleration.
mVec3_c mSpeed
The actor's speed.
mVec3_c mLastPos
The actor's position in the previous frame.
mVec3_c mPos
The actor's position.
mVec3_c mSpeedMax
The actor's maximum speed.
mVec3_c mCenterOffs
The offset from the position to the center of the actor (defaults to 0).
void calcFallSpeed()
Updates the actor's falling speed. See here for details.
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).
u32 mActorProperties
The actor's properties. See fProfile::fActorProfile_c::mActorProperties.
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
float getUnderPos()
Gets the Y position of the bottom of the collider.
Definition d_cc.cpp:135
float getCenterPosY()
Gets the Y position of the center of the collider.
Definition d_cc.cpp:139
float mCollOffsetY[CC_KIND_COUNT]
The Y offset for a collision.
Definition d_cc.hpp:297
float getCenterPosX()
Gets the X position of the center of the collider.
Definition d_cc.cpp:151
dActor_c * getOwner() const
Gets the owner actor of this collider.
Definition d_cc.hpp:163
sCcDatNewF mCcData
The collision data of this collider.
Definition d_cc.hpp:273
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
static dNext_c * m_instance
The singleton instance of this class.
Definition d_next.hpp:74
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
void fn_800d2de0(float, int, mVec3_c &, u8)
float getValue(dPyModelData_s model, u8 powerup)
static bool CheckIceballLimit(int playerNo, int limitMode)
Checks if a new iceball can be created for a player based on the limit mode.
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.
void onStatus(int id)
Enables the status with the given ID. See Status_e.
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].
void startSound(ulong soundID, bool)
int mSquishNoMoveTimer
Timer for how long to freeze the squished player in position.
KaniArg_e
Arguments for transitioning to the cliff state.
@ KANI_ARG_HANG_UP_VINE
Climbing onto the cliff from a vine.
@ KANI_ARG_WALK_FORCE
Standing on the cliff, disallow immediately hanging from it by holding down.
@ KANI_ARG_HANG
Landing high enough on the cliff to stand on it, but hang down from it instead.
@ KANI_ARG_HANG_HAND
Catching the cliff from below, hang from it.
@ KANI_ARG_JUMP_HANG
Falling onto the cliff, immediately hang from it.
@ KANI_ARG_WALK
Standing on the cliff and walking.
void holdSound(ulong soundID, bool)
@ 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_R
Touching a background object on the right.
@ BGC_FOOT
Colliding with the foot sensor.
@ BGC_ON_WATER_MOVE
On water by being mini or sliding with the penguin suit.
@ 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.
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 startJump(AnmBlend_e blendMode, int jumpType)
mEf::levelEffect_c mSlipSmokeEffect
Smoke when sliding down a slope or into a cannon.
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.
virtual void startPlayerVoice(int, int)
fBaseID_e mRelatedActorID
Actor that is eating the player, or the door actor.
virtual int doDelete()
do method for the delete operation.
static sFStateVirtualID_c< daPlBase_c > StateID_Swim
Swimming. Argument: See SwimArg_e.
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.
void calcSpeedOnIceLift()
int mAirWalkTimer
Timer to wait before changing to the falling state after walking off a ledge.
float mKaniHeight
The height of the last cliff the player interacted with.
void setStatus(int id)
int mDemoStateArg
To be used as an argument to the new demo state.
mEf::levelEffect_c mSmokeEffect
static sFStateVirtualID_c< daPlBase_c > StateID_DemoNone
Default demo state, checking for pipe entry. Argument: Whether to not force execution start (bool).
void getTurnPower(sTurnPowerData &)
int mTimer_ce8
[Related to balloon break jump]
const daPlBase_c * mpNoHitPlayer
The player that cannot collide with this player.
@ STATUS_KANI_HANG
The player is hanging from a cliff.
@ STATUS_THROW
The player is throwing something.
@ 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_CAN_WATER_SLIDE
The player can slide on water because of the penguin suit.
@ 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_PENGUIN_SLIDE_JUMP
The player is doing a penguin slide jump.
@ STATUS_KANI_WALK
The player is doing a crab walk on a cliff.
@ STATUS_HANG
The player is hanging from a ceiling rope.
@ 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_KANI_HANG_ANIMATION
The player is animating into the hanging pose on a cliff.
@ STATUS_INITIAL_SLIDE
The player is in an initial slide action. [Used in 6-6 to slide all the way down automatically].
@ STATUS_PROPEL
The player is flying with the propeller suit.
@ STATUS_QUAKE_SMALL
A small quake that makes the player do a hop was triggered.
@ STATUS_ALL_DOWN_FADE
All players have died and the screen is transitioning.
@ 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_CANNON_JUMP
The player is flying out of a pipe cannon.
@ 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_PENGUIN_SLIDE
The player is sliding with the penguin suit.
@ STATUS_PENGUIN_RECOIL
The player is bouncing back after hitting an enemy that cannot be killed by a penguin slide.
@ STATUS_CREATED
The player was created.
@ STATUS_JUMP
The player is jumping.
@ STATUS_FOLLOW_MAME_KURIBO
Mini Goombas are attached to the player.
@ STATUS_YOSHI_DISMOUNT_JUMP
The player is doing a jump to dismount Yoshi.
@ STATUS_SPIN_HIP_ATTACK_FALL
The player is falling while doing a down spin.
@ STATUS_SIT_JUMP
The player is doing a sitting jump.
@ STATUS_8E
[Cannon shot related]
@ STATUS_PROPEL_SLOW_FALL
The player will fall slowly while spinning down with the propeller suit.
@ STATUS_CAN_SPIN
The player can shake the controller to do a spin jump or a propeller spin.
@ STATUS_STAR_JUMP
The player is jumping while in star mode.
@ 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_FIREBALL_PREPARE_SHOOT
The player is about to shoot a fireball.
@ STATUS_CAN_WATER_WALK
The player can walk on water because of the mini mushroom.
@ STATUS_CAN_PENGUIN_SLIDE
If the player can start sliding as a penguin.
@ 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_KANI_JUMP
The player is doing a crab jump on a cliff.
@ 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_STUNNED
Stunned by electric shock or ice.
@ STATUS_CAN_LAND
The player can land on Yoshi or another player.
@ 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_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_07
[Ice related]
@ 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_ON_WATER_MOVE
The player is on water by being mini or sliding with the penguin suit.
@ STATUS_PROPEL_UP
The player is flying upwards with the propeller suit.
@ 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_39
[Swim related]
void * mStateArg
To be used as an argument to the new state.
static sFStateVirtualID_c< daPlBase_c > StateID_Slip
Sliding down a slope. Argument: None.
int mSubstateValue
States can use this field for various purposes - as a timer, boolean flag, etc.
SwimArg_e
Arguments for transitioning to the swim state.
@ SWIM_ARG_FIREBALL
Player was about to shoot a fireball, shoot it while in water.
@ SWIM_ARG_ENTERING
Just entered the water.
@ SWIM_ARG_INITIAL
Already in water at the start of the swim action.
@ SWIM_ARG_CLIFF_HANG
Falling from a cliff into water.
virtual void postExecute(fBase_c::MAIN_STATE_e status)
post method for the execute operation.
static sFStateVirtualID_c< daPlBase_c > StateID_None
Default state, does nothing. Argument: None.
bool isStatus(int id)
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.
@ CROUCH_ARG_FROM_WALK
Crouching while already on the ground.
@ CROUCH_ARG_FROM_SIT_JUMP
Landing from a crouch jump.
@ CROUCH_ARG_FROM_OTHER
Crouching after a slide or a ground pound.
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_VINE_TOUCH_FULL
Fully touching a vine / mesh net / rock wall.
@ BGC_VINE_TOUCH_U
Touching a vine / mesh net / rock wall on the top.
@ BGC_LIFT
[Figure out a better name for this].
@ BGC_VINE_TOUCH_L
Touching a vine / mesh net / rock wall on the left.
@ BGC_VINE_TOUCH_D
Touching a vine / mesh net / rock wall on the bottom.
@ BGC_VINE_TOUCH
Touching a vine / mesh net / rock wall on any side.
static bool fn_8005f570(PLAYER_POWERUP_e, int)
bool fn_8014eb70(dAcPy_c *player, int)
bool fn_8014f030(dAcPy_c *player)
MAIN_STATE_e
The possible operation results.
Definition f_base.hpp:36
@ SUCCESS
The operation was completed successfully.
Definition f_base.hpp:39
void deleteRequest()
Requests deletion of the base.
Definition f_base.cpp:289
@ ACTOR
The base is an actor.
Definition f_base.hpp:31
ProfileName mProfName
The base's profile name.
Definition f_base.hpp:63
@ 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 * searchBaseByGroupType(unsigned char groupType, const fBase_c *parent)
Searches for a base with a given group type, optionally under a given parent.
Definition f_manager.cpp:41
static fBase_c * searchBaseByID(fBaseID_e id)
Searches for a base with the given ID.
Definition f_manager.cpp:18
mAng y
The rotation on the Y axis.
Definition m_angle.hpp:126
mAng x
The rotation on the X axis.
Definition m_angle.hpp:125
@ HIDDEN
The screen is completely unblocked.
static mFaderBase_c * mFader
The fader currently in use.
Definition m_fader.hpp:18
A 3x4 matrix.
Definition m_mtx.hpp:9
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
void XrotM(mAng angle)
Rotates the matrix on the X axis by the given angle.
Definition m_mtx.cpp:41
void YrotM(mAng angle)
Rotates the matrix on the Y axis by the given angle.
Definition m_mtx.cpp:67
A three-dimensional floating point vector.
Definition m_vec.hpp:122
static const T::GlobalData_t mData
PLAYER_POWERUP_e
The identifiers for each powerup.
@ CREATE_ITEM_BUBBLE
Spawns the player inside a bubble.
@ CREATE_ITEM_YOSHI
Spawns a Yoshi along with the player.
@ CREATE_ITEM_STAR_POWER
Gives the player Star Power.
@ BASE_ID_NULL
Represents the null base.
Definition f_base_id.hpp:7
#define ACTOR_PROFILE(profName, className, properties)
Creates an actor profile, using the profile number as the execute and draw order value.
Definition f_profile.hpp:29
s16 atan2s(float sin, float cos)
Converts a sine and a cosine to an angle in units.
Definition c_math.cpp:167
void showFukidashi(int playerId, int fukidashiAction)
Displays the given action prompt to the given player.
void hideFukidashiTemporarily(int playerId, int fukidashiAction, int param3)
Temporarily hides the given action prompt for the given player.
void hideFukidashiForSession(int playerId, int fukidashiAction)
Hides the given action prompt for the given player for the rest of the current session.
void FUN_800b37b0(int playerId, int fukidashiAction)
T calcTimer(T *value)
Decrements a timer value.
Definition s_lib.hpp:21
float addCalc(float *value, float target, float smoothing, float maxStep, float minStep)
Smoothly moves value towards target using proportional scaling.
Definition s_lib.cpp:3
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_DEFINE(class, name)
Defines a state.
Definition s_State.hpp:36
#define STATE_VIRTUAL_DEFINE(class, name)
Defines a virtual state.
Definition s_State.hpp:46
A one-dimensional short angle vector.
Definition m_angle.hpp:12
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 mKind
The type of this collider. See CC_KIND_e.
Definition d_cc.hpp:96
u8 mAttack
The attack type of this collider. See CC_ATTACK_e.
Definition d_cc.hpp:97
sCcDatNew mBase
Base collider data.
Definition d_cc.hpp:94
mVec2_POD_c mOffset
The offset of the collider.
Definition d_cc.hpp:82