Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/HCZ/TwistingSlide.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: TwistingSlide Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectTwistingSlide *TwistingSlide;
11
12
void TwistingSlide_Update(void)
13
{
14
RSDK_THIS(TwistingSlide);
15
foreach_active(Player, player)
16
{
17
int32 playerID = RSDK.GetEntitySlot(player);
18
19
int32 storeX = player->position.x;
20
int32 storeY = player->position.y;
21
22
if (player->state != Player_State_Static)
23
self->activePlayers &= ~(1 << playerID);
24
25
if (!Player_CheckCollisionTouch(player, self, &self->hitboxSlide) || (player->position.y < self->minY) || player->position.y > self->maxY) {
26
self->activePlayers &= ~(1 << playerID);
27
}
28
else if (self->direction) {
29
switch (self->type) {
30
case TWISTINGSLIDE_START:
31
if (player->state == Player_State_Static) {
32
if (!((1 << playerID) & self->activePlayers)) {
33
self->playerAngles[playerID] = (player->position.y - self->position.y + 0x4A0000) >> 16;
34
self->activePlayers |= 1 << playerID;
35
}
36
37
int32 angle = 221 * self->playerAngles[playerID];
38
if (221 * self->playerAngles[playerID] >= 0x3FC0)
39
angle = 170 * self->playerAngles[playerID];
40
41
player->position.x = 0x2800 * RSDK.Cos256((angle >> 8) + 0xC0) + self->position.x;
42
player->position.y = self->position.y + ((self->playerAngles[playerID] - 74) << 16);
43
44
if (player->groundVel > 0 && Player_CheckCollisionTouch(player, self, &self->hitboxSlideStart)) {
45
self->activePlayers &= ~(1 << playerID);
46
player->state = Player_State_Roll;
47
player->collisionMode = CMODE_ROOF;
48
player->tileCollisions = TILECOLLISION_DOWN;
49
player->angle = 144;
50
}
51
}
52
else if (!((1 << playerID) & self->activePlayers) && player->onGround && player->groundVel < 0) {
53
if (Player_CheckCollisionTouch(player, self, &self->hitboxSlideStart)) {
54
player->tileCollisions = TILECOLLISION_NONE;
55
player->state = Player_State_Static;
56
player->velocity.x = 0;
57
player->velocity.y = 0;
58
RSDK.SetSpriteAnimation(player->aniFrames, ANI_JUMP, &player->animator, false, 0);
59
self->playerAngles[playerID] = (player->position.y - self->position.y + 0x4A0000) >> 16;
60
self->activePlayers |= (1 << playerID);
61
}
62
}
63
break;
64
65
case TWISTINGSLIDE_STRIP:
66
if (player->state == Player_State_Static) {
67
if (!((1 << playerID) & self->activePlayers)) {
68
self->playerAngles[playerID] = (0xC00000 + player->position.y - self->position.y) >> 16;
69
self->activePlayers |= 1 << playerID;
70
}
71
player->position.x = 0x800000 + self->position.x - 0xAA00 * self->playerAngles[playerID];
72
player->position.y = self->position.y + ((self->playerAngles[playerID] - 0xC0) << 16);
73
}
74
break;
75
76
case TWISTINGSLIDE_TWIST:
77
if (player->state == Player_State_Static) {
78
if (!((1 << playerID) & self->activePlayers)) {
79
self->playerAngles[playerID] = (0xC00000 + player->position.y - self->position.y) >> 16;
80
self->activePlayers |= 1 << playerID;
81
}
82
player->position.x = self->position.x + 0x2800 * RSDK.Cos256(((170 * self->playerAngles[playerID]) >> 8) + 0x40);
83
player->position.y = self->position.y + ((self->playerAngles[playerID] - 0xC0) << 16);
84
}
85
break;
86
87
case TWISTINGSLIDE_END:
88
if (player->state == Player_State_Static) {
89
if (!((1 << playerID) & self->activePlayers)) {
90
self->playerAngles[playerID] = (player->position.y + (self->endLen << 15) - self->position.y) >> 16;
91
self->activePlayers |= 1 << playerID;
92
}
93
player->position.x = self->position.x + ((self->endLen / 3) << 16) - 0xAA00 * self->playerAngles[playerID];
94
player->position.y = self->position.y + (self->playerAngles[playerID] << 16) - (self->endLen << 15);
95
if (player->groundVel < 0 && Player_CheckCollisionTouch(player, self, &self->hitboxSlideEnd)) {
96
self->activePlayers &= ~(1 << playerID);
97
player->state = Player_State_Roll;
98
player->collisionMode = CMODE_RWALL;
99
player->tileCollisions = TILECOLLISION_DOWN;
100
player->angle = 216;
101
}
102
}
103
else if (!((1 << playerID) & self->activePlayers) && player->onGround && player->groundVel > 0
104
&& Player_CheckCollisionTouch(player, self, &self->hitboxSlideEnd)) {
105
player->tileCollisions = TILECOLLISION_NONE;
106
player->state = Player_State_Static;
107
player->velocity.x = 0;
108
player->velocity.y = 0;
109
RSDK.SetSpriteAnimation(player->aniFrames, ANI_JUMP, &player->animator, false, 0);
110
self->playerAngles[playerID] = (player->position.y + (self->endLen << 15) - self->position.y) >> 16;
111
self->activePlayers |= (1 << playerID);
112
}
113
break;
114
115
default: break;
116
}
117
}
118
else {
119
switch (self->type) {
120
case TWISTINGSLIDE_START:
121
if (player->state == Player_State_Static) {
122
if (!((1 << playerID) & self->activePlayers)) {
123
self->playerAngles[playerID] = (player->position.y - self->position.y + 0x4A0000) >> 16;
124
self->activePlayers |= 1 << playerID;
125
}
126
127
int32 angle = 221 * self->playerAngles[playerID];
128
if (221 * self->playerAngles[playerID] >= 0x3FC0)
129
angle = 170 * self->playerAngles[playerID];
130
131
player->position.x = self->position.x - 0x2800 * RSDK.Cos256((angle >> 8) + 0xC0);
132
player->position.y = self->position.y + ((self->playerAngles[playerID] - 74) << 16);
133
if (player->groundVel < 0 && Player_CheckCollisionTouch(player, self, &self->hitboxSlideStart)) {
134
self->activePlayers &= ~(1 << playerID);
135
player->state = Player_State_Roll;
136
player->collisionMode = CMODE_ROOF;
137
player->tileCollisions = TILECOLLISION_DOWN;
138
player->angle = 0x70;
139
}
140
}
141
else if (!((1 << playerID) & self->activePlayers) && player->onGround && player->groundVel > 0) {
142
if (Player_CheckCollisionTouch(player, self, &self->hitboxSlideStart)) {
143
player->tileCollisions = TILECOLLISION_NONE;
144
player->state = Player_State_Static;
145
player->velocity.x = 0;
146
player->velocity.y = 0;
147
RSDK.SetSpriteAnimation(player->aniFrames, ANI_JUMP, &player->animator, false, 0);
148
self->playerAngles[playerID] = (player->position.y - self->position.y + 0x4A0000) >> 16;
149
self->activePlayers |= 1 << playerID;
150
}
151
}
152
break;
153
154
case TWISTINGSLIDE_STRIP:
155
if (player->state == Player_State_Static) {
156
if (!((1 << playerID) & self->activePlayers)) {
157
self->playerAngles[playerID] = (0xC00000 + player->position.y - self->position.y) >> 16;
158
self->activePlayers |= 1 << playerID;
159
}
160
161
player->position.x = 0xAA00 * self->playerAngles[playerID] + self->position.x - 0x800000;
162
player->position.y = self->position.y + ((self->playerAngles[playerID] - 0xC0) << 16);
163
}
164
break;
165
166
case TWISTINGSLIDE_TWIST:
167
if (player->state == Player_State_Static) {
168
if (!((1 << playerID) & self->activePlayers)) {
169
self->playerAngles[playerID] = (0xC00000 + player->position.y - self->position.y) >> 16;
170
self->activePlayers |= 1 << playerID;
171
}
172
173
player->position.x = self->position.x - 0x2800 * RSDK.Cos256(((170 * self->playerAngles[playerID]) >> 8) + 0x40);
174
player->position.y = self->position.y + ((self->playerAngles[playerID] - 0xC0) << 16);
175
}
176
break;
177
178
case TWISTINGSLIDE_END:
179
if (player->state == Player_State_Static) {
180
if (!((1 << playerID) & self->activePlayers)) {
181
self->playerAngles[playerID] = (player->position.y + (self->endLen << 15) - self->position.y) >> 16;
182
self->activePlayers |= 1 << playerID;
183
}
184
185
player->position.x = self->position.x + 0xAA00 * self->playerAngles[playerID] - ((self->endLen / 3) << 16);
186
player->position.y = self->position.y + (self->playerAngles[playerID] << 16) - (self->endLen << 15);
187
188
if (player->groundVel > 0 && Player_CheckCollisionTouch(player, self, &self->hitboxSlideEnd)) {
189
self->activePlayers &= ~(1 << playerID);
190
player->state = Player_State_Roll;
191
player->collisionMode = CMODE_RWALL;
192
player->tileCollisions = TILECOLLISION_DOWN;
193
player->angle = 40;
194
}
195
}
196
else if (!((1 << playerID) & self->activePlayers) && player->onGround && player->groundVel < 0
197
&& Player_CheckCollisionTouch(player, self, &self->hitboxSlideEnd)) {
198
player->tileCollisions = TILECOLLISION_NONE;
199
player->state = Player_State_Static;
200
player->velocity.x = 0;
201
player->velocity.y = 0;
202
203
RSDK.SetSpriteAnimation(player->aniFrames, ANI_JUMP, &player->animator, false, 0);
204
self->playerAngles[playerID] = (player->position.y + (self->endLen << 15) - self->position.y) >> 16;
205
self->activePlayers |= 1 << playerID;
206
}
207
break;
208
209
default: break;
210
}
211
}
212
213
if (((1 << playerID) & self->activePlayers)) {
214
if (self->direction) {
215
self->playerAngles[playerID] += ((-player->groundVel >> 16) * RSDK.Sin256(40)) >> 8;
216
217
if (player->groundVel <= 0)
218
player->groundVel -= 20 * RSDK.Cos256(40);
219
else
220
player->groundVel -= 80 * RSDK.Cos256(40);
221
222
if (player->groundVel < -0x180000)
223
player->groundVel = -0x180000;
224
}
225
else {
226
self->playerAngles[playerID] += ((player->groundVel >> 16) * RSDK.Sin256(40)) >> 8;
227
228
if (player->groundVel <= 0)
229
player->groundVel += 20 * RSDK.Cos256(40);
230
else
231
player->groundVel += 80 * RSDK.Cos256(40);
232
233
if (player->groundVel > 0x180000)
234
player->groundVel = 0x180000;
235
}
236
237
if (player->characterID == ID_TAILS)
238
player->animator.speed = 120;
239
else
240
player->animator.speed = ((abs(player->groundVel) * 0xF0) / 0x60000) + 0x30;
241
242
if (player->animator.speed > 0xF0)
243
player->animator.speed = 0xF0;
244
245
int32 x = player->position.x - storeX;
246
int32 y = player->position.y - storeY;
247
if (player->position.x != storeX && y) {
248
if (player->groundVel <= 0) {
249
x = storeX - player->position.x;
250
y = storeY - player->position.y;
251
}
252
253
player->angle = RSDK.ATan2(x, y);
254
player->rotation = 2 * player->angle;
255
}
256
}
257
}
258
}
259
260
void TwistingSlide_LateUpdate(void) {}
261
262
void TwistingSlide_StaticUpdate(void) {}
263
264
void TwistingSlide_Draw(void) {}
265
266
void TwistingSlide_Create(void *data)
267
{
268
RSDK_THIS(TwistingSlide);
269
270
if (!SceneInfo->inEditor) {
271
self->active = ACTIVE_BOUNDS;
272
273
switch (self->type) {
274
case TWISTINGSLIDE_START:
275
self->updateRange.y = 0x780000;
276
self->updateRange.x = 0x800000;
277
self->minY = self->position.y - 0x4A0000;
278
self->maxY = self->position.y + 0x780000;
279
break;
280
281
case TWISTINGSLIDE_STRIP:
282
self->updateRange.x = 0xC00000;
283
self->updateRange.y = 0xC00000;
284
self->minY = self->position.y - 0xC00000;
285
self->maxY = self->position.y + 0xC00000;
286
break;
287
288
case TWISTINGSLIDE_TWIST:
289
self->updateRange.y = 0xC00000;
290
self->updateRange.x = 0x800000;
291
self->minY = self->position.y - 0xC00000;
292
self->maxY = self->position.y + 0xC00000;
293
break;
294
295
case TWISTINGSLIDE_END:
296
self->minY = self->position.y - (self->endLen << 15);
297
self->maxY = self->position.y + (self->endLen << 15);
298
self->updateRange.y = 0xC00000;
299
self->updateRange.x = 0x800000;
300
break;
301
302
default: break;
303
}
304
305
TwistingSlide_SetupHitboxes();
306
}
307
}
308
309
void TwistingSlide_StageLoad(void)
310
{
311
TwistingSlide->hitbox.left = -1;
312
TwistingSlide->hitbox.top = 1;
313
TwistingSlide->hitbox.right = 1;
314
TwistingSlide->hitbox.bottom = 1;
315
}
316
317
void TwistingSlide_SetupHitboxes(void)
318
{
319
RSDK_THIS(TwistingSlide);
320
321
switch (self->type) {
322
case TWISTINGSLIDE_START:
323
self->hitboxSlide.left = -56;
324
self->hitboxSlide.top = -120;
325
self->hitboxSlide.right = 52;
326
self->hitboxSlide.bottom = 120;
327
328
self->hitboxSlideStart.top = -46;
329
self->hitboxSlideStart.bottom = -38;
330
self->hitboxSlideStart.left = ((-40 * RSDK.Cos256(48)) >> 8) - 4;
331
self->hitboxSlideStart.right = ((-40 * RSDK.Cos256(48)) >> 8) + 4;
332
break;
333
334
case TWISTINGSLIDE_STRIP:
335
case TWISTINGSLIDE_TWIST:
336
self->hitboxSlide.left = -132;
337
self->hitboxSlide.top = -196;
338
self->hitboxSlide.right = 132;
339
self->hitboxSlide.bottom = 196;
340
break;
341
342
case TWISTINGSLIDE_END:
343
self->hitboxSlide.left = self->endLen / -3;
344
self->hitboxSlide.top = -(self->endLen >> 1);
345
self->hitboxSlide.right = self->endLen / 3;
346
self->hitboxSlide.bottom = self->endLen >> 1;
347
348
self->hitboxSlideEnd.left = self->hitboxSlide.right - 4;
349
self->hitboxSlideEnd.top = self->hitboxSlide.bottom - 4;
350
self->hitboxSlideEnd.right = self->hitboxSlide.right + 4;
351
self->hitboxSlideEnd.bottom = self->hitboxSlide.bottom + 4;
352
break;
353
354
default: break;
355
}
356
}
357
358
#if GAME_INCLUDE_EDITOR
359
void TwistingSlide_EditorDraw(void)
360
{
361
RSDK_THIS(TwistingSlide);
362
363
TwistingSlide_SetupHitboxes();
364
365
if (showGizmos()) {
366
DrawHelpers_DrawHitboxOutline(self->position.x, self->position.y, &self->hitboxSlideStart, self->direction, 0xFF0000);
367
DrawHelpers_DrawHitboxOutline(self->position.x, self->position.y, &self->hitboxSlide, self->direction, 0xFF0000);
368
DrawHelpers_DrawHitboxOutline(self->position.x, self->position.y, &self->hitboxSlideEnd, self->direction, 0xFF0000);
369
}
370
}
371
372
void TwistingSlide_EditorLoad(void)
373
{
374
375
RSDK_ACTIVE_VAR(TwistingSlide, type);
376
RSDK_ENUM_VAR("Start", TWISTINGSLIDE_START);
377
RSDK_ENUM_VAR("Long Strip", TWISTINGSLIDE_STRIP);
378
RSDK_ENUM_VAR("Twist", TWISTINGSLIDE_TWIST);
379
RSDK_ENUM_VAR("End", TWISTINGSLIDE_END);
380
381
RSDK_ACTIVE_VAR(TwistingSlide, direction);
382
RSDK_ENUM_VAR("No Flip", FLIP_NONE);
383
RSDK_ENUM_VAR("Flip X", FLIP_X);
384
}
385
#endif
386
387
void TwistingSlide_Serialize(void)
388
{
389
RSDK_EDITABLE_VAR(TwistingSlide, VAR_UINT8, type);
390
RSDK_EDITABLE_VAR(TwistingSlide, VAR_ENUM, endLen);
391
RSDK_EDITABLE_VAR(TwistingSlide, VAR_UINT8, direction);
392
}
393
394