Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/SPZ/LottoBall.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: LottoBall Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectLottoBall *LottoBall;
11
12
void LottoBall_Update(void)
13
{
14
RSDK_THIS(LottoBall);
15
16
StateMachine_Run(self->state);
17
18
self->angle += self->angleVel;
19
self->rotation = (self->angle >> 15) & 0x1FF;
20
}
21
22
void LottoBall_LateUpdate(void) {}
23
24
void LottoBall_StaticUpdate(void) {}
25
26
void LottoBall_Draw(void)
27
{
28
RSDK_THIS(LottoBall);
29
30
Vector2 drawPos;
31
if (self->isVisible[SceneInfo->currentScreenID] || (!self->isUIBall && self->state != LottoBall_State_Collected)) {
32
RSDK.DrawSprite(&self->ballAnimator, NULL, self->isUIBall);
33
34
switch (self->type) {
35
case LOTTOBALL_BLUE:
36
case LOTTOBALL_YELLOW:
37
case LOTTOBALL_MULTI:
38
RSDK.DrawSprite(&self->leftNumAnimator, NULL, self->isUIBall);
39
RSDK.DrawSprite(&self->rightNumAnimator, NULL, self->isUIBall);
40
break;
41
42
case LOTTOBALL_EGGMAN: RSDK.DrawSprite(&self->leftNumAnimator, NULL, self->isUIBall); break;
43
44
case LOTTOBALL_BIG:
45
self->drawFX = FX_SCALE | FX_ROTATE;
46
drawPos.x = self->position.x;
47
drawPos.y = self->position.y;
48
drawPos.y += RSDK.Sin256(self->timer) << 10;
49
RSDK.DrawSprite(&self->leftNumAnimator, &drawPos, self->isUIBall);
50
51
self->drawFX = FX_SCALE;
52
break;
53
54
case LOTTOBALL_TOTAL:
55
drawPos = self->position;
56
drawPos.x -= 0x90000;
57
self->rightNumAnimator.frameID = self->lottoNum / 100;
58
RSDK.DrawSprite(&self->rightNumAnimator, &drawPos, self->isUIBall);
59
60
drawPos.x += 0x90000;
61
self->rightNumAnimator.frameID = (self->lottoNum / 10) % 10;
62
RSDK.DrawSprite(&self->rightNumAnimator, &drawPos, self->isUIBall);
63
64
drawPos.x += 0x90000;
65
self->rightNumAnimator.frameID = self->lottoNum % 10;
66
RSDK.DrawSprite(&self->rightNumAnimator, &drawPos, self->isUIBall);
67
break;
68
69
default: break;
70
}
71
}
72
}
73
74
void LottoBall_Create(void *data)
75
{
76
RSDK_THIS(LottoBall);
77
78
if (!SceneInfo->inEditor) {
79
self->drawFX = FX_ROTATE;
80
RSDK.SetSpriteAnimation(LottoBall->aniFrames, 0, &self->ballAnimator, true, self->type);
81
82
switch (self->type) {
83
case LOTTOBALL_BLUE:
84
case LOTTOBALL_YELLOW:
85
RSDK.SetSpriteAnimation(LottoBall->aniFrames, 1, &self->leftNumAnimator, true, self->lottoNum / 10);
86
RSDK.SetSpriteAnimation(LottoBall->aniFrames, 2, &self->rightNumAnimator, true, self->lottoNum % 10);
87
break;
88
89
case LOTTOBALL_MULTI:
90
self->lottoNum %= 10;
91
RSDK.SetSpriteAnimation(LottoBall->aniFrames, 1, &self->leftNumAnimator, true, self->lottoNum % 10);
92
RSDK.SetSpriteAnimation(LottoBall->aniFrames, 2, &self->rightNumAnimator, true, 10);
93
break;
94
95
case LOTTOBALL_EGGMAN: RSDK.SetSpriteAnimation(LottoBall->aniFrames, 1, &self->leftNumAnimator, true, 11); break;
96
97
default: break;
98
}
99
100
self->active = ACTIVE_BOUNDS;
101
self->updateRange.x = 0x400000;
102
self->updateRange.y = 0xE00000;
103
self->gravityStrength = 0x3800;
104
self->visible = true;
105
self->drawGroup = Zone->objectDrawGroup[0];
106
self->startPos = self->position;
107
}
108
}
109
110
void LottoBall_StageLoad(void)
111
{
112
LottoBall->aniFrames = RSDK.LoadSpriteAnimation("SPZ2/LottoBall.bin", SCOPE_STAGE);
113
114
LottoBall->sfxLottoBounce = RSDK.GetSfx("Stage/LottoBounce.wav");
115
LottoBall->sfxSpew = RSDK.GetSfx("Stage/SpewBall.wav");
116
}
117
118
void LottoBall_CheckOffScreen(void)
119
{
120
RSDK_THIS(LottoBall);
121
122
self->angleVel = 0;
123
if (!RSDK.CheckOnScreen(self, NULL) && !RSDK.CheckPosOnScreen(&self->startPos, &self->updateRange)) {
124
self->angle = 0;
125
self->velocity.x = 0;
126
self->velocity.y = 0;
127
self->position = self->startPos;
128
self->active = ACTIVE_BOUNDS;
129
self->state = StateMachine_None;
130
}
131
}
132
133
void LottoBall_State_FallIntoMachine(void)
134
{
135
RSDK_THIS(LottoBall);
136
137
if (self->parent) {
138
if (self->timer) {
139
self->timer--;
140
}
141
else {
142
if (self->position.y >= self->parent->position.y - 0x200000) {
143
self->state = LottoBall_State_InMachine;
144
}
145
else {
146
if (self->position.x >= self->parent->position.x)
147
self->velocity.x -= self->gravityStrength;
148
else
149
self->velocity.x += self->gravityStrength;
150
}
151
152
self->velocity.y += self->gravityStrength;
153
self->position.x += self->velocity.x;
154
self->position.y += self->velocity.y;
155
self->angleVel = self->velocity.x;
156
}
157
}
158
}
159
160
void LottoBall_State_InMachine(void)
161
{
162
RSDK_THIS(LottoBall);
163
164
EntityLottoMachine *parent = self->parent;
165
if (parent) {
166
self->velocity.y += self->gravityStrength;
167
self->position.x += self->velocity.x;
168
self->position.y += self->velocity.y;
169
170
if (self->timer) {
171
self->timer--;
172
}
173
else {
174
int32 vel = (abs(self->velocity.x) + abs(parent->spinSpeed) + abs(self->velocity.y)) >> 1;
175
if (vel > 0x60000) {
176
vel = 0x60000;
177
}
178
else if (vel < 0x30000) {
179
vel = 0x30000;
180
self->timer = RSDK.Rand(16, 32);
181
}
182
183
if (!(Zone->timer & 0xF))
184
RSDK.PlaySfx(LottoBall->sfxLottoBounce, false, 255);
185
186
foreach_active(LottoBall, ball)
187
{
188
if (ball != self) {
189
int32 rx = (self->position.x - ball->position.x) >> 16;
190
int32 ry = (self->position.y - ball->position.y) >> 16;
191
192
if (rx * rx + ry * ry < 0x100) {
193
int32 angle = RSDK.ATan2(rx, ry);
194
self->velocity.x = (vel * RSDK.Cos256(angle)) >> 8;
195
self->velocity.y = (vel * RSDK.Sin256(angle)) >> 8;
196
}
197
}
198
}
199
}
200
201
int32 rx = (self->position.x - parent->position.x) >> 16;
202
int32 ry = (self->position.y - parent->position.y) >> 16;
203
if (rx * rx + ry * ry > 0x1B90) {
204
int32 angle = RSDK.ATan2(rx, (self->position.y - parent->position.y) >> 16);
205
self->position.x = 0x5400 * RSDK.Cos256(angle) + parent->position.x;
206
self->position.y = 0x5400 * RSDK.Sin256(angle) + parent->position.y;
207
switch (((angle + 0x20) & 0xFF) >> 6) {
208
case 0:
209
case 2:
210
self->timer = 8;
211
self->velocity.x = -self->velocity.x >> 1;
212
break;
213
214
case 1:
215
self->velocity.y = -self->velocity.y >> 1;
216
self->velocity.x -= parent->spinSpeed;
217
if (parent->state == LottoMachine_State_Startup) {
218
self->active = ACTIVE_NORMAL;
219
self->state = LottoBall_CheckOffScreen;
220
}
221
break;
222
223
case 3:
224
self->velocity.y = MAX(-self->velocity.y >> 1, 0x10000);
225
self->velocity.x += parent->spinSpeed;
226
break;
227
}
228
}
229
230
if (self->velocity.x >= -0x40000) {
231
if (self->velocity.x > 0x40000)
232
self->velocity.x = 0x40000;
233
self->angleVel = self->velocity.x + self->velocity.y;
234
}
235
else {
236
self->velocity.x = -0x40000;
237
self->angleVel = self->velocity.x + self->velocity.y;
238
}
239
}
240
}
241
242
void LottoBall_State_Collected(void)
243
{
244
RSDK_THIS(LottoBall);
245
246
if (self->parent) {
247
if (self->timer == 8)
248
RSDK.PlaySfx(LottoBall->sfxSpew, false, 0xFF);
249
250
if (self->timer > 16) {
251
self->velocity.y += self->gravityStrength;
252
self->position.y += self->velocity.y;
253
}
254
255
if (++self->timer > 48) {
256
self->drawFX |= FX_SCALE;
257
self->timer = 0;
258
self->isUIBall = true;
259
self->scale.x = 0x200;
260
self->scale.y = 0x200;
261
self->drawGroup = Zone->hudDrawGroup;
262
self->active = ACTIVE_NORMAL;
263
self->state = LottoBall_State_CollectFall;
264
265
RSDK.SetSpriteAnimation(LottoBall->aniFrames, self->ballAnimator.animationID + 3, &self->ballAnimator, true, self->ballAnimator.frameID);
266
RSDK.SetSpriteAnimation(LottoBall->aniFrames, (self->leftNumAnimator.animationID + 3), &self->leftNumAnimator, true,
267
self->leftNumAnimator.frameID);
268
RSDK.SetSpriteAnimation(LottoBall->aniFrames, (self->rightNumAnimator.animationID + 3), &self->rightNumAnimator, true,
269
self->rightNumAnimator.frameID);
270
271
self->position.x = self->bounds.x - 0x1880000;
272
self->position.y = ((ScreenInfo->size.y - 160) << 16);
273
self->velocity.x = 0x80000;
274
self->velocity.y = 0x40000;
275
}
276
}
277
}
278
279
void LottoBall_State_CollectFall(void)
280
{
281
RSDK_THIS(LottoBall);
282
283
if (self->parent) {
284
self->velocity.y += 0x4800;
285
self->position.x += self->velocity.x;
286
self->position.y += self->velocity.y;
287
288
if (self->position.x > self->bounds.x)
289
self->position.x = self->bounds.x;
290
291
if (self->position.y > self->bounds.y) {
292
self->position.y = self->bounds.y;
293
self->velocity.y = -(self->velocity.y >> 1);
294
295
if (self->position.x >= self->bounds.x) {
296
self->position.x = self->bounds.x;
297
self->state = StateMachine_None;
298
}
299
}
300
}
301
}
302
303
void LottoBall_State_SetupUIBall(void)
304
{
305
RSDK_THIS(LottoBall);
306
307
++self->timer;
308
self->position.x += ((ScreenInfo->center.x << 16) - self->position.x) >> 3;
309
310
if (self->timer > 24) {
311
self->scale.x -= (self->scale.x >> 3);
312
self->scale.y -= (self->scale.y >> 3);
313
314
if (self->scale.x < 8) {
315
self->position = self->startPos;
316
self->scale.y = 8;
317
self->scale.x = 8;
318
self->angle = 0;
319
self->velocity.x = 0;
320
self->velocity.y = 0;
321
self->active = ACTIVE_BOUNDS;
322
self->isUIBall = false;
323
self->drawGroup = Zone->objectDrawGroup[0];
324
self->isVisible[0] = false;
325
self->isVisible[1] = false;
326
self->isVisible[2] = false;
327
self->isVisible[3] = false;
328
self->state = LottoBall_State_EnterUIBall;
329
330
RSDK.SetSpriteAnimation(LottoBall->aniFrames, self->ballAnimator.animationID - 3, &self->ballAnimator, true, self->ballAnimator.frameID);
331
RSDK.SetSpriteAnimation(LottoBall->aniFrames, self->leftNumAnimator.animationID - 3, &self->leftNumAnimator, true,
332
self->leftNumAnimator.frameID);
333
RSDK.SetSpriteAnimation(LottoBall->aniFrames, self->rightNumAnimator.animationID - 3, &self->rightNumAnimator, true,
334
self->rightNumAnimator.frameID);
335
}
336
}
337
}
338
339
void LottoBall_State_EnterUIBall(void)
340
{
341
RSDK_THIS(LottoBall);
342
343
self->scale.x += self->scale.x >> 3;
344
self->scale.y += self->scale.y >> 3;
345
346
if (self->scale.x >= 0x200) {
347
self->drawFX &= ~FX_SCALE;
348
self->scale.y = 0x200;
349
self->scale.x = 0x200;
350
self->state = StateMachine_None;
351
}
352
}
353
354
void LottoBall_State_ShowUIBall(void)
355
{
356
RSDK_THIS(LottoBall);
357
358
self->timer += 8;
359
360
int32 scale = MIN(self->scale.x + ((0x214 - self->scale.x) >> 3), 0x200);
361
self->scale.x = scale;
362
self->scale.y = scale;
363
364
if (self->timer > 512) {
365
self->timer = 0;
366
self->type = LOTTOBALL_TOTAL;
367
self->state = LottoBall_State_SetupUIBall;
368
self->lottoNum = abs(self->ringCount);
369
RSDK.SetSpriteAnimation(LottoBall->aniFrames, self->ringCount < 0 ? 8 : 7, &self->rightNumAnimator, true, 0);
370
}
371
}
372
373
#if GAME_INCLUDE_EDITOR
374
void LottoBall_EditorDraw(void)
375
{
376
RSDK_THIS(LottoBall);
377
378
RSDK.SetSpriteAnimation(LottoBall->aniFrames, 0, &self->ballAnimator, true, self->type);
379
380
switch (self->type) {
381
case LOTTOBALL_BLUE:
382
case LOTTOBALL_YELLOW:
383
RSDK.SetSpriteAnimation(LottoBall->aniFrames, 1, &self->leftNumAnimator, true, self->lottoNum / 10);
384
RSDK.SetSpriteAnimation(LottoBall->aniFrames, 2, &self->rightNumAnimator, true, self->lottoNum % 10);
385
break;
386
387
case LOTTOBALL_MULTI:
388
self->lottoNum %= 10;
389
RSDK.SetSpriteAnimation(LottoBall->aniFrames, 1, &self->leftNumAnimator, true, self->lottoNum % 10);
390
RSDK.SetSpriteAnimation(LottoBall->aniFrames, 2, &self->rightNumAnimator, true, 10);
391
break;
392
393
case LOTTOBALL_EGGMAN: RSDK.SetSpriteAnimation(LottoBall->aniFrames, 1, &self->leftNumAnimator, true, 11); break;
394
395
default: break;
396
}
397
398
self->updateRange.x = 0x400000;
399
self->updateRange.y = 0xE00000;
400
self->visible = true;
401
self->drawGroup = Zone->objectDrawGroup[0];
402
403
LottoBall_Draw();
404
}
405
406
void LottoBall_EditorLoad(void)
407
{
408
LottoBall->aniFrames = RSDK.LoadSpriteAnimation("SPZ2/LottoBall.bin", SCOPE_STAGE);
409
410
RSDK_ACTIVE_VAR(LottoBall, type);
411
RSDK_ENUM_VAR("Blue", LOTTOBALL_BLUE);
412
RSDK_ENUM_VAR("Yellow", LOTTOBALL_YELLOW);
413
RSDK_ENUM_VAR("Multiplier", LOTTOBALL_MULTI);
414
RSDK_ENUM_VAR("Eggman", LOTTOBALL_EGGMAN);
415
}
416
#endif
417
418
void LottoBall_Serialize(void)
419
{
420
RSDK_EDITABLE_VAR(LottoBall, VAR_UINT8, type);
421
RSDK_EDITABLE_VAR(LottoBall, VAR_UINT8, lottoNum);
422
}
423
424