summaryrefslogtreecommitdiff
path: root/src/bossSamurshai.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/bossSamurshai.cpp')
-rw-r--r--src/bossSamurshai.cpp803
1 files changed, 803 insertions, 0 deletions
diff --git a/src/bossSamurshai.cpp b/src/bossSamurshai.cpp
new file mode 100644
index 0000000..fb906c2
--- /dev/null
+++ b/src/bossSamurshai.cpp
@@ -0,0 +1,803 @@
+#include <common.h>
+#include <game.h>
+#include <g3dhax.h>
+#include <sfx.h>
+#include "boss.h"
+
+const char* SSarcNameList [] = {
+ "Shynja",
+ NULL
+};
+
+void ChucklesAndKnuckles(ActivePhysics *apThis, ActivePhysics *apOther);
+
+class daSamurshai : public daBoss {
+ int onCreate();
+ int onDelete();
+ int onExecute();
+ int onDraw();
+
+ mHeapAllocator_c allocator;
+ nw4r::g3d::ResFile resFile;
+ m3d::mdl_c bodyModel;
+ m3d::anmChr_c chrAnimation;
+
+ mEf::es2 effect;
+
+ int isBigBoss;
+ int timer;
+ int jumpCounter;
+ char damage;
+ char isDown;
+ Vec initialPos;
+ float XSpeed;
+ u32 cmgr_returnValue;
+ dStageActor_c *chosenOne;
+ bool topHurts;
+ bool slowDown;
+ bool isBouncing;
+
+ ActivePhysics Chuckles;
+ ActivePhysics Knuckles;
+
+ static daSamurshai *build();
+
+ void bindAnimChr_and_setUpdateRate(const char* name, int unk, float unk2, float rate);
+ void updateModelMatrices();
+ bool calculateTileCollisions();
+
+ // void spriteCollision(ActivePhysics *apThis, ActivePhysics *apOther);
+ void playerCollision(ActivePhysics *apThis, ActivePhysics *apOther);
+ void yoshiCollision(ActivePhysics *apThis, ActivePhysics *apOther);
+
+ void collisionCat3_StarPower(ActivePhysics *apThis, ActivePhysics *apOther);
+ void collisionCat14_YoshiFire(ActivePhysics *apThis, ActivePhysics *apOther);
+ void collisionCatD_GroundPound(ActivePhysics *apThis, ActivePhysics *apOther);
+ void collisionCat7_WMWaggleWater(ActivePhysics *apThis, ActivePhysics *apOther);
+ void collisionCat7_WMWaggleWaterYoshi(ActivePhysics *apThis, ActivePhysics *apOther);
+ void collisionCat9_RollingObject(ActivePhysics *apThis, ActivePhysics *apOther);
+ void collisionCat1_Fireball_E_Explosion(ActivePhysics *apThis, ActivePhysics *apOther);
+ bool collisionCat2_IceBall_15_YoshiIce(ActivePhysics *apThis, ActivePhysics *apOther);
+ void collisionCat13_Hammer(ActivePhysics *apThis, ActivePhysics *apOther);
+ void collisionCatA_PenguinMario(ActivePhysics *apThis, ActivePhysics *apOther);
+
+ void _vf148();
+ void _vf14C();
+ int randomPlayer();
+
+ USING_STATES(daSamurshai);
+
+ DECLARE_STATE(Intro);
+ DECLARE_STATE(Walk);
+ DECLARE_STATE(Turn);
+ DECLARE_STATE(Chop);
+ DECLARE_STATE(ChargeSlash);
+ DECLARE_STATE(Uppercut);
+ DECLARE_STATE(SpinAttack);
+ DECLARE_STATE(Damage);
+ DECLARE_STATE(Outro);
+};
+
+daSamurshai *daSamurshai::build() {
+ void *buffer = AllocFromGameHeap1(sizeof(daSamurshai));
+ return new(buffer) daSamurshai;
+}
+
+///////////////////////
+// Externs and States
+///////////////////////
+ extern "C" int SmoothRotation(short* rot, u16 amt, int unk2);
+
+ CREATE_STATE(daSamurshai, Intro);
+ CREATE_STATE(daSamurshai, Walk);
+ CREATE_STATE(daSamurshai, Turn);
+ CREATE_STATE(daSamurshai, Chop);
+ CREATE_STATE(daSamurshai, ChargeSlash);
+ CREATE_STATE(daSamurshai, Uppercut);
+ CREATE_STATE(daSamurshai, SpinAttack);
+ CREATE_STATE(daSamurshai, Damage);
+ CREATE_STATE(daSamurshai, Outro);
+
+
+////////////////////////
+// Collision Functions
+////////////////////////
+
+ void ChucklesAndKnuckles(ActivePhysics *apThis, ActivePhysics *apOther) {
+ ((dEn_c*)apThis->owner)->_vf220(apOther->owner);
+ }
+
+ void daSamurshai::playerCollision(ActivePhysics *apThis, ActivePhysics *apOther) {
+
+ char hitType = usedForDeterminingStatePress_or_playerCollision(this, apThis, apOther, 2);
+
+ if (topHurts == true) {
+ this->dEn_c::playerCollision(apThis, apOther);
+ this->_vf220(apOther->owner);
+ }
+ else if ((hitType == 1) || (hitType == 3)) {
+ apOther->someFlagByte |= 2;
+ if (this->isDown == 0) {
+ this->playEnemyDownSound1();
+ damage += 4;
+ if (damage > 15) { doStateChange(&StateID_Outro); }
+ else { doStateChange(&StateID_Damage); }
+ }
+ }
+ else {
+ this->dEn_c::playerCollision(apThis, apOther);
+ this->_vf220(apOther->owner);
+ }
+
+ this->isDead = 0;
+ this->flags_4FC |= (1<<(31-7));
+ this->counter_504[apOther->owner->which_player] = 0;
+ }
+
+ void daSamurshai::yoshiCollision(ActivePhysics *apThis, ActivePhysics *apOther) { this->playerCollision(apThis, apOther); }
+ void daSamurshai::collisionCatD_GroundPound(ActivePhysics *apThis, ActivePhysics *apOther) { }
+ void daSamurshai::collisionCat7_WMWaggleWater(ActivePhysics *apThis, ActivePhysics *apOther) {
+ apOther->someFlagByte |= 2;
+
+ if (topHurts == true) {
+ this->dEn_c::playerCollision(apThis, apOther);
+ this->_vf220(apOther->owner);
+ }
+ else if (this->isDown == 0) {
+ damage += 6;
+ if (damage > 15) { doStateChange(&StateID_Outro); }
+ else { doStateChange(&StateID_Damage); }
+ }
+
+ this->isDead = 0;
+ this->flags_4FC |= (1<<(31-7));
+ this->counter_504[apOther->owner->which_player] = 0;
+ }
+ void daSamurshai::collisionCat7_WMWaggleWaterYoshi(ActivePhysics *apThis, ActivePhysics *apOther) { this->collisionCat7_WMWaggleWater(apThis, apOther); }
+ void daSamurshai::collisionCat9_RollingObject(ActivePhysics *apThis, ActivePhysics *apOther) {
+ if (this->isDown == 0) {
+ damage += 3;
+ if (damage > 2) { doStateChange(&StateID_Outro); }
+ else { doStateChange(&StateID_Damage); }
+ }
+ }
+ void daSamurshai::collisionCat3_StarPower(ActivePhysics *apThis, ActivePhysics *apOther){ }
+ void daSamurshai::collisionCatA_PenguinMario(ActivePhysics *apThis, ActivePhysics *apOther){
+ if (this->isDown == 0) {
+ damage += 3;
+ if (damage > 15) { doStateChange(&StateID_Outro); }
+ else { doStateChange(&StateID_Damage); }
+ }
+
+ this->isDead = 0;
+ this->flags_4FC |= (1<<(31-7));
+ this->counter_504[apOther->owner->which_player] = 0;
+ }
+ void daSamurshai::collisionCat14_YoshiFire(ActivePhysics *apThis, ActivePhysics *apOther){
+ damage += 4;
+ SpawnEffect("Wm_mr_fireball_hit", 0, &apOther->owner->pos, &apOther->owner->rot, &apOther->owner->scale);
+ PlaySoundAsync(this, SE_OBJ_FIREBALL_DISAPP);
+ if (damage > 15) { doStateChange(&StateID_Outro); }
+ }
+ void daSamurshai::collisionCat1_Fireball_E_Explosion(ActivePhysics *apThis, ActivePhysics *apOther) {
+ damage += 1;
+ SpawnEffect("Wm_mr_fireball_hit", 0, &apOther->owner->pos, &apOther->owner->rot, &apOther->owner->scale);
+ PlaySoundAsync(this, SE_OBJ_FIREBALL_DISAPP);
+ if (damage > 15) { doStateChange(&StateID_Outro); }
+ }
+ bool daSamurshai::collisionCat2_IceBall_15_YoshiIce(ActivePhysics *apThis, ActivePhysics *apOther) { return true; }
+ void daSamurshai::collisionCat13_Hammer(ActivePhysics *apThis, ActivePhysics *apOther) {
+ damage += 2;
+ this->spawnHitEffectAtPosition((Vec2){apOther->owner->pos.x, apOther->owner->pos.y});
+ if (damage > 15) { doStateChange(&StateID_Outro); }
+ }
+
+ bool daSamurshai::calculateTileCollisions() {
+ // Returns true if sprite should turn, false if not.
+
+ HandleXSpeed();
+ HandleYSpeed();
+ doSpriteMovement();
+
+ cmgr_returnValue = collMgr.CollidedWithTile();
+ collMgr.execute();
+
+ if (isBouncing) {
+ stuffRelatingToCollisions(0.1875f, 1.0f, 0.5f);
+ if (speed.y != 0.0f)
+ isBouncing = false;
+ }
+
+ float xDelta = pos.x - last_pos.x;
+ if (xDelta >= 0.0f)
+ direction = 0;
+ else
+ direction = 1;
+
+ if (collMgr.CollidedWithTile()) {
+ // Walking into a tile branch
+
+ if (cmgr_returnValue == 0)
+ isBouncing = true;
+
+ if (speed.x != 0.0f) {
+ //playWmEnIronEffect();
+ }
+
+ speed.y = 0.0f;
+
+ // u32 blah = collMgr.s_80070760();
+ // u8 one = (blah & 0xFF);
+ // static const float incs[5] = {0.00390625f, 0.0078125f, 0.015625f, 0.0234375f, 0.03125f};
+ // x_speed_inc = incs[one];
+ max_speed.x = (direction == 1) ? -1.0f : 1.0f;
+ } else {
+ x_speed_inc = 0.0f;
+ }
+
+ // Bouncing checks
+ if (_34A & 4) {
+ Vec v = (Vec){0.0f, 1.0f, 0.0f};
+ collMgr.parent_speed_ptr = &v;
+
+ if (collMgr.SomethingSemiImportant(collMgr.bitfield_for_checks))
+ speed.y = 0.0f;
+
+ collMgr.parent_speed_ptr = &speed;
+
+ } else {
+ if (collMgr.SomethingSemiImportant(collMgr.bitfield_for_checks))
+ speed.y = 0.0f;
+ }
+
+ collMgr.s_8006FA40(0);
+
+ // Switch Direction
+ if (collMgr.bitfield_for_checks & (0x15 << direction)) {
+ if (collMgr.CollidedWithTile()) {
+ isBouncing = true;
+ }
+ return true;
+ }
+ return false;
+ }
+
+void daSamurshai::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 daSamurshai::onCreate() {
+
+ isBigBoss = settings & 0xF;
+
+ // Model Setup
+ allocator.link(-1, GameHeaps[0], 0, 0x20);
+
+ this->resFile.data = getResource("Shynja", "g3d/Shynja.brres");
+ nw4r::g3d::ResMdl mdl = this->resFile.GetResMdl("Model");
+ bodyModel.setup(mdl, &allocator, 0x224, 1, 0);
+
+ // Animations start here
+ nw4r::g3d::ResAnmChr anmChr = this->resFile.GetResAnmChr("c18_IDLE_R");
+ this->chrAnimation.setup(mdl, anmChr, &this->allocator, 0);
+
+ allocator.unlink();
+
+ // Character Setup
+
+ scale = (Vec){20.0, 20.0, 20.0};
+
+ pos.y = pos.y + 40.0;
+ rot.x = 0; // X is vertical axis
+ rot.y = 0xD800; // Y is horizontal axis
+ rot.z = 0; // Z is ... an axis >.>
+ direction = 1; // Heading left.
+
+ speed.x = 0.0;
+ speed.y = 0.0;
+ XSpeed = 2.0;
+ x_speed_inc = 0.2;
+ initialPos = pos;
+ topHurts = false;
+
+ // Physics
+ ActivePhysics::Info HitMeBaby;
+
+ HitMeBaby.xDistToCenter = 0.0;
+ HitMeBaby.yDistToCenter = 12.0;
+
+ HitMeBaby.xDistToEdge = 14.0;
+ HitMeBaby.yDistToEdge = 12.0;
+
+ HitMeBaby.category1 = 0x3;
+ HitMeBaby.category2 = 0x0;
+ HitMeBaby.bitfield1 = 0x4F;
+ HitMeBaby.bitfield2 = 0xffbafffe;
+ HitMeBaby.unkShort1C = 0;
+ HitMeBaby.callback = &dEn_c::collisionCallback;
+
+ this->aPhysics.initWithStruct(this, &HitMeBaby);
+ this->aPhysics.addToList();
+
+ // Tile collider
+
+ // These fucking rects do something for the tile rect
+ spriteSomeRectX = 28.0f;
+ spriteSomeRectY = 32.0f;
+ _320 = 0.0f;
+ _324 = 16.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 (collMgr.CollidedWithTile())
+ isBouncing = false;
+ else
+ isBouncing = true;
+
+ // Sword Physics
+ // Chuckles is left, Knuckles is Right
+ ActivePhysics::Info iChuckles;
+ ActivePhysics::Info iKnuckles;
+
+ iChuckles.xDistToCenter = -27.0;
+ iChuckles.yDistToCenter = 12.0;
+ iChuckles.xDistToEdge = 27.0;
+ iChuckles.yDistToEdge = 10.0;
+
+ iKnuckles.xDistToCenter = 27.0;
+ iKnuckles.yDistToCenter = 12.0;
+ iKnuckles.xDistToEdge = 27.0;
+ iKnuckles.yDistToEdge = 10.0;
+
+ iKnuckles.category1 = iChuckles.category1 = 0x3;
+ iKnuckles.category2 = iChuckles.category2 = 0x0;
+ iKnuckles.bitfield1 = iChuckles.bitfield1 = 0x4F;
+ iKnuckles.bitfield2 = iChuckles.bitfield2 = 0x6;
+ iKnuckles.unkShort1C = iChuckles.unkShort1C = 0x0;
+ iKnuckles.callback = iChuckles.callback = ChucklesAndKnuckles;
+
+ Chuckles.initWithStruct(this, &iChuckles);
+ Knuckles.initWithStruct(this, &iKnuckles);
+
+ doStateChange(&StateID_Intro);
+
+ this->onExecute();
+ return true;
+}
+
+int daSamurshai::onDelete() {
+ return true;
+}
+int daSamurshai::onExecute() {
+ acState.execute();
+ updateModelMatrices();
+
+ return true;
+}
+int daSamurshai::onDraw() {
+ bodyModel.scheduleForDrawing();
+ bodyModel._vf1C();
+
+ return true;
+}
+void daSamurshai::updateModelMatrices() {
+ // This won't work with wrap because I'm lazy.
+ matrix.translation(pos.x, pos.y - 2.0, pos.z);
+ matrix.applyRotationYXZ(&rot.x, &rot.y, &rot.z);
+
+ bodyModel.setDrawMatrix(matrix);
+ bodyModel.setScale(&scale);
+ bodyModel.calcWorld(false);
+}
+
+
+///////////////
+// Intro State
+///////////////
+ void daSamurshai::beginState_Intro() {
+ this->timer = 0;
+
+ SetupKameck(this, Kameck);
+ }
+
+ void daSamurshai::executeState_Intro() {
+ this->timer += 1;
+
+ bool ret;
+ ret = GrowBoss(this, Kameck, 1.0, 5.0, 0, this->timer);
+
+ if (ret) {
+ PlaySound(this, SE_EMY_KURI_CHANGE_BIG);
+ doStateChange(&StateID_Walk);
+ }
+ }
+ void daSamurshai::endState_Intro() {
+ CleanupKameck(this, Kameck);
+ }
+
+///////////////
+// Walk State
+///////////////
+ int daSamurshai::randomPlayer() {
+ int players[4];
+ int playerCount = 0;
+
+ for (int i = 0; i < 4; i++) {
+ if (Player_Active[i] != 0 && Player_Lives[Player_ID[i]] > 0) {
+ players[playerCount] = i;
+ playerCount++;
+ }
+ }
+ return players[MakeRandomNumber(playerCount)];
+ }
+
+ void daSamurshai::beginState_Walk() {
+ bindAnimChr_and_setUpdateRate("c18_IDLE_R2", 1, 0.0, 2.0);
+
+ chosenOne = GetSpecificPlayerActor(this->randomPlayer());
+
+ this->max_speed.x = (this->direction) ? -this->XSpeed : this->XSpeed;
+ this->speed.x = (direction) ? -0.6f : 0.6f;
+ x_speed_inc = 0.2;
+
+ this->max_speed.y = -4.0;
+ this->speed.y = -4.0;
+ this->y_speed_inc = -0.1875;
+ }
+ void daSamurshai::executeState_Walk() {
+
+ float xDistance = pos.x - chosenOne->pos.x;
+ float yDistance = pos.y - chosenOne->pos.y;
+
+ OSReport("Distance: %f, %f", xDistance, yDistance);
+ if ((xDistance > 64.0) && (direction == 0)) { doStateChange(&StateID_Turn); }
+ if ((xDistance < -64.0) && (direction == 1)) { doStateChange(&StateID_Turn); }
+
+ if (xDistance < 0.0) { xDistance = -xDistance; }
+
+ // Condition for Chop
+ if (xDistance < 32.0) { doStateChange(&StateID_Chop); }
+
+ // Condition For Charge Slash
+ if (isBigBoss) {
+ if ((xDistance < 96.0) && (xDistance > 64.0)) {
+ int charge = MakeRandomNumber(100);
+ if (charge > 90) { doStateChange(&StateID_ChargeSlash); }
+ }
+ }
+
+ // Aerial Attacks!
+ if (yDistance > 24.0) {
+
+ // Condition For Spin Attack
+ if (xDistance < 32.0) { doStateChange(&StateID_SpinAttack); }
+
+ // Condition for Uppercut
+ if ((xDistance < 48.0) && (xDistance > 64.0)) { doStateChange(&StateID_Uppercut); }
+ }
+
+ bool ret = calculateTileCollisions();
+ if (ret) {
+ doStateChange(&StateID_Turn);
+ }
+
+ if(this->chrAnimation.isAnimationDone()) {
+ this->chrAnimation.setCurrentFrame(0.0);
+ }
+ }
+ void daSamurshai::endState_Walk() { }
+
+///////////////
+// Turn State
+///////////////
+ void daSamurshai::beginState_Turn() {
+ this->speed.x = (direction) ? -0.5f : 0.5f;
+ this->direction ^= 1;
+ x_speed_inc = 0.0;
+ }
+ void daSamurshai::executeState_Turn() {
+
+ if(this->chrAnimation.isAnimationDone()) {
+ this->chrAnimation.setCurrentFrame(0.0);
+ }
+
+ u16 amt = (this->direction == 0) ? 0x2800 : 0xD800;
+ int done = SmoothRotation(&this->rot.y, amt, 0x1000);
+
+ if(done) {
+ this->doStateChange(&StateID_Walk);
+ }
+ }
+ void daSamurshai::endState_Turn() { }
+
+///////////////
+// Chop State
+///////////////
+ void daSamurshai::beginState_Chop() {
+ bindAnimChr_and_setUpdateRate("c18_H_CUT_R", 1, 0.0, 1.0);
+ }
+ void daSamurshai::executeState_Chop() {
+
+ PlaySoundAsync(this, SE_EMY_CRASHER_PUNCH);
+
+ if (this->direction == 1) {
+ SpawnEffect("Wm_ob_itemget_ring", 0, &(Vec){pos.x - 18.0, pos.y + 16.0, pos.z}, &(S16Vec){0,0,0}, &(Vec){1.5, 0.5, 1.5});
+ Chuckles.addToList();
+ }
+ else {
+ SpawnEffect("Wm_ob_itemget_ring", 0, &(Vec){pos.x + 18.0, pos.y + 16.0, pos.z}, &(S16Vec){0,0,0}, &(Vec){1.5, 0.5, 1.5});
+ Knuckles.addToList();
+ }
+
+
+ if(this->chrAnimation.isAnimationDone()) {
+ if (this->direction == 1) {
+ SpawnEffect("Wm_ob_flagget_light", 0, &(Vec){pos.x - 38.0, pos.y + 16.0, pos.z}, &(S16Vec){0,0,0}, &(Vec){1.0, 1.0, 1.0});
+ SpawnEffect("Wm_en_hanapetal", 0, &(Vec){pos.x - 38.0, pos.y + 16.0, pos.z}, &(S16Vec){0,0,0}, &(Vec){2.0, 2.0, 2.0});
+ Chuckles.removeFromList();
+ }
+ else {
+ SpawnEffect("Wm_ob_flagget_light", 0, &(Vec){pos.x + 38.0, pos.y + 16.0, pos.z}, &(S16Vec){0,0,0}, &(Vec){1.0, 1.0, 1.0});
+ SpawnEffect("Wm_en_hanapetal", 0, &(Vec){pos.x + 38.0, pos.y + 16.0, pos.z}, &(S16Vec){0,0,0}, &(Vec){2.0, 2.0, 2.0});
+ Knuckles.removeFromList();
+ }
+
+ PlaySoundAsync(this, SE_EMY_BIG_PAKKUN_DAMAGE_1);
+
+ doStateChange(&StateID_Walk);
+ }
+ }
+ void daSamurshai::endState_Chop() { }
+
+///////////////
+// ChargeSlash State
+///////////////
+ void daSamurshai::beginState_ChargeSlash() {
+ this->timer = 0;
+
+ this->speed.x = 0.0;
+ this->max_speed.x = (this->direction) ? -8.0 : 8.0;
+ }
+ void daSamurshai::executeState_ChargeSlash() {
+
+ if (this->timer == 0) { bindAnimChr_and_setUpdateRate("c18_OB_IDLE_R", 1, 0.0, 1.0);
+ if (this->direction == 1)
+ SpawnEffect("Wm_ob_keyget02_lighit", 0, &(Vec){pos.x + 7.0, pos.y + 14.0, pos.z - 5500.0}, &(S16Vec){0,0,0}, &(Vec){0.8, 0.8, 0.8});
+ else
+ SpawnEffect("Wm_ob_keyget02_lighit", 0, &(Vec){pos.x - 7.0, pos.y + 14.0, pos.z + 5500.0}, &(S16Vec){0,0,0}, &(Vec){0.8, 0.8, 0.8});
+ }
+
+ if (this->timer == 40) {
+ speed.x = (direction) ? -8.0f : 8.0f;
+ topHurts = true;
+ }
+
+ if (this->timer > 41) {
+ if (slowDown == false) {
+ float xDistance = pos.x - chosenOne->pos.x;
+
+ if (xDistance < 8.0) {
+ bindAnimChr_and_setUpdateRate("c18_H_CUT_R", 1, 0.0, 2.0);
+ SpawnEffect("Wm_ob_itemget_ring", 0, &(Vec){pos.x, pos.y + 16.0, pos.z}, &(S16Vec){0,0,0}, &(Vec){2.0, 0.2, 1.5});
+ slowDown == true;
+ }
+ }
+ else {
+ speed.x = speed.x / 1.5;
+ }
+
+ if (speed.x == 0.0) {
+ topHurts = false;
+ timer = 500;
+ }
+ else {
+ effect.spawn("Wm_mr_p_iceslip", 0, &(Vec){pos.x, pos.y, pos.z}, &(S16Vec){0,0,0}, &(Vec){1.5, 1.5, 1.5});
+ SpawnEffect("Wm_en_hanapetal", 0, &pos, &(S16Vec){0,0,0}, &(Vec){1.5, 1.5, 1.5});
+ }
+ }
+
+ if (this->timer == 550) {
+ doStateChange(&StateID_Walk);
+ }
+
+ bool ret = calculateTileCollisions();
+ if (ret) {
+ if (slowDown = false) {
+ bindAnimChr_and_setUpdateRate("c18_H_CUT_R", 1, 0.0, 2.0);
+ SpawnEffect("Wm_ob_itemget_ring", 0, &(Vec){pos.x, pos.y + 16.0, pos.z}, &(S16Vec){0,0,0}, &(Vec){2.0, 0.2, 1.5});
+ slowDown == true;
+ }
+ speed.x = 0.0;
+ }
+
+ this->timer += 1;
+
+ }
+ void daSamurshai::endState_ChargeSlash() {
+ slowDown = false;
+ }
+
+///////////////
+// Uppercut State
+///////////////
+ void daSamurshai::beginState_Uppercut() {
+ bindAnimChr_and_setUpdateRate("c18_H_SHOT_R", 1, 0.0, 1.0);
+ slowDown = false;
+ }
+ void daSamurshai::executeState_Uppercut() {
+
+ if ((slowDown) && (this->chrAnimation.isAnimationDone())) {
+ doStateChange(&StateID_Walk);
+ }
+
+ if (slowDown) {
+ return;
+ }
+
+ if ((int)this->chrAnimation.getCurrentFrame() == 34) {
+ topHurts = true;
+ PlaySoundAsync(this, SE_EMY_CRASHER_PUNCH);
+
+ speed.y = 2.0;
+ y_speed_inc = -0.1875;
+
+ if (this->direction == 1) {
+ SpawnEffect("Wm_ob_itemget_ring", 0, &(Vec){pos.x - 18.0, pos.y + 16.0, pos.z}, &(S16Vec){0,0,0}, &(Vec){0.5, 1.5, 1.5});
+ Chuckles.addToList();
+ }
+ else {
+ SpawnEffect("Wm_ob_itemget_ring", 0, &(Vec){pos.x + 18.0, pos.y + 16.0, pos.z}, &(S16Vec){0,0,0}, &(Vec){0.5, 1.5, 1.5});
+ Knuckles.addToList();
+ }
+ }
+
+ if ((this->chrAnimation.isAnimationDone()) && (speed.y != 0)) {
+ if (topHurts) {
+ if (this->direction == 1) {
+ SpawnEffect("Wm_ob_flagget_light", 0, &(Vec){pos.x - 38.0, pos.y + 16.0, pos.z}, &(S16Vec){0,0,0}, &(Vec){1.0, 1.0, 1.0});
+ SpawnEffect("Wm_en_hanapetal", 0, &(Vec){pos.x - 38.0, pos.y + 16.0, pos.z}, &(S16Vec){0,0,0}, &(Vec){2.0, 2.0, 2.0});
+ Chuckles.removeFromList();
+ }
+ else {
+ SpawnEffect("Wm_ob_flagget_light", 0, &(Vec){pos.x + 38.0, pos.y + 16.0, pos.z}, &(S16Vec){0,0,0}, &(Vec){1.0, 1.0, 1.0});
+ SpawnEffect("Wm_en_hanapetal", 0, &(Vec){pos.x + 38.0, pos.y + 16.0, pos.z}, &(S16Vec){0,0,0}, &(Vec){2.0, 2.0, 2.0});
+ Knuckles.removeFromList();
+ }
+
+ PlaySoundAsync(this, SE_EMY_BIG_PAKKUN_DAMAGE_1);
+ topHurts = false;
+ }
+ }
+
+ if ((this->chrAnimation.isAnimationDone()) && (speed.y == 0.0)) {
+ bindAnimChr_and_setUpdateRate("c18_DIVING_STEAL_R", 1, 0.0, 1.0);
+ slowDown = true;
+ }
+
+ bool ret = calculateTileCollisions();
+
+ }
+ void daSamurshai::endState_Uppercut() { slowDown = false; }
+
+///////////////
+// SpinAttack State
+///////////////
+ void daSamurshai::beginState_SpinAttack() {
+ bindAnimChr_and_setUpdateRate("c18_NORMAL_STEAL_R", 1, 0.0, 1.0);
+ }
+ void daSamurshai::executeState_SpinAttack() {
+
+ if((int)this->chrAnimation.getCurrentFrame() == 20) {
+ topHurts = true;
+ PlaySoundAsync(this, SE_EMY_CRASHER_PUNCH);
+
+ speed.y = 3.0;
+ y_speed_inc = -0.1875;
+
+ if (this->direction == 1) { Chuckles.addToList(); }
+ else { Knuckles.addToList(); }
+ }
+
+ if (((int)chrAnimation.getCurrentFrame() > 20) && ((int)this->chrAnimation.getCurrentFrame() < 60)) {
+ scale = (Vec){1.0, 1.0, 1.0};
+ if (this->direction == 1) {
+ effect.spawn("Wm_mr_spinjump", 0, &(Vec){pos.x - 18.0, pos.y + 16.0, pos.z}, &(S16Vec){0,0,0}, &scale);
+ }
+ else {
+ effect.spawn("Wm_mr_spinjump", 0, &(Vec){pos.x + 18.0, pos.y + 16.0, pos.z}, &(S16Vec){0,0,0}, &scale);
+ }
+ }
+
+ if((int)this->chrAnimation.getCurrentFrame() == 65) {
+ topHurts = false;
+ PlaySoundAsync(this, SE_EMY_CRASHER_PUNCH);
+
+ if (this->direction == 1) { Chuckles.removeFromList(); }
+ else { Knuckles.removeFromList(); }
+ }
+
+ if ((this->chrAnimation.isAnimationDone()) && (speed.y == 0.0)) { doStateChange(&StateID_Walk); }
+
+ bool ret = calculateTileCollisions();
+
+ }
+ void daSamurshai::endState_SpinAttack() {
+ }
+
+///////////////
+// Damage State
+///////////////
+ void daSamurshai::beginState_Damage() {
+ bindAnimChr_and_setUpdateRate("c18_L_DMG_F_1_R", 1, 0.0, 2.0);
+
+ this->max_speed.x = 0;
+ this->speed.x = 0;
+ this->x_speed_inc = 0;
+
+ this->max_speed.y = -2.0;
+ this->speed.y = -2.0;
+ this->y_speed_inc = -0.1875;
+
+ this->timer = 0;
+ this->isDown = 1;
+ }
+ void daSamurshai::executeState_Damage() {
+ calculateTileCollisions();
+
+ // effect.spawn("Wm_en_spindamage", 0, &(Vec){pos.x, pos.y + 24.0, 0}, &(S16Vec){0,0,0}, &(Vec){1.0, 1.0, 1.0});
+
+ if (this->chrAnimation.isAnimationDone() && (collMgr.SomethingSemiImportant(collMgr.bitfield_for_checks))) {
+ if (timer == 0) { bindAnimChr_and_setUpdateRate("c18_L_DMG_F_3_R", 1, 0.0, 2.0); timer = 1; }
+ else if (timer == 1) { bindAnimChr_and_setUpdateRate("c18_L_DMG_F_4_R", 1, 0.0, 1.0); timer = 2; }
+ else if (timer == 2) { doStateChange(&StateID_Walk); }
+ }
+ }
+ void daSamurshai::endState_Damage() {
+ this->isDown = 0;
+ this->rot.y = (direction) ? 0xD800 : 0x2800;
+ }
+
+///////////////
+// Outro State
+///////////////
+ void daSamurshai::beginState_Outro() {
+
+ OutroSetup(this);
+ this->aPhysics.removeFromList();
+ }
+ void daSamurshai::executeState_Outro() {
+
+ if (this->dying == 1) {
+
+ if (this->timer > 180) { ExitStage(WORLD_MAP, 0, BEAT_LEVEL, MARIO_WIPE); }
+ if (this->timer == 60) { PlayerVictoryCries(this); }
+
+ this->timer += 1;
+ return;
+ }
+
+ bool ret;
+ ret = ShrinkBoss(this, &pos, 1.0, this->timer);
+
+ if (ret == true) {
+ BossExplode(this, &pos);
+ this->dying = 1;
+ this->timer = 0;
+ }
+ else { PlaySound(this, SE_EMY_BIG_KURIBO_DOWN); }
+
+ this->timer += 1;
+ }
+ void daSamurshai::endState_Outro() { }
+