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
32void daBullet_c::initialize() {}
33
34void daBullet_c::allocate() {
35 mAllocator.createFrmHeap(-1, mHeap::g_gameHeaps[mHeap::GAME_HEAP_DEFAULT], nullptr, 0x20);
36 createMdl();
37 mAllocator.adjustFrmHeap();
38}
39
40void daBullet_c::createMdl() {}
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
55 case HIT_STAR:
56 mStateMgr.changeState(StateID_HitStar);
57 break;
58
59 case HIT_SHELL:
60 mStateMgr.changeState(StateID_HitShell);
61 break;
62
63 case HIT_YOSHI_BULLET:
64 mStateMgr.changeState(StateID_HitYoshiBullet);
65 break;
66 }
67 }
68
69 return SUCCEEDED;
70}
71
73 mStateMgr.executeState();
74
75 if (!mHasSplashed) {
76 mHasSplashed = splashProc();
77 }
78
79 cullingProc();
80 return SUCCEEDED;
81}
82
83void daBullet_c::cullingProc() {
85}
86
88 return SUCCEEDED;
89}
90
92
94 if (mAllocator.mpHeap != mAllocatorDummyHeap_c::getInstance()) {
95 removeMdl();
96 }
97
98 return SUCCEEDED;
99}
100
101void daBullet_c::removeMdl() {}
102
103void daBullet_c::collisionCallback(dCc_c *self, dCc_c *other) {
104 dActor_c *actor = other->getOwner();
105 daPlBase_c *player = (daPlBase_c *) actor;
106 daBullet_c *bullet = (daBullet_c *) self->getOwner();
108
109 if (kind == STAGE_ACTOR_PLAYER) {
110 if (bullet->checkPlayerDamage(self, other)) {
111 self->mInfo |= CC_NO_HIT;
112 } else if (!player->isNoDamage()) {
113 bullet->setDamage_Player(actor);
114 }
115 } else if (kind == STAGE_ACTOR_YOSHI) {
116 u8 plrNo = actor->getPlrNo();
117 if (plrNo >= PLAYER_COUNT) {
118 return;
119 }
120
121 if (other->mCcData.mAttack == CC_ATTACK_YOSHI_EAT) {
122 return;
123 }
124
125 if (bullet->checkYoshiDamage(self, other)) {
126 self->mInfo |= CC_NO_HIT;
127 } else if (!player->isNoDamage()) {
128 bullet->setDamage_Player(actor);
129 }
130 } else {
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;
135 }
136 }
137}
138
139void daBullet_c::revengeCallback(dCc_c *self, dCc_c *other) {
140 if (!(other->mCcData.mVsDamage & (1 << CC_ATTACK_YOSHI_BULLET))) {
141 return;
142 }
143
144 dActor_c *actor = other->getOwner();
145 daBullet_c* bullet = (daBullet_c *) self->getOwner();
146
147 bool canHit = true;
148
149 if (actor->mKind == STAGE_ACTOR_PLAYER) {
150 if (bullet->getPlrNo() == actor->getPlrNo()) {
151 canHit = false;
152 }
153 } else if (actor->mKind == STAGE_ACTOR_YOSHI) {
154 if (bullet->getPlrNo() == actor->getPlrNo()) {
155 canHit = false;
156 }
157 } else if (actor->mActorProperties & 0x80) {
158 canHit = false;
159 }
160
161 if (canHit) {
162 self->mInfo |= CC_NO_HIT;
163 bullet->hitProc_Reflect(other);
164 bullet->revengeHitSE();
165 }
166}
167
168void daBullet_c::revengeHitSE() {}
169
170bool daBullet_c::checkPlayerDamage(dCc_c *self, dCc_c *other) {
171 if (other->mCcData.mAttack == CC_ATTACK_STAR) {
172 if (hitProc_Star(other)) {
173 return true;
174 }
175 }
176
177 return false;
178}
179
180bool daBullet_c::checkYoshiDamage(dCc_c *self, dCc_c *other) {
181 if (other->mCcData.mAttack == CC_ATTACK_STAR) {
182 if (hitProc_Star(other)) {
183 return true;
184 }
185 }
186
187 return false;
188}
189
190void daBullet_c::setDeadMove(const mVec3_c &speed, short angle) {
191 mSpeed = speed;
192
193 mSpeedMax.set(speed.x, smc_DEAD_FALL_YMAXSPEED, 0.0f);
194
195 mAccelY = smc_DEAD_FALL_GRAVITY;
196
197 if (mDirection == mDeadMoveDirection) {
198 mDeadRollDelta.set(angle, 0, 0);
199 } else {
200 mDeadRollDelta.set(-angle, 0, 0);
201 }
202}
203
204bool daBullet_c::hitProc_Star(dCc_c *other) {
205 dActor_c *owner = other->getOwner();
206
207 if (mPos.x >= owner->mPos.x) {
208 mDeadMoveDirection = DIR_LR_R;
209 } else {
210 mDeadMoveDirection = DIR_LR_L;
211 }
212
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);
215
216 setDeadMove(speed, 0x1000);
217
218 mVec3_c effectPos(mCc.getCollPosX(), mCc.getCollPosY(), 5500.0f);
219 mEf::createEffect("Wm_en_hit", 0, &effectPos, nullptr, nullptr);
220
221 dAudio::g_pSndObjEmy->startSound(SE_EMY_DOWN_NO_SCORE, mPos, 0);
222
223 mHitType = HIT_STAR;
224
225 return true;
226}
227
228bool daBullet_c::hitProc_Shell(dCc_c *other) {
229 dActor_c *owner = other->getOwner();
230
231 if (owner->mSpeed.x >= 0.0f) {
232 mDeadMoveDirection = DIR_LR_R;
233 } else {
234 mDeadMoveDirection = DIR_LR_L;
235 }
236
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);
239
240 setDeadMove(speed, 0x1000);
241
242 mVec3_c effectPos(mCc.getCollPosX(), mCc.getCollPosY(), 5500.0f);
243 mEf::createEffect("Wm_en_hit", 0, &effectPos, nullptr, nullptr);
244
245 dAudio::g_pSndObjEmy->startSound(SE_EMY_DOWN_NO_SCORE, mPos, 0);
246
247 mHitType = HIT_SHELL;
248
249 return true;
250}
251
252bool daBullet_c::hitProc_YoshiBullet(dCc_c *other) {
253 dActor_c *owner = other->getOwner();
254
255 if (owner->mSpeed.x >= 0.0f) {
256 mDeadMoveDirection = DIR_LR_R;
257 } else {
258 mDeadMoveDirection = DIR_LR_L;
259 }
260
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);
263
264 setDeadMove(speed, 0xC00);
265
266 mVec3_c effectPos(mCc.getCollPosX(), mCc.getCollPosY(), 5500.0f);
267 mEf::createEffect("Wm_en_hit", 0, &effectPos, nullptr, nullptr);
268
269 dAudio::g_pSndObjEmy->startSound(SE_EMY_DOWN_NO_SCORE, mPos, 0);
270
271 mHitType = HIT_YOSHI_BULLET;
272
273 return true;
274}
275
276bool daBullet_c::hitProc_Reflect(dCc_c *other) {
277 mDeadMoveDirection = mDirection ^ 1;
278
279 mVec3_c speed(1.75f * smc_DIR_PRM[mDeadMoveDirection], 2.75f, 0.0f);
280
281 setDeadMove(speed, 0x600);
282 mHitType = HIT_REFLECT;
283
284 return true;
285}
286
288 removeCc();
289 mStateMgr.changeState(StateID_EatIn);
290}
291
293 mDirection = eatingActor->mDirection;
294 mPlayerNo = eatingActor->getPlrNo();
295 setSpitOutMove(eatingActor);
296
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;
306
307 reviveCc();
308
309 mPos.z = 5750.0f;
310 mStateMgr.changeState(StateID_SpiteMove);
311
312 return true;
313}
314
315void daBullet_c::setSpitOutMove(dActor_c *eatingActor) {}
316
317bool daBullet_c::splashProc() {
318 bool result = false;
319
320 float height = 0.0f;
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:
324 waterSplashEffect(mVec3_c(mPos.x, height, 6500.0f), 1.0f);
325 result = true;
326 break;
327 default:
328 break;
329 }
330
331 return result;
332}
333
334void daBullet_c::waterSplashEffect(const mVec3_c &pos, float scale) {
335 u32 splashFlags = (mLayer << 16) | 1;
336 mVec3_c splashPos = pos;
337 mVec3_c splashScale(scale, scale, scale);
338
339 dEffActorMng_c::m_instance->createWaterSplashEff(splashPos, splashFlags, -1, splashScale);
340
341 dAudio::g_pSndObjMap->startSound(SE_OBJ_CMN_SPLASH, pos, 0);
342
343 dBg_c::m_bg_p->setWaterInWave(pos.x, pos.y, 6);
344}
345
346void daBullet_c::setDamage_Player(dActor_c *actor) {
347 daPlBase_c *player = (daPlBase_c *) actor;
348 player->setDamage(this, daPlBase_c::DAMAGE_DEFAULT);
349}
350
351void daBullet_c::initializeState_EatIn() {}
352
353void daBullet_c::finalizeState_EatIn() {}
354
355void daBullet_c::executeState_EatIn() {
356 if (mEatState == EAT_STATE_EATEN) {
357 mStateMgr.changeState(StateID_EatNow);
358 }
359}
360
361void daBullet_c::initializeState_EatNow() {}
362
363void daBullet_c::finalizeState_EatNow() {}
364
365void daBullet_c::executeState_EatNow() {}
366
367void daBullet_c::initializeState_SpiteMove() {}
368
369void daBullet_c::finalizeState_SpiteMove() {}
370
371void daBullet_c::executeState_SpiteMove() {
372 calcSpeedX();
373 calcSpeedY();
374 posMove();
375 spitRoll();
376 moveSE();
377}
378
379void daBullet_c::spitRoll() {}
380
381void daBullet_c::moveSE() {}
382
383void daBullet_c::initializeState_Reflect() {}
384
385void daBullet_c::finalizeState_Reflect() {}
386
387void daBullet_c::executeState_Reflect() {
388 calcSpeedY();
389 posMove();
390}
391
392void daBullet_c::initializeState_HitReflect() {}
393
394void daBullet_c::finalizeState_HitReflect() {}
395
396void daBullet_c::executeState_HitReflect() {
397 calcSpeedY();
398 posMove();
399 deadRoll();
400}
401
402void daBullet_c::deadRoll() {
403 mAngle.x += (u16) mDeadRollDelta.x;
404 mAngle.y += (u16) mDeadRollDelta.y;
405 mAngle.z += (u16) mDeadRollDelta.z;
406}
407
408void daBullet_c::initializeState_HitStar() {}
409
410void daBullet_c::finalizeState_HitStar() {}
411
412void daBullet_c::executeState_HitStar() {
413 calcSpeedY();
414 posMove();
415 deadRoll();
416}
417
418void daBullet_c::initializeState_HitShell() {}
419
420void daBullet_c::finalizeState_HitShell() {}
421
422void daBullet_c::executeState_HitShell() {
423 calcSpeedY();
424 posMove();
425 deadRoll();
426}
427
428void daBullet_c::initializeState_HitYoshiBullet() {}
429
430void daBullet_c::finalizeState_HitYoshiBullet() {}
431
432void daBullet_c::executeState_HitYoshiBullet() {
433 calcSpeedY();
434 posMove();
435 deadRoll();
436}
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
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.
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