Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/Global/GameOver.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: GameOver Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectGameOver *GameOver;
11
12
void GameOver_Update(void)
13
{
14
RSDK_THIS(GameOver);
15
16
StateMachine_Run(self->state);
17
}
18
19
void GameOver_LateUpdate(void) {}
20
21
void GameOver_StaticUpdate(void) {}
22
23
void GameOver_Draw(void)
24
{
25
RSDK_THIS(GameOver);
26
27
#if MANIA_USE_PLUS
28
if (self->state != GameOver_State_ExitLetters && globals->gameMode == MODE_COMPETITION) {
29
if (SceneInfo->currentScreenID != self->playerID || RSDK.GetEntityCount(PauseMenu->classID, true) > 0) {
30
return;
31
}
32
}
33
34
EntityPlayer *player = RSDK_GET_ENTITY(SceneInfo->currentScreenID + Player->playerCount, Player);
35
if (SceneInfo->currentScreenID == self->playerID || player->classID != GameOver->classID)
36
RSDK.DrawFace(self->verts, 4, 0x00, 0x00, 0x00, 0xFF, INK_NONE);
37
38
if (globals->gameMode != MODE_COMPETITION || SceneInfo->currentScreenID == self->playerID) {
39
for (self->animator.frameID = 0; self->animator.frameID < GAMEOVER_LETTER_COUNT; ++self->animator.frameID) {
40
self->rotation = self->letterRotations[self->animator.frameID];
41
RSDK.DrawSprite(&self->animator, &self->letterPositions[self->animator.frameID], true);
42
}
43
}
44
#else
45
if (((1 << SceneInfo->currentScreenID) & GameOver->activeScreens) || self->state == GameOver_State_ExitLetters) {
46
RSDK.DrawFace(self->verts, 4, 0x00, 0x00, 0x00, 0xFF, INK_NONE);
47
48
if (((1 << SceneInfo->currentScreenID) & GameOver->activeScreens)) {
49
for (self->animator.frameID = 0; self->animator.frameID < GAMEOVER_LETTER_COUNT; ++self->animator.frameID) {
50
self->rotation = self->letterRotations[self->animator.frameID];
51
RSDK.DrawSprite(&self->animator, &self->letterPositions[self->animator.frameID], true);
52
}
53
}
54
}
55
#endif
56
}
57
58
void GameOver_Create(void *data)
59
{
60
RSDK_THIS(GameOver);
61
62
if (!SceneInfo->inEditor) {
63
self->active = ACTIVE_ALWAYS;
64
self->visible = true;
65
self->drawFX = FX_ROTATE | FX_SCALE;
66
if (data)
67
RSDK.SetSpriteAnimation(GameOver->aniFrames, 7, &self->animator, true, 1);
68
else
69
RSDK.SetSpriteAnimation(GameOver->aniFrames, 6, &self->animator, true, 0);
70
71
self->finalOffsets[0].x = -TO_FIXED(72);
72
self->finalOffsets[1].x = -TO_FIXED(55);
73
self->finalOffsets[2].x = -TO_FIXED(38);
74
self->finalOffsets[3].x = -TO_FIXED(21);
75
self->finalOffsets[4].x = TO_FIXED(12);
76
self->finalOffsets[5].x = TO_FIXED(29);
77
self->finalOffsets[6].x = TO_FIXED(46);
78
self->finalOffsets[7].x = TO_FIXED(63);
79
80
int32 posY = -TO_FIXED(32);
81
for (int32 i = 0; i < GAMEOVER_LETTER_COUNT; ++i) {
82
self->letterPosMove[i].x = -(self->finalOffsets[i].x >> 4);
83
self->letterPosMove[i].y = 0x2000;
84
85
self->finalOffsets[i].y = TO_FIXED(ScreenInfo->center.y - 4);
86
87
self->letterPositions[i].x = 8 * ((ScreenInfo->center.x << 13) + self->finalOffsets[i].x);
88
self->letterPositions[i].y = posY;
89
90
posY -= TO_FIXED(16);
91
}
92
93
self->barPos.x = TO_FIXED(256);
94
self->barPos.y = TO_FIXED(ScreenInfo->center.y);
95
self->scale.x = 0x800;
96
self->state = GameOver_State_EnterLetters;
97
self->drawGroup = Zone->hudDrawGroup + 1;
98
99
HUD_MoveOut();
100
101
foreach_all(HUD, hud) { hud->active = ACTIVE_ALWAYS; }
102
}
103
}
104
105
void GameOver_StageLoad(void)
106
{
107
GameOver->aniFrames = RSDK.LoadSpriteAnimation("Global/HUD.bin", SCOPE_STAGE);
108
109
GameOver->activeScreens = 0;
110
}
111
112
#if MANIA_USE_PLUS
113
void GameOver_SaveGameCallback(bool32 success)
114
{
115
UIWaitSpinner_FinishWait();
116
RSDK.LoadScene();
117
}
118
#else
119
void GameOver_SaveGameCallback(void)
120
{
121
UIWaitSpinner_FinishWait();
122
RSDK.LoadScene();
123
}
124
#endif
125
126
void GameOver_State_EnterLetters(void)
127
{
128
RSDK_THIS(GameOver);
129
130
if (self->barPos.x > 0)
131
self->barPos.x -= TO_FIXED(4);
132
133
self->verts[0].x = self->barPos.x + TO_FIXED(ScreenInfo->center.x - 104);
134
self->verts[1].x = self->barPos.x + TO_FIXED(ScreenInfo->center.x + 88);
135
self->verts[2].x = self->barPos.x + TO_FIXED(ScreenInfo->center.x + 104);
136
self->verts[3].x = self->barPos.x + TO_FIXED(ScreenInfo->center.x - 88);
137
self->verts[0].y = self->barPos.y - TO_FIXED(8);
138
self->verts[1].y = self->barPos.y - TO_FIXED(8);
139
self->verts[2].y = self->barPos.y + TO_FIXED(8);
140
self->verts[3].y = self->barPos.y + TO_FIXED(8);
141
142
for (int32 i = 0; i < GAMEOVER_LETTER_COUNT; ++i) {
143
self->letterPositions[i].x = TO_FIXED(ScreenInfo->center.x) + self->scale.x * (self->finalOffsets[i].x >> 9);
144
if (self->letterBounceCount[i] < 3) {
145
self->letterPosMove[i].y += 0x4000;
146
self->letterPositions[i].y += self->letterPosMove[i].y;
147
148
if (self->letterPosMove[i].y > 0 && self->letterPositions[i].y > self->finalOffsets[i].y) {
149
self->letterPositions[i].y = self->finalOffsets[i].y;
150
self->letterPosMove[i].y = -(self->letterPosMove[i].y / 3);
151
152
++self->letterBounceCount[i];
153
}
154
}
155
}
156
157
if (self->scale.x <= 0x200)
158
self->scale.x = 0x200;
159
else
160
self->scale.x = self->scale.x - self->scale.x / 40;
161
self->scale.y = self->scale.x;
162
163
if (self->timer == 0) {
164
#if MANIA_USE_PLUS
165
EntityCompetitionSession *session = CompetitionSession_GetSession();
166
if (globals->gameMode != MODE_COMPETITION) {
167
Music_TransitionTrack(TRACK_GAMEOVER, 0.025);
168
}
169
else {
170
if (session->playerCount <= 0) {
171
bool32 playMusic = false;
172
if (Zone->gotTimeOver)
173
playMusic = true;
174
175
if (playMusic)
176
Music_TransitionTrack(TRACK_GAMEOVER, 0.025);
177
}
178
else {
179
EntityCompetition *manager = Competition->sessionManager;
180
int32 gameOverCount = 0;
181
int32 deathCount = 0;
182
for (int32 i = 0; i < session->playerCount; ++i) {
183
EntityGameOver *gameOver = RSDK_GET_ENTITY(i + Player->playerCount, GameOver);
184
185
if (gameOver->classID == GameOver->classID) {
186
++gameOverCount;
187
++deathCount;
188
}
189
else if (manager && manager->playerFinished[i]) {
190
++deathCount;
191
}
192
}
193
194
bool32 playMusic = true;
195
if (gameOverCount < session->playerCount - 1 && deathCount != session->playerCount) {
196
if (!Zone->gotTimeOver)
197
playMusic = false;
198
}
199
200
if (playMusic)
201
Music_TransitionTrack(TRACK_GAMEOVER, 0.025);
202
}
203
}
204
#else
205
Music_TransitionTrack(TRACK_GAMEOVER, 0.025);
206
#endif
207
}
208
209
if (++self->timer == 120) {
210
self->timer = 0;
211
#if MANIA_USE_PLUS
212
if (globals->gameMode == MODE_COMPETITION || Zone->gotTimeOver)
213
self->state = GameOver_State_WaitComp;
214
else
215
#endif
216
self->state = GameOver_State_Wait;
217
}
218
}
219
220
#if MANIA_USE_PLUS
221
void GameOver_State_WaitComp(void)
222
{
223
RSDK_THIS(GameOver);
224
225
EntityCompetition *manager = Competition->sessionManager;
226
EntityCompetitionSession *session = CompetitionSession_GetSession();
227
228
int32 gameOverCount = 0;
229
int32 deathCount = 0;
230
for (int32 i = 0; i < session->playerCount; ++i) {
231
EntityGameOver *gameOver = RSDK_GET_ENTITY(i + Player->playerCount, GameOver);
232
233
if (gameOver->classID == GameOver->classID) {
234
++gameOverCount;
235
++deathCount;
236
}
237
else if (manager && manager->playerFinished[i]) {
238
++deathCount;
239
}
240
}
241
242
if (gameOverCount >= session->playerCount - 1 || deathCount == session->playerCount || Zone->gotTimeOver)
243
self->state = GameOver_State_Wait;
244
}
245
#endif
246
247
void GameOver_State_Wait(void)
248
{
249
RSDK_THIS(GameOver);
250
251
++self->timer;
252
253
int32 id = globals->gameMode == MODE_COMPETITION ? (self->playerID + 1) : INPUT_NONE;
254
255
if (ControllerInfo[id].keyA.press || ControllerInfo[id].keyB.press || ControllerInfo[id].keyC.press || ControllerInfo[id].keyX.press
256
|| ControllerInfo[id].keyStart.press)
257
self->timer = 420;
258
259
if (self->timer == 420) {
260
#if MANIA_USE_PLUS
261
Music_ClearMusicStack();
262
#endif
263
Music_FadeOut(0.05);
264
265
foreach_all(GameOver, gameOver)
266
{
267
int32 angle = 0x88;
268
for (int32 i = 0; i < GAMEOVER_LETTER_COUNT; ++i) {
269
gameOver->letterPosMove[i].x = RSDK.Cos256(angle) << 11;
270
gameOver->letterPosMove[i].y = RSDK.Sin256(angle) << 11;
271
gameOver->letterRotateSpeed[i] = RSDK.Rand(-8, 8);
272
angle += 0x10;
273
}
274
gameOver->timer = 0;
275
gameOver->state = GameOver_State_ExitLetters;
276
}
277
}
278
}
279
280
void GameOver_State_ExitLetters(void)
281
{
282
RSDK_THIS(GameOver);
283
284
if (self->timer < 120) {
285
for (int32 i = 0; i < GAMEOVER_LETTER_COUNT; ++i) {
286
self->letterPositions[i].x += self->letterPosMove[i].x;
287
self->letterPositions[i].y += self->letterPosMove[i].y;
288
self->letterRotations[i] += self->letterRotateSpeed[i];
289
}
290
self->verts[0].x -= TO_FIXED(16);
291
self->verts[0].y -= TO_FIXED(8);
292
self->verts[1].x += TO_FIXED(16);
293
self->verts[1].y -= TO_FIXED(8);
294
self->verts[2].x += TO_FIXED(16);
295
self->verts[2].y += TO_FIXED(8);
296
self->verts[3].x -= TO_FIXED(16);
297
self->verts[3].y += TO_FIXED(8);
298
self->scale.x += 0x20;
299
self->scale.y += 0x20;
300
++self->timer;
301
}
302
303
if (self->timer == 90) {
304
self->timer = 0;
305
306
EntityCompetitionSession *session = CompetitionSession_GetSession();
307
if (globals->gameMode == MODE_COMPETITION) {
308
session->completedStages[session->stageIndex] = true;
309
#if MANIA_USE_PLUS
310
session->matchID = session->prevMatchID + 1;
311
#else
312
session->matchID++;
313
#endif
314
RSDK.SetVideoSetting(VIDEOSETTING_SCREENCOUNT, 1);
315
RSDK.SetScene("Presentation", "Menu");
316
RSDK.LoadScene();
317
}
318
else if (self->animator.animationID != 6) {
319
StarPost->storedMS = 0;
320
StarPost->storedSeconds = 0;
321
StarPost->storedMinutes = 0;
322
RSDK.LoadScene();
323
}
324
else {
325
SaveRAM *saveRAM = SaveGame_GetSaveRAM();
326
if (globals->gameMode >= MODE_TIMEATTACK) {
327
RSDK.SetScene("Presentation", "Menu");
328
RSDK.LoadScene();
329
}
330
else if (globals->continues > 0) {
331
saveRAM->storedStageID = SceneInfo->listPos;
332
saveRAM->lives = 3;
333
saveRAM->score = 0;
334
saveRAM->score1UP = 0;
335
#if MANIA_USE_PLUS
336
if (globals->gameMode == MODE_ENCORE) {
337
globals->playerID &= 0xFF;
338
saveRAM->characterFlags = -1;
339
globals->characterFlags = 1 << HUD_CharacterIndexFromID(GET_CHARACTER_ID(1));
340
saveRAM->characterFlags = globals->characterFlags;
341
saveRAM->stock = globals->stock;
342
}
343
#endif
344
RSDK.SetScene("Presentation", "Continue");
345
RSDK.LoadScene();
346
}
347
else {
348
saveRAM->lives = 3;
349
saveRAM->score = 0;
350
saveRAM->score1UP = 0;
351
#if MANIA_USE_PLUS
352
if (globals->gameMode == MODE_ENCORE) {
353
globals->playerID &= 0xFF;
354
saveRAM->characterFlags = -1;
355
globals->characterFlags = 1 << HUD_CharacterIndexFromID(GET_CHARACTER_ID(1));
356
saveRAM->characterFlags = globals->characterFlags;
357
saveRAM->stock = globals->stock;
358
}
359
#endif
360
UIWaitSpinner_StartWait();
361
SaveGame_SaveFile(GameOver_SaveGameCallback);
362
RSDK.SetScene("Presentation", "Menu");
363
// GameOver_SaveGameCallback() loads the scene instead of doing it here
364
}
365
}
366
}
367
}
368
369
#if GAME_INCLUDE_EDITOR
370
void GameOver_EditorDraw(void) {}
371
372
void GameOver_EditorLoad(void) {}
373
#endif
374
375
void GameOver_Serialize(void) {}
376
377