#include #include #include class daMrSun_c : public dEn_c { int onCreate(); int onDelete(); int onExecute(); int onDraw(); mHeapAllocator_c allocator; m3d::mdl_c model; float Baseline; float SwoopSlope; float SpiralLoop; float yThreshold; float yAccel; Vec swoopTarget; float slope; u32 timer; static daMrSun_c *build(); void updateModelMatrix(); USING_STATES(daMrSun_c); DECLARE_STATE(Follow); DECLARE_STATE(Swoop); DECLARE_STATE(Spiral); DECLARE_STATE(Spit); DECLARE_STATE(Spin); DECLARE_STATE(Wait); }; daMrSun_c *daMrSun_c::build() { void *buffer = AllocFromGameHeap1(sizeof(daMrSun_c)); return new(buffer) daMrSun_c; } extern "C" void *HandleXSpeed(daMrSun_c *); extern "C" void *HandleYSpeed(daMrSun_c *); extern "C" void *UpdateObjectPosBasedOnSpeedValues_real(daMrSun_c *); extern "C" u32 GenerateRandomNumber(int max); extern "C" u8 dSprite_c__getXDirectionOfFurthestPlayerRelativeToVEC3(daMrSun_c *, Vec pos); extern "C" dStageActor_c *CreateActor(u16 classID, int settings, Vec pos, char rot, char layer); extern "C" dStageActor_c *GetSpecificPlayerActor(int number); CREATE_STATE(daMrSun_c, Follow); CREATE_STATE(daMrSun_c, Swoop); CREATE_STATE(daMrSun_c, Spiral); CREATE_STATE(daMrSun_c, Spit); CREATE_STATE(daMrSun_c, Spin); #define ACTIVATE 1 #define DEACTIVATE 0 int daMrSun_c::onCreate() { OSReport("Creating the Mr.Sun Model"); allocator.link(-1, GameHeaps[0], 0, 0x20); nw4r::g3d::ResFile rf(getResource("bubble", "g3d/t00.brres")); model.setup(rf.GetResMdl("bubble"), &allocator, 0x224, 1, 0); SetupTextures_Enemy(&model, 0); allocator.unlink(); OSReport("Setting Mr.Sun's Size to 4.0"); this->scale = (Vec){4.0, 4.0, 4.0}; OSReport("Creating Mr.Sun's Physics Struct"); ActivePhysics::Info HitMeBaby; HitMeBaby.xDistToCenter = 0.0; HitMeBaby.yDistToCenter = 0.0; HitMeBaby.xDistToEdge = 32.0; HitMeBaby.yDistToEdge = 32.0; HitMeBaby.category1 = 0x3; HitMeBaby.category2 = 0x0; HitMeBaby.bitfield1 = 0x4F; HitMeBaby.bitfield2 = 0x820C; 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 Mr.Sun's Box of Goodies"); this->Baseline = this->pos.y; this->SwoopSlope = 0.0; this->SpiralLoop = 0; this->yThreshold = 10.0; this->yAccel = 0.2; this->timer = 0; OSReport("Setting Mr.Sun's State"); doStateChange(&StateID_Swoop); OSReport("Going to Execute Mr.Sun"); this->onExecute(); return true; } int daMrSun_c::onDelete() { return true; } int daMrSun_c::onExecute() { //OSReport("Oh Mr.Sun, Sun, Mr.Golden Sun"); acState.execute(); updateModelMatrix(); return true; } int daMrSun_c::onDraw() { model.scheduleForDrawing(); return true; } void daMrSun_c::updateModelMatrix() { // 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); model.setDrawMatrix(matrix); model.setScale(&scale); model.calcWorld(false); } // Follow State void daMrSun_c::beginState_Follow() { OSReport("Mr.Sun is following youuuuu."); this->timer = 0; } void daMrSun_c::executeState_Follow() { if (this->timer > 1000) this->doStateChange(&StateID_Wait); this->direction = dSprite_c__getXDirectionOfFurthestPlayerRelativeToVEC3(this, this->pos); if (this->direction == 0) { if (this->speed.x > 10.0) this->speed.x = this->speed.x + 0.1; } else { if (this->speed.x < -10.0) this->speed.x = this->speed.x - 0.1; } HandleXSpeed(this); if (this->pos.y > this->Baseline) { if (this->speed.y > -this->yThreshold) this->speed.y = this->speed.y - this->yAccel; } else if (this->pos.y < this->Baseline) { if (this->speed.y > -this->yThreshold) this->speed.y = this->speed.y + this->yAccel; } else { this->pos.y = this->Baseline; this->speed.y = 0; } HandleYSpeed(this); UpdateObjectPosBasedOnSpeedValues_real(this); this->timer = this->timer + 1; } void daMrSun_c::endState_Follow() { OSReport("Mr.Sun is coming for you."); } // Swoop State void daMrSun_c::beginState_Swoop() { OSReport("Swooping down from above, Mr.Sun falls down."); dStageActor_c *Player = GetSpecificPlayerActor(0); if (Player == 0) Player = GetSpecificPlayerActor(1); if (Player == 0) Player = GetSpecificPlayerActor(2); if (Player == 0) Player = GetSpecificPlayerActor(3); if (Player == 0) doStateChange(&StateID_Follow); this->swoopTarget = Player->pos; float relativeSunX = this->swoopTarget.x - this->pos.x; float relativeSunY = this->swoopTarget.y - this->pos.y; this->slope = relativeSunY / relativeSunX; } void daMrSun_c::executeState_Swoop() { if (this->pos.y > this->swoopTarget.y) doStateChange(&StateID_Follow); if (this->slope < 0.0) this->speed.x = this->speed.x + 0.2; if (this->slope > 0.0) this->speed.x = this->speed.x - 0.2; HandleXSpeed(this); HandleYSpeed(this); UpdateObjectPosBasedOnSpeedValues_real(this); } void daMrSun_c::endState_Swoop() { OSReport("Returning to the sky, Mr.Sun flies into the sunset."); this->swoopTarget = (Vec){0.0, 0.0, 0.0}; } // Spiral State void daMrSun_c::beginState_Spiral() { OSReport("Super Spiral Sunspot!"); } void daMrSun_c::executeState_Spiral() { if (this->SpiralLoop > (6.28 * 5)) doStateChange(&StateID_Follow); this->pos.x = this->SpiralLoop * cos(this->SpiralLoop); this->pos.y = this->SpiralLoop * sin(this->SpiralLoop); this->SpiralLoop = this->SpiralLoop + 0.1; } void daMrSun_c::endState_Spiral() { OSReport("Nightmare Spiral Attack Ends!"); } // Spit State void daMrSun_c::beginState_Spit() { OSReport("Goodness Gracious Great Balls of Fire!"); } void daMrSun_c::executeState_Spit() { if (this->timer > 1000) doStateChange(&StateID_Follow); dStageActor_c *spawner = CreateActor(107, 0, this->pos, 0, 0); spawner->speed.x = 10.0; spawner->speed.y = 10.0; spawner = CreateActor(107, 0, this->pos, 0, 0); spawner->speed.x = 8.0; spawner->speed.y = 5.0; spawner = CreateActor(107, 0, this->pos, 0, 0); spawner->speed.x = 4.0; spawner->speed.y = 0.0; this->timer = this->timer + 1; } void daMrSun_c::endState_Spit() { OSReport("Armageddon complete."); } // Spin State void daMrSun_c::beginState_Spin() { OSReport("Hoola hoola hoola hoop."); } void daMrSun_c::executeState_Spin() { if (this->timer > 1000) this->doStateChange(&StateID_Follow); this->direction = dSprite_c__getXDirectionOfFurthestPlayerRelativeToVEC3(this, this->pos); if (this->direction == 0) { if (this->speed.x > 10.0) this->speed.x = this->speed.x + 0.1; } else { if (this->speed.x < -10.0) this->speed.x = this->speed.x - 0.1; } HandleXSpeed(this); UpdateObjectPosBasedOnSpeedValues_real(this); this->timer = this->timer + 1; int direction; direction = GenerateRandomNumber(8); float xlaunch; float ylaunch; switch (direction) { case 1: // E xlaunch = 10.0; ylaunch = 0.0; case 2: // SE xlaunch = 10.0; ylaunch = 10.0; case 3: // S xlaunch = 0.0; ylaunch = 10.0; case 4: // SW xlaunch = -10.0; ylaunch = 10.0; case 5: // W xlaunch = -10.0; ylaunch = 0.0; case 6: // NW xlaunch = -10.0; ylaunch = -10.0; case 7: // N xlaunch = 0.0; ylaunch = -10.0; case 8: // NE xlaunch = 10.0; ylaunch = -10.0; default: xlaunch = 10.0; ylaunch = -10.0; } dStageActor_c *spawner = CreateActor(107, 0, this->pos, 0, 0); spawner->speed.x = xlaunch; spawner->speed.y = ylaunch; } void daMrSun_c::endState_Spin() { OSReport("K, I is dizzy now."); } // Wait State void daMrSun_c::beginState_Wait() { OSReport("Preparing an attack!"); this->timer = 0; this->speed.x = 0.0; } void daMrSun_c::executeState_Wait() { int Choice; if (this->timer > 1000) { Choice = GenerateRandomNumber(4); switch (Choice) { case 1: doStateChange(&StateID_Swoop); case 2: doStateChange(&StateID_Spiral); case 3: doStateChange(&StateID_Spit); case 4: doStateChange(&StateID_Follow); default: doStateChange(&StateID_Follow); } } this->timer = this->timer + 1; } void daMrSun_c::endState_Wait() { OSReport("Mr.Sun Cometh!"); this->timer = 0; }