1#include <game/bases/d_a_en_togezo_base.hpp>
2#include <game/bases/d_a_player.hpp>
4#include <game/mLib/m_allocator_dummy_heap.hpp>
7const sBcSensorPoint daEnTogezoBase_c::smc_toge_head = { SENSOR_IS_POINT, 0, 0xc000 };
8const sBcSensorLine daEnTogezoBase_c::smc_toge_foot = { SENSOR_IS_LINE, -0x4000, 0x4000, 0x0 };
9const sBcSensorLine daEnTogezoBase_c::smc_toge_wall = { SENSOR_IS_LINE, 0x7000, 0x5000, 0x8000 };
11const sBcSensorLine daEnTogezoBase_c::smc_sakasa_toge_foot = { SENSOR_IS_LINE, -0x3000, 0x2000, 0x0 };
13const sBcSensorPoint daEnTogezoBase_c::smc_pipo_head = { SENSOR_IS_POINT, 0, 0x6000 };
14const sBcSensorLine daEnTogezoBase_c::smc_pipo_foot = { SENSOR_IS_LINE, -0x3000, 0x3000, -0x6000 };
15const sBcSensorLine daEnTogezoBase_c::smc_pipo_wall = { SENSOR_IS_LINE, 0x2000, -0x2000, 0x6000 };
16const sCcDatNewF daEnTogezoBase_c::smc_toge_cc = {
21 BIT_FLAG(CC_KIND_PLAYER) | BIT_FLAG(CC_KIND_PLAYER_ATTACK) |
22 BIT_FLAG(CC_KIND_YOSHI) | BIT_FLAG(CC_KIND_ENEMY) |
23 BIT_FLAG(CC_KIND_TAMA),
24 (u32) ~(BIT_FLAG(CC_ATTACK_NONE) | BIT_FLAG(CC_ATTACK_YOSHI_MOUTH) | BIT_FLAG(CC_ATTACK_SPIN_LIFT_UP) | BIT_FLAG(CC_ATTACK_SAND_PILLAR)),
26 dEn_c::normal_collcheck
29const float daEnTogezoBase_c::smc_WALK_SPEED_DAT[2] = { 0.5f, -0.5f };
30const s16 daEnTogezoBase_c::smc_ROTATE_SPEED_DAT[2] = { 0x400, -0x400 };
31const s16 daEnTogezoBase_c::smc_ANGLE_Y[2] = { 12000, -12000 };
46 createShell(
"togezo",
"g3d/togezo.brres",
"togezo_shell",
nullptr, 0.0f);
55 mScale.set(1.0f, 1.0f, 1.0f);
58 mFumiProc.mFumiCheck.m_00 = 8;
66void daEnTogezoBase_c::createModel() {
79 nw4r::g3d::ResMdl paipoMdl =
mPaipoResFile.GetResMdl(
"paipo");
90 setDeathInfo_Smoke(
nullptr);
95 if (!
isState(StateID_Ice) && checkRyusa()) {
100 if (isCullCheckOk()) {
108 if (mShellMode == SHELL_MODE_PAIPO) {
110 }
else if (mShellMode == SHELL_MODE_BASE) {
119void daEnTogezoBase_c::calcMdl() {
121 if (mShellMode == SHELL_MODE_PAIPO) {
123 }
else if (mShellMode == SHELL_MODE_BASE) {
130void daEnTogezoBase_c::calcPaipoMdl() {
134 mMatrix.trans(pos.x, pos.y, pos.z);
144void daEnTogezoBase_c::calcTogezoMdl() {
148 mMatrix.trans(pos.x, pos.y, pos.z);
153 mMatrix.concat(mMtx_c::createTrans(0.0f, 6.0f, 0.0f));
155 mMatrix.concat(mMtx_c::createTrans(0.0f, -6.0f, 0.0f));
162void daEnTogezoBase_c::drawTogezo() {
166void daEnTogezoBase_c::drawPaipo() {
173 if (
mAllocator.mpHeap != mAllocatorDummyHeap_c::getInstance()) {
181void daEnTogezoBase_c::setAfterSleepState() {
186bool daEnTogezoBase_c::specialFumiProc(
dActor_c *actor) {
195bool daEnTogezoBase_c::specialFumiProc_Yoshi(
dActor_c *actor) {
199bool daEnTogezoBase_c::checkRyusa() {
202 u32 unitType = dBc_c::getUnitType(center.x, center.y,
mLayer);
203 u32 unitKind = dBc_c::getUnitKind(center.x, center.y,
mLayer);
204 u8 v = unitKind >> 16;
205 if (unitType & 0x8000 && v == 3) {
212void daEnTogezoBase_c::ryusaEffect() {
214 mVec3_c efPos(center.x, center.y, 5500.0f);
215 mLevelEffect.createEffect(
"Wm_en_quicksand", 0, &efPos,
nullptr,
nullptr);
218bool daEnTogezoBase_c::setPlayerDamage(
dActor_c *actor) {
219 dAcPy_c *player = (dAcPy_c *) actor;
220 if (player->setDamage(
this, daPlBase_c::DAMAGE_DEFAULT)) {
221 if (mShellMode != SHELL_MODE_BASE) {
236bool daEnTogezoBase_c::turnProc() {
239 int absTarget = abs(target);
240 int absAngle = abs(
mAngle.y);
241 if (absAngle >= absTarget) {
252 setSlideThrowSpeed(eatingActor);
255 mScale.set(1.0f, 1.0f, 1.0f);
257 mSensorHead = smc_toge_head;
258 mSensorFootNormal = smc_toge_foot;
259 mSensorWall = smc_toge_wall;
266bool daEnTogezoBase_c::createIceActor() {
267 const static float cs_offset_tbl[] = {
271 const static mVec3_c cs_size_tbl[] = {
272 mVec3_c(1.15f, 1.15f, 1.15f),
273 mVec3_c(1.15f, 1.15f, 1.15f),
274 mVec3_c(1.0f, 1.0f, 1.0f)
277 mVec3_c offset(
mPos.x,
mPos.y - cs_offset_tbl[mShellMode],
mPos.z);
279 dIceInfo iceInfo[] = {
283 cs_size_tbl[mShellMode]
286 return mIceMng.createIce(iceInfo, ARRAY_SIZE(iceInfo));
289void daEnTogezoBase_c::pipoRolling() {
290 int rollSpeed = std::fabs(
mSpeed.x * 0.5f) * 0x1000;
291 if (rollSpeed > 0x400) {
299 rollSpeed = prevSpeed;
307void daEnTogezoBase_c::pipoWallBound() {
316 if (isBlockHitDeath()) {
322 hitdamageEffect(efPos);
323 dAudio::g_pSndObjEmy->startSound(SE_EMY_DOWN,
mPos, 0);
333 mSensorHead = smc_toge_head;
334 mSensorWall = smc_toge_wall;
336 mBc.set(
this, smc_sakasa_toge_foot, mSensorHead, mSensorWall);
339bool daEnTogezoBase_c::isBlockHitDeath()
const {
340 return mShellMode == SHELL_MODE_PAIPO && ACTOR_PARAM(DieOnBlockHit) == 1;
343bool daEnTogezoBase_c::isDieShell() {
344 return mShellMode != SHELL_MODE_PAIPO;
347void daEnTogezoBase_c::landonEffect(
float height) {
348 mVec3_c landPos(
mPos.x,
mPos.y + height, 5500.0f);
349 u32 unitType = dBc_c::getUnitType(landPos.x, landPos.y - 8.0f,
mLayer);
350 u32 unitKind = dBc_c::getUnitKind(landPos.x, landPos.y - 8.0f,
mLayer);
351 u32 v = (u8) (unitKind >> 16);
352 u16 footAttr =
mBc.getFootAttr();
353 if (footAttr == 12 || unitType & 0x8000 && v == 3) {
354 mEf::createEffect(
"Wm_en_sndlandsmk_s", 0, &landPos,
nullptr,
nullptr);
356 mEf::createEffect(
"Wm_en_landsmoke_s", 0, &landPos,
nullptr,
nullptr);
360void daEnTogezoBase_c::initializeState_DieFall() {
361 daEnShell_c::initializeState_DieFall();
362 if (mShellMode == SHELL_MODE_PAIPO) {
367void daEnTogezoBase_c::finalizeState_DieFall() {
368 daEnShell_c::finalizeState_DieFall();
371void daEnTogezoBase_c::executeState_DieFall() {
372 const static s16 cs_spin_speed[] = { 0x200, -0x200 };
374 if (mShellMode == SHELL_MODE_PAIPO) {
375 s16 xSpeed = smc_DEADFALL_SPINSPEED;
378 xSpeed *= smc_WATER_ROLL_DEC_RATE;
379 ySpeed *= smc_WATER_ROLL_DEC_RATE;
386 daEnShell_c::executeState_DieFall();
390void daEnTogezoBase_c::initializeState_Pipo() {
392 mShellMode = SHELL_MODE_PAIPO;
394 mCc.mCcData.mBase.mOffset.y = 0.0f;
400void daEnTogezoBase_c::finalizeState_Pipo() {
405void daEnTogezoBase_c::executeState_Pipo() {
411 mBc.checkHead(
mBc.mFlags);
414 if (mSensorHead.mFlags & BIT_FLAG(31)) {
415 if (
mBc.mFlags != 0) {
418 mSensorHead.mFlags &= ~BIT_FLAG(31);
419 mSensorFootNormal.mFlags &= ~BIT_FLAG(31);
420 mSensorWall.mFlags &= ~BIT_FLAG(31);
421 mBc.set(
this, mSensorFootNormal, mSensorHead, mSensorWall);
435 Bound(0.1875f, 0.875f, 0.5f);
438 if (
mBc.getFootAttr() == 3) {
444 dAudio::g_pSndObjEmy->startSound(SE_OBJ_PAIPO_LAND,
mPos, 0);
457void daEnTogezoBase_c::initializeState_Walk() {
468 mShellMode = SHELL_MODE_TOGEZO;
478void daEnTogezoBase_c::finalizeState_Walk() {}
480void daEnTogezoBase_c::executeState_Walk() {
488 u32 prevFoot =
mBc.isFoot();
490 mBc.checkHead(
mBc.mFlags);
506 if (dAudio::isBgmAccentSign(1)) {
511 mFootPush2.x +=
m_1eb.x;
519void daEnTogezoBase_c::initializeState_Turn() {
520 if (*
mStateMgr.getOldStateID() == StateID_Wakeup) {
531void daEnTogezoBase_c::finalizeState_Turn() {}
533void daEnTogezoBase_c::executeState_Turn() {
542 mBc.checkHead(
mBc.mFlags);
545 if (dAudio::isBgmAccentSign(1)) {
556void daEnTogezoBase_c::initializeState_Change_Pipo() {
561void daEnTogezoBase_c::finalizeState_Change_Pipo() {
562 if (mShellMode != SHELL_MODE_PAIPO) {
563 mShellMode = SHELL_MODE_PAIPO;
566 mSensorHead = smc_pipo_head;
567 mSensorFootNormal = smc_pipo_foot;
568 mSensorWall = smc_pipo_wall;
570 mCc.mCcData.mBase.mSize.x = 6.0f;
575void daEnTogezoBase_c::executeState_Change_Pipo() {
580 mBc.checkHead(
mBc.mFlags);
582 Bound(0.1875f, 1.0f, 0.5f);
596void daEnTogezoBase_c::initializeState_Change_Togezo() {
603 mShellMode = SHELL_MODE_TOGEZO;
604 dAudio::g_pSndObjEmy->startSound(SE_OBJ_PAIPO_TO_TOGEZO,
mPos, 0);
606 mSensorHead = smc_toge_head;
607 mSensorFootNormal = smc_toge_foot;
608 mSensorWall = smc_toge_wall;
610 mBc.set(
this, mSensorFootNormal, mSensorHead, mSensorWall);
612 mCc.mCcData.mBase.mOffset.y = 6.0f;
613 mCc.mCcData.mBase.mSize.x = 8.0f;
616void daEnTogezoBase_c::finalizeState_Change_Togezo() {
621void daEnTogezoBase_c::executeState_Change_Togezo() {
625 mBc.checkHead(
mBc.mFlags);
627 Bound(0.1875f, 1.0f, 0.5f);
646void daEnTogezoBase_c::initializeState_Wakeup() {
647 mShellMode = SHELL_MODE_TOGEZO;
648 daEnShell_c::initializeState_Wakeup();
651void daEnTogezoBase_c::finalizeState_Wakeup() {
652 daEnShell_c::finalizeState_Wakeup();
655void daEnTogezoBase_c::executeState_Wakeup() {
657 daEnShell_c::executeState_Wakeup();
660void daEnTogezoBase_c::initializeState_WakeupTurn() {
665 daEnShell_c::initializeState_WakeupTurn();
668void daEnTogezoBase_c::finalizeState_WakeupTurn() {
669 daEnShell_c::finalizeState_WakeupTurn();
672void daEnTogezoBase_c::executeState_WakeupTurn() {
674 daEnShell_c::executeState_WakeupTurn();
677void daEnTogezoBase_c::initializeState_WakeupReverse() {
683 mShellMode = SHELL_MODE_TOGEZO;
684 mSpeed.set(0.0f, 2.5f, 0.0);
687 mSensorFootNormal = smc_toge_foot;
688 mSensorHead = smc_toge_head;
689 mSensorWall = smc_toge_wall;
691 mBc.set(
this, mSensorFootNormal, mSensorHead, mSensorWall);
696void daEnTogezoBase_c::finalizeState_WakeupReverse() {}
698void daEnTogezoBase_c::executeState_WakeupReverse() {
703 mBc.checkHead(
mBc.mFlags);
712 bool limitReached =
false;
733 if (prevAngle < 0 && mAngle.x >= 0) {
740 if (isFoot && limitReached) {
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.
virtual s8 & getPlrNo()
Gets the player number associated with the actor. See mPlayerNo.
bool mNoRespawn
Whether the actor should not respawn after being deleted.
virtual void reviveCc()
Enables the actor's collision.
bool HasamareBgCheck()
Returns whether the actor is colliding with any enabled collision sides.
dBc_c mBc
The actor-to-tile collision sensor.
static bool getTrgToSrcDir_Main(float trgX, float srcX)
See getTrgToSrcDirFunc.
static void setSoftLight_Enemy(m3d::bmdl_c &mdl)
Sets the soft light effect for enemies.
static void changePosAngle(mVec3_c *pos, mAng3_c *ang, int param3)
Adjusts the actor's position to account for looping stages.
u8 mDirection
The actor's facing direction.
dCc_c mCc
The actor-to-actor collision sensor.
mVec2_c mVisibleAreaSize
The size of the area inside which the actor is visible.
s8 mPlayerNo
The player associated with the actor, -1 if not associated to any player.
virtual void calcSpitOutPos(dActor_c *eatingActor)
Calculates the position where the actor will be spat out.
u8 mLayer
The actor's layer.
mVec2_c mVisibleAreaOffset
The offset applied to the area size.
mMtx_c mMatrix
The actor's partial transformation matrix. See makeMtx() 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 mPos
The actor's position.
mVec3_c mSpeedMax
The actor's maximum speed.
void calcSpeedX()
Updates the actor's X speed. See here for details.
mVec3_c mCenterOffs
The offset from the position to the center of the actor (defaults to 0).
void calcFallSpeed()
Updates the actor's falling speed. See here for details.
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.
void calcSpeedY()
Updates the actor's Y speed. See here for details.
bool getPl_LRflag(const mVec3_c &pos)
Checks whether the nearest player is to the left of pos.
u8 mDeathFallDirection
The X direction to move towards on death.
u8 mIceDeathDirection
The X direction to move towards on ice death.
dIceMng_c mIceMng
The ice manager for this enemy.
u16 mTimer1
[Used in EN_HATENA_BALLON, for example]
virtual void changeState(const sStateIDIf_c &newState)
Changes the actor's state to the given state.
virtual void block_hit_init()
Callback for when a block directly beneath the actor is hit.
bool mInLiquid
Whether the enemy is in a liquid.
static dResMng_c * m_instance
The instance of this class.
bool mIsFlipped
Whether the shell is flipped upside down from a block hit.
static sFStateVirtualID_c< daEnShell_c > StateID_Slide
Sliding across the ground after being kicked.
static sFStateVirtualID_c< daEnShell_c > StateID_WakeupReverse
Waking up after being flipped upside down.
static sFStateVirtualID_c< daEnShell_c > StateID_Sleep
Remaining stationary after being jumped on.
void createShell(const char *arcName, const char *resPath, const char *modelName, const char *anmTexName, float animFrame)
Loads the resources for the shell model and animation.
static sFStateVirtualID_c< daEnShell_c > StateID_WakeupTurn
Turning around after waking up.
nw4r::g3d::ResFile mTogezoResFile
The resource file for the spiny.
m3d::anmChr_c mTogezoAnim
The spiny's animation.
u32 mChangeTimer
Timer used for transforming between spiny and rolled up spiny.
u32 mPipoTouchedGround
Whether the rolled up spiny has touched the ground since rolling up.
virtual int doDelete()
do method for the delete operation.
virtual void deleteReady()
Informs the base that it's about to be deleted.
virtual int draw()
do method for the draw operation.
static sFStateID_c< daEnTogezoBase_c > StateID_Walk
Walking on the ground.
virtual int create()
do method for the create operation.
m3d::smdl_c mPaipoMdl
The model for the rolled up spiny.
virtual void block_hit_init()
Callback for when a block directly beneath the actor is hit.
static sFStateID_c< daEnTogezoBase_c > StateID_Change_Togezo
Transforming into a regular spiny.
static sFStateID_c< daEnTogezoBase_c > StateID_Pipo
Rolled up in a ball.
virtual int execute()
do method for the execute operation.
nw4r::g3d::ResFile mPaipoResFile
The resource file for the rolled up spiny.
dHeapAllocator_c mAllocator
The allocator used for the resources of this actor.
virtual bool setEatSpitOut(dActor_c *eatingActor)
Callback for when the actor is about to be spat out.
s16 mPipoRollSpeed
The speed at which the spiny unrolls.
m3d::mdl_c mTogezoModel
The spiny model.
u8 mPipoDir
The direction the rolled up spiny is moving. Used to determine if the spiny should turn around when i...
static sFStateID_c< daEnTogezoBase_c > StateID_Turn
Turning around while walking.
@ SUCCEEDED
The step was completed successfully.
mAng y
The rotation on the Y axis.
mAng z
The rotation on the Z axis.
mAng x
The rotation on the X axis.
A two-dimensional floating point vector.
A three-dimensional floating point vector.
@ FORWARD_LOOP
Play the animation forward in a loop.
@ GAME_HEAP_DEFAULT
The default game heap (alias of MEM1 or MEM2).
EGG::ExpHeap * g_gameHeaps[GAME_HEAP_COUNT]
The game heaps.
#define STATE_DEFINE(class, name)
Defines a state.
#define STATE_VIRTUAL_DEFINE(class, name)
Defines a virtual state.
A structure that contains information about a collider.