Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/SPZ/CircleBumper.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: CircleBumper Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectCircleBumper *CircleBumper;
11
12
void CircleBumper_Update(void)
13
{
14
RSDK_THIS(CircleBumper);
15
16
StateMachine_Run(self->stateMove);
17
18
StateMachine_Run(self->stateCollide);
19
}
20
21
void CircleBumper_LateUpdate(void) {}
22
23
void CircleBumper_StaticUpdate(void) {}
24
25
void CircleBumper_Draw(void)
26
{
27
RSDK_THIS(CircleBumper);
28
29
RSDK.DrawSprite(&self->animator, &self->drawPos, false);
30
}
31
32
void CircleBumper_Create(void *data)
33
{
34
RSDK_THIS(CircleBumper);
35
36
self->visible = true;
37
self->drawGroup = Zone->objectDrawGroup[1];
38
self->drawPos = self->position;
39
self->active = ACTIVE_BOUNDS;
40
self->amplitude.x >>= 10;
41
self->amplitude.y >>= 10;
42
43
switch (self->type) {
44
default:
45
case CIRCLEBUMPER_FIXED:
46
self->updateRange.x = 0x400000;
47
self->updateRange.y = 0x400000;
48
RSDK.SetSpriteAnimation(CircleBumper->aniFrames, 0, &self->animator, true, 0);
49
self->stateMove = CircleBumper_Move_Fixed;
50
break;
51
52
case CIRCLEBUMPER_LINEAR:
53
self->updateRange.x = (abs(self->amplitude.x) + 0x1000) << 10;
54
self->updateRange.y = (abs(self->amplitude.y) + 0x1000) << 10;
55
self->stateMove = CircleBumper_Move_Linear;
56
break;
57
58
case CIRCLEBUMPER_CIRCLE:
59
self->updateRange.x = (abs(self->amplitude.x) + 0x1000) << 10;
60
self->updateRange.y = (abs(self->amplitude.y) + 0x1000) << 10;
61
RSDK.SetSpriteAnimation(CircleBumper->aniFrames, 0, &self->animator, true, 0);
62
self->stateMove = CircleBumper_Move_Circular;
63
break;
64
65
case CIRCLEBUMPER_TRACK:
66
self->updateRange.x = (abs(self->amplitude.x) + 0x2000) << 9;
67
self->updateRange.y = (abs(self->amplitude.y) + 0x2000) << 9;
68
self->stateMove = CircleBumper_Move_Track;
69
break;
70
71
case CIRCLEBUMPER_PATH:
72
self->updateRange.x = 0x400000;
73
self->updateRange.y = 0x400000;
74
self->active = ACTIVE_NEVER;
75
self->stateMove = CircleBumper_Move_Path;
76
break;
77
}
78
79
RSDK.SetSpriteAnimation(CircleBumper->aniFrames, 0, &self->animator, true, 0);
80
self->stateCollide = CircleBumper_Collide_Normal;
81
if (!self->hitCount)
82
self->hitCount = 5;
83
}
84
85
void CircleBumper_StageLoad(void)
86
{
87
if (RSDK.CheckSceneFolder("SPZ1"))
88
CircleBumper->aniFrames = RSDK.LoadSpriteAnimation("SPZ1/CircleBumper.bin", SCOPE_STAGE);
89
else if (RSDK.CheckSceneFolder("SPZ2"))
90
CircleBumper->aniFrames = RSDK.LoadSpriteAnimation("SPZ2/CircleBumper.bin", SCOPE_STAGE);
91
else if (RSDK.CheckSceneFolder("Blueprint"))
92
CircleBumper->aniFrames = RSDK.LoadSpriteAnimation("Blueprint/CircleBumper.bin", SCOPE_STAGE);
93
94
CircleBumper->hitboxBumper.left = -7;
95
CircleBumper->hitboxBumper.top = -6;
96
CircleBumper->hitboxBumper.right = 7;
97
CircleBumper->hitboxBumper.bottom = 6;
98
99
CircleBumper->sfxBumper = RSDK.GetSfx("Stage/Bumper.wav");
100
101
DEBUGMODE_ADD_OBJ(CircleBumper);
102
}
103
104
void CircleBumper_DebugDraw(void)
105
{
106
RSDK.SetSpriteAnimation(CircleBumper->aniFrames, 0, &DebugMode->animator, true, 0);
107
RSDK.DrawSprite(&DebugMode->animator, NULL, false);
108
}
109
110
void CircleBumper_DebugSpawn(void)
111
{
112
RSDK_THIS(DebugMode);
113
114
CREATE_ENTITY(CircleBumper, NULL, self->position.x, self->position.y);
115
}
116
117
void CircleBumper_CheckPlayerCollisions(void)
118
{
119
RSDK_THIS(CircleBumper);
120
121
int32 storeX = self->position.x;
122
int32 storeY = self->position.y;
123
124
self->position.x = self->drawPos.x;
125
self->position.y = self->drawPos.y;
126
foreach_active(Player, player)
127
{
128
if (player->animator.animationID != ANI_HURT && Player_CheckBadnikTouch(player, self, &CircleBumper->hitboxBumper)) {
129
self->animator.frameID = 0;
130
self->stateCollide = CircleBumper_Collide_Bumped;
131
RSDK.PlaySfx(CircleBumper->sfxBumper, false, 0xFF);
132
self->active = ACTIVE_NORMAL;
133
134
int32 angle = RSDK.ATan2(player->position.x - self->position.x, player->position.y - self->position.y);
135
int32 xVel = 0x700 * RSDK.Cos256(angle);
136
int32 yVel = 0x700 * RSDK.Sin256(angle);
137
if (player->state == Player_State_FlyCarried)
138
RSDK_GET_ENTITY(SLOT_PLAYER2, Player)->flyCarryTimer = 30;
139
140
#if MANIA_USE_PLUS
141
if (player->state == Player_State_MightyHammerDrop) {
142
RSDK.SetSpriteAnimation(player->aniFrames, ANI_JUMP, &player->animator, false, 0);
143
}
144
else {
145
#endif
146
int32 anim = player->animator.animationID;
147
if (anim != ANI_FLY && anim != ANI_FLY_LIFT_TIRED && player->state != Player_State_TailsFlight) {
148
if (player->state != Player_State_DropDash)
149
player->state = Player_State_Air;
150
if (anim != ANI_JUMP && anim != ANI_JOG && anim != ANI_RUN && anim != ANI_DASH)
151
player->animator.animationID = ANI_WALK;
152
}
153
#if MANIA_USE_PLUS
154
}
155
#endif
156
if (player->animator.animationID != ANI_FLY) {
157
player->velocity.x = xVel;
158
player->groundVel = xVel;
159
player->applyJumpCap = false;
160
}
161
162
player->velocity.y = yVel;
163
player->onGround = false;
164
player->tileCollisions = TILECOLLISION_DOWN;
165
166
if (self->hitCount) {
167
EntityScoreBonus *bonus = CREATE_ENTITY(ScoreBonus, NULL, self->position.x, self->position.y);
168
bonus->animator.frameID = 16;
169
Player_GiveScore(player, 10);
170
--self->hitCount;
171
}
172
}
173
}
174
175
self->position.x = storeX;
176
self->position.y = storeY;
177
}
178
179
void CircleBumper_Collide_Normal(void) { CircleBumper_CheckPlayerCollisions(); }
180
181
void CircleBumper_Collide_Bumped(void)
182
{
183
RSDK_THIS(CircleBumper);
184
185
CircleBumper_CheckPlayerCollisions();
186
187
RSDK.ProcessAnimation(&self->animator);
188
189
if (self->animator.frameID == self->animator.frameCount - 1) {
190
self->animator.frameID = 0;
191
self->active = ACTIVE_BOUNDS;
192
self->stateCollide = CircleBumper_Collide_Normal;
193
}
194
}
195
196
void CircleBumper_Move_Fixed(void)
197
{
198
RSDK_THIS(CircleBumper);
199
200
self->drawPos.x = self->position.x;
201
self->drawPos.y = self->position.y;
202
}
203
204
void CircleBumper_Move_Linear(void)
205
{
206
RSDK_THIS(CircleBumper);
207
208
self->drawPos.x = self->position.x + self->amplitude.x * RSDK.Sin1024(self->speed * Zone->timer);
209
self->drawPos.y = self->position.y + self->amplitude.y * RSDK.Sin1024(self->speed * Zone->timer);
210
}
211
212
void CircleBumper_Move_Circular(void)
213
{
214
RSDK_THIS(CircleBumper);
215
216
self->drawPos.x = self->position.x + self->amplitude.x * RSDK.Cos1024(self->speed * Zone->timer + 4 * self->angle);
217
self->drawPos.y = self->position.y + self->amplitude.y * RSDK.Sin1024(self->speed * Zone->timer + 4 * self->angle);
218
}
219
220
void CircleBumper_Move_Path(void)
221
{
222
RSDK_THIS(CircleBumper);
223
224
self->drawPos.x += self->velocity.x;
225
self->drawPos.y += self->velocity.y;
226
Entity *node = RSDK_GET_ENTITY_GEN(self->speed);
227
228
if (self->velocity.x <= 0) {
229
if (self->drawPos.x < node->position.x)
230
self->drawPos.x = node->position.x;
231
}
232
else if (self->drawPos.x > node->position.x) {
233
self->drawPos.x = node->position.x;
234
}
235
236
if (self->velocity.y <= 0) {
237
if (self->drawPos.y < node->position.y)
238
self->drawPos.y = node->position.y;
239
}
240
else if (self->drawPos.y > node->position.y) {
241
self->drawPos.y = node->position.y;
242
}
243
}
244
245
void CircleBumper_Move_Track(void)
246
{
247
RSDK_THIS(CircleBumper);
248
249
int32 timer = Zone->timer << 7;
250
if (((timer >> 16) & 1) == self->direction) {
251
self->drawPos.x = self->position.x + (timer * self->amplitude.x >> 6) - (self->amplitude.x << 15);
252
self->drawPos.y = self->position.y + (timer * self->amplitude.y >> 6) - (self->amplitude.y << 15);
253
}
254
else {
255
self->drawPos.x = self->position.x + (self->amplitude.x << 15) - (timer * self->amplitude.x >> 6);
256
self->drawPos.y = self->position.y + (self->amplitude.y << 15) - (timer * self->amplitude.y >> 6);
257
}
258
}
259
260
#if GAME_INCLUDE_EDITOR
261
void CircleBumper_EditorDraw(void)
262
{
263
RSDK_THIS(CircleBumper);
264
265
Vector2 amplitude;
266
amplitude.x = self->amplitude.x >> 10;
267
amplitude.y = self->amplitude.y >> 10;
268
switch (self->type) {
269
default:
270
case CIRCLEBUMPER_FIXED:
271
self->updateRange.x = 0x400000;
272
self->updateRange.y = 0x400000;
273
break;
274
275
case CIRCLEBUMPER_LINEAR:
276
self->updateRange.x = (abs(amplitude.x) + 0x1000) << 10;
277
self->updateRange.y = (abs(amplitude.y) + 0x1000) << 10;
278
break;
279
280
case CIRCLEBUMPER_CIRCLE:
281
self->updateRange.x = (abs(amplitude.x) + 0x1000) << 10;
282
self->updateRange.y = (abs(amplitude.y) + 0x1000) << 10;
283
break;
284
285
case CIRCLEBUMPER_TRACK:
286
self->updateRange.x = (abs(amplitude.x) + 0x2000) << 9;
287
self->updateRange.y = (abs(amplitude.y) + 0x2000) << 9;
288
break;
289
290
case CIRCLEBUMPER_PATH:
291
self->updateRange.x = 0x400000;
292
self->updateRange.y = 0x400000;
293
break;
294
}
295
296
RSDK.SetSpriteAnimation(CircleBumper->aniFrames, 0, &self->animator, true, 0);
297
self->drawPos = self->position;
298
299
CircleBumper_Draw();
300
301
if (showGizmos()) {
302
RSDK_DRAWING_OVERLAY(true);
303
304
Vector2 pos;
305
switch (self->type) {
306
case CIRCLEBUMPER_LINEAR:
307
self->updateRange.x = (abs(amplitude.x) + 0x1000) << 10;
308
self->updateRange.y = (abs(amplitude.y) + 0x1000) << 10;
309
310
// draw distance previews
311
self->inkEffect = INK_BLEND;
312
self->drawPos.x = amplitude.x * RSDK.Sin1024(0x100) + self->position.x;
313
self->drawPos.y = amplitude.y * RSDK.Sin1024(0x100) + self->position.y;
314
pos = self->drawPos;
315
CircleBumper_Draw();
316
317
self->drawPos.x = amplitude.x * RSDK.Sin1024(0x300) + self->position.x;
318
self->drawPos.y = amplitude.y * RSDK.Sin1024(0x300) + self->position.y;
319
CircleBumper_Draw();
320
321
RSDK.DrawLine(pos.x, pos.y, self->drawPos.x, self->drawPos.y, 0x00FF00, 0, INK_NONE, false);
322
break;
323
324
case CIRCLEBUMPER_CIRCLE:
325
self->updateRange.x = (abs(amplitude.x) + 0x1000) << 10;
326
self->updateRange.y = (abs(amplitude.y) + 0x1000) << 10;
327
328
// draw distance preview
329
self->inkEffect = INK_BLEND;
330
self->drawPos.x = amplitude.x * RSDK.Cos1024(4 * self->angle) + self->position.x;
331
self->drawPos.y = amplitude.y * RSDK.Sin1024(4 * self->angle) + self->position.y;
332
333
CircleBumper_Draw();
334
break;
335
336
case CIRCLEBUMPER_TRACK:
337
self->updateRange.x = (abs(amplitude.x) + 0x2000) << 9;
338
self->updateRange.y = (abs(amplitude.y) + 0x2000) << 9;
339
340
// draw distance preview
341
self->inkEffect = INK_BLEND;
342
343
// draw distance previews
344
self->inkEffect = INK_BLEND;
345
self->drawPos.x = self->position.x + (0x100 * amplitude.x >> 6) - (amplitude.x << 15);
346
self->drawPos.y = self->position.y + (0x100 * amplitude.y >> 6) - (amplitude.y << 15);
347
pos = self->drawPos;
348
CircleBumper_Draw();
349
350
self->drawPos.x = self->position.x + (amplitude.x << 15) - (0x000 * amplitude.x >> 6);
351
self->drawPos.y = self->position.y + (amplitude.y << 15) - (0x000 * amplitude.y >> 6);
352
CircleBumper_Draw();
353
354
RSDK.DrawLine(pos.x, pos.y, self->drawPos.x, self->drawPos.y, 0x00FF00, 0x00, INK_NONE, false);
355
break;
356
357
case CIRCLEBUMPER_PATH: {
358
Entity *target = RSDK_GET_ENTITY_GEN(self->speed);
359
360
if (target)
361
DrawHelpers_DrawArrow(self->position.x, self->position.y, target->position.x, target->position.y, 0x00FF00, INK_NONE, 0xFF);
362
break;
363
}
364
365
default:
366
case CIRCLEBUMPER_FIXED:
367
// nothin'
368
break;
369
}
370
371
self->inkEffect = INK_NONE;
372
RSDK_DRAWING_OVERLAY(false);
373
}
374
}
375
376
void CircleBumper_EditorLoad(void)
377
{
378
if (RSDK.CheckSceneFolder("SPZ1"))
379
CircleBumper->aniFrames = RSDK.LoadSpriteAnimation("SPZ1/CircleBumper.bin", SCOPE_STAGE);
380
else if (RSDK.CheckSceneFolder("SPZ2"))
381
CircleBumper->aniFrames = RSDK.LoadSpriteAnimation("SPZ2/CircleBumper.bin", SCOPE_STAGE);
382
else if (RSDK.CheckSceneFolder("Blueprint"))
383
CircleBumper->aniFrames = RSDK.LoadSpriteAnimation("Blueprint/CircleBumper.bin", SCOPE_STAGE);
384
385
RSDK_ACTIVE_VAR(CircleBumper, type);
386
RSDK_ENUM_VAR("Fixed", CIRCLEBUMPER_FIXED);
387
RSDK_ENUM_VAR("Linear", CIRCLEBUMPER_LINEAR);
388
RSDK_ENUM_VAR("Circle", CIRCLEBUMPER_CIRCLE);
389
RSDK_ENUM_VAR("Track", CIRCLEBUMPER_TRACK);
390
RSDK_ENUM_VAR("Path", CIRCLEBUMPER_PATH);
391
}
392
#endif
393
394
void CircleBumper_Serialize(void)
395
{
396
RSDK_EDITABLE_VAR(CircleBumper, VAR_ENUM, hitCount);
397
RSDK_EDITABLE_VAR(CircleBumper, VAR_ENUM, type);
398
RSDK_EDITABLE_VAR(CircleBumper, VAR_VECTOR2, amplitude);
399
RSDK_EDITABLE_VAR(CircleBumper, VAR_ENUM, speed);
400
RSDK_EDITABLE_VAR(CircleBumper, VAR_INT32, angle);
401
}
402
403