NSMBW-Decomp
A decompilation of New Super Mario Bros. Wii
Loading...
Searching...
No Matches
d_enemy_boss.cpp
1#include <game/bases/d_enemy_boss.hpp>
2#include <game/bases/d_a_player_base.hpp>
3#include <game/bases/d_a_player_demo_manager.hpp>
4#include <game/bases/d_actor_manager.hpp>
5#include <game/bases/d_quake.hpp>
6#include <game/sLib/s_GlobalData.hpp>
7
8GLOBAL_DATA_DEF(dEnBoss_c, {
9 false
10});
11
13STATE_VIRTUAL_DEFINE_INH(dEnBoss_c, DieFumi, sStateID_c); // [Why is this not properly inherited?]
19
20dEnBoss_c::dEnBoss_c() : mTenmetsuTime(0), m_d0(0), mQuakeDamage(0), mpBossLife(nullptr) {}
21
22dEnBoss_c::~dEnBoss_c() {}
23
25 allocate();
26 mFlags = EN_FLAG_4;
27 createInit();
28 mActorProperties |= 0x200;
29 changeState(StateID_DemoWait);
30 mStateMgr.refreshState();
31 return SUCCEEDED;
32}
33
34int dEnBoss_c::createInit() {
35 return 1;
36}
37
38void dEnBoss_c::allocate() {
39 mAllocator.createFrmHeapToCurrent(-1, mHeap::g_gameHeaps[mHeap::GAME_HEAP_DEFAULT], nullptr, 0x20, mHeap::OPT_NONE);
40 createModel();
41 createBossLife();
42 mAllocator.adjustFrmHeapRestoreCurrent();
43}
44
45void dEnBoss_c::createBossLife() {
46 if (mpBossLife == nullptr) {
47 mpBossLife = new dBossLife_Common_c(6 * 3);
48 }
49}
50
53 return NOT_READY;
54 }
55
56 if (mTenmetsuTime > 0) {
58 if (mTenmetsuTime > 0) {
60 } else {
62 }
63 }
64
65 if (mQuakeDamage && !(dQuake_c::m_instance->mFlags & dQuake_c::FLAG_1)) {
66 mQuakeDamage = 0;
67 }
68
69 return SUCCEEDED;
70}
71
73 if (state == SUCCESS) {
74 mSndObject.mPos = dAudio::cvtSndObjctPos(mPos);
75 mSndObject.calc();
76 }
77 dEn_c::postExecute(state);
78}
79
80bool dEnBoss_c::isQuakeDamage() {
81 if (mQuakeDamage) {
82 return false;
83 }
84 if (isState(StateID_DemoWait)) {
85 return false;
86 }
87 return mBc.isFoot();
88}
89
90void dEnBoss_c::Normal_VsPlHitCheck(dCc_c *self, dCc_c *other) {
91 if (isFumiInvalid()) {
92 dEn_c::Normal_VsPlHitCheck(self, other);
93 return;
94 }
95
96 daPlBase_c *player = (daPlBase_c *) other->getOwner();
97
98 switch (Enfumi_check(self, other, 2)) {
99 case 1:
100 case 3:
101 if (!isFumiDmgInvalid()) {
102 fumiProc(other->getOwner());
103 }
104 break;
105 case 0:
106 dEn_c::Normal_VsPlHitCheck(self, other);
107 if (player->isStatus(0x3F)) {
108 int plrNo = player->getPlrNo();
109 if (plrNo >= 0 && plrNo < PLAYER_COUNT) {
110 mNoHitPlayer.mTimer[plrNo] = 16;
111 }
112 }
113 break;
114 }
115}
116
117void dEnBoss_c::Normal_VsYoshiHitCheck(dCc_c *self, dCc_c *other) {
118 if (isFumiInvalid()) {
119 dEn_c::Normal_VsYoshiHitCheck(self, other);
120 return;
121 }
122
123 switch (Enfumi_check(self, other, 0)) {
124 case 1:
125 if (!isFumiDmgInvalid()) {
126 fumiProc(other->getOwner());
127 }
128 break;
129 case 0:
130 dEn_c::Normal_VsPlHitCheck(self, other);
131 break;
132 }
133}
134
135void dEnBoss_c::deadAllKill() {
136 dActorMng_c::m_instance->allEnemyDeath(0);
137}
138
139void dEnBoss_c::fumiProc(dActor_c *actor) {
140 if (sGlobalData_c<dEnBoss_c>::mData.mInstantKill) {
141 mpBossLife->mLife = 0;
142 } else {
143 mpBossLife->updateFumi();
144 }
145
147 if (mpBossLife->mLife <= 0) {
148 fumideadEffect();
149 fumideadSE();
150 fumiDeadVo();
151 mpBossLife->mLife = 0;
152 deadAllKill();
153 daPyDemoMng_c::mspInstance->setBossDown((daPlBase_c *) actor);
154 setFumiDead(actor);
155 deadProc();
156 } else {
157 fumidmgEffect();
158 fumidmgSE();
159 setFumiDamage(actor);
160 damageProc();
161 }
162}
163
164bool dEnBoss_c::hitCallback_Fire(dCc_c *self, dCc_c *other) {
165 if (isFireInvalid()) {
166 fireballInvalid(self, other);
167 return true;
168 }
169
170 dActor_c *player = other->getOwner();
171 int prevLives = getLife();
172 int newLives = mpBossLife->updateFire();
173
174 if (sGlobalData_c<dEnBoss_c>::mData.mInstantKill) {
175 mpBossLife->mLife = 0;
176 }
177
178 if (newLives >= prevLives) {
179 fireballInvalid(self, other);
180 } else {
181 if (isDead()) {
182 mpBossLife->mLife = 0;
183 mTenmetsuTime = getTenmetsuTime_Fire();
185 hitFireEffect();
186 firedeadSE();
187 deadAllKill();
188 daPyDemoMng_c::getInstance()->setBossDown((daPlBase_c *) player);
189 setFireDead(player);
190 deadProc();
191 } else {
192 mTenmetsuTime = getTenmetsuTime_Fire();
194 hitFireEffect();
195 firedmgSE();
196 setFireDamage(player);
197 damageProc();
198 }
199 }
200
201 return true;
202}
203
204bool dEnBoss_c::hitCallback_Shell(dCc_c *self, dCc_c *other) {
205 if (isShellInvalid()) {
206 return false;
207 }
208
209 dActor_c *player = other->getOwner();
210 int prevLives = getLife();
211 int newLives = mpBossLife->updateShell();
212
213 if (sGlobalData_c<dEnBoss_c>::mData.mInstantKill) {
214 mpBossLife->mLife = 0;
215 }
216
217 if (newLives >= prevLives) {
218 // Ignore invalid shell hit
219 } else {
220 if (isDead()) {
221 mpBossLife->mLife = 0;
222 mTenmetsuTime = getTenmetsuTime_Shell();
224 hitShellEffect();
225 shelldeadSE();
226 deadAllKill();
227 daPyDemoMng_c::mspInstance->setBossDown((daPlBase_c *) player);
228 setShellDead(player);
229 deadProc();
230 } else {
231 mTenmetsuTime = getTenmetsuTime_Shell();
233 hitShellEffect();
234 shelldmgSE();
235 setShellDamage(player);
236 damageProc();
237 }
238 }
239
240 return true;
241}
242
243bool dEnBoss_c::hitCallback_HipAttk(dCc_c *self, dCc_c *other) {
244 if (isFumiInvalid()) {
245 return false;
246 }
247
248 dActor_c *player = other->getOwner();
249 FumiJumpSet(player);
250 mTenmetsuTime = getTenmetsuTime_Press();
252 mpBossLife->updateHipAtk();
253
254 if (sGlobalData_c<dEnBoss_c>::mData.mInstantKill) {
255 mpBossLife->mLife = 0;
256 }
257
258 if (mpBossLife->mLife <= 0) {
259 fumideadEffect();
260 fumideadSE();
261 fumiDeadVo();
262 mpBossLife->mLife = 0;
263 deadAllKill();
264 daPyDemoMng_c::mspInstance->setBossDown((daPlBase_c *) player);
265 setHipatkDead(player);
266 deadProc();
267 } else {
268 fumidmgEffect();
269 fumidmgSE();
270 setHipatkDamage(player);
271 damageProc();
272 }
273
274 return true;
275}
276
277bool dEnBoss_c::hitCallback_Spin(dCc_c *self, dCc_c *other) {
278 if (isFumiInvalid()) {
279 return false;
280 }
281
282 dActor_c *player = other->getOwner();
283 FumiJumpSet(player);
284 mTenmetsuTime = getTenmetsuTime_Press();
286 mpBossLife->updateFumi();
287
288 if (sGlobalData_c<dEnBoss_c>::mData.mInstantKill) {
289 mpBossLife->mLife = 0;
290 }
291
292 if (mpBossLife->mLife <= 0) {
293 fumideadEffect();
294 fumideadSE();
295 fumiDeadVo();
296 mpBossLife->mLife = 0;
297 deadAllKill();
298 daPyDemoMng_c::getInstance()->setBossDown((daPlBase_c *) player);
299 setHipatkDead(player);
300 deadProc();
301 } else {
302 fumidmgEffect();
303 fumidmgSE();
304 setHipatkDamage(player);
305 damageProc();
306 }
307
308 return true;
309}
310
311bool dEnBoss_c::hitCallback_Star(dCc_c *self, dCc_c *other) {
312 daPlBase_c *player = (daPlBase_c *) other->getOwner();
313
314 if (isStarInvalid()) {
315 player->setForcedDamage(this, daPlBase_c::DAMAGE_HIP_ATTACK);
316 return true;
317 }
318
319 mTenmetsuTime = getTenmetsuTime_Press();
321 mpBossLife->updateStar();
322
323 if (sGlobalData_c<dEnBoss_c>::mData.mInstantKill) {
324 mpBossLife->mLife = 0;
325 }
326
327 if (isDead()) {
328 mpBossLife->mLife = 0;
329 deadAllKill();
330 daPyDemoMng_c::mspInstance->setBossDown(player);
331 stardeadSE();
332 setStarDead(player);
333 deadProc();
334 } else {
335 stardmgSE();
336 setStarDamage(player);
337 damageProc();
338 }
339
340 return true;
341}
342
343void dEnBoss_c::setDeathInfo_Quake(int) {
344 mQuakeDamage = 1;
345 mTenmetsuTime = getTenmetsuTime_Press();
347 mpBossLife->updateQuake();
348
349 if (sGlobalData_c<dEnBoss_c>::mData.mInstantKill) {
350 mpBossLife->mLife = 0;
351 }
352
353 if (isDead()) {
354 mpBossLife->mLife = 0;
355 daPyDemoMng_c::mspInstance->setBossDownPlayerNo(-1);
356 quakedeadSE();
357 deadAllKill();
358 setQuakeDead();
359 deadProc();
360 } else {
361 quakedmgSE();
362 setQuakeDamage();
363 damageProc();
364 }
365}
366
367bool dEnBoss_c::hitCallback_PenguinSlide(dCc_c *self, dCc_c *other) {
368 return false;
369}
370
371void dEnBoss_c::initializeState_DemoWait() {}
372void dEnBoss_c::finalizeState_DemoWait() {}
373void dEnBoss_c::executeState_DemoWait() {}
374
375void dEnBoss_c::initializeState_DieFumi() {}
376void dEnBoss_c::finalizeState_DieFumi() {}
377void dEnBoss_c::executeState_DieFumi() {}
378
379void dEnBoss_c::initializeState_DieFire() { initializeState_DieFumi(); }
380void dEnBoss_c::finalizeState_DieFire() { finalizeState_DieFumi(); }
381void dEnBoss_c::executeState_DieFire() { executeState_DieFumi(); }
382
383void dEnBoss_c::initializeState_DieSlide() { initializeState_DieFumi(); }
384void dEnBoss_c::finalizeState_DieSlide() { finalizeState_DieFumi(); }
385void dEnBoss_c::executeState_DieSlide() { executeState_DieFumi(); }
386
387void dEnBoss_c::initializeState_DieShell() { initializeState_DieFumi(); }
388void dEnBoss_c::finalizeState_DieShell() { finalizeState_DieFumi(); }
389void dEnBoss_c::executeState_DieShell() { executeState_DieFumi(); }
390
391void dEnBoss_c::initializeState_DieStar() { initializeState_DieFumi(); }
392void dEnBoss_c::finalizeState_DieStar() { finalizeState_DieFumi(); }
393void dEnBoss_c::executeState_DieStar() { executeState_DieFumi(); }
394
395void dEnBoss_c::initializeState_DieQuake() { initializeState_DieFumi(); }
396void dEnBoss_c::finalizeState_DieQuake() { finalizeState_DieFumi(); }
397void dEnBoss_c::executeState_DieQuake() { executeState_DieFumi(); }
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.
Definition d_actor.hpp:15
virtual s8 & getPlrNo()
Gets the player number associated with the actor. See mPlayerNo.
Definition d_actor.hpp:105
dBc_c mBc
The actor-to-tile collision sensor.
Definition d_actor.hpp:342
dActor_c()
Constructs a new actor.
Definition d_actor.cpp:46
mVec3_c mPos
The actor's position.
u32 mActorProperties
The actor's properties. See fProf::fActorProfile_c::mActorProperties.
Collider ("Collision Check") class - handles collisions between actors.
Definition d_cc.hpp:133
dActor_c * getOwner() const
Gets the owner actor of this collider.
Definition d_cc.hpp:178
The base class for boss enemies.
int mTenmetsuTime
Timer for the flashing effect when the boss takes damage.
virtual void tenmetsuFin()
Ends the flashing effect after the boss takes damage.
virtual void tenmetsuProc()
Handles the flashing effect after the boss takes damage.
virtual int create()
do method for the create operation.
void getTenmetsuTimePress(bool a)
virtual int preExecute()
pre method for the execute operation.
virtual void postExecute(MAIN_STATE_e state)
post method for the execute operation.
virtual void tenmetsuReady()
Prepares the flashing effect after the boss takes damage.
virtual void changeState(const sStateIDIf_c &newState)
Changes the actor's state to the given state.
virtual int preExecute()
pre method for the execute operation.
Definition d_enemy.cpp:63
dPlayerDownTimer_c mNoHitPlayer
Hit cooldown timers for each player. This is used to prevent, for example, a thrown shell from hittin...
Definition d_enemy.hpp:297
virtual void postExecute(fBase_c::MAIN_STATE_e status)
post method for the execute operation.
Definition d_enemy.cpp:108
u32 mFlags
Flags for this actor. See FLAGS_e.
Definition d_enemy.hpp:290
bool isStatus(int id)
MAIN_STATE_e
The possible operation results.
Definition f_base.hpp:36
@ SUCCESS
The operation was completed successfully.
Definition f_base.hpp:39
@ 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
static const T::GlobalData_t mData
A generic implementation of a state ID.
Definition s_StateID.hpp:7
@ GAME_HEAP_DEFAULT
The default game heap (alias of MEM1 or MEM2).
Definition m_heap.hpp:38
@ OPT_NONE
No special allocation options.
Definition m_heap.hpp:29
EGG::ExpHeap * g_gameHeaps[GAME_HEAP_COUNT]
The game heaps.
Definition m_heap.cpp:13
#define STATE_VIRTUAL_DEFINE_INH(class, name, inherit)
Defines a virtual state.
Definition s_State.hpp:67
#define STATE_VIRTUAL_DEFINE(class, name)
Defines a virtual state.
Definition s_State.hpp:46