summaryrefslogtreecommitdiff
path: root/src/bossCaptainBowser.cpp
diff options
context:
space:
mode:
authorTreeki <treeki@gmail.com>2013-02-22 00:26:14 +0100
committerTreeki <treeki@gmail.com>2013-02-22 00:26:14 +0100
commit457a40644f0a492ed8acf8dbf66888bee9035100 (patch)
tree759ceec3d2d7a8ecaad6d60ed682284441678db7 /src/bossCaptainBowser.cpp
parent1aa3c19834f16d5153fba34c7ef9dc5a66be9466 (diff)
downloadkamek-457a40644f0a492ed8acf8dbf66888bee9035100.tar.gz
kamek-457a40644f0a492ed8acf8dbf66888bee9035100.zip
more updates and fixes to the final boss than I can count
Diffstat (limited to '')
-rw-r--r--src/bossCaptainBowser.cpp554
1 files changed, 376 insertions, 178 deletions
diff --git a/src/bossCaptainBowser.cpp b/src/bossCaptainBowser.cpp
index cb076c6..5eb8ac7 100644
--- a/src/bossCaptainBowser.cpp
+++ b/src/bossCaptainBowser.cpp
@@ -45,6 +45,7 @@ public:
int onDelete();
int onExecute();
int onDraw();
+ int afterExecute(int param);
mHeapAllocator_c allocator;
nw4r::g3d::ResFile resFile;
@@ -56,9 +57,10 @@ public:
m3d::anmChr_c chrAnimation;
m3d::anmChr_c shipAnm;
- static const int SHIP_COLL_COUNT = 7;
- ActivePhysics shipCollisions[SHIP_COLL_COUNT];
- ActivePhysics Roar;
+ nw4r::snd::SoundHandle prplSound;
+
+ static const int SHIP_SCOLL_COUNT = 7;
+ Physics shipSColls[SHIP_SCOLL_COUNT];
mEf::es2 effect;
mEf::es2 shipDmgA;
@@ -67,23 +69,49 @@ public:
mEf::es2 shipDmgD;
mEf::es2 shipDmgE;
+ mEf::es2 flamethrowerEffect;
+ mEf::es2 flamethrowerEffectInd;
+
+ nw4r::g3d::ResFile flamethrowerRF;
+ m3d::mdl_c flamethrowerModel;
+ m3d::anmTexSrt_c flamethrowerAnim;
+ bool renderFlamethrowerModel;
+ ActivePhysics flameCollision;
+
+#define flameOffsetX -160.0f
+#define flameOffsetY 150.0f
+#define flameZ 1900.0f
+ Vec flameScale;
+
char isAngry;
char isInvulnerable;
char isIntro;
- float scaleIncreaser;
- int homingBillCountdown;
- int homingBillSlot;
int maxDamage;
int playerCount;
- float sinTimer;
float roarLen;
+ float bowserX, bowserY;
+ s16 bowserRotX, bowserRotY;
+ float bowserXSpeed, bowserYSpeed, bowserMaxYSpeed, bowserYAccel;
+
+ s16 shipRotY;
+ float sinTimerX;
+ float sinTimerY;
+ bool sinTimerXRunning, sinTimerYRunning, stopMoving;
+
+ bool wereEntirelyDone;
+ float explosionBottomBound;
+
+ bool deathSequenceRunning;
+ void initiateDeathSequence();
+
static daCaptainBowser *build();
void bindAnimChr_and_setUpdateRate(const char* name, int unk, float unk2, float rate);
void spriteCollision(ActivePhysics *apThis, ActivePhysics *apOther);
void playerCollision(ActivePhysics *apThis, ActivePhysics *apOther);
+ bool collisionCat13_Hammer(ActivePhysics *apThis, ActivePhysics *apOther);
void addScoreWhenHit(void *other);
@@ -96,6 +124,7 @@ public:
DECLARE_STATE(Damage);
DECLARE_STATE(Intro);
+ DECLARE_STATE(FinalAttack);
DECLARE_STATE(Outro);
};
@@ -118,6 +147,7 @@ daCaptainBowser *daCaptainBowser::build() {
CREATE_STATE(daCaptainBowser, Damage);
CREATE_STATE(daCaptainBowser, Intro);
+ CREATE_STATE(daCaptainBowser, FinalAttack);
CREATE_STATE(daCaptainBowser, Outro);
@@ -125,50 +155,37 @@ daCaptainBowser *daCaptainBowser::build() {
////////////////////////
// Collision Functions
////////////////////////
- void daCaptainBowser::addScoreWhenHit(void *other) { };
+void daCaptainBowser::addScoreWhenHit(void *other) { };
- void daCaptainBowser::spriteCollision(ActivePhysics *apThis, ActivePhysics *apOther) {
- if (apOther->owner->name == 657) { //time to get hurt
- if (this->isInvulnerable) {
- return;
- }
- this->damage -= 1;
-
- spawnHitEffectAtPosition((Vec2){apOther->owner->pos.x, apOther->owner->pos.y});
-
- SpawnEffect("Wm_en_burst_m", 0, &apOther->owner->pos, &(S16Vec){0,0,0}, &(Vec){1.0, 1.0, 1.0});
- PlaySound(apOther->owner, SE_BOSS_CMN_STOMPED);
- apOther->owner->Delete(1);
+bool daCaptainBowser::collisionCat13_Hammer(ActivePhysics *apThis, ActivePhysics *apOther) {
+ apOther->owner->kill();
+ SpawnEffect("Wm_en_burst_m", 0, &apOther->owner->pos, &(S16Vec){0,0,0}, &(Vec){1.0, 1.0, 1.0});
+ apThis->someFlagByte |= 2;
+ return true;
+}
- if (this->damage == this->maxDamage/2) { doStateChange(&StateID_Roar); }
- else if (this->damage < 0) { doStateChange(&StateID_Outro); }
- else { doStateChange(&StateID_Damage); }
+void daCaptainBowser::spriteCollision(ActivePhysics *apThis, ActivePhysics *apOther) {
+ if (apOther->owner->name == WM_PAKKUN) { //time to get hurt
+ if (this->isInvulnerable) {
+ return;
}
- }
+ this->damage -= 1;
- void ShipAPhysicsCallback(ActivePhysics *apThis, ActivePhysics *apOther) {
- daCaptainBowser *self = (daCaptainBowser*)apThis->owner;
- if (apOther->owner->name == 657) {
- OSReport("CANNON COLLISION");
- if (self->isInvulnerable) {
- return;
- }
- self->damage -= 1;
+ spawnHitEffectAtPosition((Vec2){apOther->owner->pos.x, apOther->owner->pos.y});
- SpawnEffect("Wm_en_burst_m", 0, &apOther->owner->pos, &(S16Vec){0,0,0}, &(Vec){1.0, 1.0, 1.0});
- PlaySound(apOther->owner, SE_OBJ_TARU_BREAK);
- apOther->owner->Delete(1);
+ SpawnEffect("Wm_en_burst_m", 0, &apOther->owner->pos, &(S16Vec){0,0,0}, &(Vec){1.0, 1.0, 1.0});
+ PlaySound(apOther->owner, SE_BOSS_CMN_STOMPED);
+ apOther->owner->Delete(1);
- if (self->damage == self->maxDamage/2) { self->doStateChange(&daCaptainBowser::StateID_Roar); }
- else if (self->damage < 0) { self->doStateChange(&daCaptainBowser::StateID_Outro); }
-
- apThis->someFlagByte |= 2;
- }
+ if (this->damage == this->maxDamage/2) { doStateChange(&StateID_Roar); }
+ else if (this->damage < 0) { initiateDeathSequence(); }
+ else { doStateChange(&StateID_Damage); }
}
+}
- void daCaptainBowser::playerCollision(ActivePhysics *apThis, ActivePhysics *apOther) {
- DamagePlayer(this, apThis, apOther);
- }
+void daCaptainBowser::playerCollision(ActivePhysics *apThis, ActivePhysics *apOther) {
+ DamagePlayer(this, apThis, apOther);
+}
@@ -180,6 +197,13 @@ void daCaptainBowser::bindAnimChr_and_setUpdateRate(const char* name, int unk, f
}
int daCaptainBowser::onCreate() {
+ bowserX = -148.0f;
+ bowserY = 122.0f;
+ bowserRotY = 0xD800;
+
+ shipRotY = 0x4000;
+ sinTimerXRunning = true;
+ sinTimerYRunning = true;
// Model creation
allocator.link(-1, GameHeaps[0], 0, 0x20);
@@ -206,6 +230,20 @@ int daCaptainBowser::onCreate() {
this->shipModel.bindAnim(&this->shipAnm, 0.0);
this->shipAnm.setUpdateRate(1.0);
+ // Flamethrower
+ flamethrowerRF.data = getResource("fire_cannon", "g3d/flame_koopa.brres");
+
+ nw4r::g3d::ResMdl ftResMdl = flamethrowerRF.GetResMdl("fire_effect1x6_right");
+ nw4r::g3d::ResAnmTexSrt ftResAnm = flamethrowerRF.GetResAnmTexSrt("fire_effect1x6_right");
+
+ flamethrowerModel.setup(ftResMdl, &allocator, 0x224, 1, 0);
+ SetupTextures_MapObj(&flamethrowerModel, 0);
+
+ flamethrowerAnim.setup(ftResMdl, ftResAnm, &allocator, 0, 1);
+ flamethrowerAnim.bindEntry(&flamethrowerModel, ftResAnm, 0, 0);
+ flamethrowerModel.bindAnim(&flamethrowerAnim, 0.0f);
+ flamethrowerAnim.setFrameForEntry(0.0f, 0);
+ flamethrowerAnim.setUpdateRate(1.0f);
allocator.unlink();
@@ -215,47 +253,20 @@ int daCaptainBowser::onCreate() {
pos.z = 8000.0;
this->scale = (Vec){0.57, 0.57, 0.57};
- this->homingBillCountdown = 270;
- this->homingBillSlot = 0;
this->damage = this->maxDamage;
-
- for (int i = 0; i < SHIP_COLL_COUNT; i++) {
- shipCollisions[i].owner = this;
- shipCollisions[i].info.category1 = 3;
- shipCollisions[i].info.category2 = 0;
- shipCollisions[i].info.bitfield1 = 0x4F;
- shipCollisions[i].info.bitfield2 = 0x8028E;
- shipCollisions[i].info.unkShort1C = 0;
- shipCollisions[i].info.callback = &ShipAPhysicsCallback;
- }
-
- static const float xToCentres[] = {-56.541185, 161.824968, 106.258581};
- static const float yToCentres[] = {-91.176745, -66.957921, 57.935231};
- static const float xToEdges[] = {39.481380, 11.698187, 24.371222};
- static const float yToEdges[] = {37.040555, 12.821730, 21.844430};
- static const float trpValues0[] = {-39.481380, -11.698187, -24.371222};
- static const float trpValues1[] = {-39.481380, -11.698187, 24.371222};
- static const float trpValues2[] = {-39.481380, -11.698187, -24.371222};
- static const float trpValues3[] = {39.481380, 11.698187, -24.371222};
- static const float scX1[] = {-176.447600, 64.340078, -157.925471, -157.925471};
- static const float scY1[] = {-128.217300, 112.570378, -109.695171, -109.695171};
- static const float scX2[] = {-176.447600, 64.340078, -157.925471, -157.925471};
- static const float scY2[] = {-128.217300, 112.570378, -109.695171, -109.695171};
-
- for (int i = 0; i < SHIP_COLL_COUNT; i++) {
- shipCollisions[i].info.xDistToCenter = xToCentres[i];
- shipCollisions[i].info.yDistToCenter = yToCentres[i];
- shipCollisions[i].info.xDistToEdge = xToEdges[i];
- shipCollisions[i].info.yDistToEdge = yToEdges[i];
- if (i >= 4) {
- int xi = i - 4;
- shipCollisions[i].trpValue0 = trpValues0[xi];
- shipCollisions[i].trpValue1 = trpValues1[xi];
- shipCollisions[i].trpValue2 = trpValues2[xi];
- shipCollisions[i].trpValue3 = trpValues3[xi];
- shipCollisions[i].collisionCheckType = 3;
- }
+ static const float scX1[] = {-176.447600, 64.340078, -157.925471, -157.925471, -158.561530, 49.742932, 48.957043};
+ static const float scY1[] = {128.217300, 86.427956, 54.136191, -36.090801, 22.765115, 162.568398, 66.849169};
+ static const float scX2[] = {-96.022566, 150.126781, 173.523155, 81.887358, -50.343171, 84.419332, 117.889270};
+ static const float scY2[] = {54.136191, 54.136191, -36.090801, -79.779661, -26.166291, 142.846802, -2.083058};
+ static s16 sRots[] = {-8192, -8192, -8192};
+
+ for (int i = 0; i < SHIP_SCOLL_COUNT; i++) {
+ shipSColls[i].setup(this,
+ scX1[i], scY1[i], scX2[i], scY2[i],
+ 0, 0, 0, 1, 0);
+ if (i >= 4)
+ shipSColls[i].setPtrToRotation(&sRots[i - 4]);
}
// Bowser Physics!
@@ -263,8 +274,8 @@ int daCaptainBowser::onCreate() {
BowserPhysics.xDistToCenter = -152.0;
BowserPhysics.yDistToCenter = 152.0;
- BowserPhysics.xDistToEdge = 38.0;
- BowserPhysics.yDistToEdge = 38.0;
+ BowserPhysics.xDistToEdge = 28.0;
+ BowserPhysics.yDistToEdge = 26.0;
BowserPhysics.category1 = 0x3;
BowserPhysics.category2 = 0x0;
@@ -277,90 +288,64 @@ int daCaptainBowser::onCreate() {
- // Roar Physics!
- ActivePhysics::Info RoarStruct;
- RoarStruct.xDistToCenter = -186.0;
- RoarStruct.yDistToCenter = 138.0;
-
- RoarStruct.xDistToEdge = 20.0;
- RoarStruct.yDistToEdge = 20.0;
-
- RoarStruct.category1 = 0x3;
- RoarStruct.category2 = 0x0;
- RoarStruct.bitfield1 = 0x4F;
- RoarStruct.bitfield2 = 0x8028E;
- RoarStruct.unkShort1C = 0;
- RoarStruct.callback = &dEn_c::collisionCallback;
-
- this->Roar.initWithStruct(this, &RoarStruct);
-
-
// State Changers
this->isIntro = 3;
doStateChange(&StateID_Intro);
+ // THIS IS FOR TESTING!!!
+ damage = 0;
+
return true;
}
int daCaptainBowser::onDelete() {
+ prplSound.Stop(0);
return true;
}
+int daCaptainBowser::afterExecute(int param) {
+ return dEn_c::afterExecute(param);
+}
+
int daCaptainBowser::onExecute() {
acState.execute();
- PlaySound(this, SE_BOSS_SHIP_PRPL);
+ if (!prplSound.Exists() && acState.getCurrentState() != &StateID_Outro) {
+ PlaySoundWithFunctionB4(SoundRelatedClass, &prplSound, SE_BOSS_SHIP_PRPL, 1);
+ }
+
+ aPhysics.info.xDistToCenter = bowserX;
+ aPhysics.info.yDistToCenter = bowserY + 28.0f;
bodyModel._vf1C();
shipModel._vf1C();
- if(this->isIntro == 0) {
+ for (int i = 0; i < SHIP_SCOLL_COUNT; i++)
+ shipSColls[i].update();
- float xmod = sin(this->sinTimer * 3.14 / 180.0) * 60.0;
- float ymod = sin(this->sinTimer * 3.14 / 130.0) * 84.0;
+ float xmod = sinTimerXRunning ? (sin(this->sinTimerX * 3.14 / 180.0) * 60.0) : 0.0f;
+ float ymod = sin(this->sinTimerY * 3.14 / 130.0) * (sinTimerYRunning ? 84.0 : 10.0);
+ if(this->isIntro == 0) {
pos.x = ClassWithCameraInfo::instance->screenCentreX + 200.0 + xmod;
pos.y = ClassWithCameraInfo::instance->screenCentreY - 180.0 + ymod;
- this->sinTimer++;
+ sinTimerX++;
+ if (sinTimerX >= 360) {
+ sinTimerX = 0;
+ if (stopMoving)
+ sinTimerXRunning = false;
+ }
+
+ sinTimerY++;
+ if (sinTimerY >= 260) {
+ sinTimerY = 0;
+ if (stopMoving)
+ sinTimerYRunning = false;
+ }
}
- // this->homingBillCountdown--;
-
- // if (this->homingBillCountdown == 0) {
-
- // Vec tempPos;
-
- // switch (this->homingBillSlot) {
- // case 0:
- // this->homingBillSlot++;
- // tempPos.x = this->pos.x - 26.0;
- // tempPos.y = this->pos.y + 40.0;
- // tempPos.z = this->pos.z + 2000.0;
- // break;
-
- // case 1:
- // this->homingBillSlot++;
- // tempPos.x = this->pos.x + 22.0;
- // tempPos.y = this->pos.y + 40.0;
- // tempPos.z = this->pos.z + 2000.0;
- // break;
-
- // case 2:
- // this->homingBillSlot = 0;
- // tempPos.x = this->pos.x + 70.0;
- // tempPos.y = this->pos.y + 40.0;
- // tempPos.z = this->pos.z + 2000.0;
- // break;
- // }
-
- // SpawnEffect("Wm_en_killervanish", 0, &tempPos, &(S16Vec){0,0,0}, &(Vec){0.1, 0.1, 0.1});
- // PlaySoundAsync(this, SE_EMY_SR_KILLER_SHOT);
- // CreateActor(EN_SEARCH_KILLER, 0, tempPos, 0, 0);
-
- // this->homingBillCountdown = (isAngry) ? 90: 180;
- // }
-
- if(this->shipAnm.isAnimationDone()) {
+
+ if(this->shipAnm.isAnimationDone() && acState.getCurrentState() != &StateID_Outro) {
this->shipAnm.setCurrentFrame(0.0);
}
@@ -371,9 +356,8 @@ int daCaptainBowser::onDraw() {
if(this->isIntro > 2) { return false; }
- matrix.translation(pos.x-146.0, pos.y+122.0, pos.z-200.0); // 136.0 is the bottom of the platform footing
- short newrot = rot.y + 0xD800;
- matrix.applyRotationYXZ(&rot.x, &newrot, &rot.z);
+ matrix.translation(pos.x+bowserX, pos.y+bowserY, pos.z-200.0); // 136.0 is the bottom of the platform footing
+ matrix.applyRotationYXZ(&bowserRotX, &bowserRotY, &rot.z);
bodyModel.setDrawMatrix(matrix);
bodyModel.setScale(&(Vec){1.0, 1.0, 1.0});
@@ -383,8 +367,7 @@ int daCaptainBowser::onDraw() {
matrix.translation(pos.x, pos.y, pos.z);
- newrot = rot.y + 0x4000;
- matrix.applyRotationYXZ(&rot.x, &newrot, &rot.z);
+ matrix.applyRotationYXZ(&rot.x, &shipRotY, &rot.z);
shipModel.setDrawMatrix(matrix);
shipModel.setScale(&scale);
@@ -392,6 +375,18 @@ int daCaptainBowser::onDraw() {
shipModel.scheduleForDrawing();
+ if (renderFlamethrowerModel) {
+ matrix.translation(pos.x + flameOffsetX, pos.y + flameOffsetY, flameZ);
+ s16 thing = 0x8000;
+ matrix.applyRotationZ(&thing);
+
+ flamethrowerModel.setDrawMatrix(matrix);
+ flamethrowerModel.setScale(&flameScale);
+ flamethrowerModel.calcWorld(false);
+
+ flamethrowerModel.scheduleForDrawing();
+ }
+
return true;
}
@@ -430,10 +425,17 @@ int daCaptainBowser::onDraw() {
}
// Bowser Flies In
- if (this->timer == 422) { this->isIntro = 2; }
- if ((this->timer > 420) && (this->timer < (420 + roarLen))) {
- pos.x = ClassWithCameraInfo::instance->screenCentreX + ((this->timer - 420.0) * 1.5) - ((roarLen * 1.5) - 200.0);
- pos.y = ClassWithCameraInfo::instance->screenCentreY - 380.0 + ((this->timer - 420.0) * 1.5) - ((roarLen * 1.5) - 200.0);
+ if (this->timer == 422) {
+ this->isIntro = 2;
+
+ for (int i = 0; i < SHIP_SCOLL_COUNT; i++)
+ shipSColls[i].addToList();
+ }
+
+ if (this->timer > 420) {
+ int effectiveTimer = min(timer, 719U);
+ pos.x = ClassWithCameraInfo::instance->screenCentreX + ((effectiveTimer - 420.0) * 1.5) - ((roarLen * 1.5) - 200.0);
+ pos.y = ClassWithCameraInfo::instance->screenCentreY - 380.0 + ((effectiveTimer - 420.0) * 1.5) - ((roarLen * 1.5) - 200.0);
}
// Bowser does a shitty roar
@@ -457,8 +459,6 @@ int daCaptainBowser::onDraw() {
}
void daCaptainBowser::endState_Intro() {
- for (int i = 0; i < SHIP_COLL_COUNT; i++)
- shipCollisions[i].addToList();
this->aPhysics.addToList();
this->isInvulnerable = 0;
@@ -507,12 +507,12 @@ int daCaptainBowser::onDraw() {
if (this->chrAnimation.getCurrentFrame() == 60.0) { // throw back
int num = GenerateRandomNumber(4);
- CreateActor(0x29F, 0x101 + ((num + 1) * 0x10), (Vec){pos.x-146.0, pos.y+122.0, pos.z}, 0, 0);
+ CreateActor(0x29F, 0x101 + ((num + 1) * 0x10), (Vec){pos.x+bowserX, pos.y+bowserY, pos.z}, 0, 0);
}
if (this->chrAnimation.getCurrentFrame() == 126.0) { // throw front
int num = GenerateRandomNumber(4);
- CreateActor(0x29F, ((num + 1) * 0x10) + 1, (Vec){pos.x-146.0, pos.y+122.0, pos.z}, 0, 0);
+ CreateActor(0x29F, ((num + 1) * 0x10) + 1, (Vec){pos.x+bowserX, pos.y+bowserY, pos.z}, 0, 0);
}
if (this->chrAnimation.isAnimationDone()) {
@@ -573,39 +573,26 @@ int daCaptainBowser::onDraw() {
bindAnimChr_and_setUpdateRate("kp_roar3", 1, 0.0, 1.0);
this->isInvulnerable = 1;
this->timer = 0;
- this->scaleIncreaser = 0.5;
-
- // this->Roar.info.xDistToEdge = 70.0 * scaleIncreaser;
- // this->Roar.info.yDistToEdge = 70.0 * scaleIncreaser;
-
- // this->Roar.addToList();
}
void daCaptainBowser::executeState_Roar() {
if (this->chrAnimation.getCurrentFrame() == 53.0) { // This is where the smackdown starts
- PlaySound(this, SE_VOC_KP_L_SHOUT);
+ nw4r::snd::SoundHandle handle;
+ PlaySoundWithFunctionB4(SoundRelatedClass, &handle, SE_VOC_KP_L_SHOUT, 1);
}
if (this->chrAnimation.getCurrentFrame() > 53.0) { // This is where the smackdown starts
- scaleIncreaser += 0.014285;
- effect.spawn("Wm_ko_shout", 0, &(Vec){pos.x-186.0+(scaleIncreaser*16.0), pos.y+138.0+(scaleIncreaser*16.0), pos.z}, &(S16Vec){0,0,0x7000}, &(Vec){scaleIncreaser, scaleIncreaser, scaleIncreaser});
-
- // this->Roar.info.xDistToEdge = 70.0 * scaleIncreaser;
- // this->Roar.info.yDistToEdge = 70.0 * scaleIncreaser;
+ effect.spawn("Wm_ko_shout", 0, &(Vec){pos.x-174.0, pos.y+140.0, pos.z}, &(S16Vec){0,0,0x7000}, &(Vec){1.0, 1.0, 1.0});
}
- // if (this->chrAnimation.getCurrentFrame() == 197.0) { // This is where the smackdown ends
- // this->Roar.removeFromList();
- // }
-
if (this->chrAnimation.isAnimationDone()) {
- doStateChange(&StateID_Wait);
+ doStateChange(deathSequenceRunning ? &StateID_FinalAttack : &StateID_Wait);
}
}
void daCaptainBowser::endState_Roar() {
this->isInvulnerable = 0;
- this->isAngry = 1;
+ this->isAngry = 1;
}
@@ -633,10 +620,221 @@ int daCaptainBowser::onDraw() {
//////////////////
// State Outro
//////////////////
- void daCaptainBowser::beginState_Outro() {
+void daCaptainBowser::initiateDeathSequence() {
+ deathSequenceRunning = true;
+ stopMoving = true;
+
+ StopBGMMusic();
+ dFlagMgr_c::instance->set(31, 0, false, false, false);
+ *((u32*)(((char*)dBgGm_c::instance) + 0x900F0)) = 999;
+
+ doStateChange(&StateID_Roar);
+}
+
+void daCaptainBowser::beginState_FinalAttack() {
+ isInvulnerable = true;
+
+ bindAnimChr_and_setUpdateRate("mastfail", 1, 0.0, 1.0f);
+
+ timer = 0;
+ flameScale.x = flameScale.y = flameScale.z = 0.0f;
+}
+
+void daCaptainBowser::executeState_FinalAttack() {
+ timer++;
+
+ if (timer == 56) {
+ nw4r::snd::SoundHandle handle;
+ PlaySoundWithFunctionB4(SoundRelatedClass, &handle, SE_VOC_JR_CHARGE, 1);
+ handle.SetPitch(0.25f);
+ } else if (timer == 185) {
+ nw4r::snd::SoundHandle handle;
+ PlaySoundWithFunctionB4(SoundRelatedClass, &handle, SE_VOC_KP_SHOUT, 1);
+ } else if (timer == 348) {
+ nw4r::snd::SoundHandle handle;
+ PlaySoundWithFunctionB4(SoundRelatedClass, &handle, SE_EMY_BIG_PAKKUN_DAMAGE_1, 1);
+ }
+
+ if (timer > 204 && timer < 315) {
+ if (timer == 205) {
+ // First thing
+ renderFlamethrowerModel = true;
+
+ static const ActivePhysics::Info fcInfo = {
+ 0.0f, 0.0f, 0.0f, 0.0f, // placeholder
+ 3, 0, 0x4F, 0x8028E, 0,
+ &dEn_c::collisionCallback
+ };
+ flameCollision.initWithStruct(this, &fcInfo);
+ flameCollision.addToList();
+ }
+ if (timer < 289) {
+ if (flameScale.y < 2.0f) {
+ flameScale.y = flameScale.y = flameScale.z = flameScale.y + 0.1f;
+ } else {
+ flameScale.y = flameScale.y = flameScale.z = 2.5f;
+ }
+ }
+ flameScale.x = flameScale.y * 1.5f;
+
+ flameCollision.info.xDistToCenter = flameOffsetX - (48.0f * flameScale.x);
+ flameCollision.info.yDistToCenter = flameOffsetY;
+ flameCollision.info.xDistToEdge = 48.0f * flameScale.x;
+ flameCollision.info.yDistToEdge = 7.0f * flameScale.y;
+
+ Vec efPos = {pos.x + flameOffsetX, pos.y + flameOffsetY, flameZ};
+ S16Vec efRot = {-0x4000, 0, 0};
+ //flamethrowerEffect.spawn("Wm_en_fireburner", 0, &efPos, &efRot, &flameScale);
+ flamethrowerEffectInd.spawn("Wm_en_fireburner6ind", 0, &efPos, &efRot, &flameScale);
+ flamethrowerModel._vf1C();
+ flamethrowerAnim.process();
+ } else if (timer == 315) {
+ renderFlamethrowerModel = false;
+ flameCollision.removeFromList();
+ aPhysics.removeFromList();
+
+ Vec efPos = {pos.x + flameOffsetX - 6.0f, pos.y + flameOffsetY + 1.0f, pos.z};
+ float offsets[] = {0.0f, 3.0f, 0.0f, -3.0f};
+ for (int i = 0; i < 20; i++) {
+ efPos.y = pos.y + flameOffsetY + offsets[i & 3];
+ SpawnEffect("Wm_mr_fireball_hit01", 0, &efPos, &(S16Vec){0,0,0}, &(Vec){1.5f, 1.5f, 1.5f});
+ efPos.x -= 12.0f;
+ }
+
+ nw4r::snd::SoundHandle handle;
+ PlaySoundWithFunctionB4(SoundRelatedClass, &handle, SE_OBJ_PAIPO, 1);
+ } else if (timer == 348) {
+ nw4r::snd::SoundHandle handle;
+ PlaySoundWithFunctionB4(SoundRelatedClass, &handle, SE_DEMO_ED_BALLOON_LAND, 1);
+
+ Vec efPos = {pos.x - 72.0f, pos.y + 170.0f, pos.z};
+ SpawnEffect("Wm_mr_wallkick_l", 0, &efPos, &(S16Vec){0,0,0}, &(Vec){2.0, 2.0, 2.0});
+ }
+
+ if (chrAnimation.isAnimationDone()) {
+ doStateChange(&StateID_Outro);
+ }
+}
+
+void daCaptainBowser::endState_FinalAttack() {
+}
+
+void daCaptainBowser::beginState_Outro() {
+ WLClass::instance->_4 = 5;
+ WLClass::instance->_8 = 0;
+ dStage32C_c::instance->freezeMarioBossFlag = 1;
+
+ bowserX += 56.0f;
+ bindAnimChr_and_setUpdateRate("kp_death1", 1, 0.0, 1.0f);
+
+ //shipRotY = -0x4000;
+ shipAnm.bind(&shipModel, shipFile.GetResAnmChr("mastfail_after"), 1);
+ shipModel.bindAnim(&shipAnm, 0.0);
+ shipAnm.setUpdateRate(0.5f);
+
+ bowserXSpeed = -3.5f;
+ bowserYSpeed = 8.9f;
+ bowserMaxYSpeed = -4.0f;
+ bowserYAccel = -0.24375f;
+
+ nw4r::snd::SoundHandle handle;
+ PlaySoundWithFunctionB4(SoundRelatedClass, &handle, SE_VOC_KP_L_FALL, 1);
+
+ explosionBottomBound = 0.0f;
+
+ timer = 0;
+}
+
+extern dStateBase_c JrClownEndDemoState;
+void daCaptainBowser::executeState_Outro() {
+ if (wereEntirelyDone)
+ return;
+
+ timer++;
+
+ float frame = shipAnm.getCurrentFrame();
+
+ // nuke the things!
+ if (frame == 35.0f) {
+ dActor_c *iter = 0;
+
+ while (iter = (dActor_c*)dActor_c::searchByBaseType(2, iter)) {
+ dStageActor_c *sa = (dStageActor_c*)iter;
+
+ if (sa->name == EN_BIRIKYU_MAKER || sa->name == KAZAN_MGR) {
+ sa->Delete(1);
+ }
+
+ if (sa->name == EN_LINE_BIRIKYU ||
+ sa->name == EN_STAR_COIN ||
+ sa->name == EN_HATENA_BALLOON ||
+ sa->name == EN_ITEM ||
+ sa->name == EN_TARZANROPE || // Meteor
+ sa->name == WM_ANCHOR) { // Koopa Throw
+ sa->killedByLevelClear();
+ sa->Delete(1);
+ }
+ }
+
+ // freeze ye olde clowne
+ dEn_c *clownIter = 0;
+ while (clownIter = (dEn_c*)dEn_c::search(JR_CLOWN_FOR_PLAYER, clownIter)) {
+ clownIter->doStateChange(&JrClownEndDemoState);
+ }
+
+ // remove all ship collisions
+ for (int i = 0; i < SHIP_SCOLL_COUNT; i++)
+ shipSColls[i].removeFromList();
+
+ } else if (frame == 150.0f) {
+ nw4r::snd::SoundHandle handle;
+ PlaySoundWithFunctionB4(SoundRelatedClass, &handle, SE_BOSS_KOOPA_CRASH, 1);
+ prplSound.Stop(10);
+
+ ClassWithCameraInfo *cwci = ClassWithCameraInfo::instance;
+ Vec efPos = {cwci->screenCentreX+168.0f, cwci->screenTop-cwci->screenHeight, pos.z};
+ SpawnEffect("Wm_bg_volcano", 0, &efPos, &(S16Vec){0,0,0}, &(Vec){4.0, 4.0, 4.0});
+
+ ShakeScreen(StageScreen, 17, 7, 0, 0);
+
+ } else if (shipAnm.isAnimationDone()) {
+ wereEntirelyDone = true;
}
- void daCaptainBowser::executeState_Outro() {
+ if (frame > 30.0f) {
+ if (timer & 4 && explosionBottomBound > -249.0f) {
+ static const char *efs[] = {"Wm_en_explosion", "Wm_ob_cmnboxpiece"};
+
+ int id = MakeRandomNumber(2);
+ Vec efPos = {
+ pos.x - 150.0f + MakeRandomNumber(300),
+ pos.y + explosionBottomBound + MakeRandomNumber(250 + explosionBottomBound),
+ pos.z + 200.0f
+ };
+ float efScale = (float(MakeRandomNumber(30)) / 20.0f);
+
+ SpawnEffect(efs[id], 0, &efPos, &(S16Vec){0,0,0}, &(Vec){efScale,efScale,efScale});
+ }
+
+ if ((timer % 12) == 0 && (frame < 150.0f)) {
+ nw4r::snd::SoundHandle handle;
+ PlaySoundWithFunctionB4(SoundRelatedClass, &handle, SE_DEMO_OP_CAKE_CLASH_1210f, 1);
+ }
+
+ explosionBottomBound -= 0.85f;
}
- void daCaptainBowser::endState_Outro() { }
+
+ // handleYSpeed():
+ bowserYSpeed += bowserYAccel;
+ if (bowserYSpeed < bowserMaxYSpeed)
+ bowserYSpeed = bowserMaxYSpeed;
+
+ // doMovement()
+ bowserX += bowserXSpeed;
+ bowserY += bowserYSpeed;
+
+ bowserRotX -= 0xC00;
+ bowserRotY -= 0x100;
+}
+void daCaptainBowser::endState_Outro() { }