#include #include #include #include #include #include "boss.h" void ShipPhysicsCallback(daBoss *self, dStageActor_c *other) { OSReport("Physics"); if (other->name == EN_CANNON_BULLET) { } } class daCaptainBowser : public daBoss { public: int onCreate(); int onDelete(); int onExecute(); int onDraw(); mHeapAllocator_c allocator; nw4r::g3d::ResFile resFile; nw4r::g3d::ResFile shipFile; m3d::mdl_c bodyModel; m3d::mdl_c shipModel; m3d::anmChr_c chrAnimation; m3d::anmChr_c shipAnm; Physics ShipPhysics; char isAngry; char isInvulnerable; // int isInvulnerableCountdown; // int isTurningCountdown; // char charging; // int flashing; static daCaptainBowser *build(); void bindAnimChr_and_setUpdateRate(const char* name, int unk, float unk2, float rate); void spriteCollision(ActivePhysics *apThis, ActivePhysics *apOther); void playerCollision(ActivePhysics *apThis, ActivePhysics *apOther); void addScoreWhenHit(void *other); USING_STATES(daCaptainBowser); DECLARE_STATE(Wait); DECLARE_STATE(Throw); DECLARE_STATE(Fire); DECLARE_STATE(Roar); DECLARE_STATE(Damage); DECLARE_STATE(Intro); DECLARE_STATE(Outro); }; daCaptainBowser *daCaptainBowser::build() { void *buffer = AllocFromGameHeap1(sizeof(daCaptainBowser)); return new(buffer) daCaptainBowser; } /////////////////////// // Externs and States /////////////////////// CREATE_STATE(daCaptainBowser, Wait); CREATE_STATE(daCaptainBowser, Throw); CREATE_STATE(daCaptainBowser, Fire); CREATE_STATE(daCaptainBowser, Roar); CREATE_STATE(daCaptainBowser, Damage); CREATE_STATE(daCaptainBowser, Intro); CREATE_STATE(daCaptainBowser, Outro); //////////////////////// // Collision Functions //////////////////////// void daCaptainBowser::addScoreWhenHit(void *other) { }; void daCaptainBowser::spriteCollision(ActivePhysics *apThis, ActivePhysics *apOther) { if (apOther->owner->name == EN_CANNON_BULLET) { //time to get hurt if (this->isInvulnerable) { return; } this->damage += 1; if (this->damage == 10) { doStateChange(&StateID_Roar); } else if (this->damage > 20) { doStateChange(&StateID_Outro); } else { doStateChange(&StateID_Damage); } } } void daCaptainBowser::playerCollision(ActivePhysics *apThis, ActivePhysics *apOther) { DamagePlayer(this, apThis, apOther); } void daCaptainBowser::bindAnimChr_and_setUpdateRate(const char* name, int unk, float unk2, float rate) { nw4r::g3d::ResAnmChr anmChr = this->resFile.GetResAnmChr(name); this->chrAnimation.bind(&this->bodyModel, anmChr, unk); this->bodyModel.bindAnim(&this->chrAnimation, unk2); this->chrAnimation.setUpdateRate(rate); } int daCaptainBowser::onCreate() { // Model creation allocator.link(-1, GameHeaps[0], 0, 0x20); // B-b-b-bad boy Bowsaa this->resFile.data = getResource("koopa", "g3d/koopa.brres"); nw4r::g3d::ResMdl mdl = this->resFile.GetResMdl("koopa"); bodyModel.setup(mdl, &allocator, 0x224, 1, 0); SetupTextures_Boss(&bodyModel, 0); nw4r::g3d::ResAnmChr anmChr = this->resFile.GetResAnmChr("kp_wait"); this->chrAnimation.setup(mdl, anmChr, &this->allocator, 0); // A ship off the ol' block this->shipFile.data = getResource("KoopaShip", "g3d/KoopaShip.brres"); nw4r::g3d::ResMdl mdlShip = this->shipFile.GetResMdl("KoopaShip"); shipModel.setup(mdlShip, &allocator, 0x224, 1, 0); // SetupTextures_MapObj(&shipModel, 0); nw4r::g3d::ResAnmChr anmChrShip = this->shipFile.GetResAnmChr("KoopaShip"); this->shipAnm.setup(mdlShip, anmChrShip, &this->allocator, 0); this->shipAnm.bind(&this->shipModel, anmChrShip, 1); this->shipModel.bindAnim(&this->shipAnm, 0.0); this->shipAnm.setUpdateRate(1.0); allocator.unlink(); // Prep the goods this->scale = (Vec){0.57, 0.57, 0.57}; // Ship Physics! // Normal rects are { left, top, right, bottom } // Callbacks are Touching upwards, Touching Downwards, and unknown ShipPhysics.baseSetup(this, &ShipPhysicsCallback, 0, 0, 1, 0); ShipPhysics.x = 8.0; ShipPhysics.y = 20.0; ShipPhysics.diameter = 12.0 * 16.0; ShipPhysics.isRound = 1; this->ShipPhysics.addToList(); // Bowser Physics! ActivePhysics::Info BowserPhysics; BowserPhysics.xDistToCenter = -152.0; BowserPhysics.yDistToCenter = 152.0; BowserPhysics.xDistToEdge = 38.0; BowserPhysics.yDistToEdge = 38.0; BowserPhysics.category1 = 0x3; BowserPhysics.category2 = 0x0; BowserPhysics.bitfield1 = 0x4F; BowserPhysics.bitfield2 = 0x8028E; BowserPhysics.unkShort1C = 0; BowserPhysics.callback = &dEn_c::collisionCallback; this->aPhysics.initWithStruct(this, &BowserPhysics); this->aPhysics.addToList(); // State Changers doStateChange(&StateID_Wait); return true; } int daCaptainBowser::onDelete() { return true; } int daCaptainBowser::onExecute() { acState.execute(); this->ShipPhysics.update(); bodyModel._vf1C(); shipModel._vf1C(); if(this->shipAnm.isAnimationDone()) { this->shipAnm.setCurrentFrame(0.0); } return true; } int daCaptainBowser::onDraw() { matrix.translation(pos.x-146.0, pos.y+122.0, pos.z-200.0); // 136.0 is the bottom of the platform footing short newrot = rot.y + 0xD800; matrix.applyRotationYXZ(&rot.x, &newrot, &rot.z); bodyModel.setDrawMatrix(matrix); bodyModel.setScale(&(Vec){1.0, 1.0, 1.0}); bodyModel.calcWorld(false); bodyModel.scheduleForDrawing(); matrix.translation(pos.x, pos.y, pos.z); newrot = rot.y + 0x4000; matrix.applyRotationYXZ(&rot.x, &newrot, &rot.z); shipModel.setDrawMatrix(matrix); shipModel.setScale(&scale); shipModel.calcWorld(false); shipModel.scheduleForDrawing(); return true; } ////////////////// // State Intro ////////////////// void daCaptainBowser::beginState_Intro() { } void daCaptainBowser::executeState_Intro() { } void daCaptainBowser::endState_Intro() { } ////////////////// // State Wait ////////////////// void daCaptainBowser::beginState_Wait() { if (this->isAngry == 0) { bindAnimChr_and_setUpdateRate("kp_wait", 1, 0.0, 1.5); } else { bindAnimChr_and_setUpdateRate("kp_wait", 1, 0.0, 2.0); } } void daCaptainBowser::executeState_Wait() { if (this->chrAnimation.isAnimationDone()) { this->chrAnimation.setCurrentFrame(0.0); int num = GenerateRandomNumber(4); if (num == 0) { doStateChange(&StateID_Fire); } else{ doStateChange(&StateID_Throw); } } } void daCaptainBowser::endState_Wait() { } ////////////////// // State Throw ////////////////// void daCaptainBowser::beginState_Throw() { bindAnimChr_and_setUpdateRate("break", 1, 0.0, 1.0); this->timer = 0; } void daCaptainBowser::executeState_Throw() { if (this->chrAnimation.getCurrentFrame() == 60.0) { // throw back int num = GenerateRandomNumber(5); CreateActor(0x29F, 0x101 + ((num + 1) * 0x10), (Vec){pos.x-146.0, pos.y+122.0, pos.z}, 0, 0); } if (this->chrAnimation.getCurrentFrame() == 126.0) { // throw front int num = GenerateRandomNumber(4); CreateActor(0x29F, ((num + 1) * 0x10) + 1, (Vec){pos.x-146.0, pos.y+122.0, pos.z}, 0, 0); } if (this->chrAnimation.isAnimationDone()) { this->chrAnimation.setCurrentFrame(0.0); if (this->isAngry == 1) { if (this->timer == 1) { doStateChange(&StateID_Wait); } } else { doStateChange(&StateID_Wait); } this->timer++; } } void daCaptainBowser::endState_Throw() { } ////////////////// // State Fire ////////////////// void daCaptainBowser::beginState_Fire() { bindAnimChr_and_setUpdateRate("fire1", 1, 0.0, 1.5); this->timer = 0; } void daCaptainBowser::executeState_Fire() { if (this->chrAnimation.getCurrentFrame() == 70) { // spit fire CreateActor(KOOPA_FIRE, 0x30, (Vec){pos.x-156.0, pos.y+128.0, pos.z}, 0, 0); // Seems like nyb 5 has a setting, 2 bits long, maybe. } if (this->chrAnimation.isAnimationDone()) { this->chrAnimation.setCurrentFrame(0.0); if (this->isAngry == 1) { if (this->timer == 1) { doStateChange(&StateID_Wait); } } else { doStateChange(&StateID_Wait); } this->timer++; } } void daCaptainBowser::endState_Fire() { } ////////////////// // State Roar ////////////////// void daCaptainBowser::beginState_Roar() { bindAnimChr_and_setUpdateRate("kp_roar3", 1, 0.0, 1.0); this->isInvulnerable = 1; } void daCaptainBowser::executeState_Roar() { if (this->chrAnimation.getCurrentFrame() == 53.0) { // This is where the smackdown starts SpawnEffect("Wm_ob_itemget_ring", 0, &this->pos, &(S16Vec){0,0,0}, &(Vec){1.0, 1.0, 1.0}); } if (this->chrAnimation.isAnimationDone()) { doStateChange(&StateID_Wait); } } void daCaptainBowser::endState_Roar() { this->isInvulnerable = 0; this->isAngry = 1; } ////////////////// // State Damage ////////////////// void daCaptainBowser::beginState_Damage() { bindAnimChr_and_setUpdateRate("grow_big", 1, 0.0, 1.0); this->isInvulnerable = 1; this->chrAnimation.setCurrentFrame(9.0); } void daCaptainBowser::executeState_Damage() { if (this->chrAnimation.getCurrentFrame() == 65.0) { // stop it here before it's too late doStateChange(&StateID_Wait); } } void daCaptainBowser::endState_Damage() { this->isInvulnerable = 0; } ////////////////// // State Outro ////////////////// void daCaptainBowser::beginState_Outro() { } void daCaptainBowser::executeState_Outro() { } void daCaptainBowser::endState_Outro() { }