#include #include #include class daFuzzyBear_c : public dEn_c { int onCreate(); int onDelete(); int onExecute(); int onDraw(); mHeapAllocator_c allocator; m3d::mdl_c bodyModel; int timer; char BigBossFuzzyBear; float Baseline; float AreaWidthLeft; float AreaWidthRight; float LaunchSpeedShort; float LaunchSpeedHigh; float dying; float storeSpeed; Vec initialPos; char RolyBounces; Vec RolyPos; char falldown; char damage; char fireballs; void dieBigFall_Execute(); static daFuzzyBear_c *build(); void updateModelMatrices(); void playerCollision(ActivePhysics *apThis, ActivePhysics *apOther); // void yoshiCollision(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); void collisionCat14_YoshiFire(ActivePhysics *apThis, ActivePhysics *apOther); USING_STATES(daFuzzyBear_c); DECLARE_STATE(Grow); DECLARE_STATE(Bounce); DECLARE_STATE(Needles); DECLARE_STATE(Spray); DECLARE_STATE(RolyPoly); }; daFuzzyBear_c *daFuzzyBear_c::build() { void *buffer = AllocFromGameHeap1(sizeof(daFuzzyBear_c)); return new(buffer) daFuzzyBear_c; } extern "C" void *HandleXSpeed(daFuzzyBear_c *); extern "C" void *HandleYSpeed(daFuzzyBear_c *); extern "C" void *UpdateObjectPosBasedOnSpeedValues_real(daFuzzyBear_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(daFuzzyBear_c *, Vec pos); extern "C" dStageActor_c *GetSpecificPlayerActor(int number); int NearestPlayerF(daFuzzyBear_c *Sprite); float PlayertoSpriteDistanceF(Vec sprite, Vec player); CREATE_STATE(daFuzzyBear_c, Grow); CREATE_STATE(daFuzzyBear_c, Bounce); CREATE_STATE(daFuzzyBear_c, Needles); CREATE_STATE(daFuzzyBear_c, Spray); CREATE_STATE(daFuzzyBear_c, RolyPoly); #define ACTIVATE 1 #define DEACTIVATE 0 void daFuzzyBear_c::playerCollision(ActivePhysics *apThis, ActivePhysics *apOther) { this->_vf220(apOther->owner); OSReport("I hit Mario."); } void daFuzzyBear_c::collisionCat1_Fireball_E_Explosion(ActivePhysics *apThis, ActivePhysics *apOther) { OSReport("Hit Fireball"); this->timer = 0; this->fireballs = this->fireballs + 1; if (this->fireballs > 4) { this->damage = this->damage + 1; } if (this->damage > 2) { doStateChange(&StateID_DieBigFall); } } bool daFuzzyBear_c::collisionCat2_IceBall_15_YoshiIce(ActivePhysics *apThis, ActivePhysics *apOther) { OSReport("Hit Iceball"); return false; } void daFuzzyBear_c::collisionCat9_RollingObject(ActivePhysics *apThis, ActivePhysics *apOther) { OSReport("Hit Rolling Object"); this->timer = 0; this->damage = this->damage + 1; if (this->damage > 2) { doStateChange(&StateID_DieBigFall); } } void daFuzzyBear_c::collisionCat13_Hammer(ActivePhysics *apThis, ActivePhysics *apOther) { OSReport("Hit Hammer"); this->timer = 0; this->damage = this->damage + 1; if (this->damage > 2) { doStateChange(&StateID_DieBigFall); } } void daFuzzyBear_c::collisionCat14_YoshiFire(ActivePhysics *apThis, ActivePhysics *apOther) { OSReport("Hit Yoshi Fire"); } void daFuzzyBear_c::dieBigFall_Execute() { this->timer = this->timer + 1; this->dying = this->dying + 0.15; this->pos.x = this->pos.x + 0.15; this->pos.y = this->pos.y + ((-0.2 * (this->dying*this->dying)) + 5); this->dEn_c::dieBigFall_Execute(); } int daFuzzyBear_c::onCreate() { OSReport("Creating the Fuzzy Bear Model"); allocator.link(-1, GameHeaps[0], 0, 0x20); nw4r::g3d::ResFile rf(getResource("chorobon", "g3d/chorobon.brres")); bodyModel.setup(rf.GetResMdl("chorobon"), &allocator, 0x224, 1, 0); SetupTextures_Enemy(&bodyModel, 0); allocator.unlink(); this->BigBossFuzzyBear = this->settings >> 28; OSReport("Setting Fuzzy Bear's Size to 1.0"); this->scale = (Vec){1.0, 1.0, 1.0}; OSReport("Creating Fuzzy Bear's Physics Struct"); ActivePhysics::Info HitMeBaby; HitMeBaby.xDistToCenter = 0.0; HitMeBaby.yDistToCenter = 0.0; if (BigBossFuzzyBear == 0) { HitMeBaby.xDistToEdge = 38.0; HitMeBaby.yDistToEdge = 38.0; } else { HitMeBaby.xDistToEdge = 50.0; HitMeBaby.yDistToEdge = 50.0; } HitMeBaby.category1 = 0x7; HitMeBaby.category2 = 0x0; HitMeBaby.bitfield1 = 0x0; HitMeBaby.bitfield2 = 0x0; // HitMeBaby.bitfield1 = 0x4F; // HitMeBaby.bitfield2 = 0x828E; 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 Fuzzy Bear's Box of Goodies"); this->pos.y = this->pos.y + 6; this->rot.x = 0; // X is vertical axis this->rot.y = 0; // Y is horizontal axis this->rot.z = 0; // Z is ... an axis >.> this->direction = 0; // Heading left. this->speed.x = 0; this->LaunchSpeedShort = ((this->settings >> 20) && 0xF) * 10.0; this->LaunchSpeedHigh = ((this->settings >> 24) && 0xF) * 10.0; this->AreaWidthRight = this->settings && 0xFF; this->AreaWidthLeft = (this->settings >> 8) && 0xFF; this->initialPos = this->pos; this->storeSpeed = 0; this->falldown = 0; this->fireballs = 0; this->damage = 0; OSReport("Setting Fuzzy Bear's State"); doStateChange(&StateID_Grow); OSReport("Going to Execute Fuzzy Bear"); this->onExecute(); return true; } int daFuzzyBear_c::onDelete() { return true; } int daFuzzyBear_c::onExecute() { // OSReport("Fuzzy Bear was Executed."); acState.execute(); updateModelMatrices(); if (this->aPhysics.result1 == 1) { char PlayerID = NearestPlayerF(this); dStageActor_c *Player = GetSpecificPlayerActor(PlayerID); this->_vf220(Player); } return true; } int NearestPlayerF(daFuzzyBear_c *Sprite) { float pfloat[] = { 0.0, 0.0, 0.0, 0.0 }; float max = 1000000.0; char maxPlayer = 5; int i; OSReport("FINDING NEAREST PLAYER"); for (i=0; i<4; i++) { OSReport("K, let's check out Player %d", i); dStageActor_c *Player = GetSpecificPlayerActor(i); if (Player != 0) { OSReport("Player %d exists", i); pfloat[i] = PlayertoSpriteDistanceF(Sprite->pos, Player->pos); OSReport("if %f > %f", pfloat[i], max); if (pfloat[i] < max) { max = pfloat[i]; maxPlayer = i; OSReport("MaxPlayer now %d", i); } } } OSReport("MaxPlayer finalized at %d", maxPlayer); return maxPlayer; } float PlayertoSpriteDistanceF(Vec sprite, Vec player) { float x = sprite.x - player.x; float y = sprite.y - player.y; float x2 = x * x; float y2 = y * y; float returnval = x2+y2; OSReport("X: (%f - %f)^2 = %f", sprite.x, player.x, x2); OSReport("Y: (%f - %f)^2 = %f", sprite.y, player.y, y2); if (returnval < 0) { returnval = -returnval; } OSReport("Return: %f", returnval); return returnval; } int daFuzzyBear_c::onDraw() { bodyModel.scheduleForDrawing(); return true; } void daFuzzyBear_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 daFuzzyBear_c::beginState_Grow() { OSReport("Growing when Kameck Tells me to."); this->timer = 0; } void daFuzzyBear_c::executeState_Grow() { this->timer = this->timer + 1; float scaleSpeed, yPosScaling; if ((this->timer > 60) && (this->timer < 140)) { if (BigBossFuzzyBear == 0) { scaleSpeed = 0.025; yPosScaling = 25; } else { scaleSpeed = 0.0375; yPosScaling = 33; } 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) { doStateChange(&StateID_Bounce); } } void daFuzzyBear_c::endState_Grow() { this->Baseline = this->pos.y; OSReport("OK. All grown up now."); } // Bounce State void daFuzzyBear_c::beginState_Bounce() { OSReport("Begin Bouncing"); if (this->direction = 0) { this->speed.x = ((this->settings >> 16) && 0xF) * 0.5; } else { this->speed.x = ((this->settings >> 16) && 0xF) * -0.5; } if (this->storeSpeed != 0) { this->speed.x = this->storeSpeed; } this->timer = 20; } void daFuzzyBear_c::executeState_Bounce() { float wallDistance, scaleDown, scaleUp, scaleBase; if (BigBossFuzzyBear == 0) { wallDistance = 38.0; scaleDown = 3.0; scaleUp = 12.0; scaleBase = 3.0; } else { wallDistance = 50.0; scaleDown = 4.0; scaleUp = 16.0; scaleBase = 4.0; } if (this->falldown == 1) { this->speed.x = 0; this->timer = 0; } // Check for walls if (this->pos.x <= this->initialPos.x - ((AreaWidthLeft * 24.0) + wallDistance)) { // Hit left wall, head right. this->speed.x = -this->speed.x; this->direction = 1; this->pos.x = this->pos.x + 1.0; } if (this->pos.x >= this->initialPos.x + ((AreaWidthRight * 24.0) - wallDistance)) { // Hit right wall, head left. this->speed.x = -this->speed.x; this->direction = 0; this->pos.x = this->pos.x - 1.0; } // Check if we're on the ground. if (this->pos.y < this->Baseline) { this->falldown = 0; this->timer = this->timer + 1; if (this->speed.x != 0) { this->storeSpeed = this->speed.x; } this->speed.x = 0; this->speed.y = 0; if (this->timer < 10) { float modifier; modifier = scaleBase - (this->timer * 0.1); this->scale.y = modifier; this->pos.y = this->pos.y + (scaleDown/10.0); if (this->pos.y > this->Baseline) { this->pos.y = this->Baseline - 1.0; } } else { float modifier; modifier = (scaleBase - 1.0) + ((this->timer - 10) * 0.1); this->scale.y = modifier; this->pos.y = this->pos.y + (scaleUp/10.0); if (this->pos.y > this->Baseline) { this->pos.y = this->Baseline - 1.0; } } if (this->timer >= 20) { int randChoice; if (BigBossFuzzyBear == 1) { randChoice = GenerateRandomNumber(5); if (randChoice == 0) { doStateChange(&StateID_Spray); } else if (randChoice == 1) { doStateChange(&StateID_Needles); } else if (randChoice == 2) { doStateChange(&StateID_RolyPoly); } } else { randChoice = GenerateRandomNumber(2); if (randChoice == 0) { doStateChange(&StateID_RolyPoly); } } randChoice = GenerateRandomNumber(5); if (randChoice == 0) { this->speed.y = LaunchSpeedHigh; } else { this->speed.y = LaunchSpeedShort; } this->timer = 0; this->pos.y = this->Baseline + 1; OSReport("Takeoff Initiated"); this->speed.x = this->storeSpeed; } } else { this->speed.y = this->speed.y - 0.1; } // Gravity HandleXSpeed(this); HandleYSpeed(this); UpdateObjectPosBasedOnSpeedValues_real(this); } void daFuzzyBear_c::endState_Bounce() { OSReport("No more bouncing."); } // Needles State - shoots out some black icicles void daFuzzyBear_c::beginState_Needles() { this->timer = 0; this->speed.y = 0; this->speed.x = 0; OSReport("Fuzzy Needle State Begin"); } void daFuzzyBear_c::executeState_Needles() { float origScale; this->speed.y = 0; this->speed.x = 0; if (BigBossFuzzyBear == 0) { origScale = 3.0; } else { origScale = 4.0; } this->timer = this->timer + 1; OSReport("Needle Timer: %d", this->timer); if (this->timer < 120) { this->scale.y = (sin(this->timer * 3.14 / 5.0) / 2.0) + origScale; // 3 shakes per second, exactly 24 shakes overall this->scale.x = (sin(this->timer * 3.14 / 5.0) / 2.0) + origScale; // 3 shakes per second, exactly 24 shakes overall if (this->timer == 30) { dStageActor_c *spawner = CreateActor(511, 0, this->pos, 0, 0); spawner->speed.x = -6.0; spawner->speed.y = 0.0; spawner->scale = (Vec){1.0, 1.0, 1.0}; } if (this->timer == 45) { dStageActor_c *spawner = CreateActor(511, 0, this->pos, 0, 0); spawner->speed.x = 6.0; spawner->speed.y = 6.0; spawner->scale = (Vec){1.0, 1.0, 1.0}; } if (this->timer == 60) { dStageActor_c *spawner = CreateActor(511, 0, this->pos, 0, 0); spawner->speed.x = 0.0; spawner->speed.y = 6.0; spawner->scale = (Vec){1.0, 1.0, 1.0}; } if (this->timer == 75) { dStageActor_c *spawner = CreateActor(511, 0, this->pos, 0, 0); spawner->speed.x = -6.0; spawner->speed.y = 6.0; spawner->scale = (Vec){1.0, 1.0, 1.0}; } if (this->timer == 90) { dStageActor_c *spawner = CreateActor(511, 0, this->pos, 0, 0); spawner->speed.x = -6.0; spawner->speed.y = 0.0; spawner->scale = (Vec){1.0, 1.0, 1.0}; } } else { doStateChange(&StateID_Bounce); } HandleXSpeed(this); HandleYSpeed(this); UpdateObjectPosBasedOnSpeedValues_real(this); } void daFuzzyBear_c::endState_Needles() { OSReport("Fuzzy Needle State End"); } // Spray State - jumps in the air and shakes out some small fuzzies void daFuzzyBear_c::beginState_Spray() { this->timer = 0; this->speed.y = 7.0; this->speed.x = 0.0; OSReport("Fuzzy Spray State Begin"); } void daFuzzyBear_c::executeState_Spray() { this->speed.x = 0.0; OSReport("Fuzzy Spray State Execute"); if (this->speed.y < 1.0) { this->speed.y = 0; if (this->timer < 120) { this->rot.y = sin(this->timer * 3.14 / 5) * 4000; // 3 shakes per second, exactly 24 shakes overall int randChoice; randChoice = GenerateRandomNumber(20); // 1.3 Fuzzies per second, 6 fuzzies overall if (randChoice == 0) { int randChoiceX, randChoiceY; randChoiceX = GenerateRandomNumber(24); randChoiceY = GenerateRandomNumber(16); dStageActor_c *spawner = CreateActor(144, 0, this->pos, 0, 0); spawner->speed.x = randChoiceX - 12.0; spawner->speed.y = randChoiceY * 1.0; spawner->scale = (Vec){1.0, 1.0, 1.0}; } } else { doStateChange(&StateID_Bounce); } this->timer = this->timer + 1; } else { this->speed.y = this->speed.y - 0.1; } // Gravity HandleXSpeed(this); HandleYSpeed(this); UpdateObjectPosBasedOnSpeedValues_real(this); } void daFuzzyBear_c::endState_Spray() { this->rot.y = 0; this->timer = 20; this->falldown = 1; OSReport("Fuzzy Spray State End"); } // Roly Poly State - Rolls from left to right, bounces off both walls, and returns to original position. void daFuzzyBear_c::beginState_RolyPoly() { this->speed.x = this->storeSpeed; this->speed.y = 0; this->RolyBounces = 0; this->RolyPos = this->pos; OSReport("Fuzzy Roly State Begin"); } void daFuzzyBear_c::executeState_RolyPoly() { OSReport("Fuzzy Roly State Execute"); float wallDistance, scaleDown, scaleUp; if (BigBossFuzzyBear == 0) { wallDistance = 38.0; } else { wallDistance = 50.0; } this->speed.y = 0; if (this->pos.x <= this->initialPos.x - ((AreaWidthLeft * 24.0) + wallDistance)) { // Hit left wall, head right. this->speed.x = -this->speed.x; this->direction = 1; this->pos.x = this->pos.x + 1.0; this->RolyBounces = this->RolyBounces + 1; } if (this->pos.x >= this->initialPos.x + ((AreaWidthRight * 24.0) - wallDistance)) { // Hit right wall, head left. this->speed.x = -this->speed.x; this->direction = 0; this->pos.x = this->pos.x - 1.0; this->RolyBounces = this->RolyBounces + 1; } if (this->direction == 1) { this->rot.z = this->rot.z + 0x1000; } else { this->rot.z = this->rot.z - 0x1000; } if (this->RolyBounces == 2) { if (this->direction == 1) { if (this->pos.x > this->RolyPos.x) { this->speed.x = 0; if (this->rot.z == 0) { doStateChange(&StateID_Bounce); } } } else { if (this->pos.x < this->RolyPos.x) { this->speed.x = 0; if (this->rot.z == 0) { doStateChange(&StateID_Bounce); } } } } HandleXSpeed(this); HandleYSpeed(this); UpdateObjectPosBasedOnSpeedValues_real(this); } void daFuzzyBear_c::endState_RolyPoly() { this->rot.z = 0; OSReport("Fuzzy Roly State End"); }