diff options
Diffstat (limited to '')
-rwxr-xr-x | src/thundercloud.cpp | 407 |
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; +} + + |