summaryrefslogtreecommitdiff
path: root/src/thundercloud.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-xsrc/thundercloud.cpp407
1 files changed, 407 insertions, 0 deletions
diff --git a/src/thundercloud.cpp b/src/thundercloud.cpp
new file mode 100755
index 0000000..a84340f
--- /dev/null
+++ b/src/thundercloud.cpp
@@ -0,0 +1,407 @@
+#include <common.h>
+#include <game.h>
+#include <g3dhax.h>
+
+#include "boss.h"
+
+const char* TLCarcNameList [] = {
+ "tcloud",
+ NULL
+};
+
+class dThunderCloud : public dEn_c {
+ int onCreate();
+ int onDelete();
+ int onExecute();
+ int onDraw();
+
+ mHeapAllocator_c allocator;
+ m3d::mdl_c bodyModel;
+ nw4r::g3d::ResFile resFile;
+ m3d::anmChr_c anm;
+
+ mEf::es2 bolt;
+ mEf::es2 charge;
+
+ float Baseline;
+ u32 timer;
+ int dying;
+ char killFlag;
+
+ u64 eventFlag;
+
+ ActivePhysics Lightning;
+
+ void dieFall_Begin();
+ void dieFall_Execute();
+ static dThunderCloud *build();
+
+ void updateModelMatrices();
+
+ void playerCollision(ActivePhysics *apThis, ActivePhysics *apOther);
+ void yoshiCollision(ActivePhysics *apThis, ActivePhysics *apOther);
+ void collisionCat1_Fireball_E_Explosion(ActivePhysics *apThis, ActivePhysics *apOther);
+ void collisionCat14_YoshiFire(ActivePhysics *apThis, ActivePhysics *apOther);
+ void collisionCat13_Hammer(ActivePhysics *apThis, ActivePhysics *apOther);
+ void collisionCat9_RollingObject(ActivePhysics *apThis, ActivePhysics *apOther);
+ void collisionCat3_StarPower(ActivePhysics *apThis, ActivePhysics *apOther);
+ void collisionCatD_GroundPound(ActivePhysics *apThis, ActivePhysics *apOther);
+ void collisionCat7_GroundPound(ActivePhysics *apThis, ActivePhysics *apOther);
+ void collisionCat7_GroundPoundYoshi(ActivePhysics *apThis, ActivePhysics *apOther);
+ void collisionCatA_PenguinMario(ActivePhysics *apThis, ActivePhysics *apOther);
+ void collisionCat5_Mario(ActivePhysics *apThis, ActivePhysics *apOther);
+ void collisionCat11_PipeCannon(ActivePhysics *apThis, ActivePhysics *apOther);
+
+ void bindAnimChr_and_setUpdateRate(const char* name, int unk, float unk2, float rate);
+
+ void _vf148();
+ void _vf14C();
+ bool CreateIceActors();
+
+ USING_STATES(dThunderCloud);
+ DECLARE_STATE(Follow);
+ DECLARE_STATE(Lightning);
+};
+
+dThunderCloud *dThunderCloud::build() {
+ void *buffer = AllocFromGameHeap1(sizeof(dThunderCloud));
+ return new(buffer) dThunderCloud;
+}
+
+
+CREATE_STATE(dThunderCloud, Follow);
+CREATE_STATE(dThunderCloud, Lightning);
+
+
+// Collision Callbacks
+ extern "C" void dAcPy_vf3F4(void* mario, void* other, int t);
+ extern "C" void BigHanaFireball(dEn_c* t, ActivePhysics *apThis, ActivePhysics *apOther);
+ extern "C" void *dAcPy_c__ChangePowerupWithAnimation(void * Player, int powerup);
+ extern "C" int CheckExistingPowerup(void * Player);
+
+ void dThunderCloud::playerCollision(ActivePhysics *apThis, ActivePhysics *apOther) {
+ if (apThis->info.category2 == 0x9) {
+ int p = CheckExistingPowerup(apOther->owner);
+ if (p != 0 && p != 3) { // Powerups - 0 = small; 1 = big; 2 = fire; 3 = mini; 4 = prop; 5 = peng; 6 = ice; 7 = hammer
+ dAcPy_c__ChangePowerupWithAnimation(apOther->owner, 3);
+ }
+ else { dAcPy_vf3F4(apOther->owner, this, 9); }
+ }
+
+ else { dAcPy_vf3F4(apOther->owner, this, 9); }
+ }
+
+ void dThunderCloud::yoshiCollision(ActivePhysics *apThis, ActivePhysics *apOther) { this->playerCollision(apThis, apOther); }
+ void dThunderCloud::collisionCatD_GroundPound(ActivePhysics *apThis, ActivePhysics *apOther) { this->playerCollision(apThis, apOther); }
+ void dThunderCloud::collisionCat7_GroundPound(ActivePhysics *apThis, ActivePhysics *apOther) { this->playerCollision(apThis, apOther); }
+ void dThunderCloud::collisionCat7_GroundPoundYoshi(ActivePhysics *apThis, ActivePhysics *apOther) { this->playerCollision(apThis, apOther); }
+ void dThunderCloud::collisionCatA_PenguinMario(ActivePhysics *apThis, ActivePhysics *apOther) { this->playerCollision(apThis, apOther); }
+ void dThunderCloud::collisionCat5_Mario(ActivePhysics *apThis, ActivePhysics *apOther) { this->playerCollision(apThis, apOther); }
+ void dThunderCloud::collisionCat11_PipeCannon(ActivePhysics *apThis, ActivePhysics *apOther) { this->playerCollision(apThis, apOther); }
+
+ void dThunderCloud::collisionCat1_Fireball_E_Explosion(ActivePhysics *apThis, ActivePhysics *apOther) { BigHanaFireball(this, apThis, apOther); }
+ void dThunderCloud::collisionCat14_YoshiFire(ActivePhysics *apThis, ActivePhysics *apOther) { BigHanaFireball(this, apThis, apOther); }
+
+ void dThunderCloud::collisionCat13_Hammer(ActivePhysics *apThis, ActivePhysics *apOther) {
+ if (apThis->info.category2 == 0x9) { return; }
+ PlaySound(this, SE_EMY_DOWN);
+ doStateChange(&StateID_DieFall); }
+ void dThunderCloud::collisionCat9_RollingObject(ActivePhysics *apThis, ActivePhysics *apOther) { this->collisionCat13_Hammer(apThis, apOther); }
+ void dThunderCloud::collisionCat3_StarPower(ActivePhysics *apThis, ActivePhysics *apOther) {
+ if (apThis->info.category2 == 0x9) { return; }
+ dEn_c::collisionCat3_StarPower(apThis, apOther);
+ this->collisionCat13_Hammer(apThis, apOther); }
+
+
+ // These handle the ice crap
+ void dThunderCloud::_vf148() {
+ dEn_c::_vf148();
+ doStateChange(&StateID_DieFall);
+ }
+ void dThunderCloud::_vf14C() {
+ dEn_c::_vf14C();
+ doStateChange(&StateID_DieFall);
+ }
+
+ extern "C" void sub_80024C20(void);
+ extern "C" void __destroy_arr(void*, void(*)(void), int, int);
+ //extern "C" __destroy_arr(struct DoSomethingCool, void(*)(void), int cnt, int bar);
+
+ bool dThunderCloud::CreateIceActors() {
+ struct DoSomethingCool my_struct = { 0, (Vec){pos.x, pos.y - 16.0, pos.z}, {1.75, 1.4, 1.5}, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
+ this->frzMgr.Create_ICEACTORs( (void*)&my_struct, 1 );
+ __destroy_arr( (void*)&my_struct, sub_80024C20, 0x3C, 1 );
+ return true;
+ }
+
+
+void dThunderCloud::dieFall_Begin() {
+ this->Lightning.removeFromList();
+ this->timer = 0;
+ this->dEn_c::dieFall_Begin();
+}
+void dThunderCloud::dieFall_Execute() {
+ if (this->killFlag == 1) { return; }
+
+ 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::dieFall_Execute();
+
+ if (this->timer > 450) {
+
+ if ((this->settings >> 28) > 0) {
+ this->kill();
+ this->pos.y = this->pos.y + 800.0;
+ this->killFlag = 1;
+ return;
+ }
+
+ 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) {
+ this->pos.x = 0;
+ doStateChange(&StateID_Follow); }
+ else {
+ Player->pos;
+ this->pos.x = Player->pos.x - 300;
+ }
+
+ this->pos.y = this->Baseline;
+
+ this->aPhysics.addToList();
+ doStateChange(&StateID_Follow);
+ }
+}
+
+
+void dThunderCloud::bindAnimChr_and_setUpdateRate(const char* name, int unk, float unk2, float rate) {
+ nw4r::g3d::ResAnmChr anmChr = this->resFile.GetResAnmChr(name);
+ this->anm.bind(&this->bodyModel, anmChr, unk);
+ this->bodyModel.bindAnim(&this->anm, unk2);
+ this->anm.setUpdateRate(rate);
+}
+
+
+int dThunderCloud::onCreate() {
+
+ // Setup the model
+ allocator.link(-1, GameHeaps[0], 0, 0x20);
+
+ this->resFile.data = getResource("tcloud", "g3d/tcloud.brres");
+ nw4r::g3d::ResMdl mdl = this->resFile.GetResMdl("cloud");
+ bodyModel.setup(mdl, &allocator, 0x224, 1, 0);
+ SetupTextures_Enemy(&bodyModel, 0);
+
+ bool ret;
+ nw4r::g3d::ResAnmChr anmChr = this->resFile.GetResAnmChr("thundershoot");
+ ret = this->anm.setup(mdl, anmChr, &this->allocator, 0);
+
+ allocator.unlink();
+
+
+ // Scale and Physics
+ ActivePhysics::Info Cloud;
+ Cloud.xDistToCenter = 0.0;
+ Cloud.yDistToCenter = 0.0;
+ Cloud.category1 = 0x3;
+ Cloud.category2 = 0x0;
+ Cloud.bitfield1 = 0x4F;
+
+ Cloud.bitfield2 = 0xffbafffe;
+ Cloud.xDistToEdge = 18.0;
+ Cloud.yDistToEdge = 12.0;
+
+ Cloud.unkShort1C = 0;
+ Cloud.callback = &dEn_c::collisionCallback;
+
+ this->aPhysics.initWithStruct(this, &Cloud);
+ this->aPhysics.addToList();
+
+
+ ActivePhysics::Info Shock;
+ Shock.xDistToCenter = 0.0;
+ Shock.yDistToCenter = -104.0;
+ Shock.category1 = 0x3;
+ Shock.category2 = 0x9;
+ Shock.bitfield1 = 0x4F;
+
+ Shock.bitfield2 = 0xffbafffe;
+ Shock.xDistToEdge = 12.0;
+ Shock.yDistToEdge = 90.0;
+
+ Shock.unkShort1C = 0;
+ Shock.callback = &dEn_c::collisionCallback;
+
+ this->Lightning.initWithStruct(this, &Shock);
+
+
+ // Some Settings
+ this->Baseline = this->pos.y;
+ this->dying = -5;
+ this->killFlag = 0;
+ this->pos.z = 5750.0f; // sun
+
+ char eventNum = (this->settings >> 16) & 0xFF;
+
+ this->eventFlag = (u64)1 << (eventNum - 1);
+
+
+ // State Change!
+ doStateChange(&StateID_Follow);
+
+ this->onExecute();
+ return true;
+}
+
+int dThunderCloud::onDelete() {
+ return true;
+}
+
+int dThunderCloud::onExecute() {
+ acState.execute();
+ updateModelMatrices();
+ bodyModel._vf1C();
+
+ if (dFlagMgr_c::instance->flags & this->eventFlag) {
+ if (this->killFlag == 0) {
+ this->kill();
+ this->pos.y = this->pos.y + 800.0;
+ this->killFlag = 1;
+ doStateChange(&StateID_DieFall);
+ }
+ }
+
+ return true;
+}
+
+int dThunderCloud::onDraw() {
+ bodyModel.scheduleForDrawing();
+
+ return true;
+}
+
+
+void dThunderCloud::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);
+}
+
+
+// Follow State
+
+void dThunderCloud::beginState_Follow() {
+ this->timer = 0;
+ this->bindAnimChr_and_setUpdateRate("thundershoot", 1, 0.0, 1.0);
+ this->rot.x = 0;
+ this->rot.y = 0;
+ this->rot.z = 0;
+ PlaySound(this, SE_AMB_THUNDER_CLOUD);
+}
+void dThunderCloud::executeState_Follow() {
+
+ charge.spawn("Wm_mr_electricshock_biri02_s", 0, &pos, &(S16Vec){0,0,0}, &(Vec){1.5, 1.5, 1.5});
+
+ if(this->anm.isAnimationDone()) {
+ this->anm.setCurrentFrame(0.0); }
+
+ if (this->timer > 200) { this->doStateChange(&StateID_Lightning); }
+
+ this->direction = dSprite_c__getXDirectionOfFurthestPlayerRelativeToVEC3(this, this->pos);
+
+ float speedDelta;
+ speedDelta = 0.05;
+
+ if (this->direction == 0) {
+ this->speed.x = this->speed.x + speedDelta;
+
+ if (this->speed.x < 0) { this->speed.x = this->speed.x + (speedDelta / 1.5); }
+ if (this->speed.x < 6.0) { this->speed.x = this->speed.x + (speedDelta); }
+ }
+ else {
+ this->speed.x = this->speed.x - speedDelta;
+
+ if (this->speed.x > 0) { this->speed.x = this->speed.x - (speedDelta / 1.5); }
+ if (this->speed.x > 6.0) { this->speed.x = this->speed.x - (speedDelta); }
+ }
+
+ this->HandleXSpeed();
+
+ float yDiff;
+ yDiff = (this->Baseline - this->pos.y) / 8;
+ this->speed.y = yDiff;
+
+ this->HandleYSpeed();
+
+ this->UpdateObjectPosBasedOnSpeedValuesReal();
+
+ this->timer = this->timer + 1;
+}
+void dThunderCloud::endState_Follow() {
+ this->speed.y = 0;
+}
+
+
+// Wait State
+
+void dThunderCloud::beginState_Lightning() {
+ this->timer = 0;
+ this->speed.x = 0.0;
+}
+void dThunderCloud::executeState_Lightning() {
+
+ switch (timer) {
+ case 0:
+ charge.spawn("Wm_en_birikyu", 0, &(Vec){pos.x, pos.y, pos.z}, &(S16Vec){0,0,0}, &(Vec){1.5, 1.5, 1.5});
+ break;
+ case 1:
+ charge.spawn("Wm_en_birikyu", 0, &(Vec){pos.x, pos.y, pos.z}, &(S16Vec){0,0,0}, &(Vec){1.5, 1.5, 1.5});
+ break;
+ case 2:
+ this->Lightning.addToList();
+ PlaySound(this, SE_BOSS_JR_ELEC_APP);
+ PlaySound(this, SE_BOSS_JR_DAMAGE_ELEC);
+ PlaySound(this, SE_OBJ_KAZAN_ERUPTION);
+
+ bolt.spawn("Wm_jr_electricline", 0, &(Vec){pos.x, pos.y - 98.0, 0}, &(S16Vec){0,0,0}, &(Vec){1.0, 2.5, 1.0});
+ break;
+ case 3:
+ this->Lightning.removeFromList();
+ charge.spawn("Wm_mr_electricshock_biri02_s", 0, &pos, &(S16Vec){0,0,0}, &(Vec){1.5, 1.5, 1.5});
+ break;
+ case 4:
+ charge.spawn("Wm_mr_electricshock_biri02_s", 0, &pos, &(S16Vec){0,0,0}, &(Vec){1.5, 1.5, 1.5});
+ break;
+ case 5:
+ this->doStateChange(&StateID_Follow);
+ break;
+ default:
+ charge.spawn("Wm_mr_electricshock_biri02_s", 0, &pos, &(S16Vec){0,0,0}, &(Vec){1.5, 1.5, 1.5});
+ break;
+ }
+
+ if(this->anm.isAnimationDone() && this->anm.getCurrentFrame() != 0.0) {
+ this->timer += 1;
+ if (timer == 2) { this->bindAnimChr_and_setUpdateRate("thundershoot", 1, 0.0, 1.0); }
+ if (timer == 3) { this->bindAnimChr_and_setUpdateRate("cloud_wait", 1, 0.0, 1.0); }
+ this->anm.setCurrentFrame(0.0); }
+
+}
+void dThunderCloud::endState_Lightning() {
+ this->timer = 0;
+}
+
+