summaryrefslogtreecommitdiff
path: root/src/bossMegaGoomba.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/bossMegaGoomba.cpp')
-rw-r--r--src/bossMegaGoomba.cpp456
1 files changed, 456 insertions, 0 deletions
diff --git a/src/bossMegaGoomba.cpp b/src/bossMegaGoomba.cpp
new file mode 100644
index 0000000..65bbdb2
--- /dev/null
+++ b/src/bossMegaGoomba.cpp
@@ -0,0 +1,456 @@
+#include <common.h>
+#include <game.h>
+#include <g3dhax.h>
+
+#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() { }