Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/HPZ/Stegway.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: Stegway Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectStegway *Stegway = NULL;
11
12
void Stegway_Update(void)
13
{
14
RSDK_THIS(Stegway);
15
RSDK.ProcessAnimation(&self->mainAnimator);
16
RSDK.ProcessAnimation(&self->wheelAnimator);
17
if (self->showJet)
18
RSDK.ProcessAnimation(&self->jetAnimator);
19
20
StateMachine_Run(self->state);
21
22
Stegway_HandlePlayerInteractions();
23
if (self->state != Stegway_State_Init)
24
Stegway_CheckOffScreen();
25
}
26
27
void Stegway_LateUpdate(void) {}
28
29
void Stegway_StaticUpdate(void) {}
30
31
void Stegway_Draw(void)
32
{
33
RSDK_THIS(Stegway);
34
RSDK.DrawSprite(&self->mainAnimator, NULL, false);
35
RSDK.DrawSprite(&self->wheelAnimator, NULL, false);
36
if (self->showJet)
37
RSDK.DrawSprite(&self->jetAnimator, NULL, false);
38
}
39
40
void Stegway_Create(void *data)
41
{
42
RSDK_THIS(Stegway);
43
self->visible = true;
44
self->drawGroup = Zone->objectDrawGroup[0];
45
self->startPos = self->position;
46
self->startDir = self->direction;
47
self->drawFX = FX_FLIP;
48
self->active = ACTIVE_BOUNDS;
49
self->updateRange.x = 0x800000;
50
self->updateRange.y = 0x800000;
51
self->state = Stegway_State_Init;
52
}
53
54
void Stegway_StageLoad(void)
55
{
56
if (RSDK.CheckSceneFolder("HPZ"))
57
Stegway->aniFrames = RSDK.LoadSpriteAnimation("HPZ/Stegway.bin", SCOPE_STAGE);
58
59
Stegway->hitboxBadnik.left = -20;
60
Stegway->hitboxBadnik.top = -14;
61
Stegway->hitboxBadnik.right = 20;
62
Stegway->hitboxBadnik.bottom = 14;
63
64
Stegway->hitboxRange.left = -96;
65
Stegway->hitboxRange.top = -32;
66
Stegway->hitboxRange.right = 0;
67
Stegway->hitboxRange.bottom = 14;
68
69
Stegway->sfxRev = RSDK.GetSfx("Stage/Rev.wav");
70
Stegway->sfxRelease = RSDK.GetSfx("Global/Release.wav");
71
72
DEBUGMODE_ADD_OBJ(Stegway);
73
}
74
75
void Stegway_DebugSpawn(void)
76
{
77
RSDK_THIS(DebugMode);
78
79
EntityStegway *stegway = CREATE_ENTITY(Stegway, NULL, self->position.x, self->position.y);
80
stegway->direction = self->direction;
81
stegway->startDir = self->direction;
82
}
83
84
void Stegway_DebugDraw(void)
85
{
86
RSDK.SetSpriteAnimation(Stegway->aniFrames, 0, &DebugMode->animator, true, 0);
87
RSDK.DrawSprite(&DebugMode->animator, NULL, false);
88
}
89
90
void Stegway_CheckOffScreen(void)
91
{
92
RSDK_THIS(Stegway);
93
94
if (!RSDK.CheckOnScreen(self, NULL) && !RSDK.CheckPosOnScreen(&self->startPos, &self->updateRange)) {
95
self->direction = self->startDir;
96
self->position = self->startPos;
97
Stegway_Create(NULL);
98
}
99
}
100
101
void Stegway_HandlePlayerInteractions(void)
102
{
103
RSDK_THIS(Stegway);
104
foreach_active(Player, player)
105
{
106
if (Player_CheckBadnikTouch(player, self, &Stegway->hitboxBadnik))
107
Player_CheckBadnikBreak(player, self, true);
108
}
109
}
110
111
void Stegway_SetupAnims(char type, bool32 force)
112
{
113
RSDK_THIS(Stegway);
114
switch (type) {
115
case 0:
116
if (force || self->mainAnimator.animationID)
117
RSDK.SetSpriteAnimation(Stegway->aniFrames, 0, &self->mainAnimator, true, 0);
118
self->mainAnimator.speed = 1;
119
self->wheelAnimator.speed = 6;
120
break;
121
122
case 1:
123
if (force || self->mainAnimator.animationID != 1)
124
RSDK.SetSpriteAnimation(Stegway->aniFrames, 1, &self->mainAnimator, true, 0);
125
self->wheelAnimator.speed = 16;
126
break;
127
128
case 2:
129
if (force || self->mainAnimator.animationID)
130
RSDK.SetSpriteAnimation(Stegway->aniFrames, 0, &self->mainAnimator, true, 0);
131
if (self->mainAnimator.frameID == 2)
132
self->mainAnimator.frameID = 1;
133
self->mainAnimator.speed = 0;
134
self->wheelAnimator.speed = 24;
135
break;
136
137
case 3:
138
if (force || self->mainAnimator.animationID)
139
RSDK.SetSpriteAnimation(Stegway->aniFrames, 0, &self->mainAnimator, true, 0);
140
if (self->mainAnimator.frameID == 2)
141
self->mainAnimator.frameID = 1;
142
self->mainAnimator.speed = 0;
143
self->wheelAnimator.speed = 0;
144
break;
145
default: break;
146
}
147
}
148
149
void Stegway_State_Init(void)
150
{
151
RSDK_THIS(Stegway);
152
153
self->active = ACTIVE_NORMAL;
154
if (self->direction == FLIP_NONE)
155
self->velocity.x = -0x4000;
156
else
157
self->velocity.x = 0x4000;
158
RSDK.SetSpriteAnimation(Stegway->aniFrames, 2, &self->wheelAnimator, true, 0);
159
RSDK.SetSpriteAnimation(Stegway->aniFrames, 3, &self->jetAnimator, true, 0);
160
Stegway_SetupAnims(0, true);
161
self->state = Stegway_State_Moving;
162
Stegway_State_Moving();
163
}
164
165
void Stegway_State_Moving(void)
166
{
167
RSDK_THIS(Stegway);
168
169
self->position.x += self->velocity.x;
170
171
foreach_active(Player, player)
172
{
173
if (Player_CheckCollisionTouch(player, self, &Stegway->hitboxRange)) {
174
self->state = Stegway_State_RevUp;
175
Stegway_SetupAnims(3, false);
176
}
177
}
178
179
bool32 collided = false;
180
if (self->direction)
181
collided = RSDK.ObjectTileGrip(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0xC0000, 0x100000, 8);
182
else
183
collided = RSDK.ObjectTileGrip(self, Zone->collisionLayers, CMODE_FLOOR, 0, -0xC0000, 0x100000, 8);
184
185
if (!collided) {
186
self->state = Stegway_State_Turn;
187
Stegway_SetupAnims(3, false);
188
self->showJet = false;
189
self->noFloor = false;
190
}
191
Stegway_CheckOffScreen();
192
}
193
194
void Stegway_State_Turn(void)
195
{
196
RSDK_THIS(Stegway);
197
198
if (self->timer >= 29) {
199
self->timer = 0;
200
self->state = Stegway_State_Moving;
201
Stegway_SetupAnims(0, false);
202
203
self->direction ^= FLIP_X;
204
if (self->direction == FLIP_NONE)
205
self->velocity.x = -0x4000;
206
else
207
self->velocity.x = 0x4000;
208
}
209
else {
210
self->timer++;
211
}
212
}
213
214
void Stegway_State_RevUp(void)
215
{
216
RSDK_THIS(Stegway);
217
if (++self->timer == 8) {
218
self->timer = 0;
219
self->state = Stegway_State_RevRelease;
220
Stegway_SetupAnims(2, false);
221
RSDK.PlaySfx(Stegway->sfxRev, false, 255);
222
}
223
}
224
225
void Stegway_State_RevRelease(void)
226
{
227
RSDK_THIS(Stegway);
228
if (++self->timer == 32) {
229
self->timer = 0;
230
self->state = Stegway_State_Dash;
231
EntityDust *dust =
232
CREATE_ENTITY(Dust, self, self->position.x - 0xA0000 * (2 * (self->direction != FLIP_NONE) - 1), self->position.y + 0x100000);
233
RSDK.SetSpriteAnimation(Dust->aniFrames, 2, &dust->animator, true, 0);
234
dust->state = Dust_State_DustPuff;
235
dust->direction = FLIP_X - self->direction;
236
dust->drawGroup = self->drawGroup;
237
Stegway_SetupAnims(1, false);
238
self->showJet = true;
239
self->velocity.x *= 12;
240
RSDK.PlaySfx(Stegway->sfxRelease, false, 255);
241
}
242
}
243
244
void Stegway_State_Dash(void)
245
{
246
RSDK_THIS(Stegway);
247
248
self->position.x += self->velocity.x;
249
int32 dir = 2 * (self->direction != FLIP_NONE) - 1;
250
251
if (!self->noFloor) {
252
int32 storeX = self->position.x;
253
int32 storeY = self->position.y;
254
if (!RSDK.ObjectTileGrip(self, Zone->collisionLayers, CMODE_FLOOR, 0, dir << 22, 0x100000, 8))
255
self->noFloor = true;
256
self->position.x = storeX;
257
self->position.y = storeY;
258
}
259
260
bool32 collided = RSDK.ObjectTileGrip(self, Zone->collisionLayers, CMODE_FLOOR, 0, 0xC0000 * dir, 0x100000, 8);
261
262
if (self->noFloor) {
263
if (self->velocity.x * dir >= 0x4000) {
264
self->velocity.x -= 0xA00 * dir;
265
if (dir * self->velocity.x < 0x4000) {
266
self->velocity.x = dir << 14;
267
self->state = Stegway_State_Moving;
268
Stegway_SetupAnims(0, false);
269
self->mainAnimator.frameID = 0;
270
self->showJet = false;
271
self->noFloor = false;
272
}
273
}
274
}
275
276
if (!collided) {
277
self->state = Stegway_State_Turn;
278
Stegway_SetupAnims(3, false);
279
self->showJet = false;
280
self->noFloor = false;
281
}
282
}
283
284
#if GAME_INCLUDE_EDITOR
285
void Stegway_EditorDraw(void)
286
{
287
RSDK_THIS(Stegway);
288
RSDK.SetSpriteAnimation(Stegway->aniFrames, 2, &self->wheelAnimator, true, 0);
289
RSDK.SetSpriteAnimation(Stegway->aniFrames, 3, &self->jetAnimator, true, 0);
290
Stegway_SetupAnims(0, true);
291
292
Stegway_Draw();
293
}
294
295
void Stegway_EditorLoad(void)
296
{
297
Stegway->aniFrames = RSDK.LoadSpriteAnimation("HPZ/Stegway.bin", SCOPE_STAGE);
298
299
RSDK_ACTIVE_VAR(Stegway, direction);
300
RSDK_ENUM_VAR("No Flip", FLIP_NONE);
301
RSDK_ENUM_VAR("Flip X", FLIP_X);
302
}
303
#endif
304
305
void Stegway_Serialize(void) { RSDK_EDITABLE_VAR(Stegway, VAR_UINT8, direction); }
306
307