Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/TMZ/LaunchSpring.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: LaunchSpring Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectLaunchSpring *LaunchSpring;
11
12
void LaunchSpring_Update(void)
13
{
14
RSDK_THIS(LaunchSpring);
15
16
StateMachine_Run(self->state);
17
}
18
19
void LaunchSpring_LateUpdate(void) {}
20
21
void LaunchSpring_StaticUpdate(void) {}
22
23
void LaunchSpring_Draw(void)
24
{
25
RSDK_THIS(LaunchSpring);
26
27
RSDK.GetFrame(LaunchSpring->aniFrames, 2, 0)->pivotY = -8 - self->springPivot;
28
RSDK.DrawSprite(&self->springAnimator, NULL, false);
29
30
self->mainAnimator.frameID = 0;
31
RSDK.DrawSprite(&self->jointAnimator, NULL, false);
32
33
SpriteFrame *frame = RSDK.GetFrame(LaunchSpring->aniFrames, 0, 0);
34
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
35
36
frame->pivotY = self->timer - 55;
37
self->direction = FLIP_X;
38
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
39
40
frame->pivotY = -55;
41
self->direction = FLIP_NONE;
42
}
43
44
void LaunchSpring_Create(void *data)
45
{
46
RSDK_THIS(LaunchSpring);
47
48
if (!self->rotSpeed)
49
self->rotSpeed = 4;
50
51
self->drawFX = FX_ROTATE | FX_FLIP;
52
self->rotation = self->angle << 6;
53
54
if (!SceneInfo->inEditor) {
55
self->active = ACTIVE_BOUNDS;
56
self->visible = RSDK.CheckSceneFolder("SSZ1") || RSDK.CheckSceneFolder("SSZ2");
57
self->updateRange.x = 0x800000;
58
self->updateRange.y = 0x800000;
59
60
RSDK.SetSpriteAnimation(LaunchSpring->aniFrames, 0, &self->mainAnimator, true, 0);
61
RSDK.SetSpriteAnimation(LaunchSpring->aniFrames, 1, &self->jointAnimator, true, 0);
62
RSDK.SetSpriteAnimation(LaunchSpring->aniFrames, 2, &self->springAnimator, true, 0);
63
self->drawGroup = Zone->objectDrawGroup[1];
64
65
switch (self->type) {
66
case LAUNCHSPRING_SPINNING:
67
self->timer = 47;
68
self->state = LaunchSpring_State_Spinning;
69
break;
70
71
case LAUNCHSPRING_CANNON:
72
self->state = LaunchSpring_State_Cannon;
73
self->springAnimator.frameID = 1;
74
break;
75
76
case LAUNCHSPRING_ROTATE_45DEG:
77
self->minAngle = self->rotation - 0x40;
78
self->maxAngle = self->rotation + 0x40;
79
self->state = LaunchSpring_State_Rotating;
80
self->springAnimator.frameID = 1;
81
break;
82
83
case LAUNCHSPRING_ROTATE_90DEG:
84
self->minAngle = self->rotation - 0x80;
85
self->maxAngle = self->rotation + 0x80;
86
self->state = LaunchSpring_State_Rotating;
87
self->springAnimator.frameID = 1;
88
break;
89
90
case LAUNCHSPRING_ROTATE_135DEG:
91
self->minAngle = self->rotation - 0xC0;
92
self->maxAngle = self->rotation + 0xC0;
93
self->state = LaunchSpring_State_Rotating;
94
self->springAnimator.frameID = 1;
95
break;
96
97
case LAUNCHSPRING_ROTATE_180DEG:
98
self->minAngle = self->rotation - 0x100;
99
self->maxAngle = self->rotation + 0x100;
100
self->state = LaunchSpring_State_Rotating;
101
self->springAnimator.frameID = 1;
102
break;
103
104
default: break;
105
}
106
107
// What's this doin here...? Isn't this supposed to be StageLoad code?
108
109
LaunchSpring->sfxGrab = RSDK.GetSfx("Global/Grab.wav");
110
111
if (RSDK.CheckSceneFolder("SSZ1") || RSDK.CheckSceneFolder("SSZ2")) {
112
LaunchSpring->isTMZ = false;
113
LaunchSpring->sfxClack = RSDK.GetSfx("Stage/Clack.wav");
114
LaunchSpring->sfxSpeedBooster = RSDK.GetSfx("Stage/SpeedBooster.wav");
115
}
116
else if (RSDK.CheckSceneFolder("TMZ1") || RSDK.CheckSceneFolder("TMZ2")) {
117
LaunchSpring->isTMZ = true;
118
LaunchSpring->sfxSpeedBooster = RSDK.GetSfx("Stage/CannonFire.wav");
119
}
120
}
121
}
122
123
void LaunchSpring_StageLoad(void)
124
{
125
if (RSDK.CheckSceneFolder("SSZ1"))
126
LaunchSpring->aniFrames = RSDK.LoadSpriteAnimation("SSZ1/LaunchSpring.bin", SCOPE_STAGE);
127
else if (RSDK.CheckSceneFolder("SSZ2"))
128
LaunchSpring->aniFrames = RSDK.LoadSpriteAnimation("SSZ2/LaunchSpring.bin", SCOPE_STAGE);
129
130
LaunchSpring->hitbox.top = -24;
131
LaunchSpring->hitbox.left = -24;
132
LaunchSpring->hitbox.right = 24;
133
LaunchSpring->hitbox.bottom = 24;
134
}
135
136
bool32 LaunchSpring_CheckFireworkActive(EntityPlayer *player)
137
{
138
if (!Firework)
139
return false;
140
141
int32 playerID = RSDK.GetEntitySlot(player);
142
bool32 fireworkActive = false;
143
144
foreach_active(Firework, firework)
145
{
146
if ((1 << playerID) & firework->activePlayers) {
147
fireworkActive = true;
148
foreach_break;
149
}
150
}
151
152
return fireworkActive;
153
}
154
155
void LaunchSpring_CheckPlayerCollisions(void *nextState)
156
{
157
RSDK_THIS(LaunchSpring);
158
159
foreach_active(Player, player)
160
{
161
if (!player->sidekick && !LaunchSpring_CheckFireworkActive(player)) {
162
if (Player_CheckCollisionTouch(player, self, &LaunchSpring->hitbox)) {
163
RSDK.PlaySfx(LaunchSpring->sfxGrab, false, 255);
164
RSDK.SetSpriteAnimation(player->aniFrames, ANI_JUMP, &player->animator, false, 0);
165
166
player->position.x = self->position.x + (RSDK.Cos512(self->rotation - 0x80) << 12);
167
player->position.y = self->position.y + (RSDK.Sin512(self->rotation - 0x80) << 12);
168
169
player->velocity.x = 0;
170
player->velocity.y = 0;
171
player->groundVel = 0;
172
player->onGround = false;
173
player->state = Player_State_Static;
174
player->nextGroundState = StateMachine_None;
175
player->nextAirState = StateMachine_None;
176
177
self->springAnimator.frameID = 1;
178
self->playerPtr = player;
179
self->state = nextState;
180
foreach_break;
181
}
182
}
183
}
184
}
185
186
void LaunchSpring_LaunchPlayer(void)
187
{
188
RSDK_THIS(LaunchSpring);
189
190
EntityPlayer *player = self->playerPtr;
191
192
if (player->state == Player_State_Static) {
193
RSDK.PlaySfx(LaunchSpring->sfxSpeedBooster, false, 0xFF);
194
195
if (self->strict) {
196
self->rotation = (self->rotation + 0x40) & 0x1C0;
197
198
player->position.x = self->position.x + (RSDK.Cos512(self->rotation - 0x80) << 12);
199
player->position.y = self->position.y + (RSDK.Sin512(self->rotation - 0x80) << 12);
200
}
201
202
player->applyJumpCap = false;
203
player->jumpAbilityState = 0;
204
player->velocity.x = RSDK.Cos512(self->rotation - 0x80) << 11;
205
player->velocity.y = RSDK.Sin512(self->rotation - 0x80) << 11;
206
player->state = Player_State_Air;
207
}
208
}
209
210
void LaunchSpring_State_Spinning(void)
211
{
212
RSDK_THIS(LaunchSpring);
213
214
self->rotation = (self->rotation - self->rotSpeed) & 0x1FF;
215
216
LaunchSpring_CheckPlayerCollisions(LaunchSpring_State_Spinning_GrabbedPlayer);
217
}
218
219
void LaunchSpring_State_Spinning_GrabbedPlayer(void)
220
{
221
RSDK_THIS(LaunchSpring);
222
223
EntityPlayer *player = self->playerPtr;
224
225
player->position.x = self->position.x + (RSDK.Cos512(self->rotation - 0x80) << 12);
226
player->position.y = self->position.y + (RSDK.Sin512(self->rotation - 0x80) << 12);
227
228
if (!--self->timer) {
229
RSDK.PlaySfx(LaunchSpring->sfxClack, false, 0xFF);
230
self->state = LaunchSpring_State_Spinning_ReadyToFire;
231
}
232
}
233
234
void LaunchSpring_State_Spinning_ReadyToFire(void)
235
{
236
RSDK_THIS(LaunchSpring);
237
EntityPlayer *player = self->playerPtr;
238
239
if (player->state == Player_State_Static) {
240
self->rotation = (self->rotation - self->rotSpeed) & 0x1FF;
241
242
player->position.x = self->position.x + (RSDK.Cos512(self->rotation - 0x80) << 12);
243
player->position.y = self->position.y + (RSDK.Sin512(self->rotation - 0x80) << 12);
244
245
if (player->jumpPress) {
246
LaunchSpring_LaunchPlayer();
247
self->state = LaunchSpring_State_Spinning_FiredPlayer;
248
}
249
}
250
else {
251
self->playerPtr = NULL;
252
self->state = LaunchSpring_State_Spinning_FiredPlayer;
253
}
254
}
255
256
void LaunchSpring_State_Spinning_FiredPlayer(void)
257
{
258
RSDK_THIS(LaunchSpring);
259
260
RSDK.ProcessAnimation(&self->springAnimator);
261
262
if (self->springAnimator.frameID == self->springAnimator.frameCount - 1) {
263
RSDK.SetSpriteAnimation(LaunchSpring->aniFrames, 2, &self->springAnimator, true, 0);
264
self->state = LaunchSpring_State_Spinning_ReadyUp;
265
}
266
}
267
268
void LaunchSpring_State_Spinning_ReadyUp(void)
269
{
270
RSDK_THIS(LaunchSpring);
271
272
self->timer += 2;
273
if (self->timer >= 47) {
274
self->timer = 47;
275
self->state = LaunchSpring_State_Spinning;
276
}
277
}
278
279
void LaunchSpring_State_Cannon(void)
280
{
281
RSDK_THIS(LaunchSpring);
282
283
if (self->manual)
284
LaunchSpring_CheckPlayerCollisions(LaunchSpring_State_Cannon_Fire_Manual);
285
else
286
LaunchSpring_CheckPlayerCollisions(LaunchSpring_State_Cannon_Fire_Automatic);
287
}
288
289
void LaunchSpring_State_Cannon_Fire_Automatic(void)
290
{
291
RSDK_THIS(LaunchSpring);
292
293
EntityPlayer *player = self->playerPtr;
294
295
if (player->state == Player_State_Static) {
296
player->position.x = self->position.x + (RSDK.Cos512(self->rotation - 0x80) << 12);
297
player->position.y = self->position.y + (RSDK.Sin512(self->rotation - 0x80) << 12);
298
299
if (++self->autoFireTimer == 60) {
300
self->autoFireTimer = 0;
301
LaunchSpring_LaunchPlayer();
302
self->state = LaunchSpring_State_Cannon_FiredPlayer;
303
}
304
}
305
else {
306
self->playerPtr = NULL;
307
self->state = LaunchSpring_State_Cannon_FiredPlayer;
308
}
309
}
310
311
void LaunchSpring_State_Cannon_Fire_Manual(void)
312
{
313
RSDK_THIS(LaunchSpring);
314
315
EntityPlayer *player = self->playerPtr;
316
317
if (player->state == Player_State_Static) {
318
player->position.x = self->position.x + (RSDK.Cos512(self->rotation - 0x80) << 12);
319
player->position.y = self->position.y + (RSDK.Sin512(self->rotation - 0x80) << 12);
320
321
if (player->jumpPress) {
322
LaunchSpring_LaunchPlayer();
323
self->autoFireTimer = 0;
324
self->state = LaunchSpring_State_Cannon_FiredPlayer;
325
}
326
}
327
else {
328
self->playerPtr = NULL;
329
self->state = LaunchSpring_State_Cannon_FiredPlayer;
330
}
331
}
332
333
void LaunchSpring_State_Cannon_FiredPlayer(void)
334
{
335
RSDK_THIS(LaunchSpring);
336
337
if (LaunchSpring->isTMZ) {
338
if (self->autoFireTimer >= 30)
339
self->state = LaunchSpring_State_Cannon;
340
else
341
self->autoFireTimer++;
342
}
343
else {
344
RSDK.ProcessAnimation(&self->springAnimator);
345
346
if (self->springAnimator.frameID == self->springAnimator.frameCount - 1) {
347
RSDK.SetSpriteAnimation(LaunchSpring->aniFrames, 2, &self->springAnimator, true, 0);
348
self->springAnimator.frameID = 1;
349
self->state = LaunchSpring_State_Cannon;
350
}
351
}
352
}
353
354
void LaunchSpring_State_Rotating(void)
355
{
356
RSDK_THIS(LaunchSpring);
357
358
if (self->rotDir) {
359
self->rotation -= self->rotSpeed;
360
361
if (self->rotation <= self->minAngle) {
362
self->rotDir = 0;
363
self->rotation = self->minAngle;
364
}
365
}
366
else {
367
self->rotation += self->rotSpeed;
368
369
if (self->rotation >= self->maxAngle) {
370
self->rotDir = 1;
371
self->rotation = self->maxAngle;
372
}
373
}
374
375
if (self->manual)
376
LaunchSpring_CheckPlayerCollisions(LaunchSpring_State_Rotate_Fire_Manual);
377
else
378
LaunchSpring_CheckPlayerCollisions(LaunchSpring_State_Rotate_Fire_Automatic);
379
}
380
381
void LaunchSpring_State_Rotate_Fire_Automatic(void)
382
{
383
RSDK_THIS(LaunchSpring);
384
385
EntityPlayer *player = self->playerPtr;
386
387
if (player->state == Player_State_Static) {
388
if (self->strict)
389
self->rotation = (self->rotation + 0x20) & 0xC0;
390
391
player->position.x = self->position.x + (RSDK.Cos512(self->rotation - 0x80) << 12);
392
player->position.y = self->position.y + (RSDK.Sin512(self->rotation - 0x80) << 12);
393
394
if (++self->autoFireTimer == 60) {
395
self->autoFireTimer = 0;
396
LaunchSpring_LaunchPlayer();
397
self->state = LaunchSpring_State_Rotating_FiredPlayer;
398
}
399
}
400
else {
401
self->playerPtr = NULL;
402
self->state = LaunchSpring_State_Rotating_FiredPlayer;
403
}
404
}
405
406
void LaunchSpring_State_Rotate_Fire_Manual(void)
407
{
408
RSDK_THIS(LaunchSpring);
409
EntityPlayer *player = self->playerPtr;
410
411
if (player->state == Player_State_Static) {
412
if (self->rotDir) {
413
self->rotation -= self->rotSpeed;
414
415
if (self->rotation <= self->minAngle) {
416
self->rotation = self->minAngle;
417
self->rotDir = FLIP_NONE;
418
}
419
}
420
else {
421
self->rotation += self->rotSpeed;
422
423
if (self->rotation >= self->maxAngle) {
424
self->rotation = self->maxAngle;
425
self->rotDir = FLIP_X;
426
}
427
}
428
429
player->position.x = self->position.x + (RSDK.Cos512(self->rotation - 0x80) << 12);
430
player->position.y = self->position.y + (RSDK.Sin512(self->rotation - 0x80) << 12);
431
432
if (player->jumpPress) {
433
LaunchSpring_LaunchPlayer();
434
self->state = LaunchSpring_State_Rotating_FiredPlayer;
435
}
436
}
437
else {
438
self->playerPtr = NULL;
439
self->state = LaunchSpring_State_Rotating_FiredPlayer;
440
}
441
}
442
443
void LaunchSpring_State_Rotating_FiredPlayer(void)
444
{
445
RSDK_THIS(LaunchSpring);
446
447
RSDK.ProcessAnimation(&self->springAnimator);
448
449
if (self->springAnimator.frameID == self->springAnimator.frameCount - 1) {
450
RSDK.SetSpriteAnimation(LaunchSpring->aniFrames, 2, &self->springAnimator, true, 0);
451
self->springAnimator.frameID = 1;
452
self->state = LaunchSpring_State_Rotating;
453
}
454
}
455
456
#if GAME_INCLUDE_EDITOR
457
void LaunchSpring_EditorDraw(void)
458
{
459
RSDK_THIS(LaunchSpring);
460
461
if (RSDK.CheckSceneFolder("SSZ1") || RSDK.CheckSceneFolder("SSZ2")) {
462
RSDK.SetSpriteAnimation(LaunchSpring->aniFrames, 0, &self->mainAnimator, true, 0);
463
RSDK.SetSpriteAnimation(LaunchSpring->aniFrames, 1, &self->jointAnimator, true, 0);
464
RSDK.SetSpriteAnimation(LaunchSpring->aniFrames, 2, &self->springAnimator, true, 0);
465
466
self->rotation = self->angle << 6;
467
468
LaunchSpring_Draw();
469
}
470
else {
471
RSDK.SetSpriteAnimation(LaunchSpring->aniFrames, 0, &self->mainAnimator, true, 4);
472
473
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
474
}
475
}
476
477
void LaunchSpring_EditorLoad(void)
478
{
479
if (RSDK.CheckSceneFolder("SSZ1"))
480
LaunchSpring->aniFrames = RSDK.LoadSpriteAnimation("SSZ1/LaunchSpring.bin", SCOPE_STAGE);
481
else if (RSDK.CheckSceneFolder("SSZ2"))
482
LaunchSpring->aniFrames = RSDK.LoadSpriteAnimation("SSZ2/LaunchSpring.bin", SCOPE_STAGE);
483
else
484
LaunchSpring->aniFrames = RSDK.LoadSpriteAnimation("Global/PlaneSwitch.bin", SCOPE_STAGE);
485
486
RSDK_ACTIVE_VAR(LaunchSpring, type);
487
RSDK_ENUM_VAR("Spinning", LAUNCHSPRING_SPINNING);
488
RSDK_ENUM_VAR("Cannon", LAUNCHSPRING_CANNON);
489
RSDK_ENUM_VAR("Rotating (45 Degrees)", LAUNCHSPRING_ROTATE_45DEG);
490
RSDK_ENUM_VAR("Rotating (90 Degrees)", LAUNCHSPRING_ROTATE_90DEG);
491
RSDK_ENUM_VAR("Rotating (135 Degrees)", LAUNCHSPRING_ROTATE_135DEG);
492
RSDK_ENUM_VAR("Rotating (180 Degrees)", LAUNCHSPRING_ROTATE_180DEG);
493
494
RSDK_ACTIVE_VAR(LaunchSpring, rotDir);
495
RSDK_ENUM_VAR("Right", FLIP_NONE);
496
RSDK_ENUM_VAR("Left", FLIP_X);
497
498
RSDK_ACTIVE_VAR(LaunchSpring, angle);
499
RSDK_ENUM_VAR("Up", 0);
500
RSDK_ENUM_VAR("Left", 1);
501
RSDK_ENUM_VAR("Down", 2);
502
RSDK_ENUM_VAR("Right", 3);
503
}
504
#endif
505
506
void LaunchSpring_Serialize(void)
507
{
508
RSDK_EDITABLE_VAR(LaunchSpring, VAR_UINT8, type);
509
RSDK_EDITABLE_VAR(LaunchSpring, VAR_UINT8, rotDir);
510
RSDK_EDITABLE_VAR(LaunchSpring, VAR_UINT8, rotSpeed);
511
RSDK_EDITABLE_VAR(LaunchSpring, VAR_INT32, angle);
512
RSDK_EDITABLE_VAR(LaunchSpring, VAR_BOOL, manual);
513
RSDK_EDITABLE_VAR(LaunchSpring, VAR_BOOL, strict);
514
}
515
516