#include #include #include #include #include #include "effects.h" // Externs extern "C" int posIsInZone(Vec,float*,float*,u8 zone); extern "C" void* ScreenPositionClass; extern "C" void ShakeScreen(void*,int,int,int,int); // (ScreenPositionClass, some other ints - set the second one to 1 to shake it) extern "C" int SpawnThwompEffects(dEn_c *); extern "C" void* SoundRelatedClass; extern "C" Vec ConvertStagePositionIntoScreenPosition__Maybe(Vec); extern "C" void AnotherSoundRelatedFunction(void*,SFX,Vec,int); extern "C" void *PlaySound(dEn_c *, int soundID); extern "C" void *PlaySoundAsync(dEn_c *, int soundID); extern "C" dStageActor_c *GetSpecificPlayerActor(int number); extern "C" void *StopBGMMusic(); extern "C" void *StartBGMMusic(); extern "C" void *MakeMarioEnterDemoMode(); extern "C" void *MakeMarioExitDemoMode(); extern "C" void *UpdateGameMgr(); class daEnMegaDosun_c : public dEn_c { int onCreate(); int onDelete(); int onExecute(); int onDraw(); static daEnMegaDosun_c *build(); mHeapAllocator_c allocator; // _524 nw4r::g3d::ResFile resFile; // _540 m3d::mdl_c bodyModel; // _544 m3d::anmVis_c anmVis; // _584 u32 collision_struct[4]; // _5BC float shakePosXoffset; // _5CC shakePosXoffset u16 puruMoveCounter; // _5D8 u16 shakeIndex; // _5DA 0=shake,1=normal u32 countdownTimer; // _5DC int timer; char notFalling; char dying; float leftBuffer; float rightBuffer; float topBuffer; bool isOutofScreen; Vec OutOfScreenPosition; dEn_c *Kameck; void setupBodyModel(); void playerCollision(ActivePhysics *apThis, ActivePhysics *apOther); void collisionCat1_Fireball_E_Explosion(ActivePhysics *apThis, ActivePhysics *apOther); bool collisionCat2_IceBall_15_YoshiIce(ActivePhysics *apThis, ActivePhysics *apOther); void collisionCat7_WMWaggleWater(ActivePhysics *apThis, ActivePhysics *apOther); void collisionCat9_RollingObject(ActivePhysics *apThis, ActivePhysics *apOther); void collisionCat13_Hammer(ActivePhysics *apThis, ActivePhysics *apOther); void collisionCat14_YoshiFire(ActivePhysics *apThis, ActivePhysics *apOther); void collisionCatA_PenguinMario(ActivePhysics *apThis, ActivePhysics *apOther); USING_STATES(daEnMegaDosun_c); DECLARE_STATE(UpWait); DECLARE_STATE(DownMoveWait); DECLARE_STATE(PuruMove); DECLARE_STATE(DownMove); DECLARE_STATE(DownWait); DECLARE_STATE(UpMove); DECLARE_STATE(Grow); DECLARE_STATE(Outro); }; // States CREATE_STATE(daEnMegaDosun_c, UpWait); CREATE_STATE(daEnMegaDosun_c, DownMoveWait); CREATE_STATE(daEnMegaDosun_c, PuruMove); CREATE_STATE(daEnMegaDosun_c, DownMove); CREATE_STATE(daEnMegaDosun_c, DownWait); CREATE_STATE(daEnMegaDosun_c, UpMove); CREATE_STATE(daEnMegaDosun_c, Grow); CREATE_STATE(daEnMegaDosun_c, Outro); daEnMegaDosun_c *daEnMegaDosun_c::build() { void *buffer = AllocFromGameHeap1(sizeof(daEnMegaDosun_c)); return new(buffer) daEnMegaDosun_c; } // Collisions void daEnMegaDosun_c::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 < 4) { this->counter_504[apOther->owner->which_player] = 0; } } void daEnMegaDosun_c::collisionCat1_Fireball_E_Explosion(ActivePhysics *apThis, ActivePhysics *apOther) { } bool daEnMegaDosun_c::collisionCat2_IceBall_15_YoshiIce(ActivePhysics *apThis, ActivePhysics *apOther) { return false; } void daEnMegaDosun_c::collisionCat7_WMWaggleWater(ActivePhysics *apThis, ActivePhysics *apOther) { } void daEnMegaDosun_c::collisionCat9_RollingObject(ActivePhysics *apThis, ActivePhysics *apOther) { } void daEnMegaDosun_c::collisionCat13_Hammer(ActivePhysics *apThis, ActivePhysics *apOther) { } void daEnMegaDosun_c::collisionCat14_YoshiFire(ActivePhysics *apThis, ActivePhysics *apOther) { } void daEnMegaDosun_c::collisionCatA_PenguinMario(ActivePhysics *apThis, ActivePhysics *apOther) { } void daEnMegaDosun_c::setupBodyModel() { allocator.link(-1, GameHeaps[0], 0, 0x20); this->resFile.data = getResource("dossun", "g3d/t00.brres"); nw4r::g3d::ResMdl mdl = this->resFile.GetResMdl("dossun_big"); bodyModel.setup(mdl, &allocator, 0x60, 1, 0); SetupTextures_Enemy(&bodyModel, 0); nw4r::g3d::ResAnmVis anmRes = this->resFile.GetResAnmVis("dossun_big"); this->anmVis.setup(mdl, anmRes, &this->allocator, 0); this->anmVis.bind(&bodyModel, anmRes, 1); allocator.unlink(); } int daEnMegaDosun_c::onCreate() { OSReport("daEnMegaDosun::onCreate()\n"); this->setupBodyModel(); this->_36D = 0; // byte this->frzMgr.setSomething(1,1,1); //@0x809f5c5c this->pos.y -= 21.0; this->pos.z = -280.0; // behind layer1 (hides spikes) this->collision_struct[0] = 0x11804101; this->collision_struct[1] = 0xFFFE1000; this->collision_struct[2] = 0x0001F000; this->collision_struct[3] = 0x00005000; ActivePhysics::Info hm; hm.xDistToCenter = 0.0; hm.yDistToCenter = 41.0; hm.xDistToEdge = 36.0; hm.yDistToEdge = 38.0; hm.category1 = 0x03; hm.category2 = 0x00; hm.bitfield1 = 0x0000004F; hm.bitfield2 = 0x0000820E; hm.unkShort1C = 0x0100; hm.callback = &dEn_c::collisionCallback; this->aPhysics.initWithStruct(this, &hm); //u8 s3[] = {0,0,0,1,0xff,0xfe,0x10,0,0,1,0xf0,0,0,5,0x50,0}; u8 s3[] = {0,0,0,1,0xff,0xfe,0x10,0,0,1,0xf0,0,0xff,0xfe,0x10,0}; OSReport("this->collMgr.Init(this,(u8*)&this->collision_struct,(u8*)&s3,0);\n"); this->collMgr.Init(this,(u8*)&this->collision_struct,(u8*)&s3,0); this->pos_delta2.x = 0.0; this->pos_delta2.y = 36.0; this->pos_delta2.z = 0.0; this->_320 = 0.0; this->_324 = 48.0; OSReport("this->aPhysics.addToList();\n"); this->aPhysics.addToList(); this->scale.x = 1.0; this->scale.y = 1.0; this->scale.z = 1.0; this->max_speed.x = 0.0; this->max_speed.y = -8.0; this->max_speed.z = 0.0; this->y_speed_inc = -0.25; this->rot.x = 0; this->rot.y = 0; this->rot.z = 0; this->notFalling = 0; this->direction = 0; this->countdownTimer = 0; this->isOutofScreen = false; // Measured in half tiles this->leftBuffer = this->pos.x - (((float)((this->settings >> 24) & 0xFF) - 5.0) * 8.0); //nyb 5-6 LEFT this->rightBuffer = this->pos.x + (((float)((this->settings >> 16) & 0xFF) - 3.0) * 8.0); //nyb 7-8 RIGHT this->topBuffer = this->pos.y + (((float)((this->settings >> 8) & 0xFF) - 8.0) * 8.0); //nyb 9-10 TOP // Boss Thwomp settings // // nybble 5-6 - Left Buffer in half tiles (minimum is 5 due to thwomp width) // nybble 7-8 - Left Buffer in half tiles (minimum is 3 due to thwomp width) // nybble 9-10 - Top Buffer in half tiles (minimum is 8 due to thwomp height) // this->doStateChange(&StateID_Grow); this->onExecute(); return true; } int daEnMegaDosun_c::onExecute() { acState.execute(); if (this->isOutofScreen == false) { float rect[] = {this->_320, this->_324, this->spriteSomeRectX, this->spriteSomeRectY}; int ret = this->outOfZone(this->pos, (float*)&rect, this->currentZoneID); if(ret) { OSReport("daEnMegaDosun_c has left the building\n"); this->OutOfScreenPosition = this->pos; this->isOutofScreen = true; doStateChange(&StateID_Outro); } } return true; } int daEnMegaDosun_c::onDraw() { 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(); return true; } int daEnMegaDosun_c::onDelete() { OSReport("Deleting Thwompy\n"); return true; } // Grow State void daEnMegaDosun_c::beginState_Grow() { this->scale = (Vec){0.5, 0.5, 0.5}; this->timer = 0; // 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); } void daEnMegaDosun_c::executeState_Grow() { if (this->timer == 130) { Kameck->doStateChange(&daKameckDemo::StateID_DemoSt); } if (this->timer == 400) { Kameck->doStateChange(&daKameckDemo::StateID_DemoSt2); } this->timer = this->timer + 1; float scaleSpeed, yPosScaling; if (this->timer == 150) { PlaySound(this, SE_BOSS_IGGY_WANWAN_TO_L); } if ((this->timer > 150) && (this->timer < 230)) { scaleSpeed = 0.00625; float modifier; modifier = 0.5 + ((this->timer - 150) * scaleSpeed); this->scale = (Vec){modifier, modifier, modifier}; } 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 } if (this->timer > 420) { PlaySound(this, SE_EMY_BIG_DOSSUN); doStateChange(&StateID_UpMove); } } void daEnMegaDosun_c::endState_Grow() { // Clean up the flags and Kameck dStage32C_c::instance->freezeMarioBossFlag = 0; WLClass::instance->_8 = 1; MakeMarioExitDemoMode(); StartBGMMusic(); Kameck->Delete(1); } // StateID_UpWait void daEnMegaDosun_c::beginState_UpWait() { this->collision_struct[0] = 0x11804101; this->timer = 0; } void daEnMegaDosun_c::executeState_UpWait() { if(this->countdownTimer != 0) { this->countdownTimer--; return; } if (this->pos.x > this->rightBuffer) { CreateEffect(&(Vec){this->pos.x + 38.0, this->pos.y + 32.0, 5500.0}, &(S16Vec){0,0,0x4000}, &(Vec){1.0, 1.0, 1.0}, 364); PlaySoundAsync(this, SE_OBJ_TEKKYU_G_CRASH); this->direction = 0; } if (this->pos.x < this->leftBuffer) { CreateEffect(&(Vec){this->pos.x - 40.0, this->pos.y + 32.0, 5500.0}, &(S16Vec){0,0,0xC000}, &(Vec){1.0, 1.0, 1.0}, 364); PlaySoundAsync(this, SE_OBJ_TEKKYU_G_CRASH); this->direction = 1; } this->pos.x += (direction) ? 0.9 : -0.9; if (this->notFalling == 0) { if(this->CheckIfPlayerBelow(40.0, 256.0)) { this->doStateChange(&StateID_DownMoveWait); this->speed.y = 0.0; } } if (this->timer == 60) { this->notFalling = 0; } this->timer += 1; } void daEnMegaDosun_c::endState_UpWait() { this->notFalling = 1; return; } // StateID_DownMoveWait void daEnMegaDosun_c::beginState_DownMoveWait() { this->anmVis.playState = 1; this->bodyModel.bindAnim(&this->anmVis, 0.5); } void daEnMegaDosun_c::executeState_DownMoveWait() { if(this->anmVis.isAnimationDone()) this->doStateChange(&StateID_PuruMove); this->anmVis.process(); } void daEnMegaDosun_c::endState_DownMoveWait() { return; } // StateID_PuruMove void daEnMegaDosun_c::beginState_PuruMove() { this->puruMoveCounter = 8; this->shakeIndex = 0; } void daEnMegaDosun_c::executeState_PuruMove() { if(this->puruMoveCounter == 0) { this->shakePosXoffset = 0.0; this->doStateChange(&StateID_DownMove); return; } this->puruMoveCounter--; if(this->puruMoveCounter & 2 == 0) return; float _array[] = {2.0, 0.0}; this->shakeIndex ^= 1; this->shakePosXoffset = _array[this->shakeIndex]; } void daEnMegaDosun_c::endState_PuruMove() { return; } // StateID_DownMove void daEnMegaDosun_c::beginState_DownMove() { OSReport("beginState_DownMove()\n"); this->speed.y = 0.0; } void daEnMegaDosun_c::executeState_DownMove() { OSReport("executeState_DownMove()\n"); this->HandleYSpeed(); this->UpdateObjectPosBasedOnSpeedValuesReal(); //FIXME what do I do? - bottom detection int ret = this->collMgr.execute(); OSReport("collMgr Returns(): %08x\n", ret); if(!ret) return; if(!(ret & 0x400000)) { OSReport("doStateChange(&StateID_DownWait)\n"); this->doStateChange(&StateID_DownWait); this->countdownTimer = 0x40; this->speed.y = 0.0; ShakeScreen(ScreenPositionClass, 0, 1, 0, 0); } else { this->collision_struct[0] = 0x00000001; this->speed.y = 0.0; OSReport("ShakeScreen(%x,%d,%d,%d,%d)\n", ScreenPositionClass,0,1,0,0); ShakeScreen(ScreenPositionClass, 0, 1, 0, 0); this->collMgr.Clear2(); } SpawnThwompEffects(this); Vec p = ConvertStagePositionIntoScreenPosition__Maybe(this->pos); AnotherSoundRelatedFunction(SoundRelatedClass, SE_EMY_BIG_DOSSUN, p, 0); //SoundRelatedClass.AnotherSoundRelatedFunction(SE_EMY_BIG_DOSSUN, p, 0); } void daEnMegaDosun_c::endState_DownMove() { OSReport("endState_DownMove()\n"); return; } // StateID_DownWait void daEnMegaDosun_c::beginState_DownWait() { return; } void daEnMegaDosun_c::executeState_DownWait() { if(this->countdownTimer == 0) { this->doStateChange(&StateID_UpMove); } else { this->countdownTimer--; if(this->countdownTimer == 0x20) { this->anmVis.playState = 3; } } this->anmVis.process(); } void daEnMegaDosun_c::endState_DownWait() { return; } // StateID_UpMove void daEnMegaDosun_c::beginState_UpMove() { this->collMgr.Clear2(); } void daEnMegaDosun_c::executeState_UpMove() { // this->speed.y = 0.0; // this->UpdateObjectPosBasedOnSpeedValuesReal(); if (this->pos.y > this->topBuffer) { this->doStateChange(&StateID_UpWait); PlaySoundAsync(this, SE_OBJ_TEKKYU_L_CRASH); this->countdownTimer = 0xc; } else { this->pos.y += 1.5; } } void daEnMegaDosun_c::endState_UpMove() { return; } // Outro void daEnMegaDosun_c::beginState_Outro() { OSReport("Outro Being\n"); WLClass::instance->_4 = 5; WLClass::instance->_8 = 0; this->removeMyActivePhysics(); this->timer = 0; StopBGMMusic(); dStage32C_c::instance->freezeMarioBossFlag = 1; this->speed.y = 0.0; this->y_speed_inc = 0.0; } void daEnMegaDosun_c::executeState_Outro() { this->pos.y = this->OutOfScreenPosition.y + 280.0; if (this->timer == 0) { OSReport("Outro Play Sound\n"); PlaySound(this, SE_EMY_BIG_DOSSUN_DEAD); CreateEffect(&this->pos, &(S16Vec){0,0,0}, &(Vec){2.0, 2.0, 2.0}, 988); CreateEffect(&this->pos, &(S16Vec){0,0,0}, &(Vec){2.0, 2.0, 2.0}, 989); } if (this->timer == 60) { OSReport("Outro Play Fanfare\n"); PlaySound(this, STRM_BGM_SHIRO_BOSS_CLEAR); MakeMarioEnterDemoMode(); } if (this->timer == 120) { OSReport("Outro Play Victory Cry\n"); 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 } } if (this->timer > 240) { OSReport("Outro Out\n"); ExitStage(WORLD_MAP, 0, BEAT_LEVEL, MARIO_WIPE); } this->timer += 1; } void daEnMegaDosun_c::endState_Outro() { }