Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/SPZ/Funnel.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: Funnel Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectFunnel *Funnel;
11
12
void Funnel_Update(void)
13
{
14
RSDK_THIS(Funnel);
15
16
for (int32 p = 0; p < Player->playerCount; ++p) {
17
if (!self->playerTimers[p]) {
18
EntityPlayer *player = RSDK_GET_ENTITY(p, Player);
19
20
if ((1 << p) & self->activePlayers) {
21
if (!Player_CheckValidState(player)) {
22
self->activePlayers &= ~(1 << p);
23
if (!self->activePlayers)
24
RSDK.StopSfx(Funnel->sfxFunnel);
25
}
26
else {
27
if (Player_CheckValidState(player) && player->state == Player_State_Static) {
28
if (player->sidekick == false && ++self->playerScoreTimer[p] >= 30) {
29
self->playerScoreTimer[p] = 0;
30
EntityScoreBonus *bonus = CREATE_ENTITY(ScoreBonus, NULL, self->position.x, self->position.y - 0x180000);
31
bonus->drawGroup = Zone->objectDrawGroup[1];
32
bonus->animator.frameID = 0;
33
Player_GiveScore(player, 100);
34
}
35
36
self->playerYVel[p] += 64 + (self->playerYVel[p] >> 8);
37
38
int32 distX = MAX(((self->position.y - player->position.y) >> 8) - 0xA00, 0x400);
39
40
player->position.x = distX * RSDK.Cos256(self->playerAngle[p]) + self->position.x;
41
self->playerAngle[p] -= self->playerXVel[p] >> 16;
42
43
if (self->playerXVel[p] <= 0)
44
self->playerXVel[p] = self->playerXVel[p] - self->playerYVel[p] - 128;
45
else
46
self->playerXVel[p] = self->playerXVel[p] + self->playerYVel[p] + 128;
47
48
if (player->position.y >= self->position.y) {
49
player->scale.x = 0x200;
50
player->scale.y = 0x200;
51
}
52
else {
53
player->drawFX |= FX_SCALE;
54
player->scale.x = ((((player->position.y - self->position.y) >> 16) * RSDK.Sin256(self->playerAngle[p])) >> 7) + 0x200;
55
player->scale.y = player->scale.x;
56
}
57
58
player->velocity.y += (self->playerYVel[p] >> 5) + 64;
59
if (player->position.y > self->position.y + 0x140000) {
60
self->activePlayers &= ~(1 << p);
61
player->drawFX &= ~FX_SCALE;
62
player->interaction = true;
63
player->tileCollisions = TILECOLLISION_DOWN;
64
player->scale.x = 0x200;
65
player->scale.y = 0x200;
66
player->position.x = self->position.x;
67
player->velocity.x = 0;
68
self->playerTimers[p] = 32;
69
70
if (player->camera)
71
player->scrollDelay = 1;
72
73
if (!self->activePlayers)
74
RSDK.StopSfx(Funnel->sfxFunnel);
75
76
Camera->centerBounds.y = 0x20000;
77
player->state = Player_State_Air;
78
}
79
}
80
else {
81
self->activePlayers &= ~(1 << p);
82
player->drawFX &= ~FX_SCALE;
83
player->interaction = true;
84
player->tileCollisions = TILECOLLISION_DOWN;
85
player->scale.x = 0x200;
86
player->scale.y = 0x200;
87
player->position.x = self->position.x;
88
player->velocity.x = 0;
89
self->playerTimers[p] = 32;
90
91
if (player->camera)
92
player->scrollDelay = 1;
93
94
if (!self->activePlayers)
95
RSDK.StopSfx(Funnel->sfxFunnel);
96
97
Camera->centerBounds.y = 0x20000;
98
player->state = Player_State_Air;
99
}
100
}
101
}
102
else {
103
if (Player_CheckValidState(player) && Player_CheckCollisionTouch(player, self, &Funnel->hitboxFunnel)) {
104
105
int32 dy = 0;
106
int32 distY = (self->position.y - player->position.y) >> 16;
107
if (distY - 10 >= 0)
108
dy = distY - 10;
109
110
int32 distX = abs(player->position.x - self->position.x) >> 16;
111
if ((distX <= dy && player->position.y < self->position.y) || (player->position.y < self->position.y - 0x280000 && distX <= 64)) {
112
if (player->camera) {
113
player->scrollDelay = 0;
114
Camera_SetupLerp(CAMERA_LERP_SIN1024_2, p, self->position.x, self->position.y - 0x400000, 8);
115
}
116
117
if (abs(player->velocity.y) > abs(player->velocity.x)) {
118
if (player->position.x >= self->position.x)
119
player->velocity.x -= (player->velocity.y >> 1);
120
else
121
player->velocity.x += (player->velocity.y >> 1);
122
123
player->velocity.y >>= 2;
124
}
125
126
self->playerXVel[p] = CLAMP(player->velocity.x, -0x100000, 0x100000);
127
128
int32 x = ((player->position.x - self->position.x) >> 16) * ((player->position.x - self->position.x) >> 16);
129
int32 y = dy * dy - x;
130
if (player->position.x < self->position.x)
131
x = -x;
132
133
self->playerAngle[p] = RSDK.ATan2(x, y);
134
135
player->velocity.y -= abs(9 * (player->velocity.x >> 4));
136
player->velocity.y = CLAMP(player->velocity.y, 0x1000, 0x10000);
137
138
#if MANIA_USE_PLUS
139
if (player->state == Player_State_MightyHammerDrop)
140
player->velocity.y = 0x80000;
141
else
142
#endif
143
RSDK.PlaySfx(Funnel->sfxFunnel, false, 0xFF);
144
145
player->velocity.x = 0;
146
self->playerScoreTimer[p] = 0;
147
self->playerYVel[p] = 0;
148
self->activePlayers |= 1 << p;
149
RSDK.SetSpriteAnimation(player->aniFrames, ANI_JUMP, &player->animator, false, 0);
150
151
player->interaction = false;
152
player->tileCollisions = TILECOLLISION_NONE;
153
player->state = Player_State_Static;
154
player->nextGroundState = StateMachine_None;
155
player->nextAirState = StateMachine_None;
156
}
157
else if (player->velocity.y <= 0x10000) {
158
int32 max = 0;
159
if (player->position.y >= self->position.y) {
160
max = 28;
161
}
162
else {
163
max = 0;
164
if (distY >= 0)
165
max = (self->position.y - player->position.y) >> 16;
166
max += 40;
167
}
168
169
if (distX < max) {
170
int32 x = RSDK.Rand(0x20000, MAX(abs(player->velocity.y + player->velocity.x) >> 8, 0x4000));
171
int32 y = x;
172
if (player->position.y >= self->position.y + 0x160000) {
173
x = player->velocity.x;
174
}
175
else {
176
if (player->position.y < self->position.y && player->velocity.y > 0)
177
continue;
178
179
if (player->position.x >= self->position.x) {
180
if (player->velocity.x > 0 && player->position.y >= self->position.y)
181
continue;
182
}
183
else {
184
if (player->velocity.x < 0 && player->position.y >= self->position.y)
185
continue;
186
x = -x;
187
}
188
}
189
190
if (player->position.y < self->position.y || player->position.y > self->position.y + 0x160000) {
191
if (player->velocity.y > 0)
192
continue;
193
}
194
else {
195
y = player->velocity.y;
196
}
197
198
if (player->animator.animationID != ANI_FLY) {
199
player->velocity.x = x;
200
player->groundVel = x;
201
}
202
203
player->velocity.y = y;
204
player->onGround = false;
205
player->applyJumpCap = false;
206
RSDK.PlaySfx(Funnel->sfxPimPom, false, 0xFF);
207
}
208
}
209
else {
210
int32 max = 0;
211
if (player->position.y >= self->position.y) {
212
max = 28;
213
}
214
else {
215
max = 0;
216
if (distY >= 0)
217
max = (self->position.y - player->position.y) >> 16;
218
max += 40;
219
}
220
221
if (distX < max) {
222
int32 x = RSDK.Rand(0x20000, MAX(abs(player->velocity.y + player->velocity.x) >> 8, 0x4000));
223
int32 y = x;
224
if (player->position.y >= self->position.y + 0x160000) {
225
x = player->velocity.x;
226
x = -x;
227
}
228
else {
229
if (player->position.y < self->position.y && player->velocity.y > 0)
230
continue;
231
else if (player->position.x < self->position.x) {
232
if (player->velocity.x < 0 && player->position.y >= self->position.y)
233
continue;
234
}
235
else if (player->velocity.x > 0 && player->position.y >= self->position.y)
236
continue;
237
else
238
x = -x;
239
}
240
241
if (player->position.y < self->position.y || player->position.y > self->position.y + 0x160000) {
242
if (player->velocity.y > 0)
243
continue;
244
y = -y;
245
}
246
else {
247
y = player->velocity.y;
248
}
249
250
if (player->animator.animationID != ANI_FLY) {
251
player->velocity.x = x;
252
player->groundVel = x;
253
}
254
255
player->velocity.y = y;
256
player->onGround = false;
257
player->applyJumpCap = false;
258
RSDK.PlaySfx(Funnel->sfxPimPom, false, 0xFF);
259
}
260
}
261
}
262
}
263
}
264
else {
265
self->playerTimers[p]--;
266
}
267
}
268
}
269
270
void Funnel_LateUpdate(void) {}
271
272
void Funnel_StaticUpdate(void)
273
{
274
foreach_all(Funnel, funnel) { RSDK.AddDrawListRef(Zone->objectDrawGroup[0], RSDK.GetEntitySlot(funnel)); }
275
}
276
277
void Funnel_Draw(void)
278
{
279
RSDK_THIS(Funnel);
280
281
self->animator.frameID = SceneInfo->currentDrawGroup == self->drawGroup;
282
RSDK.DrawSprite(&self->animator, NULL, false);
283
}
284
285
void Funnel_Create(void *data)
286
{
287
RSDK_THIS(Funnel);
288
289
RSDK.SetSpriteAnimation(Funnel->aniFrames, 0, &self->animator, true, 0);
290
291
if (!SceneInfo->inEditor) {
292
self->active = ACTIVE_BOUNDS;
293
self->updateRange.x = 0x1000000;
294
self->updateRange.y = 0x1000000;
295
self->visible = true;
296
self->drawGroup = Zone->objectDrawGroup[1] + 1;
297
self->state = Funnel_State_None;
298
}
299
}
300
301
void Funnel_StageLoad(void)
302
{
303
Funnel->aniFrames = RSDK.LoadSpriteAnimation("SPZ2/Funnel.bin", SCOPE_STAGE);
304
305
Funnel->hitboxFunnel.left = -64;
306
Funnel->hitboxFunnel.top = -48;
307
Funnel->hitboxFunnel.right = 64;
308
Funnel->hitboxFunnel.bottom = 0;
309
310
Funnel->active = ACTIVE_ALWAYS;
311
312
Funnel->sfxFunnel = RSDK.GetSfx("SPZ/Funnel.wav");
313
Funnel->sfxPimPom = RSDK.GetSfx("Stage/PimPom.wav");
314
}
315
316
void Funnel_State_None(void)
317
{
318
// this is never used actually LOL
319
}
320
321
#if GAME_INCLUDE_EDITOR
322
void Funnel_EditorDraw(void)
323
{
324
RSDK_THIS(Funnel);
325
326
self->animator.frameID = 1;
327
RSDK.DrawSprite(&self->animator, NULL, false);
328
329
self->animator.frameID = 0;
330
RSDK.DrawSprite(&self->animator, NULL, false);
331
}
332
333
void Funnel_EditorLoad(void) { Funnel->aniFrames = RSDK.LoadSpriteAnimation("SPZ2/Funnel.bin", SCOPE_STAGE); }
334
#endif
335
336
void Funnel_Serialize(void) {}
337
338