Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/OOZ/GasPlatform.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: GasPlatform Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
ObjectGasPlatform *GasPlatform;
11
12
void GasPlatform_Update(void)
13
{
14
RSDK_THIS(GasPlatform);
15
16
if (self->state == Platform_State_Fixed) {
17
switch (self->type) {
18
case GASPLATFORM_INTERVAL:
19
if (!((Zone->timer + self->intervalOffset) % self->interval))
20
GasPlatform_PopPlatform();
21
break;
22
23
case GASPLATFORM_CONTACT: {
24
int32 playerID = 0;
25
foreach_active(Player, player)
26
{
27
if ((1 << playerID) & self->stoodPlayers && !player->sidekick) {
28
if (abs(player->position.x - self->position.x) < 0x40000) {
29
player->position.x = self->position.x;
30
player->state = Player_State_Static;
31
player->velocity.x = 0;
32
player->groundVel = 0;
33
34
GasPlatform_PopPlatform();
35
}
36
}
37
38
++playerID;
39
}
40
break;
41
}
42
}
43
}
44
45
Platform_Update();
46
}
47
48
void GasPlatform_LateUpdate(void) {}
49
50
void GasPlatform_StaticUpdate(void) {}
51
52
void GasPlatform_Draw(void)
53
{
54
RSDK_THIS(GasPlatform);
55
56
if (self->centerPos.y - self->drawPos.y > 0x180000)
57
RSDK.DrawSprite(&self->gasAnimator, NULL, false);
58
59
RSDK.DrawSprite(&self->animator, &self->drawPos, false);
60
}
61
62
void GasPlatform_Create(void *data)
63
{
64
RSDK_THIS(GasPlatform);
65
66
if (!self->interval)
67
self->interval = 1;
68
69
self->frameID = 2;
70
self->collision = PLATFORM_C_PLATFORM;
71
Platform_Create(NULL);
72
RSDK.SetSpriteAnimation(Platform->aniFrames, 2, &self->gasAnimator, true, 0);
73
74
self->stateCollide = Platform_Collision_Solid;
75
self->state = Platform_State_Fixed;
76
}
77
78
void GasPlatform_StageLoad(void)
79
{
80
GasPlatform->hitboxGas.top = -16;
81
GasPlatform->hitboxGas.left = -16;
82
GasPlatform->hitboxGas.right = 16;
83
GasPlatform->hitboxGas.bottom = 0;
84
85
GasPlatform->range.x = 0x800000;
86
GasPlatform->range.y = 0x180000;
87
88
GasPlatform->sfxGasPop = RSDK.GetSfx("OOZ/GasPop.wav");
89
GasPlatform->sfxSpring = RSDK.GetSfx("Global/Spring.wav");
90
}
91
92
void GasPlatform_PopPlatform(void)
93
{
94
RSDK_THIS(GasPlatform);
95
96
if (RSDK.CheckOnScreen(self, &GasPlatform->range))
97
RSDK.PlaySfx(GasPlatform->sfxGasPop, false, 255);
98
99
self->active = ACTIVE_NORMAL;
100
self->velocity.y = -0x96800;
101
self->state = GasPlatform_State_Popped;
102
}
103
104
void GasPlatform_State_Popped(void)
105
{
106
RSDK_THIS(GasPlatform);
107
108
self->drawPos.y += self->velocity.y;
109
110
if (self->drawPos.y >= self->centerPos.y) {
111
self->drawPos.y = self->centerPos.y;
112
if (self->velocity.y <= 0x10000) {
113
self->active = ACTIVE_BOUNDS;
114
self->state = Platform_State_Fixed;
115
return;
116
}
117
118
self->velocity.y = -(self->velocity.y >> 2);
119
}
120
else {
121
self->velocity.y += 0x3800;
122
}
123
124
if (self->centerPos.y - self->drawPos.y > 0x180000) {
125
RSDK.ProcessAnimation(&self->gasAnimator);
126
int32 storeX = self->position.x;
127
int32 storeY = self->position.y;
128
self->position.x = self->centerPos.x;
129
self->position.y = self->centerPos.y;
130
131
foreach_active(Player, player)
132
{
133
if (Player_CheckCollisionTouch(player, self, &GasPlatform->hitboxGas))
134
Player_ElementHurt(player, self, SHIELD_FIRE);
135
}
136
137
self->position.x = storeX;
138
self->position.y = storeY;
139
}
140
141
if (self->type == GASPLATFORM_CONTACT) {
142
int32 playerID = 0;
143
foreach_active(Player, player)
144
{
145
int32 launchY = self->centerPos.y - 0x780000;
146
147
if (self->position.y <= launchY) {
148
self->position.y = launchY;
149
if ((1 << playerID) & self->stoodPlayers) {
150
player->velocity.y = -0x100000;
151
player->state = Player_State_Air;
152
player->onGround = false;
153
RSDK.SetSpriteAnimation(player->aniFrames, ANI_SPRING_TWIRL, &player->animator, true, 0);
154
RSDK.PlaySfx(GasPlatform->sfxSpring, false, 255);
155
self->timer = 240;
156
self->state = GasPlatform_State_SpringCooldown;
157
}
158
}
159
else if ((1 << playerID) & self->stoodPlayers) {
160
if (abs(player->position.x - self->position.x) < 0x40000) {
161
player->position.x = self->position.x;
162
player->state = Player_State_Static;
163
player->velocity.x = 0;
164
player->groundVel = 0;
165
}
166
}
167
168
++playerID;
169
}
170
}
171
}
172
173
void GasPlatform_State_SpringCooldown(void)
174
{
175
RSDK_THIS(GasPlatform);
176
177
RSDK.ProcessAnimation(&self->gasAnimator);
178
179
int32 storeX = self->position.x;
180
int32 storeY = self->position.y;
181
182
self->position.x = self->centerPos.x;
183
self->position.y = self->centerPos.y;
184
foreach_active(Player, player)
185
{
186
if (Player_CheckCollisionTouch(player, self, &GasPlatform->hitboxGas))
187
Player_ElementHurt(player, self, SHIELD_FIRE);
188
}
189
190
self->position.x = storeX;
191
self->position.y = storeY;
192
193
if (!--self->timer) {
194
self->velocity.y = 0;
195
self->state = GasPlatform_State_Popped;
196
}
197
}
198
199
void GasPlatform_State_Shaking(void)
200
{
201
RSDK_THIS(GasPlatform);
202
203
self->drawPos.x = (RSDK.Rand(-1, 1) << 16) + self->centerPos.x;
204
self->drawPos.y = (RSDK.Rand(-2, 2) << 16) + self->centerPos.y;
205
206
if (self->timer <= 0) {
207
RSDK.PlaySfx(GasPlatform->sfxGasPop, false, 255);
208
self->active = ACTIVE_NORMAL;
209
self->velocity.y = -0x8C000;
210
self->state = GasPlatform_State_Popped;
211
}
212
else {
213
self->timer--;
214
}
215
}
216
217
#if GAME_INCLUDE_EDITOR
218
void GasPlatform_EditorDraw(void)
219
{
220
RSDK_THIS(GasPlatform);
221
222
self->drawPos = self->position;
223
224
GasPlatform_Draw();
225
}
226
227
void GasPlatform_EditorLoad(void)
228
{
229
RSDK_ACTIVE_VAR(GasPlatform, type);
230
RSDK_ENUM_VAR("Pop On Interval", GASPLATFORM_INTERVAL);
231
RSDK_ENUM_VAR("Pop On Contact", GASPLATFORM_CONTACT); // never used in mania afaik, it's used in S2 though
232
}
233
#endif
234
235
void GasPlatform_Serialize(void)
236
{
237
RSDK_EDITABLE_VAR(GasPlatform, VAR_ENUM, type);
238
RSDK_EDITABLE_VAR(GasPlatform, VAR_ENUM, childCount);
239
RSDK_EDITABLE_VAR(GasPlatform, VAR_UINT16, interval);
240
RSDK_EDITABLE_VAR(GasPlatform, VAR_UINT16, intervalOffset);
241
}
242
243