Path: blob/master/SonicMania/Objects/MMZ/Gachapandora.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: Gachapandora Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectGachapandora *Gachapandora;1011void Gachapandora_Update(void)12{13RSDK_THIS(Gachapandora);1415StateMachine_Run(self->state);16}1718void Gachapandora_LateUpdate(void) {}1920void Gachapandora_StaticUpdate(void)21{22// Bug Details:23// there's no NULL check here for Gachapandora->eggman so this will be called even on MMZ1 and its NULL.24// Gachapandora->eggman also isn't cleared on StageLoad so this can point to a random entity25RSDK.AddDrawListRef(Zone->objectDrawGroup[0] + 1, RSDK.GetEntitySlot(Gachapandora->eggman));26}2728void Gachapandora_Draw(void)29{30RSDK_THIS(Gachapandora);3132StateMachine_Run(self->stateDraw);33}3435void Gachapandora_Create(void *data)36{37RSDK_THIS(Gachapandora);3839self->drawFX = FX_FLIP;40if (!SceneInfo->inEditor) {41if (globals->gameMode < MODE_TIMEATTACK) {42self->active = ACTIVE_BOUNDS;43if (data)44self->type = VOID_TO_INT(data);4546int32 capsuleOffset = 0;47switch (self->type) {48case GACHAPANDORA_MAIN:49self->visible = false;50self->drawGroup = Zone->objectDrawGroup[0];5152RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 0, &self->mainAnimator, true, 0);53RSDK.SetSpriteAnimation(Gachapandora->eggmanFrames, 0, &self->eggmanAnimator, true, 0);54RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 1, &self->handleAnimator, true, 7);55RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 2, &self->capsuleAnimator, true, 7);5657self->hitbox.left = -33;58self->hitbox.top = -37;59self->hitbox.right = 33;60self->hitbox.bottom = 6;6162self->startY = self->position.y;63self->updateRange.x = 0x800000;64self->updateRange.y = 0x800000;65Gachapandora->eggman = self;6667capsuleOffset = 55;68for (int32 i = GACHAPANDORA_CAPSULE_COUNT - 1; i >= 0; --i) {69int32 id = 0;7071Gachapandora->capsuleTypeL[i] = RSDK.Rand(0, 6);72id = Gachapandora->capsuleTypeL[i] % 3;7374while (id == Gachapandora->lastCapsuleType && Gachapandora->capsuleCount[id] == 3) {75Gachapandora->capsuleTypeL[i] = RSDK.Rand(0, 6);76id = Gachapandora->capsuleTypeL[i] % 3;77}7879Gachapandora->lastCapsuleType = Gachapandora->capsuleTypeL[i] % 3;80++Gachapandora->capsuleCount[Gachapandora->lastCapsuleType];81Gachapandora->capsuleOffsetL[i] = 4 * capsuleOffset;82Gachapandora->capsuleMaxL[i] = 4 * capsuleOffset;8384Gachapandora->capsuleTypeR[i] = RSDK.Rand(0, 6);85id = Gachapandora->capsuleTypeR[i] % 3;8687while (id == Gachapandora->lastCapsuleType && i && Gachapandora->capsuleCount[id] == 3) {88Gachapandora->capsuleTypeR[i] = RSDK.Rand(0, 6);89id = Gachapandora->capsuleTypeR[i] % 3;90}9192Gachapandora->lastCapsuleType = Gachapandora->capsuleTypeR[i] % 3;93++Gachapandora->capsuleCount[Gachapandora->lastCapsuleType];94Gachapandora->capsuleOffsetR[i] = 4 * capsuleOffset;95Gachapandora->capsuleMaxR[i] = 4 * capsuleOffset;9697capsuleOffset -= 18;98}99100Gachapandora->nextPrizeType = 0;101Gachapandora->handleSpinTimer = 0x7FFF;102Gachapandora->nextCapsuleL = 3;103Gachapandora->nextCapsuleR = 3;104Gachapandora->capsuleSide = RSDK.Rand(0, 2);105106if (Gachapandora->capsuleSide == 1) {107for (int32 i = 0; i < GACHAPANDORA_CAPSULE_COUNT; ++i) {108int32 store = Gachapandora->capsuleTypeL[i];109Gachapandora->capsuleTypeL[i] = Gachapandora->capsuleTypeR[i];110Gachapandora->capsuleTypeR[i] = store;111}112}113114self->state = Gachapandora_StateBoss_SetupArena;115self->stateDraw = Gachapandora_Draw_Boss;116break;117118case GACHAPANDORA_EGGMAN:119RSDK.SetSpriteAnimation(Gachapandora->eggmanFrames, 4, &self->mainAnimator, true, 0);120121self->state = Gachapandora_StateEggman_Falling;122self->stateDraw = Gachapandora_Draw_Simple;123124self->updateRange.x = 0x800000;125self->updateRange.y = 0x800000;126self->active = ACTIVE_NORMAL;127self->visible = true;128self->drawGroup = Zone->objectDrawGroup[0];129break;130131case GACHAPANDORA_PRIZE:132RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 2, &self->mainAnimator, true, 0);133134self->state = Gachapandora_StatePrize_CapsuleFall;135self->stateDraw = Gachapandora_Draw_Prize;136137self->updateRange.x = 0x800000;138self->updateRange.y = 0x800000;139self->active = ACTIVE_NORMAL;140self->visible = true;141self->drawGroup = Zone->objectDrawGroup[0];142break;143144case GACHAPANDORA_AMY:145case GACHAPANDORA_DRILLER:146case GACHAPANDORA_FIREDROPPER: break;147148case GACHAPANDORA_FIREBALL:149RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 11, &self->mainAnimator, true, 0);150151self->hitbox.left = -2;152self->hitbox.top = -2;153self->hitbox.right = 2;154self->hitbox.bottom = 2;155self->state = Gachapandora_StateFireball_Falling;156self->stateDraw = Gachapandora_Draw_Simple;157self->updateRange.x = 0x800000;158self->updateRange.y = 0x800000;159self->active = ACTIVE_NORMAL;160self->visible = true;161self->drawGroup = Zone->objectDrawGroup[0];162break;163164case GACHAPANDORA_DEBRIS:165self->active = ACTIVE_NORMAL;166self->visible = true;167self->drawGroup = Zone->objectDrawGroup[0];168169RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 0, &self->mainAnimator, true, 0);170171self->state = Gachapandora_StateDebris_Delay;172self->stateDraw = Gachapandora_Draw_Simple;173174self->updateRange.x = 0x800000;175self->updateRange.y = 0x800000;176break;177178case GACHAPANDORA_SPARK:179self->active = ACTIVE_NORMAL;180self->visible = true;181self->drawGroup = Zone->objectDrawGroup[1];182183RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 13, &self->mainAnimator, true, 0);184185self->state = Gachapandora_StateSpark_Attached;186self->stateDraw = Gachapandora_Draw_Simple;187188self->updateRange.x = 0x800000;189self->updateRange.y = 0x800000;190break;191192default: break;193}194}195else {196destroyEntity(self);197}198}199}200201void Gachapandora_StageLoad(void)202{203Gachapandora->aniFrames = RSDK.LoadSpriteAnimation("MMZ/Gachapandora.bin", SCOPE_STAGE);204Gachapandora->eggmanFrames = RSDK.LoadSpriteAnimation("Eggman/EggmanMMZ2.bin", SCOPE_STAGE);205206Gachapandora->hitboxHandle.left = -16;207Gachapandora->hitboxHandle.top = 22;208Gachapandora->hitboxHandle.right = 16;209Gachapandora->hitboxHandle.bottom = 30;210211Gachapandora->hitboxAmyRange.left = -128;212Gachapandora->hitboxAmyRange.top = -256;213Gachapandora->hitboxAmyRange.right = 128;214Gachapandora->hitboxAmyRange.bottom = 256;215216Gachapandora->hitboxAmy.left = -32;217Gachapandora->hitboxAmy.top = -32;218Gachapandora->hitboxAmy.right = 0;219Gachapandora->hitboxAmy.bottom = 32;220221Gachapandora->hitboxFireball.left = -5;222Gachapandora->hitboxFireball.top = -11;223Gachapandora->hitboxFireball.right = 5;224Gachapandora->hitboxFireball.bottom = 0;225226Gachapandora->hitboxDrill.left = -28;227Gachapandora->hitboxDrill.top = 3;228Gachapandora->hitboxDrill.right = -20;229Gachapandora->hitboxDrill.bottom = 10;230231Gachapandora->hitboxSpark.left = -2;232Gachapandora->hitboxSpark.top = 2;233Gachapandora->hitboxSpark.right = -2;234Gachapandora->hitboxSpark.bottom = 2;235236Gachapandora->active = ACTIVE_ALWAYS;237Gachapandora->activeToys = 0;238Gachapandora->awardAchievement = false;239Gachapandora->destroyedToys = 0;240Gachapandora->lastCapsuleType = -1;241Gachapandora->capsuleCount[0] = 0;242Gachapandora->capsuleCount[1] = 0;243Gachapandora->capsuleCount[2] = 0;244245Gachapandora->sfxHit = RSDK.GetSfx("Stage/BossHit.wav");246Gachapandora->sfxExplosion = RSDK.GetSfx("Stage/Explosion2.wav");247Gachapandora->sfxUnravel = RSDK.GetSfx("Stage/Unravel.wav");248Gachapandora->sfxPon = RSDK.GetSfx("Stage/Pon.wav");249Gachapandora->sfxFireball = RSDK.GetSfx("Stage/Fireball.wav");250Gachapandora->sfxGiggle = RSDK.GetSfx("MMZ/Giggle.wav");251}252253void Gachapandora_CheckPlayerCollisions_Prize(void)254{255RSDK_THIS(Gachapandora);256257foreach_active(Player, player)258{259if (player->animator.animationID != ANI_VICTORY) {260if (Player_CheckBadnikTouch(player, self, &self->hitbox)) {261int32 blink = player->blinkTimer;262if (self->type == GACHAPANDORA_AMY)263player->blinkTimer = 1;264265bool32 wasHit = false;266if (Player_CheckBossHit(player, self)) {267if (self->health)268self->health--;269270if (self->health) {271RSDK.PlaySfx(Gachapandora->sfxHit, false, 255);272}273else {274EntityGachapandora *eggman = Gachapandora->eggman;275RSDK.SetSpriteAnimation(Gachapandora->eggmanFrames, 1, &eggman->eggmanAnimator, true, 0);276RSDK.PlaySfx(Gachapandora->sfxExplosion, false, 255);277self->state = Gachapandora_StatePrize_Destroyed;278}279self->invincibilityTimer = 30;280wasHit = true;281}282283if (self->type == GACHAPANDORA_AMY)284player->blinkTimer = blink;285286if (wasHit)287foreach_break;288}289else {290if (self->type == GACHAPANDORA_DRILLER) {291if (Player_CheckCollisionTouch(player, self, &Gachapandora->hitboxDrill))292Player_Hurt(player, self);293}294}295}296}297}298299void Gachapandora_Explode(int32 xMin, int32 xMax, int32 yMin, int32 yMax)300{301RSDK_THIS(Gachapandora);302303int32 interval = 4 * (self->state == Gachapandora_StateBoss_Explode) + 3;304305if (!(Zone->timer % interval)) {306RSDK.PlaySfx(Gachapandora->sfxExplosion, false, 255);307308if (Zone->timer & 4) {309int32 x = self->position.x + (RSDK.Rand(xMin, xMax) << 16);310int32 y = self->position.y + (RSDK.Rand(yMin, yMax) << 16);311CREATE_ENTITY(Explosion, INT_TO_VOID((RSDK.Rand(0, 256) > 192) + EXPLOSION_BOSS), x, y)->drawGroup = Zone->objectDrawGroup[1] + 2;312}313}314}315316void Gachapandora_Player_StateInput_P1Grabbed(void)317{318RSDK_THIS(Player);319320Player_Input_P1();321322self->up = false;323self->down = false;324self->jumpPress = false;325self->jumpHold = false;326327self->velocity.x = CLAMP(self->velocity.x, -0x20000, 0x20000);328self->groundVel = CLAMP(self->groundVel, -0x20000, 0x20000);329}330331void Gachapandora_Player_StateInput_P2PlayerGrabbed(void)332{333RSDK_THIS(Player);334335Player_Input_P2_Player();336337self->up = false;338self->down = false;339self->jumpPress = false;340self->jumpHold = false;341342self->velocity.x = CLAMP(self->velocity.x, -0x40000, 0x40000);343self->groundVel = CLAMP(self->groundVel, -0x40000, 0x40000);344345if (self->stateInput == Player_Input_P2_AI)346self->stateInput = Gachapandora_Player_StateInput_P2AIGrabbed;347}348349void Gachapandora_Player_StateInput_P2AIGrabbed(void)350{351RSDK_THIS(Player);352353Player_Input_P2_AI();354355self->up = false;356self->down = false;357self->jumpPress = false;358self->jumpHold = false;359360self->velocity.x = CLAMP(self->velocity.x, -0x40000, 0x40000);361self->groundVel = CLAMP(self->groundVel, -0x40000, 0x40000);362363if (self->stateInput == Player_Input_P2_Player)364self->stateInput = Gachapandora_Player_StateInput_P2PlayerGrabbed;365}366367void Gachapandora_HandleSparksAndDebris(void)368{369RSDK_THIS(Gachapandora);370371// is this line meant to be here??372// there's no check if this is 0 so it automatically goes to -1/255 (which is far too long)373// which would be fine, but the fact there's a switch case for health implies otherwise374--Gachapandora->debrisTimer;375376if (!Gachapandora->debrisTimer) {377switch (self->health) {378default:379case 0: break;380381case 1:382case 2: Gachapandora->debrisTimer = RSDK.Rand(8, 16); break;383384case 3: Gachapandora->debrisTimer = RSDK.Rand(15, 31); break;385case 4: Gachapandora->debrisTimer = RSDK.Rand(30, 61); break;386case 5: Gachapandora->debrisTimer = RSDK.Rand(60, 91); break;387388case 6:389case 7: Gachapandora->debrisTimer = RSDK.Rand(90, 121); break;390391case 8:392case 9: return;393}394395int32 type = RSDK.Rand(0, 3);396switch (type) {397case 2:398case 0: {399int32 off = RSDK.Rand(-12, 12);400EntityGachapandora *debris = CREATE_ENTITY(Gachapandora, INT_TO_VOID(GACHAPANDORA_DEBRIS),401self->position.x + (off << 16) + self->velocity.x, self->position.y + 0x300000);402403RSDK.SetSpriteAnimation(Gachapandora->aniFrames, RSDK.Rand(0, 4) + 18, &debris->mainAnimator, true, 0);404405if (self->state != Gachapandora_StateBoss_HandleSpun && !self->invincibilityTimer)406debris->velocity.x = self->velocity.x >> 1;407408debris->state = Gachapandora_StateDebris_BossDebris;409break;410}411412case 1: {413EntityGachapandora *spark = CREATE_ENTITY(Gachapandora, INT_TO_VOID(GACHAPANDORA_SPARK), self->position.x, self->position.y);414spark->parent = self;415416if (RSDK.Rand(0, 2))417spark->originPos.x = (RSDK.Rand(-6, 6) - 26) << 16;418else419spark->originPos.x = (RSDK.Rand(-6, 6) + 26) << 16;420spark->originPos.y = (RSDK.Rand(-8, 8) + 20) << 16;421422RSDK.SetSpriteAnimation(Explosion->aniFrames, 3, &spark->mainAnimator, true, 0);423break;424}425}426}427428if (self->state == Gachapandora_StateBoss_LastDitchAttack) {429for (int32 i = 0; i < 2; ++i) {430if (!--Gachapandora->sideSparkTimer[i]) {431Gachapandora->sideSparkTimer[i] = RSDK.Rand(16, 30);432433EntityGachapandora *spark = CREATE_ENTITY(Gachapandora, INT_TO_VOID(GACHAPANDORA_SPARK), self->position.x, self->position.y);434spark->parent = self;435436if (i) {437spark->originPos.x = (RSDK.Rand(-2, 2) - 34) << 16;438}439else {440spark->direction = FLIP_X;441spark->originPos.x = (RSDK.Rand(-2, 2) + 34) << 16;442}443spark->originPos.y = (RSDK.Rand(-8, 8) + 20) << 16;444445if (RSDK.Rand(0, 3) == 2)446RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 14, &spark->mainAnimator, true, 0);447}448}449}450}451452void Gachapandora_HandleAnimations(void)453{454RSDK_THIS(Gachapandora);455456if (self->eggmanAnimator.animationID) {457if (self->eggmanAnimator.animationID == 1) {458if (self->eggmanAnimator.frameID >= self->eggmanAnimator.frameCount - 1)459RSDK.SetSpriteAnimation(Gachapandora->eggmanFrames, 0, &self->eggmanAnimator, true, 0);460}461else {462if (self->eggmanAnimator.animationID == 2) {463bool32 wasHit = false;464foreach_active(Player, player)465{466if (player->state == Player_State_Hurt || player->state == Player_State_Death)467wasHit = true;468}469470if (self->eggmanAnimator.frameID >= self->eggmanAnimator.frameCount - 1) {471if (wasHit)472RSDK.SetSpriteAnimation(Gachapandora->eggmanFrames, 2, &self->eggmanAnimator, true, 6);473else474RSDK.SetSpriteAnimation(Gachapandora->eggmanFrames, 0, &self->eggmanAnimator, true, 0);475}476}477}478}479else {480bool32 wasHit = false;481foreach_active(Player, player)482{483if (player->state == Player_State_Hurt || player->state == Player_State_Death)484wasHit = true;485}486487if (wasHit)488RSDK.SetSpriteAnimation(Gachapandora->eggmanFrames, 2, &self->eggmanAnimator, true, 0);489}490}491492void Gachapandora_StateBoss_SetupArena(void)493{494RSDK_THIS(Gachapandora);495496if (++self->timer >= 2) {497self->timer = 0;498499Zone->playerBoundActiveR[0] = true;500Zone->playerBoundActiveB[0] = true;501Zone->cameraBoundsR[0] = (self->position.x >> 16) + ScreenInfo->center.x;502Zone->cameraBoundsB[0] = (self->position.y >> 16) + 128;503504self->position.y = (ScreenInfo->position.y - 192) << 16;505self->active = ACTIVE_NORMAL;506self->visible = true;507self->state = Gachapandora_StateBoss_AwaitPlayer;508}509}510511void Gachapandora_StateBoss_AwaitPlayer(void)512{513RSDK_THIS(Gachapandora);514515Zone->playerBoundActiveL[0] = true;516Zone->cameraBoundsL[0] = ScreenInfo->position.x;517518if (RSDK_GET_ENTITY(SLOT_PLAYER1, Player)->position.x > self->position.x) {519Zone->playerBoundActiveL[0] = true;520Zone->cameraBoundsL[0] = (self->position.x >> 16) - ScreenInfo->center.x;521522Music_TransitionTrack(TRACK_EGGMAN2, 0.0125);523self->health = 9;524self->state = Gachapandora_StateBoss_EnterEggman;525}526}527528void Gachapandora_StateBoss_EnterEggman(void)529{530RSDK_THIS(Gachapandora);531532RSDK.ProcessAnimation(&self->eggmanAnimator);533RSDK.ProcessAnimation(&self->handleAnimator);534535self->position.y = self->position.y + 0x10000;536537if (self->position.y < self->startY) {538if (self->position.y >= self->startY - 0x400000)539RSDK.SetSpriteAnimation(Gachapandora->eggmanFrames, 2, &self->eggmanAnimator, false, 0);540}541else {542self->position.y = self->startY;543self->originPos.x = self->position.x;544self->originPos.y = self->position.y;545self->angle = 0;546self->state = Gachapandora_StateBoss_FloatAround;547}548549RSDK.AddDrawListRef(Zone->objectDrawGroup[0] + 1, SceneInfo->entitySlot);550}551552void Gachapandora_StateBoss_FloatAround(void)553{554RSDK_THIS(Gachapandora);555556RSDK.ProcessAnimation(&self->eggmanAnimator);557RSDK.ProcessAnimation(&self->handleAnimator);558559Gachapandora_HandleAnimations();560561self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 2, 10);562563if (self->invincibilityTimer) {564if (!--self->invincibilityTimer && !self->velocity.x) {565self->velocity.x = self->direction == FLIP_NONE ? -0x8000 : 0x8000;566}567}568else {569if (self->position.x < (ScreenInfo->position.x + 64) << 16 || self->position.x > (ScreenInfo->position.x + ScreenInfo->size.x - 64) << 16)570self->velocity.x = -self->velocity.x;571572self->position.x += self->velocity.x;573}574575if (RSDK.Rand(0, 64) == 21)576Gachapandora->eggmanDir ^= FLIP_X;577578for (int32 i = 0; i < GACHAPANDORA_CAPSULE_COUNT; ++i) {579if (Gachapandora->capsuleDelayL[i]) {580Gachapandora->capsuleDelayL[i]--;581}582else if (Gachapandora->capsuleOffsetL[i] != Gachapandora->capsuleMaxL[i]) {583++Gachapandora->capsuleSpeedL[i];584Gachapandora->capsuleOffsetL[i] += Gachapandora->capsuleSpeedL[i];585586if (Gachapandora->capsuleOffsetL[i] > Gachapandora->capsuleMaxL[i])587Gachapandora->capsuleOffsetL[i] = Gachapandora->capsuleMaxL[i];588}589590if (Gachapandora->capsuleDelayR[i]) {591Gachapandora->capsuleDelayR[i]--;592}593else if (Gachapandora->capsuleOffsetR[i] != Gachapandora->capsuleMaxR[i]) {594++Gachapandora->capsuleSpeedR[i];595Gachapandora->capsuleOffsetR[i] += Gachapandora->capsuleSpeedR[i];596597if (Gachapandora->capsuleOffsetR[i] > Gachapandora->capsuleMaxR[i])598Gachapandora->capsuleOffsetR[i] = Gachapandora->capsuleMaxR[i];599}600}601602if (self->timer <= 0) {603foreach_active(Player, player)604{605if (Player_CheckCollisionTouch(player, self, &Gachapandora->hitboxHandle)) {606RSDK.PlaySfx(Gachapandora->sfxUnravel, false, 255);607608if (player->position.x >= self->position.x)609Gachapandora->handleDir = player->velocity.y < 0;610else611Gachapandora->handleDir = player->velocity.y > 0;612613RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 1, &self->handleAnimator, true, 0);614if (Gachapandora->nextCapsuleL + Gachapandora->nextCapsuleR == 0x1FE) {615self->invincibilityTimer = 25;616self->state = Gachapandora_StateBoss_Defeated;617}618else {619self->timer = 60;620int32 id = 0;621if (Gachapandora->capsuleSide) {622Gachapandora->handleSpinTimer = 148;623Gachapandora->nextPrizeType = Gachapandora->capsuleTypeR[Gachapandora->nextCapsuleR];624Gachapandora->capsuleOffsetR[Gachapandora->nextCapsuleR] = 0xFF;625Gachapandora->capsuleMaxR[Gachapandora->nextCapsuleR--] = 0xFF;626627while (id <= Gachapandora->nextCapsuleR) {628Gachapandora->capsuleDelayR[id] = 8 * (Gachapandora->nextCapsuleR - id + 2);629Gachapandora->capsuleMaxR[id] += 72;630Gachapandora->capsuleSpeedR[id++] = 0;631}632}633else {634Gachapandora->handleSpinTimer = -148;635Gachapandora->nextPrizeType = Gachapandora->capsuleTypeL[Gachapandora->nextCapsuleL];636Gachapandora->capsuleOffsetL[Gachapandora->nextCapsuleL] = 0xFF;637Gachapandora->capsuleMaxL[Gachapandora->nextCapsuleL--] = 0xFF;638639while (id <= Gachapandora->nextCapsuleL) {640Gachapandora->capsuleDelayL[id] = 8 * (Gachapandora->nextCapsuleL - id + 2);641Gachapandora->capsuleMaxL[id] += 72;642Gachapandora->capsuleSpeedL[id++] = 0;643}644}645646Gachapandora->capsuleSide ^= 1;647self->velocity.x += self->velocity.x >= 0 ? 0x4000 : -0x4000;648self->state = Gachapandora_StateBoss_HandleSpun;649}650foreach_break;651}652}653}654else {655self->timer--;656}657}658659void Gachapandora_StateBoss_HandleSpun(void)660{661RSDK_THIS(Gachapandora);662663RSDK.ProcessAnimation(&self->eggmanAnimator);664RSDK.ProcessAnimation(&self->handleAnimator);665666Gachapandora_HandleAnimations();667668self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 2, 10);669670if (RSDK.Rand(0, 64) == 21)671Gachapandora->eggmanDir ^= FLIP_X;672673for (int32 i = 0; i < GACHAPANDORA_CAPSULE_COUNT; ++i) {674if (Gachapandora->capsuleDelayL[i]) {675Gachapandora->capsuleDelayL[i]--;676}677else if (Gachapandora->capsuleOffsetL[i] != Gachapandora->capsuleMaxL[i]) {678++Gachapandora->capsuleSpeedL[i];679Gachapandora->capsuleOffsetL[i] += Gachapandora->capsuleSpeedL[i];680681if (Gachapandora->capsuleOffsetL[i] > Gachapandora->capsuleMaxL[i])682Gachapandora->capsuleOffsetL[i] = Gachapandora->capsuleMaxL[i];683}684685if (Gachapandora->capsuleDelayR[i]) {686Gachapandora->capsuleDelayR[i]--;687}688else if (Gachapandora->capsuleOffsetR[i] != Gachapandora->capsuleMaxR[i]) {689++Gachapandora->capsuleSpeedR[i];690Gachapandora->capsuleOffsetR[i] += Gachapandora->capsuleSpeedR[i];691692if (Gachapandora->capsuleOffsetR[i] > Gachapandora->capsuleMaxR[i])693Gachapandora->capsuleOffsetR[i] = Gachapandora->capsuleMaxR[i];694}695}696697if (Gachapandora->handleSpinTimer) {698if (Gachapandora->handleSpinTimer >= 0) {699Gachapandora->handleSpinTimer -= 3;700701if (Gachapandora->handleSpinTimer < 0)702Gachapandora->handleSpinTimer = 0;703}704else {705Gachapandora->handleSpinTimer += 3;706if (Gachapandora->handleSpinTimer > 0)707Gachapandora->handleSpinTimer = 0;708}709}710else {711EntityGachapandora *prize = CREATE_ENTITY(Gachapandora, INT_TO_VOID(GACHAPANDORA_PRIZE), self->position.x, self->position.y + 0x1A0000);712prize->type = Gachapandora->nextPrizeType;713714switch (prize->type) {715default: break;716case 0:717case 1: prize->mainAnimator.frameID = 0; break;718719case 2: prize->mainAnimator.frameID = 1; break;720721case 3:722case 4: prize->mainAnimator.frameID = 2; break;723724case 5: prize->mainAnimator.frameID = 3; break;725}726727Gachapandora->handleSpinTimer = 0x7FFF;728729if (--self->health == 1) {730EntityGachapandora *debris = CREATE_ENTITY(Gachapandora, INT_TO_VOID(GACHAPANDORA_DEBRIS), self->position.x, self->position.y);731debris->mainAnimator.frameID = 4;732debris->timer = 30;733debris->velocity.x = 0x20000;734debris->velocity.y = -0x20000;735736debris = CREATE_ENTITY(Gachapandora, INT_TO_VOID(GACHAPANDORA_DEBRIS), self->position.x, self->position.y);737debris->mainAnimator.frameID = 5;738debris->timer = 30;739debris->velocity.x = -0x20000;740debris->velocity.y = -0x20000;741742debris = CREATE_ENTITY(Gachapandora, INT_TO_VOID(GACHAPANDORA_DEBRIS), self->position.x, self->position.y);743++debris->drawGroup;744debris->mainAnimator.frameID = 2;745debris->timer = 90;746debris->velocity.x = -0x20000;747debris->velocity.y = -0x20000;748749debris = CREATE_ENTITY(Gachapandora, INT_TO_VOID(GACHAPANDORA_DEBRIS), self->position.x, self->position.y);750++debris->drawGroup;751debris->mainAnimator.frameID = 3;752debris->timer = 90;753debris->velocity.x = 0x20000;754debris->velocity.y = -0x20000;755756self->invincibilityTimer = 120;757758RSDK.SetSpriteAnimation(Gachapandora->eggmanFrames, 1, &self->eggmanAnimator, true, 0);759RSDK.SetSpriteAnimation(-1, 0, &self->capsuleAnimator, true, 0);760761self->state = Gachapandora_StateBoss_Explode;762self->stateDraw = Gachapandora_Draw_BossDestroyed;763}764else {765self->invincibilityTimer = 30;766self->state = Gachapandora_StateBoss_FloatAround;767}768}769}770771void Gachapandora_StateBoss_Explode(void)772{773RSDK_THIS(Gachapandora);774775RSDK.ProcessAnimation(&self->eggmanAnimator);776777Gachapandora_Explode(-24, 24, -48, 48);778Gachapandora_HandleSparksAndDebris();779780if (--self->invincibilityTimer <= 0)781self->state = Gachapandora_StateBoss_PanicFlee;782}783784void Gachapandora_StateBoss_PanicFlee(void)785{786RSDK_THIS(Gachapandora);787788RSDK.ProcessAnimation(&self->eggmanAnimator);789790Gachapandora_HandleSparksAndDebris();791792self->position.y += self->velocity.y;793self->velocity.y -= 0x1800;794795if (self->position.y < (ScreenInfo->position.y - 192) << 16) {796self->position.y = (ScreenInfo->position.y - 192) << 16;797self->position.x = (ScreenInfo->position.x + ScreenInfo->center.x) << 16;798self->state = Gachapandora_StateBoss_EnsureAllCapsulesDestroyed;799}800}801802void Gachapandora_StateBoss_EnsureAllCapsulesDestroyed(void)803{804RSDK_THIS(Gachapandora);805806if (Gachapandora->destroyedToys >= 8) {807self->originPos.y = self->position.y;808self->angle = 0;809810RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 17, &self->capsuleAnimator, true, 0);811812self->timer = 60;813self->velocity.x >>= 1;814self->state = Gachapandora_StateBoss_LastDitchAttack;815}816}817818void Gachapandora_StateBoss_LastDitchAttack(void)819{820RSDK_THIS(Gachapandora);821822RSDK.ProcessAnimation(&self->eggmanAnimator);823RSDK.ProcessAnimation(&self->handleAnimator);824RSDK.ProcessAnimation(&self->capsuleAnimator);825826Gachapandora_HandleAnimations();827828if (self->originPos.y >= self->startY) {829self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 2, 10);830}831else {832self->originPos.y += 0x10000;833self->position.y = self->originPos.y;834}835836Gachapandora_HandleSparksAndDebris();837838if (self->position.x < (ScreenInfo->position.x + 32) << 16 || self->position.x > (ScreenInfo->position.x + ScreenInfo->size.x - 32) << 16)839self->velocity.x = -self->velocity.x;840841self->position.x = self->position.x + self->velocity.x;842843if (RSDK.Rand(0, 64) == 21)844Gachapandora->eggmanDir ^= FLIP_X;845846if (--self->timer <= 0) {847self->timer = 60;848for (int32 i = 0; i < 2; ++i) {849EntityGachapandora *spark = CREATE_ENTITY(Gachapandora, INT_TO_VOID(GACHAPANDORA_SPARK), self->position.x, self->position.y);850RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 15, &spark->mainAnimator, true, 0);851852if (i) {853spark->position.x += (RSDK.Rand(-2, 2) - 34) << 16;854spark->velocity.x = self->velocity.x - 0x10000;855}856else {857spark->direction = FLIP_X;858spark->position.x += (RSDK.Rand(-2, 2) + 34) << 16;859spark->velocity.x = self->velocity.x + 0x10000;860}861862spark->state = Gachapandora_StateSpark_Detached;863spark->position.y += (RSDK.Rand(-8, 8) + 20) << 16;864}865}866867foreach_active(Player, player)868{869if (Player_CheckCollisionTouch(player, self, &Gachapandora->hitboxHandle)) {870RSDK.SetSpriteAnimation(Gachapandora->eggmanFrames, 4, &self->eggmanAnimator, true, 0);871RSDK.PlaySfx(Gachapandora->sfxUnravel, false, 255);872873if (player->position.x >= self->position.x)874Gachapandora->handleDir = player->velocity.y < 0;875else876Gachapandora->handleDir = player->velocity.y > 0;877878RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 1, &self->handleAnimator, true, 0);879self->invincibilityTimer = 25;880self->velocity.y = 0;881self->state = Gachapandora_StateBoss_Defeated;882foreach_break;883}884}885}886887void Gachapandora_StateBoss_Defeated(void)888{889RSDK_THIS(Gachapandora);890891Gachapandora_HandleSparksAndDebris();892893self->position.y += self->velocity.y;894self->velocity.y -= 0x800;895896RSDK.ProcessAnimation(&self->eggmanAnimator);897RSDK.ProcessAnimation(&self->handleAnimator);898RSDK.ProcessAnimation(&self->capsuleAnimator);899900Gachapandora_HandleSparksAndDebris();901902self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 2, 10);903if (!--self->invincibilityTimer) {904CREATE_ENTITY(Gachapandora, INT_TO_VOID(GACHAPANDORA_EGGMAN), self->position.x, self->position.y - 0x100000)->parent = self;905RSDK.SetSpriteAnimation(-1, 0, &self->eggmanAnimator, true, 0);906self->invincibilityTimer = 60;907self->state = Gachapandora_StateBoss_EggmanFallOut;908}909}910911void Gachapandora_StateBoss_EggmanFallOut(void)912{913RSDK_THIS(Gachapandora);914915RSDK.ProcessAnimation(&self->eggmanAnimator);916RSDK.ProcessAnimation(&self->handleAnimator);917RSDK.ProcessAnimation(&self->capsuleAnimator);918919Gachapandora_HandleSparksAndDebris();920921self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 2, 10);922self->position.y += self->velocity.y;923self->velocity.y -= 0x800;924925if (!--self->invincibilityTimer) {926SceneInfo->timeEnabled = false;927Player_GiveScore(RSDK_GET_ENTITY(SLOT_PLAYER1, Player), 1000);928self->invincibilityTimer = 120;929self->state = Gachapandora_StateBoss_Finish;930}931}932933void Gachapandora_StateBoss_Finish(void)934{935RSDK_THIS(Gachapandora);936937RSDK.ProcessAnimation(&self->eggmanAnimator);938RSDK.ProcessAnimation(&self->handleAnimator);939RSDK.ProcessAnimation(&self->capsuleAnimator);940941Gachapandora_HandleSparksAndDebris();942Gachapandora_Explode(-24, 24, -48, 48);943944if (self->invincibilityTimer) {945if (!--self->invincibilityTimer || self->invincibilityTimer == 96)946self->velocity.y = -0x40000;947}948else {949self->position.y += self->velocity.y;950self->velocity.y += 0x1800;951952if (self->position.y > (ScreenInfo->position.y + ScreenInfo->size.y + 128) << 16) {953Zone->cameraBoundsR[0] += WIDE_SCR_XSIZE;954self->state = StateMachine_None;955Music_TransitionTrack(TRACK_STAGE, 0.0125);956}957}958}959960void Gachapandora_Draw_Boss(void)961{962RSDK_THIS(Gachapandora);963964Vector2 drawPos = self->position;965if (SceneInfo->currentDrawGroup == Zone->objectDrawGroup[0]) {966self->mainAnimator.frameID = 4;967RSDK.DrawSprite(&self->mainAnimator, NULL, false);968969self->mainAnimator.frameID = 5;970RSDK.DrawSprite(&self->mainAnimator, NULL, false);971972for (int32 i = 0; i < GACHAPANDORA_CAPSULE_COUNT; ++i) {973if (Gachapandora->capsuleOffsetL[i] != 0xFF) {974self->capsuleAnimator.frameID = ((Gachapandora->capsuleTypeL[i] % 3) >> 1) + 2 * (Gachapandora->capsuleTypeL[i] / 3);975drawPos.x = self->position.x - (Gachapandora->capsuleOffsets[56 - (Gachapandora->capsuleOffsetL[i] >> 2)] << 16);976drawPos.y = self->position.y + (((Gachapandora->capsuleOffsetL[i] & 0xFC) - 152) << 14);977RSDK.DrawSprite(&self->capsuleAnimator, &drawPos, false);978}979980if (Gachapandora->capsuleOffsetR[i] != 0xFF) {981self->capsuleAnimator.frameID = ((Gachapandora->capsuleTypeR[i] % 3) >> 1) + 2 * (Gachapandora->capsuleTypeR[i] / 3);982drawPos.x = self->position.x + (Gachapandora->capsuleOffsets[56 - (Gachapandora->capsuleOffsetR[i] >> 2)] << 16);983drawPos.y = self->position.y + (((Gachapandora->capsuleOffsetR[i] & 0xFC) - 152) << 14);984RSDK.DrawSprite(&self->capsuleAnimator, &drawPos, false);985}986}987988if (Gachapandora->handleSpinTimer != 0x7FFF) {989self->capsuleAnimator.frameID = ((Gachapandora->nextPrizeType % 3) >> 1) + 2 * (Gachapandora->nextPrizeType / 3);990drawPos.x = self->position.x + (Gachapandora->handleSpinTimer << 14);991drawPos.y = self->position.y + 0x120000;992RSDK.DrawSprite(&self->capsuleAnimator, &drawPos, false);993}994995self->mainAnimator.frameID = 2;996RSDK.DrawSprite(&self->mainAnimator, NULL, false);997998self->mainAnimator.frameID = 3;999RSDK.DrawSprite(&self->mainAnimator, NULL, false);10001001self->mainAnimator.frameID = 0;1002RSDK.DrawSprite(&self->mainAnimator, NULL, false);10031004int32 storeDir = self->direction;1005self->direction = Gachapandora->eggmanDir;1006drawPos.x = self->position.x;1007drawPos.y = self->position.y - 0x100000;1008RSDK.DrawSprite(&self->eggmanAnimator, &drawPos, false);10091010self->direction = storeDir;1011}1012else {1013self->mainAnimator.frameID = 1;1014RSDK.DrawSprite(&self->mainAnimator, NULL, false);10151016int32 storeDir = self->direction;1017self->direction = Gachapandora->handleDir;1018drawPos.y += 0x1A0000;1019RSDK.DrawSprite(&self->handleAnimator, &drawPos, false);10201021self->direction = storeDir;1022}1023}10241025void Gachapandora_Draw_BossDestroyed(void)1026{1027RSDK_THIS(Gachapandora);10281029int32 storeDir = self->direction;1030Vector2 drawPos = self->position;1031if (SceneInfo->currentDrawGroup == Zone->objectDrawGroup[0]) {1032self->mainAnimator.frameID = 0;1033RSDK.DrawSprite(&self->mainAnimator, NULL, false);10341035self->direction = Gachapandora->eggmanDir;1036drawPos.x = self->position.x;1037drawPos.y = self->position.y - 0x100000;1038RSDK.DrawSprite(&self->eggmanAnimator, &drawPos, false);1039}1040else {1041self->mainAnimator.frameID = 1;1042RSDK.DrawSprite(&self->mainAnimator, NULL, false);10431044storeDir = self->direction;1045self->direction = Gachapandora->handleDir;1046drawPos.y += 0x1A0000;1047RSDK.DrawSprite(&self->handleAnimator, &drawPos, false);10481049self->direction = FLIP_NONE;1050RSDK.DrawSprite(&self->capsuleAnimator, NULL, false);10511052self->direction = FLIP_X;1053RSDK.DrawSprite(&self->capsuleAnimator, NULL, false);1054}10551056self->direction = storeDir;1057}10581059void Gachapandora_StatePrize_CapsuleFall(void)1060{1061RSDK_THIS(Gachapandora);10621063self->position.y += self->velocity.y;1064self->velocity.y += 0x2000;10651066if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0xC0000, true)) {1067EntityDebris *debris = CREATE_ENTITY(Debris, Debris_State_FallAndFlicker, self->position.x, self->position.y);1068RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 2, &debris->animator, true, 4);10691070debris->velocity.x = RSDK.Rand(-1, 2) << 16;1071debris->velocity.y = -0x48000;1072debris->gravityStrength = 0x3800;1073debris->drawGroup = Zone->objectDrawGroup[1];1074debris->updateRange.x = 0x400000;1075debris->updateRange.y = 0x400000;10761077debris = CREATE_ENTITY(Debris, Debris_State_FallAndFlicker, self->position.x, self->position.y);1078RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 2, &debris->animator, true, 5);10791080if (self->type > GACHAPANDORA_PRIZE)1081++debris->animator.frameID;1082debris->velocity.x = RSDK.Rand(-1, 2) << 15;1083debris->velocity.y = -0x30000;1084debris->gravityStrength = 0x3800;1085debris->drawGroup = Zone->objectDrawGroup[1];1086debris->updateRange.x = 0x400000;1087debris->updateRange.y = 0x400000;10881089RSDK.PlaySfx(Gachapandora->sfxPon, false, 255);1090self->velocity.y = -0x38000;1091switch (self->type) {1092case 0:1093case 3:1094RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 3, &self->mainAnimator, true, 0);1095self->type = GACHAPANDORA_DRILLER;1096if (RSDK_GET_ENTITY(SLOT_PLAYER1, Player)->position.x > self->position.x)1097self->direction = FLIP_X;1098break;10991100case 1:1101case 4:1102RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 4, &self->mainAnimator, true, 0);1103self->type = GACHAPANDORA_FIREDROPPER;1104break;11051106case 2:1107case 5:1108if (RSDK_GET_ENTITY(SLOT_PLAYER1, Player)->position.x > self->position.x)1109self->velocity.x = -0x8000;1110else1111self->velocity.x = 0x8000;1112RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 5, &self->mainAnimator, true, 0);1113self->type = GACHAPANDORA_AMY;1114break;11151116default: break;1117}11181119self->drawFX |= FX_SCALE;1120self->scale.x = 0x20;1121self->scale.y = 0x20;1122self->drawGroup = Zone->objectDrawGroup[1] + 1;1123if (++Gachapandora->activeToys >= 8 && !Gachapandora->destroyedToys)1124Gachapandora->awardAchievement = true;11251126self->state = Gachapandora_StatePrize_ExitCapsule;1127}1128}11291130void Gachapandora_StatePrize_ExitCapsule(void)1131{1132RSDK_THIS(Gachapandora);11331134self->position.y += self->velocity.y;1135self->velocity.y += 0x2000;11361137if (self->scale.x < 0x200) {1138self->scale.y += 16;1139self->scale.x += 16;1140}11411142switch (self->type) {1143default: break;1144case GACHAPANDORA_AMY:1145RSDK.ProcessAnimation(&self->mainAnimator);11461147self->position.x += self->velocity.x;11481149if (self->velocity.y >= 0) {1150if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0xC0000, true)) {1151self->velocity.y = 0;11521153self->hitbox.left = -5;1154self->hitbox.top = -11;1155self->hitbox.right = 5;1156self->hitbox.bottom = 11;11571158self->health = 1;1159RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 9, &self->mainAnimator, true, 0);1160self->state = Gachapandora_StatePrize_AmyWalk;1161}1162}1163break;11641165case GACHAPANDORA_DRILLER:1166if (self->velocity.y >= 0) {1167if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0x110000, true)) {1168self->velocity.x = self->direction == FLIP_NONE ? -0x20000 : 0x20000;1169self->velocity.y = -0x18000;11701171self->hitbox.left = -16;1172self->hitbox.top = -10;1173self->hitbox.right = 25;1174self->hitbox.bottom = 17;11751176self->health = 3;1177self->state = Gachapandora_StatePrize_DrillerCapsuleExitBounce;1178}1179}1180break;11811182case GACHAPANDORA_FIREDROPPER:1183if (self->velocity.y >= 0) {1184self->originPos.y = self->position.y;1185self->velocity.x = self->direction == FLIP_NONE ? -0x18000 : 0x18000;1186self->velocity.y = 0;11871188self->hitbox.left = -13;1189self->hitbox.top = -10;1190self->hitbox.right = 13;1191self->hitbox.bottom = 10;11921193self->health = 3;1194self->timer = 120;1195self->state = Gachapandora_StatePrize_FireDropperMove;1196}1197break;1198}1199}12001201void Gachapandora_StatePrize_Destroyed(void)1202{1203RSDK_THIS(Gachapandora);12041205Gachapandora_Explode(-8, 8, -8, 8);12061207if (self->invincibilityTimer) {1208self->invincibilityTimer--;1209}1210else {1211if (++Gachapandora->destroyedToys >= 8 && Gachapandora->awardAchievement)1212API_UnlockAchievement(&achievementList[ACH_MMZ]);12131214destroyEntity(self);1215}1216}12171218void Gachapandora_StatePrize_DrillerCapsuleExitBounce(void)1219{1220RSDK_THIS(Gachapandora);12211222Gachapandora_StatePrize_DrillerMove();12231224if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0x110000, true)) {1225self->velocity.y = 0;1226self->state = Gachapandora_StatePrize_DrillerMove;1227}1228else {1229self->velocity.y += 0x3800;1230}1231}12321233void Gachapandora_StatePrize_DrillerMove(void)1234{1235RSDK_THIS(Gachapandora);12361237RSDK.ProcessAnimation(&self->mainAnimator);12381239self->position.y += self->velocity.y;1240self->position.x += self->velocity.x;12411242if (self->position.x < (ScreenInfo->position.x - 64) << 16 || self->position.x > (ScreenInfo->position.x + ScreenInfo->size.x + 64) << 16) {1243self->direction ^= FLIP_X;1244self->velocity.x = -self->velocity.x;1245}12461247if (self->invincibilityTimer)1248self->invincibilityTimer--;1249else1250Gachapandora_CheckPlayerCollisions_Prize();1251}12521253void Gachapandora_StatePrize_FireDropperMove(void)1254{1255RSDK_THIS(Gachapandora);12561257RSDK.ProcessAnimation(&self->mainAnimator);1258RSDK.ProcessAnimation(&self->eggmanAnimator);12591260self->position.x += self->velocity.x;1261if (self->startY) {1262self->position.y += self->velocity.y;1263self->velocity.y -= 0x800;12641265if (self->position.y <= self->originPos.y) {1266self->position.y = self->originPos.y;1267self->velocity.y = 0;1268self->angle = 0;1269self->startY = 0;1270}1271}1272else {1273self->position.y = BadnikHelpers_Oscillate(self->originPos.y, 4, 9);1274}12751276if (self->position.x < (ScreenInfo->position.x + 16) << 16 || self->position.x > (ScreenInfo->position.x + ScreenInfo->size.x - 16) << 16) {1277self->startY = 1;1278self->direction ^= FLIP_X;1279self->velocity.y = 0x18000;1280self->velocity.x = -self->velocity.x;1281}12821283if (!--self->timer) {1284self->timer = 120;1285RSDK.PlaySfx(Gachapandora->sfxFireball, false, 255);1286RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 10, &self->eggmanAnimator, true, 0);12871288EntityGachapandora *fireball = CREATE_ENTITY(Gachapandora, INT_TO_VOID(GACHAPANDORA_FIREBALL), self->position.x, self->position.y);1289fireball->parent = self;1290fireball->timer = 12;1291}12921293if (self->invincibilityTimer)1294self->invincibilityTimer--;1295else1296Gachapandora_CheckPlayerCollisions_Prize();1297}12981299void Gachapandora_StatePrize_AmyWalk(void)1300{1301RSDK_THIS(Gachapandora);13021303RSDK.ProcessAnimation(&self->mainAnimator);13041305self->position.x += self->velocity.x;1306self->position.y += self->velocity.y;13071308if (self->invincibilityTimer)1309self->invincibilityTimer--;1310else1311Gachapandora_CheckPlayerCollisions_Prize();13121313EntityPlayer *player = Player_GetNearestPlayer();13141315if (self->position.x < (ScreenInfo->position.x + 8) << 16 || self->position.x > (ScreenInfo->size.x + ScreenInfo->position.x - 8) << 161316|| Player_CheckCollisionTouch(player, self, &Gachapandora->hitboxAmyRange)) {1317if (abs(player->position.x - self->position.x) > 0x80000)1318self->direction = player->position.x > self->position.x;13191320bool32 canJump = false;1321if (self->direction) {1322if (self->velocity.x < 0x20000)1323self->velocity.x += 0xC00;13241325canJump = self->velocity.x >= 0x10000;1326}1327else {1328if (self->velocity.x > -0x20000)1329self->velocity.x -= 0xC00;13301331canJump = self->velocity.x <= -0x10000;1332}13331334if (canJump && Player_CheckCollisionTouch(player, self, &Gachapandora->hitboxAmy)) {1335RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 5, &self->mainAnimator, true, 0);1336self->state = Gachapandora_StatePrize_AmyJump;1337self->onGround = false;1338self->velocity.y = -0x24000;1339}1340}1341else {1342if (self->velocity.x > 0) {1343self->velocity.x -= 0xC00;13441345if (self->velocity.x < 0) {1346self->velocity.x = 0;1347RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 8, &self->mainAnimator, true, 0);1348self->state = Gachapandora_StatePrize_AmyIdle;1349}1350}1351else {1352self->velocity.x += 0xC00;1353if (self->velocity.x >= 0) {1354self->velocity.x = 0;1355RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 8, &self->mainAnimator, true, 0);1356self->state = Gachapandora_StatePrize_AmyIdle;1357}1358}1359}1360}13611362void Gachapandora_StatePrize_AmyIdle(void)1363{1364RSDK_THIS(Gachapandora);13651366EntityPlayer *player = Player_GetNearestPlayer();13671368if (Player_CheckCollisionTouch(player, self, &Gachapandora->hitboxAmyRange)) {1369self->velocity.x = 0;1370self->direction = player->position.x > self->position.x;1371RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 9, &self->mainAnimator, true, 0);13721373self->state = Gachapandora_StatePrize_AmyWalk;1374Gachapandora_StatePrize_AmyWalk();1375}13761377if (self->state == Gachapandora_StatePrize_AmyIdle) {1378RSDK.ProcessAnimation(&self->mainAnimator);13791380if (self->invincibilityTimer)1381self->invincibilityTimer--;1382else1383Gachapandora_CheckPlayerCollisions_Prize();1384}1385}13861387void Gachapandora_StatePrize_AmyJump(void)1388{1389RSDK_THIS(Gachapandora);13901391RSDK.ProcessAnimation(&self->mainAnimator);13921393self->position.x += self->velocity.x;1394self->position.y += self->velocity.y;1395self->velocity.y += 0x2800;13961397if (!self->invincibilityTimer) {1398foreach_active(Player, player)1399{1400if (Player_CheckCollisionTouch(player, self, &Gachapandora->hitboxFireball)) {1401#if MANIA_USE_PLUS1402if (player->state == Player_State_MightyHammerDrop) {1403if (Player_CheckBossHit(player, self)) {1404if (self->health)1405self->health--;14061407if (self->health) {1408RSDK.PlaySfx(Gachapandora->sfxHit, false, 255);1409}1410else {1411EntityGachapandora *eggman = Gachapandora->eggman;1412RSDK.SetSpriteAnimation(Gachapandora->eggmanFrames, 1, &eggman->eggmanAnimator, true, 0);1413RSDK.PlaySfx(Gachapandora->sfxExplosion, false, 255);1414self->state = Gachapandora_StatePrize_Destroyed;1415}14161417self->invincibilityTimer = 30;1418}1419foreach_break;1420}1421else {1422#endif1423if (Player_CheckAttacking(player, self) && player->stateInput != Gachapandora_Player_StateInput_P1Grabbed1424&& player->stateInput != Gachapandora_Player_StateInput_P2PlayerGrabbed1425&& player->stateInput != Gachapandora_Player_StateInput_P2AIGrabbed) {1426bool32 shouldRebound = self->velocity.x >= 0;1427if (player->position.x > self->position.x) {1428if (self->velocity.x > 0) {1429self->velocity.x = -self->velocity.x;1430shouldRebound = true;1431}1432}14331434if (player->position.x >= self->position.x || shouldRebound) {1435self->velocity.y = -0x20000;1436if (self->position.x >= player->position.x) {1437self->direction = FLIP_NONE;1438player->velocity.x = -0x18000;1439}1440else {1441self->direction = FLIP_X;1442player->velocity.x = 0x18000;1443}1444player->groundVel = player->velocity.x;1445player->velocity.y = -player->velocity.y;1446player->state = Player_State_Air;1447if (player->animator.animationID == ANI_SPINDASH)1448player->animator.animationID = ANI_WALK;1449self->state = Gachapandora_StatePrize_AmyRebound;1450foreach_break;1451}1452}1453else {1454RSDK.PlaySfx(Gachapandora->sfxGiggle, false, 0xFF);1455RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 6, &self->mainAnimator, true, 0);14561457if (player->stateInput == Player_Input_P1)1458player->stateInput = Gachapandora_Player_StateInput_P1Grabbed;1459else if (player->stateInput == Player_Input_P2_Player)1460player->stateInput = Gachapandora_Player_StateInput_P2PlayerGrabbed;1461else if (player->stateInput == Player_Input_P2_AI)1462player->stateInput = Gachapandora_Player_StateInput_P2AIGrabbed;14631464self->timer = 90;1465self->parent = (EntityGachapandora *)player;1466self->state = Gachapandora_StatePrize_AmyGrabbed;1467foreach_break;1468}1469#if MANIA_USE_PLUS1470}1471#endif1472}1473}1474}1475else {1476self->invincibilityTimer--;1477}14781479if (self->state == Gachapandora_StatePrize_AmyJump) {1480if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0xC0000, true)) {1481self->velocity.y = 0;1482EntityPlayer *player = Player_GetNearestPlayer();1483if (self->position.x < (ScreenInfo->position.x + 8) << 16 || self->position.x > (ScreenInfo->size.x + ScreenInfo->position.x - 8) << 161484|| Player_CheckCollisionTouch(player, self, &Gachapandora->hitboxAmyRange)) {1485RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 9, &self->mainAnimator, true, 0);1486self->state = Gachapandora_StatePrize_AmyWalk;1487}1488else {1489RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 8, &self->mainAnimator, true, 0);1490self->state = Gachapandora_StatePrize_AmyIdle;1491}1492}1493}1494}14951496void Gachapandora_StatePrize_AmyRebound(void)1497{1498RSDK_THIS(Gachapandora);14991500RSDK.ProcessAnimation(&self->mainAnimator);15011502self->position.x += self->velocity.x;1503self->position.y += self->velocity.y;1504self->velocity.y += 0x2800;15051506if (self->invincibilityTimer)1507self->invincibilityTimer--;15081509if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0xC0000, true)) {1510self->velocity.y = 0;1511EntityPlayer *player = Player_GetNearestPlayer();15121513if (Player_CheckCollisionTouch(player, self, &Gachapandora->hitboxAmyRange)) {1514RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 9, &self->mainAnimator, true, 0);1515self->state = Gachapandora_StatePrize_AmyWalk;1516}1517else {1518RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 8, &self->mainAnimator, true, 0);1519self->state = Gachapandora_StatePrize_AmyIdle;1520}1521}15221523if (self->mainAnimator.animationID == 7) {1524if (!--self->timer) {1525RSDK.PlaySfx(Gachapandora->sfxExplosion, false, 255);1526CREATE_ENTITY(Explosion, INT_TO_VOID(EXPLOSION_BOSS), self->position.x, self->position.y)->drawGroup = Zone->objectDrawGroup[1] + 2;15271528self->invincibilityTimer = 30;1529self->state = Gachapandora_StatePrize_Destroyed;1530}1531}1532}15331534void Gachapandora_StatePrize_AmyGrabbed(void)1535{1536RSDK_THIS(Gachapandora);15371538EntityPlayer *parent = (EntityPlayer *)self->parent;15391540RSDK.ProcessAnimation(&self->mainAnimator);1541self->position.x = parent->position.x;1542self->position.y = parent->position.y;15431544self->direction = parent->direction ^ FLIP_X;1545self->position.x += self->direction ? -0x60000 : 0x60000;15461547if (self->prevShakeFlags) {1548if (self->shakeTimer) {1549self->shakeTimer--;15501551uint8 shakeFlags = 0;1552if (parent->left)1553shakeFlags = 1;1554if (parent->right)1555shakeFlags |= 2;15561557if (shakeFlags) {1558if (shakeFlags != 3 && shakeFlags != self->prevShakeFlags) {1559self->prevShakeFlags = shakeFlags;1560if (++self->shakeCount >= 6) {1561self->shakeCount = 0;1562self->parent = NULL;15631564if (parent->stateInput == Gachapandora_Player_StateInput_P1Grabbed)1565parent->stateInput = Player_Input_P1;1566else if (parent->stateInput == Gachapandora_Player_StateInput_P2PlayerGrabbed)1567parent->stateInput = Player_Input_P2_Player;1568else if (parent->stateInput == Gachapandora_Player_StateInput_P2AIGrabbed)1569parent->stateInput = Player_Input_P2_AI;15701571self->velocity.x = self->direction == FLIP_NONE ? 0x20000 : -0x20000;1572self->velocity.y = -0x20000;1573self->state = Gachapandora_StatePrize_AmyRebound;1574}1575}1576}1577}1578else {1579self->shakeCount = 0;1580self->prevShakeFlags = 0;1581}1582}1583else {1584if (parent->left)1585self->prevShakeFlags = 1;1586else if (parent->right)1587self->prevShakeFlags = 2;15881589self->shakeTimer = 64;1590}15911592if (self->state == Gachapandora_StatePrize_AmyGrabbed) {1593if (!--self->timer) {1594if (parent->stateInput == Gachapandora_Player_StateInput_P1Grabbed)1595parent->stateInput = Player_Input_P1;1596else if (parent->stateInput == Gachapandora_Player_StateInput_P2PlayerGrabbed)1597parent->stateInput = Player_Input_P2_Player;1598else if (parent->stateInput == Gachapandora_Player_StateInput_P2AIGrabbed)1599parent->stateInput = Player_Input_P2_AI;16001601Player_Hurt(parent, self);16021603RSDK.PlaySfx(Gachapandora->sfxExplosion, false, 255);1604CREATE_ENTITY(Explosion, INT_TO_VOID(EXPLOSION_BOSS), self->position.x, self->position.y)->drawGroup = Zone->objectDrawGroup[1] + 2;16051606self->invincibilityTimer = 30;1607self->state = Gachapandora_StatePrize_Destroyed;1608}1609else if (self->timer == 30) {1610RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 7, &self->mainAnimator, true, 0);1611}1612}1613}16141615void Gachapandora_Draw_Prize(void)1616{1617RSDK_THIS(Gachapandora);16181619if (self->invincibilityTimer & 1)1620RSDK.SetPaletteEntry(0, 128, 0xE0E0E0);16211622RSDK.DrawSprite(&self->mainAnimator, NULL, false);1623RSDK.DrawSprite(&self->eggmanAnimator, NULL, false);16241625RSDK.SetPaletteEntry(0, 128, 0x000000);1626}16271628void Gachapandora_StateFireball_Falling(void)1629{1630RSDK_THIS(Gachapandora);16311632RSDK.ProcessAnimation(&self->mainAnimator);16331634if (self->timer) {1635EntityGachapandora *parent = self->parent;1636if (parent->direction)1637self->position.x = parent->position.x + 0x20000;1638else1639self->position.x = parent->position.x - 0x20000;1640self->position.y += parent->velocity.y;1641self->timer--;1642}16431644foreach_active(Player, player)1645{1646if (Player_CheckCollisionTouch(player, self, &Gachapandora->hitboxFireball)) {1647Player_ElementHurt(player, self, SHIELD_FIRE);1648}1649}16501651self->position.y += 0x18000;1652if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0x20000, true)) {1653self->timer = 6;1654self->health = 4;1655RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 12, &self->mainAnimator, true, 0);1656self->state = Gachapandora_StateFireball_BurnGround;1657}1658}16591660void Gachapandora_StateFireball_BurnGround(void)1661{1662RSDK_THIS(Gachapandora);16631664RSDK.ProcessAnimation(&self->mainAnimator);16651666if (self->timer) {1667if (!--self->timer) {1668EntityGachapandora *fireball =1669CREATE_ENTITY(Gachapandora, INT_TO_VOID(GACHAPANDORA_FIREBALL), self->position.x + 0x40000, self->position.y);1670RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 12, &fireball->mainAnimator, true, 0);1671fireball->state = Gachapandora_StateFireball_BurnGround;1672if (self->health) {1673fireball->timer = 6;1674fireball->health = self->health - 1;1675}16761677fireball = CREATE_ENTITY(Gachapandora, INT_TO_VOID(GACHAPANDORA_FIREBALL), self->position.x - 0x40000, self->position.y);1678RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 12, &fireball->mainAnimator, true, 0);1679fireball->state = Gachapandora_StateFireball_BurnGround;1680if (self->health) {1681fireball->timer = 6;1682fireball->health = self->health - 1;1683}1684}1685}1686if (self->mainAnimator.frameID < 5) {1687foreach_active(Player, player)1688{1689if (Player_CheckCollisionTouch(player, self, &Gachapandora->hitboxFireball)) {1690Player_ElementHurt(player, self, SHIELD_FIRE);1691}1692}1693}16941695if (self->mainAnimator.frameID == self->mainAnimator.frameCount - 1)1696destroyEntity(self);1697}16981699void Gachapandora_Draw_Simple(void)1700{1701RSDK_THIS(Gachapandora);17021703RSDK.DrawSprite(&self->mainAnimator, NULL, false);1704}17051706void Gachapandora_StateDebris_Delay(void)1707{1708RSDK_THIS(Gachapandora);17091710if (!--self->timer) {1711self->state = Gachapandora_StateDebris_Falling;1712self->stateDraw = Gachapandora_Draw_BossDebris;1713}1714}17151716void Gachapandora_StateDebris_Falling(void)1717{1718RSDK_THIS(Gachapandora);17191720RSDK.ProcessAnimation(&self->mainAnimator);17211722self->position.x += self->velocity.x;1723self->position.y += self->velocity.y;1724self->velocity.y += 0x2800;17251726if (!RSDK.CheckOnScreen(self, NULL))1727destroyEntity(self);1728}17291730void Gachapandora_StateDebris_BossDebris(void)1731{1732RSDK_THIS(Gachapandora);17331734RSDK.ProcessAnimation(&self->mainAnimator);17351736self->position.x += self->velocity.x;1737self->position.y += self->velocity.y;1738self->velocity.y += 0x2800;17391740if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0x40000, true)) {1741self->velocity.y = -0x20000;1742self->velocity.x = RSDK.Rand(-2, 3) << 16;1743self->state = Gachapandora_StateDebris_Falling;1744self->stateDraw = Gachapandora_Draw_BossDebris;1745}1746}17471748void Gachapandora_Draw_BossDebris(void)1749{1750RSDK_THIS(Gachapandora);17511752if (Zone->timer & 1)1753RSDK.DrawSprite(&self->mainAnimator, NULL, false);1754}17551756void Gachapandora_StateSpark_Attached(void)1757{1758RSDK_THIS(Gachapandora);17591760RSDK.ProcessAnimation(&self->mainAnimator);17611762EntityGachapandora *parent = self->parent;1763if (parent) {1764self->position.x = parent->position.x + self->originPos.x;1765self->position.y = parent->position.y + self->originPos.y;1766}17671768if (self->mainAnimator.animationID >= 14 && (self->mainAnimator.animationID != 16 || self->mainAnimator.frameID < 2)) {1769foreach_active(Player, player)1770{1771if (Player_CheckCollisionTouch(player, self, &Gachapandora->hitboxSpark)) {1772Player_ElementHurt(player, self, SHIELD_LIGHTNING);1773}1774}1775}17761777if (self->mainAnimator.frameID == self->mainAnimator.frameCount - 1)1778destroyEntity(self);1779}17801781void Gachapandora_StateSpark_Detached(void)1782{1783RSDK_THIS(Gachapandora);17841785RSDK.ProcessAnimation(&self->mainAnimator);17861787self->position.x += self->velocity.x;1788self->position.y += self->velocity.y;17891790if (self->velocity.y < 0x20000)1791self->velocity.y += 0x1800;17921793foreach_active(Player, player)1794{1795if (Player_CheckCollisionTouch(player, self, &Gachapandora->hitboxSpark)) {1796Player_ElementHurt(player, self, SHIELD_LIGHTNING);1797}1798}17991800if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0x40000, true)) {1801RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 16, &self->mainAnimator, true, 0);1802self->velocity.x = 0;1803self->velocity.y = 0;1804self->state = Gachapandora_StateSpark_Attached;1805}1806}18071808void Gachapandora_StateEggman_Falling(void)1809{1810RSDK_THIS(Gachapandora);18111812RSDK.ProcessAnimation(&self->mainAnimator);18131814self->position.y += self->velocity.y;1815self->velocity.y += 0x1800;18161817if (self->position.y >= self->parent->position.y + 0xE0000) {1818RSDK.SetSpriteAnimation(Gachapandora->eggmanFrames, 5, &self->mainAnimator, true, 0);1819self->state = Gachapandora_StateEggman_Escape;1820}1821}18221823void Gachapandora_StateEggman_Escape(void)1824{1825RSDK_THIS(Gachapandora);18261827self->position.y += self->velocity.y;1828self->velocity.y += 0x1800;18291830if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0, 0x180000, true)) {1831self->velocity.x = 0;1832self->velocity.y = 0;1833self->state = Gachapandora_StateEggman_RunAway;1834}1835}18361837void Gachapandora_StateEggman_RunAway(void)1838{1839RSDK_THIS(Gachapandora);18401841RSDK.ProcessAnimation(&self->mainAnimator);18421843if (self->mainAnimator.frameID >= 4) {1844if (self->velocity.x < 0x60000)1845self->velocity.x += 0xC00;18461847self->position.x += self->velocity.x;1848}18491850if (!RSDK.CheckOnScreen(self, NULL))1851destroyEntity(self);1852}18531854#if GAME_INCLUDE_EDITOR1855void Gachapandora_EditorDraw(void)1856{1857RSDK_THIS(Gachapandora);18581859RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 0, &self->mainAnimator, false, 0);1860RSDK.SetSpriteAnimation(Gachapandora->eggmanFrames, 0, &self->eggmanAnimator, false, 0);1861RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 1, &self->handleAnimator, false, 7);1862RSDK.SetSpriteAnimation(Gachapandora->aniFrames, 2, &self->capsuleAnimator, false, 7);18631864Vector2 drawPos = self->position;1865self->mainAnimator.frameID = 4;1866RSDK.DrawSprite(&self->mainAnimator, NULL, false);18671868self->mainAnimator.frameID = 5;1869RSDK.DrawSprite(&self->mainAnimator, NULL, false);18701871self->mainAnimator.frameID = 2;1872RSDK.DrawSprite(&self->mainAnimator, NULL, false);18731874self->mainAnimator.frameID = 3;1875RSDK.DrawSprite(&self->mainAnimator, NULL, false);18761877self->mainAnimator.frameID = 0;1878RSDK.DrawSprite(&self->mainAnimator, NULL, false);18791880int32 storeDir = self->direction;1881self->direction = Gachapandora->eggmanDir;1882drawPos.x = self->position.x;1883drawPos.y = self->position.y - 0x100000;1884RSDK.DrawSprite(&self->eggmanAnimator, &drawPos, false);18851886self->direction = storeDir;18871888self->mainAnimator.frameID = 1;1889RSDK.DrawSprite(&self->mainAnimator, NULL, false);18901891self->direction = Gachapandora->handleDir;1892drawPos.y += 0x1A0000;1893RSDK.DrawSprite(&self->handleAnimator, &drawPos, false);18941895self->direction = storeDir;18961897if (showGizmos()) {1898RSDK_DRAWING_OVERLAY(true);18991900DrawHelpers_DrawArenaBounds(-WIDE_SCR_XCENTER, -SCREEN_YSIZE, WIDE_SCR_XCENTER, 128, 1 | 0 | 4 | 8, 0x00C0F0);19011902RSDK_DRAWING_OVERLAY(false);1903}1904}19051906void Gachapandora_EditorLoad(void)1907{1908Gachapandora->aniFrames = RSDK.LoadSpriteAnimation("MMZ/Gachapandora.bin", SCOPE_STAGE);1909Gachapandora->eggmanFrames = RSDK.LoadSpriteAnimation("Eggman/EggmanMMZ2.bin", SCOPE_STAGE);1910}1911#endif19121913void Gachapandora_Serialize(void) {}191419151916