#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; 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; //TODO use these for MegaGecko testing of params u32 marker1_start; nw4r::ut::Rect Bounding; u32 marker1_end; u32 marker2_start; int pickedChoice; u32 marker2_end; u32 marker3_start; float XSpeed; u32 marker3_end; u32 marker4_start; float JumpHeight; u32 marker4_end; u32 marker5_start; float JumpDist; u32 marker5_end; u32 marker6_start; float JumpTime; u32 marker6_end; u32 marker7_start; int playIt; u32 marker7_end; u32 marker8_start; int toPlay; u32 marker8_end; u32 marker9_start; bool timeToPlay; u32 marker9_end; 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 "C" void *PlaySound(dStageActor_c *, int soundID); //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 -= 16.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 - 212.0; Bounding.top = pos.y + 500.0; Bounding.right = pos.x + 212.0; Bounding.bottom = pos.y; //TODO for tests this->marker1_start = 0xaabbcc11; this->marker1_end = 0xaabbff11; this->marker2_start = 0xaabbcc12; this->marker2_end = 0xaabbff12; this->marker3_start = 0xaabbcc13; this->marker3_end = 0xaabbff13; this->marker4_start = 0xaabbcc14; this->marker4_end = 0xaabbff14; this->marker5_start = 0xaabbcc15; this->marker5_end = 0xaabbff15; this->marker6_start = 0xaabbcc16; this->marker6_end = 0xaabbff16; this->marker7_start = 0xaabbcc17; this->marker7_end = 0xaabbff17; this->marker8_start = 0xaabbcc18; this->marker8_end = 0xaabbff18; this->marker9_start = 0xaabbcc19; this->marker9_end = 0xaabbff19; this->pickedChoice = -1; this->XSpeed = 2.0; // GOOD FOR FINAL SPEED? this->JumpHeight = 48.0; this->JumpDist = 64.0; this->JumpTime = 50.0; this->playIt = 0; this->toPlay = 0; this->timeToPlay = false; 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->life > 0) { 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(this, 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(this, 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 / 80numbers * 4cases = 6avg kuribo int randChoice = GenerateRandomNumber(80); int randChoiceX = GenerateRandomNumber(12); int randChoiceY = GenerateRandomNumber(7); 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 + 3.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 - 6.0; spawner->speed.y = randChoiceY + 3.0; spawner->scale = (Vec){1.0, 1.0, 1.0}; break; case 3: spawner = CreateActor(EN_PATA_KURIBO, 0, this->pos, 0, 0); spawner->speed.x = randChoiceX - 6.0; spawner->speed.y = randChoiceY + 3.0; spawner->scale = (Vec){1.0, 1.0, 1.0}; break; case 4: spawner = CreateActor(EN_MAME_KURIBO, 0, this->pos, 0, 0); spawner->speed.x = randChoiceX - 6.0; spawner->speed.y = randChoiceY + 3.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 = this->JumpHeight; float delta = (this->direction) ? -JumpDist : JumpDist; float fullTime = this->JumpTime; //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 = JumpTime + 1.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) ? -this->XSpeed : this->XSpeed; this->pos.x += delta; int Choice; float TimerMax = 150.0; if (this->timer > TimerMax) { if(this->pickedChoice != -1) { Choice = this->pickedChoice; } else { 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: OSReport("PlaySound(this, %d)\n", this->toPlay); if(this->timeToPlay) { PlaySound(this, this->toPlay); this->timeToPlay = false; this->toPlay++; if(this->toPlay > 1977) this->toPlay = 0; } else { this->timeToPlay = true; } break; default: this->direction = dSprite_c__getXDirectionOfFurthestPlayerRelativeToVEC3(this, pos); this->timer = 0; break; }; } this->timer = this->timer + 1.0; } void daMegaGoomba_c::endState_Walk() { }