Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/Global/Announcer.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: Announcer Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectAnnouncer *Announcer;
11
12
void Announcer_Update(void)
13
{
14
RSDK_THIS(Announcer);
15
StateMachine_Run(self->state);
16
}
17
18
void Announcer_LateUpdate(void) {}
19
20
void Announcer_StaticUpdate(void) {}
21
22
void Announcer_Draw(void)
23
{
24
RSDK_THIS(Announcer);
25
StateMachine_Run(self->stateDraw);
26
}
27
28
void Announcer_Create(void *data)
29
{
30
RSDK_THIS(Announcer);
31
32
self->active = ACTIVE_NORMAL;
33
self->drawGroup = 13;
34
self->visible = true;
35
self->drawFX = FX_FLIP | FX_SCALE;
36
self->isPermanent = true;
37
self->updateRange.x = TO_FIXED(128);
38
self->updateRange.y = TO_FIXED(128);
39
}
40
41
void Announcer_StageLoad(void)
42
{
43
Announcer->finishedCountdown = false;
44
45
if (RSDK.CheckSceneFolder("Menu")) {
46
#if !MANIA_USE_PLUS
47
Announcer->sfxNewRecordTop = RSDK.GetSfx("VO/NewRecordTop.wav");
48
Announcer->sfxNewRecordMid = RSDK.GetSfx("VO/NewRecordMid.wav");
49
#endif
50
Announcer->sfxSonic = RSDK.GetSfx("VO/Sonic.wav");
51
Announcer->sfxTails = RSDK.GetSfx("VO/Tails.wav");
52
Announcer->sfxKnuckles = RSDK.GetSfx("VO/Knuckles.wav");
53
#if MANIA_USE_PLUS
54
Announcer->sfxMighty = RSDK.GetSfx("VO/Mighty.wav");
55
Announcer->sfxRay = RSDK.GetSfx("VO/Ray.wav");
56
#endif
57
Announcer->sfxTheWinnerIs = RSDK.GetSfx("VO/TheWinnerIs.wav");
58
Announcer->sfxPlayer1 = RSDK.GetSfx("VO/Player1.wav");
59
Announcer->sfxPlayer2 = RSDK.GetSfx("VO/Player2.wav");
60
#if MANIA_USE_PLUS
61
Announcer->sfxPlayer3 = RSDK.GetSfx("VO/Player3.wav");
62
Announcer->sfxPlayer4 = RSDK.GetSfx("VO/Player4.wav");
63
#endif
64
Announcer->sfxSonicWins = RSDK.GetSfx("VO/SonicWins.wav");
65
Announcer->sfxTailsWins = RSDK.GetSfx("VO/TailsWins.wav");
66
Announcer->sfxKnuxWins = RSDK.GetSfx("VO/KnuxWins.wav");
67
#if MANIA_USE_PLUS
68
Announcer->sfxMightyWins = RSDK.GetSfx("VO/MightyWins.wav");
69
Announcer->sfxRayWins = RSDK.GetSfx("VO/RayWins.wav");
70
Announcer->sfxDrawRound = RSDK.GetSfx("VO/ItsADraw.wav");
71
Announcer->sfxDrawSet = RSDK.GetSfx("VO/ItsADraw_Set.wav");
72
LogHelpers_Print("sfxDrawRound = %d", Announcer->sfxDrawRound);
73
LogHelpers_Print("sfxDrawSet = %d", Announcer->sfxDrawSet);
74
#endif
75
}
76
else if (globals->gameMode == MODE_COMPETITION) {
77
Announcer->aniFrames = RSDK.LoadSpriteAnimation("Global/Announcer.bin", SCOPE_STAGE);
78
79
Announcer->sfxThree = RSDK.GetSfx("VO/Three.wav");
80
Announcer->sfxTwo = RSDK.GetSfx("VO/Two.wav");
81
Announcer->sfxOne = RSDK.GetSfx("VO/One.wav");
82
Announcer->sfxGo = RSDK.GetSfx("VO/Go.wav");
83
Announcer->sfxGoal = RSDK.GetSfx("VO/Goal.wav");
84
}
85
else if (globals->gameMode == MODE_TIMEATTACK) {
86
Announcer->aniFrames = RSDK.LoadSpriteAnimation("Global/Announcer.bin", SCOPE_STAGE);
87
88
#if MANIA_USE_PLUS
89
Announcer->sfxNewRecordTop = RSDK.GetSfx("VO/NewRecordTop.wav");
90
Announcer->sfxNewRecordMid = RSDK.GetSfx("VO/NewRecordMid.wav");
91
#endif
92
Announcer->sfxGoal = RSDK.GetSfx("VO/Goal.wav");
93
}
94
}
95
96
void Announcer_StartCountdown(void)
97
{
98
Announcer->finishedCountdown = false;
99
EntityAnnouncer *announcer = CREATE_ENTITY(Announcer, NULL, 0, 0);
100
announcer->state = Announcer_State_Countdown;
101
announcer->stateDraw = Announcer_Draw_Countdown;
102
announcer->playerID = 3;
103
announcer->scale.x = 0x200;
104
announcer->scale.y = 0x200;
105
}
106
void Announcer_AnnounceGoal(int32 screen)
107
{
108
EntityAnnouncer *announcer = CREATE_ENTITY(Announcer, NULL, 0, 0);
109
announcer->state = Announcer_State_Finished;
110
announcer->stateDraw = Announcer_Draw_Finished;
111
announcer->screen = screen;
112
RSDK.SetSpriteAnimation(Announcer->aniFrames, 0, &announcer->animator, true, 0);
113
RSDK.PlaySfx(Announcer->sfxGoal, false, 255);
114
}
115
void Announcer_Draw_Countdown(void)
116
{
117
RSDK_THIS(Announcer);
118
119
Vector2 drawPos;
120
drawPos.y = (ScreenInfo->center.y - 32) << 16;
121
drawPos.x = ScreenInfo->center.x << 16;
122
drawPos.x += self->drawOffset.x;
123
drawPos.y += self->drawOffset.y;
124
RSDK.DrawSprite(&self->animator, &drawPos, true);
125
126
if (self->playerID > 0) {
127
self->inkEffect = INK_NONE;
128
EntityCompetitionSession *session = CompetitionSession_GetSession();
129
130
int32 frame = 0;
131
switch (session->playerID[SceneInfo->currentScreenID]) {
132
default:
133
case ID_SONIC: frame = 0; break;
134
case ID_TAILS: frame = 1; break;
135
case ID_KNUCKLES: frame = 2; break;
136
#if MANIA_USE_PLUS
137
case ID_MIGHTY: frame = 3; break;
138
case ID_RAY: frame = 4; break;
139
#endif
140
}
141
RSDK.SetSpriteAnimation(Announcer->aniFrames, 2, &self->playerIconAnimator, true, frame);
142
143
drawPos.x = ScreenInfo->center.x << 16;
144
drawPos.y = (ScreenInfo->center.y + 48) << 16;
145
RSDK.DrawSprite(&self->playerIconAnimator, &drawPos, true);
146
self->inkEffect = INK_ALPHA;
147
}
148
}
149
void Announcer_Draw_Finished(void)
150
{
151
RSDK_THIS(Announcer);
152
153
Vector2 drawPos;
154
if (SceneInfo->currentScreenID == self->screen) {
155
drawPos.x = ScreenInfo->center.x << 16;
156
drawPos.y = (ScreenInfo->center.y - 32) << 16;
157
drawPos.x += self->drawOffset.x;
158
drawPos.y += self->drawOffset.y;
159
RSDK.DrawSprite(&self->animator, &drawPos, true);
160
}
161
}
162
void Announcer_State_Countdown(void)
163
{
164
RSDK_THIS(Announcer);
165
166
self->inkEffect = INK_ALPHA;
167
if (self->playerID <= 0) {
168
if (self->timer >= 60) {
169
destroyEntity(self);
170
}
171
else {
172
if (!self->timer) {
173
RSDK.PlaySfx(Announcer->sfxGo, false, 255);
174
RSDK.SetSpriteAnimation(Announcer->aniFrames, 1, &self->animator, true, 3);
175
}
176
177
int32 timer = 0;
178
if (self->timer - 15 > 0)
179
timer = (self->timer - 15) << 9;
180
self->alpha = 0x200 - timer / 45;
181
182
self->timer++;
183
}
184
}
185
else {
186
if (self->timer >= 45) {
187
self->timer = 0;
188
189
self->playerID--;
190
if (!self->playerID) {
191
Announcer->finishedCountdown = true;
192
SceneInfo->timeEnabled = true;
193
}
194
}
195
else {
196
if (!self->timer) {
197
switch (self->playerID) {
198
default: break;
199
200
case 1:
201
RSDK.PlaySfx(Announcer->sfxOne, false, 255);
202
RSDK.SetSpriteAnimation(Announcer->aniFrames, 1, &self->animator, true, 2);
203
break;
204
205
case 2:
206
RSDK.PlaySfx(Announcer->sfxTwo, false, 255);
207
RSDK.SetSpriteAnimation(Announcer->aniFrames, 1, &self->animator, true, 1);
208
break;
209
210
case 3:
211
RSDK.PlaySfx(Announcer->sfxThree, false, 255);
212
RSDK.SetSpriteAnimation(Announcer->aniFrames, 1, &self->animator, true, 0);
213
break;
214
}
215
}
216
self->drawOffset.x = 0;
217
self->drawOffset.y = 0;
218
self->alpha = 0x200 - (self->timer << 9) / 45;
219
self->timer++;
220
}
221
}
222
}
223
void Announcer_State_Finished(void)
224
{
225
RSDK_THIS(Announcer);
226
227
self->scale.x = 0x200;
228
self->scale.y = 0x200;
229
if (self->timer >= 16) {
230
if (self->timer >= 76) {
231
if (self->timer >= 92) {
232
destroyEntity(self);
233
}
234
else {
235
self->visible = true;
236
MathHelpers_Lerp(&self->drawOffset, ((self->timer - 76) << 8) / 16, 0, 0, ScreenInfo->size.x << 16, 0);
237
++self->timer;
238
}
239
}
240
else {
241
++self->timer;
242
self->drawOffset.x = 0;
243
self->drawOffset.y = 0;
244
}
245
}
246
else {
247
self->visible = true;
248
int32 t = 16 * self->timer;
249
int32 xOffset = -TO_FIXED(1) * ScreenInfo->size.x;
250
if (t > 0) {
251
if (t < 256)
252
self->drawOffset.x = xOffset + t * (-xOffset >> 8);
253
else
254
self->drawOffset.x = 0;
255
self->drawOffset.y = 0;
256
}
257
else {
258
self->drawOffset.x = xOffset;
259
self->drawOffset.y = 0;
260
}
261
++self->timer;
262
}
263
}
264
void Announcer_State_AnnounceWinner(void)
265
{
266
RSDK_THIS(Announcer);
267
268
if (self->timer >= 150) {
269
switch (self->playerID) {
270
case 0: RSDK.PlaySfx(Announcer->sfxPlayer1, false, 255); break;
271
case 1: RSDK.PlaySfx(Announcer->sfxPlayer2, false, 255); break;
272
#if MANIA_USE_PLUS
273
case 2: RSDK.PlaySfx(Announcer->sfxPlayer3, false, 255); break;
274
case 3: RSDK.PlaySfx(Announcer->sfxPlayer4, false, 255); break;
275
#endif
276
default: break;
277
}
278
destroyEntity(self);
279
}
280
else {
281
if (self->timer == 30)
282
RSDK.PlaySfx(Announcer->sfxTheWinnerIs, false, 255);
283
284
++self->timer;
285
}
286
}
287
void Announcer_State_AnnounceDraw(void)
288
{
289
RSDK_THIS(Announcer);
290
291
if (self->timer < 30) {
292
self->timer++;
293
}
294
else {
295
if (self->playerID == 0)
296
RSDK.PlaySfx(Announcer->sfxDrawRound, false, 255);
297
else if (self->playerID == 1)
298
RSDK.PlaySfx(Announcer->sfxDrawSet, false, 255);
299
300
destroyEntity(self);
301
}
302
}
303
void Announcer_State_AnnounceWinPlayer(void)
304
{
305
RSDK_THIS(Announcer);
306
307
if (self->timer >= 30) {
308
switch (self->playerID) {
309
case ID_SONIC: RSDK.PlaySfx(Announcer->sfxSonicWins, false, 255); break;
310
case ID_TAILS: RSDK.PlaySfx(Announcer->sfxTailsWins, false, 255); break;
311
case ID_KNUCKLES: RSDK.PlaySfx(Announcer->sfxKnuxWins, false, 255); break;
312
#if MANIA_USE_PLUS
313
case ID_MIGHTY: RSDK.PlaySfx(Announcer->sfxMightyWins, false, 255); break;
314
case ID_RAY: RSDK.PlaySfx(Announcer->sfxRayWins, false, 255); break;
315
#endif
316
default: break;
317
}
318
319
destroyEntity(self);
320
}
321
else {
322
self->timer++;
323
}
324
}
325
326
#if GAME_INCLUDE_EDITOR
327
void Announcer_EditorDraw(void) {}
328
329
void Announcer_EditorLoad(void) {}
330
#endif
331
332
void Announcer_Serialize(void) {}
333
334