summaryrefslogtreecommitdiff
path: root/src/bossPodouble.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/bossPodouble.cpp706
1 files changed, 706 insertions, 0 deletions
diff --git a/src/bossPodouble.cpp b/src/bossPodouble.cpp
new file mode 100644
index 0000000..663781e
--- /dev/null
+++ b/src/bossPodouble.cpp
@@ -0,0 +1,706 @@
+#include <common.h>
+#include <game.h>
+#include <g3dhax.h>
+#include <sfx.h>
+#include <stage.h>
+#include "effects.h"
+#include "player.h"
+
+void poodleCollisionCallback(ActivePhysics *apThis, ActivePhysics *apOther);
+
+void poodleCollisionCallback(ActivePhysics *apThis, ActivePhysics *apOther) {
+ if (apOther->owner->name == BROS_FIREBALL) { return; }
+ else if (apOther->owner->name == BROS_ICEBALL) { return; }
+ else { dEn_c::collisionCallback(apThis, apOther); }
+ }
+
+class daPodouble : public dEn_c {
+ int onCreate();
+ int onDelete();
+ int onExecute();
+ int onDraw();
+
+ mHeapAllocator_c allocator;
+ nw4r::g3d::ResFile resFile;
+
+ m3d::mdl_c bodyModel;
+ m3d::mdl_c fogModel;
+ m3d::mdl_c fog2Model;
+
+ m3d::anmTexSrt_c body;
+
+ m3d::anmChr_c fogChr;
+ m3d::anmTexSrt_c fogSRT;
+
+ m3d::anmChr_c fog2Chr;
+ m3d::anmTexSrt_c fog2SRT;
+
+
+ char isFire;
+ char goingUp;
+ int timer;
+ float dying;
+ int damage;
+ float Baseline;
+ char isInvulnerable;
+ int countdown;
+
+ dEn_c *Kameck;
+
+ static daPodouble *build();
+
+ // void spriteCollision(ActivePhysics *apThis, ActivePhysics *apOther);
+ void playerCollision(ActivePhysics *apThis, ActivePhysics *apOther);
+ void yoshiCollision(ActivePhysics *apThis, ActivePhysics *apOther);
+
+ void collisionCat3_StarPower(ActivePhysics *apThis, ActivePhysics *apOther);
+ void collisionCat14_YoshiFire(ActivePhysics *apThis, ActivePhysics *apOther);
+ void collisionCatD_GroundPound(ActivePhysics *apThis, ActivePhysics *apOther);
+ void collisionCat7_WMWaggleWater(ActivePhysics *apThis, ActivePhysics *apOther);
+ void collisionCat7_WMWaggleWaterYoshi(ActivePhysics *apThis, ActivePhysics *apOther);
+ void collisionCat9_RollingObject(ActivePhysics *apThis, ActivePhysics *apOther);
+ void collisionCat1_Fireball_E_Explosion(ActivePhysics *apThis, ActivePhysics *apOther);
+ bool collisionCat2_IceBall_15_YoshiIce(ActivePhysics *apThis, ActivePhysics *apOther);
+ void collisionCat13_Hammer(ActivePhysics *apThis, ActivePhysics *apOther);
+ void collisionCatA_PenguinMario(ActivePhysics *apThis, ActivePhysics *apOther);
+
+
+ USING_STATES(daPodouble);
+ DECLARE_STATE(Bounce);
+ DECLARE_STATE(Spit);
+ DECLARE_STATE(Damage);
+
+ DECLARE_STATE(Grow);
+ DECLARE_STATE(Outro);
+ DECLARE_STATE(SyncDie);
+
+};
+
+daPodouble *daPodouble::build() {
+ void *buffer = AllocFromGameHeap1(sizeof(daPodouble));
+ return new(buffer) daPodouble;
+}
+
+///////////////////////
+// Externs and States
+///////////////////////
+ extern "C" void *PlaySound(dStageActor_c *, int soundID);
+ extern "C" void *PlaySoundAsync(dStageActor_c *, int soundID);
+
+ extern "C" u32 GenerateRandomNumber(int max);
+ extern "C" dStageActor_c *GetSpecificPlayerActor(int num);
+ extern "C" int SmoothRotation(short* rot, u16 amt, int unk2);
+ extern "C" void* WaterManager;
+ extern "C" u32 CheckforLiquid(void*, Vec, int, int, int, int layer);
+
+ extern "C" void *StopBGMMusic();
+ extern "C" void *StartBGMMusic();
+
+ extern "C" void *MakeMarioEnterDemoMode();
+ extern "C" void *MakeMarioExitDemoMode();
+ extern "C" void *UpdateGameMgr();
+
+
+ CREATE_STATE(daPodouble, Bounce);
+ CREATE_STATE(daPodouble, Spit);
+ CREATE_STATE(daPodouble, Damage);
+
+ CREATE_STATE(daPodouble, Grow);
+ CREATE_STATE(daPodouble, Outro);
+ CREATE_STATE(daPodouble, SyncDie);
+
+
+////////////////////////
+// Collision Functions
+////////////////////////
+
+ void daPodouble::playerCollision(ActivePhysics *apThis, ActivePhysics *apOther) {
+ this->dEn_c::playerCollision(apThis, apOther);
+ this->_vf220(apOther->owner);
+
+ // fix multiple player collisions via megazig
+ this->isDead = 0;
+ this->flags_4FC |= (1<<(31-7));
+ if(apOther->owner->which_player < 3) {
+ this->counter_504[apOther->owner->which_player] = 0;
+ }
+ }
+
+ void daPodouble::yoshiCollision(ActivePhysics *apThis, ActivePhysics *apOther) { this->playerCollision(apThis, apOther); }
+ void daPodouble::collisionCat7_WMWaggleWater(ActivePhysics *apThis, ActivePhysics *apOther) { this->playerCollision(apThis, apOther); }
+ void daPodouble::collisionCat7_WMWaggleWaterYoshi(ActivePhysics *apThis, ActivePhysics *apOther) { this->playerCollision(apThis, apOther); }
+ void daPodouble::collisionCatA_PenguinMario(ActivePhysics *apThis, ActivePhysics *apOther) { this->playerCollision(apThis, apOther); }
+
+ void daPodouble::collisionCatD_GroundPound(ActivePhysics *apThis, ActivePhysics *apOther) { return; }
+ void daPodouble::collisionCat9_RollingObject(ActivePhysics *apThis, ActivePhysics *apOther) { return; }
+ void daPodouble::collisionCat3_StarPower(ActivePhysics *apThis, ActivePhysics *apOther) { return; }
+
+ void daPodouble::collisionCat13_Hammer(ActivePhysics *apThis, ActivePhysics *apOther) {
+ apOther->owner->kill();
+ if (this->isInvulnerable) { return; }
+
+ this->damage += 2;
+
+ if (this->damage < 12) { doStateChange(&StateID_Damage); }
+ else { doStateChange(&StateID_Outro); }
+ }
+
+ void daPodouble::collisionCat14_YoshiFire(ActivePhysics *apThis, ActivePhysics *apOther){
+ apOther->owner->Delete(1);
+ if (this->isInvulnerable) { return; }
+
+ if (this->isFire == 0) {
+ this->damage += 3;
+
+ if (this->damage < 12) { doStateChange(&StateID_Damage); }
+ else { doStateChange(&StateID_Outro); }
+ }
+ }
+
+ void daPodouble::collisionCat1_Fireball_E_Explosion(ActivePhysics *apThis, ActivePhysics *apOther) {
+ if (this->isInvulnerable) { return; }
+
+ if (this->isFire == 0) {
+ this->damage += 2;
+
+ if (this->damage < 12) { doStateChange(&StateID_Damage); }
+ else { doStateChange(&StateID_Outro); }
+ }
+ }
+
+ bool daPodouble::collisionCat2_IceBall_15_YoshiIce(ActivePhysics *apThis, ActivePhysics *apOther) {
+ apOther->owner->Delete(1);
+ if (this->isInvulnerable) { return true; }
+
+ if (this->isFire == 1) {
+ if (apOther->owner->name == 104) { this->damage += 2; }
+ else { this->damage += 3; }
+
+ if (this->damage < 12) { doStateChange(&StateID_Damage); }
+ else { doStateChange(&StateID_Outro); }
+
+ return true;
+ }
+ else { return false; }
+ }
+
+
+int daPodouble::onCreate() {
+
+ this->isFire = this->settings >> 28;
+ this->Baseline = this->pos.y - (float)((this->settings & 0xFF) * 0.8);
+
+
+ OSReport("Creating the Podouble Model\n");
+ allocator.link(-1, GameHeaps[0], 0, 0x20);
+
+ // Fire or Ice
+ if (this->isFire == 1) {
+ this->resFile.data = getResource("bubble", "g3d/t00.brres");
+ }
+ else {
+ this->resFile.data = getResource("bubble", "g3d/t05.brres");
+ }
+
+ // Body and anms
+ nw4r::g3d::ResMdl mdl = this->resFile.GetResMdl("bubble");
+ bodyModel.setup(mdl, &allocator, 0x224, 1, 0);
+
+ nw4r::g3d::ResAnmTexSrt anmRes = this->resFile.GetResAnmTexSrt("bubble");
+ this->body.setup(mdl, anmRes, &this->allocator, 0, 1);
+ this->body.bindEntry(&this->bodyModel, anmRes, 0, 0);
+ this->bodyModel.bindAnim(&this->body, 0.0);
+
+
+ // Fog up and anms
+ mdl = this->resFile.GetResMdl("bubble_fog");
+ fogModel.setup(mdl, &allocator, 0x124, 1, 0);
+
+ nw4r::g3d::ResAnmChr anmChr = this->resFile.GetResAnmChr("bubble_fog");
+ this->fogChr.setup(mdl, anmChr, &this->allocator, 0);
+ this->fogChr.bind(&this->fogModel, anmChr, 1);
+ this->fogModel.bindAnim(&this->fogChr, 0.0);
+ this->fogChr.setUpdateRate(1.0);
+
+ anmRes = this->resFile.GetResAnmTexSrt("bubble_fog");
+ this->fogSRT.setup(mdl, anmRes, &this->allocator, 0, 1);
+ this->fogSRT.bindEntry(&this->fogModel, anmRes, 0, 0);
+ this->fogModel.bindAnim(&this->fogSRT, 0.0);
+
+
+ // Fog down and anms
+ mdl = this->resFile.GetResMdl("bubble_fog2");
+ fog2Model.setup(mdl, &allocator, 0x124, 1, 0);
+
+ anmChr = this->resFile.GetResAnmChr("bubble_fog2");
+ this->fog2Chr.setup(mdl, anmChr, &this->allocator, 0);
+ this->fog2Chr.bind(&this->fog2Model, anmChr, 1);
+ this->fogModel.bindAnim(&this->fog2Chr, 0.0);
+ this->fog2Chr.setUpdateRate(1.0);
+
+ anmRes = this->resFile.GetResAnmTexSrt("bubble_fog");
+ this->fog2SRT.setup(mdl, anmRes, &this->allocator, 0, 1);
+ this->fog2SRT.bindEntry(&this->fog2Model, anmRes, 0, 0);
+ this->fog2Model.bindAnim(&this->fog2SRT, 0.0);
+
+
+
+ allocator.unlink();
+
+
+ // Stuff I do understand
+ OSReport("Setting Podouble's Size to 1.0\n");
+ this->scale = (Vec){1.0, 1.0, 1.0};
+
+
+ this->direction = (this->isFire) ? 0 : 1;
+ this->countdown = (this->isFire) ? 90 : 0;
+
+ this->rot.x = 0; // X is vertical axis
+ this->rot.y = (direction) ? 0xD800 : 0x2800;
+ this->rot.z = 0; // Z is ... an axis >.>
+
+ this->speed.x = 0.0;
+ this->speed.y = 0.0;
+ this->max_speed.x = 0.0;
+ this->x_speed_inc = 0.0;
+
+ this->goingUp = 0;
+
+
+ OSReport("Creating Podouble's Physics Struct\n");
+
+ ActivePhysics::Info HitMeBaby;
+
+ HitMeBaby.xDistToCenter = 0.0;
+ HitMeBaby.yDistToCenter = 0.0;
+
+ HitMeBaby.xDistToEdge = 40.0;
+ HitMeBaby.yDistToEdge = 40.0;
+
+ HitMeBaby.category1 = 0x3;
+ HitMeBaby.category2 = 0x0;
+ HitMeBaby.bitfield1 = 0x4F;
+ HitMeBaby.bitfield2 = (this->isFire) ? 0x388626 : 0x388626;
+ HitMeBaby.unkShort1C = 0;
+ HitMeBaby.callback = &poodleCollisionCallback;
+
+ OSReport("Making the Physics Class and adding to the list\n");
+ this->aPhysics.initWithStruct(this, &HitMeBaby);
+ this->aPhysics.addToList();
+
+ this->disableEatIn();
+
+ doStateChange(&StateID_Grow);
+
+ OSReport("Going to Execute Podouble\n");
+ this->onExecute();
+ return true;
+}
+
+int daPodouble::onDelete() {
+ return true;
+}
+
+int daPodouble::onExecute() {
+ acState.execute();
+
+ return true;
+}
+
+int daPodouble::onDraw() {
+ if (this->speed.y >= 0) {
+ matrix.translation(pos.x, pos.y, pos.z);
+
+ fogModel.setDrawMatrix(matrix);
+ fogModel.setScale(&scale);
+ fogModel.calcWorld(false);
+
+ fogModel.scheduleForDrawing();
+ fogModel._vf1C();
+
+ if(this->fogChr.isAnimationDone())
+ this->fogChr.setCurrentFrame(0.0);
+
+ this->fogSRT.process();
+ }
+ else {
+ matrix.translation(pos.x, pos.y, pos.z);
+
+ fog2Model.setDrawMatrix(matrix);
+ fog2Model.setScale(&scale);
+ fog2Model.calcWorld(false);
+
+ fog2Model.scheduleForDrawing();
+ fog2Model._vf1C();
+
+ if(this->fog2Chr.isAnimationDone())
+ this->fog2Chr.setCurrentFrame(0.0);
+
+ this->fog2SRT.process();
+ }
+
+ matrix.translation(pos.x, pos.y, pos.z);
+ matrix.applyRotationYXZ(&rot.x, &rot.y, &rot.z);
+
+ bodyModel.setDrawMatrix(matrix);
+ bodyModel.setScale(&scale);
+ bodyModel.calcWorld(false);
+
+ bodyModel.scheduleForDrawing();
+ this->body.process();
+
+ return true;
+}
+
+
+///////////////
+// Grow State
+///////////////
+ void daPodouble::beginState_Grow() {
+ this->timer = 0;
+ if (isFire) { return; }
+
+ // Stop the BGM Music
+ StopBGMMusic();
+
+ // Set the necessary Flags and make Mario enter Demo Mode
+ dStage32C_c::instance->freezeMarioBossFlag = 1;
+ WLClass::instance->_4 = 4;
+ WLClass::instance->_8 = 0;
+
+ MakeMarioEnterDemoMode();
+
+ // Make sure to use the correct position
+ Vec pos = (Vec){this->pos.x - 124.0, this->pos.y + 104.0, 3564.0};
+ S16Vec rot = (S16Vec){0, 0, 0};
+
+ // Create And use Kameck
+ Kameck = (daKameckDemo*)createChild(KAMECK_FOR_CASTLE_DEMO, (dStageActor_c*)this, 0, &pos, &rot, 0);
+ Kameck->doStateChange(&daKameckDemo::StateID_DemoWait);
+
+ this->scale = (Vec){1.0, 1.0, 1.0};
+ }
+
+ void daPodouble::executeState_Grow() {
+
+ this->timer = this->timer + 1;
+
+ float scaleSpeed, yPosScaling;
+
+
+ if ((this->timer > 150) && (this->timer < 230)) {
+
+ scaleSpeed = 0.03125;
+ yPosScaling = 18;
+
+ float modifier;
+
+ modifier = 1.0 + ((this->timer - 150) * scaleSpeed);
+
+ this->scale = (Vec){modifier, modifier, modifier};
+ this->pos.y = this->pos.y + (yPosScaling/80);
+
+ }
+ if (this->timer > 420) {
+ PlaySound(this, SE_EMY_CS_MOVE_W8_BUBBLE_APP);
+ doStateChange(&StateID_Bounce);
+ }
+
+ if (isFire) { return; }
+ if (this->timer == 130) { Kameck->doStateChange(&daKameckDemo::StateID_DemoSt); }
+ if (this->timer == 150) { PlaySound(this, SE_BOSS_IGGY_WANWAN_TO_L); }
+ if (this->timer == 400) { Kameck->doStateChange(&daKameckDemo::StateID_DemoSt2); }
+ if (this->timer == 360) {
+ Vec tempPos = (Vec){this->pos.x - 40.0, this->pos.y + 120.0, 3564.0};
+ CreateEffect(&tempPos, &(S16Vec){0,0,0}, &(Vec){1.0, 1.0, 1.0}, 175); // 400 & 401 // 564 // 583 // 754 // 958
+ CreateEffect(&tempPos, &(S16Vec){0,0,0}, &(Vec){1.0, 1.0, 1.0}, 400); // 400 & 401 // 564 // 583 // 754 // 958
+ CreateEffect(&tempPos, &(S16Vec){0,0,0}, &(Vec){1.0, 1.0, 1.0}, 401); // 400 & 401 // 564 // 583 // 754 // 958
+ CreateEffect(&tempPos, &(S16Vec){0,0,0}, &(Vec){1.0, 1.0, 1.0}, 564); // 400 & 401 // 564 // 583 // 754 // 958
+ CreateEffect(&tempPos, &(S16Vec){0,0,0}, &(Vec){1.0, 1.0, 1.0}, 583); // 400 & 401 // 564 // 583 // 754 // 958
+ CreateEffect(&tempPos, &(S16Vec){0,0,0}, &(Vec){1.0, 1.0, 1.0}, 754); // 400 & 401 // 564 // 583 // 754 // 958
+ CreateEffect(&tempPos, &(S16Vec){0,0,0}, &(Vec){1.0, 1.0, 1.0}, 958); // 400 & 401 // 564 // 583 // 754 // 958
+ }
+ }
+ void daPodouble::endState_Grow() {
+ this->Baseline = this->pos.y;
+ if (isFire) { return; }
+
+ // Clean up the flags and Kameck
+ dStage32C_c::instance->freezeMarioBossFlag = 0;
+ WLClass::instance->_8 = 1;
+
+ MakeMarioExitDemoMode();
+ StartBGMMusic();
+
+ Kameck->Delete(1);
+ }
+
+
+///////////////
+// Bounce State
+///////////////
+ void daPodouble::beginState_Bounce() {
+ this->rot.y = (direction) ? 0xD800 : 0x2800;
+ this->rot.x = 0;
+
+ this->max_speed.y = -5.0;
+ this->speed.y = -1.0;
+ this->y_speed_inc = -0.1875;
+
+ this->goingUp = 0;
+ }
+ void daPodouble::executeState_Bounce() {
+
+ if (this->countdown) {
+ this->countdown--;
+ return; }
+
+ HandleYSpeed();
+ doSpriteMovement();
+
+ if (this->pos.y < this->Baseline) {
+ this->speed.y = 8.0;
+ this->goingUp = 1; }
+
+ if (-0.1 < this->speed.y < 0.1) {
+ if (this->goingUp == 1) { doStateChange(&StateID_Spit); } }
+
+
+ // Check for stupid liquid junk
+ float ydest;
+ ydest = (this->pos.y > this->last_pos.y) ? this->last_pos.y : this->pos.y;
+
+ int liquid = CheckforLiquid(WaterManager, this->pos, 0, 0, 0, this->currentLayerID);
+
+ OSReport("Liquid type %d", liquid);
+
+ if (liquid == 1) {
+ CreateEffect(&this->pos, &(S16Vec){0,0,0}, &(Vec){3.0, 3.0, 3.0}, 415);
+ PlaySoundAsync(this, SE_EMY_BUBBLE_SPLASH);
+ }
+ if (liquid == 0) {
+ CreateEffect(&this->pos, &(S16Vec){0,0,0}, &(Vec){3.0, 3.0, 3.0}, 422);
+ PlaySoundAsync(this, SE_OBJ_CMN_SPLASH);
+ }
+
+ }
+ void daPodouble::endState_Bounce() {
+ this->speed.y = 0.0;
+ this->y_speed_inc = 0.0;
+ }
+
+
+///////////////
+// Spit State
+///////////////
+ void daPodouble::beginState_Spit() { this->timer = 0; }
+ void daPodouble::executeState_Spit() {
+
+ if (this->timer < 0x40) {
+ this->rot.x -= 0x80;
+ }
+
+ else if (this->timer < 0x48) {
+ this->rot.x += 0x400;
+ }
+
+ else if (this->timer == 0x48) {
+ if (this->isFire == 0) {
+ dStageActor_c *spawner = create(BROS_ICEBALL, 0x10, &this->pos, &(S16Vec){0,0,0}, 0);
+ *((u32 *) (((char *) spawner) + 0x3DC)) = this->id;
+ PlaySoundAsync(this, SE_EMY_ICE_BROS_ICE);
+ doStateChange(&StateID_Bounce);
+ }
+ else {
+ create(BROS_FIREBALL, 0, &this->pos, &(S16Vec){0,0,0}, 0);
+ PlaySoundAsync(this, SE_EMY_FIRE_BROS_FIRE);
+ doStateChange(&StateID_Bounce);
+ }
+ }
+
+ this->timer += 1;
+ }
+ void daPodouble::endState_Spit() {
+ this->speed.y = -1.0;
+ this->y_speed_inc = -0.1875;
+ }
+
+
+///////////////
+// Damage State
+///////////////
+ void daPodouble::beginState_Damage() {
+ this->timer = 0;
+ this->isInvulnerable = 1;
+
+ if (this->isFire == 0) {
+ PlaySoundAsync(this, SE_OBJ_PNGN_ICE_THAW);
+ CreateEffect(&this->pos, &(S16Vec){0,0,0}, &(Vec){2.0, 2.0, 2.0}, 243); }
+ else {
+ PlaySoundAsync(this, SE_EMY_FIRE_SNAKE_EXTINCT);
+ CreateEffect(&this->pos, &(S16Vec){0,0,0}, &(Vec){3.0, 3.0, 3.0}, 252); }
+ }
+ void daPodouble::executeState_Damage() {
+
+ int amt;
+ amt = sin(this->timer * 3.14 / 4.0) * 0x2000;
+
+ this->rot.y = amt;
+ this->rot.y += (direction) ? 0xD800 : 0x2800;
+
+
+ if (this->timer > 180) {
+ doStateChange(&StateID_Bounce);
+ }
+
+ if ((this->timer == 60) || (this->timer == 80) || (this->timer == 100)) {
+ if (this->isFire == 0) {
+ dStageActor_c *spawner = create(BROS_ICEBALL, 0x10, &this->pos, &(S16Vec){0,0,0}, 0);
+ *((u32 *) (((char *) spawner) + 0x3DC)) = this->id;
+ PlaySoundAsync(this, SE_EMY_ICE_BROS_ICE);
+ }
+ else {
+ create(BROS_FIREBALL, 0, &this->pos, &(S16Vec){0,0,0}, 0);
+ PlaySoundAsync(this, SE_EMY_FIRE_BROS_FIRE);
+ }
+ }
+
+ this->timer += 1;
+
+ }
+ void daPodouble::endState_Damage() {
+ this->isInvulnerable = 0;
+ }
+
+
+///////////////
+// Outro State
+///////////////
+ void daPodouble::beginState_Outro() {
+
+ daPodouble *other = (daPodouble*)FindActorByType(SHIP_WINDOW, (Actor*)this);
+ if (other != 0) { other->doStateChange(&StateID_SyncDie); }
+
+ WLClass::instance->_4 = 5;
+ WLClass::instance->_8 = 0;
+
+ this->removeMyActivePhysics();
+ this->timer = 0;
+ StopBGMMusic();
+
+ dStage32C_c::instance->freezeMarioBossFlag = 1;
+
+ }
+ void daPodouble::executeState_Outro() {
+
+ if (this->dying == 1) {
+ if (this->timer > 180) {
+ ExitStage(WORLD_MAP, 0, BEAT_LEVEL, MARIO_WIPE);
+ }
+
+ if (this->timer == 60) {
+
+ UpdateGameMgr();
+
+ if (GetSpecificPlayerActor(0) != 0) {
+ PlaySound(this, SE_VOC_MA_CLEAR_BOSS);
+ // Send PlBase into DemoGoal State here, kthxbai
+ }
+
+ if (GetSpecificPlayerActor(1) != 0) {
+ PlaySound(this, SE_VOC_LU_CLEAR_BOSS);
+ // Send PlBase into DemoGoal State here, kthxbai
+ }
+
+ if (GetSpecificPlayerActor(2) != 0) {
+ PlaySound(this, SE_VOC_KO_CLEAR_BOSS);
+ // Send PlBase into DemoGoal State here, kthxbai
+ }
+
+ if (GetSpecificPlayerActor(3) != 0) {
+ PlaySound(this, SE_VOC_KO2_CLEAR_BOSS);
+ // Send PlBase into DemoGoal State here, kthxbai
+ }
+ }
+
+ this->timer += 1;
+ return;
+ }
+
+ if (this->scale.x > 0.1) {
+
+ PlaySound(this, SE_EMY_BUBBLE_EXTINCT);
+
+ // Adjust this to equal the scale of your boss / 80.
+ this->scale.x -= 0.04375;
+ this->scale.y -= 0.04375;
+ this->scale.z -= 0.04375;
+
+ if (this->timer == 30) {
+ CreateEffect(&this->pos, &(S16Vec){0,0,0}, &(Vec){2.0, 2.0, 2.0}, 756);
+ CreateEffect(&this->pos, &(S16Vec){0,0,0}, &(Vec){2.0, 2.0, 2.0}, 801);
+ CreateEffect(&this->pos, &(S16Vec){0,0,0}, &(Vec){2.0, 2.0, 2.0}, 957);
+ this->timer = 0;
+ }
+
+ this->timer += 1;
+ }
+ else {
+ this->scale.x = 0.0;
+ this->scale.y = 0.0;
+ this->scale.z = 0.0;
+
+ CreateEffect(&this->pos, &(S16Vec){0,0,0}, &(Vec){2.0, 2.0, 2.0}, 588);
+ this->dying = 1;
+ this->timer = 0;
+
+ PlaySound(this, STRM_BGM_SHIRO_BOSS_CLEAR);
+ MakeMarioEnterDemoMode();
+ }
+ }
+ void daPodouble::endState_Outro() { }
+
+
+
+///////////////
+// SyncDie State
+///////////////
+ void daPodouble::beginState_SyncDie() {
+
+ this->removeMyActivePhysics();
+ this->timer = 0;
+ }
+ void daPodouble::executeState_SyncDie() {
+
+ if (this->dying == 1) { return; }
+
+ if (this->scale.x > 0.1) {
+
+ PlaySound(this, SE_EMY_BUBBLE_EXTINCT);
+
+ // Adjust this to equal the scale of your boss / 80.
+ this->scale.x -= 0.04375;
+ this->scale.y -= 0.04375;
+ this->scale.z -= 0.04375;
+
+ if (this->timer == 30) {
+ CreateEffect(&this->pos, &(S16Vec){0,0,0}, &(Vec){2.0, 2.0, 2.0}, 756);
+ CreateEffect(&this->pos, &(S16Vec){0,0,0}, &(Vec){2.0, 2.0, 2.0}, 801);
+ CreateEffect(&this->pos, &(S16Vec){0,0,0}, &(Vec){2.0, 2.0, 2.0}, 957);
+ this->timer = 0;
+ }
+
+ this->timer += 1;
+ }
+ else {
+ this->scale.x = 0.0;
+ this->scale.y = 0.0;
+ this->scale.z = 0.0;
+
+ CreateEffect(&this->pos, &(S16Vec){0,0,0}, &(Vec){2.0, 2.0, 2.0}, 588);
+ this->dying = 1;
+ this->timer = 0;
+ }
+ }
+ void daPodouble::endState_SyncDie() { }