#include #include #include #include #include #include "effects.h" #include "player.h" class daBalboa_c : public dEn_c { int onCreate(); int onDelete(); int onExecute(); int onDraw(); mHeapAllocator_c allocator; m3d::mdl_c bodyModel; m3d::mdl_c manholeModel; m3d::mdl_c holeModel; nw4r::g3d::ResFile resFile; m3d::anmChr_c anmDead; m3d::anmChr_c anmDead_2; m3d::anmChr_c anmGo_out_ed; m3d::anmChr_c anmGo_out_st; m3d::anmChr_c anmThrow_1; m3d::anmChr_c anmThrow_2; m3d::anmChr_c anmThrow_3; m3d::anmChr_c anmThrow_4Left; m3d::anmChr_c anmThrow_4Right; m3d::anmChr_c anmThrow_5; int timer; int damage; float Baseline; float dying; Vec PopUp [4]; char throwCount; char upsideDown; static daBalboa_c *build(); void setupModels(); void updateModelMatrices(); 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 collisionCatD_GroundPound(ActivePhysics *apThis, ActivePhysics *apOther); void collisionCat9_RollingObject(ActivePhysics *apThis, ActivePhysics *apOther); void collisionCat13_Hammer(ActivePhysics *apThis, ActivePhysics *apOther); void collisionCat7_WMWaggleWater(ActivePhysics *apThis, ActivePhysics *apOther); void collisionCat7_WMWaggleWaterYoshi(ActivePhysics *apThis, ActivePhysics *apOther); USING_STATES(daBalboa_c); DECLARE_STATE(Grow); DECLARE_STATE(ManholeUp); DECLARE_STATE(HeadPoke); DECLARE_STATE(AllOut); DECLARE_STATE(ThrowHoming); DECLARE_STATE(ThrowWrench); DECLARE_STATE(BackDown); DECLARE_STATE(Outro); }; daBalboa_c *daBalboa_c::build() { void *buffer = AllocFromGameHeap1(sizeof(daBalboa_c)); return new(buffer) daBalboa_c; } extern "C" u32 GenerateRandomNumber(int max); extern "C" dStageActor_c *CreateActor(u16 classID, int settings, Vec pos, char rot, char layer); extern "C" u8 dSprite_c__getXDirectionOfFurthestPlayerRelativeToVEC3(daBalboa_c *, Vec pos); extern "C" dStageActor_c *GetSpecificPlayerActor(int number); extern "C" void *PlaySound(daBalboa_c *, int soundID); extern "C" char usedForDeterminingStatePress_or_playerCollision(dEn_c* t, ActivePhysics *apThis, ActivePhysics *apOther, int unk1); CREATE_STATE(daBalboa_c, Grow); CREATE_STATE(daBalboa_c, ManholeUp); CREATE_STATE(daBalboa_c, HeadPoke); CREATE_STATE(daBalboa_c, AllOut); CREATE_STATE(daBalboa_c, ThrowHoming); CREATE_STATE(daBalboa_c, ThrowWrench); CREATE_STATE(daBalboa_c, BackDown); CREATE_STATE(daBalboa_c, Outro); void daBalboa_c::playerCollision(ActivePhysics *apThis, ActivePhysics *apOther) { char ret = usedForDeterminingStatePress_or_playerCollision(this, apThis, apOther, 0); if(ret == 1) { // regular jump apOther->someFlagByte |= 2; OSReport("ret == 1; regular jump;\n"); } else if(ret == 3) { // spinning apOther->someFlagByte |= 2; OSReport("ret == 3; spinning collision;\n"); } else if(ret == 0) { OSReport("calling dEn_c::playerCollsiion(apThis, apOther);\n"); this->dEn_c::playerCollision(apThis, apOther); this->_vf220(apOther->owner); } else if(ret == 2) { OSReport("Y U USIN' MINIMARIO?\n"); this->dEn_c::playerCollision(apThis, apOther); this->_vf220(apOther->owner); } else { OSReport("usedForDeter...() returned %d\n", ret); } //FIXME hack to make multiple playerCollisions work this->isDead = 0; this->flags_4FC |= (1<<(31-7)); if(apOther->owner->which_player > 3) { OSReport("!!!ATTENTION!!!\napOther->owner->which_player > 3\n"); }else{ this->counter_504[apOther->owner->which_player] = 0; } } void daBalboa_c::collisionCat7_WMWaggleWater(ActivePhysics *apThis, ActivePhysics *apOther) { this->damage -= 1; apOther->someFlagByte |= 2; // Create a huge hit effect and play a nice sound // goto a get hurt state where he does his dance and then retreats underground // Prevent him from getting hurt during his dancing if (this->damage == 0) { doStateChange(&StateID_Outro); } } void daBalboa_c::collisionCat1_Fireball_E_Explosion(ActivePhysics *apThis, ActivePhysics *apOther) { } bool daBalboa_c::collisionCat2_IceBall_15_YoshiIce(ActivePhysics *apThis, ActivePhysics *apOther) { OSReport("Hit Iceball"); return false; } void daBalboa_c::collisionCat9_RollingObject(ActivePhysics *apThis, ActivePhysics *apOther) { } void daBalboa_c::collisionCat13_Hammer(ActivePhysics *apThis, ActivePhysics *apOther) { OSReport("Hit Hammer"); } void daBalboa_c::setupModels() { allocator.link(-1, GameHeaps[0], 0, 0x20); nw4r::g3d::ResMdl mdl; nw4r::g3d::ResAnmChr anmChr; this->resFile.data = getResource("choropoo", "g3d/choropoo.brres"); mdl = this->resFile.GetResMdl("manhole"); this->manholeModel.setup(mdl, &allocator, 0x224, 1, 0); SetupTextures_Enemy(&this->manholeModel, 0); mdl = this->resFile.GetResMdl("choropoo_hole"); this->holeModel.setup(mdl, &allocator, 0x224, 1, 0); SetupTextures_Enemy(&this->holeModel, 0); mdl = this->resFile.GetResMdl("choropoo"); this->bodyModel.setup(mdl, &allocator, 0x224, 1, 0); SetupTextures_Enemy(&this->bodyModel, 0); anmChr = this->resFile.GetResAnmChr("dead"); this->anmDead.setup(mdl, anmChr, &this->allocator, 0); anmChr = this->resFile.GetResAnmChr("dead_2"); this->anmDead_2.setup(mdl, anmChr, &this->allocator, 0); anmChr = this->resFile.GetResAnmChr("go_out_ed"); this->anmGo_out_ed.setup(mdl, anmChr, &this->allocator, 0); anmChr = this->resFile.GetResAnmChr("go_out_st"); this->anmGo_out_st.setup(mdl, anmChr, &this->allocator, 0); anmChr = this->resFile.GetResAnmChr("throw_1"); this->anmThrow_1.setup(mdl, anmChr, &this->allocator, 0); anmChr = this->resFile.GetResAnmChr("throw_2"); this->anmThrow_2.setup(mdl, anmChr, &this->allocator, 0); anmChr = this->resFile.GetResAnmChr("throw_3"); this->anmThrow_3.setup(mdl, anmChr, &this->allocator, 0); anmChr = this->resFile.GetResAnmChr("throw_4_left_hand"); this->anmThrow_4Left.setup(mdl, anmChr, &this->allocator, 0); anmChr = this->resFile.GetResAnmChr("throw_4_right_hand"); this->anmThrow_4Right.setup(mdl, anmChr, &this->allocator, 0); anmChr = this->resFile.GetResAnmChr("throw_5"); this->anmThrow_5.setup(mdl, anmChr, &this->allocator, 0); allocator.unlink(); } // Animation Order... // AppearLittle - Throw One, sound 0x21F // Search - Throw two // AppearFull - Throw 3 and sound 0x220 // Attack - Throw 4 // Disappear - Throw 5 int daBalboa_c::onCreate() { OSReport("Creating the Balboa Model"); setupModels(); OSReport("Setting Balboa's Size to 4.0"); this->scale = (Vec){1.0, 1.0, 1.0}; OSReport("Creating Balboa's Physics Struct"); ActivePhysics::Info HitMeBaby; HitMeBaby.xDistToCenter = 0.0; HitMeBaby.yDistToCenter = 36.0; HitMeBaby.xDistToEdge = 24.0; HitMeBaby.yDistToEdge = 32.0; HitMeBaby.category1 = 0x3; HitMeBaby.category2 = 0x0; HitMeBaby.bitfield1 = 0x4F; HitMeBaby.bitfield2 = 0xFFBAFFFE; HitMeBaby.unkShort1C = 0; HitMeBaby.callback = &dEn_c::collisionCallback; OSReport("Making the Physics Class and adding to the list"); this->aPhysics.initWithStruct(this, &HitMeBaby); this->aPhysics.addToList(); OSReport("Setting up the Box of Goodies"); this->rot.x = 0; // X is vertical axis this->rot.y = 0xE000; // Y is horizontal axis this->rot.z = 0; // Z is ... an axis >.> this->upsideDown = 0; this->direction = 0; // Heading left. this->pos.z = -800.0; this->pos.y -= 8.0; this->damage = 3; this->PopUp[0] = (Vec){this->pos.x, this->pos.y - 72.0, this->pos.z}; this->PopUp[1] = (Vec){this->pos.x - 224.0, this->pos.y - 72.0, this->pos.z}; this->PopUp[2] = (Vec){this->pos.x, this->pos.y + 248.0, this->pos.z}; this->PopUp[3] = (Vec){this->pos.x - 224.0, this->pos.y + 248.0, this->pos.z}; this->PopUp[4] = (Vec){this->pos.x - 112.0, this->pos.y - 40.0, this->pos.z}; OSReport("Setting the State"); doStateChange(&StateID_Grow); OSReport("Going to Execute Balboa"); this->onExecute(); return true; } int daBalboa_c::onDelete() { return true; } int daBalboa_c::onExecute() { acState.execute(); updateModelMatrices(); return true; } int daBalboa_c::onDraw() { bodyModel.scheduleForDrawing(); return true; } void daBalboa_c::updateModelMatrices() { // This won't work with wrap because I'm lazy. 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); } // Grow State void daBalboa_c::beginState_Grow() { OSReport("Growing when Kameck Tells me to."); this->timer = 0; } void daBalboa_c::executeState_Grow() { this->timer = this->timer + 1; float scaleSpeed, yPosScaling; if (this->timer == 60) { PlaySound(this, SE_BOSS_IGGY_WANWAN_TO_L); } if ((this->timer > 60) && (this->timer < 140)) { scaleSpeed = 0.025; // yPosScaling = 0; float modifier; modifier = 1.0 + ((this->timer - 60) * scaleSpeed); this->scale = (Vec){modifier, modifier, modifier}; // this->pos.y = this->pos.y + (yPosScaling/80); } if (this->timer > 170) { PlaySound(this, SE_EMY_CHOROPU_BOUND); this->upsideDown = 0; doStateChange(&StateID_BackDown); } } void daBalboa_c::endState_Grow() { OSReport("OK. All grown up now."); } // ManholeUp State void daBalboa_c::beginState_ManholeUp() { nw4r::g3d::ResAnmChr anmChr = this->resFile.GetResAnmChr("throw_1"); this->anmThrow_1.bind(&this->bodyModel, anmChr, 1); this->bodyModel.bindAnim(&this->anmThrow_1, 0.0); this->anmThrow_1.setUpdateRate(1.0); this->timer = 0; int randChoice; randChoice = GenerateRandomNumber(5); this->pos = this->PopUp[randChoice]; if (randChoice == 0) { // On the left side! this->rot.y = 0xE000; this->rot.z = 0; this->upsideDown = 0; this->direction = 0; } else if (randChoice == 1) { // On the right side! this->rot.y = 0x2000; this->rot.z = 0; this->upsideDown = 0; this->direction = 1; } else if (randChoice == 2) { // On the right ceiling! this->rot.y = 0xE000; this->rot.z = 0x8000; this->upsideDown = 1; this->direction = 0; } else if (randChoice == 3) { // On the left ceiling! this->rot.y = 0x2000; this->rot.z = 0x8000; this->upsideDown = 1; this->direction = 1; } else if (randChoice == 4) { // In the Center! char PlayerID = NearestPlayer(this); dStageActor_c *Player = GetSpecificPlayerActor(PlayerID); this->upsideDown = 0; this->rot.z = 0; if (Player->pos.x < this->pos.x) { this->rot.y = 0xE000; this->direction = 0; } else { this->rot.y = 0x2000; this->direction = 1; } } PlaySound(this, 0x21F); } void daBalboa_c::executeState_ManholeUp() { this->bodyModel._vf1C(); if (this->timer < 30) { if (this->upsideDown == 0) { this->pos.y += 0.6; } // Height is 72 pixels, move up 18 pixels. else { this->pos.y -= 0.6; } // Height is 72 pixels, move down 18 pixels. } if (this->timer > 60) { doStateChange(&StateID_HeadPoke); } this->timer += 1; } void daBalboa_c::endState_ManholeUp() { } // HeadPoke State void daBalboa_c::beginState_HeadPoke() { nw4r::g3d::ResAnmChr anmChr = this->resFile.GetResAnmChr("throw_2"); this->anmThrow_2.bind(&this->bodyModel, anmChr, 1); this->bodyModel.bindAnim(&this->anmThrow_2, 0.0); this->anmThrow_2.setUpdateRate(1.0); this->timer = 0; } void daBalboa_c::executeState_HeadPoke() { if (this->timer < 30) { if (this->upsideDown == 0) { this->pos.y += 0.6; } // Height is 72 pixels, move up 20 pixels. else { this->pos.y -= 0.6; } // Height is 72 pixels, move down 20 pixels. } if (this->timer > 90) { doStateChange(&StateID_AllOut); } this->timer += 1; this->bodyModel._vf1C(); } void daBalboa_c::endState_HeadPoke() { } // AllOut State void daBalboa_c::beginState_AllOut() { nw4r::g3d::ResAnmChr anmChr = this->resFile.GetResAnmChr("throw_3"); this->anmThrow_3.bind(&this->bodyModel, anmChr, 1); this->bodyModel.bindAnim(&this->anmThrow_3, 0.0); this->anmThrow_3.setUpdateRate(1.0); this->timer = 0; PlaySound(this, 0x220); } void daBalboa_c::executeState_AllOut() { this->bodyModel._vf1C(); if (this->timer < 30) { if (this->upsideDown == 0) { this->pos.y += 1.2; } // Height is 72 pixels, move up last 36 pixels. else { this->pos.y -= 1.2; } // Height is 72 pixels, move down last 36 pixels. } if (this->timer > 45) { int randChoice; randChoice = GenerateRandomNumber(2); if (randChoice == 0) { doStateChange(&StateID_ThrowHoming); } else { doStateChange(&StateID_ThrowWrench); } } this->timer += 1; } void daBalboa_c::endState_AllOut() { } // ThrowHoming State void daBalboa_c::beginState_ThrowHoming() { if (this->direction == 0) { nw4r::g3d::ResAnmChr anmChr = this->resFile.GetResAnmChr("throw_4_left_hand"); this->anmThrow_4Left.bind(&this->bodyModel, anmChr, 1); this->bodyModel.bindAnim(&this->anmThrow_4Left, 0.0); this->anmThrow_4Left.setUpdateRate(1.0); } else { nw4r::g3d::ResAnmChr anmChr = this->resFile.GetResAnmChr("throw_4_right_hand"); this->anmThrow_4Right.bind(&this->bodyModel, anmChr, 1); this->bodyModel.bindAnim(&this->anmThrow_4Right, 0.0); this->anmThrow_4Right.setUpdateRate(1.0); } u32 settings; char dir; if (this->direction) { dir = 0; } else { dir = 1; } settings = (dir) | (this->upsideDown << 1); settings = settings | 0x10; CreateActor(544, settings, this->pos, 0, 0); this->timer = 0; } void daBalboa_c::executeState_ThrowHoming() { this->bodyModel._vf1C(); if (this->timer > 60) { doStateChange(&StateID_BackDown); } this->timer += 1; this->bodyModel._vf1C(); } void daBalboa_c::endState_ThrowHoming() { } // ThrowWrench State void daBalboa_c::beginState_ThrowWrench() { this->throwCount = 0; this->timer = 0; } void daBalboa_c::executeState_ThrowWrench() { if (this->timer > 60) { if (this->throwCount & 1) { nw4r::g3d::ResAnmChr anmChr = this->resFile.GetResAnmChr("throw_4_left_hand"); this->anmThrow_4Left.bind(&this->bodyModel, anmChr, 1); this->bodyModel.bindAnim(&this->anmThrow_4Left, 0.0); this->anmThrow_4Left.setUpdateRate(1.0); } else { nw4r::g3d::ResAnmChr anmChr = this->resFile.GetResAnmChr("throw_4_right_hand"); this->anmThrow_4Right.bind(&this->bodyModel, anmChr, 1); this->bodyModel.bindAnim(&this->anmThrow_4Right, 0.0); this->anmThrow_4Right.setUpdateRate(1.0); } u32 settings; u8 up = this->upsideDown; u8 throwc = this->throwCount; u8 dir; if (this->direction) { dir = 0; } else { dir = 1; } settings = (dir) | (up << 1); settings = settings | (throwc & 1 << 8); CreateActor(544, settings, this->pos, 0, 0); this->throwCount += 1; this->timer = 0; } if (this->throwCount > 4) { doStateChange(&StateID_BackDown); } this->timer += 1; this->bodyModel._vf1C(); } void daBalboa_c::endState_ThrowWrench() { } // BackDown State void daBalboa_c::beginState_BackDown() { nw4r::g3d::ResAnmChr anmChr = this->resFile.GetResAnmChr("throw_5"); this->anmThrow_5.bind(&this->bodyModel, anmChr, 1); this->bodyModel.bindAnim(&this->anmThrow_5, 0.0); this->anmThrow_5.setUpdateRate(1.0); this->timer = 0; PlaySound(this, 0x221); CreateEffect(&this->pos, &(S16Vec){0,0,0}, &(Vec){2.0, 1.0, 1.0}, 351); CreateEffect(&this->pos, &(S16Vec){0,0,0}, &(Vec){2.0, 1.0, 1.0}, 352); } void daBalboa_c::executeState_BackDown() { if (this->timer < 60) { if (this->upsideDown == 0) { this->pos.y -= 1.2; } // Height is 72 pixels, move down else { this->pos.y += 1.2; } // Height is 72 pixels, move up } if (this->timer > 90) { doStateChange(&StateID_ManholeUp); } this->timer += 1; this->bodyModel._vf1C(); } void daBalboa_c::endState_BackDown() { } void daBalboa_c::beginState_Outro() { this->removeMyActivePhysics(); this->timer = 0; this->rot.x = 0x0; // X is vertical axis this->rot.y = 0xE000; // Y is horizontal axis this->rot.z = 0x0; // Z is ... an axis >.> } void daBalboa_c::executeState_Outro() { if (this->dying == 1) { if (this->timer > 180) { ExitStage(WORLD_MAP, 0, BEAT_LEVEL, MARIO_WIPE); } if (this->timer == 60) { 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_BOSS_CMN_DAMAGE_LAST); PlaySound(this, SE_EMY_BIG_TERESA_DEAD); // Adjust this to equal the scale of your boss / 80. this->scale.x -= 0.175; this->scale.y -= 0.175; this->scale.z -= 0.175; this->pos.y += 2.0; Vec tempPos = (Vec){this->pos.x + 160.0, this->pos.y - 80.0, 5500.0}; if (this->timer == 30) { CreateEffect(&tempPos, &(S16Vec){0,0,0}, &(Vec){2.0, 2.0, 2.0}, 756); CreateEffect(&tempPos, &(S16Vec){0,0,0}, &(Vec){2.0, 2.0, 2.0}, 801); CreateEffect(&tempPos, &(S16Vec){0,0,0}, &(Vec){2.0, 2.0, 2.0}, 957); this->timer = 0; } } else { this->scale.x = 0.0; this->scale.y = 0.0; this->scale.z = 0.0; Vec tempPos = (Vec){this->pos.x + 160.0, this->pos.y - 80.0, 5500.0}; CreateEffect(&tempPos, &(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); } this->timer += 1; } void daBalboa_c::endState_Outro() { }