Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/TMZ/EscapeCar.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: EscapeCar Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectEscapeCar *EscapeCar;
11
12
void EscapeCar_Update(void)
13
{
14
RSDK_THIS(EscapeCar);
15
16
StateMachine_Run(self->state);
17
}
18
19
void EscapeCar_LateUpdate(void) {}
20
21
void EscapeCar_StaticUpdate(void) {}
22
23
void EscapeCar_Draw(void)
24
{
25
RSDK_THIS(EscapeCar);
26
27
if (SceneInfo->currentDrawGroup == Zone->objectDrawGroup[0]) {
28
RSDK.DrawSprite(&self->driverAnimator, NULL, false);
29
30
if (!SceneInfo->currentScreenID)
31
RSDK.AddDrawListRef(Zone->objectDrawGroup[1], SceneInfo->entitySlot);
32
}
33
else {
34
RSDK.DrawSprite(&self->carAnimator, NULL, false);
35
RSDK.DrawSprite(&self->thrustAnimator, NULL, false);
36
}
37
}
38
39
void EscapeCar_Create(void *data)
40
{
41
RSDK_THIS(EscapeCar);
42
43
if (!SceneInfo->inEditor) {
44
self->visible = true;
45
self->drawGroup = Zone->objectDrawGroup[0];
46
self->active = ACTIVE_BOUNDS;
47
self->updateRange.x = 0x800000;
48
self->updateRange.y = 0x800000;
49
50
#if MANIA_USE_PLUS
51
if (globals->gameMode == MODE_ENCORE) {
52
self->state = EscapeCar_StateEncore_Setup;
53
RSDK.SetSpriteAnimation(EscapeCar->aniFrames, 8, &self->driverAnimator, true, 0);
54
}
55
else {
56
#endif
57
switch (GET_CHARACTER_ID(1)) {
58
default:
59
case ID_SONIC: self->driver = ESCAPECAR_DRIVER_KNUX; break;
60
61
case ID_TAILS:
62
#if MANIA_USE_PLUS
63
case ID_MIGHTY:
64
case ID_RAY:
65
#endif
66
self->driver = ESCAPECAR_DRIVER_SONIC;
67
break;
68
69
case ID_KNUCKLES: self->driver = CHECK_CHARACTER_ID(ID_KNUCKLES, 2) ? ESCAPECAR_DRIVER_KNUX : ESCAPECAR_DRIVER_SONIC; break;
70
}
71
self->state = EscapeCar_StateMania_AwaitPlayer;
72
RSDK.SetSpriteAnimation(EscapeCar->aniFrames, 2 + self->driver, &self->driverAnimator, true, 0);
73
#if MANIA_USE_PLUS
74
}
75
#endif
76
77
RSDK.SetSpriteAnimation(EscapeCar->aniFrames, 0, &self->carAnimator, true, 0);
78
}
79
}
80
81
void EscapeCar_StageLoad(void)
82
{
83
EscapeCar->aniFrames = RSDK.LoadSpriteAnimation("Phantom/EscapeCar.bin", SCOPE_STAGE);
84
85
EscapeCar->hitbox.left = -16;
86
EscapeCar->hitbox.top = -16;
87
EscapeCar->hitbox.right = 16;
88
EscapeCar->hitbox.bottom = 16;
89
90
EscapeCar->sfxBumper = RSDK.GetSfx("Stage/Bumper3.wav");
91
EscapeCar->sfxDrop = RSDK.GetSfx("Stage/Drop.wav");
92
}
93
94
void EscapeCar_StateMania_AwaitPlayer(void)
95
{
96
RSDK_THIS(EscapeCar);
97
98
RSDK.ProcessAnimation(&self->driverAnimator);
99
100
// Why does this func have encore checks??? Encore has its own states..
101
102
bool32 allAboard = true;
103
foreach_active(Player, player)
104
{
105
if (player->state != Player_State_Static && player->position.x > self->position.x - 0x400000 && player->sidekick) {
106
player->velocity.x -= 0x1000;
107
}
108
#if MANIA_USE_PLUS
109
if (globals->gameMode != MODE_ENCORE && player->position.x > self->position.x - 0x400000)
110
#else
111
if (player->position.x > self->position.x - 0x400000)
112
#endif
113
RSDK.SetSpriteAnimation(EscapeCar->aniFrames, 3 + self->driver, &self->driverAnimator, true, 0);
114
115
if (Player_CheckCollisionTouch(player, self, &EscapeCar->hitbox)) {
116
player->state = Player_State_Static;
117
player->velocity.x = 0;
118
player->velocity.y = 0;
119
player->position.x = self->position.x;
120
player->position.y = self->position.y;
121
122
if (player->sidekick) {
123
player->position.x -= 0x140000;
124
player->position.y -= 0x140000;
125
}
126
else {
127
player->position.x -= 0xC0000;
128
player->position.y -= 0x80000;
129
}
130
131
RSDK.SetSpriteAnimation(player->aniFrames, ANI_RIDE, &player->animator, false, 0);
132
player->animator.speed = 0;
133
}
134
else {
135
allAboard = false;
136
}
137
}
138
139
if (self->driverAnimator.animationID == 3 + self->driver) {
140
#if MANIA_USE_PLUS
141
if (globals->gameMode != MODE_ENCORE) {
142
#endif
143
if (self->driverAnimator.frameID == self->driverAnimator.frameCount - 1)
144
RSDK.SetSpriteAnimation(EscapeCar->aniFrames, 4 + self->driver, &self->driverAnimator, true, 0);
145
#if MANIA_USE_PLUS
146
}
147
#endif
148
}
149
150
if (allAboard)
151
self->state = EscapeCar_StateMania_EnteredCar;
152
}
153
154
void EscapeCar_StateMania_EnteredCar(void)
155
{
156
RSDK_THIS(EscapeCar);
157
158
RSDK.ProcessAnimation(&self->driverAnimator);
159
RSDK.ProcessAnimation(&self->thrustAnimator);
160
161
if (++self->timer == 60)
162
RSDK.SetSpriteAnimation(EscapeCar->aniFrames, 1, &self->thrustAnimator, true, 0);
163
164
if (self->timer == 160) {
165
foreach_active(Player, player) { RSDK.SetSpriteAnimation(player->aniFrames, ANI_RIDE, &player->animator, true, 0); }
166
167
self->timer = 0;
168
self->velocity.x = 0x10000;
169
self->state = EscapeCar_StateMania_Ride;
170
}
171
}
172
173
void EscapeCar_StateMania_Ride(void)
174
{
175
RSDK_THIS(EscapeCar);
176
177
RSDK.ProcessAnimation(&self->driverAnimator);
178
RSDK.ProcessAnimation(&self->thrustAnimator);
179
180
if (self->velocity.x < 0x180000)
181
self->velocity.x += 0x2800;
182
183
self->position.x += self->velocity.x;
184
185
foreach_active(Player, player)
186
{
187
player->state = Player_State_Static;
188
player->velocity.x = 0;
189
player->velocity.y = 0;
190
player->position.x = self->position.x;
191
player->position.y = self->position.y;
192
193
if (player->sidekick) {
194
player->position.x -= 0x140000;
195
player->position.y -= 0x140000;
196
}
197
else {
198
player->position.x -= 0xC0000;
199
player->position.y -= 0x80000;
200
}
201
}
202
}
203
204
#if MANIA_USE_PLUS
205
void EscapeCar_StateEncore_Setup(void)
206
{
207
RSDK_THIS(EscapeCar);
208
209
if (self->position.x - 0x800000 < (ScreenInfo->position.x + ScreenInfo->center.x) << 16) {
210
RSDK.SetSpriteAnimation(EscapeCar->aniFrames, 1, &self->thrustAnimator, true, 0);
211
212
self->velocity.x = 0x6000;
213
if (SaveGame_AllChaosEmeralds())
214
self->state = EscapeCar_StateEncore_GoodEnd;
215
else
216
self->state = EscapeCar_StateEncore_BadEnd;
217
}
218
}
219
220
void EscapeCar_StateEncore_BadEnd(void)
221
{
222
RSDK_THIS(EscapeCar);
223
224
RSDK.ProcessAnimation(&self->driverAnimator);
225
RSDK.ProcessAnimation(&self->thrustAnimator);
226
227
if (self->velocity.x < 0x80000)
228
self->velocity.x += 0x2800;
229
230
self->position.x += self->velocity.x;
231
}
232
233
void EscapeCar_StateEncore_GoodEnd(void)
234
{
235
RSDK_THIS(EscapeCar);
236
237
RSDK.ProcessAnimation(&self->driverAnimator);
238
RSDK.ProcessAnimation(&self->thrustAnimator);
239
240
if (self->velocity.x < 0x74000)
241
self->velocity.x += 0x2800;
242
243
self->position.x += self->velocity.x;
244
245
EntityPlayer *player1 = RSDK_GET_ENTITY(SLOT_PLAYER1, Player);
246
if (abs(player1->position.x - self->position.x) < 0x100000) {
247
EntityDebris *debris = CREATE_ENTITY(Debris, NULL, self->position.x, self->position.y);
248
debris->state = Debris_State_Fall;
249
debris->gravityStrength = 0x3800;
250
debris->velocity.x = 0x30000;
251
debris->velocity.y = -0x78000;
252
debris->drawFX = FX_SCALE | FX_ROTATE;
253
debris->scale.x = 0x200;
254
debris->scale.y = 0x200;
255
debris->drawGroup = Zone->objectDrawGroup[0] + 1;
256
debris->rotSpeed = 2;
257
RSDK.SetSpriteAnimation(Eggman->aniFrames, 7, &debris->animator, true, 0);
258
debris->animator.rotationStyle = ROTSTYLE_FULL;
259
debris->isPermanent = true;
260
261
debris = CREATE_ENTITY(Debris, NULL, self->position.x, self->position.y);
262
debris->state = Debris_State_Fall;
263
debris->gravityStrength = 0x3800;
264
debris->velocity.x = 0x40000;
265
debris->velocity.y = -0x48000;
266
debris->drawFX = FX_ROTATE;
267
debris->drawGroup = Zone->objectDrawGroup[0] + 1;
268
debris->rotSpeed = -4;
269
debris->animator = self->carAnimator;
270
debris->isPermanent = true;
271
debris->animator.rotationStyle = ROTSTYLE_FULL;
272
273
RSDK.PlaySfx(EscapeCar->sfxBumper, false, 255);
274
destroyEntity(self);
275
}
276
}
277
#endif
278
279
#if GAME_INCLUDE_EDITOR
280
void EscapeCar_EditorDraw(void)
281
{
282
RSDK_THIS(EscapeCar);
283
284
self->drawGroup = Zone->objectDrawGroup[0];
285
self->updateRange.x = 0x800000;
286
self->updateRange.y = 0x800000;
287
288
#if MANIA_USE_PLUS
289
if (globals->gameMode == MODE_ENCORE) {
290
self->state = EscapeCar_StateEncore_Setup;
291
RSDK.SetSpriteAnimation(EscapeCar->aniFrames, 8, &self->driverAnimator, true, 0);
292
}
293
else {
294
#endif
295
switch (GET_CHARACTER_ID(1)) {
296
default:
297
case ID_SONIC: self->driver = ESCAPECAR_DRIVER_KNUX; break;
298
299
case ID_TAILS:
300
#if MANIA_USE_PLUS
301
case ID_MIGHTY:
302
case ID_RAY:
303
#endif
304
self->driver = ESCAPECAR_DRIVER_SONIC;
305
break;
306
307
case ID_KNUCKLES: self->driver = CHECK_CHARACTER_ID(ID_KNUCKLES, 2) ? ESCAPECAR_DRIVER_KNUX : ESCAPECAR_DRIVER_SONIC; break;
308
}
309
310
RSDK.SetSpriteAnimation(EscapeCar->aniFrames, 2 + self->driver, &self->driverAnimator, true, 0);
311
#if MANIA_USE_PLUS
312
}
313
#endif
314
315
RSDK.SetSpriteAnimation(EscapeCar->aniFrames, 0, &self->carAnimator, true, 0);
316
317
RSDK.DrawSprite(&self->driverAnimator, NULL, false);
318
RSDK.DrawSprite(&self->carAnimator, NULL, false);
319
RSDK.DrawSprite(&self->thrustAnimator, NULL, false);
320
}
321
322
void EscapeCar_EditorLoad(void) { EscapeCar->aniFrames = RSDK.LoadSpriteAnimation("Phantom/EscapeCar.bin", SCOPE_STAGE); }
323
#endif
324
325
void EscapeCar_Serialize(void) {}
326
327