Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/Global/EggPrison.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: EggPrison Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectEggPrison *EggPrison;
11
12
void EggPrison_Update(void)
13
{
14
RSDK_THIS(EggPrison);
15
16
StateMachine_Run(self->state);
17
18
if (self->type == EGGPRISON_FLYING) {
19
RSDK.ProcessAnimation(&self->propellerAnimator);
20
21
EggPrison_HandleMovement();
22
23
if (!self->notSolid) {
24
foreach_active(Player, player)
25
{
26
if (Player_CheckCollisionBox(player, self, &self->hitboxSolid) == C_TOP) {
27
player->position.x += self->velocity.x;
28
player->position.y += TO_FIXED(1);
29
}
30
31
if (self->state == EggPrison_State_Idle) {
32
if (Player_CheckCollisionBox(player, self, &self->hitboxButton) == C_BOTTOM) {
33
self->velocity.x = 0;
34
self->active = ACTIVE_NORMAL;
35
self->state = EggPrison_State_Opened;
36
self->buttonPos = -TO_FIXED(8);
37
}
38
else {
39
if (!Player_CheckCollisionTouch(player, self, &self->hitboxButtonTrigger)) {
40
if (self->buttonPos < 0)
41
self->buttonPos += TO_FIXED(1);
42
}
43
else {
44
Hitbox *playerHitbox = Player_GetHitbox(player);
45
self->buttonPos = TO_FIXED(playerHitbox->top - 48) - self->position.y + player->position.y;
46
self->buttonPos = CLAMP(self->buttonPos, -TO_FIXED(8), 0);
47
self->buttonPos &= 0xFFFF0000;
48
}
49
}
50
}
51
else {
52
Player_CheckCollisionBox(player, self, &self->hitboxButton);
53
}
54
}
55
}
56
}
57
else {
58
if (!self->notSolid) {
59
foreach_active(Player, player)
60
{
61
Player_CheckCollisionBox(player, self, &self->hitboxSolid);
62
63
if (self->state == EggPrison_State_Idle) {
64
if (Player_CheckCollisionBox(player, self, &self->hitboxButton) == C_TOP) {
65
self->buttonPos = TO_FIXED(8);
66
67
if (self->type < EGGPRISON_DUD)
68
SceneInfo->timeEnabled = false;
69
70
if (self->type == EGGPRISON_SPRING) {
71
int32 anim = player->animator.animationID;
72
if (anim == ANI_WALK || (anim > ANI_AIR_WALK && anim <= ANI_DASH))
73
player->animationReserve = player->animator.animationID;
74
else
75
player->animationReserve = ANI_WALK;
76
player->state = Player_State_Air;
77
player->onGround = false;
78
player->velocity.y = -TO_FIXED(10);
79
RSDK.SetSpriteAnimation(player->aniFrames, ANI_SPRING_TWIRL, &player->animator, true, 0);
80
RSDK.PlaySfx(EggPrison->sfxSpring, false, 255);
81
}
82
else {
83
self->active = ACTIVE_NORMAL;
84
self->state = EggPrison_State_Opened;
85
}
86
}
87
else {
88
if (Player_CheckCollisionTouch(player, self, &self->hitboxButtonTrigger)) {
89
Hitbox *playerHitbox = Player_GetHitbox(player);
90
91
self->buttonPos = TO_FIXED(playerHitbox->bottom + 48) - self->position.y + player->position.y;
92
self->buttonPos = CLAMP(self->buttonPos, 0, TO_FIXED(8));
93
self->buttonPos &= 0xFFFF0000;
94
}
95
else if (self->buttonPos > 0)
96
self->buttonPos -= TO_FIXED(1);
97
}
98
}
99
else {
100
Player_CheckCollisionBox(player, self, &self->hitboxButton);
101
}
102
}
103
}
104
}
105
}
106
107
void EggPrison_LateUpdate(void) {}
108
109
void EggPrison_StaticUpdate(void) {}
110
111
void EggPrison_Draw(void)
112
{
113
RSDK_THIS(EggPrison);
114
115
Vector2 drawPos;
116
if (self->type == EGGPRISON_FLYING) {
117
self->direction = FLIP_Y;
118
drawPos.x = self->position.x;
119
drawPos.y = self->position.y + self->buttonPos;
120
RSDK.DrawSprite(&self->buttonAnimator, &drawPos, false);
121
122
self->direction = FLIP_NONE;
123
RSDK.DrawSprite(&self->capsuleAnimator, NULL, false);
124
RSDK.DrawSprite(&self->panelAnimator, NULL, false);
125
RSDK.DrawSprite(&self->propellerAnimator, NULL, false);
126
127
self->direction = FLIP_X;
128
RSDK.DrawSprite(&self->propellerAnimator, NULL, false);
129
130
self->direction = FLIP_NONE;
131
}
132
else {
133
drawPos.x = self->position.x;
134
drawPos.y = self->position.y + self->buttonPos;
135
RSDK.DrawSprite(&self->buttonAnimator, &drawPos, false);
136
RSDK.DrawSprite(&self->capsuleAnimator, NULL, false);
137
RSDK.DrawSprite(&self->panelAnimator, NULL, false);
138
}
139
}
140
141
void EggPrison_Create(void *data)
142
{
143
RSDK_THIS(EggPrison);
144
145
if (globals->gameMode < MODE_TIMEATTACK || self->type >= EGGPRISON_FLYING) {
146
self->drawFX = FX_FLIP;
147
148
if (!SceneInfo->inEditor) {
149
if (data)
150
self->type = VOID_TO_INT(data);
151
152
if (self->type == EGGPRISON_FLYING) {
153
RSDK.SetSpriteAnimation(EggPrison->aniFrames, 0, &self->capsuleAnimator, true, 1);
154
RSDK.SetSpriteAnimation(EggPrison->aniFrames, 1, &self->buttonAnimator, true, 0);
155
RSDK.SetSpriteAnimation(EggPrison->aniFrames, 2, &self->panelAnimator, true, 1);
156
RSDK.SetSpriteAnimation(EggPrison->aniFrames, 3, &self->propellerAnimator, true, 0);
157
158
self->hitboxButton.left = -16;
159
self->hitboxButton.top = 24;
160
self->hitboxButton.right = 16;
161
self->hitboxButton.bottom = 38;
162
163
self->hitboxButtonTrigger.left = -15;
164
self->hitboxButtonTrigger.top = 24;
165
self->hitboxButtonTrigger.right = 15;
166
self->hitboxButtonTrigger.bottom = 48;
167
168
self->velocity.x = 0x10000;
169
self->velocity.y = 0x4000;
170
}
171
else {
172
RSDK.SetSpriteAnimation(EggPrison->aniFrames, 0, &self->capsuleAnimator, true, 0);
173
RSDK.SetSpriteAnimation(EggPrison->aniFrames, 1, &self->buttonAnimator, true, 0);
174
RSDK.SetSpriteAnimation(EggPrison->aniFrames, 2, &self->panelAnimator, true, 0);
175
176
self->hitboxButton.left = -16;
177
self->hitboxButton.top = -38;
178
self->hitboxButton.right = 16;
179
self->hitboxButton.bottom = -24;
180
181
self->hitboxButtonTrigger.left = -15;
182
self->hitboxButtonTrigger.top = -48;
183
self->hitboxButtonTrigger.right = 15;
184
self->hitboxButtonTrigger.top = -24;
185
}
186
self->hitboxSolid.left = -32;
187
self->hitboxSolid.top = -24;
188
self->hitboxSolid.right = 32;
189
self->hitboxSolid.bottom = 32;
190
191
self->state = EggPrison_State_Init;
192
self->active = ACTIVE_BOUNDS;
193
self->updateRange.x = TO_FIXED(128);
194
self->updateRange.y = TO_FIXED(128);
195
self->visible = true;
196
self->drawGroup = Zone->objectDrawGroup[0];
197
}
198
}
199
else {
200
destroyEntity(self);
201
}
202
}
203
204
void EggPrison_StageLoad(void)
205
{
206
EggPrison->aniFrames = RSDK.LoadSpriteAnimation("Global/EggPrison.bin", SCOPE_STAGE);
207
208
EggPrison->sfxDestroy = RSDK.GetSfx("Global/Destroy.wav");
209
EggPrison->sfxSpring = RSDK.GetSfx("Global/Spring.wav");
210
}
211
212
void EggPrison_HandleMovement(void)
213
{
214
RSDK_THIS(EggPrison);
215
216
bool32 hitFloor = false;
217
if (self->checkTileCollisions) {
218
if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, -TO_FIXED(48), TO_FIXED(144), false)
219
|| RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_FLOOR, 0, TO_FIXED(48), TO_FIXED(144), false)) {
220
self->originY -= self->velocity.y;
221
hitFloor = true;
222
}
223
}
224
225
if (!hitFloor) {
226
if (self->originY < (ScreenInfo->position.y + 64) << 16)
227
self->originY += self->velocity.y;
228
}
229
230
if (self->state != EggPrison_State_FlyOffScreen) {
231
if (self->velocity.x > 0) {
232
if (self->position.x <= TO_FIXED(ScreenInfo->position.x + ScreenInfo->size.x - 48)) {
233
if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_LWALL, 0, TO_FIXED(64), 0, true))
234
self->velocity.x = -self->velocity.x;
235
}
236
else {
237
self->velocity.x = -self->velocity.x;
238
}
239
}
240
else if (self->position.x < TO_FIXED(ScreenInfo->position.x + 48)) {
241
self->velocity.x = -self->velocity.x;
242
}
243
else {
244
if (RSDK.ObjectTileCollision(self, Zone->collisionLayers, CMODE_RWALL, 0, -TO_FIXED(64), 0, true))
245
self->velocity.x = -self->velocity.x;
246
}
247
}
248
249
self->position.x += self->velocity.x;
250
self->position.y = BadnikHelpers_Oscillate(self->originY, 4, 10);
251
}
252
253
void EggPrison_State_Opened(void)
254
{
255
RSDK_THIS(EggPrison);
256
257
RSDK.SetSpriteAnimation(-1, 0, &self->panelAnimator, true, 0);
258
self->state = EggPrison_State_Explode;
259
260
switch (self->type) {
261
default:
262
case EGGPRISON_NORMAL:
263
case EGGPRISON_FLYING:
264
case EGGPRISON_DUD:
265
case EGGPRISON_SPRING:
266
for (int32 a = 0; a < 10; ++a) {
267
int32 x = self->position.x + TO_FIXED((RSDK.Rand(0, 48) & -4) - 24);
268
int32 y = self->position.y + TO_FIXED(4);
269
EntityAnimals *animals = CREATE_ENTITY(Animals, INT_TO_VOID(Animals->animalTypes[a & 1] + 1), x, y);
270
271
animals->timer = 4 * a;
272
animals->state = Animals_State_Placed;
273
animals->behaviour = ANIMAL_BEHAVE_FOLLOW;
274
animals->direction = (a ^ (a >> 1)) & 1;
275
}
276
break;
277
278
case EGGPRISON_RINGS: {
279
int32 angle = 0x90;
280
for (int32 r = 0; r < 6; ++r) {
281
int32 x = self->position.x + TO_FIXED((RSDK.Rand(0, 48) & -4) - 24);
282
int32 y = self->position.y;
283
EntityRing *ring = CREATE_ENTITY(Ring, self, x, y);
284
285
ring->velocity.x = RSDK.Cos256(angle) << 9;
286
ring->velocity.y = RSDK.Sin256(angle) << 9;
287
ring->animator.speed = 512;
288
ring->collisionPlane = 0;
289
ring->inkEffect = INK_ALPHA;
290
if (angle != 176)
291
angle += 8;
292
else
293
angle = 0xD0;
294
ring->alpha = 0x100;
295
ring->state = Ring_State_Lost;
296
ring->stateDraw = Ring_Draw_Normal;
297
}
298
break;
299
}
300
301
case EGGPRISON_TRAP: {
302
EntityTechnosqueek *technosqueek = CREATE_ENTITY(Technosqueek, NULL, self->position.x - TO_FIXED(8), self->position.y);
303
technosqueek->velocity.x = -TO_FIXED(3);
304
technosqueek->velocity.y = -TO_FIXED(4);
305
technosqueek->active = ACTIVE_NORMAL;
306
technosqueek->state = Technosqueek_State_Fall;
307
308
technosqueek = CREATE_ENTITY(Technosqueek, NULL, self->position.x + TO_FIXED(8), self->position.y);
309
technosqueek->velocity.x = TO_FIXED(3);
310
technosqueek->velocity.y = -TO_FIXED(4);
311
technosqueek->active = ACTIVE_NORMAL;
312
technosqueek->direction = FLIP_X;
313
technosqueek->state = Technosqueek_State_Fall;
314
315
EntityBlaster *blaster = CREATE_ENTITY(Blaster, NULL, self->position.x - TO_FIXED(24), self->position.y);
316
blaster->velocity.x = -TO_FIXED(3);
317
blaster->velocity.y = -TO_FIXED(3);
318
blaster->active = ACTIVE_NORMAL;
319
blaster->state = Blaster_State_Fall;
320
321
blaster = CREATE_ENTITY(Blaster, NULL, self->position.x + TO_FIXED(24), self->position.y);
322
blaster->velocity.x = TO_FIXED(3);
323
blaster->velocity.y = -TO_FIXED(3);
324
blaster->active = ACTIVE_NORMAL;
325
blaster->direction = FLIP_X;
326
blaster->state = Blaster_State_Fall;
327
break;
328
}
329
}
330
331
EntityDebris *debris = CREATE_ENTITY(Debris, Debris_State_FallAndFlicker, self->position.x - TO_FIXED(22), self->position.y);
332
RSDK.SetSpriteAnimation(EggPrison->aniFrames, 2, &debris->animator, true, 2);
333
debris->velocity.x = -TO_FIXED(2);
334
debris->velocity.y = -TO_FIXED(2);
335
debris->gravityStrength = 0x3800;
336
debris->rotSpeed = -4;
337
debris->drawFX = FX_ROTATE;
338
debris->drawGroup = Zone->objectDrawGroup[1];
339
debris->updateRange.x = TO_FIXED(128);
340
debris->updateRange.y = TO_FIXED(128);
341
342
debris = CREATE_ENTITY(Debris, Debris_State_FallAndFlicker, self->position.x, self->position.y);
343
RSDK.SetSpriteAnimation(EggPrison->aniFrames, 2, &debris->animator, true, 3);
344
debris->velocity.x = TO_FIXED(0);
345
debris->velocity.y = -TO_FIXED(3);
346
debris->gravityStrength = 0x3800;
347
debris->rotSpeed = 8;
348
debris->drawFX = FX_ROTATE;
349
debris->drawGroup = Zone->objectDrawGroup[1];
350
debris->updateRange.x = TO_FIXED(128);
351
debris->updateRange.y = TO_FIXED(128);
352
353
debris = CREATE_ENTITY(Debris, Debris_State_FallAndFlicker, self->position.x + TO_FIXED(22), self->position.y);
354
RSDK.SetSpriteAnimation(EggPrison->aniFrames, 2, &debris->animator, true, 4);
355
debris->velocity.x = TO_FIXED(2);
356
debris->velocity.y = -TO_FIXED(2);
357
debris->gravityStrength = 0x3800;
358
debris->rotSpeed = 4;
359
debris->drawFX = FX_ROTATE;
360
debris->drawGroup = Zone->objectDrawGroup[1];
361
debris->updateRange.x = TO_FIXED(128);
362
debris->updateRange.y = TO_FIXED(128);
363
}
364
365
void EggPrison_State_Init(void)
366
{
367
RSDK_THIS(EggPrison);
368
369
self->originY = self->position.y;
370
self->state = EggPrison_State_Idle;
371
}
372
373
void EggPrison_State_Idle(void)
374
{
375
RSDK_THIS(EggPrison);
376
377
for (int32 p = 0; p < Player->playerCount && self->type < EGGPRISON_DUD; ++p) {
378
EntityPlayer *player = RSDK_GET_ENTITY(p, Player);
379
if (!player->sidekick) {
380
if (abs(self->position.x - player->position.x) < TO_FIXED(256)) {
381
if (abs(self->position.y - player->position.y) < TO_FIXED(256) && self->position.x - (Zone->cameraBoundsR[p] << 16) < TO_FIXED(256)) {
382
Zone->playerBoundActiveL[p] = true;
383
Zone->playerBoundActiveR[p] = true;
384
385
if (self->type == EGGPRISON_NORMAL) {
386
Zone->cameraBoundsL[p] = FROM_FIXED(self->position.x) - ScreenInfo[p].center.x;
387
Zone->cameraBoundsR[p] = FROM_FIXED(self->position.x) + ScreenInfo[p].center.x;
388
}
389
}
390
}
391
}
392
}
393
}
394
395
void EggPrison_State_Explode(void)
396
{
397
RSDK_THIS(EggPrison);
398
399
if (!(self->timer % 3)) {
400
int32 x = self->position.x + (RSDK.Rand(-24, 24) << 16);
401
int32 y = self->position.y + (RSDK.Rand(-24, 24) << 16);
402
EntityExplosion *explosion = CREATE_ENTITY(Explosion, INT_TO_VOID(2 * (RSDK.Rand(0, 256) > 192) + EXPLOSION_ENEMY), x, y);
403
explosion->drawGroup = Zone->objectDrawGroup[1];
404
RSDK.PlaySfx(EggPrison->sfxDestroy, false, 255);
405
}
406
407
if (++self->timer == 20) {
408
self->timer = 0;
409
if (self->type < EGGPRISON_DUD) {
410
self->state = EggPrison_State_SetupActClear;
411
Music_FadeOut(0.025);
412
}
413
else {
414
self->state = StateMachine_None;
415
}
416
}
417
}
418
419
void EggPrison_State_SetupActClear(void)
420
{
421
RSDK_THIS(EggPrison);
422
423
if (++self->timer == 60) {
424
self->timer = 0;
425
self->state = StateMachine_None;
426
Zone->shouldRecoverPlayers = false;
427
Music_PlayTrack(TRACK_ACTCLEAR);
428
RSDK.ResetEntitySlot(SLOT_ACTCLEAR, ActClear->classID, NULL);
429
}
430
}
431
432
void EggPrison_State_FlyOffScreen(void)
433
{
434
RSDK_THIS(EggPrison);
435
436
if (self->velocity.x > -TO_FIXED(3))
437
self->velocity.x -= 0x1000;
438
439
if (!RSDK.CheckOnScreen(self, NULL))
440
destroyEntity(self);
441
}
442
443
#if GAME_INCLUDE_EDITOR
444
void EggPrison_EditorDraw(void)
445
{
446
RSDK_THIS(EggPrison);
447
448
Vector2 drawPos;
449
if (self->type == EGGPRISON_FLYING) {
450
RSDK.SetSpriteAnimation(EggPrison->aniFrames, 0, &self->capsuleAnimator, true, 1);
451
RSDK.SetSpriteAnimation(EggPrison->aniFrames, 1, &self->buttonAnimator, true, 0);
452
RSDK.SetSpriteAnimation(EggPrison->aniFrames, 2, &self->panelAnimator, true, 1);
453
RSDK.SetSpriteAnimation(EggPrison->aniFrames, 3, &self->propellerAnimator, true, 0);
454
455
self->direction = FLIP_Y;
456
drawPos.x = self->position.x;
457
drawPos.y = self->position.y + self->buttonPos;
458
RSDK.DrawSprite(&self->buttonAnimator, &drawPos, false);
459
460
self->direction = FLIP_NONE;
461
RSDK.DrawSprite(&self->capsuleAnimator, NULL, false);
462
RSDK.DrawSprite(&self->panelAnimator, NULL, false);
463
RSDK.DrawSprite(&self->propellerAnimator, NULL, false);
464
465
self->direction = FLIP_X;
466
RSDK.DrawSprite(&self->propellerAnimator, NULL, false);
467
468
self->direction = FLIP_NONE;
469
}
470
else {
471
RSDK.SetSpriteAnimation(EggPrison->aniFrames, 0, &self->capsuleAnimator, true, 0);
472
RSDK.SetSpriteAnimation(EggPrison->aniFrames, 1, &self->buttonAnimator, true, 0);
473
RSDK.SetSpriteAnimation(EggPrison->aniFrames, 2, &self->panelAnimator, true, 0);
474
475
drawPos.x = self->position.x;
476
drawPos.y = self->position.y + self->buttonPos;
477
RSDK.DrawSprite(&self->buttonAnimator, &drawPos, false);
478
RSDK.DrawSprite(&self->capsuleAnimator, NULL, false);
479
RSDK.DrawSprite(&self->panelAnimator, NULL, false);
480
}
481
}
482
483
void EggPrison_EditorLoad(void)
484
{
485
EggPrison->aniFrames = RSDK.LoadSpriteAnimation("Global/EggPrison.bin", SCOPE_STAGE);
486
487
RSDK_ACTIVE_VAR(EggPrison, type);
488
RSDK_ENUM_VAR("Normal", EGGPRISON_NORMAL);
489
RSDK_ENUM_VAR("Flying", EGGPRISON_FLYING);
490
RSDK_ENUM_VAR("Dud", EGGPRISON_DUD);
491
RSDK_ENUM_VAR("Rings", EGGPRISON_RINGS);
492
RSDK_ENUM_VAR("Trap", EGGPRISON_TRAP);
493
RSDK_ENUM_VAR("Spring", EGGPRISON_SPRING);
494
}
495
#endif
496
497
void EggPrison_Serialize(void) { RSDK_EDITABLE_VAR(EggPrison, VAR_ENUM, type); }
498
499