Path: blob/master/SonicMania/Objects/GHZ/DDWrecker.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: DDWrecker Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectDDWrecker *DDWrecker;1011void DDWrecker_Update(void)12{13RSDK_THIS(DDWrecker);14StateMachine_Run(self->state);1516RSDK.ProcessAnimation(&self->animator);1718if (self->type != DDWRECKER_CORE) {19if (self->invincibilityTimer > 0)20self->invincibilityTimer--;2122StateMachine_Run(self->stateBall);23}24}2526void DDWrecker_LateUpdate(void) {}2728void DDWrecker_StaticUpdate(void) {}2930void DDWrecker_Draw(void)31{32RSDK_THIS(DDWrecker);33if (self->type == DDWRECKER_BALL1 || self->type == DDWRECKER_BALL2) {34RSDK.SetActivePalette(1, 0, ScreenInfo->size.y);3536self->direction = self->animator.frameID >= 16;37if (!(self->invincibilityTimer & 2)) {38RSDK.SetLimitedFade(1, 2, 3, self->blendAmount, 1, 28);39}40else {41for (int32 i = 1; i < 0x1C; ++i) {42RSDK.SetPaletteEntry(1, i, 0xF0F0F0);43}44}45}46RSDK.DrawSprite(&self->animator, NULL, false);4748RSDK.SetActivePalette(0, 0, ScreenInfo->size.y);49}5051void DDWrecker_Create(void *data)52{53RSDK_THIS(DDWrecker);54if (!SceneInfo->inEditor) {55if (globals->gameMode == MODE_TIMEATTACK || globals->gameMode >= MODE_TIMEATTACK) {56destroyEntity(self);57}58else if (data) {59self->type = VOID_TO_INT(data);60self->active = ACTIVE_NORMAL;61switch (self->type) {62case DDWRECKER_BALL1: // main body63case DDWRECKER_BALL2:64RSDK.SetSpriteAnimation(DDWrecker->aniFrames, 0, &self->animator, true, 0);65self->drawFX = FX_FLIP | FX_ROTATE;66self->hitbox.left = -20;67self->hitbox.top = -20;68self->hitbox.right = 20;69self->hitbox.bottom = 20;70self->health = 3;71break;7273case DDWRECKER_CHAIN: // chains74RSDK.SetSpriteAnimation(DDWrecker->aniFrames, 4, &self->animator, true, 0);75break;7677case DDWRECKER_CORE: // core78RSDK.SetSpriteAnimation(DDWrecker->aniFrames, 5, &self->animator, true, 0);79break;8081default: break;82}8384self->visible = true;85self->drawGroup = Zone->objectDrawGroup[0];86}87else {88self->active = ACTIVE_BOUNDS;89self->updateRange.x = 0x800000;90self->updateRange.y = 0x800000;91self->visible = false;92self->state = DDWrecker_State_SetupArena;93}94}95}9697void DDWrecker_StageLoad(void)98{99DDWrecker->aniFrames = RSDK.LoadSpriteAnimation("GHZ/DDWrecker.bin", SCOPE_STAGE);100101DDWrecker->sfxBossHit = RSDK.GetSfx("Stage/BossHit.wav");102DDWrecker->sfxExplosion = RSDK.GetSfx("Stage/Explosion2.wav");103DDWrecker->sfxDrop = RSDK.GetSfx("Stage/Drop.wav");104DDWrecker->sfxImpact = RSDK.GetSfx("Stage/Impact2.wav");105DDWrecker->sfxAssemble = RSDK.GetSfx("Stage/Assemble.wav");106DDWrecker->sfxRotate = RSDK.GetSfx("Stage/Rotate.wav");107DDWrecker->sfxSharp = RSDK.GetSfx("Stage/Sharp.wav");108}109110void DDWrecker_State_SetupArena(void)111{112RSDK_THIS(DDWrecker);113if (++self->timer >= 8) {114self->timer = 0;115116Zone->playerBoundActiveL[0] = true;117Zone->playerBoundActiveR[0] = true;118Zone->playerBoundActiveB[0] = true;119Zone->cameraBoundsL[0] = FROM_FIXED(self->position.x) - ScreenInfo->center.x;120Zone->cameraBoundsR[0] = FROM_FIXED(self->position.x) + ScreenInfo->center.x;121Zone->cameraBoundsB[0] = FROM_FIXED(self->position.y);122123DDWrecker->camBoundL = self->position.x + ((160 - ScreenInfo->center.x) << 16);124DDWrecker->camBoundR = self->position.x + ((ScreenInfo->center.x - 160) << 16);125DDWrecker->bossBoundL = self->position.x + ((32 - ScreenInfo->center.x) << 16);126DDWrecker->bossBoundR = self->position.x + ((ScreenInfo->center.x - 32) << 16);127DDWrecker->bossBoundT = self->position.y - 0xC00000;128129DDWrecker->attackVelocities[0] = CLAMP(ScreenInfo->center.x - 168, 0, 24);130DDWrecker->attackVelocities[0] = (DDWrecker->attackVelocities[0] + 32) << 11;131DDWrecker->attackVelocities[1] = DDWrecker->attackVelocities[0] >> 2;132DDWrecker->attackVelocities[2] = 288 * DDWrecker->attackVelocities[0] >> 8;133134self->state = DDWrecker_State_InitChildren;135}136}137138void DDWrecker_State_InitChildren(void)139{140RSDK_THIS(DDWrecker);141if (self->timer) {142self->timer++;143if (self->timer == 60) {144EntityDDWrecker *chain1 = RSDK_GET_ENTITY(SceneInfo->entitySlot + 1, DDWrecker);145RSDK.ResetEntity(chain1, DDWrecker->classID, INT_TO_VOID(DDWRECKER_CHAIN));146chain1->position.x = self->position.x;147chain1->position.y = self->position.y + 0x400000;148149EntityDDWrecker *chain2 = RSDK_GET_ENTITY(SceneInfo->entitySlot + 2, DDWrecker);150RSDK.ResetEntity(chain2, DDWrecker->classID, INT_TO_VOID(DDWRECKER_CHAIN));151chain2->position.x = self->position.x;152chain2->position.y = self->position.y + 0x400000;153154EntityDDWrecker *chain3 = RSDK_GET_ENTITY(SceneInfo->entitySlot + 4, DDWrecker);155RSDK.ResetEntity(chain3, DDWrecker->classID, INT_TO_VOID(DDWRECKER_CHAIN));156chain3->position.x = self->position.x;157chain3->position.y = self->position.y + 0x400000;158159EntityDDWrecker *chain4 = RSDK_GET_ENTITY(SceneInfo->entitySlot + 5, DDWrecker);160RSDK.ResetEntity(chain4, DDWrecker->classID, INT_TO_VOID(DDWRECKER_CHAIN));161chain4->position.x = self->position.x;162chain4->position.y = self->position.y + 0x400000;163164EntityDDWrecker *core = RSDK_GET_ENTITY(SceneInfo->entitySlot + 3, DDWrecker);165RSDK.ResetEntity(core, DDWrecker->classID, INT_TO_VOID(DDWRECKER_CORE));166core->position.x = self->position.x;167core->position.y = self->position.y;168core->position.y += 0x200000;169core->originPos.x = self->position.x;170core->originPos.y = self->position.y;171core->originPos.y -= 0x800000;172core->velocity.y = -0x98000;173core->siblingSlots[0] = SceneInfo->entitySlot + 6; // Ball 1174core->siblingSlots[1] = SceneInfo->entitySlot + 1; // Chain 1175core->siblingSlots[2] = SceneInfo->entitySlot + 2; // Chain 2176core->siblingSlots[3] = SceneInfo->entitySlot + 4; // Chain 3177core->siblingSlots[4] = SceneInfo->entitySlot + 5; // Chain 4178core->siblingSlots[5] = SceneInfo->entitySlot + 7; // Ball 2179core->bodyA = RSDK_GET_ENTITY(SceneInfo->entitySlot + 6, DDWrecker);180core->bodyB = RSDK_GET_ENTITY(SceneInfo->entitySlot + 7, DDWrecker);181core->state = DDWrecker_State_Assemble;182183EntityDDWrecker *ball1 = RSDK_GET_ENTITY(SceneInfo->entitySlot + 6, DDWrecker);184RSDK.ResetEntity(ball1, DDWrecker->classID, INT_TO_VOID(DDWRECKER_BALL1));185ball1->position.x = self->position.x;186ball1->position.y = self->position.y;187ball1->position.y += 0x400000;188ball1->siblingSlots[1] = SceneInfo->entitySlot + 2; // Chain 1189ball1->siblingSlots[2] = SceneInfo->entitySlot + 3; // Chain 2190ball1->siblingSlots[0] = SceneInfo->entitySlot + 1; // Core191ball1->siblingSlots[3] = SceneInfo->entitySlot + 4; // Chain 3192ball1->siblingSlots[4] = SceneInfo->entitySlot + 5; // Chain 4193ball1->siblingSlots[5] = SceneInfo->entitySlot + 7; // Ball 2194ball1->bodyA = RSDK_GET_ENTITY(SceneInfo->entitySlot + 6, DDWrecker);195ball1->bodyB = RSDK_GET_ENTITY(SceneInfo->entitySlot + 7, DDWrecker);196ball1->radius = 64;197198EntityDDWrecker *ball2 = RSDK_GET_ENTITY(SceneInfo->entitySlot + 7, DDWrecker);199RSDK.ResetEntity(ball2, DDWrecker->classID, INT_TO_VOID(DDWRECKER_BALL2));200ball2->position.x = self->position.x;201ball2->position.y = self->position.y;202ball2->position.y += 0x400000;203ball2->siblingSlots[0] = SceneInfo->entitySlot + 1; // Chain 1204ball2->siblingSlots[1] = SceneInfo->entitySlot + 2; // Chain 2205ball2->siblingSlots[2] = SceneInfo->entitySlot + 3; // Core206ball2->siblingSlots[3] = SceneInfo->entitySlot + 4; // Chain 3207ball2->siblingSlots[4] = SceneInfo->entitySlot + 5; // Chain 4208ball2->siblingSlots[5] = SceneInfo->entitySlot + 6; // Ball 1209ball2->bodyB = RSDK_GET_ENTITY(SceneInfo->entitySlot + 7, DDWrecker);210ball2->bodyA = RSDK_GET_ENTITY(SceneInfo->entitySlot + 6, DDWrecker);211ball2->radius = 64;212213destroyEntity(self);214}215}216else {217EntityPlayer *player = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);218219if (player->position.x > self->position.x) {220Music_TransitionTrack(TRACK_MINIBOSS, 0.0125);221++self->timer;222}223}224}225226void DDWrecker_State_Assemble(void)227{228RSDK_THIS(DDWrecker);229230self->velocity.y += 0x4000;231self->position.y += self->velocity.y;232233if (self->position.y > self->originPos.y && self->velocity.y > 0) {234self->position.y = self->originPos.y;235self->velocity.y = 0;236self->radius = 2048;237self->spinTimer = 128;238self->state = DDWrecker_State_EnterWreckers;239RSDK.PlaySfx(DDWrecker->sfxAssemble, false, 255);240}241}242243void DDWrecker_State_EnterWreckers(void)244{245RSDK_THIS(DDWrecker);246247self->spinAngle = (self->spinAngle + (self->spinTimer >> 1)) & 0x3FF;248self->radius += (64 - self->radius) >> 4;249self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 2, 10);250251DDWrecker_Spin();252253if (self->spinTimer <= 0) {254self->timer = 30;255self->state = DDWrecker_State_AttackDelay;256foreach_active(DDWrecker, child)257{258if (child->type == DDWRECKER_BALL1 || child->type == DDWRECKER_BALL2)259child->stateBall = DDWrecker_StateBall_Vulnerable;260}261}262else {263self->spinTimer--;264}265}266267void DDWrecker_State_AttackDelay(void)268{269RSDK_THIS(DDWrecker);270271self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 2, 10);272273DDWrecker_Spin();274275if (--self->timer < 1) {276if (self->bodyA->position.y - self->bodyB->position.y < 0) {277self->bodyA->originPos.x = self->originPos.x;278self->bodyA->originPos.y = self->originPos.y - 0x400000;279self->bodyA->velocity.x = 0;280self->bodyA->angle = self->angle;281self->bodyA->spinAngle = 0;282self->bodyA->timer = 4;283self->bodyA->state = DDWrecker_State_SwingLeft;284}285else {286self->bodyB->originPos.x = self->originPos.x;287self->bodyB->originPos.y = self->originPos.y - 0x400000;288self->bodyB->velocity.x = 0;289self->bodyB->angle = self->angle;290self->bodyB->spinAngle = 512;291self->bodyB->timer = 4;292self->bodyB->state = DDWrecker_State_SwingRight;293}294295if (self->swapBalls) {296self->bodyA->stateBall = DDWrecker_StateBall_Vulnerable;297self->bodyB->stateBall = DDWrecker_StateBall_Spiked;298}299else {300self->bodyA->stateBall = DDWrecker_StateBall_Spiked;301self->bodyB->stateBall = DDWrecker_StateBall_Vulnerable;302}303304RSDK.PlaySfx(DDWrecker->sfxSharp, false, 255);305self->state = StateMachine_None;306}307}308309void DDWrecker_State_SwingRight(void)310{311RSDK_THIS(DDWrecker);312313if (self->spinAngle < 0x200) {314self->position.x += self->velocity.x;315if (self->position.x < DDWrecker->camBoundL)316self->position.x = DDWrecker->camBoundL;317}318319self->spinAngle += 4;320self->spinAngle &= 0x3FF;321self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 2, 10);322323DDWrecker_Swing();324325if (self->spinAngle >= 0x300) {326if (--self->timer <= 0) {327EntityDDWrecker *core = RSDK_GET_ENTITY(self->siblingSlots[2], DDWrecker);328core->velocity.x = (core->originPos.x - core->position.x) >> 6;329core->velocity.y = (core->originPos.y - core->position.y) >> 6;330core->spinTimer = -2;331core->spinAngle = self->spinAngle;332core->angle = 0;333core->timer = 64;334core->state = DDWrecker_State_SwingMoveToCenter;335if (self == self->bodyB)336core->spinAngle += 0x200;337self->state = StateMachine_None;338339self->bodyA->stateBall = DDWrecker_StateBall_Spiked;340self->bodyB->stateBall = DDWrecker_StateBall_Spiked;341RSDK.PlaySfx(DDWrecker->sfxSharp, false, 255);342}343else {344if (self->velocity.x)345self->velocity.x = DDWrecker->attackVelocities[0];346else347self->velocity.x = DDWrecker->attackVelocities[1];348349self->state = DDWrecker_State_SwingLeft;350351if (self->timer == 2) {352if (self->bodyA->stateBall == DDWrecker_StateBall_Vulnerable)353self->bodyA->stateBall = DDWrecker_StateBall_Spiked;354else355self->bodyA->stateBall = DDWrecker_StateBall_Vulnerable;356357if (self->bodyB->stateBall == DDWrecker_StateBall_Vulnerable)358self->bodyB->stateBall = DDWrecker_StateBall_Spiked;359else360self->bodyB->stateBall = DDWrecker_StateBall_Vulnerable;361RSDK.PlaySfx(DDWrecker->sfxSharp, false, 0xFF);362}363}364}365}366367void DDWrecker_State_SwingLeft(void)368{369RSDK_THIS(DDWrecker);370371if (self->spinAngle >= 0x200) {372self->position.x += self->velocity.x;373if (self->position.x > DDWrecker->camBoundR)374self->position.x = DDWrecker->camBoundR;375}376377self->spinAngle += 4;378self->spinAngle &= 0x3FF;379self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 2, 10);380381DDWrecker_Swing();382383if (self->spinAngle >= 0x100 && self->spinAngle < 0x200) {384if (--self->timer <= 0) {385EntityDDWrecker *core = RSDK_GET_ENTITY(self->siblingSlots[2], DDWrecker);386core->velocity.x = (core->originPos.x - core->position.x) >> 6;387core->velocity.y = (core->originPos.y - core->position.y) >> 6;388core->spinTimer = 2;389core->spinAngle = self->spinAngle;390core->angle = 0;391core->timer = 64;392core->state = DDWrecker_State_SwingMoveToCenter;393if (self == self->bodyB)394core->spinAngle += 512;395self->state = StateMachine_None;396397self->bodyA->stateBall = DDWrecker_StateBall_Spiked;398self->bodyB->stateBall = DDWrecker_StateBall_Spiked;399RSDK.PlaySfx(DDWrecker->sfxSharp, false, 0xFF);400}401else {402if (self->velocity.x)403self->velocity.x = -DDWrecker->attackVelocities[0];404else405self->velocity.x = -DDWrecker->attackVelocities[1];406407self->state = DDWrecker_State_SwingRight;408409if (self->timer == 2) {410if (self->bodyA->stateBall == DDWrecker_StateBall_Vulnerable)411self->bodyA->stateBall = DDWrecker_StateBall_Spiked;412else413self->bodyA->stateBall = DDWrecker_StateBall_Vulnerable;414415if (self->bodyB->stateBall == DDWrecker_StateBall_Vulnerable)416self->bodyB->stateBall = DDWrecker_StateBall_Spiked;417else418self->bodyB->stateBall = DDWrecker_StateBall_Vulnerable;419RSDK.PlaySfx(DDWrecker->sfxSharp, false, 0xFF);420}421}422}423}424425void DDWrecker_State_SwingMoveToCenter(void)426{427RSDK_THIS(DDWrecker);428429self->position.x += self->velocity.x;430self->position.y += self->velocity.y;431432if (self->velocity.x > 0) {433if (self->position.x > self->originPos.x) {434self->velocity.x = 0;435self->position.x = self->originPos.x;436}437}438else if (self->velocity.x < 0) {439if (self->position.x < self->originPos.x) {440self->velocity.x = 0;441self->position.x = self->originPos.x;442}443}444445if (self->velocity.y < 0) {446if (self->position.y < self->originPos.y) {447self->velocity.y = 0;448self->position.y = self->originPos.y;449}450}451else if (self->velocity.y > 0) {452if (self->position.y > self->originPos.y) {453self->velocity.y = 0;454self->position.y = self->originPos.y;455}456}457458if (!self->velocity.x && !self->velocity.y)459self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 2, 10);460461if (self->spinTimer <= 0) {462if (self->spinTimer > -141) {463self->spinTimer--;464}465else {466self->state = DDWrecker_State_HandleSpinning;467RSDK.PlaySfx(DDWrecker->sfxAssemble, false, 255);468}469}470else if (self->spinTimer >= 144) {471self->state = DDWrecker_State_HandleSpinning;472RSDK.PlaySfx(DDWrecker->sfxAssemble, false, 255);473}474else {475self->spinTimer++;476}477478self->spinAngle = (self->spinAngle + (self->spinTimer >> 2)) & 0x3FF;479480DDWrecker_Spin();481}482483void DDWrecker_State_HandleSpinning(void)484{485RSDK_THIS(DDWrecker);486487self->spinAngle = (self->spinAngle + (self->spinTimer >> 2)) & 0x3FF;488self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 2, 10);489490DDWrecker_Spin();491492if (!--self->timer) {493self->state = DDWrecker_State_SwingSlowDown;494495self->bodyA->stateBall = DDWrecker_StateBall_Vulnerable;496self->bodyB->stateBall = DDWrecker_StateBall_Vulnerable;497}498}499500void DDWrecker_State_SwingSlowDown(void)501{502RSDK_THIS(DDWrecker);503504if (self->spinTimer <= 0) {505if (self->spinTimer < -8)506self->spinTimer++;507}508else {509if (self->spinTimer > 8)510self->spinTimer--;511}512513self->spinAngle = (self->spinAngle + (self->spinTimer >> 2)) & 0x3FF;514self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 2, 10);515516DDWrecker_Spin();517518if (!(self->spinAngle & 0x1FC)) {519if (abs(self->spinTimer) <= 8) {520self->spinTimer = 0;521self->timer = 30;522self->spinAngle = (self->spinAngle + 0x80) & 0x300;523self->state = DDWrecker_State_AttackDelay;524}525}526}527528void DDWrecker_State_PrepareBounceAttack(void)529{530RSDK_THIS(DDWrecker);531532self->velocity.y -= 0x800;533self->position.x += self->velocity.x;534self->originPos.y += self->velocity.y;535536if (self->originPos.y < DDWrecker->bossBoundT) {537self->originPos.y = DDWrecker->bossBoundT;538self->velocity.y = 0;539}540541self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 2, 10);542543self->angleVel = 8;544if (self->position.x <= DDWrecker->bossBoundL) {545self->position.x = DDWrecker->bossBoundL;546self->velocity.x = 0;547548if (self->originPos.y <= DDWrecker->bossBoundT)549self->state = DDWrecker_State_SignalBounceAttackStart;550}551else if (self->position.x >= DDWrecker->bossBoundR) {552self->position.x = DDWrecker->bossBoundR;553self->velocity.x = 0;554555if (self->originPos.y <= DDWrecker->bossBoundT)556self->state = DDWrecker_State_SignalBounceAttackStart;557}558559if (self->rotation < 0) {560if (self->rotation + 2 > 0)561self->rotation = 0;562else563self->rotation += 2;564}565else if (self->rotation > 0) {566self->rotation -= 2;567if (self->rotation < 0)568self->rotation = 0;569}570571if (self->animator.animationID == 2) {572if (self->animator.frameID == self->animator.frameCount - 1)573RSDK.SetSpriteAnimation(DDWrecker->aniFrames, 0, &self->animator, true, 0);574}575else {576if (self->animator.animationID == 3 && !self->animator.frameID)577RSDK.SetSpriteAnimation(DDWrecker->aniFrames, 2, &self->animator, true, 0);578}579}580581void DDWrecker_State_SignalBounceAttackStart(void)582{583RSDK_THIS(DDWrecker);584585self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 2, 10);586587if (self->animator.animationID) {588if (self->animator.animationID == 1) {589if (self->animator.frameID == self->animator.frameCount - 1)590RSDK.SetSpriteAnimation(DDWrecker->aniFrames, 3, &self->animator, true, 0);591}592else {593if (self->animator.animationID == 3) {594if (self->animator.speed < 0x100) {595self->animator.speed += 2;596}597}598}599}600else {601RSDK.SetSpriteAnimation(DDWrecker->aniFrames, 1, &self->animator, true, 0);602RSDK.PlaySfx(DDWrecker->sfxSharp, false, 255);603}604605if (++self->timer == 30) {606self->timer = 0;607self->velocity.y = -0x20000;608self->state = DDWrecker_State_HandleBounceAttack;609RSDK.PlaySfx(DDWrecker->sfxDrop, false, 255);610}611}612613void DDWrecker_State_HandleBounceAttack(void)614{615RSDK_THIS(DDWrecker);616617self->velocity.y += 0x3800;618self->position.x += self->velocity.x;619self->position.y += self->velocity.y;620621self->animator.speed = 0x100 - 32 * self->timer;622623if (self->velocity.y > 0) {624if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, 0, 0, 0, 0x180000, true)) {625++self->timer;626Camera_ShakeScreen(0, 0, 3);627RSDK.PlaySfx(DDWrecker->sfxImpact, false, 255);628self->velocity.y = (self->velocity.y >> 3) - self->velocity.y;629630if (self->timer >= 2) {631if (self->timer == 3) {632self->velocity.y = 0;633self->timer = 0;634self->originPos.y = self->position.y;635self->angleVel = 8;636self->state = DDWrecker_State_EndBounceAttack;637}638}639else {640if (self->position.x - (DDWrecker->bossBoundL + 0x100000) > 0)641self->velocity.x = -DDWrecker->attackVelocities[2];642else643self->velocity.x = DDWrecker->attackVelocities[2];644}645}646}647}648649void DDWrecker_State_EndBounceAttack(void)650{651RSDK_THIS(DDWrecker);652653if (self->animator.animationID == 2) {654if (self->animator.frameID == self->animator.frameCount - 1)655RSDK.SetSpriteAnimation(DDWrecker->aniFrames, 0, &self->animator, true, 0);656}657else {658if (self->animator.animationID == 3 && !self->animator.frameID)659RSDK.SetSpriteAnimation(DDWrecker->aniFrames, 2, &self->animator, true, 0);660}661662if (++self->timer == 30) {663self->timer = 0;664self->state = DDWrecker_State_PrepareBounceAttack;665}666}667668void DDWrecker_StateBall_Vulnerable(void)669{670RSDK_THIS(DDWrecker);671672foreach_active(Player, player)673{674if (!self->invincibilityTimer && Player_CheckBadnikTouch(player, self, &self->hitbox) && Player_CheckBossHit(player, self)) {675DDWrecker_Hit();676RSDK.PlaySfx(DDWrecker->sfxBossHit, false, 255);677}678}679680if (self->angleVel > 0) {681if (self->angleVel > 8)682self->angleVel--;683684self->unusedAngle += self->angleVel;685if (self->unusedAngle >= 0x400) {686self->unusedAngle = 0;687self->angleVel = 0;688}689}690691if (self->animator.animationID == 2) {692if (self->animator.frameID == self->animator.frameCount - 1)693RSDK.SetSpriteAnimation(DDWrecker->aniFrames, 0, &self->animator, true, 0);694}695else if (self->animator.animationID == 3 && !self->animator.frameID) {696RSDK.SetSpriteAnimation(DDWrecker->aniFrames, 2, &self->animator, true, 0);697}698699if (self->blendAmount > 0)700self->blendAmount -= 0x10;701}702703void DDWrecker_StateBall_Spiked(void)704{705RSDK_THIS(DDWrecker);706707foreach_active(Player, player)708{709if (!self->invincibilityTimer && Player_CheckBadnikTouch(player, self, &self->hitbox)) {710if (player->invincibleTimer || player->blinkTimer > 0 || self->animator.animationID < 3) {711if (Player_CheckBossHit(player, self)) {712DDWrecker_Hit();713RSDK.PlaySfx(DDWrecker->sfxBossHit, false, 255);714}715}716else {717Player_Hurt(player, self);718}719}720}721722if (self->animator.animationID) {723if (self->animator.animationID == 1) {724if (self->animator.frameID == self->animator.frameCount - 1)725RSDK.SetSpriteAnimation(DDWrecker->aniFrames, 3, &self->animator, true, 0);726}727else if (self->animator.animationID == 3) {728if (self->animator.speed < 0x100)729self->animator.speed += 2;730}731}732else {733RSDK.SetSpriteAnimation(DDWrecker->aniFrames, 1, &self->animator, true, 0);734}735736if (self->angleVel < 48)737self->angleVel += 2;738739self->unusedAngle = (self->unusedAngle + self->angleVel) & 0x3FF;740741if (self->blendAmount < 0x100)742self->blendAmount += 0x10;743}744745void DDWrecker_StateBall_Partnerless(void)746{747RSDK_THIS(DDWrecker);748749foreach_active(Player, player)750{751if (!self->invincibilityTimer && Player_CheckBadnikTouch(player, self, &self->hitbox)) {752if (player->invincibleTimer || player->blinkTimer > 0 || self->animator.animationID < 3) {753if (Player_CheckBossHit(player, self)) {754DDWrecker_Hit();755RSDK.PlaySfx(DDWrecker->sfxBossHit, false, 255);756}757}758else {759Player_Hurt(player, self);760}761}762}763764self->unusedAngle = (self->unusedAngle + self->angleVel) & 0x3FF;765766if (self->animator.animationID == 0) {767if (self->blendAmount > 0)768self->blendAmount -= 0x10;769}770else if (self->blendAmount < 0x100)771self->blendAmount += 0x10;772}773void DDWrecker_Hit(void)774{775RSDK_THIS(DDWrecker);776777if (--self->health <= 0) {778self->state = DDWrecker_State_Die;779self->stateBall = StateMachine_None;780self->timer = 0;781foreach_active(DDWrecker, child)782{783if (self != child) {784switch (child->type) {785case DDWRECKER_BALL1:786case DDWRECKER_BALL2:787if (child->stateBall) {788child->state = DDWrecker_State_EndBounceAttack;789child->originPos.y = child->position.y;790child->velocity.x = -DDWrecker->attackVelocities[2];791child->stateBall = DDWrecker_StateBall_Partnerless;792}793break;794795case DDWRECKER_CHAIN:796case DDWRECKER_CORE:797if (child->state != DDWrecker_State_Debris) {798child->state = DDWrecker_State_Debris;799child->velocity.x = RSDK.Rand(-0x20000, 0x20000);800child->velocity.y = RSDK.Rand(-0x20000, 0x20000);801}802break;803804default: break;805}806}807}808}809else {810self->invincibilityTimer = 48;811RSDK.PlaySfx(DDWrecker->sfxBossHit, false, 255);812}813}814void DDWrecker_Spin(void)815{816RSDK_THIS(DDWrecker);817818for (int32 i = 0; i < 6; ++i) {819EntityDDWrecker *chain = RSDK_GET_ENTITY(self->siblingSlots[i], DDWrecker);820chain->position.x = self->position.x + (DDWrecker->spinOffset[i] * RSDK.Sin1024(self->spinAngle) * self->radius);821chain->position.y = self->position.y + (DDWrecker->spinOffset[i] * RSDK.Cos1024(self->spinAngle) * self->radius);822823int32 rot = chain->rotation;824if (rot < 0) {825if (rot < 0) {826rot += 2;827if (rot > 0)828chain->rotation = 0;829else830chain->rotation = rot;831}832}833else if (rot > 0) {834rot -= 2;835if (rot - 2 < 0)836chain->rotation = 0;837else838chain->rotation = rot;839}840}841}842void DDWrecker_Swing(void)843{844RSDK_THIS(DDWrecker);845int32 angle = RSDK.Sin1024(self->spinAngle) >> 2;846self->rotation = RSDK.Sin1024(-self->spinAngle) >> 6;847848if (!self->angleVel)849self->unusedAngle = RSDK.Sin1024(-self->spinAngle) >> 5;850851EntityDDWrecker *chain = NULL;852for (int32 i = 0; i < 6; ++i) {853chain = RSDK_GET_ENTITY(self->siblingSlots[i], DDWrecker);854chain->position.x = self->position.x + (DDWrecker->swingOffset[i] * RSDK.Sin1024(angle) * self->radius);855chain->position.y = self->position.y + (DDWrecker->swingOffset[i] * RSDK.Cos1024(angle) * self->radius);856}857chain->rotation = RSDK.Sin1024(-self->spinAngle) >> 5;858}859860void DDWrecker_Explode(void)861{862RSDK_THIS(DDWrecker);863864if (!(Zone->timer % 3)) {865RSDK.PlaySfx(DDWrecker->sfxExplosion, false, 255);866867if (Zone->timer & 4) {868int32 x = self->position.x + (RSDK.Rand(-20, 20) << 16);869int32 y = self->position.y + (RSDK.Rand(-20, 20) << 16);870EntityExplosion *explosion = CREATE_ENTITY(Explosion, INT_TO_VOID((RSDK.Rand(0, 256) > 192) + EXPLOSION_BOSS), x, y);871872explosion->drawGroup = Zone->objectDrawGroup[1];873}874}875}876877void DDWrecker_State_Debris(void)878{879RSDK_THIS(DDWrecker);880881self->velocity.y += 0x3800;882self->position.x += self->velocity.x;883self->position.y += self->velocity.y;884885if (!RSDK.CheckOnScreen(self, NULL))886destroyEntity(self);887}888889void DDWrecker_State_Die(void)890{891RSDK_THIS(DDWrecker);892893DDWrecker_Explode();894895if (++self->timer == 80) {896int32 cnt = 0;897foreach_active(DDWrecker, child) { ++cnt; }898899if (cnt != 1) {900destroyEntity(self);901}902else {903Music_TransitionTrack(TRACK_STAGE, 0.0125);904self->timer = 0;905self->visible = false;906self->state = DDWrecker_State_SpawnSignpost;907SceneInfo->timeEnabled = false;908Player_GiveScore(RSDK_GET_ENTITY(SLOT_PLAYER1, Player), 1000);909}910}911}912void DDWrecker_State_SpawnSignpost(void)913{914RSDK_THIS(DDWrecker);915916if (++self->timer == 48) {917foreach_all(SignPost, signPost)918{919signPost->position.x = self->position.x;920signPost->state = SignPost_State_Falling;921RSDK.PlaySfx(SignPost->sfxTwinkle, false, 255);922}923destroyEntity(self);924}925}926927#if GAME_INCLUDE_EDITOR928void DDWrecker_EditorDraw(void)929{930RSDK_THIS(DDWrecker);931932RSDK.SetSpriteAnimation(DDWrecker->aniFrames, 0, &self->animator, false, 0);933934RSDK.DrawSprite(&self->animator, NULL, false);935936if (showGizmos()) {937RSDK_DRAWING_OVERLAY(true);938DrawHelpers_DrawArenaBounds(-WIDE_SCR_XCENTER, -SCREEN_YSIZE, WIDE_SCR_XCENTER, 0, 1 | 0 | 4 | 8, 0x00C0F0);939940int32 slot = RSDK.GetEntitySlot(self);941for (int32 i = 0; i < 6; ++i) {942EntityDDWrecker *child = RSDK_GET_ENTITY(slot + 1 + i, DDWrecker);943944if (child)945DrawHelpers_DrawArrow(self->position.x, self->position.y, child->position.x, child->position.y, 0xFFFF00, INK_NONE, 0xFF);946}947948RSDK_DRAWING_OVERLAY(false);949}950}951952void DDWrecker_EditorLoad(void) { DDWrecker->aniFrames = RSDK.LoadSpriteAnimation("GHZ/DDWrecker.bin", SCOPE_STAGE); }953#endif954955void DDWrecker_Serialize(void) {}956957958