#include #include #include #include #include "boss.h" struct TypeInfo { const char *arcName; const char *brresName; const char *modelName; const char *deathEffect; int launchSound; int breakSound; int flySound; float size; float scale; u16 xrot; u16 yrot; u16 zrot; }; static const TypeInfo types[6] = { {"choropoo", "g3d/choropoo.brres", "spanner", "Wm_en_hit", 0, SE_BOSS_JR_FLOOR_BREAK, 0, 8.0f, 2.0f, 0, 0, 0x1000}, {"choropoo", "g3d/choropoo.brres", "spanner", "Wm_en_burst_s", 0, SE_BOSS_JR_BOMB_BURST, 0, 8.0f, 2.0f, 0, 0, 0x1000}, {"koopa_clown_bomb", "g3d/koopa_clown_bomb.brres", "koopa_clown_bomb", "Wm_en_burst_s", SE_BOSS_JR_BOMB_BOUND, SE_BOSS_JR_BOMB_BURST, 0, 8.0f, 1.0f, 0x200, 0x800, 0x1000}, {"bros", "g3d/t00.brres", "bros_hammer", "Wm_en_hit", 0, SE_OBJ_HAMMER_HIT_BOTH, SE_EMY_MEGA_BROS_HAMMER, 8.0f, 2.0f, 0, 0, 0x1000}, {"dossun", "g3d/t00.brres", "dossun", "Wm_en_hit", SE_EMY_DOSSUN, SE_EMY_DOSSUN_DEAD, 0, 8.0f, 1.0f, 0x100, 0x1000, 0x1000}, {"KoopaShip", "g3d/present.brres", "PresentBox_penguin", "Wm_dm_presentopen",SE_EMY_DOSSUN, SE_EMY_DOSSUN_DEAD, 0, 8.0f, 1.0f, 0x20, 0x40, 0x200} }; class daKoopaThrow : public dEn_c { int onCreate(); int onExecute(); int onDelete(); int onDraw(); mHeapAllocator_c allocator; m3d::mdl_c bodyModel; int timer; char Type; char direction; char front; float ymod; int lifespan; u32 cmgr_returnValue; const TypeInfo *currentInfo; static daKoopaThrow *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(daKoopaThrow); DECLARE_STATE(Straight); }; CREATE_STATE(daKoopaThrow, Straight); // Types: // // 0 - Wrench // 1 - Exploding Wrench // 2 - Bomb // 3 - Hammer // 4 - Thwomp // 5 - Present // extern "C" void *PlayWrenchSound(dEn_c *); void daKoopaThrow::playerCollision(ActivePhysics *apThis, ActivePhysics *apOther) { if (Type == 5) { PlaySoundAsync(this, currentInfo->breakSound); SpawnEffect(currentInfo->deathEffect, 0, &this->pos, &(S16Vec){0,0,0}, &(Vec){1.0, 1.0, 1.0}); CreateActor(EN_HATENA_BALLOON, 0x100, this->pos, 0, 0); this->Delete(1); } DamagePlayer(this, apThis, apOther); if (Type == 1 || Type == 2) { 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); } } void daKoopaThrow::collisionCat1_Fireball_E_Explosion(ActivePhysics *apThis, ActivePhysics *apOther) { } bool daKoopaThrow::collisionCat2_IceBall_15_YoshiIce(ActivePhysics *apThis, ActivePhysics *apOther) { return false; } void daKoopaThrow::collisionCat9_RollingObject(ActivePhysics *apThis, ActivePhysics *apOther) {} void daKoopaThrow::collisionCat13_Hammer(ActivePhysics *apThis, ActivePhysics *apOther) { if (Type == 1 || Type == 2) { 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}); } else { SpawnEffect("Wm_ob_cmnboxgrain", 0, &this->pos, &(S16Vec){0,0,0}, &(Vec){0.5, 0.5, 0.5}); } PlaySoundAsync(this, currentInfo->breakSound); this->Delete(1); } void daKoopaThrow::collisionCat14_YoshiFire(ActivePhysics *apThis, ActivePhysics *apOther) {} void daKoopaThrow::collisionCat7_WMWaggleWater(ActivePhysics *apThis, ActivePhysics *apOther) { DamagePlayer(this, apThis, apOther); if (Type == 1 || Type == 2) { 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); } } daKoopaThrow *daKoopaThrow::build() { OSReport("Building"); void *buffer = AllocFromGameHeap1(sizeof(daKoopaThrow)); OSReport("Built"); return new(buffer) daKoopaThrow; } int daKoopaThrow::onCreate() { this->direction = this->settings & 0xF; this->Type = (this->settings >> 4) & 0xF; this->front = (this->settings >> 8) & 0xF; OSReport("Type is %d", this->Type); currentInfo = &types[Type]; OSReport("Current Info is: %s, %s, %s", currentInfo->arcName, currentInfo->brresName, currentInfo->modelName); allocator.link(-1, GameHeaps[0], 0, 0x20); OSReport("Allocated"); nw4r::g3d::ResFile rf(getResource(currentInfo->arcName, currentInfo->brresName)); OSReport("Res File Gotten"); bodyModel.setup(rf.GetResMdl(currentInfo->modelName), &allocator, 0x224, 1, 0); OSReport("Body model setup"); SetupTextures_Enemy(&bodyModel, 0); OSReport("Textures setup"); allocator.unlink(); OSReport("Onwards to Physics"); ActivePhysics::Info KoopaJunk; KoopaJunk.xDistToCenter = 0.0; KoopaJunk.yDistToCenter = 0.0; KoopaJunk.xDistToEdge = currentInfo->size; KoopaJunk.yDistToEdge = currentInfo->size; this->scale.x = currentInfo->scale; this->scale.y = currentInfo->scale; this->scale.z = currentInfo->scale; KoopaJunk.category1 = 0x3; KoopaJunk.category2 = 0x0; KoopaJunk.bitfield1 = 0x47; KoopaJunk.bitfield2 = 0xFFFFFFFF; KoopaJunk.unkShort1C = 0; KoopaJunk.callback = &dEn_c::collisionCallback; this->aPhysics.initWithStruct(this, &KoopaJunk); this->aPhysics.addToList(); spriteSomeRectX = currentInfo->size; spriteSomeRectY = currentInfo->size; _320 = 0.0f; _324 = currentInfo->size; // 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 (currentInfo->launchSound != 0) { PlaySound(this, currentInfo->launchSound); } doStateChange(&StateID_Straight); this->onExecute(); return true; } int daKoopaThrow::onDelete() { return true; } int daKoopaThrow::onDraw() { bodyModel.scheduleForDrawing(); return true; } void daKoopaThrow::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 daKoopaThrow::onExecute() { acState.execute(); updateModelMatrices(); float rect[] = {this->_320, this->_324, this->spriteSomeRectX, this->spriteSomeRectY}; int ret = this->outOfZone(this->pos, (float*)&rect, this->currentZoneID); if(ret) { this->Delete(1); } return true; } void daKoopaThrow::beginState_Straight() { float rand = (float)GenerateRandomNumber(10) * 0.8; if (this->direction == 0) { // directions 1 spins clockwise, fly rightwards speed.x = 3.0 + rand; } else { // directions 0 spins anti-clockwise, fly leftwards speed.x = -3.0 - rand; } speed.y = 9.0; } void daKoopaThrow::executeState_Straight() { speed.y = speed.y - 0.01875; HandleXSpeed(); HandleYSpeed(); doSpriteMovement(); cmgr_returnValue = collMgr.CollidedWithTile(); collMgr.execute(); if (collMgr.CollidedWithTile() || (collMgr.bitfield_for_checks & (0x15 << direction))) { // hit the ground or wall PlaySoundAsync(this, currentInfo->breakSound); SpawnEffect(currentInfo->deathEffect, 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.x -= currentInfo->xrot; this->rot.y -= currentInfo->yrot; this->rot.z -= currentInfo->zrot; } else { // directions 0 spins anti-clockwise, fly leftwards this->rot.x -= currentInfo->xrot; this->rot.y -= currentInfo->yrot; this->rot.z += currentInfo->zrot; } if (Type < 2) { PlayWrenchSound(this); } else if (currentInfo->flySound == 0) { return; } else { PlaySound(this, currentInfo->flySound); } if (Type == 5) { if (this->speed.y < 0.0) { PlaySoundAsync(this, currentInfo->breakSound); SpawnEffect(currentInfo->deathEffect, 0, &this->pos, &(S16Vec){0,0,0}, &(Vec){1.0, 1.0, 1.0}); CreateActor(EN_HATENA_BALLOON, 0x100, this->pos, 0, 0); this->Delete(1); } } } void daKoopaThrow::endState_Straight() { }