#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; float xSpiralOffset; float ySpiralOffset; 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); CREATE_STATE(daMrSun_c, Wait); #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("bilikyu", "g3d/sun.brres")); model.setup(rf.GetResMdl("Sun"), &allocator, 0x224, 1, 0); // SetupTextures_Enemy(&model, 0); SetupTextures_Map(&model, 0); allocator.unlink(); OSReport("Setting Mr.Sun's Size to 4.0"); this->scale = (Vec){0.5, 0.5, 0.5}; OSReport("Creating Mr.Sun's Physics Struct"); ActivePhysics::Info HitMeBaby; HitMeBaby.xDistToCenter = 0.0; HitMeBaby.yDistToCenter = 0.0; HitMeBaby.xDistToEdge = 16.0; HitMeBaby.yDistToEdge = 16.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 = 100.0; this->yAccel = 0.2; this->timer = 0; this->xSpiralOffset = 0.0; this->ySpiralOffset = 0.0; OSReport("Setting Mr.Sun's State"); doStateChange(&StateID_Follow); 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; this->rot.x = 11000; this->rot.y = 0; // this->rot.z = 11000; } void daMrSun_c::executeState_Follow() { if (this->timer > 200) { this->doStateChange(&StateID_Wait); } this->direction = dSprite_c__getXDirectionOfFurthestPlayerRelativeToVEC3(this, this->pos); if (this->direction == 0) { this->speed.x = this->speed.x + 0.1; } else { this->speed.x = this->speed.x - 0.1; } HandleXSpeed(this); float yDiff; yDiff = (this->Baseline - this->pos.y) / 8; this->speed.y = yDiff; OSReport("YSpeed = %f", this->speed.y); HandleYSpeed(this); UpdateObjectPosBasedOnSpeedValues_real(this); this->timer = this->timer + 1; } void daMrSun_c::endState_Follow() { OSReport("Mr.Sun is coming for you."); this->speed.y = 0; } // 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; this->swoopTarget.y = this->swoopTarget.y - 24; 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->slope < 0.0) { this->speed.x = this->speed.x + 0.3; this->speed.y = this->speed.y - (0.2 * -slope); } else if (this->slope > 0.0) { this->speed.x = this->speed.x - 0.3; this->speed.y = this->speed.y - (0.2 * slope); } float yDiff; if (this->pos.y < this->swoopTarget.y) { this->speed.x = this->speed.x * 0.2; this->speed.y = this->speed.y * 0.2; } HandleXSpeed(this); HandleYSpeed(this); UpdateObjectPosBasedOnSpeedValues_real(this); if (this->pos.y < this->swoopTarget.y) { if (this->speed.y < 0.1) { doStateChange(&StateID_Follow); } } } void daMrSun_c::endState_Swoop() { OSReport("Returning to the sky, Mr.Sun flies into the sunset."); } // Spiral State void daMrSun_c::beginState_Spiral() { OSReport("Super Spiral Sunspot!"); this->SpiralLoop = 0; this->xSpiralOffset = this->pos.x; this->ySpiralOffset = this->pos.y; } void daMrSun_c::executeState_Spiral() { float Loops; float Period; float Magnitude; Loops = 6.0; // Use a period of 0.1 for the moon Period = 0.075; Magnitude = 11.0; this->pos.x = this->xSpiralOffset + Magnitude*((this->SpiralLoop * cos(this->SpiralLoop))); this->pos.y = this->ySpiralOffset + Magnitude*((this->SpiralLoop * sin(this->SpiralLoop))); this->SpiralLoop = this->SpiralLoop + Period; if (this->SpiralLoop > (3.14 * Loops)) { doStateChange(&StateID_Follow); } } void daMrSun_c::endState_Spiral() { OSReport("Nightmare Spiral Attack Ends!"); } // Spit State void daMrSun_c::beginState_Spit() { OSReport("Goodness Gracious Great Balls of Fire!"); this->timer = 0; } void daMrSun_c::executeState_Spit() { if (this->timer == 10) { this->direction = dSprite_c__getXDirectionOfFurthestPlayerRelativeToVEC3(this, this->pos); float neg = -1.0; if (this->direction == 0) { neg = 1.0; } dStageActor_c *spawner = CreateActor(106, 0, this->pos, 0, 0); spawner->speed.x = 6.0 * neg; spawner->speed.y = -2.5; spawner = CreateActor(106, 0, this->pos, 0, 0); spawner->speed.x = 0.0 * neg; spawner->speed.y = -6.0; spawner = CreateActor(106, 0, this->pos, 0, 0); spawner->speed.x = 3.5 * neg; spawner->speed.y = -6.0; } this->timer = this->timer + 1; if (this->timer > 30) { doStateChange(&StateID_Follow); } } 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() { this->direction = dSprite_c__getXDirectionOfFurthestPlayerRelativeToVEC3(this, this->pos); if (this->direction == 0) { this->speed.x = this->speed.x + 0.2; } else { this->speed.x = this->speed.x - 0.2; } HandleXSpeed(this); UpdateObjectPosBasedOnSpeedValues_real(this); this->timer = this->timer + 1; int rotBonus; if (this->timer < 60) { rotBonus = this->timer; } else { rotBonus = 120 - this->timer; } this->rot.x = this->rot.x + (50 * rotBonus); this->rot.y = this->rot.y + (50 * rotBonus); int randomBall; randomBall = GenerateRandomNumber(6); if (randomBall == 1) { int direction; direction = GenerateRandomNumber(8); float xlaunch; float ylaunch; if (direction == 0) { xlaunch = 7.5; ylaunch = 0.0; } else if (direction == 1) { // SE xlaunch = 7.5; ylaunch = 7.5; } else if (direction == 2) { // S xlaunch = 0.0; ylaunch = 7.5; } else if (direction == 3) { // SW xlaunch = -7.5; ylaunch = 7.5; } else if (direction == 4) { // W xlaunch = -7.5; ylaunch = 0.0; } else if (direction == 5) { // NW xlaunch = -7.5; ylaunch = -7.5; } else if (direction == 6) { // N xlaunch = 0.0; ylaunch = -7.5; } else if (direction == 7) { // NE xlaunch = 7.5; ylaunch = -7.5; } dStageActor_c *spawner = CreateActor(106, 0, this->pos, 0, 0); spawner->speed.x = xlaunch; spawner->speed.y = ylaunch; } if (this->timer > 120) { this->rot.x = this->rot.x / 2; this->rot.y = this->rot.y / 2; this->doStateChange(&StateID_Follow); } } void daMrSun_c::endState_Spin() { OSReport("K, I is dizzy now."); this->rot.x = 11000; this->rot.y = 0; // this->rot.z = 11000; } // Wait State void daMrSun_c::beginState_Wait() { OSReport("Preparing an attack!"); this->timer = 0; this->speed.x = 0.0; this->rot.x = 11000; this->rot.y = 0; // this->rot.z = 11000; } void daMrSun_c::executeState_Wait() { int Choice; if (this->timer > 20) { // doStateChange(&StateID_Spit); Choice = GenerateRandomNumber(1); OSReport("Choice: %d", Choice); if (Choice == 0) { doStateChange(&StateID_Swoop); } // else if (Choice == 1) { doStateChange(&StateID_Spin); } // else if (Choice == 2) { doStateChange(&StateID_Swoop); } // else if (Choice == 3) { doStateChange(&StateID_Spiral); } } this->timer = this->timer + 1; } void daMrSun_c::endState_Wait() { OSReport("Mr.Sun Cometh!"); this->timer = 0; this->rot.x = 11000; this->rot.y = 0; // this->rot.z = 11000; }