#include #include #include #include #include #include "effects.h" #include "player.h" class daRamboo_c : public dEn_c { int onCreate(); int onDelete(); int onExecute(); int onDraw(); mHeapAllocator_c allocator; m3d::mdl_c bodyModel; m3d::mdl_c hideModel; m3d::mdl_c fogModel; nw4r::g3d::ResFile resFile; m3d::anmChr_c anmFog; m3d::anmChr_c anmWaitA; m3d::anmChr_c anmShayA; m3d::anmChr_c anmWaitB; m3d::anmChr_c anmShayB; nw4r::g3d::ResAnmTexSrt resTexSrt; m3d::anmTexSrt_c fogSrt; int timer; int ytimer; char Hiding; char dying; float Baseline; u64 eventFlag; static daRamboo_c *build(); void bindAnimChr_and_setUpdateRates(const char* name, m3d::anmChr_c animationChr, m3d::mdl_c model, float rate); 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 collisionCat9_RollingObject(ActivePhysics *apThis, ActivePhysics *apOther); void collisionCat13_Hammer(ActivePhysics *apThis, ActivePhysics *apOther); USING_STATES(daRamboo_c); DECLARE_STATE(Grow); DECLARE_STATE(Advance); DECLARE_STATE(Wait); DECLARE_STATE(Flee); DECLARE_STATE(Outro); }; daRamboo_c *daRamboo_c::build() { void *buffer = AllocFromGameHeap1(sizeof(daRamboo_c)); return new(buffer) daRamboo_c; } extern "C" void *HandleXSpeed(daRamboo_c *); extern "C" void *HandleYSpeed(daRamboo_c *); extern "C" void *UpdateObjectPosBasedOnSpeedValues_real(daRamboo_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(daRamboo_c *, Vec pos); extern "C" dStageActor_c *GetSpecificPlayerActor(int number); extern "C" void *PlaySound(daRamboo_c *, int soundID); CREATE_STATE(daRamboo_c, Grow); CREATE_STATE(daRamboo_c, Advance); CREATE_STATE(daRamboo_c, Wait); CREATE_STATE(daRamboo_c, Flee); CREATE_STATE(daRamboo_c, Outro); struct EventTable_t { u64 events; // ... }; extern EventTable_t *EventTable; void daRamboo_c::playerCollision(ActivePhysics *apThis, ActivePhysics *apOther) { this->_vf220(apOther->owner); OSReport("I hit Mario."); } void daRamboo_c::collisionCat1_Fireball_E_Explosion(ActivePhysics *apThis, ActivePhysics *apOther) { OSReport("Hit Fireball"); CreateEffect(378, &apOther->owner->pos, &(S16Vec){0,0,0}, &(Vec){0.5, 0.5, 0.5}); this->pos.x += 6.0; } bool daRamboo_c::collisionCat2_IceBall_15_YoshiIce(ActivePhysics *apThis, ActivePhysics *apOther) { OSReport("Hit Iceball"); return false; } void daRamboo_c::collisionCat9_RollingObject(ActivePhysics *apThis, ActivePhysics *apOther) { OSReport("Hit Rolling Object"); if (apOther->owner->name == 412) { // Check if it's a glow block CreateEffect(378, &apOther->owner->pos); CreateEffect(380, &apOther->owner->pos); doStateChange(&StateID_Flee); apOther->owner->Delete(); } } void daRamboo_c::collisionCat13_Hammer(ActivePhysics *apThis, ActivePhysics *apOther) { OSReport("Hit Hammer"); } void daRamboo_c::bindAnimChr_and_setUpdateRates(const char* name, m3d::anmChr_c animationChr, m3d::mdl_c model, float rate) { nw4r::g3d::ResAnmChr anmChr = this->resFile.GetResAnmChr(name); animationChr.bind(&model, anmChr, 1); model.bindAnim(&animationChr, 0.0); animationChr.setUpdateRate(rate); } void daRamboo_c::setupModels() { allocator.link(-1, GameHeaps[0], 0, 0x20); this->resFile.data = getResource("teresa", "g3d/teresa.brres"); bool ret; nw4r::g3d::ResMdl mdl = this->resFile.GetResMdl("fog"); this->fogModel.setup(mdl, &allocator, 0x224, 1, 0); SetupTextures_Enemy(&this->fogModel, 0); nw4r::g3d::ResAnmChr anmChr = this->resFile.GetResAnmChr("fog"); ret = this->anmFog.setup(mdl, anmChr, &this->allocator, 0); nw4r::g3d::ResMdl mdlB = this->resFile.GetResMdl("teresaA"); this->bodyModel.setup(mdlB, &allocator, 0x224, 1, 0); SetupTextures_Enemy(&this->bodyModel, 0); nw4r::g3d::ResAnmChr anmChrC = this->resFile.GetResAnmChr("shay_teresaA"); ret = this->anmShayA.setup(mdlB, anmChrC, &this->allocator, 0); nw4r::g3d::ResAnmChr anmChrD = this->resFile.GetResAnmChr("wait"); ret = this->anmWaitA.setup(mdlB, anmChrD, &this->allocator, 0); nw4r::g3d::ResMdl mdlC = this->resFile.GetResMdl("teresaB"); this->hideModel.setup(mdlC, &allocator, 0x224, 1, 0); SetupTextures_Enemy(&this->hideModel, 0); nw4r::g3d::ResAnmChr anmChrE = this->resFile.GetResAnmChr("shay_teresaB"); ret = this->anmShayB.setup(mdlC, anmChrE, &this->allocator, 0); nw4r::g3d::ResAnmChr anmChrF = this->resFile.GetResAnmChr("shay_teresaB_wait"); ret = this->anmWaitB.setup(mdlC, anmChrF, &this->allocator, 0); nw4r::g3d::ResAnmTexSrt anmSrt = this->resFile.GetResAnmTexSrt("fog"); this->resTexSrt = anmSrt; //setup(ResMdl mdl, ResAnmTexSrt anmSrt, mAllocator* allocator, void* NULL, int count); ret = this->fogSrt.setup(mdl, anmSrt, &this->allocator, 0, 1); //setEntryByte34(char toSet, int which); this->fogSrt.setEntryByte34(0, 0); allocator.unlink(); } int daRamboo_c::onCreate() { OSReport("Creating the Ramboo Model"); setupModels(); OSReport("Setting Ramboo's Size to 16.0"); this->scale = (Vec){2.0, 2.0, 2.0}; OSReport("Creating Ramboo's Physics Struct"); ActivePhysics::Info HitMeBaby; HitMeBaby.xDistToCenter = 160.0; HitMeBaby.yDistToCenter = -80.0; HitMeBaby.xDistToEdge = 148.0; HitMeBaby.yDistToEdge = 148.0; HitMeBaby.category1 = 0x3; HitMeBaby.category2 = 0x0; HitMeBaby.bitfield1 = 0x4F; HitMeBaby.bitfield2 = 0x222; 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->Baseline = this->pos.y; 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->direction = 0; // Heading left. this->Hiding = 0; this->dying = 0; this->speed.x = 0.0; this->ytimer = 0; char eventNum = (this->settings >> 16) & 0xFF; OSReport("Event to activate: %d", eventNum); this->eventFlag = (u64)1 << (eventNum - 1); nw4r::g3d::ResAnmChr anmChr = this->resFile.GetResAnmChr("fog"); this->anmFog.bind(&this->fogModel, anmChr, 1); this->fogModel.bindAnim(&this->anmFog, 0.0); this->anmFog.setUpdateRate(1.0); nw4r::g3d::ResAnmTexSrt anmSrt = this->resFile.GetResAnmTexSrt("fog"); //bindEntry(mdl_c* model, ResAnmTexSrt anmSrt, int which, int playState?); this->fogSrt.bindEntry(&this->fogModel, anmSrt, 0, 1); this->fogModel.bindAnim(&this->fogSrt, 1.0); //setFrameForEntry(float frame, int which); this->fogSrt.setFrameForEntry(1.0, 0); //setUpdateRateForEntry(float rate, int which); this->fogSrt.setUpdateRateForEntry(1.0, 0); OSReport("Setting the State"); doStateChange(&StateID_Grow); OSReport("Going to Execute Ramboo"); this->onExecute(); return true; } int daRamboo_c::onDelete() { return true; } int daRamboo_c::onExecute() { acState.execute(); updateModelMatrices(); this->fogModel._vf1C(); if(this->anmFog.isAnimationDone()) this->anmFog.setCurrentFrame(0.0); this->fogSrt.process(); if(this->fogSrt.isEntryAnimationDone(0)) this->fogSrt.setFrameForEntry(1.0, 0); if (this->aPhysics.result1 == 1) { char PlayerID = NearestPlayer(this); dStageActor_c *Player = GetSpecificPlayerActor(PlayerID); this->_vf220(Player); } if (EventTable->events & this->eventFlag) { doStateChange(&StateID_Outro); } return true; } int daRamboo_c::onDraw() { fogModel.scheduleForDrawing(); if (this->Hiding == 0) { bodyModel.scheduleForDrawing(); } else { hideModel.scheduleForDrawing(); } return true; } void daRamboo_c::updateModelMatrices() { // This won't work with wrap because I'm lazy. matrix.translation(pos.x + 160.0, pos.y + (scale.x * 12.0) - 80.0, pos.z); fogModel.setDrawMatrix(matrix); fogModel.setScale(&scale); fogModel.calcWorld(false); matrix.translation(pos.x + 160.0, pos.y - 80.0, pos.z + 200.0); matrix.applyRotationYXZ(&rot.x, &rot.y, &rot.z); if (this->Hiding == 0) { bodyModel.setDrawMatrix(matrix); bodyModel.setScale(&scale); bodyModel.calcWorld(false); } else { hideModel.setDrawMatrix(matrix); hideModel.setScale(&scale); hideModel.calcWorld(false); } } // Grow State void daRamboo_c::beginState_Grow() { OSReport("Growing when Kameck Tells me to."); this->timer = 0; // PlaySound(this, SE_BOSS_ROY_MAGIC_MAKE_FAST); } void daRamboo_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.175; // yPosScaling = 0; float modifier; modifier = 2.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_CS_TERESA_BRING_IT); doStateChange(&StateID_Advance); } } void daRamboo_c::endState_Grow() { this->Baseline = this->pos.y; // StopSound(SE_BOSS_ROY_MAGIC_MAKE_FAST); OSReport("OK. All grown up now."); } // Advance State void daRamboo_c::beginState_Advance() { OSReport("Charge!"); this->speed.y = 0; this->speed.z = 0; this->timer = 0; nw4r::g3d::ResAnmChr anmChr = this->resFile.GetResAnmChr("wait"); this->anmWaitA.bind(&this->bodyModel, anmChr, 1); this->bodyModel.bindAnim(&this->anmWaitA, 0.0); this->anmWaitA.setUpdateRate(1.0); } void daRamboo_c::executeState_Advance() { this->bodyModel._vf1C(); if (this->anmWaitA.isAnimationDone()) { this->anmWaitA.setCurrentFrame(0.0); } this->pos.x -= this->timer / 48.0; this->pos.y = this->Baseline + sin(this->ytimer * 3.14 / 192) * 36; if (this->timer >= 48) { this->timer = 47; } if (this->ytimer >= 384) { this->ytimer = 0; } PlaySound(this, SE_EMY_TERESA); this->timer += 1; this->ytimer += 1; } void daRamboo_c::endState_Advance() { OSReport("Ouch. Stop Charging."); } // Wait State void daRamboo_c::beginState_Wait() { OSReport("Waiting"); this->timer = 0; PlaySound(this, SE_EMY_TERESA_STOP); } void daRamboo_c::executeState_Wait() { if (this->timer < 90) { this->hideModel._vf1C(); } if (this->timer > 55) { this->bodyModel._vf1C(); } if (this->timer == 70) { this->Hiding = 0; nw4r::g3d::ResAnmChr anmChr = this->resFile.GetResAnmChr("shay_teresaA"); this->anmShayA.bind(&this->bodyModel, anmChr, 1); this->bodyModel.bindAnim(&this->anmShayA, 0.0); this->anmShayA.setUpdateRate(1.0); } if (this->timer == 55) { nw4r::g3d::ResAnmChr anmChrB = this->resFile.GetResAnmChr("shay_teresaB"); this->anmShayB.bind(&this->hideModel, anmChrB, 1); this->hideModel.bindAnim(&this->anmShayB, 0.0); this->anmShayB.setUpdateRate(1.0); } if (this->anmShayB.isAnimationDone()) { PlaySound(this, SE_EMY_CS_TERESA_BEAT_YOU); doStateChange(&StateID_Advance); } this->timer += 1; } void daRamboo_c::endState_Wait() { this->Hiding = 0; nw4r::g3d::ResAnmChr anmChr = this->resFile.GetResAnmChr("shay_teresaA"); this->anmShayA.bind(&this->bodyModel, anmChr, 1); this->bodyModel.bindAnim(&this->anmShayA, 0.0); this->anmShayA.setUpdateRate(1.0); OSReport("No more bouncing."); } // Flee State void daRamboo_c::beginState_Flee() { OSReport("Damnit that hurt."); this->timer = 0; } void daRamboo_c::executeState_Flee() { this->hideModel._vf1C(); if (this->timer == 10) { this->Hiding = 1; nw4r::g3d::ResAnmChr anmChr = this->resFile.GetResAnmChr("shay_teresaB_wait"); this->anmWaitB.bind(&this->hideModel, anmChr, 1); this->hideModel.bindAnim(&this->anmWaitB, 0.0); this->anmWaitB.setUpdateRate(1.0); } this->pos.x += (60 - this->timer) / 6; if ((this->timer > 60) && (this->anmWaitB.isAnimationDone())) { doStateChange(&StateID_Wait); } this->timer += 1; } void daRamboo_c::endState_Flee() { OSReport("Ugh, so dizzy."); } void daRamboo_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 daRamboo_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->timer < 81) { 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 daRamboo_c::endState_Outro() { }