NSMBW-Decomp
A decompilation of New Super Mario Bros. Wii
Loading...
Searching...
No Matches
d_a_bullet.cpp
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>
7
15STATE_VIRTUAL_DEFINE(daBullet_c, HitYoshiBullet);
16
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] = {
20 1.0f,
21 -1.0f
22};
23
25 allocate();
26 mActorProperties |= 0xA0;
27 initialize();
28
29 return SUCCEEDED;
30}
31
33
35 mAllocator.createFrmHeap(-1, mHeap::g_gameHeaps[mHeap::GAME_HEAP_DEFAULT], nullptr, 0x20);
36 createMdl();
37 mAllocator.adjustFrmHeap();
38}
39
41
44 return NOT_READY;
45 }
46
47 if (mHitType != HIT_NONE) {
48 removeCc();
49
50 switch (mHitType) {
51 case HIT_REFLECT:
52 mStateMgr.changeState(StateID_HitReflect);
53 break;
54 case HIT_STAR:
55 mStateMgr.changeState(StateID_HitStar);
56 break;
57 case HIT_SHELL:
58 mStateMgr.changeState(StateID_HitShell);
59 break;
60 case HIT_YOSHI_BULLET:
61 mStateMgr.changeState(StateID_HitYoshiBullet);
62 break;
63 default:
64 break;
65 }
66 }
67
68 return SUCCEEDED;
69}
70
72 mStateMgr.executeState();
73
74 if (!mHasSplashed) {
76 }
77
79 return SUCCEEDED;
80}
81
85
87 return SUCCEEDED;
88}
89
91
93 if (mAllocator.mpHeap != mAllocatorDummyHeap_c::getInstance()) {
94 removeMdl();
95 }
96
97 return SUCCEEDED;
98}
99
101
103 dActor_c *actor = other->getOwner();
104 daPlBase_c *player = (daPlBase_c *) actor;
105 daBullet_c *bullet = (daBullet_c *) self->getOwner();
107
108 if (kind == STAGE_ACTOR_PLAYER) {
109 if (bullet->checkPlayerDamage(self, other)) {
110 self->mInfo |= CC_NO_HIT;
111 } else if (!player->isNoDamage()) {
112 bullet->setDamage_Player(actor);
113 }
114 } else if (kind == STAGE_ACTOR_YOSHI) {
115 u8 plrNo = actor->getPlrNo();
116 if (plrNo >= PLAYER_COUNT) {
117 return;
118 }
119
120 if (other->mCcData.mAttack == CC_ATTACK_YOSHI_EAT) {
121 return;
122 }
123
124 if (bullet->checkYoshiDamage(self, other)) {
125 self->mInfo |= CC_NO_HIT;
126 } else if (!player->isNoDamage()) {
127 bullet->setDamage_Player(actor);
128 }
129 } else {
130 if (other->mCcData.mAttack == CC_ATTACK_SHELL && bullet->hitProc_Shell(other)) {
131 self->mInfo |= CC_NO_HIT;
132 } else if (other->mCcData.mAttack == CC_ATTACK_YOSHI_BULLET && bullet->hitProc_YoshiBullet(other)) {
133 self->mInfo |= CC_NO_HIT;
134 }
135 }
136}
137
139 if (!(other->mCcData.mVsDamage & (1 << CC_ATTACK_YOSHI_BULLET))) {
140 return;
141 }
142
143 dActor_c *actor = other->getOwner();
144 daBullet_c* bullet = (daBullet_c *) self->getOwner();
145
146 bool canHit = true;
147
148 if (actor->mKind == STAGE_ACTOR_PLAYER) {
149 if (bullet->getPlrNo() == actor->getPlrNo()) {
150 canHit = false;
151 }
152 } else if (actor->mKind == STAGE_ACTOR_YOSHI) {
153 if (bullet->getPlrNo() == actor->getPlrNo()) {
154 canHit = false;
155 }
156 } else if (actor->mActorProperties & 0x80) {
157 canHit = false;
158 }
159
160 if (canHit) {
161 self->mInfo |= CC_NO_HIT;
162 bullet->hitProc_Reflect(other);
163 bullet->revengeHitSE();
164 }
165}
166
167void daBullet_c::revengeHitSE() {}
168
170 if (other->mCcData.mAttack == CC_ATTACK_STAR) {
171 if (hitProc_Star(other)) {
172 return true;
173 }
174 }
175
176 return false;
177}
178
180 if (other->mCcData.mAttack == CC_ATTACK_STAR) {
181 if (hitProc_Star(other)) {
182 return true;
183 }
184 }
185
186 return false;
187}
188
189void daBullet_c::setDeadMove(const mVec3_c &speed, short angle) {
190 mSpeed = speed;
191
192 mSpeedMax.set(speed.x, smc_DEAD_FALL_YMAXSPEED, 0.0f);
193
195
197 mHitRollDelta.set(angle, 0, 0);
198 } else {
199 mHitRollDelta.set(-angle, 0, 0);
200 }
201}
202
204 dActor_c *owner = other->getOwner();
205
206 if (mPos.x >= owner->mPos.x) {
207 mHitMoveDirection = DIR_LR_R;
208 } else {
209 mHitMoveDirection = DIR_LR_L;
210 }
211
212 float mag = 1.75f + 0.35f * std::fabs(owner->mSpeed.x);
213 mVec3_c speed(mag * smc_DIR_PRM[mHitMoveDirection], 3.75f, 0.0f);
214
215 setDeadMove(speed, 0x1000);
216
217 mVec3_c effectPos(mCc.getCollPosX(), mCc.getCollPosY(), 5500.0f);
218 mEf::createEffect("Wm_en_hit", 0, &effectPos, nullptr, nullptr);
219
220 dAudio::g_pSndObjEmy->startSound(SE_EMY_DOWN_NO_SCORE, mPos, 0);
221
222 mHitType = HIT_STAR;
223
224 return true;
225}
226
228 dActor_c *owner = other->getOwner();
229
230 if (owner->mSpeed.x >= 0.0f) {
231 mHitMoveDirection = DIR_LR_R;
232 } else {
233 mHitMoveDirection = DIR_LR_L;
234 }
235
236 float mag = 1.75f + 0.35f * std::fabs(owner->mSpeed.x);
237 mVec3_c speed(mag * smc_DIR_PRM[mHitMoveDirection], 2.75f, 0.0f);
238
239 setDeadMove(speed, 0x1000);
240
241 mVec3_c effectPos(mCc.getCollPosX(), mCc.getCollPosY(), 5500.0f);
242 mEf::createEffect("Wm_en_hit", 0, &effectPos, nullptr, nullptr);
243
244 dAudio::g_pSndObjEmy->startSound(SE_EMY_DOWN_NO_SCORE, mPos, 0);
245
246 mHitType = HIT_SHELL;
247
248 return true;
249}
250
251bool daBullet_c::hitProc_YoshiBullet(dCc_c *other) {
252 dActor_c *owner = other->getOwner();
253
254 if (owner->mSpeed.x >= 0.0f) {
255 mHitMoveDirection = DIR_LR_R;
256 } else {
257 mHitMoveDirection = DIR_LR_L;
258 }
259
260 float mag = 1.75f + 0.35f * std::fabs(owner->mSpeed.x);
261 mVec3_c speed(mag * smc_DIR_PRM[mHitMoveDirection], 2.75f, 0.0f);
262
263 setDeadMove(speed, 0xC00);
264
265 mVec3_c effectPos(mCc.getCollPosX(), mCc.getCollPosY(), 5500.0f);
266 mEf::createEffect("Wm_en_hit", 0, &effectPos, nullptr, nullptr);
267
268 dAudio::g_pSndObjEmy->startSound(SE_EMY_DOWN_NO_SCORE, mPos, 0);
269
270 mHitType = HIT_YOSHI_BULLET;
271
272 return true;
273}
274
275bool daBullet_c::hitProc_Reflect(dCc_c *other) {
277
278 mVec3_c speed(1.75f * smc_DIR_PRM[mHitMoveDirection], 2.75f, 0.0f);
279
280 setDeadMove(speed, 0x600);
281 mHitType = HIT_REFLECT;
282
283 return true;
284}
285
287 removeCc();
288 mStateMgr.changeState(StateID_EatIn);
289}
290
292 mDirection = eatingActor->mDirection;
293 mPlayerNo = eatingActor->getPlrNo();
294 setSpitOutMove(eatingActor);
295
296 mCc.mCcData.mKind = CC_KIND_TAMA;
297 mCc.mCcData.mAttack = CC_ATTACK_YOSHI_BULLET;
298 mCc.mCcData.mVsKind =
299 BIT_FLAG(CC_KIND_PLAYER) |
300 BIT_FLAG(CC_KIND_PLAYER_ATTACK) |
301 BIT_FLAG(CC_KIND_YOSHI) |
302 BIT_FLAG(CC_KIND_ENEMY);
303 mCc.mCcData.mVsDamage = 0;
304 mCc.mCcData.mCallback = revengeCallback;
305
306 reviveCc();
307
308 mPos.z = 5750.0f;
309 mStateMgr.changeState(StateID_SpiteMove);
310
311 return true;
312}
313
315
317 bool result = false;
318
319 float height = 0.0f;
320 switch (dBc_c::checkWater(mPos.x, mPos.y + 4.0f, mLayer, &height)) {
321 case dBc_c::WATER_CHECK_WATER:
322 case dBc_c::WATER_CHECK_WATER_BUBBLE:
323 waterSplashEffect(mVec3_c(mPos.x, height, 6500.0f), 1.0f);
324 result = true;
325 break;
326 default:
327 break;
328 }
329
330 return result;
331}
332
333void daBullet_c::waterSplashEffect(const mVec3_c &pos, float scale) {
334 u32 splashFlags = (mLayer << 16) | 1;
335 mVec3_c splashPos = pos;
336 mVec3_c splashScale(scale, scale, scale);
337
338 dEffActorMng_c::m_instance->createWaterSplashEff(splashPos, splashFlags, -1, splashScale);
339
340 dAudio::g_pSndObjMap->startSound(SE_OBJ_CMN_SPLASH, pos, 0);
341
342 dBg_c::m_bg_p->setWaterInWave(pos.x, pos.y, 6);
343}
344
346 daPlBase_c *player = (daPlBase_c *) actor;
347 player->setDamage(this, daPlBase_c::DAMAGE_DEFAULT);
348}
349
350void daBullet_c::initializeState_EatIn() {}
351
352void daBullet_c::finalizeState_EatIn() {}
353
354void daBullet_c::executeState_EatIn() {
355 if (mEatState == EAT_STATE_EATEN) {
356 mStateMgr.changeState(StateID_EatNow);
357 }
358}
359
360void daBullet_c::initializeState_EatNow() {}
361
362void daBullet_c::finalizeState_EatNow() {}
363
364void daBullet_c::executeState_EatNow() {}
365
366void daBullet_c::initializeState_SpiteMove() {}
367
368void daBullet_c::finalizeState_SpiteMove() {}
369
370void daBullet_c::executeState_SpiteMove() {
371 calcSpeedX();
372 calcSpeedY();
373 posMove();
374 spitRoll();
375 moveSE();
376}
377
378void daBullet_c::spitRoll() {}
379
380void daBullet_c::moveSE() {}
381
382void daBullet_c::initializeState_Reflect() {}
383
384void daBullet_c::finalizeState_Reflect() {}
385
386void daBullet_c::executeState_Reflect() {
387 calcSpeedY();
388 posMove();
389}
390
391void daBullet_c::initializeState_HitReflect() {}
392
393void daBullet_c::finalizeState_HitReflect() {}
394
395void daBullet_c::executeState_HitReflect() {
396 calcSpeedY();
397 posMove();
398 deadRoll();
399}
400
401void daBullet_c::deadRoll() {
402 mAngle.x += (u16) mHitRollDelta.x;
403 mAngle.y += (u16) mHitRollDelta.y;
404 mAngle.z += (u16) mHitRollDelta.z;
405}
406
407void daBullet_c::initializeState_HitStar() {}
408
409void daBullet_c::finalizeState_HitStar() {}
410
411void daBullet_c::executeState_HitStar() {
412 calcSpeedY();
413 posMove();
414 deadRoll();
415}
416
417void daBullet_c::initializeState_HitShell() {}
418
419void daBullet_c::finalizeState_HitShell() {}
420
421void daBullet_c::executeState_HitShell() {
422 calcSpeedY();
423 posMove();
424 deadRoll();
425}
426
427void daBullet_c::initializeState_HitYoshiBullet() {}
428
429void daBullet_c::finalizeState_HitYoshiBullet() {}
430
431void daBullet_c::executeState_HitYoshiBullet() {
432 calcSpeedY();
433 posMove();
434 deadRoll();
435}
sFStateMgr_c< dActorState_c, sStateMethodUsr_FI_c > mStateMgr
The state manager.
The minimum required implementation for a stage actor.
Definition d_actor.hpp:15
virtual s8 & getPlrNo()
Gets the player number associated with the actor. See mPlayerNo.
Definition d_actor.hpp:105
virtual void reviveCc()
Enables the actor's collision.
Definition d_actor.cpp:804
@ SKIP_NONE
No checks are skipped.
Definition d_actor.hpp:75
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
virtual void removeCc()
Disables the actor's collision.
Definition d_actor.cpp:800
virtual int preExecute()
pre method for the execute operation.
Definition d_actor.cpp:104
s8 mPlayerNo
The player associated with the actor, -1 if not associated to any player.
Definition d_actor.hpp:375
bool ActorScrOutCheck(u16 flags)
Checks if the actor is out of gameplay and optionally deletes it.
Definition d_actor.cpp:413
@ EAT_STATE_EATEN
The actor has been successfully eaten.
Definition d_actor.hpp:29
dActor_c()
Constructs a new actor.
Definition d_actor.cpp:46
STAGE_ACTOR_KIND_e
The possible stage actor kinds.
Definition d_actor.hpp:45
@ 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
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.
Definition d_cc.hpp:133
u8 mInfo
Info flags for this collider. See CC_INFO_e.
Definition d_cc.hpp:337
dActor_c * getOwner() const
Gets the owner actor of this collider.
Definition d_cc.hpp:178
sCcDatNewF mCcData
The collision data of this collider.
Definition d_cc.hpp:288
The base class for various projectile actors.
Definition d_a_bullet.hpp:9
dHeapAllocator_c mAllocator
The allocator.
virtual void setSpitOutMove(dActor_c *eatingActor)
Handles the bullet being spat out by Yoshi.
virtual void cullingProc()
Culls the bullet if needed.
static void revengeCallback(dCc_c *self, dCc_c *other)
Collision callback for when the bullet was spat back out by Yoshi.
virtual void createMdl()
Creates the model for the bullet.
BOOL mHasSplashed
Whether the bullet has splashed in water yet.
void allocate()
Creates the allocator and load the model.
bool splashProc()
Checks if the bullet has hit water and creates a splash effect if so.
void setDamage_Player(dActor_c *actor)
Triggers damage to a player that touched the bullet.
virtual void waterSplashEffect(const mVec3_c &pos, float size)
Generates a water splash effect.
virtual bool hitProc_Star(dCc_c *other)
Handles the bullet being hit by a player or Yoshi with a star.
virtual int doDelete()
do method for the delete operation.
static const float smc_DEAD_FALL_YMAXSPEED
The maximum falling speed of a bullet.
virtual int preExecute()
pre method for the execute operation.
static const float smc_DIR_PRM[]
The unit direction values for left and right movement of the bullet.
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.
daBullet_c()
Constructs a new actor.
int mHitMoveDirection
The direction to travel after the bullet has been hit.
virtual bool setEatSpitOut(dActor_c *eatingActor)
Callback for when the actor is about to be spat out.
virtual bool hitProc_Shell(dCc_c *other)
Handles the bullet being hit by a shell.
virtual void removeMdl()
Removes the model for the bullet.
static void collisionCallback(dCc_c *self, dCc_c *other)
Regular collision callback for the bullet.
virtual void setDeadMove(const mVec3_c &speed, short angle)
Sets the movement parameters for the bullet after it has been hit.
virtual int execute()
do method for the execute operation.
virtual int draw()
do method for the draw operation.
mAng3_c mHitRollDelta
The rotation delta to apply to the bullet each frame after it has been hit.
bool checkPlayerDamage(dCc_c *self, dCc_c *other)
Returns whether a player with a star is touching the bullet.
bool checkYoshiDamage(dCc_c *self, dCc_c *other)
Returns whether a Yoshi with a star is touching the bullet.
static const float smc_DEAD_FALL_GRAVITY
The gravity to apply to a falling bullet.
virtual void initialize()
Subclass-specific initialization logic for the bullet.
HitType_e mHitType
The type of hit that the bullet has received.
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.
Definition f_base.hpp:45
@ SUCCEEDED
The step was completed successfully.
Definition f_base.hpp:46
A three-dimensional floating point vector.
Definition m_vec.hpp:122
@ GAME_HEAP_DEFAULT
The default game heap (alias of MEM1 or MEM2).
Definition m_heap.hpp:38
EGG::ExpHeap * g_gameHeaps[GAME_HEAP_COUNT]
The game heaps.
Definition m_heap.cpp:13
#define STATE_VIRTUAL_DEFINE(class, name)
Defines a virtual state.
Definition s_State.hpp:46
u8 mAttack
The attack type of this collider. See CC_ATTACK_e.
Definition d_cc.hpp:102