Path: blob/master/SonicMania/Objects/LRZ/DrillerdroidO.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: DrillerdroidO Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectDrillerdroidO *DrillerdroidO;1011void DrillerdroidO_Update(void)12{13RSDK_THIS(DrillerdroidO);1415StateMachine_Run(self->state);16}1718void DrillerdroidO_LateUpdate(void) {}1920void DrillerdroidO_StaticUpdate(void)21{22if (DrillerdroidO->drillSfxTimer) {23if (!DrillerdroidO->playingDrillSfx) {24RSDK.PlaySfx(DrillerdroidO->sfxDrill, 43643, 0xFF);25DrillerdroidO->playingDrillSfx = true;26}2728DrillerdroidO->drillSfxTimer = 0;29}30else if (DrillerdroidO->playingDrillSfx) {31RSDK.StopSfx(DrillerdroidO->sfxDrill);32DrillerdroidO->playingDrillSfx = false;33}34}3536void DrillerdroidO_Draw(void)37{38RSDK_THIS(DrillerdroidO);3940StateMachine_Run(self->stateDraw);41}4243void DrillerdroidO_Create(void *data)44{45RSDK_THIS(DrillerdroidO);4647if (!SceneInfo->inEditor) {48if (globals->gameMode < MODE_TIMEATTACK) {49self->visible = true;5051if (data)52self->type = VOID_TO_INT(data);5354switch (self->type) {55case DRILLERDROIDO_MAIN:56self->active = ACTIVE_BOUNDS;57self->updateRange.x = 0x800000;58self->updateRange.y = 0x800000;5960RSDK.SetSpriteAnimation(DrillerdroidO->aniFrames, 0, &self->mainAnimator, true, 0);61RSDK.SetSpriteAnimation(DrillerdroidO->aniFrames, 5, &self->armorAnimator, true, 0);6263self->drawGroup = Zone->objectDrawGroup[1];6465DrillerdroidO->boss = self;66DrillerdroidO->childSlotStart = SceneInfo->entitySlot + 2;67DrillerdroidO->currentLevel = 4;6869self->state = DrillerdroidO_State_SetupArena;70self->stateDraw = DrillerdroidO_Draw_Boss;71break;7273case DRILLERDROIDO_FIREBALLEMITTER:74self->active = ACTIVE_BOUNDS;75self->drawFX = FX_FLIP;76self->updateRange.x = 0x800000;77self->updateRange.y = 0x800000;7879RSDK.SetSpriteAnimation(DrillerdroidO->ticFrames, 0, &self->mainAnimator, true, 0);8081self->drawGroup = Zone->objectDrawGroup[1];82self->state = DrillerdroidO_State_FireballEmitter;83self->stateDraw = DrillerdroidO_Draw_FireballEmitter;84break;8586case DRILLERDROIDO_TARGET:87case DRILLERDROIDO_UNUSED1:88case DRILLERDROIDO_UNUSED2:89self->active = ACTIVE_NORMAL;90self->drawFX = FX_FLIP;91self->updateRange.x = 0x800000;92self->updateRange.y = 0x800000;9394RSDK.SetSpriteAnimation(DrillerdroidO->aniFrames, 2, &self->mainAnimator, true, 0);95RSDK.SetSpriteAnimation(DrillerdroidO->aniFrames, 3, &self->armorAnimator, true, 0);9697self->drawGroup = Zone->objectDrawGroup[1];98self->state = DrillerdroidO_State_Target;99self->stateDraw = DrillerdroidO_Draw_Target;100break;101102default: break;103}104}105else {106destroyEntity(self);107}108}109}110111void DrillerdroidO_StageLoad(void)112{113if (RSDK.CheckSceneFolder("LRZ1"))114DrillerdroidO->aniFrames = RSDK.LoadSpriteAnimation("LRZ1/Drillerdroid.bin", SCOPE_STAGE);115116DrillerdroidO->ticFrames = RSDK.LoadSpriteAnimation("Global/TicMark.bin", SCOPE_STAGE);117118DrillerdroidO->hitboxCore.left = -25;119DrillerdroidO->hitboxCore.top = -16;120DrillerdroidO->hitboxCore.right = 25;121DrillerdroidO->hitboxCore.bottom = 16;122123DrillerdroidO->hitboxPistonL.left = -58;124DrillerdroidO->hitboxPistonL.top = -74;125DrillerdroidO->hitboxPistonL.right = -25;126DrillerdroidO->hitboxPistonL.bottom = 16;127128DrillerdroidO->hitboxPistonR.left = 25;129DrillerdroidO->hitboxPistonR.top = -74;130DrillerdroidO->hitboxPistonR.right = 58;131DrillerdroidO->hitboxPistonR.bottom = 16;132133DrillerdroidO->hitboxDrillL.left = -58;134DrillerdroidO->hitboxDrillL.top = 16;135DrillerdroidO->hitboxDrillL.right = -25;136DrillerdroidO->hitboxDrillL.bottom = 53;137138DrillerdroidO->hitboxDrillR.left = 25;139DrillerdroidO->hitboxDrillR.top = 16;140DrillerdroidO->hitboxDrillR.right = 58;141DrillerdroidO->hitboxDrillR.bottom = 53;142143DrillerdroidO->hitboxLandPosSegmentBreak.left = -6;144DrillerdroidO->hitboxLandPosSegmentBreak.top = 16;145DrillerdroidO->hitboxLandPosSegmentBreak.right = 6;146DrillerdroidO->hitboxLandPosSegmentBreak.bottom = 16;147148DrillerdroidO->hitboxLandPosR.left = -58;149DrillerdroidO->hitboxLandPosR.top = 37;150DrillerdroidO->hitboxLandPosR.right = -42;151DrillerdroidO->hitboxLandPosR.bottom = 53;152153DrillerdroidO->hitboxLandPosL.left = 42;154DrillerdroidO->hitboxLandPosL.top = 37;155DrillerdroidO->hitboxLandPosL.right = 58;156DrillerdroidO->hitboxLandPosL.bottom = 53;157158DrillerdroidO->hitboxEmitterRange.left = -32;159DrillerdroidO->hitboxEmitterRange.top = -192;160DrillerdroidO->hitboxEmitterRange.right = 32;161DrillerdroidO->hitboxEmitterRange.bottom = 192;162163DrillerdroidO->drillDelay[0] = 4;164DrillerdroidO->pistonDelay[0] = 4;165166DrillerdroidO->drillDelay[1] = 0;167DrillerdroidO->pistonDelay[1] = 0;168169DrillerdroidO->drillPos[0] = 0x100000;170DrillerdroidO->drillPos[1] = 0x100000;171172DrillerdroidO->pistonPos[0] = 0;173DrillerdroidO->pistonPos[1] = 0;174175DrillerdroidO->drillMoveDir[0] = FLIP_NONE;176DrillerdroidO->drillMoveDir[1] = FLIP_NONE;177178DrillerdroidO->pistonMoveDir[0] = FLIP_NONE;179DrillerdroidO->pistonMoveDir[1] = FLIP_NONE;180181DrillerdroidO->active = ACTIVE_ALWAYS;182183DrillerdroidO->drillSfxTimer = 0;184DrillerdroidO->playingDrillSfx = false;185186DrillerdroidO->emitFireballs = false;187188DrillerdroidO->sfxHit = RSDK.GetSfx("Stage/BossHit.wav");189DrillerdroidO->sfxExplosion = RSDK.GetSfx("Stage/Explosion2.wav");190DrillerdroidO->sfxDrill = RSDK.GetSfx("LRZ/Drill.wav");191DrillerdroidO->sfxImpact = RSDK.GetSfx("Stage/Impact4.wav");192DrillerdroidO->sfxJump = RSDK.GetSfx("LRZ/DrillJump.wav");193DrillerdroidO->sfxTargeting = RSDK.GetSfx("Stage/Targeting1.wav");194DrillerdroidO->sfxSizzle = RSDK.GetSfx("LRZ/Sizzle.wav");195}196197void DrillerdroidO_CheckPlayerCollisions(void)198{199RSDK_THIS(DrillerdroidO);200201if (self->invincibilityTimer)202self->invincibilityTimer--;203204foreach_active(Player, player)205{206int32 playerX = player->position.y;207int32 playerY = player->position.x;208int32 velX = player->velocity.x;209int32 velY = player->velocity.y;210int32 side = Player_CheckCollisionBox(player, self, &DrillerdroidO->hitboxCore);211212switch (side) {213default: break;214215case C_TOP:216Player_Hurt(player, self);217218if (self->velocity.y <= 0)219player->collisionFlagV |= 1;220break;221222case C_BOTTOM:223if (self->rotation) {224if (!self->invincibilityTimer) {225player->velocity.x = velX;226player->velocity.y = velY;227player->position.x = playerY;228player->position.y = playerX;229230if (Player_CheckBossHit(player, self)) {231if (!--self->health) {232SceneInfo->timeEnabled = false;233Player_GiveScore(RSDK_GET_ENTITY(SLOT_PLAYER1, Player), 1000);234self->invincibilityTimer = 60;235DrillerdroidO->emitFireballs = false;236self->state = DrillerdroidO_State_Destroyed;237}238else {239RSDK.PlaySfx(DrillerdroidO->sfxHit, false, 255);240self->invincibilityTimer = 30;241}242}243}244}245else if (self->velocity.y >= 0) {246player->collisionFlagV |= 2;247}248break;249}250251Player_CheckCollisionBox(player, self, &DrillerdroidO->hitboxPistonL);252Player_CheckCollisionBox(player, self, &DrillerdroidO->hitboxPistonR);253254if (self->state == DrillerdroidO_State_Drilling) {255if (Player_CheckCollisionTouch(player, self, &DrillerdroidO->hitboxDrillL)256|| Player_CheckCollisionTouch(player, self, &DrillerdroidO->hitboxDrillR)) {257Player_Hurt(player, self);258}259}260else {261if (self->state == DrillerdroidO_State_Dropping262&& (Player_CheckCollisionBox(player, self, &DrillerdroidO->hitboxDrillL) == C_BOTTOM263|| Player_CheckCollisionBox(player, self, &DrillerdroidO->hitboxDrillR) == C_BOTTOM)) {264if (self->velocity.y >= 0)265player->collisionFlagV |= 2;266else267Player_Hurt(player, self);268}269}270}271}272273void DrillerdroidO_Explode(void)274{275RSDK_THIS(DrillerdroidO);276277if (!(Zone->timer & 3)) {278RSDK.PlaySfx(Drillerdroid->sfxExplosion, false, 255);279280if (!(Zone->timer & 3)) {281int32 x = self->position.x + (RSDK.Rand(-19, 20) << 16);282int32 y = self->position.y + (RSDK.Rand(-24, 25) << 16);283CREATE_ENTITY(Explosion, INT_TO_VOID((RSDK.Rand(0, 256) > 192) + EXPLOSION_BOSS), x, y)->drawGroup = Zone->objectDrawGroup[1] + 2;284}285}286}287288void DrillerdroidO_SpawnDebris(int32 offset)289{290RSDK_THIS(DrillerdroidO);291292EntityDebris *debris = CREATE_ENTITY(Debris, Debris_State_Fall, offset + self->position.x, self->position.y + 0x400000);293RSDK.SetSpriteAnimation(DrillerdroidO->aniFrames, 1, &debris->animator, true, RSDK.Rand(0, 8));294debris->velocity.x = RSDK.Rand(0, 6) << 15;295debris->velocity.y = RSDK.Rand(-12, -8) << 15;296debris->gravityStrength = 0x3800;297debris->drawGroup = Zone->objectDrawGroup[0];298debris->updateRange.x = 0x400000;299debris->updateRange.y = 0x400000;300301debris = CREATE_ENTITY(Debris, Debris_State_Fall, offset + self->position.x, self->position.y + 0x400000);302RSDK.SetSpriteAnimation(DrillerdroidO->aniFrames, 1, &debris->animator, true, RSDK.Rand(0, 8));303debris->velocity.x = RSDK.Rand(-6, 0) << 15;304debris->velocity.y = RSDK.Rand(-12, -8) << 15;305debris->gravityStrength = 0x3800;306debris->drawGroup = Zone->objectDrawGroup[0];307debris->updateRange.x = 0x400000;308debris->updateRange.y = 0x400000;309}310311void DrillerdroidO_State_SetupArena(void)312{313RSDK_THIS(DrillerdroidO);314315if (++self->timer >= 2) {316self->timer = 0;317318Zone->playerBoundActiveR[0] = true;319Zone->playerBoundActiveB[0] = true;320Zone->cameraBoundsR[0] = (self->position.x >> 16) + ScreenInfo->center.x;321Zone->cameraBoundsB[0] = (self->position.y >> 16) + 96;322Zone->cameraBoundsT[0] = Zone->cameraBoundsB[0] - SCREEN_YSIZE;323324self->startY = self->position.y;325self->active = ACTIVE_NORMAL;326self->position.y = (ScreenInfo->position.y - 192) << 16;327self->visible = true;328self->state = DrillerdroidO_State_AwaitPlayer;329}330}331332void DrillerdroidO_State_AwaitPlayer(void)333{334RSDK_THIS(DrillerdroidO);335336Zone->playerBoundActiveL[0] = true;337Zone->cameraBoundsL[0] = ScreenInfo->position.x;338339if (RSDK_GET_ENTITY(SLOT_PLAYER1, Player)->position.x > self->position.x) {340Zone->playerBoundActiveL[0] = true;341Zone->cameraBoundsL[0] = (self->position.x >> 16) - ScreenInfo->center.x;342343Music_TransitionTrack(TRACK_MINIBOSS, 0.0125);344self->health = 6;345346CREATE_ENTITY(DrillerdroidO, INT_TO_VOID(DRILLERDROIDO_TARGET), self->position.x, self->startY);347self->position.x = 0;348349RSDK.PlaySfx(DrillerdroidO->sfxTargeting, false, 255);350self->state = DrillerdroidO_State_DecidingDropPos;351DrillerdroidO->canBreakSegment = true;352DrillerdroidO->emitFireballs = true;353}354}355356void DrillerdroidO_State_Dropping(void)357{358RSDK_THIS(DrillerdroidO);359360self->position.y += self->velocity.y;361self->velocity.y += 0x3800;362DrillerdroidO_CheckPlayerCollisions();363364if (self->position.y >= (Zone->cameraBoundsB[0] - 112) << 16) {365self->position.y = (Zone->cameraBoundsB[0] - 112) << 16;366RSDK.PlaySfx(DrillerdroidO->sfxImpact, false, 255);367368EntityCamera *camera = RSDK_GET_ENTITY(SLOT_CAMERA1, Camera);369if (!camera->shakePos.y)370camera->shakePos.y = 4;371372self->velocity.y >>= 1;373self->startY = self->position.y + 0x100000;374375if (!DrillerdroidO->canBreakSegment) {376for (int32 i = 0; i < 4; ++i) {377DrillerdroidO_SpawnDebris(-0x300000);378DrillerdroidO_SpawnDebris(0x300000);379DrillerdroidO_SpawnDebris(-0x190000);380DrillerdroidO_SpawnDebris(0x190000);381}382}383384EntityLRZRockPile *pile = RSDK_GET_ENTITY(SceneInfo->entitySlot + 1, LRZRockPile);385pile->timer = 1;386pile->canCollapse = true;387self->timer = 60;388self->angle = 0;389self->state = DrillerdroidO_State_Landed;390}391}392393void DrillerdroidO_State_Landed(void)394{395RSDK_THIS(DrillerdroidO);396397self->position.y += self->velocity.y;398self->velocity.y -= 0xE000;399400DrillerdroidO->drillPos[0] = self->startY - self->position.y;401DrillerdroidO->drillPos[1] = self->startY - self->position.y;402403DrillerdroidO_CheckPlayerCollisions();404405if (self->velocity.y < 0) {406if (self->position.y < self->startY)407self->state = DrillerdroidO_State_LandRecoil;408}409}410411void DrillerdroidO_State_LandRecoil(void)412{413RSDK_THIS(DrillerdroidO);414415self->position.y += self->velocity.y;416self->velocity.y += 0x14000;417418DrillerdroidO->drillPos[0] = self->startY - self->position.y;419DrillerdroidO->drillPos[1] = self->startY - self->position.y;420421DrillerdroidO_CheckPlayerCollisions();422423if (self->velocity.y > 0) {424if (self->position.y > self->startY) {425self->position.y = self->startY;426427DrillerdroidO->drillPos[0] = 0;428DrillerdroidO->drillPos[1] = 0;429430self->state = DrillerdroidO_State_BeginDrilling;431}432}433}434435void DrillerdroidO_State_BeginDrilling(void)436{437RSDK_THIS(DrillerdroidO);438439DrillerdroidO_CheckPlayerCollisions();440if (--self->timer <= 0) {441if (DrillerdroidO->canBreakSegment) {442EntityLavaGeyser *geyser = CREATE_ENTITY(LavaGeyser, NULL, self->position.x, self->position.y + 0x580000);443geyser->force = 56 << 12;444geyser->duration = 120;445geyser->drawGroup = Zone->objectDrawGroup[1];446geyser->state = LavaGeyser_HandleSetup;447}448449self->timer = 240;450self->state = DrillerdroidO_State_Drilling;451}452}453454void DrillerdroidO_State_Drilling(void)455{456RSDK_THIS(DrillerdroidO);457458++DrillerdroidO->drillSfxTimer;459RSDK.ProcessAnimation(&self->mainAnimator);460461for (int32 i = 0; i < 2; ++i) {462if (DrillerdroidO->pistonDelay[i]) {463DrillerdroidO->pistonDelay[i]--;464}465else if (DrillerdroidO->pistonMoveDir[i]) {466DrillerdroidO->pistonPos[i] -= 0x20000;467if (!DrillerdroidO->pistonPos[i]) {468DrillerdroidO->pistonMoveDir[i] = FLIP_NONE;469DrillerdroidO->pistonDelay[i] = 10;470}471}472else {473DrillerdroidO->pistonPos[i] += 0x40000;474if (DrillerdroidO->pistonPos[i] == 0x100000)475DrillerdroidO->pistonMoveDir[i] = FLIP_X;476}477478if (DrillerdroidO->drillDelay[i]) {479DrillerdroidO->drillDelay[i]--;480}481else if (DrillerdroidO->drillMoveDir[i]) {482DrillerdroidO->drillPos[i] -= 0x40000;483if (!DrillerdroidO->drillPos[i]) {484DrillerdroidO->drillMoveDir[i] = FLIP_NONE;485DrillerdroidO->drillDelay[i] = 5;486}487}488else {489DrillerdroidO->drillPos[i] += 0x80000;490if (DrillerdroidO->drillPos[i] == 0x100000)491DrillerdroidO->drillMoveDir[i] = FLIP_X;492}493}494495if (!DrillerdroidO->canBreakSegment) {496if (DrillerdroidO->drillPos[0] == 0x80000) {497DrillerdroidO_SpawnDebris(-0x300000);498DrillerdroidO_SpawnDebris(0x300000);499}500else if (DrillerdroidO->drillPos[1] == 0x80000) {501DrillerdroidO_SpawnDebris(-0x190000);502DrillerdroidO_SpawnDebris(0x190000);503}504}505506EntityCamera *camera = RSDK_GET_ENTITY(SLOT_CAMERA1, Camera);507if (!camera->shakePos.y)508camera->shakePos.y = 4;509510self->position.y ^= 0x10000;511DrillerdroidO_CheckPlayerCollisions();512513if (DrillerdroidO->canBreakSegment && self->timer < 180) {514if (self->alpha < 0x200)515self->alpha += 4;516}517518if (--self->timer <= 0)519self->state = DrillerdroidO_State_FinishDrilling;520}521522void DrillerdroidO_State_FinishDrilling(void)523{524RSDK_THIS(DrillerdroidO);525526DrillerdroidO->pistonPos[0] -= 0x20000;527if (DrillerdroidO->pistonPos[0] < 0)528DrillerdroidO->pistonPos[0] = 0;529530DrillerdroidO->pistonPos[1] -= 0x20000;531if (DrillerdroidO->pistonPos[1] < 0)532DrillerdroidO->pistonPos[1] = 0;533534DrillerdroidO->drillPos[0] -= 0x20000;535if (DrillerdroidO->drillPos[0] < 0)536DrillerdroidO->drillPos[0] = 0;537538DrillerdroidO->drillPos[1] -= 0x20000;539if (DrillerdroidO->drillPos[1] < 0)540DrillerdroidO->drillPos[1] = 0;541542if (!DrillerdroidO->pistonPos[0] && !DrillerdroidO->pistonPos[1] && !DrillerdroidO->drillPos[0] && !DrillerdroidO->drillPos[1]) {543self->timer = 60;544self->state = DrillerdroidO_State_Overheat;545}546}547548void DrillerdroidO_State_Overheat(void)549{550RSDK_THIS(DrillerdroidO);551552if (--self->timer <= 0) {553if (DrillerdroidO->canBreakSegment) {554DrillerdroidO->canBreakSegment = false;555RSDK.PlaySfx(DrillerdroidO->sfxSizzle, false, 255);556self->state = DrillerdroidO_State_OverheatRecoil_DestroyedSegment;557}558else {559self->state = DrillerdroidO_State_OverheatRecoil;560}561}562563DrillerdroidO_CheckPlayerCollisions();564}565566void DrillerdroidO_State_OverheatRecoil(void)567{568RSDK_THIS(DrillerdroidO);569570DrillerdroidO->drillPos[0] += 0x10000;571DrillerdroidO->drillPos[1] += 0x10000;572573self->position.y -= 0x10000;574575DrillerdroidO_CheckPlayerCollisions();576577if (DrillerdroidO->drillPos[0] == 0x100000) {578self->timer = 30;579self->state = DrillerdroidO_State_JumpTargetDelay;580}581}582583void DrillerdroidO_State_JumpTargetDelay(void)584{585RSDK_THIS(DrillerdroidO);586587DrillerdroidO_CheckPlayerCollisions();588589if (--self->timer <= 0) {590self->velocity.y = 0x78000;591RSDK.PlaySfx(DrillerdroidO->sfxJump, false, 0xFF);592self->state = DrillerdroidO_State_PrepareJumpTarget;593}594}595596void DrillerdroidO_State_PrepareJumpTarget(void)597{598RSDK_THIS(DrillerdroidO);599600self->position.y += self->velocity.y;601self->velocity.y -= 0x1C000;602603DrillerdroidO->drillPos[0] = self->startY - self->position.y;604DrillerdroidO->drillPos[1] = self->startY - self->position.y;605606if (self->velocity.y < 0) {607if (DrillerdroidO->drillPos[0] >= 0x100000) {608DrillerdroidO->drillPos[0] = 0x100000;609DrillerdroidO->drillPos[1] = 0x100000;610611self->state = DrillerdroidO_State_JumpTargeting;612}613}614}615616void DrillerdroidO_State_JumpTargeting(void)617{618RSDK_THIS(DrillerdroidO);619620self->position.y += self->velocity.y;621self->velocity.y += 0x3800;622623if (self->velocity.y >= 0) {624DrillerdroidO->drillDelay[0] = 4;625DrillerdroidO->pistonDelay[0] = 4;626627DrillerdroidO->drillDelay[1] = 0;628DrillerdroidO->pistonDelay[1] = 0;629630DrillerdroidO->drillPos[0] = 0x100000;631DrillerdroidO->drillPos[1] = 0x100000;632633DrillerdroidO->pistonPos[0] = 0;634DrillerdroidO->pistonPos[1] = 0;635636DrillerdroidO->pistonMoveDir[0] = FLIP_NONE;637DrillerdroidO->pistonMoveDir[1] = FLIP_NONE;638639DrillerdroidO->drillMoveDir[0] = FLIP_NONE;640DrillerdroidO->drillMoveDir[1] = FLIP_NONE;641642self->position.x = 0;643644if (self->health <= DrillerdroidO->currentLevel && DrillerdroidO->currentLevel) {645self->timer = 90;646DrillerdroidO->emitFireballs = false;647self->state = DrillerdroidO_State_DestroyRockPiles;648}649else {650EntityPlayer *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);651CREATE_ENTITY(DrillerdroidO, INT_TO_VOID(DRILLERDROIDO_TARGET), player1->position.x, player1->position.y)->target = player1;652653RSDK.PlaySfx(DrillerdroidO->sfxTargeting, false, 255);654self->state = DrillerdroidO_State_DecidingDropPos;655}656}657}658659void DrillerdroidO_State_DestroyRockPiles(void)660{661RSDK_THIS(DrillerdroidO);662663if (--self->timer <= 60) {664++DrillerdroidO->drillSfxTimer;665666EntityCamera *camera = RSDK_GET_ENTITY(SLOT_CAMERA1, Camera);667if (!camera->shakePos.y)668camera->shakePos.y = 4;669}670671if (self->timer <= 0) {672DrillerdroidO->currentLevel -= 2;673674for (int32 i = 0; i < 4; ++i) {675EntityLRZRockPile *pile = RSDK_GET_ENTITY(DrillerdroidO->childSlotStart++, LRZRockPile);676pile->timer = 1;677pile->canCollapse = true;678}679680self->timer = 30;681self->state = DrillerdroidO_State_NextLevelDelay;682}683}684685void DrillerdroidO_State_NextLevelDelay(void)686{687RSDK_THIS(DrillerdroidO);688689if (--self->timer <= 0) {690self->position.y += 0x1000000;691Zone->cameraBoundsB[0] += 256;692self->state = DrillerdroidO_State_MoveToNextLevel;693}694}695696void DrillerdroidO_State_MoveToNextLevel(void)697{698RSDK_THIS(DrillerdroidO);699700Zone->cameraBoundsT[0] = ScreenInfo->position.y;701702if (Zone->cameraBoundsT[0] == Zone->cameraBoundsB[0] - SCREEN_YSIZE) {703EntityPlayer *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);704CREATE_ENTITY(DrillerdroidO, INT_TO_VOID(DRILLERDROIDO_TARGET), player1->position.x, player1->position.y)->target = player1;705706RSDK.PlaySfx(DrillerdroidO->sfxTargeting, false, 255);707DrillerdroidO->emitFireballs = true;708self->state = DrillerdroidO_State_DecidingDropPos;709}710}711712void DrillerdroidO_State_DecidingDropPos(void)713{714RSDK_THIS(DrillerdroidO);715716if (self->position.x) {717self->timer = 240;718self->state = DrillerdroidO_State_Dropping;719720foreach_active(DrillerdroidO, fireballEmitter)721{722if (fireballEmitter->type == DRILLERDROIDO_FIREBALLEMITTER && self->position.y < fireballEmitter->position.y) {723if (RSDK.CheckObjectCollisionTouchBox(fireballEmitter, &DrillerdroidO->hitboxEmitterRange, self,724&DrillerdroidO->hitboxLandPosSegmentBreak)) {725self->position.x = fireballEmitter->position.x;726DrillerdroidO->canBreakSegment = true;727foreach_break;728}729}730}731732foreach_active(DrillerdroidO, emitter)733{734if (emitter->type == DRILLERDROIDO_FIREBALLEMITTER && self->position.y < emitter->position.y) {735if (RSDK.CheckObjectCollisionTouchBox(emitter, &DrillerdroidO->hitboxEmitterRange, self, &DrillerdroidO->hitboxLandPosR)) {736self->position.x = emitter->position.x + 0x550000;737foreach_break;738}739740if (RSDK.CheckObjectCollisionTouchBox(emitter, &DrillerdroidO->hitboxEmitterRange, self, &DrillerdroidO->hitboxLandPosL)) {741self->position.x = emitter->position.x - 0x550000;742foreach_break;743}744}745}746}747}748749void DrillerdroidO_State_OverheatRecoil_DestroyedSegment(void)750{751RSDK_THIS(DrillerdroidO);752753++self->rotation;754755DrillerdroidO->drillPos[0] += 0x4000;756DrillerdroidO->drillPos[1] += 0x4000;757758DrillerdroidO->pistonPos[0] += 0x4000;759DrillerdroidO->pistonPos[1] += 0x4000;760761self->position.y -= 0x4000;762763DrillerdroidO_CheckPlayerCollisions();764765if (DrillerdroidO->drillPos[0] == 0x100000) {766self->timer = 90;767self->state = DrillerdroidO_State_Cooldown;768}769}770771void DrillerdroidO_State_Cooldown(void)772{773RSDK_THIS(DrillerdroidO);774775DrillerdroidO_CheckPlayerCollisions();776777self->alpha -= 6;778if (self->alpha < 0)779self->alpha = 0;780781if (--self->timer <= 0)782self->state = DrillerdroidO_State_ResetFromCooldown;783}784785void DrillerdroidO_State_ResetFromCooldown(void)786{787RSDK_THIS(DrillerdroidO);788789self->rotation -= 4;790791DrillerdroidO->pistonPos[0] -= 0x10000;792DrillerdroidO->pistonPos[1] -= 0x10000;793794DrillerdroidO_CheckPlayerCollisions();795796if (!DrillerdroidO->pistonPos[0]) {797self->timer = 60;798self->state = DrillerdroidO_State_JumpTargetDelay;799}800}801802void DrillerdroidO_State_Destroyed(void)803{804RSDK_THIS(DrillerdroidO);805806DrillerdroidO_Explode();807808if (!--self->invincibilityTimer) {809EntityDebris *debris = CREATE_ENTITY(Debris, Debris_State_FallAndFlicker, self->position.x - 0x300000, self->position.y);810RSDK.SetSpriteAnimation(DrillerdroidO->aniFrames, 0, &debris->animator, true, 1);811debris->velocity.x = RSDK.Rand(-4, 4) << 15;812debris->velocity.y = RSDK.Rand(-8, -4) << 15;813debris->gravityStrength = 0x3800;814debris->drawGroup = Zone->objectDrawGroup[1];815debris->updateRange.x = 0x400000;816debris->updateRange.y = 0x400000;817818debris = CREATE_ENTITY(Debris, Debris_State_FallAndFlicker, self->position.x - 0x300000, self->position.y);819RSDK.SetSpriteAnimation(DrillerdroidO->aniFrames, 0, &debris->animator, true, 2);820debris->velocity.x = RSDK.Rand(-4, 4) << 15;821debris->velocity.y = RSDK.Rand(0, 2) << 15;822debris->gravityStrength = 0x3800;823debris->drawGroup = Zone->objectDrawGroup[1];824debris->updateRange.x = 0x400000;825debris->updateRange.y = 0x400000;826827debris = CREATE_ENTITY(Debris, Debris_State_FallAndFlicker, self->position.x - 0x230000, self->position.y);828RSDK.SetSpriteAnimation(DrillerdroidO->aniFrames, 0, &debris->animator, true, 1);829debris->velocity.x = RSDK.Rand(-4, 4) << 15;830debris->velocity.y = RSDK.Rand(-8, -4) << 15;831debris->gravityStrength = 0x3800;832debris->drawGroup = Zone->objectDrawGroup[1];833debris->updateRange.x = 0x400000;834debris->updateRange.y = 0x400000;835836debris = CREATE_ENTITY(Debris, Debris_State_FallAndFlicker, self->position.x - 0x230000, self->position.y);837RSDK.SetSpriteAnimation(DrillerdroidO->aniFrames, 0, &debris->animator, true, 2);838debris->velocity.x = RSDK.Rand(-4, 4) << 15;839debris->velocity.y = RSDK.Rand(0, 2) << 15;840debris->gravityStrength = 0x3800;841debris->drawGroup = Zone->objectDrawGroup[1];842debris->updateRange.x = 0x400000;843debris->updateRange.y = 0x400000;844845debris = CREATE_ENTITY(Debris, Debris_State_FallAndFlicker, self->position.x + 0x300000, self->position.y);846RSDK.SetSpriteAnimation(DrillerdroidO->aniFrames, 0, &debris->animator, true, 1);847debris->velocity.x = RSDK.Rand(-4, 4) << 15;848debris->velocity.y = RSDK.Rand(-8, -4) << 15;849debris->gravityStrength = 0x3800;850debris->drawGroup = Zone->objectDrawGroup[1];851debris->updateRange.x = 0x400000;852debris->updateRange.y = 0x400000;853854debris = CREATE_ENTITY(Debris, Debris_State_FallAndFlicker, self->position.x + 0x300000, self->position.y);855RSDK.SetSpriteAnimation(DrillerdroidO->aniFrames, 0, &debris->animator, true, 2);856debris->velocity.x = RSDK.Rand(-4, 4) << 15;857debris->velocity.y = RSDK.Rand(0, 2) << 15;858debris->gravityStrength = 0x3800;859debris->drawGroup = Zone->objectDrawGroup[1];860debris->updateRange.x = 0x400000;861debris->updateRange.y = 0x400000;862863debris = CREATE_ENTITY(Debris, Debris_State_FallAndFlicker, self->position.x + 0x230000, self->position.y);864RSDK.SetSpriteAnimation(DrillerdroidO->aniFrames, 0, &debris->animator, true, 1);865debris->velocity.x = RSDK.Rand(-4, 4) << 15;866debris->velocity.y = RSDK.Rand(-8, -4) << 15;867debris->gravityStrength = 0x3800;868debris->drawGroup = Zone->objectDrawGroup[1];869debris->updateRange.x = 0x400000;870debris->updateRange.y = 0x400000;871872debris = CREATE_ENTITY(Debris, Debris_State_FallAndFlicker, self->position.x + 0x230000, self->position.y);873RSDK.SetSpriteAnimation(DrillerdroidO->aniFrames, 0, &debris->animator, true, 2);874debris->velocity.x = RSDK.Rand(-4, 4) << 15;875debris->velocity.y = RSDK.Rand(0, 2) << 15;876debris->gravityStrength = 0x3800;877debris->drawGroup = Zone->objectDrawGroup[1];878debris->updateRange.x = 0x400000;879debris->updateRange.y = 0x400000;880881debris = CREATE_ENTITY(Debris, Debris_State_FallAndFlicker, self->position.x, self->position.y);882RSDK.SetSpriteAnimation(DrillerdroidO->aniFrames, 0, &debris->animator, true, 3);883debris->velocity.x = RSDK.Rand(-4, 4) << 15;884debris->velocity.y = RSDK.Rand(-8, -4) << 15;885debris->gravityStrength = 0x3800;886debris->drawGroup = Zone->objectDrawGroup[1];887debris->updateRange.x = 0x400000;888debris->updateRange.y = 0x400000;889890debris = CREATE_ENTITY(Debris, Debris_State_FallAndFlicker, self->position.x, self->position.y);891RSDK.SetSpriteAnimation(DrillerdroidO->aniFrames, 0, &debris->animator, true, 5);892debris->velocity.x = RSDK.Rand(-4, 4) << 15;893debris->velocity.y = RSDK.Rand(-8, -4) << 15;894debris->gravityStrength = 0x3800;895debris->drawGroup = Zone->objectDrawGroup[1];896debris->updateRange.x = 0x400000;897debris->updateRange.y = 0x400000;898899self->velocity.x = RSDK.Rand(-4, 4) << 15;900self->velocity.y = (RSDK.Rand(-8, -4) << 15);901self->mainAnimator.frameID = 4;902self->stateDraw = DrillerdroidO_Draw_Simple;903self->state = DrillerdroidO_State_Finish;904}905}906907void DrillerdroidO_State_Finish(void)908{909RSDK_THIS(DrillerdroidO);910911self->position.x += self->velocity.x;912self->position.y += self->velocity.y;913self->velocity.y += 0x3800;914915self->visible ^= true;916917DrillerdroidO_Explode();918919if (!RSDK.CheckOnScreen(self, NULL)) {920Zone->cameraBoundsR[0] += WIDE_SCR_XSIZE;921destroyEntity(self);922}923}924925void DrillerdroidO_Draw_Boss(void)926{927RSDK_THIS(DrillerdroidO);928929RSDK.SetLimitedFade(0, 1, 2, self->alpha, 32, 41);930931if (self->invincibilityTimer & 1) {932RSDK.SetPaletteEntry(0, 32, 0xE0E0E0);933RSDK.SetPaletteEntry(0, 128, 0xE0E0E0);934}935936// Piston (L1)937self->mainAnimator.frameID = 1;938Vector2 drawPos;939drawPos.x = self->position.x - 0x300000;940drawPos.y = self->position.y - DrillerdroidO->pistonPos[0];941RSDK.DrawSprite(&self->mainAnimator, &drawPos, false);942943// Drill (L1)944self->mainAnimator.frameID = 2;945drawPos.y = self->position.y + DrillerdroidO->drillPos[0];946RSDK.DrawSprite(&self->mainAnimator, &drawPos, false);947948// Piston (L2)949self->mainAnimator.frameID = 1;950drawPos.x += 0xD0000;951drawPos.y = self->position.y - DrillerdroidO->pistonPos[1];952RSDK.DrawSprite(&self->mainAnimator, &drawPos, false);953954// Drill (L2)955self->mainAnimator.frameID = 2;956drawPos.y = self->position.y + DrillerdroidO->drillPos[1];957RSDK.DrawSprite(&self->mainAnimator, &drawPos, false);958959// Piston (R1)960self->mainAnimator.frameID = 1;961drawPos.x += 0x530000;962drawPos.y = self->position.y - DrillerdroidO->pistonPos[0];963RSDK.DrawSprite(&self->mainAnimator, &drawPos, false);964965// Drill (R1)966self->mainAnimator.frameID = 2;967drawPos.y = self->position.y + DrillerdroidO->drillPos[0];968RSDK.DrawSprite(&self->mainAnimator, &drawPos, false);969970// Piston (R2)971self->mainAnimator.frameID = 1;972drawPos.x -= 0xD0000;973drawPos.y = self->position.y - DrillerdroidO->pistonPos[1];974RSDK.DrawSprite(&self->mainAnimator, &drawPos, false);975976// Drill (R2)977self->mainAnimator.frameID = 2;978drawPos.y = self->position.y + DrillerdroidO->drillPos[1];979RSDK.DrawSprite(&self->mainAnimator, &drawPos, false);980981// Main Body982self->mainAnimator.frameID = 0;983RSDK.DrawSprite(&self->mainAnimator, NULL, false);984985self->drawFX |= FX_ROTATE;986987// Core Armor (L)988drawPos.x = self->position.x + 0x10000;989drawPos.y = self->position.y - 0x140000;990self->armorAnimator.frameID = 0;991RSDK.DrawSprite(&self->armorAnimator, &drawPos, false);992993// Core Armor (R)994self->armorAnimator.frameID = 1;995self->rotation = 0x200 - self->rotation;996RSDK.DrawSprite(&self->armorAnimator, &drawPos, false);997998self->rotation = 0x200 - self->rotation;999self->drawFX = FX_NONE;10001001RSDK.CopyPalette(1, 32, 0, 32, 10);10021003RSDK.SetPaletteEntry(0, 32, 0x282028);1004RSDK.SetPaletteEntry(0, 128, 0x000000);1005}10061007void DrillerdroidO_Draw_Simple(void)1008{1009RSDK_THIS(DrillerdroidO);10101011RSDK.DrawSprite(&self->mainAnimator, NULL, false);1012}10131014void DrillerdroidO_State_Target(void)1015{1016RSDK_THIS(DrillerdroidO);10171018RSDK.ProcessAnimation(&self->armorAnimator);1019RSDK.ProcessAnimation(&self->targetLockAnimator);10201021if (self->target) {1022self->position.x = self->target->position.x;1023self->position.y = self->target->position.y;1024}10251026self->alpha += 0x20;10271028self->targetEdgeOffset.x -= 0x20000;1029if (self->targetEdgeOffset.x <= 0xC0000) {1030self->alpha = 0;1031self->targetEdgeOffset.x = 0x2C0000;1032}10331034self->targetEdgeOffset.y = self->targetEdgeOffset.x;1035if (++self->timer == 60)1036RSDK.SetSpriteAnimation(Drillerdroid->aniFrames, 4, &self->targetLockAnimator, true, 0);10371038if (self->timer == 96) {1039self->target = NULL;1040DrillerdroidO->boss->position.x = self->position.x;10411042if (self->position.x < (Zone->cameraBoundsL[0] + 64) << 16 || self->position.x > (Zone->cameraBoundsR[0] - 64) << 16)1043DrillerdroidO->boss->position.x = (Zone->cameraBoundsL[0] + 64) << 16;1044else if (self->position.x > (Zone->cameraBoundsR[0] - 64) << 16)1045DrillerdroidO->boss->position.x = (Zone->cameraBoundsR[0] - 64) << 16;1046}10471048if (self->timer == 128)1049destroyEntity(self);1050}10511052void DrillerdroidO_Draw_Target(void)1053{1054RSDK_THIS(DrillerdroidO);10551056// Top-Left Edge1057self->mainAnimator.frameID = 0;1058self->inkEffect = INK_ALPHA;1059self->direction = FLIP_NONE;1060Vector2 drawPos;1061drawPos.x = self->position.x - self->targetEdgeOffset.x;1062drawPos.y = self->position.y - self->targetEdgeOffset.y;1063RSDK.DrawSprite(&self->mainAnimator, &drawPos, false);10641065// Top-Right Edge1066self->direction = FLIP_X;1067drawPos.x = self->position.x + self->targetEdgeOffset.x;1068drawPos.y = self->position.y - self->targetEdgeOffset.y;1069RSDK.DrawSprite(&self->mainAnimator, &drawPos, false);10701071// Bottom-Left Edge1072self->mainAnimator.frameID = 1;1073self->direction = FLIP_NONE;1074drawPos.x = self->position.x - self->targetEdgeOffset.x;1075drawPos.y = self->position.y + self->targetEdgeOffset.y;1076RSDK.DrawSprite(&self->mainAnimator, &drawPos, false);10771078// Bottom-Right Edge1079self->direction = FLIP_X;1080drawPos.x = self->position.x + self->targetEdgeOffset.x;1081drawPos.y = self->position.y + self->targetEdgeOffset.y;1082RSDK.DrawSprite(&self->mainAnimator, &drawPos, false);10831084// Target Reticle1085self->inkEffect = INK_NONE;1086self->direction = FLIP_NONE;1087RSDK.DrawSprite(&self->armorAnimator, NULL, false);1088RSDK.DrawSprite(&self->targetLockAnimator, NULL, false);1089}10901091void DrillerdroidO_State_FireballEmitter(void)1092{1093RSDK_THIS(DrillerdroidO);10941095bool32 collided = true;1096foreach_active(DrillerdroidO, drillerdroid)1097{1098if (drillerdroid->type == DRILLERDROIDO_MAIN1099&& RSDK.CheckObjectCollisionTouchBox(drillerdroid, &DrillerdroidO->hitboxLandPosSegmentBreak, self, &DrillerdroidO->hitboxEmitterRange)) {1100collided = false;1101foreach_break;1102}1103}11041105if (collided && DrillerdroidO->emitFireballs) {1106if (!(Zone->timer & 0x3F)) {1107EntityLRZFireball *fireball =1108CREATE_ENTITY(LRZFireball, LRZFireball_StateFireball_LauncherGravity, self->position.x, self->position.y + 0x940000);1109fireball->angle = 0xEE;1110fireball->rotation = 0xEE;1111fireball->groundVel = -0x300;1112fireball->velocity.x = fireball->groundVel * RSDK.Sin512(0x12);1113fireball->velocity.y = fireball->groundVel * RSDK.Cos512(0x100 - fireball->angle);11141115fireball = CREATE_ENTITY(LRZFireball, LRZFireball_StateFireball_LauncherGravity, self->position.x, self->position.y + 0x940000);1116fireball->angle = 0x116;1117fireball->rotation = 0x116;1118fireball->groundVel = -0x300;1119fireball->velocity.x = fireball->groundVel * RSDK.Sin512(-0x16);1120fireball->velocity.y = fireball->groundVel * RSDK.Cos512(0x100 - fireball->angle);1121RSDK.PlaySfx(LRZFireball->sfxFireball, false, 0xFF);1122}1123}1124}11251126void DrillerdroidO_Draw_FireballEmitter(void)1127{ /* Yeah :) */1128}11291130#if GAME_INCLUDE_EDITOR1131void DrillerdroidO_EditorDraw(void)1132{1133RSDK_THIS(DrillerdroidO);11341135DrillerdroidO->drillDelay[0] = 4;1136DrillerdroidO->pistonDelay[0] = 4;11371138DrillerdroidO->drillDelay[1] = 0;1139DrillerdroidO->pistonDelay[1] = 0;11401141DrillerdroidO->drillPos[0] = 0x100000;1142DrillerdroidO->drillPos[1] = 0x100000;11431144DrillerdroidO->pistonPos[0] = 0;1145DrillerdroidO->pistonPos[1] = 0;11461147DrillerdroidO->drillMoveDir[0] = FLIP_NONE;1148DrillerdroidO->drillMoveDir[1] = FLIP_NONE;11491150DrillerdroidO->pistonMoveDir[0] = FLIP_NONE;1151DrillerdroidO->pistonMoveDir[1] = FLIP_NONE;11521153DrillerdroidO->childSlotStart = SceneInfo->entitySlot + 2;11541155switch (self->type) {1156case DRILLERDROIDO_MAIN:1157RSDK.SetSpriteAnimation(DrillerdroidO->aniFrames, 0, &self->mainAnimator, true, 0);1158RSDK.SetSpriteAnimation(DrillerdroidO->aniFrames, 5, &self->armorAnimator, true, 0);1159DrillerdroidO_Draw_Boss();11601161if (showGizmos()) {1162RSDK_DRAWING_OVERLAY(true);11631164// Note: its actually centerX offset on left/right but mania is usually always at 424 width anyways so its pretty much the same1165DrawHelpers_DrawArenaBounds(-WIDE_SCR_XCENTER, -SCREEN_YSIZE, WIDE_SCR_XCENTER, 96, 1 | 2 | 4 | 8, 0x00C0F0);11661167if (LRZRockPile) {1168for (int32 i = 0; i < 9; ++i) {1169EntityLRZRockPile *pile = RSDK_GET_ENTITY(DrillerdroidO->childSlotStart++, LRZRockPile);11701171if (pile && pile->classID == LRZRockPile->classID)1172DrawHelpers_DrawArrow(self->position.x, self->position.y, pile->position.x, pile->position.y, 0xFFFF00, INK_NONE, 0xFF);1173}1174}11751176RSDK_DRAWING_OVERLAY(false);1177}1178break;11791180case DRILLERDROIDO_FIREBALLEMITTER:1181RSDK.SetSpriteAnimation(DrillerdroidO->ticFrames, 0, &self->mainAnimator, true, 0);1182RSDK.SetSpriteAnimation(-1, 3, &self->armorAnimator, true, 0);11831184DrawHelpers_DrawRectOutline(self->position.x, self->position.y + (0xC0 << 15), 0x40 << 16, 0xC0 << 16, 0xFFFF00);1185break;11861187default: break;1188}1189}11901191void DrillerdroidO_EditorLoad(void)1192{1193DrillerdroidO->aniFrames = RSDK.LoadSpriteAnimation("LRZ1/Drillerdroid.bin", SCOPE_STAGE);1194DrillerdroidO->ticFrames = RSDK.LoadSpriteAnimation("Global/TicMark.bin", SCOPE_STAGE);11951196RSDK_ACTIVE_VAR(DrillerdroidO, type);1197RSDK_ENUM_VAR("Drillerdroid", DRILLERDROIDO_MAIN);1198RSDK_ENUM_VAR("Fireball Emitter", DRILLERDROIDO_FIREBALLEMITTER);1199}1200#endif12011202void DrillerdroidO_Serialize(void) { RSDK_EDITABLE_VAR(DrillerdroidO, VAR_UINT8, type); }120312041205