Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/SPZ/FilmReel.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: FilmReel Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectFilmReel *FilmReel;
11
12
void FilmReel_Update(void)
13
{
14
RSDK_THIS(FilmReel);
15
16
self->velocity.x = (self->spinSpeed * RSDK.Cos256(self->angle)) >> 9;
17
self->velocity.y = (self->spinSpeed * RSDK.Sin256(self->angle)) >> 9;
18
self->lastPos.x += self->velocity.x;
19
self->lastPos.y += self->velocity.y;
20
21
int32 prevPathFlags = self->pathFlags;
22
self->pathFlags = 0;
23
switch (self->pathDir) {
24
case 0:
25
if (self->drawPos.x != self->endPos.x) {
26
if (self->lastPos.x <= self->drawPos.x) {
27
self->lastPos.x = self->drawPos.x;
28
self->pathFlags = 1;
29
}
30
31
if (self->lastPos.x >= self->endPos.x) {
32
self->pathFlags |= 2;
33
self->lastPos.x = self->endPos.x;
34
}
35
}
36
37
if (self->drawPos.y != self->endPos.y) {
38
if (self->lastPos.y <= self->drawPos.y) {
39
self->pathFlags |= 1;
40
self->lastPos.y = self->drawPos.y;
41
}
42
43
if (self->lastPos.y >= self->endPos.y) {
44
self->pathFlags |= 2;
45
self->lastPos.y = self->lastPos.y;
46
}
47
}
48
break;
49
50
case 1:
51
if (self->drawPos.x != self->endPos.x) {
52
if (self->lastPos.x <= self->endPos.x) {
53
self->lastPos.x = self->endPos.x;
54
self->pathFlags = 2;
55
}
56
57
if (self->lastPos.x >= self->endPos.x) {
58
self->pathFlags |= 1;
59
self->lastPos.x = self->drawPos.x;
60
}
61
}
62
63
if (self->drawPos.y != self->endPos.y) {
64
if (self->lastPos.y <= self->drawPos.y) {
65
self->pathFlags |= 1;
66
self->lastPos.y = self->drawPos.y;
67
}
68
69
if (self->lastPos.y >= self->endPos.y) {
70
self->pathFlags |= 2;
71
self->lastPos.y = self->lastPos.y;
72
}
73
}
74
break;
75
76
case 2:
77
if (self->drawPos.x != self->endPos.x) {
78
if (self->lastPos.x <= self->endPos.x) {
79
self->lastPos.x = self->endPos.x;
80
self->pathFlags = 2;
81
}
82
83
if (self->lastPos.x >= self->drawPos.x) {
84
self->pathFlags |= 1;
85
self->lastPos.x = self->drawPos.x;
86
}
87
}
88
89
if (self->drawPos.y != self->endPos.y) {
90
if (self->lastPos.y <= self->endPos.y) {
91
self->pathFlags |= 2;
92
self->lastPos.y = self->endPos.y;
93
}
94
95
if (self->lastPos.y >= self->drawPos.y) {
96
self->pathFlags |= 1;
97
self->lastPos.y = self->drawPos.y;
98
}
99
}
100
break;
101
102
case 3:
103
if (self->drawPos.x != self->endPos.x) {
104
if (self->lastPos.x <= self->drawPos.x) {
105
self->lastPos.x = self->drawPos.x;
106
self->pathFlags = 1;
107
}
108
109
if (self->lastPos.x >= self->endPos.x) {
110
self->pathFlags |= 2;
111
self->lastPos.x = self->endPos.x;
112
}
113
}
114
115
if (self->drawPos.y != self->endPos.y) {
116
if (self->lastPos.y <= self->endPos.y) {
117
self->pathFlags |= 2;
118
self->lastPos.y = self->endPos.y;
119
}
120
121
if (self->lastPos.y >= self->drawPos.y) {
122
self->pathFlags |= 1;
123
self->lastPos.y = self->drawPos.y;
124
}
125
}
126
break;
127
128
default: break;
129
}
130
131
if (self->pathFlags) {
132
if (!prevPathFlags) {
133
RSDK.PlaySfx(FilmReel->sfxLanding, false, 255);
134
RSDK.StopSfx(FilmReel->sfxUnravel);
135
136
if (self->pathFlags == 1)
137
self->active = ACTIVE_BOUNDS;
138
}
139
}
140
else {
141
if (!(Zone->timer & 7))
142
RSDK.PlaySfx(FilmReel->sfxUnravel, false, 255);
143
144
self->active = ACTIVE_NORMAL;
145
}
146
147
self->spinSpeed -= 0x2000;
148
self->moveOffset.x = (self->lastPos.x & 0xFFFF0000) - (self->position.x & 0xFFFF0000);
149
self->moveOffset.y = (self->lastPos.y & 0xFFFF0000) - (self->position.y & 0xFFFF0000);
150
151
if (!self->spinDirection)
152
FilmReel_SpinLeft();
153
else
154
FilmReel_SpinRight();
155
156
self->spinSpeed = CLAMP(self->spinSpeed, -0x80000, 0x80000);
157
158
self->position = self->lastPos;
159
if (!self->pathFlags) {
160
if (self->spinDirection)
161
self->spinAngle -= self->spinSpeed;
162
else
163
self->spinAngle += self->spinSpeed;
164
165
self->rotation = (self->spinAngle >> 16) & 0x1FF;
166
}
167
168
if (abs(self->pathSize.x) <= abs(self->pathSize.y)) {
169
int32 scale = MIN((abs(self->endPos.y - self->position.y) >> 8) / (abs(self->pathSize.x) >> 16) + 0x100, 0x200);
170
self->scale.x = scale;
171
self->scale.y = scale;
172
}
173
else {
174
int32 scale = MIN((abs(self->endPos.x - self->position.x) >> 8) / (abs(self->pathSize.x) >> 16) + 0x100, 0x200);
175
self->scale.x = scale;
176
self->scale.y = scale;
177
}
178
179
self->lineDir = abs(self->position.x - self->drawPos.x) <= abs(self->pathSize.y - self->drawPos.y);
180
}
181
182
void FilmReel_LateUpdate(void) {}
183
184
void FilmReel_StaticUpdate(void) {}
185
186
void FilmReel_Draw(void)
187
{
188
RSDK_THIS(FilmReel);
189
190
int32 angle = (self->angle - 64) & 0xFF;
191
int32 x2 = (16 * self->scale.x * RSDK.Cos256(angle) + self->position.x) & 0xFFFF0000;
192
int32 y2 = (16 * self->scale.x * RSDK.Sin256(angle) + self->position.y) & 0xFFFF0000;
193
194
self->celluoidAnimator.frameID = (self->rotation >> 4) & 1;
195
196
color color1 = self->celluoidAnimator.frameID ? 0x204078 : 0x3868A8;
197
color color2 = self->celluoidAnimator.frameID ? 0x182850 : 0x204078;
198
199
if (self->lineDir) {
200
RSDK.DrawLine(self->drawPos.x, self->drawPos.y, x2, y2, color1, 255, INK_NONE, false);
201
RSDK.DrawLine(self->drawPos.x, self->drawPos.y + 0x18000, x2, y2 + 0x18000, color2, 255, INK_NONE, false);
202
}
203
else {
204
RSDK.DrawLine(self->drawPos.x, self->drawPos.y, x2, y2, color1, 255, INK_NONE, false);
205
RSDK.DrawLine(self->drawPos.x - 0x18000, self->drawPos.y, x2 - 0x18000, y2, color2, 255, INK_NONE, false);
206
}
207
208
RSDK.DrawSprite(&self->pinAnimator, &self->drawPos, false);
209
210
self->drawFX = FX_SCALE;
211
RSDK.DrawSprite(&self->celluoidAnimator, NULL, false);
212
213
self->drawFX = FX_ROTATE;
214
RSDK.DrawSprite(&self->reelAnimator, NULL, false);
215
216
self->drawFX = FX_NONE;
217
RSDK.DrawSprite(&self->edgeAnimator, NULL, false);
218
}
219
220
void FilmReel_Create(void *data)
221
{
222
RSDK_THIS(FilmReel);
223
224
RSDK.SetSpriteAnimation(FilmReel->aniFrames, 0, &self->reelAnimator, true, 0);
225
RSDK.SetSpriteAnimation(FilmReel->aniFrames, 1, &self->celluoidAnimator, true, 0);
226
RSDK.SetSpriteAnimation(FilmReel->aniFrames, 2, &self->edgeAnimator, true, 0);
227
RSDK.SetSpriteAnimation(FilmReel->aniFrames, 3, &self->pinAnimator, true, 0);
228
229
if (!SceneInfo->inEditor) {
230
self->lastPos = self->position;
231
self->drawPos = self->position;
232
self->endPos.x = self->drawPos.x + self->pathSize.x;
233
self->endPos.y = self->drawPos.y + self->pathSize.y;
234
235
self->active = ACTIVE_BOUNDS;
236
self->updateRange.x = 0xC00000;
237
self->updateRange.y = 0xC00000;
238
self->scale.x = 0x200;
239
self->scale.y = 0x200;
240
241
self->angle = RSDK.ATan2(self->pathSize.x, self->pathSize.y);
242
self->pathDir = self->angle >> 6;
243
self->pathFlags = 1;
244
self->visible = true;
245
self->drawGroup = Zone->objectDrawGroup[0];
246
}
247
}
248
249
void FilmReel_StageLoad(void)
250
{
251
if (RSDK.CheckSceneFolder("SPZ1"))
252
FilmReel->aniFrames = RSDK.LoadSpriteAnimation("SPZ1/FilmReel.bin", SCOPE_STAGE);
253
else
254
FilmReel->aniFrames = RSDK.LoadSpriteAnimation("SPZ2/FilmReel.bin", SCOPE_STAGE);
255
256
FilmReel->hitboxWheel.left = -64;
257
FilmReel->hitboxWheel.top = -64;
258
FilmReel->hitboxWheel.right = 64;
259
FilmReel->hitboxWheel.bottom = 64;
260
261
FilmReel->offsetPos.x = 0x800000;
262
FilmReel->offsetPos.y = 0x800000;
263
264
FilmReel->sfxUnravel = RSDK.GetSfx("Stage/Unravel.wav");
265
FilmReel->sfxLanding = RSDK.GetSfx("Stage/Landing.wav");
266
}
267
268
void FilmReel_SpinLeft(void)
269
{
270
RSDK_THIS(FilmReel);
271
272
foreach_active(Player, player)
273
{
274
if (Player_CheckCollisionTouch(player, self, &FilmReel->hitboxWheel)) {
275
player->collisionLayers |= Zone->moveLayerMask;
276
player->moveLayerPosition.x = FilmReel->offsetPos.x - self->lastPos.x;
277
player->moveLayerPosition.y = FilmReel->offsetPos.y - self->lastPos.y;
278
279
if (!player->sidekick) {
280
if (player->onGround || RSDK.CheckObjectCollisionTouchCircle(self, 0x400000, player, 0x100000)) {
281
282
bool32 controllingMovement = true;
283
switch (self->pathFlags) {
284
case 0:
285
if (player->collisionMode || (!player->left && !player->right && player->state != Player_State_Roll)) {
286
controllingMovement = false;
287
}
288
289
if (abs(player->position.x - self->position.x) < 2 * abs(player->groundVel) && controllingMovement) {
290
if (player->groundVel < -0x60000)
291
player->groundVel = -0x60000;
292
293
if (player->direction == FLIP_X) {
294
player->position.x = self->position.x;
295
self->spinSpeed -= player->groundVel;
296
}
297
}
298
else {
299
player->groundVel += self->spinSpeed >> 5;
300
if (player->groundVel < -0x60000)
301
player->groundVel = -0x60000;
302
}
303
break;
304
305
case 1:
306
if (!player->collisionMode && (player->left || player->right || player->state == Player_State_Roll)
307
&& player->direction == FLIP_X) {
308
if (abs(player->position.x - self->position.x) < 2 * abs(player->groundVel)) {
309
if (player->groundVel < 0)
310
player->position.x = self->position.x;
311
self->spinSpeed -= player->groundVel;
312
}
313
}
314
break;
315
316
case 2:
317
if (abs(player->position.x - self->position.x) >= 2 * abs(player->groundVel) || player->collisionMode
318
|| player->position.x <= self->position.x) {
319
if (player->left)
320
self->spinSpeed -= player->groundVel;
321
}
322
else {
323
if (player->groundVel > 0)
324
player->position.x = self->position.x;
325
self->spinSpeed -= player->groundVel;
326
}
327
break;
328
}
329
330
if (player->camera && self->moveCamera) {
331
player->camera->state = StateMachine_None;
332
player->camera->position.x += self->moveOffset.x + ((self->position.x - player->camera->position.x) >> 3);
333
player->camera->position.y += self->moveOffset.y + ((self->position.y - player->camera->position.y - 0x200000) >> 3);
334
}
335
336
player->position.x += self->moveOffset.x;
337
player->position.y += self->moveOffset.y;
338
}
339
else if (player->camera && self->moveCamera) {
340
player->camera->state = Camera_State_FollowXY;
341
}
342
}
343
}
344
}
345
}
346
347
void FilmReel_SpinRight(void)
348
{
349
RSDK_THIS(FilmReel);
350
351
foreach_active(Player, player)
352
{
353
if (Player_CheckCollisionTouch(player, self, &FilmReel->hitboxWheel)) {
354
player->collisionLayers |= Zone->moveLayerMask;
355
player->moveLayerPosition.x = FilmReel->offsetPos.x - self->lastPos.x;
356
player->moveLayerPosition.y = FilmReel->offsetPos.y - self->lastPos.y;
357
if (!player->sidekick) {
358
if (player->onGround || RSDK.CheckObjectCollisionTouchCircle(self, 0x400000, player, 0x100000)) {
359
360
bool32 controllingMovement = true;
361
switch (self->pathFlags) {
362
case 0:
363
if (player->collisionMode || (!player->left && !player->right && player->state != Player_State_Roll)) {
364
controllingMovement = false;
365
}
366
367
if (abs(player->position.x - self->position.x) < 2 * abs(player->groundVel) && controllingMovement) {
368
if (player->groundVel > 0x60000)
369
player->groundVel = 0x60000;
370
371
if (player->direction == FLIP_NONE) {
372
player->position.x = self->position.x;
373
self->spinSpeed += player->groundVel;
374
}
375
}
376
else {
377
player->groundVel -= self->spinSpeed >> 5;
378
if (player->groundVel > 0x60000)
379
player->groundVel = 0x60000;
380
}
381
break;
382
383
case 1:
384
if (player->collisionMode || (!player->left && !player->right && player->state != Player_State_Roll)
385
|| player->direction) {
386
controllingMovement = false;
387
}
388
389
if (controllingMovement) {
390
if (abs(player->position.x - self->position.x) < 2 * abs(player->groundVel) && player->groundVel > 0) {
391
player->position.x = self->position.x;
392
}
393
self->spinSpeed += player->groundVel;
394
}
395
break;
396
397
case 2:
398
if (abs(player->position.x - self->position.x) >= 2 * abs(player->groundVel) || player->collisionMode
399
|| player->position.x >= self->position.x) {
400
if (player->right)
401
self->spinSpeed += player->groundVel;
402
}
403
else {
404
if (player->groundVel < 0)
405
player->position.x = self->position.x;
406
self->spinSpeed += player->groundVel;
407
}
408
break;
409
}
410
411
if (player->camera && self->moveCamera) {
412
player->camera->state = StateMachine_None;
413
player->camera->position.x += self->moveOffset.x + ((self->position.x - player->camera->position.x) >> 3);
414
player->camera->position.y += self->moveOffset.y + ((self->position.y - player->camera->position.y - 0x200000) >> 3);
415
}
416
}
417
else if (player->camera && self->moveCamera) {
418
player->camera->state = Camera_State_FollowXY;
419
}
420
}
421
}
422
}
423
}
424
425
#if GAME_INCLUDE_EDITOR
426
void FilmReel_EditorDraw(void)
427
{
428
RSDK_THIS(FilmReel);
429
430
self->lastPos = self->position;
431
self->drawPos = self->position;
432
self->endPos.x = self->position.x + self->pathSize.x;
433
self->endPos.y = self->position.y + self->pathSize.y;
434
self->active = ACTIVE_BOUNDS;
435
self->updateRange.x = 0xC00000;
436
self->updateRange.y = 0xC00000;
437
self->scale.x = 0x200;
438
self->scale.y = 0x200;
439
440
self->angle = RSDK.ATan2(self->pathSize.x, self->pathSize.y);
441
self->pathDir = self->angle >> 6;
442
self->pathFlags = 1;
443
self->visible = true;
444
self->drawGroup = Zone->objectDrawGroup[0];
445
446
FilmReel_Draw();
447
448
if (showGizmos()) {
449
RSDK_DRAWING_OVERLAY(true);
450
451
self->inkEffect = INK_BLEND;
452
self->drawPos = self->endPos;
453
FilmReel_Draw();
454
455
self->drawFX = FX_SCALE;
456
RSDK.DrawSprite(&self->celluoidAnimator, &self->drawPos, false);
457
458
self->drawFX = FX_ROTATE;
459
RSDK.DrawSprite(&self->reelAnimator, &self->drawPos, false);
460
461
self->drawFX = FX_NONE;
462
RSDK.DrawSprite(&self->edgeAnimator, &self->drawPos, false);
463
464
self->inkEffect = INK_NONE;
465
466
RSDK_DRAWING_OVERLAY(false);
467
}
468
}
469
470
void FilmReel_EditorLoad(void)
471
{
472
if (RSDK.CheckSceneFolder("SPZ1"))
473
FilmReel->aniFrames = RSDK.LoadSpriteAnimation("SPZ1/FilmReel.bin", SCOPE_STAGE);
474
else
475
FilmReel->aniFrames = RSDK.LoadSpriteAnimation("SPZ2/FilmReel.bin", SCOPE_STAGE);
476
477
RSDK_ACTIVE_VAR(FilmReel, spinDirection);
478
RSDK_ENUM_VAR("Clockwise", FLIP_NONE);
479
RSDK_ENUM_VAR("Counter-Clockwise", FLIP_X);
480
}
481
#endif
482
483
void FilmReel_Serialize(void)
484
{
485
RSDK_EDITABLE_VAR(FilmReel, VAR_VECTOR2, pathSize);
486
RSDK_EDITABLE_VAR(FilmReel, VAR_UINT8, spinDirection);
487
}
488
489