Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/UFO/UFO_Setup.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: UFO_Setup Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectUFO_Setup *UFO_Setup;
11
12
void UFO_Setup_Update(void)
13
{
14
RSDK_THIS(UFO_Setup);
15
16
StateMachine_Run(self->state);
17
18
#if MANIA_USE_PLUS
19
if (self->state != UFO_Setup_State_FinishFadeout && globals->gameMode < MODE_TIMEATTACK)
20
++SaveGame_GetSaveRAM()->zoneTimes[29];
21
#endif
22
}
23
24
void UFO_Setup_LateUpdate(void) {}
25
26
void UFO_Setup_StaticUpdate(void)
27
{
28
++UFO_Setup->timer;
29
UFO_Setup->timer &= 0x7FFF;
30
31
if (!(UFO_Setup->timer & 1)) {
32
++UFO_Setup->ringFrame;
33
UFO_Setup->ringFrame &= 0xF;
34
}
35
36
StateMachine_Run(UFO_Setup->deformCB);
37
}
38
39
void UFO_Setup_Draw(void)
40
{
41
RSDK_THIS(UFO_Setup);
42
43
RSDK.FillScreen(self->fadeColor, self->timer, self->timer - 128, self->timer - 256);
44
}
45
46
void UFO_Setup_Create(void *data)
47
{
48
RSDK_THIS(UFO_Setup);
49
50
self->active = ACTIVE_NORMAL;
51
self->visible = true;
52
self->drawGroup = 15;
53
self->fadeColor = 0xF0F0F0;
54
self->timer = 512;
55
self->state = UFO_Setup_State_ShowStartMessage;
56
}
57
58
void UFO_Setup_StageLoad(void)
59
{
60
RSDK.ResetEntitySlot(SLOT_UFO_SETUP, UFO_Setup->classID, NULL);
61
62
UFO_Setup->playFieldLayer = RSDK.GetTileLayerID("Playfield");
63
64
UFO_Setup->machPoints = 0;
65
UFO_Setup->machLevel = 0;
66
UFO_Setup->rings = 30;
67
UFO_Setup->timedOut = 0;
68
UFO_Setup->resetToTitle = false;
69
70
RSDK.GetTileLayer(UFO_Setup->playFieldLayer)->scanlineCallback = UFO_Setup_Scanline_Playfield;
71
72
RSDK.SetDrawGroupProperties(1, false, UFO_Setup_DrawHook_PrepareDrawingFX);
73
RSDK.SetDrawGroupProperties(3, false, UFO_Setup_DrawHook_PrepareDrawingFX);
74
RSDK.SetDrawGroupProperties(4, true, StateMachine_None);
75
76
UFO_Setup->sfxBlueSphere = RSDK.GetSfx("Special/BlueSphere2.wav");
77
UFO_Setup->sfxSSExit = RSDK.GetSfx("Special/SSExit.wav");
78
UFO_Setup->sfxEmerald = RSDK.GetSfx("Special/Emerald.wav");
79
UFO_Setup->sfxEvent = RSDK.GetSfx("Special/Event.wav");
80
81
RSDK.CopyPalette(0, 0, 7, 0, 128);
82
RSDK.CopyPalette(1, 96, 0, 96, 32);
83
84
RSDK.SetLimitedFade(1, 0, 7, 36, 160, 255);
85
RSDK.SetLimitedFade(2, 0, 7, 72, 160, 255);
86
RSDK.SetLimitedFade(3, 0, 7, 108, 160, 255);
87
RSDK.SetLimitedFade(4, 0, 7, 144, 160, 255);
88
RSDK.SetLimitedFade(5, 0, 7, 180, 160, 255);
89
RSDK.SetLimitedFade(6, 0, 7, 216, 160, 255);
90
91
uint16 floor3DLayer = RSDK.GetTileLayerID("3D Floor");
92
if (floor3DLayer != (uint16)-1) {
93
TileLayer *floor3D = RSDK.GetTileLayer(floor3DLayer);
94
if (floor3D) {
95
floor3D->drawGroup[0] = 0;
96
floor3D->scanlineCallback = UFO_Setup_Scanline_3DFloor;
97
}
98
}
99
100
uint16 roof3DLayer = RSDK.GetTileLayerID("3D Roof");
101
if (roof3DLayer != (uint16)-1) {
102
TileLayer *roof3D = RSDK.GetTileLayer(roof3DLayer);
103
if (roof3D) {
104
roof3D->drawGroup[0] = 0;
105
roof3D->scanlineCallback = UFO_Setup_Scanline_3DRoof;
106
}
107
}
108
109
if (RSDK.CheckSceneFolder("UFO3")) {
110
UFO_Setup->deformCB = UFO_Setup_Deform_UFO3;
111
112
int32 *deformData = RSDK.GetTileLayer(0)->deformationData;
113
for (int32 i = 0; i < 0x200; i += 0x10) {
114
int32 deform = RSDK.Rand(0, 4);
115
116
int32 deformPos = CLAMP(i, 0, 0x200);
117
118
int32 angle = 0;
119
for (int32 d = 0; d < 0x10; ++d) {
120
deformData[deformPos + d] = deform * RSDK.Sin1024(angle) >> 10;
121
angle += 0x40;
122
}
123
}
124
memcpy(&deformData[0x200], deformData, (0x200 * sizeof(int32)));
125
126
deformData = RSDK.GetTileLayer(1)->deformationData;
127
for (int32 i = 0; i < 0x200; i += 0x10) {
128
int32 deform = RSDK.Rand(0, 4);
129
130
int32 deformPos = CLAMP(i, 0, 0x200);
131
132
int32 angle = 0;
133
for (int32 d = 0; d < 0x10; ++d) {
134
deformData[deformPos + d] = deform * RSDK.Sin1024(angle) >> 10;
135
angle += 0x40;
136
}
137
}
138
memcpy(&deformData[0x200], deformData, (0x200 * sizeof(int32)));
139
}
140
else if (RSDK.CheckSceneFolder("UFO4")) {
141
UFO_Setup->deformCB = UFO_Setup_Deform_UFO4;
142
143
TileLayer *background = RSDK.GetTileLayer(0);
144
145
int32 angle = 0;
146
for (int32 i = 0; i < 0x200; ++i) {
147
background->deformationData[i] = (8 * RSDK.Sin1024(angle)) >> 10;
148
angle += 8;
149
}
150
151
memcpy(&background->deformationData[0x200], &background->deformationData[0], 0x200 * sizeof(int32));
152
}
153
else if (RSDK.CheckSceneFolder("UFO5")) {
154
UFO_Setup->deformCB = UFO_Setup_Deform_UFO5;
155
TileLayer *background = RSDK.GetTileLayer(0);
156
157
int32 angle = 0;
158
for (int32 i = 0; i < 0x200; ++i) {
159
background->deformationData[i] = 8 * RSDK.Sin1024(angle) >> 10;
160
angle += 16;
161
}
162
163
memcpy(&background->deformationData[0x200], &background->deformationData[0], 0x200 * sizeof(int32));
164
}
165
166
int32 listPos = SceneInfo->listPos;
167
RSDK.SetScene("Special Stage", "");
168
UFO_Setup->specialStageID = listPos - SceneInfo->listPos;
169
170
#if MANIA_USE_PLUS
171
if (UFO_Setup->specialStageID >= 7) {
172
UFO_Setup->specialStageID = UFO_Setup->specialStageID % 7;
173
UFO_Setup->encoreStage = true;
174
}
175
#endif
176
177
SceneInfo->listPos = listPos;
178
}
179
180
void UFO_Setup_DrawHook_PrepareDrawingFX(void)
181
{
182
RSDK.SetClipBounds(0, 0, 0, ScreenInfo->size.x, ScreenInfo->size.y);
183
RSDK.SetActivePalette(0, 0, ScreenInfo->size.y);
184
}
185
186
void UFO_Setup_Scanline_Playfield(ScanlineInfo *scanlines)
187
{
188
EntityUFO_Camera *camera = RSDK_GET_ENTITY(SLOT_UFO_CAMERA, UFO_Camera);
189
190
RSDK.SetClipBounds(0, 0, camera->clipY, ScreenInfo->size.x, ScreenInfo->size.y);
191
192
int32 sin = RSDK.Sin1024(camera->angle) >> 2;
193
int32 cos = RSDK.Cos1024(camera->angle) >> 2;
194
int32 sinX = RSDK.Sin1024(-camera->angleX) >> 2;
195
int32 cosX = RSDK.Cos1024(-camera->angleX) >> 2;
196
197
int32 cosVal = -SCREEN_YCENTER * cosX;
198
199
for (int32 i = -SCREEN_YCENTER; i < SCREEN_YCENTER; ++i) {
200
int32 div = sinX + (cosVal >> 8);
201
if (!div)
202
div = 1;
203
204
int32 h = camera->height / div;
205
scanlines->deform.x = (-cos * h) >> 8;
206
scanlines->deform.y = (sin * h) >> 8;
207
208
int32 pos = ((cosX * h) >> 8) - (sinX * ((i * h) >> 8) >> 8);
209
RSDK.SetActivePalette(CLAMP(abs(pos) >> 15, 0, 7), i + SCREEN_YCENTER, i + SCREEN_YCENTER + 1);
210
211
scanlines->position.x = (sin * pos - ScreenInfo->center.x * scanlines->deform.x) + camera->position.x;
212
scanlines->position.y = (cos * pos - ScreenInfo->center.x * scanlines->deform.y) + camera->position.y;
213
214
scanlines++;
215
cosVal += cosX;
216
}
217
}
218
219
void UFO_Setup_Scanline_3DFloor(ScanlineInfo *scanlines)
220
{
221
EntityUFO_Camera *camera = RSDK_GET_ENTITY(SLOT_UFO_CAMERA, UFO_Camera);
222
223
RSDK.SetClipBounds(0, 0, camera->clipY + 24, ScreenInfo->size.x, ScreenInfo->size.y);
224
225
int32 sin = RSDK.Sin1024(camera->angle) >> 2;
226
int32 cos = RSDK.Cos1024(camera->angle) >> 2;
227
int32 sinX = RSDK.Sin1024(-camera->angleX) >> 2;
228
int32 cosX = RSDK.Cos1024(-camera->angleX) >> 2;
229
230
int32 cosVal = -SCREEN_YCENTER * cosX;
231
232
for (int32 i = -SCREEN_YCENTER; i < SCREEN_YCENTER; ++i) {
233
int32 div = sinX + (cosVal >> 8);
234
if (!div)
235
div = 1;
236
237
int32 h = (camera->height + 0x1000000) / div;
238
scanlines->deform.x = -(cos * h) >> 8;
239
scanlines->deform.y = (sin * h) >> 8;
240
241
int32 pos = ((cosX * h) >> 8) - (sinX * ((i * h) >> 8) >> 8);
242
RSDK.SetActivePalette(CLAMP((abs(pos) >> 15) - 8, 0, 7), i + SCREEN_YCENTER, i + SCREEN_YCENTER + 1);
243
244
scanlines->position.x = (sin * pos - ScreenInfo->center.x * scanlines->deform.x) + camera->position.x;
245
scanlines->position.y = (cos * pos - ScreenInfo->center.x * scanlines->deform.y) + camera->position.y;
246
247
scanlines++;
248
cosVal += cosX;
249
}
250
}
251
void UFO_Setup_Scanline_3DRoof(ScanlineInfo *scanlines)
252
{
253
EntityUFO_Camera *camera = RSDK_GET_ENTITY(SLOT_UFO_CAMERA, UFO_Camera);
254
255
RSDK.SetClipBounds(0, 0, 0, ScreenInfo->size.x, camera->clipY - 48);
256
257
int32 sin = RSDK.Sin1024(camera->angle) >> 2;
258
int32 cos = RSDK.Cos1024(camera->angle) >> 2;
259
int32 sinX = RSDK.Sin1024(-camera->angleX) >> 2;
260
int32 cosX = RSDK.Cos1024(-camera->angleX) >> 2;
261
262
int32 cosVal = -SCREEN_YCENTER * cosX;
263
int32 height = (camera->height >> 2) - 0x600000;
264
265
for (int32 i = -SCREEN_YCENTER; i < SCREEN_YCENTER; ++i) {
266
int32 div = sinX + (cosVal >> 8);
267
if (!div)
268
div = 1;
269
270
int32 h = height / div;
271
scanlines->deform.x = -(cos * h) >> 8;
272
scanlines->deform.y = (sin * h) >> 8;
273
274
int32 pos = ((cosX * h) >> 8) - (sinX * ((i * h) >> 8) >> 8);
275
RSDK.SetActivePalette(CLAMP(abs(pos) >> 14, 0, 7), i + SCREEN_YCENTER, i + SCREEN_YCENTER + 1);
276
277
scanlines->position.x = (sin * pos - ScreenInfo->center.x * scanlines->deform.x) + (camera->position.x >> 3);
278
scanlines->position.y = (cos * pos - ScreenInfo->center.x * scanlines->deform.y) + (camera->position.y >> 3);
279
280
scanlines++;
281
cosVal += cosX;
282
}
283
}
284
285
void UFO_Setup_PlaySphereSfx(void)
286
{
287
if (UFO_Setup->spherePan) {
288
int32 channel = RSDK.PlaySfx(UFO_Setup->sfxBlueSphere, false, 0xFF);
289
RSDK.SetChannelAttributes(channel, 1.0, -1.0, 1.0);
290
UFO_Setup->spherePan = 0;
291
}
292
else {
293
int32 channel = RSDK.PlaySfx(UFO_Setup->sfxBlueSphere, false, 0xFF);
294
RSDK.SetChannelAttributes(channel, 1.0, 1.0, 1.0);
295
UFO_Setup->spherePan = 1;
296
}
297
}
298
void UFO_Setup_Finish_Win(void)
299
{
300
EntityUFO_Setup *setup = RSDK_GET_ENTITY(SLOT_UFO_SETUP, UFO_Setup);
301
302
SaveGame_SetEmerald(UFO_Setup->specialStageID);
303
304
SaveRAM *saveRAM = SaveGame_GetSaveRAM();
305
if (globals->saveSlotID != NO_SAVE_SLOT)
306
GameProgress_GiveEmerald(saveRAM->nextSpecialStage);
307
308
foreach_all(UFO_Player, player)
309
{
310
player->stateInput = StateMachine_None;
311
player->interaction = false;
312
}
313
314
saveRAM->nextSpecialStage = (saveRAM->nextSpecialStage + 1) % 7;
315
setup->visible = true;
316
setup->state = UFO_Setup_State_FinishFadeout;
317
318
RSDK.PlaySfx(UFO_Setup->sfxSSExit, false, 0xFF);
319
Music_FadeOut(0.025);
320
PauseMenu->disableEvents = true;
321
}
322
void UFO_Setup_Finish_Fail(void)
323
{
324
EntityUFO_Setup *setup = RSDK_GET_ENTITY(SLOT_UFO_SETUP, UFO_Setup);
325
326
foreach_all(UFO_Player, player)
327
{
328
player->stateInput = StateMachine_None;
329
player->interaction = false;
330
}
331
332
setup->visible = true;
333
setup->state = UFO_Setup_State_FinishFadeout;
334
335
RSDK.PlaySfx(UFO_Setup->sfxSSExit, false, 0xFF);
336
Music_FadeOut(0.025);
337
PauseMenu->disableEvents = true;
338
}
339
340
void UFO_Setup_Deform_UFO3(void)
341
{
342
if (!(UFO_Setup->timer & 1)) {
343
++RSDK.GetTileLayer(0)->deformationOffset;
344
++RSDK.GetTileLayer(1)->deformationOffset;
345
}
346
}
347
348
void UFO_Setup_Deform_UFO4(void)
349
{
350
if (!(UFO_Setup->timer & 1))
351
++RSDK.GetTileLayer(0)->deformationOffset;
352
}
353
354
void UFO_Setup_Deform_UFO5(void)
355
{
356
if (!(UFO_Setup->timer & 1))
357
++RSDK.GetTileLayer(0)->deformationOffset;
358
}
359
360
void UFO_Setup_State_ShowStartMessage(void)
361
{
362
RSDK_THIS(UFO_Setup);
363
if (self->timer <= 0) {
364
self->timer = 0;
365
self->visible = false;
366
self->state = UFO_Setup_State_HandleRingDrain;
367
368
SceneInfo->timeEnabled = true;
369
CREATE_ENTITY(UFO_Message, INT_TO_VOID(UFO_MESSAGE_CATCHUFO), self->position.x, self->position.y);
370
}
371
else {
372
self->timer -= 0x10;
373
}
374
}
375
376
void UFO_Setup_State_FinishFadeout(void)
377
{
378
RSDK_THIS(UFO_Setup);
379
380
if (self->timer >= 1024) {
381
if (UFO_Setup->resetToTitle) {
382
RSDK.SetScene("Presentation", "Title Screen");
383
RSDK.LoadScene();
384
}
385
else {
386
for (int32 l = 0; l < LAYER_COUNT; ++l) {
387
TileLayer *layer = RSDK.GetTileLayer(l);
388
if (layer)
389
layer->drawGroup[0] = DRAWGROUP_COUNT;
390
}
391
392
for (int32 l = 0; l < SCENEENTITY_COUNT; ++l) {
393
Entity *entity = RSDK_GET_ENTITY_GEN(l);
394
if (entity->classID != self->classID)
395
destroyEntity(entity);
396
}
397
398
RSDK.ResetEntitySlot(0, UIBackground->classID, NULL);
399
RSDK.ResetEntitySlot(1, SpecialClear->classID, NULL);
400
401
RSDK.AddDrawListRef(DRAWGROUP_COUNT - 2, 1);
402
403
#if MANIA_USE_PLUS
404
if (globals->gameMode == MODE_ENCORE)
405
UIBackground->activeColors = &UIBackground->bgColors[18];
406
#endif
407
408
self->visible = false;
409
self->state = StateMachine_None;
410
}
411
}
412
else {
413
self->timer += 8;
414
}
415
}
416
417
void UFO_Setup_State_HandleRingDrain(void)
418
{
419
RSDK_THIS(UFO_Setup);
420
421
if (++self->timer == 60) {
422
self->timer = 0;
423
424
if (UFO_Setup->rings > 0 && SceneInfo->timeEnabled)
425
UFO_Setup->rings--;
426
427
if (!UFO_Setup->rings && !UFO_Setup->timedOut) {
428
UFO_Setup->timedOut = true;
429
430
CREATE_ENTITY(UFO_Message, INT_TO_VOID(UFO_MESSAGE_TIMEOVER), self->position.x, self->position.y);
431
432
self->state = UFO_Setup_State_TimedOver;
433
}
434
}
435
}
436
437
void UFO_Setup_State_TimedOver(void)
438
{
439
RSDK_THIS(UFO_Setup);
440
441
if (++self->timer >= 90)
442
UFO_Setup_Finish_Fail();
443
}
444
445
#if GAME_INCLUDE_EDITOR
446
void UFO_Setup_EditorDraw(void) {}
447
448
void UFO_Setup_EditorLoad(void) {}
449
#endif
450
451
void UFO_Setup_Serialize(void) {}
452
453