1#include <game/bases/d_enemy.hpp>
3#include <game/bases/d_a_player_base.hpp>
4#include <game/bases/d_a_player_manager.hpp>
5#include <game/bases/d_actor_manager.hpp>
6#include <game/bases/d_effectmanager.hpp>
7#include <game/bases/d_enemy_manager.hpp>
8#include <game/bases/d_game_com.hpp>
9#include <game/bases/d_multi_manager.hpp>
10#include <game/bases/d_score_manager.hpp>
11#include <game/mLib/m_effect.hpp>
23const float dEn_c::smc_DEADFALL_GRAVITY = -0.25f + 0.00625001f;
24const float dEn_c::smc_DEADFALL_YSPEED = 3.9f;
25const float dEn_c::smc_DEADFALL_YSPEED_MAX = -4.0f;
26const s16 dEn_c::smc_DEADFALL_SPINSPEED = 0xc00;
28bool dEn_c::hitCallback_Star(
dCc_c *self,
dCc_c *other) {
29 daPlBase_c *player = (daPlBase_c *) other->
getOwner();
34 hitdamageEffect(mVec3_c(collPos, 5500.0f));
37 if (
mCombo.mType == dEnCombo_c::COMBO_SHORT) {
40 player->
slideComboSE(player->getStarCount(), shortCombo);
42 int score =
mCombo.getComboScore(dEnCombo_c::calcPlStarCnt(player));
45 l_base_fall_speed_x[dir],
47 smc_DEADFALL_YSPEED_MAX,
59bool dEn_c::hitCallback_Cannon(
dCc_c *self,
dCc_c *other) {
60 daPlBase_c *player = (daPlBase_c *) other->
getOwner();
65 hitdamageEffect(mVec3_c(collPos, 5500.0f));
68 if (
mCombo.mType == dEnCombo_c::COMBO_SHORT) {
73 int score =
mCombo.getComboScore(dEnCombo_c::calcPlComboCnt(player));
76 l_base_fall_speed_x[dir],
78 smc_DEADFALL_YSPEED_MAX,
90bool dEn_c::hitCallback_Slip(
dCc_c *self,
dCc_c *other) {
91 daPlBase_c *player = (daPlBase_c *) other->
getOwner();
96 hitdamageEffect(mVec3_c(collPos, 5500.0f));
98 setDeathSound_Slip(player);
100 int score =
mCombo.getComboScore(dEnCombo_c::calcPlComboCnt(player));
103 l_base_fall_speed_x[dir],
105 smc_DEADFALL_YSPEED_MAX,
106 smc_DEADFALL_GRAVITY,
117bool dEn_c::hitCallback_PenguinSlide(
dCc_c *self,
dCc_c *other) {
118 return hitCallback_Slip(self, other);
121bool dEn_c::hitCallback_Screw(
dCc_c *self,
dCc_c *other) {
125bool dEn_c::hitCallback_WireNet(
dCc_c *self,
dCc_c *other) {
126 daPlBase_c *player = (daPlBase_c *) other->
getOwner();
130 dAudio::g_pSndObjEmy->startSound(SE_EMY_DOWN,
mPos, 0);
133 0.75f * l_base_fall_speed_x[dir],
135 smc_DEADFALL_YSPEED_MAX,
136 smc_DEADFALL_GRAVITY,
147bool dEn_c::hitCallback_Large(
dCc_c *self,
dCc_c *other) {
148 daPlBase_c *player = (daPlBase_c *) other->
getOwner();
152 float xSpeed = l_EnMuki[dir];
156 }
else if (xSpeed < -6.0f) {
163 smc_DEADFALL_YSPEED_MAX,
164 smc_DEADFALL_GRAVITY,
175bool dEn_c::hitCallback_Rolling(
dCc_c *self,
dCc_c *other) {
179bool dEn_c::hitCallback_Spin(
dCc_c *self,
dCc_c *other) {
180 daPlBase_c *player = (daPlBase_c *) other->
getOwner();
184 setDeathSound_Spin();
187 playerPos.x = player->
mPos.x;
188 playerPos.y = player->
mPos.y;
189 hipatkEffect(mVec3_c(playerPos, 5500.0f));
191 int score =
mCombo.getComboScore(dEnCombo_c::calcPlFumiCnt(player));
194 l_base_fall_speed_x[dir],
196 smc_DEADFALL_YSPEED_MAX,
197 smc_DEADFALL_GRAVITY,
208bool dEn_c::hitCallback_HipAttk(
dCc_c *self,
dCc_c *other) {
209 daPlBase_c *player = (daPlBase_c *) other->
getOwner();
213 setDeathSound_HipAttk();
216 playerPos.x = player->
mPos.x;
217 playerPos.y = player->
mPos.y;
218 hipatkEffect(mVec3_c(playerPos, 5500.0f));
220 int score =
mCombo.getComboScore(dEnCombo_c::calcPlFumiCnt(player));
223 l_base_fall_speed_x[dir],
225 smc_DEADFALL_YSPEED_MAX,
226 smc_DEADFALL_GRAVITY,
237bool dEn_c::hitCallback_YoshiHipAttk(
dCc_c *self,
dCc_c *other) {
238 daPlBase_c *player = (daPlBase_c *) other->
getOwner();
242 int comboScore =
mCombo.getComboScore(dEnCombo_c::calcPlFumiCnt(player));
243 if (comboScore >= 0 && plrNo < PLAYER_COUNT) {
244 dScoreMng_c::m_instance->ScoreSet(
this, comboScore, plrNo, dScoreMng_c::smc_SCORE_X, dScoreMng_c::smc_SCORE_Y);
247 dAudio::g_pSndObjEmy->startSound(SE_EMY_YOSHI_HPDP,
mPos, 0);
249 setDeathInfo_YoshiFumi(player);
254bool dEn_c::hitCallback_YoshiBullet(
dCc_c *self,
dCc_c *other) {
255 daPlBase_c *player = (daPlBase_c *) other->
getOwner();
259 setDeathSound_Fire();
261 hitdamageEffect(mVec3_c(self->getCollPosX(), self->getCollPosY(), 5500.0f));
263 dActorMng_c::m_instance->createUpCoin(
getCenterPos(), dir, 1, 0);
266 l_base_fall_speed_x[dir],
268 smc_DEADFALL_YSPEED_MAX,
269 smc_DEADFALL_GRAVITY,
280bool dEn_c::hitCallback_YoshiFire(
dCc_c *self,
dCc_c *other) {
281 daPlBase_c *player = (daPlBase_c *) other->
getOwner();
282 u8 dir = !(player->
mSpeed.x >= 0.0f);
284 dActorMng_c::m_instance->createUpCoin(centerPos, dir, 1, 0);
288 hitdamageEffect(mVec3_c(collPos, 5500.0f));
291 if (
mCombo.mType == dEnCombo_c::COMBO_SHORT) {
302 l_base_fall_speed_x[dir],
304 smc_DEADFALL_YSPEED_MAX,
305 smc_DEADFALL_GRAVITY,
316bool dEn_c::hitCallback_Shell(
dCc_c *self,
dCc_c *other) {
317 daPlBase_c *player = (daPlBase_c *) other->
getOwner();
322 hitdamageEffect(mVec3_c(collPos, 5500.0f));
325 if (plrNo >= 0 && plrNo < PLAYER_COUNT) {
327 if (
mCombo.mType == dEnCombo_c::COMBO_SHORT) {
337 dAudio::g_pSndObjEmy->startSound(SE_EMY_DOWN,
mPos, 0);
341 l_base_fall_speed_x[dir],
343 smc_DEADFALL_YSPEED_MAX,
344 smc_DEADFALL_GRAVITY,
355bool dEn_c::hitCallback_Fire(
dCc_c *self,
dCc_c *other) {
356 daPlBase_c *player = (daPlBase_c *) other->
getOwner();
357 u8 dir = !(player->
mSpeed.x >= 0.0f);
360 setDeathSound_Fire();
362 dActorMng_c::m_instance->createUpCoin(
getCenterPos(), dir, 1, 0);
365 l_base_fall_speed_x[dir],
367 smc_DEADFALL_YSPEED_MAX,
368 smc_DEADFALL_GRAVITY,
379bool dEn_c::hitCallback_Ice(
dCc_c *self,
dCc_c *other) {
381 daPlBase_c *player = (daPlBase_c *) other->
getOwner();
383 if (player->
mSpeed.x >= 0.0f) {
384 mBoyoMng.mDirection = 0;
386 mBoyoMng.mDirection = 1;
389 for (
int i = 0; i < PLAYER_COUNT; i++) {
390 dAcPy_c *pl = daPyMng_c::getPlayer(i);
392 pl->cancelCarry(
this);
403void dEn_c::setDeadMode(
dActor_c *actor,
int i) {
411 setDeathInfo_Smoke(actor);
413 setDeathInfo_SpinFumi(actor, 0);
415 static const float cs_effect_offset_x[] = { -6.0f, 6.0f };
417 center.x += cs_effect_offset_x[
mDeathInfo.mDirection];
418 hitdamageEffect(center);
420 dAudio::g_pSndObjEmy->startSound(SE_EMY_DOWN,
mPos, 0);
425void dEn_c::setDeathInfo_Quake(
int i) {
426 mVec3_c center(getCenterX(), getCenterY(), 5500.0f);
437 dEnemyMng_c::m_instance->breakdownSE(dEnemyMng_c::m_instance->m_154,
mPos);
439 dEnemyMng_c::m_instance->incQuakeComboCount(0);
441 int comboScore =
mCombo.getQuakeScore(dEnemyMng_c::m_instance->m_154);
446 smc_DEADFALL_YSPEED_MAX,
447 smc_DEADFALL_GRAVITY,
456void dEn_c::setDeathInfo_Smoke(
dActor_c *actor) {
458 if (actor !=
nullptr) {
482 smc_DEADFALL_YSPEED_MAX,
483 smc_DEADFALL_GRAVITY,
492void dEn_c::setDeathInfo_YoshiFumi(
dActor_c *killedBy) {
501 &StateID_DieYoshiFumi,
509void dEn_c::setDeathInfo_Other(
dActor_c *killedBy) {
511 if (killedBy !=
nullptr) {
528void dEn_c::setDeathInfo_SpinFumi(
dActor_c *killedBy,
int) {
533 l_base_fall_speed_x[dir],
535 smc_DEADFALL_YSPEED_MAX,
536 smc_DEADFALL_GRAVITY,
545void dEn_c::setDeathInfo_IceBreak() {
552 l_base_fall_speed_x[dir],
554 smc_DEADFALL_YSPEED_MAX,
555 smc_DEADFALL_GRAVITY,
564void dEn_c::setDeathInfo_IceVanish() {
567 int coinDir = dGameCom::rndInt(2);
568 dActorMng_c::m_instance->createUpCoin(
getCenterPos(), coinDir, 1, 0);
578 &StateID_DieIceVanish,
586void dEn_c::initializeState_DieFumi() {
587 for (
int i = 0; i < PLAYER_COUNT; i++) {
588 dAcPy_c *pl = daPyMng_c::getPlayer(i);
590 pl->cancelCarry(
this);
614 if (plrNo >= 0 && plrNo < PLAYER_COUNT) {
615 dScoreMng_c::m_instance->ScoreSet(
this, score, plrNo, dScoreMng_c::smc_SCORE_X, dScoreMng_c::smc_SCORE_Y);
617 dScoreMng_c::m_instance->UnKnownScoreSet(
this, score, 0.0f, 24.0f);
628void dEn_c::finalizeState_DieFumi() {}
630void dEn_c::executeState_DieFumi() {
631 s16 angDelta = smc_DEADFALL_SPINSPEED / 4;
633 angDelta *= smc_WATER_ROLL_DEC_RATE;
641void dEn_c::initializeState_DieFall() {
642 for (
int i = 0; i < PLAYER_COUNT; i++) {
643 dAcPy_c *pl = daPyMng_c::getPlayer(i);
645 pl->cancelCarry(
this);
669 if (plrNo >= 0 && plrNo < PLAYER_COUNT) {
670 dScoreMng_c::m_instance->ScoreSet(
this, score, plrNo, dScoreMng_c::smc_SCORE_X, dScoreMng_c::smc_SCORE_Y);
672 dScoreMng_c::m_instance->UnKnownScoreSet(
this, score, 0.0f, 24.0f);
683void dEn_c::finalizeState_DieFall() {}
685void dEn_c::executeState_DieFall() {
686 const static s16 cs_spin_speed[] = { 0x100, -0x100 };
691 angDeltaX = smc_DEADFALL_SPINSPEED;
694 angDeltaX = -smc_DEADFALL_SPINSPEED;
698 angDeltaX *= smc_WATER_ROLL_DEC_RATE;
708void dEn_c::initializeState_DieBigFall() {
709 initializeState_DieFall();
712void dEn_c::finalizeState_DieBigFall() {
713 finalizeState_DieFall();
716void dEn_c::executeState_DieBigFall() {
717 mAngle.x += smc_DEADFALL_SPINSPEED;
723void dEn_c::initializeState_DieSmoke() {
725 mEf::createEffect(
"Wm_en_burst_m", 0, &pos,
nullptr,
nullptr);
729void dEn_c::finalizeState_DieSmoke() {}
731void dEn_c::executeState_DieSmoke() {
735void dEn_c::initializeState_DieIceVanish() {
741 if (plrNo >= 0 && plrNo < PLAYER_COUNT) {
742 dScoreMng_c::m_instance->ScoreSet(
this, score, plrNo, dScoreMng_c::smc_SCORE_X, dScoreMng_c::smc_SCORE_Y);
744 dScoreMng_c::m_instance->UnKnownScoreSet(
this, score, 0.0f, 24.0f);
749void dEn_c::finalizeState_DieIceVanish() {}
751void dEn_c::executeState_DieIceVanish() {
755void dEn_c::initializeState_DieYoshiFumi() {
757 mEf::createEffect(
"Wm_mr_yoshistep", 0, &pos,
nullptr,
nullptr);
761void dEn_c::finalizeState_DieYoshiFumi() {}
763void dEn_c::executeState_DieYoshiFumi() {
767void dEn_c::initializeState_DieGoal() {}
769void dEn_c::finalizeState_DieGoal() {}
771void dEn_c::executeState_DieGoal() {}
773void dEn_c::initializeState_DieOther() {
777void dEn_c::finalizeState_DieOther() {}
779void dEn_c::executeState_DieOther() {}
781void dEn_c::setDeathSound_Fire() {
782 dAudio::g_pSndObjEmy->startSound(SE_EMY_DOWN,
mPos, 0);
785void dEn_c::setDeathSound_HipAttk() {
786 if (
mFlags & EN_IS_HARD) {
787 dAudio::g_pSndObjEmy->startSound(SE_EMY_DOWN_HPDP_H,
mPos, 0);
789 dAudio::g_pSndObjEmy->startSound(SE_EMY_DOWN_HPDP_S,
mPos, 0);
793void dEn_c::setDeathSound_Slip(
dActor_c *killedBy) {
794 const static dAudio::SoundEffectID_t cs_combo_se[] = {
806 int count = ((daPlBase_c *) killedBy)->m_cee;
807 if (count >= ARRAY_SIZE(cs_combo_se)) {
808 count = ARRAY_SIZE(cs_combo_se) - 1;
817void dEn_c::setDeathSound_Spin() {
818 if (
mFlags & EN_IS_HARD) {
819 dAudio::g_pSndObjEmy->startSound(SE_EMY_DOWN_HPDP_H,
mPos, 0);
821 dAudio::g_pSndObjEmy->startSound(SE_EMY_DOWN_HPDP_S,
mPos, 0);
825void dEn_c::setDeathSound_Rolling() {}
static void SetVsHitEffect(mVec3_c *)
bool isState(const sStateIDIf_c &other) const
Checks if the actor is currently in the given state.
sFStateStateMgr_c< dActorMultiState_c, sStateMethodUsr_FI_c, sStateMethodUsr_FI_c > mStateMgr
The state manager.
The minimum required implementation for a stage actor.
void deleteActor(u8 deleteForever)
Deletes the actor and optionally disables respawn.
void slideComboSE(int multiplier, bool shortCombo)
Plays the combo kill sound effect.
bool mNoRespawn
Whether the actor should not respawn after being deleted.
dBc_c mBc
The actor-to-tile collision sensor.
static bool getTrgToSrcDir_Main(float trgX, float srcX)
See getTrgToSrcDirFunc.
u8 mAmiLayer
The actor's layer for chainlink fences.
u8 mDirection
The actor's facing direction.
virtual void removeCc()
Disables the actor's collision.
int mComboMultiplier
The current combo multiplier obtained by the actor by colliding with other actors.
s8 mPlayerNo
The player associated with the actor, -1 if not associated to any player.
virtual s8 * getPlrNo()
Gets the player number associated with the actor. See mPlayerNo.
float mAccelF
The actor's horizontal acceleration.
mVec3_c mSpeed
The actor's speed.
mVec3_c mPos
The actor's position.
mVec3_c mSpeedMax
The actor's maximum speed.
void posMove()
Moves the actor by its speed.
mVec3_c getCenterPos() const
Gets the actor's centered position.
mAng3_c mAngle
The actor's rotation (for 2D actors).
float mAccelY
The actor's vertical acceleration.
void calcSpeedY()
Updates the actor's Y speed. See here for details.
Collider ("Collision Check") class - handles collisions between actors.
mVec2_c mCollPos
The position where the last collision occurred.
dActor_c * getOwner() const
Gets the owner actor of this collider.
static const u8 smc_UNKNOWN_HIT
An enemy actor. Note that the definition of "enemy" in this context is actually any interactible stag...
u8 mIceDeathDirection
The X direction to move towards on ice death.
void WaterCheck(mVec3_c &pos, float h)
dDeathInfo_c mDeathInfo
The parameters for the death animation.
dIceMng_c mIceMng
The ice manager for this enemy.
dEnCombo_c mCombo
The enemy combo manager.
u32 mFlags
Flags for this actor. See FLAGS_e.
bool mInLiquid
Whether the enemy is in a liquid.
virtual bool checkComboClap(int max)
void setClapSE()
Plays the clap sound effect.
static dMultiMng_c * mspInstance
The instance of this class.
static fBase_c * searchBaseByID(fBaseID_e id)
Searches for a base with the given ID.
A two-dimensional floating point vector.
The interface for state IDs.
#define STATE_VIRTUAL_DEFINE(class, name)
Defines a virtual state.