Path: blob/master/SonicMania/Objects/UFO/UFO_Setup.c
338 views
// ---------------------------------------------------------------------1// RSDK Project: Sonic Mania2// Object Description: UFO_Setup Object3// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges4// Decompiled by: Rubberduckycooly & RMGRich5// ---------------------------------------------------------------------67#include "Game.h"89ObjectUFO_Setup *UFO_Setup;1011void UFO_Setup_Update(void)12{13RSDK_THIS(UFO_Setup);1415StateMachine_Run(self->state);1617#if MANIA_USE_PLUS18if (self->state != UFO_Setup_State_FinishFadeout && globals->gameMode < MODE_TIMEATTACK)19++SaveGame_GetSaveRAM()->zoneTimes[29];20#endif21}2223void UFO_Setup_LateUpdate(void) {}2425void UFO_Setup_StaticUpdate(void)26{27++UFO_Setup->timer;28UFO_Setup->timer &= 0x7FFF;2930if (!(UFO_Setup->timer & 1)) {31++UFO_Setup->ringFrame;32UFO_Setup->ringFrame &= 0xF;33}3435StateMachine_Run(UFO_Setup->deformCB);36}3738void UFO_Setup_Draw(void)39{40RSDK_THIS(UFO_Setup);4142RSDK.FillScreen(self->fadeColor, self->timer, self->timer - 128, self->timer - 256);43}4445void UFO_Setup_Create(void *data)46{47RSDK_THIS(UFO_Setup);4849self->active = ACTIVE_NORMAL;50self->visible = true;51self->drawGroup = 15;52self->fadeColor = 0xF0F0F0;53self->timer = 512;54self->state = UFO_Setup_State_ShowStartMessage;55}5657void UFO_Setup_StageLoad(void)58{59RSDK.ResetEntitySlot(SLOT_UFO_SETUP, UFO_Setup->classID, NULL);6061UFO_Setup->playFieldLayer = RSDK.GetTileLayerID("Playfield");6263UFO_Setup->machPoints = 0;64UFO_Setup->machLevel = 0;65UFO_Setup->rings = 30;66UFO_Setup->timedOut = 0;67UFO_Setup->resetToTitle = false;6869RSDK.GetTileLayer(UFO_Setup->playFieldLayer)->scanlineCallback = UFO_Setup_Scanline_Playfield;7071RSDK.SetDrawGroupProperties(1, false, UFO_Setup_DrawHook_PrepareDrawingFX);72RSDK.SetDrawGroupProperties(3, false, UFO_Setup_DrawHook_PrepareDrawingFX);73RSDK.SetDrawGroupProperties(4, true, StateMachine_None);7475UFO_Setup->sfxBlueSphere = RSDK.GetSfx("Special/BlueSphere2.wav");76UFO_Setup->sfxSSExit = RSDK.GetSfx("Special/SSExit.wav");77UFO_Setup->sfxEmerald = RSDK.GetSfx("Special/Emerald.wav");78UFO_Setup->sfxEvent = RSDK.GetSfx("Special/Event.wav");7980RSDK.CopyPalette(0, 0, 7, 0, 128);81RSDK.CopyPalette(1, 96, 0, 96, 32);8283RSDK.SetLimitedFade(1, 0, 7, 36, 160, 255);84RSDK.SetLimitedFade(2, 0, 7, 72, 160, 255);85RSDK.SetLimitedFade(3, 0, 7, 108, 160, 255);86RSDK.SetLimitedFade(4, 0, 7, 144, 160, 255);87RSDK.SetLimitedFade(5, 0, 7, 180, 160, 255);88RSDK.SetLimitedFade(6, 0, 7, 216, 160, 255);8990uint16 floor3DLayer = RSDK.GetTileLayerID("3D Floor");91if (floor3DLayer != (uint16)-1) {92TileLayer *floor3D = RSDK.GetTileLayer(floor3DLayer);93if (floor3D) {94floor3D->drawGroup[0] = 0;95floor3D->scanlineCallback = UFO_Setup_Scanline_3DFloor;96}97}9899uint16 roof3DLayer = RSDK.GetTileLayerID("3D Roof");100if (roof3DLayer != (uint16)-1) {101TileLayer *roof3D = RSDK.GetTileLayer(roof3DLayer);102if (roof3D) {103roof3D->drawGroup[0] = 0;104roof3D->scanlineCallback = UFO_Setup_Scanline_3DRoof;105}106}107108if (RSDK.CheckSceneFolder("UFO3")) {109UFO_Setup->deformCB = UFO_Setup_Deform_UFO3;110111int32 *deformData = RSDK.GetTileLayer(0)->deformationData;112for (int32 i = 0; i < 0x200; i += 0x10) {113int32 deform = RSDK.Rand(0, 4);114115int32 deformPos = CLAMP(i, 0, 0x200);116117int32 angle = 0;118for (int32 d = 0; d < 0x10; ++d) {119deformData[deformPos + d] = deform * RSDK.Sin1024(angle) >> 10;120angle += 0x40;121}122}123memcpy(&deformData[0x200], deformData, (0x200 * sizeof(int32)));124125deformData = RSDK.GetTileLayer(1)->deformationData;126for (int32 i = 0; i < 0x200; i += 0x10) {127int32 deform = RSDK.Rand(0, 4);128129int32 deformPos = CLAMP(i, 0, 0x200);130131int32 angle = 0;132for (int32 d = 0; d < 0x10; ++d) {133deformData[deformPos + d] = deform * RSDK.Sin1024(angle) >> 10;134angle += 0x40;135}136}137memcpy(&deformData[0x200], deformData, (0x200 * sizeof(int32)));138}139else if (RSDK.CheckSceneFolder("UFO4")) {140UFO_Setup->deformCB = UFO_Setup_Deform_UFO4;141142TileLayer *background = RSDK.GetTileLayer(0);143144int32 angle = 0;145for (int32 i = 0; i < 0x200; ++i) {146background->deformationData[i] = (8 * RSDK.Sin1024(angle)) >> 10;147angle += 8;148}149150memcpy(&background->deformationData[0x200], &background->deformationData[0], 0x200 * sizeof(int32));151}152else if (RSDK.CheckSceneFolder("UFO5")) {153UFO_Setup->deformCB = UFO_Setup_Deform_UFO5;154TileLayer *background = RSDK.GetTileLayer(0);155156int32 angle = 0;157for (int32 i = 0; i < 0x200; ++i) {158background->deformationData[i] = 8 * RSDK.Sin1024(angle) >> 10;159angle += 16;160}161162memcpy(&background->deformationData[0x200], &background->deformationData[0], 0x200 * sizeof(int32));163}164165int32 listPos = SceneInfo->listPos;166RSDK.SetScene("Special Stage", "");167UFO_Setup->specialStageID = listPos - SceneInfo->listPos;168169#if MANIA_USE_PLUS170if (UFO_Setup->specialStageID >= 7) {171UFO_Setup->specialStageID = UFO_Setup->specialStageID % 7;172UFO_Setup->encoreStage = true;173}174#endif175176SceneInfo->listPos = listPos;177}178179void UFO_Setup_DrawHook_PrepareDrawingFX(void)180{181RSDK.SetClipBounds(0, 0, 0, ScreenInfo->size.x, ScreenInfo->size.y);182RSDK.SetActivePalette(0, 0, ScreenInfo->size.y);183}184185void UFO_Setup_Scanline_Playfield(ScanlineInfo *scanlines)186{187EntityUFO_Camera *camera = RSDK_GET_ENTITY(SLOT_UFO_CAMERA, UFO_Camera);188189RSDK.SetClipBounds(0, 0, camera->clipY, ScreenInfo->size.x, ScreenInfo->size.y);190191int32 sin = RSDK.Sin1024(camera->angle) >> 2;192int32 cos = RSDK.Cos1024(camera->angle) >> 2;193int32 sinX = RSDK.Sin1024(-camera->angleX) >> 2;194int32 cosX = RSDK.Cos1024(-camera->angleX) >> 2;195196int32 cosVal = -SCREEN_YCENTER * cosX;197198for (int32 i = -SCREEN_YCENTER; i < SCREEN_YCENTER; ++i) {199int32 div = sinX + (cosVal >> 8);200if (!div)201div = 1;202203int32 h = camera->height / div;204scanlines->deform.x = (-cos * h) >> 8;205scanlines->deform.y = (sin * h) >> 8;206207int32 pos = ((cosX * h) >> 8) - (sinX * ((i * h) >> 8) >> 8);208RSDK.SetActivePalette(CLAMP(abs(pos) >> 15, 0, 7), i + SCREEN_YCENTER, i + SCREEN_YCENTER + 1);209210scanlines->position.x = (sin * pos - ScreenInfo->center.x * scanlines->deform.x) + camera->position.x;211scanlines->position.y = (cos * pos - ScreenInfo->center.x * scanlines->deform.y) + camera->position.y;212213scanlines++;214cosVal += cosX;215}216}217218void UFO_Setup_Scanline_3DFloor(ScanlineInfo *scanlines)219{220EntityUFO_Camera *camera = RSDK_GET_ENTITY(SLOT_UFO_CAMERA, UFO_Camera);221222RSDK.SetClipBounds(0, 0, camera->clipY + 24, ScreenInfo->size.x, ScreenInfo->size.y);223224int32 sin = RSDK.Sin1024(camera->angle) >> 2;225int32 cos = RSDK.Cos1024(camera->angle) >> 2;226int32 sinX = RSDK.Sin1024(-camera->angleX) >> 2;227int32 cosX = RSDK.Cos1024(-camera->angleX) >> 2;228229int32 cosVal = -SCREEN_YCENTER * cosX;230231for (int32 i = -SCREEN_YCENTER; i < SCREEN_YCENTER; ++i) {232int32 div = sinX + (cosVal >> 8);233if (!div)234div = 1;235236int32 h = (camera->height + 0x1000000) / div;237scanlines->deform.x = -(cos * h) >> 8;238scanlines->deform.y = (sin * h) >> 8;239240int32 pos = ((cosX * h) >> 8) - (sinX * ((i * h) >> 8) >> 8);241RSDK.SetActivePalette(CLAMP((abs(pos) >> 15) - 8, 0, 7), i + SCREEN_YCENTER, i + SCREEN_YCENTER + 1);242243scanlines->position.x = (sin * pos - ScreenInfo->center.x * scanlines->deform.x) + camera->position.x;244scanlines->position.y = (cos * pos - ScreenInfo->center.x * scanlines->deform.y) + camera->position.y;245246scanlines++;247cosVal += cosX;248}249}250void UFO_Setup_Scanline_3DRoof(ScanlineInfo *scanlines)251{252EntityUFO_Camera *camera = RSDK_GET_ENTITY(SLOT_UFO_CAMERA, UFO_Camera);253254RSDK.SetClipBounds(0, 0, 0, ScreenInfo->size.x, camera->clipY - 48);255256int32 sin = RSDK.Sin1024(camera->angle) >> 2;257int32 cos = RSDK.Cos1024(camera->angle) >> 2;258int32 sinX = RSDK.Sin1024(-camera->angleX) >> 2;259int32 cosX = RSDK.Cos1024(-camera->angleX) >> 2;260261int32 cosVal = -SCREEN_YCENTER * cosX;262int32 height = (camera->height >> 2) - 0x600000;263264for (int32 i = -SCREEN_YCENTER; i < SCREEN_YCENTER; ++i) {265int32 div = sinX + (cosVal >> 8);266if (!div)267div = 1;268269int32 h = height / div;270scanlines->deform.x = -(cos * h) >> 8;271scanlines->deform.y = (sin * h) >> 8;272273int32 pos = ((cosX * h) >> 8) - (sinX * ((i * h) >> 8) >> 8);274RSDK.SetActivePalette(CLAMP(abs(pos) >> 14, 0, 7), i + SCREEN_YCENTER, i + SCREEN_YCENTER + 1);275276scanlines->position.x = (sin * pos - ScreenInfo->center.x * scanlines->deform.x) + (camera->position.x >> 3);277scanlines->position.y = (cos * pos - ScreenInfo->center.x * scanlines->deform.y) + (camera->position.y >> 3);278279scanlines++;280cosVal += cosX;281}282}283284void UFO_Setup_PlaySphereSfx(void)285{286if (UFO_Setup->spherePan) {287int32 channel = RSDK.PlaySfx(UFO_Setup->sfxBlueSphere, false, 0xFF);288RSDK.SetChannelAttributes(channel, 1.0, -1.0, 1.0);289UFO_Setup->spherePan = 0;290}291else {292int32 channel = RSDK.PlaySfx(UFO_Setup->sfxBlueSphere, false, 0xFF);293RSDK.SetChannelAttributes(channel, 1.0, 1.0, 1.0);294UFO_Setup->spherePan = 1;295}296}297void UFO_Setup_Finish_Win(void)298{299EntityUFO_Setup *setup = RSDK_GET_ENTITY(SLOT_UFO_SETUP, UFO_Setup);300301SaveGame_SetEmerald(UFO_Setup->specialStageID);302303SaveRAM *saveRAM = SaveGame_GetSaveRAM();304if (globals->saveSlotID != NO_SAVE_SLOT)305GameProgress_GiveEmerald(saveRAM->nextSpecialStage);306307foreach_all(UFO_Player, player)308{309player->stateInput = StateMachine_None;310player->interaction = false;311}312313saveRAM->nextSpecialStage = (saveRAM->nextSpecialStage + 1) % 7;314setup->visible = true;315setup->state = UFO_Setup_State_FinishFadeout;316317RSDK.PlaySfx(UFO_Setup->sfxSSExit, false, 0xFF);318Music_FadeOut(0.025);319PauseMenu->disableEvents = true;320}321void UFO_Setup_Finish_Fail(void)322{323EntityUFO_Setup *setup = RSDK_GET_ENTITY(SLOT_UFO_SETUP, UFO_Setup);324325foreach_all(UFO_Player, player)326{327player->stateInput = StateMachine_None;328player->interaction = false;329}330331setup->visible = true;332setup->state = UFO_Setup_State_FinishFadeout;333334RSDK.PlaySfx(UFO_Setup->sfxSSExit, false, 0xFF);335Music_FadeOut(0.025);336PauseMenu->disableEvents = true;337}338339void UFO_Setup_Deform_UFO3(void)340{341if (!(UFO_Setup->timer & 1)) {342++RSDK.GetTileLayer(0)->deformationOffset;343++RSDK.GetTileLayer(1)->deformationOffset;344}345}346347void UFO_Setup_Deform_UFO4(void)348{349if (!(UFO_Setup->timer & 1))350++RSDK.GetTileLayer(0)->deformationOffset;351}352353void UFO_Setup_Deform_UFO5(void)354{355if (!(UFO_Setup->timer & 1))356++RSDK.GetTileLayer(0)->deformationOffset;357}358359void UFO_Setup_State_ShowStartMessage(void)360{361RSDK_THIS(UFO_Setup);362if (self->timer <= 0) {363self->timer = 0;364self->visible = false;365self->state = UFO_Setup_State_HandleRingDrain;366367SceneInfo->timeEnabled = true;368CREATE_ENTITY(UFO_Message, INT_TO_VOID(UFO_MESSAGE_CATCHUFO), self->position.x, self->position.y);369}370else {371self->timer -= 0x10;372}373}374375void UFO_Setup_State_FinishFadeout(void)376{377RSDK_THIS(UFO_Setup);378379if (self->timer >= 1024) {380if (UFO_Setup->resetToTitle) {381RSDK.SetScene("Presentation", "Title Screen");382RSDK.LoadScene();383}384else {385for (int32 l = 0; l < LAYER_COUNT; ++l) {386TileLayer *layer = RSDK.GetTileLayer(l);387if (layer)388layer->drawGroup[0] = DRAWGROUP_COUNT;389}390391for (int32 l = 0; l < SCENEENTITY_COUNT; ++l) {392Entity *entity = RSDK_GET_ENTITY_GEN(l);393if (entity->classID != self->classID)394destroyEntity(entity);395}396397RSDK.ResetEntitySlot(0, UIBackground->classID, NULL);398RSDK.ResetEntitySlot(1, SpecialClear->classID, NULL);399400RSDK.AddDrawListRef(DRAWGROUP_COUNT - 2, 1);401402#if MANIA_USE_PLUS403if (globals->gameMode == MODE_ENCORE)404UIBackground->activeColors = &UIBackground->bgColors[18];405#endif406407self->visible = false;408self->state = StateMachine_None;409}410}411else {412self->timer += 8;413}414}415416void UFO_Setup_State_HandleRingDrain(void)417{418RSDK_THIS(UFO_Setup);419420if (++self->timer == 60) {421self->timer = 0;422423if (UFO_Setup->rings > 0 && SceneInfo->timeEnabled)424UFO_Setup->rings--;425426if (!UFO_Setup->rings && !UFO_Setup->timedOut) {427UFO_Setup->timedOut = true;428429CREATE_ENTITY(UFO_Message, INT_TO_VOID(UFO_MESSAGE_TIMEOVER), self->position.x, self->position.y);430431self->state = UFO_Setup_State_TimedOver;432}433}434}435436void UFO_Setup_State_TimedOver(void)437{438RSDK_THIS(UFO_Setup);439440if (++self->timer >= 90)441UFO_Setup_Finish_Fail();442}443444#if GAME_INCLUDE_EDITOR445void UFO_Setup_EditorDraw(void) {}446447void UFO_Setup_EditorLoad(void) {}448#endif449450void UFO_Setup_Serialize(void) {}451452453