Path: blob/master/SonicMania/Objects/Pinball/PBL_Crane.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: PBL_Crane Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89#if MANIA_USE_PLUS10ObjectPBL_Crane *PBL_Crane;1112void PBL_Crane_Update(void)13{14RSDK_THIS(PBL_Crane);1516StateMachine_Run(self->state);17}1819void PBL_Crane_LateUpdate(void) {}2021void PBL_Crane_StaticUpdate(void) {}2223void PBL_Crane_Draw(void)24{25RSDK_THIS(PBL_Crane);2627if (self->stateDraw) {28StateMachine_Run(self->stateDraw);29}30else {31RSDK.DrawSprite(&self->displayAnimator, NULL, true);32}33}3435void PBL_Crane_Create(void *data)36{37RSDK_THIS(PBL_Crane);3839if (!SceneInfo->inEditor) {40self->drawGroup = 9;41self->active = ACTIVE_NORMAL;42self->type = VOID_TO_INT(data);4344switch (self->type) {45case PBL_CRANE_MANAGER:46self->position.x = ScreenInfo->center.x << 16;47self->position.y = 0;4849self->alpha = 0xFF;50self->scale.x = 0x600;51self->scale.y = 0x200;5253RSDK.SetSpriteAnimation(PBL_Crane->aniFrames, 2, &self->displayAnimator, true, 0);54RSDK.SetSpriteAnimation(PBL_Crane->aniFrames, 0, &self->machineAnimator, true, 1);5556self->stateDraw = PBL_Crane_Draw_CraneMachine;57break;5859case PBL_CRANE_CRANE:60self->visible = true;6162RSDK.SetSpriteAnimation(PBL_Crane->aniFrames, 3, &self->bgAnimator, true, 0);63RSDK.SetSpriteAnimation(PBL_Crane->aniFrames, 4, &self->craneBackAnimator, true, 0);64RSDK.SetSpriteAnimation(PBL_Crane->aniFrames, 5, &self->craneFrontAnimator, true, 0);6566self->scale.x = 0x200;67self->scale.y = 0x200;6869self->state = PBL_Crane_StateCrane_Lower;70self->stateDraw = PBL_Crane_Draw_Crane;71break;7273case PBL_CRANE_PRIZEDISPLAY:74self->visible = true;7576RSDK.SetSpriteAnimation(PBL_Crane->aniFrames, 6, &self->displayAnimator, true, 0);77RSDK.SetSpriteAnimation(PBL_Crane->aniFrames, 2, &self->bgAnimator, true, 4);7879self->state = PBL_Crane_StatePrizeDisplay_Move;80self->stateDraw = PBL_Crane_Draw_PrizeDisplay;81break;8283case PBL_CRANE_PRIZE:84self->drawGroup = 12;85self->visible = true;86self->scale.x = 0x180;87self->scale.y = 0x180;88self->drawFX = FX_SCALE;8990self->state = PBL_Crane_StatePrize_Bounce;91break;9293default: break;94}95}96}9798void PBL_Crane_StageLoad(void)99{100PBL_Crane->aniFrames = RSDK.LoadSpriteAnimation("Pinball/Backglass.bin", SCOPE_STAGE);101102PBL_Crane->sfxBackGlass = RSDK.GetSfx("Pinball/Backglass.wav");103PBL_Crane->sfxCraneMove = RSDK.GetSfx("Pinball/CraneMove.wav");104PBL_Crane->sfxCraneDrop = RSDK.GetSfx("Pinball/CraneDrop.wav");105PBL_Crane->sfxCraneGrab = RSDK.GetSfx("Pinball/CraneGrab.wav");106PBL_Crane->sfxCraneRise = RSDK.GetSfx("Pinball/CraneRise.wav");107PBL_Crane->sfxPrizeGood = RSDK.GetSfx("Pinball/PrizeGood.wav");108PBL_Crane->sfxPrizeBad = RSDK.GetSfx("Pinball/PrizeBad.wav");109}110111void PBL_Crane_HandlePrizes(void)112{113RSDK_THIS(PBL_Crane);114115switch (self->displayAnimator.frameID) {116case PBL_CRANE_PRIZE_SONIC:117case PBL_CRANE_PRIZE_TAILS:118case PBL_CRANE_PRIZE_KNUCKLES:119case PBL_CRANE_PRIZE_MIGHTY:120case PBL_CRANE_PRIZE_RAY: {121int32 playerID = 1 << self->displayAnimator.frameID;122globals->characterFlags |= playerID;123PBL_Crane->prizeID = PBL_CRANE_PRIZEID_BUDDY;124125if (!GET_CHARACTER_ID(1))126globals->playerID |= playerID;127else if (!GET_CHARACTER_ID(2))128globals->playerID |= playerID << 8;129else if (!GET_STOCK_ID(1))130globals->stock |= playerID;131else if (!GET_STOCK_ID(2))132globals->stock |= playerID << 8;133else if (!GET_STOCK_ID(3))134globals->stock |= playerID << 16;135136break;137}138139case PBL_CRANE_PRIZE_EGGMAN:140PBL_Setup->rings = 0;141PBL_Setup->score = 0;142PBL_Crane->prizeID = PBL_CRANE_PRIZEID_BAD;143break;144145case PBL_CRANE_PRIZE_RINGS:146globals->restartRings += PBL_Setup->rings;147globals->restartRings = CLAMP(globals->restartRings, 0, 999);148149if (globals->gameMode == MODE_MANIA && globals->restartRings >= globals->restart1UP) {150PBL_Setup_GiveLife();151globals->restart1UP += 100;152if (globals->restart1UP > 300)153globals->restart1UP = 1000;154}155156PBL_Setup->rings = 0;157PBL_Crane->prizeID = PBL_CRANE_PRIZEID_RINGS;158break;159160case PBL_CRANE_PRIZE_SHIELD_BLUE:161case PBL_CRANE_PRIZE_SHIELD_BUBBLE:162case PBL_CRANE_PRIZE_SHIELD_FIRE:163case PBL_CRANE_PRIZE_SHIELD_ELECTRIC:164globals->restartPowerups &= ~0x3F;165globals->restartPowerups |= self->displayAnimator.frameID - PBL_CRANE_PRIZE_SHIELD_BLUE + SHIELD_BLUE; // Converts the frame ID to a shield ID166167PBL_Crane->prizeID = PBL_CRANE_PRIZEID_ITEM;168break;169170case PBL_CRANE_PRIZE_TABLE_RESTORE: {171foreach_all(PBL_Bumper, bumper)172{173if (!bumper->state) {174bumper->velocity.y = 32;175bumper->state = PBL_TargetBumper_State_Rise;176bumper->active = ACTIVE_NORMAL;177}178}179180foreach_all(PBL_Ring, ring)181{182if (ring->active == ACTIVE_NEVER) {183ring->active = ACTIVE_BOUNDS;184RSDK.SetSpriteAnimation(PBL_Ring->aniFrames, 1, &ring->animator, true, 0);185ring->state = PBL_Ring_State_Ring;186}187}188189PBL_Crane->prizeID = PBL_CRANE_PRIZEID_TBLRESTORE;190break;191}192193case PBL_CRANE_PRIZE_1UP:194if (SaveGame_GetSaveRAM()->lives < 99)195SaveGame_GetSaveRAM()->lives++;196197if (globals->restartLives[0] < 99)198globals->restartLives[0]++;199200PBL_Crane->prizeID = PBL_CRANE_PRIZEID_1UP;201break;202203default: break;204}205}206207void PBL_Crane_Draw_CraneMachine(void)208{209RSDK_THIS(PBL_Crane);210211self->position.x = ScreenInfo->center.x << 16;212if (SceneInfo->currentDrawGroup == self->drawGroup) {213self->displayAnimator.frameID = 1;214self->inkEffect = INK_NONE;215RSDK.DrawSprite(&self->displayAnimator, NULL, true);216RSDK.DrawSprite(&self->machineAnimator, NULL, true);217218RSDK.AddDrawListRef(11, SceneInfo->entitySlot);219220RSDK.SetClipBounds(0, ScreenInfo->center.x - 96, 0, ScreenInfo->center.x + 96, (self->position.y >> 16) + 64);221}222else {223RSDK.SetClipBounds(0, 0, 0, ScreenInfo->size.x, ScreenInfo->size.y);224225self->displayAnimator.frameID = 0;226RSDK.DrawSprite(&self->displayAnimator, NULL, true);227228self->displayAnimator.frameID = 2;229self->drawFX = FX_SCALE;230self->inkEffect = INK_ADD;231RSDK.DrawSprite(&self->displayAnimator, NULL, true);232233self->displayAnimator.frameID = 3;234RSDK.DrawSprite(&self->displayAnimator, NULL, true);235236self->drawFX = FX_NONE;237}238}239240void PBL_Crane_Draw_PrizeDisplay(void)241{242RSDK_THIS(PBL_Crane);243244RSDK.DrawSprite(&self->bgAnimator, NULL, true);245RSDK.DrawSprite(&self->displayAnimator, NULL, true);246}247248void PBL_Crane_Draw_Crane(void)249{250RSDK_THIS(PBL_Crane);251252Vector2 drawPos;253254drawPos.x = self->position.x;255drawPos.y = self->position.y + 0x1A0000;256RSDK.DrawSprite(&self->craneBackAnimator, NULL, true);257258self->drawFX = FX_SCALE;259RSDK.DrawSprite(&self->displayAnimator, &drawPos, true);260261self->drawFX = FX_NONE;262RSDK.DrawSprite(&self->bgAnimator, NULL, true);263RSDK.DrawSprite(&self->craneFrontAnimator, NULL, true);264}265266void PBL_Crane_State_CreatePrizes(void)267{268RSDK_THIS(PBL_Crane);269270EntityPBL_Camera *camera = RSDK_GET_ENTITY(SLOT_PBL_CAMERA, PBL_Camera);271272self->position.y = 0;273camera->worldY = 0x1000000;274self->cameraTarget = camera->target;275camera->target = NULL;276self->visible = true;277278int32 spawnX = self->position.x - 0x6C0000;279int32 spawnY = 0x600000 + self->position.y;280self->state = PBL_Crane_State_DisplayPrizes;281282for (int32 i = 0; i < 6; ++i) {283EntityPBL_Crane *prize = CREATE_ENTITY(PBL_Crane, INT_TO_VOID(PBL_CRANE_PRIZEDISPLAY), spawnX, spawnY);284if (globals->gameMode == MODE_ENCORE) {285if (!((1 << i) & globals->characterFlags) || i == PBL_CRANE_PRIZE_EGGMAN) {286prize->displayAnimator.frameID = i;287}288else {289prize->displayAnimator.frameID = RSDK.Rand(PBL_CRANE_PRIZE_RINGS, PBL_CRANE_PRIZE_TABLE_RESTORE + 1);290}291}292else {293if (i == 5) {294prize->displayAnimator.frameID = PBL_CRANE_PRIZE_EGGMAN;295}296else {297prize->displayAnimator.frameID = RSDK.Rand(PBL_CRANE_PRIZE_RINGS, PBL_CRANE_PRIZE_1UP + 1);298}299}300301spawnX += 0x280000;302prize->parent = self;303}304305CREATE_ENTITY(PBL_Crane, INT_TO_VOID(PBL_CRANE_CRANE), self->position.x, -0x180000)->parent = self;306307if (PBL_Setup->sectorID < PBL_Setup->sectorCount)308PBL_Setup->sectorID++;309310PBL_Crane->prizeID = PBL_CRANE_PRIZEID_NOTHING;311}312313void PBL_Crane_State_DisplayPrizes(void)314{315RSDK_THIS(PBL_Crane);316317if (self->position.y >= 0x300000) {318self->timer = 0;319self->state = StateMachine_None;320}321else {322EntityPBL_Camera *camera = RSDK_GET_ENTITY(SLOT_PBL_CAMERA, PBL_Camera);323324self->position.y += 0x10000;325camera->worldY += 0x28000;326camera->position.y -= 0x14000;327328if (!self->timer)329--camera->rotationY;330331self->timer = (self->timer + 1) & 3;332}333}334335void PBL_Crane_StatePrizeDisplay_Move(void)336{337RSDK_THIS(PBL_Crane);338339EntityPBL_Crane *parent = self->parent;340341self->position.x -= 0x10000;342int32 dist = abs(self->position.x - parent->position.x);343self->position.y = (dist >> 13) * (dist >> 13) + (parent->position.y + 0x300000);344345if (self->position.x < parent->position.x - 0x980000) {346self->position.x += 0x1100000;347}348}349350void PBL_Crane_StateCrane_Lower(void)351{352RSDK_THIS(PBL_Crane);353354EntityPBL_Crane *parent = self->parent;355356if (!parent->state) {357if (self->position.y >= 0x100000)358self->state = PBL_Crane_StateCrane_Move;359else360self->position.y += 0x8000;361}362}363364void PBL_Crane_StateCrane_Move(void)365{366RSDK_THIS(PBL_Crane);367368self->velocity.x = (-((ControllerInfo[CONT_P1].keyLeft.down || AnalogStickInfoL[CONT_P1].keyLeft.down) != 0) & 0xFFFF0000) + 0x8000;369370if (++self->timer == 30) {371self->timer = 0;372self->state = PBL_Crane_StateCrane_Controlled;373RSDK.PlaySfx(PBL_Crane->sfxCraneMove, false, 255);374}375}376377void PBL_Crane_StateCrane_Controlled(void)378{379RSDK_THIS(PBL_Crane);380381EntityPBL_Crane *parent = self->parent;382383if (AnalogStickInfoL[CONT_P1].keyLeft.press || ControllerInfo[CONT_P1].keyLeft.press) {384++self->timer;385self->velocity.x = -0x18000;386RSDK.PlaySfx(PBL_Crane->sfxCraneMove, false, 0xFF);387}388else if (AnalogStickInfoL[CONT_P1].keyRight.press || ControllerInfo[CONT_P1].keyRight.press) {389++self->timer;390self->velocity.x = 0x18000;391RSDK.PlaySfx(PBL_Crane->sfxCraneMove, false, 0xFF);392}393else if (AnalogStickInfoL[CONT_P1].keyDown.press || ControllerInfo[CONT_P1].keyDown.press) {394self->timer = 4;395}396397self->position.x += self->velocity.x;398399if (self->velocity.x <= 0) {400if (self->position.x <= parent->position.x - 0x600000)401self->velocity.x = -self->velocity.x;402}403else {404if (self->position.x >= parent->position.x + 0x600000)405self->velocity.x = -self->velocity.x;406}407408if (self->timer == 4) {409self->timer = 0;410self->state = PBL_Crane_StateCrane_Drop;411RSDK.PlaySfx(PBL_Crane->sfxCraneDrop, false, 255);412}413}414415void PBL_Crane_StateCrane_Drop(void)416{417RSDK_THIS(PBL_Crane);418419EntityPBL_Crane *parent = self->parent;420421self->position.y += 0x10000;422if (self->position.y >= parent->position.y + 0x180000) {423foreach_active(PBL_Crane, crane)424{425if (crane->type == PBL_CRANE_PRIZEDISPLAY) {426if (abs(crane->position.x - self->position.x) < 0x100000) {427memcpy(&self->displayAnimator, &crane->displayAnimator, sizeof(Animator));428RSDK.SetSpriteAnimation(-1, 0, &crane->displayAnimator, false, 0);429}430}431}432433self->state = PBL_Crane_StateCrane_Grab;434RSDK.PlaySfx(PBL_Crane->sfxCraneGrab, false, 255);435}436}437438void PBL_Crane_StateCrane_Grab(void)439{440RSDK_THIS(PBL_Crane);441442++self->timer;443444if (self->scale.x > 0x180) {445self->scale.x -= 0x10;446self->scale.y -= 0x10;447}448449if (self->timer > 8) {450self->craneBackAnimator.frameID = (self->timer - 8) >> 1;451self->craneFrontAnimator.frameID = (self->timer - 8) >> 1;452}453454if (self->craneBackAnimator.frameID == self->craneBackAnimator.frameCount - 1) {455self->timer = 0;456self->state = PBL_Crane_StateCrane_Rise;457RSDK.PlaySfx(PBL_Crane->sfxCraneRise, false, 255);458}459}460461void PBL_Crane_StateCrane_Rise(void)462{463RSDK_THIS(PBL_Crane);464465EntityPBL_Crane *parent = self->parent;466467self->position.y -= 0x10000;468469if (self->scale.x > 0x180) {470self->scale.x -= 0x10;471self->scale.y -= 0x10;472}473474if (self->position.y <= 0x100000) {475if (self->displayAnimator.animationID == 6) {476EntityPBL_Crane *crane = CREATE_ENTITY(PBL_Crane, INT_TO_VOID(PBL_CRANE_PRIZE), self->position.x, self->position.y + 0x1A0000);477crane->displayAnimator = self->displayAnimator;478crane->parent = self->parent;479RSDK.SetSpriteAnimation(-1, 0, &self->displayAnimator, false, 0);480481crane->velocity.x = self->position.x > parent->position.x ? 0x20000 : -0x20000;482crane->velocity.y = -0x20000;483484if (crane->displayAnimator.frameID != 5) {485RSDK.PlaySfx(PBL_Crane->sfxPrizeGood, false, 255);486self->state = StateMachine_None;487}488else {489RSDK.PlaySfx(PBL_Crane->sfxPrizeBad, false, 255);490self->state = StateMachine_None;491}492}493else {494parent->state = PBL_Crane_StatePrize_PrizeGet;495RSDK.PlaySfx(PBL_Crane->sfxPrizeBad, false, 255);496self->state = StateMachine_None;497}498}499}500501void PBL_Crane_StatePrize_Bounce(void)502{503RSDK_THIS(PBL_Crane);504505if (self->scale.x >= 0x200) {506self->drawFX = FX_NONE;507}508else {509self->scale.x += 0x10;510self->scale.y += 0x10;511}512513self->velocity.y += 0x2800;514self->position.x += self->velocity.x;515self->position.y += self->velocity.y;516517if (self->position.y > 0x500000) {518self->velocity.y = -(self->velocity.y >> 1);519520if (++self->timer == 2) {521self->timer = 0;522self->state = PBL_Crane_StatePrize_Flash;523}524}525}526527void PBL_Crane_StatePrize_Flash(void)528{529RSDK_THIS(PBL_Crane);530531self->visible = (++self->timer >> 2) & 1;532533if (self->timer == 60) {534PBL_Crane_HandlePrizes();535self->parent->state = PBL_Crane_StatePrize_PrizeGet;536destroyEntity(self);537}538}539540void PBL_Crane_StatePrize_PrizeGet(void)541{542RSDK_THIS(PBL_Crane);543544if (++self->timer == 24) {545foreach_active(PBL_HUD, hud)546{547hud->state = PBL_HUD_State_HideCrane;548hud->visible = true;549}550}551552EntityPBL_Camera *camera = RSDK_GET_ENTITY(SLOT_PBL_CAMERA, PBL_Camera);553if (self->position.y <= 0) {554foreach_active(PBL_Crane, crane)555{556if (crane != self)557destroyEntity(crane);558}559560self->timer = 0;561self->state = StateMachine_None;562563foreach_all(PBL_Sector, sector)564{565if (sector->craneID == PBL_Setup->sectorID)566sector->active = ACTIVE_NORMAL;567}568569LogHelpers_PrintInt32("Sector", PBL_Setup->sectorID);570camera->target = self->cameraTarget;571camera->rotationY = -96;572573foreach_active(PBL_HUD, hud)574{575switch (PBL_Crane->prizeID) {576case PBL_CRANE_PRIZEID_NOTHING: PBL_HUD_DisplayMessage(hud, "TOO BAD!", PBL_HUD_MSG_FLASH); continue;577case PBL_CRANE_PRIZEID_BAD: PBL_HUD_DisplayMessage(hud, "OH NO!", PBL_HUD_MSG_FLASH); continue;578case PBL_CRANE_PRIZEID_BUDDY: PBL_HUD_DisplayMessage(hud, "NICE SAVE!", PBL_HUD_MSG_SCROLL_RIGHT); continue;579case PBL_CRANE_PRIZEID_RINGS: PBL_HUD_DisplayMessage(hud, "!RINGS DEPOSITED!", PBL_HUD_MSG_SCROLL_LEFT); break;580case PBL_CRANE_PRIZEID_ITEM: PBL_HUD_DisplayMessage(hud, "!ITEM COLLECTED!", PBL_HUD_MSG_SCROLL_LEFT); break;581case PBL_CRANE_PRIZEID_TBLRESTORE: PBL_HUD_DisplayMessage(hud, "!TABLE RESTORED!", PBL_HUD_MSG_SCROLL_LEFT); break;582case PBL_CRANE_PRIZEID_1UP: PBL_HUD_DisplayMessage(hud, "!EXTRA LIFE!", PBL_HUD_MSG_SCROLL_LEFT); break;583default: break;584}585}586}587else {588self->position.y = self->position.y - 0x10000;589camera->worldY -= 0x28000;590camera->position.y += 0x14000;591592if ((self->timer & 3) == 1)593++camera->rotationY;594}595}596597#if GAME_INCLUDE_EDITOR598void PBL_Crane_EditorDraw(void)599{600RSDK_THIS(PBL_Crane);601602RSDK.SetSpriteAnimation(PBL_Crane->aniFrames, 4, &self->craneBackAnimator, true, 0);603RSDK.SetSpriteAnimation(PBL_Crane->aniFrames, 5, &self->craneFrontAnimator, true, 0);604605RSDK.DrawSprite(&self->craneBackAnimator, NULL, false);606RSDK.DrawSprite(&self->craneFrontAnimator, NULL, false);607}608609void PBL_Crane_EditorLoad(void) { PBL_Crane->aniFrames = RSDK.LoadSpriteAnimation("Pinball/Backglass.bin", SCOPE_STAGE); }610#endif611612void PBL_Crane_Serialize(void) {}613#endif614615616