Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/SPZ/LottoMachine.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: LottoMachine Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectLottoMachine *LottoMachine;
11
12
void LottoMachine_Update(void)
13
{
14
RSDK_THIS(LottoMachine);
15
16
StateMachine_Run(self->state);
17
18
if (self->chutePos >= self->chuteTargetPos) {
19
if (self->chutePos > self->chuteTargetPos) {
20
self->chutePos -= self->chuteVel;
21
if (self->chutePos < 0)
22
self->chuteAnimator.frameID = 1;
23
}
24
}
25
else {
26
self->chutePos += self->chuteVel;
27
if (self->chutePos > 0)
28
self->chuteAnimator.frameID = 2;
29
}
30
31
self->angle = (self->angle + self->spinSpeed) & 0x1FF0000;
32
}
33
34
void LottoMachine_LateUpdate(void) {}
35
36
void LottoMachine_StaticUpdate(void)
37
{
38
LottoMachine->shineAnimator.frameID = SPZ2Setup->stageLightsFrame;
39
40
foreach_all(LottoMachine, lottoMachine)
41
{
42
int32 slot = RSDK.GetEntitySlot(lottoMachine);
43
RSDK.AddDrawListRef(Zone->objectDrawGroup[0], slot);
44
RSDK.AddDrawListRef(lottoMachine->drawGroupHigh, slot);
45
}
46
}
47
48
void LottoMachine_Draw(void)
49
{
50
RSDK_THIS(LottoMachine);
51
52
Vector2 drawPos;
53
if (SceneInfo->currentDrawGroup == self->drawGroup) {
54
self->direction = FLIP_NONE;
55
self->rotation = self->angle >> 16;
56
RSDK.DrawSprite(&self->supportAnimator, NULL, false);
57
58
self->rotation += 0x80;
59
RSDK.DrawSprite(&self->supportAnimator, NULL, false);
60
61
self->rotation += 0x80;
62
RSDK.DrawSprite(&self->supportAnimator, NULL, false);
63
64
self->rotation += 0x80;
65
RSDK.DrawSprite(&self->supportAnimator, NULL, false);
66
67
self->direction = FLIP_NONE;
68
RSDK.DrawSprite(&self->motorAnimator, NULL, false);
69
70
self->machineAnimator.frameID = 7;
71
RSDK.DrawSprite(&self->machineAnimator, NULL, false);
72
73
self->direction = FLIP_NONE;
74
RSDK.DrawSprite(&self->glassAnimator, NULL, false);
75
76
self->direction = FLIP_X;
77
RSDK.DrawSprite(&self->glassAnimator, NULL, false);
78
79
self->machineAnimator.frameID = 0;
80
self->inkEffect = INK_ADD;
81
self->direction = FLIP_NONE;
82
RSDK.DrawSprite(&self->machineAnimator, NULL, false);
83
84
self->direction = FLIP_X;
85
RSDK.DrawSprite(&self->machineAnimator, NULL, false);
86
87
self->direction = FLIP_NONE;
88
RSDK.DrawSprite(&LottoMachine->shineAnimator, NULL, false);
89
90
self->direction = FLIP_X;
91
RSDK.DrawSprite(&LottoMachine->shineAnimator, NULL, false);
92
93
self->inkEffect = INK_NONE;
94
for (int32 i = 0; i < 3; ++i) {
95
self->direction = FLIP_NONE;
96
self->machineAnimator.frameID = i + 2;
97
RSDK.DrawSprite(&self->machineAnimator, NULL, false);
98
self->direction = FLIP_X;
99
RSDK.DrawSprite(&self->machineAnimator, NULL, false);
100
}
101
}
102
else if (SceneInfo->currentDrawGroup == self->drawGroupHigh) {
103
drawPos.x = self->position.x;
104
drawPos.y = self->position.y + 0x6C0000 + self->chutePos;
105
RSDK.DrawSprite(&self->chuteAnimator, &drawPos, false);
106
}
107
else {
108
self->machineAnimator.frameID = 8;
109
self->direction = FLIP_NONE;
110
RSDK.DrawSprite(&self->machineAnimator, NULL, false);
111
112
self->direction = FLIP_X;
113
RSDK.DrawSprite(&self->machineAnimator, NULL, false);
114
115
self->direction = FLIP_Y;
116
RSDK.DrawSprite(&self->machineAnimator, NULL, false);
117
118
self->direction = FLIP_XY;
119
RSDK.DrawSprite(&self->machineAnimator, NULL, false);
120
121
self->direction = FLIP_NONE;
122
}
123
}
124
125
void LottoMachine_Create(void *data)
126
{
127
RSDK_THIS(LottoMachine);
128
129
RSDK.SetSpriteAnimation(LottoMachine->aniFrames, 0, &self->machineAnimator, true, 0);
130
RSDK.SetSpriteAnimation(LottoMachine->aniFrames, 1, &self->supportAnimator, true, 0);
131
RSDK.SetSpriteAnimation(LottoMachine->aniFrames, 2, &self->chuteAnimator, true, 0);
132
RSDK.SetSpriteAnimation(LottoMachine->aniFrames, 3, &self->motorAnimator, true, 0);
133
RSDK.SetSpriteAnimation(LottoMachine->aniFrames, 4, &self->glassAnimator, true, 0);
134
135
if (SceneInfo->inEditor) {
136
self->drawFX = FX_FLIP;
137
}
138
else {
139
self->active = ACTIVE_BOUNDS;
140
self->updateRange.x = 0x1000000;
141
self->updateRange.y = 0x1000000;
142
self->visible = true;
143
self->drawGroup = Zone->objectDrawGroup[1] + 1;
144
self->alpha = 160;
145
self->drawFX = FX_ROTATE | FX_FLIP;
146
self->chuteTargetPos = 0x180000;
147
self->chutePos = 0x180000;
148
self->drawGroupHigh = Zone->objectDrawGroup[1];
149
self->motorAnimator.speed = 0;
150
self->state = LottoMachine_State_Startup;
151
}
152
}
153
154
void LottoMachine_StageLoad(void)
155
{
156
LottoMachine->aniFrames = RSDK.LoadSpriteAnimation("SPZ2/LottoMachine.bin", SCOPE_STAGE);
157
RSDK.SetSpriteAnimation(LottoMachine->aniFrames, 5, &LottoMachine->shineAnimator, true, 0);
158
159
LottoMachine->hitboxBottom.left = -16;
160
LottoMachine->hitboxBottom.top = 124;
161
LottoMachine->hitboxBottom.right = 16;
162
LottoMachine->hitboxBottom.bottom = 160;
163
164
LottoMachine->hitboxMotor.left = -48;
165
LottoMachine->hitboxMotor.top = 92;
166
LottoMachine->hitboxMotor.right = 48;
167
LottoMachine->hitboxMotor.bottom = 124;
168
169
LottoMachine->active = ACTIVE_ALWAYS;
170
171
LottoMachine->sfxPimPom = RSDK.GetSfx("Stage/PimPom.wav");
172
LottoMachine->sfxFail = RSDK.GetSfx("Stage/Fail.wav");
173
174
Zone_AddVSSwapCallback(LottoMachine_VSSwap_CheckBusy);
175
}
176
177
void LottoMachine_VSSwap_CheckBusy(void)
178
{
179
#if MANIA_USE_PLUS
180
if ((1 << Zone->swapPlayerID) & LottoMachine->activePlayers)
181
Zone->playerSwapEnabled[Zone->swapPlayerID] = false;
182
#else
183
if (LottoMachine->activePlayers)
184
Zone->playerSwapEnabled = false;
185
#endif
186
}
187
188
void LottoMachine_CheckPlayerCollisions(void)
189
{
190
RSDK_THIS(LottoMachine);
191
192
foreach_active(Player, player)
193
{
194
int32 playerID = RSDK.GetEntitySlot(player);
195
196
if (self->playerAngles[playerID] <= 0) {
197
// Inside the Machine
198
if (RSDK.CheckObjectCollisionTouchCircle(self, 0x600000, player, 0x100000)) {
199
200
bool32 playerMatch = false;
201
for (int32 p = 0; p < self->playerCount; ++p) {
202
EntityPlayer *playerPtr = self->playerPtrs[p];
203
if (player == playerPtr)
204
playerMatch = true;
205
}
206
207
if (!playerMatch) {
208
if ((!player->sidekick || self->playerCount) && (!self->collectedBallCount || player->sidekick)) {
209
if (self->playerCount < Player->playerCount) {
210
if (!self->playerCount)
211
self->playerDir = player->direction;
212
213
self->playerPtrs[self->playerCount++] = player;
214
215
if (Zone->cameraBoundsB[playerID] != (self->position.y >> 16) + 160) {
216
self->playerTimers[playerID] = Zone->cameraBoundsB[playerID];
217
Zone->cameraBoundsB[playerID] = (self->position.y >> 16) + 160;
218
}
219
220
LottoMachine->activePlayers |= 1 << playerID;
221
if (!self->timer)
222
self->timer = 1;
223
}
224
}
225
else {
226
player->velocity.x = 0;
227
player->velocity.y = -0xA0000;
228
player->applyJumpCap = false;
229
self->playerAngles[playerID] = 16;
230
RSDK.PlaySfx(Player->sfxRelease, false, 255);
231
RSDK.PlaySfx(LottoMachine->sfxFail, false, 255);
232
}
233
}
234
}
235
else if (RSDK.CheckObjectCollisionTouchCircle(self, 0x730000, player, 0x100000)) { // Outside of the machine
236
int32 angle = RSDK.ATan2(player->position.x - self->position.x, player->position.y - self->position.y);
237
int32 vel = MAX((abs(player->velocity.x) + abs(player->velocity.y)) >> 8, 0x400);
238
int32 radius = RSDK.Rand(512, vel);
239
240
angle += RSDK.Rand(-6, 6);
241
int32 velX = radius * RSDK.Cos256(angle);
242
int32 velY = radius * RSDK.Sin256(angle);
243
244
if ((player->characterID == ID_KNUCKLES && player->animator.animationID == ANI_GLIDE) || player->state == Player_State_FlyCarried
245
#if MANIA_USE_PLUS
246
|| player->state == Player_State_RayGlide
247
#endif
248
) {
249
if (player->state == Player_State_FlyCarried)
250
RSDK_GET_ENTITY(SLOT_PLAYER2, Player)->flyCarryTimer = 30;
251
player->state = Player_State_Air;
252
RSDK.SetSpriteAnimation(player->aniFrames, ANI_JUMP, &player->animator, true, 0);
253
}
254
255
player->groundVel = velX;
256
player->velocity.x = velX;
257
player->velocity.y = velY;
258
player->onGround = false;
259
player->applyJumpCap = false;
260
self->playerAngles[playerID] = 8;
261
RSDK.PlaySfx(LottoMachine->sfxPimPom, false, 255);
262
}
263
}
264
else {
265
--self->playerAngles[playerID];
266
}
267
}
268
}
269
270
void LottoMachine_CheckPlayerCollisions_Bottom(void)
271
{
272
RSDK_THIS(LottoMachine);
273
274
foreach_active(Player, player)
275
{
276
if (!player->sidekick || self->playerCount) {
277
if (Player_CheckCollisionTouch(player, self, &LottoMachine->hitboxBottom)) {
278
bool32 hasPlayer = false;
279
for (int32 p = 0; p < self->playerCount; ++p) {
280
EntityPlayer *playerPtr = self->playerPtrs[p];
281
if (player == playerPtr)
282
hasPlayer = true;
283
}
284
285
if (!hasPlayer) {
286
if (self->playerCount < Player->playerCount) {
287
if (!self->playerCount)
288
self->playerDir = player->direction;
289
290
self->playerPtrs[self->playerCount++] = player;
291
player->state = Player_State_Static;
292
player->position.x = self->position.x;
293
player->position.y = self->position.y + 0x980000;
294
player->velocity.x = 0;
295
player->velocity.y = 0;
296
297
RSDK.SetSpriteAnimation(player->aniFrames, ANI_JUMP, &player->animator, true, 0);
298
RSDK.PlaySfx(Player->sfxRoll, false, 255);
299
LottoMachine->activePlayers |= 1 << player->playerID;
300
301
if (!self->timer)
302
self->timer = 1;
303
}
304
}
305
}
306
}
307
}
308
}
309
310
void LottoMachine_HandleMotor(void)
311
{
312
RSDK_THIS(LottoMachine);
313
314
int32 vel = 0;
315
for (int32 p = 0; p < self->playerCount; ++p) {
316
EntityPlayer *player = self->playerPtrs[p];
317
if (player) {
318
if (player->state != Player_State_Death) {
319
player->position.x = self->position.x;
320
Player_CheckCollisionPlatform(player, self, &LottoMachine->hitboxMotor);
321
player->direction = self->playerDir;
322
player->jumpAbilityState = 0;
323
324
if (player->onGround) {
325
vel += player->groundVel;
326
327
if (self->playerDir) {
328
if (player->groundVel > -0x10000)
329
player->groundVel = -0x10000;
330
}
331
else if (player->groundVel < 0x10000) {
332
player->groundVel = 0x10000;
333
}
334
}
335
}
336
}
337
}
338
339
if (self->playerDir) {
340
if (self->spinSpeed < -0x10000) {
341
self->spinSpeed += 0x800;
342
if (self->spinSpeed > -0x10000)
343
self->spinSpeed = -0x10000;
344
}
345
346
if (vel < self->spinSpeed)
347
self->spinSpeed = vel;
348
349
self->motorAnimator.speed = -self->spinSpeed >> 11;
350
}
351
else {
352
if (self->spinSpeed > 0x10000) {
353
self->spinSpeed -= 0x800;
354
if (self->spinSpeed < 0x10000)
355
self->spinSpeed = 0x10000;
356
}
357
358
if (vel > self->spinSpeed)
359
self->spinSpeed = vel;
360
361
self->motorAnimator.speed = self->spinSpeed >> 11;
362
}
363
364
if (self->motorAnimator.speed > 0x80)
365
self->motorAnimator.speed = 0x80;
366
}
367
368
void LottoMachine_SetupBalls(void)
369
{
370
RSDK_THIS(LottoMachine);
371
372
foreach_active(LottoBall, ball)
373
{
374
if (abs(ball->position.x - self->position.x) < 0x900000 && abs(ball->position.y - self->position.y) < 0x900000) {
375
ball->state = LottoBall_State_FallIntoMachine;
376
ball->parent = self;
377
ball->timer = 16;
378
}
379
}
380
}
381
382
void LottoMachine_SetupUIBalls(void)
383
{
384
RSDK_THIS(LottoMachine);
385
386
foreach_active(LottoBall, ball)
387
{
388
if (ball->isUIBall) {
389
if (ball->isVisible[RSDK.GetEntitySlot(self->playerPtrs[0])])
390
ball->state = LottoBall_State_SetupUIBall;
391
}
392
}
393
}
394
395
void LottoMachine_GiveRings(void)
396
{
397
RSDK_THIS(LottoMachine);
398
399
int32 multiplier = 1;
400
int32 bonus = 0;
401
402
int32 playerCount = 0;
403
for (int32 p = 0; p < PLAYER_COUNT; ++p) {
404
uint8 reward = self->collectedBallTypes[p] & 0xFF;
405
switch (self->collectedBallTypes[p] >> 8) {
406
case LOTTOBALL_BLUE:
407
case LOTTOBALL_YELLOW: bonus += reward; break;
408
case LOTTOBALL_MULTI: multiplier *= reward; break;
409
case LOTTOBALL_EGGMAN: ++playerCount; break;
410
default: break;
411
}
412
}
413
int32 reward = bonus * multiplier;
414
415
for (int32 p = 0; p < self->playerCount; ++p) {
416
EntityPlayer *player = self->playerPtrs[p];
417
if (player->state != Player_State_Death && !player->sidekick) {
418
int32 rings = 0;
419
int32 count = reward;
420
421
if (playerCount == 4) {
422
rings = player->rings;
423
}
424
else if (playerCount > 0) {
425
rings = player->rings - (player->rings >> playerCount);
426
if (!player->rings)
427
count = reward >> playerCount;
428
}
429
430
int32 ringCount = count - rings * multiplier;
431
Player_GiveRings(player, ringCount, false);
432
433
if (ringCount > 0) {
434
RSDK.PlaySfx(Ring->sfxRing, false, 0xFF);
435
}
436
else if (!ringCount) {
437
RSDK.PlaySfx(LottoMachine->sfxFail, false, 0xFF);
438
}
439
else if (ringCount < 0) {
440
Vector2 pos;
441
pos.x = self->position.x;
442
pos.y = self->position.y + 0x540000;
443
Ring_FakeLoseRings(&pos, -ringCount, self->drawGroup);
444
RSDK.PlaySfx(Player->sfxLoseRings, false, 255);
445
player->state = Player_State_Hurt;
446
RSDK.SetSpriteAnimation(player->aniFrames, ANI_HURT, &player->animator, false, 0);
447
player->velocity.y = -0x40000;
448
player->onGround = false;
449
player->nextAirState = StateMachine_None;
450
player->nextGroundState = StateMachine_None;
451
}
452
453
EntityLottoBall *ball = CREATE_ENTITY(LottoBall, NULL, ScreenInfo->center.x << 16, (ScreenInfo->size.y - 48) << 16);
454
ball->type = LOTTOBALL_BIG;
455
ball->isUIBall = true;
456
ball->ringCount = ringCount;
457
ball->drawGroup = Zone->hudDrawGroup;
458
ball->active = ACTIVE_NORMAL;
459
ball->drawFX = FX_SCALE;
460
ball->state = LottoBall_State_ShowUIBall;
461
ball->isVisible[player->playerID] = true;
462
if (ringCount <= 0)
463
ball->angle = 0x800000;
464
465
RSDK.SetSpriteAnimation(LottoBall->aniFrames, 6, &ball->ballAnimator, true, 0);
466
RSDK.SetSpriteAnimation(LottoBall->aniFrames, 6, &ball->leftNumAnimator, true, 1);
467
}
468
}
469
}
470
471
void LottoMachine_State_Startup(void)
472
{
473
RSDK_THIS(LottoMachine);
474
475
LottoMachine_CheckPlayerCollisions();
476
LottoMachine_CheckPlayerCollisions_Bottom();
477
LottoMachine_HandleMotor();
478
479
if (self->timer > 0) {
480
self->timer++;
481
if (self->timer > 60) {
482
self->timer = 0;
483
RSDK.PlaySfx(Player->sfxRelease, false, 0xFF);
484
485
for (int32 p = 0; p < self->playerCount; ++p) {
486
EntityPlayer *player = self->playerPtrs[p];
487
488
if (player && player->state != Player_State_Death) {
489
int32 playerID = RSDK.GetEntitySlot(player);
490
if (player->state == Player_State_Static) {
491
player->state = Player_State_Air;
492
player->velocity.x = 0;
493
player->velocity.y = -0x98000;
494
player->applyJumpCap = false;
495
self->playerAngles[playerID] = 32;
496
}
497
498
if (Zone->cameraBoundsB[playerID] != (self->position.y >> 16) + 160) {
499
self->playerTimers[playerID] = Zone->cameraBoundsB[playerID];
500
Zone->cameraBoundsB[playerID] = ((self->position.y >> 16) + 160);
501
}
502
}
503
}
504
505
LottoMachine_SetupBalls();
506
self->chuteVel = 0x10000;
507
self->spinSpeed = !self->playerDir ? 0x10000 : -0x10000;
508
self->chuteTargetPos = 0x80000;
509
self->state = LottoMachine_State_HandleBallCollect;
510
}
511
}
512
}
513
514
void LottoMachine_State_HandleBallCollect(void)
515
{
516
RSDK_THIS(LottoMachine);
517
518
LottoMachine_CheckPlayerCollisions();
519
LottoMachine_HandleMotor();
520
521
RSDK.ProcessAnimation(&self->motorAnimator);
522
self->glassAnimator.frameID = self->motorAnimator.frameID;
523
524
switch (self->collectedBallCount) {
525
case 0:
526
if (++self->timer == 240) {
527
self->timer = 0;
528
self->chuteVel = 0x20000;
529
self->chuteTargetPos = -0x180000;
530
self->drawGroupHigh = Zone->objectDrawGroup[0] + 1;
531
self->state = LottoMachine_State_CollectBall;
532
}
533
break;
534
535
case 1:
536
case 2:
537
case 3:
538
if (++self->timer == 32) {
539
self->timer = 0;
540
self->chuteVel = 0x20000;
541
self->chuteTargetPos = -0x180000;
542
self->state = LottoMachine_State_CollectBall;
543
}
544
break;
545
546
case 4:
547
if (++self->timer == 96) {
548
self->timer = 0;
549
self->collectedBallCount = 5;
550
LottoMachine_SetupUIBalls();
551
}
552
break;
553
554
case 5:
555
if (++self->timer == 32) {
556
self->timer = 0;
557
self->collectedBallCount = 6;
558
LottoMachine_GiveRings();
559
}
560
break;
561
562
case 6:
563
if (++self->timer == 64) {
564
self->timer = 0;
565
self->chuteVel = 0x20000;
566
self->chuteTargetPos = -0x180000;
567
self->drawGroupHigh = Zone->objectDrawGroup[1];
568
self->state = LottoMachine_State_DropPlayers;
569
}
570
break;
571
572
default: break;
573
}
574
}
575
576
void LottoMachine_State_CollectBall(void)
577
{
578
RSDK_THIS(LottoMachine);
579
580
LottoMachine_CheckPlayerCollisions();
581
LottoMachine_HandleMotor();
582
583
RSDK.ProcessAnimation(&self->motorAnimator);
584
self->glassAnimator.frameID = self->motorAnimator.frameID;
585
586
if (self->timer == 20) {
587
int32 dist = 10000;
588
EntityLottoBall *ballPtr = NULL;
589
590
foreach_active(LottoBall, ball)
591
{
592
if (abs(ball->position.x - self->position.x) < 0x900000) {
593
if (abs(ball->position.y - self->position.y) < 0x900000) {
594
int32 rx = (self->position.x - ball->position.x) >> 16;
595
int32 ry = (self->position.y - ball->position.y + 0x540000) >> 16;
596
if (rx * rx + ry * ry < dist) {
597
dist = rx * rx + ry * ry;
598
ballPtr = ball;
599
}
600
}
601
}
602
}
603
604
if (ballPtr) {
605
ballPtr->position.x = self->position.x;
606
ballPtr->position.y = self->position.y + 0x540000;
607
ballPtr->velocity.x = 0;
608
ballPtr->velocity.y = 0;
609
ballPtr->angle = 0;
610
ballPtr->angleVel = 0;
611
ballPtr->bounds.x = (ScreenInfo->center.x - (self->collectedBallCount << 6) + 96) << 16;
612
ballPtr->bounds.y = (ScreenInfo->size.y - 48) << 16;
613
ballPtr->timer = 0;
614
ballPtr->isVisible[0] = false;
615
616
for (int32 p = 0; p < self->playerCount; ++p) {
617
EntityPlayer *player = self->playerPtrs[p];
618
if (player)
619
ballPtr->isVisible[RSDK.GetEntitySlot(player)] = true;
620
}
621
622
ballPtr->state = LottoBall_State_Collected;
623
self->collectedBallTypes[self->collectedBallCount++] = ballPtr->lottoNum + (ballPtr->type << 8);
624
}
625
}
626
627
if (++self->timer == 32) {
628
self->timer = 0;
629
self->chuteVel = 0x40000;
630
self->chuteTargetPos = 0x180000;
631
self->state = LottoMachine_State_HandleBallCollected;
632
}
633
}
634
635
void LottoMachine_State_HandleBallCollected(void)
636
{
637
RSDK_THIS(LottoMachine);
638
639
LottoMachine_CheckPlayerCollisions();
640
LottoMachine_HandleMotor();
641
642
RSDK.ProcessAnimation(&self->motorAnimator);
643
self->glassAnimator.frameID = self->motorAnimator.frameID;
644
645
if (self->chutePos == self->chuteTargetPos) {
646
self->chuteVel = 0x10000;
647
self->chuteTargetPos = 0x80000;
648
self->state = LottoMachine_State_HandleBallCollect;
649
}
650
}
651
652
void LottoMachine_State_DropPlayers(void)
653
{
654
RSDK_THIS(LottoMachine);
655
656
LottoMachine_CheckPlayerCollisions();
657
LottoMachine_HandleMotor();
658
659
RSDK.ProcessAnimation(&self->motorAnimator);
660
self->glassAnimator.frameID = self->motorAnimator.frameID;
661
662
if (self->chutePos == self->chuteTargetPos) {
663
bool32 onGround = true;
664
for (int32 p = 0; p < self->playerCount; ++p) {
665
EntityPlayer *player = self->playerPtrs[p];
666
if (player && !player->onGround)
667
onGround = false;
668
}
669
670
if (onGround) {
671
for (int32 p = 0; p < self->playerCount; ++p) {
672
EntityPlayer *player = self->playerPtrs[p];
673
674
if (player && player->state != Player_State_Death) {
675
player->state = Player_State_Static;
676
player->nextAirState = StateMachine_None;
677
player->velocity.x = 0;
678
player->velocity.y = 0;
679
player->groundVel = 0;
680
player->onGround = false;
681
player->applyJumpCap = false;
682
RSDK.SetSpriteAnimation(player->aniFrames, ANI_JUMP, &player->animator, true, 0);
683
int32 playerID = RSDK.GetEntitySlot(player);
684
Zone->cameraBoundsB[playerID] = self->playerTimers[playerID];
685
}
686
}
687
688
self->state = LottoMachine_State_ReleasePlayers;
689
}
690
}
691
}
692
693
void LottoMachine_State_ReleasePlayers(void)
694
{
695
RSDK_THIS(LottoMachine);
696
697
LottoMachine_CheckPlayerCollisions();
698
699
self->spinSpeed -= self->spinSpeed >> 4;
700
self->motorAnimator.speed -= self->motorAnimator.speed >> 4;
701
702
RSDK.ProcessAnimation(&self->motorAnimator);
703
self->glassAnimator.frameID = self->motorAnimator.frameID;
704
705
if (++self->timer == 60) {
706
self->timer = 0;
707
self->chuteVel = 0x40000;
708
self->chuteTargetPos = 0x180000;
709
self->state = LottoMachine_State_StopSpinning;
710
711
for (int32 p = 0; p < self->playerCount; ++p) {
712
EntityPlayer *player = self->playerPtrs[p];
713
714
if (player && player->state != Player_State_Death) {
715
player->state = Player_State_Air;
716
player->velocity.y = 0x40000;
717
LottoMachine->activePlayers &= ~(1 << RSDK.GetEntitySlot(player));
718
RSDK.PlaySfx(Player->sfxRelease, false, 0xFF);
719
self->playerAngles[RSDK.GetEntitySlot(player)] = 32;
720
}
721
}
722
}
723
}
724
725
void LottoMachine_State_StopSpinning(void)
726
{
727
RSDK_THIS(LottoMachine);
728
729
LottoMachine_CheckPlayerCollisions();
730
++self->timer;
731
732
self->spinSpeed -= (self->spinSpeed >> 4);
733
self->motorAnimator.speed -= self->motorAnimator.speed >> 4;
734
735
if (self->timer == 30) {
736
for (int32 p = 0; p < PLAYER_COUNT; ++p) self->playerPtrs[p] = NULL;
737
self->playerCount = 0;
738
self->collectedBallCount = 0;
739
self->chuteAnimator.frameID = 0;
740
self->timer = 0;
741
self->spinSpeed = 0;
742
self->state = LottoMachine_State_Startup;
743
}
744
}
745
746
#if GAME_INCLUDE_EDITOR
747
void LottoMachine_EditorDraw(void)
748
{
749
RSDK_THIS(LottoMachine);
750
Vector2 drawPos;
751
752
self->machineAnimator.frameID = 8;
753
self->direction = FLIP_NONE;
754
RSDK.DrawSprite(&self->machineAnimator, NULL, false);
755
756
self->direction = FLIP_X;
757
RSDK.DrawSprite(&self->machineAnimator, NULL, false);
758
759
self->direction = FLIP_Y;
760
RSDK.DrawSprite(&self->machineAnimator, NULL, false);
761
762
self->direction = FLIP_XY;
763
RSDK.DrawSprite(&self->machineAnimator, NULL, false);
764
765
self->direction = FLIP_NONE;
766
767
drawPos.x = self->position.x;
768
drawPos.y = self->position.y + 0x6C0000 + self->chutePos;
769
RSDK.DrawSprite(&self->chuteAnimator, &drawPos, false);
770
771
self->direction = FLIP_NONE;
772
self->rotation = self->angle >> 16;
773
RSDK.DrawSprite(&self->supportAnimator, NULL, false);
774
775
self->rotation += 0x80;
776
RSDK.DrawSprite(&self->supportAnimator, NULL, false);
777
778
self->rotation += 0x80;
779
RSDK.DrawSprite(&self->supportAnimator, NULL, false);
780
781
self->rotation += 0x80;
782
RSDK.DrawSprite(&self->supportAnimator, NULL, false);
783
784
self->direction = FLIP_NONE;
785
RSDK.DrawSprite(&self->motorAnimator, NULL, false);
786
787
self->machineAnimator.frameID = 7;
788
RSDK.DrawSprite(&self->machineAnimator, NULL, false);
789
790
self->direction = FLIP_NONE;
791
RSDK.DrawSprite(&self->glassAnimator, NULL, false);
792
793
self->direction = FLIP_X;
794
RSDK.DrawSprite(&self->glassAnimator, NULL, false);
795
796
self->machineAnimator.frameID = 0;
797
self->inkEffect = INK_ADD;
798
self->direction = FLIP_NONE;
799
RSDK.DrawSprite(&self->machineAnimator, NULL, false);
800
801
self->direction = FLIP_X;
802
RSDK.DrawSprite(&self->machineAnimator, NULL, false);
803
804
self->direction = FLIP_NONE;
805
RSDK.DrawSprite(&LottoMachine->shineAnimator, NULL, false);
806
807
self->direction = FLIP_X;
808
RSDK.DrawSprite(&LottoMachine->shineAnimator, NULL, false);
809
810
self->inkEffect = INK_NONE;
811
for (int32 i = 0; i < 3; ++i) {
812
self->direction = FLIP_NONE;
813
self->machineAnimator.frameID = i + 2;
814
RSDK.DrawSprite(&self->machineAnimator, NULL, false);
815
self->direction = FLIP_X;
816
RSDK.DrawSprite(&self->machineAnimator, NULL, false);
817
}
818
}
819
820
void LottoMachine_EditorLoad(void) { LottoMachine->aniFrames = RSDK.LoadSpriteAnimation("SPZ2/LottoMachine.bin", SCOPE_STAGE); }
821
#endif
822
823
void LottoMachine_Serialize(void) {}
824
825