Path: blob/master/SonicMania/Objects/HCZ/LaundroMobile.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: LaundroMobile Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectLaundroMobile *LaundroMobile;1011void LaundroMobile_Update(void)12{13RSDK_THIS(LaundroMobile);1415StateMachine_Run(self->state);16}1718void LaundroMobile_LateUpdate(void) {}1920void LaundroMobile_StaticUpdate(void)21{22if (LaundroMobile->loopSfxTimer) {23if (!LaundroMobile->playingLoopSfx) {24if (LaundroMobile->health <= 8)25RSDK.PlaySfx(LaundroMobile->sfxWash, true, 0xFF);26else27RSDK.PlaySfx(LaundroMobile->sfxFan, 47208, 0xFF);2829LaundroMobile->playingLoopSfx = true;30}31}32else {33if (LaundroMobile->playingLoopSfx) {34RSDK.StopSfx(LaundroMobile->sfxFan);35RSDK.StopSfx(LaundroMobile->sfxWash);3637LaundroMobile->playingLoopSfx = false;38}39}4041LaundroMobile->loopSfxTimer = false;4243if (SceneInfo->state == ENGINESTATE_REGULAR && LaundroMobile->useStageWrap)44LaundroMobile_HandleStageWrap();45}4647void LaundroMobile_Draw(void)48{49RSDK_THIS(LaundroMobile);5051StateMachine_Run(self->stateDraw);52}5354void LaundroMobile_Create(void *data)55{56RSDK_THIS(LaundroMobile);5758if (globals->gameMode == MODE_TIMEATTACK) {59destroyEntity(self);60}61else {62self->drawFX = FX_FLIP;63if (!SceneInfo->inEditor) {64if (!self->type)65self->type = VOID_TO_INT(data);6667switch (self->type) {68case LAUNDROMOBILE_BOSS:69self->active = ACTIVE_BOUNDS;70self->visible = false;71self->drawGroup = Zone->objectDrawGroup[0] + 1;72RSDK.SetSpriteAnimation(LaundroMobile->aniFrames, 0, &self->mainAnimator, true, 0);73RSDK.SetSpriteAnimation(LaundroMobile->aniFrames, 3, &self->propellerAnimator, true, 0);74RSDK.SetSpriteAnimation(LaundroMobile->eggmanFrames, 0, &self->eggmanAnimator, true, 0);75self->startY = self->position.y;76self->updateRange.x = 0x800000;77self->updateRange.y = 0x800000;7879LaundroMobile->health = 5 + 8; // phase1 health + phase 2 health80LaundroMobile->invincibilityTimer = 0;81LaundroMobile->nextLoopPoint = 0;82LaundroMobile->attackDir = FLIP_NONE;83LaundroMobile->currentVelocity = 0x38000;84LaundroMobile->rocketActive = false;85LaundroMobile->animSpeed = 0;86LaundroMobile->travelledPaths = 0;87LaundroMobile->useStageWrap = false;88LaundroMobile->loopSfxTimer = 0;89LaundroMobile->playingLoopSfx = false;90RSDK.StopSfx(LaundroMobile->sfxFan);91RSDK.StopSfx(LaundroMobile->sfxWash);92LaundroMobile->rocketAngles[0] = 0;93LaundroMobile->rocketAngles[1] = 0x8000;94LaundroMobile->rocketAngles[2] = 0;95LaundroMobile->rocketAngles[3] = 0x8000;96LaundroMobile->rocketSpeeds[0] = 0;97LaundroMobile->rocketSpeeds[1] = 0;98LaundroMobile->isUnderwater = false;99100self->tileCollisions = TILECOLLISION_DOWN;101self->collisionLayers = Zone->collisionLayers;102self->collisionPlane = 0;103self->state = LaundroMobile_StateBoss_AwaitPlayer_Phase1;104self->stateDraw = LaundroMobile_Draw_Boss;105break;106107case LAUNDROMOBILE_BOMB:108self->active = ACTIVE_BOUNDS;109self->visible = true;110self->drawGroup = Zone->objectDrawGroup[0];111self->originPos = self->position;112113RSDK.SetSpriteAnimation(LaundroMobile->aniFrames, 7, &self->mainAnimator, true, 0);114115self->updateRange.x = 0x1800000;116self->updateRange.y = 0x1800000;117self->state = LaundroMobile_StateBomb_Spawner;118self->stateDraw = LaundroMobile_Draw_Simple;119break;120121case LAUNDROMOBILE_LAUNDRY:122self->active = ACTIVE_XBOUNDS;123self->visible = true;124self->drawGroup = Zone->objectDrawGroup[0] + 1;125126RSDK.SetSpriteAnimation(LaundroMobile->aniFrames, 0, &self->mainAnimator, true, 0);127RSDK.SetSpriteAnimation(LaundroMobile->aniFrames, 1, &self->propellerAnimator, true, 0);128RSDK.SetSpriteAnimation(LaundroMobile->aniFrames, 2, &self->eggmanAnimator, true, 0);129130self->updateRange.x = 0x2000000;131self->updateRange.y = 0x800000;132self->state = LaundroMobile_State_Laundry;133self->stateDraw = LaundroMobile_Draw_Laundry;134break;135136case LAUNDROMOBILE_LOOPPOINT: LaundroMobile->loopPoints[LaundroMobile->nextLoopPoint++] = (Entity *)self; break;137138case LAUNDROMOBILE_BLOCK:139self->active = ACTIVE_BOUNDS;140self->visible = true;141self->drawGroup = Zone->objectDrawGroup[0];142self->originPos = self->position;143144RSDK.SetSpriteAnimation(LaundroMobile->aniFrames, 9, &self->mainAnimator, true, RSDK.Rand(0, 3));145146self->updateRange.x = 0x1800000;147self->updateRange.y = 0x1800000;148self->velocity.x = LaundroMobile->currentVelocity - 0x18000;149self->state = LaundroMobile_StateBlock_Spawner;150self->stateDraw = LaundroMobile_Draw_Simple;151break;152153case LAUNDROMOBILE_SPIKES:154self->active = ACTIVE_BOUNDS;155self->visible = true;156self->drawGroup = Zone->objectDrawGroup[0];157self->originPos = self->position;158159RSDK.SetSpriteAnimation(LaundroMobile->aniFrames, 9, &self->mainAnimator, true, RSDK.Rand(0, 3) + 3);160161self->updateRange.x = 0x1800000;162self->updateRange.y = 0x1800000;163self->velocity.x = LaundroMobile->currentVelocity - 0x18000;164self->state = LaundroMobile_StateBlock_Spawner;165self->stateDraw = LaundroMobile_Draw_Simple;166break;167168case LAUNDROMOBILE_DELAYEDSPLASH:169self->active = ACTIVE_NORMAL;170self->timer = 8;171self->state = LaundroMobile_State_DelayedSplash;172break;173174default: break;175}176}177}178}179180void LaundroMobile_StageLoad(void)181{182LaundroMobile->aniFrames = RSDK.LoadSpriteAnimation("HCZ/LaundroMobile.bin", SCOPE_STAGE);183LaundroMobile->eggmanFrames = RSDK.LoadSpriteAnimation("Eggman/EggmanHCZ2.bin", SCOPE_STAGE);184185LaundroMobile->hitboxBoss.left = -32;186LaundroMobile->hitboxBoss.top = -32;187LaundroMobile->hitboxBoss.right = 32;188LaundroMobile->hitboxBoss.bottom = 32;189190LaundroMobile->hitboxMissile.left = -24;191LaundroMobile->hitboxMissile.top = -24;192LaundroMobile->hitboxMissile.right = 24;193LaundroMobile->hitboxMissile.bottom = 24;194195LaundroMobile->hitboxBox.left = -16;196LaundroMobile->hitboxBox.top = -16;197LaundroMobile->hitboxBox.right = 16;198LaundroMobile->hitboxBox.bottom = 16;199200LaundroMobile->hitboxBomb.left = -32;201LaundroMobile->hitboxBomb.top = -16;202LaundroMobile->hitboxBomb.right = 32;203LaundroMobile->hitboxBomb.bottom = 16;204205LaundroMobile->innerBox.left = -39;206LaundroMobile->innerBox.top = -40;207LaundroMobile->innerBox.right = 39;208LaundroMobile->innerBox.bottom = 40;209210LaundroMobile->outerBox.left = -40;211LaundroMobile->outerBox.top = -40;212LaundroMobile->outerBox.right = 40;213LaundroMobile->outerBox.bottom = 40;214215LaundroMobile->active = ACTIVE_ALWAYS;216LaundroMobile->playingLoopSfx = false;217LaundroMobile->loopSfxTimer = 0;218219LaundroMobile->sfxHit = RSDK.GetSfx("Stage/BossHit.wav");220LaundroMobile->sfxExplosion = RSDK.GetSfx("Stage/Explosion2.wav");221LaundroMobile->sfxButton2 = RSDK.GetSfx("Stage/Button2.wav");222LaundroMobile->sfxFan = RSDK.GetSfx("HCZ/BigFan.wav");223LaundroMobile->sfxRoll = RSDK.GetSfx("Global/Roll.wav");224LaundroMobile->sfxWash = RSDK.GetSfx("HCZ/Wash.wav");225LaundroMobile->sfxHullClose = RSDK.GetSfx("Stage/HullClose.wav");226LaundroMobile->sfxPush = RSDK.GetSfx("Stage/Push.wav");227LaundroMobile->sfxFireball = RSDK.GetSfx("Stage/Fireball.wav");228LaundroMobile->sfxButton = RSDK.GetSfx("Stage/Button.wav");229LaundroMobile->sfxLedgeBreak = RSDK.GetSfx("Stage/LedgeBreak3.wav");230LaundroMobile->sfxPimPom = RSDK.GetSfx("Stage/PimPom.wav");231#if MANIA_USE_PLUS232LaundroMobile->sfxRumble = RSDK.GetSfx("Stage/Rumble.wav");233LaundroMobile->sfxImpact = RSDK.GetSfx("Stage/Impact6.wav");234#endif235}236237void LaundroMobile_CheckPlayerCollisions(void)238{239RSDK_THIS(LaundroMobile);240241if (LaundroMobile->invincibilityTimer) {242LaundroMobile->invincibilityTimer--;243}244else {245int32 storeX = self->position.x;246int32 storeY = self->position.y;247foreach_active(Player, player)248{249for (int32 i = 0; i < 4 && LaundroMobile->rocketActive; ++i) {250self->position.x = LaundroMobile->rocketPositions[i].x;251self->position.y = LaundroMobile->rocketPositions[i].y;252253if (Player_CheckCollisionTouch(player, self, &LaundroMobile->hitboxMissile)) {254#if MANIA_USE_PLUS255if (!Player_CheckMightyUnspin(player, 0x400, 2, &player->uncurlTimer))256#endif257Player_Hurt(player, self);258break;259}260}261self->position.x = storeX;262self->position.y = storeY;263264int32 velX = player->velocity.x;265int32 velY = player->velocity.y;266if (Player_CheckBadnikTouch(player, self, &LaundroMobile->hitboxBoss) && Player_CheckBossHit(player, self)) {267if (LaundroMobile->health)268LaundroMobile->health--;269270if (LaundroMobile->health) {271if (LaundroMobile->health == 8) {272RSDK.StopSfx(LaundroMobile->sfxFan);273RSDK.SetSpriteAnimation(LaundroMobile->aniFrames, 4, &self->propellerAnimator, true, 0);274self->timer = 60;275self->state = LaundroMobile_StateBoss_Destroyed_Phase1;276}277else {278if (LaundroMobile->health < 8) {279RSDK.SetSpriteAnimation(LaundroMobile->eggmanFrames, 3, &self->eggmanAnimator, true, 0);280}281else {282RSDK.SetSpriteAnimation(LaundroMobile->eggmanFrames, 2, &self->eggmanAnimator, true, 0);283player->groundVel = velX;284player->velocity.x = velX;285player->velocity.y = velY;286}287RSDK.PlaySfx(LaundroMobile->sfxHit, false, 255);288LaundroMobile->invincibilityTimer = 30;289}290}291else {292SceneInfo->timeEnabled = false;293Player_GiveScore(RSDK_GET_ENTITY(SLOT_PLAYER1, Player), 1000);294RSDK.PlaySfx(LaundroMobile->sfxExplosion, false, 255);295LaundroMobile->invincibilityTimer = 60;296297EntityWhirlpool *whirlpool = self->whirlpool;298self->state = LaundroMobile_StateBoss_Destroyed_Phase2;299if (whirlpool) {300if (whirlpool->classID == Whirlpool->classID)301whirlpool->activePlayers = -3;302self->whirlpool = NULL;303}304}305foreach_break;306}307}308}309}310311void LaundroMobile_Explode(void)312{313RSDK_THIS(LaundroMobile);314315int32 interval = LaundroMobile->health > 8 ? 7 : 3;316317if (!(Zone->timer % interval)) {318RSDK.PlaySfx(LaundroMobile->sfxExplosion, false, 255);319if (Zone->timer & 4) {320int32 x = self->position.x + (RSDK.Rand(-19, 20) << 16);321int32 y = self->position.y + (RSDK.Rand(-24, 25) << 16);322EntityExplosion *explosion = CREATE_ENTITY(Explosion, INT_TO_VOID((RSDK.Rand(0, 256) > 192) + EXPLOSION_BOSS), x, y);323324explosion->drawGroup = Zone->objectDrawGroup[1] + 2;325if (LaundroMobile->health > 8)326explosion->velocity.x = 0x24000;327}328}329}330331void LaundroMobile_HandleStageWrap(void)332{333EntityLaundroMobile *boss = LaundroMobile->laundroMobile;334335if (!(Zone->timer & 3)) {336EntityCurrent *current = CREATE_ENTITY(Current, INT_TO_VOID(CURRENT_CHILD_BUBBLE), ScreenInfo->position.x << 16,337(8 * RSDK.Rand(0, ScreenInfo->size.y >> 3) + ScreenInfo->position.y) << 16);338339current->drawGroup = Zone->playerDrawGroup[0];340current->strength = 6;341current->type = CURRENT_C_RIGHT;342current->alpha = 0xF0;343current->size.x = (ScreenInfo->position.x + ScreenInfo->size.x + 0x1000) << 16;344}345346foreach_active(Player, player)347{348if (player->state != Player_State_Static) {349if (player->position.x < boss->position.x)350player->position.x = boss->position.x;351352if (Player_CheckValidState(player)) {353if ((abs(player->velocity.y) <= 0x18000 || player->onGround) && player->position.x < 0x6D800000) {354player->collisionMode = CMODE_FLOOR;355player->onGround = false;356player->nextGroundState = StateMachine_None;357player->nextAirState = StateMachine_None;358player->state = Current_PlayerState_Right;359if (player->animator.animationID != ANI_CLING && player->animator.animationID != ANI_SHAFT_SWING) {360if (player->position.x >= boss->position.x + 0xC00000) {361player->velocity.x = LaundroMobile->currentVelocity;362player->groundVel = player->velocity.x;363}364else {365player->velocity.x = LaundroMobile->currentVelocity + ((boss->position.x - player->position.x + 0xC00000) >> 6);366player->groundVel = player->velocity.x;367}368RSDK.SetSpriteAnimation(player->aniFrames, ANI_FAN, &player->animator, false, 0);369}370371player->velocity.y = 0;372if (player->up)373player->velocity.y = -0x18000;374else if (player->down)375player->velocity.y = 0x18000;376}377}378}379}380381if (LaundroMobile->currentVelocity < 0x80000)382LaundroMobile->currentVelocity += 0x400;383384EntityPlayer *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);385386if (Player_CheckValidState(player1)) {387if (LaundroMobile->nextLoopPoint == 5 && boss->timer <= 0) {388if (LaundroMobile->currentVelocity < 0xC0000)389LaundroMobile->currentVelocity += 0x1000;390}391else {392Entity *loopPoint = LaundroMobile->loopPoints[LaundroMobile->nextLoopPoint];393if (player1->position.x >= loopPoint->position.x + 0xE000000) {394int32 startOffsetX = player1->position.x - loopPoint->position.x - 0xE000000;395int32 startOffsetY = player1->position.y - loopPoint->position.y;396if (LaundroMobile->health <= 8) {397LaundroMobile->nextLoopPoint = 5;398boss->state = LaundroMobile_StateBoss_WaitForLastStageWrap;399}400else {401if (LaundroMobile->travelledPaths == 0x1E) {402LaundroMobile->travelledPaths = 0;403}404405int32 prevLoopPoint = LaundroMobile->nextLoopPoint;406while (LaundroMobile->nextLoopPoint == prevLoopPoint) {407// LoopPoints 1-4 are valid to use as attacks, 5 is reserved for the final stage wrap408LaundroMobile->nextLoopPoint = RSDK.Rand(1, 5);409410while ((1 << LaundroMobile->nextLoopPoint) & LaundroMobile->travelledPaths) {411LaundroMobile->nextLoopPoint = RSDK.Rand(1, 5);412}413}414415LaundroMobile->travelledPaths |= 1 << LaundroMobile->nextLoopPoint;416}417loopPoint = LaundroMobile->loopPoints[LaundroMobile->nextLoopPoint];418419int32 offsetX = player1->position.x - startOffsetX - loopPoint->position.x;420int32 offsetY = player1->position.y - loopPoint->position.y - startOffsetY;421player1->position.x -= offsetX;422player1->position.y -= offsetY;423424boss->position.y -= offsetY;425boss->originPos.y -= offsetY;426boss->unusedPos.y -= offsetY;427428boss->position.x -= offsetX;429boss->originPos.x -= offsetX;430boss->unusedPos.x -= offsetX;431432ScreenInfo->position.x -= offsetX >> 16;433ScreenInfo->position.y -= offsetY >> 16;434435EntityCamera *camera = RSDK_GET_ENTITY(SLOT_CAMERA1, Camera);436camera->position.x -= offsetX;437camera->position.y -= offsetY;438camera->center.x -= offsetX >> 16;439camera->center.y -= offsetY >> 16;440if (Player->playerCount >= 2) {441EntityPlayer *player2 = RSDK_GET_ENTITY(SLOT_PLAYER2, Player);442player2->position.x -= offsetX;443player2->position.y -= offsetY;444}445446for (int32 i = 0; i < 0x1000; ++i) {447Entity *entPtr = RSDK_GET_ENTITY_GEN(i);448449if (entPtr->classID == LaundroMobile->classID) {450EntityLaundroMobile *laundroMobile = (EntityLaundroMobile *)entPtr;451if ((laundroMobile->type == LAUNDROMOBILE_BOMB && laundroMobile->state != LaundroMobile_StateBomb_Spawner)452|| laundroMobile->state == LaundroMobile_StateBlock_Block) {453laundroMobile->position.x -= offsetX;454laundroMobile->position.y -= offsetY;455}456}457else if (entPtr->classID == Ring->classID) {458EntityRing *ring = (EntityRing *)entPtr;459if (ring->state != Ring_State_Normal) {460entPtr->position.x -= offsetX;461entPtr->position.y -= offsetY;462}463}464else if (entPtr->classID == Debris->classID) {465entPtr->position.x -= offsetX;466entPtr->position.y -= offsetY;467}468else if (entPtr->classID == Water->classID) {469EntityWater *water = (EntityWater *)entPtr;470if (water->type == WATER_BUBBLE) {471water->position.x -= offsetX;472water->position.y -= offsetY;473water->bubbleX = water->position.x;474}475}476else if (entPtr->classID == ImageTrail->classID) {477EntityImageTrail *trail = (EntityImageTrail *)entPtr;478trail->position.x -= offsetX;479trail->position.y -= offsetY;480trail->currentPos.x -= offsetX;481trail->currentPos.y -= offsetY;482for (int32 t = 0; t < IMAGETRAIL_TRACK_COUNT; ++t) {483trail->statePos[t].x -= offsetX;484trail->statePos[t].y -= offsetY;485}486}487else if (entPtr->classID == Current->classID) {488EntityCurrent *current = (EntityCurrent *)entPtr;489if (current->state == Current_State_Child) {490current->position.x -= offsetX;491current->position.y -= offsetY;492current->size.x -= offsetX;493}494}495}496}497}498}499}500501void LaundroMobile_HandleRocketMovement(void)502{503RSDK_THIS(LaundroMobile);504505for (int32 r = 0; r < 2; ++r) {506LaundroMobile->rocketPositions[r].x = self->position.x + 0x1400 * RSDK.Cos256(LaundroMobile->rocketAngles[r] >> 8);507LaundroMobile->rocketPositions[r].y = self->position.y + 0x1400 * RSDK.Cos256(LaundroMobile->rocketAngles[r] >> 8);508LaundroMobile->rocketAngles[r] += LaundroMobile->rocketSpeeds[0];509}510511for (int32 r = 2; r < 4; ++r) {512LaundroMobile->rocketPositions[r].x = self->position.x - 0x1400 * RSDK.Cos256(LaundroMobile->rocketAngles[r] >> 8);513LaundroMobile->rocketPositions[r].y = self->position.y + 0x1400 * RSDK.Cos256(LaundroMobile->rocketAngles[r] >> 8);514LaundroMobile->rocketAngles[r] += LaundroMobile->rocketSpeeds[1];515}516}517518void LaundroMobile_HandleEggmanAnimations(void)519{520RSDK_THIS(LaundroMobile);521522RSDK.ProcessAnimation(&self->eggmanAnimator);523524bool32 playerHurt = false;525foreach_active(Player, player)526{527if (player->state == Player_State_Hurt || player->state == Player_State_Death || player->state == Player_State_Drown)528playerHurt = true;529}530531switch (self->eggmanAnimator.animationID) {532case 0:533if (playerHurt)534RSDK.SetSpriteAnimation(LaundroMobile->eggmanFrames, 4, &self->eggmanAnimator, true, 0);535break;536537case 1:538if (playerHurt)539RSDK.SetSpriteAnimation(LaundroMobile->eggmanFrames, 5, &self->eggmanAnimator, true, 0);540break;541542case 2:543if (!LaundroMobile->invincibilityTimer)544RSDK.SetSpriteAnimation(LaundroMobile->eggmanFrames, 0, &self->eggmanAnimator, true, 0);545break;546547case 3:548if (!LaundroMobile->invincibilityTimer)549RSDK.SetSpriteAnimation(LaundroMobile->eggmanFrames, 1, &self->eggmanAnimator, true, 0);550break;551552case 4:553if (self->eggmanAnimator.frameID >= self->eggmanAnimator.frameCount - 1) {554if (playerHurt)555RSDK.SetSpriteAnimation(LaundroMobile->eggmanFrames, 4, &self->eggmanAnimator, true, 6);556else557RSDK.SetSpriteAnimation(LaundroMobile->eggmanFrames, 0, &self->eggmanAnimator, true, 0);558}559break;560561case 5:562if (self->eggmanAnimator.frameID >= self->eggmanAnimator.frameCount - 1) {563if (playerHurt)564RSDK.SetSpriteAnimation(LaundroMobile->eggmanFrames, 5, &self->eggmanAnimator, true, 6);565else566RSDK.SetSpriteAnimation(LaundroMobile->eggmanFrames, 1, &self->eggmanAnimator, true, 0);567}568break;569570default: break;571}572}573574void LaundroMobile_HandleTileCollisions(void)575{576RSDK_THIS(LaundroMobile);577578uint8 collisionLevel = 0xFF;579while (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0x200000, 0x200000, false) && collisionLevel >= 0) {580self->position.y -= 0x10000;581collisionLevel = 0;582}583584while (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_ROOF, 0, 0x200000, -0x200000, false) && collisionLevel >= 1) {585self->position.y += 0x10000;586collisionLevel = 1;587}588589while (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, -0x200000, 0x200000, false) && collisionLevel >= 2) {590self->position.y -= 0x10000;591collisionLevel = 2;592}593594while (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_ROOF, 0, -0x200000, -0x200000, false) && collisionLevel >= 3) {595self->position.y += 0x10000;596collisionLevel = 3;597}598}599600void LaundroMobile_StateBoss_AwaitPlayer_Phase1(void)601{602RSDK_THIS(LaundroMobile);603604if (++self->timer >= 2) {605self->position.y += 0x500000;606self->originPos.y = self->position.y;607self->position.x -= 0x100000;608self->timer = 0;609self->active = ACTIVE_NORMAL;610RSDK_GET_ENTITY(SLOT_PLAYER1, Player);611612if (self->position.x >= (24704 << 16)) {613// did this use to only have 12 health at some point during dev?614if (LaundroMobile->health == (MANIA_USE_PLUS ? (5 + 8) : (4 + 8))) {615LaundroMobile->health = 8;616Music_TransitionTrack(TRACK_EGGMAN1, 0.0125);617self->visible = true;618self->state = LaundroMobile_StateBoss_AwaitPlayer_Phase2;619}620else {621destroyEntity(self);622}623}624else {625LaundroMobile->laundroMobile = self;626self->state = LaundroMobile_StateBoss_SetupArena_Phase1;627RSDK_GET_ENTITY(SceneInfo->entitySlot + 1, BreakBar)->releaseTimer = 0;628EntityPlayer *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);629player1->jumpPress = false;630}631}632}633634void LaundroMobile_StateBoss_SetupArena_Phase1(void)635{636RSDK_THIS(LaundroMobile);637638EntityPlayer *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);639640RSDK_GET_ENTITY(SceneInfo->entitySlot + 1, BreakBar)->releaseTimer = 0;641player1->jumpPress = false;642643if (player1->position.x > self->position.x + 0x1700000) {644Music_TransitionTrack(TRACK_EGGMAN1, 0.0125);645RSDK.GetTileLayer(4)->drawGroup[0] = DRAWGROUP_COUNT;646LaundroMobile->nextLoopPoint = 0;647Water->waterLevel = 0;648Water->targetWaterLevel = 0;649self->timer = 120;650self->propellerAnimator.speed = 0;651self->visible = true;652self->state = LaundroMobile_StateBoss_EnterEggman_Phase1;653}654}655656void LaundroMobile_StateBoss_EnterEggman_Phase1(void)657{658RSDK_THIS(LaundroMobile);659660RSDK.ProcessAnimation(&self->propellerAnimator);661662self->position.x += 0x18000;663self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 2, 10);664665RSDK_GET_ENTITY(SceneInfo->entitySlot + 1, BreakBar)->releaseTimer = 0;666RSDK_GET_ENTITY(SLOT_PLAYER1, Player)->jumpPress = false;667668if (!--self->timer) {669RSDK.PlaySfx(LaundroMobile->sfxButton2, false, 255);670self->state = LaundroMobile_StateBoss_StartupPropellers;671LaundroMobile->useStageWrap = true;672}673674LaundroMobile_CheckPlayerCollisions();675}676677void LaundroMobile_StateBoss_StartupPropellers(void)678{679RSDK_THIS(LaundroMobile);680681RSDK_GET_ENTITY(SceneInfo->entitySlot + 1, BreakBar)->releaseTimer = 0;682RSDK_GET_ENTITY(SLOT_PLAYER1, Player)->jumpPress = false;683684RSDK.ProcessAnimation(&self->propellerAnimator);685686if (self->propellerAnimator.speed >= 0x200) {687++LaundroMobile->loopSfxTimer;688RSDK_GET_ENTITY(SceneInfo->entitySlot + 1, BreakBar)->releaseTimer = 240;689self->state = LaundroMobile_StateBoss_HandlePhase1;690}691else {692self->propellerAnimator.speed += 4;693if (self->propellerAnimator.speed >= 0x20)694++LaundroMobile->loopSfxTimer;695}696697self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 2, 10);698LaundroMobile_CheckPlayerCollisions();699}700701void LaundroMobile_StateBoss_HandlePhase1(void)702{703RSDK_THIS(LaundroMobile);704705LaundroMobile_HandleEggmanAnimations();706707RSDK.ProcessAnimation(&self->propellerAnimator);708709EntityPlayer *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);710711self->position.y = self->originPos.y;712713if (abs(self->originPos.y - player1->position.y) >= 0x100000) {714if (player1->position.y >= self->originPos.y) {715if (self->velocity.y < 0x18000)716self->velocity.y += 0x1000;717}718else {719if (self->velocity.y > -0x18000)720self->velocity.y -= 0x1000;721}722}723else if (self->velocity.y) {724if (self->velocity.y <= 0) {725self->velocity.y += 0x1000;726727if (self->velocity.y > 0)728self->velocity.y = 0;729}730else {731self->velocity.y -= 0x1000;732733if (self->velocity.y < 0)734self->velocity.y = 0;735}736}737738self->position.y += self->velocity.y;739LaundroMobile_HandleTileCollisions();740741if (self->position.y == self->originPos.y) {742self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 2, 10);743}744else {745self->originPos.y = self->position.y;746}747748self->position.x += LaundroMobile->currentVelocity;749750++LaundroMobile->loopSfxTimer;751LaundroMobile_CheckPlayerCollisions();752}753754void LaundroMobile_StateBoss_Destroyed_Phase1(void)755{756RSDK_THIS(LaundroMobile);757758LaundroMobile_Explode();759760RSDK.ProcessAnimation(&self->propellerAnimator);761762self->position.y = self->originPos.y;763LaundroMobile_HandleTileCollisions();764765self->position.x += LaundroMobile->currentVelocity - 0x8000;766767if (self->position.y == self->originPos.y)768self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 2, 10);769else770self->originPos.y = self->position.y;771772LaundroMobile_CheckPlayerCollisions();773if (--self->timer <= 0) {774EntityDebris *debris = CREATE_ENTITY(Debris, Debris_State_FallAndFlicker, self->position.x, self->position.y);775776RSDK.SetSpriteAnimation(LaundroMobile->aniFrames, 4, &debris->animator, true, 0);777debris->velocity.x = 0x50000;778debris->velocity.y = -0x28000;779debris->gravityStrength = 0x3800;780debris->drawGroup = Zone->objectDrawGroup[1];781debris->updateRange.x = 0x400000;782debris->updateRange.y = 0x400000;783RSDK.SetSpriteAnimation(-1, 0, &self->propellerAnimator, true, 0);784self->state = LaundroMobile_StateBoss_Explode_Phase1;785}786}787788void LaundroMobile_StateBoss_Explode_Phase1(void)789{790RSDK_THIS(LaundroMobile);791792LaundroMobile_Explode();793794RSDK.ProcessAnimation(&self->propellerAnimator);795796self->position.y = self->originPos.y;797LaundroMobile_HandleTileCollisions();798799self->position.x += LaundroMobile->currentVelocity - 0x10000;800801if (self->position.y == self->originPos.y)802self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 2, 10);803else804self->originPos.y = self->position.y;805806LaundroMobile_CheckPlayerCollisions();807}808809void LaundroMobile_StateBoss_WaitForLastStageWrap(void)810{811RSDK_THIS(LaundroMobile);812813if (RSDK_GET_ENTITY(SLOT_PLAYER1, Player)->position.x > (28032 << 16)) {814LaundroMobile->useStageWrap = false;815foreach_active(Player, player) { player->state = Player_State_Air; }816self->state = LaundroMobile_StateBoss_AwaitPlayer_Phase2;817}818819LaundroMobile_CheckPlayerCollisions();820}821822void LaundroMobile_StateBoss_AwaitPlayer_Phase2(void)823{824RSDK_THIS(LaundroMobile);825826EntityPlayer *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);827828if (player1->onGround && !player1->angle) { // wait till we're on flat ground829self->timer = 60;830RSDK.SetSpriteAnimation(LaundroMobile->eggmanFrames, 1, &self->eggmanAnimator, true, 0);831RSDK.SetSpriteAnimation(LaundroMobile->aniFrames, 5, &self->propellerAnimator, true, 0);832self->state = LaundroMobile_StateBoss_SetupArena_Phase2;833}834835LaundroMobile_CheckPlayerCollisions();836}837838void LaundroMobile_StateBoss_SetupArena_Phase2(void)839{840RSDK_THIS(LaundroMobile);841842if (--self->timer <= 0) {843self->position.x = 28160 << 16;844self->timer = 104;845self->position.y = (ScreenInfo->position.y - 64) << 16;846847LaundroMobile_HandleRocketMovement();848849self->stateDraw = LaundroMobile_Draw_Boss_Destroyed;850self->state = LaundroMobile_StateBoss_EnterEggman_Phase2;851}852853LaundroMobile_CheckPlayerCollisions();854}855856void LaundroMobile_StateBoss_EnterEggman_Phase2(void)857{858RSDK_THIS(LaundroMobile);859860self->position.y += 0x10000;861862LaundroMobile_HandleRocketMovement();863864if (--self->timer <= 0) {865self->timer = 32;866self->state = LaundroMobile_StateBoss_StartupRockets;867}868869LaundroMobile_CheckPlayerCollisions();870LaundroMobile_HandleEggmanAnimations();871}872873void LaundroMobile_StateBoss_StartupRockets(void)874{875RSDK_THIS(LaundroMobile);876877LaundroMobile_HandleRocketMovement();878879if (LaundroMobile->rocketSpeeds[0] < 0x200)880LaundroMobile->rocketSpeeds[0] += 8;881882if (self->timer <= 0) {883if (LaundroMobile->rocketSpeeds[1] < 0x200)884LaundroMobile->rocketSpeeds[1] += 8;885}886else {887self->timer--;888}889890if (LaundroMobile->rocketSpeeds[0] + LaundroMobile->rocketSpeeds[1] == 0x400) {891self->timer = 96;892RSDK.SetSpriteAnimation(LaundroMobile->aniFrames, 6, &self->flameAnimator, true, 0);893LaundroMobile->rocketActive = true;894RSDK.PlaySfx(LaundroMobile->sfxPush, false, 255);895self->state = LaundroMobile_StateBoss_SpeedUpRockets;896}897898LaundroMobile_CheckPlayerCollisions();899LaundroMobile_HandleEggmanAnimations();900}901902void LaundroMobile_StateBoss_SpeedUpRockets(void)903{904RSDK_THIS(LaundroMobile);905906LaundroMobile_HandleRocketMovement();907908if (LaundroMobile->rocketSpeeds[0] < 0x400) {909LaundroMobile->rocketSpeeds[1] += 8;910LaundroMobile->rocketSpeeds[0] = LaundroMobile->rocketSpeeds[1];911}912913if (--self->timer <= 0) {914self->timer = 60;915RSDK.PlaySfx(LaundroMobile->sfxFireball, false, 255);916self->state = LaundroMobile_StateBoss_RiseUpToAttack;917}918919LaundroMobile_CheckPlayerCollisions();920LaundroMobile_HandleEggmanAnimations();921}922923void LaundroMobile_StateBoss_RiseUpToAttack(void)924{925RSDK_THIS(LaundroMobile);926927self->position.y += self->velocity.y;928self->velocity.y -= 0x3800;929930LaundroMobile_HandleRocketMovement();931932if (--self->timer <= 0) {933self->position.x += LaundroMobile->attackDir ? 0x580000 : -0x580000;934self->velocity.y = 0x50000;935RSDK.PlaySfx(LaundroMobile->sfxRoll, false, 255);936LaundroMobile->attackCount = LaundroMobile->attackCounts[RSDK.Rand(0, 8)];937self->state = LaundroMobile_StateBoss_Attacking;938}939940LaundroMobile_CheckPlayerCollisions();941LaundroMobile_HandleEggmanAnimations();942}943944void LaundroMobile_StateBoss_Attacking(void)945{946RSDK_THIS(LaundroMobile);947948RSDK.ProcessObjectMovement(self, &LaundroMobile->outerBox, &LaundroMobile->innerBox);949950if (self->velocity.y < 0 && self->position.y < (ScreenInfo->position.y - 256) << 16) {951self->onGround = false;952self->velocity.y = 0x50000;953LaundroMobile->attackDir ^= FLIP_X;954RSDK.PlaySfx(LaundroMobile->sfxRoll, false, 255);955}956957if (self->position.y <= Water->waterLevel) {958if (LaundroMobile->isUnderwater) {959LaundroMobile->isUnderwater = false;960961CREATE_ENTITY(Water, INT_TO_VOID(WATER_SPLASH), self->position.x, Water->waterLevel);962CREATE_ENTITY(LaundroMobile, INT_TO_VOID(LAUNDROMOBILE_DELAYEDSPLASH), self->position.x - 0x100000, Water->waterLevel);963CREATE_ENTITY(LaundroMobile, INT_TO_VOID(LAUNDROMOBILE_DELAYEDSPLASH), self->position.x + 0x100000, Water->waterLevel);964965RSDK.PlaySfx(Water->sfxSplash, false, 255);966if (--LaundroMobile->attackCount <= 0) {967self->onGround = false;968self->state = LaundroMobile_StateBoss_ReturnToLaundry;969self->velocity.x = LaundroMobile->attackDir == FLIP_NONE ? -0x18000 : 0x18000;970}971}972}973else if (!LaundroMobile->isUnderwater) {974LaundroMobile->isUnderwater = true;975976CREATE_ENTITY(Water, INT_TO_VOID(WATER_SPLASH), self->position.x, Water->waterLevel);977CREATE_ENTITY(LaundroMobile, INT_TO_VOID(LAUNDROMOBILE_DELAYEDSPLASH), self->position.x - 0x100000, Water->waterLevel);978CREATE_ENTITY(LaundroMobile, INT_TO_VOID(LAUNDROMOBILE_DELAYEDSPLASH), self->position.x + 0x100000, Water->waterLevel);979RSDK.PlaySfx(Water->sfxSplash, false, 255);980}981982LaundroMobile_HandleRocketMovement();983LaundroMobile_CheckPlayerCollisions();984LaundroMobile_HandleEggmanAnimations();985}986987void LaundroMobile_StateBoss_ReturnToLaundry(void)988{989RSDK_THIS(LaundroMobile);990991self->position.x += self->velocity.x;992self->position.y += self->velocity.y;993self->velocity.y += 0x2800;994995if ((LaundroMobile->attackDir && self->position.x >= (28160 << 16)) || (!LaundroMobile->attackDir && self->position.x <= (28160 << 16))) {996self->position.x = 28160 << 16;997RSDK.SetSpriteAnimation(-1, 0, &self->flameAnimator, true, 0);998LaundroMobile->rocketActive = false;999RSDK.PlaySfx(LaundroMobile->sfxHullClose, false, 255);1000self->state = LaundroMobile_StateBoss_PrepareWhirlpool;1001}10021003LaundroMobile_HandleRocketMovement();1004LaundroMobile_CheckPlayerCollisions();1005LaundroMobile_HandleEggmanAnimations();1006}10071008void LaundroMobile_StateBoss_PrepareWhirlpool(void)1009{1010RSDK_THIS(LaundroMobile);10111012if (LaundroMobile->rocketSpeeds[0] <= 0x180) {1013if (!(LaundroMobile->rocketAngles[0] & 0x7E00)) {1014LaundroMobile->rocketSpeeds[0] = 0;1015LaundroMobile->rocketAngles[0] &= 0xFE00;1016LaundroMobile->rocketAngles[1] &= 0xFE00;1017}1018}1019else {1020LaundroMobile->rocketSpeeds[0] -= 8;1021}10221023if (LaundroMobile->rocketSpeeds[1] <= 0x180) {1024if (!(LaundroMobile->rocketAngles[2] & 0x7E00)) {1025LaundroMobile->rocketSpeeds[1] = 0;1026LaundroMobile->rocketAngles[2] &= 0xFE00;1027LaundroMobile->rocketAngles[3] &= 0xFE00;1028}1029}1030else {1031LaundroMobile->rocketSpeeds[1] -= 8;1032}10331034if (!(LaundroMobile->rocketSpeeds[0] + LaundroMobile->rocketSpeeds[1])) {1035RSDK.PlaySfx(LaundroMobile->sfxFan, false, 255);1036self->state = LaundroMobile_StateBoss_StartupWhirlpool;1037}10381039LaundroMobile_HandleRocketMovement();1040LaundroMobile_CheckPlayerCollisions();1041LaundroMobile_HandleEggmanAnimations();1042}10431044void LaundroMobile_StateBoss_StartupWhirlpool(void)1045{1046RSDK_THIS(LaundroMobile);10471048LaundroMobile->animSpeed += 4;1049if (LaundroMobile->animSpeed < 0x100) {1050LaundroMobile_CheckPlayerCollisions();1051LaundroMobile_HandleEggmanAnimations();1052}1053else {1054EntityWhirlpool *whirlpool = self->whirlpool;1055if (whirlpool) {1056if (whirlpool->classID == Whirlpool->classID) {1057whirlpool->position.x = self->position.x;1058}1059else {1060self->whirlpool = NULL;1061}10621063self->timer = 480;1064self->state = LaundroMobile_StateBoss_WhirlpoolActive;1065}1066else {1067Vector2 pos = { 0x1000000, 0x1000000 };1068whirlpool = CREATE_ENTITY(Whirlpool, &pos, self->position.x, self->originPos.y - 0x200000);10691070whirlpool->activePlayers = 0xFF;1071whirlpool->angVel = 10;1072whirlpool->alpha = 0;1073whirlpool->drawGroup = Zone->objectDrawGroup[0] + 1;1074whirlpool->isPermanent = true;1075self->whirlpool = whirlpool;10761077self->timer = 480;1078self->state = LaundroMobile_StateBoss_WhirlpoolActive;1079}1080}1081}10821083void LaundroMobile_StateBoss_WhirlpoolActive(void)1084{1085RSDK_THIS(LaundroMobile);10861087++LaundroMobile->loopSfxTimer;10881089if (--self->timer > 0) {1090foreach_active(Player, player)1091{1092int32 playerID = RSDK.GetEntitySlot(player);1093if (player->position.y > Water->waterLevel) {1094if (player->state == Player_State_Static) {1095player->onGround = false;1096player->nextGroundState = StateMachine_None;1097player->nextAirState = StateMachine_None;10981099if ((player->position.y & 0xFFFF0000) != (self->position.y & 0xFFFF0000) + 0x580000) {1100if (player->position.y >= self->position.y + 0x580000)1101player->position.y -= 0x10000;1102else1103player->position.y += 0x10000;1104}11051106if (LaundroMobile->playerRadius[playerID] != 0x5000) {1107if (LaundroMobile->playerRadius[playerID] >= 0x5000)1108LaundroMobile->playerRadius[playerID] -= 0x100;1109else1110LaundroMobile->playerRadius[playerID] += 0x100;1111}11121113if ((LaundroMobile->playerAngles[playerID] & 0xFF) >= 0x80)1114player->drawGroup = Zone->playerDrawGroup[0];1115else1116player->drawGroup = self->drawGroup - 1;11171118LaundroMobile->playerAngles[playerID] += 3;1119player->position.x =1120LaundroMobile->playerRadius[playerID] * RSDK.Cos256(LaundroMobile->playerAngles[playerID]) + self->position.x;1121}1122else if (Player_CheckValidState(player)) {1123player->onGround = false;1124player->velocity.x = 0;1125player->velocity.y = 0;1126player->groundVel = 0;1127player->nextGroundState = StateMachine_None;1128player->nextAirState = StateMachine_None;1129LaundroMobile->playerRadius[playerID] = ((player->position.x - self->position.x) & 0xFFFF0000);11301131if (LaundroMobile->playerRadius[playerID] <= 0) {1132LaundroMobile->playerRadius[playerID] = -LaundroMobile->playerRadius[playerID];1133LaundroMobile->playerAngles[playerID] = 128;1134}1135else {1136LaundroMobile->playerAngles[playerID] = 0;1137}1138LaundroMobile->playerRadius[playerID] >>= 8;1139RSDK.SetSpriteAnimation(player->aniFrames, ANI_FAN, &player->animator, false, 0);11401141player->state = Player_State_Static;1142}1143}1144}1145}1146else {1147foreach_active(Player, player)1148{1149int32 playerID = RSDK.GetEntitySlot(player);1150if (player->state == Player_State_Static) {1151player->velocity.x = player->position.x1152- LaundroMobile->playerRadius[playerID] * RSDK.Cos256(LaundroMobile->playerAngles[playerID] - 3)1153- self->position.x;1154player->drawGroup = Zone->playerDrawGroup[0];1155player->state = Player_State_Air;1156}1157}11581159EntityWhirlpool *whirlpool = self->whirlpool;1160if (whirlpool) {1161if (whirlpool->classID == Whirlpool->classID)1162whirlpool->activePlayers = -3;11631164self->whirlpool = NULL;1165}11661167self->state = LaundroMobile_StateBoss_PrepareRockets;1168}11691170LaundroMobile_CheckPlayerCollisions();1171LaundroMobile_HandleEggmanAnimations();1172}11731174void LaundroMobile_StateBoss_PrepareRockets(void)1175{1176RSDK_THIS(LaundroMobile);11771178LaundroMobile->animSpeed -= 4;1179if (LaundroMobile->animSpeed <= 0) {1180self->velocity.y = 0;1181self->timer = 32;1182self->state = LaundroMobile_StateBoss_StartupRockets;1183}11841185LaundroMobile_CheckPlayerCollisions();1186LaundroMobile_HandleEggmanAnimations();1187}11881189void LaundroMobile_StateBoss_Destroyed_Phase2(void)1190{1191RSDK_THIS(LaundroMobile);11921193foreach_active(Player, player)1194{1195int32 playerID = RSDK.GetEntitySlot(player);11961197if (player->state == Player_State_Static) {1198player->velocity.x = player->position.x - LaundroMobile->playerRadius[playerID] * RSDK.Cos256(LaundroMobile->playerAngles[playerID] - 3)1199- self->position.x;1200player->drawGroup = Zone->playerDrawGroup[0];1201player->state = Player_State_Air;1202}1203}12041205LaundroMobile_Explode();12061207if (LaundroMobile->animSpeed > 0)1208LaundroMobile->animSpeed -= 4;12091210if (--LaundroMobile->invincibilityTimer) {1211if (LaundroMobile->invincibilityTimer == 30) {1212for (int32 i = 0; i < 4; ++i) {1213EntityDebris *debris =1214CREATE_ENTITY(Debris, Debris_State_FallAndFlicker, LaundroMobile->rocketPositions[i].x, LaundroMobile->rocketPositions[i].y);1215RSDK.SetSpriteAnimation(LaundroMobile->aniFrames, 5, &debris->animator, true, (LaundroMobile->rocketAngles[i] >> 12) & 0xF);1216debris->animator.speed = 0;12171218if (debris->position.y >= self->position.y) {1219debris->velocity.x = debris->position.x < self->position.x ? -0x20000 : 0x20000;1220debris->velocity.y = -0x10000;1221}1222else {1223debris->velocity.x = debris->position.x < self->position.x ? -0x40000 : 0x40000;1224debris->velocity.y = -0x20000;1225}12261227debris->gravityStrength = 0x3800;1228debris->drawGroup = Zone->objectDrawGroup[1];1229debris->updateRange.x = 0x400000;1230debris->updateRange.y = 0x400000;1231LaundroMobile->rocketPositions[i].x = 0;1232LaundroMobile->rocketPositions[i].y = 0;1233}1234}1235}1236else {1237self->timer = 60;1238self->velocity.y = 0x20000;1239self->state = LaundroMobile_StateBoss_Explode_Phase2;1240}1241}12421243void LaundroMobile_StateBoss_Explode_Phase2(void)1244{1245RSDK_THIS(LaundroMobile);12461247self->position.y += self->velocity.y;1248self->velocity.y -= 0x3800;12491250LaundroMobile_Explode();12511252if (--self->timer <= 0) {1253Water->moveWaterLevel = true;1254Water->targetWaterLevel += 0x780000;1255Water->waterMoveSpeed = 0x10000;1256self->timer = 0;12571258Music_TransitionTrack(TRACK_STAGE, 0.0125);12591260CREATE_ENTITY(EggPrison, INT_TO_VOID(EGGPRISON_FLYING), (ScreenInfo->position.x + ScreenInfo->center.x) << 16,1261(ScreenInfo->position.y - 48) << 16);12621263#if MANIA_USE_PLUS1264Zone->stageFinishCallback = LaundroMobile_StageFinish_Wait;1265self->state = LaundroMobile_StateOutro_StartCutscene;1266#else1267destroyEntity(self);1268#endif1269}1270}12711272#if MANIA_USE_PLUS1273void LaundroMobile_StageFinish_Wait(void) {}12741275void LaundroMobile_StateOutro_StartCutscene(void)1276{1277RSDK_THIS(LaundroMobile);12781279EntityActClear *actClear = RSDK_GET_ENTITY(SLOT_ACTCLEAR, ActClear);12801281if (self->timer) {1282if (actClear->classID != ActClear->classID) {1283self->timer = 0;12841285EntityPlayer *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);1286player1->drawGroup = Zone->playerDrawGroup[0];1287player1->state = Player_State_Ground;1288player1->direction = FLIP_NONE;1289player1->stateInput = StateMachine_None;1290RSDK.SetSpriteAnimation(player1->aniFrames, ANI_IDLE, &player1->animator, true, 0);12911292EntityPlayer *player2 = RSDK_GET_ENTITY(SLOT_PLAYER2, Player);1293if (player2->classID == Player->classID) {1294player2->drawGroup = Zone->playerDrawGroup[0];1295player2->state = Player_State_Ground;1296player2->direction = FLIP_NONE;1297player2->stateInput = StateMachine_None;1298RSDK.SetSpriteAnimation(player2->aniFrames, ANI_IDLE, &player2->animator, true, 0);1299}13001301self->state = LaundroMobile_StateOutro_Rumble;1302}1303}1304else if (actClear->classID == ActClear->classID) {1305self->timer = 1;1306}1307}13081309void LaundroMobile_StateOutro_Rumble(void)1310{1311RSDK_THIS(LaundroMobile);13121313EntityPlayer *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);1314EntityPlayer *player2 = RSDK_GET_ENTITY(SLOT_PLAYER2, Player);13151316player1->timer = 0;1317if (player2->classID == Player->classID)1318player2->timer = 0;13191320if (!(Zone->timer & 3)) {1321Camera_ShakeScreen(0, 0, 2);1322}13231324if (!(Zone->timer & 7))1325RSDK.PlaySfx(LaundroMobile->sfxRumble, false, 255);13261327if (++self->timer == 90) {1328self->timer = 0;1329foreach_active(WaterGush, gush)1330{1331if (gush->position.x > self->position.x) {1332gush->activated = true;1333gush->inkEffect = INK_ALPHA;1334gush->alpha = 256;1335gush->drawGroup = Zone->playerDrawGroup[0];1336}1337}13381339for (int32 i = 0; i < 0x20; ++i) {1340EntityDebris *debris = CREATE_ENTITY(Debris, Debris_State_Fall, 28336 << 16, 2784 << 16);13411342RSDK.SetSpriteAnimation(WaterGush->aniFrames, 4, &debris->animator, true, 0);1343debris->position.x += 0x60000 * RSDK.Rand(-8, 8);1344debris->position.y += 0x60000 * RSDK.Rand(-8, 8);1345debris->velocity.x = RSDK.Rand(-8, 8) << 16;1346debris->velocity.y = RSDK.Rand(-8, 8) << 16;1347debris->velocity.x = RSDK.Rand(-8, 9) << 15;1348debris->velocity.y = RSDK.Rand(-8, 5) << 16;1349debris->direction = RSDK.Rand(0, 4);1350debris->drawFX = FX_FLIP;1351debris->drawGroup = Zone->objectDrawGroup[1];1352debris->gravityStrength = 0x3800;1353}13541355RSDK.CopyTileLayer(Zone->fgLayer[1], 1763, 172, Zone->fgLayer[1], 1919, 172, 11, 4);13561357RSDK.PlaySfx(LaundroMobile->sfxImpact, false, 255);1358RSDK.PlaySfx(WaterGush->sfxGush, false, 255);1359RSDK.PlaySfx(Water->sfxSplash, false, 255);1360self->state = LaundroMobile_StateOutro_WaterGush;1361}1362}13631364void LaundroMobile_StateOutro_WaterGush(void)1365{1366RSDK_THIS(LaundroMobile);13671368EntityPlayer *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);1369EntityPlayer *player2 = RSDK_GET_ENTITY(SLOT_PLAYER2, Player);13701371player1->timer = 0;1372if (player2->classID == Player->classID)1373player2->timer = 0;13741375if (++self->timer < 75) {1376foreach_active(WaterGush, gush)1377{1378gush->position.y += 0x8000;1379gush->alpha -= 2;13801381if (gush->position.x > self->position.x) {1382if (gush->position.x - gush->gushPos < player1->position.x) {1383player1->velocity.x = -0x30000;1384player1->groundVel = -0x30000;1385}13861387if (player2->classID == Player->classID && gush->position.x - gush->gushPos < player2->position.x) {1388player2->velocity.x = -0x30000;1389player2->groundVel = -0x30000;1390}1391}1392}1393}1394else {1395foreach_active(WaterGush, gush)1396{1397gush->position.y += 0x8000;1398gush->alpha -= 2;13991400if (gush->position.x > self->position.x && gush->alpha <= 0) {1401destroyEntity(gush);14021403for (int32 p = 0; p < PLAYER_COUNT; ++p) Zone->playerBoundActiveR[p] = false;14041405self->timer = 0;1406self->state = LaundroMobile_StateOutro_ExitHCZ;1407}1408}1409}1410}14111412void LaundroMobile_StateOutro_ExitHCZ(void)1413{1414RSDK_THIS(LaundroMobile);14151416if (++self->timer > 120) {1417RSDK_GET_ENTITY(SLOT_PLAYER2, Player)->right = true;14181419EntityPlayer *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);1420if (player1->classID == Player->classID)1421player1->right = true;14221423if (player1->position.x > (Zone->cameraBoundsR[0] + 64) << 16) {1424HCZSetup_StageFinish_EndAct2();1425destroyEntity(self);1426}1427}1428}1429#endif14301431void LaundroMobile_Draw_Boss(void)1432{1433RSDK_THIS(LaundroMobile);14341435if (LaundroMobile->invincibilityTimer & 1) {1436RSDK.SetPaletteEntry(0, 128, 0xE0E0E0);1437RSDK.SetPaletteEntry(1, 128, 0xE0E0E0);1438}14391440Vector2 drawPos;1441drawPos.x = self->position.x - 0x20000;1442drawPos.y = self->position.y - 0x1B0000;14431444self->mainAnimator.frameID = 4;1445RSDK.DrawSprite(&self->mainAnimator, &drawPos, false);14461447drawPos.y += 0x300000;1448RSDK.DrawSprite(&self->mainAnimator, &drawPos, false);14491450drawPos = self->position;1451drawPos.x += 0x100000;1452RSDK.DrawSprite(&self->eggmanAnimator, &drawPos, false);14531454self->mainAnimator.frameID = 0;1455RSDK.DrawSprite(&self->mainAnimator, NULL, false);1456RSDK.DrawSprite(&self->propellerAnimator, NULL, false);14571458drawPos.x = self->position.x - 0x120000;1459drawPos.y = self->position.y - 0x1B0000;1460self->mainAnimator.frameID = 4;1461RSDK.DrawSprite(&self->mainAnimator, &drawPos, false);14621463drawPos.y += 0x300000;1464RSDK.DrawSprite(&self->mainAnimator, &drawPos, false);14651466RSDK.SetPaletteEntry(0, 128, 0x000000);1467RSDK.SetPaletteEntry(1, 128, 0x000000);1468}14691470void LaundroMobile_Draw_Boss_Destroyed(void)1471{1472RSDK_THIS(LaundroMobile);14731474if (LaundroMobile->invincibilityTimer & 1) {1475RSDK.SetPaletteEntry(0, 128, 0xE0E0E0);1476RSDK.SetPaletteEntry(1, 128, 0xE0E0E0);1477}14781479for (int32 r = 0; r < 4; ++r) {1480self->direction = r >= 2 ? FLIP_X : FLIP_NONE;1481uint8 angle = LaundroMobile->rocketAngles[r] >> 8;1482if (angle >= 0x80) {1483self->propellerAnimator.frameID = angle >> 4;14841485self->flameAnimator.frameID = 12;1486if (!(Zone->timer & 1))1487self->flameAnimator.frameID = self->propellerAnimator.frameID;14881489RSDK.DrawSprite(&self->propellerAnimator, &LaundroMobile->rocketPositions[r], false);1490RSDK.DrawSprite(&self->flameAnimator, &LaundroMobile->rocketPositions[r], false);1491}1492}14931494self->direction = FLIP_NONE;1495self->mainAnimator.frameID = 5;1496RSDK.DrawSprite(&self->mainAnimator, NULL, false);1497RSDK.DrawSprite(&self->eggmanAnimator, NULL, false);14981499self->mainAnimator.frameID = 1;1500RSDK.DrawSprite(&self->mainAnimator, NULL, false);15011502for (int32 r = 0; r < 4; ++r) {1503self->direction = r >= 2 ? FLIP_X : FLIP_NONE;1504uint8 angle = LaundroMobile->rocketAngles[r] >> 8;1505if (angle < 0x80) {1506self->propellerAnimator.frameID = angle >> 4;15071508self->flameAnimator.frameID = 12;1509if (!(Zone->timer & 1))1510self->flameAnimator.frameID = self->propellerAnimator.frameID;15111512angle = (angle + 64) & 0xFF;1513if (angle <= 0x80)1514RSDK.DrawSprite(&self->flameAnimator, &LaundroMobile->rocketPositions[r], false);15151516RSDK.DrawSprite(&self->propellerAnimator, &LaundroMobile->rocketPositions[r], false);15171518if (angle > 0x80)1519RSDK.DrawSprite(&self->flameAnimator, &LaundroMobile->rocketPositions[r], false);1520}1521}15221523self->direction = FLIP_NONE;1524RSDK.SetPaletteEntry(0, 128, 0x000000);1525RSDK.SetPaletteEntry(1, 128, 0x000000);1526}15271528void LaundroMobile_StateBomb_Spawner(void)1529{1530RSDK_THIS(LaundroMobile);15311532if (self->active == ACTIVE_BOUNDS) {1533if (self->position.x + 0x200000 > ScreenInfo->position.x << 16) {1534if (self->position.x - 0x200000 <= (ScreenInfo->position.x + ScreenInfo->size.x) << 16) {1535self->visible = false;1536EntityLaundroMobile *bomb = CREATE_ENTITY(LaundroMobile, INT_TO_VOID(LAUNDROMOBILE_BOMB), self->position.x, self->position.y);1537bomb->velocity.x = LaundroMobile->currentVelocity - 0x20000;1538bomb->active = ACTIVE_NORMAL;1539bomb->state = LaundroMobile_StateBomb_Bomb_Idle;1540bomb->isPermanent = true;1541self->active = ACTIVE_NORMAL;1542}1543}1544}1545else {1546if (self->position.x + 0x200000 < ScreenInfo->position.x << 16) {1547self->visible = true;1548self->active = ACTIVE_BOUNDS;1549}1550}1551}15521553void LaundroMobile_StateBomb_Bomb_Idle(void)1554{1555RSDK_THIS(LaundroMobile);15561557self->position.x += self->velocity.x;15581559foreach_active(Player, player)1560{1561int32 velX = player->velocity.x;15621563if (Player_CheckCollisionBox(player, self, &LaundroMobile->hitboxBox) == C_LEFT) {1564RSDK.PlaySfx(LaundroMobile->sfxButton, false, 255);1565self->velocity.x = LaundroMobile->currentVelocity + 0x18000;1566RSDK.SetSpriteAnimation(LaundroMobile->aniFrames, 8, &self->mainAnimator, true, 0);1567self->state = LaundroMobile_StateBomb_Bomb_Activated;1568}15691570player->velocity.x = velX;1571}15721573if (self->position.x + 0x200000 < ScreenInfo->position.x << 16) {1574destroyEntity(self);1575}1576else {1577foreach_active(LaundroMobile, boss)1578{1579if (boss->type == LAUNDROMOBILE_BOSS1580&& RSDK.CheckObjectCollisionTouchBox(boss, &LaundroMobile->hitboxBoss, self, &LaundroMobile->hitboxBox)1581&& boss->state == LaundroMobile_StateBoss_Explode_Phase1) {1582RSDK.PlaySfx(LaundroMobile->sfxPimPom, false, 255);15831584EntityDebris *debris = CREATE_ENTITY(Debris, Debris_State_FallAndFlicker, self->position.x, self->position.y);1585RSDK.SetSpriteAnimation(LaundroMobile->aniFrames, 7, &debris->animator, true, 0);1586debris->velocity.y = -0x28000;1587debris->velocity.x = LaundroMobile->currentVelocity + 0x28000;1588debris->gravityStrength = 0x3800;1589debris->drawGroup = Zone->objectDrawGroup[1];1590debris->updateRange.x = 0x400000;1591debris->updateRange.y = 0x400000;15921593destroyEntity(self);1594foreach_break;1595}1596}1597}1598}15991600void LaundroMobile_StateBomb_Bomb_Activated(void)1601{1602RSDK_THIS(LaundroMobile);16031604self->position.x += self->velocity.x;1605self->velocity.x -= 0x800;16061607RSDK.ProcessAnimation(&self->mainAnimator);16081609if (self->position.x + 0x200000 < ScreenInfo->position.x << 16) {1610destroyEntity(self);1611}1612else {1613foreach_active(Player, player)1614{1615int32 velX = player->velocity.x;1616Player_CheckCollisionBox(player, self, &LaundroMobile->hitboxBox);1617player->velocity.x = velX;1618}16191620EntityLaundroMobile *boss = LaundroMobile->laundroMobile;1621if (RSDK.CheckObjectCollisionTouchBox(boss, &LaundroMobile->hitboxBoss, self, &LaundroMobile->hitboxBox)) {1622EntityExplosion *explosion = CREATE_ENTITY(Explosion, INT_TO_VOID(EXPLOSION_BOSS), self->position.x, self->position.y);1623explosion->drawGroup = Zone->objectDrawGroup[1];1624explosion->velocity.x = LaundroMobile->currentVelocity - 0x10000;1625RSDK.PlaySfx(LaundroMobile->sfxExplosion, false, 255);16261627EntityWater *water = CREATE_ENTITY(Water, INT_TO_VOID(WATER_BUBBLE), self->position.x, self->position.y);1628water->drawGroup = Zone->objectDrawGroup[0] + 1;1629water->angle = 2 * RSDK.Rand(0, 256);1630water->speed = -0x1400;1631water->velocity.x = (LaundroMobile->currentVelocity + (LaundroMobile->currentVelocity >> 2)) + (LaundroMobile->currentVelocity >> 1);1632water->bubbleX = water->position.x;1633water->childPtr = 0;1634RSDK.SetSpriteAnimation(Water->aniFrames, 3, &water->animator, false, 5);1635water->tileCollisions = TILECOLLISION_DOWN;16361637if (!LaundroMobile->invincibilityTimer) {1638--LaundroMobile->health;1639RSDK.SetSpriteAnimation(LaundroMobile->eggmanFrames, 2, &boss->eggmanAnimator, true, 0);1640RSDK.PlaySfx(LaundroMobile->sfxHit, false, 255);1641LaundroMobile->invincibilityTimer = 30;1642if (LaundroMobile->health <= 8) {1643RSDK.StopSfx(LaundroMobile->sfxFan);1644RSDK.SetSpriteAnimation(LaundroMobile->aniFrames, 4, &boss->propellerAnimator, true, 0);1645boss->timer = 60;1646boss->state = LaundroMobile_StateBoss_Destroyed_Phase1;1647}1648}1649destroyEntity(self);1650}1651}1652}16531654void LaundroMobile_Draw_Simple(void)1655{1656RSDK_THIS(LaundroMobile);16571658RSDK.DrawSprite(&self->mainAnimator, NULL, false);1659}16601661void LaundroMobile_StateBlock_Spawner(void)1662{1663RSDK_THIS(LaundroMobile);16641665if (self->active == ACTIVE_BOUNDS) {1666if (self->position.x + 0x200000 > ScreenInfo->position.x << 16) {1667if (self->position.x - 0x200000 <= (ScreenInfo->position.x + ScreenInfo->size.x) << 16) {1668self->visible = false;16691670EntityLaundroMobile *block = CREATE_ENTITY(LaundroMobile, INT_TO_VOID(self->type), self->position.x, self->position.y);1671block->velocity.x = LaundroMobile->currentVelocity - 0x20000;1672block->active = ACTIVE_NORMAL;1673block->state = LaundroMobile_StateBlock_Block;1674block->isPermanent = true;16751676self->active = ACTIVE_NORMAL;1677}1678}1679}1680else {1681if (self->position.x + 0x200000 < ScreenInfo->position.x << 16) {1682self->visible = true;1683self->active = ACTIVE_BOUNDS;1684}1685}1686}16871688void LaundroMobile_StateBlock_Block(void)1689{1690RSDK_THIS(LaundroMobile);16911692self->position.x += self->velocity.x;16931694foreach_active(Player, player)1695{1696if (self->type == LAUNDROMOBILE_SPIKES) {1697if (Player_CheckCollisionBox(player, self, &LaundroMobile->hitboxBomb) == C_LEFT) {1698Player_Hurt(player, self);1699}1700}1701else {1702Player_CheckCollisionBox(player, self, &LaundroMobile->hitboxBox);1703}1704}17051706if (self->position.x + 0x200000 >= ScreenInfo->position.x << 16) {1707foreach_active(LaundroMobile, laundroMobile)1708{1709if (laundroMobile->type == LAUNDROMOBILE_BOSS) {1710Hitbox *hitbox = &LaundroMobile->hitboxBomb;1711if (self->type != LAUNDROMOBILE_SPIKES)1712hitbox = &LaundroMobile->hitboxBox;17131714if (RSDK.CheckObjectCollisionTouchBox(laundroMobile, &LaundroMobile->hitboxBoss, self, hitbox)1715|| laundroMobile->state == LaundroMobile_StateBoss_Explode_Phase1) {1716RSDK.PlaySfx(LaundroMobile->sfxLedgeBreak, false, 255);17171718EntityDebris *debris = NULL;1719if (self->type == LAUNDROMOBILE_SPIKES) {1720debris = CREATE_ENTITY(Debris, Debris_State_FallAndFlicker, self->position.x, self->position.y - 0x80000);1721RSDK.SetSpriteAnimation(LaundroMobile->aniFrames, 9, &debris->animator, true, 18);1722debris->drawFX |= FX_ROTATE;1723debris->velocity.x = LaundroMobile->currentVelocity + 0x18000;1724debris->velocity.y = -0x28000;1725debris->gravityStrength = 0x3800;1726debris->rotSpeed = RSDK.Rand(-8, 8);1727debris->drawGroup = Zone->objectDrawGroup[1];1728debris->updateRange.x = 0x400000;1729debris->updateRange.y = 0x400000;17301731debris = CREATE_ENTITY(Debris, Debris_State_FallAndFlicker, self->position.x, self->position.y + 0x80000);1732RSDK.SetSpriteAnimation(LaundroMobile->aniFrames, 9, &debris->animator, true, 18);1733debris->drawFX |= FX_ROTATE;1734debris->velocity.x = LaundroMobile->currentVelocity + 0x18000;1735debris->velocity.y = -0x20000;1736debris->gravityStrength = 0x3800;1737debris->rotSpeed = RSDK.Rand(-8, 8);1738debris->drawGroup = Zone->objectDrawGroup[1];1739debris->updateRange.x = 0x400000;1740debris->updateRange.y = 0x400000;1741self->position.x += 0x100000;1742}17431744debris = CREATE_ENTITY(Debris, Debris_State_FallAndFlicker, self->position.x, self->position.y);1745RSDK.SetSpriteAnimation(LaundroMobile->aniFrames, 9, &debris->animator, true, 4 * (self->mainAnimator.frameID % 3) + 6);1746debris->velocity.y = -0x28000;1747debris->velocity.x = LaundroMobile->currentVelocity + 0x20000;1748debris->gravityStrength = 0x3800;1749debris->drawGroup = Zone->objectDrawGroup[1];1750debris->updateRange.x = 0x400000;1751debris->updateRange.y = 0x400000;17521753debris = CREATE_ENTITY(Debris, Debris_State_FallAndFlicker, self->position.x, self->position.y);1754RSDK.SetSpriteAnimation(LaundroMobile->aniFrames, 9, &debris->animator, true, 4 * (self->mainAnimator.frameID % 3) + 7);1755debris->velocity.y = -0x28000;1756debris->velocity.x = LaundroMobile->currentVelocity + 0x28000;1757debris->gravityStrength = 0x3800;1758debris->drawGroup = Zone->objectDrawGroup[1];1759debris->updateRange.x = 0x400000;1760debris->updateRange.y = 0x400000;17611762debris = CREATE_ENTITY(Debris, Debris_State_FallAndFlicker, self->position.x, self->position.y);1763RSDK.SetSpriteAnimation(LaundroMobile->aniFrames, 9, &debris->animator, true, 4 * (self->mainAnimator.frameID % 3) + 8);1764debris->velocity.y = -0x20000;1765debris->velocity.x = LaundroMobile->currentVelocity + 0x20000;1766debris->gravityStrength = 0x3800;1767debris->drawGroup = Zone->objectDrawGroup[1];1768debris->updateRange.x = 0x400000;1769debris->updateRange.y = 0x400000;17701771debris = CREATE_ENTITY(Debris, Debris_State_FallAndFlicker, self->position.x, self->position.y);1772RSDK.SetSpriteAnimation(LaundroMobile->aniFrames, 9, &debris->animator, true, 4 * (self->mainAnimator.frameID % 3) + 9);1773debris->velocity.y = -0x20000;1774debris->velocity.x = LaundroMobile->currentVelocity + 0x28000;1775debris->gravityStrength = 0x3800;1776debris->drawGroup = Zone->objectDrawGroup[1];1777debris->updateRange.x = 0x400000;1778debris->updateRange.y = 0x400000;17791780destroyEntity(self);1781foreach_break;1782}1783}1784}1785}1786else {1787destroyEntity(self);1788}1789}17901791void LaundroMobile_State_Laundry(void)1792{1793RSDK_THIS(LaundroMobile);17941795self->propellerAnimator.speed = LaundroMobile->animSpeed;1796self->eggmanAnimator.speed = LaundroMobile->animSpeed;17971798RSDK.ProcessAnimation(&self->propellerAnimator);1799RSDK.ProcessAnimation(&self->eggmanAnimator);18001801Zone->playerBoundActiveL[0] = true;1802Zone->playerBoundActiveR[0] = true;1803Zone->cameraBoundsL[0] = ScreenInfo->position.x;1804Zone->cameraBoundsR[0] = ScreenInfo->center.x + (self->position.x >> 16);18051806if (RSDK_GET_ENTITY(SLOT_PLAYER1, Player)->position.x > self->position.x - 0xC00000)1807Zone->cameraBoundsT[0] = ScreenInfo->position.y;18081809if (!LaundroMobile->health && !LaundroMobile->invincibilityTimer) {1810Debris_CreateFromEntries_UseOffset(LaundroMobile->aniFrames, LaundroMobile->debrisInfo);1811destroyEntity(self);1812}1813}18141815void LaundroMobile_Draw_Laundry(void)1816{1817RSDK_THIS(LaundroMobile);18181819Vector2 drawPos = self->position;1820self->mainAnimator.frameID = 2;1821RSDK.DrawSprite(&self->mainAnimator, 0, false);1822RSDK.DrawSprite(&self->propellerAnimator, 0, false);18231824drawPos.y += 0x200000;1825RSDK.DrawSprite(&self->propellerAnimator, &drawPos, false);18261827drawPos.y += 0x200000;1828RSDK.DrawSprite(&self->propellerAnimator, &drawPos, false);18291830self->mainAnimator.frameID = 3;1831RSDK.DrawSprite(&self->mainAnimator, &drawPos, false);1832RSDK.DrawSprite(&self->eggmanAnimator, &drawPos, false);1833}18341835void LaundroMobile_State_DelayedSplash(void)1836{1837RSDK_THIS(LaundroMobile);18381839if (--self->timer <= 0) {1840CREATE_ENTITY(Water, INT_TO_VOID(WATER_SPLASH), self->position.x, Water->waterLevel);1841destroyEntity(self);1842}1843}18441845#if GAME_INCLUDE_EDITOR1846void LaundroMobile_EditorDraw(void)1847{1848RSDK_THIS(LaundroMobile);18491850switch (self->type) {1851case LAUNDROMOBILE_BOSS:1852RSDK.SetSpriteAnimation(LaundroMobile->aniFrames, 0, &self->mainAnimator, true, 0);1853RSDK.SetSpriteAnimation(LaundroMobile->aniFrames, 3, &self->propellerAnimator, true, 0);1854RSDK.SetSpriteAnimation(LaundroMobile->eggmanFrames, 0, &self->eggmanAnimator, true, 0);18551856self->startY = self->position.y;1857self->updateRange.x = 0x800000;1858self->updateRange.y = 0x800000;1859self->stateDraw = LaundroMobile_Draw_Boss;1860break;18611862case LAUNDROMOBILE_BOMB:1863self->originPos.x = self->position.x;1864self->originPos.y = self->position.y;18651866RSDK.SetSpriteAnimation(LaundroMobile->aniFrames, 7, &self->mainAnimator, true, 0);18671868self->updateRange.x = 0x1800000;1869self->updateRange.y = 0x1800000;1870self->stateDraw = LaundroMobile_Draw_Simple;1871break;18721873case LAUNDROMOBILE_LAUNDRY:1874RSDK.SetSpriteAnimation(LaundroMobile->aniFrames, 0, &self->mainAnimator, true, 0);1875RSDK.SetSpriteAnimation(LaundroMobile->aniFrames, 1, &self->propellerAnimator, true, 0);1876RSDK.SetSpriteAnimation(LaundroMobile->aniFrames, 2, &self->eggmanAnimator, true, 0);18771878self->updateRange.x = 0x2000000;1879self->updateRange.y = 0x800000;1880self->stateDraw = LaundroMobile_Draw_Laundry;1881break;18821883case LAUNDROMOBILE_LOOPPOINT:1884RSDK.SetSpriteAnimation(LaundroMobile->aniFrames, 0, &self->mainAnimator, true, 0);18851886RSDK.DrawSprite(&self->mainAnimator, NULL, false);1887self->stateDraw = StateMachine_None;1888break;18891890case LAUNDROMOBILE_BLOCK:1891self->originPos = self->position;18921893RSDK.SetSpriteAnimation(LaundroMobile->aniFrames, 9, &self->mainAnimator, false, 0);18941895self->updateRange.x = 0x1800000;1896self->updateRange.y = 0x1800000;1897self->stateDraw = LaundroMobile_Draw_Simple;1898break;18991900case LAUNDROMOBILE_SPIKES:1901self->originPos = self->position;19021903RSDK.SetSpriteAnimation(LaundroMobile->aniFrames, 9, &self->mainAnimator, false, 3);19041905self->updateRange.x = 0x1800000;1906self->updateRange.y = 0x1800000;1907self->stateDraw = LaundroMobile_Draw_Simple;1908break;19091910default: break;1911}19121913StateMachine_Run(self->stateDraw);1914}19151916void LaundroMobile_EditorLoad(void)1917{1918LaundroMobile->aniFrames = RSDK.LoadSpriteAnimation("HCZ/LaundroMobile.bin", SCOPE_STAGE);1919LaundroMobile->eggmanFrames = RSDK.LoadSpriteAnimation("Eggman/EggmanHCZ2.bin", SCOPE_STAGE);19201921RSDK_ACTIVE_VAR(LaundroMobile, type);1922RSDK_ENUM_VAR("Boss", LAUNDROMOBILE_BOSS);1923RSDK_ENUM_VAR("Bomb", LAUNDROMOBILE_BOMB);1924RSDK_ENUM_VAR("Laundry", LAUNDROMOBILE_LAUNDRY);1925RSDK_ENUM_VAR("Loop Point", LAUNDROMOBILE_LOOPPOINT);1926RSDK_ENUM_VAR("Block", LAUNDROMOBILE_BLOCK);1927RSDK_ENUM_VAR("Spikes", LAUNDROMOBILE_SPIKES);1928}1929#endif19301931void LaundroMobile_Serialize(void) { RSDK_EDITABLE_VAR(LaundroMobile, VAR_UINT8, type); }193219331934