Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/CPZ/Staircase.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: Staircase Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectStaircase *Staircase;
11
12
void Staircase_Update(void)
13
{
14
RSDK_THIS(Staircase);
15
16
StateMachine_Run(self->state);
17
}
18
19
void Staircase_LateUpdate(void) {}
20
21
void Staircase_StaticUpdate(void) {}
22
23
void Staircase_Draw(void)
24
{
25
RSDK_THIS(Staircase);
26
27
StateMachine_Run(self->stateDraw);
28
}
29
30
void Staircase_Create(void *data)
31
{
32
RSDK_THIS(Staircase);
33
34
self->visible = true;
35
self->drawGroup = Zone->objectDrawGroup[0];
36
self->active = ACTIVE_BOUNDS;
37
self->updateRange.x = 0x1000000;
38
self->updateRange.y = 0x1000000;
39
40
// Why is a static value being initialized in Create?
41
Staircase->blockHitbox.top = -16;
42
Staircase->blockHitbox.left = -16;
43
Staircase->blockHitbox.bottom = 16;
44
Staircase->blockHitbox.right = 16;
45
46
int32 add = self->direction ? -0x200000 : 0x200000;
47
48
for (int32 i = 0; i < STAIRCASE_STAIR_COUNT; ++i) {
49
self->blockPos[i].x = self->position.x + i * add;
50
self->blockPos[i].y = self->position.y;
51
}
52
53
RSDK.SetSpriteAnimation(Staircase->aniFrames, 0, &self->animator, true, 0);
54
55
self->state = Staircase_State_Idle;
56
self->stateDraw = Staircase_Draw_Blocks;
57
}
58
59
void Staircase_StageLoad(void)
60
{
61
if (RSDK.CheckSceneFolder("CPZ")) {
62
Staircase->aniFrames = RSDK.LoadSpriteAnimation("CPZ/Staircase.bin", SCOPE_STAGE);
63
64
// What a name tbh
65
Staircase->sfxBlockStop = RSDK.GetSfx("CPZ/CPZ2HitBlocksStop.wav");
66
Soundboard_LoadSfx("CPZ/CPZ2HitBlocks.wav", true, Staircase_SfxCheck_HitBlocks, StateMachine_None);
67
}
68
}
69
70
bool32 Staircase_SfxCheck_HitBlocks(void)
71
{
72
foreach_active(Staircase, entity)
73
{
74
if (entity->stateDraw == Staircase_Draw_Shake)
75
return true;
76
}
77
78
return false;
79
}
80
81
void Staircase_State_Idle(void)
82
{
83
RSDK_THIS(Staircase);
84
85
Vector2 posStore = self->position;
86
foreach_active(Player, player)
87
{
88
for (int32 i = 0; i < STAIRCASE_STAIR_COUNT; i++) {
89
self->position = self->blockPos[i];
90
int32 side = Player_CheckCollisionBox(player, self, &Staircase->blockHitbox);
91
if (side == C_BOTTOM) {
92
// bumpable would prolly be used here :D
93
self->active = ACTIVE_NORMAL;
94
self->timer = 59;
95
self->state = Staircase_State_Wait;
96
self->stateDraw = Staircase_Draw_Shake;
97
if (player->onGround)
98
player->deathType = PLAYER_DEATH_DIE_USESFX;
99
}
100
else if (side == C_TOP) {
101
self->active = ACTIVE_NORMAL;
102
self->timer = 32;
103
self->state = Staircase_State_Wait;
104
}
105
}
106
}
107
108
self->position = posStore;
109
}
110
111
void Staircase_State_Wait(void)
112
{
113
RSDK_THIS(Staircase);
114
115
Vector2 posStore = self->position;
116
foreach_active(Player, player)
117
{
118
for (int32 i = 0; i < STAIRCASE_STAIR_COUNT; i++) {
119
self->position = self->blockPos[i];
120
Player_CheckCollisionBox(player, self, &Staircase->blockHitbox);
121
}
122
}
123
self->position = posStore;
124
125
if (--self->timer < 0) {
126
self->timer = 128;
127
if (!RSDK.IsSfxPlaying(Staircase->sfxBlockStop))
128
RSDK.PlaySfx(Staircase->sfxBlockStop, false, 255);
129
self->state = Staircase_State_MoveBlocks;
130
self->stateDraw = Staircase_Draw_Blocks;
131
}
132
133
if (!RSDK.CheckOnScreen(self, &self->updateRange))
134
Staircase_Create(NULL);
135
}
136
137
void Staircase_State_MoveBlocks(void)
138
{
139
RSDK_THIS(Staircase);
140
141
int32 add = self->type ? -0x4000 : 0x4000;
142
Vector2 posStore = self->position;
143
foreach_active(Player, player)
144
{
145
for (int32 i = 0; i < STAIRCASE_STAIR_COUNT; i++) {
146
self->position = self->blockPos[i];
147
if (Player_CheckCollisionBox(player, self, &Staircase->blockHitbox) == C_TOP)
148
player->position.y += add * (i + 1);
149
}
150
}
151
self->position = posStore;
152
153
for (int32 i = 0; i < STAIRCASE_STAIR_COUNT; ++i) self->blockPos[i].y += (i + 1) * add;
154
155
if (--self->timer <= 0)
156
self->state = Staircase_State_MovedBlocks;
157
158
if (!RSDK.CheckOnScreen(self, &self->updateRange))
159
Staircase_Create(NULL);
160
}
161
162
void Staircase_State_MovedBlocks(void)
163
{
164
RSDK_THIS(Staircase);
165
166
Vector2 posStore = self->position;
167
foreach_active(Player, player)
168
{
169
for (int32 i = 0; i < STAIRCASE_STAIR_COUNT; i++) {
170
self->position = self->blockPos[i];
171
if (Player_CheckCollisionBox(player, self, &Staircase->blockHitbox) == C_BOTTOM && player->onGround)
172
player->deathType = PLAYER_DEATH_DIE_USESFX;
173
}
174
}
175
self->position = posStore;
176
177
if (!RSDK.CheckOnScreen(self, &self->updateRange))
178
Staircase_Create(NULL);
179
}
180
181
void Staircase_Draw_Blocks(void)
182
{
183
RSDK_THIS(Staircase);
184
185
for (int32 i = 0; i < STAIRCASE_STAIR_COUNT; i++) {
186
RSDK.DrawSprite(&self->animator, &self->blockPos[i], false);
187
}
188
}
189
190
void Staircase_Draw_Shake(void)
191
{
192
RSDK_THIS(Staircase);
193
194
for (int32 i = 0; i < STAIRCASE_STAIR_COUNT; i++) {
195
Vector2 drawPos = self->blockPos[i];
196
drawPos.y += ((self->timer - i * STAIRCASE_STAIR_COUNT) << 14) & 0x10000;
197
RSDK.DrawSprite(&self->animator, &drawPos, false);
198
}
199
}
200
201
#if GAME_INCLUDE_EDITOR
202
void Staircase_EditorDraw(void)
203
{
204
RSDK_THIS(Staircase);
205
206
int32 addX = self->direction ? -0x200000 : 0x200000;
207
208
for (int32 i = 0; i < STAIRCASE_STAIR_COUNT; ++i) {
209
self->blockPos[i].x = self->position.x + i * addX;
210
self->blockPos[i].y = self->position.y;
211
}
212
213
Staircase_Draw_Blocks();
214
215
if (showGizmos()) {
216
RSDK_DRAWING_OVERLAY(true);
217
218
self->inkEffect = INK_BLEND;
219
220
int32 addY = self->type ? -0x200000 : 0x200000;
221
for (int32 i = 0; i < STAIRCASE_STAIR_COUNT; ++i) self->blockPos[i].y += (i + 1) * addY;
222
223
Staircase_Draw_Blocks();
224
225
self->inkEffect = INK_NONE;
226
227
RSDK_DRAWING_OVERLAY(false);
228
}
229
}
230
231
void Staircase_EditorLoad(void)
232
{
233
Staircase->aniFrames = RSDK.LoadSpriteAnimation("CPZ/Staircase.bin", SCOPE_STAGE);
234
235
RSDK_ACTIVE_VAR(Staircase, direction);
236
RSDK_ENUM_VAR("Right", FLIP_NONE);
237
RSDK_ENUM_VAR("Left", FLIP_X);
238
239
RSDK_ACTIVE_VAR(Staircase, type);
240
RSDK_ENUM_VAR("Down", STAIRCASE_DOWN);
241
RSDK_ENUM_VAR("Up", STAIRCASE_UP);
242
}
243
#endif
244
245
void Staircase_Serialize(void)
246
{
247
RSDK_EDITABLE_VAR(Staircase, VAR_UINT8, direction);
248
RSDK_EDITABLE_VAR(Staircase, VAR_UINT8, type);
249
// fun fact: why is this never used
250
RSDK_EDITABLE_VAR(Staircase, VAR_BOOL, bumpable);
251
}
252