#include #include #include #include "player.h" class daMegaGoomba_c : public dEn_c { int onCreate(); int onDelete(); int onExecute(); int onDraw(); mHeapAllocator_c allocator; m3d::mdl_c bodyModel; float timer; nw4r::ut::Rect Bounding; float dying; HermiteKey keysX[0x10]; unsigned int Xkey_count; HermiteKey keysY[0x10]; unsigned int Ykey_count; // HermiteKey keysZ[0x10]; // unsigned int Zkey_count; char life; bool takeHit(char count); void dieFall_Execute(); static daMegaGoomba_c *build(); void updateModelMatrices(); // bool preSpriteCollision(ActivePhysics *apThis, ActivePhysics *apOther); // bool prePlayerCollision(ActivePhysics *apThis, ActivePhysics *apOther); // bool preYoshiCollision(ActivePhysics *apThis, ActivePhysics *apOther); // bool stageActorCollision(ActivePhysics *apThis, ActivePhysics *apOther); // void spriteCollision(ActivePhysics *apThis, ActivePhysics *apOther); // 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 collisionCat3_StarPower(ActivePhysics *apThis, ActivePhysics *apOther); void collisionCat5_Mario(ActivePhysics *apThis, ActivePhysics *apOther); void collisionCat9_RollingObject(ActivePhysics *apThis, ActivePhysics *apOther); void collisionCatA_PenguinMario(ActivePhysics *apThis, ActivePhysics *apOther); void collisionCatD_GroundPound(ActivePhysics *apThis, ActivePhysics *apOther); void collisionCat11_PipeCannon(ActivePhysics *apThis, ActivePhysics *apOther); void collisionCat13_Hammer(ActivePhysics *apThis, ActivePhysics *apOther); void collisionCat14_YoshiFire(ActivePhysics *apThis, ActivePhysics *apOther); void _vf120(ActivePhysics *apThis, ActivePhysics *apOther); void _vf110(ActivePhysics *apThis, ActivePhysics *apOther); void _vf108(ActivePhysics *apThis, ActivePhysics *apOther); USING_STATES(daMegaGoomba_c); DECLARE_STATE(Grow); DECLARE_STATE(Shrink); DECLARE_STATE(Walk); DECLARE_STATE(Jump); DECLARE_STATE(Launch); }; //extern void * HandleXSpeed(daMegaGoomba_c*); //extern void * HandleYSpeed(daMegaGoomba_c*); daMegaGoomba_c *daMegaGoomba_c::build() { void *buffer = AllocFromGameHeap1(sizeof(daMegaGoomba_c)); return new(buffer) daMegaGoomba_c; } extern "C" void *HandleXSpeed(daMegaGoomba_c *); extern "C" void *HandleYSpeed(daMegaGoomba_c *); extern "C" void *UpdateObjectPosBasedOnSpeedValues_real(daMegaGoomba_c *); extern "C" u32 GenerateRandomNumber(int max); extern "C" u8 dSprite_c__getXDirectionOfFurthestPlayerRelativeToVEC3(daMegaGoomba_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(daMegaGoomba_c, Grow); CREATE_STATE(daMegaGoomba_c, Shrink); CREATE_STATE(daMegaGoomba_c, Walk); CREATE_STATE(daMegaGoomba_c, Jump); CREATE_STATE(daMegaGoomba_c, Launch); //TODO better fix for possible bug with sign (ex. life=120; count=-9;) bool daMegaGoomba_c::takeHit(char count) { int c = count; int l = this->life; if(l - c > 127) { c = 127 - l; } this->life -= c; doStateChange(&StateID_Shrink); setNewActivePhysicsRect(this, &this->scale); return (life <= 0) ? true : false; } #define ACTIVATE 1 #define DEACTIVATE 0 //bool daMegaGoomba_c::preSpriteCollision(ActivePhysics *apThis, ActivePhysics *apOther) { OSReport("preSpriteCollision\n"); return false; } //bool daMegaGoomba_c::prePlayerCollision(ActivePhysics *apThis, ActivePhysics *apOther) { OSReport("prePlayerCollision\n"); return false; } //bool daMegaGoomba_c::preYoshiCollision(ActivePhysics *apThis, ActivePhysics *apOther) { OSReport("preYoshiCollision\n"); return false; } //bool daMegaGoomba_c::stageActorCollision(ActivePhysics *apThis, ActivePhysics *apOther) { OSReport("stageActorCollision\n"); return true; } //void daMegaGoomba_c::spriteCollision(ActivePhysics *apThis, ActivePhysics *apOther) { OSReport("spriteCollision\n"); } /*void daMegaGoomba_c::playerCollision(ActivePhysics *apThis, ActivePhysics *apOther) { this->_vf220(apOther->owner); OSReport("I hit Mario.\n"); }*/ //void daMegaGoomba_c::yoshiCollision(ActivePhysics *apThis, ActivePhysics *apOther) { OSReport("yoshiCollision\n"); } void daMegaGoomba_c::collisionCat1_Fireball_E_Explosion(ActivePhysics *apThis, ActivePhysics *apOther) { OSReport("Hit Fireball\n"); } bool daMegaGoomba_c::collisionCat2_IceBall_15_YoshiIce(ActivePhysics *apThis, ActivePhysics *apOther) { OSReport("Hit Iceball\n"); return false; } void daMegaGoomba_c::collisionCat3_StarPower(ActivePhysics *apThis, ActivePhysics *apOther) { OSReport("Hit StarMario\n"); } void daMegaGoomba_c::collisionCat5_Mario(ActivePhysics *apThis, ActivePhysics *apOther) { OSReport("MarioHit\n"); } void daMegaGoomba_c::collisionCat9_RollingObject(ActivePhysics *apThis, ActivePhysics *apOther) { OSReport("Hit Rolling Object\n"); if(this->takeHit(1)) doStateChange(&StateID_DieFall); } void daMegaGoomba_c::collisionCatA_PenguinMario(ActivePhysics *apThis, ActivePhysics *apOther) { OSReport("Penguin Attack\n"); } void daMegaGoomba_c::collisionCatD_GroundPound(ActivePhysics *apThis, ActivePhysics *apOther) { OSReport("Groundpound\n"); } void daMegaGoomba_c::collisionCat11_PipeCannon(ActivePhysics *apThis, ActivePhysics *apOther) { OSReport("PipeCannon Hit\n"); } void daMegaGoomba_c::collisionCat13_Hammer(ActivePhysics *apThis, ActivePhysics *apOther) { OSReport("Hit Hammer\n"); if(this->takeHit(1)) doStateChange(&StateID_DieFall); } void daMegaGoomba_c::collisionCat14_YoshiFire(ActivePhysics *apThis, ActivePhysics *apOther) { OSReport("Hit Yoshi Fire\n"); if(this->takeHit(1)) doStateChange(&StateID_DieFall); } void daMegaGoomba_c::_vf120(ActivePhysics *apThis, ActivePhysics *apOther) { OSReport("_vf120:\n"); } void daMegaGoomba_c::_vf110(ActivePhysics *apThis, ActivePhysics *apOther) { OSReport("_vf110:\n"); } void daMegaGoomba_c::_vf108(ActivePhysics *apThis, ActivePhysics *apOther) { OSReport("_vf108:\n"); } //TODO make this real perty like void daMegaGoomba_c::dieFall_Execute() { this->timer = this->timer + 1.0; 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::dieFall_Execute(); } int daMegaGoomba_c::onCreate() { OSReport("Creating the MegaGoomba Model\n"); allocator.link(-1, GameHeaps[0], 0, 0x20); nw4r::g3d::ResFile rf(getResource("kuribo", "g3d/t02.brres")); bodyModel.setup(rf.GetResMdl("kuribo"), &allocator, 0x224, 1, 0); SetupTextures_Enemy(&bodyModel, 0); allocator.unlink(); OSReport("Creating MegaGoomba's Physics Struct\n"); // Keeping naming ActivePhysics::Info HitMeBaby; HitMeBaby.xDistToCenter = 0.0; HitMeBaby.yDistToCenter = 18.0; HitMeBaby.xDistToEdge = 24.0; HitMeBaby.yDistToEdge = 24.0; //TODO find data for a fun, yet challenging, battle HitMeBaby.category1 = 0x3; HitMeBaby.category2 = 0x0; HitMeBaby.bitfield1 = 0x4f; HitMeBaby.bitfield2 = 0xffba7ffe; HitMeBaby.unkShort1C = 0; HitMeBaby.callback = &dEn_c::collisionCallback; OSReport("Making the Physics Class and adding to the list\n"); this->aPhysics.initWithStruct(this, &HitMeBaby); this->aPhysics.addToList(); pos.y -= 20.0; pos.z = 3000.0; rot.x = rot.y = rot.z = speed.x = dying = 0.0; direction = 0; life = 3; //TODO 1) allow setting bounding rect with settings //TODO 2) don't use bounding rect. use wall/floor/ceiling detection Bounding.left = pos.x - 350.0; Bounding.top = pos.y + 500.0; Bounding.right = pos.x + 350.0; Bounding.bottom = pos.y; OSReport("Setting MegaGoomba's State\n"); doStateChange(&StateID_Grow); OSReport("Going to Execute MegaGoomba\n"); this->onExecute(); return true; } int daMegaGoomba_c::onDelete() { return true; } int daMegaGoomba_c::onExecute() { acState.execute(); updateModelMatrices(); if (this->aPhysics.result1 == 1) { char PlayerID = NearestPlayer(this); if(PlayerID > 0) { dStageActor_c *Player = GetSpecificPlayerActor(PlayerID); this->_vf220(Player); } } return true; } int daMegaGoomba_c::onDraw() { bodyModel.scheduleForDrawing(); return true; } void daMegaGoomba_c::updateModelMatrices() { // Bounds checking // TODO possibly change to a state change if(this->pos.x < this->Bounding.left) { this->direction = !this->direction; this->speed.x = -this->speed.x; this->pos.x = this->Bounding.left; } else if (this->pos.x > this->Bounding.right) { this->direction = !this->direction; this->speed.x = -this->speed.x; this->pos.x = this->Bounding.right; } if(this->pos.y < this->Bounding.bottom) { this->speed.y = 0.0; this->pos.y = this->Bounding.bottom; } else if (this->pos.y > this->Bounding.top) { this->speed.y = 0.0; this->pos.y = this->Bounding.bottom; } // 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 daMegaGoomba_c::beginState_Grow() { this->timer = 1.0; float start, end, shift1, shift2; start = 59.0; shift1 = 90.0; shift2 = 120.0; end = 139.0; /* keysX[i] = { frame, value, slope }; */ Xkey_count = 7; keysX[0] = (HermiteKey){ start, 1.0, 1.0 }; keysX[1] = (HermiteKey){ (start+shift1)/2, 2.0, 1.0 }; keysX[2] = (HermiteKey){ shift1, 4.0, 1.0 }; keysX[3] = (HermiteKey){ (shift1+shift2)/2, 3.0, 1.0 }; keysX[3] = (HermiteKey){ shift2, 6.0, 1.0 }; keysX[3] = (HermiteKey){ (shift2+end)/2, 5.0, 1.0 }; keysX[6] = (HermiteKey){ end, 7.0, 1.0 }; } void daMegaGoomba_c::executeState_Grow() { this->timer += 1.0; if ((this->timer > 60.0) && (this->timer < 140.0)) { float modifier = GetHermiteCurveValue(this->timer, this->keysX, Xkey_count); this->scale = (Vec){modifier, modifier, modifier}; setNewActivePhysicsRect(this, &this->scale); } //TODO grow sound //if(this->timer == 60.0) // playSound(SE_GROW); if (this->timer > 170.0) { doStateChange(&StateID_Walk); } } void daMegaGoomba_c::endState_Grow() { } // Shrink State void daMegaGoomba_c::beginState_Shrink() { this->timer = 1.0; Xkey_count = 4; keysX[0] = (HermiteKey){ 0.0, this->scale.x, 1.0 }; keysX[1] = (HermiteKey){ 20.0, this->scale.x - 2.0, 1.0 }; keysX[2] = (HermiteKey){ 40.0, this->scale.x, 1.0 }; keysX[3] = (HermiteKey){ 59.0, this->scale.x - 2.0, 1.0 }; } void daMegaGoomba_c::executeState_Shrink() { this->timer += 1.0; float modifier = GetHermiteCurveValue(this->timer, this->keysX, Xkey_count); this->scale = (Vec){modifier, modifier, modifier}; setNewActivePhysicsRect(this, &this->scale); //TODO shrink sound //if(this->timer == 2.0) // playSound(SE_SHRINK); if (this->timer > 60.0) { doStateChange(&StateID_Walk); } } void daMegaGoomba_c::endState_Shrink() { } // Launch State - Launches some small goombas up in arcs void daMegaGoomba_c::beginState_Launch() { this->timer = 0.0; } void daMegaGoomba_c::executeState_Launch() { if (this->timer < 120.0) { // 3 shakes per second, exactly 24 shakes overall this->rot.y = sin(this->timer * 3.14 / 5) * 4000; dStageActor_c *spawner = NULL; // 120ticks / 40numbers * 2cases = 6avg kuribo int randChoice = GenerateRandomNumber(40); int randChoiceX = GenerateRandomNumber(12); int randChoiceY = GenerateRandomNumber(12); switch(randChoice) { case 0: case 1: spawner = CreateActor(EN_KURIBO, 0, this->pos, 0, 0); spawner->speed.x = randChoiceX - 6.0; spawner->speed.y = randChoiceY * 1.0; spawner->scale = (Vec){1.0, 1.0, 1.0}; break; case 2: spawner = CreateActor(EN_BEANS_KURIBO, 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}; break; default: break; }; } if (this->timer > 150.0) { doStateChange(&StateID_Walk); } this->timer = this->timer + 1.0; } void daMegaGoomba_c::endState_Launch() { this->rot.y = 0; } // Jump State void daMegaGoomba_c::beginState_Jump() { this->timer = 1.0; //Variables for choosing a curve float jump_height = 36.0; float delta = (this->direction) ? -24.0 : 24.0; float fullTime = 90.0; //Key count Xkey_count = 2; Ykey_count = 3; //Initial Position keysX[0] = (HermiteKey){ 0.0, this->pos.x, 0.0 }; keysY[0] = (HermiteKey){ 0.0, this->pos.y, 0.8 }; //Middle Position keysY[1] = (HermiteKey){ (fullTime/2.0), this->pos.y + jump_height, 0.0 }; //End Position keysX[1] = (HermiteKey){ fullTime, this->pos.x + delta, 0.0 }; keysY[2] = (HermiteKey){ fullTime, this->pos.y, 0.8 }; } void daMegaGoomba_c::executeState_Jump() { this->pos.x = GetHermiteCurveValue(this->timer, this->keysX, Xkey_count); this->pos.y = GetHermiteCurveValue(this->timer, this->keysY, Ykey_count); float TimerMax = 91.0; if (this->timer > TimerMax) { doStateChange(&StateID_Walk); } this->timer = this->timer + 1.0; } void daMegaGoomba_c::endState_Jump() { } // Walk State void daMegaGoomba_c::beginState_Walk() { this->timer = 1.0; this->direction = dSprite_c__getXDirectionOfFurthestPlayerRelativeToVEC3(this, this->pos); //TODO add rot.changing on switching directions until animations added } void daMegaGoomba_c::executeState_Walk() { float delta = (this->direction) ? -0.5 : 0.5; this->pos.x += delta; int Choice; float TimerMax = 150.0; if (this->timer > TimerMax) { Choice = GenerateRandomNumber(4); switch(Choice) { case 0: doStateChange(&StateID_Jump); break; case 1: doStateChange(&StateID_Launch); break; case 2: break; //FIXME test case for sound effects //case 3: // break; default: this->direction = dSprite_c__getXDirectionOfFurthestPlayerRelativeToVEC3(this, pos); this->timer = 0; break; }; } this->timer = this->timer + 1.0; } void daMegaGoomba_c::endState_Walk() { }