#include #include #include #include #include "boss.h" class daKoopaBreath : public dEn_c { int onCreate(); int onExecute(); int onDelete(); int onDraw(); mHeapAllocator_c allocator; m3d::mdl_c bodyModel; int timer; char Kaboom; char direction; char front; float ymod; int lifespan; u32 cmgr_returnValue; static daKoopaBreath *build(); void updateModelMatrices(); void playerCollision(ActivePhysics *apThis, ActivePhysics *apOther); void collisionCat1_Fireball_E_Explosion(ActivePhysics *apThis, ActivePhysics *apOther); bool collisionCat2_IceBall_15_YoshiIce(ActivePhysics *apThis, ActivePhysics *apOther); void collisionCat9_RollingObject(ActivePhysics *apThis, ActivePhysics *apOther); void collisionCat13_Hammer(ActivePhysics *apThis, ActivePhysics *apOther); void collisionCat14_YoshiFire(ActivePhysics *apThis, ActivePhysics *apOther); void collisionCat7_WMWaggleWater(ActivePhysics *apThis, ActivePhysics *apOther); USING_STATES(daKoopaBreath); DECLARE_STATE(Straight); DECLARE_STATE(Kaboom); }; CREATE_STATE(daKoopaBreath, Straight); CREATE_STATE(daKoopaBreath, Kaboom); extern "C" void *PlayWrenchSound(dEn_c *); void daKoopaBreath::playerCollision(ActivePhysics *apThis, ActivePhysics *apOther) { DamagePlayer(this, apThis, apOther); } void daKoopaBreath::collisionCat1_Fireball_E_Explosion(ActivePhysics *apThis, ActivePhysics *apOther) { } bool daKoopaBreath::collisionCat2_IceBall_15_YoshiIce(ActivePhysics *apThis, ActivePhysics *apOther) { return false; } void daKoopaBreath::collisionCat9_RollingObject(ActivePhysics *apThis, ActivePhysics *apOther) {} void daKoopaBreath::collisionCat13_Hammer(ActivePhysics *apThis, ActivePhysics *apOther) { SpawnEffect("Wm_ob_cmnboxgrain", 0, &this->pos, &(S16Vec){0,0,0}, &(Vec){0.5, 0.5, 0.5}); PlaySoundAsync(this, SE_BOSS_JR_FLOOR_BREAK); this->Delete(1); } void daKoopaBreath::collisionCat14_YoshiFire(ActivePhysics *apThis, ActivePhysics *apOther) {} void daKoopaBreath::collisionCat7_WMWaggleWater(ActivePhysics *apThis, ActivePhysics *apOther) { this->_vf220(apOther->owner); SpawnEffect("Wm_ob_cmnboxgrain", 0, &this->pos, &(S16Vec){0,0,0}, &(Vec){0.5, 0.5, 0.5}); PlaySoundAsync(this, SE_BOSS_JR_FLOOR_BREAK); this->Delete(1); } daKoopaBreath *daKoopaBreath::build() { void *buffer = AllocFromGameHeap1(sizeof(daKoopaBreath)); return new(buffer) daKoopaBreath; } int daKoopaBreath::onCreate() { allocator.link(-1, GameHeaps[0], 0, 0x20); nw4r::g3d::ResFile rf(getResource("choropoo", "g3d/choropoo.brres")); bodyModel.setup(rf.GetResMdl("spanner"), &allocator, 0x224, 1, 0); SetupTextures_Enemy(&bodyModel, 0); allocator.unlink(); this->direction = this->settings & 0xF; this->Kaboom = (this->settings >> 4) & 0xF; this->front = (this->settings >> 8) & 0xF; ActivePhysics::Info HitMeBaby; if (this->Kaboom == 0) { HitMeBaby.xDistToCenter = 0.0; HitMeBaby.yDistToCenter = 0.0; HitMeBaby.xDistToEdge = 5.0; HitMeBaby.yDistToEdge = 5.0; this->scale.x = 1.25; this->scale.y = 1.25; this->scale.z = 1.25; } else { HitMeBaby.xDistToCenter = 0.0; HitMeBaby.yDistToCenter = 0.0; HitMeBaby.xDistToEdge = 8.0; HitMeBaby.yDistToEdge = 8.0; this->scale.x = 2.0; this->scale.y = 2.0; this->scale.z = 2.0; } HitMeBaby.category1 = 0x3; HitMeBaby.category2 = 0x0; HitMeBaby.bitfield1 = 0x47; HitMeBaby.bitfield2 = 0xFFFFFFFF; HitMeBaby.unkShort1C = 0; HitMeBaby.callback = &dEn_c::collisionCallback; this->aPhysics.initWithStruct(this, &HitMeBaby); this->aPhysics.addToList(); spriteSomeRectX = 5.0f; spriteSomeRectY = 5.0f; _320 = 0.0f; _324 = 5.0f; // These structs tell stupid collider what to collide with - these are from koopa troopa static const u8 one[16] = {0,0,0,1, 0,0,0xC0,0, 0,0,0x40,0, 0,0,0,0}; static const u8 two[12] = {0,0,0,0, 0,0,0,0, 0,0,0xC0,0}; static const u8 three[16] = {0,0,0,1, 0,0,0x60,0, 0,0,0x90,0, 0,0,0x60,0}; collMgr.Init(this, one, two, three); collMgr.execute(); cmgr_returnValue = collMgr.CollidedWithTile(); if (this->direction == 0) { // Ground Facing Left this->pos.x -= 0.0; // -32 to +32 this->pos.y += 36.0; this->rot.z = 0x2000; } else if (this->direction == 1) { // Ground Facing Right this->pos.x += 0.0; // +32 to -32 this->pos.y += 36.0; this->rot.z = 0xE000; } if (this->front == 1) { this->pos.z = -1804.0; } else { this->pos.z = 3300.0; } if (this->Kaboom) { doStateChange(&StateID_Kaboom); } else { doStateChange(&StateID_Straight); } this->onExecute(); return true; } int daKoopaBreath::onDelete() { return true; } int daKoopaBreath::onDraw() { bodyModel.scheduleForDrawing(); return true; } void daKoopaBreath::updateModelMatrices() { 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); } int daKoopaBreath::onExecute() { acState.execute(); updateModelMatrices(); return true; } void daKoopaBreath::beginState_Kaboom() { float rand = (float)GenerateRandomNumber(10) * 0.4; if (this->direction == 0) { // directions 1 spins clockwise, fly rightwards speed.x = 1.0 + rand; } else { // directions 0 spins anti-clockwise, fly leftwards speed.x = -1.0 - rand; } speed.y = 6.0; } void daKoopaBreath::executeState_Kaboom() { speed.y = speed.y - 0.01875; HandleXSpeed(); HandleYSpeed(); doSpriteMovement(); cmgr_returnValue = collMgr.CollidedWithTile(); collMgr.execute(); if (collMgr.CollidedWithTile()) { // hit the ground PlaySoundAsync(this, SE_BOSS_JR_BOMB_BURST); SpawnEffect("Wm_en_burst_s", 0, &this->pos, &(S16Vec){0,0,0}, &(Vec){0.75, 0.75, 0.75}); SpawnEffect("Wm_mr_wirehit", 0, &this->pos, &(S16Vec){0,0,0}, &(Vec){1.25, 1.25, 1.25}); this->Delete(1); } if (collMgr.bitfield_for_checks & (0x15 << direction)) { // hit the wall PlaySoundAsync(this, SE_BOSS_JR_BOMB_BURST); if (this->direction == 0) { // directions 1 spins clockwise, fly rightwards SpawnEffect("Wm_en_burst_s", 0, &this->pos, &(S16Vec){0,0x4000,0}, &(Vec){0.75, 0.75, 0.75}); SpawnEffect("Wm_mr_wirehit", 0, &this->pos, &(S16Vec){0,0x4000,0}, &(Vec){1.25, 1.25, 1.25}); } else { // directions 0 spins anti-clockwise, fly leftwards SpawnEffect("Wm_en_burst_s", 0, &this->pos, &(S16Vec){0,0xE000,0}, &(Vec){0.75, 0.75, 0.75}); SpawnEffect("Wm_mr_wirehit", 0, &this->pos, &(S16Vec){0,0xE000,0}, &(Vec){1.25, 1.25, 1.25}); } this->Delete(1); } if (this->direction == 1) { // directions 1 spins clockwise, fly rightwards this->rot.z -= 0x1000; } else { // directions 0 spins anti-clockwise, fly leftwards this->rot.z += 0x1000; } PlayWrenchSound(this); } void daKoopaBreath::endState_Kaboom() { } void daKoopaBreath::beginState_Straight() { float rand = (float)GenerateRandomNumber(10) * 0.4; if (this->direction == 0) { // directions 1 spins clockwise, fly rightwards speed.x = 1.0 + rand; } else { // directions 0 spins anti-clockwise, fly leftwards speed.x = -1.0 - rand; } speed.y = 6.0; } void daKoopaBreath::executeState_Straight() { speed.y = speed.y - 0.01875; HandleXSpeed(); HandleYSpeed(); doSpriteMovement(); cmgr_returnValue = collMgr.CollidedWithTile(); collMgr.execute(); if (collMgr.CollidedWithTile()) { // hit the ground PlaySoundAsync(this, SE_BOSS_JR_FLOOR_BREAK); SpawnEffect("Wm_en_burst_s", 0, &this->pos, &(S16Vec){0,0,0}, &(Vec){0.75, 0.75, 0.75}); this->Delete(1); } if (collMgr.bitfield_for_checks & (0x15 << direction)) { // hit the wall PlaySoundAsync(this, SE_BOSS_JR_FLOOR_BREAK); SpawnEffect("Wm_en_burst_s", 0, &this->pos, &(S16Vec){0,0,0}, &(Vec){0.75, 0.75, 0.75}); this->Delete(1); } if (this->direction == 1) { // directions 1 spins clockwise, fly rightwards this->rot.z -= 0x1000; } else { // directions 0 spins anti-clockwise, fly leftwards this->rot.z += 0x1000; } PlayWrenchSound(this); } void daKoopaBreath::endState_Straight() { } // Wm_en_explosion_smk