1#include <game/bases/d_a_bullet.hpp>
2#include <game/mLib/m_allocator_dummy_heap.hpp>
3#include <game/bases/d_a_player_base.hpp>
4#include <game/bases/d_eff_actor_manager.hpp>
5#include <game/bases/d_bg.hpp>
17const float daBullet_c::smc_DEAD_FALL_GRAVITY = -0.1875f;
18const float daBullet_c::smc_DEAD_FALL_YMAXSPEED = -4.5f;
19const float daBullet_c::smc_DIR_PRM[2] = {
32void daBullet_c::initialize() {}
34void daBullet_c::allocate() {
37 mAllocator.adjustFrmHeap();
40void daBullet_c::createMdl() {}
47 if (mHitType != HIT_NONE) {
52 mStateMgr.changeState(StateID_HitReflect);
63 case HIT_YOSHI_BULLET:
64 mStateMgr.changeState(StateID_HitYoshiBullet);
76 mHasSplashed = splashProc();
83void daBullet_c::cullingProc() {
94 if (mAllocator.mpHeap != mAllocatorDummyHeap_c::getInstance()) {
101void daBullet_c::removeMdl() {}
103void daBullet_c::collisionCallback(
dCc_c *self,
dCc_c *other) {
105 daPlBase_c *player = (daPlBase_c *) actor;
106 daBullet_c *bullet = (daBullet_c *) self->
getOwner();
110 if (bullet->checkPlayerDamage(self, other)) {
111 self->
mInfo |= CC_NO_HIT;
112 }
else if (!player->isNoDamage()) {
113 bullet->setDamage_Player(actor);
117 if (plrNo >= PLAYER_COUNT) {
125 if (bullet->checkYoshiDamage(self, other)) {
126 self->
mInfo |= CC_NO_HIT;
127 }
else if (!player->isNoDamage()) {
128 bullet->setDamage_Player(actor);
131 if (other->
mCcData.
mAttack == CC_ATTACK_SHELL && bullet->hitProc_Shell(other)) {
132 self->
mInfo |= CC_NO_HIT;
133 }
else if (other->
mCcData.
mAttack == CC_ATTACK_YOSHI_BULLET && bullet->hitProc_YoshiBullet(other)) {
134 self->
mInfo |= CC_NO_HIT;
139void daBullet_c::revengeCallback(
dCc_c *self,
dCc_c *other) {
140 if (!(other->
mCcData.mVsDamage & (1 << CC_ATTACK_YOSHI_BULLET))) {
145 daBullet_c* bullet = (daBullet_c *) self->
getOwner();
162 self->
mInfo |= CC_NO_HIT;
163 bullet->hitProc_Reflect(other);
164 bullet->revengeHitSE();
168void daBullet_c::revengeHitSE() {}
170bool daBullet_c::checkPlayerDamage(
dCc_c *self,
dCc_c *other) {
172 if (hitProc_Star(other)) {
180bool daBullet_c::checkYoshiDamage(
dCc_c *self,
dCc_c *other) {
182 if (hitProc_Star(other)) {
190void daBullet_c::setDeadMove(
const mVec3_c &speed,
short angle) {
193 mSpeedMax.set(speed.x, smc_DEAD_FALL_YMAXSPEED, 0.0f);
195 mAccelY = smc_DEAD_FALL_GRAVITY;
198 mDeadRollDelta.set(angle, 0, 0);
200 mDeadRollDelta.set(-angle, 0, 0);
204bool daBullet_c::hitProc_Star(
dCc_c *other) {
208 mDeadMoveDirection = DIR_LR_R;
210 mDeadMoveDirection = DIR_LR_L;
213 float mag = 1.75f + 0.35f * std::fabs(owner->
mSpeed.x);
214 mVec3_c speed(mag * smc_DIR_PRM[mDeadMoveDirection], 3.75f, 0.0f);
216 setDeadMove(speed, 0x1000);
218 mVec3_c effectPos(
mCc.getCollPosX(),
mCc.getCollPosY(), 5500.0f);
219 mEf::createEffect(
"Wm_en_hit", 0, &effectPos,
nullptr,
nullptr);
221 dAudio::g_pSndObjEmy->startSound(SE_EMY_DOWN_NO_SCORE,
mPos, 0);
228bool daBullet_c::hitProc_Shell(
dCc_c *other) {
231 if (owner->
mSpeed.x >= 0.0f) {
232 mDeadMoveDirection = DIR_LR_R;
234 mDeadMoveDirection = DIR_LR_L;
237 float mag = 1.75f + 0.35f * std::fabs(owner->
mSpeed.x);
238 mVec3_c speed(mag * smc_DIR_PRM[mDeadMoveDirection], 2.75f, 0.0f);
240 setDeadMove(speed, 0x1000);
242 mVec3_c effectPos(
mCc.getCollPosX(),
mCc.getCollPosY(), 5500.0f);
243 mEf::createEffect(
"Wm_en_hit", 0, &effectPos,
nullptr,
nullptr);
245 dAudio::g_pSndObjEmy->startSound(SE_EMY_DOWN_NO_SCORE,
mPos, 0);
247 mHitType = HIT_SHELL;
252bool daBullet_c::hitProc_YoshiBullet(
dCc_c *other) {
255 if (owner->
mSpeed.x >= 0.0f) {
256 mDeadMoveDirection = DIR_LR_R;
258 mDeadMoveDirection = DIR_LR_L;
261 float mag = 1.75f + 0.35f * std::fabs(owner->
mSpeed.x);
262 mVec3_c speed(mag * smc_DIR_PRM[mDeadMoveDirection], 2.75f, 0.0f);
264 setDeadMove(speed, 0xC00);
266 mVec3_c effectPos(
mCc.getCollPosX(),
mCc.getCollPosY(), 5500.0f);
267 mEf::createEffect(
"Wm_en_hit", 0, &effectPos,
nullptr,
nullptr);
269 dAudio::g_pSndObjEmy->startSound(SE_EMY_DOWN_NO_SCORE,
mPos, 0);
271 mHitType = HIT_YOSHI_BULLET;
276bool daBullet_c::hitProc_Reflect(
dCc_c *other) {
279 mVec3_c speed(1.75f * smc_DIR_PRM[mDeadMoveDirection], 2.75f, 0.0f);
281 setDeadMove(speed, 0x600);
282 mHitType = HIT_REFLECT;
295 setSpitOutMove(eatingActor);
297 mCc.mCcData.mKind = CC_KIND_TAMA;
298 mCc.mCcData.mAttack = CC_ATTACK_YOSHI_BULLET;
299 mCc.mCcData.mVsKind =
300 BIT_FLAG(CC_KIND_PLAYER) |
301 BIT_FLAG(CC_KIND_PLAYER_ATTACK) |
302 BIT_FLAG(CC_KIND_YOSHI) |
303 BIT_FLAG(CC_KIND_ENEMY);
304 mCc.mCcData.mVsDamage = 0;
305 mCc.mCcData.mCallback = revengeCallback;
310 mStateMgr.changeState(StateID_SpiteMove);
315void daBullet_c::setSpitOutMove(
dActor_c *eatingActor) {}
317bool daBullet_c::splashProc() {
321 switch (dBc_c::checkWater(
mPos.x,
mPos.y + 4.0f,
mLayer, &height)) {
322 case dBc_c::WATER_CHECK_WATER:
323 case dBc_c::WATER_CHECK_WATER_BUBBLE:
335 u32 splashFlags = (
mLayer << 16) | 1;
337 mVec3_c splashScale(scale, scale, scale);
339 dEffActorMng_c::m_instance->createWaterSplashEff(splashPos, splashFlags, -1, splashScale);
341 dAudio::g_pSndObjMap->startSound(SE_OBJ_CMN_SPLASH, pos, 0);
343 dBg_c::m_bg_p->setWaterInWave(pos.x, pos.y, 6);
346void daBullet_c::setDamage_Player(
dActor_c *actor) {
348 player->setDamage(
this, daPlBase_c::DAMAGE_DEFAULT);
351void daBullet_c::initializeState_EatIn() {}
353void daBullet_c::finalizeState_EatIn() {}
355void daBullet_c::executeState_EatIn() {
361void daBullet_c::initializeState_EatNow() {}
363void daBullet_c::finalizeState_EatNow() {}
365void daBullet_c::executeState_EatNow() {}
367void daBullet_c::initializeState_SpiteMove() {}
369void daBullet_c::finalizeState_SpiteMove() {}
371void daBullet_c::executeState_SpiteMove() {
379void daBullet_c::spitRoll() {}
381void daBullet_c::moveSE() {}
383void daBullet_c::initializeState_Reflect() {}
385void daBullet_c::finalizeState_Reflect() {}
387void daBullet_c::executeState_Reflect() {
392void daBullet_c::initializeState_HitReflect() {}
394void daBullet_c::finalizeState_HitReflect() {}
396void daBullet_c::executeState_HitReflect() {
402void daBullet_c::deadRoll() {
403 mAngle.x += (u16) mDeadRollDelta.x;
404 mAngle.y += (u16) mDeadRollDelta.y;
405 mAngle.z += (u16) mDeadRollDelta.z;
408void daBullet_c::initializeState_HitStar() {}
410void daBullet_c::finalizeState_HitStar() {}
412void daBullet_c::executeState_HitStar() {
418void daBullet_c::initializeState_HitShell() {}
420void daBullet_c::finalizeState_HitShell() {}
422void daBullet_c::executeState_HitShell() {
428void daBullet_c::initializeState_HitYoshiBullet() {}
430void daBullet_c::finalizeState_HitYoshiBullet() {}
432void daBullet_c::executeState_HitYoshiBullet() {
sFStateMgr_c< dActorState_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.
virtual void reviveCc()
Enables the actor's collision.
@ SKIP_NONE
No checks are skipped.
u8 mKind
The actor's kind. Value is a STAGE_ACTOR_KIND_e.
u8 mEatState
The actor's eat state. Value is a EAT_STATE_e.
u8 mDirection
The actor's facing direction.
dCc_c mCc
The actor-to-actor collision sensor.
virtual void removeCc()
Disables the actor's collision.
virtual int preExecute()
pre method for the execute operation.
s8 mPlayerNo
The player associated with the actor, -1 if not associated to any player.
bool ActorScrOutCheck(u16 flags)
Checks if the actor is out of gameplay and optionally deletes it.
@ EAT_STATE_EATEN
The actor has been successfully eaten.
dActor_c()
Constructs a new actor.
STAGE_ACTOR_KIND_e
The possible stage actor kinds.
@ STAGE_ACTOR_YOSHI
The Yoshi actor.
@ STAGE_ACTOR_PLAYER
The player actor.
u8 mLayer
The actor's layer.
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.
void posMove()
Moves the actor by its speed.
mAng3_c mAngle
The actor's rotation (for 2D actors).
u32 mActorProperties
The actor's properties. See fProf::fActorProfile_c::mActorProperties.
float mAccelY
The actor's vertical acceleration.
void calcSpeedY()
Updates the actor's Y speed. See here for details.
Collider ("Collision Check") class - handles collisions between actors.
u8 mInfo
Info flags for this collider. See CC_INFO_e.
dActor_c * getOwner() const
Gets the owner actor of this collider.
sCcDatNewF mCcData
The collision data of this collider.
virtual void waterSplashEffect(const mVec3_c &pos, float size)
Generates a water splash effect.
virtual int doDelete()
do method for the delete operation.
virtual int preExecute()
pre method for the execute operation.
virtual void setEatTongue(dActor_c *eatingActor)
Callback for when the actor is targeted by Yoshi's tongue.
virtual int create()
do method for the create operation.
virtual bool setEatSpitOut(dActor_c *eatingActor)
Callback for when the actor is about to be spat out.
virtual int execute()
do method for the execute operation.
virtual int draw()
do method for the draw operation.
virtual void deleteReady()
Informs the base that it's about to be deleted.
The base class for the player and Yoshi.
@ NOT_READY
The step could not completed at this time.
@ SUCCEEDED
The step was completed successfully.
A three-dimensional floating point vector.
@ GAME_HEAP_DEFAULT
The default game heap (alias of MEM1 or MEM2).
EGG::ExpHeap * g_gameHeaps[GAME_HEAP_COUNT]
The game heaps.
#define STATE_VIRTUAL_DEFINE(class, name)
Defines a virtual state.
u8 mAttack
The attack type of this collider. See CC_ATTACK_e.