Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/CPZ/SpeedBooster.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: SpeedBooster Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectSpeedBooster *SpeedBooster;
11
12
void SpeedBooster_Update(void)
13
{
14
RSDK_THIS(SpeedBooster);
15
16
StateMachine_Run(self->state);
17
18
for (int32 i = 0; i < PLAYER_COUNT; i++) {
19
if (self->playerTimer[i])
20
self->playerTimer[i]--;
21
}
22
}
23
24
void SpeedBooster_LateUpdate(void) {}
25
26
void SpeedBooster_StaticUpdate(void) {}
27
28
void SpeedBooster_Draw(void)
29
{
30
RSDK_THIS(SpeedBooster);
31
32
RSDK.DrawSprite(&self->animator, &self->drawPos, false);
33
}
34
35
void SpeedBooster_Create(void *data)
36
{
37
RSDK_THIS(SpeedBooster);
38
39
self->visible = true;
40
if (RSDK.CheckSceneFolder("SSZ1") || RSDK.CheckSceneFolder("SSZ2"))
41
self->drawGroup = Zone->playerDrawGroup[0];
42
else
43
self->drawGroup = Zone->objectDrawGroup[1];
44
45
self->drawPos = self->position;
46
self->updateRange.x = 0x400000;
47
self->updateRange.y = 0x400000;
48
49
if (data) {
50
self->active = ACTIVE_NORMAL;
51
self->drawFX = INK_ALPHA;
52
RSDK.SetSpriteAnimation(SpeedBooster->aniFrames, 1, &self->animator, true, 0);
53
self->state = SpeedBooster_State_SSZBullet;
54
}
55
else {
56
self->active = ACTIVE_BOUNDS;
57
if (!self->speed)
58
self->speed = RSDK.CheckSceneFolder("CPZ") ? 10 : 16;
59
self->groundVel = self->speed << 16;
60
61
RSDK.SetSpriteAnimation(SpeedBooster->aniFrames, 0, &self->animator, true, 0);
62
self->state = SpeedBooster_State_SpeedBooster;
63
}
64
}
65
66
void SpeedBooster_StageLoad(void)
67
{
68
if (RSDK.CheckSceneFolder("CPZ")) {
69
SpeedBooster->aniFrames = RSDK.LoadSpriteAnimation("CPZ/SpeedBooster.bin", SCOPE_STAGE);
70
71
SpeedBooster->hitbox.left = -16;
72
SpeedBooster->hitbox.top = -16;
73
SpeedBooster->hitbox.right = 16;
74
SpeedBooster->hitbox.bottom = 16;
75
76
SpeedBooster->sfxSpeedBooster = RSDK.GetSfx("Global/Spring.wav");
77
78
SpeedBooster->defaultState = SpeedBooster_State_SpeedBooster;
79
}
80
else if (RSDK.CheckSceneFolder("SSZ1") || RSDK.CheckSceneFolder("SSZ2")) {
81
if (RSDK.CheckSceneFolder("SSZ1"))
82
SpeedBooster->aniFrames = RSDK.LoadSpriteAnimation("SSZ1/SpeedBooster.bin", SCOPE_STAGE);
83
else
84
SpeedBooster->aniFrames = RSDK.LoadSpriteAnimation("SSZ2/SpeedBooster.bin", SCOPE_STAGE);
85
86
SpeedBooster->hitbox.left = -32;
87
SpeedBooster->hitbox.top = -16;
88
SpeedBooster->hitbox.right = 32;
89
SpeedBooster->hitbox.bottom = 0;
90
91
SpeedBooster->sfxSpeedBooster = RSDK.GetSfx("Stage/SpeedBooster.wav");
92
93
SpeedBooster->defaultState = SpeedBooster_State_SSZFire;
94
}
95
96
DEBUGMODE_ADD_OBJ(SpeedBooster);
97
}
98
99
void SpeedBooster_DebugSpawn(void)
100
{
101
RSDK_THIS(DebugMode);
102
103
CREATE_ENTITY(SpeedBooster, NULL, self->position.x, self->position.y);
104
}
105
106
void SpeedBooster_DebugDraw(void)
107
{
108
RSDK.SetSpriteAnimation(SpeedBooster->aniFrames, 0, &DebugMode->animator, true, 0);
109
RSDK.DrawSprite(&DebugMode->animator, NULL, false);
110
}
111
112
void SpeedBooster_State_SpeedBooster(void)
113
{
114
RSDK_THIS(SpeedBooster);
115
116
RSDK.ProcessAnimation(&self->animator);
117
118
SpeedBooster_HandleInteractions();
119
}
120
121
void SpeedBooster_HandleInteractions(void)
122
{
123
RSDK_THIS(SpeedBooster);
124
125
bool32 isSSZ = RSDK.CheckSceneFolder("SSZ1") || RSDK.CheckSceneFolder("SSZ2");
126
127
foreach_active(Player, player)
128
{
129
int32 playerID = RSDK.GetEntitySlot(player);
130
if (self->playerTimer[playerID] || player->animator.animationID == ANI_HURT
131
|| !Player_CheckCollisionTouch(player, self, &SpeedBooster->hitbox) || !player->onGround) {
132
self->playerPos[playerID] = player->position.x;
133
}
134
else {
135
self->velocity.x = 2 * (player->position.x < self->position.x) - 1;
136
self->state = SpeedBooster->defaultState;
137
self->animator.frameID = 0;
138
RSDK.PlaySfx(SpeedBooster->sfxSpeedBooster, false, 255);
139
self->active = ACTIVE_NORMAL;
140
141
bool32 flipFlag = isSSZ ? self->playerPos[playerID] <= self->position.x : !self->direction;
142
if (flipFlag) {
143
if (player->groundVel < self->groundVel)
144
player->groundVel = self->groundVel;
145
player->direction = FLIP_NONE;
146
}
147
else {
148
if (player->groundVel > -self->groundVel)
149
player->groundVel = -self->groundVel;
150
player->direction = FLIP_X;
151
}
152
153
self->playerTimer[playerID] = 30;
154
player->controlLock = 16;
155
player->pushing = false;
156
player->tileCollisions = TILECOLLISION_DOWN;
157
if (player->state != Player_State_Roll)
158
player->state = Player_State_Ground;
159
self->playerPos[playerID] = player->position.x;
160
}
161
}
162
}
163
164
void SpeedBooster_State_SSZFire(void)
165
{
166
RSDK_THIS(SpeedBooster);
167
168
self->velocity.x = 0x55550 * self->velocity.x;
169
self->drawPos.x = self->position.x;
170
self->drawPos.y = self->position.y;
171
172
EntitySpeedBooster *child = CREATE_ENTITY(SpeedBooster, INT_TO_VOID(true), self->position.x, self->position.y);
173
int32 newVel = 0x10000;
174
child->velocity.y = -0x70000;
175
if (self->velocity.x > 0)
176
newVel = -0x10000;
177
child->velocity.x = newVel;
178
self->active = ACTIVE_NORMAL;
179
self->timer = 6;
180
self->drawPos.x -= self->velocity.x;
181
if (!--self->timer) {
182
self->timer = 6;
183
self->state = SpeedBooster_State_SSZRetract;
184
}
185
SpeedBooster_HandleInteractions();
186
187
self->state = SpeedBooster_State_SSZRecoil;
188
SpeedBooster_HandleInteractions(); // why is this called a second time?
189
}
190
191
void SpeedBooster_State_SSZRecoil(void)
192
{
193
RSDK_THIS(SpeedBooster);
194
195
self->drawPos.x -= self->velocity.x;
196
if (!--self->timer) {
197
self->timer = 6;
198
self->state = SpeedBooster_State_SSZRetract;
199
}
200
201
SpeedBooster_HandleInteractions();
202
}
203
204
void SpeedBooster_State_SSZRetract(void)
205
{
206
RSDK_THIS(SpeedBooster);
207
208
self->drawPos.x += self->velocity.x;
209
if (!--self->timer) {
210
self->active = ACTIVE_BOUNDS;
211
self->state = SpeedBooster_State_SpeedBooster;
212
}
213
214
SpeedBooster_HandleInteractions();
215
}
216
217
void SpeedBooster_State_SSZBullet(void)
218
{
219
RSDK_THIS(SpeedBooster);
220
221
self->position.x += self->velocity.x;
222
self->position.y += self->velocity.y;
223
self->rotation += 6;
224
self->velocity.y += 0x3800;
225
226
self->drawPos = self->position;
227
228
if (!RSDK.CheckOnScreen(self, &self->updateRange))
229
destroyEntity(self);
230
}
231
232
#if GAME_INCLUDE_EDITOR
233
void SpeedBooster_EditorDraw(void)
234
{
235
RSDK_THIS(SpeedBooster);
236
237
self->visible = true;
238
self->drawPos = self->position;
239
self->updateRange.x = 0x400000;
240
self->updateRange.y = 0x400000;
241
242
self->active = ACTIVE_BOUNDS;
243
if (!self->speed)
244
self->speed = RSDK.CheckSceneFolder("CPZ") ? 10 : 16;
245
self->groundVel = self->speed << 16;
246
247
RSDK.SetSpriteAnimation(SpeedBooster->aniFrames, 0, &self->animator, true, 0);
248
249
SpeedBooster_Draw();
250
}
251
252
void SpeedBooster_EditorLoad(void)
253
{
254
if (RSDK.CheckSceneFolder("CPZ")) {
255
SpeedBooster->aniFrames = RSDK.LoadSpriteAnimation("CPZ/SpeedBooster.bin", SCOPE_STAGE);
256
}
257
else if (RSDK.CheckSceneFolder("SSZ1") || RSDK.CheckSceneFolder("SSZ2")) {
258
if (RSDK.CheckSceneFolder("SSZ1"))
259
SpeedBooster->aniFrames = RSDK.LoadSpriteAnimation("SSZ1/SpeedBooster.bin", SCOPE_STAGE);
260
else
261
SpeedBooster->aniFrames = RSDK.LoadSpriteAnimation("SSZ2/SpeedBooster.bin", SCOPE_STAGE);
262
}
263
264
RSDK_ACTIVE_VAR(SpeedBooster, direction);
265
RSDK_ENUM_VAR("No Flip", FLIP_NONE);
266
RSDK_ENUM_VAR("Flipped", FLIP_X);
267
}
268
#endif
269
270
void SpeedBooster_Serialize(void)
271
{
272
RSDK_EDITABLE_VAR(SpeedBooster, VAR_UINT8, direction);
273
RSDK_EDITABLE_VAR(SpeedBooster, VAR_UINT8, speed);
274
}
275