From e6a945496b2252477f1d5015343ce7e6cdda0cc4 Mon Sep 17 00:00:00 2001 From: Colin Noga Date: Sat, 17 Mar 2012 16:27:52 -0500 Subject: Added Captina Bowser and his crew of merry sprites, plus some fixes for other junk. --- bossCaptainBowser.yaml | 37 +++++ bossThwompaDomp.yaml | 2 +- spriteswapper.yaml | 13 +- src/boss.cpp | 12 +- src/bossCaptainBowser.cpp | 399 ++++++++++++++++++++++++++++++++++++++++++++++ src/bossFlameThrower.cpp | 313 ++++++++++++++++++++++++++++++++++++ src/bossKoopaThrow.cpp | 338 +++++++++++++++++++++++++++++++++++++++ src/bossWrenchThrow.cpp | 6 + src/spriteswapper.cpp | 86 ++++------ 9 files changed, 1137 insertions(+), 69 deletions(-) create mode 100644 bossCaptainBowser.yaml create mode 100644 src/bossCaptainBowser.cpp create mode 100644 src/bossFlameThrower.cpp create mode 100644 src/bossKoopaThrow.cpp diff --git a/bossCaptainBowser.yaml b/bossCaptainBowser.yaml new file mode 100644 index 0000000..5ac6970 --- /dev/null +++ b/bossCaptainBowser.yaml @@ -0,0 +1,37 @@ +--- +# Captain Bowser Replaces Mask +# +# KoopaThrow = WM_ANCHOR +# FlameThrower = WM_ANTLION_MGR + +source_files: [../src/bossCaptainBowser.cpp, ../src/bossKoopaThrow.cpp, ../src/bossFlameThrower.cpp] + +hooks: + - name: BossCaptainBoswerBuild + type: add_func_pointer + src_addr_pal: 0x80955978 + target_func: 'daCaptainBowser::build(void)' + + - name: KoopaThrowBuild + type: add_func_pointer + src_addr_pal: 0x80981960 + target_func: 'daKoopaThrow::build(void)' + + - name: UpdateKoopaThrowSpriteInfo + type: patch + addr_pal: 0x8030A4D0 + # [010] ( 16, 16) ( 0, 0 32: 32) 64? 64? 0? 0? | [0:No Flags] + data: '000A 0000 00000010 00000010 00000000 00000000 00000020 00000020 0040 0040 0000 0000 0000 0000' + # 0x8030A340 + sprite num * 0x28 == offset + + - name: KFlameThrowerBuild + type: add_func_pointer + src_addr_pal: 0x80981BD4 + target_func: 'daKoopaBreath::build(void)' + + - name: UpdateKoopaThrowSpriteInfo + type: patch + addr_pal: 0x8030A4F8 + # [011] ( 16, 16) ( 0, 0 32: 32) 64? 64? 0? 0? | [0:No Flags] + data: '000B 0000 00000010 00000010 00000000 00000000 00000020 00000020 0040 0040 0000 0000 0000 0000' + # 0x8030A340 + sprite num * 0x28 == offset diff --git a/bossThwompaDomp.yaml b/bossThwompaDomp.yaml index b087a17..4b439cd 100644 --- a/bossThwompaDomp.yaml +++ b/bossThwompaDomp.yaml @@ -9,7 +9,7 @@ hooks: target_func: 'daEnMegaDosun_c::build(void)' - - name: UpdateShyGuySpriteInfo + - name: UpdateThwompBossSpriteInfo type: patch addr_pal: 0x8030D5B4 #0x8030D590 # [204] ( 16, 48) ( 0, -24 16: 24) 64? 64? 0? 0? | [8:Environment?] diff --git a/spriteswapper.yaml b/spriteswapper.yaml index b5f882c..76bf7d5 100644 --- a/spriteswapper.yaml +++ b/spriteswapper.yaml @@ -3,13 +3,8 @@ source_files: [../src/spriteSwapper.cpp] hooks: - - name: SpriteSpawnerTimed_Create + - name: SpriteSpawnerTimedBuild type: add_func_pointer - src_addr_pal: 0x80B05E28 - target_func: 'SpriteSpawnerTimed_Create(SpriteSpawnerTimed *)' - - - name: SpriteSpawnerTimed_Execute - type: add_func_pointer - src_addr_pal: 0x80B05E40 - target_func: 'SpriteSpawnerTimed_Execute(SpriteSpawnerTimed *)' - \ No newline at end of file + src_addr_pal: 0x80B05E10 + target_func: 'SpriteSpawnerTimed::build(void)' + diff --git a/src/boss.cpp b/src/boss.cpp index b484171..e5be583 100644 --- a/src/boss.cpp +++ b/src/boss.cpp @@ -12,8 +12,15 @@ void DamagePlayer(dEn_c *actor, ActivePhysics *apThis, ActivePhysics *apOther) { // fix multiple player collisions via megazig actor->isDead = 0; actor->flags_4FC |= (1<<(31-7)); - actor->counter_504[apOther->owner->which_player] = 0; - OSReport("Player is good and hurt\n"); + if (apOther->owner->which_player == 255 ) { + actor->counter_504[0] = 0; + actor->counter_504[1] = 0; + actor->counter_504[2] = 0; + actor->counter_504[3] = 0; + } + else { + actor->counter_504[apOther->owner->which_player] = 0; + } } @@ -68,7 +75,6 @@ bool GrowBoss(daBoss *actor, daKameckDemo *Kameck, float initialScale, float end if (timer == 150) { PlaySound(actor, SE_BOSS_IGGY_WANWAN_TO_L); OSReport("Timer = 150\n"); } if ((timer > 150) && (timer < 230)) { - OSReport("Timer = %d\n", timer); scaleSpeed = (endScale -initialScale) / 80.0; float modifier; diff --git a/src/bossCaptainBowser.cpp b/src/bossCaptainBowser.cpp new file mode 100644 index 0000000..ce85f29 --- /dev/null +++ b/src/bossCaptainBowser.cpp @@ -0,0 +1,399 @@ +#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); } + } + else { dEn_c::spriteCollision(apThis, apOther); } + } + + 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.0); + } + else { + bindAnimChr_and_setUpdateRate("kp_wait", 1, 0.0, 1.5); + } + } + 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(10, 0x100 + ((num + 1) * 0x10), this->pos, 0, 0); + } + + if (this->chrAnimation.getCurrentFrame() == 126.0) { // throw front + int num = GenerateRandomNumber(4); + CreateActor(10, (num + 1) * 0x10, this->pos, 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, 0, this->pos, 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() { } diff --git a/src/bossFlameThrower.cpp b/src/bossFlameThrower.cpp new file mode 100644 index 0000000..70583fd --- /dev/null +++ b/src/bossFlameThrower.cpp @@ -0,0 +1,313 @@ +#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 + + + diff --git a/src/bossKoopaThrow.cpp b/src/bossKoopaThrow.cpp new file mode 100644 index 0000000..8c6d4ee --- /dev/null +++ b/src/bossKoopaThrow.cpp @@ -0,0 +1,338 @@ +#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() { } + + + + + + + + + diff --git a/src/bossWrenchThrow.cpp b/src/bossWrenchThrow.cpp index af5e272..5247c62 100644 --- a/src/bossWrenchThrow.cpp +++ b/src/bossWrenchThrow.cpp @@ -192,6 +192,12 @@ int daWrench::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; } diff --git a/src/spriteswapper.cpp b/src/spriteswapper.cpp index 2bc03d5..89ead56 100755 --- a/src/spriteswapper.cpp +++ b/src/spriteswapper.cpp @@ -1,17 +1,14 @@ #include #include -struct SpriteSpawnerTimed { - u32 id; // 0x00 - u32 settings; // 0x04 - u16 name; // 0x08 - u8 _0A[6]; // 0x0A - u8 _10[0x9C]; // 0x10 - float x; // 0xAC - float y; // 0xB0 - float z; // 0xB4 - u8 _B8[0x318]; // 0xB8 - // Any variables you add to the class go here; starting at offset 0x3D0 + +class SpriteSpawnerTimed : public dStageActor_c { +public: + int onCreate(); + int onExecute(); + + static SpriteSpawnerTimed *build(); + u64 eventFlag; // 0x3D0 u16 type; // 0x3D4 u32 inheritSet; // 0x3D6 @@ -24,68 +21,45 @@ struct EventTable_t { }; -struct VEC { - float x; - float y; - float z; -}; - +SpriteSpawnerTimed *SpriteSpawnerTimed::build() { + void *buffer = AllocFromGameHeap1(sizeof(SpriteSpawnerTimed)); + return new(buffer) SpriteSpawnerTimed; +} extern EventTable_t *EventTable; -extern "C" dStageActor_c *CreateActor(u16 classID, int settings, VEC pos, char rot, char layer); -extern "C" dStageActor_c *Actor_SearchByID(u32 actorID); - -void SpriteSpawnerTimed_Update(SpriteSpawnerTimed *self); - -#define ACTIVATE 1 -#define DEACTIVATE 0 - +extern "C" dStageActor_c *CreateActor(u16 classID, int settings, Vec pos, char rot, char layer); -bool SpriteSpawnerTimed_Create(SpriteSpawnerTimed *self) { +int SpriteSpawnerTimed::onCreate() { - char eventNum = (self->settings >> 28) & 0xF; + char eventNum = (this->settings >> 28) & 0xF; - self->eventFlag = (u64)1 << (eventNum - 1); - self->type = (self->settings >> 16) & 0xFFF; + this->eventFlag = (u64)1 << (eventNum - 1); + this->type = (this->settings >> 16) & 0xFFF; - short tempSet = self->settings & 0xFFFF; - self->inheritSet = (tempSet & 3) | ((tempSet & 0xC) << 2) | ((tempSet & 0x30) << 4) | ((tempSet & 0xC0) << 6) | ((tempSet & 0x300) << 8) | ((tempSet & 0xC00) << 10) | ((tempSet & 0x3000) << 12) | ((tempSet & 0xC000) << 14); + short tempSet = this->settings & 0xFFFF; + this->inheritSet = (tempSet & 3) | ((tempSet & 0xC) << 2) | ((tempSet & 0x30) << 4) | ((tempSet & 0xC0) << 6) | ((tempSet & 0x300) << 8) | ((tempSet & 0xC00) << 10) | ((tempSet & 0x3000) << 12) | ((tempSet & 0xC000) << 14); - self->timer = 0; - SpriteSpawnerTimed_Update(self); + this->timer = 0; return true; } -bool SpriteSpawnerTimed_Execute(SpriteSpawnerTimed *self) { - SpriteSpawnerTimed_Update(self); - return true; -} +int SpriteSpawnerTimed::onExecute() { - -void SpriteSpawnerTimed_Update(SpriteSpawnerTimed *self) { - - if (EventTable->events & self->eventFlag) - { - - if (self->timer == 0) - { - VEC pos; - pos.x = self->x; - pos.y = self->y; - pos.z = self->z; - - - dStageActor_c *spawned = CreateActor(self->type, self->inheritSet, pos, 0, 0); - self->timer = 120; + if (EventTable->events & this->eventFlag) { // If the event is on + if (this->timer < 1) { // If the timer is empty + CreateActor(this->type, this->inheritSet, this->pos, 0, 0); + this->timer = 120; } + this->timer--; } + else { - self->timer = 0; + this->timer = 0; } - self->timer--; -} + return true; +} \ No newline at end of file -- cgit v1.2.3